Skip to content

Improve source generation both for Roslyn-based and for BT-based SG #1732

Description

@0x5bfa

Summary

We should use IIncrementalSourceGenerator for CsWin32 not only because it's recommended but because NativeMethods.txt is expected to have relatively a large number of entries. Re-generating the whole source every time NativeMethods.txt or .json degrades the VS performance on large projects.

Plus, the BuildTask one has Inputs and Outputs @ GenerateCsWin32Code but once called, it generates the whole source.

Roslyn-based SG Design

[Generator]
public sealed class SourceGenerator : IIncrementalGenerator
{
    public void Initialize(IncrementalGeneratorInitializationContext context)
    {
        var options = context.AdditionalTextsProvider
            .Where(static file => Path.GetFileName(file.Path).EndsWith("NativeMethods.json", StringComparison.OrdinalIgnoreCase))
            .Collect()
            .Select(static (files, ct) => ParseOptions(files, ct));

        var nativeMethods = context.AdditionalTextsProvider
            .Where(static file => Path.GetFileName(file.Path).EndsWith("NativeMethods.txt", StringComparison.OrdinalIgnoreCase))
            .Select(static (file, ct) => ReadNativeMethods(file, ct))
            .Collect();

        var buildProps = context.AnalyzerConfigOptionsProvider
            .Select(static (provider, ct) => ReadBuildProperties(provider.GlobalOptions));

        var inputs = context.CompilationProvider
            .Combine(context.ParseOptionsProvider)
            .Combine(options)
            .Combine(nativeMethods)
            .Combine(buildProps);

        context.RegisterSourceOutput(inputs, static (spc, input) =>
        {
            // existing Execute body, but driven from immutable input models
            Generate(spc, input);
        });
    }
}

BuildTask-based SG Design

string sourceText = unit.Value.GetText(Encoding.UTF8).ToString();
bool changed = WriteFileIfChanged(filePath, sourceText);

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions