readapt 0.7.1 → 1.1.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 (70) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +16 -14
  3. data/.rspec +2 -2
  4. data/.travis.yml +18 -13
  5. data/CHANGELOG.md +76 -53
  6. data/Gemfile +4 -4
  7. data/LICENSE.txt +21 -21
  8. data/README.md +37 -29
  9. data/Rakefile +14 -25
  10. data/bin/console +14 -14
  11. data/bin/setup +8 -8
  12. data/exe/readapt +5 -5
  13. data/ext/readapt/breakpoints.c +83 -88
  14. data/ext/readapt/breakpoints.h +11 -12
  15. data/ext/readapt/extconf.rb +0 -0
  16. data/ext/readapt/frame.c +137 -0
  17. data/ext/readapt/frame.h +17 -0
  18. data/ext/readapt/hash_table.c +211 -212
  19. data/ext/readapt/hash_table.h +30 -32
  20. data/ext/readapt/inspector.c +51 -0
  21. data/ext/readapt/inspector.h +8 -0
  22. data/ext/readapt/monitor.c +40 -27
  23. data/ext/readapt/monitor.h +0 -0
  24. data/ext/readapt/normalize.c +59 -53
  25. data/ext/readapt/normalize.h +7 -7
  26. data/ext/readapt/readapt.c +18 -16
  27. data/ext/readapt/stack.c +86 -0
  28. data/ext/readapt/stack.h +20 -0
  29. data/ext/readapt/threads.c +111 -17
  30. data/ext/readapt/threads.h +11 -4
  31. data/lib/readapt.rb +21 -19
  32. data/lib/readapt/adapter.rb +98 -138
  33. data/lib/readapt/breakpoint.rb +20 -13
  34. data/lib/readapt/data_reader.rb +62 -0
  35. data/lib/readapt/debugger.rb +220 -204
  36. data/lib/readapt/error.rb +63 -0
  37. data/lib/readapt/finder.rb +20 -20
  38. data/lib/readapt/frame.rb +40 -42
  39. data/lib/readapt/input.rb +7 -0
  40. data/lib/readapt/message.rb +62 -59
  41. data/lib/readapt/message/attach.rb +11 -11
  42. data/lib/readapt/message/base.rb +32 -32
  43. data/lib/readapt/message/configuration_done.rb +11 -11
  44. data/lib/readapt/message/continue.rb +15 -15
  45. data/lib/readapt/message/disconnect.rb +13 -14
  46. data/lib/readapt/message/evaluate.rb +18 -18
  47. data/lib/readapt/message/initialize.rb +13 -13
  48. data/lib/readapt/message/launch.rb +11 -11
  49. data/lib/readapt/message/next.rb +12 -12
  50. data/lib/readapt/message/pause.rb +11 -11
  51. data/lib/readapt/message/scopes.rb +26 -25
  52. data/lib/readapt/message/set_breakpoints.rb +25 -25
  53. data/lib/readapt/message/set_exception_breakpoints.rb +8 -8
  54. data/lib/readapt/message/stack_trace.rb +38 -26
  55. data/lib/readapt/message/step_in.rb +11 -11
  56. data/lib/readapt/message/step_out.rb +11 -11
  57. data/lib/readapt/message/threads.rb +18 -18
  58. data/lib/readapt/message/variables.rb +61 -57
  59. data/lib/readapt/monitor.rb +0 -0
  60. data/lib/readapt/output.rb +25 -0
  61. data/lib/readapt/references.rb +27 -0
  62. data/lib/readapt/server.rb +22 -0
  63. data/lib/readapt/shell.rb +104 -39
  64. data/lib/readapt/snapshot.rb +1 -13
  65. data/lib/readapt/thread.rb +23 -39
  66. data/lib/readapt/variable.rb +1 -1
  67. data/lib/readapt/version.rb +3 -3
  68. data/readapt.gemspec +39 -39
  69. metadata +19 -8
  70. data/lib/readapt/location.rb +0 -25
