ruby-debug-ide19 0.4.10

Sign up to get free protection for your applications and to get access to all the features.
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