Skip to content

Commit 6be5b5e

Browse files
committed
updated docs and comments
1 parent c4adbf0 commit 6be5b5e

7 files changed

Lines changed: 104 additions & 43 deletions

File tree

.claude/CLAUDE.md

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,19 @@ All types must be declared as `partial`. Source generators produce: factory meth
8484

8585
- Base type abstract, derived types sealed. Conversion operators + Switch/Map.
8686

87+
### Setting Interdependencies
88+
89+
Several attribute settings cascade to other settings. The AI assistant must account for these when discussing or generating configuration:
90+
91+
- **`SkipFactoryMethods = true`** (Value Objects): Forces `SkipIParsable`, `SkipISpanParsable` to `true`; arithmetic operators to `None`; suppresses `TypeConverter`, `IObjectFactory<T>`, conversion operator from key type, and serialization converters (unless `[ObjectFactory<T>]` with `UseForSerialization` is present)
92+
- **`SkipIParsable = true`**: Forces `SkipISpanParsable = true` (`ISpanParsable<T>` inherits from `IParsable<T>`)
93+
- **`SkipEqualityComparison = true`**: Forces `ComparisonOperators` and `EqualityComparisonOperators` to `None`
94+
- **`EqualityComparisonOperators = None`**: Forces `ComparisonOperators` to `None` in generated code (enforced by the generator settings, not the attribute getter — circular dependency prevents getter enforcement)
95+
- **`ComparisonOperators` > `EqualityComparisonOperators`**: `EqualityComparisonOperators` is coerced upward to match
96+
- **`EmptyStringInFactoryMethodsYieldsNull = true`**: Forces `NullInFactoryMethodsYieldsNull = true`
97+
- **`TXIsStateless = true`** (Unions): Automatically sets `TXIsNullableReferenceType = true` for reference types
98+
- **`ConstructorAccessModifier`** (Unions): Also controls accessibility of implicit conversion operators
99+
87100
### What Gets Generated
88101

89102
All types: equality members (`Equals`, `GetHashCode`, `==`, `!=`), `Switch`/`Map` pattern matching.
@@ -125,7 +138,7 @@ SyntaxProvider (filter by attribute via ForAttributeWithMetadataName)
125138

126139
### Analyzers
127140

128-
1. `ThinktectureRuntimeExtensionsAnalyzer` -- 54 diagnostic rules (`TTRESG` prefix) for correct usage
141+
1. `ThinktectureRuntimeExtensionsAnalyzer` -- 55 diagnostic rules (`TTRESG` prefix) for correct usage
129142
2. `ThinktectureRuntimeExtensionsInternalUsageAnalyzer` -- Prevents external use of internal APIs
130143

131144
### Runtime Metadata

.claude/reference/ATTRIBUTES.md

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ Base class for `ValueObjectAttribute<TKey>` and `ComplexValueObjectAttribute`.
1818

