Skip to content

Commit 08834fb

Browse files
authored
Fix usage of tracer gem and add tests (#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.
1 parent af1d83b commit 08834fb

File tree

8 files changed

+120
-56
lines changed

8 files changed

+120
-56
lines changed

.github/workflows/test.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,17 +25,19 @@ jobs:
2525
run: bundle exec rubocop
2626
irb:
2727
needs: ruby-versions
28-
name: rake test ${{ matrix.ruby }} ${{ matrix.with_latest_reline && '(latest reline)' || '' }}
28+
name: rake test ${{ matrix.ruby }} ${{ matrix.with_latest_reline && '(latest reline)' || '' }} ${{ matrix.with_tracer && '(with tracer)' || '' }}
2929
strategy:
3030
matrix:
3131
ruby: ${{ fromJson(needs.ruby-versions.outputs.versions) }}
3232
with_latest_reline: [true, false]
33+
with_tracer: [true, false]
3334
exclude:
3435
- ruby: truffleruby
3536
fail-fast: false
3637
runs-on: ubuntu-latest
3738
env:
3839
WITH_LATEST_RELINE: ${{matrix.with_latest_reline}}
40+
WITH_TRACER: ${{matrix.with_tracer}}
3941
timeout-minutes: 30
4042
steps:
4143
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11

Gemfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ gem "test-unit-ruby-core"
1919

2020
gem "rubocop"
2121

22+
gem "tracer" if ENV["WITH_TRACER"] == "true"
2223
gem "debug", github: "ruby/debug", platforms: [:mri, :mswin]
2324

2425
if RUBY_VERSION >= "3.0.0" && !is_truffleruby

lib/irb/context.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,11 @@ def initialize(irb, workspace = nil, input_method = nil)
161161

162162
private_constant :KEYWORD_ALIASES
163163

164+
def use_tracer=(val)
165+
require_relative "ext/tracer"
166+
@use_tracer = val
167+
end
168+
164169
private def build_completor
165170
completor_type = IRB.conf[:COMPLETOR]
166171
case completor_type

lib/irb/ext/tracer.rb

Lines changed: 7 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -3,76 +3,30 @@
33
# irb/lib/tracer.rb -
44
# by Keiju ISHITSUKA(keiju@ruby-lang.org)
55
#
6-
6+
# Loading the gem "tracer" will cause it to extend IRB commands with:
7+
# https://github.com/ruby/tracer/blob/v0.2.2/lib/tracer/irb.rb
78
begin
89
require "tracer"
910
rescue LoadError
1011
$stderr.puts "Tracer extension of IRB is enabled but tracer gem wasn't found."
11-
module IRB
12-
class Context
13-
def use_tracer=(opt)
14-
# do nothing
15-
end
16-
end
17-
end
1812
return # This is about to disable loading below
1913
end
2014

2115
module IRB
22-
23-
# initialize tracing function
24-
def IRB.initialize_tracer
25-
Tracer.verbose = false
26-
Tracer.add_filter {
27-
|event, file, line, id, binding, *rests|
28-
/^#{Regexp.quote(@CONF[:IRB_LIB_PATH])}/ !~ file and
29-
File::basename(file) != "irb.rb"
30-
}
31-
end
32-
33-
class Context
34-
# Whether Tracer is used when evaluating statements in this context.
35-
#
36-
# See +lib/tracer.rb+ for more information.
37-
attr_reader :use_tracer
38-
alias use_tracer? use_tracer
39-
40-
# Sets whether or not to use the Tracer library when evaluating statements
41-
# in this context.
42-
#
43-
# See +lib/tracer.rb+ for more information.
44-
def use_tracer=(opt)
45-
if opt
46-
Tracer.set_get_line_procs(@irb_path) {
47-
|line_no, *rests|
48-
@io.line(line_no)
49-
}
50-
elsif !opt && @use_tracer
51-
Tracer.off
52-
end
53-
@use_tracer=opt
54-
end
55-
end
56-
5716
class WorkSpace
5817
alias __evaluate__ evaluate
5918
# Evaluate the context of this workspace and use the Tracer library to
6019
# output the exact lines of code are being executed in chronological order.
6120
#
62-
# See +lib/tracer.rb+ for more information.
63-
def evaluate(context, statements, file = nil, line = nil)
64-
if context.use_tracer? && file != nil && line != nil
65-
Tracer.on
66-
begin
21+
# See https://github.com/ruby/tracer for more information.
22+
def evaluate(statements, file = __FILE__, line = __LINE__)
23+
if IRB.conf[:USE_TRACER] == true
24+
CallTracer.new(colorize: Color.colorable?).start do
6725
__evaluate__(statements, file, line)
68-
ensure
69-
Tracer.off
7026
end
7127
else
72-
__evaluate__(statements, file || __FILE__, line || __LINE__)
28+
__evaluate__(statements, file, line)
7329
end
7430
end
7531
end
76-
77-
IRB.initialize_tracer
7832
end

lib/irb/extend-command.rb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -317,7 +317,6 @@ module ContextExtender
317317

318318
@EXTEND_COMMANDS = [
319319
[:eval_history=, "ext/eval_history.rb"],
320-
[:use_tracer=, "ext/tracer.rb"],
321320
[:use_loader=, "ext/use-loader.rb"],
322321
]
323322

test/irb/test_context.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# frozen_string_literal: false
22
require 'tempfile'
33
require 'irb'
4-
require 'rubygems' if defined?(Gem)
4+
require 'rubygems'
55

66
require_relative "helper"
77

test/irb/test_init.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,12 @@ def test_dash
216216
assert_equal(['-f'], argv)
217217
end
218218

219+
def test_option_tracer
220+
argv = %w[--tracer]
221+
IRB.setup(eval("__FILE__"), argv: argv)
222+
assert_equal(true, IRB.conf[:USE_TRACER])
223+
end
224+
219225
private
220226

221227
def with_argv(argv)

test/irb/test_tracer.rb

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
# frozen_string_literal: false
2+
require 'tempfile'
3+
require 'irb'
4+
require 'rubygems'
5+
6+
require_relative "helper"
7+
8+
module TestIRB
9+
class ContextWithTracerIntegrationTest < IntegrationTestCase
10+
def setup
11+
super
12+
13+
@envs.merge!("NO_COLOR" => "true", "RUBY_DEBUG_HISTORY_FILE" => '')
14+
end
15+
16+
def example_ruby_file
17+
<<~'RUBY'
18+
class Foo
19+
def self.foo
20+
100
21+
end
22+
end
23+
24+
def bar(obj)
25+
obj.foo
26+
end
27+
28+
binding.irb
29+
RUBY
30+
end
31+
32+
def test_use_tracer_is_disabled_by_default
33+
write_rc <<~RUBY
34+
IRB.conf[:USE_TRACER] = false
35+
RUBY
36+
37+
write_ruby example_ruby_file
38+
39+
output = run_ruby_file do
40+
type "bar(Foo)"
41+
type "exit!"
42+
end
43+
44+
assert_nil IRB.conf[:USER_TRACER]
45+
assert_not_include(output, "#depth:")
46+
assert_not_include(output, "Foo.foo")
47+
end
48+
49+
def test_use_tracer_enabled_when_gem_is_unavailable
50+
begin
51+
gem 'tracer'
52+
omit "Skipping because 'tracer' gem is available."
53+
rescue Gem::LoadError
54+
write_rc <<~RUBY
55+
IRB.conf[:USE_TRACER] = true
56+
RUBY
57+
58+
write_ruby example_ruby_file
59+
60+
output = run_ruby_file do
61+
type "bar(Foo)"
62+
type "exit!"
63+
end
64+
65+
assert_include(output, "Tracer extension of IRB is enabled but tracer gem wasn't found.")
66+
end
67+
end
68+
69+
def test_use_tracer_enabled_when_gem_is_available
70+
if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('3.1.0')
71+
omit "Ruby version before 3.1.0 does not support Tracer integration. Skipping this test."
72+
end
73+
74+
begin
75+
gem 'tracer'
76+
rescue Gem::LoadError
77+
omit "Skipping because 'tracer' gem is not available. Enable with WITH_TRACER=true."
78+
end
79+
80+
write_rc <<~RUBY
81+
IRB.conf[:USE_TRACER] = true
82+
RUBY
83+
84+
write_ruby example_ruby_file
85+
86+
output = run_ruby_file do
87+
type "bar(Foo)"
88+
type "exit!"
89+
end
90+
91+
assert_include(output, "Object#bar at")
92+
assert_include(output, "Foo.foo at")
93+
assert_include(output, "Foo.foo #=> 100")
94+
assert_include(output, "Object#bar #=> 100")
95+
end
96+
end
97+
end

0 commit comments

Comments
 (0)