prettier 1.2.5 → 1.5.2
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 +353 -367
- data/README.md +10 -4
- data/package.json +1 -1
- 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 +61 -13
- data/src/ruby/nodes/args.js +20 -6
- data/src/ruby/nodes/arrays.js +36 -33
- data/src/ruby/nodes/calls.js +2 -31
- data/src/ruby/nodes/class.js +17 -27
- data/src/ruby/nodes/commands.js +1 -1
- data/src/ruby/nodes/conditionals.js +1 -1
- data/src/ruby/nodes/hashes.js +28 -14
- data/src/ruby/nodes/heredocs.js +5 -3
- 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 +118 -33
- data/src/ruby/printer.js +8 -5
- data/src/utils.js +2 -1
- data/src/utils/inlineEnsureParens.js +8 -1
- data/src/utils/isEmptyBodyStmt.js +7 -0
- data/src/utils/isEmptyStmts.js +9 -5
- data/src/utils/literallineWithoutBreakParent.js +7 -0
- data/src/utils/printEmptyCollection.js +9 -2
- metadata +26 -3
- data/src/utils/literalLineNoBreak.js +0 -7
data/src/ruby/nodes/heredocs.js
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
const { concat, group, lineSuffix, join } = require("../../prettier");
|
2
|
-
const {
|
2
|
+
const { literallineWithoutBreakParent } = require("../../utils");
|
3
3
|
|
4
4
|
function printHeredoc(path, opts, print) {
|
5
5
|
const { body, ending } = path.getValue();
|
@@ -11,7 +11,7 @@ function printHeredoc(path, opts, print) {
|
|
11
11
|
}
|
12
12
|
|
13
13
|
// In this case, the part of the string is just regular string content
|
14
|
-
return join(
|
14
|
+
return join(literallineWithoutBreakParent, part.body.split("\n"));
|
15
15
|
});
|
16
16
|
|
17
17
|
// We use a literalline break because matching indentation is required
|
@@ -23,7 +23,9 @@ function printHeredoc(path, opts, print) {
|
|
23
23
|
concat([
|
24
24
|
path.call(print, "beging"),
|
25
25
|
lineSuffix(
|
26
|
-
group(
|
26
|
+
group(
|
27
|
+
concat([literallineWithoutBreakParent].concat(parts).concat(ending))
|
28
|
+
)
|
27
29
|
)
|
28
30
|
])
|
29
31
|
);
|
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,
|
@@ -505,6 +565,12 @@ class Prettier::Parser < Ripper
|
|
505
565
|
# binary is a parser event that represents a binary operation between two
|
506
566
|
# values.
|
507
567
|
def on_binary(left, oper, right)
|
568
|
+
# On most Ruby implementations, oper is a Symbol that represents that
|
569
|
+
# operation being performed. For instance in the example `1 < 2`, the `oper`
|
570
|
+
# object would be `:<`. However, on JRuby, it's an `@op` node, so here we're
|
571
|
+
# going to explicitly convert it into the same normalized form.
|
572
|
+
oper = scanner_events.delete(oper)[:body] unless oper.is_a?(Symbol)
|
573
|
+
|
508
574
|
{
|
509
575
|
type: :binary,
|
510
576
|
body: [left, oper, right],
|
@@ -1761,8 +1827,8 @@ class Prettier::Parser < Ripper
|
|
1761
1827
|
def bind_end(ec)
|
1762
1828
|
merge!(ec: ec)
|
1763
1829
|
|
1764
|
-
stmts = self[:body][
|
1765
|
-
consequent = self[:body][
|
1830
|
+
stmts = self[:body][1]
|
1831
|
+
consequent = self[:body][2]
|
1766
1832
|
|
1767
1833
|
if consequent
|
1768
1834
|
consequent.bind_end(ec)
|
@@ -1777,16 +1843,30 @@ class Prettier::Parser < Ripper
|
|
1777
1843
|
# inside of a bodystmt.
|
1778
1844
|
def on_rescue(exceptions, variable, stmts, consequent)
|
1779
1845
|
beging = find_scanner_event(:@kw, 'rescue')
|
1846
|
+
exceptions = exceptions[0] if exceptions.is_a?(Array)
|
1780
1847
|
|
1781
|
-
|
1782
|
-
last_node = variable || last_exception || beging
|
1783
|
-
|
1848
|
+
last_node = variable || exceptions || beging
|
1784
1849
|
stmts.bind(find_next_statement_start(last_node[:ec]), char_pos)
|
1785
1850
|
|
1851
|
+
# We add an additional inner node here that ripper doesn't provide so that
|
1852
|
+
# we have a nice place to attach inline comment. But we only need it if we
|
1853
|
+
# have an exception or a variable that we're rescuing.
|
1854
|
+
rescue_ex =
|
1855
|
+
if exceptions || variable
|
1856
|
+
{
|
1857
|
+
type: :rescue_ex,
|
1858
|
+
body: [exceptions, variable],
|
1859
|
+
sl: beging[:sl],
|
1860
|
+
sc: beging[:ec] + 1,
|
1861
|
+
el: last_node[:el],
|
1862
|
+
ec: last_node[:ec]
|
1863
|
+
}
|
1864
|
+
end
|
1865
|
+
|
1786
1866
|
Rescue.new(
|
1787
1867
|
beging.merge!(
|
1788
1868
|
type: :rescue,
|
1789
|
-
body: [
|
1869
|
+
body: [rescue_ex, stmts, consequent],
|
1790
1870
|
el: lineno,
|
1791
1871
|
ec: char_pos
|
1792
1872
|
)
|
@@ -1885,12 +1965,21 @@ class Prettier::Parser < Ripper
|
|
1885
1965
|
# propagate that onto void_stmt nodes inside the stmts in order to make sure
|
1886
1966
|
# all comments get printed appropriately.
|
1887
1967
|
class Stmts < SimpleDelegator
|
1968
|
+
attr_reader :parser
|
1969
|
+
|
1970
|
+
def initialize(parser, values)
|
1971
|
+
@parser = parser
|
1972
|
+
__setobj__(values)
|
1973
|
+
end
|
1974
|
+
|
1888
1975
|
def bind(sc, ec)
|
1889
1976
|
merge!(sc: sc, ec: ec)
|
1890
1977
|
|
1891
1978
|
if self[:body][0][:type] == :void_stmt
|
1892
1979
|
self[:body][0].merge!(sc: sc, ec: sc)
|
1893
1980
|
end
|
1981
|
+
|
1982
|
+
attach_comments(sc, ec)
|
1894
1983
|
end
|
1895
1984
|
|
1896
1985
|
def bind_end(ec)
|
@@ -1907,6 +1996,22 @@ class Prettier::Parser < Ripper
|
|
1907
1996
|
self[:body] << statement
|
1908
1997
|
self
|
1909
1998
|
end
|
1999
|
+
|
2000
|
+
private
|
2001
|
+
|
2002
|
+
def attach_comments(sc, ec)
|
2003
|
+
attachable =
|
2004
|
+
parser.comments.select do |comment|
|
2005
|
+
comment[:type] == :@comment && !comment[:inline] &&
|
2006
|
+
sc <= comment[:sc] && ec >= comment[:ec] &&
|
2007
|
+
!comment[:value].include?('prettier-ignore')
|
2008
|
+
end
|
2009
|
+
|
2010
|
+
return if attachable.empty?
|
2011
|
+
|
2012
|
+
parser.comments -= attachable
|
2013
|
+
self[:body] = (self[:body] + attachable).sort_by! { |node| node[:sc] }
|
2014
|
+
end
|
1910
2015
|
end
|
1911
2016
|
|
1912
2017
|
# stmts_new is a parser event that represents the beginning of a list of
|
@@ -1914,6 +2019,7 @@ class Prettier::Parser < Ripper
|
|
1914
2019
|
# stmts_add events, which we'll append onto an array body.
|
1915
2020
|
def on_stmts_new
|
1916
2021
|
Stmts.new(
|
2022
|
+
self,
|
1917
2023
|
type: :stmts,
|
1918
2024
|
body: [],
|
1919
2025
|
sl: lineno,
|
@@ -2542,24 +2648,3 @@ class Prettier::Parser < Ripper
|
|
2542
2648
|
find_scanner_event(:@kw, 'super').merge!(type: :zsuper)
|
2543
2649
|
end
|
2544
2650
|
end
|
2545
|
-
|
2546
|
-
# If this is the main file we're executing, then most likely this is being
|
2547
|
-
# executed from the parser.js spawn. In that case, read the ruby source from
|
2548
|
-
# stdin and report back the AST over stdout.
|
2549
|
-
|
2550
|
-
if $0 == __FILE__
|
2551
|
-
builder = Prettier::Parser.new($stdin.read)
|
2552
|
-
response = builder.parse
|
2553
|
-
|
2554
|
-
if !response || builder.error?
|
2555
|
-
warn(
|
2556
|
-
'@prettier/plugin-ruby encountered an error when attempting to parse ' \
|
2557
|
-
'the ruby source. This usually means there was a syntax error in the ' \
|
2558
|
-
'file in question. You can verify by running `ruby -i [path/to/file]`.'
|
2559
|
-
)
|
2560
|
-
|
2561
|
-
exit 1
|
2562
|
-
end
|
2563
|
-
|
2564
|
-
puts JSON.fast_generate(response)
|
2565
|
-
end
|