Skip to content

Build models, properties and enums on the emitter framework - #11601

Draft
Timothee Guerin (timotheeguerin) wants to merge 6 commits into
microsoft:mainfrom
timotheeguerin:hsc/models-on-emitter-framework
Draft

Build models, properties and enums on the emitter framework#11601
Timothee Guerin (timotheeguerin) wants to merge 6 commits into
microsoft:mainfrom
timotheeguerin:hsc/models-on-emitter-framework

Conversation

@timotheeguerin

Copy link
Copy Markdown
Member

The emitter shipped private forks of the framework's ClassDeclaration, Property and EnumDeclaration — copies made because the framework offered no way to adjust them, which then drifted. With declaration overrides and component props now available (#11597, #11598), the forks go away and the divergences are expressed as configuration:

  • The property policy (nullability, virtual/override/new, error-model members, JSON attributes) becomes a registered ModelProperty declaration override.
  • ServerClassDeclaration becomes EfClassDeclaration with an explicit properties list and the generated constructors passed as children.
  • Enums renders through EfEnumDeclaration with an explicit members list, keeping the emitter's more permissive union-as-enum detection.

models.tsx drops from ~270 lines to ~125, and the whole change is a net -350 lines.

One structural note for reviewers: the framework's TypeExpression recurses into itself, not into a consumer's wrapper. Any type kind whose handling recurses into a contained type therefore has to stay in the emitter's wrapper or its divergences are silently lost for the nested type. Scalars are the exception — they go through component overrides, which apply at every level. This is now written down in a comment at the top of the wrapper, because it is not obvious and it caused a regression while writing this.

Generated output is unchanged.


Part of a 7-PR stack moving @typespec/http-server-csharp onto the emitter framework. Stacked on #11600 — 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.
…ource of truth

The emitter had three disagreeing scalar-to-C# name maps, so error model
constructors declared parameters such as DateOnly, Uri and sbyte while the
matching properties were DateTime, string and SByte - code that does not
compile. NumericConstraintAttribute<T> had the same mismatch.
…he emitter framework

Replaces the private forks of ClassDeclaration, Property and EnumDeclaration with
the framework components, expressing the emitter's own behavior as a declaration
override and component props. Generated output is unchanged.
@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@11601
npm i https://pkg.pr.new/@typespec/http-server-csharp@11601

commit: 1befaa3

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

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

Fix generated error model constructors and numeric constraint attributes using the wrong C# types,> ,> Error model constructors declared parameters such as DateOnly, Uri and sbyte while the matching properties were DateTime, string and SByte, producing code that did not compile. NumericConstraintAttribute<T> had the same mismatch, which stopped the converter from binding.

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

Build model, property and enum generation on @typespec/emitter-framework components,> ,> The emitter carried private forks of the framework's ClassDeclaration, Property and EnumDeclaration. They are now consumed directly, with the emitter's own behavior expressed as a declaration override and component props. Generated output is unchanged.

@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