Skip to content

Commit

Permalink
Strip HEREDOC
Browse files Browse the repository at this point in the history
Heredocs in ruby are common sources of indentation even though they cannot cause either an "unmatched" or "unexpected" end syntax errors. To help avoid these false positives when parsing source, we first find and parse all heredocs. If the lines that contain the heredocs are valid, they'll be commented-out/hidden early on. This drastically decreases the chance that heredoc based indentation will lead to false positives.
  • Loading branch information
schneems committed Dec 2, 2020
1 parent 7bac04a commit b3478aa
Show file tree
Hide file tree
Showing 9 changed files with 678 additions and 3 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
## HEAD (unreleased)

- Strip out heredocs in documents first (https://github.com/zombocom/syntax_search/pull/19)

## 0.1.4

- Parser gem replaced with Ripper (https://github.com/zombocom/syntax_search/pull/17)
Expand Down
1 change: 1 addition & 0 deletions lib/syntax_search.rb
Original file line number Diff line number Diff line change
Expand Up @@ -141,3 +141,4 @@ def self.invalid_type(source)

require_relative "syntax_search/code_search"
require_relative "syntax_search/who_dis_syntax_error"
require_relative "syntax_search/heredoc_block_parse"
4 changes: 4 additions & 0 deletions lib/syntax_search/code_block.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ def is_end?
to_s.strip == "end"
end

def hidden?
@lines.all?(&:hidden?)
end

def starts_at
@starts_at ||= @lines.first&.line_number
end
Expand Down
16 changes: 14 additions & 2 deletions lib/syntax_search/code_search.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,14 @@ class CodeSearch
private; attr_reader :frontier; public
public; attr_reader :invalid_blocks, :record_dir, :code_lines

def initialize(string, record_dir: ENV["SYNTAX_SEARCH_RECORD_DIR"])
def initialize(source, record_dir: ENV["SYNTAX_SEARCH_RECORD_DIR"])
@source = source
if record_dir
@time = Time.now.strftime('%Y-%m-%d-%H-%M-%s-%N')
@record_dir = Pathname(record_dir).join(@time).tap {|p| p.mkpath }
@write_count = 0
end
@code_lines = string.lines.map.with_index do |line, i|
@code_lines = source.lines.map.with_index do |line, i|
CodeLine.new(line: line, index: i)
end
@frontier = CodeFrontier.new(code_lines: @code_lines)
Expand Down Expand Up @@ -107,8 +108,19 @@ def expand_invalid_block
push(block, name: "expand")
end


def sweep_heredocs
HeredocBlockParse.new(
source: @source,
code_lines: @code_lines
).call.each do |block|
push(block, name: "heredoc")
end
end

# Main search loop
def call
sweep_heredocs
until frontier.holds_all_syntax_errors?
@tick += 1

Expand Down
2 changes: 1 addition & 1 deletion lib/syntax_search/display_invalid_blocks.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ def initialize(code_lines: ,blocks:, io: $stderr, filename: nil, terminal: false
end

def call
if @blocks.any?
if @blocks.any? { |b| !b.hidden? }
found_invalid_blocks
else
@io.puts "Syntax OK"
Expand Down
30 changes: 30 additions & 0 deletions lib/syntax_search/heredoc_block_parse.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# frozen_string_literal: true

module SyntaxErrorSearch
# Takes in a source, and returns blocks containing each heredoc
class HeredocBlockParse
private; attr_reader :code_lines, :lex; public

def initialize(source:, code_lines: )
@code_lines = code_lines
@lex = Ripper.lex(source)
end

def call
blocks = []
beginning = []
@lex.each do |(line, col), event, *_|
case event
when :on_heredoc_beg
beginning << line
when :on_heredoc_end
start_index = beginning.pop - 1
end_index = line - 1
blocks << CodeBlock.new(lines: code_lines[start_index..end_index])
end
end

blocks
end
end
end
Loading

0 comments on commit b3478aa

Please sign in to comment.