dead_end 1.1.7 → 2.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.circleci/config.yml +14 -0
- data/.github/workflows/check_changelog.yml +14 -7
- data/.standard.yml +1 -0
- data/CHANGELOG.md +24 -0
- data/Gemfile +1 -0
- data/Gemfile.lock +29 -2
- data/README.md +1 -19
- data/Rakefile +1 -1
- data/dead_end.gemspec +12 -12
- data/exe/dead_end +17 -6
- data/lib/dead_end/around_block_scan.rb +16 -18
- data/lib/dead_end/auto.rb +2 -51
- data/lib/dead_end/banner.rb +58 -0
- data/lib/dead_end/block_expand.rb +6 -5
- data/lib/dead_end/capture_code_context.rb +167 -50
- data/lib/dead_end/clean_document.rb +313 -0
- data/lib/dead_end/code_block.rb +3 -3
- data/lib/dead_end/code_frontier.rb +28 -17
- data/lib/dead_end/code_line.rb +160 -77
- data/lib/dead_end/code_search.rb +37 -48
- data/lib/dead_end/display_code_with_line_numbers.rb +7 -8
- data/lib/dead_end/display_invalid_blocks.rb +20 -49
- data/lib/dead_end/fyi.rb +2 -1
- data/lib/dead_end/internals.rb +27 -28
- data/lib/dead_end/lex_all.rb +15 -31
- data/lib/dead_end/lex_value.rb +62 -0
- data/lib/dead_end/parse_blocks_from_indent_line.rb +3 -4
- data/lib/dead_end/version.rb +1 -1
- data/lib/dead_end/who_dis_syntax_error.rb +22 -8
- metadata +7 -6
- data/.travis.yml +0 -6
- data/lib/dead_end/heredoc_block_parse.rb +0 -30
- data/lib/dead_end/trailing_slash_join.rb +0 -53
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ec9e05716b47eb5d96ac063126a59977d98b8cf3e6f09ba0a0065d425a3c15e5
|
4
|
+
data.tar.gz: c78047c6dd36c1c716e1970e9bec5887bbcaf1fcc0341cbb5c11405043a07105
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2eca38b35ef1371cae5fd104fa88dad33d44b17cb6bf29b01b5dea0c650d3d21c0dfbf2b1ac96f0a6f307e7d541cf2a2f7be062d59f1626b16c82f1a2f7d3a3e
|
7
|
+
data.tar.gz: 1a09171cb208465cf48ff5ac0346240d5bf155aebb886c27b6259742f325bc58a0b73ec9998fcbb1544440e6df7363fa7ab57a04dba9e7887207f30916e8c3a9
|
data/.circleci/config.yml
CHANGED
@@ -7,6 +7,11 @@ references:
|
|
7
7
|
name: Run test suite
|
8
8
|
command: bundle exec rspec spec/
|
9
9
|
|
10
|
+
lint: &lint
|
11
|
+
run:
|
12
|
+
name: Run linter, fix with `standardrb --fix` locally
|
13
|
+
command: bundle exec standardrb
|
14
|
+
|
10
15
|
jobs:
|
11
16
|
"ruby-2-5":
|
12
17
|
docker:
|
@@ -40,6 +45,14 @@ jobs:
|
|
40
45
|
- ruby/install-deps
|
41
46
|
- <<: *unit
|
42
47
|
|
48
|
+
"lint":
|
49
|
+
docker:
|
50
|
+
- image: circleci/ruby:3.0
|
51
|
+
steps:
|
52
|
+
- checkout
|
53
|
+
- ruby/install-deps
|
54
|
+
- <<: *lint
|
55
|
+
|
43
56
|
workflows:
|
44
57
|
version: 2
|
45
58
|
build:
|
@@ -48,3 +61,4 @@ workflows:
|
|
48
61
|
- "ruby-2-6"
|
49
62
|
- "ruby-2-7"
|
50
63
|
- "ruby-3-0"
|
64
|
+
- "lint"
|
@@ -1,13 +1,20 @@
|
|
1
1
|
name: Check Changelog
|
2
2
|
|
3
3
|
on:
|
4
|
-
|
5
|
-
|
4
|
+
pull_request:
|
5
|
+
types: [opened, reopened, edited, labeled, unlabeled, synchronize]
|
6
|
+
|
6
7
|
jobs:
|
7
|
-
|
8
|
+
check-changelog:
|
8
9
|
runs-on: ubuntu-latest
|
10
|
+
if: |
|
11
|
+
!contains(github.event.pull_request.body, '[skip changelog]') &&
|
12
|
+
!contains(github.event.pull_request.body, '[changelog skip]') &&
|
13
|
+
!contains(github.event.pull_request.body, '[skip ci]') &&
|
14
|
+
!contains(github.event.pull_request.labels.*.name, 'skip changelog')
|
9
15
|
steps:
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
16
|
+
- uses: actions/checkout@v2.3.5
|
17
|
+
- name: Check that CHANGELOG is touched
|
18
|
+
run: |
|
19
|
+
git fetch origin ${{ github.base_ref }} --depth 1 && \
|
20
|
+
git diff remotes/origin/${{ github.base_ref }} --name-only | grep CHANGELOG.md
|
data/.standard.yml
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
ruby_version: 2.5.9
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,29 @@
|
|
1
1
|
## HEAD (unreleased)
|
2
2
|
|
3
|
+
## 2.0.2
|
4
|
+
|
5
|
+
- Don't print terminal color codes when output is not tty (https://github.com/zombocom/dead_end/pull/91)
|
6
|
+
|
7
|
+
## 2.0.1
|
8
|
+
|
9
|
+
- Reintroduce Ruby 2.5 support (https://github.com/zombocom/dead_end/pull/90)
|
10
|
+
- Support naked braces/brackets/parens, invert labels on banner (https://github.com/zombocom/dead_end/pull/89)
|
11
|
+
- Handle mismatched end when using rescue without begin (https://github.com/zombocom/dead_end/pull/83)
|
12
|
+
- CLI returns non-zero exit code when syntax error is found (https://github.com/zombocom/dead_end/pull/86)
|
13
|
+
- Let -v respond with gem version instead of 'unknown' (https://github.com/zombocom/dead_end/pull/82)
|
14
|
+
|
15
|
+
## 2.0.0
|
16
|
+
|
17
|
+
- Support "endless" oneline method definitions for Ruby 3+ (https://github.com/zombocom/dead_end/pull/80)
|
18
|
+
- Reduce timeout to 1 second (https://github.com/zombocom/dead_end/pull/79)
|
19
|
+
- Logically consecutive lines (such as chained methods are now joined) (https://github.com/zombocom/dead_end/pull/78)
|
20
|
+
- Output improvement for cases where the only line is an single `end` (https://github.com/zombocom/dead_end/pull/78)
|
21
|
+
|
22
|
+
## 1.2.0
|
23
|
+
|
24
|
+
- Output improvements via less greedy unmatched kw capture https://github.com/zombocom/dead_end/pull/73
|
25
|
+
- Remove NoMethodError patching instead use https://github.com/ruby/error_highlight/ (https://github.com/zombocom/dead_end/pull/71)
|
26
|
+
|
3
27
|
## 1.1.7
|
4
28
|
|
5
29
|
- Fix sinatra support for `require_relative` (https://github.com/zombocom/dead_end/pull/63)
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,13 +1,20 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
dead_end (
|
4
|
+
dead_end (2.0.2)
|
5
5
|
|
6
6
|
GEM
|
7
7
|
remote: https://rubygems.org/
|
8
8
|
specs:
|
9
|
+
ast (2.4.2)
|
9
10
|
diff-lcs (1.4.4)
|
11
|
+
parallel (1.21.0)
|
12
|
+
parser (3.0.2.0)
|
13
|
+
ast (~> 2.4.1)
|
14
|
+
rainbow (3.0.0)
|
10
15
|
rake (12.3.3)
|
16
|
+
regexp_parser (2.1.1)
|
17
|
+
rexml (3.2.5)
|
11
18
|
rspec (3.10.0)
|
12
19
|
rspec-core (~> 3.10.0)
|
13
20
|
rspec-expectations (~> 3.10.0)
|
@@ -21,7 +28,26 @@ GEM
|
|
21
28
|
diff-lcs (>= 1.2.0, < 2.0)
|
22
29
|
rspec-support (~> 3.10.0)
|
23
30
|
rspec-support (3.10.0)
|
31
|
+
rubocop (1.20.0)
|
32
|
+
parallel (~> 1.10)
|
33
|
+
parser (>= 3.0.0.0)
|
34
|
+
rainbow (>= 2.2.2, < 4.0)
|
35
|
+
regexp_parser (>= 1.8, < 3.0)
|
36
|
+
rexml
|
37
|
+
rubocop-ast (>= 1.9.1, < 2.0)
|
38
|
+
ruby-progressbar (~> 1.7)
|
39
|
+
unicode-display_width (>= 1.4.0, < 3.0)
|
40
|
+
rubocop-ast (1.12.0)
|
41
|
+
parser (>= 3.0.1.1)
|
42
|
+
rubocop-performance (1.11.5)
|
43
|
+
rubocop (>= 1.7.0, < 2.0)
|
44
|
+
rubocop-ast (>= 0.4.0)
|
45
|
+
ruby-progressbar (1.11.0)
|
24
46
|
stackprof (0.2.16)
|
47
|
+
standard (1.3.0)
|
48
|
+
rubocop (= 1.20.0)
|
49
|
+
rubocop-performance (= 1.11.5)
|
50
|
+
unicode-display_width (2.1.0)
|
25
51
|
|
26
52
|
PLATFORMS
|
27
53
|
ruby
|
@@ -31,6 +57,7 @@ DEPENDENCIES
|
|
31
57
|
rake (~> 12.0)
|
32
58
|
rspec (~> 3.0)
|
33
59
|
stackprof
|
60
|
+
standard
|
34
61
|
|
35
62
|
BUNDLED WITH
|
36
|
-
2.2.
|
63
|
+
2.2.29
|
data/README.md
CHANGED
@@ -81,27 +81,9 @@ end
|
|
81
81
|
|
82
82
|
As well as unmatched `|` and unmatched `}`. These errors can be time consuming to debug because Ruby often only tells you the last line in the file. The command `ruby -wc path/to/file.rb` can narrow it down a little bit, but this library does a better job.
|
83
83
|
|
84
|
-
## What other errors does it handle?
|
85
|
-
|
86
|
-
In addition to syntax errors, the NoMethodError is annotated to show the line where the error occured, and the surrounding context:
|
87
|
-
|
88
|
-
```
|
89
|
-
scratch.rb:7:in `call': undefined method `upcase' for nil:NilClass (NoMethodError)
|
90
|
-
|
91
|
-
|
92
|
-
1 class Pet
|
93
|
-
6 def call
|
94
|
-
❯ 7 puts "Come here #{@neam.upcase}"
|
95
|
-
8 end
|
96
|
-
9 end
|
97
|
-
```
|
98
|
-
|
99
84
|
## Sounds cool, but why isn't this baked into Ruby directly?
|
100
85
|
|
101
|
-
|
102
|
-
|
103
|
-
1. Get real world useage and feedback. If we gave you an awful suggestion, let us know! We try to handle lots of cases well, but maybe we could be better.
|
104
|
-
2. Prove out demand. If you like this idea, then vote for it by putting it in your Gemfile.
|
86
|
+
We are now talking about it https://bugs.ruby-lang.org/issues/18159#change-93682.
|
105
87
|
|
106
88
|
## Artificial Inteligence?
|
107
89
|
|
data/Rakefile
CHANGED
data/dead_end.gemspec
CHANGED
@@ -1,17 +1,17 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative
|
3
|
+
require_relative "lib/dead_end/version"
|
4
4
|
|
5
5
|
Gem::Specification.new do |spec|
|
6
|
-
spec.name
|
7
|
-
spec.version
|
8
|
-
spec.authors
|
9
|
-
spec.email
|
6
|
+
spec.name = "dead_end"
|
7
|
+
spec.version = DeadEnd::VERSION
|
8
|
+
spec.authors = ["schneems"]
|
9
|
+
spec.email = ["richard.schneeman+foo@gmail.com"]
|
10
10
|
|
11
|
-
spec.summary
|
12
|
-
spec.description
|
13
|
-
spec.homepage
|
14
|
-
spec.license
|
11
|
+
spec.summary = "Find syntax errors in your source in a snap"
|
12
|
+
spec.description = 'When you get an "unexpected end" in your syntax this gem helps you find it'
|
13
|
+
spec.homepage = "https://github.com/zombocom/dead_end.git"
|
14
|
+
spec.license = "MIT"
|
15
15
|
spec.required_ruby_version = Gem::Requirement.new(">= 2.5.0")
|
16
16
|
|
17
17
|
spec.metadata["homepage_uri"] = spec.homepage
|
@@ -19,10 +19,10 @@ Gem::Specification.new do |spec|
|
|
19
19
|
|
20
20
|
# Specify which files should be added to the gem when it is released.
|
21
21
|
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
22
|
-
spec.files
|
22
|
+
spec.files = Dir.chdir(File.expand_path("..", __FILE__)) do
|
23
23
|
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features|assets)/}) }
|
24
24
|
end
|
25
|
-
spec.bindir
|
26
|
-
spec.executables
|
25
|
+
spec.bindir = "exe"
|
26
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
27
27
|
spec.require_paths = ["lib"]
|
28
28
|
end
|
data/exe/dead_end
CHANGED
@@ -1,11 +1,10 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
require
|
3
|
+
require "pathname"
|
4
4
|
require "optparse"
|
5
|
-
require_relative "../lib/dead_end
|
5
|
+
require_relative "../lib/dead_end"
|
6
6
|
|
7
7
|
options = {}
|
8
|
-
options[:terminal] = true
|
9
8
|
options[:record_dir] = ENV["DEAD_END_RECORD_DIR"]
|
10
9
|
|
11
10
|
parser = OptionParser.new do |opts|
|
@@ -35,6 +34,8 @@ parser = OptionParser.new do |opts|
|
|
35
34
|
Options:
|
36
35
|
EOM
|
37
36
|
|
37
|
+
opts.version = DeadEnd::VERSION
|
38
|
+
|
38
39
|
opts.on("--help", "Help - displays this message") do |v|
|
39
40
|
puts opts
|
40
41
|
exit
|
@@ -44,6 +45,10 @@ parser = OptionParser.new do |opts|
|
|
44
45
|
options[:record_dir] = v
|
45
46
|
end
|
46
47
|
|
48
|
+
opts.on("--terminal", "Enable terminal highlighting") do |v|
|
49
|
+
options[:terminal] = true
|
50
|
+
end
|
51
|
+
|
47
52
|
opts.on("--no-terminal", "Disable terminal highlighting") do |v|
|
48
53
|
options[:terminal] = false
|
49
54
|
end
|
@@ -60,11 +65,17 @@ end
|
|
60
65
|
file = Pathname(file)
|
61
66
|
options[:record_dir] = "tmp" if ENV["DEBUG"]
|
62
67
|
|
63
|
-
|
68
|
+
warn "Record dir: #{options[:record_dir]}" if options[:record_dir]
|
64
69
|
|
65
|
-
DeadEnd.call(
|
70
|
+
display = DeadEnd.call(
|
66
71
|
source: file.read,
|
67
72
|
filename: file.expand_path,
|
68
|
-
terminal: options
|
73
|
+
terminal: options.fetch(:terminal, DeadEnd::DEFAULT_VALUE),
|
69
74
|
record_dir: options[:record_dir]
|
70
75
|
)
|
76
|
+
|
77
|
+
if display.document_ok?
|
78
|
+
exit(0)
|
79
|
+
else
|
80
|
+
exit(1)
|
81
|
+
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
|
2
|
+
|
3
3
|
module DeadEnd
|
4
4
|
# This class is useful for exploring contents before and after
|
5
5
|
# a block
|
@@ -9,10 +9,10 @@ module DeadEnd
|
|
9
9
|
#
|
10
10
|
# Example:
|
11
11
|
#
|
12
|
-
# def dog
|
13
|
-
# puts "bark"
|
14
|
-
# puts "bark"
|
15
|
-
# end
|
12
|
+
# def dog # 1
|
13
|
+
# puts "bark" # 2
|
14
|
+
# puts "bark" # 3
|
15
|
+
# end # 4
|
16
16
|
#
|
17
17
|
# scan = AroundBlockScan.new(
|
18
18
|
# code_lines: code_lines
|
@@ -22,13 +22,13 @@ module DeadEnd
|
|
22
22
|
# scan.scan_while { true }
|
23
23
|
#
|
24
24
|
# puts scan.before_index # => 0
|
25
|
-
# puts scan.after_index
|
25
|
+
# puts scan.after_index # => 3
|
26
26
|
#
|
27
27
|
# Contents can also be filtered using AroundBlockScan#skip
|
28
28
|
#
|
29
29
|
# To grab the next surrounding indentation use AroundBlockScan#scan_adjacent_indent
|
30
30
|
class AroundBlockScan
|
31
|
-
def initialize(code_lines
|
31
|
+
def initialize(code_lines:, block:)
|
32
32
|
@code_lines = code_lines
|
33
33
|
@orig_before_index = block.lines.first.index
|
34
34
|
@orig_after_index = block.lines.last.index
|
@@ -56,7 +56,7 @@ module DeadEnd
|
|
56
56
|
end_count = 0
|
57
57
|
@before_index = before_lines.reverse_each.take_while do |line|
|
58
58
|
next false if stop_next
|
59
|
-
next true if @skip_array.detect {|meth| line.send(meth) }
|
59
|
+
next true if @skip_array.detect { |meth| line.send(meth) }
|
60
60
|
|
61
61
|
kw_count += 1 if line.is_kw?
|
62
62
|
end_count += 1 if line.is_end?
|
@@ -65,14 +65,14 @@ module DeadEnd
|
|
65
65
|
end
|
66
66
|
|
67
67
|
block.call(line)
|
68
|
-
end.
|
68
|
+
end.last&.index
|
69
69
|
|
70
70
|
stop_next = false
|
71
71
|
kw_count = 0
|
72
72
|
end_count = 0
|
73
73
|
@after_index = after_lines.take_while do |line|
|
74
74
|
next false if stop_next
|
75
|
-
next true if @skip_array.detect {|meth| line.send(meth) }
|
75
|
+
next true if @skip_array.detect { |meth| line.send(meth) }
|
76
76
|
|
77
77
|
kw_count += 1 if line.is_kw?
|
78
78
|
end_count += 1 if line.is_end?
|
@@ -89,7 +89,7 @@ module DeadEnd
|
|
89
89
|
lines = []
|
90
90
|
kw_count = 0
|
91
91
|
end_count = 0
|
92
|
-
before_lines.
|
92
|
+
before_lines.reverse_each do |line|
|
93
93
|
next if line.empty?
|
94
94
|
break if line.indent < @orig_indent
|
95
95
|
next if line.indent != @orig_indent
|
@@ -109,8 +109,6 @@ module DeadEnd
|
|
109
109
|
kw_count = 0
|
110
110
|
end_count = 0
|
111
111
|
after_lines.each do |line|
|
112
|
-
# puts "line: #{line.number} #{line.original_line}, indent: #{line.indent}, #{line.empty?} #{line.indent == @orig_indent}"
|
113
|
-
|
114
112
|
next if line.empty?
|
115
113
|
break if line.indent < @orig_indent
|
116
114
|
next if line.indent != @orig_indent
|
@@ -124,14 +122,13 @@ module DeadEnd
|
|
124
122
|
|
125
123
|
lines << line
|
126
124
|
end
|
127
|
-
lines.select! {|line| !line.is_comment? }
|
128
125
|
|
129
126
|
lines
|
130
127
|
end
|
131
128
|
|
132
129
|
def on_falling_indent
|
133
130
|
last_indent = @orig_indent
|
134
|
-
before_lines.
|
131
|
+
before_lines.reverse_each do |line|
|
135
132
|
next if line.empty?
|
136
133
|
if line.indent < last_indent
|
137
134
|
yield line
|
@@ -150,7 +147,7 @@ module DeadEnd
|
|
150
147
|
end
|
151
148
|
|
152
149
|
def scan_neighbors
|
153
|
-
|
150
|
+
scan_while { |line| line.not_empty? && line.indent >= @orig_indent }
|
154
151
|
end
|
155
152
|
|
156
153
|
def next_up
|
@@ -167,13 +164,14 @@ module DeadEnd
|
|
167
164
|
before_after_indent << (next_down&.indent || 0)
|
168
165
|
|
169
166
|
indent = before_after_indent.min
|
170
|
-
|
167
|
+
scan_while { |line| line.not_empty? && line.indent >= indent }
|
171
168
|
|
172
169
|
self
|
173
170
|
end
|
174
171
|
|
175
172
|
def start_at_next_line
|
176
|
-
before_index
|
173
|
+
before_index
|
174
|
+
after_index
|
177
175
|
@before_index -= 1
|
178
176
|
@after_index += 1
|
179
177
|
self
|
data/lib/dead_end/auto.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
|
2
|
+
|
3
3
|
require_relative "../dead_end/internals"
|
4
4
|
|
5
5
|
# Monkey patch kernel to ensure that all `require` calls call the same
|
@@ -40,6 +40,7 @@ end
|
|
40
40
|
# am I doing something different?
|
41
41
|
class Object
|
42
42
|
private
|
43
|
+
|
43
44
|
def load(path, wrap = false)
|
44
45
|
Kernel.load(path, wrap)
|
45
46
|
rescue SyntaxError => e
|
@@ -52,53 +53,3 @@ class Object
|
|
52
53
|
DeadEnd.handle_error(e)
|
53
54
|
end
|
54
55
|
end
|
55
|
-
|
56
|
-
module DeadEnd
|
57
|
-
IsProduction = -> {
|
58
|
-
ENV["RAILS_ENV"] == "production" || ENV["RACK_ENV"] == "production"
|
59
|
-
}
|
60
|
-
end
|
61
|
-
|
62
|
-
# Unlike a syntax error, a NoMethodError can occur hundreds or thousands of times and
|
63
|
-
# chew up CPU and other resources. Since this is primarilly a "development" optimization
|
64
|
-
# we can attempt to disable this behavior in a production context.
|
65
|
-
if !DeadEnd::IsProduction.call
|
66
|
-
class NoMethodError
|
67
|
-
alias :dead_end_original_to_s :to_s
|
68
|
-
|
69
|
-
def to_s
|
70
|
-
return super if DeadEnd::IsProduction.call
|
71
|
-
|
72
|
-
file, line, _ = backtrace[0].split(":")
|
73
|
-
return super if !File.exist?(file)
|
74
|
-
|
75
|
-
index = line.to_i - 1
|
76
|
-
source = File.read(file)
|
77
|
-
code_lines = DeadEnd::CodeLine.parse(source)
|
78
|
-
|
79
|
-
block = DeadEnd::CodeBlock.new(lines: code_lines[index])
|
80
|
-
lines = DeadEnd::CaptureCodeContext.new(
|
81
|
-
blocks: block,
|
82
|
-
code_lines: code_lines
|
83
|
-
).call
|
84
|
-
|
85
|
-
message = super.dup
|
86
|
-
message << $/
|
87
|
-
message << $/
|
88
|
-
|
89
|
-
message << DeadEnd::DisplayCodeWithLineNumbers.new(
|
90
|
-
lines: lines,
|
91
|
-
highlight_lines: block.lines,
|
92
|
-
terminal: self.class.to_tty?
|
93
|
-
).call
|
94
|
-
|
95
|
-
message << $/
|
96
|
-
message
|
97
|
-
rescue => e
|
98
|
-
puts "DeadEnd Internal error: #{e.dead_end_original_to_s}"
|
99
|
-
puts "DeadEnd Internal backtrace:"
|
100
|
-
puts backtrace.map {|l| " " + l }.join($/)
|
101
|
-
super
|
102
|
-
end
|
103
|
-
end
|
104
|
-
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DeadEnd
|
4
|
+
class Banner
|
5
|
+
attr_reader :invalid_obj
|
6
|
+
|
7
|
+
def initialize(invalid_obj:)
|
8
|
+
@invalid_obj = invalid_obj
|
9
|
+
end
|
10
|
+
|
11
|
+
def call
|
12
|
+
case invalid_obj.error_symbol
|
13
|
+
when :missing_end
|
14
|
+
<<~EOM
|
15
|
+
DeadEnd: Missing `end` detected
|
16
|
+
|
17
|
+
This code has a missing `end`. Ensure that all
|
18
|
+
syntax keywords (`def`, `do`, etc.) have a matching `end`.
|
19
|
+
EOM
|
20
|
+
when :unmatched_syntax
|
21
|
+
case unmatched_symbol
|
22
|
+
when :end
|
23
|
+
<<~EOM
|
24
|
+
DeadEnd: Unmatched `end` detected
|
25
|
+
|
26
|
+
This code has an unmatched `end`. Ensure that all `end` lines
|
27
|
+
in your code have a matching syntax keyword (`def`, `do`, etc.)
|
28
|
+
and that you don't have any extra `end` lines.
|
29
|
+
EOM
|
30
|
+
when :|
|
31
|
+
<<~EOM
|
32
|
+
DeadEnd: Unmatched `|` character detected
|
33
|
+
|
34
|
+
Example:
|
35
|
+
|
36
|
+
`do |x` should be `do |x|`
|
37
|
+
EOM
|
38
|
+
when *WhoDisSyntaxError::CHARACTERS.keys
|
39
|
+
<<~EOM
|
40
|
+
DeadEnd: Unmatched `#{unmatched_symbol}` character detected
|
41
|
+
|
42
|
+
It appears a `#{missing_character}` might be missing.
|
43
|
+
EOM
|
44
|
+
else
|
45
|
+
"DeadEnd: Unmatched `#{unmatched_symbol}` detected"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
private def unmatched_symbol
|
51
|
+
invalid_obj.unmatched_symbol
|
52
|
+
end
|
53
|
+
|
54
|
+
private def missing_character
|
55
|
+
WhoDisSyntaxError::CHARACTERS[unmatched_symbol]
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module DeadEnd
|
3
4
|
# This class is responsible for taking a code block that exists
|
4
5
|
# at a far indentaion and then iteratively increasing the block
|
@@ -30,7 +31,7 @@ module DeadEnd
|
|
30
31
|
# end
|
31
32
|
#
|
32
33
|
class BlockExpand
|
33
|
-
def initialize(code_lines:
|
34
|
+
def initialize(code_lines:)
|
34
35
|
@code_lines = code_lines
|
35
36
|
end
|
36
37
|
|
@@ -43,7 +44,7 @@ module DeadEnd
|
|
43
44
|
end
|
44
45
|
|
45
46
|
def expand_indent(block)
|
46
|
-
|
47
|
+
AroundBlockScan.new(code_lines: @code_lines, block: block)
|
47
48
|
.skip(:hidden?)
|
48
49
|
.stop_after_kw
|
49
50
|
.scan_adjacent_indent
|
@@ -59,15 +60,15 @@ module DeadEnd
|
|
59
60
|
# Slurp up empties
|
60
61
|
if grab_empty
|
61
62
|
scan = AroundBlockScan.new(code_lines: @code_lines, block: scan.code_block)
|
62
|
-
.scan_while {|line| line.empty? || line.hidden? }
|
63
|
+
.scan_while { |line| line.empty? || line.hidden? }
|
63
64
|
end
|
64
65
|
|
65
66
|
new_block = scan.code_block
|
66
67
|
|
67
68
|
if block.lines == new_block.lines
|
68
|
-
|
69
|
+
nil
|
69
70
|
else
|
70
|
-
|
71
|
+
new_block
|
71
72
|
end
|
72
73
|
end
|
73
74
|
end
|