Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
## HEAD (unreleased)

- Remove NoMethodError patching instead use https://github.com/ruby/error_highlight/ (https://github.com/zombocom/dead_end/pull/71)

## 1.1.7

- Fix sinatra support for `require_relative` (https://github.com/zombocom/dead_end/pull/63)
Expand Down
20 changes: 1 addition & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,27 +81,9 @@ end

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.

## What other errors does it handle?

In addition to syntax errors, the NoMethodError is annotated to show the line where the error occured, and the surrounding context:

```
scratch.rb:7:in `call': undefined method `upcase' for nil:NilClass (NoMethodError)


1 class Pet
6 def call
❯ 7 puts "Come here #{@neam.upcase}"
8 end
9 end
```

## Sounds cool, but why isn't this baked into Ruby directly?

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:

1. Get real world usage 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.
2. Prove out demand. If you like this idea, then vote for it by putting it in your Gemfile.
We are now talking about it https://bugs.ruby-lang.org/issues/18159#change-93682.

## Artificial Inteligence?

Expand Down
49 changes: 0 additions & 49 deletions lib/dead_end/auto.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,52 +53,3 @@ def require(path)
end
end

module DeadEnd
IsProduction = -> {
ENV["RAILS_ENV"] == "production" || ENV["RACK_ENV"] == "production"
}
end

# Unlike a syntax error, a NoMethodError can occur hundreds or thousands of times and
# chew up CPU and other resources. Since this is primarilly a "development" optimization
# we can attempt to disable this behavior in a production context.
if !DeadEnd::IsProduction.call
class NoMethodError
alias :dead_end_original_to_s :to_s

def to_s
return super if DeadEnd::IsProduction.call

file, line, _ = backtrace[0].split(":")
return super if !File.exist?(file)

index = line.to_i - 1
source = File.read(file)
code_lines = DeadEnd::CodeLine.parse(source)

block = DeadEnd::CodeBlock.new(lines: code_lines[index])
lines = DeadEnd::CaptureCodeContext.new(
blocks: block,
code_lines: code_lines
).call

message = super.dup
message << $/
message << $/

message << DeadEnd::DisplayCodeWithLineNumbers.new(
lines: lines,
highlight_lines: block.lines,
terminal: self.class.to_tty?
).call

message << $/
message
rescue => e
puts "DeadEnd Internal error: #{e.dead_end_original_to_s}"
puts "DeadEnd Internal backtrace:"
puts backtrace.map {|l| " " + l }.join($/)
super
end
end
end
78 changes: 0 additions & 78 deletions spec/integration/ruby_command_line_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,84 +29,6 @@ module DeadEnd
end
end

it "does not get in an infinite loop when NoMethodError is raised internally" do
Dir.mktmpdir do |dir|
@tmpdir = Pathname(dir)
@script = @tmpdir.join("script.rb")
@script.write <<~'EOM'
class DeadEnd::DisplayCodeWithLineNumbers
def call
raise NoMethodError.new("foo")
end
end
class Pet
def initialize
@name = "cinco"
end
def call
puts "Come here #{@neam.upcase}"
end
end
Pet.new.call
EOM

out = `ruby -I#{lib_dir} -rdead_end/auto #{@script} 2>&1`

expect(out).to include("DeadEnd Internal error: foo")
expect(out).to include("DeadEnd Internal backtrace")
expect($?.success?).to be_falsey
end
end

it "annotates NoMethodError" do
Dir.mktmpdir do |dir|
@tmpdir = Pathname(dir)
@script = @tmpdir.join("script.rb")
@script.write <<~'EOM'
class Pet
def initialize
@name = "cinco"
end
def call
puts "Come here #{@neam.upcase}"
end
end
Pet.new.call
EOM

out = `ruby -I#{lib_dir} -rdead_end/auto #{@script} 2>&1`

error_line = <<~'EOM'
❯ 7 puts "Come here #{@neam.upcase}"
EOM

expect(out).to include("NoMethodError")
expect(out).to include(error_line)
expect(out).to include(<<~'EOM')
1 class Pet
6 def call
❯ 7 puts "Come here #{@neam.upcase}"
8 end
9 end
EOM
expect($?.success?).to be_falsey

# Test production check
out = `RAILS_ENV=production ruby -I#{lib_dir} -rdead_end/auto #{@script} 2>&1`
expect(out).to include("NoMethodError")
expect(out).to_not include(error_line)

out = `RACK_ENV=production ruby -I#{lib_dir} -rdead_end/auto #{@script} 2>&1`
expect(out).to include("NoMethodError")
expect(out).to_not include(error_line)
end
end

it "detects require error and adds a message with auto mode" do
Dir.mktmpdir do |dir|
@tmpdir = Pathname(dir)
Expand Down