From 53b658c6ce32f71d281f8262f7798f33a8e9fc1c Mon Sep 17 00:00:00 2001 From: get-me-power Date: Wed, 24 Jan 2024 20:48:04 +0900 Subject: [PATCH 1/5] update: test project version --- .../Dena.CodeAnalysis.Testing.Tests.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Dena.CodeAnalysis.Testing.Tests/Dena.CodeAnalysis.Testing.Tests.csproj b/tests/Dena.CodeAnalysis.Testing.Tests/Dena.CodeAnalysis.Testing.Tests.csproj index 2c07dab..6fcc1b2 100644 --- a/tests/Dena.CodeAnalysis.Testing.Tests/Dena.CodeAnalysis.Testing.Tests.csproj +++ b/tests/Dena.CodeAnalysis.Testing.Tests/Dena.CodeAnalysis.Testing.Tests.csproj @@ -1,7 +1,7 @@ - netcoreapp5.0 + net6.0 true true From fabbffba141eaa0642f4761f8042f604861f4bdd Mon Sep 17 00:00:00 2001 From: get-me-power Date: Wed, 24 Jan 2024 22:00:10 +0900 Subject: [PATCH 2/5] feature: can read metadata --- .../AnalyzerRunner.cs | 27 ++++++++++++++----- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/src/Dena.CodeAnalysis.Testing/AnalyzerRunner.cs b/src/Dena.CodeAnalysis.Testing/AnalyzerRunner.cs index 74931ab..5f8281b 100644 --- a/src/Dena.CodeAnalysis.Testing/AnalyzerRunner.cs +++ b/src/Dena.CodeAnalysis.Testing/AnalyzerRunner.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Linq; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Diagnostics; @@ -12,7 +13,6 @@ using Microsoft.VisualStudio.Composition; - namespace Dena.CodeAnalysis.CSharp.Testing { /// @@ -31,11 +31,13 @@ public static class DiagnosticAnalyzerRunner /// Run the specified . /// /// The to run. + /// /// The target code that the analyze. /// ImmutableArray contains all reported . /// Throws if are empty. public static async Task> Run( DiagnosticAnalyzer analyzer, + Type[] types = default, params string[] codes ) => await Run( @@ -43,10 +45,10 @@ await Run( CancellationToken.None, ParseOptionsForLanguageVersionsDefault(), CompilationOptionsForDynamicClassLibrary(), + MetadataReferencesDefault(types), codes ); - /// /// Run the specified . /// @@ -63,6 +65,7 @@ public static async Task> Run( CancellationToken cancellationToken, ParseOptions parseOptions, CompilationOptions compilationOptions, + IEnumerable metadataReferences, params string[] codes ) { @@ -89,10 +92,6 @@ params string[] codes var noMetadataReferencedProject = solution.Projects.First(); - // NOTE: Make .NET standard libraries visible to the specified codes to analyze. - var metadataReferences = - await ReferenceAssemblies.Default.ResolveAsync(Language, CancellationToken.None); - var project = noMetadataReferencedProject .AddMetadataReferences(metadataReferences) .WithParseOptions(parseOptions) @@ -120,6 +119,21 @@ public static CompilationOptions CompilationOptionsForDynamicClassLibrary() => public static ParseOptions ParseOptionsForLanguageVersionsDefault() => new CSharpParseOptions(DefaultLanguageVersion, DocumentationMode.Diagnose); + private static IEnumerable MetadataReferencesDefault(Type[] types) + { + var metadataReferences = ReferenceAssemblies.Default.ResolveAsync(Language, CancellationToken.None).Result + .ToList(); + if (types != null) + { + foreach (var type in types) + { + metadataReferences.Add(MetadataReference.CreateFromFile(type.Assembly.Location)); + } + } + + return metadataReferences; + } + /// /// This value is equivalent to @@ -191,7 +205,6 @@ static DiagnosticAnalyzerRunner() } - /// /// None of codes specified but at least one code must be required. /// From 70568cde25ff239fafc19783f104103dc5727eea Mon Sep 17 00:00:00 2001 From: get-me-power Date: Wed, 24 Jan 2024 22:00:23 +0900 Subject: [PATCH 3/5] test: add Unitask case diff --git a/tests/Dena.CodeAnalysis.Testing.Tests/AnalyzerRunnerTests.cs b/tests/Dena.CodeAnalysis.Testing.Tests/AnalyzerRunnerTests.cs index b1b8f4e..fd4e358 100644 --- a/tests/Dena.CodeAnalysis.Testing.Tests/AnalyzerRunnerTests.cs +++ b/tests/Dena.CodeAnalysis.Testing.Tests/AnalyzerRunnerTests.cs @@ -1,4 +1,5 @@ using System.Threading.Tasks; +using Cysharp.Threading.Tasks; using Microsoft.VisualStudio.TestTools.UnitTesting; using MSTestAssert = Microsoft.VisualStudio.TestTools.UnitTesting.Assert; @@ -25,12 +26,24 @@ namespace Dena.CodeAnalysis.CSharp.Testing var anyAnalyzer = new NullAnalyzer(); var diagnostics = await DiagnosticAnalyzerRunner.Run( anyAnalyzer, - ExampleCode.DiagnosticsFreeClassLibrary + codes: ExampleCode.DiagnosticsFreeClassLibrary ); MSTestAssert.AreEqual(0, diagnostics.Length, DiagnosticsFormatter.Format(diagnostics)); } + [TestMethod] + public async Task WhenGivenUniTaskImport_ItShouldReturnNoDiagnostics() + { + var anyAnalyzer = new NullAnalyzer(); + var diagnostics = await DiagnosticAnalyzerRunner.Run( + anyAnalyzer, + new[] { typeof(UniTask) }, + ExampleCode.UniTaskImport + ); + + MSTestAssert.AreEqual(1, diagnostics.Length, DiagnosticsFormatter.Format(diagnostics)); + } [TestMethod] public async Task WhenGivenContainingASyntaxError_ItShouldReturnSeveralDiagnostics() @@ -38,7 +51,7 @@ namespace Dena.CodeAnalysis.CSharp.Testing var anyAnalyzer = new NullAnalyzer(); var diagnostics = await DiagnosticAnalyzerRunner.Run( anyAnalyzer, - ExampleCode.ContainingSyntaxError + codes: ExampleCode.ContainingSyntaxError ); MSTestAssert.AreNotEqual(0, diagnostics.Length); @@ -50,7 +63,7 @@ namespace Dena.CodeAnalysis.CSharp.Testing { var spyAnalyzer = new SpyAnalyzer(); - await DiagnosticAnalyzerRunner.Run(spyAnalyzer, ExampleCode.DiagnosticsFreeClassLibrary); + await DiagnosticAnalyzerRunner.Run(spyAnalyzer, codes: ExampleCode.DiagnosticsFreeClassLibrary); MSTestAssert.IsTrue(spyAnalyzer.IsInitialized); } --- src/Dena.CodeAnalysis.Testing/ExampleCode.cs | 10 ++++++++++ .../AnalyzerRunnerTests.cs | 19 ++++++++++++++++--- .../Dena.CodeAnalysis.Testing.Tests.csproj | 1 + 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/src/Dena.CodeAnalysis.Testing/ExampleCode.cs b/src/Dena.CodeAnalysis.Testing/ExampleCode.cs index f2f1f37..7a62c0a 100644 --- a/src/Dena.CodeAnalysis.Testing/ExampleCode.cs +++ b/src/Dena.CodeAnalysis.Testing/ExampleCode.cs @@ -22,6 +22,16 @@ internal static void Bar() } "; + public const string UniTaskImport = @" +using Cysharp.Threading.Tasks; +internal static class Foo +{ + internal static void Bar() + { + System.Console.WriteLine(""Hello, World!""); + } +}"; + /// /// An example code that contains a syntax error. /// diff --git a/tests/Dena.CodeAnalysis.Testing.Tests/AnalyzerRunnerTests.cs b/tests/Dena.CodeAnalysis.Testing.Tests/AnalyzerRunnerTests.cs index b1b8f4e..fd4e358 100644 --- a/tests/Dena.CodeAnalysis.Testing.Tests/AnalyzerRunnerTests.cs +++ b/tests/Dena.CodeAnalysis.Testing.Tests/AnalyzerRunnerTests.cs @@ -1,4 +1,5 @@ using System.Threading.Tasks; +using Cysharp.Threading.Tasks; using Microsoft.VisualStudio.TestTools.UnitTesting; using MSTestAssert = Microsoft.VisualStudio.TestTools.UnitTesting.Assert; @@ -25,12 +26,24 @@ public async Task WhenGivenDiagnosticCleanCode_ItShouldReturnNoDiagnostics() var anyAnalyzer = new NullAnalyzer(); var diagnostics = await DiagnosticAnalyzerRunner.Run( anyAnalyzer, - ExampleCode.DiagnosticsFreeClassLibrary + codes: ExampleCode.DiagnosticsFreeClassLibrary ); MSTestAssert.AreEqual(0, diagnostics.Length, DiagnosticsFormatter.Format(diagnostics)); } + [TestMethod] + public async Task WhenGivenUniTaskImport_ItShouldReturnNoDiagnostics() + { + var anyAnalyzer = new NullAnalyzer(); + var diagnostics = await DiagnosticAnalyzerRunner.Run( + anyAnalyzer, + new[] { typeof(UniTask) }, + ExampleCode.UniTaskImport + ); + + MSTestAssert.AreEqual(1, diagnostics.Length, DiagnosticsFormatter.Format(diagnostics)); + } [TestMethod] public async Task WhenGivenContainingASyntaxError_ItShouldReturnSeveralDiagnostics() @@ -38,7 +51,7 @@ public async Task WhenGivenContainingASyntaxError_ItShouldReturnSeveralDiagnosti var anyAnalyzer = new NullAnalyzer(); var diagnostics = await DiagnosticAnalyzerRunner.Run( anyAnalyzer, - ExampleCode.ContainingSyntaxError + codes: ExampleCode.ContainingSyntaxError ); MSTestAssert.AreNotEqual(0, diagnostics.Length); @@ -50,7 +63,7 @@ public async Task WhenGivenAnyCodes_ItShouldCallAnalyzerInitialize() { var spyAnalyzer = new SpyAnalyzer(); - await DiagnosticAnalyzerRunner.Run(spyAnalyzer, ExampleCode.DiagnosticsFreeClassLibrary); + await DiagnosticAnalyzerRunner.Run(spyAnalyzer, codes: ExampleCode.DiagnosticsFreeClassLibrary); MSTestAssert.IsTrue(spyAnalyzer.IsInitialized); } diff --git a/tests/Dena.CodeAnalysis.Testing.Tests/Dena.CodeAnalysis.Testing.Tests.csproj b/tests/Dena.CodeAnalysis.Testing.Tests/Dena.CodeAnalysis.Testing.Tests.csproj index 6fcc1b2..061a0f8 100644 --- a/tests/Dena.CodeAnalysis.Testing.Tests/Dena.CodeAnalysis.Testing.Tests.csproj +++ b/tests/Dena.CodeAnalysis.Testing.Tests/Dena.CodeAnalysis.Testing.Tests.csproj @@ -9,6 +9,7 @@ + runtime; build; native; contentfiles; analyzers all From c7216567ba265c7f52fb29f34ca6fae7baa61912 Mon Sep 17 00:00:00 2001 From: get-me-power Date: Wed, 24 Jan 2024 22:02:14 +0900 Subject: [PATCH 4/5] refactor: add name for params --- .../DiagnosticsFormatterTests.cs | 3 +-- .../LocationFactory.cs | 2 +- .../SpyAnalyzerTests.cs | 3 +-- .../StubAnalyzerTests.cs | 25 +++++++++---------- 4 files changed, 15 insertions(+), 18 deletions(-) diff --git a/tests/Dena.CodeAnalysis.Testing.Tests/DiagnosticsFormatterTests.cs b/tests/Dena.CodeAnalysis.Testing.Tests/DiagnosticsFormatterTests.cs index 3ca200e..d5925bb 100644 --- a/tests/Dena.CodeAnalysis.Testing.Tests/DiagnosticsFormatterTests.cs +++ b/tests/Dena.CodeAnalysis.Testing.Tests/DiagnosticsFormatterTests.cs @@ -3,7 +3,6 @@ using MSTestAssert = Microsoft.VisualStudio.TestTools.UnitTesting.Assert; - namespace Dena.CodeAnalysis.CSharp.Testing { [TestClass] @@ -14,7 +13,7 @@ public async Task Format() { var diagnostics = await DiagnosticAnalyzerRunner.Run( new NullAnalyzer(), - ExampleCode.ContainingSyntaxError + codes: ExampleCode.ContainingSyntaxError ); var actual = DiagnosticsFormatter.Format(diagnostics); diff --git a/tests/Dena.CodeAnalysis.Testing.Tests/LocationFactory.cs b/tests/Dena.CodeAnalysis.Testing.Tests/LocationFactory.cs index 1581911..4b602b9 100644 --- a/tests/Dena.CodeAnalysis.Testing.Tests/LocationFactory.cs +++ b/tests/Dena.CodeAnalysis.Testing.Tests/LocationFactory.cs @@ -11,7 +11,7 @@ public static async Task Create() { var ds = await DiagnosticAnalyzerRunner.Run( new NullAnalyzer(), - ExampleCode.ContainingSyntaxError + codes: ExampleCode.ContainingSyntaxError ); return ds[0].Location; } diff --git a/tests/Dena.CodeAnalysis.Testing.Tests/SpyAnalyzerTests.cs b/tests/Dena.CodeAnalysis.Testing.Tests/SpyAnalyzerTests.cs index 9cc0282..a5d8e1f 100644 --- a/tests/Dena.CodeAnalysis.Testing.Tests/SpyAnalyzerTests.cs +++ b/tests/Dena.CodeAnalysis.Testing.Tests/SpyAnalyzerTests.cs @@ -4,7 +4,6 @@ using MSTestAssert = Microsoft.VisualStudio.TestTools.UnitTesting.Assert; - namespace Dena.CodeAnalysis.CSharp.Testing { [TestClass] @@ -17,7 +16,7 @@ public async Task WhenGivenAnyCodes_RecordAllActionHistory() var builder = new StringBuilder(); var failed = false; - await DiagnosticAnalyzerRunner.Run(spy, ExampleCode.DiagnosticsFreeClassLibrary); + await DiagnosticAnalyzerRunner.Run(spy, codes: ExampleCode.DiagnosticsFreeClassLibrary); if (0 == spy.CodeBlockActionHistory.Count) { diff --git a/tests/Dena.CodeAnalysis.Testing.Tests/StubAnalyzerTests.cs b/tests/Dena.CodeAnalysis.Testing.Tests/StubAnalyzerTests.cs index e9e5c37..8517ad3 100644 --- a/tests/Dena.CodeAnalysis.Testing.Tests/StubAnalyzerTests.cs +++ b/tests/Dena.CodeAnalysis.Testing.Tests/StubAnalyzerTests.cs @@ -3,7 +3,6 @@ using MSTestAssert = Microsoft.VisualStudio.TestTools.UnitTesting.Assert; - namespace Dena.CodeAnalysis.CSharp.Testing { [TestClass] @@ -20,7 +19,7 @@ public async Task WhenGivenAnyCodes_ItShouldGetToCallCodeBlockAction() } ); - await DiagnosticAnalyzerRunner.Run(stubAnalyzer, ExampleCode.DiagnosticsFreeClassLibrary); + await DiagnosticAnalyzerRunner.Run(stubAnalyzer, codes: ExampleCode.DiagnosticsFreeClassLibrary); MSTestAssert.AreNotEqual(0, callCount); } @@ -37,7 +36,7 @@ public async Task WhenGivenAnyCodes_ItShouldGetToCallCodeBlockStartAction() } ); - await DiagnosticAnalyzerRunner.Run(stubAnalyzer, ExampleCode.DiagnosticsFreeClassLibrary); + await DiagnosticAnalyzerRunner.Run(stubAnalyzer, codes: ExampleCode.DiagnosticsFreeClassLibrary); MSTestAssert.AreNotEqual(0, callCount); } @@ -54,7 +53,7 @@ public async Task WhenGivenAnyCodes_ItShouldGetToCallCompilationAction() } ); - await DiagnosticAnalyzerRunner.Run(stubAnalyzer, ExampleCode.DiagnosticsFreeClassLibrary); + await DiagnosticAnalyzerRunner.Run(stubAnalyzer, codes: ExampleCode.DiagnosticsFreeClassLibrary); MSTestAssert.AreNotEqual(0, callCount); } @@ -71,7 +70,7 @@ public async Task WhenGivenAnyCodes_ItShouldGetToCallCompilationStartAction() } ); - await DiagnosticAnalyzerRunner.Run(stubAnalyzer, ExampleCode.DiagnosticsFreeClassLibrary); + await DiagnosticAnalyzerRunner.Run(stubAnalyzer, codes: ExampleCode.DiagnosticsFreeClassLibrary); MSTestAssert.AreNotEqual(0, callCount); } @@ -88,7 +87,7 @@ public async Task WhenGivenAnyCodes_ItShouldGetToCallOperationAction() } ); - await DiagnosticAnalyzerRunner.Run(stubAnalyzer, ExampleCode.DiagnosticsFreeClassLibrary); + await DiagnosticAnalyzerRunner.Run(stubAnalyzer, codes: ExampleCode.DiagnosticsFreeClassLibrary); MSTestAssert.AreNotEqual(0, callCount); } @@ -105,7 +104,7 @@ public async Task WhenGivenAnyCodes_ItShouldGetToCallOperationBlockAction() } ); - await DiagnosticAnalyzerRunner.Run(stubAnalyzer, ExampleCode.DiagnosticsFreeClassLibrary); + await DiagnosticAnalyzerRunner.Run(stubAnalyzer, codes: ExampleCode.DiagnosticsFreeClassLibrary); MSTestAssert.AreNotEqual(0, callCount); } @@ -122,7 +121,7 @@ public async Task WhenGivenAnyCodes_ItShouldGetToCallOperationBlockStartAction() } ); - await DiagnosticAnalyzerRunner.Run(stubAnalyzer, ExampleCode.DiagnosticsFreeClassLibrary); + await DiagnosticAnalyzerRunner.Run(stubAnalyzer, codes: ExampleCode.DiagnosticsFreeClassLibrary); MSTestAssert.AreNotEqual(0, callCount); } @@ -139,7 +138,7 @@ public async Task WhenGivenAnyCodes_ItShouldGetToCallSemanticModelAction() } ); - await DiagnosticAnalyzerRunner.Run(stubAnalyzer, ExampleCode.DiagnosticsFreeClassLibrary); + await DiagnosticAnalyzerRunner.Run(stubAnalyzer, codes: ExampleCode.DiagnosticsFreeClassLibrary); MSTestAssert.AreNotEqual(0, callCount); } @@ -156,7 +155,7 @@ public async Task WhenGivenAnyCodes_ItShouldGetToCallSymbolAction() } ); - await DiagnosticAnalyzerRunner.Run(stubAnalyzer, ExampleCode.DiagnosticsFreeClassLibrary); + await DiagnosticAnalyzerRunner.Run(stubAnalyzer, codes: ExampleCode.DiagnosticsFreeClassLibrary); MSTestAssert.AreNotEqual(0, callCount); } @@ -173,7 +172,7 @@ public async Task WhenGivenAnyCodes_ItShouldGetToCallSymbolStartAction() } ); - await DiagnosticAnalyzerRunner.Run(stubAnalyzer, ExampleCode.DiagnosticsFreeClassLibrary); + await DiagnosticAnalyzerRunner.Run(stubAnalyzer, codes: ExampleCode.DiagnosticsFreeClassLibrary); MSTestAssert.AreNotEqual(0, callCount); } @@ -190,7 +189,7 @@ public async Task WhenGivenAnyCodes_ItShouldGetToCallSyntaxNodeAction() } ); - await DiagnosticAnalyzerRunner.Run(stubAnalyzer, ExampleCode.DiagnosticsFreeClassLibrary); + await DiagnosticAnalyzerRunner.Run(stubAnalyzer, codes: ExampleCode.DiagnosticsFreeClassLibrary); MSTestAssert.AreNotEqual(0, callCount); } @@ -207,7 +206,7 @@ public async Task WhenGivenAnyCodes_ItShouldGetToCallSyntaxTreeAction() } ); - await DiagnosticAnalyzerRunner.Run(stubAnalyzer, ExampleCode.DiagnosticsFreeClassLibrary); + await DiagnosticAnalyzerRunner.Run(stubAnalyzer, codes: ExampleCode.DiagnosticsFreeClassLibrary); MSTestAssert.AreNotEqual(0, callCount); } From 3852aea514ce45a2a3ce68214980ce949b2b0f67 Mon Sep 17 00:00:00 2001 From: get-me-power Date: Wed, 24 Jan 2024 23:47:45 +0900 Subject: [PATCH 5/5] docs: update xml comment --- src/Dena.CodeAnalysis.Testing/AnalyzerRunner.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Dena.CodeAnalysis.Testing/AnalyzerRunner.cs b/src/Dena.CodeAnalysis.Testing/AnalyzerRunner.cs index 5f8281b..e8e60f1 100644 --- a/src/Dena.CodeAnalysis.Testing/AnalyzerRunner.cs +++ b/src/Dena.CodeAnalysis.Testing/AnalyzerRunner.cs @@ -31,7 +31,7 @@ public static class DiagnosticAnalyzerRunner /// Run the specified . /// /// The to run. - /// + /// The type of metadata you want to add. /// The target code that the analyze. /// ImmutableArray contains all reported . /// Throws if are empty.