Skip to content

Commit 2adb1c6

Browse files
committed
add types for writer
1 parent abd29ec commit 2adb1c6

File tree

3 files changed

+91
-11
lines changed

3 files changed

+91
-11
lines changed

lib/error.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
/** @import { Base } from "./productions/base.js" */
2+
13
/**
24
* @param {string} text
35
*/
@@ -14,6 +16,9 @@ function appendIfExist(base, target) {
1416
return result;
1517
}
1618

19+
/**
20+
* @param {Base} node
21+
*/
1722
function contextAsText(node) {
1823
const hierarchy = [node];
1924
while (node && node.parent) {

lib/productions/base.js

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ export class Base {
2929
});
3030
}
3131

32+
get type() { return undefined; };
33+
get name() { return undefined; };
34+
3235
/**
3336
* @param {Definitions} defs
3437
* @returns {IterableIterator<any>}
@@ -37,11 +40,12 @@ export class Base {
3740
*validate(defs) {}
3841

3942
/**
40-
* @param {Writer} w
41-
* @returns {*}
43+
* @template T
44+
* @param {Writer<T>} w
45+
* @returns {T | string}
4246
*/
4347
// eslint-disable-next-line no-unused-vars
44-
write(w) {}
48+
write(w) { return "" }
4549

4650
toJSON() {
4751
const json = { type: undefined, name: undefined, inheritance: undefined };

lib/writer.js

Lines changed: 79 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,39 @@
1+
/** @import { Base } from "./productions/base.js" */
2+
/** @import { Token } from "./tokeniser.js" */
3+
4+
/**
5+
* @template T
6+
* @param {T} arg
7+
*/
18
function noop(arg) {
29
return arg;
310
}
411

12+
/**
13+
* @typedef {object} TemplateContext
14+
* @property {Base} data
15+
* @property {Base} parent
16+
*/
17+
18+
/**
19+
* @template T
20+
* @typedef {object} WriteTemplates
21+
* @property {(items: (T | string)[]) => T} wrap
22+
* @property {(trivia: string) => T} trivia
23+
* @property {(escaped: string, context: TemplateContext) => T} name
24+
* @property {(escaped: string, unescaped: string, context: Base) => T} reference
25+
* @property {(type: T) => T} type
26+
* @property {(name: string) => T} generic
27+
* @property {(keyword: string, context: TemplateContext) => T} nameless
28+
* @property {(inheritable: T) => T} inheritance
29+
* @property {(content: T, context: TemplateContext) => T} definition
30+
* @property {(content: T) => T} extendedAttribute
31+
* @property {(content: string) => T} extendedAttributeReference
32+
*/
33+
34+
/** @type {WriteTemplates<string>} */
535
const templates = {
36+
/** @type {(items: any[]) => string} */
637
wrap: (items) => items.join(""),
738
trivia: noop,
839
name: noop,
@@ -16,7 +47,14 @@ const templates = {
1647
extendedAttributeReference: noop,
1748
};
1849

50+
/** @template T */
1951
export class Writer {
52+
/** @type {WriteTemplates<T>} */
53+
ts;
54+
55+
/**
56+
* @param {WriteTemplates<T>} ts
57+
*/
2058
constructor(ts) {
2159
this.ts = Object.assign({}, templates, ts);
2260
}
@@ -25,8 +63,7 @@ export class Writer {
2563
* @param {string} raw
2664
* @param {object} options
2765
* @param {string} [options.unescaped]
28-
* @param {import("./productions/base.js").Base} [options.context]
29-
* @returns
66+
* @param {Base} [options.context]
3067
*/
3168
reference(raw, { unescaped, context }) {
3269
if (!unescaped) {
@@ -36,16 +73,30 @@ export class Writer {
3673
}
3774

3875
/**
39-
* @param {import("./tokeniser.js").Token} t
40-
* @param {Function} wrapper
41-
* @param {...any} args
42-
* @returns
76+
* @overload
77+
* @param {Token} t
78+
* @param {(tokenValue: string, options: { context: Base }) => T | string} wrapper
79+
* @param {object} options
80+
* @param {Base} options.context
81+
* @returns {T | string}
82+
*/
83+
/**
84+
* @overload
85+
* @param {Token} t
86+
* @param {(tokenValue: string, context: TemplateContext) => T | string} [wrapper]
87+
* @param {TemplateContext} [context]
88+
* @returns {T | string}
89+
*/
90+
/**
91+
* @param {Token} t
92+
* @param {(tokenValue: string, context: any) => T | string} [wrapper]
93+
* @param {any} [context]
4394
*/
44-
token(t, wrapper = noop, ...args) {
95+
token(t, wrapper = noop, context) {
4596
if (!t) {
4697
return "";
4798
}
48-
const value = wrapper(t.value, ...args);
99+
const value = wrapper(t.value, context);
49100
return this.ts.wrap([this.ts.trivia(t.trivia), value]);
50101
}
51102

@@ -65,9 +116,29 @@ export class Writer {
65116
}
66117
}
67118

119+
/**
120+
* @overload
121+
* @param {Base[]} ast
122+
* @returns {string}
123+
*/
124+
/**
125+
* @template T
126+
* @overload
127+
* @param {Base[]} ast
128+
* @param {object} options
129+
* @param {WriteTemplates<T>} [options.templates]
130+
* @returns {T}
131+
*/
132+
/**
133+
* @param {Base[]} ast
134+
* @param {object} options
135+
* @param {WriteTemplates<unknown>} [options.templates]
136+
* @returns {unknown}
137+
*/
68138
export function write(ast, { templates: ts = templates } = {}) {
69139
ts = Object.assign({}, templates, ts);
70140

141+
/** @type {Writer<unknown>} */
71142
const w = new Writer(ts);
72143

73144
return ts.wrap(ast.map((it) => it.write(w)));

0 commit comments

Comments
 (0)