Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support for implicit conversion from raw to refined #19

Merged
merged 4 commits into from
Jan 8, 2025

Conversation

bmazzarol
Copy link
Owner

@bmazzarol bmazzarol commented Jan 8, 2025

Summary by CodeRabbit

  • New Features

    • Added support for implicit type conversions in refinement attributes.
    • Introduced ToString() method for various refined type structs.
    • Added Deconstruct method for multi-refined types.
    • New property HasImplicitConversionFromRaw added to multiple classes for enhanced conversion control.
    • New method RenderIfTrue for conditional string rendering.
    • New refined integer type OddInt with validation and conversion operators.
  • Improvements

    • Enhanced refinement type generation with more flexible conversion options.
    • Improved string representation for refined types.
    • Refined analyzer logic for attribute checking.
    • New method HasInterface for checking interface implementations.
  • Tests

    • Added new test cases for implicit conversion scenarios.
    • Expanded test coverage for refinement type behaviors.
    • New test case added for the OddInt refined type.

@bmazzarol bmazzarol added the enhancement New feature or request label Jan 8, 2025
@bmazzarol bmazzarol self-assigned this Jan 8, 2025
Copy link

coderabbitai bot commented Jan 8, 2025

Walkthrough

The pull request introduces several enhancements to the Tuxedo source generator, focusing on refinement type generation and analysis. The changes primarily involve adding a new HasImplicitConversionFromRaw property across multiple components, which allows more flexible control over type conversions. Additionally, the changes include the implementation of ToString() methods for various generated refined types and a new method for deconstruction. The modifications aim to improve the flexibility and usability of the source generator's type refinement capabilities.

Changes

File Change Summary
Tuxedo.SourceGenerator/Analysers/MissingFailureMessageAnalyzer.cs Refined string literal checking logic in Analyze method
Tuxedo.SourceGenerator/Generators/RefinementSourceGenerator.AttributeSources.cs Added HasImplicitConversionFromRaw property to RefinementAttribute
Tuxedo.SourceGenerator/Generators/RefinementSourceGenerator.MultiRefinedTypeSource.cs Added Deconstruct method and RenderFormattingMembers call
Tuxedo.SourceGenerator/Generators/RefinementSourceGenerator.RefinedTypeDetails.cs Modified RefinedTypeDetails to include new fields and remove others
Tuxedo.SourceGenerator/Generators/RefinementSourceGenerator.RefinementAttributeParts.cs Changed RefinementAttributeParts to a sealed record and added HasImplicitConversionFromRaw property
Tuxedo.SourceGenerator/Generators/RefinementSourceGenerator.SingleRefinedTypeSource.cs Added RenderFormattingMembers method and updated ToString implementations
Tuxedo.SourceGenerator/Generators/RefinementSourceGenerator.cs Updated BuildRefinedTypeDetails to include HasImplicitConversionFromRaw
Multiple Test Files Added ToString() methods to various generated refined type structs
Tuxedo.Tests/ConfigureRefinementTypesExample.cs Added ExampleWithImplicitConversion method
Tuxedo.SourceGenerator/Extensions/StringExtensions.cs Added RenderIfTrue method for conditional rendering
Tuxedo.SourceGenerator/Extensions/SymbolExtensions.cs Added HasInterface method to check for interface implementation

Sequence Diagram

sequenceDiagram
    participant SG as Source Generator
    participant RT as Refined Type
    participant Attr as RefinementAttribute

    SG->>Attr: Check HasImplicitConversionFromRaw
    Attr-->>SG: Return conversion flag
    SG->>RT: Generate Type
    alt Implicit Conversion
        SG->>RT: Use Implicit Conversion Operator
    else Explicit Conversion
        SG->>RT: Use Explicit Conversion Operator
    end
Loading

Poem

🐰 Refinement's Dance, a Rabbit's Delight
Implicit or explicit, types take flight
Conversion magic, with a gentle prance
Tuxedo's source gen leads the dance
Generating code with whiskered might! 🌟


🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

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)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

github-actions bot commented Jan 8, 2025

Test Results

36 tests   36 ✅  10s ⏱️
 1 suites   0 💤
 1 files     0 ❌

Results for commit fcf8530.

♻️ This comment has been updated with latest results.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (6)
Tuxedo.Tests/PasswordStringExampleTests.Case2#PasswordString.g.verified.cs (1)

117-120: Simplify the ToString implementation.

The current implementation calls ToString() on a string value which is redundant. Since _value is already a string, you can return it directly.

    public override string? ToString()
    {
-       return _value?.ToString();
+       return _value;
    }
Tuxedo.Tests/ConfigureRefinementTypesExample.Case2#Case4.g.verified.cs (1)

17-22: Handle default instances of Case4 more explicitly

The _value field is nullable, and accessing Value when _value is null throws an InvalidOperationException. This could lead to unexpected exceptions if a default instance of Case4 is used inadvertently. Consider making Case4 a struct without nullable fields or provide a default value to prevent _value from being null.

Tuxedo.Tests/SharedTests.Case1#RefinementAttribute.g.verified.cs (1)

Line range hint 39-43: Fix incomplete XML documentation comments for constructors

