ruby-lsp 0.16.4 → 0.16.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 94d4dfcda701bdf2ea1dd04e2a271572a139fe3d716e1bd535e2c05bcc9b3d23
4
- data.tar.gz: b79dfc816bf027e733fa5f44db3e2d1039ae860f9dee88fe996ab1a27089d467
3
+ metadata.gz: bcd4426f17d6d429be733a9adcdf799e23c29689ad5fb69f9b9f7b3cd334bf9b
4
+ data.tar.gz: 071d5c37e1acf83c07a5b48e85a3bc4a18fb63a20b54ff191158799cf4320803
5
5
  SHA512:
6
- metadata.gz: 9de1f73feba2284c75294542a0e9ae1196f092004fe83ef815b2e08a1b404daceebc0b3f6f8f59149f936c8f7414821942556bee522776a909c071765dcc3443
7
- data.tar.gz: b7617a6d508a94e5a06b8d39acb4d2bcc28d02832b19ab8567ed58b6b297aa3fc450dd0a116257fe91fc9545683550456c0d712fc32dc3f3ff716e2cdca2985e
6
+ metadata.gz: 9edc44ec74f5f5d9b5f15fb7d22501126eb8f6bec3d9a69b3061946b369ecb0e453e45e9a0dc9df1482117dc738f7bd66005e2dcd0cd46e3aaad6f6658283766
7
+ data.tar.gz: c4f9ddb4da9373544b2456632a0fb76bdbca5e5ddf5e874b0e6ab4f6aae13ad8b17ef9482873b37ae33bc7ec797faebde76bf5a6e9d86e6a4ddf798b4eb9f0df
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.16.4
1
+ 0.16.5
@@ -11,7 +11,7 @@ module RubyIndexer
11
11
  sig { returns(String) }
12
12
  attr_reader :file_path
13
13
 
14
- sig { returns(Prism::Location) }
14
+ sig { returns(RubyIndexer::Location) }
15
15
  attr_reader :location
16
16
 
17
17
  sig { returns(T::Array[String]) }
@@ -20,13 +20,33 @@ module RubyIndexer
20
20
  sig { returns(Symbol) }
21
21
  attr_accessor :visibility
22
22
 
23
- sig { params(name: String, file_path: String, location: Prism::Location, comments: T::Array[String]).void }
23
+ sig do
24
+ params(
25
+ name: String,
26
+ file_path: String,
27
+ location: T.any(Prism::Location, RubyIndexer::Location),
28
+ comments: T::Array[String],
29
+ ).void
30
+ end
24
31
  def initialize(name, file_path, location, comments)
25
32
  @name = name
26
33
  @file_path = file_path
27
- @location = location
28
34
  @comments = comments
29
35
  @visibility = T.let(:public, Symbol)
36
+
37
+ @location = T.let(
38
+ if location.is_a?(Prism::Location)
39
+ Location.new(
40
+ location.start_line,
41
+ location.end_line,
42
+ location.start_column,
43
+ location.end_column,
44
+ )
45
+ else
46
+ location
47
+ end,
48
+ RubyIndexer::Location,
49
+ )
30
50
  end
31
51
 
32
52
  sig { returns(String) }
@@ -50,7 +70,7 @@ module RubyIndexer
50
70
  params(
51
71
  name: String,
52
72
  file_path: String,
53
- location: Prism::Location,
73
+ location: T.any(Prism::Location, RubyIndexer::Location),
54
74
  comments: T::Array[String],
55
75
  ).void
56
76
  end
@@ -81,7 +101,7 @@ module RubyIndexer
81
101
  params(
82
102
  name: String,
83
103
  file_path: String,
84
- location: Prism::Location,
104
+ location: T.any(Prism::Location, RubyIndexer::Location),
85
105
  comments: T::Array[String],
86
106
  parent_class: T.nilable(String),
87
107
  ).void
@@ -181,7 +201,7 @@ module RubyIndexer
181
201
  params(
182
202
  name: String,
183
203
  file_path: String,
184
- location: Prism::Location,
204
+ location: T.any(Prism::Location, RubyIndexer::Location),
185
205
  comments: T::Array[String],
186
206
  owner: T.nilable(Entry::Namespace),
187
207
  ).void
