コード例 #1
0
        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);
            }
        }
コード例 #2
0
        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);
        }
コード例 #3
0
        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);
        }
コード例 #4
0
        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);
        }
コード例 #5
0
        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);
        }
コード例 #6
0
        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();
                }
            }
        }