The XML documentation comments for the constructors are missing closing </summary> tags, which can result in documentation warnings and incomplete generated documentation. Ensure all XML comments are properly closed.

Apply this diff to correct the XML comments:

     /// <summary>
     /// Initializes a new instance of the <see cref="RefinementAttribute"/> class
+    /// </summary>
     public RefinementAttribute(string failureMessage)
     {
         FailureMessage = failureMessage;
     }
     
     /// <summary>
     /// Initializes a new instance of the <see cref="RefinementAttribute"/> class
+    /// </summary>
     public RefinementAttribute()
     {
     }
Tuxedo.Tests/ConfigureRefinementTypesExample.cs (1)

17-22: Add XML documentation for the new method.

Consider adding XML documentation to maintain consistency with the codebase's documentation standards.

+    /// <summary>
+    /// Example refinement method that supports implicit conversion from raw type
+    /// </summary>
+    /// <param name="value">The raw value to refine</param>
+    /// <returns>The refined value</returns>
     [Refinement(
         Name = nameof(Case4),
         HasImplicitConversionFromRaw = true,
         FailureMessage = "Must be true"
     )]
     public static bool ExampleWithImplicitConversion(bool value) => value;
Tuxedo.Tests/BoolRefinementsTests.Case5#TrueBool.g.verified.cs (1)

115-120: Consider more specific ToString implementation for boolean refinements.

While the current implementation is correct and consistent with other refined types, consider providing a more specific implementation for boolean refinements. This could improve clarity when the value is used in string contexts.

-    public override string? ToString()
-    {
-        return _value?.ToString();
-    }
+    public override string ToString()
+    {
+        return _value?.ToString() ?? "undefined";
+    }
Tuxedo.SourceGenerator/Analysers/MissingFailureMessageAnalyzer.cs (1)

67-70: Consider extracting and simplifying the string literal check.

The string literal check could be more readable and maintainable.

Consider this refactoring:

-            .Any(arg =>
-                arg.Expression is LiteralExpressionSyntax literal
-                && literal.IsKind(SyntaxKind.StringLiteralExpression)
-            );
+            .Any(arg => arg.Expression.IsKind(SyntaxKind.StringLiteralExpression));

Or for better readability, extract to a dedicated method:

