diff --git a/PowerShell.sln b/PowerShell.sln
index 224d27ab3f..4938316281 100644
--- a/PowerShell.sln
+++ b/PowerShell.sln
@@ -31,6 +31,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "powershell-unix", "src\powe
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "xUnit.tests", "test\xUnit\xUnit.tests.csproj", "{08704934-9764-48CE-86DB-BCF0A1CF7899}"
EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PSVersionInfoGenerator", "src\System.Management.Automation\SourceGenerators\PSVersionInfoGenerator\PSVersionInfoGenerator.csproj", "{B22424E8-0516-4FC3-A9CB-D84D15EF0589}"
+EndProject
# Configuration mapping comment
# All global configurations must be mapped to project configurations
#
diff --git a/src/System.Management.Automation/SourceGenerators/PSVersionInfoGenerator/PSVersionInfoGenerator.cs b/src/System.Management.Automation/SourceGenerators/PSVersionInfoGenerator/PSVersionInfoGenerator.cs
index 6f5b47cca0..29325d2789 100644
--- a/src/System.Management.Automation/SourceGenerators/PSVersionInfoGenerator/PSVersionInfoGenerator.cs
+++ b/src/System.Management.Automation/SourceGenerators/PSVersionInfoGenerator/PSVersionInfoGenerator.cs
@@ -11,40 +11,70 @@ namespace SMA
/// Source Code Generator to create partial PSVersionInfo class.
///
[Generator]
- public class PSVersionInfoGenerator : ISourceGenerator
+ public class PSVersionInfoGenerator : IIncrementalGenerator
{
- ///
- /// Generate output PSVersionInfo.g.cs file.
- /// This allows to directly get ProductVersion and others without reflection.
- ///
- /// Generator execution context.
- public void Execute(GeneratorExecutionContext context)
- {
- var result = CreatePSVersionInfoPartialClass(context);
-
- // We must use specific file name suffix (*.g.cs,*.g, *.i.cs, *.generated.cs, *.designer.cs)
- // so that Roslyn analyzers skip the file.
- context.AddSource("PSVersionInfo.g.cs", result);
- }
-
///
/// Not used.
///
/// Generator initialization context.
- public void Initialize(GeneratorInitializationContext context)
+ public void Initialize(IncrementalGeneratorInitializationContext context)
{
- // No initialization required for this one.
+ IncrementalValueProvider buildOptionsProvider = context.AnalyzerConfigOptionsProvider
+ .Select(static (provider, _) =>
+ {
+ provider.GlobalOptions.TryGetValue("build_property.ProductVersion", out var productVersion);
+ provider.GlobalOptions.TryGetValue("build_property.PSCoreBuildVersion", out var mainVersion);
+ provider.GlobalOptions.TryGetValue("build_property.PowerShellVersion", out var gitDescribe);
+ provider.GlobalOptions.TryGetValue("build_property.ReleaseTag", out var releaseTag);
+
+ BuildOptions options = new()
+ {
+ ProductVersion = productVersion ?? string.Empty,
+ MainVersion = mainVersion ?? string.Empty,
+ GitDescribe = gitDescribe ?? string.Empty,
+ ReleaseTag = releaseTag ?? string.Empty
+ };
+
+ return options;
+ });
+
+ context.RegisterSourceOutput(
+ buildOptionsProvider,
+ static (context, buildOptions) =>
+ {
+ string gitCommitId = string.IsNullOrEmpty(buildOptions.ReleaseTag) ? buildOptions.GitDescribe : buildOptions.ReleaseTag;
+ if (gitCommitId.StartsWith("v"))
+ {
+ gitCommitId = gitCommitId.Substring(1);
+ }
+
+ var versions = ParsePSVersion(buildOptions.MainVersion);
+ string result = string.Format(
+ CultureInfo.InvariantCulture,
+ SourceTemplate,
+ buildOptions.ProductVersion,
+ gitCommitId,
+ versions.major,
+ versions.minor,
+ versions.patch,
+ versions.preReleaseLabel);
+
+ // We must use specific file name suffix (*.g.cs,*.g, *.i.cs, *.generated.cs, *.designer.cs)
+ // so that Roslyn analyzers skip the file.
+ context.AddSource("PSVersionInfo.g.cs", result);
+ });
}
- ///
- /// Generate source code for the partial PSVersionInfo class.
- ///
- /// Generator execution context.
- /// A string with partial PSVersionInfo class.
- private static string CreatePSVersionInfoPartialClass(GeneratorExecutionContext context)
+ private struct BuildOptions
{
- // We must put "
+ public string ProductVersion;
+ public string MainVersion;
+ public string GitDescribe;
+ public string ReleaseTag;
+ }
+
+ // We must put "
// This file is auto-generated by PSVersionInfoGenerator.
//
@@ -81,30 +111,6 @@ namespace System.Management.Automation
}}
}}";
- context.AnalyzerConfigOptions.GlobalOptions.TryGetValue("build_property.ProductVersion", out var productVersion);
- context.AnalyzerConfigOptions.GlobalOptions.TryGetValue("build_property.PSCoreBuildVersion", out var mainVersion);
- context.AnalyzerConfigOptions.GlobalOptions.TryGetValue("build_property.PowerShellVersion", out var gitDescribe);
- context.AnalyzerConfigOptions.GlobalOptions.TryGetValue("build_property.ReleaseTag", out var releaseTag);
-
- string gitCommitId = string.IsNullOrEmpty(releaseTag) ? gitDescribe : releaseTag;
- if (gitCommitId.StartsWith("v"))
- {
- gitCommitId = gitCommitId.Substring(1);
- }
-
- var result = ParsePSVersion(mainVersion);
-
- return string.Format(
- CultureInfo.InvariantCulture,
- SourceTemplate,
- productVersion,
- gitCommitId,
- result.major,
- result.minor,
- result.patch,
- result.preReleaseLabel);
- }
-
private static (int major, int minor, int patch, string preReleaseLabel) ParsePSVersion(string mainVersion)
{
// We only handle the pre-defined PSVersion format here, e.g. 7.x.x or 7.x.x-preview.x
diff --git a/src/System.Management.Automation/SourceGenerators/PSVersionInfoGenerator/PSVersionInfoGenerator.csproj b/src/System.Management.Automation/SourceGenerators/PSVersionInfoGenerator/PSVersionInfoGenerator.csproj
index fe82962adc..a8f91c5f9e 100644
--- a/src/System.Management.Automation/SourceGenerators/PSVersionInfoGenerator/PSVersionInfoGenerator.csproj
+++ b/src/System.Management.Automation/SourceGenerators/PSVersionInfoGenerator/PSVersionInfoGenerator.csproj
@@ -10,7 +10,7 @@
11.0
true
true
- RS1035
+ enable