Skip to content

Commit 23008f6

Browse files
committed
Improve link resolution prioritization
Ref: Gerrit0/typedoc-plugin-zod#8
1 parent 2c10f67 commit 23008f6

File tree

6 files changed

+75
-11
lines changed

6 files changed

+75
-11
lines changed

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ title: Changelog
88

99
- `@include` and `@includeCode` now work in the readme file, #2814.
1010
- TypeDoc will now avoid making references to references, #2811.
11+
- Improved link resolution logic to prioritize type alias properties with the
12+
same symbol over type literal properties within function parameters.
1113

1214
## v0.27.5 (2024-12-14)
1315

src/lib/converter/comments/linkResolver.ts

+27-8
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
parseDeclarationReference,
1414
} from "./declarationReference.js";
1515
import { resolveDeclarationReference } from "./declarationReferenceResolver.js";
16+
import { maxElementByScore } from "../../utils/array.js";
1617

1718
const urlPrefix = /^(http|ftp)s?:\/\//;
1819

@@ -138,14 +139,32 @@ function resolveLinkTag(
138139

139140
if (tsTargets.length) {
140141
// Find the target most likely to have a real url in the generated documentation
141-
target =
142-
tsTargets.find((r) => r.kindOf(ReflectionKind.SomeExport)) ||
143-
tsTargets.find(
144-
(r) =>
145-
r.kindOf(ReflectionKind.SomeMember) &&
146-
r.parent?.kindOf(ReflectionKind.SomeExport),
147-
) ||
148-
tsTargets[0];
142+
// 1. A direct export (class, interface, variable)
143+
// 2. A property of a direct export (class/interface property)
144+
// 3. A property of a type of an export (property on type alias)
145+
// 4. Whatever the first symbol found was
146+
target = maxElementByScore(tsTargets, (r) => {
147+
if (r.kindOf(ReflectionKind.SomeExport)) {
148+
return 4;
149+
}
150+
if (
151+
r.kindOf(ReflectionKind.SomeMember) &&
152+
r.parent?.kindOf(ReflectionKind.SomeExport)
153+
) {
154+
return 3;
155+
}
156+
if (
157+
r.kindOf(ReflectionKind.SomeMember) &&
158+
r.parent?.kindOf(ReflectionKind.TypeLiteral) &&
159+
r.parent.parent?.kindOf(
160+
ReflectionKind.TypeAlias | ReflectionKind.Variable,
161+
)
162+
) {
163+
return 2;
164+
}
165+
166+
return 1;
167+
})!;
149168
pos = end;
150169
defaultDisplayText =
151170
part.tsLinkText ||

src/lib/utils/array.ts

+22
Original file line numberDiff line numberDiff line change
@@ -196,3 +196,25 @@ export function joinArray<T>(
196196
}
197197
return "";
198198
}
199+
200+
export function maxElementByScore<T>(
201+
arr: readonly T[],
202+
score: (a: T) => number,
203+
): T | undefined {
204+
if (arr.length === 0) {
205+
return undefined;
206+
}
207+
208+
let largest = arr[0];
209+
let largestScore = score(arr[0]);
210+
211+
for (let i = 1; i < arr.length; ++i) {
212+
const itemScore = score(arr[i]);
213+
if (itemScore > largestScore) {
214+
largest = arr[i];
215+
largestScore = itemScore;
216+
}
217+
}
218+
219+
return largest;
220+
}

src/test/converter/exports/specs.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,7 @@
308308
"url": "typedoc://mod.ts#L13"
309309
}
310310
],
311-
"target": 31
311+
"target": 30
312312
},
313313
{
314314
"id": 40,
@@ -412,7 +412,7 @@
412412
"url": "typedoc://mod.ts#L40"
413413
}
414414
],
415-
"target": 34
415+
"target": 29
416416
}
417417
],
418418
"groups": [

src/test/converter/exports/specs.nodoc.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
"url": "typedoc://mod.ts#L13"
3535
}
3636
],
37-
"target": 31
37+
"target": 30
3838
},
3939
{
4040
"id": 43,

src/test/utils/array.test.ts

+21
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {
33
binaryFindPartition,
44
insertOrderSorted,
55
insertPrioritySorted,
6+
maxElementByScore,
67
removeIfPresent,
78
} from "../../lib/utils/array.js";
89

@@ -138,4 +139,24 @@ describe("Array utils", () => {
138139
equal(arr, [2, 1]);
139140
});
140141
});
142+
143+
describe("maxElementByScore", () => {
144+
it("Gets the max element", () => {
145+
const arr = [1, 2, 3];
146+
const item = maxElementByScore(arr, (x) => x);
147+
equal(item, 3);
148+
});
149+
150+
it("Prioritizes elements earlier in the array", () => {
151+
const arr = [1, 2, 3];
152+
const item = maxElementByScore(arr, () => 1);
153+
equal(item, 1);
154+
});
155+
156+
it("Returns undefined for an empty array", () => {
157+
const arr: unknown[] = [];
158+
const item = maxElementByScore(arr, () => 1);
159+
equal(item, undefined);
160+
});
161+
});
141162
});

0 commit comments

Comments
 (0)