From 9faaab1092459a908a71fe96e45d973f00ffbcfc Mon Sep 17 00:00:00 2001 From: Llewellyn Pritchard Date: Fri, 15 Jan 2016 23:48:22 +0200 Subject: [PATCH] Fix #7878 for interfaces --- .../Source/SourceNamedTypeSymbol_Bases.cs | 42 ++++++++-------- .../Symbol/Symbols/Source/BaseClassTests.cs | 48 +++++++++++++++++++ 2 files changed, 70 insertions(+), 20 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceNamedTypeSymbol_Bases.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceNamedTypeSymbol_Bases.cs index c6989189e06..51e84ca01e0 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceNamedTypeSymbol_Bases.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceNamedTypeSymbol_Bases.cs @@ -10,6 +10,7 @@ using Microsoft.CodeAnalysis.Text; using Roslyn.Utilities; using System.Collections.Generic; +using Microsoft.CodeAnalysis.Collections; namespace Microsoft.CodeAnalysis.CSharp.Symbols { @@ -226,6 +227,7 @@ internal override ImmutableArray GetDeclaredInterfaces(ConsList NamedTypeSymbol baseType = null; SourceLocation baseTypeLocation = null; + var interfaceLocations = PooledDictionary.GetInstance(); foreach (var decl in this.declaration.Declarations) { @@ -258,34 +260,32 @@ internal override ImmutableArray GetDeclaredInterfaces(ConsList } } - int n = baseInterfaces.Count; - foreach (var t in partInterfaces) // this could probably be done more efficiently with a side hash table if it proves necessary + foreach (var t in partInterfaces) { - for (int i = 0; i < n; i++) + if (!interfaceLocations.ContainsKey(t)) { - if (t == baseInterfaces[i]) - { - goto alreadyInInterfaceList; - } + baseInterfaces.Add(t); + interfaceLocations.Add(t, decl.NameLocation); } - - baseInterfaces.Add(t); - alreadyInInterfaceList:; } } - if ((object)baseType != null && baseType.IsStatic) - { - // '{1}': cannot derive from static class '{0}' - diagnostics.Add(ErrorCode.ERR_StaticBaseClass, baseTypeLocation ?? Locations[0], baseType, this); - } - HashSet useSiteDiagnostics = null; - if ((object)baseType != null && !this.IsNoMoreVisibleThan(baseType, ref useSiteDiagnostics)) + if ((object)baseType != null) { - // Inconsistent accessibility: base class '{1}' is less accessible than class '{0}' - diagnostics.Add(ErrorCode.ERR_BadVisBaseClass, baseTypeLocation ?? Locations[0], this, baseType); + Debug.Assert(baseTypeLocation != null); + if (baseType.IsStatic) + { + // '{1}': cannot derive from static class '{0}' + diagnostics.Add(ErrorCode.ERR_StaticBaseClass, baseTypeLocation, baseType, this); + } + + if (!this.IsNoMoreVisibleThan(baseType, ref useSiteDiagnostics)) + { + // Inconsistent accessibility: base class '{1}' is less accessible than class '{0}' + diagnostics.Add(ErrorCode.ERR_BadVisBaseClass, baseTypeLocation, this, baseType); + } } var baseInterfacesRO = baseInterfaces.ToImmutableAndFree(); @@ -296,11 +296,13 @@ internal override ImmutableArray GetDeclaredInterfaces(ConsList if (!i.IsAtLeastAsVisibleAs(this, ref useSiteDiagnostics)) { // Inconsistent accessibility: base interface '{1}' is less accessible than interface '{0}' - diagnostics.Add(ErrorCode.ERR_BadVisBaseInterface, Locations[0], this, i); + diagnostics.Add(ErrorCode.ERR_BadVisBaseInterface, interfaceLocations[i], this, i); } } } + interfaceLocations.Free(); + diagnostics.Add(Locations[0], useSiteDiagnostics); return new Tuple>(baseType, baseInterfacesRO); diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/Source/BaseClassTests.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/Source/BaseClassTests.cs index cda917054b2..61e59e9eb2a 100644 --- a/src/Compilers/CSharp/Test/Symbol/Symbols/Source/BaseClassTests.cs +++ b/src/Compilers/CSharp/Test/Symbol/Symbols/Source/BaseClassTests.cs @@ -395,6 +395,54 @@ public partial class C1 Diagnostic(ErrorCode.ERR_BadVisBaseClass, "C1").WithArguments("C1", "NV").WithLocation(10, 15)); } + + [Fact, WorkItem(7878, "https://github.com/dotnet/roslyn/issues/7878")] + public void BadVisInterfacePartial() + { + var text = @" +interface IFoo +{ + void Moo(); +} + +interface IBaz +{ + void Noo(); +} + +interface IBam +{ + void Zoo(); +} + +public partial interface IBar +{ +} + +partial interface IBar : IFoo, IBam +{ +} + +partial interface IBar : IBaz, IBaz +{ +} +"; + var comp = CreateCompilationWithMscorlib(text); + comp.VerifyDiagnostics( + // (25,32): error CS0528: 'IBaz' is already listed in interface list + // partial interface IBar : IBaz, IBaz + Diagnostic(ErrorCode.ERR_DuplicateInterfaceInBaseList, "IBaz").WithArguments("IBaz").WithLocation(25, 32), + // (21,19): error CS0061: Inconsistent accessibility: base interface 'IFoo' is less accessible than interface 'IBar' + // partial interface IBar : IFoo, IBam + Diagnostic(ErrorCode.ERR_BadVisBaseInterface, "IBar").WithArguments("IBar", "IFoo").WithLocation(21, 19), + // (21,19): error CS0061: Inconsistent accessibility: base interface 'IBam' is less accessible than interface 'IBar' + // partial interface IBar : IFoo, IBam + Diagnostic(ErrorCode.ERR_BadVisBaseInterface, "IBar").WithArguments("IBar", "IBam").WithLocation(21, 19), + // (25,19): error CS0061: Inconsistent accessibility: base interface 'IBaz' is less accessible than interface 'IBar' + // partial interface IBar : IBaz, IBaz + Diagnostic(ErrorCode.ERR_BadVisBaseInterface, "IBar").WithArguments("IBar", "IBaz").WithLocation(25, 19)); + } + [Fact] public void EricLiCase1() { -- GitLab