< Summary

Information
Class: NexusLabs.Needlr.Generators.GeneratedConstructorGenerator
Assembly: NexusLabs.Needlr.Generators
File(s): /home/runner/work/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)

/home/runner/work/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    {
 7732        var candidateModels = context.SyntaxProvider.CreateSyntaxProvider(
 371133                predicate: static (node, _) => ConstructorGenerationDiscoveryHelper.IsCandidateClassDeclaration(node),
 10634                transform: static (ctx, _) => ConstructorGenerationDiscoveryHelper.TryCreateCanonicalModel(ctx))
 7735            .WithTrackingName(GeneratedConstructorTrackingNames.Candidates);
 36
 7737        var models = candidateModels
 9738            .Where(static model => model is not null)
 8839            .Select(static (model, _) => model!.Value)
 7740            .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.
 7748        var assemblyName = context.CompilationProvider
 8649            .Select(static (compilation, _) => compilation.AssemblyName ?? "Generated")
 7750            .WithTrackingName(GeneratedConstructorTrackingNames.AssemblyName);
 51
 7752        var breadcrumbLevel = context.AnalyzerConfigOptionsProvider
 7753            .Select(static (configOptions, _) => TypeRegistryGenerator.GetBreadcrumbLevel(configOptions))
 7754            .WithTrackingName(GeneratedConstructorTrackingNames.BreadcrumbLevel);
 55
 7756        var emitContext = assemblyName.Combine(breadcrumbLevel)
 7757            .Select(static (pair, _) => new GeneratedConstructorEmitContext(pair.Left, pair.Right))
 7758            .WithTrackingName(GeneratedConstructorTrackingNames.EmitContext);
 59
 7760        var modelsWithContext = models.Combine(emitContext)
 7761            .WithTrackingName(GeneratedConstructorTrackingNames.Output);
 62
 7763        context.RegisterSourceOutput(modelsWithContext, static (spc, source) =>
 7764        {
 8865            var (model, emitContext) = source;
 8866            var breadcrumbs = new BreadcrumbWriter(emitContext.BreadcrumbLevel);
 8867            var generatedSource = GeneratedConstructorCodeGenerator.GenerateConstructorSource(model, emitContext.Assembl
 8868            spc.AddSource(GeneratedConstructorCodeGenerator.BuildHintName(model), GeneratedSourceText.Create(generatedSo
 16569        });
 7770    }
 71}