# Description of Changes
Makes C# consistent with the other module languages.
# API and ABI breaking changes
N/A
# Expected complexity level and risk
1
# Testing
Unit test
# Description of Changes
Adds some docs to the C# bindings packages.
# API and ABI breaking changes
None
# Expected complexity level and risk
0
# Testing
N/A
---------
Signed-off-by: Tyler Cloutier <cloutiertyler@users.noreply.github.com>
Co-authored-by: Tyler Cloutier <cloutiertyler@users.noreply.github.com>
This is the implementation to resolve#4424
# Description of Changes
* Add support for `IEnumerable<T>` as a valid C# View return type in
codegen, so view implementations can return query results without
forcing `ToList()`. The generator now detects `IEnumerable<T>`,
serializes it via the list serializer.
* Snapshots have been updated with a test to confirm that
`IEnumerable<T>` rather than checking it is unsupported (which we had
added when removing support during the transition away from `Query<T>`
usage.
* Refreshes docs/examples to reflect the new supported signature.
# API and ABI breaking changes
No breaking changes. This is additive support for an existing .NET
interface.
# Expected complexity level and risk
2 - Low
# Testing
- [X] Rebuilt CLI locally, ran regression tests, and `dotnet tests` in
C# module bindings.
- [X] Tested updated docs code snippets to ensure they resolve in an IDE
and publish.
---------
Signed-off-by: Ryan <r.ekhoff@clockworklabs.io>
## Summary
This PR fixes an issue where C# reserved keywords (like `params`,
`class`, `event`, etc.) used as field or parameter names in SpacetimeDB
types would cause compilation errors in the generated code.
## Problem
When a user defines a table or reducer with a field named using a C#
reserved keyword:
```csharp
[SpacetimeDB.Table]
public partial struct MyTable
{
public int @params; // User escapes it in their code
public string @class;
}
```
The codegen would generate invalid C# like:
```csharp
// Generated code (broken)
public int params; // Error: keyword used as identifier
public void Read(BinaryReader reader) {
params = ...; // Error
}
```
## Solution
1. Added an `Identifier` property to `MemberDeclaration` in the codegen
that automatically detects C# reserved keywords using
`SyntaxFacts.GetKeywordKind()` and prefixes them with `@` when needed.
2. Updated all code generation sites to use `Identifier` instead of
`Name` when generating:
- Field declarations
- Property accessors
- Constructor parameters
- BSATN serialization code
- Index accessors
- Reducer/procedure parameters
3. Added a regression test that verifies tables, reducers, and
procedures with keyword field names compile successfully.
## Test Plan
- Added `CSharpKeywordIdentifiersAreEscapedInGeneratedCode` test that
creates a table with `@class` and `@params` fields, plus a reducer and
procedure with keyword parameters
- Existing tests continue to pass (verified locally with
`FormerlyForbiddenFieldNames` fixture which already tests edge cases
like `Read`, `Write`, `GetAlgebraicType`)
Fixes#4529
---------
Co-authored-by: Stable Genius <259448942+stablegenius49@users.noreply.github.com>
Co-authored-by: Ryan <r.ekhoff@clockworklabs.io>
This is the implementation of a fix for #4425
# Description of Changes
* Clarified C# generator diagnostics for view return types:
1. Updated the comments around `IQuery<T>` handling to describe the
return value as `T?`, matching C# semantics.
2. Adjusted the validation comment to say views must return `List<T>` or
nullable `T` instead of “Vec/Option”.
* Synced the diagnostics fixture comments with the new terminology so
STDB0024 examples talk about `List<T>`/`T?`.
* Checked current documentation for anything C# related to “Vec/Option”
and confirmed everything now references `List<T>`/`T?`.
* Regenerated/verified tests and snapshots.
# API and ABI breaking changes
None
# Expected complexity level and risk
1 - Changes are documentation and diagnostic-comment only.
# Testing
- [X] CLI rebuilt, local `dotnet test` pass and error output tests
validated.
---------
Signed-off-by: Ryan <r.ekhoff@clockworklabs.io>
Co-authored-by: joshua-spacetime <josh@clockworklabs.io>
This is the implementation of the "Nice to Have in 2.0" items from #4295
# Description of Changes
* Propagate the module’s case-conversion policy and each explicit
canonical name (tables, reducers, procedures, views, indexes) into
`RawModuleDefV10`, so runtime consumers receive the same metadata
emitted by the Rust toolchain.
* Implement support for `[SpacetimeDB.Settings]` + explicit `Name = ...`
attribute overrides in the C# module bindings generator.
* Adds an `explicitnames` fixture to the Codegen Test suite to cover the
generated registration calls, ensuring accessor vs. canonical names stay
in sync.
# API and ABI breaking changes
None. Generator + runtime internals only; no public surface changes.
# Expected complexity level and risk
2 – localized to the C# codegen/runtime plumbing, validated by focused
tests.
# Testing
- [X] Compiled CLI changes locally and ran C# regression tests.
- [X] Ran `dotnet test
crates/bindings-csharp/Codegen.Tests/Codegen.Tests.csproj -c Release` to
verify code tests pass
# Description of Changes
This is the implementation of the Typed Query Builder for C# modules
outlined in #3750.
This requires the changes from #4146 to be in place before it can
properly function.
This aligns the C# typed query builder SQL formatter with the Rust
implementation:
* Supports `And/Or` with same grouping styles as Rust.
* All comparison operators (`Eq/Neq/Lt/…`) wrap expressions in
parentheses so chained predicates produce byte-for-byte identical SQL.
# API and ABI breaking changes
Not breaking. Existing modules keep producing the same SQL semantics;
only redundant parentheses were added to match the Rust formatter.
# Expected complexity level and risk
2 — localized string-format updates plus parity harness tweaks. Low
functional risk; largest concern is ensuring every comparison path
gained parentheses.
# Testing
- [X] Tested against a local test harness validating output from these
changes match current Rust behavior.
---------
Signed-off-by: Ryan <r.ekhoff@clockworklabs.io>
Co-authored-by: joshua-spacetime <josh@clockworklabs.io>
# Description of Changes
This PR fixes a C# SDK regression where using `Bound` in index filters
could trigger an ambiguous reference compiler error for Local after
upgrading to `v1.11.2`, as reported in
[#3995](https://github.com/clockworklabs/SpacetimeDB/issues/3995).
It also fixes a related warning-spam regression (`CS0436`) where user
projects could see `Local` type conflicts between generated module code
and the `SpacetimeDB.Runtime` assembly.
* Introduced a public `SpacetimeDB.Bound` type so users no longer need
to import `SpacetimeDB.Internal` to use bounds in index filters.
* Kept `SpacetimeDB.Internal.Bound` for compatibility, but added
implicit conversions between `SpacetimeDB.Internal.Bound` and
`SpacetimeDB.Bound`.
* Updated the C# code generator to emit fully-qualified
`global::SpacetimeDB.Bound` in generated index filter signatures,
avoiding `SpacetimeDB.Internal` in public-facing APIs and preventing
name collisions (e.g., `Local`).
* Updated internal runtime bounds helpers (`BTreeIndexBounds<...>`) to
explicitly use `SpacetimeDB.Bound` when constructing range-scan
arguments.
* Updated Codegen snapshot fixtures to match the new generated output
(type name + formatting).
* Fixed codegen output for `ITableView` `static abstract` member
implementations to generate `public static` methods (required for the
generated code to compile).
It also fixes a related warning-spam regression (CS0436) where user
projects could see Local type conflicts between generated module code
and the SpacetimeDB.Runtime assembly.
Additional fix (related to the `Local` reports):
* Removed the runtime assembly’s ownership of `SpacetimeDB.Local`
(introduced more recently than the generated module `Local`) to prevent
`CS0436` duplicate-type warnings. Basically, the runtime’s concrete
`Local`/`ProcedureTxContext` helpers were renamed and made internal so
the code generator remains the sole owner of module-level
`SpacetimeDB.Local`.
Regression coverage:
* Added generator regression assertions to ensure generated code does
not reference `global::SpacetimeDB.Internal.Bound<...>` and does
reference `global::SpacetimeDB.Bound<...>`.
* Added a runtime API regression assertion that `SpacetimeDB.Bound`
exists and is public in the runtime reference.
* Added a regression assertion that `SpacetimeDB.Runtime` does not
define codegen-owned types (e.g. `SpacetimeDB.Local`,
`ProcedureContext`, etc.) to prevent future `CS0436` conflicts.
* Added a “simulated downstream user file” compile check ensuring no
`CS0436` diagnostics occur when user code references
`SpacetimeDB.Local`.
# API and ABI breaking changes
None.
* No schema or wire-format changes.
* The changes are limited to C# type exposure / naming and codegen
output.
* `SpacetimeDB.Internal.Bound` remains usable via implicit conversions
(backwards compatible for existing code).
# Expected complexity level and risk
2 - Low
* Changes are isolated to C# runtime type exposure, codegen type
references, and snapshot updates.
* No runtime behavior changes to index scan encoding/decoding; only
avoids requiring SpacetimeDB.Internal in user code.
# Testing
- [X] Ran:`dotnet test
crates/bindings-csharp/Codegen.Tests/Codegen.Tests.csproj`
- [X] Ran regression tests locally.