ruby-lsp-rails 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0cdbd01ae2a03195931208bf88504c5e06ae95b321e32e1c07a5fcef993817dc
4
- data.tar.gz: 8ee3dbd7f7b0bc4851e98a51e624700526f0fbbd7535495e52bd7f9fe43d581a
3
+ metadata.gz: 641af662aeb7df4487d90ec7ffe3c1f26b7f8a936700a3b8dc5ec77d38eb65ba
4
+ data.tar.gz: 52d1989ad1288d0e3a0d0d478cdd9a79cb0ff33a3ddf25e2757a80e6822be7d3
5
5
  SHA512:
6
- metadata.gz: c2adee12e7cf92359ee6b26b64ade207c3507e2f881d0b2d00ee6b30e45e3bff1025735e616d1da062d6bde2d70bbd72ae73114f1cc13f17a30f47e48171b6a7
7
- data.tar.gz: 67307e0b0388f38e254f1fbc1822b8814075cd5ded94b73e674b1ef35cc1c989dfd2286bac4eaa901e45caa6335e024d80480470c30d08c74a2a812bf377e365
6
+ metadata.gz: f3b5ab9bad1cd657d5f79f0ef467435f6840ee720cf5b7b332e42fed3b050170521fcd0bbc590f72d0d865fb8f73daa2b0d16b16e11e61d8e2416f1963b51f83
7
+ data.tar.gz: d9f1be241d9ab18e8cfb44c62b52b09634a598bb02420dcf55a2f0de6cb8185a4aa05d41cc5d9011a5fcdbe268cf8c1178ff8d24c42b8c52abcd7d2ce225a6d4
data/README.md CHANGED
@@ -3,39 +3,68 @@
3
3
  Ruby LSP Rails is a [Ruby LSP](https://github.com/Shopify/ruby-lsp) extension for extra Rails editor features, such as:
4
4
 
5
5
  - Displaying an ActiveRecord model's database columns and types when hovering over it
6
- - (More to come!)
7
-
6
+ - Running tests and debugging tests through the terminal or the editor's UI
8
7
 
9
8
  ## Installation
10
9
 
11
10
  To install, add the following line to your application's Gemfile:
12
11
 
13
12
  ```ruby
13
+ # Gemfile
14
14
  group :development do
15
15
  gem "ruby-lsp-rails"
16
16
  end
17
17
  ```
18
+ Some features rely on server introspection, and use a Rack server which is automatically mounted by using a Railtie.
19
+
20
+ For applications with specialized routing requirements, such as custom sharding, this may not be compatible. It can
21
+ be disabled with:
22
+
23
+ ```ruby
24
+ # config/environments/development.rb
25
+ Rails.application.configure do
26
+ # ...
27
+ config.ruby_lsp_rails.server = false
28
+ # ...
29
+ end
30
+ ```
18
31
 
19
32
  ## Usage
20
33
 
34
+ ### Hover to reveal ActiveRecord schema
35
+
21
36
  1. Start your Rails server
22
37
  1. Hover over an ActiveRecord model to see its details
23
38
 
39
+ Nested models (e.g. `Admin::User`) are not yet supported.
40
+
41
+ ### Documentation
42
+
43
+ See the [documentation](https://shopify.github.io/ruby-lsp-rails) for more in-depth details about the
44
+ [supported features](https://shopify.github.io/ruby-lsp-rails/RubyLsp/Rails.html).
45
+
46
+ ### Running Tests
47
+
48
+ 1. Open a test which inherits from `ActiveSupport::TestCase` or one if its descendants, such as `ActionDispatch::IntegrationTest`.
49
+ 2. Click on the "Run", "Run in Terminal" or "Debug" code lens which appears above the test class, or an individual test.
50
+
51
+ Note: When using the Test Explorer view, if your code contains a statement to pause execution (e.g. `debugger`) it will
52
+ cause the test runner to hang.
53
+
24
54
  ## How It Works
25
55
 
26
56
  This gem consists of two components that enable enhanced Rails functionality in the editor:
27
57
 
28
- 1. A Rails engine that automatically exposes APIs when Rails server is running
58
+ 1. A Rack app that automatically exposes APIs when Rails server is running
29
59
  1. A Ruby LSP extension that connects to the exposed APIs to fetch runtime information from the Rails server
30
60
 
31
- This is why the Rails server needs to be running for features to work.
61
+ This is why the Rails server needs to be running for some features to work.
32
62
 
33
63
  > **Note**
34
64
  >
35
65
  > There is no need to restart the Ruby LSP every time the Rails server is booted.
36
66
  > If the server is shut down, the extra features will temporarily disappear and reappear once the server is running again.
37
67
 
38
-
39
68
  ## Contributing
40
69
 
41
70
  Bug reports and pull requests are welcome on GitHub at https://github.com/Shopify/ruby-lsp-rails. This project is
data/Rakefile CHANGED
@@ -9,6 +9,8 @@ load "rails/tasks/statistics.rake"
9
9
 
10
10
  require "bundler/gem_tasks"
11
11
  require "rake/testtask"
12
+ require "ruby_lsp/check_docs"
13
+ require "rdoc/task"
12
14
 
13
15
  Rake::TestTask.new(:test) do |t|
14
16
  t.libs << "test"
@@ -16,4 +18,15 @@ Rake::TestTask.new(:test) do |t|
16
18
  t.test_files = FileList["test/**/*_test.rb"]
17
19
  end
18
20
 
21
+ RDoc::Task.new do |rdoc|
22
+ rdoc.main = "README.md"
23
+ rdoc.rdoc_files.include("*.md", "lib/**/*.rb")
24
+ rdoc.rdoc_dir = "docs"
25
+ rdoc.markup = "markdown"
26
+ rdoc.options.push("--copy-files", "misc")
27
+ rdoc.options.push("--copy-files", "LICENSE.txt")
28
+ end
29
+
30
+ RubyLsp::CheckDocs.new(FileList["#{__dir__}/lib/ruby_lsp/**/*.rb"], FileList["#{__dir__}/misc/**/*.gif"])
31
+
19
32
  task default: :test
@@ -7,7 +7,11 @@ require "pathname"
7
7
  require "ruby_lsp_rails/version"
8
8
  require "ruby_lsp_rails/railtie"
9
9
 
10
- module RubyLSP
10
+ module RubyLsp
11
+ # # Supported features
12
+ #
13
+ # - [Hover](rdoc-ref:RubyLsp::Rails::Hover)
14
+ # - [CodeLens](rdoc-ref:RubyLsp::Rails::CodeLens)
11
15
  module Rails
12
16
  end
13
17
  end
@@ -0,0 +1,134 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module RubyLsp
5
+ module Rails
6
+ # ![CodeLens demo](../../code_lens.gif)
7
+ #
8
+ # This feature adds several CodeLens features for Rails applications using Active Support test cases:
9
+ # - Run tests in the VS Terminal
10
+ # - Run tests in the VS Code Test Explorer
11
+ # - Debug tests
12
+ #
13
+ # The
14
+ # [code lens](https://microsoft.github.io/language-server-protocol/specification#textDocument_codeLens)
15
+ # request informs the editor of runnable commands such as tests
16
+ #
17
+ # # Example:
18
+ #
19
+ # For the following code, Code Lenses will be added above the class definition above each test method.
20
+ #
21
+ # ```ruby
22
+ # Run
23
+ # class HelloTest < ActiveSupport::TestCase # <- Will show code lenses above for running or debugging the whole test
24
+ # test "outputs hello" do # <- Will show code lenses above for running or debugging this test
25
+ # # ...
26
+ # end
27
+ #
28
+ # test "outputs goodbye" do # <- Will show code lenses above for running or debugging this test
29
+ # # ...
30
+ # end
31
+ # end
32
+ # ````
33
+ #
34
+ # The code lenses will be displayed above the class and above each test method.
35
+ class CodeLens < ::RubyLsp::Listener
36
+ extend T::Sig
37
+ extend T::Generic
38
+
39
+ ResponseType = type_member { { fixed: T::Array[::RubyLsp::Interface::CodeLens] } }
40
+ BASE_COMMAND = "bin/rails test"
41
+
42
+ ::RubyLsp::Requests::CodeLens.add_listener(self)
43
+
44
+ sig { override.returns(ResponseType) }
45
+ attr_reader :response
46
+
47
+ sig { params(uri: String, emitter: EventEmitter, message_queue: Thread::Queue).void }
48
+ def initialize(uri, emitter, message_queue)
49
+ @response = T.let([], ResponseType)
50
+ @path = T.let(URI(uri).path, T.nilable(String))
51
+ emitter.register(self, :on_command, :on_class, :on_def)
52
+
53
+ super(emitter, message_queue)
54
+ end
55
+
56
+ sig { params(node: SyntaxTree::Command).void }
57
+ def on_command(node)
58
+ message_value = node.message.value
59
+ return unless message_value == "test" && node.arguments.parts.any?
60
+
61
+ first_argument = node.arguments.parts.first
62
+ return unless first_argument.is_a?(SyntaxTree::StringLiteral)
63
+
64
+ test_name = first_argument.parts.first.value
65
+ return unless test_name
66
+
67
+ line_number = node.location.start_line
68
+ command = "#{BASE_COMMAND} #{@path}:#{line_number}"
69
+ add_test_code_lens(node, name: test_name, command: command, kind: :example)
70
+ end
71
+
72
+ # Although uncommon, Rails tests can be written with the classic "def test_name" syntax.
73
+ sig { params(node: SyntaxTree::DefNode).void }
74
+ def on_def(node)
75
+ method_name = node.name.value
76
+ if method_name.start_with?("test_")
77
+ line_number = node.location.start_line
78
+ command = "#{BASE_COMMAND} #{@path}:#{line_number}"
79
+ add_test_code_lens(node, name: method_name, command: command, kind: :example)
80
+ end
81
+ end
82
+
83
+ sig { params(node: SyntaxTree::ClassDeclaration).void }
84
+ def on_class(node)
85
+ class_name = node.constant.constant.value
86
+ if class_name.end_with?("Test")
87
+ command = "#{BASE_COMMAND} #{@path}"
88
+ add_test_code_lens(node, name: class_name, command: command, kind: :group)
89
+ end
90
+ end
91
+
92
+ private
93
+
94
+ sig { params(node: SyntaxTree::Node, name: String, command: String, kind: Symbol).void }
95
+ def add_test_code_lens(node, name:, command:, kind:)
96
+ arguments = [
97
+ @path,
98
+ name,
99
+ command,
100
+ {
101
+ start_line: node.location.start_line - 1,
102
+ start_column: node.location.start_column,
103
+ end_line: node.location.end_line - 1,
104
+ end_column: node.location.end_column,
105
+ },
106
+ ]
107
+
108
+ @response << create_code_lens(
109
+ node,
110
+ title: "Run",
111
+ command_name: "rubyLsp.runTest",
112
+ arguments: arguments,
113
+ data: { type: "test", kind: kind },
114
+ )
115
+
116
+ @response << create_code_lens(
117
+ node,
118
+ title: "Run In Terminal",
119
+ command_name: "rubyLsp.runTestInTerminal",
120
+ arguments: arguments,
121
+ data: { type: "test_in_terminal", kind: kind },
122
+ )
123
+
124
+ @response << create_code_lens(
125
+ node,
126
+ title: "Debug",
127
+ command_name: "rubyLsp.debugTest",
128
+ arguments: arguments,
129
+ data: { type: "debug", kind: kind },
130
+ )
131
+ end
132
+ end
133
+ end
134
+ end
@@ -5,6 +5,7 @@ require "ruby_lsp/extension"
5
5
 
6
6
  require_relative "rails_client"
7
7
  require_relative "hover"
8
+ require_relative "code_lens"
8
9
 
9
10
  module RubyLsp
10
11
  module Rails
@@ -13,7 +14,6 @@ module RubyLsp
13
14
 
14
15
  sig { override.void }
15
16
  def activate
16
- # Must be the last statement in activate since it raises to display a notification for the user
17
17
  RubyLsp::Rails::RailsClient.instance.check_if_server_is_running!
18
18
  end
19
19
 
@@ -3,6 +3,17 @@
3
3
 
4
4
  module RubyLsp
5
5
  module Rails
6
+ # ![Hover demo](../../hover.gif)
7
+ #
8
+ # Augment [hover](https://microsoft.github.io/language-server-protocol/specification#textDocument_hover) with
9
+ # information about a model.
10
+ #
11
+ # # Example
12
+ #
13
+ # ```ruby
14
+ # User.all
15
+ # # ^ hovering here will show information about the User model
16
+ # ```
6
17
  class Hover < ::RubyLsp::Listener
7
18
  extend T::Sig
8
19
  extend T::Generic
@@ -14,27 +25,27 @@ module RubyLsp
14
25
  sig { override.returns(ResponseType) }
15
26
  attr_reader :response
16
27
 
17
- sig { void }
18
- def initialize
19
- @response = T.let(nil, ResponseType)
28
+ sig { params(emitter: RubyLsp::EventEmitter, message_queue: Thread::Queue).void }
29
+ def initialize(emitter, message_queue)
20
30
  super
31
+
32
+ @response = T.let(nil, ResponseType)
33
+ emitter.register(self, :on_const)
21
34
  end
22
35
 
23
- listener_events do
24
- sig { params(node: SyntaxTree::Const).void }
25
- def on_const(node)
26
- model = RailsClient.instance.model(node.value)
27
- return if model.nil?
28
-
29
- schema_file = model[:schema_file]
30
- content = +""
31
- if schema_file
32
- content << "[Schema](file://#{schema_file})\n\n"
33
- end
34
- content << model[:columns].map { |name, type| "**#{name}**: #{type}\n" }.join("\n")
35
- contents = RubyLsp::Interface::MarkupContent.new(kind: "markdown", value: content)
36
- @response = RubyLsp::Interface::Hover.new(range: range_from_syntax_tree_node(node), contents: contents)
36
+ sig { params(node: SyntaxTree::Const).void }
37
+ def on_const(node)
38
+ model = RailsClient.instance.model(node.value)
39
+ return if model.nil?
40
+
41
+ schema_file = model[:schema_file]
42
+ content = +""
43
+ if schema_file
44
+ content << "[Schema](file://#{schema_file})\n\n"
37
45
  end
46
+ content << model[:columns].map { |name, type| "**#{name}**: #{type}\n" }.join("\n")
47
+ contents = RubyLsp::Interface::MarkupContent.new(kind: "markdown", value: content)
48
+ @response = RubyLsp::Interface::Hover.new(range: range_from_syntax_tree_node(node), contents: contents)
38
49
  end
39
50
  end
40
51
  end
@@ -7,8 +7,7 @@ require "net/http"
7
7
  module RubyLsp
8
8
  module Rails
9
9
  class RailsClient
10
- class ServerNotRunningError < StandardError; end
11
- class NeedsRestartError < StandardError; end
10
+ class ServerAddressUnknown < StandardError; end
12
11
 
13
12
  extend T::Sig
14
13
  include Singleton
@@ -31,15 +30,16 @@ module RubyLsp
31
30
  @root = T.let(Dir.exist?(dummy_path) ? dummy_path : project_root.to_s, String)
32
31
  app_uri_path = "#{@root}/tmp/app_uri.txt"
33
32
 
34
- unless File.exist?(app_uri_path)
35
- raise NeedsRestartError, <<~MESSAGE
36
- The Ruby LSP Rails extension needs to be initialized. Please restart the Rails server and the Ruby LSP
37
- to get Rails features in the editor
38
- MESSAGE
39
- end
33
+ if File.exist?(app_uri_path)
34
+ url = File.read(app_uri_path).chomp
35
+
36
+ scheme, rest = url.split("://")
37
+ uri, port = T.must(rest).split(":")
40
38
 
41
- base_uri = File.read(app_uri_path).chomp
42
- @uri = T.let("#{base_uri}/ruby_lsp_rails", String)
39
+ @ssl = T.let(scheme == "https", T::Boolean)
40
+ @uri = T.let(T.must(uri), T.nilable(String))
41
+ @port = T.let(T.must(port).to_i, Integer)
42
+ end
43
43
  end
44
44
 
45
45
  sig { params(name: String).returns(T.nilable(T::Hash[Symbol, T.untyped])) }
@@ -48,34 +48,30 @@ module RubyLsp
48
48
  return unless response.code == "200"
49
49
 
50
50
  JSON.parse(response.body.chomp, symbolize_names: true)
51
- rescue Errno::ECONNREFUSED
52
- raise ServerNotRunningError, SERVER_NOT_RUNNING_MESSAGE
51
+ rescue Errno::ECONNREFUSED, ServerAddressUnknown
52
+ nil
53
53
  end
54
54
 
55
55
  sig { void }
56
56
  def check_if_server_is_running!
57
- # Check if the Rails server is running. Warn the user to boot it for Rails features
58
- pid_file = ENV.fetch("PIDFILE") { File.join(@root, "tmp", "pids", "server.pid") }
59
-
60
- # If the PID file doesn't exist, then the server hasn't been booted
61
- raise ServerNotRunningError, SERVER_NOT_RUNNING_MESSAGE unless File.exist?(pid_file)
62
-
63
- pid = File.read(pid_file).to_i
64
-
65
- begin
66
- # Issuing an EXIT signal to an existing process actually doesn't make the server shutdown. But if this
67
- # call succeeds, then the server is running. If the PID doesn't exist, Errno::ESRCH is raised
68
- Process.kill(T.must(Signal.list["EXIT"]), pid)
69
- rescue Errno::ESRCH
70
- raise ServerNotRunningError, SERVER_NOT_RUNNING_MESSAGE
71
- end
57
+ request("activate", 0.2)
58
+ rescue Errno::ECONNREFUSED, ServerAddressUnknown
59
+ warn(SERVER_NOT_RUNNING_MESSAGE)
60
+ rescue Net::ReadTimeout
61
+ # If the server is running, but the initial request is taking too long, we don't want to block the
62
+ # initialization of the Ruby LSP
72
63
  end
73
64
 
74
65
  private
75
66
 
76
- sig { params(path: String).returns(Net::HTTPResponse) }
77
- def request(path)
78
- Net::HTTP.get_response(URI("#{@uri}/#{path}"))
67
+ sig { params(path: String, timeout: T.nilable(Float)).returns(Net::HTTPResponse) }
68
+ def request(path, timeout = nil)
69
+ raise ServerAddressUnknown unless @uri
70
+
71
+ http = Net::HTTP.new(@uri, @port)
72
+ http.use_ssl = @ssl
73
+ http.read_timeout = timeout if timeout
74
+ http.get("/ruby_lsp_rails/#{path}")
79
75
  end
80
76
  end
81
77
  end
@@ -3,29 +3,26 @@
3
3
 
4
4
  module RubyLsp
5
5
  module Rails
6
- class Middleware
6
+ class RackApp
7
7
  extend T::Sig
8
8
 
9
- PATH_REGEXP = %r{/ruby_lsp_rails/models/(?<model_name>.+)}
10
-
11
- sig { params(app: T.untyped).void }
12
- def initialize(app)
13
- @app = app
14
- end
9
+ BASE_PATH = "/ruby_lsp_rails/"
15
10
 
16
11
  sig { params(env: T::Hash[T.untyped, T.untyped]).returns(T::Array[T.untyped]) }
17
12
  def call(env)
18
13
  request = ActionDispatch::Request.new(env)
19
- # TODO: improve the model name regex
20
- match = request.path.match(PATH_REGEXP)
14
+ path = request.path
21
15
 
22
- if match
23
- resolve_database_info_from_model(match[:model_name])
16
+ route, argument = path.delete_prefix(BASE_PATH).split("/")
17
+
18
+ case route
19
+ when "activate"
20
+ [200, { "Content-Type" => "application/json" }, []]
21
+ when "models"
22
+ resolve_database_info_from_model(argument)
24
23
  else
25
- @app.call(env)
24
+ not_found
26
25
  end
27
- rescue
28
- @app.call(env)
29
26
  end
30
27
 
31
28
  private
@@ -1,19 +1,37 @@
1
1
  # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
- require "ruby_lsp_rails/middleware"
4
+ require "rails/railtie"
5
+ require "ruby_lsp_rails/rack_app"
5
6
 
6
7
  module RubyLsp
7
8
  module Rails
8
9
  class Railtie < ::Rails::Railtie
9
- initializer "ruby_lsp_rails.setup" do |app|
10
- app.config.middleware.insert_after(ActionDispatch::ShowExceptions, RubyLsp::Rails::Middleware)
10
+ config.ruby_lsp_rails = ActiveSupport::OrderedOptions.new
11
+ config.ruby_lsp_rails.server = true
11
12
 
12
- config.after_initialize do |_app|
13
+ initializer "ruby_lsp_rails.setup" do |_app|
14
+ config.after_initialize do |app|
15
+ unless config.ruby_lsp_rails.server == false
16
+ app.routes.prepend do
17
+ T.bind(self, ActionDispatch::Routing::Mapper)
18
+ mount(RackApp.new => RackApp::BASE_PATH)
19
+ end
20
+ end
21
+
22
+ # If we start the app with `bin/rails console` then `Rails::Server` is not defined.
13
23
  if defined?(::Rails::Server)
14
24
  ssl_enable, host, port = ::Rails::Server::Options.new.parse!(ARGV).values_at(:SSLEnable, :Host, :Port)
15
25
  app_uri = "#{ssl_enable ? "https" : "http"}://#{host}:#{port}"
16
- File.write("#{::Rails.root}/tmp/app_uri.txt", app_uri)
26
+ app_uri_path = "#{::Rails.root}/tmp/app_uri.txt"
27
+ File.write(app_uri_path, app_uri)
28
+
29
+ at_exit do
30
+ # The app_uri.txt file should only exist when the server is running. The extension uses its presence to
31
+ # report if the server is running or not. If the server is not running, some of the extension features
32
+ # will not be available.
33
+ File.delete(app_uri_path) if File.exist?(app_uri_path)
34
+ end
17
35
  end
18
36
  end
19
37
  end
@@ -3,6 +3,6 @@
3
3
 
4
4
  module RubyLsp
5
5
  module Rails
6
- VERSION = "0.1.0"
6
+ VERSION = "0.2.0"
7
7
  end
8
8
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-lsp-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shopify
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-04-21 00:00:00.000000000 Z
11
+ date: 2023-06-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -28,16 +28,22 @@ dependencies:
28
28
  name: ruby-lsp
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - "~>"
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 0.6.2
34
+ - - "<"
32
35
  - !ruby/object:Gem::Version
33
- version: 0.4.5
36
+ version: 0.8.0
34
37
  type: :runtime
35
38
  prerelease: false
36
39
  version_requirements: !ruby/object:Gem::Requirement
37
40
  requirements:
38
- - - "~>"
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: 0.6.2
44
+ - - "<"
39
45
  - !ruby/object:Gem::Version
40
- version: 0.4.5
46
+ version: 0.8.0
41
47
  - !ruby/object:Gem::Dependency
42
48
  name: sorbet-runtime
43
49
  requirement: !ruby/object:Gem::Requirement
@@ -63,10 +69,11 @@ files:
63
69
  - README.md
64
70
  - Rakefile
65
71
  - lib/ruby-lsp-rails.rb
72
+ - lib/ruby_lsp/ruby_lsp_rails/code_lens.rb
66
73
  - lib/ruby_lsp/ruby_lsp_rails/extension.rb
67
74
  - lib/ruby_lsp/ruby_lsp_rails/hover.rb
68
75
  - lib/ruby_lsp/ruby_lsp_rails/rails_client.rb
69
- - lib/ruby_lsp_rails/middleware.rb
76
+ - lib/ruby_lsp_rails/rack_app.rb
70
77
  - lib/ruby_lsp_rails/railtie.rb
71
78
  - lib/ruby_lsp_rails/version.rb
72
79
  - lib/tasks/ruby_lsp_rails_tasks.rake
@@ -93,7 +100,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
93
100
  - !ruby/object:Gem::Version
94
101
  version: '0'
95
102
  requirements: []
96
- rubygems_version: 3.4.12
103
+ rubygems_version: 3.4.14
97
104
  signing_key:
98
105
  specification_version: 4
99
106
  summary: A Ruby LSP extension for Rails