Skip to content

Commit a546bc8

Browse files
authored
Rekhoff/csharp default field values (#3235)
# Description of Changes This is the implementation of issue #3191. This adds a Default attribute to C# module fields. **Note**: In C#, attribute arguments must be compile-time constants, which means you can't directly use non-constant expressions like new expressions, method calls, or dynamic values in attribute constructors. (Ref: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/attributes#2324-attribute-parameter-types) For this reason, these default values are limited to primitive types, enums, and strings. This includes (shown as `C# Type` (`BSATN type`): * `bool` (`Bool`) * `sbyte` (`I8`) * `byte` (`U8`) * `short` (`I16`) * `ushort` (`U16`) * `int` (`I32`) * `unit` (`U32`) * `long` (`I64`) * `ulong` (`U64`) * `float` (`F32`) * `double` (`F64`) * `enum` (`Enum`) * `string` (`String`) * `null` (`RefOption`) <- Nullable type Because of C# limitations, for nullable and complex data types, such as a struct, can take use `[Default(null)]` to populate values with null defaults. This allows things like structs to workaround the non-constant expressions in attribute constructors limitation by allowing these complex types to still be able to be added as new column tables. The `int` type can also be in the form of Hex or Binary literals, such as `[Default(0x2A)]` or `[Default(0b00101010)]` Both Decimal (like `[Default(3.14m)]`) and Char (like `[Default('A')]`) are unsupported types in BSATN and will still return `BSATN0001` errors. # API and ABI breaking changes Not API breaking. This change only adds the `[Default(value)]` attribute logic. Using the `[Default(value)]` attribute with older versions SpacetimeDB C# modules will result in an error. # Expected complexity level and risk 2 # Testing Local testing of this requires use of CLI changes in #3278 - [x] Regression test of functionality added.
1 parent 4a57de1 commit a546bc8

29 files changed

Lines changed: 2129 additions & 27 deletions

File tree

crates/bindings-csharp/Codegen.Tests/fixtures/diag/Lib.cs

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using System.ComponentModel;
12
using SpacetimeDB;
23

34
public enum LocalEnum { }
@@ -361,6 +362,80 @@ public static partial class InAnotherNamespace
361362
public partial struct TestDuplicateTableName { }
362363
}
363364

365+
[SpacetimeDB.Table]
366+
public partial struct TestDefaultFieldValues
367+
{
368+
[Unique]
369+
public int? UniqueField;
370+
371+
[Default("A default string set by attribute")]
372+
public string DefaultString = "";
373+
374+
[Default(true)]
375+
public bool DefaultBool = false;
376+
377+
[Default((sbyte)2)]
378+
public sbyte DefaultI8 = 1;
379+
380+
[Default((byte)2)]
381+
public byte DefaultU8 = 1;
382+
383+
[Default((short)2)]
384+
public short DefaultI16 = 1;
385+
386+
[Default((ushort)2)]
387+
public ushort DefaultU16 = 1;
388+
389+
[Default(2)]
390+
public int DefaultI32 = 1;
391+
392+
[Default(2U)]
393+
public uint DefaultU32 = 1U;
394+
395+
[Default(2L)]
396+
public long DefaultI64 = 1L;
397+
398+
[Default(2UL)]
399+
public ulong DefaultU64 = 1UL;
400+
401+
[Default(0x02)]
402+
public int DefaultHex = 1;
403+
404+
[Default(0b00000010)]
405+
public int DefaultBin = 1;
406+
407+
[Default(2.0f)]
408+
public float DefaultF32 = 1.0f;
409+
410+
[Default(2.0)]
411+
public double DefaultF64 = 1.0;
412+
413+
[Default(MyEnum.SetByAttribute)]
414+
public MyEnum DefaultEnum = MyEnum.SetByInitalization;
415+
416+
[Default(null!)]
417+
public MyStruct? DefaultNull = new MyStruct(1);
418+
}
419+
420+
[SpacetimeDB.Type]
421+
public enum MyEnum
422+
{
423+
Default,
424+
SetByInitalization,
425+
SetByAttribute,
426+
}
427+
428+
[SpacetimeDB.Type]
429+
public partial struct MyStruct
430+
{
431+
public int x;
432+
433+
public MyStruct(int x)
434+
{
435+
this.x = x;
436+
}
437+
}
438+
364439
[SpacetimeDB.Table]
365440
[SpacetimeDB.Index.BTree(Name = "TestIndexWithoutColumns")]
366441
[SpacetimeDB.Index.BTree(Name = "TestIndexWithEmptyColumns", Columns = [])]

crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/ExtraCompilationErrors.verified.txt

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,10 +92,33 @@ var ___hashUnsupportedEnum = UnsupportedEnum.GetHashCode();
9292
}
9393
},
9494
{/*
95+
[SpacetimeDB.Table]
96+
public partial struct TestDefaultFieldValues
97+
^^^^^^^^^^^^^^^^^^^^^^
98+
{
99+
*/
100+
Message: A 'struct' with field initializers must include an explicitly declared constructor.,
101+
Severity: Error,
102+
Descriptor: {
103+
Id: CS8983,
104+
Title: ,
105+
HelpLink: https://msdn.microsoft.com/query/roslyn.query?appId=roslyn&k=k(CS8983),
106+
MessageFormat: A 'struct' with field initializers must include an explicitly declared constructor.,
107+
Category: Compiler,
108+
DefaultSeverity: Error,
109+
IsEnabledByDefault: true,
110+
CustomTags: [
111+
Compiler,
112+
Telemetry,
113+
NotConfigurable
114+
]
115+
}
116+
},
117+
{/*
95118
SpacetimeDB.Internal.Module.RegisterClientVisibilityFilter(global::Module.MY_SECOND_FILTER);
96119
SpacetimeDB.Internal.Module.RegisterClientVisibilityFilter(global::Module.MY_THIRD_FILTER);
97120
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
98-
}
121+
{
99122
*/
100123
Message: Argument 1: cannot convert from 'string' to 'SpacetimeDB.Filter',
101124
Severity: Error,

0 commit comments

Comments
 (0)