From 4141bcc3dfeda05df88c26cc0466f32f73ceb9b5 Mon Sep 17 00:00:00 2001 From: tpodolak Date: Wed, 27 Feb 2019 22:25:04 +0100 Subject: [PATCH] [GH-70] - checking menu items generation when source code is not available --- ...ternalSetupSpecificationCodeFixProvider.cs | 4 -- ...alSetupSpecificationCodeFixActionsTests.cs | 53 +++++++++++++++++-- ...alSetupSpecificationCodeFixActionsTests.cs | 52 ++++++++++++++++-- 3 files changed, 99 insertions(+), 10 deletions(-) diff --git a/src/NSubstitute.Analyzers.CSharp/CodeFixProviders/InternalSetupSpecificationCodeFixProvider.cs b/src/NSubstitute.Analyzers.CSharp/CodeFixProviders/InternalSetupSpecificationCodeFixProvider.cs index a3c41cc9..2795bd87 100644 --- a/src/NSubstitute.Analyzers.CSharp/CodeFixProviders/InternalSetupSpecificationCodeFixProvider.cs +++ b/src/NSubstitute.Analyzers.CSharp/CodeFixProviders/InternalSetupSpecificationCodeFixProvider.cs @@ -1,10 +1,8 @@ -using System.Collections.Immutable; using System.Threading.Tasks; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CodeFixes; using Microsoft.CodeAnalysis.CSharp.Syntax; using NSubstitute.Analyzers.CSharp.Refactorings; -using NSubstitute.Analyzers.Shared; using NSubstitute.Analyzers.Shared.CodeFixProviders; namespace NSubstitute.Analyzers.CSharp.CodeFixProviders @@ -12,8 +10,6 @@ namespace NSubstitute.Analyzers.CSharp.CodeFixProviders [ExportCodeFixProvider(LanguageNames.CSharp)] internal class InternalSetupSpecificationCodeFixProvider : AbstractInternalSetupSpecificationCodeFixProvider { - public override ImmutableArray FixableDiagnosticIds { get; } = ImmutableArray.Create(DiagnosticIdentifiers.InternalSetupSpecification); - protected override string ReplaceModifierCodeFixTitle { get; } = "Replace internal with public modifier"; protected override Task AddModifierRefactoring(Document document, SyntaxNode node, Accessibility accessibility) diff --git a/tests/NSubstitute.Analyzers.Tests.CSharp/CodeFixProviderTests/InternalSetupSpecificationCodeFixProviderTests/InternalSetupSpecificationCodeFixActionsTests.cs b/tests/NSubstitute.Analyzers.Tests.CSharp/CodeFixProviderTests/InternalSetupSpecificationCodeFixProviderTests/InternalSetupSpecificationCodeFixActionsTests.cs index 6a5a6646..b042957a 100644 --- a/tests/NSubstitute.Analyzers.Tests.CSharp/CodeFixProviderTests/InternalSetupSpecificationCodeFixProviderTests/InternalSetupSpecificationCodeFixActionsTests.cs +++ b/tests/NSubstitute.Analyzers.Tests.CSharp/CodeFixProviderTests/InternalSetupSpecificationCodeFixProviderTests/InternalSetupSpecificationCodeFixActionsTests.cs @@ -1,5 +1,11 @@ -using System.Threading.Tasks; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CodeFixes; +using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.Diagnostics; using NSubstitute.Analyzers.CSharp.CodeFixProviders; using NSubstitute.Analyzers.CSharp.DiagnosticAnalyzers; @@ -43,6 +49,7 @@ public void Test() public async Task DoesNotCreateCodeActions_WhenSymbol_DoesNotBelongToCompilation() { var source = @"using NSubstitute; +using ExternalNamespace; namespace MyNamespace { @@ -50,14 +57,19 @@ public class FooTests { public void Test() { - var substitute = NSubstitute.Substitute.For(); - var x = substitute.ToString().Returns(string.Empty); + var substitute = NSubstitute.Substitute.For(); + var x = substitute.Bar().Returns(1); } } }"; await VerifyCodeActions(source); } + protected override IEnumerable GetAdditionalMetadataReferences() + { + return new[] { GetInternalLibraryMetadataReference() }; + } + protected override DiagnosticAnalyzer GetDiagnosticAnalyzer() { return new NonSubstitutableMemberAnalyzer(); @@ -67,5 +79,40 @@ protected override CodeFixProvider GetCodeFixProvider() { return new InternalSetupSpecificationCodeFixProvider(); } + + private static PortableExecutableReference GetInternalLibraryMetadataReference() + { + var syntaxTree = CSharpSyntaxTree.ParseText($@" +using System.Runtime.CompilerServices; +[assembly: InternalsVisibleTo(""{TestProjectName}"")] +namespace ExternalNamespace +{{ + public class InternalFoo + {{ + internal virtual int Bar() + {{ + return 1; + }} + }} +}}"); + + var references = new[] { MetadataReference.CreateFromFile(typeof(object).Assembly.Location) }; + var compilationOptions = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary); + var compilation = CSharpCompilation.Create("Internal", new[] { syntaxTree }, references, compilationOptions); + + using (var ms = new MemoryStream()) + { + var result = compilation.Emit(ms); + + if (result.Success == false) + { + var errors = result.Diagnostics.Where(diag => diag.IsWarningAsError || diag.Severity == DiagnosticSeverity.Error); + throw new InvalidOperationException($"Internal library compilation failed: {string.Join(",", errors)}"); + } + + ms.Seek(0, SeekOrigin.Begin); + return MetadataReference.CreateFromStream(ms); + } + } } } \ No newline at end of file diff --git a/tests/NSubstitute.Analyzers.Tests.VisualBasic/CodeFixProvidersTests/InternalSetupSpecificationCodeFixProviderTests/InternalSetupSpecificationCodeFixActionsTests.cs b/tests/NSubstitute.Analyzers.Tests.VisualBasic/CodeFixProvidersTests/InternalSetupSpecificationCodeFixProviderTests/InternalSetupSpecificationCodeFixActionsTests.cs index e085e30e..6af9be49 100644 --- a/tests/NSubstitute.Analyzers.Tests.VisualBasic/CodeFixProvidersTests/InternalSetupSpecificationCodeFixProviderTests/InternalSetupSpecificationCodeFixActionsTests.cs +++ b/tests/NSubstitute.Analyzers.Tests.VisualBasic/CodeFixProvidersTests/InternalSetupSpecificationCodeFixProviderTests/InternalSetupSpecificationCodeFixActionsTests.cs @@ -1,6 +1,12 @@ -using System.Threading.Tasks; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CodeFixes; using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.VisualBasic; using NSubstitute.Analyzers.Tests.Shared.CodeFixProviders; using NSubstitute.Analyzers.VisualBasic.CodeFixProviders; using NSubstitute.Analyzers.VisualBasic.DiagnosticAnalyzers; @@ -38,15 +44,17 @@ End Namespace public async Task DoesNotCreateCodeActions_WhenSymbol_DoesNotBelongToCompilation() { var source = @"Imports NSubstitute +Imports ExternalNamespace Namespace MyNamespace Public Class FooTests Public Sub Test() - Dim substitute = NSubstitute.Substitute.[For](Of Object)() - Dim x = substitute.ToString().Returns(String.Empty) + Dim substitute = NSubstitute.Substitute.[For](Of InternalFoo)() + Dim x = substitute.Bar().Returns(1) End Sub End Class End Namespace"; + await VerifyCodeActions(source); } @@ -59,5 +67,43 @@ protected override CodeFixProvider GetCodeFixProvider() { return new InternalSetupSpecificationCodeFixProvider(); } + + protected override IEnumerable GetAdditionalMetadataReferences() + { + return new[] { GetInternalLibraryMetadataReference() }; + } + + private static PortableExecutableReference GetInternalLibraryMetadataReference() + { + var syntaxTree = VisualBasicSyntaxTree.ParseText($@"Imports System.Runtime.CompilerServices + + +Namespace ExternalNamespace + Public Class InternalFoo + Friend Overridable Function Bar() As Integer + Return 1 + End Function + End Class +End Namespace +"); + + var references = new[] { MetadataReference.CreateFromFile(typeof(object).Assembly.Location) }; + var compilationOptions = new VisualBasicCompilationOptions(OutputKind.DynamicallyLinkedLibrary); + var compilation = VisualBasicCompilation.Create("Internal", new[] { syntaxTree }, references, compilationOptions); + + using (var ms = new MemoryStream()) + { + var result = compilation.Emit(ms); + + if (result.Success == false) + { + var errors = result.Diagnostics.Where(diag => diag.IsWarningAsError || diag.Severity == DiagnosticSeverity.Error); + throw new InvalidOperationException($"Internal library compilation failed: {string.Join(",", errors)}"); + } + + ms.Seek(0, SeekOrigin.Begin); + return MetadataReference.CreateFromStream(ms); + } + } } } \ No newline at end of file