ruby-lsp 0.13.3 → 0.14.2
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 +6 -2
- data/VERSION +1 -1
- data/exe/ruby-lsp-doctor +2 -0
- 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 +10 -5
- data/lib/ruby_indexer/test/classes_and_modules_test.rb +9 -0
- data/lib/ruby_indexer/test/index_test.rb +54 -3
- data/lib/ruby_lsp/addon.rb +34 -17
- data/lib/ruby_lsp/check_docs.rb +8 -8
- data/lib/ruby_lsp/executor.rb +28 -10
- data/lib/ruby_lsp/internal.rb +8 -6
- data/lib/ruby_lsp/listeners/code_lens.rb +54 -55
- data/lib/ruby_lsp/listeners/completion.rb +22 -18
- data/lib/ruby_lsp/listeners/definition.rb +31 -29
- 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 +194 -55
- data/lib/ruby_lsp/listeners/folding_ranges.rb +19 -23
- data/lib/ruby_lsp/listeners/hover.rb +36 -34
- 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 +15 -14
- data/lib/ruby_lsp/requests/code_lens.rb +11 -19
- 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 +38 -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 +64 -23
- data/lib/ruby_lsp/store.rb +4 -4
- metadata +17 -11
- data/lib/ruby_lsp/listener.rb +0 -33
- data/lib/ruby_lsp/requests/support/semantic_token_encoder.rb +0 -73
@@ -2,13 +2,12 @@
|
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
require "shellwords"
|
5
|
-
require_relative "../listener"
|
6
5
|
|
7
6
|
module RubyLsp
|
8
7
|
module Listeners
|
9
|
-
class CodeLens
|
8
|
+
class CodeLens
|
10
9
|
extend T::Sig
|
11
|
-
|
10
|
+
include Requests::Support::Common
|
12
11
|
|
13
12
|
BASE_COMMAND = T.let(
|
14
13
|
begin
|
@@ -21,31 +20,25 @@ module RubyLsp
|
|
21
20
|
)
|
22
21
|
ACCESS_MODIFIERS = T.let([:public, :private, :protected], T::Array[Symbol])
|
23
22
|
SUPPORTED_TEST_LIBRARIES = T.let(["minitest", "test-unit"], T::Array[String])
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
sig { override.returns(ResponseType) }
|
28
|
-
attr_reader :_response
|
23
|
+
DESCRIBE_KEYWORD = T.let(:describe, Symbol)
|
24
|
+
IT_KEYWORD = T.let(:it, Symbol)
|
29
25
|
|
30
26
|
sig do
|
31
27
|
params(
|
28
|
+
response_builder: ResponseBuilders::CollectionResponseBuilder[Interface::CodeLens],
|
32
29
|
uri: URI::Generic,
|
33
|
-
lenses_configuration: RequestConfig,
|
34
30
|
dispatcher: Prism::Dispatcher,
|
35
31
|
).void
|
36
32
|
end
|
37
|
-
def initialize(
|
33
|
+
def initialize(response_builder, uri, dispatcher)
|
34
|
+
@response_builder = response_builder
|
38
35
|
@uri = T.let(uri, URI::Generic)
|
39
|
-
@_response = T.let([], ResponseType)
|
40
36
|
@path = T.let(uri.to_standardized_path, T.nilable(String))
|
41
37
|
# visibility_stack is a stack of [current_visibility, previous_visibility]
|
42
38
|
@visibility_stack = T.let([[:public, :public]], T::Array[T::Array[T.nilable(Symbol)]])
|
43
|
-
@
|
39
|
+
@group_stack = T.let([], T::Array[String])
|
44
40
|
@group_id = T.let(1, Integer)
|
45
41
|
@group_id_stack = T.let([], T::Array[Integer])
|
46
|
-
@lenses_configuration = lenses_configuration
|
47
|
-
|
48
|
-
super(dispatcher)
|
49
42
|
|
50
43
|
dispatcher.register(
|
51
44
|
self,
|
@@ -61,13 +54,13 @@ module RubyLsp
|
|
61
54
|
def on_class_node_enter(node)
|
62
55
|
@visibility_stack.push([:public, :public])
|
63
56
|
class_name = node.constant_path.slice
|
64
|
-
@
|
57
|
+
@group_stack.push(class_name)
|
65
58
|
|
66
59
|
if @path && class_name.end_with?("Test")
|
67
60
|
add_test_code_lens(
|
68
61
|
node,
|
69
62
|
name: class_name,
|
70
|
-
command: generate_test_command(
|
63
|
+
command: generate_test_command(group_name: class_name),
|
71
64
|
kind: :group,
|
72
65
|
)
|
73
66
|
end
|
@@ -79,13 +72,13 @@ module RubyLsp
|
|
79
72
|
sig { params(node: Prism::ClassNode).void }
|
80
73
|
def on_class_node_leave(node)
|
81
74
|
@visibility_stack.pop
|
82
|
-
@
|
75
|
+
@group_stack.pop
|
83
76
|
@group_id_stack.pop
|
84
77
|
end
|
85
78
|
|
86
79
|
sig { params(node: Prism::DefNode).void }
|
87
80
|
def on_def_node_enter(node)
|
88
|
-
class_name = @
|
81
|
+
class_name = @group_stack.last
|
89
82
|
return unless class_name&.end_with?("Test")
|
90
83
|
|
91
84
|
visibility, _ = @visibility_stack.last
|
@@ -95,7 +88,7 @@ module RubyLsp
|
|
95
88
|
add_test_code_lens(
|
96
89
|
node,
|
97
90
|
name: method_name,
|
98
|
-
command: generate_test_command(method_name: method_name,
|
91
|
+
command: generate_test_command(method_name: method_name, group_name: class_name),
|
99
92
|
kind: :example,
|
100
93
|
)
|
101
94
|
end
|
@@ -120,16 +113,15 @@ module RubyLsp
|
|
120
113
|
return
|
121
114
|
end
|
122
115
|
|
123
|
-
if
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
add_open_gem_remote_code_lens(node, remote)
|
116
|
+
if [DESCRIBE_KEYWORD, IT_KEYWORD].include?(name)
|
117
|
+
case name
|
118
|
+
when DESCRIBE_KEYWORD
|
119
|
+
add_spec_code_lens(node, kind: :group)
|
120
|
+
@group_id_stack.push(@group_id)
|
121
|
+
@group_id += 1
|
122
|
+
when IT_KEYWORD
|
123
|
+
add_spec_code_lens(node, kind: :example)
|
124
|
+
end
|
133
125
|
end
|
134
126
|
end
|
135
127
|
|
@@ -137,6 +129,9 @@ module RubyLsp
|
|
137
129
|
def on_call_node_leave(node)
|
138
130
|
_, prev_visibility = @visibility_stack.pop
|
139
131
|
@visibility_stack.push([prev_visibility, prev_visibility])
|
132
|
+
if node.name == DESCRIBE_KEYWORD
|
133
|
+
@group_id_stack.pop
|
134
|
+
end
|
140
135
|
end
|
141
136
|
|
142
137
|
private
|
@@ -161,7 +156,7 @@ module RubyLsp
|
|
161
156
|
grouping_data = { group_id: @group_id_stack.last, kind: kind }
|
162
157
|
grouping_data[:id] = @group_id if kind == :group
|
163
158
|
|
164
|
-
@
|
159
|
+
@response_builder << create_code_lens(
|
165
160
|
node,
|
166
161
|
title: "Run",
|
167
162
|
command_name: "rubyLsp.runTest",
|
@@ -169,7 +164,7 @@ module RubyLsp
|
|
169
164
|
data: { type: "test", **grouping_data },
|
170
165
|
)
|
171
166
|
|
172
|
-
@
|
167
|
+
@response_builder << create_code_lens(
|
173
168
|
node,
|
174
169
|
title: "Run In Terminal",
|
175
170
|
command_name: "rubyLsp.runTestInTerminal",
|
@@ -177,7 +172,7 @@ module RubyLsp
|
|
177
172
|
data: { type: "test_in_terminal", **grouping_data },
|
178
173
|
)
|
179
174
|
|
180
|
-
@
|
175
|
+
@response_builder << create_code_lens(
|
181
176
|
node,
|
182
177
|
title: "Debug",
|
183
178
|
command_name: "rubyLsp.debugTest",
|
@@ -186,29 +181,19 @@ module RubyLsp
|
|
186
181
|
)
|
187
182
|
end
|
188
183
|
|
189
|
-
sig { params(
|
190
|
-
def
|
191
|
-
spec = Gem::Specification.stubs.find { |gem| gem.name == gem_name.content }&.to_spec
|
192
|
-
return if spec.nil?
|
193
|
-
|
194
|
-
[spec.homepage, spec.metadata["source_code_uri"]].compact.find do |page|
|
195
|
-
page.start_with?("https://github.com", "https://gitlab.com")
|
196
|
-
end
|
197
|
-
end
|
198
|
-
|
199
|
-
sig { params(class_name: String, method_name: T.nilable(String)).returns(String) }
|
200
|
-
def generate_test_command(class_name:, method_name: nil)
|
184
|
+
sig { params(group_name: String, method_name: T.nilable(String)).returns(String) }
|
185
|
+
def generate_test_command(group_name:, method_name: nil)
|
201
186
|
command = BASE_COMMAND + T.must(@path)
|
202
187
|
|
203
188
|
case DependencyDetector.instance.detected_test_library
|
204
189
|
when "minitest"
|
205
190
|
command += if method_name
|
206
|
-
" --name " + "/#{Shellwords.escape(
|
191
|
+
" --name " + "/#{Shellwords.escape(group_name + "#" + method_name)}/"
|
207
192
|
else
|
208
|
-
" --name " + "/#{Shellwords.escape(
|
193
|
+
" --name " + "/#{Shellwords.escape(group_name)}/"
|
209
194
|
end
|
210
195
|
when "test-unit"
|
211
|
-
command += " --testcase " + "/#{Shellwords.escape(
|
196
|
+
command += " --testcase " + "/#{Shellwords.escape(group_name)}/"
|
212
197
|
|
213
198
|
if method_name
|
214
199
|
command += " --name " + Shellwords.escape(method_name)
|
@@ -218,14 +203,28 @@ module RubyLsp
|
|
218
203
|
command
|
219
204
|
end
|
220
205
|
|
221
|
-
sig { params(node: Prism::CallNode,
|
222
|
-
def
|
223
|
-
|
206
|
+
sig { params(node: Prism::CallNode, kind: Symbol).void }
|
207
|
+
def add_spec_code_lens(node, kind:)
|
208
|
+
arguments = node.arguments
|
209
|
+
return unless arguments
|
210
|
+
|
211
|
+
first_argument = arguments.arguments.first
|
212
|
+
return unless first_argument
|
213
|
+
|
214
|
+
name = case first_argument
|
215
|
+
when Prism::StringNode
|
216
|
+
first_argument.content
|
217
|
+
when Prism::ConstantReadNode
|
218
|
+
first_argument.full_name
|
219
|
+
end
|
220
|
+
|
221
|
+
return unless name
|
222
|
+
|
223
|
+
add_test_code_lens(
|
224
224
|
node,
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
data: { type: "link" },
|
225
|
+
name: name,
|
226
|
+
command: generate_test_command(group_name: name),
|
227
|
+
kind: kind,
|
229
228
|
)
|
230
229
|
end
|
231
230
|
end
|
@@ -3,26 +3,21 @@
|
|
3
3
|
|
4
4
|
module RubyLsp
|
5
5
|
module Listeners
|
6
|
-
class Completion
|
6
|
+
class Completion
|
7
7
|
extend T::Sig
|
8
|
-
|
9
|
-
|
10
|
-
ResponseType = type_member { { fixed: T::Array[Interface::CompletionItem] } }
|
11
|
-
|
12
|
-
sig { override.returns(ResponseType) }
|
13
|
-
attr_reader :_response
|
8
|
+
include Requests::Support::Common
|
14
9
|
|
15
10
|
sig do
|
16
11
|
params(
|
12
|
+
response_builder: ResponseBuilders::CollectionResponseBuilder[Interface::CompletionItem],
|
17
13
|
index: RubyIndexer::Index,
|
18
14
|
nesting: T::Array[String],
|
19
15
|
typechecker_enabled: T::Boolean,
|
20
16
|
dispatcher: Prism::Dispatcher,
|
21
17
|
).void
|
22
18
|
end
|
23
|
-
def initialize(index, nesting, typechecker_enabled, dispatcher)
|
24
|
-
|
25
|
-
@_response = T.let([], ResponseType)
|
19
|
+
def initialize(response_builder, index, nesting, typechecker_enabled, dispatcher)
|
20
|
+
@response_builder = response_builder
|
26
21
|
@index = index
|
27
22
|
@nesting = nesting
|
28
23
|
@typechecker_enabled = typechecker_enabled
|
@@ -39,7 +34,7 @@ module RubyLsp
|
|
39
34
|
sig { params(node: Prism::StringNode).void }
|
40
35
|
def on_string_node_enter(node)
|
41
36
|
@index.search_require_paths(node.content).map!(&:require_path).sort!.each do |path|
|
42
|
-
@
|
37
|
+
@response_builder << build_completion(T.must(path), node)
|
43
38
|
end
|
44
39
|
end
|
45
40
|
|
@@ -48,11 +43,13 @@ module RubyLsp
|
|
48
43
|
def on_constant_read_node_enter(node)
|
49
44
|
return if DependencyDetector.instance.typechecker
|
50
45
|
|
51
|
-
name = node
|
46
|
+
name = constant_name(node)
|
47
|
+
return if name.nil?
|
48
|
+
|
52
49
|
candidates = @index.prefix_search(name, @nesting)
|
53
50
|
candidates.each do |entries|
|
54
51
|
complete_name = T.must(entries.first).name
|
55
|
-
@
|
52
|
+
@response_builder << build_entry_completion(
|
56
53
|
complete_name,
|
57
54
|
name,
|
58
55
|
node,
|
@@ -67,7 +64,8 @@ module RubyLsp
|
|
67
64
|
def on_constant_path_node_enter(node)
|
68
65
|
return if DependencyDetector.instance.typechecker
|
69
66
|
|
70
|
-
name = node
|
67
|
+
name = constant_name(node)
|
68
|
+
return if name.nil?
|
71
69
|
|
72
70
|
top_level_reference = if name.start_with?("::")
|
73
71
|
name = name.delete_prefix("::")
|
@@ -96,7 +94,7 @@ module RubyLsp
|
|
96
94
|
|
97
95
|
full_name = aliased_namespace.empty? ? constant_name : "#{aliased_namespace}::#{constant_name}"
|
98
96
|
|
99
|
-
@
|
97
|
+
@response_builder << build_entry_completion(
|
100
98
|
full_name,
|
101
99
|
name,
|
102
100
|
node,
|
@@ -123,7 +121,7 @@ module RubyLsp
|
|
123
121
|
entry = entries.find { |e| e.is_a?(RubyIndexer::Entry::Member) && e.owner&.name == receiver.name }
|
124
122
|
next unless entry
|
125
123
|
|
126
|
-
@
|
124
|
+
@response_builder << build_method_completion(T.cast(entry, RubyIndexer::Entry::Member), node)
|
127
125
|
end
|
128
126
|
end
|
129
127
|
|
@@ -147,7 +145,10 @@ module RubyLsp
|
|
147
145
|
detail: "(#{entry.parameters.map(&:decorated_name).join(", ")})",
|
148
146
|
description: entry.file_name,
|
149
147
|
),
|
150
|
-
documentation:
|
148
|
+
documentation: Interface::MarkupContent.new(
|
149
|
+
kind: "markdown",
|
150
|
+
value: markdown_from_index_entries(name, entry),
|
151
|
+
),
|
151
152
|
)
|
152
153
|
end
|
153
154
|
|
@@ -240,7 +241,10 @@ module RubyLsp
|
|
240
241
|
label_details: Interface::CompletionItemLabelDetails.new(
|
241
242
|
description: entries.map(&:file_name).join(","),
|
242
243
|
),
|
243
|
-
documentation:
|
244
|
+
documentation: Interface::MarkupContent.new(
|
245
|
+
kind: "markdown",
|
246
|
+
value: markdown_from_index_entries(real_name, entries),
|
247
|
+
),
|
244
248
|
)
|
245
249
|
end
|
246
250
|
|
@@ -3,17 +3,13 @@
|
|
3
3
|
|
4
4
|
module RubyLsp
|
5
5
|
module Listeners
|
6
|
-
class Definition
|
6
|
+
class Definition
|
7
7
|
extend T::Sig
|
8
|
-
|
9
|
-
|
10
|
-
ResponseType = type_member { { fixed: T.nilable(T.any(T::Array[Interface::Location], Interface::Location)) } }
|
11
|
-
|
12
|
-
sig { override.returns(ResponseType) }
|
13
|
-
attr_reader :_response
|
8
|
+
include Requests::Support::Common
|
14
9
|
|
15
10
|
sig do
|
16
11
|
params(
|
12
|
+
response_builder: ResponseBuilders::CollectionResponseBuilder[Interface::Location],
|
17
13
|
uri: URI::Generic,
|
18
14
|
nesting: T::Array[String],
|
19
15
|
index: RubyIndexer::Index,
|
@@ -21,14 +17,12 @@ module RubyLsp
|
|
21
17
|
typechecker_enabled: T::Boolean,
|
22
18
|
).void
|
23
19
|
end
|
24
|
-
def initialize(uri, nesting, index, dispatcher, typechecker_enabled)
|
20
|
+
def initialize(response_builder, uri, nesting, index, dispatcher, typechecker_enabled) # rubocop:disable Metrics/ParameterLists
|
21
|
+
@response_builder = response_builder
|
25
22
|
@uri = uri
|
26
23
|
@nesting = nesting
|
27
24
|
@index = index
|
28
25
|
@typechecker_enabled = typechecker_enabled
|
29
|
-
@_response = T.let(nil, ResponseType)
|
30
|
-
|
31
|
-
super(dispatcher)
|
32
26
|
|
33
27
|
dispatcher.register(
|
34
28
|
self,
|
@@ -51,12 +45,18 @@ module RubyLsp
|
|
51
45
|
|
52
46
|
sig { params(node: Prism::ConstantPathNode).void }
|
53
47
|
def on_constant_path_node_enter(node)
|
54
|
-
|
48
|
+
name = constant_name(node)
|
49
|
+
return if name.nil?
|
50
|
+
|
51
|
+
find_in_index(name)
|
55
52
|
end
|
56
53
|
|
57
54
|
sig { params(node: Prism::ConstantReadNode).void }
|
58
55
|
def on_constant_read_node_enter(node)
|
59
|
-
|
56
|
+
name = constant_name(node)
|
57
|
+
return if name.nil?
|
58
|
+
|
59
|
+
find_in_index(name)
|
60
60
|
end
|
61
61
|
|
62
62
|
private
|
@@ -68,20 +68,22 @@ module RubyLsp
|
|
68
68
|
message = node.message
|
69
69
|
return unless message
|
70
70
|
|
71
|
-
|
72
|
-
return unless
|
71
|
+
methods = @index.resolve_method(message, @nesting.join("::"))
|
72
|
+
return unless methods
|
73
73
|
|
74
|
-
|
75
|
-
|
76
|
-
|
74
|
+
methods.each do |target_method|
|
75
|
+
location = target_method.location
|
76
|
+
file_path = target_method.file_path
|
77
|
+
next if @typechecker_enabled && not_in_dependencies?(file_path)
|
77
78
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
79
|
+
@response_builder << Interface::Location.new(
|
80
|
+
uri: URI::Generic.from_path(path: file_path).to_s,
|
81
|
+
range: Interface::Range.new(
|
82
|
+
start: Interface::Position.new(line: location.start_line - 1, character: location.start_column),
|
83
|
+
end: Interface::Position.new(line: location.end_line - 1, character: location.end_column),
|
84
|
+
),
|
85
|
+
)
|
86
|
+
end
|
85
87
|
end
|
86
88
|
|
87
89
|
sig { params(node: Prism::CallNode).void }
|
@@ -102,7 +104,7 @@ module RubyLsp
|
|
102
104
|
if entry
|
103
105
|
candidate = entry.full_path
|
104
106
|
|
105
|
-
@
|
107
|
+
@response_builder << Interface::Location.new(
|
106
108
|
uri: URI::Generic.from_path(path: candidate).to_s,
|
107
109
|
range: Interface::Range.new(
|
108
110
|
start: Interface::Position.new(line: 0, character: 0),
|
@@ -116,7 +118,7 @@ module RubyLsp
|
|
116
118
|
current_folder = path ? Pathname.new(CGI.unescape(path)).dirname : Dir.pwd
|
117
119
|
candidate = File.expand_path(File.join(current_folder, required_file))
|
118
120
|
|
119
|
-
@
|
121
|
+
@response_builder << Interface::Location.new(
|
120
122
|
uri: URI::Generic.from_path(path: candidate).to_s,
|
121
123
|
range: Interface::Range.new(
|
122
124
|
start: Interface::Position.new(line: 0, character: 0),
|
@@ -136,7 +138,7 @@ module RubyLsp
|
|
136
138
|
first_entry = T.must(entries.first)
|
137
139
|
return if first_entry.visibility == :private && first_entry.name != "#{@nesting.join("::")}::#{value}"
|
138
140
|
|
139
|
-
|
141
|
+
entries.each do |entry|
|
140
142
|
location = entry.location
|
141
143
|
# If the project has Sorbet, then we only want to handle go to definition for constants defined in gems, as an
|
142
144
|
# additional behavior on top of jumping to RBIs. Sorbet can already handle go to definition for all constants
|
@@ -144,7 +146,7 @@ module RubyLsp
|
|
144
146
|
file_path = entry.file_path
|
145
147
|
next if @typechecker_enabled && not_in_dependencies?(file_path)
|
146
148
|
|
147
|
-
Interface::Location.new(
|
149
|
+
@response_builder << Interface::Location.new(
|
148
150
|
uri: URI::Generic.from_path(path: file_path).to_s,
|
149
151
|
range: Interface::Range.new(
|
150
152
|
start: Interface::Position.new(line: location.start_line - 1, character: location.start_column),
|
@@ -3,10 +3,9 @@
|
|
3
3
|
|
4
4
|
module RubyLsp
|
5
5
|
module Listeners
|
6
|
-
class DocumentHighlight
|
6
|
+
class DocumentHighlight
|
7
7
|
extend T::Sig
|
8
|
-
|
9
|
-
ResponseType = type_member { { fixed: T::Array[Interface::DocumentHighlight] } }
|
8
|
+
include Requests::Support::Common
|
10
9
|
|
11
10
|
GLOBAL_VARIABLE_NODES = T.let(
|
12
11
|
[
|
@@ -87,20 +86,16 @@ module RubyLsp
|
|
87
86
|
T::Array[T.class_of(Prism::Node)],
|
88
87
|
)
|
89
88
|
|
90
|
-
sig { override.returns(ResponseType) }
|
91
|
-
attr_reader :_response
|
92
|
-
|
93
89
|
sig do
|
94
90
|
params(
|
91
|
+
response_builder: ResponseBuilders::CollectionResponseBuilder[Interface::DocumentHighlight],
|
95
92
|
target: T.nilable(Prism::Node),
|
96
93
|
parent: T.nilable(Prism::Node),
|
97
94
|
dispatcher: Prism::Dispatcher,
|
98
95
|
).void
|
99
96
|
end
|
100
|
-
def initialize(target, parent, dispatcher)
|
101
|
-
|
102
|
-
|
103
|
-
@_response = T.let([], T::Array[Interface::DocumentHighlight])
|
97
|
+
def initialize(response_builder, target, parent, dispatcher)
|
98
|
+
@response_builder = response_builder
|
104
99
|
|
105
100
|
return unless target && parent
|
106
101
|
|
@@ -521,7 +516,7 @@ module RubyLsp
|
|
521
516
|
|
522
517
|
sig { params(kind: Integer, location: Prism::Location).void }
|
523
518
|
def add_highlight(kind, location)
|
524
|
-
@
|
519
|
+
@response_builder << Interface::DocumentHighlight.new(range: range_from_location(location), kind: kind)
|
525
520
|
end
|
526
521
|
|
527
522
|
sig { params(node: T.nilable(Prism::Node)).returns(T.nilable(String)) }
|
@@ -5,11 +5,9 @@ require "ruby_lsp/requests/support/source_uri"
|
|
5
5
|
|
6
6
|
module RubyLsp
|
7
7
|
module Listeners
|
8
|
-
class DocumentLink
|
8
|
+
class DocumentLink
|
9
9
|
extend T::Sig
|
10
|
-
|
11
|
-
|
12
|
-
ResponseType = type_member { { fixed: T::Array[Interface::DocumentLink] } }
|
10
|
+
include Requests::Support::Common
|
13
11
|
|
14
12
|
GEM_TO_VERSION_MAP = T.let(
|
15
13
|
[*::Gem::Specification.default_stubs, *::Gem::Specification.stubs].map! do |s|
|
@@ -59,25 +57,21 @@ module RubyLsp
|
|
59
57
|
end
|
60
58
|
end
|
61
59
|
|
62
|
-
sig { override.returns(ResponseType) }
|
63
|
-
attr_reader :_response
|
64
|
-
|
65
60
|
sig do
|
66
61
|
params(
|
62
|
+
response_builder: ResponseBuilders::CollectionResponseBuilder[Interface::DocumentLink],
|
67
63
|
uri: URI::Generic,
|
68
64
|
comments: T::Array[Prism::Comment],
|
69
65
|
dispatcher: Prism::Dispatcher,
|
70
66
|
).void
|
71
67
|
end
|
72
|
-
def initialize(uri, comments, dispatcher)
|
73
|
-
super(dispatcher)
|
74
|
-
|
68
|
+
def initialize(response_builder, uri, comments, dispatcher)
|
75
69
|
# Match the version based on the version in the RBI file name. Notice that the `@` symbol is sanitized to `%40`
|
76
70
|
# in the URI
|
71
|
+
@response_builder = response_builder
|
77
72
|
path = uri.to_standardized_path
|
78
73
|
version_match = path ? /(?<=%40)[\d.]+(?=\.rbi$)/.match(path) : nil
|
79
74
|
@gem_version = T.let(version_match && version_match[0], T.nilable(String))
|
80
|
-
@_response = T.let([], T::Array[Interface::DocumentLink])
|
81
75
|
@lines_to_comments = T.let(
|
82
76
|
comments.to_h do |comment|
|
83
77
|
[comment.location.end_line, comment]
|
@@ -137,7 +131,7 @@ module RubyLsp
|
|
137
131
|
file_path = self.class.gem_paths.dig(uri.gem_name, gem_version, CGI.unescape(uri.path))
|
138
132
|
return if file_path.nil?
|
139
133
|
|
140
|
-
@
|
134
|
+
@response_builder << Interface::DocumentLink.new(
|
141
135
|
range: range_from_location(comment.location),
|
142
136
|
target: "file://#{file_path}##{uri.line_number}",
|
143
137
|
tooltip: "Jump to #{file_path}##{uri.line_number}",
|