readapt 1.0.0 → 1.1.0

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 (69) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +16 -15
  3. data/.rspec +2 -2
  4. data/.travis.yml +18 -18
  5. data/CHANGELOG.md +72 -69
  6. data/Gemfile +4 -4
  7. data/LICENSE.txt +21 -21
  8. data/README.md +37 -29
  9. data/Rakefile +14 -14
  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 -83
  14. data/ext/readapt/breakpoints.h +11 -11
  15. data/ext/readapt/extconf.rb +0 -0
  16. data/ext/readapt/frame.c +137 -137
  17. data/ext/readapt/frame.h +17 -17
  18. data/ext/readapt/hash_table.c +211 -211
  19. data/ext/readapt/hash_table.h +30 -30
  20. data/ext/readapt/inspector.c +51 -51
  21. data/ext/readapt/inspector.h +8 -8
  22. data/ext/readapt/monitor.c +1 -1
  23. data/ext/readapt/monitor.h +0 -0
  24. data/ext/readapt/normalize.c +59 -59
  25. data/ext/readapt/normalize.h +7 -7
  26. data/ext/readapt/readapt.c +18 -18
  27. data/ext/readapt/stack.c +86 -86
  28. data/ext/readapt/stack.h +20 -20
  29. data/ext/readapt/threads.c +15 -11
  30. data/ext/readapt/threads.h +1 -1
  31. data/lib/readapt.rb +21 -20
  32. data/lib/readapt/adapter.rb +98 -98
  33. data/lib/readapt/breakpoint.rb +20 -20
  34. data/lib/readapt/data_reader.rb +62 -62
  35. data/lib/readapt/debugger.rb +220 -220
  36. data/lib/readapt/error.rb +63 -63
  37. data/lib/readapt/finder.rb +20 -20
  38. data/lib/readapt/frame.rb +40 -40
  39. data/lib/readapt/input.rb +7 -7
  40. data/lib/readapt/message.rb +62 -62
  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 -13
  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 -26
  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 -38
  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 -61
  59. data/lib/readapt/monitor.rb +0 -0
  60. data/lib/readapt/output.rb +25 -25
  61. data/lib/readapt/references.rb +27 -0
  62. data/lib/readapt/server.rb +22 -22
  63. data/lib/readapt/shell.rb +104 -104
  64. data/lib/readapt/snapshot.rb +0 -0
  65. data/lib/readapt/thread.rb +23 -23
  66. data/lib/readapt/variable.rb +1 -1
  67. data/lib/readapt/version.rb +3 -3
  68. data/readapt.gemspec +39 -39
  69. metadata +4 -3
@@ -1,20 +1,20 @@
1
- #ifndef STACK_H_
2
- #define STACK_H_
3
-
4
- #include "stddef.h"
5
-
6
- typedef struct readapt_stack_struct {
7
- int size;
8
- size_t elem_size;
9
- void (*free_func)(void *);
10
- int capacity;
11
- void **elements;
12
- } readapt_stack_t;
13
-
14
- readapt_stack_t *stack_alloc(size_t elem_size, void(*free_func)(void*));
15
- void stack_push(readapt_stack_t *stack, void *element);
16
- void *stack_peek(readapt_stack_t *stack);
17
- void stack_pop(readapt_stack_t *stack);
18
- void stack_free(readapt_stack_t *stack);
19
-
20
- #endif
1
+ #ifndef STACK_H_
2
+ #define STACK_H_
3
+
4
+ #include "stddef.h"
5
+
6
+ typedef struct readapt_stack_struct {
7
+ int size;
8
+ size_t elem_size;
9
+ void (*free_func)(void *);
10
+ int capacity;
11
+ void **elements;
12
+ } readapt_stack_t;
13
+
14
+ readapt_stack_t *stack_alloc(size_t elem_size, void(*free_func)(void*));
15
+ void stack_push(readapt_stack_t *stack, void *element);
16
+ void *stack_peek(readapt_stack_t *stack);
17
+ void stack_pop(readapt_stack_t *stack);
18
+ void stack_free(readapt_stack_t *stack);
19
+
20
+ #endif
@@ -6,13 +6,14 @@
6
6
 
7
7
  static VALUE c_Thread;
8
8
  static VALUE threads;
9
+ static VALUE ids;
10
+ static int next_id;
9
11
 
