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 00000000000000..fbf8cb48a3a95b --- /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.ToString().Replace(".", ", ")}); + }} +}} + +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 fa1603a0091095..ff92d663d01c35 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/Environment.cs b/src/libraries/System.Private.CoreLib/src/System/Environment.cs index 53028ec74d0219..ff58e43d54eb3d 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,24 +200,6 @@ public static OperatingSystem OSVersion } } - 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); - - // Return zeros rather then failing if the version string fails to parse - return Version.TryParse(versionSpan, out Version? version) ? version : new Version(); - } - } - 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 1bb3db3da1940d..e750d1011584ce 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,38 +1,12 @@ // 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; - } - } - /// /// Returns an opaque string that identifies the platform on which an app is running. ///