1919
| Property | Type | Default | Description |
2020
|-------------------------------|---------------------------|---------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
21-
| `SkipFactoryMethods` | `bool` | `false` | Do not generate `Create`, `TryCreate`, `Validate` methods |
21+
| `SkipFactoryMethods` | `bool` | `false` | Do not generate `Create`, `TryCreate`, `Validate` methods. Also suppresses: `TypeConverter` attribute, `IObjectFactory<T>` implementation, conversion operator from key type, `IParsable<T>` and `ISpanParsable<T>` implementations, all arithmetic operators, and serialization converters (JSON, Newtonsoft, MessagePack) — unless an `[ObjectFactory<T>(UseForSerialization = ...)]` is present |
2222
| `ConstructorAccessModifier` | `AccessModifier` | `Private` | Access modifier for generated constructor |
2323
| `CreateFactoryMethodName` | `string` | `"Create"` | Name for the Create factory method (whitespace resets to default) |
2424
| `TryCreateFactoryMethodName` | `string` | `"TryCreate"` | Name for the TryCreate factory method (whitespace resets to default) |
@@ -38,7 +38,7 @@ Base class for `AdHocUnionAttribute` and generic `UnionAttribute<T1, T2, ...>`.
3838
|-------------------------------|----------------------------------|---------------------|---------------------------------------------------------------------------------------|
3939
| `DefaultStringComparison` | `StringComparison` | `OrdinalIgnoreCase` | Default string comparison for union operations |
4040
| `SkipToString` | `bool` | `false` | Skip `ToString()` generation |
41-
| `ConstructorAccessModifier` | `UnionConstructorAccessModifier` | `Public` | Access modifier for generated constructor |
41+
| `ConstructorAccessModifier` | `UnionConstructorAccessModifier` | `Public` | Access modifier for generated constructor; also affects accessibility of implicit conversion operators |
4242
| `ConversionFromValue` | `ConversionOperatorsGeneration` | `Implicit` | Generate implicit conversion operators from member types to union |
4343
| `ConversionToValue` | `ConversionOperatorsGeneration` | `Explicit` | Generate explicit conversion operators from union to member types |
4444
| `SwitchMethods` | `SwitchMapMethodsGeneration` | (varies) | Configure Switch method generation |
@@ -65,7 +65,7 @@ SmartEnumAttribute()
6565

6666
| Property | Type | Default | Description |
6767
|-------------------------------|------------------------------|-----------|-----------------------------------------------|
68-
| `EqualityComparisonOperators` | `OperatorsGeneration` | `Default` | Generation of equality operators (`==`, `!=`) |
68+
| `EqualityComparisonOperators` | `OperatorsGeneration` | `Default` | Generation of equality operators (`==`, `!=`). Note: `DefaultWithKeyTypeOverloads` produces the same code as `Default` for keyless enums (no key member to overload with) |
6969
| `SwitchMethods` | `SwitchMapMethodsGeneration` | `Default` | Switch method generation configuration |
7070
| `MapMethods` | `SwitchMapMethodsGeneration` | `Default` | Map method generation configuration |
7171
| `SwitchMapStateParameterName` | `string?` | `"state"` | Name of state parameter in Switch/Map methods |
@@ -91,10 +91,10 @@ SmartEnumAttribute()
9191
| `KeyMemberKind` | `MemberKind` | `Property` | Whether key member is property or field |
9292
| `KeyMemberName` | `string` | `"_key"` (private field) or `"Key"` (otherwise) | Name of the key member |
9393
| `SkipIComparable` | `bool` | `false` | Skip `IComparable<T>` implementation (when key not comparable) |
94-
| `SkipIParsable` | `bool` | `false` | Skip `IParsable<T>` implementation (independent from SkipISpanParsable) |
95-
| `SkipISpanParsable` | `bool` | `false` | Skip `ISpanParsable<T>` implementation (independent from SkipIParsable; NET9+) |
96-
| `ComparisonOperators` | `OperatorsGeneration` | `Default` | Comparison operators (`<`, `<=`, `>`, `>=`) - depends on EqualityComparisonOperators |
97-
| `EqualityComparisonOperators` | `OperatorsGeneration` | `Default` | Equality operators (`==`, `!=`) - coerced to at least ComparisonOperators |
94+
| `SkipIParsable` | `bool` | `false` | Skip `IParsable<T>` implementation; setting to `true` also forces `SkipISpanParsable` to `true` |
95+
| `SkipISpanParsable` | `bool` | `false` | Skip `ISpanParsable<T>` implementation; forced to `true` when `SkipIParsable` is `true` (`ISpanParsable<T>` inherits from `IParsable<T>`); NET9+ |
96+
| `ComparisonOperators` | `OperatorsGeneration` | `Default` | Comparison operators (`<`, `<=`, `>`, `>=`) - depends on EqualityComparisonOperators; forced to `None` when `EqualityComparisonOperators` is `None` |
97+
| `EqualityComparisonOperators` | `OperatorsGeneration` | `Default` | Equality operators (`==`, `!=`) - coerced upward to at least `ComparisonOperators` |
9898
| `SkipIFormattable` | `bool` | `false` | Skip `IFormattable` implementation (when key not IFormattable) |
9999
| `SkipToString` | `bool` | `false` | Skip `ToString()` generation |
100100
| `SwitchMethods` | `SwitchMapMethodsGeneration` | `Default` | Switch method generation configuration |
@@ -105,7 +105,7 @@ SmartEnumAttribute()
105105
| `DisableSpanBasedJsonConversion` | `bool` | `false` | Disables ReadOnlySpan-based zero-allocation JSON conversion, falling back to string-based conversion (string keys only; NET9+) |
106106
| `SwitchMapStateParameterName` | `string?` | `"state"` | Name of state parameter in Switch/Map methods |
107107

