src/AutoRest.CSharp/Common/AutoRest/Communication/StandaloneGeneratorRunner.cs (126 lines of code) (raw):

// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information. using System; using System.IO; using System.Linq; using System.Text.Json; using System.Threading.Tasks; using AutoRest.CSharp.AutoRest.Plugins; using AutoRest.CSharp.Common.AutoRest.Plugins; using AutoRest.CSharp.Common.Input; using AutoRest.CSharp.Input; using Microsoft.CodeAnalysis; namespace AutoRest.CSharp.AutoRest.Communication { internal class StandaloneGeneratorRunner { private static readonly string[] keepFiles = new string[] { "CodeModel.yaml", "Configuration.json", "tspCodeModel.json" }; public static async Task RunAsync(CommandLineOptions options) { string? projectPath = null; string outputPath; string generatedTestOutputPath; bool wasProjectPathPassedIn = options.ProjectPath is not null; if (options.Standalone is not null) { //TODO this is only here for back compat we should consider removing it outputPath = options.Standalone; } else { projectPath = options.ProjectPath!; if (!projectPath!.EndsWith("src", StringComparison.Ordinal)) projectPath = Path.Combine(projectPath, "src"); outputPath = Path.Combine(projectPath, "Generated"); } generatedTestOutputPath = Path.Combine(outputPath, "..", "..", "tests", "Generated"); var configurationPath = options.ConfigurationPath; if (configurationPath == null) { configurationPath = Path.Combine(outputPath, "Configuration.json"); if (!File.Exists(configurationPath)) { configurationPath = Path.Combine(outputPath, "..", "..", "Configuration.json"); } } LoadConfiguration(projectPath, outputPath, options.ExistingProjectFolder, File.ReadAllText(configurationPath)); var codeModelInputPath = Path.Combine(outputPath, "CodeModel.yaml"); var tspInputFile = Path.Combine(outputPath, "tspCodeModel.json"); if (!File.Exists(tspInputFile)) { tspInputFile = Path.Combine(outputPath, "..", "..", "tspCodeModel.json"); } GeneratedCodeWorkspace workspace; if (File.Exists(tspInputFile)) { var json = await File.ReadAllTextAsync(tspInputFile); var rootNamespace = TypeSpecSerialization.Deserialize(json) ?? throw new InvalidOperationException($"Deserializing {tspInputFile} has failed."); workspace = await new CSharpGen().ExecuteAsync(rootNamespace); if (options.IsNewProject) { bool needAzureKeyAuth = rootNamespace.Auth?.ApiKey != null; // TODO - add support for DataFactoryElement lookup await new NewProjectScaffolding(needAzureKeyAuth, false).Execute(); } } else if (File.Exists(codeModelInputPath)) { var yaml = await File.ReadAllTextAsync(codeModelInputPath); var codeModel = CodeModelSerialization.DeserializeCodeModel(yaml); workspace = await new CSharpGen().ExecuteAsync(codeModel); if (options.IsNewProject) { bool needAzureKeyAuth = codeModel.Security.Schemes.Any(scheme => scheme is KeySecurityScheme); bool includeDfe = yaml.Contains("x-ms-format: dfe-", StringComparison.Ordinal); await new NewProjectScaffolding(needAzureKeyAuth, includeDfe).Execute(); } } else { throw new InvalidOperationException($"Neither CodeModel.yaml nor tspCodeModel.json exist in {outputPath} folder."); } if (options.ClearOutputFolder) { DeleteDirectory(outputPath, keepFiles); DeleteDirectory(generatedTestOutputPath, keepFiles); } await foreach (var file in workspace.GetGeneratedFilesAsync()) { if (string.IsNullOrEmpty(file.Text)) { continue; } var filename = Path.Combine(outputPath, file.Name); Console.WriteLine($"Writing {filename}"); Directory.CreateDirectory(Path.GetDirectoryName(filename)!); await File.WriteAllTextAsync(filename, file.Text); } } private static void DeleteDirectory(string path, string[] keepFiles) { var directoryInfo = new DirectoryInfo(path); if (!directoryInfo.Exists) { return; } foreach (FileInfo file in directoryInfo.GetFiles()) { if (keepFiles.Contains(file.Name)) { continue; } file.Delete(); } foreach (DirectoryInfo directory in directoryInfo.GetDirectories()) { DeleteDirectory(directory.FullName, keepFiles); } if (!directoryInfo.EnumerateFileSystemInfos().Any()) { directoryInfo.Delete(); } } internal static void LoadConfiguration(string? projectPath, string outputPath, string? existingProjectFolder, string json) { var root = JsonDocument.Parse(json).RootElement; Configuration.LoadConfiguration(root, projectPath, outputPath, existingProjectFolder); } } }