Skip to content

Use Alloy for C# keywords and System.Text.Json symbols - #11599

Draft
Timothee Guerin (timotheeguerin) wants to merge 4 commits into
microsoft:mainfrom
timotheeguerin:hsc/alloy-naming-and-json-builtins
Draft

Use Alloy for C# keywords and System.Text.Json symbols#11599
Timothee Guerin (timotheeguerin) wants to merge 4 commits into
microsoft:mainfrom
timotheeguerin:hsc/alloy-naming-and-json-builtins

Conversation

@timotheeguerin

Copy link
Copy Markdown
Member

The emitter carried a 217-line hand-maintained table of C# keywords and a createLibrary call re-declaring the System.Text.Json.Serialization attributes. @alloy-js/csharp ships both, and its versions are better: the local keyword list was missing delegate, and hand-declared symbols do not participate in Alloy's automatic using management.

Both are deleted in favour of the Alloy equivalents (isValidCSharpIdentifier, csharpKeywords, the System/Text/Json builtins), along with the local getDocComments copy, which is already exported from @typespec/emitter-framework/csharp.

One thing Alloy deliberately does not do is worth calling out: its name policy @-escapes real keywords, but the emitter needs namespace segments colliding with common BCL type names to be renamed — a namespace called Type shadows System.Type and breaks every typeof() in the generated converters. That rule survives, now isolated in getCSharpNamespaceName and built on Alloy's keyword sets rather than a parallel list.

Generated output is unchanged.


Part of a 7-PR stack moving @typespec/http-server-csharp onto the emitter framework. Stacked on #11598 — only the last commit is new here.

Adds handling for Tuple, StringTemplate, EnumMember, ModelProperty, UnionVariant,
template parameters and the full Intrinsic set. An unsupported type now reports a
diagnostic and falls back to `object` instead of throwing.

Also fixes the C# components reporting a TypeScript diagnostic for unsupported
scalars, and corrects the C# expressions emitted for the `null` and `never`
intrinsics. Adds an `isCSharpValueType` util.
…al_ComponentOverrides

The `declaration` descriptor existed but nothing dispatched to it, so an emitter
could override how a type is referenced but not how it is declared. The C#
`ClassDeclaration`, `Property` and `EnumDeclaration` now render through the
override point.
ClassDeclaration takes an explicit property list and extra members, Property
takes the full Alloy property prop set plus name/csharpType overrides,
EnumDeclaration takes an explicit member list and jsonAttributes, and
JsonConverter takes doc, access modifiers, extra members and an explicit
csharpType.
…xt.Json symbols

Deletes the emitter's own C# keyword table and its re-declaration of the
System.Text.Json.Serialization attributes, both of which are provided by
@alloy-js/csharp. Namespace segments colliding with BCL type names are still
renamed, now via a dedicated getCSharpNamespaceName helper.
@pkg-pr-new

pkg-pr-new Bot commented Aug 7, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/@typespec/emitter-framework@11599
npm i https://pkg.pr.new/@typespec/http-server-csharp@11599

commit: deadf7c

@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

All changed packages have been documented.

  • @typespec/emitter-framework
  • @typespec/http-server-csharp
Show changes

@typespec/emitter-framework - feature ✏️

Let emitters author the C# declaration components instead of forking them,> ,> - ClassDeclaration accepts an explicit properties list and extra members as children.,> - Property accepts every Alloy property prop, plus name and csharpType overrides.,> - EnumDeclaration accepts an explicit members list and a jsonAttributes prop.,> - JsonConverter accepts doc, access modifiers, extra members, an explicit csharpType, and a readReturns override.,> ,> tsx,> <ClassDeclaration type={model} properties={model.properties.values().filter(isVisible)} partial>,> <Constructor />,> </ClassDeclaration>,>

@typespec/emitter-framework - fix ✏️

Make the C# TypeExpression handle every type kind instead of throwing,> ,> Tuple, StringTemplate, EnumMember, ModelProperty, UnionVariant, template parameters and the full Intrinsic set are now supported, and an unsupported type reports a diagnostic and falls back to object rather than throwing. Also fixes the C# components reporting a TypeScript diagnostic for unsupported scalars, and corrects the C# expressions for the null and never intrinsics.

@typespec/emitter-framework - feature ✏️

Support declaration overrides in Experimental_ComponentOverrides,> ,> Only reference overrides were dispatched, so an emitter could customize how a type is referenced but not how it is declared, forcing it to fork the framework's declaration components. The C# ClassDeclaration, Property and EnumDeclaration now render through the override point.,> ,> tsx,> const overrides = Experimental_ComponentOverridesConfig().forTypeKind("ModelProperty", {,> declaration: (props) =>,> props.type.name === "id" ? (,> <props.Declaration {...props.declarationProps} name="Identifier" />,> ) : (,> props.default,> ),,> });,>

@typespec/http-server-csharp - internal ✏️

Use Alloy's C# keyword handling and System.Text.Json symbols instead of local copies,> ,> Deletes the emitter's own 217-line C# keyword table and its re-declaration of the System.Text.Json.Serialization attributes, which are both provided by @alloy-js/csharp. Namespace segments that collide with common BCL type names are still renamed, now in a dedicated getCSharpNamespaceName helper.

@azure-sdk-automation

Copy link
Copy Markdown

You can try these changes here

🛝 Playground 🌐 Website 🛝 VSCode Extension

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

emitter-framework Issues for the emitter framework

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant