debug 1.3.3 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d2f3adfa33baa3d7ef0a8ff1924d4d148be909f8cbdfc1992efda7e4ef564a17
4
- data.tar.gz: 43085e7bec187d698d42bf7a4fc7c3ee2f4cde387cf411b2648411dc6cbb1721
3
+ metadata.gz: 121cdb1003971d234dbeb40878f693d06053fa32f28024c5d2a7c0e0fd6d3719
4
+ data.tar.gz: fd95c68d4bf99b38a83cef1a6851680bb9abb65d39fa9fc69a94d248295a5829
5
5
  SHA512:
6
- metadata.gz: 5bafcaeeb661378a3696968655cfc9b24aadb6c0ada385d143406472db4cc1a51d55bb460431ef9679d8e6ffe846c269f731335380999256565b2d259139f2d9
7
- data.tar.gz: 961d6a453a4f117af9e056658d31afc39e173668f32eb1745f0bdad842c4891a2b6bff0bfec45d6e17fc94108da3ac4a5274118a4f0213ae0a2a5a181de89f99
6
+ metadata.gz: 4354a11670db6e0fd49e4b8151b268a08c7843c80ccd36b5c492cf5fabc7b42c6632939905b9912c81434f5513e36dac8378686b5d47c274248c523eea88a0c8
7
+ data.tar.gz: e22274473f567bed800c25d46a46d32adf263f070e8147cd71778ef9cbd95b8e239e2912b226892f032266a92322045a62e7f9c908f176e601a984e254acd2a7
data/CONTRIBUTING.md CHANGED
@@ -26,11 +26,17 @@ $ ruby test/debug/bp_test.rb -h # to see all the test options
26
26
  ```
27
27
 
28
28
  ## Generate Tests
29
+
29
30
  There is a test generator in `debug.rb` project to make it easier to write tests.
31
+
30
32
  ### Quickstart
31
- This section shows you how to create test file by test generator. For more advanced informations on creating tests, please take a look at [gentest options](#gentest-options). (You can also check by `$bin/gentest -h`)
33
+
34
+ This section shows you how to create test file by test generator. For more advanced information on creating tests, please take a look at [gentest options](#gentest-options). (You can also check by `$bin/gentest -h`)
35
+
32
36
  #### 1. Create a target file for debuggee.
37
+
33
38
  Let's say, we created `target.rb` which is located in top level directory of debugger.
39
+
34
40
  ```ruby
35
41
  module Foo
36
42
  class Bar
@@ -42,11 +48,15 @@ module Foo
42
48
  bar = Bar.new
43
49
  end
44
50
  ```
51
+
45
52
  #### 2. Run `gentest` as shown in the example below.
53
+
46
54
  ```shell
47
55
  $ bin/gentest target.rb
48
56
  ```
57
+
49
58
  #### 3. Debugger will be executed. You can type any debug commands.
59
+
50
60
  ```shell
51
61
  $ bin/gentest target.rb
52
62
  DEBUGGER: Session start (pid: 11139)
@@ -119,8 +129,11 @@ created: /Users/naotto/workspace/debug/test/tool/../debug/foo_test.rb
119
129
  class: FooTest
120
130
  method: test_1629720194
121
131
  ```
132
+
122
133
  #### 4. The test file will be created as `test/debug/foo_test.rb`.
134
+
123
135
  If the file already exists, **only method** will be added to it.
136
+
124
137
  ```ruby
125
138
  # frozen_string_literal: true
126
139
 
@@ -204,17 +217,161 @@ end
204
217
  ```
205
218
 
206
219
  #### gentest options
220
+
207
221
  You can get more information about `gentest` here.
208
222
 
209
- The default method name is `test_#{some integer numbers}`, the class name is `FooTest`, and the file name will be `foo_test.rb`.
223
+ The default method name is `test_#{some integer numbers}`, the class name is `FooTest#{some integer numbers}`, and the file name will be `foo_test.rb`.
210
224
  The following table shows examples of the gentest options.
211
225
 
212
226
  | Command | Description | File | Class | Method |
213
227
  | --- | --- | --- | --- | --- |
