feat: use a parser and simplify the syntax#2
Conversation
WalkthroughThis update transitions the project from "Fluidic" to "Cutout," introducing a new template parsing, rendering, and source generation system. It adds comprehensive parsing logic for template control flow, loops, and expressions, and implements a new source generator that processes Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant SourceGenerator
participant Parser
participant Renderer
User->>SourceGenerator: Annotate method with [Cutout.Template]
SourceGenerator->>Parser: Parse template attribute string
Parser->>Parser: Tokenize and build syntax tree
Parser->>SourceGenerator: Return syntax nodes
SourceGenerator->>Renderer: Render syntax nodes to C# code
Renderer->>SourceGenerator: Return generated method body
SourceGenerator->>User: Emit generated partial method
Poem
Tip ⚡️ Faster reviews with caching
Enjoy the performance boost—your workflow just got faster. ✨ Finishing Touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Actionable comments posted: 31
🔭 Outside diff range comments (4)
Cutout.Tests/IfStatementTests.Case3a#Test.Test.g.verified.cs (1)
1-29: 🛠️ Refactor suggestionMissing import for System.Text.StringBuilder
The code uses
StringBuilderbut doesn't include the appropriate namespace import. Add the following import statement to ensure the code compiles correctly:using Cutout; using System.Diagnostics.CodeAnalysis; using System; +using System.Text;Cutout.Tests/TemplateTests.Case5a#Test.TestWithConstantTemplate.g.verified.cs (1)
1-28: 🛠️ Refactor suggestionMissing import for System.Text.StringBuilder and SomeModel
The code uses
StringBuilderandSomeModeltypes without importing their respective namespaces:using Cutout; using System.Diagnostics.CodeAnalysis; using System; +using System.Text; +// Add the appropriate namespace for SomeModelCutout.Tests/ForStatementTests.Case3a#Test.Test.g.verified.cs (1)
1-33: 🛠️ Refactor suggestionMissing import for System.Text.StringBuilder
The code uses
StringBuilderbut doesn't include the appropriate namespace import. Add the following import statement:using Cutout; using System.Diagnostics.CodeAnalysis; using System; +using System.Text;Cutout.Tests/ForStatementTests.Case1a#Test.Test.g.verified.cs (1)
1-24: 🛠️ Refactor suggestionMissing import for System.Text.StringBuilder
The code uses
StringBuilderbut doesn't include the appropriate namespace import:using Cutout; using System.Diagnostics.CodeAnalysis; using System; +using System.Text;
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
⛔ Files ignored due to path filters (4)
droplets-icon.pngis excluded by!**/*.pngdroplets-small-icon.pngis excluded by!**/*.pngscissors-icon.pngis excluded by!**/*.pngscissors-small-icon.pngis excluded by!**/*.png
📒 Files selected for processing (64)
Cutout.Sample/Cutout.Sample.csproj(1 hunks)Cutout.Sample/Examples.cs(1 hunks)Cutout.Tests/CallStatementTests.Case1a#Test.Test.g.verified.cs(1 hunks)Cutout.Tests/CallStatementTests.cs(1 hunks)Cutout.Tests/Cutout.Tests.csproj(1 hunks)Cutout.Tests/Extensions/GeneratorDriverExtensions.cs(3 hunks)Cutout.Tests/ForStatementTests.Case1a#Test.Test.g.verified.cs(1 hunks)Cutout.Tests/ForStatementTests.Case2a#Test.Test.g.verified.cs(1 hunks)Cutout.Tests/ForStatementTests.Case3a#Test.Test.g.verified.cs(1 hunks)Cutout.Tests/ForStatementTests.cs(1 hunks)Cutout.Tests/IfStatementTests.Case1a#Test.Test.g.verified.cs(2 hunks)Cutout.Tests/IfStatementTests.Case2a#Test.Test.g.verified.cs(1 hunks)Cutout.Tests/IfStatementTests.Case3a#Test.Test.g.verified.cs(1 hunks)Cutout.Tests/IfStatementTests.cs(1 hunks)Cutout.Tests/ModuleInit.cs(1 hunks)Cutout.Tests/SharedTests.Case1#TemplateAttribute.g.verified.cs(1 hunks)Cutout.Tests/SharedTests.cs(1 hunks)Cutout.Tests/TemplateParserTests.cs(1 hunks)Cutout.Tests/TemplateTests.Case1a#Test.Test.g.verified.cs(1 hunks)Cutout.Tests/TemplateTests.Case2a#Test.TestWithParameter.g.verified.cs(2 hunks)Cutout.Tests/TemplateTests.Case3a#Test.TestWithTwoParameters.g.verified.cs(2 hunks)Cutout.Tests/TemplateTests.Case4a#Test.TestWithModel.g.verified.cs(2 hunks)Cutout.Tests/TemplateTests.Case5a#Test.TestWithConstantTemplate.g.verified.cs(1 hunks)Cutout.Tests/TemplateTests.cs(6 hunks)Cutout.sln(1 hunks)Cutout/Cutout.csproj(2 hunks)Cutout/Exceptions/ParseException.cs(1 hunks)Cutout/Extensions/IndentedTextWriterExtensions.cs(1 hunks)Cutout/Extensions/SyntaxExtensions.cs(1 hunks)Cutout/Extensions/TokenExtensions.cs(1 hunks)Cutout/Parser/Identifiers.cs(1 hunks)Cutout/Parser/Syntax.cs(1 hunks)Cutout/Parser/TemplateParser.CallStatement.cs(1 hunks)Cutout/Parser/TemplateParser.EndBreakPredicate.cs(1 hunks)Cutout/Parser/TemplateParser.ForStatements.cs(1 hunks)Cutout/Parser/TemplateParser.IBreakPredicate.cs(1 hunks)Cutout/Parser/TemplateParser.IfStatements.cs(1 hunks)Cutout/Parser/TemplateParser.KeywordStatement.cs(1 hunks)Cutout/Parser/TemplateParser.VarStatement.cs(1 hunks)Cutout/Parser/TemplateParser.cs(1 hunks)Cutout/Properties/launchSettings.json(1 hunks)Cutout/README.md(1 hunks)Cutout/Renderer/Renderer.cs(1 hunks)Cutout/TemplateAttributeParts.cs(1 hunks)Cutout/TemplateMethodDetails.cs(1 hunks)Cutout/TemplateSourceGenerator.StringTemplateAttribute.cs(1 hunks)Cutout/TemplateSourceGenerator.TemplateMethodImpl.cs(1 hunks)Cutout/TemplateSourceGenerator.cs(3 hunks)Fluidic.Sample/Examples.cs(0 hunks)Fluidic.Sample/Fluidic.Sample.Examples.FileTest.liquid(0 hunks)Fluidic.Tests/FileTemplateTests.Case1a#Test.FileTest.g.verified.cs(0 hunks)Fluidic.Tests/FileTemplateTests.cs(0 hunks)Fluidic.Tests/Fluidic.Tests.Examples.FileTest.liquid(0 hunks)Fluidic.Tests/Fluidic.Tests.IfTemplates.Case1.liquid(0 hunks)Fluidic.Tests/IfControlTests.cs(0 hunks)Fluidic.Tests/SharedTests.Case1#FileTemplateAttribute.g.verified.cs(0 hunks)Fluidic.Tests/SharedTests.Case1#StringTemplateAttribute.g.verified.cs(0 hunks)Fluidic/Extensions/StringExtensions.cs(0 hunks)Fluidic/README.md(0 hunks)Fluidic/StringTemplateSourceGenerator.FileTemplateAttribute.cs(0 hunks)Fluidic/StringTemplateSourceGenerator.TemplateAttributeParts.cs(0 hunks)Fluidic/StringTemplateSourceGenerator.TemplateMethodDetails.cs(0 hunks)Fluidic/StringTemplateSourceGenerator.TemplateMethodImpl.cs(0 hunks)README.md(2 hunks)
💤 Files with no reviewable changes (15)
- Fluidic.Sample/Fluidic.Sample.Examples.FileTest.liquid
- Fluidic.Tests/Fluidic.Tests.IfTemplates.Case1.liquid
- Fluidic.Tests/FileTemplateTests.Case1a#Test.FileTest.g.verified.cs
- Fluidic.Tests/SharedTests.Case1#StringTemplateAttribute.g.verified.cs
- Fluidic/README.md
- Fluidic.Sample/Examples.cs
- Fluidic.Tests/Fluidic.Tests.Examples.FileTest.liquid
- Fluidic/StringTemplateSourceGenerator.TemplateMethodDetails.cs
- Fluidic.Tests/SharedTests.Case1#FileTemplateAttribute.g.verified.cs
- Fluidic.Tests/FileTemplateTests.cs
- Fluidic.Tests/IfControlTests.cs
- Fluidic/StringTemplateSourceGenerator.FileTemplateAttribute.cs
- Fluidic/StringTemplateSourceGenerator.TemplateMethodImpl.cs
- Fluidic/Extensions/StringExtensions.cs
- Fluidic/StringTemplateSourceGenerator.TemplateAttributeParts.cs
🧰 Additional context used
🧬 Code Graph Analysis (12)
Cutout.Tests/IfStatementTests.Case3a#Test.Test.g.verified.cs (2)
Cutout.Tests/IfStatementTests.Case1a#Test.Test.g.verified.cs (2)
Test(11-20)Test(13-19)Cutout.Tests/IfStatementTests.Case2a#Test.Test.g.verified.cs (2)
Test(11-24)Test(13-23)
Cutout.Tests/ForStatementTests.Case2a#Test.Test.g.verified.cs (2)
Cutout.Tests/ForStatementTests.Case1a#Test.Test.g.verified.cs (2)
Test(11-23)Test(13-22)Cutout.Tests/ForStatementTests.Case3a#Test.Test.g.verified.cs (2)
Test(11-32)Test(13-31)
Cutout.Sample/Examples.cs (3)
Cutout.Tests/TemplateTests.cs (6)
Examples(6-47)Template(8-9)Template(11-12)Template(14-21)Template(25-28)Template(42-46)Cutout.Tests/TemplateTests.Case1a#Test.Test.g.verified.cs (2)
Test(11-17)Test(13-16)Cutout.Tests/TemplateTests.Case2a#Test.TestWithParameter.g.verified.cs (1)
Test(11-18)
Cutout.Tests/IfStatementTests.Case2a#Test.Test.g.verified.cs (2)
Cutout.Tests/IfStatementTests.Case1a#Test.Test.g.verified.cs (2)
Test(11-20)Test(13-19)Cutout.Tests/IfStatementTests.Case3a#Test.Test.g.verified.cs (2)
Test(11-28)Test(13-27)
Cutout.Tests/SharedTests.Case1#TemplateAttribute.g.verified.cs (4)
Cutout.Sample/Examples.cs (1)
Template(7-8)Cutout.Tests/ForStatementTests.cs (3)
Template(32-33)Template(44-45)Template(60-61)Cutout.Tests/IfStatementTests.cs (3)
Template(16-17)Template(27-28)Template(40-41)Cutout.Tests/TemplateTests.cs (5)
Template(8-9)Template(11-12)Template(14-21)Template(25-28)Template(42-46)
Cutout.Tests/Extensions/GeneratorDriverExtensions.cs (3)
Cutout.Tests/SharedTests.Case1#TemplateAttribute.g.verified.cs (2)
TemplateAttribute(26-29)TemplateAttribute(34-36)Cutout/TemplateSourceGenerator.StringTemplateAttribute.cs (1)
TemplateSourceGenerator(3-44)Cutout/TemplateSourceGenerator.TemplateMethodImpl.cs (1)
TemplateSourceGenerator(6-85)
Cutout/Parser/TemplateParser.EndBreakPredicate.cs (4)
Cutout/Parser/TemplateParser.cs (3)
TemplateParser(10-338)ReadOnlySpan(139-158)ReadOnlySpan(160-169)Cutout/Parser/TemplateParser.IBreakPredicate.cs (2)
TemplateParser(5-15)ShouldBreak(9-9)Cutout/Extensions/TokenExtensions.cs (1)
ReadOnlySpan(7-24)Cutout/Parser/Identifiers.cs (1)
Identifiers(3-19)
Cutout.Tests/ForStatementTests.Case3a#Test.Test.g.verified.cs (5)
Cutout.Tests/ForStatementTests.Case2a#Test.Test.g.verified.cs (2)
Test(11-24)Test(13-23)Cutout.Tests/ForStatementTests.Case1a#Test.Test.g.verified.cs (2)
Test(11-23)Test(13-22)Cutout.Tests/IfStatementTests.Case1a#Test.Test.g.verified.cs (2)
Test(11-20)Test(13-19)Cutout.Tests/IfStatementTests.Case2a#Test.Test.g.verified.cs (2)
Test(11-24)Test(13-23)Cutout.Tests/IfStatementTests.Case3a#Test.Test.g.verified.cs (2)
Test(11-28)Test(13-27)
Cutout.Tests/ForStatementTests.Case1a#Test.Test.g.verified.cs (2)
Cutout.Tests/ForStatementTests.Case2a#Test.Test.g.verified.cs (2)
Test(11-24)Test(13-23)Cutout.Tests/ForStatementTests.Case3a#Test.Test.g.verified.cs (2)
Test(11-32)Test(13-31)
Cutout/Parser/TemplateParser.CallStatement.cs (1)
Cutout/Parser/TemplateParser.cs (8)
TemplateParser(10-338)Syntax(117-137)Syntax(171-250)Syntax(252-261)ReadOnlySpan(139-158)ReadOnlySpan(160-169)ExtractCodeTokens(263-296)TrySkipWhitespace(298-312)
Cutout.Tests/CallStatementTests.cs (1)
Cutout.Tests/Extensions/GeneratorDriverExtensions.cs (1)
Task(40-55)
Cutout/TemplateSourceGenerator.StringTemplateAttribute.cs (1)
Cutout/TemplateSourceGenerator.TemplateMethodImpl.cs (1)
TemplateSourceGenerator(6-85)
🪛 LanguageTool
Cutout/README.md
[typographical] ~9-~9: Consider adding a comma.
Context: ...utout/) When building source generators there is a requirement to generate source cod...
(IF_THERE_COMMA)
[uncategorized] ~98-~98: Loose punctuation mark.
Context: ...} {{ while true }} {{ end }} ``` var, `continue`, `break` and `return` are al...
(UNLIKELY_OPENING_PUNCTUATION)
README.md
[uncategorized] ~115-~115: Loose punctuation mark.
Context: ...} {{ while true }} {{ end }} ``` var, `continue`, `break` and `return` are al...
(UNLIKELY_OPENING_PUNCTUATION)
🔇 Additional comments (73)
Cutout/Extensions/IndentedTextWriterExtensions.cs (1)
3-3: Namespace Updated to Reflect Rebranding
The namespace has been correctly changed fromFluidic.ExtensionstoCutout.Extensionsto match the new project branding. No other references in this file require adjustments.Cutout.Tests/TemplateTests.Case1a#Test.Test.g.verified.cs (1)
5-5: Using Directive Updated for Cutout
Theusing Fluidic;import has been replaced withusing Cutout;, aligning the generated test code with the new templating engine namespace.Cutout.Tests/ModuleInit.cs (1)
3-3: Test Project Namespace Aligned with Cutout
The namespace has been updated toCutout.Tests, ensuring consistency across the test assembly after the rebranding.Cutout.Tests/TemplateTests.Case2a#Test.TestWithParameter.g.verified.cs (2)
5-5: Import Updated to New Cutout Namespace
The import has been updated tousing Cutout;, ensuring the generated template extension method references the correct namespace.
16-16: Minor Formatting Adjustment in Generated Code
The space before the method call inbuilder.Append(param);has been normalized. This change is purely stylistic and correct.Cutout.Tests/TemplateTests.Case4a#Test.TestWithModel.g.verified.cs (3)
5-5: Using Directive Updated for New Namespace
The generated test file now correctly importsCutoutinstead ofFluidic, consistent with the rest of the migration.
16-16: Formatting Consistency: Removed Extra Space
The callbuilder.Append(model.Value);has been reformatted by removing the stray space before the parentheses.
18-18: Formatting Consistency: Removed Extra Space
Similarly,builder.Append(model.Text);has been reformatted to remove the extra space.Cutout.Tests/TemplateTests.Case3a#Test.TestWithTwoParameters.g.verified.cs (3)
5-5: Namespace import updated to new branding
The import has been correctly changed fromFluidictoCutout, aligning with the new codebase naming.
16-16: Cleaned up formatting around parameter append
The extra spaces around the parameter insertion have been removed, improving consistency in generated code.
18-18: Cleaned up formatting around parameter append
The extra spaces around the second parameter insertion have been removed, matching the adjusted style.Cutout.sln (1)
3-3: Solution project entries renamed for Cutout
Project entries for the main, sample, and test projects have been updated fromFluidictoCutoutin the solution. Confirm that all solution references and build configurations remain valid.Also applies to: 5-5, 7-7
Cutout.Tests/IfStatementTests.Case1a#Test.Test.g.verified.cs (2)
5-5: Namespace import updated to new branding
Theusingdirective has been correctly updated fromFluidictoCutout, ensuring test generation targets the new namespace.
15-15: Tightened formatting onifstatement
Removed the extra space betweenifand the opening parenthesis for consistent code style in generated output.Cutout/Properties/launchSettings.json (1)
6-6: Updated launch target to Cutout sample project
ThetargetProjectpath now correctly points toCutout.Sample/Cutout.Sample.csproj, aligning the debugger profile with the renamed sample.Cutout.Sample/Cutout.Sample.csproj (2)
6-6: Root namespace updated to Cutout.Sample
The<RootNamespace>has been changed toCutout.Sample, matching the project rename.
10-10: ProjectReference updated to Cutout analyzer
The sample project now references..\Cutout\Cutout.csprojas an analyzer, reflecting the new source generator location.Cutout.Tests/SharedTests.cs (1)
1-1: Namespace and attribute rebranding looks goodThe renaming from "Fluidic" to "Cutout" has been consistently applied across all references, and the simplification of
[StringTemplate]to[Template]aligns with the PR objective of simplifying the syntax while maintaining the same functionality.Also applies to: 3-3, 11-11, 15-15
Cutout.Tests/Cutout.Tests.csproj (2)
21-22: Project reference correctly updated to CutoutThe project reference has been properly updated to point to the new Cutout project instead of the former Fluidic project.
24-28: Good addition of file dependency relationshipAdding the DependentUpon element improves IDE tooling by explicitly linking the generated verification file to its source test file, making it easier to navigate between related files.
Cutout.Tests/CallStatementTests.Case1a#Test.Test.g.verified.cs (1)
1-19: Well-structured generated code for call statementsThe generated code correctly implements the call statement functionality in the new template engine. It demonstrates how one template can call another template during rendering (calling
Case2after appending some text), which is an important capability for template composition.Cutout.Tests/IfStatementTests.Case2a#Test.Test.g.verified.cs (1)
1-25: Clean implementation of conditional template logicThe generated code correctly implements if-else conditional logic within the template engine. This example shows how the template system can generate different output text based on runtime conditions. Looking at the related files, this appears to be part of a comprehensive test suite for conditional statements (simple if, if-else, and if-else-if-else patterns).
Cutout/Extensions/SyntaxExtensions.cs (2)
5-5: Namespace updated to align with project rebrandingThe namespace has been correctly renamed from
Fluidic.ExtensionstoCutout.Extensionsas part of the overall project rebranding.
11-22: Refactored TryGetUsings implementation for improved readabilityThe method has been nicely refactored to use LINQ's
Aggregateinstead of what was likely a foreach loop. This functional approach is more concise while maintaining the same behavior of collecting using directives from namespace and compilation unit ancestors.Cutout.Sample/Examples.cs (1)
1-9: Sample class demonstrates the new template syntaxThis example correctly demonstrates the basic usage of the Cutout templating system with a simple template string. The implementation aligns with the test examples seen in
Cutout.Tests/TemplateTests.cs.Cutout/Cutout.csproj (1)
7-11: Updated project metadata for rebrandingThe project title and URLs have been correctly updated to reflect the rebranding from "Fluidic" to "Cutout".
Cutout.Tests/IfStatementTests.Case3a#Test.Test.g.verified.cs (1)
15-26: LGTM! Good implementation of if-else-if-else logicThe conditional logic properly handles the three scenarios (Awesome Shoes, Cool Shoes, and everything else) with appropriate messages in each case.
Cutout.Tests/TemplateTests.Case5a#Test.TestWithConstantTemplate.g.verified.cs (1)
15-25: LGTM! Effective conditional template renderingThe implementation correctly renders different messages based on
model.Value, showing a good example of dynamic content generation in templates.Cutout/Parser/TemplateParser.KeywordStatement.cs (1)
9-24: Well-structured error handling for keyword statements.The
EnsureKeywordStatementOnlymethod effectively validates that a token is of the expected type, with a clear error message that helps with debugging. The use of theinparameter modifier for the index is a good optimization for value types.Cutout.Tests/SharedTests.Case1#TemplateAttribute.g.verified.cs (1)
11-37: Well-documented attribute implementation.The
TemplateAttributeclass has clear XML documentation that explains its purpose and usage. The implementation with both parameterized and parameterless constructors provides flexibility. The conditional compilation with#if !CUTOUT_EXCLUDE_ATTRIBUTESallows for scenarios where you might want to exclude these attributes.Cutout/Extensions/TokenExtensions.cs (1)
1-25: Clean and efficient implementation!The
ToSpanextension method is well-designed for performance:
- Uses
ReadOnlySpan<char>to avoid string allocations- Properly handles the EOF token case
- Ensures non-negative slice length with
Math.Max- Supports extracting spans between two tokens with the optional
endparameterCutout/Parser/TemplateParser.CallStatement.cs (1)
9-42: Overall implementation is clean and follows the parser pattern.The method successfully integrates with the broader parsing infrastructure and handles the basic functionality of parsing call statements.
README.md (1)
39-128: Excellent documentation of the template language.The documentation clearly explains how to use the templating system, with well-structured sections for different language features and helpful code examples.
🧰 Tools
🪛 LanguageTool
[uncategorized] ~115-~115: Loose punctuation mark.
Context: ...} {{ while true }} {{ end }} ```var, `continue`, `break` and `return` are al...(UNLIKELY_OPENING_PUNCTUATION)
Cutout/Exceptions/ParseException.cs (1)
1-25: Well-designed exception with detailed error information.The
ParseExceptionclass:
- Provides helpful properties to access the token and value
- Creates informative error messages with line/column position
- Follows standard exception patterns
- Integrates well with the parser infrastructure
Cutout/TemplateMethodDetails.cs (2)
1-17: Clean record structure for template method detailsThis record provides a well-structured way to store details about template methods. The use of records is appropriate here since they're immutable data containers, which works well for this metadata scenario.
19-23: Good separation of concerns with MethodDetails recordThe separation of method-specific details into its own record type is a good design choice, providing clear organization of the related data.
Cutout/Parser/TemplateParser.IBreakPredicate.cs (1)
9-10: Good use of ReadOnlySpan for performanceThe use of
ReadOnlySpan<T>for both tokens and template text is an excellent choice for performance, reducing unnecessary allocations during parsing operations.Cutout.Tests/Extensions/GeneratorDriverExtensions.cs (6)
7-7: Namespace update is consistent with project renamingThe namespace has been correctly updated from what was likely
Fluidic.Tests.ExtensionstoCutout.Tests.Extensions, which is consistent with the project renaming.
31-31: Updated reference to renamed attribute typeThe reference to the attribute assembly has been correctly updated to use the new
TemplateAttributetype.
35-35: Updated generator class nameThe source generator instance creation has been correctly updated to use the new
TemplateSourceGeneratorclass.
40-55: Test helper method renamed for consistencyThe test helper method has been appropriately renamed from what was likely
VerifyStringTemplatetoVerifyTemplate, which aligns with the simplified attribute model that no longer distinguishes between string and file templates.
47-47: Updated using directive in test templateThe using directive in the test template string has been correctly updated to use the new
Cutoutnamespace.
59-59: Simplified standard support code filterThe
IgnoreStandardSupportCodemethod has been simplified to only ignore theTemplateAttribute.g.csfile, which is consistent with the consolidation of template attributes.Cutout/TemplateSourceGenerator.StringTemplateAttribute.cs (2)
5-43: Attribute renamed and simplifiedThe attribute has been correctly renamed from what was likely
StringTemplateAttributetoTemplateAttribute, and the documentation has been updated to reflect this change. The simplification to a single template attribute type is a good design choice.
6-6: Updated preprocessor directive is consistentThe preprocessor directive has been correctly updated from what was likely
FLUIDIC_EXCLUDE_ATTRIBUTEStoCUTOUT_EXCLUDE_ATTRIBUTESto maintain consistency with the project renaming.Cutout/Parser/TemplateParser.EndBreakPredicate.cs (1)
8-35: Well-structured implementation of template end token parsing.The
EndParseContextimplementation correctly follows theIParseContextinterface and provides a clean way to detect "end" tokens in template parsing. The two static instances with different newline skipping configurations offer flexibility for various parsing contexts.Cutout/README.md (1)
98-98: Well-structured documentation with clear examples.The documentation provides clear examples of the template syntax and supported language features, making it easy for users to understand how to use the library.
🧰 Tools
🪛 LanguageTool
[uncategorized] ~98-~98: Loose punctuation mark.
Context: ...} {{ while true }} {{ end }} ```var, `continue`, `break` and `return` are al...(UNLIKELY_OPENING_PUNCTUATION)
Cutout/TemplateSourceGenerator.TemplateMethodImpl.cs (2)
49-62: Efficient implementation of template writing.The template writing logic efficiently iterates through syntax nodes and delegates the rendering to the appropriate extension method. The null check before processing is a good defensive programming practice.
64-84: Well-organized namespace and using directives.The code properly organizes the generated file with standard components - auto-generated comment, nullable enable directive, and alphabetically sorted using statements.
Cutout/Parser/TemplateParser.ForStatements.cs (1)
1-60: Well-structured parsing methods with consistent implementation patternThe implementation of the three parsing methods for loop statements follows a clean, consistent pattern. Each method handles a specific loop type (for, foreach, while) but delegates the common extraction logic to a shared helper method, which is a good example of the DRY principle.
Cutout.Tests/TemplateTests.cs (1)
30-46: Well-structured multiline template with conditional logicThe constant template with conditional logic is well-defined and properly implemented as a raw string literal using triple quotes. The template correctly demonstrates conditional rendering based on the model's value.
Cutout/TemplateSourceGenerator.cs (2)
13-32: Clean consolidation of template handlingThe source generator has been effectively simplified by consolidating support from multiple attributes into a single unified
TemplateAttribute. This makes the code more maintainable and easier to understand.
91-105: Method renamed for clarityThe method was appropriately renamed from
GenerateStringTemplatetoGenerateTemplateto reflect its more general purpose, now that it handles all template types rather than only string templates.Cutout.Tests/IfStatementTests.cs (3)
10-18: Well-structured template example with conditional logicThe template example correctly demonstrates a simple if statement with proper syntax and formatting.
19-29: Well-structured template example with if-elseThe template example correctly demonstrates an if-else statement with proper syntax and formatting.
30-42: Well-structured template example with if-else-if-elseThe template example correctly demonstrates an if-else-if-else chain with proper syntax and formatting.
Cutout.Tests/CallStatementTests.cs (4)
10-13: Template definition for Call1 looks goodThe template correctly demonstrates how to use the
callstatement to invoke another template with a parameter.
15-18: Template definition for Case2 is well structuredThis template properly defines a simple template that accepts a title parameter and renders it.
24-29: Test correctly verifies template renderingThe test validates that nested template calls work as expected, with proper parameter passing from one template to another.
31-36:Details
❌ Incorrect review comment
Parameter mismatch between test and implementation
The test uses
productas a parameter in the call statement, while the actual implementation inCase1passesproduct.Title. This inconsistency might cause confusion.
🏁 Script executed:
#!/bin/bash # Let's verify how the template parameter is used in the generated code rg -p "call Case2\(" --include="*.cs" -A 1 -B 1Length of output: 491
🏁 Script executed:
#!/bin/bash # Search for calls to Case2 in any .cs file with context rg --context 2 --glob '*.cs' 'call Case2' # Search for template definitions of Case1 and Case2 rg --context 3 --glob '*.cs' 'partial void Case1' rg --context 3 --glob '*.cs' 'partial void Case2'Length of output: 3708
Ignore the Parameter Mismatch Comment
The inline test is deliberately using a different signature (
string product) to verify the templating engine’s call-statement generation, not theCase1method defined earlier. There is no unintended mismatch between this snippet and the actualCase1implementation—this test is validating a separate scenario and can remain as-is.Likely an incorrect or invalid review comment.
Cutout.Tests/ForStatementTests.cs (6)
10-30: Well-structured template with multiple loop typesThis template effectively demonstrates three different loop constructs:
foreachwith both simple and tuple iteration- Traditional
forloop- All with appropriate indentation and formatting
The template is comprehensive and serves as good documentation for the feature.
35-42: Well-implemented while loop templateThe template correctly demonstrates how to use a while loop with variable initialization and incrementation within the loop.
47-58: Effective demonstration of control flow in loopsThis template successfully showcases how to use
continueandbreakstatements within a loop based on conditional checks.
67-98: Comprehensive test for for/foreach loopsThe test properly validates that all three loop variations (foreach, foreach with index, and for) produce identical output, confirming the correctness of the template implementation.
108-123: Effective while loop testThe test validates that the while loop implementation works correctly and produces the expected output.
133-143: Correct verification of continue/break behaviorThe test confirms that the template with continue/break statements functions as expected, skipping the "awesome" tag and stopping before processing the "shoes" tag.
Cutout/Renderer/Renderer.cs (5)
9-54: Well-structured switch statement for syntax renderingThe
WriteSyntaxmethod effectively handles all syntax node types with a clear switch statement. Each case delegates to the appropriate specialized method or performs simple inline rendering.
56-61: Proper escaping in raw text renderingThe
WriteRawTextmethod correctly wraps text in verbatim string literals to preserve formatting.
73-88: Well-implemented expression block renderingThe
WriteExpressionsmethod properly handles indentation for blocks of expressions, ensuring that the generated code is properly formatted.
90-101: Reusable conditional statement renderingThe
WriteConditionalStatementmethod is well-designed to handle multiple types of conditional statements with a parameterized prefix, promoting code reuse.
103-112: Simple and effective call statement renderingThe
WriteCallStatementmethod correctly generates the method call with the builder and parameters, following a consistent pattern with other rendering methods.Cutout/Parser/TemplateParser.IfStatements.cs (2)
37-62: Well-implemented if statement parsingThe
ParseIfStatementmethod correctly extracts and validates the condition expression, throws appropriate exceptions for malformed input, and recursively parses the inner expressions.
64-110: Thorough else/else-if parsing implementationThe
ParseElseStatementmethod effectively handles bothelseandelse ifbranches, with proper validation and error handling. The code correctly distinguishes between the two cases and generates the appropriate syntax nodes.
There was a problem hiding this comment.
Actionable comments posted: 7
♻️ Duplicate comments (2)
README.md (2)
4-4: Update alt text for accessibility.The
altattribute"Tuxedo"doesn't match the image content (scissors-icon.png). Consider updating to something descriptive like"Cutout scissors icon".
114-114: 🧹 Nitpick (assertive)Add Oxford comma for consistency.
Adjust the list punctuation to maintain an Oxford comma:
-`var`, `continue`, `break` and `return` are also supported. +`var`, `continue`, `break`, and `return` are also supported.🧰 Tools
🪛 LanguageTool
[uncategorized] ~114-~114: Loose punctuation mark.
Context: ...} {{ while true }} {{ end }} ```var, `continue`, `break` and `return` are al...(UNLIKELY_OPENING_PUNCTUATION)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (6)
Cutout.Tests/Cutout.Tests.csproj(1 hunks)Cutout/Cutout.csproj(2 hunks)Cutout/Parser/Syntax.cs(1 hunks)Cutout/Parser/TemplateParser.IParseContext.cs(1 hunks)Cutout/TemplateSourceGenerator.TemplateAttribute.cs(1 hunks)README.md(2 hunks)
🧰 Additional context used
🪛 LanguageTool
README.md
[uncategorized] ~114-~114: Loose punctuation mark.
Context: ...} {{ while true }} {{ end }} ``` var, `continue`, `break` and `return` are al...
(UNLIKELY_OPENING_PUNCTUATION)
🔇 Additional comments (16)
Cutout/TemplateSourceGenerator.TemplateAttribute.cs (1)
1-44: LGTM - Consistent rebranding from Fluidic to CutoutThe namespace and class name changes from
Fluidic/StringTemplateAttributetoCutout/TemplateAttributeare consistent throughout the file, including in documentation comments and preprocessor directives. This matches the PR objective of transitioning to "Cutout" and simplifying the syntax.Cutout/Parser/Syntax.cs (1)
3-135: Well-designed syntax hierarchy with appropriate use of C# recordsThe syntax hierarchy is well-structured, making good use of C# record types for immutable syntax nodes. The inheritance relationships are clear and logical, and the special singleton instances for statement types like
BreakStatementare implemented correctly with private constructors and static instances.Cutout/Parser/TemplateParser.IParseContext.cs (1)
1-15: Well-designed parsing interface with clear responsibilitiesThe
IParseContextinterface is well-designed with clear responsibilities for controlling parsing flow and newline handling. Good use ofReadOnlySpanfor performance optimization when handling tokens and template content.Cutout.Tests/Cutout.Tests.csproj (1)
21-21: Correctly updated project reference to match renameThe project reference has been properly updated from
FluidictoCutout, consistent with the namespace and project renaming throughout the codebase.README.md (9)
6-6: Project name updated appropriately.The heading now reflects the new project name "Cutout".
8-10: Update documentation links.Ensure that the "Getting Started" and "Documentation" URLs reference the Cutout project (instead of the previous Fluidic/Tuxedo site).
12-12: Update NuGet package badge.The badge correctly points to the
cutoutpackage on NuGet now.
15-16: Add CI badges for CD and Markdown checks.Including badges for continuous deployment and markdown validation improves visibility into build and documentation status.
43-43: Add "How to use" section heading.The new section clearly introduces usage instructions for the Cutout templating API.
50-66: Provide full template example.The C# code snippet using raw string literals and
[Cutout.Template]is comprehensive and demonstrates typical usage effectively.
68-68: Introduce "Template Language" section.This heading properly signals the start of the templating syntax documentation.
70-73: Explain literal and variable rendering.These lines clearly distinguish between static text and dynamic expressions.
77-77: List supported keywords.This sets up the detailed keyword descriptions that follow.
Cutout/Cutout.csproj (3)
7-7: Approve Title rebrandingThe
<Title>element has been correctly updated from “Fluidic” to “Cutout” to reflect the new project name.
12-12: Approve updated package icon referenceThe
<PackageIcon>has been updated toscissors-icon.png, matching the included file. This addresses the previous icon inconsistency.
11-11:Details
✅ Verification successful
Verify repository URL
Ensure the new
<RepositoryUrl>(https://github.com/bmazzarol/Cutout) points to the renamed repository and is accessible.
🏁 Script executed:
#!/bin/bash # Check that the GitHub repository exists (HTTP 200) curl -s -o /dev/null -w "%{http_code}" https://api.github.com/repos/bmazzarol/CutoutLength of output: 90
Repository URL verified
The<RepositoryUrl>inCutout/Cutout.csproj(https://github.com/bmazzarol/Cutout) is reachable (HTTP 200). No further action required.
| /// <summary> | ||
| /// Represents a conditional else statement in the template | ||
| /// </summary> | ||
| /// <param name="Expressions"></param> | ||
| public sealed record ElseStatement(IReadOnlyList<Syntax> Expressions) | ||
| : WrappingExpressionsStatement(Expressions); |
There was a problem hiding this comment.
🧹 Nitpick (assertive)
Missing parameter description in ElseStatement XML documentation
The XML documentation for ElseStatement has an incomplete parameter description for Expressions.
Update the XML comment to include a description:
/// <summary>
/// Represents a conditional else statement in the template
/// </summary>
- /// <param name="Expressions"></param>
+ /// <param name="Expressions">expressions to render unconditionally</param>
public sealed record ElseStatement(IReadOnlyList<Syntax> Expressions)
: WrappingExpressionsStatement(Expressions);📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| /// <summary> | |
| /// Represents a conditional else statement in the template | |
| /// </summary> | |
| /// <param name="Expressions"></param> | |
| public sealed record ElseStatement(IReadOnlyList<Syntax> Expressions) | |
| : WrappingExpressionsStatement(Expressions); | |
| /// <summary> | |
| /// Represents a conditional else statement in the template | |
| /// </summary> | |
| /// <param name="Expressions">expressions to render unconditionally</param> | |
| public sealed record ElseStatement(IReadOnlyList<Syntax> Expressions) | |
| : WrappingExpressionsStatement(Expressions); |
| Create a static method with the `[Cutout.Template]` attribute. | ||
|
|
||
| The first parameter is the `StringBuilder` like type to write to. |
There was a problem hiding this comment.
🧹 Nitpick (assertive)
Describe template method signature.
The instructions on annotating static methods with [Cutout.Template] and parameter order are clear. You might mention any constraints on supported parameter types.
| A standard template engine is a better approach from a code maintenance | ||
| perspective, but the performance is not as good. |
There was a problem hiding this comment.
🧹 Nitpick (assertive)
Clarify performance trade-off.
This sentence highlights maintenance vs. performance. Consider adding a link to benchmark results or a brief example to illustrate performance gains.
| Any valid C# expression can be used in the template as it is compiled to C# | ||
| code. So if something is not working, the compiler will tell you. | ||
|
|
There was a problem hiding this comment.
🧹 Nitpick (assertive)
Highlight compiled C# integration.
Noting that templates compile to C# aids in debugging; consider adding a tip on interpreting compiler errors in IDEs.
| It's a source generator, so can be used in other source generators without | ||
| incurring a dependency on a template engine, and it lets you use a simplified | ||
| version of [liquid](https://shopify.github.io/liquid/) and any type that |
There was a problem hiding this comment.
🧹 Nitpick (assertive)
Explain integration benefits.
Good note that this can be used without external dependencies. You could optionally include a short usage snippet or link to advanced integration scenarios.
|
|
||
| <ItemGroup> | ||
| <None Include="..\droplets-icon.png" Pack="true" PackagePath="\"/> | ||
| <None Include="..\scissors-icon.png" Pack="true" PackagePath="\"/> |
There was a problem hiding this comment.
🧹 Nitpick (assertive)
Use a forward slash for PackagePath
NuGet expects forward-slash paths in PackagePath. To ensure scissors-icon.png is placed at the package root, consider:
- <None Include="..\scissors-icon.png" Pack="true" PackagePath="\"/>
+ <None Include="..\scissors-icon.png" Pack="true" PackagePath="/" />📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| <None Include="..\scissors-icon.png" Pack="true" PackagePath="\"/> | |
| <None Include="..\scissors-icon.png" Pack="true" PackagePath="/" /> |
| <PackageProjectUrl>https://bmazzarol.github.io/Fluidic</PackageProjectUrl> | ||
| <RepositoryUrl>https://github.com/bmazzarol/Fluidic</RepositoryUrl> | ||
| <PackageIcon>droplets-icon.png</PackageIcon> | ||
| <PackageProjectUrl>https://bmazzarol.github.io/Cutout</PackageProjectUrl> |
There was a problem hiding this comment.
💡 Verification agent
🧩 Analysis chain
Verify project homepage URL
Please confirm that the updated <PackageProjectUrl> (https://bmazzarol.github.io/Cutout) is correct and resolves without redirects or errors.
🏁 Script executed:
#!/bin/bash
# Check that the project homepage returns HTTP 200
curl -s -o /dev/null -w "%{http_code}" https://bmazzarol.github.io/CutoutLength of output: 79
🏁 Script executed:
#!/bin/bash
# Check various URL forms for the project homepage
for url in \
https://bmazzarol.github.io/Cutout \
https://bmazzarol.github.io/Cutout/ \
https://bmazzarol.github.io/Cutout/index.html; do
code=$(curl -s -o /dev/null -w "%{http_code}" "$url")
echo "$url -> $code"
doneLength of output: 968
🏁 Script executed:
#!/bin/bash
# Check lowercase URL forms for the project homepage
for url in \
https://bmazzarol.github.io/cutout \
https://bmazzarol.github.io/cutout/ \
https://bmazzarol.github.io/cutout/index.html; do
code=$(curl -s -o /dev/null -w "%{http_code}" "$url")
echo "$url -> $code"
doneLength of output: 968
Fix <PackageProjectUrl>: invalid homepage URL
The configured URL (https://bmazzarol.github.io/Cutout) returns HTTP 404 and does not resolve. Please update the <PackageProjectUrl> in Cutout/Cutout.csproj (line 10) to a valid, reachable project homepage.
Summary by CodeRabbit
New Features
[Template]attribute for annotating static partial methods to generate code from templates.Refactor
[Template]attribute, removing previous string and file template attributes.Bug Fixes
Documentation
Chores