Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 6 additions & 10 deletions lib/irb/ruby-lex.rb
Original file line number Diff line number Diff line change
Expand Up @@ -184,8 +184,8 @@ def self.ripper_lex_without_warning(code, context: nil)

def prompt(opens, continue, line_num_offset)
ltype = ltype_from_open_tokens(opens)
_indent_level, nesting_level = calc_nesting_depth(opens)
@prompt&.call(ltype, nesting_level, opens.any? || continue, @line_no + line_num_offset)
indent_level = calc_indent_level(opens)
@prompt&.call(ltype, indent_level, opens.any? || continue, @line_no + line_num_offset)
end

def check_code_state(code)
Expand Down Expand Up @@ -356,10 +356,8 @@ def check_code_block(code, tokens)
false
end

# Calculates [indent_level, nesting_level]. nesting_level is used in prompt string.
def calc_nesting_depth(opens)
def calc_indent_level(opens)
indent_level = 0
nesting_level = 0
opens.each_with_index do |t, index|
case t.event
when :on_heredoc_beg
Expand All @@ -377,11 +375,10 @@ def calc_nesting_depth(opens)
when :on_embdoc_beg
indent_level = 0
else
nesting_level += 1
indent_level += 1
end
end
[indent_level, nesting_level]
indent_level
end

FREE_INDENT_TOKENS = %i[on_tstring_beg on_backtick on_regexp_beg on_symbeg]
Expand All @@ -403,8 +400,7 @@ def process_indent_level(tokens, lines, line_index, is_newline)

# To correctly indent line like `end.map do`, we use shortest open tokens on each line for indent calculation.
# Shortest open tokens can be calculated by `opens.take(min_depth)`
indent_level, _nesting_level = calc_nesting_depth(prev_opens.take(min_depth))
indent = 2 * indent_level
indent = 2 * calc_indent_level(prev_opens.take(min_depth))

preserve_indent = lines[line_index - (is_newline ? 1 : 0)][/^ */].size

Expand Down Expand Up @@ -442,7 +438,7 @@ def process_indent_level(tokens, lines, line_index, is_newline)
end
else
# Heredoc close
prev_line_indent_level, _prev_line_nesting_level = calc_nesting_depth(prev_opens)
prev_line_indent_level = calc_indent_level(prev_opens)
tok.match?(/^<<[~-]/) ? 2 * (prev_line_indent_level - 1) : 0
end
else
Expand Down
98 changes: 49 additions & 49 deletions test/irb/test_ruby_lex.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

module TestIRB
class RubyLexTest < TestCase
Row = Struct.new(:content, :current_line_spaces, :new_line_spaces, :nesting_level)
Row = Struct.new(:content, :current_line_spaces, :new_line_spaces, :indent_level)

class MockIO_AutoIndent
attr_reader :calculated_indent
Expand Down Expand Up @@ -81,14 +81,14 @@ def assert_row_indenting(lines, row)
assert_equal(row.new_line_spaces, actual_next_line_spaces, error_message)
end

def assert_nesting_level(lines, expected, local_variables: [])
nesting_level, _code_block_open = check_state(lines, local_variables: local_variables)
error_message = "Calculated the wrong number of nesting level for:\n #{lines.join("\n")}"
assert_equal(expected, nesting_level, error_message)
def assert_indent_level(lines, expected, local_variables: [])
indent_level, _code_block_open = check_state(lines, local_variables: local_variables)
error_message = "Calculated the wrong number of indent level for:\n #{lines.join("\n")}"
assert_equal(expected, indent_level, error_message)
end

def assert_code_block_open(lines, expected, local_variables: [])
_nesting_level, code_block_open = check_state(lines, local_variables: local_variables)
_indent_level, code_block_open = check_state(lines, local_variables: local_variables)
error_message = "Wrong result of code_block_open for:\n #{lines.join("\n")}"
assert_equal(expected, code_block_open, error_message)
end
Expand All @@ -98,9 +98,9 @@ def check_state(lines, local_variables: [])
tokens = RubyLex.ripper_lex_without_warning(lines.join("\n"), context: context)
opens = IRB::NestingParser.open_tokens(tokens)
ruby_lex = RubyLex.new(context)
_indent, nesting_level = ruby_lex.calc_nesting_depth(opens)
indent_level = ruby_lex.calc_indent_level(opens)
code_block_open = !opens.empty? || ruby_lex.process_continue(tokens)
[nesting_level, code_block_open]
[indent_level, code_block_open]
end

