@@ -3,6 +3,20 @@ require "./cursor_visitor"
33require " ./submodule_visitor"
44
55module Crystalline::Analysis
6+ {% if flag?(:preview_mt ) % }
7+ @@dedicated_thread : Thread = Thread .new(name: " crystalline-dedicated-thread" ) do
8+ scheduler = Thread .current.scheduler
9+ scheduler.run_loop
10+ end
11+ {% end % }
12+
13+ private def self.spawn_dedicated (* , name : String ? = nil , & block )
14+ fiber = Fiber .new(name, & block)
15+ {% if flag?(:preview_mt ) % } fiber.set_current_thread(@@dedicated_thread ) {% end % }
16+ fiber.enqueue
17+ fiber
18+ end
19+
620 # Compile a target *file_uri*.
721 def self.compile (server : LSP ::Server , file_uri : URI , * , lib_path : String ? = nil , file_overrides : Hash (String , String )? = nil , ignore_diagnostics = false , wants_doc = false , fail_fast = false , top_level = false )
822 if file_uri.scheme == " file"
@@ -24,45 +38,40 @@ module Crystalline::Analysis
2438 # LSP::Log.info { "lib_path: #{lib_path}" }
2539
2640 # Delegate heavy processing to a separate thread.
27- Thread .new do
28- wait_before_termination = Channel (Nil ).new
29- spawn same_thread: true do
30- dev_null = File .open(File ::NULL , " w" )
31- compiler = Crystal ::Compiler .new
32- compiler.no_codegen = true
33- compiler.color = false
34- compiler.no_cleanup = true
35- compiler.file_overrides = file_overrides
36- compiler.wants_doc = wants_doc
37- compiler.stdout = dev_null
38- compiler.stderr = dev_null
39-
40- if lib_path_override = lib_path
41- path = Crystal ::CrystalPath .default_path_without_lib.split(Process ::PATH_DELIMITER )
42- path.insert(0 , lib_path_override)
43- compiler.crystal_path = Crystal ::CrystalPath .new(path)
44- end
41+ spawn_dedicated do
42+ dev_null = File .open(File ::NULL , " w" )
43+ compiler = Crystal ::Compiler .new
44+ compiler.no_codegen = true
45+ compiler.color = false
46+ compiler.no_cleanup = true
47+ compiler.file_overrides = file_overrides
48+ compiler.wants_doc = wants_doc
49+ compiler.stdout = dev_null
50+ compiler.stderr = dev_null
51+
52+ if lib_path_override = lib_path
53+ path = Crystal ::CrystalPath .default_path_without_lib.split(Process ::PATH_DELIMITER )
54+ path.insert(0 , lib_path_override)
55+ compiler.crystal_path = Crystal ::CrystalPath .new(path)
56+ end
4557
46- reply = begin
47- if top_level
48- # Top level only.
49- compiler.top_level_semantic(sources)
50- elsif fail_fast
51- # Regular parser + semantic analysis phases.
52- compiler.compile(sources, " " )
53- else
54- # Fail-slow means that errors are collected instead of throwing during the semantic phase, and we still get a partially typed AST back.
55- compiler.fail_slow_compile(sources, " " )
56- end
58+ reply = begin
59+ if top_level
60+ # Top level only.
61+ compiler.top_level_semantic(sources)
62+ elsif fail_fast
63+ # Regular parser + semantic analysis phases.
64+ compiler.compile(sources, " " )
65+ else
66+ # Fail-slow means that errors are collected instead of throwing during the semantic phase, and we still get a partially typed AST back.
67+ compiler.fail_slow_compile(sources, " " )
5768 end
58- reply_channel.send(reply)
59- rescue e : Exception
60- reply_channel.send(e)
61- ensure
62- dev_null.try & .close
63- wait_before_termination.send nil
6469 end
65- wait_before_termination.receive
70+ reply_channel.send(reply)
71+ rescue e : Exception
72+ reply_channel.send(e)
73+ ensure
74+ dev_null.try & .close
6675 end
6776 result = reply_channel.receive
6877
0 commit comments