+    private static bool IsStringLiteralArgument(AttributeArgumentSyntax arg) =>
+        arg.Expression.IsKind(SyntaxKind.StringLiteralExpression);
+
     private static void Analyze(SyntaxNodeAnalysisContext ctx)
     {
         // ... existing code ...
         var hasStringConstructor = ctx
             .Node.DescendantNodes()
             .OfType<AttributeArgumentSyntax>()
-            .Any(arg =>
-                arg.Expression is LiteralExpressionSyntax literal
-                && literal.IsKind(SyntaxKind.StringLiteralExpression)
-            );
+            .Any(IsStringLiteralArgument);
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fb373d2 and 369b691.

📒 Files selected for processing (20)
  • Tuxedo.SourceGenerator/Analysers/MissingFailureMessageAnalyzer.cs (1 hunks)
  • Tuxedo.SourceGenerator/Generators/RefinementSourceGenerator.AttributeSources.cs (1 hunks)
  • Tuxedo.SourceGenerator/Generators/RefinementSourceGenerator.MultiRefinedTypeSource.cs (1 hunks)
  • Tuxedo.SourceGenerator/Generators/RefinementSourceGenerator.RefinedTypeDetails.cs (1 hunks)
  • Tuxedo.SourceGenerator/Generators/RefinementSourceGenerator.RefinementAttributeParts.cs (2 hunks)
  • Tuxedo.SourceGenerator/Generators/RefinementSourceGenerator.SingleRefinedTypeSource.cs (3 hunks)
  • Tuxedo.SourceGenerator/Generators/RefinementSourceGenerator.cs (2 hunks)
  • Tuxedo.Tests/BoolRefinementsTests.Case4#FalseBool.g.verified.cs (1 hunks)
  • Tuxedo.Tests/BoolRefinementsTests.Case5#TrueBool.g.verified.cs (1 hunks)
  • Tuxedo.Tests/ConfigureRefinementTypesExample.Case1#Case3.g.verified.cs (1 hunks)
  • Tuxedo.Tests/ConfigureRefinementTypesExample.Case2#Case4.g.verified.cs (1 hunks)
  • Tuxedo.Tests/ConfigureRefinementTypesExample.cs (2 hunks)
  • Tuxedo.Tests/CustomAccessModifierTests.Case2#WhiteSpaceChar.g.verified.cs (1 hunks)
  • Tuxedo.Tests/CustomTypeRefinementTests.Case3#ValidWidget.g.verified.cs (1 hunks)
  • Tuxedo.Tests/DateOnlyExample.Case3#DateOnlyString.g.verified.cs (1 hunks)
  • Tuxedo.Tests/GuidStringTests.Case3#GuidString.g.verified.cs (1 hunks)
  • Tuxedo.Tests/OddNumberExample.Case4#Odd.g.verified.cs (1 hunks)
  • Tuxedo.Tests/OddNumberExample.Case5#Odd.g.verified.cs (1 hunks)
  • Tuxedo.Tests/PasswordStringExampleTests.Case2#PasswordString.g.verified.cs (1 hunks)
  • Tuxedo.Tests/SharedTests.Case1#RefinementAttribute.g.verified.cs (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Build and analyze
🔇 Additional comments (19)
Tuxedo.Tests/PasswordStringExampleTests.Case2#PasswordString.g.verified.cs (1)

Line range hint 1-120: Well-structured implementation with good practices!

The implementation demonstrates several good practices:

  • Immutable value type design
  • Comprehensive null handling
  • Clear validation error messages
  • Safe construction methods via Parse/TryParse
  • Complete equality implementation
Tuxedo.SourceGenerator/Generators/RefinementSourceGenerator.RefinedTypeDetails.cs (1)

20-21: Addition of HasImplicitConversionFromRaw property is appropriate

The inclusion of the HasImplicitConversionFromRaw boolean property in the RefinedTypeDetails record struct extends its functionality to capture implicit conversion capabilities, enhancing the flexibility of type refinements.

Tuxedo.Tests/SharedTests.Case1#RefinementAttribute.g.verified.cs (1)

32-36: Addition of HasImplicitConversionFromRaw property enhances flexibility

Introducing the HasImplicitConversionFromRaw property to the RefinementAttribute class allows fine-grained control over the generation of implicit conversions from the raw type to the refined type, improving the usability of refined types.

Tuxedo.Tests/ConfigureRefinementTypesExample.cs (1)

34-41: LGTM! Well-structured test case.

The test case effectively verifies the new implicit conversion feature.

Tuxedo.SourceGenerator/Generators/RefinementSourceGenerator.MultiRefinedTypeSource.cs (1)

40-41: LGTM! Well-implemented deconstruction support.

The addition of the Deconstruct method with proper XML documentation enhances the usability of the refined types by supporting tuple-like deconstruction.

Also applies to: 42-51

Tuxedo.SourceGenerator/Generators/RefinementSourceGenerator.RefinementAttributeParts.cs (2)

14-14: LGTM! Property declaration is clear and concise.

The HasImplicitConversionFromRaw property is well-integrated into the attribute parts structure.


46-50: LGTM! Good refactoring of boolean attribute checking.

The introduction of the IsEnabled method improves code maintainability by eliminating duplication in boolean attribute checking.

Also applies to: 53-55

Tuxedo.SourceGenerator/Generators/RefinementSourceGenerator.AttributeSources.cs (1)

36-41: LGTM! Well-documented attribute property.

The HasImplicitConversionFromRaw property is properly documented with clear explanation of its purpose and default behavior.

Tuxedo.Tests/OddNumberExample.Case4#Odd.g.verified.cs (1)

116-121: LGTM! Clean ToString implementation.

The implementation correctly handles the nullable case and follows the standard pattern for ToString implementations.

Tuxedo.Tests/OddNumberExample.Case5#Odd.g.verified.cs (1)

117-122: LGTM! Consistent implementation across cases.

The ToString implementation is consistent with Case4, which is good for maintainability.

Tuxedo.Tests/BoolRefinementsTests.Case4#FalseBool.g.verified.cs (1)

115-120: Same enhancement applies as TrueBool.

The same suggestion for a more specific ToString implementation applies here as well.

Tuxedo.Tests/ConfigureRefinementTypesExample.Case1#Case3.g.verified.cs (1)

115-120: LGTM! Clean ToString() implementation.

The implementation correctly handles the nullable value and follows C# conventions.

Tuxedo.Tests/CustomTypeRefinementTests.Case3#ValidWidget.g.verified.cs (1)

115-120: LGTM! Consistent ToString() implementation.

The implementation follows the same pattern as other refined types and correctly handles null values.

Tuxedo.Tests/CustomAccessModifierTests.Case2#WhiteSpaceChar.g.verified.cs (1)

115-120: LGTM! Consistent ToString() implementation.

The implementation maintains consistency with other refined types and properly handles null values.

Tuxedo.Tests/GuidStringTests.Case3#GuidString.g.verified.cs (1)

134-138: LGTM! Clean ToString implementation.

The implementation correctly handles null values and follows the standard ToString pattern.

Tuxedo.Tests/DateOnlyExample.Case3#DateOnlyString.g.verified.cs (1)

134-138: LGTM! Consistent ToString implementation.

The implementation maintains consistency with other refined types and correctly handles null values.

Tuxedo.SourceGenerator/Generators/RefinementSourceGenerator.cs (1)

96-96: LGTM! Clean integration of implicit conversion support.

The hasImplicitConversionFromRaw property is well-integrated into the BuildRefinedTypeDetails method and follows the established pattern.

Also applies to: 143-144

Tuxedo.SourceGenerator/Generators/RefinementSourceGenerator.SingleRefinedTypeSource.cs (2)

208-215: LGTM! Clean ToString template implementation.

The FormattingMembers constant provides a consistent template for ToString implementation across all refined types.


108-117: LGTM! Well-implemented conversion type handling.

The implementation cleanly switches between implicit and explicit conversion operators while maintaining consistent documentation.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (3)
Tuxedo.Tests/BoolRefinementsTests.Case5#TrueBool.g.verified.cs (1)

115-120: Consider adding a comment about the empty string fallback.

The ToString() implementation looks good, but consider documenting why an empty string is returned for null values to improve maintainability.

     /// <inheritdoc />
+    /// <remarks>Returns an empty string if the underlying value is null (default struct state)</remarks>
     public override string ToString()
     {
         return _value?.ToString() ?? string.Empty;
     }
Tuxedo.Tests/DateOnlyExample.Case3#DateOnlyString.g.verified.cs (1)

134-138: Consider aligning ToString with Value property behavior.

The current implementation returns an empty string for null values, while the Value property throws. This inconsistency could mask initialization issues. Consider either:

  1. Aligning with Value property behavior:
public override string ToString()
{
-    return _value?.ToString() ?? string.Empty;
+    return Value;
}
  1. Or documenting the intentional difference in behavior.
Tuxedo.SourceGenerator/Generators/RefinementSourceGenerator.SingleRefinedTypeSource.cs (1)

209-215: LGTM! Consider future enhancement for custom formatting.

The ToString implementation correctly handles null values and follows standard patterns. For future enhancement, consider adding support for custom format strings to handle more complex formatting scenarios.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 369b691 and f8db8a1.

📒 Files selected for processing (12)
  • Tuxedo.SourceGenerator/Generators/RefinementSourceGenerator.SingleRefinedTypeSource.cs (4 hunks)
  • Tuxedo.Tests/BoolRefinementsTests.Case4#FalseBool.g.verified.cs (2 hunks)
  • Tuxedo.Tests/BoolRefinementsTests.Case5#TrueBool.g.verified.cs (2 hunks)
  • Tuxedo.Tests/ConfigureRefinementTypesExample.Case1#Case3.g.verified.cs (2 hunks)
  • Tuxedo.Tests/ConfigureRefinementTypesExample.Case2#Case4.g.verified.cs (1 hunks)
  • Tuxedo.Tests/CustomAccessModifierTests.Case2#WhiteSpaceChar.g.verified.cs (2 hunks)
  • Tuxedo.Tests/CustomTypeRefinementTests.Case3#ValidWidget.g.verified.cs (2 hunks)
  • Tuxedo.Tests/DateOnlyExample.Case3#DateOnlyString.g.verified.cs (2 hunks)
  • Tuxedo.Tests/GuidStringTests.Case3#GuidString.g.verified.cs (2 hunks)
  • Tuxedo.Tests/OddNumberExample.Case4#Odd.g.verified.cs (2 hunks)
  • Tuxedo.Tests/OddNumberExample.Case5#Odd.g.verified.cs (2 hunks)
  • Tuxedo.Tests/PasswordStringExampleTests.Case2#PasswordString.g.verified.cs (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (9)
  • Tuxedo.Tests/CustomAccessModifierTests.Case2#WhiteSpaceChar.g.verified.cs
  • Tuxedo.Tests/BoolRefinementsTests.Case4#FalseBool.g.verified.cs
  • Tuxedo.Tests/OddNumberExample.Case5#Odd.g.verified.cs
  • Tuxedo.Tests/ConfigureRefinementTypesExample.Case1#Case3.g.verified.cs
  • Tuxedo.Tests/OddNumberExample.Case4#Odd.g.verified.cs
  • Tuxedo.Tests/PasswordStringExampleTests.Case2#PasswordString.g.verified.cs
  • Tuxedo.Tests/CustomTypeRefinementTests.Case3#ValidWidget.g.verified.cs
  • Tuxedo.Tests/GuidStringTests.Case3#GuidString.g.verified.cs
  • Tuxedo.Tests/ConfigureRefinementTypesExample.Case2#Case4.g.verified.cs
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Build and analyze
🔇 Additional comments (5)
Tuxedo.Tests/BoolRefinementsTests.Case5#TrueBool.g.verified.cs (1)

81-81: LGTM! Safer default assignment.

The removal of the null-forgiving operator makes the code safer by not suppressing nullability warnings.

Tuxedo.Tests/DateOnlyExample.Case3#DateOnlyString.g.verified.cs (1)

99-99: LGTM! Improved null-safety.

The change from default! to default better represents the failure state and aligns with nullable reference type best practices.

Tuxedo.SourceGenerator/Generators/RefinementSourceGenerator.SingleRefinedTypeSource.cs (3)

30-31: LGTM! Clean integration of formatting members.

The placement and integration of the formatting members is well-structured and maintains consistent code organization.


160-160: LGTM! Safer initialization without null-forgiving operator.

Good change to use default instead of default!. This is safer as it properly handles the nullable context without suppressing warnings.


108-117: Verify HasImplicitConversionFromRaw property usage.

The conditional operator conversion looks good, but let's verify the HasImplicitConversionFromRaw property implementation and usage.

Let's check the property implementation and its usage:

✅ Verification successful

HasImplicitConversionFromRaw property implementation is correct and properly used.

The property is well-defined with clear documentation, proper default value handling (false), and consistent usage throughout the source generator pipeline. Test cases demonstrate both implicit and explicit conversion scenarios.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify HasImplicitConversionFromRaw property implementation and usage

# Find the property definition
echo "Property definition:"
rg -l "HasImplicitConversionFromRaw"

# Check its usage in tests
echo -e "\nProperty usage in tests:"
rg "HasImplicitConversionFromRaw.*=.*true" -A 2

Length of output: 1317


Script:

#!/bin/bash
# Check property definition and usage in source generator
echo "Property definition and initialization:"
rg -A 3 "HasImplicitConversionFromRaw.*{.*get" 

echo -e "\nSource generator processing:"
rg -A 5 "HasImplicitConversionFromRaw.*=.*false" 

echo -e "\nTest cases (including false cases):"
ast-grep --pattern 'Refinement($$$, HasImplicitConversionFromRaw = $_)'

Length of output: 572


Script:

#!/bin/bash
# Search for property definition and implementation
echo "Property definition:"
rg "HasImplicitConversionFromRaw" -B 2 -A 2

echo -e "\nRefinement attribute usage:"
rg "Refinement.*HasImplicitConversionFromRaw" -B 1 -A 1

echo -e "\nSource generator implementation:"
rg "HasImplicitConversionFromRaw" "Tuxedo.SourceGenerator/Generators/RefinementSourceGenerator.RefinedTypeDetails.cs" -B 2 -A 2

Length of output: 7414

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (4)
Tuxedo.SourceGenerator/Generators/RefinementSourceGenerator.RefinementAttributeParts.cs (1)

53-55: Consider enhancing boolean parsing robustness

While the current implementation works for "true", consider supporting additional boolean string representations for better flexibility.

 private static bool IsEnabled(string value, Dictionary<string?, string> nameToArgs) =>
     nameToArgs.TryGetValue(value, out var v)
-    && string.Equals(v, "true", StringComparison.Ordinal);
+    && (string.Equals(v, "true", StringComparison.OrdinalIgnoreCase) ||
+        string.Equals(v, "True", StringComparison.Ordinal) ||
+        string.Equals(v, "1", StringComparison.Ordinal));
Tuxedo.SourceGenerator/Extensions/SymbolExtensions.cs (2)

18-24: LGTM! Consider adding XML documentation.

The implementation is correct and follows good practices with null-safety and proper string comparison. Consider adding XML documentation to improve maintainability.

+    /// <summary>
+    /// Checks if the type symbol implements the specified interface.
+    /// </summary>
+    /// <param name="symbol">The type symbol to check.</param>
+    /// <param name="interfaceName">The fully qualified interface name.</param>
+    /// <returns>True if the type implements the interface, false otherwise.</returns>
     public static bool HasInterface(this ITypeSymbol? symbol, string interfaceName)

20-23: Consider simplifying the boolean expression.

The current pattern using is true can be simplified.

-        return symbol?.AllInterfaces.Any(i =>
-            i.ToDisplayString().Equals(interfaceName, StringComparison.Ordinal)
-        )
-            is true;
+        return symbol?.AllInterfaces.Any(i =>
+            i.ToDisplayString().Equals(interfaceName, StringComparison.Ordinal)) ?? false;
Tuxedo.SourceGenerator/Generators/RefinementSourceGenerator.MultiRefinedTypeSource.cs (1)

Line range hint 42-50: Enhance XML documentation for the altValue parameter.

The XML comment for altValue could be more descriptive about its purpose and relationship to the refined type.

-     /// <param name="altValue">alternative {{model.AlternativeType.EscapeXml()}}</param>
+     /// <param name="altValue">The alternative value produced when the refinement predicate is satisfied</param>
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f8db8a1 and cae2afb.

📒 Files selected for processing (18)
  • Tuxedo.SourceGenerator/Extensions/StringExtensions.cs (1 hunks)
  • Tuxedo.SourceGenerator/Extensions/SymbolExtensions.cs (1 hunks)
  • Tuxedo.SourceGenerator/Generators/RefinementSourceGenerator.MultiRefinedTypeSource.cs (1 hunks)
  • Tuxedo.SourceGenerator/Generators/RefinementSourceGenerator.RefinedTypeDetails.cs (1 hunks)
  • Tuxedo.SourceGenerator/Generators/RefinementSourceGenerator.RefinementAttributeParts.cs (2 hunks)
  • Tuxedo.SourceGenerator/Generators/RefinementSourceGenerator.SingleRefinedTypeSource.cs (5 hunks)
  • Tuxedo.SourceGenerator/Generators/RefinementSourceGenerator.cs (1 hunks)
  • Tuxedo.Tests/BoolRefinementsTests.Case4#FalseBool.g.verified.cs (2 hunks)
  • Tuxedo.Tests/BoolRefinementsTests.Case5#TrueBool.g.verified.cs (2 hunks)
  • Tuxedo.Tests/ConfigureRefinementTypesExample.Case1#Case3.g.verified.cs (2 hunks)
  • Tuxedo.Tests/ConfigureRefinementTypesExample.Case2#Case4.g.verified.cs (1 hunks)
  • Tuxedo.Tests/CustomAccessModifierTests.Case2#WhiteSpaceChar.g.verified.cs (2 hunks)
  • Tuxedo.Tests/CustomTypeRefinementTests.Case3#ValidWidget.g.verified.cs (2 hunks)
  • Tuxedo.Tests/DateOnlyExample.Case3#DateOnlyString.g.verified.cs (2 hunks)
  • Tuxedo.Tests/GuidStringTests.Case3#GuidString.g.verified.cs (2 hunks)
  • Tuxedo.Tests/OddNumberExample.Case4#Odd.g.verified.cs (2 hunks)
  • Tuxedo.Tests/OddNumberExample.Case5#Odd.g.verified.cs (2 hunks)
  • Tuxedo.Tests/PasswordStringExampleTests.Case2#PasswordString.g.verified.cs (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (12)
  • Tuxedo.Tests/CustomAccessModifierTests.Case2#WhiteSpaceChar.g.verified.cs
  • Tuxedo.Tests/BoolRefinementsTests.Case4#FalseBool.g.verified.cs
  • Tuxedo.Tests/BoolRefinementsTests.Case5#TrueBool.g.verified.cs
  • Tuxedo.Tests/CustomTypeRefinementTests.Case3#ValidWidget.g.verified.cs
  • Tuxedo.Tests/ConfigureRefinementTypesExample.Case1#Case3.g.verified.cs
  • Tuxedo.Tests/OddNumberExample.Case4#Odd.g.verified.cs
  • Tuxedo.Tests/DateOnlyExample.Case3#DateOnlyString.g.verified.cs
  • Tuxedo.Tests/GuidStringTests.Case3#GuidString.g.verified.cs
  • Tuxedo.Tests/OddNumberExample.Case5#Odd.g.verified.cs
  • Tuxedo.SourceGenerator/Generators/RefinementSourceGenerator.cs
  • Tuxedo.Tests/PasswordStringExampleTests.Case2#PasswordString.g.verified.cs
  • Tuxedo.Tests/ConfigureRefinementTypesExample.Case2#Case4.g.verified.cs
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Build and analyze
🔇 Additional comments (10)
Tuxedo.SourceGenerator/Generators/RefinementSourceGenerator.RefinementAttributeParts.cs (3)

14-14: LGTM! Well-designed property addition

The new HasImplicitConversionFromRaw property is well-named and follows immutable design principles, aligning perfectly with the PR's objective of supporting implicit conversions from raw types.


46-50: LGTM! Good refactoring for maintainability

The extraction of the boolean parsing logic into IsEnabled improves code maintainability and reduces duplication. The multi-line formatting enhances readability.


8-8: Verify performance impact of changing from ref struct to sealed record

The change from ref struct to sealed record shifts from stack-only allocation to heap allocation. While this improves usability and maintainability, it might impact performance in performance-critical paths.

Run this script to analyze usage patterns and potential performance implications:

✅ Verification successful

Change from ref struct to sealed record is safe

The type is only used during source generation at compile time, with no high-frequency allocations or performance-critical paths. The change improves maintainability without impacting runtime performance.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check usage patterns of RefinementAttributeParts to assess performance impact

# Find all usages of RefinementAttributeParts
rg -l "RefinementAttributeParts" | while read -r file; do
  echo "=== $file ==="
  # Show context to understand usage patterns (loops, high-frequency operations, etc.)
  rg -C 5 "RefinementAttributeParts" "$file"
done

Length of output: 2539

Tuxedo.SourceGenerator/Extensions/SymbolExtensions.cs (1)

18-24: Verify the usage context for implicit conversions.

Let's verify how this method is used in the context of implicit conversions from raw to refined types.

✅ Verification successful

Implementation correctly supports interface preservation for refined types

The HasInterface method is properly used to maintain IConvertible and IFormattable capabilities when generating refined types from raw types that implement these interfaces. This aligns with the PR's objective of supporting implicit conversions while preserving the original type's capabilities.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for usages of HasInterface method in the context of implicit conversions
rg -l "HasInterface.*IConvertible|IConvertible.*HasInterface" 

# Search for any usage of the new HasInterface method
rg "HasInterface\(" -A 3

Length of output: 2031


Script:

#!/bin/bash
# Get more context around the usage of HasInterface in the source generator
rg "HasInterface" Tuxedo.SourceGenerator/Generators/RefinementSourceGenerator.SingleRefinedTypeSource.cs -B 5 -A 10

Length of output: 1715

Tuxedo.SourceGenerator/Extensions/StringExtensions.cs (1)

46-49: LGTM!

The new RenderIfTrue extension method is well-designed, following the established patterns in the class and maintaining consistency with existing methods like RenderIfNotNull.

Tuxedo.SourceGenerator/Generators/RefinementSourceGenerator.RefinedTypeDetails.cs (1)

9-22: LGTM! Well-structured record with improved type safety.

The changes enhance the type safety and maintainability of the RefinedTypeDetails record:

  • Sealing prevents unintended inheritance
  • Adding ITypeSymbol fields provides stronger typing for code generation
  • Consolidating attribute details reduces fragmentation
Tuxedo.SourceGenerator/Generators/RefinementSourceGenerator.MultiRefinedTypeSource.cs (1)

40-40: LGTM! Good addition of formatting support.

Adding formatting members ensures consistent string representation of the refined type.

Tuxedo.SourceGenerator/Generators/RefinementSourceGenerator.SingleRefinedTypeSource.cs (3)

109-118: LGTM! Well-implemented conversion operator support.

The operator generation properly handles both implicit and explicit conversions based on the HasImplicitConversionFromRaw property, with appropriate documentation.


161-162: LGTM! Improved null handling in TryParse.

The changes improve null safety by:

  • Using default instead of default!
  • Properly handling failure messages through the attribute details

210-255: Verify interface casts in formatting members.

The implementation of formatting members looks good, but the direct casts to IConvertible and IFormattable could throw at runtime if the interface check is incorrect.

✅ Verification successful

Interface casts in formatting members are properly protected

The implementation is safe because HasInterface performs compiler-verified interface checks using ITypeSymbol.AllInterfaces before any casting occurs. The null-safe operators and exact interface name matching provide additional safety guarantees.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Verify that the interface checks are consistent with the casts
ast-grep --pattern 'interface IConvertible {
  $$$
  string ToString(IFormatProvider?) $$$
}'

