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
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
## HEAD (unreleased)

- Replace some references in tests with foobar style code (https://github.com/zombocom/dead_end/pull/38)
- Fix bug where empty lines were interpreted to have a zero indentation (https://github.com/zombocom/dead_end/pull/39)

## 1.0.1

Expand Down
5 changes: 4 additions & 1 deletion lib/dead_end/code_block.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,12 @@ module DeadEnd
#
#
class CodeBlock
UNSET = Object.new.freeze
attr_reader :lines

def initialize(lines: [])
@lines = Array(lines)
@valid = UNSET
end

def visible_lines
Expand Down Expand Up @@ -68,7 +70,8 @@ def invalid?
end

def valid?
DeadEnd.valid?(self.to_s)
return @valid if @valid != UNSET
@valid = DeadEnd.valid?(self.to_s)
end

def to_s
Expand Down
45 changes: 16 additions & 29 deletions lib/dead_end/code_frontier.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,20 @@ module DeadEnd
# sorted and then the frontier can be filtered. Large blocks that totally contain a
# smaller block will cause the smaller block to be evicted.
#
# CodeFrontier#<<
# CodeFrontier#pop
# CodeFrontier#<<(block) # Adds block to frontier
# CodeFrontier#pop # Removes block from frontier
#
# ## Knowing where we can go
#
# Internally it keeps track of an "indent hash" which is exposed via `next_indent_line`
# Internally it keeps track of "unvisited" lines which is exposed via `next_indent_line`
# when called this will return a line of code with the most indentation.
#
# This line of code can be used to build a CodeBlock via and then when that code block
# is added back to the frontier, then the lines in the code block are removed from the
# indent hash so we don't double-create the same block.
# This line of code can be used to build a CodeBlock and then when that code block
# is added back to the frontier, then the lines are removed from the
# "unvisited" so we don't double-create the same block.
#
# CodeFrontier#next_indent_line
# CodeFrontier#register_indent_block
# CodeFrontier#next_indent_line # Shows next line
# CodeFrontier#register_indent_block(block) # Removes lines from unvisited
#
# ## Knowing when to stop
#
Expand All @@ -42,13 +42,7 @@ class CodeFrontier
def initialize(code_lines: )
@code_lines = code_lines
@frontier = []
@indent_hash = {}
code_lines.each do |line|
next if line.empty?

@indent_hash[line.indent] ||= []
@indent_hash[line.indent] << line
end
@unvisited_lines = @code_lines.sort_by(&:indent_index)
end

def count
Expand All @@ -75,38 +69,31 @@ def pop
return @frontier.pop
end

def indent_hash_indent
@indent_hash.keys.sort.last
end

def next_indent_line
indent = @indent_hash.keys.sort.last
@indent_hash[indent]&.first
@unvisited_lines.last
end

def expand?
return false if @frontier.empty?
return true if @indent_hash.empty?
return true if @unvisited_lines.empty?

frontier_indent = @frontier.last.current_indent
hash_indent = @indent_hash.keys.sort.last
unvisited_indent= next_indent_line.indent

if ENV["DEBUG"]
puts "```"
puts @frontier.last.to_s
puts "```"
puts " @frontier indent: #{frontier_indent}"
puts " @hash indent: #{hash_indent}"
puts " @unvisited indent: #{unvisited_indent}"
end

frontier_indent >= hash_indent
# Expand all blocks before moving to unvisited lines
frontier_indent >= unvisited_indent
end

def register_indent_block(block)
block.lines.each do |line|
@indent_hash[line.indent]&.delete(line)
end
@indent_hash.select! {|k, v| !v.empty?}
@unvisited_lines -= block.lines
self
end

Expand Down
22 changes: 11 additions & 11 deletions lib/dead_end/code_line.rb
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,14 @@ class CodeLine
def initialize(line: , index:)
@original_line = line.freeze
@line = @original_line
@empty = line.strip.empty?
if line.strip.empty?
@empty = true
@indent = 0
else
@empty = false
@indent = SpaceCount.indent(line)
end
@index = index
@indent = SpaceCount.indent(line)
@status = nil # valid, invalid, unknown
@invalid = false

Expand Down Expand Up @@ -72,6 +77,10 @@ def trailing_slash?
@is_trailing_slash
end

def indent_index
@indent_index ||= [indent, index]
end

def <=>(b)
self.index <=> b.index
end
Expand All @@ -92,15 +101,6 @@ def is_end?
@is_end
end

def mark_invalid
@invalid = true
self
end

def marked_invalid?
@invalid
end

def mark_invisible
@line = ""
self
Expand Down
6 changes: 3 additions & 3 deletions lib/dead_end/code_search.rb
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ def push(block, name: )
record(block: block, name: name)

if block.valid?
block.lines.each(&:mark_invisible)
block.mark_invisible
frontier << block
else
frontier << block
Expand All @@ -92,7 +92,7 @@ def sweep(block:, name: )

# Parses the most indented lines into blocks that are marked
# and added to the frontier
def add_invalid_blocks
def visit_new_blocks
max_indent = frontier.next_indent_line&.indent

while (line = frontier.next_indent_line) && (line.indent == max_indent)
Expand Down Expand Up @@ -145,7 +145,7 @@ def call
if frontier.expand?
expand_invalid_block
else
add_invalid_blocks
visit_new_blocks
end
end

Expand Down
23 changes: 9 additions & 14 deletions spec/unit/code_line_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,20 +41,6 @@ module DeadEnd
expect(line.is_kw?).to be_truthy
end

it "can be marked as invalid or valid" do
code_lines = code_line_array(<<~EOM)
def foo
Array(value) |x|
end
end
EOM

expect(code_lines[0].marked_invalid?).to be_falsey
code_lines[0].mark_invalid
expect(code_lines[0].marked_invalid?).to be_truthy

end

it "ignores marked lines" do
code_lines = code_line_array(<<~EOM)
def foo
Expand Down Expand Up @@ -110,5 +96,14 @@ def foo

expect(code_lines.map(&:indent)).to eq([0, 2, 4, 2, 0])
end

it "doesn't count empty lines as having an indentation" do
code_lines = code_line_array(<<~EOM)


EOM

expect(code_lines.map(&:indent)).to eq([0, 0])
end
end
end
6 changes: 3 additions & 3 deletions spec/unit/code_search_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -277,15 +277,15 @@ def foo

it "stacked ends 2" do
search = CodeSearch.new(<<~EOM)
def lol
def cat
blerg
end

Foo.call do
end # one
end # two

def lol
def dog
end
EOM
search.call
Expand Down Expand Up @@ -445,7 +445,7 @@ def foo
puts 'lol'
end
EOM
search.add_invalid_blocks
search.visit_new_blocks

expect(search.code_lines.join).to eq(<<~EOM)
def foo
Expand Down