/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Compilers/CSharp/Test/Emit/PrivateProtected.cs
797 строк
38 KB
Jared Parsons
Move net451 test assets to net461 (#74766)
17 авг 2024, 19:21
Не верифицирован
17 авг 2024, 19:21
75b26a2
Код
Авторство
О чём код?
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. #nullable disable using System.Collections.Immutable; using Microsoft.CodeAnalysis.CSharp.Test.Utilities; using Microsoft.CodeAnalysis.Test.Utilities; using Roslyn.Test.Utilities; using static Roslyn.Test.Utilities.SigningTestHelpers; using Xunit; using Microsoft.CodeAnalysis.CSharp.Symbols; namespace Microsoft.CodeAnalysis.CSharp.UnitTests { [CompilerTrait(CompilerFeature.PrivateProtected)] public class PrivateProtected : CSharpTestBase { private static readonly string s_keyPairFile = SigningTestHelpers.KeyPairFile; private static readonly string s_publicKeyFile = SigningTestHelpers.PublicKeyFile; private static readonly ImmutableArray<byte> s_publicKey = SigningTestHelpers.PublicKey; [ConditionalFact(typeof(DesktopOnly))] public void RejectIncompatibleModifiers() { string source = @"public class Base { private internal int Field1; internal private int Field2; private internal protected int Field3; internal protected private int Field4; private public protected int Field5; private readonly protected int Field6; // ok } "; CreateCompilation(source, parseOptions: TestOptions.Regular7_2) .VerifyDiagnostics( // (3,26): error CS0107: More than one protection modifier // private internal int Field1; Diagnostic(ErrorCode.ERR_BadMemberProtection, "Field1").WithLocation(3, 26), // (4,26): error CS0107: More than one protection modifier // internal private int Field2; Diagnostic(ErrorCode.ERR_BadMemberProtection, "Field2").WithLocation(4, 26), // (5,36): error CS0107: More than one protection modifier // private internal protected int Field3; Diagnostic(ErrorCode.ERR_BadMemberProtection, "Field3").WithLocation(5, 36), // (6,36): error CS0107: More than one protection modifier // internal protected private int Field4; Diagnostic(ErrorCode.ERR_BadMemberProtection, "Field4").WithLocation(6, 36), // (7,34): error CS0107: More than one protection modifier // private public protected int Field5; Diagnostic(ErrorCode.ERR_BadMemberProtection, "Field5").WithLocation(7, 34) ); } [ConditionalFact(typeof(DesktopOnly))] public void AccessibleWhereRequired_01() { string source = @"public class Base { private protected int Field1; protected private int Field2; } public class Derived : Base { void M() { Field1 = 1; Field2 = 2; } } "; var compilation = CreateCompilation(source, parseOptions: TestOptions.Regular7_2) .VerifyDiagnostics( ); } [ConditionalFact(typeof(DesktopOnly))] public void AccessibleWhereRequired_02() { string source1 = @"[assembly: System.Runtime.CompilerServices.InternalsVisibleTo(""WantsIVTAccess"")] public class Base { private protected const int Constant = 3; private protected int Field1; protected private int Field2; private protected void Method() { } private protected event System.Action Event1; private protected int Property1 { set {} } public int Property2 { private protected set {} get { return 4; } } private protected int this[int x] { set { } get { return 6; } } public int this[string x] { private protected set { } get { return 5; } } private protected Base() { Event1?.Invoke(); } }"; var baseCompilation = CreateCompilation(source1, parseOptions: TestOptions.Regular7_2, options: TestOptions.SigningReleaseDll, assemblyName: "Paul"); var bb = (NamedTypeSymbol)baseCompilation.GlobalNamespace.GetMember("Base"); foreach (var member in bb.GetMembers()) { switch (member.Name) { case "Property2": case "get_Property2": case "this[]": case "get_Item": break; default: Assert.Equal(Accessibility.ProtectedAndInternal, member.DeclaredAccessibility); break; } } string source2 = @"public class Derived : Base { void M() { Field1 = Constant; Field2 = Constant; Method(); Event1 += null; Property1 = Constant; Property2 = Constant; this[1] = 2; this[string.Empty] = 4; } Derived(int x) : base() {} Derived(long x) {} // implicit base() } "; CreateCompilation(source2, parseOptions: TestOptions.Regular7_2, references: new[] { new CSharpCompilationReference(baseCompilation) }, assemblyName: "WantsIVTAccessButCantHave", options: TestOptions.SigningReleaseDll) .VerifyDiagnostics( // (5,9): error CS0122: 'Base.Field1' is inaccessible due to its protection level // Field1 = Constant; Diagnostic(ErrorCode.ERR_BadAccess, "Field1").WithArguments("Base.Field1").WithLocation(5, 9), // (5,18): error CS0122: 'Base.Constant' is inaccessible due to its protection level // Field1 = Constant; Diagnostic(ErrorCode.ERR_BadAccess, "Constant").WithArguments("Base.Constant").WithLocation(5, 18), // (6,9): error CS0122: 'Base.Field2' is inaccessible due to its protection level // Field2 = Constant; Diagnostic(ErrorCode.ERR_BadAccess, "Field2").WithArguments("Base.Field2").WithLocation(6, 9), // (6,18): error CS0122: 'Base.Constant' is inaccessible due to its protection level // Field2 = Constant; Diagnostic(ErrorCode.ERR_BadAccess, "Constant").WithArguments("Base.Constant").WithLocation(6, 18), // (7,9): error CS0122: 'Base.Method()' is inaccessible due to its protection level // Method(); Diagnostic(ErrorCode.ERR_BadAccess, "Method").WithArguments("Base.Method()").WithLocation(7, 9), // (8,9): error CS0122: 'Base.Event1' is inaccessible due to its protection level // Event1 += null; Diagnostic(ErrorCode.ERR_BadAccess, "Event1").WithArguments("Base.Event1").WithLocation(8, 9), // (8,9): error CS0122: 'Base.Event1.add' is inaccessible due to its protection level // Event1 += null; Diagnostic(ErrorCode.ERR_BadAccess, "Event1 += null").WithArguments("Base.Event1.add").WithLocation(8, 9), // (9,9): error CS0122: 'Base.Property1' is inaccessible due to its protection level // Property1 = Constant; Diagnostic(ErrorCode.ERR_BadAccess, "Property1").WithArguments("Base.Property1").WithLocation(9, 9), // (9,21): error CS0122: 'Base.Constant' is inaccessible due to its protection level // Property1 = Constant; Diagnostic(ErrorCode.ERR_BadAccess, "Constant").WithArguments("Base.Constant").WithLocation(9, 21), // (10,9): error CS0272: The property or indexer 'Base.Property2' cannot be used in this context because the set accessor is inaccessible // Property2 = Constant; Diagnostic(ErrorCode.ERR_InaccessibleSetter, "Property2").WithArguments("Base.Property2").WithLocation(10, 9), // (10,21): error CS0122: 'Base.Constant' is inaccessible due to its protection level // Property2 = Constant; Diagnostic(ErrorCode.ERR_BadAccess, "Constant").WithArguments("Base.Constant").WithLocation(10, 21), // (11,14): error CS1503: Argument 1: cannot convert from 'int' to 'string' // this[1] = 2; Diagnostic(ErrorCode.ERR_BadArgType, "1").WithArguments("1", "int", "string").WithLocation(11, 14), // (12,9): error CS0272: The property or indexer 'Base.this[string]' cannot be used in this context because the set accessor is inaccessible // this[string.Empty] = 4; Diagnostic(ErrorCode.ERR_InaccessibleSetter, "this[string.Empty]").WithArguments("Base.this[string]").WithLocation(12, 9), // (14,22): error CS0122: 'Base.Base()' is inaccessible due to its protection level // Derived(int x) : base() {} Diagnostic(ErrorCode.ERR_BadAccess, "base").WithArguments("Base.Base()").WithLocation(14, 22), // (15,5): error CS0122: 'Base.Base()' is inaccessible due to its protection level // Derived(long x) {} // implicit base() Diagnostic(ErrorCode.ERR_BadAccess, "Derived").WithArguments("Base.Base()").WithLocation(15, 5) ); CreateCompilation(source2, parseOptions: TestOptions.Regular7_2, references: new[] { MetadataReference.CreateFromImage(baseCompilation.EmitToArray()) }, assemblyName: "WantsIVTAccessButCantHave", options: TestOptions.SigningReleaseDll) .VerifyDiagnostics( // (5,9): error CS0122: 'Base.Field1' is inaccessible due to its protection level // Field1 = Constant; Diagnostic(ErrorCode.ERR_BadAccess, "Field1").WithArguments("Base.Field1").WithLocation(5, 9), // (5,18): error CS0122: 'Base.Constant' is inaccessible due to its protection level // Field1 = Constant; Diagnostic(ErrorCode.ERR_BadAccess, "Constant").WithArguments("Base.Constant").WithLocation(5, 18), // (6,9): error CS0122: 'Base.Field2' is inaccessible due to its protection level // Field2 = Constant; Diagnostic(ErrorCode.ERR_BadAccess, "Field2").WithArguments("Base.Field2").WithLocation(6, 9), // (6,18): error CS0122: 'Base.Constant' is inaccessible due to its protection level // Field2 = Constant; Diagnostic(ErrorCode.ERR_BadAccess, "Constant").WithArguments("Base.Constant").WithLocation(6, 18), // (7,9): error CS0122: 'Base.Method()' is inaccessible due to its protection level // Method(); Diagnostic(ErrorCode.ERR_BadAccess, "Method").WithArguments("Base.Method()").WithLocation(7, 9), // (8,9): error CS0122: 'Base.Event1' is inaccessible due to its protection level // Event1 += null; Diagnostic(ErrorCode.ERR_BadAccess, "Event1").WithArguments("Base.Event1").WithLocation(8, 9), // (8,9): error CS0122: 'Base.Event1.add' is inaccessible due to its protection level // Event1 += null; Diagnostic(ErrorCode.ERR_BadAccess, "Event1 += null").WithArguments("Base.Event1.add").WithLocation(8, 9), // (9,9): error CS0122: 'Base.Property1' is inaccessible due to its protection level // Property1 = Constant; Diagnostic(ErrorCode.ERR_BadAccess, "Property1").WithArguments("Base.Property1").WithLocation(9, 9), // (9,21): error CS0122: 'Base.Constant' is inaccessible due to its protection level // Property1 = Constant; Diagnostic(ErrorCode.ERR_BadAccess, "Constant").WithArguments("Base.Constant").WithLocation(9, 21), // (10,9): error CS0272: The property or indexer 'Base.Property2' cannot be used in this context because the set accessor is inaccessible // Property2 = Constant; Diagnostic(ErrorCode.ERR_InaccessibleSetter, "Property2").WithArguments("Base.Property2").WithLocation(10, 9), // (10,21): error CS0122: 'Base.Constant' is inaccessible due to its protection level // Property2 = Constant; Diagnostic(ErrorCode.ERR_BadAccess, "Constant").WithArguments("Base.Constant").WithLocation(10, 21), // (11,14): error CS1503: Argument 1: cannot convert from 'int' to 'string' // this[1] = 2; Diagnostic(ErrorCode.ERR_BadArgType, "1").WithArguments("1", "int", "string").WithLocation(11, 14), // (12,9): error CS0272: The property or indexer 'Base.this[string]' cannot be used in this context because the set accessor is inaccessible // this[string.Empty] = 4; Diagnostic(ErrorCode.ERR_InaccessibleSetter, "this[string.Empty]").WithArguments("Base.this[string]").WithLocation(12, 9), // (14,22): error CS0122: 'Base.Base()' is inaccessible due to its protection level // Derived(int x) : base() {} Diagnostic(ErrorCode.ERR_BadAccess, "base").WithArguments("Base.Base()").WithLocation(14, 22), // (15,5): error CS0122: 'Base.Base()' is inaccessible due to its protection level // Derived(long x) {} // implicit base() Diagnostic(ErrorCode.ERR_BadAccess, "Derived").WithArguments("Base.Base()").WithLocation(15, 5) ); CreateCompilation(source2, parseOptions: TestOptions.Regular7_2, references: new[] { new CSharpCompilationReference(baseCompilation) }, assemblyName: "WantsIVTAccess", options: TestOptions.SigningReleaseDll) .VerifyDiagnostics( ); CreateCompilation(source2, parseOptions: TestOptions.Regular7_2, references: new[] { MetadataReference.CreateFromImage(baseCompilation.EmitToArray()) }, assemblyName: "WantsIVTAccess", options: TestOptions.SigningReleaseDll) .VerifyDiagnostics( ); } [ConditionalFact(typeof(DesktopOnly))] public void NotAccessibleWhereRequired() { string source = @"public class Base { private protected int Field1; protected private int Field2; } public class Derived // : Base { void M() { Base b = null; b.Field1 = 1; b.Field2 = 2; } } "; CreateCompilation(source, parseOptions: TestOptions.Regular7_2) .VerifyDiagnostics( // (12,11): error CS0122: 'Base.Field1' is inaccessible due to its protection level // b.Field1 = 1; Diagnostic(ErrorCode.ERR_BadAccess, "Field1").WithArguments("Base.Field1").WithLocation(12, 11), // (13,11): error CS0122: 'Base.Field2' is inaccessible due to its protection level // b.Field2 = 2; Diagnostic(ErrorCode.ERR_BadAccess, "Field2").WithArguments("Base.Field2").WithLocation(13, 11) ); } [ConditionalFact(typeof(DesktopOnly))] public void NotInStructOrNamespace() { string source = @"protected private struct Struct { private protected int Field1; } "; CreateCompilation(source, parseOptions: TestOptions.Regular7_2) .VerifyDiagnostics( // (1,18): error CS1527: Elements defined in a namespace cannot be explicitly declared as private, protected, protected internal, or private protected // protected private struct Struct Diagnostic(ErrorCode.ERR_NoNamespacePrivate, "Struct").WithLocation(1, 26), // (3,27): error CS0666: 'Struct.Field1': new protected member declared in struct // private protected int Field1; Diagnostic(ErrorCode.ERR_ProtectedInStruct, "Field1").WithArguments("Struct.Field1").WithLocation(3, 27) ); } [ConditionalFact(typeof(DesktopOnly))] public void NotInStaticClass() { string source = @"static class C { static private protected int Field1 = 2; } sealed class D { static private protected int Field2 = 2; } "; CreateCompilation(source, parseOptions: TestOptions.Regular7_2) .VerifyDiagnostics( // (7,34): warning CS0628: 'D.Field2': new protected member declared in sealed type // static private protected int Field2 = 2; Diagnostic(ErrorCode.WRN_ProtectedInSealed, "Field2").WithArguments("D.Field2").WithLocation(7, 34), // (3,34): error CS1057: 'C.Field1': static classes cannot contain protected members // static private protected int Field1 = 2; Diagnostic(ErrorCode.ERR_ProtectedInStatic, "Field1").WithArguments("C.Field1").WithLocation(3, 34) ); } [ConditionalFact(typeof(DesktopOnly))] public void NestedTypes() { string source = @"class Outer { private protected class Inner { } } class Derived : Outer { public void M() { Outer.Inner x = null; } } class NotDerived { public void M() { Outer.Inner x = null; // error: Outer.Inner not accessible } } struct Struct { private protected class Inner // error: protected not allowed in struct { } } "; CreateCompilation(source, parseOptions: TestOptions.Regular7_2) .VerifyDiagnostics( // (23,29): error CS0666: 'Struct.Inner': new protected member declared in struct // private protected class Inner // error: protected not allowed in struct Diagnostic(ErrorCode.ERR_ProtectedInStruct, "Inner").WithArguments("Struct.Inner").WithLocation(23, 29), // (11,21): warning CS0219: The variable 'x' is assigned but its value is never used // Outer.Inner x = null; Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "x").WithArguments("x").WithLocation(11, 21), // (18,15): error CS0122: 'Outer.Inner' is inaccessible due to its protection level // Outer.Inner x = null; // error: Outer.Inner not accessible Diagnostic(ErrorCode.ERR_BadAccess, "Inner").WithArguments("Outer.Inner").WithLocation(18, 15) ); } [ConditionalFact(typeof(DesktopOnly))] public void PermittedAccessorProtection() { string source = @"class Class { public int Prop1 { get; private protected set; } protected internal int Prop2 { get; private protected set; } protected int Prop3 { get; private protected set; } internal int Prop4 { get; private protected set; } private protected int Prop5 { get; private set; } }"; CreateCompilation(source, parseOptions: TestOptions.Regular7_2) .VerifyDiagnostics( ); } [ConditionalFact(typeof(DesktopOnly))] public void ForbiddenAccessorProtection_01() { string source = @"class Class { private protected int Prop1 { get; private protected set; } private int Prop2 { get; private protected set; } }"; CreateCompilation(source, parseOptions: TestOptions.Regular7_2) .VerifyDiagnostics( // (3,58): error CS0273: The accessibility modifier of the 'Class.Prop1.set' accessor must be more restrictive than the property or indexer 'Class.Prop1' // private protected int Prop1 { get; private protected set; } Diagnostic(ErrorCode.ERR_InvalidPropertyAccessMod, "set").WithArguments("Class.Prop1.set", "Class.Prop1").WithLocation(3, 58), // (4,48): error CS0273: The accessibility modifier of the 'Class.Prop2.set' accessor must be more restrictive than the property or indexer 'Class.Prop2' // private int Prop2 { get; private protected set; } Diagnostic(ErrorCode.ERR_InvalidPropertyAccessMod, "set").WithArguments("Class.Prop2.set", "Class.Prop2").WithLocation(4, 48) ); } [ConditionalFact(typeof(DesktopOnly))] public void ForbiddenAccessorProtection_02() { string source = @"interface ISomething { private protected int M(); }"; CreateCompilation(source, parseOptions: TestOptions.Regular7_2) .VerifyDiagnostics( // (3,27): error CS8503: The modifier 'private protected' is not valid for this item in C# 7.2. Please use language version '8.0' or greater. // private protected int M(); Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "M").WithArguments("private protected", "7.2", "8.0").WithLocation(3, 27), // (3,27): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // private protected int M(); Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "M").WithLocation(3, 27) ); } [ConditionalFact(typeof(DesktopOnly))] public void AtLeastAsRestrictivePositive_01() { string source = @" public class C { internal class Internal {} protected class Protected {} private protected class PrivateProtected {} private protected void M(Internal x) {} // ok private protected void M(Protected x) {} // ok private protected void M(PrivateProtected x) {} // ok private protected class Nested { public void M(Internal x) {} // ok public void M(Protected x) {} // ok private protected void M(PrivateProtected x) {} // ok } } "; CreateCompilation(source, parseOptions: TestOptions.Regular7_2) .VerifyDiagnostics( ); } [ConditionalFact(typeof(DesktopOnly))] public void AtLeastAsRestrictiveNegative_01() { string source = @" public class Container { private protected class PrivateProtected {} internal void M1(PrivateProtected x) {} // error: conflicting access protected void M2(PrivateProtected x) {} // error: conflicting access } "; CreateCompilation(source, parseOptions: TestOptions.Regular7_2) .VerifyDiagnostics( // (6,20): error CS0051: Inconsistent accessibility: parameter type 'Container.PrivateProtected' is less accessible than method 'Container.M2(Container.PrivateProtected)' // protected void M2(PrivateProtected x) {} // error: conflicting access Diagnostic(ErrorCode.ERR_BadVisParamType, "M2").WithArguments("Container.M2(Container.PrivateProtected)", "Container.PrivateProtected").WithLocation(6, 20), // (5,19): error CS0051: Inconsistent accessibility: parameter type 'Container.PrivateProtected' is less accessible than method 'Container.M1(Container.PrivateProtected)' // internal void M1(PrivateProtected x) {} // error: conflicting access Diagnostic(ErrorCode.ERR_BadVisParamType, "M1").WithArguments("Container.M1(Container.PrivateProtected)", "Container.PrivateProtected").WithLocation(5, 19) ); } [ConditionalFact(typeof(DesktopOnly))] public void DuplicateAccessInBinder() { string source = @" public class Container { private public int Field; // 1 private public int Property { get; set; } // 2 private public int M() => 1; // 3 private public class C {} // 4 private public struct S {} // 5 private public enum E {} // 6 private public event System.Action V; // 7 private public interface I {} // 8 private public int this[int index] => 1; // 9 void Q() { V.Invoke(); V = null; } } "; CreateCompilation(source, parseOptions: TestOptions.Regular7_2) .VerifyDiagnostics( // (7,26): error CS0107: More than one protection modifier // private public class C {} // 4 Diagnostic(ErrorCode.ERR_BadMemberProtection, "C").WithLocation(7, 26), // (8,27): error CS0107: More than one protection modifier // private public struct S {} // 5 Diagnostic(ErrorCode.ERR_BadMemberProtection, "S").WithLocation(8, 27), // (9,25): error CS0107: More than one protection modifier // private public enum E {} // 6 Diagnostic(ErrorCode.ERR_BadMemberProtection, "E").WithLocation(9, 25), // (11,30): error CS0107: More than one protection modifier // private public interface I {} // 8 Diagnostic(ErrorCode.ERR_BadMemberProtection, "I").WithLocation(11, 30), // (4,24): error CS0107: More than one protection modifier // private public int Field; // 1 Diagnostic(ErrorCode.ERR_BadMemberProtection, "Field").WithLocation(4, 24), // (5,24): error CS0107: More than one protection modifier // private public int Property { get; set; } // 2 Diagnostic(ErrorCode.ERR_BadMemberProtection, "Property").WithLocation(5, 24), // (6,24): error CS0107: More than one protection modifier // private public int M() => 1; // 3 Diagnostic(ErrorCode.ERR_BadMemberProtection, "M").WithLocation(6, 24), // (10,40): error CS0107: More than one protection modifier // private public event System.Action V; // 7 Diagnostic(ErrorCode.ERR_BadMemberProtection, "V").WithLocation(10, 40), // (12,24): error CS0107: More than one protection modifier // private public int this[int index] => 1; // 9 Diagnostic(ErrorCode.ERR_BadMemberProtection, "this").WithLocation(12, 24) ); } [ConditionalFact(typeof(DesktopOnly))] public void NotInVersion71() { string source = @" public class Container { private protected int Field; // 1 private protected int Property { get; set; } // 2 private protected int M() => 1; // 3 private protected class C {} // 4 private protected struct S {} // 5 private protected enum E {} // 6 private protected event System.Action V; // 7 private protected interface I {} // 8 private protected int this[int index] => 1; // 9 void Q() { V.Invoke(); V = null; } } "; CreateCompilation(source, parseOptions: TestOptions.Regular7_1) .VerifyDiagnostics( // (7,29): error CS8302: Feature 'private protected' is not available in C# 7.1. Please use language version 7.2 or greater. // private protected class C {} // 4 Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_1, "C").WithArguments("private protected", "7.2").WithLocation(7, 29), // (8,30): error CS8302: Feature 'private protected' is not available in C# 7.1. Please use language version 7.2 or greater. // private protected struct S {} // 5 Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_1, "S").WithArguments("private protected", "7.2").WithLocation(8, 30), // (9,28): error CS8302: Feature 'private protected' is not available in C# 7.1. Please use language version 7.2 or greater. // private protected enum E {} // 6 Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_1, "E").WithArguments("private protected", "7.2").WithLocation(9, 28), // (11,33): error CS8302: Feature 'private protected' is not available in C# 7.1. Please use language version 7.2 or greater. // private protected interface I {} // 8 Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_1, "I").WithArguments("private protected", "7.2").WithLocation(11, 33), // (4,27): error CS8302: Feature 'private protected' is not available in C# 7.1. Please use language version 7.2 or greater. // private protected int Field; // 1 Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_1, "Field").WithArguments("private protected", "7.2").WithLocation(4, 27), // (5,27): error CS8302: Feature 'private protected' is not available in C# 7.1. Please use language version 7.2 or greater. // private protected int Property { get; set; } // 2 Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_1, "Property").WithArguments("private protected", "7.2").WithLocation(5, 27), // (6,27): error CS8302: Feature 'private protected' is not available in C# 7.1. Please use language version 7.2 or greater. // private protected int M() => 1; // 3 Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_1, "M").WithArguments("private protected", "7.2").WithLocation(6, 27), // (10,43): error CS8302: Feature 'private protected' is not available in C# 7.1. Please use language version 7.2 or greater. // private protected event System.Action V; // 7 Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_1, "V").WithArguments("private protected", "7.2").WithLocation(10, 43), // (12,27): error CS8302: Feature 'private protected' is not available in C# 7.1. Please use language version 7.2 or greater. // private protected int this[int index] => 1; // 9 Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_1, "this").WithArguments("private protected", "7.2").WithLocation(12, 27) ); CreateCompilation(source, parseOptions: TestOptions.Regular7_2) .VerifyDiagnostics( ); } [ConditionalFact(typeof(DesktopOnly))] public void VerifyPrivateProtectedIL() { var text = @" class Program { private protected void M() {} private protected int F; } "; var verifier = CompileAndVerify( text, parseOptions: TestOptions.Regular7_2, expectedSignatures: new[] { Signature("Program", "M", ".method famandassem hidebysig instance System.Void M() cil managed"), Signature("Program", "F", ".field famandassem instance System.Int32 F"), }); } [ConditionalFact(typeof(DesktopOnly))] public void VerifyPartialPartsMatch() { var source = @"class Outer { private protected partial class Inner {} private partial class Inner {} }"; CreateCompilation(source, parseOptions: TestOptions.Regular7_2) .VerifyDiagnostics( // (3,37): error CS0262: Partial declarations of 'Outer.Inner' have conflicting accessibility modifiers // private protected partial class Inner {} Diagnostic(ErrorCode.ERR_PartialModifierConflict, "Inner").WithArguments("Outer.Inner").WithLocation(3, 37) ); source = @"class Outer { private protected partial class Inner {} private protected partial class Inner {} }"; CreateCompilation(source, parseOptions: TestOptions.Regular7_2) .VerifyDiagnostics( ); } [ConditionalFact(typeof(DesktopOnly))] public void VerifyProtectedSemantics() { var source = @"class Base { private protected void M() { System.Console.WriteLine(this.GetType().Name); } } class Derived : Base { public void Main() { Derived derived = new Derived(); derived.M(); Base bb = new Base(); bb.M(); // error 1 Other other = new Other(); other.M(); // error 2 } } class Other : Base { }"; CreateCompilation(source, parseOptions: TestOptions.Regular7_2) .VerifyDiagnostics( // (16,12): error CS1540: Cannot access protected member 'Base.M()' via a qualifier of type 'Base'; the qualifier must be of type 'Derived' (or derived from it) // bb.M(); // error 1 Diagnostic(ErrorCode.ERR_BadProtectedAccess, "M").WithArguments("Base.M()", "Base", "Derived").WithLocation(16, 12), // (18,15): error CS1540: Cannot access protected member 'Base.M()' via a qualifier of type 'Other'; the qualifier must be of type 'Derived' (or derived from it) // other.M(); // error 2 Diagnostic(ErrorCode.ERR_BadProtectedAccess, "M").WithArguments("Base.M()", "Other", "Derived").WithLocation(18, 15) ); } [ConditionalFact(typeof(DesktopOnly))] public void HidingAbstract() { var source = @"abstract class A { internal abstract void F(); } abstract class B : A { private protected new void F() { } // No CS0533 }"; CreateCompilation(source, parseOptions: TestOptions.Regular7_2) .VerifyDiagnostics( ); } [ConditionalFact(typeof(DesktopOnly))] public void HidingInaccessible() { string source1 = @"public class A { private protected void F() { } } "; var compilation1 = CreateCompilation(source1, parseOptions: TestOptions.Regular7_2); compilation1.VerifyDiagnostics(); string source2 = @"class B : A { new void F() { } // CS0109 } "; CreateCompilation(source2, parseOptions: TestOptions.Regular7_2, references: new[] { new CSharpCompilationReference(compilation1) }) .VerifyDiagnostics( // (3,14): warning CS0109: The member 'B.F()' does not hide an accessible member. The new keyword is not required. // new void F() { } // CS0109 Diagnostic(ErrorCode.WRN_NewNotRequired, "F").WithArguments("B.F()").WithLocation(3, 14) ); } [ConditionalFact(typeof(DesktopOnly))] public void UnimplementedInaccessible() { string source1 = @"public abstract class A { private protected abstract void F(); } "; var compilation1 = CreateCompilation(source1, parseOptions: TestOptions.Regular7_2); compilation1.VerifyDiagnostics(); string source2 = @"class B : A // CS0534 { } "; CreateCompilation(source2, parseOptions: TestOptions.Regular7_2, references: new[] { new CSharpCompilationReference(compilation1) }) .VerifyDiagnostics( // (1,7): error CS0534: 'B' does not implement inherited abstract member 'A.F()' // class B : A // CS0534 Diagnostic(ErrorCode.ERR_UnimplementedAbstractMethod, "B").WithArguments("B", "A.F()").WithLocation(1, 7) ); } [ConditionalFact(typeof(DesktopOnly))] public void ImplementInaccessible() { string source1 = @"public abstract class A { private protected abstract void F(); } "; var compilation1 = CreateCompilation(source1, parseOptions: TestOptions.Regular7_2); compilation1.VerifyDiagnostics(); string source2 = @"class B : A // CS0534 { override private protected void F() {} } "; CreateCompilation(source2, parseOptions: TestOptions.Regular7_2, references: new[] { new CSharpCompilationReference(compilation1) }) .VerifyDiagnostics( // (3,37): error CS0115: 'B.F()': no suitable method found to override // override private protected void F() {} Diagnostic(ErrorCode.ERR_OverrideNotExpected, "F").WithArguments("B.F()").WithLocation(3, 37), // (1,7): error CS0534: 'B' does not implement inherited abstract member 'A.F()' // class B : A // CS0534 Diagnostic(ErrorCode.ERR_UnimplementedAbstractMethod, "B").WithArguments("B", "A.F()").WithLocation(1, 7) ); } [ConditionalFact(typeof(DesktopOnly))] public void VerifyPPExtension() { string source = @" static class Extensions { static private protected void SomeExtension(this string s) { } // error: no pp in static class } class Client { public static void M(string s) { s.SomeExtension(); // error: no accessible SomeExtension } } "; CreateCompilationWithMscorlib461(source, parseOptions: TestOptions.Regular7_2) .VerifyDiagnostics( // (4,35): error CS1057: 'Extensions.SomeExtension(string)': static classes cannot contain protected members // static private protected void SomeExtension(this string s) { } // error: no pp in static class Diagnostic(ErrorCode.ERR_ProtectedInStatic, "SomeExtension").WithArguments("Extensions.SomeExtension(string)").WithLocation(4, 35), // (11,11): error CS1061: 'string' does not contain a definition for 'SomeExtension' and no accessible extension method 'SomeExtension' accepting a first argument of type 'string' could be found (are you missing a using directive or an assembly reference?) // s.SomeExtension(); // error: no accessible SomeExtension Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "SomeExtension").WithArguments("string", "SomeExtension").WithLocation(11, 11) ); } } }