mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00

* [ruby/irb] Update help message for next context-mode of 4 While here, fixing tab/space issues in help message, and sync rdoc for IRB class to match the help message. https://github.com/ruby/irb/commit/ef8e3901cc * [ruby/irb] Do not continue line if last expression is an endless range Fixes [Bug #14824] https://github.com/ruby/irb/commit/63414f8465 * [ruby/irb] Add a test for not continuing when endless range at eol https://github.com/ruby/irb/commit/1020ac9c65 * [ruby/irb] Make save-history extension safe for concurrent use This makes the save-history extension check for modifications to the history file before saving it. If the history file was modified after the history was loaded and before it was saved, append only the new history lines to the history file. This can result in more lines in the history file than SAVE_HISTORY allows. However, that will be fixed the next time irb is run and the history is saved. Fixes [Bug #13654] https://github.com/ruby/irb/commit/041ef53845 * Fix errors when XDG_CONFIG_HOME points to non-writable directory `$HOME/.config` is not writable on CI because I think tests should not corrupt user's data. And GitHub Actions CI sets `XDG_CONFIG_HOME` since `Version: 20210309.1`. https://github.com/ruby/actions/runs/2130811016?check_suite_focus=true#step:16:301 ``` Errno::EACCES: Permission denied @ dir_s_mkdir - /home/runner/.config/irb ``` * Try to fix errors in TestIRB::TestHistory too https://github.com/ruby/actions/runs/2137935523?check_suite_focus=true#step:9:562 ``` 1) Error: TestIRB::TestHistory#test_history_concurrent_use: Errno::EACCES: Permission denied @ dir_s_mkdir - /home/runner/.config/irb /home/runner/work/actions/actions/ruby/lib/fileutils.rb:253:in `mkdir' /home/runner/work/actions/actions/ruby/lib/fileutils.rb:253:in `fu_mkdir' /home/runner/work/actions/actions/ruby/lib/fileutils.rb:231:in `block (2 levels) in mkdir_p' /home/runner/work/actions/actions/ruby/lib/fileutils.rb:229:in `reverse_each' /home/runner/work/actions/actions/ruby/lib/fileutils.rb:229:in `block in mkdir_p' /home/runner/work/actions/actions/ruby/lib/fileutils.rb:211:in `each' /home/runner/work/actions/actions/ruby/lib/fileutils.rb:211:in `mkdir_p' /home/runner/work/actions/actions/ruby/lib/irb/init.rb:355:in `rc_file_generators' /home/runner/work/actions/actions/ruby/lib/irb/init.rb:330:in `rc_file' /home/runner/work/actions/actions/ruby/test/irb/test_history.rb:170:in `block in assert_history' /home/runner/work/actions/actions/ruby/lib/tmpdir.rb:96:in `mktmpdir' /home/runner/work/actions/actions/ruby/test/irb/test_history.rb:168:in `assert_history' /home/runner/work/actions/actions/ruby/test/irb/test_history.rb:133:in `test_history_concurrent_use' ``` * [ruby/irb] Define "measure" command without forced override https://github.com/ruby/irb/commit/9587ba13b5 * [ruby/irb] Add all lib files automatically https://github.com/ruby/irb/commit/ecc82336b7 * [ruby/irb] Don't call Ruby 2.4+'s String#pretty_print https://github.com/ruby/irb/commit/89bcf107be * [ruby/irb] Implement ls command https://github.com/ruby/irb/commit/19b6c20604 * [ruby/irb] Add whereami command https://github.com/ruby/irb/commit/bc822e4aac * [ruby/irb] Fix column overflow on ls output https://github.com/ruby/irb/commit/6115754623 * [ruby/irb] Fix step's argument cols.size was calling Integer#size, which returns 8. Fixing a bug of https://github.com/ruby/irb/pull/209 https://github.com/ruby/irb/commit/c93ae4be71 * [ruby/irb] Deal with different screen sizes e.g. http://rubyci.s3.amazonaws.com/centos8/ruby-master/log/20210321T063003Z.fail.html.gz https://github.com/ruby/irb/commit/ddb3472ba2 * [ruby/irb] Have some right padding instead of filling out an entire line https://github.com/ruby/irb/commit/6ac8f45f5f * Suppress verbose messages Get rid of warnings in the parallel test. ``` unknown command: "Switch to inspect mode." ``` * [ruby/irb] Change ripper_lex_without_warning to a class method https://github.com/ruby/irb/commit/d9f8abc17e * [ruby/irb] Complete require and require_relative https://github.com/ruby/irb/commit/1c61178b4c * [ruby/reline] Add Reline.ungetc to control buffer https://github.com/ruby/reline/commit/43ac03c624 * [ruby/reline] Reline.delete_text removes the current line in multiline https://github.com/ruby/reline/commit/da90c094a1 * [ruby/reline] Support preposing and postposing for Reline.completion_proc https://github.com/ruby/reline/commit/1f469de90c * [ruby/reline] Suppress crashing when completer_{quote,word_break}_characters is empty https://github.com/ruby/reline/commit/c6f1164942 * [ruby/irb] fix completion test when out-of-place build * [ruby/irb] Cache completion files to require https://github.com/ruby/irb/commit/612ebcb311 * [ruby/irb] Always add input method when calling Irb.new in tests When passes input method as nil to Context.new through Irb.new, ReidlineInputMethod.new is executed and the global internal state of Reline is rewritten, therefore other tests are failed in the Ruby repository. This commit changes to use TestInputMethod. https://github.com/ruby/irb/commit/010dce9210 * [ruby/irb] Prevent the completion from crashing if rdoc is missing There are cases where ruby is installed without rdoc and e.g. lib/irb/cmd/help.rb also handles the LoadError Here is how to replicate the issue: ``` $ docker run -it alpine:3.13.3 sh / # apk add ruby ruby-irb ruby-io-console / # irb irb(main):001:0> Class[TAB][TAB] ``` And you end up with something like: ``` irb(main):001:0> ClassTraceback (most recent call last): 34: from /usr/bin/irb:23:in `<main>' 33: from /usr/bin/irb:23:in `load' 32: from /usr/lib/ruby/gems/2.7.0/gems/irb-1.2.6/exe/irb:11:in `<top (required)>' 31: from /usr/lib/ruby/2.7.0/irb.rb:400:in `start' 30: from /usr/lib/ruby/2.7.0/irb.rb:471:in `run' 29: from /usr/lib/ruby/2.7.0/irb.rb:471:in `catch' 28: from /usr/lib/ruby/2.7.0/irb.rb:472:in `block in run' 27: from /usr/lib/ruby/2.7.0/irb.rb:537:in `eval_input' 26: from /usr/lib/ruby/2.7.0/irb/ruby-lex.rb:150:in `each_top_level_statement' 25: from /usr/lib/ruby/2.7.0/irb/ruby-lex.rb:150:in `catch' 24: from /usr/lib/ruby/2.7.0/irb/ruby-lex.rb:151:in `block in each_top_level_statement' 23: from /usr/lib/ruby/2.7.0/irb/ruby-lex.rb:151:in `loop' 22: from /usr/lib/ruby/2.7.0/irb/ruby-lex.rb:154:in `block (2 levels) in each_top_level_statement' 21: from /usr/lib/ruby/2.7.0/irb/ruby-lex.rb:182:in `lex' 20: from /usr/lib/ruby/2.7.0/irb.rb:518:in `block in eval_input' 19: from /usr/lib/ruby/2.7.0/irb.rb:704:in `signal_status' 18: from /usr/lib/ruby/2.7.0/irb.rb:519:in `block (2 levels) in eval_input' 17: from /usr/lib/ruby/2.7.0/irb/input-method.rb:294:in `gets' 16: from /usr/lib/ruby/2.7.0/forwardable.rb:235:in `readmultiline' 15: from /usr/lib/ruby/2.7.0/forwardable.rb:235:in `readmultiline' 14: from /usr/lib/ruby/2.7.0/reline.rb:175:in `readmultiline' 13: from /usr/lib/ruby/2.7.0/reline.rb:238:in `inner_readline' 12: from /usr/lib/ruby/2.7.0/reline.rb:238:in `loop' 11: from /usr/lib/ruby/2.7.0/reline.rb:239:in `block in inner_readline' 10: from /usr/lib/ruby/2.7.0/reline.rb:270:in `read_io' 9: from /usr/lib/ruby/2.7.0/reline.rb:270:in `loop' 8: from /usr/lib/ruby/2.7.0/reline.rb:311:in `block in read_io' 7: from /usr/lib/ruby/2.7.0/reline.rb:240:in `block (2 levels) in inner_readline' 6: from /usr/lib/ruby/2.7.0/reline.rb:240:in `each' 5: from /usr/lib/ruby/2.7.0/reline.rb:241:in `block (3 levels) in inner_readline' 4: from /usr/lib/ruby/2.7.0/reline/line_editor.rb:820:in `input_key' 3: from /usr/lib/ruby/2.7.0/reline/line_editor.rb:608:in `complete' 2: from /usr/lib/ruby/2.7.0/irb/completion.rb:269:in `block in <module:InputCompletor>' 1: from /usr/lib/ruby/2.7.0/rubygems/core_ext/kernel_require.rb:92:in `require' /usr/lib/ruby/2.7.0/rubygems/core_ext/kernel_require.rb:92:in `require': cannot load such file -- rdoc (LoadError) ``` https://github.com/ruby/irb/commit/a2d299c2ac * [ruby/irb] Suppress verbose messages in the parallel test `:VERBOSE` flag needs to be set prior to `IRB::Irb.new`. https://github.com/ruby/irb/commit/78604682d9 * [ruby/irb] SIGINT should raise Interrupt after IRB session https://github.com/ruby/irb/commit/5832cfe75b * [ruby/irb] Colorize `__END__` as keyword https://github.com/ruby/irb/commit/9b84018311 * [ruby/irb] Add show_source command https://github.com/ruby/irb/commit/108cb04352 * [ruby/reline] Reset @rest_height when clear screen https://github.com/ruby/reline/commit/3a7019b0d5 * [ruby/irb] process multi-line pastes as a single entity this allows pasting leading-dot chained methods correctly: ```ruby class A def a; self; end def b; true; end end a = A.new a .a .b ``` will properly return `true` instead of erroring on the `.a` line: ``` irb(main):001:1* class A irb(main):002:1* def a; self; end irb(main):003:0> end irb(main):004:0* irb(main):005:0> a = A.new irb(main):006:0* irb(main):007:0> a irb(main):008:0> .a irb(main):009:0> .a => #<A:0x00007f984211fbe8> ``` https://github.com/ruby/irb/commit/45aeb52575 * [ruby/irb] Add yamatanooroti test example https://github.com/ruby/irb/commit/279155fcee * [ruby/irb] Add test for multiline paste https://github.com/ruby/irb/commit/e93c9cb54d * [ruby/irb] Evaluate each toplevel statement https://github.com/ruby/irb/commit/bc1b1d8bc3 * [ruby/irb] Version 1.3.5 https://github.com/ruby/irb/commit/22e2ddf715 * [ruby/reline] Version 0.2.5 https://github.com/ruby/reline/commit/22ce5651e5 Co-authored-by: Jeremy Evans <code@jeremyevans.net> Co-authored-by: Kazuhiro NISHIYAMA <zn@mbf.nifty.com> Co-authored-by: Takashi Kokubun <takashikkbn@gmail.com> Co-authored-by: Nobuyoshi Nakada <nobu@ruby-lang.org> Co-authored-by: Aleksandar Ivanov <aivanov92@gmail.com> Co-authored-by: Koichi Sasada <ko1@atdot.net> Co-authored-by: Cody Cutrer <cody@instructure.com>
586 lines
19 KiB
Ruby
586 lines
19 KiB
Ruby
$LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
|
|
require 'irb/ruby-lex'
|
|
require 'test/unit'
|
|
require 'ostruct'
|
|
|
|
module TestIRB
|
|
class TestRubyLex < Test::Unit::TestCase
|
|
Row = Struct.new(:content, :current_line_spaces, :new_line_spaces, :nesting_level)
|
|
|
|
class MockIO_AutoIndent
|
|
def initialize(params, &assertion)
|
|
@params = params
|
|
@assertion = assertion
|
|
end
|
|
|
|
def auto_indent(&block)
|
|
result = block.call(*@params)
|
|
@assertion.call(result)
|
|
end
|
|
end
|
|
|
|
def assert_indenting(lines, correct_space_count, add_new_line)
|
|
lines = lines + [""] if add_new_line
|
|
last_line_index = lines.length - 1
|
|
byte_pointer = lines.last.length
|
|
|
|
ruby_lex = RubyLex.new()
|
|
io = MockIO_AutoIndent.new([lines, last_line_index, byte_pointer, add_new_line]) do |auto_indent|
|
|
error_message = "Calculated the wrong number of spaces for:\n #{lines.join("\n")}"
|
|
assert_equal(correct_space_count, auto_indent, error_message)
|
|
end
|
|
ruby_lex.set_input(io)
|
|
context = OpenStruct.new(auto_indent_mode: true)
|
|
ruby_lex.set_auto_indent(context)
|
|
end
|
|
|
|
def assert_nesting_level(lines, expected)
|
|
ruby_lex = RubyLex.new()
|
|
io = proc{ lines.join("\n") }
|
|
ruby_lex.set_input(io, io)
|
|
ruby_lex.lex
|
|
error_message = "Calculated the wrong number of nesting level for:\n #{lines.join("\n")}"
|
|
assert_equal(expected, ruby_lex.instance_variable_get(:@indent), error_message)
|
|
end
|
|
|
|
def test_auto_indent
|
|
input_with_correct_indents = [
|
|
Row.new(%q(def each_top_level_statement), nil, 2),
|
|
Row.new(%q( initialize_input), nil, 2),
|
|
Row.new(%q( catch(:TERM_INPUT) do), nil, 4),
|
|
Row.new(%q( loop do), nil, 6),
|
|
Row.new(%q( begin), nil, 8),
|
|
Row.new(%q( prompt), nil, 8),
|
|
Row.new(%q( unless l = lex), nil, 10),
|
|
Row.new(%q( throw :TERM_INPUT if @line == ''), nil, 10),
|
|
Row.new(%q( else), 8, 10),
|
|
Row.new(%q( @line_no += l.count("\n")), nil, 10),
|
|
Row.new(%q( next if l == "\n"), nil, 10),
|
|
Row.new(%q( @line.concat l), nil, 10),
|
|
Row.new(%q( if @code_block_open or @ltype or @continue or @indent > 0), nil, 12),
|
|
Row.new(%q( next), nil, 12),
|
|
Row.new(%q( end), 10, 10),
|
|
Row.new(%q( end), 8, 8),
|
|
Row.new(%q( if @line != "\n"), nil, 10),
|
|
Row.new(%q( @line.force_encoding(@io.encoding)), nil, 10),
|
|
Row.new(%q( yield @line, @exp_line_no), nil, 10),
|
|
Row.new(%q( end), 8, 8),
|
|
Row.new(%q( break if @io.eof?), nil, 8),
|
|
Row.new(%q( @line = ''), nil, 8),
|
|
Row.new(%q( @exp_line_no = @line_no), nil, 8),
|
|
Row.new(%q( ), nil, 8),
|
|
Row.new(%q( @indent = 0), nil, 8),
|
|
Row.new(%q( rescue TerminateLineInput), 6, 8),
|
|
Row.new(%q( initialize_input), nil, 8),
|
|
Row.new(%q( prompt), nil, 8),
|
|
Row.new(%q( end), 6, 6),
|
|
Row.new(%q( end), 4, 4),
|
|
Row.new(%q( end), 2, 2),
|
|
Row.new(%q(end), 0, 0),
|
|
]
|
|
|
|
lines = []
|
|
input_with_correct_indents.each do |row|
|
|
lines << row.content
|
|
assert_indenting(lines, row.current_line_spaces, false)
|
|
assert_indenting(lines, row.new_line_spaces, true)
|
|
end
|
|
end
|
|
|
|
def test_braces_on_their_own_line
|
|
input_with_correct_indents = [
|
|
Row.new(%q(if true), nil, 2),
|
|
Row.new(%q( [), nil, 4),
|
|
Row.new(%q( ]), 2, 2),
|
|
Row.new(%q(end), 0, 0),
|
|
]
|
|
|
|
lines = []
|
|
input_with_correct_indents.each do |row|
|
|
lines << row.content
|
|
assert_indenting(lines, row.current_line_spaces, false)
|
|
assert_indenting(lines, row.new_line_spaces, true)
|
|
end
|
|
end
|
|
|
|
def test_multiple_braces_in_a_line
|
|
input_with_correct_indents = [
|
|
Row.new(%q([[[), nil, 6),
|
|
Row.new(%q( ]), 4, 4),
|
|
Row.new(%q( ]), 2, 2),
|
|
Row.new(%q(]), 0, 0),
|
|
Row.new(%q([<<FOO]), nil, 0),
|
|
Row.new(%q(hello), nil, 0),
|
|
Row.new(%q(FOO), nil, 0),
|
|
]
|
|
|
|
lines = []
|
|
input_with_correct_indents.each do |row|
|
|
lines << row.content
|
|
assert_indenting(lines, row.current_line_spaces, false)
|
|
assert_indenting(lines, row.new_line_spaces, true)
|
|
end
|
|
end
|
|
|
|
def test_a_closed_brace_and_not_closed_brace_in_a_line
|
|
input_with_correct_indents = [
|
|
Row.new(%q(p() {), nil, 2),
|
|
Row.new(%q(}), 0, 0),
|
|
]
|
|
|
|
lines = []
|
|
input_with_correct_indents.each do |row|
|
|
lines << row.content
|
|
assert_indenting(lines, row.current_line_spaces, false)
|
|
assert_indenting(lines, row.new_line_spaces, true)
|
|
end
|
|
end
|
|
|
|
def test_endless_range_at_end_of_line
|
|
if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.6.0')
|
|
skip 'Endless range is available in 2.6.0 or later'
|
|
end
|
|
input_with_prompt = [
|
|
PromptRow.new('001:0: :> ', %q(a = 3..)),
|
|
PromptRow.new('002:0: :* ', %q()),
|
|
]
|
|
|
|
lines = input_with_prompt.map(&:content)
|
|
expected_prompt_list = input_with_prompt.map(&:prompt)
|
|
assert_dynamic_prompt(lines, expected_prompt_list)
|
|
end
|
|
|
|
def test_incomplete_coding_magic_comment
|
|
input_with_correct_indents = [
|
|
Row.new(%q(#coding:u), nil, 0),
|
|
]
|
|
|
|
lines = []
|
|
input_with_correct_indents.each do |row|
|
|
lines << row.content
|
|
assert_indenting(lines, row.current_line_spaces, false)
|
|
assert_indenting(lines, row.new_line_spaces, true)
|
|
end
|
|
end
|
|
|
|
def test_incomplete_encoding_magic_comment
|
|
input_with_correct_indents = [
|
|
Row.new(%q(#encoding:u), nil, 0),
|
|
]
|
|
|
|
lines = []
|
|
input_with_correct_indents.each do |row|
|
|
lines << row.content
|
|
assert_indenting(lines, row.current_line_spaces, false)
|
|
assert_indenting(lines, row.new_line_spaces, true)
|
|
end
|
|
end
|
|
|
|
def test_incomplete_emacs_coding_magic_comment
|
|
input_with_correct_indents = [
|
|
Row.new(%q(# -*- coding: u), nil, 0),
|
|
]
|
|
|
|
lines = []
|
|
input_with_correct_indents.each do |row|
|
|
lines << row.content
|
|
assert_indenting(lines, row.current_line_spaces, false)
|
|
assert_indenting(lines, row.new_line_spaces, true)
|
|
end
|
|
end
|
|
|
|
def test_incomplete_vim_coding_magic_comment
|
|
input_with_correct_indents = [
|
|
Row.new(%q(# vim:set fileencoding=u), nil, 0),
|
|
]
|
|
|
|
lines = []
|
|
input_with_correct_indents.each do |row|
|
|
lines << row.content
|
|
assert_indenting(lines, row.current_line_spaces, false)
|
|
assert_indenting(lines, row.new_line_spaces, true)
|
|
end
|
|
end
|
|
|
|
def test_mixed_rescue
|
|
input_with_correct_indents = [
|
|
Row.new(%q(def m), nil, 2),
|
|
Row.new(%q( begin), nil, 4),
|
|
Row.new(%q( begin), nil, 6),
|
|
Row.new(%q( x = a rescue 4), nil, 6),
|
|
Row.new(%q( y = [(a rescue 5)]), nil, 6),
|
|
Row.new(%q( [x, y]), nil, 6),
|
|
Row.new(%q( rescue => e), 4, 6),
|
|
Row.new(%q( raise e rescue 8), nil, 6),
|
|
Row.new(%q( end), 4, 4),
|
|
Row.new(%q( rescue), 2, 4),
|
|
Row.new(%q( raise rescue 11), nil, 4),
|
|
Row.new(%q( end), 2, 2),
|
|
Row.new(%q(rescue => e), 0, 2),
|
|
Row.new(%q( raise e rescue 14), nil, 2),
|
|
Row.new(%q(end), 0, 0),
|
|
]
|
|
|
|
lines = []
|
|
input_with_correct_indents.each do |row|
|
|
lines << row.content
|
|
assert_indenting(lines, row.current_line_spaces, false)
|
|
assert_indenting(lines, row.new_line_spaces, true)
|
|
end
|
|
end
|
|
|
|
def test_oneliner_method_definition
|
|
input_with_correct_indents = [
|
|
Row.new(%q(class A), nil, 2),
|
|
Row.new(%q( def foo0), nil, 4),
|
|
Row.new(%q( 3), nil, 4),
|
|
Row.new(%q( end), 2, 2),
|
|
Row.new(%q( def foo1()), nil, 4),
|
|
Row.new(%q( 3), nil, 4),
|
|
Row.new(%q( end), 2, 2),
|
|
Row.new(%q( def foo2(a, b)), nil, 4),
|
|
Row.new(%q( a + b), nil, 4),
|
|
Row.new(%q( end), 2, 2),
|
|
Row.new(%q( def foo3 a, b), nil, 4),
|
|
Row.new(%q( a + b), nil, 4),
|
|
Row.new(%q( end), 2, 2),
|
|
Row.new(%q( def bar0() = 3), nil, 2),
|
|
Row.new(%q( def bar1(a) = a), nil, 2),
|
|
Row.new(%q( def bar2(a, b) = a + b), nil, 2),
|
|
Row.new(%q( def bar3() = :s), nil, 2),
|
|
Row.new(%q( def bar4() = Time.now), nil, 2),
|
|
Row.new(%q(end), 0, 0),
|
|
]
|
|
|
|
lines = []
|
|
input_with_correct_indents.each do |row|
|
|
lines << row.content
|
|
assert_indenting(lines, row.current_line_spaces, false)
|
|
assert_indenting(lines, row.new_line_spaces, true)
|
|
end
|
|
end
|
|
|
|
def test_tlambda
|
|
input_with_correct_indents = [
|
|
Row.new(%q(if true), nil, 2, 1),
|
|
Row.new(%q( -> {), nil, 4, 2),
|
|
Row.new(%q( }), 2, 2, 1),
|
|
Row.new(%q(end), 0, 0, 0),
|
|
]
|
|
|
|
lines = []
|
|
input_with_correct_indents.each do |row|
|
|
lines << row.content
|
|
assert_indenting(lines, row.current_line_spaces, false)
|
|
assert_indenting(lines, row.new_line_spaces, true)
|
|
assert_nesting_level(lines, row.nesting_level)
|
|
end
|
|
end
|
|
|
|
def test_corresponding_syntax_to_keyword_do_in_class
|
|
input_with_correct_indents = [
|
|
Row.new(%q(class C), nil, 2, 1),
|
|
Row.new(%q( while method_name do), nil, 4, 2),
|
|
Row.new(%q( 3), nil, 4, 2),
|
|
Row.new(%q( end), 2, 2, 1),
|
|
Row.new(%q( foo do), nil, 4, 2),
|
|
Row.new(%q( 3), nil, 4, 2),
|
|
Row.new(%q( end), 2, 2, 1),
|
|
Row.new(%q(end), 0, 0, 0),
|
|
]
|
|
|
|
lines = []
|
|
input_with_correct_indents.each do |row|
|
|
lines << row.content
|
|
assert_indenting(lines, row.current_line_spaces, false)
|
|
assert_indenting(lines, row.new_line_spaces, true)
|
|
assert_nesting_level(lines, row.nesting_level)
|
|
end
|
|
end
|
|
|
|
def test_corresponding_syntax_to_keyword_do
|
|
input_with_correct_indents = [
|
|
Row.new(%q(while i > 0), nil, 2, 1),
|
|
Row.new(%q( 3), nil, 2, 1),
|
|
Row.new(%q(end), 0, 0, 0),
|
|
Row.new(%q(while true), nil, 2, 1),
|
|
Row.new(%q( 3), nil, 2, 1),
|
|
Row.new(%q(end), 0, 0, 0),
|
|
Row.new(%q(while ->{i > 0}.call), nil, 2, 1),
|
|
Row.new(%q( 3), nil, 2, 1),
|
|
Row.new(%q(end), 0, 0, 0),
|
|
Row.new(%q(while ->{true}.call), nil, 2, 1),
|
|
Row.new(%q( 3), nil, 2, 1),
|
|
Row.new(%q(end), 0, 0, 0),
|
|
Row.new(%q(while i > 0 do), nil, 2, 1),
|
|
Row.new(%q( 3), nil, 2, 1),
|
|
Row.new(%q(end), 0, 0, 0),
|
|
Row.new(%q(while true do), nil, 2, 1),
|
|
Row.new(%q( 3), nil, 2, 1),
|
|
Row.new(%q(end), 0, 0, 0),
|
|
Row.new(%q(while ->{i > 0}.call do), nil, 2, 1),
|
|
Row.new(%q( 3), nil, 2, 1),
|
|
Row.new(%q(end), 0, 0, 0),
|
|
Row.new(%q(while ->{true}.call do), nil, 2, 1),
|
|
Row.new(%q( 3), nil, 2, 1),
|
|
Row.new(%q(end), 0, 0, 0),
|
|
Row.new(%q(foo do), nil, 2, 1),
|
|
Row.new(%q( 3), nil, 2, 1),
|
|
Row.new(%q(end), 0, 0, 0),
|
|
Row.new(%q(foo true do), nil, 2, 1),
|
|
Row.new(%q( 3), nil, 2, 1),
|
|
Row.new(%q(end), 0, 0, 0),
|
|
Row.new(%q(foo ->{true} do), nil, 2, 1),
|
|
Row.new(%q( 3), nil, 2, 1),
|
|
Row.new(%q(end), 0, 0, 0),
|
|
Row.new(%q(foo ->{i > 0} do), nil, 2, 1),
|
|
Row.new(%q( 3), nil, 2, 1),
|
|
Row.new(%q(end), 0, 0, 0),
|
|
]
|
|
|
|
lines = []
|
|
input_with_correct_indents.each do |row|
|
|
lines << row.content
|
|
assert_indenting(lines, row.current_line_spaces, false)
|
|
assert_indenting(lines, row.new_line_spaces, true)
|
|
assert_nesting_level(lines, row.nesting_level)
|
|
end
|
|
end
|
|
|
|
def test_corresponding_syntax_to_keyword_for
|
|
input_with_correct_indents = [
|
|
Row.new(%q(for i in [1]), nil, 2, 1),
|
|
Row.new(%q( puts i), nil, 2, 1),
|
|
Row.new(%q(end), 0, 0, 0),
|
|
]
|
|
|
|
lines = []
|
|
input_with_correct_indents.each do |row|
|
|
lines << row.content
|
|
assert_indenting(lines, row.current_line_spaces, false)
|
|
assert_indenting(lines, row.new_line_spaces, true)
|
|
assert_nesting_level(lines, row.nesting_level)
|
|
end
|
|
end
|
|
|
|
def test_corresponding_syntax_to_keyword_for_with_do
|
|
input_with_correct_indents = [
|
|
Row.new(%q(for i in [1] do), nil, 2, 1),
|
|
Row.new(%q( puts i), nil, 2, 1),
|
|
Row.new(%q(end), 0, 0, 0),
|
|
]
|
|
|
|
lines = []
|
|
input_with_correct_indents.each do |row|
|
|
lines << row.content
|
|
assert_indenting(lines, row.current_line_spaces, false)
|
|
assert_indenting(lines, row.new_line_spaces, true)
|
|
assert_nesting_level(lines, row.nesting_level)
|
|
end
|
|
end
|
|
|
|
def test_bracket_corresponding_to_times
|
|
input_with_correct_indents = [
|
|
Row.new(%q(3.times { |i|), nil, 2, 1),
|
|
Row.new(%q( puts i), nil, 2, 1),
|
|
Row.new(%q(}), 0, 0, 0),
|
|
]
|
|
|
|
lines = []
|
|
input_with_correct_indents.each do |row|
|
|
lines << row.content
|
|
assert_indenting(lines, row.current_line_spaces, false)
|
|
assert_indenting(lines, row.new_line_spaces, true)
|
|
assert_nesting_level(lines, row.nesting_level)
|
|
end
|
|
end
|
|
|
|
def test_do_corresponding_to_times
|
|
input_with_correct_indents = [
|
|
Row.new(%q(3.times do |i|), nil, 2, 1),
|
|
#Row.new(%q( puts i), nil, 2, 1),
|
|
#Row.new(%q(end), 0, 0, 0),
|
|
]
|
|
|
|
lines = []
|
|
input_with_correct_indents.each do |row|
|
|
lines << row.content
|
|
assert_indenting(lines, row.current_line_spaces, false)
|
|
assert_indenting(lines, row.new_line_spaces, true)
|
|
assert_nesting_level(lines, row.nesting_level)
|
|
end
|
|
end
|
|
|
|
def test_bracket_corresponding_to_loop
|
|
input_with_correct_indents = [
|
|
Row.new(%q(loop {), nil, 2, 1),
|
|
Row.new(%q( 3), nil, 2, 1),
|
|
Row.new(%q(}), 0, 0, 0),
|
|
]
|
|
|
|
lines = []
|
|
input_with_correct_indents.each do |row|
|
|
lines << row.content
|
|
assert_indenting(lines, row.current_line_spaces, false)
|
|
assert_indenting(lines, row.new_line_spaces, true)
|
|
assert_nesting_level(lines, row.nesting_level)
|
|
end
|
|
end
|
|
|
|
def test_do_corresponding_to_loop
|
|
input_with_correct_indents = [
|
|
Row.new(%q(loop do), nil, 2, 1),
|
|
Row.new(%q( 3), nil, 2, 1),
|
|
Row.new(%q(end), 0, 0, 0),
|
|
]
|
|
|
|
lines = []
|
|
input_with_correct_indents.each do |row|
|
|
lines << row.content
|
|
assert_indenting(lines, row.current_line_spaces, false)
|
|
assert_indenting(lines, row.new_line_spaces, true)
|
|
assert_nesting_level(lines, row.nesting_level)
|
|
end
|
|
end
|
|
|
|
def test_heredoc_with_indent
|
|
input_with_correct_indents = [
|
|
Row.new(%q(<<~Q), nil, 0, 0),
|
|
Row.new(%q({), nil, 0, 0),
|
|
Row.new(%q( #), nil, 0, 0),
|
|
Row.new(%q(}), nil, 0, 0),
|
|
]
|
|
|
|
lines = []
|
|
input_with_correct_indents.each do |row|
|
|
lines << row.content
|
|
assert_indenting(lines, row.current_line_spaces, false)
|
|
assert_indenting(lines, row.new_line_spaces, true)
|
|
assert_nesting_level(lines, row.nesting_level)
|
|
end
|
|
end
|
|
|
|
def test_oneliner_def_in_multiple_lines
|
|
input_with_correct_indents = [
|
|
Row.new(%q(def a()=[), nil, 4, 2),
|
|
Row.new(%q( 1,), nil, 4, 1),
|
|
Row.new(%q(].), 0, 0, 0),
|
|
Row.new(%q(to_s), nil, 0, 0),
|
|
]
|
|
|
|
lines = []
|
|
input_with_correct_indents.each do |row|
|
|
lines << row.content
|
|
assert_indenting(lines, row.current_line_spaces, false)
|
|
assert_indenting(lines, row.new_line_spaces, true)
|
|
assert_nesting_level(lines, row.nesting_level)
|
|
end
|
|
end
|
|
|
|
def test_broken_heredoc
|
|
if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.7.0')
|
|
skip 'This test needs Ripper::Lexer#scan to take broken tokens'
|
|
end
|
|
input_with_correct_indents = [
|
|
Row.new(%q(def foo), nil, 2, 1),
|
|
Row.new(%q( <<~Q), nil, 2, 1),
|
|
Row.new(%q( Qend), nil, 2, 1),
|
|
]
|
|
|
|
lines = []
|
|
input_with_correct_indents.each do |row|
|
|
lines << row.content
|
|
assert_indenting(lines, row.current_line_spaces, false)
|
|
assert_indenting(lines, row.new_line_spaces, true)
|
|
assert_nesting_level(lines, row.nesting_level)
|
|
end
|
|
end
|
|
|
|
PromptRow = Struct.new(:prompt, :content)
|
|
|
|
class MockIO_DynamicPrompt
|
|
def initialize(params, &assertion)
|
|
@params = params
|
|
@assertion = assertion
|
|
end
|
|
|
|
def dynamic_prompt(&block)
|
|
result = block.call(@params)
|
|
@assertion.call(result)
|
|
end
|
|
end
|
|
|
|
def assert_dynamic_prompt(lines, expected_prompt_list)
|
|
skip if RUBY_ENGINE == 'truffleruby'
|
|
ruby_lex = RubyLex.new()
|
|
io = MockIO_DynamicPrompt.new(lines) do |prompt_list|
|
|
error_message = <<~EOM
|
|
Expected dynamic prompt:
|
|
#{expected_prompt_list.join("\n")}
|
|
|
|
Actual dynamic prompt:
|
|
#{prompt_list.join("\n")}
|
|
EOM
|
|
assert_equal(expected_prompt_list, prompt_list, error_message)
|
|
end
|
|
ruby_lex.set_prompt do |ltype, indent, continue, line_no|
|
|
'%03d:%01d:%1s:%s ' % [line_no, indent, ltype, continue ? '*' : '>']
|
|
end
|
|
ruby_lex.set_input(io)
|
|
end
|
|
|
|
def test_dyanmic_prompt
|
|
input_with_prompt = [
|
|
PromptRow.new('001:1: :* ', %q(def hoge)),
|
|
PromptRow.new('002:1: :* ', %q( 3)),
|
|
PromptRow.new('003:0: :> ', %q(end)),
|
|
]
|
|
|
|
lines = input_with_prompt.map(&:content)
|
|
expected_prompt_list = input_with_prompt.map(&:prompt)
|
|
assert_dynamic_prompt(lines, expected_prompt_list)
|
|
end
|
|
|
|
def test_dyanmic_prompt_with_blank_line
|
|
input_with_prompt = [
|
|
PromptRow.new('001:0:]:* ', %q(%w[)),
|
|
PromptRow.new('002:0:]:* ', %q()),
|
|
PromptRow.new('003:0: :> ', %q(])),
|
|
]
|
|
|
|
lines = input_with_prompt.map(&:content)
|
|
expected_prompt_list = input_with_prompt.map(&:prompt)
|
|
assert_dynamic_prompt(lines, expected_prompt_list)
|
|
end
|
|
|
|
def test_broken_percent_literal
|
|
if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.7.0')
|
|
skip 'This test needs Ripper::Lexer#scan to take broken tokens'
|
|
end
|
|
|
|
tokens = RubyLex.ripper_lex_without_warning('%wwww')
|
|
pos_to_index = {}
|
|
tokens.each_with_index { |t, i|
|
|
assert_nil(pos_to_index[t[0]], "There is already another token in the position of #{t.inspect}.")
|
|
pos_to_index[t[0]] = i
|
|
}
|
|
end
|
|
|
|
def test_broken_percent_literal_in_method
|
|
if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.7.0')
|
|
skip 'This test needs Ripper::Lexer#scan to take broken tokens'
|
|
end
|
|
|
|
tokens = RubyLex.ripper_lex_without_warning(<<~EOC.chomp)
|
|
def foo
|
|
%wwww
|
|
end
|
|
EOC
|
|
pos_to_index = {}
|
|
tokens.each_with_index { |t, i|
|
|
assert_nil(pos_to_index[t[0]], "There is already another token in the position of #{t.inspect}.")
|
|
pos_to_index[t[0]] = i
|
|
}
|
|
end
|
|
end
|
|
end
|