Repository navigation
feat(vscode): report GraphQLSP diagnostics through TypeScript 7's API sessions - #439
Open
JoviDeCroock wants to merge 2 commits into
Open
JoviDeCroock wants to merge 2 commits into
JoviDeCroock wants to merge 2 commits into
Conversation
🦋 Changeset detectedLatest commit: a708e4d The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
This was referenced Oct 24, 2026
JoviDeCroock
added this pull request to stack #440
October 24, 2026 09:23
JoviDeCroock
marked this pull request as ready for review
October 24, 2026 09:23
Adds createLanguageServerSession to @0no-co/graphqlsp/check, which runs GraphQLSP's diagnostics on a TypeScript 7.1 language server's snapshot (including unsaved editor changes) through an API session pipe. Since the 7.1 sync client can't connect to pipes yet, it's bridged by a small relay that translates the sync client's MessagePack stdio protocol to the session's JSON-RPC. The VS Code extension uses it when TypeScript 7's extension initializes its language server, publishing diagnostics through a DiagnosticCollection from a forked process. The TypeScript 5/6 plugin path is unchanged.
JoviDeCroock
force-pushed
the
feat/vscode-ts7-api-session
branch
from
October 24, 2026 09:52
8465872 to
24265fb
Compare
TypeScriptTeam.native-preview 1.0 calls onLanguageServerInitialized's listener without an argument and exposes initializeAPIConnection on its extension API instead. The TypeScript installation is then resolved from the same tsdk settings, falling back to the workspace's typescript@>=7.
This branch has not been deployed
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.
Stacked on #438 (base
feat/ts7-api-host). Context: 0no-co/gql.tada#606 and 0no-co/gql.tada#610 handle.graphqlfiles through a TypeScript 7.1 content mapper. This PR covers inlinegraphql()documents in the editor.TypeScript 7's language server doesn't load the tsserver plugin, so with the TypeScript 7 VS Code extension, GraphQLSP's diagnostics are gone in the editor. With this PR, once TypeScript 7's extension initializes its language server, the GraphQLSP extension opens an API session of it. It runs #438's diagnostics core on the server's current snapshot, which includes unsaved editor changes, and publishes the results through a
DiagnosticCollection. The TypeScript 5/6 plugin path is unchanged.What changed
@0no-co/graphqlsp/check:createLanguageServerSessioncheckreadsgetCurrentLanguageServerSnapshot(), thengetDefaultProjectForFile(). It reads the plugin entry from that project's tsconfig (followingextends) and loads the schema once per project. Diagnostics use the sameCheckDiagnosticshape ascheckProject.nullfor files outside projects that configure GraphQLSP.textis the file text the diagnostics were computed for. If it doesn't match the editor's text, the language server hasn't caught up yet, and the caller should retry.CheckDiagnostic, the conversion helpers and line/column mapping moved tosrc/ts7/report.ts, socheckProjectand the session share them.loadSchemagained anonChangeoption.The sync client can't use LSP pipes yet, so there's a relay (
src/ts7/relay.ts)The plan was
API.fromLSPConnection({ pipe })fromtypescript/sync. That fails in typescript@7.1.0-beta, and in today'stypescript@next(7.1.0-dev.20261024.1), with "Socket connections are not yet supported in the sync client".handleInitializeAPISessionintsc/internal/lsp/server.go) only speak JSON-RPC over an async connection.So the session tries
fromLSPConnection({ pipe })first. When that throws "not yet supported", it passes a generatedtsserverPathto the sync client instead:[type, method, payload]tuples to JSON-RPC requests on the pipe.isSourceFileResponseMethodintsc/internal/api/session.go), it decodes JSON-RPC's{ data: base64 }back into raw bytes.Once the sync client supports pipes, the relay drops out without changes. Windows isn't supported: the sync client can only spawn an executable there.
VS Code extension (
packages/vscode-graphqlsp/src/typescript7/)activateTypeScript7looks forTypeScriptTeam.native-previeworTypeScriptTeam.vscode-typescript-nightlyand subscribes toonLanguageServerInitialized. The releasedTypeScriptTeam.native-preview1.0 calls that listener without aTypeScriptSDKand hasinitializeAPIConnectionon its extension API. In that case the extension resolves the TypeScript installation from the samejs/ts.tsdk.path/typescript.tsdk/typescript.native-preview.tsdksettings, falling back to the workspace'stypescript@>=7. Nothing runs unless TypeScript 7's language server starts. On every (re)initialization, the previous session is discarded, as the extension API documents.dist/typescript7/server.jswithNODE_PATHpointing at the SDK'snode_modules, and talks to it over IPC. The sync API blocks, so it must not run in the extension host.NODE_PATHmatters because@gql.tada/internaldoesrequire('typescript')at import time, and the vsix doesn't shiptypescript.textdoesn't match the document (the language server is lagging) is retried every 100 ms, up to 20 times.document.positionAt(start), with sourcegraphqlsp.typescriptServerPluginscontribution,configurePluginand settings sync stay as they were.tsconfig.jsongains"types": ["node"], because TypeScript 6 changed thetypesdefault to[].Verification (local, macOS)
pnpm run test:e2e: 21 files, 114 passed and 3 skipped, on top of feat: check GraphQL documents with TypeScript 7.1 and tsrs (checkProject) #438 atb423a19. That includes 3 new session tests on TypeScript 7.1; the 3 skips are the tsrs legs.test/e2e/ts7-session.test.tsspawns the realtypescript@7.1.0-betalanguage server (--lsp --stdio), opensvalid.tswith an unsavednmaefield and requestscustom/initializeAPISession. It checks that:Cannot query field "nmae"…at the unsaved text's position;didChangeback to the saved text, there are no diagnostics;null.MethodNotFound: custom/initializeAPISession is not ported yet. The CItypescript-7job now also runs the session test.dist/typescript7/server.jsagainst a live TS 7.1 language server over IPC. The first check returned in about 560 ms, schema load included, andvalid.tsandinvalid.tsgave the expected diagnostics.typescriptcouldn't be resolved: it works withNODE_PATH, and without it fails withCannot find module 'typescript'from@gql.tada/internal.pnpm buildandpnpm --filter vscode-graphqlsp build(tsc) pass, andpnpm --filter vscode-graphqlsp packagebuilds the vsix.tsc -p packages/graphqlsp --types node --module esnext --moduleResolution bundlershows no errors in new or changed files. The existing errors in untouched files are the same.Dogfooded in VS Code
Setup
@vscode/test-electron.TypeScriptTeam.native-preview1.0.1 from the marketplace, plus the vsix built from this branch.fixture-project-ts7withtypescript@7.1.0-beta,gql.tada@1.11.4, and@gql.tada/content-mapperfrom feat(content-mapper): experimental field IntelliSense via lowered selections gql.tada#614 withintellisense: true.js/ts.experimental.useTsgo: trueand a globaljs/ts.tsdk.path. Workspace trust was disabled so content mappers run.vscode.languages.getDiagnostics(),vscode.executeHoverProviderandvscode.executeCompletionItemProvider.Bug found and fixed (
a708e4d). The released extension calls theonLanguageServerInitializedlistener with no argument. TheTypeScriptSDKargument only exists in 7.1.0-beta'stypescript/vscodetypes. Because of this, the first VS Code run threwCannot read properties of undefined (reading 'packageJsonPath')and reported nothing. Both API shapes are handled now. One caveat remains: if TypeScript 7's extension ignores a workspacetsdksetting because the workspace version hasn't been approved, GraphQLSP may load the API client from a different installation than the server's.Results after the fix
invalid.ts, cold, including the schema load. After reopening the window, it takes 0.9 s.invalid.ts,colocation.ts,field-usage.tsandbroken.graphqlhave no duplicate diagnostics.graphqlsp-source diagnostics. The built-in extension's tsserver plugin doesn't also report whileuseTsgois on.typescript.native-preview.restartclears the collection, and diagnostics are back 0.87 s after the restart.broken.graphqlreportsCannot query field "nmae"at 4:5-4:9, andsyntax.graphqlreports its syntax error at 4:1.pokemon.graphqlhas none.(property) 'name': "String!".cllists all 15 fields plus__typename.useTsgooff.ts, at the same ranges as the TypeScript 7 path, and nothing comes from thegraphqlspcollection. There are no duplicates.7:7-8:1) are the plugin's existing behavior, so I kept them the same.[error]lines, all from the deliberate restart: the API socket closed and the server exited.Observed once: on the very first TypeScript 5.9 run, the classic plugin's diagnostics didn't show up until the first edit. I couldn't reproduce it in 3 later runs, 2 on this branch and 1 on
main. This PR doesn't touch that path, and the plugin doesn't refresh diagnostics after the schema loads, so it looks like an existing race.Not tested
vscode-typescript-nightlyextension, and theTypeScriptSDKAPI shape inside a real extension. No released extension ships it yet; that shape is only covered by types.workbench.action.reloadWindowin the same process. I relaunched VS Code instead.graphql(). They aren't implemented: in VS Code, inline documents get no GraphQL hover and only TypeScript's completions.Gaps and TODOs
registerLspMiddleware(method, transformer)fortextDocument/hoverandtextDocument/completion(plustextDocument/diagnostic, which could replace the separateDiagnosticCollection). Those transformers are async, and the session would need GraphQLSP's hover and completion entry points behind the host interface, like feat: check GraphQL documents with TypeScript 7.1 and tsrs (checkProject) #438 did for diagnostics.custom/initializeAPISessionisn't ported in tsrs@0.18.@gql.tada/internal: the top-levelrequire('typescript')forces theNODE_PATHworkaround.tsconfig.jsonare checked. Thegraphqlsp.*VS Code settings only reach the tsserver plugin.@0no-co/graphqlsp.vscode-graphqlspis in the changesetignorelist.