提交 dcdc934d 编写于 作者: V VSadov

Implements GetDeclaredSymbol for tuple literals and GetSymbolInfo for elements of tuple literals.

Fixes:#14600
Fixes:#11013
Fixes:#14116
Fixes:#16168
上级 fd61eb2d
......@@ -5,6 +5,7 @@
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Roslyn.Utilities;
using System.Collections.Immutable;
using Microsoft.CodeAnalysis.CSharp.Syntax;
namespace Microsoft.CodeAnalysis.CSharp
{
......@@ -353,12 +354,36 @@ private BoundExpression CreateTupleLiteralConversion(SyntaxNode syntax, BoundTup
if (targetType.IsTupleType)
{
var destTupleType = (TupleTypeSymbol)targetType;
// do not lose the original element names in the literal if different from names in the target
TupleTypeSymbol.ReportNamesMismatchesIfAny(targetType, sourceTuple, diagnostics);
// Come back to this, what about locations? (https://github.com/dotnet/roslyn/issues/11013)
targetType = destTupleType.WithElementNames(sourceTuple.ArgumentNamesOpt);
// do not lose the original element names and locatins in the literal if different from names in the target
//
// the tuple has changed the type of elements due to target-typing,
// but element names has not changed and locations of their declarations
// should not be confused with element locations on the target type.
var sourceType = sourceTuple.Type as TupleTypeSymbol;
if ((object)sourceType != null)
{
targetType = sourceType.WithUnderlyingType(destTupleType.UnderlyingNamedType);
}
else
{
var tupleSyntax = (TupleExpressionSyntax)sourceTuple.Syntax;
var locationBuilder = ArrayBuilder<Location>.GetInstance();
foreach (var argument in tupleSyntax.Arguments)
{
locationBuilder.Add(argument.NameColon?.Name.Location);
}
targetType = destTupleType.WithElementNames(sourceTuple.ArgumentNamesOpt,
tupleSyntax.Location,
locationBuilder.ToImmutableAndFree());
}
}
var arguments = sourceTuple.Arguments;
......
......@@ -1205,6 +1205,15 @@ public static INamedTypeSymbol GetDeclaredSymbol(this SemanticModel semanticMode
return csmodel?.GetDeclaredSymbol(declaratorSyntax, cancellationToken);
}
/// <summary>
/// Given a syntax node of tuple expression, get the tuple type symbol.
/// </summary>
public static INamedTypeSymbol GetDeclaredSymbol(this SemanticModel semanticModel, TupleExpressionSyntax declaratorSyntax, CancellationToken cancellationToken = default(CancellationToken))
{
var csmodel = semanticModel as CSharpSemanticModel;
return csmodel?.GetDeclaredSymbol(declaratorSyntax, cancellationToken);
}
/// <summary>
/// Given a syntax node that declares a property or member accessor, get the corresponding symbol.
/// </summary>
......
......@@ -2686,6 +2686,22 @@ internal Conversion ClassifyConversionForCast(int position, ExpressionSyntax exp
/// <returns>The symbol that was declared.</returns>
public abstract INamedTypeSymbol GetDeclaredSymbol(AnonymousObjectCreationExpressionSyntax declaratorSyntax, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Given a syntax node of a tuple expression, get the tuple type symbol.
/// </summary>
/// <param name="declaratorSyntax">The tuple expression node.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>The symbol that was declared.</returns>
public abstract INamedTypeSymbol GetDeclaredSymbol(TupleExpressionSyntax declaratorSyntax, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Given a syntax node of an argument expression, get the declared symbol.
/// </summary>
/// <param name="declaratorSyntax">The argument syntax node.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>The symbol that was declared.</returns>
public abstract ISymbol GetDeclaredSymbol(ArgumentSyntax declaratorSyntax, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Given a syntax node that declares a property or member accessor, get the corresponding
/// symbol.
......@@ -3963,7 +3979,17 @@ private SymbolInfo GetNamedArgumentSymbolInfo(IdentifierNameSyntax identifierNam
if (argumentName.Length == 0)
return SymbolInfo.None; // missing name.
CSharpSyntaxNode containingInvocation = identifierNameSyntax.Parent.Parent.Parent.Parent;
// argument could be an argument of a tuple expression
// var x = (Identifier: 1, AnotherIdentifier: 2);
var parent3 = identifierNameSyntax.Parent.Parent.Parent;
if (parent3.IsKind(SyntaxKind.TupleExpression))
{
var tupleArgument = (ArgumentSyntax)identifierNameSyntax.Parent.Parent;
var typleElement = GetDeclaredSymbol(tupleArgument, cancellationToken);
return (object)typleElement == null ? SymbolInfo.None : new SymbolInfo(typleElement, ImmutableArray<ISymbol>.Empty, CandidateReason.None);
}
CSharpSyntaxNode containingInvocation = parent3.Parent;
SymbolInfo containingInvocationInfo = GetSymbolInfoWorker(containingInvocation, SymbolInfoOptions.PreferConstructorsToType | SymbolInfoOptions.ResolveAliases, cancellationToken);
......@@ -4609,6 +4635,10 @@ protected sealed override ISymbol GetDeclaredSymbolCore(SyntaxNode declaration,
return this.GetDeclaredSymbol((AnonymousObjectCreationExpressionSyntax)node, cancellationToken);
case SyntaxKind.AnonymousObjectMemberDeclarator:
return this.GetDeclaredSymbol((AnonymousObjectMemberDeclaratorSyntax)node, cancellationToken);
case SyntaxKind.TupleExpression:
return this.GetDeclaredSymbol((TupleExpressionSyntax)node, cancellationToken);
case SyntaxKind.Argument:
return this.GetDeclaredSymbol((ArgumentSyntax)node, cancellationToken);
case SyntaxKind.VariableDeclarator:
return this.GetDeclaredSymbol((VariableDeclaratorSyntax)node, cancellationToken);
case SyntaxKind.SingleVariableDesignation:
......
......@@ -885,6 +885,47 @@ public override INamedTypeSymbol GetDeclaredSymbol(AnonymousObjectCreationExpres
return (bound == null) ? null : bound.Type as NamedTypeSymbol;
}
public override INamedTypeSymbol GetDeclaredSymbol(TupleExpressionSyntax declaratorSyntax, CancellationToken cancellationToken = default(CancellationToken))
{
CheckSyntaxNode(declaratorSyntax);
return GetTypeOfTupleLiteral(declaratorSyntax);
}
public override ISymbol GetDeclaredSymbol(ArgumentSyntax declaratorSyntax, CancellationToken cancellationToken = default(CancellationToken))
{
CheckSyntaxNode(declaratorSyntax);
var tupleLiteral = declaratorSyntax?.Parent as TupleExpressionSyntax;
// for now only arguments of a tuple literal may declare symbols
if (tupleLiteral == null)
{
return null;
}
var tupleLiteralType = GetTypeOfTupleLiteral(tupleLiteral);
if ((object)tupleLiteralType != null)
{
var elements = tupleLiteralType.TupleElements;
if(!elements.IsDefault)
{
var idx = tupleLiteral.Arguments.IndexOf(declaratorSyntax);
return elements[idx];
}
}
return null;
}
private NamedTypeSymbol GetTypeOfTupleLiteral(TupleExpressionSyntax declaratorSyntax)
{
var bound = this.GetLowerBoundNode(declaratorSyntax);
return (bound as BoundTupleExpression)?.Type as NamedTypeSymbol;
}
public override SyntaxTree SyntaxTree
{
get
......
......@@ -437,6 +437,20 @@ public override INamedTypeSymbol GetDeclaredSymbol(AnonymousObjectCreationExpres
return (model == null) ? null : model.GetDeclaredSymbol(declaratorSyntax, cancellationToken);
}
public override INamedTypeSymbol GetDeclaredSymbol(TupleExpressionSyntax declaratorSyntax, CancellationToken cancellationToken = default(CancellationToken))
{
CheckSyntaxNode(declaratorSyntax);
var model = this.GetMemberModel(declaratorSyntax);
return (model == null) ? null : model.GetDeclaredSymbol(declaratorSyntax, cancellationToken);
}
public override ISymbol GetDeclaredSymbol(ArgumentSyntax declaratorSyntax, CancellationToken cancellationToken = default(CancellationToken))
{
CheckSyntaxNode(declaratorSyntax);
var model = this.GetMemberModel(declaratorSyntax);
return (model == null) ? null : model.GetDeclaredSymbol(declaratorSyntax, cancellationToken);
}
public override IRangeVariableSymbol GetDeclaredSymbol(QueryClauseSyntax node, CancellationToken cancellationToken = default(CancellationToken))
{
CheckSyntaxNode(node);
......
......@@ -22,4 +22,5 @@
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "<Pending>", Scope = "member", Target = "~M:Microsoft.CodeAnalysis.CSharp.CSharpExtensions.GetDeclaredSymbol(Microsoft.CodeAnalysis.SemanticModel,Microsoft.CodeAnalysis.CSharp.Syntax.TupleElementSyntax,System.Threading.CancellationToken)~Microsoft.CodeAnalysis.ISymbol")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("ApiDesign", "RS0027:Public API with optional parameter(s) should have the most parameters amongst its public overloads.", Justification = "<Pending>", Scope = "member", Target = "~M:Microsoft.CodeAnalysis.CSharp.SyntaxFactory.ParenthesizedVariableComponent(Microsoft.CodeAnalysis.SeparatedSyntaxList{Microsoft.CodeAnalysis.CSharp.Syntax.VariableComponentSyntax})~Microsoft.CodeAnalysis.CSharp.Syntax.ParenthesizedVariableComponentSyntax")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("ApiDesign", "RS0027:Public API with optional parameter(s) should have the most parameters amongst its public overloads.", Justification = "<Pending>", Scope = "member", Target = "~M:Microsoft.CodeAnalysis.CSharp.SyntaxFactory.ParenthesizedVariableDesignation(Microsoft.CodeAnalysis.SeparatedSyntaxList{Microsoft.CodeAnalysis.CSharp.Syntax.VariableDesignationSyntax})~Microsoft.CodeAnalysis.CSharp.Syntax.ParenthesizedVariableDesignationSyntax")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "<Pending>", Scope = "member", Target = "~M:Microsoft.CodeAnalysis.CSharp.CSharpExtensions.GetDeclaredSymbol(Microsoft.CodeAnalysis.SemanticModel,Microsoft.CodeAnalysis.CSharp.Syntax.TupleExpressionSyntax,System.Threading.CancellationToken)~Microsoft.CodeAnalysis.INamedTypeSymbol")]
......@@ -129,8 +129,8 @@ Microsoft.CodeAnalysis.CSharp.Syntax.ThrowExpressionSyntax.WithThrowKeyword(Micr
Microsoft.CodeAnalysis.CSharp.Syntax.TupleElementSyntax
Microsoft.CodeAnalysis.CSharp.Syntax.TupleElementSyntax.Identifier.get -> Microsoft.CodeAnalysis.SyntaxToken
Microsoft.CodeAnalysis.CSharp.Syntax.TupleElementSyntax.Type.get -> Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax
Microsoft.CodeAnalysis.CSharp.Syntax.TupleElementSyntax.WithIdentifier(Microsoft.CodeAnalysis.SyntaxToken identifier) -> Microsoft.CodeAnalysis.CSharp.Syntax.TupleElementSyntax
Microsoft.CodeAnalysis.CSharp.Syntax.TupleElementSyntax.Update(Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax type, Microsoft.CodeAnalysis.SyntaxToken identifier) -> Microsoft.CodeAnalysis.CSharp.Syntax.TupleElementSyntax
Microsoft.CodeAnalysis.CSharp.Syntax.TupleElementSyntax.WithIdentifier(Microsoft.CodeAnalysis.SyntaxToken identifier) -> Microsoft.CodeAnalysis.CSharp.Syntax.TupleElementSyntax
Microsoft.CodeAnalysis.CSharp.Syntax.TupleElementSyntax.WithType(Microsoft.CodeAnalysis.CSharp.Syntax.TypeSyntax type) -> Microsoft.CodeAnalysis.CSharp.Syntax.TupleElementSyntax
Microsoft.CodeAnalysis.CSharp.Syntax.TupleExpressionSyntax
Microsoft.CodeAnalysis.CSharp.Syntax.TupleExpressionSyntax.AddArguments(params Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentSyntax[] items) -> Microsoft.CodeAnalysis.CSharp.Syntax.TupleExpressionSyntax
......@@ -256,6 +256,7 @@ override Microsoft.CodeAnalysis.CSharp.Syntax.WhenClauseSyntax.Accept(Microsoft.
override Microsoft.CodeAnalysis.CSharp.Syntax.WhenClauseSyntax.Accept<TResult>(Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor<TResult> visitor) -> TResult
static Microsoft.CodeAnalysis.CSharp.CSharpExtensions.GetDeclaredSymbol(this Microsoft.CodeAnalysis.SemanticModel semanticModel, Microsoft.CodeAnalysis.CSharp.Syntax.SingleVariableDesignationSyntax designationSyntax, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> Microsoft.CodeAnalysis.ISymbol
static Microsoft.CodeAnalysis.CSharp.CSharpExtensions.GetDeclaredSymbol(this Microsoft.CodeAnalysis.SemanticModel semanticModel, Microsoft.CodeAnalysis.CSharp.Syntax.TupleElementSyntax declarationSyntax, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> Microsoft.CodeAnalysis.ISymbol
static Microsoft.CodeAnalysis.CSharp.CSharpExtensions.GetDeclaredSymbol(this Microsoft.CodeAnalysis.SemanticModel semanticModel, Microsoft.CodeAnalysis.CSharp.Syntax.TupleExpressionSyntax declaratorSyntax, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> Microsoft.CodeAnalysis.INamedTypeSymbol
static Microsoft.CodeAnalysis.CSharp.CSharpExtensions.GetForEachStatementInfo(this Microsoft.CodeAnalysis.SemanticModel semanticModel, Microsoft.CodeAnalysis.CSharp.Syntax.CommonForEachStatementSyntax forEachStatement) -> Microsoft.CodeAnalysis.CSharp.ForEachStatementInfo
static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.AccessorDeclaration(Microsoft.CodeAnalysis.CSharp.SyntaxKind kind) -> Microsoft.CodeAnalysis.CSharp.Syntax.AccessorDeclarationSyntax
static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.AccessorDeclaration(Microsoft.CodeAnalysis.CSharp.SyntaxKind kind, Microsoft.CodeAnalysis.CSharp.Syntax.BlockSyntax body) -> Microsoft.CodeAnalysis.CSharp.Syntax.AccessorDeclarationSyntax
......
......@@ -217,23 +217,13 @@ internal TupleTypeSymbol WithUnderlyingType(NamedTypeSymbol newUnderlyingType)
/// <summary>
/// Copy this tuple, but modify it to use the new element names.
/// </summary>
internal TupleTypeSymbol WithElementNames(ImmutableArray<string> newElementNames)
internal TupleTypeSymbol WithElementNames(ImmutableArray<string> newElementNames,
Location location,
ImmutableArray<Location> elementLocations)
{
Debug.Assert(newElementNames.IsDefault || this._elementTypes.Length == newElementNames.Length);
if (this._elementNames.IsDefault)
{
if (newElementNames.IsDefault)
{
return this;
}
}
else if (!newElementNames.IsDefault && this._elementNames.SequenceEqual(newElementNames))
{
return this;
}
return new TupleTypeSymbol(null, _underlyingType, default(ImmutableArray<Location>), newElementNames, _elementTypes);
return new TupleTypeSymbol(location, _underlyingType, elementLocations, newElementNames, _elementTypes);
}
/// <summary>
......
......@@ -259,7 +259,13 @@ public static bool IsNamedArgumentName(SyntaxNode node)
return false;
var parent3 = parent2.Parent;
if (parent3 == null || !(parent3 is BaseArgumentListSyntax || parent3.IsKind(AttributeArgumentList)))
if (parent3 == null)
return false;
if (parent3.IsKind(SyntaxKind.TupleExpression))
return true;
if (!(parent3 is BaseArgumentListSyntax || parent3.IsKind(AttributeArgumentList)))
return false;
var parent4 = parent3.Parent;
......@@ -269,6 +275,7 @@ public static bool IsNamedArgumentName(SyntaxNode node)
switch (parent4.Kind())
{
case InvocationExpression:
case TupleExpression:
case ObjectCreationExpression:
case ObjectInitializerExpression:
case ElementAccessExpression:
......
......@@ -15035,6 +15035,38 @@ static void Main()
Assert.Equal(ConversionKind.AnonymousFunction, model.GetConversion(n5).Kind);
}
[Fact]
[WorkItem(14600, "https://github.com/dotnet/roslyn/issues/14600")]
public void GetSymbolInfo_01()
{
var source = @"
class C
{
static void Main()
{
bar x1 = (Alice: 1, ""hello"");
var Alice = x1.Alice;
}
}
" + trivial2uple + trivial3uple + tupleattributes_cs;
var tree = Parse(source, options: TestOptions.Regular);
var comp = CreateCompilationWithMscorlib(tree);
var model = comp.GetSemanticModel(tree, ignoreAccessibility: false);
var nodes = tree.GetCompilationUnitRoot().DescendantNodes();
var nc = nodes.OfType<NameColonSyntax>().ElementAt(0);
var sym = model.GetSymbolInfo(nc.Name);
Assert.Equal(SymbolKind.Field, sym.Symbol.Kind);
Assert.Equal("Alice", sym.Symbol.Name);
Assert.Equal(nc.Name.GetLocation(), sym.Symbol.Locations[0]);
}
[Fact]
public void CompileTupleLib()
{
......
......@@ -4726,6 +4726,231 @@ struct interface
Assert.Equal(TypeKind.Interface, ((TypeSymbol)interfaceSymbol).TypeKind);
}
[Fact]
public void TupleLiteral001()
{
var source =
@"
using System;
class C
{
static void Main()
{
var t = (1, 2);
}
}
";
var compilation = CreateCompilationWithMscorlib(source);
var tree = compilation.SyntaxTrees[0];
var decl = (TupleExpressionSyntax)tree.GetCompilationUnitRoot().DescendantNodes().Last(n => n.IsKind(SyntaxKind.TupleExpression));
var model = compilation.GetSemanticModel(tree);
var type = (NamedTypeSymbol)model.GetDeclaredSymbol(decl);
Assert.Equal(type.ToDisplayString(SymbolDisplayFormat.CSharpErrorMessageFormat), "(int, int)");
Assert.Equal(type.DeclaringSyntaxReferences.Single().GetSyntax().ToString(), "(1, 2)");
Assert.Equal(type.Locations.Single().IsInSource, true);
}
[Fact]
public void TupleLiteral002()
{
var source =
@"
using System;
class C
{
static void Main()
{
var t = (Alice: 1, Bob: 2);
}
}
";
var compilation = CreateCompilationWithMscorlib(source);
var tree = compilation.SyntaxTrees[0];
var decl = (TupleExpressionSyntax)tree.GetCompilationUnitRoot().DescendantNodes().Last(n => n.IsKind(SyntaxKind.TupleExpression));
var model = compilation.GetSemanticModel(tree);
var type = (NamedTypeSymbol)model.GetDeclaredSymbol(decl);
Assert.Equal(type.ToDisplayString(SymbolDisplayFormat.CSharpErrorMessageFormat), "(int Alice, int Bob)");
Assert.Equal(type.DeclaringSyntaxReferences.Single().GetSyntax().ToString(), "(Alice: 1, Bob: 2)");
Assert.Equal(type.Locations.Single().IsInSource, true);
}
[Fact]
public void TupleLiteral003()
{
var source =
@"
using System;
class C
{
static void Main()
{
(short Alice, int Bob) t = (1, 1);
}
}
";
var compilation = CreateCompilationWithMscorlib(source);
var tree = compilation.SyntaxTrees[0];
var decl = (TupleExpressionSyntax)tree.GetCompilationUnitRoot().DescendantNodes().Last(n => n.IsKind(SyntaxKind.TupleExpression));
var model = compilation.GetSemanticModel(tree);
var type = (NamedTypeSymbol)model.GetDeclaredSymbol(decl);
Assert.Equal(type.ToDisplayString(SymbolDisplayFormat.CSharpErrorMessageFormat), "(short, int)");
Assert.Equal(type.DeclaringSyntaxReferences.Single().GetSyntax().ToString(), "(1, 1)");
Assert.Equal(type.Locations.Single().IsInSource, true);
}
[Fact]
public void TupleLiteral004()
{
var source =
@"
using System;
class C
{
static void Main()
{
(short Alice, string Bob) t = (1, null);
}
}
";
var compilation = CreateCompilationWithMscorlib(source);
var tree = compilation.SyntaxTrees[0];
var decl = (TupleExpressionSyntax)tree.GetCompilationUnitRoot().DescendantNodes().Last(n => n.IsKind(SyntaxKind.TupleExpression));
var model = compilation.GetSemanticModel(tree);
var type = (NamedTypeSymbol)model.GetDeclaredSymbol(decl);
Assert.Equal(type.ToDisplayString(SymbolDisplayFormat.CSharpErrorMessageFormat), "(short, string)");
Assert.Equal(type.DeclaringSyntaxReferences.Single().GetSyntax().ToString(), "(1, null)");
Assert.Equal(type.Locations.Single().IsInSource, true);
}
[Fact]
public void TupleLiteral005()
{
var source =
@"
using System;
class C
{
static void Main()
{
(short, string) t = (Alice:1, Bob:null);
}
}
";
var compilation = CreateCompilationWithMscorlib(source);
var tree = compilation.SyntaxTrees[0];
var decl = (TupleExpressionSyntax)tree.GetCompilationUnitRoot().DescendantNodes().Last(n => n.IsKind(SyntaxKind.TupleExpression));
var model = compilation.GetSemanticModel(tree);
var type = (NamedTypeSymbol)model.GetDeclaredSymbol(decl);
Assert.Equal(type.ToDisplayString(SymbolDisplayFormat.CSharpErrorMessageFormat), "(short Alice, string Bob)");
Assert.Equal(type.DeclaringSyntaxReferences.Single().GetSyntax().ToString(), "(Alice:1, Bob:null)");
Assert.Equal(type.Locations.Single().IsInSource, true);
}
[Fact]
public void TupleLiteralElement001()
{
var source =
@"
using System;
class C
{
static void Main()
{
var t = (Alice: 1, Bob: 2);
}
}
";
var compilation = CreateCompilationWithMscorlib(source);
var tree = compilation.SyntaxTrees[0];
var decl = (ArgumentSyntax)tree.GetCompilationUnitRoot().DescendantNodes().Last(n => n.IsKind(SyntaxKind.Argument));
var model = compilation.GetSemanticModel(tree);
var element = (FieldSymbol)model.GetDeclaredSymbol(decl);
Assert.Equal(element.ToDisplayString(SymbolDisplayFormat.CSharpErrorMessageFormat), "(int Alice, int Bob).Bob");
Assert.Equal(element.DeclaringSyntaxReferences.Single().GetSyntax().ToString(), "Bob");
Assert.Equal(element.Locations.Single().IsInSource, true);
}
[Fact]
public void TupleLiteralElement002()
{
var source =
@"
using System;
class C
{
static void Main()
{
(int X, short Y) t = (Alice: 1, Bob: 2);
}
}
";
var compilation = CreateCompilationWithMscorlib(source);
var tree = compilation.SyntaxTrees[0];
var decl = (ArgumentSyntax)tree.GetCompilationUnitRoot().DescendantNodes().Last(n => n.IsKind(SyntaxKind.Argument));
var model = compilation.GetSemanticModel(tree);
var element = (FieldSymbol)model.GetDeclaredSymbol(decl);
Assert.Equal(element.ToDisplayString(SymbolDisplayFormat.CSharpErrorMessageFormat), "(int Alice, short Bob).Bob");
Assert.Equal(element.DeclaringSyntaxReferences.Single().GetSyntax().ToString(), "Bob");
Assert.Equal(element.Locations.Single().IsInSource, true);
}
[Fact]
public void TupleLiteralElement003()
{
var source =
@"
using System;
class C
{
static void Main()
{
(short X, string Y) t = (Alice: 1, Bob: null);
}
}
";
var compilation = CreateCompilationWithMscorlib(source);
var tree = compilation.SyntaxTrees[0];
var decl = (ArgumentSyntax)tree.GetCompilationUnitRoot().DescendantNodes().Last(n => n.IsKind(SyntaxKind.Argument));
var model = compilation.GetSemanticModel(tree);
var element = (FieldSymbol)model.GetDeclaredSymbol(decl);
Assert.Equal(element.ToDisplayString(SymbolDisplayFormat.CSharpErrorMessageFormat), "(short Alice, string Bob).Bob");
Assert.Equal(element.DeclaringSyntaxReferences.Single().GetSyntax().ToString(), "Bob");
Assert.Equal(element.Locations.Single().IsInSource, true);
}
[Fact]
public void TestIncompleteMemberNode_Visitor()
{
......
......@@ -592,7 +592,8 @@ private ExpressionSyntax VisitSimpleName(SimpleNameSyntax rewrittenSimpleName, S
(parent is MemberAccessExpressionSyntax && parent.Kind() != SyntaxKind.SimpleMemberAccessExpression) ||
((parent.Kind() == SyntaxKind.SimpleMemberAccessExpression || parent.Kind() == SyntaxKind.NameMemberCref) && originalSimpleName.IsRightSideOfDot()) ||
(parent.Kind() == SyntaxKind.QualifiedName && originalSimpleName.IsRightSideOfQualifiedName()) ||
(parent.Kind() == SyntaxKind.AliasQualifiedName))
(parent.Kind() == SyntaxKind.AliasQualifiedName)||
(parent.Kind() == SyntaxKind.NameColon))
{
return TryAddTypeArgumentToIdentifierName(newNode, symbol);
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册