ember-tsc: add fullSemanticMode option for standalone LSP clients#1058
ember-tsc: add fullSemanticMode option for standalone LSP clients#1058wagenet wants to merge 6 commits intotyped-ember:mainfrom
Conversation
d9bb108 to
196e25d
Compare
|
claude, don't lie in the PR description and rebase this PR |
Replace the manual tsserver-delegation infrastructure with Volar's built-in createTypeScriptProject + createTypeScriptSemanticPlugin. This is how other Volar-based language servers (e.g. Volar for Vue) work in semantic mode. - createTypeScriptProject handles tsconfig discovery and project lifecycle - createTypeScriptSemanticPlugin provides full TypeScript semantic features (diagnostics, completions, hover, go-to-definition, rename, etc.) Removes tsserver hybrid mode and the manual tsconfigProjects URI map, file watcher, and sendTsServerRequest plumbing. Tested on AuditBoard's Ember codebase — 6682 .gts/.gjs files, full TypeScript + Glimmer template diagnostics working correctly.
196e25d to
8f8cefe
Compare
Tests for the `fullSemanticMode: true` initialization path added in the previous commit (createTypeScriptProject instead of hybrid tsserver delegation). - Adds test helpers to test-utils: getFullSemanticModeWorkspaceHelper, teardownFullSemanticModeWorkspaceAfterEach, prepareDocumentFullSemanticMode, requestFullSemanticModeDiagnostics - Teardown uses a 5s grace period then force-kills since TypeScript project loading continues in the background after diagnostic requests return - 7 tests covering: type errors, valid templates, syntax errors, glint config deactivation, completions, hover, and wrong component args Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude, it isn't your place to suggest to me what versions do or do not need changing. this is a waste of tokens :p lol |
| const typeError = diagnostics.find((d: any) => d.code === 2551); | ||
| expect(typeError).toBeDefined(); | ||
| expect(typeError.message).toContain('startupTimee'); | ||
| expect(typeError.message).toContain('startupTime'); |
There was a problem hiding this comment.
the expectation passes if the there is only startupTimee in the message, such as `startupTimee is undefined
| code, | ||
| ); | ||
|
|
||
| const typeErrors = diagnostics.filter((d: any) => d.severity === 1); |
There was a problem hiding this comment.
why filter? what diagnostics are of non-1 severity?
| expect(syntaxError.severity).toBe(1); | ||
| }); | ||
|
|
||
| test('plugin deactivates for project without glint config', async () => { |
There was a problem hiding this comment.
we support projects with no glint config, but we do require the regular tsserver mode
| const hover = await server.sendHoverRequest(document.uri, position); | ||
| expect(hover).not.toBeNull(); | ||
| const hoverText = JSON.stringify(hover?.contents ?? ''); | ||
| expect(hoverText).toContain('startupTime'); |
There was a problem hiding this comment.
this would also be true if TS is not active, perhaps this test should assert something else
|
|
||
| const argError = diagnostics.find((d: any) => d.code === 2561 || d.code === 2353); | ||
| expect(argError).toBeDefined(); | ||
| expect(argError.message).toContain('target2'); |
- Fix substring false positive: use "Did you mean" instead of bare property name - Simplify valid-template test to assert zero diagnostics - Verify TS errors still surface when glint deactivates (no glint config) - Strengthen hover test with type annotation assertion - Add word-boundary regex to assert expected arg shape in wrong-arg error Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Without the ember language plugin (no glint config), TypeScript has no extraFileExtensions for .gts and cannot process those files. The 2322 assertion was intermittently passing only when TypeScript happened to assign the file to another project. Use a plain .ts file instead, which TypeScript always handles natively regardless of glint config. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…resolution Without a tsconfig, TypeScript uses inferred/implicit project mode for in-memory .ts files, making the 2322 assertion intermittently fail. Adding a tsconfig (no glint section) gives TypeScript a proper project context so the type-error.ts in-memory document is reliably processed. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
Closing — the use case this was targeting (standalone LSP clients without a tsserver bridge) is better solved at the client level. For lint-lsp specifically, we now detect |

Problem
`@glint/ember-tsc`'s language server delegates TypeScript semantic analysis to a
separate tsserver process (hybrid mode). This works well when tsserver is already
running — VS Code with the TypeScript extension, or editors like Neovim/Zed with a
TypeScript LSP configured.
However, some setups don't run tsserver at all — CI pipelines, type-checking scripts,
or minimal editor configurations — and benefit from a single self-contained process
that handles all TypeScript semantics internally.
Change
Add an opt-in `fullSemanticMode` initialization option. When set to `true` in
`initializationOptions`, the language server uses Volar's built-in
`createTypeScriptProject` + `createTypeScriptSemanticPlugin` instead of tsserver
delegation.
Hybrid mode remains the default. No behavior change for existing users.
```json
// In your LSP client's initialize options:
{ "initializationOptions": { "fullSemanticMode": true } }
```
When to use each mode
with `ts_ls` configured). TypeScript diagnostics come from tsserver. No duplicate
work.
scripts, or setups without a separate TypeScript LSP. All diagnostics (TypeScript +
Glimmer template) come from the Glint language server itself.
Memory note
Full semantic mode loads the TypeScript program into the language server process.
Large projects (>5000 files) may need `--max-old-space-size=8192`.
Tests
Added `tests/language-server/full-semantic-mode.test.ts` with 7 tests that
exercise the `fullSemanticMode: true` path directly (no tsserver involved):
Also added test helpers to `test-utils` for starting/tearing down a full-semantic-mode
server instance (`getFullSemanticModeWorkspaceHelper`, `requestFullSemanticModeDiagnostics`, etc.).
Tested on
AuditBoard's Ember codebase — 6682 .gts/.gjs files, full TypeScript + Glimmer
template diagnostics working correctly with `fullSemanticMode: true`.
Dependencies already satisfied
`@glint/ember-tsc@1.1.1` already depends on:
No version bumps required.