diff --git a/CHANGELOG.md b/CHANGELOG.md index a0730d8..d44600e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ ## HEAD (unreleased) +- Do not count trailing if/unless as a kewyword (https://github.com/zombocom/dead_end/pull/44) + ## 1.0.2 - Fix bug where empty lines were interpreted to have a zero indentation (https://github.com/zombocom/dead_end/pull/39) diff --git a/lib/dead_end/code_line.rb b/lib/dead_end/code_line.rb index f4463fd..24bc129 100644 --- a/lib/dead_end/code_line.rb +++ b/lib/dead_end/code_line.rb @@ -51,25 +51,29 @@ def initialize(line: , index:) end private def lex_detect! - lex = LexAll.new(source: line) + lex_array = LexAll.new(source: line) kw_count = 0 end_count = 0 - lex.each do |lex| + lex_array.each_with_index do |lex, index| next unless lex.type == :on_kw case lex.token - when 'def', 'case', 'for', 'begin', 'class', 'module', 'if', 'unless', 'while', 'until' , 'do' + when 'if', 'unless', 'while', 'until' + # Only count if/unless when it's not a "trailing" if/unless + # https://github.com/ruby/ruby/blob/06b44f819eb7b5ede1ff69cecb25682b56a1d60c/lib/irb/ruby-lex.rb#L374-L375 + kw_count += 1 if !lex.expr_label? + when 'def', 'case', 'for', 'begin', 'class', 'module', 'do' kw_count += 1 when 'end' end_count += 1 end end - @is_comment = lex.detect {|lex| lex.type != :on_sp}&.type == :on_comment + @is_comment = lex_array.detect {|lex| lex.type != :on_sp}&.type == :on_comment return if @is_comment @is_kw = (kw_count - end_count) > 0 @is_end = (end_count - kw_count) > 0 - @is_trailing_slash = lex.last.token == TRAILING_SLASH + @is_trailing_slash = lex_array.last.token == TRAILING_SLASH end alias :original :original_line diff --git a/lib/dead_end/lex_all.rb b/lib/dead_end/lex_all.rb index 5a6a128..e7cba5a 100644 --- a/lib/dead_end/lex_all.rb +++ b/lib/dead_end/lex_all.rb @@ -21,7 +21,7 @@ def initialize(source: ) lineno = @lex.last&.first&.first + 1 end - @lex.map! {|(line, _), type, token| LexValue.new(line, _, type, token) } + @lex.map! {|(line, _), type, token, state| LexValue.new(line, _, type, token, state) } end def each @@ -47,11 +47,17 @@ def last # lex.type # => :on_indent # lex.token # => "describe" class LexValue - attr_reader :line, :type, :token - def initialize(line, _, type, token) + attr_reader :line, :type, :token, :state + + def initialize(line, _, type, token, state) @line = line @type = type @token = token + @state = state + end + + def expr_label? + state.allbits?(Ripper::EXPR_LABEL) end end end diff --git a/spec/unit/capture_code_context_spec.rb b/spec/unit/capture_code_context_spec.rb index 30160b3..091e1b3 100644 --- a/spec/unit/capture_code_context_spec.rb +++ b/spec/unit/capture_code_context_spec.rb @@ -4,6 +4,52 @@ module DeadEnd RSpec.describe CaptureCodeContext do + it "doesn't capture trailing if or unless" do + source = <<~'EOM' + def call + + # try do + + @options = CommandLineParser.new.parse + + options.requires.each { |r| require!(r) } + load_global_config_if_exists + options.loads.each { |file| load(file) } + + @user_source_code = ARGV.join(' ') + @user_source_code = 'self' if @user_source_code == '' + + @callable = create_callable + + init_rexe_context + init_parser_and_formatters + + # This is where the user's source code will be executed; the action will in turn call `execute`. + lookup_action(options.input_mode).call unless options.noop + + output_log_entry + end # one + end # two + EOM + + search = CodeSearch.new(source) + search.call + + display = CaptureCodeContext.new( + blocks: search.invalid_blocks, + code_lines: search.code_lines + ) + lines = display.call + + lines = lines.sort.map(&:original) + + expect(lines.join).to eq(<<~EOM) + def call + end # one + end # two + EOM + end + it "shows ends of captured block" do lines = fixtures_dir.join("rexe.rb.txt").read.lines lines.delete_at(148 - 1) diff --git a/spec/unit/code_line_spec.rb b/spec/unit/code_line_spec.rb index 92e7bd5..ff7d24c 100644 --- a/spec/unit/code_line_spec.rb +++ b/spec/unit/code_line_spec.rb @@ -4,6 +4,26 @@ module DeadEnd RSpec.describe CodeLine do + it "trailing if" do + code_lines = code_line_array(<<~'EOM') + puts "lol" if foo + if foo + end + EOM + + expect(code_lines.map(&:is_kw?)).to eq([false, true, false]) + end + + it "trailing unless" do + code_lines = code_line_array(<<~'EOM') + puts "lol" unless foo + unless foo + end + EOM + + expect(code_lines.map(&:is_kw?)).to eq([false, true, false]) + end + it "trailing slash" do code_lines = code_line_array(<<~'EOM') it "trailing s" \ diff --git a/spec/unit/lex_all_spec.rb b/spec/unit/lex_all_spec.rb index d1f872f..fd40320 100644 --- a/spec/unit/lex_all_spec.rb +++ b/spec/unit/lex_all_spec.rb @@ -17,8 +17,8 @@ module DeadEnd end # 9 EOM - raw_lex = Ripper.lex(source) - expect(raw_lex.to_s).to_not include("dog") + # raw_lex = Ripper.lex(source) + # expect(raw_lex.to_s).to_not include("dog") lex = LexAll.new(source: source) expect(lex.map(&:token).to_s).to include("dog")