ruby-debug-ide19 0.4.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. data/CHANGES +75 -0
  2. data/ChangeLog +465 -0
  3. data/ChangeLog.archive +1073 -0
  4. data/MIT-LICENSE +24 -0
  5. data/Rakefile +110 -0
  6. data/bin/rdebug-ide +88 -0
  7. data/ext/mkrf_conf.rb +28 -0
  8. data/lib/ruby-debug-ide.rb +172 -0
  9. data/lib/ruby-debug/command.rb +169 -0
  10. data/lib/ruby-debug/commands/breakpoints.rb +129 -0
  11. data/lib/ruby-debug/commands/catchpoint.rb +52 -0
  12. data/lib/ruby-debug/commands/condition.rb +51 -0
  13. data/lib/ruby-debug/commands/control.rb +129 -0
  14. data/lib/ruby-debug/commands/enable.rb +203 -0
  15. data/lib/ruby-debug/commands/eval.rb +64 -0
  16. data/lib/ruby-debug/commands/frame.rb +155 -0
  17. data/lib/ruby-debug/commands/inspect.rb +24 -0
  18. data/lib/ruby-debug/commands/jump.rb +73 -0
  19. data/lib/ruby-debug/commands/load.rb +18 -0
  20. data/lib/ruby-debug/commands/stepping.rb +108 -0
  21. data/lib/ruby-debug/commands/threads.rb +153 -0
  22. data/lib/ruby-debug/commands/variables.rb +136 -0
  23. data/lib/ruby-debug/event_processor.rb +74 -0
  24. data/lib/ruby-debug/helper.rb +33 -0
  25. data/lib/ruby-debug/interface.rb +39 -0
  26. data/lib/ruby-debug/printers.rb +2 -0
  27. data/lib/ruby-debug/processor.rb +152 -0
  28. data/lib/ruby-debug/xml_printer.rb +268 -0
  29. data/test/rd_basic_test.rb +10 -0
  30. data/test/rd_catchpoint_test.rb +20 -0
  31. data/test/rd_condition_test.rb +11 -0
  32. data/test/rd_enable_disable_test.rb +43 -0
  33. data/test/rd_inspect_test.rb +11 -0
  34. data/test/rd_stepping_breakpoints_test.rb +36 -0
  35. data/test/rd_test_base.rb +44 -0
  36. data/test/rd_threads_and_frames_test.rb +11 -0
  37. data/test/rd_variables_test.rb +11 -0
  38. data/test/ruby-debug/xml_printer_test.rb +105 -0
  39. metadata +103 -0
