[typespec-ts] wip split emitter into adapter / codemodel / codegen#3981
Draft
maorleger wants to merge 35 commits into
Draft
[typespec-ts] wip split emitter into adapter / codemodel / codegen#3981maorleger wants to merge 35 commits into
maorleger wants to merge 35 commits into
Conversation
Tasks executed: 1. ✅ Decisions archive: No archival needed (decisions.md < 20KB threshold) 2. ✅ Decision inbox: Merged ripley-staged-refactor-plan.md + copilot-directive into decisions.md - Summary of 9-stage pipeline refactor (stages 1–9, stage 10 dropped) - Key decisions: swap-in-place, adapter testing focus, readability-first organization - Directives: skip lint guard, focus adapter tests, skip package separation 3. ✅ Orchestration log: Created 2026-05-15T2238Z-ripley.md (not git-tracked per .gitignore) 4. ✅ Session log: Created 2026-05-15T2238Z-refactor-plan.md (not git-tracked per .gitignore) 5. ✅ Cross-agent history: Appended Ripley plan summary to dallas/history.md and parker/history.md 6. ✅ History summarization: All history.md < 15KB (no summarization needed) 7. ✅ Git commit: Staged 3 files (decisions.md, dallas/history.md, parker/history.md) 8. ✅ Health report: decisions.md 0→1710 bytes, inbox count 2→0 (after merge) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ne (Stage 1) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ns (Stage 2) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Fix Stage 3 adapter: add missing isRLCMultiEndpoint import - Fix child TSClient construction: add allowOptionalSubscriptionId and usesNamespacedContextType properties - Rewrite adaptFunctionDeclaration for safe handling of OptionalKind types from ts-morph - Update adapter test expectations for new IR properties (TSClient 16→18, TSMethod 9→17) - Validate: build ✅, unit tests ✅ (662/662 passing), format ✅ - Document session: .squad/log/2026-05-16T0107Z-stage3-scribe-fixes.md - Update decisions.md: Stage 2/3 completion notes Stage 3 now unblocked. Parker ready to implement model/enum/union adapters. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…Stage 4) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…line (Stage 5) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…e (Stage 6a) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ts, serializer placeholders Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ular codegen Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
High-level architecture map for the typespec-ts emitter: entry, RLC vs Modular split, the three-layer TCGC adapter -> code model -> codegen pipeline, framework/reference system, two end-to-end flows, and current known follow-ups. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This reverts commit d4b543a.
…sion package.json continued to advertise ./api/<resource> subpath exports, but the rewritten root index only re-exported ./api/index.js. That left the source graph unable to reach those barrels, so the dist subpath files and root OptionalParams re-exports were never produced during build. Restore the missing top-level api/** recursion in root index emission so the producer once again reaches every generated api subbarrel instead of trying to clean things up downstream. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The rewritten client-context renderer was treating every api-version parameter as required based on isApiVersion alone, even when the adapter had already recorded a client default and left the parameter optional. That changed generated *Context interfaces from apiVersion?: string to apiVersion: string for defaulted clients. Make requiredness follow the adapted TSClientParameter metadata instead of the api-version marker, and lock it in with a modular unit test that renders the new pipeline's client context for a versioned client with a defaulted api-version. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
… models renderer The new pipeline's models renderer was still walking the legacy global emit queue, so it bypassed the adapter's filtered TSCodeModel.models/enums/unions set and reintroduced paging result types like *ListResult onto the public surface. Switch file selection to the filtered IR and look raw sdk types up only for the legacy declaration/serializer helpers that are still shared with src/modular/emitModels.ts. The production path remains src/codegen/models.ts; the legacy file stays as a rendering helper while this removes the direct TCGC dependency from the codegen layer. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Apply formatter output for the client-context and model-renderer regression fixes after re-running build and unit validation. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
… placeholders The new filtered-IR renderer in src/codegen/models.ts only walked codeModel.models/enums/unions and skipped array/dict helper types from the emitQueue. The serializer builders (buildSerializerFunction.ts, buildDeserializerFunction.ts) still emit refkey(type, 'serializer') / refkey(type, 'deserializer') references for those helpers. With no matching declaration registered, the binder left __PLACEHOLDER_*__ tokens unresolved — causing 26 TS2304 errors in the SCVMM and NetworkAnalytics repros. Strategy A: walk emitQueue entries of kind 'array'/'dict' and call emitType() for each, mirroring what the legacy emitTypes() in emitModels.ts did. This registers the serializer/deserializer refkeys so the binder can substitute them. A TODO comment and .squad/decisions/inbox/dallas-models-helpers.md document the follow-up to migrate these helper types into TSCodeModel IR, removing the emitQueue side-channel dependency from the codegen layer. Validated: - pnpm build: clean - npm run unit-test (typespec-ts): 664/664 passed - NetworkAnalytics.Management regen: zero __PLACEHOLDER_ matches, zero TS2304 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Implement Strategy B for modular model helpers by adapting array, dict, and named nullable wrapper types into TSCodeModel.helperTypes and consuming that IR from codegen/models.ts instead of the legacy emitQueue patch. This keeps helper registration in the adapter, removes the dead Strategy A loop from the renderer, and leaves the extensible-enum follow-up (U1) explicitly scoped to adaptEnums. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
These two files were committed before .gitignore caught .squad/. Untracking so the squad-rewrite branch stays free of squad meta-files. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Three-layer pipeline architecture (adapter → code model → renderer) following the proven patterns from typespec-rust and autorest.go. Contains: - Design document (docs/DESIGN.md) with full surface inventory and IR contract - Code model IR types (src/codemodel/) — pure data, no TCGC imports - Adapter stub (src/tcgcadapter/) — TCGC boundary, only layer that imports TCGC - Renderer stub (src/codegen/) — consumes IR only, one function per file kind - Comparator scaffold (src/comparator/) — diff tool interface for validation - Package infrastructure (package.json, tsconfig.json, README.md) All stubs compile cleanly. No implementation yet — architecture only. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ls + comparator on spread Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
… selection Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…SDK metadata Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ly complete Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…loads_modular Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This is the refactor I've wanted for the TypeSpec TS modular emitter for a while: make it boring.
The core problem I noticed was that the old path was reading TCGC types, shaping emitter state, and rendering with
ts-morphall mixed together acrosssrc/modular/. That works until it doesn't. It makes it much harder to reason about boundaries, test the adaptation layer directly, or move code around without accidentally dragging TCGC assumptions everywhere. The real symptoms show up as hard-to-trace bugs that belong in one layer but live in another.What I wanted from this refactor:
This PR builds off of #3970 (the seed POC for the separation). The in-place modular refactor landed in stages 0-6, and I ran the entire suite against real Azure specs to shake out customer-found issues. Stages 0-6 are now wired:
src/tcgcadapter/adapter.tsis the only place that imports TCGC directly and adapts it into the pure IR insrc/codemodel/index.ts. From there,src/codegen/owns the ts-morph rendering for clients, operations, classical clients/operations, models, enums, unions, response types, API options, LRO helpers, and index files. In other words, "what the SDK is" stays separate from "how we print it".I also started a north-star package at
packages/typespec-ts-pristine/(commits 6c0f156 through 03abed9, 9 slices in). This imagines what we'd write today knowing what we know now — a clean-room emitter with zero internal monorepo dependencies (no rlc-common, no typespec-ts), liftable with acp -r. It has a comparator script that validates output equivalence. Early demo results:spreadfixture matches at 95.2%,overloads_modularat 85.7%. Seepackages/typespec-ts-pristine/docs/DESIGN.mdfor the architecture blueprint.Worth flagging: the end goal isn't to land this rewrite in
autorest.typescript. The emitter is being migrated as-is intotypespec-azure, and the real plan is to do this refactor there once the migration lands. This PR is exploratory — it proves the shape works against real fixtures and gets the boring pipeline working so we know what we're committing to.I could have hidden this behind a feature flag or kept it additive for longer; however, I'd rather do the swap in place and keep one source of truth if possible. The migration is still very much WIP.
Still not done in this PR:
ContextManageris still an ambient singleton instead of explicit data flowsrc/modular/helpers/src/tcgcadapter/naming.tsmodule yetValidation on this branch is green:
pnpm buildScope-wise this is 25 files under
packages/typespec-ts/plus a tiny.gitignorehousekeeping change for local team-state files. The last commit is just that housekeeping and not part of the architectural story.Co-authored-by: Copilot 223556219+Copilot@users.noreply.github.com