diff --git a/CHANGELOG.md b/CHANGELOG.md index fcd790c..9dcee51 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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) diff --git a/README.md b/README.md index 3f21ae1..8cf2252 100644 --- a/README.md +++ b/README.md @@ -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? diff --git a/lib/dead_end/auto.rb b/lib/dead_end/auto.rb index 67e23ac..4c0b601 100644 --- a/lib/dead_end/auto.rb +++ b/lib/dead_end/auto.rb @@ -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 diff --git a/spec/integration/ruby_command_line_spec.rb b/spec/integration/ruby_command_line_spec.rb index bdda039..acadfde 100644 --- a/spec/integration/ruby_command_line_spec.rb +++ b/spec/integration/ruby_command_line_spec.rb @@ -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)