Skip to content

Analyzer Diagnostics

Pawel Gerr edited this page Apr 6, 2026 · 6 revisions

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.

Diagnostic Rules

General / Shared

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.

Smart Enum

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.

Value Object

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.

Discriminated Union

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 TypeParamRef1TypeParamRef5.

Object Factory

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.

Internal Errors

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.

Internal API Usage

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.

Switch/Map Usage

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.

Suppressing Diagnostics

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 TTRESG048

Using [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 = none

Note: Suppressing Error-level diagnostics is generally not recommended, as these indicate conditions that will cause incorrect code generation or runtime failures.

Clone this wiki locally