Class: IRB::ExtendCommand::Debug
Do not use. This class is for internal use only.
Relationships & Source Files | |
Namespace Children | |
Modules:
| |
Extension / Inclusion / Inheritance Descendants | |
Subclasses:
|
|
Super Chains via Extension / Inclusion / Inheritance | |
Class Chain:
self,
Nop
|
|
Instance Chain:
self,
Nop
|
|
Inherits: |
IRB::ExtendCommand::Nop
|
Defined in: | lib/irb/cmd/debug.rb |
Constant Summary
-
BINDING_IRB_FRAME_REGEXPS =
# File 'lib/irb/cmd/debug.rb', line 11[ '<internal:prelude>', binding.method(:irb).source_location.first, ].map { |file| /\A#{Regexp.escape(file)}:\d+:in `irb'\z/ }
-
IRB_DIR =
# File 'lib/irb/cmd/debug.rb', line 15File. ('..', __dir__)
Class Method Summary
Nop
- Inherited
.category, .description, | |
.execute | See additional method definition at line 39. |
.new, .string_literal? |
Instance Attribute Summary
Instance Method Summary
- #execute(pre_cmds: nil, do_cmds: nil)
-
#load_bundled_debug_gem
This is used when debug.gem is not written in Gemfile.
- #setup_debugger
Nop
- Inherited
Constructor Details
This class inherits a constructor from IRB::ExtendCommand::Nop
Instance Attribute Details
#binding_irb? ⇒ Boolean
(readonly, private)
[ GitHub ]
# File 'lib/irb/cmd/debug.rb', line 50
def binding_irb? caller.any? do |frame| BINDING_IRB_FRAME_REGEXPS.any? do |regexp| frame.match?(regexp) end end end
Instance Method Details
#execute(pre_cmds: nil, do_cmds: nil)
[ GitHub ]# File 'lib/irb/cmd/debug.rb', line 17
def execute(pre_cmds: nil, do_cmds: nil) unless binding_irb? puts "`debug` command is only available when IRB is started with binding.irb" return end unless setup_debugger puts <<~MSG You need to install the debug gem before using this command. If you use `bundle exec`, please add `gem "debug"` into your Gemfile. MSG return end = { oneshot: true, hook_call: false } if pre_cmds || do_cmds [:command] = ['irb', pre_cmds, do_cmds] end if DEBUGGER__::LineBreakpoint.instance_method(:initialize).parameters.include?([:key, :skip_src]) [:skip_src] = true end # To make debugger commands like `next` or `continue` work without asking # the user to quit IRB after that, we need to exit IRB first and then hit # a TracePoint on #debug_break. file, lineno = IRB::Irb.instance_method(:debug_break).source_location DEBUGGER__::SESSION.add_line_breakpoint(file, lineno + 1, ** ) # exit current Irb#run call throw :IRB_EXIT end
#load_bundled_debug_gem
This is used when debug.gem is not written in Gemfile. Even if it’s not installed by bundle install
, debug.gem is installed by default because it’s a bundled gem. This method tries to activate and load that.
# File 'lib/irb/cmd/debug.rb', line 95
def load_bundled_debug_gem # Discover latest debug.gem under GEM_PATH debug_gem = Gem.paths.path.flat_map { |path| Dir.glob("#{path}/gems/debug-*") }.select do |path| File.basename(path).match?(/\Adebug-\d\.\d\.\d(\w)?\z/) end.sort_by do |path| Gem::Version.new(File.basename(path).delete_prefix('debug-')) end.last return false unless debug_gem # Discover debug/debug.so under extensions for Ruby 3.2+ ext_name = "/debug/debug.#{RbConfig::CONFIG['DLEXT']}" ext_path = Gem.paths.path.flat_map do |path| Dir.glob("#{path}/extensions/**/#{File.basename(debug_gem)}#{ext_name}") end.first # Attempt to forcibly load the bundled gem if ext_path $LOAD_PATH << ext_path.delete_suffix(ext_name) end $LOAD_PATH << "#{debug_gem}/lib" begin require "debug/session" puts "Loaded #{File.basename(debug_gem)}" true rescue LoadError false end end
#setup_debugger
[ GitHub ]# File 'lib/irb/cmd/debug.rb', line 65
def setup_debugger unless defined?(DEBUGGER__::SESSION) begin require "debug/session" rescue LoadError # debug.gem is not written in Gemfile return false unless load_bundled_debug_gem end DEBUGGER__.start(nonstop: true) end unless DEBUGGER__.respond_to?(:capture_frames_without_irb) DEBUGGER__.singleton_class.send(:alias_method, :capture_frames_without_irb, :capture_frames) def DEBUGGER__.capture_frames(*args) frames = capture_frames_without_irb(*args) frames.reject! do |frame| frame.realpath&.start_with?(IRB_DIR) || frame.path == "<internal:prelude>" end frames end DEBUGGER__::ThreadClient.prepend(SkipPathHelperForIRB) end true end