108-
**Note**: `ISpanParsable<T>` inherits from `IParsable<T>`, so setting `SkipISpanParsable = false` will automatically set `SkipIParsable = false` if needed.
108+
**Note**: `SkipIParsable = true` automatically forces `SkipISpanParsable = true` because `ISpanParsable<T>` inherits from `IParsable<T>`.
109109

110110
## Value Object Attributes
111111

@@ -135,20 +135,20 @@ ValueObjectAttribute()
135135
| `NullInFactoryMethodsYieldsNull` | `bool` | `false` | `Create`/`TryCreate`/`Validate` return null on null input (class + factories only) |
136136
| `EmptyStringInFactoryMethodsYieldsNull` | `bool` | `false` | String-key empty/whitespace yields null (class + factories only; implies NullInFactoryMethodsYieldsNull = true) |
137137
| `SkipIComparable` | `bool` | `false` | Skip `IComparable<T>` implementation (if key not comparable and no custom comparer) |
138-
| `SkipIParsable` | `bool` | `false` | Skip `IParsable<T>` implementation (if factories skipped or key not string/IParsable; independent from SkipISpanParsable) |
139-
| `SkipISpanParsable` | `bool` | `false` | Skip `ISpanParsable<T>` implementation (if factories skipped or key not string/ISpanParsable; independent from SkipIParsable; NET9+) |
138+
| `SkipIParsable` | `bool` | `false` | Skip `IParsable<T>` implementation (if factories skipped or key not string/IParsable); setting to `true` also forces `SkipISpanParsable` to `true` |
139+
| `SkipISpanParsable` | `bool` | `false` | Skip `ISpanParsable<T>` implementation; forced to `true` when `SkipIParsable` or `SkipFactoryMethods` is `true`; NET9+ |
140140
| `AdditionOperators` | `OperatorsGeneration` | `None` | Generate addition operators (`+`) - requires key supports these ops |
141141
| `SubtractionOperators` | `OperatorsGeneration` | `None` | Generate subtraction operators (`-`) - requires key supports these ops |
142142
| `MultiplyOperators` | `OperatorsGeneration` | `None` | Generate multiplication operators (`*`) - requires key supports these ops |
143143
| `DivisionOperators` | `OperatorsGeneration` | `None` | Generate division operators (`/`) - requires key supports these ops |
144-
| `ComparisonOperators` | `OperatorsGeneration` | `Default` | Comparison operators (`<`, `<=`, `>`, `>=`) - depends on EqualityComparisonOperators |
145-
| `EqualityComparisonOperators` | `OperatorsGeneration` | `Default` | Equality operators (`==`, `!=`) - coerced to at least ComparisonOperators |
144+
| `ComparisonOperators` | `OperatorsGeneration` | `Default` | Comparison operators (`<`, `<=`, `>`, `>=`) - depends on EqualityComparisonOperators; forced to `None` when `EqualityComparisonOperators` is `None` |
145+
| `EqualityComparisonOperators` | `OperatorsGeneration` | `Default` | Equality operators (`==`, `!=`) - coerced upward to at least `ComparisonOperators` |
146146
| `SkipIFormattable` | `bool` | `false` | Skip `IFormattable` implementation (if key not IFormattable) |
147147
| `ConversionToKeyMemberType` | `ConversionOperatorsGeneration` | `Implicit` | Generate implicit conversion operator from value object to key type |
148148
| `UnsafeConversionToKeyMemberType` | `ConversionOperatorsGeneration` | `Explicit` | Generate explicit conversion operator from value object to key type (may throw if validation fails) |
149149
| `ConversionFromKeyMemberType` | `ConversionOperatorsGeneration` | `Explicit` | Generate explicit conversion operator from key type to value object |
150150

