prettier 1.5.1 → 1.6.0

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.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +55 -2
  3. data/CONTRIBUTING.md +2 -2
  4. data/README.md +41 -12
  5. data/node_modules/prettier/bin-prettier.js +13702 -11629
  6. data/node_modules/prettier/index.js +19191 -16565
  7. data/node_modules/prettier/parser-angular.js +67 -0
  8. data/node_modules/prettier/parser-babel.js +22 -0
  9. data/node_modules/prettier/parser-espree.js +22 -0
  10. data/node_modules/prettier/parser-flow.js +22 -0
  11. data/node_modules/prettier/parser-glimmer.js +1 -0
  12. data/node_modules/prettier/parser-graphql.js +1 -0
  13. data/node_modules/prettier/parser-html.js +132 -0
  14. data/node_modules/prettier/parser-markdown.js +34 -0
  15. data/node_modules/prettier/parser-meriyah.js +22 -0
  16. data/node_modules/prettier/parser-postcss.js +22 -0
  17. data/node_modules/prettier/parser-typescript.js +22 -0
  18. data/node_modules/prettier/parser-yaml.js +15 -0
  19. data/node_modules/prettier/third-party.js +1042 -833
  20. data/package.json +5 -5
  21. data/rubocop.yml +12 -0
  22. data/src/haml/parser.js +6 -5
  23. data/src/haml/parser.rb +8 -3
  24. data/src/haml/printer.js +428 -18
  25. data/src/parser/netcat.js +0 -2
  26. data/src/parser/parseSync.js +153 -14
  27. data/src/parser/server.rb +7 -2
  28. data/src/plugin.js +7 -1
  29. data/src/rbs/parser.js +3 -5
  30. data/src/rbs/parser.rb +7 -3
  31. data/src/rbs/printer.js +46 -8
  32. data/src/ruby/embed.js +7 -5
  33. data/src/ruby/nodes/args.js +111 -19
  34. data/src/ruby/nodes/calls.js +8 -1
  35. data/src/ruby/nodes/conditionals.js +47 -45
  36. data/src/ruby/nodes/hashes.js +5 -14
  37. data/src/ruby/nodes/heredocs.js +5 -3
  38. data/src/ruby/nodes/params.js +2 -9
  39. data/src/ruby/nodes/strings.js +95 -2
  40. data/src/ruby/parser.js +3 -5
  41. data/src/ruby/parser.rb +82 -31
  42. data/src/ruby/printer.js +10 -1
  43. data/src/utils.js +1 -1
  44. data/src/utils/inlineEnsureParens.js +1 -0
  45. data/src/utils/literallineWithoutBreakParent.js +7 -0
  46. data/src/utils/skipAssignIndent.js +8 -1
  47. metadata +15 -15
  48. data/src/haml/nodes/comment.js +0 -27
  49. data/src/haml/nodes/doctype.js +0 -34
  50. data/src/haml/nodes/filter.js +0 -16
  51. data/src/haml/nodes/hamlComment.js +0 -21
  52. data/src/haml/nodes/plain.js +0 -6
  53. data/src/haml/nodes/root.js +0 -8
  54. data/src/haml/nodes/script.js +0 -33
  55. data/src/haml/nodes/silentScript.js +0 -59
  56. data/src/haml/nodes/tag.js +0 -193
  57. data/src/parser/getLang.js +0 -32
  58. data/src/parser/getNetcat.js +0 -50
  59. data/src/parser/requestParse.js +0 -74
  60. data/src/utils/literalLineNoBreak.js +0 -7
@@ -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");
@@ -133,7 +134,13 @@ function printMethodAddArg(path, opts, print) {
133
134
  );
134
135
  }
135
136
 
136
- return concat([methodDoc, argsDoc]);
137
+ // If there are already parentheses, then we can just use the doc that's
138
+ // already printed.
139
+ if (argNode.type == "arg_paren") {
140
+ return concat([methodDoc, argsDoc]);
141
+ }
142
+
143
+ return concat([methodDoc, " ", join(", ", argsDoc), " "]);
137
144
  }
138
145
 
