byebug 11.0.1

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 (132) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +897 -0
  3. data/CONTRIBUTING.md +58 -0
  4. data/GUIDE.md +1806 -0
  5. data/LICENSE +23 -0
  6. data/README.md +199 -0
  7. data/exe/byebug +6 -0
  8. data/ext/byebug/breakpoint.c +517 -0
  9. data/ext/byebug/byebug.c +905 -0
  10. data/ext/byebug/byebug.h +143 -0
  11. data/ext/byebug/context.c +673 -0
  12. data/ext/byebug/extconf.rb +12 -0
  13. data/ext/byebug/locker.c +96 -0
  14. data/ext/byebug/threads.c +230 -0
  15. data/lib/byebug.rb +3 -0
  16. data/lib/byebug/attacher.rb +48 -0
  17. data/lib/byebug/breakpoint.rb +111 -0
  18. data/lib/byebug/command.rb +111 -0
  19. data/lib/byebug/command_list.rb +34 -0
  20. data/lib/byebug/commands.rb +40 -0
  21. data/lib/byebug/commands/break.rb +112 -0
  22. data/lib/byebug/commands/catch.rb +78 -0
  23. data/lib/byebug/commands/condition.rb +55 -0
  24. data/lib/byebug/commands/continue.rb +68 -0
  25. data/lib/byebug/commands/debug.rb +38 -0
  26. data/lib/byebug/commands/delete.rb +55 -0
  27. data/lib/byebug/commands/disable.rb +33 -0
  28. data/lib/byebug/commands/disable/breakpoints.rb +42 -0
  29. data/lib/byebug/commands/disable/display.rb +43 -0
  30. data/lib/byebug/commands/display.rb +66 -0
  31. data/lib/byebug/commands/down.rb +45 -0
  32. data/lib/byebug/commands/edit.rb +69 -0
  33. data/lib/byebug/commands/enable.rb +33 -0
  34. data/lib/byebug/commands/enable/breakpoints.rb +42 -0
  35. data/lib/byebug/commands/enable/display.rb +43 -0
  36. data/lib/byebug/commands/finish.rb +57 -0
  37. data/lib/byebug/commands/frame.rb +57 -0
  38. data/lib/byebug/commands/help.rb +64 -0
  39. data/lib/byebug/commands/history.rb +39 -0
  40. data/lib/byebug/commands/info.rb +37 -0
  41. data/lib/byebug/commands/info/breakpoints.rb +65 -0
  42. data/lib/byebug/commands/info/display.rb +49 -0
  43. data/lib/byebug/commands/info/file.rb +80 -0
  44. data/lib/byebug/commands/info/line.rb +35 -0
  45. data/lib/byebug/commands/info/program.rb +49 -0
  46. data/lib/byebug/commands/interrupt.rb +34 -0
  47. data/lib/byebug/commands/irb.rb +50 -0
  48. data/lib/byebug/commands/kill.rb +45 -0
  49. data/lib/byebug/commands/list.rb +159 -0
  50. data/lib/byebug/commands/method.rb +53 -0
  51. data/lib/byebug/commands/next.rb +40 -0
  52. data/lib/byebug/commands/pry.rb +41 -0
  53. data/lib/byebug/commands/quit.rb +42 -0
  54. data/lib/byebug/commands/restart.rb +64 -0
  55. data/lib/byebug/commands/save.rb +72 -0
  56. data/lib/byebug/commands/set.rb +79 -0
  57. data/lib/byebug/commands/show.rb +45 -0
  58. data/lib/byebug/commands/skip.rb +85 -0
  59. data/lib/byebug/commands/source.rb +40 -0
  60. data/lib/byebug/commands/step.rb +40 -0
  61. data/lib/byebug/commands/thread.rb +34 -0
  62. data/lib/byebug/commands/thread/current.rb +37 -0
  63. data/lib/byebug/commands/thread/list.rb +43 -0
  64. data/lib/byebug/commands/thread/resume.rb +45 -0
  65. data/lib/byebug/commands/thread/stop.rb +43 -0
  66. data/lib/byebug/commands/thread/switch.rb +46 -0
  67. data/lib/byebug/commands/tracevar.rb +54 -0
  68. data/lib/byebug/commands/undisplay.rb +51 -0
  69. data/lib/byebug/commands/untracevar.rb +36 -0
  70. data/lib/byebug/commands/up.rb +45 -0
  71. data/lib/byebug/commands/var.rb +37 -0
  72. data/lib/byebug/commands/var/all.rb +41 -0
  73. data/lib/byebug/commands/var/args.rb +39 -0
  74. data/lib/byebug/commands/var/const.rb +49 -0
  75. data/lib/byebug/commands/var/global.rb +37 -0
  76. data/lib/byebug/commands/var/instance.rb +39 -0
  77. data/lib/byebug/commands/var/local.rb +39 -0
  78. data/lib/byebug/commands/where.rb +53 -0
  79. data/lib/byebug/context.rb +157 -0
  80. data/lib/byebug/core.rb +115 -0
  81. data/lib/byebug/errors.rb +29 -0
  82. data/lib/byebug/frame.rb +185 -0
  83. data/lib/byebug/helpers/bin.rb +47 -0
  84. data/lib/byebug/helpers/eval.rb +126 -0
  85. data/lib/byebug/helpers/file.rb +63 -0
  86. data/lib/byebug/helpers/frame.rb +75 -0
  87. data/lib/byebug/helpers/parse.rb +75 -0
  88. data/lib/byebug/helpers/path.rb +40 -0
  89. data/lib/byebug/helpers/reflection.rb +19 -0
  90. data/lib/byebug/helpers/string.rb +33 -0
  91. data/lib/byebug/helpers/thread.rb +67 -0
  92. data/lib/byebug/helpers/toggle.rb +62 -0
  93. data/lib/byebug/helpers/var.rb +54 -0
  94. data/lib/byebug/history.rb +130 -0
  95. data/lib/byebug/interface.rb +146 -0
  96. data/lib/byebug/interfaces/local_interface.rb +44 -0
  97. data/lib/byebug/interfaces/remote_interface.rb +50 -0
  98. data/lib/byebug/interfaces/script_interface.rb +33 -0
  99. data/lib/byebug/interfaces/test_interface.rb +67 -0
  100. data/lib/byebug/option_setter.rb +95 -0
  101. data/lib/byebug/printers/base.rb +68 -0
  102. data/lib/byebug/printers/plain.rb +44 -0
  103. data/lib/byebug/printers/texts/base.yml +115 -0
  104. data/lib/byebug/printers/texts/plain.yml +33 -0
  105. data/lib/byebug/processors/command_processor.rb +173 -0
  106. data/lib/byebug/processors/control_processor.rb +24 -0
  107. data/lib/byebug/processors/post_mortem_processor.rb +18 -0
  108. data/lib/byebug/processors/script_processor.rb +49 -0
  109. data/lib/byebug/remote.rb +85 -0
  110. data/lib/byebug/remote/client.rb +57 -0
  111. data/lib/byebug/remote/server.rb +47 -0
  112. data/lib/byebug/runner.rb +198 -0
  113. data/lib/byebug/setting.rb +79 -0
  114. data/lib/byebug/settings/autoirb.rb +29 -0
  115. data/lib/byebug/settings/autolist.rb +29 -0
  116. data/lib/byebug/settings/autopry.rb +29 -0
  117. data/lib/byebug/settings/autosave.rb +17 -0
  118. data/lib/byebug/settings/basename.rb +16 -0
  119. data/lib/byebug/settings/callstyle.rb +20 -0
  120. data/lib/byebug/settings/fullpath.rb +16 -0
  121. data/lib/byebug/settings/histfile.rb +20 -0
  122. data/lib/byebug/settings/histsize.rb +20 -0
  123. data/lib/byebug/settings/linetrace.rb +22 -0
  124. data/lib/byebug/settings/listsize.rb +21 -0
  125. data/lib/byebug/settings/post_mortem.rb +27 -0
  126. data/lib/byebug/settings/savefile.rb +20 -0
  127. data/lib/byebug/settings/stack_on_error.rb +15 -0
  128. data/lib/byebug/settings/width.rb +20 -0
  129. data/lib/byebug/source_file_formatter.rb +71 -0
  130. data/lib/byebug/subcommands.rb +54 -0
  131. data/lib/byebug/version.rb +8 -0
  132. metadata +199 -0
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Byebug
4
+ #
5
+ # Reopens the +info+ command to define the +line+ subcommand
6
+ #
7
+ class InfoCommand < Command
8
+ #
9
+ # Information about current location
10
+ #
11
+ class LineCommand < Command
12
+ self.allow_in_post_mortem = true
13
+
14
+ def self.regexp
15
+ /^\s* l(?:ine)? \s*$/x
16
+ end
17
+
18
+ def self.description
19
+ <<-DESCRIPTION
20
+ inf[o] l[ine]
21
+
22
+ #{short_description}
23
+ DESCRIPTION
24
+ end
25
+
26
+ def self.short_description
27
+ "Line number and file name of current position in source file."
28
+ end
29
+
30
+ def execute
31
+ puts "Line #{frame.line} of \"#{frame.file}\""
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Byebug
4
+ #
5
+ # Reopens the +info+ command to define the +args+ subcommand
6
+ #
7
+ class InfoCommand < Command
8
+ #
9
+ # Information about arguments of the current method/block
10
+ #
11
+ class ProgramCommand < Command
12
+ self.allow_in_post_mortem = true
13
+
14
+ def self.regexp
15
+ /^\s* p(?:rogram)? \s*$/x
16
+ end
17
+
18
+ def self.description
19
+ <<-DESCRIPTION
20
+ inf[o] p[rogram]
21
+
22
+ #{short_description}
23
+ DESCRIPTION
24
+ end
25
+
26
+ def self.short_description
27
+ "Information about the current status of the debugged program."
28
+ end
29
+
30
+ def execute
31
+ puts "Program stopped. "
32
+ format_stop_reason context.stop_reason
33
+ end
34
+
35
+ private
36
+
37
+ def format_stop_reason(stop_reason)
38
+ case stop_reason
39
+ when :step
40
+ puts "It stopped after stepping, next'ing or initial start."
41
+ when :breakpoint
42
+ puts "It stopped at a breakpoint."
43
+ when :catchpoint
44
+ puts "It stopped at a catchpoint."
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "byebug/command"
4
+
5
+ module Byebug
6
+ #
7
+ # Interrupting execution of current thread.
8
+ #
9
+ class InterruptCommand < Command
10
+ self.allow_in_control = true
11
+
12
+ def self.regexp
13
+ /^\s*int(?:errupt)?\s*$/
14
+ end
15
+
16
+ def self.description
17
+ <<-DESCRIPTION
18
+ int[errupt]
19
+
20
+ #{short_description}
21
+ DESCRIPTION
22
+ end
23
+
24
+ def self.short_description
25
+ "Interrupts the program"
26
+ end
27
+
28
+ def execute
29
+ Byebug.start
30
+
31
+ Byebug.thread_context(Thread.main).interrupt
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "byebug/command"
4
+ require "irb"
5
+ require "English"
6
+
7
+ module Byebug
8
+ #
9
+ # Enter IRB from byebug's prompt
10
+ #
11
+ class IrbCommand < Command
12
+ self.allow_in_post_mortem = true
13
+
14
+ def self.regexp
15
+ /^\s* irb \s*$/x
16
+ end
17
+
18
+ def self.description
19
+ <<-DESCRIPTION
20
+ irb
21
+
22
+ #{short_description}
23
+ DESCRIPTION
24
+ end
25
+
26
+ def self.short_description
27
+ "Starts an IRB session"
28
+ end
29
+
30
+ def execute
31
+ return errmsg(pr("base.errors.only_local")) unless processor.interface.instance_of?(LocalInterface)
32
+
33
+ # @todo IRB tries to parse $ARGV so we must clear it (see #197). Add a
34
+ # test case for it so we can remove this comment.
35
+ with_clean_argv { IRB.start }
36
+ end
37
+
38
+ private
39
+
40
+ def with_clean_argv
41
+ saved_argv = $ARGV.dup
42
+ $ARGV.clear
43
+ begin
44
+ yield
45
+ ensure
46
+ $ARGV.concat(saved_argv)
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "byebug/command"
4
+
5
+ module Byebug
6
+ #
7
+ # Send custom signals to the debugged program.
8
+ #
9
+ class KillCommand < Command
10
+ self.allow_in_control = true
11
+
12
+ def self.regexp
13
+ /^\s* kill \s* (?:\s+(\S+))? \s*$/x
14
+ end
15
+
16
+ def self.description
17
+ <<-DESCRIPTION
18
+ kill[ signal]
19
+
20
+ #{short_description}
21
+
22
+ Equivalent of Process.kill(Process.pid)
23
+ DESCRIPTION
24
+ end
25
+
26
+ def self.short_description
27
+ "Sends a signal to the current process"
28
+ end
29
+
30
+ def execute
31
+ if @match[1]
32
+ signame = @match[1]
33
+
34
+ return errmsg("signal name #{signame} is not a signal I know about\n") unless Signal.list.member?(signame)
35
+ else
36
+ return unless confirm("Really kill? (y/n) ")
37
+
38
+ signame = "KILL"
39
+ end
40
+
41
+ processor.interface.close if signame == "KILL"
42
+ Process.kill(signame, Process.pid)
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,159 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "byebug/command"
4
+ require "byebug/source_file_formatter"
5
+ require "byebug/helpers/file"
6
+ require "byebug/helpers/parse"
7
+
8
+ module Byebug
9
+ #
10
+ # List parts of the source code.
11
+ #
12
+ class ListCommand < Command
13
+ include Helpers::FileHelper
14
+ include Helpers::ParseHelper
15
+
16
+ self.allow_in_post_mortem = true
17
+
18
+ def self.regexp
19
+ /^\s* l(?:ist)? (?:\s*([-=])|\s+(\S+))? \s*$/x
20
+ end
21
+
22
+ def self.description
23
+ <<-DESCRIPTION
24
+ l[ist][[-=]][ nn-mm]
25
+
26
+ #{short_description}
27
+
28
+ Lists lines forward from current line or from the place where code was
29
+ last listed. If "list-" is specified, lists backwards instead. If
30
+ "list=" is specified, lists from current line regardless of where code
31
+ was last listed. A line range can also be specified to list specific
32
+ sections of code.
33
+ DESCRIPTION
34
+ end
35
+
36
+ def self.short_description
37
+ "Lists lines of source code"
38
+ end
39
+
40
+ def execute
41
+ msg = "No sourcefile available for #{frame.file}"
42
+ raise(msg) unless File.exist?(frame.file)
43
+
44
+ b, e = range(@match[2])
45
+
46
+ display_lines(b, e)
47
+
48
+ processor.prev_line = b
49
+ end
50
+
51
+ private
52
+
53
+ #
54
+ # Line range to be printed by `list`.
55
+ #
56
+ # If <input> is set, range is parsed from it.
57
+ #
58
+ # Otherwise it's automatically chosen.
59
+ #
60
+ def range(input)
61
+ return auto_range(@match[1] || "+") unless input
62
+
63
+ b, e = parse_range(input)
64
+ raise("Invalid line range") unless valid_range?(b, e)
65
+
66
+ [b, e]
67
+ end
68
+
69
+ def valid_range?(first, last)
70
+ first <= last && (1..max_line).cover?(first) && (1..max_line).cover?(last)
71
+ end
72
+
73
+ #
74
+ # Set line range to be printed by list
75
+ #
76
+ # @return first line number to list
77
+ # @return last line number to list
78
+ #
79
+ def auto_range(direction)
80
+ prev_line = processor.prev_line
81
+
82
+ if direction == "=" || prev_line.nil?
83
+ source_file_formatter.range_around(frame.line)
84
+ else
85
+ source_file_formatter.range_from(move(prev_line, size, direction))
86
+ end
87
+ end
88
+
89
+ def parse_range(input)
90
+ first, err = get_int(lower_bound(input), "List", 1, max_line)
91
+ raise(err) unless first
92
+
93
+ if upper_bound(input)
94
+ last, err = get_int(upper_bound(input), "List", 1, max_line)
95
+ raise(err) unless last
96
+
97
+ last = amend_final(last)
98
+ else
99
+ first -= (size / 2)
100
+ end
101
+
102
+ [first, last || move(first, size - 1)]
103
+ end
104
+
105
+ def move(line, size, direction = "+")
106
+ line.send(direction, size)
107
+ end
108
+
109
+ #
110
+ # Show a range of lines in the current file.
111
+ #
112
+ # @param min [Integer] Lower bound
113
+ # @param max [Integer] Upper bound
114
+ #
115
+ def display_lines(min, max)
116
+ puts "\n[#{min}, #{max}] in #{frame.file}"
117
+
118
+ puts source_file_formatter.lines(min, max).join
119
+ end
120
+
121
+ #
122
+ # @param range [String] A string with an integer range format
123
+ #
124
+ # @return [String] The lower bound of the given range
125
+ #
126
+ def lower_bound(range)
127
+ split_range(range)[0]
128
+ end
129
+
130
+ #
131
+ # @param range [String] A string with an integer range format
132
+ #
133
+ # @return [String] The upper bound of the given range
134
+ #
135
+ def upper_bound(range)
136
+ split_range(range)[1]
137
+ end
138
+
139
+ #
140
+ # @param str [String] A string with an integer range format
141
+ #
142
+ # @return [Array] The upper & lower bounds of the given range
143
+ #
144
+ def split_range(str)
145
+ str.split(/[-,]/)
146
+ end
147
+
148
+ extend Forwardable
149
+
150
+ def_delegators :source_file_formatter, :amend_final, :size, :max_line
151
+
152
+ def source_file_formatter
153
+ @source_file_formatter ||= SourceFileFormatter.new(
154
+ frame.file,
155
+ ->(n) { n == frame.line ? "=>" : " " }
156
+ )
157
+ end
158
+ end
159
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "byebug/command"
4
+ require "byebug/helpers/eval"
5
+
6
+ module Byebug
7
+ #
8
+ # Show methods of specific classes/modules/objects.
9
+ #
10
+ class MethodCommand < Command
11
+ include Helpers::EvalHelper
12
+
13
+ self.allow_in_post_mortem = true
14
+
15
+ def self.regexp
16
+ /^\s* m(?:ethod)? \s+ (i(:?nstance)?\s+)?/x
17
+ end
18
+
19
+ def self.description
20
+ <<-DESCRIPTION
21
+ m[ethod] (i[nstance][ <obj>]|<class|module>)
22
+
23
+ #{short_description}
24
+
25
+ When invoked with "instance", shows instance methods of the object
26
+ specified as argument or of self no object was specified.
27
+
28
+ When invoked only with a class or module, shows class methods of the
29
+ class or module specified as argument.
30
+ DESCRIPTION
31
+ end
32
+
33
+ def self.short_description
34
+ "Shows methods of an object, class or module"
35
+ end
36
+
37
+ def execute
38
+ obj = warning_eval(@match.post_match)
39
+
40
+ result =
41
+ if @match[1]
42
+ prc("method.methods", obj.methods.sort) { |item, _| { name: item } }
43
+ elsif !obj.is_a?(Module)
44
+ pr("variable.errors.not_module", object: @match.post_match)
45
+ else
46
+ prc("method.methods", obj.instance_methods(false).sort) do |item, _|
47
+ { name: item }
48
+ end
49
+ end
50
+ puts result
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "byebug/command"
4
+ require "byebug/helpers/parse"
5
+
6
+ module Byebug
7
+ #
8
+ # Implements the next functionality.
9
+ #
10
+ # Allows the user the continue execution until the next instruction in the
11
+ # current frame.
12
+ #
13
+ class NextCommand < Command
14
+ include Helpers::ParseHelper
15
+
16
+ def self.regexp
17
+ /^\s* n(?:ext)? (?:\s+(\S+))? \s*$/x
18
+ end
19
+
20
+ def self.description
21
+ <<-DESCRIPTION
22
+ n[ext][ nnn]
23
+
24
+ #{short_description}
25
+ DESCRIPTION
26
+ end
27
+
28
+ def self.short_description
29
+ "Runs one or more lines of code"
30
+ end
31
+
32
+ def execute
33
+ steps, err = parse_steps(@match[1], "Next")
34
+ return errmsg(err) unless steps
35
+
36
+ context.step_over(steps, context.frame.pos)
37
+ processor.proceed!
38
+ end
39
+ end
40
+ end