@@ -20,6 +20,8 @@ module Rails
20
20
class Addon < ::RubyLsp ::Addon
21
21
extend T ::Sig
22
22
23
+ RUN_MIGRATIONS_TITLE = "Run Migrations"
24
+
23
25
sig { void }
24
26
def initialize
25
27
super
@@ -37,6 +39,7 @@ def initialize
37
39
@addon_mutex . synchronize do
38
40
# We need to ensure the Rails client is fully loaded before we activate the server addons
39
41
@client_mutex . synchronize { @rails_runner_client = RunnerClient . create_client ( T . must ( @outgoing_queue ) ) }
42
+ offer_to_run_pending_migrations
40
43
end
41
44
end
42
45
end
@@ -119,11 +122,80 @@ def create_definition_listener(response_builder, uri, node_context, dispatcher)
119
122
120
123
sig { params ( changes : T ::Array [ { uri : String , type : Integer } ] ) . void }
121
124
def workspace_did_change_watched_files ( changes )
122
- if changes . any? do |change |
123
- change [ :uri ] . end_with? ( "db/schema.rb" ) || change [ :uri ] . end_with? ( "structure.sql" )
124
- end
125
+ if changes . any? { |c | c [ :uri ] . end_with? ( "db/schema.rb" ) || c [ :uri ] . end_with? ( "structure.sql" ) }
125
126
@rails_runner_client . trigger_reload
126
127
end
128
+
129
+ if changes . any? do |c |
130
+ %r{db/migrate/.*\. rb} . match? ( c [ :uri ] ) && c [ :type ] != Constant ::FileChangeType ::CHANGED
131
+ end
132
+
133
+ offer_to_run_pending_migrations
134
+ end
135
+ end
136
+
137
+ sig { override . returns ( String ) }
138
+ def name
139
+ "Ruby LSP Rails"
140
+ end
141
+
142
+ sig { override . params ( title : String ) . void }
143
+ def handle_window_show_message_response ( title )
144
+ if title == RUN_MIGRATIONS_TITLE
145
+
146
+ begin_progress ( "run-migrations" , "Running Migrations" )
147
+ response = @rails_runner_client . run_migrations
148
+
149
+ if response && @outgoing_queue
150
+ if response [ :status ] == 0
151
+ # Both log the message and show it as part of progress because sometimes running migrations is so fast you
152
+ # can't see the progress notification
153
+ @outgoing_queue << Notification . window_log_message ( response [ :message ] )
154
+ report_progress ( "run-migrations" , message : response [ :message ] )
155
+ else
156
+ @outgoing_queue << Notification . window_show_message (
157
+ "Migrations failed to run\n \n #{ response [ :message ] } " ,
158
+ type : Constant ::MessageType ::ERROR ,
159
+ )
160
+ end
161
+ end
162
+
163
+ end_progress ( "run-migrations" )
164
+ end
165
+ end
166
+
167
+ private
168
+
169
+ sig { params ( id : String , title : String , percentage : T . nilable ( Integer ) , message : T . nilable ( String ) ) . void }
170
+ def begin_progress ( id , title , percentage : nil , message : nil )
171
+ return unless @global_state &.client_capabilities &.supports_progress && @outgoing_queue
172
+
173
+ @outgoing_queue << Request . new (
174
+ id : "progress-request-#{ id } " ,
175
+ method : "window/workDoneProgress/create" ,
176
+ params : Interface ::WorkDoneProgressCreateParams . new ( token : id ) ,
177
+ )
178
+
179
+ @outgoing_queue << Notification . progress_begin (
180
+ id ,
181
+ title ,
182
+ percentage : percentage ,
183
+ message : "#{ percentage } % completed" ,
184
+ )
185
+ end
186
+
187
+ sig { params ( id : String , percentage : T . nilable ( Integer ) , message : T . nilable ( String ) ) . void }
188
+ def report_progress ( id , percentage : nil , message : nil )
189
+ return unless @global_state &.client_capabilities &.supports_progress && @outgoing_queue
190
+
191
+ @outgoing_queue << Notification . progress_report ( id , percentage : percentage , message : message )
192
+ end
193
+
194
+ sig { params ( id : String ) . void }
195
+ def end_progress ( id )
196
+ return unless @global_state &.client_capabilities &.supports_progress && @outgoing_queue
197
+
198
+ @outgoing_queue << Notification . progress_end ( id )
127
199
end
128
200
129
201
sig { params ( global_state : GlobalState , outgoing_queue : Thread ::Queue ) . void }
@@ -152,9 +224,26 @@ def register_additional_file_watchers(global_state:, outgoing_queue:)
152
224
)
153
225
end
154
226
155
- sig { override . returns ( String ) }
156
- def name
157
- "Ruby LSP Rails"
227
+ sig { void }
228
+ def offer_to_run_pending_migrations
229
+ return unless @outgoing_queue
230
+ return unless @global_state &.client_capabilities &.window_show_message_supports_extra_properties
231
+
232
+ migration_message = @rails_runner_client . pending_migrations_message
233
+ return unless migration_message
234
+
235
+ @outgoing_queue << Request . new (
236
+ id : "rails-pending-migrations" ,
237
+ method : "window/showMessageRequest" ,
238
+ params : {
239
+ type : Constant ::MessageType ::INFO ,
240
+ message : migration_message ,
241
+ actions : [
242
+ { title : RUN_MIGRATIONS_TITLE , addon_name : name , method : "window/showMessageRequest" } ,
243
+ { title : "Cancel" , addon_name : name , method : "window/showMessageRequest" } ,
244
+ ] ,
245
+ } ,
246
+ )
158
247
end
159
248
end
160
249
end
0 commit comments