prettier 0.12.3 → 0.13.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +44 -1
- data/README.md +24 -1
- data/node_modules/prettier/bin-prettier.js +505 -276
- data/node_modules/prettier/index.js +514 -285
- data/node_modules/prettier/third-party.js +34 -3
- data/package.json +3 -4
- data/src/nodes/hashes.js +2 -1
- data/src/ripper.rb +281 -124
- data/src/ruby.js +6 -1
- metadata +2 -16
@@ -1682,6 +1682,10 @@ var PATTERN_FLOW_INDICATORS = /[,\[\]\{\}]/;
|
|
1682
1682
|
var PATTERN_TAG_HANDLE = /^(?:!|!!|![a-z\-]+!)$/i;
|
1683
1683
|
var PATTERN_TAG_URI = /^(?:!|[^,\[\]\{\}])(?:%[0-9a-f]{2}|[0-9a-z\-#;\/\?:@&=\+\$,_\.!~\*'\(\)\[\]])*$/i;
|
1684
1684
|
|
1685
|
+
function _class(obj) {
|
1686
|
+
return Object.prototype.toString.call(obj);
|
1687
|
+
}
|
1688
|
+
|
1685
1689
|
function is_EOL(c) {
|
1686
1690
|
return c === 0x0A
|
1687
1691
|
/* LF */
|
@@ -1985,7 +1989,31 @@ function mergeMappings(state, destination, source, overridableKeys) {
|
|
1985
1989
|
}
|
1986
1990
|
|
1987
1991
|
function storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, valueNode, startLine, startPos) {
|
1988
|
-
var index, quantity;
|
1992
|
+
var index, quantity; // The output is a plain object here, so keys can only be strings.
|
1993
|
+
// We need to convert keyNode to a string, but doing so can hang the process
|
1994
|
+
// (deeply nested arrays that explode exponentially using aliases).
|
1995
|
+
|
1996
|
+
if (Array.isArray(keyNode)) {
|
1997
|
+
keyNode = Array.prototype.slice.call(keyNode);
|
1998
|
+
|
1999
|
+
for (index = 0, quantity = keyNode.length; index < quantity; index += 1) {
|
2000
|
+
if (Array.isArray(keyNode[index])) {
|
2001
|
+
throwError(state, 'nested arrays are not supported inside keys');
|
2002
|
+
}
|
2003
|
+
|
2004
|
+
if (typeof keyNode === 'object' && _class(keyNode[index]) === '[object Object]') {
|
2005
|
+
keyNode[index] = '[object Object]';
|
2006
|
+
}
|
2007
|
+
}
|
2008
|
+
} // Avoid code execution in load() via toString property
|
2009
|
+
// (still use its own toString for arrays, timestamps,
|
2010
|
+
// and whatever user schema extensions happen to have @@toStringTag)
|
2011
|
+
|
2012
|
+
|
2013
|
+
if (typeof keyNode === 'object' && _class(keyNode) === '[object Object]') {
|
2014
|
+
keyNode = '[object Object]';
|
2015
|
+
}
|
2016
|
+
|
1989
2017
|
keyNode = String(keyNode);
|
1990
2018
|
|
1991
2019
|
if (_result === null) {
|
@@ -3480,6 +3508,7 @@ function encodeHex(character) {
|
|
3480
3508
|
function State$1(options) {
|
3481
3509
|
this.schema = options['schema'] || default_full;
|
3482
3510
|
this.indent = Math.max(1, options['indent'] || 2);
|
3511
|
+
this.noArrayIndent = options['noArrayIndent'] || false;
|
3483
3512
|
this.skipInvalid = options['skipInvalid'] || false;
|
3484
3513
|
this.flowLevel = common.isNothing(options['flowLevel']) ? -1 : options['flowLevel'];
|
3485
3514
|
this.styleMap = compileStyleMap(this.schema, options['styles'] || null);
|
@@ -4080,14 +4109,16 @@ function writeNode(state, level, object, block, compact, iskey) {
|
|
4080
4109
|
}
|
4081
4110
|
}
|
4082
4111
|
} else if (type === '[object Array]') {
|
4112
|
+
var arrayLevel = state.noArrayIndent && level > 0 ? level - 1 : level;
|
4113
|
+
|
4083
4114
|
if (block && state.dump.length !== 0) {
|
4084
|
-
writeBlockSequence(state,
|
4115
|
+
writeBlockSequence(state, arrayLevel, state.dump, compact);
|
4085
4116
|
|
4086
4117
|
if (duplicate) {
|
4087
4118
|
state.dump = '&ref_' + duplicateIndex + state.dump;
|
4088
4119
|
}
|
4089
4120
|
} else {
|
4090
|
-
writeFlowSequence(state,
|
4121
|
+
writeFlowSequence(state, arrayLevel, state.dump);
|
4091
4122
|
|
4092
4123
|
if (duplicate) {
|
4093
4124
|
state.dump = '&ref_' + duplicateIndex + ' ' + state.dump;
|
data/package.json
CHANGED
@@ -1,12 +1,11 @@
|
|
1
1
|
{
|
2
2
|
"name": "@prettier/plugin-ruby",
|
3
|
-
"version": "0.
|
3
|
+
"version": "0.13.0",
|
4
4
|
"description": "prettier plugin for the Ruby programming language",
|
5
5
|
"main": "src/ruby.js",
|
6
6
|
"scripts": {
|
7
7
|
"lint": "eslint --cache .",
|
8
8
|
"print": "prettier --plugin=.",
|
9
|
-
"rubocop": "run() { prettier --plugin=. $@ | bundle exec rubocop --stdin $1; }; run",
|
10
9
|
"test": "jest"
|
11
10
|
},
|
12
11
|
"repository": {
|
@@ -24,9 +23,9 @@
|
|
24
23
|
},
|
25
24
|
"devDependencies": {
|
26
25
|
"all-contributors-cli": "^6.1.2",
|
27
|
-
"eslint": "^
|
26
|
+
"eslint": "^6.0.1",
|
28
27
|
"eslint-config-airbnb-base": "^13.1.0",
|
29
|
-
"eslint-config-prettier": "^
|
28
|
+
"eslint-config-prettier": "^6.0.0",
|
30
29
|
"eslint-plugin-import": "^2.16.0",
|
31
30
|
"jest": "^24.0.0"
|
32
31
|
},
|
data/src/nodes/hashes.js
CHANGED
@@ -78,8 +78,9 @@ module.exports = {
|
|
78
78
|
const isInner = index !== assocNodes.length - 1;
|
79
79
|
const valueNode = assocNode.body[1];
|
80
80
|
|
81
|
-
const isStraightHeredoc = valueNode.type === "heredoc";
|
81
|
+
const isStraightHeredoc = valueNode && valueNode.type === "heredoc";
|
82
82
|
const isSquigglyHeredoc =
|
83
|
+
valueNode &&
|
83
84
|
valueNode.type === "string_literal" &&
|
84
85
|
valueNode.body[0].type === "heredoc";
|
85
86
|
|
data/src/ripper.rb
CHANGED
@@ -10,6 +10,15 @@ require 'json' unless defined?(JSON)
|
|
10
10
|
require 'ripper'
|
11
11
|
|
12
12
|
class RipperJS < Ripper
|
13
|
+
attr_reader :lines, :__end__
|
14
|
+
|
15
|
+
def initialize(source, *args)
|
16
|
+
super(source, *args)
|
17
|
+
|
18
|
+
@lines = source.split("\n")
|
19
|
+
@__end__ = nil
|
20
|
+
end
|
21
|
+
|
13
22
|
private
|
14
23
|
|
15
24
|
# Scanner events occur when the lexer hits a new token, like a keyword or an
|
@@ -99,44 +108,239 @@ class RipperJS < Ripper
|
|
99
108
|
end
|
100
109
|
)
|
101
110
|
|
111
|
+
# For each node, we need to attach where it came from in order to be able to
|
112
|
+
# support placing the cursor correctly before and after formatting.
|
113
|
+
#
|
102
114
|
# For most nodes, it's enough to look at the child nodes to determine the
|
103
115
|
# start of the parent node. However, for some nodes it's necessary to keep
|
104
116
|
# track of the keywords as they come in from the lexer and to modify the start
|
105
|
-
# node once we have it.
|
106
|
-
# embed block comments into the right kind of node.
|
117
|
+
# node once we have it.
|
107
118
|
prepend(
|
108
119
|
Module.new do
|
109
|
-
|
120
|
+
def initialize(source, *args)
|
121
|
+
super(source, *args)
|
110
122
|
|
111
|
-
|
112
|
-
|
113
|
-
|
123
|
+
@scanner_events = []
|
124
|
+
@line_counts = [0]
|
125
|
+
|
126
|
+
source.split("\n").each do |line|
|
127
|
+
line_counts << line_counts.last + line.size + 1
|
128
|
+
end
|
114
129
|
end
|
115
130
|
|
116
131
|
def self.prepended(base)
|
117
|
-
base.attr_reader :
|
132
|
+
base.attr_reader :scanner_events, :line_counts
|
118
133
|
end
|
119
134
|
|
120
135
|
private
|
121
136
|
|
122
|
-
def
|
123
|
-
|
137
|
+
def char_pos
|
138
|
+
line_counts[lineno - 1] + column
|
124
139
|
end
|
125
140
|
|
126
|
-
|
127
|
-
|
141
|
+
def char_start_for(body)
|
142
|
+
children = body.length == 1 && body[0].is_a?(Array) ? body[0] : body
|
143
|
+
char_starts =
|
144
|
+
children.map { |part| part[:char_start] if part.is_a?(Hash) }.compact
|
145
|
+
|
146
|
+
char_starts.min || char_pos
|
147
|
+
end
|
128
148
|
|
149
|
+
def find_scanner_event(type, body = :any)
|
150
|
+
index =
|
151
|
+
scanner_events.rindex do |scanner_event|
|
152
|
+
scanner_event[:type] == type &&
|
153
|
+
(body == :any || (scanner_event[:body] == body))
|
154
|
+
end
|
155
|
+
|
156
|
+
scanner_events.delete_at(index)
|
157
|
+
end
|
158
|
+
|
159
|
+
# :backref, :const, :embdoc, :embdoc_beg, :embdoc_end,
|
160
|
+
# :embexpr_beg, :embexpr_end, :embvar, :heredoc_beg, :heredoc_end,
|
161
|
+
# :ident, :lbrace, :lbracket, :lparen, :op, :period, :regexp_beg,
|
162
|
+
# :regexp_end, :rparen, :symbeg, :symbols_beg, :tlambda, :tlambeg,
|
163
|
+
# :tstring_beg, :tstring_content, :tstring_end
|
164
|
+
|
165
|
+
events = {
|
166
|
+
BEGIN: [:@kw, 'BEGIN'],
|
167
|
+
END: [:@kw, 'END'],
|
168
|
+
alias: [:@kw, 'alias'],
|
169
|
+
assoc_splat: [:@op, '**'],
|
170
|
+
arg_paren: :@lparen,
|
171
|
+
args_add_star: [:@op, '*'],
|
172
|
+
begin: [:@kw, 'begin'],
|
173
|
+
blockarg: [:@op, '&'],
|
174
|
+
brace_block: :@lbrace,
|
175
|
+
break: [:@kw, 'break'],
|
176
|
+
case: [:@kw, 'case'],
|
177
|
+
class: [:@kw, 'class'],
|
178
|
+
def: [:@kw, 'def'],
|
179
|
+
defined: [:@kw, 'defined?'],
|
180
|
+
defs: [:@kw, 'def'],
|
181
|
+
do_block: [:@kw, 'do'],
|
182
|
+
else: [:@kw, 'else'],
|
183
|
+
elsif: [:@kw, 'elsif'],
|
184
|
+
ensure: [:@kw, 'ensure'],
|
185
|
+
excessed_comma: :@comma,
|
186
|
+
for: [:@kw, 'for'],
|
187
|
+
hash: :@lbrace,
|
188
|
+
if: [:@kw, 'if'],
|
189
|
+
kwrest_param: [:@op, '**'],
|
190
|
+
lambda: :@tlambda,
|
191
|
+
mlhs_paren: :@lparen,
|
192
|
+
mrhs_add_star: [:@op, '*'],
|
193
|
+
module: [:@kw, 'module'],
|
194
|
+
next: [:@kw, 'next'],
|
195
|
+
paren: :@lparen,
|
196
|
+
qsymbols_new: :@qsymbols_beg,
|
197
|
+
qwords_new: :@qwords_beg,
|
198
|
+
redo: [:@kw, 'redo'],
|
199
|
+
regexp_literal: :@regexp_beg,
|
200
|
+
rescue: [:@kw, 'rescue'],
|
201
|
+
rest_param: [:@op, '*'],
|
202
|
+
retry: [:@kw, 'retry'],
|
203
|
+
return0: [:@kw, 'return'],
|
204
|
+
return: [:@kw, 'return'],
|
205
|
+
sclass: [:@kw, 'class'],
|
206
|
+
string_dvar: :@embvar,
|
207
|
+
string_embexpr: :@embexpr_beg,
|
208
|
+
super: [:@kw, 'super'],
|
209
|
+
symbols_new: :@symbols_beg,
|
210
|
+
top_const_field: [:@op, '::'],
|
211
|
+
top_const_ref: [:@op, '::'],
|
212
|
+
undef: [:@kw, 'undef'],
|
213
|
+
unless: [:@kw, 'unless'],
|
214
|
+
until: [:@kw, 'until'],
|
215
|
+
var_alias: [:@kw, 'alias'],
|
216
|
+
when: [:@kw, 'when'],
|
217
|
+
while: [:@kw, 'while'],
|
218
|
+
words_new: :@words_beg,
|
219
|
+
xstring_literal: :@backtick,
|
220
|
+
yield0: [:@kw, 'yield'],
|
221
|
+
yield: [:@kw, 'yield'],
|
222
|
+
zsuper: [:@kw, 'super']
|
223
|
+
}
|
224
|
+
|
225
|
+
events.each do |event, (type, scanned)|
|
129
226
|
define_method(:"on_#{event}") do |*body|
|
130
|
-
|
227
|
+
node = find_scanner_event(type, scanned || :any)
|
228
|
+
|
229
|
+
super(*body).merge!(
|
230
|
+
start: node[:start],
|
231
|
+
char_start: node[:char_start],
|
232
|
+
char_end: char_pos
|
233
|
+
)
|
131
234
|
end
|
132
235
|
end
|
133
236
|
|
134
|
-
|
135
|
-
|
237
|
+
# Array nodes can contain a myriad of subnodes because of the special
|
238
|
+
# array literal syntax like %w and %i. As a result, we may be looking for
|
239
|
+
# an left bracket, or we may be just looking at the children.
|
240
|
+
def on_array(*body)
|
241
|
+
if body[0] && %i[args args_add_star].include?(body[0][:type])
|
242
|
+
node = find_scanner_event(:@lbracket)
|
243
|
+
|
244
|
+
super(*body).merge!(
|
245
|
+
start: node[:start],
|
246
|
+
char_start: node[:char_start],
|
247
|
+
char_end: char_pos
|
248
|
+
)
|
249
|
+
else
|
250
|
+
super(*body).merge!(
|
251
|
+
char_start: char_start_for(body), char_end: char_pos
|
252
|
+
)
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
# Params have a somewhat interesting structure in that they are an array
|
257
|
+
# of arrays where the position in the top-level array indicates the type
|
258
|
+
# of param and the subarray is the list of parameters of that type. We
|
259
|
+
# therefore have to flatten them down to get to the location.
|
260
|
+
def on_params(*body)
|
261
|
+
super(*body).merge!(
|
262
|
+
char_start: char_start_for(body.flatten(1)), char_end: char_pos
|
263
|
+
)
|
264
|
+
end
|
265
|
+
|
266
|
+
# String literals and either contain string parts or a heredoc. If it
|
267
|
+
# contains a heredoc we can just go directly to the child nodes, otherwise
|
268
|
+
# we need to look for a `tstring_beg`.
|
269
|
+
def on_string_literal(*body)
|
270
|
+
if body[0][:type] == :heredoc
|
271
|
+
super(*body).merge!(
|
272
|
+
char_start: char_start_for(body), char_end: char_pos
|
273
|
+
)
|
274
|
+
else
|
275
|
+
node = find_scanner_event(:@tstring_beg)
|
276
|
+
|
277
|
+
super(*body).merge!(
|
278
|
+
start: node[:start],
|
279
|
+
char_start: node[:char_start],
|
280
|
+
char_end: char_pos
|
281
|
+
)
|
282
|
+
end
|
283
|
+
end
|
284
|
+
|
285
|
+
# Technically, the `not` operator is a unary operator but is reported as
|
286
|
+
# a keyword and not an operator. Because of the inconsistency, we have to
|
287
|
+
# manually look for the correct scanner event here.
|
288
|
+
def on_unary(*body)
|
289
|
+
node =
|
290
|
+
if body[0] == :not
|
291
|
+
find_scanner_event(:@kw, 'not')
|
292
|
+
else
|
293
|
+
find_scanner_event(:@op)
|
294
|
+
end
|
295
|
+
|
296
|
+
super(*body).merge!(
|
297
|
+
start: node[:start], char_start: node[:char_start], char_end: char_pos
|
298
|
+
)
|
299
|
+
end
|
300
|
+
|
301
|
+
# Symbols don't necessarily have to have a @symbeg event fired before they
|
302
|
+
# start. For example, you can have symbol literals inside an `alias` node
|
303
|
+
# if you're just using bare words, as in: `alias foo bar`. So this is a
|
304
|
+
# special case in which if there is a `:@symbeg` event we can hook on to
|
305
|
+
# then we use it, otherwise we just look at the beginning of the first
|
306
|
+
# child node.
|
307
|
+
%i[dyna_symbol symbol_literal].each do |event|
|
308
|
+
define_method(:"on_#{event}") do |*body|
|
309
|
+
char_start =
|
310
|
+
if scanner_events.any? { |sevent| sevent[:type] == :@symbeg }
|
311
|
+
find_scanner_event(:@symbeg)[:char_start]
|
312
|
+
else
|
313
|
+
char_start_for(body)
|
314
|
+
end
|
315
|
+
|
316
|
+
super(*body).merge!(char_start: char_start, char_end: char_pos)
|
317
|
+
end
|
136
318
|
end
|
137
319
|
|
138
320
|
def on_program(*body)
|
139
|
-
super(*body).
|
321
|
+
super(*body).merge!(start: 1, char_start: 0, char_end: char_pos)
|
322
|
+
end
|
323
|
+
|
324
|
+
defined =
|
325
|
+
private_instance_methods(false).grep(/\Aon_/) { $'.to_sym } +
|
326
|
+
%i[embdoc embdoc_beg embdoc_end heredoc_beg heredoc_end]
|
327
|
+
|
328
|
+
(SCANNER_EVENTS - defined).each do |event|
|
329
|
+
define_method(:"on_#{event}") do |body|
|
330
|
+
super(body).tap do |node|
|
331
|
+
node.merge!(char_start: char_pos, char_end: char_pos + body.size)
|
332
|
+
|
333
|
+
scanner_events << node
|
334
|
+
end
|
335
|
+
end
|
336
|
+
end
|
337
|
+
|
338
|
+
(PARSER_EVENTS - defined).each do |event|
|
339
|
+
define_method(:"on_#{event}") do |*body|
|
340
|
+
super(*body).merge!(
|
341
|
+
char_start: char_start_for(body), char_end: char_pos
|
342
|
+
)
|
343
|
+
end
|
140
344
|
end
|
141
345
|
end
|
142
346
|
)
|
@@ -153,6 +357,7 @@ class RipperJS < Ripper
|
|
153
357
|
aref: [:body, 1],
|
154
358
|
args_add_block: [:body, 0],
|
155
359
|
break: [:body, 0],
|
360
|
+
call: [:body, 0],
|
156
361
|
command: [:body, 1],
|
157
362
|
command_call: [:body, 3],
|
158
363
|
regexp_literal: [:body, 0],
|
@@ -238,15 +443,15 @@ class RipperJS < Ripper
|
|
238
443
|
def on_comment(body)
|
239
444
|
sexp = { type: :@comment, body: body.chomp, start: lineno, end: lineno }
|
240
445
|
|
241
|
-
case RipperJS.lex_state_name(state)
|
242
|
-
when '
|
446
|
+
case RipperJS.lex_state_name(state).gsub('EXPR_', '')
|
447
|
+
when 'END', 'ARG|LABELED', 'ENDFN'
|
243
448
|
last_sexp.merge!(comments: [sexp])
|
244
|
-
when '
|
245
|
-
'
|
449
|
+
when 'CMDARG', 'END|ENDARG', 'ENDARG', 'ARG', 'FNAME|FITEM', 'CLASS',
|
450
|
+
'END|LABEL'
|
246
451
|
inline_comments << sexp
|
247
|
-
when '
|
452
|
+
when 'BEG|LABEL', 'MID'
|
248
453
|
inline_comments << sexp.merge!(break: true)
|
249
|
-
when '
|
454
|
+
when 'DOT'
|
250
455
|
last_sexp.merge!(comments: [sexp.merge!(break: true)])
|
251
456
|
end
|
252
457
|
|
@@ -255,7 +460,7 @@ class RipperJS < Ripper
|
|
255
460
|
|
256
461
|
defined = private_instance_methods(false).grep(/\Aon_/) { $'.to_sym }
|
257
462
|
|
258
|
-
(
|
463
|
+
(PARSER_EVENTS - defined).each do |event|
|
259
464
|
define_method(:"on_#{event}") do |*body|
|
260
465
|
super(*body).tap do |sexp|
|
261
466
|
@last_sexp = sexp
|
@@ -327,7 +532,8 @@ class RipperJS < Ripper
|
|
327
532
|
|
328
533
|
def on_comment(body)
|
329
534
|
super(body).tap do |sexp|
|
330
|
-
|
535
|
+
lex_state = RipperJS.lex_state_name(state).gsub('EXPR_', '')
|
536
|
+
block_comments << sexp if lex_state == 'BEG'
|
331
537
|
end
|
332
538
|
end
|
333
539
|
|
@@ -410,62 +616,40 @@ class RipperJS < Ripper
|
|
410
616
|
end
|
411
617
|
)
|
412
618
|
|
413
|
-
# These are the event types that contain _actual_ string content. If there is
|
414
|
-
# an encoding magic comment at the top of the file, ripper will actually
|
415
|
-
# change into that encoding for the storage of the string. This will break
|
416
|
-
# everything, so we need to force the encoding back into UTF-8 so that
|
417
|
-
# the JSON library won't break.
|
418
619
|
prepend(
|
419
620
|
Module.new do
|
420
621
|
private
|
421
622
|
|
623
|
+
# These are the event types that contain _actual_ string content. If
|
624
|
+
# there is an encoding magic comment at the top of the file, ripper will
|
625
|
+
# actually change into that encoding for the storage of the string. This
|
626
|
+
# will break everything, so we need to force the encoding back into UTF-8
|
627
|
+
# so that the JSON library won't break.
|
422
628
|
%w[comment ident tstring_content].each do |event|
|
423
629
|
define_method(:"on_#{event}") do |body|
|
424
630
|
super(body.force_encoding('UTF-8'))
|
425
631
|
end
|
426
632
|
end
|
427
|
-
end
|
428
|
-
)
|
429
|
-
|
430
|
-
# Handles __END__ syntax, which allows individual scripts to keep content
|
431
|
-
# after the main ruby code that can be read through DATA. Which looks like:
|
432
|
-
#
|
433
|
-
# foo.bar
|
434
|
-
#
|
435
|
-
# __END__
|
436
|
-
# some other content that isn't read by ripper normally
|
437
|
-
prepend(
|
438
|
-
Module.new do
|
439
|
-
def initialize(source, *args)
|
440
|
-
super(source, *args)
|
441
|
-
@source = source
|
442
|
-
@ending = nil
|
443
|
-
end
|
444
|
-
|
445
|
-
def self.prepended(base)
|
446
|
-
base.attr_reader :source, :ending
|
447
|
-
end
|
448
|
-
|
449
|
-
private
|
450
633
|
|
634
|
+
# Handles __END__ syntax, which allows individual scripts to keep content
|
635
|
+
# after the main ruby code that can be read through DATA. It looks like:
|
636
|
+
#
|
637
|
+
# foo.bar
|
638
|
+
#
|
639
|
+
# __END__
|
640
|
+
# some other content that isn't normally read by ripper
|
451
641
|
def on___end__(body)
|
452
|
-
@
|
642
|
+
@__end__ = super(lines[lineno..-1].join("\n"))
|
453
643
|
end
|
454
644
|
|
455
645
|
def on_program(*body)
|
456
|
-
super(*body).tap { |
|
646
|
+
super(*body).tap { |node| node[:body][0][:body] << __end__ if __end__ }
|
457
647
|
end
|
458
|
-
end
|
459
|
-
)
|
460
|
-
|
461
|
-
# Adds the used quote type onto string nodes. This is necessary because we're
|
462
|
-
# going to have to stick to whatever quote the user chose if there are escape
|
463
|
-
# sequences within the string. For example, if you have '\n' we can't switch
|
464
|
-
# to double quotes without changing what it means.
|
465
|
-
prepend(
|
466
|
-
Module.new do
|
467
|
-
private
|
468
648
|
|
649
|
+
# Adds the used quote type onto string nodes. This is necessary because
|
650
|
+
# we're going to have to stick to whatever quote the user chose if there
|
651
|
+
# are escape sequences within the string. For example, if you have '\n'
|
652
|
+
# we can't switch to double quotes without changing what it means.
|
469
653
|
def on_tstring_end(quote)
|
470
654
|
last_sexp.merge!(quote: quote)
|
471
655
|
end
|
@@ -473,66 +657,45 @@ class RipperJS < Ripper
|
|
473
657
|
def on_label_end(quote)
|
474
658
|
last_sexp.merge!(quote: quote[0]) # quote is ": or ':
|
475
659
|
end
|
476
|
-
end
|
477
|
-
)
|
478
|
-
|
479
|
-
# Normally access controls are reported as vcall nodes. This module creates a
|
480
|
-
# new node type to explicitly track those nodes instead, so that the printer
|
481
|
-
# can add new lines as necessary.
|
482
|
-
prepend(
|
483
|
-
Module.new do
|
484
|
-
KEYWORDS = %w[private protected public].freeze
|
485
|
-
|
486
|
-
def initialize(source, *args)
|
487
|
-
super(source, *args)
|
488
|
-
@lines = source.split("\n")
|
489
|
-
end
|
490
|
-
|
491
|
-
def self.prepended(base)
|
492
|
-
base.attr_reader :lines
|
493
|
-
end
|
494
|
-
|
495
|
-
private
|
496
660
|
|
661
|
+
# Normally access controls are reported as vcall nodes. This creates a
|
662
|
+
# new node type to explicitly track those nodes instead, so that the
|
663
|
+
# printer can add new lines as necessary.
|
497
664
|
def on_vcall(ident)
|
498
|
-
|
499
|
-
|
665
|
+
@access_controls ||= %w[private protected public].freeze
|
666
|
+
|
667
|
+
super(ident).tap do |node|
|
668
|
+
if !@access_controls.include?(ident[:body]) ||
|
500
669
|
ident[:body] != lines[lineno - 1].strip
|
501
670
|
next
|
502
671
|
end
|
503
672
|
|
504
|
-
|
673
|
+
node.merge!(type: :access_ctrl)
|
505
674
|
end
|
506
675
|
end
|
507
|
-
end
|
508
|
-
)
|
509
|
-
|
510
|
-
# When the only statement inside of a `def` node is a `begin` node, then you
|
511
|
-
# can safely replace the body of the `def` with the body of the `begin`. For
|
512
|
-
# example:
|
513
|
-
#
|
514
|
-
# def foo
|
515
|
-
# begin
|
516
|
-
# try_something
|
517
|
-
# rescue SomeError => error
|
518
|
-
# handle_error(error)
|
519
|
-
# end
|
520
|
-
# end
|
521
|
-
#
|
522
|
-
# can get transformed into:
|
523
|
-
#
|
524
|
-
# def foo
|
525
|
-
# try_something
|
526
|
-
# rescue SomeError => error
|
527
|
-
# handle_error(error)
|
528
|
-
# end
|
529
|
-
#
|
530
|
-
# This module handles this by hoisting up the `bodystmt` node from the inner
|
531
|
-
# `begin` up to the `def`.
|
532
|
-
prepend(
|
533
|
-
Module.new do
|
534
|
-
private
|
535
676
|
|
677
|
+
# When the only statement inside of a `def` node is a `begin` node, then
|
678
|
+
# you can safely replace the body of the `def` with the body of the
|
679
|
+
# `begin`. For example:
|
680
|
+
#
|
681
|
+
# def foo
|
682
|
+
# begin
|
683
|
+
# try_something
|
684
|
+
# rescue SomeError => error
|
685
|
+
# handle_error(error)
|
686
|
+
# end
|
687
|
+
# end
|
688
|
+
#
|
689
|
+
# can get transformed into:
|
690
|
+
#
|
691
|
+
# def foo
|
692
|
+
# try_something
|
693
|
+
# rescue SomeError => error
|
694
|
+
# handle_error(error)
|
695
|
+
# end
|
696
|
+
#
|
697
|
+
# This module handles this by hoisting up the `bodystmt` node from the
|
698
|
+
# inner `begin` up to the `def`.
|
536
699
|
def on_def(ident, params, bodystmt)
|
537
700
|
def_bodystmt = bodystmt
|
538
701
|
stmts, *other_parts = bodystmt[:body]
|
@@ -544,17 +707,11 @@ class RipperJS < Ripper
|
|
544
707
|
|
545
708
|
super(ident, params, def_bodystmt)
|
546
709
|
end
|
547
|
-
end
|
548
|
-
)
|
549
|
-
|
550
|
-
# By default, Ripper parses the expression `lambda { foo }` as a
|
551
|
-
# `method_add_block` node, so we can't turn it back into `-> { foo }`. This
|
552
|
-
# module overrides that behavior and reports it back as a `lambda` node
|
553
|
-
# instead.
|
554
|
-
prepend(
|
555
|
-
Module.new do
|
556
|
-
private
|
557
710
|
|
711
|
+
# By default, Ripper parses the expression `lambda { foo }` as a
|
712
|
+
# `method_add_block` node, so we can't turn it back into `-> { foo }`.
|
713
|
+
# This module overrides that behavior and reports it back as a `lambda`
|
714
|
+
# node instead.
|
558
715
|
def on_method_add_block(invocation, block)
|
559
716
|
# It's possible to hit a `method_add_block` node without going through
|
560
717
|
# `method_add_arg` node, ex: `super {}`. In that case we're definitely
|