Skip to content

Commit e370aab

Browse files
committed
Add support for @namespace tag
Closes #2055
1 parent 929949e commit e370aab

File tree

9 files changed

+90
-21
lines changed

9 files changed

+90
-21
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
- TypeDoc options may now be set under the `typedocOptions` key in `package.json`, #2112.
4747
- Moved sidebar to left of content for consistency with most other websites, #2189.
4848
- Added `--cacheBust` option to tell TypeDoc to include include the generation time in files, #2124.
49+
- Added support for `@namespace` on variable declarations to tell TypeDoc to convert the variable as a namespace, #2055.
4950

5051
### Bug Fixes
5152

src/lib/converter/comments/discovery.ts

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,20 @@ import { CommentStyle } from "../../utils/options/declaration";
55
import { nicePath } from "../../utils/paths";
66
import { ok } from "assert";
77

8+
const variablePropertyKinds = [
9+
ts.SyntaxKind.PropertyDeclaration,
10+
ts.SyntaxKind.PropertySignature,
11+
ts.SyntaxKind.BinaryExpression,
12+
ts.SyntaxKind.PropertyAssignment,
13+
// class X { constructor(/** Comment */ readonly z: string) }
14+
ts.SyntaxKind.Parameter,
15+
// Variable values
16+
ts.SyntaxKind.VariableDeclaration,
17+
ts.SyntaxKind.BindingElement,
18+
ts.SyntaxKind.ExportAssignment,
19+
ts.SyntaxKind.PropertyAccessExpression,
20+
];
21+
822
// Note: This does NOT include JSDoc syntax kinds. This is important!
923
// Comments from @typedef and @callback tags are handled specially by
1024
// the JSDoc converter because we only want part of the comment when
@@ -18,6 +32,11 @@ const wantedKinds: Record<ReflectionKind, ts.SyntaxKind[]> = {
1832
ts.SyntaxKind.BindingElement,
1933
ts.SyntaxKind.ExportSpecifier,
2034
ts.SyntaxKind.NamespaceExport,
35+
// @namespace support
36+
ts.SyntaxKind.VariableDeclaration,
37+
ts.SyntaxKind.BindingElement,
38+
ts.SyntaxKind.ExportAssignment,
39+
ts.SyntaxKind.PropertyAccessExpression,
2140
],
2241
[ReflectionKind.Enum]: [
2342
ts.SyntaxKind.EnumDeclaration,
@@ -29,13 +48,7 @@ const wantedKinds: Record<ReflectionKind, ts.SyntaxKind[]> = {
2948
ts.SyntaxKind.PropertyAssignment,
3049
ts.SyntaxKind.PropertySignature,
3150
],
32-
[ReflectionKind.Variable]: [
33-
// everything here should also be in ReflectionKind.Property
34-
ts.SyntaxKind.VariableDeclaration,
35-
ts.SyntaxKind.BindingElement,
36-
ts.SyntaxKind.ExportAssignment,
37-
ts.SyntaxKind.PropertyAccessExpression,
38-
],
51+
[ReflectionKind.Variable]: variablePropertyKinds,
3952
[ReflectionKind.Function]: [
4053
ts.SyntaxKind.FunctionDeclaration,
4154
ts.SyntaxKind.BindingElement,
@@ -49,19 +62,7 @@ const wantedKinds: Record<ReflectionKind, ts.SyntaxKind[]> = {
4962
],
5063
[ReflectionKind.Interface]: [ts.SyntaxKind.InterfaceDeclaration],
5164
[ReflectionKind.Constructor]: [ts.SyntaxKind.Constructor],
52-
[ReflectionKind.Property]: [
53-
ts.SyntaxKind.PropertyDeclaration,
54-
ts.SyntaxKind.PropertySignature,
55-
ts.SyntaxKind.BinaryExpression,
56-
ts.SyntaxKind.PropertyAssignment,
57-
// class X { constructor(/** Comment */ readonly z: string) }
58-
ts.SyntaxKind.Parameter,
59-
// Variable values
60-
ts.SyntaxKind.VariableDeclaration,
61-
ts.SyntaxKind.BindingElement,
62-
ts.SyntaxKind.ExportAssignment,
63-
ts.SyntaxKind.PropertyAccessExpression,
64-
],
65+
[ReflectionKind.Property]: variablePropertyKinds,
6566
[ReflectionKind.Method]: [
6667
ts.SyntaxKind.FunctionDeclaration,
6768
ts.SyntaxKind.MethodDeclaration,

src/lib/converter/plugins/CommentPlugin.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,10 @@ export class CommentPlugin extends ConverterComponent {
149149
* @param comment The comment that should be searched for modifiers.
150150
*/
151151
private applyModifiers(reflection: Reflection, comment: Comment) {
152+
if (reflection.kindOf(ReflectionKind.SomeModule)) {
153+
comment.removeModifier("@namespace");
154+
}
155+
152156
if (comment.hasModifier("@private")) {
153157
reflection.setFlag(ReflectionFlag.Private);
154158
if (reflection.kindOf(ReflectionKind.CallSignature)) {

src/lib/converter/symbols.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -791,6 +791,10 @@ function convertVariable(
791791
return convertVariableAsEnum(context, symbol, exportSymbol);
792792
}
793793

794+
if (symbol.getJsDocTags().some((tag) => tag.name === "namespace")) {
795+
return convertVariableAsNamespace(context, symbol, exportSymbol);
796+
}
797+
794798
if (type.getCallSignatures().length) {
795799
return convertVariableAsFunction(context, symbol, exportSymbol);
796800
}
@@ -876,6 +880,27 @@ function convertVariableAsEnum(
876880
return ts.SymbolFlags.TypeAlias;
877881
}
878882

883+
function convertVariableAsNamespace(
884+
context: Context,
885+
symbol: ts.Symbol,
886+
exportSymbol?: ts.Symbol
887+
) {
888+
const reflection = context.createDeclarationReflection(
889+
ReflectionKind.Namespace,
890+
symbol,
891+
exportSymbol
892+
);
893+
context.finalizeDeclarationReflection(reflection);
894+
const rc = context.withScope(reflection);
895+
896+
const declaration = symbol.declarations![0] as ts.VariableDeclaration;
897+
const type = context.checker.getTypeAtLocation(declaration);
898+
899+
convertSymbols(rc, type.getProperties());
900+
901+
return ts.SymbolFlags.Property;
902+
}
903+
879904
function convertVariableAsFunction(
880905
context: Context,
881906
symbol: ts.Symbol,

src/lib/utils/options/tsdoc-defaults.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,4 +54,5 @@ export const modifierTags = [
5454
"@enum",
5555
"@event",
5656
"@overload",
57+
"@namespace",
5758
] as const;

src/test/behaviorTests.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,21 @@ export const behaviorTests: {
141141
);
142142
},
143143

144+
constNamespace(project) {
145+
const someNs = query(project, "someNs");
146+
equal(someNs.kind, ReflectionKind.Namespace);
147+
equal(Comment.combineDisplayParts(someNs.comment?.summary), "ns doc");
148+
149+
const a = query(project, "someNs.a");
150+
equal(Comment.combineDisplayParts(a.comment?.summary), "a doc");
151+
152+
const b = query(project, "someNs.b");
153+
equal(
154+
Comment.combineDisplayParts(b.signatures?.[0].comment?.summary),
155+
"b doc"
156+
);
157+
},
158+
144159
constTypeParam(project) {
145160
const getNamesExactly = query(project, "getNamesExactly");
146161
const typeParams = getNamesExactly.signatures?.[0].typeParameters;
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/**
2+
* const doc
3+
*/
4+
export const someConst = {
5+
/** a doc */
6+
a: 123,
7+
8+
/** b doc */
9+
b() {
10+
return "456";
11+
},
12+
};
13+
14+
/**
15+
* ns doc
16+
* @namespace
17+
*/
18+
export const someNs = someConst;

src/test/issueTests.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,7 @@ export const issueTests: {
325325
project.children[1].signatures![0].comment?.summary,
326326
].map(Comment.combineDisplayParts);
327327

328-
equal(comments, ["", "metadata", "fn", "bar"]);
328+
equal(comments, ["bar", "metadata", "fn", "bar"]);
329329
},
330330

331331
gh1660(project) {

tsdoc.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,10 @@
8282
{
8383
"tagName": "@overload",
8484
"syntaxKind": "modifier"
85+
},
86+
{
87+
"tagName": "@namespace",
88+
"syntaxKind": "modifier"
8589
}
8690
]
8791
}

0 commit comments

Comments
 (0)