Skip to content

Commit 842e449

Browse files
feat: support for static methods and properties (#56)
* feat: support for static methods and properties * 🤖 Documentation auto-update --------- Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
1 parent e92d672 commit 842e449

File tree

7 files changed

+213
-24
lines changed

7 files changed

+213
-24
lines changed

README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ Parameters:
149149
- `params.inputFiles`: The list of files to scan and for which the documentation should be build.
150150
- `params.options`: Optional compiler options to generate the docs
151151

152-
[:link: Source](https://github.com/peterpeterparker/tsdoc-markdown/tree/main/src/lib/docs.ts#L477)
152+
[:link: Source](https://github.com/peterpeterparker/tsdoc-markdown/tree/main/src/lib/docs.ts#L496)
153153

154154
### :gear: documentationToMarkdown
155155

@@ -164,7 +164,7 @@ Parameters:
164164
- `params.entries`: The entries of the documentation (functions, constants and classes).
165165
- `params.options`: Optional configuration to render the Markdown content. See `types.ts` for details.
166166

167-
[:link: Source](https://github.com/peterpeterparker/tsdoc-markdown/tree/main/src/lib/markdown.ts#L296)
167+
[:link: Source](https://github.com/peterpeterparker/tsdoc-markdown/tree/main/src/lib/markdown.ts#L335)
168168

169169
### :gear: generateDocumentation
170170

src/lib/docs.ts

+23-4
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,18 @@ const isNodeExportedOrPublic = (node: Node): boolean => {
128128
);
129129
};
130130

131+
/**
132+
* True if node is a method or property and is declaration is static.
133+
*/
134+
const isNodeStatic = (node: Node): boolean | undefined => {
135+
if (!isMethodDeclaration(node) && !isPropertyDeclaration(node)) {
136+
return undefined;
137+
}
138+
139+
const flags = getCombinedModifierFlags(node as Declaration);
140+
return (flags & ModifierFlags.Static) !== 0;
141+
};
142+
131143
/** Serialize a signature (call or construct) */
132144
const serializeSignature = ({
133145
checker,
@@ -274,17 +286,22 @@ const visit = ({
274286
const addDocEntry = ({
275287
symbol,
276288
doc_type,
289+
isStatic,
277290
node
278291
}: {
279292
symbol: TypeScriptSymbol | undefined;
280293
doc_type: DocEntryType;
281294
node: Node;
282-
}): void => {
295+
} & Pick<DocEntry, 'isStatic'>): void => {
283296
if (!symbol) {
284297
return;
285298
}
286299

287-
const details = serializeSymbol({checker, symbol, doc_type});
300+
const details = {
301+
...serializeSymbol({checker, symbol, doc_type}),
302+
isStatic
303+
};
304+
288305
pushEntry({node, details});
289306
};
290307

@@ -335,7 +352,8 @@ const visit = ({
335352
forEachChild(node, visitChild);
336353
} else if (isMethodDeclaration(node)) {
337354
const symbol = checker.getSymbolAtLocation(node.name);
338-
addDocEntry({symbol, doc_type: 'method', node});
355+
const isStatic = isNodeStatic(node);
356+
addDocEntry({symbol, doc_type: 'method', isStatic, node});
339357
} else if (isFunctionDeclaration(node)) {
340358
const symbol = checker.getSymbolAtLocation(node.name ?? node);
341359
addDocEntry({symbol, doc_type: 'function', node});
@@ -365,7 +383,8 @@ const visit = ({
365383
} else if (isPropertyDeclaration(node)) {
366384
// We test for the property after the arrow function because a public property of a class can be an arrow function.
367385
const symbol = checker.getSymbolAtLocation(node.name);
368-
addDocEntry({symbol, doc_type: 'property', node});
386+
const isStatic = isNodeStatic(node);
387+
addDocEntry({symbol, doc_type: 'property', isStatic, node});
369388
} else if (isVariableStatement(node)) {
370389
const {
371390
declarationList: {declarations, flags}

src/lib/markdown.ts

+46-7
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,15 @@ const inlineDocParam = (documentation: string | undefined): string =>
3030
const inlineParams = (params: Params[]): string[] =>
3131
params.map(({name, documentation}) => `* \`${name}\`${inlineDocParam(documentation)}`);
3232

33+
const reduceStatic = (values: DocEntry[]): [DocEntry[], DocEntry[]] =>
34+
values.reduce<[DocEntry[], DocEntry[]]>(
35+
([i, s], value) => [
36+
[...i, ...(value.isStatic !== true ? [value] : [])],
37+
[...s, ...(value.isStatic === true ? [value] : [])]
38+
],
39+
[[], []]
40+
);
41+
3342
const classesToMarkdown = ({
3443
entry,
3544
headingLevel,
@@ -73,9 +82,19 @@ const classesToMarkdown = ({
7382
markdown.push('\n');
7483
}
7584

76-
if ((methods?.length ?? 0) > 0) {
77-
markdown.push(`${headingLevel}# Methods\n`);
78-
markdown.push(`${tableOfContent({entries: methods ?? [], emoji})}\n`);
85+
const methodsToMarkdown = ({
86+
methods,
87+
titlePrefix
88+
}: {
89+
methods: DocEntry[];
90+
titlePrefix?: string;
91+
}): void => {
92+
if ((methods?.length ?? 0) === 0) {
93+
return;
94+
}
95+
96+
markdown.push(`${headingLevel}# ${titlePrefix ?? ''}Methods\n`);
97+
markdown.push(`${tableOfContent({entries: methods, emoji})}\n`);
7998

8099
// Explicitly do not pass repo to generate the source code link afterwards for the all block
81100
markdown.push(
@@ -86,10 +105,25 @@ const classesToMarkdown = ({
86105
emoji
87106
})
88107
);
89-
}
108+
};
109+
110+
const [instanceMethods, staticMethods] = reduceStatic(methods ?? []);
90111

91-
if ((properties?.length ?? 0) > 0) {
92-
markdown.push(`${headingLevel}# Properties\n`);
112+
methodsToMarkdown({methods: staticMethods, titlePrefix: 'Static '});
113+
methodsToMarkdown({methods: instanceMethods});
114+
115+
const propertiesToMarkdown = ({
116+
properties,
117+
titlePrefix
118+
}: {
119+
properties: DocEntry[];
120+
titlePrefix?: string;
121+
}): void => {
122+
if ((properties?.length ?? 0) === 0) {
123+
return;
124+
}
125+
126+
markdown.push(`${headingLevel}# ${titlePrefix ?? ''}Properties\n`);
93127
markdown.push(`${tableOfContent({entries: properties ?? [], emoji})}\n`);
94128

95129
// Explicitly do not pass repo to generate the source code link afterwards for the all block
@@ -101,7 +135,12 @@ const classesToMarkdown = ({
101135
emoji
102136
})
103137
);
104-
}
138+
};
139+
140+
const [instanceProperties, staticProperties] = reduceStatic(properties ?? []);
141+
142+
propertiesToMarkdown({properties: staticProperties, titlePrefix: 'Static '});
143+
propertiesToMarkdown({properties: instanceProperties});
105144

106145
return markdown.join('\n');
107146
};

src/lib/types.ts

+1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ export interface DocEntry {
2020
url?: string;
2121
documentation?: string;
2222
type?: string;
23+
isStatic?: boolean;
2324
constructors?: DocEntryConstructor[];
2425
parameters?: DocEntry[];
2526
methods?: DocEntry[];

src/test/mock.json

+56-6
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,8 @@
136136
]
137137
}
138138
],
139-
"doc_type": "method"
139+
"doc_type": "method",
140+
"isStatic": true
140141
},
141142
{
142143
"name": "accountBalance",
@@ -181,7 +182,8 @@
181182
"documentation": "Public method.",
182183
"type": "() => void",
183184
"jsDocs": [],
184-
"doc_type": "method"
185+
"doc_type": "method",
186+
"isStatic": false
185187
}
186188
],
187189
"properties": [
@@ -190,7 +192,8 @@
190192
"documentation": "The documentation of the public property.",
191193
"type": "string",
192194
"jsDocs": [],
193-
"doc_type": "property"
195+
"doc_type": "property",
196+
"isStatic": false
194197
}
195198
],
196199
"fileName": "src/test/mock.ts"
@@ -225,7 +228,8 @@
225228
]
226229
}
227230
],
228-
"doc_type": "method"
231+
"doc_type": "method",
232+
"isStatic": true
229233
},
230234
{
231235
"name": "metadata",
@@ -251,7 +255,8 @@
251255
"documentation": "Description",
252256
"type": "() => void",
253257
"jsDocs": [],
254-
"doc_type": "method"
258+
"doc_type": "method",
259+
"isStatic": false
255260
}
256261
],
257262
"properties": [],
@@ -500,5 +505,50 @@
500505
],
501506
"doc_type": "const",
502507
"fileName": "src/test/mock.ts"
508+
},
509+
{
510+
"name": "Number",
511+
"documentation": "Should differentiate methods / properties and static methods / properties",
512+
"type": "typeof Number",
513+
"jsDocs": [],
514+
"doc_type": "class",
515+
"constructors": [],
516+
"methods": [
517+
{
518+
"name": "add",
519+
"documentation": "",
520+
"type": "(n: Number) => Number",
521+
"jsDocs": [],
522+
"doc_type": "method",
523+
"isStatic": false
524+
},
525+
{
526+
"name": "add",
527+
"documentation": "",
528+
"type": "(n1: Number, n2: Number) => Number",
529+
"jsDocs": [],
530+
"doc_type": "method",
531+
"isStatic": true
532+
}
533+
],
534+
"properties": [
535+
{
536+
"name": "hello",
537+
"documentation": "",
538+
"type": "string",
539+
"jsDocs": [],
540+
"doc_type": "property",
541+
"isStatic": false
542+
},
543+
{
544+
"name": "world",
545+
"documentation": "",
546+
"type": "string",
547+
"jsDocs": [],
548+
"doc_type": "property",
549+
"isStatic": true
550+
}
551+
],
552+
"fileName": "src/test/mock.ts"
503553
}
504-
]
554+
]