10
12
  static void thread_reference_free(void* data)
11
13
  {
12
14
  thread_reference_t* thr;
13
15
 
14
16
  thr = data;
15
- // stack_free(thr->calls);
16
17
  stack_free(thr->frames);
17
18
  free(thr);
18
19
  }
@@ -37,12 +38,12 @@ static VALUE thread_reference_new(VALUE thr)
37
38
  {
38
39
  thread_reference_t *data = malloc(sizeof(thread_reference_t));
39
40
  VALUE obj = TypedData_Make_Struct(c_Thread, thread_reference_t, &thread_reference_type, data);
40
- data->id = NUM2LONG(rb_funcall(thr, rb_intern("object_id"), 0));
41
+ data->id = next_id;
41
42
  data->cursor = 0;
42
43
  data->depth = 0;
43
44
  data->control = rb_intern("continue");
44
45
  data->frames = stack_alloc(sizeof(frame_t), frame_free);
45
- // data->calls = stack_alloc(sizeof(frame_t), NULL);
46
+ next_id++;
46
47
  return obj;
47
48
  }
48
49
 
@@ -65,20 +66,24 @@ VALUE thread_reference(VALUE thr)
65
66
 
66
67
  VALUE thread_reference_id(VALUE id)
67
68
  {
68
- return rb_hash_aref(threads, id);
69
+ return rb_hash_aref(ids, id);
69
70
  }
70
71
 
71
72
  VALUE thread_add_reference(VALUE thr)
72
73
  {
73
74
  VALUE ref;
75
+ thread_reference_t *ptr;
74
76
 
75
77
  ref = thread_reference_new(thr);
78
+ ptr = thread_reference_pointer(ref);
76
79
  rb_hash_aset(threads, rb_obj_id(thr), ref);
80
+ rb_hash_aset(ids, INT2NUM(ptr->id), ref);
77
81
  return ref;
78
82
  }
79
83
 
80
84
  VALUE thread_delete_reference(VALUE thr)
81
85
  {
86
+ // TODO: Do we need to delete from ids here?
82
87
  return rb_hash_delete(threads, rb_obj_id(thr));
83
88
  }
84
89
 
@@ -101,6 +106,7 @@ void thread_pause()
101
106
  void thread_clear()
102
107
  {
103
108
  rb_funcall(threads, rb_intern("clear"), 0);
109
+ rb_funcall(ids, rb_intern("clear"), 0);
104
110
  }
105
111
 
106
112
  static VALUE thread_allocate_s(VALUE self)
@@ -110,7 +116,6 @@ static VALUE thread_allocate_s(VALUE self)
110
116
  data->depth = 0;
111
117
  data->cursor = 0;
112
118
  data->frames = stack_alloc(sizeof(frame_t), frame_free);
113
- // data->calls = stack_alloc(sizeof(frame_t), NULL);
114
119
  data->id = 0;
115
120
  return TypedData_Wrap_Struct(self, &thread_reference_type, data);
116
121
  }
@@ -127,7 +132,7 @@ static VALUE thread_find_s(VALUE self, VALUE id)
127
132
 
128
133
  static VALUE thread_include_s(VALUE self, VALUE id)
129
134
  {
130
- return rb_funcall(threads, rb_intern("include?"), 1, id);
135
+ return rb_funcall(ids, rb_intern("include?"), 1, id);
131
136
  }
132
137
 
133
138
  static VALUE thread_id_m(VALUE self)
@@ -167,17 +172,14 @@ void thread_reference_build_frames(thread_reference_t *ptr)
167
172
 
168
173
  void thread_reference_clear_frames(thread_reference_t *ptr)
169
174
  {
170
- // TODO This is probably suboptimal
171
- // while (ptr->frames->size > 0)
172
- // {
173
- // stack_pop(ptr->frames);
174
- // }
175
175
  stack_free(ptr->frames);
176
176
  ptr->frames = stack_alloc(sizeof(frame_t), frame_free);
177
177
  }
178
178
 
179
179
  void initialize_threads(VALUE m_Readapt)
