ruby-lsp 0.13.1 → 0.13.3
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_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",
|