ast-grep --pattern 'interface IFormattable {
  $$$
  string ToString(string?, IFormatProvider?) $$$
}'

Length of output: 200


Script:

#!/bin/bash
# Find HasInterface implementation
ast-grep --pattern 'HasInterface($_) {
  $$$
}'

# Find similar casting patterns
rg "HasInterface.*IConvertible|HasInterface.*IFormattable" -A 2

# Look for direct casts to these interfaces
rg "\(\(IConvertible\)|IFormattable\)\)" -A 2

# Find any extension methods related to interface checking
fd "Extensions?.cs" --exec grep -l "HasInterface"

Length of output: 1646


Script:

#!/bin/bash
# Check HasInterface implementation
cat "./Tuxedo.SourceGenerator/Extensions/SymbolExtensions.cs"

# Look for any test files related to interface checking
fd ".*Tests?.cs" --exec grep -l "HasInterface"

Length of output: 816

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 13

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cae2afb and fcf8530.

📒 Files selected for processing (13)
  • Tuxedo.SourceGenerator/Extensions/SymbolExtensions.cs (1 hunks)
  • Tuxedo.SourceGenerator/Generators/RefinementSourceGenerator.MultiRefinedTypeSource.cs (1 hunks)
  • Tuxedo.Tests/BoolRefinementsTests.Case4#FalseBool.g.verified.cs (2 hunks)
  • Tuxedo.Tests/BoolRefinementsTests.Case5#TrueBool.g.verified.cs (2 hunks)
  • Tuxedo.Tests/ConfigureRefinementTypesExample.Case1#Case3.g.verified.cs (2 hunks)
  • Tuxedo.Tests/ConfigureRefinementTypesExample.Case2#Case4.g.verified.cs (1 hunks)
  • Tuxedo.Tests/CustomAccessModifierTests.Case2#WhiteSpaceChar.g.verified.cs (3 hunks)
  • Tuxedo.Tests/DateOnlyExample.Case3#DateOnlyString.g.verified.cs (5 hunks)
  • Tuxedo.Tests/Extensions/GeneratorDriverExtensions.cs (2 hunks)
  • Tuxedo.Tests/GuidStringTests.Case3#GuidString.g.verified.cs (5 hunks)
  • Tuxedo.Tests/OddNumberExample.Case6#OddInt.g.verified.cs (1 hunks)
  • Tuxedo.Tests/OddNumberExample.cs (1 hunks)
  • Tuxedo.Tests/PasswordStringExampleTests.Case2#PasswordString.g.verified.cs (2 hunks)
