Skip to content

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

@0x5bfa

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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions