prettier 1.2.4 → 1.5.1
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +351 -361
- data/README.md +11 -96
- data/node_modules/prettier/index.js +54 -54
- data/package.json +1 -2
- data/src/haml/embed.js +87 -0
- data/src/haml/nodes/comment.js +27 -0
- data/src/haml/nodes/doctype.js +34 -0
- data/src/haml/nodes/filter.js +16 -0
- data/src/haml/nodes/hamlComment.js +21 -0
- data/src/haml/nodes/plain.js +6 -0
- data/src/haml/nodes/root.js +8 -0
- data/src/haml/nodes/script.js +33 -0
- data/src/haml/nodes/silentScript.js +59 -0
- data/src/haml/nodes/tag.js +193 -0
- data/src/haml/parser.js +22 -0
- data/src/haml/parser.rb +138 -0
- data/src/haml/printer.js +28 -0
- data/src/parser/getLang.js +32 -0
- data/src/parser/getNetcat.js +50 -0
- data/src/parser/netcat.js +15 -0
- data/src/parser/parseSync.js +33 -0
- data/src/parser/requestParse.js +74 -0
- data/src/parser/server.rb +61 -0
- data/src/plugin.js +26 -4
- data/src/rbs/parser.js +39 -0
- data/src/rbs/parser.rb +94 -0
- data/src/rbs/printer.js +605 -0
- data/src/ruby/embed.js +54 -8
- data/src/ruby/nodes/args.js +20 -6
- data/src/ruby/nodes/arrays.js +36 -33
- data/src/ruby/nodes/calls.js +12 -43
- data/src/ruby/nodes/class.js +17 -27
- data/src/ruby/nodes/commands.js +8 -3
- data/src/ruby/nodes/conditionals.js +1 -1
- data/src/ruby/nodes/hashes.js +28 -14
- data/src/ruby/nodes/loops.js +4 -10
- data/src/ruby/nodes/methods.js +4 -11
- data/src/ruby/nodes/rescue.js +32 -25
- data/src/ruby/nodes/statements.js +6 -5
- data/src/ruby/nodes/strings.js +7 -6
- data/src/ruby/parser.js +2 -50
- data/src/ruby/parser.rb +113 -43
- data/src/ruby/printer.js +8 -5
- data/src/utils.js +1 -0
- data/src/utils/inlineEnsureParens.js +8 -1
- data/src/utils/isEmptyBodyStmt.js +7 -0
- data/src/utils/isEmptyStmts.js +9 -5
- data/src/utils/noIndent.js +1 -0
- data/src/utils/printEmptyCollection.js +9 -2
- metadata +25 -2
@@ -219,7 +219,7 @@ const printConditional = (keyword) => (path, { rubyModifier }, print) => {
|
|
219
219
|
|
220
220
|
// If the body of the conditional is empty, then we explicitly have to use the
|
221
221
|
// block form.
|
222
|
-
if (isEmptyStmts(statements)
|
222
|
+
if (isEmptyStmts(statements)) {
|
223
223
|
return concat([
|
224
224
|
`${keyword} `,
|
225
225
|
align(keyword.length + 1, path.call(print, "body", 0)),
|
data/src/ruby/nodes/hashes.js
CHANGED
@@ -6,6 +6,7 @@ const {
|
|
6
6
|
join,
|
7
7
|
line
|
8
8
|
} = require("../../prettier");
|
9
|
+
|
9
10
|
const {
|
10
11
|
getTrailingComma,
|
11
12
|
printEmptyCollection,
|
@@ -89,6 +90,13 @@ function printAssocNew(path, opts, print) {
|
|
89
90
|
const parts = [path.call((keyPath) => keyPrinter(keyPath, print), "body", 0)];
|
90
91
|
const valueDoc = path.call(print, "body", 1);
|
91
92
|
|
93
|
+
// If we're printing a child hash then we want it to break along with its
|
94
|
+
// parent hash, so we don't group the parts.
|
95
|
+
if (valueNode.type === "hash") {
|
96
|
+
parts.push(" ", valueDoc);
|
97
|
+
return concat(parts);
|
98
|
+
}
|
99
|
+
|
92
100
|
if (!skipAssignIndent(valueNode) || keyNode.comments) {
|
93
101
|
parts.push(indent(concat([line, valueDoc])));
|
94
102
|
} else {
|
@@ -125,20 +133,26 @@ function printHash(path, opts, print) {
|
|
125
133
|
return printEmptyCollection(path, opts, "{", "}");
|
126
134
|
}
|
127
135
|
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
136
|
+
let hashDoc = concat([
|
137
|
+
"{",
|
138
|
+
indent(
|
139
|
+
concat([
|
140
|
+
line,
|
141
|
+
path.call(print, "body", 0),
|
142
|
+
getTrailingComma(opts) ? ifBreak(",", "") : ""
|
143
|
+
])
|
144
|
+
),
|
145
|
+
line,
|
146
|
+
"}"
|
147
|
+
]);
|
148
|
+
|
149
|
+
// If we're inside another hash, then we don't want to group our contents
|
150
|
+
// because we want this hash to break along with its parent hash.
|
151
|
+
if (path.getParentNode().type === "assoc_new") {
|
152
|
+
return hashDoc;
|
153
|
+
}
|
154
|
+
|
155
|
+
return group(hashDoc);
|
142
156
|
}
|
143
157
|
|
144
158
|
module.exports = {
|
data/src/ruby/nodes/loops.js
CHANGED
@@ -10,7 +10,7 @@ const {
|
|
10
10
|
softline
|
11
11
|
} = require("../../prettier");
|
12
12
|
|
13
|
-
const { containsAssignment } = require("../../utils");
|
13
|
+
const { containsAssignment, isEmptyStmts } = require("../../utils");
|
14
14
|
const inlineEnsureParens = require("../../utils/inlineEnsureParens");
|
15
15
|
|
16
16
|
function printLoop(keyword, modifier) {
|
@@ -19,17 +19,11 @@ function printLoop(keyword, modifier) {
|
|
19
19
|
|
20
20
|
// If the only statement inside this while loop is a void statement, then we
|
21
21
|
// can shorten to just displaying the predicate and then a semicolon.
|
22
|
-
if (
|
23
|
-
stmts.body.length === 1 &&
|
24
|
-
stmts.body[0].type === "void_stmt" &&
|
25
|
-
!stmts.body[0].comments
|
26
|
-
) {
|
22
|
+
if (isEmptyStmts(stmts)) {
|
27
23
|
return group(
|
28
24
|
concat([
|
29
|
-
keyword,
|
30
|
-
|
31
|
-
path.call(print, "body", 0),
|
32
|
-
ifBreak(softline, "; "),
|
25
|
+
group(concat([keyword, " ", path.call(print, "body", 0)])),
|
26
|
+
hardline,
|
33
27
|
"end"
|
34
28
|
])
|
35
29
|
);
|
data/src/ruby/nodes/methods.js
CHANGED
@@ -1,8 +1,9 @@
|
|
1
1
|
const { concat, group, hardline, indent, line } = require("../../prettier");
|
2
|
+
const { isEmptyBodyStmt } = require("../../utils");
|
2
3
|
|
3
4
|
function printMethod(offset) {
|
4
5
|
return function printMethodWithOffset(path, opts, print) {
|
5
|
-
const [_name, params,
|
6
|
+
const [_name, params, bodystmt] = path.getValue().body.slice(offset);
|
6
7
|
const declaration = ["def "];
|
7
8
|
|
8
9
|
// In this case, we're printing a method that's defined as a singleton, so
|
@@ -24,16 +25,8 @@ function printMethod(offset) {
|
|
24
25
|
parens ? ")" : ""
|
25
26
|
);
|
26
27
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
if (
|
31
|
-
!body.body.slice(1).some((node) => node) &&
|
32
|
-
stmts.length === 1 &&
|
33
|
-
stmts[0].type === "void_stmt" &&
|
34
|
-
!stmts[0].comments
|
35
|
-
) {
|
36
|
-
return group(concat(declaration.concat(["; end"])));
|
28
|
+
if (isEmptyBodyStmt(bodystmt)) {
|
29
|
+
return group(concat(declaration.concat("; end")));
|
37
30
|
}
|
38
31
|
|
39
32
|
return group(
|
data/src/ruby/nodes/rescue.js
CHANGED
@@ -26,28 +26,10 @@ function printEnsure(path, opts, print) {
|
|
26
26
|
}
|
27
27
|
|
28
28
|
function printRescue(path, opts, print) {
|
29
|
-
const [exception, variable, _stmts, addition] = path.getValue().body;
|
30
29
|
const parts = ["rescue"];
|
31
30
|
|
32
|
-
if (
|
33
|
-
|
34
|
-
if (Array.isArray(exception)) {
|
35
|
-
// In this case, it's actually only the one exception (it's an array
|
36
|
-
// of length 1).
|
37
|
-
parts.push(" ", path.call(print, "body", 0, 0));
|
38
|
-
} else {
|
39
|
-
// Here we have multiple exceptions from which we're rescuing, so we
|
40
|
-
// need to align them and join them together.
|
41
|
-
const joiner = concat([",", line]);
|
42
|
-
const exceptions = group(join(joiner, path.call(print, "body", 0)));
|
43
|
-
|
44
|
-
parts.push(" ", align("rescue ".length, exceptions));
|
45
|
-
}
|
46
|
-
}
|
47
|
-
|
48
|
-
if (variable) {
|
49
|
-
parts.push(" => ", path.call(print, "body", 1));
|
50
|
-
}
|
31
|
+
if (path.getValue().body[0]) {
|
32
|
+
parts.push(align("rescue ".length, path.call(print, "body", 0)));
|
51
33
|
} else {
|
52
34
|
// If you don't specify an error to rescue in a `begin/rescue` block, then
|
53
35
|
// implicitly you're rescuing from `StandardError`. In this case, we're
|
@@ -55,16 +37,40 @@ function printRescue(path, opts, print) {
|
|
55
37
|
parts.push(" StandardError");
|
56
38
|
}
|
57
39
|
|
58
|
-
const
|
40
|
+
const bodystmt = path.call(print, "body", 1);
|
59
41
|
|
60
|
-
if (
|
61
|
-
parts.push(indent(concat([hardline,
|
42
|
+
if (bodystmt.parts.length > 0) {
|
43
|
+
parts.push(indent(concat([hardline, bodystmt])));
|
62
44
|
}
|
63
45
|
|
64
46
|
// This is the next clause on the `begin` statement, either another
|
65
47
|
// `rescue`, and `ensure`, or an `else` clause.
|
66
|
-
if (
|
67
|
-
parts.push(concat([hardline, path.call(print, "body",
|
48
|
+
if (path.getValue().body[2]) {
|
49
|
+
parts.push(concat([hardline, path.call(print, "body", 2)]));
|
50
|
+
}
|
51
|
+
|
52
|
+
return group(concat(parts));
|
53
|
+
}
|
54
|
+
|
55
|
+
// This is a container node that we're adding into the AST that isn't present in
|
56
|
+
// Ripper solely so that we have a nice place to attach inline comments.
|
57
|
+
function printRescueEx(path, opts, print) {
|
58
|
+
const [exception, variable] = path.getValue().body;
|
59
|
+
const parts = [];
|
60
|
+
|
61
|
+
if (exception) {
|
62
|
+
let exceptionDoc = path.call(print, "body", 0);
|
63
|
+
|
64
|
+
if (Array.isArray(exceptionDoc)) {
|
65
|
+
const joiner = concat([",", line]);
|
66
|
+
exceptionDoc = group(join(joiner, exceptionDoc));
|
67
|
+
}
|
68
|
+
|
69
|
+
parts.push(" ", exceptionDoc);
|
70
|
+
}
|
71
|
+
|
72
|
+
if (variable) {
|
73
|
+
parts.push(" => ", path.call(print, "body", 1));
|
68
74
|
}
|
69
75
|
|
70
76
|
return group(concat(parts));
|
@@ -89,6 +95,7 @@ module.exports = {
|
|
89
95
|
ensure: printEnsure,
|
90
96
|
redo: literal("redo"),
|
91
97
|
rescue: printRescue,
|
98
|
+
rescue_ex: printRescueEx,
|
92
99
|
rescue_mod: printRescueMod,
|
93
100
|
retry: literal("retry")
|
94
101
|
};
|
@@ -12,15 +12,13 @@ const {
|
|
12
12
|
trim
|
13
13
|
} = require("../../prettier");
|
14
14
|
|
15
|
+
const { isEmptyStmts } = require("../../utils");
|
16
|
+
|
15
17
|
function printBodyStmt(path, opts, print) {
|
16
18
|
const [stmts, rescue, elseClause, ensure] = path.getValue().body;
|
17
19
|
const parts = [];
|
18
20
|
|
19
|
-
if (
|
20
|
-
stmts.body.length > 1 ||
|
21
|
-
stmts.body[0].type != "void_stmt" ||
|
22
|
-
stmts.body[0].comments
|
23
|
-
) {
|
21
|
+
if (!isEmptyStmts(stmts)) {
|
24
22
|
parts.push(path.call(print, "body", 0));
|
25
23
|
}
|
26
24
|
|
@@ -79,6 +77,9 @@ module.exports = {
|
|
79
77
|
const { body } = path.getValue();
|
80
78
|
return concat([trim, "__END__", literalline, body]);
|
81
79
|
},
|
80
|
+
"@comment"(path, opts, _print) {
|
81
|
+
return opts.printer.printComment(path);
|
82
|
+
},
|
82
83
|
bodystmt: printBodyStmt,
|
83
84
|
paren: printParen,
|
84
85
|
program: (path, opts, print) =>
|
data/src/ruby/nodes/strings.js
CHANGED
@@ -4,6 +4,7 @@ const {
|
|
4
4
|
hardline,
|
5
5
|
indent,
|
6
6
|
literalline,
|
7
|
+
removeLines,
|
7
8
|
softline,
|
8
9
|
join
|
9
10
|
} = require("../../prettier");
|
@@ -103,14 +104,14 @@ function printStringDVar(path, opts, print) {
|
|
103
104
|
}
|
104
105
|
|
105
106
|
function printStringEmbExpr(path, opts, print) {
|
107
|
+
const node = path.getValue();
|
106
108
|
const parts = path.call(print, "body", 0);
|
107
109
|
|
108
|
-
// If the
|
109
|
-
//
|
110
|
-
//
|
111
|
-
|
112
|
-
|
113
|
-
return concat(["#{", parts, "}"]);
|
110
|
+
// If the contents of this embedded expression were originally on the same
|
111
|
+
// line in the source, then we're going to leave them in place and assume
|
112
|
+
// that's the way the developer wanted this expression represented.
|
113
|
+
if (node.sl === node.el) {
|
114
|
+
return concat(["#{", removeLines(parts), "}"]);
|
114
115
|
}
|
115
116
|
|
116
117
|
return group(
|
data/src/ruby/parser.js
CHANGED
@@ -1,59 +1,11 @@
|
|
1
|
-
const
|
2
|
-
const path = require("path");
|
3
|
-
|
4
|
-
// In order to properly parse ruby code, we need to tell the ruby process to
|
5
|
-
// parse using UTF-8. Unfortunately, the way that you accomplish this looks
|
6
|
-
// differently depending on your platform.
|
7
|
-
/* istanbul ignore next */
|
8
|
-
const LANG = (() => {
|
9
|
-
const { env, platform } = process;
|
10
|
-
const envValue = env.LC_ALL || env.LC_CTYPE || env.LANG;
|
11
|
-
|
12
|
-
// If an env var is set for the locale that already includes UTF-8 in the
|
13
|
-
// name, then assume we can go with that.
|
14
|
-
if (envValue && envValue.includes("UTF-8")) {
|
15
|
-
return envValue;
|
16
|
-
}
|
17
|
-
|
18
|
-
// Otherwise, we're going to guess which encoding to use based on the system.
|
19
|
-
// This is probably not the best approach in the world, as you could be on
|
20
|
-
// linux and not have C.UTF-8, but in that case you're probably passing an env
|
21
|
-
// var for it. This object below represents all of the possible values of
|
22
|
-
// process.platform per:
|
23
|
-
// https://nodejs.org/api/process.html#process_process_platform
|
24
|
-
return {
|
25
|
-
aix: "C.UTF-8",
|
26
|
-
darwin: "en_US.UTF-8",
|
27
|
-
freebsd: "C.UTF-8",
|
28
|
-
linux: "C.UTF-8",
|
29
|
-
openbsd: "C.UTF-8",
|
30
|
-
sunos: "C.UTF-8",
|
31
|
-
win32: ".UTF-8"
|
32
|
-
}[platform];
|
33
|
-
})();
|
1
|
+
const parseSync = require("../parser/parseSync");
|
34
2
|
|
35
3
|
// This function is responsible for taking an input string of text and returning
|
36
4
|
// to prettier a JavaScript object that is the equivalent AST that represents
|
37
5
|
// the code stored in that string. We accomplish this by spawning a new Ruby
|
38
6
|
// process of parser.rb and reading JSON off STDOUT.
|
39
7
|
function parse(text, _parsers, _opts) {
|
40
|
-
|
41
|
-
"ruby",
|
42
|
-
["--disable-gems", path.join(__dirname, "./parser.rb")],
|
43
|
-
{
|
44
|
-
env: Object.assign({}, process.env, { LANG }),
|
45
|
-
input: text,
|
46
|
-
maxBuffer: 15 * 1024 * 1024 // 15MB
|
47
|
-
}
|
48
|
-
);
|
49
|
-
|
50
|
-
const error = child.stderr.toString();
|
51
|
-
if (error) {
|
52
|
-
throw new Error(error);
|
53
|
-
}
|
54
|
-
|
55
|
-
const response = child.stdout.toString();
|
56
|
-
return JSON.parse(response);
|
8
|
+
return parseSync("ruby", text);
|
57
9
|
}
|
58
10
|
|
59
11
|
const pragmaPattern = /#\s*@(prettier|format)/;
|
data/src/ruby/parser.rb
CHANGED
@@ -14,13 +14,51 @@ if (RUBY_MAJOR < 2) || ((RUBY_MAJOR == 2) && (RUBY_MINOR < 5))
|
|
14
14
|
end
|
15
15
|
|
16
16
|
require 'delegate'
|
17
|
-
require 'json'
|
17
|
+
require 'json'
|
18
18
|
require 'ripper'
|
19
19
|
|
20
|
-
module Prettier
|
20
|
+
module Prettier
|
21
|
+
end
|
21
22
|
|
22
23
|
class Prettier::Parser < Ripper
|
23
|
-
|
24
|
+
# Represents a line in the source. If this class is being used, it means that
|
25
|
+
# every character in the string is 1 byte in length, so we can just return the
|
26
|
+
# start of the line + the index.
|
27
|
+
class SingleByteString
|
28
|
+
def initialize(start)
|
29
|
+
@start = start
|
30
|
+
end
|
31
|
+
|
32
|
+
def [](byteindex)
|
33
|
+
@start + byteindex
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# Represents a line in the source. If this class is being used, it means that
|
38
|
+
# there are characters in the string that are multi-byte, so we will build up
|
39
|
+
# an array of indices, such that array[byteindex] will be equal to the index
|
40
|
+
# of the character within the string.
|
41
|
+
class MultiByteString
|
42
|
+
def initialize(start, line)
|
43
|
+
@indices = []
|
44
|
+
|
45
|
+
line
|
46
|
+
.each_char
|
47
|
+
.with_index(start) do |char, index|
|
48
|
+
char.bytesize.times { @indices << index }
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def [](byteindex)
|
53
|
+
@indices[byteindex]
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
attr_reader :source, :lines, :scanner_events
|
58
|
+
|
59
|
+
# This is an attr_accessor so Stmts objects can grab comments out of this
|
60
|
+
# array and attach them to themselves.
|
61
|
+
attr_accessor :comments
|
24
62
|
|
25
63
|
def initialize(source, *args)
|
26
64
|
super(source, *args)
|
@@ -35,9 +73,30 @@ class Prettier::Parser < Ripper
|
|
35
73
|
@heredocs = []
|
36
74
|
|
37
75
|
@scanner_events = []
|
38
|
-
@line_counts = [
|
76
|
+
@line_counts = []
|
77
|
+
|
78
|
+
# Here we're going to build up a list of SingleByteString or MultiByteString
|
79
|
+
# objects. They're each going to represent a string in the source. They are
|
80
|
+
# used by the `char_pos` method to determine where we are in the source
|
81
|
+
# string.
|
82
|
+
last_index = 0
|
83
|
+
|
84
|
+
@source.lines.each do |line|
|
85
|
+
if line.size == line.bytesize
|
86
|
+
@line_counts << SingleByteString.new(last_index)
|
87
|
+
else
|
88
|
+
@line_counts << MultiByteString.new(last_index, line)
|
89
|
+
end
|
39
90
|
|
40
|
-
|
91
|
+
last_index += line.size
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def self.parse(source)
|
96
|
+
builder = new(source)
|
97
|
+
|
98
|
+
response = builder.parse
|
99
|
+
response unless builder.error?
|
41
100
|
end
|
42
101
|
|
43
102
|
private
|
@@ -48,7 +107,7 @@ class Prettier::Parser < Ripper
|
|
48
107
|
# this line, then we add the number of columns into this line that we've gone
|
49
108
|
# through.
|
50
109
|
def char_pos
|
51
|
-
line_counts[lineno - 1]
|
110
|
+
@line_counts[lineno - 1][column]
|
52
111
|
end
|
53
112
|
|
54
113
|
# As we build up a list of scanner events, we'll periodically need to go
|
@@ -118,6 +177,7 @@ class Prettier::Parser < Ripper
|
|
118
177
|
@comments << {
|
119
178
|
type: :@comment,
|
120
179
|
value: value[1..-1].chomp.force_encoding('UTF-8'),
|
180
|
+
inline: value.strip != lines[lineno - 1],
|
121
181
|
sl: lineno,
|
122
182
|
el: lineno,
|
123
183
|
sc: char_pos,
|
@@ -634,10 +694,6 @@ class Prettier::Parser < Ripper
|
|
634
694
|
# foo.(1, 2, 3)
|
635
695
|
#
|
636
696
|
def on_call(receiver, oper, sending)
|
637
|
-
# Make sure we take the operator out of the scanner events so that it
|
638
|
-
# doesn't get confused for a unary operator later.
|
639
|
-
scanner_events.delete(oper)
|
640
|
-
|
641
697
|
ending = sending
|
642
698
|
|
643
699
|
if sending == :call
|
@@ -740,11 +796,6 @@ class Prettier::Parser < Ripper
|
|
740
796
|
# of the method, the operator being used to send the method, the name of
|
741
797
|
# the method, and the arguments being passed to the method.
|
742
798
|
def on_command_call(receiver, oper, ident, args)
|
743
|
-
# Make sure we take the operator out of the scanner events so that it
|
744
|
-
# doesn't get confused for a unary operator later.
|
745
|
-
scanner_events.delete(oper)
|
746
|
-
|
747
|
-
# Grab the ending from either the arguments or the method being sent
|
748
799
|
ending = args || ident
|
749
800
|
|
750
801
|
{
|
@@ -1770,8 +1821,8 @@ class Prettier::Parser < Ripper
|
|
1770
1821
|
def bind_end(ec)
|
1771
1822
|
merge!(ec: ec)
|
1772
1823
|
|
1773
|
-
stmts = self[:body][
|
1774
|
-
consequent = self[:body][
|
1824
|
+
stmts = self[:body][1]
|
1825
|
+
consequent = self[:body][2]
|
1775
1826
|
|
1776
1827
|
if consequent
|
1777
1828
|
consequent.bind_end(ec)
|
@@ -1786,16 +1837,30 @@ class Prettier::Parser < Ripper
|
|
1786
1837
|
# inside of a bodystmt.
|
1787
1838
|
def on_rescue(exceptions, variable, stmts, consequent)
|
1788
1839
|
beging = find_scanner_event(:@kw, 'rescue')
|
1840
|
+
exceptions = exceptions[0] if exceptions.is_a?(Array)
|
1789
1841
|
|
1790
|
-
|
1791
|
-
last_node = variable || last_exception || beging
|
1792
|
-
|
1842
|
+
last_node = variable || exceptions || beging
|
1793
1843
|
stmts.bind(find_next_statement_start(last_node[:ec]), char_pos)
|
1794
1844
|
|
1845
|
+
# We add an additional inner node here that ripper doesn't provide so that
|
1846
|
+
# we have a nice place to attach inline comment. But we only need it if we
|
1847
|
+
# have an exception or a variable that we're rescuing.
|
1848
|
+
rescue_ex =
|
1849
|
+
if exceptions || variable
|
1850
|
+
{
|
1851
|
+
type: :rescue_ex,
|
1852
|
+
body: [exceptions, variable],
|
1853
|
+
sl: beging[:sl],
|
1854
|
+
sc: beging[:ec] + 1,
|
1855
|
+
el: last_node[:el],
|
1856
|
+
ec: last_node[:ec]
|
1857
|
+
}
|
1858
|
+
end
|
1859
|
+
|
1795
1860
|
Rescue.new(
|
1796
1861
|
beging.merge!(
|
1797
1862
|
type: :rescue,
|
1798
|
-
body: [
|
1863
|
+
body: [rescue_ex, stmts, consequent],
|
1799
1864
|
el: lineno,
|
1800
1865
|
ec: char_pos
|
1801
1866
|
)
|
@@ -1894,12 +1959,21 @@ class Prettier::Parser < Ripper
|
|
1894
1959
|
# propagate that onto void_stmt nodes inside the stmts in order to make sure
|
1895
1960
|
# all comments get printed appropriately.
|
1896
1961
|
class Stmts < SimpleDelegator
|
1962
|
+
attr_reader :parser
|
1963
|
+
|
1964
|
+
def initialize(parser, values)
|
1965
|
+
@parser = parser
|
1966
|
+
__setobj__(values)
|
1967
|
+
end
|
1968
|
+
|
1897
1969
|
def bind(sc, ec)
|
1898
1970
|
merge!(sc: sc, ec: ec)
|
1899
1971
|
|
1900
1972
|
if self[:body][0][:type] == :void_stmt
|
1901
1973
|
self[:body][0].merge!(sc: sc, ec: sc)
|
1902
1974
|
end
|
1975
|
+
|
1976
|
+
attach_comments(sc, ec)
|
1903
1977
|
end
|
1904
1978
|
|
1905
1979
|
def bind_end(ec)
|
@@ -1916,6 +1990,22 @@ class Prettier::Parser < Ripper
|
|
1916
1990
|
self[:body] << statement
|
1917
1991
|
self
|
1918
1992
|
end
|
1993
|
+
|
1994
|
+
private
|
1995
|
+
|
1996
|
+
def attach_comments(sc, ec)
|
1997
|
+
attachable =
|
1998
|
+
parser.comments.select do |comment|
|
1999
|
+
comment[:type] == :@comment && !comment[:inline] &&
|
2000
|
+
sc <= comment[:sc] && ec >= comment[:ec] &&
|
2001
|
+
!comment[:value].include?('prettier-ignore')
|
2002
|
+
end
|
2003
|
+
|
2004
|
+
return if attachable.empty?
|
2005
|
+
|
2006
|
+
parser.comments -= attachable
|
2007
|
+
self[:body] = (self[:body] + attachable).sort_by! { |node| node[:sc] }
|
2008
|
+
end
|
1919
2009
|
end
|
1920
2010
|
|
1921
2011
|
# stmts_new is a parser event that represents the beginning of a list of
|
@@ -1923,6 +2013,7 @@ class Prettier::Parser < Ripper
|
|
1923
2013
|
# stmts_add events, which we'll append onto an array body.
|
1924
2014
|
def on_stmts_new
|
1925
2015
|
Stmts.new(
|
2016
|
+
self,
|
1926
2017
|
type: :stmts,
|
1927
2018
|
body: [],
|
1928
2019
|
sl: lineno,
|
@@ -2173,7 +2264,7 @@ class Prettier::Parser < Ripper
|
|
2173
2264
|
# stack. So we need to explicitly disallow those operators.
|
2174
2265
|
index =
|
2175
2266
|
scanner_events.rindex do |scanner_event|
|
2176
|
-
scanner_event[:type] == :@op &&
|
2267
|
+
scanner_event[:type] == :@op && scanner_event[:sc] < value[:sc] &&
|
2177
2268
|
!%w[.. ...].include?(scanner_event[:body])
|
2178
2269
|
end
|
2179
2270
|
|
@@ -2551,24 +2642,3 @@ class Prettier::Parser < Ripper
|
|
2551
2642
|
find_scanner_event(:@kw, 'super').merge!(type: :zsuper)
|
2552
2643
|
end
|
2553
2644
|
end
|
2554
|
-
|
2555
|
-
# If this is the main file we're executing, then most likely this is being
|
2556
|
-
# executed from the parser.js spawn. In that case, read the ruby source from
|
2557
|
-
# stdin and report back the AST over stdout.
|
2558
|
-
|
2559
|
-
if $0 == __FILE__
|
2560
|
-
builder = Prettier::Parser.new($stdin.read)
|
2561
|
-
response = builder.parse
|
2562
|
-
|
2563
|
-
if !response || builder.error?
|
2564
|
-
warn(
|
2565
|
-
'@prettier/plugin-ruby encountered an error when attempting to parse ' \
|
2566
|
-
'the ruby source. This usually means there was a syntax error in the ' \
|
2567
|
-
'file in question. You can verify by running `ruby -i [path/to/file]`.'
|
2568
|
-
)
|
2569
|
-
|
2570
|
-
exit 1
|
2571
|
-
end
|
2572
|
-
|
2573
|
-
puts JSON.fast_generate(response)
|
2574
|
-
end
|