Repository navigation
Show every JSDoc comment on an alias chain in hover and completions - #64657
patrick kettner (patrickkettner) wants to merge 3 commits into
Conversation
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Merged alias symbols may read JSDoc from a non-alias declaration.
Review effort: Balanced
Findings: 1
What changed in this PR
Restores alias-authored JSDoc in hover and completion details.
Changes:
- Adds alias declaration documentation lookup with call-site precedence.
- Adds fourslash coverage and hover baseline.
| File | Description |
|---|---|
tsc/internal/ls/hover.go |
Resolves documentation from alias declarations. |
tsc/internal/fourslash/tests/hoverImportEqualsAliasJSDoc_test.go |
Tests hover and completions. |
tsc/testdata/baselines/reference/fourslash/quickInfo/hoverImportEqualsAliasJSDoc.baseline |
Records expected hover output. |
💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.
| if symbol == nil || symbol.Flags&ast.SymbolFlagsAlias == 0 { | ||
| return "" | ||
| } | ||
| return getDocumentationFromDeclaration(getMappedLocation, c, symbol, core.FirstOrNil(symbol.Declarations), node, contentFormat, commentOnly) |
|
@microsoft-github-policy-service agree |
import x = a.x alias in hover and completions
There was a problem hiding this comment.
Honestly, I think the whole a.fn and a.fn() yielding different documentation comment sources thing is weird. It's not our TS 6.0 behavior - AFAIK we just used the implementation docs everywhere.
Take this example:
// @filename: src/lib.ts
/**
* Doc on impl
*/
export function foo() {}
// @filename: src/main.ts
import * as lib from "./lib.js";
/**
* Doc on export import alias
*/
export import bar = lib.foo
// @filename: src/use.ts
import {
/**
* Doc on import alias
*/
bar
} from "./main.js"
bar()
barIt's subjective, but IMHO, if we wanna improve things, quickinfo documentation on both bar refs (the call and the bare ref) should be
Doc on import alias
Doc on export import alias
Doc on impl
anything only looking at a single declaration in an alias chain is gonna potentially miss something otherwise.
|
yeah, that would be my preference too. I kept this at 6.0 parity to keep it small (on 6.0.3 the bare ref shows the alias comment and the call shows the impl's, same with |
827b307 to
bcfcd25
Compare
|
Yeah, if we're gonna change anything here, I'd wanna make it consistent across reference site kinds and include all the docs possible, for sure. |
|
what about tags? like if the alias and the impl have the same description but the tags are different /** Does the thing.
* @since 2.0 */
export function doThing(): void
/** Does the thing.
* @since 1.0 */
export import doThing = lib.doThingshould hover show both |
The only "semantic" tags are the type-providing ones, and those only work on the implementation anyway. Any other tag is basically just docs anyway, so I'd imagine they're shown inline. |
A comment on `import x = a.x` was never read. Hover and completion details showed the target's comment, or nothing when the target had none. 6.0 shows the alias's own comment, except on a call, where the resolved signature's documentation still wins.
On a merged symbol Declarations[0] is the namespace, so the alias comment was never read. An alias comment with no description was hiding the target's.
A reference to an alias showed the comment of one declaration on its chain, and which one depended on whether the name was called, so a comment on an import binding or a re-export was lost at some sites. getDocumentationForSymbol now walks the alias chain and joins each alias declaration's comment, outermost first, ahead of the implementation's, with the tag sections following in the same order. The parser attaches JSDoc to import specifiers the way it already does for export specifiers, and checkAliasSymbol no longer reports a deprecated specifier against itself.
import x = a.x alias in hover and completionsbcfcd25 to
2d474ec
Compare

Fixes #64655
Analysis
getDocumentationForSymbolshows one declaration's comment and which one depends on the reference site. Theimport x = a.xcomment is attached by the parser and never read, and a comment on an import specifier is never attached at all (6.0 does not attach one either).Fix
Every alias on the chain contributes the JSDoc on its own declaration, outermost first, and the implementation contributes what it did before (the resolved signature, root symbols, the picked declaration, the alias target). Descriptions are joined with a newline, then the tag sections follow in the same order, exact duplicates dropped. The reference site only decides which implementation declaration is picked, so
barandbar()show the same lines.The parser attaches JSDoc to import specifiers the way it does to export specifiers, including the same-line form inside the braces.
import { /** @deprecated */ x }now deprecatesx, socheckAliasSymbolskips the suggestion a specifier would raise on itself.quickInfoAliasandquickInfoAliasVSchange because the specifier comment in that test (Doc 3) now shows ahead of the target's.Copilot Checklist
I successfully ran the applicable command at the end of my session, and it completed without error:
I used Claude Code to write the patch and the tests, and I have read and reviewed both.