From 536d4adb9aa527d3f4bd80b24cb06e14c2527307 Mon Sep 17 00:00:00 2001 From: tpodolak Date: Sun, 6 Sep 2020 17:42:10 +0200 Subject: [PATCH] [GH-144] - handling protected internal constructors when analyzing NS2001 diagnostic --- global.json | 2 +- .../AbstractSubstituteConstructorAnalysis.cs | 21 +++- .../ForAsGenericMethodTests.cs | 100 +++++++++++++++++ .../ForAsNonGenericMethodTests.cs | 100 +++++++++++++++++ .../ForPartsOfMethodTests.cs | 102 +++++++++++++++++ .../SubstituteDiagnosticVerifier.cs | 12 ++ .../SubstituteFactoryCreateMethodTests.cs | 105 +++++++++++++++++- ...bstituteFactoryCreatePartialMethodTests.cs | 104 +++++++++++++++++ .../ISubstituteAnalyzerVerifier.cs | 8 ++ .../ForAsGenericMethodTests.cs | 84 ++++++++++++++ .../ForAsNonGenericMethodTests.cs | 84 ++++++++++++++ .../ForPartsOfMethodTests.cs | 88 ++++++++++++++- .../SubstituteDiagnosticVerifier.cs | 12 ++ .../SubstituteFactoryCreateMethodTests.cs | 84 ++++++++++++++ ...bstituteFactoryCreatePartialMethodTests.cs | 91 ++++++++++++++- 15 files changed, 981 insertions(+), 16 deletions(-) diff --git a/global.json b/global.json index ee30eea7..05d0ae3d 100644 --- a/global.json +++ b/global.json @@ -1,5 +1,5 @@ { "sdk": { - "version": "2.2.104" + "version": "3.1.201" } } diff --git a/src/NSubstitute.Analyzers.Shared/DiagnosticAnalyzers/AbstractSubstituteConstructorAnalysis.cs b/src/NSubstitute.Analyzers.Shared/DiagnosticAnalyzers/AbstractSubstituteConstructorAnalysis.cs index e92cb511..1c83548e 100644 --- a/src/NSubstitute.Analyzers.Shared/DiagnosticAnalyzers/AbstractSubstituteConstructorAnalysis.cs +++ b/src/NSubstitute.Analyzers.Shared/DiagnosticAnalyzers/AbstractSubstituteConstructorAnalysis.cs @@ -115,12 +115,27 @@ private IMethodSymbol[] GetAccessibleConstructors(ITypeSymbol genericArgument) { var internalsVisibleToProxy = genericArgument.InternalsVisibleToProxyGenerator(); + bool IsAccessible(IMethodSymbol symbol) + { + return symbol.DeclaredAccessibility == Accessibility.Protected || + symbol.DeclaredAccessibility == Accessibility.Public; + } + + bool IsVisibleToProxy(IMethodSymbol symbol) + { + if (internalsVisibleToProxy == false) + { + return false; + } + + return symbol.DeclaredAccessibility == Accessibility.Internal || + symbol.DeclaredAccessibility == Accessibility.ProtectedOrInternal; + } + return genericArgument.GetMembers().OfType().Where(symbol => symbol.MethodKind == MethodKind.Constructor && symbol.IsStatic == false && - (symbol.DeclaredAccessibility == Accessibility.Protected || - symbol.DeclaredAccessibility == Accessibility.Public || - (internalsVisibleToProxy && symbol.DeclaredAccessibility == Accessibility.Internal))).ToArray(); + (IsAccessible(symbol) || IsVisibleToProxy(symbol))).ToArray(); } private TypeInfo GetTypeInfo(SubstituteContext substituteContext, SyntaxNode syntax) diff --git a/tests/NSubstitute.Analyzers.Tests.CSharp/DiagnosticAnalyzerTests/SubstituteAnalyzerTests/ForAsGenericMethodTests.cs b/tests/NSubstitute.Analyzers.Tests.CSharp/DiagnosticAnalyzerTests/SubstituteAnalyzerTests/ForAsGenericMethodTests.cs index 64641ad6..e9c7997e 100644 --- a/tests/NSubstitute.Analyzers.Tests.CSharp/DiagnosticAnalyzerTests/SubstituteAnalyzerTests/ForAsGenericMethodTests.cs +++ b/tests/NSubstitute.Analyzers.Tests.CSharp/DiagnosticAnalyzerTests/SubstituteAnalyzerTests/ForAsGenericMethodTests.cs @@ -250,6 +250,106 @@ public void Test() await VerifyDiagnostic(source, SubstituteForWithoutAccessibleConstructorDescriptor, "Could not find accessible constructor. Make sure that type MyNamespace.Foo exposes public or protected constructors."); } + public override async Task ReturnsDiagnostic_WhenUsedForClassWithInternalConstructor_AndInternalsVisibleToNotApplied() + { + var source = @"using NSubstitute; + +namespace MyNamespace +{ + public class Foo + { + internal Foo() + { + } + } + + public class FooTests + { + public void Test() + { + var substitute = [|NSubstitute.Substitute.For()|]; + } + } +}"; + await VerifyDiagnostic(source, SubstituteForWithoutAccessibleConstructorDescriptor, "Could not find accessible constructor. Make sure that type MyNamespace.Foo exposes public or protected constructors."); + } + + public override async Task ReturnsDiagnostic_WhenUsedForClassWithProtectedInternalConstructor_AndInternalsVisibleToNotApplied() + { + var source = @"using NSubstitute; + +namespace MyNamespace +{ + public class Foo + { + protected internal Foo() + { + } + } + + public class FooTests + { + public void Test() + { + var substitute = [|NSubstitute.Substitute.For()|]; + } + } +}"; + await VerifyDiagnostic(source, SubstituteForWithoutAccessibleConstructorDescriptor, "Could not find accessible constructor. Make sure that type MyNamespace.Foo exposes public or protected constructors."); + } + + public override async Task ReturnsNoDiagnostic_WhenUsedForClassWithInternalConstructor_AndInternalsVisibleToApplied() + { + var source = @"using NSubstitute; +using System.Runtime.CompilerServices; + +[assembly: InternalsVisibleTo(""DynamicProxyGenAssembly2"")] +namespace MyNamespace +{ + public class Foo + { + internal Foo() + { + } + } + + public class FooTests + { + public void Test() + { + var substitute = NSubstitute.Substitute.For(); + } + } +}"; + await VerifyNoDiagnostic(source); + } + + public override async Task ReturnsNoDiagnostic_WhenUsedForClassWithProtectedInternalConstructor_AndInternalsVisibleToApplied() + { + var source = @"using NSubstitute; +using System.Runtime.CompilerServices; + +[assembly: InternalsVisibleTo(""DynamicProxyGenAssembly2"")] +namespace MyNamespace +{ + public class Foo + { + protected internal Foo() + { + } + } + + public class FooTests + { + public void Test() + { + var substitute = NSubstitute.Substitute.For(); + } + } +}"; + await VerifyNoDiagnostic(source); + } + [Fact] public override async Task ReturnsDiagnostic_WhenPassedParametersCount_GreaterThanCtorParametersCount() { diff --git a/tests/NSubstitute.Analyzers.Tests.CSharp/DiagnosticAnalyzerTests/SubstituteAnalyzerTests/ForAsNonGenericMethodTests.cs b/tests/NSubstitute.Analyzers.Tests.CSharp/DiagnosticAnalyzerTests/SubstituteAnalyzerTests/ForAsNonGenericMethodTests.cs index 7895f7d1..a80d1a7f 100644 --- a/tests/NSubstitute.Analyzers.Tests.CSharp/DiagnosticAnalyzerTests/SubstituteAnalyzerTests/ForAsNonGenericMethodTests.cs +++ b/tests/NSubstitute.Analyzers.Tests.CSharp/DiagnosticAnalyzerTests/SubstituteAnalyzerTests/ForAsNonGenericMethodTests.cs @@ -304,6 +304,106 @@ public void Test() await VerifyDiagnostic(source, SubstituteForWithoutAccessibleConstructorDescriptor, "Could not find accessible constructor. Make sure that type MyNamespace.Foo exposes public or protected constructors."); } + public override async Task ReturnsDiagnostic_WhenUsedForClassWithInternalConstructor_AndInternalsVisibleToNotApplied() + { + var source = @"using NSubstitute; + +namespace MyNamespace +{ + public class Foo + { + internal Foo() + { + } + } + + public class FooTests + { + public void Test() + { + var substitute = [|NSubstitute.Substitute.For(new [] { typeof(Foo) }, null)|]; + } + } +}"; + await VerifyDiagnostic(source, SubstituteForWithoutAccessibleConstructorDescriptor, "Could not find accessible constructor. Make sure that type MyNamespace.Foo exposes public or protected constructors."); + } + + public override async Task ReturnsDiagnostic_WhenUsedForClassWithProtectedInternalConstructor_AndInternalsVisibleToNotApplied() + { + var source = @"using NSubstitute; + +namespace MyNamespace +{ + public class Foo + { + protected internal Foo() + { + } + } + + public class FooTests + { + public void Test() + { + var substitute = [|NSubstitute.Substitute.For(new [] { typeof(Foo) }, null)|]; + } + } +}"; + await VerifyDiagnostic(source, SubstituteForWithoutAccessibleConstructorDescriptor, "Could not find accessible constructor. Make sure that type MyNamespace.Foo exposes public or protected constructors."); + } + + public override async Task ReturnsNoDiagnostic_WhenUsedForClassWithInternalConstructor_AndInternalsVisibleToApplied() + { + var source = @"using NSubstitute; +using System.Runtime.CompilerServices; + +[assembly: InternalsVisibleTo(""DynamicProxyGenAssembly2"")] +namespace MyNamespace +{ + public class Foo + { + internal Foo() + { + } + } + + public class FooTests + { + public void Test() + { + var substitute = NSubstitute.Substitute.For(new [] { typeof(Foo) }, null); + } + } +}"; + await VerifyNoDiagnostic(source); + } + + public override async Task ReturnsNoDiagnostic_WhenUsedForClassWithProtectedInternalConstructor_AndInternalsVisibleToApplied() + { + var source = @"using NSubstitute; +using System.Runtime.CompilerServices; + +[assembly: InternalsVisibleTo(""DynamicProxyGenAssembly2"")] +namespace MyNamespace +{ + public class Foo + { + protected internal Foo() + { + } + } + + public class FooTests + { + public void Test() + { + var substitute = NSubstitute.Substitute.For(new [] { typeof(Foo) }, null); + } + } +}"; + await VerifyNoDiagnostic(source); + } + [Fact] public override async Task ReturnsDiagnostic_WhenPassedParametersCount_GreaterThanCtorParametersCount() { diff --git a/tests/NSubstitute.Analyzers.Tests.CSharp/DiagnosticAnalyzerTests/SubstituteAnalyzerTests/ForPartsOfMethodTests.cs b/tests/NSubstitute.Analyzers.Tests.CSharp/DiagnosticAnalyzerTests/SubstituteAnalyzerTests/ForPartsOfMethodTests.cs index c8ef47d4..d77874c5 100644 --- a/tests/NSubstitute.Analyzers.Tests.CSharp/DiagnosticAnalyzerTests/SubstituteAnalyzerTests/ForPartsOfMethodTests.cs +++ b/tests/NSubstitute.Analyzers.Tests.CSharp/DiagnosticAnalyzerTests/SubstituteAnalyzerTests/ForPartsOfMethodTests.cs @@ -80,6 +80,108 @@ public void Test() await VerifyDiagnostic(source, SubstituteForWithoutAccessibleConstructorDescriptor, "Could not find accessible constructor. Make sure that type MyNamespace.Foo exposes public or protected constructors."); } + public override async Task ReturnsDiagnostic_WhenUsedForClassWithInternalConstructor_AndInternalsVisibleToNotApplied() + { + var source = @"using NSubstitute; + +namespace MyNamespace +{ + public class Foo + { + internal Foo() + { + } + } + + public class FooTests + { + public void Test() + { + var substitute = [|NSubstitute.Substitute.ForPartsOf()|]; + } + } +}"; + await VerifyDiagnostic(source, SubstituteForWithoutAccessibleConstructorDescriptor, "Could not find accessible constructor. Make sure that type MyNamespace.Foo exposes public or protected constructors."); + } + + public override async Task ReturnsDiagnostic_WhenUsedForClassWithProtectedInternalConstructor_AndInternalsVisibleToNotApplied() + { + var source = @"using NSubstitute; + +namespace MyNamespace +{ + public class Foo + { + protected internal Foo() + { + } + } + + public class FooTests + { + public void Test() + { + var substitute = [|NSubstitute.Substitute.ForPartsOf()|]; + } + } +}"; + await VerifyDiagnostic(source, SubstituteForWithoutAccessibleConstructorDescriptor, "Could not find accessible constructor. Make sure that type MyNamespace.Foo exposes public or protected constructors."); + } + + public override async Task ReturnsNoDiagnostic_WhenUsedForClassWithInternalConstructor_AndInternalsVisibleToApplied() + { + var source = @"using NSubstitute; +using System.Runtime.CompilerServices; + +[assembly: InternalsVisibleTo(""DynamicProxyGenAssembly2"")] + +namespace MyNamespace +{ + public class Foo + { + internal Foo() + { + } + } + + public class FooTests + { + public void Test() + { + var substitute = NSubstitute.Substitute.ForPartsOf(); + } + } +}"; + await VerifyNoDiagnostic(source); + } + + public override async Task ReturnsNoDiagnostic_WhenUsedForClassWithProtectedInternalConstructor_AndInternalsVisibleToApplied() + { + var source = @"using NSubstitute; +using System.Runtime.CompilerServices; + +[assembly: InternalsVisibleTo(""DynamicProxyGenAssembly2"")] + +namespace MyNamespace +{ + public class Foo + { + protected internal Foo() + { + } + } + + public class FooTests + { + public void Test() + { + var substitute = NSubstitute.Substitute.ForPartsOf(); + } + } +}"; + await VerifyNoDiagnostic(source); + } + [Fact] public override async Task ReturnsDiagnostic_WhenPassedParametersCount_GreaterThanCtorParametersCount() { diff --git a/tests/NSubstitute.Analyzers.Tests.CSharp/DiagnosticAnalyzerTests/SubstituteAnalyzerTests/SubstituteDiagnosticVerifier.cs b/tests/NSubstitute.Analyzers.Tests.CSharp/DiagnosticAnalyzerTests/SubstituteAnalyzerTests/SubstituteDiagnosticVerifier.cs index 02fb7b3c..37eb063c 100644 --- a/tests/NSubstitute.Analyzers.Tests.CSharp/DiagnosticAnalyzerTests/SubstituteAnalyzerTests/SubstituteDiagnosticVerifier.cs +++ b/tests/NSubstitute.Analyzers.Tests.CSharp/DiagnosticAnalyzerTests/SubstituteAnalyzerTests/SubstituteDiagnosticVerifier.cs @@ -33,6 +33,18 @@ public abstract class SubstituteDiagnosticVerifier : CSharpDiagnosticVerifier, I [Fact] public abstract Task ReturnsDiagnostic_WhenUsedForClassWithoutPublicOrProtectedConstructor(); + [Fact] + public abstract Task ReturnsDiagnostic_WhenUsedForClassWithInternalConstructor_AndInternalsVisibleToNotApplied(); + + [Fact] + public abstract Task ReturnsDiagnostic_WhenUsedForClassWithProtectedInternalConstructor_AndInternalsVisibleToNotApplied(); + + [Fact] + public abstract Task ReturnsNoDiagnostic_WhenUsedForClassWithInternalConstructor_AndInternalsVisibleToApplied(); + + [Fact] + public abstract Task ReturnsNoDiagnostic_WhenUsedForClassWithProtectedInternalConstructor_AndInternalsVisibleToApplied(); + [Fact] public abstract Task ReturnsDiagnostic_WhenPassedParametersCount_GreaterThanCtorParametersCount(); diff --git a/tests/NSubstitute.Analyzers.Tests.CSharp/DiagnosticAnalyzerTests/SubstituteAnalyzerTests/SubstituteFactoryCreateMethodTests.cs b/tests/NSubstitute.Analyzers.Tests.CSharp/DiagnosticAnalyzerTests/SubstituteAnalyzerTests/SubstituteFactoryCreateMethodTests.cs index 8883c356..d9404fb4 100644 --- a/tests/NSubstitute.Analyzers.Tests.CSharp/DiagnosticAnalyzerTests/SubstituteAnalyzerTests/SubstituteFactoryCreateMethodTests.cs +++ b/tests/NSubstitute.Analyzers.Tests.CSharp/DiagnosticAnalyzerTests/SubstituteAnalyzerTests/SubstituteFactoryCreateMethodTests.cs @@ -1,9 +1,4 @@ using System.Threading.Tasks; -using Microsoft.CodeAnalysis; -using NSubstitute.Analyzers.CSharp; -using NSubstitute.Analyzers.Shared; -using NSubstitute.Analyzers.Tests.Shared.DiagnosticAnalyzers; -using NSubstitute.Analyzers.Tests.Shared.Extensions; using Xunit; namespace NSubstitute.Analyzers.Tests.CSharp.DiagnosticAnalyzerTests.SubstituteAnalyzerTests @@ -260,6 +255,106 @@ public void Test() await VerifyDiagnostic(source, SubstituteForWithoutAccessibleConstructorDescriptor, "Could not find accessible constructor. Make sure that type MyNamespace.Foo exposes public or protected constructors."); } + public override async Task ReturnsDiagnostic_WhenUsedForClassWithInternalConstructor_AndInternalsVisibleToNotApplied() + { + var source = @"using NSubstitute.Core; + +namespace MyNamespace +{ + public class Foo + { + internal Foo() + { + } + } + + public class FooTests + { + public void Test() + { + var substitute = [|SubstitutionContext.Current.SubstituteFactory.Create(new[] {typeof(Foo)}, null)|]; + } + } +}"; + await VerifyDiagnostic(source, SubstituteForWithoutAccessibleConstructorDescriptor, "Could not find accessible constructor. Make sure that type MyNamespace.Foo exposes public or protected constructors."); + } + + public override async Task ReturnsDiagnostic_WhenUsedForClassWithProtectedInternalConstructor_AndInternalsVisibleToNotApplied() + { + var source = @"using NSubstitute.Core; + +namespace MyNamespace +{ + public class Foo + { + protected internal Foo() + { + } + } + + public class FooTests + { + public void Test() + { + var substitute = [|SubstitutionContext.Current.SubstituteFactory.Create(new[] {typeof(Foo)}, null)|]; + } + } +}"; + await VerifyDiagnostic(source, SubstituteForWithoutAccessibleConstructorDescriptor, "Could not find accessible constructor. Make sure that type MyNamespace.Foo exposes public or protected constructors."); + } + + public override async Task ReturnsNoDiagnostic_WhenUsedForClassWithInternalConstructor_AndInternalsVisibleToApplied() + { + var source = @"using NSubstitute.Core; +using System.Runtime.CompilerServices; + +[assembly: InternalsVisibleTo(""DynamicProxyGenAssembly2"")] +namespace MyNamespace +{ + public class Foo + { + internal Foo() + { + } + } + + public class FooTests + { + public void Test() + { + var substitute = SubstitutionContext.Current.SubstituteFactory.Create(new[] {typeof(Foo)}, null); + } + } +}"; + await VerifyNoDiagnostic(source); + } + + public override async Task ReturnsNoDiagnostic_WhenUsedForClassWithProtectedInternalConstructor_AndInternalsVisibleToApplied() + { + var source = @"using NSubstitute.Core; +using System.Runtime.CompilerServices; + +[assembly: InternalsVisibleTo(""DynamicProxyGenAssembly2"")] +namespace MyNamespace +{ + public class Foo + { + protected internal Foo() + { + } + } + + public class FooTests + { + public void Test() + { + var substitute = SubstitutionContext.Current.SubstituteFactory.Create(new[] {typeof(Foo)}, null); + } + } +}"; + await VerifyNoDiagnostic(source); + } + [Fact] public override async Task ReturnsDiagnostic_WhenPassedParametersCount_GreaterThanCtorParametersCount() { diff --git a/tests/NSubstitute.Analyzers.Tests.CSharp/DiagnosticAnalyzerTests/SubstituteAnalyzerTests/SubstituteFactoryCreatePartialMethodTests.cs b/tests/NSubstitute.Analyzers.Tests.CSharp/DiagnosticAnalyzerTests/SubstituteAnalyzerTests/SubstituteFactoryCreatePartialMethodTests.cs index 30a3fae1..face2cfb 100644 --- a/tests/NSubstitute.Analyzers.Tests.CSharp/DiagnosticAnalyzerTests/SubstituteAnalyzerTests/SubstituteFactoryCreatePartialMethodTests.cs +++ b/tests/NSubstitute.Analyzers.Tests.CSharp/DiagnosticAnalyzerTests/SubstituteAnalyzerTests/SubstituteFactoryCreatePartialMethodTests.cs @@ -80,6 +80,110 @@ public void Test() await VerifyDiagnostic(source, SubstituteForWithoutAccessibleConstructorDescriptor, "Could not find accessible constructor. Make sure that type MyNamespace.Foo exposes public or protected constructors."); } + public override async Task ReturnsDiagnostic_WhenUsedForClassWithInternalConstructor_AndInternalsVisibleToNotApplied() + { + var source = @"using System; +using NSubstitute.Core; + +namespace MyNamespace +{ + public class Foo + { + internal Foo() + { + } + } + + public class FooTests + { + public void Test() + { + var substitute = [|SubstitutionContext.Current.SubstituteFactory.CreatePartial(new Type[] { typeof(Foo)}, null)|]; + } + } +}"; + await VerifyDiagnostic(source, SubstituteForWithoutAccessibleConstructorDescriptor, "Could not find accessible constructor. Make sure that type MyNamespace.Foo exposes public or protected constructors."); + } + + public override async Task ReturnsDiagnostic_WhenUsedForClassWithProtectedInternalConstructor_AndInternalsVisibleToNotApplied() + { + var source = @"using System; +using NSubstitute.Core; + +namespace MyNamespace +{ + public class Foo + { + protected internal Foo() + { + } + } + + public class FooTests + { + public void Test() + { + var substitute = [|SubstitutionContext.Current.SubstituteFactory.CreatePartial(new Type[] { typeof(Foo)}, null)|]; + } + } +}"; + await VerifyDiagnostic(source, SubstituteForWithoutAccessibleConstructorDescriptor, "Could not find accessible constructor. Make sure that type MyNamespace.Foo exposes public or protected constructors."); + } + + public override async Task ReturnsNoDiagnostic_WhenUsedForClassWithInternalConstructor_AndInternalsVisibleToApplied() + { + var source = @"using System; +using NSubstitute.Core; +using System.Runtime.CompilerServices; + +[assembly: InternalsVisibleTo(""DynamicProxyGenAssembly2"")] +namespace MyNamespace +{ + public class Foo + { + internal Foo() + { + } + } + + public class FooTests + { + public void Test() + { + var substitute = SubstitutionContext.Current.SubstituteFactory.CreatePartial(new Type[] { typeof(Foo)}, null); + } + } +}"; + await VerifyNoDiagnostic(source); + } + + public override async Task ReturnsNoDiagnostic_WhenUsedForClassWithProtectedInternalConstructor_AndInternalsVisibleToApplied() + { + var source = @"using System; +using NSubstitute.Core; +using System.Runtime.CompilerServices; + +[assembly: InternalsVisibleTo(""DynamicProxyGenAssembly2"")] +namespace MyNamespace +{ + public class Foo + { + protected internal Foo() + { + } + } + + public class FooTests + { + public void Test() + { + var substitute = SubstitutionContext.Current.SubstituteFactory.CreatePartial(new Type[] { typeof(Foo)}, null); + } + } +}"; + await VerifyNoDiagnostic(source); + } + [Fact] public override async Task ReturnsDiagnostic_WhenPassedParametersCount_GreaterThanCtorParametersCount() { diff --git a/tests/NSubstitute.Analyzers.Tests.Shared/DiagnosticAnalyzers/ISubstituteAnalyzerVerifier.cs b/tests/NSubstitute.Analyzers.Tests.Shared/DiagnosticAnalyzers/ISubstituteAnalyzerVerifier.cs index 3d2cd7f2..aca485a9 100644 --- a/tests/NSubstitute.Analyzers.Tests.Shared/DiagnosticAnalyzers/ISubstituteAnalyzerVerifier.cs +++ b/tests/NSubstitute.Analyzers.Tests.Shared/DiagnosticAnalyzers/ISubstituteAnalyzerVerifier.cs @@ -6,6 +6,14 @@ public interface ISubstituteAnalyzerVerifier { Task ReturnsDiagnostic_WhenUsedForClassWithoutPublicOrProtectedConstructor(); + Task ReturnsDiagnostic_WhenUsedForClassWithInternalConstructor_AndInternalsVisibleToNotApplied(); + + Task ReturnsDiagnostic_WhenUsedForClassWithProtectedInternalConstructor_AndInternalsVisibleToNotApplied(); + + Task ReturnsNoDiagnostic_WhenUsedForClassWithInternalConstructor_AndInternalsVisibleToApplied(); + + Task ReturnsNoDiagnostic_WhenUsedForClassWithProtectedInternalConstructor_AndInternalsVisibleToApplied(); + Task ReturnsDiagnostic_WhenPassedParametersCount_GreaterThanCtorParametersCount(); Task ReturnsDiagnostic_WhenPassedParametersCount_LessThanCtorParametersCount(); diff --git a/tests/NSubstitute.Analyzers.Tests.VisualBasic/DiagnosticAnalyzersTests/SubstituteAnalyzerTests/ForAsGenericMethodTests.cs b/tests/NSubstitute.Analyzers.Tests.VisualBasic/DiagnosticAnalyzersTests/SubstituteAnalyzerTests/ForAsGenericMethodTests.cs index 0a297281..bb89ddbe 100644 --- a/tests/NSubstitute.Analyzers.Tests.VisualBasic/DiagnosticAnalyzersTests/SubstituteAnalyzerTests/ForAsGenericMethodTests.cs +++ b/tests/NSubstitute.Analyzers.Tests.VisualBasic/DiagnosticAnalyzersTests/SubstituteAnalyzerTests/ForAsGenericMethodTests.cs @@ -210,6 +210,90 @@ End Namespace await VerifyDiagnostic(source, SubstituteForWithoutAccessibleConstructorDescriptor, "Could not find accessible constructor. Make sure that type MyNamespace.Foo exposes public or protected constructors."); } + public override async Task ReturnsDiagnostic_WhenUsedForClassWithInternalConstructor_AndInternalsVisibleToNotApplied() + { + var source = @"Imports NSubstitute + +Namespace MyNamespace + Public Class Foo + Friend Sub New() + End Sub + End Class + + Public Class FooTests + Public Sub Test() + Dim substitute = [|NSubstitute.Substitute.[For](Of Foo)()|] + End Sub + End Class +End Namespace +"; + await VerifyDiagnostic(source, SubstituteForWithoutAccessibleConstructorDescriptor, "Could not find accessible constructor. Make sure that type MyNamespace.Foo exposes public or protected constructors."); + } + + public override async Task ReturnsDiagnostic_WhenUsedForClassWithProtectedInternalConstructor_AndInternalsVisibleToNotApplied() + { + var source = @"Imports NSubstitute + +Namespace MyNamespace + Public Class Foo + Protected Friend Sub New() + End Sub + End Class + + Public Class FooTests + Public Sub Test() + Dim substitute = [|NSubstitute.Substitute.[For](Of Foo)()|] + End Sub + End Class +End Namespace +"; + await VerifyDiagnostic(source, SubstituteForWithoutAccessibleConstructorDescriptor, "Could not find accessible constructor. Make sure that type MyNamespace.Foo exposes public or protected constructors."); + } + + public override async Task ReturnsNoDiagnostic_WhenUsedForClassWithInternalConstructor_AndInternalsVisibleToApplied() + { + var source = @"Imports NSubstitute +Imports System.Runtime.CompilerServices + + +Namespace MyNamespace + Public Class Foo + Friend Sub New() + End Sub + End Class + + Public Class FooTests + Public Sub Test() + Dim substitute = NSubstitute.Substitute.[For](Of Foo)() + End Sub + End Class +End Namespace +"; + await VerifyNoDiagnostic(source); + } + + public override async Task ReturnsNoDiagnostic_WhenUsedForClassWithProtectedInternalConstructor_AndInternalsVisibleToApplied() + { + var source = @"Imports NSubstitute +Imports System.Runtime.CompilerServices + + +Namespace MyNamespace + Public Class Foo + Protected Friend Sub New() + End Sub + End Class + + Public Class FooTests + Public Sub Test() + Dim substitute = NSubstitute.Substitute.[For](Of Foo)() + End Sub + End Class +End Namespace +"; + await VerifyNoDiagnostic(source); + } + public override async Task ReturnsDiagnostic_WhenPassedParametersCount_GreaterThanCtorParametersCount() { var source = @"Imports NSubstitute diff --git a/tests/NSubstitute.Analyzers.Tests.VisualBasic/DiagnosticAnalyzersTests/SubstituteAnalyzerTests/ForAsNonGenericMethodTests.cs b/tests/NSubstitute.Analyzers.Tests.VisualBasic/DiagnosticAnalyzersTests/SubstituteAnalyzerTests/ForAsNonGenericMethodTests.cs index 94a7efa3..97fc067d 100644 --- a/tests/NSubstitute.Analyzers.Tests.VisualBasic/DiagnosticAnalyzersTests/SubstituteAnalyzerTests/ForAsNonGenericMethodTests.cs +++ b/tests/NSubstitute.Analyzers.Tests.VisualBasic/DiagnosticAnalyzersTests/SubstituteAnalyzerTests/ForAsNonGenericMethodTests.cs @@ -262,6 +262,90 @@ End Namespace await VerifyDiagnostic(source, SubstituteForWithoutAccessibleConstructorDescriptor, "Could not find accessible constructor. Make sure that type MyNamespace.Foo exposes public or protected constructors."); } + public override async Task ReturnsDiagnostic_WhenUsedForClassWithInternalConstructor_AndInternalsVisibleToNotApplied() + { + var source = @"Imports NSubstitute + +Namespace MyNamespace + Public Class Foo + Friend Sub New() + End Sub + End Class + + Public Class FooTests + Public Sub Test() + Dim substitute = [|NSubstitute.Substitute.[For]({GetType(Foo)}, Nothing)|] + End Sub + End Class +End Namespace +"; + await VerifyDiagnostic(source, SubstituteForWithoutAccessibleConstructorDescriptor, "Could not find accessible constructor. Make sure that type MyNamespace.Foo exposes public or protected constructors."); + } + + public override async Task ReturnsDiagnostic_WhenUsedForClassWithProtectedInternalConstructor_AndInternalsVisibleToNotApplied() + { + var source = @"Imports NSubstitute + +Namespace MyNamespace + Public Class Foo + Protected Friend Sub New() + End Sub + End Class + + Public Class FooTests + Public Sub Test() + Dim substitute = [|NSubstitute.Substitute.[For]({GetType(Foo)}, Nothing)|] + End Sub + End Class +End Namespace +"; + await VerifyDiagnostic(source, SubstituteForWithoutAccessibleConstructorDescriptor, "Could not find accessible constructor. Make sure that type MyNamespace.Foo exposes public or protected constructors."); + } + + public override async Task ReturnsNoDiagnostic_WhenUsedForClassWithInternalConstructor_AndInternalsVisibleToApplied() + { + var source = @"Imports NSubstitute +Imports System.Runtime.CompilerServices + + +Namespace MyNamespace + Public Class Foo + Friend Sub New() + End Sub + End Class + + Public Class FooTests + Public Sub Test() + Dim substitute = NSubstitute.Substitute.[For]({GetType(Foo)}, Nothing) + End Sub + End Class +End Namespace +"; + await VerifyNoDiagnostic(source); + } + + public override async Task ReturnsNoDiagnostic_WhenUsedForClassWithProtectedInternalConstructor_AndInternalsVisibleToApplied() + { + var source = @"Imports NSubstitute +Imports System.Runtime.CompilerServices + + +Namespace MyNamespace + Public Class Foo + Protected Friend Sub New() + End Sub + End Class + + Public Class FooTests + Public Sub Test() + Dim substitute = NSubstitute.Substitute.[For]({GetType(Foo)}, Nothing) + End Sub + End Class +End Namespace +"; + await VerifyNoDiagnostic(source); + } + public override async Task ReturnsDiagnostic_WhenPassedParametersCount_GreaterThanCtorParametersCount() { var source = @"Imports NSubstitute diff --git a/tests/NSubstitute.Analyzers.Tests.VisualBasic/DiagnosticAnalyzersTests/SubstituteAnalyzerTests/ForPartsOfMethodTests.cs b/tests/NSubstitute.Analyzers.Tests.VisualBasic/DiagnosticAnalyzersTests/SubstituteAnalyzerTests/ForPartsOfMethodTests.cs index dc6c3744..00e35744 100644 --- a/tests/NSubstitute.Analyzers.Tests.VisualBasic/DiagnosticAnalyzersTests/SubstituteAnalyzerTests/ForPartsOfMethodTests.cs +++ b/tests/NSubstitute.Analyzers.Tests.VisualBasic/DiagnosticAnalyzersTests/SubstituteAnalyzerTests/ForPartsOfMethodTests.cs @@ -1,8 +1,4 @@ using System.Threading.Tasks; -using Microsoft.CodeAnalysis; -using NSubstitute.Analyzers.Shared; -using NSubstitute.Analyzers.Tests.Shared; -using NSubstitute.Analyzers.Tests.Shared.DiagnosticAnalyzers; using Xunit; namespace NSubstitute.Analyzers.Tests.VisualBasic.DiagnosticAnalyzersTests.SubstituteAnalyzerTests @@ -68,6 +64,90 @@ End Namespace await VerifyDiagnostic(source, SubstituteForWithoutAccessibleConstructorDescriptor, "Could not find accessible constructor. Make sure that type MyNamespace.Foo exposes public or protected constructors."); } + public override async Task ReturnsDiagnostic_WhenUsedForClassWithInternalConstructor_AndInternalsVisibleToNotApplied() + { + var source = @"Imports NSubstitute + +Namespace MyNamespace + Public Class Foo + Friend Sub New() + End Sub + End Class + + Public Class FooTests + Public Sub Test() + Dim substitute = [|NSubstitute.Substitute.ForPartsOf(Of Foo)()|] + End Sub + End Class +End Namespace +"; + await VerifyDiagnostic(source, SubstituteForWithoutAccessibleConstructorDescriptor, "Could not find accessible constructor. Make sure that type MyNamespace.Foo exposes public or protected constructors."); + } + + public override async Task ReturnsDiagnostic_WhenUsedForClassWithProtectedInternalConstructor_AndInternalsVisibleToNotApplied() + { + var source = @"Imports NSubstitute + +Namespace MyNamespace + Public Class Foo + Protected Friend Sub New() + End Sub + End Class + + Public Class FooTests + Public Sub Test() + Dim substitute = [|NSubstitute.Substitute.ForPartsOf(Of Foo)()|] + End Sub + End Class +End Namespace +"; + await VerifyDiagnostic(source, SubstituteForWithoutAccessibleConstructorDescriptor, "Could not find accessible constructor. Make sure that type MyNamespace.Foo exposes public or protected constructors."); + } + + public override async Task ReturnsNoDiagnostic_WhenUsedForClassWithInternalConstructor_AndInternalsVisibleToApplied() + { + var source = @"Imports NSubstitute +Imports System.Runtime.CompilerServices + + +Namespace MyNamespace + Public Class Foo + Friend Sub New() + End Sub + End Class + + Public Class FooTests + Public Sub Test() + Dim substitute = NSubstitute.Substitute.ForPartsOf(Of Foo)() + End Sub + End Class +End Namespace +"; + await VerifyNoDiagnostic(source); + } + + public override async Task ReturnsNoDiagnostic_WhenUsedForClassWithProtectedInternalConstructor_AndInternalsVisibleToApplied() + { + var source = @"Imports NSubstitute +Imports System.Runtime.CompilerServices + + +Namespace MyNamespace + Public Class Foo + Protected Friend Sub New() + End Sub + End Class + + Public Class FooTests + Public Sub Test() + Dim substitute = NSubstitute.Substitute.ForPartsOf(Of Foo)() + End Sub + End Class +End Namespace +"; + await VerifyNoDiagnostic(source); + } + public override async Task ReturnsDiagnostic_WhenPassedParametersCount_GreaterThanCtorParametersCount() { var source = @"Imports NSubstitute diff --git a/tests/NSubstitute.Analyzers.Tests.VisualBasic/DiagnosticAnalyzersTests/SubstituteAnalyzerTests/SubstituteDiagnosticVerifier.cs b/tests/NSubstitute.Analyzers.Tests.VisualBasic/DiagnosticAnalyzersTests/SubstituteAnalyzerTests/SubstituteDiagnosticVerifier.cs index 052ab8b1..0b8cb416 100644 --- a/tests/NSubstitute.Analyzers.Tests.VisualBasic/DiagnosticAnalyzersTests/SubstituteAnalyzerTests/SubstituteDiagnosticVerifier.cs +++ b/tests/NSubstitute.Analyzers.Tests.VisualBasic/DiagnosticAnalyzersTests/SubstituteAnalyzerTests/SubstituteDiagnosticVerifier.cs @@ -33,6 +33,18 @@ public abstract class SubstituteDiagnosticVerifier : VisualBasicDiagnosticVerifi [Fact] public abstract Task ReturnsDiagnostic_WhenUsedForClassWithoutPublicOrProtectedConstructor(); + [Fact] + public abstract Task ReturnsDiagnostic_WhenUsedForClassWithInternalConstructor_AndInternalsVisibleToNotApplied(); + + [Fact] + public abstract Task ReturnsDiagnostic_WhenUsedForClassWithProtectedInternalConstructor_AndInternalsVisibleToNotApplied(); + + [Fact] + public abstract Task ReturnsNoDiagnostic_WhenUsedForClassWithInternalConstructor_AndInternalsVisibleToApplied(); + + [Fact] + public abstract Task ReturnsNoDiagnostic_WhenUsedForClassWithProtectedInternalConstructor_AndInternalsVisibleToApplied(); + [Fact] public abstract Task ReturnsDiagnostic_WhenPassedParametersCount_GreaterThanCtorParametersCount(); diff --git a/tests/NSubstitute.Analyzers.Tests.VisualBasic/DiagnosticAnalyzersTests/SubstituteAnalyzerTests/SubstituteFactoryCreateMethodTests.cs b/tests/NSubstitute.Analyzers.Tests.VisualBasic/DiagnosticAnalyzersTests/SubstituteAnalyzerTests/SubstituteFactoryCreateMethodTests.cs index 4d850057..f702fc0a 100644 --- a/tests/NSubstitute.Analyzers.Tests.VisualBasic/DiagnosticAnalyzersTests/SubstituteAnalyzerTests/SubstituteFactoryCreateMethodTests.cs +++ b/tests/NSubstitute.Analyzers.Tests.VisualBasic/DiagnosticAnalyzersTests/SubstituteAnalyzerTests/SubstituteFactoryCreateMethodTests.cs @@ -217,6 +217,90 @@ End Namespace await VerifyDiagnostic(source, SubstituteForWithoutAccessibleConstructorDescriptor, "Could not find accessible constructor. Make sure that type MyNamespace.Foo exposes public or protected constructors."); } + public override async Task ReturnsDiagnostic_WhenUsedForClassWithInternalConstructor_AndInternalsVisibleToNotApplied() + { + var source = @"Imports NSubstitute.Core + +Namespace MyNamespace + Public Class Foo + Friend Sub New() + End Sub + End Class + + Public Class FooTests + Public Sub Test() + Dim substitute = [|SubstitutionContext.Current.SubstituteFactory.Create({GetType(Foo)}, Nothing)|] + End Sub + End Class +End Namespace +"; + await VerifyDiagnostic(source, SubstituteForWithoutAccessibleConstructorDescriptor, "Could not find accessible constructor. Make sure that type MyNamespace.Foo exposes public or protected constructors."); + } + + public override async Task ReturnsDiagnostic_WhenUsedForClassWithProtectedInternalConstructor_AndInternalsVisibleToNotApplied() + { + var source = @"Imports NSubstitute.Core + +Namespace MyNamespace + Public Class Foo + Protected Friend Sub New() + End Sub + End Class + + Public Class FooTests + Public Sub Test() + Dim substitute = [|SubstitutionContext.Current.SubstituteFactory.Create({GetType(Foo)}, Nothing)|] + End Sub + End Class +End Namespace +"; + await VerifyDiagnostic(source, SubstituteForWithoutAccessibleConstructorDescriptor, "Could not find accessible constructor. Make sure that type MyNamespace.Foo exposes public or protected constructors."); + } + + public override async Task ReturnsNoDiagnostic_WhenUsedForClassWithInternalConstructor_AndInternalsVisibleToApplied() + { + var source = @"Imports NSubstitute.Core +Imports System.Runtime.CompilerServices + + +Namespace MyNamespace + Public Class Foo + Friend Sub New() + End Sub + End Class + + Public Class FooTests + Public Sub Test() + Dim substitute = SubstitutionContext.Current.SubstituteFactory.Create({GetType(Foo)}, Nothing) + End Sub + End Class +End Namespace +"; + await VerifyNoDiagnostic(source); + } + + public override async Task ReturnsNoDiagnostic_WhenUsedForClassWithProtectedInternalConstructor_AndInternalsVisibleToApplied() + { + var source = @"Imports NSubstitute.Core +Imports System.Runtime.CompilerServices + + +Namespace MyNamespace + Public Class Foo + Protected Friend Sub New() + End Sub + End Class + + Public Class FooTests + Public Sub Test() + Dim substitute = SubstitutionContext.Current.SubstituteFactory.Create({GetType(Foo)}, Nothing) + End Sub + End Class +End Namespace +"; + await VerifyNoDiagnostic(source); + } + [Fact] public override async Task ReturnsDiagnostic_WhenPassedParametersCount_GreaterThanCtorParametersCount() { diff --git a/tests/NSubstitute.Analyzers.Tests.VisualBasic/DiagnosticAnalyzersTests/SubstituteAnalyzerTests/SubstituteFactoryCreatePartialMethodTests.cs b/tests/NSubstitute.Analyzers.Tests.VisualBasic/DiagnosticAnalyzersTests/SubstituteAnalyzerTests/SubstituteFactoryCreatePartialMethodTests.cs index ba33cbb4..4e8364ff 100644 --- a/tests/NSubstitute.Analyzers.Tests.VisualBasic/DiagnosticAnalyzersTests/SubstituteAnalyzerTests/SubstituteFactoryCreatePartialMethodTests.cs +++ b/tests/NSubstitute.Analyzers.Tests.VisualBasic/DiagnosticAnalyzersTests/SubstituteAnalyzerTests/SubstituteFactoryCreatePartialMethodTests.cs @@ -1,7 +1,4 @@ using System.Threading.Tasks; -using Microsoft.CodeAnalysis; -using NSubstitute.Analyzers.Shared; -using NSubstitute.Analyzers.Tests.Shared.DiagnosticAnalyzers; using Xunit; namespace NSubstitute.Analyzers.Tests.VisualBasic.DiagnosticAnalyzersTests.SubstituteAnalyzerTests @@ -70,6 +67,94 @@ End Namespace await VerifyDiagnostic(source, SubstituteForWithoutAccessibleConstructorDescriptor, "Could not find accessible constructor. Make sure that type MyNamespace.Foo exposes public or protected constructors."); } + public override async Task ReturnsDiagnostic_WhenUsedForClassWithInternalConstructor_AndInternalsVisibleToNotApplied() + { + var source = @"Imports System +Imports NSubstitute.Core + +Namespace MyNamespace + Public Class Foo + Friend Sub New() + End Sub + End Class + + Public Class FooTests + Public Sub Test() + Dim substitute = [|SubstitutionContext.Current.SubstituteFactory.CreatePartial(New Type() {GetType(Foo)}, Nothing)|] + End Sub + End Class +End Namespace +"; + await VerifyDiagnostic(source, SubstituteForWithoutAccessibleConstructorDescriptor, "Could not find accessible constructor. Make sure that type MyNamespace.Foo exposes public or protected constructors."); + } + + public override async Task ReturnsDiagnostic_WhenUsedForClassWithProtectedInternalConstructor_AndInternalsVisibleToNotApplied() + { + var source = @"Imports System +Imports NSubstitute.Core + +Namespace MyNamespace + Public Class Foo + Protected Friend Sub New() + End Sub + End Class + + Public Class FooTests + Public Sub Test() + Dim substitute = [|SubstitutionContext.Current.SubstituteFactory.CreatePartial(New Type() {GetType(Foo)}, Nothing)|] + End Sub + End Class +End Namespace +"; + await VerifyDiagnostic(source, SubstituteForWithoutAccessibleConstructorDescriptor, "Could not find accessible constructor. Make sure that type MyNamespace.Foo exposes public or protected constructors."); + } + + public override async Task ReturnsNoDiagnostic_WhenUsedForClassWithInternalConstructor_AndInternalsVisibleToApplied() + { + var source = @"Imports System +Imports NSubstitute.Core +Imports System.Runtime.CompilerServices + + +Namespace MyNamespace + Public Class Foo + Public Sub New() + End Sub + End Class + + Public Class FooTests + Public Sub Test() + Dim substitute = SubstitutionContext.Current.SubstituteFactory.CreatePartial(New Type() {GetType(Foo)}, Nothing) + End Sub + End Class +End Namespace +"; + await VerifyNoDiagnostic(source); + } + + public override async Task ReturnsNoDiagnostic_WhenUsedForClassWithProtectedInternalConstructor_AndInternalsVisibleToApplied() + { + var source = @"Imports System +Imports NSubstitute.Core +Imports System.Runtime.CompilerServices + + +Namespace MyNamespace + Public Class Foo + Protected Friend Sub New() + End Sub + End Class + + Public Class FooTests + Public Sub Test() + Dim substitute = SubstitutionContext.Current.SubstituteFactory.CreatePartial(New Type() {GetType(Foo)}, Nothing) + End Sub + End Class +End Namespace +"; + await VerifyNoDiagnostic(source); + } + [Fact] public override async Task ReturnsDiagnostic_WhenPassedParametersCount_GreaterThanCtorParametersCount() {