@@ -219,7 +239,7 @@ module RubyIndexer
219
239
  params(
220
240
  name: String,
221
241
  file_path: String,
222
- location: Prism::Location,
242
+ location: T.any(Prism::Location, RubyIndexer::Location),
223
243
  comments: T::Array[String],
224
244
  parameters_node: T.nilable(Prism::ParametersNode),
225
245
  owner: T.nilable(Entry::Namespace),
@@ -349,7 +369,7 @@ module RubyIndexer
349
369
  nesting: T::Array[String],
350
370
  name: String,
351
371
  file_path: String,
352
- location: Prism::Location,
372
+ location: T.any(Prism::Location, RubyIndexer::Location),
353
373
  comments: T::Array[String],
354
374
  ).void
355
375
  end
@@ -0,0 +1,26 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module RubyIndexer
5
+ class Location
6
+ extend T::Sig
7
+
8
+ sig { returns(Integer) }
9
+ attr_reader :start_line, :end_line, :start_column, :end_column
10
+
11
+ sig do
12
+ params(
13
+ start_line: Integer,
14
+ end_line: Integer,
15
+ start_column: Integer,
16
+ end_column: Integer,
17
+ ).void
18
+ end
19
+ def initialize(start_line, end_line, start_column, end_column)
20
+ @start_line = start_line
21
+ @end_line = end_line
22
+ @start_column = start_column
23
+ @end_column = end_column
24
+ end
25
+ end
26
+ end
@@ -10,6 +10,7 @@ require "ruby_indexer/lib/ruby_indexer/index"
10
10
  require "ruby_indexer/lib/ruby_indexer/entry"
11
11
  require "ruby_indexer/lib/ruby_indexer/configuration"
12
12
  require "ruby_indexer/lib/ruby_indexer/prefix_tree"
13
+ require "ruby_indexer/lib/ruby_indexer/location"
13
14
 
14
15
  module RubyIndexer
15
16
  @configuration = T.let(Configuration.new, Configuration)
@@ -62,7 +62,7 @@ module RubyLsp
62
62
  # The following requests need to be executed in the main thread directly to avoid concurrency issues. Everything
63
63
  # else is pushed into the incoming queue
64
64
  case method
65
- when "initialize", "textDocument/didOpen", "textDocument/didClose", "textDocument/didChange"
65
+ when "initialize", "initialized", "textDocument/didOpen", "textDocument/didClose", "textDocument/didChange"
66
66
  process_message(message)
67
67
  when "shutdown"
68
68
  $stderr.puts("Shutting down Ruby LSP...")
@@ -29,8 +29,9 @@ module RubyLsp
29
29
  @encoding = T.let(Encoding::UTF_8, Encoding)
30
30
 
31
31
  @formatter = T.let("auto", String)
32
- @test_library = T.let(detect_test_library, String)
33
- @typechecker = T.let(detect_typechecker, T::Boolean)
32
+ @linters = T.let([], T::Array[String])
33
+ @test_library = T.let("minitest", String)
34
+ @typechecker = T.let(true, T::Boolean)
34
35
  @index = T.let(RubyIndexer::Index.new, RubyIndexer::Index)
35
36
  @supported_formatters = T.let({}, T::Hash[String, Requests::Support::Formatter])
36
37
  @supports_watching_files = T.let(false, T::Boolean)
@@ -46,14 +47,25 @@ module RubyLsp
46
47
  @supported_formatters[@formatter]
47
48
  end
48
49
 
50
+ sig { returns(T::Array[Requests::Support::Formatter]) }
51
+ def active_linters
52
+ @linters.filter_map { |name| @supported_formatters[name] }
53
+ end
54
+
49
55
  sig { params(options: T::Hash[Symbol, T.untyped]).void }
50
56
  def apply_options(options)
57
+ dependencies = gather_dependencies
51
58
  workspace_uri = options.dig(:workspaceFolders, 0, :uri)
52
59
  @workspace_uri = URI(workspace_uri) if workspace_uri
53
60
 
