prettier 1.5.2 → 1.6.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +58 -1
- data/CONTRIBUTING.md +2 -2
- data/README.md +41 -12
- data/node_modules/prettier/bin-prettier.js +13848 -11589
- data/node_modules/prettier/doc.js +4961 -0
- data/node_modules/prettier/index.js +19466 -16783
- data/node_modules/prettier/package.json +23 -0
- data/node_modules/prettier/parser-angular.js +67 -0
- data/node_modules/prettier/parser-babel.js +22 -0
- data/node_modules/prettier/parser-espree.js +22 -0
- data/node_modules/prettier/parser-flow.js +22 -0
- data/node_modules/prettier/parser-glimmer.js +1 -0
- data/node_modules/prettier/parser-graphql.js +1 -0
- data/node_modules/prettier/parser-html.js +132 -0
- data/node_modules/prettier/parser-markdown.js +34 -0
- data/node_modules/prettier/parser-meriyah.js +22 -0
- data/node_modules/prettier/parser-postcss.js +22 -0
- data/node_modules/prettier/parser-typescript.js +22 -0
- data/node_modules/prettier/parser-yaml.js +15 -0
- data/node_modules/prettier/third-party.js +1671 -864
- data/package.json +5 -5
- data/rubocop.yml +12 -0
- data/src/haml/parser.js +6 -5
- data/src/haml/parser.rb +8 -3
- data/src/haml/printer.js +428 -18
- data/src/parser/netcat.js +0 -2
- data/src/parser/parseSync.js +153 -14
- data/src/parser/server.rb +5 -0
- data/src/plugin.js +7 -1
- data/src/rbs/parser.js +3 -5
- data/src/rbs/parser.rb +7 -3
- data/src/rbs/printer.js +46 -8
- data/src/ruby/nodes/args.js +111 -19
- data/src/ruby/nodes/calls.js +50 -3
- data/src/ruby/nodes/conditionals.js +47 -45
- data/src/ruby/nodes/hashes.js +5 -14
- data/src/ruby/nodes/params.js +2 -9
- data/src/ruby/nodes/strings.js +97 -2
- data/src/ruby/parser.js +3 -5
- data/src/ruby/parser.rb +76 -31
- data/src/ruby/printer.js +10 -1
- data/src/utils/inlineEnsureParens.js +1 -0
- data/src/utils/noIndent.js +0 -1
- data/src/utils/skipAssignIndent.js +8 -1
- metadata +16 -14
- data/src/haml/nodes/comment.js +0 -27
- data/src/haml/nodes/doctype.js +0 -34
- data/src/haml/nodes/filter.js +0 -16
- data/src/haml/nodes/hamlComment.js +0 -21
- data/src/haml/nodes/plain.js +0 -6
- data/src/haml/nodes/root.js +0 -8
- data/src/haml/nodes/script.js +0 -33
- data/src/haml/nodes/silentScript.js +0 -59
- data/src/haml/nodes/tag.js +0 -193
- data/src/parser/getLang.js +0 -32
- data/src/parser/getNetcat.js +0 -50
- data/src/parser/requestParse.js +0 -74
data/src/ruby/nodes/calls.js
CHANGED
@@ -4,6 +4,7 @@ const {
|
|
4
4
|
hardline,
|
5
5
|
ifBreak,
|
6
6
|
indent,
|
7
|
+
join,
|
7
8
|
softline
|
8
9
|
} = require("../../prettier");
|
9
10
|
const { makeCall, noIndent } = require("../../utils");
|
@@ -32,12 +33,23 @@ function printCall(path, opts, print) {
|
|
32
33
|
|
33
34
|
// The right side of the call node, as in everything including the operator
|
34
35
|
// and beyond.
|
35
|
-
|
36
|
+
let rightSideDoc = concat([
|
36
37
|
receiverNode.comments ? hardline : softline,
|
37
38
|
operatorDoc,
|
38
39
|
messageDoc
|
39
40
|
]);
|
40
41
|
|
42
|
+
// This is very specialized behavior wherein we group .where.not calls
|
43
|
+
// together because it looks better. For more information, see
|
44
|
+
// https://github.com/prettier/plugin-ruby/issues/862.
|
45
|
+
if (
|
46
|
+
receiverNode.type === "call" &&
|
47
|
+
receiverNode.body[2].body === "where" &&
|
48
|
+
messageDoc === "not"
|
49
|
+
) {
|
50
|
+
rightSideDoc = concat([operatorDoc, messageDoc]);
|
51
|
+
}
|
52
|
+
|
41
53
|
// Get a reference to the parent node so we can check if we're inside a chain
|
42
54
|
const parentNode = path.getParentNode();
|
43
55
|
|
@@ -109,9 +121,38 @@ function printMethodAddArg(path, opts, print) {
|
|
109
121
|
parentNode.firstReceiverType = node.firstReceiverType;
|
110
122
|
}
|
111
123
|
|
124
|
+
// This is the threshold at which we will start to try to make a nicely
|
125
|
+
// indented call chain. For the most part, it's always 3.
|
126
|
+
let threshold = 3;
|
127
|
+
|
128
|
+
// Here, we have very specialized behavior where if we're within a sig block,
|
129
|
+
// then we're going to assume we're creating a Sorbet type signature. In that
|
130
|
+
// case, we really want the threshold to be lowered to 2 so that we create
|
131
|
+
// method chains off of any two method calls within the block. For more
|
132
|
+
// details, see
|
133
|
+
// https://github.com/prettier/plugin-ruby/issues/863.
|
134
|
+
let sigBlock = path.getParentNode(2);
|
135
|
+
if (sigBlock) {
|
136
|
+
// If we're at a do_block, then we want to go one more level up. This is
|
137
|
+
// because do_blocks have bodystmt nodes instead of just stmt nodes.
|
138
|
+
if (sigBlock.type === "do_block") {
|
139
|
+
sigBlock = path.getParentNode(3);
|
140
|
+
}
|
141
|
+
|
142
|
+
if (
|
143
|
+
sigBlock.type === "method_add_block" &&
|
144
|
+
sigBlock.body[1] &&
|
145
|
+
sigBlock.body[0].type === "method_add_arg" &&
|
146
|
+
sigBlock.body[0].body[0].type === "fcall" &&
|
147
|
+
sigBlock.body[0].body[0].body[0].body === "sig"
|
148
|
+
) {
|
149
|
+
threshold = 2;
|
150
|
+
}
|
151
|
+
}
|
152
|
+
|
112
153
|
// If we're at the top of a chain, then we're going to print out a nice
|
113
154
|
// multi-line layout if this doesn't break into multiple lines.
|
114
|
-
if (!chained.includes(parentNode.type) && (node.chain || 0) >=
|
155
|
+
if (!chained.includes(parentNode.type) && (node.chain || 0) >= threshold) {
|
115
156
|
// This is pretty specialized behavior. Basically if we're at the top of a
|
116
157
|
// chain but we've only had method calls without arguments and now we have
|
117
158
|
// arguments, then we're effectively trying to call a method with arguments
|
@@ -133,7 +174,13 @@ function printMethodAddArg(path, opts, print) {
|
|
133
174
|
);
|
134
175
|
}
|
135
176
|
|
136
|
-
|
177
|
+
// If there are already parentheses, then we can just use the doc that's
|
178
|
+
// already printed.
|
179
|
+
if (argNode.type == "arg_paren") {
|
180
|
+
return concat([methodDoc, argsDoc]);
|
181
|
+
}
|
182
|
+
|
183
|
+
return concat([methodDoc, " ", join(", ", argsDoc), " "]);
|
137
184
|
}
|
138
185
|
|
139
186
|
function printMethodAddBlock(path, opts, print) {
|
@@ -190,57 +190,59 @@ const canTernary = (path) => {
|
|
190
190
|
};
|
191
191
|
|
192
192
|
// A normalized print function for both `if` and `unless` nodes.
|
193
|
-
const printConditional =
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
193
|
+
const printConditional =
|
194
|
+
(keyword) =>
|
195
|
+
(path, { rubyModifier }, print) => {
|
196
|
+
if (canTernary(path)) {
|
197
|
+
let ternaryParts = [path.call(print, "body", 0), " ? "].concat(
|
198
|
+
printTernaryClauses(
|
199
|
+
keyword,
|
200
|
+
path.call(print, "body", 1),
|
201
|
+
path.call(print, "body", 2, "body", 0)
|
202
|
+
)
|
203
|
+
);
|
204
|
+
|
205
|
+
if (["binary", "call"].includes(path.getParentNode().type)) {
|
206
|
+
ternaryParts = ["("].concat(ternaryParts).concat(")");
|
207
|
+
}
|
208
|
+
|
209
|
+
return group(
|
210
|
+
ifBreak(printWithAddition(keyword, path, print), concat(ternaryParts))
|
211
|
+
);
|
205
212
|
}
|
206
213
|
|
207
|
-
|
208
|
-
ifBreak(printWithAddition(keyword, path, print), concat(ternaryParts))
|
209
|
-
);
|
210
|
-
}
|
211
|
-
|
212
|
-
const [predicate, statements, addition] = path.getValue().body;
|
214
|
+
const [predicate, statements, addition] = path.getValue().body;
|
213
215
|
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
216
|
+
// If there's an additional clause that wasn't matched earlier, we know we
|
217
|
+
// can't go for the inline option.
|
218
|
+
if (addition) {
|
219
|
+
return group(printWithAddition(keyword, path, print, { breaking: true }));
|
220
|
+
}
|
219
221
|
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
222
|
+
// If the body of the conditional is empty, then we explicitly have to use the
|
223
|
+
// block form.
|
224
|
+
if (isEmptyStmts(statements)) {
|
225
|
+
return concat([
|
226
|
+
`${keyword} `,
|
227
|
+
align(keyword.length + 1, path.call(print, "body", 0)),
|
228
|
+
concat([hardline, "end"])
|
229
|
+
]);
|
230
|
+
}
|
229
231
|
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
232
|
+
// If the predicate of the conditional contains an assignment, then we can't
|
233
|
+
// know for sure that it doesn't impact the body of the conditional, so we
|
234
|
+
// have to default to the block form.
|
235
|
+
if (containsAssignment(predicate)) {
|
236
|
+
return concat([
|
237
|
+
`${keyword} `,
|
238
|
+
align(keyword.length + 1, path.call(print, "body", 0)),
|
239
|
+
indent(concat([hardline, path.call(print, "body", 1)])),
|
240
|
+
concat([hardline, "end"])
|
241
|
+
]);
|
242
|
+
}
|
241
243
|
|
242
|
-
|
243
|
-
};
|
244
|
+
return printSingle(keyword)(path, { rubyModifier }, print);
|
245
|
+
};
|
244
246
|
|
245
247
|
module.exports = {
|
246
248
|
else: (path, opts, print) => {
|
data/src/ruby/nodes/hashes.js
CHANGED
@@ -56,28 +56,19 @@ function printHashKeyLabel(path, print) {
|
|
56
56
|
case "symbol_literal":
|
57
57
|
return concat([path.call(print, "body", 0), ":"]);
|
58
58
|
case "dyna_symbol": {
|
59
|
-
|
60
|
-
|
61
|
-
// We're going to slice off the starting colon character so that we can
|
62
|
-
// move it to the end. If there are comments, then we're going to go
|
63
|
-
// further into the printed doc nodes.
|
64
|
-
if (parts[0] === ":") {
|
65
|
-
parts.splice(0, 1);
|
66
|
-
} else {
|
67
|
-
parts[1].parts.splice(0, 1);
|
68
|
-
}
|
69
|
-
|
70
|
-
return concat(parts.concat(":"));
|
59
|
+
return concat([print(path), ":"]);
|
71
60
|
}
|
72
61
|
}
|
73
62
|
}
|
74
63
|
|
75
64
|
function printHashKeyRocket(path, print) {
|
76
65
|
const node = path.getValue();
|
77
|
-
|
66
|
+
let doc = print(path);
|
78
67
|
|
79
68
|
if (node.type === "@label") {
|
80
|
-
|
69
|
+
doc = concat([":", doc.slice(0, doc.length - 1)]);
|
70
|
+
} else if (node.type === "dyna_symbol") {
|
71
|
+
doc = concat([":", doc]);
|
81
72
|
}
|
82
73
|
|
83
74
|
return concat([doc, " =>"]);
|
data/src/ruby/nodes/params.js
CHANGED
@@ -17,15 +17,8 @@ function printRestParam(symbol) {
|
|
17
17
|
}
|
18
18
|
|
19
19
|
function printParams(path, opts, print) {
|
20
|
-
const [
|
21
|
-
|
22
|
-
optls,
|
23
|
-
rest,
|
24
|
-
post,
|
25
|
-
kwargs,
|
26
|
-
kwargRest,
|
27
|
-
block
|
28
|
-
] = path.getValue().body;
|
20
|
+
const [reqs, optls, rest, post, kwargs, kwargRest, block] =
|
21
|
+
path.getValue().body;
|
29
22
|
let parts = [];
|
30
23
|
|
31
24
|
if (reqs) {
|
data/src/ruby/nodes/strings.js
CHANGED
@@ -82,13 +82,108 @@ function printChar(path, { rubySingleQuote }, _print) {
|
|
82
82
|
return concat([quote, body.slice(1), quote]);
|
83
83
|
}
|
84
84
|
|
85
|
+
function printPercentSDynaSymbol(path, opts, print) {
|
86
|
+
const node = path.getValue();
|
87
|
+
const parts = [];
|
88
|
+
|
89
|
+
// Push on the quote, which includes the opening character.
|
90
|
+
parts.push(node.quote);
|
91
|
+
|
92
|
+
path.each((childPath) => {
|
93
|
+
const childNode = childPath.getValue();
|
94
|
+
|
95
|
+
if (childNode.type !== "@tstring_content") {
|
96
|
+
// Here we are printing an embedded variable or expression.
|
97
|
+
parts.push(print(childPath));
|
98
|
+
} else {
|
99
|
+
// Here we are printing plain string content.
|
100
|
+
parts.push(join(literalline, childNode.body.split("\n")));
|
101
|
+
}
|
102
|
+
}, "body");
|
103
|
+
|
104
|
+
// Push on the closing character, which is the opposite of the third
|
105
|
+
// character from the opening.
|
106
|
+
parts.push(quotePairs[node.quote[2]]);
|
107
|
+
|
108
|
+
return concat(parts);
|
109
|
+
}
|
110
|
+
|
111
|
+
// We don't actually want to print %s symbols, as they're much more rarely seen
|
112
|
+
// in the wild. But we're going to be forced into it if it's a multi-line symbol
|
113
|
+
// or if the quoting would get super complicated.
|
114
|
+
function shouldPrintPercentSDynaSymbol(node) {
|
115
|
+
// We shouldn't print a %s dyna symbol if it was not already that way in the
|
116
|
+
// original source.
|
117
|
+
if (node.quote[0] !== "%") {
|
118
|
+
return false;
|
119
|
+
}
|
120
|
+
|
121
|
+
// Here we're going to check if there is a closing character, a new line, or a
|
122
|
+
// quote in the content of the dyna symbol. If there is, then quoting could
|
123
|
+
// get weird, so just bail out and stick to the original bounds in the source.
|
124
|
+
const closing = quotePairs[node.quote[2]];
|
125
|
+
|
126
|
+
return node.body.some(
|
127
|
+
(child) =>
|
128
|
+
child.type === "@tstring_content" &&
|
129
|
+
(child.body.includes("\n") ||
|
130
|
+
child.body.includes(closing) ||
|
131
|
+
child.body.includes("'") ||
|
132
|
+
child.body.includes('"'))
|
133
|
+
);
|
134
|
+
}
|
135
|
+
|
85
136
|
// Prints a dynamic symbol. Assumes there's a quote property attached to the
|
86
137
|
// node that will tell us which quote to use when printing. We're just going to
|
87
138
|
// use whatever quote was provided.
|
139
|
+
//
|
140
|
+
// In the case of a plain dyna symbol, node.quote will be either :" or :'
|
141
|
+
// For %s dyna symbols, node.quote will be %s[, %s(, %s{, or %s<
|
88
142
|
function printDynaSymbol(path, opts, print) {
|
89
|
-
const
|
143
|
+
const node = path.getValue();
|
144
|
+
|
145
|
+
if (shouldPrintPercentSDynaSymbol(node)) {
|
146
|
+
return printPercentSDynaSymbol(path, opts, print);
|
147
|
+
}
|
148
|
+
|
149
|
+
const parts = [];
|
150
|
+
let quote;
|
151
|
+
|
152
|
+
if (isQuoteLocked(node)) {
|
153
|
+
if (node.quote.startsWith("%")) {
|
154
|
+
quote = opts.rubySingleQuote ? "'" : '"';
|
155
|
+
} else if (node.quote.startsWith(":")) {
|
156
|
+
quote = node.quote.slice(1);
|
157
|
+
} else {
|
158
|
+
quote = node.quote;
|
159
|
+
}
|
160
|
+
} else {
|
161
|
+
quote = opts.rubySingleQuote && isSingleQuotable(node) ? "'" : '"';
|
162
|
+
}
|
163
|
+
|
164
|
+
parts.push(quote);
|
165
|
+
path.each((childPath) => {
|
166
|
+
const child = childPath.getValue();
|
167
|
+
|
168
|
+
if (child.type !== "@tstring_content") {
|
169
|
+
parts.push(print(childPath));
|
170
|
+
} else {
|
171
|
+
parts.push(
|
172
|
+
join(literalline, normalizeQuotes(child.body, quote).split("\n"))
|
173
|
+
);
|
174
|
+
}
|
175
|
+
}, "body");
|
176
|
+
|
177
|
+
parts.push(quote);
|
178
|
+
|
179
|
+
// If we're inside of an assoc_new node as the key, then it will handle
|
180
|
+
// printing the : on its own since it could change sides.
|
181
|
+
const parentNode = path.getParentNode();
|
182
|
+
if (parentNode.type !== "assoc_new" || parentNode.body[0] !== node) {
|
183
|
+
parts.unshift(":");
|
184
|
+
}
|
90
185
|
|
91
|
-
return concat(
|
186
|
+
return concat(parts);
|
92
187
|
}
|
93
188
|
|
94
189
|
function printStringConcat(path, opts, print) {
|
data/src/ruby/parser.js
CHANGED
@@ -4,16 +4,14 @@ const parseSync = require("../parser/parseSync");
|
|
4
4
|
// to prettier a JavaScript object that is the equivalent AST that represents
|
5
5
|
// the code stored in that string. We accomplish this by spawning a new Ruby
|
6
6
|
// process of parser.rb and reading JSON off STDOUT.
|
7
|
-
function parse(text, _parsers,
|
8
|
-
return parseSync("ruby", text);
|
7
|
+
function parse(text, _parsers, opts) {
|
8
|
+
return parseSync("ruby", text, opts);
|
9
9
|
}
|
10
10
|
|
11
|
-
const pragmaPattern = /#\s*@(prettier|format)/;
|
12
|
-
|
13
11
|
// This function handles checking whether or not the source string has the
|
14
12
|
// pragma for prettier. This is an optional workflow for incremental adoption.
|
15
13
|
function hasPragma(text) {
|
16
|
-
return
|
14
|
+
return /^\s*#[^\S\n]*@(format|prettier)\s*(\n|$)/.test(text);
|
17
15
|
}
|
18
16
|
|
19
17
|
// This function is critical for comments and cursor support, and is responsible
|
data/src/ruby/parser.rb
CHANGED
@@ -13,8 +13,7 @@ if (RUBY_MAJOR < 2) || ((RUBY_MAJOR == 2) && (RUBY_MINOR < 5))
|
|
13
13
|
exit 1
|
14
14
|
end
|
15
15
|
|
16
|
-
require '
|
17
|
-
require 'json'
|
16
|
+
require 'json' unless defined?(JSON)
|
18
17
|
require 'ripper'
|
19
18
|
|
20
19
|
module Prettier
|
@@ -54,6 +53,35 @@ class Prettier::Parser < Ripper
|
|
54
53
|
end
|
55
54
|
end
|
56
55
|
|
56
|
+
# This is a small wrapper around the value of a node for those specific events
|
57
|
+
# that need extra handling. (For example: statement, body statement, and
|
58
|
+
# rescue nodes which all need extra information to determine their character
|
59
|
+
# boundaries.)
|
60
|
+
class Node
|
61
|
+
attr_reader :parser, :value
|
62
|
+
|
63
|
+
def initialize(parser, value)
|
64
|
+
@parser = parser
|
65
|
+
@value = value
|
66
|
+
end
|
67
|
+
|
68
|
+
def [](key)
|
69
|
+
value[key]
|
70
|
+
end
|
71
|
+
|
72
|
+
def dig(*keys)
|
73
|
+
value.dig(*keys)
|
74
|
+
end
|
75
|
+
|
76
|
+
def to_json(*opts)
|
77
|
+
value.to_json(*opts)
|
78
|
+
end
|
79
|
+
|
80
|
+
def pretty_print(q)
|
81
|
+
q.pp_hash(self)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
57
85
|
attr_reader :source, :lines, :scanner_events
|
58
86
|
|
59
87
|
# This is an attr_accessor so Stmts objects can grab comments out of this
|
@@ -617,19 +645,19 @@ class Prettier::Parser < Ripper
|
|
617
645
|
# bodystmt can't actually determine its bounds appropriately because it
|
618
646
|
# doesn't necessarily know where it started. So the parent node needs to
|
619
647
|
# report back down into this one where it goes.
|
620
|
-
class BodyStmt <
|
648
|
+
class BodyStmt < Node
|
621
649
|
def bind(sc, ec)
|
622
|
-
merge!(sc: sc, ec: ec)
|
623
|
-
parts =
|
650
|
+
value.merge!(sc: sc, ec: ec)
|
651
|
+
parts = value[:body]
|
624
652
|
|
625
653
|
# Here we're going to determine the bounds for the stmts
|
626
654
|
consequent = parts[1..-1].compact.first
|
627
|
-
|
655
|
+
value[:body][0].bind(sc, consequent ? consequent[:sc] : ec)
|
628
656
|
|
629
657
|
# Next we're going to determine the rescue clause if there is one
|
630
658
|
if parts[1]
|
631
659
|
consequent = parts[2..-1].compact.first
|
632
|
-
|
660
|
+
value[:body][1].bind_end(consequent ? consequent[:sc] : ec)
|
633
661
|
end
|
634
662
|
end
|
635
663
|
end
|
@@ -638,6 +666,7 @@ class Prettier::Parser < Ripper
|
|
638
666
|
# of clauses within the body of a method or block.
|
639
667
|
def on_bodystmt(stmts, rescued, ensured, elsed)
|
640
668
|
BodyStmt.new(
|
669
|
+
self,
|
641
670
|
type: :bodystmt,
|
642
671
|
body: [stmts, rescued, ensured, elsed],
|
643
672
|
sl: lineno,
|
@@ -662,7 +691,7 @@ class Prettier::Parser < Ripper
|
|
662
691
|
body: [block_var, stmts],
|
663
692
|
sl: beging[:sl],
|
664
693
|
sc: beging[:sc],
|
665
|
-
el: ending[:el],
|
694
|
+
el: [ending[:el], stmts[:el]].max,
|
666
695
|
ec: ending[:ec]
|
667
696
|
}
|
668
697
|
end
|
@@ -715,7 +744,7 @@ class Prettier::Parser < Ripper
|
|
715
744
|
body: [receiver, oper, sending],
|
716
745
|
sl: receiver[:sl],
|
717
746
|
sc: receiver[:sc],
|
718
|
-
el: ending[:el],
|
747
|
+
el: [ending[:el], receiver[:el]].max,
|
719
748
|
ec: ending[:ec]
|
720
749
|
}
|
721
750
|
end
|
@@ -1063,7 +1092,7 @@ class Prettier::Parser < Ripper
|
|
1063
1092
|
|
1064
1093
|
beging.merge(
|
1065
1094
|
type: :dyna_symbol,
|
1066
|
-
quote: beging[:body]
|
1095
|
+
quote: beging[:body],
|
1067
1096
|
body: string[:body],
|
1068
1097
|
el: ending[:el],
|
1069
1098
|
ec: ending[:ec]
|
@@ -1729,6 +1758,28 @@ class Prettier::Parser < Ripper
|
|
1729
1758
|
)
|
1730
1759
|
end
|
1731
1760
|
|
1761
|
+
# A special parser error so that we can get nice syntax displays on the error
|
1762
|
+
# message when prettier prints out the results.
|
1763
|
+
class ParserError < StandardError
|
1764
|
+
attr_reader :lineno, :column
|
1765
|
+
|
1766
|
+
def initialize(error, lineno, column)
|
1767
|
+
super(error)
|
1768
|
+
@lineno = lineno
|
1769
|
+
@column = column
|
1770
|
+
end
|
1771
|
+
end
|
1772
|
+
|
1773
|
+
# If we encounter a parse error, just immediately bail out so that our runner
|
1774
|
+
# can catch it.
|
1775
|
+
def on_parse_error(error, *)
|
1776
|
+
raise ParserError.new(error, lineno, column)
|
1777
|
+
end
|
1778
|
+
alias on_alias_error on_parse_error
|
1779
|
+
alias on_assign_error on_parse_error
|
1780
|
+
alias on_class_name_error on_parse_error
|
1781
|
+
alias on_param_error on_parse_error
|
1782
|
+
|
1732
1783
|
# The program node is the very top of the AST. Here we'll attach all of
|
1733
1784
|
# the comments that we've gathered up over the course of parsing the
|
1734
1785
|
# source string. We'll also attach on the __END__ content if there was
|
@@ -1823,12 +1874,12 @@ class Prettier::Parser < Ripper
|
|
1823
1874
|
# doesn't really have all of the information that it needs in order to
|
1824
1875
|
# determine its ending. Therefore it relies on its parent bodystmt node to
|
1825
1876
|
# report its ending to it.
|
1826
|
-
class Rescue <
|
1877
|
+
class Rescue < Node
|
1827
1878
|
def bind_end(ec)
|
1828
|
-
merge!(ec: ec)
|
1879
|
+
value.merge!(ec: ec)
|
1829
1880
|
|
1830
|
-
stmts =
|
1831
|
-
consequent =
|
1881
|
+
stmts = value[:body][1]
|
1882
|
+
consequent = value[:body][2]
|
1832
1883
|
|
1833
1884
|
if consequent
|
1834
1885
|
consequent.bind_end(ec)
|
@@ -1864,6 +1915,7 @@ class Prettier::Parser < Ripper
|
|
1864
1915
|
end
|
1865
1916
|
|
1866
1917
|
Rescue.new(
|
1918
|
+
self,
|
1867
1919
|
beging.merge!(
|
1868
1920
|
type: :rescue,
|
1869
1921
|
body: [rescue_ex, stmts, consequent],
|
@@ -1964,36 +2016,29 @@ class Prettier::Parser < Ripper
|
|
1964
2016
|
# stmts nodes will report back down the location information. We then
|
1965
2017
|
# propagate that onto void_stmt nodes inside the stmts in order to make sure
|
1966
2018
|
# all comments get printed appropriately.
|
1967
|
-
class Stmts <
|
1968
|
-
attr_reader :parser
|
1969
|
-
|
1970
|
-
def initialize(parser, values)
|
1971
|
-
@parser = parser
|
1972
|
-
__setobj__(values)
|
1973
|
-
end
|
1974
|
-
|
2019
|
+
class Stmts < Node
|
1975
2020
|
def bind(sc, ec)
|
1976
|
-
merge!(sc: sc, ec: ec)
|
2021
|
+
value.merge!(sc: sc, ec: ec)
|
1977
2022
|
|
1978
|
-
if
|
1979
|
-
|
2023
|
+
if value[:body][0][:type] == :void_stmt
|
2024
|
+
value[:body][0].merge!(sc: sc, ec: sc)
|
1980
2025
|
end
|
1981
2026
|
|
1982
2027
|
attach_comments(sc, ec)
|
1983
2028
|
end
|
1984
2029
|
|
1985
2030
|
def bind_end(ec)
|
1986
|
-
merge!(ec: ec)
|
2031
|
+
value.merge!(ec: ec)
|
1987
2032
|
end
|
1988
2033
|
|
1989
2034
|
def <<(statement)
|
1990
|
-
if
|
1991
|
-
merge!(statement.slice(:el, :ec))
|
2035
|
+
if value[:body].any?
|
2036
|
+
value.merge!(statement.slice(:el, :ec))
|
1992
2037
|
else
|
1993
|
-
merge!(statement.slice(:sl, :el, :sc, :ec))
|
2038
|
+
value.merge!(statement.slice(:sl, :el, :sc, :ec))
|
1994
2039
|
end
|
1995
2040
|
|
1996
|
-
|
2041
|
+
value[:body] << statement
|
1997
2042
|
self
|
1998
2043
|
end
|
1999
2044
|
|
@@ -2010,7 +2055,7 @@ class Prettier::Parser < Ripper
|
|
2010
2055
|
return if attachable.empty?
|
2011
2056
|
|
2012
2057
|
parser.comments -= attachable
|
2013
|
-
|
2058
|
+
value[:body] = (value[:body] + attachable).sort_by! { |node| node[:sc] }
|
2014
2059
|
end
|
2015
2060
|
end
|
2016
2061
|
|