prettier 0.12.3 → 0.13.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|