private void PackNuGet(IServiceProvider serviceProvider, YardarmGenerationSettings settings) { if (!settings.DllOutput.CanRead || !settings.DllOutput.CanSeek) { throw new InvalidOperationException( $"{nameof(YardarmGenerationSettings.DllOutput)} must be seekable and readable to pack a NuGet package."); } if (!settings.XmlDocumentationOutput.CanRead || !settings.XmlDocumentationOutput.CanSeek) { throw new InvalidOperationException( $"{nameof(YardarmGenerationSettings.XmlDocumentationOutput)} must be seekable and readable to pack a NuGet package."); } settings.DllOutput.Seek(0, SeekOrigin.Begin); settings.XmlDocumentationOutput.Seek(0, SeekOrigin.Begin); var packer = serviceProvider.GetRequiredService <NuGetPacker>(); packer.Pack(settings.DllOutput, settings.XmlDocumentationOutput, settings.NuGetOutput !); if (settings.NuGetSymbolsOutput != null) { if (!settings.PdbOutput.CanRead || !settings.PdbOutput.CanSeek) { throw new InvalidOperationException( $"{nameof(YardarmGenerationSettings.PdbOutput)} must be seekable and readable to pack a NuGet symbols package."); } settings.PdbOutput.Seek(0, SeekOrigin.Begin); packer.PackSymbols(settings.PdbOutput, settings.NuGetSymbolsOutput); } }
private async Task <(EmitResult, ImmutableArray <Diagnostic>)> BuildForTargetFrameworkAsync( GenerationContext context, YardarmGenerationSettings settings, NuGetFramework targetFramework, Stream dllOutput, Stream pdbOutput, Stream xmlDocumentationOutput, CancellationToken cancellationToken = default) { context.CurrentTargetFramework = targetFramework; // Create the empty compilation var compilation = CSharpCompilation.Create(settings.AssemblyName) .WithOptions(settings.CompilationOptions); // Run all enrichers against the compilation var enrichers = context.GenerationServices.GetRequiredService <IEnumerable <ICompilationEnricher> >(); compilation = await compilation.EnrichAsync(enrichers, cancellationToken); ImmutableArray <Diagnostic> additionalDiagnostics; var assemblyLoadContext = new YardarmAssemblyLoadContext(); try { var sourceGenerators = context.GenerationServices.GetRequiredService <NuGetRestoreProcessor>() .GetSourceGenerators(context.NuGetRestoreInfo !.Providers, context.NuGetRestoreInfo !.Result, targetFramework, assemblyLoadContext); // Execute the source generators compilation = ExecuteSourceGenerators(compilation, sourceGenerators, out additionalDiagnostics, cancellationToken); } finally { assemblyLoadContext.Unload(); } return(compilation.Emit(dllOutput, pdbStream: pdbOutput, xmlDocumentationStream: xmlDocumentationOutput, options: new EmitOptions() .WithDebugInformationFormat(DebugInformationFormat.PortablePdb) .WithHighEntropyVirtualAddressSpace(true)), additionalDiagnostics); }
public async Task <EmitResult> EmitAsync(OpenApiDocument document, YardarmGenerationSettings settings, CancellationToken cancellationToken = default) { if (document == null) { throw new ArgumentNullException(nameof(document)); } if (settings == null) { throw new ArgumentNullException(nameof(settings)); } var serviceProvider = settings.BuildServiceProvider(document); var compilation = CSharpCompilation.Create(settings.AssemblyName) .WithOptions(settings.CompilationOptions); var enrichers = serviceProvider.GetRequiredService <IEnumerable <ICompilationEnricher> >(); compilation = await compilation.EnrichAsync(enrichers, cancellationToken); var compilationResult = compilation.Emit(settings.DllOutput, pdbStream: settings.PdbOutput, xmlDocumentationStream: settings.XmlDocumentationOutput, options: new EmitOptions() .WithDebugInformationFormat(DebugInformationFormat.PortablePdb) .WithHighEntropyVirtualAddressSpace(true)); if (!compilationResult.Success) { return(compilationResult); } if (settings.NuGetOutput != null) { PackNuGet(serviceProvider, settings); } return(compilationResult); }
public static IServiceCollection AddYardarm(this IServiceCollection services, YardarmGenerationSettings settings, OpenApiDocument document) { services.AddDefaultEnrichers(); // Generators services .AddTransient <IReferenceGenerator, NuGetReferenceGenerator>() .AddTransient <ISyntaxTreeGenerator, AssemblyInfoGenerator>() .AddTransient <ISyntaxTreeGenerator, ClientGenerator>() .AddTransient <ISyntaxTreeGenerator, SchemaGenerator>() .AddTransient <ISyntaxTreeGenerator, SecuritySchemeGenerator>() .AddTransient <ISyntaxTreeGenerator, RequestBodyGenerator>() .AddTransient <ISyntaxTreeGenerator, ResponseGenerator>() .AddTransient <ISyntaxTreeGenerator, ResponseSetGenerator>() .AddTransient <ISyntaxTreeGenerator, RequestGenerator>() .AddTransient <ISyntaxTreeGenerator, TagGenerator>() .AddTransient <IDependencyGenerator, StandardDependencyGenerator>(); services.TryAddSingleton <ITypeGeneratorRegistry, TypeGeneratorRegistry>(); services.TryAdd(new ServiceDescriptor(typeof(ITypeGeneratorRegistry <>), typeof(TypeGeneratorRegistry <>), ServiceLifetime.Singleton)); services.TryAddSingleton <ITypeGeneratorFactory <OpenApiSchema>, DefaultSchemaGeneratorFactory>(); services.TryAddSingleton <ITypeGeneratorFactory <OpenApiSecurityScheme>, SecuritySchemeTypeGeneratorFactory>(); services.TryAddSingleton <ITypeGeneratorFactory <OpenApiRequestBody>, RequestBodyTypeGeneratorFactory>(); services.TryAddSingleton <ITypeGeneratorFactory <OpenApiResponse>, ResponseTypeGeneratorFactory>(); services.TryAddSingleton <ITypeGeneratorFactory <OpenApiResponses>, ResponseSetTypeGeneratorFactory>(); services.TryAddSingleton <ITypeGeneratorFactory <OpenApiOperation>, RequestTypeGeneratorFactory>(); services.TryAddSingleton <ITypeGeneratorFactory <OpenApiTag>, TagTypeGeneratorFactory>(); services.TryAddSingleton <ITypeGeneratorFactory <OpenApiUnknownResponse>, UnknownResponseTypeGeneratorFactory>(); services.TryAddSingleton <IAddHeadersMethodGenerator, AddHeadersMethodGenerator>(); services.TryAddSingleton <IBuildContentMethodGenerator, BuildContentMethodGenerator>(); services.TryAddSingleton <IBuildRequestMethodGenerator, BuildRequestMethodGenerator>(); services.TryAddSingleton <IBuildUriMethodGenerator, BuildUriMethodGenerator>(); services.TryAddSingleton <IGetBodyMethodGenerator, GetBodyMethodGenerator>(); services.TryAddSingleton <IOperationMethodGenerator, OperationMethodGenerator>(); services.TryAddSingleton <IMediaTypeSelector, JsonMediaTypeSelector>(); services.TryAddSingleton <IPackageSpecGenerator, DefaultPackageSpecGenerator>(); services.TryAddSingleton(serviceProvider => serviceProvider.GetRequiredService <IPackageSpecGenerator>().Generate()); // Names services.TryAddSingleton <CamelCaseNameFormatter>(); services.TryAddSingleton <PascalCaseNameFormatter>(); services.TryAddSingleton <INameFormatterSelector, DefaultNameFormatterSelector>(); services.TryAddSingleton <IElementTypeNameProvider, DefaultElementTypeNameProvider>(); services.TryAddSingleton <INamespaceProvider, DefaultNamespaceProvider>(); services.TryAddSingleton <IHttpResponseCodeNameProvider, HttpResponseCodeNameProvider>(); services.TryAddSingleton <IRootNamespace, RootNamespace>(); services.TryAddSingleton <IAuthenticationNamespace, AuthenticationNamespace>(); services.TryAddSingleton <IRequestsNamespace, RequestsNamespace>(); services.TryAddSingleton <IResponsesNamespace, ResponsesNamespace>(); services.TryAddSingleton <ISerializationNamespace, SerializationNamespace>(); // Other services .AddLogging() .AddSingleton <GenerationContext>() .AddSingleton(settings) .AddSingleton(document) .AddTransient <NuGetPacker>(); services.TryAddSingleton <IOpenApiElementRegistry, OpenApiElementRegistry>(); return(services); }
public static IServiceCollection AddYardarm(this IServiceCollection services, YardarmGenerationSettings settings, OpenApiDocument document) { services.AddDefaultEnrichers(); // Generators services .AddTransient <IReferenceGenerator, NuGetReferenceGenerator>() .AddTransient <ISyntaxTreeGenerator, AssemblyInfoGenerator>() .AddTransient <ISyntaxTreeGenerator, ClientGenerator>() .AddTransient <ISyntaxTreeGenerator, HeaderGenerator>() .AddTransient <ISyntaxTreeGenerator, MediaTypeGenerator>() .AddTransient <ISyntaxTreeGenerator, ParameterGenerator>() .AddTransient <ISyntaxTreeGenerator, SchemaGenerator>() .AddTransient <ISyntaxTreeGenerator, SecuritySchemeGenerator>() .AddTransient <ISyntaxTreeGenerator, ResponseGenerator>() .AddTransient <ISyntaxTreeGenerator, ResponseSetGenerator>() .AddTransient <ISyntaxTreeGenerator, RequestGenerator>() .AddTransient <ISyntaxTreeGenerator, TagGenerator>() .AddTransient <IDependencyGenerator, StandardDependencyGenerator>(); services.TryAddSingleton <ITypeGeneratorRegistry, TypeGeneratorRegistry>(); services.TryAdd(new ServiceDescriptor(typeof(ITypeGeneratorRegistry <,>), typeof(TypeGeneratorRegistry <,>), ServiceLifetime.Singleton)); services.TryAdd(new ServiceDescriptor(typeof(ITypeGeneratorRegistry <>), typeof(PrimaryGeneratorCategory.TypeGeneratorRegistryWrapper <>), ServiceLifetime.Singleton)); services.TryAdd(new ServiceDescriptor(typeof(ITypeGeneratorFactory <,>), typeof(NoopTypeGeneratorFactory <,>), ServiceLifetime.Singleton)); services.TryAddTypeGeneratorFactory <OpenApiHeader, HeaderTypeGeneratorFactory>(); services.TryAddTypeGeneratorFactory <OpenApiMediaType, MediaTypeGeneratorFactory>(); services.TryAddTypeGeneratorFactory <OpenApiSchema, DefaultSchemaGeneratorFactory>(); services.TryAddTypeGeneratorFactory <OpenApiSecurityScheme, SecuritySchemeTypeGeneratorFactory>(); services.TryAddTypeGeneratorFactory <OpenApiResponse, ResponseTypeGeneratorFactory>(); services.TryAddTypeGeneratorFactory <OpenApiResponses, ResponseSetTypeGeneratorFactory>(); services.TryAddTypeGeneratorFactory <OpenApiOperation, RequestTypeGeneratorFactory>(); services.TryAddTypeGeneratorFactory <OpenApiParameter, ParameterTypeGeneratorFactory>(); services.TryAddTypeGeneratorFactory <OpenApiTag, TagTypeGeneratorFactory>(); services.TryAddTypeGeneratorFactory <OpenApiUnknownResponse, UnknownResponseTypeGeneratorFactory>(); services.AddSingleton <IRequestMemberGenerator, AddHeadersMethodGenerator>(); services.AddSingleton <IRequestMemberGenerator, BuildContentMethodGenerator>(); services.AddSingleton <IRequestMemberGenerator, BuildRequestMethodGenerator>(); services.AddSingleton <IRequestMemberGenerator, BuildUriMethodGenerator>(); services.AddSingleton <IResponseMethodGenerator, GetBodyMethodGenerator>(); services.AddSingleton <IResponseMethodGenerator, BodyConstructorMethodGenerator>(); services.AddSingleton <IResponseMethodGenerator, NoBodyConstructorMethodGenerator>(); services.TryAddSingleton <IOperationMethodGenerator, OperationMethodGenerator>(); services.TryAddSingleton <IMediaTypeSelector, PriorityMediaTypeSelector>(); // Need to be able to specifically inject this one as well services.TryAddSingleton(serviceProvider => serviceProvider.GetRequiredService <IEnumerable <IRequestMemberGenerator> >() .OfType <IBuildContentMethodGenerator>().First()); services.TryAddSingleton <IPackageSpecGenerator, DefaultPackageSpecGenerator>(); services.TryAddSingleton(serviceProvider => serviceProvider.GetRequiredService <IPackageSpecGenerator>().Generate()); // Names services.TryAddSingleton <CamelCaseNameFormatter>(); services.TryAddSingleton <PascalCaseNameFormatter>(); services.TryAddSingleton <INameFormatterSelector, NameFormatterSelector>(); services.TryAddSingleton <INamespaceProvider, DefaultNamespaceProvider>(); services.TryAddSingleton <INameConverterRegistry>(_ => NameConverterRegistry.CreateDefaultRegistry()); services.TryAddSingleton <IHttpResponseCodeNameProvider, HttpResponseCodeNameProvider>(); services.TryAddSingleton <IRootNamespace, RootNamespace>(); services.TryAddSingleton <IAuthenticationNamespace, AuthenticationNamespace>(); services.TryAddSingleton <IRequestsNamespace, RequestsNamespace>(); services.TryAddSingleton <IResponsesNamespace, ResponsesNamespace>(); services.TryAddSingleton <ISerializationNamespace, SerializationNamespace>(); // Serialization services.TryAddSingleton <ISerializerSelector, DefaultSerializerSelector>(); services.AddSerializerDescriptor(serviceProvider => new SerializerDescriptor( ImmutableHashSet.Create(new SerializerMediaType("multipart/form-data", 0.9)), "Multipart", serviceProvider.GetRequiredService <ISerializationNamespace>().MultipartFormDataSerializer)); // Other services .AddLogging() .AddSingleton <GenerationContext>() .AddTransient <NuGetRestoreProcessor>() .AddSingleton(settings) .AddSingleton(document) .AddTransient <NuGetPacker>(); services.TryAddSingleton <IOpenApiElementRegistry, OpenApiElementRegistry>(); return(services); }
public async Task <YardarmGenerationResult> EmitAsync(OpenApiDocument document, YardarmGenerationSettings settings, CancellationToken cancellationToken = default) { if (document == null) { throw new ArgumentNullException(nameof(document)); } if (settings == null) { throw new ArgumentNullException(nameof(settings)); } var toDispose = new List <IDisposable>(); try { var serviceProvider = settings.BuildServiceProvider(document); var context = serviceProvider.GetRequiredService <GenerationContext>(); // Perform the NuGet restore var restoreProcessor = serviceProvider.GetRequiredService <NuGetRestoreProcessor>(); context.NuGetRestoreInfo = await restoreProcessor.ExecuteAsync(cancellationToken).ConfigureAwait(false); if (settings.TargetFrameworkMonikers.Length == 0) { throw new InvalidOperationException("No target framework monikers provided."); } var compilationResults = new List <YardarmCompilationResult>(); if (settings.TargetFrameworkMonikers.Length == 1) { var targetFramework = NuGetFramework.Parse(settings.TargetFrameworkMonikers[0]); // Perform the compilation var(emitResult, additionalDiagnostics) = await BuildForTargetFrameworkAsync( context, settings, targetFramework, settings.DllOutput, settings.PdbOutput, settings.XmlDocumentationOutput, cancellationToken).ConfigureAwait(false); compilationResults.Add(new(targetFramework, emitResult, settings.DllOutput, settings.PdbOutput, settings.XmlDocumentationOutput, additionalDiagnostics)); } else { if (settings.NuGetOutput is null) { throw new InvalidOperationException( "Targeting multiple frameworks is only supported with NuGet output."); } foreach (var targetFramework in settings.TargetFrameworkMonikers.Select(NuGetFramework.Parse)) { var dllOutput = new MemoryStream(); toDispose.Add(dllOutput); var pdbOutput = new MemoryStream(); toDispose.Add(pdbOutput); var xmlDocumentationOutput = new MemoryStream(); toDispose.Add(xmlDocumentationOutput); // Perform the compilation var(emitResult, additionalDiagnostics) = await BuildForTargetFrameworkAsync( context, settings, targetFramework, dllOutput, pdbOutput, xmlDocumentationOutput, cancellationToken).ConfigureAwait(false); compilationResults.Add(new(targetFramework, emitResult, dllOutput, pdbOutput, xmlDocumentationOutput, additionalDiagnostics)); } } if (compilationResults.All(p => p.EmitResult.Success)) { if (settings.NuGetOutput != null) { PackNuGet(serviceProvider, settings, compilationResults); } } return(new YardarmGenerationResult(serviceProvider.GetRequiredService <GenerationContext>(), compilationResults)); } finally { foreach (var disposable in toDispose) { disposable.Dispose(); } } }