dead_end 1.1.5 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8e2b1b2c93acbc5dde38ac7da8fc9dee057389e676bde9eb95683395b6b78ad8
4
- data.tar.gz: 0ef003bc94de8db02a1a0573bc77a0045b63207c6dd24557ec8f7b9dc76383f0
3
+ metadata.gz: 9fb84957790492d9f453b8863ea276ffc603ccb365fee3621f322e3f19e172e5
4
+ data.tar.gz: 798626bcc0dfa8457ef1fed8fb9ab8c9783a12ee109d94310a0cf787b2a0491a
5
5
  SHA512:
6
- metadata.gz: 8a6f4849d79629110326aba138ab290ca0bdc9eedf427b13b21ed1cbae084be28d017bf20644684552dbb660bd9547b514951eb909cc894304d25db8b020310b
7
- data.tar.gz: 8f1056255fa656d206e1e2b4160b903b6d88d60043f150e1fbf943a852901488e52e0819fd29bb059109ff015e01a7167688010733d49b81057bb62d2d000bd0
6
+ metadata.gz: 44624834e772d2c0d5c0035eb373571cb379cf6417a1d3422528f312c06771ef00c45e3c1ceebb8f78fa4ebce232fd99798f957c408a8a3a78710e65f18da7ce
7
+ data.tar.gz: 478fce76c26ffcf975111bb51a8ea71c20aa0ecbabb606d621d715e3d7055a818e82e5b1bc11cc7143e5cd4e120da257c1b33dc30a1b07356dacb782ad7299bf
data/.circleci/config.yml CHANGED
@@ -7,15 +7,12 @@ references:
7
7
  name: Run test suite
8
8
  command: bundle exec rspec spec/
9
9
 
10
- jobs:
11
- "ruby-2-5":
12
- docker:
13
- - image: circleci/ruby:2.5
14
- steps:
15
- - checkout
16
- - ruby/install-deps
17
- - <<: *unit
10
+ lint: &lint
11
+ run:
12
+ name: Run linter, fix with `standardrb --fix` locally
13
+ command: bundle exec standardrb
18
14
 
15
+ jobs:
19
16
  "ruby-2-6":
20
17
  docker:
21
18
  - image: circleci/ruby:2.6
@@ -40,11 +37,19 @@ jobs:
40
37
  - ruby/install-deps
41
38
  - <<: *unit
42
39
 
40
+ "lint":
41
+ docker:
42
+ - image: circleci/ruby:3.0
43
+ steps:
44
+ - checkout
45
+ - ruby/install-deps
46
+ - <<: *lint
47
+
43
48
  workflows:
44
49
  version: 2
45
50
  build:
46
51
  jobs:
47
- - "ruby-2-5"
48
52
  - "ruby-2-6"
49
53
  - "ruby-2-7"
50
54
  - "ruby-3-0"
55
+ - "lint"
data/.standard.yml ADDED
@@ -0,0 +1 @@
1
+ ruby_version: 2.6.6
data/CHANGELOG.md CHANGED
@@ -1,8 +1,28 @@
1
1
  ## HEAD (unreleased)
2
2
 
