racer-rb 0.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.
- checksums.yaml +7 -0
- data/.rubocop.yml +9 -0
- data/.tool-versions +1 -0
- data/CHANGELOG.md +5 -0
- data/CODE_OF_CONDUCT.md +84 -0
- data/LICENSE.txt +21 -0
- data/README.md +93 -0
- data/Rakefile +23 -0
- data/ext/racer/extconf.rb +14 -0
- data/ext/racer/racer.cc +999 -0
- data/ext/racer/racer.hh +37 -0
- data/ext/racer/tiny_queue.cc +103 -0
- data/ext/racer/tiny_queue.hh +39 -0
- data/ext/racer/traces.cc +70 -0
- data/ext/racer/traces.hh +95 -0
- data/ext/racer/worker.cc +188 -0
- data/ext/racer/worker.hh +15 -0
- data/lib/racer/agent.rb +250 -0
- data/lib/racer/collectors/rbs_collector.rb +645 -0
- data/lib/racer/minitest.rb +20 -0
- data/lib/racer/minitest_plugin.rb +35 -0
- data/lib/racer/rails/railtie.rb +38 -0
- data/lib/racer/rb.rb +2 -0
- data/lib/racer/rspec.rb +19 -0
- data/lib/racer/rspec_plugin.rb +28 -0
- data/lib/racer/trace.rb +121 -0
- data/lib/racer/version.rb +5 -0
- data/lib/racer.rb +40 -0
- data/sig/racer.rbs +4 -0
- metadata +87 -0
data/lib/racer/agent.rb
ADDED
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
require "json"
|
|
2
|
+
|
|
3
|
+
class Racer::Agent
|
|
4
|
+
def initialize(server_path, collectors)
|
|
5
|
+
@queue = Queue.new
|
|
6
|
+
@server_path = server_path
|
|
7
|
+
@server = nil
|
|
8
|
+
@collectors = collectors
|
|
9
|
+
@should_stop = false
|
|
10
|
+
@agent_threads = []
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def start
|
|
14
|
+
unless @server.nil?
|
|
15
|
+
raise "tried to start server again"
|
|
16
|
+
end
|
|
17
|
+
Process.setproctitle("Racer: Agent")
|
|
18
|
+
|
|
19
|
+
@server = UNIXServer.new(@server_path)
|
|
20
|
+
|
|
21
|
+
worker_thread =
|
|
22
|
+
Thread.new do
|
|
23
|
+
while (trace = @queue.pop) do
|
|
24
|
+
@collectors.each do |collector|
|
|
25
|
+
collector.collect(trace)
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
@collectors.each do |collector|
|
|
30
|
+
collector.stop
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
trap "HUP" do
|
|
35
|
+
exit
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
at_exit do
|
|
39
|
+
# puts "Shutting down agent. Waiting for all clients to finish sending messages..."
|
|
40
|
+
@agent_threads.each(&:join)
|
|
41
|
+
# puts "Closed server. Waiting for collectors to process messages..."
|
|
42
|
+
@server.close
|
|
43
|
+
@queue.close if @queue.empty?
|
|
44
|
+
File.unlink(@server_path)
|
|
45
|
+
worker_thread.join
|
|
46
|
+
# puts "Done"
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
main_loop
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
private
|
|
53
|
+
|
|
54
|
+
def main_loop
|
|
55
|
+
loop do
|
|
56
|
+
connection = @server.accept
|
|
57
|
+
# this is not really good because new clients need to wait until first client finished but for now its okay
|
|
58
|
+
@agent_threads <<
|
|
59
|
+
Thread.new do
|
|
60
|
+
worker_loop(connection)
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def worker_loop(connection)
|
|
66
|
+
pending_message = nil
|
|
67
|
+
loop do
|
|
68
|
+
# TODO: Difference between connection.read connection.recv and connection.recvmsg
|
|
69
|
+
received_message = connection.read(1024)
|
|
70
|
+
# TODO: Is this an error? I would expect it waits until there is something to read?
|
|
71
|
+
if received_message.nil?
|
|
72
|
+
# warn "received nil as message"
|
|
73
|
+
next
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# File.write("messages", "#{received_message}\n\n", mode: "a+")
|
|
77
|
+
|
|
78
|
+
*messages, last_message = received_message.split("\0")
|
|
79
|
+
|
|
80
|
+
if pending_message
|
|
81
|
+
if messages.empty?
|
|
82
|
+
last_message = "#{pending_message}#{last_message}"
|
|
83
|
+
else
|
|
84
|
+
first_message = messages.shift
|
|
85
|
+
messages.prepend(*("#{pending_message}#{first_message}".split("\0")))
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
pending_message = nil
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
if received_message.end_with?("\0")
|
|
92
|
+
messages << last_message
|
|
93
|
+
else
|
|
94
|
+
pending_message = last_message
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
messages.each do |data|
|
|
98
|
+
if data == "stop"
|
|
99
|
+
# puts "Received last message from one worker"
|
|
100
|
+
# Exits the thread
|
|
101
|
+
return
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
data = JSON.parse(data)
|
|
105
|
+
# File.write("parsed_messages", "#{data}\n\n", mode: "a+")
|
|
106
|
+
|
|
107
|
+
method_name = data.shift
|
|
108
|
+
method_kind =
|
|
109
|
+
Racer::Trace::KINDS.fetch(data.shift) do |index|
|
|
110
|
+
warn "Unexpected method kind received #{index}"
|
|
111
|
+
Racer::Trace::KINDS.first
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
method_visibility =
|
|
115
|
+
Racer::Trace::VISIBILITIES.fetch(data.shift) do |index|
|
|
116
|
+
warn "Unexpected method visibility received #{index}"
|
|
117
|
+
Racer::Trace::VISIBILITIES.first
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
return_type = shift_constant_instance(data)
|
|
121
|
+
method_owner = shift_constant_instance(data)
|
|
122
|
+
method_callee =
|
|
123
|
+
if data.first
|
|
124
|
+
shift_constant_instance(data)
|
|
125
|
+
else
|
|
126
|
+
# pop nil from data
|
|
127
|
+
data.shift
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
constant_updates = shift_constant_updates(data)
|
|
131
|
+
|
|
132
|
+
params, block_param = shift_params(data)
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
unless data.empty?
|
|
136
|
+
warn "Received more data then expected: #{data}"
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
@queue.push(
|
|
140
|
+
Racer::Trace.new(
|
|
141
|
+
method_owner:,
|
|
142
|
+
method_callee:,
|
|
143
|
+
method_name:,
|
|
144
|
+
method_kind:,
|
|
145
|
+
method_visibility:,
|
|
146
|
+
return_type:,
|
|
147
|
+
params:,
|
|
148
|
+
block_param:,
|
|
149
|
+
constant_updates:
|
|
150
|
+
)
|
|
151
|
+
)
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
def shift_block_trace(data)
|
|
157
|
+
self_type = shift_constant_instance(data)
|
|
158
|
+
return_type = shift_constant_instance(data)
|
|
159
|
+
params, block_param = shift_params(data)
|
|
160
|
+
|
|
161
|
+
Racer::Trace::BlockTrace.new(self_type:, return_type:, params:, block_param:)
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
def shift_params(data)
|
|
165
|
+
params_size = data.shift
|
|
166
|
+
params = params_size.times.map { shift_param(data) }
|
|
167
|
+
|
|
168
|
+
block_present = data.shift
|
|
169
|
+
block_param =
|
|
170
|
+
if block_present
|
|
171
|
+
block_name = data.shift
|
|
172
|
+
traces_count = data.shift
|
|
173
|
+
traces = traces_count.times.map { shift_block_trace(data) }
|
|
174
|
+
|
|
175
|
+
Racer::Trace::BlockParam.new(
|
|
176
|
+
name: block_name,
|
|
177
|
+
traces:
|
|
178
|
+
)
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
[params, block_param]
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
def shift_param(data)
|
|
185
|
+
name = data.shift
|
|
186
|
+
type = Racer::Trace::Param::TYPES.fetch(data.shift) do |key|
|
|
187
|
+
warn "Unexpected return type received #{key}"
|
|
188
|
+
Racer::Trace::Param::TYPES.first
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
type_name = shift_constant_instance(data)
|
|
192
|
+
|
|
193
|
+
Racer::Trace::Param.new(name: name&.to_sym, type_name:, type:)
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
def shift_constant_updates(data)
|
|
197
|
+
constant_update_count = data.shift
|
|
198
|
+
constant_update_count.times.map do
|
|
199
|
+
shift_constant(data)
|
|
200
|
+
end
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
def shift_constant(data)
|
|
204
|
+
name = data.shift
|
|
205
|
+
anonymous = data.shift
|
|
206
|
+
type = data.shift
|
|
207
|
+
|
|
208
|
+
superclass = data.shift
|
|
209
|
+
|
|
210
|
+
included_modules_count = data.shift
|
|
211
|
+
included_modules = included_modules_count.times.map { data.shift }
|
|
212
|
+
|
|
213
|
+
prepended_modules_count = data.shift
|
|
214
|
+
prepended_modules = prepended_modules_count.times.map { data.shift }
|
|
215
|
+
|
|
216
|
+
extended_modules_count = data.shift
|
|
217
|
+
extended_modules = extended_modules_count.times.map { data.shift }
|
|
218
|
+
|
|
219
|
+
Racer::Trace::Constant.new(
|
|
220
|
+
name:,
|
|
221
|
+
anonymous:,
|
|
222
|
+
type: Racer::Trace::Constant::TYPES.fetch(type),
|
|
223
|
+
superclass:,
|
|
224
|
+
included_modules:,
|
|
225
|
+
prepended_modules:,
|
|
226
|
+
extended_modules:
|
|
227
|
+
)
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
def shift_constant_instance(data)
|
|
231
|
+
name = data.shift
|
|
232
|
+
singleton = data.shift
|
|
233
|
+
generic_argument_count = data.shift
|
|
234
|
+
|
|
235
|
+
generic_arguments =
|
|
236
|
+
generic_argument_count.times.map do
|
|
237
|
+
union_size = data.shift
|
|
238
|
+
|
|
239
|
+
union_size.times.map do
|
|
240
|
+
shift_constant_instance(data)
|
|
241
|
+
end
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
Racer::Trace::ConstantInstance.new(
|
|
245
|
+
name:,
|
|
246
|
+
singleton:,
|
|
247
|
+
generic_arguments:
|
|
248
|
+
)
|
|
249
|
+
end
|
|
250
|
+
end
|