[ruby/irb] Fix usage of tracer gem and add tests

(https://github.com/ruby/irb/pull/857)

The new tests are skipped when ruby below 3.1, as it was a default gem on it, and in a version we do not support.

This also move definition of `use_tracer` to module Context instead of monkey patch.

08834fbd5f
This commit is contained in:
Nuno Silva 2024-02-06 16:46:41 +00:00 committed by git
parent 26fac8f6fa
commit 300dee1fe8
6 changed files with 116 additions and 55 deletions

View file

@ -161,6 +161,11 @@ module IRB
private_constant :KEYWORD_ALIASES
def use_tracer=(val)
require_relative "ext/tracer"
@use_tracer = val
end
private def build_completor
completor_type = IRB.conf[:COMPLETOR]
case completor_type

View file

@ -3,76 +3,30 @@
# irb/lib/tracer.rb -
# by Keiju ISHITSUKA(keiju@ruby-lang.org)
#
# Loading the gem "tracer" will cause it to extend IRB commands with:
# https://github.com/ruby/tracer/blob/v0.2.2/lib/tracer/irb.rb
begin
require "tracer"
rescue LoadError
$stderr.puts "Tracer extension of IRB is enabled but tracer gem wasn't found."
module IRB
class Context
def use_tracer=(opt)
# do nothing
end
end
end
return # This is about to disable loading below
end
module IRB
# initialize tracing function
def IRB.initialize_tracer
Tracer.verbose = false
Tracer.add_filter {
|event, file, line, id, binding, *rests|
/^#{Regexp.quote(@CONF[:IRB_LIB_PATH])}/ !~ file and
File::basename(file) != "irb.rb"
}
end
class Context
# Whether Tracer is used when evaluating statements in this context.
#
# See +lib/tracer.rb+ for more information.
attr_reader :use_tracer
alias use_tracer? use_tracer
# Sets whether or not to use the Tracer library when evaluating statements
# in this context.
#
# See +lib/tracer.rb+ for more information.
def use_tracer=(opt)
if opt
Tracer.set_get_line_procs(@irb_path) {
|line_no, *rests|
@io.line(line_no)
}
elsif !opt && @use_tracer
Tracer.off
end
@use_tracer=opt
end
end
class WorkSpace
alias __evaluate__ evaluate
# Evaluate the context of this workspace and use the Tracer library to
# output the exact lines of code are being executed in chronological order.
#
# See +lib/tracer.rb+ for more information.
def evaluate(context, statements, file = nil, line = nil)
if context.use_tracer? && file != nil && line != nil
Tracer.on
begin
# See https://github.com/ruby/tracer for more information.
def evaluate(statements, file = __FILE__, line = __LINE__)
if IRB.conf[:USE_TRACER] == true
CallTracer.new(colorize: Color.colorable?).start do
__evaluate__(statements, file, line)
ensure
Tracer.off
end
else
__evaluate__(statements, file || __FILE__, line || __LINE__)
__evaluate__(statements, file, line)
end
end
end
IRB.initialize_tracer
end

View file

@ -317,7 +317,6 @@ module IRB # :nodoc:
@EXTEND_COMMANDS = [
[:eval_history=, "ext/eval_history.rb"],
[:use_tracer=, "ext/tracer.rb"],
[:use_loader=, "ext/use-loader.rb"],
]

View file

@ -1,7 +1,7 @@
# frozen_string_literal: false
require 'tempfile'
require 'irb'
require 'rubygems' if defined?(Gem)
require 'rubygems'
require_relative "helper"

View file

@ -216,6 +216,12 @@ module TestIRB
assert_equal(['-f'], argv)
end
def test_option_tracer
argv = %w[--tracer]
IRB.setup(eval("__FILE__"), argv: argv)
assert_equal(true, IRB.conf[:USE_TRACER])
end
private
def with_argv(argv)

97
test/irb/test_tracer.rb Normal file
View file

@ -0,0 +1,97 @@
# frozen_string_literal: false
require 'tempfile'
require 'irb'
require 'rubygems'
require_relative "helper"
module TestIRB
class ContextWithTracerIntegrationTest < IntegrationTestCase
def setup
super
@envs.merge!("NO_COLOR" => "true", "RUBY_DEBUG_HISTORY_FILE" => '')
end
def example_ruby_file
<<~'RUBY'
class Foo
def self.foo
100
end
end
def bar(obj)
obj.foo
end
binding.irb
RUBY
end
def test_use_tracer_is_disabled_by_default
write_rc <<~RUBY
IRB.conf[:USE_TRACER] = false
RUBY
write_ruby example_ruby_file
output = run_ruby_file do
type "bar(Foo)"
type "exit!"
end
assert_nil IRB.conf[:USER_TRACER]
assert_not_include(output, "#depth:")
assert_not_include(output, "Foo.foo")
end
def test_use_tracer_enabled_when_gem_is_unavailable
begin
gem 'tracer'
omit "Skipping because 'tracer' gem is available."
rescue Gem::LoadError
write_rc <<~RUBY
IRB.conf[:USE_TRACER] = true
RUBY
write_ruby example_ruby_file
output = run_ruby_file do
type "bar(Foo)"
type "exit!"
end
assert_include(output, "Tracer extension of IRB is enabled but tracer gem wasn't found.")
end
end
def test_use_tracer_enabled_when_gem_is_available
if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('3.1.0')
omit "Ruby version before 3.1.0 does not support Tracer integration. Skipping this test."
end
begin
gem 'tracer'
rescue Gem::LoadError
omit "Skipping because 'tracer' gem is not available. Enable with WITH_TRACER=true."
end
write_rc <<~RUBY
IRB.conf[:USE_TRACER] = true
RUBY
write_ruby example_ruby_file
output = run_ruby_file do
type "bar(Foo)"
type "exit!"
end
assert_include(output, "Object#bar at")
assert_include(output, "Foo.foo at")
assert_include(output, "Foo.foo #=> 100")
assert_include(output, "Object#bar #=> 100")
end
end
end