From 2113b06a1587b9bf60b6a09ada1631532d1902e9 Mon Sep 17 00:00:00 2001 From: schneems Date: Sat, 22 Jan 2022 12:07:41 -0600 Subject: [PATCH 1/2] Clean up CodeSearch spec - Make all heredocs literal - Remove unused test --- spec/unit/code_search_spec.rb | 122 ++++++++++++++++++---------------- 1 file changed, 65 insertions(+), 57 deletions(-) diff --git a/spec/unit/code_search_spec.rb b/spec/unit/code_search_spec.rb index 9f98839..472b28c 100644 --- a/spec/unit/code_search_spec.rb +++ b/spec/unit/code_search_spec.rb @@ -4,6 +4,37 @@ module DeadEnd RSpec.describe CodeSearch do + it "regression test ambiguous end" do + source = <<~'EOM' + def call # 0 + print "lol" # 1 + end # one # 2 + end # two # 3 + EOM + + search = CodeSearch.new(source) + search.call + + expect(search.invalid_blocks.join).to eq(<<~'EOM') + end # two # 3 + EOM + end + + it "regression dog test" do + source = <<~'EOM' + class Dog + def bark + puts "woof" + end + EOM + search = CodeSearch.new(source) + search.call + + expect(search.invalid_blocks.join).to eq(<<~'EOM') + class Dog + EOM + end + it "handles mismatched |" do source = <<~EOM class Blerg @@ -18,7 +49,7 @@ class Foo search = CodeSearch.new(source) search.call - expect(search.invalid_blocks.join).to eq(<<~EOM.indent(2)) + expect(search.invalid_blocks.join).to eq(<<~'EOM'.indent(2)) Foo.call do |a end # one EOM @@ -37,7 +68,7 @@ class Foo search = CodeSearch.new(source) search.call - expect(search.invalid_blocks.join).to eq(<<~EOM.indent(2)) + expect(search.invalid_blocks.join).to eq(<<~'EOM'.indent(2)) Foo.call do { EOM end @@ -71,7 +102,7 @@ class Foo end it "handles no spaces between blocks" do - source = <<~EOM + source = <<~'EOM' context "foo bar" do it "bars the foo" do travel_to DateTime.new(2020, 10, 1, 10, 0, 0) do @@ -91,7 +122,7 @@ class Foo it "records debugging steps to a directory" do Dir.mktmpdir do |dir| dir = Pathname(dir) - search = CodeSearch.new(<<~EOM, record_dir: dir) + search = CodeSearch.new(<<~'EOM', record_dir: dir) class OH def hello def hai @@ -112,7 +143,7 @@ def hai end it "def with missing end" do - search = CodeSearch.new(<<~EOM) + search = CodeSearch.new(<<~'EOM') class OH def hello @@ -125,7 +156,7 @@ def hai expect(search.invalid_blocks.join.strip).to eq("def hello") - search = CodeSearch.new(<<~EOM) + search = CodeSearch.new(<<~'EOM') class OH def hello @@ -137,7 +168,7 @@ def hai expect(search.invalid_blocks.join.strip).to eq("def hello") - search = CodeSearch.new(<<~EOM) + search = CodeSearch.new(<<~'EOM') class OH def hello def hai @@ -146,7 +177,7 @@ def hai EOM search.call - expect(search.invalid_blocks.join).to eq(<<~EOM.indent(2)) + expect(search.invalid_blocks.join).to eq(<<~'EOM'.indent(2)) def hello EOM end @@ -163,13 +194,13 @@ def hello highlight_lines: search.invalid_blocks.flat_map(&:lines) ).call - expect(document).to include(<<~EOM) + expect(document).to include(<<~'EOM') ❯ 36 def filename EOM end it "Format Code blocks real world example" do - search = CodeSearch.new(<<~EOM) + search = CodeSearch.new(<<~'EOM') require 'rails_helper' RSpec.describe AclassNameHere, type: :worker do @@ -210,7 +241,7 @@ def hello highlight_lines: search.invalid_blocks.flat_map(&:lines) ).call - expect(document).to include(<<~EOM) + expect(document).to include(<<~'EOM') 1 require 'rails_helper' 2 3 RSpec.describe AclassNameHere, type: :worker do @@ -225,32 +256,9 @@ def hello # For code that's not perfectly formatted, we ideally want to do our best # These examples represent the results that exist today, but I would like to improve upon them describe "needs improvement" do - describe "missing describe/do line" do - it "blerg" do - # code_lines = code_line_array fixtures_dir.join("this_project_extra_def.rb.txt").read - # block = CodeBlock.new( - # lines: code_lines[31], - # code_lines: code_lines - # ) - # expect(block.to_s).to eq(<<~EOM.indent(8)) - # \#{code_with_filename} - # EOM - - # puts block.before_line.to_s.inspect - # puts block.before_line.to_s.split(/\S/).inspect - # puts block.before_line.indent - - # puts block.after_line.to_s.inspect - # puts block.after_line.to_s.split(/\S/).inspect - # puts block.after_line.indent - - # puts block.expand_until_next_boundry - end - end - describe "mis-matched-indentation" do it "extra space before end" do - search = CodeSearch.new(<<~EOM) + search = CodeSearch.new(<<~'EOM') Foo.call def foo puts "lol" @@ -260,14 +268,14 @@ def foo EOM search.call - expect(search.invalid_blocks.join).to eq(<<~EOM) + expect(search.invalid_blocks.join).to eq(<<~'EOM') Foo.call end # two EOM end it "stacked ends 2" do - search = CodeSearch.new(<<~EOM) + search = CodeSearch.new(<<~'EOM') def cat blerg end @@ -281,7 +289,7 @@ def dog EOM search.call - expect(search.invalid_blocks.join).to eq(<<~EOM) + expect(search.invalid_blocks.join).to eq(<<~'EOM') Foo.call do end # one end # two @@ -290,7 +298,7 @@ def dog end it "stacked ends " do - search = CodeSearch.new(<<~EOM) + search = CodeSearch.new(<<~'EOM') Foo.call def foo puts "lol" @@ -300,14 +308,14 @@ def foo EOM search.call - expect(search.invalid_blocks.join).to eq(<<~EOM) + expect(search.invalid_blocks.join).to eq(<<~'EOM') Foo.call end EOM end it "missing space before end" do - search = CodeSearch.new(<<~EOM) + search = CodeSearch.new(<<~'EOM') Foo.call def foo @@ -319,7 +327,7 @@ def foo search.call # expand-1 and expand-2 seem to be broken? - expect(search.invalid_blocks.join).to eq(<<~EOM) + expect(search.invalid_blocks.join).to eq(<<~'EOM') Foo.call end EOM @@ -328,7 +336,7 @@ def foo end it "returns syntax error in outer block without inner block" do - search = CodeSearch.new(<<~EOM) + search = CodeSearch.new(<<~'EOM') Foo.call def foo puts "lol" @@ -338,27 +346,27 @@ def foo EOM search.call - expect(search.invalid_blocks.join).to eq(<<~EOM) + expect(search.invalid_blocks.join).to eq(<<~'EOM') Foo.call end # two EOM end it "doesn't just return an empty `end`" do - search = CodeSearch.new(<<~EOM) + search = CodeSearch.new(<<~'EOM') Foo.call end EOM search.call - expect(search.invalid_blocks.join).to eq(<<~EOM) + expect(search.invalid_blocks.join).to eq(<<~'EOM') Foo.call end EOM end it "finds multiple syntax errors" do - search = CodeSearch.new(<<~EOM) + search = CodeSearch.new(<<~'EOM') describe "hi" do Foo.call end @@ -371,7 +379,7 @@ def foo EOM search.call - expect(search.invalid_blocks.join).to eq(<<~EOM.indent(2)) + expect(search.invalid_blocks.join).to eq(<<~'EOM'.indent(2)) Foo.call end Bar.call @@ -380,47 +388,47 @@ def foo end it "finds a typo def" do - search = CodeSearch.new(<<~EOM) + search = CodeSearch.new(<<~'EOM') defzfoo puts "lol" end EOM search.call - expect(search.invalid_blocks.join).to eq(<<~EOM) + expect(search.invalid_blocks.join).to eq(<<~'EOM') defzfoo end EOM end it "finds a mis-matched def" do - search = CodeSearch.new(<<~EOM) + search = CodeSearch.new(<<~'EOM') def foo def blerg end EOM search.call - expect(search.invalid_blocks.join).to eq(<<~EOM.indent(2)) + expect(search.invalid_blocks.join).to eq(<<~'EOM'.indent(2)) def blerg EOM end it "finds a naked end" do - search = CodeSearch.new(<<~EOM) + search = CodeSearch.new(<<~'EOM') def foo end # one end # two EOM search.call - expect(search.invalid_blocks.join).to eq(<<~EOM.indent(2)) + expect(search.invalid_blocks.join).to eq(<<~'EOM'.indent(2)) end # one EOM end it "returns when no invalid blocks are found" do - search = CodeSearch.new(<<~EOM) + search = CodeSearch.new(<<~'EOM') def foo puts 'lol' end @@ -431,14 +439,14 @@ def foo end it "expands frontier by eliminating valid lines" do - search = CodeSearch.new(<<~EOM) + search = CodeSearch.new(<<~'EOM') def foo puts 'lol' end EOM search.create_blocks_from_untracked_lines - expect(search.code_lines.join).to eq(<<~EOM) + expect(search.code_lines.join).to eq(<<~'EOM') def foo end EOM From 514d6839c483c8f20ca44140ab5aa014ca6e6f27 Mon Sep 17 00:00:00 2001 From: schneems Date: Sat, 22 Jan 2022 11:44:24 -0600 Subject: [PATCH 2/2] Decouple Capture Context tests The "capture code context spec" currently depends on code search which can change as the algorithm evolves. This makes development hard since it's unclear when those tests fail if it's because the functionality changed or the search output changed. Also since the existing "capture context" logic is based on quirks of how the code search algorithm works, when the search is improved it may need different "capture context" logic before it produces good output. For these cases, we actually need to duplicate the tests 3 times. - Integration with everything - Capture Code Context works with static input - CodeSearch produces the static input we expect So when all 3 start failing then we can look at it in isolation and see if it "makes sense". I.e. if the CodeSearch output actually "improved" but the integration and capture context are failing then we need to write new logic. --- spec/integration/dead_end_spec.rb | 61 ++++++++++ spec/unit/capture_code_context_spec.rb | 152 ++++++++++--------------- spec/unit/code_search_spec.rb | 49 ++++++++ 3 files changed, 167 insertions(+), 95 deletions(-) diff --git a/spec/integration/dead_end_spec.rb b/spec/integration/dead_end_spec.rb index bd2746a..926383a 100644 --- a/spec/integration/dead_end_spec.rb +++ b/spec/integration/dead_end_spec.rb @@ -146,5 +146,66 @@ module DeadEnd 551 end EOM end + + it "rexe" do + lines = fixtures_dir.join("rexe.rb.txt").read.lines + lines.delete_at(148 - 1) + source = lines.join + + io = StringIO.new + DeadEnd.call( + io: io, + source: source + ) + out = io.string + expect(out).to include(<<~EOM) + 16 class Rexe + 18 VERSION = '1.5.1' + ❯ 77 class Lookups + ❯ 140 def format_requires + ❯ 148 end + 551 end + EOM + end + + it "ambiguous end" do + source = <<~'EOM' + def call # 0 + print "lol" # 1 + end # one # 2 + end # two # 3 + EOM + io = StringIO.new + DeadEnd.call( + io: io, + source: source + ) + out = io.string + expect(out).to include(<<~EOM) + ❯ 1 def call # 0 + ❯ 3 end # one # 2 + ❯ 4 end # two # 3 + EOM + end + + it "simple regression" do + source = <<~'EOM' + class Dog + def bark + puts "woof" + end + EOM + io = StringIO.new + DeadEnd.call( + io: io, + source: source + ) + out = io.string + expect(out).to include(<<~EOM) + ❯ 1 class Dog + ❯ 2 def bark + ❯ 4 end + EOM + end end end diff --git a/spec/unit/capture_code_context_spec.rb b/spec/unit/capture_code_context_spec.rb index 0eb7300..9b77348 100644 --- a/spec/unit/capture_code_context_spec.rb +++ b/spec/unit/capture_code_context_spec.rb @@ -15,8 +15,7 @@ def eat end EOM - code_lines = CodeLine.from_source(source) - + code_lines = CleanDocument.new(source: source).call.lines block = CodeBlock.new(lines: code_lines[0]) display = CaptureCodeContext.new( @@ -24,7 +23,7 @@ def eat code_lines: code_lines ) lines = display.call - expect(lines.join).to eq(<<~EOM) + expect(lines.join).to eq(<<~'EOM') def sit end def bark @@ -35,73 +34,28 @@ def eat it "handles ambiguous end" do source = <<~'EOM' - def call # 1 - puts "lol" # 2 - end # one # 3 - end # two # 4 - 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 # 1 - end # one # 3 - end # two # 4 - EOM - end - - it "finds internal end associated with missing do" do - source = <<~'EOM' - def call - trydo - - @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 + def call # 0 + print "lol" # 1 + end # one # 2 + end # two # 3 EOM - search = CodeSearch.new(source) - search.call + code_lines = CleanDocument.new(source: source).call.lines + code_lines[0..2].each(&:mark_invisible) + block = CodeBlock.new(lines: code_lines) display = CaptureCodeContext.new( - blocks: search.invalid_blocks, - code_lines: search.code_lines + blocks: [block], + code_lines: code_lines ) lines = display.call lines = lines.sort.map(&:original) - expect(lines.join).to eq(<<~EOM) - def call - trydo - end # one - end # two + expect(lines.join).to eq(<<~'EOM') + def call # 0 + end # one # 2 + end # two # 3 EOM end @@ -110,22 +64,24 @@ def call lines.delete_at(148 - 1) source = lines.join - search = CodeSearch.new(source) - search.call + code_lines = CleanDocument.new(source: source).call.lines + + code_lines[0..75].each(&:mark_invisible) + code_lines[77..-1].each(&:mark_invisible) + expect(code_lines.join.strip).to eq("class Lookups") + + block = CodeBlock.new(lines: code_lines[76..149]) display = CaptureCodeContext.new( - blocks: search.invalid_blocks, - code_lines: search.code_lines + blocks: [block], + code_lines: code_lines ) lines = display.call lines = lines.sort.map(&:original) - expect(lines.join).to eq(<<~EOM) - class Rexe - VERSION = '1.5.1' - class Lookups - def format_requires - end + expect(lines.join).to include(<<~'EOM'.indent(2)) + class Lookups + def format_requires end EOM end @@ -137,16 +93,19 @@ def bark puts "woof" end EOM - search = CodeSearch.new(source) - search.call - expect(search.invalid_blocks.join.strip).to eq("class Dog") + code_lines = CleanDocument.new(source: source).call.lines + block = CodeBlock.new(lines: code_lines) + code_lines[1..-1].each(&:mark_invisible) + + expect(block.to_s.strip).to eq("class Dog") + display = CaptureCodeContext.new( - blocks: search.invalid_blocks, - code_lines: search.code_lines + blocks: [block], + code_lines: code_lines ) lines = display.call.sort.map(&:original) - expect(lines.join).to eq(<<~EOM) + expect(lines.join).to eq(<<~'EOM') class Dog def bark end @@ -154,7 +113,7 @@ def bark end it "captures surrounding context on falling indent" do - syntax_string = <<~EOM + source = <<~'EOM' class Blerg end @@ -168,18 +127,17 @@ def hello class Zerg end EOM + code_lines = CleanDocument.new(source: source).call.lines + block = CodeBlock.new(lines: code_lines[6]) - search = CodeSearch.new(syntax_string) - search.call - - expect(search.invalid_blocks.join.strip).to eq('it "foo" do') + expect(block.to_s.strip).to eq('it "foo" do') display = CaptureCodeContext.new( - blocks: search.invalid_blocks, - code_lines: search.code_lines + blocks: [block], + code_lines: code_lines ) lines = display.call.sort.map(&:original) - expect(lines.join).to eq(<<~EOM) + expect(lines.join).to eq(<<~'EOM') class OH def hello it "foo" do @@ -189,7 +147,7 @@ def hello end it "captures surrounding context on same indent" do - syntax_string = <<~EOM + source = <<~'EOM' class Blerg end class OH @@ -200,7 +158,6 @@ def nope def lol end - puts "here" end # here def haha @@ -214,26 +171,31 @@ class Zerg end EOM - search = CodeSearch.new(syntax_string) - search.call + code_lines = CleanDocument.new(source: source).call.lines + block = CodeBlock.new(lines: code_lines[7..10]) + expect(block.to_s).to eq(<<~'EOM'.indent(2)) + def lol + end + + end # here + EOM code_context = CaptureCodeContext.new( - blocks: search.invalid_blocks, - code_lines: search.code_lines + blocks: [block], + code_lines: code_lines ) lines = code_context.call - out = DisplayCodeWithLineNumbers.new( lines: lines ).call - expect(out).to eq(<<~EOM.indent(2)) + expect(out).to eq(<<~'EOM'.indent(2)) 3 class OH 8 def lol 9 end - 12 end # here - 19 end + 11 end # here + 18 end EOM end end diff --git a/spec/unit/code_search_spec.rb b/spec/unit/code_search_spec.rb index 472b28c..9e384de 100644 --- a/spec/unit/code_search_spec.rb +++ b/spec/unit/code_search_spec.rb @@ -4,6 +4,55 @@ module DeadEnd RSpec.describe CodeSearch do + it "rexe regression" do + lines = fixtures_dir.join("rexe.rb.txt").read.lines + lines.delete_at(148 - 1) + source = lines.join + + search = CodeSearch.new(source) + search.call + + expect(search.invalid_blocks.join.strip).to eq(<<~'EOM'.strip) + class Lookups + EOM + end + + it "squished do regression" do + source = <<~'EOM' + def call + trydo + + @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 + + expect(search.invalid_blocks.join).to eq(<<~'EOM'.indent(2)) + trydo + end # one + EOM + end + it "regression test ambiguous end" do source = <<~'EOM' def call # 0