esrap 1.2.2 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -1
- package/package.json +14 -9
- package/src/handlers.js +374 -78
- package/src/index.js +6 -11
- package/src/public.d.ts +2 -0
- package/src/types.d.ts +35 -6
- package/types/index.d.ts +10 -7
- package/types/index.d.ts.map +5 -1
package/README.md
CHANGED
|
@@ -44,13 +44,17 @@ const { code, map } = print(ast, {
|
|
|
44
44
|
});
|
|
45
45
|
```
|
|
46
46
|
|
|
47
|
+
## TypeScript
|
|
48
|
+
|
|
49
|
+
`esrap` can also print TypeScript nodes, assuming they match the ESTree-like [`@typescript-eslint/types`](https://www.npmjs.com/package/@typescript-eslint/types).
|
|
50
|
+
|
|
47
51
|
## Why not just use Prettier?
|
|
48
52
|
|
|
49
53
|
Because it's ginormous.
|
|
50
54
|
|
|
51
55
|
## Developing
|
|
52
56
|
|
|
53
|
-
This repo uses [
|
|
57
|
+
This repo uses [pnpm](https://pnpm.io). Once it's installed, do `pnpm install` to install dependencies, and `pnpm test` to run the tests.
|
|
54
58
|
|
|
55
59
|
## License
|
|
56
60
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "esrap",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "Parse in reverse",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -19,21 +19,26 @@
|
|
|
19
19
|
},
|
|
20
20
|
"types": "./types/index.d.ts",
|
|
21
21
|
"devDependencies": {
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
"
|
|
22
|
+
"@vitest/ui": "^2.1.1",
|
|
23
|
+
"acorn": "^8.11.3",
|
|
24
|
+
"acorn-typescript": "^1.4.13",
|
|
25
|
+
"dts-buddy": "^0.5.4",
|
|
25
26
|
"prettier": "^3.0.3",
|
|
26
|
-
"typescript": "^5.
|
|
27
|
+
"typescript": "^5.7.2",
|
|
28
|
+
"vitest": "^2.1.1",
|
|
27
29
|
"zimmerframe": "^1.0.0"
|
|
28
30
|
},
|
|
29
31
|
"scripts": {
|
|
30
32
|
"check": "tsc",
|
|
31
|
-
"prepublishOnly": "
|
|
32
|
-
"sandbox": "
|
|
33
|
+
"prepublishOnly": "pnpm test && dts-buddy -m dts-buddy:./src/public.d.ts",
|
|
34
|
+
"sandbox": "node test/sandbox/index.js",
|
|
35
|
+
"test": "vitest --run",
|
|
36
|
+
"test:ui": "vitest --ui"
|
|
33
37
|
},
|
|
34
38
|
"license": "MIT",
|
|
35
39
|
"dependencies": {
|
|
36
40
|
"@jridgewell/sourcemap-codec": "^1.4.15",
|
|
37
|
-
"@types
|
|
38
|
-
}
|
|
41
|
+
"@typescript-eslint/types": "^8.2.0"
|
|
42
|
+
},
|
|
43
|
+
"packageManager": "pnpm@9.8.0"
|
|
39
44
|
}
|
package/src/handlers.js
CHANGED
|
@@ -1,15 +1,18 @@
|
|
|
1
|
-
/** @
|
|
1
|
+
/** @import { TSESTree } from '@typescript-eslint/types' */
|
|
2
|
+
/** @import { Chunk, Command, Dedent, Handlers, Indent, Newline, NodeWithComments, Sequence, State, TypeAnnotationNodes } from './types' */
|
|
3
|
+
|
|
4
|
+
/** @type {Newline} */
|
|
2
5
|
const newline = { type: 'Newline' };
|
|
3
6
|
|
|
4
|
-
/** @type {
|
|
7
|
+
/** @type {Indent} */
|
|
5
8
|
const indent = { type: 'Indent' };
|
|
6
9
|
|
|
7
|
-
/** @type {
|
|
10
|
+
/** @type {Dedent} */
|
|
8
11
|
const dedent = { type: 'Dedent' };
|
|
9
12
|
|
|
10
13
|
/**
|
|
11
|
-
* @param {
|
|
12
|
-
* @returns {
|
|
14
|
+
* @param {Command[]} children
|
|
15
|
+
* @returns {Sequence}
|
|
13
16
|
*/
|
|
14
17
|
function create_sequence(...children) {
|
|
15
18
|
return { type: 'Sequence', children };
|
|
@@ -17,7 +20,7 @@ function create_sequence(...children) {
|
|
|
17
20
|
|
|
18
21
|
/**
|
|
19
22
|
* Rough estimate of the combined width of a group of commands
|
|
20
|
-
* @param {
|
|
23
|
+
* @param {Command[]} commands
|
|
21
24
|
* @param {number} from
|
|
22
25
|
* @param {number} to
|
|
23
26
|
*/
|
|
@@ -39,32 +42,34 @@ function measure(commands, from, to = commands.length) {
|
|
|
39
42
|
}
|
|
40
43
|
|
|
41
44
|
/**
|
|
42
|
-
* @param {
|
|
43
|
-
* @param {
|
|
45
|
+
* @param {TSESTree.Node} node
|
|
46
|
+
* @param {State} state
|
|
44
47
|
*/
|
|
45
48
|
export function handle(node, state) {
|
|
49
|
+
const node_with_comments = /** @type {NodeWithComments} */ (node);
|
|
50
|
+
|
|
46
51
|
const handler = handlers[node.type];
|
|
47
52
|
|
|
48
53
|
if (!handler) {
|
|
49
54
|
throw new Error(`Not implemented ${node.type}`);
|
|
50
55
|
}
|
|
51
56
|
|
|
52
|
-
if (
|
|
53
|
-
prepend_comments(
|
|
57
|
+
if (node_with_comments.leadingComments) {
|
|
58
|
+
prepend_comments(node_with_comments.leadingComments, state, false);
|
|
54
59
|
}
|
|
55
60
|
|
|
56
61
|
// @ts-expect-error
|
|
57
62
|
handler(node, state);
|
|
58
63
|
|
|
59
|
-
if (
|
|
60
|
-
state.comments.push(
|
|
64
|
+
if (node_with_comments.trailingComments) {
|
|
65
|
+
state.comments.push(node_with_comments.trailingComments[0]); // there is only ever one
|
|
61
66
|
}
|
|
62
67
|
}
|
|
63
68
|
|
|
64
69
|
/**
|
|
65
70
|
* @param {string} content
|
|
66
|
-
* @param {
|
|
67
|
-
* @returns {
|
|
71
|
+
* @param {TSESTree.Node} node
|
|
72
|
+
* @returns {Chunk}
|
|
68
73
|
*/
|
|
69
74
|
function c(content, node) {
|
|
70
75
|
return {
|
|
@@ -75,8 +80,8 @@ function c(content, node) {
|
|
|
75
80
|
}
|
|
76
81
|
|
|
77
82
|
/**
|
|
78
|
-
* @param {
|
|
79
|
-
* @param {
|
|
83
|
+
* @param {TSESTree.Comment[]} comments
|
|
84
|
+
* @param {State} state
|
|
80
85
|
* @param {boolean} newlines
|
|
81
86
|
*/
|
|
82
87
|
function prepend_comments(comments, state, newlines) {
|
|
@@ -119,13 +124,16 @@ const OPERATOR_PRECEDENCE = {
|
|
|
119
124
|
'**': 13
|
|
120
125
|
};
|
|
121
126
|
|
|
122
|
-
/** @type {Record<
|
|
127
|
+
/** @type {Record<TSESTree.Expression['type'] | 'Super' | 'RestElement', number>} */
|
|
123
128
|
const EXPRESSIONS_PRECEDENCE = {
|
|
129
|
+
JSXFragment: 20,
|
|
130
|
+
JSXElement: 20,
|
|
131
|
+
ArrayPattern: 20,
|
|
132
|
+
ObjectPattern: 20,
|
|
124
133
|
ArrayExpression: 20,
|
|
125
134
|
TaggedTemplateExpression: 20,
|
|
126
135
|
ThisExpression: 20,
|
|
127
136
|
Identifier: 20,
|
|
128
|
-
Literal: 18,
|
|
129
137
|
TemplateLiteral: 20,
|
|
130
138
|
Super: 20,
|
|
131
139
|
SequenceExpression: 20,
|
|
@@ -135,10 +143,16 @@ const EXPRESSIONS_PRECEDENCE = {
|
|
|
135
143
|
ChainExpression: 19,
|
|
136
144
|
ImportExpression: 19,
|
|
137
145
|
NewExpression: 19,
|
|
146
|
+
Literal: 18,
|
|
147
|
+
TSSatisfiesExpression: 18,
|
|
148
|
+
TSInstantiationExpression: 18,
|
|
149
|
+
TSNonNullExpression: 18,
|
|
150
|
+
TSTypeAssertion: 18,
|
|
138
151
|
AwaitExpression: 17,
|
|
139
152
|
ClassExpression: 17,
|
|
140
153
|
FunctionExpression: 17,
|
|
141
154
|
ObjectExpression: 17,
|
|
155
|
+
TSAsExpression: 16,
|
|
142
156
|
UpdateExpression: 16,
|
|
143
157
|
UnaryExpression: 15,
|
|
144
158
|
BinaryExpression: 14,
|
|
@@ -152,12 +166,14 @@ const EXPRESSIONS_PRECEDENCE = {
|
|
|
152
166
|
|
|
153
167
|
/**
|
|
154
168
|
*
|
|
155
|
-
* @param {
|
|
156
|
-
* @param {
|
|
169
|
+
* @param {TSESTree.Expression | TSESTree.PrivateIdentifier} node
|
|
170
|
+
* @param {TSESTree.BinaryExpression | TSESTree.LogicalExpression} parent
|
|
157
171
|
* @param {boolean} is_right
|
|
158
172
|
* @returns
|
|
159
173
|
*/
|
|
160
174
|
function needs_parens(node, parent, is_right) {
|
|
175
|
+
if (node.type === 'PrivateIdentifier') return false;
|
|
176
|
+
|
|
161
177
|
// special case where logical expressions and coalesce expressions cannot be mixed,
|
|
162
178
|
// either of them need to be wrapped with parentheses
|
|
163
179
|
if (
|
|
@@ -186,7 +202,7 @@ function needs_parens(node, parent, is_right) {
|
|
|
186
202
|
}
|
|
187
203
|
|
|
188
204
|
if (
|
|
189
|
-
/** @type {
|
|
205
|
+
/** @type {TSESTree.BinaryExpression} */ (node).operator === '**' &&
|
|
190
206
|
parent.operator === '**'
|
|
191
207
|
) {
|
|
192
208
|
// Exponentiation operator has right-to-left associativity
|
|
@@ -196,18 +212,18 @@ function needs_parens(node, parent, is_right) {
|
|
|
196
212
|
if (is_right) {
|
|
197
213
|
// Parenthesis are used if both operators have the same precedence
|
|
198
214
|
return (
|
|
199
|
-
OPERATOR_PRECEDENCE[/** @type {
|
|
215
|
+
OPERATOR_PRECEDENCE[/** @type {TSESTree.BinaryExpression} */ (node).operator] <=
|
|
200
216
|
OPERATOR_PRECEDENCE[parent.operator]
|
|
201
217
|
);
|
|
202
218
|
}
|
|
203
219
|
|
|
204
220
|
return (
|
|
205
|
-
OPERATOR_PRECEDENCE[/** @type {
|
|
221
|
+
OPERATOR_PRECEDENCE[/** @type {TSESTree.BinaryExpression} */ (node).operator] <
|
|
206
222
|
OPERATOR_PRECEDENCE[parent.operator]
|
|
207
223
|
);
|
|
208
224
|
}
|
|
209
225
|
|
|
210
|
-
/** @param {
|
|
226
|
+
/** @param {TSESTree.Node} node */
|
|
211
227
|
function has_call_expression(node) {
|
|
212
228
|
while (node) {
|
|
213
229
|
if (node.type === 'CallExpression') {
|
|
@@ -228,11 +244,13 @@ const grouped_expression_types = [
|
|
|
228
244
|
];
|
|
229
245
|
|
|
230
246
|
/**
|
|
231
|
-
* @param {
|
|
232
|
-
* @param {
|
|
247
|
+
* @param {TSESTree.Node[]} nodes
|
|
248
|
+
* @param {State} state
|
|
233
249
|
*/
|
|
234
250
|
const handle_body = (nodes, state) => {
|
|
235
|
-
let last_statement = /** @type {
|
|
251
|
+
let last_statement = /** @type {TSESTree.Node} */ ({
|
|
252
|
+
type: 'EmptyStatement'
|
|
253
|
+
});
|
|
236
254
|
let first = true;
|
|
237
255
|
let needs_margin = false;
|
|
238
256
|
|
|
@@ -244,11 +262,12 @@ const handle_body = (nodes, state) => {
|
|
|
244
262
|
if (!first) state.commands.push(margin, newline);
|
|
245
263
|
first = false;
|
|
246
264
|
|
|
247
|
-
const
|
|
248
|
-
|
|
265
|
+
const statement_with_comments = /** @type {NodeWithComments} */ (statement);
|
|
266
|
+
const leading_comments = statement_with_comments.leadingComments;
|
|
267
|
+
delete statement_with_comments.leadingComments;
|
|
249
268
|
|
|
250
|
-
if (
|
|
251
|
-
prepend_comments(
|
|
269
|
+
if (leading_comments && leading_comments.length > 0) {
|
|
270
|
+
prepend_comments(leading_comments, state, true);
|
|
252
271
|
}
|
|
253
272
|
|
|
254
273
|
const child_state = { ...state, multiline: false };
|
|
@@ -267,7 +286,7 @@ const handle_body = (nodes, state) => {
|
|
|
267
286
|
let add_newline = false;
|
|
268
287
|
|
|
269
288
|
while (state.comments.length) {
|
|
270
|
-
const comment = /** @type {
|
|
289
|
+
const comment = /** @type {TSESTree.Comment} */ (state.comments.shift());
|
|
271
290
|
|
|
272
291
|
state.commands.push(add_newline ? newline : ' ', { type: 'Comment', comment });
|
|
273
292
|
add_newline = comment.type === 'Line';
|
|
@@ -279,8 +298,8 @@ const handle_body = (nodes, state) => {
|
|
|
279
298
|
};
|
|
280
299
|
|
|
281
300
|
/**
|
|
282
|
-
* @param {
|
|
283
|
-
* @param {
|
|
301
|
+
* @param {TSESTree.VariableDeclaration} node
|
|
302
|
+
* @param {State} state
|
|
284
303
|
*/
|
|
285
304
|
const handle_var_declaration = (node, state) => {
|
|
286
305
|
const index = state.commands.length;
|
|
@@ -314,13 +333,13 @@ const handle_var_declaration = (node, state) => {
|
|
|
314
333
|
};
|
|
315
334
|
|
|
316
335
|
/**
|
|
317
|
-
* @template {
|
|
336
|
+
* @template {TSESTree.Node} T
|
|
318
337
|
* @param {Array<T | null>} nodes
|
|
319
|
-
* @param {
|
|
338
|
+
* @param {State} state
|
|
320
339
|
* @param {boolean} spaces
|
|
321
|
-
* @param {(node: T, state:
|
|
340
|
+
* @param {(node: T, state: State) => void} fn
|
|
322
341
|
*/
|
|
323
|
-
function sequence(nodes, state, spaces, fn) {
|
|
342
|
+
function sequence(nodes, state, spaces, fn, separator = ',') {
|
|
324
343
|
if (nodes.length === 0) return;
|
|
325
344
|
|
|
326
345
|
const index = state.commands.length;
|
|
@@ -348,14 +367,14 @@ function sequence(nodes, state, spaces, fn) {
|
|
|
348
367
|
fn(node, child_state);
|
|
349
368
|
|
|
350
369
|
if (!is_last) {
|
|
351
|
-
state.commands.push(
|
|
370
|
+
state.commands.push(separator);
|
|
352
371
|
}
|
|
353
372
|
|
|
354
373
|
if (state.comments.length > 0) {
|
|
355
374
|
state.commands.push(' ');
|
|
356
375
|
|
|
357
376
|
while (state.comments.length) {
|
|
358
|
-
const comment = /** @type {
|
|
377
|
+
const comment = /** @type {TSESTree.Comment} */ (state.comments.shift());
|
|
359
378
|
state.commands.push({ type: 'Comment', comment });
|
|
360
379
|
if (!is_last) state.commands.push(join);
|
|
361
380
|
}
|
|
@@ -368,7 +387,7 @@ function sequence(nodes, state, spaces, fn) {
|
|
|
368
387
|
// This is only used for ArrayPattern and ArrayExpression, but
|
|
369
388
|
// it makes more sense to have the logic here than there, because
|
|
370
389
|
// otherwise we'd duplicate a lot more stuff
|
|
371
|
-
state.commands.push(
|
|
390
|
+
state.commands.push(separator);
|
|
372
391
|
}
|
|
373
392
|
|
|
374
393
|
prev = node;
|
|
@@ -391,21 +410,172 @@ function sequence(nodes, state, spaces, fn) {
|
|
|
391
410
|
}
|
|
392
411
|
}
|
|
393
412
|
|
|
394
|
-
/**
|
|
413
|
+
/**
|
|
414
|
+
* @param {TypeAnnotationNodes} node
|
|
415
|
+
* @param {State} state
|
|
416
|
+
*/
|
|
417
|
+
function handle_type_annotation(node, state) {
|
|
418
|
+
switch (node.type) {
|
|
419
|
+
case 'TSNumberKeyword':
|
|
420
|
+
state.commands.push('number');
|
|
421
|
+
break;
|
|
422
|
+
case 'TSStringKeyword':
|
|
423
|
+
state.commands.push('string');
|
|
424
|
+
break;
|
|
425
|
+
case 'TSBooleanKeyword':
|
|
426
|
+
state.commands.push('boolean');
|
|
427
|
+
break;
|
|
428
|
+
case 'TSAnyKeyword':
|
|
429
|
+
state.commands.push('any');
|
|
430
|
+
break;
|
|
431
|
+
case 'TSVoidKeyword':
|
|
432
|
+
state.commands.push('void');
|
|
433
|
+
break;
|
|
434
|
+
case 'TSUnknownKeyword':
|
|
435
|
+
state.commands.push('unknown');
|
|
436
|
+
break;
|
|
437
|
+
case 'TSNeverKeyword':
|
|
438
|
+
state.commands.push('never');
|
|
439
|
+
break;
|
|
440
|
+
case 'TSArrayType':
|
|
441
|
+
handle_type_annotation(node.elementType, state);
|
|
442
|
+
state.commands.push('[]');
|
|
443
|
+
break;
|
|
444
|
+
case 'TSTypeAnnotation':
|
|
445
|
+
state.commands.push(': ');
|
|
446
|
+
handle_type_annotation(node.typeAnnotation, state);
|
|
447
|
+
break;
|
|
448
|
+
case 'TSTypeLiteral':
|
|
449
|
+
state.commands.push('{ ');
|
|
450
|
+
sequence(node.members, state, false, handle_type_annotation, ';');
|
|
451
|
+
state.commands.push(' }');
|
|
452
|
+
break;
|
|
453
|
+
case 'TSPropertySignature':
|
|
454
|
+
handle(node.key, state);
|
|
455
|
+
if (node.optional) state.commands.push('?');
|
|
456
|
+
if (node.typeAnnotation) handle_type_annotation(node.typeAnnotation, state);
|
|
457
|
+
break;
|
|
458
|
+
case 'TSTypeReference':
|
|
459
|
+
handle(node.typeName, state);
|
|
460
|
+
|
|
461
|
+
// @ts-expect-error `acorn-typescript` and `@typescript-esling/types` have slightly different type definitions
|
|
462
|
+
if (node.typeParameters) handle_type_annotation(node.typeParameters, state);
|
|
463
|
+
break;
|
|
464
|
+
case 'TSTypeParameterInstantiation':
|
|
465
|
+
case 'TSTypeParameterDeclaration':
|
|
466
|
+
state.commands.push('<');
|
|
467
|
+
for (let i = 0; i < node.params.length; i++) {
|
|
468
|
+
handle_type_annotation(node.params[i], state);
|
|
469
|
+
if (i != node.params.length - 1) state.commands.push(', ');
|
|
470
|
+
}
|
|
471
|
+
state.commands.push('>');
|
|
472
|
+
break;
|
|
473
|
+
case 'TSTypeParameter':
|
|
474
|
+
// @ts-expect-error `acorn-typescript` and `@typescript-esling/types` have slightly different type definitions
|
|
475
|
+
state.commands.push(node.name);
|
|
476
|
+
|
|
477
|
+
if (node.constraint) {
|
|
478
|
+
state.commands.push(' extends ');
|
|
479
|
+
handle_type_annotation(node.constraint, state);
|
|
480
|
+
}
|
|
481
|
+
break;
|
|
482
|
+
case 'TSTypeQuery':
|
|
483
|
+
state.commands.push('typeof ');
|
|
484
|
+
handle(node.exprName, state);
|
|
485
|
+
break;
|
|
486
|
+
case 'TSEnumMember':
|
|
487
|
+
handle(node.id, state);
|
|
488
|
+
if (node.initializer) {
|
|
489
|
+
state.commands.push(' = ');
|
|
490
|
+
handle(node.initializer, state);
|
|
491
|
+
}
|
|
492
|
+
break;
|
|
493
|
+
case 'TSFunctionType':
|
|
494
|
+
if (node.typeParameters) handle_type_annotation(node.typeParameters, state);
|
|
495
|
+
|
|
496
|
+
// @ts-expect-error `acorn-typescript` and `@typescript-esling/types` have slightly different type definitions
|
|
497
|
+
const parameters = node.parameters;
|
|
498
|
+
state.commands.push('(');
|
|
499
|
+
sequence(parameters, state, false, handle);
|
|
500
|
+
|
|
501
|
+
state.commands.push(') => ');
|
|
502
|
+
|
|
503
|
+
// @ts-expect-error `acorn-typescript` and `@typescript-esling/types` have slightly different type definitions
|
|
504
|
+
handle_type_annotation(node.typeAnnotation.typeAnnotation, state);
|
|
505
|
+
break;
|
|
506
|
+
case 'TSIndexSignature':
|
|
507
|
+
const indexParameters = node.parameters;
|
|
508
|
+
state.commands.push('[');
|
|
509
|
+
sequence(indexParameters, state, false, handle);
|
|
510
|
+
state.commands.push(']');
|
|
511
|
+
|
|
512
|
+
// @ts-expect-error `acorn-typescript` and `@typescript-esling/types` have slightly different type definitions
|
|
513
|
+
handle_type_annotation(node.typeAnnotation, state);
|
|
514
|
+
break;
|
|
515
|
+
case 'TSMethodSignature':
|
|
516
|
+
handle(node.key, state);
|
|
517
|
+
|
|
518
|
+
// @ts-expect-error `acorn-typescript` and `@typescript-esling/types` have slightly different type definitions
|
|
519
|
+
const parametersSignature = node.parameters;
|
|
520
|
+
state.commands.push('(');
|
|
521
|
+
sequence(parametersSignature, state, false, handle);
|
|
522
|
+
state.commands.push(')');
|
|
523
|
+
|
|
524
|
+
// @ts-expect-error `acorn-typescript` and `@typescript-esling/types` have slightly different type definitions
|
|
525
|
+
handle_type_annotation(node.typeAnnotation, state);
|
|
526
|
+
break;
|
|
527
|
+
case 'TSExpressionWithTypeArguments':
|
|
528
|
+
handle(node.expression, state);
|
|
529
|
+
break;
|
|
530
|
+
case 'TSTupleType':
|
|
531
|
+
state.commands.push('[');
|
|
532
|
+
sequence(node.elementTypes, state, false, handle_type_annotation);
|
|
533
|
+
state.commands.push(']');
|
|
534
|
+
break;
|
|
535
|
+
case 'TSNamedTupleMember':
|
|
536
|
+
handle(node.label, state);
|
|
537
|
+
state.commands.push(': ');
|
|
538
|
+
handle_type_annotation(node.elementType, state);
|
|
539
|
+
|
|
540
|
+
break;
|
|
541
|
+
case 'TSUnionType':
|
|
542
|
+
sequence(node.types, state, false, handle_type_annotation, ' |');
|
|
543
|
+
break;
|
|
544
|
+
case 'TSIntersectionType':
|
|
545
|
+
sequence(node.types, state, false, handle_type_annotation, ' &');
|
|
546
|
+
break;
|
|
547
|
+
case 'TSLiteralType':
|
|
548
|
+
handle(node.literal, state);
|
|
549
|
+
break;
|
|
550
|
+
case 'TSConditionalType':
|
|
551
|
+
handle_type_annotation(node.checkType, state);
|
|
552
|
+
state.commands.push(' extends ');
|
|
553
|
+
handle_type_annotation(node.extendsType, state);
|
|
554
|
+
state.commands.push(' ? ');
|
|
555
|
+
handle_type_annotation(node.trueType, state);
|
|
556
|
+
state.commands.push(' : ');
|
|
557
|
+
handle_type_annotation(node.falseType, state);
|
|
558
|
+
break;
|
|
559
|
+
default:
|
|
560
|
+
throw new Error(`Not implemented type annotation ${node.type}`);
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
/** @satisfies {Record<string, (node: any, state: State) => undefined>} */
|
|
395
565
|
const shared = {
|
|
396
566
|
/**
|
|
397
|
-
* @param {
|
|
398
|
-
* @param {
|
|
567
|
+
* @param {TSESTree.ArrayExpression | TSESTree.ArrayPattern} node
|
|
568
|
+
* @param {State} state
|
|
399
569
|
*/
|
|
400
570
|
'ArrayExpression|ArrayPattern': (node, state) => {
|
|
401
571
|
state.commands.push('[');
|
|
402
|
-
sequence(/** @type {
|
|
572
|
+
sequence(/** @type {TSESTree.Node[]} */ (node.elements), state, false, handle);
|
|
403
573
|
state.commands.push(']');
|
|
404
574
|
},
|
|
405
575
|
|
|
406
576
|
/**
|
|
407
|
-
* @param {
|
|
408
|
-
* @param {
|
|
577
|
+
* @param {TSESTree.BinaryExpression | TSESTree.LogicalExpression} node
|
|
578
|
+
* @param {State} state
|
|
409
579
|
*/
|
|
410
580
|
'BinaryExpression|LogicalExpression': (node, state) => {
|
|
411
581
|
// TODO
|
|
@@ -435,8 +605,8 @@ const shared = {
|
|
|
435
605
|
},
|
|
436
606
|
|
|
437
607
|
/**
|
|
438
|
-
* @param {
|
|
439
|
-
* @param {
|
|
608
|
+
* @param {TSESTree.BlockStatement | TSESTree.ClassBody} node
|
|
609
|
+
* @param {State} state
|
|
440
610
|
*/
|
|
441
611
|
'BlockStatement|ClassBody': (node, state) => {
|
|
442
612
|
if (node.body.length === 0) {
|
|
@@ -452,12 +622,10 @@ const shared = {
|
|
|
452
622
|
},
|
|
453
623
|
|
|
454
624
|
/**
|
|
455
|
-
* @param {
|
|
456
|
-
* @param {
|
|
625
|
+
* @param {TSESTree.CallExpression | TSESTree.NewExpression} node
|
|
626
|
+
* @param {State} state
|
|
457
627
|
*/
|
|
458
628
|
'CallExpression|NewExpression': (node, state) => {
|
|
459
|
-
const index = state.commands.length;
|
|
460
|
-
|
|
461
629
|
if (node.type === 'NewExpression') {
|
|
462
630
|
state.commands.push('new ');
|
|
463
631
|
}
|
|
@@ -474,10 +642,13 @@ const shared = {
|
|
|
474
642
|
handle(node.callee, state);
|
|
475
643
|
}
|
|
476
644
|
|
|
477
|
-
if (/** @type {
|
|
645
|
+
if (/** @type {TSESTree.CallExpression} */ (node).optional) {
|
|
478
646
|
state.commands.push('?.');
|
|
479
647
|
}
|
|
480
648
|
|
|
649
|
+
// @ts-expect-error
|
|
650
|
+
if (node.typeParameters) handle_type_annotation(node.typeParameters, state);
|
|
651
|
+
|
|
481
652
|
const open = create_sequence();
|
|
482
653
|
const join = create_sequence();
|
|
483
654
|
const close = create_sequence();
|
|
@@ -495,7 +666,7 @@ const shared = {
|
|
|
495
666
|
state.commands.push(', ');
|
|
496
667
|
|
|
497
668
|
while (state.comments.length) {
|
|
498
|
-
const comment = /** @type {
|
|
669
|
+
const comment = /** @type {TSESTree.Comment} */ (state.comments.shift());
|
|
499
670
|
|
|
500
671
|
state.commands.push({ type: 'Comment', comment });
|
|
501
672
|
|
|
@@ -534,8 +705,8 @@ const shared = {
|
|
|
534
705
|
},
|
|
535
706
|
|
|
536
707
|
/**
|
|
537
|
-
* @param {
|
|
538
|
-
* @param {
|
|
708
|
+
* @param {TSESTree.ClassDeclaration | TSESTree.ClassExpression} node
|
|
709
|
+
* @param {State} state
|
|
539
710
|
*/
|
|
540
711
|
'ClassDeclaration|ClassExpression': (node, state) => {
|
|
541
712
|
state.commands.push('class ');
|
|
@@ -551,12 +722,17 @@ const shared = {
|
|
|
551
722
|
state.commands.push(' ');
|
|
552
723
|
}
|
|
553
724
|
|
|
725
|
+
if (node.implements) {
|
|
726
|
+
state.commands.push('implements ');
|
|
727
|
+
sequence(node.implements, state, false, handle_type_annotation);
|
|
728
|
+
}
|
|
729
|
+
|
|
554
730
|
handle(node.body, state);
|
|
555
731
|
},
|
|
556
732
|
|
|
557
733
|
/**
|
|
558
|
-
* @param {
|
|
559
|
-
* @param {
|
|
734
|
+
* @param {TSESTree.ForInStatement | TSESTree.ForOfStatement} node
|
|
735
|
+
* @param {State} state
|
|
560
736
|
*/
|
|
561
737
|
'ForInStatement|ForOfStatement': (node, state) => {
|
|
562
738
|
state.commands.push('for ');
|
|
@@ -576,32 +752,43 @@ const shared = {
|
|
|
576
752
|
},
|
|
577
753
|
|
|
578
754
|
/**
|
|
579
|
-
* @param {
|
|
580
|
-
* @param {
|
|
755
|
+
* @param {TSESTree.FunctionDeclaration | TSESTree.FunctionExpression} node
|
|
756
|
+
* @param {State} state
|
|
581
757
|
*/
|
|
582
758
|
'FunctionDeclaration|FunctionExpression': (node, state) => {
|
|
583
759
|
if (node.async) state.commands.push('async ');
|
|
584
760
|
state.commands.push(node.generator ? 'function* ' : 'function ');
|
|
585
761
|
if (node.id) handle(node.id, state);
|
|
586
762
|
|
|
763
|
+
if (node.typeParameters) {
|
|
764
|
+
handle_type_annotation(node.typeParameters, state);
|
|
765
|
+
}
|
|
766
|
+
|
|
587
767
|
state.commands.push('(');
|
|
588
768
|
sequence(node.params, state, false, handle);
|
|
589
|
-
state.commands.push(')
|
|
769
|
+
state.commands.push(')');
|
|
770
|
+
|
|
771
|
+
if (node.returnType) handle_type_annotation(node.returnType, state);
|
|
772
|
+
|
|
773
|
+
state.commands.push(' ');
|
|
590
774
|
|
|
591
775
|
handle(node.body, state);
|
|
592
776
|
},
|
|
593
777
|
|
|
594
778
|
/**
|
|
595
|
-
* @param {
|
|
596
|
-
* @param {
|
|
779
|
+
* @param {TSESTree.RestElement | TSESTree.SpreadElement} node
|
|
780
|
+
* @param {State} state
|
|
597
781
|
*/
|
|
598
782
|
'RestElement|SpreadElement': (node, state) => {
|
|
599
783
|
state.commands.push('...');
|
|
600
784
|
handle(node.argument, state);
|
|
785
|
+
|
|
786
|
+
// @ts-expect-error `acorn-typescript` and `@typescript-esling/types` have slightly different type definitions
|
|
787
|
+
if (node.typeAnnotation) handle_type_annotation(node.typeAnnotation, state);
|
|
601
788
|
}
|
|
602
789
|
};
|
|
603
790
|
|
|
604
|
-
/** @type {
|
|
791
|
+
/** @type {Handlers} */
|
|
605
792
|
const handlers = {
|
|
606
793
|
ArrayExpression: shared['ArrayExpression|ArrayPattern'],
|
|
607
794
|
|
|
@@ -728,6 +915,12 @@ const handlers = {
|
|
|
728
915
|
state.commands.push(c('debugger', node), ';');
|
|
729
916
|
},
|
|
730
917
|
|
|
918
|
+
Decorator(node, state) {
|
|
919
|
+
state.commands.push('@');
|
|
920
|
+
handle(node.expression, state);
|
|
921
|
+
state.commands.push(newline);
|
|
922
|
+
},
|
|
923
|
+
|
|
731
924
|
DoWhileStatement(node, state) {
|
|
732
925
|
state.commands.push('do ');
|
|
733
926
|
handle(node.body, state);
|
|
@@ -785,8 +978,9 @@ const handlers = {
|
|
|
785
978
|
|
|
786
979
|
ExpressionStatement(node, state) {
|
|
787
980
|
if (
|
|
788
|
-
node.expression.type === '
|
|
789
|
-
node.expression.
|
|
981
|
+
node.expression.type === 'ObjectExpression' ||
|
|
982
|
+
(node.expression.type === 'AssignmentExpression' &&
|
|
983
|
+
node.expression.left.type === 'ObjectPattern')
|
|
790
984
|
) {
|
|
791
985
|
// is an AssignmentExpression to an ObjectPattern
|
|
792
986
|
state.commands.push('(');
|
|
@@ -830,6 +1024,8 @@ const handlers = {
|
|
|
830
1024
|
Identifier(node, state) {
|
|
831
1025
|
let name = node.name;
|
|
832
1026
|
state.commands.push(c(name, node));
|
|
1027
|
+
|
|
1028
|
+
if (node.typeAnnotation) handle_type_annotation(node.typeAnnotation, state);
|
|
833
1029
|
},
|
|
834
1030
|
|
|
835
1031
|
IfStatement(node, state) {
|
|
@@ -852,13 +1048,13 @@ const handlers = {
|
|
|
852
1048
|
return;
|
|
853
1049
|
}
|
|
854
1050
|
|
|
855
|
-
/** @type {
|
|
1051
|
+
/** @type {TSESTree.ImportNamespaceSpecifier | null} */
|
|
856
1052
|
let namespace_specifier = null;
|
|
857
1053
|
|
|
858
|
-
/** @type {
|
|
1054
|
+
/** @type {TSESTree.ImportDefaultSpecifier | null} */
|
|
859
1055
|
let default_specifier = null;
|
|
860
1056
|
|
|
861
|
-
/** @type {
|
|
1057
|
+
/** @type {TSESTree.ImportSpecifier[]} */
|
|
862
1058
|
const named_specifiers = [];
|
|
863
1059
|
|
|
864
1060
|
for (const s of node.specifiers) {
|
|
@@ -872,6 +1068,7 @@ const handlers = {
|
|
|
872
1068
|
}
|
|
873
1069
|
|
|
874
1070
|
state.commands.push('import ');
|
|
1071
|
+
if (node.importKind == 'type') state.commands.push('type ');
|
|
875
1072
|
|
|
876
1073
|
if (default_specifier) {
|
|
877
1074
|
state.commands.push(c(default_specifier.local.name, default_specifier));
|
|
@@ -890,6 +1087,7 @@ const handlers = {
|
|
|
890
1087
|
state.commands.push(' as ');
|
|
891
1088
|
}
|
|
892
1089
|
|
|
1090
|
+
if (s.importKind == 'type') state.commands.push('type ');
|
|
893
1091
|
handle(s.local, state);
|
|
894
1092
|
});
|
|
895
1093
|
state.commands.push('}');
|
|
@@ -915,9 +1113,10 @@ const handlers = {
|
|
|
915
1113
|
Literal(node, state) {
|
|
916
1114
|
// TODO do we need to handle weird unicode characters somehow?
|
|
917
1115
|
// str.replace(/\\u(\d{4})/g, (m, n) => String.fromCharCode(+n))
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
1116
|
+
|
|
1117
|
+
let value = node.raw;
|
|
1118
|
+
if (!value)
|
|
1119
|
+
value = typeof node.value === 'string' ? JSON.stringify(node.value) : String(node.value);
|
|
921
1120
|
|
|
922
1121
|
state.commands.push(c(value, node));
|
|
923
1122
|
},
|
|
@@ -953,6 +1152,12 @@ const handlers = {
|
|
|
953
1152
|
},
|
|
954
1153
|
|
|
955
1154
|
MethodDefinition(node, state) {
|
|
1155
|
+
if (node.decorators) {
|
|
1156
|
+
for (const decorator of node.decorators) {
|
|
1157
|
+
handle(decorator, state);
|
|
1158
|
+
}
|
|
1159
|
+
}
|
|
1160
|
+
|
|
956
1161
|
if (node.static) {
|
|
957
1162
|
state.commands.push('static ');
|
|
958
1163
|
}
|
|
@@ -978,7 +1183,7 @@ const handlers = {
|
|
|
978
1183
|
sequence(node.value.params, state, false, handle);
|
|
979
1184
|
state.commands.push(') ');
|
|
980
1185
|
|
|
981
|
-
handle(node.value.body, state);
|
|
1186
|
+
if (node.value.body) handle(node.value.body, state);
|
|
982
1187
|
},
|
|
983
1188
|
|
|
984
1189
|
NewExpression: shared['CallExpression|NewExpression'],
|
|
@@ -987,7 +1192,7 @@ const handlers = {
|
|
|
987
1192
|
state.commands.push('{');
|
|
988
1193
|
sequence(node.properties, state, true, (p, state) => {
|
|
989
1194
|
if (p.type === 'Property' && p.value.type === 'FunctionExpression') {
|
|
990
|
-
const fn = /** @type {
|
|
1195
|
+
const fn = /** @type {TSESTree.FunctionExpression} */ (p.value);
|
|
991
1196
|
|
|
992
1197
|
if (p.kind === 'get' || p.kind === 'set') {
|
|
993
1198
|
state.commands.push(p.kind + ' ');
|
|
@@ -1016,6 +1221,8 @@ const handlers = {
|
|
|
1016
1221
|
state.commands.push('{');
|
|
1017
1222
|
sequence(node.properties, state, true, handle);
|
|
1018
1223
|
state.commands.push('}');
|
|
1224
|
+
|
|
1225
|
+
if (node.typeAnnotation) handle_type_annotation(node.typeAnnotation, state);
|
|
1019
1226
|
},
|
|
1020
1227
|
|
|
1021
1228
|
// @ts-expect-error this isn't a real node type, but Acorn produces it
|
|
@@ -1053,6 +1260,10 @@ const handlers = {
|
|
|
1053
1260
|
},
|
|
1054
1261
|
|
|
1055
1262
|
PropertyDefinition(node, state) {
|
|
1263
|
+
if (node.accessibility) {
|
|
1264
|
+
state.commands.push(node.accessibility, ' ');
|
|
1265
|
+
}
|
|
1266
|
+
|
|
1056
1267
|
if (node.static) {
|
|
1057
1268
|
state.commands.push('static ');
|
|
1058
1269
|
}
|
|
@@ -1065,6 +1276,11 @@ const handlers = {
|
|
|
1065
1276
|
handle(node.key, state);
|
|
1066
1277
|
}
|
|
1067
1278
|
|
|
1279
|
+
if (node.typeAnnotation) {
|
|
1280
|
+
state.commands.push(': ');
|
|
1281
|
+
handle_type_annotation(node.typeAnnotation.typeAnnotation, state);
|
|
1282
|
+
}
|
|
1283
|
+
|
|
1068
1284
|
if (node.value) {
|
|
1069
1285
|
state.commands.push(' = ');
|
|
1070
1286
|
|
|
@@ -1078,9 +1294,10 @@ const handlers = {
|
|
|
1078
1294
|
|
|
1079
1295
|
ReturnStatement(node, state) {
|
|
1080
1296
|
if (node.argument) {
|
|
1297
|
+
const argumentWithComment = /** @type {NodeWithComments} */ (node.argument);
|
|
1081
1298
|
const contains_comment =
|
|
1082
|
-
|
|
1083
|
-
|
|
1299
|
+
argumentWithComment.leadingComments &&
|
|
1300
|
+
argumentWithComment.leadingComments.some((comment) => comment.type === 'Line');
|
|
1084
1301
|
|
|
1085
1302
|
state.commands.push(contains_comment ? 'return (' : 'return ');
|
|
1086
1303
|
handle(node.argument, state);
|
|
@@ -1174,7 +1391,7 @@ const handlers = {
|
|
|
1174
1391
|
|
|
1175
1392
|
ThrowStatement(node, state) {
|
|
1176
1393
|
state.commands.push('throw ');
|
|
1177
|
-
handle(node.argument, state);
|
|
1394
|
+
if (node.argument) handle(node.argument, state);
|
|
1178
1395
|
state.commands.push(';');
|
|
1179
1396
|
},
|
|
1180
1397
|
|
|
@@ -1200,6 +1417,85 @@ const handlers = {
|
|
|
1200
1417
|
}
|
|
1201
1418
|
},
|
|
1202
1419
|
|
|
1420
|
+
TSAsExpression(node, state) {
|
|
1421
|
+
if (node.expression) {
|
|
1422
|
+
const needs_parens =
|
|
1423
|
+
EXPRESSIONS_PRECEDENCE[node.expression.type] < EXPRESSIONS_PRECEDENCE.TSAsExpression;
|
|
1424
|
+
|
|
1425
|
+
if (needs_parens) {
|
|
1426
|
+
state.commands.push('(');
|
|
1427
|
+
handle(node.expression, state);
|
|
1428
|
+
state.commands.push(')');
|
|
1429
|
+
} else {
|
|
1430
|
+
handle(node.expression, state);
|
|
1431
|
+
}
|
|
1432
|
+
}
|
|
1433
|
+
state.commands.push(' as ');
|
|
1434
|
+
handle_type_annotation(node.typeAnnotation, state);
|
|
1435
|
+
},
|
|
1436
|
+
|
|
1437
|
+
TSEnumDeclaration(node, state) {
|
|
1438
|
+
state.commands.push('enum ');
|
|
1439
|
+
handle(node.id, state);
|
|
1440
|
+
state.commands.push(' {', indent, newline);
|
|
1441
|
+
sequence(node.members, state, false, handle_type_annotation);
|
|
1442
|
+
state.commands.push(dedent, newline, '}', newline);
|
|
1443
|
+
},
|
|
1444
|
+
|
|
1445
|
+
TSNonNullExpression(node, state) {
|
|
1446
|
+
handle(node.expression, state);
|
|
1447
|
+
state.commands.push('!');
|
|
1448
|
+
},
|
|
1449
|
+
|
|
1450
|
+
TSInterfaceBody(node, state) {
|
|
1451
|
+
sequence(node.body, state, false, handle_type_annotation, ';');
|
|
1452
|
+
},
|
|
1453
|
+
|
|
1454
|
+
TSInterfaceDeclaration(node, state) {
|
|
1455
|
+
state.commands.push('interface ');
|
|
1456
|
+
handle(node.id, state);
|
|
1457
|
+
if (node.typeParameters) handle_type_annotation(node.typeParameters, state);
|
|
1458
|
+
if (node.extends) {
|
|
1459
|
+
state.commands.push(' extends ');
|
|
1460
|
+
sequence(node.extends, state, false, handle_type_annotation);
|
|
1461
|
+
}
|
|
1462
|
+
state.commands.push(' {');
|
|
1463
|
+
handle(node.body, state);
|
|
1464
|
+
state.commands.push('}');
|
|
1465
|
+
},
|
|
1466
|
+
|
|
1467
|
+
TSSatisfiesExpression(node, state) {
|
|
1468
|
+
if (node.expression) {
|
|
1469
|
+
const needs_parens =
|
|
1470
|
+
EXPRESSIONS_PRECEDENCE[node.expression.type] < EXPRESSIONS_PRECEDENCE.TSSatisfiesExpression;
|
|
1471
|
+
|
|
1472
|
+
if (needs_parens) {
|
|
1473
|
+
state.commands.push('(');
|
|
1474
|
+
handle(node.expression, state);
|
|
1475
|
+
state.commands.push(')');
|
|
1476
|
+
} else {
|
|
1477
|
+
handle(node.expression, state);
|
|
1478
|
+
}
|
|
1479
|
+
}
|
|
1480
|
+
state.commands.push(' satisfies ');
|
|
1481
|
+
handle_type_annotation(node.typeAnnotation, state);
|
|
1482
|
+
},
|
|
1483
|
+
|
|
1484
|
+
TSTypeAliasDeclaration(node, state) {
|
|
1485
|
+
state.commands.push('type ');
|
|
1486
|
+
handle(node.id, state);
|
|
1487
|
+
if (node.typeParameters) handle_type_annotation(node.typeParameters, state);
|
|
1488
|
+
state.commands.push(' = ');
|
|
1489
|
+
handle_type_annotation(node.typeAnnotation, state);
|
|
1490
|
+
state.commands.push(';');
|
|
1491
|
+
},
|
|
1492
|
+
|
|
1493
|
+
TSQualifiedName(node, state) {
|
|
1494
|
+
handle(node.left, state);
|
|
1495
|
+
state.commands.push('.');
|
|
1496
|
+
handle(node.right, state);
|
|
1497
|
+
},
|
|
1498
|
+
|
|
1203
1499
|
UnaryExpression(node, state) {
|
|
1204
1500
|
state.commands.push(node.operator);
|
|
1205
1501
|
|
package/src/index.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
/** @import { TSESTree } from '@typescript-eslint/types' */
|
|
2
|
+
/** @import { Command, PrintOptions, State } from './types' */
|
|
1
3
|
import { handle } from './handlers.js';
|
|
2
4
|
import { encode } from '@jridgewell/sourcemap-codec';
|
|
3
5
|
|
|
@@ -15,15 +17,7 @@ if (typeof window !== 'undefined' && typeof window.btoa === 'function') {
|
|
|
15
17
|
}
|
|
16
18
|
|
|
17
19
|
/**
|
|
18
|
-
* @
|
|
19
|
-
* sourceMapSource?: string;
|
|
20
|
-
* sourceMapContent?: string;
|
|
21
|
-
* sourceMapEncodeMappings?: boolean; // default true
|
|
22
|
-
* }} PrintOptions
|
|
23
|
-
*/
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* @param {import('estree').Node} node
|
|
20
|
+
* @param {TSESTree.Node} node
|
|
27
21
|
* @param {PrintOptions} opts
|
|
28
22
|
* @returns {{ code: string, map: any }} // TODO
|
|
29
23
|
*/
|
|
@@ -31,6 +25,7 @@ export function print(node, opts = {}) {
|
|
|
31
25
|
if (Array.isArray(node)) {
|
|
32
26
|
return print(
|
|
33
27
|
{
|
|
28
|
+
//@ts-expect-error
|
|
34
29
|
type: 'Program',
|
|
35
30
|
body: node,
|
|
36
31
|
sourceType: 'module'
|
|
@@ -39,7 +34,7 @@ export function print(node, opts = {}) {
|
|
|
39
34
|
);
|
|
40
35
|
}
|
|
41
36
|
|
|
42
|
-
/** @type {
|
|
37
|
+
/** @type {State} */
|
|
43
38
|
const state = {
|
|
44
39
|
commands: [],
|
|
45
40
|
comments: [],
|
|
@@ -76,7 +71,7 @@ export function print(node, opts = {}) {
|
|
|
76
71
|
|
|
77
72
|
let newline = '\n';
|
|
78
73
|
|
|
79
|
-
/** @param {
|
|
74
|
+
/** @param {Command} command */
|
|
80
75
|
function run(command) {
|
|
81
76
|
if (typeof command === 'string') {
|
|
82
77
|
append(command);
|
package/src/public.d.ts
ADDED
package/src/types.d.ts
CHANGED
|
@@ -1,16 +1,39 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
type NodeOf<T extends string, X> = X extends { type: T } ? X : never;
|
|
1
|
+
import { TSESTree } from '@typescript-eslint/types';
|
|
4
2
|
|
|
5
3
|
type Handler<T> = (node: T, state: State) => undefined;
|
|
6
4
|
|
|
7
5
|
export type Handlers = {
|
|
8
|
-
[
|
|
6
|
+
[T in TSESTree.Node['type']]: Handler<Extract<TSESTree.Node, { type: T }>>;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export type TypeAnnotationNodes =
|
|
10
|
+
| TSESTree.TypeNode
|
|
11
|
+
| TSESTree.TypeElement
|
|
12
|
+
| TSESTree.TSTypeAnnotation
|
|
13
|
+
| TSESTree.TSPropertySignature
|
|
14
|
+
| TSESTree.TSTypeParameter
|
|
15
|
+
| TSESTree.TSTypeParameterDeclaration
|
|
16
|
+
| TSESTree.TSTypeParameterInstantiation
|
|
17
|
+
| TSESTree.TSEnumMember
|
|
18
|
+
| TSESTree.TSInterfaceHeritage
|
|
19
|
+
| TSESTree.TSClassImplements
|
|
20
|
+
| TSExpressionWithTypeArguments;
|
|
21
|
+
|
|
22
|
+
type TSExpressionWithTypeArguments = {
|
|
23
|
+
type: 'TSExpressionWithTypeArguments';
|
|
24
|
+
expression: any;
|
|
9
25
|
};
|
|
10
26
|
|
|
27
|
+
// `@typescript-eslint/types` differs from the official `estree` spec by handling
|
|
28
|
+
// comments differently. This is a node which we can use to ensure type saftey.
|
|
29
|
+
export type NodeWithComments = {
|
|
30
|
+
leadingComments?: TSESTree.Comment[] | undefined;
|
|
31
|
+
trailingComments?: TSESTree.Comment[] | undefined;
|
|
32
|
+
} & TSESTree.Node;
|
|
33
|
+
|
|
11
34
|
export interface State {
|
|
12
35
|
commands: Command[];
|
|
13
|
-
comments: Comment[];
|
|
36
|
+
comments: TSESTree.Comment[];
|
|
14
37
|
multiline: boolean;
|
|
15
38
|
}
|
|
16
39
|
|
|
@@ -47,7 +70,13 @@ export interface Sequence {
|
|
|
47
70
|
|
|
48
71
|
export interface CommentChunk {
|
|
49
72
|
type: 'Comment';
|
|
50
|
-
comment: Comment;
|
|
73
|
+
comment: TSESTree.Comment;
|
|
51
74
|
}
|
|
52
75
|
|
|
53
76
|
export type Command = string | Chunk | Newline | Indent | Dedent | Sequence | CommentChunk;
|
|
77
|
+
|
|
78
|
+
export interface PrintOptions {
|
|
79
|
+
sourceMapSource?: string;
|
|
80
|
+
sourceMapContent?: string;
|
|
81
|
+
sourceMapEncodeMappings?: boolean; // default true
|
|
82
|
+
}
|
package/types/index.d.ts
CHANGED
|
@@ -1,16 +1,19 @@
|
|
|
1
|
-
declare module '
|
|
1
|
+
declare module 'dts-buddy' {
|
|
2
|
+
import type { TSESTree } from '@typescript-eslint/types';
|
|
3
|
+
export interface PrintOptions {
|
|
4
|
+
sourceMapSource?: string;
|
|
5
|
+
sourceMapContent?: string;
|
|
6
|
+
sourceMapEncodeMappings?: boolean; // default true
|
|
7
|
+
}
|
|
2
8
|
/**
|
|
3
9
|
* @returns // TODO
|
|
4
10
|
*/
|
|
5
|
-
export function print(node:
|
|
11
|
+
export function print(node: TSESTree.Node, opts?: PrintOptions): {
|
|
6
12
|
code: string;
|
|
7
13
|
map: any;
|
|
8
14
|
};
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
sourceMapContent?: string;
|
|
12
|
-
sourceMapEncodeMappings?: boolean;
|
|
13
|
-
};
|
|
15
|
+
|
|
16
|
+
export {};
|
|
14
17
|
}
|
|
15
18
|
|
|
16
19
|
//# sourceMappingURL=index.d.ts.map
|
package/types/index.d.ts.map
CHANGED
|
@@ -2,13 +2,17 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"file": "index.d.ts",
|
|
4
4
|
"names": [
|
|
5
|
+
"PrintOptions",
|
|
5
6
|
"print"
|
|
6
7
|
],
|
|
7
8
|
"sources": [
|
|
9
|
+
"../src/types.d.ts",
|
|
8
10
|
"../src/index.js"
|
|
9
11
|
],
|
|
10
12
|
"sourcesContent": [
|
|
13
|
+
null,
|
|
11
14
|
null
|
|
12
15
|
],
|
|
13
|
-
"mappings": "
|
|
16
|
+
"mappings": ";;kBA6EiBA,YAAYA;;;;;;;;iBCtDbC,KAAKA",
|
|
17
|
+
"ignoreList": []
|
|
14
18
|
}
|