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())
{