ruby-lsp 0.3.5 → 0.3.7
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 +4 -4
- data/README.md +8 -0
- data/VERSION +1 -1
- data/lib/ruby_lsp/document.rb +47 -13
- data/lib/ruby_lsp/requests/base_request.rb +9 -0
- data/lib/ruby_lsp/requests/code_actions.rb +1 -1
- data/lib/ruby_lsp/requests/document_highlight.rb +1 -2
- data/lib/ruby_lsp/requests/document_link.rb +2 -3
- data/lib/ruby_lsp/requests/hover.rb +1 -1
- data/lib/ruby_lsp/requests/inlay_hints.rb +1 -1
- data/lib/ruby_lsp/requests/on_type_formatting.rb +3 -3
- data/lib/ruby_lsp/requests/semantic_highlighting.rb +41 -2
- data/lib/ruby_lsp/server.rb +19 -7
- data/lib/ruby_lsp/store.rb +5 -1
- metadata +8 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cddece941249b188843957c1c026e6e1e10f875c26a7c2f14f556a53556cc94f
|
4
|
+
data.tar.gz: cdc7368658e3de269033b41bceb831becb68320cd1444ec9792380408ee2a4f2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d28c2f96939d517cacae6b86407e5990ca1587f99848bc14ff98ea24b5421e2ad38ba0ee39a7040c2a4694623e349c907c6f2a764737e0cc9316d302804687b2
|
7
|
+
data.tar.gz: a5e118206994b0e58ff9568043eb534360e591f931c0c8f078579283ab0519057a236606728c230e4be86f7405035a6e2bea1e52959af280f2067f0e52127278
|
data/README.md
CHANGED
@@ -28,6 +28,14 @@ are expected to adhere to the
|
|
28
28
|
[Contributor Covenant](https://github.com/Shopify/ruby-lsp/blob/main/CODE_OF_CONDUCT.md)
|
29
29
|
code of conduct.
|
30
30
|
|
31
|
+
### Running the test suite
|
32
|
+
|
33
|
+
Run the test suite with `bin/test`.
|
34
|
+
|
35
|
+
For more visibility into which tests are running, use the `SpecReporter`:
|
36
|
+
|
37
|
+
`SPEC_REPORTER=1 bin/test`
|
38
|
+
|
31
39
|
### Expectation testing
|
32
40
|
|
33
41
|
To simplify the way we run tests over different pieces of Ruby code, we use a custom expectations test framework against a set of Ruby fixtures.
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.3.
|
1
|
+
0.3.7
|
data/lib/ruby_lsp/document.rb
CHANGED
@@ -18,10 +18,11 @@ module RubyLsp
|
|
18
18
|
sig { returns(T::Array[EditShape]) }
|
19
19
|
attr_reader :syntax_error_edits
|
20
20
|
|
21
|
-
sig { params(source: String).void }
|
22
|
-
def initialize(source)
|
21
|
+
sig { params(source: String, encoding: String).void }
|
22
|
+
def initialize(source, encoding = "utf-8")
|
23
23
|
@cache = T.let({}, T::Hash[Symbol, T.untyped])
|
24
24
|
@syntax_error_edits = T.let([], T::Array[EditShape])
|
25
|
+
@encoding = T.let(encoding, String)
|
25
26
|
@source = T.let(source, String)
|
26
27
|
@parsable_source = T.let(source.dup, String)
|
27
28
|
@unparsed_edits = T.let([], T::Array[EditShape])
|
@@ -83,6 +84,11 @@ module RubyLsp
|
|
83
84
|
!@tree.nil?
|
84
85
|
end
|
85
86
|
|
87
|
+
sig { returns(Scanner) }
|
88
|
+
def create_scanner
|
89
|
+
Scanner.new(@source, @encoding)
|
90
|
+
end
|
91
|
+
|
86
92
|
private
|
87
93
|
|
88
94
|
sig { params(edits: T::Array[EditShape]).void }
|
@@ -96,15 +102,16 @@ module RubyLsp
|
|
96
102
|
end
|
97
103
|
|
98
104
|
@tree = SyntaxTree.parse(@parsable_source)
|
99
|
-
rescue
|
100
|
-
#
|
105
|
+
rescue StandardError
|
106
|
+
# Trying to maintain a parsable source when there are syntax errors is a best effort. If we fail to apply edits or
|
107
|
+
# parse, just ignore it
|
101
108
|
end
|
102
109
|
|
103
110
|
sig { params(source: String, range: RangeShape, text: String).void }
|
104
111
|
def apply_edit(source, range, text)
|
105
|
-
scanner = Scanner.new(source)
|
106
|
-
start_position = scanner.
|
107
|
-
end_position = scanner.
|
112
|
+
scanner = Scanner.new(source, @encoding)
|
113
|
+
start_position = scanner.find_char_position(range[:start])
|
114
|
+
end_position = scanner.find_char_position(range[:end])
|
108
115
|
|
109
116
|
source[start_position...end_position] = text
|
110
117
|
end
|
@@ -112,22 +119,49 @@ module RubyLsp
|
|
112
119
|
class Scanner
|
113
120
|
extend T::Sig
|
114
121
|
|
115
|
-
|
116
|
-
|
122
|
+
LINE_BREAK = T.let(0x0A, Integer)
|
123
|
+
# After character 0xFFFF, UTF-16 considers characters to have length 2 and we have to account for that
|
124
|
+
SURROGATE_PAIR_START = T.let(0xFFFF, Integer)
|
125
|
+
|
126
|
+
sig { params(source: String, encoding: String).void }
|
127
|
+
def initialize(source, encoding)
|
117
128
|
@current_line = T.let(0, Integer)
|
118
129
|
@pos = T.let(0, Integer)
|
119
|
-
@source = source
|
130
|
+
@source = T.let(source.codepoints, T::Array[Integer])
|
131
|
+
@encoding = encoding
|
120
132
|
end
|
121
133
|
|
134
|
+
# Finds the character index inside the source string for a given line and column
|
122
135
|
sig { params(position: PositionShape).returns(Integer) }
|
123
|
-
def
|
136
|
+
def find_char_position(position)
|
137
|
+
# Find the character index for the beginning of the requested line
|
124
138
|
until @current_line == position[:line]
|
125
|
-
@pos += 1 until
|
139
|
+
@pos += 1 until LINE_BREAK == @source[@pos]
|
126
140
|
@pos += 1
|
127
141
|
@current_line += 1
|
128
142
|
end
|
129
143
|
|
130
|
-
|
144
|
+
# The final position is the beginning of the line plus the requested column. If the encoding is UTF-16, we also
|
145
|
+
# need to adjust for surrogate pairs
|
146
|
+
requested_position = @pos + position[:character]
|
147
|
+
requested_position -= utf_16_character_position_correction(@pos, requested_position) if @encoding == "utf-16"
|
148
|
+
requested_position
|
149
|
+
end
|
150
|
+
|
151
|
+
# Subtract 1 for each character after 0xFFFF in the current line from the column position, so that we hit the
|
152
|
+
# right character in the UTF-8 representation
|
153
|
+
sig { params(current_position: Integer, requested_position: Integer).returns(Integer) }
|
154
|
+
def utf_16_character_position_correction(current_position, requested_position)
|
155
|
+
utf16_unicode_correction = 0
|
156
|
+
|
157
|
+
until current_position == requested_position
|
158
|
+
codepoint = @source[current_position]
|
159
|
+
utf16_unicode_correction += 1 if codepoint && codepoint > SURROGATE_PAIR_START
|
160
|
+
|
161
|
+
current_position += 1
|
162
|
+
end
|
163
|
+
|
164
|
+
utf16_unicode_correction
|
131
165
|
end
|
132
166
|
end
|
133
167
|
end
|
@@ -79,6 +79,15 @@ module RubyLsp
|
|
79
79
|
[]
|
80
80
|
end
|
81
81
|
end
|
82
|
+
|
83
|
+
sig { params(node: T.nilable(SyntaxTree::Node), range: T.nilable(T::Range[Integer])).returns(T::Boolean) }
|
84
|
+
def visible?(node, range)
|
85
|
+
return true if range.nil?
|
86
|
+
return false if node.nil?
|
87
|
+
|
88
|
+
loc = node.location
|
89
|
+
range.cover?(loc.start_line - 1) && range.cover?(loc.end_line - 1)
|
90
|
+
end
|
82
91
|
end
|
83
92
|
end
|
84
93
|
end
|
@@ -35,7 +35,7 @@ module RubyLsp
|
|
35
35
|
|
36
36
|
sig { override.returns(T.all(T::Array[LanguageServer::Protocol::Interface::CodeAction], Object)) }
|
37
37
|
def run
|
38
|
-
diagnostics = Diagnostics.new(@uri, @document).run
|
38
|
+
diagnostics = @document.cache_fetch(:diagnostics) { Diagnostics.new(@uri, @document).run }
|
39
39
|
corrections = diagnostics.select do |diagnostic|
|
40
40
|
diagnostic.correctable? && T.cast(diagnostic, Support::RuboCopDiagnostic).in_range?(@range)
|
41
41
|
end
|
@@ -30,10 +30,9 @@ module RubyLsp
|
|
30
30
|
super(document)
|
31
31
|
|
32
32
|
@highlights = T.let([], T::Array[LanguageServer::Protocol::Interface::DocumentHighlight])
|
33
|
-
position = Document::Scanner.new(document.source).find_position(position)
|
34
|
-
|
35
33
|
return unless document.parsed?
|
36
34
|
|
35
|
+
position = document.create_scanner.find_char_position(position)
|
37
36
|
@target = T.let(find(T.must(document.tree), position), T.nilable(Support::HighlightTarget))
|
38
37
|
end
|
39
38
|
|
@@ -50,9 +50,8 @@ module RubyLsp
|
|
50
50
|
spec = stub.to_spec
|
51
51
|
lookup[spec.name] = {}
|
52
52
|
lookup[spec.name][spec.version.to_s] = {}
|
53
|
-
prefix_matchers =
|
54
|
-
|
55
|
-
prefix_matcher = Regexp.union(prefix_matchers)
|
53
|
+
prefix_matchers = Regexp.union(spec.require_paths.map { |rp| Regexp.new("^#{rp}/") })
|
54
|
+
prefix_matcher = Regexp.union(prefix_matchers, //)
|
56
55
|
|
57
56
|
spec.files.each do |file|
|
58
57
|
path = file.sub(prefix_matcher, "")
|
@@ -24,7 +24,7 @@ module RubyLsp
|
|
24
24
|
def initialize(document, position)
|
25
25
|
super(document)
|
26
26
|
|
27
|
-
@position = T.let(
|
27
|
+
@position = T.let(document.create_scanner.find_char_position(position), Integer)
|
28
28
|
end
|
29
29
|
|
30
30
|
sig { override.returns(T.nilable(LanguageServer::Protocol::Interface::Hover)) }
|
@@ -40,7 +40,7 @@ module RubyLsp
|
|
40
40
|
return unless node.exception.nil?
|
41
41
|
|
42
42
|
loc = node.location
|
43
|
-
return unless
|
43
|
+
return unless visible?(node, @range)
|
44
44
|
|
45
45
|
@hints << LanguageServer::Protocol::Interface::InlayHint.new(
|
46
46
|
position: { line: loc.start_line - 1, character: loc.start_column + RESCUE_STRING_LENGTH },
|
@@ -27,9 +27,9 @@ module RubyLsp
|
|
27
27
|
def initialize(document, position, trigger_character)
|
28
28
|
super(document)
|
29
29
|
|
30
|
-
scanner =
|
31
|
-
line_begin = position[:line] == 0 ? 0 : scanner.
|
32
|
-
line_end = scanner.
|
30
|
+
scanner = document.create_scanner
|
31
|
+
line_begin = position[:line] == 0 ? 0 : scanner.find_char_position({ line: position[:line] - 1, character: 0 })
|
32
|
+
line_end = scanner.find_char_position(position)
|
33
33
|
line = T.must(@document.source[line_begin..line_end])
|
34
34
|
|
35
35
|
@indentation = T.let(find_indentation(line), Integer)
|
@@ -76,13 +76,20 @@ module RubyLsp
|
|
76
76
|
const :modifier, T::Array[Integer]
|
77
77
|
end
|
78
78
|
|
79
|
-
sig
|
80
|
-
|
79
|
+
sig do
|
80
|
+
params(
|
81
|
+
document: Document,
|
82
|
+
range: T.nilable(T::Range[Integer]),
|
83
|
+
encoder: T.nilable(Support::SemanticTokenEncoder),
|
84
|
+
).void
|
85
|
+
end
|
86
|
+
def initialize(document, range: nil, encoder: nil)
|
81
87
|
super(document)
|
82
88
|
|
83
89
|
@encoder = encoder
|
84
90
|
@tokens = T.let([], T::Array[SemanticToken])
|
85
91
|
@tree = T.let(T.must(document.tree), SyntaxTree::Node)
|
92
|
+
@range = range
|
86
93
|
@special_methods = T.let(nil, T.nilable(T::Array[String]))
|
87
94
|
end
|
88
95
|
|
@@ -105,6 +112,8 @@ module RubyLsp
|
|
105
112
|
|
106
113
|
sig { override.params(node: SyntaxTree::Call).void }
|
107
114
|
def visit_call(node)
|
115
|
+
return super unless visible?(node, @range)
|
116
|
+
|
108
117
|
visit(node.receiver)
|
109
118
|
|
110
119
|
message = node.message
|
@@ -115,12 +124,16 @@ module RubyLsp
|
|
115
124
|
|
116
125
|
sig { override.params(node: SyntaxTree::Command).void }
|
117
126
|
def visit_command(node)
|
127
|
+
return super unless visible?(node, @range)
|
128
|
+
|
118
129
|
add_token(node.message.location, :method) unless special_method?(node.message.value)
|
119
130
|
visit(node.arguments)
|
120
131
|
end
|
121
132
|
|
122
133
|
sig { override.params(node: SyntaxTree::CommandCall).void }
|
123
134
|
def visit_command_call(node)
|
135
|
+
return super unless visible?(node, @range)
|
136
|
+
|
124
137
|
visit(node.receiver)
|
125
138
|
add_token(node.message.location, :method)
|
126
139
|
visit(node.arguments)
|
@@ -128,11 +141,15 @@ module RubyLsp
|
|
128
141
|
|
129
142
|
sig { override.params(node: SyntaxTree::Const).void }
|
130
143
|
def visit_const(node)
|
144
|
+
return super unless visible?(node, @range)
|
145
|
+
|
131
146
|
add_token(node.location, :namespace)
|
132
147
|
end
|
133
148
|
|
134
149
|
sig { override.params(node: SyntaxTree::Def).void }
|
135
150
|
def visit_def(node)
|
151
|
+
return super unless visible?(node, @range)
|
152
|
+
|
136
153
|
add_token(node.name.location, :method, [:declaration])
|
137
154
|
visit(node.params)
|
138
155
|
visit(node.bodystmt)
|
@@ -140,6 +157,8 @@ module RubyLsp
|
|
140
157
|
|
141
158
|
sig { override.params(node: SyntaxTree::DefEndless).void }
|
142
159
|
def visit_def_endless(node)
|
160
|
+
return super unless visible?(node, @range)
|
161
|
+
|
143
162
|
add_token(node.name.location, :method, [:declaration])
|
144
163
|
visit(node.paren)
|
145
164
|
visit(node.operator)
|
@@ -148,6 +167,8 @@ module RubyLsp
|
|
148
167
|
|
149
168
|
sig { override.params(node: SyntaxTree::Defs).void }
|
150
169
|
def visit_defs(node)
|
170
|
+
return super unless visible?(node, @range)
|
171
|
+
|
151
172
|
visit(node.target)
|
152
173
|
visit(node.operator)
|
153
174
|
add_token(node.name.location, :method, [:declaration])
|
@@ -157,12 +178,16 @@ module RubyLsp
|
|
157
178
|
|
158
179
|
sig { override.params(node: SyntaxTree::FCall).void }
|
159
180
|
def visit_fcall(node)
|
181
|
+
return super unless visible?(node, @range)
|
182
|
+
|
160
183
|
add_token(node.value.location, :method) unless special_method?(node.value.value)
|
161
184
|
visit(node.arguments)
|
162
185
|
end
|
163
186
|
|
164
187
|
sig { override.params(node: SyntaxTree::Kw).void }
|
165
188
|
def visit_kw(node)
|
189
|
+
return super unless visible?(node, @range)
|
190
|
+
|
166
191
|
case node.value
|
167
192
|
when "self"
|
168
193
|
add_token(node.location, :variable, [:default_library])
|
@@ -171,6 +196,8 @@ module RubyLsp
|
|
171
196
|
|
172
197
|
sig { override.params(node: SyntaxTree::Params).void }
|
173
198
|
def visit_params(node)
|
199
|
+
return super unless visible?(node, @range)
|
200
|
+
|
174
201
|
node.keywords.each do |keyword,|
|
175
202
|
location = keyword.location
|
176
203
|
add_token(location_without_colon(location), :parameter)
|
@@ -191,6 +218,8 @@ module RubyLsp
|
|
191
218
|
|
192
219
|
sig { override.params(node: SyntaxTree::Field).void }
|
193
220
|
def visit_field(node)
|
221
|
+
return super unless visible?(node, @range)
|
222
|
+
|
194
223
|
add_token(node.name.location, :method)
|
195
224
|
|
196
225
|
super
|
@@ -198,6 +227,8 @@ module RubyLsp
|
|
198
227
|
|
199
228
|
sig { override.params(node: SyntaxTree::VarField).void }
|
200
229
|
def visit_var_field(node)
|
230
|
+
return super unless visible?(node, @range)
|
231
|
+
|
201
232
|
value = node.value
|
202
233
|
|
203
234
|
case value
|
@@ -211,6 +242,8 @@ module RubyLsp
|
|
211
242
|
|
212
243
|
sig { override.params(node: SyntaxTree::VarRef).void }
|
213
244
|
def visit_var_ref(node)
|
245
|
+
return super unless visible?(node, @range)
|
246
|
+
|
214
247
|
value = node.value
|
215
248
|
|
216
249
|
case value
|
@@ -224,11 +257,15 @@ module RubyLsp
|
|
224
257
|
|
225
258
|
sig { override.params(node: SyntaxTree::VCall).void }
|
226
259
|
def visit_vcall(node)
|
260
|
+
return super unless visible?(node, @range)
|
261
|
+
|
227
262
|
add_token(node.value.location, :method) unless special_method?(node.value.value)
|
228
263
|
end
|
229
264
|
|
230
265
|
sig { override.params(node: SyntaxTree::ClassDeclaration).void }
|
231
266
|
def visit_class(node)
|
267
|
+
return super unless visible?(node, @range)
|
268
|
+
|
232
269
|
add_token(node.constant.location, :class, [:declaration])
|
233
270
|
add_token(node.superclass.location, :class) if node.superclass
|
234
271
|
visit(node.bodystmt)
|
@@ -236,6 +273,8 @@ module RubyLsp
|
|
236
273
|
|
237
274
|
sig { override.params(node: SyntaxTree::ModuleDeclaration).void }
|
238
275
|
def visit_module(node)
|
276
|
+
return super unless visible?(node, @range)
|
277
|
+
|
239
278
|
add_token(node.constant.location, :class, [:declaration])
|
240
279
|
visit(node.bodystmt)
|
241
280
|
end
|
data/lib/ruby_lsp/server.rb
CHANGED
@@ -7,6 +7,8 @@ module RubyLsp
|
|
7
7
|
Handler.start do
|
8
8
|
on("initialize") do |request|
|
9
9
|
store.clear
|
10
|
+
store.encoding = request.dig(:params, :capabilities, :general, :positionEncodings)
|
11
|
+
|
10
12
|
initialization_options = request.dig(:params, :initializationOptions)
|
11
13
|
enabled_features = initialization_options.fetch(:enabledFeatures, [])
|
12
14
|
|
@@ -38,10 +40,8 @@ module RubyLsp
|
|
38
40
|
token_types: Requests::SemanticHighlighting::TOKEN_TYPES.keys,
|
39
41
|
token_modifiers: Requests::SemanticHighlighting::TOKEN_MODIFIERS.keys,
|
40
42
|
),
|
41
|
-
range:
|
42
|
-
full: {
|
43
|
-
delta: true,
|
44
|
-
},
|
43
|
+
range: true,
|
44
|
+
full: { delta: false },
|
45
45
|
)
|
46
46
|
end
|
47
47
|
|
@@ -168,6 +168,19 @@ module RubyLsp
|
|
168
168
|
end
|
169
169
|
end
|
170
170
|
|
171
|
+
on("textDocument/semanticTokens/range", parallel: true) do |request|
|
172
|
+
document = store.get(request.dig(:params, :textDocument, :uri))
|
173
|
+
range = request.dig(:params, :range)
|
174
|
+
start_line = range.dig(:start, :line)
|
175
|
+
end_line = range.dig(:end, :line)
|
176
|
+
|
177
|
+
Requests::SemanticHighlighting.new(
|
178
|
+
document,
|
179
|
+
range: start_line..end_line,
|
180
|
+
encoder: Requests::Support::SemanticTokenEncoder.new,
|
181
|
+
).run
|
182
|
+
end
|
183
|
+
|
171
184
|
on("textDocument/formatting", parallel: true) do |request|
|
172
185
|
uri = request.dig(:params, :textDocument, :uri)
|
173
186
|
|
@@ -192,13 +205,12 @@ module RubyLsp
|
|
192
205
|
|
193
206
|
on("textDocument/codeAction", parallel: true) do |request|
|
194
207
|
uri = request.dig(:params, :textDocument, :uri)
|
208
|
+
document = store.get(uri)
|
195
209
|
range = request.dig(:params, :range)
|
196
210
|
start_line = range.dig(:start, :line)
|
197
211
|
end_line = range.dig(:end, :line)
|
198
212
|
|
199
|
-
|
200
|
-
Requests::CodeActions.new(uri, document, start_line..end_line).run
|
201
|
-
end
|
213
|
+
Requests::CodeActions.new(uri, document, start_line..end_line).run
|
202
214
|
end
|
203
215
|
|
204
216
|
on("textDocument/inlayHint", parallel: true) do |request|
|
data/lib/ruby_lsp/store.rb
CHANGED
@@ -9,9 +9,13 @@ module RubyLsp
|
|
9
9
|
class Store
|
10
10
|
extend T::Sig
|
11
11
|
|
12
|
+
sig { params(encoding: String).void }
|
13
|
+
attr_writer :encoding
|
14
|
+
|
12
15
|
sig { void }
|
13
16
|
def initialize
|
14
17
|
@state = T.let({}, T::Hash[String, Document])
|
18
|
+
@encoding = T.let("utf-8", String)
|
15
19
|
end
|
16
20
|
|
17
21
|
sig { params(uri: String).returns(Document) }
|
@@ -25,7 +29,7 @@ module RubyLsp
|
|
25
29
|
|
26
30
|
sig { params(uri: String, content: String).void }
|
27
31
|
def set(uri, content)
|
28
|
-
document = Document.new(content)
|
32
|
+
document = Document.new(content, @encoding)
|
29
33
|
@state[uri] = document
|
30
34
|
end
|
31
35
|
|
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.3.
|
4
|
+
version: 0.3.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Shopify
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-12-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: language_server-protocol
|
@@ -45,6 +45,9 @@ dependencies:
|
|
45
45
|
- - ">="
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: 4.0.2
|
48
|
+
- - "<"
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
version: 5.0.0
|
48
51
|
type: :runtime
|
49
52
|
prerelease: false
|
50
53
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -52,6 +55,9 @@ dependencies:
|
|
52
55
|
- - ">="
|
53
56
|
- !ruby/object:Gem::Version
|
54
57
|
version: 4.0.2
|
58
|
+
- - "<"
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: 5.0.0
|
55
61
|
description: An opinionated language server for Ruby
|
56
62
|
email:
|
57
63
|
- ruby@shopify.com
|