From d6145641b66d007f0b046d42155c39e4ccc22476 Mon Sep 17 00:00:00 2001 From: Youssef Victor Date: Thu, 21 Jul 2022 18:51:07 +0200 Subject: [PATCH] Produce errors for 'partial file record' (#62686) --- .../CSharp/Portable/Parser/LanguageParser.cs | 6 +- .../Portable/Symbols/Source/ModifierUtils.cs | 26 ++- .../Symbols/Source/SourceConstructorSymbol.cs | 2 +- .../Symbols/Source/SourceDestructorSymbol.cs | 2 +- .../Symbols/Source/SourceEventSymbol.cs | 2 +- .../Symbols/Source/SourceMemberFieldSymbol.cs | 2 +- .../Source/SourceOrdinaryMethodSymbol.cs | 2 +- .../Source/SourcePropertyAccessorSymbol.cs | 2 +- .../Symbols/Source/SourcePropertySymbol.cs | 2 +- .../SourceUserDefinedOperatorSymbolBase.cs | 2 +- .../Test/Semantic/Semantics/LambdaTests.cs | 75 ++++++++ .../CSharp/Test/Symbol/Symbols/EnumTests.cs | 12 ++ .../Test/Symbol/Symbols/LocalFunctionTests.cs | 87 +++++++++ .../Symbol/Symbols/Source/DelegateTests.cs | 30 +++ .../Test/Symbol/Symbols/SymbolErrorTests.cs | 175 ++++++++++++++++++ .../Syntax/Parsing/DeclarationParsingTests.cs | 3 - .../Parsing/FileModifierParsingTests.cs | 39 ++-- .../Syntax/Parsing/ParserErrorMessageTests.cs | 10 - .../Test/Syntax/Parsing/RoundTrippingTests.cs | 3 +- .../Test/Syntax/Parsing/ScriptParsingTests.cs | 32 ++-- .../Parsing/TopLevelStatementsParsingTests.cs | 26 ++- 21 files changed, 470 insertions(+), 70 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs b/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs index 721bb5f3e601e..0eed54af34f15 100644 --- a/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs +++ b/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs @@ -1212,10 +1212,8 @@ private void ParseModifiers(SyntaxListBuilder tokens, bool forAccessors, bool fo nextToken.Kind == SyntaxKind.DelegateKeyword || (IsPossibleStartOfTypeDeclaration(nextToken.Kind) && GetModifier(nextToken) != DeclarationModifiers.None)) { - // Misplaced partial - // TODO(https://github.com/dotnet/roslyn/issues/22439): - // We should consider moving this check into binding, but avoid holding on to trees - modTok = AddError(ConvertToKeyword(this.EatToken()), ErrorCode.ERR_PartialMisplaced); + // Error reported in ModifierUtils. + modTok = ConvertToKeyword(this.EatToken()); } else { diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/ModifierUtils.cs b/src/Compilers/CSharp/Portable/Symbols/Source/ModifierUtils.cs index 86180610ecd95..6ca2b298f7250 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/ModifierUtils.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/ModifierUtils.cs @@ -12,7 +12,7 @@ namespace Microsoft.CodeAnalysis.CSharp.Symbols internal static class ModifierUtils { internal static DeclarationModifiers MakeAndCheckNontypeMemberModifiers( - bool isForTypeDeclaration, + bool isOrdinaryMethod, bool isForInterfaceMember, SyntaxTokenList modifiers, DeclarationModifiers defaultAccess, @@ -21,8 +21,8 @@ internal static class ModifierUtils BindingDiagnosticBag diagnostics, out bool modifierErrors) { - var result = modifiers.ToDeclarationModifiers(diagnostics.DiagnosticBag ?? new DiagnosticBag()); - result = CheckModifiers(isForTypeDeclaration, isForInterfaceMember, result, allowedModifiers, errorLocation, diagnostics, modifiers, out modifierErrors); + var result = modifiers.ToDeclarationModifiers(diagnostics.DiagnosticBag ?? new DiagnosticBag(), isOrdinaryMethod: isOrdinaryMethod); + result = CheckModifiers(isForTypeDeclaration: false, isForInterfaceMember, result, allowedModifiers, errorLocation, diagnostics, modifiers, out modifierErrors); if ((result & DeclarationModifiers.AccessibilityMask) == 0) { @@ -382,21 +382,32 @@ private static DeclarationModifiers ToDeclarationModifier(SyntaxKind kind) } public static DeclarationModifiers ToDeclarationModifiers( - this SyntaxTokenList modifiers, DiagnosticBag diagnostics) + this SyntaxTokenList modifiers, DiagnosticBag diagnostics, bool isOrdinaryMethod = false) { var result = DeclarationModifiers.None; bool seenNoDuplicates = true; - bool seenNoAccessibilityDuplicates = true; - foreach (var modifier in modifiers) + for (int i = 0; i < modifiers.Count; i++) { + SyntaxToken modifier = modifiers[i]; DeclarationModifiers one = ToDeclarationModifier(modifier.ContextualKind()); ReportDuplicateModifiers( modifier, one, result, - ref seenNoDuplicates, ref seenNoAccessibilityDuplicates, + ref seenNoDuplicates, diagnostics); + if (one == DeclarationModifiers.Partial && i < modifiers.Count - 1) + { + // There was a bug where we allowed `partial async` at the end of modifiers on methods. We keep this behavior for backcompat. + if (!(isOrdinaryMethod && i == modifiers.Count - 2 && ToDeclarationModifier(modifiers[i + 1].ContextualKind()) == DeclarationModifiers.Async)) + { + diagnostics.Add( + ErrorCode.ERR_PartialMisplaced, + modifier.GetLocation()); + } + } + result |= one; } @@ -423,7 +434,6 @@ private static DeclarationModifiers ToDeclarationModifier(SyntaxKind kind) DeclarationModifiers modifierKind, DeclarationModifiers allModifiers, ref bool seenNoDuplicates, - ref bool seenNoAccessibilityDuplicates, DiagnosticBag diagnostics) { if ((allModifiers & modifierKind) != 0) diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceConstructorSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceConstructorSymbol.cs index 4e8b19878fbb5..60a4778d46996 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceConstructorSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceConstructorSymbol.cs @@ -107,7 +107,7 @@ private DeclarationModifiers MakeModifiers(SyntaxTokenList modifiers, MethodKind DeclarationModifiers.Unsafe; bool isInterface = ContainingType.IsInterface; - var mods = ModifierUtils.MakeAndCheckNontypeMemberModifiers(isForTypeDeclaration: false, isForInterfaceMember: isInterface, modifiers, defaultAccess, allowedModifiers, location, diagnostics, out modifierErrors); + var mods = ModifierUtils.MakeAndCheckNontypeMemberModifiers(isOrdinaryMethod: false, isForInterfaceMember: isInterface, modifiers, defaultAccess, allowedModifiers, location, diagnostics, out modifierErrors); this.CheckUnsafeModifier(mods, diagnostics); diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceDestructorSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceDestructorSymbol.cs index 39e067dbe76c6..5a7af1f4e8990 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceDestructorSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceDestructorSymbol.cs @@ -123,7 +123,7 @@ private DeclarationModifiers MakeModifiers(SyntaxTokenList modifiers, Location l { // Check that the set of modifiers is allowed const DeclarationModifiers allowedModifiers = DeclarationModifiers.Extern | DeclarationModifiers.Unsafe; - var mods = ModifierUtils.MakeAndCheckNontypeMemberModifiers(isForTypeDeclaration: false, isForInterfaceMember: ContainingType.IsInterface, modifiers, DeclarationModifiers.None, allowedModifiers, location, diagnostics, out modifierErrors); + var mods = ModifierUtils.MakeAndCheckNontypeMemberModifiers(isOrdinaryMethod: false, isForInterfaceMember: ContainingType.IsInterface, modifiers, DeclarationModifiers.None, allowedModifiers, location, diagnostics, out modifierErrors); this.CheckUnsafeModifier(mods, diagnostics); diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceEventSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceEventSymbol.cs index ad0c6f2e34a0c..0cb10a9901503 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceEventSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceEventSymbol.cs @@ -488,7 +488,7 @@ private void CheckAccessibility(Location location, BindingDiagnosticBag diagnost allowedModifiers |= DeclarationModifiers.Extern; } - var mods = ModifierUtils.MakeAndCheckNontypeMemberModifiers(isForTypeDeclaration: false, isForInterfaceMember: isInterface, + var mods = ModifierUtils.MakeAndCheckNontypeMemberModifiers(isOrdinaryMethod: false, isForInterfaceMember: isInterface, modifiers, defaultAccess, allowedModifiers, location, diagnostics, out modifierErrors); ModifierUtils.CheckFeatureAvailabilityForStaticAbstractMembersInInterfacesIfNeeded(mods, explicitInterfaceImplementation, location, diagnostics); diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberFieldSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberFieldSymbol.cs index a6949bbcbed85..f3818d90b81dd 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberFieldSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberFieldSymbol.cs @@ -166,7 +166,7 @@ internal static DeclarationModifiers MakeModifiers(NamedTypeSymbol containingTyp var errorLocation = new SourceLocation(firstIdentifier); DeclarationModifiers result = ModifierUtils.MakeAndCheckNontypeMemberModifiers( - isForTypeDeclaration: false, isForInterfaceMember: isInterface, + isOrdinaryMethod: false, isForInterfaceMember: isInterface, modifiers, defaultAccess, allowedModifiers, errorLocation, diagnostics, out modifierErrors); if ((result & DeclarationModifiers.Abstract) != 0) diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceOrdinaryMethodSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceOrdinaryMethodSymbol.cs index 73a2c91b162f0..257b1c7f9978b 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceOrdinaryMethodSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceOrdinaryMethodSymbol.cs @@ -515,7 +515,7 @@ internal override bool IsExpressionBodied protected override DeclarationModifiers MakeDeclarationModifiers(DeclarationModifiers allowedModifiers, BindingDiagnosticBag diagnostics) { var syntax = GetSyntax(); - return ModifierUtils.MakeAndCheckNontypeMemberModifiers(isForTypeDeclaration: false, isForInterfaceMember: ContainingType.IsInterface, + return ModifierUtils.MakeAndCheckNontypeMemberModifiers(isOrdinaryMethod: true, isForInterfaceMember: ContainingType.IsInterface, syntax.Modifiers, defaultAccess: DeclarationModifiers.None, allowedModifiers, Locations[0], diagnostics, out _); } diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertyAccessorSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertyAccessorSymbol.cs index 9281e38c0bfea..5ea0a59236811 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertyAccessorSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertyAccessorSymbol.cs @@ -508,7 +508,7 @@ internal sealed override bool IsDeclaredReadOnly defaultInterfaceImplementationModifiers = DeclarationModifiers.AccessibilityMask; } - var mods = ModifierUtils.MakeAndCheckNontypeMemberModifiers(isForTypeDeclaration: false, isForInterfaceMember: isInterface, + var mods = ModifierUtils.MakeAndCheckNontypeMemberModifiers(isOrdinaryMethod: false, isForInterfaceMember: isInterface, modifiers, defaultAccess, allowedModifiers, location, diagnostics, out modifierErrors); ModifierUtils.ReportDefaultInterfaceImplementationModifiers(hasBody, mods, diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbol.cs index 4426258799b56..74cf7603f3668 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbol.cs @@ -334,7 +334,7 @@ private static AccessorDeclarationSyntax GetSetAccessorDeclaration(BasePropertyD allowedModifiers |= DeclarationModifiers.Extern; - var mods = ModifierUtils.MakeAndCheckNontypeMemberModifiers(isForTypeDeclaration: false, isForInterfaceMember: isInterface, + var mods = ModifierUtils.MakeAndCheckNontypeMemberModifiers(isOrdinaryMethod: false, isForInterfaceMember: isInterface, modifiers, defaultAccess, allowedModifiers, location, diagnostics, out modifierErrors); ModifierUtils.CheckFeatureAvailabilityForStaticAbstractMembersInInterfacesIfNeeded(mods, isExplicitInterfaceImplementation, location, diagnostics); diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceUserDefinedOperatorSymbolBase.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceUserDefinedOperatorSymbolBase.cs index 46da86f3d889f..7ac58a62879c8 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceUserDefinedOperatorSymbolBase.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceUserDefinedOperatorSymbolBase.cs @@ -149,7 +149,7 @@ protected static DeclarationModifiers MakeDeclarationModifiers(MethodKind method } var result = ModifierUtils.MakeAndCheckNontypeMemberModifiers( - isForTypeDeclaration: false, isForInterfaceMember: inInterface, + isOrdinaryMethod: false, isForInterfaceMember: inInterface, syntax.Modifiers, defaultAccess, allowedModifiers, location, diagnostics, modifierErrors: out _); if (inInterface) diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/LambdaTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/LambdaTests.cs index df26acaf747ee..8d107c0a61c3a 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/LambdaTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/LambdaTests.cs @@ -6783,6 +6783,81 @@ static void Main() Assert.Equal(RefKind.Out, lambdas[2].Parameters[0].RefKind); } + [Fact] + public void StaticPartialLambda() + { + CreateCompilation(""" + class C + { + void M() + { + System.Action x = static partial () => { }; + } + } + """).VerifyDiagnostics( + // (5,27): error CS8934: Cannot convert lambda expression to type 'Action' because the return type does not match the delegate return type + // System.Action x = static partial () => { }; + Diagnostic(ErrorCode.ERR_CantConvAnonMethReturnType, "static partial () => { }").WithArguments("lambda expression", "System.Action").WithLocation(5, 27), + // (5,34): error CS0246: The type or namespace name 'partial' could not be found (are you missing a using directive or an assembly reference?) + // System.Action x = static partial () => { }; + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "partial").WithArguments("partial").WithLocation(5, 34)); + } + + [Fact] + public void PartialStaticLambda() + { + CreateCompilation(""" + class C + { + void M() + { + System.Action x = partial static () => { }; + } + } + """).VerifyDiagnostics( + // (5,27): error CS0103: The name 'partial' does not exist in the current context + // System.Action x = partial static () => { }; + Diagnostic(ErrorCode.ERR_NameNotInContext, "partial").WithArguments("partial").WithLocation(5, 27), + // (5,35): error CS1002: ; expected + // System.Action x = partial static () => { }; + Diagnostic(ErrorCode.ERR_SemicolonExpected, "static").WithLocation(5, 35), + // (5,35): error CS0106: The modifier 'static' is not valid for this item + // System.Action x = partial static () => { }; + Diagnostic(ErrorCode.ERR_BadMemberFlag, "static").WithArguments("static").WithLocation(5, 35), + // (5,43): error CS8124: Tuple must contain at least two elements. + // System.Action x = partial static () => { }; + Diagnostic(ErrorCode.ERR_TupleTooFewElements, ")").WithLocation(5, 43), + // (5,45): error CS1001: Identifier expected + // System.Action x = partial static () => { }; + Diagnostic(ErrorCode.ERR_IdentifierExpected, "=>").WithLocation(5, 45), + // (5,45): error CS1003: Syntax error, ',' expected + // System.Action x = partial static () => { }; + Diagnostic(ErrorCode.ERR_SyntaxError, "=>").WithArguments(",").WithLocation(5, 45), + // (5,48): error CS1002: ; expected + // System.Action x = partial static () => { }; + Diagnostic(ErrorCode.ERR_SemicolonExpected, "{").WithLocation(5, 48)); + } + + [Fact] + public void PartialLambda() + { + CreateCompilation(""" + class C + { + void M() + { + System.Action x = partial () => { }; + } + } + """).VerifyDiagnostics( + // (5,27): error CS0246: The type or namespace name 'partial' could not be found (are you missing a using directive or an assembly reference?) + // System.Action x = partial () => { }; + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "partial").WithArguments("partial").WithLocation(5, 27), + // (5,27): error CS8934: Cannot convert lambda expression to type 'Action' because the return type does not match the delegate return type + // System.Action x = partial () => { }; + Diagnostic(ErrorCode.ERR_CantConvAnonMethReturnType, "partial () => { }").WithArguments("lambda expression", "System.Action").WithLocation(5, 27)); + } + [WorkItem(61013, "https://github.com/dotnet/roslyn/issues/61013")] [Fact] public void InvalidCast() diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/EnumTests.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/EnumTests.cs index 44c3121545ded..e615c2da0e765 100644 --- a/src/Compilers/CSharp/Test/Symbol/Symbols/EnumTests.cs +++ b/src/Compilers/CSharp/Test/Symbol/Symbols/EnumTests.cs @@ -399,5 +399,17 @@ static void Main() Diagnostic(ErrorCode.ERR_NoTypeDef, "F").WithArguments("A", "UseSiteError_sourceA, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").WithLocation(5, 20) ); } + + [Fact] + public void PartialPublicEnum() + { + CreateCompilation("partial public enum E { }").VerifyDiagnostics( + // (1,1): error CS0267: The 'partial' modifier can only appear immediately before 'class', 'record', 'struct', 'interface', or a method return type. + // partial public enum E { } + Diagnostic(ErrorCode.ERR_PartialMisplaced, "partial").WithLocation(1, 1), + // (1,21): error CS0267: The 'partial' modifier can only appear immediately before 'class', 'record', 'struct', 'interface', or a method return type. + // partial public enum E { } + Diagnostic(ErrorCode.ERR_PartialMisplaced, "E").WithLocation(1, 21)); + } } } diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/LocalFunctionTests.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/LocalFunctionTests.cs index 5b8464902e893..d00b5f4beaefd 100644 --- a/src/Compilers/CSharp/Test/Symbol/Symbols/LocalFunctionTests.cs +++ b/src/Compilers/CSharp/Test/Symbol/Symbols/LocalFunctionTests.cs @@ -102,5 +102,92 @@ void M() var staticLocal = semanticModel.GetDeclaredSymbol(localsSyntax[0]).GetSymbol(); Assert.False(staticLocal.RequiresInstanceReceiver); } + + [Fact] + public void PartialStaticLocalFunction() + { + CreateCompilation(""" + public class C + { + public void M() + { + partial static void local() { } + } + } + """).VerifyDiagnostics( + // (5,9): error CS0103: The name 'partial' does not exist in the current context + // partial static void local() { } + Diagnostic(ErrorCode.ERR_NameNotInContext, "partial").WithArguments("partial").WithLocation(5, 9), + // (5,17): error CS1002: ; expected + // partial static void local() { } + Diagnostic(ErrorCode.ERR_SemicolonExpected, "static").WithLocation(5, 17), + // (5,29): warning CS8321: The local function 'local' is declared but never used + // partial static void local() { } + Diagnostic(ErrorCode.WRN_UnreferencedLocalFunction, "local").WithArguments("local").WithLocation(5, 29)); + } + + [Fact] + public void StaticPartialLocalFunction() + { + CreateCompilation(""" + public class C + { + public void M() + { + static partial void local() { } + } + } + """).VerifyDiagnostics( + // (5,9): error CS0106: The modifier 'static' is not valid for this item + // static partial void local() { } + Diagnostic(ErrorCode.ERR_BadMemberFlag, "static").WithArguments("static").WithLocation(5, 9), + // (5,16): error CS1031: Type expected + // static partial void local() { } + Diagnostic(ErrorCode.ERR_TypeExpected, "partial").WithLocation(5, 16), + // (5,16): error CS1525: Invalid expression term 'partial' + // static partial void local() { } + Diagnostic(ErrorCode.ERR_InvalidExprTerm, "partial").WithArguments("partial").WithLocation(5, 16), + // (5,16): error CS1002: ; expected + // static partial void local() { } + Diagnostic(ErrorCode.ERR_SemicolonExpected, "partial").WithLocation(5, 16), + // (5,16): error CS1513: } expected + // static partial void local() { } + Diagnostic(ErrorCode.ERR_RbraceExpected, "partial").WithLocation(5, 16), + // (5,29): error CS0759: No defining declaration found for implementing declaration of partial method 'C.local()' + // static partial void local() { } + Diagnostic(ErrorCode.ERR_PartialMethodMustHaveLatent, "local").WithArguments("C.local()").WithLocation(5, 29), + // (5,29): error CS0751: A partial method must be declared within a partial type + // static partial void local() { } + Diagnostic(ErrorCode.ERR_PartialMethodOnlyInPartialClass, "local").WithLocation(5, 29), + // (7,1): error CS1022: Type or namespace definition, or end-of-file expected + // } + Diagnostic(ErrorCode.ERR_EOFExpected, "}").WithLocation(7, 1)); + } + + [Fact] + public void PartialLocalFunction() + { + CreateCompilation(""" + public class C + { + public void M() + { + partial void local() { } + } + } + """).VerifyDiagnostics( + // (4,6): error CS1513: } expected + // { + Diagnostic(ErrorCode.ERR_RbraceExpected, "").WithLocation(4, 6), + // (5,22): error CS0759: No defining declaration found for implementing declaration of partial method 'C.local()' + // partial void local() { } + Diagnostic(ErrorCode.ERR_PartialMethodMustHaveLatent, "local").WithArguments("C.local()").WithLocation(5, 22), + // (5,22): error CS0751: A partial method must be declared within a partial type + // partial void local() { } + Diagnostic(ErrorCode.ERR_PartialMethodOnlyInPartialClass, "local").WithLocation(5, 22), + // (7,1): error CS1022: Type or namespace definition, or end-of-file expected + // } + Diagnostic(ErrorCode.ERR_EOFExpected, "}").WithLocation(7, 1)); + } } } diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/Source/DelegateTests.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/Source/DelegateTests.cs index 3272fbc03002f..6475a1433efab 100644 --- a/src/Compilers/CSharp/Test/Symbol/Symbols/Source/DelegateTests.cs +++ b/src/Compilers/CSharp/Test/Symbol/Symbols/Source/DelegateTests.cs @@ -790,5 +790,35 @@ public static void Main() Assert.True(lambda.ReturnsByRefReadonly); Assert.Equal(RefKind.In, lambda.Parameters[0].RefKind); } + + [Fact] + public void PartialPublicDelegate() + { + CreateCompilation("partial public delegate void M();").VerifyDiagnostics( + // (1,1): error CS0267: The 'partial' modifier can only appear immediately before 'class', 'record', 'struct', 'interface', or a method return type. + // partial public delegate void M(); + Diagnostic(ErrorCode.ERR_PartialMisplaced, "partial").WithLocation(1, 1), + // (1,30): error CS0267: The 'partial' modifier can only appear immediately before 'class', 'record', 'struct', 'interface', or a method return type. + // partial public delegate void M(); + Diagnostic(ErrorCode.ERR_PartialMisplaced, "M").WithLocation(1, 30)); + } + + [Fact] + public void PublicPartialDelegate() + { + CreateCompilation("public partial delegate void M();").VerifyDiagnostics( + // (1,30): error CS0267: The 'partial' modifier can only appear immediately before 'class', 'record', 'struct', 'interface', or a method return type. + // public partial delegate void M(); + Diagnostic(ErrorCode.ERR_PartialMisplaced, "M").WithLocation(1, 30)); + } + + [Fact] + public void PartialDelegate() + { + CreateCompilation("public partial delegate void M();").VerifyDiagnostics( + // (1,30): error CS0267: The 'partial' modifier can only appear immediately before 'class', 'record', 'struct', 'interface', or a method return type. + // public partial delegate void M(); + Diagnostic(ErrorCode.ERR_PartialMisplaced, "M").WithLocation(1, 30)); + } } } diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/SymbolErrorTests.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/SymbolErrorTests.cs index 5de747ddf36f8..84467f7147533 100644 --- a/src/Compilers/CSharp/Test/Symbol/Symbols/SymbolErrorTests.cs +++ b/src/Compilers/CSharp/Test/Symbol/Symbols/SymbolErrorTests.cs @@ -21845,5 +21845,180 @@ string featureName Diagnostic(ErrorCode.ERR_UnsupportedCompilerFeature, "C1").WithArguments("C1", "SomeFeatureIsRequired").WithLocation(4, 35) ); } + + [Fact] + public void PartialConstructor() + { + CreateCompilation(new[] + { + """ + public class PartialCtor + { + partial PartialCtor() { } + } + """, + """ + public class PublicPartialCtor + { + public partial PublicPartialCtor() { } + } + """, + """ + public class PartialPublicCtor + { + partial public PartialPublicCtor() { } + } + """ + }).VerifyDiagnostics( + // (3,5): error CS0267: The 'partial' modifier can only appear immediately before 'class', 'record', 'struct', 'interface', or a method return type. + // partial public PartialPublicCtor() { } + Diagnostic(ErrorCode.ERR_PartialMisplaced, "partial").WithLocation(3, 5), + // (3,5): error CS0267: The 'partial' modifier can only appear immediately before 'class', 'record', 'struct', 'interface', or a method return type. + // partial public PartialPublicCtor() { } + Diagnostic(ErrorCode.ERR_PartialMisplaced, "partial").WithLocation(3, 5), + // (3,5): error CS0246: The type or namespace name 'partial' could not be found (are you missing a using directive or an assembly reference?) + // partial PartialCtor() { } + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "partial").WithArguments("partial").WithLocation(3, 5), + // (3,12): error CS0246: The type or namespace name 'partial' could not be found (are you missing a using directive or an assembly reference?) + // public partial PublicPartialCtor() { } + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "partial").WithArguments("partial").WithLocation(3, 12), + // (3,13): error CS0542: 'PartialCtor': member names cannot be the same as their enclosing type + // partial PartialCtor() { } + Diagnostic(ErrorCode.ERR_MemberNameSameAsType, "PartialCtor").WithArguments("PartialCtor").WithLocation(3, 13), + // (3,13): error CS0161: 'PartialCtor.PartialCtor()': not all code paths return a value + // partial PartialCtor() { } + Diagnostic(ErrorCode.ERR_ReturnExpected, "PartialCtor").WithArguments("PartialCtor.PartialCtor()").WithLocation(3, 13), + // (3,20): error CS0542: 'PublicPartialCtor': member names cannot be the same as their enclosing type + // public partial PublicPartialCtor() { } + Diagnostic(ErrorCode.ERR_MemberNameSameAsType, "PublicPartialCtor").WithArguments("PublicPartialCtor").WithLocation(3, 20), + // (3,20): error CS0161: 'PublicPartialCtor.PublicPartialCtor()': not all code paths return a value + // public partial PublicPartialCtor() { } + Diagnostic(ErrorCode.ERR_ReturnExpected, "PublicPartialCtor").WithArguments("PublicPartialCtor.PublicPartialCtor()").WithLocation(3, 20)); + } + + [Fact] + public void PartialStaticConstructor() + { + CreateCompilation(new[] + { + """ + public class PartialStaticCtor + { + partial static PartialStaticCtor() { } + } + """, + """ + public class StaticPartialCtor + { + static partial StaticPartialCtor() { } + } + """, + """ + public class PublicStaticPartialCtor + { + public static partial PublicStaticPartialCtor() { } + } + """, + """ + public class PublicPartialStaticCtor + { + public partial static PublicPartialStaticCtor() { } + } + """, + """ + public class StaticPublicPartialCtor + { + static public partial StaticPublicPartialCtor() { } + } + """, + """ + public class StaticPartialPublicCtor + { + static partial public StaticPartialPublicCtor() { } + } + """, + """ + public class PartialStaticPublicCtor + { + partial static public PartialStaticPublicCtor() { } + } + """, + """ + public class PartialPublicStaticCtor + { + partial public static PartialPublicStaticCtor() { } + } + """, + }).VerifyDiagnostics( + // (3,5): error CS0267: The 'partial' modifier can only appear immediately before 'class', 'record', 'struct', 'interface', or a method return type. + // partial static PartialStaticCtor() { } + Diagnostic(ErrorCode.ERR_PartialMisplaced, "partial").WithLocation(3, 5), + // (3,5): error CS0267: The 'partial' modifier can only appear immediately before 'class', 'record', 'struct', 'interface', or a method return type. + // partial static PartialStaticCtor() { } + Diagnostic(ErrorCode.ERR_PartialMisplaced, "partial").WithLocation(3, 5), + // (3,5): error CS0267: The 'partial' modifier can only appear immediately before 'class', 'record', 'struct', 'interface', or a method return type. + // partial public static PartialPublicStaticCtor() { } + Diagnostic(ErrorCode.ERR_PartialMisplaced, "partial").WithLocation(3, 5), + // (3,5): error CS0267: The 'partial' modifier can only appear immediately before 'class', 'record', 'struct', 'interface', or a method return type. + // partial public static PartialPublicStaticCtor() { } + Diagnostic(ErrorCode.ERR_PartialMisplaced, "partial").WithLocation(3, 5), + // (3,5): error CS0267: The 'partial' modifier can only appear immediately before 'class', 'record', 'struct', 'interface', or a method return type. + // partial static public PartialStaticPublicCtor() { } + Diagnostic(ErrorCode.ERR_PartialMisplaced, "partial").WithLocation(3, 5), + // (3,5): error CS0267: The 'partial' modifier can only appear immediately before 'class', 'record', 'struct', 'interface', or a method return type. + // partial static public PartialStaticPublicCtor() { } + Diagnostic(ErrorCode.ERR_PartialMisplaced, "partial").WithLocation(3, 5), + // (3,12): error CS0267: The 'partial' modifier can only appear immediately before 'class', 'record', 'struct', 'interface', or a method return type. + // public partial static PublicPartialStaticCtor() { } + Diagnostic(ErrorCode.ERR_PartialMisplaced, "partial").WithLocation(3, 12), + // (3,12): error CS0267: The 'partial' modifier can only appear immediately before 'class', 'record', 'struct', 'interface', or a method return type. + // public partial static PublicPartialStaticCtor() { } + Diagnostic(ErrorCode.ERR_PartialMisplaced, "partial").WithLocation(3, 12), + // (3,12): error CS0267: The 'partial' modifier can only appear immediately before 'class', 'record', 'struct', 'interface', or a method return type. + // static partial public StaticPartialPublicCtor() { } + Diagnostic(ErrorCode.ERR_PartialMisplaced, "partial").WithLocation(3, 12), + // (3,12): error CS0267: The 'partial' modifier can only appear immediately before 'class', 'record', 'struct', 'interface', or a method return type. + // static partial public StaticPartialPublicCtor() { } + Diagnostic(ErrorCode.ERR_PartialMisplaced, "partial").WithLocation(3, 12), + // (3,12): error CS0246: The type or namespace name 'partial' could not be found (are you missing a using directive or an assembly reference?) + // static partial StaticPartialCtor() { } + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "partial").WithArguments("partial").WithLocation(3, 12), + // (3,19): error CS0246: The type or namespace name 'partial' could not be found (are you missing a using directive or an assembly reference?) + // public static partial PublicStaticPartialCtor() { } + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "partial").WithArguments("partial").WithLocation(3, 19), + // (3,19): error CS0246: The type or namespace name 'partial' could not be found (are you missing a using directive or an assembly reference?) + // static public partial StaticPublicPartialCtor() { } + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "partial").WithArguments("partial").WithLocation(3, 19), + // (3,20): error CS0542: 'StaticPartialCtor': member names cannot be the same as their enclosing type + // static partial StaticPartialCtor() { } + Diagnostic(ErrorCode.ERR_MemberNameSameAsType, "StaticPartialCtor").WithArguments("StaticPartialCtor").WithLocation(3, 20), + // (3,20): error CS0161: 'StaticPartialCtor.StaticPartialCtor()': not all code paths return a value + // static partial StaticPartialCtor() { } + Diagnostic(ErrorCode.ERR_ReturnExpected, "StaticPartialCtor").WithArguments("StaticPartialCtor.StaticPartialCtor()").WithLocation(3, 20), + // (3,27): error CS0515: 'PartialPublicStaticCtor.PartialPublicStaticCtor()': access modifiers are not allowed on static constructors + // partial public static PartialPublicStaticCtor() { } + Diagnostic(ErrorCode.ERR_StaticConstructorWithAccessModifiers, "PartialPublicStaticCtor").WithArguments("PartialPublicStaticCtor.PartialPublicStaticCtor()").WithLocation(3, 27), + // (3,27): error CS0515: 'PublicPartialStaticCtor.PublicPartialStaticCtor()': access modifiers are not allowed on static constructors + // public partial static PublicPartialStaticCtor() { } + Diagnostic(ErrorCode.ERR_StaticConstructorWithAccessModifiers, "PublicPartialStaticCtor").WithArguments("PublicPartialStaticCtor.PublicPartialStaticCtor()").WithLocation(3, 27), + // (3,27): error CS0515: 'StaticPartialPublicCtor.StaticPartialPublicCtor()': access modifiers are not allowed on static constructors + // static partial public StaticPartialPublicCtor() { } + Diagnostic(ErrorCode.ERR_StaticConstructorWithAccessModifiers, "StaticPartialPublicCtor").WithArguments("StaticPartialPublicCtor.StaticPartialPublicCtor()").WithLocation(3, 27), + // (3,27): error CS0515: 'PartialStaticPublicCtor.PartialStaticPublicCtor()': access modifiers are not allowed on static constructors + // partial static public PartialStaticPublicCtor() { } + Diagnostic(ErrorCode.ERR_StaticConstructorWithAccessModifiers, "PartialStaticPublicCtor").WithArguments("PartialStaticPublicCtor.PartialStaticPublicCtor()").WithLocation(3, 27), + // (3,27): error CS0542: 'StaticPublicPartialCtor': member names cannot be the same as their enclosing type + // static public partial StaticPublicPartialCtor() { } + Diagnostic(ErrorCode.ERR_MemberNameSameAsType, "StaticPublicPartialCtor").WithArguments("StaticPublicPartialCtor").WithLocation(3, 27), + // (3,27): error CS0542: 'PublicStaticPartialCtor': member names cannot be the same as their enclosing type + // public static partial PublicStaticPartialCtor() { } + Diagnostic(ErrorCode.ERR_MemberNameSameAsType, "PublicStaticPartialCtor").WithArguments("PublicStaticPartialCtor").WithLocation(3, 27), + // (3,27): error CS0161: 'StaticPublicPartialCtor.StaticPublicPartialCtor()': not all code paths return a value + // static public partial StaticPublicPartialCtor() { } + Diagnostic(ErrorCode.ERR_ReturnExpected, "StaticPublicPartialCtor").WithArguments("StaticPublicPartialCtor.StaticPublicPartialCtor()").WithLocation(3, 27), + // (3,27): error CS0161: 'PublicStaticPartialCtor.PublicStaticPartialCtor()': not all code paths return a value + // public static partial PublicStaticPartialCtor() { } + Diagnostic(ErrorCode.ERR_ReturnExpected, "PublicStaticPartialCtor").WithArguments("PublicStaticPartialCtor.PublicStaticPartialCtor()").WithLocation(3, 27)); + } } } diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/DeclarationParsingTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/DeclarationParsingTests.cs index a0f882f108be7..ea0b0e036738c 100644 --- a/src/Compilers/CSharp/Test/Syntax/Parsing/DeclarationParsingTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/DeclarationParsingTests.cs @@ -5757,9 +5757,6 @@ public void TestPartialEnum() { var text = @"partial enum E{}"; CreateCompilationWithMscorlib45(text).VerifyDiagnostics( - // (1,1): error CS0267: The 'partial' modifier can only appear immediately before 'class', 'record', 'struct', 'interface', or a method return type. - // partial enum E{} - Diagnostic(ErrorCode.ERR_PartialMisplaced, "partial").WithLocation(1, 1), // (1,14): error CS0267: The 'partial' modifier can only appear immediately before 'class', 'record', 'struct', 'interface', or a method return type. // partial enum E{} Diagnostic(ErrorCode.ERR_PartialMisplaced, "E").WithLocation(1, 14)); diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/FileModifierParsingTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/FileModifierParsingTests.cs index 6f0c7f920f7fd..fcbd84a47a552 100644 --- a/src/Compilers/CSharp/Test/Syntax/Parsing/FileModifierParsingTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/FileModifierParsingTests.cs @@ -101,18 +101,8 @@ public void FileModifier_02_Enum() UsingNode($$""" file partial enum C { } """, - expectedParsingDiagnostics: new[] - { - // (1,6): error CS0267: The 'partial' modifier can only appear immediately before 'class', 'record', 'struct', 'interface', or a method return type. - // file partial enum C { } - Diagnostic(ErrorCode.ERR_PartialMisplaced, "partial").WithLocation(1, 6) - }, - // note: we also get duplicate ERR_PartialMisplaced diagnostics on `partial enum C { }`. expectedBindingDiagnostics: new[] { - // (1,6): error CS0267: The 'partial' modifier can only appear immediately before 'class', 'record', 'struct', 'interface', or a method return type. - // file partial enum C { } - Diagnostic(ErrorCode.ERR_PartialMisplaced, "partial").WithLocation(1, 6), // (1,19): error CS0267: The 'partial' modifier can only appear immediately before 'class', 'record', 'struct', 'interface', or a method return type. // file partial enum C { } Diagnostic(ErrorCode.ERR_PartialMisplaced, "C").WithLocation(1, 19) @@ -192,20 +182,25 @@ public void FileModifier_03(SyntaxKind typeKeyword) EOF(); } - [Theory] - [InlineData(SyntaxKind.RecordKeyword)] - public void FileModifier_04(SyntaxKind typeKeyword) + [Fact] + public void FileModifier_04() { - UsingNode($$""" - partial file {{SyntaxFacts.GetText(typeKeyword)}} C { } - """); + UsingNode(""" + partial file record C { } + """, + expectedBindingDiagnostics: new DiagnosticDescription[] + { + // (1,1): error CS0267: The 'partial' modifier can only appear immediately before 'class', 'record', 'struct', 'interface', or a method return type. + // partial file record C { } + Diagnostic(ErrorCode.ERR_PartialMisplaced, "partial").WithLocation(1, 1) + }); N(SyntaxKind.CompilationUnit); { - N(SyntaxFacts.GetBaseTypeDeclarationKind(typeKeyword)); + N(SyntaxKind.RecordDeclaration); { N(SyntaxKind.PartialKeyword); N(SyntaxKind.FileKeyword); - N(typeKeyword); + N(SyntaxKind.RecordKeyword); N(SyntaxKind.IdentifierToken, "C"); N(SyntaxKind.OpenBraceToken); N(SyntaxKind.CloseBraceToken); @@ -243,7 +238,13 @@ public void FileModifier_06() { UsingNode($$""" partial file record struct C { } - """); + """, + expectedBindingDiagnostics: new DiagnosticDescription[] + { + // (1,1): error CS0267: The 'partial' modifier can only appear immediately before 'class', 'record', 'struct', 'interface', or a method return type. + // partial file record struct C { } + Diagnostic(ErrorCode.ERR_PartialMisplaced, "partial").WithLocation(1, 1) + }); N(SyntaxKind.CompilationUnit); { N(SyntaxKind.RecordStructDeclaration); diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/ParserErrorMessageTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/ParserErrorMessageTests.cs index 7e9a5834ff242..6ab46ca6c10b8 100644 --- a/src/Compilers/CSharp/Test/Syntax/Parsing/ParserErrorMessageTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/ParserErrorMessageTests.cs @@ -622,9 +622,6 @@ partial enum E { } "; CreateCompilation(test).VerifyDiagnostics( - // (2,1): error CS0267: The 'partial' modifier can only appear immediately before 'class', 'record', 'struct', 'interface', or a method return type. - // partial enum E { } - Diagnostic(ErrorCode.ERR_PartialMisplaced, "partial").WithLocation(2, 1), // (2,14): error CS0267: The 'partial' modifier can only appear immediately before 'class', 'record', 'struct', 'interface', or a method return type. // partial enum E { } Diagnostic(ErrorCode.ERR_PartialMisplaced, "E").WithLocation(2, 14)); @@ -639,9 +636,6 @@ public void CS0267ERR_PartialMisplaced_Delegate1() // Extra errors CreateCompilation(test, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular9).VerifyDiagnostics( - // (2,1): error CS0267: The 'partial' modifier can only appear immediately before 'class', 'record', 'struct', 'interface', or a method return type. - // partial delegate E { } - Diagnostic(ErrorCode.ERR_PartialMisplaced, "partial").WithLocation(2, 1), // (2,20): error CS1001: Identifier expected // partial delegate E { } Diagnostic(ErrorCode.ERR_IdentifierExpected, "{").WithLocation(2, 20), @@ -672,11 +666,7 @@ public void CS0267ERR_PartialMisplaced_Delegate2() partial delegate void E(); "; - // Extra errors CreateCompilation(test).VerifyDiagnostics( - // (2,1): error CS0267: The 'partial' modifier can only appear immediately before 'class', 'record', 'struct', 'interface', or a method return type. - // partial delegate void E(); - Diagnostic(ErrorCode.ERR_PartialMisplaced, "partial").WithLocation(2, 1), // (2,23): error CS0267: The 'partial' modifier can only appear immediately before 'class', 'record', 'struct', 'interface', or a method return type. // partial delegate void E(); Diagnostic(ErrorCode.ERR_PartialMisplaced, "E").WithLocation(2, 23)); diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/RoundTrippingTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/RoundTrippingTests.cs index 52fa43128dc55..acd3ae2240809 100644 --- a/src/Compilers/CSharp/Test/Syntax/Parsing/RoundTrippingTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/RoundTrippingTests.cs @@ -402,7 +402,8 @@ public partial() public void TestNegBug876575() { var text = @"partial enum E{}"; - ParseAndRoundTripping(text, errorCount: 1); + // ERR_PartialMisplaced is not produced during parsing. + ParseAndRoundTripping(text, errorCount: 0); } [Fact] diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/ScriptParsingTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/ScriptParsingTests.cs index 579d049be589a..17d12a4d447e1 100644 --- a/src/Compilers/CSharp/Test/Syntax/Parsing/ScriptParsingTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/ScriptParsingTests.cs @@ -1040,12 +1040,16 @@ public void NewModifier_PartialClass() [Fact] public void NewModifier_ClassWithMisplacedModifiers1() { - var tree = UsingTree(@" -new partial public class C { } -", - // (2,5): error CS0267: The 'partial' modifier can only appear immediately before 'class', 'record', 'struct', 'interface', or a method return type. - // new partial public class C { } - Diagnostic(ErrorCode.ERR_PartialMisplaced, "partial").WithLocation(2, 5)); + var source = "new partial public class C { }"; + CreateCompilation(source).VerifyDiagnostics( + // (1,5): error CS0267: The 'partial' modifier can only appear immediately before 'class', 'record', 'struct', 'interface', or a method return type. + // new partial public class C { } + Diagnostic(ErrorCode.ERR_PartialMisplaced, "partial").WithLocation(1, 5), + // (1,26): error CS0106: The modifier 'new' is not valid for this item + // new partial public class C { } + Diagnostic(ErrorCode.ERR_BadMemberFlag, "C").WithArguments("new").WithLocation(1, 26) + ); + var tree = UsingTree(source); N(SyntaxKind.CompilationUnit); { N(SyntaxKind.ClassDeclaration); @@ -1065,12 +1069,15 @@ public void NewModifier_ClassWithMisplacedModifiers1() [Fact] public void NewModifier_ClassWithMisplacedModifiers2() { - var tree = UsingTree(@" -new static partial public class C { } -", - // (2,12): error CS0267: The 'partial' modifier can only appear immediately before 'class', 'record', 'struct', 'interface', or a method return type. + var source = "new static partial public class C { }"; + CreateCompilation(source).VerifyDiagnostics( + // (1,12): error CS0267: The 'partial' modifier can only appear immediately before 'class', 'record', 'struct', 'interface', or a method return type. + // new static partial public class C { } + Diagnostic(ErrorCode.ERR_PartialMisplaced, "partial").WithLocation(1, 12), + // (1,33): error CS0106: The modifier 'new' is not valid for this item // new static partial public class C { } - Diagnostic(ErrorCode.ERR_PartialMisplaced, "partial").WithLocation(2, 12)); + Diagnostic(ErrorCode.ERR_BadMemberFlag, "C").WithArguments("new").WithLocation(1, 33)); + var tree = UsingTree(source); N(SyntaxKind.CompilationUnit); { @@ -1971,9 +1978,6 @@ public void EnumDeclaration() partial enum @en {}; "; CreateCompilation(test).VerifyDiagnostics( - // (2,1): error CS0267: The 'partial' modifier can only appear immediately before 'class', 'record', 'struct', 'interface', or a method return type. - // partial enum @en {}; - Diagnostic(ErrorCode.ERR_PartialMisplaced, "partial").WithLocation(2, 1), // (2,14): error CS0267: The 'partial' modifier can only appear immediately before 'class', 'record', 'struct', 'interface', or a method return type. // partial enum @en {}; Diagnostic(ErrorCode.ERR_PartialMisplaced, "@en").WithLocation(2, 14)); diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/TopLevelStatementsParsingTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/TopLevelStatementsParsingTests.cs index fdd2101a2afb0..7872c94b99b28 100644 --- a/src/Compilers/CSharp/Test/Syntax/Parsing/TopLevelStatementsParsingTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/TopLevelStatementsParsingTests.cs @@ -922,10 +922,30 @@ public void CS0267ERR_PartialMisplaced_Delegate1() var test = @" partial delegate E { } "; + CreateCompilation(test).VerifyDiagnostics( + // (2,18): error CS0246: The type or namespace name 'E' could not be found (are you missing a using directive or an assembly reference?) + // partial delegate E { } + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "E").WithArguments("E").WithLocation(2, 18), + // (2,20): error CS1001: Identifier expected + // partial delegate E { } + Diagnostic(ErrorCode.ERR_IdentifierExpected, "{").WithLocation(2, 20), + // (2,20): error CS1003: Syntax error, '(' expected + // partial delegate E { } + Diagnostic(ErrorCode.ERR_SyntaxError, "{").WithArguments("(").WithLocation(2, 20), + // (2,20): error CS1026: ) expected + // partial delegate E { } + Diagnostic(ErrorCode.ERR_CloseParenExpected, "{").WithLocation(2, 20), + // (2,20): error CS1002: ; expected + // partial delegate E { } + Diagnostic(ErrorCode.ERR_SemicolonExpected, "{").WithLocation(2, 20), + // (2,20): error CS8803: Top-level statements must precede namespace and type declarations. + // partial delegate E { } + Diagnostic(ErrorCode.ERR_TopLevelStatementAfterNamespaceOrType, "{ }").WithLocation(2, 20), + // (2,20): error CS0267: The 'partial' modifier can only appear immediately before 'class', 'record', 'struct', 'interface', or a method return type. + // partial delegate E { } + Diagnostic(ErrorCode.ERR_PartialMisplaced, "").WithLocation(2, 20) + ); UsingTree(test, - // (2,1): error CS0267: The 'partial' modifier can only appear immediately before 'class', 'record', 'struct', 'interface', or a method return type. - // partial delegate E { } - Diagnostic(ErrorCode.ERR_PartialMisplaced, "partial").WithLocation(2, 1), // (2,20): error CS1001: Identifier expected // partial delegate E { } Diagnostic(ErrorCode.ERR_IdentifierExpected, "{").WithLocation(2, 20),