Skip to content

Commit aba0ef8

Browse files
Gerrit0Nokel81
andcommitted
Detect duplicate nodes when discovering comments
Closes #2359 Resolves #2437 Co-Authored-By: Sebastian Malton <sebastian@malton.name>
1 parent c9103fc commit aba0ef8

File tree

6 files changed

+43
-7
lines changed

6 files changed

+43
-7
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,12 @@
55
- Fixed default option values on options declared by plugins in packages mode, #2433.
66
- `gitRevision` will now be replaced in `sourceLinkTemplate`, #2434.
77
- Improved handling of function-modules created with `Object.assign`, #2436.
8+
- TypeDoc will no longer warn about duplicate comments with warnings which point to a single comment, #2437
89
- Fixed an infinite loop when `skipLibCheck` is used to ignore some compiler errors, #2438.
910

1011
### Thanks!
1112

13+
- @Nokel81
1214
- @ocavue
1315
- @swarnpallav
1416

scripts/testcase.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,11 @@ async function main() {
4949
const tokens = lexer.lex(data.body);
5050

5151
const code = /** @type {marked.marked.Tokens.Code} */ (
52-
tokens.find((tok) => tok.type === "code")
52+
tokens.find(
53+
(tok) =>
54+
tok.type === "code" &&
55+
["ts", "tsx", "js", "jsx"].includes(tok.lang || ""),
56+
) || tokens.find((tok) => tok.type === "code")
5357
);
5458
if (!code) {
5559
console.log("No codeblock found");

src/lib/converter/comments/discovery.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,14 +140,16 @@ export function discoverComment(
140140
const reverse = !symbol.declarations?.some(ts.isSourceFile);
141141

142142
const discovered: DiscoveredComment[] = [];
143+
const seen = new Set<ts.Node>();
143144

144145
for (const decl of symbol.declarations || []) {
145146
const text = decl.getSourceFile().text;
146147
if (wantedKinds[kind].includes(decl.kind)) {
147148
const node = declarationToCommentNode(decl);
148-
if (!node) {
149+
if (!node || seen.has(node)) {
149150
continue;
150151
}
152+
seen.add(node);
151153

152154
// Special behavior here! We temporarily put the implementation comment
153155
// on the reflection which contains all the signatures. This lets us pull

src/lib/converter/symbols.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -856,10 +856,11 @@ function convertVariable(
856856
exportSymbol?: ts.Symbol,
857857
) {
858858
const declaration = symbol.getDeclarations()?.[0];
859-
assert(declaration);
860859

861860
const comment = context.getComment(symbol, ReflectionKind.Variable);
862-
const type = context.checker.getTypeOfSymbolAtLocation(symbol, declaration);
861+
const type = declaration
862+
? context.checker.getTypeOfSymbolAtLocation(symbol, declaration)
863+
: context.checker.getTypeOfSymbol(symbol);
863864

864865
if (
865866
isEnumLike(context.checker, type, declaration) &&
@@ -883,7 +884,7 @@ function convertVariable(
883884
);
884885

885886
let typeNode: ts.TypeNode | undefined;
886-
if (ts.isVariableDeclaration(declaration)) {
887+
if (declaration && ts.isVariableDeclaration(declaration)) {
887888
// Otherwise we might have destructuring
888889
typeNode = declaration.type;
889890
}
@@ -902,8 +903,12 @@ function convertVariable(
902903
return ts.SymbolFlags.Property;
903904
}
904905

905-
function isEnumLike(checker: ts.TypeChecker, type: ts.Type, location: ts.Node) {
906-
if (!hasAllFlags(type.flags, ts.TypeFlags.Object)) {
906+
function isEnumLike(
907+
checker: ts.TypeChecker,
908+
type: ts.Type,
909+
location?: ts.Node,
910+
) {
911+
if (!location || !hasAllFlags(type.flags, ts.TypeFlags.Object)) {
907912
return false;
908913
}
909914

src/test/converter2/issues/gh2437.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
export interface TemplatedTypeBase {
2+
/**
3+
* Doc here
4+
*/
5+
prop?: string[];
6+
}
7+
8+
export interface One extends TemplatedTypeBase {}
9+
10+
export interface Two extends TemplatedTypeBase {}
11+
12+
export type Type = One | Two;
13+
14+
export function isTemplateInstance(
15+
type: Type,
16+
): type is Type & { prop: string[] } {
17+
return true;
18+
}

src/test/issues.c2.test.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1213,6 +1213,11 @@ describe("Issue Tests", () => {
12131213
);
12141214
});
12151215

1216+
it("Does not warn due to the diamond problem in comment discovery #2437", () => {
1217+
convert();
1218+
logger.expectNoOtherMessages();
1219+
});
1220+
12161221
it("Handles recursive aliases without looping infinitely #2438", () => {
12171222
const bad = query(convert(), "Bad");
12181223
equal(bad.kind, ReflectionKind.Interface);

0 commit comments

Comments
 (0)