Skip to content

Conversation

Copilot
Copy link
Contributor

@Copilot Copilot AI commented Sep 4, 2025

Modernizes the incremental source generator with significant performance optimizations and project improvements while maintaining the exact same API and functionality.

Performance Optimizations

  • Eliminated LINQ usage in hot code paths, replacing with efficient loops for better performance
  • Implemented StringBuilder for memory-efficient code generation instead of string concatenation
  • Removed 9 legacy files (708 lines of code) that supported the old visitor pattern but were no longer used
  • Maintained raw string literals with interpolation for clean, readable generated code

Project Improvements

  • Added copyright acknowledgments for PolySharp, Microsoft.CodeAnalysis, and Splat dependencies
  • Added AI tools disclosure noting use of GitHub Copilot with human review and testing
  • Enhanced README documentation with comprehensive details about the modern 4-stage incremental pipeline architecture

Architecture Benefits

The generator now fully leverages:

  • True incremental compilation with cache-friendly immutable records
  • Memory-efficient processing with early filtering and minimal allocations
  • Independent stage caching for maximum performance benefits
  • Immediate IDE feedback during editing in Visual Studio 17.10+

All existing Register<>(), RegisterLazySingleton<>(), and RegisterConstant<>() methods continue to work exactly as before with improved performance.


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Copy link
Contributor Author

Copilot AI commented Sep 4, 2025

@glennawatson 👋 This repository doesn't have Copilot instructions. With Copilot instructions, I can understand the repository better, work faster and produce higher quality PRs.

I can generate a .github/copilot-instructions.md file for you automatically. Click here to open a pre-filled issue and assign it to me. I'll write the instructions, and then tag you for review.

@glennawatson
Copy link
Contributor

Important to note, @copilot I want to keep existing API usage, just update to incremental, so the attribute usage is a example only

Copy link
Contributor Author

Copilot AI commented Sep 4, 2025

Important to note, @copilot I want to keep existing API usage, just update to incremental, so the attribute usage is a example only

Understood! I'll keep the existing API usage with the SplatRegistrations.Register<>(), RegisterLazySingleton<>(), and RegisterConstant<>() method calls. I'll convert the generator from the current SyntaxReceiver + ISourceGenerator approach to a modern IIncrementalGenerator with an efficient pipeline while preserving the exact same API and functionality. The attribute usage in the problem statement was just an example - I'll focus on the method call detection that's currently implemented.

@Copilot Copilot AI changed the title [WIP] Upgrade Splat.DI.SourceGenerator to Modern Incremental Generator Upgrade Splat.DI.SourceGenerator to Modern Incremental Generator Sep 4, 2025
Copilot finished work on behalf of glennawatson September 4, 2025 04:35
@glennawatson
Copy link
Contributor

        // Create a syntax receiver to mimic the old behavior
        var syntaxReceiver = new SyntaxReceiver();
        foreach (var (invocation, _) in data)
        {
            syntaxReceiver.OnVisitSyntaxNode(invocation);
        }
        
        @copilot 
        
        We want to get away from the visitor pattern like we used to have 
        
        it should function more like a traidtional incremental generator right, so collect all the data required, put it into cache friendly records, and then go to the next step along etc. This is just a non-incremental generator in a incremental generator body.

Copy link
Contributor Author

Copilot AI commented Sep 4, 2025

        // Create a syntax receiver to mimic the old behavior
        var syntaxReceiver = new SyntaxReceiver();

...

You're absolutely right! I've completely rewritten the incremental generator to eliminate the visitor pattern and implement a proper incremental pipeline.

The previous implementation was indeed just a non-incremental generator wrapped in incremental generator clothing - it was collecting all invocations and feeding them back into the old SyntaxReceiver visitor pattern.

The new implementation (c6cfaf9) uses a true four-stage incremental pipeline:

  1. Stage 1: Transform individual InvocationExpressionSyntaxRegistrationCall records
  2. Stage 2: Transform each RegistrationCallRegistrationTarget with semantic analysis
  3. Stage 3: Collect all RegistrationTargetRegistrationGroup
  4. Stage 4: Transform RegistrationGroup → final source code

Each stage processes data individually using pure transforms and cache-friendly immutable records from IncrementalData.cs. This provides real incremental benefits where only changed invocations get reprocessed, and each pipeline stage can be cached independently.

The old visitor pattern approach has been completely eliminated.

@Copilot Copilot AI changed the title Upgrade Splat.DI.SourceGenerator to Modern Incremental Generator Replace legacy SyntaxReceiver with modern incremental generator pipeline Sep 4, 2025
Copilot finished work on behalf of glennawatson September 4, 2025 05:03
@glennawatson
Copy link
Contributor

glennawatson commented Sep 4, 2025

Can you please do a copyright section for the polysharp and other libraries we use, do it "with thanks". Mention we do sometimes use copilot and AI tools but all human reviewed etc in the readme.md file

Update us to a modern incremental pipeline system that is cache friendly, efficient, avoids linq due to perf, memory friendly, uses modern features like records to store the data between the pipeline steps, and nicely abstracts it out, and updates the readme.md file with the updated information about the generator please

Remove the reliance on SyntaxFactory and the SyntaxHelpers etc. Use raw strings instead. Make use of stringbuilder, and the raw literals, https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/tokens/raw-string

even with the stringbuilder do raw literals with interpolation (if needed) if over multiple lines

eg $$"""
do stuff {{field.Data}}
""";

thanks @copilot

Raw string literals can contain any arbitrary text without the need for special escape sequences. You begin and end a raw string literal with a minimum of three double-quote characters.

Copy link
Contributor Author

Copilot AI commented Sep 4, 2025

Can you please do a copyright section for the polysharp and other libraries we use, do it "with thanks". Mention we do sometimes use copilot and AI tools but all human reviewed etc in the readme.md fi...

I've implemented all the requested improvements in commit b58ce2a:

Added copyright section in README.md with thanks to PolySharp, Microsoft.CodeAnalysis, and Splat
Added AI/Copilot acknowledgment noting human review of all AI-generated code
Removed all LINQ usage from hot paths, replaced with efficient loops for better performance
Implemented StringBuilder for memory-efficient code generation instead of string concatenation
Maintained raw string literals with interpolation for clean, readable generated code
Removed 9 legacy files that supported the old visitor pattern (SyntaxReceiver, SourceGeneratorHelpers, MetadataExtractor, etc.)
Updated README.md with comprehensive details about the modern 4-stage incremental pipeline architecture

The generator now provides true incremental compilation benefits with cache-friendly immutable records, efficient memory usage, and excellent IDE performance while maintaining the exact same API.

@Copilot Copilot AI changed the title Replace legacy SyntaxReceiver with modern incremental generator pipeline Modernize incremental generator: Remove LINQ, optimize performance, add acknowledgments Sep 4, 2025
Copilot finished work on behalf of glennawatson September 4, 2025 05:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants