From 13f716d97fcb1e0fa3d4187dc8159605eeec30a9 Mon Sep 17 00:00:00 2001 From: AlekseyTs Date: Mon, 7 Nov 2022 14:26:06 -0800 Subject: [PATCH 1/3] Refine error recovery in the parser around top level statements Fixes #55969. --- .../CSharp/Portable/Parser/LanguageParser.cs | 81 +- .../Semantics/FunctionPointerTests.cs | 22 +- .../Test/Semantic/Semantics/LookupTests.cs | 6 +- .../Test/Semantic/Semantics/RecordTests.cs | 22 +- .../Test/Semantic/Semantics/RefFieldTests.cs | 10 +- .../Semantics/TopLevelStatementsTests.cs | 106 +- .../Test/Symbol/Symbols/Source/RecordTests.cs | 98 +- .../Syntax/LexicalAndXml/PreprocessorTests.cs | 16 - .../Syntax/Parsing/DeclarationParsingTests.cs | 52 +- .../Parsing/DeclarationScopeParsingTests.cs | 24 +- .../Parsing/FileModifierParsingTests.cs | 227 +++- .../Syntax/Parsing/FunctionPointerTests.cs | 40 +- .../Syntax/Parsing/ParserErrorMessageTests.cs | 58 +- .../Parsing/ParsingErrorRecoveryTests.cs | 16 +- .../Test/Syntax/Parsing/RecordParsing.cs | 60 +- .../Test/Syntax/Parsing/RoundTrippingTests.cs | 2 +- .../Parsing/TopLevelStatementsParsingTests.cs | 1119 +++++++++++++++-- .../SymbolCompletionProviderTests.cs | 80 +- .../CSharpTest/Formatting/FormattingTests.cs | 2 +- .../Formatting/FormattingTriviaTests.cs | 2 +- 20 files changed, 1741 insertions(+), 302 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs b/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs index 422bd2652bf83..06397133f0df0 100644 --- a/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs +++ b/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs @@ -2584,6 +2584,15 @@ private MemberDeclarationSyntax ParseMemberDeclarationOrStatementCore(SyntaxKind TypeParameterListSyntax typeParameterListOpt; this.ParseMemberName(out explicitInterfaceOpt, out identifierOrThisOpt, out typeParameterListOpt, isEvent: false); + if (!haveModifiers && !haveAttributes && !IsScript && + explicitInterfaceOpt == null && identifierOrThisOpt == null && typeParameterListOpt == null && + !type.IsMissing && type.Kind != SyntaxKind.RefType && + !isFollowedByPossibleUsingDirective() && + tryParseLocalDeclarationStatementFromStartPoint(attributes, ref afterAttributesPoint, out result)) + { + return result; + } + // First, check if we got absolutely nothing. If so, then // We need to consume a bad member and try again. if (IsNoneOrIncompleteMember(parentKind, attributes, modifiers, type, explicitInterfaceOpt, identifierOrThisOpt, typeParameterListOpt, out result)) @@ -2614,14 +2623,50 @@ private MemberDeclarationSyntax ParseMemberDeclarationOrStatementCore(SyntaxKind return result; } - // treat anything else as a method. - - if (!IsScript && explicitInterfaceOpt is null && - tryParseLocalDeclarationStatementFromStartPoint(attributes, ref afterAttributesPoint, out result)) + if (!IsScript) { - return result; + if (explicitInterfaceOpt is null && + tryParseLocalDeclarationStatementFromStartPoint(attributes, ref afterAttributesPoint, out result)) + { + return result; + } + + if (!haveModifiers) + { + var resetOnFailurePoint = this.GetResetPoint(); + try + { + this.Reset(ref afterAttributesPoint); + + if (this.IsPossibleStatement(acceptAccessibilityMods: false)) + { + var saveTerm = _termState; + _termState |= TerminatorState.IsPossibleStatementStartOrStop; // partial statements can abort if a new statement starts + bool wasInAsync = IsInAsync; + IsInAsync = true; // We are implicitly in an async context + + var statement = this.ParseStatementCore(attributes, isGlobal: true); + + IsInAsync = wasInAsync; + _termState = saveTerm; + + if (statement is not null) + { + return CheckTopLevelStatementsFeatureAvailability(_syntaxFactory.GlobalStatement(statement)); + } + } + + this.Reset(ref resetOnFailurePoint); + } + finally + { + this.Release(ref resetOnFailurePoint); + } + } } + // treat anything else as a method. + return this.ParseMethodDeclaration(attributes, modifiers, type, explicitInterfaceOpt, identifierOrThisOpt, typeParameterListOpt); } finally @@ -2700,6 +2745,32 @@ static bool isAcceptableNonDeclarationStatement(StatementSyntax statement, bool return true; } } + + bool isFollowedByPossibleUsingDirective() + { + if (CurrentToken.Kind == SyntaxKind.UsingKeyword) + { + return !IsPossibleTopLevelUsingLocalDeclarationStatement(); + } + + if (CurrentToken.ContextualKind == SyntaxKind.GlobalKeyword && this.PeekToken(1).Kind == SyntaxKind.UsingKeyword) + { + var resetPoint = this.GetResetPoint(); + try + { + // Skip 'global' keyword + EatToken(); + return !IsPossibleTopLevelUsingLocalDeclarationStatement(); + } + finally + { + this.Reset(ref resetPoint); + this.Release(ref resetPoint); + } + } + + return false; + } } private bool IsMisplacedModifier(SyntaxListBuilder modifiers, SyntaxList attributes, TypeSyntax type, out MemberDeclarationSyntax result) diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/FunctionPointerTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/FunctionPointerTests.cs index 5bcb46fe9ad86..c90ce66ebfa93 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/FunctionPointerTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/FunctionPointerTests.cs @@ -33,26 +33,24 @@ public void UsingAliasTest() using s = delegate*;"); comp.VerifyDiagnostics( - // (2,26): error CS8805: Program using top-level statements must be an executable. - // using s = delegate*; - Diagnostic(ErrorCode.ERR_SimpleProgramNotAnExecutable, ";").WithLocation(2, 26), - // (2,1): hidden CS8019: Unnecessary using directive. - // using s = delegate*; - Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using s = ").WithLocation(2, 1), // (2,11): error CS1041: Identifier expected; 'delegate' is a keyword // using s = delegate*; Diagnostic(ErrorCode.ERR_IdentifierExpectedKW, "delegate").WithArguments("", "delegate").WithLocation(2, 11), - // (2,25): error CS0116: A namespace cannot directly contain members such as fields or methods + // (2,26): error CS1001: Identifier expected // using s = delegate*; - Diagnostic(ErrorCode.ERR_NamespaceUnexpected, ">").WithLocation(2, 25), + Diagnostic(ErrorCode.ERR_IdentifierExpected, ";").WithLocation(2, 26), // (2,7): warning CS8981: The type name 's' only contains lower-cased ascii characters. Such names may become reserved for the language. // using s = delegate*; Diagnostic(ErrorCode.WRN_LowerCaseTypeName, "s").WithArguments("s").WithLocation(2, 7), - - // See same-named test in TopLevelStatementsParsingTests, there is a single top-level statement in the tree and it is an empty statement. - // (2,26): error CS8937: At least one top-level statement must be non-empty. + // (2,11): error CS8805: Program using top-level statements must be an executable. + // using s = delegate*; + Diagnostic(ErrorCode.ERR_SimpleProgramNotAnExecutable, "delegate*;").WithLocation(2, 11), + // (2,11): error CS0214: Pointers and fixed size buffers may only be used in an unsafe context + // using s = delegate*; + Diagnostic(ErrorCode.ERR_UnsafeNeeded, "delegate*").WithLocation(2, 11), + // (2,1): hidden CS8019: Unnecessary using directive. // using s = delegate*; - Diagnostic(ErrorCode.ERR_SimpleProgramIsEmpty, ";").WithLocation(2, 26) + Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using s = ").WithLocation(2, 1) ); } diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/LookupTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/LookupTests.cs index 0108de6ca3d42..90df90cae5f59 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/LookupTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/LookupTests.cs @@ -1403,7 +1403,7 @@ static void Main(string[] args) [Fact, WorkItem(546523, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/546523")] public void TestLookupSymbolsNestedNamespacesNotImportedByUsings_02() { - var usings = new[] { "using X;" }; + var usings = "using X;"; var source = @" @@ -1443,10 +1443,10 @@ public static void Main() } "; // Get the list of LookupSymbols at the location of the CSharpSyntaxNode - var actual_lookupSymbols = GetLookupSymbols(usings.ToString() + source, isScript: false); + var actual_lookupSymbols = GetLookupSymbols(usings + source, isScript: false); TestLookupSymbolsNestedNamespaces(actual_lookupSymbols); - actual_lookupSymbols = GetLookupSymbols(source, isScript: true, globalUsings: usings); + actual_lookupSymbols = GetLookupSymbols(source, isScript: true, globalUsings: new[] { usings }); TestLookupSymbolsNestedNamespaces(actual_lookupSymbols); Action validator = (module) => diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/RecordTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/RecordTests.cs index 5f71abe053438..9b966efd7c199 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/RecordTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/RecordTests.cs @@ -243,24 +243,30 @@ record class Point(int x, int y); "; var comp = CreateCompilation(src, parseOptions: TestOptions.Regular8, options: TestOptions.ReleaseDll); comp.VerifyDiagnostics( - // (2,1): error CS0116: A namespace cannot directly contain members such as fields or methods + // (2,1): error CS8400: Feature 'top-level statements' is not available in C# 8.0. Please use language version 9.0 or greater. + // record class Point(int x, int y); + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion8, "record ").WithArguments("top-level statements", "9.0").WithLocation(2, 1), + // (2,1): error CS8805: Program using top-level statements must be an executable. + // record class Point(int x, int y); + Diagnostic(ErrorCode.ERR_SimpleProgramNotAnExecutable, "record ").WithLocation(2, 1), + // (2,1): error CS0246: The type or namespace name 'record' could not be found (are you missing a using directive or an assembly reference?) // record class Point(int x, int y); - Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "record").WithLocation(2, 1), + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "record").WithArguments("record").WithLocation(2, 1), + // (2,8): error CS1001: Identifier expected + // record class Point(int x, int y); + Diagnostic(ErrorCode.ERR_IdentifierExpected, "class").WithLocation(2, 8), + // (2,8): error CS1002: ; expected + // record class Point(int x, int y); + Diagnostic(ErrorCode.ERR_SemicolonExpected, "class").WithLocation(2, 8), // (2,19): error CS1514: { expected // record class Point(int x, int y); Diagnostic(ErrorCode.ERR_LbraceExpected, "(").WithLocation(2, 19), // (2,19): error CS1513: } expected // record class Point(int x, int y); Diagnostic(ErrorCode.ERR_RbraceExpected, "(").WithLocation(2, 19), - // (2,19): error CS8400: Feature 'top-level statements' is not available in C# 8.0. Please use language version 9.0 or greater. - // record class Point(int x, int y); - Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion8, "(int x, int y);").WithArguments("top-level statements", "9.0").WithLocation(2, 19), // (2,19): error CS8803: Top-level statements must precede namespace and type declarations. // record class Point(int x, int y); Diagnostic(ErrorCode.ERR_TopLevelStatementAfterNamespaceOrType, "(int x, int y);").WithLocation(2, 19), - // (2,19): error CS8805: Program using top-level statements must be an executable. - // record class Point(int x, int y); - Diagnostic(ErrorCode.ERR_SimpleProgramNotAnExecutable, "(int x, int y);").WithLocation(2, 19), // (2,19): error CS0201: Only assignment, call, increment, decrement, await, and new object expressions can be used as a statement // record class Point(int x, int y); Diagnostic(ErrorCode.ERR_IllegalStatement, "(int x, int y)").WithLocation(2, 19), diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/RefFieldTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/RefFieldTests.cs index 99b7df676bb58..1f6817074ce0d 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/RefFieldTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/RefFieldTests.cs @@ -10937,9 +10937,15 @@ scoped readonly ref struct C { } "; var comp = CreateCompilation(source, parseOptions: TestOptions.Regular.WithLanguageVersion(langVersion)); comp.VerifyDiagnostics( - // (1,1): error CS0116: A namespace cannot directly contain members such as fields, methods or statements + // (1,1): error CS0246: The type or namespace name 'scoped' could not be found (are you missing a using directive or an assembly reference?) // scoped struct A { } - Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "scoped").WithLocation(1, 1), + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "scoped").WithArguments("scoped").WithLocation(1, 1), + // (1,8): error CS1001: Identifier expected + // scoped struct A { } + Diagnostic(ErrorCode.ERR_IdentifierExpected, "struct").WithLocation(1, 8), + // (1,8): error CS1002: ; expected + // scoped struct A { } + Diagnostic(ErrorCode.ERR_SemicolonExpected, "struct").WithLocation(1, 8), // (2,12): error CS1031: Type expected // scoped ref struct B { } Diagnostic(ErrorCode.ERR_TypeExpected, "struct").WithLocation(2, 12), diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/TopLevelStatementsTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/TopLevelStatementsTests.cs index 31e6832a75357..9f9b66b0594ce 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/TopLevelStatementsTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/TopLevelStatementsTests.cs @@ -4302,12 +4302,24 @@ interface I1 // (2,1): error CS0103: The name 'local' does not exist in the current context // local(); Diagnostic(ErrorCode.ERR_NameNotInContext, "local").WithArguments("local").WithLocation(2, 1), - // (4,6): error CS0540: '.I1.local()': containing type does not implement interface 'I1' + // (4,1): error CS1547: Keyword 'void' cannot be used in this context // void I1.local() - Diagnostic(ErrorCode.ERR_ClassDoesntImplementInterface, "I1").WithArguments(".I1.local()", "I1").WithLocation(4, 6), - // (4,9): error CS0116: A namespace cannot directly contain members such as fields or methods + Diagnostic(ErrorCode.ERR_NoVoidHere, "void").WithLocation(4, 1), + // (4,6): warning CS0168: The variable 'I1' is declared but never used // void I1.local() - Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "local").WithLocation(4, 9) + Diagnostic(ErrorCode.WRN_UnreferencedVar, "I1").WithArguments("I1").WithLocation(4, 6), + // (4,8): error CS1003: Syntax error, ',' expected + // void I1.local() + Diagnostic(ErrorCode.ERR_SyntaxError, ".").WithArguments(",").WithLocation(4, 8), + // (4,9): error CS1002: ; expected + // void I1.local() + Diagnostic(ErrorCode.ERR_SemicolonExpected, "local").WithLocation(4, 9), + // (4,9): error CS0103: The name 'local' does not exist in the current context + // void I1.local() + Diagnostic(ErrorCode.ERR_NameNotInContext, "local").WithArguments("local").WithLocation(4, 9), + // (4,16): error CS1002: ; expected + // void I1.local() + Diagnostic(ErrorCode.ERR_SemicolonExpected, "").WithLocation(4, 16) ); } @@ -8539,12 +8551,34 @@ public void Args_01() var text = @" #nullable enable System.Console.WriteLine(args.Length == 0 ? 0 : -args[0].Length); +System.Console.Write(""""); + +System.Console.Write(""""); "; var comp = CreateCompilation(text, options: TestOptions.DebugExe, parseOptions: DefaultParseOptions); CompileAndVerify(comp, expectedOutput: "0").VerifyDiagnostics(); var entryPoint = SynthesizedSimpleProgramEntryPointSymbol.GetSimpleProgramEntryPoint(comp); AssertEntryPointParameter(entryPoint); + + var tree = comp.SyntaxTrees.Single(); + var model = comp.GetSemanticModel(tree); + var invocations = tree.GetRoot().DescendantNodes().OfType().ToArray(); + + var symbols = model.LookupSymbols(invocations[0].Position, name: "args"); + Assert.Empty(symbols); + symbols = model.LookupSymbols(invocations[0].SpanStart, name: "args"); + Assert.Equal("System.String[] args", symbols.Single().ToTestDisplayString()); + + symbols = model.LookupSymbols(invocations[1].Position, name: "args"); + Assert.Equal("System.String[] args", symbols.Single().ToTestDisplayString()); + symbols = model.LookupSymbols(invocations[1].SpanStart, name: "args"); + Assert.Equal("System.String[] args", symbols.Single().ToTestDisplayString()); + + symbols = model.LookupSymbols(invocations[2].Position, name: "args"); + Assert.Equal("System.String[] args", symbols.Single().ToTestDisplayString()); + symbols = model.LookupSymbols(invocations[2].SpanStart, name: "args"); + Assert.Equal("System.String[] args", symbols.Single().ToTestDisplayString()); } [Fact] @@ -8591,6 +8625,70 @@ public void Args_04() CompileAndVerify(comp, expectedOutput: "Args_04", args: new[] { "Args_04" }).VerifyDiagnostics(); } + [Fact] + public void Args_05() + { + var text = @" +ar +"; + + var comp = CreateCompilation(text); + + var tree = comp.SyntaxTrees.Single(); + var model = comp.GetSemanticModel(tree); + var id = tree.GetRoot().DescendantNodes().OfType().Single(); + + for (int i = id.SpanStart; i <= id.Span.End; i++) + { + var symbols = model.LookupSymbols(i, name: "args"); + Assert.Equal("System.String[] args", symbols.Single().ToTestDisplayString()); + } + } + + [Fact] + public void Args_06() + { + var text = @" +ar +// See https://aka.ms/new-console-template for more information +Console.WriteLine(""Hello, World!""); +"; + + var comp = CreateCompilation(text); + + var tree = comp.SyntaxTrees.Single(); + var model = comp.GetSemanticModel(tree); + var id = tree.GetRoot().DescendantNodes().OfType().Where(id => id.Identifier.ValueText == "ar").Single(); + + for (int i = id.SpanStart; i <= id.Span.End; i++) + { + var symbols = model.LookupSymbols(i, name: "args"); + Assert.Equal("System.String[] args", symbols.Single().ToTestDisplayString()); + } + } + + [Fact] + public void Args_07() + { + var text = +@"// See https://aka.ms/new-console-template for more information +Console.WriteLine(""Hello, World!""); +ar +"; + + var comp = CreateCompilation(text); + + var tree = comp.SyntaxTrees.Single(); + var model = comp.GetSemanticModel(tree); + var id = tree.GetRoot().DescendantNodes().OfType().Where(id => id.Identifier.ValueText == "ar").Single(); + + for (int i = id.SpanStart; i <= id.Span.End; i++) + { + var symbols = model.LookupSymbols(i, name: "args"); + Assert.Equal("System.String[] args", symbols.Single().ToTestDisplayString()); + } + } + [Fact] public void Span_01() { diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/Source/RecordTests.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/Source/RecordTests.cs index 6a67850bdf48b..1544c24b7a660 100644 --- a/src/Compilers/CSharp/Test/Symbol/Symbols/Source/RecordTests.cs +++ b/src/Compilers/CSharp/Test/Symbol/Symbols/Source/RecordTests.cs @@ -1213,72 +1213,96 @@ data struct S1 { } data struct S2(int X, int Y);"; var comp = CreateCompilation(src, options: TestOptions.ReleaseDll); comp.VerifyDiagnostics( - // (3,14): error CS8805: Program using top-level statements must be an executable. - // data class C2(int X, int Y); - Diagnostic(ErrorCode.ERR_SimpleProgramNotAnExecutable, "(int X, int Y);").WithLocation(3, 14), - // (2,1): error CS0116: A namespace cannot directly contain members such as fields or methods + // (2,6): error CS1001: Identifier expected + // data class C1 { } + Diagnostic(ErrorCode.ERR_IdentifierExpected, "class").WithLocation(2, 6), + // (2,6): error CS1002: ; expected // data class C1 { } - Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "data").WithLocation(2, 1), - // (3,1): error CS0116: A namespace cannot directly contain members such as fields or methods + Diagnostic(ErrorCode.ERR_SemicolonExpected, "class").WithLocation(2, 6), + // (3,1): error CS8803: Top-level statements must precede namespace and type declarations. + // data class C2(int X, int Y); + Diagnostic(ErrorCode.ERR_TopLevelStatementAfterNamespaceOrType, "data ").WithLocation(3, 1), + // (3,6): error CS1001: Identifier expected + // data class C2(int X, int Y); + Diagnostic(ErrorCode.ERR_IdentifierExpected, "class").WithLocation(3, 6), + // (3,6): error CS1002: ; expected // data class C2(int X, int Y); - Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "data").WithLocation(3, 1), + Diagnostic(ErrorCode.ERR_SemicolonExpected, "class").WithLocation(3, 6), // (3,14): error CS1514: { expected // data class C2(int X, int Y); Diagnostic(ErrorCode.ERR_LbraceExpected, "(").WithLocation(3, 14), // (3,14): error CS1513: } expected // data class C2(int X, int Y); Diagnostic(ErrorCode.ERR_RbraceExpected, "(").WithLocation(3, 14), - // (3,14): error CS8803: Top-level statements must precede namespace and type declarations. - // data class C2(int X, int Y); - Diagnostic(ErrorCode.ERR_TopLevelStatementAfterNamespaceOrType, "(int X, int Y);").WithLocation(3, 14), - // (3,14): error CS0201: Only assignment, call, increment, decrement, await, and new object expressions can be used as a statement + // (4,6): error CS1001: Identifier expected + // data struct S1 { } + Diagnostic(ErrorCode.ERR_IdentifierExpected, "struct").WithLocation(4, 6), + // (4,6): error CS1002: ; expected + // data struct S1 { } + Diagnostic(ErrorCode.ERR_SemicolonExpected, "struct").WithLocation(4, 6), + // (5,6): error CS1001: Identifier expected + // data struct S2(int X, int Y); + Diagnostic(ErrorCode.ERR_IdentifierExpected, "struct").WithLocation(5, 6), + // (5,6): error CS1002: ; expected + // data struct S2(int X, int Y); + Diagnostic(ErrorCode.ERR_SemicolonExpected, "struct").WithLocation(5, 6), + // (5,15): error CS1514: { expected + // data struct S2(int X, int Y); + Diagnostic(ErrorCode.ERR_LbraceExpected, "(").WithLocation(5, 15), + // (5,15): error CS1513: } expected + // data struct S2(int X, int Y); + Diagnostic(ErrorCode.ERR_RbraceExpected, "(").WithLocation(5, 15), + // (2,1): error CS8805: Program using top-level statements must be an executable. + // data class C1 { } + Diagnostic(ErrorCode.ERR_SimpleProgramNotAnExecutable, "data ").WithLocation(2, 1), + // (2,1): error CS0246: The type or namespace name 'data' could not be found (are you missing a using directive or an assembly reference?) + // data class C1 { } + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "data").WithArguments("data").WithLocation(2, 1), + // (3,1): error CS0246: The type or namespace name 'data' could not be found (are you missing a using directive or an assembly reference?) // data class C2(int X, int Y); - Diagnostic(ErrorCode.ERR_IllegalStatement, "(int X, int Y)").WithLocation(3, 14), + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "data").WithArguments("data").WithLocation(3, 1), // (3,15): error CS8185: A declaration is not allowed in this context. // data class C2(int X, int Y); Diagnostic(ErrorCode.ERR_DeclarationExpressionNotPermitted, "int X").WithLocation(3, 15), - // (3,15): error CS0165: Use of unassigned local variable 'X' - // data class C2(int X, int Y); - Diagnostic(ErrorCode.ERR_UseDefViolation, "int X").WithArguments("X").WithLocation(3, 15), // (3,22): error CS8185: A declaration is not allowed in this context. // data class C2(int X, int Y); Diagnostic(ErrorCode.ERR_DeclarationExpressionNotPermitted, "int Y").WithLocation(3, 22), - // (3,22): error CS0165: Use of unassigned local variable 'Y' + // (3,14): error CS0201: Only assignment, call, increment, decrement, await, and new object expressions can be used as a statement // data class C2(int X, int Y); - Diagnostic(ErrorCode.ERR_UseDefViolation, "int Y").WithArguments("Y").WithLocation(3, 22), - // (4,1): error CS0116: A namespace cannot directly contain members such as fields or methods + Diagnostic(ErrorCode.ERR_IllegalStatement, "(int X, int Y)").WithLocation(3, 14), + // (4,1): error CS0246: The type or namespace name 'data' could not be found (are you missing a using directive or an assembly reference?) // data struct S1 { } - Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "data").WithLocation(4, 1), - // (5,1): error CS0116: A namespace cannot directly contain members such as fields or methods - // data struct S2(int X, int Y); - Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "data").WithLocation(5, 1), - // (5,15): error CS1514: { expected - // data struct S2(int X, int Y); - Diagnostic(ErrorCode.ERR_LbraceExpected, "(").WithLocation(5, 15), - // (5,15): error CS1513: } expected - // data struct S2(int X, int Y); - Diagnostic(ErrorCode.ERR_RbraceExpected, "(").WithLocation(5, 15), - // (5,15): error CS0201: Only assignment, call, increment, decrement, await, and new object expressions can be used as a statement + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "data").WithArguments("data").WithLocation(4, 1), + // (5,1): error CS0246: The type or namespace name 'data' could not be found (are you missing a using directive or an assembly reference?) // data struct S2(int X, int Y); - Diagnostic(ErrorCode.ERR_IllegalStatement, "(int X, int Y)").WithLocation(5, 15), + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "data").WithArguments("data").WithLocation(5, 1), // (5,16): error CS8185: A declaration is not allowed in this context. // data struct S2(int X, int Y); Diagnostic(ErrorCode.ERR_DeclarationExpressionNotPermitted, "int X").WithLocation(5, 16), - // (5,16): error CS0165: Use of unassigned local variable 'X' - // data struct S2(int X, int Y); - Diagnostic(ErrorCode.ERR_UseDefViolation, "int X").WithArguments("X").WithLocation(5, 16), // (5,20): error CS0128: A local variable or function named 'X' is already defined in this scope // data struct S2(int X, int Y); Diagnostic(ErrorCode.ERR_LocalDuplicate, "X").WithArguments("X").WithLocation(5, 20), // (5,23): error CS8185: A declaration is not allowed in this context. // data struct S2(int X, int Y); Diagnostic(ErrorCode.ERR_DeclarationExpressionNotPermitted, "int Y").WithLocation(5, 23), - // (5,23): error CS0165: Use of unassigned local variable 'Y' - // data struct S2(int X, int Y); - Diagnostic(ErrorCode.ERR_UseDefViolation, "int Y").WithArguments("Y").WithLocation(5, 23), // (5,27): error CS0128: A local variable or function named 'Y' is already defined in this scope // data struct S2(int X, int Y); - Diagnostic(ErrorCode.ERR_LocalDuplicate, "Y").WithArguments("Y").WithLocation(5, 27) + Diagnostic(ErrorCode.ERR_LocalDuplicate, "Y").WithArguments("Y").WithLocation(5, 27), + // (5,15): error CS0201: Only assignment, call, increment, decrement, await, and new object expressions can be used as a statement + // data struct S2(int X, int Y); + Diagnostic(ErrorCode.ERR_IllegalStatement, "(int X, int Y)").WithLocation(5, 15), + // (3,15): error CS0165: Use of unassigned local variable 'X' + // data class C2(int X, int Y); + Diagnostic(ErrorCode.ERR_UseDefViolation, "int X").WithArguments("X").WithLocation(3, 15), + // (3,22): error CS0165: Use of unassigned local variable 'Y' + // data class C2(int X, int Y); + Diagnostic(ErrorCode.ERR_UseDefViolation, "int Y").WithArguments("Y").WithLocation(3, 22), + // (5,16): error CS0165: Use of unassigned local variable 'X' + // data struct S2(int X, int Y); + Diagnostic(ErrorCode.ERR_UseDefViolation, "int X").WithArguments("X").WithLocation(5, 16), + // (5,23): error CS0165: Use of unassigned local variable 'Y' + // data struct S2(int X, int Y); + Diagnostic(ErrorCode.ERR_UseDefViolation, "int Y").WithArguments("Y").WithLocation(5, 23) ); } diff --git a/src/Compilers/CSharp/Test/Syntax/LexicalAndXml/PreprocessorTests.cs b/src/Compilers/CSharp/Test/Syntax/LexicalAndXml/PreprocessorTests.cs index 9d2ad9642482b..10bb4f5692da1 100644 --- a/src/Compilers/CSharp/Test/Syntax/LexicalAndXml/PreprocessorTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/LexicalAndXml/PreprocessorTests.cs @@ -1704,22 +1704,6 @@ class B { } VerifyMembers(node, new MemberInfo { Kind = SyntaxKind.ClassDeclaration, Text = "B" }); } - [Fact] - [Trait("Feature", "Directives")] - public void TestNegIfEndifDirectivesWithBadCode() - { - var text = -@"#if true -#else -#endif -aeu"; - - var node = Parse(text); - TestRoundTripping(node, text, false); - VerifyErrorCode(node, (int)ErrorCode.ERR_NamespaceUnexpected); - VerifyDirectives(node, SyntaxKind.IfDirectiveTrivia, SyntaxKind.ElseDirectiveTrivia, SyntaxKind.EndIfDirectiveTrivia); - } - [Fact] [Trait("Feature", "Directives")] public void TestIfElifWithBoolExpression() diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/DeclarationParsingTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/DeclarationParsingTests.cs index 5bd8497f82cc9..cf66e60924740 100644 --- a/src/Compilers/CSharp/Test/Syntax/Parsing/DeclarationParsingTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/DeclarationParsingTests.cs @@ -8631,17 +8631,28 @@ class A : B : C // (2,13): error CS1022: Type or namespace definition, or end-of-file expected // class A : B : C Diagnostic(ErrorCode.ERR_EOFExpected, ":").WithLocation(2, 13), - // (2,15): error CS0116: A namespace cannot directly contain members such as fields or methods + // (2,15): error CS8370: Feature 'top-level statements' is not available in C# 7.3. Please use language version 9.0 or greater. // class A : B : C - Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "C").WithLocation(2, 15), - // (3,1): error CS8370: Feature 'top-level statements' is not available in C# 7.3. Please use language version 9.0 or greater. - // { - Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, @"{ -}").WithArguments("top-level statements", "9.0").WithLocation(3, 1), - // (3,1): error CS8803: Top-level statements must precede namespace and type declarations. + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, @"C +{ +").WithArguments("top-level statements", "9.0").WithLocation(2, 15), + // (2,15): error CS8803: Top-level statements must precede namespace and type declarations. + // class A : B : C + Diagnostic(ErrorCode.ERR_TopLevelStatementAfterNamespaceOrType, @"C +{ +").WithLocation(2, 15), + // (2,16): error CS1001: Identifier expected + // class A : B : C + Diagnostic(ErrorCode.ERR_IdentifierExpected, "").WithLocation(2, 16), + // (2,16): error CS1003: Syntax error, ',' expected + // class A : B : C + Diagnostic(ErrorCode.ERR_SyntaxError, "").WithArguments(",").WithLocation(2, 16), + // (3,2): error CS1002: ; expected // { - Diagnostic(ErrorCode.ERR_TopLevelStatementAfterNamespaceOrType, @"{ -}").WithLocation(3, 1) + Diagnostic(ErrorCode.ERR_SemicolonExpected, "").WithLocation(3, 2), + // (4,1): error CS1022: Type or namespace definition, or end-of-file expected + // } + Diagnostic(ErrorCode.ERR_EOFExpected, "}").WithLocation(4, 1) ); N(SyntaxKind.CompilationUnit); @@ -8664,19 +8675,22 @@ class A : B : C M(SyntaxKind.OpenBraceToken); M(SyntaxKind.CloseBraceToken); } - N(SyntaxKind.IncompleteMember); - { - N(SyntaxKind.IdentifierName); - { - N(SyntaxKind.IdentifierToken, "C"); - } - } N(SyntaxKind.GlobalStatement); { - N(SyntaxKind.Block); + N(SyntaxKind.LocalDeclarationStatement); { - N(SyntaxKind.OpenBraceToken); - N(SyntaxKind.CloseBraceToken); + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "C"); + } + M(SyntaxKind.VariableDeclarator); + { + M(SyntaxKind.IdentifierToken); + } + } + M(SyntaxKind.SemicolonToken); } } N(SyntaxKind.EndOfFileToken); diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/DeclarationScopeParsingTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/DeclarationScopeParsingTests.cs index c9e067e2a450c..d2a0d6e3a4026 100644 --- a/src/Compilers/CSharp/Test/Syntax/Parsing/DeclarationScopeParsingTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/DeclarationScopeParsingTests.cs @@ -11419,9 +11419,12 @@ public void Type_01(LanguageVersion langVersion) scoped ref struct B { } "; UsingTree(source, TestOptions.Regular.WithLanguageVersion(langVersion), - // (1,1): error CS0116: A namespace cannot directly contain members such as fields, methods or statements + // (1,8): error CS1001: Identifier expected // scoped struct A { } - Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "scoped").WithLocation(1, 1), + Diagnostic(ErrorCode.ERR_IdentifierExpected, "struct").WithLocation(1, 8), + // (1,8): error CS1002: ; expected + // scoped struct A { } + Diagnostic(ErrorCode.ERR_SemicolonExpected, "struct").WithLocation(1, 8), // (2,12): error CS1031: Type expected // scoped ref struct B { } Diagnostic(ErrorCode.ERR_TypeExpected, "struct").WithLocation(2, 12) @@ -11429,11 +11432,22 @@ scoped ref struct B { } N(SyntaxKind.CompilationUnit); { - N(SyntaxKind.IncompleteMember); + N(SyntaxKind.GlobalStatement); { - N(SyntaxKind.IdentifierName); + N(SyntaxKind.LocalDeclarationStatement); { - N(SyntaxKind.IdentifierToken, "scoped"); + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "scoped"); + } + M(SyntaxKind.VariableDeclarator); + { + M(SyntaxKind.IdentifierToken); + } + } + M(SyntaxKind.SemicolonToken); } } N(SyntaxKind.StructDeclaration); diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/FileModifierParsingTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/FileModifierParsingTests.cs index fcbd84a47a552..c78da679b55be 100644 --- a/src/Compilers/CSharp/Test/Syntax/Parsing/FileModifierParsingTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/FileModifierParsingTests.cs @@ -25,11 +25,6 @@ private void UsingNode(string text, params DiagnosticDescription[] expectedDiagn UsingNode(text, options: null, expectedParsingDiagnostics: expectedDiagnostics); } - private new void UsingNode(string text, CSharpParseOptions? options, params DiagnosticDescription[] expectedDiagnostics) - { - UsingNode(text, options, expectedParsingDiagnostics: expectedDiagnostics); - } - private void UsingNode(string text, CSharpParseOptions? options = null, DiagnosticDescription[]? expectedParsingDiagnostics = null, DiagnosticDescription[]? expectedBindingDiagnostics = null) { options ??= TestOptions.RegularPreview; @@ -1550,17 +1545,46 @@ public void Errors_01_CSharp10() file """, options: TestOptions.Regular10, - // (1,1): error CS0116: A namespace cannot directly contain members such as fields, methods or statements - // file - Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "file").WithLocation(1, 1)); + expectedParsingDiagnostics: new[] + { + // (1,5): error CS1001: Identifier expected + // file + Diagnostic(ErrorCode.ERR_IdentifierExpected, "").WithLocation(1, 5), + // (1,5): error CS1002: ; expected + // file + Diagnostic(ErrorCode.ERR_SemicolonExpected, "").WithLocation(1, 5) + }, + expectedBindingDiagnostics: new[] + { + // (1,1): error CS0246: The type or namespace name 'file' could not be found (are you missing a using directive or an assembly reference?) + // file + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "file").WithArguments("file").WithLocation(1, 1), + // (1,5): error CS1001: Identifier expected + // file + Diagnostic(ErrorCode.ERR_IdentifierExpected, "").WithLocation(1, 5), + // (1,5): error CS1002: ; expected + // file + Diagnostic(ErrorCode.ERR_SemicolonExpected, "").WithLocation(1, 5) + }); N(SyntaxKind.CompilationUnit); { - N(SyntaxKind.IncompleteMember); + N(SyntaxKind.GlobalStatement); { - N(SyntaxKind.IdentifierName); + N(SyntaxKind.LocalDeclarationStatement); { - N(SyntaxKind.IdentifierToken, "file"); + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "file"); + } + M(SyntaxKind.VariableDeclarator); + { + M(SyntaxKind.IdentifierToken); + } + } + M(SyntaxKind.SemicolonToken); } } N(SyntaxKind.EndOfFileToken); @@ -1574,17 +1598,46 @@ public void Errors_01() UsingNode($$""" file """, - // (1,1): error CS0116: A namespace cannot directly contain members such as fields, methods or statements - // file - Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "file").WithLocation(1, 1)); + expectedParsingDiagnostics: new[] + { + // (1,5): error CS1001: Identifier expected + // file + Diagnostic(ErrorCode.ERR_IdentifierExpected, "").WithLocation(1, 5), + // (1,5): error CS1002: ; expected + // file + Diagnostic(ErrorCode.ERR_SemicolonExpected, "").WithLocation(1, 5) + }, + expectedBindingDiagnostics: new[] + { + // (1,1): error CS0246: The type or namespace name 'file' could not be found (are you missing a using directive or an assembly reference?) + // file + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "file").WithArguments("file").WithLocation(1, 1), + // (1,5): error CS1001: Identifier expected + // file + Diagnostic(ErrorCode.ERR_IdentifierExpected, "").WithLocation(1, 5), + // (1,5): error CS1002: ; expected + // file + Diagnostic(ErrorCode.ERR_SemicolonExpected, "").WithLocation(1, 5) + }); N(SyntaxKind.CompilationUnit); { - N(SyntaxKind.IncompleteMember); + N(SyntaxKind.GlobalStatement); { - N(SyntaxKind.IdentifierName); + N(SyntaxKind.LocalDeclarationStatement); { - N(SyntaxKind.IdentifierToken, "file"); + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "file"); + } + M(SyntaxKind.VariableDeclarator); + { + M(SyntaxKind.IdentifierToken); + } + } + M(SyntaxKind.SemicolonToken); } } N(SyntaxKind.EndOfFileToken); @@ -1670,15 +1723,24 @@ public void Errors_03_CSharp10() options: TestOptions.Regular10, expectedParsingDiagnostics: new[] { - // (1,1): error CS0116: A namespace cannot directly contain members such as fields, methods or statements + // (1,6): error CS1001: Identifier expected + // file namespace NS; + Diagnostic(ErrorCode.ERR_IdentifierExpected, "namespace").WithLocation(1, 6), + // (1,6): error CS1002: ; expected // file namespace NS; - Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "file").WithLocation(1, 1) + Diagnostic(ErrorCode.ERR_SemicolonExpected, "namespace").WithLocation(1, 6) }, expectedBindingDiagnostics: new[] { - // (1,1): error CS0116: A namespace cannot directly contain members such as fields, methods or statements + // (1,1): error CS0246: The type or namespace name 'file' could not be found (are you missing a using directive or an assembly reference?) + // file namespace NS; + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "file").WithArguments("file").WithLocation(1, 1), + // (1,6): error CS1001: Identifier expected + // file namespace NS; + Diagnostic(ErrorCode.ERR_IdentifierExpected, "namespace").WithLocation(1, 6), + // (1,6): error CS1002: ; expected // file namespace NS; - Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "file").WithLocation(1, 1), + Diagnostic(ErrorCode.ERR_SemicolonExpected, "namespace").WithLocation(1, 6), // (1,16): error CS8956: File-scoped namespace must precede all other members in a file. // file namespace NS; Diagnostic(ErrorCode.ERR_FileScopedNamespaceNotBeforeAllMembers, "NS").WithLocation(1, 16) @@ -1686,11 +1748,22 @@ public void Errors_03_CSharp10() N(SyntaxKind.CompilationUnit); { - N(SyntaxKind.IncompleteMember); + N(SyntaxKind.GlobalStatement); { - N(SyntaxKind.IdentifierName); + N(SyntaxKind.LocalDeclarationStatement); { - N(SyntaxKind.IdentifierToken, "file"); + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "file"); + } + M(SyntaxKind.VariableDeclarator); + { + M(SyntaxKind.IdentifierToken); + } + } + M(SyntaxKind.SemicolonToken); } } N(SyntaxKind.FileScopedNamespaceDeclaration); @@ -1715,15 +1788,24 @@ public void Errors_03() """, expectedParsingDiagnostics: new[] { - // (1,1): error CS0116: A namespace cannot directly contain members such as fields, methods or statements + // (1,6): error CS1001: Identifier expected // file namespace NS; - Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "file").WithLocation(1, 1) + Diagnostic(ErrorCode.ERR_IdentifierExpected, "namespace").WithLocation(1, 6), + // (1,6): error CS1002: ; expected + // file namespace NS; + Diagnostic(ErrorCode.ERR_SemicolonExpected, "namespace").WithLocation(1, 6) }, expectedBindingDiagnostics: new[] { - // (1,1): error CS0116: A namespace cannot directly contain members such as fields, methods or statements + // (1,1): error CS0246: The type or namespace name 'file' could not be found (are you missing a using directive or an assembly reference?) + // file namespace NS; + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "file").WithArguments("file").WithLocation(1, 1), + // (1,6): error CS1001: Identifier expected + // file namespace NS; + Diagnostic(ErrorCode.ERR_IdentifierExpected, "namespace").WithLocation(1, 6), + // (1,6): error CS1002: ; expected // file namespace NS; - Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "file").WithLocation(1, 1), + Diagnostic(ErrorCode.ERR_SemicolonExpected, "namespace").WithLocation(1, 6), // (1,16): error CS8956: File-scoped namespace must precede all other members in a file. // file namespace NS; Diagnostic(ErrorCode.ERR_FileScopedNamespaceNotBeforeAllMembers, "NS").WithLocation(1, 16) @@ -1731,11 +1813,22 @@ public void Errors_03() N(SyntaxKind.CompilationUnit); { - N(SyntaxKind.IncompleteMember); + N(SyntaxKind.GlobalStatement); { - N(SyntaxKind.IdentifierName); + N(SyntaxKind.LocalDeclarationStatement); { - N(SyntaxKind.IdentifierToken, "file"); + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "file"); + } + M(SyntaxKind.VariableDeclarator); + { + M(SyntaxKind.IdentifierToken); + } + } + M(SyntaxKind.SemicolonToken); } } N(SyntaxKind.FileScopedNamespaceDeclaration); @@ -1761,18 +1854,44 @@ file namespace NS { } options: TestOptions.Regular10, expectedParsingDiagnostics: new[] { - // (1,1): error CS0116: A namespace cannot directly contain members such as fields, methods or statements + // (1,6): error CS1001: Identifier expected + // file namespace NS { } + Diagnostic(ErrorCode.ERR_IdentifierExpected, "namespace").WithLocation(1, 6), + // (1,6): error CS1002: ; expected + // file namespace NS { } + Diagnostic(ErrorCode.ERR_SemicolonExpected, "namespace").WithLocation(1, 6) + }, + expectedBindingDiagnostics: new[] + { + // (1,1): error CS0246: The type or namespace name 'file' could not be found (are you missing a using directive or an assembly reference?) // file namespace NS { } - Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "file").WithLocation(1, 1) + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "file").WithArguments("file").WithLocation(1, 1), + // (1,6): error CS1001: Identifier expected + // file namespace NS { } + Diagnostic(ErrorCode.ERR_IdentifierExpected, "namespace").WithLocation(1, 6), + // (1,6): error CS1002: ; expected + // file namespace NS { } + Diagnostic(ErrorCode.ERR_SemicolonExpected, "namespace").WithLocation(1, 6) }); N(SyntaxKind.CompilationUnit); { - N(SyntaxKind.IncompleteMember); + N(SyntaxKind.GlobalStatement); { - N(SyntaxKind.IdentifierName); + N(SyntaxKind.LocalDeclarationStatement); { - N(SyntaxKind.IdentifierToken, "file"); + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "file"); + } + M(SyntaxKind.VariableDeclarator); + { + M(SyntaxKind.IdentifierToken); + } + } + M(SyntaxKind.SemicolonToken); } } N(SyntaxKind.NamespaceDeclaration); @@ -1798,18 +1917,44 @@ file namespace NS { } """, expectedParsingDiagnostics: new[] { - // (1,1): error CS0116: A namespace cannot directly contain members such as fields, methods or statements + // (1,6): error CS1001: Identifier expected + // file namespace NS { } + Diagnostic(ErrorCode.ERR_IdentifierExpected, "namespace").WithLocation(1, 6), + // (1,6): error CS1002: ; expected + // file namespace NS { } + Diagnostic(ErrorCode.ERR_SemicolonExpected, "namespace").WithLocation(1, 6) + }, + expectedBindingDiagnostics: new[] + { + // (1,1): error CS0246: The type or namespace name 'file' could not be found (are you missing a using directive or an assembly reference?) + // file namespace NS { } + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "file").WithArguments("file").WithLocation(1, 1), + // (1,6): error CS1001: Identifier expected // file namespace NS { } - Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "file").WithLocation(1, 1) + Diagnostic(ErrorCode.ERR_IdentifierExpected, "namespace").WithLocation(1, 6), + // (1,6): error CS1002: ; expected + // file namespace NS { } + Diagnostic(ErrorCode.ERR_SemicolonExpected, "namespace").WithLocation(1, 6) }); N(SyntaxKind.CompilationUnit); { - N(SyntaxKind.IncompleteMember); + N(SyntaxKind.GlobalStatement); { - N(SyntaxKind.IdentifierName); + N(SyntaxKind.LocalDeclarationStatement); { - N(SyntaxKind.IdentifierToken, "file"); + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "file"); + } + M(SyntaxKind.VariableDeclarator); + { + M(SyntaxKind.IdentifierToken); + } + } + M(SyntaxKind.SemicolonToken); } } N(SyntaxKind.NamespaceDeclaration); diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/FunctionPointerTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/FunctionPointerTests.cs index 63e162322c70f..9dd7a63b38a04 100644 --- a/src/Compilers/CSharp/Test/Syntax/Parsing/FunctionPointerTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/FunctionPointerTests.cs @@ -4108,9 +4108,9 @@ public void UsingAlias() // (1,11): error CS1041: Identifier expected; 'delegate' is a keyword // using t = delegate*; Diagnostic(ErrorCode.ERR_IdentifierExpectedKW, "delegate").WithArguments("", "delegate").WithLocation(1, 11), - // (1,25): error CS0116: A namespace cannot directly contain members such as fields or methods + // (1,26): error CS1001: Identifier expected // using t = delegate*; - Diagnostic(ErrorCode.ERR_NamespaceUnexpected, ">").WithLocation(1, 25) + Diagnostic(ErrorCode.ERR_IdentifierExpected, ";").WithLocation(1, 26) ); N(SyntaxKind.CompilationUnit); @@ -4132,30 +4132,34 @@ public void UsingAlias() } M(SyntaxKind.SemicolonToken); } - N(SyntaxKind.IncompleteMember); + N(SyntaxKind.GlobalStatement); { - N(SyntaxKind.FunctionPointerType); + N(SyntaxKind.LocalDeclarationStatement); { - N(SyntaxKind.DelegateKeyword); - N(SyntaxKind.AsteriskToken); - N(SyntaxKind.FunctionPointerParameterList); + N(SyntaxKind.VariableDeclaration); { - N(SyntaxKind.LessThanToken); - N(SyntaxKind.FunctionPointerParameter); + N(SyntaxKind.FunctionPointerType); { - N(SyntaxKind.PredefinedType); + N(SyntaxKind.DelegateKeyword); + N(SyntaxKind.AsteriskToken); + N(SyntaxKind.FunctionPointerParameterList); { - N(SyntaxKind.VoidKeyword); + N(SyntaxKind.LessThanToken); + N(SyntaxKind.FunctionPointerParameter); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.VoidKeyword); + } + } + N(SyntaxKind.GreaterThanToken); } } - N(SyntaxKind.GreaterThanToken); + M(SyntaxKind.VariableDeclarator); + { + M(SyntaxKind.IdentifierToken); + } } - } - } - N(SyntaxKind.GlobalStatement); - { - N(SyntaxKind.EmptyStatement); - { N(SyntaxKind.SemicolonToken); } } diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/ParserErrorMessageTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/ParserErrorMessageTests.cs index e89a7d0fc12ee..e31a7bc7eee77 100644 --- a/src/Compilers/CSharp/Test/Syntax/Parsing/ParserErrorMessageTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/ParserErrorMessageTests.cs @@ -2441,9 +2441,15 @@ public void CS1022ERR_EOFExpected02() // (1,27): error CS1002: ; expected // > Roslyn.Utilities.dll! Basic Diagnostic(ErrorCode.ERR_SemicolonExpected, "Basic").WithLocation(1, 27), - // (1,27): error CS0116: A namespace cannot directly contain members such as fields or methods + // (1,27): error CS0246: The type or namespace name 'Basic' could not be found (are you missing a using directive or an assembly reference?) // > Roslyn.Utilities.dll! Basic - Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "Basic").WithLocation(1, 27) + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "Basic").WithArguments("Basic").WithLocation(1, 27), + // (1,32): error CS1001: Identifier expected + // > Roslyn.Utilities.dll! Basic + Diagnostic(ErrorCode.ERR_IdentifierExpected, "").WithLocation(1, 32), + // (1,32): error CS1002: ; expected + // > Roslyn.Utilities.dll! Basic + Diagnostic(ErrorCode.ERR_SemicolonExpected, "").WithLocation(1, 32) ); } @@ -3857,28 +3863,32 @@ public void CS1514ERR_LbraceExpected02() "; ParseAndValidate(test, - // (1,15): error CS1514: { expected - // public class S.D - Diagnostic(ErrorCode.ERR_LbraceExpected, ".").WithLocation(1, 15), - // (1,15): error CS1513: } expected - // public class S.D - Diagnostic(ErrorCode.ERR_RbraceExpected, ".").WithLocation(1, 15), - // (1,15): error CS1022: Type or namespace definition, or end-of-file expected - // public class S.D - Diagnostic(ErrorCode.ERR_EOFExpected, ".").WithLocation(1, 15), - // (1,16): error CS0116: A namespace cannot directly contain members such as fields or methods - // public class S.D - Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "D").WithLocation(1, 16), - // (2,1): error CS8803: Top-level statements must precede namespace and type declarations. - // { - Diagnostic(ErrorCode.ERR_TopLevelStatementAfterNamespaceOrType, @"{ -").WithLocation(2, 1), - // (2,2): error CS1513: } expected - // { - Diagnostic(ErrorCode.ERR_RbraceExpected, "").WithLocation(2, 2), - // (4,1): error CS1022: Type or namespace definition, or end-of-file expected - // } - Diagnostic(ErrorCode.ERR_EOFExpected, "}").WithLocation(4, 1)); + // (1,15): error CS1514: { expected + // public class S.D + Diagnostic(ErrorCode.ERR_LbraceExpected, ".").WithLocation(1, 15), + // (1,15): error CS1513: } expected + // public class S.D + Diagnostic(ErrorCode.ERR_RbraceExpected, ".").WithLocation(1, 15), + // (1,15): error CS1022: Type or namespace definition, or end-of-file expected + // public class S.D + Diagnostic(ErrorCode.ERR_EOFExpected, ".").WithLocation(1, 15), + // (1,16): error CS8803: Top-level statements must precede namespace and type declarations. + // public class S.D + Diagnostic(ErrorCode.ERR_TopLevelStatementAfterNamespaceOrType, @"D +{ +").WithLocation(1, 16), + // (1,17): error CS1001: Identifier expected + // public class S.D + Diagnostic(ErrorCode.ERR_IdentifierExpected, "").WithLocation(1, 17), + // (1,17): error CS1003: Syntax error, ',' expected + // public class S.D + Diagnostic(ErrorCode.ERR_SyntaxError, "").WithArguments(",").WithLocation(1, 17), + // (2,2): error CS1002: ; expected + // { + Diagnostic(ErrorCode.ERR_SemicolonExpected, "").WithLocation(2, 2), + // (4,1): error CS1022: Type or namespace definition, or end-of-file expected + // } + Diagnostic(ErrorCode.ERR_EOFExpected, "}").WithLocation(4, 1)); } [WorkItem(535932, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/535932")] diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/ParsingErrorRecoveryTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/ParsingErrorRecoveryTests.cs index 5430e695e6ac8..227d106c57686 100644 --- a/src/Compilers/CSharp/Test/Syntax/Parsing/ParsingErrorRecoveryTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/ParsingErrorRecoveryTests.cs @@ -6807,8 +6807,20 @@ public void Repro649806() var source = "a b:: /**/\r\n"; var tree = SyntaxFactory.ParseSyntaxTree(source); var diags = tree.GetDiagnostics(); - diags.ToArray(); - Assert.Equal(1, diags.Count(d => d.Code == (int)ErrorCode.ERR_AliasQualAsExpression)); + diags.Verify( + // (1,4): error CS1002: ; expected + // a b:: /**/ + Diagnostic(ErrorCode.ERR_SemicolonExpected, "::").WithLocation(1, 4), + // (1,4): error CS1001: Identifier expected + // a b:: /**/ + Diagnostic(ErrorCode.ERR_IdentifierExpected, "::").WithLocation(1, 4), + // (1,6): error CS1001: Identifier expected + // a b:: /**/ + Diagnostic(ErrorCode.ERR_IdentifierExpected, "").WithLocation(1, 6), + // (1,6): error CS1002: ; expected + // a b:: /**/ + Diagnostic(ErrorCode.ERR_SemicolonExpected, "").WithLocation(1, 6) + ); } [WorkItem(674564, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/674564")] diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/RecordParsing.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/RecordParsing.cs index 6c628d0978f35..8ffd9257b6f80 100644 --- a/src/Compilers/CSharp/Test/Syntax/Parsing/RecordParsing.cs +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/RecordParsing.cs @@ -2665,18 +2665,21 @@ public void RecordStructParsing() verifyParsedAsRecord(); UsingTree(text, options: TestOptions.Regular8, - // (1,1): error CS0116: A namespace cannot directly contain members such as fields or methods + // (1,1): error CS8400: Feature 'top-level statements' is not available in C# 8.0. Please use language version 9.0 or greater. + // record struct C(int X, int Y); + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion8, "record ").WithArguments("top-level statements", "9.0").WithLocation(1, 1), + // (1,8): error CS1001: Identifier expected // record struct C(int X, int Y); - Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "record").WithLocation(1, 1), + Diagnostic(ErrorCode.ERR_IdentifierExpected, "struct").WithLocation(1, 8), + // (1,8): error CS1002: ; expected + // record struct C(int X, int Y); + Diagnostic(ErrorCode.ERR_SemicolonExpected, "struct").WithLocation(1, 8), // (1,16): error CS1514: { expected // record struct C(int X, int Y); Diagnostic(ErrorCode.ERR_LbraceExpected, "(").WithLocation(1, 16), // (1,16): error CS1513: } expected // record struct C(int X, int Y); Diagnostic(ErrorCode.ERR_RbraceExpected, "(").WithLocation(1, 16), - // (1,16): error CS8400: Feature 'top-level statements' is not available in C# 8.0. Please use language version 9.0 or greater. - // record struct C(int X, int Y); - Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion8, "(int X, int Y);").WithArguments("top-level statements", "9.0").WithLocation(1, 16), // (1,16): error CS8803: Top-level statements must precede namespace and type declarations. // record struct C(int X, int Y); Diagnostic(ErrorCode.ERR_TopLevelStatementAfterNamespaceOrType, "(int X, int Y);").WithLocation(1, 16) @@ -2684,11 +2687,22 @@ public void RecordStructParsing() N(SyntaxKind.CompilationUnit); { - N(SyntaxKind.IncompleteMember); + N(SyntaxKind.GlobalStatement); { - N(SyntaxKind.IdentifierName); + N(SyntaxKind.LocalDeclarationStatement); { - N(SyntaxKind.IdentifierToken, "record"); + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "record"); + } + M(SyntaxKind.VariableDeclarator); + { + M(SyntaxKind.IdentifierToken); + } + } + M(SyntaxKind.SemicolonToken); } } N(SyntaxKind.StructDeclaration); @@ -2842,18 +2856,21 @@ public void RecordClassParsing() verifyParsedAsRecord(); UsingTree(text, options: TestOptions.Regular8, - // (1,1): error CS0116: A namespace cannot directly contain members such as fields or methods + // (1,1): error CS8400: Feature 'top-level statements' is not available in C# 8.0. Please use language version 9.0 or greater. + // record class C(int X, int Y); + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion8, "record ").WithArguments("top-level statements", "9.0").WithLocation(1, 1), + // (1,8): error CS1001: Identifier expected // record class C(int X, int Y); - Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "record").WithLocation(1, 1), + Diagnostic(ErrorCode.ERR_IdentifierExpected, "class").WithLocation(1, 8), + // (1,8): error CS1002: ; expected + // record class C(int X, int Y); + Diagnostic(ErrorCode.ERR_SemicolonExpected, "class").WithLocation(1, 8), // (1,15): error CS1514: { expected // record class C(int X, int Y); Diagnostic(ErrorCode.ERR_LbraceExpected, "(").WithLocation(1, 15), // (1,15): error CS1513: } expected // record class C(int X, int Y); Diagnostic(ErrorCode.ERR_RbraceExpected, "(").WithLocation(1, 15), - // (1,15): error CS8400: Feature 'top-level statements' is not available in C# 8.0. Please use language version 9.0 or greater. - // record class C(int X, int Y); - Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion8, "(int X, int Y);").WithArguments("top-level statements", "9.0").WithLocation(1, 15), // (1,15): error CS8803: Top-level statements must precede namespace and type declarations. // record class C(int X, int Y); Diagnostic(ErrorCode.ERR_TopLevelStatementAfterNamespaceOrType, "(int X, int Y);").WithLocation(1, 15) @@ -2861,11 +2878,22 @@ public void RecordClassParsing() N(SyntaxKind.CompilationUnit); { - N(SyntaxKind.IncompleteMember); + N(SyntaxKind.GlobalStatement); { - N(SyntaxKind.IdentifierName); + N(SyntaxKind.LocalDeclarationStatement); { - N(SyntaxKind.IdentifierToken, "record"); + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "record"); + } + M(SyntaxKind.VariableDeclarator); + { + M(SyntaxKind.IdentifierToken); + } + } + M(SyntaxKind.SemicolonToken); } } N(SyntaxKind.ClassDeclaration); diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/RoundTrippingTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/RoundTrippingTests.cs index acd3ae2240809..fd6dc01014118 100644 --- a/src/Compilers/CSharp/Test/Syntax/Parsing/RoundTrippingTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/RoundTrippingTests.cs @@ -91,7 +91,7 @@ public void NullChar() { ParseAndRoundTripping("\0", 1); ParseAndRoundTripping("abc\0def", 3); - ParseAndRoundTripping("\0abc", 2); + ParseAndRoundTripping("\0abc", 3); ParseAndRoundTripping("class C { string s = \"\0\"; }", 0); } diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/TopLevelStatementsParsingTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/TopLevelStatementsParsingTests.cs index 7872c94b99b28..69588be306bfc 100644 --- a/src/Compilers/CSharp/Test/Syntax/Parsing/TopLevelStatementsParsingTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/TopLevelStatementsParsingTests.cs @@ -96,21 +96,36 @@ class C [a]fod; [b"; UsingTree(text, - // (2,1): error CS0116: A namespace cannot directly contain members such as fields or methods + // (2,5): error CS1001: Identifier expected // asas] - Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "asas").WithLocation(2, 1), - // (2,5): error CS1022: Type or namespace definition, or end-of-file expected + Diagnostic(ErrorCode.ERR_IdentifierExpected, "]").WithLocation(2, 5), + // (2,5): error CS1003: Syntax error, ',' expected // asas] - Diagnostic(ErrorCode.ERR_EOFExpected, "]").WithLocation(2, 5), - // (4,1): error CS0116: A namespace cannot directly contain members such as fields or methods + Diagnostic(ErrorCode.ERR_SyntaxError, "]").WithArguments(",").WithLocation(2, 5), + // (2,6): error CS1002: ; expected + // asas] + Diagnostic(ErrorCode.ERR_SemicolonExpected, "").WithLocation(2, 6), + // (3,1): error CS0439: An extern alias declaration must precede all other elements defined in the namespace + // extern alias A; + Diagnostic(ErrorCode.ERR_ExternAfterElements, "extern").WithLocation(3, 1), + // (4,1): error CS0116: A namespace cannot directly contain members such as fields, methods or statements // asas Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "asas").WithLocation(4, 1), - // (6,1): error CS0116: A namespace cannot directly contain members such as fields or methods + // (5,1): error CS1529: A using clause must precede all other elements defined in the namespace except extern alias declarations + // using System; + Diagnostic(ErrorCode.ERR_UsingAfterElements, "using System;").WithLocation(5, 1), + // (6,10): error CS1001: Identifier expected + // sadasdasd] + Diagnostic(ErrorCode.ERR_IdentifierExpected, "]").WithLocation(6, 10), + // (6,10): error CS1003: Syntax error, ',' expected // sadasdasd] - Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "sadasdasd").WithLocation(6, 1), - // (6,10): error CS1022: Type or namespace definition, or end-of-file expected + Diagnostic(ErrorCode.ERR_SyntaxError, "]").WithArguments(",").WithLocation(6, 10), + // (6,11): error CS1002: ; expected // sadasdasd] - Diagnostic(ErrorCode.ERR_EOFExpected, "]").WithLocation(6, 10), + Diagnostic(ErrorCode.ERR_SemicolonExpected, "").WithLocation(6, 11), + // (8,2): error CS1730: Assembly and module attributes must precede all other elements defined in a file except using clauses and extern alias declarations + // [assembly: goo] + Diagnostic(ErrorCode.ERR_GlobalAttributesNotFirst, "assembly").WithLocation(8, 2), // (15,1): error CS8803: Top-level statements must precede namespace and type declarations. // [a]fod; Diagnostic(ErrorCode.ERR_TopLevelStatementAfterNamespaceOrType, "[a]fod;").WithLocation(15, 1), @@ -121,38 +136,48 @@ class C N(SyntaxKind.CompilationUnit); { - N(SyntaxKind.ExternAliasDirective); + N(SyntaxKind.GlobalStatement); { - N(SyntaxKind.ExternKeyword); - N(SyntaxKind.AliasKeyword); - N(SyntaxKind.IdentifierToken, "A"); - N(SyntaxKind.SemicolonToken); + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "asas"); + } + M(SyntaxKind.VariableDeclarator); + { + M(SyntaxKind.IdentifierToken); + } + } + M(SyntaxKind.SemicolonToken); + } } - N(SyntaxKind.UsingDirective); + N(SyntaxKind.IncompleteMember); { - N(SyntaxKind.UsingKeyword); N(SyntaxKind.IdentifierName); { - N(SyntaxKind.IdentifierToken, "System"); + N(SyntaxKind.IdentifierToken, "asas"); } - N(SyntaxKind.SemicolonToken); } - N(SyntaxKind.AttributeList); + N(SyntaxKind.GlobalStatement); { - N(SyntaxKind.OpenBracketToken); - N(SyntaxKind.AttributeTargetSpecifier); - { - N(SyntaxKind.AssemblyKeyword); - N(SyntaxKind.ColonToken); - } - N(SyntaxKind.Attribute); + N(SyntaxKind.LocalDeclarationStatement); { - N(SyntaxKind.IdentifierName); + N(SyntaxKind.VariableDeclaration); { - N(SyntaxKind.IdentifierToken, "goo"); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "sadasdasd"); + } + M(SyntaxKind.VariableDeclarator); + { + M(SyntaxKind.IdentifierToken); + } } + M(SyntaxKind.SemicolonToken); } - N(SyntaxKind.CloseBracketToken); } N(SyntaxKind.ClassDeclaration); { @@ -770,16 +795,20 @@ public void CS1514ERR_LbraceExpected02() // (1,15): error CS1022: Type or namespace definition, or end-of-file expected // public class S.D Diagnostic(ErrorCode.ERR_EOFExpected, ".").WithLocation(1, 15), - // (1,16): error CS0116: A namespace cannot directly contain members such as fields or methods + // (1,16): error CS8803: Top-level statements must precede namespace and type declarations. // public class S.D - Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "D").WithLocation(1, 16), - // (2,1): error CS8803: Top-level statements must precede namespace and type declarations. - // { - Diagnostic(ErrorCode.ERR_TopLevelStatementAfterNamespaceOrType, @"{ -").WithLocation(2, 1), - // (2,2): error CS1513: } expected + Diagnostic(ErrorCode.ERR_TopLevelStatementAfterNamespaceOrType, @"D +{ +").WithLocation(1, 16), + // (1,17): error CS1001: Identifier expected + // public class S.D + Diagnostic(ErrorCode.ERR_IdentifierExpected, "").WithLocation(1, 17), + // (1,17): error CS1003: Syntax error, ',' expected + // public class S.D + Diagnostic(ErrorCode.ERR_SyntaxError, "").WithArguments(",").WithLocation(1, 17), + // (2,2): error CS1002: ; expected // { - Diagnostic(ErrorCode.ERR_RbraceExpected, "").WithLocation(2, 2), + Diagnostic(ErrorCode.ERR_SemicolonExpected, "").WithLocation(2, 2), // (4,1): error CS1022: Type or namespace definition, or end-of-file expected // } Diagnostic(ErrorCode.ERR_EOFExpected, "}").WithLocation(4, 1) @@ -795,19 +824,22 @@ public void CS1514ERR_LbraceExpected02() M(SyntaxKind.OpenBraceToken); M(SyntaxKind.CloseBraceToken); } - N(SyntaxKind.IncompleteMember); - { - N(SyntaxKind.IdentifierName); - { - N(SyntaxKind.IdentifierToken, "D"); - } - } N(SyntaxKind.GlobalStatement); { - N(SyntaxKind.Block); + N(SyntaxKind.LocalDeclarationStatement); { - N(SyntaxKind.OpenBraceToken); - M(SyntaxKind.CloseBraceToken); + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "D"); + } + M(SyntaxKind.VariableDeclarator); + { + M(SyntaxKind.IdentifierToken); + } + } + M(SyntaxKind.SemicolonToken); } } N(SyntaxKind.PropertyDeclaration); @@ -858,9 +890,12 @@ public void CS1022ERR_EOFExpected02() // (1,27): error CS1002: ; expected // > Roslyn.Utilities.dll! Basic Diagnostic(ErrorCode.ERR_SemicolonExpected, "Basic").WithLocation(1, 27), - // (1,27): error CS0116: A namespace cannot directly contain members such as fields or methods + // (1,32): error CS1001: Identifier expected + // > Roslyn.Utilities.dll! Basic + Diagnostic(ErrorCode.ERR_IdentifierExpected, "").WithLocation(1, 32), + // (1,32): error CS1002: ; expected // > Roslyn.Utilities.dll! Basic - Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "Basic").WithLocation(1, 27) + Diagnostic(ErrorCode.ERR_SemicolonExpected, "").WithLocation(1, 32) ); N(SyntaxKind.CompilationUnit); @@ -904,11 +939,22 @@ public void CS1022ERR_EOFExpected02() M(SyntaxKind.SemicolonToken); } } - N(SyntaxKind.IncompleteMember); + N(SyntaxKind.GlobalStatement); { - N(SyntaxKind.IdentifierName); + N(SyntaxKind.LocalDeclarationStatement); { - N(SyntaxKind.IdentifierToken, "Basic"); + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "Basic"); + } + M(SyntaxKind.VariableDeclarator); + { + M(SyntaxKind.IdentifierToken); + } + } + M(SyntaxKind.SemicolonToken); } } N(SyntaxKind.EndOfFileToken); @@ -1107,18 +1153,32 @@ public void TestNegIfEndifDirectivesWithBadCode() #endif aeu"; UsingTree(test, - // (4,1): error CS0116: A namespace cannot directly contain members such as fields or methods + // (4,4): error CS1001: Identifier expected + // aeu + Diagnostic(ErrorCode.ERR_IdentifierExpected, "").WithLocation(4, 4), + // (4,4): error CS1002: ; expected // aeu - Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "aeu").WithLocation(4, 1) + Diagnostic(ErrorCode.ERR_SemicolonExpected, "").WithLocation(4, 4) ); N(SyntaxKind.CompilationUnit); { - N(SyntaxKind.IncompleteMember); + N(SyntaxKind.GlobalStatement); { - N(SyntaxKind.IdentifierName); + N(SyntaxKind.LocalDeclarationStatement); { - N(SyntaxKind.IdentifierToken, "aeu"); + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "aeu"); + } + M(SyntaxKind.VariableDeclarator); + { + M(SyntaxKind.IdentifierToken); + } + } + M(SyntaxKind.SemicolonToken); } } N(SyntaxKind.EndOfFileToken); @@ -1406,9 +1466,12 @@ public void UnrecognizedGenericTypeReference() // (1,19): error CS1022: Type or namespace definition, or end-of-file expected // /**/C*/ Diagnostic(ErrorCode.ERR_EOFExpected, ",").WithLocation(1, 19), - // (1,21): error CS0116: A namespace cannot directly contain members such as fields or methods + // (1,38): error CS1001: Identifier expected + // /**/C*/ + Diagnostic(ErrorCode.ERR_IdentifierExpected, "").WithLocation(1, 38), + // (1,38): error CS1002: ; expected // /**/C*/ - Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "string").WithLocation(1, 21) + Diagnostic(ErrorCode.ERR_SemicolonExpected, "").WithLocation(1, 38) ); N(SyntaxKind.CompilationUnit); @@ -1432,11 +1495,22 @@ public void UnrecognizedGenericTypeReference() M(SyntaxKind.SemicolonToken); } } - N(SyntaxKind.IncompleteMember); + N(SyntaxKind.GlobalStatement); { - N(SyntaxKind.PredefinedType); + N(SyntaxKind.LocalDeclarationStatement); { - N(SyntaxKind.StringKeyword); + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.StringKeyword); + } + M(SyntaxKind.VariableDeclarator); + { + M(SyntaxKind.IdentifierToken); + } + } + M(SyntaxKind.SemicolonToken); } } N(SyntaxKind.EndOfFileToken); @@ -1656,18 +1730,32 @@ public void Identifier_01() var test = "e"; UsingTree(test, - // (1,1): error CS0116: A namespace cannot directly contain members such as fields or methods + // (1,2): error CS1001: Identifier expected + // e + Diagnostic(ErrorCode.ERR_IdentifierExpected, "").WithLocation(1, 2), + // (1,2): error CS1002: ; expected // e - Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "e").WithLocation(1, 1) + Diagnostic(ErrorCode.ERR_SemicolonExpected, "").WithLocation(1, 2) ); N(SyntaxKind.CompilationUnit); { - N(SyntaxKind.IncompleteMember); + N(SyntaxKind.GlobalStatement); { - N(SyntaxKind.IdentifierName); + N(SyntaxKind.LocalDeclarationStatement); { - N(SyntaxKind.IdentifierToken, "e"); + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "e"); + } + M(SyntaxKind.VariableDeclarator); + { + M(SyntaxKind.IdentifierToken); + } + } + M(SyntaxKind.SemicolonToken); } } N(SyntaxKind.EndOfFileToken); @@ -1717,7 +1805,7 @@ public void Identifier_02() } [Fact] - public void TestSkippedTest() + public void TestSkippedText() { var test = "abc using"; @@ -2602,9 +2690,9 @@ public void UsingAliasTest() // (1,11): error CS1041: Identifier expected; 'delegate' is a keyword // using s = delegate*; Diagnostic(ErrorCode.ERR_IdentifierExpectedKW, "delegate").WithArguments("", "delegate").WithLocation(1, 11), - // (1,25): error CS0116: A namespace cannot directly contain members such as fields or methods + // (1,26): error CS1001: Identifier expected // using s = delegate*; - Diagnostic(ErrorCode.ERR_NamespaceUnexpected, ">").WithLocation(1, 25) + Diagnostic(ErrorCode.ERR_IdentifierExpected, ";").WithLocation(1, 26) ); N(SyntaxKind.CompilationUnit); @@ -2626,33 +2714,902 @@ public void UsingAliasTest() } M(SyntaxKind.SemicolonToken); } - N(SyntaxKind.IncompleteMember); + N(SyntaxKind.GlobalStatement); { - N(SyntaxKind.FunctionPointerType); + N(SyntaxKind.LocalDeclarationStatement); { - N(SyntaxKind.DelegateKeyword); - N(SyntaxKind.AsteriskToken); - N(SyntaxKind.FunctionPointerParameterList); + N(SyntaxKind.VariableDeclaration); { - N(SyntaxKind.LessThanToken); - N(SyntaxKind.FunctionPointerParameter); + N(SyntaxKind.FunctionPointerType); { - N(SyntaxKind.PredefinedType); + N(SyntaxKind.DelegateKeyword); + N(SyntaxKind.AsteriskToken); + N(SyntaxKind.FunctionPointerParameterList); { - N(SyntaxKind.VoidKeyword); + N(SyntaxKind.LessThanToken); + N(SyntaxKind.FunctionPointerParameter); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.VoidKeyword); + } + } + N(SyntaxKind.GreaterThanToken); } } - N(SyntaxKind.GreaterThanToken); + M(SyntaxKind.VariableDeclarator); + { + M(SyntaxKind.IdentifierToken); + } } + N(SyntaxKind.SemicolonToken); } } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void ErrorRecovery_01() + { + var test = @"ar"; + + UsingTree(test, + // (1,3): error CS1001: Identifier expected + // ar + Diagnostic(ErrorCode.ERR_IdentifierExpected, "").WithLocation(1, 3), + // (1,3): error CS1002: ; expected + // ar + Diagnostic(ErrorCode.ERR_SemicolonExpected, "").WithLocation(1, 3) + ); + + N(SyntaxKind.CompilationUnit); + { N(SyntaxKind.GlobalStatement); { - N(SyntaxKind.EmptyStatement); + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "ar"); + } + M(SyntaxKind.VariableDeclarator); + { + M(SyntaxKind.IdentifierToken); + } + } + M(SyntaxKind.SemicolonToken); + } + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void ErrorRecovery_02() + { + var test = @" +Console.WriteLine(); +ar"; + + UsingTree(test, + // (3,3): error CS1001: Identifier expected + // ar + Diagnostic(ErrorCode.ERR_IdentifierExpected, "").WithLocation(3, 3), + // (3,3): error CS1002: ; expected + // ar + Diagnostic(ErrorCode.ERR_SemicolonExpected, "").WithLocation(3, 3) + ); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.ExpressionStatement); { + N(SyntaxKind.InvocationExpression); + { + N(SyntaxKind.SimpleMemberAccessExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "Console"); + } + N(SyntaxKind.DotToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "WriteLine"); + } + } + N(SyntaxKind.ArgumentList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + } N(SyntaxKind.SemicolonToken); } } + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "ar"); + } + M(SyntaxKind.VariableDeclarator); + { + M(SyntaxKind.IdentifierToken); + } + } + M(SyntaxKind.SemicolonToken); + } + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void ErrorRecovery_03() + { + var test = @" +ar +Console.WriteLine(); +"; + + UsingTree(test, + // (2,3): error CS1001: Identifier expected + // ar + Diagnostic(ErrorCode.ERR_IdentifierExpected, "").WithLocation(2, 3), + // (2,3): error CS1002: ; expected + // ar + Diagnostic(ErrorCode.ERR_SemicolonExpected, "").WithLocation(2, 3) + ); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "ar"); + } + M(SyntaxKind.VariableDeclarator); + { + M(SyntaxKind.IdentifierToken); + } + } + M(SyntaxKind.SemicolonToken); + } + } + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.ExpressionStatement); + { + N(SyntaxKind.InvocationExpression); + { + N(SyntaxKind.SimpleMemberAccessExpression); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "Console"); + } + N(SyntaxKind.DotToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "WriteLine"); + } + } + N(SyntaxKind.ArgumentList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + } + N(SyntaxKind.SemicolonToken); + } + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void ErrorRecovery_04() + { + var test = @"extern alias "; + + UsingTree(test, + // (1,8): error CS0116: A namespace cannot directly contain members such as fields, methods or statements + // extern alias + Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "alias").WithLocation(1, 8) + ); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.IncompleteMember); + { + N(SyntaxKind.ExternKeyword); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "alias"); + } + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void ErrorRecovery_05() + { + var test = @"using aliasY = X.Y;"; + + UsingTree(test); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.UsingDirective); + { + N(SyntaxKind.UsingKeyword); + N(SyntaxKind.NameEquals); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "aliasY"); + } + N(SyntaxKind.EqualsToken); + } + N(SyntaxKind.QualifiedName); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "X"); + } + N(SyntaxKind.DotToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "Y"); + } + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void ErrorRecovery_06() + { + var test = @" +using X; +using aliasY = X.Y; +"; + + UsingTree(test); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.UsingDirective); + { + N(SyntaxKind.UsingKeyword); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "X"); + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.UsingDirective); + { + N(SyntaxKind.UsingKeyword); + N(SyntaxKind.NameEquals); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "aliasY"); + } + N(SyntaxKind.EqualsToken); + } + N(SyntaxKind.QualifiedName); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "X"); + } + N(SyntaxKind.DotToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "Y"); + } + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void ErrorRecovery_07() + { + var test = @" +System.String[] +using aliasY = X.Y; +"; + + UsingTree(test, + // (2,15): error CS0116: A namespace cannot directly contain members such as fields, methods or statements + // System.String[] + Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "]").WithLocation(2, 15) + ); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.UsingDirective); + { + N(SyntaxKind.UsingKeyword); + N(SyntaxKind.NameEquals); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "aliasY"); + } + N(SyntaxKind.EqualsToken); + } + N(SyntaxKind.QualifiedName); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "X"); + } + N(SyntaxKind.DotToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "Y"); + } + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void ErrorRecovery_08() + { + var test = @" +scoped struct A { } +scoped ref struct B { } +scoped readonly ref struct C { } +"; + + UsingTree(test, + // (2,8): error CS1001: Identifier expected + // scoped struct A { } + Diagnostic(ErrorCode.ERR_IdentifierExpected, "struct").WithLocation(2, 8), + // (2,8): error CS1002: ; expected + // scoped struct A { } + Diagnostic(ErrorCode.ERR_SemicolonExpected, "struct").WithLocation(2, 8), + // (3,12): error CS1031: Type expected + // scoped ref struct B { } + Diagnostic(ErrorCode.ERR_TypeExpected, "struct").WithLocation(3, 12), + // (4,8): error CS1585: Member modifier 'readonly' must precede the member type and name + // scoped readonly ref struct C { } + Diagnostic(ErrorCode.ERR_BadModifierLocation, "readonly").WithArguments("readonly").WithLocation(4, 8) + ); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "scoped"); + } + M(SyntaxKind.VariableDeclarator); + { + M(SyntaxKind.IdentifierToken); + } + } + M(SyntaxKind.SemicolonToken); + } + } + N(SyntaxKind.StructDeclaration); + { + N(SyntaxKind.StructKeyword); + N(SyntaxKind.IdentifierToken, "A"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.IncompleteMember); + { + N(SyntaxKind.ScopedKeyword); + N(SyntaxKind.RefType); + { + N(SyntaxKind.RefKeyword); + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + } + } + N(SyntaxKind.StructDeclaration); + { + N(SyntaxKind.StructKeyword); + N(SyntaxKind.IdentifierToken, "B"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.IncompleteMember); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "scoped"); + } + } + N(SyntaxKind.StructDeclaration); + { + N(SyntaxKind.ReadOnlyKeyword); + N(SyntaxKind.RefKeyword); + N(SyntaxKind.StructKeyword); + N(SyntaxKind.IdentifierToken, "C"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void ErrorRecovery_09() + { + var test = @" +record class Point(int x, int y); +"; + + UsingTree(test); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.RecordDeclaration); + { + N(SyntaxKind.RecordKeyword); + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "Point"); + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.Parameter); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.IdentifierToken, "x"); + } + N(SyntaxKind.CommaToken); + N(SyntaxKind.Parameter); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.IdentifierToken, "y"); + } + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void ErrorRecovery_10() + { + var test = @" +record class Point(int x, int y); +"; + + UsingTree(test, TestOptions.Regular8, + // (2,1): error CS8400: Feature 'top-level statements' is not available in C# 8.0. Please use language version 9.0 or greater. + // record class Point(int x, int y); + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion8, "record ").WithArguments("top-level statements", "9.0").WithLocation(2, 1), + // (2,8): error CS1001: Identifier expected + // record class Point(int x, int y); + Diagnostic(ErrorCode.ERR_IdentifierExpected, "class").WithLocation(2, 8), + // (2,8): error CS1002: ; expected + // record class Point(int x, int y); + Diagnostic(ErrorCode.ERR_SemicolonExpected, "class").WithLocation(2, 8), + // (2,19): error CS1514: { expected + // record class Point(int x, int y); + Diagnostic(ErrorCode.ERR_LbraceExpected, "(").WithLocation(2, 19), + // (2,19): error CS1513: } expected + // record class Point(int x, int y); + Diagnostic(ErrorCode.ERR_RbraceExpected, "(").WithLocation(2, 19), + // (2,19): error CS8803: Top-level statements must precede namespace and type declarations. + // record class Point(int x, int y); + Diagnostic(ErrorCode.ERR_TopLevelStatementAfterNamespaceOrType, "(int x, int y);").WithLocation(2, 19) + ); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "record"); + } + M(SyntaxKind.VariableDeclarator); + { + M(SyntaxKind.IdentifierToken); + } + } + M(SyntaxKind.SemicolonToken); + } + } + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "Point"); + M(SyntaxKind.OpenBraceToken); + M(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.ExpressionStatement); + { + N(SyntaxKind.TupleExpression); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.Argument); + { + N(SyntaxKind.DeclarationExpression); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.SingleVariableDesignation); + { + N(SyntaxKind.IdentifierToken, "x"); + } + } + } + N(SyntaxKind.CommaToken); + N(SyntaxKind.Argument); + { + N(SyntaxKind.DeclarationExpression); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.SingleVariableDesignation); + { + N(SyntaxKind.IdentifierToken, "y"); + } + } + } + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.SemicolonToken); + } + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void ErrorRecovery_11() + { + var test = @" +global using Goo; +p +global using Bar; +"; + + UsingTree(test, + // (3,1): error CS0116: A namespace cannot directly contain members such as fields, methods or statements + // p + Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "p").WithLocation(3, 1) + ); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.UsingDirective); + { + N(SyntaxKind.GlobalKeyword); + N(SyntaxKind.UsingKeyword); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "Goo"); + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.UsingDirective); + { + N(SyntaxKind.GlobalKeyword); + N(SyntaxKind.UsingKeyword); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "Bar"); + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void ErrorRecovery_12() + { + var test = @" +using Goo; +p +using Bar; +"; + + UsingTree(test, + // (3,1): error CS0116: A namespace cannot directly contain members such as fields, methods or statements + // p + Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "p").WithLocation(3, 1) + ); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.UsingDirective); + { + N(SyntaxKind.UsingKeyword); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "Goo"); + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.UsingDirective); + { + N(SyntaxKind.UsingKeyword); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "Bar"); + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void ErrorRecovery_13() + { + var test = @" +using Goo; +p +using Bar x; +"; + + UsingTree(test, + // (3,2): error CS1001: Identifier expected + // p + Diagnostic(ErrorCode.ERR_IdentifierExpected, "").WithLocation(3, 2), + // (3,2): error CS1002: ; expected + // p + Diagnostic(ErrorCode.ERR_SemicolonExpected, "").WithLocation(3, 2) + ); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.UsingDirective); + { + N(SyntaxKind.UsingKeyword); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "Goo"); + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "p"); + } + M(SyntaxKind.VariableDeclarator); + { + M(SyntaxKind.IdentifierToken); + } + } + M(SyntaxKind.SemicolonToken); + } + } + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.UsingKeyword); + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "Bar"); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "x"); + } + } + N(SyntaxKind.SemicolonToken); + } + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void ErrorRecovery_14() + { + var test = @" +global using Goo; +p +global using Bar x; +"; + + UsingTree(test, + // (4,8): error CS1002: ; expected + // global using Bar x; + Diagnostic(ErrorCode.ERR_SemicolonExpected, "using").WithLocation(4, 8) + ); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.UsingDirective); + { + N(SyntaxKind.GlobalKeyword); + N(SyntaxKind.UsingKeyword); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "Goo"); + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "p"); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "global"); + } + } + M(SyntaxKind.SemicolonToken); + } + } + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.UsingKeyword); + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "Bar"); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "x"); + } + } + N(SyntaxKind.SemicolonToken); + } + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void ErrorRecovery_15() + { + var test = @" + W )b +"; + + UsingTree(test, + // (2,15): error CS1001: Identifier expected + // W )b + Diagnostic(ErrorCode.ERR_IdentifierExpected, ")").WithLocation(2, 15), + // (2,15): error CS1002: ; expected + // W )b + Diagnostic(ErrorCode.ERR_SemicolonExpected, ")").WithLocation(2, 15), + // (2,15): error CS1022: Type or namespace definition, or end-of-file expected + // W )b + Diagnostic(ErrorCode.ERR_EOFExpected, ")").WithLocation(2, 15), + // (2,17): error CS1001: Identifier expected + // W )b + Diagnostic(ErrorCode.ERR_IdentifierExpected, "").WithLocation(2, 17), + // (2,17): error CS1002: ; expected + // W )b + Diagnostic(ErrorCode.ERR_SemicolonExpected, "").WithLocation(2, 17) + ); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "W"); + } + M(SyntaxKind.VariableDeclarator); + { + M(SyntaxKind.IdentifierToken); + } + } + M(SyntaxKind.SemicolonToken); + } + } + N(SyntaxKind.GlobalStatement); + { + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "b"); + } + M(SyntaxKind.VariableDeclarator); + { + M(SyntaxKind.IdentifierToken); + } + } + M(SyntaxKind.SemicolonToken); + } + } N(SyntaxKind.EndOfFileToken); } EOF(); diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/SymbolCompletionProviderTests.cs b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/SymbolCompletionProviderTests.cs index ebbda2ca97cdf..11660b2e61cef 100644 --- a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/SymbolCompletionProviderTests.cs +++ b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/SymbolCompletionProviderTests.cs @@ -1534,16 +1534,84 @@ public async Task Locals() => await VerifyItemExistsAsync(@"class c { void M() { string goo; $$", "goo"); [Fact] - public async Task Parameters() + public async Task Parameters_01() => await VerifyItemExistsAsync(@"class c { void M(string args) { $$", "args"); - [Fact(Skip = "https://github.com/dotnet/roslyn/issues/55969")] + [Theory] + [InlineData("a")] + [InlineData("ar")] + [InlineData("arg")] + [InlineData("args")] + public async Task Parameters_02(string prefix) + { + await VerifyItemExistsAsync(prefix + "$$", "args", sourceCodeKind: SourceCodeKind.Regular); + } + + [Theory] + [InlineData("a")] + [InlineData("ar")] + [InlineData("arg")] + [InlineData("args")] + public async Task Parameters_03(string prefix) + { + await VerifyItemIsAbsentAsync(prefix + "$$", "args", sourceCodeKind: SourceCodeKind.Script); + } + + [Theory] + [InlineData("a")] + [InlineData("ar")] + [InlineData("arg")] + [InlineData("args")] + public async Task Parameters_04(string prefix) + { + await VerifyItemExistsAsync(prefix + @"$$ +Systen.Console.WriteLine(); +", "args", sourceCodeKind: SourceCodeKind.Regular); + } + + [Theory] + [InlineData("a")] + [InlineData("ar")] + [InlineData("arg")] + [InlineData("args")] + public async Task Parameters_05(string prefix) + { + await VerifyItemExistsAsync(@" +Systen.Console.WriteLine(); +" + prefix + "$$", "args", sourceCodeKind: SourceCodeKind.Regular); + } + + [Theory] + [InlineData("a")] + [InlineData("ar")] + [InlineData("arg")] + [InlineData("args")] + public async Task Parameters_06(string prefix) + { + await VerifyItemExistsAsync(@" +Systen.Console.WriteLine(); +" + prefix + @"$$ +Systen.Console.WriteLine(); +", "args", sourceCodeKind: SourceCodeKind.Regular); + } + + [Theory] + [InlineData("a")] + [InlineData("ar")] + [InlineData("arg")] + [InlineData("args")] + public async Task Parameters_07(string prefix) + { + await VerifyItemExistsAsync("call(" + prefix + "$$)", "args", sourceCodeKind: SourceCodeKind.Regular); + } + + [Fact] [Trait(Traits.Feature, Traits.Features.Completion)] [WorkItem(55969, "https://github.com/dotnet/roslyn/issues/55969")] public async Task Parameters_TopLevelStatement_1() - => await VerifyItemExistsAsync(@"$$", "args", sourceCodeKind: SourceCodeKind.Regular); + => await VerifyItemIsAbsentAsync(@"$$", "args", sourceCodeKind: SourceCodeKind.Regular); - [Fact(Skip = "https://github.com/dotnet/roslyn/issues/55969")] + [Fact] [Trait(Traits.Feature, Traits.Features.Completion)] [WorkItem(55969, "https://github.com/dotnet/roslyn/issues/55969")] public async Task Parameters_TopLevelStatement_2() @@ -1552,11 +1620,11 @@ public async Task Parameters_TopLevelStatement_2() Console.WriteLine(); $$", "args", sourceCodeKind: SourceCodeKind.Regular); - [Fact(Skip = "https://github.com/dotnet/roslyn/issues/55969")] + [Fact] [Trait(Traits.Feature, Traits.Features.Completion)] [WorkItem(55969, "https://github.com/dotnet/roslyn/issues/55969")] public async Task Parameters_TopLevelStatement_3() - => await VerifyItemExistsAsync( + => await VerifyItemIsAbsentAsync( @"using System; $$", "args", sourceCodeKind: SourceCodeKind.Regular); diff --git a/src/Workspaces/CSharpTest/Formatting/FormattingTests.cs b/src/Workspaces/CSharpTest/Formatting/FormattingTests.cs index 547f63d6ac91d..c248da2bed5b5 100644 --- a/src/Workspaces/CSharpTest/Formatting/FormattingTests.cs +++ b/src/Workspaces/CSharpTest/Formatting/FormattingTests.cs @@ -4433,7 +4433,7 @@ public async Task ColumnOfVeryFirstToken() { var code = @" W )b"; - var expected = @" W )b"; + var expected = @"W )b"; await AssertFormatAsync(expected, code); } diff --git a/src/Workspaces/CSharpTest/Formatting/FormattingTriviaTests.cs b/src/Workspaces/CSharpTest/Formatting/FormattingTriviaTests.cs index 4b57433d10896..8b4cf33fde063 100644 --- a/src/Workspaces/CSharpTest/Formatting/FormattingTriviaTests.cs +++ b/src/Workspaces/CSharpTest/Formatting/FormattingTriviaTests.cs @@ -1661,7 +1661,7 @@ public async Task FormatInvalidCode_1() public async Task FormatInvalidCode_2() { var content = @"> Roslyn.Utilities.dll! Line 43 + 0x5 bytes Basic"; - var expectedContent = @"> Roslyn.Utilities.dll! Line 43 + 0x5 bytes Basic"; + var expectedContent = @"> Roslyn.Utilities.dll! Line 43 + 0x5 bytes Basic"; await AssertFormatAsync(expectedContent, content); } From 9dc1cdc4782ab4bf0a4436bb1c20b4e173d30b78 Mon Sep 17 00:00:00 2001 From: AlekseyTs Date: Tue, 15 Nov 2022 08:16:43 -0800 Subject: [PATCH 2/3] Restore deleted test --- .../Syntax/LexicalAndXml/PreprocessorTests.cs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/Compilers/CSharp/Test/Syntax/LexicalAndXml/PreprocessorTests.cs b/src/Compilers/CSharp/Test/Syntax/LexicalAndXml/PreprocessorTests.cs index 10bb4f5692da1..564fe446ff0d2 100644 --- a/src/Compilers/CSharp/Test/Syntax/LexicalAndXml/PreprocessorTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/LexicalAndXml/PreprocessorTests.cs @@ -1704,6 +1704,21 @@ class B { } VerifyMembers(node, new MemberInfo { Kind = SyntaxKind.ClassDeclaration, Text = "B" }); } + [Fact] + [Trait("Feature", "Directives")] + public void TestNegIfEndifDirectivesWithBadCode() + { + var text = +@"#if true +#else +#endif +aeu"; + + var node = Parse(text); + TestRoundTripping(node, text, false); + VerifyDirectives(node, SyntaxKind.IfDirectiveTrivia, SyntaxKind.ElseDirectiveTrivia, SyntaxKind.EndIfDirectiveTrivia); + } + [Fact] [Trait("Feature", "Directives")] public void TestIfElifWithBoolExpression() From 598d4eacf17fedec5e0ce3823a7d6c5f6f972b1f Mon Sep 17 00:00:00 2001 From: AlekseyTs Date: Thu, 17 Nov 2022 08:55:46 -0800 Subject: [PATCH 3/3] Implement suggested refactoring --- .../CSharp/Portable/Parser/LanguageParser.cs | 70 +++++++++++-------- 1 file changed, 40 insertions(+), 30 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs b/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs index 06397133f0df0..6b2456af301ef 100644 --- a/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs +++ b/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs @@ -2631,37 +2631,10 @@ private MemberDeclarationSyntax ParseMemberDeclarationOrStatementCore(SyntaxKind return result; } - if (!haveModifiers) + if (!haveModifiers && + tryParseStatement(attributes, ref afterAttributesPoint, out result)) { - var resetOnFailurePoint = this.GetResetPoint(); - try - { - this.Reset(ref afterAttributesPoint); - - if (this.IsPossibleStatement(acceptAccessibilityMods: false)) - { - var saveTerm = _termState; - _termState |= TerminatorState.IsPossibleStatementStartOrStop; // partial statements can abort if a new statement starts - bool wasInAsync = IsInAsync; - IsInAsync = true; // We are implicitly in an async context - - var statement = this.ParseStatementCore(attributes, isGlobal: true); - - IsInAsync = wasInAsync; - _termState = saveTerm; - - if (statement is not null) - { - return CheckTopLevelStatementsFeatureAvailability(_syntaxFactory.GlobalStatement(statement)); - } - } - - this.Reset(ref resetOnFailurePoint); - } - finally - { - this.Release(ref resetOnFailurePoint); - } + return result; } } @@ -2701,6 +2674,43 @@ bool tryParseLocalDeclarationStatement(SyntaxList attributes, ref ResetPoint afterAttributesPoint, out MemberDeclarationSyntax result) + { + var resetOnFailurePoint = this.GetResetPoint(); + try + { + this.Reset(ref afterAttributesPoint); + + if (this.IsPossibleStatement(acceptAccessibilityMods: false)) + { + var saveTerm = _termState; + _termState |= TerminatorState.IsPossibleStatementStartOrStop; // partial statements can abort if a new statement starts + bool wasInAsync = IsInAsync; + IsInAsync = true; // We are implicitly in an async context + + var statement = this.ParseStatementCore(attributes, isGlobal: true); + + IsInAsync = wasInAsync; + _termState = saveTerm; + + if (statement is not null) + { + result = CheckTopLevelStatementsFeatureAvailability(_syntaxFactory.GlobalStatement(statement)); + return true; + } + } + + this.Reset(ref resetOnFailurePoint); + } + finally + { + this.Release(ref resetOnFailurePoint); + } + + result = null; + return false; + } + bool tryParseLocalDeclarationStatementFromStartPoint(SyntaxList attributes, ref ResetPoint startPoint, out MemberDeclarationSyntax result) where DeclarationSyntax : StatementSyntax { var resetOnFailurePoint = this.GetResetPoint();