irb 1.14.0 → 1.14.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/Gemfile +1 -1
- data/README.md +8 -2
- data/lib/irb/command/base.rb +10 -8
- data/lib/irb/command/debug.rb +8 -6
- data/lib/irb/command/help.rb +1 -1
- data/lib/irb/context.rb +42 -13
- data/lib/irb/debug.rb +6 -10
- data/lib/irb/default_commands.rb +15 -7
- data/lib/irb/easter-egg.rb +8 -5
- data/lib/irb/input-method.rb +10 -17
- data/lib/irb/inspector.rb +31 -30
- data/lib/irb/nesting_parser.rb +196 -194
- data/lib/irb/pager.rb +5 -1
- data/lib/irb/ruby-lex.rb +84 -82
- data/lib/irb/ruby_logo.aa +75 -37
- data/lib/irb/source_finder.rb +1 -1
- data/lib/irb/version.rb +2 -2
- data/lib/irb/workspace.rb +7 -5
- data/lib/irb.rb +32 -57
- metadata +2 -2
data/lib/irb/nesting_parser.rb
CHANGED
@@ -3,235 +3,237 @@ module IRB
|
|
3
3
|
module NestingParser
|
4
4
|
IGNORE_TOKENS = %i[on_sp on_ignored_nl on_comment on_embdoc_beg on_embdoc on_embdoc_end]
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
6
|
+
class << self
|
7
|
+
# Scan each token and call the given block with array of token and other information for parsing
|
8
|
+
def scan_opens(tokens)
|
9
|
+
opens = []
|
10
|
+
pending_heredocs = []
|
11
|
+
first_token_on_line = true
|
12
|
+
tokens.each do |t|
|
13
|
+
skip = false
|
14
|
+
last_tok, state, args = opens.last
|
15
|
+
case state
|
16
|
+
when :in_alias_undef
|
17
|
+
skip = t.event == :on_kw
|
18
|
+
when :in_unquoted_symbol
|
19
|
+
unless IGNORE_TOKENS.include?(t.event)
|
20
|
+
opens.pop
|
21
|
+
skip = true
|
22
|
+
end
|
23
|
+
when :in_lambda_head
|
24
|
+
opens.pop if t.event == :on_tlambeg || (t.event == :on_kw && t.tok == 'do')
|
25
|
+
when :in_method_head
|
26
|
+
unless IGNORE_TOKENS.include?(t.event)
|
27
|
+
next_args = []
|
28
|
+
body = nil
|
29
|
+
if args.include?(:receiver)
|
30
|
+
case t.event
|
31
|
+
when :on_lparen, :on_ivar, :on_gvar, :on_cvar
|
32
|
+
# def (receiver). | def @ivar. | def $gvar. | def @@cvar.
|
33
|
+
next_args << :dot
|
34
|
+
when :on_kw
|
35
|
+
case t.tok
|
36
|
+
when 'self', 'true', 'false', 'nil'
|
37
|
+
# def self(arg) | def self.
|
38
|
+
next_args.push(:arg, :dot)
|
39
|
+
else
|
40
|
+
# def if(arg)
|
41
|
+
skip = true
|
42
|
+
next_args << :arg
|
43
|
+
end
|
44
|
+
when :on_op, :on_backtick
|
45
|
+
# def +(arg)
|
40
46
|
skip = true
|
41
47
|
next_args << :arg
|
48
|
+
when :on_ident, :on_const
|
49
|
+
# def a(arg) | def a.
|
50
|
+
next_args.push(:arg, :dot)
|
42
51
|
end
|
43
|
-
when :on_op, :on_backtick
|
44
|
-
# def +(arg)
|
45
|
-
skip = true
|
46
|
-
next_args << :arg
|
47
|
-
when :on_ident, :on_const
|
48
|
-
# def a(arg) | def a.
|
49
|
-
next_args.push(:arg, :dot)
|
50
52
|
end
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
next_args << :name if t.event == :on_period || (t.event == :on_op && t.tok == '::')
|
55
|
-
end
|
56
|
-
if args.include?(:name)
|
57
|
-
if %i[on_ident on_const on_op on_kw on_backtick].include?(t.event)
|
58
|
-
# def name(arg) | def receiver.name(arg)
|
59
|
-
next_args << :arg
|
60
|
-
skip = true
|
53
|
+
if args.include?(:dot)
|
54
|
+
# def receiver.name
|
55
|
+
next_args << :name if t.event == :on_period || (t.event == :on_op && t.tok == '::')
|
61
56
|
end
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
57
|
+
if args.include?(:name)
|
58
|
+
if %i[on_ident on_const on_op on_kw on_backtick].include?(t.event)
|
59
|
+
# def name(arg) | def receiver.name(arg)
|
60
|
+
next_args << :arg
|
61
|
+
skip = true
|
62
|
+
end
|
63
|
+
end
|
64
|
+
if args.include?(:arg)
|
65
|
+
case t.event
|
66
|
+
when :on_nl, :on_semicolon
|
67
|
+
# def receiver.f;
|
68
|
+
body = :normal
|
69
|
+
when :on_lparen
|
70
|
+
# def receiver.f()
|
71
|
+
next_args << :eq
|
72
|
+
else
|
73
|
+
if t.event == :on_op && t.tok == '='
|
74
|
+
# def receiver.f =
|
75
|
+
body = :oneliner
|
76
|
+
else
|
77
|
+
# def receiver.f arg
|
78
|
+
next_args << :arg_without_paren
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
if args.include?(:eq)
|
72
83
|
if t.event == :on_op && t.tok == '='
|
73
|
-
# def receiver.f =
|
74
84
|
body = :oneliner
|
75
85
|
else
|
76
|
-
|
77
|
-
next_args << :arg_without_paren
|
86
|
+
body = :normal
|
78
87
|
end
|
79
88
|
end
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
89
|
+
if args.include?(:arg_without_paren)
|
90
|
+
if %i[on_semicolon on_nl].include?(t.event)
|
91
|
+
# def f a;
|
92
|
+
body = :normal
|
93
|
+
else
|
94
|
+
# def f a, b
|
95
|
+
next_args << :arg_without_paren
|
96
|
+
end
|
86
97
|
end
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
body = :normal
|
98
|
+
if body == :oneliner
|
99
|
+
opens.pop
|
100
|
+
elsif body
|
101
|
+
opens[-1] = [last_tok, nil]
|
92
102
|
else
|
93
|
-
|
94
|
-
next_args << :arg_without_paren
|
103
|
+
opens[-1] = [last_tok, :in_method_head, next_args]
|
95
104
|
end
|
96
105
|
end
|
97
|
-
|
98
|
-
|
99
|
-
|
106
|
+
when :in_for_while_until_condition
|
107
|
+
if t.event == :on_semicolon || t.event == :on_nl || (t.event == :on_kw && t.tok == 'do')
|
108
|
+
skip = true if t.event == :on_kw && t.tok == 'do'
|
100
109
|
opens[-1] = [last_tok, nil]
|
101
|
-
else
|
102
|
-
opens[-1] = [last_tok, :in_method_head, next_args]
|
103
110
|
end
|
104
111
|
end
|
105
|
-
when :in_for_while_until_condition
|
106
|
-
if t.event == :on_semicolon || t.event == :on_nl || (t.event == :on_kw && t.tok == 'do')
|
107
|
-
skip = true if t.event == :on_kw && t.tok == 'do'
|
108
|
-
opens[-1] = [last_tok, nil]
|
109
|
-
end
|
110
|
-
end
|
111
112
|
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
opens << [t, nil]
|
118
|
-
when 'end'
|
119
|
-
opens.pop
|
120
|
-
when 'def'
|
121
|
-
opens << [t, :in_method_head, [:receiver, :name]]
|
122
|
-
when 'if', 'unless'
|
123
|
-
unless t.state.allbits?(Ripper::EXPR_LABEL)
|
113
|
+
unless skip
|
114
|
+
case t.event
|
115
|
+
when :on_kw
|
116
|
+
case t.tok
|
117
|
+
when 'begin', 'class', 'module', 'do', 'case'
|
124
118
|
opens << [t, nil]
|
125
|
-
end
|
126
|
-
|
127
|
-
|
128
|
-
opens << [t, :
|
129
|
-
|
130
|
-
|
131
|
-
|
119
|
+
when 'end'
|
120
|
+
opens.pop
|
121
|
+
when 'def'
|
122
|
+
opens << [t, :in_method_head, [:receiver, :name]]
|
123
|
+
when 'if', 'unless'
|
124
|
+
unless t.state.allbits?(Ripper::EXPR_LABEL)
|
125
|
+
opens << [t, nil]
|
126
|
+
end
|
127
|
+
when 'while', 'until'
|
128
|
+
unless t.state.allbits?(Ripper::EXPR_LABEL)
|
129
|
+
opens << [t, :in_for_while_until_condition]
|
130
|
+
end
|
131
|
+
when 'ensure', 'rescue'
|
132
|
+
unless t.state.allbits?(Ripper::EXPR_LABEL)
|
133
|
+
opens.pop
|
134
|
+
opens << [t, nil]
|
135
|
+
end
|
136
|
+
when 'alias'
|
137
|
+
opens << [t, :in_alias_undef, 2]
|
138
|
+
when 'undef'
|
139
|
+
opens << [t, :in_alias_undef, 1]
|
140
|
+
when 'elsif', 'else', 'when'
|
132
141
|
opens.pop
|
133
142
|
opens << [t, nil]
|
143
|
+
when 'for'
|
144
|
+
opens << [t, :in_for_while_until_condition]
|
145
|
+
when 'in'
|
146
|
+
if last_tok&.event == :on_kw && %w[case in].include?(last_tok.tok) && first_token_on_line
|
147
|
+
opens.pop
|
148
|
+
opens << [t, nil]
|
149
|
+
end
|
134
150
|
end
|
135
|
-
when
|
136
|
-
opens << [t, :
|
137
|
-
when
|
138
|
-
opens << [t,
|
139
|
-
when
|
151
|
+
when :on_tlambda
|
152
|
+
opens << [t, :in_lambda_head]
|
153
|
+
when :on_lparen, :on_lbracket, :on_lbrace, :on_tlambeg, :on_embexpr_beg, :on_embdoc_beg
|
154
|
+
opens << [t, nil]
|
155
|
+
when :on_rparen, :on_rbracket, :on_rbrace, :on_embexpr_end, :on_embdoc_end
|
156
|
+
opens.pop
|
157
|
+
when :on_heredoc_beg
|
158
|
+
pending_heredocs << t
|
159
|
+
when :on_heredoc_end
|
140
160
|
opens.pop
|
161
|
+
when :on_backtick
|
162
|
+
opens << [t, nil] if t.state.allbits?(Ripper::EXPR_BEG)
|
163
|
+
when :on_tstring_beg, :on_words_beg, :on_qwords_beg, :on_symbols_beg, :on_qsymbols_beg, :on_regexp_beg
|
141
164
|
opens << [t, nil]
|
142
|
-
when
|
143
|
-
opens
|
144
|
-
when
|
145
|
-
if
|
146
|
-
opens
|
165
|
+
when :on_tstring_end, :on_regexp_end, :on_label_end
|
166
|
+
opens.pop
|
167
|
+
when :on_symbeg
|
168
|
+
if t.tok == ':'
|
169
|
+
opens << [t, :in_unquoted_symbol]
|
170
|
+
else
|
147
171
|
opens << [t, nil]
|
148
172
|
end
|
149
173
|
end
|
150
|
-
when :on_tlambda
|
151
|
-
opens << [t, :in_lambda_head]
|
152
|
-
when :on_lparen, :on_lbracket, :on_lbrace, :on_tlambeg, :on_embexpr_beg, :on_embdoc_beg
|
153
|
-
opens << [t, nil]
|
154
|
-
when :on_rparen, :on_rbracket, :on_rbrace, :on_embexpr_end, :on_embdoc_end
|
155
|
-
opens.pop
|
156
|
-
when :on_heredoc_beg
|
157
|
-
pending_heredocs << t
|
158
|
-
when :on_heredoc_end
|
159
|
-
opens.pop
|
160
|
-
when :on_backtick
|
161
|
-
opens << [t, nil] if t.state.allbits?(Ripper::EXPR_BEG)
|
162
|
-
when :on_tstring_beg, :on_words_beg, :on_qwords_beg, :on_symbols_beg, :on_qsymbols_beg, :on_regexp_beg
|
163
|
-
opens << [t, nil]
|
164
|
-
when :on_tstring_end, :on_regexp_end, :on_label_end
|
165
|
-
opens.pop
|
166
|
-
when :on_symbeg
|
167
|
-
if t.tok == ':'
|
168
|
-
opens << [t, :in_unquoted_symbol]
|
169
|
-
else
|
170
|
-
opens << [t, nil]
|
171
|
-
end
|
172
174
|
end
|
175
|
+
if t.event == :on_nl || t.event == :on_semicolon
|
176
|
+
first_token_on_line = true
|
177
|
+
elsif t.event != :on_sp
|
178
|
+
first_token_on_line = false
|
179
|
+
end
|
180
|
+
if pending_heredocs.any? && t.tok.include?("\n")
|
181
|
+
pending_heredocs.reverse_each { |t| opens << [t, nil] }
|
182
|
+
pending_heredocs = []
|
183
|
+
end
|
184
|
+
if opens.last && opens.last[1] == :in_alias_undef && !IGNORE_TOKENS.include?(t.event) && t.event != :on_heredoc_end
|
185
|
+
tok, state, arg = opens.pop
|
186
|
+
opens << [tok, state, arg - 1] if arg >= 1
|
187
|
+
end
|
188
|
+
yield t, opens if block_given?
|
173
189
|
end
|
174
|
-
|
175
|
-
first_token_on_line = true
|
176
|
-
elsif t.event != :on_sp
|
177
|
-
first_token_on_line = false
|
178
|
-
end
|
179
|
-
if pending_heredocs.any? && t.tok.include?("\n")
|
180
|
-
pending_heredocs.reverse_each { |t| opens << [t, nil] }
|
181
|
-
pending_heredocs = []
|
182
|
-
end
|
183
|
-
if opens.last && opens.last[1] == :in_alias_undef && !IGNORE_TOKENS.include?(t.event) && t.event != :on_heredoc_end
|
184
|
-
tok, state, arg = opens.pop
|
185
|
-
opens << [tok, state, arg - 1] if arg >= 1
|
186
|
-
end
|
187
|
-
yield t, opens if block_given?
|
190
|
+
opens.map(&:first) + pending_heredocs.reverse
|
188
191
|
end
|
189
|
-
opens.map(&:first) + pending_heredocs.reverse
|
190
|
-
end
|
191
192
|
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
193
|
+
def open_tokens(tokens)
|
194
|
+
# scan_opens without block will return a list of open tokens at last token position
|
195
|
+
scan_opens(tokens)
|
196
|
+
end
|
196
197
|
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
198
|
+
# Calculates token information [line_tokens, prev_opens, next_opens, min_depth] for each line.
|
199
|
+
# Example code
|
200
|
+
# ["hello
|
201
|
+
# world"+(
|
202
|
+
# First line
|
203
|
+
# line_tokens: [[lbracket, '['], [tstring_beg, '"'], [tstring_content("hello\nworld"), "hello\n"]]
|
204
|
+
# prev_opens: []
|
205
|
+
# next_tokens: [lbracket, tstring_beg]
|
206
|
+
# min_depth: 0 (minimum at beginning of line)
|
207
|
+
# Second line
|
208
|
+
# line_tokens: [[tstring_content("hello\nworld"), "world"], [tstring_end, '"'], [op, '+'], [lparen, '(']]
|
209
|
+
# prev_opens: [lbracket, tstring_beg]
|
210
|
+
# next_tokens: [lbracket, lparen]
|
211
|
+
# min_depth: 1 (minimum just after tstring_end)
|
212
|
+
def parse_by_line(tokens)
|
213
|
+
line_tokens = []
|
214
|
+
prev_opens = []
|
215
|
+
min_depth = 0
|
216
|
+
output = []
|
217
|
+
last_opens = scan_opens(tokens) do |t, opens|
|
218
|
+
depth = t == opens.last&.first ? opens.size - 1 : opens.size
|
219
|
+
min_depth = depth if depth < min_depth
|
220
|
+
if t.tok.include?("\n")
|
221
|
+
t.tok.each_line do |line|
|
222
|
+
line_tokens << [t, line]
|
223
|
+
next if line[-1] != "\n"
|
224
|
+
next_opens = opens.map(&:first)
|
225
|
+
output << [line_tokens, prev_opens, next_opens, min_depth]
|
226
|
+
prev_opens = next_opens
|
227
|
+
min_depth = prev_opens.size
|
228
|
+
line_tokens = []
|
229
|
+
end
|
230
|
+
else
|
231
|
+
line_tokens << [t, t.tok]
|
228
232
|
end
|
229
|
-
else
|
230
|
-
line_tokens << [t, t.tok]
|
231
233
|
end
|
234
|
+
output << [line_tokens, prev_opens, last_opens, min_depth] if line_tokens.any?
|
235
|
+
output
|
232
236
|
end
|
233
|
-
output << [line_tokens, prev_opens, last_opens, min_depth] if line_tokens.any?
|
234
|
-
output
|
235
237
|
end
|
236
238
|
end
|
237
239
|
end
|
data/lib/irb/pager.rb
CHANGED
@@ -33,7 +33,11 @@ module IRB
|
|
33
33
|
# the `IRB::Abort` exception only interrupts IRB's execution but doesn't affect the pager
|
34
34
|
# So to properly terminate the pager with Ctrl-C, we need to catch `IRB::Abort` and kill the pager process
|
35
35
|
rescue IRB::Abort
|
36
|
-
|
36
|
+
begin
|
37
|
+
Process.kill("TERM", pid) if pid
|
38
|
+
rescue Errno::ESRCH
|
39
|
+
# Pager process already terminated
|
40
|
+
end
|
37
41
|
nil
|
38
42
|
rescue Errno::EPIPE
|
39
43
|
end
|
data/lib/irb/ruby-lex.rb
CHANGED
@@ -36,29 +36,6 @@ module IRB
|
|
36
36
|
:massign,
|
37
37
|
]
|
38
38
|
|
39
|
-
class TerminateLineInput < StandardError
|
40
|
-
def initialize
|
41
|
-
super("Terminate Line Input")
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
def self.compile_with_errors_suppressed(code, line_no: 1)
|
46
|
-
begin
|
47
|
-
result = yield code, line_no
|
48
|
-
rescue ArgumentError
|
49
|
-
# Ruby can issue an error for the code if there is an
|
50
|
-
# incomplete magic comment for encoding in it. Force an
|
51
|
-
# expression with a new line before the code in this
|
52
|
-
# case to prevent magic comment handling. To make sure
|
53
|
-
# line numbers in the lexed code remain the same,
|
54
|
-
# decrease the line number by one.
|
55
|
-
code = ";\n#{code}"
|
56
|
-
line_no -= 1
|
57
|
-
result = yield code, line_no
|
58
|
-
end
|
59
|
-
result
|
60
|
-
end
|
61
|
-
|
62
39
|
ERROR_TOKENS = [
|
63
40
|
:on_parse_error,
|
64
41
|
:compile_error,
|
@@ -68,70 +45,102 @@ module IRB
|
|
68
45
|
:on_param_error
|
69
46
|
]
|
70
47
|
|
71
|
-
|
72
|
-
|
48
|
+
LTYPE_TOKENS = %i[
|
49
|
+
on_heredoc_beg on_tstring_beg
|
50
|
+
on_regexp_beg on_symbeg on_backtick
|
51
|
+
on_symbols_beg on_qsymbols_beg
|
52
|
+
on_words_beg on_qwords_beg
|
53
|
+
]
|
54
|
+
|
55
|
+
class TerminateLineInput < StandardError
|
56
|
+
def initialize
|
57
|
+
super("Terminate Line Input")
|
58
|
+
end
|
73
59
|
end
|
74
60
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
61
|
+
class << self
|
62
|
+
def compile_with_errors_suppressed(code, line_no: 1)
|
63
|
+
begin
|
64
|
+
result = yield code, line_no
|
65
|
+
rescue ArgumentError
|
66
|
+
# Ruby can issue an error for the code if there is an
|
67
|
+
# incomplete magic comment for encoding in it. Force an
|
68
|
+
# expression with a new line before the code in this
|
69
|
+
# case to prevent magic comment handling. To make sure
|
70
|
+
# line numbers in the lexed code remain the same,
|
71
|
+
# decrease the line number by one.
|
72
|
+
code = ";\n#{code}"
|
73
|
+
line_no -= 1
|
74
|
+
result = yield code, line_no
|
75
|
+
end
|
76
|
+
result
|
77
|
+
end
|
78
|
+
|
79
|
+
def generate_local_variables_assign_code(local_variables)
|
80
|
+
"#{local_variables.join('=')}=nil;" unless local_variables.empty?
|
82
81
|
end
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
tokens.
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
82
|
+
|
83
|
+
# Some part of the code is not included in Ripper's token.
|
84
|
+
# Example: DATA part, token after heredoc_beg when heredoc has unclosed embexpr.
|
85
|
+
# With interpolated tokens, tokens.map(&:tok).join will be equal to code.
|
86
|
+
def interpolate_ripper_ignored_tokens(code, tokens)
|
87
|
+
line_positions = [0]
|
88
|
+
code.lines.each do |line|
|
89
|
+
line_positions << line_positions.last + line.bytesize
|
90
|
+
end
|
91
|
+
prev_byte_pos = 0
|
92
|
+
interpolated = []
|
93
|
+
prev_line = 1
|
94
|
+
tokens.each do |t|
|
95
|
+
line, col = t.pos
|
96
|
+
byte_pos = line_positions[line - 1] + col
|
97
|
+
if prev_byte_pos < byte_pos
|
98
|
+
tok = code.byteslice(prev_byte_pos...byte_pos)
|
99
|
+
pos = [prev_line, prev_byte_pos - line_positions[prev_line - 1]]
|
100
|
+
interpolated << Ripper::Lexer::Elem.new(pos, :on_ignored_by_ripper, tok, 0)
|
101
|
+
prev_line += tok.count("\n")
|
102
|
+
end
|
103
|
+
interpolated << t
|
104
|
+
prev_byte_pos = byte_pos + t.tok.bytesize
|
105
|
+
prev_line += t.tok.count("\n")
|
106
|
+
end
|
107
|
+
if prev_byte_pos < code.bytesize
|
108
|
+
tok = code.byteslice(prev_byte_pos..)
|
91
109
|
pos = [prev_line, prev_byte_pos - line_positions[prev_line - 1]]
|
92
110
|
interpolated << Ripper::Lexer::Elem.new(pos, :on_ignored_by_ripper, tok, 0)
|
93
|
-
prev_line += tok.count("\n")
|
94
111
|
end
|
95
|
-
interpolated
|
96
|
-
prev_byte_pos = byte_pos + t.tok.bytesize
|
97
|
-
prev_line += t.tok.count("\n")
|
98
|
-
end
|
99
|
-
if prev_byte_pos < code.bytesize
|
100
|
-
tok = code.byteslice(prev_byte_pos..)
|
101
|
-
pos = [prev_line, prev_byte_pos - line_positions[prev_line - 1]]
|
102
|
-
interpolated << Ripper::Lexer::Elem.new(pos, :on_ignored_by_ripper, tok, 0)
|
112
|
+
interpolated
|
103
113
|
end
|
104
|
-
interpolated
|
105
|
-
end
|
106
114
|
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
115
|
+
def ripper_lex_without_warning(code, local_variables: [])
|
116
|
+
verbose, $VERBOSE = $VERBOSE, nil
|
117
|
+
lvars_code = generate_local_variables_assign_code(local_variables)
|
118
|
+
original_code = code
|
119
|
+
if lvars_code
|
120
|
+
code = "#{lvars_code}\n#{code}"
|
121
|
+
line_no = 0
|
122
|
+
else
|
123
|
+
line_no = 1
|
124
|
+
end
|
117
125
|
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
126
|
+
compile_with_errors_suppressed(code, line_no: line_no) do |inner_code, line_no|
|
127
|
+
lexer = Ripper::Lexer.new(inner_code, '-', line_no)
|
128
|
+
tokens = []
|
129
|
+
lexer.scan.each do |t|
|
130
|
+
next if t.pos.first == 0
|
131
|
+
prev_tk = tokens.last
|
132
|
+
position_overlapped = prev_tk && t.pos[0] == prev_tk.pos[0] && t.pos[1] < prev_tk.pos[1] + prev_tk.tok.bytesize
|
133
|
+
if position_overlapped
|
134
|
+
tokens[-1] = t if ERROR_TOKENS.include?(prev_tk.event) && !ERROR_TOKENS.include?(t.event)
|
135
|
+
else
|
136
|
+
tokens << t
|
137
|
+
end
|
129
138
|
end
|
139
|
+
interpolate_ripper_ignored_tokens(original_code, tokens)
|
130
140
|
end
|
131
|
-
|
141
|
+
ensure
|
142
|
+
$VERBOSE = verbose
|
132
143
|
end
|
133
|
-
ensure
|
134
|
-
$VERBOSE = verbose
|
135
144
|
end
|
136
145
|
|
137
146
|
def check_code_state(code, local_variables:)
|
@@ -391,13 +400,6 @@ module IRB
|
|
391
400
|
end
|
392
401
|
end
|
393
402
|
|
394
|
-
LTYPE_TOKENS = %i[
|
395
|
-
on_heredoc_beg on_tstring_beg
|
396
|
-
on_regexp_beg on_symbeg on_backtick
|
397
|
-
on_symbols_beg on_qsymbols_beg
|
398
|
-
on_words_beg on_qwords_beg
|
399
|
-
]
|
400
|
-
|
401
403
|
def ltype_from_open_tokens(opens)
|
402
404
|
start_token = opens.reverse_each.find do |tok|
|
403
405
|
LTYPE_TOKENS.include?(tok.event)
|