@@ -1,14 +1,13 @@
1
- # frozen_string_literal: true
2
-
3
- module Readapt
4
- module Message
5
- class Disconnect < Base
6
- def run
7
- # HACK: Wait a moment to make sure the output is flushed
8
- # @todo Find a better way
9
- sleep 1
10
- debugger.disconnect
11
- end
12
- end
13
- end
14
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Readapt
4
+ module Message
5
+ class Disconnect < Base
6
+ def run
7
+ # The message only sets an empty body to acknowledge that the request
8
+ # was received. The adapter handles the actual disconnection process.
9
+ set_body({})
10
+ end
11
+ end
12
+ end
13
+ end
@@ -1,18 +1,18 @@
1
- # frozen_string_literal: true
2
-
3
- require 'json'
4
-
5
- module Readapt
6
- module Message
7
- class Evaluate < Base
8
- def run
9
- ref = arguments['frameId']
10
- frame = debugger.frame(ref)
11
- result = frame.evaluate(arguments['expression'])
12
- set_body(
13
- result: result
14
- )
15
- end
16
- end
17
- end
18
- end
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+
5
+ module Readapt
6
+ module Message
7
+ class Evaluate < Base
8
+ def run
9
+ ref = arguments['frameId']
10
+ frame = debugger.frame(ref)
11
+ result = frame.evaluate(arguments['expression'])
12
+ set_body(
13
+ result: result
14
+ )
15
+ end
16
+ end
17
+ end
18
+ end
@@ -1,13 +1,13 @@
1
- # frozen_string_literal: true
2
-
3
- module Readapt
4
- module Message
5
- class Initialize < Base
6
- def run
7
- set_body({
8
- supportsConfigurationDoneRequest: true
9
- })
10
- end
11
- end
12
- end
13
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Readapt
4
+ module Message
5
+ class Initialize < Base
6
+ def run
7
+ set_body({
8
+ supportsConfigurationDoneRequest: true
9
+ })
10
+ end
11
+ end
12
+ end
13
+ end
@@ -1,11 +1,11 @@
1
- # frozen_string_literal: true
2
-
3
- module Readapt
4
- module Message
5
- class Launch < Base
6
- def run
7
- debugger.config arguments, :launch
8
- end
9
- end
10
- end
11
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Readapt
4
+ module Message
5
+ class Launch < Base
6
+ def run
7
+ debugger.config arguments, :launch
8
+ end
9
+ end
10
+ end
11
+ end
@@ -1,12 +1,12 @@
1
- # frozen_string_literal: true
2
-
3
- module Readapt
4
- module Message
5
- class Next < Base
6
- def run
7
- thread = debugger.thread(arguments['threadId'])
8
- thread.control = :next
9
- end
10
- end
11
- end
12
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Readapt
4
+ module Message
5
+ class Next < Base
6
+ def run
7
+ thread = debugger.thread(arguments['threadId'])
8
+ thread.control = :next
9
+ end
10
+ end
11
+ end
12
+ end
@@ -1,11 +1,11 @@
1
- # frozen_string_literal: true
2
-
3
- module Readapt
4
- module Message
5
- class Pause < Base
6
- def run
7
- Monitor.pause arguments['threadId']
8
- end
9
- end
10
- end
11
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Readapt
4
+ module Message
5
+ class Pause < Base
6
+ def run
7
+ Monitor.pause arguments['threadId']
8
+ end
9
+ end
10
+ end
11
+ end
@@ -1,25 +1,26 @@
1
- # frozen_string_literal: true
2
-
3
- module Readapt
4
- module Message
5
- class Scopes < Base
6
- def run
7
- frame = debugger.frame(arguments['frameId'])
8
- set_body({
9
- scopes: [
10
- {
11
- name: 'Local',
12
- variablesReference: frame.local_id,
13
- expensive: false
14
- },
15
- {
16
- name: 'Global',
17
- variablesReference: TOPLEVEL_BINDING.receiver.object_id,
18
- expensive: true
19
- }
20
- ]
21
- })
22
- end
23
- end
24
- end
25
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Readapt
4
+ module Message
5
+ class Scopes < Base
6
+ def run
7
+ frame = debugger.frame(arguments['frameId'])
8
+ set_body({
9
+ scopes: [
10
+ {
11
+ name: 'Local',
12
+ variablesReference: frame.local_id,
13
+ expensive: false
14
+ },
15
+ {
16
+ name: 'Global',
17
+ # @todo 1 is a magic number representing the toplevel binding
18
+ variablesReference: 1,
19
+ expensive: true
20
+ }
21
+ ]
22
+ })
23
+ end
24
+ end
25
+ end
26
+ end
@@ -1,25 +1,25 @@
1
- # frozen_string_literal: true
2
-
3
- module Readapt
4
- module Message
5
- class SetBreakpoints < Base
6
- def run
7
- path = Readapt.normalize_path(arguments['source']['path'])
8
- debugger.clear_breakpoints path
9
- lines = []
10
- set_body(
11
- breakpoints: arguments['breakpoints'].map do |val|
12
- debugger.set_breakpoint path, val['line'], val['condition']
13
- lines.push val['line']
14
- {
15
- verified: true, # @todo Verify
16
- source: arguments['source'],
17
- line: val['line']
18
- }
19
- end
20
- )
21
- Breakpoints.set(path, lines)
22
- end
23
- end
24
- end
25
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Readapt
4
+ module Message
5
+ class SetBreakpoints < Base
6
+ def run
7
+ path = Readapt.normalize_path(arguments['source']['path'])
8
+ debugger.clear_breakpoints path
9
+ lines = []
10
+ set_body(
11
+ breakpoints: arguments['breakpoints'].map do |val|
12
+ debugger.set_breakpoint path, val['line'], val['condition'], val['hitCondition']
13
+ lines.push val['line']
14
+ {
15
+ verified: true, # @todo Verify
16
+ source: arguments['source'],
17
+ line: val['line']
18
+ }
19
+ end
20
+ )
21
+ Breakpoints.set(path, lines)
22
+ end
23
+ end
24
+ end
25
+ end
@@ -1,8 +1,8 @@
1
- # frozen_string_literal: true
2
-
3
- module Readapt
4
- module Message
5
- class SetExceptionBreakpoints < Base
6
- end
7
- end
8
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Readapt
4
+ module Message
5
+ class SetExceptionBreakpoints < Base
6
+ end
7
+ end
8
+ end
@@ -1,26 +1,38 @@
1
- # frozen_string_literal: true
2
-
3
- module Readapt
4
- module Message
5
- class StackTrace < Base
6
- def run
7
- frames = debugger.thread(arguments['threadId']).frames
8
- set_body({
9
- stackFrames: frames.map do |frm|
10
- {
11
- name: "#{File.basename(frm.location.file)}:#{frm.location.line}",
12
- source: {
13
- name: File.basename(frm.location.file),
14
- path: frm.location.file
15
- },
16
- id: frm.local_id,
17
- line: frm.location.line,
18
- column: 0
19
- }
20
- end,
21
- totalFrames: frames.length
22
- })
23
- end
24
- end
25
- end
26
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Readapt
4
+ module Message
5
+ class StackTrace < Base
6
+ @@file_hash = {}
7
+
8
+ def run
9
+ frames = debugger.thread(arguments['threadId']).frames
10
+ set_body({
11
+ stackFrames: frames.map do |frm|
12
+ {
13
+ name: frame_code(frm.file, frm.line),
14
+ source: {
15
+ name: frm.file ? File.basename(frm.file) : nil,
16
+ path: frm.file
17
+ },
18
+ id: frm.local_id,
19
+ line: frm.line,
20
+ column: 0
21
+ }
22
+ end,
23
+ totalFrames: frames.length
24
+ })
25
+ end
26
+
27
+ private
28
+
29
+ def read_file file
30
+ @@file_hash[file] ||= File.read(file)
31
+ end
32
+
33
+ def frame_code file, line
34
+ read_file(file).lines[line - 1].strip
35
+ end
36
+ end
37
+ end
38
+ end
@@ -1,11 +1,11 @@
1
- # frozen_string_literal: true
2
-
3
- module Readapt
4
- module Message
5
- class StepIn < Base
6
- def run
7
- debugger.thread(arguments['threadId']).control = :step_in
8
- end
9
- end
10
- end
11
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Readapt
4
+ module Message
5
+ class StepIn < Base
6
+ def run
7
+ debugger.thread(arguments['threadId']).control = :step_in
8
+ end
9
+ end
10
+ end
11
+ end
@@ -1,11 +1,11 @@
1
- # frozen_string_literal: true
2
-
3
- module Readapt
4
- module Message
5
- class StepOut < Base
6
- def run
7
- debugger.thread(arguments['threadId']).control = :step_out
8
- end
9
- end
10
- end
11
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Readapt
4
+ module Message
5
+ class StepOut < Base
6
+ def run
7
+ debugger.thread(arguments['threadId']).control = :step_out
8
+ end
9
+ end
10
+ end
11
+ end
@@ -1,18 +1,18 @@
1
- # frozen_string_literal: true
2
-
3
- module Readapt
4
- module Message
5
- class Threads < Base
6
- def run
7
- set_body({
8
- threads: debugger.threads.map do |thr|
9
- {
10
- id: thr.id,
11
- name: thr.name
12
- }
13
- end
14
- })
15
- end
16
- end
17
- end
18
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Readapt
4
+ module Message
5
+ class Threads < Base
6
+ def run
7
+ set_body({
8
+ threads: debugger.threads.map do |thr|
9
+ {
10
+ id: thr.id,
11
+ name: thr.name
12
+ }
13
+ end
14
+ })
15
+ end
16
+ end
17
+ end
18
+ end
@@ -1,57 +1,61 @@
1
- # frozen_string_literal: true
2
-
3
- module Readapt
4
- module Message
5
- class Variables < Base
6
- def run
7
- ref = arguments['variablesReference']
8
- frame = debugger.frame(ref)
9
- vars = if frame != Frame::NULL_FRAME && !frame.nil?
10
- frame.locals
11
- elsif ref == TOPLEVEL_BINDING.receiver.object_id
12
- global_variables.map do |gv|
13
- Variable.new(gv, eval(gv.to_s))
14
- end
15
- else
16
- obj = object_reference
17
- result = []
18
- if obj.is_a?(Array)
19
- obj.each_with_index do |itm, idx|
20
- result.push Variable.new("[#{idx}]", itm)
21
- end
22
- elsif obj.is_a?(Hash)
23
- obj.each_pair do |idx, itm|
24
- result.push Variable.new("[#{idx}]", itm)
25
- end
26
- else
27
- obj.instance_variables.each do |iv|
28
- result.push Variable.new(iv, obj.instance_variable_get(iv))
29
- end
30
- obj.class.class_variables.each do |cv|
31
- result.push Variable.new(cv, obj.class.class_variable_get(cv))
32
- end
33
- end
34
- result
35
- end
36
- set_body({
37
- variables: vars.map do |var|
38
- {
39
- name: var.name,
40
- value: var.value,
41
- type: var.type,
42
- variablesReference: var.reference
43
- }
44
- end
45
- })
46
- end
47
-
48
- private
49
-
50
- def object_reference
51
- ObjectSpace._id2ref(arguments['variablesReference'])
52
- rescue RangeError
53
- nil
54
- end
55
- end
56
- end
57
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Readapt
4
+ module Message
5
+ class Variables < Base
6
+ def run
7
+ ref = arguments['variablesReference']
8
+ frame = debugger.frame(ref)
9
+ # @todo 1 is a magic number representing the toplevel binding (see
10
+ # Message::Scopes)
11
+ vars = if ref == 1
12
+ global_variables.map do |gv|
13
+ Variable.new(gv, eval(gv.to_s))
14
+ end
15
+ else
16
+ if frame != Frame::NULL_FRAME && !frame.nil?
17
+ frame.locals
18
+ else
19
+ obj = object_reference
20
+ result = []
21
+ if obj.is_a?(Array)
22
+ obj.each_with_index do |itm, idx|
23
+ result.push Variable.new("[#{idx}]", itm)
24
+ end
25
+ elsif obj.is_a?(Hash)
26
+ obj.each_pair do |idx, itm|
27
+ result.push Variable.new("[#{idx}]", itm)
28
+ end
29
+ else
30
+ obj.instance_variables.sort.each do |iv|
31
+ result.push Variable.new(iv, obj.instance_variable_get(iv))
32
+ end
33
+ obj.class.class_variables.sort.each do |cv|
34
+ result.push Variable.new(cv, obj.class.class_variable_get(cv))
35
+ end
36
+ end
37
+ result
38
+ end
39
+ end
40
+ set_body({
41
+ variables: vars.map do |var|
42
+ {
43
+ name: var.name,
44
+ value: var.value,
45
+ type: var.type,
46
+ variablesReference: var.reference
47
+ }
48
+ end
49
+ })
50
+ end
51
+
52
+ private
53
+
54
+ def object_reference
55
+ ObjectSpace._id2ref(arguments['variablesReference'])
56
+ rescue RangeError
57
+ nil
58
+ end
59
+ end
60
+ end
61
+ end