🧰 Additional context used
📓 Learnings (2)
Tuxedo.Tests/ConfigureRefinementTypesExample.Case1#Case3.g.verified.cs (1)
Learnt from: bmazzarol
PR: bmazzarol/Tuxedo#19
File: Tuxedo.Tests/ConfigureRefinementTypesExample.Case2#Case4.g.verified.cs:117-120
Timestamp: 2025-01-08T13:37:48.329Z
Learning: When implementing ToString() methods that need to handle null values, prefer using string.Empty as the default value instead of custom strings like "Undefined".
Tuxedo.Tests/ConfigureRefinementTypesExample.Case2#Case4.g.verified.cs (1)
Learnt from: bmazzarol
PR: bmazzarol/Tuxedo#19
File: Tuxedo.Tests/ConfigureRefinementTypesExample.Case2#Case4.g.verified.cs:117-120
Timestamp: 2025-01-08T13:37:48.329Z
Learning: When implementing ToString() methods that need to handle null values, prefer using string.Empty as the default value instead of custom strings like "Undefined".
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Build and analyze
🔇 Additional comments (16)
Tuxedo.Tests/GuidStringTests.Case3#GuidString.g.verified.cs (3)

12-12: Documentation improvements look good!

The updates to use fully qualified type names (System.Guid instead of Guid) in the documentation improve clarity and consistency.