180
180
  {
181
+ next_id = 1;
182
+
181
183
  c_Thread = rb_define_class_under(m_Readapt, "Thread", rb_cData);
182
184
  rb_define_alloc_func(c_Thread, thread_allocate_s);
183
185
  rb_define_method(c_Thread, "id", thread_id_m, 0);
@@ -188,4 +190,6 @@ void initialize_threads(VALUE m_Readapt)
188
190
 
189
191
  threads = rb_hash_new();
190
192
  rb_global_variable(&threads);
193
+ ids = rb_hash_new();
194
+ rb_global_variable(&ids);
191
195
  }
@@ -6,7 +6,7 @@
6
6
  #include "stack.h"
7
7
 
8
8
  typedef struct thread_reference_struct {
9
- long id;
9
+ int id;
10
10
  int cursor;
11
11
  int depth;
12
12
  ID control;
@@ -1,20 +1,21 @@
1
- require 'backport'
2
-
3
- require 'readapt/version'
4
- require 'readapt/readapt'
5
- require 'readapt/breakpoint'
6
- require 'readapt/thread'
7
- require 'readapt/frame'
8
- require 'readapt/monitor'
9
- require 'readapt/snapshot'
10
- require 'readapt/finder'
11
- require 'readapt/debugger'
12
- require 'readapt/message'
13
- require 'readapt/variable'
14
- require 'readapt/data_reader'
15
- require 'readapt/server'
16
- require 'readapt/adapter'
17
- require 'readapt/input'
18
- require 'readapt/output'
19
- require 'readapt/error'
20
- require 'readapt/shell'
1
+ require 'backport'
2
+
3
+ require 'readapt/version'
4
+ require 'readapt/readapt'
5
+ require 'readapt/references'
6
+ require 'readapt/breakpoint'
7
+ require 'readapt/thread'
8
+ require 'readapt/frame'
9
+ require 'readapt/monitor'
10
+ require 'readapt/snapshot'
11
+ require 'readapt/finder'
12
+ require 'readapt/debugger'
13
+ require 'readapt/message'
14
+ require 'readapt/variable'
15
+ require 'readapt/data_reader'
16
+ require 'readapt/server'
17
+ require 'readapt/adapter'
18
+ require 'readapt/input'
19
+ require 'readapt/output'
20
+ require 'readapt/error'
21
+ require 'readapt/shell'
@@ -1,98 +1,98 @@
1
- # frozen_string_literal: true
2
-
3
- require 'json'
4
-
5
- module Readapt
6
- module Adapter
7
- # @!parse include Backport::Adapter
8
-
9
- @@debugger = nil
10
-
11
- def self.host debugger
12
- @@debugger = debugger
13
- end
14
-
15
- def self.procid= pid
16
- @@procid = pid
17
- end
18
-
19
- def procid
20
- @@procid
21
- end
22
-
23
- def open_message
24
- @@open_message ||= "<readapt-#{procid}>"
25
- end
26
-
27
- def close_message
28
- @@close_message ||= "</readapt-#{procid}>"
29
- end
30
-
31
- def format result
32
- write_line result.to_protocol.to_json
33
- end
34
-
35
- def opening
36
- @@debugger.add_observer self
37
- @data_reader = DataReader.new
38
- @data_reader.set_message_handler do |message|
39
- process message
40
- end
41
- end
42
-
43
- def closing
44
- @@debugger.delete_observer(self)
45
- end
46
-
47
- def receiving data
48
- @data_reader.receive data
49
- end
50
-
51
- def update event, data
52
- obj = {
53
- type: 'event',
54
- event: event
55
- }
56
- obj[:body] = data unless data.nil?
57
- json = obj.to_json
58
- envelope = "#{open_message}Content-Length: #{json.bytesize}\r\n\r\n#{json}#{close_message}"
59
- write envelope
60
- write "#{open_message}__TERMINATE__#{close_message}" if event == 'terminated'
61
- end
62
-
63
- private
64
-
65
- # @param data [Hash]
66
- # @return [void]
67
- def process data
68
- message = Message.process(data, @@debugger)
69
- if data['seq']
70
- json = {
71
- type: 'response',
72
- request_seq: data['seq'],
73
- success: true,
74
- command: data['command'],
75
- body: message.body
76
- }.to_json
77
- envelope = "Content-Length: #{json.bytesize}\r\n\r\n#{json}"
78
- write "#{open_message}#{envelope}#{close_message}"
79
- if data['command'] == 'disconnect'
80
- @@debugger.disconnect
81
- # @todo It does not appear necessary to close the adapter after
82
- # disconnecting the debugger.
83
- # close
84
- end
85
- return unless data['command'] == 'initialize'
86
- json = {
87
- type: 'event',
88
- event: 'initialized'
89
- }.to_json
90
- envelope = "Content-Length: #{json.bytesize}\r\n\r\n#{json}"
91
- write "#{open_message}#{envelope}#{close_message}"
92
- end
93
- rescue RuntimeError => e
94
- STDERR.puts "[#{e.class}] #{e.message}"
95
- STDERR.puts e.backtrace.join
96
- end
97
- end
98
- end
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+
5
+ module Readapt
6
+ module Adapter
7
+ # @!parse include Backport::Adapter
8
+
9
+ @@debugger = nil
10
+
11
+ def self.host debugger
12
+ @@debugger = debugger
13
+ end
14
+
15
+ def self.procid= pid
16
+ @@procid = pid
17
+ end
18
+
19
+ def procid
20
+ @@procid
21
+ end
22
+
23
+ def open_message
24
+ @@open_message ||= "<readapt-#{procid}>"
25
+ end
26
+
27
+ def close_message
28
+ @@close_message ||= "</readapt-#{procid}>"
29
+ end
30
+
31
+ def format result
32
+ write_line result.to_protocol.to_json
33
+ end
34
+
35
+ def opening
36
+ @@debugger.add_observer self
37
+ @data_reader = DataReader.new
38
+ @data_reader.set_message_handler do |message|
39
+ process message
40
+ end
41
+ end
42
+
43
+ def closing
44
+ @@debugger.delete_observer(self)
45
+ end
46
+
47
+ def receiving data
48
+ @data_reader.receive data
49
+ end
50
+
51
+ def update event, data
52
+ obj = {
53
+ type: 'event',
54
+ event: event
55
+ }
56
+ obj[:body] = data unless data.nil?
57
+ json = obj.to_json
58
+ envelope = "#{open_message}Content-Length: #{json.bytesize}\r\n\r\n#{json}#{close_message}"
59
+ write envelope
60
+ write "#{open_message}__TERMINATE__#{close_message}" if event == 'terminated'
61
+ end
62
+
63
+ private
64
+
65
+ # @param data [Hash]
66
+ # @return [void]
67
+ def process data
68
+ message = Message.process(data, @@debugger)
69
+ if data['seq']
70
+ json = {
71
+ type: 'response',
72
+ request_seq: data['seq'],
73
+ success: true,
74
+ command: data['command'],
75
+ body: message.body
76
+ }.to_json
77
+ envelope = "Content-Length: #{json.bytesize}\r\n\r\n#{json}"
78
+ write "#{open_message}#{envelope}#{close_message}"
79
+ if data['command'] == 'disconnect'
80
+ @@debugger.disconnect
81
+ # @todo It does not appear necessary to close the adapter after
82
+ # disconnecting the debugger.
83
+ # close
84
+ end
85
+ return unless data['command'] == 'initialize'
86
+ json = {
87
+ type: 'event',
88
+ event: 'initialized'
89
+ }.to_json
90
+ envelope = "Content-Length: #{json.bytesize}\r\n\r\n#{json}"
91
+ write "#{open_message}#{envelope}#{close_message}"
92
+ end
93
+ rescue RuntimeError => e
94
+ STDERR.puts "[#{e.class}] #{e.message}"
95
+ STDERR.puts e.backtrace.join
96
+ end
97
+ end
98
+ end
@@ -1,20 +1,20 @@
1
- module Readapt
2
- class Breakpoint
3
- attr_reader :source
4
- attr_reader :line
5
- attr_reader :condition
6
- attr_reader :hit_condition
7
- attr_writer :hit_cursor
8
-
9
- def initialize source, line, condition, hit_condition
10
- @source = source
11
- @line = line
12
- @condition = condition
13
- @hit_condition = hit_condition
14
- end
15
-
16
- def hit_cursor
17
- @hit_cursor ||= 0
18
- end
19
- end
20
- end
1
+ module Readapt
2
+ class Breakpoint
3
+ attr_reader :source
4
+ attr_reader :line
5
+ attr_reader :condition
6
+ attr_reader :hit_condition
7
+ attr_writer :hit_cursor
8
+
9
+ def initialize source, line, condition, hit_condition
10
+ @source = source
11
+ @line = line
12
+ @condition = condition
13
+ @hit_condition = hit_condition
14
+ end
15
+
16
+ def hit_cursor
17
+ @hit_cursor ||= 0
18
+ end
19
+ end
20
+ end
@@ -1,62 +1,62 @@
1
- module Readapt
2
- class DataReader
3
- def initialize
4
- @in_header = true
5
- @content_length = 0
6
- @buffer = String.new
7
- end
8
-
9
- # Declare a block to be executed for each message received from the
10
- # client.
11
- #
12
- # @yieldparam [Hash] The message received from the client
13
- def set_message_handler &block
14
- @message_handler = block
15
- end
16
-
17
- # Process raw data received from the client. The data will be parsed
18
- # into messages based on the JSON-RPC protocol. Each message will be
19
- # passed to the block declared via set_message_handler. Incomplete data
20
- # will be buffered and subsequent data will be appended to the buffer.
21
- #
22
- # @param data [String]
23
- def receive data
24
- data.each_char do |char|
25
- @buffer.concat char
26
- if @in_header
27
- prepare_to_parse_message if @buffer.end_with?("\r\n\r\n")
28
- else
29
- parse_message_from_buffer if @buffer.bytesize == @content_length
30
- end
31
- end
32
- end
33
-
34
- private
35
-
36
- def prepare_to_parse_message
37
- @in_header = false
38
- @buffer.each_line do |line|
39
- parts = line.split(':').map(&:strip)
40
- if parts[0] == 'Content-Length'
41
- @content_length = parts[1].to_i
42
- break
43
- end
44
- end
45
- @buffer.clear
46
- end
47
-
48
- def parse_message_from_buffer
49
- begin
50
- msg = JSON.parse(@buffer)
51
- @message_handler.call msg unless @message_handler.nil?
52
- rescue JSON::ParserError => e
53
- Solargraph::Logging.logger.warn "Failed to parse request: #{e.message}"
54
- Solargraph::Logging.logger.debug "Buffer: #{@buffer}"
55
- ensure
56
- @buffer.clear
57
- @in_header = true
58
- @content_length = 0
59
- end
60
- end
61
- end
62
- end
1
+ module Readapt
2
+ class DataReader
3
+ def initialize
4
+ @in_header = true
5
+ @content_length = 0
6
+ @buffer = String.new
7
+ end
8
+
9
+ # Declare a block to be executed for each message received from the
10
+ # client.
11
+ #
12
+ # @yieldparam [Hash] The message received from the client
13
+ def set_message_handler &block
14
+ @message_handler = block
15
+ end
16
+
17
+ # Process raw data received from the client. The data will be parsed
18
+ # into messages based on the JSON-RPC protocol. Each message will be
19
+ # passed to the block declared via set_message_handler. Incomplete data
20
+ # will be buffered and subsequent data will be appended to the buffer.
21
+ #
22
+ # @param data [String]
23
+ def receive data
24
+ data.each_char do |char|
25
+ @buffer.concat char
26
+ if @in_header
27
+ prepare_to_parse_message if @buffer.end_with?("\r\n\r\n")
28
+ else
29
+ parse_message_from_buffer if @buffer.bytesize == @content_length
30
+ end
31
+ end
32
+ end
33
+
34
+ private
35
+
36
+ def prepare_to_parse_message
37
+ @in_header = false
38
+ @buffer.each_line do |line|
39
+ parts = line.split(':').map(&:strip)
40
+ if parts[0] == 'Content-Length'
41
+ @content_length = parts[1].to_i
42
+ break
43
+ end
44
+ end
45
+ @buffer.clear
46
+ end
47
+
48
+ def parse_message_from_buffer
49
+ begin
50
+ msg = JSON.parse(@buffer)
51
+ @message_handler.call msg unless @message_handler.nil?
52
+ rescue JSON::ParserError => e
53
+ Solargraph::Logging.logger.warn "Failed to parse request: #{e.message}"
54
+ Solargraph::Logging.logger.debug "Buffer: #{@buffer}"
55
+ ensure
56
+ @buffer.clear
57
+ @in_header = true
58
+ @content_length = 0
59
+ end
60
+ end
61
+ end
62
+ end