From c3b186f90c32398fd02c6d027c12cb7a6c4cc399 Mon Sep 17 00:00:00 2001 From: David Vreony Date: Mon, 3 Jun 2024 23:53:51 +0100 Subject: [PATCH 1/3] prep to inject test config + mahapps --- ...AppsMetroViewBindingModelGeneratorTests.cs | 82 +++++++++++++++++++ .../WPF/WpfViewBindingModelGeneratorTests.cs | 7 ++ .../WinUi3ViewBindingModelGeneratorTests.cs | 7 ++ .../WinformsViewBindingModelGeneratorTests.cs | 7 ++ .../Vetuviem.IntegrationTests.csproj | 5 ++ src/Vetuviem.Testing/BaseGeneratorTests.cs | 34 +++++++- .../TestAnalyzerConfigOptionsProvider.cs | 25 ++++++ 7 files changed, 163 insertions(+), 4 deletions(-) create mode 100644 src/Vetuviem.IntegrationTests/ReactiveUI/WPF/MahAppsMetroViewBindingModelGeneratorTests.cs create mode 100644 src/Vetuviem.Testing/TestAnalyzerConfigOptionsProvider.cs diff --git a/src/Vetuviem.IntegrationTests/ReactiveUI/WPF/MahAppsMetroViewBindingModelGeneratorTests.cs b/src/Vetuviem.IntegrationTests/ReactiveUI/WPF/MahAppsMetroViewBindingModelGeneratorTests.cs new file mode 100644 index 00000000..9e9b1d23 --- /dev/null +++ b/src/Vetuviem.IntegrationTests/ReactiveUI/WPF/MahAppsMetroViewBindingModelGeneratorTests.cs @@ -0,0 +1,82 @@ +// Copyright (c) 2022 DPVreony and Contributors. All rights reserved. +// DPVreony and Contributors licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +using System; +using System.Collections.Generic; +using System.IO; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Diagnostics; +using Vetuviem.SourceGenerator.Features.ControlBindingModels; +using Vetuviem.Testing; +using Vetuviem.WPF.SourceGenerator; +using Xunit.Abstractions; + +namespace Vetuviem.IntegrationTests.ReactiveUI.WPF +{ + /// + /// Unit Tests for the ViewBinding Model Source Generator for MahApps Metro. + /// + public static class MahAppsMetroViewBindingModelGeneratorTests + { + /// + public sealed class ExecuteMethod : BaseGeneratorTests.BaseExecuteMethod + { + /// + /// Initializes a new instance of the class. + /// + /// Test Output Helper. + public ExecuteMethod(ITestOutputHelper output) + : base(output) + { + } + + /// + protected override AnalyzerConfigOptionsProvider? GetAnalyzerConfigOptionsProvider() + { + return null; + } + + /// + protected override void AddReferenceAssemblies(IList metadataReferences) + { + if (metadataReferences == null) + { + throw new ArgumentNullException(nameof(metadataReferences)); + } + + var trustedAssembliesPaths = GetPlatformAssemblyPaths(); + if (trustedAssembliesPaths == null) + { + return; + } + + foreach (string trustedAssembliesPath in trustedAssembliesPaths) + { + var metadataReference = MetadataReference.CreateFromFile(trustedAssembliesPath); + if (metadataReference == null) + { + throw new InvalidOperationException($"Failed to create metadata reference for {trustedAssembliesPath}"); + } + metadataReferences.Add(metadataReference); + } + } + + /// + protected override Func GetFactory() + { + return () => new WpfControlBindingModelSourceGenerator(); + } + + private static string[]? GetPlatformAssemblyPaths() + { + if (AppContext.GetData("TRUSTED_PLATFORM_ASSEMBLIES") is string trustedPlatformAssemblies) + { + return trustedPlatformAssemblies.Split(Path.PathSeparator); + } + + return null; + } + } + } +} diff --git a/src/Vetuviem.IntegrationTests/ReactiveUI/WPF/WpfViewBindingModelGeneratorTests.cs b/src/Vetuviem.IntegrationTests/ReactiveUI/WPF/WpfViewBindingModelGeneratorTests.cs index e6a664f6..0a4871c2 100644 --- a/src/Vetuviem.IntegrationTests/ReactiveUI/WPF/WpfViewBindingModelGeneratorTests.cs +++ b/src/Vetuviem.IntegrationTests/ReactiveUI/WPF/WpfViewBindingModelGeneratorTests.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.IO; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Diagnostics; using Vetuviem.SourceGenerator.Features.ControlBindingModels; using Vetuviem.Testing; using Vetuviem.WPF.SourceGenerator; @@ -30,6 +31,12 @@ public ExecuteMethod(ITestOutputHelper output) { } + /// + protected override AnalyzerConfigOptionsProvider? GetAnalyzerConfigOptionsProvider() + { + return null; + } + /// protected override void AddReferenceAssemblies(IList metadataReferences) { diff --git a/src/Vetuviem.IntegrationTests/ReactiveUI/WinUi3/WinUi3ViewBindingModelGeneratorTests.cs b/src/Vetuviem.IntegrationTests/ReactiveUI/WinUi3/WinUi3ViewBindingModelGeneratorTests.cs index 7d0de060..7415ae19 100644 --- a/src/Vetuviem.IntegrationTests/ReactiveUI/WinUi3/WinUi3ViewBindingModelGeneratorTests.cs +++ b/src/Vetuviem.IntegrationTests/ReactiveUI/WinUi3/WinUi3ViewBindingModelGeneratorTests.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Diagnostics; using Vetuviem.SourceGenerator.Features.ControlBindingModels; using Vetuviem.Testing; using Vetuviem.WinUi.SourceGenerator; @@ -29,6 +30,12 @@ public ExecuteMethod(ITestOutputHelper output) { } + /// + protected override AnalyzerConfigOptionsProvider? GetAnalyzerConfigOptionsProvider() + { + return null; + } + /// protected override void AddReferenceAssemblies(IList metadataReferences) { diff --git a/src/Vetuviem.IntegrationTests/ReactiveUI/Winforms/WinformsViewBindingModelGeneratorTests.cs b/src/Vetuviem.IntegrationTests/ReactiveUI/Winforms/WinformsViewBindingModelGeneratorTests.cs index cdfaa380..193cb4e5 100644 --- a/src/Vetuviem.IntegrationTests/ReactiveUI/Winforms/WinformsViewBindingModelGeneratorTests.cs +++ b/src/Vetuviem.IntegrationTests/ReactiveUI/Winforms/WinformsViewBindingModelGeneratorTests.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.IO; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Diagnostics; using Vetuviem.SourceGenerator.Features.ControlBindingModels; using Vetuviem.Testing; using Vetuviem.Winforms.SourceGenerator; @@ -30,6 +31,12 @@ public ExecuteMethod(ITestOutputHelper output) { } + /// + protected override AnalyzerConfigOptionsProvider? GetAnalyzerConfigOptionsProvider() + { + return null; + } + /// protected override void AddReferenceAssemblies(IList metadataReferences) { diff --git a/src/Vetuviem.IntegrationTests/Vetuviem.IntegrationTests.csproj b/src/Vetuviem.IntegrationTests/Vetuviem.IntegrationTests.csproj index a1ec0365..726ebe9f 100644 --- a/src/Vetuviem.IntegrationTests/Vetuviem.IntegrationTests.csproj +++ b/src/Vetuviem.IntegrationTests/Vetuviem.IntegrationTests.csproj @@ -6,6 +6,11 @@ False + + + + + diff --git a/src/Vetuviem.Testing/BaseGeneratorTests.cs b/src/Vetuviem.Testing/BaseGeneratorTests.cs index 1c31cae4..3b0e2f70 100644 --- a/src/Vetuviem.Testing/BaseGeneratorTests.cs +++ b/src/Vetuviem.Testing/BaseGeneratorTests.cs @@ -10,6 +10,7 @@ using System.Reflection; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.Extensions.Logging; using Vetuviem.SourceGenerator; using Vetuviem.SourceGenerator.Features.Core; @@ -61,8 +62,11 @@ public void GeneratesCode() var comp = CreateCompilation(string.Empty, references); + var analyzerConfigOptionsProvider = GetAnalyzerConfigOptionsProvider(); + var newComp = RunGenerators( comp, + analyzerConfigOptionsProvider, out var generatorDiags, instance); @@ -79,6 +83,12 @@ public void GeneratesCode() Assert.False(hasErrors); } + /// + /// Gets the analyzer config options provider to test with. + /// + /// Analyzer Config Options. + protected abstract AnalyzerConfigOptionsProvider? GetAnalyzerConfigOptionsProvider(); + /// /// Allows addition of platform specific metadata references. Unit Tests start in an agnostic fashion /// with no specific references loaded. Source generators typically take these via MSBuild loading @@ -99,15 +109,31 @@ private static Compilation CreateCompilation(string source, IEnumerable CSharpGeneratorDriver.Create( + private static GeneratorDriver CreateDriver( + Compilation compilation, + AnalyzerConfigOptionsProvider? analyzerConfigOptionsProvider, + params ISourceGenerator[] generators) => CSharpGeneratorDriver.Create( generators: ImmutableArray.Create(generators), additionalTexts: ImmutableArray.Empty, parseOptions: (CSharpParseOptions)compilation.SyntaxTrees.First().Options, - optionsProvider: null); + optionsProvider: analyzerConfigOptionsProvider); - private static Compilation RunGenerators(Compilation compilation, out ImmutableArray diagnostics, params ISourceGenerator[] generators) + private static Compilation RunGenerators( + Compilation compilation, + AnalyzerConfigOptionsProvider? analyzerConfigOptionsProvider, + out ImmutableArray diagnostics, + params ISourceGenerator[] generators) { - CreateDriver(compilation, generators).RunGeneratorsAndUpdateCompilation(compilation, out var updatedCompilation, out diagnostics); + var driver = CreateDriver( + compilation, + analyzerConfigOptionsProvider, + generators); + + driver.RunGeneratorsAndUpdateCompilation( + compilation, + out var updatedCompilation, + out diagnostics); + return updatedCompilation; } } diff --git a/src/Vetuviem.Testing/TestAnalyzerConfigOptionsProvider.cs b/src/Vetuviem.Testing/TestAnalyzerConfigOptionsProvider.cs new file mode 100644 index 00000000..7270b9b7 --- /dev/null +++ b/src/Vetuviem.Testing/TestAnalyzerConfigOptionsProvider.cs @@ -0,0 +1,25 @@ +#if TBC +using System; +using System.Collections.Generic; +using System.Text; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Diagnostics; + +namespace Vetuviem.Testing +{ + public sealed class TestAnalyzerConfigOptionsProvider : AnalyzerConfigOptionsProvider + { + public override AnalyzerConfigOptions GetOptions(SyntaxTree tree) + { + throw new NotImplementedException(); + } + + public override AnalyzerConfigOptions GetOptions(AdditionalText textFile) + { + throw new NotImplementedException(); + } + + public override AnalyzerConfigOptions GlobalOptions { get; } + } +} +#endif From 2aa98243c4e9f898a4f3853553df97f602198b2e Mon Sep 17 00:00:00 2001 From: David Vreony Date: Tue, 4 Jun 2024 19:46:36 +0100 Subject: [PATCH 2/3] logic for injecting build property config in test --- ...AppsMetroViewBindingModelGeneratorTests.cs | 7 ++- .../Vetuviem.IntegrationTests.csproj | 3 +- .../Features/Core/ReportDiagnosticFactory.cs | 2 +- .../InMemoryAnalyzerConfigOptions.cs | 24 ++++++++++ .../InMemoryAnalyzerConfigOptionsProvider.cs | 45 +++++++++++++++++++ src/Vetuviem.Testing/Vetuviem.Testing.csproj | 7 +-- .../Vetuviem.UnitTests.csproj | 4 +- 7 files changed, 84 insertions(+), 8 deletions(-) create mode 100644 src/Vetuviem.Testing/InMemoryAnalyzerConfigOptions.cs create mode 100644 src/Vetuviem.Testing/InMemoryAnalyzerConfigOptionsProvider.cs diff --git a/src/Vetuviem.IntegrationTests/ReactiveUI/WPF/MahAppsMetroViewBindingModelGeneratorTests.cs b/src/Vetuviem.IntegrationTests/ReactiveUI/WPF/MahAppsMetroViewBindingModelGeneratorTests.cs index 9e9b1d23..8b8361a6 100644 --- a/src/Vetuviem.IntegrationTests/ReactiveUI/WPF/MahAppsMetroViewBindingModelGeneratorTests.cs +++ b/src/Vetuviem.IntegrationTests/ReactiveUI/WPF/MahAppsMetroViewBindingModelGeneratorTests.cs @@ -34,7 +34,12 @@ public ExecuteMethod(ITestOutputHelper output) /// protected override AnalyzerConfigOptionsProvider? GetAnalyzerConfigOptionsProvider() { - return null; + var globalOptions = new InMemoryAnalyzerConfigOptions(); + globalOptions.Add( + "build_property.Vetuviem_Assemblies", + "ControlzEx.dll;MahApps.Metro.dll;MahApps.Metro.SimpleChildWindow.dll"); + + return new InMemoryAnalyzerConfigOptionsProvider(globalOptions); } /// diff --git a/src/Vetuviem.IntegrationTests/Vetuviem.IntegrationTests.csproj b/src/Vetuviem.IntegrationTests/Vetuviem.IntegrationTests.csproj index 726ebe9f..0b1711e9 100644 --- a/src/Vetuviem.IntegrationTests/Vetuviem.IntegrationTests.csproj +++ b/src/Vetuviem.IntegrationTests/Vetuviem.IntegrationTests.csproj @@ -1,7 +1,7 @@  - net8.0-windows + net8.0-windows10.0.19041 True False @@ -9,6 +9,7 @@ + diff --git a/src/Vetuviem.SourceGenerator/Features/Core/ReportDiagnosticFactory.cs b/src/Vetuviem.SourceGenerator/Features/Core/ReportDiagnosticFactory.cs index 884d518e..7a55726d 100644 --- a/src/Vetuviem.SourceGenerator/Features/Core/ReportDiagnosticFactory.cs +++ b/src/Vetuviem.SourceGenerator/Features/Core/ReportDiagnosticFactory.cs @@ -45,7 +45,7 @@ public static Diagnostic StartingScanOfAssembly(MetadataReference metadataRefere { return InfoDiagnostic( ReportDiagnosticIds.StartingScanOfAssembly, - $"Starting Scan Of Namespace: {metadataReference.Display}"); + $"Starting Scan Of Assembly: {metadataReference.Display}"); } /// diff --git a/src/Vetuviem.Testing/InMemoryAnalyzerConfigOptions.cs b/src/Vetuviem.Testing/InMemoryAnalyzerConfigOptions.cs new file mode 100644 index 00000000..14bbbf27 --- /dev/null +++ b/src/Vetuviem.Testing/InMemoryAnalyzerConfigOptions.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text; +using Microsoft.CodeAnalysis.Diagnostics; + +namespace Vetuviem.Testing +{ + public sealed class InMemoryAnalyzerConfigOptions : AnalyzerConfigOptions + { + private readonly Dictionary _options = new(); + + public void Add(string key, string value) + { + _options.Add(key, value); + } + + /// + public override bool TryGetValue(string key, [NotNullWhen(true)] out string? value) + { + return _options.TryGetValue(key, out value); + } + } +} diff --git a/src/Vetuviem.Testing/InMemoryAnalyzerConfigOptionsProvider.cs b/src/Vetuviem.Testing/InMemoryAnalyzerConfigOptionsProvider.cs new file mode 100644 index 00000000..2fe38407 --- /dev/null +++ b/src/Vetuviem.Testing/InMemoryAnalyzerConfigOptionsProvider.cs @@ -0,0 +1,45 @@ +// Copyright (c) 2022 DPVreony and Contributors. All rights reserved. +// DPVreony and Contributors licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +using System.Collections.Generic; +using System.IO; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Diagnostics; + +namespace Vetuviem.Testing +{ + public sealed class InMemoryAnalyzerConfigOptionsProvider : AnalyzerConfigOptionsProvider + { + private readonly Dictionary _options = []; + private readonly AnalyzerConfigOptions _globalOptions; + + public InMemoryAnalyzerConfigOptionsProvider(AnalyzerConfigOptions globalOptions) + { + System.ArgumentNullException.ThrowIfNull(globalOptions); + _globalOptions = globalOptions; + } + + public override AnalyzerConfigOptions GetOptions(SyntaxTree tree) + { + return GetOptions(Path.GetFileName(tree.FilePath)); + } + + public override AnalyzerConfigOptions GetOptions(Microsoft.CodeAnalysis.AdditionalText textFile) + { + return GetOptions(Path.GetFileName(textFile.Path)); + } + + public override AnalyzerConfigOptions GlobalOptions => _globalOptions; + + private AnalyzerConfigOptions GetOptions(string path) + { + if (!_options.TryGetValue(path, out var options)) + { + options ??= new InMemoryAnalyzerConfigOptions(); + } + + return options; + } + } +} diff --git a/src/Vetuviem.Testing/Vetuviem.Testing.csproj b/src/Vetuviem.Testing/Vetuviem.Testing.csproj index 0a124994..a44928d3 100644 --- a/src/Vetuviem.Testing/Vetuviem.Testing.csproj +++ b/src/Vetuviem.Testing/Vetuviem.Testing.csproj @@ -1,9 +1,10 @@ - + - netstandard2.0 + net8.0 False - 8 + latest + enable diff --git a/src/Vetuviem.UnitTests/Vetuviem.UnitTests.csproj b/src/Vetuviem.UnitTests/Vetuviem.UnitTests.csproj index 799d4bfa..0f7afdc7 100644 --- a/src/Vetuviem.UnitTests/Vetuviem.UnitTests.csproj +++ b/src/Vetuviem.UnitTests/Vetuviem.UnitTests.csproj @@ -1,7 +1,7 @@ - + - net7.0 + net8.0 False From a3a70306f7818f85504ea42acdbd119b0f2d0b94 Mon Sep 17 00:00:00 2001 From: David Vreony Date: Tue, 4 Jun 2024 20:09:40 +0100 Subject: [PATCH 3/3] change split to comma --- .../WPF/MahAppsMetroViewBindingModelGeneratorTests.cs | 2 +- .../AbstractBaseSourceGenerator.cs | 2 +- src/Vetuviem.Testing/BaseGeneratorTests.cs | 9 +++++++++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/Vetuviem.IntegrationTests/ReactiveUI/WPF/MahAppsMetroViewBindingModelGeneratorTests.cs b/src/Vetuviem.IntegrationTests/ReactiveUI/WPF/MahAppsMetroViewBindingModelGeneratorTests.cs index 8b8361a6..9411b0c7 100644 --- a/src/Vetuviem.IntegrationTests/ReactiveUI/WPF/MahAppsMetroViewBindingModelGeneratorTests.cs +++ b/src/Vetuviem.IntegrationTests/ReactiveUI/WPF/MahAppsMetroViewBindingModelGeneratorTests.cs @@ -37,7 +37,7 @@ public ExecuteMethod(ITestOutputHelper output) var globalOptions = new InMemoryAnalyzerConfigOptions(); globalOptions.Add( "build_property.Vetuviem_Assemblies", - "ControlzEx.dll;MahApps.Metro.dll;MahApps.Metro.SimpleChildWindow.dll"); + "ControlzEx.dll,MahApps.Metro.dll,MahApps.Metro.SimpleChildWindow.dll"); return new InMemoryAnalyzerConfigOptionsProvider(globalOptions); } diff --git a/src/Vetuviem.SourceGenerator/AbstractBaseSourceGenerator.cs b/src/Vetuviem.SourceGenerator/AbstractBaseSourceGenerator.cs index 4309f116..63e46a10 100644 --- a/src/Vetuviem.SourceGenerator/AbstractBaseSourceGenerator.cs +++ b/src/Vetuviem.SourceGenerator/AbstractBaseSourceGenerator.cs @@ -128,7 +128,7 @@ public void Execute(GeneratorExecutionContext context) globalOptions.TryGetBuildPropertyValue("Vetuviem_Assemblies", out var assemblies); var assembliesArray = assemblies?.Split( - [';'], + [','], StringSplitOptions.RemoveEmptyEntries) .Where(s => !string.IsNullOrWhiteSpace(s)) .ToArray(); diff --git a/src/Vetuviem.Testing/BaseGeneratorTests.cs b/src/Vetuviem.Testing/BaseGeneratorTests.cs index 3b0e2f70..4b6ceb95 100644 --- a/src/Vetuviem.Testing/BaseGeneratorTests.cs +++ b/src/Vetuviem.Testing/BaseGeneratorTests.cs @@ -8,6 +8,7 @@ using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Reflection; +using Castle.Core.Logging; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.Diagnostics; @@ -80,7 +81,15 @@ public void GeneratesCode() hasErrors |= generatorDiag.Severity == DiagnosticSeverity.Error; } + foreach (var newCompSyntaxTree in newComp.SyntaxTrees) + { + _logger.LogInformation("Syntax Tree:"); + _logger.LogInformation(newCompSyntaxTree.GetText().ToString()); + } + Assert.False(hasErrors); + + } ///