@@ -10,20 +10,34 @@ class RunnerClient
1010 class << self
1111 extend T ::Sig
1212
13- sig { returns ( RunnerClient ) }
14- def create_client
13+ sig { params ( outgoing_queue : Thread :: Queue ) . returns ( RunnerClient ) }
14+ def create_client ( outgoing_queue )
1515 if File . exist? ( "bin/rails" )
16- new
16+ new ( outgoing_queue )
1717 else
18- $stderr. puts ( <<~MSG )
19- Ruby LSP Rails failed to locate bin/rails in the current directory: #{ Dir . pwd } "
20- MSG
21- $stderr. puts ( "Server dependent features will not be available" )
18+ unless outgoing_queue . closed?
19+ outgoing_queue << RubyLsp ::Notification . window_log_message (
20+ <<~MESSAGE . chomp ,
21+ Ruby LSP Rails failed to locate bin/rails in the current directory: #{ Dir . pwd }
22+ Server dependent features will not be available
23+ MESSAGE
24+ type : RubyLsp ::Constant ::MessageType ::WARNING ,
25+ )
26+ end
27+
2228 NullClient . new
2329 end
2430 rescue Errno ::ENOENT , StandardError => e # rubocop:disable Lint/ShadowedException
25- $stderr. puts ( "Ruby LSP Rails failed to initialize server: #{ e . message } \n #{ e . backtrace &.join ( "\n " ) } " )
26- $stderr. puts ( "Server dependent features will not be available" )
31+ unless outgoing_queue . closed?
32+ outgoing_queue << RubyLsp ::Notification . window_log_message (
33+ <<~MESSAGE . chomp ,
34+ Ruby LSP Rails failed to initialize server: #{ e . full_message }
35+ Server dependent features will not be available
36+ MESSAGE
37+ type : Constant ::MessageType ::ERROR ,
38+ )
39+ end
40+
2741 NullClient . new
2842 end
2943 end
@@ -39,8 +53,9 @@ class EmptyMessageError < StandardError; end
3953 sig { returns ( String ) }
4054 attr_reader :rails_root
4155
42- sig { void }
43- def initialize
56+ sig { params ( outgoing_queue : Thread ::Queue ) . void }
57+ def initialize ( outgoing_queue )
58+ @outgoing_queue = T . let ( outgoing_queue , Thread ::Queue )
4459 @mutex = T . let ( Mutex . new , Mutex )
4560 # Spring needs a Process session ID. It uses this ID to "attach" itself to the parent process, so that when the
4661 # parent ends, the spring process ends as well. If this is not set, Spring will throw an error while trying to
@@ -69,24 +84,23 @@ def initialize
6984 @stdout . binmode
7085 @stderr . binmode
7186
72- $stderr . puts ( "Ruby LSP Rails booting server" )
87+ log_message ( "Ruby LSP Rails booting server" )
7388 count = 0
7489
7590 begin
7691 count += 1
7792 initialize_response = T . must ( read_response )
7893 @rails_root = T . let ( initialize_response [ :root ] , String )
7994 rescue EmptyMessageError
80- $stderr . puts ( "Ruby LSP Rails is retrying initialize (#{ count } )" )
95+ log_message ( "Ruby LSP Rails is retrying initialize (#{ count } )" )
8196 retry if count < MAX_RETRIES
8297 end
8398
84- $stderr . puts ( "Finished booting Ruby LSP Rails server" )
99+ log_message ( "Finished booting Ruby LSP Rails server" )
85100
86101 unless ENV [ "RAILS_ENV" ] == "test"
87102 at_exit do
88103 if @wait_thread . alive?
89- $stderr. puts ( "Ruby LSP Rails is force killing the server" )
90104 sleep ( 0.5 ) # give the server a bit of time if we already issued a shutdown notification
91105 force_kill
92106 end
@@ -100,15 +114,21 @@ def initialize
100114 def register_server_addon ( server_addon_path )
101115 send_notification ( "server_addon/register" , server_addon_path : server_addon_path )
102116 rescue IncompleteMessageError
103- $stderr. puts ( "Ruby LSP Rails failed to register server addon #{ server_addon_path } " )
117+ log_message (
118+ "Ruby LSP Rails failed to register server addon #{ server_addon_path } " ,
119+ type : RubyLsp ::Constant ::MessageType ::ERROR ,
120+ )
104121 nil
105122 end
106123
107124 sig { params ( name : String ) . returns ( T . nilable ( T ::Hash [ Symbol , T . untyped ] ) ) }
108125 def model ( name )
109126 make_request ( "model" , name : name )
110127 rescue IncompleteMessageError
111- $stderr. puts ( "Ruby LSP Rails failed to get model information: #{ @stderr . read } " )
128+ log_message (
129+ "Ruby LSP Rails failed to get model information: #{ @stderr . read } " ,
130+ type : RubyLsp ::Constant ::MessageType ::ERROR ,
131+ )
112132 nil
113133 end
114134
@@ -125,37 +145,50 @@ def association_target_location(model_name:, association_name:)
125145 association_name : association_name ,
126146 )
127147 rescue => e
128- $stderr. puts ( "Ruby LSP Rails failed with #{ e . message } : #{ @stderr . read } " )
148+ log_message (
149+ "Ruby LSP Rails failed with #{ e . message } : #{ @stderr . read } " ,
150+ type : RubyLsp ::Constant ::MessageType ::ERROR ,
151+ )
152+ nil
129153 end
130154
131155 sig { params ( name : String ) . returns ( T . nilable ( T ::Hash [ Symbol , T . untyped ] ) ) }
132156 def route_location ( name )
133157 make_request ( "route_location" , name : name )
134158 rescue IncompleteMessageError
135- $stderr. puts ( "Ruby LSP Rails failed to get route location: #{ @stderr . read } " )
159+ log_message (
160+ "Ruby LSP Rails failed to get route location: #{ @stderr . read } " ,
161+ type : RubyLsp ::Constant ::MessageType ::ERROR ,
162+ )
136163 nil
137164 end
138165
139166 sig { params ( controller : String , action : String ) . returns ( T . nilable ( T ::Hash [ Symbol , T . untyped ] ) ) }
140167 def route ( controller :, action :)
141168 make_request ( "route_info" , controller : controller , action : action )
142169 rescue IncompleteMessageError
143- $stderr. puts ( "Ruby LSP Rails failed to get route information: #{ @stderr . read } " )
170+ log_message (
171+ "Ruby LSP Rails failed to get route information: #{ @stderr . read } " ,
172+ type : RubyLsp ::Constant ::MessageType ::ERROR ,
173+ )
144174 nil
145175 end
146176
147177 sig { void }
148178 def trigger_reload
149- $stderr . puts ( "Reloading Rails application" )
179+ log_message ( "Reloading Rails application" )
150180 send_notification ( "reload" )
151181 rescue IncompleteMessageError
152- $stderr. puts ( "Ruby LSP Rails failed to trigger reload" )
182+ log_message (
183+ "Ruby LSP Rails failed to trigger reload" ,
184+ type : RubyLsp ::Constant ::MessageType ::ERROR ,
185+ )
153186 nil
154187 end
155188
156189 sig { void }
157190 def shutdown
158- $stderr . puts ( "Ruby LSP Rails shutting down server" )
191+ log_message ( "Ruby LSP Rails shutting down server" )
159192 send_message ( "shutdown" )
160193 sleep ( 0.5 ) # give the server a bit of time to shutdown
161194 [ @stdin , @stdout , @stderr ] . each ( &:close )
@@ -214,7 +247,10 @@ def read_response
214247 response = JSON . parse ( T . must ( raw_response ) , symbolize_names : true )
215248
216249 if response [ :error ]
217- $stderr. puts ( "Ruby LSP Rails error: " + response [ :error ] )
250+ log_message (
251+ "Ruby LSP Rails error: #{ response [ :error ] } " ,
252+ type : RubyLsp ::Constant ::MessageType ::ERROR ,
253+ )
218254 return
219255 end
220256
@@ -229,6 +265,13 @@ def force_kill
229265 # Windows does not support the `TERM` signal, so we're forced to use `KILL` here
230266 Process . kill ( T . must ( Signal . list [ "KILL" ] ) , @wait_thread . pid )
231267 end
268+
269+ sig { params ( message : ::String , type : ::Integer ) . void }
270+ def log_message ( message , type : RubyLsp ::Constant ::MessageType ::LOG )
271+ return if @outgoing_queue . closed?
272+
273+ @outgoing_queue << RubyLsp ::Notification . window_log_message ( message , type : type )
274+ end
232275 end
233276
234277 class NullClient < RunnerClient
@@ -255,6 +298,11 @@ def rails_root
255298
256299 private
257300
301+ sig { params ( message : ::String , type : ::Integer ) . void }
302+ def log_message ( message , type : RubyLsp ::Constant ::MessageType ::LOG )
303+ # no-op
304+ end
305+
258306 sig { override . params ( request : String , params : T . nilable ( T ::Hash [ Symbol , T . untyped ] ) ) . void }
259307 def send_message ( request , params = nil )
260308 # no-op
0 commit comments