Also applies to: 37-38, 42-45


134-148: Well-implemented ToString methods!

The new ToString implementations:

  • Handle null cases gracefully
  • Provide culture-aware formatting support
  • Maintain consistent behavior

99-99: Good safety improvement in TryParse!

Removing the null-forgiving operator (!) in favor of default is a better approach as it:

  • Properly represents the method's contract
  • Maintains type safety without forcing non-null assertion
  • Aligns with the method's failure path behavior
Tuxedo.SourceGenerator/Generators/RefinementSourceGenerator.MultiRefinedTypeSource.cs (1)

40-40: LGTM! Good addition of formatting support.

Adding ToString methods through RenderFormattingMembers improves the usability of the generated refined types by providing proper string representations.

Tuxedo.Tests/Extensions/GeneratorDriverExtensions.cs (1)

14-19: LGTM! Verify C# 12 compatibility.

The added metadata references are essential for the compilation to work correctly. However, the collection expression syntax [] on line 14 requires C# 12.

Let's verify the project's language version:

✅ Verification successful

Collection expression syntax is compatible with project settings

The project uses <LangVersion>latest</LangVersion>, which supports C# 12 features including collection expressions.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check C# language version in project files
fd -e csproj | xargs cat | grep -A 1 "<LangVersion"

Length of output: 116

