diff --git a/README.md b/README.md index ff8e379..d1ae20c 100644 --- a/README.md +++ b/README.md @@ -241,6 +241,86 @@ SolutionCreator.Create(Path.Combine(Environment.CurrentDirectory, "solution1.sln .Save(); ``` +# Global.json Files +You can create `global.json` files with the `GlobalJsonCreator` class to control SDK versions and MSBuild SDK references in your test projects. + +## Examples + +### Basic global.json with SDK version +```C# +GlobalJsonCreator.Create( + directory: Environment.CurrentDirectory, + sdkVersion: "8.0.100") + .Save(); +``` + +This generates: +```json +{ + "sdk": { + "version": "8.0.100" + } +} +``` + +### With SDK roll-forward policy and prerelease +```C# +GlobalJsonCreator.Create( + directory: Environment.CurrentDirectory, + sdkVersion: "8.0.100", + rollForward: GlobalJsonSdkRollForward.LatestMinor, + allowPrerelease: true) + .Save(); +``` + +This generates: +```json +{ + "sdk": { + "version": "8.0.100", + "rollForward": "latestMinor", + "allowPrerelease": true + } +} +``` + +### With MSBuild SDKs +```C# +GlobalJsonCreator.Create( + directory: Environment.CurrentDirectory, + sdkVersion: "8.0.100") + .MSBuildSdk("Microsoft.Build.NoTargets", "3.7.0") + .MSBuildSdk("Microsoft.Build.Traversal", "4.1.0") + .Save(); +``` + +This generates: +```json +{ + "sdk": { + "version": "8.0.100" + }, + "msbuild-sdks": { + "Microsoft.Build.NoTargets": "3.7.0", + "Microsoft.Build.Traversal": "4.1.0" + } +} +``` + +### Get JSON without saving +```C# +string json = GlobalJsonCreator.Create( + directory: Environment.CurrentDirectory, + sdkVersion: "8.0.100") + .MSBuildSdk("My.Custom.Sdk", "1.0.0") + .ToJson(); + +// Or use implicit string conversion +string json2 = GlobalJsonCreator.Create( + directory: Environment.CurrentDirectory, + sdkVersion: "8.0.100"); +``` + # Package Repositories and Feeds NuGet and MSBuild are very tightly coupled and a lot of times you need packages available when building projects. This API offers two solutions: diff --git a/src/Microsoft.Build.Utilities.ProjectCreation.UnitTests/GlobalJsonTests.cs b/src/Microsoft.Build.Utilities.ProjectCreation.UnitTests/GlobalJsonTests.cs new file mode 100644 index 0000000..260568d --- /dev/null +++ b/src/Microsoft.Build.Utilities.ProjectCreation.UnitTests/GlobalJsonTests.cs @@ -0,0 +1,139 @@ +// Copyright (c) Jeff Kluge. All rights reserved. +// +// Licensed under the MIT license. + +using Shouldly; +using System.IO; +using Xunit; + +namespace Microsoft.Build.Utilities.ProjectCreation.UnitTests +{ + public class GlobalJsonTests : TestBase + { + public GlobalJsonTests() + { + TestDirectory = new DirectoryInfo(Path.Combine(TestRootPath, Path.GetRandomFileName())); + } + + public DirectoryInfo TestDirectory { get; } + + [Fact] + public void BasicGlobalJson() + { + GlobalJsonCreator globalJson = GlobalJsonCreator.Create(TestDirectory, "8.0.100") + .Save(); + + new FileInfo(globalJson.FullPath).ShouldExist(); + + string json = File.ReadAllText(globalJson.FullPath); + + json.ShouldBe( +@"{ + ""sdk"": { + ""version"": ""8.0.100"" + } +}", +StringCompareShould.IgnoreLineEndings); + } + + [Fact] + public void GlobalJsonImplicitConversionToString() + { + string json = GlobalJsonCreator + .Create(TestDirectory, "8.0.100"); + + json.ShouldBe( +@"{ + ""sdk"": { + ""version"": ""8.0.100"" + } +}", +StringCompareShould.IgnoreLineEndings); + } + + [Fact] + public void GlobalJsonToJson() + { + string json = GlobalJsonCreator + .Create(TestDirectory, "8.0.100", rollForward: GlobalJsonSdkRollForward.LatestMinor) + .ToJson(); + + json.ShouldBe( +@"{ + ""sdk"": { + ""version"": ""8.0.100"", + ""rollForward"": ""latestMinor"" + } +}", +StringCompareShould.IgnoreLineEndings); + } + + [Fact] + public void GlobalJsonWithAllowPrerelease() + { + GlobalJsonCreator globalJson = GlobalJsonCreator + .Create(TestDirectory, "8.0.100", allowPrerelease: true) + .Save(); + + new FileInfo(globalJson.FullPath).ShouldExist(); + + string json = File.ReadAllText(globalJson.FullPath); + + json.ShouldBe( +@"{ + ""sdk"": { + ""version"": ""8.0.100"", + ""allowPrerelease"": true + } +}", +StringCompareShould.IgnoreLineEndings); + } + + [Fact] + public void GlobalJsonWithMsbuildSdks() + { + GlobalJsonCreator globalJson = GlobalJsonCreator + .Create(TestDirectory, "8.0.100") + .MSBuildSdk("Microsoft.Build.NoTargets", "3.7.0") + .MSBuildSdk("Microsoft.Build.Traversal", "4.1.0") + .Save(); + + new FileInfo(globalJson.FullPath).ShouldExist(); + + string json = File.ReadAllText(globalJson.FullPath); + + json.ShouldBe( +@"{ + ""sdk"": { + ""version"": ""8.0.100"" + }, + ""msbuild-sdks"": { + ""Microsoft.Build.NoTargets"": ""3.7.0"", + ""Microsoft.Build.Traversal"": ""4.1.0"" + } +}", +StringCompareShould.IgnoreLineEndings); + } + + [Fact] + public void GlobalJsonWithRollForward() + { + GlobalJsonCreator globalJson = GlobalJsonCreator + .Create(TestDirectory, "10.0.100", GlobalJsonSdkRollForward.LatestMinor) + .Save(); + + new FileInfo(globalJson.FullPath).ShouldExist(); + + string json = File.ReadAllText(globalJson.FullPath); + + json.ShouldBe( +@"{ + ""sdk"": { + ""version"": ""10.0.100"", + ""rollForward"": ""latestMinor"" + } +}", +StringCompareShould.IgnoreLineEndings); + } + } +} diff --git a/src/Microsoft.Build.Utilities.ProjectCreation/GlobalJsonCreator.cs b/src/Microsoft.Build.Utilities.ProjectCreation/GlobalJsonCreator.cs new file mode 100644 index 0000000..da7602c --- /dev/null +++ b/src/Microsoft.Build.Utilities.ProjectCreation/GlobalJsonCreator.cs @@ -0,0 +1,169 @@ +// Copyright (c) Jeff Kluge. All rights reserved. +// +// Licensed under the MIT license. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Microsoft.Build.Utilities.ProjectCreation +{ + /// + /// A fluent API for generating global.json files. + /// + public partial class GlobalJsonCreator + { + private readonly GlobalJson _globalJson; + + private readonly JsonSerializerOptions _jsonSerializerOptions = new() + { + WriteIndented = true, + DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, + PropertyNamingPolicy = JsonNamingPolicy.CamelCase, + }; + + private GlobalJsonCreator(FileInfo fullPath, string sdkVersion, GlobalJsonSdkRollForward? rollForward, bool? allowPrerelease) + { + _globalJson = new GlobalJson( + fullPath, + new GlobalJsonSdk + { + Version = sdkVersion, + RollForward = rollForward, + AllowPrerelease = allowPrerelease, + }); + } + + /// + /// Gets the full path to the global.json file. + /// + public string FullPath => _globalJson.FullPath.FullName; + + /// + /// Implicitly converts a to a string. + /// + /// The to convert. + public static implicit operator string(GlobalJsonCreator creator) => creator.ToJson(); + + /// + /// Creates a new instance. + /// + /// The directory where the global.json file will be saved. + /// The SDK version to use. + /// The optional SDK roll-forward policy. + /// Whether to allow prerelease SDK versions. + /// A object used to construct a global.json file. + public static GlobalJsonCreator Create( + DirectoryInfo directory, + string sdkVersion, + GlobalJsonSdkRollForward? rollForward = null, + bool? allowPrerelease = null) + { + if (string.IsNullOrWhiteSpace(sdkVersion)) + { + throw new ArgumentNullException(nameof(sdkVersion)); + } + + FileInfo fullPath = new(Path.GetFullPath(Path.Combine(directory.FullName, "global.json"))); + + return new GlobalJsonCreator(fullPath, sdkVersion, rollForward, allowPrerelease); + } + + /// + /// Creates a new instance. + /// + /// The directory where the global.json file will be saved. + /// The SDK version to use. + /// The optional SDK roll-forward policy. + /// Whether to allow prerelease SDK versions. + /// A object used to construct a global.json file. + public static GlobalJsonCreator Create( + string? directory, + string sdkVersion, + GlobalJsonSdkRollForward? rollForward = null, + bool? allowPrerelease = null) + { + if (string.IsNullOrWhiteSpace(directory)) + { + throw new ArgumentNullException(nameof(directory)); + } + + return Create(new DirectoryInfo(directory), sdkVersion, rollForward, allowPrerelease); + } + + /// + /// Adds an MSBuild SDK to the msbuild-sdks section of the global.json file. + /// + /// The name of the MSBuild SDK. + /// The version of the MSBuild SDK. + /// The current . + public GlobalJsonCreator MSBuildSdk(string name, string version) + { + if (string.IsNullOrWhiteSpace(name)) + { + throw new ArgumentNullException(nameof(name)); + } + + if (string.IsNullOrWhiteSpace(version)) + { + throw new ArgumentNullException(nameof(version)); + } + + _globalJson.MSBuildSdks ??= []; + + _globalJson.MSBuildSdks[name] = version; + + return this; + } + + /// + /// Saves the global.json file. + /// + /// The current . + public GlobalJsonCreator Save() + { + _globalJson.FullPath.Directory!.Create(); + + string json = ToJson(); + + File.WriteAllText(_globalJson.FullPath.FullName, json, Encoding.UTF8); + + return this; + } + + /// + /// Gets the JSON representation of the global.json file. + /// + /// A JSON string representing the global.json file. + public string ToJson() => JsonSerializer.Serialize(_globalJson, _jsonSerializerOptions); + + internal record GlobalJson + { + public GlobalJson(FileInfo fullPath, GlobalJsonSdk sdk) + { + FullPath = fullPath; + Sdk = sdk; + } + + [JsonIgnore] + public FileInfo FullPath { get; init; } + + public GlobalJsonSdk Sdk { get; init; } + + [JsonPropertyName("msbuild-sdks")] + public Dictionary? MSBuildSdks { get; set; } + } + + internal record GlobalJsonSdk + { + public required string Version { get; init; } + + public GlobalJsonSdkRollForward? RollForward { get; init; } + + public bool? AllowPrerelease { get; init; } + } + } +} diff --git a/src/Microsoft.Build.Utilities.ProjectCreation/GlobalJsonSdkRollForward.cs b/src/Microsoft.Build.Utilities.ProjectCreation/GlobalJsonSdkRollForward.cs new file mode 100644 index 0000000..7e910c5 --- /dev/null +++ b/src/Microsoft.Build.Utilities.ProjectCreation/GlobalJsonSdkRollForward.cs @@ -0,0 +1,91 @@ +// Copyright (c) Jeff Kluge. All rights reserved. +// +// Licensed under the MIT license. + +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Microsoft.Build.Utilities.ProjectCreation +{ + /// + /// Specifies the SDK roll-forward policy for global.json. + /// + [JsonConverter(typeof(GlobalJsonSdkRollForwardJsonConverter))] + public enum GlobalJsonSdkRollForward + { + /// + /// Roll forward to the latest patch version. + /// + LatestPatch, + + /// + /// Roll forward to the latest feature version. + /// + LatestFeature, + + /// + /// Roll forward to the latest minor version. + /// + LatestMinor, + + /// + /// Roll forward to the latest major version. + /// + LatestMajor, + + /// + /// Disable roll-forward. + /// + Disable, + } + +#pragma warning disable SA1649 // File name should match first type name + internal class GlobalJsonSdkRollForwardJsonConverter : JsonConverter +#pragma warning restore SA1649 // File name should match first type name + { + public override GlobalJsonSdkRollForward Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + string? value = reader.GetString(); + + return value?.Trim() switch + { + "latestPatch" => GlobalJsonSdkRollForward.LatestPatch, + "latestFeature" => GlobalJsonSdkRollForward.LatestFeature, + "latestMinor" => GlobalJsonSdkRollForward.LatestMinor, + "latestMajor" => GlobalJsonSdkRollForward.LatestMajor, + "disable" => GlobalJsonSdkRollForward.Disable, + _ => throw new JsonException($"Unexpected value '{value}' for {nameof(GlobalJsonSdkRollForward)}."), + }; + } + + public override void Write(Utf8JsonWriter writer, GlobalJsonSdkRollForward value, JsonSerializerOptions options) + { + switch (value) + { + case GlobalJsonSdkRollForward.LatestPatch: + writer.WriteStringValue("latestPatch"); + break; + + case GlobalJsonSdkRollForward.LatestFeature: + writer.WriteStringValue("latestFeature"); + break; + + case GlobalJsonSdkRollForward.LatestMinor: + writer.WriteStringValue("latestMinor"); + break; + + case GlobalJsonSdkRollForward.LatestMajor: + writer.WriteStringValue("latestMajor"); + break; + + case GlobalJsonSdkRollForward.Disable: + writer.WriteStringValue("disable"); + break; + + default: + throw new JsonException($"Unexpected value '{value}' for {nameof(GlobalJsonSdkRollForward)}."); + } + } + } +} diff --git a/src/Microsoft.Build.Utilities.ProjectCreation/IsExternalInit.cs b/src/Microsoft.Build.Utilities.ProjectCreation/IsExternalInit.cs new file mode 100644 index 0000000..57c00da --- /dev/null +++ b/src/Microsoft.Build.Utilities.ProjectCreation/IsExternalInit.cs @@ -0,0 +1,15 @@ +// Copyright (c) Jeff Kluge. All rights reserved. +// +// Licensed under the MIT license. + +#if NETFRAMEWORK +namespace System.Runtime.CompilerServices +{ + /// + /// Reserved for compiler use. Enables init-only properties in records for .NET Framework. + /// + internal static class IsExternalInit + { + } +} +#endif diff --git a/src/Microsoft.Build.Utilities.ProjectCreation/PolyfillAttributes.cs b/src/Microsoft.Build.Utilities.ProjectCreation/PolyfillAttributes.cs new file mode 100644 index 0000000..9cdd2cf --- /dev/null +++ b/src/Microsoft.Build.Utilities.ProjectCreation/PolyfillAttributes.cs @@ -0,0 +1,40 @@ +// Copyright (c) Jeff Kluge. All rights reserved. +// +// Licensed under the MIT license. + +#if NETFRAMEWORK + +#pragma warning disable SA1402 // File may only contain a single type +#pragma warning disable SA1403 // File may only contain a single namespace +#pragma warning disable SA1649 // File name should match first type name + +namespace System.Runtime.CompilerServices +{ + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = false)] + internal sealed class RequiredMemberAttribute : Attribute + { + } + + [AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = false)] + internal sealed class CompilerFeatureRequiredAttribute : Attribute + { + public CompilerFeatureRequiredAttribute(string featureName) + { + FeatureName = featureName; + } + + public string FeatureName { get; } + + public bool IsOptional { get; init; } + } +} + +namespace System.Diagnostics.CodeAnalysis +{ + [AttributeUsage(AttributeTargets.Constructor, AllowMultiple = false, Inherited = false)] + internal sealed class SetsRequiredMembersAttribute : Attribute + { + } +} + +#endif diff --git a/src/Microsoft.Build.Utilities.ProjectCreation/PublicAPI/net10.0/PublicAPI.Unshipped.txt b/src/Microsoft.Build.Utilities.ProjectCreation/PublicAPI/net10.0/PublicAPI.Unshipped.txt index 3df6e35..00524cf 100644 --- a/src/Microsoft.Build.Utilities.ProjectCreation/PublicAPI/net10.0/PublicAPI.Unshipped.txt +++ b/src/Microsoft.Build.Utilities.ProjectCreation/PublicAPI/net10.0/PublicAPI.Unshipped.txt @@ -1,2 +1,16 @@ #nullable enable +Microsoft.Build.Utilities.ProjectCreation.GlobalJsonCreator +Microsoft.Build.Utilities.ProjectCreation.GlobalJsonCreator.FullPath.get -> string! +Microsoft.Build.Utilities.ProjectCreation.GlobalJsonCreator.MSBuildSdk(string! name, string! version) -> Microsoft.Build.Utilities.ProjectCreation.GlobalJsonCreator! +Microsoft.Build.Utilities.ProjectCreation.GlobalJsonCreator.Save() -> Microsoft.Build.Utilities.ProjectCreation.GlobalJsonCreator! +Microsoft.Build.Utilities.ProjectCreation.GlobalJsonCreator.ToJson() -> string! +Microsoft.Build.Utilities.ProjectCreation.GlobalJsonSdkRollForward +Microsoft.Build.Utilities.ProjectCreation.GlobalJsonSdkRollForward.Disable = 4 -> Microsoft.Build.Utilities.ProjectCreation.GlobalJsonSdkRollForward +Microsoft.Build.Utilities.ProjectCreation.GlobalJsonSdkRollForward.LatestFeature = 1 -> Microsoft.Build.Utilities.ProjectCreation.GlobalJsonSdkRollForward +Microsoft.Build.Utilities.ProjectCreation.GlobalJsonSdkRollForward.LatestMajor = 3 -> Microsoft.Build.Utilities.ProjectCreation.GlobalJsonSdkRollForward +Microsoft.Build.Utilities.ProjectCreation.GlobalJsonSdkRollForward.LatestMinor = 2 -> Microsoft.Build.Utilities.ProjectCreation.GlobalJsonSdkRollForward +Microsoft.Build.Utilities.ProjectCreation.GlobalJsonSdkRollForward.LatestPatch = 0 -> Microsoft.Build.Utilities.ProjectCreation.GlobalJsonSdkRollForward Microsoft.Build.Utilities.ProjectCreation.ProjectCreator.TryBuild(System.Collections.Generic.IDictionary? globalProperties, out bool result) -> Microsoft.Build.Utilities.ProjectCreation.ProjectCreator! +static Microsoft.Build.Utilities.ProjectCreation.GlobalJsonCreator.Create(string? directory, string! sdkVersion, Microsoft.Build.Utilities.ProjectCreation.GlobalJsonSdkRollForward? rollForward = null, bool? allowPrerelease = null) -> Microsoft.Build.Utilities.ProjectCreation.GlobalJsonCreator! +static Microsoft.Build.Utilities.ProjectCreation.GlobalJsonCreator.Create(System.IO.DirectoryInfo! directory, string! sdkVersion, Microsoft.Build.Utilities.ProjectCreation.GlobalJsonSdkRollForward? rollForward = null, bool? allowPrerelease = null) -> Microsoft.Build.Utilities.ProjectCreation.GlobalJsonCreator! +static Microsoft.Build.Utilities.ProjectCreation.GlobalJsonCreator.implicit operator string!(Microsoft.Build.Utilities.ProjectCreation.GlobalJsonCreator! creator) -> string! diff --git a/src/Microsoft.Build.Utilities.ProjectCreation/PublicAPI/net472/PublicAPI.Unshipped.txt b/src/Microsoft.Build.Utilities.ProjectCreation/PublicAPI/net472/PublicAPI.Unshipped.txt index 3df6e35..00524cf 100644 --- a/src/Microsoft.Build.Utilities.ProjectCreation/PublicAPI/net472/PublicAPI.Unshipped.txt +++ b/src/Microsoft.Build.Utilities.ProjectCreation/PublicAPI/net472/PublicAPI.Unshipped.txt @@ -1,2 +1,16 @@ #nullable enable +Microsoft.Build.Utilities.ProjectCreation.GlobalJsonCreator +Microsoft.Build.Utilities.ProjectCreation.GlobalJsonCreator.FullPath.get -> string! +Microsoft.Build.Utilities.ProjectCreation.GlobalJsonCreator.MSBuildSdk(string! name, string! version) -> Microsoft.Build.Utilities.ProjectCreation.GlobalJsonCreator! +Microsoft.Build.Utilities.ProjectCreation.GlobalJsonCreator.Save() -> Microsoft.Build.Utilities.ProjectCreation.GlobalJsonCreator! +Microsoft.Build.Utilities.ProjectCreation.GlobalJsonCreator.ToJson() -> string! +Microsoft.Build.Utilities.ProjectCreation.GlobalJsonSdkRollForward +Microsoft.Build.Utilities.ProjectCreation.GlobalJsonSdkRollForward.Disable = 4 -> Microsoft.Build.Utilities.ProjectCreation.GlobalJsonSdkRollForward +Microsoft.Build.Utilities.ProjectCreation.GlobalJsonSdkRollForward.LatestFeature = 1 -> Microsoft.Build.Utilities.ProjectCreation.GlobalJsonSdkRollForward +Microsoft.Build.Utilities.ProjectCreation.GlobalJsonSdkRollForward.LatestMajor = 3 -> Microsoft.Build.Utilities.ProjectCreation.GlobalJsonSdkRollForward +Microsoft.Build.Utilities.ProjectCreation.GlobalJsonSdkRollForward.LatestMinor = 2 -> Microsoft.Build.Utilities.ProjectCreation.GlobalJsonSdkRollForward +Microsoft.Build.Utilities.ProjectCreation.GlobalJsonSdkRollForward.LatestPatch = 0 -> Microsoft.Build.Utilities.ProjectCreation.GlobalJsonSdkRollForward Microsoft.Build.Utilities.ProjectCreation.ProjectCreator.TryBuild(System.Collections.Generic.IDictionary? globalProperties, out bool result) -> Microsoft.Build.Utilities.ProjectCreation.ProjectCreator! +static Microsoft.Build.Utilities.ProjectCreation.GlobalJsonCreator.Create(string? directory, string! sdkVersion, Microsoft.Build.Utilities.ProjectCreation.GlobalJsonSdkRollForward? rollForward = null, bool? allowPrerelease = null) -> Microsoft.Build.Utilities.ProjectCreation.GlobalJsonCreator! +static Microsoft.Build.Utilities.ProjectCreation.GlobalJsonCreator.Create(System.IO.DirectoryInfo! directory, string! sdkVersion, Microsoft.Build.Utilities.ProjectCreation.GlobalJsonSdkRollForward? rollForward = null, bool? allowPrerelease = null) -> Microsoft.Build.Utilities.ProjectCreation.GlobalJsonCreator! +static Microsoft.Build.Utilities.ProjectCreation.GlobalJsonCreator.implicit operator string!(Microsoft.Build.Utilities.ProjectCreation.GlobalJsonCreator! creator) -> string! diff --git a/src/Microsoft.Build.Utilities.ProjectCreation/PublicAPI/net8.0/PublicAPI.Unshipped.txt b/src/Microsoft.Build.Utilities.ProjectCreation/PublicAPI/net8.0/PublicAPI.Unshipped.txt index 3df6e35..00524cf 100644 --- a/src/Microsoft.Build.Utilities.ProjectCreation/PublicAPI/net8.0/PublicAPI.Unshipped.txt +++ b/src/Microsoft.Build.Utilities.ProjectCreation/PublicAPI/net8.0/PublicAPI.Unshipped.txt @@ -1,2 +1,16 @@ #nullable enable +Microsoft.Build.Utilities.ProjectCreation.GlobalJsonCreator +Microsoft.Build.Utilities.ProjectCreation.GlobalJsonCreator.FullPath.get -> string! +Microsoft.Build.Utilities.ProjectCreation.GlobalJsonCreator.MSBuildSdk(string! name, string! version) -> Microsoft.Build.Utilities.ProjectCreation.GlobalJsonCreator! +Microsoft.Build.Utilities.ProjectCreation.GlobalJsonCreator.Save() -> Microsoft.Build.Utilities.ProjectCreation.GlobalJsonCreator! +Microsoft.Build.Utilities.ProjectCreation.GlobalJsonCreator.ToJson() -> string! +Microsoft.Build.Utilities.ProjectCreation.GlobalJsonSdkRollForward +Microsoft.Build.Utilities.ProjectCreation.GlobalJsonSdkRollForward.Disable = 4 -> Microsoft.Build.Utilities.ProjectCreation.GlobalJsonSdkRollForward +Microsoft.Build.Utilities.ProjectCreation.GlobalJsonSdkRollForward.LatestFeature = 1 -> Microsoft.Build.Utilities.ProjectCreation.GlobalJsonSdkRollForward +Microsoft.Build.Utilities.ProjectCreation.GlobalJsonSdkRollForward.LatestMajor = 3 -> Microsoft.Build.Utilities.ProjectCreation.GlobalJsonSdkRollForward +Microsoft.Build.Utilities.ProjectCreation.GlobalJsonSdkRollForward.LatestMinor = 2 -> Microsoft.Build.Utilities.ProjectCreation.GlobalJsonSdkRollForward +Microsoft.Build.Utilities.ProjectCreation.GlobalJsonSdkRollForward.LatestPatch = 0 -> Microsoft.Build.Utilities.ProjectCreation.GlobalJsonSdkRollForward Microsoft.Build.Utilities.ProjectCreation.ProjectCreator.TryBuild(System.Collections.Generic.IDictionary? globalProperties, out bool result) -> Microsoft.Build.Utilities.ProjectCreation.ProjectCreator! +static Microsoft.Build.Utilities.ProjectCreation.GlobalJsonCreator.Create(string? directory, string! sdkVersion, Microsoft.Build.Utilities.ProjectCreation.GlobalJsonSdkRollForward? rollForward = null, bool? allowPrerelease = null) -> Microsoft.Build.Utilities.ProjectCreation.GlobalJsonCreator! +static Microsoft.Build.Utilities.ProjectCreation.GlobalJsonCreator.Create(System.IO.DirectoryInfo! directory, string! sdkVersion, Microsoft.Build.Utilities.ProjectCreation.GlobalJsonSdkRollForward? rollForward = null, bool? allowPrerelease = null) -> Microsoft.Build.Utilities.ProjectCreation.GlobalJsonCreator! +static Microsoft.Build.Utilities.ProjectCreation.GlobalJsonCreator.implicit operator string!(Microsoft.Build.Utilities.ProjectCreation.GlobalJsonCreator! creator) -> string!