feat: add file-based template attribute and utility method for whitespace handling#6
Conversation
…pace handling - Introduced `FileTemplateAttribute` to support templates from external files. - Added `RenderUtilities.ApplyExtraWhitespace` for improved whitespace handling. - Enhanced internal generator setup to embed new utility and attribute source files. - Improved consistency in parameter type representation and tests.
|
Warning Rate limit exceeded@bmazzarol has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 12 minutes and 9 seconds before requesting another review. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. 📒 Files selected for processing (2)
WalkthroughThe PR adds file-based template support (new Changes
Sequence Diagram(s)sequenceDiagram
participant Tool as TemplateSourceGenerator
participant Attr as Attribute Path
participant File as File Path (.editorconfig / AdditionalFiles)
participant Comb as Combiner
participant Emit as EmitGeneratorOutput
Note over Tool: post-initialization emits attribute & utility sources
par Attribute-based discovery
Tool->>Attr: Analyze syntax & semantics
Attr->>Comb: BuildTemplateDetailsFromSyntax()
and File-based discovery
Tool->>File: Read AnalyzerConfig (template_method) & AdditionalText
File->>Comb: BuildTemplateDetailsFromFile()
end
Comb->>Emit: Yield combined TemplateMethodDetails
Emit->>Emit: Generate standard + wsr variants using RenderUtilities
sequenceDiagram
participant RendererOld as Old inline handling
participant RenderUtil as RenderUtilities.ApplyExtraWhitespace
participant Builder as StringBuilder.Append
rect rgb(250,240,240)
Note over RendererOld: previous per-append newline checks
RendererOld->>Builder: Append(value)
RendererOld->>RendererOld: if contains newline -> Append(whitespace)
end
rect rgb(240,250,240)
Note over RenderUtil: centralized handling
RendererOld->>RenderUtil: ApplyExtraWhitespace(value, whitespace)
RenderUtil->>Builder: Append(result)
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Areas to focus on:
Possibly related PRs
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
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. Comment |
Test Results82 tests 82 ✅ 5s ⏱️ Results for commit 2b65799. ♻️ This comment has been updated with latest results. |
There was a problem hiding this comment.
Actionable comments posted: 6
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (42)
CODE_OF_CONDUCT.md(1 hunks)Cutout.Sample/.editorconfig(1 hunks)Cutout.Sample/Cutout.Sample.csproj(1 hunks)Cutout.Sample/Examples.cs(1 hunks)Cutout.Sample/SampleTemplate.cs.liquid(1 hunks)Cutout.Tests/CallStatementTests.Case1a#Test.Test.g.verified.cs(1 hunks)Cutout.Tests/CallStatementTests.Case1a#Test.Test.wsr.g.verified.cs(1 hunks)Cutout.Tests/CallStatementTests.cs(2 hunks)Cutout.Tests/Extensions/GeneratorDriverExtensions.cs(1 hunks)Cutout.Tests/ForStatementTests.Case1a#Test.Test.g.verified.cs(1 hunks)Cutout.Tests/ForStatementTests.Case1a#Test.Test.wsr.g.verified.cs(1 hunks)Cutout.Tests/ForStatementTests.Case2a#Test.Test.g.verified.cs(1 hunks)Cutout.Tests/ForStatementTests.Case2a#Test.Test.wsr.g.verified.cs(1 hunks)Cutout.Tests/ForStatementTests.Case3a#Test.Test.g.verified.cs(1 hunks)Cutout.Tests/ForStatementTests.Case3a#Test.Test.wsr.g.verified.cs(2 hunks)Cutout.Tests/IfStatementTests.Case1a#Test.Test.g.verified.cs(1 hunks)Cutout.Tests/IfStatementTests.Case1a#Test.Test.wsr.g.verified.cs(1 hunks)Cutout.Tests/IfStatementTests.Case2a#Test.Test.g.verified.cs(1 hunks)Cutout.Tests/IfStatementTests.Case2a#Test.Test.wsr.g.verified.cs(1 hunks)Cutout.Tests/IfStatementTests.Case3a#Test.Test.g.verified.cs(1 hunks)Cutout.Tests/IfStatementTests.Case3a#Test.Test.wsr.g.verified.cs(1 hunks)Cutout.Tests/SharedTests.Case1#FileTemplateAttribute.g.verified.cs(1 hunks)Cutout.Tests/SharedTests.Case1#RenderUtilities.g.verified.cs(1 hunks)Cutout.Tests/SharedTests.Case1#TemplateAttribute.g.verified.cs(1 hunks)Cutout.Tests/TemplateTests.Case2a#Test.TestWithParameter.g.verified.cs(1 hunks)Cutout.Tests/TemplateTests.Case2a#Test.TestWithParameter.wsr.g.verified.cs(1 hunks)Cutout.Tests/TemplateTests.Case3a#Test.TestWithTwoParameters.g.verified.cs(1 hunks)Cutout.Tests/TemplateTests.Case3a#Test.TestWithTwoParameters.wsr.g.verified.cs(1 hunks)Cutout.Tests/TemplateTests.Case4a#Test.TestWithModel.g.verified.cs(1 hunks)Cutout.Tests/TemplateTests.Case4a#Test.TestWithModel.wsr.g.verified.cs(1 hunks)Cutout.Tests/TemplateTests.Case5a#Test.TestWithConstantTemplate.wsr.g.verified.cs(1 hunks)Cutout/.editorconfig(1 hunks)Cutout/Cutout.csproj(1 hunks)Cutout/FileTemplateAttribute.Source.cs(1 hunks)Cutout/RenderUtilities.Source.cs(1 hunks)Cutout/Renderer/Renderer.cs(3 hunks)Cutout/TemplateAttribute.Source.cs(1 hunks)Cutout/TemplateAttributeParts.cs(1 hunks)Cutout/TemplateSourceGenerator.TemplateAttribute.cs(0 hunks)Cutout/TemplateSourceGenerator.TemplateMethodImpl.cs(2 hunks)Cutout/TemplateSourceGenerator.cs(4 hunks)Parent.Directory.Packages.props(1 hunks)
💤 Files with no reviewable changes (1)
- Cutout/TemplateSourceGenerator.TemplateAttribute.cs
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-08-02T15:10:00.574Z
Learnt from: bmazzarol
PR: bmazzarol/Cutout#3
File: Cutout/Parser/Parser.cs:20-36
Timestamp: 2025-08-02T15:10:00.574Z
Learning: The Cutout Parser (Cutout/Parser/Parser.cs) is specifically designed for use in a source generator context, where it runs during compilation rather than at runtime. This context makes memory optimization concerns around thread-static contexts less relevant since source generators have limited lifespans during the build process.
Applied to files:
Cutout/TemplateSourceGenerator.cs
🧬 Code graph analysis (28)
Cutout.Tests/CallStatementTests.Case1a#Test.Test.g.verified.cs (1)
Cutout.Tests/CallStatementTests.Case1a#Test.Test.wsr.g.verified.cs (1)
Test(11-18)
Cutout.Tests/ForStatementTests.Case3a#Test.Test.wsr.g.verified.cs (2)
Cutout.Tests/ForStatementTests.Case3a#Test.Test.g.verified.cs (2)
Test(11-32)Test(13-31)Cutout.Tests/SharedTests.Case1#RenderUtilities.g.verified.cs (2)
RenderUtilities(12-25)ApplyExtraWhitespace(14-24)
Cutout.Tests/ForStatementTests.Case2a#Test.Test.g.verified.cs (3)
Cutout.Tests/CallStatementTests.Case1a#Test.Test.g.verified.cs (2)
Test(11-18)Test(13-17)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.Tests/TemplateTests.Case2a#Test.TestWithParameter.g.verified.cs (1)
Cutout.Tests/TemplateTests.Case2a#Test.TestWithParameter.wsr.g.verified.cs (1)
TestWithParameter(13-17)
Cutout.Tests/ForStatementTests.Case3a#Test.Test.g.verified.cs (2)
Cutout.Tests/CallStatementTests.Case1a#Test.Test.g.verified.cs (2)
Test(11-18)Test(13-17)Cutout.Tests/ForStatementTests.Case1a#Test.Test.g.verified.cs (2)
Test(11-23)Test(13-22)
Cutout.Tests/SharedTests.Case1#RenderUtilities.g.verified.cs (1)
Cutout/RenderUtilities.Source.cs (2)
RenderUtilities(11-24)ApplyExtraWhitespace(13-23)
Cutout.Tests/TemplateTests.Case4a#Test.TestWithModel.g.verified.cs (1)
Cutout.Tests/TemplateTests.Case4a#Test.TestWithModel.wsr.g.verified.cs (1)
TestWithModel(13-19)
Cutout.Tests/SharedTests.Case1#FileTemplateAttribute.g.verified.cs (2)
Cutout.Tests/SharedTests.Case1#TemplateAttribute.g.verified.cs (1)
AttributeUsage(13-28)Cutout/FileTemplateAttribute.Source.cs (2)
AttributeUsage(12-19)FileTemplateAttribute(18-18)
Cutout.Tests/ForStatementTests.Case2a#Test.Test.wsr.g.verified.cs (2)
Cutout.Tests/ForStatementTests.Case2a#Test.Test.g.verified.cs (2)
Test(11-24)Test(13-23)Cutout.Tests/SharedTests.Case1#RenderUtilities.g.verified.cs (2)
RenderUtilities(12-25)ApplyExtraWhitespace(14-24)
Cutout.Tests/IfStatementTests.Case3a#Test.Test.wsr.g.verified.cs (4)
Cutout.Tests/CallStatementTests.Case1a#Test.Test.wsr.g.verified.cs (2)
Test(11-18)Test(13-17)Cutout.Tests/ForStatementTests.Case1a#Test.Test.wsr.g.verified.cs (2)
Test(11-23)Test(13-22)Cutout.Tests/ForStatementTests.Case2a#Test.Test.wsr.g.verified.cs (2)
Test(11-24)Test(13-23)Cutout.Tests/ForStatementTests.Case3a#Test.Test.wsr.g.verified.cs (2)
Test(11-32)Test(13-31)
Cutout.Tests/TemplateTests.Case5a#Test.TestWithConstantTemplate.wsr.g.verified.cs (2)
Cutout.Tests/SharedTests.Case1#RenderUtilities.g.verified.cs (2)
RenderUtilities(12-25)ApplyExtraWhitespace(14-24)Cutout/RenderUtilities.Source.cs (2)
RenderUtilities(11-24)ApplyExtraWhitespace(13-23)
Cutout/TemplateAttribute.Source.cs (4)
Cutout.Tests/SharedTests.Case1#FileTemplateAttribute.g.verified.cs (1)
AttributeUsage(13-20)Cutout/FileTemplateAttribute.Source.cs (1)
AttributeUsage(12-19)Cutout.Sample/Examples.cs (3)
Template(7-8)Template(12-13)Template(31-32)Cutout.Tests/CallStatementTests.cs (5)
Template(12-13)Template(17-18)Template(27-28)Template(36-37)Template(39-46)
Cutout.Tests/ForStatementTests.Case1a#Test.Test.wsr.g.verified.cs (2)
Cutout.Tests/ForStatementTests.Case1a#Test.Test.g.verified.cs (2)
Test(11-23)Test(13-22)Cutout.Tests/SharedTests.Case1#RenderUtilities.g.verified.cs (2)
RenderUtilities(12-25)ApplyExtraWhitespace(14-24)
Cutout.Tests/ForStatementTests.Case1a#Test.Test.g.verified.cs (4)
Cutout.Tests/CallStatementTests.Case1a#Test.Test.g.verified.cs (2)
Test(11-18)Test(13-17)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.Tests/IfStatementTests.Case1a#Test.Test.g.verified.cs (2)
Test(11-20)Test(13-19)
Cutout/TemplateAttributeParts.cs (3)
Cutout/Parser/Parser.cs (3)
SyntaxList(23-36)SyntaxList(44-170)Parser(5-447)Cutout/Lexer/Lexer.ApplyWhitespaceSuppression.cs (1)
Lexer(3-64)Cutout/Lexer/Lexer.cs (1)
Lexer(3-164)
Cutout/FileTemplateAttribute.Source.cs (1)
Cutout/TemplateAttribute.Source.cs (1)
AttributeUsage(12-27)
Cutout.Tests/IfStatementTests.Case3a#Test.Test.g.verified.cs (3)
Cutout.Tests/CallStatementTests.Case1a#Test.Test.g.verified.cs (2)
Test(11-18)Test(13-17)Cutout.Tests/ForStatementTests.Case3a#Test.Test.g.verified.cs (2)
Test(11-32)Test(13-31)Cutout.Tests/IfStatementTests.Case1a#Test.Test.g.verified.cs (2)
Test(11-20)Test(13-19)
Cutout.Tests/TemplateTests.Case3a#Test.TestWithTwoParameters.wsr.g.verified.cs (2)
Cutout.Tests/TemplateTests.Case3a#Test.TestWithTwoParameters.g.verified.cs (1)
TestWithTwoParameters(13-19)Cutout.Tests/SharedTests.Case1#RenderUtilities.g.verified.cs (2)
RenderUtilities(12-25)ApplyExtraWhitespace(14-24)
Cutout.Tests/IfStatementTests.Case1a#Test.Test.g.verified.cs (3)
Cutout.Tests/CallStatementTests.Case1a#Test.Test.g.verified.cs (2)
Test(11-18)Test(13-17)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/IfStatementTests.Case1a#Test.Test.wsr.g.verified.cs (2)
Cutout.Tests/CallStatementTests.Case1a#Test.Test.wsr.g.verified.cs (2)
Test(11-18)Test(13-17)Cutout.Tests/ForStatementTests.Case1a#Test.Test.wsr.g.verified.cs (2)
Test(11-23)Test(13-22)
Cutout.Tests/IfStatementTests.Case2a#Test.Test.g.verified.cs (4)
Cutout.Tests/CallStatementTests.Case1a#Test.Test.g.verified.cs (2)
Test(11-18)Test(13-17)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.Case3a#Test.Test.g.verified.cs (2)
Test(11-28)Test(13-27)
Cutout/TemplateSourceGenerator.cs (1)
Cutout/TemplateAttributeParts.cs (2)
TemplateAttributeParts(13-28)TemplateAttributeParts(30-34)
Cutout.Tests/IfStatementTests.Case2a#Test.Test.wsr.g.verified.cs (3)
Cutout.Tests/CallStatementTests.Case1a#Test.Test.wsr.g.verified.cs (2)
Test(11-18)Test(13-17)Cutout.Tests/ForStatementTests.Case1a#Test.Test.wsr.g.verified.cs (2)
Test(11-23)Test(13-22)Cutout.Tests/ForStatementTests.Case2a#Test.Test.wsr.g.verified.cs (2)
Test(11-24)Test(13-23)
Cutout.Tests/TemplateTests.Case4a#Test.TestWithModel.wsr.g.verified.cs (3)
Cutout.Tests/TemplateTests.Case4a#Test.TestWithModel.g.verified.cs (1)
TestWithModel(13-19)Cutout.Tests/SharedTests.Case1#RenderUtilities.g.verified.cs (2)
RenderUtilities(12-25)ApplyExtraWhitespace(14-24)Cutout/RenderUtilities.Source.cs (2)
RenderUtilities(11-24)ApplyExtraWhitespace(13-23)
Cutout.Tests/TemplateTests.Case2a#Test.TestWithParameter.wsr.g.verified.cs (2)
Cutout.Tests/TemplateTests.Case2a#Test.TestWithParameter.g.verified.cs (1)
TestWithParameter(13-17)Cutout.Tests/SharedTests.Case1#RenderUtilities.g.verified.cs (2)
RenderUtilities(12-25)ApplyExtraWhitespace(14-24)
Cutout/Renderer/Renderer.cs (1)
Cutout/Extensions/TokenListExtensions.cs (1)
ToString(7-36)
Cutout.Tests/CallStatementTests.Case1a#Test.Test.wsr.g.verified.cs (2)
Cutout.Tests/CallStatementTests.Case1a#Test.Test.g.verified.cs (2)
Test(11-18)Test(13-17)Cutout.Tests/ForStatementTests.Case1a#Test.Test.wsr.g.verified.cs (2)
Test(11-23)Test(13-22)
Cutout.Tests/TemplateTests.Case3a#Test.TestWithTwoParameters.g.verified.cs (1)
Cutout.Tests/TemplateTests.Case3a#Test.TestWithTwoParameters.wsr.g.verified.cs (1)
TestWithTwoParameters(13-19)
🔇 Additional comments (51)
Cutout.Tests/IfStatementTests.Case2a#Test.Test.g.verified.cs (1)
13-13: LGTM! Idiomatic type alias usage.The parameter type has been updated to use the C# keyword alias
stringinstead ofString(System.String), which is the preferred idiomatic style in C#.Cutout.Tests/IfStatementTests.Case3a#Test.Test.wsr.g.verified.cs (1)
13-13: LGTM! Consistent type alias usage.The parameter types now consistently use the C# keyword alias
string, aligning with idiomatic C# style.Cutout.Tests/Extensions/GeneratorDriverExtensions.cs (1)
59-64: LGTM! Extends ignore list for new infrastructure.The method now correctly ignores the newly introduced
FileTemplateAttribute.g.csandRenderUtilities.g.csgenerated files, in addition to the existingTemplateAttribute.g.cs. This aligns with the PR's introduction of file-based templates and centralized whitespace handling utilities.CODE_OF_CONDUCT.md (1)
118-128: LGTM! Improved markdown formatting.The formatting changes make the attribution section more readable by placing links inline with their descriptive text, with no semantic changes to the content.
Cutout/TemplateSourceGenerator.TemplateMethodImpl.cs (2)
33-33: LGTM! Generates idiomatic type representations.Using
ToDisplayString()ensures generated code uses idiomatic C# type aliases (e.g.,stringinstead ofString,intinstead ofInt32). This change is the root cause of the consistent type alias improvements across all test verification files.
97-99: LGTM! Loop pattern changed while preserving behavior.The iteration has been refactored from
foreachto an indexedforloop. The behavior is preserved as the loop still processes each syntax element in order. The indexed access pattern may provide benefits for debugging or align with collection type constraints.Cutout.Tests/IfStatementTests.Case2a#Test.Test.wsr.g.verified.cs (1)
13-13: LGTM! Idiomatic type alias usage.The parameter types now use the C# keyword alias
string, consistent with the systematic improvement across all generated code files.Cutout.Tests/CallStatementTests.cs (2)
39-46: LGTM! Adds nested call template test case.The new
Case5template demonstrates multi-level nesting by callingCase3, which in turn callsCase4. This provides valuable test coverage for nested call statement scenarios with proper whitespace handling.
84-102: LGTM! Validates nested call statement behavior.The new test validates that multi-level nested call statements (Case5 → Case3 → Case4) produce correctly indented output, ensuring the whitespace handling works properly across nesting levels.
Cutout.Tests/IfStatementTests.Case1a#Test.Test.g.verified.cs (1)
13-13: LGTM! Consistent type alias usage.The parameter type uses the idiomatic C# keyword alias
string, completing the systematic consistency improvement across all generated code verification files.Cutout.Tests/ForStatementTests.Case2a#Test.Test.g.verified.cs (1)
13-13: LGTM - Type alias improvement.The change from
Stringtostringfollows C# conventions by using the built-in type alias instead of the BCL type name.Cutout.Tests/CallStatementTests.Case1a#Test.Test.wsr.g.verified.cs (1)
13-16: LGTM - Proper whitespace parameter propagation.The changes correctly:
- Use the
stringtype alias (line 13)- Thread the
whitespaceparameter through to the nestedCase2call (line 16)This aligns with the centralized whitespace handling approach introduced in this PR.
Cutout/TemplateAttributeParts.cs (1)
27-44: LGTM - Clean refactoring with new constructor.The extraction of
BuildSyntax()(lines 36-44) eliminates duplication between the two constructors and properly encapsulates the lazy initialization logic. The new public constructor (lines 30-34) enables programmatic template creation, which aligns with the file-based template feature.Cutout.Sample/.editorconfig (1)
1-2: LGTM - Template configuration.The EditorConfig entry correctly associates the template file with the target method, enabling the file-based template feature introduced in this PR.
Cutout.Tests/ForStatementTests.Case3a#Test.Test.g.verified.cs (1)
13-13: LGTM - Consistent type alias usage.The change from
Stringtostringmaintains consistency with other test files in this PR and follows C# conventions.Cutout.Sample/Cutout.Sample.csproj (1)
14-16: LGTM - Required for source generator.The
AdditionalFilesentry correctly makesSampleTemplate.cs.liquidavailable to the source generator, which is necessary for the file-based template feature.Cutout/.editorconfig (1)
1-6: LGTM - Embedding configuration.The EditorConfig entries correctly mark the three source files for embedding in the generator, enabling them to be included in the generator assembly and emitted to consumer projects.
Cutout.Tests/SharedTests.Case1#TemplateAttribute.g.verified.cs (1)
24-28: LGTM! Enforcing required template parameter.The removal of the parameterless constructor ensures that
TemplateAttributealways receives a template string, which aligns with its purpose. This prevents misuse where the attribute might be applied without an actual template.Cutout.Sample/Examples.cs (1)
36-41: LGTM! Clear demonstration of file-based templating.The new
Test4method effectively demonstrates theFileTemplateAttributefeature and follows the established pattern of the other example methods. The region name clearly indicates this is an external file template example.Cutout.Tests/IfStatementTests.Case3a#Test.Test.g.verified.cs (1)
13-13: LGTM! Consistent type alias usage.The change from
Stringtostringimproves code consistency by using the idiomatic C# keyword alias. This is part of a broader update across the generated test files.Cutout.Tests/TemplateTests.Case4a#Test.TestWithModel.g.verified.cs (1)
13-13: LGTM! Improved type qualification.The change from
SomeModeltoTest.SomeModelmakes the type reference explicit and fully qualified, improving clarity and avoiding potential ambiguity. This is the non-whitespace-sensitive version, correctly using directAppendcalls, while the.wsr.g.verified.csvariant usesRenderUtilitiesfor whitespace handling.Parent.Directory.Packages.props (2)
14-14: LGTM! Release version update.The version bump from
0.0.0-beta.1to1.0.0indicates this PR is preparing for a stable release. The change is appropriate given the new features being added (FileTemplateAttribute, RenderUtilities).
16-16: LGTM! New dependency addition.The addition of the
Pastedpackage at version1.0.0with the appropriate mono-repo condition is consistent with the existing project structure. Based on the AI summary, this package is used for analyzer purposes in the Cutout project.Cutout.Tests/TemplateTests.Case3a#Test.TestWithTwoParameters.wsr.g.verified.cs (1)
13-19: LGTM! Excellent whitespace handling refactor.The changes improve the code in two ways:
- Type aliases: Using
intandstringinstead ofInt32andStringis more idiomatic C#.- Centralized whitespace handling: Using
RenderUtilities.ApplyExtraWhitespaceconsolidates whitespace logic into a reusable utility, replacing per-parameter inline handling. This improves maintainability and consistency across the codebase.The whitespace-sensitive rendering (
.wsrvariant) correctly uses the utility, while the standard version (.gvariant) uses directAppendcalls.Cutout.Tests/CallStatementTests.Case1a#Test.Test.g.verified.cs (1)
13-13: LGTM! Consistent type alias usage.The change from
Stringtostringaligns with idiomatic C# conventions and improves consistency across the generated test files. This is part of the broader generator improvements in this PR.Cutout.Tests/SharedTests.Case1#FileTemplateAttribute.g.verified.cs (1)
14-20: No issues found—template discovery mechanism is working correctly.The
FileTemplateAttributecorrectly has no constructor parameters. Template files are discovered via.editorconfigconfiguration, as evidenced by:
.editorconfiginCutout.Samplecontainstemplate_method = Cutout.Sample.Examples.Test4SampleTemplate.cs.liquidis present and mapped to theTest4method via this configurationTemplateSourceGeneratorcombines embedded files, config options, and decorated methods to process template files- The
Test4method inExamples.csis properly decorated with[FileTemplate]The design is correct and working as intended.
Cutout.Sample/SampleTemplate.cs.liquid (1)
1-10: LGTM! Well-structured liquid template.The template correctly uses the
{{parameter}}placeholder for both the class name and within the method's return string. The syntax is valid and the structure follows standard C# conventions.Cutout.Tests/TemplateTests.Case5a#Test.TestWithConstantTemplate.wsr.g.verified.cs (1)
15-17: LGTM! Centralized whitespace handling applied correctly.The refactoring successfully consolidates whitespace normalization into a single
ApplyExtraWhitespacecall, improving maintainability and consistency across the codebase.Cutout.Tests/TemplateTests.Case2a#Test.TestWithParameter.g.verified.cs (1)
13-13: LGTM! Type alias standardization.The change from
Int32tointaligns with C# coding conventions and improves code consistency across the generated files.Cutout.Tests/TemplateTests.Case3a#Test.TestWithTwoParameters.g.verified.cs (1)
13-13: LGTM! Type alias standardization.The change from
Int32tointandStringtostringaligns with C# coding conventions and improves consistency across the codebase.Cutout.Tests/ForStatementTests.Case1a#Test.Test.g.verified.cs (1)
13-13: LGTM! Type alias standardization.The change from
Stringtostringaligns with C# coding conventions and maintains consistency with the broader refactoring in this PR.Cutout.Tests/ForStatementTests.Case3a#Test.Test.wsr.g.verified.cs (2)
13-13: LGTM! Type alias standardization.The parameter type change from
Stringtostringaligns with C# coding conventions.
26-28: LGTM! Centralized whitespace handling applied correctly.The refactoring successfully applies
ApplyExtraWhitespaceto both the loop index and tag values, ensuring consistent whitespace normalization across interpolated content.Cutout.Tests/TemplateTests.Case2a#Test.TestWithParameter.wsr.g.verified.cs (2)
13-13: LGTM! Signature updated for centralized whitespace handling.The parameter type change to
intaligns with C# conventions, and the additionalwhitespaceparameter enables the centralized whitespace normalization pattern.
16-16: LGTM! Centralized whitespace handling applied correctly.The parameter value is now properly wrapped with
ApplyExtraWhitespace, ensuring consistent whitespace normalization for interpolated values.Cutout.Tests/SharedTests.Case1#RenderUtilities.g.verified.cs (1)
12-24: LGTM! Well-designed utility for whitespace normalization.The
RenderUtilities.ApplyExtraWhitespaceimplementation correctly handles:
- Null values (returns null)
- String values (passes through without conversion)
- Other types (uses
ToString())- Newline indentation (prefixes each newline with the specified whitespace)
This centralized approach improves maintainability and ensures consistent whitespace handling across all generated render methods.
Cutout.Tests/IfStatementTests.Case1a#Test.Test.wsr.g.verified.cs (1)
13-13: LGTM! Type alias normalization.The parameter type has been correctly normalized from
Stringtostring, aligning with C# conventions that prefer primitive type aliases.Cutout.Tests/ForStatementTests.Case1a#Test.Test.wsr.g.verified.cs (1)
13-18: LGTM! Type normalization and centralized whitespace handling.The changes correctly normalize the parameter type alias and adopt the centralized
RenderUtilities.ApplyExtraWhitespaceutility for consistent whitespace handling across the codebase.Cutout/Cutout.csproj (2)
37-48: LGTM! Proper conditional dependency configuration.The conditional references correctly handle both mono-repo and standalone builds:
- NuGet package reference with
PrivateAssets=allfor standalone builds- Analyzer-only project reference for mono-repo builds
This ensures the Pasted dependency is available for source generation without leaking to consumers.
50-52: LGTM! Embedded source files configuration.The
AdditionalFilesconfiguration correctly includes all*.Source.csfiles, making them available to the source generator for embedding into consuming projects.Cutout/FileTemplateAttribute.Source.cs (1)
8-19: LGTM! Clean marker attribute design.The
FileTemplateAttributeis appropriately designed as a marker attribute for file-based templates. The parameterless constructor and absence of properties align with the design where template content is sourced from external files rather than attribute parameters.Cutout.Tests/ForStatementTests.Case2a#Test.Test.wsr.g.verified.cs (1)
13-20: LGTM! Consistent pattern adoption.The changes correctly apply both the type alias normalization and centralized whitespace handling pattern using
RenderUtilities.ApplyExtraWhitespacefor both expressions within the loop.Cutout.Tests/TemplateTests.Case4a#Test.TestWithModel.wsr.g.verified.cs (1)
13-18: LGTM! Enhanced signature and whitespace handling.The changes correctly:
- Add the
whitespaceparameter to support whitespace handling- Fully qualify the nested
Test.SomeModeltype- Apply the centralized
RenderUtilities.ApplyExtraWhitespaceutility for both model propertiesCutout/Renderer/Renderer.cs (3)
111-123: LGTM! Centralized whitespace handling in WriteRawText.The refactoring correctly:
- Extracts the renderable variable for clarity
- Conditionally applies
ApplyExtraWhitespaceonly when whitespace receiver is included and text contains newlines- Maintains backward compatibility for standard cases
133-145: LGTM! Consistent whitespace handling pattern.The refactoring applies the same centralized whitespace handling pattern as
WriteRawText, extracting the renderable expression and conditionally applyingApplyExtraWhitespacebased on the whitespace receiver flag.
203-222: LGTM! Cleaner whitespace parameter logic.The refactoring introduces a
hasWhitespaceboolean that makes the conditional logic more readable and correctly handles all combinations:
- Pass runtime
whitespaceparameter when receiver is included- Pass literal whitespace string when available
- Concatenate both when necessary
The logic is clearer and maintains correct behavior.
Cutout/TemplateSourceGenerator.cs (5)
35-60: LGTM: Dual-pipeline architecture is well-structured.The separation between attribute-based and file-based template providers is clear and maintainable. Both pipelines correctly feed into the same
GenerateTemplatemethod.
119-129: Consider reporting diagnostics for missing template method references.When
template_methodis specified in the config but doesn't match any[FileTemplateAttribute]-annotated method, the configuration is silently ignored. This could lead to confusion during development.Consider adding diagnostic reporting:
if (!methodLookup.TryGetValue(method, out var methodContext)) { context.ReportDiagnostic( Diagnostic.Create( new DiagnosticDescriptor( "CUTOUT002", "Template method not found", $"Method '{method}' specified in template_method option not found or not decorated with [FileTemplateAttribute]", "Cutout", DiagnosticSeverity.Warning, isEnabledByDefault: true ), Location.None ) ); continue; }Note: You'll need to adjust the signature to accept
SourceProductionContextor use a different diagnostic reporting mechanism appropriate for theSelectManycontext.
109-115: Verify file type/extension filtering for template files.The code processes all
AdditionalTextfiles without filtering by extension or path pattern. While thetemplate_methodoption check (line 119) acts as a filter, you may want to verify that unrelated additional files (e.g., JSON configs, documentation) don't incur unnecessary processing overhead.Optionally, add extension filtering for clarity:
foreach (var file in ctx.Static.Files) { // Only process .txt or .template files (adjust extensions as needed) if (!file.Path.EndsWith(".txt", StringComparison.OrdinalIgnoreCase) && !file.Path.EndsWith(".template", StringComparison.OrdinalIgnoreCase)) { continue; } if (file.GetText(token)?.ToString() is not { } templateText) { continue; } // ... }
141-159: LGTM: Clean refactor that enables code reuse.Delegating to
BuildTemplateDetailsFromSyntaxextracts common logic and maintains consistency between attribute-based and file-based template handling.
85-92: Verify case-sensitive method name matching is intended.The
methodLookupdictionary usesStringComparer.Ordinal, requiring exact case-sensitive matches betweentemplate_methodconfig values and method full names. Ensure this aligns with the expected.editorconfigusage pattern—any casing mismatch will result in silent failure to match methods.If case-insensitive matching is preferred, use:
Dictionary< string, ( SemanticModel semanticModel, MethodDeclarationSyntax methodDeclarationSyntax, IMethodSymbol methodSymbol ) - > methodLookup = new(StringComparer.Ordinal); + > methodLookup = new(StringComparer.OrdinalIgnoreCase);
There was a problem hiding this comment.
Actionable comments posted: 1
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (2)
Cutout.Docs/articles/file-templates.md(1 hunks)Cutout.Docs/toc.yml(1 hunks)
🧰 Additional context used
🪛 markdownlint-cli2 (0.18.1)
Cutout.Docs/articles/file-templates.md
9-9: Trailing spaces
Expected: 0 or 2; Actual: 1
(MD009, no-trailing-spaces)
41-41: Trailing spaces
Expected: 0 or 2; Actual: 1
(MD009, no-trailing-spaces)
🔇 Additional comments (2)
Cutout.Docs/toc.yml (1)
6-7: LGTM!Navigation entry is well-placed and properly formatted. The new "File Templates" section logically precedes the "Template" section.
Cutout.Docs/articles/file-templates.md (1)
1-42: Comprehensive and well-structured documentation.The documentation effectively explains the file-based templating workflow with clear, practical examples covering project file setup, C# method definitions, and .editorconfig binding. Content aligns well with the PR objectives and the new
FileTemplateAttributefeature.
…eaner initialization logic
047d327 to
2b65799
Compare
|


FileTemplateAttributeto support templates from external files.RenderUtilities.ApplyExtraWhitespacefor improved whitespace handling.Summary by CodeRabbit
New Features
Documentation
Tests
Chores