Tuxedo.Tests/BoolRefinementsTests.Case5#TrueBool.g.verified.cs (2)

81-81: LGTM! Safer initialization in TryParse

The change from default! to default is a good improvement that avoids unnecessary null-forgiving operators while maintaining type safety.


115-130: LGTM! Well-implemented ToString methods

The ToString implementations follow best practices:

  • Properly handles null values using string.Empty
  • Provides culture-aware formatting support via IFormatProvider
Tuxedo.Tests/ConfigureRefinementTypesExample.Case1#Case3.g.verified.cs (1)

81-81: LGTM! Consistent implementation

The changes follow the same safe patterns as in TrueBool:

  • Safe default initialization in TryParse
  • Proper ToString implementations with null handling and culture support

Also applies to: 115-130

Tuxedo.Tests/DateOnlyExample.Case3#DateOnlyString.g.verified.cs (1)

12-12: LGTM! Improved type clarity

Good improvement in fully qualifying System.DateOnly to prevent any ambiguity with custom DateOnly types.

Also applies to: 34-34, 37-37, 39-39, 42-42, 45-45, 46-46, 51-51, 80-80, 99-99, 154-155

Tuxedo.Tests/BoolRefinementsTests.Case4#FalseBool.g.verified.cs (1)

81-81: LGTM! Improved null safety