src/test/mock.md

+65-5
Original file line numberDiff line numberDiff line change
@@ -152,11 +152,9 @@ Parameters:
152152
* `hardwareWallet`
153153

154154

155-
### Methods
155+
### Static Methods
156156

157157
- [create](#gear-create)
158-
- [accountBalance](#gear-accountbalance)
159-
- [shouldBeDocumented](#gear-shouldbedocumented)
160158

161159
#### :gear: create
162160

@@ -168,6 +166,11 @@ Create a LedgerCanister
168166

169167
[:link: Source](https://github.com/peterpeterparker/tsdoc-markdown/tree/main/src/test/mock.ts#L55)
170168

169+
### Methods
170+
171+
- [accountBalance](#gear-accountbalance)
172+
- [shouldBeDocumented](#gear-shouldbedocumented)
173+
171174
#### :gear: accountBalance
172175

173176
Returns the balance of the specified account identifier.
@@ -212,10 +215,9 @@ The documentation of the public property.
212215

213216

214217

215-
### Methods
218+
### Static Methods
216219

217220
- [create](#gear-create)
218-
- [metadata](#gear-metadata)
219221

220222
#### :gear: create
221223

@@ -227,6 +229,10 @@ This create function is public as well.
227229

228230
[:link: Source](https://github.com/peterpeterparker/tsdoc-markdown/tree/main/src/test/mock.ts#L133)
229231

232+
### Methods
233+
234+
- [metadata](#gear-metadata)
235+
230236
#### :gear: metadata
231237

232238
The token metadata (name, symbol, etc.).
@@ -255,6 +261,60 @@ Description
255261

256262
[:link: Source](https://github.com/peterpeterparker/tsdoc-markdown/tree/main/src/test/mock.ts#L150)
257263

264+
## :factory: Number
265+
266+
Should differentiate methods / properties and static methods / properties
267+
268+
[:link: Source](https://github.com/peterpeterparker/tsdoc-markdown/tree/main/src/test/mock.ts#L315)
269+
270+
### Static Methods
271+
272+
- [add](#gear-add)
273+
274+
#### :gear: add
275+
276+
| Method | Type |
277+
| ---------- | ---------- |
278+
| `add` | `(n1: Number, n2: Number) => Number` |
279+
280+
[:link: Source](https://github.com/peterpeterparker/tsdoc-markdown/tree/main/src/test/mock.ts#L327)
281+
282+
### Methods
283+
284+
- [add](#gear-add)
285+
286+
#### :gear: add
287+
288+
| Method | Type |
289+
| ---------- | ---------- |
290+
| `add` | `(n: Number) => Number` |
291+
292+
[:link: Source](https://github.com/peterpeterparker/tsdoc-markdown/tree/main/src/test/mock.ts#L323)
293+
294+
### Static Properties
295+
296+
- [world](#gear-world)
297+
298+
#### :gear: world
299+
300+
| Property | Type |
301+
| ---------- | ---------- |
302+
| `world` | `string` |
303+
304+
[:link: Source](https://github.com/peterpeterparker/tsdoc-markdown/tree/main/src/test/mock.ts#L318)
305+
306+
### Properties
307+
308+
- [hello](#gear-hello)
309+
310+
#### :gear: hello
311+
312+
| Property | Type |
313+
| ---------- | ---------- |
314+
| `hello` | `string` |
315+
316+
[:link: Source](https://github.com/peterpeterparker/tsdoc-markdown/tree/main/src/test/mock.ts#L317)
317+
258318
## :nut_and_bolt: Enum
259319

260320
- [Time](#gear-time)

0 commit comments

Comments
 (0)