ruby-lsp 0.13.1 → 0.13.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +30 -0
- data/VERSION +1 -1
- data/lib/ruby_indexer/lib/ruby_indexer/configuration.rb +1 -1
- data/lib/ruby_indexer/lib/ruby_indexer/entry.rb +30 -1
- data/lib/ruby_lsp/check_docs.rb +3 -3
- data/lib/ruby_lsp/document.rb +15 -7
- data/lib/ruby_lsp/executor.rb +85 -226
- 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 +5 -5
- data/lib/ruby_lsp/requests/code_actions.rb +15 -6
- data/lib/ruby_lsp/requests/code_lens.rb +21 -221
- data/lib/ruby_lsp/requests/completion.rb +64 -246
- 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 +18 -6
- 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 +5 -5
- data/lib/ruby_lsp/requests/signature_help.rb +87 -0
- 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/selection_range.rb +1 -1
- 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 +3 -1
- data/lib/ruby_lsp/store.rb +1 -1
- data/lib/ruby_lsp/utils.rb +8 -0
- metadata +20 -8
- data/lib/ruby_lsp/requests/base_request.rb +0 -24
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 28e657dce7a85c270d1c647a158fd1a1c5f81dca211844defd817070fd264126
|
4
|
+
data.tar.gz: f129245dd0e632916573c0b9dcf04bfaa2c7b942b39aaa6aa1618dd70f13e69e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3ab4afce37f672fd0d3c3ecc54c7b30247f893fc4b7b4f10549e13db4ab181c67a9b84da37dea9fbdd195e8d87ca2f2f794cbcce300c68b4709ee0ae3b3171b2
|
7
|
+
data.tar.gz: ffdb3a1bdb2d5c4172f74c934da896bd6c19f09158effa137afd0443e79b8c2dfd392989997d5745616db58e1286191a9e35570bd69024779137e7aaf15bb987
|
data/README.md
CHANGED
@@ -46,6 +46,36 @@ See the [documentation](https://shopify.github.io/ruby-lsp) for more in-depth de
|
|
46
46
|
For creating rich themes for Ruby using the semantic highlighting information, see the [semantic highlighting
|
47
47
|
documentation](SEMANTIC_HIGHLIGHTING.md).
|
48
48
|
|
49
|
+
### Configuring code indexing
|
50
|
+
|
51
|
+
By default, the Ruby LSP indexes all Ruby files defined in the current project and all of its dependencies, including
|
52
|
+
default gems, except for
|
53
|
+
|
54
|
+
- Gems that only appear under the `:development` group
|
55
|
+
- All Ruby files under `test/**/*.rb`
|
56
|
+
|
57
|
+
By creating a `.index.yml` file, these configurations can be overridden and tuned.
|
58
|
+
|
59
|
+
```yaml
|
60
|
+
# Exclude files based on a given pattern. Often used to exclude test files or fixtures
|
61
|
+
excluded_patterns:
|
62
|
+
- "**/spec/**/*.rb"
|
63
|
+
|
64
|
+
# Include files based on a given pattern. Can be used to index Ruby files that use different extensions
|
65
|
+
included_patterns:
|
66
|
+
- "**/bin/*"
|
67
|
+
|
68
|
+
# Exclude gems by name. If a gem is never referenced in the project's code and is only used as a tool, excluding it will
|
69
|
+
# speed up indexing and reduce the amount of results in features like definition or completion
|
70
|
+
excluded_gems:
|
71
|
+
- rubocop
|
72
|
+
- pathname
|
73
|
+
|
74
|
+
# Include gems by name. Normally used to include development gems that are excluded by default
|
75
|
+
included_gems:
|
76
|
+
- prism
|
77
|
+
```
|
78
|
+
|
49
79
|
### Addons
|
50
80
|
|
51
81
|
The Ruby LSP provides an addon system that allows other gems to enhance the base functionality with more editor
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.13.
|
1
|
+
0.13.3
|
@@ -193,7 +193,7 @@ module RubyIndexer
|
|
193
193
|
# When working on a gem, we need to make sure that its gemspec dependencies can't be excluded. This is necessary
|
194
194
|
# because Bundler doesn't assign groups to gemspec dependencies
|
195
195
|
this_gem = Bundler.definition.dependencies.find do |d|
|
196
|
-
d.to_spec
|
196
|
+
d.to_spec&.full_gem_path == Dir.pwd
|
197
197
|
rescue Gem::MissingSpecError
|
198
198
|
false
|
199
199
|
end
|
@@ -81,9 +81,13 @@ module RubyIndexer
|
|
81
81
|
|
82
82
|
abstract!
|
83
83
|
|
84
|
+
# Name includes just the name of the parameter, excluding symbols like splats
|
84
85
|
sig { returns(Symbol) }
|
85
86
|
attr_reader :name
|
86
87
|
|
88
|
+
# Decorated name is the parameter name including the splat or block prefix, e.g.: `*foo`, `**foo` or `&block`
|
89
|
+
alias_method :decorated_name, :name
|
90
|
+
|
87
91
|
sig { params(name: Symbol).void }
|
88
92
|
def initialize(name:)
|
89
93
|
@name = name
|
@@ -100,25 +104,48 @@ module RubyIndexer
|
|
100
104
|
|
101
105
|
# An required keyword method parameter, e.g. `def foo(a:)`
|
102
106
|
class KeywordParameter < Parameter
|
107
|
+
sig { override.returns(Symbol) }
|
108
|
+
def decorated_name
|
109
|
+
:"#{@name}:"
|
110
|
+
end
|
103
111
|
end
|
104
112
|
|
105
113
|
# An optional keyword method parameter, e.g. `def foo(a: 123)`
|
106
114
|
class OptionalKeywordParameter < Parameter
|
115
|
+
sig { override.returns(Symbol) }
|
116
|
+
def decorated_name
|
117
|
+
:"#{@name}:"
|
118
|
+
end
|
107
119
|
end
|
108
120
|
|
109
121
|
# A rest method parameter, e.g. `def foo(*a)`
|
110
122
|
class RestParameter < Parameter
|
111
123
|
DEFAULT_NAME = T.let(:"<anonymous splat>", Symbol)
|
124
|
+
|
125
|
+
sig { override.returns(Symbol) }
|
126
|
+
def decorated_name
|
127
|
+
:"*#{@name}"
|
128
|
+
end
|
112
129
|
end
|
113
130
|
|
114
131
|
# A keyword rest method parameter, e.g. `def foo(**a)`
|
115
132
|
class KeywordRestParameter < Parameter
|
116
133
|
DEFAULT_NAME = T.let(:"<anonymous keyword splat>", Symbol)
|
134
|
+
|
135
|
+
sig { override.returns(Symbol) }
|
136
|
+
def decorated_name
|
137
|
+
:"**#{@name}"
|
138
|
+
end
|
117
139
|
end
|
118
140
|
|
119
141
|
# A block method parameter, e.g. `def foo(&block)`
|
120
142
|
class BlockParameter < Parameter
|
121
143
|
DEFAULT_NAME = T.let(:"<anonymous block>", Symbol)
|
144
|
+
|
145
|
+
sig { override.returns(Symbol) }
|
146
|
+
def decorated_name
|
147
|
+
:"&#{@name}"
|
148
|
+
end
|
122
149
|
end
|
123
150
|
|
124
151
|
class Member < Entry
|
@@ -220,7 +247,7 @@ module RubyIndexer
|
|
220
247
|
|
221
248
|
rest = parameters_node.rest
|
222
249
|
|
223
|
-
if rest
|
250
|
+
if rest.is_a?(Prism::RestParameterNode)
|
224
251
|
rest_name = rest.name || RestParameter::DEFAULT_NAME
|
225
252
|
parameters << RestParameter.new(name: rest_name)
|
226
253
|
end
|
@@ -261,6 +288,8 @@ module RubyIndexer
|
|
261
288
|
names << (rest.operator == "*" ? "*#{name}".to_sym : name&.to_sym)
|
262
289
|
end
|
263
290
|
|
291
|
+
names << nil if rest.is_a?(Prism::ImplicitRestNode)
|
292
|
+
|
264
293
|
names.concat(node.rights.map { |parameter_node| parameter_name(parameter_node) })
|
265
294
|
|
266
295
|
names_with_commas = names.join(", ")
|
data/lib/ruby_lsp/check_docs.rb
CHANGED
@@ -51,15 +51,15 @@ module RubyLsp
|
|
51
51
|
|
52
52
|
# Find all classes that inherit from BaseRequest or Listener, which are the ones we want to make sure are
|
53
53
|
# documented
|
54
|
-
features = ObjectSpace.each_object(Class).
|
54
|
+
features = ObjectSpace.each_object(Class).select do |k|
|
55
55
|
klass = T.unsafe(k)
|
56
|
-
klass
|
56
|
+
klass < Requests::Request
|
57
57
|
end
|
58
58
|
|
59
59
|
missing_docs = T.let(Hash.new { |h, k| h[k] = [] }, T::Hash[String, T::Array[String]])
|
60
60
|
|
61
61
|
features.each do |klass|
|
62
|
-
class_name = T.
|
62
|
+
class_name = T.unsafe(klass).name
|
63
63
|
file_path, line_number = Module.const_source_location(class_name)
|
64
64
|
next unless file_path && line_number
|
65
65
|
|
data/lib/ruby_lsp/document.rb
CHANGED
@@ -8,10 +8,6 @@ module RubyLsp
|
|
8
8
|
|
9
9
|
abstract!
|
10
10
|
|
11
|
-
PositionShape = T.type_alias { { line: Integer, character: Integer } }
|
12
|
-
RangeShape = T.type_alias { { start: PositionShape, end: PositionShape } }
|
13
|
-
EditShape = T.type_alias { { range: RangeShape, text: String } }
|
14
|
-
|
15
11
|
sig { returns(Prism::ParseResult) }
|
16
12
|
attr_reader :parse_result
|
17
13
|
|
@@ -80,7 +76,7 @@ module RubyLsp
|
|
80
76
|
@cache[request_name]
|
81
77
|
end
|
82
78
|
|
83
|
-
sig { params(edits: T::Array[
|
79
|
+
sig { params(edits: T::Array[T::Hash[Symbol, T.untyped]], version: Integer).void }
|
84
80
|
def push_edits(edits, version:)
|
85
81
|
edits.each do |edit|
|
86
82
|
range = edit[:range]
|
@@ -112,7 +108,7 @@ module RubyLsp
|
|
112
108
|
|
113
109
|
sig do
|
114
110
|
params(
|
115
|
-
position:
|
111
|
+
position: T::Hash[Symbol, T.untyped],
|
116
112
|
node_types: T::Array[T.class_of(Prism::Node)],
|
117
113
|
).returns([T.nilable(Prism::Node), T.nilable(Prism::Node), T::Array[String]])
|
118
114
|
end
|
@@ -177,6 +173,18 @@ module RubyLsp
|
|
177
173
|
[closest, parent, nesting.map { |n| n.constant_path.location.slice }]
|
178
174
|
end
|
179
175
|
|
176
|
+
sig { returns(T::Boolean) }
|
177
|
+
def sorbet_sigil_is_true_or_higher
|
178
|
+
parse_result.magic_comments.any? do |comment|
|
179
|
+
comment.key == "typed" && ["true", "strict", "strong"].include?(comment.value)
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
sig { returns(T::Boolean) }
|
184
|
+
def typechecker_enabled?
|
185
|
+
DependencyDetector.instance.typechecker && sorbet_sigil_is_true_or_higher
|
186
|
+
end
|
187
|
+
|
180
188
|
class Scanner
|
181
189
|
extend T::Sig
|
182
190
|
|
@@ -193,7 +201,7 @@ module RubyLsp
|
|
193
201
|
end
|
194
202
|
|
195
203
|
# Finds the character index inside the source string for a given line and column
|
196
|
-
sig { params(position:
|
204
|
+
sig { params(position: T::Hash[Symbol, T.untyped]).returns(Integer) }
|
197
205
|
def find_char_position(position)
|
198
206
|
# Find the character index for the beginning of the requested line
|
199
207
|
until @current_line == position[:line]
|
data/lib/ruby_lsp/executor.rb
CHANGED
@@ -25,6 +25,7 @@ module RubyLsp
|
|
25
25
|
begin
|
26
26
|
response = run(request)
|
27
27
|
rescue StandardError, LoadError => e
|
28
|
+
warn(e.message)
|
28
29
|
error = e
|
29
30
|
end
|
30
31
|
|
@@ -93,7 +94,7 @@ module RubyLsp
|
|
93
94
|
cached_response = document.cache_get(request[:method])
|
94
95
|
return cached_response if cached_response
|
95
96
|
|
96
|
-
# Run
|
97
|
+
# Run requests for the document
|
97
98
|
dispatcher = Prism::Dispatcher.new
|
98
99
|
folding_range = Requests::FoldingRanges.new(document.parse_result.comments, dispatcher)
|
99
100
|
document_symbol = Requests::DocumentSymbol.new(dispatcher)
|
@@ -106,13 +107,13 @@ module RubyLsp
|
|
106
107
|
|
107
108
|
# Store all responses retrieve in this round of visits in the cache and then return the response for the request
|
108
109
|
# we actually received
|
109
|
-
document.cache_set("textDocument/foldingRange", folding_range.
|
110
|
-
document.cache_set("textDocument/documentSymbol", document_symbol.
|
111
|
-
document.cache_set("textDocument/documentLink", document_link.
|
112
|
-
document.cache_set("textDocument/codeLens", code_lens.
|
110
|
+
document.cache_set("textDocument/foldingRange", folding_range.perform)
|
111
|
+
document.cache_set("textDocument/documentSymbol", document_symbol.perform)
|
112
|
+
document.cache_set("textDocument/documentLink", document_link.perform)
|
113
|
+
document.cache_set("textDocument/codeLens", code_lens.perform)
|
113
114
|
document.cache_set(
|
114
115
|
"textDocument/semanticTokens/full",
|
115
|
-
Requests::Support::SemanticTokenEncoder.new.encode(semantic_highlighting.
|
116
|
+
Requests::Support::SemanticTokenEncoder.new.encode(semantic_highlighting.perform),
|
116
117
|
)
|
117
118
|
document.cache_get(request[:method])
|
118
119
|
when "textDocument/semanticTokens/range"
|
@@ -142,13 +143,30 @@ module RubyLsp
|
|
142
143
|
nil
|
143
144
|
end
|
144
145
|
when "textDocument/documentHighlight"
|
145
|
-
|
146
|
+
dispatcher = Prism::Dispatcher.new
|
147
|
+
document = @store.get(uri)
|
148
|
+
request = Requests::DocumentHighlight.new(document, request.dig(:params, :position), dispatcher)
|
149
|
+
dispatcher.dispatch(document.tree)
|
150
|
+
request.perform
|
146
151
|
when "textDocument/onTypeFormatting"
|
147
152
|
on_type_formatting(uri, request.dig(:params, :position), request.dig(:params, :ch))
|
148
153
|
when "textDocument/hover"
|
149
|
-
|
154
|
+
dispatcher = Prism::Dispatcher.new
|
155
|
+
document = @store.get(uri)
|
156
|
+
Requests::Hover.new(
|
157
|
+
document,
|
158
|
+
@index,
|
159
|
+
request.dig(:params, :position),
|
160
|
+
dispatcher,
|
161
|
+
document.typechecker_enabled?,
|
162
|
+
).perform
|
150
163
|
when "textDocument/inlayHint"
|
151
|
-
|
164
|
+
hints_configurations = T.must(@store.features_configuration.dig(:inlayHint))
|
165
|
+
dispatcher = Prism::Dispatcher.new
|
166
|
+
document = @store.get(uri)
|
167
|
+
request = Requests::InlayHints.new(document, request.dig(:params, :range), hints_configurations, dispatcher)
|
168
|
+
dispatcher.visit(document.tree)
|
169
|
+
request.perform
|
152
170
|
when "textDocument/codeAction"
|
153
171
|
code_action(uri, request.dig(:params, :range), request.dig(:params, :context))
|
154
172
|
when "codeAction/resolve"
|
@@ -168,9 +186,36 @@ module RubyLsp
|
|
168
186
|
nil
|
169
187
|
end
|
170
188
|
when "textDocument/completion"
|
171
|
-
|
189
|
+
dispatcher = Prism::Dispatcher.new
|
190
|
+
document = @store.get(uri)
|
191
|
+
Requests::Completion.new(
|
192
|
+
document,
|
193
|
+
@index,
|
194
|
+
request.dig(:params, :position),
|
195
|
+
document.typechecker_enabled?,
|
196
|
+
dispatcher,
|
197
|
+
).perform
|
198
|
+
when "textDocument/signatureHelp"
|
199
|
+
dispatcher = Prism::Dispatcher.new
|
200
|
+
document = @store.get(uri)
|
201
|
+
|
202
|
+
Requests::SignatureHelp.new(
|
203
|
+
document,
|
204
|
+
@index,
|
205
|
+
request.dig(:params, :position),
|
206
|
+
request.dig(:params, :context),
|
207
|
+
dispatcher,
|
208
|
+
).perform
|
172
209
|
when "textDocument/definition"
|
173
|
-
|
210
|
+
dispatcher = Prism::Dispatcher.new
|
211
|
+
document = @store.get(uri)
|
212
|
+
Requests::Definition.new(
|
213
|
+
document,
|
214
|
+
@index,
|
215
|
+
request.dig(:params, :position),
|
216
|
+
dispatcher,
|
217
|
+
document.typechecker_enabled?,
|
218
|
+
).perform
|
174
219
|
when "workspace/didChangeWatchedFiles"
|
175
220
|
did_change_watched_files(request.dig(:params, :changes))
|
176
221
|
when "workspace/symbol"
|
@@ -242,66 +287,16 @@ module RubyLsp
|
|
242
287
|
|
243
288
|
sig { params(query: T.nilable(String)).returns(T::Array[Interface::WorkspaceSymbol]) }
|
244
289
|
def workspace_symbol(query)
|
245
|
-
Requests::WorkspaceSymbol.new(query, @index).
|
290
|
+
Requests::WorkspaceSymbol.new(query, @index).perform
|
246
291
|
end
|
247
292
|
|
248
|
-
sig { params(uri: URI::Generic, range: T.nilable(
|
293
|
+
sig { params(uri: URI::Generic, range: T.nilable(T::Hash[Symbol, T.untyped])).returns({ ast: String }) }
|
249
294
|
def show_syntax_tree(uri, range)
|
250
|
-
{ ast: Requests::ShowSyntaxTree.new(@store.get(uri), range).
|
251
|
-
end
|
252
|
-
|
253
|
-
sig do
|
254
|
-
params(
|
255
|
-
uri: URI::Generic,
|
256
|
-
position: Document::PositionShape,
|
257
|
-
).returns(T.nilable(T.any(T::Array[Interface::Location], Interface::Location)))
|
258
|
-
end
|
259
|
-
def definition(uri, position)
|
260
|
-
document = @store.get(uri)
|
261
|
-
target, parent, nesting = document.locate_node(
|
262
|
-
position,
|
263
|
-
node_types: [Prism::CallNode, Prism::ConstantReadNode, Prism::ConstantPathNode],
|
264
|
-
)
|
265
|
-
|
266
|
-
target = parent if target.is_a?(Prism::ConstantReadNode) && parent.is_a?(Prism::ConstantPathNode)
|
267
|
-
|
268
|
-
dispatcher = Prism::Dispatcher.new
|
269
|
-
base_listener = Requests::Definition.new(uri, nesting, @index, dispatcher)
|
270
|
-
dispatcher.dispatch_once(target)
|
271
|
-
base_listener.response
|
272
|
-
end
|
273
|
-
|
274
|
-
sig do
|
275
|
-
params(
|
276
|
-
uri: URI::Generic,
|
277
|
-
position: Document::PositionShape,
|
278
|
-
).returns(T.nilable(Interface::Hover))
|
279
|
-
end
|
280
|
-
def hover(uri, position)
|
281
|
-
document = @store.get(uri)
|
282
|
-
target, parent, nesting = document.locate_node(
|
283
|
-
position,
|
284
|
-
node_types: Requests::Hover::ALLOWED_TARGETS,
|
285
|
-
)
|
286
|
-
|
287
|
-
if (Requests::Hover::ALLOWED_TARGETS.include?(parent.class) &&
|
288
|
-
!Requests::Hover::ALLOWED_TARGETS.include?(target.class)) ||
|
289
|
-
(parent.is_a?(Prism::ConstantPathNode) && target.is_a?(Prism::ConstantReadNode))
|
290
|
-
target = parent
|
291
|
-
end
|
292
|
-
|
293
|
-
# Instantiate all listeners
|
294
|
-
dispatcher = Prism::Dispatcher.new
|
295
|
-
hover = Requests::Hover.new(@index, nesting, dispatcher)
|
296
|
-
|
297
|
-
# Emit events for all listeners
|
298
|
-
dispatcher.dispatch_once(target)
|
299
|
-
|
300
|
-
hover.response
|
295
|
+
{ ast: Requests::ShowSyntaxTree.new(@store.get(uri), range).perform }
|
301
296
|
end
|
302
297
|
|
303
298
|
sig do
|
304
|
-
params(uri: URI::Generic, content_changes: T::Array[
|
299
|
+
params(uri: URI::Generic, content_changes: T::Array[T::Hash[Symbol, T.untyped]], version: Integer).returns(Object)
|
305
300
|
end
|
306
301
|
def text_document_did_change(uri, content_changes, version)
|
307
302
|
@store.push_edits(uri: uri, edits: content_changes, version: version)
|
@@ -323,12 +318,12 @@ module RubyLsp
|
|
323
318
|
sig do
|
324
319
|
params(
|
325
320
|
uri: URI::Generic,
|
326
|
-
positions: T::Array[
|
321
|
+
positions: T::Array[T::Hash[Symbol, T.untyped]],
|
327
322
|
).returns(T.nilable(T::Array[T.nilable(Requests::Support::SelectionRange)]))
|
328
323
|
end
|
329
324
|
def selection_range(uri, positions)
|
330
325
|
ranges = @store.cache_fetch(uri, "textDocument/selectionRange") do |document|
|
331
|
-
Requests::SelectionRanges.new(document).
|
326
|
+
Requests::SelectionRanges.new(document).perform
|
332
327
|
end
|
333
328
|
|
334
329
|
# Per the selection range request spec (https://microsoft.github.io/language-server-protocol/specification#textDocument_selectionRange),
|
@@ -355,68 +350,38 @@ module RubyLsp
|
|
355
350
|
path = uri.to_standardized_path
|
356
351
|
return unless path.nil? || path.start_with?(T.must(@store.workspace_uri.to_standardized_path))
|
357
352
|
|
358
|
-
Requests::Formatting.new(@store.get(uri), formatter: @store.formatter).
|
353
|
+
Requests::Formatting.new(@store.get(uri), formatter: @store.formatter).perform
|
359
354
|
end
|
360
355
|
|
361
356
|
sig do
|
362
357
|
params(
|
363
358
|
uri: URI::Generic,
|
364
|
-
position:
|
359
|
+
position: T::Hash[Symbol, T.untyped],
|
365
360
|
character: String,
|
366
361
|
).returns(T::Array[Interface::TextEdit])
|
367
362
|
end
|
368
363
|
def on_type_formatting(uri, position, character)
|
369
|
-
Requests::OnTypeFormatting.new(@store.get(uri), position, character).
|
364
|
+
Requests::OnTypeFormatting.new(@store.get(uri), position, character).perform
|
370
365
|
end
|
371
366
|
|
372
367
|
sig do
|
373
368
|
params(
|
374
369
|
uri: URI::Generic,
|
375
|
-
|
376
|
-
).returns(T.nilable(T::Array[Interface::DocumentHighlight]))
|
377
|
-
end
|
378
|
-
def document_highlight(uri, position)
|
379
|
-
document = @store.get(uri)
|
380
|
-
|
381
|
-
target, parent = document.locate_node(position)
|
382
|
-
dispatcher = Prism::Dispatcher.new
|
383
|
-
listener = Requests::DocumentHighlight.new(target, parent, dispatcher)
|
384
|
-
dispatcher.visit(document.tree)
|
385
|
-
listener.response
|
386
|
-
end
|
387
|
-
|
388
|
-
sig { params(uri: URI::Generic, range: Document::RangeShape).returns(T.nilable(T::Array[Interface::InlayHint])) }
|
389
|
-
def inlay_hint(uri, range)
|
390
|
-
document = @store.get(uri)
|
391
|
-
|
392
|
-
start_line = range.dig(:start, :line)
|
393
|
-
end_line = range.dig(:end, :line)
|
394
|
-
|
395
|
-
dispatcher = Prism::Dispatcher.new
|
396
|
-
hints_configurations = T.must(@store.features_configuration.dig(:inlayHint))
|
397
|
-
listener = Requests::InlayHints.new(start_line..end_line, hints_configurations, dispatcher)
|
398
|
-
dispatcher.visit(document.tree)
|
399
|
-
listener.response
|
400
|
-
end
|
401
|
-
|
402
|
-
sig do
|
403
|
-
params(
|
404
|
-
uri: URI::Generic,
|
405
|
-
range: Document::RangeShape,
|
370
|
+
range: T::Hash[Symbol, T.untyped],
|
406
371
|
context: T::Hash[Symbol, T.untyped],
|
407
372
|
).returns(T.nilable(T::Array[Interface::CodeAction]))
|
408
373
|
end
|
409
374
|
def code_action(uri, range, context)
|
410
375
|
document = @store.get(uri)
|
411
376
|
|
412
|
-
Requests::CodeActions.new(document, range, context).
|
377
|
+
Requests::CodeActions.new(document, range, context).perform
|
413
378
|
end
|
414
379
|
|
415
380
|
sig { params(params: T::Hash[Symbol, T.untyped]).returns(Interface::CodeAction) }
|
416
381
|
def code_action_resolve(params)
|
417
382
|
uri = URI(params.dig(:data, :uri))
|
418
383
|
document = @store.get(uri)
|
419
|
-
result = Requests::CodeActionResolve.new(document, params).
|
384
|
+
result = Requests::CodeActionResolve.new(document, params).perform
|
420
385
|
|
421
386
|
case result
|
422
387
|
when Requests::CodeActionResolve::Error::EmptySelection
|
@@ -450,74 +415,23 @@ module RubyLsp
|
|
450
415
|
return unless path.nil? || path.start_with?(T.must(@store.workspace_uri.to_standardized_path))
|
451
416
|
|
452
417
|
response = @store.cache_fetch(uri, "textDocument/diagnostic") do |document|
|
453
|
-
Requests::Diagnostics.new(document).
|
418
|
+
Requests::Diagnostics.new(document).perform
|
454
419
|
end
|
455
420
|
|
456
421
|
Interface::FullDocumentDiagnosticReport.new(kind: "full", items: response) if response
|
457
422
|
end
|
458
423
|
|
459
|
-
sig { params(uri: URI::Generic, range:
|
424
|
+
sig { params(uri: URI::Generic, range: T::Hash[Symbol, T.untyped]).returns(Interface::SemanticTokens) }
|
460
425
|
def semantic_tokens_range(uri, range)
|
461
426
|
document = @store.get(uri)
|
462
427
|
start_line = range.dig(:start, :line)
|
463
428
|
end_line = range.dig(:end, :line)
|
464
429
|
|
465
430
|
dispatcher = Prism::Dispatcher.new
|
466
|
-
|
431
|
+
request = Requests::SemanticHighlighting.new(dispatcher, range: start_line..end_line)
|
467
432
|
dispatcher.visit(document.tree)
|
468
433
|
|
469
|
-
Requests::Support::SemanticTokenEncoder.new.encode(
|
470
|
-
end
|
471
|
-
|
472
|
-
sig do
|
473
|
-
params(
|
474
|
-
uri: URI::Generic,
|
475
|
-
position: Document::PositionShape,
|
476
|
-
).returns(T.nilable(T::Array[Interface::CompletionItem]))
|
477
|
-
end
|
478
|
-
def completion(uri, position)
|
479
|
-
document = @store.get(uri)
|
480
|
-
|
481
|
-
# Completion always receives the position immediately after the character that was just typed. Here we adjust it
|
482
|
-
# back by 1, so that we find the right node
|
483
|
-
char_position = document.create_scanner.find_char_position(position) - 1
|
484
|
-
matched, parent, nesting = document.locate(
|
485
|
-
document.tree,
|
486
|
-
char_position,
|
487
|
-
node_types: [Prism::CallNode, Prism::ConstantReadNode, Prism::ConstantPathNode],
|
488
|
-
)
|
489
|
-
return unless matched && parent
|
490
|
-
|
491
|
-
target = case matched
|
492
|
-
when Prism::CallNode
|
493
|
-
message = matched.message
|
494
|
-
|
495
|
-
if message == "require"
|
496
|
-
args = matched.arguments&.arguments
|
497
|
-
return if args.nil? || args.is_a?(Prism::ForwardingArgumentsNode)
|
498
|
-
|
499
|
-
argument = args.first
|
500
|
-
return unless argument.is_a?(Prism::StringNode)
|
501
|
-
return unless (argument.location.start_offset..argument.location.end_offset).cover?(char_position)
|
502
|
-
|
503
|
-
argument
|
504
|
-
else
|
505
|
-
matched
|
506
|
-
end
|
507
|
-
when Prism::ConstantReadNode, Prism::ConstantPathNode
|
508
|
-
if parent.is_a?(Prism::ConstantPathNode) && matched.is_a?(Prism::ConstantReadNode)
|
509
|
-
parent
|
510
|
-
else
|
511
|
-
matched
|
512
|
-
end
|
513
|
-
end
|
514
|
-
|
515
|
-
return unless target
|
516
|
-
|
517
|
-
dispatcher = Prism::Dispatcher.new
|
518
|
-
listener = Requests::Completion.new(@index, nesting, dispatcher)
|
519
|
-
dispatcher.dispatch_once(target)
|
520
|
-
listener.response
|
434
|
+
Requests::Support::SemanticTokenEncoder.new.encode(request.perform)
|
521
435
|
end
|
522
436
|
|
523
437
|
sig { params(id: String, title: String, percentage: Integer).void }
|
@@ -623,74 +537,18 @@ module RubyLsp
|
|
623
537
|
Hash.new(true)
|
624
538
|
end
|
625
539
|
|
626
|
-
document_symbol_provider = if enabled_features["documentSymbols"]
|
627
|
-
|
628
|
-
|
629
|
-
|
630
|
-
|
631
|
-
|
632
|
-
|
633
|
-
|
634
|
-
|
635
|
-
|
636
|
-
|
637
|
-
|
638
|
-
|
639
|
-
code_lens_provider = if enabled_features["codeLens"]
|
640
|
-
Interface::CodeLensOptions.new(resolve_provider: false)
|
641
|
-
end
|
642
|
-
|
643
|
-
hover_provider = if enabled_features["hover"]
|
644
|
-
Interface::HoverClientCapabilities.new(dynamic_registration: false)
|
645
|
-
end
|
646
|
-
|
647
|
-
folding_ranges_provider = if enabled_features["foldingRanges"]
|
648
|
-
Interface::FoldingRangeClientCapabilities.new(line_folding_only: true)
|
649
|
-
end
|
650
|
-
|
651
|
-
semantic_tokens_provider = if enabled_features["semanticHighlighting"]
|
652
|
-
Interface::SemanticTokensRegistrationOptions.new(
|
653
|
-
document_selector: { scheme: "file", language: "ruby" },
|
654
|
-
legend: Interface::SemanticTokensLegend.new(
|
655
|
-
token_types: Requests::SemanticHighlighting::TOKEN_TYPES.keys,
|
656
|
-
token_modifiers: Requests::SemanticHighlighting::TOKEN_MODIFIERS.keys,
|
657
|
-
),
|
658
|
-
range: true,
|
659
|
-
full: { delta: false },
|
660
|
-
)
|
661
|
-
end
|
662
|
-
|
663
|
-
diagnostics_provider = if enabled_features["diagnostics"]
|
664
|
-
{
|
665
|
-
interFileDependencies: false,
|
666
|
-
workspaceDiagnostics: false,
|
667
|
-
}
|
668
|
-
end
|
669
|
-
|
670
|
-
on_type_formatting_provider = if enabled_features["onTypeFormatting"]
|
671
|
-
Interface::DocumentOnTypeFormattingOptions.new(
|
672
|
-
first_trigger_character: "{",
|
673
|
-
more_trigger_character: ["\n", "|", "d"],
|
674
|
-
)
|
675
|
-
end
|
676
|
-
|
677
|
-
code_action_provider = if enabled_features["codeActions"]
|
678
|
-
Interface::CodeActionOptions.new(resolve_provider: true)
|
679
|
-
end
|
680
|
-
|
681
|
-
inlay_hint_provider = if enabled_features["inlayHint"]
|
682
|
-
Interface::InlayHintOptions.new(resolve_provider: false)
|
683
|
-
end
|
684
|
-
|
685
|
-
completion_provider = if enabled_features["completion"]
|
686
|
-
Interface::CompletionOptions.new(
|
687
|
-
resolve_provider: false,
|
688
|
-
trigger_characters: ["/"],
|
689
|
-
completion_item: {
|
690
|
-
labelDetailsSupport: true,
|
691
|
-
},
|
692
|
-
)
|
693
|
-
end
|
540
|
+
document_symbol_provider = Requests::DocumentSymbol.provider if enabled_features["documentSymbols"]
|
541
|
+
document_link_provider = Requests::DocumentLink.provider if enabled_features["documentLink"]
|
542
|
+
code_lens_provider = Requests::CodeLens.provider if enabled_features["codeLens"]
|
543
|
+
hover_provider = Requests::Hover.provider if enabled_features["hover"]
|
544
|
+
folding_ranges_provider = Requests::FoldingRanges.provider if enabled_features["foldingRanges"]
|
545
|
+
semantic_tokens_provider = Requests::SemanticHighlighting.provider if enabled_features["semanticHighlighting"]
|
546
|
+
diagnostics_provider = Requests::Diagnostics.provider if enabled_features["diagnostics"]
|
547
|
+
on_type_formatting_provider = Requests::OnTypeFormatting.provider if enabled_features["onTypeFormatting"]
|
548
|
+
code_action_provider = Requests::CodeActions.provider if enabled_features["codeActions"]
|
549
|
+
inlay_hint_provider = Requests::InlayHints.provider if enabled_features["inlayHint"]
|
550
|
+
completion_provider = Requests::Completion.provider if enabled_features["completion"]
|
551
|
+
signature_help_provider = Requests::SignatureHelp.provider if enabled_features["signatureHelp"]
|
694
552
|
|
695
553
|
# Dynamically registered capabilities
|
696
554
|
file_watching_caps = options.dig(:capabilities, :workspace, :didChangeWatchedFiles)
|
@@ -744,6 +602,7 @@ module RubyLsp
|
|
744
602
|
code_lens_provider: code_lens_provider,
|
745
603
|
definition_provider: enabled_features["definition"],
|
746
604
|
workspace_symbol_provider: enabled_features["workspaceSymbol"],
|
605
|
+
signature_help_provider: signature_help_provider,
|
747
606
|
),
|
748
607
|
serverInfo: {
|
749
608
|
name: "Ruby LSP",
|