diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs index 0e9668c024a774d084f5fbb29dfb2ad0d11dc6e6..767ea8607f3a729da942c4dae008efe37f6a09fd 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs @@ -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,34 @@ 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 locations 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.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; diff --git a/src/Compilers/CSharp/Portable/CSharpExtensions.cs b/src/Compilers/CSharp/Portable/CSharpExtensions.cs index a9332cd949347638c21a2d8ed3d59c6a18965b4c..67098f11352a9143ab37fd881c0fd303101c905a 100644 --- a/src/Compilers/CSharp/Portable/CSharpExtensions.cs +++ b/src/Compilers/CSharp/Portable/CSharpExtensions.cs @@ -1205,6 +1205,24 @@ public static INamedTypeSymbol GetDeclaredSymbol(this SemanticModel semanticMode return csmodel?.GetDeclaredSymbol(declaratorSyntax, cancellationToken); } + /// + /// Given a syntax node of tuple expression, get the tuple type symbol. + /// + public static INamedTypeSymbol GetDeclaredSymbol(this SemanticModel semanticModel, TupleExpressionSyntax declaratorSyntax, CancellationToken cancellationToken = default(CancellationToken)) + { + var csmodel = semanticModel as CSharpSemanticModel; + 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 5b4caff35511c2d848155770a4678fe219fbb849..d6fccd813eaea1407fd3b1a0046f45e3a0de72ce 100644 --- a/src/Compilers/CSharp/Portable/Compilation/CSharpSemanticModel.cs +++ b/src/Compilers/CSharp/Portable/Compilation/CSharpSemanticModel.cs @@ -2679,6 +2679,59 @@ internal Conversion ClassifyConversionForCast(int position, ExpressionSyntax exp #endregion + // Anonymous types and Tuple expressions are an interesting case here because they declare their own types + // + // In both cases there is no distinct syntax that creates the type and the syntax that describes the type is the literal itself. + // Surely - if you need to modify the anonymous type or a type of a tuple literal, you would be modifying these expressions. + // + // As a result we support GetDeclaredSymbol on the whole AnonymousObjectCreationExpressionSyntax/TupleExpressionSyntax. + // The implementation returns the type of the expression. + // + // In addition to that GetDeclaredSymbol works on the AnonymousObjectMemberDeclaratorSyntax/ArgumentSyntax + // The implementation returns the property/field symbol that is declared by the corresponding syntax. + // + // Example: + // GetDeclaredSymbol => Type: (int Alice, int Bob) + // _____ |__________ + // [ ] + // var tuple = (Alice: 1, Bob: 2); + // [ ] + // \GetDeclaredSymbol => Field: (int Alice, int Bob).Bob + // + // A special note must be made about the locations of the corresponding symbols - they refer to the actual syntax + // of the literal or the anonymous type creation expression + // + // This way IDEs can unambiguously implement such services as "Go to definition" + // + // 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. + // + // + // In comparison to anonymous types, tuples have one special behavior. + // It is permitted for tuple literals to not have a natural type as long as there is a target type which determines the types of the fields. + // As, such for the purpose of GetDeclaredSymbol, the type symbol that is returned for tuple literals has target-typed fields, + // but yet with the original names. + // + // GetDeclaredSymbol => Type: (string Alice, short Bob) + // ________ |__________ + // [ ] + // (string, short) tuple = (Alice: null, Bob: 2); + // [ ] + // \GetDeclaredSymbol => Field: (string Alice, short Bob).Alice + // + // In partiucular, the location of the field declaration is "Alice: null" and not the "string" + // the location of the type is "(Alice: null, Bob: 2)" and not the "(string, short)" + // + // The reason for this behavior is that, even though there might not be other references to "Alice" field in the code, + // the name "Alice" itself evidently refers to something named "Alice" and should still work with + // all the related APIs and services such as "Find all References", "Go to definition", "symbolic rename" etc... + // + // GetSymbolInfo => Field: (string Alice, short Bob).Alice + // __ |__ + // [ ] + // (string, short) tuple = (Alice: null, Bob: 2); + // + /// /// Given a syntax node of anonymous object creation initializer, get the anonymous object property symbol. /// @@ -2695,6 +2748,27 @@ internal Conversion ClassifyConversionForCast(int position, ExpressionSyntax exp /// The symbol that was declared. public abstract INamedTypeSymbol GetDeclaredSymbol(AnonymousObjectCreationExpressionSyntax declaratorSyntax, CancellationToken cancellationToken = default(CancellationToken)); + /// + /// Given a syntax node of a tuple expression, get the tuple type symbol. + /// + /// The tuple expression node. + /// The cancellation token. + /// The symbol that was declared. + public abstract INamedTypeSymbol GetDeclaredSymbol(TupleExpressionSyntax declaratorSyntax, CancellationToken cancellationToken = default(CancellationToken)); + + /// + /// Given a syntax node of an argument expression, get the declared symbol. + /// + /// 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)); + /// /// Given a syntax node that declares a property or member accessor, get the corresponding /// symbol. @@ -3972,7 +4046,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 tupleElement = GetDeclaredSymbol(tupleArgument, cancellationToken); + return (object)tupleElement == null ? SymbolInfo.None : new SymbolInfo(tupleElement, ImmutableArray.Empty, CandidateReason.None); + } + + CSharpSyntaxNode containingInvocation = parent3.Parent; SymbolInfo containingInvocationInfo = GetSymbolInfoWorker(containingInvocation, SymbolInfoOptions.PreferConstructorsToType | SymbolInfoOptions.ResolveAliases, cancellationToken); @@ -4618,6 +4702,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: diff --git a/src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.cs b/src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.cs index 871e5bdb01dbaffd7164ae265f5ff211bea3e9e0..1cae812891b1250bd1ee032bce6392bc55e4cfaa 100644 --- a/src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.cs +++ b/src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.cs @@ -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 diff --git a/src/Compilers/CSharp/Portable/Compilation/SyntaxTreeSemanticModel.cs b/src/Compilers/CSharp/Portable/Compilation/SyntaxTreeSemanticModel.cs index 03b161b46d176f96e95854be1e347e02c04e0e49..3f1ab11868e37e0e985bcb9e3ee46f79bb169c98 100644 --- a/src/Compilers/CSharp/Portable/Compilation/SyntaxTreeSemanticModel.cs +++ b/src/Compilers/CSharp/Portable/Compilation/SyntaxTreeSemanticModel.cs @@ -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); diff --git a/src/Compilers/CSharp/Portable/GlobalSuppressions.cs b/src/Compilers/CSharp/Portable/GlobalSuppressions.cs index 6b9387437479c161a7f070be16573d9c51ebc197..55fb3e0f72459169e6c41451b3353518808dd291 100644 --- a/src/Compilers/CSharp/Portable/GlobalSuppressions.cs +++ b/src/Compilers/CSharp/Portable/GlobalSuppressions.cs @@ -22,4 +22,6 @@ [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.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 = "", 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 f068d4aa60979486cafad6a113bf7e6633774d91..742b9babf0e54c94b32890db802e5d592037aa04 100644 --- a/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt +++ b/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt @@ -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 @@ -254,8 +254,10 @@ 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 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 diff --git a/src/Compilers/CSharp/Portable/Symbols/Tuples/TupleTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Tuples/TupleTypeSymbol.cs index 09180f5fdfc8d1c2537d823757393cf32191dd3f..f34311107171413810ed2e7996c948ac5b139eca 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Tuples/TupleTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Tuples/TupleTypeSymbol.cs @@ -216,24 +216,15 @@ internal TupleTypeSymbol WithUnderlyingType(NamedTypeSymbol newUnderlyingType) /// /// Copy this tuple, but modify it to use the new element names. + /// Also applies new location of the whole tuple as well as each element. /// - internal TupleTypeSymbol WithElementNames(ImmutableArray newElementNames) + internal TupleTypeSymbol WithElementNames(ImmutableArray newElementNames, + Location newLocation, + ImmutableArray newElementLocations) { 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), newElementNames, _elementTypes); + return new TupleTypeSymbol(newLocation, _underlyingType, newElementLocations, newElementNames, _elementTypes); } /// diff --git a/src/Compilers/CSharp/Portable/Syntax/SyntaxFacts.cs b/src/Compilers/CSharp/Portable/Syntax/SyntaxFacts.cs index e320389a42bbd71a8a95689ae2a07c23406fc5ed..0b57907c44bd02bdf69afcde4cbb5ac179acdbef 100644 --- a/src/Compilers/CSharp/Portable/Syntax/SyntaxFacts.cs +++ b/src/Compilers/CSharp/Portable/Syntax/SyntaxFacts.cs @@ -248,27 +248,48 @@ 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 || !(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; if (parent4 == null) + { return false; + } switch (parent4.Kind()) { case InvocationExpression: + case TupleExpression: case ObjectCreationExpression: case ObjectInitializerExpression: case ElementAccessExpression: diff --git a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTupleTest.cs b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTupleTest.cs index 9951379fea32e6f52fc11eab998b738b5113a2b9..e02838d7ad6c4b0cb082e37b3fa7904e4106e842 100644 --- a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTupleTest.cs +++ b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTupleTest.cs @@ -15074,6 +15074,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() + { + // error is intentional. GetSymbolInfo should still work + DummyType 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().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() { diff --git a/src/Compilers/CSharp/Test/Symbol/Compilation/SemanticModelGetDeclaredSymbolAPITests.cs b/src/Compilers/CSharp/Test/Symbol/Compilation/SemanticModelGetDeclaredSymbolAPITests.cs index b378bc34f31a69f85944308df9d98c7da05b1b39..a9174e728440077b9638cb63bf2a5064090a7f2c 100644 --- a/src/Compilers/CSharp/Test/Symbol/Compilation/SemanticModelGetDeclaredSymbolAPITests.cs +++ b/src/Compilers/CSharp/Test/Symbol/Compilation/SemanticModelGetDeclaredSymbolAPITests.cs @@ -4726,6 +4726,336 @@ 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 TupleLiteralElement004() + { + var source = +@" + +using System; + +class C +{ + static void Main() + { + (short X, string Y) = (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 TupleLiteralElement005() + { + var source = +@" + +using System; + +class C +{ + static void Main() + { + ValueTuple vt = (Alice: 1, Bob: null); + } +} + +namespace System +{ + // struct with two values + public struct ValueTuple + { + public T1 Item1; + public T2 Item2; + + public ValueTuple(T1 item1, T2 item2) + { + this.Item1 = item1; + this.Item2 = item2; + } + + public override string ToString() + { + return '{' + Item1?.ToString() + "", "" + Item2?.ToString() + '}'; + } + } +} + +"; + + 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 TupleLiteralElement006() + { + var source = +@" + +using System; + +class C +{ + static void Main() + { + (short X, string) t = (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, string Bob).Bob"); + Assert.Equal(element.DeclaringSyntaxReferences.Single().GetSyntax().ToString(), "Bob"); + Assert.Equal(element.Locations.Single().IsInSource, true); + } + [Fact] public void TestIncompleteMemberNode_Visitor() { diff --git a/src/EditorFeatures/Test2/EditorServicesTest2.vbproj b/src/EditorFeatures/Test2/EditorServicesTest2.vbproj index ee828e128f4e86711867de87ff91825ef7db3048..38deb2b5e02f6e42384bf33b8130f2f1a08783ef 100644 --- a/src/EditorFeatures/Test2/EditorServicesTest2.vbproj +++ b/src/EditorFeatures/Test2/EditorServicesTest2.vbproj @@ -194,6 +194,7 @@ + diff --git a/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.Tuples.vb b/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.Tuples.vb new file mode 100644 index 0000000000000000000000000000000000000000..5bef568fb55e20ba82819d5419fc85b0d1e9d360 --- /dev/null +++ b/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.Tuples.vb @@ -0,0 +1,234 @@ +' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +Imports System.Threading.Tasks + +Namespace Microsoft.CodeAnalysis.Editor.UnitTests.FindReferences + Partial Public Class FindReferencesTests + Dim tuple2Doc As XElement = + +namespace System +{ + // struct with two values + public struct ValueTuple<T1, T2> + { + public T1 Item1; + public T2 Item2; + + public ValueTuple(T1 item1, T2 item2) + { + this.Item1 = item1; + this.Item2 = item2; + } + + public override string ToString() + { + return '{' + Item1?.ToString() + "", "" + Item2?.ToString() + '}'; + } + } +} + + + + Public Async Function TestTupleFieldSameTuples01() As Task + Dim input = + + + <%= tuple2Doc %> + + + + + Await TestAPIAndFeature(input) + End Function + + + Public Async Function TestTupleFieldSameTuples02() As Task + Dim input = + + + <%= tuple2Doc %> + + + + + Await TestAPIAndFeature(input) + End Function + + + Public Async Function TestTupleFieldSameTuples03() As Task + Dim input = + + + <%= tuple2Doc %> + + + + + Await TestAPIAndFeature(input) + End Function + + + Public Async Function TestTupleFieldSameTuplesMultidocument() As Task + Dim input = + + + <%= tuple2Doc %> + + + + + + + Await TestAPIAndFeature(input) + End Function + + + Public Async Function TestTupleFieldDifferentTuples01() As Task + Dim input = + + + <%= tuple2Doc %> + + + + + Await TestAPIAndFeature(input) + End Function + + + Public Async Function TestTupleFieldSameTuplesMatchOuterSymbols01() As Task + Dim input = + + + <%= tuple2Doc %> + + + + + Await TestAPIAndFeature(input) + End Function + + + Public Async Function TestTupleFieldSameTuplesMatchOuterSymbols02() As Task + Dim input = + + + <%= tuple2Doc %> + + + + + Await TestAPIAndFeature(input) + End Function + + End Class +End Namespace diff --git a/src/EditorFeatures/Test2/GoToDefinition/GoToDefinitionTests.vb b/src/EditorFeatures/Test2/GoToDefinition/GoToDefinitionTests.vb index ad3fee9687b0bd8642c43405a83991924732fb1f..d494328a84662c2f6535e595027849da1086dd4a 100644 --- a/src/EditorFeatures/Test2/GoToDefinition/GoToDefinitionTests.vb +++ b/src/EditorFeatures/Test2/GoToDefinition/GoToDefinitionTests.vb @@ -765,6 +765,245 @@ class C Await TestAsync(workspace) End Function +#End Region + +#Region "CSharp TupleTests" + Dim tuple2Doc As XElement = + +namespace System +{ + // struct with two values + public struct ValueTuple<T1, T2> + { + public T1 Item1; + public T2 Item2; + + public ValueTuple(T1 item1, T2 item2) + { + this.Item1 = item1; + this.Item2 = item2; + } + + public override string ToString() + { + return '{' + Item1?.ToString() + "", "" + Item2?.ToString() + '}'; + } + } +} + + + + Public Async Function TestCSharpGotoDefinitionTupleFieldEqualTuples01() As Task + Dim workspace = + + + <%= tuple2Doc %> + + class Program + { + static void Main(string[] args) + { + var x = ([|Alice|]: 1, Bob: 2); + + var y = (Alice: 1, Bob: 2); + + var z1 = x.$$Alice; + var z2 = y.Alice; + } + } + + + + + Await TestAsync(workspace) + End Function + + + Public Async Function TestCSharpGotoDefinitionTupleFieldEqualTuples02() As Task + Dim workspace = + + + + + class Program + { + static void Main(string[] args) + { + var x = (Alice: 1, Bob: 2); + + var y = ([|Alice|]: 1, Bob: 2); + + var z1 = x.Alice; + var z2 = y.$$Alice; + } + } + + + + + Await TestAsync(workspace) + End Function + + + Public Async Function TestCSharpGotoDefinitionTupleFieldMatchToOuter01() As Task + Dim workspace = + + + <%= tuple2Doc %> + + class Program + { + static void Main(string[] args) + { + var x = ([|Program|]: 1, Main: 2); + + var z = x.$$Program; + } + } + + + + + Await TestAsync(workspace) + End Function + + + Public Async Function TestCSharpGotoDefinitionTupleFieldMatchToOuter02() As Task + Dim workspace = + + + <%= tuple2Doc %> + + class Program + { + static void Main(string[] args) + { + var x = ([|Pro$$gram|]: 1, Main: 2); + + var z = x.Program; + } + } + + + + + Await TestAsync(workspace) + End Function + + + Public Async Function TestCSharpGotoDefinitionTupleFieldMatchToOuter03() As Task + Dim workspace = + + + <%= tuple2Doc %> + + class Program + { + static void Main(string[] args) + { + var x = (1,2,3,4,5,6,7,8,9,10, [|Program|]: 1, Main: 2); + + var z = x.$$Program; + } + } + + + + + Await TestAsync(workspace) + End Function + + + Public Async Function TestCSharpGotoDefinitionTupleFieldRedeclared01() As Task + Dim workspace = + + + <%= tuple2Doc %> + + class Program + { + static void Main(string[] args) + { + (int [|Alice|], int Bob) x = (Alice: 1, Bob: 2); + + var z1 = x.$$Alice; + } + } + + + + + Await TestAsync(workspace) + End Function + + + Public Async Function TestCSharpGotoDefinitionTupleFieldRedeclared02() As Task + Dim workspace = + + + <%= tuple2Doc %> + + class Program + { + static void Main(string[] args) + { + (string Alice, int Bob) x = ([|Al$$ice|]: null, Bob: 2); + + var z1 = x.Alice; + } + } + + + + + Await TestAsync(workspace) + End Function + + + Public Async Function TestCSharpGotoDefinitionTupleFieldItem01() As Task + Dim workspace = + + + <%= tuple2Doc %> + + class Program + { + static void Main(string[] args) + { + var x = ([|1|], Bob: 2); + + var z1 = x.$$Item1; + } + } + + + + + Await TestAsync(workspace) + End Function + + + Public Async Function TestCSharpGotoDefinitionTupleFieldItem02() As Task + Dim workspace = + + + <%= tuple2Doc %> + + class Program + { + static void Main(string[] args) + { + var x = ([|Alice|]: 1, Bob: 2); + + var z1 = x.$$Item1; + } + } + + + + + Await TestAsync(workspace) + End Function #End Region diff --git a/src/EditorFeatures/Test2/Rename/RenameNonRenameableSymbols.vb b/src/EditorFeatures/Test2/Rename/RenameNonRenameableSymbols.vb index 66b7e30e390c83a8a9d3f31bda815fa44b25371c..ae647bbecbad42226785ffde4e2d47058d694602 100644 --- a/src/EditorFeatures/Test2/Rename/RenameNonRenameableSymbols.vb +++ b/src/EditorFeatures/Test2/Rename/RenameNonRenameableSymbols.vb @@ -643,6 +643,60 @@ namespace System End Sub + + + + + Public Sub RenameTupleFiledInLiteralRegress14600() + Using workspace = CreateWorkspaceWithWaiter( + + + +using System; + +class Program +{ + static void Main(string[] args) + { + var x = (Program: 1, Bob: 2); + + var Alice = x.$$Program; + } + +} + + + +namespace System +{ + // struct with two values + public struct ValueTuple<T1, T2> + { + public T1 Item1; + public T2 Item2; + + public ValueTuple(T1 item1, T2 item2) + { + this.Item1 = item1; + this.Item2 = item2; + } + + public override string ToString() + { + return '{' + Item1?.ToString() + ", " + Item2?.ToString() + '}'; + } + } +} + + + ) + + ' NOTE: this is currently intentionally blocked + ' see https://github.com/dotnet/roslyn/issues/10898 + AssertTokenNotRenamable(workspace) + End Using + End Sub + #End Region End Class diff --git a/src/Workspaces/CSharp/Portable/Simplification/CSharpSimplificationService.Expander.cs b/src/Workspaces/CSharp/Portable/Simplification/CSharpSimplificationService.Expander.cs index 4cb326c1da4df1ecc15ba979d348a0e3c0108b41..e6c9a4778ddc5b811a202cd9ba42805921c0b911 100644 --- a/src/Workspaces/CSharp/Portable/Simplification/CSharpSimplificationService.Expander.cs +++ b/src/Workspaces/CSharp/Portable/Simplification/CSharpSimplificationService.Expander.cs @@ -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); }