@@ -10,6 +10,7 @@ module Rails
10
10
# - Run tests in the VS Terminal
11
11
# - Run tests in the VS Code Test Explorer
12
12
# - Debug tests
13
+ # - Run migrations in the VS Terminal
13
14
#
14
15
# The
15
16
# [code lens](https://microsoft.github.io/language-server-protocol/specification#textDocument_codeLens)
@@ -34,6 +35,14 @@ module Rails
34
35
# end
35
36
# ````
36
37
#
38
+ # # Example:
39
+ # ```ruby
40
+ # Run in terminal
41
+ # class AddFirstNameToUsers < ActiveRecord::Migration[7.1]
42
+ # # ...
43
+ # end
44
+ # ````
45
+ #
37
46
# The code lenses will be displayed above the class and above each test method.
38
47
#
39
48
# Note: When using the Test Explorer view, if your code contains a statement to pause execution (e.g. `debugger`) it
@@ -43,6 +52,8 @@ class CodeLens
43
52
include Requests ::Support ::Common
44
53
include ActiveSupportTestCaseHelper
45
54
55
+ MIGRATE_COMMAND = "bin/rails db:migrate"
56
+
46
57
sig do
47
58
params (
48
59
response_builder : ResponseBuilders ::CollectionResponseBuilder [ Interface ::CodeLens ] ,
@@ -74,6 +85,7 @@ def on_call_node_enter(node)
74
85
sig { params ( node : Prism ::DefNode ) . void }
75
86
def on_def_node_enter ( node )
76
87
method_name = node . name . to_s
88
+
77
89
if method_name . start_with? ( "test_" )
78
90
line_number = node . location . start_line
79
91
command = "#{ test_command } #{ @path } :#{ line_number } "
@@ -84,12 +96,19 @@ def on_def_node_enter(node)
84
96
sig { params ( node : Prism ::ClassNode ) . void }
85
97
def on_class_node_enter ( node )
86
98
class_name = node . constant_path . slice
99
+ superclass_name = node . superclass &.slice
100
+
87
101
if class_name . end_with? ( "Test" )
88
102
command = "#{ test_command } #{ @path } "
89
103
add_test_code_lens ( node , name : class_name , command : command , kind : :group )
90
104
@group_id_stack . push ( @group_id )
91
105
@group_id += 1
92
106
end
107
+
108
+ if superclass_name &.start_with? ( "ActiveRecord::Migration" )
109
+ command = "#{ MIGRATE_COMMAND } VERSION=#{ migration_version } "
110
+ add_migrate_code_lens ( node , name : class_name , command : command )
111
+ end
93
112
end
94
113
95
114
sig { params ( node : Prism ::ClassNode ) . void }
@@ -111,6 +130,34 @@ def test_command
111
130
end
112
131
end
113
132
133
+ sig { returns ( T . nilable ( String ) ) }
134
+ def migration_version
135
+ File . basename ( T . must ( @path ) ) . split ( "_" ) . first
136
+ end
137
+
138
+ sig { params ( node : Prism ::Node , name : String , command : String ) . void }
139
+ def add_migrate_code_lens ( node , name :, command :)
140
+ return unless @path
141
+
142
+ arguments = [
143
+ command ,
144
+ {
145
+ start_line : node . location . start_line - 1 ,
146
+ start_column : node . location . start_column ,
147
+ end_line : node . location . end_line - 1 ,
148
+ end_column : node . location . end_column ,
149
+ } ,
150
+ ]
151
+
152
+ @response_builder << create_code_lens (
153
+ node ,
154
+ title : "Run in terminal" ,
155
+ command_name : "rubyLsp.runMigrationInTerminal" ,
156
+ arguments : arguments ,
157
+ data : { type : "migrate" } ,
158
+ )
159
+ end
160
+
114
161
sig { params ( node : Prism ::Node , name : String , command : String , kind : Symbol ) . void }
115
162
def add_test_code_lens ( node , name :, command :, kind :)
116
163
return unless @path
0 commit comments