Conversation
There was a problem hiding this comment.
Pull request overview
This PR adds an “expandable hover” feature end-to-end: a proposed VS Code hover API that can request increased “verbosity”, an LSP extension (verbosityLevel on HoverParams + canIncreaseVerbosity on Hover), server plumbing to honor it, and fourslash coverage/baselines for the new hover behavior.
Changes:
- Extend LSP hover request/response shapes to support verbosity (
verbosityLevel) and server-provided expandability (canIncreaseVerbosity). - Add a VS Code extension hover provider that uses the proposed hover verbosity API and sends
verbosityLevelover LSP (disabling the languageclient’s built-in hover). - Add fourslash harness support + many new baselines/tests for hover verbosity scenarios, plus conversion-script support for
verify.baselineQuickInfo({...}).
Reviewed changes
Copilot reviewed 91 out of 93 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
internal/lsp/server.go |
Routes hover requests to verbose hover implementation when verbosityLevel is present. |
internal/lsp/lsproto/lsp_generated.go |
Adds verbosityLevel to HoverParams, canIncreaseVerbosity to Hover, and a capabilities flag. |
internal/lsp/lsproto/_generate/generate.mts |
Patches the LSP model so the generator emits the new hover fields/capabilities. |
_extension/src/languageFeatures/hover.ts |
New VS Code hover provider that requests verbose hover via LSP and maps expand/decrease flags. |
_extension/src/vscode.proposed.editorHoverVerbosityLevel.d.ts |
Declares the proposed VS Code API surface (VerboseHover, HoverContext, etc.). |
_extension/src/client.ts |
Advertises hover verbosity capability + registers the custom hover provider; disables LSP hover via middleware. |
_extension/package.json |
Enables the editorHoverVerbosityLevel proposal and bumps VS Code engine/types. |
package-lock.json |
Updates VS Code typings version to match the engine bump. |
internal/checker/printer.go |
Adds verbosity-aware type/signature/symbol-to-declaration stringification helpers. |
internal/checker/nodebuilder.go |
Adds verbosity-aware nodebuilder entry points and symbol-declaration rendering helpers. |
internal/checker/services.go |
Introduces Checker.IsLibType used to prevent expanding default-lib types. |
internal/ls/completions.go |
Refactors completion item detail generation; threads hover quickinfo via the updated quickinfo helper signature. |
internal/ls/string_completions.go |
Updates call into completion details helper after signature refactor. |
internal/fourslash/fourslash.go |
Adds VerifyBaselineHoverWithVerbosity helper for producing multi-verbosity hover baselines. |
internal/fourslash/baselineutil.go |
Uses stable sorting when inserting multiple tooltips at the same position. |
internal/fourslash/_scripts/convertFourslash.mts |
Adds support for verify.baselineQuickInfo({...verbosity...}) conversion into Go tests. |
internal/fourslash/_scripts/unparsedTests.txt |
Removes now-supported quickinfoVerbosity tests from the “unparsed” list. |
internal/fourslash/_scripts/failingTests.txt |
Updates the list of failing tests (removals). |
internal/fourslash/tests/quickinfoVerbosityNamespaceDefaultExport_test.go |
New manual fourslash test for namespace default export verbosity behavior. |
internal/fourslash/tests/gen/quickinfoVerbosity1_test.go |
Generated hover verbosity test. |
internal/fourslash/tests/gen/quickinfoVerbosity2_test.go |
Generated hover verbosity test. |
internal/fourslash/tests/gen/quickinfoVerbosity3_test.go |
Generated hover verbosity test. |
internal/fourslash/tests/gen/quickinfoVerbosityClass1_test.go |
Generated hover verbosity test. |
internal/fourslash/tests/gen/quickinfoVerbosityClass2_test.go |
Generated hover verbosity test. |
internal/fourslash/tests/gen/quickinfoVerbosityConditionalType_test.go |
Generated hover verbosity test. |
internal/fourslash/tests/gen/quickinfoVerbosityEnum_test.go |
Generated hover verbosity test. |
internal/fourslash/tests/gen/quickinfoVerbosityFunction_test.go |
Generated hover verbosity test. |
internal/fourslash/tests/gen/quickinfoVerbosityImport_test.go |
Generated hover verbosity test. |
internal/fourslash/tests/gen/quickinfoVerbosityIndexedAccessType_test.go |
Generated hover verbosity test. |
internal/fourslash/tests/gen/quickinfoVerbosityIndexSignature_test.go |
Generated hover verbosity test. |
internal/fourslash/tests/gen/quickinfoVerbosityIndexType_test.go |
Generated hover verbosity test. |
internal/fourslash/tests/gen/quickinfoVerbosityInterface1_test.go |
Generated hover verbosity test. |
internal/fourslash/tests/gen/quickinfoVerbosityInterface2_test.go |
Generated hover verbosity test. |
internal/fourslash/tests/gen/quickinfoVerbosityIntersection1_test.go |
Generated hover verbosity test. |
internal/fourslash/tests/gen/quickinfoVerbosityJs_test.go |
Generated hover verbosity test. |
internal/fourslash/tests/gen/quickinfoVerbosityLibType_test.go |
Generated hover verbosity test. |
internal/fourslash/tests/gen/quickinfoVerbosityMappedType_test.go |
Generated hover verbosity test. |
internal/fourslash/tests/gen/quickinfoVerbosityNamespace_test.go |
Generated hover verbosity test. |
internal/fourslash/tests/gen/quickinfoVerbosityNamespaceDefaultExport_test.go |
Generated hover verbosity test. |
internal/fourslash/tests/gen/quickinfoVerbosityNoErrorTruncation1_test.go |
Generated hover verbosity test. |
internal/fourslash/tests/gen/quickinfoVerbosityObjectType1_test.go |
Generated hover verbosity test. |
internal/fourslash/tests/gen/quickinfoVerbosityRecursiveType_test.go |
Generated hover verbosity test. |
internal/fourslash/tests/gen/quickinfoVerbosityServer_test.go |
Generated hover verbosity test (server mode). |
internal/fourslash/tests/gen/quickinfoVerbosityToplevelTruncation1_test.go |
Generated hover verbosity test. |
internal/fourslash/tests/gen/quickinfoVerbosityToplevelTruncation2_test.go |
Generated hover verbosity test. |
internal/fourslash/tests/gen/quickinfoVerbosityTruncation1_test.go |
Generated hover verbosity test. |
internal/fourslash/tests/gen/quickinfoVerbosityTruncation2_test.go |
Generated hover verbosity test. |
internal/fourslash/tests/gen/quickinfoVerbosityTuple_test.go |
Generated hover verbosity test. |
internal/fourslash/tests/gen/quickinfoVerbosityTypeof_test.go |
Generated hover verbosity test. |
internal/fourslash/tests/gen/quickinfoVerbosityTypeParameter_test.go |
Generated hover verbosity test. |
testdata/baselines/reference/fourslash/quickInfo/quickinfoVerbosity1.baseline |
New hover verbosity baseline. |
testdata/baselines/reference/fourslash/quickInfo/quickinfoVerbosity2.baseline |
New hover verbosity baseline. |
testdata/baselines/reference/fourslash/quickInfo/quickinfoVerbosityConditionalType.baseline |
New hover verbosity baseline. |
testdata/baselines/reference/fourslash/quickInfo/quickinfoVerbosityFunction.baseline |
New hover verbosity baseline. |
testdata/baselines/reference/fourslash/quickInfo/quickinfoVerbosityIndexSignature.baseline |
New hover verbosity baseline. |
testdata/baselines/reference/fourslash/quickInfo/quickinfoVerbosityIndexType.baseline |
New hover verbosity baseline. |
testdata/baselines/reference/fourslash/quickInfo/quickinfoVerbosityIndexedAccessType.baseline |
New hover verbosity baseline. |
testdata/baselines/reference/fourslash/quickInfo/quickinfoVerbosityIntersection1.baseline |
New hover verbosity baseline. |
testdata/baselines/reference/fourslash/quickInfo/quickinfoVerbosityLibType.baseline |
New hover verbosity baseline. |
testdata/baselines/reference/fourslash/quickInfo/quickinfoVerbosityMappedType.baseline |
New hover verbosity baseline. |
testdata/baselines/reference/fourslash/quickInfo/quickinfoVerbosityNamespaceDefaultExport.baseline |
New hover verbosity baseline. |
testdata/baselines/reference/fourslash/quickInfo/quickinfoVerbosityNoErrorTruncation1.baseline |
New hover verbosity baseline. |
testdata/baselines/reference/fourslash/quickInfo/quickinfoVerbosityObjectType1.baseline |
New hover verbosity baseline. |
testdata/baselines/reference/fourslash/quickInfo/quickinfoVerbosityRecursiveType.baseline |
New hover verbosity baseline. |
testdata/baselines/reference/fourslash/quickInfo/quickinfoVerbosityServer.baseline |
New hover verbosity baseline. |
testdata/baselines/reference/fourslash/quickInfo/quickinfoVerbosityTruncation1.baseline |
New hover verbosity baseline. |
testdata/baselines/reference/fourslash/quickInfo/quickinfoVerbosityToplevelTruncation1.baseline |
New hover verbosity baseline. |
testdata/baselines/reference/fourslash/quickInfo/quickinfoVerbosityToplevelTruncation2.baseline |
New hover verbosity baseline. |
testdata/baselines/reference/fourslash/quickInfo/quickinfoVerbosityTypeof.baseline |
New hover verbosity baseline. |
testdata/baselines/reference/fourslash/quickInfo/quickinfoVerbosityTypeParameter.baseline |
New hover verbosity baseline. |
testdata/baselines/reference/fourslash/quickInfo/quickInfoDisplayPartsTypeParameterInFunction.baseline |
Updates baseline output for type parameter/parameter quickinfo display parts. |
testdata/baselines/reference/fourslash/quickInfo/quickInfoDisplayPartsTypeParameterInClass.baseline |
Updates baseline output for class type parameter/parameter quickinfo display parts. |
testdata/baselines/reference/fourslash/quickInfo/quickInfoDisplayPartsTypeParameterInTypeAlias.baseline |
Updates baseline output for type parameter quickinfo display parts. |
testdata/baselines/reference/fourslash/quickInfo/quickInfoDisplayPartsTypeParameterInFunctionLikeInTypeAlias.baseline |
Updates baseline output for type parameter quickinfo display parts. |
testdata/baselines/reference/fourslash/quickInfo/quickInfoDisplayPartsEnum1.baseline |
Updates enum quickinfo baseline (e.g. const enum rendering). |
testdata/baselines/reference/fourslash/quickInfo/quickInfoDisplayPartsEnum2.baseline |
Updates enum quickinfo baseline (e.g. const enum rendering). |
testdata/baselines/reference/fourslash/quickInfo/quickInfoDisplayPartsEnum3.baseline |
Updates enum quickinfo baseline (e.g. const enum rendering). |
testdata/baselines/reference/submodule/compiler/privateFieldsInClassExpressionDeclaration.js |
Updates compiler baseline output for private fields in .d.ts emit. |
testdata/baselines/reference/submodule/compiler/privateFieldsInClassExpressionDeclaration.js.diff |
Updates compiler baseline diff for the same private field emit change. |
...aselines/reference/fourslash/quickInfo/quickInfoDisplayPartsTypeParameterInFunction.baseline
Show resolved
Hide resolved
...a/baselines/reference/fourslash/quickInfo/quickInfoDisplayPartsTypeParameterInClass.baseline
Show resolved
Hide resolved
|
One icky thing is that |
| levels = []int{0} | ||
| } | ||
| for _, level := range levels { | ||
| for i, level := range levels { |
There was a problem hiding this comment.
I wonder if a better way to test this would be to just make the tests allow you to specify a maximum verbosity level, and then make fourslash check if every level from 0 to that can be expanded, and that it cannot be further expanded.
There was a problem hiding this comment.
Yeah, I just didn't want to make every test manual, so this was my workaround while debugging these. 😄
| // canPossiblyExpandType returns true if it's possible the type or one of its components can be expanded. | ||
| // At maxExpansionDepth <= 0, no expansion will occur so we return false to allow type-node reuse. | ||
| // canPossiblyExpandType reports whether we are actively expanding types (depth < maxExpansionDepth), | ||
| // meaning type-node reuse should be skipped so typeToTypeNode can expand named types. |
There was a problem hiding this comment.
Why do we need this function now? IIRC the difference between canPossiblyExpandType and shouldExpandType is that canPossiblyExpandType was meant to be called to see if we should avoid node reuse, but now we're not really avoiding node reuse anyways, so I don't quite get why not always use shouldExpandType.
There was a problem hiding this comment.
We don't; it actually should have just been reduced to being a depth check. Refactored it again.
| // as its structural form during hover expansion. Filters out lib types. | ||
| // When isAlias is true, checks whether t's alias symbol is from user code (not lib). | ||
| func (b *NodeBuilderImpl) isExpandableType(t *Type, isAlias bool) bool { | ||
| if isAlias { |
There was a problem hiding this comment.
I can't really picture it in my head how this reflects the behavior of walking through a type and seeing if any of its parts are expandable. For instance, what if the type we're checking is an object literal type with a property whose type is an alias? How would that work?
There was a problem hiding this comment.
Basically, it doesn't; this is only surface level, and the type traversal is in the caller during printing.
Closes #2457
This is a proposed VS Code feature. To make this work, we add the new API ontop of the LSP, then disable the LSP client's hover provider, in favor of one with the feature.