Skip to content

Commit 2c14a1c

Browse files
authored
fix(55650): Wrong/missing quick info in JSDoc @implements tag (microsoft#56884)
1 parent 4bcbc16 commit 2c14a1c

File tree

3 files changed

+353
-2
lines changed

3 files changed

+353
-2
lines changed

src/compiler/utilities.ts

+9-2
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,7 @@ import {
282282
isJSDoc,
283283
isJSDocAugmentsTag,
284284
isJSDocFunctionType,
285+
isJSDocImplementsTag,
285286
isJSDocLinkLike,
286287
isJSDocMemberName,
287288
isJSDocNameReference,
@@ -2452,7 +2453,7 @@ export function isPartOfTypeNode(node: Node): boolean {
24522453
case SyntaxKind.VoidKeyword:
24532454
return node.parent.kind !== SyntaxKind.VoidExpression;
24542455
case SyntaxKind.ExpressionWithTypeArguments:
2455-
return isHeritageClause(node.parent) && !isExpressionWithTypeArgumentsInClassExtendsClause(node);
2456+
return isPartOfTypeExpressionWithTypeArguments(node);
24562457
case SyntaxKind.TypeParameter:
24572458
return node.parent.kind === SyntaxKind.MappedType || node.parent.kind === SyntaxKind.InferType;
24582459

@@ -2491,7 +2492,7 @@ export function isPartOfTypeNode(node: Node): boolean {
24912492
}
24922493
switch (parent.kind) {
24932494
case SyntaxKind.ExpressionWithTypeArguments:
2494-
return isHeritageClause(parent.parent) && !isExpressionWithTypeArgumentsInClassExtendsClause(parent);
2495+
return isPartOfTypeExpressionWithTypeArguments(parent);
24952496
case SyntaxKind.TypeParameter:
24962497
return node === (parent as TypeParameterDeclaration).constraint;
24972498
case SyntaxKind.JSDocTemplateTag:
@@ -2527,6 +2528,12 @@ export function isPartOfTypeNode(node: Node): boolean {
25272528
return false;
25282529
}
25292530

2531+
function isPartOfTypeExpressionWithTypeArguments(node: Node) {
2532+
return isJSDocImplementsTag(node.parent)
2533+
|| isJSDocAugmentsTag(node.parent)
2534+
|| isHeritageClause(node.parent) && !isExpressionWithTypeArgumentsInClassExtendsClause(node);
2535+
}
2536+
25302537
/** @internal */
25312538
export function isChildOfNodeWithKind(node: Node, kind: SyntaxKind): boolean {
25322539
while (node) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,308 @@
1+
// === QuickInfo ===
2+
=== /b.js ===
3+
// import * as _a from "./a.js";
4+
// /**
5+
// * @implements {_a.Foo}
6+
// ^^^
7+
// | ----------------------------------------------------------------------
8+
// | type Foo = {
9+
// | getName: _a.Bar;
10+
// | }
11+
// | ----------------------------------------------------------------------
12+
// */
13+
// class C1 { }
14+
//
15+
// /**
16+
// * @extends {_a.Foo}
17+
// ^^^
18+
// | ----------------------------------------------------------------------
19+
// | type Foo = {
20+
// | getName: _a.Bar;
21+
// | }
22+
// | ----------------------------------------------------------------------
23+
// */
24+
// class C2 { }
25+
//
26+
// /**
27+
// * @augments {_a.Foo}
28+
// ^^^
29+
// | ----------------------------------------------------------------------
30+
// | type Foo = {
31+
// | getName: _a.Bar;
32+
// | }
33+
// | ----------------------------------------------------------------------
34+
// */
35+
// class C3 { }
36+
37+
[
38+
{
39+
"marker": {
40+
"fileName": "/b.js",
41+
"position": 56,
42+
"name": "1"
43+
},
44+
"item": {
45+
"kind": "type",
46+
"kindModifiers": "",
47+
"textSpan": {
48+
"start": 53,
49+
"length": 3
50+
},
51+
"displayParts": [
52+
{
53+
"text": "type",
54+
"kind": "keyword"
55+
},
56+
{
57+
"text": " ",
58+
"kind": "space"
59+
},
60+
{
61+
"text": "Foo",
62+
"kind": "aliasName"
63+
},
64+
{
65+
"text": " ",
66+
"kind": "space"
67+
},
68+
{
69+
"text": "=",
70+
"kind": "operator"
71+
},
72+
{
73+
"text": " ",
74+
"kind": "space"
75+
},
76+
{
77+
"text": "{",
78+
"kind": "punctuation"
79+
},
80+
{
81+
"text": "\n",
82+
"kind": "lineBreak"
83+
},
84+
{
85+
"text": " ",
86+
"kind": "space"
87+
},
88+
{
89+
"text": "getName",
90+
"kind": "propertyName"
91+
},
92+
{
93+
"text": ":",
94+
"kind": "punctuation"
95+
},
96+
{
97+
"text": " ",
98+
"kind": "space"
99+
},
100+
{
101+
"text": "_a",
102+
"kind": "aliasName"
103+
},
104+
{
105+
"text": ".",
106+
"kind": "punctuation"
107+
},
108+
{
109+
"text": "Bar",
110+
"kind": "aliasName"
111+
},
112+
{
113+
"text": ";",
114+
"kind": "punctuation"
115+
},
116+
{
117+
"text": "\n",
118+
"kind": "lineBreak"
119+
},
120+
{
121+
"text": "}",
122+
"kind": "punctuation"
123+
}
124+
],
125+
"documentation": []
126+
}
127+
},
128+
{
129+
"marker": {
130+
"fileName": "/b.js",
131+
"position": 99,
132+
"name": "2"
133+
},
134+
"item": {
135+
"kind": "type",
136+
"kindModifiers": "",
137+
"textSpan": {
138+
"start": 96,
139+
"length": 3
140+
},
141+
"displayParts": [
142+
{
143+
"text": "type",
144+
"kind": "keyword"
145+
},
146+
{
147+
"text": " ",
148+
"kind": "space"
149+
},
150+
{
151+
"text": "Foo",
152+
"kind": "aliasName"
153+
},
154+
{
155+
"text": " ",
156+
"kind": "space"
157+
},
158+
{
159+
"text": "=",
160+
"kind": "operator"
161+
},
162+
{
163+
"text": " ",
164+
"kind": "space"
165+
},
166+
{
167+
"text": "{",
168+
"kind": "punctuation"
169+
},
170+
{
171+
"text": "\n",
172+
"kind": "lineBreak"
173+
},
174+
{
175+
"text": " ",
176+
"kind": "space"
177+
},
178+
{
179+
"text": "getName",
180+
"kind": "propertyName"
181+
},
182+
{
183+
"text": ":",
184+
"kind": "punctuation"
185+
},
186+
{
187+
"text": " ",
188+
"kind": "space"
189+
},
190+
{
191+
"text": "_a",
192+
"kind": "aliasName"
193+
},
194+
{
195+
"text": ".",
196+
"kind": "punctuation"
197+
},
198+
{
199+
"text": "Bar",
200+
"kind": "aliasName"
201+
},
202+
{
203+
"text": ";",
204+
"kind": "punctuation"
205+
},
206+
{
207+
"text": "\n",
208+
"kind": "lineBreak"
209+
},
210+
{
211+
"text": "}",
212+
"kind": "punctuation"
213+
}
214+
],
215+
"documentation": []
216+
}
217+
},
218+
{
219+
"marker": {
220+
"fileName": "/b.js",
221+
"position": 143,
222+
"name": "3"
223+
},
224+
"item": {
225+
"kind": "type",
226+
"kindModifiers": "",
227+
"textSpan": {
228+
"start": 140,
229+
"length": 3
230+
},
231+
"displayParts": [
232+
{
233+
"text": "type",
234+
"kind": "keyword"
235+
},
236+
{
237+
"text": " ",
238+
"kind": "space"
239+
},
240+
{
241+
"text": "Foo",
242+
"kind": "aliasName"
243+
},
244+
{
245+
"text": " ",
246+
"kind": "space"
247+
},
248+
{
249+
"text": "=",
250+
"kind": "operator"
251+
},
252+
{
253+
"text": " ",
254+
"kind": "space"
255+
},
256+
{
257+
"text": "{",
258+
"kind": "punctuation"
259+
},
260+
{
261+
"text": "\n",
262+
"kind": "lineBreak"
263+
},
264+
{
265+
"text": " ",
266+
"kind": "space"
267+
},
268+
{
269+
"text": "getName",
270+
"kind": "propertyName"
271+
},
272+
{
273+
"text": ":",
274+
"kind": "punctuation"
275+
},
276+
{
277+
"text": " ",
278+
"kind": "space"
279+
},
280+
{
281+
"text": "_a",
282+
"kind": "aliasName"
283+
},
284+
{
285+
"text": ".",
286+
"kind": "punctuation"
287+
},
288+
{
289+
"text": "Bar",
290+
"kind": "aliasName"
291+
},
292+
{
293+
"text": ";",
294+
"kind": "punctuation"
295+
},
296+
{
297+
"text": "\n",
298+
"kind": "lineBreak"
299+
},
300+
{
301+
"text": "}",
302+
"kind": "punctuation"
303+
}
304+
],
305+
"documentation": []
306+
}
307+
}
308+
]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/// <reference path="fourslash.ts" />
2+
3+
// @allowJs: true
4+
// @checkJs: true
5+
// @filename: /a.js
6+
/////**
7+
//// * @callback Bar
8+
//// * @param {string} name
9+
//// * @returns {string}
10+
//// */
11+
////
12+
/////**
13+
//// * @typedef Foo
14+
//// * @property {Bar} getName
15+
//// */
16+
////export const foo = 1;
17+
18+
// @filename: /b.js
19+
////import * as _a from "./a.js";
20+
/////**
21+
//// * @implements {_a.Foo/*1*/}
22+
//// */
23+
////class C1 { }
24+
////
25+
/////**
26+
//// * @extends {_a.Foo/*2*/}
27+
//// */
28+
////class C2 { }
29+
////
30+
/////**
31+
//// * @augments {_a.Foo/*3*/}
32+
//// */
33+
////class C3 { }
34+
35+
goTo.file("/b.js")
36+
verify.baselineQuickInfo();

0 commit comments

Comments
 (0)