readapt 0.8.0 → 1.2.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 (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 +80 -60
  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/inspector.c +51 -51
  19. data/ext/readapt/inspector.h +8 -8
  20. data/ext/readapt/{hash_table.c → lookup_table.c} +211 -211
  21. data/ext/readapt/lookup_table.h +30 -0
  22. data/ext/readapt/monitor.c +42 -5
  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 +2 -2
  31. data/lib/readapt.rb +21 -18
  32. data/lib/readapt/adapter.rb +98 -138
  33. data/lib/readapt/breakpoint.rb +21 -20
  34. data/lib/readapt/data_reader.rb +62 -0
  35. data/lib/readapt/debugger.rb +220 -224
  36. data/lib/readapt/error.rb +63 -0
  37. data/lib/readapt/finder.rb +34 -20
  38. data/lib/readapt/frame.rb +40 -40
  39. data/lib/readapt/input.rb +7 -0
  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 -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 -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 -0
  61. data/lib/readapt/references.rb +27 -0
  62. data/lib/readapt/server.rb +22 -0
  63. data/lib/readapt/shell.rb +104 -41
  64. data/lib/readapt/snapshot.rb +0 -0
  65. data/lib/readapt/thread.rb +25 -28
  66. data/lib/readapt/variable.rb +1 -1
  67. data/lib/readapt/version.rb +3 -3
  68. data/readapt.gemspec +39 -39
  69. metadata +15 -9
  70. data/ext/readapt/hash_table.h +0 -30
data/ext/readapt/stack.h CHANGED
@@ -1,20 +1,20 @@
1
- #ifndef STACK_H_
2
- #define STACK_H_
3
-
4
- #include "stddef.h"
5
-
6
- typedef struct stack_struct {
7
- int size;
8
- size_t elem_size;
9
- void (*free_func)(void *);
10
- int capacity;
11
- void **elements;
12
- } stack_t;
13
-
14
- stack_t *stack_alloc(size_t elem_size, void(*free_func)(void*));
15
- void stack_push(stack_t *stack, void *element);
16
- void *stack_peek(stack_t *stack);
17
- void stack_pop(stack_t *stack);
18
- void stack_free(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,11 +6,11 @@
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;
13
- stack_t *frames;
13
+ readapt_stack_t *frames;
14
14
  } thread_reference_t;
15
15
 
16
16
  void initialize_threads(VALUE);
data/lib/readapt.rb CHANGED
@@ -1,18 +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/adapter'
15
- require 'readapt/shell'
16
-
17
- module Readapt
18
- end
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,138 +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 format result
16
- write_line result.to_protocol.to_json
17
- end
18
-
19
- def opening
20
- @@debugger.add_observer self
21
- @data_reader = DataReader.new
22
- @data_reader.set_message_handler do |message|
23
- process message
24
- end
25
- end
26
-
27
- def closing
28
- @@debugger.delete_observer(self)
29
- end
30
-
31
- def receiving data
32
- @data_reader.receive data
33
- end
34
-
35
- def update event, data
36
- obj = {
37
- type: 'event',
38
- event: event
39
- }
40
- obj[:body] = data unless data.nil?
41
- json = obj.to_json
42
- envelope = "Content-Length: #{json.bytesize}\r\n\r\n#{json}"
43
- write envelope
44
- end
45
-
46
- private
47
-
48
- # @param data [Hash]
49
- # @return [void]
50
- def process data
51
- # @todo Better solution than nil frames
52
- message = Message.process(data, @@debugger)
53
- if data['seq']
54
- json = {
55
- type: 'response',
56
- request_seq: data['seq'],
57
- success: true,
58
- command: data['command'],
59
- body: message.body
60
- }.to_json
61
- envelope = "Content-Length: #{json.bytesize}\r\n\r\n#{json}"
62
- write envelope
63
- close if data['command'] == 'disconnect'
64
- return unless data['command'] == 'initialize'
65
- json = {
66
- type: 'event',
67
- event: 'initialized'
68
- }.to_json
69
- envelope = "Content-Length: #{json.bytesize}\r\n\r\n#{json}"
70
- write envelope
71
- end
72
- rescue RuntimeError => e
73
- STDERR.puts "[#{e.class}] #{e.message}"
74
- STDERR.puts e.backtrace.join
75
- end
76
- end
77
-
78
- class DataReader
79
- def initialize
80
- @in_header = true
81
- @content_length = 0
82
- @buffer = String.new
83
- end
84
-
85
- # Declare a block to be executed for each message received from the
86
- # client.
87
- #
88
- # @yieldparam [Hash] The message received from the client
89
- def set_message_handler &block
90
- @message_handler = block
91
- end
92
-
93
- # Process raw data received from the client. The data will be parsed
94
- # into messages based on the JSON-RPC protocol. Each message will be
95
- # passed to the block declared via set_message_handler. Incomplete data
96
- # will be buffered and subsequent data will be appended to the buffer.
97
- #
98
- # @param data [String]
99
- def receive data
100
- data.each_char do |char|
101
- @buffer.concat char
102
- if @in_header
103
- prepare_to_parse_message if @buffer.end_with?("\r\n\r\n")
104
- else
105
- parse_message_from_buffer if @buffer.bytesize == @content_length
106
- end
107
- end
108
- end
109
-
110
- private
111
-
112
- def prepare_to_parse_message
113
- @in_header = false
114
- @buffer.each_line do |line|
115
- parts = line.split(':').map(&:strip)
116
- if parts[0] == 'Content-Length'
117
- @content_length = parts[1].to_i
118
- break
119
- end
120
- end
121
- @buffer.clear
122
- end
123
-
124
- def parse_message_from_buffer
125
- begin
126
- msg = JSON.parse(@buffer)
127
- @message_handler.call msg unless @message_handler.nil?
128
- rescue JSON::ParserError => e
129
- Solargraph::Logging.logger.warn "Failed to parse request: #{e.message}"
130
- Solargraph::Logging.logger.debug "Buffer: #{@buffer}"
131
- ensure
132
- @buffer.clear
133
- @in_header = true
134
- @content_length = 0
135
- end
136
- end
137
- end
138
- 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,21 @@
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
+ # @return [Integer]
17
+ def hit_cursor
18
+ @hit_cursor ||= 0
19
+ end
20
+ end
21
+ end