ruby-lsp 0.13.2 → 0.13.4
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 +30 -0
- data/VERSION +1 -1
- data/lib/ruby_lsp/check_docs.rb +3 -3
- data/lib/ruby_lsp/document.rb +12 -0
- data/lib/ruby_lsp/executor.rb +77 -266
- data/lib/ruby_lsp/listener.rb +1 -50
- data/lib/ruby_lsp/listeners/code_lens.rb +233 -0
- data/lib/ruby_lsp/listeners/completion.rb +275 -0
- data/lib/ruby_lsp/listeners/definition.rb +158 -0
- data/lib/ruby_lsp/listeners/document_highlight.rb +556 -0
- data/lib/ruby_lsp/listeners/document_link.rb +162 -0
- data/lib/ruby_lsp/listeners/document_symbol.rb +223 -0
- data/lib/ruby_lsp/listeners/folding_ranges.rb +271 -0
- data/lib/ruby_lsp/listeners/hover.rb +152 -0
- data/lib/ruby_lsp/listeners/inlay_hints.rb +80 -0
- data/lib/ruby_lsp/listeners/semantic_highlighting.rb +430 -0
- data/lib/ruby_lsp/listeners/signature_help.rb +74 -0
- data/lib/ruby_lsp/requests/code_action_resolve.rb +4 -4
- data/lib/ruby_lsp/requests/code_actions.rb +13 -4
- data/lib/ruby_lsp/requests/code_lens.rb +21 -221
- data/lib/ruby_lsp/requests/completion.rb +64 -244
- data/lib/ruby_lsp/requests/definition.rb +34 -147
- data/lib/ruby_lsp/requests/diagnostics.rb +17 -5
- data/lib/ruby_lsp/requests/document_highlight.rb +12 -536
- data/lib/ruby_lsp/requests/document_link.rb +11 -132
- data/lib/ruby_lsp/requests/document_symbol.rb +23 -210
- data/lib/ruby_lsp/requests/folding_ranges.rb +16 -252
- data/lib/ruby_lsp/requests/formatting.rb +4 -4
- data/lib/ruby_lsp/requests/hover.rb +48 -92
- data/lib/ruby_lsp/requests/inlay_hints.rb +23 -56
- data/lib/ruby_lsp/requests/on_type_formatting.rb +16 -4
- data/lib/ruby_lsp/requests/request.rb +17 -0
- data/lib/ruby_lsp/requests/selection_ranges.rb +4 -3
- data/lib/ruby_lsp/requests/semantic_highlighting.rb +21 -408
- data/lib/ruby_lsp/requests/show_syntax_tree.rb +4 -4
- data/lib/ruby_lsp/requests/signature_help.rb +43 -51
- data/lib/ruby_lsp/requests/support/common.rb +3 -2
- data/lib/ruby_lsp/requests/support/dependency_detector.rb +2 -0
- data/lib/ruby_lsp/requests/support/semantic_token_encoder.rb +2 -2
- data/lib/ruby_lsp/requests/workspace_symbol.rb +5 -4
- data/lib/ruby_lsp/requests.rb +1 -1
- data/lib/ruby_lsp/utils.rb +8 -0
- metadata +17 -6
- data/lib/ruby_lsp/requests/base_request.rb +0 -24
@@ -1,6 +1,8 @@
|
|
1
1
|
# typed: strict
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
+
require "ruby_lsp/listeners/folding_ranges"
|
5
|
+
|
4
6
|
module RubyLsp
|
5
7
|
module Requests
|
6
8
|
# 
|
@@ -15,268 +17,30 @@ module RubyLsp
|
|
15
17
|
# puts "Hello"
|
16
18
|
# end # <-- folding range end
|
17
19
|
# ```
|
18
|
-
class FoldingRanges <
|
20
|
+
class FoldingRanges < Request
|
19
21
|
extend T::Sig
|
20
22
|
extend T::Generic
|
21
23
|
|
22
|
-
|
23
|
-
|
24
|
-
sig { params(comments: T::Array[Prism::Comment], dispatcher: Prism::Dispatcher).void }
|
25
|
-
def initialize(comments, dispatcher)
|
26
|
-
super(dispatcher)
|
27
|
-
|
28
|
-
@_response = T.let([], ResponseType)
|
29
|
-
@requires = T.let([], T::Array[Prism::CallNode])
|
30
|
-
@finalized_response = T.let(false, T::Boolean)
|
31
|
-
@comments = comments
|
24
|
+
class << self
|
25
|
+
extend T::Sig
|
32
26
|
|
33
|
-
|
34
|
-
|
35
|
-
:
|
36
|
-
:on_in_node_enter,
|
37
|
-
:on_rescue_node_enter,
|
38
|
-
:on_when_node_enter,
|
39
|
-
:on_interpolated_string_node_enter,
|
40
|
-
:on_array_node_enter,
|
41
|
-
:on_block_node_enter,
|
42
|
-
:on_case_node_enter,
|
43
|
-
:on_case_match_node_enter,
|
44
|
-
:on_class_node_enter,
|
45
|
-
:on_module_node_enter,
|
46
|
-
:on_for_node_enter,
|
47
|
-
:on_hash_node_enter,
|
48
|
-
:on_singleton_class_node_enter,
|
49
|
-
:on_unless_node_enter,
|
50
|
-
:on_until_node_enter,
|
51
|
-
:on_while_node_enter,
|
52
|
-
:on_else_node_enter,
|
53
|
-
:on_ensure_node_enter,
|
54
|
-
:on_begin_node_enter,
|
55
|
-
:on_def_node_enter,
|
56
|
-
:on_call_node_enter,
|
57
|
-
:on_lambda_node_enter,
|
58
|
-
)
|
59
|
-
end
|
60
|
-
|
61
|
-
sig { override.returns(ResponseType) }
|
62
|
-
def _response
|
63
|
-
unless @finalized_response
|
64
|
-
push_comment_ranges
|
65
|
-
emit_requires_range
|
66
|
-
@finalized_response = true
|
27
|
+
sig { returns(Interface::FoldingRangeClientCapabilities) }
|
28
|
+
def provider
|
29
|
+
Interface::FoldingRangeClientCapabilities.new(line_folding_only: true)
|
67
30
|
end
|
68
|
-
|
69
|
-
@_response
|
70
|
-
end
|
71
|
-
|
72
|
-
sig { params(node: Prism::IfNode).void }
|
73
|
-
def on_if_node_enter(node)
|
74
|
-
add_statements_range(node)
|
75
|
-
end
|
76
|
-
|
77
|
-
sig { params(node: Prism::InNode).void }
|
78
|
-
def on_in_node_enter(node)
|
79
|
-
add_statements_range(node)
|
80
|
-
end
|
81
|
-
|
82
|
-
sig { params(node: Prism::RescueNode).void }
|
83
|
-
def on_rescue_node_enter(node)
|
84
|
-
add_statements_range(node)
|
85
|
-
end
|
86
|
-
|
87
|
-
sig { params(node: Prism::WhenNode).void }
|
88
|
-
def on_when_node_enter(node)
|
89
|
-
add_statements_range(node)
|
90
|
-
end
|
91
|
-
|
92
|
-
sig { params(node: Prism::InterpolatedStringNode).void }
|
93
|
-
def on_interpolated_string_node_enter(node)
|
94
|
-
opening_loc = node.opening_loc || node.location
|
95
|
-
closing_loc = node.closing_loc || node.parts.last&.location || node.location
|
96
|
-
|
97
|
-
add_lines_range(opening_loc.start_line, closing_loc.start_line - 1)
|
98
31
|
end
|
99
32
|
|
100
|
-
|
101
|
-
def on_array_node_enter(node)
|
102
|
-
add_simple_range(node)
|
103
|
-
end
|
104
|
-
|
105
|
-
sig { params(node: Prism::BlockNode).void }
|
106
|
-
def on_block_node_enter(node)
|
107
|
-
add_simple_range(node)
|
108
|
-
end
|
109
|
-
|
110
|
-
sig { params(node: Prism::CaseNode).void }
|
111
|
-
def on_case_node_enter(node)
|
112
|
-
add_simple_range(node)
|
113
|
-
end
|
114
|
-
|
115
|
-
sig { params(node: Prism::CaseMatchNode).void }
|
116
|
-
def on_case_match_node_enter(node)
|
117
|
-
add_simple_range(node)
|
118
|
-
end
|
119
|
-
|
120
|
-
sig { params(node: Prism::ClassNode).void }
|
121
|
-
def on_class_node_enter(node)
|
122
|
-
add_simple_range(node)
|
123
|
-
end
|
124
|
-
|
125
|
-
sig { params(node: Prism::ModuleNode).void }
|
126
|
-
def on_module_node_enter(node)
|
127
|
-
add_simple_range(node)
|
128
|
-
end
|
129
|
-
|
130
|
-
sig { params(node: Prism::ForNode).void }
|
131
|
-
def on_for_node_enter(node)
|
132
|
-
add_simple_range(node)
|
133
|
-
end
|
134
|
-
|
135
|
-
sig { params(node: Prism::HashNode).void }
|
136
|
-
def on_hash_node_enter(node)
|
137
|
-
add_simple_range(node)
|
138
|
-
end
|
139
|
-
|
140
|
-
sig { params(node: Prism::SingletonClassNode).void }
|
141
|
-
def on_singleton_class_node_enter(node)
|
142
|
-
add_simple_range(node)
|
143
|
-
end
|
144
|
-
|
145
|
-
sig { params(node: Prism::UnlessNode).void }
|
146
|
-
def on_unless_node_enter(node)
|
147
|
-
add_simple_range(node)
|
148
|
-
end
|
149
|
-
|
150
|
-
sig { params(node: Prism::UntilNode).void }
|
151
|
-
def on_until_node_enter(node)
|
152
|
-
add_simple_range(node)
|
153
|
-
end
|
154
|
-
|
155
|
-
sig { params(node: Prism::WhileNode).void }
|
156
|
-
def on_while_node_enter(node)
|
157
|
-
add_simple_range(node)
|
158
|
-
end
|
159
|
-
|
160
|
-
sig { params(node: Prism::ElseNode).void }
|
161
|
-
def on_else_node_enter(node)
|
162
|
-
add_simple_range(node)
|
163
|
-
end
|
164
|
-
|
165
|
-
sig { params(node: Prism::EnsureNode).void }
|
166
|
-
def on_ensure_node_enter(node)
|
167
|
-
add_simple_range(node)
|
168
|
-
end
|
169
|
-
|
170
|
-
sig { params(node: Prism::BeginNode).void }
|
171
|
-
def on_begin_node_enter(node)
|
172
|
-
add_simple_range(node)
|
173
|
-
end
|
174
|
-
|
175
|
-
sig { params(node: Prism::DefNode).void }
|
176
|
-
def on_def_node_enter(node)
|
177
|
-
params = node.parameters
|
178
|
-
parameter_loc = params&.location
|
179
|
-
location = node.location
|
180
|
-
|
181
|
-
if params && parameter_loc.end_line > location.start_line
|
182
|
-
# Multiline parameters
|
183
|
-
add_lines_range(location.start_line, parameter_loc.end_line)
|
184
|
-
add_lines_range(parameter_loc.end_line + 1, location.end_line - 1)
|
185
|
-
else
|
186
|
-
add_lines_range(location.start_line, location.end_line - 1)
|
187
|
-
end
|
188
|
-
end
|
189
|
-
|
190
|
-
sig { params(node: Prism::CallNode).void }
|
191
|
-
def on_call_node_enter(node)
|
192
|
-
# If we find a require, don't visit the child nodes (prevent `super`), so that we can keep accumulating into
|
193
|
-
# the `@requires` array and then push the range whenever we find a node that isn't a CallNode
|
194
|
-
if require?(node)
|
195
|
-
@requires << node
|
196
|
-
return
|
197
|
-
end
|
198
|
-
|
199
|
-
location = node.location
|
200
|
-
add_lines_range(location.start_line, location.end_line - 1)
|
201
|
-
end
|
202
|
-
|
203
|
-
sig { params(node: Prism::LambdaNode).void }
|
204
|
-
def on_lambda_node_enter(node)
|
205
|
-
add_simple_range(node)
|
206
|
-
end
|
207
|
-
|
208
|
-
private
|
209
|
-
|
210
|
-
sig { void }
|
211
|
-
def push_comment_ranges
|
212
|
-
# Group comments that are on consecutive lines and then push ranges for each group that has at least 2 comments
|
213
|
-
@comments.chunk_while do |this, other|
|
214
|
-
this.location.end_line + 1 == other.location.start_line
|
215
|
-
end.each do |chunk|
|
216
|
-
next if chunk.length == 1
|
217
|
-
|
218
|
-
@_response << Interface::FoldingRange.new(
|
219
|
-
start_line: T.must(chunk.first).location.start_line - 1,
|
220
|
-
end_line: T.must(chunk.last).location.end_line - 1,
|
221
|
-
kind: "comment",
|
222
|
-
)
|
223
|
-
end
|
224
|
-
end
|
225
|
-
|
226
|
-
sig { void }
|
227
|
-
def emit_requires_range
|
228
|
-
if @requires.length > 1
|
229
|
-
@_response << Interface::FoldingRange.new(
|
230
|
-
start_line: T.must(@requires.first).location.start_line - 1,
|
231
|
-
end_line: T.must(@requires.last).location.end_line - 1,
|
232
|
-
kind: "imports",
|
233
|
-
)
|
234
|
-
end
|
235
|
-
|
236
|
-
@requires.clear
|
237
|
-
end
|
238
|
-
|
239
|
-
sig { params(node: Prism::CallNode).returns(T::Boolean) }
|
240
|
-
def require?(node)
|
241
|
-
message = node.message
|
242
|
-
return false unless message == "require" || message == "require_relative"
|
243
|
-
|
244
|
-
receiver = node.receiver
|
245
|
-
return false unless receiver.nil? || receiver.slice == "Kernel"
|
246
|
-
|
247
|
-
arguments = node.arguments&.arguments
|
248
|
-
return false unless arguments
|
249
|
-
|
250
|
-
arguments.length == 1 && arguments.first.is_a?(Prism::StringNode)
|
251
|
-
end
|
252
|
-
|
253
|
-
sig { params(node: T.any(Prism::IfNode, Prism::InNode, Prism::RescueNode, Prism::WhenNode)).void }
|
254
|
-
def add_statements_range(node)
|
255
|
-
statements = node.statements
|
256
|
-
return unless statements
|
257
|
-
|
258
|
-
body = statements.body
|
259
|
-
return if body.empty?
|
260
|
-
|
261
|
-
add_lines_range(node.location.start_line, T.must(body.last).location.end_line)
|
262
|
-
end
|
33
|
+
ResponseType = type_member { { fixed: T::Array[Interface::FoldingRange] } }
|
263
34
|
|
264
|
-
sig { params(
|
265
|
-
def
|
266
|
-
|
267
|
-
|
35
|
+
sig { params(comments: T::Array[Prism::Comment], dispatcher: Prism::Dispatcher).void }
|
36
|
+
def initialize(comments, dispatcher)
|
37
|
+
super()
|
38
|
+
@listener = T.let(Listeners::FoldingRanges.new(comments, dispatcher), Listener[ResponseType])
|
268
39
|
end
|
269
40
|
|
270
|
-
sig {
|
271
|
-
def
|
272
|
-
|
273
|
-
return if start_line >= end_line
|
274
|
-
|
275
|
-
@_response << Interface::FoldingRange.new(
|
276
|
-
start_line: start_line - 1,
|
277
|
-
end_line: end_line - 1,
|
278
|
-
kind: "region",
|
279
|
-
)
|
41
|
+
sig { override.returns(ResponseType) }
|
42
|
+
def perform
|
43
|
+
@listener.response
|
280
44
|
end
|
281
45
|
end
|
282
46
|
end
|
@@ -25,7 +25,7 @@ module RubyLsp
|
|
25
25
|
# puts "Hello" # --> formatting: fixes the indentation on save
|
26
26
|
# end
|
27
27
|
# ```
|
28
|
-
class Formatting <
|
28
|
+
class Formatting < Request
|
29
29
|
class Error < StandardError; end
|
30
30
|
class InvalidFormatter < StandardError; end
|
31
31
|
|
@@ -55,14 +55,14 @@ module RubyLsp
|
|
55
55
|
|
56
56
|
sig { params(document: Document, formatter: String).void }
|
57
57
|
def initialize(document, formatter: "auto")
|
58
|
-
super(
|
59
|
-
|
58
|
+
super()
|
59
|
+
@document = document
|
60
60
|
@uri = T.let(document.uri, URI::Generic)
|
61
61
|
@formatter = formatter
|
62
62
|
end
|
63
63
|
|
64
64
|
sig { override.returns(T.nilable(T.all(T::Array[Interface::TextEdit], Object))) }
|
65
|
-
def
|
65
|
+
def perform
|
66
66
|
return if @formatter == "none"
|
67
67
|
return if @document.syntax_error?
|
68
68
|
|
@@ -1,6 +1,8 @@
|
|
1
1
|
# typed: strict
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
+
require "ruby_lsp/listeners/hover"
|
5
|
+
|
4
6
|
module RubyLsp
|
5
7
|
module Requests
|
6
8
|
# 
|
@@ -13,123 +15,77 @@ module RubyLsp
|
|
13
15
|
# ```ruby
|
14
16
|
# String # -> Hovering over the class reference will show all declaration locations and the documentation
|
15
17
|
# ```
|
16
|
-
class Hover <
|
18
|
+
class Hover < Request
|
17
19
|
extend T::Sig
|
18
20
|
extend T::Generic
|
19
21
|
|
20
|
-
|
22
|
+
class << self
|
23
|
+
extend T::Sig
|
21
24
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
Prism::ConstantPathNode,
|
28
|
-
],
|
29
|
-
T::Array[T.class_of(Prism::Node)],
|
30
|
-
)
|
25
|
+
sig { returns(Interface::HoverClientCapabilities) }
|
26
|
+
def provider
|
27
|
+
Interface::HoverClientCapabilities.new(dynamic_registration: false)
|
28
|
+
end
|
29
|
+
end
|
31
30
|
|
32
|
-
|
33
|
-
attr_reader :_response
|
31
|
+
ResponseType = type_member { { fixed: T.nilable(Interface::Hover) } }
|
34
32
|
|
35
33
|
sig do
|
36
34
|
params(
|
35
|
+
document: Document,
|
37
36
|
index: RubyIndexer::Index,
|
38
|
-
|
37
|
+
position: T::Hash[Symbol, T.untyped],
|
39
38
|
dispatcher: Prism::Dispatcher,
|
39
|
+
typechecker_enabled: T::Boolean,
|
40
40
|
).void
|
41
41
|
end
|
42
|
-
def initialize(index,
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
super(dispatcher)
|
48
|
-
dispatcher.register(
|
49
|
-
self,
|
50
|
-
:on_constant_read_node_enter,
|
51
|
-
:on_constant_write_node_enter,
|
52
|
-
:on_constant_path_node_enter,
|
53
|
-
:on_call_node_enter,
|
42
|
+
def initialize(document, index, position, dispatcher, typechecker_enabled)
|
43
|
+
super()
|
44
|
+
target, parent, nesting = document.locate_node(
|
45
|
+
position,
|
46
|
+
node_types: Listeners::Hover::ALLOWED_TARGETS,
|
54
47
|
)
|
55
|
-
end
|
56
48
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
# Merges responses from other hover listeners
|
63
|
-
sig { override.params(other: Listener[ResponseType]).returns(T.self_type) }
|
64
|
-
def merge_response!(other)
|
65
|
-
other_response = other.response
|
66
|
-
return self unless other_response
|
67
|
-
|
68
|
-
if @_response.nil?
|
69
|
-
@_response = other.response
|
70
|
-
else
|
71
|
-
@_response.contents.value << "\n\n" << other_response.contents.value
|
49
|
+
if (Listeners::Hover::ALLOWED_TARGETS.include?(parent.class) &&
|
50
|
+
!Listeners::Hover::ALLOWED_TARGETS.include?(target.class)) ||
|
51
|
+
(parent.is_a?(Prism::ConstantPathNode) && target.is_a?(Prism::ConstantReadNode))
|
52
|
+
target = parent
|
72
53
|
end
|
73
54
|
|
74
|
-
|
75
|
-
end
|
76
|
-
|
77
|
-
sig { params(node: Prism::ConstantReadNode).void }
|
78
|
-
def on_constant_read_node_enter(node)
|
79
|
-
return if DependencyDetector.instance.typechecker
|
80
|
-
|
81
|
-
generate_hover(node.slice, node.location)
|
82
|
-
end
|
55
|
+
@listeners = T.let([], T::Array[Listener[ResponseType]])
|
83
56
|
|
84
|
-
|
85
|
-
|
86
|
-
return if DependencyDetector.instance.typechecker
|
57
|
+
# Don't need to instantiate any listeners if there's no target
|
58
|
+
return unless target
|
87
59
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
60
|
+
uri = document.uri
|
61
|
+
@listeners = T.let(
|
62
|
+
[Listeners::Hover.new(uri, nesting, index, dispatcher, typechecker_enabled)],
|
63
|
+
T::Array[Listener[ResponseType]],
|
64
|
+
)
|
65
|
+
Addon.addons.each do |addon|
|
66
|
+
addon_listener = addon.create_hover_listener(nesting, index, dispatcher)
|
67
|
+
@listeners << addon_listener if addon_listener
|
68
|
+
end
|
94
69
|
|
95
|
-
|
70
|
+
@target = T.let(target, Prism::Node)
|
71
|
+
@dispatcher = dispatcher
|
96
72
|
end
|
97
73
|
|
98
|
-
sig {
|
99
|
-
def
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
message = node.message
|
104
|
-
return unless message
|
105
|
-
|
106
|
-
target_method = @index.resolve_method(message, @nesting.join("::"))
|
107
|
-
return unless target_method
|
108
|
-
|
109
|
-
location = target_method.location
|
110
|
-
|
111
|
-
@_response = Interface::Hover.new(
|
112
|
-
range: range_from_location(location),
|
113
|
-
contents: markdown_from_index_entries(message, target_method),
|
114
|
-
)
|
115
|
-
end
|
74
|
+
sig { override.returns(ResponseType) }
|
75
|
+
def perform
|
76
|
+
@dispatcher.dispatch_once(@target)
|
77
|
+
responses = @listeners.map(&:response).compact
|
116
78
|
|
117
|
-
|
79
|
+
first_response, *other_responses = responses
|
118
80
|
|
119
|
-
|
120
|
-
def generate_hover(name, location)
|
121
|
-
entries = @index.resolve(name, @nesting)
|
122
|
-
return unless entries
|
81
|
+
return unless first_response
|
123
82
|
|
124
|
-
#
|
125
|
-
|
126
|
-
|
127
|
-
|
83
|
+
# TODO: other_responses should never be nil. Check Sorbet
|
84
|
+
T.must(other_responses).each do |other_response|
|
85
|
+
first_response.contents.value << "\n\n" << other_response.contents.value
|
86
|
+
end
|
128
87
|
|
129
|
-
|
130
|
-
range: range_from_location(location),
|
131
|
-
contents: markdown_from_index_entries(name, entries),
|
132
|
-
)
|
88
|
+
first_response
|
133
89
|
end
|
134
90
|
end
|
135
91
|
end
|
@@ -1,6 +1,8 @@
|
|
1
1
|
# typed: strict
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
+
require "ruby_lsp/listeners/inlay_hints"
|
5
|
+
|
4
6
|
module RubyLsp
|
5
7
|
module Requests
|
6
8
|
# 
|
@@ -36,77 +38,42 @@ module RubyLsp
|
|
36
38
|
# a: "hello",
|
37
39
|
# }
|
38
40
|
# ```
|
39
|
-
class InlayHints <
|
41
|
+
class InlayHints < Request
|
40
42
|
extend T::Sig
|
41
43
|
extend T::Generic
|
42
44
|
|
43
|
-
|
45
|
+
class << self
|
46
|
+
extend T::Sig
|
44
47
|
|
45
|
-
|
48
|
+
sig { returns(Interface::InlayHintOptions) }
|
49
|
+
def provider
|
50
|
+
Interface::InlayHintOptions.new(resolve_provider: false)
|
51
|
+
end
|
52
|
+
end
|
46
53
|
|
47
|
-
|
48
|
-
attr_reader :_response
|
54
|
+
ResponseType = type_member { { fixed: T::Array[Interface::InlayHint] } }
|
49
55
|
|
50
56
|
sig do
|
51
57
|
params(
|
52
|
-
|
58
|
+
document: Document,
|
59
|
+
range: T::Hash[Symbol, T.untyped],
|
53
60
|
hints_configuration: RequestConfig,
|
54
61
|
dispatcher: Prism::Dispatcher,
|
55
62
|
).void
|
56
63
|
end
|
57
|
-
def initialize(range, hints_configuration, dispatcher)
|
58
|
-
super(
|
59
|
-
|
60
|
-
|
61
|
-
@
|
62
|
-
|
63
|
-
|
64
|
-
dispatcher.register(self, :on_rescue_node_enter, :on_implicit_node_enter)
|
65
|
-
end
|
66
|
-
|
67
|
-
sig { params(node: Prism::RescueNode).void }
|
68
|
-
def on_rescue_node_enter(node)
|
69
|
-
return unless @hints_configuration.enabled?(:implicitRescue)
|
70
|
-
return unless node.exceptions.empty?
|
71
|
-
|
72
|
-
loc = node.location
|
73
|
-
return unless visible?(node, @range)
|
74
|
-
|
75
|
-
@_response << Interface::InlayHint.new(
|
76
|
-
position: { line: loc.start_line - 1, character: loc.start_column + RESCUE_STRING_LENGTH },
|
77
|
-
label: "StandardError",
|
78
|
-
padding_left: true,
|
79
|
-
tooltip: "StandardError is implied in a bare rescue",
|
64
|
+
def initialize(document, range, hints_configuration, dispatcher)
|
65
|
+
super()
|
66
|
+
start_line = range.dig(:start, :line)
|
67
|
+
end_line = range.dig(:end, :line)
|
68
|
+
@listener = T.let(
|
69
|
+
Listeners::InlayHints.new(start_line..end_line, hints_configuration, dispatcher),
|
70
|
+
Listener[ResponseType],
|
80
71
|
)
|
81
72
|
end
|
82
73
|
|
83
|
-
sig {
|
84
|
-
def
|
85
|
-
|
86
|
-
return unless visible?(node, @range)
|
87
|
-
|
88
|
-
node_value = node.value
|
89
|
-
loc = node.location
|
90
|
-
tooltip = ""
|
91
|
-
node_name = ""
|
92
|
-
case node_value
|
93
|
-
when Prism::CallNode
|
94
|
-
node_name = node_value.name
|
95
|
-
tooltip = "This is a method call. Method name: #{node_name}"
|
96
|
-
when Prism::ConstantReadNode
|
97
|
-
node_name = node_value.name
|
98
|
-
tooltip = "This is a constant: #{node_name}"
|
99
|
-
when Prism::LocalVariableReadNode
|
100
|
-
node_name = node_value.name
|
101
|
-
tooltip = "This is a local variable: #{node_name}"
|
102
|
-
end
|
103
|
-
|
104
|
-
@_response << Interface::InlayHint.new(
|
105
|
-
position: { line: loc.start_line - 1, character: loc.start_column + node_name.length + 1 },
|
106
|
-
label: node_name,
|
107
|
-
padding_left: true,
|
108
|
-
tooltip: tooltip,
|
109
|
-
)
|
74
|
+
sig { override.returns(ResponseType) }
|
75
|
+
def perform
|
76
|
+
@listener.response
|
110
77
|
end
|
111
78
|
end
|
112
79
|
end
|
@@ -15,9 +15,21 @@ module RubyLsp
|
|
15
15
|
# # <-- cursor ends up here
|
16
16
|
# end # <-- end is automatically added
|
17
17
|
# ```
|
18
|
-
class OnTypeFormatting <
|
18
|
+
class OnTypeFormatting < Request
|
19
19
|
extend T::Sig
|
20
20
|
|
21
|
+
class << self
|
22
|
+
extend T::Sig
|
23
|
+
|
24
|
+
sig { returns(Interface::DocumentOnTypeFormattingOptions) }
|
25
|
+
def provider
|
26
|
+
Interface::DocumentOnTypeFormattingOptions.new(
|
27
|
+
first_trigger_character: "{",
|
28
|
+
more_trigger_character: ["\n", "|", "d"],
|
29
|
+
)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
21
33
|
END_REGEXES = T.let(
|
22
34
|
[
|
23
35
|
/\b(if|unless|for|while|class|module|until|def|case)\b.*/,
|
@@ -28,8 +40,8 @@ module RubyLsp
|
|
28
40
|
|
29
41
|
sig { params(document: Document, position: T::Hash[Symbol, T.untyped], trigger_character: String).void }
|
30
42
|
def initialize(document, position, trigger_character)
|
31
|
-
super(
|
32
|
-
|
43
|
+
super()
|
44
|
+
@document = document
|
33
45
|
@lines = T.let(@document.source.lines, T::Array[String])
|
34
46
|
line = @lines[[position[:line] - 1, 0].max]
|
35
47
|
|
@@ -41,7 +53,7 @@ module RubyLsp
|
|
41
53
|
end
|
42
54
|
|
43
55
|
sig { override.returns(T.all(T::Array[Interface::TextEdit], Object)) }
|
44
|
-
def
|
56
|
+
def perform
|
45
57
|
case @trigger_character
|
46
58
|
when "{"
|
47
59
|
handle_curly_brace if @document.syntax_error?
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module RubyLsp
|
5
|
+
module Requests
|
6
|
+
# :nodoc:
|
7
|
+
class Request
|
8
|
+
extend T::Sig
|
9
|
+
extend T::Generic
|
10
|
+
|
11
|
+
abstract!
|
12
|
+
|
13
|
+
sig { abstract.returns(T.anything) }
|
14
|
+
def perform; end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -20,18 +20,19 @@ module RubyLsp
|
|
20
20
|
# puts "Hello, world!" # --> Cursor is on this line
|
21
21
|
# end
|
22
22
|
# ```
|
23
|
-
class SelectionRanges
|
23
|
+
class SelectionRanges < Request
|
24
24
|
extend T::Sig
|
25
25
|
include Support::Common
|
26
26
|
sig { params(document: Document).void }
|
27
27
|
def initialize(document)
|
28
|
+
super()
|
28
29
|
@document = document
|
29
30
|
@ranges = T.let([], T::Array[Support::SelectionRange])
|
30
31
|
@stack = T.let([], T::Array[Support::SelectionRange])
|
31
32
|
end
|
32
33
|
|
33
|
-
sig { returns(T.all(T::Array[Support::SelectionRange], Object)) }
|
34
|
-
def
|
34
|
+
sig { override.returns(T.all(T::Array[Support::SelectionRange], Object)) }
|
35
|
+
def perform
|
35
36
|
# [node, parent]
|
36
37
|
queue = [[@document.tree, nil]]
|
37
38
|
|