From f03005118b3ad47a3522bde75f8006394a2b1578 Mon Sep 17 00:00:00 2001 From: AlekseyTs Date: Thu, 18 May 2017 20:57:07 -0700 Subject: [PATCH] Disallow implicit implementation of non-public interface members and explicit implementation of inaccessible members. (#19549) --- .../DefaultInterfaceImplementation.md | 38 + .../Portable/CSharpResources.Designer.cs | 23 +- .../CSharp/Portable/CSharpResources.resx | 3 + .../CSharp/Portable/Errors/ErrorCode.cs | 1 + .../Symbols/MemberSymbolExtensions.cs | 21 + .../Source/ExplicitInterfaceHelpers.cs | 42 +- ...berContainerSymbol_ImplementationChecks.cs | 18 + .../CSharp/Portable/Symbols/TypeSymbol.cs | 46 +- .../DefaultInterfaceImplementationTests.cs | 20039 ++++++++++------ 9 files changed, 12758 insertions(+), 7473 deletions(-) diff --git a/docs/features/DefaultInterfaceImplementation.md b/docs/features/DefaultInterfaceImplementation.md index b93dbf47fc4bf..7e41fcdfeaa93 100644 --- a/docs/features/DefaultInterfaceImplementation.md +++ b/docs/features/DefaultInterfaceImplementation.md @@ -44,3 +44,41 @@ class Test1 : I1 - Declaring types within interfaces. **Protected** and **protected internal** accessibility is not supported. **Open issues and work items** are tracked in https://github.com/dotnet/roslyn/issues/17952. + +**Parts of ECMA-335 that become obsolete/inaccurate/incomplete** +>I.8.5.3.2 Accessibility of members and nested types +Members (other than nested types) defined by an interface shall be public. +I.8.9.4 Interface type definition +Similarly, an interface type definition shall not provide implementations for any methods on the +values of its type. +Interfaces can have static or virtual methods, but shall not have instance methods. +However, since accessibility attributes are relative to the implementing type rather +than the interface itself, all members of an interface shall have public accessibility, ... +I.8.11.1 Method definitions +All non-static methods of an interface definition are abstract. +All non-static method definitions in interface definitions shall be virtual methods. +II.10.4 Method implementat ion requirements +II.12 Semantics of interfaces +Interfaces can have static fields and methods, but they shall not have instance fields or +methods. Interfaces can define virtual methods, but only if those methods are abstract +(see Partition I and §II.15.4.2.4). +II.12.2 Implement ing virtual methods on interfaces +If the class defines any public virtual methods whose name and signature +match a virtual method on the interface, then add these to the list for that +method, in type declaration order (see above). +If there are any public virtual methods available on this class (directly or inherited) +having the same name and signature as the interface method, and whose generic type +parameters do not exactly match any methods in the existing list for that interface +method for this class or any class in its inheritance chain, then add them (in type +declaration order) to the list for the corresponding methods on the interface. +II.15.2 Static, instance, and virtual methods +It follows that instance methods shall only be defined in classes or value types, +but not in interfaces or outside of a type (i.e., globally). +II.22.27 MethodImpl : 0x19 +The method indexed by MethodBody shall be a member of Class or some base class +of Class (MethodImpls do not allow compilers to ‘hook’ arbitrary method bodies) +II.22.37 TypeDef : 0x02 +All of the methods owned by an Interface (Flags.Interface = 1) shall be abstract +(Flags.Abstract = 1) +IV.6 Implementation-specific modifications to the system libraries +Interfaces and virtual methods shall not be added to an existing interface. diff --git a/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs b/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs index ba34e166c9b82..62448e9d142e4 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs +++ b/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs @@ -20,7 +20,7 @@ namespace Microsoft.CodeAnalysis.CSharp { // class via a tool like ResGen or Visual Studio. // To add or remove a member, edit your .ResX file then rerun ResGen // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] internal class CSharpResources { @@ -3212,20 +3212,20 @@ internal static string ERR_DeconstructWrongCardinality { } /// - /// Looks up a localized string similar to Use of default literal is not valid in this context. + /// Looks up a localized string similar to The modifier '{0}' is not valid for this item in C# {1}. Please use language version {2} or greater.. /// - internal static string ERR_DefaultLiteralNotValid { + internal static string ERR_DefaultInterfaceImplementationModifier { get { - return ResourceManager.GetString("ERR_DefaultLiteralNotValid", resourceCulture); + return ResourceManager.GetString("ERR_DefaultInterfaceImplementationModifier", resourceCulture); } } /// - /// Looks up a localized string similar to The modifier '{0}' is not valid for this item in C# {1}. Please use language version {2} or greater.. + /// Looks up a localized string similar to Use of default literal is not valid in this context. /// - internal static string ERR_DefaultInterfaceImplementationModifier { + internal static string ERR_DefaultLiteralNotValid { get { - return ResourceManager.GetString("ERR_DefaultInterfaceImplementationModifier", resourceCulture); + return ResourceManager.GetString("ERR_DefaultLiteralNotValid", resourceCulture); } } @@ -5047,6 +5047,15 @@ internal static string ERR_ImplBadTupleNames { } } + /// + /// Looks up a localized string similar to '{0}' does not implement interface member '{1}'. '{2}' cannot implicitly implement a non-public member.. + /// + internal static string ERR_ImplicitImplementationOfNonPublicInterfaceMember { + get { + return ResourceManager.GetString("ERR_ImplicitImplementationOfNonPublicInterfaceMember", resourceCulture); + } + } + /// /// Looks up a localized string similar to No best type found for implicitly-typed array. /// diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx index a0c8e393c68d5..011fc30ae60ba 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.resx +++ b/src/Compilers/CSharp/Portable/CSharpResources.resx @@ -5076,4 +5076,7 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ The modifier '{0}' is not valid for this item in C# {1}. Please use language version {2} or greater. + + '{0}' does not implement interface member '{1}'. '{2}' cannot implicitly implement a non-public member. + diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs index 7e1844fded576..8343bd6e0f6df 100644 --- a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs +++ b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs @@ -1485,6 +1485,7 @@ internal enum ErrorCode // PROTOTYPE(DefaultInterfaceImplementation): Should add this error code to the list monitored by the UpgradeProject code fixer. // This PR can be used to find the relevant code and test files: https://github.com/dotnet/roslyn/pull/18045. ERR_DefaultInterfaceImplementationModifier = 8503, + ERR_ImplicitImplementationOfNonPublicInterfaceMember = 8504, ERR_BadDynamicMethodArgDefaultLiteral = 9000, ERR_DefaultLiteralNotValid = 9001, diff --git a/src/Compilers/CSharp/Portable/Symbols/MemberSymbolExtensions.cs b/src/Compilers/CSharp/Portable/Symbols/MemberSymbolExtensions.cs index ee437ed7d7344..fa11868fcc95c 100644 --- a/src/Compilers/CSharp/Portable/Symbols/MemberSymbolExtensions.cs +++ b/src/Compilers/CSharp/Portable/Symbols/MemberSymbolExtensions.cs @@ -119,6 +119,27 @@ internal static bool HasUnsafeParameter(this Symbol member) return false; } + public static bool IsEventOrPropertyWithNonPublicAccessor(this Symbol symbol) + { + switch (symbol.Kind) + { + case SymbolKind.Property: + var propertySymbol = (PropertySymbol)symbol; + return AccessorIsNotPublic(propertySymbol.GetMethod) || AccessorIsNotPublic(propertySymbol.SetMethod); + + case SymbolKind.Event: + var eventSymbol = (EventSymbol)symbol; + return AccessorIsNotPublic(eventSymbol.AddMethod) || AccessorIsNotPublic(eventSymbol.RemoveMethod); + } + + return false; + + bool AccessorIsNotPublic(MethodSymbol accessor) + { + return (object)accessor != null && accessor.DeclaredAccessibility != Accessibility.Public; + } + } + public static bool IsAccessor(this MethodSymbol methodSymbol) { return (object)methodSymbol.AssociatedSymbol != null; diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/ExplicitInterfaceHelpers.cs b/src/Compilers/CSharp/Portable/Symbols/Source/ExplicitInterfaceHelpers.cs index 0c51f66300580..3a18bca95d60d 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/ExplicitInterfaceHelpers.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/ExplicitInterfaceHelpers.cs @@ -1,5 +1,6 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; using System.Text; @@ -219,8 +220,6 @@ private static Symbol FindExplicitlyImplementedMember( { // At this point, we know that explicitInterfaceNamedType is an interface. // However, metadata interface members can be static - we ignore them, as does Dev10. - // PROTOTYPE(DefaultInterfaceImplementation): We might want to check accessibility of the members as well, since - // they don't have to be public any more. if (interfaceMember.Kind != implementingMember.Kind || !interfaceMember.IsImplementableInterfaceMember()) { continue; @@ -261,6 +260,45 @@ private static Symbol FindExplicitlyImplementedMember( diagnostics.Add(ErrorCode.ERR_InterfaceMemberNotFound, memberLocation, implementingMember); } + // Make sure implemented member is accessible + if ((object)implementedMember != null) + { + HashSet useSiteDiagnostics = null; + + if (!AccessCheck.IsSymbolAccessible(implementedMember, implementingMember.ContainingType, ref useSiteDiagnostics, throughTypeOpt: implementedMember.ContainingType)) + { + diagnostics.Add(ErrorCode.ERR_BadAccess, memberLocation, implementedMember); + } + else + { + switch (implementedMember.Kind) + { + case SymbolKind.Property: + var propertySymbol = (PropertySymbol)implementedMember; + CheckAccessorAccessible(propertySymbol.GetMethod); + CheckAccessorAccessible(propertySymbol.SetMethod); + break; + + case SymbolKind.Event: + var eventSymbol = (EventSymbol)implementedMember; + CheckAccessorAccessible(eventSymbol.AddMethod); + CheckAccessorAccessible(eventSymbol.RemoveMethod); + break; + } + + void CheckAccessorAccessible(MethodSymbol accessor) + { + if ((object)accessor != null && + !AccessCheck.IsSymbolAccessible(accessor, implementingMember.ContainingType, ref useSiteDiagnostics, throughTypeOpt: accessor.ContainingType)) + { + diagnostics.Add(ErrorCode.ERR_BadAccess, memberLocation, accessor); + } + } + } + + diagnostics.Add(memberLocation, useSiteDiagnostics); + } + if (MemberSignatureComparer.ConsideringTupleNamesCreatesDifference(implementingMember, implementedMember)) { diagnostics.Add(ErrorCode.ERR_ImplBadTupleNames, memberLocation, implementingMember, implementedMember); diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol_ImplementationChecks.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol_ImplementationChecks.cs index 82282674697c5..d7e9a373cc687 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol_ImplementationChecks.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol_ImplementationChecks.cs @@ -1025,6 +1025,15 @@ private void CheckInterfaceUnification(DiagnosticBag diagnostics) /// Synthesized implementation or null if not needed. private SynthesizedExplicitImplementationForwardingMethod SynthesizeInterfaceMemberImplementation(SymbolAndDiagnostics implementingMemberAndDiagnostics, Symbol interfaceMember) { + if (interfaceMember.DeclaredAccessibility != Accessibility.Public) + { + // Non-public interface members cannot be implemented implicitly, + // appropriate errors are reported elsewhere. Let's not synthesize + // forwarding methods, or modify metadata virtualness of the + // implementing methods. + return null; + } + foreach (Diagnostic diagnostic in implementingMemberAndDiagnostics.Diagnostics) { if (diagnostic.Severity == DiagnosticSeverity.Error) @@ -1044,6 +1053,15 @@ private SynthesizedExplicitImplementationForwardingMethod SynthesizeInterfaceMem MethodSymbol interfaceMethod = (MethodSymbol)interfaceMember; MethodSymbol implementingMethod = (MethodSymbol)implementingMember; + // Interface properties/events with non-public accessors cannot be implemented implicitly, + // appropriate errors are reported elsewhere. Let's not synthesize + // forwarding methods, or modify metadata virtualness of the + // implementing accessors, even for public ones. + if (interfaceMethod.AssociatedSymbol?.IsEventOrPropertyWithNonPublicAccessor() == true) + { + return null; + } + //explicit implementations are always respected by the CLR if (implementingMethod.ExplicitInterfaceImplementations.Contains(interfaceMethod)) { diff --git a/src/Compilers/CSharp/Portable/Symbols/TypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/TypeSymbol.cs index b7a03328958a1..ff1eedc9a78c0 100644 --- a/src/Compilers/CSharp/Portable/Symbols/TypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/TypeSymbol.cs @@ -775,7 +775,7 @@ private SymbolAndDiagnostics ComputeImplementationAndDiagnosticsForInterfaceMemb /// /// CONSIDER: we could probably do less work in the metadata and retargeting cases - we won't use the diagnostics. /// - /// A non-null property on an interface type. + /// A non-null implementable member on an interface type. /// The type implementing the interface property (usually "this"). /// Bag to which to add diagnostics. /// The implementing property or null, if there isn't one. @@ -807,6 +807,8 @@ private static Symbol ComputeImplementationForInterfaceMember(Symbol interfaceMe Symbol implicitImpl = null; Symbol closestMismatch = null; + bool canBeImplementedImplicitly = interfaceMember.DeclaredAccessibility == Accessibility.Public && !interfaceMember.IsEventOrPropertyWithNonPublicAccessor(); + TypeSymbol implementingBaseOpt = null; // Calculated only if canBeImplementedImplicitly == true for (TypeSymbol currType = implementingType; (object)currType != null; currType = currType.BaseTypeNoUseSiteDiagnostics) { @@ -829,7 +831,20 @@ private static Symbol ComputeImplementationForInterfaceMember(Symbol interfaceMe return currTypeExplicitImpl; } - seenTypeDeclaringInterface = seenTypeDeclaringInterface || currType.InterfacesAndTheirBaseInterfacesNoUseSiteDiagnostics.Contains(interfaceType); + if (!seenTypeDeclaringInterface || + (!canBeImplementedImplicitly && (object)implementingBaseOpt == null)) + { + if (currType.InterfacesAndTheirBaseInterfacesNoUseSiteDiagnostics.Contains(interfaceType)) + { + seenTypeDeclaringInterface = true; + + if (!canBeImplementedImplicitly && (object)implementingBaseOpt == null && (object)currType != implementingType) + { + implementingBaseOpt = currType; + } + } + } + // We want the implementation from the most derived type at or above the first one to // include the interface (or a subinterface) in its interface list @@ -859,11 +874,14 @@ private static Symbol ComputeImplementationForInterfaceMember(Symbol interfaceMe } } + Debug.Assert(!canBeImplementedImplicitly || (object)implementingBaseOpt == null); + // Dev10 has some extra restrictions and extra wiggle room when finding implicit // implementations for interface accessors. Perform some extra checks and possibly // update the result (i.e. implicitImpl). if (interfaceMember.IsAccessor()) { + // PROTOTYPE(DefaultInterfaceImplementation): Do we need to adjust behavior of this function in any way? CheckForImplementationOfCorrespondingPropertyOrEvent((MethodSymbol)interfaceMember, implementingType, implementingTypeIsFromSomeCompilation, ref implicitImpl); } @@ -878,10 +896,24 @@ private static Symbol ComputeImplementationForInterfaceMember(Symbol interfaceMe if ((object)implicitImpl != null) { - ReportImplicitImplementationMatchDiagnostics(interfaceMember, implementingType, implicitImpl, diagnostics); + if (!canBeImplementedImplicitly && !implicitImpl.ContainingType.IsInterface) + { + if (interfaceMember.Kind == SymbolKind.Method && + (object)implementingBaseOpt == null) // Otherwise any approprite errors are going to be reported for the base. + { + diagnostics.Add(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, GetInterfaceLocation(interfaceMember, implementingType), + implementingType, interfaceMember, implicitImpl); + } + } + else + { + ReportImplicitImplementationMatchDiagnostics(interfaceMember, implementingType, implicitImpl, diagnostics); + } } else if ((object)closestMismatch != null) { + Debug.Assert(interfaceMember.DeclaredAccessibility == Accessibility.Public); + Debug.Assert(!interfaceMember.IsEventOrPropertyWithNonPublicAccessor()); ReportImplicitImplementationMismatchDiagnostics(interfaceMember, implementingType, closestMismatch, diagnostics); } @@ -1297,8 +1329,12 @@ private static void FindPotentialImplicitImplementationMemberDeclaredInType( return; } - //if we haven't found a match, do a weaker comparison that ignores static-ness, accessibility, and return type - if ((object)closeMismatch == null && implementingTypeIsFromSomeCompilation) + // If we haven't found a match, do a weaker comparison that ignores static-ness, accessibility, and return type. + // But do this only if interface member is public because language doesn't allow implicit implementations for + // non-public members and, since candidate's signature doesn't match, runtime will never pick it up either. + else if ((object)closeMismatch == null && implementingTypeIsFromSomeCompilation && + interfaceMember.DeclaredAccessibility == Accessibility.Public && + !interfaceMember.IsEventOrPropertyWithNonPublicAccessor()) { // We can ignore custom modifiers here, because our goal is to improve the helpfulness // of an error we're already giving, rather than to generate a new error. diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/DefaultInterfaceImplementationTests.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/DefaultInterfaceImplementationTests.cs index afba43699f602..409aa8a8a6eea 100644 --- a/src/Compilers/CSharp/Test/Symbol/Symbols/DefaultInterfaceImplementationTests.cs +++ b/src/Compilers/CSharp/Test/Symbol/Symbols/DefaultInterfaceImplementationTests.cs @@ -6052,7 +6052,7 @@ class Test1 : I1 } [Fact] - public void MethodModifiers_10() + public void MethodModifiers_10_01() { var source1 = @" @@ -6083,56 +6083,42 @@ public void M1() var compilation1 = CreateStandardCompilation(source1 + source2, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); - CompileAndVerify(compilation1/*, expectedOutput:"M1"*/, verify:false, symbolValidator: Validate1); - - Validate1(compilation1.SourceModule); - - void Validate1(ModuleSymbol m) - { - var test1 = m.GlobalNamespace.GetTypeMember("Test1"); - var i1 = test1.Interfaces.Single(); - var m1 = i1.GetMember("M1"); - - ValidateMethod(m1); - Assert.Same(test1.GetMember("M1"), test1.FindImplementationForInterfaceMember(m1)); - } + compilation1.VerifyDiagnostics( + // (9,15): error CS8504: 'Test1' does not implement interface member 'I1.M1()'. 'Test1.M1()' cannot implicitly implement a non-public member. + // class Test1 : I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test1", "I1.M1()", "Test1.M1()").WithLocation(9, 15) + ); - void ValidateMethod(MethodSymbol m1) - { - Assert.True(m1.IsAbstract); - Assert.False(m1.IsVirtual); - Assert.True(m1.IsMetadataVirtual()); - Assert.False(m1.IsSealed); - Assert.False(m1.IsStatic); - Assert.False(m1.IsExtern); - Assert.False(m1.IsAsync); - Assert.False(m1.IsOverride); - Assert.Equal(Accessibility.Internal, m1.DeclaredAccessibility); - } + ValidateMethodModifiersImplicit_10(compilation1.SourceModule); var compilation2 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation2.VerifyDiagnostics(); - { - var i1 = compilation2.GetTypeByMetadataName("I1"); - ValidateMethod(i1.GetMember("M1")); - } + ValidateMethodModifiers_10(compilation2.GetTypeByMetadataName("I1").GetMember("M1")); var compilation3 = CreateStandardCompilation(source2, new[] { compilation2.ToMetadataReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); Assert.True(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); - CompileAndVerify(compilation3/*, expectedOutput:"M1"*/, verify: false, symbolValidator: Validate1); + compilation3.VerifyDiagnostics( + // (2,15): error CS8504: 'Test1' does not implement interface member 'I1.M1()'. 'Test1.M1()' cannot implicitly implement a non-public member. + // class Test1 : I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test1", "I1.M1()", "Test1.M1()").WithLocation(2, 15) + ); - Validate1(compilation3.SourceModule); + ValidateMethodModifiersImplicit_10(compilation3.SourceModule); var compilation4 = CreateStandardCompilation(source2, new[] { compilation2.EmitToImageReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); Assert.True(compilation4.Assembly.RuntimeSupportsDefaultInterfaceImplementation); - CompileAndVerify(compilation4/*, expectedOutput:"M1"*/, verify: false, symbolValidator: Validate1); + compilation4.VerifyDiagnostics( + // (2,15): error CS8504: 'Test1' does not implement interface member 'I1.M1()'. 'Test1.M1()' cannot implicitly implement a non-public member. + // class Test1 : I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test1", "I1.M1()", "Test1.M1()").WithLocation(2, 15) + ); - Validate1(compilation4.SourceModule); + ValidateMethodModifiersImplicit_10(compilation4.SourceModule); var source3 = @" @@ -6150,12 +6136,7 @@ class Test2 : I1 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test2", "I1.M1()").WithLocation(2, 15) ); - { - var test2 = compilation5.GetTypeByMetadataName("Test2"); - var i1 = compilation5.GetTypeByMetadataName("I1"); - var m1 = i1.GetMember("M1"); - Assert.Null(test2.FindImplementationForInterfaceMember(m1)); - } + ValidateI1M1NotImplemented(compilation5, "Test2"); var compilation6 = CreateStandardCompilation(source3, new[] { compilation2.EmitToImageReference() }, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); @@ -6166,41 +6147,57 @@ class Test2 : I1 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test2", "I1.M1()").WithLocation(2, 15) ); - { - var test2 = compilation6.GetTypeByMetadataName("Test2"); - var i1 = compilation6.GetTypeByMetadataName("I1"); - var m1 = i1.GetMember("M1"); - Assert.Null(test2.FindImplementationForInterfaceMember(m1)); - } + ValidateI1M1NotImplemented(compilation6, "Test2"); } - [Fact] - public void MethodModifiers_11() + private static void ValidateI1M1NotImplemented(CSharpCompilation compilation, string className) { - var source1 = -@" -public interface I1 -{ - internal abstract void M1(); -} + var test2 = compilation.GetTypeByMetadataName(className); + var i1 = compilation.GetTypeByMetadataName("I1"); + var m1 = i1.GetMember("M1"); + Assert.Null(test2.FindImplementationForInterfaceMember(m1)); + } -class Test1 : I1 -{ -} -"; - var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, - parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); - Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); - compilation1.VerifyDiagnostics( - // (7,15): error CS0535: 'Test1' does not implement interface member 'I1.M1()' - // class Test1 : I1 - Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test1", "I1.M1()").WithLocation(7, 15) - ); + private static void ValidateMethodModifiersImplicit_10(ModuleSymbol m) + { + ValidateMethodModifiers_10(m, implementedByBase: false, isExplicit: false); + } - var test1 = compilation1.GetTypeByMetadataName("Test1"); - var i1 = compilation1.GetTypeByMetadataName("I1"); + private static void ValidateMethodModifiersExplicit_10(ModuleSymbol m) + { + ValidateMethodModifiers_10(m, implementedByBase: false, isExplicit: true); + } + + private static void ValidateMethodModifiersImplicitInTest2_10(ModuleSymbol m) + { + ValidateMethodModifiers_10(m, implementedByBase: true, isExplicit: false); + } + + private static void ValidateMethodModifiersExplicitInTest2_10(ModuleSymbol m) + { + ValidateMethodModifiers_10(m, implementedByBase: true, isExplicit: true); + } + + private static void ValidateMethodModifiers_10(ModuleSymbol m, bool implementedByBase, bool isExplicit) + { + var test1 = m.GlobalNamespace.GetTypeMember("Test1"); + var i1 = test1.Interfaces.Where(i => i.Name == "I1").Single(); var m1 = i1.GetMember("M1"); + ValidateMethodModifiers_10(m1); + var implementation = (implementedByBase ? test1.BaseType : test1).GetMember((isExplicit ? "I1." : "") + "M1"); + Assert.NotNull(implementation); + Assert.Same(implementation, test1.FindImplementationForInterfaceMember(m1)); + + var i2 = test1.Interfaces.Where(i => i.Name == "I2").SingleOrDefault(); + Assert.Equal(implementation.IsVirtual || implementation.IsAbstract || isExplicit || + (!implementedByBase && (object)i2 != null && + (object)implementation == test1.FindImplementationForInterfaceMember(i2.GetMember("M1"))), + implementation.IsMetadataVirtual()); + } + + private static void ValidateMethodModifiers_10(MethodSymbol m1) + { Assert.True(m1.IsAbstract); Assert.False(m1.IsVirtual); Assert.True(m1.IsMetadataVirtual()); @@ -6210,2040 +6207,1846 @@ class Test1 : I1 Assert.False(m1.IsAsync); Assert.False(m1.IsOverride); Assert.Equal(Accessibility.Internal, m1.DeclaredAccessibility); - Assert.Null(test1.FindImplementationForInterfaceMember(m1)); } [Fact] - public void MethodModifiers_12() + public void MethodModifiers_10_02() { var source1 = @" public interface I1 { - public sealed void M1() - { - System.Console.WriteLine(""M1""); - } + internal abstract void M1(); } +public class TestHelper +{ + public static void CallM1(I1 x) {x.M1();} +} +"; + + var source2 = +@" class Test1 : I1 { static void Main() { - I1 x = new Test1(); - x.M1(); + TestHelper.CallM1(new Test1()); } - public void M1() + public virtual void M1() { - System.Console.WriteLine(""Test1.M1""); + System.Console.WriteLine(""M1""); } } "; - var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugExe, + + ValidateMethodModifiers_10_02(source1, source2, + // (2,15): error CS8504: 'Test1' does not implement interface member 'I1.M1()'. 'Test1.M1()' cannot implicitly implement a non-public member. + // class Test1 : I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test1", "I1.M1()", "Test1.M1()").WithLocation(2, 15) + ); + } + + private void ValidateMethodModifiers_10_02(string source1, string source2, + params DiagnosticDescription[] expected) + { + var compilation1 = CreateStandardCompilation(source2 + source1, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation1.VerifyDiagnostics(expected); - void Validate(ModuleSymbol m) - { - var test1 = m.GlobalNamespace.GetTypeMember("Test1"); - var i1 = m.GlobalNamespace.GetTypeMember("I1"); - var m1 = i1.GetMember("M1"); + ValidateMethodModifiersImplicit_10(compilation1.SourceModule); - Assert.False(m1.IsAbstract); - Assert.False(m1.IsVirtual); - Assert.False(m1.IsMetadataVirtual()); - Assert.False(m1.IsSealed); - Assert.False(m1.IsStatic); - Assert.False(m1.IsExtern); - Assert.False(m1.IsAsync); - Assert.False(m1.IsOverride); - Assert.Equal(Accessibility.Public, m1.DeclaredAccessibility); - Assert.Null(test1.FindImplementationForInterfaceMember(m1)); - } + var compilation2 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation2.VerifyDiagnostics(); - CompileAndVerify(compilation1/*, expectedOutput:"M1"*/, verify: false, symbolValidator: Validate); - Validate(compilation1.SourceModule); + ValidateMethodModifiers_10(compilation2.GetTypeByMetadataName("I1").GetMember("M1")); + + var compilation3 = CreateStandardCompilation(source2, new[] { compilation2.ToMetadataReference() }, options: TestOptions.DebugExe, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation3.VerifyDiagnostics(expected); + + ValidateMethodModifiersImplicit_10(compilation3.SourceModule); + + var compilation4 = CreateStandardCompilation(source2, new[] { compilation2.EmitToImageReference() }, options: TestOptions.DebugExe, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation4.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation4.VerifyDiagnostics(expected); + + ValidateMethodModifiersImplicit_10(compilation4.SourceModule); } [Fact] - public void MethodModifiers_13() + public void MethodModifiers_10_03() { var source1 = @" public interface I1 { - public sealed void M1() - { - System.Console.WriteLine(""M1""); - } - - abstract sealed void M2(); - - virtual sealed void M3() - { - } + internal abstract void M1(); +} - public sealed void M4(); +public class TestHelper +{ + public static void CallM1(I1 x) {x.M1();} } +"; + var source2 = +@" class Test1 : I1 { - void I1.M1() {} - void I1.M2() {} - void I1.M3() {} - void I1.M4() {} -} + static void Main() + { + TestHelper.CallM1(new Test1()); + } -class Test2 : I1 -{} + void I1.M1() + { + System.Console.WriteLine(""M1""); + } +} "; - var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, + var compilation1 = CreateStandardCompilation(source1 + source2, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); - compilation1.VerifyDiagnostics( - // (15,24): error CS0501: 'I1.M4()' must declare a body because it is not marked abstract, extern, or partial - // public sealed void M4(); - Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "M4").WithArguments("I1.M4()").WithLocation(15, 24), - // (9,26): error CS0238: 'I1.M2()' cannot be sealed because it is not an override - // abstract sealed void M2(); - Diagnostic(ErrorCode.ERR_SealedNonOverride, "M2").WithArguments("I1.M2()").WithLocation(9, 26), - // (11,25): error CS0238: 'I1.M3()' cannot be sealed because it is not an override - // virtual sealed void M3() - Diagnostic(ErrorCode.ERR_SealedNonOverride, "M3").WithArguments("I1.M3()").WithLocation(11, 25), - // (26,15): error CS0535: 'Test2' does not implement interface member 'I1.M2()' - // class Test2 : I1 - Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test2", "I1.M2()").WithLocation(26, 15), - // (23,13): error CS0539: 'Test1.M4()' in explicit interface declaration is not found among members of the interface that can be implemented - // void I1.M4() {} - Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "M4").WithArguments("Test1.M4()").WithLocation(23, 13), - // (20,13): error CS0539: 'Test1.M1()' in explicit interface declaration is not found among members of the interface that can be implemented - // void I1.M1() {} - Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "M1").WithArguments("Test1.M1()").WithLocation(20, 13) - ); + CompileAndVerify(compilation1, expectedOutput: "M1", verify: false, symbolValidator: ValidateMethodModifiersExplicit_10); - var test1 = compilation1.GetTypeByMetadataName("Test1"); - var test2 = compilation1.GetTypeByMetadataName("Test2"); - var i1 = compilation1.GetTypeByMetadataName("I1"); - var m1 = i1.GetMember("M1"); + ValidateMethodModifiersExplicit_10(compilation1.SourceModule); - Assert.False(m1.IsAbstract); - Assert.False(m1.IsVirtual); - Assert.False(m1.IsMetadataVirtual()); - Assert.False(m1.IsSealed); - Assert.False(m1.IsStatic); - Assert.False(m1.IsExtern); - Assert.False(m1.IsAsync); - Assert.False(m1.IsOverride); - Assert.Equal(Accessibility.Public, m1.DeclaredAccessibility); - Assert.Null(test1.FindImplementationForInterfaceMember(m1)); - Assert.Null(test2.FindImplementationForInterfaceMember(m1)); + var compilation2 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation2.VerifyDiagnostics(); - var m2 = i1.GetMember("M2"); + ValidateMethodModifiers_10(compilation2.GetTypeByMetadataName("I1").GetMember("M1")); - Assert.True(m2.IsAbstract); - Assert.False(m2.IsVirtual); - Assert.True(m2.IsMetadataVirtual()); - Assert.True(m2.IsSealed); - Assert.False(m2.IsStatic); - Assert.False(m2.IsExtern); - Assert.False(m2.IsAsync); - Assert.False(m2.IsOverride); - Assert.Equal(Accessibility.Public, m2.DeclaredAccessibility); - Assert.Same(test1.GetMember("I1.M2"), test1.FindImplementationForInterfaceMember(m2)); - Assert.Null(test2.FindImplementationForInterfaceMember(m2)); + var compilation3 = CreateStandardCompilation(source2, new[] { compilation2.ToMetadataReference() }, options: TestOptions.DebugExe, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation3.VerifyDiagnostics( + // (9,13): error CS0122: 'I1.M1()' is inaccessible due to its protection level + // void I1.M1() + Diagnostic(ErrorCode.ERR_BadAccess, "M1").WithArguments("I1.M1()").WithLocation(9, 13) + ); - var m3 = i1.GetMember("M3"); + ValidateMethodModifiersExplicit_10(compilation3.SourceModule); - Assert.False(m3.IsAbstract); - Assert.True(m3.IsVirtual); - Assert.True(m3.IsMetadataVirtual()); - Assert.True(m3.IsSealed); - Assert.False(m3.IsStatic); - Assert.False(m3.IsExtern); - Assert.False(m3.IsAsync); - Assert.False(m3.IsOverride); - Assert.Equal(Accessibility.Public, m3.DeclaredAccessibility); - Assert.Same(test1.GetMember("I1.M3"), test1.FindImplementationForInterfaceMember(m3)); - Assert.Same(m3, test2.FindImplementationForInterfaceMember(m3)); + var compilation4 = CreateStandardCompilation(source2, new[] { compilation2.EmitToImageReference() }, options: TestOptions.DebugExe, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation4.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation4.VerifyDiagnostics( + // (9,13): error CS0122: 'I1.M1()' is inaccessible due to its protection level + // void I1.M1() + Diagnostic(ErrorCode.ERR_BadAccess, "M1").WithArguments("I1.M1()").WithLocation(9, 13) + ); - var m4 = i1.GetMember("M4"); - - Assert.False(m4.IsAbstract); - Assert.False(m4.IsVirtual); - Assert.False(m4.IsMetadataVirtual()); - Assert.False(m4.IsSealed); - Assert.False(m4.IsStatic); - Assert.False(m4.IsExtern); - Assert.False(m4.IsAsync); - Assert.False(m4.IsOverride); - Assert.Equal(Accessibility.Public, m4.DeclaredAccessibility); - Assert.Null(test1.FindImplementationForInterfaceMember(m4)); - Assert.Null(test2.FindImplementationForInterfaceMember(m4)); - } + ValidateMethodModifiersExplicit_10(compilation4.SourceModule); + } [Fact] - public void MethodModifiers_14() + public void MethodModifiers_10_04() { var source1 = @" public interface I1 { - abstract virtual void M2(); + internal abstract void M1(); +} - virtual abstract void M3() +public class TestHelper +{ + public static void CallM1(I1 x) {x.M1();} +} + +public class Test2 : I1 +{ + void I1.M1() { + System.Console.WriteLine(""Test2.M1""); } } +"; -class Test1 : I1 + var source2 = +@" +class Test1 : Test2, I1 { - void I1.M2() {} - void I1.M3() {} -} + static void Main() + { + TestHelper.CallM1(new Test1()); + } -class Test2 : I1 -{} + public void M1() + { + System.Console.WriteLine(""Test1.M1""); + } +} "; - var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, - parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); - Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); - compilation1.VerifyDiagnostics( - // (6,27): error CS0500: 'I1.M3()' cannot declare a body because it is marked abstract - // virtual abstract void M3() - Diagnostic(ErrorCode.ERR_AbstractHasBody, "M3").WithArguments("I1.M3()").WithLocation(6, 27), - // (6,27): error CS0503: The abstract method 'I1.M3()' cannot be marked virtual - // virtual abstract void M3() - Diagnostic(ErrorCode.ERR_AbstractNotVirtual, "M3").WithArguments("I1.M3()").WithLocation(6, 27), - // (4,27): error CS0503: The abstract method 'I1.M2()' cannot be marked virtual - // abstract virtual void M2(); - Diagnostic(ErrorCode.ERR_AbstractNotVirtual, "M2").WithArguments("I1.M2()").WithLocation(4, 27), - // (17,15): error CS0535: 'Test2' does not implement interface member 'I1.M3()' - // class Test2 : I1 - Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test2", "I1.M3()").WithLocation(17, 15), - // (17,15): error CS0535: 'Test2' does not implement interface member 'I1.M2()' - // class Test2 : I1 - Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test2", "I1.M2()").WithLocation(17, 15) + ValidateMethodModifiers_10_02(source1, source2, + // (2,22): error CS8504: 'Test1' does not implement interface member 'I1.M1()'. 'Test1.M1()' cannot implicitly implement a non-public member. + // class Test1 : Test2, I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test1", "I1.M1()", "Test1.M1()").WithLocation(2, 22) ); + } - var test1 = compilation1.GetTypeByMetadataName("Test1"); - var test2 = compilation1.GetTypeByMetadataName("Test2"); - var i1 = compilation1.GetTypeByMetadataName("I1"); + [Fact] + public void MethodModifiers_10_05() + { + var source1 = +@" +public interface I1 +{ + internal abstract void M1(); +} - foreach (var methodName in new[] { "M2", "M3" }) - { - var m2 = i1.GetMember(methodName); +public class TestHelper +{ + public static void CallM1(I1 x) {x.M1();} +} - Assert.True(m2.IsAbstract); - Assert.True(m2.IsVirtual); - Assert.True(m2.IsMetadataVirtual()); - Assert.False(m2.IsSealed); - Assert.False(m2.IsStatic); - Assert.False(m2.IsExtern); - Assert.False(m2.IsAsync); - Assert.False(m2.IsOverride); - Assert.Equal(Accessibility.Public, m2.DeclaredAccessibility); - Assert.Same(test1.GetMember("I1." + methodName), test1.FindImplementationForInterfaceMember(m2)); - Assert.Null(test2.FindImplementationForInterfaceMember(m2)); - } +public class Test2 : I1 +{ + void I1.M1() + { + System.Console.WriteLine(""Test2.M1""); + } +} +"; + + var source2 = +@" +class Test1 : Test2, I1 +{ + static void Main() + { + TestHelper.CallM1(new Test1()); + } + + public virtual void M1() + { + System.Console.WriteLine(""Test1.M1""); + } +} +"; + ValidateMethodModifiers_10_02(source1, source2, + // (2,22): error CS8504: 'Test1' does not implement interface member 'I1.M1()'. 'Test1.M1()' cannot implicitly implement a non-public member. + // class Test1 : Test2, I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test1", "I1.M1()", "Test1.M1()").WithLocation(2, 22) + ); } [Fact] - public void MethodModifiers_15() + public void MethodModifiers_10_06() { var source1 = @" public interface I1 { - extern void M1(); - virtual extern void M2(); - static extern void M3(); - private extern void M4(); - extern sealed void M5(); + internal abstract void M1(); } -class Test1 : I1 +public class TestHelper { + public static void CallM1(I1 x) {x.M1();} } -class Test2 : I1 +public class Test2 : I1 { - void I1.M1() {} - void I1.M2() {} + void I1.M1() + { + System.Console.WriteLine(""Test2.M1""); + } } "; - var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All), - parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); - Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); - CompileAndVerify(compilation1, verify: false, symbolValidator: Validate); - - Validate(compilation1.SourceModule); - - void Validate(ModuleSymbol m) - { - var test1 = m.GlobalNamespace.GetTypeMember("Test1"); - var test2 = m.GlobalNamespace.GetTypeMember("Test2"); - var i1 = m.GlobalNamespace.GetTypeMember("I1"); - var m1 = i1.GetMember("M1"); - bool isSource = !(m is PEModuleSymbol); - Assert.False(m1.IsAbstract); - Assert.True(m1.IsVirtual); - Assert.True(m1.IsMetadataVirtual()); - Assert.False(m1.IsSealed); - Assert.False(m1.IsStatic); - Assert.Equal(isSource, m1.IsExtern); - Assert.False(m1.IsAsync); - Assert.False(m1.IsOverride); - Assert.Equal(Accessibility.Public, m1.DeclaredAccessibility); - Assert.Same(m1, test1.FindImplementationForInterfaceMember(m1)); - Assert.Same(test2.GetMember("I1.M1"), test2.FindImplementationForInterfaceMember(m1)); + var source2 = +@"abstract +class Test1 : Test2, I1 +{ + static void Main() + { + TestHelper.CallM1(new Test3()); + } - var m2 = i1.GetMember("M2"); + public abstract void M1(); +} - Assert.False(m2.IsAbstract); - Assert.True(m2.IsVirtual); - Assert.True(m2.IsMetadataVirtual()); - Assert.False(m2.IsSealed); - Assert.False(m2.IsStatic); - Assert.Equal(isSource, m2.IsExtern); - Assert.False(m2.IsAsync); - Assert.False(m2.IsOverride); - Assert.Equal(Accessibility.Public, m2.DeclaredAccessibility); - Assert.Same(m2, test1.FindImplementationForInterfaceMember(m2)); - Assert.Same(test2.GetMember("I1.M2"), test2.FindImplementationForInterfaceMember(m2)); +class Test3 : Test1 +{ + public override void M1() + { + System.Console.WriteLine(""Test3.M1""); + } +} +"; + ValidateMethodModifiers_10_02(source1, source2, + // (2,22): error CS8504: 'Test1' does not implement interface member 'I1.M1()'. 'Test1.M1()' cannot implicitly implement a non-public member. + // class Test1 : Test2, I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test1", "I1.M1()", "Test1.M1()").WithLocation(2, 22) + ); + } - var m3 = i1.GetMember("M3"); + [Fact] + public void MethodModifiers_10_07() + { + var source1 = +@" +public interface I1 +{ + internal abstract void M1(); +} - Assert.False(m3.IsAbstract); - Assert.False(m3.IsVirtual); - Assert.False(m3.IsMetadataVirtual()); - Assert.False(m3.IsSealed); - Assert.True(m3.IsStatic); - Assert.Equal(isSource, m3.IsExtern); - Assert.False(m3.IsAsync); - Assert.False(m3.IsOverride); - Assert.Equal(Accessibility.Public, m3.DeclaredAccessibility); - Assert.Null(test1.FindImplementationForInterfaceMember(m3)); - Assert.Null(test2.FindImplementationForInterfaceMember(m3)); +public class TestHelper +{ + public static void CallM1(I1 x) {x.M1();} +} - var m4 = i1.GetMember("M4"); +public class Test2 : I1 +{ + void I1.M1() + { + System.Console.WriteLine(""Test2.M1""); + } +} +"; - Assert.False(m4.IsAbstract); - Assert.False(m4.IsVirtual); - Assert.False(m4.IsMetadataVirtual()); - Assert.False(m4.IsSealed); - Assert.False(m4.IsStatic); - Assert.Equal(isSource, m4.IsExtern); - Assert.False(m4.IsAsync); - Assert.False(m4.IsOverride); - Assert.Equal(Accessibility.Private, m4.DeclaredAccessibility); - Assert.Null(test1.FindImplementationForInterfaceMember(m4)); - Assert.Null(test2.FindImplementationForInterfaceMember(m4)); + var source2 = +@" +class Test1 : Test2, I1, I2 +{ + static void Main() + { + TestHelper.CallM1(new Test1()); + } - var m5 = i1.GetMember("M5"); + public void M1() + { + System.Console.WriteLine(""Test1.M1""); + } +} - Assert.False(m5.IsAbstract); - Assert.False(m5.IsVirtual); - Assert.False(m5.IsMetadataVirtual()); - Assert.False(m5.IsSealed); - Assert.False(m5.IsStatic); - Assert.Equal(isSource, m5.IsExtern); - Assert.False(m5.IsAsync); - Assert.False(m5.IsOverride); - Assert.Equal(Accessibility.Public, m5.DeclaredAccessibility); - Assert.Null(test1.FindImplementationForInterfaceMember(m5)); - Assert.Null(test2.FindImplementationForInterfaceMember(m5)); - } +public interface I2 +{ + void M1(); +} +"; + ValidateMethodModifiers_10_02(source1, source2, + // (2,22): error CS8504: 'Test1' does not implement interface member 'I1.M1()'. 'Test1.M1()' cannot implicitly implement a non-public member. + // class Test1 : Test2, I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test1", "I1.M1()", "Test1.M1()").WithLocation(2, 22) + ); } [Fact] - public void MethodModifiers_16() + public void MethodModifiers_10_08() { var source1 = @" public interface I1 { - abstract extern void M1(); - extern void M2() {} - static extern void M3(); - private extern void M4(); - extern sealed void M5(); + internal abstract void M1(); } -class Test1 : I1 +public class TestHelper { + public static void CallM1(I1 x) {x.M1();} } -class Test2 : I1 +public class Test2 : I1 { - void I1.M1() {} - void I1.M2() {} - void I1.M3() {} - void I1.M4() {} - void I1.M5() {} + void I1.M1() + { + System.Console.WriteLine(""Test2.M1""); + } } "; - var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, + + var source2 = +@" +class Test1 : Test2, I1 +{ + static void Main() + { + TestHelper.CallM1(new Test1()); + } + + public virtual int M1() + { + System.Console.WriteLine(""Test1.M1""); + return 0; + } +} +"; + var compilation1 = CreateStandardCompilation(source1 + source2, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); - compilation1.VerifyDiagnostics( - // (4,26): error CS0180: 'I1.M1()' cannot be both extern and abstract - // abstract extern void M1(); - Diagnostic(ErrorCode.ERR_AbstractAndExtern, "M1").WithArguments("I1.M1()").WithLocation(4, 26), - // (5,17): error CS0179: 'I1.M2()' cannot be extern and declare a body - // extern void M2() {} - Diagnostic(ErrorCode.ERR_ExternHasBody, "M2").WithArguments("I1.M2()").WithLocation(5, 17), - // (11,15): error CS0535: 'Test1' does not implement interface member 'I1.M1()' - // class Test1 : I1 - Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test1", "I1.M1()").WithLocation(11, 15), - // (19,13): error CS0539: 'Test2.M3()' in explicit interface declaration is not found among members of the interface that can be implemented - // void I1.M3() {} - Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "M3").WithArguments("Test2.M3()").WithLocation(19, 13), - // (20,13): error CS0539: 'Test2.M4()' in explicit interface declaration is not found among members of the interface that can be implemented - // void I1.M4() {} - Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "M4").WithArguments("Test2.M4()").WithLocation(20, 13), - // (21,13): error CS0539: 'Test2.M5()' in explicit interface declaration is not found among members of the interface that can be implemented - // void I1.M5() {} - Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "M5").WithArguments("Test2.M5()").WithLocation(21, 13), - // (6,24): warning CS0626: Method, operator, or accessor 'I1.M3()' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. - // static extern void M3(); - Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "M3").WithArguments("I1.M3()").WithLocation(6, 24), - // (7,25): warning CS0626: Method, operator, or accessor 'I1.M4()' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. - // private extern void M4(); - Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "M4").WithArguments("I1.M4()").WithLocation(7, 25), - // (8,24): warning CS0626: Method, operator, or accessor 'I1.M5()' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. - // extern sealed void M5(); - Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "M5").WithArguments("I1.M5()").WithLocation(8, 24) - ); + CompileAndVerify(compilation1, expectedOutput: "Test2.M1", verify: false, symbolValidator: ValidateMethodModifiersExplicitInTest2_10); - var test1 = compilation1.GetTypeByMetadataName("Test1"); - var test2 = compilation1.GetTypeByMetadataName("Test2"); - var i1 = compilation1.GetTypeByMetadataName("I1"); - var m1 = i1.GetMember("M1"); + ValidateMethodModifiersExplicitInTest2_10(compilation1.SourceModule); - Assert.True(m1.IsAbstract); - Assert.False(m1.IsVirtual); - Assert.True(m1.IsMetadataVirtual()); - Assert.False(m1.IsSealed); - Assert.False(m1.IsStatic); - Assert.True(m1.IsExtern); - Assert.False(m1.IsAsync); - Assert.False(m1.IsOverride); - Assert.Equal(Accessibility.Public, m1.DeclaredAccessibility); - Assert.Null(test1.FindImplementationForInterfaceMember(m1)); - Assert.Same(test2.GetMember("I1.M1"), test2.FindImplementationForInterfaceMember(m1)); + var compilation2 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation2.VerifyDiagnostics(); - var m2 = i1.GetMember("M2"); + ValidateMethodModifiers_10(compilation2.GetTypeByMetadataName("I1").GetMember("M1")); - Assert.False(m2.IsAbstract); - Assert.True(m2.IsVirtual); - Assert.True(m2.IsMetadataVirtual()); - Assert.False(m2.IsSealed); - Assert.False(m2.IsStatic); - Assert.True(m2.IsExtern); - Assert.False(m2.IsAsync); - Assert.False(m2.IsOverride); - Assert.Equal(Accessibility.Public, m2.DeclaredAccessibility); - Assert.Same(m2, test1.FindImplementationForInterfaceMember(m2)); - Assert.Same(test2.GetMember("I1.M2"), test2.FindImplementationForInterfaceMember(m2)); + var compilation3 = CreateStandardCompilation(source2, new[] { compilation2.ToMetadataReference() }, options: TestOptions.DebugExe, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + CompileAndVerify(compilation3, expectedOutput: "Test2.M1", verify: false, symbolValidator: ValidateMethodModifiersExplicitInTest2_10); - var m3 = i1.GetMember("M3"); - Assert.Null(test2.FindImplementationForInterfaceMember(m3)); + ValidateMethodModifiersExplicitInTest2_10(compilation3.SourceModule); - var m4 = i1.GetMember("M4"); - Assert.Null(test2.FindImplementationForInterfaceMember(m4)); + var compilation4 = CreateStandardCompilation(source2, new[] { compilation2.EmitToImageReference() }, options: TestOptions.DebugExe, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation4.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + CompileAndVerify(compilation4, expectedOutput: "Test2.M1", verify: false, symbolValidator: ValidateMethodModifiersExplicitInTest2_10); - var m5 = i1.GetMember("M5"); - Assert.Null(test2.FindImplementationForInterfaceMember(m5)); + ValidateMethodModifiersExplicitInTest2_10(compilation4.SourceModule); } [Fact] - public void MethodModifiers_17() + public void MethodModifiers_10_09() { var source1 = @" public interface I1 { - abstract void M1() {} - abstract private void M2() {} - abstract static void M3() {} - static extern void M4() {} - override sealed void M5() {} + internal abstract void M1(); + + void M2() {M1();} } +"; + var source2 = +@" class Test1 : I1 { -} + static void Main() + { + I1 x = new Test1(); + x.M2(); + } -class Test2 : I1 -{ - void I1.M1() {} - void I1.M2() {} - void I1.M3() {} - void I1.M4() {} - void I1.M5() {} + public virtual int M1() + { + System.Console.WriteLine(""M1""); + return 0; + } } "; - var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, + var compilation1 = CreateStandardCompilation(source1 + source2, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics( - // (4,19): error CS0500: 'I1.M1()' cannot declare a body because it is marked abstract - // abstract void M1() {} - Diagnostic(ErrorCode.ERR_AbstractHasBody, "M1").WithArguments("I1.M1()").WithLocation(4, 19), - // (5,27): error CS0500: 'I1.M2()' cannot declare a body because it is marked abstract - // abstract private void M2() {} - Diagnostic(ErrorCode.ERR_AbstractHasBody, "M2").WithArguments("I1.M2()").WithLocation(5, 27), - // (6,26): error CS0500: 'I1.M3()' cannot declare a body because it is marked abstract - // abstract static void M3() {} - Diagnostic(ErrorCode.ERR_AbstractHasBody, "M3").WithArguments("I1.M3()").WithLocation(6, 26), - // (7,24): error CS0179: 'I1.M4()' cannot be extern and declare a body - // static extern void M4() {} - Diagnostic(ErrorCode.ERR_ExternHasBody, "M4").WithArguments("I1.M4()").WithLocation(7, 24), - // (8,26): error CS0106: The modifier 'override' is not valid for this item - // override sealed void M5() {} - Diagnostic(ErrorCode.ERR_BadMemberFlag, "M5").WithArguments("override").WithLocation(8, 26), - // (5,27): error CS0621: 'I1.M2()': virtual or abstract members cannot be private - // abstract private void M2() {} - Diagnostic(ErrorCode.ERR_VirtualPrivate, "M2").WithArguments("I1.M2()").WithLocation(5, 27), - // (6,26): error CS0112: A static member 'I1.M3()' cannot be marked as override, virtual, or abstract - // abstract static void M3() {} - Diagnostic(ErrorCode.ERR_StaticNotVirtual, "M3").WithArguments("I1.M3()").WithLocation(6, 26), - // (11,15): error CS0535: 'Test1' does not implement interface member 'I1.M2()' - // class Test1 : I1 - Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test1", "I1.M2()").WithLocation(11, 15), - // (11,15): error CS0535: 'Test1' does not implement interface member 'I1.M1()' + // (9,15): error CS0535: 'Test1' does not implement interface member 'I1.M1()' // class Test1 : I1 - Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test1", "I1.M1()").WithLocation(11, 15), - // (19,13): error CS0539: 'Test2.M3()' in explicit interface declaration is not found among members of the interface that can be implemented - // void I1.M3() {} - Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "M3").WithArguments("Test2.M3()").WithLocation(19, 13), - // (20,13): error CS0539: 'Test2.M4()' in explicit interface declaration is not found among members of the interface that can be implemented - // void I1.M4() {} - Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "M4").WithArguments("Test2.M4()").WithLocation(20, 13), - // (21,13): error CS0539: 'Test2.M5()' in explicit interface declaration is not found among members of the interface that can be implemented - // void I1.M5() {} - Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "M5").WithArguments("Test2.M5()").WithLocation(21, 13) + Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test1", "I1.M1()").WithLocation(9, 15) ); - var test1 = compilation1.GetTypeByMetadataName("Test1"); - var test2 = compilation1.GetTypeByMetadataName("Test2"); - var i1 = compilation1.GetTypeByMetadataName("I1"); - var m1 = i1.GetMember("M1"); - - Assert.True(m1.IsAbstract); - Assert.False(m1.IsVirtual); - Assert.True(m1.IsMetadataVirtual()); - Assert.False(m1.IsSealed); - Assert.False(m1.IsStatic); - Assert.False(m1.IsExtern); - Assert.False(m1.IsAsync); - Assert.False(m1.IsOverride); - Assert.Equal(Accessibility.Public, m1.DeclaredAccessibility); - Assert.Null(test1.FindImplementationForInterfaceMember(m1)); - Assert.Same(test2.GetMember("I1.M1"), test2.FindImplementationForInterfaceMember(m1)); + ValidateI1M1NotImplemented(compilation1, "Test1"); - var m2 = i1.GetMember("M2"); - - Assert.True(m2.IsAbstract); - Assert.False(m2.IsVirtual); - Assert.True(m2.IsMetadataVirtual()); - Assert.False(m2.IsSealed); - Assert.False(m2.IsStatic); - Assert.False(m2.IsExtern); - Assert.False(m2.IsAsync); - Assert.False(m2.IsOverride); - Assert.Equal(Accessibility.Private, m2.DeclaredAccessibility); - Assert.Null(test1.FindImplementationForInterfaceMember(m2)); - Assert.Same(test2.GetMember("I1.M2"), test2.FindImplementationForInterfaceMember(m2)); - - var m3 = i1.GetMember("M3"); + var compilation2 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation2.VerifyDiagnostics(); - Assert.True(m3.IsAbstract); - Assert.False(m3.IsVirtual); - Assert.True(m3.IsMetadataVirtual()); - Assert.False(m3.IsSealed); - Assert.True(m3.IsStatic); - Assert.False(m3.IsExtern); - Assert.False(m3.IsAsync); - Assert.False(m3.IsOverride); - Assert.Equal(Accessibility.Public, m3.DeclaredAccessibility); - Assert.Null(test1.FindImplementationForInterfaceMember(m3)); - Assert.Null(test2.FindImplementationForInterfaceMember(m3)); + ValidateMethodModifiers_10(compilation2.GetTypeByMetadataName("I1").GetMember("M1")); - var m4 = i1.GetMember("M4"); + var compilation3 = CreateStandardCompilation(source2, new[] { compilation2.ToMetadataReference() }, options: TestOptions.DebugExe, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation3.VerifyDiagnostics( + // (2,15): error CS0535: 'Test1' does not implement interface member 'I1.M1()' + // class Test1 : I1 + Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test1", "I1.M1()").WithLocation(2, 15) + ); - Assert.False(m4.IsAbstract); - Assert.False(m4.IsVirtual); - Assert.False(m4.IsMetadataVirtual()); - Assert.False(m4.IsSealed); - Assert.True(m4.IsStatic); - Assert.True(m4.IsExtern); - Assert.False(m4.IsAsync); - Assert.False(m4.IsOverride); - Assert.Equal(Accessibility.Public, m4.DeclaredAccessibility); - Assert.Null(test1.FindImplementationForInterfaceMember(m4)); - Assert.Null(test2.FindImplementationForInterfaceMember(m4)); + ValidateI1M1NotImplemented(compilation3, "Test1"); - var m5 = i1.GetMember("M5"); + var compilation4 = CreateStandardCompilation(source2, new[] { compilation2.EmitToImageReference() }, options: TestOptions.DebugExe, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation4.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation4.VerifyDiagnostics( + // (2,15): error CS0535: 'Test1' does not implement interface member 'I1.M1()' + // class Test1 : I1 + Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test1", "I1.M1()").WithLocation(2, 15) + ); - Assert.False(m5.IsAbstract); - Assert.False(m5.IsVirtual); - Assert.False(m5.IsMetadataVirtual()); - Assert.False(m5.IsSealed); - Assert.False(m5.IsStatic); - Assert.False(m5.IsExtern); - Assert.False(m5.IsAsync); - Assert.False(m5.IsOverride); - Assert.Equal(Accessibility.Public, m5.DeclaredAccessibility); - Assert.Null(test1.FindImplementationForInterfaceMember(m5)); - Assert.Null(test2.FindImplementationForInterfaceMember(m5)); + ValidateI1M1NotImplemented(compilation4, "Test1"); } [Fact] - public void MethodModifiers_18() + public void MethodModifiers_10_10() { var source1 = @" -using System.Threading; -using System.Threading.Tasks; - public interface I1 { - public static async Task M1() - { - await Task.Factory.StartNew(() => System.Console.WriteLine(""M1"")); - } + internal abstract void M1(); } +"; -class Test1 : I1 + var source2 = +@" +class Test2 : I1 { - static void Main() + public void M1() { - I1.M1().Wait(); + System.Console.WriteLine(""M1""); } } + +class Test1 : Test2, I1 +{ +} "; - var compilation1 = CreateCompilationWithMscorlib45(source1, options: TestOptions.DebugExe, - parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + var compilation1 = CreateStandardCompilation(source1 + source2, options: TestOptions.DebugDll, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); - CompileAndVerify(compilation1, expectedOutput:"M1", symbolValidator: Validate); + compilation1.VerifyDiagnostics( + // (7,15): error CS8504: 'Test2' does not implement interface member 'I1.M1()'. 'Test2.M1()' cannot implicitly implement a non-public member. + // class Test2 : I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test2", "I1.M1()", "Test2.M1()").WithLocation(7, 15) + ); - Validate(compilation1.SourceModule); + ValidateMethodModifiersImplicitInTest2_10(compilation1.SourceModule); - void Validate(ModuleSymbol m) - { - var test1 = m.GlobalNamespace.GetTypeMember("Test1"); - var i1 = m.GlobalNamespace.GetTypeMember("I1"); - var m1 = i1.GetMember("M1"); + var compilation2 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation2.VerifyDiagnostics(); - Assert.False(m1.IsAbstract); - Assert.False(m1.IsVirtual); - Assert.False(m1.IsMetadataVirtual()); - Assert.False(m1.IsSealed); - Assert.True(m1.IsStatic); - Assert.False(m1.IsExtern); - Assert.Equal(!(m is PEModuleSymbol), m1.IsAsync); - Assert.False(m1.IsOverride); - Assert.Equal(Accessibility.Public, m1.DeclaredAccessibility); - Assert.Null(test1.FindImplementationForInterfaceMember(m1)); - } + ValidateMethodModifiers_10(compilation2.GetTypeByMetadataName("I1").GetMember("M1")); + + var compilation3 = CreateStandardCompilation(source2, new[] { compilation2.ToMetadataReference() }, options: TestOptions.DebugDll, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation3.VerifyDiagnostics( + // (2,15): error CS8504: 'Test2' does not implement interface member 'I1.M1()'. 'Test2.M1()' cannot implicitly implement a non-public member. + // class Test2 : I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test2", "I1.M1()", "Test2.M1()") + ); + + ValidateMethodModifiersImplicitInTest2_10(compilation3.SourceModule); + + var compilation4 = CreateStandardCompilation(source2, new[] { compilation2.EmitToImageReference() }, options: TestOptions.DebugDll, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation4.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation4.VerifyDiagnostics( + // (2,15): error CS8504: 'Test2' does not implement interface member 'I1.M1()'. 'Test2.M1()' cannot implicitly implement a non-public member. + // class Test2 : I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test2", "I1.M1()", "Test2.M1()") + ); + + ValidateMethodModifiersImplicitInTest2_10(compilation4.SourceModule); } [Fact] - public void MethodModifiers_19() + public void MethodModifiers_10_11() { var source1 = @" - -public interface I2 {} - public interface I1 { - public void I2.M01(); - protected void I2.M02(); - protected internal void I2.M03(); - internal void I2.M04(); - private void I2.M05(); - static void I2.M06(); - virtual void I2.M07(); - sealed void I2.M08(); - override void I2.M09(); - abstract void I2.M10(); - extern void I2.M11(); - async void I2.M12(); + internal abstract void M1(); } -"; - var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, - parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); - Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); - var expected = new[] - { - // (7,20): error CS0106: The modifier 'public' is not valid for this item - // public void I2.M01(); - Diagnostic(ErrorCode.ERR_BadMemberFlag, "M01").WithArguments("public").WithLocation(7, 20), - // (8,23): error CS0106: The modifier 'protected' is not valid for this item - // protected void I2.M02(); - Diagnostic(ErrorCode.ERR_BadMemberFlag, "M02").WithArguments("protected").WithLocation(8, 23), - // (9,32): error CS0106: The modifier 'protected internal' is not valid for this item - // protected internal void I2.M03(); - Diagnostic(ErrorCode.ERR_BadMemberFlag, "M03").WithArguments("protected internal").WithLocation(9, 32), - // (10,22): error CS0106: The modifier 'internal' is not valid for this item - // internal void I2.M04(); - Diagnostic(ErrorCode.ERR_BadMemberFlag, "M04").WithArguments("internal").WithLocation(10, 22), - // (11,21): error CS0106: The modifier 'private' is not valid for this item - // private void I2.M05(); - Diagnostic(ErrorCode.ERR_BadMemberFlag, "M05").WithArguments("private").WithLocation(11, 21), - // (12,20): error CS0106: The modifier 'static' is not valid for this item - // static void I2.M06(); - Diagnostic(ErrorCode.ERR_BadMemberFlag, "M06").WithArguments("static").WithLocation(12, 20), - // (13,21): error CS0106: The modifier 'virtual' is not valid for this item - // virtual void I2.M07(); - Diagnostic(ErrorCode.ERR_BadMemberFlag, "M07").WithArguments("virtual").WithLocation(13, 21), - // (14,20): error CS0106: The modifier 'sealed' is not valid for this item - // sealed void I2.M08(); - Diagnostic(ErrorCode.ERR_BadMemberFlag, "M08").WithArguments("sealed").WithLocation(14, 20), - // (15,22): error CS0106: The modifier 'override' is not valid for this item - // override void I2.M09(); - Diagnostic(ErrorCode.ERR_BadMemberFlag, "M09").WithArguments("override").WithLocation(15, 22), - // (16,22): error CS0106: The modifier 'abstract' is not valid for this item - // abstract void I2.M10(); - Diagnostic(ErrorCode.ERR_BadMemberFlag, "M10").WithArguments("abstract").WithLocation(16, 22), - // (17,20): error CS0106: The modifier 'extern' is not valid for this item - // extern void I2.M11(); - Diagnostic(ErrorCode.ERR_BadMemberFlag, "M11").WithArguments("extern").WithLocation(17, 20), - // (18,19): error CS0106: The modifier 'async' is not valid for this item - // async void I2.M12(); - Diagnostic(ErrorCode.ERR_BadMemberFlag, "M12").WithArguments("async").WithLocation(18, 19), - // (7,20): error CS0541: 'I1.M01()': explicit interface declaration can only be declared in a class or struct - // public void I2.M01(); - Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "M01").WithArguments("I1.M01()").WithLocation(7, 20), - // (8,23): error CS0541: 'I1.M02()': explicit interface declaration can only be declared in a class or struct - // protected void I2.M02(); - Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "M02").WithArguments("I1.M02()").WithLocation(8, 23), - // (9,32): error CS0541: 'I1.M03()': explicit interface declaration can only be declared in a class or struct - // protected internal void I2.M03(); - Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "M03").WithArguments("I1.M03()").WithLocation(9, 32), - // (10,22): error CS0541: 'I1.M04()': explicit interface declaration can only be declared in a class or struct - // internal void I2.M04(); - Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "M04").WithArguments("I1.M04()").WithLocation(10, 22), - // (11,21): error CS0541: 'I1.M05()': explicit interface declaration can only be declared in a class or struct - // private void I2.M05(); - Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "M05").WithArguments("I1.M05()").WithLocation(11, 21), - // (12,20): error CS0541: 'I1.M06()': explicit interface declaration can only be declared in a class or struct - // static void I2.M06(); - Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "M06").WithArguments("I1.M06()").WithLocation(12, 20), - // (13,21): error CS0541: 'I1.M07()': explicit interface declaration can only be declared in a class or struct - // virtual void I2.M07(); - Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "M07").WithArguments("I1.M07()").WithLocation(13, 21), - // (14,20): error CS0541: 'I1.M08()': explicit interface declaration can only be declared in a class or struct - // sealed void I2.M08(); - Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "M08").WithArguments("I1.M08()").WithLocation(14, 20), - // (15,22): error CS0541: 'I1.M09()': explicit interface declaration can only be declared in a class or struct - // override void I2.M09(); - Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "M09").WithArguments("I1.M09()").WithLocation(15, 22), - // (16,22): error CS0541: 'I1.M10()': explicit interface declaration can only be declared in a class or struct - // abstract void I2.M10(); - Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "M10").WithArguments("I1.M10()").WithLocation(16, 22), - // (17,20): error CS0541: 'I1.M11()': explicit interface declaration can only be declared in a class or struct - // extern void I2.M11(); - Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "M11").WithArguments("I1.M11()").WithLocation(17, 20), - // (18,19): error CS0541: 'I1.M12()': explicit interface declaration can only be declared in a class or struct - // async void I2.M12(); - Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "M12").WithArguments("I1.M12()").WithLocation(18, 19) - }; - compilation1.VerifyDiagnostics(expected); - - ValidateSymbolsMethodModifiers_19(compilation1); +public class Test2 : I1 +{ + public void M1() + { + System.Console.WriteLine(""M1""); + } +} +"; + var source2 = +@" +class Test1 : Test2, I1 +{ +} +"; var compilation2 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, - parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp7)); + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest), + assemblyName: "MethodModifiers_10_11"); Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); - compilation2.VerifyDiagnostics(expected); + compilation2.VerifyDiagnostics( + // (7,22): error CS8504: 'Test2' does not implement interface member 'I1.M1()'. 'Test2.M1()' cannot implicitly implement a non-public member. + // public class Test2 : I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test2", "I1.M1()", "Test2.M1()").WithLocation(7, 22) + ); - ValidateSymbolsMethodModifiers_19(compilation2); + var compilation3 = CreateStandardCompilation(source2, new[] { compilation2.ToMetadataReference() }, options: TestOptions.DebugDll, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation3.VerifyDiagnostics(); + + ValidateMethodModifiersImplicitInTest2_10(compilation3.SourceModule); + + var compilation3Ref = compilation3.EmitToImageReference(); + var compilation4 = CreateStandardCompilation("", new[] { compilation2.ToMetadataReference(), compilation3Ref }, options: TestOptions.DebugDll, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + + ValidateMethodModifiersImplicitInTest2_10(compilation4.GetReferencedAssemblySymbol(compilation3Ref).Modules[0]); } - private static void ValidateSymbolsMethodModifiers_19(CSharpCompilation compilation1) + [Fact] + public void MethodModifiers_11() { - var i1 = compilation1.GetTypeByMetadataName("I1"); + var source1 = +@" +public interface I1 +{ + internal abstract void M1(); +} - foreach (var methodName in new[] { "I2.M01", "I2.M02", "I2.M03", "I2.M04", "I2.M05", "I2.M06", "I2.M07", "I2.M08", "I2.M09", "I2.M10", "I2.M11", "I2.M12" }) - { - var m01 = i1.GetMember(methodName); +class Test1 : I1 +{ +} +"; + var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation1.VerifyDiagnostics( + // (7,15): error CS0535: 'Test1' does not implement interface member 'I1.M1()' + // class Test1 : I1 + Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test1", "I1.M1()").WithLocation(7, 15) + ); - Assert.True(m01.IsAbstract); - Assert.False(m01.IsVirtual); - Assert.True(m01.IsMetadataVirtual()); - Assert.False(m01.IsSealed); - Assert.False(m01.IsStatic); - Assert.False(m01.IsExtern); - Assert.False(m01.IsAsync); - Assert.False(m01.IsOverride); - Assert.Equal(Accessibility.Public, m01.DeclaredAccessibility); - } + var test1 = compilation1.GetTypeByMetadataName("Test1"); + var i1 = compilation1.GetTypeByMetadataName("I1"); + var m1 = i1.GetMember("M1"); + + Assert.True(m1.IsAbstract); + Assert.False(m1.IsVirtual); + Assert.True(m1.IsMetadataVirtual()); + Assert.False(m1.IsSealed); + Assert.False(m1.IsStatic); + Assert.False(m1.IsExtern); + Assert.False(m1.IsAsync); + Assert.False(m1.IsOverride); + Assert.Equal(Accessibility.Internal, m1.DeclaredAccessibility); + Assert.Null(test1.FindImplementationForInterfaceMember(m1)); } [Fact] - public void MethodModifiers_20() + public void MethodModifiers_12() { var source1 = @" public interface I1 { - internal void M1() + public sealed void M1() { System.Console.WriteLine(""M1""); } - - void M2() {M1();} } -"; - var source2 = -@" class Test1 : I1 { static void Main() { I1 x = new Test1(); - x.M2(); + x.M1(); + } + + public void M1() + { + System.Console.WriteLine(""Test1.M1""); } } "; - var compilation1 = CreateStandardCompilation(source1 + source2, options: TestOptions.DebugExe, + var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); - CompileAndVerify(compilation1/*, expectedOutput:"M1"*/, verify: false, symbolValidator: Validate1); - - Validate1(compilation1.SourceModule); - void Validate1(ModuleSymbol m) + void Validate(ModuleSymbol m) { var test1 = m.GlobalNamespace.GetTypeMember("Test1"); - var i1 = test1.Interfaces.Single(); + var i1 = m.GlobalNamespace.GetTypeMember("I1"); var m1 = i1.GetMember("M1"); - ValidateMethod(m1); - Assert.Same(m1, test1.FindImplementationForInterfaceMember(m1)); - } - - void ValidateMethod(MethodSymbol m1) - { Assert.False(m1.IsAbstract); - Assert.True(m1.IsVirtual); - Assert.True(m1.IsMetadataVirtual()); + Assert.False(m1.IsVirtual); + Assert.False(m1.IsMetadataVirtual()); Assert.False(m1.IsSealed); Assert.False(m1.IsStatic); Assert.False(m1.IsExtern); Assert.False(m1.IsAsync); Assert.False(m1.IsOverride); - Assert.Equal(Accessibility.Internal, m1.DeclaredAccessibility); - } - - var compilation2 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, - parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); - Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); - compilation2.VerifyDiagnostics(); - - { - var i1 = compilation2.GetTypeByMetadataName("I1"); - var m1 = i1.GetMember("M1"); - ValidateMethod(m1); + Assert.Equal(Accessibility.Public, m1.DeclaredAccessibility); + Assert.Null(test1.FindImplementationForInterfaceMember(m1)); } - var compilation3 = CreateStandardCompilation(source2, new[] { compilation2.ToMetadataReference() }, options: TestOptions.DebugExe, - parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); - Assert.True(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); - CompileAndVerify(compilation3/*, expectedOutput:"M1"*/, verify: false, symbolValidator: Validate1); - - Validate1(compilation3.SourceModule); - - var compilation4 = CreateStandardCompilation(source2, new[] { compilation2.EmitToImageReference() }, options: TestOptions.DebugExe, - parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); - Assert.True(compilation4.Assembly.RuntimeSupportsDefaultInterfaceImplementation); - CompileAndVerify(compilation4/*, expectedOutput:"M1"*/, verify: false, symbolValidator: Validate1); - - Validate1(compilation4.SourceModule); + CompileAndVerify(compilation1/*, expectedOutput:"M1"*/, verify: false, symbolValidator: Validate); + Validate(compilation1.SourceModule); } [Fact] - public void MethodModifiers_21() + public void MethodModifiers_13() { var source1 = @" public interface I1 { - private static void M1() {} + public sealed void M1() + { + System.Console.WriteLine(""M1""); + } - internal static void M2() {} + abstract sealed void M2(); - public static void M3() {} + virtual sealed void M3() + { + } - static void M4() {} + public sealed void M4(); } -class Test1 +class Test1 : I1 { - static void Main() - { - I1.M1(); - I1.M2(); - I1.M3(); - I1.M4(); - } + void I1.M1() {} + void I1.M2() {} + void I1.M3() {} + void I1.M4() {} } + +class Test2 : I1 +{} "; - var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All), + var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics( - // (17,12): error CS0122: 'I1.M1()' is inaccessible due to its protection level - // I1.M1(); - Diagnostic(ErrorCode.ERR_BadAccess, "M1").WithArguments("I1.M1()").WithLocation(17, 12) + // (15,24): error CS0501: 'I1.M4()' must declare a body because it is not marked abstract, extern, or partial + // public sealed void M4(); + Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "M4").WithArguments("I1.M4()").WithLocation(15, 24), + // (9,26): error CS0238: 'I1.M2()' cannot be sealed because it is not an override + // abstract sealed void M2(); + Diagnostic(ErrorCode.ERR_SealedNonOverride, "M2").WithArguments("I1.M2()").WithLocation(9, 26), + // (11,25): error CS0238: 'I1.M3()' cannot be sealed because it is not an override + // virtual sealed void M3() + Diagnostic(ErrorCode.ERR_SealedNonOverride, "M3").WithArguments("I1.M3()").WithLocation(11, 25), + // (26,15): error CS0535: 'Test2' does not implement interface member 'I1.M2()' + // class Test2 : I1 + Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test2", "I1.M2()").WithLocation(26, 15), + // (23,13): error CS0539: 'Test1.M4()' in explicit interface declaration is not found among members of the interface that can be implemented + // void I1.M4() {} + Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "M4").WithArguments("Test1.M4()").WithLocation(23, 13), + // (20,13): error CS0539: 'Test1.M1()' in explicit interface declaration is not found among members of the interface that can be implemented + // void I1.M1() {} + Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "M1").WithArguments("Test1.M1()").WithLocation(20, 13) ); - var source2 = -@" -class Test2 -{ - static void Main() - { - I1.M1(); - I1.M2(); - I1.M3(); - I1.M4(); - } -} -"; - var compilation2 = CreateStandardCompilation(source2, new[] { compilation1.ToMetadataReference() }, - options: TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All), - parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); - Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); - compilation2.VerifyDiagnostics( - // (6,12): error CS0122: 'I1.M1()' is inaccessible due to its protection level - // I1.M1(); - Diagnostic(ErrorCode.ERR_BadAccess, "M1").WithArguments("I1.M1()").WithLocation(6, 12), - // (7,12): error CS0122: 'I1.M2()' is inaccessible due to its protection level - // I1.M2(); - Diagnostic(ErrorCode.ERR_BadAccess, "M2").WithArguments("I1.M2()").WithLocation(7, 12) - ); + var test1 = compilation1.GetTypeByMetadataName("Test1"); + var test2 = compilation1.GetTypeByMetadataName("Test2"); + var i1 = compilation1.GetTypeByMetadataName("I1"); + var m1 = i1.GetMember("M1"); + + Assert.False(m1.IsAbstract); + Assert.False(m1.IsVirtual); + Assert.False(m1.IsMetadataVirtual()); + Assert.False(m1.IsSealed); + Assert.False(m1.IsStatic); + Assert.False(m1.IsExtern); + Assert.False(m1.IsAsync); + Assert.False(m1.IsOverride); + Assert.Equal(Accessibility.Public, m1.DeclaredAccessibility); + Assert.Null(test1.FindImplementationForInterfaceMember(m1)); + Assert.Null(test2.FindImplementationForInterfaceMember(m1)); + + var m2 = i1.GetMember("M2"); + + Assert.True(m2.IsAbstract); + Assert.False(m2.IsVirtual); + Assert.True(m2.IsMetadataVirtual()); + Assert.True(m2.IsSealed); + Assert.False(m2.IsStatic); + Assert.False(m2.IsExtern); + Assert.False(m2.IsAsync); + Assert.False(m2.IsOverride); + Assert.Equal(Accessibility.Public, m2.DeclaredAccessibility); + Assert.Same(test1.GetMember("I1.M2"), test1.FindImplementationForInterfaceMember(m2)); + Assert.Null(test2.FindImplementationForInterfaceMember(m2)); + + var m3 = i1.GetMember("M3"); + + Assert.False(m3.IsAbstract); + Assert.True(m3.IsVirtual); + Assert.True(m3.IsMetadataVirtual()); + Assert.True(m3.IsSealed); + Assert.False(m3.IsStatic); + Assert.False(m3.IsExtern); + Assert.False(m3.IsAsync); + Assert.False(m3.IsOverride); + Assert.Equal(Accessibility.Public, m3.DeclaredAccessibility); + Assert.Same(test1.GetMember("I1.M3"), test1.FindImplementationForInterfaceMember(m3)); + Assert.Same(m3, test2.FindImplementationForInterfaceMember(m3)); + + var m4 = i1.GetMember("M4"); + + Assert.False(m4.IsAbstract); + Assert.False(m4.IsVirtual); + Assert.False(m4.IsMetadataVirtual()); + Assert.False(m4.IsSealed); + Assert.False(m4.IsStatic); + Assert.False(m4.IsExtern); + Assert.False(m4.IsAsync); + Assert.False(m4.IsOverride); + Assert.Equal(Accessibility.Public, m4.DeclaredAccessibility); + Assert.Null(test1.FindImplementationForInterfaceMember(m4)); + Assert.Null(test2.FindImplementationForInterfaceMember(m4)); } [Fact] - public void ImplicitThisIsAllowed_03() + public void MethodModifiers_14() { var source1 = @" public interface I1 { - public int F1; - - void M1() - { - System.Console.WriteLine(""I1.M1""); - } - - int P1 - { - get - { - System.Console.WriteLine(""I1.get_P1""); - return 0; - } - set => System.Console.WriteLine(""I1.set_P1""); - } + abstract virtual void M2(); - event System.Action E1 + virtual abstract void M3() { - add => System.Console.WriteLine(""I1.add_E1""); - remove => System.Console.WriteLine(""I1.remove_E1""); } +} - public interface I2 : I1 - { - void M2() - { - M1(); - P1 = P1; - E1 += null; - E1 -= null; - F1 = 0; - } - } +class Test1 : I1 +{ + void I1.M2() {} + void I1.M3() {} } + +class Test2 : I1 +{} "; var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); - compilation1.VerifyDiagnostics( - // (4,16): error CS0525: Interfaces cannot contain fields - // public int F1; - Diagnostic(ErrorCode.ERR_InterfacesCantContainFields, "F1").WithLocation(4, 16) + // (6,27): error CS0500: 'I1.M3()' cannot declare a body because it is marked abstract + // virtual abstract void M3() + Diagnostic(ErrorCode.ERR_AbstractHasBody, "M3").WithArguments("I1.M3()").WithLocation(6, 27), + // (6,27): error CS0503: The abstract method 'I1.M3()' cannot be marked virtual + // virtual abstract void M3() + Diagnostic(ErrorCode.ERR_AbstractNotVirtual, "M3").WithArguments("I1.M3()").WithLocation(6, 27), + // (4,27): error CS0503: The abstract method 'I1.M2()' cannot be marked virtual + // abstract virtual void M2(); + Diagnostic(ErrorCode.ERR_AbstractNotVirtual, "M2").WithArguments("I1.M2()").WithLocation(4, 27), + // (17,15): error CS0535: 'Test2' does not implement interface member 'I1.M3()' + // class Test2 : I1 + Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test2", "I1.M3()").WithLocation(17, 15), + // (17,15): error CS0535: 'Test2' does not implement interface member 'I1.M2()' + // class Test2 : I1 + Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test2", "I1.M2()").WithLocation(17, 15) ); + + var test1 = compilation1.GetTypeByMetadataName("Test1"); + var test2 = compilation1.GetTypeByMetadataName("Test2"); + var i1 = compilation1.GetTypeByMetadataName("I1"); + + foreach (var methodName in new[] { "M2", "M3" }) + { + var m2 = i1.GetMember(methodName); + + Assert.True(m2.IsAbstract); + Assert.True(m2.IsVirtual); + Assert.True(m2.IsMetadataVirtual()); + Assert.False(m2.IsSealed); + Assert.False(m2.IsStatic); + Assert.False(m2.IsExtern); + Assert.False(m2.IsAsync); + Assert.False(m2.IsOverride); + Assert.Equal(Accessibility.Public, m2.DeclaredAccessibility); + Assert.Same(test1.GetMember("I1." + methodName), test1.FindImplementationForInterfaceMember(m2)); + Assert.Null(test2.FindImplementationForInterfaceMember(m2)); + } } [Fact] - public void ImplicitThisIsAllowed_04() + public void MethodModifiers_15() { var source1 = @" public interface I1 { - public int F1; + extern void M1(); + virtual extern void M2(); + static extern void M3(); + private extern void M4(); + extern sealed void M5(); +} - void M1() - { - System.Console.WriteLine(""I1.M1""); - } - - int P1 - { - get - { - System.Console.WriteLine(""I1.get_P1""); - return 0; - } - set => System.Console.WriteLine(""I1.set_P1""); - } - - event System.Action E1 - { - add => System.Console.WriteLine(""I1.add_E1""); - remove => System.Console.WriteLine(""I1.remove_E1""); - } +class Test1 : I1 +{ +} - public interface I2 - { - void M2() - { - M1(); - P1 = P1; - E1 += null; - E1 -= null; - F1 = 0; - } - } +class Test2 : I1 +{ + void I1.M1() {} + void I1.M2() {} } "; - var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, + var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All), parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + CompileAndVerify(compilation1, verify: false, symbolValidator: Validate); - compilation1.VerifyDiagnostics( - // (4,16): error CS0525: Interfaces cannot contain fields - // public int F1; - Diagnostic(ErrorCode.ERR_InterfacesCantContainFields, "F1").WithLocation(4, 16), - // (31,13): error CS0120: An object reference is required for the non-static field, method, or property 'I1.M1()' - // M1(); - Diagnostic(ErrorCode.ERR_ObjectRequired, "M1").WithArguments("I1.M1()").WithLocation(31, 13), - // (32,13): error CS0120: An object reference is required for the non-static field, method, or property 'I1.P1' - // P1 = P1; - Diagnostic(ErrorCode.ERR_ObjectRequired, "P1").WithArguments("I1.P1").WithLocation(32, 13), - // (32,18): error CS0120: An object reference is required for the non-static field, method, or property 'I1.P1' - // P1 = P1; - Diagnostic(ErrorCode.ERR_ObjectRequired, "P1").WithArguments("I1.P1").WithLocation(32, 18), - // (33,13): error CS0120: An object reference is required for the non-static field, method, or property 'I1.E1' - // E1 += null; - Diagnostic(ErrorCode.ERR_ObjectRequired, "E1").WithArguments("I1.E1").WithLocation(33, 13), - // (34,13): error CS0120: An object reference is required for the non-static field, method, or property 'I1.E1' - // E1 -= null; - Diagnostic(ErrorCode.ERR_ObjectRequired, "E1").WithArguments("I1.E1").WithLocation(34, 13), - // (35,13): error CS0120: An object reference is required for the non-static field, method, or property 'I1.F1' - // F1 = 0; - Diagnostic(ErrorCode.ERR_ObjectRequired, "F1").WithArguments("I1.F1").WithLocation(35, 13) - ); - } + Validate(compilation1.SourceModule); - [Fact] - public void ImplicitThisIsAllowed_05() - { - var source1 = -@" -public class C1 -{ - public int F1; + void Validate(ModuleSymbol m) + { + var test1 = m.GlobalNamespace.GetTypeMember("Test1"); + var test2 = m.GlobalNamespace.GetTypeMember("Test2"); + var i1 = m.GlobalNamespace.GetTypeMember("I1"); + var m1 = i1.GetMember("M1"); + bool isSource = !(m is PEModuleSymbol); - void M1() - { - System.Console.WriteLine(""I1.M1""); - } + Assert.False(m1.IsAbstract); + Assert.True(m1.IsVirtual); + Assert.True(m1.IsMetadataVirtual()); + Assert.False(m1.IsSealed); + Assert.False(m1.IsStatic); + Assert.Equal(isSource, m1.IsExtern); + Assert.False(m1.IsAsync); + Assert.False(m1.IsOverride); + Assert.Equal(Accessibility.Public, m1.DeclaredAccessibility); + Assert.Same(m1, test1.FindImplementationForInterfaceMember(m1)); + Assert.Same(test2.GetMember("I1.M1"), test2.FindImplementationForInterfaceMember(m1)); - int P1 - { - get - { - System.Console.WriteLine(""I1.get_P1""); - return 0; - } - set => System.Console.WriteLine(""I1.set_P1""); - } + var m2 = i1.GetMember("M2"); - event System.Action E1 - { - add => System.Console.WriteLine(""I1.add_E1""); - remove => System.Console.WriteLine(""I1.remove_E1""); - } + Assert.False(m2.IsAbstract); + Assert.True(m2.IsVirtual); + Assert.True(m2.IsMetadataVirtual()); + Assert.False(m2.IsSealed); + Assert.False(m2.IsStatic); + Assert.Equal(isSource, m2.IsExtern); + Assert.False(m2.IsAsync); + Assert.False(m2.IsOverride); + Assert.Equal(Accessibility.Public, m2.DeclaredAccessibility); + Assert.Same(m2, test1.FindImplementationForInterfaceMember(m2)); + Assert.Same(test2.GetMember("I1.M2"), test2.FindImplementationForInterfaceMember(m2)); - public interface I2 - { - void M2() - { - M1(); - P1 = P1; - E1 += null; - E1 -= null; - F1 = 0; - } - } -} -"; - var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, - parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); - Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + var m3 = i1.GetMember("M3"); - compilation1.VerifyDiagnostics( - // (31,13): error CS0120: An object reference is required for the non-static field, method, or property 'C1.M1()' - // M1(); - Diagnostic(ErrorCode.ERR_ObjectRequired, "M1").WithArguments("C1.M1()").WithLocation(31, 13), - // (32,13): error CS0120: An object reference is required for the non-static field, method, or property 'C1.P1' - // P1 = P1; - Diagnostic(ErrorCode.ERR_ObjectRequired, "P1").WithArguments("C1.P1").WithLocation(32, 13), - // (32,18): error CS0120: An object reference is required for the non-static field, method, or property 'C1.P1' - // P1 = P1; - Diagnostic(ErrorCode.ERR_ObjectRequired, "P1").WithArguments("C1.P1").WithLocation(32, 18), - // (33,13): error CS0120: An object reference is required for the non-static field, method, or property 'C1.E1' - // E1 += null; - Diagnostic(ErrorCode.ERR_ObjectRequired, "E1").WithArguments("C1.E1").WithLocation(33, 13), - // (34,13): error CS0120: An object reference is required for the non-static field, method, or property 'C1.E1' - // E1 -= null; - Diagnostic(ErrorCode.ERR_ObjectRequired, "E1").WithArguments("C1.E1").WithLocation(34, 13), - // (35,13): error CS0120: An object reference is required for the non-static field, method, or property 'C1.F1' - // F1 = 0; - Diagnostic(ErrorCode.ERR_ObjectRequired, "F1").WithArguments("C1.F1").WithLocation(35, 13) - ); + Assert.False(m3.IsAbstract); + Assert.False(m3.IsVirtual); + Assert.False(m3.IsMetadataVirtual()); + Assert.False(m3.IsSealed); + Assert.True(m3.IsStatic); + Assert.Equal(isSource, m3.IsExtern); + Assert.False(m3.IsAsync); + Assert.False(m3.IsOverride); + Assert.Equal(Accessibility.Public, m3.DeclaredAccessibility); + Assert.Null(test1.FindImplementationForInterfaceMember(m3)); + Assert.Null(test2.FindImplementationForInterfaceMember(m3)); + + var m4 = i1.GetMember("M4"); + + Assert.False(m4.IsAbstract); + Assert.False(m4.IsVirtual); + Assert.False(m4.IsMetadataVirtual()); + Assert.False(m4.IsSealed); + Assert.False(m4.IsStatic); + Assert.Equal(isSource, m4.IsExtern); + Assert.False(m4.IsAsync); + Assert.False(m4.IsOverride); + Assert.Equal(Accessibility.Private, m4.DeclaredAccessibility); + Assert.Null(test1.FindImplementationForInterfaceMember(m4)); + Assert.Null(test2.FindImplementationForInterfaceMember(m4)); + + var m5 = i1.GetMember("M5"); + + Assert.False(m5.IsAbstract); + Assert.False(m5.IsVirtual); + Assert.False(m5.IsMetadataVirtual()); + Assert.False(m5.IsSealed); + Assert.False(m5.IsStatic); + Assert.Equal(isSource, m5.IsExtern); + Assert.False(m5.IsAsync); + Assert.False(m5.IsOverride); + Assert.Equal(Accessibility.Public, m5.DeclaredAccessibility); + Assert.Null(test1.FindImplementationForInterfaceMember(m5)); + Assert.Null(test2.FindImplementationForInterfaceMember(m5)); + } } [Fact] - public void PropertyModifiers_01() + public void MethodModifiers_16() { var source1 = @" public interface I1 { - public int P01 {get; set;} - protected int P02 {get;} - protected internal int P03 {set;} - internal int P04 {get;} - private int P05 {set;} - static int P06 {get;} - virtual int P07 {set;} - sealed int P08 {get;} - override int P09 {set;} - abstract int P10 {get;} - extern int P11 {get; set;} + abstract extern void M1(); + extern void M2() {} + static extern void M3(); + private extern void M4(); + extern sealed void M5(); +} - int P12 { public get; set;} - int P13 { get; protected set;} - int P14 { protected internal get; set;} - int P15 { get; internal set;} - int P16 { private get; set;} - int P17 { private get;} +class Test1 : I1 +{ +} + +class Test2 : I1 +{ + void I1.M1() {} + void I1.M2() {} + void I1.M3() {} + void I1.M4() {} + void I1.M5() {} } "; var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics( - // (5,19): error CS0106: The modifier 'protected' is not valid for this item - // protected int P02 {get;} - Diagnostic(ErrorCode.ERR_BadMemberFlag, "P02").WithArguments("protected").WithLocation(5, 19), - // (6,28): error CS0106: The modifier 'protected internal' is not valid for this item - // protected internal int P03 {set;} - Diagnostic(ErrorCode.ERR_BadMemberFlag, "P03").WithArguments("protected internal").WithLocation(6, 28), - // (8,22): error CS0501: 'I1.P05.set' must declare a body because it is not marked abstract, extern, or partial - // private int P05 {set;} - Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "set").WithArguments("I1.P05.set").WithLocation(8, 22), - // (9,21): error CS0501: 'I1.P06.get' must declare a body because it is not marked abstract, extern, or partial - // static int P06 {get;} - Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "get").WithArguments("I1.P06.get").WithLocation(9, 21), - // (10,22): error CS0501: 'I1.P07.set' must declare a body because it is not marked abstract, extern, or partial - // virtual int P07 {set;} - Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "set").WithArguments("I1.P07.set").WithLocation(10, 22), - // (11,21): error CS0501: 'I1.P08.get' must declare a body because it is not marked abstract, extern, or partial - // sealed int P08 {get;} - Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "get").WithArguments("I1.P08.get").WithLocation(11, 21), - // (12,18): error CS0106: The modifier 'override' is not valid for this item - // override int P09 {set;} - Diagnostic(ErrorCode.ERR_BadMemberFlag, "P09").WithArguments("override").WithLocation(12, 18), - // (16,22): error CS0273: The accessibility modifier of the 'I1.P12.get' accessor must be more restrictive than the property or indexer 'I1.P12' - // int P12 { public get; set;} - Diagnostic(ErrorCode.ERR_InvalidPropertyAccessMod, "get").WithArguments("I1.P12.get", "I1.P12").WithLocation(16, 22), - // (17,30): error CS0106: The modifier 'protected' is not valid for this item - // int P13 { get; protected set;} - Diagnostic(ErrorCode.ERR_BadMemberFlag, "set").WithArguments("protected").WithLocation(17, 30), - // (18,34): error CS0106: The modifier 'protected internal' is not valid for this item - // int P14 { protected internal get; set;} - Diagnostic(ErrorCode.ERR_BadMemberFlag, "get").WithArguments("protected internal").WithLocation(18, 34), - // (20,23): error CS0442: 'I1.P16.get': abstract properties cannot have private accessors - // int P16 { private get; set;} - Diagnostic(ErrorCode.ERR_PrivateAbstractAccessor, "get").WithArguments("I1.P16.get").WithLocation(20, 23), - // (21,9): error CS0276: 'I1.P17': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor - // int P17 { private get;} - Diagnostic(ErrorCode.ERR_AccessModMissingAccessor, "P17").WithArguments("I1.P17").WithLocation(21, 9), - // (14,21): warning CS0626: Method, operator, or accessor 'I1.P11.get' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. - // extern int P11 {get; set;} - Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "get").WithArguments("I1.P11.get").WithLocation(14, 21), - // (14,26): warning CS0626: Method, operator, or accessor 'I1.P11.set' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. - // extern int P11 {get; set;} - Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "set").WithArguments("I1.P11.set").WithLocation(14, 26) + // (4,26): error CS0180: 'I1.M1()' cannot be both extern and abstract + // abstract extern void M1(); + Diagnostic(ErrorCode.ERR_AbstractAndExtern, "M1").WithArguments("I1.M1()").WithLocation(4, 26), + // (5,17): error CS0179: 'I1.M2()' cannot be extern and declare a body + // extern void M2() {} + Diagnostic(ErrorCode.ERR_ExternHasBody, "M2").WithArguments("I1.M2()").WithLocation(5, 17), + // (11,15): error CS0535: 'Test1' does not implement interface member 'I1.M1()' + // class Test1 : I1 + Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test1", "I1.M1()").WithLocation(11, 15), + // (19,13): error CS0539: 'Test2.M3()' in explicit interface declaration is not found among members of the interface that can be implemented + // void I1.M3() {} + Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "M3").WithArguments("Test2.M3()").WithLocation(19, 13), + // (20,13): error CS0539: 'Test2.M4()' in explicit interface declaration is not found among members of the interface that can be implemented + // void I1.M4() {} + Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "M4").WithArguments("Test2.M4()").WithLocation(20, 13), + // (21,13): error CS0539: 'Test2.M5()' in explicit interface declaration is not found among members of the interface that can be implemented + // void I1.M5() {} + Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "M5").WithArguments("Test2.M5()").WithLocation(21, 13), + // (6,24): warning CS0626: Method, operator, or accessor 'I1.M3()' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. + // static extern void M3(); + Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "M3").WithArguments("I1.M3()").WithLocation(6, 24), + // (7,25): warning CS0626: Method, operator, or accessor 'I1.M4()' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. + // private extern void M4(); + Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "M4").WithArguments("I1.M4()").WithLocation(7, 25), + // (8,24): warning CS0626: Method, operator, or accessor 'I1.M5()' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. + // extern sealed void M5(); + Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "M5").WithArguments("I1.M5()").WithLocation(8, 24) ); - ValidateSymbolsPropertyModifiers_01(compilation1); - } - - private static void ValidateSymbolsPropertyModifiers_01(CSharpCompilation compilation1) - { + var test1 = compilation1.GetTypeByMetadataName("Test1"); + var test2 = compilation1.GetTypeByMetadataName("Test2"); var i1 = compilation1.GetTypeByMetadataName("I1"); - var p01 = i1.GetMember("P01"); - - Assert.True(p01.IsAbstract); - Assert.False(p01.IsVirtual); - Assert.False(p01.IsSealed); - Assert.False(p01.IsStatic); - Assert.False(p01.IsExtern); - Assert.False(p01.IsOverride); - Assert.Equal(Accessibility.Public, p01.DeclaredAccessibility); + var m1 = i1.GetMember("M1"); - VaidateP01Accessor(p01.GetMethod); - VaidateP01Accessor(p01.SetMethod); - void VaidateP01Accessor(MethodSymbol accessor) - { - Assert.True(accessor.IsAbstract); - Assert.False(accessor.IsVirtual); - Assert.True(accessor.IsMetadataVirtual()); - Assert.False(accessor.IsSealed); - Assert.False(accessor.IsStatic); - Assert.False(accessor.IsExtern); - Assert.False(accessor.IsAsync); - Assert.False(accessor.IsOverride); - Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); - } + Assert.True(m1.IsAbstract); + Assert.False(m1.IsVirtual); + Assert.True(m1.IsMetadataVirtual()); + Assert.False(m1.IsSealed); + Assert.False(m1.IsStatic); + Assert.True(m1.IsExtern); + Assert.False(m1.IsAsync); + Assert.False(m1.IsOverride); + Assert.Equal(Accessibility.Public, m1.DeclaredAccessibility); + Assert.Null(test1.FindImplementationForInterfaceMember(m1)); + Assert.Same(test2.GetMember("I1.M1"), test2.FindImplementationForInterfaceMember(m1)); - var p02 = i1.GetMember("P02"); - var p02get = p02.GetMethod; + var m2 = i1.GetMember("M2"); - Assert.True(p02.IsAbstract); - Assert.False(p02.IsVirtual); - Assert.False(p02.IsSealed); - Assert.False(p02.IsStatic); - Assert.False(p02.IsExtern); - Assert.False(p02.IsOverride); - Assert.Equal(Accessibility.Public, p02.DeclaredAccessibility); + Assert.False(m2.IsAbstract); + Assert.True(m2.IsVirtual); + Assert.True(m2.IsMetadataVirtual()); + Assert.False(m2.IsSealed); + Assert.False(m2.IsStatic); + Assert.True(m2.IsExtern); + Assert.False(m2.IsAsync); + Assert.False(m2.IsOverride); + Assert.Equal(Accessibility.Public, m2.DeclaredAccessibility); + Assert.Same(m2, test1.FindImplementationForInterfaceMember(m2)); + Assert.Same(test2.GetMember("I1.M2"), test2.FindImplementationForInterfaceMember(m2)); - Assert.True(p02get.IsAbstract); - Assert.False(p02get.IsVirtual); - Assert.True(p02get.IsMetadataVirtual()); - Assert.False(p02get.IsSealed); - Assert.False(p02get.IsStatic); - Assert.False(p02get.IsExtern); - Assert.False(p02get.IsAsync); - Assert.False(p02get.IsOverride); - Assert.Equal(Accessibility.Public, p02get.DeclaredAccessibility); + var m3 = i1.GetMember("M3"); + Assert.Null(test2.FindImplementationForInterfaceMember(m3)); - var p03 = i1.GetMember("P03"); - var p03set = p03.SetMethod; + var m4 = i1.GetMember("M4"); + Assert.Null(test2.FindImplementationForInterfaceMember(m4)); - Assert.True(p03.IsAbstract); - Assert.False(p03.IsVirtual); - Assert.False(p03.IsSealed); - Assert.False(p03.IsStatic); - Assert.False(p03.IsExtern); - Assert.False(p03.IsOverride); - Assert.Equal(Accessibility.Public, p03.DeclaredAccessibility); + var m5 = i1.GetMember("M5"); + Assert.Null(test2.FindImplementationForInterfaceMember(m5)); + } - Assert.True(p03set.IsAbstract); - Assert.False(p03set.IsVirtual); - Assert.True(p03set.IsMetadataVirtual()); - Assert.False(p03set.IsSealed); - Assert.False(p03set.IsStatic); - Assert.False(p03set.IsExtern); - Assert.False(p03set.IsAsync); - Assert.False(p03set.IsOverride); - Assert.Equal(Accessibility.Public, p03set.DeclaredAccessibility); + [Fact] + public void MethodModifiers_17() + { + var source1 = +@" +public interface I1 +{ + abstract void M1() {} + abstract private void M2() {} + abstract static void M3() {} + static extern void M4() {} + override sealed void M5() {} +} - var p04 = i1.GetMember("P04"); - var p04get = p04.GetMethod; +class Test1 : I1 +{ +} - Assert.True(p04.IsAbstract); - Assert.False(p04.IsVirtual); - Assert.False(p04.IsSealed); - Assert.False(p04.IsStatic); - Assert.False(p04.IsExtern); - Assert.False(p04.IsOverride); - Assert.Equal(Accessibility.Internal, p04.DeclaredAccessibility); +class Test2 : I1 +{ + void I1.M1() {} + void I1.M2() {} + void I1.M3() {} + void I1.M4() {} + void I1.M5() {} +} +"; + var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation1.VerifyDiagnostics( + // (4,19): error CS0500: 'I1.M1()' cannot declare a body because it is marked abstract + // abstract void M1() {} + Diagnostic(ErrorCode.ERR_AbstractHasBody, "M1").WithArguments("I1.M1()").WithLocation(4, 19), + // (5,27): error CS0500: 'I1.M2()' cannot declare a body because it is marked abstract + // abstract private void M2() {} + Diagnostic(ErrorCode.ERR_AbstractHasBody, "M2").WithArguments("I1.M2()").WithLocation(5, 27), + // (6,26): error CS0500: 'I1.M3()' cannot declare a body because it is marked abstract + // abstract static void M3() {} + Diagnostic(ErrorCode.ERR_AbstractHasBody, "M3").WithArguments("I1.M3()").WithLocation(6, 26), + // (7,24): error CS0179: 'I1.M4()' cannot be extern and declare a body + // static extern void M4() {} + Diagnostic(ErrorCode.ERR_ExternHasBody, "M4").WithArguments("I1.M4()").WithLocation(7, 24), + // (8,26): error CS0106: The modifier 'override' is not valid for this item + // override sealed void M5() {} + Diagnostic(ErrorCode.ERR_BadMemberFlag, "M5").WithArguments("override").WithLocation(8, 26), + // (5,27): error CS0621: 'I1.M2()': virtual or abstract members cannot be private + // abstract private void M2() {} + Diagnostic(ErrorCode.ERR_VirtualPrivate, "M2").WithArguments("I1.M2()").WithLocation(5, 27), + // (6,26): error CS0112: A static member 'I1.M3()' cannot be marked as override, virtual, or abstract + // abstract static void M3() {} + Diagnostic(ErrorCode.ERR_StaticNotVirtual, "M3").WithArguments("I1.M3()").WithLocation(6, 26), + // (11,15): error CS0535: 'Test1' does not implement interface member 'I1.M2()' + // class Test1 : I1 + Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test1", "I1.M2()").WithLocation(11, 15), + // (11,15): error CS0535: 'Test1' does not implement interface member 'I1.M1()' + // class Test1 : I1 + Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test1", "I1.M1()").WithLocation(11, 15), + // (18,13): error CS0122: 'I1.M2()' is inaccessible due to its protection level + // void I1.M2() {} + Diagnostic(ErrorCode.ERR_BadAccess, "M2").WithArguments("I1.M2()").WithLocation(18, 13), + // (19,13): error CS0539: 'Test2.M3()' in explicit interface declaration is not found among members of the interface that can be implemented + // void I1.M3() {} + Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "M3").WithArguments("Test2.M3()").WithLocation(19, 13), + // (20,13): error CS0539: 'Test2.M4()' in explicit interface declaration is not found among members of the interface that can be implemented + // void I1.M4() {} + Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "M4").WithArguments("Test2.M4()").WithLocation(20, 13), + // (21,13): error CS0539: 'Test2.M5()' in explicit interface declaration is not found among members of the interface that can be implemented + // void I1.M5() {} + Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "M5").WithArguments("Test2.M5()").WithLocation(21, 13) + ); - Assert.True(p04get.IsAbstract); - Assert.False(p04get.IsVirtual); - Assert.True(p04get.IsMetadataVirtual()); - Assert.False(p04get.IsSealed); - Assert.False(p04get.IsStatic); - Assert.False(p04get.IsExtern); - Assert.False(p04get.IsAsync); - Assert.False(p04get.IsOverride); - Assert.Equal(Accessibility.Internal, p04get.DeclaredAccessibility); + var test1 = compilation1.GetTypeByMetadataName("Test1"); + var test2 = compilation1.GetTypeByMetadataName("Test2"); + var i1 = compilation1.GetTypeByMetadataName("I1"); + var m1 = i1.GetMember("M1"); - var p05 = i1.GetMember("P05"); - var p05set = p05.SetMethod; + Assert.True(m1.IsAbstract); + Assert.False(m1.IsVirtual); + Assert.True(m1.IsMetadataVirtual()); + Assert.False(m1.IsSealed); + Assert.False(m1.IsStatic); + Assert.False(m1.IsExtern); + Assert.False(m1.IsAsync); + Assert.False(m1.IsOverride); + Assert.Equal(Accessibility.Public, m1.DeclaredAccessibility); + Assert.Null(test1.FindImplementationForInterfaceMember(m1)); + Assert.Same(test2.GetMember("I1.M1"), test2.FindImplementationForInterfaceMember(m1)); - Assert.False(p05.IsAbstract); - Assert.False(p05.IsVirtual); - Assert.False(p05.IsSealed); - Assert.False(p05.IsStatic); - Assert.False(p05.IsExtern); - Assert.False(p05.IsOverride); - Assert.Equal(Accessibility.Private, p05.DeclaredAccessibility); + var m2 = i1.GetMember("M2"); - Assert.False(p05set.IsAbstract); - Assert.False(p05set.IsVirtual); - Assert.False(p05set.IsMetadataVirtual()); - Assert.False(p05set.IsSealed); - Assert.False(p05set.IsStatic); - Assert.False(p05set.IsExtern); - Assert.False(p05set.IsAsync); - Assert.False(p05set.IsOverride); - Assert.Equal(Accessibility.Private, p05set.DeclaredAccessibility); - - var p06 = i1.GetMember("P06"); - var p06get = p06.GetMethod; - - Assert.False(p06.IsAbstract); - Assert.False(p06.IsVirtual); - Assert.False(p06.IsSealed); - Assert.True(p06.IsStatic); - Assert.False(p06.IsExtern); - Assert.False(p06.IsOverride); - Assert.Equal(Accessibility.Public, p06.DeclaredAccessibility); - - Assert.False(p06get.IsAbstract); - Assert.False(p06get.IsVirtual); - Assert.False(p06get.IsMetadataVirtual()); - Assert.False(p06get.IsSealed); - Assert.True(p06get.IsStatic); - Assert.False(p06get.IsExtern); - Assert.False(p06get.IsAsync); - Assert.False(p06get.IsOverride); - Assert.Equal(Accessibility.Public, p06get.DeclaredAccessibility); - - var p07 = i1.GetMember("P07"); - var p07set = p07.SetMethod; - - Assert.False(p07.IsAbstract); - Assert.True(p07.IsVirtual); - Assert.False(p07.IsSealed); - Assert.False(p07.IsStatic); - Assert.False(p07.IsExtern); - Assert.False(p07.IsOverride); - Assert.Equal(Accessibility.Public, p07.DeclaredAccessibility); - - Assert.False(p07set.IsAbstract); - Assert.True(p07set.IsVirtual); - Assert.True(p07set.IsMetadataVirtual()); - Assert.False(p07set.IsSealed); - Assert.False(p07set.IsStatic); - Assert.False(p07set.IsExtern); - Assert.False(p07set.IsAsync); - Assert.False(p07set.IsOverride); - Assert.Equal(Accessibility.Public, p07set.DeclaredAccessibility); - - var p08 = i1.GetMember("P08"); - var p08get = p08.GetMethod; + Assert.True(m2.IsAbstract); + Assert.False(m2.IsVirtual); + Assert.True(m2.IsMetadataVirtual()); + Assert.False(m2.IsSealed); + Assert.False(m2.IsStatic); + Assert.False(m2.IsExtern); + Assert.False(m2.IsAsync); + Assert.False(m2.IsOverride); + Assert.Equal(Accessibility.Private, m2.DeclaredAccessibility); + Assert.Null(test1.FindImplementationForInterfaceMember(m2)); + Assert.Same(test2.GetMember("I1.M2"), test2.FindImplementationForInterfaceMember(m2)); - Assert.False(p08.IsAbstract); - Assert.False(p08.IsVirtual); - Assert.False(p08.IsSealed); - Assert.False(p08.IsStatic); - Assert.False(p08.IsExtern); - Assert.False(p08.IsOverride); - Assert.Equal(Accessibility.Public, p08.DeclaredAccessibility); + var m3 = i1.GetMember("M3"); - Assert.False(p08get.IsAbstract); - Assert.False(p08get.IsVirtual); - Assert.False(p08get.IsMetadataVirtual()); - Assert.False(p08get.IsSealed); - Assert.False(p08get.IsStatic); - Assert.False(p08get.IsExtern); - Assert.False(p08get.IsAsync); - Assert.False(p08get.IsOverride); - Assert.Equal(Accessibility.Public, p08get.DeclaredAccessibility); + Assert.True(m3.IsAbstract); + Assert.False(m3.IsVirtual); + Assert.True(m3.IsMetadataVirtual()); + Assert.False(m3.IsSealed); + Assert.True(m3.IsStatic); + Assert.False(m3.IsExtern); + Assert.False(m3.IsAsync); + Assert.False(m3.IsOverride); + Assert.Equal(Accessibility.Public, m3.DeclaredAccessibility); + Assert.Null(test1.FindImplementationForInterfaceMember(m3)); + Assert.Null(test2.FindImplementationForInterfaceMember(m3)); - var p09 = i1.GetMember("P09"); - var p09set = p09.SetMethod; + var m4 = i1.GetMember("M4"); - Assert.True(p09.IsAbstract); - Assert.False(p09.IsVirtual); - Assert.False(p09.IsSealed); - Assert.False(p09.IsStatic); - Assert.False(p09.IsExtern); - Assert.False(p09.IsOverride); - Assert.Equal(Accessibility.Public, p09.DeclaredAccessibility); + Assert.False(m4.IsAbstract); + Assert.False(m4.IsVirtual); + Assert.False(m4.IsMetadataVirtual()); + Assert.False(m4.IsSealed); + Assert.True(m4.IsStatic); + Assert.True(m4.IsExtern); + Assert.False(m4.IsAsync); + Assert.False(m4.IsOverride); + Assert.Equal(Accessibility.Public, m4.DeclaredAccessibility); + Assert.Null(test1.FindImplementationForInterfaceMember(m4)); + Assert.Null(test2.FindImplementationForInterfaceMember(m4)); - Assert.True(p09set.IsAbstract); - Assert.False(p09set.IsVirtual); - Assert.True(p09set.IsMetadataVirtual()); - Assert.False(p09set.IsSealed); - Assert.False(p09set.IsStatic); - Assert.False(p09set.IsExtern); - Assert.False(p09set.IsAsync); - Assert.False(p09set.IsOverride); - Assert.Equal(Accessibility.Public, p09set.DeclaredAccessibility); + var m5 = i1.GetMember("M5"); - var p10 = i1.GetMember("P10"); - var p10get = p10.GetMethod; + Assert.False(m5.IsAbstract); + Assert.False(m5.IsVirtual); + Assert.False(m5.IsMetadataVirtual()); + Assert.False(m5.IsSealed); + Assert.False(m5.IsStatic); + Assert.False(m5.IsExtern); + Assert.False(m5.IsAsync); + Assert.False(m5.IsOverride); + Assert.Equal(Accessibility.Public, m5.DeclaredAccessibility); + Assert.Null(test1.FindImplementationForInterfaceMember(m5)); + Assert.Null(test2.FindImplementationForInterfaceMember(m5)); + } - Assert.True(p10.IsAbstract); - Assert.False(p10.IsVirtual); - Assert.False(p10.IsSealed); - Assert.False(p10.IsStatic); - Assert.False(p10.IsExtern); - Assert.False(p10.IsOverride); - Assert.Equal(Accessibility.Public, p10.DeclaredAccessibility); + [Fact] + public void MethodModifiers_18() + { + var source1 = +@" +using System.Threading; +using System.Threading.Tasks; - Assert.True(p10get.IsAbstract); - Assert.False(p10get.IsVirtual); - Assert.True(p10get.IsMetadataVirtual()); - Assert.False(p10get.IsSealed); - Assert.False(p10get.IsStatic); - Assert.False(p10get.IsExtern); - Assert.False(p10get.IsAsync); - Assert.False(p10get.IsOverride); - Assert.Equal(Accessibility.Public, p10get.DeclaredAccessibility); +public interface I1 +{ + public static async Task M1() + { + await Task.Factory.StartNew(() => System.Console.WriteLine(""M1"")); + } +} - var p11 = i1.GetMember("P11"); +class Test1 : I1 +{ + static void Main() + { + I1.M1().Wait(); + } +} +"; + var compilation1 = CreateCompilationWithMscorlib45(source1, options: TestOptions.DebugExe, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + CompileAndVerify(compilation1, expectedOutput:"M1", symbolValidator: Validate); - Assert.False(p11.IsAbstract); - Assert.True(p11.IsVirtual); - Assert.False(p11.IsSealed); - Assert.False(p11.IsStatic); - Assert.True(p11.IsExtern); - Assert.False(p11.IsOverride); - Assert.Equal(Accessibility.Public, p11.DeclaredAccessibility); + Validate(compilation1.SourceModule); - ValidateP11Accessor(p11.GetMethod); - ValidateP11Accessor(p11.SetMethod); - void ValidateP11Accessor(MethodSymbol accessor) + void Validate(ModuleSymbol m) { - Assert.False(accessor.IsAbstract); - Assert.True(accessor.IsVirtual); - Assert.True(accessor.IsMetadataVirtual()); - Assert.False(accessor.IsSealed); - Assert.False(accessor.IsStatic); - Assert.True(accessor.IsExtern); - Assert.False(accessor.IsAsync); - Assert.False(accessor.IsOverride); - Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); - } - - var p12 = i1.GetMember("P12"); - - Assert.True(p12.IsAbstract); - Assert.False(p12.IsVirtual); - Assert.False(p12.IsSealed); - Assert.False(p12.IsStatic); - Assert.False(p12.IsExtern); - Assert.False(p12.IsOverride); - Assert.Equal(Accessibility.Public, p12.DeclaredAccessibility); + var test1 = m.GlobalNamespace.GetTypeMember("Test1"); + var i1 = m.GlobalNamespace.GetTypeMember("I1"); + var m1 = i1.GetMember("M1"); - ValidateP12Accessor(p12.GetMethod); - ValidateP12Accessor(p12.SetMethod); - void ValidateP12Accessor(MethodSymbol accessor) - { - Assert.True(accessor.IsAbstract); - Assert.False(accessor.IsVirtual); - Assert.True(accessor.IsMetadataVirtual()); - Assert.False(accessor.IsSealed); - Assert.False(accessor.IsStatic); - Assert.False(accessor.IsExtern); - Assert.False(accessor.IsAsync); - Assert.False(accessor.IsOverride); - Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); + Assert.False(m1.IsAbstract); + Assert.False(m1.IsVirtual); + Assert.False(m1.IsMetadataVirtual()); + Assert.False(m1.IsSealed); + Assert.True(m1.IsStatic); + Assert.False(m1.IsExtern); + Assert.Equal(!(m is PEModuleSymbol), m1.IsAsync); + Assert.False(m1.IsOverride); + Assert.Equal(Accessibility.Public, m1.DeclaredAccessibility); + Assert.Null(test1.FindImplementationForInterfaceMember(m1)); } + } - var p13 = i1.GetMember("P13"); + [Fact] + public void MethodModifiers_19() + { + var source1 = +@" - Assert.True(p13.IsAbstract); - Assert.False(p13.IsVirtual); - Assert.False(p13.IsSealed); - Assert.False(p13.IsStatic); - Assert.False(p13.IsExtern); - Assert.False(p13.IsOverride); - Assert.Equal(Accessibility.Public, p13.DeclaredAccessibility); +public interface I2 {} - ValidateP13Accessor(p13.GetMethod); - ValidateP13Accessor(p13.SetMethod); - void ValidateP13Accessor(MethodSymbol accessor) +public interface I1 +{ + public void I2.M01(); + protected void I2.M02(); + protected internal void I2.M03(); + internal void I2.M04(); + private void I2.M05(); + static void I2.M06(); + virtual void I2.M07(); + sealed void I2.M08(); + override void I2.M09(); + abstract void I2.M10(); + extern void I2.M11(); + async void I2.M12(); +} +"; + var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + var expected = new[] { - Assert.True(accessor.IsAbstract); - Assert.False(accessor.IsVirtual); - Assert.True(accessor.IsMetadataVirtual()); - Assert.False(accessor.IsSealed); - Assert.False(accessor.IsStatic); - Assert.False(accessor.IsExtern); - Assert.False(accessor.IsAsync); - Assert.False(accessor.IsOverride); - Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); - } + // (7,20): error CS0106: The modifier 'public' is not valid for this item + // public void I2.M01(); + Diagnostic(ErrorCode.ERR_BadMemberFlag, "M01").WithArguments("public").WithLocation(7, 20), + // (8,23): error CS0106: The modifier 'protected' is not valid for this item + // protected void I2.M02(); + Diagnostic(ErrorCode.ERR_BadMemberFlag, "M02").WithArguments("protected").WithLocation(8, 23), + // (9,32): error CS0106: The modifier 'protected internal' is not valid for this item + // protected internal void I2.M03(); + Diagnostic(ErrorCode.ERR_BadMemberFlag, "M03").WithArguments("protected internal").WithLocation(9, 32), + // (10,22): error CS0106: The modifier 'internal' is not valid for this item + // internal void I2.M04(); + Diagnostic(ErrorCode.ERR_BadMemberFlag, "M04").WithArguments("internal").WithLocation(10, 22), + // (11,21): error CS0106: The modifier 'private' is not valid for this item + // private void I2.M05(); + Diagnostic(ErrorCode.ERR_BadMemberFlag, "M05").WithArguments("private").WithLocation(11, 21), + // (12,20): error CS0106: The modifier 'static' is not valid for this item + // static void I2.M06(); + Diagnostic(ErrorCode.ERR_BadMemberFlag, "M06").WithArguments("static").WithLocation(12, 20), + // (13,21): error CS0106: The modifier 'virtual' is not valid for this item + // virtual void I2.M07(); + Diagnostic(ErrorCode.ERR_BadMemberFlag, "M07").WithArguments("virtual").WithLocation(13, 21), + // (14,20): error CS0106: The modifier 'sealed' is not valid for this item + // sealed void I2.M08(); + Diagnostic(ErrorCode.ERR_BadMemberFlag, "M08").WithArguments("sealed").WithLocation(14, 20), + // (15,22): error CS0106: The modifier 'override' is not valid for this item + // override void I2.M09(); + Diagnostic(ErrorCode.ERR_BadMemberFlag, "M09").WithArguments("override").WithLocation(15, 22), + // (16,22): error CS0106: The modifier 'abstract' is not valid for this item + // abstract void I2.M10(); + Diagnostic(ErrorCode.ERR_BadMemberFlag, "M10").WithArguments("abstract").WithLocation(16, 22), + // (17,20): error CS0106: The modifier 'extern' is not valid for this item + // extern void I2.M11(); + Diagnostic(ErrorCode.ERR_BadMemberFlag, "M11").WithArguments("extern").WithLocation(17, 20), + // (18,19): error CS0106: The modifier 'async' is not valid for this item + // async void I2.M12(); + Diagnostic(ErrorCode.ERR_BadMemberFlag, "M12").WithArguments("async").WithLocation(18, 19), + // (7,20): error CS0541: 'I1.M01()': explicit interface declaration can only be declared in a class or struct + // public void I2.M01(); + Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "M01").WithArguments("I1.M01()").WithLocation(7, 20), + // (8,23): error CS0541: 'I1.M02()': explicit interface declaration can only be declared in a class or struct + // protected void I2.M02(); + Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "M02").WithArguments("I1.M02()").WithLocation(8, 23), + // (9,32): error CS0541: 'I1.M03()': explicit interface declaration can only be declared in a class or struct + // protected internal void I2.M03(); + Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "M03").WithArguments("I1.M03()").WithLocation(9, 32), + // (10,22): error CS0541: 'I1.M04()': explicit interface declaration can only be declared in a class or struct + // internal void I2.M04(); + Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "M04").WithArguments("I1.M04()").WithLocation(10, 22), + // (11,21): error CS0541: 'I1.M05()': explicit interface declaration can only be declared in a class or struct + // private void I2.M05(); + Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "M05").WithArguments("I1.M05()").WithLocation(11, 21), + // (12,20): error CS0541: 'I1.M06()': explicit interface declaration can only be declared in a class or struct + // static void I2.M06(); + Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "M06").WithArguments("I1.M06()").WithLocation(12, 20), + // (13,21): error CS0541: 'I1.M07()': explicit interface declaration can only be declared in a class or struct + // virtual void I2.M07(); + Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "M07").WithArguments("I1.M07()").WithLocation(13, 21), + // (14,20): error CS0541: 'I1.M08()': explicit interface declaration can only be declared in a class or struct + // sealed void I2.M08(); + Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "M08").WithArguments("I1.M08()").WithLocation(14, 20), + // (15,22): error CS0541: 'I1.M09()': explicit interface declaration can only be declared in a class or struct + // override void I2.M09(); + Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "M09").WithArguments("I1.M09()").WithLocation(15, 22), + // (16,22): error CS0541: 'I1.M10()': explicit interface declaration can only be declared in a class or struct + // abstract void I2.M10(); + Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "M10").WithArguments("I1.M10()").WithLocation(16, 22), + // (17,20): error CS0541: 'I1.M11()': explicit interface declaration can only be declared in a class or struct + // extern void I2.M11(); + Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "M11").WithArguments("I1.M11()").WithLocation(17, 20), + // (18,19): error CS0541: 'I1.M12()': explicit interface declaration can only be declared in a class or struct + // async void I2.M12(); + Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "M12").WithArguments("I1.M12()").WithLocation(18, 19) + }; - var p14 = i1.GetMember("P14"); + compilation1.VerifyDiagnostics(expected); - Assert.True(p14.IsAbstract); - Assert.False(p14.IsVirtual); - Assert.False(p14.IsSealed); - Assert.False(p14.IsStatic); - Assert.False(p14.IsExtern); - Assert.False(p14.IsOverride); - Assert.Equal(Accessibility.Public, p14.DeclaredAccessibility); + ValidateSymbolsMethodModifiers_19(compilation1); - ValidateP14Accessor(p14.GetMethod); - ValidateP14Accessor(p14.SetMethod); - void ValidateP14Accessor(MethodSymbol accessor) - { - Assert.True(accessor.IsAbstract); - Assert.False(accessor.IsVirtual); - Assert.True(accessor.IsMetadataVirtual()); - Assert.False(accessor.IsSealed); - Assert.False(accessor.IsStatic); - Assert.False(accessor.IsExtern); - Assert.False(accessor.IsAsync); - Assert.False(accessor.IsOverride); - Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); - } + var compilation2 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp7)); + Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation2.VerifyDiagnostics(expected); - var p15 = i1.GetMember("P15"); + ValidateSymbolsMethodModifiers_19(compilation2); + } - Assert.True(p15.IsAbstract); - Assert.False(p15.IsVirtual); - Assert.False(p15.IsSealed); - Assert.False(p15.IsStatic); - Assert.False(p15.IsExtern); - Assert.False(p15.IsOverride); - Assert.Equal(Accessibility.Public, p15.DeclaredAccessibility); + private static void ValidateSymbolsMethodModifiers_19(CSharpCompilation compilation1) + { + var i1 = compilation1.GetTypeByMetadataName("I1"); - ValidateP15Accessor(p15.GetMethod, Accessibility.Public); - ValidateP15Accessor(p15.SetMethod, Accessibility.Internal); - void ValidateP15Accessor(MethodSymbol accessor, Accessibility accessibility) + foreach (var methodName in new[] { "I2.M01", "I2.M02", "I2.M03", "I2.M04", "I2.M05", "I2.M06", "I2.M07", "I2.M08", "I2.M09", "I2.M10", "I2.M11", "I2.M12" }) { - Assert.True(accessor.IsAbstract); - Assert.False(accessor.IsVirtual); - Assert.True(accessor.IsMetadataVirtual()); - Assert.False(accessor.IsSealed); - Assert.False(accessor.IsStatic); - Assert.False(accessor.IsExtern); - Assert.False(accessor.IsAsync); - Assert.False(accessor.IsOverride); - Assert.Equal(accessibility, accessor.DeclaredAccessibility); - } - - var p16 = i1.GetMember("P16"); - - Assert.True(p16.IsAbstract); - Assert.False(p16.IsVirtual); - Assert.False(p16.IsSealed); - Assert.False(p16.IsStatic); - Assert.False(p16.IsExtern); - Assert.False(p16.IsOverride); - Assert.Equal(Accessibility.Public, p16.DeclaredAccessibility); + var m01 = i1.GetMember(methodName); - ValidateP16Accessor(p16.GetMethod, Accessibility.Private); - ValidateP16Accessor(p16.SetMethod, Accessibility.Public); - void ValidateP16Accessor(MethodSymbol accessor, Accessibility accessibility) - { - Assert.True(accessor.IsAbstract); - Assert.False(accessor.IsVirtual); - Assert.True(accessor.IsMetadataVirtual()); - Assert.False(accessor.IsSealed); - Assert.False(accessor.IsStatic); - Assert.False(accessor.IsExtern); - Assert.False(accessor.IsAsync); - Assert.False(accessor.IsOverride); - Assert.Equal(accessibility, accessor.DeclaredAccessibility); + Assert.True(m01.IsAbstract); + Assert.False(m01.IsVirtual); + Assert.True(m01.IsMetadataVirtual()); + Assert.False(m01.IsSealed); + Assert.False(m01.IsStatic); + Assert.False(m01.IsExtern); + Assert.False(m01.IsAsync); + Assert.False(m01.IsOverride); + Assert.Equal(Accessibility.Public, m01.DeclaredAccessibility); } - - var p17 = i1.GetMember("P17"); - var p17get = p17.GetMethod; - - Assert.True(p17.IsAbstract); - Assert.False(p17.IsVirtual); - Assert.False(p17.IsSealed); - Assert.False(p17.IsStatic); - Assert.False(p17.IsExtern); - Assert.False(p17.IsOverride); - Assert.Equal(Accessibility.Public, p17.DeclaredAccessibility); - - Assert.True(p17get.IsAbstract); - Assert.False(p17get.IsVirtual); - Assert.True(p17get.IsMetadataVirtual()); - Assert.False(p17get.IsSealed); - Assert.False(p17get.IsStatic); - Assert.False(p17get.IsExtern); - Assert.False(p17get.IsAsync); - Assert.False(p17get.IsOverride); - Assert.Equal(Accessibility.Private, p17get.DeclaredAccessibility); } [Fact] - public void PropertyModifiers_02() + public void MethodModifiers_20() { var source1 = @" public interface I1 { - public int P01 {get; set;} - protected int P02 {get;} - protected internal int P03 {set;} - internal int P04 {get;} - private int P05 {set;} - static int P06 {get;} - virtual int P07 {set;} - sealed int P08 {get;} - override int P09 {set;} - abstract int P10 {get;} - extern int P11 {get; set;} + internal void M1() + { + System.Console.WriteLine(""M1""); + } - int P12 { public get; set;} - int P13 { get; protected set;} - int P14 { protected internal get; set;} - int P15 { get; internal set;} - int P16 { private get; set;} - int P17 { private get;} + void M2() {M1();} } "; - var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, - parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp7)); + + var source2 = +@" +class Test1 : I1 +{ + static void Main() + { + I1 x = new Test1(); + x.M2(); + } +} +"; + var compilation1 = CreateStandardCompilation(source1 + source2, options: TestOptions.DebugExe, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); - compilation1.VerifyDiagnostics( - // (4,16): error CS8503: The modifier 'public' is not valid for this item in C# 7. Please use language version 7.1 or greater. - // public int P01 {get; set;} - Diagnostic(ErrorCode.ERR_DefaultInterfaceImplementationModifier, "P01").WithArguments("public", "7", "7.1").WithLocation(4, 16), - // (5,19): error CS0106: The modifier 'protected' is not valid for this item - // protected int P02 {get;} - Diagnostic(ErrorCode.ERR_BadMemberFlag, "P02").WithArguments("protected").WithLocation(5, 19), - // (6,28): error CS0106: The modifier 'protected internal' is not valid for this item - // protected internal int P03 {set;} - Diagnostic(ErrorCode.ERR_BadMemberFlag, "P03").WithArguments("protected internal").WithLocation(6, 28), - // (7,18): error CS8503: The modifier 'internal' is not valid for this item in C# 7. Please use language version 7.1 or greater. - // internal int P04 {get;} - Diagnostic(ErrorCode.ERR_DefaultInterfaceImplementationModifier, "P04").WithArguments("internal", "7", "7.1").WithLocation(7, 18), - // (8,17): error CS8503: The modifier 'private' is not valid for this item in C# 7. Please use language version 7.1 or greater. - // private int P05 {set;} - Diagnostic(ErrorCode.ERR_DefaultInterfaceImplementationModifier, "P05").WithArguments("private", "7", "7.1").WithLocation(8, 17), - // (8,22): error CS0501: 'I1.P05.set' must declare a body because it is not marked abstract, extern, or partial - // private int P05 {set;} - Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "set").WithArguments("I1.P05.set").WithLocation(8, 22), - // (9,16): error CS8503: The modifier 'static' is not valid for this item in C# 7. Please use language version 7.1 or greater. - // static int P06 {get;} - Diagnostic(ErrorCode.ERR_DefaultInterfaceImplementationModifier, "P06").WithArguments("static", "7", "7.1").WithLocation(9, 16), - // (9,21): error CS0501: 'I1.P06.get' must declare a body because it is not marked abstract, extern, or partial - // static int P06 {get;} - Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "get").WithArguments("I1.P06.get").WithLocation(9, 21), - // (10,17): error CS8503: The modifier 'virtual' is not valid for this item in C# 7. Please use language version 7.1 or greater. - // virtual int P07 {set;} - Diagnostic(ErrorCode.ERR_DefaultInterfaceImplementationModifier, "P07").WithArguments("virtual", "7", "7.1").WithLocation(10, 17), - // (10,22): error CS0501: 'I1.P07.set' must declare a body because it is not marked abstract, extern, or partial - // virtual int P07 {set;} - Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "set").WithArguments("I1.P07.set").WithLocation(10, 22), - // (11,16): error CS8503: The modifier 'sealed' is not valid for this item in C# 7. Please use language version 7.1 or greater. - // sealed int P08 {get;} - Diagnostic(ErrorCode.ERR_DefaultInterfaceImplementationModifier, "P08").WithArguments("sealed", "7", "7.1").WithLocation(11, 16), - // (11,21): error CS0501: 'I1.P08.get' must declare a body because it is not marked abstract, extern, or partial - // sealed int P08 {get;} - Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "get").WithArguments("I1.P08.get").WithLocation(11, 21), - // (12,18): error CS0106: The modifier 'override' is not valid for this item - // override int P09 {set;} - Diagnostic(ErrorCode.ERR_BadMemberFlag, "P09").WithArguments("override").WithLocation(12, 18), - // (13,18): error CS8503: The modifier 'abstract' is not valid for this item in C# 7. Please use language version 7.1 or greater. - // abstract int P10 {get;} - Diagnostic(ErrorCode.ERR_DefaultInterfaceImplementationModifier, "P10").WithArguments("abstract", "7", "7.1").WithLocation(13, 18), - // (14,16): error CS8503: The modifier 'extern' is not valid for this item in C# 7. Please use language version 7.1 or greater. - // extern int P11 {get; set;} - Diagnostic(ErrorCode.ERR_DefaultInterfaceImplementationModifier, "P11").WithArguments("extern", "7", "7.1").WithLocation(14, 16), - // (16,22): error CS8503: The modifier 'public' is not valid for this item in C# 7. Please use language version 7.1 or greater. - // int P12 { public get; set;} - Diagnostic(ErrorCode.ERR_DefaultInterfaceImplementationModifier, "get").WithArguments("public", "7", "7.1").WithLocation(16, 22), - // (16,22): error CS0273: The accessibility modifier of the 'I1.P12.get' accessor must be more restrictive than the property or indexer 'I1.P12' - // int P12 { public get; set;} - Diagnostic(ErrorCode.ERR_InvalidPropertyAccessMod, "get").WithArguments("I1.P12.get", "I1.P12").WithLocation(16, 22), - // (17,30): error CS0106: The modifier 'protected' is not valid for this item - // int P13 { get; protected set;} - Diagnostic(ErrorCode.ERR_BadMemberFlag, "set").WithArguments("protected").WithLocation(17, 30), - // (18,34): error CS0106: The modifier 'protected internal' is not valid for this item - // int P14 { protected internal get; set;} - Diagnostic(ErrorCode.ERR_BadMemberFlag, "get").WithArguments("protected internal").WithLocation(18, 34), - // (19,29): error CS8503: The modifier 'internal' is not valid for this item in C# 7. Please use language version 7.1 or greater. - // int P15 { get; internal set;} - Diagnostic(ErrorCode.ERR_DefaultInterfaceImplementationModifier, "set").WithArguments("internal", "7", "7.1").WithLocation(19, 29), - // (20,23): error CS8503: The modifier 'private' is not valid for this item in C# 7. Please use language version 7.1 or greater. - // int P16 { private get; set;} - Diagnostic(ErrorCode.ERR_DefaultInterfaceImplementationModifier, "get").WithArguments("private", "7", "7.1").WithLocation(20, 23), - // (20,23): error CS0442: 'I1.P16.get': abstract properties cannot have private accessors - // int P16 { private get; set;} - Diagnostic(ErrorCode.ERR_PrivateAbstractAccessor, "get").WithArguments("I1.P16.get").WithLocation(20, 23), - // (21,23): error CS8503: The modifier 'private' is not valid for this item in C# 7. Please use language version 7.1 or greater. - // int P17 { private get;} - Diagnostic(ErrorCode.ERR_DefaultInterfaceImplementationModifier, "get").WithArguments("private", "7", "7.1").WithLocation(21, 23), - // (21,9): error CS0276: 'I1.P17': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor - // int P17 { private get;} - Diagnostic(ErrorCode.ERR_AccessModMissingAccessor, "P17").WithArguments("I1.P17").WithLocation(21, 9), - // (14,21): warning CS0626: Method, operator, or accessor 'I1.P11.get' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. - // extern int P11 {get; set;} - Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "get").WithArguments("I1.P11.get").WithLocation(14, 21), - // (14,26): warning CS0626: Method, operator, or accessor 'I1.P11.set' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. - // extern int P11 {get; set;} - Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "set").WithArguments("I1.P11.set").WithLocation(14, 26) - ); + CompileAndVerify(compilation1/*, expectedOutput:"M1"*/, verify: false, symbolValidator: Validate1); - ValidateSymbolsPropertyModifiers_01(compilation1); + Validate1(compilation1.SourceModule); + + void Validate1(ModuleSymbol m) + { + var test1 = m.GlobalNamespace.GetTypeMember("Test1"); + var i1 = test1.Interfaces.Single(); + var m1 = i1.GetMember("M1"); + + ValidateMethod(m1); + Assert.Same(m1, test1.FindImplementationForInterfaceMember(m1)); + } + + void ValidateMethod(MethodSymbol m1) + { + Assert.False(m1.IsAbstract); + Assert.True(m1.IsVirtual); + Assert.True(m1.IsMetadataVirtual()); + Assert.False(m1.IsSealed); + Assert.False(m1.IsStatic); + Assert.False(m1.IsExtern); + Assert.False(m1.IsAsync); + Assert.False(m1.IsOverride); + Assert.Equal(Accessibility.Internal, m1.DeclaredAccessibility); + } + + var compilation2 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation2.VerifyDiagnostics(); + + { + var i1 = compilation2.GetTypeByMetadataName("I1"); + var m1 = i1.GetMember("M1"); + ValidateMethod(m1); + } + + var compilation3 = CreateStandardCompilation(source2, new[] { compilation2.ToMetadataReference() }, options: TestOptions.DebugExe, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + CompileAndVerify(compilation3/*, expectedOutput:"M1"*/, verify: false, symbolValidator: Validate1); + + Validate1(compilation3.SourceModule); + + var compilation4 = CreateStandardCompilation(source2, new[] { compilation2.EmitToImageReference() }, options: TestOptions.DebugExe, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation4.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + CompileAndVerify(compilation4/*, expectedOutput:"M1"*/, verify: false, symbolValidator: Validate1); + + Validate1(compilation4.SourceModule); } [Fact] - public void PropertyModifiers_03() + public void MethodModifiers_21() { - ValidatePropertyImplementation_101(@" + var source1 = +@" public interface I1 { - public virtual int P1 - { - get - { - System.Console.WriteLine(""get P1""); - return 0; - } - } -} + private static void M1() {} -class Test1 : I1 -{} -"); + internal static void M2() {} - ValidatePropertyImplementation_101(@" -public interface I1 + public static void M3() {} + + static void M4() {} +} + +class Test1 { - public virtual int P1 + static void Main() { - get => Test1.GetP1(); + I1.M1(); + I1.M2(); + I1.M3(); + I1.M4(); } } +"; + var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All), + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation1.VerifyDiagnostics( + // (17,12): error CS0122: 'I1.M1()' is inaccessible due to its protection level + // I1.M1(); + Diagnostic(ErrorCode.ERR_BadAccess, "M1").WithArguments("I1.M1()").WithLocation(17, 12) + ); -class Test1 : I1 + var source2 = +@" +class Test2 { - public static int GetP1() + static void Main() { - System.Console.WriteLine(""get P1""); - return 0; + I1.M1(); + I1.M2(); + I1.M3(); + I1.M4(); } } -"); +"; + var compilation2 = CreateStandardCompilation(source2, new[] { compilation1.ToMetadataReference() }, + options: TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All), + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation2.VerifyDiagnostics( + // (6,12): error CS0122: 'I1.M1()' is inaccessible due to its protection level + // I1.M1(); + Diagnostic(ErrorCode.ERR_BadAccess, "M1").WithArguments("I1.M1()").WithLocation(6, 12), + // (7,12): error CS0122: 'I1.M2()' is inaccessible due to its protection level + // I1.M2(); + Diagnostic(ErrorCode.ERR_BadAccess, "M2").WithArguments("I1.M2()").WithLocation(7, 12) + ); + } - ValidatePropertyImplementation_101(@" + [Fact] + public void ImplicitThisIsAllowed_03() + { + var source1 = +@" public interface I1 { - public virtual int P1 => Test1.GetP1(); -} + public int F1; -class Test1 : I1 -{ - public static int GetP1() + void M1() { - System.Console.WriteLine(""get P1""); - return 0; + System.Console.WriteLine(""I1.M1""); } -} -"); - ValidatePropertyImplementation_102(@" -public interface I1 -{ - public virtual int P1 + int P1 { get { - System.Console.WriteLine(""get P1""); + System.Console.WriteLine(""I1.get_P1""); return 0; } - set - { - System.Console.WriteLine(""set P1""); - } + set => System.Console.WriteLine(""I1.set_P1""); } -} - -class Test1 : I1 -{} -"); - ValidatePropertyImplementation_102(@" -public interface I1 -{ - public virtual int P1 + event System.Action E1 { - get => Test1.GetP1(); - set => System.Console.WriteLine(""set P1""); + add => System.Console.WriteLine(""I1.add_E1""); + remove => System.Console.WriteLine(""I1.remove_E1""); } -} -class Test1 : I1 -{ - public static int GetP1() + public interface I2 : I1 { - System.Console.WriteLine(""get P1""); - return 0; + void M2() + { + M1(); + P1 = P1; + E1 += null; + E1 -= null; + F1 = 0; + } } } -"); +"; + var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); - ValidatePropertyImplementation_103(@" + compilation1.VerifyDiagnostics( + // (4,16): error CS0525: Interfaces cannot contain fields + // public int F1; + Diagnostic(ErrorCode.ERR_InterfacesCantContainFields, "F1").WithLocation(4, 16) + ); + } + + [Fact] + public void ImplicitThisIsAllowed_04() + { + var source1 = +@" public interface I1 { - public virtual int P1 + public int F1; + + void M1() { - set + System.Console.WriteLine(""I1.M1""); + } + + int P1 + { + get { - System.Console.WriteLine(""set P1""); + System.Console.WriteLine(""I1.get_P1""); + return 0; } + set => System.Console.WriteLine(""I1.set_P1""); } -} - -class Test1 : I1 -{} -"); - ValidatePropertyImplementation_103(@" -public interface I1 -{ - public virtual int P1 + event System.Action E1 { - set => System.Console.WriteLine(""set P1""); + add => System.Console.WriteLine(""I1.add_E1""); + remove => System.Console.WriteLine(""I1.remove_E1""); } -} - -class Test1 : I1 -{} -"); - } - [Fact] - public void PropertyModifiers_04() + public interface I2 + { + void M2() { - var source1 = -@" -public interface I1 -{ - public virtual int P1 { get; } = 0; + M1(); + P1 = P1; + E1 += null; + E1 -= null; + F1 = 0; + } + } } "; var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation1.VerifyDiagnostics( - // (4,24): error CS8052: Auto-implemented properties inside interfaces cannot have initializers. - // public virtual int P1 { get; } = 0; - Diagnostic(ErrorCode.ERR_AutoPropertyInitializerInInterface, "P1").WithArguments("I1.P1").WithLocation(4, 24), - // (4,29): error CS0501: 'I1.P1.get' must declare a body because it is not marked abstract, extern, or partial - // public virtual int P1 { get; } = 0; - Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "get").WithArguments("I1.P1.get").WithLocation(4, 29) + // (4,16): error CS0525: Interfaces cannot contain fields + // public int F1; + Diagnostic(ErrorCode.ERR_InterfacesCantContainFields, "F1").WithLocation(4, 16), + // (31,13): error CS0120: An object reference is required for the non-static field, method, or property 'I1.M1()' + // M1(); + Diagnostic(ErrorCode.ERR_ObjectRequired, "M1").WithArguments("I1.M1()").WithLocation(31, 13), + // (32,13): error CS0120: An object reference is required for the non-static field, method, or property 'I1.P1' + // P1 = P1; + Diagnostic(ErrorCode.ERR_ObjectRequired, "P1").WithArguments("I1.P1").WithLocation(32, 13), + // (32,18): error CS0120: An object reference is required for the non-static field, method, or property 'I1.P1' + // P1 = P1; + Diagnostic(ErrorCode.ERR_ObjectRequired, "P1").WithArguments("I1.P1").WithLocation(32, 18), + // (33,13): error CS0120: An object reference is required for the non-static field, method, or property 'I1.E1' + // E1 += null; + Diagnostic(ErrorCode.ERR_ObjectRequired, "E1").WithArguments("I1.E1").WithLocation(33, 13), + // (34,13): error CS0120: An object reference is required for the non-static field, method, or property 'I1.E1' + // E1 -= null; + Diagnostic(ErrorCode.ERR_ObjectRequired, "E1").WithArguments("I1.E1").WithLocation(34, 13), + // (35,13): error CS0120: An object reference is required for the non-static field, method, or property 'I1.F1' + // F1 = 0; + Diagnostic(ErrorCode.ERR_ObjectRequired, "F1").WithArguments("I1.F1").WithLocation(35, 13) ); - - ValidatePropertyModifiers_04(compilation1, "P1"); - } - - private static void ValidatePropertyModifiers_04(CSharpCompilation compilation1, string propertyName) - { - var i1 = compilation1.GlobalNamespace.GetTypeMember("I1"); - var p1 = i1.GetMember(propertyName); - var p1get = p1.GetMethod; - - Assert.False(p1.IsAbstract); - Assert.True(p1.IsVirtual); - Assert.False(p1.IsSealed); - Assert.False(p1.IsStatic); - Assert.False(p1.IsExtern); - Assert.False(p1.IsOverride); - Assert.Equal(Accessibility.Public, p1.DeclaredAccessibility); - - Assert.False(p1get.IsAbstract); - Assert.True(p1get.IsVirtual); - Assert.True(p1get.IsMetadataVirtual()); - Assert.False(p1get.IsSealed); - Assert.False(p1get.IsStatic); - Assert.False(p1get.IsExtern); - Assert.False(p1get.IsAsync); - Assert.False(p1get.IsOverride); - Assert.Equal(Accessibility.Public, p1get.DeclaredAccessibility); } [Fact] - public void PropertyModifiers_05() + public void ImplicitThisIsAllowed_05() { var source1 = @" -public interface I1 -{ - public abstract int P1 {get; set;} -} -public interface I2 +public class C1 { - int P2 {get; set;} -} + public int F1; -class Test1 : I1 -{ - public int P1 + void M1() { - get - { - System.Console.WriteLine(""get_P1""); - return 0; - } - set => System.Console.WriteLine(""set_P1""); + System.Console.WriteLine(""I1.M1""); } -} -class Test2 : I2 -{ - public int P2 + + int P1 { get { - System.Console.WriteLine(""get_P2""); + System.Console.WriteLine(""I1.get_P1""); return 0; } - set => System.Console.WriteLine(""set_P2""); + set => System.Console.WriteLine(""I1.set_P1""); } - static void Main() + event System.Action E1 { - I1 x = new Test1(); - x.P1 = x.P1; - I2 y = new Test2(); - y.P2 = y.P2; + add => System.Console.WriteLine(""I1.add_E1""); + remove => System.Console.WriteLine(""I1.remove_E1""); } -} -"; - - ValidatePropertyModifiers_05(source1); - } - - private void ValidatePropertyModifiers_05(string source1) - { - var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugExe, - parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); - Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); - - CompileAndVerify(compilation1, expectedOutput: -@"get_P1 -set_P1 -get_P2 -set_P2", symbolValidator: Validate); - - Validate(compilation1.SourceModule); - - void Validate(ModuleSymbol m) - { - for (int i = 1; i <= 2; i++) - { - var test1 = m.GlobalNamespace.GetTypeMember("Test" + i); - var i1 = m.GlobalNamespace.GetTypeMember("I" + i); - var p1 = GetSingleProperty(i1); - var test1P1 = GetSingleProperty(test1); - Assert.True(p1.IsAbstract); - Assert.False(p1.IsVirtual); - Assert.False(p1.IsSealed); - Assert.False(p1.IsStatic); - Assert.False(p1.IsExtern); - Assert.False(p1.IsOverride); - Assert.Equal(Accessibility.Public, p1.DeclaredAccessibility); - Assert.Same(test1P1, test1.FindImplementationForInterfaceMember(p1)); - - ValidateAccessor(p1.GetMethod, test1P1.GetMethod); - ValidateAccessor(p1.SetMethod, test1P1.SetMethod); - - void ValidateAccessor(MethodSymbol accessor, MethodSymbol implementation) - { - Assert.True(accessor.IsAbstract); - Assert.False(accessor.IsVirtual); - Assert.True(accessor.IsMetadataVirtual()); - Assert.False(accessor.IsSealed); - Assert.False(accessor.IsStatic); - Assert.False(accessor.IsExtern); - Assert.False(accessor.IsAsync); - Assert.False(accessor.IsOverride); - Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); - Assert.Same(implementation, test1.FindImplementationForInterfaceMember(accessor)); - } - } - } - } - - private static PropertySymbol GetSingleProperty(NamedTypeSymbol container) - { - return container.GetMembers().OfType().Single(); - } - - private static PropertySymbol GetSingleProperty(CSharpCompilation compilation, string containerName) - { - return GetSingleProperty(compilation.GetTypeByMetadataName(containerName)); - } - - private static PropertySymbol GetSingleProperty(ModuleSymbol m, string containerName) + public interface I2 + { + void M2() { - return GetSingleProperty(m.GlobalNamespace.GetTypeMember(containerName)); + M1(); + P1 = P1; + E1 += null; + E1 -= null; + F1 = 0; } - - [Fact] - public void PropertyModifiers_06() - { - var source1 = -@" -public interface I1 -{ - public abstract int P1 {get; set;} + } } "; var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, - parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp7)); + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation1.VerifyDiagnostics( - // (4,25): error CS8503: The modifier 'abstract' is not valid for this item in C# 7. Please use language version 7.1 or greater. - // public abstract int P1 {get; set;} - Diagnostic(ErrorCode.ERR_DefaultInterfaceImplementationModifier, "P1").WithArguments("abstract", "7", "7.1").WithLocation(4, 25), - // (4,25): error CS8503: The modifier 'public' is not valid for this item in C# 7. Please use language version 7.1 or greater. - // public abstract int P1 {get; set;} - Diagnostic(ErrorCode.ERR_DefaultInterfaceImplementationModifier, "P1").WithArguments("public", "7", "7.1").WithLocation(4, 25) + // (31,13): error CS0120: An object reference is required for the non-static field, method, or property 'C1.M1()' + // M1(); + Diagnostic(ErrorCode.ERR_ObjectRequired, "M1").WithArguments("C1.M1()").WithLocation(31, 13), + // (32,13): error CS0120: An object reference is required for the non-static field, method, or property 'C1.P1' + // P1 = P1; + Diagnostic(ErrorCode.ERR_ObjectRequired, "P1").WithArguments("C1.P1").WithLocation(32, 13), + // (32,18): error CS0120: An object reference is required for the non-static field, method, or property 'C1.P1' + // P1 = P1; + Diagnostic(ErrorCode.ERR_ObjectRequired, "P1").WithArguments("C1.P1").WithLocation(32, 18), + // (33,13): error CS0120: An object reference is required for the non-static field, method, or property 'C1.E1' + // E1 += null; + Diagnostic(ErrorCode.ERR_ObjectRequired, "E1").WithArguments("C1.E1").WithLocation(33, 13), + // (34,13): error CS0120: An object reference is required for the non-static field, method, or property 'C1.E1' + // E1 -= null; + Diagnostic(ErrorCode.ERR_ObjectRequired, "E1").WithArguments("C1.E1").WithLocation(34, 13), + // (35,13): error CS0120: An object reference is required for the non-static field, method, or property 'C1.F1' + // F1 = 0; + Diagnostic(ErrorCode.ERR_ObjectRequired, "F1").WithArguments("C1.F1").WithLocation(35, 13) ); + } - ValidatePropertyModifiers_06(compilation1, "P1"); + [Fact] + public void PropertyModifiers_01() + { + var source1 = +@" +public interface I1 +{ + public int P01 {get; set;} + protected int P02 {get;} + protected internal int P03 {set;} + internal int P04 {get;} + private int P05 {set;} + static int P06 {get;} + virtual int P07 {set;} + sealed int P08 {get;} + override int P09 {set;} + abstract int P10 {get;} + extern int P11 {get; set;} + + int P12 { public get; set;} + int P13 { get; protected set;} + int P14 { protected internal get; set;} + int P15 { get; internal set;} + int P16 { private get; set;} + int P17 { private get;} +} +"; + var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation1.VerifyDiagnostics( + // (5,19): error CS0106: The modifier 'protected' is not valid for this item + // protected int P02 {get;} + Diagnostic(ErrorCode.ERR_BadMemberFlag, "P02").WithArguments("protected").WithLocation(5, 19), + // (6,28): error CS0106: The modifier 'protected internal' is not valid for this item + // protected internal int P03 {set;} + Diagnostic(ErrorCode.ERR_BadMemberFlag, "P03").WithArguments("protected internal").WithLocation(6, 28), + // (8,22): error CS0501: 'I1.P05.set' must declare a body because it is not marked abstract, extern, or partial + // private int P05 {set;} + Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "set").WithArguments("I1.P05.set").WithLocation(8, 22), + // (9,21): error CS0501: 'I1.P06.get' must declare a body because it is not marked abstract, extern, or partial + // static int P06 {get;} + Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "get").WithArguments("I1.P06.get").WithLocation(9, 21), + // (10,22): error CS0501: 'I1.P07.set' must declare a body because it is not marked abstract, extern, or partial + // virtual int P07 {set;} + Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "set").WithArguments("I1.P07.set").WithLocation(10, 22), + // (11,21): error CS0501: 'I1.P08.get' must declare a body because it is not marked abstract, extern, or partial + // sealed int P08 {get;} + Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "get").WithArguments("I1.P08.get").WithLocation(11, 21), + // (12,18): error CS0106: The modifier 'override' is not valid for this item + // override int P09 {set;} + Diagnostic(ErrorCode.ERR_BadMemberFlag, "P09").WithArguments("override").WithLocation(12, 18), + // (16,22): error CS0273: The accessibility modifier of the 'I1.P12.get' accessor must be more restrictive than the property or indexer 'I1.P12' + // int P12 { public get; set;} + Diagnostic(ErrorCode.ERR_InvalidPropertyAccessMod, "get").WithArguments("I1.P12.get", "I1.P12").WithLocation(16, 22), + // (17,30): error CS0106: The modifier 'protected' is not valid for this item + // int P13 { get; protected set;} + Diagnostic(ErrorCode.ERR_BadMemberFlag, "set").WithArguments("protected").WithLocation(17, 30), + // (18,34): error CS0106: The modifier 'protected internal' is not valid for this item + // int P14 { protected internal get; set;} + Diagnostic(ErrorCode.ERR_BadMemberFlag, "get").WithArguments("protected internal").WithLocation(18, 34), + // (20,23): error CS0442: 'I1.P16.get': abstract properties cannot have private accessors + // int P16 { private get; set;} + Diagnostic(ErrorCode.ERR_PrivateAbstractAccessor, "get").WithArguments("I1.P16.get").WithLocation(20, 23), + // (21,9): error CS0276: 'I1.P17': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor + // int P17 { private get;} + Diagnostic(ErrorCode.ERR_AccessModMissingAccessor, "P17").WithArguments("I1.P17").WithLocation(21, 9), + // (14,21): warning CS0626: Method, operator, or accessor 'I1.P11.get' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. + // extern int P11 {get; set;} + Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "get").WithArguments("I1.P11.get").WithLocation(14, 21), + // (14,26): warning CS0626: Method, operator, or accessor 'I1.P11.set' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. + // extern int P11 {get; set;} + Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "set").WithArguments("I1.P11.set").WithLocation(14, 26) + ); + + ValidateSymbolsPropertyModifiers_01(compilation1); } - private static void ValidatePropertyModifiers_06(CSharpCompilation compilation1, string propertyName) + private static void ValidateSymbolsPropertyModifiers_01(CSharpCompilation compilation1) { var i1 = compilation1.GetTypeByMetadataName("I1"); - var p1 = i1.GetMember(propertyName); - - Assert.True(p1.IsAbstract); - Assert.False(p1.IsVirtual); - Assert.False(p1.IsSealed); - Assert.False(p1.IsStatic); - Assert.False(p1.IsExtern); - Assert.False(p1.IsOverride); - Assert.Equal(Accessibility.Public, p1.DeclaredAccessibility); + var p01 = i1.GetMember("P01"); - ValidateAccessor(p1.GetMethod); - ValidateAccessor(p1.SetMethod); + Assert.True(p01.IsAbstract); + Assert.False(p01.IsVirtual); + Assert.False(p01.IsSealed); + Assert.False(p01.IsStatic); + Assert.False(p01.IsExtern); + Assert.False(p01.IsOverride); + Assert.Equal(Accessibility.Public, p01.DeclaredAccessibility); - void ValidateAccessor(MethodSymbol accessor) + VaidateP01Accessor(p01.GetMethod); + VaidateP01Accessor(p01.SetMethod); + void VaidateP01Accessor(MethodSymbol accessor) { Assert.True(accessor.IsAbstract); Assert.False(accessor.IsVirtual); @@ -8255,701 +8058,674 @@ void ValidateAccessor(MethodSymbol accessor) Assert.False(accessor.IsOverride); Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); } - } - [Fact] - public void PropertyModifiers_07() - { - var source1 = -@" -public interface I1 -{ - public static int P1 - { - get - { - System.Console.WriteLine(""get_P1""); - return 0; - } - set - { - System.Console.WriteLine(""set_P1""); - } - } + var p02 = i1.GetMember("P02"); + var p02get = p02.GetMethod; - internal static int P2 - { - get - { - System.Console.WriteLine(""get_P2""); - return P3; - } - set - { - System.Console.WriteLine(""set_P2""); - P3 = value; - } - } + Assert.True(p02.IsAbstract); + Assert.False(p02.IsVirtual); + Assert.False(p02.IsSealed); + Assert.False(p02.IsStatic); + Assert.False(p02.IsExtern); + Assert.False(p02.IsOverride); + Assert.Equal(Accessibility.Public, p02.DeclaredAccessibility); - private static int P3 - { - get => Test1.GetP3(); - set => System.Console.WriteLine(""set_P3""); - } + Assert.True(p02get.IsAbstract); + Assert.False(p02get.IsVirtual); + Assert.True(p02get.IsMetadataVirtual()); + Assert.False(p02get.IsSealed); + Assert.False(p02get.IsStatic); + Assert.False(p02get.IsExtern); + Assert.False(p02get.IsAsync); + Assert.False(p02get.IsOverride); + Assert.Equal(Accessibility.Public, p02get.DeclaredAccessibility); - internal static int P4 => Test1.GetP4(); + var p03 = i1.GetMember("P03"); + var p03set = p03.SetMethod; - internal static int P5 - { - get - { - System.Console.WriteLine(""get_P5""); - return 0; - } - } + Assert.True(p03.IsAbstract); + Assert.False(p03.IsVirtual); + Assert.False(p03.IsSealed); + Assert.False(p03.IsStatic); + Assert.False(p03.IsExtern); + Assert.False(p03.IsOverride); + Assert.Equal(Accessibility.Public, p03.DeclaredAccessibility); - internal static int P6 - { - get => Test1.GetP6(); - } + Assert.True(p03set.IsAbstract); + Assert.False(p03set.IsVirtual); + Assert.True(p03set.IsMetadataVirtual()); + Assert.False(p03set.IsSealed); + Assert.False(p03set.IsStatic); + Assert.False(p03set.IsExtern); + Assert.False(p03set.IsAsync); + Assert.False(p03set.IsOverride); + Assert.Equal(Accessibility.Public, p03set.DeclaredAccessibility); - internal static int P7 - { - set - { - System.Console.WriteLine(""set_P7""); - } - } + var p04 = i1.GetMember("P04"); + var p04get = p04.GetMethod; - internal static int P8 - { - set => System.Console.WriteLine(""set_P8""); - } -} + Assert.True(p04.IsAbstract); + Assert.False(p04.IsVirtual); + Assert.False(p04.IsSealed); + Assert.False(p04.IsStatic); + Assert.False(p04.IsExtern); + Assert.False(p04.IsOverride); + Assert.Equal(Accessibility.Internal, p04.DeclaredAccessibility); -class Test1 : I1 -{ - static void Main() - { - I1.P1 = I1.P1; - I1.P2 = I1.P2; - var x = I1.P4; - x = I1.P5; - x = I1.P6; - I1.P7 = x; - I1.P8 = x; - } + Assert.True(p04get.IsAbstract); + Assert.False(p04get.IsVirtual); + Assert.True(p04get.IsMetadataVirtual()); + Assert.False(p04get.IsSealed); + Assert.False(p04get.IsStatic); + Assert.False(p04get.IsExtern); + Assert.False(p04get.IsAsync); + Assert.False(p04get.IsOverride); + Assert.Equal(Accessibility.Internal, p04get.DeclaredAccessibility); - public static int GetP3() - { - System.Console.WriteLine(""get_P3""); - return 0; - } + var p05 = i1.GetMember("P05"); + var p05set = p05.SetMethod; - public static int GetP4() - { - System.Console.WriteLine(""get_P4""); - return 0; - } + Assert.False(p05.IsAbstract); + Assert.False(p05.IsVirtual); + Assert.False(p05.IsSealed); + Assert.False(p05.IsStatic); + Assert.False(p05.IsExtern); + Assert.False(p05.IsOverride); + Assert.Equal(Accessibility.Private, p05.DeclaredAccessibility); - public static int GetP6() - { - System.Console.WriteLine(""get_P6""); - return 0; - } -} -"; - var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All), - parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); - Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); - CompileAndVerify(compilation1, expectedOutput: -@"get_P1 -set_P1 -get_P2 -get_P3 -set_P2 -set_P3 -get_P4 -get_P5 -get_P6 -set_P7 -set_P8", symbolValidator: Validate); + Assert.False(p05set.IsAbstract); + Assert.False(p05set.IsVirtual); + Assert.False(p05set.IsMetadataVirtual()); + Assert.False(p05set.IsSealed); + Assert.False(p05set.IsStatic); + Assert.False(p05set.IsExtern); + Assert.False(p05set.IsAsync); + Assert.False(p05set.IsOverride); + Assert.Equal(Accessibility.Private, p05set.DeclaredAccessibility); - Validate(compilation1.SourceModule); + var p06 = i1.GetMember("P06"); + var p06get = p06.GetMethod; - void Validate(ModuleSymbol m) - { - var test1 = m.GlobalNamespace.GetTypeMember("Test1"); - var i1 = m.GlobalNamespace.GetTypeMember("I1"); + Assert.False(p06.IsAbstract); + Assert.False(p06.IsVirtual); + Assert.False(p06.IsSealed); + Assert.True(p06.IsStatic); + Assert.False(p06.IsExtern); + Assert.False(p06.IsOverride); + Assert.Equal(Accessibility.Public, p06.DeclaredAccessibility); - foreach (var tuple in new[] { (name: "P1", access: Accessibility.Public), - (name: "P2", access: Accessibility.Internal), - (name: "P3", access: Accessibility.Private), - (name: "P4", access: Accessibility.Internal), - (name: "P5", access: Accessibility.Internal), - (name: "P6", access: Accessibility.Internal), - (name: "P7", access: Accessibility.Internal), - (name: "P8", access: Accessibility.Internal)}) - { - var p1 = i1.GetMember(tuple.name); + Assert.False(p06get.IsAbstract); + Assert.False(p06get.IsVirtual); + Assert.False(p06get.IsMetadataVirtual()); + Assert.False(p06get.IsSealed); + Assert.True(p06get.IsStatic); + Assert.False(p06get.IsExtern); + Assert.False(p06get.IsAsync); + Assert.False(p06get.IsOverride); + Assert.Equal(Accessibility.Public, p06get.DeclaredAccessibility); - Assert.False(p1.IsAbstract); - Assert.False(p1.IsVirtual); - Assert.False(p1.IsSealed); - Assert.True(p1.IsStatic); - Assert.False(p1.IsExtern); - Assert.False(p1.IsOverride); - Assert.Equal(tuple.access, p1.DeclaredAccessibility); - Assert.Null(test1.FindImplementationForInterfaceMember(p1)); + var p07 = i1.GetMember("P07"); + var p07set = p07.SetMethod; - switch (tuple.name) - { - case "P7": - case "P8": - Assert.Null(p1.GetMethod); - ValidateAccessor(p1.SetMethod); - break; - case "P4": - case "P5": - case "P6": - Assert.Null(p1.SetMethod); - ValidateAccessor(p1.GetMethod); - break; - default: - ValidateAccessor(p1.GetMethod); - ValidateAccessor(p1.SetMethod); - break; - } + Assert.False(p07.IsAbstract); + Assert.True(p07.IsVirtual); + Assert.False(p07.IsSealed); + Assert.False(p07.IsStatic); + Assert.False(p07.IsExtern); + Assert.False(p07.IsOverride); + Assert.Equal(Accessibility.Public, p07.DeclaredAccessibility); - void ValidateAccessor(MethodSymbol accessor) - { - Assert.False(accessor.IsAbstract); - Assert.False(accessor.IsVirtual); - Assert.False(accessor.IsMetadataVirtual()); - Assert.False(accessor.IsSealed); - Assert.True(accessor.IsStatic); - Assert.False(accessor.IsExtern); - Assert.False(accessor.IsAsync); - Assert.False(accessor.IsOverride); - Assert.Equal(tuple.access, accessor.DeclaredAccessibility); - Assert.Null(test1.FindImplementationForInterfaceMember(accessor)); - } - } - } - } + Assert.False(p07set.IsAbstract); + Assert.True(p07set.IsVirtual); + Assert.True(p07set.IsMetadataVirtual()); + Assert.False(p07set.IsSealed); + Assert.False(p07set.IsStatic); + Assert.False(p07set.IsExtern); + Assert.False(p07set.IsAsync); + Assert.False(p07set.IsOverride); + Assert.Equal(Accessibility.Public, p07set.DeclaredAccessibility); - [Fact] - public void PropertyModifiers_08() - { - var source1 = -@" -public interface I1 -{ - abstract static int P1 {get;} + var p08 = i1.GetMember("P08"); + var p08get = p08.GetMethod; - virtual static int P2 {set {}} - - sealed static int P3 => 0; + Assert.False(p08.IsAbstract); + Assert.False(p08.IsVirtual); + Assert.False(p08.IsSealed); + Assert.False(p08.IsStatic); + Assert.False(p08.IsExtern); + Assert.False(p08.IsOverride); + Assert.Equal(Accessibility.Public, p08.DeclaredAccessibility); - static int P4 {get;} = 0; -} + Assert.False(p08get.IsAbstract); + Assert.False(p08get.IsVirtual); + Assert.False(p08get.IsMetadataVirtual()); + Assert.False(p08get.IsSealed); + Assert.False(p08get.IsStatic); + Assert.False(p08get.IsExtern); + Assert.False(p08get.IsAsync); + Assert.False(p08get.IsOverride); + Assert.Equal(Accessibility.Public, p08get.DeclaredAccessibility); -class Test1 : I1 -{ - int I1.P1 => 0; - int I1.P2 {set {}} - int I1.P3 => 0; - int I1.P4 {set {}} -} + var p09 = i1.GetMember("P09"); + var p09set = p09.SetMethod; -class Test2 : I1 -{} -"; - var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, - parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); - Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); - compilation1.VerifyDiagnostics( - // (4,25): error CS0112: A static member 'I1.P1' cannot be marked as override, virtual, or abstract - // abstract static int P1 {get;} - Diagnostic(ErrorCode.ERR_StaticNotVirtual, "P1").WithArguments("I1.P1").WithLocation(4, 25), - // (6,24): error CS0112: A static member 'I1.P2' cannot be marked as override, virtual, or abstract - // virtual static int P2 {set {}} - Diagnostic(ErrorCode.ERR_StaticNotVirtual, "P2").WithArguments("I1.P2").WithLocation(6, 24), - // (8,23): error CS0238: 'I1.P3' cannot be sealed because it is not an override - // sealed static int P3 => 0; - Diagnostic(ErrorCode.ERR_SealedNonOverride, "P3").WithArguments("I1.P3").WithLocation(8, 23), - // (10,16): error CS8052: Auto-implemented properties inside interfaces cannot have initializers. - // static int P4 {get;} = 0; - Diagnostic(ErrorCode.ERR_AutoPropertyInitializerInInterface, "P4").WithArguments("I1.P4").WithLocation(10, 16), - // (10,20): error CS0501: 'I1.P4.get' must declare a body because it is not marked abstract, extern, or partial - // static int P4 {get;} = 0; - Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "get").WithArguments("I1.P4.get").WithLocation(10, 20), - // (15,12): error CS0539: 'Test1.P1' in explicit interface declaration is not found among members of the interface that can be implemented - // int I1.P1 => 0; - Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "P1").WithArguments("Test1.P1").WithLocation(15, 12), - // (16,12): error CS0539: 'Test1.P2' in explicit interface declaration is not found among members of the interface that can be implemented - // int I1.P2 {set {}} - Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "P2").WithArguments("Test1.P2").WithLocation(16, 12), - // (17,12): error CS0539: 'Test1.P3' in explicit interface declaration is not found among members of the interface that can be implemented - // int I1.P3 => 0; - Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "P3").WithArguments("Test1.P3").WithLocation(17, 12), - // (18,12): error CS0539: 'Test1.P4' in explicit interface declaration is not found among members of the interface that can be implemented - // int I1.P4 {set {}} - Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "P4").WithArguments("Test1.P4").WithLocation(18, 12) - ); + Assert.True(p09.IsAbstract); + Assert.False(p09.IsVirtual); + Assert.False(p09.IsSealed); + Assert.False(p09.IsStatic); + Assert.False(p09.IsExtern); + Assert.False(p09.IsOverride); + Assert.Equal(Accessibility.Public, p09.DeclaredAccessibility); - var test1 = compilation1.GetTypeByMetadataName("Test1"); - var i1 = compilation1.GetTypeByMetadataName("I1"); - var p1 = i1.GetMember("P1"); - var p1get = p1.GetMethod; + Assert.True(p09set.IsAbstract); + Assert.False(p09set.IsVirtual); + Assert.True(p09set.IsMetadataVirtual()); + Assert.False(p09set.IsSealed); + Assert.False(p09set.IsStatic); + Assert.False(p09set.IsExtern); + Assert.False(p09set.IsAsync); + Assert.False(p09set.IsOverride); + Assert.Equal(Accessibility.Public, p09set.DeclaredAccessibility); - Assert.True(p1.IsAbstract); - Assert.False(p1.IsVirtual); - Assert.False(p1.IsSealed); - Assert.True(p1.IsStatic); - Assert.False(p1.IsExtern); - Assert.False(p1.IsOverride); - Assert.Equal(Accessibility.Public, p1.DeclaredAccessibility); - Assert.Null(test1.FindImplementationForInterfaceMember(p1)); + var p10 = i1.GetMember("P10"); + var p10get = p10.GetMethod; - Assert.True(p1get.IsAbstract); - Assert.False(p1get.IsVirtual); - Assert.True(p1get.IsMetadataVirtual()); - Assert.False(p1get.IsSealed); - Assert.True(p1get.IsStatic); - Assert.False(p1get.IsExtern); - Assert.False(p1get.IsAsync); - Assert.False(p1get.IsOverride); - Assert.Equal(Accessibility.Public, p1get.DeclaredAccessibility); - Assert.Null(test1.FindImplementationForInterfaceMember(p1get)); + Assert.True(p10.IsAbstract); + Assert.False(p10.IsVirtual); + Assert.False(p10.IsSealed); + Assert.False(p10.IsStatic); + Assert.False(p10.IsExtern); + Assert.False(p10.IsOverride); + Assert.Equal(Accessibility.Public, p10.DeclaredAccessibility); - var p2 = i1.GetMember("P2"); - var p2set = p2.SetMethod; + Assert.True(p10get.IsAbstract); + Assert.False(p10get.IsVirtual); + Assert.True(p10get.IsMetadataVirtual()); + Assert.False(p10get.IsSealed); + Assert.False(p10get.IsStatic); + Assert.False(p10get.IsExtern); + Assert.False(p10get.IsAsync); + Assert.False(p10get.IsOverride); + Assert.Equal(Accessibility.Public, p10get.DeclaredAccessibility); - Assert.False(p2.IsAbstract); - Assert.True(p2.IsVirtual); - Assert.False(p2.IsSealed); - Assert.True(p2.IsStatic); - Assert.False(p2.IsExtern); - Assert.False(p2.IsOverride); - Assert.Equal(Accessibility.Public, p2.DeclaredAccessibility); - Assert.Null(test1.FindImplementationForInterfaceMember(p2)); + var p11 = i1.GetMember("P11"); - Assert.False(p2set.IsAbstract); - Assert.True(p2set.IsVirtual); - Assert.True(p2set.IsMetadataVirtual()); - Assert.False(p2set.IsSealed); - Assert.True(p2set.IsStatic); - Assert.False(p2set.IsExtern); - Assert.False(p2set.IsAsync); - Assert.False(p2set.IsOverride); - Assert.Equal(Accessibility.Public, p2set.DeclaredAccessibility); - Assert.Null(test1.FindImplementationForInterfaceMember(p2set)); + Assert.False(p11.IsAbstract); + Assert.True(p11.IsVirtual); + Assert.False(p11.IsSealed); + Assert.False(p11.IsStatic); + Assert.True(p11.IsExtern); + Assert.False(p11.IsOverride); + Assert.Equal(Accessibility.Public, p11.DeclaredAccessibility); - var p3 = i1.GetMember("P3"); - var p3get = p3.GetMethod; + ValidateP11Accessor(p11.GetMethod); + ValidateP11Accessor(p11.SetMethod); + void ValidateP11Accessor(MethodSymbol accessor) + { + Assert.False(accessor.IsAbstract); + Assert.True(accessor.IsVirtual); + Assert.True(accessor.IsMetadataVirtual()); + Assert.False(accessor.IsSealed); + Assert.False(accessor.IsStatic); + Assert.True(accessor.IsExtern); + Assert.False(accessor.IsAsync); + Assert.False(accessor.IsOverride); + Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); + } - Assert.False(p3.IsAbstract); - Assert.False(p3.IsVirtual); - Assert.True(p3.IsSealed); - Assert.True(p3.IsStatic); - Assert.False(p3.IsExtern); - Assert.False(p3.IsOverride); - Assert.Equal(Accessibility.Public, p3.DeclaredAccessibility); - Assert.Null(test1.FindImplementationForInterfaceMember(p3)); + var p12 = i1.GetMember("P12"); - Assert.False(p3get.IsAbstract); - Assert.False(p3get.IsVirtual); - Assert.False(p3get.IsMetadataVirtual()); - Assert.True(p3get.IsSealed); - Assert.True(p3get.IsStatic); - Assert.False(p3get.IsExtern); - Assert.False(p3get.IsAsync); - Assert.False(p3get.IsOverride); - Assert.Equal(Accessibility.Public, p3get.DeclaredAccessibility); - Assert.Null(test1.FindImplementationForInterfaceMember(p3get)); + Assert.True(p12.IsAbstract); + Assert.False(p12.IsVirtual); + Assert.False(p12.IsSealed); + Assert.False(p12.IsStatic); + Assert.False(p12.IsExtern); + Assert.False(p12.IsOverride); + Assert.Equal(Accessibility.Public, p12.DeclaredAccessibility); + + ValidateP12Accessor(p12.GetMethod); + ValidateP12Accessor(p12.SetMethod); + void ValidateP12Accessor(MethodSymbol accessor) + { + Assert.True(accessor.IsAbstract); + Assert.False(accessor.IsVirtual); + Assert.True(accessor.IsMetadataVirtual()); + Assert.False(accessor.IsSealed); + Assert.False(accessor.IsStatic); + Assert.False(accessor.IsExtern); + Assert.False(accessor.IsAsync); + Assert.False(accessor.IsOverride); + Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); + } + + var p13 = i1.GetMember("P13"); + + Assert.True(p13.IsAbstract); + Assert.False(p13.IsVirtual); + Assert.False(p13.IsSealed); + Assert.False(p13.IsStatic); + Assert.False(p13.IsExtern); + Assert.False(p13.IsOverride); + Assert.Equal(Accessibility.Public, p13.DeclaredAccessibility); + + ValidateP13Accessor(p13.GetMethod); + ValidateP13Accessor(p13.SetMethod); + void ValidateP13Accessor(MethodSymbol accessor) + { + Assert.True(accessor.IsAbstract); + Assert.False(accessor.IsVirtual); + Assert.True(accessor.IsMetadataVirtual()); + Assert.False(accessor.IsSealed); + Assert.False(accessor.IsStatic); + Assert.False(accessor.IsExtern); + Assert.False(accessor.IsAsync); + Assert.False(accessor.IsOverride); + Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); + } + + var p14 = i1.GetMember("P14"); + + Assert.True(p14.IsAbstract); + Assert.False(p14.IsVirtual); + Assert.False(p14.IsSealed); + Assert.False(p14.IsStatic); + Assert.False(p14.IsExtern); + Assert.False(p14.IsOverride); + Assert.Equal(Accessibility.Public, p14.DeclaredAccessibility); + + ValidateP14Accessor(p14.GetMethod); + ValidateP14Accessor(p14.SetMethod); + void ValidateP14Accessor(MethodSymbol accessor) + { + Assert.True(accessor.IsAbstract); + Assert.False(accessor.IsVirtual); + Assert.True(accessor.IsMetadataVirtual()); + Assert.False(accessor.IsSealed); + Assert.False(accessor.IsStatic); + Assert.False(accessor.IsExtern); + Assert.False(accessor.IsAsync); + Assert.False(accessor.IsOverride); + Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); + } + + var p15 = i1.GetMember("P15"); + + Assert.True(p15.IsAbstract); + Assert.False(p15.IsVirtual); + Assert.False(p15.IsSealed); + Assert.False(p15.IsStatic); + Assert.False(p15.IsExtern); + Assert.False(p15.IsOverride); + Assert.Equal(Accessibility.Public, p15.DeclaredAccessibility); + + ValidateP15Accessor(p15.GetMethod, Accessibility.Public); + ValidateP15Accessor(p15.SetMethod, Accessibility.Internal); + void ValidateP15Accessor(MethodSymbol accessor, Accessibility accessibility) + { + Assert.True(accessor.IsAbstract); + Assert.False(accessor.IsVirtual); + Assert.True(accessor.IsMetadataVirtual()); + Assert.False(accessor.IsSealed); + Assert.False(accessor.IsStatic); + Assert.False(accessor.IsExtern); + Assert.False(accessor.IsAsync); + Assert.False(accessor.IsOverride); + Assert.Equal(accessibility, accessor.DeclaredAccessibility); + } + + var p16 = i1.GetMember("P16"); + + Assert.True(p16.IsAbstract); + Assert.False(p16.IsVirtual); + Assert.False(p16.IsSealed); + Assert.False(p16.IsStatic); + Assert.False(p16.IsExtern); + Assert.False(p16.IsOverride); + Assert.Equal(Accessibility.Public, p16.DeclaredAccessibility); + + ValidateP16Accessor(p16.GetMethod, Accessibility.Private); + ValidateP16Accessor(p16.SetMethod, Accessibility.Public); + void ValidateP16Accessor(MethodSymbol accessor, Accessibility accessibility) + { + Assert.True(accessor.IsAbstract); + Assert.False(accessor.IsVirtual); + Assert.True(accessor.IsMetadataVirtual()); + Assert.False(accessor.IsSealed); + Assert.False(accessor.IsStatic); + Assert.False(accessor.IsExtern); + Assert.False(accessor.IsAsync); + Assert.False(accessor.IsOverride); + Assert.Equal(accessibility, accessor.DeclaredAccessibility); + } + + var p17 = i1.GetMember("P17"); + var p17get = p17.GetMethod; + + Assert.True(p17.IsAbstract); + Assert.False(p17.IsVirtual); + Assert.False(p17.IsSealed); + Assert.False(p17.IsStatic); + Assert.False(p17.IsExtern); + Assert.False(p17.IsOverride); + Assert.Equal(Accessibility.Public, p17.DeclaredAccessibility); + + Assert.True(p17get.IsAbstract); + Assert.False(p17get.IsVirtual); + Assert.True(p17get.IsMetadataVirtual()); + Assert.False(p17get.IsSealed); + Assert.False(p17get.IsStatic); + Assert.False(p17get.IsExtern); + Assert.False(p17get.IsAsync); + Assert.False(p17get.IsOverride); + Assert.Equal(Accessibility.Private, p17get.DeclaredAccessibility); } [Fact] - public void PropertyModifiers_09() + public void PropertyModifiers_02() { var source1 = @" public interface I1 { - private int P1 - { - get - { - System.Console.WriteLine(""get_P1""); - return 0; - } - } - sealed void M() - { - var x = P1; - } + public int P01 {get; set;} + protected int P02 {get;} + protected internal int P03 {set;} + internal int P04 {get;} + private int P05 {set;} + static int P06 {get;} + virtual int P07 {set;} + sealed int P08 {get;} + override int P09 {set;} + abstract int P10 {get;} + extern int P11 {get; set;} + + int P12 { public get; set;} + int P13 { get; protected set;} + int P14 { protected internal get; set;} + int P15 { get; internal set;} + int P16 { private get; set;} + int P17 { private get;} } -public interface I2 -{ - private int P2 +"; + var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp7)); + Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation1.VerifyDiagnostics( + // (4,16): error CS8503: The modifier 'public' is not valid for this item in C# 7. Please use language version 7.1 or greater. + // public int P01 {get; set;} + Diagnostic(ErrorCode.ERR_DefaultInterfaceImplementationModifier, "P01").WithArguments("public", "7", "7.1").WithLocation(4, 16), + // (5,19): error CS0106: The modifier 'protected' is not valid for this item + // protected int P02 {get;} + Diagnostic(ErrorCode.ERR_BadMemberFlag, "P02").WithArguments("protected").WithLocation(5, 19), + // (6,28): error CS0106: The modifier 'protected internal' is not valid for this item + // protected internal int P03 {set;} + Diagnostic(ErrorCode.ERR_BadMemberFlag, "P03").WithArguments("protected internal").WithLocation(6, 28), + // (7,18): error CS8503: The modifier 'internal' is not valid for this item in C# 7. Please use language version 7.1 or greater. + // internal int P04 {get;} + Diagnostic(ErrorCode.ERR_DefaultInterfaceImplementationModifier, "P04").WithArguments("internal", "7", "7.1").WithLocation(7, 18), + // (8,17): error CS8503: The modifier 'private' is not valid for this item in C# 7. Please use language version 7.1 or greater. + // private int P05 {set;} + Diagnostic(ErrorCode.ERR_DefaultInterfaceImplementationModifier, "P05").WithArguments("private", "7", "7.1").WithLocation(8, 17), + // (8,22): error CS0501: 'I1.P05.set' must declare a body because it is not marked abstract, extern, or partial + // private int P05 {set;} + Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "set").WithArguments("I1.P05.set").WithLocation(8, 22), + // (9,16): error CS8503: The modifier 'static' is not valid for this item in C# 7. Please use language version 7.1 or greater. + // static int P06 {get;} + Diagnostic(ErrorCode.ERR_DefaultInterfaceImplementationModifier, "P06").WithArguments("static", "7", "7.1").WithLocation(9, 16), + // (9,21): error CS0501: 'I1.P06.get' must declare a body because it is not marked abstract, extern, or partial + // static int P06 {get;} + Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "get").WithArguments("I1.P06.get").WithLocation(9, 21), + // (10,17): error CS8503: The modifier 'virtual' is not valid for this item in C# 7. Please use language version 7.1 or greater. + // virtual int P07 {set;} + Diagnostic(ErrorCode.ERR_DefaultInterfaceImplementationModifier, "P07").WithArguments("virtual", "7", "7.1").WithLocation(10, 17), + // (10,22): error CS0501: 'I1.P07.set' must declare a body because it is not marked abstract, extern, or partial + // virtual int P07 {set;} + Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "set").WithArguments("I1.P07.set").WithLocation(10, 22), + // (11,16): error CS8503: The modifier 'sealed' is not valid for this item in C# 7. Please use language version 7.1 or greater. + // sealed int P08 {get;} + Diagnostic(ErrorCode.ERR_DefaultInterfaceImplementationModifier, "P08").WithArguments("sealed", "7", "7.1").WithLocation(11, 16), + // (11,21): error CS0501: 'I1.P08.get' must declare a body because it is not marked abstract, extern, or partial + // sealed int P08 {get;} + Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "get").WithArguments("I1.P08.get").WithLocation(11, 21), + // (12,18): error CS0106: The modifier 'override' is not valid for this item + // override int P09 {set;} + Diagnostic(ErrorCode.ERR_BadMemberFlag, "P09").WithArguments("override").WithLocation(12, 18), + // (13,18): error CS8503: The modifier 'abstract' is not valid for this item in C# 7. Please use language version 7.1 or greater. + // abstract int P10 {get;} + Diagnostic(ErrorCode.ERR_DefaultInterfaceImplementationModifier, "P10").WithArguments("abstract", "7", "7.1").WithLocation(13, 18), + // (14,16): error CS8503: The modifier 'extern' is not valid for this item in C# 7. Please use language version 7.1 or greater. + // extern int P11 {get; set;} + Diagnostic(ErrorCode.ERR_DefaultInterfaceImplementationModifier, "P11").WithArguments("extern", "7", "7.1").WithLocation(14, 16), + // (16,22): error CS8503: The modifier 'public' is not valid for this item in C# 7. Please use language version 7.1 or greater. + // int P12 { public get; set;} + Diagnostic(ErrorCode.ERR_DefaultInterfaceImplementationModifier, "get").WithArguments("public", "7", "7.1").WithLocation(16, 22), + // (16,22): error CS0273: The accessibility modifier of the 'I1.P12.get' accessor must be more restrictive than the property or indexer 'I1.P12' + // int P12 { public get; set;} + Diagnostic(ErrorCode.ERR_InvalidPropertyAccessMod, "get").WithArguments("I1.P12.get", "I1.P12").WithLocation(16, 22), + // (17,30): error CS0106: The modifier 'protected' is not valid for this item + // int P13 { get; protected set;} + Diagnostic(ErrorCode.ERR_BadMemberFlag, "set").WithArguments("protected").WithLocation(17, 30), + // (18,34): error CS0106: The modifier 'protected internal' is not valid for this item + // int P14 { protected internal get; set;} + Diagnostic(ErrorCode.ERR_BadMemberFlag, "get").WithArguments("protected internal").WithLocation(18, 34), + // (19,29): error CS8503: The modifier 'internal' is not valid for this item in C# 7. Please use language version 7.1 or greater. + // int P15 { get; internal set;} + Diagnostic(ErrorCode.ERR_DefaultInterfaceImplementationModifier, "set").WithArguments("internal", "7", "7.1").WithLocation(19, 29), + // (20,23): error CS8503: The modifier 'private' is not valid for this item in C# 7. Please use language version 7.1 or greater. + // int P16 { private get; set;} + Diagnostic(ErrorCode.ERR_DefaultInterfaceImplementationModifier, "get").WithArguments("private", "7", "7.1").WithLocation(20, 23), + // (20,23): error CS0442: 'I1.P16.get': abstract properties cannot have private accessors + // int P16 { private get; set;} + Diagnostic(ErrorCode.ERR_PrivateAbstractAccessor, "get").WithArguments("I1.P16.get").WithLocation(20, 23), + // (21,23): error CS8503: The modifier 'private' is not valid for this item in C# 7. Please use language version 7.1 or greater. + // int P17 { private get;} + Diagnostic(ErrorCode.ERR_DefaultInterfaceImplementationModifier, "get").WithArguments("private", "7", "7.1").WithLocation(21, 23), + // (21,9): error CS0276: 'I1.P17': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor + // int P17 { private get;} + Diagnostic(ErrorCode.ERR_AccessModMissingAccessor, "P17").WithArguments("I1.P17").WithLocation(21, 9), + // (14,21): warning CS0626: Method, operator, or accessor 'I1.P11.get' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. + // extern int P11 {get; set;} + Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "get").WithArguments("I1.P11.get").WithLocation(14, 21), + // (14,26): warning CS0626: Method, operator, or accessor 'I1.P11.set' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. + // extern int P11 {get; set;} + Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "set").WithArguments("I1.P11.set").WithLocation(14, 26) + ); + + ValidateSymbolsPropertyModifiers_01(compilation1); + } + + [Fact] + public void PropertyModifiers_03() + { + ValidatePropertyImplementation_101(@" +public interface I1 +{ + public virtual int P1 { get - { - System.Console.WriteLine(""get_P2""); + { + System.Console.WriteLine(""get P1""); return 0; - } - set - { - System.Console.WriteLine(""set_P2""); - } - } - sealed void M() - { - P2 = P2; + } } } -public interface I3 + +class Test1 : I1 +{} +"); + + ValidatePropertyImplementation_101(@" +public interface I1 { - private int P3 - { - set - { - System.Console.WriteLine(""set_P3""); - } - } - sealed void M() + public virtual int P1 { - P3 = 0; + get => Test1.GetP1(); } } -public interface I4 + +class Test1 : I1 { - private int P4 + public static int GetP1() { - get => GetP4(); - } - - private int GetP4() - { - System.Console.WriteLine(""get_P4""); + System.Console.WriteLine(""get P1""); return 0; - } - sealed void M() - { - var x = P4; } } -public interface I5 +"); + + ValidatePropertyImplementation_101(@" +public interface I1 { - private int P5 + public virtual int P1 => Test1.GetP1(); +} + +class Test1 : I1 +{ + public static int GetP1() { - get => GetP5(); - set => System.Console.WriteLine(""set_P5""); + System.Console.WriteLine(""get P1""); + return 0; } +} +"); - private int GetP5() - { - System.Console.WriteLine(""get_P5""); - return 0; - } - sealed void M() + ValidatePropertyImplementation_102(@" +public interface I1 +{ + public virtual int P1 { - P5 = P5; + get + { + System.Console.WriteLine(""get P1""); + return 0; + } + set + { + System.Console.WriteLine(""set P1""); + } } } -public interface I6 + +class Test1 : I1 +{} +"); + + ValidatePropertyImplementation_102(@" +public interface I1 { - private int P6 + public virtual int P1 { - set => System.Console.WriteLine(""set_P6""); + get => Test1.GetP1(); + set => System.Console.WriteLine(""set P1""); } - sealed void M() +} + +class Test1 : I1 +{ + public static int GetP1() { - P6 = 0; + System.Console.WriteLine(""get P1""); + return 0; } } -public interface I7 -{ - private int P7 => GetP7(); +"); - private int GetP7() - { - System.Console.WriteLine(""get_P7""); - return 0; - } - sealed void M() + ValidatePropertyImplementation_103(@" +public interface I1 +{ + public virtual int P1 { - var x = P7; + set + { + System.Console.WriteLine(""set P1""); + } } } -class Test1 : I1, I2, I3, I4, I5, I6, I7 +class Test1 : I1 +{} +"); + + ValidatePropertyImplementation_103(@" +public interface I1 { - static void Main() + public virtual int P1 { - I1 x1 = new Test1(); - x1.M(); - I2 x2 = new Test1(); - x2.M(); - I3 x3 = new Test1(); - x3.M(); - I4 x4 = new Test1(); - x4.M(); - I5 x5 = new Test1(); - x5.M(); - I6 x6 = new Test1(); - x6.M(); - I7 x7 = new Test1(); - x7.M(); + set => System.Console.WriteLine(""set P1""); } } -"; - ValidatePropertyModifiers_09(source1); +class Test1 : I1 +{} +"); } - private void ValidatePropertyModifiers_09(string source1) - { - var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All), - parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); - Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); - CompileAndVerify(compilation1, verify: false, symbolValidator: Validate); - - Validate(compilation1.SourceModule); - - void Validate(ModuleSymbol m) - { - var test1 = m.GlobalNamespace.GetTypeMember("Test1"); - - for (int i = 1; i <= 7; i++) - { - var i1 = m.GlobalNamespace.GetTypeMember("I" + i); - var p1 = GetSingleProperty(i1); - - Assert.False(p1.IsAbstract); - Assert.False(p1.IsVirtual); - Assert.False(p1.IsSealed); - Assert.False(p1.IsStatic); - Assert.False(p1.IsExtern); - Assert.False(p1.IsOverride); - Assert.Equal(Accessibility.Private, p1.DeclaredAccessibility); - Assert.Null(test1.FindImplementationForInterfaceMember(p1)); - - switch (i) - { - case 3: - case 6: - Assert.Null(p1.GetMethod); - ValidateAccessor(p1.SetMethod); - break; - case 1: - case 4: - case 7: - Assert.Null(p1.SetMethod); - ValidateAccessor(p1.GetMethod); - break; - default: - ValidateAccessor(p1.GetMethod); - ValidateAccessor(p1.SetMethod); - break; - } - - void ValidateAccessor(MethodSymbol accessor) - { - Assert.False(accessor.IsAbstract); - Assert.False(accessor.IsVirtual); - Assert.False(accessor.IsMetadataVirtual()); - Assert.False(accessor.IsSealed); - Assert.False(accessor.IsStatic); - Assert.False(accessor.IsExtern); - Assert.False(accessor.IsAsync); - Assert.False(accessor.IsOverride); - Assert.Equal(Accessibility.Private, accessor.DeclaredAccessibility); - Assert.Null(test1.FindImplementationForInterfaceMember(accessor)); - } - } - } - } - - [Fact] - public void PropertyModifiers_10() + [Fact] + public void PropertyModifiers_04() { var source1 = @" public interface I1 { - abstract private int P1 { get; } - - virtual private int P2 => 0; - - sealed private int P3 - { - get => 0; - set {} - } - - private int P4 {get;} = 0; -} - -class Test1 : I1 -{ + public virtual int P1 { get; } = 0; } "; var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics( - // (4,26): error CS0621: 'I1.P1': virtual or abstract members cannot be private - // abstract private int P1 { get; } - Diagnostic(ErrorCode.ERR_VirtualPrivate, "P1").WithArguments("I1.P1").WithLocation(4, 26), - // (6,25): error CS0621: 'I1.P2': virtual or abstract members cannot be private - // virtual private int P2 => 0; - Diagnostic(ErrorCode.ERR_VirtualPrivate, "P2").WithArguments("I1.P2").WithLocation(6, 25), - // (8,24): error CS0238: 'I1.P3' cannot be sealed because it is not an override - // sealed private int P3 - Diagnostic(ErrorCode.ERR_SealedNonOverride, "P3").WithArguments("I1.P3").WithLocation(8, 24), - // (14,17): error CS8052: Auto-implemented properties inside interfaces cannot have initializers. - // private int P4 {get;} = 0; - Diagnostic(ErrorCode.ERR_AutoPropertyInitializerInInterface, "P4").WithArguments("I1.P4").WithLocation(14, 17), - // (14,21): error CS0501: 'I1.P4.get' must declare a body because it is not marked abstract, extern, or partial - // private int P4 {get;} = 0; - Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "get").WithArguments("I1.P4.get").WithLocation(14, 21), - // (17,15): error CS0535: 'Test1' does not implement interface member 'I1.P1' - // class Test1 : I1 - Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test1", "I1.P1").WithLocation(17, 15) + // (4,24): error CS8052: Auto-implemented properties inside interfaces cannot have initializers. + // public virtual int P1 { get; } = 0; + Diagnostic(ErrorCode.ERR_AutoPropertyInitializerInInterface, "P1").WithArguments("I1.P1").WithLocation(4, 24), + // (4,29): error CS0501: 'I1.P1.get' must declare a body because it is not marked abstract, extern, or partial + // public virtual int P1 { get; } = 0; + Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "get").WithArguments("I1.P1.get").WithLocation(4, 29) ); - ValidatePropertyModifiers_10(compilation1); + ValidatePropertyModifiers_04(compilation1, "P1"); } - private static void ValidatePropertyModifiers_10(CSharpCompilation compilation1) + private static void ValidatePropertyModifiers_04(CSharpCompilation compilation1, string propertyName) { - var test1 = compilation1.GetTypeByMetadataName("Test1"); - var i1 = compilation1.GetTypeByMetadataName("I1"); - var p1 = i1.GetMembers().OfType().ElementAt(0); + var i1 = compilation1.GlobalNamespace.GetTypeMember("I1"); + var p1 = i1.GetMember(propertyName); var p1get = p1.GetMethod; - Assert.True(p1.IsAbstract); - Assert.False(p1.IsVirtual); + Assert.False(p1.IsAbstract); + Assert.True(p1.IsVirtual); Assert.False(p1.IsSealed); Assert.False(p1.IsStatic); Assert.False(p1.IsExtern); Assert.False(p1.IsOverride); - Assert.Equal(Accessibility.Private, p1.DeclaredAccessibility); - Assert.Null(test1.FindImplementationForInterfaceMember(p1)); + Assert.Equal(Accessibility.Public, p1.DeclaredAccessibility); - Assert.True(p1get.IsAbstract); - Assert.False(p1get.IsVirtual); + Assert.False(p1get.IsAbstract); + Assert.True(p1get.IsVirtual); Assert.True(p1get.IsMetadataVirtual()); Assert.False(p1get.IsSealed); Assert.False(p1get.IsStatic); Assert.False(p1get.IsExtern); Assert.False(p1get.IsAsync); Assert.False(p1get.IsOverride); - Assert.Equal(Accessibility.Private, p1get.DeclaredAccessibility); - Assert.Null(test1.FindImplementationForInterfaceMember(p1get)); - - var p2 = i1.GetMembers().OfType().ElementAt(1); - var p2get = p2.GetMethod; - - Assert.False(p2.IsAbstract); - Assert.True(p2.IsVirtual); - Assert.False(p2.IsSealed); - Assert.False(p2.IsStatic); - Assert.False(p2.IsExtern); - Assert.False(p2.IsOverride); - Assert.Equal(Accessibility.Private, p2.DeclaredAccessibility); - Assert.Same(p2, test1.FindImplementationForInterfaceMember(p2)); - - Assert.False(p2get.IsAbstract); - Assert.True(p2get.IsVirtual); - Assert.True(p2get.IsMetadataVirtual()); - Assert.False(p2get.IsSealed); - Assert.False(p2get.IsStatic); - Assert.False(p2get.IsExtern); - Assert.False(p2get.IsAsync); - Assert.False(p2get.IsOverride); - Assert.Equal(Accessibility.Private, p2get.DeclaredAccessibility); - Assert.Same(p2get, test1.FindImplementationForInterfaceMember(p2get)); - - var p3 = i1.GetMembers().OfType().ElementAt(2); - - Assert.False(p3.IsAbstract); - Assert.False(p3.IsVirtual); - Assert.True(p3.IsSealed); - Assert.False(p3.IsStatic); - Assert.False(p3.IsExtern); - Assert.False(p3.IsOverride); - Assert.Equal(Accessibility.Private, p3.DeclaredAccessibility); - Assert.Null(test1.FindImplementationForInterfaceMember(p3)); - - ValidateP3Accessor(p3.GetMethod); - ValidateP3Accessor(p3.SetMethod); - void ValidateP3Accessor(MethodSymbol accessor) - { - Assert.False(accessor.IsAbstract); - Assert.False(accessor.IsVirtual); - Assert.False(accessor.IsMetadataVirtual()); - Assert.True(accessor.IsSealed); - Assert.False(accessor.IsStatic); - Assert.False(accessor.IsExtern); - Assert.False(accessor.IsAsync); - Assert.False(accessor.IsOverride); - Assert.Equal(Accessibility.Private, accessor.DeclaredAccessibility); - Assert.Null(test1.FindImplementationForInterfaceMember(accessor)); - } - - var p4 = i1.GetMembers().OfType().ElementAt(3); - var p4get = p4.GetMethod; - - Assert.False(p4.IsAbstract); - Assert.False(p4.IsVirtual); - Assert.False(p4.IsSealed); - Assert.False(p4.IsStatic); - Assert.False(p4.IsExtern); - Assert.False(p4.IsOverride); - Assert.Equal(Accessibility.Private, p4.DeclaredAccessibility); - Assert.Null(test1.FindImplementationForInterfaceMember(p4)); - - Assert.False(p4get.IsAbstract); - Assert.False(p4get.IsVirtual); - Assert.False(p4get.IsMetadataVirtual()); - Assert.False(p4get.IsSealed); - Assert.False(p4get.IsStatic); - Assert.False(p4get.IsExtern); - Assert.False(p4get.IsAsync); - Assert.False(p4get.IsOverride); - Assert.Equal(Accessibility.Private, p4get.DeclaredAccessibility); - Assert.Null(test1.FindImplementationForInterfaceMember(p4get)); + Assert.Equal(Accessibility.Public, p1get.DeclaredAccessibility); } [Fact] - public void PropertyModifiers_11() + public void PropertyModifiers_05() { var source1 = @" public interface I1 { - internal abstract int P1 {get; set;} - - sealed void Test() - { - P1 = P1; - } + public abstract int P1 {get; set;} +} +public interface I2 +{ + int P2 {get; set;} } -"; - var source2 = -@" class Test1 : I1 { - static void Main() - { - I1 x = new Test1(); - x.Test(); - } - public int P1 { get @@ -8957,355 +8733,311 @@ public int P1 System.Console.WriteLine(""get_P1""); return 0; } - set + set => System.Console.WriteLine(""set_P1""); + } +} +class Test2 : I2 +{ + public int P2 + { + get { - System.Console.WriteLine(""set_P1""); + System.Console.WriteLine(""get_P2""); + return 0; } + set => System.Console.WriteLine(""set_P2""); + } + + static void Main() + { + I1 x = new Test1(); + x.P1 = x.P1; + I2 y = new Test2(); + y.P2 = y.P2; } } "; - ValidatePropertyModifiers_11(source1, source2, - // (2,15): error CS0535: 'Test2' does not implement interface member 'I1.P1' - // class Test2 : I1 - Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test2", "I1.P1").WithLocation(2, 15) - ); + ValidatePropertyModifiers_05(source1); } - private void ValidatePropertyModifiers_11(string source1, string source2, params DiagnosticDescription[] expected) - { - var compilation1 = CreateStandardCompilation(source1 + source2, options: TestOptions.DebugExe, + private void ValidatePropertyModifiers_05(string source1) + { + var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); - CompileAndVerify(compilation1, verify: false, symbolValidator: Validate1); - - Validate1(compilation1.SourceModule); - void Validate1(ModuleSymbol m) - { - var test1 = m.GlobalNamespace.GetTypeMember("Test1"); - var i1 = test1.Interfaces.Single(); - var p1 = GetSingleProperty(i1); - var test1P1 = GetSingleProperty(test1); - var p1get = p1.GetMethod; - var p1set = p1.SetMethod; - - ValidateProperty(p1); - ValidateMethod(p1get); - ValidateMethod(p1set); - Assert.Same(test1P1, test1.FindImplementationForInterfaceMember(p1)); - Assert.Same(test1P1.GetMethod, test1.FindImplementationForInterfaceMember(p1get)); - Assert.Same(test1P1.SetMethod, test1.FindImplementationForInterfaceMember(p1set)); - } + CompileAndVerify(compilation1, expectedOutput: +@"get_P1 +set_P1 +get_P2 +set_P2", symbolValidator: Validate); - void ValidateProperty(PropertySymbol p1) - { - Assert.True(p1.IsAbstract); - Assert.False(p1.IsVirtual); - Assert.False(p1.IsSealed); - Assert.False(p1.IsStatic); - Assert.False(p1.IsExtern); - Assert.False(p1.IsOverride); - Assert.Equal(Accessibility.Internal, p1.DeclaredAccessibility); - } + Validate(compilation1.SourceModule); - void ValidateMethod(MethodSymbol m1) + void Validate(ModuleSymbol m) { - Assert.True(m1.IsAbstract); - Assert.False(m1.IsVirtual); - Assert.True(m1.IsMetadataVirtual()); - Assert.False(m1.IsSealed); - Assert.False(m1.IsStatic); - Assert.False(m1.IsExtern); - Assert.False(m1.IsAsync); - Assert.False(m1.IsOverride); - Assert.Equal(Accessibility.Internal, m1.DeclaredAccessibility); - } + for (int i = 1; i <= 2; i++) + { + var test1 = m.GlobalNamespace.GetTypeMember("Test" + i); + var i1 = m.GlobalNamespace.GetTypeMember("I" + i); + var p1 = GetSingleProperty(i1); + var test1P1 = GetSingleProperty(test1); - var compilation2 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, - parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); - Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); - compilation2.VerifyDiagnostics(); + Assert.True(p1.IsAbstract); + Assert.False(p1.IsVirtual); + Assert.False(p1.IsSealed); + Assert.False(p1.IsStatic); + Assert.False(p1.IsExtern); + Assert.False(p1.IsOverride); + Assert.Equal(Accessibility.Public, p1.DeclaredAccessibility); + Assert.Same(test1P1, test1.FindImplementationForInterfaceMember(p1)); - { - var i1 = compilation2.GetTypeByMetadataName("I1"); - var p1 = GetSingleProperty(i1); - var p1get = p1.GetMethod; - var p1set = p1.SetMethod; + ValidateAccessor(p1.GetMethod, test1P1.GetMethod); + ValidateAccessor(p1.SetMethod, test1P1.SetMethod); - ValidateProperty(p1); - ValidateMethod(p1get); - ValidateMethod(p1set); + void ValidateAccessor(MethodSymbol accessor, MethodSymbol implementation) + { + Assert.True(accessor.IsAbstract); + Assert.False(accessor.IsVirtual); + Assert.True(accessor.IsMetadataVirtual()); + Assert.False(accessor.IsSealed); + Assert.False(accessor.IsStatic); + Assert.False(accessor.IsExtern); + Assert.False(accessor.IsAsync); + Assert.False(accessor.IsOverride); + Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); + Assert.Same(implementation, test1.FindImplementationForInterfaceMember(accessor)); + } + } } + } - var compilation3 = CreateStandardCompilation(source2, new[] { compilation2.ToMetadataReference() }, options: TestOptions.DebugExe, - parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); - Assert.True(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); - CompileAndVerify(compilation3, verify: false, symbolValidator: Validate1); - - Validate1(compilation3.SourceModule); - - var compilation4 = CreateStandardCompilation(source2, new[] { compilation2.EmitToImageReference() }, options: TestOptions.DebugExe, - parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); - Assert.True(compilation4.Assembly.RuntimeSupportsDefaultInterfaceImplementation); - CompileAndVerify(compilation4, verify: false, symbolValidator: Validate1); - - Validate1(compilation4.SourceModule); - - var source3 = -@" -class Test2 : I1 -{ -} -"; - - var compilation5 = CreateStandardCompilation(source3, new[] { compilation2.ToMetadataReference() }, options: TestOptions.DebugDll, - parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); - Assert.True(compilation5.Assembly.RuntimeSupportsDefaultInterfaceImplementation); - compilation5.VerifyDiagnostics(expected); - - { - var test2 = compilation5.GetTypeByMetadataName("Test2"); - var i1 = compilation5.GetTypeByMetadataName("I1"); - var p1 = GetSingleProperty(i1); - Assert.Null(test2.FindImplementationForInterfaceMember(p1)); - Assert.Null(test2.FindImplementationForInterfaceMember(p1.GetMethod)); - Assert.Null(test2.FindImplementationForInterfaceMember(p1.SetMethod)); - } + private static PropertySymbol GetSingleProperty(NamedTypeSymbol container) + { + return container.GetMembers().OfType().Single(); + } - var compilation6 = CreateStandardCompilation(source3, new[] { compilation2.EmitToImageReference() }, options: TestOptions.DebugDll, - parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); - Assert.True(compilation6.Assembly.RuntimeSupportsDefaultInterfaceImplementation); - compilation6.VerifyDiagnostics(expected); + private static PropertySymbol GetSingleProperty(CSharpCompilation compilation, string containerName) + { + return GetSingleProperty(compilation.GetTypeByMetadataName(containerName)); + } - { - var test2 = compilation6.GetTypeByMetadataName("Test2"); - var i1 = compilation6.GetTypeByMetadataName("I1"); - var p1 = GetSingleProperty(i1); - Assert.Null(test2.FindImplementationForInterfaceMember(p1)); - Assert.Null(test2.FindImplementationForInterfaceMember(p1.GetMethod)); - Assert.Null(test2.FindImplementationForInterfaceMember(p1.SetMethod)); - } + private static PropertySymbol GetSingleProperty(ModuleSymbol m, string containerName) + { + return GetSingleProperty(m.GlobalNamespace.GetTypeMember(containerName)); } [Fact] - public void PropertyModifiers_12() + public void PropertyModifiers_06() { var source1 = @" public interface I1 { - internal abstract int P1 {get; set;} -} - -class Test1 : I1 -{ + public abstract int P1 {get; set;} } "; var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, - parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp7)); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics( - // (7,15): error CS0535: 'Test1' does not implement interface member 'I1.P1' - // class Test1 : I1 - Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test1", "I1.P1").WithLocation(7, 15) + // (4,25): error CS8503: The modifier 'abstract' is not valid for this item in C# 7. Please use language version 7.1 or greater. + // public abstract int P1 {get; set;} + Diagnostic(ErrorCode.ERR_DefaultInterfaceImplementationModifier, "P1").WithArguments("abstract", "7", "7.1").WithLocation(4, 25), + // (4,25): error CS8503: The modifier 'public' is not valid for this item in C# 7. Please use language version 7.1 or greater. + // public abstract int P1 {get; set;} + Diagnostic(ErrorCode.ERR_DefaultInterfaceImplementationModifier, "P1").WithArguments("public", "7", "7.1").WithLocation(4, 25) ); - var test1 = compilation1.GetTypeByMetadataName("Test1"); + ValidatePropertyModifiers_06(compilation1, "P1"); + } + + private static void ValidatePropertyModifiers_06(CSharpCompilation compilation1, string propertyName) + { var i1 = compilation1.GetTypeByMetadataName("I1"); - var p1 = i1.GetMember("P1"); - Assert.Null(test1.FindImplementationForInterfaceMember(p1)); - Assert.Null(test1.FindImplementationForInterfaceMember(p1.GetMethod)); - Assert.Null(test1.FindImplementationForInterfaceMember(p1.SetMethod)); + var p1 = i1.GetMember(propertyName); + + Assert.True(p1.IsAbstract); + Assert.False(p1.IsVirtual); + Assert.False(p1.IsSealed); + Assert.False(p1.IsStatic); + Assert.False(p1.IsExtern); + Assert.False(p1.IsOverride); + Assert.Equal(Accessibility.Public, p1.DeclaredAccessibility); + + ValidateAccessor(p1.GetMethod); + ValidateAccessor(p1.SetMethod); + + void ValidateAccessor(MethodSymbol accessor) + { + Assert.True(accessor.IsAbstract); + Assert.False(accessor.IsVirtual); + Assert.True(accessor.IsMetadataVirtual()); + Assert.False(accessor.IsSealed); + Assert.False(accessor.IsStatic); + Assert.False(accessor.IsExtern); + Assert.False(accessor.IsAsync); + Assert.False(accessor.IsOverride); + Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); + } } [Fact] - public void PropertyModifiers_13() + public void PropertyModifiers_07() { var source1 = @" public interface I1 { - public sealed int P1 + public static int P1 { get - { + { System.Console.WriteLine(""get_P1""); return 0; - } + } + set + { + System.Console.WriteLine(""set_P1""); + } } -} -public interface I2 -{ - public sealed int P2 + + internal static int P2 { get - { + { System.Console.WriteLine(""get_P2""); - return 0; - } + return P3; + } set - { + { System.Console.WriteLine(""set_P2""); - } + P3 = value; + } } -} -public interface I3 -{ - public sealed int P3 + + private static int P3 { - set - { - System.Console.WriteLine(""set_P3""); - } + get => Test1.GetP3(); + set => System.Console.WriteLine(""set_P3""); } -} -public interface I4 -{ - public sealed int P4 + + internal static int P4 => Test1.GetP4(); + + internal static int P5 { - get => GetP4(); + get + { + System.Console.WriteLine(""get_P5""); + return 0; + } } - private int GetP4() - { - System.Console.WriteLine(""get_P4""); - return 0; - } -} -public interface I5 -{ - public sealed int P5 + internal static int P6 { - get => GetP5(); - set => System.Console.WriteLine(""set_P5""); + get => Test1.GetP6(); } - private int GetP5() - { - System.Console.WriteLine(""get_P5""); - return 0; - } -} -public interface I6 -{ - public sealed int P6 + internal static int P7 { - set => System.Console.WriteLine(""set_P6""); + set + { + System.Console.WriteLine(""set_P7""); + } } -} -public interface I7 -{ - public sealed int P7 => GetP7(); - private int GetP7() - { - System.Console.WriteLine(""get_P7""); - return 0; - } + internal static int P8 + { + set => System.Console.WriteLine(""set_P8""); + } } class Test1 : I1 { static void Main() { - I1 i1 = new Test1(); - var x = i1.P1; - I2 i2 = new Test2(); - i2.P2 = i2.P2; - I3 i3 = new Test3(); - i3.P3 = x; - I4 i4 = new Test4(); - x = i4.P4; - I5 i5 = new Test5(); - i5.P5 = i5.P5; - I6 i6 = new Test6(); - i6.P6 = x; - I7 i7 = new Test7(); - x = i7.P7; + I1.P1 = I1.P1; + I1.P2 = I1.P2; + var x = I1.P4; + x = I1.P5; + x = I1.P6; + I1.P7 = x; + I1.P8 = x; } - public int P1 => throw null; -} -class Test2 : I2 -{ - public int P2 - { - get => throw null; - set => throw null; - } -} -class Test3 : I3 -{ - public int P3 - { - set => throw null; - } -} -class Test4 : I4 -{ - public int P4 + public static int GetP3() { - get => throw null; + System.Console.WriteLine(""get_P3""); + return 0; } -} -class Test5 : I5 -{ - public int P5 + + public static int GetP4() { - get => throw null; - set => throw null; + System.Console.WriteLine(""get_P4""); + return 0; } -} -class Test6 : I6 -{ - public int P6 + + public static int GetP6() { - set => throw null; + System.Console.WriteLine(""get_P6""); + return 0; } } -class Test7 : I7 -{ - public int P7 => throw null; -} "; - - ValidatePropertyModifiers_13(source1); - } - - private void ValidatePropertyModifiers_13(string source1) - { - var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugExe, + var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All), parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + CompileAndVerify(compilation1, expectedOutput: +@"get_P1 +set_P1 +get_P2 +get_P3 +set_P2 +set_P3 +get_P4 +get_P5 +get_P6 +set_P7 +set_P8", symbolValidator: Validate); + + Validate(compilation1.SourceModule); void Validate(ModuleSymbol m) { - for (int i = 1; i <= 7; i++) + var test1 = m.GlobalNamespace.GetTypeMember("Test1"); + var i1 = m.GlobalNamespace.GetTypeMember("I1"); + + foreach (var tuple in new[] { (name: "P1", access: Accessibility.Public), + (name: "P2", access: Accessibility.Internal), + (name: "P3", access: Accessibility.Private), + (name: "P4", access: Accessibility.Internal), + (name: "P5", access: Accessibility.Internal), + (name: "P6", access: Accessibility.Internal), + (name: "P7", access: Accessibility.Internal), + (name: "P8", access: Accessibility.Internal)}) { - var test1 = m.GlobalNamespace.GetTypeMember("Test" + i); - var i1 = m.GlobalNamespace.GetTypeMember("I" + i); - var p1 = GetSingleProperty(i1); + var p1 = i1.GetMember(tuple.name); Assert.False(p1.IsAbstract); Assert.False(p1.IsVirtual); Assert.False(p1.IsSealed); - Assert.False(p1.IsStatic); + Assert.True(p1.IsStatic); Assert.False(p1.IsExtern); Assert.False(p1.IsOverride); - Assert.Equal(Accessibility.Public, p1.DeclaredAccessibility); + Assert.Equal(tuple.access, p1.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(p1)); - switch (i) + switch (tuple.name) { - case 3: - case 6: + case "P7": + case "P8": Assert.Null(p1.GetMethod); ValidateAccessor(p1.SetMethod); break; - case 1: - case 4: - case 7: + case "P4": + case "P5": + case "P6": Assert.Null(p1.SetMethod); ValidateAccessor(p1.GetMethod); break; @@ -9321,2420 +9053,5291 @@ void ValidateAccessor(MethodSymbol accessor) Assert.False(accessor.IsVirtual); Assert.False(accessor.IsMetadataVirtual()); Assert.False(accessor.IsSealed); - Assert.False(accessor.IsStatic); + Assert.True(accessor.IsStatic); Assert.False(accessor.IsExtern); Assert.False(accessor.IsAsync); Assert.False(accessor.IsOverride); - Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); + Assert.Equal(tuple.access, accessor.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(accessor)); } } } - - CompileAndVerify(compilation1, verify: false, symbolValidator: Validate); - Validate(compilation1.SourceModule); } [Fact] - public void PropertyModifiers_14() + public void PropertyModifiers_08() { var source1 = @" public interface I1 { - public sealed int P1 {get;} = 0; -} -public interface I2 -{ - abstract sealed int P2 {get;} -} -public interface I3 -{ - virtual sealed int P3 - { - set {} - } + abstract static int P1 {get;} + + virtual static int P2 {set {}} + + sealed static int P3 => 0; + + static int P4 {get;} = 0; } -class Test1 : I1, I2, I3 +class Test1 : I1 { - int I1.P1 { get => throw null; } - int I2.P2 { get => throw null; } - int I3.P3 { set => throw null; } + int I1.P1 => 0; + int I1.P2 {set {}} + int I1.P3 => 0; + int I1.P4 {set {}} } -class Test2 : I1, I2, I3 +class Test2 : I1 {} "; - ValidatePropertyModifiers_14(source1, - // (4,23): error CS8052: Auto-implemented properties inside interfaces cannot have initializers. - // public sealed int P1 {get;} = 0; - Diagnostic(ErrorCode.ERR_AutoPropertyInitializerInInterface, "P1").WithArguments("I1.P1").WithLocation(4, 23), - // (4,27): error CS0501: 'I1.P1.get' must declare a body because it is not marked abstract, extern, or partial - // public sealed int P1 {get;} = 0; - Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "get").WithArguments("I1.P1.get").WithLocation(4, 27), - // (8,25): error CS0238: 'I2.P2' cannot be sealed because it is not an override - // abstract sealed int P2 {get;} - Diagnostic(ErrorCode.ERR_SealedNonOverride, "P2").WithArguments("I2.P2").WithLocation(8, 25), - // (12,24): error CS0238: 'I3.P3' cannot be sealed because it is not an override - // virtual sealed int P3 - Diagnostic(ErrorCode.ERR_SealedNonOverride, "P3").WithArguments("I3.P3").WithLocation(12, 24), - // (20,12): error CS0539: 'Test1.P1' in explicit interface declaration is not found among members of the interface that can be implemented - // int I1.P1 { get => throw null; } - Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "P1").WithArguments("Test1.P1").WithLocation(20, 12), - // (25,19): error CS0535: 'Test2' does not implement interface member 'I2.P2' - // class Test2 : I1, I2, I3 - Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I2").WithArguments("Test2", "I2.P2").WithLocation(25, 19) - ); - } - - private void ValidatePropertyModifiers_14(string source1, params DiagnosticDescription[] expected) - { var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); - compilation1.VerifyDiagnostics(expected); + compilation1.VerifyDiagnostics( + // (4,25): error CS0112: A static member 'I1.P1' cannot be marked as override, virtual, or abstract + // abstract static int P1 {get;} + Diagnostic(ErrorCode.ERR_StaticNotVirtual, "P1").WithArguments("I1.P1").WithLocation(4, 25), + // (6,24): error CS0112: A static member 'I1.P2' cannot be marked as override, virtual, or abstract + // virtual static int P2 {set {}} + Diagnostic(ErrorCode.ERR_StaticNotVirtual, "P2").WithArguments("I1.P2").WithLocation(6, 24), + // (8,23): error CS0238: 'I1.P3' cannot be sealed because it is not an override + // sealed static int P3 => 0; + Diagnostic(ErrorCode.ERR_SealedNonOverride, "P3").WithArguments("I1.P3").WithLocation(8, 23), + // (10,16): error CS8052: Auto-implemented properties inside interfaces cannot have initializers. + // static int P4 {get;} = 0; + Diagnostic(ErrorCode.ERR_AutoPropertyInitializerInInterface, "P4").WithArguments("I1.P4").WithLocation(10, 16), + // (10,20): error CS0501: 'I1.P4.get' must declare a body because it is not marked abstract, extern, or partial + // static int P4 {get;} = 0; + Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "get").WithArguments("I1.P4.get").WithLocation(10, 20), + // (15,12): error CS0539: 'Test1.P1' in explicit interface declaration is not found among members of the interface that can be implemented + // int I1.P1 => 0; + Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "P1").WithArguments("Test1.P1").WithLocation(15, 12), + // (16,12): error CS0539: 'Test1.P2' in explicit interface declaration is not found among members of the interface that can be implemented + // int I1.P2 {set {}} + Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "P2").WithArguments("Test1.P2").WithLocation(16, 12), + // (17,12): error CS0539: 'Test1.P3' in explicit interface declaration is not found among members of the interface that can be implemented + // int I1.P3 => 0; + Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "P3").WithArguments("Test1.P3").WithLocation(17, 12), + // (18,12): error CS0539: 'Test1.P4' in explicit interface declaration is not found among members of the interface that can be implemented + // int I1.P4 {set {}} + Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "P4").WithArguments("Test1.P4").WithLocation(18, 12) + ); var test1 = compilation1.GetTypeByMetadataName("Test1"); - var test2 = compilation1.GetTypeByMetadataName("Test2"); - var p1 = GetSingleProperty(compilation1, "I1"); + var i1 = compilation1.GetTypeByMetadataName("I1"); + var p1 = i1.GetMember("P1"); var p1get = p1.GetMethod; - Assert.False(p1.IsAbstract); + Assert.True(p1.IsAbstract); Assert.False(p1.IsVirtual); Assert.False(p1.IsSealed); - Assert.False(p1.IsStatic); + Assert.True(p1.IsStatic); Assert.False(p1.IsExtern); Assert.False(p1.IsOverride); Assert.Equal(Accessibility.Public, p1.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(p1)); - Assert.Null(test2.FindImplementationForInterfaceMember(p1)); - Assert.False(p1get.IsAbstract); + Assert.True(p1get.IsAbstract); Assert.False(p1get.IsVirtual); - Assert.False(p1get.IsMetadataVirtual()); + Assert.True(p1get.IsMetadataVirtual()); Assert.False(p1get.IsSealed); - Assert.False(p1get.IsStatic); + Assert.True(p1get.IsStatic); Assert.False(p1get.IsExtern); Assert.False(p1get.IsAsync); Assert.False(p1get.IsOverride); Assert.Equal(Accessibility.Public, p1get.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(p1get)); - Assert.Null(test2.FindImplementationForInterfaceMember(p1get)); - var p2 = GetSingleProperty(compilation1, "I2"); - var test1P2 = test1.GetMembers().OfType().Where(p => p.Name.StartsWith("I2.")).Single(); - var p2get = p2.GetMethod; + var p2 = i1.GetMember("P2"); + var p2set = p2.SetMethod; - Assert.True(p2.IsAbstract); - Assert.False(p2.IsVirtual); - Assert.True(p2.IsSealed); - Assert.False(p2.IsStatic); + Assert.False(p2.IsAbstract); + Assert.True(p2.IsVirtual); + Assert.False(p2.IsSealed); + Assert.True(p2.IsStatic); Assert.False(p2.IsExtern); Assert.False(p2.IsOverride); Assert.Equal(Accessibility.Public, p2.DeclaredAccessibility); - Assert.Same(test1P2, test1.FindImplementationForInterfaceMember(p2)); - Assert.Null(test2.FindImplementationForInterfaceMember(p2)); + Assert.Null(test1.FindImplementationForInterfaceMember(p2)); - Assert.True(p2get.IsAbstract); - Assert.False(p2get.IsVirtual); - Assert.True(p2get.IsMetadataVirtual()); - Assert.True(p2get.IsSealed); - Assert.False(p2get.IsStatic); - Assert.False(p2get.IsExtern); - Assert.False(p2get.IsAsync); - Assert.False(p2get.IsOverride); - Assert.Equal(Accessibility.Public, p2get.DeclaredAccessibility); - Assert.Same(test1P2.GetMethod, test1.FindImplementationForInterfaceMember(p2get)); - Assert.Null(test2.FindImplementationForInterfaceMember(p2get)); + Assert.False(p2set.IsAbstract); + Assert.True(p2set.IsVirtual); + Assert.True(p2set.IsMetadataVirtual()); + Assert.False(p2set.IsSealed); + Assert.True(p2set.IsStatic); + Assert.False(p2set.IsExtern); + Assert.False(p2set.IsAsync); + Assert.False(p2set.IsOverride); + Assert.Equal(Accessibility.Public, p2set.DeclaredAccessibility); + Assert.Null(test1.FindImplementationForInterfaceMember(p2set)); - var p3 = GetSingleProperty(compilation1, "I3"); - var test1P3 = test1.GetMembers().OfType().Where(p => p.Name.StartsWith("I3.")).Single(); - var p3set = p3.SetMethod; + var p3 = i1.GetMember("P3"); + var p3get = p3.GetMethod; Assert.False(p3.IsAbstract); - Assert.True(p3.IsVirtual); + Assert.False(p3.IsVirtual); Assert.True(p3.IsSealed); - Assert.False(p3.IsStatic); + Assert.True(p3.IsStatic); Assert.False(p3.IsExtern); Assert.False(p3.IsOverride); Assert.Equal(Accessibility.Public, p3.DeclaredAccessibility); - Assert.Same(test1P3, test1.FindImplementationForInterfaceMember(p3)); - Assert.Same(p3, test2.FindImplementationForInterfaceMember(p3)); + Assert.Null(test1.FindImplementationForInterfaceMember(p3)); - Assert.False(p3set.IsAbstract); - Assert.True(p3set.IsVirtual); - Assert.True(p3set.IsMetadataVirtual()); - Assert.True(p3set.IsSealed); - Assert.False(p3set.IsStatic); - Assert.False(p3set.IsExtern); - Assert.False(p3set.IsAsync); - Assert.False(p3set.IsOverride); - Assert.Equal(Accessibility.Public, p3set.DeclaredAccessibility); - Assert.Same(test1P3.SetMethod, test1.FindImplementationForInterfaceMember(p3set)); - Assert.Same(p3set, test2.FindImplementationForInterfaceMember(p3set)); + Assert.False(p3get.IsAbstract); + Assert.False(p3get.IsVirtual); + Assert.False(p3get.IsMetadataVirtual()); + Assert.True(p3get.IsSealed); + Assert.True(p3get.IsStatic); + Assert.False(p3get.IsExtern); + Assert.False(p3get.IsAsync); + Assert.False(p3get.IsOverride); + Assert.Equal(Accessibility.Public, p3get.DeclaredAccessibility); + Assert.Null(test1.FindImplementationForInterfaceMember(p3get)); } [Fact] - public void PropertyModifiers_15() + public void PropertyModifiers_09() { var source1 = @" -public interface I0 -{ - abstract virtual int P0 { get; set; } -} public interface I1 { - abstract virtual int P1 { get { throw null; } } + private int P1 + { + get + { + System.Console.WriteLine(""get_P1""); + return 0; + } + } + sealed void M() + { + var x = P1; + } } public interface I2 { - virtual abstract int P2 + private int P2 { - get { throw null; } - set { throw null; } + get + { + System.Console.WriteLine(""get_P2""); + return 0; + } + set + { + System.Console.WriteLine(""set_P2""); + } } -} -public interface I3 -{ - abstract virtual int P3 { set { throw null; } } -} -public interface I4 -{ - abstract virtual int P4 { get => throw null; } -} -public interface I5 -{ - abstract virtual int P5 + sealed void M() { - get => throw null; - set => throw null; + P2 = P2; } } -public interface I6 -{ - abstract virtual int P6 { set => throw null; } -} -public interface I7 -{ - abstract virtual int P7 => throw null; -} -public interface I8 -{ - abstract virtual int P8 {get;} = 0; -} - -class Test1 : I0, I1, I2, I3, I4, I5, I6, I7, I8 +public interface I3 { - int I0.P0 + private int P3 { - get { throw null; } - set { throw null; } + set + { + System.Console.WriteLine(""set_P3""); + } } - int I1.P1 + sealed void M() { - get { throw null; } + P3 = 0; } - int I2.P2 +} +public interface I4 +{ + private int P4 { - get { throw null; } - set { throw null; } + get => GetP4(); } - int I3.P3 + + private int GetP4() + { + System.Console.WriteLine(""get_P4""); + return 0; + } + sealed void M() { - set { throw null; } + var x = P4; } - int I4.P4 +} +public interface I5 +{ + private int P5 { - get { throw null; } + get => GetP5(); + set => System.Console.WriteLine(""set_P5""); } - int I5.P5 + + private int GetP5() + { + System.Console.WriteLine(""get_P5""); + return 0; + } + sealed void M() { - get { throw null; } - set { throw null; } + P5 = P5; } - int I6.P6 +} +public interface I6 +{ + private int P6 { - set { throw null; } + set => System.Console.WriteLine(""set_P6""); } - int I7.P7 + sealed void M() { - get { throw null; } + P6 = 0; } - int I8.P8 +} +public interface I7 +{ + private int P7 => GetP7(); + + private int GetP7() + { + System.Console.WriteLine(""get_P7""); + return 0; + } + sealed void M() { - get { throw null; } + var x = P7; } } -class Test2 : I0, I1, I2, I3, I4, I5, I6, I7, I8 -{} +class Test1 : I1, I2, I3, I4, I5, I6, I7 +{ + static void Main() + { + I1 x1 = new Test1(); + x1.M(); + I2 x2 = new Test1(); + x2.M(); + I3 x3 = new Test1(); + x3.M(); + I4 x4 = new Test1(); + x4.M(); + I5 x5 = new Test1(); + x5.M(); + I6 x6 = new Test1(); + x6.M(); + I7 x7 = new Test1(); + x7.M(); + } +} "; - ValidatePropertyModifiers_15(source1, - // (4,26): error CS0503: The abstract method 'I0.P0' cannot be marked virtual - // abstract virtual int P0 { get; set; } - Diagnostic(ErrorCode.ERR_AbstractNotVirtual, "P0").WithArguments("I0.P0"), - // (8,26): error CS0503: The abstract method 'I1.P1' cannot be marked virtual - // abstract virtual int P1 { get { throw null; } } - Diagnostic(ErrorCode.ERR_AbstractNotVirtual, "P1").WithArguments("I1.P1").WithLocation(8, 26), - // (8,31): error CS0500: 'I1.P1.get' cannot declare a body because it is marked abstract - // abstract virtual int P1 { get { throw null; } } - Diagnostic(ErrorCode.ERR_AbstractHasBody, "get").WithArguments("I1.P1.get").WithLocation(8, 31), - // (12,26): error CS0503: The abstract method 'I2.P2' cannot be marked virtual - // virtual abstract int P2 - Diagnostic(ErrorCode.ERR_AbstractNotVirtual, "P2").WithArguments("I2.P2").WithLocation(12, 26), - // (14,9): error CS0500: 'I2.P2.get' cannot declare a body because it is marked abstract - // get { throw null; } - Diagnostic(ErrorCode.ERR_AbstractHasBody, "get").WithArguments("I2.P2.get").WithLocation(14, 9), - // (15,9): error CS0500: 'I2.P2.set' cannot declare a body because it is marked abstract - // set { throw null; } - Diagnostic(ErrorCode.ERR_AbstractHasBody, "set").WithArguments("I2.P2.set").WithLocation(15, 9), - // (20,26): error CS0503: The abstract method 'I3.P3' cannot be marked virtual - // abstract virtual int P3 { set { throw null; } } - Diagnostic(ErrorCode.ERR_AbstractNotVirtual, "P3").WithArguments("I3.P3").WithLocation(20, 26), - // (20,31): error CS0500: 'I3.P3.set' cannot declare a body because it is marked abstract - // abstract virtual int P3 { set { throw null; } } - Diagnostic(ErrorCode.ERR_AbstractHasBody, "set").WithArguments("I3.P3.set").WithLocation(20, 31), - // (24,26): error CS0503: The abstract method 'I4.P4' cannot be marked virtual - // abstract virtual int P4 { get => throw null; } - Diagnostic(ErrorCode.ERR_AbstractNotVirtual, "P4").WithArguments("I4.P4").WithLocation(24, 26), - // (24,31): error CS0500: 'I4.P4.get' cannot declare a body because it is marked abstract - // abstract virtual int P4 { get => throw null; } - Diagnostic(ErrorCode.ERR_AbstractHasBody, "get").WithArguments("I4.P4.get").WithLocation(24, 31), - // (28,26): error CS0503: The abstract method 'I5.P5' cannot be marked virtual - // abstract virtual int P5 - Diagnostic(ErrorCode.ERR_AbstractNotVirtual, "P5").WithArguments("I5.P5").WithLocation(28, 26), - // (30,9): error CS0500: 'I5.P5.get' cannot declare a body because it is marked abstract - // get => throw null; - Diagnostic(ErrorCode.ERR_AbstractHasBody, "get").WithArguments("I5.P5.get").WithLocation(30, 9), - // (31,9): error CS0500: 'I5.P5.set' cannot declare a body because it is marked abstract - // set => throw null; - Diagnostic(ErrorCode.ERR_AbstractHasBody, "set").WithArguments("I5.P5.set").WithLocation(31, 9), - // (36,26): error CS0503: The abstract method 'I6.P6' cannot be marked virtual - // abstract virtual int P6 { set => throw null; } - Diagnostic(ErrorCode.ERR_AbstractNotVirtual, "P6").WithArguments("I6.P6").WithLocation(36, 26), - // (36,31): error CS0500: 'I6.P6.set' cannot declare a body because it is marked abstract - // abstract virtual int P6 { set => throw null; } - Diagnostic(ErrorCode.ERR_AbstractHasBody, "set").WithArguments("I6.P6.set").WithLocation(36, 31), - // (40,26): error CS0503: The abstract method 'I7.P7' cannot be marked virtual - // abstract virtual int P7 => throw null; - Diagnostic(ErrorCode.ERR_AbstractNotVirtual, "P7").WithArguments("I7.P7").WithLocation(40, 26), - // (40,32): error CS0500: 'I7.P7.get' cannot declare a body because it is marked abstract - // abstract virtual int P7 => throw null; - Diagnostic(ErrorCode.ERR_AbstractHasBody, "throw null").WithArguments("I7.P7.get").WithLocation(40, 32), - // (44,26): error CS0503: The abstract method 'I8.P8' cannot be marked virtual - // abstract virtual int P8 {get;} = 0; - Diagnostic(ErrorCode.ERR_AbstractNotVirtual, "P8").WithArguments("I8.P8").WithLocation(44, 26), - // (44,26): error CS8052: Auto-implemented properties inside interfaces cannot have initializers. - // abstract virtual int P8 {get;} = 0; - Diagnostic(ErrorCode.ERR_AutoPropertyInitializerInInterface, "P8").WithArguments("I8.P8").WithLocation(44, 26), - // (90,15): error CS0535: 'Test2' does not implement interface member 'I0.P0' - // class Test2 : I0, I1, I2, I3, I4, I5, I6, I7, I8 - Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I0").WithArguments("Test2", "I0.P0").WithLocation(90, 15), - // (90,19): error CS0535: 'Test2' does not implement interface member 'I1.P1' - // class Test2 : I0, I1, I2, I3, I4, I5, I6, I7, I8 - Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test2", "I1.P1").WithLocation(90, 19), - // (90,23): error CS0535: 'Test2' does not implement interface member 'I2.P2' - // class Test2 : I0, I1, I2, I3, I4, I5, I6, I7, I8 - Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I2").WithArguments("Test2", "I2.P2").WithLocation(90, 23), - // (90,27): error CS0535: 'Test2' does not implement interface member 'I3.P3' - // class Test2 : I0, I1, I2, I3, I4, I5, I6, I7, I8 - Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I3").WithArguments("Test2", "I3.P3").WithLocation(90, 27), - // (90,31): error CS0535: 'Test2' does not implement interface member 'I4.P4' - // class Test2 : I0, I1, I2, I3, I4, I5, I6, I7, I8 - Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I4").WithArguments("Test2", "I4.P4").WithLocation(90, 31), - // (90,35): error CS0535: 'Test2' does not implement interface member 'I5.P5' - // class Test2 : I0, I1, I2, I3, I4, I5, I6, I7, I8 - Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I5").WithArguments("Test2", "I5.P5").WithLocation(90, 35), - // (90,39): error CS0535: 'Test2' does not implement interface member 'I6.P6' - // class Test2 : I0, I1, I2, I3, I4, I5, I6, I7, I8 - Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I6").WithArguments("Test2", "I6.P6").WithLocation(90, 39), - // (90,43): error CS0535: 'Test2' does not implement interface member 'I7.P7' - // class Test2 : I0, I1, I2, I3, I4, I5, I6, I7, I8 - Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I7").WithArguments("Test2", "I7.P7").WithLocation(90, 43), - // (90,47): error CS0535: 'Test2' does not implement interface member 'I8.P8' - // class Test2 : I0, I1, I2, I3, I4, I5, I6, I7, I8 - Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I8").WithArguments("Test2", "I8.P8").WithLocation(90, 47) - ); + + ValidatePropertyModifiers_09(source1); } - private void ValidatePropertyModifiers_15(string source1, params DiagnosticDescription[] expected) + private void ValidatePropertyModifiers_09(string source1) { - var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, + var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All), parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); - compilation1.VerifyDiagnostics(expected); + CompileAndVerify(compilation1, verify: false, symbolValidator: Validate); - var test1 = compilation1.GetTypeByMetadataName("Test1"); - var test2 = compilation1.GetTypeByMetadataName("Test2"); + Validate(compilation1.SourceModule); - for (int i = 0; i <= 8; i++) + void Validate(ModuleSymbol m) { - var i1 = compilation1.GetTypeByMetadataName("I" + i); - var p2 = GetSingleProperty(i1); - var test1P2 = test1.GetMembers().OfType().Where(p => p.Name.StartsWith(i1.Name)).Single(); - - Assert.True(p2.IsAbstract); - Assert.True(p2.IsVirtual); - Assert.False(p2.IsSealed); - Assert.False(p2.IsStatic); - Assert.False(p2.IsExtern); - Assert.False(p2.IsOverride); - Assert.Equal(Accessibility.Public, p2.DeclaredAccessibility); - Assert.Same(test1P2, test1.FindImplementationForInterfaceMember(p2)); - Assert.Null(test2.FindImplementationForInterfaceMember(p2)); + var test1 = m.GlobalNamespace.GetTypeMember("Test1"); - switch (i) + for (int i = 1; i <= 7; i++) { - case 3: - case 6: - Assert.Null(p2.GetMethod); - ValidateAccessor(p2.SetMethod, test1P2.SetMethod); - break; - case 1: - case 4: - case 7: - case 8: - Assert.Null(p2.SetMethod); - ValidateAccessor(p2.GetMethod, test1P2.GetMethod); - break; - default: - ValidateAccessor(p2.GetMethod, test1P2.GetMethod); - ValidateAccessor(p2.SetMethod, test1P2.SetMethod); - break; - } + var i1 = m.GlobalNamespace.GetTypeMember("I" + i); + var p1 = GetSingleProperty(i1); - void ValidateAccessor(MethodSymbol accessor, MethodSymbol implementedBy) - { - Assert.True(accessor.IsAbstract); - Assert.True(accessor.IsVirtual); - Assert.True(accessor.IsMetadataVirtual()); - Assert.False(accessor.IsSealed); - Assert.False(accessor.IsStatic); - Assert.False(accessor.IsExtern); - Assert.False(accessor.IsAsync); - Assert.False(accessor.IsOverride); - Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); - Assert.Same(implementedBy, test1.FindImplementationForInterfaceMember(accessor)); - Assert.Null(test2.FindImplementationForInterfaceMember(accessor)); + Assert.False(p1.IsAbstract); + Assert.False(p1.IsVirtual); + Assert.False(p1.IsSealed); + Assert.False(p1.IsStatic); + Assert.False(p1.IsExtern); + Assert.False(p1.IsOverride); + Assert.Equal(Accessibility.Private, p1.DeclaredAccessibility); + Assert.Null(test1.FindImplementationForInterfaceMember(p1)); + + switch (i) + { + case 3: + case 6: + Assert.Null(p1.GetMethod); + ValidateAccessor(p1.SetMethod); + break; + case 1: + case 4: + case 7: + Assert.Null(p1.SetMethod); + ValidateAccessor(p1.GetMethod); + break; + default: + ValidateAccessor(p1.GetMethod); + ValidateAccessor(p1.SetMethod); + break; + } + + void ValidateAccessor(MethodSymbol accessor) + { + Assert.False(accessor.IsAbstract); + Assert.False(accessor.IsVirtual); + Assert.False(accessor.IsMetadataVirtual()); + Assert.False(accessor.IsSealed); + Assert.False(accessor.IsStatic); + Assert.False(accessor.IsExtern); + Assert.False(accessor.IsAsync); + Assert.False(accessor.IsOverride); + Assert.Equal(Accessibility.Private, accessor.DeclaredAccessibility); + Assert.Null(test1.FindImplementationForInterfaceMember(accessor)); + } } } } [Fact] - public void PropertyModifiers_16() + public void PropertyModifiers_10() { var source1 = @" public interface I1 { - extern int P1 {get;} -} -public interface I2 -{ - virtual extern int P2 {set;} -} -public interface I3 -{ - static extern int P3 {get; set;} -} -public interface I4 -{ - private extern int P4 {get;} -} -public interface I5 -{ - extern sealed int P5 {set;} -} + abstract private int P1 { get; } -class Test1 : I1, I2, I3, I4, I5 -{ + virtual private int P2 => 0; + + sealed private int P3 + { + get => 0; + set {} + } + + private int P4 {get;} = 0; } -class Test2 : I1, I2, I3, I4, I5 +class Test1 : I1 { - int I1.P1 => 0; - int I2.P2 { set {} } } "; - ValidatePropertyModifiers_16(source1); - } - - private void ValidatePropertyModifiers_16(string source1) - { - var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All), + var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); - CompileAndVerify(compilation1, verify: false, symbolValidator: Validate); + compilation1.VerifyDiagnostics( + // (4,26): error CS0621: 'I1.P1': virtual or abstract members cannot be private + // abstract private int P1 { get; } + Diagnostic(ErrorCode.ERR_VirtualPrivate, "P1").WithArguments("I1.P1").WithLocation(4, 26), + // (6,25): error CS0621: 'I1.P2': virtual or abstract members cannot be private + // virtual private int P2 => 0; + Diagnostic(ErrorCode.ERR_VirtualPrivate, "P2").WithArguments("I1.P2").WithLocation(6, 25), + // (8,24): error CS0238: 'I1.P3' cannot be sealed because it is not an override + // sealed private int P3 + Diagnostic(ErrorCode.ERR_SealedNonOverride, "P3").WithArguments("I1.P3").WithLocation(8, 24), + // (14,17): error CS8052: Auto-implemented properties inside interfaces cannot have initializers. + // private int P4 {get;} = 0; + Diagnostic(ErrorCode.ERR_AutoPropertyInitializerInInterface, "P4").WithArguments("I1.P4").WithLocation(14, 17), + // (14,21): error CS0501: 'I1.P4.get' must declare a body because it is not marked abstract, extern, or partial + // private int P4 {get;} = 0; + Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "get").WithArguments("I1.P4.get").WithLocation(14, 21), + // (17,15): error CS0535: 'Test1' does not implement interface member 'I1.P1' + // class Test1 : I1 + Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test1", "I1.P1").WithLocation(17, 15) + ); - Validate(compilation1.SourceModule); + ValidatePropertyModifiers_10(compilation1); + } - void Validate(ModuleSymbol m) - { - var test1 = m.GlobalNamespace.GetTypeMember("Test1"); - var test2 = m.GlobalNamespace.GetTypeMember("Test2"); - bool isSource = !(m is PEModuleSymbol); - var p1 = GetSingleProperty(m, "I1"); - var test2P1 = test2.GetMembers().OfType().Where(p => p.Name.StartsWith("I1.")).Single(); - var p1get = p1.GetMethod; + private static void ValidatePropertyModifiers_10(CSharpCompilation compilation1) + { + var test1 = compilation1.GetTypeByMetadataName("Test1"); + var i1 = compilation1.GetTypeByMetadataName("I1"); + var p1 = i1.GetMembers().OfType().ElementAt(0); + var p1get = p1.GetMethod; - Assert.False(p1.IsAbstract); - Assert.True(p1.IsVirtual); - Assert.False(p1.IsSealed); - Assert.False(p1.IsStatic); - Assert.Equal(isSource, p1.IsExtern); - Assert.False(p1.IsOverride); - Assert.Equal(Accessibility.Public, p1.DeclaredAccessibility); - Assert.Same(p1, test1.FindImplementationForInterfaceMember(p1)); - Assert.Same(test2P1, test2.FindImplementationForInterfaceMember(p1)); - - Assert.False(p1get.IsAbstract); - Assert.True(p1get.IsVirtual); - Assert.True(p1get.IsMetadataVirtual()); - Assert.False(p1get.IsSealed); - Assert.False(p1get.IsStatic); - Assert.Equal(isSource, p1get.IsExtern); - Assert.False(p1get.IsAsync); - Assert.False(p1get.IsOverride); - Assert.Equal(Accessibility.Public, p1get.DeclaredAccessibility); - Assert.Same(p1get, test1.FindImplementationForInterfaceMember(p1get)); - Assert.Same(test2P1.GetMethod, test2.FindImplementationForInterfaceMember(p1get)); - - var p2 = GetSingleProperty(m, "I2"); - var test2P2 = test2.GetMembers().OfType().Where(p => p.Name.StartsWith("I2.")).Single(); - var p2set = p2.SetMethod; - - Assert.False(p2.IsAbstract); - Assert.True(p2.IsVirtual); - Assert.False(p2.IsSealed); - Assert.False(p2.IsStatic); - Assert.Equal(isSource, p2.IsExtern); - Assert.False(p2.IsOverride); - Assert.Equal(Accessibility.Public, p2.DeclaredAccessibility); - Assert.Same(p2, test1.FindImplementationForInterfaceMember(p2)); - Assert.Same(test2P2, test2.FindImplementationForInterfaceMember(p2)); - - Assert.False(p2set.IsAbstract); - Assert.True(p2set.IsVirtual); - Assert.True(p2set.IsMetadataVirtual()); - Assert.False(p2set.IsSealed); - Assert.False(p2set.IsStatic); - Assert.Equal(isSource, p2set.IsExtern); - Assert.False(p2set.IsAsync); - Assert.False(p2set.IsOverride); - Assert.Equal(Accessibility.Public, p2set.DeclaredAccessibility); - Assert.Same(p2set, test1.FindImplementationForInterfaceMember(p2set)); - Assert.Same(test2P2.SetMethod, test2.FindImplementationForInterfaceMember(p2set)); - - var i3 = m.ContainingAssembly.GetTypeByMetadataName("I3"); - - if ((object)i3 != null) - { - var p3 = GetSingleProperty(i3); - - Assert.False(p3.IsAbstract); - Assert.False(p3.IsVirtual); - Assert.False(p3.IsSealed); - Assert.True(p3.IsStatic); - Assert.Equal(isSource, p3.IsExtern); - Assert.False(p3.IsOverride); - Assert.Equal(Accessibility.Public, p3.DeclaredAccessibility); - Assert.Null(test1.FindImplementationForInterfaceMember(p3)); - Assert.Null(test2.FindImplementationForInterfaceMember(p3)); - - ValidateP3Accessor(p3.GetMethod); - ValidateP3Accessor(p3.SetMethod); - void ValidateP3Accessor(MethodSymbol accessor) - { - Assert.False(accessor.IsAbstract); - Assert.False(accessor.IsVirtual); - Assert.False(accessor.IsMetadataVirtual()); - Assert.False(accessor.IsSealed); - Assert.True(accessor.IsStatic); - Assert.Equal(isSource, accessor.IsExtern); - Assert.False(accessor.IsAsync); - Assert.False(accessor.IsOverride); - Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); - Assert.Null(test1.FindImplementationForInterfaceMember(accessor)); - Assert.Null(test2.FindImplementationForInterfaceMember(accessor)); - } - } - - var p4 = GetSingleProperty(m, "I4"); - var p4get = p4.GetMethod; - - Assert.False(p4.IsAbstract); - Assert.False(p4.IsVirtual); - Assert.False(p4.IsSealed); - Assert.False(p4.IsStatic); - Assert.Equal(isSource, p4.IsExtern); - Assert.False(p4.IsOverride); - Assert.Equal(Accessibility.Private, p4.DeclaredAccessibility); - Assert.Null(test1.FindImplementationForInterfaceMember(p4)); - Assert.Null(test2.FindImplementationForInterfaceMember(p4)); - - Assert.False(p4get.IsAbstract); - Assert.False(p4get.IsVirtual); - Assert.False(p4get.IsMetadataVirtual()); - Assert.False(p4get.IsSealed); - Assert.False(p4get.IsStatic); - Assert.Equal(isSource, p4get.IsExtern); - Assert.False(p4get.IsAsync); - Assert.False(p4get.IsOverride); - Assert.Equal(Accessibility.Private, p4get.DeclaredAccessibility); - Assert.Null(test1.FindImplementationForInterfaceMember(p4get)); - Assert.Null(test2.FindImplementationForInterfaceMember(p4get)); - - var p5 = GetSingleProperty(m, "I5"); - var p5set = p5.SetMethod; - - Assert.False(p5.IsAbstract); - Assert.False(p5.IsVirtual); - Assert.False(p5.IsSealed); - Assert.False(p5.IsStatic); - Assert.Equal(isSource, p5.IsExtern); - Assert.False(p5.IsOverride); - Assert.Equal(Accessibility.Public, p5.DeclaredAccessibility); - Assert.Null(test1.FindImplementationForInterfaceMember(p5)); - Assert.Null(test2.FindImplementationForInterfaceMember(p5)); - - Assert.False(p5set.IsAbstract); - Assert.False(p5set.IsVirtual); - Assert.False(p5set.IsMetadataVirtual()); - Assert.False(p5set.IsSealed); - Assert.False(p5set.IsStatic); - Assert.Equal(isSource, p5set.IsExtern); - Assert.False(p5set.IsAsync); - Assert.False(p5set.IsOverride); - Assert.Equal(Accessibility.Public, p5set.DeclaredAccessibility); - Assert.Null(test1.FindImplementationForInterfaceMember(p5set)); - Assert.Null(test2.FindImplementationForInterfaceMember(p5set)); - } - } - - [Fact] - public void PropertyModifiers_17() - { - var source1 = -@" -public interface I1 -{ - abstract extern int P1 {get;} -} -public interface I2 -{ - extern int P2 => 0; -} -public interface I3 -{ - static extern int P3 {get => 0; set => throw null;} -} -public interface I4 -{ - private extern int P4 { get {throw null;} set {throw null;}} -} -public interface I5 -{ - extern sealed int P5 {get;} = 0; -} - -class Test1 : I1, I2, I3, I4, I5 -{ -} - -class Test2 : I1, I2, I3, I4, I5 -{ - int I1.P1 => 0; - int I2.P2 => 0; - int I3.P3 { get => 0; set => throw null;} - int I4.P4 { get => 0; set => throw null;} - int I5.P5 => 0; -} -"; - ValidatePropertyModifiers_17(source1, - // (4,25): error CS0180: 'I1.P1' cannot be both extern and abstract - // abstract extern int P1 {get;} - Diagnostic(ErrorCode.ERR_AbstractAndExtern, "P1").WithArguments("I1.P1").WithLocation(4, 25), - // (8,22): error CS0179: 'I2.P2.get' cannot be extern and declare a body - // extern int P2 => 0; - Diagnostic(ErrorCode.ERR_ExternHasBody, "0").WithArguments("I2.P2.get").WithLocation(8, 22), - // (12,27): error CS0179: 'I3.P3.get' cannot be extern and declare a body - // static extern int P3 {get => 0; set => throw null;} - Diagnostic(ErrorCode.ERR_ExternHasBody, "get").WithArguments("I3.P3.get").WithLocation(12, 27), - // (12,37): error CS0179: 'I3.P3.set' cannot be extern and declare a body - // static extern int P3 {get => 0; set => throw null;} - Diagnostic(ErrorCode.ERR_ExternHasBody, "set").WithArguments("I3.P3.set").WithLocation(12, 37), - // (16,29): error CS0179: 'I4.P4.get' cannot be extern and declare a body - // private extern int P4 { get {throw null;} set {throw null;}} - Diagnostic(ErrorCode.ERR_ExternHasBody, "get").WithArguments("I4.P4.get").WithLocation(16, 29), - // (16,47): error CS0179: 'I4.P4.set' cannot be extern and declare a body - // private extern int P4 { get {throw null;} set {throw null;}} - Diagnostic(ErrorCode.ERR_ExternHasBody, "set").WithArguments("I4.P4.set").WithLocation(16, 47), - // (20,23): error CS8052: Auto-implemented properties inside interfaces cannot have initializers. - // extern sealed int P5 {get;} = 0; - Diagnostic(ErrorCode.ERR_AutoPropertyInitializerInInterface, "P5").WithArguments("I5.P5").WithLocation(20, 23), - // (23,15): error CS0535: 'Test1' does not implement interface member 'I1.P1' - // class Test1 : I1, I2, I3, I4, I5 - Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test1", "I1.P1").WithLocation(23, 15), - // (31,12): error CS0539: 'Test2.P3' in explicit interface declaration is not found among members of the interface that can be implemented - // int I3.P3 { get => 0; set => throw null;} - Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "P3").WithArguments("Test2.P3").WithLocation(31, 12), - // (32,12): error CS0539: 'Test2.P4' in explicit interface declaration is not found among members of the interface that can be implemented - // int I4.P4 { get => 0; set => throw null;} - Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "P4").WithArguments("Test2.P4").WithLocation(32, 12), - // (33,12): error CS0539: 'Test2.P5' in explicit interface declaration is not found among members of the interface that can be implemented - // int I5.P5 => 0; - Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "P5").WithArguments("Test2.P5").WithLocation(33, 12), - // (20,27): warning CS0626: Method, operator, or accessor 'I5.P5.get' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. - // extern sealed int P5 {get;} = 0; - Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "get").WithArguments("I5.P5.get").WithLocation(20, 27) - ); - } - - private void ValidatePropertyModifiers_17(string source1, params DiagnosticDescription[] expected) - { - var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, - parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); - Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); - compilation1.VerifyDiagnostics(expected); - - var test1 = compilation1.GetTypeByMetadataName("Test1"); - var test2 = compilation1.GetTypeByMetadataName("Test2"); - var p1 = GetSingleProperty(compilation1, "I1"); - var test2P1 = test2.GetMembers().OfType().Where(p => p.Name.StartsWith("I1.")).Single(); - var p1get = p1.GetMethod; - - Assert.True(p1.IsAbstract); - Assert.False(p1.IsVirtual); - Assert.False(p1.IsSealed); - Assert.False(p1.IsStatic); - Assert.True(p1.IsExtern); - Assert.False(p1.IsOverride); - Assert.Equal(Accessibility.Public, p1.DeclaredAccessibility); - Assert.Null(test1.FindImplementationForInterfaceMember(p1)); - Assert.Same(test2P1, test2.FindImplementationForInterfaceMember(p1)); + Assert.True(p1.IsAbstract); + Assert.False(p1.IsVirtual); + Assert.False(p1.IsSealed); + Assert.False(p1.IsStatic); + Assert.False(p1.IsExtern); + Assert.False(p1.IsOverride); + Assert.Equal(Accessibility.Private, p1.DeclaredAccessibility); + Assert.Null(test1.FindImplementationForInterfaceMember(p1)); Assert.True(p1get.IsAbstract); Assert.False(p1get.IsVirtual); Assert.True(p1get.IsMetadataVirtual()); Assert.False(p1get.IsSealed); Assert.False(p1get.IsStatic); - Assert.True(p1get.IsExtern); + Assert.False(p1get.IsExtern); Assert.False(p1get.IsAsync); Assert.False(p1get.IsOverride); - Assert.Equal(Accessibility.Public, p1get.DeclaredAccessibility); + Assert.Equal(Accessibility.Private, p1get.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(p1get)); - Assert.Same(test2P1.GetMethod, test2.FindImplementationForInterfaceMember(p1get)); - var p2 = GetSingleProperty(compilation1, "I2"); - var test2P2 = test2.GetMembers().OfType().Where(p => p.Name.StartsWith("I2.")).Single(); + var p2 = i1.GetMembers().OfType().ElementAt(1); var p2get = p2.GetMethod; Assert.False(p2.IsAbstract); Assert.True(p2.IsVirtual); Assert.False(p2.IsSealed); Assert.False(p2.IsStatic); - Assert.True(p2.IsExtern); + Assert.False(p2.IsExtern); Assert.False(p2.IsOverride); - Assert.Equal(Accessibility.Public, p2.DeclaredAccessibility); + Assert.Equal(Accessibility.Private, p2.DeclaredAccessibility); Assert.Same(p2, test1.FindImplementationForInterfaceMember(p2)); - Assert.Same(test2P2, test2.FindImplementationForInterfaceMember(p2)); Assert.False(p2get.IsAbstract); Assert.True(p2get.IsVirtual); Assert.True(p2get.IsMetadataVirtual()); Assert.False(p2get.IsSealed); Assert.False(p2get.IsStatic); - Assert.True(p2get.IsExtern); + Assert.False(p2get.IsExtern); Assert.False(p2get.IsAsync); Assert.False(p2get.IsOverride); - Assert.Equal(Accessibility.Public, p2get.DeclaredAccessibility); + Assert.Equal(Accessibility.Private, p2get.DeclaredAccessibility); Assert.Same(p2get, test1.FindImplementationForInterfaceMember(p2get)); - Assert.Same(test2P2.GetMethod, test2.FindImplementationForInterfaceMember(p2get)); - var p3 = GetSingleProperty(compilation1, "I3"); - var test2P3 = test2.GetMembers().OfType().Where(p => p.Name.StartsWith("I3.")).Single(); + var p3 = i1.GetMembers().OfType().ElementAt(2); Assert.False(p3.IsAbstract); - Assert.Equal(p3.IsIndexer, p3.IsVirtual); - Assert.False(p3.IsSealed); - Assert.Equal(!p3.IsIndexer, p3.IsStatic); - Assert.True(p3.IsExtern); + Assert.False(p3.IsVirtual); + Assert.True(p3.IsSealed); + Assert.False(p3.IsStatic); + Assert.False(p3.IsExtern); Assert.False(p3.IsOverride); - Assert.Equal(Accessibility.Public, p3.DeclaredAccessibility); - Assert.Same(p3.IsIndexer ? p3 : null, test1.FindImplementationForInterfaceMember(p3)); - Assert.Same(p3.IsIndexer ? test2P3 : null, test2.FindImplementationForInterfaceMember(p3)); + Assert.Equal(Accessibility.Private, p3.DeclaredAccessibility); + Assert.Null(test1.FindImplementationForInterfaceMember(p3)); - ValidateP3Accessor(p3.GetMethod, p3.IsIndexer ? test2P3.GetMethod : null); - ValidateP3Accessor(p3.SetMethod, p3.IsIndexer ? test2P3.SetMethod : null); - void ValidateP3Accessor(MethodSymbol accessor, MethodSymbol test2Implementation) + ValidateP3Accessor(p3.GetMethod); + ValidateP3Accessor(p3.SetMethod); + void ValidateP3Accessor(MethodSymbol accessor) { Assert.False(accessor.IsAbstract); - Assert.Equal(p3.IsIndexer, accessor.IsVirtual); - Assert.Equal(p3.IsIndexer, accessor.IsMetadataVirtual()); - Assert.False(accessor.IsSealed); - Assert.Equal(!p3.IsIndexer, accessor.IsStatic); - Assert.True(accessor.IsExtern); + Assert.False(accessor.IsVirtual); + Assert.False(accessor.IsMetadataVirtual()); + Assert.True(accessor.IsSealed); + Assert.False(accessor.IsStatic); + Assert.False(accessor.IsExtern); Assert.False(accessor.IsAsync); Assert.False(accessor.IsOverride); - Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); - Assert.Same(p3.IsIndexer ? accessor : null, test1.FindImplementationForInterfaceMember(accessor)); - Assert.Same(test2Implementation, test2.FindImplementationForInterfaceMember(accessor)); + Assert.Equal(Accessibility.Private, accessor.DeclaredAccessibility); + Assert.Null(test1.FindImplementationForInterfaceMember(accessor)); } - var p4 = GetSingleProperty(compilation1, "I4"); + var p4 = i1.GetMembers().OfType().ElementAt(3); + var p4get = p4.GetMethod; Assert.False(p4.IsAbstract); Assert.False(p4.IsVirtual); Assert.False(p4.IsSealed); Assert.False(p4.IsStatic); - Assert.True(p4.IsExtern); + Assert.False(p4.IsExtern); Assert.False(p4.IsOverride); Assert.Equal(Accessibility.Private, p4.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(p4)); - Assert.Null(test2.FindImplementationForInterfaceMember(p4)); - - ValidateP4Accessor(p4.GetMethod); - ValidateP4Accessor(p4.SetMethod); - void ValidateP4Accessor(MethodSymbol accessor) - { - Assert.False(accessor.IsAbstract); - Assert.False(accessor.IsVirtual); - Assert.False(accessor.IsMetadataVirtual()); - Assert.False(accessor.IsSealed); - Assert.False(accessor.IsStatic); - Assert.True(accessor.IsExtern); - Assert.False(accessor.IsAsync); - Assert.False(accessor.IsOverride); - Assert.Equal(Accessibility.Private, accessor.DeclaredAccessibility); - Assert.Null(test1.FindImplementationForInterfaceMember(accessor)); - Assert.Null(test2.FindImplementationForInterfaceMember(accessor)); - } - var p5 = GetSingleProperty(compilation1, "I5"); - var p5get = p5.GetMethod; - - Assert.False(p5.IsAbstract); - Assert.False(p5.IsVirtual); - Assert.False(p5.IsSealed); - Assert.False(p5.IsStatic); - Assert.True(p5.IsExtern); - Assert.False(p5.IsOverride); - Assert.Equal(Accessibility.Public, p5.DeclaredAccessibility); - Assert.Null(test1.FindImplementationForInterfaceMember(p5)); - Assert.Null(test2.FindImplementationForInterfaceMember(p5)); - - Assert.False(p5get.IsAbstract); - Assert.False(p5get.IsVirtual); - Assert.False(p5get.IsMetadataVirtual()); - Assert.False(p5get.IsSealed); - Assert.False(p5get.IsStatic); - Assert.True(p5get.IsExtern); - Assert.False(p5get.IsAsync); - Assert.False(p5get.IsOverride); - Assert.Equal(Accessibility.Public, p5get.DeclaredAccessibility); - Assert.Null(test1.FindImplementationForInterfaceMember(p5get)); - Assert.Null(test2.FindImplementationForInterfaceMember(p5get)); + Assert.False(p4get.IsAbstract); + Assert.False(p4get.IsVirtual); + Assert.False(p4get.IsMetadataVirtual()); + Assert.False(p4get.IsSealed); + Assert.False(p4get.IsStatic); + Assert.False(p4get.IsExtern); + Assert.False(p4get.IsAsync); + Assert.False(p4get.IsOverride); + Assert.Equal(Accessibility.Private, p4get.DeclaredAccessibility); + Assert.Null(test1.FindImplementationForInterfaceMember(p4get)); } [Fact] - public void PropertyModifiers_18() + public void PropertyModifiers_11_01() { var source1 = @" public interface I1 { - abstract int P1 {get => 0; set => throw null;} -} -public interface I2 -{ - abstract private int P2 => 0; -} -public interface I3 -{ - static extern int P3 {get; set;} -} -public interface I4 -{ - abstract static int P4 { get {throw null;} set {throw null;}} -} -public interface I5 -{ - override sealed int P5 {get;} = 0; -} + internal abstract int P1 {get; set;} -class Test1 : I1, I2, I3, I4, I5 -{ + sealed void Test() + { + P1 = P1; + } } +"; -class Test2 : I1, I2, I3, I4, I5 + var source2 = +@" +class Test1 : I1 { - int I1.P1 { get => 0; set => throw null;} - int I2.P2 => 0; - int I3.P3 { get => 0; set => throw null;} - int I4.P4 { get => 0; set => throw null;} - int I5.P5 => 0; + static void Main() + { + I1 x = new Test1(); + x.Test(); + } + + public int P1 + { + get + { + System.Console.WriteLine(""get_P1""); + return 0; + } + set + { + System.Console.WriteLine(""set_P1""); + } + } } "; - ValidatePropertyModifiers_18(source1, - // (4,22): error CS0500: 'I1.P1.get' cannot declare a body because it is marked abstract - // abstract int P1 {get => 0; set => throw null;} - Diagnostic(ErrorCode.ERR_AbstractHasBody, "get").WithArguments("I1.P1.get"), - // (4,32): error CS0500: 'I1.P1.set' cannot declare a body because it is marked abstract - // abstract int P1 {get => 0; set => throw null;} - Diagnostic(ErrorCode.ERR_AbstractHasBody, "set").WithArguments("I1.P1.set"), - // (8,26): error CS0621: 'I2.P2': virtual or abstract members cannot be private - // abstract private int P2 => 0; - Diagnostic(ErrorCode.ERR_VirtualPrivate, "P2").WithArguments("I2.P2").WithLocation(8, 26), - // (8,32): error CS0500: 'I2.P2.get' cannot declare a body because it is marked abstract - // abstract private int P2 => 0; - Diagnostic(ErrorCode.ERR_AbstractHasBody, "0").WithArguments("I2.P2.get").WithLocation(8, 32), - // (16,25): error CS0112: A static member 'I4.P4' cannot be marked as override, virtual, or abstract - // abstract static int P4 { get {throw null;} set {throw null;}} - Diagnostic(ErrorCode.ERR_StaticNotVirtual, "P4").WithArguments("I4.P4").WithLocation(16, 25), - // (16,30): error CS0500: 'I4.P4.get' cannot declare a body because it is marked abstract - // abstract static int P4 { get {throw null;} set {throw null;}} - Diagnostic(ErrorCode.ERR_AbstractHasBody, "get").WithArguments("I4.P4.get").WithLocation(16, 30), - // (16,48): error CS0500: 'I4.P4.set' cannot declare a body because it is marked abstract - // abstract static int P4 { get {throw null;} set {throw null;}} - Diagnostic(ErrorCode.ERR_AbstractHasBody, "set").WithArguments("I4.P4.set").WithLocation(16, 48), - // (20,25): error CS0106: The modifier 'override' is not valid for this item - // override sealed int P5 {get;} = 0; - Diagnostic(ErrorCode.ERR_BadMemberFlag, "P5").WithArguments("override").WithLocation(20, 25), - // (20,25): error CS8052: Auto-implemented properties inside interfaces cannot have initializers. - // override sealed int P5 {get;} = 0; - Diagnostic(ErrorCode.ERR_AutoPropertyInitializerInInterface, "P5").WithArguments("I5.P5").WithLocation(20, 25), - // (20,29): error CS0501: 'I5.P5.get' must declare a body because it is not marked abstract, extern, or partial - // override sealed int P5 {get;} = 0; - Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "get").WithArguments("I5.P5.get").WithLocation(20, 29), - // (23,15): error CS0535: 'Test1' does not implement interface member 'I1.P1' - // class Test1 : I1, I2, I3, I4, I5 - Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test1", "I1.P1").WithLocation(23, 15), - // (23,19): error CS0535: 'Test1' does not implement interface member 'I2.P2' - // class Test1 : I1, I2, I3, I4, I5 - Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I2").WithArguments("Test1", "I2.P2").WithLocation(23, 19), - // (31,12): error CS0539: 'Test2.P3' in explicit interface declaration is not found among members of the interface that can be implemented - // int I3.P3 { get => 0; set => throw null;} - Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "P3").WithArguments("Test2.P3").WithLocation(31, 12), - // (32,12): error CS0539: 'Test2.P4' in explicit interface declaration is not found among members of the interface that can be implemented - // int I4.P4 { get => 0; set => throw null;} - Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "P4").WithArguments("Test2.P4").WithLocation(32, 12), - // (33,12): error CS0539: 'Test2.P5' in explicit interface declaration is not found among members of the interface that can be implemented - // int I5.P5 => 0; - Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "P5").WithArguments("Test2.P5").WithLocation(33, 12), - // (12,27): warning CS0626: Method, operator, or accessor 'I3.P3.get' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. - // static extern int P3 {get; set;} - Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "get").WithArguments("I3.P3.get").WithLocation(12, 27), - // (12,32): warning CS0626: Method, operator, or accessor 'I3.P3.set' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. - // static extern int P3 {get; set;} - Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "set").WithArguments("I3.P3.set").WithLocation(12, 32) + + ValidatePropertyModifiers_11_01(source1, source2, + new DiagnosticDescription[] { + // (2,15): error CS8504: 'Test1' does not implement interface member 'I1.P1.get'. 'Test1.P1.get' cannot implicitly implement a non-public member. + // class Test1 : I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test1", "I1.P1.get", "Test1.P1.get").WithLocation(2, 15), + // (2,15): error CS8504: 'Test1' does not implement interface member 'I1.P1.set'. 'Test1.P1.set' cannot implicitly implement a non-public member. + // class Test1 : I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test1", "I1.P1.set", "Test1.P1.set").WithLocation(2, 15) + }, + // (2,15): error CS0535: 'Test2' does not implement interface member 'I1.P1' + // class Test2 : I1 + Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test2", "I1.P1").WithLocation(2, 15) ); } - private void ValidatePropertyModifiers_18(string source1, params DiagnosticDescription[] expected) - { - var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, + private void ValidatePropertyModifiers_11_01(string source1, string source2, + DiagnosticDescription[] expected1, + params DiagnosticDescription[] expected2) + { + var compilation1 = CreateStandardCompilation(source2 + source1, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); - compilation1.VerifyDiagnostics(expected); + compilation1.VerifyDiagnostics(expected1); - var test1 = compilation1.GetTypeByMetadataName("Test1"); - var test2 = compilation1.GetTypeByMetadataName("Test2"); - var p1 = GetSingleProperty(compilation1, "I1"); - var test2P1 = test2.GetMembers().OfType().Where(p => p.Name.StartsWith("I1.")).Single(); + ValidatePropertyModifiers_11(compilation1.SourceModule); + + var compilation2 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation2.VerifyDiagnostics(); + + { + var i1 = compilation2.GetTypeByMetadataName("I1"); + var p1 = GetSingleProperty(i1); + var p1get = p1.GetMethod; + var p1set = p1.SetMethod; + + ValidatePropertyModifiers_11(p1); + ValidatePropertyAccessorModifiers_11(p1get); + ValidatePropertyAccessorModifiers_11(p1set); + } + + var compilation3 = CreateStandardCompilation(source2, new[] { compilation2.ToMetadataReference() }, options: TestOptions.DebugExe, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation3.VerifyDiagnostics(expected1); + + ValidatePropertyModifiers_11(compilation3.SourceModule); + + var compilation4 = CreateStandardCompilation(source2, new[] { compilation2.EmitToImageReference() }, options: TestOptions.DebugExe, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation4.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation4.VerifyDiagnostics(expected1); + + ValidatePropertyModifiers_11(compilation4.SourceModule); + + var source3 = +@" +class Test2 : I1 +{ +} +"; + + var compilation5 = CreateStandardCompilation(source3, new[] { compilation2.ToMetadataReference() }, options: TestOptions.DebugDll, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation5.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation5.VerifyDiagnostics(expected2); + + ValidatePropertyNotImplemented_11(compilation5, "Test2"); + + var compilation6 = CreateStandardCompilation(source3, new[] { compilation2.EmitToImageReference() }, options: TestOptions.DebugDll, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation6.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation6.VerifyDiagnostics(expected2); + + ValidatePropertyNotImplemented_11(compilation6, "Test2"); + } + + private static void ValidatePropertyModifiers_11(ModuleSymbol m) + { + var test1 = m.GlobalNamespace.GetTypeMember("Test1"); + var i1 = test1.Interfaces.Single(); + var p1 = GetSingleProperty(i1); + var test1P1 = GetSingleProperty(test1); + var p1get = p1.GetMethod; + var p1set = p1.SetMethod; + + ValidatePropertyModifiers_11(p1); + ValidatePropertyAccessorModifiers_11(p1get); + ValidatePropertyAccessorModifiers_11(p1set); + Assert.Same(test1P1, test1.FindImplementationForInterfaceMember(p1)); + Assert.Same(test1P1.GetMethod, test1.FindImplementationForInterfaceMember(p1get)); + Assert.Same(test1P1.SetMethod, test1.FindImplementationForInterfaceMember(p1set)); + } + private static void ValidatePropertyModifiers_11(PropertySymbol p1) + { Assert.True(p1.IsAbstract); Assert.False(p1.IsVirtual); Assert.False(p1.IsSealed); Assert.False(p1.IsStatic); Assert.False(p1.IsExtern); Assert.False(p1.IsOverride); - Assert.Equal(Accessibility.Public, p1.DeclaredAccessibility); - Assert.Null(test1.FindImplementationForInterfaceMember(p1)); - Assert.Same(test2P1, test2.FindImplementationForInterfaceMember(p1)); + Assert.Equal(Accessibility.Internal, p1.DeclaredAccessibility); + } - ValidateP1Accessor(p1.GetMethod, test2P1.GetMethod); - ValidateP1Accessor(p1.SetMethod, test2P1.SetMethod); - void ValidateP1Accessor(MethodSymbol accessor, MethodSymbol implementation) - { - Assert.True(accessor.IsAbstract); - Assert.False(accessor.IsVirtual); - Assert.True(accessor.IsMetadataVirtual()); - Assert.False(accessor.IsSealed); - Assert.False(accessor.IsStatic); - Assert.False(accessor.IsExtern); - Assert.False(accessor.IsAsync); - Assert.False(accessor.IsOverride); - Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); - Assert.Null(test1.FindImplementationForInterfaceMember(accessor)); - Assert.Same(implementation, test2.FindImplementationForInterfaceMember(accessor)); - } + private static void ValidatePropertyAccessorModifiers_11(MethodSymbol m1) + { + Assert.True(m1.IsAbstract); + Assert.False(m1.IsVirtual); + Assert.True(m1.IsMetadataVirtual()); + Assert.False(m1.IsSealed); + Assert.False(m1.IsStatic); + Assert.False(m1.IsExtern); + Assert.False(m1.IsAsync); + Assert.False(m1.IsOverride); + Assert.Equal(Accessibility.Internal, m1.DeclaredAccessibility); + } - var p2 = GetSingleProperty(compilation1, "I2"); - var test2P2 = test2.GetMembers().OfType().Where(p => p.Name.StartsWith("I2.")).Single(); - var p2get = p2.GetMethod; + private static void ValidatePropertyNotImplemented_11(CSharpCompilation compilation, string className) + { + var test2 = compilation.GetTypeByMetadataName(className); + var i1 = compilation.GetTypeByMetadataName("I1"); + var p1 = GetSingleProperty(i1); + Assert.Null(test2.FindImplementationForInterfaceMember(p1)); + Assert.Null(test2.FindImplementationForInterfaceMember(p1.GetMethod)); + Assert.Null(test2.FindImplementationForInterfaceMember(p1.SetMethod)); + } - Assert.True(p2.IsAbstract); - Assert.False(p2.IsVirtual); - Assert.False(p2.IsSealed); - Assert.False(p2.IsStatic); - Assert.False(p2.IsExtern); - Assert.False(p2.IsOverride); - Assert.Equal(Accessibility.Private, p2.DeclaredAccessibility); - Assert.Null(test1.FindImplementationForInterfaceMember(p2)); - Assert.Same(test2P2, test2.FindImplementationForInterfaceMember(p2)); + [Fact] + public void PropertyModifiers_11_02() + { + var source1 = +@" +public interface I1 +{ + internal abstract int P1 {get; set;} +} - Assert.True(p2get.IsAbstract); - Assert.False(p2get.IsVirtual); - Assert.True(p2get.IsMetadataVirtual()); - Assert.False(p2get.IsSealed); - Assert.False(p2get.IsStatic); - Assert.False(p2get.IsExtern); - Assert.False(p2get.IsAsync); - Assert.False(p2get.IsOverride); - Assert.Equal(Accessibility.Private, p2get.DeclaredAccessibility); - Assert.Null(test1.FindImplementationForInterfaceMember(p2get)); - Assert.Same(test2P2.GetMethod, test2.FindImplementationForInterfaceMember(p2get)); +public class TestHelper +{ + public static void CallP1(I1 x) {x.P1 = x.P1;} +} +"; - var p3 = GetSingleProperty(compilation1, "I3"); - var test2P3 = test2.GetMembers().OfType().Where(p => p.Name.StartsWith("I3.")).Single(); + var source2 = +@" +class Test1 : I1 +{ + static void Main() + { + TestHelper.CallP1(new Test1()); + } - Assert.False(p3.IsAbstract); - Assert.Equal(p3.IsIndexer, p3.IsVirtual); - Assert.False(p3.IsSealed); - Assert.Equal(!p3.IsIndexer, p3.IsStatic); - Assert.True(p3.IsExtern); - Assert.False(p3.IsOverride); - Assert.Equal(Accessibility.Public, p3.DeclaredAccessibility); - Assert.Same(p3.IsIndexer ? p3 : null, test1.FindImplementationForInterfaceMember(p3)); - Assert.Same(p3.IsIndexer ? test2P3 : null, test2.FindImplementationForInterfaceMember(p3)); + public virtual int P1 + { + get + { + System.Console.WriteLine(""get_P1""); + return 0; + } + set + { + System.Console.WriteLine(""set_P1""); + } + } +} +"; - ValidateP3Accessor(p3.GetMethod, p3.IsIndexer ? test2P3.GetMethod : null); - ValidateP3Accessor(p3.SetMethod, p3.IsIndexer ? test2P3.SetMethod : null); - void ValidateP3Accessor(MethodSymbol accessor, MethodSymbol implementation) - { - Assert.False(accessor.IsAbstract); - Assert.Equal(p3.IsIndexer, accessor.IsVirtual); - Assert.Equal(p3.IsIndexer, accessor.IsMetadataVirtual()); - Assert.False(accessor.IsSealed); - Assert.Equal(!p3.IsIndexer, accessor.IsStatic); - Assert.True(accessor.IsExtern); - Assert.False(accessor.IsAsync); - Assert.False(accessor.IsOverride); - Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); - Assert.Same(p3.IsIndexer ? accessor : null, test1.FindImplementationForInterfaceMember(accessor)); - Assert.Same(implementation, test2.FindImplementationForInterfaceMember(accessor)); - } + ValidatePropertyModifiers_11_02(source1, source2, + // (2,15): error CS8504: 'Test1' does not implement interface member 'I1.P1.get'. 'Test1.P1.get' cannot implicitly implement a non-public member. + // class Test1 : I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test1", "I1.P1.get", "Test1.P1.get").WithLocation(2, 15), + // (2,15): error CS8504: 'Test1' does not implement interface member 'I1.P1.set'. 'Test1.P1.set' cannot implicitly implement a non-public member. + // class Test1 : I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test1", "I1.P1.set", "Test1.P1.set").WithLocation(2, 15) + ); + } - var p4 = GetSingleProperty(compilation1, "I4"); - var test2P4 = test2.GetMembers().OfType().Where(p => p.Name.StartsWith("I4.")).Single(); + private void ValidatePropertyModifiers_11_02(string source1, string source2, + params DiagnosticDescription[] expected) + { + var compilation1 = CreateStandardCompilation(source2 + source1, options: TestOptions.DebugExe, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation1.VerifyDiagnostics(expected); - Assert.True(p4.IsAbstract); - Assert.False(p4.IsVirtual); - Assert.False(p4.IsSealed); - Assert.Equal(!p4.IsIndexer, p4.IsStatic); - Assert.False(p4.IsExtern); - Assert.False(p4.IsOverride); - Assert.Equal(Accessibility.Public, p4.DeclaredAccessibility); - Assert.Null(test1.FindImplementationForInterfaceMember(p4)); - Assert.Same(p4.IsIndexer ? test2P4 : null, test2.FindImplementationForInterfaceMember(p4)); + ValidatePropertyImplementation_11(compilation1.SourceModule); - ValidateP4Accessor(p4.GetMethod, p4.IsIndexer ? test2P4.GetMethod : null); - ValidateP4Accessor(p4.SetMethod, p4.IsIndexer ? test2P4.SetMethod : null); - void ValidateP4Accessor(MethodSymbol accessor, MethodSymbol implementation) - { - Assert.True(accessor.IsAbstract); - Assert.False(accessor.IsVirtual); - Assert.True(accessor.IsMetadataVirtual()); - Assert.False(accessor.IsSealed); - Assert.Equal(!p4.IsIndexer, accessor.IsStatic); - Assert.False(accessor.IsExtern); - Assert.False(accessor.IsAsync); - Assert.False(accessor.IsOverride); - Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); - Assert.Null(test1.FindImplementationForInterfaceMember(accessor)); - Assert.Same(implementation, test2.FindImplementationForInterfaceMember(accessor)); - } + var compilation2 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation2.VerifyDiagnostics(); - var p5 = GetSingleProperty(compilation1, "I5"); - var p5get = p5.GetMethod; + var compilation3 = CreateStandardCompilation(source2, new[] { compilation2.ToMetadataReference() }, options: TestOptions.DebugExe, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation3.VerifyDiagnostics(expected); - Assert.False(p5.IsAbstract); - Assert.False(p5.IsVirtual); - Assert.False(p5.IsSealed); - Assert.False(p5.IsStatic); - Assert.False(p5.IsExtern); - Assert.False(p5.IsOverride); - Assert.Equal(Accessibility.Public, p5.DeclaredAccessibility); - Assert.Null(test1.FindImplementationForInterfaceMember(p5)); - Assert.Null(test2.FindImplementationForInterfaceMember(p5)); + ValidatePropertyImplementation_11(compilation3.SourceModule); - Assert.False(p5get.IsAbstract); - Assert.False(p5get.IsVirtual); - Assert.False(p5get.IsMetadataVirtual()); - Assert.False(p5get.IsSealed); - Assert.False(p5get.IsStatic); - Assert.False(p5get.IsExtern); - Assert.False(p5get.IsAsync); - Assert.False(p5get.IsOverride); - Assert.Equal(Accessibility.Public, p5get.DeclaredAccessibility); - Assert.Null(test1.FindImplementationForInterfaceMember(p5get)); - Assert.Null(test2.FindImplementationForInterfaceMember(p5get)); + var compilation4 = CreateStandardCompilation(source2, new[] { compilation2.EmitToImageReference() }, options: TestOptions.DebugExe, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation4.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation4.VerifyDiagnostics(expected); + + ValidatePropertyImplementation_11(compilation4.SourceModule); + } + + private static void ValidatePropertyImplementation_11(ModuleSymbol m) + { + ValidatePropertyImplementation_11(m, implementedByBase: false); + } + + private static void ValidatePropertyImplementationByBase_11(ModuleSymbol m) + { + ValidatePropertyImplementation_11(m, implementedByBase: true); + } + + private static void ValidatePropertyImplementation_11(ModuleSymbol m, bool implementedByBase) + { + var test1 = m.GlobalNamespace.GetTypeMember("Test1"); + var i1 = test1.Interfaces.Where(i => i.Name == "I1").Single(); + var p1 = GetSingleProperty(i1); + var test1P1 = GetSingleProperty(implementedByBase ? test1.BaseType : test1); + var p1get = p1.GetMethod; + var p1set = p1.SetMethod; + + Assert.Same(test1P1, test1.FindImplementationForInterfaceMember(p1)); + + Assert.Same(test1P1.GetMethod, test1.FindImplementationForInterfaceMember(p1get)); + Assert.Same(test1P1.SetMethod, test1.FindImplementationForInterfaceMember(p1set)); + + var i2 = test1.Interfaces.Where(i => i.Name == "I2").SingleOrDefault(); + bool isMetadataVirtual = test1P1.IsVirtual || test1P1.IsAbstract || test1P1.IsExplicitInterfaceImplementation || + (!implementedByBase && (object)i2 != null && (object)test1P1 == test1.FindImplementationForInterfaceMember(GetSingleProperty(i2))); + Assert.Equal(isMetadataVirtual, test1P1.GetMethod.IsMetadataVirtual()); + Assert.Equal(isMetadataVirtual, test1P1.SetMethod.IsMetadataVirtual()); } [Fact] - public void PropertyModifiers_19() + public void PropertyModifiers_11_03() { var source1 = @" +public interface I1 +{ + internal abstract int P1 {get; set;} +} -public interface I2 {} +public class TestHelper +{ + public static void CallP1(I1 x) {x.P1 = x.P1;} +} +"; -public interface I1 + var source2 = +@" +class Test1 : I1 { - public int I2.P01 {get; set;} - protected int I2.P02 {get;} - protected internal int I2.P03 {set;} - internal int I2.P04 {get;} - private int I2.P05 {set;} - static int I2.P06 {get;} - virtual int I2.P07 {set;} - sealed int I2.P08 {get;} - override int I2.P09 {set;} - abstract int I2.P10 {get;} - extern int I2.P11 {get; set;} + static void Main() + { + TestHelper.CallP1(new Test1()); + } - int I2.P12 { public get; set;} - int I2.P13 { get; protected set;} - int I2.P14 { protected internal get; set;} - int I2.P15 { get; internal set;} - int I2.P16 { private get; set;} - int I2.P17 { private get;} + int I1.P1 + { + get + { + System.Console.WriteLine(""get_P1""); + return 0; + } + set + { + System.Console.WriteLine(""set_P1""); + } + } } "; - var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, + + ValidatePropertyModifiers_11_03(source1, source2, + // (9,12): error CS0122: 'I1.P1' is inaccessible due to its protection level + // int I1.P1 + Diagnostic(ErrorCode.ERR_BadAccess, "P1").WithArguments("I1.P1").WithLocation(9, 12) + ); + } + + private void ValidatePropertyModifiers_11_03(string source1, string source2, + params DiagnosticDescription[] expected) + { + var compilation1 = CreateStandardCompilation(source2 + source1, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); - var expected = new[] - { - // (7,19): error CS0106: The modifier 'public' is not valid for this item - // public int I2.P01 {get; set;} - Diagnostic(ErrorCode.ERR_BadMemberFlag, "P01").WithArguments("public").WithLocation(7, 19), - // (7,19): error CS0541: 'I1.P01': explicit interface declaration can only be declared in a class or struct - // public int I2.P01 {get; set;} - Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "P01").WithArguments("I1.P01").WithLocation(7, 19), - // (8,22): error CS0106: The modifier 'protected' is not valid for this item - // protected int I2.P02 {get;} - Diagnostic(ErrorCode.ERR_BadMemberFlag, "P02").WithArguments("protected").WithLocation(8, 22), - // (8,22): error CS0541: 'I1.P02': explicit interface declaration can only be declared in a class or struct - // protected int I2.P02 {get;} - Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "P02").WithArguments("I1.P02").WithLocation(8, 22), - // (9,31): error CS0106: The modifier 'protected internal' is not valid for this item - // protected internal int I2.P03 {set;} - Diagnostic(ErrorCode.ERR_BadMemberFlag, "P03").WithArguments("protected internal").WithLocation(9, 31), - // (9,31): error CS0541: 'I1.P03': explicit interface declaration can only be declared in a class or struct - // protected internal int I2.P03 {set;} - Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "P03").WithArguments("I1.P03").WithLocation(9, 31), - // (10,21): error CS0106: The modifier 'internal' is not valid for this item - // internal int I2.P04 {get;} - Diagnostic(ErrorCode.ERR_BadMemberFlag, "P04").WithArguments("internal").WithLocation(10, 21), - // (10,21): error CS0541: 'I1.P04': explicit interface declaration can only be declared in a class or struct - // internal int I2.P04 {get;} - Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "P04").WithArguments("I1.P04").WithLocation(10, 21), - // (11,20): error CS0106: The modifier 'private' is not valid for this item - // private int I2.P05 {set;} - Diagnostic(ErrorCode.ERR_BadMemberFlag, "P05").WithArguments("private").WithLocation(11, 20), - // (11,20): error CS0541: 'I1.P05': explicit interface declaration can only be declared in a class or struct - // private int I2.P05 {set;} - Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "P05").WithArguments("I1.P05").WithLocation(11, 20), - // (12,19): error CS0106: The modifier 'static' is not valid for this item - // static int I2.P06 {get;} - Diagnostic(ErrorCode.ERR_BadMemberFlag, "P06").WithArguments("static").WithLocation(12, 19), - // (12,19): error CS0541: 'I1.P06': explicit interface declaration can only be declared in a class or struct - // static int I2.P06 {get;} - Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "P06").WithArguments("I1.P06").WithLocation(12, 19), - // (13,20): error CS0106: The modifier 'virtual' is not valid for this item - // virtual int I2.P07 {set;} - Diagnostic(ErrorCode.ERR_BadMemberFlag, "P07").WithArguments("virtual").WithLocation(13, 20), - // (13,20): error CS0541: 'I1.P07': explicit interface declaration can only be declared in a class or struct - // virtual int I2.P07 {set;} - Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "P07").WithArguments("I1.P07").WithLocation(13, 20), - // (14,19): error CS0106: The modifier 'sealed' is not valid for this item - // sealed int I2.P08 {get;} - Diagnostic(ErrorCode.ERR_BadMemberFlag, "P08").WithArguments("sealed").WithLocation(14, 19), - // (14,19): error CS0541: 'I1.P08': explicit interface declaration can only be declared in a class or struct - // sealed int I2.P08 {get;} - Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "P08").WithArguments("I1.P08").WithLocation(14, 19), - // (15,21): error CS0106: The modifier 'override' is not valid for this item - // override int I2.P09 {set;} - Diagnostic(ErrorCode.ERR_BadMemberFlag, "P09").WithArguments("override").WithLocation(15, 21), - // (15,21): error CS0541: 'I1.P09': explicit interface declaration can only be declared in a class or struct - // override int I2.P09 {set;} - Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "P09").WithArguments("I1.P09").WithLocation(15, 21), - // (16,21): error CS0106: The modifier 'abstract' is not valid for this item - // abstract int I2.P10 {get;} - Diagnostic(ErrorCode.ERR_BadMemberFlag, "P10").WithArguments("abstract").WithLocation(16, 21), - // (16,21): error CS0541: 'I1.P10': explicit interface declaration can only be declared in a class or struct - // abstract int I2.P10 {get;} - Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "P10").WithArguments("I1.P10").WithLocation(16, 21), - // (17,19): error CS0106: The modifier 'extern' is not valid for this item - // extern int I2.P11 {get; set;} - Diagnostic(ErrorCode.ERR_BadMemberFlag, "P11").WithArguments("extern").WithLocation(17, 19), - // (17,19): error CS0541: 'I1.P11': explicit interface declaration can only be declared in a class or struct - // extern int I2.P11 {get; set;} - Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "P11").WithArguments("I1.P11").WithLocation(17, 19), - // (19,12): error CS0541: 'I1.P12': explicit interface declaration can only be declared in a class or struct - // int I2.P12 { public get; set;} - Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "P12").WithArguments("I1.P12").WithLocation(19, 12), - // (19,25): error CS0106: The modifier 'public' is not valid for this item - // int I2.P12 { public get; set;} - Diagnostic(ErrorCode.ERR_BadMemberFlag, "get").WithArguments("public").WithLocation(19, 25), - // (20,12): error CS0541: 'I1.P13': explicit interface declaration can only be declared in a class or struct - // int I2.P13 { get; protected set;} - Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "P13").WithArguments("I1.P13").WithLocation(20, 12), - // (20,33): error CS0106: The modifier 'protected' is not valid for this item - // int I2.P13 { get; protected set;} - Diagnostic(ErrorCode.ERR_BadMemberFlag, "set").WithArguments("protected").WithLocation(20, 33), - // (21,12): error CS0541: 'I1.P14': explicit interface declaration can only be declared in a class or struct - // int I2.P14 { protected internal get; set;} - Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "P14").WithArguments("I1.P14").WithLocation(21, 12), - // (21,37): error CS0106: The modifier 'protected internal' is not valid for this item - // int I2.P14 { protected internal get; set;} - Diagnostic(ErrorCode.ERR_BadMemberFlag, "get").WithArguments("protected internal").WithLocation(21, 37), - // (22,12): error CS0541: 'I1.P15': explicit interface declaration can only be declared in a class or struct - // int I2.P15 { get; internal set;} - Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "P15").WithArguments("I1.P15").WithLocation(22, 12), - // (22,32): error CS0106: The modifier 'internal' is not valid for this item - // int I2.P15 { get; internal set;} - Diagnostic(ErrorCode.ERR_BadMemberFlag, "set").WithArguments("internal").WithLocation(22, 32), - // (23,12): error CS0541: 'I1.P16': explicit interface declaration can only be declared in a class or struct - // int I2.P16 { private get; set;} - Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "P16").WithArguments("I1.P16").WithLocation(23, 12), - // (23,26): error CS0106: The modifier 'private' is not valid for this item - // int I2.P16 { private get; set;} - Diagnostic(ErrorCode.ERR_BadMemberFlag, "get").WithArguments("private").WithLocation(23, 26), - // (24,12): error CS0541: 'I1.P17': explicit interface declaration can only be declared in a class or struct - // int I2.P17 { private get;} - Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "P17").WithArguments("I1.P17").WithLocation(24, 12), - // (24,26): error CS0106: The modifier 'private' is not valid for this item - // int I2.P17 { private get;} - Diagnostic(ErrorCode.ERR_BadMemberFlag, "get").WithArguments("private").WithLocation(24, 26) - }; - - compilation1.VerifyDiagnostics(expected); + CompileAndVerify(compilation1, expectedOutput: +@"get_P1 +set_P1", verify: false, symbolValidator: ValidatePropertyImplementation_11); - ValidateSymbolsPropertyModifiers_19(compilation1); + ValidatePropertyImplementation_11(compilation1.SourceModule); var compilation2 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, - parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp7)); + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); - compilation2.VerifyDiagnostics(expected); + compilation2.VerifyDiagnostics(); - ValidateSymbolsPropertyModifiers_19(compilation2); + var compilation3 = CreateStandardCompilation(source2, new[] { compilation2.ToMetadataReference() }, options: TestOptions.DebugExe, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation3.VerifyDiagnostics(expected); + + ValidatePropertyImplementation_11(compilation3.SourceModule); + + var compilation4 = CreateStandardCompilation(source2, new[] { compilation2.EmitToImageReference() }, options: TestOptions.DebugExe, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation4.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation4.VerifyDiagnostics(expected); + + ValidatePropertyImplementation_11(compilation4.SourceModule); } - private static void ValidateSymbolsPropertyModifiers_19(CSharpCompilation compilation1) + [Fact] + public void PropertyModifiers_11_04() { - var i1 = compilation1.GetTypeByMetadataName("I1"); + var source1 = +@" +public interface I1 +{ + internal abstract int P1 {get; set;} +} - foreach (var propertyName in new[] { "I2.P01", "I2.P02", "I2.P03", "I2.P04", "I2.P05", "I2.P06", "I2.P07", "I2.P08", "I2.P09", "I2.P10", - "I2.P11", "I2.P12", "I2.P13", "I2.P14", "I2.P15", "I2.P16", "I2.P17" }) - { - ValidateSymbolsPropertyModifiers_19(i1.GetMember(propertyName)); +public class TestHelper +{ + public static void CallP1(I1 x) {x.P1 = x.P1;} +} - } +public class Test2 : I1 +{ + int I1.P1 + { + get + { + System.Console.WriteLine(""Test2.get_P1""); + return 0; } - - private static void ValidateSymbolsPropertyModifiers_19(PropertySymbol p01) + set { - Assert.True(p01.IsAbstract); - Assert.False(p01.IsVirtual); - Assert.False(p01.IsSealed); - Assert.False(p01.IsStatic); - Assert.False(p01.IsExtern); - Assert.False(p01.IsOverride); - Assert.Equal(Accessibility.Public, p01.DeclaredAccessibility); + System.Console.WriteLine(""Test2.set_P1""); + } + } +} - ValidateAccessor(p01.GetMethod); - ValidateAccessor(p01.SetMethod); +"; - void ValidateAccessor(MethodSymbol accessor) - { - if ((object)accessor == null) - { - return; - } + var source2 = +@" +class Test1 : Test2, I1 +{ + static void Main() + { + TestHelper.CallP1(new Test1()); + } - Assert.True(accessor.IsAbstract); - Assert.False(accessor.IsVirtual); - Assert.True(accessor.IsMetadataVirtual()); - Assert.False(accessor.IsSealed); - Assert.False(accessor.IsStatic); - Assert.False(accessor.IsExtern); - Assert.False(accessor.IsAsync); - Assert.False(accessor.IsOverride); - Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); - } + public int P1 + { + get + { + System.Console.WriteLine(""Test1.get_P1""); + return 0; + } + set + { + System.Console.WriteLine(""Test1.set_P1""); + } + } +} +"; + + ValidatePropertyModifiers_11_02(source1, source2, + // (2,22): error CS8504: 'Test1' does not implement interface member 'I1.P1.set'. 'Test1.P1.set' cannot implicitly implement a non-public member. + // class Test1 : Test2, I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test1", "I1.P1.set", "Test1.P1.set").WithLocation(2, 22), + // (2,22): error CS8504: 'Test1' does not implement interface member 'I1.P1.get'. 'Test1.P1.get' cannot implicitly implement a non-public member. + // class Test1 : Test2, I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test1", "I1.P1.get", "Test1.P1.get").WithLocation(2, 22) + ); } [Fact] - public void PropertyModifiers_20() + public void PropertyModifiers_11_05() { var source1 = @" public interface I1 { - internal int P1 + internal abstract int P1 {get; set;} +} + +public class TestHelper +{ + public static void CallP1(I1 x) {x.P1 = x.P1;} +} + +public class Test2 : I1 +{ + int I1.P1 { - get + get { - System.Console.WriteLine(""get_P1""); + System.Console.WriteLine(""Test2.get_P1""); return 0; } - set + set { - System.Console.WriteLine(""set_P1""); + System.Console.WriteLine(""Test2.set_P1""); } } - - void M2() {P1 = P1;} } + "; var source2 = @" -class Test1 : I1 +class Test1 : Test2, I1 { static void Main() { - I1 x = new Test1(); - x.M2(); + TestHelper.CallP1(new Test1()); + } + + public virtual int P1 + { + get + { + System.Console.WriteLine(""Test1.get_P1""); + return 0; + } + set + { + System.Console.WriteLine(""Test1.set_P1""); + } } } "; - ValidatePropertyModifiers_20(source1, source2); + ValidatePropertyModifiers_11_02(source1, source2, + // (2,22): error CS8504: 'Test1' does not implement interface member 'I1.P1.set'. 'Test1.P1.set' cannot implicitly implement a non-public member. + // class Test1 : Test2, I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test1", "I1.P1.set", "Test1.P1.set").WithLocation(2, 22), + // (2,22): error CS8504: 'Test1' does not implement interface member 'I1.P1.get'. 'Test1.P1.get' cannot implicitly implement a non-public member. + // class Test1 : Test2, I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test1", "I1.P1.get", "Test1.P1.get").WithLocation(2, 22) + ); } - private void ValidatePropertyModifiers_20(string source1, string source2) + [Fact] + public void PropertyModifiers_11_06() { - var compilation1 = CreateStandardCompilation(source1 + source2, options: TestOptions.DebugExe, - parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); - Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); - CompileAndVerify(compilation1, verify: false, symbolValidator: Validate1); - - Validate1(compilation1.SourceModule); + var source1 = +@" +public interface I1 +{ + internal abstract int P1 {get; set;} +} - void Validate1(ModuleSymbol m) - { - var test1 = m.GlobalNamespace.GetTypeMember("Test1"); - var i1 = test1.Interfaces.Single(); - var p1 = GetSingleProperty(i1); - var p1get = p1.GetMethod; - var p1set = p1.SetMethod; +public class TestHelper +{ + public static void CallP1(I1 x) {x.P1 = x.P1;} +} - ValidateProperty(p1); - ValidateMethod(p1get); - ValidateMethod(p1set); - Assert.Same(p1, test1.FindImplementationForInterfaceMember(p1)); - Assert.Same(p1get, test1.FindImplementationForInterfaceMember(p1get)); - Assert.Same(p1set, test1.FindImplementationForInterfaceMember(p1set)); - } - - void ValidateProperty(PropertySymbol p1) - { - Assert.False(p1.IsAbstract); - Assert.True(p1.IsVirtual); - Assert.False(p1.IsSealed); - Assert.False(p1.IsStatic); - Assert.False(p1.IsExtern); - Assert.False(p1.IsOverride); - Assert.Equal(Accessibility.Internal, p1.DeclaredAccessibility); - } - - void ValidateMethod(MethodSymbol m1) - { - Assert.False(m1.IsAbstract); - Assert.True(m1.IsVirtual); - Assert.True(m1.IsMetadataVirtual()); - Assert.False(m1.IsSealed); - Assert.False(m1.IsStatic); - Assert.False(m1.IsExtern); - Assert.False(m1.IsAsync); - Assert.False(m1.IsOverride); - Assert.Equal(Accessibility.Internal, m1.DeclaredAccessibility); - } - - var compilation2 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, - parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); - Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); - compilation2.VerifyDiagnostics(); - - { - var i1 = compilation2.GetTypeByMetadataName("I1"); - var p1 = GetSingleProperty(i1); - var p1get = p1.GetMethod; - var p1set = p1.SetMethod; - - ValidateProperty(p1); - ValidateMethod(p1get); - ValidateMethod(p1set); - } - - var compilation3 = CreateStandardCompilation(source2, new[] { compilation2.ToMetadataReference() }, options: TestOptions.DebugExe, - parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); - Assert.True(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); - CompileAndVerify(compilation3, verify: false, symbolValidator: Validate1); - - Validate1(compilation3.SourceModule); - - var compilation4 = CreateStandardCompilation(source2, new[] { compilation2.EmitToImageReference() }, options: TestOptions.DebugExe, - parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); - Assert.True(compilation4.Assembly.RuntimeSupportsDefaultInterfaceImplementation); - CompileAndVerify(compilation4, verify: false, symbolValidator: Validate1); - - Validate1(compilation4.SourceModule); +public class Test2 : I1 +{ + int I1.P1 + { + get + { + System.Console.WriteLine(""Test2.get_P1""); + return 0; } - - [Fact] - public void PropertyModifiers_21() + set { - var source1 = -@" -public interface I1 -{ - private static int P1 { get => throw null; set => throw null; } - - internal static int P2 { get => throw null; set => throw null; } - - public static int P3 { get => throw null; set => throw null; } - - static int P4 { get => throw null; set => throw null; } + System.Console.WriteLine(""Test2.set_P1""); + } + } } -class Test1 +"; + + var source2 = +@"abstract +class Test1 : Test2, I1 { static void Main() { - int x; - x = I1.P1; - I1.P1 = x; - x = I1.P2; - I1.P2 = x; - x = I1.P3; - I1.P3 = x; - x = I1.P4; - I1.P4 = x; + TestHelper.CallP1(new Test3()); } + + public abstract int P1 {get; set;} } -"; - var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, - parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); - Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); - compilation1.VerifyDiagnostics( - // (18,16): error CS0122: 'I1.P1' is inaccessible due to its protection level - // x = I1.P1; - Diagnostic(ErrorCode.ERR_BadAccess, "P1").WithArguments("I1.P1").WithLocation(18, 16), - // (19,12): error CS0122: 'I1.P1' is inaccessible due to its protection level - // I1.P1 = x; - Diagnostic(ErrorCode.ERR_BadAccess, "P1").WithArguments("I1.P1").WithLocation(19, 12) - ); - var source2 = -@" -class Test2 +class Test3 : Test1 { - static void Main() + public override int P1 { - int x; - x = I1.P1; - I1.P1 = x; - x = I1.P2; - I1.P2 = x; - x = I1.P3; - I1.P3 = x; - x = I1.P4; - I1.P4 = x; + get + { + System.Console.WriteLine(""Test3.get_P1""); + return 0; + } + set + { + System.Console.WriteLine(""Test3.set_P1""); + } } } "; - var compilation2 = CreateStandardCompilation(source2, new[] { compilation1.ToMetadataReference() }, - options: TestOptions.DebugDll, - parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); - Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); - compilation2.VerifyDiagnostics( - // (7,16): error CS0122: 'I1.P1' is inaccessible due to its protection level - // x = I1.P1; - Diagnostic(ErrorCode.ERR_BadAccess, "P1").WithArguments("I1.P1").WithLocation(7, 16), - // (8,12): error CS0122: 'I1.P1' is inaccessible due to its protection level - // I1.P1 = x; - Diagnostic(ErrorCode.ERR_BadAccess, "P1").WithArguments("I1.P1").WithLocation(8, 12), - // (9,16): error CS0122: 'I1.P2' is inaccessible due to its protection level - // x = I1.P2; - Diagnostic(ErrorCode.ERR_BadAccess, "P2").WithArguments("I1.P2").WithLocation(9, 16), - // (10,12): error CS0122: 'I1.P2' is inaccessible due to its protection level - // I1.P2 = x; - Diagnostic(ErrorCode.ERR_BadAccess, "P2").WithArguments("I1.P2").WithLocation(10, 12) + + ValidatePropertyModifiers_11_02(source1, source2, + // (2,22): error CS8504: 'Test1' does not implement interface member 'I1.P1.set'. 'Test1.P1.set' cannot implicitly implement a non-public member. + // class Test1 : Test2, I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test1", "I1.P1.set", "Test1.P1.set").WithLocation(2, 22), + // (2,22): error CS8504: 'Test1' does not implement interface member 'I1.P1.get'. 'Test1.P1.get' cannot implicitly implement a non-public member. + // class Test1 : Test2, I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test1", "I1.P1.get", "Test1.P1.get").WithLocation(2, 22) ); } [Fact] - public void PropertyModifiers_22() + public void PropertyModifiers_11_07() { var source1 = @" public interface I1 { - public int P1 + internal abstract int P1 {get; set;} +} + +public class TestHelper +{ + public static void CallP1(I1 x) {x.P1 = x.P1;} +} + +public class Test2 : I1 +{ + int I1.P1 { - internal get + get { - System.Console.WriteLine(""get_P1""); + System.Console.WriteLine(""Test2.get_P1""); return 0; } - set + set { - System.Console.WriteLine(""set_P1""); + System.Console.WriteLine(""Test2.set_P1""); } } } -public interface I2 + +"; + + var source2 = +@" +class Test1 : Test2, I1, I2 { - int P2 + static void Main() + { + TestHelper.CallP1(new Test1()); + } + + public int P1 { get { - System.Console.WriteLine(""get_P2""); + System.Console.WriteLine(""Test1.get_P1""); return 0; } - internal set + set { - System.Console.WriteLine(""set_P2""); + System.Console.WriteLine(""Test1.set_P1""); } } } -public interface I3 + +public interface I2 { - int P3 - { - internal get => Test1.GetP3(); - set => System.Console.WriteLine(""set_P3""); - } + int P1 {get; set;} } -public interface I4 +"; + + ValidatePropertyModifiers_11_02(source1, source2, + // (2,22): error CS8504: 'Test1' does not implement interface member 'I1.P1.set'. 'Test1.P1.set' cannot implicitly implement a non-public member. + // class Test1 : Test2, I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test1", "I1.P1.set", "Test1.P1.set").WithLocation(2, 22), + // (2,22): error CS8504: 'Test1' does not implement interface member 'I1.P1.get'. 'Test1.P1.get' cannot implicitly implement a non-public member. + // class Test1 : Test2, I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test1", "I1.P1.get", "Test1.P1.get").WithLocation(2, 22) + ); + } + + [Fact] + public void PropertyModifiers_11_08() + { + var source1 = +@" +public interface I1 { - int P4 - { - get => Test1.GetP4(); - internal set => System.Console.WriteLine(""set_P4""); - } + internal abstract int P1 {get; set;} } -public interface I5 + +public class TestHelper { - int P5 + public static void CallP1(I1 x) {x.P1 = x.P1;} +} + +public class Test2 : I1 +{ + int I1.P1 { - private get + get { - System.Console.WriteLine(""get_P5""); + System.Console.WriteLine(""Test2.get_P1""); return 0; } - set + set { - System.Console.WriteLine(""set_P5""); + System.Console.WriteLine(""Test2.set_P1""); } } +} - void Test() +"; + + var source2 = +@" +class Test1 : Test2, I1 +{ + static void Main() { - P5 = P5; + TestHelper.CallP1(new Test1()); } -} -public interface I6 -{ - int P6 + + public virtual long P1 { get { - System.Console.WriteLine(""get_P6""); + System.Console.WriteLine(""Test1.get_P1""); return 0; } - private set + set { - System.Console.WriteLine(""set_P6""); + System.Console.WriteLine(""Test1.set_P1""); } } - - void Test() - { - P6 = P6; - } } -public interface I7 -{ - int P7 - { - private get => Test1.GetP7(); - set => System.Console.WriteLine(""set_P7""); - } +"; - void Test() - { - P7 = P7; - } -} -public interface I8 -{ - int P8 - { - get => Test1.GetP8(); - private set => System.Console.WriteLine(""set_P8""); - } + ValidatePropertyModifiers_11_08(source1, source2); + } - void Test() - { - P8 = P8; - } -} + private void ValidatePropertyModifiers_11_08(string source1, string source2) + { + var compilation1 = CreateStandardCompilation(source2 + source1, options: TestOptions.DebugExe, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + CompileAndVerify(compilation1, expectedOutput: +@"Test2.get_P1 +Test2.set_P1", verify: false, symbolValidator: ValidatePropertyImplementationByBase_11); -class Test1 : I1, I2, I3, I4, I5, I6, I7, I8 -{ - static void Main() - { - I1 i1 = new Test1(); - I2 i2 = new Test1(); - I3 i3 = new Test1(); - I4 i4 = new Test1(); - I5 i5 = new Test1(); - I6 i6 = new Test1(); - I7 i7 = new Test1(); - I8 i8 = new Test1(); + ValidatePropertyImplementationByBase_11(compilation1.SourceModule); - i1.P1 = i1.P1; - i2.P2 = i2.P2; - i3.P3 = i3.P3; - i4.P4 = i4.P4; - i5.Test(); - i6.Test(); - i7.Test(); - i8.Test(); - } + var compilation2 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation2.VerifyDiagnostics(); - public static int GetP3() - { - System.Console.WriteLine(""get_P3""); - return 0; - } + var compilation3 = CreateStandardCompilation(source2, new[] { compilation2.ToMetadataReference() }, options: TestOptions.DebugExe, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + CompileAndVerify(compilation3, expectedOutput: +@"Test2.get_P1 +Test2.set_P1", verify: false, symbolValidator: ValidatePropertyImplementationByBase_11); - public static int GetP4() - { - System.Console.WriteLine(""get_P4""); - return 0; - } + ValidatePropertyImplementationByBase_11(compilation3.SourceModule); - public static int GetP7() + var compilation4 = CreateStandardCompilation(source2, new[] { compilation2.EmitToImageReference() }, options: TestOptions.DebugExe, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation4.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + CompileAndVerify(compilation4, expectedOutput: +@"Test2.get_P1 +Test2.set_P1", verify: false, symbolValidator: ValidatePropertyImplementationByBase_11); + + ValidatePropertyImplementationByBase_11(compilation4.SourceModule); + } + + [Fact] + public void PropertyModifiers_11_09() + { + var source1 = +@" +public interface I1 +{ + internal abstract int P1 {get; set;} +} + +public class TestHelper +{ + public static void CallP1(I1 x) {x.P1 = x.P1;} +} +"; + + var source2 = +@" +class Test1 : I1 +{ + static void Main() { - System.Console.WriteLine(""get_P7""); - return 0; + TestHelper.CallP1(new Test1()); } - public static int GetP8() + public virtual long P1 { - System.Console.WriteLine(""get_P8""); - return 0; + get + { + System.Console.WriteLine(""Test1.get_P1""); + return 0; + } + set + { + System.Console.WriteLine(""Test1.set_P1""); + } } } "; - ValidatePropertyModifiers_22(source1); + ValidatePropertyModifiers_11_09(source1, source2, + // (2,15): error CS0535: 'Test1' does not implement interface member 'I1.P1' + // class Test1 : I1 + Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test1", "I1.P1").WithLocation(2, 15) + ); } - private void ValidatePropertyModifiers_22(string source1) + private void ValidatePropertyModifiers_11_09(string source1, string source2, + params DiagnosticDescription[] expected) { - var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All), + var compilation1 = CreateStandardCompilation(source2 + source1, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); - CompileAndVerify(compilation1, /*expectedOutput: -@"get_P1 -set_P1 -get_P2 -set_P2 -get_P3 -set_P3 -get_P4 -set_P4 -get_P5 -set_P5 -get_P6 -set_P6 -get_P7 -set_P7 -get_P8 -set_P8",*/ symbolValidator: Validate, verify: false); + compilation1.VerifyDiagnostics(expected); - Validate(compilation1.SourceModule); + ValidatePropertyNotImplemented_11(compilation1, "Test1"); - void Validate(ModuleSymbol m) - { - var test1 = m.GlobalNamespace.GetTypeMember("Test1"); + var compilation2 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation2.VerifyDiagnostics(); - for (int i = 1; i <= 8; i++) - { - var i1 = m.GlobalNamespace.GetTypeMember("I" + i); - var p1 = GetSingleProperty(i1); + var compilation3 = CreateStandardCompilation(source2, new[] { compilation2.ToMetadataReference() }, options: TestOptions.DebugExe, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation3.VerifyDiagnostics(expected); - Assert.False(p1.IsAbstract); - Assert.True(p1.IsVirtual); - Assert.False(p1.IsSealed); - Assert.False(p1.IsStatic); - Assert.False(p1.IsExtern); - Assert.False(p1.IsOverride); - Assert.Equal(Accessibility.Public, p1.DeclaredAccessibility); - Assert.Same(p1, test1.FindImplementationForInterfaceMember(p1)); + ValidatePropertyNotImplemented_11(compilation3, "Test1"); - switch (i) - { - case 1: - case 3: - ValidateAccessor(p1.GetMethod, Accessibility.Internal); - ValidateAccessor(p1.SetMethod, Accessibility.Public); - break; - case 2: - case 4: - ValidateAccessor(p1.GetMethod, Accessibility.Public); - ValidateAccessor(p1.SetMethod, Accessibility.Internal); - break; - case 5: - case 7: - ValidateAccessor(p1.GetMethod, Accessibility.Private); - ValidateAccessor(p1.SetMethod, Accessibility.Public); - break; - case 6: - case 8: - ValidateAccessor(p1.GetMethod, Accessibility.Public); - ValidateAccessor(p1.SetMethod, Accessibility.Private); - break; - default: - Assert.False(true); - break; - } + var compilation4 = CreateStandardCompilation(source2, new[] { compilation2.EmitToImageReference() }, options: TestOptions.DebugExe, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation4.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation4.VerifyDiagnostics(expected); - void ValidateAccessor(MethodSymbol accessor, Accessibility access) - { - Assert.False(accessor.IsAbstract); - Assert.Equal(accessor.DeclaredAccessibility != Accessibility.Private, accessor.IsVirtual); - Assert.Equal(accessor.DeclaredAccessibility != Accessibility.Private, accessor.IsMetadataVirtual()); - Assert.False(accessor.IsSealed); - Assert.False(accessor.IsStatic); - Assert.False(accessor.IsExtern); - Assert.False(accessor.IsAsync); - Assert.False(accessor.IsOverride); - Assert.Equal(access, accessor.DeclaredAccessibility); - Assert.Same(accessor.DeclaredAccessibility == Accessibility.Private ? null : accessor, test1.FindImplementationForInterfaceMember(accessor)); - } - } - } + ValidatePropertyNotImplemented_11(compilation4, "Test1"); } [Fact] - public void PropertyModifiers_23() + public void PropertyModifiers_11_10() { var source1 = @" public interface I1 { - abstract int P1 {internal get; set;} - - void M2() - { - P1 = P1; - } + internal abstract int P1 {get; set;} } -public interface I3 +"; + + var source2 = +@" +public class Test2 : I1 { - int P3 + public int P1 { - private get + get { - System.Console.WriteLine(""get_P3""); return 0; - } + } set {} } - - void M2() - { - P3 = P3; - } } -public interface I4 +class Test1 : Test2, I1 { - int P4 - { - get {throw null;} - private set {System.Console.WriteLine(""set_P4"");} - } - - void M2() - { - P4 = P4; - } } -public interface I5 -{ - int P5 - { - private get => GetP5(); - set => throw null; - } +"; - private int GetP5() - { - System.Console.WriteLine(""get_P5""); - return 0; - } + ValidatePropertyModifiers_11_10(source1, source2, + // (2,22): error CS8504: 'Test2' does not implement interface member 'I1.P1.set'. 'Test2.P1.set' cannot implicitly implement a non-public member. + // public class Test2 : I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test2", "I1.P1.set", "Test2.P1.set").WithLocation(2, 22), + // (2,22): error CS8504: 'Test2' does not implement interface member 'I1.P1.get'. 'Test2.P1.get' cannot implicitly implement a non-public member. + // public class Test2 : I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test2", "I1.P1.get", "Test2.P1.get").WithLocation(2, 22) + ); + } - void M2() - { - P5 = P5; - } -} -public interface I6 -{ - int P6 - { - get => throw null; - private set => System.Console.WriteLine(""set_P6""); - } + private void ValidatePropertyModifiers_11_10(string source1, string source2, + params DiagnosticDescription[] expected) + { + var compilation1 = CreateStandardCompilation(source2 + source1, options: TestOptions.DebugDll, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation1.VerifyDiagnostics(expected); - void M2() - { - P6 = P6; - } -} -"; - - var source2 = -@" -class Test1 : I1 -{ - static void Main() - { - I1 i1 = new Test1(); - I3 i3 = new Test3(); - I4 i4 = new Test4(); - I5 i5 = new Test5(); - I6 i6 = new Test6(); - i1.M2(); - i3.M2(); - i4.M2(); - i5.M2(); - i6.M2(); - } - - public int P1 - { - get - { - System.Console.WriteLine(""get_P1""); - return 0; - } - set - { - System.Console.WriteLine(""set_P1""); - } - } -} -class Test3 : I3 -{ - public int P3 - { - get - { - throw null; - } - set - { - System.Console.WriteLine(""set_P3""); - } - } -} -class Test4 : I4 -{ - public int P4 - { - get - { - System.Console.WriteLine(""get_P4""); - return 0; - } - set - { - throw null; - } - } -} -class Test5 : I5 -{ - public int P5 - { - get - { - throw null; - } - set - { - System.Console.WriteLine(""set_P5""); - } - } -} -class Test6 : I6 -{ - public int P6 - { - get - { - System.Console.WriteLine(""get_P6""); - return 0; - } - set - { - throw null; - } - } -} -"; - ValidatePropertyModifiers_23(source1, source2); - } - - private void ValidatePropertyModifiers_23(string source1, string source2) - { - var compilation1 = CreateStandardCompilation(source1 + source2, options: TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All), - parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); - Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); - CompileAndVerify(compilation1, verify: false, symbolValidator: Validate1); - - Validate1(compilation1.SourceModule); - - void Validate1(ModuleSymbol m) - { - var test1 = m.GlobalNamespace.GetTypeMember("Test1"); - var im = test1.Interfaces.Single().ContainingModule; - - ValidateProperty(GetSingleProperty(im, "I1"), true, Accessibility.Internal, Accessibility.Public, test1); - ValidateProperty(GetSingleProperty(im, "I3"), false, Accessibility.Private, Accessibility.Public, m.GlobalNamespace.GetTypeMember("Test3")); - ValidateProperty(GetSingleProperty(im, "I4"), false, Accessibility.Public, Accessibility.Private, m.GlobalNamespace.GetTypeMember("Test4")); - ValidateProperty(GetSingleProperty(im, "I5"), false, Accessibility.Private, Accessibility.Public, m.GlobalNamespace.GetTypeMember("Test5")); - ValidateProperty(GetSingleProperty(im, "I6"), false, Accessibility.Public, Accessibility.Private, m.GlobalNamespace.GetTypeMember("Test6")); - } - - void ValidateProperty(PropertySymbol p1, bool isAbstract, Accessibility getAccess, Accessibility setAccess, NamedTypeSymbol test1 = null) - { - Assert.Equal(isAbstract, p1.IsAbstract); - Assert.NotEqual(isAbstract, p1.IsVirtual); - Assert.False(p1.IsSealed); - Assert.False(p1.IsStatic); - Assert.False(p1.IsExtern); - Assert.False(p1.IsOverride); - Assert.Equal(Accessibility.Public, p1.DeclaredAccessibility); - - if ((object)test1 != null) - { - Assert.Same(test1.GetMember(p1.Name), test1.FindImplementationForInterfaceMember(p1)); - } - - ValidateMethod(p1.GetMethod, isAbstract, getAccess, test1); - ValidateMethod(p1.SetMethod, isAbstract, setAccess, test1); - } - - void ValidateMethod(MethodSymbol m1, bool isAbstract, Accessibility access, NamedTypeSymbol test1) - { - Assert.Equal(isAbstract, m1.IsAbstract); - Assert.NotEqual(isAbstract || access == Accessibility.Private, m1.IsVirtual); - Assert.Equal(isAbstract || access != Accessibility.Private, m1.IsMetadataVirtual()); - Assert.False(m1.IsSealed); - Assert.False(m1.IsStatic); - Assert.False(m1.IsExtern); - Assert.False(m1.IsAsync); - Assert.False(m1.IsOverride); - Assert.Equal(access, m1.DeclaredAccessibility); - - if ((object)test1 != null) - { - Assert.Same(access != Accessibility.Private ? test1.GetMember(m1.Name) : null, test1.FindImplementationForInterfaceMember(m1)); - } - } + ValidatePropertyImplementationByBase_11(compilation1.SourceModule); var compilation2 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation2.VerifyDiagnostics(); - ValidateProperty(GetSingleProperty(compilation2, "I1"), true, Accessibility.Internal, Accessibility.Public); - ValidateProperty(GetSingleProperty(compilation2, "I3"), false, Accessibility.Private, Accessibility.Public); - ValidateProperty(GetSingleProperty(compilation2, "I4"), false, Accessibility.Public, Accessibility.Private); - ValidateProperty(GetSingleProperty(compilation2, "I5"), false, Accessibility.Private, Accessibility.Public); - ValidateProperty(GetSingleProperty(compilation2, "I6"), false, Accessibility.Public, Accessibility.Private); - - var compilation3 = CreateStandardCompilation(source2, new[] { compilation2.ToMetadataReference() }, - options: TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All), + var compilation3 = CreateStandardCompilation(source2, new[] { compilation2.ToMetadataReference() }, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); Assert.True(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); - CompileAndVerify(compilation3, verify: false, symbolValidator: Validate1); + compilation3.VerifyDiagnostics(expected); - Validate1(compilation3.SourceModule); + ValidatePropertyImplementationByBase_11(compilation3.SourceModule); - var compilation4 = CreateStandardCompilation(source2, new[] { compilation2.EmitToImageReference() }, - options: TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All), + var compilation4 = CreateStandardCompilation(source2, new[] { compilation2.EmitToImageReference() }, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); Assert.True(compilation4.Assembly.RuntimeSupportsDefaultInterfaceImplementation); - CompileAndVerify(compilation4, verify: false, symbolValidator: Validate1); + compilation4.VerifyDiagnostics(expected); - Validate1(compilation4.SourceModule); + ValidatePropertyImplementationByBase_11(compilation4.SourceModule); } [Fact] - public void PropertyModifiers_24() + public void PropertyModifiers_11_11() { var source1 = @" public interface I1 { - int P1 + internal abstract int P1 {get; set;} +} +public class Test2 : I1 +{ + public int P1 { - get + get { - System.Console.WriteLine(""get_P1""); return 0; } - internal set - { - System.Console.WriteLine(""set_P1""); - } + set {} } - - void M2() {P1 = P1;} } "; var source2 = @" -class Test1 : I1 +class Test1 : Test2, I1 { - static void Main() - { - I1 x = new Test1(); - x.M2(); - } } "; - ValidatePropertyModifiers_24(source1, source2); + + ValidatePropertyModifiers_11_11(source1, source2, + // (6,22): error CS8504: 'Test2' does not implement interface member 'I1.P1.set'. 'Test2.P1.set' cannot implicitly implement a non-public member. + // public class Test2 : I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test2", "I1.P1.set", "Test2.P1.set").WithLocation(6, 22), + // (6,22): error CS8504: 'Test2' does not implement interface member 'I1.P1.get'. 'Test2.P1.get' cannot implicitly implement a non-public member. + // public class Test2 : I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test2", "I1.P1.get", "Test2.P1.get").WithLocation(6, 22) + ); } - private void ValidatePropertyModifiers_24(string source1, string source2) + private void ValidatePropertyModifiers_11_11(string source1, string source2, + params DiagnosticDescription[] expected) { - var compilation1 = CreateStandardCompilation(source1 + source2, options: TestOptions.DebugExe, - parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); - Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); - CompileAndVerify(compilation1, verify: false, symbolValidator: Validate1); - - Validate1(compilation1.SourceModule); - - void Validate1(ModuleSymbol m) - { - var test1 = m.GlobalNamespace.GetTypeMember("Test1"); - var i1 = test1.Interfaces.Single(); - var p1 = GetSingleProperty(i1); - var p1get = p1.GetMethod; - var p1set = p1.SetMethod; - - ValidateProperty(p1); - ValidateMethod(p1get, Accessibility.Public); - ValidateMethod(p1set, Accessibility.Internal); - Assert.Same(p1, test1.FindImplementationForInterfaceMember(p1)); - Assert.Same(p1get, test1.FindImplementationForInterfaceMember(p1get)); - Assert.Same(p1set, test1.FindImplementationForInterfaceMember(p1set)); - } - - void ValidateProperty(PropertySymbol p1) - { - Assert.False(p1.IsAbstract); - Assert.True(p1.IsVirtual); - Assert.False(p1.IsSealed); - Assert.False(p1.IsStatic); - Assert.False(p1.IsExtern); - Assert.False(p1.IsOverride); - Assert.Equal(Accessibility.Public, p1.DeclaredAccessibility); - } - - void ValidateMethod(MethodSymbol m1, Accessibility access) - { - Assert.False(m1.IsAbstract); - Assert.True(m1.IsVirtual); - Assert.True(m1.IsMetadataVirtual()); - Assert.False(m1.IsSealed); - Assert.False(m1.IsStatic); - Assert.False(m1.IsExtern); - Assert.False(m1.IsAsync); - Assert.False(m1.IsOverride); - Assert.Equal(access, m1.DeclaredAccessibility); - } - var compilation2 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, - parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest), + assemblyName: "PropertyModifiers_11_11"); Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); - compilation2.VerifyDiagnostics(); - - { - var i1 = compilation2.GetTypeByMetadataName("I1"); - var p1 = GetSingleProperty(i1); - var p1get = p1.GetMethod; - var p1set = p1.SetMethod; - - ValidateProperty(p1); - ValidateMethod(p1get, Accessibility.Public); - ValidateMethod(p1set, Accessibility.Internal); - } + compilation2.VerifyDiagnostics(expected); - var compilation3 = CreateStandardCompilation(source2, new[] { compilation2.ToMetadataReference() }, options: TestOptions.DebugExe, + var compilation3 = CreateStandardCompilation(source2, new[] { compilation2.ToMetadataReference() }, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); Assert.True(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); - CompileAndVerify(compilation3, verify: false, symbolValidator: Validate1); + compilation3.VerifyDiagnostics(); - Validate1(compilation3.SourceModule); + ValidatePropertyImplementationByBase_11(compilation3.SourceModule); - var compilation4 = CreateStandardCompilation(source2, new[] { compilation2.EmitToImageReference() }, options: TestOptions.DebugExe, + var compilation3Ref = compilation3.EmitToImageReference(); + var compilation4 = CreateStandardCompilation("", new[] { compilation2.ToMetadataReference(), compilation3Ref }, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); - Assert.True(compilation4.Assembly.RuntimeSupportsDefaultInterfaceImplementation); - CompileAndVerify(compilation4, verify: false, symbolValidator: Validate1); - Validate1(compilation4.SourceModule); + ValidatePropertyImplementationByBase_11(compilation4.GetReferencedAssemblySymbol(compilation3Ref).Modules[0]); } [Fact] - public void PropertyModifiers_25() + public void PropertyModifiers_12() { var source1 = @" public interface I1 { - static int P1 { private get => throw null; set => throw null; } - - static int P2 { internal get => throw null; set => throw null; } - - public static int P3 { get => throw null; private set => throw null; } - - static int P4 { get => throw null; internal set => throw null; } + internal abstract int P1 {get; set;} } -class Test1 +class Test1 : I1 { - static void Main() - { - int x; - x = I1.P1; - I1.P1 = x; - x = I1.P2; - I1.P2 = x; - x = I1.P3; - I1.P3 = x; - x = I1.P4; - I1.P4 = x; - } } "; - var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All), + var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics( - // (18,13): error CS0271: The property or indexer 'I1.P1' cannot be used in this context because the get accessor is inaccessible - // x = I1.P1; - Diagnostic(ErrorCode.ERR_InaccessibleGetter, "I1.P1").WithArguments("I1.P1").WithLocation(18, 13), - // (23,9): error CS0272: The property or indexer 'I1.P3' cannot be used in this context because the set accessor is inaccessible - // I1.P3 = x; - Diagnostic(ErrorCode.ERR_InaccessibleSetter, "I1.P3").WithArguments("I1.P3").WithLocation(23, 9) + // (7,15): error CS0535: 'Test1' does not implement interface member 'I1.P1' + // class Test1 : I1 + Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test1", "I1.P1").WithLocation(7, 15) ); - var source2 = -@" -class Test2 -{ - static void Main() - { - int x; - x = I1.P1; - I1.P1 = x; - x = I1.P2; - I1.P2 = x; - x = I1.P3; - I1.P3 = x; - x = I1.P4; - I1.P4 = x; - } -} -"; - var compilation2 = CreateStandardCompilation(source2, new[] { compilation1.ToMetadataReference() }, - options: TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All), - parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); - Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); - compilation2.VerifyDiagnostics( - // (7,13): error CS0271: The property or indexer 'I1.P1' cannot be used in this context because the get accessor is inaccessible - // x = I1.P1; - Diagnostic(ErrorCode.ERR_InaccessibleGetter, "I1.P1").WithArguments("I1.P1").WithLocation(7, 13), - // (9,13): error CS0271: The property or indexer 'I1.P2' cannot be used in this context because the get accessor is inaccessible - // x = I1.P2; - Diagnostic(ErrorCode.ERR_InaccessibleGetter, "I1.P2").WithArguments("I1.P2").WithLocation(9, 13), - // (12,9): error CS0272: The property or indexer 'I1.P3' cannot be used in this context because the set accessor is inaccessible - // I1.P3 = x; - Diagnostic(ErrorCode.ERR_InaccessibleSetter, "I1.P3").WithArguments("I1.P3").WithLocation(12, 9), - // (14,9): error CS0272: The property or indexer 'I1.P4' cannot be used in this context because the set accessor is inaccessible - // I1.P4 = x; - Diagnostic(ErrorCode.ERR_InaccessibleSetter, "I1.P4").WithArguments("I1.P4").WithLocation(14, 9) - ); + var test1 = compilation1.GetTypeByMetadataName("Test1"); + var i1 = compilation1.GetTypeByMetadataName("I1"); + var p1 = i1.GetMember("P1"); + Assert.Null(test1.FindImplementationForInterfaceMember(p1)); + Assert.Null(test1.FindImplementationForInterfaceMember(p1.GetMethod)); + Assert.Null(test1.FindImplementationForInterfaceMember(p1.SetMethod)); } [Fact] - public void PropertyModifiers_26() + public void PropertyModifiers_13() { var source1 = @" public interface I1 { - abstract int P1 { private get; set; } - abstract int P2 { get; private set; } - abstract int P3 { internal get; } - static int P4 {internal get;} = 0; - static int P5 { internal get {throw null;} } - static int P6 { internal set {throw null;} } - static int P7 { internal get => throw null; } - static int P8 { internal set => throw null; } - static int P9 { internal get {throw null;} private set {throw null;}} - static int P10 { internal get => throw null; private set => throw null;} + public sealed int P1 + { + get + { + System.Console.WriteLine(""get_P1""); + return 0; + } + } } -"; - var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All), - parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); - Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); - compilation1.VerifyDiagnostics( - // (4,31): error CS0442: 'I1.P1.get': abstract properties cannot have private accessors - // abstract int P1 { private get; set; } - Diagnostic(ErrorCode.ERR_PrivateAbstractAccessor, "get").WithArguments("I1.P1.get").WithLocation(4, 31), - // (5,36): error CS0442: 'I1.P2.set': abstract properties cannot have private accessors - // abstract int P2 { get; private set; } - Diagnostic(ErrorCode.ERR_PrivateAbstractAccessor, "set").WithArguments("I1.P2.set").WithLocation(5, 36), - // (6,18): error CS0276: 'I1.P3': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor - // abstract int P3 { internal get; } - Diagnostic(ErrorCode.ERR_AccessModMissingAccessor, "P3").WithArguments("I1.P3").WithLocation(6, 18), - // (7,16): error CS8052: Auto-implemented properties inside interfaces cannot have initializers. - // static int P4 {internal get;} = 0; - Diagnostic(ErrorCode.ERR_AutoPropertyInitializerInInterface, "P4").WithArguments("I1.P4").WithLocation(7, 16), - // (7,29): error CS0501: 'I1.P4.get' must declare a body because it is not marked abstract, extern, or partial - // static int P4 {internal get;} = 0; - Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "get").WithArguments("I1.P4.get").WithLocation(7, 29), - // (7,16): error CS0276: 'I1.P4': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor - // static int P4 {internal get;} = 0; - Diagnostic(ErrorCode.ERR_AccessModMissingAccessor, "P4").WithArguments("I1.P4").WithLocation(7, 16), - // (8,16): error CS0276: 'I1.P5': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor - // static int P5 { internal get {throw null;} } - Diagnostic(ErrorCode.ERR_AccessModMissingAccessor, "P5").WithArguments("I1.P5").WithLocation(8, 16), - // (9,16): error CS0276: 'I1.P6': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor - // static int P6 { internal set {throw null;} } - Diagnostic(ErrorCode.ERR_AccessModMissingAccessor, "P6").WithArguments("I1.P6").WithLocation(9, 16), - // (10,16): error CS0276: 'I1.P7': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor - // static int P7 { internal get => throw null; } - Diagnostic(ErrorCode.ERR_AccessModMissingAccessor, "P7").WithArguments("I1.P7").WithLocation(10, 16), - // (11,16): error CS0276: 'I1.P8': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor - // static int P8 { internal set => throw null; } - Diagnostic(ErrorCode.ERR_AccessModMissingAccessor, "P8").WithArguments("I1.P8").WithLocation(11, 16), - // (12,16): error CS0274: Cannot specify accessibility modifiers for both accessors of the property or indexer 'I1.P9' - // static int P9 { internal get {throw null;} private set {throw null;}} - Diagnostic(ErrorCode.ERR_DuplicatePropertyAccessMods, "P9").WithArguments("I1.P9").WithLocation(12, 16), - // (13,16): error CS0274: Cannot specify accessibility modifiers for both accessors of the property or indexer 'I1.P10' - // static int P10 { internal get => throw null; private set => throw null;} - Diagnostic(ErrorCode.ERR_DuplicatePropertyAccessMods, "P10").WithArguments("I1.P10").WithLocation(13, 16) - ); - } +public interface I2 +{ + public sealed int P2 + { + get + { + System.Console.WriteLine(""get_P2""); + return 0; + } + set + { + System.Console.WriteLine(""set_P2""); + } + } +} +public interface I3 +{ + public sealed int P3 + { + set + { + System.Console.WriteLine(""set_P3""); + } + } +} +public interface I4 +{ + public sealed int P4 + { + get => GetP4(); + } - [Fact] - public void PropertyModifiers_27() - { - var source1 = -@" -public interface I1 + private int GetP4() + { + System.Console.WriteLine(""get_P4""); + return 0; + } +} +public interface I5 { - int P3 + public sealed int P5 { - private get {throw null;} - set {} + get => GetP5(); + set => System.Console.WriteLine(""set_P5""); } - int P4 + private int GetP5() + { + System.Console.WriteLine(""get_P5""); + return 0; + } +} +public interface I6 +{ + public sealed int P6 { - get {throw null;} - private set {} + set => System.Console.WriteLine(""set_P6""); } } +public interface I7 +{ + public sealed int P7 => GetP7(); + + private int GetP7() + { + System.Console.WriteLine(""get_P7""); + return 0; + } +} class Test1 : I1 { - int I1.P3 + static void Main() { - get {throw null;} - set {} + I1 i1 = new Test1(); + var x = i1.P1; + I2 i2 = new Test2(); + i2.P2 = i2.P2; + I3 i3 = new Test3(); + i3.P3 = x; + I4 i4 = new Test4(); + x = i4.P4; + I5 i5 = new Test5(); + i5.P5 = i5.P5; + I6 i6 = new Test6(); + i6.P6 = x; + I7 i7 = new Test7(); + x = i7.P7; } - int I1.P4 + public int P1 => throw null; +} +class Test2 : I2 +{ + public int P2 { - get {throw null;} - set {} + get => throw null; + set => throw null; } } - -class Test2 : I1 +class Test3 : I3 { - int I1.P3 + public int P3 { - set {} + set => throw null; } - - int I1.P4 +} +class Test4 : I4 +{ + public int P4 { - get => throw null; + get => throw null; + } +} +class Test5 : I5 +{ + public int P5 + { + get => throw null; + set => throw null; + } +} +class Test6 : I6 +{ + public int P6 + { + set => throw null; } } +class Test7 : I7 +{ + public int P7 => throw null; +} "; - var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All), - parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); - Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); - // PROTOTYPE(DefaultInterfaceImplementation): The lack of errors for Test1 looks wrong. Private accessor is never virtual - // (the behavior goes back to native compiler). So, it would be wrong - // to have a MethodImpl to point to an accessor like this in an interface. - compilation1.VerifyDiagnostics( - // (34,12): error CS0551: Explicit interface implementation 'Test2.I1.P3' is missing accessor 'I1.P3.get' - // int I1.P3 - Diagnostic(ErrorCode.ERR_ExplicitPropertyMissingAccessor, "P3").WithArguments("Test2.I1.P3", "I1.P3.get").WithLocation(34, 12), - // (39,12): error CS0551: Explicit interface implementation 'Test2.I1.P4' is missing accessor 'I1.P4.set' - // int I1.P4 - Diagnostic(ErrorCode.ERR_ExplicitPropertyMissingAccessor, "P4").WithArguments("Test2.I1.P4", "I1.P4.set").WithLocation(39, 12) - ); + ValidatePropertyModifiers_13(source1); + } + + private void ValidatePropertyModifiers_13(string source1) + { + var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugExe, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + + void Validate(ModuleSymbol m) + { + for (int i = 1; i <= 7; i++) + { + var test1 = m.GlobalNamespace.GetTypeMember("Test" + i); + var i1 = m.GlobalNamespace.GetTypeMember("I" + i); + var p1 = GetSingleProperty(i1); + + Assert.False(p1.IsAbstract); + Assert.False(p1.IsVirtual); + Assert.False(p1.IsSealed); + Assert.False(p1.IsStatic); + Assert.False(p1.IsExtern); + Assert.False(p1.IsOverride); + Assert.Equal(Accessibility.Public, p1.DeclaredAccessibility); + Assert.Null(test1.FindImplementationForInterfaceMember(p1)); + + switch (i) + { + case 3: + case 6: + Assert.Null(p1.GetMethod); + ValidateAccessor(p1.SetMethod); + break; + case 1: + case 4: + case 7: + Assert.Null(p1.SetMethod); + ValidateAccessor(p1.GetMethod); + break; + default: + ValidateAccessor(p1.GetMethod); + ValidateAccessor(p1.SetMethod); + break; + } + + void ValidateAccessor(MethodSymbol accessor) + { + Assert.False(accessor.IsAbstract); + Assert.False(accessor.IsVirtual); + Assert.False(accessor.IsMetadataVirtual()); + Assert.False(accessor.IsSealed); + Assert.False(accessor.IsStatic); + Assert.False(accessor.IsExtern); + Assert.False(accessor.IsAsync); + Assert.False(accessor.IsOverride); + Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); + Assert.Null(test1.FindImplementationForInterfaceMember(accessor)); + } + } + } + + CompileAndVerify(compilation1, verify: false, symbolValidator: Validate); + Validate(compilation1.SourceModule); } [Fact] - public void IndexerModifiers_01() + public void PropertyModifiers_14() { var source1 = @" -public interface I01{ public int this[int x] {get; set;} } -public interface I02{ protected int this[int x] {get;} } -public interface I03{ protected internal int this[int x] {set;} } -public interface I04{ internal int this[int x] {get;} } -public interface I05{ private int this[int x] {set;} } -public interface I06{ static int this[int x] {get;} } -public interface I07{ virtual int this[int x] {set;} } -public interface I08{ sealed int this[int x] {get;} } -public interface I09{ override int this[int x] {set;} } -public interface I10{ abstract int this[int x] {get;} } -public interface I11{ extern int this[int x] {get; set;} } +public interface I1 +{ + public sealed int P1 {get;} = 0; +} +public interface I2 +{ + abstract sealed int P2 {get;} +} +public interface I3 +{ + virtual sealed int P3 + { + set {} + } +} -public interface I12{ int this[int x] { public get; set;} } -public interface I13{ int this[int x] { get; protected set;} } -public interface I14{ int this[int x] { protected internal get; set;} } -public interface I15{ int this[int x] { get; internal set;} } -public interface I16{ int this[int x] { private get; set;} } -public interface I17{ int this[int x] { private get;} } +class Test1 : I1, I2, I3 +{ + int I1.P1 { get => throw null; } + int I2.P2 { get => throw null; } + int I3.P3 { set => throw null; } +} + +class Test2 : I1, I2, I3 +{} "; + ValidatePropertyModifiers_14(source1, + // (4,23): error CS8052: Auto-implemented properties inside interfaces cannot have initializers. + // public sealed int P1 {get;} = 0; + Diagnostic(ErrorCode.ERR_AutoPropertyInitializerInInterface, "P1").WithArguments("I1.P1").WithLocation(4, 23), + // (4,27): error CS0501: 'I1.P1.get' must declare a body because it is not marked abstract, extern, or partial + // public sealed int P1 {get;} = 0; + Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "get").WithArguments("I1.P1.get").WithLocation(4, 27), + // (8,25): error CS0238: 'I2.P2' cannot be sealed because it is not an override + // abstract sealed int P2 {get;} + Diagnostic(ErrorCode.ERR_SealedNonOverride, "P2").WithArguments("I2.P2").WithLocation(8, 25), + // (12,24): error CS0238: 'I3.P3' cannot be sealed because it is not an override + // virtual sealed int P3 + Diagnostic(ErrorCode.ERR_SealedNonOverride, "P3").WithArguments("I3.P3").WithLocation(12, 24), + // (20,12): error CS0539: 'Test1.P1' in explicit interface declaration is not found among members of the interface that can be implemented + // int I1.P1 { get => throw null; } + Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "P1").WithArguments("Test1.P1").WithLocation(20, 12), + // (25,19): error CS0535: 'Test2' does not implement interface member 'I2.P2' + // class Test2 : I1, I2, I3 + Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I2").WithArguments("Test2", "I2.P2").WithLocation(25, 19) + ); + } + + private void ValidatePropertyModifiers_14(string source1, params DiagnosticDescription[] expected) + { var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); - compilation1.VerifyDiagnostics( - // (3,37): error CS0106: The modifier 'protected' is not valid for this item - // public interface I02{ protected int this[int x] {get;} } - Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("protected").WithLocation(3, 37), - // (4,46): error CS0106: The modifier 'protected internal' is not valid for this item - // public interface I03{ protected internal int this[int x] {set;} } - Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("protected internal").WithLocation(4, 46), - // (6,48): error CS0501: 'I05.this[int].set' must declare a body because it is not marked abstract, extern, or partial - // public interface I05{ private int this[int x] {set;} } - Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "set").WithArguments("I05.this[int].set").WithLocation(6, 48), - // (7,34): error CS0106: The modifier 'static' is not valid for this item - // public interface I06{ static int this[int x] {get;} } - Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("static").WithLocation(7, 34), - // (8,48): error CS0501: 'I07.this[int].set' must declare a body because it is not marked abstract, extern, or partial - // public interface I07{ virtual int this[int x] {set;} } - Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "set").WithArguments("I07.this[int].set").WithLocation(8, 48), - // (9,47): error CS0501: 'I08.this[int].get' must declare a body because it is not marked abstract, extern, or partial - // public interface I08{ sealed int this[int x] {get;} } - Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "get").WithArguments("I08.this[int].get").WithLocation(9, 47), - // (10,36): error CS0106: The modifier 'override' is not valid for this item - // public interface I09{ override int this[int x] {set;} } - Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("override").WithLocation(10, 36), - // (14,48): error CS0273: The accessibility modifier of the 'I12.this[int].get' accessor must be more restrictive than the property or indexer 'I12.this[int]' - // public interface I12{ int this[int x] { public get; set;} } - Diagnostic(ErrorCode.ERR_InvalidPropertyAccessMod, "get").WithArguments("I12.this[int].get", "I12.this[int]").WithLocation(14, 48), - // (15,56): error CS0106: The modifier 'protected' is not valid for this item - // public interface I13{ int this[int x] { get; protected set;} } - Diagnostic(ErrorCode.ERR_BadMemberFlag, "set").WithArguments("protected").WithLocation(15, 56), - // (16,60): error CS0106: The modifier 'protected internal' is not valid for this item - // public interface I14{ int this[int x] { protected internal get; set;} } - Diagnostic(ErrorCode.ERR_BadMemberFlag, "get").WithArguments("protected internal").WithLocation(16, 60), - // (18,49): error CS0442: 'I16.this[int].get': abstract properties cannot have private accessors - // public interface I16{ int this[int x] { private get; set;} } - Diagnostic(ErrorCode.ERR_PrivateAbstractAccessor, "get").WithArguments("I16.this[int].get").WithLocation(18, 49), - // (19,27): error CS0276: 'I17.this[int]': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor - // public interface I17{ int this[int x] { private get;} } - Diagnostic(ErrorCode.ERR_AccessModMissingAccessor, "this").WithArguments("I17.this[int]").WithLocation(19, 27), - // (12,47): warning CS0626: Method, operator, or accessor 'I11.this[int].get' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. - // public interface I11{ extern int this[int x] {get; set;} } - Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "get").WithArguments("I11.this[int].get").WithLocation(12, 47), - // (12,52): warning CS0626: Method, operator, or accessor 'I11.this[int].set' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. - // public interface I11{ extern int this[int x] {get; set;} } - Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "set").WithArguments("I11.this[int].set").WithLocation(12, 52) - ); - - ValidateSymbolsIndexerModifiers_01(compilation1); - } + compilation1.VerifyDiagnostics(expected); - private static void ValidateSymbolsIndexerModifiers_01(CSharpCompilation compilation1) - { - var p01 = compilation1.GetMember("I01.this[]"); + var test1 = compilation1.GetTypeByMetadataName("Test1"); + var test2 = compilation1.GetTypeByMetadataName("Test2"); + var p1 = GetSingleProperty(compilation1, "I1"); + var p1get = p1.GetMethod; - Assert.True(p01.IsAbstract); - Assert.False(p01.IsVirtual); - Assert.False(p01.IsSealed); - Assert.False(p01.IsStatic); - Assert.False(p01.IsExtern); - Assert.False(p01.IsOverride); - Assert.Equal(Accessibility.Public, p01.DeclaredAccessibility); + Assert.False(p1.IsAbstract); + Assert.False(p1.IsVirtual); + Assert.False(p1.IsSealed); + Assert.False(p1.IsStatic); + Assert.False(p1.IsExtern); + Assert.False(p1.IsOverride); + Assert.Equal(Accessibility.Public, p1.DeclaredAccessibility); + Assert.Null(test1.FindImplementationForInterfaceMember(p1)); + Assert.Null(test2.FindImplementationForInterfaceMember(p1)); - VaidateP01Accessor(p01.GetMethod); - VaidateP01Accessor(p01.SetMethod); - void VaidateP01Accessor(MethodSymbol accessor) - { - Assert.True(accessor.IsAbstract); - Assert.False(accessor.IsVirtual); - Assert.True(accessor.IsMetadataVirtual()); - Assert.False(accessor.IsSealed); - Assert.False(accessor.IsStatic); - Assert.False(accessor.IsExtern); - Assert.False(accessor.IsAsync); - Assert.False(accessor.IsOverride); - Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); - } + Assert.False(p1get.IsAbstract); + Assert.False(p1get.IsVirtual); + Assert.False(p1get.IsMetadataVirtual()); + Assert.False(p1get.IsSealed); + Assert.False(p1get.IsStatic); + Assert.False(p1get.IsExtern); + Assert.False(p1get.IsAsync); + Assert.False(p1get.IsOverride); + Assert.Equal(Accessibility.Public, p1get.DeclaredAccessibility); + Assert.Null(test1.FindImplementationForInterfaceMember(p1get)); + Assert.Null(test2.FindImplementationForInterfaceMember(p1get)); - var p02 = compilation1.GetMember("I02.this[]"); - var p02get = p02.GetMethod; + var p2 = GetSingleProperty(compilation1, "I2"); + var test1P2 = test1.GetMembers().OfType().Where(p => p.Name.StartsWith("I2.")).Single(); + var p2get = p2.GetMethod; - Assert.True(p02.IsAbstract); - Assert.False(p02.IsVirtual); - Assert.False(p02.IsSealed); - Assert.False(p02.IsStatic); - Assert.False(p02.IsExtern); - Assert.False(p02.IsOverride); - Assert.Equal(Accessibility.Public, p02.DeclaredAccessibility); + Assert.True(p2.IsAbstract); + Assert.False(p2.IsVirtual); + Assert.True(p2.IsSealed); + Assert.False(p2.IsStatic); + Assert.False(p2.IsExtern); + Assert.False(p2.IsOverride); + Assert.Equal(Accessibility.Public, p2.DeclaredAccessibility); + Assert.Same(test1P2, test1.FindImplementationForInterfaceMember(p2)); + Assert.Null(test2.FindImplementationForInterfaceMember(p2)); - Assert.True(p02get.IsAbstract); - Assert.False(p02get.IsVirtual); + Assert.True(p2get.IsAbstract); + Assert.False(p2get.IsVirtual); + Assert.True(p2get.IsMetadataVirtual()); + Assert.True(p2get.IsSealed); + Assert.False(p2get.IsStatic); + Assert.False(p2get.IsExtern); + Assert.False(p2get.IsAsync); + Assert.False(p2get.IsOverride); + Assert.Equal(Accessibility.Public, p2get.DeclaredAccessibility); + Assert.Same(test1P2.GetMethod, test1.FindImplementationForInterfaceMember(p2get)); + Assert.Null(test2.FindImplementationForInterfaceMember(p2get)); + + var p3 = GetSingleProperty(compilation1, "I3"); + var test1P3 = test1.GetMembers().OfType().Where(p => p.Name.StartsWith("I3.")).Single(); + var p3set = p3.SetMethod; + + Assert.False(p3.IsAbstract); + Assert.True(p3.IsVirtual); + Assert.True(p3.IsSealed); + Assert.False(p3.IsStatic); + Assert.False(p3.IsExtern); + Assert.False(p3.IsOverride); + Assert.Equal(Accessibility.Public, p3.DeclaredAccessibility); + Assert.Same(test1P3, test1.FindImplementationForInterfaceMember(p3)); + Assert.Same(p3, test2.FindImplementationForInterfaceMember(p3)); + + Assert.False(p3set.IsAbstract); + Assert.True(p3set.IsVirtual); + Assert.True(p3set.IsMetadataVirtual()); + Assert.True(p3set.IsSealed); + Assert.False(p3set.IsStatic); + Assert.False(p3set.IsExtern); + Assert.False(p3set.IsAsync); + Assert.False(p3set.IsOverride); + Assert.Equal(Accessibility.Public, p3set.DeclaredAccessibility); + Assert.Same(test1P3.SetMethod, test1.FindImplementationForInterfaceMember(p3set)); + Assert.Same(p3set, test2.FindImplementationForInterfaceMember(p3set)); + } + + [Fact] + public void PropertyModifiers_15() + { + var source1 = +@" +public interface I0 +{ + abstract virtual int P0 { get; set; } +} +public interface I1 +{ + abstract virtual int P1 { get { throw null; } } +} +public interface I2 +{ + virtual abstract int P2 + { + get { throw null; } + set { throw null; } + } +} +public interface I3 +{ + abstract virtual int P3 { set { throw null; } } +} +public interface I4 +{ + abstract virtual int P4 { get => throw null; } +} +public interface I5 +{ + abstract virtual int P5 + { + get => throw null; + set => throw null; + } +} +public interface I6 +{ + abstract virtual int P6 { set => throw null; } +} +public interface I7 +{ + abstract virtual int P7 => throw null; +} +public interface I8 +{ + abstract virtual int P8 {get;} = 0; +} + +class Test1 : I0, I1, I2, I3, I4, I5, I6, I7, I8 +{ + int I0.P0 + { + get { throw null; } + set { throw null; } + } + int I1.P1 + { + get { throw null; } + } + int I2.P2 + { + get { throw null; } + set { throw null; } + } + int I3.P3 + { + set { throw null; } + } + int I4.P4 + { + get { throw null; } + } + int I5.P5 + { + get { throw null; } + set { throw null; } + } + int I6.P6 + { + set { throw null; } + } + int I7.P7 + { + get { throw null; } + } + int I8.P8 + { + get { throw null; } + } +} + +class Test2 : I0, I1, I2, I3, I4, I5, I6, I7, I8 +{} +"; + ValidatePropertyModifiers_15(source1, + // (4,26): error CS0503: The abstract method 'I0.P0' cannot be marked virtual + // abstract virtual int P0 { get; set; } + Diagnostic(ErrorCode.ERR_AbstractNotVirtual, "P0").WithArguments("I0.P0"), + // (8,26): error CS0503: The abstract method 'I1.P1' cannot be marked virtual + // abstract virtual int P1 { get { throw null; } } + Diagnostic(ErrorCode.ERR_AbstractNotVirtual, "P1").WithArguments("I1.P1").WithLocation(8, 26), + // (8,31): error CS0500: 'I1.P1.get' cannot declare a body because it is marked abstract + // abstract virtual int P1 { get { throw null; } } + Diagnostic(ErrorCode.ERR_AbstractHasBody, "get").WithArguments("I1.P1.get").WithLocation(8, 31), + // (12,26): error CS0503: The abstract method 'I2.P2' cannot be marked virtual + // virtual abstract int P2 + Diagnostic(ErrorCode.ERR_AbstractNotVirtual, "P2").WithArguments("I2.P2").WithLocation(12, 26), + // (14,9): error CS0500: 'I2.P2.get' cannot declare a body because it is marked abstract + // get { throw null; } + Diagnostic(ErrorCode.ERR_AbstractHasBody, "get").WithArguments("I2.P2.get").WithLocation(14, 9), + // (15,9): error CS0500: 'I2.P2.set' cannot declare a body because it is marked abstract + // set { throw null; } + Diagnostic(ErrorCode.ERR_AbstractHasBody, "set").WithArguments("I2.P2.set").WithLocation(15, 9), + // (20,26): error CS0503: The abstract method 'I3.P3' cannot be marked virtual + // abstract virtual int P3 { set { throw null; } } + Diagnostic(ErrorCode.ERR_AbstractNotVirtual, "P3").WithArguments("I3.P3").WithLocation(20, 26), + // (20,31): error CS0500: 'I3.P3.set' cannot declare a body because it is marked abstract + // abstract virtual int P3 { set { throw null; } } + Diagnostic(ErrorCode.ERR_AbstractHasBody, "set").WithArguments("I3.P3.set").WithLocation(20, 31), + // (24,26): error CS0503: The abstract method 'I4.P4' cannot be marked virtual + // abstract virtual int P4 { get => throw null; } + Diagnostic(ErrorCode.ERR_AbstractNotVirtual, "P4").WithArguments("I4.P4").WithLocation(24, 26), + // (24,31): error CS0500: 'I4.P4.get' cannot declare a body because it is marked abstract + // abstract virtual int P4 { get => throw null; } + Diagnostic(ErrorCode.ERR_AbstractHasBody, "get").WithArguments("I4.P4.get").WithLocation(24, 31), + // (28,26): error CS0503: The abstract method 'I5.P5' cannot be marked virtual + // abstract virtual int P5 + Diagnostic(ErrorCode.ERR_AbstractNotVirtual, "P5").WithArguments("I5.P5").WithLocation(28, 26), + // (30,9): error CS0500: 'I5.P5.get' cannot declare a body because it is marked abstract + // get => throw null; + Diagnostic(ErrorCode.ERR_AbstractHasBody, "get").WithArguments("I5.P5.get").WithLocation(30, 9), + // (31,9): error CS0500: 'I5.P5.set' cannot declare a body because it is marked abstract + // set => throw null; + Diagnostic(ErrorCode.ERR_AbstractHasBody, "set").WithArguments("I5.P5.set").WithLocation(31, 9), + // (36,26): error CS0503: The abstract method 'I6.P6' cannot be marked virtual + // abstract virtual int P6 { set => throw null; } + Diagnostic(ErrorCode.ERR_AbstractNotVirtual, "P6").WithArguments("I6.P6").WithLocation(36, 26), + // (36,31): error CS0500: 'I6.P6.set' cannot declare a body because it is marked abstract + // abstract virtual int P6 { set => throw null; } + Diagnostic(ErrorCode.ERR_AbstractHasBody, "set").WithArguments("I6.P6.set").WithLocation(36, 31), + // (40,26): error CS0503: The abstract method 'I7.P7' cannot be marked virtual + // abstract virtual int P7 => throw null; + Diagnostic(ErrorCode.ERR_AbstractNotVirtual, "P7").WithArguments("I7.P7").WithLocation(40, 26), + // (40,32): error CS0500: 'I7.P7.get' cannot declare a body because it is marked abstract + // abstract virtual int P7 => throw null; + Diagnostic(ErrorCode.ERR_AbstractHasBody, "throw null").WithArguments("I7.P7.get").WithLocation(40, 32), + // (44,26): error CS0503: The abstract method 'I8.P8' cannot be marked virtual + // abstract virtual int P8 {get;} = 0; + Diagnostic(ErrorCode.ERR_AbstractNotVirtual, "P8").WithArguments("I8.P8").WithLocation(44, 26), + // (44,26): error CS8052: Auto-implemented properties inside interfaces cannot have initializers. + // abstract virtual int P8 {get;} = 0; + Diagnostic(ErrorCode.ERR_AutoPropertyInitializerInInterface, "P8").WithArguments("I8.P8").WithLocation(44, 26), + // (90,15): error CS0535: 'Test2' does not implement interface member 'I0.P0' + // class Test2 : I0, I1, I2, I3, I4, I5, I6, I7, I8 + Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I0").WithArguments("Test2", "I0.P0").WithLocation(90, 15), + // (90,19): error CS0535: 'Test2' does not implement interface member 'I1.P1' + // class Test2 : I0, I1, I2, I3, I4, I5, I6, I7, I8 + Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test2", "I1.P1").WithLocation(90, 19), + // (90,23): error CS0535: 'Test2' does not implement interface member 'I2.P2' + // class Test2 : I0, I1, I2, I3, I4, I5, I6, I7, I8 + Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I2").WithArguments("Test2", "I2.P2").WithLocation(90, 23), + // (90,27): error CS0535: 'Test2' does not implement interface member 'I3.P3' + // class Test2 : I0, I1, I2, I3, I4, I5, I6, I7, I8 + Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I3").WithArguments("Test2", "I3.P3").WithLocation(90, 27), + // (90,31): error CS0535: 'Test2' does not implement interface member 'I4.P4' + // class Test2 : I0, I1, I2, I3, I4, I5, I6, I7, I8 + Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I4").WithArguments("Test2", "I4.P4").WithLocation(90, 31), + // (90,35): error CS0535: 'Test2' does not implement interface member 'I5.P5' + // class Test2 : I0, I1, I2, I3, I4, I5, I6, I7, I8 + Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I5").WithArguments("Test2", "I5.P5").WithLocation(90, 35), + // (90,39): error CS0535: 'Test2' does not implement interface member 'I6.P6' + // class Test2 : I0, I1, I2, I3, I4, I5, I6, I7, I8 + Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I6").WithArguments("Test2", "I6.P6").WithLocation(90, 39), + // (90,43): error CS0535: 'Test2' does not implement interface member 'I7.P7' + // class Test2 : I0, I1, I2, I3, I4, I5, I6, I7, I8 + Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I7").WithArguments("Test2", "I7.P7").WithLocation(90, 43), + // (90,47): error CS0535: 'Test2' does not implement interface member 'I8.P8' + // class Test2 : I0, I1, I2, I3, I4, I5, I6, I7, I8 + Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I8").WithArguments("Test2", "I8.P8").WithLocation(90, 47) + ); + } + + private void ValidatePropertyModifiers_15(string source1, params DiagnosticDescription[] expected) + { + var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation1.VerifyDiagnostics(expected); + + var test1 = compilation1.GetTypeByMetadataName("Test1"); + var test2 = compilation1.GetTypeByMetadataName("Test2"); + + for (int i = 0; i <= 8; i++) + { + var i1 = compilation1.GetTypeByMetadataName("I" + i); + var p2 = GetSingleProperty(i1); + var test1P2 = test1.GetMembers().OfType().Where(p => p.Name.StartsWith(i1.Name)).Single(); + + Assert.True(p2.IsAbstract); + Assert.True(p2.IsVirtual); + Assert.False(p2.IsSealed); + Assert.False(p2.IsStatic); + Assert.False(p2.IsExtern); + Assert.False(p2.IsOverride); + Assert.Equal(Accessibility.Public, p2.DeclaredAccessibility); + Assert.Same(test1P2, test1.FindImplementationForInterfaceMember(p2)); + Assert.Null(test2.FindImplementationForInterfaceMember(p2)); + + switch (i) + { + case 3: + case 6: + Assert.Null(p2.GetMethod); + ValidateAccessor(p2.SetMethod, test1P2.SetMethod); + break; + case 1: + case 4: + case 7: + case 8: + Assert.Null(p2.SetMethod); + ValidateAccessor(p2.GetMethod, test1P2.GetMethod); + break; + default: + ValidateAccessor(p2.GetMethod, test1P2.GetMethod); + ValidateAccessor(p2.SetMethod, test1P2.SetMethod); + break; + } + + void ValidateAccessor(MethodSymbol accessor, MethodSymbol implementedBy) + { + Assert.True(accessor.IsAbstract); + Assert.True(accessor.IsVirtual); + Assert.True(accessor.IsMetadataVirtual()); + Assert.False(accessor.IsSealed); + Assert.False(accessor.IsStatic); + Assert.False(accessor.IsExtern); + Assert.False(accessor.IsAsync); + Assert.False(accessor.IsOverride); + Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); + Assert.Same(implementedBy, test1.FindImplementationForInterfaceMember(accessor)); + Assert.Null(test2.FindImplementationForInterfaceMember(accessor)); + } + } + } + + [Fact] + public void PropertyModifiers_16() + { + var source1 = +@" +public interface I1 +{ + extern int P1 {get;} +} +public interface I2 +{ + virtual extern int P2 {set;} +} +public interface I3 +{ + static extern int P3 {get; set;} +} +public interface I4 +{ + private extern int P4 {get;} +} +public interface I5 +{ + extern sealed int P5 {set;} +} + +class Test1 : I1, I2, I3, I4, I5 +{ +} + +class Test2 : I1, I2, I3, I4, I5 +{ + int I1.P1 => 0; + int I2.P2 { set {} } +} +"; + ValidatePropertyModifiers_16(source1); + } + + private void ValidatePropertyModifiers_16(string source1) + { + var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All), + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + CompileAndVerify(compilation1, verify: false, symbolValidator: Validate); + + Validate(compilation1.SourceModule); + + void Validate(ModuleSymbol m) + { + var test1 = m.GlobalNamespace.GetTypeMember("Test1"); + var test2 = m.GlobalNamespace.GetTypeMember("Test2"); + bool isSource = !(m is PEModuleSymbol); + var p1 = GetSingleProperty(m, "I1"); + var test2P1 = test2.GetMembers().OfType().Where(p => p.Name.StartsWith("I1.")).Single(); + var p1get = p1.GetMethod; + + Assert.False(p1.IsAbstract); + Assert.True(p1.IsVirtual); + Assert.False(p1.IsSealed); + Assert.False(p1.IsStatic); + Assert.Equal(isSource, p1.IsExtern); + Assert.False(p1.IsOverride); + Assert.Equal(Accessibility.Public, p1.DeclaredAccessibility); + Assert.Same(p1, test1.FindImplementationForInterfaceMember(p1)); + Assert.Same(test2P1, test2.FindImplementationForInterfaceMember(p1)); + + Assert.False(p1get.IsAbstract); + Assert.True(p1get.IsVirtual); + Assert.True(p1get.IsMetadataVirtual()); + Assert.False(p1get.IsSealed); + Assert.False(p1get.IsStatic); + Assert.Equal(isSource, p1get.IsExtern); + Assert.False(p1get.IsAsync); + Assert.False(p1get.IsOverride); + Assert.Equal(Accessibility.Public, p1get.DeclaredAccessibility); + Assert.Same(p1get, test1.FindImplementationForInterfaceMember(p1get)); + Assert.Same(test2P1.GetMethod, test2.FindImplementationForInterfaceMember(p1get)); + + var p2 = GetSingleProperty(m, "I2"); + var test2P2 = test2.GetMembers().OfType().Where(p => p.Name.StartsWith("I2.")).Single(); + var p2set = p2.SetMethod; + + Assert.False(p2.IsAbstract); + Assert.True(p2.IsVirtual); + Assert.False(p2.IsSealed); + Assert.False(p2.IsStatic); + Assert.Equal(isSource, p2.IsExtern); + Assert.False(p2.IsOverride); + Assert.Equal(Accessibility.Public, p2.DeclaredAccessibility); + Assert.Same(p2, test1.FindImplementationForInterfaceMember(p2)); + Assert.Same(test2P2, test2.FindImplementationForInterfaceMember(p2)); + + Assert.False(p2set.IsAbstract); + Assert.True(p2set.IsVirtual); + Assert.True(p2set.IsMetadataVirtual()); + Assert.False(p2set.IsSealed); + Assert.False(p2set.IsStatic); + Assert.Equal(isSource, p2set.IsExtern); + Assert.False(p2set.IsAsync); + Assert.False(p2set.IsOverride); + Assert.Equal(Accessibility.Public, p2set.DeclaredAccessibility); + Assert.Same(p2set, test1.FindImplementationForInterfaceMember(p2set)); + Assert.Same(test2P2.SetMethod, test2.FindImplementationForInterfaceMember(p2set)); + + var i3 = m.ContainingAssembly.GetTypeByMetadataName("I3"); + + if ((object)i3 != null) + { + var p3 = GetSingleProperty(i3); + + Assert.False(p3.IsAbstract); + Assert.False(p3.IsVirtual); + Assert.False(p3.IsSealed); + Assert.True(p3.IsStatic); + Assert.Equal(isSource, p3.IsExtern); + Assert.False(p3.IsOverride); + Assert.Equal(Accessibility.Public, p3.DeclaredAccessibility); + Assert.Null(test1.FindImplementationForInterfaceMember(p3)); + Assert.Null(test2.FindImplementationForInterfaceMember(p3)); + + ValidateP3Accessor(p3.GetMethod); + ValidateP3Accessor(p3.SetMethod); + void ValidateP3Accessor(MethodSymbol accessor) + { + Assert.False(accessor.IsAbstract); + Assert.False(accessor.IsVirtual); + Assert.False(accessor.IsMetadataVirtual()); + Assert.False(accessor.IsSealed); + Assert.True(accessor.IsStatic); + Assert.Equal(isSource, accessor.IsExtern); + Assert.False(accessor.IsAsync); + Assert.False(accessor.IsOverride); + Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); + Assert.Null(test1.FindImplementationForInterfaceMember(accessor)); + Assert.Null(test2.FindImplementationForInterfaceMember(accessor)); + } + } + + var p4 = GetSingleProperty(m, "I4"); + var p4get = p4.GetMethod; + + Assert.False(p4.IsAbstract); + Assert.False(p4.IsVirtual); + Assert.False(p4.IsSealed); + Assert.False(p4.IsStatic); + Assert.Equal(isSource, p4.IsExtern); + Assert.False(p4.IsOverride); + Assert.Equal(Accessibility.Private, p4.DeclaredAccessibility); + Assert.Null(test1.FindImplementationForInterfaceMember(p4)); + Assert.Null(test2.FindImplementationForInterfaceMember(p4)); + + Assert.False(p4get.IsAbstract); + Assert.False(p4get.IsVirtual); + Assert.False(p4get.IsMetadataVirtual()); + Assert.False(p4get.IsSealed); + Assert.False(p4get.IsStatic); + Assert.Equal(isSource, p4get.IsExtern); + Assert.False(p4get.IsAsync); + Assert.False(p4get.IsOverride); + Assert.Equal(Accessibility.Private, p4get.DeclaredAccessibility); + Assert.Null(test1.FindImplementationForInterfaceMember(p4get)); + Assert.Null(test2.FindImplementationForInterfaceMember(p4get)); + + var p5 = GetSingleProperty(m, "I5"); + var p5set = p5.SetMethod; + + Assert.False(p5.IsAbstract); + Assert.False(p5.IsVirtual); + Assert.False(p5.IsSealed); + Assert.False(p5.IsStatic); + Assert.Equal(isSource, p5.IsExtern); + Assert.False(p5.IsOverride); + Assert.Equal(Accessibility.Public, p5.DeclaredAccessibility); + Assert.Null(test1.FindImplementationForInterfaceMember(p5)); + Assert.Null(test2.FindImplementationForInterfaceMember(p5)); + + Assert.False(p5set.IsAbstract); + Assert.False(p5set.IsVirtual); + Assert.False(p5set.IsMetadataVirtual()); + Assert.False(p5set.IsSealed); + Assert.False(p5set.IsStatic); + Assert.Equal(isSource, p5set.IsExtern); + Assert.False(p5set.IsAsync); + Assert.False(p5set.IsOverride); + Assert.Equal(Accessibility.Public, p5set.DeclaredAccessibility); + Assert.Null(test1.FindImplementationForInterfaceMember(p5set)); + Assert.Null(test2.FindImplementationForInterfaceMember(p5set)); + } + } + + [Fact] + public void PropertyModifiers_17() + { + var source1 = +@" +public interface I1 +{ + abstract extern int P1 {get;} +} +public interface I2 +{ + extern int P2 => 0; +} +public interface I3 +{ + static extern int P3 {get => 0; set => throw null;} +} +public interface I4 +{ + private extern int P4 { get {throw null;} set {throw null;}} +} +public interface I5 +{ + extern sealed int P5 {get;} = 0; +} + +class Test1 : I1, I2, I3, I4, I5 +{ +} + +class Test2 : I1, I2, I3, I4, I5 +{ + int I1.P1 => 0; + int I2.P2 => 0; + int I3.P3 { get => 0; set => throw null;} + int I4.P4 { get => 0; set => throw null;} + int I5.P5 => 0; +} +"; + ValidatePropertyModifiers_17(source1, + // (4,25): error CS0180: 'I1.P1' cannot be both extern and abstract + // abstract extern int P1 {get;} + Diagnostic(ErrorCode.ERR_AbstractAndExtern, "P1").WithArguments("I1.P1").WithLocation(4, 25), + // (8,22): error CS0179: 'I2.P2.get' cannot be extern and declare a body + // extern int P2 => 0; + Diagnostic(ErrorCode.ERR_ExternHasBody, "0").WithArguments("I2.P2.get").WithLocation(8, 22), + // (12,27): error CS0179: 'I3.P3.get' cannot be extern and declare a body + // static extern int P3 {get => 0; set => throw null;} + Diagnostic(ErrorCode.ERR_ExternHasBody, "get").WithArguments("I3.P3.get").WithLocation(12, 27), + // (12,37): error CS0179: 'I3.P3.set' cannot be extern and declare a body + // static extern int P3 {get => 0; set => throw null;} + Diagnostic(ErrorCode.ERR_ExternHasBody, "set").WithArguments("I3.P3.set").WithLocation(12, 37), + // (16,29): error CS0179: 'I4.P4.get' cannot be extern and declare a body + // private extern int P4 { get {throw null;} set {throw null;}} + Diagnostic(ErrorCode.ERR_ExternHasBody, "get").WithArguments("I4.P4.get").WithLocation(16, 29), + // (16,47): error CS0179: 'I4.P4.set' cannot be extern and declare a body + // private extern int P4 { get {throw null;} set {throw null;}} + Diagnostic(ErrorCode.ERR_ExternHasBody, "set").WithArguments("I4.P4.set").WithLocation(16, 47), + // (20,23): error CS8052: Auto-implemented properties inside interfaces cannot have initializers. + // extern sealed int P5 {get;} = 0; + Diagnostic(ErrorCode.ERR_AutoPropertyInitializerInInterface, "P5").WithArguments("I5.P5").WithLocation(20, 23), + // (23,15): error CS0535: 'Test1' does not implement interface member 'I1.P1' + // class Test1 : I1, I2, I3, I4, I5 + Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test1", "I1.P1").WithLocation(23, 15), + // (31,12): error CS0539: 'Test2.P3' in explicit interface declaration is not found among members of the interface that can be implemented + // int I3.P3 { get => 0; set => throw null;} + Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "P3").WithArguments("Test2.P3").WithLocation(31, 12), + // (32,12): error CS0539: 'Test2.P4' in explicit interface declaration is not found among members of the interface that can be implemented + // int I4.P4 { get => 0; set => throw null;} + Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "P4").WithArguments("Test2.P4").WithLocation(32, 12), + // (33,12): error CS0539: 'Test2.P5' in explicit interface declaration is not found among members of the interface that can be implemented + // int I5.P5 => 0; + Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "P5").WithArguments("Test2.P5").WithLocation(33, 12), + // (20,27): warning CS0626: Method, operator, or accessor 'I5.P5.get' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. + // extern sealed int P5 {get;} = 0; + Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "get").WithArguments("I5.P5.get").WithLocation(20, 27) + ); + } + + private void ValidatePropertyModifiers_17(string source1, params DiagnosticDescription[] expected) + { + var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation1.VerifyDiagnostics(expected); + + var test1 = compilation1.GetTypeByMetadataName("Test1"); + var test2 = compilation1.GetTypeByMetadataName("Test2"); + var p1 = GetSingleProperty(compilation1, "I1"); + var test2P1 = test2.GetMembers().OfType().Where(p => p.Name.StartsWith("I1.")).Single(); + var p1get = p1.GetMethod; + + Assert.True(p1.IsAbstract); + Assert.False(p1.IsVirtual); + Assert.False(p1.IsSealed); + Assert.False(p1.IsStatic); + Assert.True(p1.IsExtern); + Assert.False(p1.IsOverride); + Assert.Equal(Accessibility.Public, p1.DeclaredAccessibility); + Assert.Null(test1.FindImplementationForInterfaceMember(p1)); + Assert.Same(test2P1, test2.FindImplementationForInterfaceMember(p1)); + + Assert.True(p1get.IsAbstract); + Assert.False(p1get.IsVirtual); + Assert.True(p1get.IsMetadataVirtual()); + Assert.False(p1get.IsSealed); + Assert.False(p1get.IsStatic); + Assert.True(p1get.IsExtern); + Assert.False(p1get.IsAsync); + Assert.False(p1get.IsOverride); + Assert.Equal(Accessibility.Public, p1get.DeclaredAccessibility); + Assert.Null(test1.FindImplementationForInterfaceMember(p1get)); + Assert.Same(test2P1.GetMethod, test2.FindImplementationForInterfaceMember(p1get)); + + var p2 = GetSingleProperty(compilation1, "I2"); + var test2P2 = test2.GetMembers().OfType().Where(p => p.Name.StartsWith("I2.")).Single(); + var p2get = p2.GetMethod; + + Assert.False(p2.IsAbstract); + Assert.True(p2.IsVirtual); + Assert.False(p2.IsSealed); + Assert.False(p2.IsStatic); + Assert.True(p2.IsExtern); + Assert.False(p2.IsOverride); + Assert.Equal(Accessibility.Public, p2.DeclaredAccessibility); + Assert.Same(p2, test1.FindImplementationForInterfaceMember(p2)); + Assert.Same(test2P2, test2.FindImplementationForInterfaceMember(p2)); + + Assert.False(p2get.IsAbstract); + Assert.True(p2get.IsVirtual); + Assert.True(p2get.IsMetadataVirtual()); + Assert.False(p2get.IsSealed); + Assert.False(p2get.IsStatic); + Assert.True(p2get.IsExtern); + Assert.False(p2get.IsAsync); + Assert.False(p2get.IsOverride); + Assert.Equal(Accessibility.Public, p2get.DeclaredAccessibility); + Assert.Same(p2get, test1.FindImplementationForInterfaceMember(p2get)); + Assert.Same(test2P2.GetMethod, test2.FindImplementationForInterfaceMember(p2get)); + + var p3 = GetSingleProperty(compilation1, "I3"); + var test2P3 = test2.GetMembers().OfType().Where(p => p.Name.StartsWith("I3.")).Single(); + + Assert.False(p3.IsAbstract); + Assert.Equal(p3.IsIndexer, p3.IsVirtual); + Assert.False(p3.IsSealed); + Assert.Equal(!p3.IsIndexer, p3.IsStatic); + Assert.True(p3.IsExtern); + Assert.False(p3.IsOverride); + Assert.Equal(Accessibility.Public, p3.DeclaredAccessibility); + Assert.Same(p3.IsIndexer ? p3 : null, test1.FindImplementationForInterfaceMember(p3)); + Assert.Same(p3.IsIndexer ? test2P3 : null, test2.FindImplementationForInterfaceMember(p3)); + + ValidateP3Accessor(p3.GetMethod, p3.IsIndexer ? test2P3.GetMethod : null); + ValidateP3Accessor(p3.SetMethod, p3.IsIndexer ? test2P3.SetMethod : null); + void ValidateP3Accessor(MethodSymbol accessor, MethodSymbol test2Implementation) + { + Assert.False(accessor.IsAbstract); + Assert.Equal(p3.IsIndexer, accessor.IsVirtual); + Assert.Equal(p3.IsIndexer, accessor.IsMetadataVirtual()); + Assert.False(accessor.IsSealed); + Assert.Equal(!p3.IsIndexer, accessor.IsStatic); + Assert.True(accessor.IsExtern); + Assert.False(accessor.IsAsync); + Assert.False(accessor.IsOverride); + Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); + Assert.Same(p3.IsIndexer ? accessor : null, test1.FindImplementationForInterfaceMember(accessor)); + Assert.Same(test2Implementation, test2.FindImplementationForInterfaceMember(accessor)); + } + + var p4 = GetSingleProperty(compilation1, "I4"); + + Assert.False(p4.IsAbstract); + Assert.False(p4.IsVirtual); + Assert.False(p4.IsSealed); + Assert.False(p4.IsStatic); + Assert.True(p4.IsExtern); + Assert.False(p4.IsOverride); + Assert.Equal(Accessibility.Private, p4.DeclaredAccessibility); + Assert.Null(test1.FindImplementationForInterfaceMember(p4)); + Assert.Null(test2.FindImplementationForInterfaceMember(p4)); + + ValidateP4Accessor(p4.GetMethod); + ValidateP4Accessor(p4.SetMethod); + void ValidateP4Accessor(MethodSymbol accessor) + { + Assert.False(accessor.IsAbstract); + Assert.False(accessor.IsVirtual); + Assert.False(accessor.IsMetadataVirtual()); + Assert.False(accessor.IsSealed); + Assert.False(accessor.IsStatic); + Assert.True(accessor.IsExtern); + Assert.False(accessor.IsAsync); + Assert.False(accessor.IsOverride); + Assert.Equal(Accessibility.Private, accessor.DeclaredAccessibility); + Assert.Null(test1.FindImplementationForInterfaceMember(accessor)); + Assert.Null(test2.FindImplementationForInterfaceMember(accessor)); + } + + var p5 = GetSingleProperty(compilation1, "I5"); + var p5get = p5.GetMethod; + + Assert.False(p5.IsAbstract); + Assert.False(p5.IsVirtual); + Assert.False(p5.IsSealed); + Assert.False(p5.IsStatic); + Assert.True(p5.IsExtern); + Assert.False(p5.IsOverride); + Assert.Equal(Accessibility.Public, p5.DeclaredAccessibility); + Assert.Null(test1.FindImplementationForInterfaceMember(p5)); + Assert.Null(test2.FindImplementationForInterfaceMember(p5)); + + Assert.False(p5get.IsAbstract); + Assert.False(p5get.IsVirtual); + Assert.False(p5get.IsMetadataVirtual()); + Assert.False(p5get.IsSealed); + Assert.False(p5get.IsStatic); + Assert.True(p5get.IsExtern); + Assert.False(p5get.IsAsync); + Assert.False(p5get.IsOverride); + Assert.Equal(Accessibility.Public, p5get.DeclaredAccessibility); + Assert.Null(test1.FindImplementationForInterfaceMember(p5get)); + Assert.Null(test2.FindImplementationForInterfaceMember(p5get)); + } + + [Fact] + public void PropertyModifiers_18() + { + var source1 = +@" +public interface I1 +{ + abstract int P1 {get => 0; set => throw null;} +} +public interface I2 +{ + abstract private int P2 => 0; +} +public interface I3 +{ + static extern int P3 {get; set;} +} +public interface I4 +{ + abstract static int P4 { get {throw null;} set {throw null;}} +} +public interface I5 +{ + override sealed int P5 {get;} = 0; +} + +class Test1 : I1, I2, I3, I4, I5 +{ +} + +class Test2 : I1, I2, I3, I4, I5 +{ + int I1.P1 { get => 0; set => throw null;} + int I2.P2 => 0; + int I3.P3 { get => 0; set => throw null;} + int I4.P4 { get => 0; set => throw null;} + int I5.P5 => 0; +} +"; + ValidatePropertyModifiers_18(source1, + // (4,22): error CS0500: 'I1.P1.get' cannot declare a body because it is marked abstract + // abstract int P1 {get => 0; set => throw null;} + Diagnostic(ErrorCode.ERR_AbstractHasBody, "get").WithArguments("I1.P1.get"), + // (4,32): error CS0500: 'I1.P1.set' cannot declare a body because it is marked abstract + // abstract int P1 {get => 0; set => throw null;} + Diagnostic(ErrorCode.ERR_AbstractHasBody, "set").WithArguments("I1.P1.set"), + // (8,26): error CS0621: 'I2.P2': virtual or abstract members cannot be private + // abstract private int P2 => 0; + Diagnostic(ErrorCode.ERR_VirtualPrivate, "P2").WithArguments("I2.P2").WithLocation(8, 26), + // (8,32): error CS0500: 'I2.P2.get' cannot declare a body because it is marked abstract + // abstract private int P2 => 0; + Diagnostic(ErrorCode.ERR_AbstractHasBody, "0").WithArguments("I2.P2.get").WithLocation(8, 32), + // (16,25): error CS0112: A static member 'I4.P4' cannot be marked as override, virtual, or abstract + // abstract static int P4 { get {throw null;} set {throw null;}} + Diagnostic(ErrorCode.ERR_StaticNotVirtual, "P4").WithArguments("I4.P4").WithLocation(16, 25), + // (16,30): error CS0500: 'I4.P4.get' cannot declare a body because it is marked abstract + // abstract static int P4 { get {throw null;} set {throw null;}} + Diagnostic(ErrorCode.ERR_AbstractHasBody, "get").WithArguments("I4.P4.get").WithLocation(16, 30), + // (16,48): error CS0500: 'I4.P4.set' cannot declare a body because it is marked abstract + // abstract static int P4 { get {throw null;} set {throw null;}} + Diagnostic(ErrorCode.ERR_AbstractHasBody, "set").WithArguments("I4.P4.set").WithLocation(16, 48), + // (20,25): error CS0106: The modifier 'override' is not valid for this item + // override sealed int P5 {get;} = 0; + Diagnostic(ErrorCode.ERR_BadMemberFlag, "P5").WithArguments("override").WithLocation(20, 25), + // (20,25): error CS8052: Auto-implemented properties inside interfaces cannot have initializers. + // override sealed int P5 {get;} = 0; + Diagnostic(ErrorCode.ERR_AutoPropertyInitializerInInterface, "P5").WithArguments("I5.P5").WithLocation(20, 25), + // (20,29): error CS0501: 'I5.P5.get' must declare a body because it is not marked abstract, extern, or partial + // override sealed int P5 {get;} = 0; + Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "get").WithArguments("I5.P5.get").WithLocation(20, 29), + // (23,15): error CS0535: 'Test1' does not implement interface member 'I1.P1' + // class Test1 : I1, I2, I3, I4, I5 + Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test1", "I1.P1").WithLocation(23, 15), + // (23,19): error CS0535: 'Test1' does not implement interface member 'I2.P2' + // class Test1 : I1, I2, I3, I4, I5 + Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I2").WithArguments("Test1", "I2.P2").WithLocation(23, 19), + // (30,12): error CS0122: 'I2.P2' is inaccessible due to its protection level + // int I2.P2 => 0; + Diagnostic(ErrorCode.ERR_BadAccess, "P2").WithArguments("I2.P2").WithLocation(30, 12), + // (31,12): error CS0539: 'Test2.P3' in explicit interface declaration is not found among members of the interface that can be implemented + // int I3.P3 { get => 0; set => throw null;} + Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "P3").WithArguments("Test2.P3").WithLocation(31, 12), + // (32,12): error CS0539: 'Test2.P4' in explicit interface declaration is not found among members of the interface that can be implemented + // int I4.P4 { get => 0; set => throw null;} + Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "P4").WithArguments("Test2.P4").WithLocation(32, 12), + // (33,12): error CS0539: 'Test2.P5' in explicit interface declaration is not found among members of the interface that can be implemented + // int I5.P5 => 0; + Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "P5").WithArguments("Test2.P5").WithLocation(33, 12), + // (12,27): warning CS0626: Method, operator, or accessor 'I3.P3.get' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. + // static extern int P3 {get; set;} + Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "get").WithArguments("I3.P3.get").WithLocation(12, 27), + // (12,32): warning CS0626: Method, operator, or accessor 'I3.P3.set' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. + // static extern int P3 {get; set;} + Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "set").WithArguments("I3.P3.set").WithLocation(12, 32) + ); + } + + private void ValidatePropertyModifiers_18(string source1, params DiagnosticDescription[] expected) + { + var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation1.VerifyDiagnostics(expected); + + var test1 = compilation1.GetTypeByMetadataName("Test1"); + var test2 = compilation1.GetTypeByMetadataName("Test2"); + var p1 = GetSingleProperty(compilation1, "I1"); + var test2P1 = test2.GetMembers().OfType().Where(p => p.Name.StartsWith("I1.")).Single(); + + Assert.True(p1.IsAbstract); + Assert.False(p1.IsVirtual); + Assert.False(p1.IsSealed); + Assert.False(p1.IsStatic); + Assert.False(p1.IsExtern); + Assert.False(p1.IsOverride); + Assert.Equal(Accessibility.Public, p1.DeclaredAccessibility); + Assert.Null(test1.FindImplementationForInterfaceMember(p1)); + Assert.Same(test2P1, test2.FindImplementationForInterfaceMember(p1)); + + ValidateP1Accessor(p1.GetMethod, test2P1.GetMethod); + ValidateP1Accessor(p1.SetMethod, test2P1.SetMethod); + void ValidateP1Accessor(MethodSymbol accessor, MethodSymbol implementation) + { + Assert.True(accessor.IsAbstract); + Assert.False(accessor.IsVirtual); + Assert.True(accessor.IsMetadataVirtual()); + Assert.False(accessor.IsSealed); + Assert.False(accessor.IsStatic); + Assert.False(accessor.IsExtern); + Assert.False(accessor.IsAsync); + Assert.False(accessor.IsOverride); + Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); + Assert.Null(test1.FindImplementationForInterfaceMember(accessor)); + Assert.Same(implementation, test2.FindImplementationForInterfaceMember(accessor)); + } + + var p2 = GetSingleProperty(compilation1, "I2"); + var test2P2 = test2.GetMembers().OfType().Where(p => p.Name.StartsWith("I2.")).Single(); + var p2get = p2.GetMethod; + + Assert.True(p2.IsAbstract); + Assert.False(p2.IsVirtual); + Assert.False(p2.IsSealed); + Assert.False(p2.IsStatic); + Assert.False(p2.IsExtern); + Assert.False(p2.IsOverride); + Assert.Equal(Accessibility.Private, p2.DeclaredAccessibility); + Assert.Null(test1.FindImplementationForInterfaceMember(p2)); + Assert.Same(test2P2, test2.FindImplementationForInterfaceMember(p2)); + + Assert.True(p2get.IsAbstract); + Assert.False(p2get.IsVirtual); + Assert.True(p2get.IsMetadataVirtual()); + Assert.False(p2get.IsSealed); + Assert.False(p2get.IsStatic); + Assert.False(p2get.IsExtern); + Assert.False(p2get.IsAsync); + Assert.False(p2get.IsOverride); + Assert.Equal(Accessibility.Private, p2get.DeclaredAccessibility); + Assert.Null(test1.FindImplementationForInterfaceMember(p2get)); + Assert.Same(test2P2.GetMethod, test2.FindImplementationForInterfaceMember(p2get)); + + var p3 = GetSingleProperty(compilation1, "I3"); + var test2P3 = test2.GetMembers().OfType().Where(p => p.Name.StartsWith("I3.")).Single(); + + Assert.False(p3.IsAbstract); + Assert.Equal(p3.IsIndexer, p3.IsVirtual); + Assert.False(p3.IsSealed); + Assert.Equal(!p3.IsIndexer, p3.IsStatic); + Assert.True(p3.IsExtern); + Assert.False(p3.IsOverride); + Assert.Equal(Accessibility.Public, p3.DeclaredAccessibility); + Assert.Same(p3.IsIndexer ? p3 : null, test1.FindImplementationForInterfaceMember(p3)); + Assert.Same(p3.IsIndexer ? test2P3 : null, test2.FindImplementationForInterfaceMember(p3)); + + ValidateP3Accessor(p3.GetMethod, p3.IsIndexer ? test2P3.GetMethod : null); + ValidateP3Accessor(p3.SetMethod, p3.IsIndexer ? test2P3.SetMethod : null); + void ValidateP3Accessor(MethodSymbol accessor, MethodSymbol implementation) + { + Assert.False(accessor.IsAbstract); + Assert.Equal(p3.IsIndexer, accessor.IsVirtual); + Assert.Equal(p3.IsIndexer, accessor.IsMetadataVirtual()); + Assert.False(accessor.IsSealed); + Assert.Equal(!p3.IsIndexer, accessor.IsStatic); + Assert.True(accessor.IsExtern); + Assert.False(accessor.IsAsync); + Assert.False(accessor.IsOverride); + Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); + Assert.Same(p3.IsIndexer ? accessor : null, test1.FindImplementationForInterfaceMember(accessor)); + Assert.Same(implementation, test2.FindImplementationForInterfaceMember(accessor)); + } + + var p4 = GetSingleProperty(compilation1, "I4"); + var test2P4 = test2.GetMembers().OfType().Where(p => p.Name.StartsWith("I4.")).Single(); + + Assert.True(p4.IsAbstract); + Assert.False(p4.IsVirtual); + Assert.False(p4.IsSealed); + Assert.Equal(!p4.IsIndexer, p4.IsStatic); + Assert.False(p4.IsExtern); + Assert.False(p4.IsOverride); + Assert.Equal(Accessibility.Public, p4.DeclaredAccessibility); + Assert.Null(test1.FindImplementationForInterfaceMember(p4)); + Assert.Same(p4.IsIndexer ? test2P4 : null, test2.FindImplementationForInterfaceMember(p4)); + + ValidateP4Accessor(p4.GetMethod, p4.IsIndexer ? test2P4.GetMethod : null); + ValidateP4Accessor(p4.SetMethod, p4.IsIndexer ? test2P4.SetMethod : null); + void ValidateP4Accessor(MethodSymbol accessor, MethodSymbol implementation) + { + Assert.True(accessor.IsAbstract); + Assert.False(accessor.IsVirtual); + Assert.True(accessor.IsMetadataVirtual()); + Assert.False(accessor.IsSealed); + Assert.Equal(!p4.IsIndexer, accessor.IsStatic); + Assert.False(accessor.IsExtern); + Assert.False(accessor.IsAsync); + Assert.False(accessor.IsOverride); + Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); + Assert.Null(test1.FindImplementationForInterfaceMember(accessor)); + Assert.Same(implementation, test2.FindImplementationForInterfaceMember(accessor)); + } + + var p5 = GetSingleProperty(compilation1, "I5"); + var p5get = p5.GetMethod; + + Assert.False(p5.IsAbstract); + Assert.False(p5.IsVirtual); + Assert.False(p5.IsSealed); + Assert.False(p5.IsStatic); + Assert.False(p5.IsExtern); + Assert.False(p5.IsOverride); + Assert.Equal(Accessibility.Public, p5.DeclaredAccessibility); + Assert.Null(test1.FindImplementationForInterfaceMember(p5)); + Assert.Null(test2.FindImplementationForInterfaceMember(p5)); + + Assert.False(p5get.IsAbstract); + Assert.False(p5get.IsVirtual); + Assert.False(p5get.IsMetadataVirtual()); + Assert.False(p5get.IsSealed); + Assert.False(p5get.IsStatic); + Assert.False(p5get.IsExtern); + Assert.False(p5get.IsAsync); + Assert.False(p5get.IsOverride); + Assert.Equal(Accessibility.Public, p5get.DeclaredAccessibility); + Assert.Null(test1.FindImplementationForInterfaceMember(p5get)); + Assert.Null(test2.FindImplementationForInterfaceMember(p5get)); + } + + [Fact] + public void PropertyModifiers_19() + { + var source1 = +@" + +public interface I2 {} + +public interface I1 +{ + public int I2.P01 {get; set;} + protected int I2.P02 {get;} + protected internal int I2.P03 {set;} + internal int I2.P04 {get;} + private int I2.P05 {set;} + static int I2.P06 {get;} + virtual int I2.P07 {set;} + sealed int I2.P08 {get;} + override int I2.P09 {set;} + abstract int I2.P10 {get;} + extern int I2.P11 {get; set;} + + int I2.P12 { public get; set;} + int I2.P13 { get; protected set;} + int I2.P14 { protected internal get; set;} + int I2.P15 { get; internal set;} + int I2.P16 { private get; set;} + int I2.P17 { private get;} +} +"; + var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + var expected = new[] + { + // (7,19): error CS0106: The modifier 'public' is not valid for this item + // public int I2.P01 {get; set;} + Diagnostic(ErrorCode.ERR_BadMemberFlag, "P01").WithArguments("public").WithLocation(7, 19), + // (7,19): error CS0541: 'I1.P01': explicit interface declaration can only be declared in a class or struct + // public int I2.P01 {get; set;} + Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "P01").WithArguments("I1.P01").WithLocation(7, 19), + // (8,22): error CS0106: The modifier 'protected' is not valid for this item + // protected int I2.P02 {get;} + Diagnostic(ErrorCode.ERR_BadMemberFlag, "P02").WithArguments("protected").WithLocation(8, 22), + // (8,22): error CS0541: 'I1.P02': explicit interface declaration can only be declared in a class or struct + // protected int I2.P02 {get;} + Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "P02").WithArguments("I1.P02").WithLocation(8, 22), + // (9,31): error CS0106: The modifier 'protected internal' is not valid for this item + // protected internal int I2.P03 {set;} + Diagnostic(ErrorCode.ERR_BadMemberFlag, "P03").WithArguments("protected internal").WithLocation(9, 31), + // (9,31): error CS0541: 'I1.P03': explicit interface declaration can only be declared in a class or struct + // protected internal int I2.P03 {set;} + Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "P03").WithArguments("I1.P03").WithLocation(9, 31), + // (10,21): error CS0106: The modifier 'internal' is not valid for this item + // internal int I2.P04 {get;} + Diagnostic(ErrorCode.ERR_BadMemberFlag, "P04").WithArguments("internal").WithLocation(10, 21), + // (10,21): error CS0541: 'I1.P04': explicit interface declaration can only be declared in a class or struct + // internal int I2.P04 {get;} + Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "P04").WithArguments("I1.P04").WithLocation(10, 21), + // (11,20): error CS0106: The modifier 'private' is not valid for this item + // private int I2.P05 {set;} + Diagnostic(ErrorCode.ERR_BadMemberFlag, "P05").WithArguments("private").WithLocation(11, 20), + // (11,20): error CS0541: 'I1.P05': explicit interface declaration can only be declared in a class or struct + // private int I2.P05 {set;} + Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "P05").WithArguments("I1.P05").WithLocation(11, 20), + // (12,19): error CS0106: The modifier 'static' is not valid for this item + // static int I2.P06 {get;} + Diagnostic(ErrorCode.ERR_BadMemberFlag, "P06").WithArguments("static").WithLocation(12, 19), + // (12,19): error CS0541: 'I1.P06': explicit interface declaration can only be declared in a class or struct + // static int I2.P06 {get;} + Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "P06").WithArguments("I1.P06").WithLocation(12, 19), + // (13,20): error CS0106: The modifier 'virtual' is not valid for this item + // virtual int I2.P07 {set;} + Diagnostic(ErrorCode.ERR_BadMemberFlag, "P07").WithArguments("virtual").WithLocation(13, 20), + // (13,20): error CS0541: 'I1.P07': explicit interface declaration can only be declared in a class or struct + // virtual int I2.P07 {set;} + Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "P07").WithArguments("I1.P07").WithLocation(13, 20), + // (14,19): error CS0106: The modifier 'sealed' is not valid for this item + // sealed int I2.P08 {get;} + Diagnostic(ErrorCode.ERR_BadMemberFlag, "P08").WithArguments("sealed").WithLocation(14, 19), + // (14,19): error CS0541: 'I1.P08': explicit interface declaration can only be declared in a class or struct + // sealed int I2.P08 {get;} + Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "P08").WithArguments("I1.P08").WithLocation(14, 19), + // (15,21): error CS0106: The modifier 'override' is not valid for this item + // override int I2.P09 {set;} + Diagnostic(ErrorCode.ERR_BadMemberFlag, "P09").WithArguments("override").WithLocation(15, 21), + // (15,21): error CS0541: 'I1.P09': explicit interface declaration can only be declared in a class or struct + // override int I2.P09 {set;} + Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "P09").WithArguments("I1.P09").WithLocation(15, 21), + // (16,21): error CS0106: The modifier 'abstract' is not valid for this item + // abstract int I2.P10 {get;} + Diagnostic(ErrorCode.ERR_BadMemberFlag, "P10").WithArguments("abstract").WithLocation(16, 21), + // (16,21): error CS0541: 'I1.P10': explicit interface declaration can only be declared in a class or struct + // abstract int I2.P10 {get;} + Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "P10").WithArguments("I1.P10").WithLocation(16, 21), + // (17,19): error CS0106: The modifier 'extern' is not valid for this item + // extern int I2.P11 {get; set;} + Diagnostic(ErrorCode.ERR_BadMemberFlag, "P11").WithArguments("extern").WithLocation(17, 19), + // (17,19): error CS0541: 'I1.P11': explicit interface declaration can only be declared in a class or struct + // extern int I2.P11 {get; set;} + Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "P11").WithArguments("I1.P11").WithLocation(17, 19), + // (19,12): error CS0541: 'I1.P12': explicit interface declaration can only be declared in a class or struct + // int I2.P12 { public get; set;} + Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "P12").WithArguments("I1.P12").WithLocation(19, 12), + // (19,25): error CS0106: The modifier 'public' is not valid for this item + // int I2.P12 { public get; set;} + Diagnostic(ErrorCode.ERR_BadMemberFlag, "get").WithArguments("public").WithLocation(19, 25), + // (20,12): error CS0541: 'I1.P13': explicit interface declaration can only be declared in a class or struct + // int I2.P13 { get; protected set;} + Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "P13").WithArguments("I1.P13").WithLocation(20, 12), + // (20,33): error CS0106: The modifier 'protected' is not valid for this item + // int I2.P13 { get; protected set;} + Diagnostic(ErrorCode.ERR_BadMemberFlag, "set").WithArguments("protected").WithLocation(20, 33), + // (21,12): error CS0541: 'I1.P14': explicit interface declaration can only be declared in a class or struct + // int I2.P14 { protected internal get; set;} + Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "P14").WithArguments("I1.P14").WithLocation(21, 12), + // (21,37): error CS0106: The modifier 'protected internal' is not valid for this item + // int I2.P14 { protected internal get; set;} + Diagnostic(ErrorCode.ERR_BadMemberFlag, "get").WithArguments("protected internal").WithLocation(21, 37), + // (22,12): error CS0541: 'I1.P15': explicit interface declaration can only be declared in a class or struct + // int I2.P15 { get; internal set;} + Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "P15").WithArguments("I1.P15").WithLocation(22, 12), + // (22,32): error CS0106: The modifier 'internal' is not valid for this item + // int I2.P15 { get; internal set;} + Diagnostic(ErrorCode.ERR_BadMemberFlag, "set").WithArguments("internal").WithLocation(22, 32), + // (23,12): error CS0541: 'I1.P16': explicit interface declaration can only be declared in a class or struct + // int I2.P16 { private get; set;} + Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "P16").WithArguments("I1.P16").WithLocation(23, 12), + // (23,26): error CS0106: The modifier 'private' is not valid for this item + // int I2.P16 { private get; set;} + Diagnostic(ErrorCode.ERR_BadMemberFlag, "get").WithArguments("private").WithLocation(23, 26), + // (24,12): error CS0541: 'I1.P17': explicit interface declaration can only be declared in a class or struct + // int I2.P17 { private get;} + Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "P17").WithArguments("I1.P17").WithLocation(24, 12), + // (24,26): error CS0106: The modifier 'private' is not valid for this item + // int I2.P17 { private get;} + Diagnostic(ErrorCode.ERR_BadMemberFlag, "get").WithArguments("private").WithLocation(24, 26) + }; + + compilation1.VerifyDiagnostics(expected); + + ValidateSymbolsPropertyModifiers_19(compilation1); + + var compilation2 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp7)); + Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation2.VerifyDiagnostics(expected); + + ValidateSymbolsPropertyModifiers_19(compilation2); + } + + private static void ValidateSymbolsPropertyModifiers_19(CSharpCompilation compilation1) + { + var i1 = compilation1.GetTypeByMetadataName("I1"); + + foreach (var propertyName in new[] { "I2.P01", "I2.P02", "I2.P03", "I2.P04", "I2.P05", "I2.P06", "I2.P07", "I2.P08", "I2.P09", "I2.P10", + "I2.P11", "I2.P12", "I2.P13", "I2.P14", "I2.P15", "I2.P16", "I2.P17" }) + { + ValidateSymbolsPropertyModifiers_19(i1.GetMember(propertyName)); + + } + } + + private static void ValidateSymbolsPropertyModifiers_19(PropertySymbol p01) + { + Assert.True(p01.IsAbstract); + Assert.False(p01.IsVirtual); + Assert.False(p01.IsSealed); + Assert.False(p01.IsStatic); + Assert.False(p01.IsExtern); + Assert.False(p01.IsOverride); + Assert.Equal(Accessibility.Public, p01.DeclaredAccessibility); + + ValidateAccessor(p01.GetMethod); + ValidateAccessor(p01.SetMethod); + + void ValidateAccessor(MethodSymbol accessor) + { + if ((object)accessor == null) + { + return; + } + + Assert.True(accessor.IsAbstract); + Assert.False(accessor.IsVirtual); + Assert.True(accessor.IsMetadataVirtual()); + Assert.False(accessor.IsSealed); + Assert.False(accessor.IsStatic); + Assert.False(accessor.IsExtern); + Assert.False(accessor.IsAsync); + Assert.False(accessor.IsOverride); + Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); + } + } + + [Fact] + public void PropertyModifiers_20() + { + var source1 = +@" +public interface I1 +{ + internal int P1 + { + get + { + System.Console.WriteLine(""get_P1""); + return 0; + } + set + { + System.Console.WriteLine(""set_P1""); + } + } + + void M2() {P1 = P1;} +} +"; + + var source2 = +@" +class Test1 : I1 +{ + static void Main() + { + I1 x = new Test1(); + x.M2(); + } +} +"; + + ValidatePropertyModifiers_20(source1, source2); + } + + private void ValidatePropertyModifiers_20(string source1, string source2) + { + var compilation1 = CreateStandardCompilation(source1 + source2, options: TestOptions.DebugExe, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + CompileAndVerify(compilation1, verify: false, symbolValidator: Validate1); + + Validate1(compilation1.SourceModule); + + void Validate1(ModuleSymbol m) + { + var test1 = m.GlobalNamespace.GetTypeMember("Test1"); + var i1 = test1.Interfaces.Single(); + var p1 = GetSingleProperty(i1); + var p1get = p1.GetMethod; + var p1set = p1.SetMethod; + + ValidateProperty(p1); + ValidateMethod(p1get); + ValidateMethod(p1set); + Assert.Same(p1, test1.FindImplementationForInterfaceMember(p1)); + Assert.Same(p1get, test1.FindImplementationForInterfaceMember(p1get)); + Assert.Same(p1set, test1.FindImplementationForInterfaceMember(p1set)); + } + + void ValidateProperty(PropertySymbol p1) + { + Assert.False(p1.IsAbstract); + Assert.True(p1.IsVirtual); + Assert.False(p1.IsSealed); + Assert.False(p1.IsStatic); + Assert.False(p1.IsExtern); + Assert.False(p1.IsOverride); + Assert.Equal(Accessibility.Internal, p1.DeclaredAccessibility); + } + + void ValidateMethod(MethodSymbol m1) + { + Assert.False(m1.IsAbstract); + Assert.True(m1.IsVirtual); + Assert.True(m1.IsMetadataVirtual()); + Assert.False(m1.IsSealed); + Assert.False(m1.IsStatic); + Assert.False(m1.IsExtern); + Assert.False(m1.IsAsync); + Assert.False(m1.IsOverride); + Assert.Equal(Accessibility.Internal, m1.DeclaredAccessibility); + } + + var compilation2 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation2.VerifyDiagnostics(); + + { + var i1 = compilation2.GetTypeByMetadataName("I1"); + var p1 = GetSingleProperty(i1); + var p1get = p1.GetMethod; + var p1set = p1.SetMethod; + + ValidateProperty(p1); + ValidateMethod(p1get); + ValidateMethod(p1set); + } + + var compilation3 = CreateStandardCompilation(source2, new[] { compilation2.ToMetadataReference() }, options: TestOptions.DebugExe, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + CompileAndVerify(compilation3, verify: false, symbolValidator: Validate1); + + Validate1(compilation3.SourceModule); + + var compilation4 = CreateStandardCompilation(source2, new[] { compilation2.EmitToImageReference() }, options: TestOptions.DebugExe, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation4.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + CompileAndVerify(compilation4, verify: false, symbolValidator: Validate1); + + Validate1(compilation4.SourceModule); + } + + [Fact] + public void PropertyModifiers_21() + { + var source1 = +@" +public interface I1 +{ + private static int P1 { get => throw null; set => throw null; } + + internal static int P2 { get => throw null; set => throw null; } + + public static int P3 { get => throw null; set => throw null; } + + static int P4 { get => throw null; set => throw null; } +} + +class Test1 +{ + static void Main() + { + int x; + x = I1.P1; + I1.P1 = x; + x = I1.P2; + I1.P2 = x; + x = I1.P3; + I1.P3 = x; + x = I1.P4; + I1.P4 = x; + } +} +"; + var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation1.VerifyDiagnostics( + // (18,16): error CS0122: 'I1.P1' is inaccessible due to its protection level + // x = I1.P1; + Diagnostic(ErrorCode.ERR_BadAccess, "P1").WithArguments("I1.P1").WithLocation(18, 16), + // (19,12): error CS0122: 'I1.P1' is inaccessible due to its protection level + // I1.P1 = x; + Diagnostic(ErrorCode.ERR_BadAccess, "P1").WithArguments("I1.P1").WithLocation(19, 12) + ); + + var source2 = +@" +class Test2 +{ + static void Main() + { + int x; + x = I1.P1; + I1.P1 = x; + x = I1.P2; + I1.P2 = x; + x = I1.P3; + I1.P3 = x; + x = I1.P4; + I1.P4 = x; + } +} +"; + var compilation2 = CreateStandardCompilation(source2, new[] { compilation1.ToMetadataReference() }, + options: TestOptions.DebugDll, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation2.VerifyDiagnostics( + // (7,16): error CS0122: 'I1.P1' is inaccessible due to its protection level + // x = I1.P1; + Diagnostic(ErrorCode.ERR_BadAccess, "P1").WithArguments("I1.P1").WithLocation(7, 16), + // (8,12): error CS0122: 'I1.P1' is inaccessible due to its protection level + // I1.P1 = x; + Diagnostic(ErrorCode.ERR_BadAccess, "P1").WithArguments("I1.P1").WithLocation(8, 12), + // (9,16): error CS0122: 'I1.P2' is inaccessible due to its protection level + // x = I1.P2; + Diagnostic(ErrorCode.ERR_BadAccess, "P2").WithArguments("I1.P2").WithLocation(9, 16), + // (10,12): error CS0122: 'I1.P2' is inaccessible due to its protection level + // I1.P2 = x; + Diagnostic(ErrorCode.ERR_BadAccess, "P2").WithArguments("I1.P2").WithLocation(10, 12) + ); + } + + [Fact] + public void PropertyModifiers_22() + { + var source1 = +@" +public interface I1 +{ + public int P1 + { + internal get + { + System.Console.WriteLine(""get_P1""); + return 0; + } + set + { + System.Console.WriteLine(""set_P1""); + } + } +} +public interface I2 +{ + int P2 + { + get + { + System.Console.WriteLine(""get_P2""); + return 0; + } + internal set + { + System.Console.WriteLine(""set_P2""); + } + } +} +public interface I3 +{ + int P3 + { + internal get => Test1.GetP3(); + set => System.Console.WriteLine(""set_P3""); + } +} +public interface I4 +{ + int P4 + { + get => Test1.GetP4(); + internal set => System.Console.WriteLine(""set_P4""); + } +} +public interface I5 +{ + int P5 + { + private get + { + System.Console.WriteLine(""get_P5""); + return 0; + } + set + { + System.Console.WriteLine(""set_P5""); + } + } + + void Test() + { + P5 = P5; + } +} +public interface I6 +{ + int P6 + { + get + { + System.Console.WriteLine(""get_P6""); + return 0; + } + private set + { + System.Console.WriteLine(""set_P6""); + } + } + + void Test() + { + P6 = P6; + } +} +public interface I7 +{ + int P7 + { + private get => Test1.GetP7(); + set => System.Console.WriteLine(""set_P7""); + } + + void Test() + { + P7 = P7; + } +} +public interface I8 +{ + int P8 + { + get => Test1.GetP8(); + private set => System.Console.WriteLine(""set_P8""); + } + + void Test() + { + P8 = P8; + } +} + +class Test1 : I1, I2, I3, I4, I5, I6, I7, I8 +{ + static void Main() + { + I1 i1 = new Test1(); + I2 i2 = new Test1(); + I3 i3 = new Test1(); + I4 i4 = new Test1(); + I5 i5 = new Test1(); + I6 i6 = new Test1(); + I7 i7 = new Test1(); + I8 i8 = new Test1(); + + i1.P1 = i1.P1; + i2.P2 = i2.P2; + i3.P3 = i3.P3; + i4.P4 = i4.P4; + i5.Test(); + i6.Test(); + i7.Test(); + i8.Test(); + } + + public static int GetP3() + { + System.Console.WriteLine(""get_P3""); + return 0; + } + + public static int GetP4() + { + System.Console.WriteLine(""get_P4""); + return 0; + } + + public static int GetP7() + { + System.Console.WriteLine(""get_P7""); + return 0; + } + + public static int GetP8() + { + System.Console.WriteLine(""get_P8""); + return 0; + } +} +"; + + ValidatePropertyModifiers_22(source1); + } + + private void ValidatePropertyModifiers_22(string source1) + { + var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All), + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + CompileAndVerify(compilation1, /*expectedOutput: +@"get_P1 +set_P1 +get_P2 +set_P2 +get_P3 +set_P3 +get_P4 +set_P4 +get_P5 +set_P5 +get_P6 +set_P6 +get_P7 +set_P7 +get_P8 +set_P8",*/ symbolValidator: Validate, verify: false); + + Validate(compilation1.SourceModule); + + void Validate(ModuleSymbol m) + { + var test1 = m.GlobalNamespace.GetTypeMember("Test1"); + + for (int i = 1; i <= 8; i++) + { + var i1 = m.GlobalNamespace.GetTypeMember("I" + i); + var p1 = GetSingleProperty(i1); + + Assert.False(p1.IsAbstract); + Assert.True(p1.IsVirtual); + Assert.False(p1.IsSealed); + Assert.False(p1.IsStatic); + Assert.False(p1.IsExtern); + Assert.False(p1.IsOverride); + Assert.Equal(Accessibility.Public, p1.DeclaredAccessibility); + Assert.Same(p1, test1.FindImplementationForInterfaceMember(p1)); + + switch (i) + { + case 1: + case 3: + ValidateAccessor(p1.GetMethod, Accessibility.Internal); + ValidateAccessor(p1.SetMethod, Accessibility.Public); + break; + case 2: + case 4: + ValidateAccessor(p1.GetMethod, Accessibility.Public); + ValidateAccessor(p1.SetMethod, Accessibility.Internal); + break; + case 5: + case 7: + ValidateAccessor(p1.GetMethod, Accessibility.Private); + ValidateAccessor(p1.SetMethod, Accessibility.Public); + break; + case 6: + case 8: + ValidateAccessor(p1.GetMethod, Accessibility.Public); + ValidateAccessor(p1.SetMethod, Accessibility.Private); + break; + default: + Assert.False(true); + break; + } + + void ValidateAccessor(MethodSymbol accessor, Accessibility access) + { + Assert.False(accessor.IsAbstract); + Assert.Equal(accessor.DeclaredAccessibility != Accessibility.Private, accessor.IsVirtual); + Assert.Equal(accessor.DeclaredAccessibility != Accessibility.Private, accessor.IsMetadataVirtual()); + Assert.False(accessor.IsSealed); + Assert.False(accessor.IsStatic); + Assert.False(accessor.IsExtern); + Assert.False(accessor.IsAsync); + Assert.False(accessor.IsOverride); + Assert.Equal(access, accessor.DeclaredAccessibility); + Assert.Same(accessor.DeclaredAccessibility == Accessibility.Private ? null : accessor, test1.FindImplementationForInterfaceMember(accessor)); + } + } + } + } + + [Fact] + public void PropertyModifiers_23_00() + { + var source1 = +@" +public interface I1 +{} +public interface I3 +{ + int P3 + { + private get + { + System.Console.WriteLine(""get_P3""); + return 0; + } + set {} + } + + void M2() + { + P3 = P3; + } +} +public interface I4 +{ + int P4 + { + get {throw null;} + private set {System.Console.WriteLine(""set_P4"");} + } + + void M2() + { + P4 = P4; + } +} +public interface I5 +{ + int P5 + { + private get => GetP5(); + set => throw null; + } + + private int GetP5() + { + System.Console.WriteLine(""get_P5""); + return 0; + } + + void M2() + { + P5 = P5; + } +} +public interface I6 +{ + int P6 + { + get => throw null; + private set => System.Console.WriteLine(""set_P6""); + } + + void M2() + { + P6 = P6; + } +} +"; + + var source2 = +@" +class Test1 : I1 +{ + static void Main() + { + I3 i3 = new Test3(); + I4 i4 = new Test4(); + I5 i5 = new Test5(); + I6 i6 = new Test6(); + i3.M2(); + i4.M2(); + i5.M2(); + i6.M2(); + } +} +class Test3 : I3 +{ + public int P3 + { + get + { + throw null; + } + set + { + System.Console.WriteLine(""set_P3""); + } + } +} +class Test4 : I4 +{ + public int P4 + { + get + { + System.Console.WriteLine(""get_P4""); + return 0; + } + set + { + throw null; + } + } +} +class Test5 : I5 +{ + public int P5 + { + get + { + throw null; + } + set + { + System.Console.WriteLine(""set_P5""); + } + } +} +class Test6 : I6 +{ + public int P6 + { + get + { + System.Console.WriteLine(""get_P6""); + return 0; + } + set + { + throw null; + } + } +} +"; + ValidatePropertyModifiers_23(source1, source2); + } + + private void ValidatePropertyModifiers_23(string source1, string source2) + { + var compilation1 = CreateStandardCompilation(source1 + source2, options: TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All), + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + CompileAndVerify(compilation1, verify: false, symbolValidator: Validate1); + + Validate1(compilation1.SourceModule); + + void Validate1(ModuleSymbol m) + { + var test1 = m.GlobalNamespace.GetTypeMember("Test1"); + var im = test1.Interfaces.Single().ContainingModule; + + ValidateProperty23(GetSingleProperty(im, "I3"), false, Accessibility.Private, Accessibility.Public, m.GlobalNamespace.GetTypeMember("Test3")); + ValidateProperty23(GetSingleProperty(im, "I4"), false, Accessibility.Public, Accessibility.Private, m.GlobalNamespace.GetTypeMember("Test4")); + ValidateProperty23(GetSingleProperty(im, "I5"), false, Accessibility.Private, Accessibility.Public, m.GlobalNamespace.GetTypeMember("Test5")); + ValidateProperty23(GetSingleProperty(im, "I6"), false, Accessibility.Public, Accessibility.Private, m.GlobalNamespace.GetTypeMember("Test6")); + } + + var compilation2 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation2.VerifyDiagnostics(); + + ValidateProperty23(GetSingleProperty(compilation2, "I3"), false, Accessibility.Private, Accessibility.Public); + ValidateProperty23(GetSingleProperty(compilation2, "I4"), false, Accessibility.Public, Accessibility.Private); + ValidateProperty23(GetSingleProperty(compilation2, "I5"), false, Accessibility.Private, Accessibility.Public); + ValidateProperty23(GetSingleProperty(compilation2, "I6"), false, Accessibility.Public, Accessibility.Private); + + var compilation3 = CreateStandardCompilation(source2, new[] { compilation2.ToMetadataReference() }, + options: TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All), + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + CompileAndVerify(compilation3, verify: false, symbolValidator: Validate1); + + Validate1(compilation3.SourceModule); + + var compilation4 = CreateStandardCompilation(source2, new[] { compilation2.EmitToImageReference() }, + options: TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All), + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation4.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + CompileAndVerify(compilation4, verify: false, symbolValidator: Validate1); + + Validate1(compilation4.SourceModule); + } + + private static void ValidateProperty23(PropertySymbol p1, bool isAbstract, Accessibility getAccess, Accessibility setAccess, NamedTypeSymbol test1 = null) + { + Assert.Equal(isAbstract, p1.IsAbstract); + Assert.NotEqual(isAbstract, p1.IsVirtual); + Assert.False(p1.IsSealed); + Assert.False(p1.IsStatic); + Assert.False(p1.IsExtern); + Assert.False(p1.IsOverride); + Assert.Equal(Accessibility.Public, p1.DeclaredAccessibility); + + if ((object)test1 != null) + { + Assert.Same(test1.GetMember(p1.Name), test1.FindImplementationForInterfaceMember(p1)); + } + + ValidateMethod23(p1.GetMethod, isAbstract, getAccess, test1); + ValidateMethod23(p1.SetMethod, isAbstract, setAccess, test1); + } + + private static void ValidateMethod23(MethodSymbol m1, bool isAbstract, Accessibility access, NamedTypeSymbol test1) + { + Assert.Equal(isAbstract, m1.IsAbstract); + Assert.NotEqual(isAbstract || access == Accessibility.Private, m1.IsVirtual); + Assert.Equal(isAbstract || access != Accessibility.Private, m1.IsMetadataVirtual()); + Assert.False(m1.IsSealed); + Assert.False(m1.IsStatic); + Assert.False(m1.IsExtern); + Assert.False(m1.IsAsync); + Assert.False(m1.IsOverride); + Assert.Equal(access, m1.DeclaredAccessibility); + + if ((object)test1 != null) + { + Assert.Same(access != Accessibility.Private ? test1.GetMember(m1.Name) : null, test1.FindImplementationForInterfaceMember(m1)); + } + } + + [Fact] + public void PropertyModifiers_23_01() + { + var source1 = +@" +public interface I1 +{ + abstract int P1 {internal get; set;} + + void M2() + { + P1 = P1; + } +} +"; + + var source2 = +@" +class Test1 : I1 +{ + static void Main() + { + } + + public int P1 + { + get + { + System.Console.WriteLine(""get_P1""); + return 0; + } + set + { + System.Console.WriteLine(""set_P1""); + } + } +} +"; + ValidatePropertyModifiers_23(source1, source2, Accessibility.Internal, Accessibility.Public, + // (2,15): error CS8504: 'Test1' does not implement interface member 'I1.P1.get'. 'Test1.P1.get' cannot implicitly implement a non-public member. + // class Test1 : I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test1", "I1.P1.get", "Test1.P1.get").WithLocation(2, 15) + ); + } + + private void ValidatePropertyModifiers_23(string source1, string source2, Accessibility getAccess, Accessibility setAccess, params DiagnosticDescription[] expected) + { + var compilation1 = CreateStandardCompilation(source2 + source1, options: TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All), + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation1.VerifyDiagnostics(expected); + + Validate1(compilation1.SourceModule); + + void Validate1(ModuleSymbol m) + { + var test1 = m.GlobalNamespace.GetTypeMember("Test1"); + var im = test1.Interfaces.Single().ContainingModule; + + ValidateProperty23(GetSingleProperty(im, "I1"), true, getAccess, setAccess, test1); + } + + var compilation2 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation2.VerifyDiagnostics(); + + ValidateProperty23(GetSingleProperty(compilation2, "I1"), true, getAccess, setAccess); + + var compilation3 = CreateStandardCompilation(source2, new[] { compilation2.ToMetadataReference() }, + options: TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All), + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation3.VerifyDiagnostics(expected); + + Validate1(compilation3.SourceModule); + + var compilation4 = CreateStandardCompilation(source2, new[] { compilation2.EmitToImageReference() }, + options: TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All), + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation4.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation4.VerifyDiagnostics(expected); + + Validate1(compilation4.SourceModule); + } + + [Fact] + public void PropertyModifiers_23_02() + { + var source1 = +@" +public interface I1 +{ + abstract int P1 {internal get; set;} +} + +public class TestHelper +{ + public static void CallP1(I1 x) {x.P1 = x.P1;} +} +"; + + var source2 = +@" +class Test1 : I1 +{ + static void Main() + { + TestHelper.CallP1(new Test1()); + } + + public virtual int P1 + { + get + { + System.Console.WriteLine(""get_P1""); + return 0; + } + set + { + System.Console.WriteLine(""set_P1""); + } + } +} +"; + + ValidatePropertyModifiers_11_02(source1, source2, + // (2,15): error CS8504: 'Test1' does not implement interface member 'I1.P1.get'. 'Test1.P1.get' cannot implicitly implement a non-public member. + // class Test1 : I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test1", "I1.P1.get", "Test1.P1.get").WithLocation(2, 15) + ); + } + + [Fact] + public void PropertyModifiers_23_03() + { + var source1 = +@" +public interface I1 +{ + abstract int P1 {internal get; set;} +} + +public class TestHelper +{ + public static void CallP1(I1 x) {x.P1 = x.P1;} +} +"; + + var source2 = +@" +class Test1 : I1 +{ + static void Main() + { + TestHelper.CallP1(new Test1()); + } + + int I1.P1 + { + get + { + System.Console.WriteLine(""get_P1""); + return 0; + } + set + { + System.Console.WriteLine(""set_P1""); + } + } +} +"; + + ValidatePropertyModifiers_11_03(source1, source2, + // (9,12): error CS0122: 'I1.P1.get' is inaccessible due to its protection level + // int I1.P1 + Diagnostic(ErrorCode.ERR_BadAccess, "P1").WithArguments("I1.P1.get").WithLocation(9, 12) + ); + } + + [Fact] + public void PropertyModifiers_23_04() + { + var source1 = +@" +public interface I1 +{ + abstract int P1 {internal get; set;} +} + +public class TestHelper +{ + public static void CallP1(I1 x) {x.P1 = x.P1;} +} + +public class Test2 : I1 +{ + int I1.P1 + { + get + { + System.Console.WriteLine(""Test2.get_P1""); + return 0; + } + set + { + System.Console.WriteLine(""Test2.set_P1""); + } + } +} + +"; + + var source2 = +@" +class Test1 : Test2, I1 +{ + static void Main() + { + TestHelper.CallP1(new Test1()); + } + + public int P1 + { + get + { + System.Console.WriteLine(""Test1.get_P1""); + return 0; + } + set + { + System.Console.WriteLine(""Test1.set_P1""); + } + } +} +"; + + ValidatePropertyModifiers_11_02(source1, source2, + // (2,22): error CS8504: 'Test1' does not implement interface member 'I1.P1.get'. 'Test1.P1.get' cannot implicitly implement a non-public member. + // class Test1 : Test2, I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test1", "I1.P1.get", "Test1.P1.get").WithLocation(2, 22) + ); + } + + [Fact] + public void PropertyModifiers_23_05() + { + var source1 = +@" +public interface I1 +{ + abstract int P1 {internal get; set;} +} + +public class TestHelper +{ + public static void CallP1(I1 x) {x.P1 = x.P1;} +} + +public class Test2 : I1 +{ + int I1.P1 + { + get + { + System.Console.WriteLine(""Test2.get_P1""); + return 0; + } + set + { + System.Console.WriteLine(""Test2.set_P1""); + } + } +} + +"; + + var source2 = +@" +class Test1 : Test2, I1 +{ + static void Main() + { + TestHelper.CallP1(new Test1()); + } + + public virtual int P1 + { + get + { + System.Console.WriteLine(""Test1.get_P1""); + return 0; + } + set + { + System.Console.WriteLine(""Test1.set_P1""); + } + } +} +"; + + ValidatePropertyModifiers_11_02(source1, source2, + // (2,22): error CS8504: 'Test1' does not implement interface member 'I1.P1.get'. 'Test1.P1.get' cannot implicitly implement a non-public member. + // class Test1 : Test2, I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test1", "I1.P1.get", "Test1.P1.get").WithLocation(2, 22) + ); + } + + [Fact] + public void PropertyModifiers_23_06() + { + var source1 = +@" +public interface I1 +{ + abstract int P1 {internal get; set;} +} + +public class TestHelper +{ + public static void CallP1(I1 x) {x.P1 = x.P1;} +} + +public class Test2 : I1 +{ + int I1.P1 + { + get + { + System.Console.WriteLine(""Test2.get_P1""); + return 0; + } + set + { + System.Console.WriteLine(""Test2.set_P1""); + } + } +} + +"; + + var source2 = +@"abstract +class Test1 : Test2, I1 +{ + static void Main() + { + TestHelper.CallP1(new Test3()); + } + + public abstract int P1 {get; set;} +} + +class Test3 : Test1 +{ + public override int P1 + { + get + { + System.Console.WriteLine(""Test3.get_P1""); + return 0; + } + set + { + System.Console.WriteLine(""Test3.set_P1""); + } + } +} +"; + + ValidatePropertyModifiers_11_02(source1, source2, + // (2,22): error CS8504: 'Test1' does not implement interface member 'I1.P1.get'. 'Test1.P1.get' cannot implicitly implement a non-public member. + // class Test1 : Test2, I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test1", "I1.P1.get", "Test1.P1.get").WithLocation(2, 22) + ); + } + + [Fact] + public void PropertyModifiers_23_07() + { + var source1 = +@" +public interface I1 +{ + abstract int P1 {internal get; set;} +} + +public class TestHelper +{ + public static void CallP1(I1 x) {x.P1 = x.P1;} +} + +public class Test2 : I1 +{ + int I1.P1 + { + get + { + System.Console.WriteLine(""Test2.get_P1""); + return 0; + } + set + { + System.Console.WriteLine(""Test2.set_P1""); + } + } +} + +"; + + var source2 = +@" +class Test1 : Test2, I1, I2 +{ + static void Main() + { + TestHelper.CallP1(new Test1()); + } + + public int P1 + { + get + { + System.Console.WriteLine(""Test1.get_P1""); + return 0; + } + set + { + System.Console.WriteLine(""Test1.set_P1""); + } + } +} + +public interface I2 +{ + int P1 {get; set;} +} +"; + + ValidatePropertyModifiers_11_02(source1, source2, + // (2,22): error CS8504: 'Test1' does not implement interface member 'I1.P1.get'. 'Test1.P1.get' cannot implicitly implement a non-public member. + // class Test1 : Test2, I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test1", "I1.P1.get", "Test1.P1.get").WithLocation(2, 22) + ); + } + + [Fact] + public void PropertyModifiers_23_08() + { + var source1 = +@" +public interface I1 +{ + abstract int P1 {internal get; set;} +} + +public class TestHelper +{ + public static void CallP1(I1 x) {x.P1 = x.P1;} +} + +public class Test2 : I1 +{ + int I1.P1 + { + get + { + System.Console.WriteLine(""Test2.get_P1""); + return 0; + } + set + { + System.Console.WriteLine(""Test2.set_P1""); + } + } +} + +"; + + var source2 = +@" +class Test1 : Test2, I1 +{ + static void Main() + { + TestHelper.CallP1(new Test1()); + } + + public virtual long P1 + { + get + { + System.Console.WriteLine(""Test1.get_P1""); + return 0; + } + set + { + System.Console.WriteLine(""Test1.set_P1""); + } + } +} +"; + + ValidatePropertyModifiers_11_08(source1, source2); + } + + [Fact] + public void PropertyModifiers_23_09() + { + var source1 = +@" +public interface I1 +{ + abstract int P1 {internal get; set;} +} + +public class TestHelper +{ + public static void CallP1(I1 x) {x.P1 = x.P1;} +} +"; + + var source2 = +@" +class Test1 : I1 +{ + static void Main() + { + TestHelper.CallP1(new Test1()); + } + + public virtual long P1 + { + get + { + System.Console.WriteLine(""Test1.get_P1""); + return 0; + } + set + { + System.Console.WriteLine(""Test1.set_P1""); + } + } +} +"; + + ValidatePropertyModifiers_11_09(source1, source2, + // (2,15): error CS0535: 'Test1' does not implement interface member 'I1.P1' + // class Test1 : I1 + Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test1", "I1.P1").WithLocation(2, 15) + ); + } + + [Fact] + public void PropertyModifiers_23_10() + { + var source1 = +@" +public interface I1 +{ + abstract int P1 {internal get; set;} +} +"; + + var source2 = +@" +public class Test2 : I1 +{ + public int P1 + { + get + { + return 0; + } + set {} + } +} +class Test1 : Test2, I1 +{ +} +"; + + ValidatePropertyModifiers_11_10(source1, source2, + // (2,22): error CS8504: 'Test2' does not implement interface member 'I1.P1.get'. 'Test2.P1.get' cannot implicitly implement a non-public member. + // public class Test2 : I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test2", "I1.P1.get", "Test2.P1.get").WithLocation(2, 22) + ); + } + + [Fact] + public void PropertyModifiers_23_11() + { + var source1 = +@" +public interface I1 +{ + abstract int P1 {internal get; set;} +} +public class Test2 : I1 +{ + public int P1 + { + get + { + return 0; + } + set {} + } +} +"; + + var source2 = +@" +class Test1 : Test2, I1 +{ +} +"; + + ValidatePropertyModifiers_11_11(source1, source2, + // (6,22): error CS8504: 'Test2' does not implement interface member 'I1.P1.get'. 'Test2.P1.get' cannot implicitly implement a non-public member. + // public class Test2 : I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test2", "I1.P1.get", "Test2.P1.get").WithLocation(6, 22) + ); + } + + [Fact] + public void PropertyModifiers_23_51() + { + var source1 = +@" +public interface I1 +{ + abstract int P1 {get; internal set;} + + void M2() + { + P1 = P1; + } +} +"; + + var source2 = +@" +class Test1 : I1 +{ + static void Main() + { + } + + public int P1 + { + get + { + System.Console.WriteLine(""get_P1""); + return 0; + } + set + { + System.Console.WriteLine(""set_P1""); + } + } +} +"; + ValidatePropertyModifiers_23(source1, source2, Accessibility.Public, Accessibility.Internal, + // (2,15): error CS8504: 'Test1' does not implement interface member 'I1.P1.set'. 'Test1.P1.set' cannot implicitly implement a non-public member. + // class Test1 : I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test1", "I1.P1.set", "Test1.P1.set").WithLocation(2, 15) + ); + } + + [Fact] + public void PropertyModifiers_23_52() + { + var source1 = +@" +public interface I1 +{ + abstract int P1 {get; internal set;} +} + +public class TestHelper +{ + public static void CallP1(I1 x) {x.P1 = x.P1;} +} +"; + + var source2 = +@" +class Test1 : I1 +{ + static void Main() + { + TestHelper.CallP1(new Test1()); + } + + public virtual int P1 + { + get + { + System.Console.WriteLine(""get_P1""); + return 0; + } + set + { + System.Console.WriteLine(""set_P1""); + } + } +} +"; + + ValidatePropertyModifiers_11_02(source1, source2, + // (2,15): error CS8504: 'Test1' does not implement interface member 'I1.P1.set'. 'Test1.P1.set' cannot implicitly implement a non-public member. + // class Test1 : I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test1", "I1.P1.set", "Test1.P1.set").WithLocation(2, 15) + ); + } + + [Fact] + public void PropertyModifiers_23_53() + { + var source1 = +@" +public interface I1 +{ + abstract int P1 {get; internal set;} +} + +public class TestHelper +{ + public static void CallP1(I1 x) {x.P1 = x.P1;} +} +"; + + var source2 = +@" +class Test1 : I1 +{ + static void Main() + { + TestHelper.CallP1(new Test1()); + } + + int I1.P1 + { + get + { + System.Console.WriteLine(""get_P1""); + return 0; + } + set + { + System.Console.WriteLine(""set_P1""); + } + } +} +"; + + ValidatePropertyModifiers_11_03(source1, source2, + // (9,12): error CS0122: 'I1.P1.set' is inaccessible due to its protection level + // int I1.P1 + Diagnostic(ErrorCode.ERR_BadAccess, "P1").WithArguments("I1.P1.set").WithLocation(9, 12) + ); + } + + [Fact] + public void PropertyModifiers_23_54() + { + var source1 = +@" +public interface I1 +{ + abstract int P1 {get; internal set;} +} + +public class TestHelper +{ + public static void CallP1(I1 x) {x.P1 = x.P1;} +} + +public class Test2 : I1 +{ + int I1.P1 + { + get + { + System.Console.WriteLine(""Test2.get_P1""); + return 0; + } + set + { + System.Console.WriteLine(""Test2.set_P1""); + } + } +} + +"; + + var source2 = +@" +class Test1 : Test2, I1 +{ + static void Main() + { + TestHelper.CallP1(new Test1()); + } + + public int P1 + { + get + { + System.Console.WriteLine(""Test1.get_P1""); + return 0; + } + set + { + System.Console.WriteLine(""Test1.set_P1""); + } + } +} +"; + + ValidatePropertyModifiers_11_02(source1, source2, + // (2,22): error CS8504: 'Test1' does not implement interface member 'I1.P1.set'. 'Test1.P1.set' cannot implicitly implement a non-public member. + // class Test1 : Test2, I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test1", "I1.P1.set", "Test1.P1.set").WithLocation(2, 22) + ); + } + + [Fact] + public void PropertyModifiers_23_55() + { + var source1 = +@" +public interface I1 +{ + abstract int P1 {get; internal set;} +} + +public class TestHelper +{ + public static void CallP1(I1 x) {x.P1 = x.P1;} +} + +public class Test2 : I1 +{ + int I1.P1 + { + get + { + System.Console.WriteLine(""Test2.get_P1""); + return 0; + } + set + { + System.Console.WriteLine(""Test2.set_P1""); + } + } +} + +"; + + var source2 = +@" +class Test1 : Test2, I1 +{ + static void Main() + { + TestHelper.CallP1(new Test1()); + } + + public virtual int P1 + { + get + { + System.Console.WriteLine(""Test1.get_P1""); + return 0; + } + set + { + System.Console.WriteLine(""Test1.set_P1""); + } + } +} +"; + + ValidatePropertyModifiers_11_02(source1, source2, + // (2,22): error CS8504: 'Test1' does not implement interface member 'I1.P1.set'. 'Test1.P1.set' cannot implicitly implement a non-public member. + // class Test1 : Test2, I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test1", "I1.P1.set", "Test1.P1.set").WithLocation(2, 22) + ); + } + + [Fact] + public void PropertyModifiers_23_56() + { + var source1 = +@" +public interface I1 +{ + abstract int P1 {get; internal set;} +} + +public class TestHelper +{ + public static void CallP1(I1 x) {x.P1 = x.P1;} +} + +public class Test2 : I1 +{ + int I1.P1 + { + get + { + System.Console.WriteLine(""Test2.get_P1""); + return 0; + } + set + { + System.Console.WriteLine(""Test2.set_P1""); + } + } +} + +"; + + var source2 = +@"abstract +class Test1 : Test2, I1 +{ + static void Main() + { + TestHelper.CallP1(new Test3()); + } + + public abstract int P1 {get; set;} +} + +class Test3 : Test1 +{ + public override int P1 + { + get + { + System.Console.WriteLine(""Test3.get_P1""); + return 0; + } + set + { + System.Console.WriteLine(""Test3.set_P1""); + } + } +} +"; + + ValidatePropertyModifiers_11_02(source1, source2, + // (2,22): error CS8504: 'Test1' does not implement interface member 'I1.P1.set'. 'Test1.P1.set' cannot implicitly implement a non-public member. + // class Test1 : Test2, I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test1", "I1.P1.set", "Test1.P1.set").WithLocation(2, 22) + ); + } + + [Fact] + public void PropertyModifiers_23_57() + { + var source1 = +@" +public interface I1 +{ + abstract int P1 {get; internal set;} +} + +public class TestHelper +{ + public static void CallP1(I1 x) {x.P1 = x.P1;} +} + +public class Test2 : I1 +{ + int I1.P1 + { + get + { + System.Console.WriteLine(""Test2.get_P1""); + return 0; + } + set + { + System.Console.WriteLine(""Test2.set_P1""); + } + } +} + +"; + + var source2 = +@" +class Test1 : Test2, I1, I2 +{ + static void Main() + { + TestHelper.CallP1(new Test1()); + } + + public int P1 + { + get + { + System.Console.WriteLine(""Test1.get_P1""); + return 0; + } + set + { + System.Console.WriteLine(""Test1.set_P1""); + } + } +} + +public interface I2 +{ + int P1 {get; set;} +} +"; + + ValidatePropertyModifiers_11_02(source1, source2, + // (2,22): error CS8504: 'Test1' does not implement interface member 'I1.P1.set'. 'Test1.P1.set' cannot implicitly implement a non-public member. + // class Test1 : Test2, I1, I2 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test1", "I1.P1.set", "Test1.P1.set").WithLocation(2, 22) + ); + } + + [Fact] + public void PropertyModifiers_23_58() + { + var source1 = +@" +public interface I1 +{ + abstract int P1 {get; internal set;} +} + +public class TestHelper +{ + public static void CallP1(I1 x) {x.P1 = x.P1;} +} + +public class Test2 : I1 +{ + int I1.P1 + { + get + { + System.Console.WriteLine(""Test2.get_P1""); + return 0; + } + set + { + System.Console.WriteLine(""Test2.set_P1""); + } + } +} + +"; + + var source2 = +@" +class Test1 : Test2, I1 +{ + static void Main() + { + TestHelper.CallP1(new Test1()); + } + + public virtual long P1 + { + get + { + System.Console.WriteLine(""Test1.get_P1""); + return 0; + } + set + { + System.Console.WriteLine(""Test1.set_P1""); + } + } +} +"; + + ValidatePropertyModifiers_11_08(source1, source2); + } + + [Fact] + public void PropertyModifiers_23_59() + { + var source1 = +@" +public interface I1 +{ + abstract int P1 {get; internal set;} +} + +public class TestHelper +{ + public static void CallP1(I1 x) {x.P1 = x.P1;} +} +"; + + var source2 = +@" +class Test1 : I1 +{ + static void Main() + { + TestHelper.CallP1(new Test1()); + } + + public virtual long P1 + { + get + { + System.Console.WriteLine(""Test1.get_P1""); + return 0; + } + set + { + System.Console.WriteLine(""Test1.set_P1""); + } + } +} +"; + + ValidatePropertyModifiers_11_09(source1, source2, + // (2,15): error CS0535: 'Test1' does not implement interface member 'I1.P1' + // class Test1 : I1 + Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test1", "I1.P1").WithLocation(2, 15) + ); + } + + [Fact] + public void PropertyModifiers_23_60() + { + var source1 = +@" +public interface I1 +{ + abstract int P1 {get; internal set;} +} +"; + + var source2 = +@" +public class Test2 : I1 +{ + public int P1 + { + get + { + return 0; + } + set {} + } +} +class Test1 : Test2, I1 +{ +} +"; + + ValidatePropertyModifiers_11_10(source1, source2, + // (2,22): error CS8504: 'Test2' does not implement interface member 'I1.P1.set'. 'Test2.P1.set' cannot implicitly implement a non-public member. + // public class Test2 : I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test2", "I1.P1.set", "Test2.P1.set").WithLocation(2, 22) + ); + } + + [Fact] + public void PropertyModifiers_23_61() + { + var source1 = +@" +public interface I1 +{ + abstract int P1 {get; internal set;} +} +public class Test2 : I1 +{ + public int P1 + { + get + { + return 0; + } + set {} + } +} +"; + + var source2 = +@" +class Test1 : Test2, I1 +{ +} +"; + + ValidatePropertyModifiers_11_11(source1, source2, + // (6,22): error CS8504: 'Test2' does not implement interface member 'I1.P1.set'. 'Test2.P1.set' cannot implicitly implement a non-public member. + // public class Test2 : I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test2", "I1.P1.set", "Test2.P1.set").WithLocation(6, 22) + ); + } + + [Fact] + public void PropertyModifiers_24() + { + var source1 = +@" +public interface I1 +{ + int P1 + { + get + { + System.Console.WriteLine(""get_P1""); + return 0; + } + internal set + { + System.Console.WriteLine(""set_P1""); + } + } + + void M2() {P1 = P1;} +} +"; + + var source2 = +@" +class Test1 : I1 +{ + static void Main() + { + I1 x = new Test1(); + x.M2(); + } +} +"; + ValidatePropertyModifiers_24(source1, source2); + } + + private void ValidatePropertyModifiers_24(string source1, string source2) + { + var compilation1 = CreateStandardCompilation(source1 + source2, options: TestOptions.DebugExe, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + CompileAndVerify(compilation1, verify: false, symbolValidator: Validate1); + + Validate1(compilation1.SourceModule); + + void Validate1(ModuleSymbol m) + { + var test1 = m.GlobalNamespace.GetTypeMember("Test1"); + var i1 = test1.Interfaces.Single(); + var p1 = GetSingleProperty(i1); + var p1get = p1.GetMethod; + var p1set = p1.SetMethod; + + ValidateProperty(p1); + ValidateMethod(p1get, Accessibility.Public); + ValidateMethod(p1set, Accessibility.Internal); + Assert.Same(p1, test1.FindImplementationForInterfaceMember(p1)); + Assert.Same(p1get, test1.FindImplementationForInterfaceMember(p1get)); + Assert.Same(p1set, test1.FindImplementationForInterfaceMember(p1set)); + } + + void ValidateProperty(PropertySymbol p1) + { + Assert.False(p1.IsAbstract); + Assert.True(p1.IsVirtual); + Assert.False(p1.IsSealed); + Assert.False(p1.IsStatic); + Assert.False(p1.IsExtern); + Assert.False(p1.IsOverride); + Assert.Equal(Accessibility.Public, p1.DeclaredAccessibility); + } + + void ValidateMethod(MethodSymbol m1, Accessibility access) + { + Assert.False(m1.IsAbstract); + Assert.True(m1.IsVirtual); + Assert.True(m1.IsMetadataVirtual()); + Assert.False(m1.IsSealed); + Assert.False(m1.IsStatic); + Assert.False(m1.IsExtern); + Assert.False(m1.IsAsync); + Assert.False(m1.IsOverride); + Assert.Equal(access, m1.DeclaredAccessibility); + } + + var compilation2 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation2.VerifyDiagnostics(); + + { + var i1 = compilation2.GetTypeByMetadataName("I1"); + var p1 = GetSingleProperty(i1); + var p1get = p1.GetMethod; + var p1set = p1.SetMethod; + + ValidateProperty(p1); + ValidateMethod(p1get, Accessibility.Public); + ValidateMethod(p1set, Accessibility.Internal); + } + + var compilation3 = CreateStandardCompilation(source2, new[] { compilation2.ToMetadataReference() }, options: TestOptions.DebugExe, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + CompileAndVerify(compilation3, verify: false, symbolValidator: Validate1); + + Validate1(compilation3.SourceModule); + + var compilation4 = CreateStandardCompilation(source2, new[] { compilation2.EmitToImageReference() }, options: TestOptions.DebugExe, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation4.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + CompileAndVerify(compilation4, verify: false, symbolValidator: Validate1); + + Validate1(compilation4.SourceModule); + } + + [Fact] + public void PropertyModifiers_25() + { + var source1 = +@" +public interface I1 +{ + static int P1 { private get => throw null; set => throw null; } + + static int P2 { internal get => throw null; set => throw null; } + + public static int P3 { get => throw null; private set => throw null; } + + static int P4 { get => throw null; internal set => throw null; } +} + +class Test1 +{ + static void Main() + { + int x; + x = I1.P1; + I1.P1 = x; + x = I1.P2; + I1.P2 = x; + x = I1.P3; + I1.P3 = x; + x = I1.P4; + I1.P4 = x; + } +} +"; + var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All), + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation1.VerifyDiagnostics( + // (18,13): error CS0271: The property or indexer 'I1.P1' cannot be used in this context because the get accessor is inaccessible + // x = I1.P1; + Diagnostic(ErrorCode.ERR_InaccessibleGetter, "I1.P1").WithArguments("I1.P1").WithLocation(18, 13), + // (23,9): error CS0272: The property or indexer 'I1.P3' cannot be used in this context because the set accessor is inaccessible + // I1.P3 = x; + Diagnostic(ErrorCode.ERR_InaccessibleSetter, "I1.P3").WithArguments("I1.P3").WithLocation(23, 9) + ); + + var source2 = +@" +class Test2 +{ + static void Main() + { + int x; + x = I1.P1; + I1.P1 = x; + x = I1.P2; + I1.P2 = x; + x = I1.P3; + I1.P3 = x; + x = I1.P4; + I1.P4 = x; + } +} +"; + var compilation2 = CreateStandardCompilation(source2, new[] { compilation1.ToMetadataReference() }, + options: TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All), + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation2.VerifyDiagnostics( + // (7,13): error CS0271: The property or indexer 'I1.P1' cannot be used in this context because the get accessor is inaccessible + // x = I1.P1; + Diagnostic(ErrorCode.ERR_InaccessibleGetter, "I1.P1").WithArguments("I1.P1").WithLocation(7, 13), + // (9,13): error CS0271: The property or indexer 'I1.P2' cannot be used in this context because the get accessor is inaccessible + // x = I1.P2; + Diagnostic(ErrorCode.ERR_InaccessibleGetter, "I1.P2").WithArguments("I1.P2").WithLocation(9, 13), + // (12,9): error CS0272: The property or indexer 'I1.P3' cannot be used in this context because the set accessor is inaccessible + // I1.P3 = x; + Diagnostic(ErrorCode.ERR_InaccessibleSetter, "I1.P3").WithArguments("I1.P3").WithLocation(12, 9), + // (14,9): error CS0272: The property or indexer 'I1.P4' cannot be used in this context because the set accessor is inaccessible + // I1.P4 = x; + Diagnostic(ErrorCode.ERR_InaccessibleSetter, "I1.P4").WithArguments("I1.P4").WithLocation(14, 9) + ); + } + + [Fact] + public void PropertyModifiers_26() + { + var source1 = +@" +public interface I1 +{ + abstract int P1 { private get; set; } + abstract int P2 { get; private set; } + abstract int P3 { internal get; } + static int P4 {internal get;} = 0; + static int P5 { internal get {throw null;} } + static int P6 { internal set {throw null;} } + static int P7 { internal get => throw null; } + static int P8 { internal set => throw null; } + static int P9 { internal get {throw null;} private set {throw null;}} + static int P10 { internal get => throw null; private set => throw null;} +} +"; + var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All), + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation1.VerifyDiagnostics( + // (4,31): error CS0442: 'I1.P1.get': abstract properties cannot have private accessors + // abstract int P1 { private get; set; } + Diagnostic(ErrorCode.ERR_PrivateAbstractAccessor, "get").WithArguments("I1.P1.get").WithLocation(4, 31), + // (5,36): error CS0442: 'I1.P2.set': abstract properties cannot have private accessors + // abstract int P2 { get; private set; } + Diagnostic(ErrorCode.ERR_PrivateAbstractAccessor, "set").WithArguments("I1.P2.set").WithLocation(5, 36), + // (6,18): error CS0276: 'I1.P3': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor + // abstract int P3 { internal get; } + Diagnostic(ErrorCode.ERR_AccessModMissingAccessor, "P3").WithArguments("I1.P3").WithLocation(6, 18), + // (7,16): error CS8052: Auto-implemented properties inside interfaces cannot have initializers. + // static int P4 {internal get;} = 0; + Diagnostic(ErrorCode.ERR_AutoPropertyInitializerInInterface, "P4").WithArguments("I1.P4").WithLocation(7, 16), + // (7,29): error CS0501: 'I1.P4.get' must declare a body because it is not marked abstract, extern, or partial + // static int P4 {internal get;} = 0; + Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "get").WithArguments("I1.P4.get").WithLocation(7, 29), + // (7,16): error CS0276: 'I1.P4': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor + // static int P4 {internal get;} = 0; + Diagnostic(ErrorCode.ERR_AccessModMissingAccessor, "P4").WithArguments("I1.P4").WithLocation(7, 16), + // (8,16): error CS0276: 'I1.P5': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor + // static int P5 { internal get {throw null;} } + Diagnostic(ErrorCode.ERR_AccessModMissingAccessor, "P5").WithArguments("I1.P5").WithLocation(8, 16), + // (9,16): error CS0276: 'I1.P6': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor + // static int P6 { internal set {throw null;} } + Diagnostic(ErrorCode.ERR_AccessModMissingAccessor, "P6").WithArguments("I1.P6").WithLocation(9, 16), + // (10,16): error CS0276: 'I1.P7': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor + // static int P7 { internal get => throw null; } + Diagnostic(ErrorCode.ERR_AccessModMissingAccessor, "P7").WithArguments("I1.P7").WithLocation(10, 16), + // (11,16): error CS0276: 'I1.P8': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor + // static int P8 { internal set => throw null; } + Diagnostic(ErrorCode.ERR_AccessModMissingAccessor, "P8").WithArguments("I1.P8").WithLocation(11, 16), + // (12,16): error CS0274: Cannot specify accessibility modifiers for both accessors of the property or indexer 'I1.P9' + // static int P9 { internal get {throw null;} private set {throw null;}} + Diagnostic(ErrorCode.ERR_DuplicatePropertyAccessMods, "P9").WithArguments("I1.P9").WithLocation(12, 16), + // (13,16): error CS0274: Cannot specify accessibility modifiers for both accessors of the property or indexer 'I1.P10' + // static int P10 { internal get => throw null; private set => throw null;} + Diagnostic(ErrorCode.ERR_DuplicatePropertyAccessMods, "P10").WithArguments("I1.P10").WithLocation(13, 16) + ); + } + + [Fact] + public void PropertyModifiers_27() + { + var source1 = +@" +public interface I1 +{ + int P3 + { + private get {throw null;} + set {} + } + + int P4 + { + get {throw null;} + private set {} + } +} + +class Test1 : I1 +{ + int I1.P3 + { + get {throw null;} + set {} + } + + int I1.P4 + { + get {throw null;} + set {} + } +} + +class Test2 : I1 +{ + int I1.P3 + { + set {} + } + + int I1.P4 + { + get => throw null; + } +} +"; + var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All), + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + + // PROTOTYPE(DefaultInterfaceImplementation): Private accessor is never virtual (the behavior goes back to native compiler). + // So, should we complain about them at all, or shoudl we treat private accessors + // as not implementable and ignore them for the purpose of interface implementation? + compilation1.VerifyDiagnostics( + // (19,12): error CS0122: 'I1.P3.get' is inaccessible due to its protection level + // int I1.P3 + Diagnostic(ErrorCode.ERR_BadAccess, "P3").WithArguments("I1.P3.get").WithLocation(19, 12), + // (25,12): error CS0122: 'I1.P4.set' is inaccessible due to its protection level + // int I1.P4 + Diagnostic(ErrorCode.ERR_BadAccess, "P4").WithArguments("I1.P4.set").WithLocation(25, 12), + // (34,12): error CS0122: 'I1.P3.get' is inaccessible due to its protection level + // int I1.P3 + Diagnostic(ErrorCode.ERR_BadAccess, "P3").WithArguments("I1.P3.get").WithLocation(34, 12), + // (34,12): error CS0551: Explicit interface implementation 'Test2.I1.P3' is missing accessor 'I1.P3.get' + // int I1.P3 + Diagnostic(ErrorCode.ERR_ExplicitPropertyMissingAccessor, "P3").WithArguments("Test2.I1.P3", "I1.P3.get").WithLocation(34, 12), + // (39,12): error CS0122: 'I1.P4.set' is inaccessible due to its protection level + // int I1.P4 + Diagnostic(ErrorCode.ERR_BadAccess, "P4").WithArguments("I1.P4.set").WithLocation(39, 12), + // (39,12): error CS0551: Explicit interface implementation 'Test2.I1.P4' is missing accessor 'I1.P4.set' + // int I1.P4 + Diagnostic(ErrorCode.ERR_ExplicitPropertyMissingAccessor, "P4").WithArguments("Test2.I1.P4", "I1.P4.set").WithLocation(39, 12) + ); + } + + [Fact] + public void IndexerModifiers_01() + { + var source1 = +@" +public interface I01{ public int this[int x] {get; set;} } +public interface I02{ protected int this[int x] {get;} } +public interface I03{ protected internal int this[int x] {set;} } +public interface I04{ internal int this[int x] {get;} } +public interface I05{ private int this[int x] {set;} } +public interface I06{ static int this[int x] {get;} } +public interface I07{ virtual int this[int x] {set;} } +public interface I08{ sealed int this[int x] {get;} } +public interface I09{ override int this[int x] {set;} } +public interface I10{ abstract int this[int x] {get;} } +public interface I11{ extern int this[int x] {get; set;} } + +public interface I12{ int this[int x] { public get; set;} } +public interface I13{ int this[int x] { get; protected set;} } +public interface I14{ int this[int x] { protected internal get; set;} } +public interface I15{ int this[int x] { get; internal set;} } +public interface I16{ int this[int x] { private get; set;} } +public interface I17{ int this[int x] { private get;} } +"; + var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation1.VerifyDiagnostics( + // (3,37): error CS0106: The modifier 'protected' is not valid for this item + // public interface I02{ protected int this[int x] {get;} } + Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("protected").WithLocation(3, 37), + // (4,46): error CS0106: The modifier 'protected internal' is not valid for this item + // public interface I03{ protected internal int this[int x] {set;} } + Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("protected internal").WithLocation(4, 46), + // (6,48): error CS0501: 'I05.this[int].set' must declare a body because it is not marked abstract, extern, or partial + // public interface I05{ private int this[int x] {set;} } + Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "set").WithArguments("I05.this[int].set").WithLocation(6, 48), + // (7,34): error CS0106: The modifier 'static' is not valid for this item + // public interface I06{ static int this[int x] {get;} } + Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("static").WithLocation(7, 34), + // (8,48): error CS0501: 'I07.this[int].set' must declare a body because it is not marked abstract, extern, or partial + // public interface I07{ virtual int this[int x] {set;} } + Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "set").WithArguments("I07.this[int].set").WithLocation(8, 48), + // (9,47): error CS0501: 'I08.this[int].get' must declare a body because it is not marked abstract, extern, or partial + // public interface I08{ sealed int this[int x] {get;} } + Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "get").WithArguments("I08.this[int].get").WithLocation(9, 47), + // (10,36): error CS0106: The modifier 'override' is not valid for this item + // public interface I09{ override int this[int x] {set;} } + Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("override").WithLocation(10, 36), + // (14,48): error CS0273: The accessibility modifier of the 'I12.this[int].get' accessor must be more restrictive than the property or indexer 'I12.this[int]' + // public interface I12{ int this[int x] { public get; set;} } + Diagnostic(ErrorCode.ERR_InvalidPropertyAccessMod, "get").WithArguments("I12.this[int].get", "I12.this[int]").WithLocation(14, 48), + // (15,56): error CS0106: The modifier 'protected' is not valid for this item + // public interface I13{ int this[int x] { get; protected set;} } + Diagnostic(ErrorCode.ERR_BadMemberFlag, "set").WithArguments("protected").WithLocation(15, 56), + // (16,60): error CS0106: The modifier 'protected internal' is not valid for this item + // public interface I14{ int this[int x] { protected internal get; set;} } + Diagnostic(ErrorCode.ERR_BadMemberFlag, "get").WithArguments("protected internal").WithLocation(16, 60), + // (18,49): error CS0442: 'I16.this[int].get': abstract properties cannot have private accessors + // public interface I16{ int this[int x] { private get; set;} } + Diagnostic(ErrorCode.ERR_PrivateAbstractAccessor, "get").WithArguments("I16.this[int].get").WithLocation(18, 49), + // (19,27): error CS0276: 'I17.this[int]': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor + // public interface I17{ int this[int x] { private get;} } + Diagnostic(ErrorCode.ERR_AccessModMissingAccessor, "this").WithArguments("I17.this[int]").WithLocation(19, 27), + // (12,47): warning CS0626: Method, operator, or accessor 'I11.this[int].get' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. + // public interface I11{ extern int this[int x] {get; set;} } + Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "get").WithArguments("I11.this[int].get").WithLocation(12, 47), + // (12,52): warning CS0626: Method, operator, or accessor 'I11.this[int].set' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. + // public interface I11{ extern int this[int x] {get; set;} } + Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "set").WithArguments("I11.this[int].set").WithLocation(12, 52) + ); + + ValidateSymbolsIndexerModifiers_01(compilation1); + } + + private static void ValidateSymbolsIndexerModifiers_01(CSharpCompilation compilation1) + { + var p01 = compilation1.GetMember("I01.this[]"); + + Assert.True(p01.IsAbstract); + Assert.False(p01.IsVirtual); + Assert.False(p01.IsSealed); + Assert.False(p01.IsStatic); + Assert.False(p01.IsExtern); + Assert.False(p01.IsOverride); + Assert.Equal(Accessibility.Public, p01.DeclaredAccessibility); + + VaidateP01Accessor(p01.GetMethod); + VaidateP01Accessor(p01.SetMethod); + void VaidateP01Accessor(MethodSymbol accessor) + { + Assert.True(accessor.IsAbstract); + Assert.False(accessor.IsVirtual); + Assert.True(accessor.IsMetadataVirtual()); + Assert.False(accessor.IsSealed); + Assert.False(accessor.IsStatic); + Assert.False(accessor.IsExtern); + Assert.False(accessor.IsAsync); + Assert.False(accessor.IsOverride); + Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); + } + + var p02 = compilation1.GetMember("I02.this[]"); + var p02get = p02.GetMethod; + + Assert.True(p02.IsAbstract); + Assert.False(p02.IsVirtual); + Assert.False(p02.IsSealed); + Assert.False(p02.IsStatic); + Assert.False(p02.IsExtern); + Assert.False(p02.IsOverride); + Assert.Equal(Accessibility.Public, p02.DeclaredAccessibility); + + Assert.True(p02get.IsAbstract); + Assert.False(p02get.IsVirtual); Assert.True(p02get.IsMetadataVirtual()); Assert.False(p02get.IsSealed); Assert.False(p02get.IsStatic); @@ -11743,881 +14346,3319 @@ void VaidateP01Accessor(MethodSymbol accessor) Assert.False(p02get.IsOverride); Assert.Equal(Accessibility.Public, p02get.DeclaredAccessibility); - var p03 = compilation1.GetMember("I03.this[]"); - var p03set = p03.SetMethod; + var p03 = compilation1.GetMember("I03.this[]"); + var p03set = p03.SetMethod; + + Assert.True(p03.IsAbstract); + Assert.False(p03.IsVirtual); + Assert.False(p03.IsSealed); + Assert.False(p03.IsStatic); + Assert.False(p03.IsExtern); + Assert.False(p03.IsOverride); + Assert.Equal(Accessibility.Public, p03.DeclaredAccessibility); + + Assert.True(p03set.IsAbstract); + Assert.False(p03set.IsVirtual); + Assert.True(p03set.IsMetadataVirtual()); + Assert.False(p03set.IsSealed); + Assert.False(p03set.IsStatic); + Assert.False(p03set.IsExtern); + Assert.False(p03set.IsAsync); + Assert.False(p03set.IsOverride); + Assert.Equal(Accessibility.Public, p03set.DeclaredAccessibility); + + var p04 = compilation1.GetMember("I04.this[]"); + var p04get = p04.GetMethod; + + Assert.True(p04.IsAbstract); + Assert.False(p04.IsVirtual); + Assert.False(p04.IsSealed); + Assert.False(p04.IsStatic); + Assert.False(p04.IsExtern); + Assert.False(p04.IsOverride); + Assert.Equal(Accessibility.Internal, p04.DeclaredAccessibility); + + Assert.True(p04get.IsAbstract); + Assert.False(p04get.IsVirtual); + Assert.True(p04get.IsMetadataVirtual()); + Assert.False(p04get.IsSealed); + Assert.False(p04get.IsStatic); + Assert.False(p04get.IsExtern); + Assert.False(p04get.IsAsync); + Assert.False(p04get.IsOverride); + Assert.Equal(Accessibility.Internal, p04get.DeclaredAccessibility); + + var p05 = compilation1.GetMember("I05.this[]"); + var p05set = p05.SetMethod; + + Assert.False(p05.IsAbstract); + Assert.False(p05.IsVirtual); + Assert.False(p05.IsSealed); + Assert.False(p05.IsStatic); + Assert.False(p05.IsExtern); + Assert.False(p05.IsOverride); + Assert.Equal(Accessibility.Private, p05.DeclaredAccessibility); + + Assert.False(p05set.IsAbstract); + Assert.False(p05set.IsVirtual); + Assert.False(p05set.IsMetadataVirtual()); + Assert.False(p05set.IsSealed); + Assert.False(p05set.IsStatic); + Assert.False(p05set.IsExtern); + Assert.False(p05set.IsAsync); + Assert.False(p05set.IsOverride); + Assert.Equal(Accessibility.Private, p05set.DeclaredAccessibility); + + var p06 = compilation1.GetMember("I06.this[]"); + var p06get = p06.GetMethod; + + Assert.True(p06.IsAbstract); + Assert.False(p06.IsVirtual); + Assert.False(p06.IsSealed); + Assert.False(p06.IsStatic); + Assert.False(p06.IsExtern); + Assert.False(p06.IsOverride); + Assert.Equal(Accessibility.Public, p06.DeclaredAccessibility); + + Assert.True(p06get.IsAbstract); + Assert.False(p06get.IsVirtual); + Assert.True(p06get.IsMetadataVirtual()); + Assert.False(p06get.IsSealed); + Assert.False(p06get.IsStatic); + Assert.False(p06get.IsExtern); + Assert.False(p06get.IsAsync); + Assert.False(p06get.IsOverride); + Assert.Equal(Accessibility.Public, p06get.DeclaredAccessibility); + + var p07 = compilation1.GetMember("I07.this[]"); + var p07set = p07.SetMethod; + + Assert.False(p07.IsAbstract); + Assert.True(p07.IsVirtual); + Assert.False(p07.IsSealed); + Assert.False(p07.IsStatic); + Assert.False(p07.IsExtern); + Assert.False(p07.IsOverride); + Assert.Equal(Accessibility.Public, p07.DeclaredAccessibility); + + Assert.False(p07set.IsAbstract); + Assert.True(p07set.IsVirtual); + Assert.True(p07set.IsMetadataVirtual()); + Assert.False(p07set.IsSealed); + Assert.False(p07set.IsStatic); + Assert.False(p07set.IsExtern); + Assert.False(p07set.IsAsync); + Assert.False(p07set.IsOverride); + Assert.Equal(Accessibility.Public, p07set.DeclaredAccessibility); + + var p08 = compilation1.GetMember("I08.this[]"); + var p08get = p08.GetMethod; + + Assert.False(p08.IsAbstract); + Assert.False(p08.IsVirtual); + Assert.False(p08.IsSealed); + Assert.False(p08.IsStatic); + Assert.False(p08.IsExtern); + Assert.False(p08.IsOverride); + Assert.Equal(Accessibility.Public, p08.DeclaredAccessibility); + + Assert.False(p08get.IsAbstract); + Assert.False(p08get.IsVirtual); + Assert.False(p08get.IsMetadataVirtual()); + Assert.False(p08get.IsSealed); + Assert.False(p08get.IsStatic); + Assert.False(p08get.IsExtern); + Assert.False(p08get.IsAsync); + Assert.False(p08get.IsOverride); + Assert.Equal(Accessibility.Public, p08get.DeclaredAccessibility); + + var p09 = compilation1.GetMember("I09.this[]"); + var p09set = p09.SetMethod; + + Assert.True(p09.IsAbstract); + Assert.False(p09.IsVirtual); + Assert.False(p09.IsSealed); + Assert.False(p09.IsStatic); + Assert.False(p09.IsExtern); + Assert.False(p09.IsOverride); + Assert.Equal(Accessibility.Public, p09.DeclaredAccessibility); + + Assert.True(p09set.IsAbstract); + Assert.False(p09set.IsVirtual); + Assert.True(p09set.IsMetadataVirtual()); + Assert.False(p09set.IsSealed); + Assert.False(p09set.IsStatic); + Assert.False(p09set.IsExtern); + Assert.False(p09set.IsAsync); + Assert.False(p09set.IsOverride); + Assert.Equal(Accessibility.Public, p09set.DeclaredAccessibility); + + var p10 = compilation1.GetMember("I10.this[]"); + var p10get = p10.GetMethod; + + Assert.True(p10.IsAbstract); + Assert.False(p10.IsVirtual); + Assert.False(p10.IsSealed); + Assert.False(p10.IsStatic); + Assert.False(p10.IsExtern); + Assert.False(p10.IsOverride); + Assert.Equal(Accessibility.Public, p10.DeclaredAccessibility); + + Assert.True(p10get.IsAbstract); + Assert.False(p10get.IsVirtual); + Assert.True(p10get.IsMetadataVirtual()); + Assert.False(p10get.IsSealed); + Assert.False(p10get.IsStatic); + Assert.False(p10get.IsExtern); + Assert.False(p10get.IsAsync); + Assert.False(p10get.IsOverride); + Assert.Equal(Accessibility.Public, p10get.DeclaredAccessibility); + + var p11 = compilation1.GetMember("I11.this[]"); + + Assert.False(p11.IsAbstract); + Assert.True(p11.IsVirtual); + Assert.False(p11.IsSealed); + Assert.False(p11.IsStatic); + Assert.True(p11.IsExtern); + Assert.False(p11.IsOverride); + Assert.Equal(Accessibility.Public, p11.DeclaredAccessibility); + + ValidateP11Accessor(p11.GetMethod); + ValidateP11Accessor(p11.SetMethod); + void ValidateP11Accessor(MethodSymbol accessor) + { + Assert.False(accessor.IsAbstract); + Assert.True(accessor.IsVirtual); + Assert.True(accessor.IsMetadataVirtual()); + Assert.False(accessor.IsSealed); + Assert.False(accessor.IsStatic); + Assert.True(accessor.IsExtern); + Assert.False(accessor.IsAsync); + Assert.False(accessor.IsOverride); + Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); + } + + var p12 = compilation1.GetMember("I12.this[]"); + + Assert.True(p12.IsAbstract); + Assert.False(p12.IsVirtual); + Assert.False(p12.IsSealed); + Assert.False(p12.IsStatic); + Assert.False(p12.IsExtern); + Assert.False(p12.IsOverride); + Assert.Equal(Accessibility.Public, p12.DeclaredAccessibility); + + ValidateP12Accessor(p12.GetMethod); + ValidateP12Accessor(p12.SetMethod); + void ValidateP12Accessor(MethodSymbol accessor) + { + Assert.True(accessor.IsAbstract); + Assert.False(accessor.IsVirtual); + Assert.True(accessor.IsMetadataVirtual()); + Assert.False(accessor.IsSealed); + Assert.False(accessor.IsStatic); + Assert.False(accessor.IsExtern); + Assert.False(accessor.IsAsync); + Assert.False(accessor.IsOverride); + Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); + } + + var p13 = compilation1.GetMember("I13.this[]"); + + Assert.True(p13.IsAbstract); + Assert.False(p13.IsVirtual); + Assert.False(p13.IsSealed); + Assert.False(p13.IsStatic); + Assert.False(p13.IsExtern); + Assert.False(p13.IsOverride); + Assert.Equal(Accessibility.Public, p13.DeclaredAccessibility); + + ValidateP13Accessor(p13.GetMethod); + ValidateP13Accessor(p13.SetMethod); + void ValidateP13Accessor(MethodSymbol accessor) + { + Assert.True(accessor.IsAbstract); + Assert.False(accessor.IsVirtual); + Assert.True(accessor.IsMetadataVirtual()); + Assert.False(accessor.IsSealed); + Assert.False(accessor.IsStatic); + Assert.False(accessor.IsExtern); + Assert.False(accessor.IsAsync); + Assert.False(accessor.IsOverride); + Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); + } + + var p14 = compilation1.GetMember("I14.this[]"); + + Assert.True(p14.IsAbstract); + Assert.False(p14.IsVirtual); + Assert.False(p14.IsSealed); + Assert.False(p14.IsStatic); + Assert.False(p14.IsExtern); + Assert.False(p14.IsOverride); + Assert.Equal(Accessibility.Public, p14.DeclaredAccessibility); + + ValidateP14Accessor(p14.GetMethod); + ValidateP14Accessor(p14.SetMethod); + void ValidateP14Accessor(MethodSymbol accessor) + { + Assert.True(accessor.IsAbstract); + Assert.False(accessor.IsVirtual); + Assert.True(accessor.IsMetadataVirtual()); + Assert.False(accessor.IsSealed); + Assert.False(accessor.IsStatic); + Assert.False(accessor.IsExtern); + Assert.False(accessor.IsAsync); + Assert.False(accessor.IsOverride); + Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); + } + + var p15 = compilation1.GetMember("I15.this[]"); + + Assert.True(p15.IsAbstract); + Assert.False(p15.IsVirtual); + Assert.False(p15.IsSealed); + Assert.False(p15.IsStatic); + Assert.False(p15.IsExtern); + Assert.False(p15.IsOverride); + Assert.Equal(Accessibility.Public, p15.DeclaredAccessibility); + + ValidateP15Accessor(p15.GetMethod, Accessibility.Public); + ValidateP15Accessor(p15.SetMethod, Accessibility.Internal); + void ValidateP15Accessor(MethodSymbol accessor, Accessibility accessibility) + { + Assert.True(accessor.IsAbstract); + Assert.False(accessor.IsVirtual); + Assert.True(accessor.IsMetadataVirtual()); + Assert.False(accessor.IsSealed); + Assert.False(accessor.IsStatic); + Assert.False(accessor.IsExtern); + Assert.False(accessor.IsAsync); + Assert.False(accessor.IsOverride); + Assert.Equal(accessibility, accessor.DeclaredAccessibility); + } + + var p16 = compilation1.GetMember("I16.this[]"); + + Assert.True(p16.IsAbstract); + Assert.False(p16.IsVirtual); + Assert.False(p16.IsSealed); + Assert.False(p16.IsStatic); + Assert.False(p16.IsExtern); + Assert.False(p16.IsOverride); + Assert.Equal(Accessibility.Public, p16.DeclaredAccessibility); + + ValidateP16Accessor(p16.GetMethod, Accessibility.Private); + ValidateP16Accessor(p16.SetMethod, Accessibility.Public); + void ValidateP16Accessor(MethodSymbol accessor, Accessibility accessibility) + { + Assert.True(accessor.IsAbstract); + Assert.False(accessor.IsVirtual); + Assert.True(accessor.IsMetadataVirtual()); + Assert.False(accessor.IsSealed); + Assert.False(accessor.IsStatic); + Assert.False(accessor.IsExtern); + Assert.False(accessor.IsAsync); + Assert.False(accessor.IsOverride); + Assert.Equal(accessibility, accessor.DeclaredAccessibility); + } + + var p17 = compilation1.GetMember("I17.this[]"); + var p17get = p17.GetMethod; + + Assert.True(p17.IsAbstract); + Assert.False(p17.IsVirtual); + Assert.False(p17.IsSealed); + Assert.False(p17.IsStatic); + Assert.False(p17.IsExtern); + Assert.False(p17.IsOverride); + Assert.Equal(Accessibility.Public, p17.DeclaredAccessibility); + + Assert.True(p17get.IsAbstract); + Assert.False(p17get.IsVirtual); + Assert.True(p17get.IsMetadataVirtual()); + Assert.False(p17get.IsSealed); + Assert.False(p17get.IsStatic); + Assert.False(p17get.IsExtern); + Assert.False(p17get.IsAsync); + Assert.False(p17get.IsOverride); + Assert.Equal(Accessibility.Private, p17get.DeclaredAccessibility); + } + + [Fact] + public void IndexerModifiers_02() + { + var source1 = +@" +public interface I01{ public int this[int x] {get; set;} } +public interface I02{ protected int this[int x] {get;} } +public interface I03{ protected internal int this[int x] {set;} } +public interface I04{ internal int this[int x] {get;} } +public interface I05{ private int this[int x] {set;} } +public interface I06{ static int this[int x] {get;} } +public interface I07{ virtual int this[int x] {set;} } +public interface I08{ sealed int this[int x] {get;} } +public interface I09{ override int this[int x] {set;} } +public interface I10{ abstract int this[int x] {get;} } +public interface I11{ extern int this[int x] {get; set;} } + +public interface I12{ int this[int x] { public get; set;} } +public interface I13{ int this[int x] { get; protected set;} } +public interface I14{ int this[int x] { protected internal get; set;} } +public interface I15{ int this[int x] { get; internal set;} } +public interface I16{ int this[int x] { private get; set;} } +public interface I17{ int this[int x] { private get;} } +"; + var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp7)); + Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation1.VerifyDiagnostics( + // (2,34): error CS8503: The modifier 'public' is not valid for this item in C# 7. Please use language version 7.1 or greater. + // public interface I01{ public int this[int x] {get; set;} } + Diagnostic(ErrorCode.ERR_DefaultInterfaceImplementationModifier, "this").WithArguments("public", "7", "7.1").WithLocation(2, 34), + // (3,37): error CS0106: The modifier 'protected' is not valid for this item + // public interface I02{ protected int this[int x] {get;} } + Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("protected").WithLocation(3, 37), + // (4,46): error CS0106: The modifier 'protected internal' is not valid for this item + // public interface I03{ protected internal int this[int x] {set;} } + Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("protected internal").WithLocation(4, 46), + // (5,36): error CS8503: The modifier 'internal' is not valid for this item in C# 7. Please use language version 7.1 or greater. + // public interface I04{ internal int this[int x] {get;} } + Diagnostic(ErrorCode.ERR_DefaultInterfaceImplementationModifier, "this").WithArguments("internal", "7", "7.1").WithLocation(5, 36), + // (6,35): error CS8503: The modifier 'private' is not valid for this item in C# 7. Please use language version 7.1 or greater. + // public interface I05{ private int this[int x] {set;} } + Diagnostic(ErrorCode.ERR_DefaultInterfaceImplementationModifier, "this").WithArguments("private", "7", "7.1").WithLocation(6, 35), + // (6,48): error CS0501: 'I05.this[int].set' must declare a body because it is not marked abstract, extern, or partial + // public interface I05{ private int this[int x] {set;} } + Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "set").WithArguments("I05.this[int].set").WithLocation(6, 48), + // (7,34): error CS0106: The modifier 'static' is not valid for this item + // public interface I06{ static int this[int x] {get;} } + Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("static").WithLocation(7, 34), + // (8,35): error CS8503: The modifier 'virtual' is not valid for this item in C# 7. Please use language version 7.1 or greater. + // public interface I07{ virtual int this[int x] {set;} } + Diagnostic(ErrorCode.ERR_DefaultInterfaceImplementationModifier, "this").WithArguments("virtual", "7", "7.1").WithLocation(8, 35), + // (8,48): error CS0501: 'I07.this[int].set' must declare a body because it is not marked abstract, extern, or partial + // public interface I07{ virtual int this[int x] {set;} } + Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "set").WithArguments("I07.this[int].set").WithLocation(8, 48), + // (9,34): error CS8503: The modifier 'sealed' is not valid for this item in C# 7. Please use language version 7.1 or greater. + // public interface I08{ sealed int this[int x] {get;} } + Diagnostic(ErrorCode.ERR_DefaultInterfaceImplementationModifier, "this").WithArguments("sealed", "7", "7.1").WithLocation(9, 34), + // (9,47): error CS0501: 'I08.this[int].get' must declare a body because it is not marked abstract, extern, or partial + // public interface I08{ sealed int this[int x] {get;} } + Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "get").WithArguments("I08.this[int].get").WithLocation(9, 47), + // (10,36): error CS0106: The modifier 'override' is not valid for this item + // public interface I09{ override int this[int x] {set;} } + Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("override").WithLocation(10, 36), + // (11,36): error CS8503: The modifier 'abstract' is not valid for this item in C# 7. Please use language version 7.1 or greater. + // public interface I10{ abstract int this[int x] {get;} } + Diagnostic(ErrorCode.ERR_DefaultInterfaceImplementationModifier, "this").WithArguments("abstract", "7", "7.1").WithLocation(11, 36), + // (12,34): error CS8503: The modifier 'extern' is not valid for this item in C# 7. Please use language version 7.1 or greater. + // public interface I11{ extern int this[int x] {get; set;} } + Diagnostic(ErrorCode.ERR_DefaultInterfaceImplementationModifier, "this").WithArguments("extern", "7", "7.1").WithLocation(12, 34), + // (14,48): error CS8503: The modifier 'public' is not valid for this item in C# 7. Please use language version 7.1 or greater. + // public interface I12{ int this[int x] { public get; set;} } + Diagnostic(ErrorCode.ERR_DefaultInterfaceImplementationModifier, "get").WithArguments("public", "7", "7.1").WithLocation(14, 48), + // (14,48): error CS0273: The accessibility modifier of the 'I12.this[int].get' accessor must be more restrictive than the property or indexer 'I12.this[int]' + // public interface I12{ int this[int x] { public get; set;} } + Diagnostic(ErrorCode.ERR_InvalidPropertyAccessMod, "get").WithArguments("I12.this[int].get", "I12.this[int]").WithLocation(14, 48), + // (15,56): error CS0106: The modifier 'protected' is not valid for this item + // public interface I13{ int this[int x] { get; protected set;} } + Diagnostic(ErrorCode.ERR_BadMemberFlag, "set").WithArguments("protected").WithLocation(15, 56), + // (16,60): error CS0106: The modifier 'protected internal' is not valid for this item + // public interface I14{ int this[int x] { protected internal get; set;} } + Diagnostic(ErrorCode.ERR_BadMemberFlag, "get").WithArguments("protected internal").WithLocation(16, 60), + // (17,55): error CS8503: The modifier 'internal' is not valid for this item in C# 7. Please use language version 7.1 or greater. + // public interface I15{ int this[int x] { get; internal set;} } + Diagnostic(ErrorCode.ERR_DefaultInterfaceImplementationModifier, "set").WithArguments("internal", "7", "7.1").WithLocation(17, 55), + // (18,49): error CS8503: The modifier 'private' is not valid for this item in C# 7. Please use language version 7.1 or greater. + // public interface I16{ int this[int x] { private get; set;} } + Diagnostic(ErrorCode.ERR_DefaultInterfaceImplementationModifier, "get").WithArguments("private", "7", "7.1").WithLocation(18, 49), + // (18,49): error CS0442: 'I16.this[int].get': abstract properties cannot have private accessors + // public interface I16{ int this[int x] { private get; set;} } + Diagnostic(ErrorCode.ERR_PrivateAbstractAccessor, "get").WithArguments("I16.this[int].get").WithLocation(18, 49), + // (19,49): error CS8503: The modifier 'private' is not valid for this item in C# 7. Please use language version 7.1 or greater. + // public interface I17{ int this[int x] { private get;} } + Diagnostic(ErrorCode.ERR_DefaultInterfaceImplementationModifier, "get").WithArguments("private", "7", "7.1").WithLocation(19, 49), + // (19,27): error CS0276: 'I17.this[int]': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor + // public interface I17{ int this[int x] { private get;} } + Diagnostic(ErrorCode.ERR_AccessModMissingAccessor, "this").WithArguments("I17.this[int]").WithLocation(19, 27), + // (12,47): warning CS0626: Method, operator, or accessor 'I11.this[int].get' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. + // public interface I11{ extern int this[int x] {get; set;} } + Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "get").WithArguments("I11.this[int].get").WithLocation(12, 47), + // (12,52): warning CS0626: Method, operator, or accessor 'I11.this[int].set' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. + // public interface I11{ extern int this[int x] {get; set;} } + Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "set").WithArguments("I11.this[int].set").WithLocation(12, 52) + ); + + ValidateSymbolsIndexerModifiers_01(compilation1); + } + + [Fact] + public void IndexerModifiers_03() + { + ValidateIndexerImplementation_101(@" +public interface I1 +{ + public virtual int this[int i] + { + get + { + System.Console.WriteLine(""get P1""); + return 0; + } + } +} + +class Test1 : I1 +{} +"); + + ValidateIndexerImplementation_101(@" +public interface I1 +{ + public virtual int this[int i] + { + get => Test1.GetP1(); + } +} + +class Test1 : I1 +{ + public static int GetP1() + { + System.Console.WriteLine(""get P1""); + return 0; + } +} +"); + + ValidateIndexerImplementation_101(@" +public interface I1 +{ + public virtual int this[int i] => Test1.GetP1(); +} + +class Test1 : I1 +{ + public static int GetP1() + { + System.Console.WriteLine(""get P1""); + return 0; + } +} +"); + + ValidateIndexerImplementation_102(@" +public interface I1 +{ + public virtual int this[int i] + { + get + { + System.Console.WriteLine(""get P1""); + return 0; + } + set + { + System.Console.WriteLine(""set P1""); + } + } +} + +class Test1 : I1 +{} +"); + + ValidateIndexerImplementation_102(@" +public interface I1 +{ + public virtual int this[int i] + { + get => Test1.GetP1(); + set => System.Console.WriteLine(""set P1""); + } +} + +class Test1 : I1 +{ + public static int GetP1() + { + System.Console.WriteLine(""get P1""); + return 0; + } +} +"); + + ValidateIndexerImplementation_103(@" +public interface I1 +{ + public virtual int this[int i] + { + set + { + System.Console.WriteLine(""set P1""); + } + } +} + +class Test1 : I1 +{} +"); + + ValidateIndexerImplementation_103(@" +public interface I1 +{ + public virtual int this[int i] + { + set => System.Console.WriteLine(""set P1""); + } +} + +class Test1 : I1 +{} +"); + } + + [Fact] + public void IndexerModifiers_04() + { + var source1 = +@" +public interface I1 +{ + public virtual int this[int x] { get; } = 0; +} +"; + var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation1.VerifyDiagnostics( + // (4,45): error CS1519: Invalid token '=' in class, struct, or interface member declaration + // public virtual int this[int x] { get; } = 0; + Diagnostic(ErrorCode.ERR_InvalidMemberDecl, "=").WithArguments("=").WithLocation(4, 45), + // (4,38): error CS0501: 'I1.this[int].get' must declare a body because it is not marked abstract, extern, or partial + // public virtual int this[int x] { get; } = 0; + Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "get").WithArguments("I1.this[int].get").WithLocation(4, 38) + ); + + ValidatePropertyModifiers_04(compilation1, "this[]"); + } + + [Fact] + public void IndexerModifiers_05() + { + var source1 = +@" +public interface I1 +{ + public abstract int this[int x] {get; set;} +} +public interface I2 +{ + int this[int x] {get; set;} +} + +class Test1 : I1 +{ + public int this[int x] + { + get + { + System.Console.WriteLine(""get_P1""); + return 0; + } + set => System.Console.WriteLine(""set_P1""); + } +} +class Test2 : I2 +{ + public int this[int x] + { + get + { + System.Console.WriteLine(""get_P2""); + return 0; + } + set => System.Console.WriteLine(""set_P2""); + } + + static void Main() + { + I1 x = new Test1(); + x[0] = x[0]; + I2 y = new Test2(); + y[0] = y[0]; + } +} +"; + + ValidatePropertyModifiers_05(source1); + } + + [Fact] + public void IndexerModifiers_06() + { + var source1 = +@" +public interface I1 +{ + public abstract int this[int x] {get; set;} +} +"; + var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp7)); + Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation1.VerifyDiagnostics( + // (4,25): error CS8503: The modifier 'abstract' is not valid for this item in C# 7. Please use language version 7.1 or greater. + // public abstract int this[int x] {get; set;} + Diagnostic(ErrorCode.ERR_DefaultInterfaceImplementationModifier, "this").WithArguments("abstract", "7", "7.1").WithLocation(4, 25), + // (4,25): error CS8503: The modifier 'public' is not valid for this item in C# 7. Please use language version 7.1 or greater. + // public abstract int this[int x] {get; set;} + Diagnostic(ErrorCode.ERR_DefaultInterfaceImplementationModifier, "this").WithArguments("public", "7", "7.1").WithLocation(4, 25) + ); + + ValidatePropertyModifiers_06(compilation1, "this[]"); + } + + [Fact] + public void IndexerModifiers_09() + { + var source1 = +@" +public interface I1 +{ + private int this[int x] + { + get + { + System.Console.WriteLine(""get_P1""); + return 0; + } + } + sealed void M() + { + var x = this[0]; + } +} +public interface I2 +{ + private int this[int x] + { + get + { + System.Console.WriteLine(""get_P2""); + return 0; + } + set + { + System.Console.WriteLine(""set_P2""); + } + } + sealed void M() + { + this[0] = this[0]; + } +} +public interface I3 +{ + private int this[int x] + { + set + { + System.Console.WriteLine(""set_P3""); + } + } + sealed void M() + { + this[0] = 0; + } +} +public interface I4 +{ + private int this[int x] + { + get => GetP4(); + } + + private int GetP4() + { + System.Console.WriteLine(""get_P4""); + return 0; + } + sealed void M() + { + var x = this[0]; + } +} +public interface I5 +{ + private int this[int x] + { + get => GetP5(); + set => System.Console.WriteLine(""set_P5""); + } + + private int GetP5() + { + System.Console.WriteLine(""get_P5""); + return 0; + } + sealed void M() + { + this[0] = this[0]; + } +} +public interface I6 +{ + private int this[int x] + { + set => System.Console.WriteLine(""set_P6""); + } + sealed void M() + { + this[0] = 0; + } +} +public interface I7 +{ + private int this[int x] => GetP7(); + + private int GetP7() + { + System.Console.WriteLine(""get_P7""); + return 0; + } + sealed void M() + { + var x = this[0]; + } +} + +class Test1 : I1, I2, I3, I4, I5, I6, I7 +{ + static void Main() + { + I1 x1 = new Test1(); + x1.M(); + I2 x2 = new Test1(); + x2.M(); + I3 x3 = new Test1(); + x3.M(); + I4 x4 = new Test1(); + x4.M(); + I5 x5 = new Test1(); + x5.M(); + I6 x6 = new Test1(); + x6.M(); + I7 x7 = new Test1(); + x7.M(); + } +} +"; + + ValidatePropertyModifiers_09(source1); + } + + [Fact] + public void IndexerModifiers_10() + { + var source1 = +@" +public interface I1 +{ + abstract private int this[byte x] { get; } + + virtual private int this[int x] => 0; + + sealed private int this[short x] + { + get => 0; + set {} + } + + private int this[long x] {get;} = 0; +} + +class Test1 : I1 +{ +} +"; + var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation1.VerifyDiagnostics( + // (14,37): error CS1519: Invalid token '=' in class, struct, or interface member declaration + // private int this[long x] {get;} = 0; + Diagnostic(ErrorCode.ERR_InvalidMemberDecl, "=").WithArguments("=").WithLocation(14, 37), + // (4,26): error CS0621: 'I1.this[byte]': virtual or abstract members cannot be private + // abstract private int this[byte x] { get; } + Diagnostic(ErrorCode.ERR_VirtualPrivate, "this").WithArguments("I1.this[byte]").WithLocation(4, 26), + // (6,25): error CS0621: 'I1.this[int]': virtual or abstract members cannot be private + // virtual private int this[int x] => 0; + Diagnostic(ErrorCode.ERR_VirtualPrivate, "this").WithArguments("I1.this[int]").WithLocation(6, 25), + // (8,24): error CS0238: 'I1.this[short]' cannot be sealed because it is not an override + // sealed private int this[short x] + Diagnostic(ErrorCode.ERR_SealedNonOverride, "this").WithArguments("I1.this[short]").WithLocation(8, 24), + // (14,31): error CS0501: 'I1.this[long].get' must declare a body because it is not marked abstract, extern, or partial + // private int this[long x] {get;} = 0; + Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "get").WithArguments("I1.this[long].get").WithLocation(14, 31), + // (17,15): error CS0535: 'Test1' does not implement interface member 'I1.this[byte]' + // class Test1 : I1 + Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test1", "I1.this[byte]") + ); + + ValidatePropertyModifiers_10(compilation1); + } + + [Fact] + public void IndexerModifiers_11_01() + { + var source1 = +@" +public interface I1 +{ + internal abstract int this[int x] {get; set;} + + sealed void Test() + { + this[0] = this[0]; + } +} +"; + + var source2 = +@" +class Test1 : I1 +{ + static void Main() + { + I1 x = new Test1(); + x.Test(); + } + + public int this[int x] + { + get + { + System.Console.WriteLine(""get_P1""); + return 0; + } + set + { + System.Console.WriteLine(""set_P1""); + } + } +} +"; + + ValidatePropertyModifiers_11_01(source1, source2, + new DiagnosticDescription[] { + // (2,15): error CS8504: 'Test1' does not implement interface member 'I1.this[int].get'. 'Test1.this[int].get' cannot implicitly implement a non-public member. + // class Test1 : I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test1", "I1.this[int].get", "Test1.this[int].get").WithLocation(2, 15), + // (2,15): error CS8504: 'Test1' does not implement interface member 'I1.this[int].set'. 'Test1.this[int].set' cannot implicitly implement a non-public member. + // class Test1 : I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test1", "I1.this[int].set", "Test1.this[int].set").WithLocation(2, 15) + }, + // (2,15): error CS0535: 'Test2' does not implement interface member 'I1.this[int]' + // class Test2 : I1 + Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test2", "I1.this[int]") + ); + } + + [Fact] + public void IndexerModifiers_11_02() + { + var source1 = +@" +public interface I1 +{ + internal abstract int this[int x] {get; set;} +} + +public class TestHelper +{ + public static void CallP1(I1 x) {x[0] = x[0];} +} +"; + + var source2 = +@" +class Test1 : I1 +{ + static void Main() + { + TestHelper.CallP1(new Test1()); + } + + public virtual int this[int x] + { + get + { + System.Console.WriteLine(""get_P1""); + return 0; + } + set + { + System.Console.WriteLine(""set_P1""); + } + } +} +"; + + ValidatePropertyModifiers_11_02(source1, source2, + // (2,15): error CS8504: 'Test1' does not implement interface member 'I1.this[int].set'. 'Test1.this[int].set' cannot implicitly implement a non-public member. + // class Test1 : I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test1", "I1.this[int].set", "Test1.this[int].set").WithLocation(2, 15), + // (2,15): error CS8504: 'Test1' does not implement interface member 'I1.this[int].get'. 'Test1.this[int].get' cannot implicitly implement a non-public member. + // class Test1 : I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test1", "I1.this[int].get", "Test1.this[int].get").WithLocation(2, 15) + ); + } + + [Fact] + public void IndexerModifiers_11_03() + { + var source1 = +@" +public interface I1 +{ + internal abstract int this[int x] {get; set;} +} + +public class TestHelper +{ + public static void CallP1(I1 x) {x[0] = x[0];} +} +"; + + var source2 = +@" +class Test1 : I1 +{ + static void Main() + { + TestHelper.CallP1(new Test1()); + } + + int I1.this[int x] + { + get + { + System.Console.WriteLine(""get_P1""); + return 0; + } + set + { + System.Console.WriteLine(""set_P1""); + } + } +} +"; + + ValidatePropertyModifiers_11_03(source1, source2, + // (9,12): error CS0122: 'I1.this[int]' is inaccessible due to its protection level + // int I1.this[int x] + Diagnostic(ErrorCode.ERR_BadAccess, "this").WithArguments("I1.this[int]").WithLocation(9, 12) + ); + } + + [Fact] + public void IndexerModifiers_11_04() + { + var source1 = +@" +public interface I1 +{ + internal abstract int this[int x] {get; set;} +} + +public class TestHelper +{ + public static void CallP1(I1 x) {x[0] = x[0];} +} + +public class Test2 : I1 +{ + int I1.this[int x] + { + get + { + System.Console.WriteLine(""Test2.get_P1""); + return 0; + } + set + { + System.Console.WriteLine(""Test2.set_P1""); + } + } +} + +"; + + var source2 = +@" +class Test1 : Test2, I1 +{ + static void Main() + { + TestHelper.CallP1(new Test1()); + } + + public int this[int x] + { + get + { + System.Console.WriteLine(""Test1.get_P1""); + return 0; + } + set + { + System.Console.WriteLine(""Test1.set_P1""); + } + } +} +"; + + ValidatePropertyModifiers_11_02(source1, source2, + // (2,22): error CS8504: 'Test1' does not implement interface member 'I1.this[int].set'. 'Test1.this[int].set' cannot implicitly implement a non-public member. + // class Test1 : Test2, I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test1", "I1.this[int].set", "Test1.this[int].set").WithLocation(2, 22), + // (2,22): error CS8504: 'Test1' does not implement interface member 'I1.this[int].get'. 'Test1.this[int].get' cannot implicitly implement a non-public member. + // class Test1 : Test2, I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test1", "I1.this[int].get", "Test1.this[int].get").WithLocation(2, 22) + ); + } + + [Fact] + public void IndexerModifiers_11_05() + { + var source1 = +@" +public interface I1 +{ + internal abstract int this[int x] {get; set;} +} + +public class TestHelper +{ + public static void CallP1(I1 x) {x[0] = x[0];} +} + +public class Test2 : I1 +{ + int I1.this[int x] + { + get + { + System.Console.WriteLine(""Test2.get_P1""); + return 0; + } + set + { + System.Console.WriteLine(""Test2.set_P1""); + } + } +} + +"; + + var source2 = +@" +class Test1 : Test2, I1 +{ + static void Main() + { + TestHelper.CallP1(new Test1()); + } + + public virtual int this[int x] + { + get + { + System.Console.WriteLine(""Test1.get_P1""); + return 0; + } + set + { + System.Console.WriteLine(""Test1.set_P1""); + } + } +} +"; + + ValidatePropertyModifiers_11_02(source1, source2, + // (2,22): error CS8504: 'Test1' does not implement interface member 'I1.this[int].set'. 'Test1.this[int].set' cannot implicitly implement a non-public member. + // class Test1 : Test2, I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test1", "I1.this[int].set", "Test1.this[int].set").WithLocation(2, 22), + // (2,22): error CS8504: 'Test1' does not implement interface member 'I1.this[int].get'. 'Test1.this[int].get' cannot implicitly implement a non-public member. + // class Test1 : Test2, I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test1", "I1.this[int].get", "Test1.this[int].get").WithLocation(2, 22) + ); + } + + [Fact] + public void IndexerModifiers_11_06() + { + var source1 = +@" +public interface I1 +{ + internal abstract int this[int x] {get; set;} +} + +public class TestHelper +{ + public static void CallP1(I1 x) {x[0] = x[0];} +} + +public class Test2 : I1 +{ + int I1.this[int x] + { + get + { + System.Console.WriteLine(""Test2.get_P1""); + return 0; + } + set + { + System.Console.WriteLine(""Test2.set_P1""); + } + } +} + +"; + + var source2 = +@"abstract +class Test1 : Test2, I1 +{ + static void Main() + { + TestHelper.CallP1(new Test3()); + } + + public abstract int this[int x] {get; set;} +} + +class Test3 : Test1 +{ + public override int this[int x] + { + get + { + System.Console.WriteLine(""Test3.get_P1""); + return 0; + } + set + { + System.Console.WriteLine(""Test3.set_P1""); + } + } +} +"; + + ValidatePropertyModifiers_11_02(source1, source2, + // (2,22): error CS8504: 'Test1' does not implement interface member 'I1.this[int].set'. 'Test1.this[int].set' cannot implicitly implement a non-public member. + // class Test1 : Test2, I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test1", "I1.this[int].set", "Test1.this[int].set").WithLocation(2, 22), + // (2,22): error CS8504: 'Test1' does not implement interface member 'I1.this[int].get'. 'Test1.this[int].get' cannot implicitly implement a non-public member. + // class Test1 : Test2, I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test1", "I1.this[int].get", "Test1.this[int].get").WithLocation(2, 22) + ); + } + + [Fact] + public void IndexerModifiers_11_07() + { + var source1 = +@" +public interface I1 +{ + internal abstract int this[int x] {get; set;} +} + +public class TestHelper +{ + public static void CallP1(I1 x) {x[0] = x[0];} +} + +public class Test2 : I1 +{ + int I1.this[int x] + { + get + { + System.Console.WriteLine(""Test2.get_P1""); + return 0; + } + set + { + System.Console.WriteLine(""Test2.set_P1""); + } + } +} + +"; + + var source2 = +@" +class Test1 : Test2, I1, I2 +{ + static void Main() + { + TestHelper.CallP1(new Test1()); + } + + public int this[int x] + { + get + { + System.Console.WriteLine(""Test1.get_P1""); + return 0; + } + set + { + System.Console.WriteLine(""Test1.set_P1""); + } + } +} + +public interface I2 +{ + int this[int x] {get; set;} +} +"; + + ValidatePropertyModifiers_11_02(source1, source2, + // (2,22): error CS8504: 'Test1' does not implement interface member 'I1.this[int].set'. 'Test1.this[int].set' cannot implicitly implement a non-public member. + // class Test1 : Test2, I1, I2 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test1", "I1.this[int].set", "Test1.this[int].set").WithLocation(2, 22), + // (2,22): error CS8504: 'Test1' does not implement interface member 'I1.this[int].get'. 'Test1.this[int].get' cannot implicitly implement a non-public member. + // class Test1 : Test2, I1, I2 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test1", "I1.this[int].get", "Test1.this[int].get").WithLocation(2, 22) + ); + } + + [Fact] + public void IndexerModifiers_11_08() + { + var source1 = +@" +public interface I1 +{ + internal abstract int this[int x] {get; set;} +} + +public class TestHelper +{ + public static void CallP1(I1 x) {x[0] = x[0];} +} + +public class Test2 : I1 +{ + int I1.this[int x] + { + get + { + System.Console.WriteLine(""Test2.get_P1""); + return 0; + } + set + { + System.Console.WriteLine(""Test2.set_P1""); + } + } +} + +"; + + var source2 = +@" +class Test1 : Test2, I1 +{ + static void Main() + { + TestHelper.CallP1(new Test1()); + } + + public virtual long this[int x] + { + get + { + System.Console.WriteLine(""Test1.get_P1""); + return 0; + } + set + { + System.Console.WriteLine(""Test1.set_P1""); + } + } +} +"; + + ValidatePropertyModifiers_11_08(source1, source2); + } + + [Fact] + public void IndexerModifiers_11_09() + { + var source1 = +@" +public interface I1 +{ + internal abstract int this[int x] {get; set;} +} + +public class TestHelper +{ + public static void CallP1(I1 x) {x[0] = x[0];} +} +"; + + var source2 = +@" +class Test1 : I1 +{ + static void Main() + { + TestHelper.CallP1(new Test1()); + } + + public virtual long this[int x] + { + get + { + System.Console.WriteLine(""Test1.get_P1""); + return 0; + } + set + { + System.Console.WriteLine(""Test1.set_P1""); + } + } +} +"; + + ValidatePropertyModifiers_11_09(source1, source2, + // (2,15): error CS0535: 'Test1' does not implement interface member 'I1.this[int]' + // class Test1 : I1 + Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test1", "I1.this[int]").WithLocation(2, 15) + ); + } + + [Fact] + public void IndexerModifiers_11_10() + { + var source1 = +@" +public interface I1 +{ + internal abstract int this[int x] {get; set;} +} +"; + + var source2 = +@" +public class Test2 : I1 +{ + public int this[int x] + { + get + { + return 0; + } + set {} + } +} +class Test1 : Test2, I1 +{ +} +"; + + ValidatePropertyModifiers_11_10(source1, source2, + // (2,22): error CS8504: 'Test2' does not implement interface member 'I1.this[int].set'. 'Test2.this[int].set' cannot implicitly implement a non-public member. + // public class Test2 : I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test2", "I1.this[int].set", "Test2.this[int].set").WithLocation(2, 22), + // (2,22): error CS8504: 'Test2' does not implement interface member 'I1.this[int].get'. 'Test2.this[int].get' cannot implicitly implement a non-public member. + // public class Test2 : I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test2", "I1.this[int].get", "Test2.this[int].get").WithLocation(2, 22) + ); + } + + [Fact] + public void IndexerModifiers_11_11() + { + var source1 = +@" +public interface I1 +{ + internal abstract int this[int x] {get; set;} +} +public class Test2 : I1 +{ + public int this[int x] + { + get + { + return 0; + } + set {} + } +} +"; + + var source2 = +@" +class Test1 : Test2, I1 +{ +} +"; + + ValidatePropertyModifiers_11_11(source1, source2, + // (6,22): error CS8504: 'Test2' does not implement interface member 'I1.this[int].set'. 'Test2.this[int].set' cannot implicitly implement a non-public member. + // public class Test2 : I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test2", "I1.this[int].set", "Test2.this[int].set").WithLocation(6, 22), + // (6,22): error CS8504: 'Test2' does not implement interface member 'I1.this[int].get'. 'Test2.this[int].get' cannot implicitly implement a non-public member. + // public class Test2 : I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test2", "I1.this[int].get", "Test2.this[int].get").WithLocation(6, 22) + ); + } + + [Fact] + public void IndexerModifiers_12() + { + var source1 = +@" +public interface I1 +{ + internal abstract int this[int x] {get; set;} +} + +class Test1 : I1 +{ +} +"; + var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation1.VerifyDiagnostics( + // (7,15): error CS0535: 'Test1' does not implement interface member 'I1.this[int]' + // class Test1 : I1 + Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test1", "I1.this[int]") + ); + + var test1 = compilation1.GetTypeByMetadataName("Test1"); + var i1 = compilation1.GetTypeByMetadataName("I1"); + var p1 = i1.GetMember("this[]"); + Assert.Null(test1.FindImplementationForInterfaceMember(p1)); + Assert.Null(test1.FindImplementationForInterfaceMember(p1.GetMethod)); + Assert.Null(test1.FindImplementationForInterfaceMember(p1.SetMethod)); + } + + [Fact] + public void IndexerModifiers_13() + { + var source1 = +@" +public interface I1 +{ + public sealed int this[int x] + { + get + { + System.Console.WriteLine(""get_P1""); + return 0; + } + } +} +public interface I2 +{ + public sealed int this[int x] + { + get + { + System.Console.WriteLine(""get_P2""); + return 0; + } + set + { + System.Console.WriteLine(""set_P2""); + } + } +} +public interface I3 +{ + public sealed int this[int x] + { + set + { + System.Console.WriteLine(""set_P3""); + } + } +} +public interface I4 +{ + public sealed int this[int x] + { + get => GetP4(); + } + + private int GetP4() + { + System.Console.WriteLine(""get_P4""); + return 0; + } +} +public interface I5 +{ + public sealed int this[int x] + { + get => GetP5(); + set => System.Console.WriteLine(""set_P5""); + } + + private int GetP5() + { + System.Console.WriteLine(""get_P5""); + return 0; + } +} +public interface I6 +{ + public sealed int this[int x] + { + set => System.Console.WriteLine(""set_P6""); + } +} +public interface I7 +{ + public sealed int this[int x] => GetP7(); + + private int GetP7() + { + System.Console.WriteLine(""get_P7""); + return 0; + } +} + +class Test1 : I1 +{ + static void Main() + { + I1 i1 = new Test1(); + var x = i1[0]; + I2 i2 = new Test2(); + i2[0] = i2[0]; + I3 i3 = new Test3(); + i3[0] = x; + I4 i4 = new Test4(); + x = i4[0]; + I5 i5 = new Test5(); + i5[0] = i5[0]; + I6 i6 = new Test6(); + i6[0] = x; + I7 i7 = new Test7(); + x = i7[0]; + } + + public int this[int x] => throw null; +} +class Test2 : I2 +{ + public int this[int x] + { + get => throw null; + set => throw null; + } +} +class Test3 : I3 +{ + public int this[int x] + { + set => throw null; + } +} +class Test4 : I4 +{ + public int this[int x] + { + get => throw null; + } +} +class Test5 : I5 +{ + public int this[int x] + { + get => throw null; + set => throw null; + } +} +class Test6 : I6 +{ + public int this[int x] + { + set => throw null; + } +} +class Test7 : I7 +{ + public int this[int x] => throw null; +} +"; + + ValidatePropertyModifiers_13(source1); + } + + [Fact] + public void AccessModifiers_14() + { + var source1 = +@" +public interface I1 +{ + public sealed int this[int x] {get;} = 0; +} +public interface I2 +{ + abstract sealed int this[int x] {get;} +} +public interface I3 +{ + virtual sealed int this[int x] + { + set {} + } +} + +class Test1 : I1, I2, I3 +{ + int I1.this[int x] { get => throw null; } + int I2.this[int x] { get => throw null; } + int I3.this[int x] { set => throw null; } +} + +class Test2 : I1, I2, I3 +{} +"; + ValidatePropertyModifiers_14(source1, + // (4,42): error CS1519: Invalid token '=' in class, struct, or interface member declaration + // public sealed int this[int x] {get;} = 0; + Diagnostic(ErrorCode.ERR_InvalidMemberDecl, "=").WithArguments("=").WithLocation(4, 42), + // (4,36): error CS0501: 'I1.this[int].get' must declare a body because it is not marked abstract, extern, or partial + // public sealed int this[int x] {get;} = 0; + Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "get").WithArguments("I1.this[int].get").WithLocation(4, 36), + // (8,25): error CS0238: 'I2.this[int]' cannot be sealed because it is not an override + // abstract sealed int this[int x] {get;} + Diagnostic(ErrorCode.ERR_SealedNonOverride, "this").WithArguments("I2.this[int]").WithLocation(8, 25), + // (12,24): error CS0238: 'I3.this[int]' cannot be sealed because it is not an override + // virtual sealed int this[int x] + Diagnostic(ErrorCode.ERR_SealedNonOverride, "this").WithArguments("I3.this[int]").WithLocation(12, 24), + // (20,12): error CS0539: 'Test1.this[int]' in explicit interface declaration is not found among members of the interface that can be implemented + // int I1.this[int x] { get => throw null; } + Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "this").WithArguments("Test1.this[int]").WithLocation(20, 12), + // (25,19): error CS0535: 'Test2' does not implement interface member 'I2.this[int]' + // class Test2 : I1, I2, I3 + Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I2").WithArguments("Test2", "I2.this[int]") + ); + } + + [Fact] + public void IndexerModifiers_15() + { + var source1 = +@" +public interface I0 +{ + abstract virtual int this[int x] { get; set; } +} +public interface I1 +{ + abstract virtual int this[int x] { get { throw null; } } +} +public interface I2 +{ + virtual abstract int this[int x] + { + get { throw null; } + set { throw null; } + } +} +public interface I3 +{ + abstract virtual int this[int x] { set { throw null; } } +} +public interface I4 +{ + abstract virtual int this[int x] { get => throw null; } +} +public interface I5 +{ + abstract virtual int this[int x] + { + get => throw null; + set => throw null; + } +} +public interface I6 +{ + abstract virtual int this[int x] { set => throw null; } +} +public interface I7 +{ + abstract virtual int this[int x] => throw null; +} +public interface I8 +{ + abstract virtual int this[int x] {get;} = 0; +} + +class Test1 : I0, I1, I2, I3, I4, I5, I6, I7, I8 +{ + int I0.this[int x] + { + get { throw null; } + set { throw null; } + } + int I1.this[int x] + { + get { throw null; } + } + int I2.this[int x] + { + get { throw null; } + set { throw null; } + } + int I3.this[int x] + { + set { throw null; } + } + int I4.this[int x] + { + get { throw null; } + } + int I5.this[int x] + { + get { throw null; } + set { throw null; } + } + int I6.this[int x] + { + set { throw null; } + } + int I7.this[int x] + { + get { throw null; } + } + int I8.this[int x] + { + get { throw null; } + } +} + +class Test2 : I0, I1, I2, I3, I4, I5, I6, I7, I8 +{} +"; + ValidatePropertyModifiers_15(source1, + // (44,45): error CS1519: Invalid token '=' in class, struct, or interface member declaration + // abstract virtual int this[int x] {get;} = 0; + Diagnostic(ErrorCode.ERR_InvalidMemberDecl, "=").WithArguments("=").WithLocation(44, 45), + // (4,26): error CS0503: The abstract method 'I0.this[int]' cannot be marked virtual + // abstract virtual int this[int x] { get; set; } + Diagnostic(ErrorCode.ERR_AbstractNotVirtual, "this").WithArguments("I0.this[int]").WithLocation(4, 26), + // (8,26): error CS0503: The abstract method 'I1.this[int]' cannot be marked virtual + // abstract virtual int this[int x] { get { throw null; } } + Diagnostic(ErrorCode.ERR_AbstractNotVirtual, "this").WithArguments("I1.this[int]").WithLocation(8, 26), + // (8,40): error CS0500: 'I1.this[int].get' cannot declare a body because it is marked abstract + // abstract virtual int this[int x] { get { throw null; } } + Diagnostic(ErrorCode.ERR_AbstractHasBody, "get").WithArguments("I1.this[int].get").WithLocation(8, 40), + // (12,26): error CS0503: The abstract method 'I2.this[int]' cannot be marked virtual + // virtual abstract int this[int x] + Diagnostic(ErrorCode.ERR_AbstractNotVirtual, "this").WithArguments("I2.this[int]").WithLocation(12, 26), + // (14,9): error CS0500: 'I2.this[int].get' cannot declare a body because it is marked abstract + // get { throw null; } + Diagnostic(ErrorCode.ERR_AbstractHasBody, "get").WithArguments("I2.this[int].get").WithLocation(14, 9), + // (15,9): error CS0500: 'I2.this[int].set' cannot declare a body because it is marked abstract + // set { throw null; } + Diagnostic(ErrorCode.ERR_AbstractHasBody, "set").WithArguments("I2.this[int].set").WithLocation(15, 9), + // (20,26): error CS0503: The abstract method 'I3.this[int]' cannot be marked virtual + // abstract virtual int this[int x] { set { throw null; } } + Diagnostic(ErrorCode.ERR_AbstractNotVirtual, "this").WithArguments("I3.this[int]").WithLocation(20, 26), + // (20,40): error CS0500: 'I3.this[int].set' cannot declare a body because it is marked abstract + // abstract virtual int this[int x] { set { throw null; } } + Diagnostic(ErrorCode.ERR_AbstractHasBody, "set").WithArguments("I3.this[int].set").WithLocation(20, 40), + // (24,26): error CS0503: The abstract method 'I4.this[int]' cannot be marked virtual + // abstract virtual int this[int x] { get => throw null; } + Diagnostic(ErrorCode.ERR_AbstractNotVirtual, "this").WithArguments("I4.this[int]").WithLocation(24, 26), + // (24,40): error CS0500: 'I4.this[int].get' cannot declare a body because it is marked abstract + // abstract virtual int this[int x] { get => throw null; } + Diagnostic(ErrorCode.ERR_AbstractHasBody, "get").WithArguments("I4.this[int].get").WithLocation(24, 40), + // (28,26): error CS0503: The abstract method 'I5.this[int]' cannot be marked virtual + // abstract virtual int this[int x] + Diagnostic(ErrorCode.ERR_AbstractNotVirtual, "this").WithArguments("I5.this[int]").WithLocation(28, 26), + // (30,9): error CS0500: 'I5.this[int].get' cannot declare a body because it is marked abstract + // get => throw null; + Diagnostic(ErrorCode.ERR_AbstractHasBody, "get").WithArguments("I5.this[int].get"), + // (31,9): error CS0500: 'I5.this[int].set' cannot declare a body because it is marked abstract + // set => throw null; + Diagnostic(ErrorCode.ERR_AbstractHasBody, "set").WithArguments("I5.this[int].set").WithLocation(31, 9), + // (36,26): error CS0503: The abstract method 'I6.this[int]' cannot be marked virtual + // abstract virtual int this[int x] { set => throw null; } + Diagnostic(ErrorCode.ERR_AbstractNotVirtual, "this").WithArguments("I6.this[int]").WithLocation(36, 26), + // (36,40): error CS0500: 'I6.this[int].set' cannot declare a body because it is marked abstract + // abstract virtual int this[int x] { set => throw null; } + Diagnostic(ErrorCode.ERR_AbstractHasBody, "set").WithArguments("I6.this[int].set").WithLocation(36, 40), + // (40,26): error CS0503: The abstract method 'I7.this[int]' cannot be marked virtual + // abstract virtual int this[int x] => throw null; + Diagnostic(ErrorCode.ERR_AbstractNotVirtual, "this").WithArguments("I7.this[int]").WithLocation(40, 26), + // (40,41): error CS0500: 'I7.this[int].get' cannot declare a body because it is marked abstract + // abstract virtual int this[int x] => throw null; + Diagnostic(ErrorCode.ERR_AbstractHasBody, "throw null").WithArguments("I7.this[int].get").WithLocation(40, 41), + // (44,26): error CS0503: The abstract method 'I8.this[int]' cannot be marked virtual + // abstract virtual int this[int x] {get;} = 0; + Diagnostic(ErrorCode.ERR_AbstractNotVirtual, "this").WithArguments("I8.this[int]").WithLocation(44, 26), + // (90,15): error CS0535: 'Test2' does not implement interface member 'I0.this[int]' + // class Test2 : I0, I1, I2, I3, I4, I5, I6, I7, I8 + Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I0").WithArguments("Test2", "I0.this[int]"), + // (90,19): error CS0535: 'Test2' does not implement interface member 'I1.this[int]' + // class Test2 : I0, I1, I2, I3, I4, I5, I6, I7, I8 + Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test2", "I1.this[int]"), + // (90,23): error CS0535: 'Test2' does not implement interface member 'I2.this[int]' + // class Test2 : I0, I1, I2, I3, I4, I5, I6, I7, I8 + Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I2").WithArguments("Test2", "I2.this[int]"), + // (90,27): error CS0535: 'Test2' does not implement interface member 'I3.this[int]' + // class Test2 : I0, I1, I2, I3, I4, I5, I6, I7, I8 + Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I3").WithArguments("Test2", "I3.this[int]"), + // (90,31): error CS0535: 'Test2' does not implement interface member 'I4.this[int]' + // class Test2 : I0, I1, I2, I3, I4, I5, I6, I7, I8 + Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I4").WithArguments("Test2", "I4.this[int]"), + // (90,35): error CS0535: 'Test2' does not implement interface member 'I5.this[int]' + // class Test2 : I0, I1, I2, I3, I4, I5, I6, I7, I8 + Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I5").WithArguments("Test2", "I5.this[int]"), + // (90,39): error CS0535: 'Test2' does not implement interface member 'I6.this[int]' + // class Test2 : I0, I1, I2, I3, I4, I5, I6, I7, I8 + Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I6").WithArguments("Test2", "I6.this[int]"), + // (90,43): error CS0535: 'Test2' does not implement interface member 'I7.this[int]' + // class Test2 : I0, I1, I2, I3, I4, I5, I6, I7, I8 + Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I7").WithArguments("Test2", "I7.this[int]"), + // (90,47): error CS0535: 'Test2' does not implement interface member 'I8.this[int]' + // class Test2 : I0, I1, I2, I3, I4, I5, I6, I7, I8 + Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I8").WithArguments("Test2", "I8.this[int]") + ); + } + + [Fact] + public void IndexerModifiers_16() + { + var source1 = +@" +public interface I1 +{ + extern int this[int x] {get;} +} +public interface I2 +{ + virtual extern int this[int x] {set;} +} +public interface I4 +{ + private extern int this[int x] {get;} +} +public interface I5 +{ + extern sealed int this[int x] {set;} +} + +class Test1 : I1, I2, I4, I5 +{ +} + +class Test2 : I1, I2, I4, I5 +{ + int I1.this[int x] => 0; + int I2.this[int x] { set {} } +} +"; + ValidatePropertyModifiers_16(source1); + } + + [Fact] + public void IndexerModifiers_17() + { + var source1 = +@" +public interface I1 +{ + abstract extern int this[int x] {get;} +} +public interface I2 +{ + extern int this[int x] => 0; +} +public interface I3 +{ + static extern int this[int x] {get => 0; set => throw null;} +} +public interface I4 +{ + private extern int this[int x] { get {throw null;} set {throw null;}} +} +public interface I5 +{ + extern sealed int this[int x] {get;} = 0; +} + +class Test1 : I1, I2, I3, I4, I5 +{ +} + +class Test2 : I1, I2, I3, I4, I5 +{ + int I1.this[int x] => 0; + int I2.this[int x] => 0; + int I3.this[int x] { get => 0; set => throw null;} + int I4.this[int x] { get => 0; set => throw null;} + int I5.this[int x] => 0; +} +"; + ValidatePropertyModifiers_17(source1, + // (20,42): error CS1519: Invalid token '=' in class, struct, or interface member declaration + // extern sealed int this[int x] {get;} = 0; + Diagnostic(ErrorCode.ERR_InvalidMemberDecl, "=").WithArguments("=").WithLocation(20, 42), + // (4,25): error CS0180: 'I1.this[int]' cannot be both extern and abstract + // abstract extern int this[int x] {get;} + Diagnostic(ErrorCode.ERR_AbstractAndExtern, "this").WithArguments("I1.this[int]").WithLocation(4, 25), + // (8,31): error CS0179: 'I2.this[int].get' cannot be extern and declare a body + // extern int this[int x] => 0; + Diagnostic(ErrorCode.ERR_ExternHasBody, "0").WithArguments("I2.this[int].get").WithLocation(8, 31), + // (12,23): error CS0106: The modifier 'static' is not valid for this item + // static extern int this[int x] {get => 0; set => throw null;} + Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("static").WithLocation(12, 23), + // (12,36): error CS0179: 'I3.this[int].get' cannot be extern and declare a body + // static extern int this[int x] {get => 0; set => throw null;} + Diagnostic(ErrorCode.ERR_ExternHasBody, "get").WithArguments("I3.this[int].get").WithLocation(12, 36), + // (12,46): error CS0179: 'I3.this[int].set' cannot be extern and declare a body + // static extern int this[int x] {get => 0; set => throw null;} + Diagnostic(ErrorCode.ERR_ExternHasBody, "set").WithArguments("I3.this[int].set").WithLocation(12, 46), + // (16,38): error CS0179: 'I4.this[int].get' cannot be extern and declare a body + // private extern int this[int x] { get {throw null;} set {throw null;}} + Diagnostic(ErrorCode.ERR_ExternHasBody, "get").WithArguments("I4.this[int].get").WithLocation(16, 38), + // (16,56): error CS0179: 'I4.this[int].set' cannot be extern and declare a body + // private extern int this[int x] { get {throw null;} set {throw null;}} + Diagnostic(ErrorCode.ERR_ExternHasBody, "set").WithArguments("I4.this[int].set").WithLocation(16, 56), + // (23,15): error CS0535: 'Test1' does not implement interface member 'I1.this[int]' + // class Test1 : I1, I2, I3, I4, I5 + Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test1", "I1.this[int]"), + // (32,12): error CS0539: 'Test2.this[int]' in explicit interface declaration is not found among members of the interface that can be implemented + // int I4.this[int x] { get => 0; set => throw null;} + Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "this").WithArguments("Test2.this[int]").WithLocation(32, 12), + // (33,12): error CS0539: 'Test2.this[int]' in explicit interface declaration is not found among members of the interface that can be implemented + // int I5.this[int x] => 0; + Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "this").WithArguments("Test2.this[int]").WithLocation(33, 12), + // (20,36): warning CS0626: Method, operator, or accessor 'I5.this[int].get' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. + // extern sealed int this[int x] {get;} = 0; + Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "get").WithArguments("I5.this[int].get").WithLocation(20, 36) + ); + } + + [Fact] + public void IndexerModifiers_18() + { + var source1 = +@" +public interface I1 +{ + abstract int this[int x] {get => 0; set => throw null;} +} +public interface I2 +{ + abstract private int this[int x] => 0; +} +public interface I3 +{ + static extern int this[int x] {get; set;} +} +public interface I4 +{ + abstract static int this[int x] { get {throw null;} set {throw null;}} +} +public interface I5 +{ + override sealed int this[int x] {get;} = 0; +} + +class Test1 : I1, I2, I3, I4, I5 +{ +} - Assert.True(p03.IsAbstract); - Assert.False(p03.IsVirtual); - Assert.False(p03.IsSealed); - Assert.False(p03.IsStatic); - Assert.False(p03.IsExtern); - Assert.False(p03.IsOverride); - Assert.Equal(Accessibility.Public, p03.DeclaredAccessibility); +class Test2 : I1, I2, I3, I4, I5 +{ + int I1.this[int x] { get => 0; set => throw null;} + int I2.this[int x] => 0; + int I3.this[int x] { get => 0; set => throw null;} + int I4.this[int x] { get => 0; set => throw null;} + int I5.this[int x] => 0; +} +"; + ValidatePropertyModifiers_18(source1, + // (20,44): error CS1519: Invalid token '=' in class, struct, or interface member declaration + // override sealed int this[int x] {get;} = 0; + Diagnostic(ErrorCode.ERR_InvalidMemberDecl, "=").WithArguments("=").WithLocation(20, 44), + // (4,31): error CS0500: 'I1.this[int].get' cannot declare a body because it is marked abstract + // abstract int this[int x] {get => 0; set => throw null;} + Diagnostic(ErrorCode.ERR_AbstractHasBody, "get").WithArguments("I1.this[int].get").WithLocation(4, 31), + // (4,41): error CS0500: 'I1.this[int].set' cannot declare a body because it is marked abstract + // abstract int this[int x] {get => 0; set => throw null;} + Diagnostic(ErrorCode.ERR_AbstractHasBody, "set").WithArguments("I1.this[int].set").WithLocation(4, 41), + // (8,26): error CS0621: 'I2.this[int]': virtual or abstract members cannot be private + // abstract private int this[int x] => 0; + Diagnostic(ErrorCode.ERR_VirtualPrivate, "this").WithArguments("I2.this[int]").WithLocation(8, 26), + // (8,41): error CS0500: 'I2.this[int].get' cannot declare a body because it is marked abstract + // abstract private int this[int x] => 0; + Diagnostic(ErrorCode.ERR_AbstractHasBody, "0").WithArguments("I2.this[int].get").WithLocation(8, 41), + // (12,23): error CS0106: The modifier 'static' is not valid for this item + // static extern int this[int x] {get; set;} + Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("static").WithLocation(12, 23), + // (16,25): error CS0106: The modifier 'static' is not valid for this item + // abstract static int this[int x] { get {throw null;} set {throw null;}} + Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("static").WithLocation(16, 25), + // (16,39): error CS0500: 'I4.this[int].get' cannot declare a body because it is marked abstract + // abstract static int this[int x] { get {throw null;} set {throw null;}} + Diagnostic(ErrorCode.ERR_AbstractHasBody, "get").WithArguments("I4.this[int].get").WithLocation(16, 39), + // (16,57): error CS0500: 'I4.this[int].set' cannot declare a body because it is marked abstract + // abstract static int this[int x] { get {throw null;} set {throw null;}} + Diagnostic(ErrorCode.ERR_AbstractHasBody, "set").WithArguments("I4.this[int].set").WithLocation(16, 57), + // (20,25): error CS0106: The modifier 'override' is not valid for this item + // override sealed int this[int x] {get;} = 0; + Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("override").WithLocation(20, 25), + // (20,38): error CS0501: 'I5.this[int].get' must declare a body because it is not marked abstract, extern, or partial + // override sealed int this[int x] {get;} = 0; + Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "get").WithArguments("I5.this[int].get").WithLocation(20, 38), + // (23,15): error CS0535: 'Test1' does not implement interface member 'I1.this[int]' + // class Test1 : I1, I2, I3, I4, I5 + Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test1", "I1.this[int]"), + // (23,19): error CS0535: 'Test1' does not implement interface member 'I2.this[int]' + // class Test1 : I1, I2, I3, I4, I5 + Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I2").WithArguments("Test1", "I2.this[int]"), + // (23,27): error CS0535: 'Test1' does not implement interface member 'I4.this[int]' + // class Test1 : I1, I2, I3, I4, I5 + Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I4").WithArguments("Test1", "I4.this[int]").WithLocation(23, 27), + // (30,12): error CS0122: 'I2.this[int]' is inaccessible due to its protection level + // int I2.this[int x] => 0; + Diagnostic(ErrorCode.ERR_BadAccess, "this").WithArguments("I2.this[int]").WithLocation(30, 12), + // (33,12): error CS0539: 'Test2.this[int]' in explicit interface declaration is not found among members of the interface that can be implemented + // int I5.this[int x] => 0; + Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "this").WithArguments("Test2.this[int]").WithLocation(33, 12), + // (12,36): warning CS0626: Method, operator, or accessor 'I3.this[int].get' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. + // static extern int this[int x] {get; set;} + Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "get").WithArguments("I3.this[int].get").WithLocation(12, 36), + // (12,41): warning CS0626: Method, operator, or accessor 'I3.this[int].set' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. + // static extern int this[int x] {get; set;} + Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "set").WithArguments("I3.this[int].set").WithLocation(12, 41) + ); + } - Assert.True(p03set.IsAbstract); - Assert.False(p03set.IsVirtual); - Assert.True(p03set.IsMetadataVirtual()); - Assert.False(p03set.IsSealed); - Assert.False(p03set.IsStatic); - Assert.False(p03set.IsExtern); - Assert.False(p03set.IsAsync); - Assert.False(p03set.IsOverride); - Assert.Equal(Accessibility.Public, p03set.DeclaredAccessibility); + [Fact] + public void IndexerModifiers_19() + { + var source1 = +@" - var p04 = compilation1.GetMember("I04.this[]"); - var p04get = p04.GetMethod; +public interface I2 {} - Assert.True(p04.IsAbstract); - Assert.False(p04.IsVirtual); - Assert.False(p04.IsSealed); - Assert.False(p04.IsStatic); - Assert.False(p04.IsExtern); - Assert.False(p04.IsOverride); - Assert.Equal(Accessibility.Internal, p04.DeclaredAccessibility); +public interface I01{ public int I2.this[int x] {get; set;} } +public interface I02{ protected int I2.this[int x] {get;} } +public interface I03{ protected internal int I2.this[int x] {set;} } +public interface I04{ internal int I2.this[int x] {get;} } +public interface I05{ private int I2.this[int x] {set;} } +public interface I06{ static int I2.this[int x] {get;} } +public interface I07{ virtual int I2.this[int x] {set;} } +public interface I08{ sealed int I2.this[int x] {get;} } +public interface I09{ override int I2.this[int x] {set;} } +public interface I10{ abstract int I2.this[int x] {get;} } +public interface I11{ extern int I2.this[int x] {get; set;} } - Assert.True(p04get.IsAbstract); - Assert.False(p04get.IsVirtual); - Assert.True(p04get.IsMetadataVirtual()); - Assert.False(p04get.IsSealed); - Assert.False(p04get.IsStatic); - Assert.False(p04get.IsExtern); - Assert.False(p04get.IsAsync); - Assert.False(p04get.IsOverride); - Assert.Equal(Accessibility.Internal, p04get.DeclaredAccessibility); +public interface I12{ int I2.this[int x] { public get; set;} } +public interface I13{ int I2.this[int x] { get; protected set;} } +public interface I14{ int I2.this[int x] { protected internal get; set;} } +public interface I15{ int I2.this[int x] { get; internal set;} } +public interface I16{ int I2.this[int x] { private get; set;} } +public interface I17{ int I2.this[int x] { private get;} } +"; + var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + var expected = new[] + { + // (5,37): error CS0106: The modifier 'public' is not valid for this item + // public interface I01{ public int I2.this[int x] {get; set;} } + Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("public").WithLocation(5, 37), + // (5,37): error CS0541: 'I01.this[int]': explicit interface declaration can only be declared in a class or struct + // public interface I01{ public int I2.this[int x] {get; set;} } + Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "this").WithArguments("I01.this[int]").WithLocation(5, 37), + // (6,40): error CS0106: The modifier 'protected' is not valid for this item + // public interface I02{ protected int I2.this[int x] {get;} } + Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("protected").WithLocation(6, 40), + // (6,40): error CS0541: 'I02.this[int]': explicit interface declaration can only be declared in a class or struct + // public interface I02{ protected int I2.this[int x] {get;} } + Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "this").WithArguments("I02.this[int]").WithLocation(6, 40), + // (7,49): error CS0106: The modifier 'protected internal' is not valid for this item + // public interface I03{ protected internal int I2.this[int x] {set;} } + Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("protected internal").WithLocation(7, 49), + // (7,49): error CS0541: 'I03.this[int]': explicit interface declaration can only be declared in a class or struct + // public interface I03{ protected internal int I2.this[int x] {set;} } + Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "this").WithArguments("I03.this[int]").WithLocation(7, 49), + // (8,39): error CS0106: The modifier 'internal' is not valid for this item + // public interface I04{ internal int I2.this[int x] {get;} } + Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("internal").WithLocation(8, 39), + // (8,39): error CS0541: 'I04.this[int]': explicit interface declaration can only be declared in a class or struct + // public interface I04{ internal int I2.this[int x] {get;} } + Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "this").WithArguments("I04.this[int]").WithLocation(8, 39), + // (9,38): error CS0106: The modifier 'private' is not valid for this item + // public interface I05{ private int I2.this[int x] {set;} } + Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("private").WithLocation(9, 38), + // (9,38): error CS0541: 'I05.this[int]': explicit interface declaration can only be declared in a class or struct + // public interface I05{ private int I2.this[int x] {set;} } + Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "this").WithArguments("I05.this[int]").WithLocation(9, 38), + // (10,37): error CS0106: The modifier 'static' is not valid for this item + // public interface I06{ static int I2.this[int x] {get;} } + Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("static").WithLocation(10, 37), + // (10,37): error CS0541: 'I06.this[int]': explicit interface declaration can only be declared in a class or struct + // public interface I06{ static int I2.this[int x] {get;} } + Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "this").WithArguments("I06.this[int]").WithLocation(10, 37), + // (11,38): error CS0106: The modifier 'virtual' is not valid for this item + // public interface I07{ virtual int I2.this[int x] {set;} } + Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("virtual").WithLocation(11, 38), + // (11,38): error CS0541: 'I07.this[int]': explicit interface declaration can only be declared in a class or struct + // public interface I07{ virtual int I2.this[int x] {set;} } + Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "this").WithArguments("I07.this[int]").WithLocation(11, 38), + // (12,37): error CS0106: The modifier 'sealed' is not valid for this item + // public interface I08{ sealed int I2.this[int x] {get;} } + Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("sealed").WithLocation(12, 37), + // (12,37): error CS0541: 'I08.this[int]': explicit interface declaration can only be declared in a class or struct + // public interface I08{ sealed int I2.this[int x] {get;} } + Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "this").WithArguments("I08.this[int]").WithLocation(12, 37), + // (13,39): error CS0106: The modifier 'override' is not valid for this item + // public interface I09{ override int I2.this[int x] {set;} } + Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("override").WithLocation(13, 39), + // (13,39): error CS0541: 'I09.this[int]': explicit interface declaration can only be declared in a class or struct + // public interface I09{ override int I2.this[int x] {set;} } + Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "this").WithArguments("I09.this[int]").WithLocation(13, 39), + // (14,39): error CS0106: The modifier 'abstract' is not valid for this item + // public interface I10{ abstract int I2.this[int x] {get;} } + Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("abstract").WithLocation(14, 39), + // (14,39): error CS0541: 'I10.this[int]': explicit interface declaration can only be declared in a class or struct + // public interface I10{ abstract int I2.this[int x] {get;} } + Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "this").WithArguments("I10.this[int]").WithLocation(14, 39), + // (15,37): error CS0106: The modifier 'extern' is not valid for this item + // public interface I11{ extern int I2.this[int x] {get; set;} } + Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("extern").WithLocation(15, 37), + // (15,37): error CS0541: 'I11.this[int]': explicit interface declaration can only be declared in a class or struct + // public interface I11{ extern int I2.this[int x] {get; set;} } + Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "this").WithArguments("I11.this[int]").WithLocation(15, 37), + // (17,30): error CS0541: 'I12.this[int]': explicit interface declaration can only be declared in a class or struct + // public interface I12{ int I2.this[int x] { public get; set;} } + Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "this").WithArguments("I12.this[int]").WithLocation(17, 30), + // (17,51): error CS0106: The modifier 'public' is not valid for this item + // public interface I12{ int I2.this[int x] { public get; set;} } + Diagnostic(ErrorCode.ERR_BadMemberFlag, "get").WithArguments("public").WithLocation(17, 51), + // (18,30): error CS0541: 'I13.this[int]': explicit interface declaration can only be declared in a class or struct + // public interface I13{ int I2.this[int x] { get; protected set;} } + Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "this").WithArguments("I13.this[int]").WithLocation(18, 30), + // (18,59): error CS0106: The modifier 'protected' is not valid for this item + // public interface I13{ int I2.this[int x] { get; protected set;} } + Diagnostic(ErrorCode.ERR_BadMemberFlag, "set").WithArguments("protected").WithLocation(18, 59), + // (19,30): error CS0541: 'I14.this[int]': explicit interface declaration can only be declared in a class or struct + // public interface I14{ int I2.this[int x] { protected internal get; set;} } + Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "this").WithArguments("I14.this[int]").WithLocation(19, 30), + // (19,63): error CS0106: The modifier 'protected internal' is not valid for this item + // public interface I14{ int I2.this[int x] { protected internal get; set;} } + Diagnostic(ErrorCode.ERR_BadMemberFlag, "get").WithArguments("protected internal").WithLocation(19, 63), + // (20,30): error CS0541: 'I15.this[int]': explicit interface declaration can only be declared in a class or struct + // public interface I15{ int I2.this[int x] { get; internal set;} } + Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "this").WithArguments("I15.this[int]").WithLocation(20, 30), + // (20,58): error CS0106: The modifier 'internal' is not valid for this item + // public interface I15{ int I2.this[int x] { get; internal set;} } + Diagnostic(ErrorCode.ERR_BadMemberFlag, "set").WithArguments("internal").WithLocation(20, 58), + // (21,30): error CS0541: 'I16.this[int]': explicit interface declaration can only be declared in a class or struct + // public interface I16{ int I2.this[int x] { private get; set;} } + Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "this").WithArguments("I16.this[int]").WithLocation(21, 30), + // (21,52): error CS0106: The modifier 'private' is not valid for this item + // public interface I16{ int I2.this[int x] { private get; set;} } + Diagnostic(ErrorCode.ERR_BadMemberFlag, "get").WithArguments("private").WithLocation(21, 52), + // (22,30): error CS0541: 'I17.this[int]': explicit interface declaration can only be declared in a class or struct + // public interface I17{ int I2.this[int x] { private get;} } + Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "this").WithArguments("I17.this[int]").WithLocation(22, 30), + // (22,52): error CS0106: The modifier 'private' is not valid for this item + // public interface I17{ int I2.this[int x] { private get;} } + Diagnostic(ErrorCode.ERR_BadMemberFlag, "get").WithArguments("private").WithLocation(22, 52) + }; - var p05 = compilation1.GetMember("I05.this[]"); - var p05set = p05.SetMethod; + compilation1.VerifyDiagnostics(expected); - Assert.False(p05.IsAbstract); - Assert.False(p05.IsVirtual); - Assert.False(p05.IsSealed); - Assert.False(p05.IsStatic); - Assert.False(p05.IsExtern); - Assert.False(p05.IsOverride); - Assert.Equal(Accessibility.Private, p05.DeclaredAccessibility); + ValidateSymbolsIndexerModifiers_19(compilation1); - Assert.False(p05set.IsAbstract); - Assert.False(p05set.IsVirtual); - Assert.False(p05set.IsMetadataVirtual()); - Assert.False(p05set.IsSealed); - Assert.False(p05set.IsStatic); - Assert.False(p05set.IsExtern); - Assert.False(p05set.IsAsync); - Assert.False(p05set.IsOverride); - Assert.Equal(Accessibility.Private, p05set.DeclaredAccessibility); + var compilation2 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp7)); + Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation2.VerifyDiagnostics(expected); - var p06 = compilation1.GetMember("I06.this[]"); - var p06get = p06.GetMethod; + ValidateSymbolsIndexerModifiers_19(compilation2); + } - Assert.True(p06.IsAbstract); - Assert.False(p06.IsVirtual); - Assert.False(p06.IsSealed); - Assert.False(p06.IsStatic); - Assert.False(p06.IsExtern); - Assert.False(p06.IsOverride); - Assert.Equal(Accessibility.Public, p06.DeclaredAccessibility); + private static void ValidateSymbolsIndexerModifiers_19(CSharpCompilation compilation1) + { - Assert.True(p06get.IsAbstract); - Assert.False(p06get.IsVirtual); - Assert.True(p06get.IsMetadataVirtual()); - Assert.False(p06get.IsSealed); - Assert.False(p06get.IsStatic); - Assert.False(p06get.IsExtern); - Assert.False(p06get.IsAsync); - Assert.False(p06get.IsOverride); - Assert.Equal(Accessibility.Public, p06get.DeclaredAccessibility); + for (int i = 1; i <= 17; i++) + { + var i1 = compilation1.GetTypeByMetadataName("I" + (i < 10 ? "0" : "") + i); + ValidateSymbolsPropertyModifiers_19(i1.GetMember("I2.this[]")); + } + } - var p07 = compilation1.GetMember("I07.this[]"); - var p07set = p07.SetMethod; + [Fact] + public void IndexerModifiers_20() + { + var source1 = +@" +public interface I1 +{ + internal int this[int x] + { + get + { + System.Console.WriteLine(""get_P1""); + return 0; + } + set + { + System.Console.WriteLine(""set_P1""); + } + } - Assert.False(p07.IsAbstract); - Assert.True(p07.IsVirtual); - Assert.False(p07.IsSealed); - Assert.False(p07.IsStatic); - Assert.False(p07.IsExtern); - Assert.False(p07.IsOverride); - Assert.Equal(Accessibility.Public, p07.DeclaredAccessibility); + void M2() {this[0] = this[0];} +} +"; - Assert.False(p07set.IsAbstract); - Assert.True(p07set.IsVirtual); - Assert.True(p07set.IsMetadataVirtual()); - Assert.False(p07set.IsSealed); - Assert.False(p07set.IsStatic); - Assert.False(p07set.IsExtern); - Assert.False(p07set.IsAsync); - Assert.False(p07set.IsOverride); - Assert.Equal(Accessibility.Public, p07set.DeclaredAccessibility); + var source2 = +@" +class Test1 : I1 +{ + static void Main() + { + I1 x = new Test1(); + x.M2(); + } +} +"; - var p08 = compilation1.GetMember("I08.this[]"); - var p08get = p08.GetMethod; + ValidatePropertyModifiers_20(source1, source2); + } - Assert.False(p08.IsAbstract); - Assert.False(p08.IsVirtual); - Assert.False(p08.IsSealed); - Assert.False(p08.IsStatic); - Assert.False(p08.IsExtern); - Assert.False(p08.IsOverride); - Assert.Equal(Accessibility.Public, p08.DeclaredAccessibility); + [Fact] + public void IndexerModifiers_21() + { + var source1 = +@" +public interface I1 +{ + private int this[int x] { get => throw null; set => throw null; } +} +public interface I2 +{ + internal int this[int x] { get => throw null; set => throw null; } +} +public interface I3 +{ + public int this[int x] { get => throw null; set => throw null; } +} +public interface I4 +{ + int this[int x] { get => throw null; set => throw null; } +} - Assert.False(p08get.IsAbstract); - Assert.False(p08get.IsVirtual); - Assert.False(p08get.IsMetadataVirtual()); - Assert.False(p08get.IsSealed); - Assert.False(p08get.IsStatic); - Assert.False(p08get.IsExtern); - Assert.False(p08get.IsAsync); - Assert.False(p08get.IsOverride); - Assert.Equal(Accessibility.Public, p08get.DeclaredAccessibility); +class Test1 +{ + static void Test(I1 i1, I2 i2, I3 i3, I4 i4) + { + int x; + x = i1[0]; + i1[0] = x; + x = i2[0]; + i2[0] = x; + x = i3[0]; + i3[0] = x; + x = i4[0]; + i4[0] = x; + } +} +"; + var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation1.VerifyDiagnostics( + // (24,13): error CS0122: 'I1.this[int]' is inaccessible due to its protection level + // x = i1[0]; + Diagnostic(ErrorCode.ERR_BadAccess, "i1[0]").WithArguments("I1.this[int]").WithLocation(24, 13), + // (25,9): error CS0122: 'I1.this[int]' is inaccessible due to its protection level + // i1[0] = x; + Diagnostic(ErrorCode.ERR_BadAccess, "i1[0]").WithArguments("I1.this[int]").WithLocation(25, 9) + ); - var p09 = compilation1.GetMember("I09.this[]"); - var p09set = p09.SetMethod; + var source2 = +@" +class Test2 +{ + static void Test(I1 i1, I2 i2, I3 i3, I4 i4) + { + int x; + x = i1[0]; + i1[0] = x; + x = i2[0]; + i2[0] = x; + x = i3[0]; + i3[0] = x; + x = i4[0]; + i4[0] = x; + } +} +"; + var compilation2 = CreateStandardCompilation(source2, new[] { compilation1.ToMetadataReference() }, + options: TestOptions.DebugDll, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation2.VerifyDiagnostics( + // (7,13): error CS0122: 'I1.this[int]' is inaccessible due to its protection level + // x = i1[0]; + Diagnostic(ErrorCode.ERR_BadAccess, "i1[0]").WithArguments("I1.this[int]").WithLocation(7, 13), + // (8,9): error CS0122: 'I1.this[int]' is inaccessible due to its protection level + // i1[0] = x; + Diagnostic(ErrorCode.ERR_BadAccess, "i1[0]").WithArguments("I1.this[int]").WithLocation(8, 9), + // (9,13): error CS0122: 'I2.this[int]' is inaccessible due to its protection level + // x = i2[0]; + Diagnostic(ErrorCode.ERR_BadAccess, "i2[0]").WithArguments("I2.this[int]").WithLocation(9, 13), + // (10,9): error CS0122: 'I2.this[int]' is inaccessible due to its protection level + // i2[0] = x; + Diagnostic(ErrorCode.ERR_BadAccess, "i2[0]").WithArguments("I2.this[int]").WithLocation(10, 9) + ); + } + + [Fact] + public void IndexerModifiers_22() + { + var source1 = +@" +public interface I1 +{ + public int this[int x] + { + internal get + { + System.Console.WriteLine(""get_P1""); + return 0; + } + set + { + System.Console.WriteLine(""set_P1""); + } + } +} +public interface I2 +{ + int this[int x] + { + get + { + System.Console.WriteLine(""get_P2""); + return 0; + } + internal set + { + System.Console.WriteLine(""set_P2""); + } + } +} +public interface I3 +{ + int this[int x] + { + internal get => Test1.GetP3(); + set => System.Console.WriteLine(""set_P3""); + } +} +public interface I4 +{ + int this[int x] + { + get => Test1.GetP4(); + internal set => System.Console.WriteLine(""set_P4""); + } +} +public interface I5 +{ + int this[int x] + { + private get + { + System.Console.WriteLine(""get_P5""); + return 0; + } + set + { + System.Console.WriteLine(""set_P5""); + } + } - Assert.True(p09.IsAbstract); - Assert.False(p09.IsVirtual); - Assert.False(p09.IsSealed); - Assert.False(p09.IsStatic); - Assert.False(p09.IsExtern); - Assert.False(p09.IsOverride); - Assert.Equal(Accessibility.Public, p09.DeclaredAccessibility); + void Test() + { + this[0] = this[0]; + } +} +public interface I6 +{ + int this[int x] + { + get + { + System.Console.WriteLine(""get_P6""); + return 0; + } + private set + { + System.Console.WriteLine(""set_P6""); + } + } - Assert.True(p09set.IsAbstract); - Assert.False(p09set.IsVirtual); - Assert.True(p09set.IsMetadataVirtual()); - Assert.False(p09set.IsSealed); - Assert.False(p09set.IsStatic); - Assert.False(p09set.IsExtern); - Assert.False(p09set.IsAsync); - Assert.False(p09set.IsOverride); - Assert.Equal(Accessibility.Public, p09set.DeclaredAccessibility); + void Test() + { + this[0] = this[0]; + } +} +public interface I7 +{ + int this[int x] + { + private get => Test1.GetP7(); + set => System.Console.WriteLine(""set_P7""); + } - var p10 = compilation1.GetMember("I10.this[]"); - var p10get = p10.GetMethod; + void Test() + { + this[0] = this[0]; + } +} +public interface I8 +{ + int this[int x] + { + get => Test1.GetP8(); + private set => System.Console.WriteLine(""set_P8""); + } - Assert.True(p10.IsAbstract); - Assert.False(p10.IsVirtual); - Assert.False(p10.IsSealed); - Assert.False(p10.IsStatic); - Assert.False(p10.IsExtern); - Assert.False(p10.IsOverride); - Assert.Equal(Accessibility.Public, p10.DeclaredAccessibility); + void Test() + { + this[0] = this[0]; + } +} - Assert.True(p10get.IsAbstract); - Assert.False(p10get.IsVirtual); - Assert.True(p10get.IsMetadataVirtual()); - Assert.False(p10get.IsSealed); - Assert.False(p10get.IsStatic); - Assert.False(p10get.IsExtern); - Assert.False(p10get.IsAsync); - Assert.False(p10get.IsOverride); - Assert.Equal(Accessibility.Public, p10get.DeclaredAccessibility); +class Test1 : I1, I2, I3, I4, I5, I6, I7, I8 +{ + static void Main() + { + I1 i1 = new Test1(); + I2 i2 = new Test1(); + I3 i3 = new Test1(); + I4 i4 = new Test1(); + I5 i5 = new Test1(); + I6 i6 = new Test1(); + I7 i7 = new Test1(); + I8 i8 = new Test1(); - var p11 = compilation1.GetMember("I11.this[]"); + i1[0] = i1[0]; + i2[0] = i2[0]; + i3[0] = i3[0]; + i4[0] = i4[0]; + i5.Test(); + i6.Test(); + i7.Test(); + i8.Test(); + } - Assert.False(p11.IsAbstract); - Assert.True(p11.IsVirtual); - Assert.False(p11.IsSealed); - Assert.False(p11.IsStatic); - Assert.True(p11.IsExtern); - Assert.False(p11.IsOverride); - Assert.Equal(Accessibility.Public, p11.DeclaredAccessibility); + public static int GetP3() + { + System.Console.WriteLine(""get_P3""); + return 0; + } - ValidateP11Accessor(p11.GetMethod); - ValidateP11Accessor(p11.SetMethod); - void ValidateP11Accessor(MethodSymbol accessor) - { - Assert.False(accessor.IsAbstract); - Assert.True(accessor.IsVirtual); - Assert.True(accessor.IsMetadataVirtual()); - Assert.False(accessor.IsSealed); - Assert.False(accessor.IsStatic); - Assert.True(accessor.IsExtern); - Assert.False(accessor.IsAsync); - Assert.False(accessor.IsOverride); - Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); - } + public static int GetP4() + { + System.Console.WriteLine(""get_P4""); + return 0; + } - var p12 = compilation1.GetMember("I12.this[]"); + public static int GetP7() + { + System.Console.WriteLine(""get_P7""); + return 0; + } - Assert.True(p12.IsAbstract); - Assert.False(p12.IsVirtual); - Assert.False(p12.IsSealed); - Assert.False(p12.IsStatic); - Assert.False(p12.IsExtern); - Assert.False(p12.IsOverride); - Assert.Equal(Accessibility.Public, p12.DeclaredAccessibility); + public static int GetP8() + { + System.Console.WriteLine(""get_P8""); + return 0; + } +} +"; - ValidateP12Accessor(p12.GetMethod); - ValidateP12Accessor(p12.SetMethod); - void ValidateP12Accessor(MethodSymbol accessor) - { - Assert.True(accessor.IsAbstract); - Assert.False(accessor.IsVirtual); - Assert.True(accessor.IsMetadataVirtual()); - Assert.False(accessor.IsSealed); - Assert.False(accessor.IsStatic); - Assert.False(accessor.IsExtern); - Assert.False(accessor.IsAsync); - Assert.False(accessor.IsOverride); - Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); - } + ValidatePropertyModifiers_22(source1); + } - var p13 = compilation1.GetMember("I13.this[]"); + [Fact] + public void IndexerModifiers_23_00() + { + var source1 = +@" +public interface I1 +{ +} +public interface I3 +{ + int this[int x] + { + private get + { + System.Console.WriteLine(""get_P3""); + return 0; + } + set {} + } - Assert.True(p13.IsAbstract); - Assert.False(p13.IsVirtual); - Assert.False(p13.IsSealed); - Assert.False(p13.IsStatic); - Assert.False(p13.IsExtern); - Assert.False(p13.IsOverride); - Assert.Equal(Accessibility.Public, p13.DeclaredAccessibility); + void M2() + { + this[0] = this[1]; + } +} +public interface I4 +{ + int this[int x] + { + get {throw null;} + private set {System.Console.WriteLine(""set_P4"");} + } - ValidateP13Accessor(p13.GetMethod); - ValidateP13Accessor(p13.SetMethod); - void ValidateP13Accessor(MethodSymbol accessor) - { - Assert.True(accessor.IsAbstract); - Assert.False(accessor.IsVirtual); - Assert.True(accessor.IsMetadataVirtual()); - Assert.False(accessor.IsSealed); - Assert.False(accessor.IsStatic); - Assert.False(accessor.IsExtern); - Assert.False(accessor.IsAsync); - Assert.False(accessor.IsOverride); - Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); - } + void M2() + { + this[0] = this[1]; + } +} +public interface I5 +{ + int this[int x] + { + private get => GetP5(); + set => throw null; + } - var p14 = compilation1.GetMember("I14.this[]"); + private int GetP5() + { + System.Console.WriteLine(""get_P5""); + return 0; + } - Assert.True(p14.IsAbstract); - Assert.False(p14.IsVirtual); - Assert.False(p14.IsSealed); - Assert.False(p14.IsStatic); - Assert.False(p14.IsExtern); - Assert.False(p14.IsOverride); - Assert.Equal(Accessibility.Public, p14.DeclaredAccessibility); + void M2() + { + this[0] = this[1]; + } +} +public interface I6 +{ + int this[int x] + { + get => throw null; + private set => System.Console.WriteLine(""set_P6""); + } - ValidateP14Accessor(p14.GetMethod); - ValidateP14Accessor(p14.SetMethod); - void ValidateP14Accessor(MethodSymbol accessor) - { - Assert.True(accessor.IsAbstract); - Assert.False(accessor.IsVirtual); - Assert.True(accessor.IsMetadataVirtual()); - Assert.False(accessor.IsSealed); - Assert.False(accessor.IsStatic); - Assert.False(accessor.IsExtern); - Assert.False(accessor.IsAsync); - Assert.False(accessor.IsOverride); - Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); - } + void M2() + { + this[0] = this[1]; + } +} +"; - var p15 = compilation1.GetMember("I15.this[]"); + var source2 = +@" +class Test1 : I1 +{ + static void Main() + { + I3 i3 = new Test3(); + I4 i4 = new Test4(); + I5 i5 = new Test5(); + I6 i6 = new Test6(); + i3.M2(); + i4.M2(); + i5.M2(); + i6.M2(); + } +} +class Test3 : I3 +{ + public int this[int x] + { + get + { + throw null; + } + set + { + System.Console.WriteLine(""set_P3""); + } + } +} +class Test4 : I4 +{ + public int this[int x] + { + get + { + System.Console.WriteLine(""get_P4""); + return 0; + } + set + { + throw null; + } + } +} +class Test5 : I5 +{ + public int this[int x] + { + get + { + throw null; + } + set + { + System.Console.WriteLine(""set_P5""); + } + } +} +class Test6 : I6 +{ + public int this[int x] + { + get + { + System.Console.WriteLine(""get_P6""); + return 0; + } + set + { + throw null; + } + } +} +"; + ValidatePropertyModifiers_23(source1, source2); + } - Assert.True(p15.IsAbstract); - Assert.False(p15.IsVirtual); - Assert.False(p15.IsSealed); - Assert.False(p15.IsStatic); - Assert.False(p15.IsExtern); - Assert.False(p15.IsOverride); - Assert.Equal(Accessibility.Public, p15.DeclaredAccessibility); + [Fact] + public void IndexerModifiers_23_01() + { + var source1 = +@" +public interface I1 +{ + abstract int this[int x] {internal get; set;} - ValidateP15Accessor(p15.GetMethod, Accessibility.Public); - ValidateP15Accessor(p15.SetMethod, Accessibility.Internal); - void ValidateP15Accessor(MethodSymbol accessor, Accessibility accessibility) - { - Assert.True(accessor.IsAbstract); - Assert.False(accessor.IsVirtual); - Assert.True(accessor.IsMetadataVirtual()); - Assert.False(accessor.IsSealed); - Assert.False(accessor.IsStatic); - Assert.False(accessor.IsExtern); - Assert.False(accessor.IsAsync); - Assert.False(accessor.IsOverride); - Assert.Equal(accessibility, accessor.DeclaredAccessibility); - } + void M2() + { + this[0] = this[1]; + } +} +"; - var p16 = compilation1.GetMember("I16.this[]"); + var source2 = +@" +class Test1 : I1 +{ + static void Main() + { + } - Assert.True(p16.IsAbstract); - Assert.False(p16.IsVirtual); - Assert.False(p16.IsSealed); - Assert.False(p16.IsStatic); - Assert.False(p16.IsExtern); - Assert.False(p16.IsOverride); - Assert.Equal(Accessibility.Public, p16.DeclaredAccessibility); + public int this[int x] + { + get + { + System.Console.WriteLine(""get_P1""); + return 0; + } + set + { + System.Console.WriteLine(""set_P1""); + } + } +} +"; + ValidatePropertyModifiers_23(source1, source2, Accessibility.Internal, Accessibility.Public, + // (2,15): error CS8504: 'Test1' does not implement interface member 'I1.this[int].get'. 'Test1.this[int].get' cannot implicitly implement a non-public member. + // class Test1 : I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test1", "I1.this[int].get", "Test1.this[int].get").WithLocation(2, 15) + ); + } - ValidateP16Accessor(p16.GetMethod, Accessibility.Private); - ValidateP16Accessor(p16.SetMethod, Accessibility.Public); - void ValidateP16Accessor(MethodSymbol accessor, Accessibility accessibility) - { - Assert.True(accessor.IsAbstract); - Assert.False(accessor.IsVirtual); - Assert.True(accessor.IsMetadataVirtual()); - Assert.False(accessor.IsSealed); - Assert.False(accessor.IsStatic); - Assert.False(accessor.IsExtern); - Assert.False(accessor.IsAsync); - Assert.False(accessor.IsOverride); - Assert.Equal(accessibility, accessor.DeclaredAccessibility); - } + [Fact] + public void IndexerModifiers_23_02() + { + var source1 = +@" +public interface I1 +{ + abstract int this[int x] {internal get; set;} +} - var p17 = compilation1.GetMember("I17.this[]"); - var p17get = p17.GetMethod; +public class TestHelper +{ + public static void CallP1(I1 x) {x[0] = x[0];} +} +"; - Assert.True(p17.IsAbstract); - Assert.False(p17.IsVirtual); - Assert.False(p17.IsSealed); - Assert.False(p17.IsStatic); - Assert.False(p17.IsExtern); - Assert.False(p17.IsOverride); - Assert.Equal(Accessibility.Public, p17.DeclaredAccessibility); + var source2 = +@" +class Test1 : I1 +{ + static void Main() + { + TestHelper.CallP1(new Test1()); + } - Assert.True(p17get.IsAbstract); - Assert.False(p17get.IsVirtual); - Assert.True(p17get.IsMetadataVirtual()); - Assert.False(p17get.IsSealed); - Assert.False(p17get.IsStatic); - Assert.False(p17get.IsExtern); - Assert.False(p17get.IsAsync); - Assert.False(p17get.IsOverride); - Assert.Equal(Accessibility.Private, p17get.DeclaredAccessibility); + public virtual int this[int x] + { + get + { + System.Console.WriteLine(""get_P1""); + return 0; + } + set + { + System.Console.WriteLine(""set_P1""); + } + } +} +"; + + ValidatePropertyModifiers_11_02(source1, source2, + // (2,15): error CS8504: 'Test1' does not implement interface member 'I1.this[int].get'. 'Test1.this[int].get' cannot implicitly implement a non-public member. + // class Test1 : I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test1", "I1.this[int].get", "Test1.this[int].get").WithLocation(2, 15) + ); } [Fact] - public void IndexerModifiers_02() + public void IndexerModifiers_23_03() { var source1 = @" -public interface I01{ public int this[int x] {get; set;} } -public interface I02{ protected int this[int x] {get;} } -public interface I03{ protected internal int this[int x] {set;} } -public interface I04{ internal int this[int x] {get;} } -public interface I05{ private int this[int x] {set;} } -public interface I06{ static int this[int x] {get;} } -public interface I07{ virtual int this[int x] {set;} } -public interface I08{ sealed int this[int x] {get;} } -public interface I09{ override int this[int x] {set;} } -public interface I10{ abstract int this[int x] {get;} } -public interface I11{ extern int this[int x] {get; set;} } +public interface I1 +{ + abstract int this[int x] {internal get; set;} +} -public interface I12{ int this[int x] { public get; set;} } -public interface I13{ int this[int x] { get; protected set;} } -public interface I14{ int this[int x] { protected internal get; set;} } -public interface I15{ int this[int x] { get; internal set;} } -public interface I16{ int this[int x] { private get; set;} } -public interface I17{ int this[int x] { private get;} } +public class TestHelper +{ + public static void CallP1(I1 x) {x[0] = x[0];} +} "; - var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, - parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp7)); - Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); - compilation1.VerifyDiagnostics( - // (2,34): error CS8503: The modifier 'public' is not valid for this item in C# 7. Please use language version 7.1 or greater. - // public interface I01{ public int this[int x] {get; set;} } - Diagnostic(ErrorCode.ERR_DefaultInterfaceImplementationModifier, "this").WithArguments("public", "7", "7.1").WithLocation(2, 34), - // (3,37): error CS0106: The modifier 'protected' is not valid for this item - // public interface I02{ protected int this[int x] {get;} } - Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("protected").WithLocation(3, 37), - // (4,46): error CS0106: The modifier 'protected internal' is not valid for this item - // public interface I03{ protected internal int this[int x] {set;} } - Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("protected internal").WithLocation(4, 46), - // (5,36): error CS8503: The modifier 'internal' is not valid for this item in C# 7. Please use language version 7.1 or greater. - // public interface I04{ internal int this[int x] {get;} } - Diagnostic(ErrorCode.ERR_DefaultInterfaceImplementationModifier, "this").WithArguments("internal", "7", "7.1").WithLocation(5, 36), - // (6,35): error CS8503: The modifier 'private' is not valid for this item in C# 7. Please use language version 7.1 or greater. - // public interface I05{ private int this[int x] {set;} } - Diagnostic(ErrorCode.ERR_DefaultInterfaceImplementationModifier, "this").WithArguments("private", "7", "7.1").WithLocation(6, 35), - // (6,48): error CS0501: 'I05.this[int].set' must declare a body because it is not marked abstract, extern, or partial - // public interface I05{ private int this[int x] {set;} } - Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "set").WithArguments("I05.this[int].set").WithLocation(6, 48), - // (7,34): error CS0106: The modifier 'static' is not valid for this item - // public interface I06{ static int this[int x] {get;} } - Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("static").WithLocation(7, 34), - // (8,35): error CS8503: The modifier 'virtual' is not valid for this item in C# 7. Please use language version 7.1 or greater. - // public interface I07{ virtual int this[int x] {set;} } - Diagnostic(ErrorCode.ERR_DefaultInterfaceImplementationModifier, "this").WithArguments("virtual", "7", "7.1").WithLocation(8, 35), - // (8,48): error CS0501: 'I07.this[int].set' must declare a body because it is not marked abstract, extern, or partial - // public interface I07{ virtual int this[int x] {set;} } - Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "set").WithArguments("I07.this[int].set").WithLocation(8, 48), - // (9,34): error CS8503: The modifier 'sealed' is not valid for this item in C# 7. Please use language version 7.1 or greater. - // public interface I08{ sealed int this[int x] {get;} } - Diagnostic(ErrorCode.ERR_DefaultInterfaceImplementationModifier, "this").WithArguments("sealed", "7", "7.1").WithLocation(9, 34), - // (9,47): error CS0501: 'I08.this[int].get' must declare a body because it is not marked abstract, extern, or partial - // public interface I08{ sealed int this[int x] {get;} } - Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "get").WithArguments("I08.this[int].get").WithLocation(9, 47), - // (10,36): error CS0106: The modifier 'override' is not valid for this item - // public interface I09{ override int this[int x] {set;} } - Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("override").WithLocation(10, 36), - // (11,36): error CS8503: The modifier 'abstract' is not valid for this item in C# 7. Please use language version 7.1 or greater. - // public interface I10{ abstract int this[int x] {get;} } - Diagnostic(ErrorCode.ERR_DefaultInterfaceImplementationModifier, "this").WithArguments("abstract", "7", "7.1").WithLocation(11, 36), - // (12,34): error CS8503: The modifier 'extern' is not valid for this item in C# 7. Please use language version 7.1 or greater. - // public interface I11{ extern int this[int x] {get; set;} } - Diagnostic(ErrorCode.ERR_DefaultInterfaceImplementationModifier, "this").WithArguments("extern", "7", "7.1").WithLocation(12, 34), - // (14,48): error CS8503: The modifier 'public' is not valid for this item in C# 7. Please use language version 7.1 or greater. - // public interface I12{ int this[int x] { public get; set;} } - Diagnostic(ErrorCode.ERR_DefaultInterfaceImplementationModifier, "get").WithArguments("public", "7", "7.1").WithLocation(14, 48), - // (14,48): error CS0273: The accessibility modifier of the 'I12.this[int].get' accessor must be more restrictive than the property or indexer 'I12.this[int]' - // public interface I12{ int this[int x] { public get; set;} } - Diagnostic(ErrorCode.ERR_InvalidPropertyAccessMod, "get").WithArguments("I12.this[int].get", "I12.this[int]").WithLocation(14, 48), - // (15,56): error CS0106: The modifier 'protected' is not valid for this item - // public interface I13{ int this[int x] { get; protected set;} } - Diagnostic(ErrorCode.ERR_BadMemberFlag, "set").WithArguments("protected").WithLocation(15, 56), - // (16,60): error CS0106: The modifier 'protected internal' is not valid for this item - // public interface I14{ int this[int x] { protected internal get; set;} } - Diagnostic(ErrorCode.ERR_BadMemberFlag, "get").WithArguments("protected internal").WithLocation(16, 60), - // (17,55): error CS8503: The modifier 'internal' is not valid for this item in C# 7. Please use language version 7.1 or greater. - // public interface I15{ int this[int x] { get; internal set;} } - Diagnostic(ErrorCode.ERR_DefaultInterfaceImplementationModifier, "set").WithArguments("internal", "7", "7.1").WithLocation(17, 55), - // (18,49): error CS8503: The modifier 'private' is not valid for this item in C# 7. Please use language version 7.1 or greater. - // public interface I16{ int this[int x] { private get; set;} } - Diagnostic(ErrorCode.ERR_DefaultInterfaceImplementationModifier, "get").WithArguments("private", "7", "7.1").WithLocation(18, 49), - // (18,49): error CS0442: 'I16.this[int].get': abstract properties cannot have private accessors - // public interface I16{ int this[int x] { private get; set;} } - Diagnostic(ErrorCode.ERR_PrivateAbstractAccessor, "get").WithArguments("I16.this[int].get").WithLocation(18, 49), - // (19,49): error CS8503: The modifier 'private' is not valid for this item in C# 7. Please use language version 7.1 or greater. - // public interface I17{ int this[int x] { private get;} } - Diagnostic(ErrorCode.ERR_DefaultInterfaceImplementationModifier, "get").WithArguments("private", "7", "7.1").WithLocation(19, 49), - // (19,27): error CS0276: 'I17.this[int]': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor - // public interface I17{ int this[int x] { private get;} } - Diagnostic(ErrorCode.ERR_AccessModMissingAccessor, "this").WithArguments("I17.this[int]").WithLocation(19, 27), - // (12,47): warning CS0626: Method, operator, or accessor 'I11.this[int].get' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. - // public interface I11{ extern int this[int x] {get; set;} } - Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "get").WithArguments("I11.this[int].get").WithLocation(12, 47), - // (12,52): warning CS0626: Method, operator, or accessor 'I11.this[int].set' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. - // public interface I11{ extern int this[int x] {get; set;} } - Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "set").WithArguments("I11.this[int].set").WithLocation(12, 52) - ); - ValidateSymbolsIndexerModifiers_01(compilation1); + var source2 = +@" +class Test1 : I1 +{ + static void Main() + { + TestHelper.CallP1(new Test1()); + } + + int I1.this[int x] + { + get + { + System.Console.WriteLine(""get_P1""); + return 0; + } + set + { + System.Console.WriteLine(""set_P1""); + } + } +} +"; + + ValidatePropertyModifiers_11_03(source1, source2, + // (9,12): error CS0122: 'I1.this[int].get' is inaccessible due to its protection level + // int I1.this[int x] + Diagnostic(ErrorCode.ERR_BadAccess, "this").WithArguments("I1.this[int].get").WithLocation(9, 12) + ); } [Fact] - public void IndexerModifiers_03() + public void IndexerModifiers_23_04() { - ValidateIndexerImplementation_101(@" + var source1 = +@" public interface I1 { - public virtual int this[int i] + abstract int this[int x] {internal get; set;} +} + +public class TestHelper +{ + public static void CallP1(I1 x) {x[0] = x[0];} +} + +public class Test2 : I1 +{ + int I1.this[int x] { get { - System.Console.WriteLine(""get P1""); + System.Console.WriteLine(""Test2.get_P1""); return 0; } + set + { + System.Console.WriteLine(""Test2.set_P1""); + } } } -class Test1 : I1 -{} -"); +"; - ValidateIndexerImplementation_101(@" -public interface I1 + var source2 = +@" +class Test1 : Test2, I1 { - public virtual int this[int i] + static void Main() { - get => Test1.GetP1(); + TestHelper.CallP1(new Test1()); } -} -class Test1 : I1 -{ - public static int GetP1() + public int this[int x] { - System.Console.WriteLine(""get P1""); - return 0; + get + { + System.Console.WriteLine(""Test1.get_P1""); + return 0; + } + set + { + System.Console.WriteLine(""Test1.set_P1""); + } } } -"); +"; - ValidateIndexerImplementation_101(@" + ValidatePropertyModifiers_11_02(source1, source2, + // (2,22): error CS8504: 'Test1' does not implement interface member 'I1.this[int].get'. 'Test1.this[int].get' cannot implicitly implement a non-public member. + // class Test1 : Test2, I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test1", "I1.this[int].get", "Test1.this[int].get").WithLocation(2, 22) + ); + } + + [Fact] + public void IndexerModifiers_23_05() + { + var source1 = +@" public interface I1 { - public virtual int this[int i] => Test1.GetP1(); + abstract int this[int x] {internal get; set;} } -class Test1 : I1 +public class TestHelper { - public static int GetP1() - { - System.Console.WriteLine(""get P1""); - return 0; - } + public static void CallP1(I1 x) {x[0] = x[0];} } -"); - ValidateIndexerImplementation_102(@" -public interface I1 +public class Test2 : I1 { - public virtual int this[int i] + int I1.this[int x] { get { - System.Console.WriteLine(""get P1""); + System.Console.WriteLine(""Test2.get_P1""); return 0; } set { - System.Console.WriteLine(""set P1""); + System.Console.WriteLine(""Test2.set_P1""); } } } -class Test1 : I1 -{} -"); +"; - ValidateIndexerImplementation_102(@" -public interface I1 + var source2 = +@" +class Test1 : Test2, I1 { - public virtual int this[int i] + static void Main() { - get => Test1.GetP1(); - set => System.Console.WriteLine(""set P1""); + TestHelper.CallP1(new Test1()); } -} -class Test1 : I1 -{ - public static int GetP1() + public virtual int this[int x] { - System.Console.WriteLine(""get P1""); - return 0; + get + { + System.Console.WriteLine(""Test1.get_P1""); + return 0; + } + set + { + System.Console.WriteLine(""Test1.set_P1""); + } } } -"); +"; - ValidateIndexerImplementation_103(@" + ValidatePropertyModifiers_11_02(source1, source2, + // (2,22): error CS8504: 'Test1' does not implement interface member 'I1.this[int].get'. 'Test1.this[int].get' cannot implicitly implement a non-public member. + // class Test1 : Test2, I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test1", "I1.this[int].get", "Test1.this[int].get").WithLocation(2, 22) + ); + } + + [Fact] + public void IndexerModifiers_23_06() + { + var source1 = +@" public interface I1 { - public virtual int this[int i] + abstract int this[int x] {internal get; set;} +} + +public class TestHelper +{ + public static void CallP1(I1 x) {x[0] = x[0];} +} + +public class Test2 : I1 +{ + int I1.this[int x] { + get + { + System.Console.WriteLine(""Test2.get_P1""); + return 0; + } set { - System.Console.WriteLine(""set P1""); + System.Console.WriteLine(""Test2.set_P1""); } } } -class Test1 : I1 -{} -"); +"; - ValidateIndexerImplementation_103(@" -public interface I1 + var source2 = +@"abstract +class Test1 : Test2, I1 { - public virtual int this[int i] + static void Main() { - set => System.Console.WriteLine(""set P1""); + TestHelper.CallP1(new Test3()); } + + public abstract int this[int x] {get; set;} } -class Test1 : I1 -{} -"); +class Test3 : Test1 +{ + public override int this[int x] + { + get + { + System.Console.WriteLine(""Test3.get_P1""); + return 0; } - - [Fact] - public void IndexerModifiers_04() + set { - var source1 = -@" -public interface I1 -{ - public virtual int this[int x] { get; } = 0; + System.Console.WriteLine(""Test3.set_P1""); + } + } } "; - var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, - parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); - Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); - compilation1.VerifyDiagnostics( - // (4,45): error CS1519: Invalid token '=' in class, struct, or interface member declaration - // public virtual int this[int x] { get; } = 0; - Diagnostic(ErrorCode.ERR_InvalidMemberDecl, "=").WithArguments("=").WithLocation(4, 45), - // (4,38): error CS0501: 'I1.this[int].get' must declare a body because it is not marked abstract, extern, or partial - // public virtual int this[int x] { get; } = 0; - Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "get").WithArguments("I1.this[int].get").WithLocation(4, 38) - ); - ValidatePropertyModifiers_04(compilation1, "this[]"); + ValidatePropertyModifiers_11_02(source1, source2, + // (2,22): error CS8504: 'Test1' does not implement interface member 'I1.this[int].get'. 'Test1.this[int].get' cannot implicitly implement a non-public member. + // class Test1 : Test2, I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test1", "I1.this[int].get", "Test1.this[int].get").WithLocation(2, 22) + ); } [Fact] - public void IndexerModifiers_05() + public void IndexerModifiers_23_07() { var source1 = @" public interface I1 { - public abstract int this[int x] {get; set;} + abstract int this[int x] {internal get; set;} } -public interface I2 + +public class TestHelper { - int this[int x] {get; set;} + public static void CallP1(I1 x) {x[0] = x[0];} } -class Test1 : I1 +public class Test2 : I1 { - public int this[int x] + int I1.this[int x] { get { - System.Console.WriteLine(""get_P1""); + System.Console.WriteLine(""Test2.get_P1""); return 0; } - set => System.Console.WriteLine(""set_P1""); + set + { + System.Console.WriteLine(""Test2.set_P1""); + } } } -class Test2 : I2 + +"; + + var source2 = +@" +class Test1 : Test2, I1, I2 { + static void Main() + { + TestHelper.CallP1(new Test1()); + } + public int this[int x] { get { - System.Console.WriteLine(""get_P2""); + System.Console.WriteLine(""Test1.get_P1""); return 0; } - set => System.Console.WriteLine(""set_P2""); + set + { + System.Console.WriteLine(""Test1.set_P1""); + } } +} - static void Main() - { - I1 x = new Test1(); - x[0] = x[0]; - I2 y = new Test2(); - y[0] = y[0]; - } +public interface I2 +{ + int this[int x] {get; set;} } "; - ValidatePropertyModifiers_05(source1); + ValidatePropertyModifiers_11_02(source1, source2, + // (2,22): error CS8504: 'Test1' does not implement interface member 'I1.this[int].get'. 'Test1.this[int].get' cannot implicitly implement a non-public member. + // class Test1 : Test2, I1, I2 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test1", "I1.this[int].get", "Test1.this[int].get").WithLocation(2, 22) + ); } [Fact] - public void IndexerModifiers_06() + public void IndexerModifiers_23_08() { var source1 = @" public interface I1 { - public abstract int this[int x] {get; set;} + abstract int this[int x] {internal get; set;} } -"; - var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, - parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp7)); - Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); - compilation1.VerifyDiagnostics( - // (4,25): error CS8503: The modifier 'abstract' is not valid for this item in C# 7. Please use language version 7.1 or greater. - // public abstract int this[int x] {get; set;} - Diagnostic(ErrorCode.ERR_DefaultInterfaceImplementationModifier, "this").WithArguments("abstract", "7", "7.1").WithLocation(4, 25), - // (4,25): error CS8503: The modifier 'public' is not valid for this item in C# 7. Please use language version 7.1 or greater. - // public abstract int this[int x] {get; set;} - Diagnostic(ErrorCode.ERR_DefaultInterfaceImplementationModifier, "this").WithArguments("public", "7", "7.1").WithLocation(4, 25) - ); - - ValidatePropertyModifiers_06(compilation1, "this[]"); - } - [Fact] - public void IndexerModifiers_09() - { - var source1 = -@" -public interface I1 +public class TestHelper { - private int this[int x] - { - get - { - System.Console.WriteLine(""get_P1""); - return 0; - } - } - sealed void M() - { - var x = this[0]; - } + public static void CallP1(I1 x) {x[0] = x[0];} } -public interface I2 + +public class Test2 : I1 { - private int this[int x] + int I1.this[int x] { get - { - System.Console.WriteLine(""get_P2""); + { + System.Console.WriteLine(""Test2.get_P1""); return 0; - } - set - { - System.Console.WriteLine(""set_P2""); - } - } - sealed void M() - { - this[0] = this[0]; - } -} -public interface I3 -{ - private int this[int x] - { + } set - { - System.Console.WriteLine(""set_P3""); - } - } - sealed void M() - { - this[0] = 0; + { + System.Console.WriteLine(""Test2.set_P1""); + } } } -public interface I4 + +"; + + var source2 = +@" +class Test1 : Test2, I1 { - private int this[int x] + static void Main() { - get => GetP4(); + TestHelper.CallP1(new Test1()); } - private int GetP4() - { - System.Console.WriteLine(""get_P4""); - return 0; - } - sealed void M() + public virtual long this[int x] { - var x = this[0]; + get + { + System.Console.WriteLine(""Test1.get_P1""); + return 0; + } + set + { + System.Console.WriteLine(""Test1.set_P1""); + } } } -public interface I5 +"; + + ValidatePropertyModifiers_11_08(source1, source2); + } + + [Fact] + public void IndexerModifiers_23_09() + { + var source1 = +@" +public interface I1 { - private int this[int x] - { - get => GetP5(); - set => System.Console.WriteLine(""set_P5""); - } + abstract int this[int x] {internal get; set;} +} - private int GetP5() - { - System.Console.WriteLine(""get_P5""); - return 0; - } - sealed void M() - { - this[0] = this[0]; - } +public class TestHelper +{ + public static void CallP1(I1 x) {x[0] = x[0];} } -public interface I6 +"; + + var source2 = +@" +class Test1 : I1 { - private int this[int x] - { - set => System.Console.WriteLine(""set_P6""); - } - sealed void M() + static void Main() { - this[0] = 0; + TestHelper.CallP1(new Test1()); } -} -public interface I7 -{ - private int this[int x] => GetP7(); - private int GetP7() - { - System.Console.WriteLine(""get_P7""); - return 0; - } - sealed void M() + public virtual long this[int x] { - var x = this[0]; + get + { + System.Console.WriteLine(""Test1.get_P1""); + return 0; + } + set + { + System.Console.WriteLine(""Test1.set_P1""); + } } } +"; -class Test1 : I1, I2, I3, I4, I5, I6, I7 + ValidatePropertyModifiers_11_09(source1, source2, + // (2,15): error CS0535: 'Test1' does not implement interface member 'I1.this[int]' + // class Test1 : I1 + Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test1", "I1.this[int]").WithLocation(2, 15) + ); + } + + [Fact] + public void IndexerModifiers_23_10() + { + var source1 = +@" +public interface I1 { - static void Main() - { - I1 x1 = new Test1(); - x1.M(); - I2 x2 = new Test1(); - x2.M(); - I3 x3 = new Test1(); - x3.M(); - I4 x4 = new Test1(); - x4.M(); - I5 x5 = new Test1(); - x5.M(); - I6 x6 = new Test1(); - x6.M(); - I7 x7 = new Test1(); - x7.M(); + abstract int this[int x] {internal get; set;} +} +"; + + var source2 = +@" +public class Test2 : I1 +{ + public int this[int x] + { + get + { + return 0; + } + set {} } } +class Test1 : Test2, I1 +{ +} "; - ValidatePropertyModifiers_09(source1); + ValidatePropertyModifiers_11_10(source1, source2, + // (2,22): error CS8504: 'Test2' does not implement interface member 'I1.this[int].get'. 'Test2.this[int].get' cannot implicitly implement a non-public member. + // public class Test2 : I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test2", "I1.this[int].get", "Test2.this[int].get").WithLocation(2, 22) + ); } [Fact] - public void IndexerModifiers_10() + public void IndexerModifiers_23_11() { var source1 = @" public interface I1 { - abstract private int this[byte x] { get; } - - virtual private int this[int x] => 0; - - sealed private int this[short x] + abstract int this[int x] {internal get; set;} +} +public class Test2 : I1 +{ + public int this[int x] { - get => 0; + get + { + return 0; + } set {} } - - private int this[long x] {get;} = 0; } +"; -class Test1 : I1 + var source2 = +@" +class Test1 : Test2, I1 { } "; - var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, - parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); - Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); - compilation1.VerifyDiagnostics( - // (14,37): error CS1519: Invalid token '=' in class, struct, or interface member declaration - // private int this[long x] {get;} = 0; - Diagnostic(ErrorCode.ERR_InvalidMemberDecl, "=").WithArguments("=").WithLocation(14, 37), - // (4,26): error CS0621: 'I1.this[byte]': virtual or abstract members cannot be private - // abstract private int this[byte x] { get; } - Diagnostic(ErrorCode.ERR_VirtualPrivate, "this").WithArguments("I1.this[byte]").WithLocation(4, 26), - // (6,25): error CS0621: 'I1.this[int]': virtual or abstract members cannot be private - // virtual private int this[int x] => 0; - Diagnostic(ErrorCode.ERR_VirtualPrivate, "this").WithArguments("I1.this[int]").WithLocation(6, 25), - // (8,24): error CS0238: 'I1.this[short]' cannot be sealed because it is not an override - // sealed private int this[short x] - Diagnostic(ErrorCode.ERR_SealedNonOverride, "this").WithArguments("I1.this[short]").WithLocation(8, 24), - // (14,31): error CS0501: 'I1.this[long].get' must declare a body because it is not marked abstract, extern, or partial - // private int this[long x] {get;} = 0; - Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "get").WithArguments("I1.this[long].get").WithLocation(14, 31), - // (17,15): error CS0535: 'Test1' does not implement interface member 'I1.this[byte]' - // class Test1 : I1 - Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test1", "I1.this[byte]") - ); - ValidatePropertyModifiers_10(compilation1); + ValidatePropertyModifiers_11_11(source1, source2, + // (6,22): error CS8504: 'Test2' does not implement interface member 'I1.this[int].get'. 'Test2.this[int].get' cannot implicitly implement a non-public member. + // public class Test2 : I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test2", "I1.this[int].get", "Test2.this[int].get").WithLocation(6, 22) + ); } [Fact] - public void IndexerModifiers_11() + public void IndexerModifiers_23_51() { var source1 = @" public interface I1 { - internal abstract int this[int x] {get; set;} + abstract int this[int x] {get; internal set;} - sealed void Test() + void M2() { this[0] = this[0]; } @@ -12630,8 +17671,6 @@ class Test1 : I1 { static void Main() { - I1 x = new Test1(); - x.Test(); } public int this[int x] @@ -12648,2935 +17687,2973 @@ public int this[int x] } } "; - - ValidatePropertyModifiers_11(source1, source2, - // (2,15): error CS0535: 'Test2' does not implement interface member 'I1.this[int]' - // class Test2 : I1 - Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test2", "I1.this[int]") + ValidatePropertyModifiers_23(source1, source2, Accessibility.Public, Accessibility.Internal, + // (2,15): error CS8504: 'Test1' does not implement interface member 'I1.this[int].set'. 'Test1.this[int].set' cannot implicitly implement a non-public member. + // class Test1 : I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test1", "I1.this[int].set", "Test1.this[int].set").WithLocation(2, 15) ); } [Fact] - public void IndexerModifiers_12() + public void IndexerModifiers_23_52() { var source1 = @" public interface I1 { - internal abstract int this[int x] {get; set;} + abstract int this[int x] {get; internal set;} } -class Test1 : I1 +public class TestHelper { + public static void CallP1(I1 x) {x[0] = x[0];} } "; - var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, - parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); - Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); - compilation1.VerifyDiagnostics( - // (7,15): error CS0535: 'Test1' does not implement interface member 'I1.this[int]' - // class Test1 : I1 - Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test1", "I1.this[int]") - ); - - var test1 = compilation1.GetTypeByMetadataName("Test1"); - var i1 = compilation1.GetTypeByMetadataName("I1"); - var p1 = i1.GetMember("this[]"); - Assert.Null(test1.FindImplementationForInterfaceMember(p1)); - Assert.Null(test1.FindImplementationForInterfaceMember(p1.GetMethod)); - Assert.Null(test1.FindImplementationForInterfaceMember(p1.SetMethod)); - } - [Fact] - public void IndexerModifiers_13() - { - var source1 = + var source2 = @" -public interface I1 +class Test1 : I1 { - public sealed int this[int x] + static void Main() { - get - { - System.Console.WriteLine(""get_P1""); - return 0; - } + TestHelper.CallP1(new Test1()); } -} -public interface I2 -{ - public sealed int this[int x] + + public virtual int this[int x] { get - { - System.Console.WriteLine(""get_P2""); + { + System.Console.WriteLine(""get_P1""); return 0; - } - set - { - System.Console.WriteLine(""set_P2""); - } - } -} -public interface I3 -{ - public sealed int this[int x] - { + } set - { - System.Console.WriteLine(""set_P3""); - } + { + System.Console.WriteLine(""set_P1""); + } } } -public interface I4 -{ - public sealed int this[int x] - { - get => GetP4(); - } +"; - private int GetP4() - { - System.Console.WriteLine(""get_P4""); - return 0; - } -} -public interface I5 -{ - public sealed int this[int x] - { - get => GetP5(); - set => System.Console.WriteLine(""set_P5""); - } + ValidatePropertyModifiers_11_02(source1, source2, + // (2,15): error CS8504: 'Test1' does not implement interface member 'I1.this[int].set'. 'Test1.this[int].set' cannot implicitly implement a non-public member. + // class Test1 : I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test1", "I1.this[int].set", "Test1.this[int].set").WithLocation(2, 15) + ); + } - private int GetP5() - { - System.Console.WriteLine(""get_P5""); - return 0; - } -} -public interface I6 + [Fact] + public void IndexerModifiers_23_53() + { + var source1 = +@" +public interface I1 { - public sealed int this[int x] - { - set => System.Console.WriteLine(""set_P6""); - } + abstract int this[int x] {get; internal set;} } -public interface I7 -{ - public sealed int this[int x] => GetP7(); - private int GetP7() - { - System.Console.WriteLine(""get_P7""); - return 0; - } +public class TestHelper +{ + public static void CallP1(I1 x) {x[0] = x[0];} } +"; + var source2 = +@" class Test1 : I1 { static void Main() { - I1 i1 = new Test1(); - var x = i1[0]; - I2 i2 = new Test2(); - i2[0] = i2[0]; - I3 i3 = new Test3(); - i3[0] = x; - I4 i4 = new Test4(); - x = i4[0]; - I5 i5 = new Test5(); - i5[0] = i5[0]; - I6 i6 = new Test6(); - i6[0] = x; - I7 i7 = new Test7(); - x = i7[0]; + TestHelper.CallP1(new Test1()); } - public int this[int x] => throw null; -} -class Test2 : I2 -{ - public int this[int x] + int I1.this[int x] { - get => throw null; - set => throw null; + get + { + System.Console.WriteLine(""get_P1""); + return 0; + } + set + { + System.Console.WriteLine(""set_P1""); + } } } -class Test3 : I3 +"; + + ValidatePropertyModifiers_11_03(source1, source2, + // (9,12): error CS0122: 'I1.this[int].set' is inaccessible due to its protection level + // int I1.this[int x] + Diagnostic(ErrorCode.ERR_BadAccess, "this").WithArguments("I1.this[int].set").WithLocation(9, 12) + ); + } + + [Fact] + public void IndexerModifiers_23_54() + { + var source1 = +@" +public interface I1 { - public int this[int x] - { - set => throw null; - } + abstract int this[int x] {get; internal set;} } -class Test4 : I4 + +public class TestHelper { - public int this[int x] + public static void CallP1(I1 x) {x[0] = x[0];} +} + +public class Test2 : I1 +{ + int I1.this[int x] { - get => throw null; + get + { + System.Console.WriteLine(""Test2.get_P1""); + return 0; + } + set + { + System.Console.WriteLine(""Test2.set_P1""); + } } } -class Test5 : I5 + +"; + + var source2 = +@" +class Test1 : Test2, I1 { - public int this[int x] + static void Main() { - get => throw null; - set => throw null; + TestHelper.CallP1(new Test1()); } -} -class Test6 : I6 -{ + public int this[int x] { - set => throw null; + get + { + System.Console.WriteLine(""Test1.get_P1""); + return 0; + } + set + { + System.Console.WriteLine(""Test1.set_P1""); + } } } -class Test7 : I7 -{ - public int this[int x] => throw null; -} "; - ValidatePropertyModifiers_13(source1); + ValidatePropertyModifiers_11_02(source1, source2, + // (2,22): error CS8504: 'Test1' does not implement interface member 'I1.this[int].set'. 'Test1.this[int].set' cannot implicitly implement a non-public member. + // class Test1 : Test2, I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test1", "I1.this[int].set", "Test1.this[int].set").WithLocation(2, 22) + ); } [Fact] - public void AccessModifiers_14() + public void IndexerModifiers_23_55() { var source1 = @" public interface I1 { - public sealed int this[int x] {get;} = 0; + abstract int this[int x] {get; internal set;} } -public interface I2 + +public class TestHelper { - abstract sealed int this[int x] {get;} + public static void CallP1(I1 x) {x[0] = x[0];} } -public interface I3 + +public class Test2 : I1 { - virtual sealed int this[int x] + int I1.this[int x] { - set {} + get + { + System.Console.WriteLine(""Test2.get_P1""); + return 0; + } + set + { + System.Console.WriteLine(""Test2.set_P1""); + } } } -class Test1 : I1, I2, I3 +"; + + var source2 = +@" +class Test1 : Test2, I1 { - int I1.this[int x] { get => throw null; } - int I2.this[int x] { get => throw null; } - int I3.this[int x] { set => throw null; } -} + static void Main() + { + TestHelper.CallP1(new Test1()); + } -class Test2 : I1, I2, I3 -{} + public virtual int this[int x] + { + get + { + System.Console.WriteLine(""Test1.get_P1""); + return 0; + } + set + { + System.Console.WriteLine(""Test1.set_P1""); + } + } +} "; - ValidatePropertyModifiers_14(source1, - // (4,42): error CS1519: Invalid token '=' in class, struct, or interface member declaration - // public sealed int this[int x] {get;} = 0; - Diagnostic(ErrorCode.ERR_InvalidMemberDecl, "=").WithArguments("=").WithLocation(4, 42), - // (4,36): error CS0501: 'I1.this[int].get' must declare a body because it is not marked abstract, extern, or partial - // public sealed int this[int x] {get;} = 0; - Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "get").WithArguments("I1.this[int].get").WithLocation(4, 36), - // (8,25): error CS0238: 'I2.this[int]' cannot be sealed because it is not an override - // abstract sealed int this[int x] {get;} - Diagnostic(ErrorCode.ERR_SealedNonOverride, "this").WithArguments("I2.this[int]").WithLocation(8, 25), - // (12,24): error CS0238: 'I3.this[int]' cannot be sealed because it is not an override - // virtual sealed int this[int x] - Diagnostic(ErrorCode.ERR_SealedNonOverride, "this").WithArguments("I3.this[int]").WithLocation(12, 24), - // (20,12): error CS0539: 'Test1.this[int]' in explicit interface declaration is not found among members of the interface that can be implemented - // int I1.this[int x] { get => throw null; } - Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "this").WithArguments("Test1.this[int]").WithLocation(20, 12), - // (25,19): error CS0535: 'Test2' does not implement interface member 'I2.this[int]' - // class Test2 : I1, I2, I3 - Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I2").WithArguments("Test2", "I2.this[int]") + + ValidatePropertyModifiers_11_02(source1, source2, + // (2,22): error CS8504: 'Test1' does not implement interface member 'I1.this[int].set'. 'Test1.this[int].set' cannot implicitly implement a non-public member. + // class Test1 : Test2, I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test1", "I1.this[int].set", "Test1.this[int].set").WithLocation(2, 22) ); } [Fact] - public void IndexerModifiers_15() + public void IndexerModifiers_23_56() { var source1 = @" -public interface I0 -{ - abstract virtual int this[int x] { get; set; } -} public interface I1 { - abstract virtual int this[int x] { get { throw null; } } -} -public interface I2 -{ - virtual abstract int this[int x] - { - get { throw null; } - set { throw null; } - } -} -public interface I3 -{ - abstract virtual int this[int x] { set { throw null; } } -} -public interface I4 -{ - abstract virtual int this[int x] { get => throw null; } -} -public interface I5 -{ - abstract virtual int this[int x] - { - get => throw null; - set => throw null; - } -} -public interface I6 -{ - abstract virtual int this[int x] { set => throw null; } -} -public interface I7 -{ - abstract virtual int this[int x] => throw null; + abstract int this[int x] {get; internal set;} } -public interface I8 + +public class TestHelper { - abstract virtual int this[int x] {get;} = 0; + public static void CallP1(I1 x) {x[0] = x[0];} } -class Test1 : I0, I1, I2, I3, I4, I5, I6, I7, I8 +public class Test2 : I1 { - int I0.this[int x] - { - get { throw null; } - set { throw null; } - } int I1.this[int x] { - get { throw null; } - } - int I2.this[int x] - { - get { throw null; } - set { throw null; } - } - int I3.this[int x] - { - set { throw null; } - } - int I4.this[int x] - { - get { throw null; } - } - int I5.this[int x] - { - get { throw null; } - set { throw null; } - } - int I6.this[int x] - { - set { throw null; } - } - int I7.this[int x] - { - get { throw null; } - } - int I8.this[int x] - { - get { throw null; } - } -} - -class Test2 : I0, I1, I2, I3, I4, I5, I6, I7, I8 -{} -"; - ValidatePropertyModifiers_15(source1, - // (44,45): error CS1519: Invalid token '=' in class, struct, or interface member declaration - // abstract virtual int this[int x] {get;} = 0; - Diagnostic(ErrorCode.ERR_InvalidMemberDecl, "=").WithArguments("=").WithLocation(44, 45), - // (4,26): error CS0503: The abstract method 'I0.this[int]' cannot be marked virtual - // abstract virtual int this[int x] { get; set; } - Diagnostic(ErrorCode.ERR_AbstractNotVirtual, "this").WithArguments("I0.this[int]").WithLocation(4, 26), - // (8,26): error CS0503: The abstract method 'I1.this[int]' cannot be marked virtual - // abstract virtual int this[int x] { get { throw null; } } - Diagnostic(ErrorCode.ERR_AbstractNotVirtual, "this").WithArguments("I1.this[int]").WithLocation(8, 26), - // (8,40): error CS0500: 'I1.this[int].get' cannot declare a body because it is marked abstract - // abstract virtual int this[int x] { get { throw null; } } - Diagnostic(ErrorCode.ERR_AbstractHasBody, "get").WithArguments("I1.this[int].get").WithLocation(8, 40), - // (12,26): error CS0503: The abstract method 'I2.this[int]' cannot be marked virtual - // virtual abstract int this[int x] - Diagnostic(ErrorCode.ERR_AbstractNotVirtual, "this").WithArguments("I2.this[int]").WithLocation(12, 26), - // (14,9): error CS0500: 'I2.this[int].get' cannot declare a body because it is marked abstract - // get { throw null; } - Diagnostic(ErrorCode.ERR_AbstractHasBody, "get").WithArguments("I2.this[int].get").WithLocation(14, 9), - // (15,9): error CS0500: 'I2.this[int].set' cannot declare a body because it is marked abstract - // set { throw null; } - Diagnostic(ErrorCode.ERR_AbstractHasBody, "set").WithArguments("I2.this[int].set").WithLocation(15, 9), - // (20,26): error CS0503: The abstract method 'I3.this[int]' cannot be marked virtual - // abstract virtual int this[int x] { set { throw null; } } - Diagnostic(ErrorCode.ERR_AbstractNotVirtual, "this").WithArguments("I3.this[int]").WithLocation(20, 26), - // (20,40): error CS0500: 'I3.this[int].set' cannot declare a body because it is marked abstract - // abstract virtual int this[int x] { set { throw null; } } - Diagnostic(ErrorCode.ERR_AbstractHasBody, "set").WithArguments("I3.this[int].set").WithLocation(20, 40), - // (24,26): error CS0503: The abstract method 'I4.this[int]' cannot be marked virtual - // abstract virtual int this[int x] { get => throw null; } - Diagnostic(ErrorCode.ERR_AbstractNotVirtual, "this").WithArguments("I4.this[int]").WithLocation(24, 26), - // (24,40): error CS0500: 'I4.this[int].get' cannot declare a body because it is marked abstract - // abstract virtual int this[int x] { get => throw null; } - Diagnostic(ErrorCode.ERR_AbstractHasBody, "get").WithArguments("I4.this[int].get").WithLocation(24, 40), - // (28,26): error CS0503: The abstract method 'I5.this[int]' cannot be marked virtual - // abstract virtual int this[int x] - Diagnostic(ErrorCode.ERR_AbstractNotVirtual, "this").WithArguments("I5.this[int]").WithLocation(28, 26), - // (30,9): error CS0500: 'I5.this[int].get' cannot declare a body because it is marked abstract - // get => throw null; - Diagnostic(ErrorCode.ERR_AbstractHasBody, "get").WithArguments("I5.this[int].get"), - // (31,9): error CS0500: 'I5.this[int].set' cannot declare a body because it is marked abstract - // set => throw null; - Diagnostic(ErrorCode.ERR_AbstractHasBody, "set").WithArguments("I5.this[int].set").WithLocation(31, 9), - // (36,26): error CS0503: The abstract method 'I6.this[int]' cannot be marked virtual - // abstract virtual int this[int x] { set => throw null; } - Diagnostic(ErrorCode.ERR_AbstractNotVirtual, "this").WithArguments("I6.this[int]").WithLocation(36, 26), - // (36,40): error CS0500: 'I6.this[int].set' cannot declare a body because it is marked abstract - // abstract virtual int this[int x] { set => throw null; } - Diagnostic(ErrorCode.ERR_AbstractHasBody, "set").WithArguments("I6.this[int].set").WithLocation(36, 40), - // (40,26): error CS0503: The abstract method 'I7.this[int]' cannot be marked virtual - // abstract virtual int this[int x] => throw null; - Diagnostic(ErrorCode.ERR_AbstractNotVirtual, "this").WithArguments("I7.this[int]").WithLocation(40, 26), - // (40,41): error CS0500: 'I7.this[int].get' cannot declare a body because it is marked abstract - // abstract virtual int this[int x] => throw null; - Diagnostic(ErrorCode.ERR_AbstractHasBody, "throw null").WithArguments("I7.this[int].get").WithLocation(40, 41), - // (44,26): error CS0503: The abstract method 'I8.this[int]' cannot be marked virtual - // abstract virtual int this[int x] {get;} = 0; - Diagnostic(ErrorCode.ERR_AbstractNotVirtual, "this").WithArguments("I8.this[int]").WithLocation(44, 26), - // (90,15): error CS0535: 'Test2' does not implement interface member 'I0.this[int]' - // class Test2 : I0, I1, I2, I3, I4, I5, I6, I7, I8 - Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I0").WithArguments("Test2", "I0.this[int]"), - // (90,19): error CS0535: 'Test2' does not implement interface member 'I1.this[int]' - // class Test2 : I0, I1, I2, I3, I4, I5, I6, I7, I8 - Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test2", "I1.this[int]"), - // (90,23): error CS0535: 'Test2' does not implement interface member 'I2.this[int]' - // class Test2 : I0, I1, I2, I3, I4, I5, I6, I7, I8 - Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I2").WithArguments("Test2", "I2.this[int]"), - // (90,27): error CS0535: 'Test2' does not implement interface member 'I3.this[int]' - // class Test2 : I0, I1, I2, I3, I4, I5, I6, I7, I8 - Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I3").WithArguments("Test2", "I3.this[int]"), - // (90,31): error CS0535: 'Test2' does not implement interface member 'I4.this[int]' - // class Test2 : I0, I1, I2, I3, I4, I5, I6, I7, I8 - Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I4").WithArguments("Test2", "I4.this[int]"), - // (90,35): error CS0535: 'Test2' does not implement interface member 'I5.this[int]' - // class Test2 : I0, I1, I2, I3, I4, I5, I6, I7, I8 - Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I5").WithArguments("Test2", "I5.this[int]"), - // (90,39): error CS0535: 'Test2' does not implement interface member 'I6.this[int]' - // class Test2 : I0, I1, I2, I3, I4, I5, I6, I7, I8 - Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I6").WithArguments("Test2", "I6.this[int]"), - // (90,43): error CS0535: 'Test2' does not implement interface member 'I7.this[int]' - // class Test2 : I0, I1, I2, I3, I4, I5, I6, I7, I8 - Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I7").WithArguments("Test2", "I7.this[int]"), - // (90,47): error CS0535: 'Test2' does not implement interface member 'I8.this[int]' - // class Test2 : I0, I1, I2, I3, I4, I5, I6, I7, I8 - Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I8").WithArguments("Test2", "I8.this[int]") + get + { + System.Console.WriteLine(""Test2.get_P1""); + return 0; + } + set + { + System.Console.WriteLine(""Test2.set_P1""); + } + } +} + +"; + + var source2 = +@"abstract +class Test1 : Test2, I1 +{ + static void Main() + { + TestHelper.CallP1(new Test3()); + } + + public abstract int this[int x] {get; set;} +} + +class Test3 : Test1 +{ + public override int this[int x] + { + get + { + System.Console.WriteLine(""Test3.get_P1""); + return 0; + } + set + { + System.Console.WriteLine(""Test3.set_P1""); + } + } +} +"; + + ValidatePropertyModifiers_11_02(source1, source2, + // (2,22): error CS8504: 'Test1' does not implement interface member 'I1.this[int].set'. 'Test1.this[int].set' cannot implicitly implement a non-public member. + // class Test1 : Test2, I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test1", "I1.this[int].set", "Test1.this[int].set").WithLocation(2, 22) ); } [Fact] - public void IndexerModifiers_16() + public void IndexerModifiers_23_57() { var source1 = @" public interface I1 { - extern int this[int x] {get;} + abstract int this[int x] {get; internal set;} +} + +public class TestHelper +{ + public static void CallP1(I1 x) {x[0] = x[0];} +} + +public class Test2 : I1 +{ + int I1.this[int x] + { + get + { + System.Console.WriteLine(""Test2.get_P1""); + return 0; + } + set + { + System.Console.WriteLine(""Test2.set_P1""); + } + } +} + +"; + + var source2 = +@" +class Test1 : Test2, I1, I2 +{ + static void Main() + { + TestHelper.CallP1(new Test1()); + } + + public int this[int x] + { + get + { + System.Console.WriteLine(""Test1.get_P1""); + return 0; + } + set + { + System.Console.WriteLine(""Test1.set_P1""); + } + } } + public interface I2 { - virtual extern int this[int x] {set;} + int this[int x] {get; set;} } -public interface I4 +"; + + ValidatePropertyModifiers_11_02(source1, source2, + // (2,22): error CS8504: 'Test1' does not implement interface member 'I1.this[int].set'. 'Test1.this[int].set' cannot implicitly implement a non-public member. + // class Test1 : Test2, I1, I2 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test1", "I1.this[int].set", "Test1.this[int].set").WithLocation(2, 22) + ); + } + + [Fact] + public void IndexerModifiers_23_58() + { + var source1 = +@" +public interface I1 { - private extern int this[int x] {get;} + abstract int this[int x] {get; internal set;} } -public interface I5 + +public class TestHelper { - extern sealed int this[int x] {set;} + public static void CallP1(I1 x) {x[0] = x[0];} } -class Test1 : I1, I2, I4, I5 +public class Test2 : I1 { + int I1.this[int x] + { + get + { + System.Console.WriteLine(""Test2.get_P1""); + return 0; + } + set + { + System.Console.WriteLine(""Test2.set_P1""); + } + } } -class Test2 : I1, I2, I4, I5 +"; + + var source2 = +@" +class Test1 : Test2, I1 { - int I1.this[int x] => 0; - int I2.this[int x] { set {} } + static void Main() + { + TestHelper.CallP1(new Test1()); + } + + public virtual long this[int x] + { + get + { + System.Console.WriteLine(""Test1.get_P1""); + return 0; + } + set + { + System.Console.WriteLine(""Test1.set_P1""); + } + } } "; - ValidatePropertyModifiers_16(source1); + + ValidatePropertyModifiers_11_08(source1, source2); } [Fact] - public void IndexerModifiers_17() + public void IndexerModifiers_23_59() { var source1 = @" public interface I1 { - abstract extern int this[int x] {get;} + abstract int this[int x] {get; internal set;} } -public interface I2 + +public class TestHelper { - extern int this[int x] => 0; + public static void CallP1(I1 x) {x[0] = x[0];} } -public interface I3 +"; + + var source2 = +@" +class Test1 : I1 { - static extern int this[int x] {get => 0; set => throw null;} + static void Main() + { + TestHelper.CallP1(new Test1()); + } + + public virtual long this[int x] + { + get + { + System.Console.WriteLine(""Test1.get_P1""); + return 0; + } + set + { + System.Console.WriteLine(""Test1.set_P1""); + } + } } -public interface I4 +"; + + ValidatePropertyModifiers_11_09(source1, source2, + // (2,15): error CS0535: 'Test1' does not implement interface member 'I1.this[int]' + // class Test1 : I1 + Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test1", "I1.this[int]").WithLocation(2, 15) + ); + } + + [Fact] + public void IndexerModifiers_23_60() + { + var source1 = +@" +public interface I1 { - private extern int this[int x] { get {throw null;} set {throw null;}} + abstract int this[int x] {get; internal set;} } -public interface I5 +"; + + var source2 = +@" +public class Test2 : I1 +{ + public int this[int x] + { + get + { + return 0; + } + set {} + } +} +class Test1 : Test2, I1 { - extern sealed int this[int x] {get;} = 0; } +"; -class Test1 : I1, I2, I3, I4, I5 + ValidatePropertyModifiers_11_10(source1, source2, + // (2,22): error CS8504: 'Test2' does not implement interface member 'I1.this[int].set'. 'Test2.this[int].set' cannot implicitly implement a non-public member. + // public class Test2 : I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test2", "I1.this[int].set", "Test2.this[int].set").WithLocation(2, 22) + ); + } + + [Fact] + public void IndexerModifiers_23_61() + { + var source1 = +@" +public interface I1 +{ + abstract int this[int x] {get; internal set;} +} +public class Test2 : I1 { + public int this[int x] + { + get + { + return 0; + } + set {} + } } +"; -class Test2 : I1, I2, I3, I4, I5 + var source2 = +@" +class Test1 : Test2, I1 { - int I1.this[int x] => 0; - int I2.this[int x] => 0; - int I3.this[int x] { get => 0; set => throw null;} - int I4.this[int x] { get => 0; set => throw null;} - int I5.this[int x] => 0; } "; - ValidatePropertyModifiers_17(source1, - // (20,42): error CS1519: Invalid token '=' in class, struct, or interface member declaration - // extern sealed int this[int x] {get;} = 0; - Diagnostic(ErrorCode.ERR_InvalidMemberDecl, "=").WithArguments("=").WithLocation(20, 42), - // (4,25): error CS0180: 'I1.this[int]' cannot be both extern and abstract - // abstract extern int this[int x] {get;} - Diagnostic(ErrorCode.ERR_AbstractAndExtern, "this").WithArguments("I1.this[int]").WithLocation(4, 25), - // (8,31): error CS0179: 'I2.this[int].get' cannot be extern and declare a body - // extern int this[int x] => 0; - Diagnostic(ErrorCode.ERR_ExternHasBody, "0").WithArguments("I2.this[int].get").WithLocation(8, 31), - // (12,23): error CS0106: The modifier 'static' is not valid for this item - // static extern int this[int x] {get => 0; set => throw null;} - Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("static").WithLocation(12, 23), - // (12,36): error CS0179: 'I3.this[int].get' cannot be extern and declare a body - // static extern int this[int x] {get => 0; set => throw null;} - Diagnostic(ErrorCode.ERR_ExternHasBody, "get").WithArguments("I3.this[int].get").WithLocation(12, 36), - // (12,46): error CS0179: 'I3.this[int].set' cannot be extern and declare a body - // static extern int this[int x] {get => 0; set => throw null;} - Diagnostic(ErrorCode.ERR_ExternHasBody, "set").WithArguments("I3.this[int].set").WithLocation(12, 46), - // (16,38): error CS0179: 'I4.this[int].get' cannot be extern and declare a body - // private extern int this[int x] { get {throw null;} set {throw null;}} - Diagnostic(ErrorCode.ERR_ExternHasBody, "get").WithArguments("I4.this[int].get").WithLocation(16, 38), - // (16,56): error CS0179: 'I4.this[int].set' cannot be extern and declare a body - // private extern int this[int x] { get {throw null;} set {throw null;}} - Diagnostic(ErrorCode.ERR_ExternHasBody, "set").WithArguments("I4.this[int].set").WithLocation(16, 56), - // (23,15): error CS0535: 'Test1' does not implement interface member 'I1.this[int]' - // class Test1 : I1, I2, I3, I4, I5 - Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test1", "I1.this[int]"), - // (32,12): error CS0539: 'Test2.this[int]' in explicit interface declaration is not found among members of the interface that can be implemented - // int I4.this[int x] { get => 0; set => throw null;} - Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "this").WithArguments("Test2.this[int]").WithLocation(32, 12), - // (33,12): error CS0539: 'Test2.this[int]' in explicit interface declaration is not found among members of the interface that can be implemented - // int I5.this[int x] => 0; - Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "this").WithArguments("Test2.this[int]").WithLocation(33, 12), - // (20,36): warning CS0626: Method, operator, or accessor 'I5.this[int].get' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. - // extern sealed int this[int x] {get;} = 0; - Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "get").WithArguments("I5.this[int].get").WithLocation(20, 36) + + ValidatePropertyModifiers_11_11(source1, source2, + // (6,22): error CS8504: 'Test2' does not implement interface member 'I1.this[int].set'. 'Test2.this[int].set' cannot implicitly implement a non-public member. + // public class Test2 : I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test2", "I1.this[int].set", "Test2.this[int].set").WithLocation(6, 22) ); } [Fact] - public void IndexerModifiers_18() + public void IndexerModifiers_24() + { + var source1 = +@" +public interface I1 +{ + int this[int x] + { + get + { + System.Console.WriteLine(""get_P1""); + return 0; + } + internal set + { + System.Console.WriteLine(""set_P1""); + } + } + + void M2() {this[0] = this[1];} +} +"; + + var source2 = +@" +class Test1 : I1 +{ + static void Main() + { + I1 x = new Test1(); + x.M2(); + } +} +"; + ValidatePropertyModifiers_24(source1, source2); + } + + [Fact] + public void IndexerModifiers_25() { var source1 = @" public interface I1 { - abstract int this[int x] {get => 0; set => throw null;} + int this[int x] { private get => throw null; set => throw null; } } public interface I2 { - abstract private int this[int x] => 0; + int this[int x] { internal get => throw null; set => throw null; } } public interface I3 { - static extern int this[int x] {get; set;} + public int this[int x] { get => throw null; private set => throw null; } } public interface I4 { - abstract static int this[int x] { get {throw null;} set {throw null;}} + int this[int x] { get => throw null; internal set => throw null; } } -public interface I5 + +public class Test1 : I1, I2, I3, I4 { - override sealed int this[int x] {get;} = 0; + static void Main() + { + int x; + I1 i1 = new Test1(); + I2 i2 = new Test1(); + I3 i3 = new Test1(); + I4 i4 = new Test1(); + + x = i1[0]; + i1[0] = x; + x = i2[0]; + i2[0] = x; + x = i3[0]; + i3[0] = x; + x = i4[0]; + i4[0] = x; + } } +"; + var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All), + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation1.VerifyDiagnostics( + // (29,13): error CS0271: The property or indexer 'I1.this[int]' cannot be used in this context because the get accessor is inaccessible + // x = i1[0]; + Diagnostic(ErrorCode.ERR_InaccessibleGetter, "i1[0]").WithArguments("I1.this[int]").WithLocation(29, 13), + // (34,9): error CS0272: The property or indexer 'I3.this[int]' cannot be used in this context because the set accessor is inaccessible + // i3[0] = x; + Diagnostic(ErrorCode.ERR_InaccessibleSetter, "i3[0]").WithArguments("I3.this[int]").WithLocation(34, 9) + ); -class Test1 : I1, I2, I3, I4, I5 + var source2 = +@" +class Test2 { + static void Main() + { + int x; + I1 i1 = new Test1(); + I2 i2 = new Test1(); + I3 i3 = new Test1(); + I4 i4 = new Test1(); + + x = i1[0]; + i1[0] = x; + x = i2[0]; + i2[0] = x; + x = i3[0]; + i3[0] = x; + x = i4[0]; + i4[0] = x; + } } +"; + var compilation2 = CreateStandardCompilation(source2, new[] { compilation1.ToMetadataReference() }, + options: TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All), + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation2.VerifyDiagnostics( + // (12,13): error CS0271: The property or indexer 'I1.this[int]' cannot be used in this context because the get accessor is inaccessible + // x = i1[0]; + Diagnostic(ErrorCode.ERR_InaccessibleGetter, "i1[0]").WithArguments("I1.this[int]").WithLocation(12, 13), + // (14,13): error CS0271: The property or indexer 'I2.this[int]' cannot be used in this context because the get accessor is inaccessible + // x = i2[0]; + Diagnostic(ErrorCode.ERR_InaccessibleGetter, "i2[0]").WithArguments("I2.this[int]").WithLocation(14, 13), + // (17,9): error CS0272: The property or indexer 'I3.this[int]' cannot be used in this context because the set accessor is inaccessible + // i3[0] = x; + Diagnostic(ErrorCode.ERR_InaccessibleSetter, "i3[0]").WithArguments("I3.this[int]").WithLocation(17, 9), + // (19,9): error CS0272: The property or indexer 'I4.this[int]' cannot be used in this context because the set accessor is inaccessible + // i4[0] = x; + Diagnostic(ErrorCode.ERR_InaccessibleSetter, "i4[0]").WithArguments("I4.this[int]").WithLocation(19, 9) + ); + } -class Test2 : I1, I2, I3, I4, I5 + [Fact] + public void IndexerModifiers_26() + { + var source1 = +@" +public interface I1 { - int I1.this[int x] { get => 0; set => throw null;} - int I2.this[int x] => 0; - int I3.this[int x] { get => 0; set => throw null;} - int I4.this[int x] { get => 0; set => throw null;} - int I5.this[int x] => 0; + abstract int this[sbyte x] { private get; set; } + abstract int this[byte x] { get; private set; } + abstract int this[short x] { internal get; } + int this[ushort x] {internal get;} = 0; + int this[int x] { internal get {throw null;} } + int this[uint x] { internal set {throw null;} } + int this[long x] { internal get => throw null; } + int this[ulong x] { internal set => throw null; } + int this[float x] { internal get {throw null;} private set {throw null;}} + int this[double x] { internal get => throw null; private set => throw null;} } "; - ValidatePropertyModifiers_18(source1, - // (20,44): error CS1519: Invalid token '=' in class, struct, or interface member declaration - // override sealed int this[int x] {get;} = 0; - Diagnostic(ErrorCode.ERR_InvalidMemberDecl, "=").WithArguments("=").WithLocation(20, 44), - // (4,31): error CS0500: 'I1.this[int].get' cannot declare a body because it is marked abstract - // abstract int this[int x] {get => 0; set => throw null;} - Diagnostic(ErrorCode.ERR_AbstractHasBody, "get").WithArguments("I1.this[int].get").WithLocation(4, 31), - // (4,41): error CS0500: 'I1.this[int].set' cannot declare a body because it is marked abstract - // abstract int this[int x] {get => 0; set => throw null;} - Diagnostic(ErrorCode.ERR_AbstractHasBody, "set").WithArguments("I1.this[int].set").WithLocation(4, 41), - // (8,26): error CS0621: 'I2.this[int]': virtual or abstract members cannot be private - // abstract private int this[int x] => 0; - Diagnostic(ErrorCode.ERR_VirtualPrivate, "this").WithArguments("I2.this[int]").WithLocation(8, 26), - // (8,41): error CS0500: 'I2.this[int].get' cannot declare a body because it is marked abstract - // abstract private int this[int x] => 0; - Diagnostic(ErrorCode.ERR_AbstractHasBody, "0").WithArguments("I2.this[int].get").WithLocation(8, 41), - // (12,23): error CS0106: The modifier 'static' is not valid for this item - // static extern int this[int x] {get; set;} - Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("static").WithLocation(12, 23), - // (16,25): error CS0106: The modifier 'static' is not valid for this item - // abstract static int this[int x] { get {throw null;} set {throw null;}} - Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("static").WithLocation(16, 25), - // (16,39): error CS0500: 'I4.this[int].get' cannot declare a body because it is marked abstract - // abstract static int this[int x] { get {throw null;} set {throw null;}} - Diagnostic(ErrorCode.ERR_AbstractHasBody, "get").WithArguments("I4.this[int].get").WithLocation(16, 39), - // (16,57): error CS0500: 'I4.this[int].set' cannot declare a body because it is marked abstract - // abstract static int this[int x] { get {throw null;} set {throw null;}} - Diagnostic(ErrorCode.ERR_AbstractHasBody, "set").WithArguments("I4.this[int].set").WithLocation(16, 57), - // (20,25): error CS0106: The modifier 'override' is not valid for this item - // override sealed int this[int x] {get;} = 0; - Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("override").WithLocation(20, 25), - // (20,38): error CS0501: 'I5.this[int].get' must declare a body because it is not marked abstract, extern, or partial - // override sealed int this[int x] {get;} = 0; - Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "get").WithArguments("I5.this[int].get").WithLocation(20, 38), - // (23,15): error CS0535: 'Test1' does not implement interface member 'I1.this[int]' - // class Test1 : I1, I2, I3, I4, I5 - Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test1", "I1.this[int]"), - // (23,19): error CS0535: 'Test1' does not implement interface member 'I2.this[int]' - // class Test1 : I1, I2, I3, I4, I5 - Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I2").WithArguments("Test1", "I2.this[int]"), - // (23,27): error CS0535: 'Test1' does not implement interface member 'I4.this[int]' - // class Test1 : I1, I2, I3, I4, I5 - Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I4").WithArguments("Test1", "I4.this[int]").WithLocation(23, 27), - // (33,12): error CS0539: 'Test2.this[int]' in explicit interface declaration is not found among members of the interface that can be implemented - // int I5.this[int x] => 0; - Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "this").WithArguments("Test2.this[int]").WithLocation(33, 12), - // (12,36): warning CS0626: Method, operator, or accessor 'I3.this[int].get' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. - // static extern int this[int x] {get; set;} - Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "get").WithArguments("I3.this[int].get").WithLocation(12, 36), - // (12,41): warning CS0626: Method, operator, or accessor 'I3.this[int].set' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. - // static extern int this[int x] {get; set;} - Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "set").WithArguments("I3.this[int].set").WithLocation(12, 41) + var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All), + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation1.VerifyDiagnostics( + // (7,40): error CS1519: Invalid token '=' in class, struct, or interface member declaration + // int this[ushort x] {internal get;} = 0; + Diagnostic(ErrorCode.ERR_InvalidMemberDecl, "=").WithArguments("=").WithLocation(7, 40), + // (4,42): error CS0442: 'I1.this[sbyte].get': abstract properties cannot have private accessors + // abstract int this[sbyte x] { private get; set; } + Diagnostic(ErrorCode.ERR_PrivateAbstractAccessor, "get").WithArguments("I1.this[sbyte].get").WithLocation(4, 42), + // (5,46): error CS0442: 'I1.this[byte].set': abstract properties cannot have private accessors + // abstract int this[byte x] { get; private set; } + Diagnostic(ErrorCode.ERR_PrivateAbstractAccessor, "set").WithArguments("I1.this[byte].set").WithLocation(5, 46), + // (6,18): error CS0276: 'I1.this[short]': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor + // abstract int this[short x] { internal get; } + Diagnostic(ErrorCode.ERR_AccessModMissingAccessor, "this").WithArguments("I1.this[short]").WithLocation(6, 18), + // (7,9): error CS0276: 'I1.this[ushort]': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor + // int this[ushort x] {internal get;} = 0; + Diagnostic(ErrorCode.ERR_AccessModMissingAccessor, "this").WithArguments("I1.this[ushort]").WithLocation(7, 9), + // (8,9): error CS0276: 'I1.this[int]': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor + // int this[int x] { internal get {throw null;} } + Diagnostic(ErrorCode.ERR_AccessModMissingAccessor, "this").WithArguments("I1.this[int]").WithLocation(8, 9), + // (9,9): error CS0276: 'I1.this[uint]': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor + // int this[uint x] { internal set {throw null;} } + Diagnostic(ErrorCode.ERR_AccessModMissingAccessor, "this").WithArguments("I1.this[uint]").WithLocation(9, 9), + // (10,9): error CS0276: 'I1.this[long]': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor + // int this[long x] { internal get => throw null; } + Diagnostic(ErrorCode.ERR_AccessModMissingAccessor, "this").WithArguments("I1.this[long]").WithLocation(10, 9), + // (11,9): error CS0276: 'I1.this[ulong]': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor + // int this[ulong x] { internal set => throw null; } + Diagnostic(ErrorCode.ERR_AccessModMissingAccessor, "this").WithArguments("I1.this[ulong]").WithLocation(11, 9), + // (12,9): error CS0274: Cannot specify accessibility modifiers for both accessors of the property or indexer 'I1.this[float]' + // int this[float x] { internal get {throw null;} private set {throw null;}} + Diagnostic(ErrorCode.ERR_DuplicatePropertyAccessMods, "this").WithArguments("I1.this[float]").WithLocation(12, 9), + // (13,9): error CS0274: Cannot specify accessibility modifiers for both accessors of the property or indexer 'I1.this[double]' + // int this[double x] { internal get => throw null; private set => throw null;} + Diagnostic(ErrorCode.ERR_DuplicatePropertyAccessMods, "this").WithArguments("I1.this[double]").WithLocation(13, 9) + ); + } + + [Fact] + public void IndexerModifiers_27() + { + var source1 = +@" +public interface I1 +{ + int this[short x] + { + private get {throw null;} + set {} + } + + int this[int x] + { + get {throw null;} + private set {} + } +} + +class Test1 : I1 +{ + int I1.this[short x] + { + get {throw null;} + set {} + } + + int I1.this[int x] + { + get {throw null;} + set {} + } +} + +class Test2 : I1 +{ + int I1.this[short x] + { + set {throw null;} + } + + int I1.this[int x] + { + get => throw null; + } +} +"; + var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All), + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + + // PROTOTYPE(DefaultInterfaceImplementation): Private accessor is never virtual (the behavior goes back to native compiler). + // So, should we complain about them at all, or shoudl we treat private accessors + // as not implementable and ignore them for the purpose of interface implementation? + compilation1.VerifyDiagnostics( + // (19,12): error CS0122: 'I1.this[short].get' is inaccessible due to its protection level + // int I1.this[short x] + Diagnostic(ErrorCode.ERR_BadAccess, "this").WithArguments("I1.this[short].get").WithLocation(19, 12), + // (25,12): error CS0122: 'I1.this[int].set' is inaccessible due to its protection level + // int I1.this[int x] + Diagnostic(ErrorCode.ERR_BadAccess, "this").WithArguments("I1.this[int].set").WithLocation(25, 12), + // (34,12): error CS0122: 'I1.this[short].get' is inaccessible due to its protection level + // int I1.this[short x] + Diagnostic(ErrorCode.ERR_BadAccess, "this").WithArguments("I1.this[short].get").WithLocation(34, 12), + // (34,12): error CS0551: Explicit interface implementation 'Test2.I1.this[short]' is missing accessor 'I1.this[short].get' + // int I1.this[short x] + Diagnostic(ErrorCode.ERR_ExplicitPropertyMissingAccessor, "this").WithArguments("Test2.I1.this[short]", "I1.this[short].get").WithLocation(34, 12), + // (39,12): error CS0122: 'I1.this[int].set' is inaccessible due to its protection level + // int I1.this[int x] + Diagnostic(ErrorCode.ERR_BadAccess, "this").WithArguments("I1.this[int].set").WithLocation(39, 12), + // (39,12): error CS0551: Explicit interface implementation 'Test2.I1.this[int]' is missing accessor 'I1.this[int].set' + // int I1.this[int x] + Diagnostic(ErrorCode.ERR_ExplicitPropertyMissingAccessor, "this").WithArguments("Test2.I1.this[int]", "I1.this[int].set").WithLocation(39, 12) ); } [Fact] - public void IndexerModifiers_19() + public void EventModifiers_01() { var source1 = @" - -public interface I2 {} - -public interface I01{ public int I2.this[int x] {get; set;} } -public interface I02{ protected int I2.this[int x] {get;} } -public interface I03{ protected internal int I2.this[int x] {set;} } -public interface I04{ internal int I2.this[int x] {get;} } -public interface I05{ private int I2.this[int x] {set;} } -public interface I06{ static int I2.this[int x] {get;} } -public interface I07{ virtual int I2.this[int x] {set;} } -public interface I08{ sealed int I2.this[int x] {get;} } -public interface I09{ override int I2.this[int x] {set;} } -public interface I10{ abstract int I2.this[int x] {get;} } -public interface I11{ extern int I2.this[int x] {get; set;} } - -public interface I12{ int I2.this[int x] { public get; set;} } -public interface I13{ int I2.this[int x] { get; protected set;} } -public interface I14{ int I2.this[int x] { protected internal get; set;} } -public interface I15{ int I2.this[int x] { get; internal set;} } -public interface I16{ int I2.this[int x] { private get; set;} } -public interface I17{ int I2.this[int x] { private get;} } +public interface I1 +{ + public event System.Action P01; + protected event System.Action P02 {add{}} + protected internal event System.Action P03 {remove{}} + internal event System.Action P04 {add{}} + private event System.Action P05 {remove{}} + static event System.Action P06 {add{}} + virtual event System.Action P07 {remove{}} + sealed event System.Action P08 {add{}} + override event System.Action P09 {remove{}} + abstract event System.Action P10 {add{}} + extern event System.Action P11 {add{} remove{}} + extern event System.Action P12 {add; remove;} + extern event System.Action P13; +} "; var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); - var expected = new[] + compilation1.GetDiagnostics().Where(d => d.Code != (int)ErrorCode.ERR_EventNeedsBothAccessors).Verify( + // (5,35): error CS0106: The modifier 'protected' is not valid for this item + // protected event System.Action P02 {add{}} + Diagnostic(ErrorCode.ERR_BadMemberFlag, "P02").WithArguments("protected").WithLocation(5, 35), + // (6,44): error CS0106: The modifier 'protected internal' is not valid for this item + // protected internal event System.Action P03 {remove{}} + Diagnostic(ErrorCode.ERR_BadMemberFlag, "P03").WithArguments("protected internal").WithLocation(6, 44), + // (12,34): error CS0106: The modifier 'override' is not valid for this item + // override event System.Action P09 {remove{}} + Diagnostic(ErrorCode.ERR_BadMemberFlag, "P09").WithArguments("override").WithLocation(12, 34), + // (13,39): error CS0500: 'I1.P10.add' cannot declare a body because it is marked abstract + // abstract event System.Action P10 {add{}} + Diagnostic(ErrorCode.ERR_AbstractHasBody, "add").WithArguments("I1.P10.add").WithLocation(13, 39), + // (14,37): error CS0179: 'I1.P11.add' cannot be extern and declare a body + // extern event System.Action P11 {add{} remove{}} + Diagnostic(ErrorCode.ERR_ExternHasBody, "add").WithArguments("I1.P11.add").WithLocation(14, 37), + // (14,43): error CS0179: 'I1.P11.remove' cannot be extern and declare a body + // extern event System.Action P11 {add{} remove{}} + Diagnostic(ErrorCode.ERR_ExternHasBody, "remove").WithArguments("I1.P11.remove").WithLocation(14, 43), + // (15,37): warning CS0626: Method, operator, or accessor 'I1.P12.add' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. + // extern event System.Action P12 {add; remove;} + Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "add").WithArguments("I1.P12.add").WithLocation(15, 37), + // (15,40): error CS0073: An add or remove accessor must have a body + // extern event System.Action P12 {add; remove;} + Diagnostic(ErrorCode.ERR_AddRemoveMustHaveBody, ";").WithLocation(15, 40), + // (15,42): warning CS0626: Method, operator, or accessor 'I1.P12.remove' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. + // extern event System.Action P12 {add; remove;} + Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "remove").WithArguments("I1.P12.remove").WithLocation(15, 42), + // (15,48): error CS0073: An add or remove accessor must have a body + // extern event System.Action P12 {add; remove;} + Diagnostic(ErrorCode.ERR_AddRemoveMustHaveBody, ";").WithLocation(15, 48), + // (16,32): warning CS0626: Method, operator, or accessor 'I1.P13.add' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. + // extern event System.Action P13; + Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "P13").WithArguments("I1.P13.add").WithLocation(16, 32), + // (16,32): warning CS0626: Method, operator, or accessor 'I1.P13.remove' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. + // extern event System.Action P13; + Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "P13").WithArguments("I1.P13.remove").WithLocation(16, 32) + ); + + ValidateSymbolsEventModifiers_01(compilation1); + } + + private static void ValidateSymbolsEventModifiers_01(CSharpCompilation compilation1) + { + var i1 = compilation1.GetTypeByMetadataName("I1"); + var p01 = i1.GetMember("P01"); + + Assert.True(p01.IsAbstract); + Assert.False(p01.IsVirtual); + Assert.False(p01.IsSealed); + Assert.False(p01.IsStatic); + Assert.False(p01.IsExtern); + Assert.False(p01.IsOverride); + Assert.Equal(Accessibility.Public, p01.DeclaredAccessibility); + + VaidateP01Accessor(p01.AddMethod); + VaidateP01Accessor(p01.RemoveMethod); + void VaidateP01Accessor(MethodSymbol accessor) { - // (5,37): error CS0106: The modifier 'public' is not valid for this item - // public interface I01{ public int I2.this[int x] {get; set;} } - Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("public").WithLocation(5, 37), - // (5,37): error CS0541: 'I01.this[int]': explicit interface declaration can only be declared in a class or struct - // public interface I01{ public int I2.this[int x] {get; set;} } - Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "this").WithArguments("I01.this[int]").WithLocation(5, 37), - // (6,40): error CS0106: The modifier 'protected' is not valid for this item - // public interface I02{ protected int I2.this[int x] {get;} } - Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("protected").WithLocation(6, 40), - // (6,40): error CS0541: 'I02.this[int]': explicit interface declaration can only be declared in a class or struct - // public interface I02{ protected int I2.this[int x] {get;} } - Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "this").WithArguments("I02.this[int]").WithLocation(6, 40), - // (7,49): error CS0106: The modifier 'protected internal' is not valid for this item - // public interface I03{ protected internal int I2.this[int x] {set;} } - Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("protected internal").WithLocation(7, 49), - // (7,49): error CS0541: 'I03.this[int]': explicit interface declaration can only be declared in a class or struct - // public interface I03{ protected internal int I2.this[int x] {set;} } - Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "this").WithArguments("I03.this[int]").WithLocation(7, 49), - // (8,39): error CS0106: The modifier 'internal' is not valid for this item - // public interface I04{ internal int I2.this[int x] {get;} } - Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("internal").WithLocation(8, 39), - // (8,39): error CS0541: 'I04.this[int]': explicit interface declaration can only be declared in a class or struct - // public interface I04{ internal int I2.this[int x] {get;} } - Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "this").WithArguments("I04.this[int]").WithLocation(8, 39), - // (9,38): error CS0106: The modifier 'private' is not valid for this item - // public interface I05{ private int I2.this[int x] {set;} } - Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("private").WithLocation(9, 38), - // (9,38): error CS0541: 'I05.this[int]': explicit interface declaration can only be declared in a class or struct - // public interface I05{ private int I2.this[int x] {set;} } - Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "this").WithArguments("I05.this[int]").WithLocation(9, 38), - // (10,37): error CS0106: The modifier 'static' is not valid for this item - // public interface I06{ static int I2.this[int x] {get;} } - Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("static").WithLocation(10, 37), - // (10,37): error CS0541: 'I06.this[int]': explicit interface declaration can only be declared in a class or struct - // public interface I06{ static int I2.this[int x] {get;} } - Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "this").WithArguments("I06.this[int]").WithLocation(10, 37), - // (11,38): error CS0106: The modifier 'virtual' is not valid for this item - // public interface I07{ virtual int I2.this[int x] {set;} } - Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("virtual").WithLocation(11, 38), - // (11,38): error CS0541: 'I07.this[int]': explicit interface declaration can only be declared in a class or struct - // public interface I07{ virtual int I2.this[int x] {set;} } - Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "this").WithArguments("I07.this[int]").WithLocation(11, 38), - // (12,37): error CS0106: The modifier 'sealed' is not valid for this item - // public interface I08{ sealed int I2.this[int x] {get;} } - Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("sealed").WithLocation(12, 37), - // (12,37): error CS0541: 'I08.this[int]': explicit interface declaration can only be declared in a class or struct - // public interface I08{ sealed int I2.this[int x] {get;} } - Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "this").WithArguments("I08.this[int]").WithLocation(12, 37), - // (13,39): error CS0106: The modifier 'override' is not valid for this item - // public interface I09{ override int I2.this[int x] {set;} } - Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("override").WithLocation(13, 39), - // (13,39): error CS0541: 'I09.this[int]': explicit interface declaration can only be declared in a class or struct - // public interface I09{ override int I2.this[int x] {set;} } - Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "this").WithArguments("I09.this[int]").WithLocation(13, 39), - // (14,39): error CS0106: The modifier 'abstract' is not valid for this item - // public interface I10{ abstract int I2.this[int x] {get;} } - Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("abstract").WithLocation(14, 39), - // (14,39): error CS0541: 'I10.this[int]': explicit interface declaration can only be declared in a class or struct - // public interface I10{ abstract int I2.this[int x] {get;} } - Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "this").WithArguments("I10.this[int]").WithLocation(14, 39), - // (15,37): error CS0106: The modifier 'extern' is not valid for this item - // public interface I11{ extern int I2.this[int x] {get; set;} } - Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("extern").WithLocation(15, 37), - // (15,37): error CS0541: 'I11.this[int]': explicit interface declaration can only be declared in a class or struct - // public interface I11{ extern int I2.this[int x] {get; set;} } - Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "this").WithArguments("I11.this[int]").WithLocation(15, 37), - // (17,30): error CS0541: 'I12.this[int]': explicit interface declaration can only be declared in a class or struct - // public interface I12{ int I2.this[int x] { public get; set;} } - Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "this").WithArguments("I12.this[int]").WithLocation(17, 30), - // (17,51): error CS0106: The modifier 'public' is not valid for this item - // public interface I12{ int I2.this[int x] { public get; set;} } - Diagnostic(ErrorCode.ERR_BadMemberFlag, "get").WithArguments("public").WithLocation(17, 51), - // (18,30): error CS0541: 'I13.this[int]': explicit interface declaration can only be declared in a class or struct - // public interface I13{ int I2.this[int x] { get; protected set;} } - Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "this").WithArguments("I13.this[int]").WithLocation(18, 30), - // (18,59): error CS0106: The modifier 'protected' is not valid for this item - // public interface I13{ int I2.this[int x] { get; protected set;} } - Diagnostic(ErrorCode.ERR_BadMemberFlag, "set").WithArguments("protected").WithLocation(18, 59), - // (19,30): error CS0541: 'I14.this[int]': explicit interface declaration can only be declared in a class or struct - // public interface I14{ int I2.this[int x] { protected internal get; set;} } - Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "this").WithArguments("I14.this[int]").WithLocation(19, 30), - // (19,63): error CS0106: The modifier 'protected internal' is not valid for this item - // public interface I14{ int I2.this[int x] { protected internal get; set;} } - Diagnostic(ErrorCode.ERR_BadMemberFlag, "get").WithArguments("protected internal").WithLocation(19, 63), - // (20,30): error CS0541: 'I15.this[int]': explicit interface declaration can only be declared in a class or struct - // public interface I15{ int I2.this[int x] { get; internal set;} } - Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "this").WithArguments("I15.this[int]").WithLocation(20, 30), - // (20,58): error CS0106: The modifier 'internal' is not valid for this item - // public interface I15{ int I2.this[int x] { get; internal set;} } - Diagnostic(ErrorCode.ERR_BadMemberFlag, "set").WithArguments("internal").WithLocation(20, 58), - // (21,30): error CS0541: 'I16.this[int]': explicit interface declaration can only be declared in a class or struct - // public interface I16{ int I2.this[int x] { private get; set;} } - Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "this").WithArguments("I16.this[int]").WithLocation(21, 30), - // (21,52): error CS0106: The modifier 'private' is not valid for this item - // public interface I16{ int I2.this[int x] { private get; set;} } - Diagnostic(ErrorCode.ERR_BadMemberFlag, "get").WithArguments("private").WithLocation(21, 52), - // (22,30): error CS0541: 'I17.this[int]': explicit interface declaration can only be declared in a class or struct - // public interface I17{ int I2.this[int x] { private get;} } - Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "this").WithArguments("I17.this[int]").WithLocation(22, 30), - // (22,52): error CS0106: The modifier 'private' is not valid for this item - // public interface I17{ int I2.this[int x] { private get;} } - Diagnostic(ErrorCode.ERR_BadMemberFlag, "get").WithArguments("private").WithLocation(22, 52) - }; + Assert.True(accessor.IsAbstract); + Assert.False(accessor.IsVirtual); + Assert.True(accessor.IsMetadataVirtual()); + Assert.False(accessor.IsSealed); + Assert.False(accessor.IsStatic); + Assert.False(accessor.IsExtern); + Assert.False(accessor.IsAsync); + Assert.False(accessor.IsOverride); + Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); + } + + var p02 = i1.GetMember("P02"); + var p02get = p02.AddMethod; + + Assert.False(p02.IsAbstract); + Assert.True(p02.IsVirtual); + Assert.False(p02.IsSealed); + Assert.False(p02.IsStatic); + Assert.False(p02.IsExtern); + Assert.False(p02.IsOverride); + Assert.Equal(Accessibility.Public, p02.DeclaredAccessibility); + + Assert.False(p02get.IsAbstract); + Assert.True(p02get.IsVirtual); + Assert.True(p02get.IsMetadataVirtual()); + Assert.False(p02get.IsSealed); + Assert.False(p02get.IsStatic); + Assert.False(p02get.IsExtern); + Assert.False(p02get.IsAsync); + Assert.False(p02get.IsOverride); + Assert.Equal(Accessibility.Public, p02get.DeclaredAccessibility); - compilation1.VerifyDiagnostics(expected); + var p03 = i1.GetMember("P03"); + var p03set = p03.RemoveMethod; - ValidateSymbolsIndexerModifiers_19(compilation1); + Assert.False(p03.IsAbstract); + Assert.True(p03.IsVirtual); + Assert.False(p03.IsSealed); + Assert.False(p03.IsStatic); + Assert.False(p03.IsExtern); + Assert.False(p03.IsOverride); + Assert.Equal(Accessibility.Public, p03.DeclaredAccessibility); - var compilation2 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, - parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp7)); - Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); - compilation2.VerifyDiagnostics(expected); + Assert.False(p03set.IsAbstract); + Assert.True(p03set.IsVirtual); + Assert.True(p03set.IsMetadataVirtual()); + Assert.False(p03set.IsSealed); + Assert.False(p03set.IsStatic); + Assert.False(p03set.IsExtern); + Assert.False(p03set.IsAsync); + Assert.False(p03set.IsOverride); + Assert.Equal(Accessibility.Public, p03set.DeclaredAccessibility); - ValidateSymbolsIndexerModifiers_19(compilation2); - } + var p04 = i1.GetMember("P04"); + var p04get = p04.AddMethod; - private static void ValidateSymbolsIndexerModifiers_19(CSharpCompilation compilation1) - { + Assert.False(p04.IsAbstract); + Assert.True(p04.IsVirtual); + Assert.False(p04.IsSealed); + Assert.False(p04.IsStatic); + Assert.False(p04.IsExtern); + Assert.False(p04.IsOverride); + Assert.Equal(Accessibility.Internal, p04.DeclaredAccessibility); - for (int i = 1; i <= 17; i++) - { - var i1 = compilation1.GetTypeByMetadataName("I" + (i < 10 ? "0" : "") + i); - ValidateSymbolsPropertyModifiers_19(i1.GetMember("I2.this[]")); - } - } + Assert.False(p04get.IsAbstract); + Assert.True(p04get.IsVirtual); + Assert.True(p04get.IsMetadataVirtual()); + Assert.False(p04get.IsSealed); + Assert.False(p04get.IsStatic); + Assert.False(p04get.IsExtern); + Assert.False(p04get.IsAsync); + Assert.False(p04get.IsOverride); + Assert.Equal(Accessibility.Internal, p04get.DeclaredAccessibility); - [Fact] - public void IndexerModifiers_20() - { - var source1 = -@" -public interface I1 -{ - internal int this[int x] - { - get - { - System.Console.WriteLine(""get_P1""); - return 0; - } - set - { - System.Console.WriteLine(""set_P1""); - } - } + var p05 = i1.GetMember("P05"); + var p05set = p05.RemoveMethod; - void M2() {this[0] = this[0];} -} -"; + Assert.False(p05.IsAbstract); + Assert.False(p05.IsVirtual); + Assert.False(p05.IsSealed); + Assert.False(p05.IsStatic); + Assert.False(p05.IsExtern); + Assert.False(p05.IsOverride); + Assert.Equal(Accessibility.Private, p05.DeclaredAccessibility); - var source2 = -@" -class Test1 : I1 -{ - static void Main() - { - I1 x = new Test1(); - x.M2(); - } -} -"; + Assert.False(p05set.IsAbstract); + Assert.False(p05set.IsVirtual); + Assert.False(p05set.IsMetadataVirtual()); + Assert.False(p05set.IsSealed); + Assert.False(p05set.IsStatic); + Assert.False(p05set.IsExtern); + Assert.False(p05set.IsAsync); + Assert.False(p05set.IsOverride); + Assert.Equal(Accessibility.Private, p05set.DeclaredAccessibility); - ValidatePropertyModifiers_20(source1, source2); - } + var p06 = i1.GetMember("P06"); + var p06get = p06.AddMethod; - [Fact] - public void IndexerModifiers_21() - { - var source1 = -@" -public interface I1 -{ - private int this[int x] { get => throw null; set => throw null; } -} -public interface I2 -{ - internal int this[int x] { get => throw null; set => throw null; } -} -public interface I3 -{ - public int this[int x] { get => throw null; set => throw null; } -} -public interface I4 -{ - int this[int x] { get => throw null; set => throw null; } -} + Assert.False(p06.IsAbstract); + Assert.False(p06.IsVirtual); + Assert.False(p06.IsSealed); + Assert.True(p06.IsStatic); + Assert.False(p06.IsExtern); + Assert.False(p06.IsOverride); + Assert.Equal(Accessibility.Public, p06.DeclaredAccessibility); -class Test1 -{ - static void Test(I1 i1, I2 i2, I3 i3, I4 i4) - { - int x; - x = i1[0]; - i1[0] = x; - x = i2[0]; - i2[0] = x; - x = i3[0]; - i3[0] = x; - x = i4[0]; - i4[0] = x; - } -} -"; - var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, - parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); - Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); - compilation1.VerifyDiagnostics( - // (24,13): error CS0122: 'I1.this[int]' is inaccessible due to its protection level - // x = i1[0]; - Diagnostic(ErrorCode.ERR_BadAccess, "i1[0]").WithArguments("I1.this[int]").WithLocation(24, 13), - // (25,9): error CS0122: 'I1.this[int]' is inaccessible due to its protection level - // i1[0] = x; - Diagnostic(ErrorCode.ERR_BadAccess, "i1[0]").WithArguments("I1.this[int]").WithLocation(25, 9) - ); + Assert.False(p06get.IsAbstract); + Assert.False(p06get.IsVirtual); + Assert.False(p06get.IsMetadataVirtual()); + Assert.False(p06get.IsSealed); + Assert.True(p06get.IsStatic); + Assert.False(p06get.IsExtern); + Assert.False(p06get.IsAsync); + Assert.False(p06get.IsOverride); + Assert.Equal(Accessibility.Public, p06get.DeclaredAccessibility); + + var p07 = i1.GetMember("P07"); + var p07set = p07.RemoveMethod; + + Assert.False(p07.IsAbstract); + Assert.True(p07.IsVirtual); + Assert.False(p07.IsSealed); + Assert.False(p07.IsStatic); + Assert.False(p07.IsExtern); + Assert.False(p07.IsOverride); + Assert.Equal(Accessibility.Public, p07.DeclaredAccessibility); + + Assert.False(p07set.IsAbstract); + Assert.True(p07set.IsVirtual); + Assert.True(p07set.IsMetadataVirtual()); + Assert.False(p07set.IsSealed); + Assert.False(p07set.IsStatic); + Assert.False(p07set.IsExtern); + Assert.False(p07set.IsAsync); + Assert.False(p07set.IsOverride); + Assert.Equal(Accessibility.Public, p07set.DeclaredAccessibility); + + var p08 = i1.GetMember("P08"); + var p08get = p08.AddMethod; + + Assert.False(p08.IsAbstract); + Assert.False(p08.IsVirtual); + Assert.False(p08.IsSealed); + Assert.False(p08.IsStatic); + Assert.False(p08.IsExtern); + Assert.False(p08.IsOverride); + Assert.Equal(Accessibility.Public, p08.DeclaredAccessibility); + + Assert.False(p08get.IsAbstract); + Assert.False(p08get.IsVirtual); + Assert.False(p08get.IsMetadataVirtual()); + Assert.False(p08get.IsSealed); + Assert.False(p08get.IsStatic); + Assert.False(p08get.IsExtern); + Assert.False(p08get.IsAsync); + Assert.False(p08get.IsOverride); + Assert.Equal(Accessibility.Public, p08get.DeclaredAccessibility); + + var p09 = i1.GetMember("P09"); + var p09set = p09.RemoveMethod; + + Assert.False(p09.IsAbstract); + Assert.True(p09.IsVirtual); + Assert.False(p09.IsSealed); + Assert.False(p09.IsStatic); + Assert.False(p09.IsExtern); + Assert.False(p09.IsOverride); + Assert.Equal(Accessibility.Public, p09.DeclaredAccessibility); + + Assert.False(p09set.IsAbstract); + Assert.True(p09set.IsVirtual); + Assert.True(p09set.IsMetadataVirtual()); + Assert.False(p09set.IsSealed); + Assert.False(p09set.IsStatic); + Assert.False(p09set.IsExtern); + Assert.False(p09set.IsAsync); + Assert.False(p09set.IsOverride); + Assert.Equal(Accessibility.Public, p09set.DeclaredAccessibility); + + var p10 = i1.GetMember("P10"); + var p10get = p10.AddMethod; + + Assert.True(p10.IsAbstract); + Assert.False(p10.IsVirtual); + Assert.False(p10.IsSealed); + Assert.False(p10.IsStatic); + Assert.False(p10.IsExtern); + Assert.False(p10.IsOverride); + Assert.Equal(Accessibility.Public, p10.DeclaredAccessibility); + + Assert.True(p10get.IsAbstract); + Assert.False(p10get.IsVirtual); + Assert.True(p10get.IsMetadataVirtual()); + Assert.False(p10get.IsSealed); + Assert.False(p10get.IsStatic); + Assert.False(p10get.IsExtern); + Assert.False(p10get.IsAsync); + Assert.False(p10get.IsOverride); + Assert.Equal(Accessibility.Public, p10get.DeclaredAccessibility); - var source2 = -@" -class Test2 -{ - static void Test(I1 i1, I2 i2, I3 i3, I4 i4) - { - int x; - x = i1[0]; - i1[0] = x; - x = i2[0]; - i2[0] = x; - x = i3[0]; - i3[0] = x; - x = i4[0]; - i4[0] = x; - } -} -"; - var compilation2 = CreateStandardCompilation(source2, new[] { compilation1.ToMetadataReference() }, - options: TestOptions.DebugDll, - parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); - Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); - compilation2.VerifyDiagnostics( - // (7,13): error CS0122: 'I1.this[int]' is inaccessible due to its protection level - // x = i1[0]; - Diagnostic(ErrorCode.ERR_BadAccess, "i1[0]").WithArguments("I1.this[int]").WithLocation(7, 13), - // (8,9): error CS0122: 'I1.this[int]' is inaccessible due to its protection level - // i1[0] = x; - Diagnostic(ErrorCode.ERR_BadAccess, "i1[0]").WithArguments("I1.this[int]").WithLocation(8, 9), - // (9,13): error CS0122: 'I2.this[int]' is inaccessible due to its protection level - // x = i2[0]; - Diagnostic(ErrorCode.ERR_BadAccess, "i2[0]").WithArguments("I2.this[int]").WithLocation(9, 13), - // (10,9): error CS0122: 'I2.this[int]' is inaccessible due to its protection level - // i2[0] = x; - Diagnostic(ErrorCode.ERR_BadAccess, "i2[0]").WithArguments("I2.this[int]").WithLocation(10, 9) - ); + foreach (var name in new[] { "P11", "P12", "P13" }) + { + var p11 = i1.GetMember(name); + + Assert.False(p11.IsAbstract); + Assert.True(p11.IsVirtual); + Assert.False(p11.IsSealed); + Assert.False(p11.IsStatic); + Assert.True(p11.IsExtern); + Assert.False(p11.IsOverride); + Assert.Equal(Accessibility.Public, p11.DeclaredAccessibility); + + ValidateP11Accessor(p11.AddMethod); + ValidateP11Accessor(p11.RemoveMethod); + void ValidateP11Accessor(MethodSymbol accessor) + { + Assert.False(accessor.IsAbstract); + Assert.True(accessor.IsVirtual); + Assert.True(accessor.IsMetadataVirtual()); + Assert.False(accessor.IsSealed); + Assert.False(accessor.IsStatic); + Assert.True(accessor.IsExtern); + Assert.False(accessor.IsAsync); + Assert.False(accessor.IsOverride); + Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); + } + } } [Fact] - public void IndexerModifiers_22() + public void EventModifiers_02() { var source1 = @" public interface I1 { - public int this[int x] - { - internal get - { - System.Console.WriteLine(""get_P1""); - return 0; - } - set - { - System.Console.WriteLine(""set_P1""); - } - } -} -public interface I2 -{ - int this[int x] - { - get - { - System.Console.WriteLine(""get_P2""); - return 0; - } - internal set - { - System.Console.WriteLine(""set_P2""); - } - } -} -public interface I3 -{ - int this[int x] - { - internal get => Test1.GetP3(); - set => System.Console.WriteLine(""set_P3""); - } -} -public interface I4 -{ - int this[int x] - { - get => Test1.GetP4(); - internal set => System.Console.WriteLine(""set_P4""); - } -} -public interface I5 -{ - int this[int x] - { - private get - { - System.Console.WriteLine(""get_P5""); - return 0; - } - set - { - System.Console.WriteLine(""set_P5""); - } - } - - void Test() - { - this[0] = this[0]; - } -} -public interface I6 -{ - int this[int x] - { - get - { - System.Console.WriteLine(""get_P6""); - return 0; - } - private set - { - System.Console.WriteLine(""set_P6""); - } - } - - void Test() - { - this[0] = this[0]; - } + public event System.Action P01; + protected event System.Action P02 {add{}} + protected internal event System.Action P03 {remove{}} + internal event System.Action P04 {add{}} + private event System.Action P05 {remove{}} + static event System.Action P06 {add{}} + virtual event System.Action P07 {remove{}} + sealed event System.Action P08 {add{}} + override event System.Action P09 {remove{}} + abstract event System.Action P10 {add{}} + extern event System.Action P11 {add{} remove{}} + extern event System.Action P12 {add; remove;} + extern event System.Action P13; } -public interface I7 -{ - int this[int x] - { - private get => Test1.GetP7(); - set => System.Console.WriteLine(""set_P7""); - } +"; + var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp7)); + Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation1.GetDiagnostics().Where(d => d.Code != (int)ErrorCode.ERR_EventNeedsBothAccessors).Verify( + // (4,32): error CS8503: The modifier 'public' is not valid for this item in C# 7. Please use language version 7.1 or greater. + // public event System.Action P01; + Diagnostic(ErrorCode.ERR_DefaultInterfaceImplementationModifier, "P01").WithArguments("public", "7", "7.1").WithLocation(4, 32), + // (5,35): error CS0106: The modifier 'protected' is not valid for this item + // protected event System.Action P02 {add{}} + Diagnostic(ErrorCode.ERR_BadMemberFlag, "P02").WithArguments("protected").WithLocation(5, 35), + // (5,40): error CS8107: Feature 'default interface implementation' is not available in C# 7. Please use language version 7.1 or greater. + // protected event System.Action P02 {add{}} + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7, "add").WithArguments("default interface implementation", "7.1").WithLocation(5, 40), + // (6,44): error CS0106: The modifier 'protected internal' is not valid for this item + // protected internal event System.Action P03 {remove{}} + Diagnostic(ErrorCode.ERR_BadMemberFlag, "P03").WithArguments("protected internal").WithLocation(6, 44), + // (6,49): error CS8107: Feature 'default interface implementation' is not available in C# 7. Please use language version 7.1 or greater. + // protected internal event System.Action P03 {remove{}} + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7, "remove").WithArguments("default interface implementation", "7.1").WithLocation(6, 49), + // (7,39): error CS8107: Feature 'default interface implementation' is not available in C# 7. Please use language version 7.1 or greater. + // internal event System.Action P04 {add{}} + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7, "add").WithArguments("default interface implementation", "7.1").WithLocation(7, 39), + // (8,38): error CS8107: Feature 'default interface implementation' is not available in C# 7. Please use language version 7.1 or greater. + // private event System.Action P05 {remove{}} + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7, "remove").WithArguments("default interface implementation", "7.1").WithLocation(8, 38), + // (9,37): error CS8107: Feature 'default interface implementation' is not available in C# 7. Please use language version 7.1 or greater. + // static event System.Action P06 {add{}} + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7, "add").WithArguments("default interface implementation", "7.1").WithLocation(9, 37), + // (10,38): error CS8107: Feature 'default interface implementation' is not available in C# 7. Please use language version 7.1 or greater. + // virtual event System.Action P07 {remove{}} + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7, "remove").WithArguments("default interface implementation", "7.1").WithLocation(10, 38), + // (11,37): error CS8107: Feature 'default interface implementation' is not available in C# 7. Please use language version 7.1 or greater. + // sealed event System.Action P08 {add{}} + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7, "add").WithArguments("default interface implementation", "7.1").WithLocation(11, 37), + // (12,34): error CS0106: The modifier 'override' is not valid for this item + // override event System.Action P09 {remove{}} + Diagnostic(ErrorCode.ERR_BadMemberFlag, "P09").WithArguments("override").WithLocation(12, 34), + // (12,39): error CS8107: Feature 'default interface implementation' is not available in C# 7. Please use language version 7.1 or greater. + // override event System.Action P09 {remove{}} + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7, "remove").WithArguments("default interface implementation", "7.1").WithLocation(12, 39), + // (13,39): error CS8107: Feature 'default interface implementation' is not available in C# 7. Please use language version 7.1 or greater. + // abstract event System.Action P10 {add{}} + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7, "add").WithArguments("default interface implementation", "7.1").WithLocation(13, 39), + // (13,39): error CS0500: 'I1.P10.add' cannot declare a body because it is marked abstract + // abstract event System.Action P10 {add{}} + Diagnostic(ErrorCode.ERR_AbstractHasBody, "add").WithArguments("I1.P10.add").WithLocation(13, 39), + // (14,37): error CS8107: Feature 'default interface implementation' is not available in C# 7. Please use language version 7.1 or greater. + // extern event System.Action P11 {add{} remove{}} + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7, "add").WithArguments("default interface implementation", "7.1").WithLocation(14, 37), + // (14,37): error CS0179: 'I1.P11.add' cannot be extern and declare a body + // extern event System.Action P11 {add{} remove{}} + Diagnostic(ErrorCode.ERR_ExternHasBody, "add").WithArguments("I1.P11.add").WithLocation(14, 37), + // (14,43): error CS8107: Feature 'default interface implementation' is not available in C# 7. Please use language version 7.1 or greater. + // extern event System.Action P11 {add{} remove{}} + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7, "remove").WithArguments("default interface implementation", "7.1").WithLocation(14, 43), + // (14,43): error CS0179: 'I1.P11.remove' cannot be extern and declare a body + // extern event System.Action P11 {add{} remove{}} + Diagnostic(ErrorCode.ERR_ExternHasBody, "remove").WithArguments("I1.P11.remove").WithLocation(14, 43), + // (15,37): error CS8107: Feature 'default interface implementation' is not available in C# 7. Please use language version 7.1 or greater. + // extern event System.Action P12 {add; remove;} + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7, "add").WithArguments("default interface implementation", "7.1").WithLocation(15, 37), + // (15,37): warning CS0626: Method, operator, or accessor 'I1.P12.add' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. + // extern event System.Action P12 {add; remove;} + Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "add").WithArguments("I1.P12.add").WithLocation(15, 37), + // (15,40): error CS0073: An add or remove accessor must have a body + // extern event System.Action P12 {add; remove;} + Diagnostic(ErrorCode.ERR_AddRemoveMustHaveBody, ";").WithLocation(15, 40), + // (15,42): error CS8107: Feature 'default interface implementation' is not available in C# 7. Please use language version 7.1 or greater. + // extern event System.Action P12 {add; remove;} + Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7, "remove").WithArguments("default interface implementation", "7.1").WithLocation(15, 42), + // (15,42): warning CS0626: Method, operator, or accessor 'I1.P12.remove' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. + // extern event System.Action P12 {add; remove;} + Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "remove").WithArguments("I1.P12.remove").WithLocation(15, 42), + // (15,48): error CS0073: An add or remove accessor must have a body + // extern event System.Action P12 {add; remove;} + Diagnostic(ErrorCode.ERR_AddRemoveMustHaveBody, ";").WithLocation(15, 48), + // (16,32): error CS8503: The modifier 'extern' is not valid for this item in C# 7. Please use language version 7.1 or greater. + // extern event System.Action P13; + Diagnostic(ErrorCode.ERR_DefaultInterfaceImplementationModifier, "P13").WithArguments("extern", "7", "7.1").WithLocation(16, 32), + // (16,32): warning CS0626: Method, operator, or accessor 'I1.P13.add' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. + // extern event System.Action P13; + Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "P13").WithArguments("I1.P13.add").WithLocation(16, 32), + // (16,32): warning CS0626: Method, operator, or accessor 'I1.P13.remove' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. + // extern event System.Action P13; + Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "P13").WithArguments("I1.P13.remove").WithLocation(16, 32) + ); - void Test() - { - this[0] = this[0]; - } -} -public interface I8 -{ - int this[int x] - { - get => Test1.GetP8(); - private set => System.Console.WriteLine(""set_P8""); - } + ValidateSymbolsEventModifiers_01(compilation1); + } - void Test() + [Fact] + public void EventModifiers_03() + { + ValidateEventImplementation_102(@" +public interface I1 +{ + public virtual event System.Action E1 { - this[0] = this[0]; + add => System.Console.WriteLine(""add E1""); + remove => System.Console.WriteLine(""remove E1""); } } -class Test1 : I1, I2, I3, I4, I5, I6, I7, I8 +class Test1 : I1 +{} +"); + ValidateEventImplementation_102(@" +public interface I1 { - static void Main() - { - I1 i1 = new Test1(); - I2 i2 = new Test1(); - I3 i3 = new Test1(); - I4 i4 = new Test1(); - I5 i5 = new Test1(); - I6 i6 = new Test1(); - I7 i7 = new Test1(); - I8 i8 = new Test1(); - - i1[0] = i1[0]; - i2[0] = i2[0]; - i3[0] = i3[0]; - i4[0] = i4[0]; - i5.Test(); - i6.Test(); - i7.Test(); - i8.Test(); - } - - public static int GetP3() - { - System.Console.WriteLine(""get_P3""); - return 0; - } - - public static int GetP4() - { - System.Console.WriteLine(""get_P4""); - return 0; - } - - public static int GetP7() - { - System.Console.WriteLine(""get_P7""); - return 0; - } - - public static int GetP8() + public virtual event System.Action E1 { - System.Console.WriteLine(""get_P8""); - return 0; + add {System.Console.WriteLine(""add E1"");} + remove {System.Console.WriteLine(""remove E1"");} } } -"; - ValidatePropertyModifiers_22(source1); +class Test1 : I1 +{} +"); } [Fact] - public void IndexerModifiers_23() + public void EventModifiers_04() { - var source1 = -@" + ValidateEventImplementation_101(@" public interface I1 { - abstract int this[int x] {internal get; set;} - - void M2() - { - this[0] = this[1]; - } + public virtual event System.Action E1 {} } -public interface I3 -{ - int this[int x] - { - private get - { - System.Console.WriteLine(""get_P3""); - return 0; - } - set {} - } - void M2() - { - this[0] = this[1]; - } -} -public interface I4 -{ - int this[int x] - { - get {throw null;} - private set {System.Console.WriteLine(""set_P4"");} - } +class Test1 : I1 +{} +", + new[] { + // (4,40): error CS0065: 'I1.E1': event property must have both add and remove accessors + // public virtual event System.Action E1 {} + Diagnostic(ErrorCode.ERR_EventNeedsBothAccessors, "E1").WithArguments("I1.E1").WithLocation(4, 40) + }, + haveAdd: false, haveRemove: false); - void M2() - { - this[0] = this[1]; - } -} -public interface I5 + ValidateEventImplementation_101(@" +public interface I1 { - int this[int x] + public virtual event System.Action E1 { - private get => GetP5(); - set => throw null; + add; } +} - private int GetP5() - { - System.Console.WriteLine(""get_P5""); - return 0; - } +class Test1 : I1 +{} +", + new[] { + // (6,12): error CS0073: An add or remove accessor must have a body + // add; + Diagnostic(ErrorCode.ERR_AddRemoveMustHaveBody, ";"), + // (4,40): error CS0065: 'I1.E1': event property must have both add and remove accessors + // public virtual event System.Action E1 + Diagnostic(ErrorCode.ERR_EventNeedsBothAccessors, "E1").WithArguments("I1.E1").WithLocation(4, 40) + }, + haveAdd: true, haveRemove: false); - void M2() - { - this[0] = this[1]; - } -} -public interface I6 + ValidateEventImplementation_101(@" +public interface I1 { - int this[int x] - { - get => throw null; - private set => System.Console.WriteLine(""set_P6""); - } - - void M2() + public virtual event System.Action E1 { - this[0] = this[1]; + add {} } } -"; - var source2 = -@" class Test1 : I1 -{ - static void Main() - { - I1 i1 = new Test1(); - I3 i3 = new Test3(); - I4 i4 = new Test4(); - I5 i5 = new Test5(); - I6 i6 = new Test6(); - i1.M2(); - i3.M2(); - i4.M2(); - i5.M2(); - i6.M2(); - } +{} +", + new[] { + // (4,40): error CS0065: 'I1.E1': event property must have both add and remove accessors + // public virtual event System.Action E1 + Diagnostic(ErrorCode.ERR_EventNeedsBothAccessors, "E1").WithArguments("I1.E1").WithLocation(4, 40) + }, + haveAdd: true, haveRemove: false); - public int this[int x] - { - get - { - System.Console.WriteLine(""get_P1""); - return 0; - } - set - { - System.Console.WriteLine(""set_P1""); - } - } -} -class Test3 : I3 + + ValidateEventImplementation_101(@" +public interface I1 { - public int this[int x] + public virtual event System.Action E1 { - get - { - throw null; - } - set - { - System.Console.WriteLine(""set_P3""); - } + add => throw null; } } -class Test4 : I4 + +class Test1 : I1 +{} +", + new[] { + // (4,40): error CS0065: 'I1.E1': event property must have both add and remove accessors + // public virtual event System.Action E1 + Diagnostic(ErrorCode.ERR_EventNeedsBothAccessors, "E1").WithArguments("I1.E1").WithLocation(4, 40) + }, + haveAdd: true, haveRemove: false); + + ValidateEventImplementation_101(@" +public interface I1 { - public int this[int x] + public virtual event System.Action E1 { - get - { - System.Console.WriteLine(""get_P4""); - return 0; - } - set - { - throw null; - } + remove; } } -class Test5 : I5 + +class Test1 : I1 +{} +", + new[] { + // (6,15): error CS0073: An add or remove accessor must have a body + // remove; + Diagnostic(ErrorCode.ERR_AddRemoveMustHaveBody, ";").WithLocation(6, 15), + // (4,40): error CS0065: 'I1.E1': event property must have both add and remove accessors + // public virtual event System.Action E1 + Diagnostic(ErrorCode.ERR_EventNeedsBothAccessors, "E1").WithArguments("I1.E1").WithLocation(4, 40) + }, + haveAdd: false, haveRemove: true); + + ValidateEventImplementation_101(@" +public interface I1 { - public int this[int x] + public virtual event System.Action E1 { - get - { - throw null; - } - set - { - System.Console.WriteLine(""set_P5""); - } + remove {} } } -class Test6 : I6 + +class Test1 : I1 +{} +", + new[] { + // (4,40): error CS0065: 'I1.E1': event property must have both add and remove accessors + // public virtual event System.Action E1 + Diagnostic(ErrorCode.ERR_EventNeedsBothAccessors, "E1").WithArguments("I1.E1").WithLocation(4, 40) + }, + haveAdd: false, haveRemove: true); + + ValidateEventImplementation_101(@" +public interface I1 { - public int this[int x] + public virtual event System.Action E1 { - get - { - System.Console.WriteLine(""get_P6""); - return 0; - } - set - { - throw null; - } + remove => throw null; } } -"; - ValidatePropertyModifiers_23(source1, source2); - } - [Fact] - public void IndexerModifiers_24() - { - var source1 = -@" +class Test1 : I1 +{} +", + new[] { + // (4,40): error CS0065: 'I1.E1': event property must have both add and remove accessors + // public virtual event System.Action E1 + Diagnostic(ErrorCode.ERR_EventNeedsBothAccessors, "E1").WithArguments("I1.E1").WithLocation(4, 40) + }, + haveAdd: false, haveRemove: true); + + ValidateEventImplementation_101(@" public interface I1 { - int this[int x] + public virtual event System.Action E1 { - get - { - System.Console.WriteLine(""get_P1""); - return 0; - } - internal set - { - System.Console.WriteLine(""set_P1""); - } + add; + remove; } +} - void M2() {this[0] = this[1];} +class Test1 : I1 +{} +", + new[] { + // (6,12): error CS0073: An add or remove accessor must have a body + // add; + Diagnostic(ErrorCode.ERR_AddRemoveMustHaveBody, ";"), + // (7,15): error CS0073: An add or remove accessor must have a body + // remove; + Diagnostic(ErrorCode.ERR_AddRemoveMustHaveBody, ";").WithLocation(7, 15) + }, + haveAdd: true, haveRemove: true); + + ValidateEventImplementation_101(@" +public interface I1 +{ + public virtual event System.Action E1; } -"; - var source2 = -@" class Test1 : I1 +{} +", + new[] { + // (4,40): error CS0065: 'I1.E1': event property must have both add and remove accessors + // public virtual event System.Action E1; + Diagnostic(ErrorCode.ERR_EventNeedsBothAccessors, "E1").WithArguments("I1.E1").WithLocation(4, 40) + }, + haveAdd: true, haveRemove: true); + + ValidateEventImplementation_101(@" +public interface I1 { - static void Main() - { - I1 x = new Test1(); - x.M2(); - } + public virtual event System.Action E1 = null; } -"; - ValidatePropertyModifiers_24(source1, source2); + +class Test1 : I1 +{} +", + new[] { + // (4,40): error CS0068: 'I1.E1': event in interface cannot have initializer + // public virtual event System.Action E1 = null; + Diagnostic(ErrorCode.ERR_InterfaceEventInitializer, "E1").WithArguments("I1.E1").WithLocation(4, 40), + // (4,40): error CS0065: 'I1.E1': event property must have both add and remove accessors + // public virtual event System.Action E1 = null; + Diagnostic(ErrorCode.ERR_EventNeedsBothAccessors, "E1").WithArguments("I1.E1").WithLocation(4, 40), + // (4,40): warning CS0067: The event 'I1.E1' is never used + // public virtual event System.Action E1 = null; + Diagnostic(ErrorCode.WRN_UnreferencedEvent, "E1").WithArguments("I1.E1").WithLocation(4, 40) + }, + haveAdd: true, haveRemove: true); } [Fact] - public void IndexerModifiers_25() + public void EventModifiers_05() { var source1 = @" public interface I1 { - int this[int x] { private get => throw null; set => throw null; } + public abstract event System.Action P1; } public interface I2 { - int this[int x] { internal get => throw null; set => throw null; } + event System.Action P2; } -public interface I3 + +class Test1 : I1 { - public int this[int x] { get => throw null; private set => throw null; } + public event System.Action P1 + { + add + { + System.Console.WriteLine(""get_P1""); + } + remove => System.Console.WriteLine(""set_P1""); + } } -public interface I4 +class Test2 : I2 { - int this[int x] { get => throw null; internal set => throw null; } -} + public event System.Action P2 + { + add + { + System.Console.WriteLine(""get_P2""); + } + remove => System.Console.WriteLine(""set_P2""); + } -public class Test1 : I1, I2, I3, I4 -{ static void Main() { - int x; - I1 i1 = new Test1(); - I2 i2 = new Test1(); - I3 i3 = new Test1(); - I4 i4 = new Test1(); - - x = i1[0]; - i1[0] = x; - x = i2[0]; - i2[0] = x; - x = i3[0]; - i3[0] = x; - x = i4[0]; - i4[0] = x; + I1 x = new Test1(); + x.P1 += null; + x.P1 -= null; + I2 y = new Test2(); + y.P2 += null; + y.P2 -= null; } } "; - var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All), + + ValidateEventModifiers_05(source1); + } + + private void ValidateEventModifiers_05(string source1) + { + var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); - compilation1.VerifyDiagnostics( - // (29,13): error CS0271: The property or indexer 'I1.this[int]' cannot be used in this context because the get accessor is inaccessible - // x = i1[0]; - Diagnostic(ErrorCode.ERR_InaccessibleGetter, "i1[0]").WithArguments("I1.this[int]").WithLocation(29, 13), - // (34,9): error CS0272: The property or indexer 'I3.this[int]' cannot be used in this context because the set accessor is inaccessible - // i3[0] = x; - Diagnostic(ErrorCode.ERR_InaccessibleSetter, "i3[0]").WithArguments("I3.this[int]").WithLocation(34, 9) - ); - var source2 = -@" -class Test2 -{ - static void Main() - { - int x; - I1 i1 = new Test1(); - I2 i2 = new Test1(); - I3 i3 = new Test1(); - I4 i4 = new Test1(); + CompileAndVerify(compilation1, expectedOutput: +@"get_P1 +set_P1 +get_P2 +set_P2", symbolValidator: Validate); + + Validate(compilation1.SourceModule); + + void Validate(ModuleSymbol m) + { + for (int i = 1; i <= 2; i++) + { + var test1 = m.GlobalNamespace.GetTypeMember("Test" + i); + var i1 = m.GlobalNamespace.GetTypeMember("I" + i); + var p1 = GetSingleEvent(i1); + var test1P1 = GetSingleEvent(test1); + + Assert.True(p1.IsAbstract); + Assert.False(p1.IsVirtual); + Assert.False(p1.IsSealed); + Assert.False(p1.IsStatic); + Assert.False(p1.IsExtern); + Assert.False(p1.IsOverride); + Assert.Equal(Accessibility.Public, p1.DeclaredAccessibility); + Assert.Same(test1P1, test1.FindImplementationForInterfaceMember(p1)); + + ValidateAccessor(p1.AddMethod, test1P1.AddMethod); + ValidateAccessor(p1.RemoveMethod, test1P1.RemoveMethod); + + void ValidateAccessor(MethodSymbol accessor, MethodSymbol implementation) + { + Assert.True(accessor.IsAbstract); + Assert.False(accessor.IsVirtual); + Assert.True(accessor.IsMetadataVirtual()); + Assert.False(accessor.IsSealed); + Assert.False(accessor.IsStatic); + Assert.False(accessor.IsExtern); + Assert.False(accessor.IsAsync); + Assert.False(accessor.IsOverride); + Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); + Assert.Same(implementation, test1.FindImplementationForInterfaceMember(accessor)); + } + } + } + } + + private static EventSymbol GetSingleEvent(NamedTypeSymbol container) + { + return container.GetMembers().OfType().Single(); + } - x = i1[0]; - i1[0] = x; - x = i2[0]; - i2[0] = x; - x = i3[0]; - i3[0] = x; - x = i4[0]; - i4[0] = x; - } -} -"; - var compilation2 = CreateStandardCompilation(source2, new[] { compilation1.ToMetadataReference() }, - options: TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All), - parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); - Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); - compilation2.VerifyDiagnostics( - // (12,13): error CS0271: The property or indexer 'I1.this[int]' cannot be used in this context because the get accessor is inaccessible - // x = i1[0]; - Diagnostic(ErrorCode.ERR_InaccessibleGetter, "i1[0]").WithArguments("I1.this[int]").WithLocation(12, 13), - // (14,13): error CS0271: The property or indexer 'I2.this[int]' cannot be used in this context because the get accessor is inaccessible - // x = i2[0]; - Diagnostic(ErrorCode.ERR_InaccessibleGetter, "i2[0]").WithArguments("I2.this[int]").WithLocation(14, 13), - // (17,9): error CS0272: The property or indexer 'I3.this[int]' cannot be used in this context because the set accessor is inaccessible - // i3[0] = x; - Diagnostic(ErrorCode.ERR_InaccessibleSetter, "i3[0]").WithArguments("I3.this[int]").WithLocation(17, 9), - // (19,9): error CS0272: The property or indexer 'I4.this[int]' cannot be used in this context because the set accessor is inaccessible - // i4[0] = x; - Diagnostic(ErrorCode.ERR_InaccessibleSetter, "i4[0]").WithArguments("I4.this[int]").WithLocation(19, 9) - ); + private static EventSymbol GetSingleEvent(CSharpCompilation compilation, string containerName) + { + return GetSingleEvent(compilation.GetTypeByMetadataName(containerName)); + } + + private static EventSymbol GetSingleEvent(ModuleSymbol m, string containerName) + { + return GetSingleEvent(m.GlobalNamespace.GetTypeMember(containerName)); } [Fact] - public void IndexerModifiers_26() + public void EventModifiers_06() { var source1 = @" public interface I1 { - abstract int this[sbyte x] { private get; set; } - abstract int this[byte x] { get; private set; } - abstract int this[short x] { internal get; } - int this[ushort x] {internal get;} = 0; - int this[int x] { internal get {throw null;} } - int this[uint x] { internal set {throw null;} } - int this[long x] { internal get => throw null; } - int this[ulong x] { internal set => throw null; } - int this[float x] { internal get {throw null;} private set {throw null;}} - int this[double x] { internal get => throw null; private set => throw null;} + public abstract event System.Action P1; } "; - var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All), - parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp7)); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics( - // (7,40): error CS1519: Invalid token '=' in class, struct, or interface member declaration - // int this[ushort x] {internal get;} = 0; - Diagnostic(ErrorCode.ERR_InvalidMemberDecl, "=").WithArguments("=").WithLocation(7, 40), - // (4,42): error CS0442: 'I1.this[sbyte].get': abstract properties cannot have private accessors - // abstract int this[sbyte x] { private get; set; } - Diagnostic(ErrorCode.ERR_PrivateAbstractAccessor, "get").WithArguments("I1.this[sbyte].get").WithLocation(4, 42), - // (5,46): error CS0442: 'I1.this[byte].set': abstract properties cannot have private accessors - // abstract int this[byte x] { get; private set; } - Diagnostic(ErrorCode.ERR_PrivateAbstractAccessor, "set").WithArguments("I1.this[byte].set").WithLocation(5, 46), - // (6,18): error CS0276: 'I1.this[short]': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor - // abstract int this[short x] { internal get; } - Diagnostic(ErrorCode.ERR_AccessModMissingAccessor, "this").WithArguments("I1.this[short]").WithLocation(6, 18), - // (7,9): error CS0276: 'I1.this[ushort]': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor - // int this[ushort x] {internal get;} = 0; - Diagnostic(ErrorCode.ERR_AccessModMissingAccessor, "this").WithArguments("I1.this[ushort]").WithLocation(7, 9), - // (8,9): error CS0276: 'I1.this[int]': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor - // int this[int x] { internal get {throw null;} } - Diagnostic(ErrorCode.ERR_AccessModMissingAccessor, "this").WithArguments("I1.this[int]").WithLocation(8, 9), - // (9,9): error CS0276: 'I1.this[uint]': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor - // int this[uint x] { internal set {throw null;} } - Diagnostic(ErrorCode.ERR_AccessModMissingAccessor, "this").WithArguments("I1.this[uint]").WithLocation(9, 9), - // (10,9): error CS0276: 'I1.this[long]': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor - // int this[long x] { internal get => throw null; } - Diagnostic(ErrorCode.ERR_AccessModMissingAccessor, "this").WithArguments("I1.this[long]").WithLocation(10, 9), - // (11,9): error CS0276: 'I1.this[ulong]': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor - // int this[ulong x] { internal set => throw null; } - Diagnostic(ErrorCode.ERR_AccessModMissingAccessor, "this").WithArguments("I1.this[ulong]").WithLocation(11, 9), - // (12,9): error CS0274: Cannot specify accessibility modifiers for both accessors of the property or indexer 'I1.this[float]' - // int this[float x] { internal get {throw null;} private set {throw null;}} - Diagnostic(ErrorCode.ERR_DuplicatePropertyAccessMods, "this").WithArguments("I1.this[float]").WithLocation(12, 9), - // (13,9): error CS0274: Cannot specify accessibility modifiers for both accessors of the property or indexer 'I1.this[double]' - // int this[double x] { internal get => throw null; private set => throw null;} - Diagnostic(ErrorCode.ERR_DuplicatePropertyAccessMods, "this").WithArguments("I1.this[double]").WithLocation(13, 9) + // (4,41): error CS8503: The modifier 'abstract' is not valid for this item in C# 7. Please use language version 7.1 or greater. + // public abstract event System.Action P1; + Diagnostic(ErrorCode.ERR_DefaultInterfaceImplementationModifier, "P1").WithArguments("abstract", "7", "7.1").WithLocation(4, 41), + // (4,41): error CS8503: The modifier 'public' is not valid for this item in C# 7. Please use language version 7.1 or greater. + // public abstract event System.Action P1; + Diagnostic(ErrorCode.ERR_DefaultInterfaceImplementationModifier, "P1").WithArguments("public", "7", "7.1").WithLocation(4, 41) ); + + ValidateEventModifiers_06(compilation1); + } + + private static void ValidateEventModifiers_06(CSharpCompilation compilation1) + { + var i1 = compilation1.GetTypeByMetadataName("I1"); + var p1 = i1.GetMember("P1"); + + Assert.True(p1.IsAbstract); + Assert.False(p1.IsVirtual); + Assert.False(p1.IsSealed); + Assert.False(p1.IsStatic); + Assert.False(p1.IsExtern); + Assert.False(p1.IsOverride); + Assert.Equal(Accessibility.Public, p1.DeclaredAccessibility); + + ValidateAccessor(p1.AddMethod); + ValidateAccessor(p1.RemoveMethod); + + void ValidateAccessor(MethodSymbol accessor) + { + Assert.True(accessor.IsAbstract); + Assert.False(accessor.IsVirtual); + Assert.True(accessor.IsMetadataVirtual()); + Assert.False(accessor.IsSealed); + Assert.False(accessor.IsStatic); + Assert.False(accessor.IsExtern); + Assert.False(accessor.IsAsync); + Assert.False(accessor.IsOverride); + Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); + } } [Fact] - public void IndexerModifiers_27() + public void EventModifiers_07() { var source1 = @" public interface I1 { - int this[short x] + public static event System.Action P1 { - private get {throw null;} - set {} + add + { + System.Console.WriteLine(""get_P1""); + } + remove + { + System.Console.WriteLine(""set_P1""); + } } - int this[int x] + internal static event System.Action P2 { - get {throw null;} - private set {} + add + { + System.Console.WriteLine(""get_P2""); + P3 += value; + } + remove + { + System.Console.WriteLine(""set_P2""); + P3 -= value; + } } -} -class Test1 : I1 -{ - int I1.this[short x] + private static event System.Action P3 { - get {throw null;} - set {} + add => System.Console.WriteLine(""get_P3""); + remove => System.Console.WriteLine(""set_P3""); } +} - int I1.this[int x] +class Test1 : I1 +{ + static void Main() { - get {throw null;} - set {} + I1.P1 += null; + I1.P1 -= null; + I1.P2 += null; + I1.P2 -= null; } } +"; + var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All), + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + CompileAndVerify(compilation1, expectedOutput: +@"get_P1 +set_P1 +get_P2 +get_P3 +set_P2 +set_P3", symbolValidator: Validate); -class Test2 : I1 + Validate(compilation1.SourceModule); + + void Validate(ModuleSymbol m) + { + var test1 = m.GlobalNamespace.GetTypeMember("Test1"); + var i1 = m.GlobalNamespace.GetTypeMember("I1"); + + foreach (var tuple in new[] { (name: "P1", access: Accessibility.Public), + (name: "P2", access: Accessibility.Internal), + (name: "P3", access: Accessibility.Private)}) + { + var p1 = i1.GetMember(tuple.name); + + Assert.False(p1.IsAbstract); + Assert.False(p1.IsVirtual); + Assert.False(p1.IsSealed); + Assert.True(p1.IsStatic); + Assert.False(p1.IsExtern); + Assert.False(p1.IsOverride); + Assert.Equal(tuple.access, p1.DeclaredAccessibility); + Assert.Null(test1.FindImplementationForInterfaceMember(p1)); + + ValidateAccessor(p1.AddMethod); + ValidateAccessor(p1.RemoveMethod); + + void ValidateAccessor(MethodSymbol accessor) + { + Assert.False(accessor.IsAbstract); + Assert.False(accessor.IsVirtual); + Assert.False(accessor.IsMetadataVirtual()); + Assert.False(accessor.IsSealed); + Assert.True(accessor.IsStatic); + Assert.False(accessor.IsExtern); + Assert.False(accessor.IsAsync); + Assert.False(accessor.IsOverride); + Assert.Equal(tuple.access, accessor.DeclaredAccessibility); + Assert.Null(test1.FindImplementationForInterfaceMember(accessor)); + } + } + } + + var source2 = +@" +public interface I1 { - int I1.this[short x] + public static event System.Action P1; + + internal static event System.Action P2 { - set {throw null;} + add; + remove; } - int I1.this[int x] + private static event System.Action P3 = null; +} + +class Test1 : I1 +{ + static void Main() { - get => throw null; } } "; - var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All), + var compilation2 = CreateStandardCompilation(source2, options: TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All), parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); - Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); - - // PROTOTYPE(DefaultInterfaceImplementation): The lack of errors for Test1 looks wrong. Private accessor is never virtual - // (the behavior goes back to native compiler). So, it would be wrong - // to have a MethodImpl to point to an accessor like this in an interface. - compilation1.VerifyDiagnostics( - // (34,12): error CS0551: Explicit interface implementation 'Test2.I1.this[short]' is missing accessor 'I1.this[short].get' - // int I1.this[short x] - Diagnostic(ErrorCode.ERR_ExplicitPropertyMissingAccessor, "this").WithArguments("Test2.I1.this[short]", "I1.this[short].get").WithLocation(34, 12), - // (39,12): error CS0551: Explicit interface implementation 'Test2.I1.this[int]' is missing accessor 'I1.this[int].set' - // int I1.this[int x] - Diagnostic(ErrorCode.ERR_ExplicitPropertyMissingAccessor, "this").WithArguments("Test2.I1.this[int]", "I1.this[int].set").WithLocation(39, 12) + Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation2.VerifyDiagnostics( + // (8,12): error CS0073: An add or remove accessor must have a body + // add; + Diagnostic(ErrorCode.ERR_AddRemoveMustHaveBody, ";").WithLocation(8, 12), + // (9,15): error CS0073: An add or remove accessor must have a body + // remove; + Diagnostic(ErrorCode.ERR_AddRemoveMustHaveBody, ";").WithLocation(9, 15), + // (4,39): error CS0065: 'I1.P1': event property must have both add and remove accessors + // public static event System.Action P1; + Diagnostic(ErrorCode.ERR_EventNeedsBothAccessors, "P1").WithArguments("I1.P1").WithLocation(4, 39), + // (12,40): error CS0068: 'I1.P3': event in interface cannot have initializer + // private static event System.Action P3 = null; + Diagnostic(ErrorCode.ERR_InterfaceEventInitializer, "P3").WithArguments("I1.P3").WithLocation(12, 40), + // (12,40): error CS0065: 'I1.P3': event property must have both add and remove accessors + // private static event System.Action P3 = null; + Diagnostic(ErrorCode.ERR_EventNeedsBothAccessors, "P3").WithArguments("I1.P3").WithLocation(12, 40), + // (12,40): warning CS0067: The event 'I1.P3' is never used + // private static event System.Action P3 = null; + Diagnostic(ErrorCode.WRN_UnreferencedEvent, "P3").WithArguments("I1.P3").WithLocation(12, 40) ); + + Validate(compilation2.SourceModule); } [Fact] - public void EventModifiers_01() + public void EventModifiers_08() { var source1 = @" public interface I1 { - public event System.Action P01; - protected event System.Action P02 {add{}} - protected internal event System.Action P03 {remove{}} - internal event System.Action P04 {add{}} - private event System.Action P05 {remove{}} - static event System.Action P06 {add{}} - virtual event System.Action P07 {remove{}} - sealed event System.Action P08 {add{}} - override event System.Action P09 {remove{}} - abstract event System.Action P10 {add{}} - extern event System.Action P11 {add{} remove{}} - extern event System.Action P12 {add; remove;} - extern event System.Action P13; + abstract static event System.Action P1; + + virtual static event System.Action P2 {add {} remove{}} + + sealed static event System.Action P3 {add; remove;} +} + +class Test1 : I1 +{ + event System.Action I1.P1 {add {} remove{}} + event System.Action I1.P2 {add {} remove{}} + event System.Action I1.P3 {add {} remove{}} } + +class Test2 : I1 +{} "; var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); - compilation1.GetDiagnostics().Where(d => d.Code != (int)ErrorCode.ERR_EventNeedsBothAccessors).Verify( - // (5,35): error CS0106: The modifier 'protected' is not valid for this item - // protected event System.Action P02 {add{}} - Diagnostic(ErrorCode.ERR_BadMemberFlag, "P02").WithArguments("protected").WithLocation(5, 35), - // (6,44): error CS0106: The modifier 'protected internal' is not valid for this item - // protected internal event System.Action P03 {remove{}} - Diagnostic(ErrorCode.ERR_BadMemberFlag, "P03").WithArguments("protected internal").WithLocation(6, 44), - // (12,34): error CS0106: The modifier 'override' is not valid for this item - // override event System.Action P09 {remove{}} - Diagnostic(ErrorCode.ERR_BadMemberFlag, "P09").WithArguments("override").WithLocation(12, 34), - // (13,39): error CS0500: 'I1.P10.add' cannot declare a body because it is marked abstract - // abstract event System.Action P10 {add{}} - Diagnostic(ErrorCode.ERR_AbstractHasBody, "add").WithArguments("I1.P10.add").WithLocation(13, 39), - // (14,37): error CS0179: 'I1.P11.add' cannot be extern and declare a body - // extern event System.Action P11 {add{} remove{}} - Diagnostic(ErrorCode.ERR_ExternHasBody, "add").WithArguments("I1.P11.add").WithLocation(14, 37), - // (14,43): error CS0179: 'I1.P11.remove' cannot be extern and declare a body - // extern event System.Action P11 {add{} remove{}} - Diagnostic(ErrorCode.ERR_ExternHasBody, "remove").WithArguments("I1.P11.remove").WithLocation(14, 43), - // (15,37): warning CS0626: Method, operator, or accessor 'I1.P12.add' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. - // extern event System.Action P12 {add; remove;} - Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "add").WithArguments("I1.P12.add").WithLocation(15, 37), - // (15,40): error CS0073: An add or remove accessor must have a body - // extern event System.Action P12 {add; remove;} - Diagnostic(ErrorCode.ERR_AddRemoveMustHaveBody, ";").WithLocation(15, 40), - // (15,42): warning CS0626: Method, operator, or accessor 'I1.P12.remove' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. - // extern event System.Action P12 {add; remove;} - Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "remove").WithArguments("I1.P12.remove").WithLocation(15, 42), - // (15,48): error CS0073: An add or remove accessor must have a body - // extern event System.Action P12 {add; remove;} - Diagnostic(ErrorCode.ERR_AddRemoveMustHaveBody, ";").WithLocation(15, 48), - // (16,32): warning CS0626: Method, operator, or accessor 'I1.P13.add' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. - // extern event System.Action P13; - Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "P13").WithArguments("I1.P13.add").WithLocation(16, 32), - // (16,32): warning CS0626: Method, operator, or accessor 'I1.P13.remove' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. - // extern event System.Action P13; - Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "P13").WithArguments("I1.P13.remove").WithLocation(16, 32) + compilation1.VerifyDiagnostics( + // (8,46): error CS0073: An add or remove accessor must have a body + // sealed static event System.Action P3 {add; remove;} + Diagnostic(ErrorCode.ERR_AddRemoveMustHaveBody, ";").WithLocation(8, 46), + // (8,54): error CS0073: An add or remove accessor must have a body + // sealed static event System.Action P3 {add; remove;} + Diagnostic(ErrorCode.ERR_AddRemoveMustHaveBody, ";").WithLocation(8, 54), + // (6,40): error CS0112: A static member 'I1.P2' cannot be marked as override, virtual, or abstract + // virtual static event System.Action P2 {add {} remove{}} + Diagnostic(ErrorCode.ERR_StaticNotVirtual, "P2").WithArguments("I1.P2").WithLocation(6, 40), + // (8,39): error CS0238: 'I1.P3' cannot be sealed because it is not an override + // sealed static event System.Action P3 {add; remove;} + Diagnostic(ErrorCode.ERR_SealedNonOverride, "P3").WithArguments("I1.P3").WithLocation(8, 39), + // (4,41): error CS0112: A static member 'I1.P1' cannot be marked as override, virtual, or abstract + // abstract static event System.Action P1; + Diagnostic(ErrorCode.ERR_StaticNotVirtual, "P1").WithArguments("I1.P1").WithLocation(4, 41), + // (13,28): error CS0539: 'Test1.P1' in explicit interface declaration is not found among members of the interface that can be implemented + // event System.Action I1.P1 {add {} remove{}} + Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "P1").WithArguments("Test1.P1").WithLocation(13, 28), + // (14,28): error CS0539: 'Test1.P2' in explicit interface declaration is not found among members of the interface that can be implemented + // event System.Action I1.P2 {add {} remove{}} + Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "P2").WithArguments("Test1.P2").WithLocation(14, 28), + // (15,28): error CS0539: 'Test1.P3' in explicit interface declaration is not found among members of the interface that can be implemented + // event System.Action I1.P3 {add {} remove{}} + Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "P3").WithArguments("Test1.P3").WithLocation(15, 28) ); - ValidateSymbolsEventModifiers_01(compilation1); - } - - private static void ValidateSymbolsEventModifiers_01(CSharpCompilation compilation1) - { + var test1 = compilation1.GetTypeByMetadataName("Test1"); var i1 = compilation1.GetTypeByMetadataName("I1"); - var p01 = i1.GetMember("P01"); - - Assert.True(p01.IsAbstract); - Assert.False(p01.IsVirtual); - Assert.False(p01.IsSealed); - Assert.False(p01.IsStatic); - Assert.False(p01.IsExtern); - Assert.False(p01.IsOverride); - Assert.Equal(Accessibility.Public, p01.DeclaredAccessibility); - - VaidateP01Accessor(p01.AddMethod); - VaidateP01Accessor(p01.RemoveMethod); - void VaidateP01Accessor(MethodSymbol accessor) - { - Assert.True(accessor.IsAbstract); - Assert.False(accessor.IsVirtual); - Assert.True(accessor.IsMetadataVirtual()); - Assert.False(accessor.IsSealed); - Assert.False(accessor.IsStatic); - Assert.False(accessor.IsExtern); - Assert.False(accessor.IsAsync); - Assert.False(accessor.IsOverride); - Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); - } - - var p02 = i1.GetMember("P02"); - var p02get = p02.AddMethod; - - Assert.False(p02.IsAbstract); - Assert.True(p02.IsVirtual); - Assert.False(p02.IsSealed); - Assert.False(p02.IsStatic); - Assert.False(p02.IsExtern); - Assert.False(p02.IsOverride); - Assert.Equal(Accessibility.Public, p02.DeclaredAccessibility); - - Assert.False(p02get.IsAbstract); - Assert.True(p02get.IsVirtual); - Assert.True(p02get.IsMetadataVirtual()); - Assert.False(p02get.IsSealed); - Assert.False(p02get.IsStatic); - Assert.False(p02get.IsExtern); - Assert.False(p02get.IsAsync); - Assert.False(p02get.IsOverride); - Assert.Equal(Accessibility.Public, p02get.DeclaredAccessibility); - - var p03 = i1.GetMember("P03"); - var p03set = p03.RemoveMethod; - - Assert.False(p03.IsAbstract); - Assert.True(p03.IsVirtual); - Assert.False(p03.IsSealed); - Assert.False(p03.IsStatic); - Assert.False(p03.IsExtern); - Assert.False(p03.IsOverride); - Assert.Equal(Accessibility.Public, p03.DeclaredAccessibility); - - Assert.False(p03set.IsAbstract); - Assert.True(p03set.IsVirtual); - Assert.True(p03set.IsMetadataVirtual()); - Assert.False(p03set.IsSealed); - Assert.False(p03set.IsStatic); - Assert.False(p03set.IsExtern); - Assert.False(p03set.IsAsync); - Assert.False(p03set.IsOverride); - Assert.Equal(Accessibility.Public, p03set.DeclaredAccessibility); - - var p04 = i1.GetMember("P04"); - var p04get = p04.AddMethod; - - Assert.False(p04.IsAbstract); - Assert.True(p04.IsVirtual); - Assert.False(p04.IsSealed); - Assert.False(p04.IsStatic); - Assert.False(p04.IsExtern); - Assert.False(p04.IsOverride); - Assert.Equal(Accessibility.Internal, p04.DeclaredAccessibility); - - Assert.False(p04get.IsAbstract); - Assert.True(p04get.IsVirtual); - Assert.True(p04get.IsMetadataVirtual()); - Assert.False(p04get.IsSealed); - Assert.False(p04get.IsStatic); - Assert.False(p04get.IsExtern); - Assert.False(p04get.IsAsync); - Assert.False(p04get.IsOverride); - Assert.Equal(Accessibility.Internal, p04get.DeclaredAccessibility); - - var p05 = i1.GetMember("P05"); - var p05set = p05.RemoveMethod; - - Assert.False(p05.IsAbstract); - Assert.False(p05.IsVirtual); - Assert.False(p05.IsSealed); - Assert.False(p05.IsStatic); - Assert.False(p05.IsExtern); - Assert.False(p05.IsOverride); - Assert.Equal(Accessibility.Private, p05.DeclaredAccessibility); - - Assert.False(p05set.IsAbstract); - Assert.False(p05set.IsVirtual); - Assert.False(p05set.IsMetadataVirtual()); - Assert.False(p05set.IsSealed); - Assert.False(p05set.IsStatic); - Assert.False(p05set.IsExtern); - Assert.False(p05set.IsAsync); - Assert.False(p05set.IsOverride); - Assert.Equal(Accessibility.Private, p05set.DeclaredAccessibility); - - var p06 = i1.GetMember("P06"); - var p06get = p06.AddMethod; + var p1 = i1.GetMember("P1"); - Assert.False(p06.IsAbstract); - Assert.False(p06.IsVirtual); - Assert.False(p06.IsSealed); - Assert.True(p06.IsStatic); - Assert.False(p06.IsExtern); - Assert.False(p06.IsOverride); - Assert.Equal(Accessibility.Public, p06.DeclaredAccessibility); + Assert.True(p1.IsAbstract); + Assert.False(p1.IsVirtual); + Assert.False(p1.IsSealed); + Assert.True(p1.IsStatic); + Assert.False(p1.IsExtern); + Assert.False(p1.IsOverride); + Assert.Equal(Accessibility.Public, p1.DeclaredAccessibility); + Assert.Null(test1.FindImplementationForInterfaceMember(p1)); - Assert.False(p06get.IsAbstract); - Assert.False(p06get.IsVirtual); - Assert.False(p06get.IsMetadataVirtual()); - Assert.False(p06get.IsSealed); - Assert.True(p06get.IsStatic); - Assert.False(p06get.IsExtern); - Assert.False(p06get.IsAsync); - Assert.False(p06get.IsOverride); - Assert.Equal(Accessibility.Public, p06get.DeclaredAccessibility); + ValidateAccessor1(p1.AddMethod); + ValidateAccessor1(p1.RemoveMethod); + void ValidateAccessor1(MethodSymbol accessor) + { + Assert.True(accessor.IsAbstract); + Assert.False(accessor.IsVirtual); + Assert.True(accessor.IsMetadataVirtual()); + Assert.False(accessor.IsSealed); + Assert.True(accessor.IsStatic); + Assert.False(accessor.IsExtern); + Assert.False(accessor.IsAsync); + Assert.False(accessor.IsOverride); + Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); + Assert.Null(test1.FindImplementationForInterfaceMember(accessor)); + } - var p07 = i1.GetMember("P07"); - var p07set = p07.RemoveMethod; + var p2 = i1.GetMember("P2"); - Assert.False(p07.IsAbstract); - Assert.True(p07.IsVirtual); - Assert.False(p07.IsSealed); - Assert.False(p07.IsStatic); - Assert.False(p07.IsExtern); - Assert.False(p07.IsOverride); - Assert.Equal(Accessibility.Public, p07.DeclaredAccessibility); + Assert.False(p2.IsAbstract); + Assert.True(p2.IsVirtual); + Assert.False(p2.IsSealed); + Assert.True(p2.IsStatic); + Assert.False(p2.IsExtern); + Assert.False(p2.IsOverride); + Assert.Equal(Accessibility.Public, p2.DeclaredAccessibility); + Assert.Null(test1.FindImplementationForInterfaceMember(p2)); - Assert.False(p07set.IsAbstract); - Assert.True(p07set.IsVirtual); - Assert.True(p07set.IsMetadataVirtual()); - Assert.False(p07set.IsSealed); - Assert.False(p07set.IsStatic); - Assert.False(p07set.IsExtern); - Assert.False(p07set.IsAsync); - Assert.False(p07set.IsOverride); - Assert.Equal(Accessibility.Public, p07set.DeclaredAccessibility); + ValidateAccessor2(p2.AddMethod); + ValidateAccessor2(p2.RemoveMethod); + void ValidateAccessor2(MethodSymbol accessor) + { + Assert.False(accessor.IsAbstract); + Assert.True(accessor.IsVirtual); + Assert.True(accessor.IsMetadataVirtual()); + Assert.False(accessor.IsSealed); + Assert.True(accessor.IsStatic); + Assert.False(accessor.IsExtern); + Assert.False(accessor.IsAsync); + Assert.False(accessor.IsOverride); + Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); + Assert.Null(test1.FindImplementationForInterfaceMember(accessor)); + } - var p08 = i1.GetMember("P08"); - var p08get = p08.AddMethod; + var p3 = i1.GetMember("P3"); - Assert.False(p08.IsAbstract); - Assert.False(p08.IsVirtual); - Assert.False(p08.IsSealed); - Assert.False(p08.IsStatic); - Assert.False(p08.IsExtern); - Assert.False(p08.IsOverride); - Assert.Equal(Accessibility.Public, p08.DeclaredAccessibility); + Assert.False(p3.IsAbstract); + Assert.False(p3.IsVirtual); + Assert.True(p3.IsSealed); + Assert.True(p3.IsStatic); + Assert.False(p3.IsExtern); + Assert.False(p3.IsOverride); + Assert.Equal(Accessibility.Public, p3.DeclaredAccessibility); + Assert.Null(test1.FindImplementationForInterfaceMember(p3)); - Assert.False(p08get.IsAbstract); - Assert.False(p08get.IsVirtual); - Assert.False(p08get.IsMetadataVirtual()); - Assert.False(p08get.IsSealed); - Assert.False(p08get.IsStatic); - Assert.False(p08get.IsExtern); - Assert.False(p08get.IsAsync); - Assert.False(p08get.IsOverride); - Assert.Equal(Accessibility.Public, p08get.DeclaredAccessibility); + ValidateAccessor3(p3.AddMethod); + ValidateAccessor3(p3.RemoveMethod); + void ValidateAccessor3(MethodSymbol accessor) + { + Assert.False(accessor.IsAbstract); + Assert.False(accessor.IsVirtual); + Assert.False(accessor.IsMetadataVirtual()); + Assert.True(accessor.IsSealed); + Assert.True(accessor.IsStatic); + Assert.False(accessor.IsExtern); + Assert.False(accessor.IsAsync); + Assert.False(accessor.IsOverride); + Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); + Assert.Null(test1.FindImplementationForInterfaceMember(accessor)); + } + } - var p09 = i1.GetMember("P09"); - var p09set = p09.RemoveMethod; + [Fact] + public void EventModifiers_09() + { + var source1 = +@" +public interface I1 +{ + private event System.Action P1 + { + add + { + System.Console.WriteLine(""get_P1""); + } + remove + { + System.Console.WriteLine(""set_P1""); + } + } + sealed void M() + { + P1 += null; + P1 -= null; + } +} +public interface I2 +{ + private event System.Action P2 + { + add => System.Console.WriteLine(""get_P2""); + remove => System.Console.WriteLine(""set_P2""); + } - Assert.False(p09.IsAbstract); - Assert.True(p09.IsVirtual); - Assert.False(p09.IsSealed); - Assert.False(p09.IsStatic); - Assert.False(p09.IsExtern); - Assert.False(p09.IsOverride); - Assert.Equal(Accessibility.Public, p09.DeclaredAccessibility); + sealed void M() + { + P2 += null; + P2 -= null; + } +} - Assert.False(p09set.IsAbstract); - Assert.True(p09set.IsVirtual); - Assert.True(p09set.IsMetadataVirtual()); - Assert.False(p09set.IsSealed); - Assert.False(p09set.IsStatic); - Assert.False(p09set.IsExtern); - Assert.False(p09set.IsAsync); - Assert.False(p09set.IsOverride); - Assert.Equal(Accessibility.Public, p09set.DeclaredAccessibility); +class Test1 : I1, I2 +{ + static void Main() + { + I1 x1 = new Test1(); + x1.M(); + I2 x2 = new Test1(); + x2.M(); + } +} +"; - var p10 = i1.GetMember("P10"); - var p10get = p10.AddMethod; + ValidateEventModifiers_09(source1); + } - Assert.True(p10.IsAbstract); - Assert.False(p10.IsVirtual); - Assert.False(p10.IsSealed); - Assert.False(p10.IsStatic); - Assert.False(p10.IsExtern); - Assert.False(p10.IsOverride); - Assert.Equal(Accessibility.Public, p10.DeclaredAccessibility); + private void ValidateEventModifiers_09(string source1) + { + var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All), + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + CompileAndVerify(compilation1, verify: false, symbolValidator: Validate); - Assert.True(p10get.IsAbstract); - Assert.False(p10get.IsVirtual); - Assert.True(p10get.IsMetadataVirtual()); - Assert.False(p10get.IsSealed); - Assert.False(p10get.IsStatic); - Assert.False(p10get.IsExtern); - Assert.False(p10get.IsAsync); - Assert.False(p10get.IsOverride); - Assert.Equal(Accessibility.Public, p10get.DeclaredAccessibility); + Validate(compilation1.SourceModule); - foreach (var name in new[] { "P11", "P12", "P13" }) + void Validate(ModuleSymbol m) { - var p11 = i1.GetMember(name); - - Assert.False(p11.IsAbstract); - Assert.True(p11.IsVirtual); - Assert.False(p11.IsSealed); - Assert.False(p11.IsStatic); - Assert.True(p11.IsExtern); - Assert.False(p11.IsOverride); - Assert.Equal(Accessibility.Public, p11.DeclaredAccessibility); + var test1 = m.GlobalNamespace.GetTypeMember("Test1"); - ValidateP11Accessor(p11.AddMethod); - ValidateP11Accessor(p11.RemoveMethod); - void ValidateP11Accessor(MethodSymbol accessor) + for (int i = 1; i <= 2; i++) { - Assert.False(accessor.IsAbstract); - Assert.True(accessor.IsVirtual); - Assert.True(accessor.IsMetadataVirtual()); - Assert.False(accessor.IsSealed); - Assert.False(accessor.IsStatic); - Assert.True(accessor.IsExtern); - Assert.False(accessor.IsAsync); - Assert.False(accessor.IsOverride); - Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); + var i1 = m.GlobalNamespace.GetTypeMember("I" + i); + var p1 = GetSingleEvent(i1); + + Assert.False(p1.IsAbstract); + Assert.False(p1.IsVirtual); + Assert.False(p1.IsSealed); + Assert.False(p1.IsStatic); + Assert.False(p1.IsExtern); + Assert.False(p1.IsOverride); + Assert.Equal(Accessibility.Private, p1.DeclaredAccessibility); + Assert.Null(test1.FindImplementationForInterfaceMember(p1)); + + ValidateAccessor(p1.AddMethod); + ValidateAccessor(p1.RemoveMethod); + + void ValidateAccessor(MethodSymbol accessor) + { + Assert.False(accessor.IsAbstract); + Assert.False(accessor.IsVirtual); + Assert.False(accessor.IsMetadataVirtual()); + Assert.False(accessor.IsSealed); + Assert.False(accessor.IsStatic); + Assert.False(accessor.IsExtern); + Assert.False(accessor.IsAsync); + Assert.False(accessor.IsOverride); + Assert.Equal(Accessibility.Private, accessor.DeclaredAccessibility); + Assert.Null(test1.FindImplementationForInterfaceMember(accessor)); + } } } } [Fact] - public void EventModifiers_02() + public void EventModifiers_10() { var source1 = @" public interface I1 { - public event System.Action P01; - protected event System.Action P02 {add{}} - protected internal event System.Action P03 {remove{}} - internal event System.Action P04 {add{}} - private event System.Action P05 {remove{}} - static event System.Action P06 {add{}} - virtual event System.Action P07 {remove{}} - sealed event System.Action P08 {add{}} - override event System.Action P09 {remove{}} - abstract event System.Action P10 {add{}} - extern event System.Action P11 {add{} remove{}} - extern event System.Action P12 {add; remove;} - extern event System.Action P13; + abstract private event System.Action P1; + + virtual private event System.Action P2; + + sealed private event System.Action P3 + { + add => throw null; + remove {} + } + + private event System.Action P4 = null; +} + +class Test1 : I1 +{ } "; var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, - parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp7)); + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); - compilation1.GetDiagnostics().Where(d => d.Code != (int)ErrorCode.ERR_EventNeedsBothAccessors).Verify( - // (4,32): error CS8503: The modifier 'public' is not valid for this item in C# 7. Please use language version 7.1 or greater. - // public event System.Action P01; - Diagnostic(ErrorCode.ERR_DefaultInterfaceImplementationModifier, "P01").WithArguments("public", "7", "7.1").WithLocation(4, 32), - // (5,35): error CS0106: The modifier 'protected' is not valid for this item - // protected event System.Action P02 {add{}} - Diagnostic(ErrorCode.ERR_BadMemberFlag, "P02").WithArguments("protected").WithLocation(5, 35), - // (5,40): error CS8107: Feature 'default interface implementation' is not available in C# 7. Please use language version 7.1 or greater. - // protected event System.Action P02 {add{}} - Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7, "add").WithArguments("default interface implementation", "7.1").WithLocation(5, 40), - // (6,44): error CS0106: The modifier 'protected internal' is not valid for this item - // protected internal event System.Action P03 {remove{}} - Diagnostic(ErrorCode.ERR_BadMemberFlag, "P03").WithArguments("protected internal").WithLocation(6, 44), - // (6,49): error CS8107: Feature 'default interface implementation' is not available in C# 7. Please use language version 7.1 or greater. - // protected internal event System.Action P03 {remove{}} - Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7, "remove").WithArguments("default interface implementation", "7.1").WithLocation(6, 49), - // (7,39): error CS8107: Feature 'default interface implementation' is not available in C# 7. Please use language version 7.1 or greater. - // internal event System.Action P04 {add{}} - Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7, "add").WithArguments("default interface implementation", "7.1").WithLocation(7, 39), - // (8,38): error CS8107: Feature 'default interface implementation' is not available in C# 7. Please use language version 7.1 or greater. - // private event System.Action P05 {remove{}} - Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7, "remove").WithArguments("default interface implementation", "7.1").WithLocation(8, 38), - // (9,37): error CS8107: Feature 'default interface implementation' is not available in C# 7. Please use language version 7.1 or greater. - // static event System.Action P06 {add{}} - Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7, "add").WithArguments("default interface implementation", "7.1").WithLocation(9, 37), - // (10,38): error CS8107: Feature 'default interface implementation' is not available in C# 7. Please use language version 7.1 or greater. - // virtual event System.Action P07 {remove{}} - Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7, "remove").WithArguments("default interface implementation", "7.1").WithLocation(10, 38), - // (11,37): error CS8107: Feature 'default interface implementation' is not available in C# 7. Please use language version 7.1 or greater. - // sealed event System.Action P08 {add{}} - Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7, "add").WithArguments("default interface implementation", "7.1").WithLocation(11, 37), - // (12,34): error CS0106: The modifier 'override' is not valid for this item - // override event System.Action P09 {remove{}} - Diagnostic(ErrorCode.ERR_BadMemberFlag, "P09").WithArguments("override").WithLocation(12, 34), - // (12,39): error CS8107: Feature 'default interface implementation' is not available in C# 7. Please use language version 7.1 or greater. - // override event System.Action P09 {remove{}} - Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7, "remove").WithArguments("default interface implementation", "7.1").WithLocation(12, 39), - // (13,39): error CS8107: Feature 'default interface implementation' is not available in C# 7. Please use language version 7.1 or greater. - // abstract event System.Action P10 {add{}} - Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7, "add").WithArguments("default interface implementation", "7.1").WithLocation(13, 39), - // (13,39): error CS0500: 'I1.P10.add' cannot declare a body because it is marked abstract - // abstract event System.Action P10 {add{}} - Diagnostic(ErrorCode.ERR_AbstractHasBody, "add").WithArguments("I1.P10.add").WithLocation(13, 39), - // (14,37): error CS8107: Feature 'default interface implementation' is not available in C# 7. Please use language version 7.1 or greater. - // extern event System.Action P11 {add{} remove{}} - Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7, "add").WithArguments("default interface implementation", "7.1").WithLocation(14, 37), - // (14,37): error CS0179: 'I1.P11.add' cannot be extern and declare a body - // extern event System.Action P11 {add{} remove{}} - Diagnostic(ErrorCode.ERR_ExternHasBody, "add").WithArguments("I1.P11.add").WithLocation(14, 37), - // (14,43): error CS8107: Feature 'default interface implementation' is not available in C# 7. Please use language version 7.1 or greater. - // extern event System.Action P11 {add{} remove{}} - Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7, "remove").WithArguments("default interface implementation", "7.1").WithLocation(14, 43), - // (14,43): error CS0179: 'I1.P11.remove' cannot be extern and declare a body - // extern event System.Action P11 {add{} remove{}} - Diagnostic(ErrorCode.ERR_ExternHasBody, "remove").WithArguments("I1.P11.remove").WithLocation(14, 43), - // (15,37): error CS8107: Feature 'default interface implementation' is not available in C# 7. Please use language version 7.1 or greater. - // extern event System.Action P12 {add; remove;} - Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7, "add").WithArguments("default interface implementation", "7.1").WithLocation(15, 37), - // (15,37): warning CS0626: Method, operator, or accessor 'I1.P12.add' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. - // extern event System.Action P12 {add; remove;} - Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "add").WithArguments("I1.P12.add").WithLocation(15, 37), - // (15,40): error CS0073: An add or remove accessor must have a body - // extern event System.Action P12 {add; remove;} - Diagnostic(ErrorCode.ERR_AddRemoveMustHaveBody, ";").WithLocation(15, 40), - // (15,42): error CS8107: Feature 'default interface implementation' is not available in C# 7. Please use language version 7.1 or greater. - // extern event System.Action P12 {add; remove;} - Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7, "remove").WithArguments("default interface implementation", "7.1").WithLocation(15, 42), - // (15,42): warning CS0626: Method, operator, or accessor 'I1.P12.remove' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. - // extern event System.Action P12 {add; remove;} - Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "remove").WithArguments("I1.P12.remove").WithLocation(15, 42), - // (15,48): error CS0073: An add or remove accessor must have a body - // extern event System.Action P12 {add; remove;} - Diagnostic(ErrorCode.ERR_AddRemoveMustHaveBody, ";").WithLocation(15, 48), - // (16,32): error CS8503: The modifier 'extern' is not valid for this item in C# 7. Please use language version 7.1 or greater. - // extern event System.Action P13; - Diagnostic(ErrorCode.ERR_DefaultInterfaceImplementationModifier, "P13").WithArguments("extern", "7", "7.1").WithLocation(16, 32), - // (16,32): warning CS0626: Method, operator, or accessor 'I1.P13.add' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. - // extern event System.Action P13; - Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "P13").WithArguments("I1.P13.add").WithLocation(16, 32), - // (16,32): warning CS0626: Method, operator, or accessor 'I1.P13.remove' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. - // extern event System.Action P13; - Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "P13").WithArguments("I1.P13.remove").WithLocation(16, 32) + compilation1.VerifyDiagnostics( + // (4,42): error CS0621: 'I1.P1': virtual or abstract members cannot be private + // abstract private event System.Action P1; + Diagnostic(ErrorCode.ERR_VirtualPrivate, "P1").WithArguments("I1.P1").WithLocation(4, 42), + // (6,41): error CS0065: 'I1.P2': event property must have both add and remove accessors + // virtual private event System.Action P2; + Diagnostic(ErrorCode.ERR_EventNeedsBothAccessors, "P2").WithArguments("I1.P2").WithLocation(6, 41), + // (6,41): error CS0621: 'I1.P2': virtual or abstract members cannot be private + // virtual private event System.Action P2; + Diagnostic(ErrorCode.ERR_VirtualPrivate, "P2").WithArguments("I1.P2").WithLocation(6, 41), + // (8,40): error CS0238: 'I1.P3' cannot be sealed because it is not an override + // sealed private event System.Action P3 + Diagnostic(ErrorCode.ERR_SealedNonOverride, "P3").WithArguments("I1.P3").WithLocation(8, 40), + // (14,33): error CS0068: 'I1.P4': event in interface cannot have initializer + // private event System.Action P4 = null; + Diagnostic(ErrorCode.ERR_InterfaceEventInitializer, "P4").WithArguments("I1.P4").WithLocation(14, 33), + // (14,33): error CS0065: 'I1.P4': event property must have both add and remove accessors + // private event System.Action P4 = null; + Diagnostic(ErrorCode.ERR_EventNeedsBothAccessors, "P4").WithArguments("I1.P4").WithLocation(14, 33), + // (17,15): error CS0535: 'Test1' does not implement interface member 'I1.P1' + // class Test1 : I1 + Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test1", "I1.P1"), + // (14,33): warning CS0067: The event 'I1.P4' is never used + // private event System.Action P4 = null; + Diagnostic(ErrorCode.WRN_UnreferencedEvent, "P4").WithArguments("I1.P4").WithLocation(14, 33) ); - ValidateSymbolsEventModifiers_01(compilation1); + ValidateEventModifiers_10(compilation1); + } + + private static void ValidateEventModifiers_10(CSharpCompilation compilation1) + { + var test1 = compilation1.GetTypeByMetadataName("Test1"); + var i1 = compilation1.GetTypeByMetadataName("I1"); + var p1 = i1.GetMembers().OfType().ElementAt(0); + + Assert.True(p1.IsAbstract); + Assert.False(p1.IsVirtual); + Assert.False(p1.IsSealed); + Assert.False(p1.IsStatic); + Assert.False(p1.IsExtern); + Assert.False(p1.IsOverride); + Assert.Equal(Accessibility.Private, p1.DeclaredAccessibility); + Assert.Null(test1.FindImplementationForInterfaceMember(p1)); + + ValidateP1Accessor(p1.AddMethod); + ValidateP1Accessor(p1.RemoveMethod); + void ValidateP1Accessor(MethodSymbol accessor) + { + Assert.True(accessor.IsAbstract); + Assert.False(accessor.IsVirtual); + Assert.True(accessor.IsMetadataVirtual()); + Assert.False(accessor.IsSealed); + Assert.False(accessor.IsStatic); + Assert.False(accessor.IsExtern); + Assert.False(accessor.IsAsync); + Assert.False(accessor.IsOverride); + Assert.Equal(Accessibility.Private, accessor.DeclaredAccessibility); + Assert.Null(test1.FindImplementationForInterfaceMember(accessor)); + } + + var p2 = i1.GetMembers().OfType().ElementAt(1); + + Assert.False(p2.IsAbstract); + Assert.True(p2.IsVirtual); + Assert.False(p2.IsSealed); + Assert.False(p2.IsStatic); + Assert.False(p2.IsExtern); + Assert.False(p2.IsOverride); + Assert.Equal(Accessibility.Private, p2.DeclaredAccessibility); + Assert.Same(p2, test1.FindImplementationForInterfaceMember(p2)); + + ValidateP2Accessor(p2.AddMethod); + ValidateP2Accessor(p2.RemoveMethod); + void ValidateP2Accessor(MethodSymbol accessor) + { + Assert.False(accessor.IsAbstract); + Assert.True(accessor.IsVirtual); + Assert.True(accessor.IsMetadataVirtual()); + Assert.False(accessor.IsSealed); + Assert.False(accessor.IsStatic); + Assert.False(accessor.IsExtern); + Assert.False(accessor.IsAsync); + Assert.False(accessor.IsOverride); + Assert.Equal(Accessibility.Private, accessor.DeclaredAccessibility); + Assert.Same(accessor, test1.FindImplementationForInterfaceMember(accessor)); + } + + var p3 = i1.GetMembers().OfType().ElementAt(2); + + Assert.False(p3.IsAbstract); + Assert.False(p3.IsVirtual); + Assert.True(p3.IsSealed); + Assert.False(p3.IsStatic); + Assert.False(p3.IsExtern); + Assert.False(p3.IsOverride); + Assert.Equal(Accessibility.Private, p3.DeclaredAccessibility); + Assert.Null(test1.FindImplementationForInterfaceMember(p3)); + + ValidateP3Accessor(p3.AddMethod); + ValidateP3Accessor(p3.RemoveMethod); + void ValidateP3Accessor(MethodSymbol accessor) + { + Assert.False(accessor.IsAbstract); + Assert.False(accessor.IsVirtual); + Assert.False(accessor.IsMetadataVirtual()); + Assert.True(accessor.IsSealed); + Assert.False(accessor.IsStatic); + Assert.False(accessor.IsExtern); + Assert.False(accessor.IsAsync); + Assert.False(accessor.IsOverride); + Assert.Equal(Accessibility.Private, accessor.DeclaredAccessibility); + Assert.Null(test1.FindImplementationForInterfaceMember(accessor)); + } + + var p4 = i1.GetMembers().OfType().ElementAt(3); + + Assert.False(p4.IsAbstract); + Assert.False(p4.IsVirtual); + Assert.False(p4.IsSealed); + Assert.False(p4.IsStatic); + Assert.False(p4.IsExtern); + Assert.False(p4.IsOverride); + Assert.Equal(Accessibility.Private, p4.DeclaredAccessibility); + Assert.Null(test1.FindImplementationForInterfaceMember(p4)); + + ValidateP4Accessor(p4.AddMethod); + ValidateP4Accessor(p4.RemoveMethod); + void ValidateP4Accessor(MethodSymbol accessor) + { + Assert.False(accessor.IsAbstract); + Assert.False(accessor.IsVirtual); + Assert.False(accessor.IsMetadataVirtual()); + Assert.False(accessor.IsSealed); + Assert.False(accessor.IsStatic); + Assert.False(accessor.IsExtern); + Assert.False(accessor.IsAsync); + Assert.False(accessor.IsOverride); + Assert.Equal(Accessibility.Private, accessor.DeclaredAccessibility); + Assert.Null(test1.FindImplementationForInterfaceMember(accessor)); + } } [Fact] - public void EventModifiers_03() + public void EventModifiers_11_01() { - ValidateEventImplementation_102(@" + var source1 = +@" public interface I1 { - public virtual event System.Action E1 + internal abstract event System.Action P1; + + sealed void Test() { - add => System.Console.WriteLine(""add E1""); - remove => System.Console.WriteLine(""remove E1""); + P1 += null; + P1 -= null; } } +"; + var source2 = +@" class Test1 : I1 -{} -"); - ValidateEventImplementation_102(@" -public interface I1 { - public virtual event System.Action E1 + static void Main() { - add {System.Console.WriteLine(""add E1"");} - remove {System.Console.WriteLine(""remove E1"");} + I1 x = new Test1(); + x.Test(); } -} -class Test1 : I1 -{} -"); + public event System.Action P1 + { + add + { + System.Console.WriteLine(""get_P1""); } - - [Fact] - public void EventModifiers_04() + remove { - ValidateEventImplementation_101(@" -public interface I1 -{ - public virtual event System.Action E1 {} -} - -class Test1 : I1 -{} -", - new[] { - // (4,40): error CS0065: 'I1.E1': event property must have both add and remove accessors - // public virtual event System.Action E1 {} - Diagnostic(ErrorCode.ERR_EventNeedsBothAccessors, "E1").WithArguments("I1.E1").WithLocation(4, 40) - }, - haveAdd: false, haveRemove: false); - - ValidateEventImplementation_101(@" -public interface I1 -{ - public virtual event System.Action E1 - { - add; + System.Console.WriteLine(""set_P1""); + } } } +"; -class Test1 : I1 -{} -", - new[] { - // (6,12): error CS0073: An add or remove accessor must have a body - // add; - Diagnostic(ErrorCode.ERR_AddRemoveMustHaveBody, ";"), - // (4,40): error CS0065: 'I1.E1': event property must have both add and remove accessors - // public virtual event System.Action E1 - Diagnostic(ErrorCode.ERR_EventNeedsBothAccessors, "E1").WithArguments("I1.E1").WithLocation(4, 40) + ValidateEventModifiers_11(source1, source2, + new DiagnosticDescription[] + { + // (2,15): error CS8504: 'Test1' does not implement interface member 'I1.P1.remove'. 'Test1.P1.remove' cannot implicitly implement a non-public member. + // class Test1 : I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test1", "I1.P1.remove", "Test1.P1.remove").WithLocation(2, 15), + // (2,15): error CS8504: 'Test1' does not implement interface member 'I1.P1.add'. 'Test1.P1.add' cannot implicitly implement a non-public member. + // class Test1 : I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test1", "I1.P1.add", "Test1.P1.add").WithLocation(2, 15) }, - haveAdd: true, haveRemove: false); - - ValidateEventImplementation_101(@" -public interface I1 -{ - public virtual event System.Action E1 - { - add {} - } -} + // (2,15): error CS0535: 'Test2' does not implement interface member 'I1.P1' + // class Test2 : I1 + Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test2", "I1.P1").WithLocation(2, 15) + ); + } -class Test1 : I1 -{} -", - new[] { - // (4,40): error CS0065: 'I1.E1': event property must have both add and remove accessors - // public virtual event System.Action E1 - Diagnostic(ErrorCode.ERR_EventNeedsBothAccessors, "E1").WithArguments("I1.E1").WithLocation(4, 40) - }, - haveAdd: true, haveRemove: false); + private void ValidateEventModifiers_11(string source1, string source2, DiagnosticDescription[] expected1, params DiagnosticDescription[] expected2) + { + var compilation1 = CreateStandardCompilation(source2 + source1, options: TestOptions.DebugExe, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation1.VerifyDiagnostics(expected1); + Validate1(compilation1.SourceModule); - ValidateEventImplementation_101(@" -public interface I1 -{ - public virtual event System.Action E1 - { - add => throw null; - } -} + void Validate1(ModuleSymbol m) + { + var test1 = m.GlobalNamespace.GetTypeMember("Test1"); + var i1 = test1.Interfaces.Single(); + var p1 = GetSingleEvent(i1); + var test1P1 = GetSingleEvent(test1); + var p1add = p1.AddMethod; + var p1remove = p1.RemoveMethod; -class Test1 : I1 -{} -", - new[] { - // (4,40): error CS0065: 'I1.E1': event property must have both add and remove accessors - // public virtual event System.Action E1 - Diagnostic(ErrorCode.ERR_EventNeedsBothAccessors, "E1").WithArguments("I1.E1").WithLocation(4, 40) - }, - haveAdd: true, haveRemove: false); + ValidateEvent(p1); + ValidateMethod(p1add); + ValidateMethod(p1remove); + Assert.Same(test1P1, test1.FindImplementationForInterfaceMember(p1)); + Assert.Same(test1P1.AddMethod, test1.FindImplementationForInterfaceMember(p1add)); + Assert.Same(test1P1.RemoveMethod, test1.FindImplementationForInterfaceMember(p1remove)); + } - ValidateEventImplementation_101(@" -public interface I1 -{ - public virtual event System.Action E1 - { - remove; - } -} + void ValidateEvent(EventSymbol p1) + { + Assert.True(p1.IsAbstract); + Assert.False(p1.IsVirtual); + Assert.False(p1.IsSealed); + Assert.False(p1.IsStatic); + Assert.False(p1.IsExtern); + Assert.False(p1.IsOverride); + Assert.Equal(Accessibility.Internal, p1.DeclaredAccessibility); + } -class Test1 : I1 -{} -", - new[] { - // (6,15): error CS0073: An add or remove accessor must have a body - // remove; - Diagnostic(ErrorCode.ERR_AddRemoveMustHaveBody, ";").WithLocation(6, 15), - // (4,40): error CS0065: 'I1.E1': event property must have both add and remove accessors - // public virtual event System.Action E1 - Diagnostic(ErrorCode.ERR_EventNeedsBothAccessors, "E1").WithArguments("I1.E1").WithLocation(4, 40) - }, - haveAdd: false, haveRemove: true); + void ValidateMethod(MethodSymbol m1) + { + Assert.True(m1.IsAbstract); + Assert.False(m1.IsVirtual); + Assert.True(m1.IsMetadataVirtual()); + Assert.False(m1.IsSealed); + Assert.False(m1.IsStatic); + Assert.False(m1.IsExtern); + Assert.False(m1.IsAsync); + Assert.False(m1.IsOverride); + Assert.Equal(Accessibility.Internal, m1.DeclaredAccessibility); + } - ValidateEventImplementation_101(@" -public interface I1 -{ - public virtual event System.Action E1 - { - remove {} - } -} + var compilation2 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation2.VerifyDiagnostics(); -class Test1 : I1 -{} -", - new[] { - // (4,40): error CS0065: 'I1.E1': event property must have both add and remove accessors - // public virtual event System.Action E1 - Diagnostic(ErrorCode.ERR_EventNeedsBothAccessors, "E1").WithArguments("I1.E1").WithLocation(4, 40) - }, - haveAdd: false, haveRemove: true); + { + var i1 = compilation2.GetTypeByMetadataName("I1"); + var p1 = GetSingleEvent(i1); + ValidateEvent(p1); + ValidateMethod(p1.AddMethod); + ValidateMethod(p1.RemoveMethod); + } - ValidateEventImplementation_101(@" -public interface I1 -{ - public virtual event System.Action E1 - { - remove => throw null; - } -} + var compilation3 = CreateStandardCompilation(source2, new[] { compilation2.ToMetadataReference() }, options: TestOptions.DebugExe, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation3.VerifyDiagnostics(expected1); -class Test1 : I1 -{} -", - new[] { - // (4,40): error CS0065: 'I1.E1': event property must have both add and remove accessors - // public virtual event System.Action E1 - Diagnostic(ErrorCode.ERR_EventNeedsBothAccessors, "E1").WithArguments("I1.E1").WithLocation(4, 40) - }, - haveAdd: false, haveRemove: true); + Validate1(compilation3.SourceModule); - ValidateEventImplementation_101(@" -public interface I1 -{ - public virtual event System.Action E1 - { - add; - remove; - } -} + var compilation4 = CreateStandardCompilation(source2, new[] { compilation2.EmitToImageReference() }, options: TestOptions.DebugExe, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation4.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation4.VerifyDiagnostics(expected1); -class Test1 : I1 -{} -", - new[] { - // (6,12): error CS0073: An add or remove accessor must have a body - // add; - Diagnostic(ErrorCode.ERR_AddRemoveMustHaveBody, ";"), - // (7,15): error CS0073: An add or remove accessor must have a body - // remove; - Diagnostic(ErrorCode.ERR_AddRemoveMustHaveBody, ";").WithLocation(7, 15) - }, - haveAdd: true, haveRemove: true); + Validate1(compilation4.SourceModule); - ValidateEventImplementation_101(@" -public interface I1 + var source3 = +@" +class Test2 : I1 { - public virtual event System.Action E1; } +"; -class Test1 : I1 -{} -", - new[] { - // (4,40): error CS0065: 'I1.E1': event property must have both add and remove accessors - // public virtual event System.Action E1; - Diagnostic(ErrorCode.ERR_EventNeedsBothAccessors, "E1").WithArguments("I1.E1").WithLocation(4, 40) - }, - haveAdd: true, haveRemove: true); + var compilation5 = CreateStandardCompilation(source3, new[] { compilation2.ToMetadataReference() }, options: TestOptions.DebugDll, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation5.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation5.VerifyDiagnostics(expected2); - ValidateEventImplementation_101(@" -public interface I1 -{ - public virtual event System.Action E1 = null; -} + ValidateEventNotImplemented_11(compilation5, "Test2"); -class Test1 : I1 -{} -", - new[] { - // (4,40): error CS0068: 'I1.E1': event in interface cannot have initializer - // public virtual event System.Action E1 = null; - Diagnostic(ErrorCode.ERR_InterfaceEventInitializer, "E1").WithArguments("I1.E1").WithLocation(4, 40), - // (4,40): error CS0065: 'I1.E1': event property must have both add and remove accessors - // public virtual event System.Action E1 = null; - Diagnostic(ErrorCode.ERR_EventNeedsBothAccessors, "E1").WithArguments("I1.E1").WithLocation(4, 40), - // (4,40): warning CS0067: The event 'I1.E1' is never used - // public virtual event System.Action E1 = null; - Diagnostic(ErrorCode.WRN_UnreferencedEvent, "E1").WithArguments("I1.E1").WithLocation(4, 40) - }, - haveAdd: true, haveRemove: true); + var compilation6 = CreateStandardCompilation(source3, new[] { compilation2.EmitToImageReference() }, options: TestOptions.DebugDll, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation6.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation6.VerifyDiagnostics(expected2); + + ValidateEventNotImplemented_11(compilation6, "Test2"); + } + + private static void ValidateEventNotImplemented_11(CSharpCompilation compilation, string className) + { + var test2 = compilation.GetTypeByMetadataName(className); + var i1 = compilation.GetTypeByMetadataName("I1"); + var p1 = GetSingleEvent(i1); + Assert.Null(test2.FindImplementationForInterfaceMember(p1)); + Assert.Null(test2.FindImplementationForInterfaceMember(p1.AddMethod)); + Assert.Null(test2.FindImplementationForInterfaceMember(p1.RemoveMethod)); } [Fact] - public void EventModifiers_05() + public void EventModifiers_11_02() { var source1 = @" public interface I1 { - public abstract event System.Action P1; + internal abstract event System.Action P1; } -public interface I2 + +public class TestHelper { - event System.Action P2; + public static void CallP1(I1 x) + { + x.P1 += null; + x.P1 -= null; + } } +"; + var source2 = +@" class Test1 : I1 { - public event System.Action P1 + static void Main() + { + TestHelper.CallP1(new Test1()); + } + + public virtual event System.Action P1 { add { System.Console.WriteLine(""get_P1""); } - remove => System.Console.WriteLine(""set_P1""); - } -} -class Test2 : I2 -{ - public event System.Action P2 - { - add + remove { - System.Console.WriteLine(""get_P2""); + System.Console.WriteLine(""set_P1""); } - remove => System.Console.WriteLine(""set_P2""); - } - - static void Main() - { - I1 x = new Test1(); - x.P1 += null; - x.P1 -= null; - I2 y = new Test2(); - y.P2 += null; - y.P2 -= null; } } "; - ValidateEventModifiers_05(source1); + ValidateEventModifiers_11_02(source1, source2, + // (2,15): error CS8504: 'Test1' does not implement interface member 'I1.P1.remove'. 'Test1.P1.remove' cannot implicitly implement a non-public member. + // class Test1 : I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test1", "I1.P1.remove", "Test1.P1.remove").WithLocation(2, 15), + // (2,15): error CS8504: 'Test1' does not implement interface member 'I1.P1.add'. 'Test1.P1.add' cannot implicitly implement a non-public member. + // class Test1 : I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test1", "I1.P1.add", "Test1.P1.add").WithLocation(2, 15) + ); } - private void ValidateEventModifiers_05(string source1) + private void ValidateEventModifiers_11_02(string source1, string source2, + params DiagnosticDescription[] expected) { - var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugExe, + var compilation1 = CreateStandardCompilation(source2 + source1, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation1.VerifyDiagnostics(expected); - CompileAndVerify(compilation1, expectedOutput: -@"get_P1 -set_P1 -get_P2 -set_P2", symbolValidator: Validate); + ValidateEventImplementation_11(compilation1.SourceModule); - Validate(compilation1.SourceModule); + var compilation2 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation2.VerifyDiagnostics(); - void Validate(ModuleSymbol m) - { - for (int i = 1; i <= 2; i++) - { - var test1 = m.GlobalNamespace.GetTypeMember("Test" + i); - var i1 = m.GlobalNamespace.GetTypeMember("I" + i); - var p1 = GetSingleEvent(i1); - var test1P1 = GetSingleEvent(test1); + var compilation3 = CreateStandardCompilation(source2, new[] { compilation2.ToMetadataReference() }, options: TestOptions.DebugExe, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation3.VerifyDiagnostics(expected); - Assert.True(p1.IsAbstract); - Assert.False(p1.IsVirtual); - Assert.False(p1.IsSealed); - Assert.False(p1.IsStatic); - Assert.False(p1.IsExtern); - Assert.False(p1.IsOverride); - Assert.Equal(Accessibility.Public, p1.DeclaredAccessibility); - Assert.Same(test1P1, test1.FindImplementationForInterfaceMember(p1)); + ValidateEventImplementation_11(compilation3.SourceModule); - ValidateAccessor(p1.AddMethod, test1P1.AddMethod); - ValidateAccessor(p1.RemoveMethod, test1P1.RemoveMethod); + var compilation4 = CreateStandardCompilation(source2, new[] { compilation2.EmitToImageReference() }, options: TestOptions.DebugExe, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation4.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation4.VerifyDiagnostics(expected); - void ValidateAccessor(MethodSymbol accessor, MethodSymbol implementation) - { - Assert.True(accessor.IsAbstract); - Assert.False(accessor.IsVirtual); - Assert.True(accessor.IsMetadataVirtual()); - Assert.False(accessor.IsSealed); - Assert.False(accessor.IsStatic); - Assert.False(accessor.IsExtern); - Assert.False(accessor.IsAsync); - Assert.False(accessor.IsOverride); - Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); - Assert.Same(implementation, test1.FindImplementationForInterfaceMember(accessor)); - } - } - } + ValidateEventImplementation_11(compilation4.SourceModule); } - private static EventSymbol GetSingleEvent(NamedTypeSymbol container) + private static void ValidateEventImplementation_11(ModuleSymbol m) { - return container.GetMembers().OfType().Single(); + ValidateEventImplementation_11(m, implementedByBase: false); } - private static EventSymbol GetSingleEvent(CSharpCompilation compilation, string containerName) + private static void ValidateEventImplementationByBase_11(ModuleSymbol m) { - return GetSingleEvent(compilation.GetTypeByMetadataName(containerName)); + ValidateEventImplementation_11(m, implementedByBase: true); } - private static EventSymbol GetSingleEvent(ModuleSymbol m, string containerName) + private static void ValidateEventImplementation_11(ModuleSymbol m, bool implementedByBase) { - return GetSingleEvent(m.GlobalNamespace.GetTypeMember(containerName)); + var test1 = m.GlobalNamespace.GetTypeMember("Test1"); + var i1 = test1.Interfaces.Where(i => i.Name == "I1").Single(); + var p1 = GetSingleEvent(i1); + var test1P1 = GetSingleEvent(implementedByBase ? test1.BaseType : test1); + var p1Add = p1.AddMethod; + var p1Remove = p1.RemoveMethod; + + Assert.Same(test1P1, test1.FindImplementationForInterfaceMember(p1)); + + Assert.Same(test1P1.AddMethod, test1.FindImplementationForInterfaceMember(p1Add)); + Assert.Same(test1P1.RemoveMethod, test1.FindImplementationForInterfaceMember(p1Remove)); + + var i2 = test1.Interfaces.Where(i => i.Name == "I2").SingleOrDefault(); + bool isMetadataVirtual = test1P1.IsVirtual || test1P1.IsAbstract || test1P1.IsExplicitInterfaceImplementation || + (!implementedByBase && (object)i2 != null && (object)test1P1 == test1.FindImplementationForInterfaceMember(GetSingleEvent(i2))); + Assert.Equal(isMetadataVirtual, test1P1.AddMethod.IsMetadataVirtual()); + Assert.Equal(isMetadataVirtual, test1P1.RemoveMethod.IsMetadataVirtual()); } [Fact] - public void EventModifiers_06() + public void EventModifiers_11_03() { var source1 = @" public interface I1 { - public abstract event System.Action P1; + internal abstract event System.Action P1; } -"; - var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, - parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp7)); - Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); - compilation1.VerifyDiagnostics( - // (4,41): error CS8503: The modifier 'abstract' is not valid for this item in C# 7. Please use language version 7.1 or greater. - // public abstract event System.Action P1; - Diagnostic(ErrorCode.ERR_DefaultInterfaceImplementationModifier, "P1").WithArguments("abstract", "7", "7.1").WithLocation(4, 41), - // (4,41): error CS8503: The modifier 'public' is not valid for this item in C# 7. Please use language version 7.1 or greater. - // public abstract event System.Action P1; - Diagnostic(ErrorCode.ERR_DefaultInterfaceImplementationModifier, "P1").WithArguments("public", "7", "7.1").WithLocation(4, 41) - ); - - ValidateEventModifiers_06(compilation1); - } - - private static void ValidateEventModifiers_06(CSharpCompilation compilation1) - { - var i1 = compilation1.GetTypeByMetadataName("I1"); - var p1 = i1.GetMember("P1"); - - Assert.True(p1.IsAbstract); - Assert.False(p1.IsVirtual); - Assert.False(p1.IsSealed); - Assert.False(p1.IsStatic); - Assert.False(p1.IsExtern); - Assert.False(p1.IsOverride); - Assert.Equal(Accessibility.Public, p1.DeclaredAccessibility); - - ValidateAccessor(p1.AddMethod); - ValidateAccessor(p1.RemoveMethod); - void ValidateAccessor(MethodSymbol accessor) - { - Assert.True(accessor.IsAbstract); - Assert.False(accessor.IsVirtual); - Assert.True(accessor.IsMetadataVirtual()); - Assert.False(accessor.IsSealed); - Assert.False(accessor.IsStatic); - Assert.False(accessor.IsExtern); - Assert.False(accessor.IsAsync); - Assert.False(accessor.IsOverride); - Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); - } - } +public class TestHelper +{ + public static void CallP1(I1 x) + { + x.P1 += null; + x.P1 -= null; + } +} +"; - [Fact] - public void EventModifiers_07() - { - var source1 = + var source2 = @" -public interface I1 +class Test1 : I1 { - public static event System.Action P1 + static void Main() { - add - { - System.Console.WriteLine(""get_P1""); - } - remove - { - System.Console.WriteLine(""set_P1""); - } + TestHelper.CallP1(new Test1()); } - internal static event System.Action P2 + event System.Action I1.P1 { add { - System.Console.WriteLine(""get_P2""); - P3 += value; + System.Console.WriteLine(""get_P1""); } remove { - System.Console.WriteLine(""set_P2""); - P3 -= value; + System.Console.WriteLine(""set_P1""); } } - - private static event System.Action P3 - { - add => System.Console.WriteLine(""get_P3""); - remove => System.Console.WriteLine(""set_P3""); - } -} - -class Test1 : I1 -{ - static void Main() - { - I1.P1 += null; - I1.P1 -= null; - I1.P2 += null; - I1.P2 -= null; - } } "; - var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All), + + ValidateEventModifiers_11_03(source1, source2, + // (9,28): error CS0122: 'I1.P1' is inaccessible due to its protection level + // event System.Action I1.P1 + Diagnostic(ErrorCode.ERR_BadAccess, "P1").WithArguments("I1.P1").WithLocation(9, 28) + ); + } + + private void ValidateEventModifiers_11_03(string source1, string source2, + params DiagnosticDescription[] expected) + { + var compilation1 = CreateStandardCompilation(source2 + source1, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); CompileAndVerify(compilation1, expectedOutput: @"get_P1 -set_P1 -get_P2 -get_P3 -set_P2 -set_P3", symbolValidator: Validate); +set_P1", verify: false, symbolValidator: ValidateEventImplementation_11); - Validate(compilation1.SourceModule); + ValidateEventImplementation_11(compilation1.SourceModule); - void Validate(ModuleSymbol m) - { - var test1 = m.GlobalNamespace.GetTypeMember("Test1"); - var i1 = m.GlobalNamespace.GetTypeMember("I1"); + var compilation2 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation2.VerifyDiagnostics(); - foreach (var tuple in new[] { (name: "P1", access: Accessibility.Public), - (name: "P2", access: Accessibility.Internal), - (name: "P3", access: Accessibility.Private)}) - { - var p1 = i1.GetMember(tuple.name); + var compilation3 = CreateStandardCompilation(source2, new[] { compilation2.ToMetadataReference() }, options: TestOptions.DebugExe, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation3.VerifyDiagnostics(expected); - Assert.False(p1.IsAbstract); - Assert.False(p1.IsVirtual); - Assert.False(p1.IsSealed); - Assert.True(p1.IsStatic); - Assert.False(p1.IsExtern); - Assert.False(p1.IsOverride); - Assert.Equal(tuple.access, p1.DeclaredAccessibility); - Assert.Null(test1.FindImplementationForInterfaceMember(p1)); + ValidateEventImplementation_11(compilation3.SourceModule); - ValidateAccessor(p1.AddMethod); - ValidateAccessor(p1.RemoveMethod); + var compilation4 = CreateStandardCompilation(source2, new[] { compilation2.EmitToImageReference() }, options: TestOptions.DebugExe, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation4.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation4.VerifyDiagnostics(expected); - void ValidateAccessor(MethodSymbol accessor) - { - Assert.False(accessor.IsAbstract); - Assert.False(accessor.IsVirtual); - Assert.False(accessor.IsMetadataVirtual()); - Assert.False(accessor.IsSealed); - Assert.True(accessor.IsStatic); - Assert.False(accessor.IsExtern); - Assert.False(accessor.IsAsync); - Assert.False(accessor.IsOverride); - Assert.Equal(tuple.access, accessor.DeclaredAccessibility); - Assert.Null(test1.FindImplementationForInterfaceMember(accessor)); - } - } - } + ValidateEventImplementation_11(compilation4.SourceModule); + } - var source2 = + [Fact] + public void EventModifiers_11_04() + { + var source1 = @" public interface I1 { - public static event System.Action P1; + internal abstract event System.Action P1; +} - internal static event System.Action P2 +public class TestHelper +{ + public static void CallP1(I1 x) { - add; - remove; + x.P1 += null; + x.P1 -= null; } +} - private static event System.Action P3 = null; +public class Test2 : I1 +{ + event System.Action I1.P1 + { + add + { + System.Console.WriteLine(""Test2.get_P1""); + } + remove + { + System.Console.WriteLine(""Test2.set_P1""); + } + } } +"; -class Test1 : I1 + var source2 = +@" +class Test1 : Test2, I1 { static void Main() { + TestHelper.CallP1(new Test1()); + } + + public event System.Action P1 + { + add + { + System.Console.WriteLine(""Test1.get_P1""); + } + remove + { + System.Console.WriteLine(""Test1.set_P1""); + } } } "; - var compilation2 = CreateStandardCompilation(source2, options: TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All), - parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); - Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); - compilation2.VerifyDiagnostics( - // (8,12): error CS0073: An add or remove accessor must have a body - // add; - Diagnostic(ErrorCode.ERR_AddRemoveMustHaveBody, ";").WithLocation(8, 12), - // (9,15): error CS0073: An add or remove accessor must have a body - // remove; - Diagnostic(ErrorCode.ERR_AddRemoveMustHaveBody, ";").WithLocation(9, 15), - // (4,39): error CS0065: 'I1.P1': event property must have both add and remove accessors - // public static event System.Action P1; - Diagnostic(ErrorCode.ERR_EventNeedsBothAccessors, "P1").WithArguments("I1.P1").WithLocation(4, 39), - // (12,40): error CS0068: 'I1.P3': event in interface cannot have initializer - // private static event System.Action P3 = null; - Diagnostic(ErrorCode.ERR_InterfaceEventInitializer, "P3").WithArguments("I1.P3").WithLocation(12, 40), - // (12,40): error CS0065: 'I1.P3': event property must have both add and remove accessors - // private static event System.Action P3 = null; - Diagnostic(ErrorCode.ERR_EventNeedsBothAccessors, "P3").WithArguments("I1.P3").WithLocation(12, 40), - // (12,40): warning CS0067: The event 'I1.P3' is never used - // private static event System.Action P3 = null; - Diagnostic(ErrorCode.WRN_UnreferencedEvent, "P3").WithArguments("I1.P3").WithLocation(12, 40) - ); - Validate(compilation2.SourceModule); + ValidateEventModifiers_11_02(source1, source2, + // (2,22): error CS8504: 'Test1' does not implement interface member 'I1.P1.remove'. 'Test1.P1.remove' cannot implicitly implement a non-public member. + // class Test1 : Test2, I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test1", "I1.P1.remove", "Test1.P1.remove").WithLocation(2, 22), + // (2,22): error CS8504: 'Test1' does not implement interface member 'I1.P1.add'. 'Test1.P1.add' cannot implicitly implement a non-public member. + // class Test1 : Test2, I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test1", "I1.P1.add", "Test1.P1.add").WithLocation(2, 22) + ); } [Fact] - public void EventModifiers_08() + public void EventModifiers_11_05() { var source1 = @" public interface I1 { - abstract static event System.Action P1; - - virtual static event System.Action P2 {add {} remove{}} - - sealed static event System.Action P3 {add; remove;} + internal abstract event System.Action P1; } -class Test1 : I1 +public class TestHelper { - event System.Action I1.P1 {add {} remove{}} - event System.Action I1.P2 {add {} remove{}} - event System.Action I1.P3 {add {} remove{}} + public static void CallP1(I1 x) + { + x.P1 += null; + x.P1 -= null; + } } -class Test2 : I1 -{} +public class Test2 : I1 +{ + event System.Action I1.P1 + { + add + { + System.Console.WriteLine(""Test2.get_P1""); + } + remove + { + System.Console.WriteLine(""Test2.set_P1""); + } + } +} "; - var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, - parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); - Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); - compilation1.VerifyDiagnostics( - // (8,46): error CS0073: An add or remove accessor must have a body - // sealed static event System.Action P3 {add; remove;} - Diagnostic(ErrorCode.ERR_AddRemoveMustHaveBody, ";").WithLocation(8, 46), - // (8,54): error CS0073: An add or remove accessor must have a body - // sealed static event System.Action P3 {add; remove;} - Diagnostic(ErrorCode.ERR_AddRemoveMustHaveBody, ";").WithLocation(8, 54), - // (6,40): error CS0112: A static member 'I1.P2' cannot be marked as override, virtual, or abstract - // virtual static event System.Action P2 {add {} remove{}} - Diagnostic(ErrorCode.ERR_StaticNotVirtual, "P2").WithArguments("I1.P2").WithLocation(6, 40), - // (8,39): error CS0238: 'I1.P3' cannot be sealed because it is not an override - // sealed static event System.Action P3 {add; remove;} - Diagnostic(ErrorCode.ERR_SealedNonOverride, "P3").WithArguments("I1.P3").WithLocation(8, 39), - // (4,41): error CS0112: A static member 'I1.P1' cannot be marked as override, virtual, or abstract - // abstract static event System.Action P1; - Diagnostic(ErrorCode.ERR_StaticNotVirtual, "P1").WithArguments("I1.P1").WithLocation(4, 41), - // (13,28): error CS0539: 'Test1.P1' in explicit interface declaration is not found among members of the interface that can be implemented - // event System.Action I1.P1 {add {} remove{}} - Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "P1").WithArguments("Test1.P1").WithLocation(13, 28), - // (14,28): error CS0539: 'Test1.P2' in explicit interface declaration is not found among members of the interface that can be implemented - // event System.Action I1.P2 {add {} remove{}} - Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "P2").WithArguments("Test1.P2").WithLocation(14, 28), - // (15,28): error CS0539: 'Test1.P3' in explicit interface declaration is not found among members of the interface that can be implemented - // event System.Action I1.P3 {add {} remove{}} - Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "P3").WithArguments("Test1.P3").WithLocation(15, 28) - ); - - var test1 = compilation1.GetTypeByMetadataName("Test1"); - var i1 = compilation1.GetTypeByMetadataName("I1"); - var p1 = i1.GetMember("P1"); - - Assert.True(p1.IsAbstract); - Assert.False(p1.IsVirtual); - Assert.False(p1.IsSealed); - Assert.True(p1.IsStatic); - Assert.False(p1.IsExtern); - Assert.False(p1.IsOverride); - Assert.Equal(Accessibility.Public, p1.DeclaredAccessibility); - Assert.Null(test1.FindImplementationForInterfaceMember(p1)); - - ValidateAccessor1(p1.AddMethod); - ValidateAccessor1(p1.RemoveMethod); - void ValidateAccessor1(MethodSymbol accessor) - { - Assert.True(accessor.IsAbstract); - Assert.False(accessor.IsVirtual); - Assert.True(accessor.IsMetadataVirtual()); - Assert.False(accessor.IsSealed); - Assert.True(accessor.IsStatic); - Assert.False(accessor.IsExtern); - Assert.False(accessor.IsAsync); - Assert.False(accessor.IsOverride); - Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); - Assert.Null(test1.FindImplementationForInterfaceMember(accessor)); - } - - var p2 = i1.GetMember("P2"); - - Assert.False(p2.IsAbstract); - Assert.True(p2.IsVirtual); - Assert.False(p2.IsSealed); - Assert.True(p2.IsStatic); - Assert.False(p2.IsExtern); - Assert.False(p2.IsOverride); - Assert.Equal(Accessibility.Public, p2.DeclaredAccessibility); - Assert.Null(test1.FindImplementationForInterfaceMember(p2)); - - ValidateAccessor2(p2.AddMethod); - ValidateAccessor2(p2.RemoveMethod); - void ValidateAccessor2(MethodSymbol accessor) - { - Assert.False(accessor.IsAbstract); - Assert.True(accessor.IsVirtual); - Assert.True(accessor.IsMetadataVirtual()); - Assert.False(accessor.IsSealed); - Assert.True(accessor.IsStatic); - Assert.False(accessor.IsExtern); - Assert.False(accessor.IsAsync); - Assert.False(accessor.IsOverride); - Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); - Assert.Null(test1.FindImplementationForInterfaceMember(accessor)); - } - var p3 = i1.GetMember("P3"); + var source2 = +@" +class Test1 : Test2, I1 +{ + static void Main() + { + TestHelper.CallP1(new Test1()); + } - Assert.False(p3.IsAbstract); - Assert.False(p3.IsVirtual); - Assert.True(p3.IsSealed); - Assert.True(p3.IsStatic); - Assert.False(p3.IsExtern); - Assert.False(p3.IsOverride); - Assert.Equal(Accessibility.Public, p3.DeclaredAccessibility); - Assert.Null(test1.FindImplementationForInterfaceMember(p3)); + public virtual event System.Action P1 + { + add + { + System.Console.WriteLine(""Test1.get_P1""); + } + remove + { + System.Console.WriteLine(""Test1.set_P1""); + } + } +} +"; - ValidateAccessor3(p3.AddMethod); - ValidateAccessor3(p3.RemoveMethod); - void ValidateAccessor3(MethodSymbol accessor) - { - Assert.False(accessor.IsAbstract); - Assert.False(accessor.IsVirtual); - Assert.False(accessor.IsMetadataVirtual()); - Assert.True(accessor.IsSealed); - Assert.True(accessor.IsStatic); - Assert.False(accessor.IsExtern); - Assert.False(accessor.IsAsync); - Assert.False(accessor.IsOverride); - Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); - Assert.Null(test1.FindImplementationForInterfaceMember(accessor)); - } + ValidateEventModifiers_11_02(source1, source2, + // (2,22): error CS8504: 'Test1' does not implement interface member 'I1.P1.remove'. 'Test1.P1.remove' cannot implicitly implement a non-public member. + // class Test1 : Test2, I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test1", "I1.P1.remove", "Test1.P1.remove").WithLocation(2, 22), + // (2,22): error CS8504: 'Test1' does not implement interface member 'I1.P1.add'. 'Test1.P1.add' cannot implicitly implement a non-public member. + // class Test1 : Test2, I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test1", "I1.P1.add", "Test1.P1.add").WithLocation(2, 22) + ); } [Fact] - public void EventModifiers_09() + public void EventModifiers_11_06() { var source1 = @" public interface I1 { - private event System.Action P1 - { - add - { - System.Console.WriteLine(""get_P1""); - } - remove - { - System.Console.WriteLine(""set_P1""); - } - } - sealed void M() - { - P1 += null; - P1 -= null; - } + internal abstract event System.Action P1; } -public interface I2 + +public class TestHelper { - private event System.Action P2 + public static void CallP1(I1 x) { - add => System.Console.WriteLine(""get_P2""); - remove => System.Console.WriteLine(""set_P2""); + x.P1 += null; + x.P1 -= null; } +} - sealed void M() +public class Test2 : I1 +{ + event System.Action I1.P1 { - P2 += null; - P2 -= null; + add + { + System.Console.WriteLine(""Test2.get_P1""); + } + remove + { + System.Console.WriteLine(""Test2.set_P1""); + } } } +"; -class Test1 : I1, I2 + var source2 = +@"abstract +class Test1 : Test2, I1 { static void Main() { - I1 x1 = new Test1(); - x1.M(); - I2 x2 = new Test1(); - x2.M(); + TestHelper.CallP1(new Test3()); } + + public abstract event System.Action P1; } -"; - ValidateEventModifiers_09(source1); +class Test3 : Test1 +{ + public override event System.Action P1 + { + add + { + System.Console.WriteLine(""Test3.get_P1""); } - - private void ValidateEventModifiers_09(string source1) + remove { - var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All), - parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); - Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); - CompileAndVerify(compilation1, verify: false, symbolValidator: Validate); - - Validate(compilation1.SourceModule); - - void Validate(ModuleSymbol m) - { - var test1 = m.GlobalNamespace.GetTypeMember("Test1"); - - for (int i = 1; i <= 2; i++) - { - var i1 = m.GlobalNamespace.GetTypeMember("I" + i); - var p1 = GetSingleEvent(i1); - - Assert.False(p1.IsAbstract); - Assert.False(p1.IsVirtual); - Assert.False(p1.IsSealed); - Assert.False(p1.IsStatic); - Assert.False(p1.IsExtern); - Assert.False(p1.IsOverride); - Assert.Equal(Accessibility.Private, p1.DeclaredAccessibility); - Assert.Null(test1.FindImplementationForInterfaceMember(p1)); + System.Console.WriteLine(""Test3.set_P1""); + } + } +} - ValidateAccessor(p1.AddMethod); - ValidateAccessor(p1.RemoveMethod); +"; - void ValidateAccessor(MethodSymbol accessor) - { - Assert.False(accessor.IsAbstract); - Assert.False(accessor.IsVirtual); - Assert.False(accessor.IsMetadataVirtual()); - Assert.False(accessor.IsSealed); - Assert.False(accessor.IsStatic); - Assert.False(accessor.IsExtern); - Assert.False(accessor.IsAsync); - Assert.False(accessor.IsOverride); - Assert.Equal(Accessibility.Private, accessor.DeclaredAccessibility); - Assert.Null(test1.FindImplementationForInterfaceMember(accessor)); - } - } - } + ValidateEventModifiers_11_02(source1, source2, + // (2,22): error CS8504: 'Test1' does not implement interface member 'I1.P1.remove'. 'Test1.P1.remove' cannot implicitly implement a non-public member. + // class Test1 : Test2, I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test1", "I1.P1.remove", "Test1.P1.remove").WithLocation(2, 22), + // (2,22): error CS8504: 'Test1' does not implement interface member 'I1.P1.add'. 'Test1.P1.add' cannot implicitly implement a non-public member. + // class Test1 : Test2, I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test1", "I1.P1.add", "Test1.P1.add").WithLocation(2, 22) + ); } [Fact] - public void EventModifiers_10() + public void EventModifiers_11_07() { var source1 = @" public interface I1 { - abstract private event System.Action P1; + internal abstract event System.Action P1; +} - virtual private event System.Action P2; +public class TestHelper +{ + public static void CallP1(I1 x) + { + x.P1 += null; + x.P1 -= null; + } +} - sealed private event System.Action P3 +public class Test2 : I1 +{ + event System.Action I1.P1 { - add => throw null; - remove {} + add + { + System.Console.WriteLine(""Test2.get_P1""); + } + remove + { + System.Console.WriteLine(""Test2.set_P1""); + } + } +} +"; + + var source2 = +@" +class Test1 : Test2, I1, I2 +{ + static void Main() + { + TestHelper.CallP1(new Test1()); } - private event System.Action P4 = null; + public event System.Action P1 + { + add + { + System.Console.WriteLine(""Test1.get_P1""); + } + remove + { + System.Console.WriteLine(""Test1.set_P1""); + } + } } -class Test1 : I1 +public interface I2 { + event System.Action P1; } "; - var compilation1 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, - parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); - Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); - compilation1.VerifyDiagnostics( - // (4,42): error CS0621: 'I1.P1': virtual or abstract members cannot be private - // abstract private event System.Action P1; - Diagnostic(ErrorCode.ERR_VirtualPrivate, "P1").WithArguments("I1.P1").WithLocation(4, 42), - // (6,41): error CS0065: 'I1.P2': event property must have both add and remove accessors - // virtual private event System.Action P2; - Diagnostic(ErrorCode.ERR_EventNeedsBothAccessors, "P2").WithArguments("I1.P2").WithLocation(6, 41), - // (6,41): error CS0621: 'I1.P2': virtual or abstract members cannot be private - // virtual private event System.Action P2; - Diagnostic(ErrorCode.ERR_VirtualPrivate, "P2").WithArguments("I1.P2").WithLocation(6, 41), - // (8,40): error CS0238: 'I1.P3' cannot be sealed because it is not an override - // sealed private event System.Action P3 - Diagnostic(ErrorCode.ERR_SealedNonOverride, "P3").WithArguments("I1.P3").WithLocation(8, 40), - // (14,33): error CS0068: 'I1.P4': event in interface cannot have initializer - // private event System.Action P4 = null; - Diagnostic(ErrorCode.ERR_InterfaceEventInitializer, "P4").WithArguments("I1.P4").WithLocation(14, 33), - // (14,33): error CS0065: 'I1.P4': event property must have both add and remove accessors - // private event System.Action P4 = null; - Diagnostic(ErrorCode.ERR_EventNeedsBothAccessors, "P4").WithArguments("I1.P4").WithLocation(14, 33), - // (17,15): error CS0535: 'Test1' does not implement interface member 'I1.P1' - // class Test1 : I1 - Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test1", "I1.P1"), - // (14,33): warning CS0067: The event 'I1.P4' is never used - // private event System.Action P4 = null; - Diagnostic(ErrorCode.WRN_UnreferencedEvent, "P4").WithArguments("I1.P4").WithLocation(14, 33) - ); - ValidateEventModifiers_10(compilation1); + ValidateEventModifiers_11_02(source1, source2, + // (2,22): error CS8504: 'Test1' does not implement interface member 'I1.P1.remove'. 'Test1.P1.remove' cannot implicitly implement a non-public member. + // class Test1 : Test2, I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test1", "I1.P1.remove", "Test1.P1.remove").WithLocation(2, 22), + // (2,22): error CS8504: 'Test1' does not implement interface member 'I1.P1.add'. 'Test1.P1.add' cannot implicitly implement a non-public member. + // class Test1 : Test2, I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test1", "I1.P1.add", "Test1.P1.add").WithLocation(2, 22) + ); } - private static void ValidateEventModifiers_10(CSharpCompilation compilation1) + [Fact] + public void EventModifiers_11_08() { - var test1 = compilation1.GetTypeByMetadataName("Test1"); - var i1 = compilation1.GetTypeByMetadataName("I1"); - var p1 = i1.GetMembers().OfType().ElementAt(0); + var source1 = +@" +public interface I1 +{ + internal abstract event System.Action P1; +} - Assert.True(p1.IsAbstract); - Assert.False(p1.IsVirtual); - Assert.False(p1.IsSealed); - Assert.False(p1.IsStatic); - Assert.False(p1.IsExtern); - Assert.False(p1.IsOverride); - Assert.Equal(Accessibility.Private, p1.DeclaredAccessibility); - Assert.Null(test1.FindImplementationForInterfaceMember(p1)); +public class TestHelper +{ + public static void CallP1(I1 x) + { + x.P1 += null; + x.P1 -= null; + } +} - ValidateP1Accessor(p1.AddMethod); - ValidateP1Accessor(p1.RemoveMethod); - void ValidateP1Accessor(MethodSymbol accessor) - { - Assert.True(accessor.IsAbstract); - Assert.False(accessor.IsVirtual); - Assert.True(accessor.IsMetadataVirtual()); - Assert.False(accessor.IsSealed); - Assert.False(accessor.IsStatic); - Assert.False(accessor.IsExtern); - Assert.False(accessor.IsAsync); - Assert.False(accessor.IsOverride); - Assert.Equal(Accessibility.Private, accessor.DeclaredAccessibility); - Assert.Null(test1.FindImplementationForInterfaceMember(accessor)); - } +public class Test2 : I1 +{ + event System.Action I1.P1 + { + add + { + System.Console.WriteLine(""Test2.get_P1""); + } + remove + { + System.Console.WriteLine(""Test2.set_P1""); + } + } +} +"; - var p2 = i1.GetMembers().OfType().ElementAt(1); + var source2 = +@" +class Test1 : Test2, I1 +{ + static void Main() + { + TestHelper.CallP1(new Test1()); + } + + public virtual event System.Action P1 + { + add + { + System.Console.WriteLine(""Test1.get_P1""); + } + remove + { + System.Console.WriteLine(""Test1.set_P1""); + } + } +} +"; - Assert.False(p2.IsAbstract); - Assert.True(p2.IsVirtual); - Assert.False(p2.IsSealed); - Assert.False(p2.IsStatic); - Assert.False(p2.IsExtern); - Assert.False(p2.IsOverride); - Assert.Equal(Accessibility.Private, p2.DeclaredAccessibility); - Assert.Same(p2, test1.FindImplementationForInterfaceMember(p2)); + ValidateEventModifiers_11_08(source1, source2); + } - ValidateP2Accessor(p2.AddMethod); - ValidateP2Accessor(p2.RemoveMethod); - void ValidateP2Accessor(MethodSymbol accessor) - { - Assert.False(accessor.IsAbstract); - Assert.True(accessor.IsVirtual); - Assert.True(accessor.IsMetadataVirtual()); - Assert.False(accessor.IsSealed); - Assert.False(accessor.IsStatic); - Assert.False(accessor.IsExtern); - Assert.False(accessor.IsAsync); - Assert.False(accessor.IsOverride); - Assert.Equal(Accessibility.Private, accessor.DeclaredAccessibility); - Assert.Same(accessor, test1.FindImplementationForInterfaceMember(accessor)); - } + private void ValidateEventModifiers_11_08(string source1, string source2) + { + var compilation1 = CreateStandardCompilation(source2 + source1, options: TestOptions.DebugExe, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + CompileAndVerify(compilation1, expectedOutput: +@"Test2.get_P1 +Test2.set_P1", verify: false, symbolValidator: ValidateEventImplementationByBase_11); - var p3 = i1.GetMembers().OfType().ElementAt(2); + ValidateEventImplementationByBase_11(compilation1.SourceModule); - Assert.False(p3.IsAbstract); - Assert.False(p3.IsVirtual); - Assert.True(p3.IsSealed); - Assert.False(p3.IsStatic); - Assert.False(p3.IsExtern); - Assert.False(p3.IsOverride); - Assert.Equal(Accessibility.Private, p3.DeclaredAccessibility); - Assert.Null(test1.FindImplementationForInterfaceMember(p3)); + var compilation2 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation2.VerifyDiagnostics(); - ValidateP3Accessor(p3.AddMethod); - ValidateP3Accessor(p3.RemoveMethod); - void ValidateP3Accessor(MethodSymbol accessor) - { - Assert.False(accessor.IsAbstract); - Assert.False(accessor.IsVirtual); - Assert.False(accessor.IsMetadataVirtual()); - Assert.True(accessor.IsSealed); - Assert.False(accessor.IsStatic); - Assert.False(accessor.IsExtern); - Assert.False(accessor.IsAsync); - Assert.False(accessor.IsOverride); - Assert.Equal(Accessibility.Private, accessor.DeclaredAccessibility); - Assert.Null(test1.FindImplementationForInterfaceMember(accessor)); - } + var compilation3 = CreateStandardCompilation(source2, new[] { compilation2.ToMetadataReference() }, options: TestOptions.DebugExe, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + CompileAndVerify(compilation3, expectedOutput: +@"Test2.get_P1 +Test2.set_P1", verify: false, symbolValidator: ValidateEventImplementationByBase_11); - var p4 = i1.GetMembers().OfType().ElementAt(3); + ValidateEventImplementationByBase_11(compilation3.SourceModule); - Assert.False(p4.IsAbstract); - Assert.False(p4.IsVirtual); - Assert.False(p4.IsSealed); - Assert.False(p4.IsStatic); - Assert.False(p4.IsExtern); - Assert.False(p4.IsOverride); - Assert.Equal(Accessibility.Private, p4.DeclaredAccessibility); - Assert.Null(test1.FindImplementationForInterfaceMember(p4)); + var compilation4 = CreateStandardCompilation(source2, new[] { compilation2.EmitToImageReference() }, options: TestOptions.DebugExe, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation4.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + CompileAndVerify(compilation4, expectedOutput: +@"Test2.get_P1 +Test2.set_P1", verify: false, symbolValidator: ValidateEventImplementationByBase_11); - ValidateP4Accessor(p4.AddMethod); - ValidateP4Accessor(p4.RemoveMethod); - void ValidateP4Accessor(MethodSymbol accessor) - { - Assert.False(accessor.IsAbstract); - Assert.False(accessor.IsVirtual); - Assert.False(accessor.IsMetadataVirtual()); - Assert.False(accessor.IsSealed); - Assert.False(accessor.IsStatic); - Assert.False(accessor.IsExtern); - Assert.False(accessor.IsAsync); - Assert.False(accessor.IsOverride); - Assert.Equal(Accessibility.Private, accessor.DeclaredAccessibility); - Assert.Null(test1.FindImplementationForInterfaceMember(accessor)); - } + ValidateEventImplementationByBase_11(compilation4.SourceModule); } [Fact] - public void EventModifiers_11() + public void EventModifiers_11_09() { var source1 = @" public interface I1 { internal abstract event System.Action P1; +} - sealed void Test() +public class TestHelper +{ + public static void CallP1(I1 x) { - P1 += null; - P1 -= null; + x.P1 += null; + x.P1 -= null; } } "; @@ -15587,142 +20664,183 @@ class Test1 : I1 { static void Main() { - I1 x = new Test1(); - x.Test(); + TestHelper.CallP1(new Test1()); } - public event System.Action P1 + public virtual event System.Action P1 { add { - System.Console.WriteLine(""get_P1""); + System.Console.WriteLine(""Test1.get_P1""); } remove { - System.Console.WriteLine(""set_P1""); + System.Console.WriteLine(""Test1.set_P1""); } } } "; - ValidateEventModifiers_11(source1, source2, - // (2,15): error CS0535: 'Test2' does not implement interface member 'I1.P1' - // class Test2 : I1 - Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test2", "I1.P1").WithLocation(2, 15) + ValidateEventModifiers_11_09(source1, source2, + // (2,15): error CS0535: 'Test1' does not implement interface member 'I1.P1' + // class Test1 : I1 + Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test1", "I1.P1").WithLocation(2, 15) ); } - private void ValidateEventModifiers_11(string source1, string source2, params DiagnosticDescription[] expected) + private void ValidateEventModifiers_11_09(string source1, string source2, + params DiagnosticDescription[] expected) { - var compilation1 = CreateStandardCompilation(source1 + source2, options: TestOptions.DebugExe, + var compilation1 = CreateStandardCompilation(source2 + source1, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); - CompileAndVerify(compilation1, verify: false, symbolValidator: Validate1); + compilation1.VerifyDiagnostics(expected); - Validate1(compilation1.SourceModule); + ValidateEventNotImplemented_11(compilation1, "Test1"); - void Validate1(ModuleSymbol m) - { - var test1 = m.GlobalNamespace.GetTypeMember("Test1"); - var i1 = test1.Interfaces.Single(); - var p1 = GetSingleEvent(i1); - var test1P1 = GetSingleEvent(test1); - var p1add = p1.AddMethod; - var p1remove = p1.RemoveMethod; + var compilation2 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation2.VerifyDiagnostics(); - ValidateEvent(p1); - ValidateMethod(p1add); - ValidateMethod(p1remove); - Assert.Same(test1P1, test1.FindImplementationForInterfaceMember(p1)); - Assert.Same(test1P1.AddMethod, test1.FindImplementationForInterfaceMember(p1add)); - Assert.Same(test1P1.RemoveMethod, test1.FindImplementationForInterfaceMember(p1remove)); - } + var compilation3 = CreateStandardCompilation(source2, new[] { compilation2.ToMetadataReference() }, options: TestOptions.DebugExe, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation3.VerifyDiagnostics(expected); - void ValidateEvent(EventSymbol p1) - { - Assert.True(p1.IsAbstract); - Assert.False(p1.IsVirtual); - Assert.False(p1.IsSealed); - Assert.False(p1.IsStatic); - Assert.False(p1.IsExtern); - Assert.False(p1.IsOverride); - Assert.Equal(Accessibility.Internal, p1.DeclaredAccessibility); - } + ValidateEventNotImplemented_11(compilation3, "Test1"); - void ValidateMethod(MethodSymbol m1) - { - Assert.True(m1.IsAbstract); - Assert.False(m1.IsVirtual); - Assert.True(m1.IsMetadataVirtual()); - Assert.False(m1.IsSealed); - Assert.False(m1.IsStatic); - Assert.False(m1.IsExtern); - Assert.False(m1.IsAsync); - Assert.False(m1.IsOverride); - Assert.Equal(Accessibility.Internal, m1.DeclaredAccessibility); - } + var compilation4 = CreateStandardCompilation(source2, new[] { compilation2.EmitToImageReference() }, options: TestOptions.DebugExe, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation4.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation4.VerifyDiagnostics(expected); + + ValidateEventNotImplemented_11(compilation4, "Test1"); + } + + [Fact] + public void EventModifiers_11_10() + { + var source1 = +@" +public interface I1 +{ + internal abstract event System.Action P1; +} +"; + + var source2 = +@" +public class Test2 : I1 +{ + public event System.Action P1 + { + add {} + remove {} + } +} +class Test1 : Test2, I1 +{ +} +"; + + ValidateEventModifiers_11_10(source1, source2, + // (2,22): error CS8504: 'Test2' does not implement interface member 'I1.P1.remove'. 'Test2.P1.remove' cannot implicitly implement a non-public member. + // public class Test2 : I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test2", "I1.P1.remove", "Test2.P1.remove").WithLocation(2, 22), + // (2,22): error CS8504: 'Test2' does not implement interface member 'I1.P1.add'. 'Test2.P1.add' cannot implicitly implement a non-public member. + // public class Test2 : I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test2", "I1.P1.add", "Test2.P1.add").WithLocation(2, 22) + ); + } + + private void ValidateEventModifiers_11_10(string source1, string source2, + params DiagnosticDescription[] expected) + { + var compilation1 = CreateStandardCompilation(source2 + source1, options: TestOptions.DebugDll, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); + Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation1.VerifyDiagnostics(expected); + + ValidateEventImplementationByBase_11(compilation1.SourceModule); var compilation2 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation2.VerifyDiagnostics(); - { - var i1 = compilation2.GetTypeByMetadataName("I1"); - var p1 = GetSingleEvent(i1); - ValidateEvent(p1); - ValidateMethod(p1.AddMethod); - ValidateMethod(p1.RemoveMethod); - } - - var compilation3 = CreateStandardCompilation(source2, new[] { compilation2.ToMetadataReference() }, options: TestOptions.DebugExe, + var compilation3 = CreateStandardCompilation(source2, new[] { compilation2.ToMetadataReference() }, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); Assert.True(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); - CompileAndVerify(compilation3, verify: false, symbolValidator: Validate1); + compilation3.VerifyDiagnostics(expected); - Validate1(compilation3.SourceModule); + ValidateEventImplementationByBase_11(compilation3.SourceModule); - var compilation4 = CreateStandardCompilation(source2, new[] { compilation2.EmitToImageReference() }, options: TestOptions.DebugExe, + var compilation4 = CreateStandardCompilation(source2, new[] { compilation2.EmitToImageReference() }, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); Assert.True(compilation4.Assembly.RuntimeSupportsDefaultInterfaceImplementation); - CompileAndVerify(compilation4, verify: false, symbolValidator: Validate1); + compilation4.VerifyDiagnostics(expected); - Validate1(compilation4.SourceModule); + ValidateEventImplementationByBase_11(compilation4.SourceModule); + } - var source3 = + [Fact] + public void EventModifiers_11_11() + { + var source1 = @" -class Test2 : I1 +public interface I1 +{ + internal abstract event System.Action P1; +} +public class Test2 : I1 { + public event System.Action P1 + { + add {} + remove {} + } } "; - var compilation5 = CreateStandardCompilation(source3, new[] { compilation2.ToMetadataReference() }, options: TestOptions.DebugDll, + var source2 = +@" +class Test1 : Test2, I1 +{ +} +"; + + ValidateEventModifiers_11_11(source1, source2, + // (6,22): error CS8504: 'Test2' does not implement interface member 'I1.P1.remove'. 'Test2.P1.remove' cannot implicitly implement a non-public member. + // public class Test2 : I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test2", "I1.P1.remove", "Test2.P1.remove").WithLocation(6, 22), + // (6,22): error CS8504: 'Test2' does not implement interface member 'I1.P1.add'. 'Test2.P1.add' cannot implicitly implement a non-public member. + // public class Test2 : I1 + Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "I1").WithArguments("Test2", "I1.P1.add", "Test2.P1.add").WithLocation(6, 22) + ); + } + + private void ValidateEventModifiers_11_11(string source1, string source2, + params DiagnosticDescription[] expected) + { + var compilation2 = CreateStandardCompilation(source1, options: TestOptions.DebugDll, + parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest), + assemblyName: "EventModifiers_11_11"); + Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation2.VerifyDiagnostics(expected); + + var compilation3 = CreateStandardCompilation(source2, new[] { compilation2.ToMetadataReference() }, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); - Assert.True(compilation5.Assembly.RuntimeSupportsDefaultInterfaceImplementation); - compilation5.VerifyDiagnostics(expected); + Assert.True(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); + compilation3.VerifyDiagnostics(); - { - var test2 = compilation5.GetTypeByMetadataName("Test2"); - var i1 = compilation5.GetTypeByMetadataName("I1"); - var p1 = GetSingleEvent(i1); - Assert.Null(test2.FindImplementationForInterfaceMember(p1)); - Assert.Null(test2.FindImplementationForInterfaceMember(p1.AddMethod)); - Assert.Null(test2.FindImplementationForInterfaceMember(p1.RemoveMethod)); - } + ValidateEventImplementationByBase_11(compilation3.SourceModule); - var compilation6 = CreateStandardCompilation(source3, new[] { compilation2.EmitToImageReference() }, options: TestOptions.DebugDll, + var compilation3Ref = compilation3.EmitToImageReference(); + var compilation4 = CreateStandardCompilation("", new[] { compilation2.ToMetadataReference(), compilation3Ref }, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Latest)); - Assert.True(compilation6.Assembly.RuntimeSupportsDefaultInterfaceImplementation); - compilation6.VerifyDiagnostics(expected); - { - var test2 = compilation6.GetTypeByMetadataName("Test2"); - var i1 = compilation6.GetTypeByMetadataName("I1"); - var p1 = GetSingleEvent(i1); - Assert.Null(test2.FindImplementationForInterfaceMember(p1)); - Assert.Null(test2.FindImplementationForInterfaceMember(p1.AddMethod)); - Assert.Null(test2.FindImplementationForInterfaceMember(p1.RemoveMethod)); - } + ValidateEventImplementationByBase_11(compilation4.GetReferencedAssemblySymbol(compilation3Ref).Modules[0]); } [Fact] @@ -16776,6 +21894,9 @@ class Test2 : I1, I2, I3, I4, I5 // (23,19): error CS0535: 'Test1' does not implement interface member 'I2.P2' // class Test1 : I1, I2, I3, I4, I5 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I2").WithArguments("Test1", "I2.P2").WithLocation(23, 19), + // (30,28): error CS0122: 'I2.P2' is inaccessible due to its protection level + // event System.Action I2.P2 { add {throw null;} remove {throw null;}} + Diagnostic(ErrorCode.ERR_BadAccess, "P2").WithArguments("I2.P2").WithLocation(30, 28), // (31,28): error CS0539: 'Test2.P3' in explicit interface declaration is not found among members of the interface that can be implemented // event System.Action I3.P3 { add {throw null;} remove {throw null;}} Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "P3").WithArguments("Test2.P3").WithLocation(31, 28),