File: GenAPIApp.cs
Web Access
Project: ..\..\..\src\Compatibility\GenAPI\Microsoft.DotNet.GenAPI\Microsoft.DotNet.GenAPI.csproj (Microsoft.DotNet.GenAPI)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
#if !NET
using System.Text.RegularExpressions;
#endif
using Microsoft.CodeAnalysis;
using Microsoft.DotNet.ApiSymbolExtensions;
using Microsoft.DotNet.ApiSymbolExtensions.Filtering;
using Microsoft.DotNet.ApiSymbolExtensions.Logging;
 
namespace Microsoft.DotNet.GenAPI
{
    /// <summary>
    /// Class to standardize initialization and running of GenAPI tool.
    /// Shared between CLI and MSBuild tasks frontends.
    /// </summary>
    public static class GenAPIApp
    {
        /// <summary>
        /// Initialize and run Roslyn-based GenAPI tool specifying the assemblies to load.
        /// </summary>
        public static void Run(ILog log,
            string[] assembliesPaths,
            string[]? assemblyReferencesPaths,
            string? outputPath,
            string? headerFile,
            string? exceptionMessage,
            string[]? excludeApiFiles,
            string[]? excludeAttributesFiles,
            bool respectInternals,
            bool includeAssemblyAttributes)
        {
            (IAssemblySymbolLoader loader, Dictionary<string, IAssemblySymbol> assemblySymbols) = AssemblySymbolLoader.CreateFromFiles(
                log,
                assembliesPaths,
                assemblyReferencesPaths,
                assembliesToExclude: [],
                respectInternals: respectInternals);
 
            Run(log,
                loader,
                assemblySymbols,
                outputPath,
                headerFile,
                exceptionMessage,
                excludeApiFiles,
                excludeAttributesFiles,
                respectInternals,
                includeAssemblyAttributes);
        }
 
        /// <summary>
        /// Initialize and run Roslyn-based GenAPI tool using an assembly symbol loader that pre-loaded the assemblies separately.
        /// </summary>
        public static void Run(ILog log,
            IAssemblySymbolLoader loader,
            Dictionary<string, IAssemblySymbol> assemblySymbols,
            string? outputPath,
            string? headerFile,
            string? exceptionMessage,
            string[]? excludeApiFiles,
            string[]? excludeAttributesFiles,
            bool respectInternals,
            bool includeAssemblyAttributes)
        {
            // Shared accessibility filter for the API and Attribute composite filters.
            AccessibilitySymbolFilter accessibilitySymbolFilter = new(
                respectInternals,
                includeEffectivelyPrivateSymbols: true,
                includeExplicitInterfaceImplementationSymbols: true);
 
            // Invoke the CSharpFileBuilder for each directly loaded assembly.
            foreach (KeyValuePair<string, IAssemblySymbol> kvp in assemblySymbols)
            {
                using TextWriter textWriter = GetTextWriter(outputPath, kvp.Key);
 
                ISymbolFilter symbolFilter = SymbolFilterFactory.GetFilterFromFiles(
                        excludeApiFiles, accessibilitySymbolFilter,
                        respectInternals: respectInternals);
                ISymbolFilter attributeDataSymbolFilter = SymbolFilterFactory.GetFilterFromFiles(
                        excludeAttributesFiles, accessibilitySymbolFilter,
                        respectInternals: respectInternals);
 
                string? headerText = headerFile != null ? File.ReadAllText(headerFile) : null;
 
                CSharpFileBuilder fileBuilder = new(log,
                    textWriter,
                    loader,
                    symbolFilter,
                    attributeDataSymbolFilter,
                    headerText,
                    exceptionMessage,
                    includeAssemblyAttributes,
                    loader.MetadataReferences,
                    addPartialModifier: true);
 
                fileBuilder.WriteAssembly(kvp.Value);
            }
        }
 
        // Creates a TextWriter capable of writing into Console or a cs file.
        private static TextWriter GetTextWriter(string? outputDirPath, string assemblyName)
        {
            if (outputDirPath is null)
            {
                return Console.Out;
            }
 
            string fileName = assemblyName + ".cs";
            if (Directory.Exists(outputDirPath))
            {
                return File.CreateText(Path.Combine(outputDirPath, fileName));
            }
 
            return File.CreateText(outputDirPath);
        }
    }
}