ruby-debug-ide22 0.7.4

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 (50) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGES +75 -0
  3. data/ChangeLog.archive +1073 -0
  4. data/ChangeLog.md +594 -0
  5. data/Gemfile +38 -0
  6. data/MIT-LICENSE +24 -0
  7. data/Rakefile +93 -0
  8. data/bin/gdb_wrapper +96 -0
  9. data/bin/rdebug-ide +200 -0
  10. data/ext/mkrf_conf.rb +44 -0
  11. data/lib/ruby-debug-ide/attach/debugger_loader.rb +20 -0
  12. data/lib/ruby-debug-ide/attach/gdb.rb +73 -0
  13. data/lib/ruby-debug-ide/attach/lldb.rb +71 -0
  14. data/lib/ruby-debug-ide/attach/native_debugger.rb +133 -0
  15. data/lib/ruby-debug-ide/attach/process_thread.rb +54 -0
  16. data/lib/ruby-debug-ide/attach/util.rb +115 -0
  17. data/lib/ruby-debug-ide/command.rb +187 -0
  18. data/lib/ruby-debug-ide/commands/breakpoints.rb +128 -0
  19. data/lib/ruby-debug-ide/commands/catchpoint.rb +64 -0
  20. data/lib/ruby-debug-ide/commands/condition.rb +51 -0
  21. data/lib/ruby-debug-ide/commands/control.rb +158 -0
  22. data/lib/ruby-debug-ide/commands/enable.rb +203 -0
  23. data/lib/ruby-debug-ide/commands/eval.rb +64 -0
  24. data/lib/ruby-debug-ide/commands/expression_info.rb +71 -0
  25. data/lib/ruby-debug-ide/commands/file_filtering.rb +107 -0
  26. data/lib/ruby-debug-ide/commands/frame.rb +155 -0
  27. data/lib/ruby-debug-ide/commands/inspect.rb +25 -0
  28. data/lib/ruby-debug-ide/commands/jump.rb +73 -0
  29. data/lib/ruby-debug-ide/commands/load.rb +18 -0
  30. data/lib/ruby-debug-ide/commands/pause.rb +33 -0
  31. data/lib/ruby-debug-ide/commands/set_type.rb +47 -0
  32. data/lib/ruby-debug-ide/commands/stepping.rb +108 -0
  33. data/lib/ruby-debug-ide/commands/threads.rb +178 -0
  34. data/lib/ruby-debug-ide/commands/variables.rb +154 -0
  35. data/lib/ruby-debug-ide/event_processor.rb +71 -0
  36. data/lib/ruby-debug-ide/greeter.rb +42 -0
  37. data/lib/ruby-debug-ide/helper.rb +33 -0
  38. data/lib/ruby-debug-ide/ide_processor.rb +155 -0
  39. data/lib/ruby-debug-ide/interface.rb +45 -0
  40. data/lib/ruby-debug-ide/multiprocess/monkey.rb +47 -0
  41. data/lib/ruby-debug-ide/multiprocess/pre_child.rb +59 -0
  42. data/lib/ruby-debug-ide/multiprocess/starter.rb +11 -0
  43. data/lib/ruby-debug-ide/multiprocess/unmonkey.rb +31 -0
  44. data/lib/ruby-debug-ide/multiprocess.rb +23 -0
  45. data/lib/ruby-debug-ide/thread_alias.rb +27 -0
  46. data/lib/ruby-debug-ide/version.rb +3 -0
  47. data/lib/ruby-debug-ide/xml_printer.rb +571 -0
  48. data/lib/ruby-debug-ide.rb +228 -0
  49. data/ruby-debug-ide.gemspec +47 -0
  50. metadata +110 -0
