Skip to content

Commit db13113

Browse files
Orta Theroxsandersn
Orta Therox
andauthored
Don't inherit jsdoc tags from overloaded signatures (#43165) (#43180)
* Don't inherit jsdoc tags from overloaded signatures (#43165) Previously, when getting jsdoc for signatures, the services layer would get the jsdoc tags for the base symbol of a signature if it was present. This is fine except when the base was overloaded. In that case, the multiple signatures of the overload would all contribute jsdoc, which is not correct. A more correct fix would be to resolve overloads to the base, but the compiler doesn't have this capability and adding it or jury-rigging it seems like it would be complex, inappropriate for a fix to ship in a patch version. Co-authored-by: Orta Therox <git@orta.io> Co-authored-by: Orta Therox <git@orta.io> * Update baseline Co-authored-by: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com>
1 parent e462dfa commit db13113

File tree

3 files changed

+178
-11
lines changed

3 files changed

+178
-11
lines changed

src/services/services.ts

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -550,7 +550,7 @@ namespace ts {
550550

551551
getJsDocTags(): JSDocTagInfo[] {
552552
if (this.jsDocTags === undefined) {
553-
this.jsDocTags = this.declaration ? getJsDocTags([this.declaration], this.checker) : [];
553+
this.jsDocTags = this.declaration ? getJsDocTagsOfSignature(this.declaration, this.checker) : [];
554554
}
555555
return this.jsDocTags;
556556
}
@@ -565,15 +565,13 @@ namespace ts {
565565
return getJSDocTags(node).some(tag => tag.tagName.text === "inheritDoc");
566566
}
567567

568-
function getJsDocTags(declarations: Declaration[], checker: TypeChecker): JSDocTagInfo[] {
569-
let tags = JsDoc.getJsDocTagsFromDeclarations(declarations);
570-
if (tags.length === 0 || declarations.some(hasJSDocInheritDocTag)) {
571-
forEachUnique(declarations, declaration => {
572-
const inheritedTags = findBaseOfDeclaration(checker, declaration, symbol => symbol.getJsDocTags());
573-
if (inheritedTags) {
574-
tags = [...inheritedTags, ...tags];
575-
}
576-
});
568+
function getJsDocTagsOfSignature(declaration: Declaration, checker: TypeChecker): JSDocTagInfo[] {
569+
let tags = JsDoc.getJsDocTagsFromDeclarations([declaration]);
570+
if (tags.length === 0 || hasJSDocInheritDocTag(declaration)) {
571+
const inheritedTags = findBaseOfDeclaration(checker, declaration, symbol => symbol.declarations?.length === 1 ? symbol.getJsDocTags() : undefined);
572+
if (inheritedTags) {
573+
tags = [...inheritedTags, ...tags];
574+
}
577575
}
578576
return tags;
579577
}
@@ -592,7 +590,7 @@ namespace ts {
592590
return doc;
593591
}
594592

595-
function findBaseOfDeclaration<T>(checker: TypeChecker, declaration: Declaration, cb: (symbol: Symbol) => T[]): T[] | undefined {
593+
function findBaseOfDeclaration<T>(checker: TypeChecker, declaration: Declaration, cb: (symbol: Symbol) => T[] | undefined): T[] | undefined {
596594
return firstDefined(declaration.parent ? getAllSuperTypeNodes(declaration.parent) : emptyArray, superTypeNode => {
597595
const symbol = checker.getPropertyOfType(checker.getTypeAtLocation(superTypeNode), declaration.symbol.name);
598596
return symbol ? cb(symbol) : undefined;
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
[
2+
{
3+
"marker": {
4+
"fileName": "/tests/cases/fourslash/deprecatedInheritedJSDocOverload.ts",
5+
"position": 1183
6+
},
7+
"quickInfo": {
8+
"kind": "method",
9+
"kindModifiers": "",
10+
"textSpan": {
11+
"start": 1174,
12+
"length": 9
13+
},
14+
"displayParts": [
15+
{
16+
"text": "(",
17+
"kind": "punctuation"
18+
},
19+
{
20+
"text": "method",
21+
"kind": "text"
22+
},
23+
{
24+
"text": ")",
25+
"kind": "punctuation"
26+
},
27+
{
28+
"text": " ",
29+
"kind": "space"
30+
},
31+
{
32+
"text": "ThingWithDeprecations",
33+
"kind": "interfaceName"
34+
},
35+
{
36+
"text": "<",
37+
"kind": "punctuation"
38+
},
39+
{
40+
"text": "void",
41+
"kind": "keyword"
42+
},
43+
{
44+
"text": ">",
45+
"kind": "punctuation"
46+
},
47+
{
48+
"text": ".",
49+
"kind": "punctuation"
50+
},
51+
{
52+
"text": "subscribe",
53+
"kind": "methodName"
54+
},
55+
{
56+
"text": "(",
57+
"kind": "punctuation"
58+
},
59+
{
60+
"text": "observer",
61+
"kind": "parameterName"
62+
},
63+
{
64+
"text": "?",
65+
"kind": "punctuation"
66+
},
67+
{
68+
"text": ":",
69+
"kind": "punctuation"
70+
},
71+
{
72+
"text": " ",
73+
"kind": "space"
74+
},
75+
{
76+
"text": "PartialObserver",
77+
"kind": "interfaceName"
78+
},
79+
{
80+
"text": "<",
81+
"kind": "punctuation"
82+
},
83+
{
84+
"text": "void",
85+
"kind": "keyword"
86+
},
87+
{
88+
"text": ">",
89+
"kind": "punctuation"
90+
},
91+
{
92+
"text": ")",
93+
"kind": "punctuation"
94+
},
95+
{
96+
"text": ":",
97+
"kind": "punctuation"
98+
},
99+
{
100+
"text": " ",
101+
"kind": "space"
102+
},
103+
{
104+
"text": "Subscription",
105+
"kind": "interfaceName"
106+
},
107+
{
108+
"text": " ",
109+
"kind": "space"
110+
},
111+
{
112+
"text": "(",
113+
"kind": "punctuation"
114+
},
115+
{
116+
"text": "+",
117+
"kind": "operator"
118+
},
119+
{
120+
"text": "2",
121+
"kind": "numericLiteral"
122+
},
123+
{
124+
"text": " ",
125+
"kind": "space"
126+
},
127+
{
128+
"text": "overloads",
129+
"kind": "text"
130+
},
131+
{
132+
"text": ")",
133+
"kind": "punctuation"
134+
}
135+
],
136+
"documentation": []
137+
}
138+
}
139+
]
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
2+
//// interface PartialObserver<T> {}
3+
//// interface Subscription {}
4+
//// interface Unsubscribable {}
5+
////
6+
//// export interface Subscribable<T> {
7+
//// subscribe(observer?: PartialObserver<T>): Unsubscribable;
8+
//// /** @deprecated Base deprecation 1 */
9+
//// subscribe(next: null | undefined, error: null | undefined, complete: () => void): Unsubscribable;
10+
//// /** @deprecated Base deprecation 2 */
11+
//// subscribe(next: null | undefined, error: (error: any) => void, complete?: () => void): Unsubscribable;
12+
//// /** @deprecated Base deprecation 3 */
13+
//// subscribe(next: (value: T) => void, error: null | undefined, complete: () => void): Unsubscribable;
14+
//// subscribe(next?: (value: T) => void, error?: (error: any) => void, complete?: () => void): Unsubscribable;
15+
//// }
16+
17+
//// interface ThingWithDeprecations<T> extends Subscribable<T> {
18+
//// subscribe(observer?: PartialObserver<T>): Subscription;
19+
//// /** @deprecated 'real' deprecation */
20+
//// subscribe(next: null | undefined, error: null | undefined, complete: () => void): Subscription;
21+
//// /** @deprecated 'real' deprecation */
22+
//// subscribe(next: null | undefined, error: (error: any) => void, complete?: () => void): Subscription;
23+
//// }
24+
25+
//// declare const a: ThingWithDeprecations<void>
26+
//// a.subscribe/**/(() => {
27+
//// console.log('something happened');
28+
//// });
29+
30+
verify.baselineQuickInfo();

0 commit comments

Comments
 (0)