Skip to content

Commit 8ebdb96

Browse files
committed
Dedupe inherited jsdoc comments
JSDoc on own properties was already deduped, but inherited jsdoc was incorrectly not deduped. Fixes #32708
1 parent 178417f commit 8ebdb96

File tree

4 files changed

+35
-21
lines changed

4 files changed

+35
-21
lines changed

src/services/jsDoc.ts

-19
Original file line numberDiff line numberDiff line change
@@ -158,25 +158,6 @@ namespace ts.JsDoc {
158158
}
159159
}
160160

161-
/**
162-
* Iterates through 'array' by index and performs the callback on each element of array until the callback
163-
* returns a truthy value, then returns that value.
164-
* If no such value is found, the callback is applied to each element of array and undefined is returned.
165-
*/
166-
function forEachUnique<T, U>(array: readonly T[] | undefined, callback: (element: T, index: number) => U): U | undefined {
167-
if (array) {
168-
for (let i = 0; i < array.length; i++) {
169-
if (array.indexOf(array[i]) === i) {
170-
const result = callback(array[i], i);
171-
if (result) {
172-
return result;
173-
}
174-
}
175-
}
176-
}
177-
return undefined;
178-
}
179-
180161
export function getJSDocTagNameCompletions(): CompletionEntry[] {
181162
return jsDocTagNameCompletionEntries || (jsDocTagNameCompletionEntries = map(jsDocTagNames, tagName => {
182163
return {

src/services/services.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -527,11 +527,11 @@ namespace ts {
527527

528528
let doc = JsDoc.getJsDocCommentsFromDeclarations(declarations);
529529
if (doc.length === 0 || declarations.some(hasJSDocInheritDocTag)) {
530-
for (const declaration of declarations) {
530+
forEachUnique(declarations, declaration => {
531531
const inheritedDocs = findInheritedJSDocComments(declaration, declaration.symbol.name, checker!); // TODO: GH#18217
532532
// TODO: GH#16312 Return a ReadonlyArray, avoid copying inheritedDocs
533533
if (inheritedDocs) doc = doc.length === 0 ? inheritedDocs.slice() : inheritedDocs.concat(lineBreakPart(), doc);
534-
}
534+
});
535535
}
536536
return doc;
537537
}

src/services/utilities.ts

+19
Original file line numberDiff line numberDiff line change
@@ -1458,6 +1458,25 @@ namespace ts {
14581458
export function documentSpansEqual(a: DocumentSpan, b: DocumentSpan): boolean {
14591459
return a.fileName === b.fileName && textSpansEqual(a.textSpan, b.textSpan);
14601460
}
1461+
1462+
/**
1463+
* Iterates through 'array' by index and performs the callback on each element of array until the callback
1464+
* returns a truthy value, then returns that value.
1465+
* If no such value is found, the callback is applied to each element of array and undefined is returned.
1466+
*/
1467+
export function forEachUnique<T, U>(array: readonly T[] | undefined, callback: (element: T, index: number) => U): U | undefined {
1468+
if (array) {
1469+
for (let i = 0; i < array.length; i++) {
1470+
if (array.indexOf(array[i]) === i) {
1471+
const result = callback(array[i], i);
1472+
if (result) {
1473+
return result;
1474+
}
1475+
}
1476+
}
1477+
}
1478+
return undefined;
1479+
}
14611480
}
14621481

14631482
// Display-part writer helpers
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/// <reference path='fourslash.ts'/>
2+
// #32708
3+
4+
////interface I<T> {
5+
//// /** only once please */
6+
//// t: T
7+
////}
8+
////interface C<T> extends I<T> {
9+
//// t: T
10+
////}
11+
////declare var cnsb: C<number> & C<string> & C<boolean>;
12+
////cnsb.t/**/
13+
14+
verify.quickInfoAt("", "(property) C<T>.t: never", "only once please");

0 commit comments

Comments
 (0)