214
- | `$ bin/gentest target.rb` | Run without any options | `foo_test.rb` | `FooTest` | `test_#{some integer numbers}` |
215
- | `$ bin/gentest target.rb -c step` | Specify the class name | `step_test.rb` | `StepTest` | `test_#{some integer numbers}` |
216
- | `$ bin/gentest target.rb -m test_step` | Specify the method name | `foo_test.rb` | `FooTest` | `test_step` |
217
- | `$ bin/gentest target.rb -c step -m test_step` | Specify the class name and the method name | `step_test.rb` | `StepTest` | `test_step` |
228
+ | `$ bin/gentest target.rb` | Run without any options | `foo_test.rb` | `FooTest...` | `test_...` |
229
+ | `$ bin/gentest target.rb --open=vscode` | Run the debugger with VScode | `foo_test.rb` | `FooTest...` | `test_...` |
230
+ | `$ bin/gentest target.rb -c step` | Specify the class name | `step_test.rb` | `StepTest...` | `test_...` |
231
+ | `$ bin/gentest target.rb -m test_step` | Specify the method name | `foo_test.rb` | `FooTest...` | `test_step` |
232
+ | `$ bin/gentest target.rb -c step -m test_step` | Specify the class name and the method name | `step_test.rb` | `StepTest...` | `test_step` |
233
+
234
+ ### Assertions
235
+
236
+ - assert_line_num(expected)
237
+
238
+ Passes if `expected` is equal to the location where debugger stops.
239
+
240
+ - assert_line_text(text)
241
+
242
+ Passes if `text` is included in the last debugger log.
243
+
244
+ - assert_no_line_text(text)
245
+
246
+ Passes if `text` is not included in the last debugger log.
247
+
248
+ - assert_debuggee_line_text(text)
249
+
250
+ Passes if `text` is included in the debuggee log.
251
+
252
+ ### Tests for DAP and CDP
253
+
254
+ Currently, there are 2 kinds of test frameworks for DAP and CDP.
255
+
256
+ 1. Protocol-based tests
257
+
258
+ If you want to write protocol-based tests, you should use the test generator.
259
+ To run the test generator, you can enter `$ bin/gentest target.rb --open=vscode` in the terminal, VSCode will be executed.
260
+ Also, if you enter ``$ bin/gentest target.rb --open=chrome` there, Chrome will be executed.
261
+ If you need to modify existing tests, it is basically a good idea to regenerate them by the test generator instead of rewriting them directly.
262
+ Please refer to [the Microsoft "Debug Adapter Protocol" article](https://microsoft.github.io/debug-adapter-protocol/specification) to learn more about DAP formats.
263
+ Please refer to [Procol viewer for "Chrome DevTools Protocol"](https://chromedevtools.github.io/devtools-protocol/) to learn more about CDP formats.
264
+
265
+ 2. High-level tests
266
+
267
+ High-level tests are designed to test both DAP and CDP for a single method.
268
+ You can write tests as follows:
269
+ **NOTE:** Use `req_terminate_debuggee` to finish debugging. You can't use any methods such as `req_continue`, `req_next` and so on.
270
+
271
+ ```ruby
272
+ require_relative '../support/test_case'
273
+ module DEBUGGER__
274
+ class BreakTest < TestCase
275
+ # PROGRAM is the target script.
276
+ PROGRAM = <<~RUBY
277
+ 1| module Foo
278
+ 2| class Bar
279
+ 3| def self.a
280
+ 4| "hello"
281
+ 5| end
282
+ 6| end
283
+ 7| Bar.a
284
+ 8| bar = Bar.new
285
+ 9| end
286
+ RUBY
287
+
288
+ def test_break1
289
+ run_protocol_scenario PROGRAM do # Start debugging with DAP and CDP
290
+ req_add_breakpoint 5 # Set a breakpoint on line 5.
291
+ req_add_breakpoint 8 # Set a breakpoint on line 8.
292
+ req_continue # Resume the program.
293
+ assert_line_num 5 # Check if debugger stops at line 5.
294
+ req_continue # Resume the program.
295
+ assert_line_num 8 # Check if debugger stops at line 8.
296
+ req_terminate_debuggee # Terminate debugging.
297
+ end
298
+ end
299
+ end
300
+ end
301
+ ```
302
+
303
+ #### API
304
+
305
+ - run_protocol_scenario program, dap: true, cdp: true, &scenario
306
+
307
+ Execute debugging `program` with `&scenario`. If you want to test it only for DAP, you can write as follows:
308
+
309
+ `run_protocol_scenario program, cdp: false ...`
310
+
311
+ - req_add_breakpoint(lineno, path: temp_file_path, cond: nil)
312
+
313
+ Sends request to rdbg to add a breakpoint.
314
+
315
+ - req_delete_breakpoint bpnum
316
+
317
+ Sends request to rdbg to delete a breakpoint.
318
+
319
+ - req_set_exception_breakpoints
320
+
321
+ Sends request to rdbg to set exception breakpoints.
322
+
323
+ - req_continue
324
+
325
+ Sends request to rdbg to resume the program.
326
+
327
+ - req_step
328
+
329
+ Sends request to rdbg to step into next method.
330
+
331
+ - req_next
332
+
333
+ Sends request to rdbg to step over next method.
334
+
335
+ - req_finish
336
+
337
+ Sends request to rdbg to step out of current method.
338
+
339
+ - req_step_back
340
+
341
+ Sends request to rdbg to step back from current method.
342
+
343
+ - req_terminate_debuggee
344
+
345
+ Sends request to rdbg to terminate the debuggee.
346
+
347
+ - assert_reattach
348
+
349
+ Passes if reattaching to rdbg is successful.
350
+
351
+ - assert_hover_result(expected, expression: nil)
352
+
353
+ Passes if result of `expression` is equal to `expected`.
354
+
355
+ - assert_repl_result(expected, expression: nil)
356
+
357
+ Passes if result of `expression` is equal to `expected`.
358
+
359
+ - assert_watch_result(expected, expression: nil)
360
+
361
+ Passes if result of `expression` is equal to `expected`.
362
+
363
+ - assert_line_num(expected)
364
+
365
+ Passes if `expected` is equal to the location where debugger stops.
366
+
367
+ - assert_locals_result(expected)
368
+
369
+ Passes if all of `expected` local variable entries match the ones returned by debugger.
370
+
371
+ An variable entry looks like this: `{ name: "bar", value: "nil", type: "NilClass" }`.
372
+
373
+ Please note that both `value` and `type` need to be strings.
374
+
218
375
 
219
376
  ## To Update README
220
377
 
data/Gemfile CHANGED
@@ -6,3 +6,4 @@ gem "rake"
6
6
  gem "rake-compiler"
7
7
  gem "test-unit", "~> 3.0"
8
8
  gem "test-unit-rr"
9
+ gem "json-schema"
data/README.md CHANGED
@@ -1,8 +1,8 @@
1
- [![Ruby](https://github.com/ruby/debug/actions/workflows/ruby.yml/badge.svg?branch=master)](https://github.com/ruby/debug/actions/workflows/ruby.yml?query=branch%3Amaster)
1
+ [![Ruby](https://github.com/ruby/debug/actions/workflows/ruby.yml/badge.svg?branch=master)](https://github.com/ruby/debug/actions/workflows/ruby.yml?query=branch%3Amaster) [![Protocol](https://github.com/ruby/debug/actions/workflows/protocol.yml/badge.svg)](https://github.com/ruby/debug/actions/workflows/protocol.yml)
2
2
 
3
3
  # debug.rb
4
4
 
5
- This library provides debugging functionality to Ruby.
5
+ This library provides debugging functionality to Ruby (MRI) 2.6 and later.
6
6
 
7
7
  This debug.rb is replacement of traditional lib/debug.rb standard library which is implemented by `set_trace_func`.
8
8
  New debug.rb has several advantages:
@@ -60,8 +60,14 @@ There are several options for (1) and (2). Please choose your favorite way.
60
60
 
61
61
  ### Modify source code with [`binding.break`](#bindingbreak-method) (similar to `binding.pry` or `binding.irb`)
62
62
 
63
- If you can modify the source code, you can use the debugger by adding `require 'debug'` line at the top of your program and putting [`binding.break`](#bindingbreak-method) method (`binding.b` for short) into lines where you want to stop as breakpoints like `binding.pry` and `binding.irb`.
64
- After that, you run the program as usual and you will enter the debug console at breakpoints you inserted.
63
+ If you can modify the source code, you can use the debugger by adding `require 'debug'` at the top of your program and putting [`binding.break`](#bindingbreak-method) method into lines where you want to stop as breakpoints like `binding.pry` and `binding.irb`.
64
+
65
+ You can also use its 2 aliases in the same way:
66
+
67
+ - `binding.b`
68
+ - `debugger`
69
+
70
+ After that, run the program as usual and you will enter the debug console at breakpoints you inserted.
65
71
 
66
72
  The following example shows the demonstration of [`binding.break`](#bindingbreak-method).
67
73
 
@@ -107,7 +113,7 @@ d => nil
107
113
  5| binding.break
108
114
  6| c = 3
109
115
  7| d = 4
110
- => 8| binding.break # Again the program stops at here
116
+ => 8| binding.break # Again the program stops here
111
117
  9| p [a, b, c, d]
112
118
  10|
113
119
  11| __END__
@@ -346,12 +352,14 @@ You can attach with external debugger frontend with VSCode and Chrome.
346
352
  $ rdbg --open=[frontend] target.rb
347
353
  ```
