Skip to content

Commit

Permalink
Remove reflection from FrameworkDescription (dotnet#102164)
Browse files Browse the repository at this point in the history
* Remove reflection from FrameworkDescription

* Switch to source gen

* Address CR feedback

* Update src/libraries/System.Private.CoreLib/gen/ProductVersionInfoGenerator.cs

Co-authored-by: Jan Kotas <jkotas@microsoft.com>

---------

Co-authored-by: Jan Kotas <jkotas@microsoft.com>
  • Loading branch information
am11 and jkotas committed May 15, 2024
1 parent 46986e2 commit 426edd0
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 45 deletions.
Original file line number Diff line number Diff line change
@@ -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<AssemblyInformationalVersionAttribute>()?.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", $@"// <auto-generated/>
namespace System
{{
public static partial class Environment
{{
/// <summary>
/// Gets a version consisting of the major, minor, build, and revision numbers of the common language runtime.
/// </summary>
public static Version Version => new Version({versionObject.ToString().Replace(".", ", ")});
}}
}}
namespace System.Runtime.InteropServices
{{
public static partial class RuntimeInformation
{{
/// <summary>
/// Gets the name of the .NET installation on which an app is running.
/// </summary>
public static string FrameworkDescription => "".NET {productVersion}"";
}}
}}");
});
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
</PropertyGroup>

<ItemGroup>
<Compile Include="ProductVersionInfoGenerator.cs" />
<Compile Include="EventSourceGenerator.cs" />
<Compile Include="EventSourceGenerator.Emitter.cs" />
<Compile Include="EventSourceGenerator.Parser.cs" />
Expand All @@ -20,4 +21,5 @@
<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" PrivateAssets="all" Version="$(MicrosoftCodeAnalysisVersion_LatestVS)" />
</ItemGroup>

</Project>
19 changes: 0 additions & 19 deletions src/libraries/System.Private.CoreLib/src/System/Environment.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

using System.Collections;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Threading;

Expand Down Expand Up @@ -201,24 +200,6 @@ public static OperatingSystem OSVersion
}
}

public static Version Version
{
get
{
string? versionString = typeof(object).Assembly.GetCustomAttribute<AssemblyInformationalVersionAttribute>()?.InformationalVersion;

ReadOnlySpan<char> 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
Expand Down
Original file line number Diff line number Diff line change
@@ -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<char> versionString = typeof(object).Assembly.GetCustomAttribute<AssemblyInformationalVersionAttribute>()?.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;
}
}

/// <summary>
/// Returns an opaque string that identifies the platform on which an app is running.
/// </summary>
Expand Down

0 comments on commit 426edd0

Please sign in to comment.