139
146
  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 = (keyword) => (path, { rubyModifier }, print) => {
194
- if (canTernary(path)) {
195
- let ternaryParts = [path.call(print, "body", 0), " ? "].concat(
196
- printTernaryClauses(
197
- keyword,
198
- path.call(print, "body", 1),
199
- path.call(print, "body", 2, "body", 0)
200
- )
201
- );
202
-
203
- if (["binary", "call"].includes(path.getParentNode().type)) {
204
- ternaryParts = ["("].concat(ternaryParts).concat(")");
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
- return group(
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
- // If there's an additional clause that wasn't matched earlier, we know we
215
- // can't go for the inline option.
216
- if (addition) {
217
- return group(printWithAddition(keyword, path, print, { breaking: true }));
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
- // If the body of the conditional is empty, then we explicitly have to use the
221
- // block form.
222
- if (isEmptyStmts(statements)) {
223
- return concat([
224
- `${keyword} `,
225
- align(keyword.length + 1, path.call(print, "body", 0)),
226
- concat([hardline, "end"])
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
- // If the predicate of the conditional contains an assignment, then we can't
231
- // know for sure that it doesn't impact the body of the conditional, so we
232
- // have to default to the block form.
233
- if (containsAssignment(predicate)) {
234
- return concat([
235
- `${keyword} `,
236
- align(keyword.length + 1, path.call(print, "body", 0)),
237
- indent(concat([hardline, path.call(print, "body", 1)])),
238
- concat([hardline, "end"])
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
- return printSingle(keyword)(path, { rubyModifier }, print);
243
- };
244
+ return printSingle(keyword)(path, { rubyModifier }, print);
245
+ };
244
246
 
245
247
  module.exports = {
246
248
  else: (path, opts, print) => {
@@ -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
- const { parts } = print(path);
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
- const doc = print(path);
66
+ let doc = print(path);
78
67
 
79
68
  if (node.type === "@label") {
80
- return `:${doc.slice(0, doc.length - 1)} =>`;
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, " =>"]);
@@ -1,5 +1,5 @@
1
1
  const { concat, group, lineSuffix, join } = require("../../prettier");
2
- const { literalLineNoBreak } = require("../../utils");
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(literalLineNoBreak, part.body.split("\n"));
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(concat([literalLineNoBreak].concat(parts).concat(ending)))
26
+ group(
27
+ concat([literallineWithoutBreakParent].concat(parts).concat(ending))
28
+ )
27
29
  )
28
30
  ])
29
31
  );
@@ -17,15 +17,8 @@ function printRestParam(symbol) {
17
17
  }
18
18
 
19
19
  function printParams(path, opts, print) {
20
- const [
21
- reqs,
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) {
@@ -82,13 +82,106 @@ 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 { quote } = path.getValue();
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 {
156
+ quote = node.quote.slice(1);
157
+ }
158
+ } else {
159
+ quote = opts.rubySingleQuote && isSingleQuotable(node) ? "'" : '"';
160
+ }
161
+
162
+ parts.push(quote);
163
+ path.each((childPath) => {
164
+ const child = childPath.getValue();
165
+
166
+ if (child.type !== "@tstring_content") {
167
+ parts.push(print(childPath));
168
+ } else {
169
+ parts.push(
170
+ join(literalline, normalizeQuotes(child.body, quote).split("\n"))
171
+ );
172
+ }
173
+ }, "body");
174
+
175
+ parts.push(quote);
176
+
177
+ // If we're inside of an assoc_new node as the key, then it will handle
178
+ // printing the : on its own since it could change sides.
179
+ const parentNode = path.getParentNode();
180
+ if (parentNode.type !== "assoc_new" || parentNode.body[0] !== node) {
181
+ parts.unshift(":");
182
+ }
90
183
 
91
- return concat([":", quote].concat(path.map(print, "body")).concat(quote));
184
+ return concat(parts);
92
185
  }
93
186
 
94
187
  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, _opts) {
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 pragmaPattern.test(text);
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 'delegate'
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
@@ -565,6 +593,12 @@ class Prettier::Parser < Ripper
565
593
  # binary is a parser event that represents a binary operation between two
566
594
  # values.
567
595
  def on_binary(left, oper, right)
596
+ # On most Ruby implementations, oper is a Symbol that represents that
597
+ # operation being performed. For instance in the example `1 < 2`, the `oper`
598
+ # object would be `:<`. However, on JRuby, it's an `@op` node, so here we're
599
+ # going to explicitly convert it into the same normalized form.
600
+ oper = scanner_events.delete(oper)[:body] unless oper.is_a?(Symbol)
601
+
568
602
  {
569
603
  type: :binary,
570
604
  body: [left, oper, right],
@@ -611,19 +645,19 @@ class Prettier::Parser < Ripper
611
645
  # bodystmt can't actually determine its bounds appropriately because it
612
646
  # doesn't necessarily know where it started. So the parent node needs to
613
647
  # report back down into this one where it goes.
614
- class BodyStmt < SimpleDelegator
648
+ class BodyStmt < Node
615
649
  def bind(sc, ec)
616
- merge!(sc: sc, ec: ec)
617
- parts = self[:body]
650
+ value.merge!(sc: sc, ec: ec)
651
+ parts = value[:body]
618
652
 
619
653
  # Here we're going to determine the bounds for the stmts
620
654
  consequent = parts[1..-1].compact.first
621
- self[:body][0].bind(sc, consequent ? consequent[:sc] : ec)
655
+ value[:body][0].bind(sc, consequent ? consequent[:sc] : ec)
622
656
 
623
657
  # Next we're going to determine the rescue clause if there is one
624
658
  if parts[1]
625
659
  consequent = parts[2..-1].compact.first
626
- self[:body][1].bind_end(consequent ? consequent[:sc] : ec)
660
+ value[:body][1].bind_end(consequent ? consequent[:sc] : ec)
627
661
  end
628
662
  end
629
663
  end
@@ -632,6 +666,7 @@ class Prettier::Parser < Ripper
632
666
  # of clauses within the body of a method or block.
633
667
  def on_bodystmt(stmts, rescued, ensured, elsed)
634
668
  BodyStmt.new(
669
+ self,
635
670
  type: :bodystmt,
636
671
  body: [stmts, rescued, ensured, elsed],
637
672
  sl: lineno,
@@ -656,7 +691,7 @@ class Prettier::Parser < Ripper
656
691
  body: [block_var, stmts],
657
692
  sl: beging[:sl],
658
693
  sc: beging[:sc],
659
- el: ending[:el],
694
+ el: [ending[:el], stmts[:el]].max,
660
695
  ec: ending[:ec]
661
696
  }
662
697
  end
@@ -709,7 +744,7 @@ class Prettier::Parser < Ripper
709
744
  body: [receiver, oper, sending],
710
745
  sl: receiver[:sl],
711
746
  sc: receiver[:sc],
712
- el: ending[:el],
747
+ el: [ending[:el], receiver[:el]].max,
713
748
  ec: ending[:ec]
714
749
  }
715
750
  end
@@ -1057,7 +1092,7 @@ class Prettier::Parser < Ripper
1057
1092
 
1058
1093
  beging.merge(
1059
1094
  type: :dyna_symbol,
1060
- quote: beging[:body][1],
1095
+ quote: beging[:body],
1061
1096
  body: string[:body],
1062
1097
  el: ending[:el],
1063
1098
  ec: ending[:ec]
@@ -1723,6 +1758,28 @@ class Prettier::Parser < Ripper
1723
1758
  )
1724
1759
  end
1725
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
+
1726
1783
  # The program node is the very top of the AST. Here we'll attach all of
1727
1784
  # the comments that we've gathered up over the course of parsing the
1728
1785
  # source string. We'll also attach on the __END__ content if there was
@@ -1817,12 +1874,12 @@ class Prettier::Parser < Ripper
1817
1874
  # doesn't really have all of the information that it needs in order to
1818
1875
  # determine its ending. Therefore it relies on its parent bodystmt node to
1819
1876
  # report its ending to it.
1820
- class Rescue < SimpleDelegator
1877
+ class Rescue < Node
1821
1878
  def bind_end(ec)
1822
- merge!(ec: ec)
1879
+ value.merge!(ec: ec)
1823
1880
 
1824
- stmts = self[:body][1]
1825
- consequent = self[:body][2]
1881
+ stmts = value[:body][1]
1882
+ consequent = value[:body][2]
1826
1883
 
1827
1884
  if consequent
1828
1885
  consequent.bind_end(ec)
@@ -1858,6 +1915,7 @@ class Prettier::Parser < Ripper
1858
1915
  end
1859
1916
 
1860
1917
  Rescue.new(
1918
+ self,
1861
1919
  beging.merge!(
1862
1920
  type: :rescue,
1863
1921
  body: [rescue_ex, stmts, consequent],
@@ -1958,36 +2016,29 @@ class Prettier::Parser < Ripper
1958
2016
  # stmts nodes will report back down the location information. We then
1959
2017
  # propagate that onto void_stmt nodes inside the stmts in order to make sure
1960
2018
  # all comments get printed appropriately.
1961
- class Stmts < SimpleDelegator
1962
- attr_reader :parser
1963
-
1964
- def initialize(parser, values)
1965
- @parser = parser
1966
- __setobj__(values)
1967
- end
1968
-
2019
+ class Stmts < Node
1969
2020
  def bind(sc, ec)
1970
- merge!(sc: sc, ec: ec)
2021
+ value.merge!(sc: sc, ec: ec)
1971
2022
 
1972
- if self[:body][0][:type] == :void_stmt
1973
- self[:body][0].merge!(sc: sc, ec: sc)
2023
+ if value[:body][0][:type] == :void_stmt
2024
+ value[:body][0].merge!(sc: sc, ec: sc)
1974
2025
  end
1975
2026
 
1976
2027
  attach_comments(sc, ec)
1977
2028
  end
1978
2029
 
1979
2030
  def bind_end(ec)
1980
- merge!(ec: ec)
2031
+ value.merge!(ec: ec)
1981
2032
  end
1982
2033
 
1983
2034
  def <<(statement)
1984
- if self[:body].any?
1985
- merge!(statement.slice(:el, :ec))
2035
+ if value[:body].any?
2036
+ value.merge!(statement.slice(:el, :ec))
1986
2037
  else
1987
- merge!(statement.slice(:sl, :el, :sc, :ec))
2038
+ value.merge!(statement.slice(:sl, :el, :sc, :ec))
1988
2039
  end
1989
2040
 
1990
- self[:body] << statement
2041
+ value[:body] << statement
1991
2042
  self
1992
2043
  end
1993
2044
 
@@ -2004,7 +2055,7 @@ class Prettier::Parser < Ripper
2004
2055
  return if attachable.empty?
2005
2056
 
2006
2057
  parser.comments -= attachable
2007
- self[:body] = (self[:body] + attachable).sort_by! { |node| node[:sc] }
2058
+ value[:body] = (value[:body] + attachable).sort_by! { |node| node[:sc] }
2008
2059
  end
2009
2060
  end
2010
2061