| File: Emitter.cs | Web Access |
| Project: src\src\Generators\Microsoft.Gen.BuildMetadata\Microsoft.Gen.BuildMetadata.csproj (Microsoft.Gen.BuildMetadata) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics.CodeAnalysis; using Microsoft.Gen.Shared; namespace Microsoft.Gen.BuildMetadata; [SuppressMessage("Format", "S1199", Justification = "For better visualization of how the generated code will look like.")] internal sealed class Emitter : EmitterBase { private const string DependencyInjectionNamespace = "global::Microsoft.Extensions.DependencyInjection."; private const string ConfigurationNamespace = "global::Microsoft.Extensions.Configuration."; private const string HostingNamespace = "global::Microsoft.Extensions.Hosting."; private readonly string? _buildId; private readonly string? _buildNumber; private readonly string? _sourceBranchName; private readonly string? _sourceVersion; public Emitter(BuildMetadata buildMetadata) { _buildId = buildMetadata.BuildId; _buildNumber = buildMetadata.BuildNumber; _sourceBranchName = buildMetadata.SourceBranchName; _sourceVersion = buildMetadata.SourceVersion; } public string Emit() { GenerateBuildMetadataExtensions(); return Capture(); } private void GenerateBuildMetadataSource() { OutGeneratedCodeAttribute(); OutLn("[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]"); OutLn($"private sealed class BuildMetadataSource : {ConfigurationNamespace}IConfigurationSource"); OutOpenBrace(); { OutLn("public string SectionName { get; }"); OutLn(); OutLn("public BuildMetadataSource(string sectionName)"); OutOpenBrace(); { OutNullGuards(checkBuilder: false); OutLn("SectionName = sectionName;"); } OutCloseBrace(); OutLn(); OutLn($"public {ConfigurationNamespace}IConfigurationProvider Build({ConfigurationNamespace}IConfigurationBuilder builder)"); OutOpenBrace(); { OutLn($"return new {ConfigurationNamespace}Memory.MemoryConfigurationProvider(new {ConfigurationNamespace}Memory.MemoryConfigurationSource())"); OutOpenBrace(); { OutLn($$"""{ $"{SectionName}:buildid", "{{_buildId}}" },"""); OutLn($$"""{ $"{SectionName}:buildnumber", "{{_buildNumber}}" },"""); OutLn($$"""{ $"{SectionName}:sourcebranchname", "{{_sourceBranchName}}" },"""); OutLn($$"""{ $"{SectionName}:sourceversion", "{{_sourceVersion}}" },"""); } OutCloseBraceWithExtra(";"); } OutCloseBrace(); } OutCloseBrace(); } private void GenerateBuildMetadataExtensions() { OutLn("namespace Microsoft.Extensions.AmbientMetadata"); OutOpenBrace(); { OutGeneratedCodeAttribute(); OutLn("internal static class BuildMetadataGeneratedExtensions"); OutOpenBrace(); { OutLn("private const string DefaultSectionName = \"ambientmetadata:build\";"); OutLn(); GenerateBuildMetadataSource(); OutLn(); OutLn($"public static {HostingNamespace}IHostBuilder UseBuildMetadata(this {HostingNamespace}IHostBuilder builder, string sectionName = DefaultSectionName)"); OutOpenBrace(); { OutNullGuards(); OutLn("_ = builder.ConfigureHostConfiguration(configBuilder => configBuilder.AddBuildMetadata(sectionName))"); Indent(); OutLn(".ConfigureServices((hostBuilderContext, serviceCollection) =>"); Indent(); OutLn($"{DependencyInjectionNamespace}BuildMetadataServiceCollectionExtensions.AddBuildMetadata(serviceCollection, hostBuilderContext.Configuration.GetSection(sectionName)));"); Unindent(); Unindent(); OutLn(); OutLn("return builder;"); } OutCloseBrace(); OutLn(); OutLn("public static TBuilder UseBuildMetadata<TBuilder>(this TBuilder builder, string sectionName = DefaultSectionName)"); Indent(); OutLn($"where TBuilder : {HostingNamespace}IHostApplicationBuilder"); Unindent(); OutOpenBrace(); { OutNullGuards(); OutLn("_ = builder.Configuration.AddBuildMetadata(sectionName);"); OutLn($"{DependencyInjectionNamespace}BuildMetadataServiceCollectionExtensions.AddBuildMetadata(builder.Services, builder.Configuration.GetSection(sectionName));"); OutLn(); OutLn("return builder;"); } OutCloseBrace(); OutLn(); #pragma warning disable S103 // Lines should not be too long OutLn($"public static {ConfigurationNamespace}IConfigurationBuilder AddBuildMetadata(this {ConfigurationNamespace}IConfigurationBuilder builder, string sectionName = DefaultSectionName)"); #pragma warning restore S103 // Lines should not be too long OutOpenBrace(); { OutNullGuards(); OutLn("return builder.Add(new BuildMetadataSource(sectionName));"); } OutCloseBrace(); } OutCloseBrace(); } OutCloseBrace(); } private void OutNullGuards(bool checkBuilder = true) { OutPP("#if !NET"); if (checkBuilder) { OutLn("if (builder is null)"); OutOpenBrace(); OutLn("throw new global::System.ArgumentNullException(nameof(builder));"); OutCloseBrace(); OutLn(); } OutLn("if (string.IsNullOrWhiteSpace(sectionName))"); OutOpenBrace(); { OutLn("if (sectionName is null)"); OutOpenBrace(); { OutLn("throw new global::System.ArgumentNullException(nameof(sectionName));"); } OutCloseBrace(); OutLn(); OutLn("throw new global::System.ArgumentException(\"The value cannot be an empty string or composed entirely of whitespace.\", nameof(sectionName));"); } OutCloseBrace(); OutPP("#else"); if (checkBuilder) { OutLn("global::System.ArgumentNullException.ThrowIfNull(builder);"); } OutLn("global::System.ArgumentException.ThrowIfNullOrWhiteSpace(sectionName);"); OutPP("#endif"); OutLn(); } }