ruby-lsp 0.23.11 → 0.23.17
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 +2 -2
- data/VERSION +1 -1
- data/exe/ruby-lsp-launcher +20 -11
- data/lib/rubocop/cop/ruby_lsp/use_language_server_aliases.rb +1 -1
- data/lib/rubocop/cop/ruby_lsp/use_register_with_handler_method.rb +3 -5
- data/lib/ruby_indexer/lib/ruby_indexer/configuration.rb +82 -116
- data/lib/ruby_indexer/lib/ruby_indexer/declaration_listener.rb +134 -183
- data/lib/ruby_indexer/lib/ruby_indexer/enhancement.rb +9 -10
- data/lib/ruby_indexer/lib/ruby_indexer/entry.rb +97 -217
- data/lib/ruby_indexer/lib/ruby_indexer/index.rb +139 -281
- data/lib/ruby_indexer/lib/ruby_indexer/location.rb +4 -27
- data/lib/ruby_indexer/lib/ruby_indexer/prefix_tree.rb +18 -19
- data/lib/ruby_indexer/lib/ruby_indexer/rbs_indexer.rb +23 -55
- data/lib/ruby_indexer/lib/ruby_indexer/reference_finder.rb +47 -61
- data/lib/ruby_indexer/lib/ruby_indexer/uri.rb +17 -19
- data/lib/ruby_indexer/lib/ruby_indexer/visibility_scope.rb +7 -11
- data/lib/ruby_indexer/test/class_variables_test.rb +14 -14
- data/lib/ruby_indexer/test/classes_and_modules_test.rb +65 -40
- data/lib/ruby_indexer/test/configuration_test.rb +48 -7
- data/lib/ruby_indexer/test/constant_test.rb +34 -34
- data/lib/ruby_indexer/test/enhancements_test.rb +1 -1
- data/lib/ruby_indexer/test/index_test.rb +146 -135
- data/lib/ruby_indexer/test/instance_variables_test.rb +37 -37
- data/lib/ruby_indexer/test/method_test.rb +149 -123
- data/lib/ruby_indexer/test/prefix_tree_test.rb +13 -13
- data/lib/ruby_indexer/test/rbs_indexer_test.rb +68 -73
- data/lib/ruby_indexer/test/test_case.rb +9 -3
- data/lib/ruby_indexer/test/uri_test.rb +15 -2
- data/lib/ruby_lsp/addon.rb +44 -71
- data/lib/ruby_lsp/base_server.rb +29 -32
- data/lib/ruby_lsp/client_capabilities.rb +10 -12
- data/lib/ruby_lsp/document.rb +40 -54
- data/lib/ruby_lsp/erb_document.rb +37 -41
- data/lib/ruby_lsp/global_state.rb +52 -57
- data/lib/ruby_lsp/internal.rb +2 -0
- data/lib/ruby_lsp/listeners/code_lens.rb +82 -89
- data/lib/ruby_lsp/listeners/completion.rb +67 -73
- data/lib/ruby_lsp/listeners/definition.rb +44 -58
- data/lib/ruby_lsp/listeners/document_highlight.rb +123 -150
- data/lib/ruby_lsp/listeners/document_link.rb +50 -70
- data/lib/ruby_lsp/listeners/document_symbol.rb +38 -52
- data/lib/ruby_lsp/listeners/folding_ranges.rb +40 -43
- data/lib/ruby_lsp/listeners/hover.rb +92 -110
- data/lib/ruby_lsp/listeners/inlay_hints.rb +4 -11
- data/lib/ruby_lsp/listeners/semantic_highlighting.rb +54 -56
- data/lib/ruby_lsp/listeners/signature_help.rb +12 -27
- data/lib/ruby_lsp/listeners/spec_style.rb +155 -0
- data/lib/ruby_lsp/listeners/test_discovery.rb +89 -0
- data/lib/ruby_lsp/listeners/test_style.rb +167 -90
- data/lib/ruby_lsp/node_context.rb +12 -39
- data/lib/ruby_lsp/rbs_document.rb +9 -7
- data/lib/ruby_lsp/requests/code_action_resolve.rb +63 -59
- data/lib/ruby_lsp/requests/code_actions.rb +14 -26
- data/lib/ruby_lsp/requests/code_lens.rb +20 -19
- data/lib/ruby_lsp/requests/completion.rb +7 -20
- data/lib/ruby_lsp/requests/completion_resolve.rb +6 -6
- data/lib/ruby_lsp/requests/definition.rb +7 -17
- data/lib/ruby_lsp/requests/diagnostics.rb +8 -11
- data/lib/ruby_lsp/requests/discover_tests.rb +18 -5
- data/lib/ruby_lsp/requests/document_highlight.rb +5 -15
- data/lib/ruby_lsp/requests/document_link.rb +6 -17
- data/lib/ruby_lsp/requests/document_symbol.rb +5 -8
- data/lib/ruby_lsp/requests/folding_ranges.rb +7 -15
- data/lib/ruby_lsp/requests/formatting.rb +6 -9
- data/lib/ruby_lsp/requests/go_to_relevant_file.rb +85 -0
- data/lib/ruby_lsp/requests/hover.rb +10 -20
- data/lib/ruby_lsp/requests/inlay_hints.rb +6 -17
- data/lib/ruby_lsp/requests/on_type_formatting.rb +32 -40
- data/lib/ruby_lsp/requests/prepare_rename.rb +4 -9
- data/lib/ruby_lsp/requests/prepare_type_hierarchy.rb +5 -15
- data/lib/ruby_lsp/requests/range_formatting.rb +5 -6
- data/lib/ruby_lsp/requests/references.rb +9 -53
- data/lib/ruby_lsp/requests/rename.rb +20 -46
- data/lib/ruby_lsp/requests/request.rb +8 -19
- data/lib/ruby_lsp/requests/selection_ranges.rb +6 -6
- data/lib/ruby_lsp/requests/semantic_highlighting.rb +16 -35
- data/lib/ruby_lsp/requests/show_syntax_tree.rb +7 -8
- data/lib/ruby_lsp/requests/signature_help.rb +8 -26
- data/lib/ruby_lsp/requests/support/annotation.rb +4 -10
- data/lib/ruby_lsp/requests/support/common.rb +15 -55
- data/lib/ruby_lsp/requests/support/rubocop_diagnostic.rb +27 -35
- data/lib/ruby_lsp/requests/support/rubocop_formatter.rb +11 -14
- data/lib/ruby_lsp/requests/support/rubocop_runner.rb +22 -34
- data/lib/ruby_lsp/requests/support/selection_range.rb +1 -3
- data/lib/ruby_lsp/requests/support/sorbet.rb +29 -38
- data/lib/ruby_lsp/requests/support/source_uri.rb +20 -32
- data/lib/ruby_lsp/requests/support/syntax_tree_formatter.rb +12 -19
- data/lib/ruby_lsp/requests/support/test_item.rb +16 -14
- data/lib/ruby_lsp/requests/type_hierarchy_supertypes.rb +5 -6
- data/lib/ruby_lsp/requests/workspace_symbol.rb +4 -4
- data/lib/ruby_lsp/response_builders/collection_response_builder.rb +5 -5
- data/lib/ruby_lsp/response_builders/document_symbol.rb +14 -19
- data/lib/ruby_lsp/response_builders/hover.rb +11 -14
- data/lib/ruby_lsp/response_builders/response_builder.rb +1 -1
- data/lib/ruby_lsp/response_builders/semantic_highlighting.rb +60 -88
- data/lib/ruby_lsp/response_builders/signature_help.rb +5 -6
- data/lib/ruby_lsp/response_builders/test_collection.rb +43 -10
- data/lib/ruby_lsp/ruby_document.rb +24 -92
- data/lib/ruby_lsp/scope.rb +7 -11
- data/lib/ruby_lsp/scripts/compose_bundle.rb +6 -4
- data/lib/ruby_lsp/server.rb +182 -99
- data/lib/ruby_lsp/setup_bundler.rb +65 -60
- data/lib/ruby_lsp/static_docs.rb +11 -7
- data/lib/ruby_lsp/store.rb +29 -47
- data/lib/ruby_lsp/test_helper.rb +2 -12
- data/lib/ruby_lsp/test_reporters/lsp_reporter.rb +191 -0
- data/lib/ruby_lsp/test_reporters/minitest_reporter.rb +105 -0
- data/lib/ruby_lsp/test_reporters/test_unit_reporter.rb +94 -0
- data/lib/ruby_lsp/type_inferrer.rb +13 -14
- data/lib/ruby_lsp/utils.rb +92 -83
- metadata +9 -3
@@ -7,27 +7,20 @@ module RubyLsp
|
|
7
7
|
# [references](https://microsoft.github.io/language-server-protocol/specification#textDocument_references)
|
8
8
|
# request finds all references for the selected symbol.
|
9
9
|
class References < Request
|
10
|
-
extend T::Sig
|
11
10
|
include Support::Common
|
12
11
|
|
13
|
-
|
14
|
-
params(
|
15
|
-
global_state: GlobalState,
|
16
|
-
store: Store,
|
17
|
-
document: T.any(RubyDocument, ERBDocument),
|
18
|
-
params: T::Hash[Symbol, T.untyped],
|
19
|
-
).void
|
20
|
-
end
|
12
|
+
#: (GlobalState global_state, Store store, (RubyDocument | ERBDocument) document, Hash[Symbol, untyped] params) -> void
|
21
13
|
def initialize(global_state, store, document, params)
|
22
14
|
super()
|
23
15
|
@global_state = global_state
|
24
16
|
@store = store
|
25
17
|
@document = document
|
26
18
|
@params = params
|
27
|
-
@locations =
|
19
|
+
@locations = [] #: Array[Interface::Location]
|
28
20
|
end
|
29
21
|
|
30
|
-
|
22
|
+
# @override
|
23
|
+
#: -> Array[Interface::Location]
|
31
24
|
def perform
|
32
25
|
position = @params[:position]
|
33
26
|
char_position, _ = @document.find_index_by_position(position)
|
@@ -62,22 +55,7 @@ module RubyLsp
|
|
62
55
|
)
|
63
56
|
end
|
64
57
|
|
65
|
-
target =
|
66
|
-
target,
|
67
|
-
T.any(
|
68
|
-
Prism::ConstantReadNode,
|
69
|
-
Prism::ConstantPathNode,
|
70
|
-
Prism::ConstantPathTargetNode,
|
71
|
-
Prism::InstanceVariableAndWriteNode,
|
72
|
-
Prism::InstanceVariableOperatorWriteNode,
|
73
|
-
Prism::InstanceVariableOrWriteNode,
|
74
|
-
Prism::InstanceVariableReadNode,
|
75
|
-
Prism::InstanceVariableTargetNode,
|
76
|
-
Prism::InstanceVariableWriteNode,
|
77
|
-
Prism::CallNode,
|
78
|
-
Prism::DefNode,
|
79
|
-
),
|
80
|
-
)
|
58
|
+
target = target #: as Prism::ConstantReadNode | Prism::ConstantPathNode | Prism::ConstantPathTargetNode | Prism::InstanceVariableAndWriteNode | Prism::InstanceVariableOperatorWriteNode | Prism::InstanceVariableOrWriteNode | Prism::InstanceVariableReadNode | Prism::InstanceVariableTargetNode | Prism::InstanceVariableWriteNode | Prism::CallNode | Prism::DefNode, # rubocop:disable Layout/LineLength
|
81
59
|
|
82
60
|
reference_target = create_reference_target(target, node_context)
|
83
61
|
return @locations unless reference_target
|
@@ -103,24 +81,7 @@ module RubyLsp
|
|
103
81
|
|
104
82
|
private
|
105
83
|
|
106
|
-
|
107
|
-
params(
|
108
|
-
target_node: T.any(
|
109
|
-
Prism::ConstantReadNode,
|
110
|
-
Prism::ConstantPathNode,
|
111
|
-
Prism::ConstantPathTargetNode,
|
112
|
-
Prism::InstanceVariableAndWriteNode,
|
113
|
-
Prism::InstanceVariableOperatorWriteNode,
|
114
|
-
Prism::InstanceVariableOrWriteNode,
|
115
|
-
Prism::InstanceVariableReadNode,
|
116
|
-
Prism::InstanceVariableTargetNode,
|
117
|
-
Prism::InstanceVariableWriteNode,
|
118
|
-
Prism::CallNode,
|
119
|
-
Prism::DefNode,
|
120
|
-
),
|
121
|
-
node_context: NodeContext,
|
122
|
-
).returns(T.nilable(RubyIndexer::ReferenceFinder::Target))
|
123
|
-
end
|
84
|
+
#: ((Prism::ConstantReadNode | Prism::ConstantPathNode | Prism::ConstantPathTargetNode | Prism::InstanceVariableAndWriteNode | Prism::InstanceVariableOperatorWriteNode | Prism::InstanceVariableOrWriteNode | Prism::InstanceVariableReadNode | Prism::InstanceVariableTargetNode | Prism::InstanceVariableWriteNode | Prism::CallNode | Prism::DefNode) target_node, NodeContext node_context) -> RubyIndexer::ReferenceFinder::Target?
|
124
85
|
def create_reference_target(target_node, node_context)
|
125
86
|
case target_node
|
126
87
|
when Prism::ConstantReadNode, Prism::ConstantPathNode, Prism::ConstantPathTargetNode
|
@@ -130,7 +91,8 @@ module RubyLsp
|
|
130
91
|
entries = @global_state.index.resolve(name, node_context.nesting)
|
131
92
|
return unless entries
|
132
93
|
|
133
|
-
fully_qualified_name =
|
94
|
+
fully_qualified_name = entries.first #: as !nil
|
95
|
+
.name
|
134
96
|
RubyIndexer::ReferenceFinder::ConstTarget.new(fully_qualified_name)
|
135
97
|
when
|
136
98
|
Prism::InstanceVariableAndWriteNode,
|
@@ -145,13 +107,7 @@ module RubyLsp
|
|
145
107
|
end
|
146
108
|
end
|
147
109
|
|
148
|
-
|
149
|
-
params(
|
150
|
-
target: RubyIndexer::ReferenceFinder::Target,
|
151
|
-
parse_result: Prism::ParseResult,
|
152
|
-
uri: URI::Generic,
|
153
|
-
).void
|
154
|
-
end
|
110
|
+
#: (RubyIndexer::ReferenceFinder::Target target, Prism::ParseResult parse_result, URI::Generic uri) -> void
|
155
111
|
def collect_references(target, parse_result, uri)
|
156
112
|
dispatcher = Prism::Dispatcher.new
|
157
113
|
finder = RubyIndexer::ReferenceFinder.new(
|
@@ -7,38 +7,29 @@ module RubyLsp
|
|
7
7
|
# [rename](https://microsoft.github.io/language-server-protocol/specification#textDocument_rename)
|
8
8
|
# request renames all instances of a symbol in a document.
|
9
9
|
class Rename < Request
|
10
|
-
extend T::Sig
|
11
10
|
include Support::Common
|
12
11
|
|
13
12
|
class InvalidNameError < StandardError; end
|
14
13
|
|
15
14
|
class << self
|
16
|
-
|
17
|
-
|
18
|
-
sig { returns(Interface::RenameOptions) }
|
15
|
+
#: -> Interface::RenameOptions
|
19
16
|
def provider
|
20
17
|
Interface::RenameOptions.new(prepare_provider: true)
|
21
18
|
end
|
22
19
|
end
|
23
20
|
|
24
|
-
|
25
|
-
params(
|
26
|
-
global_state: GlobalState,
|
27
|
-
store: Store,
|
28
|
-
document: T.any(RubyDocument, ERBDocument),
|
29
|
-
params: T::Hash[Symbol, T.untyped],
|
30
|
-
).void
|
31
|
-
end
|
21
|
+
#: (GlobalState global_state, Store store, (RubyDocument | ERBDocument) document, Hash[Symbol, untyped] params) -> void
|
32
22
|
def initialize(global_state, store, document, params)
|
33
23
|
super()
|
34
24
|
@global_state = global_state
|
35
25
|
@store = store
|
36
26
|
@document = document
|
37
|
-
@position =
|
38
|
-
@new_name =
|
27
|
+
@position = params[:position] #: Hash[Symbol, Integer]
|
28
|
+
@new_name = params[:newName] #: String
|
39
29
|
end
|
40
30
|
|
41
|
-
|
31
|
+
# @override
|
32
|
+
#: -> Interface::WorkspaceEdit?
|
42
33
|
def perform
|
43
34
|
char_position, _ = @document.find_index_by_position(@position)
|
44
35
|
|
@@ -60,10 +51,7 @@ module RubyLsp
|
|
60
51
|
)
|
61
52
|
end
|
62
53
|
|
63
|
-
target =
|
64
|
-
target,
|
65
|
-
T.any(Prism::ConstantReadNode, Prism::ConstantPathNode, Prism::ConstantPathTargetNode),
|
66
|
-
)
|
54
|
+
target = target #: as Prism::ConstantReadNode | Prism::ConstantPathNode | Prism::ConstantPathTargetNode
|
67
55
|
|
68
56
|
name = RubyIndexer::Index.constant_name(target)
|
69
57
|
return unless name
|
@@ -72,10 +60,11 @@ module RubyLsp
|
|
72
60
|
return unless entries
|
73
61
|
|
74
62
|
if (conflict_entries = @global_state.index.resolve(@new_name, node_context.nesting))
|
75
|
-
raise InvalidNameError, "The new name is already in use by #{
|
63
|
+
raise InvalidNameError, "The new name is already in use by #{conflict_entries.first&.name}"
|
76
64
|
end
|
77
65
|
|
78
|
-
fully_qualified_name =
|
66
|
+
fully_qualified_name = entries.first #: as !nil
|
67
|
+
.name
|
79
68
|
reference_target = RubyIndexer::ReferenceFinder::ConstTarget.new(fully_qualified_name)
|
80
69
|
changes = collect_text_edits(reference_target, name)
|
81
70
|
|
@@ -100,20 +89,15 @@ module RubyLsp
|
|
100
89
|
|
101
90
|
private
|
102
91
|
|
103
|
-
|
104
|
-
params(
|
105
|
-
fully_qualified_name: String,
|
106
|
-
document_changes: T::Array[T.any(Interface::RenameFile, Interface::TextDocumentEdit)],
|
107
|
-
).void
|
108
|
-
end
|
92
|
+
#: (String fully_qualified_name, Array[(Interface::RenameFile | Interface::TextDocumentEdit)] document_changes) -> void
|
109
93
|
def collect_file_renames(fully_qualified_name, document_changes)
|
110
94
|
# Check if the declarations of the symbol being renamed match the file name. In case they do, we automatically
|
111
95
|
# rename the files for the user.
|
112
96
|
#
|
113
97
|
# We also look for an associated test file and rename it too
|
114
|
-
short_name =
|
98
|
+
short_name = fully_qualified_name.split("::").last #: as !nil
|
115
99
|
|
116
|
-
|
100
|
+
@global_state.index[fully_qualified_name]&.each do |entry|
|
117
101
|
# Do not rename files that are not part of the workspace
|
118
102
|
uri = entry.uri
|
119
103
|
file_path = uri.full_path
|
@@ -126,7 +110,9 @@ module RubyLsp
|
|
126
110
|
file_name = file_from_constant_name(short_name)
|
127
111
|
|
128
112
|
if "#{file_name}.rb" == entry.file_name
|
129
|
-
new_file_name = file_from_constant_name(
|
113
|
+
new_file_name = file_from_constant_name(
|
114
|
+
@new_name.split("::").last, #: as !nil
|
115
|
+
)
|
130
116
|
|
131
117
|
new_uri = URI::Generic.from_path(path: File.join(
|
132
118
|
File.dirname(file_path),
|
@@ -139,12 +125,7 @@ module RubyLsp
|
|
139
125
|
end
|
140
126
|
end
|
141
127
|
|
142
|
-
|
143
|
-
params(
|
144
|
-
target: RubyIndexer::ReferenceFinder::Target,
|
145
|
-
name: String,
|
146
|
-
).returns(T::Hash[String, T::Array[Interface::TextEdit]])
|
147
|
-
end
|
128
|
+
#: (RubyIndexer::ReferenceFinder::Target target, String name) -> Hash[String, Array[Interface::TextEdit]]
|
148
129
|
def collect_text_edits(target, name)
|
149
130
|
changes = {}
|
150
131
|
|
@@ -169,14 +150,7 @@ module RubyLsp
|
|
169
150
|
changes
|
170
151
|
end
|
171
152
|
|
172
|
-
|
173
|
-
params(
|
174
|
-
target: RubyIndexer::ReferenceFinder::Target,
|
175
|
-
parse_result: Prism::ParseResult,
|
176
|
-
name: String,
|
177
|
-
uri: URI::Generic,
|
178
|
-
).returns(T::Array[Interface::TextEdit])
|
179
|
-
end
|
153
|
+
#: (RubyIndexer::ReferenceFinder::Target target, Prism::ParseResult parse_result, String name, URI::Generic uri) -> Array[Interface::TextEdit]
|
180
154
|
def collect_changes(target, parse_result, name, uri)
|
181
155
|
dispatcher = Prism::Dispatcher.new
|
182
156
|
finder = RubyIndexer::ReferenceFinder.new(target, @global_state.index, dispatcher, uri)
|
@@ -187,7 +161,7 @@ module RubyLsp
|
|
187
161
|
end
|
188
162
|
end
|
189
163
|
|
190
|
-
|
164
|
+
#: (String name, RubyIndexer::ReferenceFinder::Reference reference) -> Interface::TextEdit
|
191
165
|
def adjust_reference_for_edit(name, reference)
|
192
166
|
# The reference may include a namespace in front. We need to check if the rename new name includes namespaces
|
193
167
|
# and then adjust both the text and the location to produce the correct edit
|
@@ -197,7 +171,7 @@ module RubyLsp
|
|
197
171
|
Interface::TextEdit.new(range: range_from_location(location), new_text: new_text)
|
198
172
|
end
|
199
173
|
|
200
|
-
|
174
|
+
#: (String constant_name) -> String
|
201
175
|
def file_from_constant_name(constant_name)
|
202
176
|
constant_name
|
203
177
|
.gsub(/([a-z])([A-Z])|([A-Z])([A-Z][a-z])/, '\1\3_\2\4')
|
@@ -4,8 +4,8 @@
|
|
4
4
|
module RubyLsp
|
5
5
|
module Requests
|
6
6
|
class Request
|
7
|
-
extend T::Sig
|
8
7
|
extend T::Generic
|
8
|
+
extend T::Sig
|
9
9
|
|
10
10
|
class InvalidFormatter < StandardError; end
|
11
11
|
|
@@ -18,13 +18,7 @@ module RubyLsp
|
|
18
18
|
|
19
19
|
# Signals to the client that the request should be delegated to the language server server for the host language
|
20
20
|
# in ERB files
|
21
|
-
|
22
|
-
params(
|
23
|
-
global_state: GlobalState,
|
24
|
-
document: Document[T.untyped],
|
25
|
-
char_position: Integer,
|
26
|
-
).void
|
27
|
-
end
|
21
|
+
#: (GlobalState global_state, Document[untyped] document, Integer char_position) -> void
|
28
22
|
def delegate_request_if_needed!(global_state, document, char_position)
|
29
23
|
if global_state.client_capabilities.supports_request_delegation &&
|
30
24
|
document.is_a?(ERBDocument) &&
|
@@ -34,7 +28,7 @@ module RubyLsp
|
|
34
28
|
end
|
35
29
|
|
36
30
|
# Checks if a location covers a position
|
37
|
-
|
31
|
+
#: (Prism::Location location, untyped position) -> bool
|
38
32
|
def cover?(location, position)
|
39
33
|
start_covered =
|
40
34
|
location.start_line - 1 < position[:line] ||
|
@@ -61,18 +55,13 @@ module RubyLsp
|
|
61
55
|
# # ^ Going to definition here should go to Foo::Bar
|
62
56
|
# #^ Going to definition here should go to Foo
|
63
57
|
# ```
|
64
|
-
|
65
|
-
params(
|
66
|
-
target: Prism::Node,
|
67
|
-
parent: Prism::Node,
|
68
|
-
position: T::Hash[Symbol, Integer],
|
69
|
-
).returns(Prism::Node)
|
70
|
-
end
|
58
|
+
#: (Prism::Node target, Prism::Node parent, Hash[Symbol, Integer] position) -> Prism::Node
|
71
59
|
def determine_target(target, parent, position)
|
72
60
|
return target unless parent.is_a?(Prism::ConstantPathNode)
|
73
61
|
|
74
|
-
target =
|
75
|
-
parent =
|
62
|
+
target = parent #: Prism::Node
|
63
|
+
parent = target #: as Prism::ConstantPathNode
|
64
|
+
.parent #: Prism::Node?
|
76
65
|
|
77
66
|
while parent && cover?(parent.location, position)
|
78
67
|
target = parent
|
@@ -83,7 +72,7 @@ module RubyLsp
|
|
83
72
|
end
|
84
73
|
|
85
74
|
# Checks if a given location covers the position requested
|
86
|
-
|
75
|
+
#: (Prism::Location? location, Hash[Symbol, untyped] position) -> bool
|
87
76
|
def covers_position?(location, position)
|
88
77
|
return false unless location
|
89
78
|
|
@@ -11,18 +11,18 @@ module RubyLsp
|
|
11
11
|
#
|
12
12
|
# Note that if using VSCode Neovim, you will need to be in Insert mode for this to work correctly.
|
13
13
|
class SelectionRanges < Request
|
14
|
-
extend T::Sig
|
15
14
|
include Support::Common
|
16
15
|
|
17
|
-
|
16
|
+
#: ((RubyDocument | ERBDocument) document) -> void
|
18
17
|
def initialize(document)
|
19
18
|
super()
|
20
19
|
@document = document
|
21
|
-
@ranges =
|
22
|
-
@stack =
|
20
|
+
@ranges = [] #: Array[Support::SelectionRange]
|
21
|
+
@stack = [] #: Array[Support::SelectionRange]
|
23
22
|
end
|
24
23
|
|
25
|
-
|
24
|
+
# @override
|
25
|
+
#: -> (Array[Support::SelectionRange] & Object)
|
26
26
|
def perform
|
27
27
|
# [node, parent]
|
28
28
|
queue = [[@document.parse_result.value, nil]]
|
@@ -32,7 +32,7 @@ module RubyLsp
|
|
32
32
|
next unless node
|
33
33
|
|
34
34
|
range = Support::SelectionRange.new(range: range_from_location(node.location), parent: parent)
|
35
|
-
|
35
|
+
queue.unshift(*node.child_nodes.map { |child| [child, range] })
|
36
36
|
@ranges.unshift(range)
|
37
37
|
end
|
38
38
|
|
@@ -9,12 +9,8 @@ module RubyLsp
|
|
9
9
|
# highlighting](https://microsoft.github.io/language-server-protocol/specification#textDocument_semanticTokens)
|
10
10
|
# request informs the editor of the correct token types to provide consistent and accurate highlighting for themes.
|
11
11
|
class SemanticHighlighting < Request
|
12
|
-
extend T::Sig
|
13
|
-
|
14
12
|
class << self
|
15
|
-
|
16
|
-
|
17
|
-
sig { returns(Interface::SemanticTokensRegistrationOptions) }
|
13
|
+
#: -> Interface::SemanticTokensRegistrationOptions
|
18
14
|
def provider
|
19
15
|
Interface::SemanticTokensRegistrationOptions.new(
|
20
16
|
document_selector: nil,
|
@@ -29,13 +25,7 @@ module RubyLsp
|
|
29
25
|
|
30
26
|
# The compute_delta method receives the current semantic tokens and the previous semantic tokens and then tries
|
31
27
|
# to compute the smallest possible semantic token edit that will turn previous into current
|
32
|
-
|
33
|
-
params(
|
34
|
-
current_tokens: T::Array[Integer],
|
35
|
-
previous_tokens: T::Array[Integer],
|
36
|
-
result_id: String,
|
37
|
-
).returns(Interface::SemanticTokensDelta)
|
38
|
-
end
|
28
|
+
#: (Array[Integer] current_tokens, Array[Integer] previous_tokens, String result_id) -> Interface::SemanticTokensDelta
|
39
29
|
def compute_delta(current_tokens, previous_tokens, result_id)
|
40
30
|
# Find the index of the first token that is different between the two sets of tokens
|
41
31
|
first_different_position = current_tokens.zip(previous_tokens).find_index { |new, old| new != old }
|
@@ -53,8 +43,8 @@ module RubyLsp
|
|
53
43
|
# Filter the tokens based on the first different position. This must happen at this stage, before we try to
|
54
44
|
# find the next position from the end or else we risk confusing sets of token that may have different lengths,
|
55
45
|
# but end with the exact same token
|
56
|
-
old_tokens =
|
57
|
-
new_tokens =
|
46
|
+
old_tokens = previous_tokens[first_different_position...] #: as !nil
|
47
|
+
new_tokens = current_tokens[first_different_position...] #: as !nil
|
58
48
|
|
59
49
|
# Then search from the end to find the first token that doesn't match. Since the user is normally editing the
|
60
50
|
# middle of the file, this will minimize the number of edits since the end of the token array has not changed
|
@@ -63,8 +53,8 @@ module RubyLsp
|
|
63
53
|
end || 0
|
64
54
|
|
65
55
|
# Filter the old and new tokens to only the section that will be replaced/inserted/deleted
|
66
|
-
old_tokens =
|
67
|
-
new_tokens =
|
56
|
+
old_tokens = old_tokens[...old_tokens.length - first_different_token_from_end] #: as !nil
|
57
|
+
new_tokens = new_tokens[...new_tokens.length - first_different_token_from_end] #: as !nil
|
68
58
|
|
69
59
|
# And we send back a single edit, replacing an entire section for the new tokens
|
70
60
|
Interface::SemanticTokensDelta.new(
|
@@ -73,7 +63,7 @@ module RubyLsp
|
|
73
63
|
)
|
74
64
|
end
|
75
65
|
|
76
|
-
|
66
|
+
#: -> Integer
|
77
67
|
def next_result_id
|
78
68
|
@mutex.synchronize do
|
79
69
|
@result_id += 1
|
@@ -81,29 +71,19 @@ module RubyLsp
|
|
81
71
|
end
|
82
72
|
end
|
83
73
|
|
84
|
-
@result_id =
|
85
|
-
@mutex =
|
86
|
-
|
87
|
-
|
88
|
-
params(
|
89
|
-
global_state: GlobalState,
|
90
|
-
dispatcher: Prism::Dispatcher,
|
91
|
-
document: T.any(RubyDocument, ERBDocument),
|
92
|
-
previous_result_id: T.nilable(String),
|
93
|
-
range: T.nilable(T::Range[Integer]),
|
94
|
-
).void
|
95
|
-
end
|
74
|
+
@result_id = 0 #: Integer
|
75
|
+
@mutex = Mutex.new #: Mutex
|
76
|
+
|
77
|
+
#: (GlobalState global_state, Prism::Dispatcher dispatcher, (RubyDocument | ERBDocument) document, String? previous_result_id, ?range: Range[Integer]?) -> void
|
96
78
|
def initialize(global_state, dispatcher, document, previous_result_id, range: nil)
|
97
79
|
super()
|
98
80
|
|
99
81
|
@document = document
|
100
82
|
@previous_result_id = previous_result_id
|
101
83
|
@range = range
|
102
|
-
@result_id =
|
103
|
-
@response_builder =
|
104
|
-
|
105
|
-
ResponseBuilders::SemanticHighlighting,
|
106
|
-
)
|
84
|
+
@result_id = SemanticHighlighting.next_result_id.to_s #: String
|
85
|
+
@response_builder = ResponseBuilders::SemanticHighlighting
|
86
|
+
.new(document.code_units_cache) #: ResponseBuilders::SemanticHighlighting
|
107
87
|
Listeners::SemanticHighlighting.new(dispatcher, @response_builder)
|
108
88
|
|
109
89
|
Addon.addons.each do |addon|
|
@@ -111,7 +91,8 @@ module RubyLsp
|
|
111
91
|
end
|
112
92
|
end
|
113
93
|
|
114
|
-
|
94
|
+
# @override
|
95
|
+
#: -> (Interface::SemanticTokens | Interface::SemanticTokensDelta)
|
115
96
|
def perform
|
116
97
|
previous_tokens = @document.semantic_tokens
|
117
98
|
tokens = @response_builder.response
|
@@ -7,17 +7,16 @@ module RubyLsp
|
|
7
7
|
# request](https://microsoft.github.io/language-server-protocol/specification#requestMessage) that displays the AST
|
8
8
|
# for the current document or for the current selection in a new tab.
|
9
9
|
class ShowSyntaxTree < Request
|
10
|
-
|
11
|
-
|
12
|
-
sig { params(document: RubyDocument, range: T.nilable(T::Hash[Symbol, T.untyped])).void }
|
10
|
+
#: (RubyDocument document, Hash[Symbol, untyped]? range) -> void
|
13
11
|
def initialize(document, range)
|
14
12
|
super()
|
15
13
|
@document = document
|
16
14
|
@range = range
|
17
|
-
@tree =
|
15
|
+
@tree = document.parse_result.value #: Prism::ProgramNode
|
18
16
|
end
|
19
17
|
|
20
|
-
|
18
|
+
# @override
|
19
|
+
#: -> String
|
21
20
|
def perform
|
22
21
|
return ast_for_range if @range
|
23
22
|
|
@@ -28,9 +27,9 @@ module RubyLsp
|
|
28
27
|
|
29
28
|
private
|
30
29
|
|
31
|
-
|
30
|
+
#: -> String
|
32
31
|
def ast_for_range
|
33
|
-
range =
|
32
|
+
range = @range #: as !nil
|
34
33
|
start_char, end_char = @document.find_index_by_position(range[:start], range[:end])
|
35
34
|
|
36
35
|
queue = @tree.statements.body.dup
|
@@ -47,7 +46,7 @@ module RubyLsp
|
|
47
46
|
if (start_char..end_char).cover?(loc.start_offset..loc.end_offset)
|
48
47
|
found_nodes << node
|
49
48
|
else
|
50
|
-
|
49
|
+
queue.unshift(*node.child_nodes)
|
51
50
|
end
|
52
51
|
end
|
53
52
|
|
@@ -9,12 +9,8 @@ module RubyLsp
|
|
9
9
|
# request](https://microsoft.github.io/language-server-protocol/specification#textDocument_signatureHelp) displays
|
10
10
|
# information about the parameters of a method as you type an invocation.
|
11
11
|
class SignatureHelp < Request
|
12
|
-
extend T::Sig
|
13
|
-
|
14
12
|
class << self
|
15
|
-
|
16
|
-
|
17
|
-
sig { returns(Interface::SignatureHelpOptions) }
|
13
|
+
#: -> Interface::SignatureHelpOptions
|
18
14
|
def provider
|
19
15
|
# Identifier characters are automatically included, such as A-Z, a-z, 0-9, _, * or :
|
20
16
|
Interface::SignatureHelpOptions.new(
|
@@ -23,16 +19,7 @@ module RubyLsp
|
|
23
19
|
end
|
24
20
|
end
|
25
21
|
|
26
|
-
|
27
|
-
params(
|
28
|
-
document: T.any(RubyDocument, ERBDocument),
|
29
|
-
global_state: GlobalState,
|
30
|
-
position: T::Hash[Symbol, T.untyped],
|
31
|
-
context: T.nilable(T::Hash[Symbol, T.untyped]),
|
32
|
-
dispatcher: Prism::Dispatcher,
|
33
|
-
sorbet_level: RubyDocument::SorbetLevel,
|
34
|
-
).void
|
35
|
-
end
|
22
|
+
#: ((RubyDocument | ERBDocument) document, GlobalState global_state, Hash[Symbol, untyped] position, Hash[Symbol, untyped]? context, Prism::Dispatcher dispatcher, SorbetLevel sorbet_level) -> void
|
36
23
|
def initialize(document, global_state, position, context, dispatcher, sorbet_level) # rubocop:disable Metrics/ParameterLists
|
37
24
|
super()
|
38
25
|
|
@@ -48,13 +35,14 @@ module RubyLsp
|
|
48
35
|
|
49
36
|
target = adjust_for_nested_target(node_context.node, node_context.parent, position)
|
50
37
|
|
51
|
-
@target =
|
38
|
+
@target = target #: Prism::Node?
|
52
39
|
@dispatcher = dispatcher
|
53
|
-
@response_builder =
|
40
|
+
@response_builder = ResponseBuilders::SignatureHelp.new #: ResponseBuilders::SignatureHelp
|
54
41
|
Listeners::SignatureHelp.new(@response_builder, global_state, node_context, dispatcher, sorbet_level)
|
55
42
|
end
|
56
43
|
|
57
|
-
|
44
|
+
# @override
|
45
|
+
#: -> Interface::SignatureHelp?
|
58
46
|
def perform
|
59
47
|
return unless @target
|
60
48
|
|
@@ -70,13 +58,7 @@ module RubyLsp
|
|
70
58
|
# foo(another_method_call)
|
71
59
|
#
|
72
60
|
# In that case, we want to provide signature help for `foo` and not `another_method_call`.
|
73
|
-
|
74
|
-
params(
|
75
|
-
target: T.nilable(Prism::Node),
|
76
|
-
parent: T.nilable(Prism::Node),
|
77
|
-
position: T::Hash[Symbol, T.untyped],
|
78
|
-
).returns(T.nilable(Prism::Node))
|
79
|
-
end
|
61
|
+
#: (Prism::Node? target, Prism::Node? parent, Hash[Symbol, untyped] position) -> Prism::Node?
|
80
62
|
def adjust_for_nested_target(target, parent, position)
|
81
63
|
# If the parent node is not a method call, then make no adjustments
|
82
64
|
return target unless parent.is_a?(Prism::CallNode)
|
@@ -92,7 +74,7 @@ module RubyLsp
|
|
92
74
|
arguments.nil? || !node_covers?(arguments, position) ? parent : target
|
93
75
|
end
|
94
76
|
|
95
|
-
|
77
|
+
#: (Prism::Node node, Hash[Symbol, untyped] position) -> bool
|
96
78
|
def node_covers?(node, position)
|
97
79
|
location = node.location
|
98
80
|
start_line = location.start_line - 1
|
@@ -5,32 +5,26 @@ module RubyLsp
|
|
5
5
|
module Requests
|
6
6
|
module Support
|
7
7
|
class Annotation
|
8
|
-
|
9
|
-
sig do
|
10
|
-
params(
|
11
|
-
arity: T.any(Integer, T::Range[Integer]),
|
12
|
-
receiver: T::Boolean,
|
13
|
-
).void
|
14
|
-
end
|
8
|
+
#: (arity: (Integer | Range[Integer]), ?receiver: bool) -> void
|
15
9
|
def initialize(arity:, receiver: false)
|
16
10
|
@arity = arity
|
17
11
|
@receiver = receiver
|
18
12
|
end
|
19
13
|
|
20
|
-
|
14
|
+
#: (Prism::CallNode node) -> bool
|
21
15
|
def match?(node)
|
22
16
|
receiver_matches?(node) && arity_matches?(node)
|
23
17
|
end
|
24
18
|
|
25
19
|
private
|
26
20
|
|
27
|
-
|
21
|
+
#: (Prism::CallNode node) -> bool
|
28
22
|
def receiver_matches?(node)
|
29
23
|
node_receiver = node.receiver
|
30
24
|
(node_receiver && @receiver && node_receiver.location.slice == "T") || (!node_receiver && !@receiver)
|
31
25
|
end
|
32
26
|
|
33
|
-
|
27
|
+
#: (Prism::CallNode node) -> bool
|
34
28
|
def arity_matches?(node)
|
35
29
|
node_arity = node.arguments&.arguments&.size || 0
|
36
30
|
|