54
61
  specified_formatter = options.dig(:initializationOptions, :formatter)
55
62
  @formatter = specified_formatter if specified_formatter
56
- @formatter = detect_formatter if @formatter == "auto"
63
+ @formatter = detect_formatter(dependencies) if @formatter == "auto"
64
+
65
+ specified_linters = options.dig(:initializationOptions, :linters)
66
+ @linters = specified_linters || detect_linters(dependencies)
67
+ @test_library = detect_test_library(dependencies)
68
+ @typechecker = detect_typechecker(dependencies)
57
69
 
58
70
  encodings = options.dig(:capabilities, :general, :positionEncodings)
59
71
  @encoding = if !encodings || encodings.empty?
@@ -89,28 +101,32 @@ module RubyLsp
89
101
  end
90
102
  end
91
103
 
92
- sig { params(gem_pattern: Regexp).returns(T::Boolean) }
93
- def direct_dependency?(gem_pattern)
94
- dependencies.any?(gem_pattern)
95
- end
96
-
97
104
  private
98
105
 
99
- sig { returns(String) }
100
- def detect_formatter
106
+ sig { params(dependencies: T::Array[String]).returns(String) }
107
+ def detect_formatter(dependencies)
101
108
  # NOTE: Intentionally no $ at end, since we want to match rubocop-shopify, etc.
102
- if direct_dependency?(/^rubocop/)
109
+ if dependencies.any?(/^rubocop/)
103
110
  "rubocop"
104
- elsif direct_dependency?(/^syntax_tree$/)
111
+ elsif dependencies.any?(/^syntax_tree$/)
105
112
  "syntax_tree"
106
113
  else
107
114
  "none"
108
115
  end
109
116
  end
110
117
 
111
- sig { returns(String) }
112
- def detect_test_library
113
- if direct_dependency?(/^rspec/)
118
+ # Try to detect if there are linters in the project's dependencies. For auto-detection, we always only consider a
119
+ # single linter. To have multiple linters running, the user must configure them manually
120
+ sig { params(dependencies: T::Array[String]).returns(T::Array[String]) }
121
+ def detect_linters(dependencies)
122
+ linters = []
123
+ linters << "rubocop" if dependencies.any?(/^rubocop/)
124
+ linters
125
+ end
126
+
127
+ sig { params(dependencies: T::Array[String]).returns(String) }
128
+ def detect_test_library(dependencies)
129
+ if dependencies.any?(/^rspec/)
114
130
  "rspec"
115
131
  # A Rails app may have a dependency on minitest, but we would instead want to use the Rails test runner provided
116
132
  # by ruby-lsp-rails. A Rails app doesn't need to depend on the rails gem itself, individual components like
@@ -119,23 +135,23 @@ module RubyLsp
119
135
  elsif File.exist?(File.join(workspace_path, "bin/rails"))
120
136
  "rails"
121
137
  # NOTE: Intentionally ends with $ to avoid mis-matching minitest-reporters, etc. in a Rails app.
122
- elsif direct_dependency?(/^minitest$/)
138
+ elsif dependencies.any?(/^minitest$/)
123
139
  "minitest"
124
- elsif direct_dependency?(/^test-unit/)
140
+ elsif dependencies.any?(/^test-unit/)
125
141
  "test-unit"
126
142
  else
127
143
  "unknown"
128
144
  end
129
145
  end
130
146
 
131
- sig { returns(T::Boolean) }
132
- def detect_typechecker
147
+ sig { params(dependencies: T::Array[String]).returns(T::Boolean) }
148
+ def detect_typechecker(dependencies)
133
149
  return false if ENV["RUBY_LSP_BYPASS_TYPECHECKER"]
134
150
 
135
151
  # We can't read the env from within `Bundle.with_original_env` so we need to set it here.
136
152
  ruby_lsp_env_is_test = (ENV["RUBY_LSP_ENV"] == "test")
137
153
  Bundler.with_original_env do
138
- sorbet_static_detected = Bundler.locked_gems.specs.any? { |spec| spec.name == "sorbet-static" }
154
+ sorbet_static_detected = dependencies.any?(/^sorbet-static/)
139
155
  # Don't show message while running tests, since it's noisy
