Skip to content

Commit 0875618

Browse files
committed
Support nested namespaces
Resolves #2582
1 parent ff65a58 commit 0875618

File tree

7 files changed

+80
-19
lines changed

7 files changed

+80
-19
lines changed

src/lib/converter/comments/discovery.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ const variablePropertyKinds = [
1010
ts.SyntaxKind.PropertySignature,
1111
ts.SyntaxKind.BinaryExpression,
1212
ts.SyntaxKind.PropertyAssignment,
13+
ts.SyntaxKind.ShorthandPropertyAssignment,
1314
// class X { constructor(/** Comment */ readonly z: string) }
1415
ts.SyntaxKind.Parameter,
1516
// Variable values
@@ -43,6 +44,9 @@ const wantedKinds: Record<ReflectionKind, ts.SyntaxKind[]> = {
4344
ts.SyntaxKind.BindingElement,
4445
ts.SyntaxKind.ExportAssignment,
4546
ts.SyntaxKind.PropertyAccessExpression,
47+
ts.SyntaxKind.PropertyDeclaration,
48+
ts.SyntaxKind.PropertyAssignment,
49+
ts.SyntaxKind.ShorthandPropertyAssignment,
4650
],
4751
[ReflectionKind.Enum]: [
4852
ts.SyntaxKind.EnumDeclaration,
@@ -61,6 +65,9 @@ const wantedKinds: Record<ReflectionKind, ts.SyntaxKind[]> = {
6165
ts.SyntaxKind.VariableDeclaration,
6266
ts.SyntaxKind.ExportAssignment,
6367
ts.SyntaxKind.PropertyAccessExpression,
68+
ts.SyntaxKind.PropertyDeclaration,
69+
ts.SyntaxKind.PropertyAssignment,
70+
ts.SyntaxKind.ShorthandPropertyAssignment,
6471
],
6572
[ReflectionKind.Class]: [
6673
ts.SyntaxKind.ClassDeclaration,

src/lib/converter/symbols.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1007,10 +1007,7 @@ function convertVariableAsNamespace(
10071007
context.finalizeDeclarationReflection(reflection);
10081008
const rc = context.withScope(reflection);
10091009

1010-
const declaration = symbol.declarations?.find(ts.isVariableDeclaration);
1011-
assert(declaration, "Missing variable declaration");
1012-
const type = context.checker.getTypeAtLocation(declaration);
1013-
1010+
const type = context.checker.getTypeOfSymbol(symbol);
10141011
convertSymbols(rc, type.getProperties());
10151012

10161013
return ts.SymbolFlags.Property;

src/lib/models/MediaRegistry.ts

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ export class MediaRegistry {
3232
return this.nextId++;
3333
}
3434

35+
/** Called by {@link ProjectReflection.registerReflection} @internal*/
3536
registerReflection(absolute: string, reflection: Reflection) {
3637
absolute = normalizePath(absolute);
3738
const id = this.registerAbsolute(absolute);
@@ -106,12 +107,7 @@ export class MediaRegistry {
106107
fromObject(de: Deserializer, obj: JSONMediaRegistry): void {
107108
for (const [key, val] of Object.entries(obj.entries)) {
108109
const absolute = normalizePath(resolve(de.projectRoot, val));
109-
const existingId = this.pathToMedia.get(absolute);
110-
if (existingId) return;
111-
112-
de.oldMediaToNewMedia[+key] = this.nextId;
113-
this.mediaToPath.set(this.nextId, absolute);
114-
this.pathToMedia.set(absolute, this.nextId++);
110+
de.oldMediaToNewMedia[+key] = this.registerAbsolute(absolute);
115111
}
116112

117113
de.defer((project) => {
@@ -145,9 +141,6 @@ export class ValidatingMediaRegistry extends MediaRegistry {
145141
override fromObject(de: Deserializer, obj: JSONMediaRegistry) {
146142
for (const [key, val] of Object.entries(obj.entries)) {
147143
const absolute = normalizePath(resolve(de.projectRoot, val));
148-
const existingId = this.pathToMedia.get(absolute);
149-
if (existingId) return;
150-
151144
if (!existsSync(absolute)) {
152145
de.logger.warn(
153146
de.logger.i18n.saved_relative_path_0_resolved_from_1_does_not_exist(
@@ -158,9 +151,7 @@ export class ValidatingMediaRegistry extends MediaRegistry {
158151
continue;
159152
}
160153

161-
de.oldMediaToNewMedia[+key] = this.nextId;
162-
this.mediaToPath.set(this.nextId, absolute);
163-
this.pathToMedia.set(absolute, this.nextId++);
154+
de.oldMediaToNewMedia[+key] = this.registerAbsolute(absolute);
164155
}
165156

166157
de.defer((project) => {
@@ -173,6 +164,12 @@ export class ValidatingMediaRegistry extends MediaRegistry {
173164
de.oldMediaToNewMedia[+media]!,
174165
refl,
175166
);
167+
} else {
168+
de.logger.warn(
169+
de.logger.i18n.serialized_project_referenced_0_not_part_of_project(
170+
reflId.toString(),
171+
),
172+
);
176173
}
177174
}
178175
});

src/lib/models/comments/index.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,6 @@
11
export { Comment, CommentTag } from "./comment";
2-
export type { CommentDisplayPart, InlineTagDisplayPart } from "./comment";
2+
export type {
3+
CommentDisplayPart,
4+
InlineTagDisplayPart,
5+
RelativeLinkDisplayPart,
6+
} from "./comment";

src/test/converter2/issues/gh2582.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
function getApi<T>(Ctor: new () => T) {
2+
return {
3+
/** Member comment */
4+
member: 1,
5+
/** Fn comment */
6+
fn: () => new Ctor(),
7+
};
8+
}
9+
10+
function getAPIs<T1, T2>(Ctor1: new () => T1, Ctor2: new () => T2) {
11+
const a = getApi(Ctor1);
12+
13+
return {
14+
/** A comment @namespace*/
15+
a,
16+
/** B comment @namespace */
17+
b: getApi(Ctor2),
18+
};
19+
}
20+
21+
/** f32 comment @namespace */
22+
export const f32 = getAPIs(Float32Array, Float64Array);

src/test/issues.c2.test.ts

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,14 @@ import {
2727
getConverter2Program,
2828
} from "./programs";
2929
import { TestLogger } from "./TestLogger";
30-
import { getComment, getLinks, getSigComment, query, querySig } from "./utils";
30+
import {
31+
equalKind,
32+
getComment,
33+
getLinks,
34+
getSigComment,
35+
query,
36+
querySig,
37+
} from "./utils";
3138
import { DefaultTheme, PageEvent } from "..";
3239

3340
const base = getConverter2Base();
@@ -1526,4 +1533,22 @@ describe("Issue Tests", () => {
15261533
"Incorrect qualified name",
15271534
);
15281535
});
1536+
1537+
it("#2582 nested @namespace", () => {
1538+
const project = convert();
1539+
1540+
equalKind(query(project, "f32"), ReflectionKind.Namespace);
1541+
equalKind(query(project, "f32.a"), ReflectionKind.Namespace);
1542+
equalKind(query(project, "f32.a.member"), ReflectionKind.Variable);
1543+
equalKind(query(project, "f32.a.fn"), ReflectionKind.Function);
1544+
equalKind(query(project, "f32.b"), ReflectionKind.Namespace);
1545+
equalKind(query(project, "f32.b.member"), ReflectionKind.Reference); // Somewhat odd, but not wrong...
1546+
equalKind(query(project, "f32.b.fn"), ReflectionKind.Function);
1547+
1548+
equal(getComment(project, "f32"), "f32 comment");
1549+
equal(getComment(project, "f32.a"), "A comment");
1550+
equal(getComment(project, "f32.a.member"), "Member comment");
1551+
equal(getComment(project, "f32.a.fn"), "Fn comment");
1552+
equal(getComment(project, "f32.b"), "B comment");
1553+
});
15291554
});

src/test/utils.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,11 @@ import {
44
DeclarationReflection,
55
type ProjectReflection,
66
Reflection,
7-
type ReflectionKind,
7+
ReflectionKind,
88
type SignatureReflection,
99
} from "..";
1010
import { filterMap } from "../lib/utils";
11+
import { equal } from "assert/strict";
1112

1213
export function query(
1314
project: ProjectReflection,
@@ -68,3 +69,11 @@ export function getLinks(refl: Reflection): Array<{
6869
}
6970
});
7071
}
72+
73+
export function equalKind(refl: Reflection, kind: ReflectionKind) {
74+
equal(
75+
refl.kind,
76+
kind,
77+
`Expected ${ReflectionKind[kind]} but got ${ReflectionKind[refl.kind]}`,
78+
);
79+
}

0 commit comments

Comments
 (0)