dead_end 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DeadEnd
4
+ VERSION = "1.0.0"
5
+ 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: []