Skip to content

Commit

Permalink
Fix usage of tracer gem and add tests
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
nunosilva800 committed Feb 5, 2024
1 parent 1b11fd9 commit b658e7c
Show file tree
Hide file tree
Showing 8 changed files with 120 additions and 56 deletions.
4 changes: 3 additions & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,19 @@ jobs:
run: bundle exec rubocop
irb:
needs: ruby-versions
name: rake test ${{ matrix.ruby }} ${{ matrix.with_latest_reline && '(latest reline)' || '' }}
name: rake test ${{ matrix.ruby }} ${{ matrix.with_latest_reline && '(latest reline)' || '' }} ${{ matrix.with_tracer && '(with tracer)' || '' }}
strategy:
matrix:
ruby: ${{ fromJson(needs.ruby-versions.outputs.versions) }}
with_latest_reline: [true, false]
with_tracer: [true, false]
exclude:
- ruby: truffleruby
fail-fast: false
runs-on: ubuntu-latest
env:
WITH_LATEST_RELINE: ${{matrix.with_latest_reline}}
WITH_TRACER: ${{matrix.with_tracer}}
timeout-minutes: 30
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
Expand Down
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ gem "test-unit-ruby-core"

gem "rubocop"

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

if RUBY_VERSION >= "3.0.0" && !is_truffleruby
Expand Down
5 changes: 5 additions & 0 deletions lib/irb/context.rb
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,11 @@ def initialize(irb, workspace = nil, input_method = nil)

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
Expand Down
60 changes: 7 additions & 53 deletions lib/irb/ext/tracer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,76 +3,30 @@
# irb/lib/tracer.rb -
# by Keiju ISHITSUKA([email protected])
#

# 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
1 change: 0 additions & 1 deletion lib/irb/extend-command.rb
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,6 @@ module ContextExtender

@EXTEND_COMMANDS = [
[:eval_history=, "ext/eval_history.rb"],
[:use_tracer=, "ext/tracer.rb"],
[:use_loader=, "ext/use-loader.rb"],
]

Expand Down
2 changes: 1 addition & 1 deletion test/irb/test_context.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# frozen_string_literal: false
require 'tempfile'
require 'irb'
require 'rubygems' if defined?(Gem)
require 'rubygems'

require_relative "helper"

Expand Down
6 changes: 6 additions & 0 deletions test/irb/test_init.rb
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,12 @@ def test_dash
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)
Expand Down
97 changes: 97 additions & 0 deletions test/irb/test_tracer.rb
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit b658e7c

Please sign in to comment.