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.
- checksums.yaml +4 -4
- data/.gitignore +16 -14
- data/.rspec +2 -2
- data/.travis.yml +18 -13
- data/CHANGELOG.md +76 -53
- data/Gemfile +4 -4
- data/LICENSE.txt +21 -21
- data/README.md +37 -29
- data/Rakefile +14 -25
- data/bin/console +14 -14
- data/bin/setup +8 -8
- data/exe/readapt +5 -5
- data/ext/readapt/breakpoints.c +83 -88
- data/ext/readapt/breakpoints.h +11 -12
- data/ext/readapt/extconf.rb +0 -0
- data/ext/readapt/frame.c +137 -0
- data/ext/readapt/frame.h +17 -0
- data/ext/readapt/hash_table.c +211 -212
- data/ext/readapt/hash_table.h +30 -32
- data/ext/readapt/inspector.c +51 -0
- data/ext/readapt/inspector.h +8 -0
- data/ext/readapt/monitor.c +40 -27
- data/ext/readapt/monitor.h +0 -0
- data/ext/readapt/normalize.c +59 -53
- data/ext/readapt/normalize.h +7 -7
- data/ext/readapt/readapt.c +18 -16
- data/ext/readapt/stack.c +86 -0
- data/ext/readapt/stack.h +20 -0
- data/ext/readapt/threads.c +111 -17
- data/ext/readapt/threads.h +11 -4
- data/lib/readapt.rb +21 -19
- data/lib/readapt/adapter.rb +98 -138
- data/lib/readapt/breakpoint.rb +20 -13
- data/lib/readapt/data_reader.rb +62 -0
- data/lib/readapt/debugger.rb +220 -204
- data/lib/readapt/error.rb +63 -0
- data/lib/readapt/finder.rb +20 -20
- data/lib/readapt/frame.rb +40 -42
- data/lib/readapt/input.rb +7 -0
- data/lib/readapt/message.rb +62 -59
- data/lib/readapt/message/attach.rb +11 -11
- data/lib/readapt/message/base.rb +32 -32
- data/lib/readapt/message/configuration_done.rb +11 -11
- data/lib/readapt/message/continue.rb +15 -15
- data/lib/readapt/message/disconnect.rb +13 -14
- data/lib/readapt/message/evaluate.rb +18 -18
- data/lib/readapt/message/initialize.rb +13 -13
- data/lib/readapt/message/launch.rb +11 -11
- data/lib/readapt/message/next.rb +12 -12
- data/lib/readapt/message/pause.rb +11 -11
- data/lib/readapt/message/scopes.rb +26 -25
- data/lib/readapt/message/set_breakpoints.rb +25 -25
- data/lib/readapt/message/set_exception_breakpoints.rb +8 -8
- data/lib/readapt/message/stack_trace.rb +38 -26
- data/lib/readapt/message/step_in.rb +11 -11
- data/lib/readapt/message/step_out.rb +11 -11
- data/lib/readapt/message/threads.rb +18 -18
- data/lib/readapt/message/variables.rb +61 -57
- data/lib/readapt/monitor.rb +0 -0
- data/lib/readapt/output.rb +25 -0
- data/lib/readapt/references.rb +27 -0
- data/lib/readapt/server.rb +22 -0
- data/lib/readapt/shell.rb +104 -39
- data/lib/readapt/snapshot.rb +1 -13
- data/lib/readapt/thread.rb +23 -39
- data/lib/readapt/variable.rb +1 -1
- data/lib/readapt/version.rb +3 -3
- data/readapt.gemspec +39 -39
- metadata +19 -8
- data/lib/readapt/location.rb +0 -25
data/ext/readapt/stack.h
ADDED
@@ -0,0 +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
|
data/ext/readapt/threads.c
CHANGED
@@ -1,15 +1,24 @@
|
|
1
1
|
#include "ruby.h"
|
2
2
|
#include "ruby/debug.h"
|
3
3
|
#include "threads.h"
|
4
|
+
#include "frame.h"
|
5
|
+
#include "inspector.h"
|
4
6
|
|
7
|
+
static VALUE c_Thread;
|
5
8
|
static VALUE threads;
|
9
|
+
static VALUE ids;
|
10
|
+
static int next_id;
|
6
11
|
|
7
|
-
void thread_reference_free(void* data)
|
12
|
+
static void thread_reference_free(void* data)
|
8
13
|
{
|
9
|
-
|
14
|
+
thread_reference_t* thr;
|
15
|
+
|
16
|
+
thr = data;
|
17
|
+
stack_free(thr->frames);
|
18
|
+
free(thr);
|
10
19
|
}
|
11
20
|
|
12
|
-
size_t thread_reference_size(const void* data)
|
21
|
+
static size_t thread_reference_size(const void* data)
|
13
22
|
{
|
14
23
|
return sizeof(thread_reference_t);
|
15
24
|
}
|
@@ -25,20 +34,16 @@ static const rb_data_type_t thread_reference_type = {
|
|
25
34
|
.flags = RUBY_TYPED_FREE_IMMEDIATELY,
|
26
35
|
};
|
27
36
|
|
28
|
-
|
29
|
-
{
|
30
|
-
threads = rb_hash_new();
|
31
|
-
rb_global_variable(&threads);
|
32
|
-
}
|
33
|
-
|
34
|
-
VALUE thread_reference_new(VALUE thr)
|
37
|
+
static VALUE thread_reference_new(VALUE thr)
|
35
38
|
{
|
36
39
|
thread_reference_t *data = malloc(sizeof(thread_reference_t));
|
37
|
-
VALUE obj = TypedData_Make_Struct(
|
38
|
-
data->id =
|
39
|
-
data->depth = 0;
|
40
|
+
VALUE obj = TypedData_Make_Struct(c_Thread, thread_reference_t, &thread_reference_type, data);
|
41
|
+
data->id = next_id;
|
40
42
|
data->cursor = 0;
|
43
|
+
data->depth = 0;
|
41
44
|
data->control = rb_intern("continue");
|
45
|
+
data->frames = stack_alloc(sizeof(frame_t), frame_free);
|
46
|
+
next_id++;
|
42
47
|
return obj;
|
43
48
|
}
|
44
49
|
|
@@ -61,22 +66,25 @@ VALUE thread_reference(VALUE thr)
|
|
61
66
|
|
62
67
|
VALUE thread_reference_id(VALUE id)
|
63
68
|
{
|
64
|
-
return rb_hash_aref(
|
69
|
+
return rb_hash_aref(ids, id);
|
65
70
|
}
|
66
71
|
|
67
72
|
VALUE thread_add_reference(VALUE thr)
|
68
73
|
{
|
69
74
|
VALUE ref;
|
75
|
+
thread_reference_t *ptr;
|
70
76
|
|
71
77
|
ref = thread_reference_new(thr);
|
78
|
+
ptr = thread_reference_pointer(ref);
|
72
79
|
rb_hash_aset(threads, rb_obj_id(thr), ref);
|
80
|
+
rb_hash_aset(ids, INT2NUM(ptr->id), ref);
|
73
81
|
return ref;
|
74
82
|
}
|
75
83
|
|
76
84
|
VALUE thread_delete_reference(VALUE thr)
|
77
85
|
{
|
78
|
-
|
79
|
-
return
|
86
|
+
// TODO: Do we need to delete from ids here?
|
87
|
+
return rb_hash_delete(threads, rb_obj_id(thr));
|
80
88
|
}
|
81
89
|
|
82
90
|
void thread_pause()
|
@@ -95,7 +103,93 @@ void thread_pause()
|
|
95
103
|
}
|
96
104
|
}
|
97
105
|
|
98
|
-
void
|
106
|
+
void thread_clear()
|
99
107
|
{
|
100
108
|
rb_funcall(threads, rb_intern("clear"), 0);
|
109
|
+
rb_funcall(ids, rb_intern("clear"), 0);
|
110
|
+
}
|
111
|
+
|
112
|
+
static VALUE thread_allocate_s(VALUE self)
|
113
|
+
{
|
114
|
+
thread_reference_t *data = malloc(sizeof(thread_reference_t));
|
115
|
+
data->control = rb_intern("continue");
|
116
|
+
data->depth = 0;
|
117
|
+
data->cursor = 0;
|
118
|
+
data->frames = stack_alloc(sizeof(frame_t), frame_free);
|
119
|
+
data->id = 0;
|
120
|
+
return TypedData_Wrap_Struct(self, &thread_reference_type, data);
|
121
|
+
}
|
122
|
+
|
123
|
+
static VALUE thread_all_s(VALUE self)
|
124
|
+
{
|
125
|
+
return rb_funcall(threads, rb_intern("values"), 0);
|
126
|
+
}
|
127
|
+
|
128
|
+
static VALUE thread_find_s(VALUE self, VALUE id)
|
129
|
+
{
|
130
|
+
return thread_reference_id(id);
|
131
|
+
}
|
132
|
+
|
133
|
+
static VALUE thread_include_s(VALUE self, VALUE id)
|
134
|
+
{
|
135
|
+
return rb_funcall(ids, rb_intern("include?"), 1, id);
|
136
|
+
}
|
137
|
+
|
138
|
+
static VALUE thread_id_m(VALUE self)
|
139
|
+
{
|
140
|
+
thread_reference_t *data = thread_reference_pointer(self);
|
141
|
+
return LONG2NUM(data->id);
|
142
|
+
}
|
143
|
+
|
144
|
+
static VALUE frames_m(VALUE self)
|
145
|
+
{
|
146
|
+
thread_reference_t *data;
|
147
|
+
VALUE ary;
|
148
|
+
VALUE frm;
|
149
|
+
int i;
|
150
|
+
frame_t *fd;
|
151
|
+
|
152
|
+
ary = rb_ary_new();
|
153
|
+
data = thread_reference_pointer(self);
|
154
|
+
for (i = data->frames->size - 1; i >= 0; i--)
|
155
|
+
{
|
156
|
+
fd = data->frames->elements[i];
|
157
|
+
// TODO This condition should probably not be necessary.
|
158
|
+
if (fd->binding != Qnil)
|
159
|
+
{
|
160
|
+
frm = frame_new_from_data(fd);
|
161
|
+
rb_ary_push(ary, frm);
|
162
|
+
}
|
163
|
+
}
|
164
|
+
|
165
|
+
return ary;
|
166
|
+
}
|
167
|
+
|
168
|
+
void thread_reference_build_frames(thread_reference_t *ptr)
|
169
|
+
{
|
170
|
+
inspector_inspect(ptr);
|
171
|
+
}
|
172
|
+
|
173
|
+
void thread_reference_clear_frames(thread_reference_t *ptr)
|
174
|
+
{
|
175
|
+
stack_free(ptr->frames);
|
176
|
+
ptr->frames = stack_alloc(sizeof(frame_t), frame_free);
|
177
|
+
}
|
178
|
+
|
179
|
+
void initialize_threads(VALUE m_Readapt)
|
180
|
+
{
|
181
|
+
next_id = 1;
|
182
|
+
|
183
|
+
c_Thread = rb_define_class_under(m_Readapt, "Thread", rb_cData);
|
184
|
+
rb_define_alloc_func(c_Thread, thread_allocate_s);
|
185
|
+
rb_define_method(c_Thread, "id", thread_id_m, 0);
|
186
|
+
rb_define_method(c_Thread, "frames", frames_m, 0);
|
187
|
+
rb_define_singleton_method(c_Thread, "all", thread_all_s, 0);
|
188
|
+
rb_define_singleton_method(c_Thread, "find", thread_find_s, 1);
|
189
|
+
rb_define_singleton_method(c_Thread, "include?", thread_include_s, 1);
|
190
|
+
|
191
|
+
threads = rb_hash_new();
|
192
|
+
rb_global_variable(&threads);
|
193
|
+
ids = rb_hash_new();
|
194
|
+
rb_global_variable(&ids);
|
101
195
|
}
|
data/ext/readapt/threads.h
CHANGED
@@ -1,21 +1,28 @@
|
|
1
1
|
#ifndef THREADS_H_
|
2
2
|
#define THREADS_H_
|
3
3
|
|
4
|
+
#include "ruby.h"
|
5
|
+
#include "frame.h"
|
6
|
+
#include "stack.h"
|
7
|
+
|
4
8
|
typedef struct thread_reference_struct {
|
5
|
-
|
6
|
-
int depth;
|
9
|
+
int id;
|
7
10
|
int cursor;
|
11
|
+
int depth;
|
8
12
|
ID control;
|
13
|
+
readapt_stack_t *frames;
|
9
14
|
} thread_reference_t;
|
10
15
|
|
11
|
-
void initialize_threads();
|
16
|
+
void initialize_threads(VALUE);
|
12
17
|
VALUE thread_current_reference();
|
13
18
|
VALUE thread_reference(VALUE);
|
14
19
|
VALUE thread_reference_id(VALUE);
|
15
20
|
VALUE thread_add_reference(VALUE);
|
16
21
|
VALUE thread_delete_reference(VALUE);
|
17
22
|
thread_reference_t *thread_reference_pointer(VALUE);
|
23
|
+
void thread_reference_build_frames(thread_reference_t *);
|
24
|
+
void thread_reference_clear_frames(thread_reference_t *);
|
18
25
|
void thread_pause();
|
19
|
-
void
|
26
|
+
void thread_clear();
|
20
27
|
|
21
28
|
#endif
|
data/lib/readapt.rb
CHANGED
@@ -1,19 +1,21 @@
|
|
1
|
-
require 'backport'
|
2
|
-
|
3
|
-
require 'readapt/version'
|
4
|
-
require 'readapt/
|
5
|
-
require 'readapt/
|
6
|
-
require 'readapt/
|
7
|
-
require 'readapt/
|
8
|
-
require 'readapt/
|
9
|
-
require 'readapt/
|
10
|
-
require 'readapt/
|
11
|
-
require 'readapt/
|
12
|
-
require 'readapt/
|
13
|
-
require 'readapt/
|
14
|
-
require 'readapt/
|
15
|
-
require 'readapt/
|
16
|
-
require 'readapt/
|
17
|
-
|
18
|
-
|
19
|
-
|
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'
|
data/lib/readapt/adapter.rb
CHANGED
@@ -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
|
16
|
-
|
17
|
-
end
|
18
|
-
|
19
|
-
def
|
20
|
-
@@
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
end
|
26
|
-
|
27
|
-
def
|
28
|
-
@@
|
29
|
-
end
|
30
|
-
|
31
|
-
def
|
32
|
-
|
33
|
-
end
|
34
|
-
|
35
|
-
def
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
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
|