The change from default! to default is a better approach as it properly handles the invalid state without suppressing nullable warnings.

Tuxedo.Tests/OddNumberExample.Case6#OddInt.g.verified.cs (4)

14-22: LGTM! Well-structured type declaration

The struct is correctly marked as readonly and partial, implementing appropriate interfaces. The nullable backing field with validation in the Value property is a good practice.


24-48: Consider supporting implicit conversion from raw type

According to the PR objective "support for implicit conversion from raw to refined", consider changing the explicit operator to implicit for converting from int to OddInt.

However, this change needs careful consideration:

  1. Implicit conversion could silently fail at runtime
  2. Explicit conversion makes the validation more visible

Would you like to discuss the tradeoffs of implicit vs explicit conversion in this context?


50-84: LGTM! Well-implemented parsing methods

The Parse and TryParse methods follow .NET conventions and provide good error handling.


86-114: LGTM! Complete equality implementation

Thorough implementation of equality members following all best practices for value types.

Tuxedo.Tests/CustomAccessModifierTests.Case2#WhiteSpaceChar.g.verified.cs (1)

15-15: Implementation of IFormattable interface

Adding the IFormattable interface to WhiteSpaceChar enhances its formatting capabilities and allows for custom string representations. Good addition.

Tuxedo.Tests/ConfigureRefinementTypesExample.Case2#Case4.g.verified.cs (1)

121-122: 🧹 Nitpick (assertive)

Simplify ToString() methods by removing unnecessary null-coalescing operator

In both ToString() methods, the null-coalescing operator ?? string.Empty is unnecessary because Value.ToString() for a non-nullable bool cannot return null. You can simplify the code by removing the ?? string.Empty.

Apply this diff to simplify the ToString() methods:

 public override string ToString()
 {
-    return Value.ToString() ?? string.Empty;
+    return Value.ToString();
 }

 public string ToString(IFormatProvider? provider)
 {
-    return ((IConvertible)Value).ToString(provider) ?? string.Empty;
+    return ((IConvertible)Value).ToString(provider);
 }

Also applies to: 129-130

⛔ Skipped due to learnings
Learnt from: bmazzarol
PR: bmazzarol/Tuxedo#19
File: Tuxedo.Tests/ConfigureRefinementTypesExample.Case2#Case4.g.verified.cs:117-120
Timestamp: 2025-01-08T13:37:48.329Z
Learning: When implementing ToString() methods that need to handle null values, prefer using string.Empty as the default value instead of custom strings like "Undefined".

@bmazzarol bmazzarol merged commit 9d44c1f into main Jan 8, 2025
9 checks passed
@bmazzarol bmazzarol deleted the feat/implicit-option branch January 8, 2025 16:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant