dead_end 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.circleci/config.yml +41 -0
- data/.github/workflows/check_changelog.yml +13 -0
- data/.gitignore +14 -0
- data/.rspec +3 -0
- data/.travis.yml +6 -0
- data/CHANGELOG.md +39 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +10 -0
- data/Gemfile.lock +36 -0
- data/LICENSE.txt +21 -0
- data/README.md +122 -0
- data/Rakefile +8 -0
- data/assets/syntax_search.gif +0 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/dead_end.gemspec +28 -0
- data/exe/dead_end +70 -0
- data/lib/dead_end.rb +4 -0
- data/lib/dead_end/around_block_scan.rb +193 -0
- data/lib/dead_end/auto.rb +51 -0
- data/lib/dead_end/block_expand.rb +74 -0
- data/lib/dead_end/capture_code_context.rb +62 -0
- data/lib/dead_end/code_block.rb +78 -0
- data/lib/dead_end/code_frontier.rb +151 -0
- data/lib/dead_end/code_line.rb +139 -0
- data/lib/dead_end/code_search.rb +157 -0
- data/lib/dead_end/display_code_with_line_numbers.rb +71 -0
- data/lib/dead_end/display_invalid_blocks.rb +122 -0
- data/lib/dead_end/fyi.rb +7 -0
- data/lib/dead_end/heredoc_block_parse.rb +30 -0
- data/lib/dead_end/internals.rb +156 -0
- data/lib/dead_end/lex_all.rb +58 -0
- data/lib/dead_end/parse_blocks_from_indent_line.rb +56 -0
- data/lib/dead_end/trailing_slash_join.rb +53 -0
- data/lib/dead_end/version.rb +5 -0
- data/lib/dead_end/who_dis_syntax_error.rb +66 -0
- metadata +83 -0
@@ -0,0 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DeadEnd
|
4
|
+
# This class is responsible for generating initial code blocks
|
5
|
+
# that will then later be expanded.
|
6
|
+
#
|
7
|
+
# The biggest concern when guessing about code blocks, is accidentally
|
8
|
+
# grabbing one that contains only an "end". In this example:
|
9
|
+
#
|
10
|
+
# def dog
|
11
|
+
# begonn # mispelled `begin`
|
12
|
+
# puts "bark"
|
13
|
+
# end
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
# The following lines would be matched (from bottom to top):
|
17
|
+
#
|
18
|
+
# 1) end
|
19
|
+
#
|
20
|
+
# 2) puts "bark"
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
# 3) begonn
|
24
|
+
# puts "bark"
|
25
|
+
# end
|
26
|
+
#
|
27
|
+
# At this point it has no where else to expand, and it will yield this inner
|
28
|
+
# code as a block
|
29
|
+
class ParseBlocksFromIndentLine
|
30
|
+
attr_reader :code_lines
|
31
|
+
|
32
|
+
def initialize(code_lines: )
|
33
|
+
@code_lines = code_lines
|
34
|
+
end
|
35
|
+
|
36
|
+
# Builds blocks from bottom up
|
37
|
+
def each_neighbor_block(target_line)
|
38
|
+
scan = AroundBlockScan.new(code_lines: code_lines, block: CodeBlock.new(lines: target_line))
|
39
|
+
.skip(:empty?)
|
40
|
+
.skip(:hidden?)
|
41
|
+
.scan_while {|line| line.indent >= target_line.indent }
|
42
|
+
|
43
|
+
neighbors = @code_lines[scan.before_index..scan.after_index]
|
44
|
+
|
45
|
+
until neighbors.empty?
|
46
|
+
lines = [neighbors.pop]
|
47
|
+
while (block = CodeBlock.new(lines: lines)) && block.invalid? && neighbors.any?
|
48
|
+
lines.prepend neighbors.pop
|
49
|
+
end
|
50
|
+
|
51
|
+
yield block if block
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DeadEnd
|
4
|
+
# Handles code that contains trailing slashes
|
5
|
+
# by turning multiple lines with trailing slash(es) into
|
6
|
+
# a single code line
|
7
|
+
#
|
8
|
+
# expect(code_lines.join).to eq(<<~EOM)
|
9
|
+
# it "trailing \
|
10
|
+
# "slash" do
|
11
|
+
# end
|
12
|
+
# EOM
|
13
|
+
#
|
14
|
+
# lines = TrailngSlashJoin(code_lines: code_lines).call
|
15
|
+
# expect(lines.first.to_s).to eq(<<~EOM)
|
16
|
+
# it "trailing \
|
17
|
+
# "slash" do
|
18
|
+
# EOM
|
19
|
+
#
|
20
|
+
class TrailingSlashJoin
|
21
|
+
def initialize(code_lines:)
|
22
|
+
@code_lines = code_lines
|
23
|
+
@code_lines_dup = code_lines.dup
|
24
|
+
end
|
25
|
+
|
26
|
+
def call
|
27
|
+
@trailing_lines = []
|
28
|
+
@code_lines.select(&:trailing_slash?).each do |trailing|
|
29
|
+
stop_next = false
|
30
|
+
lines = @code_lines[trailing.index..-1].take_while do |line|
|
31
|
+
next false if stop_next
|
32
|
+
|
33
|
+
if !line.trailing_slash?
|
34
|
+
stop_next = true
|
35
|
+
end
|
36
|
+
|
37
|
+
true
|
38
|
+
end
|
39
|
+
|
40
|
+
joined_line = CodeLine.new(line: lines.map(&:original_line).join, index: trailing.index)
|
41
|
+
|
42
|
+
@code_lines_dup[trailing.index] = joined_line
|
43
|
+
|
44
|
+
@trailing_lines << joined_line
|
45
|
+
|
46
|
+
lines.shift # Don't hide first trailing slash line
|
47
|
+
lines.each(&:mark_invisible)
|
48
|
+
end
|
49
|
+
|
50
|
+
return @code_lines_dup
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DeadEnd
|
4
|
+
# Determines what type of syntax error is in the source
|
5
|
+
#
|
6
|
+
# Example:
|
7
|
+
#
|
8
|
+
# puts WhoDisSyntaxError.new("def foo;").call.error_symbol
|
9
|
+
# # => :missing_end
|
10
|
+
class WhoDisSyntaxError < Ripper
|
11
|
+
class Null
|
12
|
+
def error_symbol; :missing_end; end
|
13
|
+
def unmatched_symbol; :end ; end
|
14
|
+
end
|
15
|
+
attr_reader :error, :run_once
|
16
|
+
|
17
|
+
# Return options:
|
18
|
+
# - :missing_end
|
19
|
+
# - :unmatched_syntax
|
20
|
+
# - :unknown
|
21
|
+
def error_symbol
|
22
|
+
call
|
23
|
+
@error_symbol
|
24
|
+
end
|
25
|
+
|
26
|
+
# Return options:
|
27
|
+
# - :end
|
28
|
+
# - :|
|
29
|
+
# - :}
|
30
|
+
# - :unknown
|
31
|
+
def unmatched_symbol
|
32
|
+
call
|
33
|
+
@unmatched_symbol
|
34
|
+
end
|
35
|
+
|
36
|
+
def call
|
37
|
+
@run_once ||= begin
|
38
|
+
parse
|
39
|
+
true
|
40
|
+
end
|
41
|
+
self
|
42
|
+
end
|
43
|
+
|
44
|
+
def on_parse_error(msg)
|
45
|
+
@error = msg
|
46
|
+
@unmatched_symbol = :unknown
|
47
|
+
|
48
|
+
if @error.match?(/unexpected end-of-input/)
|
49
|
+
@error_symbol = :missing_end
|
50
|
+
elsif @error.match?(/expecting end-of-input/)
|
51
|
+
@error_symbol = :unmatched_syntax
|
52
|
+
@unmatched_symbol = :end
|
53
|
+
elsif @error.match?(/unexpected `end'/) || # Ruby 2.7 & 3.0
|
54
|
+
@error.match?(/unexpected end,/) || # Ruby 2.6
|
55
|
+
@error.match?(/unexpected keyword_end/) # Ruby 2.5
|
56
|
+
|
57
|
+
@error_symbol = :unmatched_syntax
|
58
|
+
|
59
|
+
match = @error.match(/expecting '(?<unmatched_symbol>.*)'/)
|
60
|
+
@unmatched_symbol = match[:unmatched_symbol].to_sym if match
|
61
|
+
else
|
62
|
+
@error_symbol = :unknown
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
metadata
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: dead_end
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- schneems
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2020-12-10 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: When you get an "unexpected end" in your syntax this gem helps you find
|
14
|
+
it
|
15
|
+
email:
|
16
|
+
- richard.schneeman+foo@gmail.com
|
17
|
+
executables:
|
18
|
+
- dead_end
|
19
|
+
extensions: []
|
20
|
+
extra_rdoc_files: []
|
21
|
+
files:
|
22
|
+
- ".circleci/config.yml"
|
23
|
+
- ".github/workflows/check_changelog.yml"
|
24
|
+
- ".gitignore"
|
25
|
+
- ".rspec"
|
26
|
+
- ".travis.yml"
|
27
|
+
- CHANGELOG.md
|
28
|
+
- CODE_OF_CONDUCT.md
|
29
|
+
- Gemfile
|
30
|
+
- Gemfile.lock
|
31
|
+
- LICENSE.txt
|
32
|
+
- README.md
|
33
|
+
- Rakefile
|
34
|
+
- assets/syntax_search.gif
|
35
|
+
- bin/console
|
36
|
+
- bin/setup
|
37
|
+
- dead_end.gemspec
|
38
|
+
- exe/dead_end
|
39
|
+
- lib/dead_end.rb
|
40
|
+
- lib/dead_end/around_block_scan.rb
|
41
|
+
- lib/dead_end/auto.rb
|
42
|
+
- lib/dead_end/block_expand.rb
|
43
|
+
- lib/dead_end/capture_code_context.rb
|
44
|
+
- lib/dead_end/code_block.rb
|
45
|
+
- lib/dead_end/code_frontier.rb
|
46
|
+
- lib/dead_end/code_line.rb
|
47
|
+
- lib/dead_end/code_search.rb
|
48
|
+
- lib/dead_end/display_code_with_line_numbers.rb
|
49
|
+
- lib/dead_end/display_invalid_blocks.rb
|
50
|
+
- lib/dead_end/fyi.rb
|
51
|
+
- lib/dead_end/heredoc_block_parse.rb
|
52
|
+
- lib/dead_end/internals.rb
|
53
|
+
- lib/dead_end/lex_all.rb
|
54
|
+
- lib/dead_end/parse_blocks_from_indent_line.rb
|
55
|
+
- lib/dead_end/trailing_slash_join.rb
|
56
|
+
- lib/dead_end/version.rb
|
57
|
+
- lib/dead_end/who_dis_syntax_error.rb
|
58
|
+
homepage: https://github.com/zombocom/dead_end.git
|
59
|
+
licenses:
|
60
|
+
- MIT
|
61
|
+
metadata:
|
62
|
+
homepage_uri: https://github.com/zombocom/dead_end.git
|
63
|
+
source_code_uri: https://github.com/zombocom/dead_end.git
|
64
|
+
post_install_message:
|
65
|
+
rdoc_options: []
|
66
|
+
require_paths:
|
67
|
+
- lib
|
68
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
69
|
+
requirements:
|
70
|
+
- - ">="
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: 2.5.0
|
73
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
74
|
+
requirements:
|
75
|
+
- - ">="
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
requirements: []
|
79
|
+
rubygems_version: 3.1.4
|
80
|
+
signing_key:
|
81
|
+
specification_version: 4
|
82
|
+
summary: Find syntax errors in your source in a snap
|
83
|
+
test_files: []
|