Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Record search #5

Merged
merged 7 commits into from
Nov 9, 2020
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: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,5 @@

# rspec failure tracking
.rspec_status
.DS_Store

2 changes: 2 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# frozen_string_literal: true

source "https://rubygems.org"

# Specify your gem's dependencies in syntax_error_search.gemspec
Expand Down
2 changes: 2 additions & 0 deletions Rakefile
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# frozen_string_literal: true

require "bundler/gem_tasks"
require "rspec/core/rake_task"

Expand Down
4 changes: 3 additions & 1 deletion lib/syntax_error_search.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# frozen_string_literal: true

require "syntax_error_search/version"

require 'parser/current'
Expand All @@ -10,7 +12,7 @@ class Error < StandardError; end
# Used for counting spaces
module SpaceCount
def self.indent(string)
string.split(/\w/).first&.length || 0
string.split(/\S/).first&.length || 0
end
end

Expand Down
2 changes: 2 additions & 0 deletions lib/syntax_error_search/code_block.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# frozen_string_literal: true

module SyntaxErrorSearch
# Multiple lines form a singular CodeBlock
#
Expand Down
20 changes: 15 additions & 5 deletions lib/syntax_error_search/code_frontier.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# frozen_string_literal: true

module SyntaxErrorSearch
# This class is responsible for generating, storing, and sorting code blocks
#
Expand Down Expand Up @@ -185,10 +187,13 @@ def next_block
indent = @indent_hash.keys.sort.last
lines = @indent_hash[indent].first

