From c398549fd6244027f3da0e88aeabbb591c7afb36 Mon Sep 17 00:00:00 2001 From: Adeel <3840695+am11@users.noreply.github.com> Date: Mon, 13 May 2024 21:30:15 +0300 Subject: [PATCH 1/6] Remove reflection from FrameworkDescription --- .../src/System/Environment.cs | 16 ++++------ .../InteropServices/RuntimeInformation.cs | 29 +++---------------- 2 files changed, 10 insertions(+), 35 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/Environment.cs b/src/libraries/System.Private.CoreLib/src/System/Environment.cs index 53028ec74d021..4b702e6d46e93 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Environment.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Environment.cs @@ -201,21 +201,17 @@ public static OperatingSystem OSVersion } } + internal const string InternalVersion = "9.0.0"; + public static Version Version { get { - string? versionString = typeof(object).Assembly.GetCustomAttribute()?.InformationalVersion; - - ReadOnlySpan versionSpan = versionString.AsSpan(); - - // Strip optional suffixes - int separatorIndex = versionSpan.IndexOfAny('-', '+', ' '); - if (separatorIndex >= 0) - versionSpan = versionSpan.Slice(0, separatorIndex); + Debug.Assert(InternalVersion == + typeof(object).Assembly.GetCustomAttribute()?.InformationalVersion?.Split('-', '+')?[0], + $"{nameof(InternalVersion)} mismatched! Keep {nameof(InternalVersion)} in sync with ProductVersion in eng/Versions.props."); - // Return zeros rather then failing if the version string fails to parse - return Version.TryParse(versionSpan, out Version? version) ? version : new Version(); + return Version.Parse(InternalVersion); } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/RuntimeInformation.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/RuntimeInformation.cs index 1bb3db3da1940..14d4cee8cabc7 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/RuntimeInformation.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/RuntimeInformation.cs @@ -1,37 +1,16 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.Reflection; - namespace System.Runtime.InteropServices { public static partial class RuntimeInformation { - private const string FrameworkName = ".NET"; - private static string? s_frameworkDescription; private static string? s_runtimeIdentifier; - public static string FrameworkDescription - { - get - { - if (s_frameworkDescription == null) - { - ReadOnlySpan versionString = typeof(object).Assembly.GetCustomAttribute()?.InformationalVersion; - - // Strip the git hash if there is one - int plusIndex = versionString.IndexOf('+'); - if (plusIndex >= 0) - { - versionString = versionString.Slice(0, plusIndex); - } - - s_frameworkDescription = !versionString.Trim().IsEmpty ? $"{FrameworkName} {versionString}" : FrameworkName; - } - - return s_frameworkDescription; - } - } + /// + /// Gets the name of the .NET installation on which an app is running. + /// + public static string FrameworkDescription { get; } = ".NET " + Environment.InternalVersion; /// /// Returns an opaque string that identifies the platform on which an app is running. From 0bbf65bfeb0abd65ed4d9d344e2aa8cb4e1d33b7 Mon Sep 17 00:00:00 2001 From: Adeel Mujahid <3840695+am11@users.noreply.github.com> Date: Mon, 13 May 2024 22:45:28 +0300 Subject: [PATCH 2/6] Remove prerelease tests --- .../DescriptionNameTests.cs | 13 ++----------- ....InteropServices.RuntimeInformation.Tests.csproj | 3 --- 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/src/libraries/System.Runtime/tests/System.Runtime.InteropServices.RuntimeInformation.Tests/DescriptionNameTests.cs b/src/libraries/System.Runtime/tests/System.Runtime.InteropServices.RuntimeInformation.Tests/DescriptionNameTests.cs index 335c9c001deee..c29191f3e1e3a 100644 --- a/src/libraries/System.Runtime/tests/System.Runtime.InteropServices.RuntimeInformation.Tests/DescriptionNameTests.cs +++ b/src/libraries/System.Runtime/tests/System.Runtime.InteropServices.RuntimeInformation.Tests/DescriptionNameTests.cs @@ -196,17 +196,8 @@ public void VerifyFrameworkDescriptionContainsCorrectVersion() return; Assert.DoesNotContain("+", version); // no git hash - -#if STABILIZE_PACKAGE_VERSION - // a stabilized version looks like 8.0.0 - Assert.DoesNotContain("-", version); - Assert.True(Version.TryParse(version, out Version _)); -#else - // a non-stabilized version looks like 8.0.0-preview.5.23280.8 or 8.0.0-dev - Assert.Contains("-", version); - var versionNumber = version.Substring(0, version.IndexOf("-")); - Assert.True(Version.TryParse(versionNumber, out Version _)); -#endif + Assert.DoesNotContain("-", version); // no labels + Assert.True(Version.TryParse(version, out _)); } [Fact] diff --git a/src/libraries/System.Runtime/tests/System.Runtime.InteropServices.RuntimeInformation.Tests/System.Runtime.InteropServices.RuntimeInformation.Tests.csproj b/src/libraries/System.Runtime/tests/System.Runtime.InteropServices.RuntimeInformation.Tests/System.Runtime.InteropServices.RuntimeInformation.Tests.csproj index 94daeb2079a35..72355db6c397d 100644 --- a/src/libraries/System.Runtime/tests/System.Runtime.InteropServices.RuntimeInformation.Tests/System.Runtime.InteropServices.RuntimeInformation.Tests.csproj +++ b/src/libraries/System.Runtime/tests/System.Runtime.InteropServices.RuntimeInformation.Tests/System.Runtime.InteropServices.RuntimeInformation.Tests.csproj @@ -4,9 +4,6 @@ true $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent)-unix;$(NetCoreAppCurrent)-browser - - $(DefineConstants);STABILIZE_PACKAGE_VERSION - From db1420daeb53a1b7588cbd2e071647ab17a14351 Mon Sep 17 00:00:00 2001 From: Adeel <3840695+am11@users.noreply.github.com> Date: Tue, 14 May 2024 04:17:39 +0300 Subject: [PATCH 3/6] Switch to source gen --- .../gen/DotnetProductVersionInfoGenerator.cs | 42 +++++++++++++++++++ .../System.Private.CoreLib.Generators.csproj | 2 + .../System.Private.CoreLib.Shared.projitems | 3 ++ .../src/System/Environment.cs | 14 +------ .../InteropServices/RuntimeInformation.cs | 2 +- .../DescriptionNameTests.cs | 13 +++++- 6 files changed, 60 insertions(+), 16 deletions(-) create mode 100644 src/libraries/System.Private.CoreLib/gen/DotnetProductVersionInfoGenerator.cs diff --git a/src/libraries/System.Private.CoreLib/gen/DotnetProductVersionInfoGenerator.cs b/src/libraries/System.Private.CoreLib/gen/DotnetProductVersionInfoGenerator.cs new file mode 100644 index 0000000000000..2d9624765351a --- /dev/null +++ b/src/libraries/System.Private.CoreLib/gen/DotnetProductVersionInfoGenerator.cs @@ -0,0 +1,42 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Immutable; +using System.IO; +using Microsoft.CodeAnalysis; + +namespace Generators +{ + [Generator] + public partial class DotnetProductVersionInfoGenerator : IIncrementalGenerator + { + public void Initialize(IncrementalGeneratorInitializationContext context) + { + // we only care about filename which is of the form "$(Version).versionstring", no need to actually read the file. + IncrementalValuesProvider textFiles = context.AdditionalTextsProvider.Where(static file => file.Path.EndsWith(".versionstring")); + IncrementalValueProvider<(Compilation Left, ImmutableArray Right)> compilationAndFiles = + context.CompilationProvider.Combine(textFiles.Collect()); + + context.RegisterSourceOutput(compilationAndFiles, (spc, content) => + { + // strip semver metadata (git hash) followed by + sign + string? productVersion = Path.GetFileNameWithoutExtension(content.Right[0].Path.Split('+')?[0]); + + if (productVersion is null) + throw new InvalidOperationException($"Unable to get product version at build time."); + + spc.AddSource("Environment.DotnetProductVersionInfo.g.cs", $@" +// + +namespace System; + +public static partial class Environment +{{ + internal const string ProductVersionWithLabel = ""{productVersion}""; + private const string ProductVersionWithoutLabel = ""{productVersion.Split('-')?[0]}""; +}}"); + }); + } + } +} diff --git a/src/libraries/System.Private.CoreLib/gen/System.Private.CoreLib.Generators.csproj b/src/libraries/System.Private.CoreLib/gen/System.Private.CoreLib.Generators.csproj index fa1603a009109..466240aa822be 100644 --- a/src/libraries/System.Private.CoreLib/gen/System.Private.CoreLib.Generators.csproj +++ b/src/libraries/System.Private.CoreLib/gen/System.Private.CoreLib.Generators.csproj @@ -5,6 +5,7 @@ + @@ -20,4 +21,5 @@ + diff --git a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems index ce22178ca8a0f..d44e826137682 100644 --- a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems +++ b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems @@ -2783,4 +2783,7 @@ + + + diff --git a/src/libraries/System.Private.CoreLib/src/System/Environment.cs b/src/libraries/System.Private.CoreLib/src/System/Environment.cs index 4b702e6d46e93..aa2a4df985a11 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Environment.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Environment.cs @@ -201,19 +201,7 @@ public static OperatingSystem OSVersion } } - internal const string InternalVersion = "9.0.0"; - - public static Version Version - { - get - { - Debug.Assert(InternalVersion == - typeof(object).Assembly.GetCustomAttribute()?.InformationalVersion?.Split('-', '+')?[0], - $"{nameof(InternalVersion)} mismatched! Keep {nameof(InternalVersion)} in sync with ProductVersion in eng/Versions.props."); - - return Version.Parse(InternalVersion); - } - } + public static Version Version => Version.Parse(ProductVersionWithoutLabel); public static string StackTrace { diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/RuntimeInformation.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/RuntimeInformation.cs index 14d4cee8cabc7..a86c3ee8da9f2 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/RuntimeInformation.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/RuntimeInformation.cs @@ -10,7 +10,7 @@ public static partial class RuntimeInformation /// /// Gets the name of the .NET installation on which an app is running. /// - public static string FrameworkDescription { get; } = ".NET " + Environment.InternalVersion; + public static string FrameworkDescription { get; } = ".NET " + Environment.ProductVersionWithLabel; /// /// Returns an opaque string that identifies the platform on which an app is running. diff --git a/src/libraries/System.Runtime/tests/System.Runtime.InteropServices.RuntimeInformation.Tests/DescriptionNameTests.cs b/src/libraries/System.Runtime/tests/System.Runtime.InteropServices.RuntimeInformation.Tests/DescriptionNameTests.cs index c29191f3e1e3a..335c9c001deee 100644 --- a/src/libraries/System.Runtime/tests/System.Runtime.InteropServices.RuntimeInformation.Tests/DescriptionNameTests.cs +++ b/src/libraries/System.Runtime/tests/System.Runtime.InteropServices.RuntimeInformation.Tests/DescriptionNameTests.cs @@ -196,8 +196,17 @@ public void VerifyFrameworkDescriptionContainsCorrectVersion() return; Assert.DoesNotContain("+", version); // no git hash - Assert.DoesNotContain("-", version); // no labels - Assert.True(Version.TryParse(version, out _)); + +#if STABILIZE_PACKAGE_VERSION + // a stabilized version looks like 8.0.0 + Assert.DoesNotContain("-", version); + Assert.True(Version.TryParse(version, out Version _)); +#else + // a non-stabilized version looks like 8.0.0-preview.5.23280.8 or 8.0.0-dev + Assert.Contains("-", version); + var versionNumber = version.Substring(0, version.IndexOf("-")); + Assert.True(Version.TryParse(versionNumber, out Version _)); +#endif } [Fact] From c1ce4158cade2b3fd613cf189573617289e10de2 Mon Sep 17 00:00:00 2001 From: Adeel <3840695+am11@users.noreply.github.com> Date: Tue, 14 May 2024 10:10:14 +0300 Subject: [PATCH 4/6] Address CR feedback --- .../gen/DotnetProductVersionInfoGenerator.cs | 42 --------------- .../gen/ProductVersionInfoGenerator.cs | 54 +++++++++++++++++++ .../System.Private.CoreLib.Generators.csproj | 2 +- .../System.Private.CoreLib.Shared.projitems | 3 -- .../src/System/Environment.cs | 3 -- .../InteropServices/RuntimeInformation.cs | 5 -- ...opServices.RuntimeInformation.Tests.csproj | 3 ++ 7 files changed, 58 insertions(+), 54 deletions(-) delete mode 100644 src/libraries/System.Private.CoreLib/gen/DotnetProductVersionInfoGenerator.cs create mode 100644 src/libraries/System.Private.CoreLib/gen/ProductVersionInfoGenerator.cs diff --git a/src/libraries/System.Private.CoreLib/gen/DotnetProductVersionInfoGenerator.cs b/src/libraries/System.Private.CoreLib/gen/DotnetProductVersionInfoGenerator.cs deleted file mode 100644 index 2d9624765351a..0000000000000 --- a/src/libraries/System.Private.CoreLib/gen/DotnetProductVersionInfoGenerator.cs +++ /dev/null @@ -1,42 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; -using System.Collections.Immutable; -using System.IO; -using Microsoft.CodeAnalysis; - -namespace Generators -{ - [Generator] - public partial class DotnetProductVersionInfoGenerator : IIncrementalGenerator - { - public void Initialize(IncrementalGeneratorInitializationContext context) - { - // we only care about filename which is of the form "$(Version).versionstring", no need to actually read the file. - IncrementalValuesProvider textFiles = context.AdditionalTextsProvider.Where(static file => file.Path.EndsWith(".versionstring")); - IncrementalValueProvider<(Compilation Left, ImmutableArray Right)> compilationAndFiles = - context.CompilationProvider.Combine(textFiles.Collect()); - - context.RegisterSourceOutput(compilationAndFiles, (spc, content) => - { - // strip semver metadata (git hash) followed by + sign - string? productVersion = Path.GetFileNameWithoutExtension(content.Right[0].Path.Split('+')?[0]); - - if (productVersion is null) - throw new InvalidOperationException($"Unable to get product version at build time."); - - spc.AddSource("Environment.DotnetProductVersionInfo.g.cs", $@" -// - -namespace System; - -public static partial class Environment -{{ - internal const string ProductVersionWithLabel = ""{productVersion}""; - private const string ProductVersionWithoutLabel = ""{productVersion.Split('-')?[0]}""; -}}"); - }); - } - } -} diff --git a/src/libraries/System.Private.CoreLib/gen/ProductVersionInfoGenerator.cs b/src/libraries/System.Private.CoreLib/gen/ProductVersionInfoGenerator.cs new file mode 100644 index 0000000000000..4c31a40882492 --- /dev/null +++ b/src/libraries/System.Private.CoreLib/gen/ProductVersionInfoGenerator.cs @@ -0,0 +1,54 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Reflection; +using Microsoft.CodeAnalysis; + +namespace Generators +{ + [Generator] + public partial class ProductVersionInfoGenerator : IIncrementalGenerator + { + public void Initialize(IncrementalGeneratorInitializationContext context) + { + context.RegisterPostInitializationOutput(ctx => + { + string? informationalVersion = typeof(ProductVersionInfoGenerator).Assembly.GetCustomAttribute()?.InformationalVersion; + + // strip semver metadata (git hash) followed by + sign + string? productVersion = informationalVersion?.Split('+')?[0]; + + if (string.IsNullOrEmpty(productVersion)) + throw new InvalidOperationException($"Unable to obtain product version at build-time."); + + // strip semver prerelease label followed by - sign for Environment.Version + Version versionObject = Version.Parse(productVersion.Split('-')[0]); + + ctx.AddSource("ProductVersionInfo.g.cs", $@"// + +namespace System +{{ + public static partial class Environment + {{ + /// + /// Gets a version consisting of the major, minor, build, and revision numbers of the common language runtime. + /// + public static Version Version => new Version({versionObject.Major}, {versionObject.Minor}, {versionObject.Build}); + }} +}} + +namespace System.Runtime.InteropServices +{{ + public static partial class RuntimeInformation + {{ + /// + /// Gets the name of the .NET installation on which an app is running. + /// + public static string FrameworkDescription => "".NET {productVersion}""; + }} +}}"); + }); + } + } +} diff --git a/src/libraries/System.Private.CoreLib/gen/System.Private.CoreLib.Generators.csproj b/src/libraries/System.Private.CoreLib/gen/System.Private.CoreLib.Generators.csproj index 466240aa822be..ff92d663d01c3 100644 --- a/src/libraries/System.Private.CoreLib/gen/System.Private.CoreLib.Generators.csproj +++ b/src/libraries/System.Private.CoreLib/gen/System.Private.CoreLib.Generators.csproj @@ -5,7 +5,7 @@ - + diff --git a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems index d44e826137682..ce22178ca8a0f 100644 --- a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems +++ b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems @@ -2783,7 +2783,4 @@ - - - diff --git a/src/libraries/System.Private.CoreLib/src/System/Environment.cs b/src/libraries/System.Private.CoreLib/src/System/Environment.cs index aa2a4df985a11..ff58e43d54eb3 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Environment.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Environment.cs @@ -3,7 +3,6 @@ using System.Collections; using System.Diagnostics; -using System.Reflection; using System.Runtime.CompilerServices; using System.Threading; @@ -201,8 +200,6 @@ public static OperatingSystem OSVersion } } - public static Version Version => Version.Parse(ProductVersionWithoutLabel); - public static string StackTrace { [MethodImpl(MethodImplOptions.NoInlining)] // Prevent inlining from affecting where the stacktrace starts diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/RuntimeInformation.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/RuntimeInformation.cs index a86c3ee8da9f2..e750d1011584c 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/RuntimeInformation.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/RuntimeInformation.cs @@ -7,11 +7,6 @@ public static partial class RuntimeInformation { private static string? s_runtimeIdentifier; - /// - /// Gets the name of the .NET installation on which an app is running. - /// - public static string FrameworkDescription { get; } = ".NET " + Environment.ProductVersionWithLabel; - /// /// Returns an opaque string that identifies the platform on which an app is running. /// diff --git a/src/libraries/System.Runtime/tests/System.Runtime.InteropServices.RuntimeInformation.Tests/System.Runtime.InteropServices.RuntimeInformation.Tests.csproj b/src/libraries/System.Runtime/tests/System.Runtime.InteropServices.RuntimeInformation.Tests/System.Runtime.InteropServices.RuntimeInformation.Tests.csproj index 72355db6c397d..94daeb2079a35 100644 --- a/src/libraries/System.Runtime/tests/System.Runtime.InteropServices.RuntimeInformation.Tests/System.Runtime.InteropServices.RuntimeInformation.Tests.csproj +++ b/src/libraries/System.Runtime/tests/System.Runtime.InteropServices.RuntimeInformation.Tests/System.Runtime.InteropServices.RuntimeInformation.Tests.csproj @@ -4,6 +4,9 @@ true $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent)-unix;$(NetCoreAppCurrent)-browser + + $(DefineConstants);STABILIZE_PACKAGE_VERSION + From bd4f66edbdf462708bc9f389fd3d492deddc5f99 Mon Sep 17 00:00:00 2001 From: Adeel Mujahid <3840695+am11@users.noreply.github.com> Date: Tue, 14 May 2024 18:00:09 +0300 Subject: [PATCH 5/6] Update src/libraries/System.Private.CoreLib/gen/ProductVersionInfoGenerator.cs Co-authored-by: Jan Kotas --- .../System.Private.CoreLib/gen/ProductVersionInfoGenerator.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/System.Private.CoreLib/gen/ProductVersionInfoGenerator.cs b/src/libraries/System.Private.CoreLib/gen/ProductVersionInfoGenerator.cs index 4c31a40882492..92dc62c741d17 100644 --- a/src/libraries/System.Private.CoreLib/gen/ProductVersionInfoGenerator.cs +++ b/src/libraries/System.Private.CoreLib/gen/ProductVersionInfoGenerator.cs @@ -34,7 +34,7 @@ public static partial class Environment /// /// Gets a version consisting of the major, minor, build, and revision numbers of the common language runtime. /// - public static Version Version => new Version({versionObject.Major}, {versionObject.Minor}, {versionObject.Build}); + public static Version Version => new Version({string.Replace(versionObject.ToString(), ".", ", ")}); }} }} From 4165c9c57f213537af1d7a2c48eafecfd2085d34 Mon Sep 17 00:00:00 2001 From: Adeel Mujahid <3840695+am11@users.noreply.github.com> Date: Tue, 14 May 2024 18:39:30 +0300 Subject: [PATCH 6/6] Fix build --- .../System.Private.CoreLib/gen/ProductVersionInfoGenerator.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/System.Private.CoreLib/gen/ProductVersionInfoGenerator.cs b/src/libraries/System.Private.CoreLib/gen/ProductVersionInfoGenerator.cs index 92dc62c741d17..fbf8cb48a3a95 100644 --- a/src/libraries/System.Private.CoreLib/gen/ProductVersionInfoGenerator.cs +++ b/src/libraries/System.Private.CoreLib/gen/ProductVersionInfoGenerator.cs @@ -34,7 +34,7 @@ public static partial class Environment /// /// Gets a version consisting of the major, minor, build, and revision numbers of the common language runtime. /// - public static Version Version => new Version({string.Replace(versionObject.ToString(), ".", ", ")}); + public static Version Version => new Version({versionObject.ToString().Replace(".", ", ")}); }} }}