-
Notifications
You must be signed in to change notification settings - Fork 85
Expand file tree
/
Copy pathslangPrinter.ts
More file actions
75 lines (66 loc) · 2.46 KB
/
slangPrinter.ts
File metadata and controls
75 lines (66 loc) · 2.46 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
import { isBlockComment } from './slang-utils/is-comment.js';
import { locEnd, locStart } from './slang-utils/loc.js';
import type { AstPath, Doc, ParserOptions } from 'prettier';
import type { AstNode, StrictAstNode } from './slang-nodes/types.d.ts';
import type { PrintFunction } from './types.d.ts';
import type { ArgumentsDeclaration } from './slang-nodes/ArgumentsDeclaration.js';
function hasNodeIgnoreComment({ comments }: StrictAstNode): boolean {
// Prettier sets SourceUnit's comments to undefined after assigning comments
// to each node.
return Boolean(
comments?.some(
(comment) =>
comment.value
.slice(2, isBlockComment(comment) ? -2 : undefined)
.trim() === 'prettier-ignore'
)
);
}
function ignoreComments(path: AstPath<AstNode>): void {
const node = path.node;
// We ignore anything that is not an object
if (node === null || typeof node !== 'object') return;
let key: keyof StrictAstNode;
for (key in node) {
switch (key) {
// We ignore `kind`, `loc`, and `comments` since these are added by the
// parser. `updateMetadata` is an internal function.
case 'kind':
case 'loc':
case 'updateMetadata':
break;
// The key `comments` will contain every comment for this node.
case 'comments':
path.each((commentPath) => (commentPath.node.printed = true), key);
break;
default:
// If the value for that key is an Array or an Object we go deeper.
const childNode = node[key];
if (typeof childNode === 'object') {
if (Array.isArray(childNode)) {
path.each(ignoreComments, key);
return;
}
path.call(ignoreComments, key);
}
}
}
}
// Nodes take care of undefined and string properties so we can restrict path
// to AstPath<StrictAstNode>
function genericPrint(
path: AstPath<Exclude<StrictAstNode, ArgumentsDeclaration>>,
options: ParserOptions<AstNode>,
print: PrintFunction
): Doc {
const node = path.node;
if (hasNodeIgnoreComment(node)) {
ignoreComments(path);
return options.originalText.slice(locStart(node), locEnd(node));
}
// Since each node has a print function with a specific AstPath, the union of
// all nodes into AstNode creates a print function with an AstPath of the
// intersection of all nodes. This forces us to cast this with a never type.
return node.print(path as AstPath<never>, print, options);
}
export default genericPrint;