Optimize LSP discriminated union decoding - #63934
Draft
Jake Bailey (jakebailey) wants to merge 3 commits into
Draft
Optimize LSP discriminated union decoding#63934Jake Bailey (jakebailey) wants to merge 3 commits into
Jake Bailey (jakebailey) wants to merge 3 commits into
Conversation
Jake Bailey (jakebailey)
requested review from
Andrew Branch (andrewbranch) and
Gabriela Araujo Britto (gabritto)
and
a balanced review from Copilot
August 20, 2026 21:38
Contributor
There was a problem hiding this comment.
Pull request overview
Optimizes LSP discriminated-union decoding by streaming fields once the discriminator is found.
Changes:
- Adds reusable streaming struct decoding.
- Updates generated union decoders and generator logic.
- Adds correctness tests and benchmarks.
Reviewed changes
Copilot reviewed 5 out of 6 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
structcodec.go |
Implements streaming discriminated-struct decoding. |
lsp.go |
Removes obsolete raw-field scanning. |
lsp_json_test.go |
Tests discriminator ordering and absence. |
lsp_json_benchmark_test.go |
Benchmarks buffered versus streaming decoding. |
lsp_generated.go |
Uses streaming decoding in generated unions. |
_generate/generate.mts |
Generates streaming discriminator dispatch. |
Files not reviewed (1)
- tsc/internal/lsp/lsproto/lsp_generated.go: Generated file
💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.
Contributor
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 5 out of 6 changed files in this pull request and generated 1 comment.
Files not reviewed (1)
- tsc/internal/lsp/lsproto/lsp_generated.go: Generated file
Suppressed comments (2)
tsc/internal/lsp/lsproto/_generate/generate.mts:3462
- This path can stream only when the optional fallback arm is a generated structure. In particular, when
hasUnknownKindscomes from ananyarm, non-object input now fails the object scan instead of decoding asany, while object input reaching the default arm can panic whenunmarshalDiscriminatedArmreflects over the non-struct. Maps are another non-struct object fallback with the same panic. Retain the buffered discriminator dispatch for such arms.
if (disc && disc.unmapped.length <= 1) {
generateStreamingDiscriminatorDispatch(name, disc, "\t");
exhaustive = true;
tsc/internal/lsp/lsproto/structcodec.go:212
- Do not reject non-string values here: a generated union may have one unmapped fallback arm. For example, a valid
TextDocumentEditcan contain an unknown"kind": nullproperty; the previous decoder dispatched its raw value to the defaultTextDocumentEditarm, whose struct decoder ignores that property, but this scan now fails before reaching the fallback. Retain the raw value and let the generated switch either choose its fallback or report an invalid discriminator when no fallback exists.
if value.Kind() != '"' {
return discriminatedStructDecoder{}, fmt.Errorf("invalid %s discriminator %q: got %v", typeName, discriminator, value.Kind())
}
Comment on lines
+3415
to
+3417
| if (disc && disc.unmapped.length <= 1) { | ||
| generateStreamingDiscriminatorDispatch(name, disc, "\t\t"); | ||
| exhaustive = true; |
Jake Bailey (jakebailey)
force-pushed
the
jakebailey/lsp-streaming-discriminated-unions
branch
from
August 21, 2026 18:46
c2a0f70 to
66d7e1c
Compare
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.
While doing some JSON stuff, I realized that since the LSP client put the discriminator first, we can skip buffering anything and just go right into the real decode. If the discriminator is not first, then we are forced to do the slow thing, but the VS Code language client always puts the discriminator first!
This nets faster decoding: