/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Compilers/CSharp/Test/Syntax/Parsing/NameParsingTests.cs
1 668 строк
69 KB
Copilot
Add parser test demonstrating recovery from missing type arguments in generic names. (#81062)
07 ноя 2025, 00:10
Не верифицирован
07 ноя 2025, 00:10
ccb63b4
Код
Авторство
О чём код?
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. #nullable disable using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.CSharp.Test.Utilities; using Roslyn.Test.Utilities; using Xunit; using Xunit.Abstractions; namespace Microsoft.CodeAnalysis.CSharp.UnitTests { public class NameParsingTests : ParsingTests { public NameParsingTests(ITestOutputHelper output) : base(output) { } private NameSyntax ParseName(string text) { return SyntaxFactory.ParseName(text); } private TypeSyntax ParseTypeName(string text) { return SyntaxFactory.ParseTypeName(text); } [Fact] public void TestBasicName() { var text = "goo"; var name = ParseName(text); Assert.NotNull(name); Assert.Equal(SyntaxKind.IdentifierName, name.Kind()); Assert.False(((IdentifierNameSyntax)name).Identifier.IsMissing); Assert.Equal(0, name.Errors().Length); Assert.Equal(text, name.ToString()); } [Fact] public void TestBasicNameWithTrash() { var text = "/*comment*/goo/*comment2*/ bar"; var name = ParseName(text); Assert.NotNull(name); Assert.Equal(SyntaxKind.IdentifierName, name.Kind()); Assert.False(((IdentifierNameSyntax)name).Identifier.IsMissing); Assert.Equal(1, name.Errors().Length); Assert.Equal(text, name.ToFullString()); } [Fact] public void TestMissingName() { var text = string.Empty; var name = ParseName(text); Assert.NotNull(name); Assert.Equal(SyntaxKind.IdentifierName, name.Kind()); Assert.True(((IdentifierNameSyntax)name).Identifier.IsMissing); Assert.Equal(1, name.Errors().Length); Assert.Equal((int)ErrorCode.ERR_IdentifierExpected, name.Errors()[0].Code); Assert.Equal(string.Empty, name.ToString()); } [Fact] public void TestMissingNameDueToKeyword() { var text = "class"; var name = ParseName(text); Assert.NotNull(name); Assert.Equal(SyntaxKind.IdentifierName, name.Kind()); Assert.True(name.IsMissing); Assert.Equal(2, name.Errors().Length); Assert.Equal((int)ErrorCode.ERR_UnexpectedToken, name.Errors()[0].Code); Assert.Equal((int)ErrorCode.ERR_IdentifierExpected, name.Errors()[1].Code); Assert.Equal(string.Empty, name.ToString()); } [Fact] public void TestMissingNameDueToPartialClassStart() { var text = "partial class"; var name = ParseName(text); Assert.NotNull(name); Assert.Equal(SyntaxKind.IdentifierName, name.Kind()); Assert.True(name.IsMissing); Assert.Equal(2, name.Errors().Length); Assert.Equal((int)ErrorCode.ERR_UnexpectedToken, name.Errors()[0].Code); Assert.Equal((int)ErrorCode.ERR_InvalidExprTerm, name.Errors()[1].Code); Assert.Equal(string.Empty, name.ToString()); } [Fact] public void TestMissingNameDueToPartialMethodStart() { var text = "partial void Method()"; var name = ParseName(text); Assert.NotNull(name); Assert.Equal(SyntaxKind.IdentifierName, name.Kind()); Assert.True(name.IsMissing); Assert.Equal(2, name.Errors().Length); Assert.Equal((int)ErrorCode.ERR_UnexpectedToken, name.Errors()[0].Code); Assert.Equal((int)ErrorCode.ERR_InvalidExprTerm, name.Errors()[1].Code); Assert.Equal(string.Empty, name.ToString()); } [Fact] public void TestAliasedName() { var text = "goo::bar"; var name = ParseName(text); Assert.NotNull(name); Assert.Equal(SyntaxKind.AliasQualifiedName, name.Kind()); Assert.False(name.IsMissing); Assert.Equal(0, name.Errors().Length); Assert.Equal(text, name.ToString()); } [Fact] public void TestGlobalAliasedName() { var text = "global::bar"; var name = ParseName(text); Assert.NotNull(name); Assert.False(name.IsMissing); Assert.Equal(SyntaxKind.AliasQualifiedName, name.Kind()); var an = (AliasQualifiedNameSyntax)name; Assert.Equal(SyntaxKind.GlobalKeyword, an.Alias.Identifier.Kind()); Assert.Equal(0, name.Errors().Length); Assert.Equal(text, name.ToString()); } [Fact] public void TestDottedName() { var text = "goo.bar"; var name = ParseName(text); Assert.NotNull(name); Assert.Equal(SyntaxKind.QualifiedName, name.Kind()); Assert.False(name.IsMissing); Assert.Equal(0, name.Errors().Length); Assert.Equal(text, name.ToString()); } [Fact] public void TestAliasedDottedName() { var text = "goo::bar.Zed"; var name = ParseName(text); Assert.NotNull(name); Assert.Equal(SyntaxKind.QualifiedName, name.Kind()); Assert.False(name.IsMissing); Assert.Equal(0, name.Errors().Length); Assert.Equal(text, name.ToString()); name = ((QualifiedNameSyntax)name).Left; Assert.Equal(SyntaxKind.AliasQualifiedName, name.Kind()); Assert.False(name.IsMissing); Assert.Equal(0, name.Errors().Length); } [Fact] public void TestDoubleAliasName() { // In the original implementation of the parser this error case was parsed as // // (goo :: bar ) :: baz // // However, we have decided that the left hand side of a :: should always be // an identifier, not a name, even in error cases. Therefore instead we // parse this as though the error was that the user intended to make the // second :: a dot; we parse this as // // (goo :: bar ) . baz var text = "goo::bar::baz"; var name = ParseName(text); Assert.NotNull(name); Assert.Equal(SyntaxKind.QualifiedName, name.Kind()); Assert.False(name.IsMissing); Assert.Equal(1, name.Errors().Length); Assert.Equal(text, name.ToString()); name = ((QualifiedNameSyntax)name).Left; Assert.Equal(SyntaxKind.AliasQualifiedName, name.Kind()); Assert.False(name.IsMissing); Assert.Equal(0, name.Errors().Length); } [Fact] public void TestGenericName() { var text = "goo<bar>"; var name = ParseName(text); Assert.NotNull(name); Assert.Equal(SyntaxKind.GenericName, name.Kind()); Assert.False(name.IsMissing); Assert.Equal(0, name.Errors().Length); var gname = (GenericNameSyntax)name; Assert.Equal(1, gname.TypeArgumentList.Arguments.Count); Assert.False(gname.IsUnboundGenericName); Assert.Equal(text, name.ToString()); } [Fact] public void TestGenericNameWithTwoArguments() { var text = "goo<bar,zed>"; var name = ParseName(text); Assert.NotNull(name); Assert.Equal(SyntaxKind.GenericName, name.Kind()); Assert.False(name.IsMissing); Assert.Equal(0, name.Errors().Length); var gname = (GenericNameSyntax)name; Assert.Equal(2, gname.TypeArgumentList.Arguments.Count); Assert.False(gname.IsUnboundGenericName); Assert.Equal(text, name.ToString()); } [Fact] public void TestNestedGenericName_01() { var text = "goo<bar<zed>>"; var name = ParseName(text); Assert.NotNull(name); Assert.Equal(SyntaxKind.GenericName, name.Kind()); Assert.False(name.IsMissing); Assert.Equal(0, name.Errors().Length); var gname = (GenericNameSyntax)name; Assert.Equal(1, gname.TypeArgumentList.Arguments.Count); Assert.False(gname.IsUnboundGenericName); Assert.NotNull(gname.TypeArgumentList.Arguments[0]); Assert.Equal(SyntaxKind.GenericName, gname.TypeArgumentList.Arguments[0].Kind()); Assert.Equal(text, name.ToString()); } [Fact] public void TestNestedGenericName_02() { var text = "goo<bar<zed<U>>>"; var name = ParseName(text); UsingNode(text, name); N(SyntaxKind.GenericName); { N(SyntaxKind.IdentifierToken, "goo"); N(SyntaxKind.TypeArgumentList); { N(SyntaxKind.LessThanToken); N(SyntaxKind.GenericName); { N(SyntaxKind.IdentifierToken, "bar"); N(SyntaxKind.TypeArgumentList); { N(SyntaxKind.LessThanToken); N(SyntaxKind.GenericName); { N(SyntaxKind.IdentifierToken, "zed"); N(SyntaxKind.TypeArgumentList); { N(SyntaxKind.LessThanToken); N(SyntaxKind.IdentifierName); { N(SyntaxKind.IdentifierToken, "U"); } N(SyntaxKind.GreaterThanToken); } } N(SyntaxKind.GreaterThanToken); } } N(SyntaxKind.GreaterThanToken); } } EOF(); } [Fact] public void TestOpenNameWithNoCommas() { var text = "goo<>"; var name = ParseName(text); Assert.NotNull(name); Assert.Equal(SyntaxKind.GenericName, name.Kind()); Assert.False(name.IsMissing); Assert.Equal(0, name.Errors().Length); var gname = (GenericNameSyntax)name; Assert.Equal(1, gname.TypeArgumentList.Arguments.Count); Assert.Equal(0, gname.TypeArgumentList.Arguments.SeparatorCount); Assert.True(gname.IsUnboundGenericName); Assert.Equal(text, name.ToString()); } [Fact] public void TestOpenNameWithAComma() { var text = "goo<,>"; var name = ParseName(text); Assert.NotNull(name); Assert.Equal(SyntaxKind.GenericName, name.Kind()); Assert.False(name.IsMissing); Assert.Equal(0, name.Errors().Length); var gname = (GenericNameSyntax)name; Assert.Equal(2, gname.TypeArgumentList.Arguments.Count); Assert.Equal(1, gname.TypeArgumentList.Arguments.SeparatorCount); Assert.True(gname.IsUnboundGenericName); Assert.Equal(text, name.ToString()); } [Fact] public void TestBasicTypeName() { var text = "goo"; var tname = ParseTypeName(text); Assert.NotNull(tname); Assert.Equal(SyntaxKind.IdentifierName, tname.Kind()); var name = (NameSyntax)tname; Assert.False(name.IsMissing); Assert.Equal(0, name.Errors().Length); Assert.Equal(text, name.ToString()); } [Fact] public void TestDottedTypeName() { var text = "goo.bar"; var tname = ParseTypeName(text); Assert.NotNull(tname); Assert.Equal(SyntaxKind.QualifiedName, tname.Kind()); var name = (NameSyntax)tname; Assert.False(name.IsMissing); Assert.Equal(0, name.Errors().Length); Assert.Equal(text, name.ToString()); } [Fact] public void TestGenericTypeName() { var text = "goo<bar>"; var tname = ParseTypeName(text); Assert.NotNull(tname); Assert.Equal(SyntaxKind.GenericName, tname.Kind()); var name = (NameSyntax)tname; Assert.False(name.IsMissing); Assert.Equal(0, name.Errors().Length); var gname = (GenericNameSyntax)name; Assert.Equal(1, gname.TypeArgumentList.Arguments.Count); Assert.False(gname.IsUnboundGenericName); Assert.Equal(text, name.ToString()); } [Fact] public void TestNestedGenericTypeName_01() { var text = "goo<bar<zed>>"; var tname = ParseTypeName(text); Assert.NotNull(tname); Assert.Equal(SyntaxKind.GenericName, tname.Kind()); var name = (NameSyntax)tname; Assert.False(name.IsMissing); Assert.Equal(0, name.Errors().Length); var gname = (GenericNameSyntax)name; Assert.Equal(1, gname.TypeArgumentList.Arguments.Count); Assert.False(gname.IsUnboundGenericName); Assert.NotNull(gname.TypeArgumentList.Arguments[0]); Assert.Equal(SyntaxKind.GenericName, gname.TypeArgumentList.Arguments[0].Kind()); Assert.Equal(text, name.ToString()); } [Fact] public void TestNestedGenericTypeName_02() { var text = "goo<bar<zed<U>>>"; var tname = ParseTypeName(text); UsingNode(text, tname); N(SyntaxKind.GenericName); { N(SyntaxKind.IdentifierToken, "goo"); N(SyntaxKind.TypeArgumentList); { N(SyntaxKind.LessThanToken); N(SyntaxKind.GenericName); { N(SyntaxKind.IdentifierToken, "bar"); N(SyntaxKind.TypeArgumentList); { N(SyntaxKind.LessThanToken); N(SyntaxKind.GenericName); { N(SyntaxKind.IdentifierToken, "zed"); N(SyntaxKind.TypeArgumentList); { N(SyntaxKind.LessThanToken); N(SyntaxKind.IdentifierName); { N(SyntaxKind.IdentifierToken, "U"); } N(SyntaxKind.GreaterThanToken); } } N(SyntaxKind.GreaterThanToken); } } N(SyntaxKind.GreaterThanToken); } } EOF(); } [Fact] public void TestOpenTypeNameWithNoCommas() { var text = "goo<>"; var tname = ParseTypeName(text); Assert.NotNull(tname); Assert.Equal(SyntaxKind.GenericName, tname.Kind()); var name = (NameSyntax)tname; Assert.False(name.IsMissing); Assert.Equal(0, name.Errors().Length); var gname = (GenericNameSyntax)name; Assert.Equal(1, gname.TypeArgumentList.Arguments.Count); Assert.Equal(0, gname.TypeArgumentList.Arguments.SeparatorCount); Assert.True(gname.IsUnboundGenericName); Assert.Equal(text, name.ToString()); } [Fact] public void TestKnownTypeNames() { ParseKnownTypeName(SyntaxKind.BoolKeyword); ParseKnownTypeName(SyntaxKind.ByteKeyword); ParseKnownTypeName(SyntaxKind.SByteKeyword); ParseKnownTypeName(SyntaxKind.ShortKeyword); ParseKnownTypeName(SyntaxKind.UShortKeyword); ParseKnownTypeName(SyntaxKind.IntKeyword); ParseKnownTypeName(SyntaxKind.UIntKeyword); ParseKnownTypeName(SyntaxKind.LongKeyword); ParseKnownTypeName(SyntaxKind.ULongKeyword); ParseKnownTypeName(SyntaxKind.FloatKeyword); ParseKnownTypeName(SyntaxKind.DoubleKeyword); ParseKnownTypeName(SyntaxKind.DecimalKeyword); ParseKnownTypeName(SyntaxKind.StringKeyword); ParseKnownTypeName(SyntaxKind.ObjectKeyword); } private void ParseKnownTypeName(SyntaxKind kind) { var text = SyntaxFacts.GetText(kind); var tname = ParseTypeName(text); Assert.NotNull(tname); Assert.Equal(SyntaxKind.PredefinedType, tname.Kind()); Assert.Equal(text, tname.ToString()); var tok = ((PredefinedTypeSyntax)tname).Keyword; Assert.Equal(kind, tok.Kind()); } [Fact] public void TestNullableTypeName() { var text = "goo?"; var tname = ParseTypeName(text); Assert.NotNull(tname); Assert.Equal(SyntaxKind.NullableType, tname.Kind()); Assert.Equal(text, tname.ToString()); var name = (NameSyntax)((NullableTypeSyntax)tname).ElementType; Assert.Equal(SyntaxKind.IdentifierName, name.Kind()); Assert.False(name.IsMissing); Assert.Equal(0, name.Errors().Length); } [Fact] public void TestPointerTypeName() { var text = "goo*"; var tname = ParseTypeName(text); Assert.NotNull(tname); Assert.Equal(SyntaxKind.PointerType, tname.Kind()); Assert.Equal(text, tname.ToString()); var name = (NameSyntax)((PointerTypeSyntax)tname).ElementType; Assert.Equal(SyntaxKind.IdentifierName, name.Kind()); Assert.False(name.IsMissing); Assert.Equal(0, name.Errors().Length); } [Fact] public void TestPointerTypeNameWithMultipleAsterisks() { var text = "goo***"; var tname = ParseTypeName(text); Assert.NotNull(tname); Assert.Equal(text, tname.ToString()); Assert.Equal(SyntaxKind.PointerType, tname.Kind()); // check depth of pointer defers int depth = 0; while (tname.Kind() == SyntaxKind.PointerType) { tname = ((PointerTypeSyntax)tname).ElementType; depth++; } Assert.Equal(3, depth); var name = (NameSyntax)tname; Assert.Equal(SyntaxKind.IdentifierName, name.Kind()); Assert.False(name.IsMissing); Assert.Equal(0, name.Errors().Length); } [Fact] public void TestArrayTypeName() { var text = "goo[]"; var tname = ParseTypeName(text); Assert.NotNull(tname); Assert.Equal(text, tname.ToString()); Assert.Equal(SyntaxKind.ArrayType, tname.Kind()); var array = (ArrayTypeSyntax)tname; Assert.Equal(1, array.RankSpecifiers.Count); Assert.Equal(1, array.RankSpecifiers[0].Sizes.Count); Assert.Equal(0, array.RankSpecifiers[0].Sizes.SeparatorCount); Assert.Equal(1, array.RankSpecifiers[0].Rank); var name = (NameSyntax)array.ElementType; Assert.Equal(SyntaxKind.IdentifierName, name.Kind()); Assert.False(name.IsMissing); Assert.Equal(0, name.Errors().Length); } [Fact] public void TestMultiDimensionalArrayTypeName() { var text = "goo[,,]"; var tname = ParseTypeName(text); Assert.NotNull(tname); Assert.Equal(text, tname.ToString()); Assert.Equal(SyntaxKind.ArrayType, tname.Kind()); var array = (ArrayTypeSyntax)tname; Assert.Equal(1, array.RankSpecifiers.Count); Assert.Equal(3, array.RankSpecifiers[0].Sizes.Count); Assert.Equal(2, array.RankSpecifiers[0].Sizes.SeparatorCount); Assert.Equal(3, array.RankSpecifiers[0].Rank); var name = (NameSyntax)array.ElementType; Assert.Equal(SyntaxKind.IdentifierName, name.Kind()); Assert.False(name.IsMissing); Assert.Equal(0, name.Errors().Length); } [Fact] public void TestMultiRankedArrayTypeName() { var text = "goo[][,][,,]"; var tname = ParseTypeName(text); Assert.NotNull(tname); Assert.Equal(text, tname.ToString()); Assert.Equal(SyntaxKind.ArrayType, tname.Kind()); var array = (ArrayTypeSyntax)tname; Assert.Equal(3, array.RankSpecifiers.Count); Assert.Equal(1, array.RankSpecifiers[0].Sizes.Count); Assert.Equal(0, array.RankSpecifiers[0].Sizes.SeparatorCount); Assert.Equal(1, array.RankSpecifiers[0].Rank); Assert.Equal(2, array.RankSpecifiers[1].Sizes.Count); Assert.Equal(1, array.RankSpecifiers[1].Sizes.SeparatorCount); Assert.Equal(2, array.RankSpecifiers[1].Rank); Assert.Equal(3, array.RankSpecifiers[2].Sizes.Count); Assert.Equal(2, array.RankSpecifiers[2].Sizes.SeparatorCount); Assert.Equal(3, array.RankSpecifiers[2].Rank); var name = (NameSyntax)array.ElementType; Assert.Equal(SyntaxKind.IdentifierName, name.Kind()); Assert.False(name.IsMissing); Assert.Equal(0, name.Errors().Length); } [Fact] public void TestVarianceInNameBad() { var text = "goo<in bar>"; var tname = ParseName(text); Assert.NotNull(tname); Assert.Equal(text, tname.ToString()); Assert.Equal(SyntaxKind.GenericName, tname.Kind()); var gname = (GenericNameSyntax)tname; Assert.Equal("goo", gname.Identifier.ToString()); Assert.False(gname.IsUnboundGenericName); Assert.Equal(1, gname.TypeArgumentList.Arguments.Count); Assert.NotNull(gname.TypeArgumentList.Arguments[0]); var arg = gname.TypeArgumentList.Arguments[0]; Assert.Equal(SyntaxKind.IdentifierName, arg.Kind()); Assert.True(arg.ContainsDiagnostics); Assert.Equal(1, arg.Errors().Length); Assert.Equal((int)ErrorCode.ERR_IllegalVarianceSyntax, arg.Errors()[0].Code); Assert.Equal(text, tname.ToString()); } [Fact] public void TestAttributeInNameBad() { var text = "goo<[My]bar>"; var tname = ParseName(text); Assert.NotNull(tname); Assert.Equal(text, tname.ToString()); Assert.Equal(SyntaxKind.GenericName, tname.Kind()); var gname = (GenericNameSyntax)tname; Assert.Equal("goo", gname.Identifier.ToString()); Assert.False(gname.IsUnboundGenericName); Assert.Equal(1, gname.TypeArgumentList.Arguments.Count); Assert.NotNull(gname.TypeArgumentList.Arguments[0]); var arg = gname.TypeArgumentList.Arguments[0]; Assert.Equal(SyntaxKind.IdentifierName, arg.Kind()); Assert.True(arg.ContainsDiagnostics); Assert.Equal(1, arg.Errors().Length); Assert.Equal((int)ErrorCode.ERR_TypeExpected, arg.Errors()[0].Code); Assert.Equal(text, tname.ToString()); } [WorkItem(7177, "https://github.com/dotnet/roslyn/issues/7177")] [Fact] public void TestConstantInGenericNameBad() { var text = "goo<0>"; var tname = ParseName(text); Assert.NotNull(tname); Assert.Equal(text, tname.ToString()); Assert.Equal(SyntaxKind.GenericName, tname.Kind()); var gname = (GenericNameSyntax)tname; Assert.Equal("goo", gname.Identifier.ToString()); Assert.False(gname.IsUnboundGenericName); Assert.Equal(1, gname.TypeArgumentList.Arguments.Count); Assert.NotNull(gname.TypeArgumentList.Arguments[0]); var arg = gname.TypeArgumentList.Arguments[0]; Assert.Equal(SyntaxKind.IdentifierName, arg.Kind()); Assert.True(arg.ContainsDiagnostics); Assert.Equal(1, arg.Errors().Length); Assert.Equal((int)ErrorCode.ERR_TypeExpected, arg.Errors()[0].Code); Assert.Equal(text, tname.ToString()); } [WorkItem(7177, "https://github.com/dotnet/roslyn/issues/7177")] [Fact] public void TestConstantInGenericNamePartiallyBad() { var text = "goo<0,bool>"; var tname = ParseName(text); Assert.NotNull(tname); Assert.Equal(text, tname.ToString()); Assert.Equal(SyntaxKind.GenericName, tname.Kind()); var gname = (GenericNameSyntax)tname; Assert.Equal("goo", gname.Identifier.ToString()); Assert.False(gname.IsUnboundGenericName); Assert.Equal(2, gname.TypeArgumentList.Arguments.Count); Assert.NotNull(gname.TypeArgumentList.Arguments[0]); Assert.NotNull(gname.TypeArgumentList.Arguments[1]); var arg = gname.TypeArgumentList.Arguments[0]; Assert.Equal(SyntaxKind.IdentifierName, arg.Kind()); Assert.True(arg.ContainsDiagnostics); Assert.Equal(1, arg.Errors().Length); Assert.Equal((int)ErrorCode.ERR_TypeExpected, arg.Errors()[0].Code); var arg2 = gname.TypeArgumentList.Arguments[1]; Assert.Equal(SyntaxKind.PredefinedType, arg2.Kind()); Assert.False(arg2.ContainsDiagnostics); Assert.Equal(0, arg2.Errors().Length); Assert.Equal(text, tname.ToString()); } [WorkItem(7177, "https://github.com/dotnet/roslyn/issues/7177")] [Fact] public void TestKeywordInGenericNameBad() { var text = "goo<static>"; var tname = ParseName(text); Assert.NotNull(tname); Assert.Equal(text, tname.ToString()); Assert.Equal(SyntaxKind.GenericName, tname.Kind()); var gname = (GenericNameSyntax)tname; Assert.Equal("goo", gname.Identifier.ToString()); Assert.False(gname.IsUnboundGenericName); Assert.Equal(1, gname.TypeArgumentList.Arguments.Count); Assert.NotNull(gname.TypeArgumentList.Arguments[0]); var arg = gname.TypeArgumentList.Arguments[0]; Assert.Equal(SyntaxKind.IdentifierName, arg.Kind()); Assert.True(arg.ContainsDiagnostics); Assert.Equal(1, arg.Errors().Length); Assert.Equal((int)ErrorCode.ERR_TypeExpected, arg.Errors()[0].Code); Assert.Equal(text, tname.ToString()); } [Fact] public void TestAttributeAndVarianceInNameBad() { var text = "goo<[My]in bar>"; var tname = ParseName(text); Assert.NotNull(tname); Assert.Equal(text, tname.ToString()); Assert.Equal(SyntaxKind.GenericName, tname.Kind()); var gname = (GenericNameSyntax)tname; Assert.Equal("goo", gname.Identifier.ToString()); Assert.False(gname.IsUnboundGenericName); Assert.Equal(1, gname.TypeArgumentList.Arguments.Count); Assert.NotNull(gname.TypeArgumentList.Arguments[0]); var arg = gname.TypeArgumentList.Arguments[0]; Assert.Equal(SyntaxKind.IdentifierName, arg.Kind()); Assert.True(arg.ContainsDiagnostics); Assert.Equal(2, arg.Errors().Length); Assert.Equal((int)ErrorCode.ERR_TypeExpected, arg.Errors()[0].Code); Assert.Equal((int)ErrorCode.ERR_IllegalVarianceSyntax, arg.Errors()[1].Code); Assert.Equal(text, tname.ToString()); } [WorkItem(545778, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545778")] [Fact] public void TestFormattingCharacter() { var text = "\u0915\u094d\u200d\u0937"; var tok = SyntaxFactory.ParseToken(text); Assert.NotEqual(default, tok); Assert.Equal(text, tok.ToString()); Assert.NotEqual(text, tok.ValueText); Assert.Equal("\u0915\u094d\u0937", tok.ValueText); //formatting character \u200d removed Assert.True(SyntaxFacts.ContainsDroppedIdentifierCharacters(text)); Assert.False(SyntaxFacts.ContainsDroppedIdentifierCharacters(tok.ValueText)); } [WorkItem(959148, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/959148")] [Fact] public void TestSoftHyphen() { var text = "x\u00ady"; var tok = SyntaxFactory.ParseToken(text); Assert.NotEqual(default, tok); Assert.Equal(text, tok.ToString()); Assert.NotEqual(text, tok.ValueText); Assert.Equal("xy", tok.ValueText); // formatting character SOFT HYPHEN (U+00AD) removed Assert.True(SyntaxFacts.ContainsDroppedIdentifierCharacters(text)); Assert.False(SyntaxFacts.ContainsDroppedIdentifierCharacters(tok.ValueText)); } [WorkItem(545778, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545778")] [Fact] public void ContainsDroppedIdentifierCharacters() { Assert.False(SyntaxFacts.ContainsDroppedIdentifierCharacters(null)); Assert.False(SyntaxFacts.ContainsDroppedIdentifierCharacters("")); Assert.False(SyntaxFacts.ContainsDroppedIdentifierCharacters("a")); Assert.False(SyntaxFacts.ContainsDroppedIdentifierCharacters("a@")); Assert.True(SyntaxFacts.ContainsDroppedIdentifierCharacters("@")); Assert.True(SyntaxFacts.ContainsDroppedIdentifierCharacters("@a")); Assert.True(SyntaxFacts.ContainsDroppedIdentifierCharacters("\u200d")); Assert.True(SyntaxFacts.ContainsDroppedIdentifierCharacters("a\u200d")); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/67277")] public void ParseGenericNameInvocationWithOmittedTypeArguments() { var source = """ class C { void M<T1, T2>() { M<,>(); } } """; UsingTree(source); N(SyntaxKind.CompilationUnit); { N(SyntaxKind.ClassDeclaration); { N(SyntaxKind.ClassKeyword); N(SyntaxKind.IdentifierToken, "C"); N(SyntaxKind.OpenBraceToken); N(SyntaxKind.MethodDeclaration); { N(SyntaxKind.PredefinedType); { N(SyntaxKind.VoidKeyword); } N(SyntaxKind.IdentifierToken, "M"); N(SyntaxKind.TypeParameterList); { N(SyntaxKind.LessThanToken); N(SyntaxKind.TypeParameter); { N(SyntaxKind.IdentifierToken, "T1"); } N(SyntaxKind.CommaToken); N(SyntaxKind.TypeParameter); { N(SyntaxKind.IdentifierToken, "T2"); } N(SyntaxKind.GreaterThanToken); } N(SyntaxKind.ParameterList); { N(SyntaxKind.OpenParenToken); N(SyntaxKind.CloseParenToken); } N(SyntaxKind.Block); { N(SyntaxKind.OpenBraceToken); N(SyntaxKind.ExpressionStatement); { N(SyntaxKind.InvocationExpression); { N(SyntaxKind.GenericName); { N(SyntaxKind.IdentifierToken, "M"); N(SyntaxKind.TypeArgumentList); { N(SyntaxKind.LessThanToken); N(SyntaxKind.OmittedTypeArgument); { N(SyntaxKind.OmittedTypeArgumentToken); } N(SyntaxKind.CommaToken); N(SyntaxKind.OmittedTypeArgument); { N(SyntaxKind.OmittedTypeArgumentToken); } N(SyntaxKind.GreaterThanToken); } } N(SyntaxKind.ArgumentList); { N(SyntaxKind.OpenParenToken); N(SyntaxKind.CloseParenToken); } } N(SyntaxKind.SemicolonToken); } N(SyntaxKind.CloseBraceToken); } } N(SyntaxKind.CloseBraceToken); } N(SyntaxKind.EndOfFileToken); } EOF(); CreateCompilation(source).VerifyDiagnostics( // (5,9): error CS0305: Using the generic method group 'M' requires 2 type arguments // M<,>(); Diagnostic(ErrorCode.ERR_BadArity, "M<,>").WithArguments("M", "method group", "2").WithLocation(5, 9)); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/67277")] public void ParseGenericNameInvocationWithOmittedTypeArguments_CSharp1() { var source = """ class C { void M<T1, T2>() { M<,>(); } } """; UsingTree(source, TestOptions.Regular1, // (5,10): error CS8022: Feature 'generics' is not available in C# 1. Please use language version 2 or greater. // M<,>(); Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion1, "<").WithArguments("generics", "2").WithLocation(5, 10)); N(SyntaxKind.CompilationUnit); { N(SyntaxKind.ClassDeclaration); { N(SyntaxKind.ClassKeyword); N(SyntaxKind.IdentifierToken, "C"); N(SyntaxKind.OpenBraceToken); N(SyntaxKind.MethodDeclaration); { N(SyntaxKind.PredefinedType); { N(SyntaxKind.VoidKeyword); } N(SyntaxKind.IdentifierToken, "M"); N(SyntaxKind.TypeParameterList); { N(SyntaxKind.LessThanToken); N(SyntaxKind.TypeParameter); { N(SyntaxKind.IdentifierToken, "T1"); } N(SyntaxKind.CommaToken); N(SyntaxKind.TypeParameter); { N(SyntaxKind.IdentifierToken, "T2"); } N(SyntaxKind.GreaterThanToken); } N(SyntaxKind.ParameterList); { N(SyntaxKind.OpenParenToken); N(SyntaxKind.CloseParenToken); } N(SyntaxKind.Block); { N(SyntaxKind.OpenBraceToken); N(SyntaxKind.ExpressionStatement); { N(SyntaxKind.InvocationExpression); { N(SyntaxKind.GenericName); { N(SyntaxKind.IdentifierToken, "M"); N(SyntaxKind.TypeArgumentList); { N(SyntaxKind.LessThanToken); N(SyntaxKind.OmittedTypeArgument); { N(SyntaxKind.OmittedTypeArgumentToken); } N(SyntaxKind.CommaToken); N(SyntaxKind.OmittedTypeArgument); { N(SyntaxKind.OmittedTypeArgumentToken); } N(SyntaxKind.GreaterThanToken); } } N(SyntaxKind.ArgumentList); { N(SyntaxKind.OpenParenToken); N(SyntaxKind.CloseParenToken); } } N(SyntaxKind.SemicolonToken); } N(SyntaxKind.CloseBraceToken); } } N(SyntaxKind.CloseBraceToken); } N(SyntaxKind.EndOfFileToken); } EOF(); CreateCompilation(source, parseOptions: TestOptions.Regular1).VerifyDiagnostics( // (3,11): error CS8022: Feature 'generics' is not available in C# 1. Please use language version 2 or greater. // void M<T1, T2>() Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion1, "<").WithArguments("generics", "2").WithLocation(3, 11), // (5,9): error CS0305: Using the generic method group 'M' requires 2 type arguments // M<,>(); Diagnostic(ErrorCode.ERR_BadArity, "M<,>").WithArguments("M", "method group", "2").WithLocation(5, 9), // (5,10): error CS8022: Feature 'generics' is not available in C# 1. Please use language version 2 or greater. // M<,>(); Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion1, "<").WithArguments("generics", "2").WithLocation(5, 10)); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/67277")] public void ParseGenericNameInvocationWithOmittedTypeArguments2() { var source = """ class X<T> { } class C { void M<T1, T2>() { M<int,X<>>(); } } """; UsingTree(source); N(SyntaxKind.CompilationUnit); { N(SyntaxKind.ClassDeclaration); { N(SyntaxKind.ClassKeyword); N(SyntaxKind.IdentifierToken, "X"); N(SyntaxKind.TypeParameterList); { N(SyntaxKind.LessThanToken); N(SyntaxKind.TypeParameter); { N(SyntaxKind.IdentifierToken, "T"); } N(SyntaxKind.GreaterThanToken); } N(SyntaxKind.OpenBraceToken); N(SyntaxKind.CloseBraceToken); } N(SyntaxKind.ClassDeclaration); { N(SyntaxKind.ClassKeyword); N(SyntaxKind.IdentifierToken, "C"); N(SyntaxKind.OpenBraceToken); N(SyntaxKind.MethodDeclaration); { N(SyntaxKind.PredefinedType); { N(SyntaxKind.VoidKeyword); } N(SyntaxKind.IdentifierToken, "M"); N(SyntaxKind.TypeParameterList); { N(SyntaxKind.LessThanToken); N(SyntaxKind.TypeParameter); { N(SyntaxKind.IdentifierToken, "T1"); } N(SyntaxKind.CommaToken); N(SyntaxKind.TypeParameter); { N(SyntaxKind.IdentifierToken, "T2"); } N(SyntaxKind.GreaterThanToken); } N(SyntaxKind.ParameterList); { N(SyntaxKind.OpenParenToken); N(SyntaxKind.CloseParenToken); } N(SyntaxKind.Block); { N(SyntaxKind.OpenBraceToken); N(SyntaxKind.ExpressionStatement); { N(SyntaxKind.InvocationExpression); { N(SyntaxKind.GenericName); { N(SyntaxKind.IdentifierToken, "M"); N(SyntaxKind.TypeArgumentList); { N(SyntaxKind.LessThanToken); N(SyntaxKind.PredefinedType); { N(SyntaxKind.IntKeyword); } N(SyntaxKind.CommaToken); N(SyntaxKind.GenericName); { N(SyntaxKind.IdentifierToken, "X"); N(SyntaxKind.TypeArgumentList); { N(SyntaxKind.LessThanToken); N(SyntaxKind.OmittedTypeArgument); { N(SyntaxKind.OmittedTypeArgumentToken); } N(SyntaxKind.GreaterThanToken); } } N(SyntaxKind.GreaterThanToken); } } N(SyntaxKind.ArgumentList); { N(SyntaxKind.OpenParenToken); N(SyntaxKind.CloseParenToken); } } N(SyntaxKind.SemicolonToken); } N(SyntaxKind.CloseBraceToken); } } N(SyntaxKind.CloseBraceToken); } N(SyntaxKind.EndOfFileToken); } EOF(); CreateCompilation(source).VerifyDiagnostics( // (9,15): error CS7003: Unexpected use of an unbound generic name // M<int,X<>>(); Diagnostic(ErrorCode.ERR_UnexpectedUnboundGenericName, "X<>").WithLocation(9, 15)); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/67277")] public void ParseGenericNameInvocationWithOmittedTypeArguments3() { var source = """ class X<T> { } class C { void M<T1, T2>() { M<X<>, int>(); } } """; UsingTree(source); N(SyntaxKind.CompilationUnit); { N(SyntaxKind.ClassDeclaration); { N(SyntaxKind.ClassKeyword); N(SyntaxKind.IdentifierToken, "X"); N(SyntaxKind.TypeParameterList); { N(SyntaxKind.LessThanToken); N(SyntaxKind.TypeParameter); { N(SyntaxKind.IdentifierToken, "T"); } N(SyntaxKind.GreaterThanToken); } N(SyntaxKind.OpenBraceToken); N(SyntaxKind.CloseBraceToken); } N(SyntaxKind.ClassDeclaration); { N(SyntaxKind.ClassKeyword); N(SyntaxKind.IdentifierToken, "C"); N(SyntaxKind.OpenBraceToken); N(SyntaxKind.MethodDeclaration); { N(SyntaxKind.PredefinedType); { N(SyntaxKind.VoidKeyword); } N(SyntaxKind.IdentifierToken, "M"); N(SyntaxKind.TypeParameterList); { N(SyntaxKind.LessThanToken); N(SyntaxKind.TypeParameter); { N(SyntaxKind.IdentifierToken, "T1"); } N(SyntaxKind.CommaToken); N(SyntaxKind.TypeParameter); { N(SyntaxKind.IdentifierToken, "T2"); } N(SyntaxKind.GreaterThanToken); } N(SyntaxKind.ParameterList); { N(SyntaxKind.OpenParenToken); N(SyntaxKind.CloseParenToken); } N(SyntaxKind.Block); { N(SyntaxKind.OpenBraceToken); N(SyntaxKind.ExpressionStatement); { N(SyntaxKind.InvocationExpression); { N(SyntaxKind.GenericName); { N(SyntaxKind.IdentifierToken, "M"); N(SyntaxKind.TypeArgumentList); { N(SyntaxKind.LessThanToken); N(SyntaxKind.GenericName); { N(SyntaxKind.IdentifierToken, "X"); N(SyntaxKind.TypeArgumentList); { N(SyntaxKind.LessThanToken); N(SyntaxKind.OmittedTypeArgument); { N(SyntaxKind.OmittedTypeArgumentToken); } N(SyntaxKind.GreaterThanToken); } } N(SyntaxKind.CommaToken); N(SyntaxKind.PredefinedType); { N(SyntaxKind.IntKeyword); } N(SyntaxKind.GreaterThanToken); } } N(SyntaxKind.ArgumentList); { N(SyntaxKind.OpenParenToken); N(SyntaxKind.CloseParenToken); } } N(SyntaxKind.SemicolonToken); } N(SyntaxKind.CloseBraceToken); } } N(SyntaxKind.CloseBraceToken); } N(SyntaxKind.EndOfFileToken); } EOF(); CreateCompilation(source).VerifyDiagnostics( // (9,11): error CS7003: Unexpected use of an unbound generic name // M<X<>, int>(); Diagnostic(ErrorCode.ERR_UnexpectedUnboundGenericName, "X<>").WithLocation(9, 11)); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/67277")] public void ParseGenericNameInvocationWithOmittedTypeArguments4() { var source = """ class X<T> { } class Y<A, B> { } class C { void M<T1, T2>() { M<X<>, Y<,>>(); } } """; UsingTree(source); N(SyntaxKind.CompilationUnit); { N(SyntaxKind.ClassDeclaration); { N(SyntaxKind.ClassKeyword); N(SyntaxKind.IdentifierToken, "X"); N(SyntaxKind.TypeParameterList); { N(SyntaxKind.LessThanToken); N(SyntaxKind.TypeParameter); { N(SyntaxKind.IdentifierToken, "T"); } N(SyntaxKind.GreaterThanToken); } N(SyntaxKind.OpenBraceToken); N(SyntaxKind.CloseBraceToken); } N(SyntaxKind.ClassDeclaration); { N(SyntaxKind.ClassKeyword); N(SyntaxKind.IdentifierToken, "Y"); N(SyntaxKind.TypeParameterList); { N(SyntaxKind.LessThanToken); N(SyntaxKind.TypeParameter); { N(SyntaxKind.IdentifierToken, "A"); } N(SyntaxKind.CommaToken); N(SyntaxKind.TypeParameter); { N(SyntaxKind.IdentifierToken, "B"); } N(SyntaxKind.GreaterThanToken); } N(SyntaxKind.OpenBraceToken); N(SyntaxKind.CloseBraceToken); } N(SyntaxKind.ClassDeclaration); { N(SyntaxKind.ClassKeyword); N(SyntaxKind.IdentifierToken, "C"); N(SyntaxKind.OpenBraceToken); N(SyntaxKind.MethodDeclaration); { N(SyntaxKind.PredefinedType); { N(SyntaxKind.VoidKeyword); } N(SyntaxKind.IdentifierToken, "M"); N(SyntaxKind.TypeParameterList); { N(SyntaxKind.LessThanToken); N(SyntaxKind.TypeParameter); { N(SyntaxKind.IdentifierToken, "T1"); } N(SyntaxKind.CommaToken); N(SyntaxKind.TypeParameter); { N(SyntaxKind.IdentifierToken, "T2"); } N(SyntaxKind.GreaterThanToken); } N(SyntaxKind.ParameterList); { N(SyntaxKind.OpenParenToken); N(SyntaxKind.CloseParenToken); } N(SyntaxKind.Block); { N(SyntaxKind.OpenBraceToken); N(SyntaxKind.ExpressionStatement); { N(SyntaxKind.InvocationExpression); { N(SyntaxKind.GenericName); { N(SyntaxKind.IdentifierToken, "M"); N(SyntaxKind.TypeArgumentList); { N(SyntaxKind.LessThanToken); N(SyntaxKind.GenericName); { N(SyntaxKind.IdentifierToken, "X"); N(SyntaxKind.TypeArgumentList); { N(SyntaxKind.LessThanToken); N(SyntaxKind.OmittedTypeArgument); { N(SyntaxKind.OmittedTypeArgumentToken); } N(SyntaxKind.GreaterThanToken); } } N(SyntaxKind.CommaToken); N(SyntaxKind.GenericName); { N(SyntaxKind.IdentifierToken, "Y"); N(SyntaxKind.TypeArgumentList); { N(SyntaxKind.LessThanToken); N(SyntaxKind.OmittedTypeArgument); { N(SyntaxKind.OmittedTypeArgumentToken); } N(SyntaxKind.CommaToken); N(SyntaxKind.OmittedTypeArgument); { N(SyntaxKind.OmittedTypeArgumentToken); } N(SyntaxKind.GreaterThanToken); } } N(SyntaxKind.GreaterThanToken); } } N(SyntaxKind.ArgumentList); { N(SyntaxKind.OpenParenToken); N(SyntaxKind.CloseParenToken); } } N(SyntaxKind.SemicolonToken); } N(SyntaxKind.CloseBraceToken); } } N(SyntaxKind.CloseBraceToken); } N(SyntaxKind.EndOfFileToken); } EOF(); CreateCompilation(source).VerifyDiagnostics( // (13,11): error CS7003: Unexpected use of an unbound generic name // M<X<>, Y<,>>(); Diagnostic(ErrorCode.ERR_UnexpectedUnboundGenericName, "X<>").WithLocation(13, 11), // (13,16): error CS7003: Unexpected use of an unbound generic name // M<X<>, Y<,>>(); Diagnostic(ErrorCode.ERR_UnexpectedUnboundGenericName, "Y<,>").WithLocation(13, 16)); } [Fact] public void ParseGlobalAliasQualifiedNameAfterConditionalExpression() { UsingExpression("x is X ? global::X.Y.Z : default"); N(SyntaxKind.ConditionalExpression); { N(SyntaxKind.IsExpression); { N(SyntaxKind.IdentifierName); { N(SyntaxKind.IdentifierToken, "x"); } N(SyntaxKind.IsKeyword); N(SyntaxKind.IdentifierName); { N(SyntaxKind.IdentifierToken, "X"); } } N(SyntaxKind.QuestionToken); N(SyntaxKind.SimpleMemberAccessExpression); { N(SyntaxKind.SimpleMemberAccessExpression); { N(SyntaxKind.AliasQualifiedName); { N(SyntaxKind.IdentifierName); { N(SyntaxKind.GlobalKeyword); } N(SyntaxKind.ColonColonToken); N(SyntaxKind.IdentifierName); { N(SyntaxKind.IdentifierToken, "X"); } } N(SyntaxKind.DotToken); N(SyntaxKind.IdentifierName); { N(SyntaxKind.IdentifierToken, "Y"); } } N(SyntaxKind.DotToken); N(SyntaxKind.IdentifierName); { N(SyntaxKind.IdentifierToken, "Z"); } } N(SyntaxKind.ColonToken); N(SyntaxKind.DefaultLiteralExpression); { N(SyntaxKind.DefaultKeyword); } } EOF(); } [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/71379")] public void ParseGenericNameInvocationWithPartiallyOmittedTypeArguments() { // Tests for partially closed generic type names where the first type argument is missing var source = """ class C { void M<T1, T2>() { M<,int>(); // First argument omitted M<string,>(); // Second argument omitted M<,int,>(); // First and third arguments omitted (if we had 3 params) } } """; UsingTree(source, // (5,11): error CS1031: Type expected // M<,int>(); // First argument omitted Diagnostic(ErrorCode.ERR_TypeExpected, ",").WithLocation(5, 11), // (6,18): error CS1031: Type expected // M<string,>(); // Second argument omitted Diagnostic(ErrorCode.ERR_TypeExpected, ">").WithLocation(6, 18), // (7,11): error CS1031: Type expected // M<,int,>(); // First and third arguments omitted (if we had 3 params) Diagnostic(ErrorCode.ERR_TypeExpected, ",").WithLocation(7, 11), // (7,16): error CS1031: Type expected // M<,int,>(); // First and third arguments omitted (if we had 3 params) Diagnostic(ErrorCode.ERR_TypeExpected, ">").WithLocation(7, 16)); N(SyntaxKind.CompilationUnit); { N(SyntaxKind.ClassDeclaration); { N(SyntaxKind.ClassKeyword); N(SyntaxKind.IdentifierToken, "C"); N(SyntaxKind.OpenBraceToken); N(SyntaxKind.MethodDeclaration); { N(SyntaxKind.PredefinedType); { N(SyntaxKind.VoidKeyword); } N(SyntaxKind.IdentifierToken, "M"); N(SyntaxKind.TypeParameterList); { N(SyntaxKind.LessThanToken); N(SyntaxKind.TypeParameter); { N(SyntaxKind.IdentifierToken, "T1"); } N(SyntaxKind.CommaToken); N(SyntaxKind.TypeParameter); { N(SyntaxKind.IdentifierToken, "T2"); } N(SyntaxKind.GreaterThanToken); } N(SyntaxKind.ParameterList); { N(SyntaxKind.OpenParenToken); N(SyntaxKind.CloseParenToken); } N(SyntaxKind.Block); { N(SyntaxKind.OpenBraceToken); // M<,int>() N(SyntaxKind.ExpressionStatement); { N(SyntaxKind.InvocationExpression); { N(SyntaxKind.GenericName); { N(SyntaxKind.IdentifierToken, "M"); N(SyntaxKind.TypeArgumentList); { N(SyntaxKind.LessThanToken); M(SyntaxKind.IdentifierName); { M(SyntaxKind.IdentifierToken); } N(SyntaxKind.CommaToken); N(SyntaxKind.PredefinedType); { N(SyntaxKind.IntKeyword); } N(SyntaxKind.GreaterThanToken); } } N(SyntaxKind.ArgumentList); { N(SyntaxKind.OpenParenToken); N(SyntaxKind.CloseParenToken); } } N(SyntaxKind.SemicolonToken); } // M<string,>() N(SyntaxKind.ExpressionStatement); { N(SyntaxKind.InvocationExpression); { N(SyntaxKind.GenericName); { N(SyntaxKind.IdentifierToken, "M"); N(SyntaxKind.TypeArgumentList); { N(SyntaxKind.LessThanToken); N(SyntaxKind.PredefinedType); { N(SyntaxKind.StringKeyword); } N(SyntaxKind.CommaToken); M(SyntaxKind.IdentifierName); { M(SyntaxKind.IdentifierToken); } N(SyntaxKind.GreaterThanToken); } } N(SyntaxKind.ArgumentList); { N(SyntaxKind.OpenParenToken); N(SyntaxKind.CloseParenToken); } } N(SyntaxKind.SemicolonToken); } // M<,int,>() N(SyntaxKind.ExpressionStatement); { N(SyntaxKind.InvocationExpression); { N(SyntaxKind.GenericName); { N(SyntaxKind.IdentifierToken, "M"); N(SyntaxKind.TypeArgumentList); { N(SyntaxKind.LessThanToken); M(SyntaxKind.IdentifierName); { M(SyntaxKind.IdentifierToken); } N(SyntaxKind.CommaToken); N(SyntaxKind.PredefinedType); { N(SyntaxKind.IntKeyword); } N(SyntaxKind.CommaToken); M(SyntaxKind.IdentifierName); { M(SyntaxKind.IdentifierToken); } N(SyntaxKind.GreaterThanToken); } } N(SyntaxKind.ArgumentList); { N(SyntaxKind.OpenParenToken); N(SyntaxKind.CloseParenToken); } } N(SyntaxKind.SemicolonToken); } N(SyntaxKind.CloseBraceToken); } } N(SyntaxKind.CloseBraceToken); } N(SyntaxKind.EndOfFileToken); } EOF(); } } }