@@ -0,0 +1,24 @@
1
+ The file lib/classic-debug.rb is based on the debug.rb file from Ruby
2
+ project.
3
+
4
+ Copyright (c) 2007-2008, debug-commons team
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining
7
+ a copy of this software and associated documentation files (the
8
+ "Software"), to deal in the Software without restriction, including
9
+ without limitation the rights to use, copy, modify, merge, publish,
10
+ distribute, sublicense, and/or sell copies of the Software, and to
11
+ permit persons to whom the Software is furnished to do so, subject to
12
+ the following conditions:
13
+
14
+ The above copyright notice and this permission notice shall be
15
+ included in all copies or substantial portions of the Software.
16
+
17
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
+
@@ -0,0 +1,110 @@
1
+ require 'rubygems'
2
+
3
+ require 'rake/gempackagetask'
4
+ require 'rake/rdoctask'
5
+ require 'rake/testtask'
6
+ require 'date'
7
+
8
+ desc 'Default: run unit tests.'
9
+ task :default => [:test]
10
+
11
+ # ------- Default Package ----------
12
+ RUBY_DEBUG_IDE_VERSION = "0.4.10"
13
+
14
+ FILES = FileList[
15
+ 'CHANGES',
16
+ 'ChangeLog',
17
+ 'ChangeLog.archive',
18
+ 'MIT-LICENSE',
19
+ 'Rakefile',
20
+ 'bin/*',
21
+ 'lib/**/*',
22
+ 'test/**/*',
23
+ 'ext/mkrf_conf.rb'
24
+ ]
25
+
26
+ ide_spec = Gem::Specification.new do |spec|
27
+ spec.name = "ruby-debug-ide19"
28
+
29
+ spec.homepage = "http://rubyforge.org/projects/debug-commons/"
30
+ spec.summary = "IDE interface for ruby-debug."
31
+ spec.description = <<-EOF
32
+ An interface which glues ruby-debug to IDEs like Eclipse (RDT) and NetBeans.
33
+ EOF
34
+
35
+ spec.version = RUBY_DEBUG_IDE_VERSION
36
+
37
+ spec.author = "Markus Barchfeld, Martin Krauskopf"
38
+ spec.email = "rubyeclipse-dev-list@sourceforge.net"
39
+ spec.platform = Gem::Platform::RUBY
40
+ spec.require_path = "lib"
41
+ spec.bindir = "bin"
42
+ spec.executables = ["rdebug-ide"]
43
+ spec.files = FILES.to_a
44
+ spec.extensions << "ext/mkrf_conf.rb"
45
+ spec.add_dependency("rake", ">= 0.8.1")
46
+
47
+ spec.required_ruby_version = '>= 1.8.2'
48
+ spec.date = DateTime.now
49
+ spec.rubyforge_project = 'debug-commons'
50
+
51
+ # rdoc
52
+ spec.has_rdoc = false
53
+ end
54
+
55
+ # Rake task to build the default package
56
+ Rake::GemPackageTask.new(ide_spec) do |pkg|
57
+ pkg.need_tar = true
58
+ end
59
+
60
+ # Unit tests
61
+ Rake::TestTask.new do |t|
62
+ t.libs << "test"
63
+ t.libs << "test-base"
64
+ t.pattern = 'test/*_test.rb'
65
+ t.verbose = true
66
+ t.warning = false
67
+ end
68
+
69
+
70
+ desc "Create a GNU-style ChangeLog via svn2cl"
71
+ task :ChangeLog do
72
+ system("svn2cl --authors=svn2cl_usermap svn://rubyforge.org/var/svn/debug-commons/ruby-debug-ide/trunk -o ChangeLog")
73
+ end
74
+
75
+ #desc "Publish ruby-debug to RubyForge."
76
+ #task :publish do
77
+ # require 'rake/contrib/sshpublisher'
78
+ #
79
+ # # Get ruby-debug path
80
+ # ruby_debug_path = File.expand_path(File.dirname(__FILE__))
81
+ #
82
+ # publisher = Rake::SshDirPublisher.new("kent@rubyforge.org",
83
+ # "/var/www/gforge-projects/ruby-debug", ruby_debug_path)
84
+ #end
85
+ #
86
+ #desc "Clear temp files"
87
+ #task :clean do
88
+ # cd "ext" do
89
+ # if File.exists?("Makefile")
90
+ # sh "make clean"
91
+ # rm "Makefile"
92
+ # end
93
+ # end
94
+ #end
95
+ #
96
+ ## --------- RDoc Documentation ------
97
+ #desc "Generate rdoc documentation"
98
+ #Rake::RDocTask.new("rdoc") do |rdoc|
99
+ # rdoc.rdoc_dir = 'doc'
100
+ # rdoc.title = "ruby-debug"
101
+ # # Show source inline with line numbers
102
+ # rdoc.options << "--inline-source" << "--line-numbers"
103
+ # # Make the readme file the start page for the generated html
104
+ # rdoc.options << '--main' << 'README'
105
+ # rdoc.rdoc_files.include('bin/**/*',
106
+ # 'lib/**/*.rb',
107
+ # 'ext/**/ruby_debug.c',
108
+ # 'README',
109
+ # 'LICENSE')
110
+ #end
@@ -0,0 +1,88 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'optparse'
5
+ require "ostruct"
6
+ if RUBY_VERSION < "1.9"
7
+ require 'ruby-debug-ide'
8
+ else
9
+ require_relative '../lib/ruby-debug-ide'
10
+ end
11
+
12
+ $stdout.sync=true
13
+
14
+ options = OpenStruct.new(
15
+ 'frame_bind' => false,
16
+ 'host' => nil,
17
+ 'load_mode' => false,
18
+ 'port' => 1234,
19
+ 'stop' => false,
20
+ 'tracing' => false
21
+ )
22
+
23
+ opts = OptionParser.new do |opts|
24
+ opts.banner = <<EOB
25
+ Using ruby-debug-base #{Debugger::VERSION}
26
+ Usage: rdebug-ide is supposed to be called from RDT, NetBeans or RubyMine. The
27
+ command line interface to ruby-debug is rdebug.
28
+ EOB
29
+ opts.separator ""
30
+ opts.separator "Options:"
31
+ opts.on("-h", "--host HOST", "Host name used for remote debugging") {|host| options.host = host}
32
+ opts.on("-p", "--port PORT", Integer, "Port used for remote debugging") {|port| options.port = port}
33
+ opts.on('--stop', 'stop when the script is loaded') {options.stop = true}
34
+ opts.on("-x", "--trace", "turn on line tracing") {options.tracing = true}
35
+ opts.on("-l", "--load-mode", "load mode (experimental)") {options.load_mode = true}
36
+ opts.on("-d", "--debug", "Debug self - prints information for debugging ruby-debug itself") do
37
+ Debugger.cli_debug = true
38
+ end
39
+ opts.on("--xml-debug", "Debug self - sends information <message>s for debugging ruby-debug itself") do
40
+ Debugger.xml_debug = true
41
+ end
42
+ opts.on("-I", "--include PATH", String, "Add PATH to $LOAD_PATH") do |path|
43
+ $LOAD_PATH.unshift(path)
44
+ end
45
+
46
+ opts.on("--keep-frame-binding", "Keep frame bindings") {options.frame_bind = true}
47
+ opts.separator ""
48
+ opts.separator "Common options:"
49
+ opts.on_tail("-v", "--version", "Show version") do
50
+ puts "Using ruby-debug-base #{Debugger::VERSION}"
51
+ exit
52
+ end
53
+ end
54
+
55
+ begin
56
+ Debugger::ARGV = ARGV.clone
57
+ rdebug_path = File.expand_path($0)
58
+ if RUBY_PLATFORM =~ /mswin/
59
+ rdebug_path += ".cmd" unless rdebug_path =~ /\.cmd$/i
60
+ end
61
+ Debugger::RDEBUG_SCRIPT = rdebug_path
62
+ opts.parse! ARGV
63
+ rescue StandardError => e
64
+ puts opts
65
+ puts
66
+ puts e.message
67
+ exit(1)
68
+ end
69
+
70
+ if ARGV.empty?
71
+ puts opts
72
+ puts
73
+ puts "Must specify a script to run"
74
+ exit(1)
75
+ end
76
+
77
+ # save script name
78
+ Debugger::PROG_SCRIPT = ARGV.shift
79
+
80
+ # install interruption handler
81
+ trap('INT') { Debugger.interrupt_last }
82
+
83
+ # set options
84
+ Debugger.keep_frame_binding = options.frame_bind
85
+ Debugger.tracing = options.tracing
86
+
87
+ Debugger.debug_program(options)
88
+
@@ -0,0 +1,28 @@
1
+ jruby = defined?(JRUBY_VERSION) || (defined?(RUBY_ENGINE) && 'jruby' == RUBY_ENGINE)
2
+ unless jruby
3
+ require 'rubygems'
4
+ require 'rubygems/command.rb'
5
+ require 'rubygems/dependency_installer.rb'
6
+
7
+ begin
8
+ Gem::Command.build_args = ARGV
9
+ rescue NoMethodError
10
+ end
11
+
12
+ inst = Gem::DependencyInstaller.new
13
+ begin
14
+ if RUBY_VERSION < "1.9"
15
+ inst.install "ruby-debug-base", "~> 0.10.3"
16
+ else
17
+ inst.install "ruby-debug-base19", "~> 0.11.15"
18
+ end
19
+ rescue
20
+ exit(1)
21
+ end
22
+ end
23
+
24
+ # create dummy rakefile to indicate success
25
+ f = File.open(File.join(File.dirname(__FILE__), "Rakefile"), "w")
26
+ f.write("task :default\n")
27
+ f.close
28
+
@@ -0,0 +1,172 @@
1
+ require 'pp'
2
+ require 'stringio'
3
+ require "socket"
4
+ require 'thread'
5
+ require 'ruby-debug-base'
6
+ if RUBY_VERSION < "1.9"
7
+ require 'ruby-debug/xml_printer'
8
+ require 'ruby-debug/processor'
9
+ require 'ruby-debug/event_processor'
10
+ else
11
+ require_relative 'ruby-debug/xml_printer'
12
+ require_relative 'ruby-debug/processor'
13
+ require_relative 'ruby-debug/event_processor'
14
+ end
15
+
16
+ module Debugger
17
+
18
+ class << self
19
+ # Prints to the stderr using printf(*args) if debug logging flag (-d) is on.
20
+ def print_debug(*args)
21
+ if Debugger.cli_debug
22
+ $stderr.printf(*args)
23
+ $stderr.printf("\n")
24
+ $stderr.flush
25
+ end
26
+ end
27
+ end
28
+
29
+ class Context
30
+ def interrupt
31
+ self.stop_next = 1
32
+ end
33
+
34
+ private
35
+
36
+ def event_processor
37
+ Debugger.event_processor
38
+ end
39
+
40
+ def at_breakpoint(breakpoint)
41
+ event_processor.at_breakpoint(self, breakpoint)
42
+ end
43
+
44
+ def at_catchpoint(excpt)
45
+ event_processor.at_catchpoint(self, excpt)
46
+ end
47
+
48
+ def at_tracing(file, line)
49
+ if event_processor
50
+ event_processor.at_tracing(self, file, line)
51
+ else
52
+ Debugger::print_debug "trace: location=\"%s:%s\", threadId=%d", file, line, self.thnum
53
+ end
54
+ end
55
+
56
+ def at_line(file, line)
57
+ event_processor.at_line(self, file, line)
58
+ end
59
+
60
+ def at_return(file, line)
61
+ event_processor.at_return(self, file, line)
62
+ end
63
+ end
64
+
65
+ class << self
66
+
67
+ attr_accessor :event_processor, :cli_debug, :xml_debug
68
+ attr_reader :control_thread
69
+
70
+ #
71
+ # Interrupts the current thread
72
+ #
73
+ def interrupt
74
+ current_context.interrupt
75
+ end
76
+
77
+ #
78
+ # Interrupts the last debugged thread
79
+ #
80
+ def interrupt_last
81
+ skip do
82
+ if context = last_context
83
+ return nil unless context.thread.alive?
84
+ context.interrupt
85
+ end
86
+ context
87
+ end
88
+ end
89
+
90
+ def start_server(host = nil, port = 1234)
91
+ return if started?
92
+ start
93
+ start_control(host, port)
94
+ end
95
+
96
+ def debug_program(options)
97
+ start_server(options.host, options.port)
98
+
99
+ raise "Control thread did not start (#{@control_thread}}" unless @control_thread && @control_thread.alive?
100
+
101
+ @mutex = Mutex.new
102
+ @proceed = ConditionVariable.new
103
+
104
+ # wait for 'start' command
105
+ @mutex.synchronize do
106
+ @proceed.wait(@mutex)
107
+ end
108
+
109
+ bt = debug_load(Debugger::PROG_SCRIPT, options.stop, options.load_mode)
110
+ if bt
111
+ $stderr.print bt.backtrace.map{|l| "\t#{l}"}.join("\n"), "\n"
112
+ $stderr.print "Uncaught exception: #{bt}\n"
113
+ end
114
+ end
115
+
116
+ def run_prog_script
117
+ return unless @mutex
118
+ @mutex.synchronize do
119
+ @proceed.signal
120
+ end
121
+ end
122
+
123
+ def start_control(host, port)
124
+ raise "Debugger is not started" unless started?
125
+ return if @control_thread
126
+ @control_thread = DebugThread.new do
127
+ begin
128
+ $stderr.printf "Fast Debugger (ruby-debug-ide 0.4.9) listens on #{host}:#{port}\n"
129
+ # 127.0.0.1 seemingly works with all systems and with IPv6 as well.
130
+ # "localhost" and nil on have problems on some systems.
131
+ host ||= '127.0.0.1'
132
+ server = TCPServer.new(host, port)
133
+ while (session = server.accept)
134
+ begin
135
+ interface = RemoteInterface.new(session)
136
+ @event_processor = EventProcessor.new(interface)
137
+ ControlCommandProcessor.new(interface).process_commands
138
+ rescue StandardError, ScriptError => ex
139
+ $stderr.printf "Exception in DebugThread loop: #{ex}\n"
140
+ exit 1
141
+ end
142
+ end
143
+ rescue
144
+ $stderr.printf "Exception in DebugThread: #$!\n"
145
+ exit 2
146
+ end
147
+ end
148
+ end
149
+
150
+ end
151
+
152
+ class Exception # :nodoc:
153
+ attr_reader :__debug_file, :__debug_line, :__debug_binding, :__debug_context
154
+ end
155
+
156
+ module Kernel
157
+ #
158
+ # Stops the current thread after a number of _steps_ made.
159
+ #
160
+ def debugger(steps = 1)
161
+ Debugger.current_context.stop_next = steps
162
+ end
163
+
164
+ #
165
+ # Returns a binding of n-th call frame
166
+ #
167
+ def binding_n(n = 0)
168
+ Debugger.current_context.frame_binding[n+1]
169
+ end
170
+ end
171
+
172
+ end
@@ -0,0 +1,169 @@
1
+ if RUBY_VERSION < "1.9"
2
+ require 'ruby-debug/helper'
3
+ else
4
+ require_relative 'helper'
5
+ end
6
+
7
+
8
+ module Debugger
9
+
10
+ class Command # :nodoc:
11
+ SubcmdStruct=Struct.new(:name, :min, :short_help, :long_help) unless
12
+ defined?(SubcmdStruct)
13
+
14
+ # Find param in subcmds. param id downcased and can be abbreviated
15
+ # to the minimum length listed in the subcommands
16
+ def find(subcmds, param)
17
+ param.downcase!
18
+ for try_subcmd in subcmds do
19
+ if (param.size >= try_subcmd.min) and
20
+ (try_subcmd.name[0..param.size-1] == param)
21
+ return try_subcmd
22
+ end
23
+ end
24
+ return nil
25
+ end
26
+
27
+ class << self
28
+ def commands
29
+ @commands ||= []
30
+ end
31
+
32
+ DEF_OPTIONS = {
33
+ :event => true,
34
+ :control => false,
35
+ :unknown => false,
36
+ :need_context => false,
37
+ }
38
+
39
+ def inherited(klass)
40
+ DEF_OPTIONS.each do |o, v|
41
+ klass.options[o] = v if klass.options[o].nil?
42
+ end
43
+ commands << klass
44
+ end
45
+
46
+ def load_commands
47
+ dir = File.dirname(__FILE__)
48
+ Dir[File.join(dir, 'commands', '*')].each do |file|
49
+ require file if file =~ /\.rb$/
50
+ end
51
+ Debugger.constants.grep(/Functions$/).map { |name| Debugger.const_get(name) }.each do |mod|
52
+ include mod
53
+ end
54
+ end
55
+
56
+ def method_missing(meth, *args, &block)
57
+ if meth.to_s =~ /^(.+?)=$/
58
+ @options[$1.intern] = args.first
59
+ else
60
+ if @options.has_key?(meth)
61
+ @options[meth]
62
+ else
63
+ super
64
+ end
65
+ end
66
+ end
67
+
68
+ def options
69
+ @options ||= {}
70
+ end
71
+ end
72
+
73
+ def initialize(state, printer)
74
+ @state, @printer = state, printer
75
+ end
76
+
77
+ def match(input)
78
+ @match = regexp.match(input)
79
+ end
80
+
81
+ protected
82
+
83
+ def method_missing(meth, *args, &block)
84
+ if @printer.respond_to? meth
85
+ @printer.send meth, *args, &block
86
+ else
87
+ super
88
+ end
89
+ end
90
+
91
+ # FIXME: use delegate?
92
+ def errmsg(*args)
93
+ @printer.print_error(*args)
94
+ end
95
+
96
+ def print(*args)
97
+ @state.print(*args)
98
+ end
99
+
100
+ # see Timeout::timeout, the difference is that we must use a DebugThread
101
+ # because every other thread would be halted when the event hook is reached
102
+ # in ruby-debug.c
103
+ def timeout(sec)
104
+ return yield if sec == nil or sec.zero?
105
+ if RUBY_VERSION < "1.9"
106
+ raise ThreadError, "timeout within critical session" if Thread.critical
107
+ end
108
+ begin
109
+ x = Thread.current
110
+ y = DebugThread.start {
111
+ sleep sec
112
+ x.raise StandardError, "Timeout: evaluation took longer than #{sec} seconds." if x.alive?
113
+ }
114
+ yield sec
115
+ ensure
116
+ y.kill if y and y.alive?
117
+ end
118
+ end
119
+
120
+ def debug_eval(str, b = get_binding)
121
+ begin
122
+ str = str.to_s
123
+ max_time = 10
124
+ to_inspect = str.gsub(/\\n/, "\n")
125
+ @printer.print_debug("Evaluating with timeout after %i sec", max_time)
126
+ timeout(max_time) do
127
+ eval(to_inspect, b)
128
+ end
129
+ rescue StandardError, ScriptError => e
130
+ @printer.print_exception(e, @state.binding)
131
+ throw :debug_error
132
+ end
133
+ end
134
+
135
+ def debug_silent_eval(str)
136
+ begin
137
+ str = str.to_s
138
+ eval(str, get_binding)
139
+ rescue StandardError, ScriptError
140
+ nil
141
+ end
142
+ end
143
+
144
+ def hbinding(hash)
145
+ code = hash.keys.map{|k| "#{k} = hash['#{k}']"}.join(';') + ';binding'
146
+ if obj = @state.context.frame_self(@state.frame_pos)
147
+ obj.instance_eval code
148
+ else
149
+ eval code
150
+ end
151
+ end
152
+ private :hbinding
153
+
154
+ def get_binding
155
+ binding = @state.context.frame_binding(@state.frame_pos)
156
+ binding || hbinding(@state.context.frame_locals(@state.frame_pos))
157
+ end
158
+
159
+ def line_at(file, line)
160
+ Debugger.line_at(file, line)
161
+ end
162
+
163
+ def get_context(thnum)
164
+ Debugger.contexts.find{|c| c.thnum == thnum}
165
+ end
166
+ end
167
+
168
+ Command.load_commands
169
+ end