140
156
  if sorbet_static_detected && !ruby_lsp_env_is_test
141
157
  $stderr.puts("Ruby LSP detected this is a Sorbet project so will defer to Sorbet LSP for some functionality")
@@ -147,16 +163,11 @@ module RubyLsp
147
163
  end
148
164
 
149
165
  sig { returns(T::Array[String]) }
150
- def dependencies
151
- @dependencies ||= T.let(
152
- begin
153
- Bundler.with_original_env { Bundler.default_gemfile }
154
- Bundler.locked_gems.dependencies.keys + gemspec_dependencies
155
- rescue Bundler::GemfileNotFound
156
- []
157
- end,
158
- T.nilable(T::Array[String]),
159
- )
166
+ def gather_dependencies
167
+ Bundler.with_original_env { Bundler.default_gemfile }
168
+ Bundler.locked_gems.dependencies.keys + gemspec_dependencies
169
+ rescue Bundler::GemfileNotFound
170
+ []
160
171
  end
161
172
 
162
173
  sig { returns(T::Array[String]) }
@@ -7,6 +7,8 @@ module RubyLsp
7
7
  extend T::Sig
8
8
  include Requests::Support::Common
9
9
 
10
+ MAX_NUMBER_OF_DEFINITION_CANDIDATES_WITHOUT_RECEIVER = 10
11
+
10
12
  sig do
