Fix namespaced JSX intrinsic completions and hover#4366
Conversation
Co-authored-by: jakebailey <5341706+jakebailey@users.noreply.github.com>
Co-authored-by: jakebailey <5341706+jakebailey@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Fixes language-service hover and completions for namespaced JSX intrinsic elements (e.g. <foo:bar />) by ensuring the LS uses the normalized “quick info” node for symbol resolution and by treating JsxNamespacedName (and its identifiers) as valid JSX element contexts for completion.
Changes:
- Adjust hover symbol resolution to use the normalized quick-info node (improves hover on
JsxNamespacedNameand related nodes likeimport.meta). - Extend JSX completion context detection to handle
JsxNamespacedNameand its child identifiers, restoring intrinsic attribute completions. - Add/refresh fourslash coverage and update quick-info baselines for the corrected hover output.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
internal/ls/hover.go |
Uses the normalized quick-info node for symbol lookup so hover info matches the displayed range/node. |
internal/ls/completions.go |
Treats JsxNamespacedName and identifiers within it as valid JSX opening-element contexts for attribute completions. |
internal/fourslash/tests/quickInfoJsxNamespacedIntrinsic_test.go |
New regression test for quick info on namespaced JSX intrinsic tags/attributes. |
internal/fourslash/tests/completionsInJsxTag_test.go |
New regression test for intrinsic attribute completions on namespaced JSX intrinsic tags. |
testdata/baselines/reference/fourslash/quickInfo/quickInfoOnJsxNamespacedName.baseline |
Baseline update: quick info now produced for the full namespaced tag. |
testdata/baselines/reference/fourslash/quickInfo/quickInfoImportMeta.baseline |
Baseline update: hover now resolves to ImportMeta interface docs (consistent with normalized-node symbol resolution). |
| <foo:ba/*tag*/r fo/*attr*/o />` | ||
| f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) | ||
| defer done() | ||
| f.VerifyQuickInfoAt(t, "tag", "(property) JSX.IntrinsicElements[\"foo:bar\"]: {\n foo: boolean;\n bar: string;\n}", "Element docs") |
|
@copilot a now non-failing test needs to be removed from internal/fourslash/_scripts/failingTests.txt |
The hover.go fix (using rangeNode for symbol lookup) now makes TestQuickInfoOnNewKeyword01 pass, so it no longer needs to be listed as a failing test. Co-authored-by: jakebailey <5341706+jakebailey@users.noreply.github.com>
Done. |
| @@ -386,7 +386,6 @@ TestQuickInfoOnInternalAliases | |||
| TestQuickInfoOnJsxNamespacedNameWithDoc1 | |||
There was a problem hiding this comment.
While we're at it, we should either figure out what's preventing this (and other JSX namespace tests) from passing, or turn this into a manual test.
There was a problem hiding this comment.
Investigated. The test was failing because getContainingObjectLiteralElementWorker in internal/ls/utilities.go didn't handle KindJsxNamespacedName. When hovering over a JSX attribute like prop:foo, the node returned by getNodeForQuickInfo is the JsxNamespacedName; without this case, the function returned nil instead of the enclosing JsxAttribute, causing getSymbolAtLocationForQuickInfo to fall through to checker.GetSymbolAtLocation, which returns the attribute's own declaration symbol (wrong name, no docs) rather than the contextual property symbol ('prop:foo': string with JSDoc).
Fixed in the latest commit by adding ast.KindJsxNamespacedName alongside ast.KindIdentifier in the switch, mirroring TypeScript's services.ts. TestQuickInfoOnJsxNamespacedNameWithDoc1 now passes and is removed from failingTests.txt.
Co-authored-by: jakebailey <5341706+jakebailey@users.noreply.github.com>
Namespaced JSX intrinsic elements such as
<foo:bar />type-check correctly, but the language service missed attribute completions and hover info for the tag and its attributes.Completions
Treat
JsxNamespacedNametag nodes, and their child identifiers, as valid JSX opening-element contexts.Restores intrinsic attribute completions in positions like:
Hover
Coverage