< Summary

Information
Class: NexusLabs.Needlr.Generators.GeneratedConstructorGenerator
Assembly: NexusLabs.Needlr.Generators
File(s): /_work/nick-alienware-needlr-1-1784953859-3e8997/needlr/needlr/src/NexusLabs.Needlr.Generators/GeneratedConstructorGenerator.cs
Line coverage
100%
Covered lines: 27
Uncovered lines: 0
Coverable lines: 27
Total lines: 71
Line coverage: 100%
Branch coverage
50%
Covered branches: 1
Total branches: 2
Branch coverage: 50%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
Initialize(...)50%22100%

File(s)

/_work/nick-alienware-needlr-1-1784953859-3e8997/needlr/needlr/src/NexusLabs.Needlr.Generators/GeneratedConstructorGenerator.cs

#LineLine coverage
 1using System.Text;
 2
 3using Microsoft.CodeAnalysis;
 4using Microsoft.CodeAnalysis.Text;
 5
 6using NexusLabs.Needlr.Generators.CodeGen;
 7using NexusLabs.Needlr.Generators.Models;
 8
 9namespace NexusLabs.Needlr.Generators;
 10
 11/// <summary>
 12/// Incremental source generator that emits a public constructor for partial classes
 13/// eligible for generated-constructor generation, either via
 14/// <c>[GenerateConstructor]</c> on the class or a positive field-level constructor
 15/// guard trigger.
 16/// </summary>
 17/// <remarks>
 18/// The pipeline is genuinely per-type: <see cref="ConstructorGenerationDiscoveryHelper.TryCreateCanonicalModel"/>
 19/// converts each candidate class declaration directly into an equatable
 20/// <see cref="GeneratedConstructorModel"/> (never passing an <see cref="INamedTypeSymbol"/>
 21/// further down the pipeline), and the only cross-type context combined into each
 22/// model is a small, independently-cacheable <see cref="GeneratedConstructorEmitContext"/>
 23/// -- never the whole <see cref="Compilation"/>. As a result, editing one type's fields
 24/// recomputes and re-emits only that type; every other eligible type's cached model and
 25/// generated source are reused unchanged.
 26/// </remarks>
 27[Generator(LanguageNames.CSharp)]
 28public sealed class GeneratedConstructorGenerator : IIncrementalGenerator
 29{
 30    public void Initialize(IncrementalGeneratorInitializationContext context)
 31    {
 6732        var candidateModels = context.SyntaxProvider.CreateSyntaxProvider(
 285833                predicate: static (node, _) => ConstructorGenerationDiscoveryHelper.IsCandidateClassDeclaration(node),
 7834                transform: static (ctx, _) => ConstructorGenerationDiscoveryHelper.TryCreateCanonicalModel(ctx))
 6735            .WithTrackingName(GeneratedConstructorTrackingNames.Candidates);
 36
 6737        var models = candidateModels
 7538            .Where(static model => model is not null)
 6639            .Select(static (model, _) => model!.Value)
 6740            .WithTrackingName(GeneratedConstructorTrackingNames.Models);
 41
 42        // Only cheap, independently-cacheable scalars are derived from the compilation
 43        // and analyzer config options -- never the Compilation or
 44        // AnalyzerConfigOptionsProvider themselves -- so an edit that leaves both the
 45        // assembly name and the breadcrumb MSBuild property unchanged reuses the
 46        // cached emission context instead of forcing every model to recombine with a
 47        // brand-new Compilation snapshot.
 6748        var assemblyName = context.CompilationProvider
 7049            .Select(static (compilation, _) => compilation.AssemblyName ?? "Generated")
 6750            .WithTrackingName(GeneratedConstructorTrackingNames.AssemblyName);
 51
 6752        var breadcrumbLevel = context.AnalyzerConfigOptionsProvider
 6753            .Select(static (configOptions, _) => TypeRegistryGenerator.GetBreadcrumbLevel(configOptions))
 6754            .WithTrackingName(GeneratedConstructorTrackingNames.BreadcrumbLevel);
 55
 6756        var emitContext = assemblyName.Combine(breadcrumbLevel)
 6757            .Select(static (pair, _) => new GeneratedConstructorEmitContext(pair.Left, pair.Right))
 6758            .WithTrackingName(GeneratedConstructorTrackingNames.EmitContext);
 59
 6760        var modelsWithContext = models.Combine(emitContext)
 6761            .WithTrackingName(GeneratedConstructorTrackingNames.Output);
 62
 6763        context.RegisterSourceOutput(modelsWithContext, static (spc, source) =>
 6764        {
 6665            var (model, emitContext) = source;
 6666            var breadcrumbs = new BreadcrumbWriter(emitContext.BreadcrumbLevel);
 6667            var generatedSource = GeneratedConstructorCodeGenerator.GenerateConstructorSource(model, emitContext.Assembl
 6668            spc.AddSource(GeneratedConstructorCodeGenerator.BuildHintName(model), SourceText.From(generatedSource, Encod
 13369        });
 6770    }
 71}