-
Notifications
You must be signed in to change notification settings - Fork 5
Analyzer Diagnostics
The Thinktecture.Runtime.Extensions library includes Roslyn analyzers that validate correct usage of Smart Enums, Value Objects, and Discriminated Unions at compile time. These analyzers catch common mistakes early, before they become runtime errors. There are 59 diagnostic rules across the categories below.
The library ships two analyzers:
- ThinktectureRuntimeExtensionsAnalyzer -- Validates correct declaration and usage of all type categories.
- ThinktectureRuntimeExtensionsInternalUsageAnalyzer -- Prevents external use of internal infrastructure APIs.
These rules apply across multiple type categories (Smart Enums, Value Objects, Unions).
| ID | Severity | Title | Guidance |
|---|---|---|---|
| TTRESG001 | Error | Field must be read-only | Add the readonly modifier to the field. |
| TTRESG003 | Error | Property must be read-only | Remove the setter or make the property get-only. |
| TTRESG004 | Error | The type must be a class or a struct | Change the type declaration to a class or struct. |
| TTRESG006 | Error | Type must be partial | Add the partial modifier to the type declaration. |
| TTRESG009 | Error | The constructors must be private | Mark all constructors as private. |
| TTRESG017 | Error | The key member must not be nullable | Change the key member type to a non-nullable type. |
| TTRESG034 | Error | Field of the base class must be read-only | Add the readonly modifier to the base class field. |
| TTRESG035 | Error | Property of the base class must be read-only | Remove the setter from the base class property. |
| TTRESG041 | Error | The type of the comparer doesn't match the type of the member | Ensure the comparer generic type argument matches the member type. |
| TTRESG042 | Error | Property 'init' accessor must be private | Mark the init accessor as private. |
| TTRESG043 | Error | Primary constructor is not allowed | Remove the primary constructor and use a regular private constructor instead. |
| TTRESG046 | Error | The arguments of 'Switch' and 'Map' must be named | Use named arguments when calling Switch or Map methods. See also Switch/Map Usage. |
| TTRESG047 | Error | Variable must be initialized with non-default value | Initialize the variable using a factory method (e.g., Create) instead of default. |
| TTRESG063 | Error | Type must not have more than one ValueObject/SmartEnum/Union-attribute | Remove duplicate attributes; only one category attribute is allowed per type. |
See Smart Enums and Smart Enums Customization for detailed documentation.
| ID | Severity | Title | Guidance |
|---|---|---|---|
| TTRESG002 | Error | Smart Enum item must be public | Mark the static readonly field as public. |
| TTRESG012 | Error | Provided key member name is not allowed | Choose a different key member name via KeyMemberName. |
| TTRESG014 | Error | Inner Smart Enum on first level must be private | Mark the first-level derived inner Smart Enum as private. |
| TTRESG015 | Error | Inner Smart Enum on non-first level must be public | Mark deeper-level derived inner Smart Enums as public. |
| TTRESG036 | Error | The key type must not be nullable | Use a non-nullable type for the SmartEnumAttribute<T> type argument. |
| TTRESG037 | Error | Smart Enum without derived types must be sealed | Add the sealed modifier to the Smart Enum, or add derived inner types. |
| TTRESG060 | Error | Smart Enums with ObjectFactoryAttribute must not have HasCorrespondingConstructor = true | Set HasCorrespondingConstructor = false or remove the property. Smart Enums do not use constructors for item creation. |
| TTRESG064 | Error | Type must not have more than one SmartEnumAttribute | Remove duplicate SmartEnumAttribute declarations. |
| TTRESG100 | Warning | The Smart Enum has no items | Add at least one public static readonly field of the Smart Enum type. |
| TTRESG101 | Warning | Static properties are not considered Smart Enum items, use a field instead | Change the static property to a static readonly field. |
See Value Objects and Value Objects Customization for detailed documentation.
| ID | Severity | Title | Guidance |
|---|---|---|---|
| TTRESG044 | Error | Custom implementation of the key member not found | Implement a field or property matching the expected key member name. Use KeyMemberName to change the name. |
| TTRESG045 | Error | Key member type mismatch | Change the key member type to match the type specified in the attribute. |
| TTRESG048 | Warning | String-based Value Object needs equality comparer | Add [KeyMemberEqualityComparer<ComparerAccessors.StringOrdinalIgnoreCase, string>] or another appropriate comparer. |
| TTRESG049 | Warning | Complex Value Object with string members needs equality comparer | Set DefaultStringComparison on the attribute, e.g., [ComplexValueObject(DefaultStringComparison = StringComparison.OrdinalIgnoreCase)]. |
| TTRESG057 | Error | 'AllowDefaultStructs' must be 'false' if Value Object is a struct but key type is a reference type | Set AllowDefaultStructs = false because default would produce a null key. |
| TTRESG058 | Error | 'AllowDefaultStructs' must be 'false' if some members disallow default values | Set AllowDefaultStructs = false because some members implement IDisallowDefaultValue. |
| TTRESG065 | Error | Type must not have more than one ValueObjectAttribute/ComplexValueObjectAttribute | Remove duplicate Value Object attributes. |
| TTRESG102 | Warning | The type has a comparer defined but no equality comparer | Add an equality comparer alongside the comparer for consistent behavior. |
| TTRESG103 | Warning | The type has an equality comparer defined but no comparer | Add a comparer alongside the equality comparer for consistent behavior. |
| TTRESG104 | Warning | The member must be marked as 'required' to ensure proper initialization | Add the required modifier to the member to prevent uninitialized usage. Does not apply to interface properties, which cannot be required. |
| TTRESG105 | Warning | Comparison and equality operators settings mismatch | Set ComparisonOperators and EqualityComparisonOperators to the same value. |
See Discriminated Unions and Discriminated Unions Customization for detailed documentation.
| ID | Severity | Title | Guidance |
|---|---|---|---|
| TTRESG053 | Error | Derived type of a union must not be generic | Remove generic type parameters from the derived union type. |
| TTRESG054 | Error | Discriminated union must be sealed or have private constructors only | Either seal the union type or make all constructors private. |
| TTRESG055 | Error | Discriminated union implemented using a record must be sealed | Seal the record-based union. Use a class instead if you need nested unions. |
| TTRESG056 | Error | Non-abstract derived union is less accessible than base union | Increase the accessibility of the derived union to match or exceed the base union. |
| TTRESG066 | Error | Type must not have more than one UnionAttribute/AdHocUnionAttribute | Remove duplicate union attributes. |
| TTRESG067 | Error | Ad hoc union must define at least two member types | Add at least two type arguments to the union attribute. |
| TTRESG071 | Error | TypeParamRef index exceeds the number of type parameters | The TypeParamRef index is higher than the union's type parameter count. Use a TypeParamRef that matches an existing type parameter. |
| TTRESG072 | Error | TypeParamRef cannot be used on non-generic ad-hoc union | The union must declare its own type parameters for TypeParamRef placeholders to reference. Either make the union generic or replace the TypeParamRef with a concrete type. |
| TTRESG073 | Error | Ad-hoc unions do not support allows ref struct type parameters |
Remove the allows ref struct anti-constraint from the type parameter. Ref structs cannot be boxed, which conflicts with equality, the Value property, and Switch/Map delegate patterns. |
| TTRESG074 | Error | Type parameter used via TypeParamRef must have notnull constraint |
When using TypeParamRef to reference a generic type parameter as the key type of a Smart Enum or keyed Value Object, the type parameter must have a notnull constraint (or struct/class, which imply non-null). Add where T : notnull to the type declaration. |
| TTRESG106 | Warning | Inner type should derive from union type | Make the inner type derive from the enclosing union type. |
| TTRESG107 | Warning | Generic ad-hoc union does not reference any type parameter via TypeParamRef | The union is generic but none of its member types use TypeParamRef. Reference at least one type parameter via TypeParamRef1–TypeParamRef5. |
See Object Factories for detailed documentation.
| ID | Severity | Title | Guidance |
|---|---|---|---|
| TTRESG050 | Error | Method with UseDelegateFromConstructorAttribute must be partial | Add the partial modifier to the method. |
| TTRESG051 | Error | Method with UseDelegateFromConstructorAttribute must not have generics | Remove generic type parameters from the method. Use the inheritance approach instead. |
| TTRESG059 | Error | Type with ObjectFactoryAttribute and HasCorrespondingConstructor = true must have a matching constructor | Add a constructor with a single parameter of the object factory's type argument. |
| TTRESG061 | Error | Type with ObjectFactoryAttribute must implement static Validate method | Add a static Validate method with the required signature (see error message for details). |
| TTRESG062 | Error | Type with ObjectFactoryAttribute must implement ToValue method | Add an instance ToValue() method when UseForSerialization is not None or UseWithEntityFramework is true. |
| TTRESG068 | Error | Multiple ObjectFactoryAttribute instances cannot have UseWithEntityFramework = true | Set UseWithEntityFramework = true on only one ObjectFactoryAttribute. |
| TTRESG069 | Error | Multiple ObjectFactoryAttribute instances cannot have UseForModelBinding = true | Set UseForModelBinding = true on only one ObjectFactoryAttribute. |
| TTRESG070 | Error | Multiple ObjectFactoryAttribute instances cannot specify overlapping serialization frameworks | Ensure each serialization framework is used by only one ObjectFactoryAttribute. |
These diagnostics indicate problems within the source generator itself and are not typically caused by user code.
| ID | Severity | Title | Guidance |
|---|---|---|---|
| TTRESG097 | Error | Error during analysis of referenced modules | Check that all referenced Thinktecture integration packages are compatible with the installed version of the core library. |
| TTRESG098 | Warning | Error during code analysis | Report the issue if it persists. The error message contains details about the affected type. |
| TTRESG099 | Error | Error during code generation | Report the issue if it persists. The error message contains details about the affected type. |
| ID | Severity | Title | Guidance |
|---|---|---|---|
| TTRESG1000 | Warning | Internal Thinktecture.Runtime.Extensions API usage | Do not use types or members from the Thinktecture.Internal namespace. These are internal infrastructure APIs that may change or be removed without notice. |
See also TTRESG046 in General / Shared for the requirement that Switch/Map arguments must be named.
| ID | Severity | Title | Guidance |
|---|---|---|---|
| TTRESG1001 | Info | Consider using a static lambda | Lambda passed to Switch/Map should be static. Use a static lambda to avoid unnecessary allocations, or use the state overload to pass captured variables explicitly. |
If you need to suppress a specific diagnostic, you can use one of the following approaches:
Using #pragma directives:
#pragma warning disable TTRESG048 // String-based Value Object needs equality comparer
[ValueObject<string>]
public partial class MyValueObject
{
// ...
}
#pragma warning restore TTRESG048Using [SuppressMessage] attribute:
using System.Diagnostics.CodeAnalysis;
[SuppressMessage("ThinktectureRuntimeExtensionsAnalyzer", "TTRESG048")]
[ValueObject<string>]
public partial class MyValueObject
{
// ...
}Note: TTRESG1000 uses a different category:
"ThinktectureRuntimeExtensionsInternalUsageAnalyzer".
In .editorconfig:
[*.cs]
dotnet_diagnostic.TTRESG048.severity = noneNote: Suppressing Error-level diagnostics is generally not recommended, as these indicate conditions that will cause incorrect code generation or runtime failures.
- Home
- Smart Enums
- Value Objects
- Discriminated Unions
- Object Factories
- Analyzer Diagnostics
- Source Generator Configuration
- Convenience methods and classes
- Migrations
- Version 7
- Version 8