// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. namespace WixToolset.Dnc.HostGenerator { using System; using System.Diagnostics.CodeAnalysis; using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Text; [Generator] public sealed class DncHostGenerator : ISourceGenerator { public static readonly string Version = String.Format($"{ThisAssembly.Git.SemVer.Major}.{ThisAssembly.Git.SemVer.Minor}.{ThisAssembly.Git.SemVer.Patch}{ThisAssembly.Git.SemVer.DashLabel}+{ThisAssembly.Git.Sha}"); public static readonly string TargetAttributeFullName = "WixToolset.Mba.Core.BootstrapperApplicationFactoryAttribute"; [SuppressMessage("MicrosoftCodeAnalysisReleaseTracking", "RS2008:Enable analyzer release tracking", Justification = "Tracking not needed")] public static readonly DiagnosticDescriptor MissingFactoryAttributeDescriptor = new DiagnosticDescriptor( "WIXBAL001", $"Missing assembly level attribute {TargetAttributeFullName}.", $"Add [assembly: {TargetAttributeFullName}(typeof()].", "WixToolset.Bal.wixext", DiagnosticSeverity.Error, true ); public void Initialize(GeneratorInitializationContext context) { } public void Execute(GeneratorExecutionContext context) { var symbolDisplayFormat = new SymbolDisplayFormat(typeQualificationStyle: SymbolDisplayTypeQualificationStyle.NameAndContainingTypesAndNamespaces); string baFactoryClassName = null; foreach (var assemblyAttribute in context.Compilation.Assembly.GetAttributes()) { var fullAssemblyTypeName = assemblyAttribute.AttributeClass.ToDisplayString(symbolDisplayFormat); if (fullAssemblyTypeName == TargetAttributeFullName && assemblyAttribute.ConstructorArguments.Length == 1) { var arg = assemblyAttribute.ConstructorArguments[0]; if (arg.Value is INamedTypeSymbol argValue) { baFactoryClassName = argValue.ToDisplayString(symbolDisplayFormat); break; } } } if (baFactoryClassName == null) { context.ReportDiagnostic(Diagnostic.Create(MissingFactoryAttributeDescriptor, null)); } else { var source = String.Format(Template, Version, baFactoryClassName); context.AddSource("WixToolset.Dnc.Host.g.cs", SourceText.From(source, Encoding.UTF8, SourceHashAlgorithm.Sha256)); } } public const string Template = @" //------------------------------------------------------------------------------ // // This code was generated by a tool. // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // //------------------------------------------------------------------------------ namespace WixToolset.Dnc.Host {{ using System; using System.CodeDom.Compiler; using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using WixToolset.Mba.Core; [GeneratedCode(""WixToolset.Dnc.HostGenerator.DncHostGenerator"", ""{0}"")] [CompilerGenerated] delegate IBootstrapperApplicationFactory StaticEntryDelegate(); /// /// Entry point for the .NET Core host to create and return the BA to the engine. /// [GeneratedCode(""WixToolset.Dnc.HostGenerator.DncHostGenerator"", ""{0}"")] [CompilerGenerated] public sealed class BootstrapperApplicationFactory : IBootstrapperApplicationFactory {{ /// /// Creates the bootstrapper application factory and calls its IBootstrapperApplicationFactory.Create method. /// /// Pointer to BOOTSTRAPPER_CREATE_ARGS struct. /// Pointer to BOOTSTRAPPER_CREATE_RESULTS struct. public void Create(IntPtr pArgs, IntPtr pResults) {{ var baFactory = new {1}(); baFactory.Create(pArgs, pResults); }} // Entry point for the DNC host. public static IBootstrapperApplicationFactory CreateBAFactory() {{ return new BootstrapperApplicationFactory(); }} #if NET5_0_OR_GREATER [ModuleInitializer] [DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(BootstrapperApplicationFactory))] #if NET5_0 [DynamicDependency(""GetFunctionPointer(System.IntPtr,System.IntPtr,System.IntPtr,System.IntPtr,System.IntPtr,System.IntPtr)"", ""Internal.Runtime.InteropServices.ComponentActivator"", ""System.Private.CoreLib"")] #endif /// /// Empty method to attach above attributes to support linker trimming. /// public static void ModuleInitialize() {{ }} #endif }} }} "; } }