151-
**Note**: `ISpanParsable<T>` inherits from `IParsable<T>`, so setting `SkipISpanParsable = false` will automatically set `SkipIParsable = false` if needed.
151+
**Note**: `SkipIParsable = true` automatically forces `SkipISpanParsable = true` because `ISpanParsable<T>` inherits from `IParsable<T>`.
152152

153153
**Inherits all properties from `ValueObjectAttributeBase`** (see above).
154154

docs

Submodule docs updated from 3664747 to d0d6294

src/Thinktecture.Runtime.Extensions/SmartEnumAttribute.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,10 @@ public string KeyMemberName
8080
/// This setting has no effect if:
8181
/// - the key is neither a <see cref="string"/> nor an <see cref="IParsable{T}"/> itself.
8282
/// </summary>
83+
/// <remarks>
84+
/// Setting this to <c>true</c> also forces <see cref="SkipISpanParsable"/> to <c>true</c>,
85+
/// because <see cref="ISpanParsable{T}"/> inherits from <see cref="IParsable{T}"/>.
86+
/// </remarks>
8387
public bool SkipIParsable { get; set; }
8488

8589
/// <summary>
@@ -112,6 +116,10 @@ public bool SkipISpanParsable
112116
/// This setting has no effect:
113117
/// - if key-member is not an <see cref="IComparisonOperators{TSelf,TOther,TResult}"/> itself and has no corresponding operators (<c>op_GreaterThan</c>, <c>op_GreaterThanOrEqual</c>, <c>op_LessThan</c>, <c>op_LessThanOrEqual</c>).
114118
/// </summary>
119+
/// <remarks>
120+
/// In generated code, this is also forced to <see cref="OperatorsGeneration.None"/> when <see cref="EqualityComparisonOperators"/> is <see cref="OperatorsGeneration.None"/>,
121+
/// because comparison operators require equality operators.
122+
/// </remarks>
115123
public OperatorsGeneration ComparisonOperators { get; set; }
116124

117125
/// <summary>
@@ -120,6 +128,10 @@ public bool SkipISpanParsable
120128
/// This setting has no effect:
121129
/// - if key-member is not an <see cref="IEqualityOperators{TSelf,TOther,TResult}"/> itself and has no corresponding operators (<c>op_Equality</c>, <c>op_Inequality</c>).
122130
/// </summary>
131+
/// <remarks>
132+
/// This value is coerced upward to match <see cref="ComparisonOperators"/> when <see cref="ComparisonOperators"/> is greater,
133+
/// because comparison operators require equality operators.
134+
/// </remarks>
123135
public OperatorsGeneration EqualityComparisonOperators
124136
{
125137
get => ComparisonOperators > field ? ComparisonOperators : field;

src/Thinktecture.Runtime.Extensions/UnionAttributeBase.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@ public abstract class UnionAttributeBase : Attribute
2121
/// Default is <see cref="UnionConstructorAccessModifier.Public"/>.
2222
/// </summary>
2323
/// <remarks>
24-
/// Access modifier of the constructors will have effect on the access modifier of implicit casts.
24+
/// The access modifier also applies to the generated implicit conversion operators (from member types to union type).
25+
/// For example, setting this to <see cref="UnionConstructorAccessModifier.Private"/> makes both the constructors
26+
/// and the implicit conversion operators private, requiring custom factory methods for union creation.
2527
/// </remarks>
2628
public UnionConstructorAccessModifier ConstructorAccessModifier { get; set; } = UnionConstructorAccessModifier.Public;
2729

0 commit comments

Comments
 (0)