11
13
  params(
12
14
  response_builder: ResponseBuilders::CollectionResponseBuilder[Interface::Location],
@@ -64,12 +66,17 @@ module RubyLsp
64
66
 
65
67
  sig { params(node: Prism::CallNode).void }
66
68
  def handle_method_definition(node)
67
- return unless self_receiver?(node)
68
-
69
69
  message = node.message
70
70
  return unless message
71
71
 
72
- methods = @index.resolve_method(message, @nesting.join("::"))
72
+ methods = if self_receiver?(node)
73
+ @index.resolve_method(message, @nesting.join("::"))
74
+ else
75
+ # If the method doesn't have a receiver, then we provide a few candidates to jump to
76
+ # But we don't want to provide too many candidates, as it can be overwhelming
77
+ @index[message]&.take(MAX_NUMBER_OF_DEFINITION_CANDIDATES_WITHOUT_RECEIVER)
78
+ end
79
+
73
80
  return unless methods
74
81
 
75
82
  methods.each do |target_method|
@@ -34,7 +34,7 @@ module RubyLsp
34
34
  sig { params(global_state: GlobalState, document: Document).void }
35
35
  def initialize(global_state, document)
36
36
  super()
37
- @active_formatter = T.let(global_state.active_formatter, T.nilable(Support::Formatter))
37
+ @active_linters = T.let(global_state.active_linters, T::Array[Support::Formatter])
38
38
  @document = document
39
39
  @uri = T.let(document.uri, URI::Generic)
40
40
  end
@@ -45,10 +45,13 @@ module RubyLsp
45
45
  diagnostics.concat(syntax_error_diagnostics, syntax_warning_diagnostics)
46
46
 
47
47
  # Running RuboCop is slow, so to avoid excessive runs we only do so if the file is syntactically valid
48
- return diagnostics if @document.syntax_error? || !@active_formatter
48
+ return diagnostics if @document.syntax_error? || @active_linters.empty?
49
+
50
+ @active_linters.each do |linter|
51
+ linter_diagnostics = linter.run_diagnostic(@uri, @document)
52
+ diagnostics.concat(linter_diagnostics) if linter_diagnostics
53
+ end
49
54
 
50
- formatter_diagnostics = @active_formatter.run_diagnostic(@uri, @document)
51
- diagnostics.concat(formatter_diagnostics) if formatter_diagnostics
52
55
  diagnostics
53
56
  end
54
57
 
@@ -40,10 +40,13 @@ module RubyLsp
40
40
  end
41
41
  end
42
42
 
43
- sig { params(dispatcher: Prism::Dispatcher, range: T.nilable(T::Range[Integer])).void }
44
- def initialize(dispatcher, range: nil)
43
+ sig { params(global_state: GlobalState, dispatcher: Prism::Dispatcher, range: T.nilable(T::Range[Integer])).void }
44
+ def initialize(global_state, dispatcher, range: nil)
45
45
  super()
46
- @response_builder = T.let(ResponseBuilders::SemanticHighlighting.new, ResponseBuilders::SemanticHighlighting)
46
+ @response_builder = T.let(
47
+ ResponseBuilders::SemanticHighlighting.new(global_state.encoding),
48
+ ResponseBuilders::SemanticHighlighting,
49
+ )
47
50
  Listeners::SemanticHighlighting.new(dispatcher, @response_builder, range: range)
48
51
 
49
52
  Addon.addons.each do |addon|
@@ -55,19 +55,21 @@ module RubyLsp
55
55
 
56
56
  ResponseType = type_member { { fixed: Interface::SemanticTokens } }
57
57
 
58
- sig { void }
59
- def initialize
60
- super
58
+ sig { params(encoding: Encoding).void }
59
+ def initialize(encoding)
60
+ super()
61
+ @encoding = encoding
61
62
  @stack = T.let([], T::Array[SemanticToken])
62
63
  end
63
64
 
64
65
  sig { params(location: Prism::Location, type: Symbol, modifiers: T::Array[Symbol]).void }
65
66
  def add_token(location, type, modifiers = [])
66
- length = location.end_offset - location.start_offset
67
+ length = location.end_code_units_offset(@encoding) - location.start_code_units_offset(@encoding)
67
68
  modifiers_indices = modifiers.filter_map { |modifier| TOKEN_MODIFIERS[modifier] }
68
69
  @stack.push(
69
70
  SemanticToken.new(
70
- location: location,
71
+ start_line: location.start_line,
72
+ start_code_unit_column: location.start_code_units_column(@encoding),
71
73
  length: length,
72
74
  type: T.must(TOKEN_TYPES[type]),
73
75
  modifier: modifiers_indices,
@@ -75,6 +77,15 @@ module RubyLsp
75
77
  )
76
78
  end
77
79
 
80
+ sig { params(location: Prism::Location).returns(T::Boolean) }
81
+ def last_token_matches?(location)
82
+ token = @stack.last
83
+ return false unless token
84
+
85
+ token.start_line == location.start_line &&
86
+ token.start_code_unit_column == location.start_code_units_column(@encoding)
87
+ end
88
+
78
89
  sig { returns(T.nilable(SemanticToken)) }
79
90
  def last
80
91
  @stack.last
@@ -88,8 +99,11 @@ module RubyLsp
88
99
  class SemanticToken
89
100
  extend T::Sig
90
101
 
91
- sig { returns(Prism::Location) }
92
- attr_reader :location
102
+ sig { returns(Integer) }
103
+ attr_reader :start_line
104
+
105
+ sig { returns(Integer) }
106
+ attr_reader :start_code_unit_column
93
107
 
94
108
  sig { returns(Integer) }
95
109
  attr_reader :length
@@ -100,9 +114,18 @@ module RubyLsp
100
114
  sig { returns(T::Array[Integer]) }
101
115
  attr_reader :modifier
102
116
 
103
- sig { params(location: Prism::Location, length: Integer, type: Integer, modifier: T::Array[Integer]).void }
104
- def initialize(location:, length:, type:, modifier:)
105
- @location = location
117
+ sig do
118
+ params(
119
+ start_line: Integer,
120
+ start_code_unit_column: Integer,
121
+ length: Integer,
122
+ type: Integer,
123
+ modifier: T::Array[Integer],
124
+ ).void
125
+ end
126
+ def initialize(start_line:, start_code_unit_column:, length:, type:, modifier:)
127
+ @start_line = start_line
128
+ @start_code_unit_column = start_code_unit_column
106
129
  @length = length
107
130
  @type = type
108
131
  @modifier = modifier
@@ -146,7 +169,7 @@ module RubyLsp
146
169
  # Enumerable#sort_by is not deterministic when the compared values are equal.
147
170
  # When that happens, we need to use the index as a tie breaker to ensure
148
171
  # that the order of the tokens is always the same.
149
- [token.location.start_line, token.location.start_column, index]
172
+ [token.start_line, token.start_code_unit_column, index]
150
173
  end
151
174
 
152
175
  delta = sorted_tokens.flat_map do |token|
@@ -167,8 +190,8 @@ module RubyLsp
167
190
  # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_semanticTokens
168
191
  sig { params(token: SemanticToken).returns(T::Array[Integer]) }
169
192
  def compute_delta(token)
170
- row = token.location.start_line - 1
171
- column = token.location.start_column
193
+ row = token.start_line - 1
194
+ column = token.start_code_unit_column
172
195
 
173
196
  begin
174
197
  delta_line = row - @current_row
@@ -334,7 +334,7 @@ module RubyLsp
334
334
  document_link = Requests::DocumentLink.new(uri, document.comments, dispatcher)
335
335
  code_lens = Requests::CodeLens.new(@global_state, uri, dispatcher)
336
336
 
337
- semantic_highlighting = Requests::SemanticHighlighting.new(dispatcher)
337
+ semantic_highlighting = Requests::SemanticHighlighting.new(@global_state, dispatcher)
338
338
  dispatcher.dispatch(document.tree)
339
339
 
340
340
  # Store all responses retrieve in this round of visits in the cache and then return the response for the request
@@ -366,7 +366,7 @@ module RubyLsp
366
366
  end_line = range.dig(:end, :line)
367
367
 
368
368
  dispatcher = Prism::Dispatcher.new
369
- request = Requests::SemanticHighlighting.new(dispatcher, range: start_line..end_line)
369
+ request = Requests::SemanticHighlighting.new(@global_state, dispatcher, range: start_line..end_line)
370
370
  dispatcher.visit(document.tree)
371
371
 
372
372
  response = request.perform
@@ -75,7 +75,7 @@ module RubyLsp
75
75
  class Request < Message
76
76
  extend T::Sig
77
77
 
78
- sig { params(id: Integer, method: String, params: Object).void }
78
+ sig { params(id: T.any(Integer, String), method: String, params: Object).void }
79
79
  def initialize(id:, method:, params:)
80
80
  @id = id
81
81
  super(method: method, params: params)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-lsp
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.16.4
4
+ version: 0.16.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shopify
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-04-11 00:00:00.000000000 Z
11
+ date: 2024-04-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: language_server-protocol
@@ -30,20 +30,20 @@ dependencies:
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: 0.22.0
33
+ version: 0.23.0
34
34
  - - "<"
35
35
  - !ruby/object:Gem::Version
36
- version: '0.25'
36
+ version: '0.28'
37
37
  type: :runtime
38
38
  prerelease: false
39
39
  version_requirements: !ruby/object:Gem::Requirement
40
40
  requirements:
41
41
  - - ">="
42
42
  - !ruby/object:Gem::Version
43
- version: 0.22.0
43
+ version: 0.23.0
44
44
  - - "<"
45
45
  - !ruby/object:Gem::Version
46
- version: '0.25'
46
+ version: '0.28'
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: sorbet-runtime
49
49
  requirement: !ruby/object:Gem::Requirement
@@ -83,6 +83,7 @@ files:
83
83
  - lib/ruby_indexer/lib/ruby_indexer/entry.rb
84
84
  - lib/ruby_indexer/lib/ruby_indexer/index.rb
85
85
  - lib/ruby_indexer/lib/ruby_indexer/indexable_path.rb
86
+ - lib/ruby_indexer/lib/ruby_indexer/location.rb
86
87
  - lib/ruby_indexer/lib/ruby_indexer/prefix_tree.rb
87
88
  - lib/ruby_indexer/ruby_indexer.rb
88
89
  - lib/ruby_indexer/test/classes_and_modules_test.rb
@@ -177,7 +178,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
177
178
  - !ruby/object:Gem::Version
178
179
  version: '0'
179
180
  requirements: []
180
- rubygems_version: 3.5.7
181
+ rubygems_version: 3.5.9
181
182
  signing_key:
182
183
  specification_version: 4
183
184
  summary: An opinionated language server for Ruby