CodeBlock.new(
block = CodeBlock.new(
lines: lines,
code_lines: @code_lines
).expand_until_neighbors

register(block)
block
end

# This method is responsible for determining if a new code
Expand All @@ -201,16 +206,21 @@ def generate_new_block?
@frontier.last.current_indent <= @indent_hash.keys.sort.last
end

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

# Add a block to the frontier
#
# This method ensures the frontier always remains sorted (in indentation order)
# and that each code block's lines are removed from the indentation hash so we
# don't re-evaluate the same line multiple times.
def <<(block)
block.lines.each do |line|
@indent_hash[line.indent]&.delete(line)
end
@indent_hash.select! {|k, v| !v.empty?}
register(block)

@frontier << block
@frontier.sort!
Expand Down
2 changes: 2 additions & 0 deletions lib/syntax_error_search/code_line.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# frozen_string_literal: true

module SyntaxErrorSearch
# Represents a single line of code of a given source file
#
Expand Down
64 changes: 52 additions & 12 deletions lib/syntax_error_search/code_search.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# frozen_string_literal: true

module SyntaxErrorSearch
# Searches code for a syntax error
#
Expand All @@ -24,28 +26,66 @@ module SyntaxErrorSearch
#
class CodeSearch
private; attr_reader :frontier; public
public; attr_reader :invalid_blocks
public; attr_reader :invalid_blocks, :record_dir

def initialize(string)
def initialize(string, record_dir: ENV["SYNTAX_SEARCH_RECORD_DIR"])
if record_dir
@time = Time.now.strftime('%Y-%m-%d-%H-%M-%s-%N')
@record_dir = Pathname(record_dir).join(@time)
end
@code_lines = string.lines.map.with_index do |line, i|
CodeLine.new(line: line, index: i)
end
@frontier = CodeFrontier.new(code_lines: @code_lines)
@invalid_blocks = []
@name_tick = Hash.new {|hash, k| hash[k] = 0 }
@tick = 0
end

def call
until frontier.holds_all_syntax_errors?
frontier << frontier.next_block if frontier.next_block?
def record(block:, name: "record")
return if !@record_dir
@name_tick[name] += 1
file = @record_dir.join("#{@tick}-#{name}-#{@name_tick[name]}.txt").tap {|p| p.dirname.mkpath }
file.open(mode: "a") do |f|
display = DisplayInvalidBlocks.new(
blocks: block,
terminal: false
)
f.write(display.indent display.code_with_lines)
end
end

def expand_frontier
return if !frontier.next_block?
block = frontier.next_block
record(block: block, name: "add")
if block.valid?
block.lines.each(&:mark_invisible)
return expand_frontier
else
frontier << block
end
block
end

block = frontier.pop
def search
block = frontier.pop

if block.valid?
block.lines.each(&:mark_invisible)
else
block.expand_until_neighbors
frontier << block
end
block.expand_until_next_boundry
record(block: block, name: "expand")
if block.valid?
block.lines.each(&:mark_invisible)
else
frontier << block
end
end

def call
until frontier.holds_all_syntax_errors?
@tick += 1
expand_frontier
break if frontier.holds_all_syntax_errors? # Need to check after every time something is added to frontier
search
end

@invalid_blocks.concat(frontier.detect_invalid_blocks )
Expand Down
47 changes: 34 additions & 13 deletions lib/syntax_error_search/display_invalid_blocks.rb
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
# frozen_string_literal: true

module SyntaxErrorSearch
# Used for formatting invalid blocks
class DisplayInvalidBlocks
attr_reader :filename

def initialize(block_array, io: $stderr, filename: nil)
def initialize(blocks:, io: $stderr, filename: nil, terminal: false)
@terminal = terminal
@filename = filename
@io = io
@blocks = block_array
@blocks = Array(blocks)
@lines = @blocks.map(&:lines).flatten
@digit_count = @lines.last.line_number.to_s.length
@code_lines = @blocks.first.code_lines
@digit_count = @code_lines.last.line_number.to_s.length

@invalid_line_hash = @lines.each_with_object({}) {|line, h| h[line] = true}
@invalid_line_hash = @lines.each_with_object({}) {|line, h| h[line] = true }
end

def call
Expand All @@ -28,35 +31,53 @@ def call
@io.puts <<~EOM
simplified:

#{code_with_filename(indent: 2)}
#{indent(code_block)}
EOM
self
end

def indent(string, with: " ")
string.each_line.map {|l| with + l }.join
end

def code_with_filename(indent: 0)
def code_block
string = String.new("")
string << "```\n"
# string << "#".rjust(@digit_count) + " filename: #{filename}\n\n" if filename
string << code_with_lines
string << "```\n"
string
end

def terminal_end
"\e[0m"
end

string.each_line.map {|l| " " * indent + l }.join
def terminal_highlight
"\e[1;3m" # Bold, italics
end

def code_with_lines
@code_lines.map do |line|
next if line.hidden?
string = String.new("")
if @invalid_line_hash[line]
string << "❯ "
else
string << " "
end

number = line.line_number.to_s.rjust(@digit_count)
string << number.to_s
if line.empty?
"#{number.to_s}#{line}"
string << line.to_s
else
string = String.new
string << "\e[1;3m" if @invalid_line_hash[line] # Bold, italics
string << "#{number.to_s} "
string << " "
string << terminal_highlight if @terminal && @invalid_line_hash[line] # Bold, italics
string << line.to_s
string << "\e[0m"
string
string << terminal_end if @terminal
end
string
end.join
end
end
Expand Down
2 changes: 2 additions & 0 deletions lib/syntax_error_search/version.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# frozen_string_literal: true

module SyntaxErrorSearch
VERSION = "0.1.0"
end
2 changes: 2 additions & 0 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# frozen_string_literal: true

require "bundler/setup"
require "syntax_error_search"

Expand Down
2 changes: 2 additions & 0 deletions spec/syntax_error_search_spec.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# frozen_string_literal: true

module SyntaxErrorSearch
RSpec.describe SyntaxErrorSearch do
it "has a version number" do
Expand Down
2 changes: 2 additions & 0 deletions spec/unit/code_block_spec.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# frozen_string_literal: true

require_relative "../spec_helper.rb"

module SyntaxErrorSearch
Expand Down
2 changes: 2 additions & 0 deletions spec/unit/code_frontier_spec.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# frozen_string_literal: true

require_relative "../spec_helper.rb"

module SyntaxErrorSearch
Expand Down
2 changes: 2 additions & 0 deletions spec/unit/code_line_spec.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# frozen_string_literal: true

require_relative "../spec_helper.rb"

module SyntaxErrorSearch
Expand Down
Loading