3
+ ## 2.0.0
4
+
5
+ - Support "endless" oneline method definitions for Ruby 3+ (https://github.com/zombocom/dead_end/pull/80)
6
+ - Reduce timeout to 1 second (https://github.com/zombocom/dead_end/pull/79)
7
+ - Logically consecutive lines (such as chained methods are now joined) (https://github.com/zombocom/dead_end/pull/78)
8
+ - Output improvement for cases where the only line is an single `end` (https://github.com/zombocom/dead_end/pull/78)
9
+
10
+ ## 1.2.0
11
+
12
+ - Output improvements via less greedy unmatched kw capture https://github.com/zombocom/dead_end/pull/73
13
+ - Remove NoMethodError patching instead use https://github.com/ruby/error_highlight/ (https://github.com/zombocom/dead_end/pull/71)
14
+
15
+ ## 1.1.7
16
+
17
+ - Fix sinatra support for `require_relative` (https://github.com/zombocom/dead_end/pull/63)
18
+
19
+ ## 1.1.6
20
+
21
+ - Consider if syntax error caused an unexpected variable instead of end (https://github.com/zombocom/dead_end/pull/58)
22
+
3
23
  ## 1.1.5
4
24
 
5
- - Source code with multiple syntax errors will be indentified by their first syntax error (https://github.com/zombocom/dead_end/pull/57)
25
+ - Parse error once and not twice if there's more than one available (https://github.com/zombocom/dead_end/pull/57)
6
26
 
7
27
  ## 1.1.4
8
28
 
data/Gemfile CHANGED
@@ -8,3 +8,4 @@ gemspec
8
8
  gem "rake", "~> 12.0"
9
9
  gem "rspec", "~> 3.0"
10
10
  gem "stackprof"
11
+ gem "standard"
data/Gemfile.lock CHANGED
@@ -1,13 +1,20 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- dead_end (1.1.5)
4
+ dead_end (2.0.0)
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.9
63
+ 2.2.27
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
- I would love to get something like this directly in Ruby, but I first need to prove it's useful. The `did_you_mean` functionality started as a gem that was eventually adopted by a bunch of people and then Ruby core liked it enough that they included it in the source. The goal of this gem is to:
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
@@ -5,4 +5,4 @@ require "rspec/core/rake_task"
5
5
 
6
6
  RSpec::Core::RakeTask.new(:spec)
7
7
 
8
- task :default => :spec
8
+ task default: :spec
data/dead_end.gemspec CHANGED
@@ -1,17 +1,17 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'lib/dead_end/version'
3
+ require_relative "lib/dead_end/version"
4
4
 
5
5
  Gem::Specification.new do |spec|
6
- spec.name = "dead_end"
7
- spec.version = DeadEnd::VERSION
8
- spec.authors = ["schneems"]
9
- spec.email = ["richard.schneeman+foo@gmail.com"]
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 = %q{Find syntax errors in your source in a snap}
12
- spec.description = %q{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"
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 = Dir.chdir(File.expand_path('..', __FILE__)) do
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 = "exe"
26
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
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,8 +1,8 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require 'pathname'
3
+ require "pathname"
4
4
  require "optparse"
5
- require_relative "../lib/dead_end.rb"
5
+ require_relative "../lib/dead_end"
6
6
 
7
7
  options = {}
8
8
  options[:terminal] = true
@@ -60,7 +60,7 @@ end
60
60
  file = Pathname(file)
61
61
  options[:record_dir] = "tmp" if ENV["DEBUG"]
62
62
 
63
- $stderr.puts "Record dir: #{options[:record_dir]}" if options[:record_dir]
63
+ warn "Record dir: #{options[:record_dir]}" if options[:record_dir]
64
64
 
65
65
  DeadEnd.call(
66
66
  source: file.read,
@@ -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 # => 3
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: , block:)
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.reverse.first&.index
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.reverse.each do |line|
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.reverse.each do |line|
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
- self.scan_while {|line| line.not_empty? && line.indent >= @orig_indent }
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
- self.scan_while {|line| line.not_empty? && line.indent >= indent }
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; after_index
173
+ before_index
174
+ after_index
177
175
  @before_index -= 1
178
176
  @after_index += 1
179
177
  self
@@ -196,7 +194,7 @@ module DeadEnd
196
194
  end
197
195
 
198
196
  private def after_lines
199
- @code_lines[after_index.next..-1] || []
197
+ @code_lines[after_index.next..] || []
200
198
  end
201
199
  end
202
200
  end
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
@@ -27,7 +27,7 @@ module Kernel
27
27
  if Pathname.new(file).absolute?
28
28
  dead_end_original_require file
29
29
  else
30
- dead_end_original_require File.expand_path("../#{file}", caller_locations(1, 1)[0].absolute_path)
30
+ dead_end_original_require File.expand_path("../#{file}", Kernel.caller_locations(1, 1)[0].absolute_path)
31
31
  end
32
32
  rescue SyntaxError => e
33
33
  DeadEnd.handle_error(e)
@@ -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
@@ -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
- block = AroundBlockScan.new(code_lines: @code_lines, block: block)
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
- return nil
69
+ nil
69
70
  else
70
- return new_block
71
+ new_block
71
72
  end
72
73
  end
73
74
  end