ruby-lsp 0.13.3 → 0.14.0
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 +3 -2
- data/VERSION +1 -1
- data/lib/rubocop/cop/ruby_lsp/use_register_with_handler_method.rb +4 -8
- data/lib/ruby_indexer/lib/ruby_indexer/collector.rb +5 -1
- data/lib/ruby_indexer/lib/ruby_indexer/configuration.rb +4 -2
- data/lib/ruby_indexer/lib/ruby_indexer/index.rb +8 -3
- data/lib/ruby_indexer/test/classes_and_modules_test.rb +9 -0
- data/lib/ruby_indexer/test/index_test.rb +27 -0
- data/lib/ruby_lsp/addon.rb +21 -10
- data/lib/ruby_lsp/check_docs.rb +8 -8
- data/lib/ruby_lsp/executor.rb +28 -10
- data/lib/ruby_lsp/internal.rb +1 -1
- data/lib/ruby_lsp/listeners/code_lens.rb +54 -55
- data/lib/ruby_lsp/listeners/completion.rb +17 -16
- data/lib/ruby_lsp/listeners/definition.rb +10 -16
- data/lib/ruby_lsp/listeners/document_highlight.rb +6 -11
- data/lib/ruby_lsp/listeners/document_link.rb +6 -12
- data/lib/ruby_lsp/listeners/document_symbol.rb +95 -55
- data/lib/ruby_lsp/listeners/folding_ranges.rb +19 -23
- data/lib/ruby_lsp/listeners/hover.rb +26 -30
- data/lib/ruby_lsp/listeners/inlay_hints.rb +7 -13
- data/lib/ruby_lsp/listeners/semantic_highlighting.rb +54 -124
- data/lib/ruby_lsp/listeners/signature_help.rb +11 -13
- data/lib/ruby_lsp/requests/code_lens.rb +9 -17
- data/lib/ruby_lsp/requests/completion.rb +7 -9
- data/lib/ruby_lsp/requests/definition.rb +10 -22
- data/lib/ruby_lsp/requests/document_highlight.rb +7 -5
- data/lib/ruby_lsp/requests/document_link.rb +7 -6
- data/lib/ruby_lsp/requests/document_symbol.rb +5 -11
- data/lib/ruby_lsp/requests/folding_ranges.rb +11 -6
- data/lib/ruby_lsp/requests/hover.rb +18 -24
- data/lib/ruby_lsp/requests/inlay_hints.rb +7 -8
- data/lib/ruby_lsp/requests/on_type_formatting.rb +12 -2
- data/lib/ruby_lsp/requests/semantic_highlighting.rb +10 -8
- data/lib/ruby_lsp/requests/signature_help.rb +53 -18
- data/lib/ruby_lsp/requests/support/common.rb +23 -10
- data/lib/ruby_lsp/requests/support/dependency_detector.rb +5 -1
- data/lib/ruby_lsp/requests.rb +0 -1
- data/lib/ruby_lsp/response_builders/collection_response_builder.rb +29 -0
- data/lib/ruby_lsp/response_builders/document_symbol.rb +57 -0
- data/lib/ruby_lsp/response_builders/hover.rb +49 -0
- data/lib/ruby_lsp/response_builders/response_builder.rb +16 -0
- data/lib/ruby_lsp/response_builders/semantic_highlighting.rb +199 -0
- data/lib/ruby_lsp/response_builders/signature_help.rb +28 -0
- data/lib/ruby_lsp/response_builders.rb +13 -0
- data/lib/ruby_lsp/server.rb +3 -3
- data/lib/ruby_lsp/setup_bundler.rb +30 -5
- data/lib/ruby_lsp/store.rb +4 -4
- metadata +14 -9
- data/lib/ruby_lsp/listener.rb +0 -33
- data/lib/ruby_lsp/requests/support/semantic_token_encoder.rb +0 -73
@@ -3,39 +3,20 @@
|
|
3
3
|
|
4
4
|
module RubyLsp
|
5
5
|
module Listeners
|
6
|
-
class DocumentSymbol
|
6
|
+
class DocumentSymbol
|
7
7
|
extend T::Sig
|
8
|
-
|
9
|
-
|
10
|
-
ResponseType = type_member { { fixed: T::Array[Interface::DocumentSymbol] } }
|
8
|
+
include Requests::Support::Common
|
11
9
|
|
12
10
|
ATTR_ACCESSORS = T.let([:attr_reader, :attr_writer, :attr_accessor].freeze, T::Array[Symbol])
|
13
11
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
sig { void }
|
21
|
-
def initialize
|
22
|
-
@children = T.let([], T::Array[Interface::DocumentSymbol])
|
23
|
-
end
|
12
|
+
sig do
|
13
|
+
params(
|
14
|
+
response_builder: ResponseBuilders::DocumentSymbol,
|
15
|
+
dispatcher: Prism::Dispatcher,
|
16
|
+
).void
|
24
17
|
end
|
25
|
-
|
26
|
-
|
27
|
-
attr_reader :_response
|
28
|
-
|
29
|
-
sig { params(dispatcher: Prism::Dispatcher).void }
|
30
|
-
def initialize(dispatcher)
|
31
|
-
@root = T.let(SymbolHierarchyRoot.new, SymbolHierarchyRoot)
|
32
|
-
@_response = T.let(@root.children, T::Array[Interface::DocumentSymbol])
|
33
|
-
@stack = T.let(
|
34
|
-
[@root],
|
35
|
-
T::Array[T.any(SymbolHierarchyRoot, Interface::DocumentSymbol)],
|
36
|
-
)
|
37
|
-
|
38
|
-
super
|
18
|
+
def initialize(response_builder, dispatcher)
|
19
|
+
@response_builder = response_builder
|
39
20
|
|
40
21
|
dispatcher.register(
|
41
22
|
self,
|
@@ -52,12 +33,13 @@ module RubyLsp
|
|
52
33
|
:on_class_variable_write_node_enter,
|
53
34
|
:on_singleton_class_node_enter,
|
54
35
|
:on_singleton_class_node_leave,
|
36
|
+
:on_alias_method_node_enter,
|
55
37
|
)
|
56
38
|
end
|
57
39
|
|
58
40
|
sig { params(node: Prism::ClassNode).void }
|
59
41
|
def on_class_node_enter(node)
|
60
|
-
@
|
42
|
+
@response_builder << create_document_symbol(
|
61
43
|
name: node.constant_path.location.slice,
|
62
44
|
kind: Constant::SymbolKind::CLASS,
|
63
45
|
range_location: node.location,
|
@@ -67,14 +49,14 @@ module RubyLsp
|
|
67
49
|
|
68
50
|
sig { params(node: Prism::ClassNode).void }
|
69
51
|
def on_class_node_leave(node)
|
70
|
-
@
|
52
|
+
@response_builder.pop
|
71
53
|
end
|
72
54
|
|
73
55
|
sig { params(node: Prism::SingletonClassNode).void }
|
74
56
|
def on_singleton_class_node_enter(node)
|
75
57
|
expression = node.expression
|
76
58
|
|
77
|
-
@
|
59
|
+
@response_builder << create_document_symbol(
|
78
60
|
name: "<< #{expression.slice}",
|
79
61
|
kind: Constant::SymbolKind::NAMESPACE,
|
80
62
|
range_location: node.location,
|
@@ -84,28 +66,15 @@ module RubyLsp
|
|
84
66
|
|
85
67
|
sig { params(node: Prism::SingletonClassNode).void }
|
86
68
|
def on_singleton_class_node_leave(node)
|
87
|
-
@
|
69
|
+
@response_builder.pop
|
88
70
|
end
|
89
71
|
|
90
72
|
sig { params(node: Prism::CallNode).void }
|
91
73
|
def on_call_node_enter(node)
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
arguments.arguments.each do |argument|
|
98
|
-
next unless argument.is_a?(Prism::SymbolNode)
|
99
|
-
|
100
|
-
name = argument.value
|
101
|
-
next unless name
|
102
|
-
|
103
|
-
create_document_symbol(
|
104
|
-
name: name,
|
105
|
-
kind: Constant::SymbolKind::FIELD,
|
106
|
-
range_location: argument.location,
|
107
|
-
selection_range_location: T.must(argument.value_loc),
|
108
|
-
)
|
74
|
+
if ATTR_ACCESSORS.include?(node.name)
|
75
|
+
handle_attr_accessor(node)
|
76
|
+
elsif node.name == :alias_method
|
77
|
+
handle_alias_method(node)
|
109
78
|
end
|
110
79
|
end
|
111
80
|
|
@@ -131,12 +100,12 @@ module RubyLsp
|
|
131
100
|
|
132
101
|
sig { params(node: Prism::DefNode).void }
|
133
102
|
def on_def_node_leave(node)
|
134
|
-
@
|
103
|
+
@response_builder.pop
|
135
104
|
end
|
136
105
|
|
137
106
|
sig { params(node: Prism::ModuleNode).void }
|
138
107
|
def on_module_node_enter(node)
|
139
|
-
@
|
108
|
+
@response_builder << create_document_symbol(
|
140
109
|
name: node.constant_path.location.slice,
|
141
110
|
kind: Constant::SymbolKind::MODULE,
|
142
111
|
range_location: node.location,
|
@@ -147,7 +116,7 @@ module RubyLsp
|
|
147
116
|
sig { params(node: Prism::DefNode).void }
|
148
117
|
def on_def_node_enter(node)
|
149
118
|
receiver = node.receiver
|
150
|
-
previous_symbol = @
|
119
|
+
previous_symbol = @response_builder.last
|
151
120
|
|
152
121
|
if receiver.is_a?(Prism::SelfNode)
|
153
122
|
name = "self.#{node.name}"
|
@@ -167,12 +136,12 @@ module RubyLsp
|
|
167
136
|
selection_range_location: node.name_loc,
|
168
137
|
)
|
169
138
|
|
170
|
-
@
|
139
|
+
@response_builder << symbol
|
171
140
|
end
|
172
141
|
|
173
142
|
sig { params(node: Prism::ModuleNode).void }
|
174
143
|
def on_module_node_leave(node)
|
175
|
-
@
|
144
|
+
@response_builder.pop
|
176
145
|
end
|
177
146
|
|
178
147
|
sig { params(node: Prism::InstanceVariableWriteNode).void }
|
@@ -195,6 +164,22 @@ module RubyLsp
|
|
195
164
|
)
|
196
165
|
end
|
197
166
|
|
167
|
+
sig { params(node: Prism::AliasMethodNode).void }
|
168
|
+
def on_alias_method_node_enter(node)
|
169
|
+
new_name_node = node.new_name
|
170
|
+
return unless new_name_node.is_a?(Prism::SymbolNode)
|
171
|
+
|
172
|
+
name = new_name_node.value
|
173
|
+
return unless name
|
174
|
+
|
175
|
+
create_document_symbol(
|
176
|
+
name: name,
|
177
|
+
kind: Constant::SymbolKind::METHOD,
|
178
|
+
range_location: new_name_node.location,
|
179
|
+
selection_range_location: T.must(new_name_node.value_loc),
|
180
|
+
)
|
181
|
+
end
|
182
|
+
|
198
183
|
private
|
199
184
|
|
200
185
|
sig do
|
@@ -214,10 +199,65 @@ module RubyLsp
|
|
214
199
|
children: [],
|
215
200
|
)
|
216
201
|
|
217
|
-
|
202
|
+
@response_builder.last.children << symbol
|
218
203
|
|
219
204
|
symbol
|
220
205
|
end
|
206
|
+
|
207
|
+
sig { params(node: Prism::CallNode).void }
|
208
|
+
def handle_attr_accessor(node)
|
209
|
+
return unless node.receiver.nil?
|
210
|
+
|
211
|
+
arguments = node.arguments
|
212
|
+
return unless arguments
|
213
|
+
|
214
|
+
arguments.arguments.each do |argument|
|
215
|
+
next unless argument.is_a?(Prism::SymbolNode)
|
216
|
+
|
217
|
+
name = argument.value
|
218
|
+
next unless name
|
219
|
+
|
220
|
+
create_document_symbol(
|
221
|
+
name: name,
|
222
|
+
kind: Constant::SymbolKind::FIELD,
|
223
|
+
range_location: argument.location,
|
224
|
+
selection_range_location: T.must(argument.value_loc),
|
225
|
+
)
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
sig { params(node: Prism::CallNode).void }
|
230
|
+
def handle_alias_method(node)
|
231
|
+
receiver = node.receiver
|
232
|
+
return if receiver && !receiver.is_a?(Prism::SelfNode)
|
233
|
+
|
234
|
+
arguments = node.arguments
|
235
|
+
return unless arguments
|
236
|
+
|
237
|
+
new_name_argument = arguments.arguments.first
|
238
|
+
|
239
|
+
if new_name_argument.is_a?(Prism::SymbolNode)
|
240
|
+
name = new_name_argument.value
|
241
|
+
return unless name
|
242
|
+
|
243
|
+
create_document_symbol(
|
244
|
+
name: name,
|
245
|
+
kind: Constant::SymbolKind::METHOD,
|
246
|
+
range_location: new_name_argument.location,
|
247
|
+
selection_range_location: T.must(new_name_argument.value_loc),
|
248
|
+
)
|
249
|
+
elsif new_name_argument.is_a?(Prism::StringNode)
|
250
|
+
name = new_name_argument.content
|
251
|
+
return if name.empty?
|
252
|
+
|
253
|
+
create_document_symbol(
|
254
|
+
name: name,
|
255
|
+
kind: Constant::SymbolKind::METHOD,
|
256
|
+
range_location: new_name_argument.location,
|
257
|
+
selection_range_location: new_name_argument.content_loc,
|
258
|
+
)
|
259
|
+
end
|
260
|
+
end
|
221
261
|
end
|
222
262
|
end
|
223
263
|
end
|
@@ -3,19 +3,20 @@
|
|
3
3
|
|
4
4
|
module RubyLsp
|
5
5
|
module Listeners
|
6
|
-
class FoldingRanges
|
6
|
+
class FoldingRanges
|
7
7
|
extend T::Sig
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
8
|
+
include Requests::Support::Common
|
9
|
+
|
10
|
+
sig do
|
11
|
+
params(
|
12
|
+
response_builder: ResponseBuilders::CollectionResponseBuilder[Interface::FoldingRange],
|
13
|
+
comments: T::Array[Prism::Comment],
|
14
|
+
dispatcher: Prism::Dispatcher,
|
15
|
+
).void
|
16
|
+
end
|
17
|
+
def initialize(response_builder, comments, dispatcher)
|
18
|
+
@response_builder = response_builder
|
17
19
|
@requires = T.let([], T::Array[Prism::CallNode])
|
18
|
-
@finalized_response = T.let(false, T::Boolean)
|
19
20
|
@comments = comments
|
20
21
|
|
21
22
|
dispatcher.register(
|
@@ -46,15 +47,10 @@ module RubyLsp
|
|
46
47
|
)
|
47
48
|
end
|
48
49
|
|
49
|
-
sig {
|
50
|
-
def
|
51
|
-
|
52
|
-
|
53
|
-
emit_requires_range
|
54
|
-
@finalized_response = true
|
55
|
-
end
|
56
|
-
|
57
|
-
@_response
|
50
|
+
sig { void }
|
51
|
+
def finalize_response!
|
52
|
+
push_comment_ranges
|
53
|
+
emit_requires_range
|
58
54
|
end
|
59
55
|
|
60
56
|
sig { params(node: Prism::IfNode).void }
|
@@ -203,7 +199,7 @@ module RubyLsp
|
|
203
199
|
end.each do |chunk|
|
204
200
|
next if chunk.length == 1
|
205
201
|
|
206
|
-
@
|
202
|
+
@response_builder << Interface::FoldingRange.new(
|
207
203
|
start_line: T.must(chunk.first).location.start_line - 1,
|
208
204
|
end_line: T.must(chunk.last).location.end_line - 1,
|
209
205
|
kind: "comment",
|
@@ -214,7 +210,7 @@ module RubyLsp
|
|
214
210
|
sig { void }
|
215
211
|
def emit_requires_range
|
216
212
|
if @requires.length > 1
|
217
|
-
@
|
213
|
+
@response_builder << Interface::FoldingRange.new(
|
218
214
|
start_line: T.must(@requires.first).location.start_line - 1,
|
219
215
|
end_line: T.must(@requires.last).location.end_line - 1,
|
220
216
|
kind: "imports",
|
@@ -260,7 +256,7 @@ module RubyLsp
|
|
260
256
|
emit_requires_range
|
261
257
|
return if start_line >= end_line
|
262
258
|
|
263
|
-
@
|
259
|
+
@response_builder << Interface::FoldingRange.new(
|
264
260
|
start_line: start_line - 1,
|
265
261
|
end_line: end_line - 1,
|
266
262
|
kind: "region",
|
@@ -3,11 +3,9 @@
|
|
3
3
|
|
4
4
|
module RubyLsp
|
5
5
|
module Listeners
|
6
|
-
class Hover
|
6
|
+
class Hover
|
7
7
|
extend T::Sig
|
8
|
-
|
9
|
-
|
10
|
-
ResponseType = type_member { { fixed: T.nilable(Interface::Hover) } }
|
8
|
+
include Requests::Support::Common
|
11
9
|
|
12
10
|
ALLOWED_TARGETS = T.let(
|
13
11
|
[
|
@@ -19,11 +17,17 @@ module RubyLsp
|
|
19
17
|
T::Array[T.class_of(Prism::Node)],
|
20
18
|
)
|
21
19
|
|
22
|
-
|
23
|
-
|
20
|
+
ALLOWED_REMOTE_PROVIDERS = T.let(
|
21
|
+
[
|
22
|
+
"https://github.com",
|
23
|
+
"https://gitlab.com",
|
24
|
+
].freeze,
|
25
|
+
T::Array[String],
|
26
|
+
)
|
24
27
|
|
25
28
|
sig do
|
26
29
|
params(
|
30
|
+
response_builder: ResponseBuilders::Hover,
|
27
31
|
uri: URI::Generic,
|
28
32
|
nesting: T::Array[String],
|
29
33
|
index: RubyIndexer::Index,
|
@@ -31,14 +35,13 @@ module RubyLsp
|
|
31
35
|
typechecker_enabled: T::Boolean,
|
32
36
|
).void
|
33
37
|
end
|
34
|
-
def initialize(uri, nesting, index, dispatcher, typechecker_enabled)
|
38
|
+
def initialize(response_builder, uri, nesting, index, dispatcher, typechecker_enabled) # rubocop:disable Metrics/ParameterLists
|
39
|
+
@response_builder = response_builder
|
35
40
|
@path = T.let(uri.to_standardized_path, T.nilable(String))
|
36
41
|
@nesting = nesting
|
37
42
|
@index = index
|
38
43
|
@typechecker_enabled = typechecker_enabled
|
39
|
-
@_response = T.let(nil, ResponseType)
|
40
44
|
|
41
|
-
super(dispatcher)
|
42
45
|
dispatcher.register(
|
43
46
|
self,
|
44
47
|
:on_constant_read_node_enter,
|
@@ -86,12 +89,9 @@ module RubyLsp
|
|
86
89
|
target_method = @index.resolve_method(message, @nesting.join("::"))
|
87
90
|
return unless target_method
|
88
91
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
range: range_from_location(location),
|
93
|
-
contents: markdown_from_index_entries(message, target_method),
|
94
|
-
)
|
92
|
+
categorized_markdown_from_index_entries(message, target_method).each do |category, content|
|
93
|
+
@response_builder.push(content, category: category)
|
94
|
+
end
|
95
95
|
end
|
96
96
|
|
97
97
|
private
|
@@ -106,10 +106,9 @@ module RubyLsp
|
|
106
106
|
first_entry = T.must(entries.first)
|
107
107
|
return if first_entry.visibility == :private && first_entry.name != "#{@nesting.join("::")}::#{name}"
|
108
108
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
)
|
109
|
+
categorized_markdown_from_index_entries(name, entries).each do |category, content|
|
110
|
+
@response_builder.push(content, category: category)
|
111
|
+
end
|
113
112
|
end
|
114
113
|
|
115
114
|
sig { params(node: Prism::CallNode).void }
|
@@ -132,18 +131,15 @@ module RubyLsp
|
|
132
131
|
# Remove leading whitespace if a heredoc was used for the summary or description
|
133
132
|
info = info.gsub(/^ +/, "")
|
134
133
|
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
contents: Interface::MarkupContent.new(
|
143
|
-
kind: Constant::MarkupKind::MARKDOWN,
|
144
|
-
value: markdown,
|
145
|
-
),
|
134
|
+
remote_url = [spec.homepage, spec.metadata["source_code_uri"]].compact.find do |page|
|
135
|
+
page.start_with?(*ALLOWED_REMOTE_PROVIDERS)
|
136
|
+
end
|
137
|
+
|
138
|
+
@response_builder.push(
|
139
|
+
"**#{spec.name}** (#{spec.version}) #{remote_url && " - [open remote](#{remote_url})"}",
|
140
|
+
category: :title,
|
146
141
|
)
|
142
|
+
@response_builder.push(info, category: :documentation)
|
147
143
|
rescue Gem::MissingSpecError
|
148
144
|
# Do nothing if the spec cannot be found
|
149
145
|
end
|
@@ -3,28 +3,22 @@
|
|
3
3
|
|
4
4
|
module RubyLsp
|
5
5
|
module Listeners
|
6
|
-
class InlayHints
|
6
|
+
class InlayHints
|
7
7
|
extend T::Sig
|
8
|
-
|
9
|
-
|
10
|
-
ResponseType = type_member { { fixed: T::Array[Interface::InlayHint] } }
|
8
|
+
include Requests::Support::Common
|
11
9
|
|
12
10
|
RESCUE_STRING_LENGTH = T.let("rescue".length, Integer)
|
13
11
|
|
14
|
-
sig { override.returns(ResponseType) }
|
15
|
-
attr_reader :_response
|
16
|
-
|
17
12
|
sig do
|
18
13
|
params(
|
14
|
+
response_builder: ResponseBuilders::CollectionResponseBuilder[Interface::InlayHint],
|
19
15
|
range: T::Range[Integer],
|
20
16
|
hints_configuration: RequestConfig,
|
21
17
|
dispatcher: Prism::Dispatcher,
|
22
18
|
).void
|
23
19
|
end
|
24
|
-
def initialize(range, hints_configuration, dispatcher)
|
25
|
-
|
26
|
-
|
27
|
-
@_response = T.let([], ResponseType)
|
20
|
+
def initialize(response_builder, range, hints_configuration, dispatcher)
|
21
|
+
@response_builder = response_builder
|
28
22
|
@range = range
|
29
23
|
@hints_configuration = hints_configuration
|
30
24
|
|
@@ -39,7 +33,7 @@ module RubyLsp
|
|
39
33
|
loc = node.location
|
40
34
|
return unless visible?(node, @range)
|
41
35
|
|
42
|
-
@
|
36
|
+
@response_builder << Interface::InlayHint.new(
|
43
37
|
position: { line: loc.start_line - 1, character: loc.start_column + RESCUE_STRING_LENGTH },
|
44
38
|
label: "StandardError",
|
45
39
|
padding_left: true,
|
@@ -68,7 +62,7 @@ module RubyLsp
|
|
68
62
|
tooltip = "This is a local variable: #{node_name}"
|
69
63
|
end
|
70
64
|
|
71
|
-
@
|
65
|
+
@response_builder << Interface::InlayHint.new(
|
72
66
|
position: { line: loc.start_line - 1, character: loc.start_column + node_name.length + 1 },
|
73
67
|
label: node_name,
|
74
68
|
padding_left: true,
|