Files
SpacetimeDB/crates/bindings-csharp/Codegen/Diag.cs
clockwork-labs-bot dd2c95f113 Move CaseConversionPolicy to public SpacetimeDB namespace (#4382)
Move `CaseConversionPolicy` from `SpacetimeDB.Internal` to the public
`SpacetimeDB` namespace so module authors can write:

```csharp
[SpacetimeDB.Settings]
public const CaseConversionPolicy CASE_CONVERSION_POLICY = CaseConversionPolicy.SnakeCase;
```

instead of the verbose:

```csharp
public const SpacetimeDB.Internal.CaseConversionPolicy CASE_CONVERSION_POLICY = SpacetimeDB.Internal.CaseConversionPolicy.SnakeCase;
```

### Changes
- Move enum definition from `SpacetimeDB.Internal` to `SpacetimeDB`
namespace in autogen
- Fully qualify all `Internal` references to
`SpacetimeDB.CaseConversionPolicy`
- Codegen source generator accepts both
`SpacetimeDB.CaseConversionPolicy` and
`SpacetimeDB.Internal.CaseConversionPolicy` for backward compatibility
- Updated test fixture and verified snapshots
- All 4 codegen tests pass

---------

Co-authored-by: clockwork-labs-bot <clockwork-labs-bot@users.noreply.github.com>
2026-02-20 22:21:46 +00:00

261 lines
9.7 KiB
C#

namespace SpacetimeDB.Codegen;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
internal static class ErrorDescriptor
{
private static readonly ErrorDescriptorGroup group = new("STDB", "SpacetimeDB");
public static readonly ErrorDescriptor<MethodDeclarationSyntax> ReducerReturnType =
new(
group,
"[SpacetimeDB.Reducer] methods must return void",
method =>
$"Reducer method {method.Identifier} returns {method.ReturnType} instead of void.",
method => method.ReturnType
);
public static readonly ErrorDescriptor<IFieldSymbol> AutoIncNotInteger =
new(
group,
"AutoInc fields must be of integer type",
field =>
$"Field {field.Name} is marked as AutoInc but it has a non-integer type {field.Type}.",
field => field
);
public static readonly ErrorDescriptor<IFieldSymbol> UniqueNotEquatable =
new(
group,
"Unique fields must be equatable",
field =>
$"Field {field.Name} is marked as Unique but it has a type {field.Type} which is not an equatable primitive.",
field => field
);
public static readonly ErrorDescriptor<AttributeData> EmptyIndexColumns =
new(
group,
"Index attribute must specify Columns",
_ => $"Index attribute doesn't specify columns.",
attr => attr
);
public static readonly ErrorDescriptor<TypeDeclarationSyntax> InvalidTableVisibility =
new(
group,
"Table row visibility must be public or internal",
table => $"Table {table.Identifier} and its parent types must be public or internal.",
table => table.Identifier
);
public static readonly ErrorDescriptor<TypeDeclarationSyntax> TableTaggedEnum =
new(
group,
"Tables cannot be tagged enums",
table => $"Table {table.Identifier} is a tagged enum, which is not allowed.",
table => table.BaseList!
);
public static readonly ErrorDescriptor<(
string kind,
string exportName,
IEnumerable<string> fullNames
)> DuplicateExport =
new(
group,
"Duplicate exports",
ctx =>
$"{ctx.kind} with the same export name {ctx.exportName} is registered in multiple places: {string.Join(", ", ctx.fullNames)}",
ctx => Location.None
);
public static readonly ErrorDescriptor<MethodDeclarationSyntax> ReducerContextParam =
new(
group,
"Reducers must have a first argument of type ReducerContext",
method =>
$"Reducer method {method.Identifier} does not have a ReducerContext parameter.",
method => method.ParameterList
);
public static readonly ErrorDescriptor<MethodDeclarationSyntax> ProcedureContextParam =
new(
group,
"Procedures must have a first argument of type ProcedureContext",
method =>
$"Procedure method {method.Identifier} does not have a ProcedureContext parameter.",
method => method.ParameterList
);
public static readonly ErrorDescriptor<(
MethodDeclarationSyntax method,
string prefix
)> ReducerReservedPrefix =
new(
group,
"Reducer method has a reserved name prefix",
ctx =>
$"Reducer method {ctx.method.Identifier} starts with '{ctx.prefix}', which is a reserved prefix.",
ctx => ctx.method.Identifier
);
public static readonly ErrorDescriptor<(
MethodDeclarationSyntax method,
string prefix
)> ProcedureReservedPrefix =
new(
group,
"Procedure method has a reserved name prefix",
ctx =>
$"Procedure method {ctx.method.Identifier} starts with '{ctx.prefix}', which is a reserved prefix.",
ctx => ctx.method.Identifier
);
public static readonly UnusedErrorDescriptor IncompatibleTableSchedule = new(group);
public static readonly ErrorDescriptor<(
ReducerKind kind,
IEnumerable<string> fullNames
)> DuplicateSpecialReducer =
new(
group,
"Multiple reducers of the same kind",
ctx =>
$"Several reducers are assigned to the same lifecycle kind {ctx.kind}: {string.Join(", ", ctx.fullNames)}",
ctx => Location.None
);
public static readonly ErrorDescriptor<(
AttributeData attr,
string message
)> InvalidScheduledDeclaration =
new(group, "Invalid scheduled table declaration", ctx => $"{ctx.message}", ctx => ctx.attr);
public static readonly ErrorDescriptor<AttributeData> UnexpectedIndexColumns =
new(
group,
"Index attribute on a field must not specify Columns",
_ =>
$"Index attribute on a field applies directly to that field, so it doesn't accept the Columns parameter.",
attr => attr
);
public static readonly ErrorDescriptor<(
AttributeData attr,
string columnName,
string typeName
)> UnknownColumn =
new(
group,
"Unknown column",
ctx => $"Could not find the specified column {ctx.columnName} in {ctx.typeName}.",
ctx => ctx.attr
);
public static readonly ErrorDescriptor<IFieldSymbol> ClientVisibilityNotFilter =
new(
group,
"ClientVisibilityFilters must be Filters",
field =>
$"Field {field.Name} is marked as ClientVisibilityFilter but it has type {field.Type} which is not SpacetimeDB.Filter",
field => field
);
public static readonly ErrorDescriptor<IFieldSymbol> ClientVisibilityNotPublicStaticReadonly =
new(
group,
"ClientVisibilityFilters must be public static readonly",
field =>
$"Field {field.Name} is marked as [ClientVisibilityFilter] but it is not public static readonly",
field => field
);
public static readonly ErrorDescriptor<IFieldSymbol> IncompatibleDefaultAttributesCombination =
new(
group,
"Invalid Combination: AutoInc, Unique or PrimaryKey cannot have a Default value",
field =>
$"Field {field.Name} contains a default value and has a AutoInc, Unique or PrimaryKey attributes, which is not allowed.",
field => field
);
public static readonly ErrorDescriptor<IFieldSymbol> InvalidDefaultValueType =
new(
group,
"Invalid Default Value Type",
field => $"Default value for field {field.Name} cannot be converted to provided type",
field => field
);
public static readonly ErrorDescriptor<IFieldSymbol> InvalidDefaultValueFormat =
new(
group,
"Invalid Default Value Format",
field => $"Default value for field {field.Name} has invalid format for provided type ",
field => field
);
public static readonly ErrorDescriptor<MethodDeclarationSyntax> ViewContextParam =
new(
group,
"Views must start with ViewContext or AnonymousViewContext",
method =>
$"View method {method.Identifier} must have a first parameter of type ViewContext or AnonymousViewContext.",
method => method.ParameterList
);
public static readonly ErrorDescriptor<MethodDeclarationSyntax> ViewMustHaveName =
new(
group,
"Views must have an explicit name.",
method => $"View '{method.Identifier}' must have an explicit name.",
method => method
);
public static readonly ErrorDescriptor<MethodDeclarationSyntax> ViewInvalidReturn =
new(
group,
"Views must return Vec<T> or Option<T>",
method => $"View '{method.Identifier}' must return Vec<T> or Option<T>.",
method => method
);
// TODO: Remove once Views support Private: Views must be Public currently
public static readonly ErrorDescriptor<MethodDeclarationSyntax> ViewMustBePublic =
new(
group,
"Views must be public",
method =>
$"View '{method.Identifier}' must have Public = true. Views are always public in SpacetimeDB.",
method => method
);
// TODO: Remove once Views support arguments: Views must have no arguments beyond the context.
public static readonly ErrorDescriptor<MethodDeclarationSyntax> ViewArgsUnsupported =
new(
group,
"Views must have no arguments beyond the context.",
method =>
$"View '{method.Identifier}' must have no arguments beyond the context. This is a temporary limitation.",
method => method
);
public static readonly ErrorDescriptor<IFieldSymbol> SettingsMustBeConstCaseConversionPolicy =
new(
group,
"[SpacetimeDB.Settings] field must be a const CaseConversionPolicy",
field =>
$"Settings field {field.Name} must be declared as 'public const SpacetimeDB.CaseConversionPolicy ...'.",
field => field
);
public static readonly ErrorDescriptor<IEnumerable<string>> DuplicateSettings =
new(
group,
"Multiple [SpacetimeDB.Settings] declarations",
fullNames =>
$"[SpacetimeDB.Settings] is declared multiple times: {string.Join(", ", fullNames)}",
_ => Location.None
);
}