def test_interpolate_token_with_heredoc_and_unclosed_embexpr
Expand Down Expand Up @@ -266,14 +266,14 @@ def test_heredoc_with_embexpr

def test_heredoc_prompt_with_quotes
input_with_prompt = [
PromptRow.new("001:0:':* ", %q(<<~'A')),
PromptRow.new("002:0:':* ", %q(#{foobar})),
PromptRow.new("001:1:':* ", %q(<<~'A')),
PromptRow.new("002:1:':* ", %q(#{foobar})),
PromptRow.new("003:0: :> ", %q(A)),
PromptRow.new("004:0:`:* ", %q(<<~`A`)),
PromptRow.new("005:0:`:* ", %q(whoami)),
PromptRow.new("004:1:`:* ", %q(<<~`A`)),
PromptRow.new("005:1:`:* ", %q(whoami)),
PromptRow.new("006:0: :> ", %q(A)),
PromptRow.new('007:0:":* ', %q(<<~"A")),
PromptRow.new('008:0:":* ', %q(foobar)),
PromptRow.new('007:1:":* ', %q(<<~"A")),
PromptRow.new('008:1:":* ', %q(foobar)),
PromptRow.new('009:0: :> ', %q(A)),
]

Expand Down Expand Up @@ -411,7 +411,7 @@ def test_tlambda
input_with_correct_indents.each do |row|
lines << row.content
assert_row_indenting(lines, row)
assert_nesting_level(lines, row.nesting_level)
assert_indent_level(lines, row.indent_level)
end
end

Expand All @@ -431,7 +431,7 @@ def test_corresponding_syntax_to_keyword_do_in_class
input_with_correct_indents.each do |row|
lines << row.content
assert_row_indenting(lines, row)
assert_nesting_level(lines, row.nesting_level)
assert_indent_level(lines, row.indent_level)
end
end

Expand Down Expand Up @@ -479,7 +479,7 @@ def test_corresponding_syntax_to_keyword_do
input_with_correct_indents.each do |row|
lines << row.content
assert_row_indenting(lines, row)
assert_nesting_level(lines, row.nesting_level)
assert_indent_level(lines, row.indent_level)
end
end

Expand All @@ -494,7 +494,7 @@ def test_corresponding_syntax_to_keyword_for
input_with_correct_indents.each do |row|
lines << row.content
assert_row_indenting(lines, row)
assert_nesting_level(lines, row.nesting_level)
assert_indent_level(lines, row.indent_level)
end
end

Expand All @@ -509,7 +509,7 @@ def test_corresponding_syntax_to_keyword_for_with_do
input_with_correct_indents.each do |row|
lines << row.content
assert_row_indenting(lines, row)
assert_nesting_level(lines, row.nesting_level)
assert_indent_level(lines, row.indent_level)
end
end

Expand All @@ -525,7 +525,7 @@ def test_typing_incomplete_include_interpreted_as_keyword_in
input_with_correct_indents.each do |row|
lines << row.content
assert_row_indenting(lines, row)
assert_nesting_level(lines, row.nesting_level)
assert_indent_level(lines, row.indent_level)
end
end

Expand All @@ -540,7 +540,7 @@ def test_bracket_corresponding_to_times
input_with_correct_indents.each do |row|
lines << row.content
assert_row_indenting(lines, row)
assert_nesting_level(lines, row.nesting_level)
assert_indent_level(lines, row.indent_level)
end
end

Expand All @@ -555,7 +555,7 @@ def test_do_corresponding_to_times
input_with_correct_indents.each do |row|
lines << row.content
assert_row_indenting(lines, row)
assert_nesting_level(lines, row.nesting_level)
assert_indent_level(lines, row.indent_level)
end
end

Expand All @@ -570,7 +570,7 @@ def test_bracket_corresponding_to_loop
input_with_correct_indents.each do |row|
lines << row.content
assert_row_indenting(lines, row)
assert_nesting_level(lines, row.nesting_level)
assert_indent_level(lines, row.indent_level)
end
end

Expand All @@ -585,16 +585,16 @@ def test_do_corresponding_to_loop
input_with_correct_indents.each do |row|
lines << row.content
assert_row_indenting(lines, row)
assert_nesting_level(lines, row.nesting_level)
assert_indent_level(lines, row.indent_level)
end
end

def test_local_variables_dependent_code
pend if RUBY_ENGINE == 'truffleruby'
lines = ["a /1#/ do", "2"]
assert_nesting_level(lines, 1)
assert_indent_level(lines, 1)
assert_code_block_open(lines, true)
assert_nesting_level(lines, 0, local_variables: ['a'])
assert_indent_level(lines, 0, local_variables: ['a'])
assert_code_block_open(lines, false, local_variables: ['a'])
end

Expand All @@ -606,9 +606,9 @@ def test_embdoc_indent
Row.new(%q(=end), 0, 0, 0),
Row.new(%q(if 1), 0, 2, 1),
Row.new(%q( 2), 2, 2, 1),
Row.new(%q(=begin), 0, 0, 1),
Row.new(%q(a), 0, 0, 1),
Row.new(%q( b), 1, 1, 1),
Row.new(%q(=begin), 0, 0, 0),
Row.new(%q(a), 0, 0, 0),
Row.new(%q( b), 1, 1, 0),
Row.new(%q(=end), 0, 2, 1),
Row.new(%q( 3), 2, 2, 1),
Row.new(%q(end), 0, 0, 0),
Expand All @@ -617,7 +617,7 @@ def test_embdoc_indent
input_with_correct_indents.each do |row|
lines << row.content
assert_row_indenting(lines, row)
assert_nesting_level(lines, row.nesting_level)
assert_indent_level(lines, row.indent_level)
end
end

Expand All @@ -626,22 +626,22 @@ def test_heredoc_with_indent
pend 'This test needs Ripper::Lexer#scan to take broken tokens'
end
input_with_correct_indents = [
Row.new(%q(<<~Q+<<~R), 0, 2, 0),
Row.new(%q(a), 2, 2, 0),
Row.new(%q(a), 2, 2, 0),
Row.new(%q( b), 2, 2, 0),
Row.new(%q( b), 2, 2, 0),
Row.new(%q( Q), 0, 2, 0),
Row.new(%q( c), 4, 4, 0),
Row.new(%q( c), 4, 4, 0),
Row.new(%q(<<~Q+<<~R), 0, 2, 1),
Row.new(%q(a), 2, 2, 1),
Row.new(%q(a), 2, 2, 1),
Row.new(%q( b), 2, 2, 1),
Row.new(%q( b), 2, 2, 1),
Row.new(%q( Q), 0, 2, 1),
Row.new(%q( c), 4, 4, 1),
Row.new(%q( c), 4, 4, 1),
Row.new(%q( R), 0, 0, 0),
]

lines = []
input_with_correct_indents.each do |row|
lines << row.content
assert_row_indenting(lines, row)
assert_nesting_level(lines, row.nesting_level)
assert_indent_level(lines, row.indent_level)
end
end

Expand All @@ -657,30 +657,30 @@ def test_oneliner_def_in_multiple_lines
input_with_correct_indents.each do |row|
lines << row.content
assert_row_indenting(lines, row)
assert_nesting_level(lines, row.nesting_level)
assert_indent_level(lines, row.indent_level)
end
end

def test_broken_heredoc
input_with_correct_indents = [
Row.new(%q(def foo), 0, 2, 1),
Row.new(%q( <<~Q), 2, 4, 1),
Row.new(%q( Qend), 4, 4, 1),
Row.new(%q( <<~Q), 2, 4, 2),
Row.new(%q( Qend), 4, 4, 2),
]
lines = []
input_with_correct_indents.each do |row|
lines << row.content
assert_row_indenting(lines, row)
assert_nesting_level(lines, row.nesting_level)
assert_indent_level(lines, row.indent_level)
end
end

def test_heredoc_keep_indent_spaces
(1..4).each do |indent|
row = Row.new(' ' * indent, nil, [4, indent].max, 1)
row = Row.new(' ' * indent, nil, [4, indent].max, 2)
lines = ['def foo', ' <<~Q', row.content]
assert_row_indenting(lines, row)
assert_nesting_level(lines, row.nesting_level)
assert_indent_level(lines, row.indent_level)
end
end

Expand Down Expand Up @@ -816,7 +816,7 @@ def test_unterminated_heredoc_string_literal
end
end

def test_nesting_level_with_heredoc_and_embdoc
def test_indent_level_with_heredoc_and_embdoc
reference_code = <<~EOC.chomp
if true
hello
Expand All @@ -838,9 +838,9 @@ def test_nesting_level_with_heredoc_and_embdoc
)
EOC
expected = 1
assert_nesting_level(reference_code.lines, expected)
assert_nesting_level(code_with_heredoc.lines, expected)
assert_nesting_level(code_with_embdoc.lines, expected)
assert_indent_level(reference_code.lines, expected)
assert_indent_level(code_with_heredoc.lines, expected)
assert_indent_level(code_with_embdoc.lines, expected)
end

private
Expand Down