dead_end 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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: []
|