This repository was archived by the owner on Jun 24, 2022. It is now read-only.
forked from prettier/plugin-ruby
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathprinter.js
138 lines (115 loc) · 3.42 KB
/
printer.js
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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
const { concat, trim } = require("../prettier");
const embed = require("./embed");
const nodes = require("./nodes");
// This is the generic node print function, used to convert any node in the AST
// into its equivalent Doc representation.
function printNode(path, opts, print) {
const { type, body } = path.getValue();
if (type in nodes) {
return nodes[type](path, opts, print);
}
if (type[0] === "@") {
return body;
}
const ast = JSON.stringify(body, null, 2);
throw new Error(`Unsupported node encountered: ${type}\n${ast}`);
}
// This is an escape-hatch to ignore nodes in the tree. If you have a comment
// that includes this pattern, then the entire node will be ignored and just the
// original source will be printed out.
function hasPrettierIgnore(path) {
const node = path.getValue();
return (
node.comments &&
node.comments.some((comment) => comment.value.includes("prettier-ignore"))
);
}
const noComments = [
"args",
"args_add_block",
"args_add_star",
"mlhs",
"mlhs_add_post",
"mlhs_add_star",
"mlhs_paren"
];
// Certain nodes are used more for organizational purposed than for actually
// displaying content, so we tell prettier that we don't want comments attached
// to them.
function canAttachComment(node) {
return !noComments.includes(node.type);
}
// This function tells prettier how to recurse down our AST so that it can find
// where it needs to attach the comments.
function getCommentChildNodes(node) {
switch (node.type) {
case "heredoc":
return [node.beging];
case "aryptn":
return [node.body[0]]
.concat(node.body[1])
.concat(node.body[2])
.concat(node.body[3]);
case "hshptn": {
const pairs = node.body[1];
const values = pairs.reduce((left, right) => left.concat(right), []);
return [node.body[0]].concat(values).concat(node.body[2]);
}
case "params": {
const [reqs, optls, rest, post, kwargs, kwargRest, block] = node.body;
let parts = reqs || [];
(optls || []).forEach((optl) => {
parts = parts.concat(optl);
});
if (rest) {
parts.push(rest);
}
parts = parts.concat(post || []);
(kwargs || []).forEach((kwarg) => {
if (kwarg[1]) {
parts = parts.concat(kwarg);
} else {
parts.push(kwarg[0]);
}
});
if (kwargRest && kwargRest !== "nil") {
parts.push(kwargRest);
}
if (block) {
parts.push(block);
}
return parts;
}
default: {
if (Array.isArray(node.body)) {
return node.body.filter((child) => child && typeof child === "object");
}
return [];
}
}
}
// This is the generic print function for any comment in the AST. It handles
// both regular comments that begin with a # and embdoc comments, which are
// surrounded by =begin..=end.
function printComment(path, _opts) {
const comment = path.getValue();
if (comment.type === "@comment") {
return `#${comment.value}`;
}
return concat([trim, comment.value]);
}
// To be honest I'm not 100% sure this function is actually necessary, but it
// *feels* like a block comment equivalent in JavaScript so I'm going to leave
// it in place for now.
function isBlockComment(comment) {
return comment.type === "@embdoc";
}
module.exports = {
embed,
print: printNode,
hasPrettierIgnore,
canAttachComment,
getCommentChildNodes,
printComment,
isBlockComment
};