@@ -82,25 +82,33 @@ def assert_row_indenting(lines, row)
82
82
end
83
83
84
84
def assert_indent_level ( lines , expected , local_variables : [ ] )
85
- indent_level , _code_block_open = check_state ( lines , local_variables : local_variables )
85
+ indent_level , _continue , _code_block_open = check_state ( lines , local_variables : local_variables )
86
86
error_message = "Calculated the wrong number of indent level for:\n #{ lines . join ( "\n " ) } "
87
87
assert_equal ( expected , indent_level , error_message )
88
88
end
89
89
90
+ def assert_should_continue ( lines , expected , local_variables : [ ] )
91
+ _indent_level , continue , _code_block_open = check_state ( lines , local_variables : local_variables )
92
+ error_message = "Wrong result of should_continue for:\n #{ lines . join ( "\n " ) } "
93
+ assert_equal ( expected , continue , error_message )
94
+ end
95
+
90
96
def assert_code_block_open ( lines , expected , local_variables : [ ] )
91
- _indent_level , code_block_open = check_state ( lines , local_variables : local_variables )
97
+ _indent_level , _continue , code_block_open = check_state ( lines , local_variables : local_variables )
92
98
error_message = "Wrong result of code_block_open for:\n #{ lines . join ( "\n " ) } "
93
99
assert_equal ( expected , code_block_open , error_message )
94
100
end
95
101
96
102
def check_state ( lines , local_variables : [ ] )
97
103
context = build_context ( local_variables )
98
- tokens = RubyLex . ripper_lex_without_warning ( lines . join ( "\n " ) , context : context )
104
+ code = lines . join ( "\n " )
105
+ tokens = RubyLex . ripper_lex_without_warning ( code , context : context )
99
106
opens = IRB ::NestingParser . open_tokens ( tokens )
100
107
ruby_lex = RubyLex . new ( context )
101
108
indent_level = ruby_lex . calc_indent_level ( opens )
102
- code_block_open = !opens . empty? || ruby_lex . process_continue ( tokens )
103
- [ indent_level , code_block_open ]
109
+ continue = ruby_lex . should_continue? ( tokens )
110
+ terminated = ruby_lex . code_terminated? ( code , tokens , opens )
111
+ [ indent_level , continue , !terminated ]
104
112
end
105
113
106
114
def test_interpolate_token_with_heredoc_and_unclosed_embexpr
@@ -235,7 +243,7 @@ def test_symbols
235
243
def test_endless_range_at_end_of_line
236
244
input_with_prompt = [
237
245
PromptRow . new ( '001:0: :> ' , %q(a = 3..) ) ,
238
- PromptRow . new ( '002:0: :* ' , %q() ) ,
246
+ PromptRow . new ( '002:0: :> ' , %q() ) ,
239
247
]
240
248
241
249
lines = input_with_prompt . map ( &:content )
@@ -256,7 +264,7 @@ def test_heredoc_with_embexpr
256
264
PromptRow . new ( '009:0:]:* ' , %q(B) ) ,
257
265
PromptRow . new ( '010:0:]:* ' , %q(}) ) ,
258
266
PromptRow . new ( '011:0: :> ' , %q(]) ) ,
259
- PromptRow . new ( '012:0: :* ' , %q() ) ,
267
+ PromptRow . new ( '012:0: :> ' , %q() ) ,
260
268
]
261
269
262
270
lines = input_with_prompt . map ( &:content )
@@ -285,9 +293,9 @@ def test_heredoc_prompt_with_quotes
285
293
def test_backtick_method
286
294
input_with_prompt = [
287
295
PromptRow . new ( '001:0: :> ' , %q(self.`(arg)) ) ,
288
- PromptRow . new ( '002:0: :* ' , %q() ) ,
296
+ PromptRow . new ( '002:0: :> ' , %q() ) ,
289
297
PromptRow . new ( '003:0: :> ' , %q(def `(); end) ) ,
290
- PromptRow . new ( '004:0: :* ' , %q() ) ,
298
+ PromptRow . new ( '004:0: :> ' , %q() ) ,
291
299
]
292
300
293
301
lines = input_with_prompt . map ( &:content )
@@ -777,6 +785,36 @@ def test_dynamic_prompt_with_blank_line
777
785
assert_dynamic_prompt ( lines , expected_prompt_list )
778
786
end
779
787
788
+ def test_should_continue
789
+ assert_should_continue ( [ 'a' ] , false )
790
+ assert_should_continue ( [ '/a/' ] , false )
791
+ assert_should_continue ( [ 'a;' ] , false )
792
+ assert_should_continue ( [ '<<A' , 'A' ] , false )
793
+ assert_should_continue ( [ 'a...' ] , false )
794
+ assert_should_continue ( [ 'a\\' , '' ] , true )
795
+ assert_should_continue ( [ 'a.' ] , true )
796
+ assert_should_continue ( [ 'a+' ] , true )
797
+ assert_should_continue ( [ 'a; #comment' , '' , '=begin' , 'embdoc' , '=end' , '' ] , false )
798
+ assert_should_continue ( [ 'a+ #comment' , '' , '=begin' , 'embdoc' , '=end' , '' ] , true )
799
+ end
800
+
801
+ def test_code_block_open_with_should_continue
802
+ # syntax ok
803
+ assert_code_block_open ( [ 'a' ] , false ) # continue: false
804
+ assert_code_block_open ( [ 'a\\' , '' ] , true ) # continue: true
805
+
806
+ # recoverable syntax error code is not terminated
807
+ assert_code_block_open ( [ 'a+' , '' ] , true )
808
+
809
+ # unrecoverable syntax error code is terminated
810
+ assert_code_block_open ( [ '.; a+' , '' ] , false )
811
+
812
+ # other syntax error that failed to determine if it is recoverable or not
813
+ assert_code_block_open ( [ '@; a' ] , false )
814
+ assert_code_block_open ( [ '@; a+' ] , true )
815
+ assert_code_block_open ( [ '@; (a' ] , true )
816
+ end
817
+
780
818
def test_broken_percent_literal
781
819
tokens = RubyLex . ripper_lex_without_warning ( '%wwww' )
782
820
pos_to_index = { }
0 commit comments