Skip to content

Commit c37a0e5

Browse files
committed
Add ReplTypeCompletor.reload_rbs to load rbs in newly required gem
1 parent 4e27333 commit c37a0e5

File tree

2 files changed

+89
-14
lines changed

2 files changed

+89
-14
lines changed

lib/repl_type_completor.rb

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,17 @@ def rbs_loaded?
2121
end
2222

2323
def load_rbs
24-
Types.load_rbs_builder unless rbs_loaded?
24+
Types.load_rbs_builder
2525
end
2626

2727
def preload_rbs
2828
Types.preload_rbs_builder
2929
end
3030

31+
def reload_rbs
32+
Types.reload_rbs_builder
33+
end
34+
3135
def analyze(code, binding:, filename: nil)
3236
verbose, $VERBOSE = $VERBOSE, nil
3337
result = analyze_code(code, binding)

lib/repl_type_completor/types.rb

Lines changed: 84 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,28 +8,99 @@ module Types
88

99
singleton_class.attr_reader :rbs_builder, :rbs_load_error
1010

11+
class Loader
12+
attr_reader :load_started, :rbs_load_error
13+
14+
def initialize(thread: false, &block)
15+
@load_callback = block
16+
@gems = {}
17+
@loaded_features = []
18+
if thread
19+
@queue = Thread::Queue.new
20+
Thread.new { run }
21+
else
22+
run
23+
end
24+
end
25+
26+
def added_gems
27+
features = $LOADED_FEATURES.dup
28+
loaded_gems = (features - (@loaded_features || [])).filter_map do |lf|
29+
next unless %r{(?<gem_path>.*/gems/(?<gem_name>[a-zA-Z0-9_-]+)-(?<version>\d+\.\d[\d\.a-zA-Z_]+)/)} =~ lf
30+
next if @gems[gem_name]
31+
32+
[gem_name, [gem_path, version]]
33+
end.to_h
34+
@gems.merge!(loaded_gems)
35+
@loaded_featues = features
36+
loaded_gems
37+
end
38+
39+
def reload
40+
@queue&.enq(:reload)
41+
end
42+
43+
def terminate
44+
@queue&.enq(:terminate)
45+
end
46+
47+
def update_loader(loader)
48+
new_gems = added_gems
49+
new_gems.each do |library, (path, version)|
50+
loader.add(library: library, version: version) if Dir.exist?("#{path}sig")
51+
end
52+
new_gems.any?
53+
end
54+
55+
def load(loader)
56+
@load_callback.call(RBS::DefinitionBuilder.new env: RBS::Environment.from_loader(loader).resolve_type_names)
57+
end
58+
59+
def run
60+
require 'rbs'
61+
require 'rbs/cli'
62+
loader = RBS::CLI::LibraryOptions.new.loader
63+
loader.add path: Pathname('sig')
64+
update_loader(loader)
65+
load(loader)
66+
return unless @queue
67+
68+
loop do
69+
break if @queue.deq == :terminate
70+
next unless update_loader(loader)
71+
72+
load(loader)
73+
end
74+
rescue LoadError, StandardError => e
75+
@rbs_load_error = e
76+
nil
77+
end
78+
end
79+
1180
def self.rbs_load_started?
12-
!!@load_started
81+
!!@loader
1382
end
1483

1584
def self.preload_rbs_builder
1685
return if rbs_load_started?
17-
@load_started = true
18-
Thread.new do
19-
load_rbs_builder
86+
87+
@loader ||= Loader.new(thread: true) do |builder|
88+
@rbs_builder = builder
2089
end
2190
end
2291

92+
def self.rbs_load_error
93+
@loader&.rbs_load_error
94+
end
95+
2396
def self.load_rbs_builder
24-
@load_started = true
25-
require 'rbs'
26-
require 'rbs/cli'
27-
loader = RBS::CLI::LibraryOptions.new.loader
28-
loader.add path: Pathname('sig')
29-
@rbs_builder = RBS::DefinitionBuilder.new env: RBS::Environment.from_loader(loader).resolve_type_names
30-
rescue LoadError, StandardError => e
31-
@rbs_load_error = e
32-
nil
97+
@loader ||= Loader.new do |builder|
98+
@rbs_builder = builder
99+
end
100+
end
101+
102+
def self.reload_rbs_builder
103+
@loader.reload
33104
end
34105

35106
def self.class_name_of(klass)

0 commit comments

Comments
 (0)