@@ -0,0 +1,51 @@
1
+ module Debugger
2
+
3
+ class ConditionCommand < Command # :nodoc:
4
+ self.control = true
5
+
6
+ def regexp
7
+ /^\s* cond(?:ition)? (?:\s+(\d+)\s*(.*))?$/ix
8
+ end
9
+
10
+ def execute
11
+ if not @match[1]
12
+ errmsg "\"condition\" must be followed a breakpoint number and expression\n"
13
+ else
14
+ breakpoints = Debugger.breakpoints.sort_by{|b| b.id }
15
+ largest = breakpoints.inject(0) do |largest_so_far, b|
16
+ b.id if b.id > largest_so_far
17
+ end
18
+ if 0 == largest
19
+ print "No breakpoints have been set.\n"
20
+ return
21
+ end
22
+ pos = get_int(@match[1], "Condition", 1, largest)
23
+ return unless pos
24
+ breakpoints.each do |b|
25
+ if b.id == pos
26
+ b.expr = @match[2].empty? ? nil : Command.unescape_incoming(@match[2])
27
+ print_contdition_set(b.id)
28
+ break
29
+ end
30
+ end
31
+
32
+ end
33
+ end
34
+
35
+ class << self
36
+ def help_command
37
+ 'condition'
38
+ end
39
+
40
+ def help(cmd)
41
+ %{
42
+ Condition breakpoint-number expression
43
+ Specify breakpoint number N to break only if COND is true.
44
+ N is an integer and COND is an expression to be evaluated whenever
45
+ breakpoint N is reached. If the empty string is used, the condition is removed.
46
+ }
47
+ end
48
+ end
49
+ end
50
+
51
+ end # module Debugger
@@ -0,0 +1,158 @@
1
+ module Debugger
2
+ class QuitCommand < Command # :nodoc:
3
+ self.control = true
4
+
5
+ def regexp
6
+ /^\s*(?:q(?:uit)?|exit)\s*$/
7
+ end
8
+
9
+ def execute
10
+ begin
11
+ @printer.print_msg("finished")
12
+ @printer.print_debug("Exiting debugger.")
13
+ ensure
14
+ exit! unless ENV['DEBUGGER_KEEP_PROCESS_ALIVE'] == "true" # exit -> exit!: No graceful way to stop threads...
15
+ end
16
+ end
17
+
18
+ class << self
19
+ def help_command
20
+ %w[quit exit]
21
+ end
22
+
23
+ def help(cmd)
24
+ %{
25
+ q[uit]\texit from debugger,
26
+ exit\talias to quit
27
+ }
28
+ end
29
+ end
30
+ end
31
+
32
+ class RestartCommand < Command # :nodoc:
33
+ self.control = true
34
+
35
+ def regexp
36
+ / ^\s*
37
+ (restart|R)
38
+ (\s+ \S+ .*)?
39
+ $
40
+ /x
41
+ end
42
+
43
+ def execute
44
+ if not defined? Debugger::RDEBUG_SCRIPT or not defined? Debugger::ARGV
45
+ print "We are not in a context we can restart from.\n"
46
+ return
47
+ end
48
+ if @match[2]
49
+ args = Debugger::PROG_SCRIPT + " " + @match[2]
50
+ else
51
+ args = Debugger::ARGV.join(" ")
52
+ end
53
+
54
+ # An execv would be preferable to the "exec" below.
55
+ cmd = Debugger::RDEBUG_SCRIPT + " " + args
56
+ print "Re exec'ing:\n\t#{cmd}\n"
57
+ exec cmd
58
+ end
59
+
60
+ class << self
61
+ def help_command
62
+ 'restart'
63
+ end
64
+
65
+ def help(cmd)
66
+ %{
67
+ restart|R [args]
68
+ Restart the program. This is is a re-exec - all debugger state
69
+ is lost. If command arguments are passed those are used.
70
+ }
71
+ end
72
+ end
73
+ end
74
+
75
+ class StartCommand < Command # :nodoc:
76
+ self.control = true
77
+
78
+ def regexp
79
+ /^\s*(start)(\s+ \S+ .*)?$/x
80
+ end
81
+
82
+ def execute
83
+ @printer.print_debug("Starting: running program script")
84
+ Debugger.run_prog_script #Debugger.prog_script_running?
85
+ end
86
+
87
+ class << self
88
+ def help_command
89
+ 'start'
90
+ end
91
+
92
+ def help(cmd)
93
+ %{
94
+ run prog script
95
+ }
96
+ end
97
+ end
98
+ end
99
+
100
+
101
+ class InterruptCommand < Command # :nodoc:
102
+ self.event = false
103
+ self.control = true
104
+ self.need_context = true
105
+
106
+ def regexp
107
+ /^\s*i(?:nterrupt)?\s*$/
108
+ end
109
+
110
+ def execute
111
+ unless Debugger.interrupt_last
112
+ context = Debugger.thread_context(Thread.main)
113
+ context.interrupt
114
+ end
115
+ end
116
+
117
+ class << self
118
+ def help_command
119
+ 'interrupt'
120
+ end
121
+
122
+ def help(cmd)
123
+ %{
124
+ i[nterrupt]\tinterrupt the program
125
+ }
126
+ end
127
+ end
128
+ end
129
+
130
+
131
+ class DetachCommand < Command # :nodoc:
132
+ self.control = true
133
+
134
+ def regexp
135
+ /^\s*detach\s*$/
136
+ end
137
+
138
+ def execute
139
+ Debugger.stop
140
+ Debugger.interface.close
141
+ Debugger::MultiProcess.undo_monkey
142
+ Debugger.control_thread = nil
143
+ Thread.current.exit #@control_thread is a current thread
144
+ end
145
+
146
+ class << self
147
+ def help_command
148
+ 'detach'
149
+ end
150
+
151
+ def help(cmd)
152
+ %{
153
+ detach\ndetach debugger\nnote: this option is only for remote debugging (or local attach)
154
+ }
155
+ end
156
+ end
157
+ end
158
+ end
@@ -0,0 +1,203 @@
1
+ module Debugger
2
+ # Mix-in module to assist in command parsing.
3
+ module EnableDisableFunctions # :nodoc:
4
+ def enable_disable_breakpoints(is_enable, args)
5
+ breakpoints = Debugger.breakpoints.sort_by{|b| b.id }
6
+ largest = breakpoints.inject(0) do |largest_so_far, b|
7
+ b.id if b.id > largest_so_far
8
+ end
9
+ if 0 == largest
10
+ errmsg "No breakpoints have been set.\n"
11
+ return
12
+ end
13
+ args.each do |pos|
14
+ pos = get_int(pos, "#{is_enable} breakpoints", 1, largest)
15
+ return nil unless pos
16
+ breakpoints.each do |b|
17
+ if b.id == pos
18
+ enabled = ("Enable" == is_enable)
19
+ if enabled
20
+ unless syntax_valid?(b.expr)
21
+ errmsg("Expression \"#{b.expr}\" syntactically incorrect; breakpoint remains disabled.\n")
22
+ break
23
+ end
24
+ end
25
+ b.enabled = enabled
26
+ enabled ? print_breakpoint_enabled(b) : print_breakpoint_disabled(b)
27
+ break
28
+ end
29
+ end
30
+ end
31
+ end
32
+
33
+ def enable_disable_display(is_enable, args)
34
+ if 0 == @state.display.size
35
+ errmsg "No display expressions have been set.\n"
36
+ return
37
+ end
38
+ args.each do |pos|
39
+ pos = get_int(pos, "#{is_enable} display", 1, @state.display.size)
40
+ return nil unless pos
41
+ @state.display[pos-1][0] = ("Enable" == is_enable)
42
+ end
43
+ end
44
+
45
+ end
46
+
47
+ class EnableCommand < Command # :nodoc:
48
+ Subcommands =
49
+ [
50
+ ['breakpoints', 2, "Enable specified breakpoints",
51
+ "Give breakpoint numbers (separated by spaces) as arguments.
52
+ This is used to cancel the effect of the \"disable\" command."
53
+ ],
54
+ ['display', 2,
55
+ "Enable some expressions to be displayed when program stops",
56
+ "Arguments are the code numbers of the expressions to resume displaying.
57
+ Do \"info display\" to see current list of code numbers."],
58
+ ].map do |name, min, short_help, long_help|
59
+ SubcmdStruct.new(name, min, short_help, long_help)
60
+ end unless defined?(Subcommands)
61
+
62
+ def regexp
63
+ /^\s* en(?:able)? (?:\s+(.*))?$/ix
64
+ end
65
+
66
+ def execute
67
+ if not @match[1]
68
+ errmsg "\"enable\" must be followed \"display\", \"breakpoints\"" +
69
+ " or breakpoint numbers.\n"
70
+ else
71
+ args = @match[1].split(/[ \t]+/)
72
+ param = args.shift
73
+ subcmd = find(Subcommands, param)
74
+ if subcmd
75
+ send("enable_#{subcmd.name}", args)
76
+ else
77
+ send("enable_breakpoints", args.unshift(param))
78
+ end
79
+ end
80
+ end
81
+
82
+ def enable_breakpoints(args)
83
+ enable_disable_breakpoints("Enable", args)
84
+ end
85
+
86
+ def enable_display(args)
87
+ enable_disable_display("Enable", args)
88
+ end
89
+
90
+ class << self
91
+ def help_command
92
+ 'enable'
93
+ end
94
+
95
+ def help(args)
96
+ if args[1]
97
+ s = args[1]
98
+ subcmd = Subcommands.find do |try_subcmd|
99
+ (s.size >= try_subcmd.min) and
100
+ (try_subcmd.name[0..s.size-1] == s)
101
+ end
102
+ if subcmd
103
+ str = subcmd.short_help + '.'
104
+ str += "\n" + subcmd.long_help if subcmd.long_help
105
+ return str
106
+ else
107
+ return "Invalid 'enable' subcommand '#{args[1]}'."
108
+ end
109
+ end
110
+ s = %{
111
+ Enable some things.
112
+ This is used to cancel the effect of the "disable" command.
113
+ --
114
+ List of enable subcommands:
115
+ --
116
+ }
117
+ for subcmd in Subcommands do
118
+ s += "enable #{subcmd.name} -- #{subcmd.short_help}\n"
119
+ end
120
+ return s
121
+ end
122
+ end
123
+ end
124
+
125
+ class DisableCommand < Command # :nodoc:
126
+ Subcommands =
127
+ [
128
+ ['breakpoints', 1, "Disable some breakpoints",
129
+ "Arguments are breakpoint numbers with spaces in between.
130
+ A disabled breakpoint is not forgotten, but has no effect until reenabled."],
131
+ ['display', 1, "Disable some display expressions when program stops",
132
+ "Arguments are the code numbers of the expressions to stop displaying.
133
+ Do \"info display\" to see current list of code numbers."],
134
+ ].map do |name, min, short_help, long_help|
135
+ SubcmdStruct.new(name, min, short_help, long_help)
136
+ end unless defined?(Subcommands)
137
+
138
+ def regexp
139
+ /^\s* dis(?:able)? (?:\s+(.*))?$/ix
140
+ end
141
+
142
+ def execute
143
+ if not @match[1]
144
+ errmsg "\"disable\" must be followed \"display\", \"breakpoints\"" +
145
+ " or breakpoint numbers.\n"
146
+ else
147
+ args = @match[1].split(/[ \t]+/)
148
+ param = args.shift
149
+ subcmd = find(Subcommands, param)
150
+ if subcmd
151
+ send("disable_#{subcmd.name}", args)
152
+ else
153
+ send("disable_breakpoints", args.unshift(param))
154
+ end
155
+ end
156
+ end
157
+
158
+ def disable_breakpoints(args)
159
+ enable_disable_breakpoints("Disable", args)
160
+ end
161
+
162
+ def disable_display(args)
163
+ enable_disable_display("Disable", args)
164
+ end
165
+
166
+ class << self
167
+ def help_command
168
+ 'disable'
169
+ end
170
+
171
+ def help(args)
172
+ if args[1]
173
+ s = args[1]
174
+ subcmd = Subcommands.find do |try_subcmd|
175
+ (s.size >= try_subcmd.min) and
176
+ (try_subcmd.name[0..s.size-1] == s)
177
+ end
178
+ if subcmd
179
+ str = subcmd.short_help + '.'
180
+ str += "\n" + subcmd.long_help if subcmd.long_help
181
+ return str
182
+ else
183
+ return "Invalid 'disable' subcommand '#{args[1]}'."
184
+ end
185
+ end
186
+ s = %{
187
+ Disable some things.
188
+
189
+ A disabled item is not forgotten, but has no effect until reenabled.
190
+ Use the "enable" command to have it take effect again.
191
+ --
192
+ List of disable subcommands:
193
+ --
194
+ }
195
+ for subcmd in Subcommands do
196
+ s += "disable #{subcmd.name} -- #{subcmd.short_help}\n"
197
+ end
198
+ return s
199
+ end
200
+ end
201
+ end
202
+
203
+ end # module Debugger
@@ -0,0 +1,64 @@
1
+ module Debugger
2
+ class EvalCommand < Command # :nodoc:
3
+ #self.control = true
4
+
5
+ def match(input)
6
+ @input = input
7
+ super
8
+ end
9
+
10
+ def regexp
11
+ /^\s*(p|e(?:val)?)\s+/
12
+ end
13
+
14
+ def execute
15
+ expr = @match ? @match.post_match : @input
16
+ binding = @state.context ? get_binding : TOPLEVEL_BINDING
17
+ print_eval expr, debug_eval(expr, binding).inspect
18
+ end
19
+
20
+ class << self
21
+ def help_command
22
+ %w|p eval|
23
+ end
24
+
25
+ def help(cmd)
26
+ if cmd == 'p'
27
+ %{
28
+ p expression\tevaluate expression and print its value
29
+ }
30
+ else
31
+ %{
32
+ e[val] expression\tevaluate expression and print its value,
33
+ \t\t\talias for p.
34
+ }
35
+ end
36
+ end
37
+ end
38
+ end
39
+
40
+ class PPCommand < Command # :nodoc:
41
+ def regexp
42
+ /^\s*pp\s+/
43
+ end
44
+
45
+ def execute
46
+ exp = @match.post_match
47
+ out = StringIO.new
48
+ PP.pp(debug_eval(exp), out) rescue out.puts $!.message
49
+ print_pp out.string
50
+ end
51
+
52
+ class << self
53
+ def help_command
54
+ 'pp'
55
+ end
56
+
57
+ def help(cmd)
58
+ %{
59
+ pp expression\tevaluate expression and print its value
60
+ }
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,71 @@
1
+ require 'stringio'
2
+ require 'irb/ruby-lex'
3
+
4
+ module Debugger
5
+
6
+ class ExpressionInfoCommand < Command
7
+ def regexp
8
+ /^\s*ex(?:pression_info)?\s+/
9
+ end
10
+
11
+ def execute
12
+ string_to_parse = Command.unescape_incoming(@match.post_match) + " \n \n\n"
13
+ total_lines = string_to_parse.count("\n") + 1
14
+
15
+ lexer = RubyLex.new
16
+ lexer.set_input(create_io_reader(string_to_parse))
17
+
18
+ last_statement = ''
19
+ last_prompt = ''
20
+ last_indent = 0
21
+ lexer.set_prompt do |ltype, indent, continue, lineno|
22
+ next if (lineno >= total_lines)
23
+
24
+ last_prompt = ltype || ''
25
+ last_indent = indent
26
+ end
27
+
28
+ lexer.each_top_level_statement do |line, line_no|
29
+ last_statement = line
30
+ end
31
+
32
+ incomplete = true
33
+ if /\A\s*\Z/m =~ last_statement
34
+ incomplete = false
35
+ end
36
+
37
+ @printer.print_expression_info(incomplete, last_prompt, last_indent)
38
+ end
39
+
40
+ def create_io_reader(string_to_parse)
41
+ io = StringIO.new(string_to_parse)
42
+
43
+ if string_to_parse.respond_to?(:encoding)
44
+ io.instance_exec(string_to_parse.encoding) do |string_encoding|
45
+ @my_encoding = string_encoding
46
+ def self.encoding
47
+ @my_encoding
48
+ end
49
+ end
50
+ end
51
+
52
+ io
53
+ end
54
+
55
+ class << self
56
+ def help_command
57
+ "expression_info"
58
+ end
59
+
60
+ def help(cmd)
61
+ %{
62
+ ex[pression_info] <expression>\t
63
+ returns parser-related information for the expression given\t\t
64
+ 'incomplete'=true|false\tindicates whether expression is a complete ruby
65
+ expression and can be evaluated without getting syntax errors
66
+ }
67
+ end
68
+ end
69
+ end
70
+
71
+ end
@@ -0,0 +1,107 @@
1
+ module Debugger
2
+ class IncludeFile < Command # :nodoc:
3
+ self.control = true
4
+
5
+ def regexp
6
+ / ^\s*include\s+(.+?)\s*$/x
7
+ end
8
+
9
+ def execute
10
+ file = @match[1]
11
+
12
+ return if file.nil?
13
+ file = realpath(file)
14
+
15
+ if Command.file_filter_supported?
16
+ Debugger.file_filter.include(file)
17
+ print_file_included(file)
18
+ else
19
+ print_debug("file filter is not supported")
20
+ end
21
+ end
22
+
23
+ class << self
24
+ def help_command
25
+ 'include'
26
+ end
27
+
28
+ def help(cmd)
29
+ %{
30
+ include file - adds file/dir to file filter (either remove already excluded or add as included)
31
+ }
32
+ end
33
+ end
34
+ end
35
+
36
+ class ExcludeFile < Command # :nodoc:
37
+ self.control = true
38
+
39
+ def regexp
40
+ / ^\s*exclude\s+(.+?)\s*$/x
41
+ end
42
+
43
+ def execute
44
+ file = @match[1]
45
+
46
+ return if file.nil?
47
+ file = realpath(file)
48
+
49
+ if Command.file_filter_supported?
50
+ Debugger.file_filter.exclude(file)
51
+ print_file_excluded(file)
52
+ else
53
+ print_debug("file filter is not supported")
54
+ end
55
+ end
56
+
57
+ class << self
58
+ def help_command
59
+ 'include'
60
+ end
61
+
62
+ def help(cmd)
63
+ %{
64
+ exclude file - exclude file/dir from file filter (either remove already included or add as exclude)
65
+ }
66
+ end
67
+ end
68
+ end
69
+
70
+ class FileFilterCommand < Command # :nodoc:
71
+ self.control = true
72
+
73
+ def regexp
74
+ / ^\s*file-filter\s+(on|off)\s*$/x
75
+ end
76
+
77
+ def execute
78
+ action = @match[1]
79
+
80
+ if Command.file_filter_supported?
81
+ if 'on' == action
82
+ Debugger.file_filter.enable
83
+ print_file_filter_status(true)
84
+ elsif 'off' == action
85
+ Debugger.file_filter.disable
86
+ print_file_filter_status(false)
87
+ else
88
+ print_error "Unknown option '#{action}'"
89
+ end
90
+ else
91
+ print_debug("file filter is not supported")
92
+ end
93
+ end
94
+
95
+ class << self
96
+ def help_command
97
+ 'file-filter'
98
+ end
99
+
100
+ def help(cmd)
101
+ %{
102
+ file-filter (on|off) - enable/disable file filtering
103
+ }
104
+ end
105
+ end
106
+ end
107
+ end