diff --git a/src/Compilers/CSharp/Portable/CSharpExtensions.cs b/src/Compilers/CSharp/Portable/CSharpExtensions.cs index e682fdbce563a3f79f9c78daf9360576bceecf4a..67098f11352a9143ab37fd881c0fd303101c905a 100644 --- a/src/Compilers/CSharp/Portable/CSharpExtensions.cs +++ b/src/Compilers/CSharp/Portable/CSharpExtensions.cs @@ -1214,6 +1214,15 @@ public static INamedTypeSymbol GetDeclaredSymbol(this SemanticModel semanticMode return csmodel?.GetDeclaredSymbol(declaratorSyntax, cancellationToken); } + /// + /// Given a syntax node of a tuple argument, get the tuple element symbol. + /// + public static ISymbol GetDeclaredSymbol(this SemanticModel semanticModel, ArgumentSyntax declaratorSyntax, CancellationToken cancellationToken = default(CancellationToken)) + { + var csmodel = semanticModel as CSharpSemanticModel; + return csmodel?.GetDeclaredSymbol(declaratorSyntax, cancellationToken); + } + /// /// Given a syntax node that declares a property or member accessor, get the corresponding symbol. /// diff --git a/src/Compilers/CSharp/Portable/Compilation/CSharpSemanticModel.cs b/src/Compilers/CSharp/Portable/Compilation/CSharpSemanticModel.cs index d5cbcbdeb5a6f5dd2227e00438530b9260f38ddb..0adb7f5096875e9703294ae091b6ad71d767a938 100644 --- a/src/Compilers/CSharp/Portable/Compilation/CSharpSemanticModel.cs +++ b/src/Compilers/CSharp/Portable/Compilation/CSharpSemanticModel.cs @@ -2694,7 +2694,7 @@ internal Conversion ClassifyConversionForCast(int position, ExpressionSyntax exp // // This way IDEs can unambiguously implement such services as "Go to definition" // - // I.E. GetSymbolInfo for "tuple.Alice" should point to the same field as returned by GetDeclaredSymbol when applied to + // I.E. GetSymbolInfo for "Bob" in "tuple.Bob" should point to the same field as returned by GetDeclaredSymbol when applied to // the ArgumentSyntax "Bob: 2", since that is where the field was declared, where renames should be applied and so on. // // @@ -2753,6 +2753,11 @@ internal Conversion ClassifyConversionForCast(int position, ExpressionSyntax exp /// The argument syntax node. /// The cancellation token. /// The symbol that was declared. + /// + /// Generally ArgumentSyntax nodes do not declare symbols, except when used as aarguments of a tuple literal. + /// Example: var x = (Alice: 1, Bob: 2); + /// ArgumentSyntax "Alice: 1" declares a tuple element field "(int Alice, int Bob).Alice" + /// public abstract ISymbol GetDeclaredSymbol(ArgumentSyntax declaratorSyntax, CancellationToken cancellationToken = default(CancellationToken)); /// diff --git a/src/Compilers/CSharp/Portable/GlobalSuppressions.cs b/src/Compilers/CSharp/Portable/GlobalSuppressions.cs index 6390af8a9e05ffd62372137dd08e18165f6bb870..55fb3e0f72459169e6c41451b3353518808dd291 100644 --- a/src/Compilers/CSharp/Portable/GlobalSuppressions.cs +++ b/src/Compilers/CSharp/Portable/GlobalSuppressions.cs @@ -23,4 +23,5 @@ [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("ApiDesign", "RS0027:Public API with optional parameter(s) should have the most parameters amongst its public overloads.", Justification = "", 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 = "", 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 = "", Scope = "member", Target = "~M:Microsoft.CodeAnalysis.CSharp.CSharpExtensions.GetDeclaredSymbol(Microsoft.CodeAnalysis.SemanticModel,Microsoft.CodeAnalysis.CSharp.Syntax.TupleExpressionSyntax,System.Threading.CancellationToken)~Microsoft.CodeAnalysis.INamedTypeSymbol")] +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("ApiDesign", "RS0026:Do not add multiple public overloads with optional parameters", Justification = "", Scope = "member", Target = "~M:Microsoft.CodeAnalysis.CSharp.CSharpExtensions.GetDeclaredSymbol(Microsoft.CodeAnalysis.SemanticModel,Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentSyntax,System.Threading.CancellationToken)~Microsoft.CodeAnalysis.ISymbol")] diff --git a/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt b/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt index 71958966af68cc9c214d29748aac0546243e0eff..742b9babf0e54c94b32890db802e5d592037aa04 100644 --- a/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt +++ b/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt @@ -254,6 +254,7 @@ override Microsoft.CodeAnalysis.CSharp.Syntax.TupleTypeSyntax.Accept(Microsoft.C override Microsoft.CodeAnalysis.CSharp.Syntax.TupleTypeSyntax.Accept(Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor visitor) -> TResult override Microsoft.CodeAnalysis.CSharp.Syntax.WhenClauseSyntax.Accept(Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor visitor) -> void override Microsoft.CodeAnalysis.CSharp.Syntax.WhenClauseSyntax.Accept(Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor visitor) -> TResult +static Microsoft.CodeAnalysis.CSharp.CSharpExtensions.GetDeclaredSymbol(this Microsoft.CodeAnalysis.SemanticModel semanticModel, Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentSyntax declaratorSyntax, 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.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 diff --git a/src/Compilers/CSharp/Portable/Syntax/SyntaxFacts.cs b/src/Compilers/CSharp/Portable/Syntax/SyntaxFacts.cs index 12b89c519b372e340b7b43addbaa4e810c637fc3..0b57907c44bd02bdf69afcde4cbb5ac179acdbef 100644 --- a/src/Compilers/CSharp/Portable/Syntax/SyntaxFacts.cs +++ b/src/Compilers/CSharp/Portable/Syntax/SyntaxFacts.cs @@ -248,29 +248,43 @@ public static bool IsNamedArgumentName(SyntaxNode node) // Invocation, ObjectCreation, ObjectInitializer, or ElementAccess. if (!node.IsKind(IdentifierName)) + { return false; + } var parent1 = node.Parent; if (parent1 == null || !parent1.IsKind(NameColon)) + { return false; + } var parent2 = parent1.Parent; if (parent2 == null || !(parent2.IsKind(Argument) || parent2.IsKind(AttributeArgument))) + { return false; + } var parent3 = parent2.Parent; - if (parent3 == null) + 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; if (parent4 == null) + { return false; + } switch (parent4.Kind()) {