348
354
 
349
- will open a debug port and `[frontned]` can attache to the port.
355
+ will open a debug port and `[frontend]` can attach to the port.
350
356
 
351
357
  Also `open` command allows opening the debug port.
352
358
 
353
359
  #### VSCode integration
354
360
 
361
+ ([vscode-rdbg v0.0.9](https://marketplace.visualstudio.com/items?itemName=KoichiSasada.vscode-rdbg) or later is required)
362
+
355
363
  If you don't run a debuggee Ruby process on VSCode, you can attach with VSCode later with the following steps.
356
364
 
357
365
  `rdbg --open=vscode` opens the debug port and tries to invoke the VSCode (`code` command).
@@ -411,7 +419,7 @@ Note that you can attach with `rdbg --attach` and continue REPL debugging.
411
419
 
412
420
  #### Chrome DevTool integration
413
421
 
414
- With `rdbg --open=chrome` command will shows the following message.
422
+ With `rdbg --open=chrome` command will show the following message.
415
423
 
416
424
  ```
417
425
  $ rdbg target.rb --open=chrome
@@ -427,7 +435,7 @@ Type `devtools://devtools/bundled/inspector.html?ws=127.0.0.1:43633` in the addr
427
435
 
428
436
  Also `open chrome` command works like `open vscode`.
429
437
 
430
- For more information about how to use Chrome debugging, you might want to read [here](https://developer.chrome.com/docs/devtools/)
438
+ For more information about how to use Chrome debugging, you might want to read [here](https://developer.chrome.com/docs/devtools/).
431
439
 
432
440
  ## Configuration
433
441
 
@@ -479,6 +487,7 @@ config set no_color true
479
487
  * `RUBY_DEBUG_SOCK_DIR` (`sock_dir`): UNIX Domain Socket remote debugging: socket directory
480
488
  * `RUBY_DEBUG_COOKIE` (`cookie`): Cookie for negotiation
481
489
  * `RUBY_DEBUG_OPEN_FRONTEND` (`open_frontend`): frontend used by open command (vscode, chrome, default: rdbg).
490
+ * `RUBY_DEBUG_CHROME_PATH` (`chrome_path`): Platform dependent path of Chrome (For more information, See [here](https://github.com/ruby/debug/pull/334/files#diff-5fc3d0a901379a95bc111b86cf0090b03f857edfd0b99a0c1537e26735698453R55-R64))
482
491
 
483
492
  * OBSOLETE
484
493
  * `RUBY_DEBUG_PARENT_ON_FORK` (`parent_on_fork`): Keep debugging parent process on fork (default: false)
@@ -525,7 +534,7 @@ The `<...>` notation means the argument.
525
534
  * `fin[ish]`
526
535
  * Finish this frame. Resume the program until the current frame is finished.
527
536
  * `fin[ish] <n>`
528
- * Finish frames, same as `step <n>`.
537
+ * Finish `<n>`th frames.
529
538
  * `c[ontinue]`
530
539
  * Resume the program.
531
540
  * `q[uit]` or `Ctrl-D`
@@ -533,11 +542,11 @@ The `<...>` notation means the argument.
533
542
  * `q[uit]!`
534
543
  * Same as q[uit] but without the confirmation prompt.
535
544
  * `kill`
536
- * Stop the debuggee process with `Kernal#exit!`.
545
+ * Stop the debuggee process with `Kernel#exit!`.
537
546
  * `kill!`
538
547
  * Same as kill but without the confirmation prompt.
539
548
  * `sigint`
540
- * Execute SIGINT handler registerred by the debuggee.
549
+ * Execute SIGINT handler registered by the debuggee.
541
550
  * Note that this command should be used just after stop by `SIGINT`.
542
551
 
543
552
  ### Breakpoint
@@ -558,14 +567,32 @@ The `<...>` notation means the argument.
558
567
  * break and run `<command>` before stopping.
559
568
  * `b[reak] ... do: <command>`
560
569
  * break and run `<command>`, and continue.
570
+ * `b[reak] ... path: <path>`
571
+ * break if the path matches to `<path>`. `<path>` can be a regexp with `/regexp/`.
561
572
  * `b[reak] if: <expr>`
562
573
  * break if: `<expr>` is true at any lines.
563
574
  * Note that this feature is super slow.
564
575
  * `catch <Error>`
565
576
  * Set breakpoint on raising `<Error>`.
577
+ * `catch ... if: <expr>`
578
+ * stops only if `<expr>` is true as well.
579
+ * `catch ... pre: <command>`
580
+ * runs `<command>` before stopping.
581
+ * `catch ... do: <command>`
582
+ * stops and run `<command>`, and continue.
583
+ * `catch ... path: <path>`
584
+ * stops if the exception is raised from a `<path>`. `<path>` can be a regexp with `/regexp/`.
566
585
  * `watch @ivar`
567
586
  * Stop the execution when the result of current scope's `@ivar` is changed.
568
587
  * Note that this feature is super slow.
588
+ * `watch ... if: <expr>`
589
+ * stops only if `<expr>` is true as well.
590
+ * `watch ... pre: <command>`
591
+ * runs `<command>` before stopping.
592
+ * `watch ... do: <command>`
593
+ * stops and run `<command>`, and continue.
594
+ * `watch ... path: <path>`
595
+ * stops if the path matches `<path>`. `<path>` can be a regexp with `/regexp/`.
569
596
  * `del[ete]`
570
597
  * delete all breakpoints.
571
598
  * `del[ete] <bpnum>`
@@ -604,8 +631,8 @@ The `<...>` notation means the argument.
604
631
  * Show information about accessible constants except toplevel constants.
605
632
  * `i[nfo] g[lobal[s]]`
606
633
  * Show information about global variables
607
- * `i[nfo] ... </pattern/>`
608
- * Filter the output with `</pattern/>`.
634
+ * `i[nfo] ... /regexp/`
635
+ * Filter the output with `/regexp/`.
609
636
  * `i[nfo] th[read[s]]`
610
637
  * Show all threads (same as `th[read]`).
611
638
  * `o[utline]` or `ls`
@@ -656,8 +683,8 @@ The `<...>` notation means the argument.
656
683
  * Add an exception tracer. It indicates raising exceptions.
657
684
  * `trace object <expr>`
658
685
  * Add an object tracer. It indicates that an object by `<expr>` is passed as a parameter or a receiver on method call.
659
- * `trace ... </pattern/>`
660
- * Indicates only matched events to `</pattern/>` (RegExp).
686
+ * `trace ... /regexp/`
687
+ * Indicates only matched events to `/regexp/`.
661
688
  * `trace ... into: <file>`
662
689
  * Save trace information into: `<file>`.
663
690
  * `trace off <num>`
data/Rakefile CHANGED
@@ -2,8 +2,6 @@ require "bundler/gem_tasks"
2
2
  require "rake/testtask"
3
3
 
4
4
  Rake::TestTask.new(:test) do |t|
5
- t.libs << "test"
6
- t.libs << "lib"
7
5
  t.test_files = FileList["test/**/*_test.rb"]
8
6
  end
9
7
 
@@ -17,7 +15,6 @@ begin
17
15
  rescue LoadError
18
16
  end
19
17
 
20
-
21
18
  task :default => [:clobber, :compile, 'README.md', :test]
22
19
 
23
20
  file 'README.md' => ['lib/debug/session.rb', 'lib/debug/config.rb',
@@ -28,7 +25,10 @@ file 'README.md' => ['lib/debug/session.rb', 'lib/debug/config.rb',
28
25
  puts 'README.md is updated.'
29
26
  end
30
27
 
31
- task :run => :compile do
32
- system(RbConfig.ruby, *%w(-I ./lib test.rb))
28
+ task :test_protocol do
29
+ ENV['RUBY_DEBUG_PROTOCOL_TEST'] = '1'
33
30
  end
34
31
 
32
+ Rake::TestTask.new(:test_protocol) do |t|
33
+ t.test_files = FileList["test/protocol/*_test.rb"]
34
+ end
data/debug.gemspec CHANGED
@@ -7,7 +7,7 @@ Gem::Specification.new do |spec|
7
7
  spec.email = ["ko1@atdot.net"]
8
8
 
9
9
  spec.summary = %q{Debugging functionality for Ruby}
10
- spec.description = %q{Debugging functionality for Ruby. This is completely rewritten debug.rb which was contained by the encient Ruby versions.}
10
+ spec.description = %q{Debugging functionality for Ruby. This is completely rewritten debug.rb which was contained by the ancient Ruby versions.}
11
11
  spec.homepage = "https://github.com/ruby/debug"
12
12
  spec.licenses = ["Ruby", "BSD-2-Clause"]
13
13
  spec.required_ruby_version = Gem::Requirement.new(">= 2.6.0")
@@ -17,11 +17,13 @@ Gem::Specification.new do |spec|
17
17
 
18
18
  # Specify which files should be added to the gem when it is released.
19
19
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
20
- spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
21
- `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
20
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
21
+ `git ls-files -z`.split("\x0").reject do |f|
22
+ (f == __FILE__) || f.match(%r{\A(?:(?:bin|test|spec|features)/|\.(?:git|travis|circleci)|appveyor)})
23
+ end
22
24
  end
23
25
  spec.bindir = "exe"
24
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
26
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
25
27
  spec.require_paths = ["lib"]
26
28
  spec.extensions = ['ext/debug/extconf.rb']
27
29
 
data/ext/debug/debug.c CHANGED
@@ -32,7 +32,10 @@ di_entry(VALUE loc, VALUE self, VALUE binding, VALUE iseq, VALUE klass, VALUE de
32
32
  // :show_line, :local_variables
33
33
  Qnil,
34
34
  // :_local_variables, :_callee # for recorder
35
- Qnil, Qnil);
35
+ Qnil, Qnil,
36
+ // :dupped_binding
37
+ Qnil
38
+ );
36
39
  }
37
40
 
38
41
  static int
@@ -115,11 +118,82 @@ create_method_added_tracker(VALUE self)
115
118
  return rb_tracepoint_new(0, RUBY_EVENT_CALL, method_added_tracker, NULL);
116
119
  }
117
120
 
121
+ // iseq
122
+
123
+ const struct rb_iseq *rb_iseqw_to_iseq(VALUE iseqw);
124
+
125
+ #ifdef HAVE_RB_ISEQ_TYPE
126
+ VALUE rb_iseq_type(const struct rb_iseq *);
127
+
128
+ static VALUE
129
+ iseq_type(VALUE iseqw)
130
+ {
131
+ const struct rb_iseq *iseq = rb_iseqw_to_iseq(iseqw);
132
+ return rb_iseq_type(iseq);
133
+ }
134
+ #endif
135
+
136
+ #ifdef HAVE_RB_ISEQ_PARAMETERS
137
+ VALUE rb_iseq_parameters(const struct rb_iseq *, int is_proc);
138
+
139
+ static VALUE
140
+ iseq_parameters_symbols(VALUE iseqw)
141
+ {
142
+ const struct rb_iseq *iseq = rb_iseqw_to_iseq(iseqw);
143
+ VALUE params = rb_iseq_parameters(iseq, 0);
144
+ VALUE ary = rb_ary_new();
145
+
146
+ static VALUE sym_ast, sym_astast, sym_amp;
147
+
148
+ if (sym_ast == 0) {
149
+ sym_ast = ID2SYM(rb_intern("*"));
150
+ sym_astast = ID2SYM(rb_intern("**"));
151
+ sym_amp = ID2SYM(rb_intern("&"));
152
+ }
153
+
154
+ for (long i=0; i<RARRAY_LEN(params); i++) {
155
+ VALUE e = RARRAY_AREF(params, i);
156
+ if (RARRAY_LEN(e) == 2) {
157
+ VALUE sym = RARRAY_AREF(e, 1);
158
+ if (sym != sym_ast &&
159
+ sym != sym_astast &&
160
+ sym != sym_amp) rb_ary_push(ary, RARRAY_AREF(e, 1));
161
+ }
162
+ }
163
+
164
+ return ary;
165
+ }
166
+ #endif
167
+
168
+ #ifdef HAVE_RB_ISEQ_CODE_LOCATION
169
+ void rb_iseq_code_location(const struct rb_iseq *, int *first_lineno, int *first_column, int *last_lineno, int *last_column);
170
+
171
+ static VALUE
172
+ iseq_first_line(VALUE iseqw)
173
+ {
174
+ const struct rb_iseq *iseq = rb_iseqw_to_iseq(iseqw);
175
+ int line;
176
+ rb_iseq_code_location(iseq, &line, NULL, NULL, NULL);
177
+ return INT2NUM(line);
178
+ }
179
+
180
+ static VALUE
181
+ iseq_last_line(VALUE iseqw)
182
+ {
183
+ const struct rb_iseq *iseq = rb_iseqw_to_iseq(iseqw);
184
+ int line;
185
+ rb_iseq_code_location(iseq, NULL, NULL, &line, NULL);
186
+ return INT2NUM(line);
187
+ }
188
+ #endif
189
+
118
190
  void Init_iseq_collector(void);
119
191
 
120
192
  void
121
193
  Init_debug(void)
122
194
  {
195
+ VALUE rb_mRubyVM = rb_const_get(rb_cObject, rb_intern("RubyVM"));
196
+ VALUE rb_cISeq = rb_const_get(rb_mRubyVM, rb_intern("InstructionSequence"));
123
197
  rb_mDebugger = rb_const_get(rb_cObject, rb_intern("DEBUGGER__"));
124
198
  rb_cFrameInfo = rb_const_get(rb_mDebugger, rb_intern("FrameInfo"));
125
199
 
@@ -131,5 +205,18 @@ Init_debug(void)
131
205
  rb_define_singleton_method(rb_mDebugger, "frame_depth", frame_depth, 0);
132
206
  rb_define_singleton_method(rb_mDebugger, "create_method_added_tracker", create_method_added_tracker, 0);
133
207
  rb_define_const(rb_mDebugger, "SO_VERSION", rb_str_new2(RUBY_DEBUG_VERSION));
208
+
209
+ // iseq
210
+ #ifdef HAVE_RB_ISEQ_TYPE
211
+ rb_define_method(rb_cISeq, "type", iseq_type, 0);
212
+ #endif
213
+ #ifdef HAVE_RB_ISEQ_PARAMETERS
214
+ rb_define_method(rb_cISeq, "parameters_symbols", iseq_parameters_symbols, 0);
215
+ #endif
216
+ #ifdef HAVE_RB_ISEQ_CODE_LOCATION
217
+ rb_define_method(rb_cISeq, "first_line", iseq_first_line, 0);
218
+ rb_define_method(rb_cISeq, "last_line", iseq_last_line, 0);
219
+ #endif
220
+
134
221
  Init_iseq_collector();
135
222
  }
data/ext/debug/extconf.rb CHANGED
@@ -1,4 +1,15 @@
1
1
  require 'mkmf'
2
2
  require_relative '../../lib/debug/version'
3
3
  File.write("debug_version.h", "#define RUBY_DEBUG_VERSION \"#{DEBUGGER__::VERSION}\"\n")
4
+
5
+ have_func "rb_iseq_parameters(NULL, 0)",
6
+ [["VALUE rb_iseq_parameters(void *, int is_proc);"]]
7
+
8
+ have_func "rb_iseq_code_location(NULL, NULL, NULL, NULL, NULL)",
9
+ [["void rb_iseq_code_location(void *, int *first_lineno, int *first_column, int *last_lineno, int *last_column);"]]
10
+
11
+ # from Ruby 3.1
12
+ have_func "rb_iseq_type(NULL)",
13
+ [["VALUE rb_iseq_type(void *);"]]
14
+
4
15
  create_makefile 'debug/debug'