ruby-lsp 0.23.16 → 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/VERSION +1 -1
- data/lib/ruby_indexer/lib/ruby_indexer/declaration_listener.rb +16 -19
- data/lib/ruby_indexer/lib/ruby_indexer/enhancement.rb +0 -3
- data/lib/ruby_indexer/lib/ruby_indexer/entry.rb +9 -19
- data/lib/ruby_indexer/lib/ruby_indexer/index.rb +32 -68
- data/lib/ruby_indexer/lib/ruby_indexer/rbs_indexer.rb +1 -10
- data/lib/ruby_indexer/lib/ruby_indexer/visibility_scope.rb +4 -4
- data/lib/ruby_indexer/test/index_test.rb +7 -0
- data/lib/ruby_indexer/test/method_test.rb +7 -7
- data/lib/ruby_indexer/test/rbs_indexer_test.rb +4 -3
- data/lib/ruby_indexer/test/test_case.rb +7 -1
- data/lib/ruby_lsp/document.rb +1 -9
- data/lib/ruby_lsp/erb_document.rb +2 -2
- data/lib/ruby_lsp/listeners/completion.rb +8 -8
- data/lib/ruby_lsp/listeners/definition.rb +7 -7
- data/lib/ruby_lsp/listeners/document_link.rb +7 -10
- data/lib/ruby_lsp/listeners/hover.rb +10 -9
- data/lib/ruby_lsp/listeners/signature_help.rb +2 -2
- data/lib/ruby_lsp/listeners/spec_style.rb +11 -11
- data/lib/ruby_lsp/listeners/test_style.rb +10 -5
- data/lib/ruby_lsp/rbs_document.rb +2 -2
- data/lib/ruby_lsp/requests/code_action_resolve.rb +44 -39
- data/lib/ruby_lsp/requests/code_lens.rb +15 -3
- data/lib/ruby_lsp/requests/completion.rb +2 -2
- data/lib/ruby_lsp/requests/definition.rb +3 -4
- data/lib/ruby_lsp/requests/document_highlight.rb +1 -1
- data/lib/ruby_lsp/requests/document_link.rb +1 -1
- data/lib/ruby_lsp/requests/folding_ranges.rb +1 -1
- data/lib/ruby_lsp/requests/go_to_relevant_file.rb +0 -2
- data/lib/ruby_lsp/requests/hover.rb +1 -1
- data/lib/ruby_lsp/requests/inlay_hints.rb +1 -1
- data/lib/ruby_lsp/requests/references.rb +1 -16
- data/lib/ruby_lsp/requests/rename.rb +1 -4
- data/lib/ruby_lsp/requests/request.rb +2 -1
- data/lib/ruby_lsp/requests/semantic_highlighting.rb +1 -1
- data/lib/ruby_lsp/requests/signature_help.rb +1 -1
- data/lib/ruby_lsp/requests/support/annotation.rb +1 -1
- data/lib/ruby_lsp/requests/support/common.rb +0 -5
- data/lib/ruby_lsp/requests/support/test_item.rb +6 -0
- data/lib/ruby_lsp/response_builders/document_symbol.rb +1 -1
- data/lib/ruby_lsp/response_builders/test_collection.rb +37 -0
- data/lib/ruby_lsp/ruby_document.rb +2 -32
- data/lib/ruby_lsp/server.rb +36 -21
- data/lib/ruby_lsp/store.rb +6 -6
- data/lib/ruby_lsp/test_reporters/lsp_reporter.rb +31 -4
- data/lib/ruby_lsp/utils.rb +43 -0
- metadata +1 -1
@@ -50,7 +50,7 @@ module RubyLsp
|
|
50
50
|
"__LINE__",
|
51
51
|
].freeze
|
52
52
|
|
53
|
-
#: (ResponseBuilders::CollectionResponseBuilder[Interface::CompletionItem] response_builder, GlobalState global_state, NodeContext node_context,
|
53
|
+
#: (ResponseBuilders::CollectionResponseBuilder[Interface::CompletionItem] response_builder, GlobalState global_state, NodeContext node_context, SorbetLevel sorbet_level, Prism::Dispatcher dispatcher, URI::Generic uri, String? trigger_character) -> void
|
54
54
|
def initialize( # rubocop:disable Metrics/ParameterLists
|
55
55
|
response_builder,
|
56
56
|
global_state,
|
@@ -100,7 +100,7 @@ module RubyLsp
|
|
100
100
|
def on_constant_read_node_enter(node)
|
101
101
|
# The only scenario where Sorbet doesn't provide constant completion is on ignored files. Even if the file has
|
102
102
|
# no sigil, Sorbet will still provide completion for constants
|
103
|
-
return
|
103
|
+
return unless @sorbet_level.ignore?
|
104
104
|
|
105
105
|
name = RubyIndexer::Index.constant_name(node)
|
106
106
|
return if name.nil?
|
@@ -125,7 +125,7 @@ module RubyLsp
|
|
125
125
|
def on_constant_path_node_enter(node)
|
126
126
|
# The only scenario where Sorbet doesn't provide constant completion is on ignored files. Even if the file has
|
127
127
|
# no sigil, Sorbet will still provide completion for constants
|
128
|
-
return
|
128
|
+
return unless @sorbet_level.ignore?
|
129
129
|
|
130
130
|
name = begin
|
131
131
|
node.full_name
|
@@ -143,7 +143,7 @@ module RubyLsp
|
|
143
143
|
def on_call_node_enter(node)
|
144
144
|
# The only scenario where Sorbet doesn't provide constant completion is on ignored files. Even if the file has
|
145
145
|
# no sigil, Sorbet will still provide completion for constants
|
146
|
-
if @sorbet_level
|
146
|
+
if @sorbet_level.ignore?
|
147
147
|
receiver = node.receiver
|
148
148
|
|
149
149
|
# When writing `Foo::`, the AST assigns a method call node (because you can use that syntax to invoke
|
@@ -390,7 +390,7 @@ module RubyLsp
|
|
390
390
|
def handle_instance_variable_completion(name, location)
|
391
391
|
# Sorbet enforces that all instance variables be declared on typed strict or higher, which means it will be able
|
392
392
|
# to provide all features for them
|
393
|
-
return if @sorbet_level
|
393
|
+
return if @sorbet_level.strict?
|
394
394
|
|
395
395
|
type = @type_inferrer.infer_receiver_type(@node_context)
|
396
396
|
return unless type
|
@@ -475,13 +475,13 @@ module RubyLsp
|
|
475
475
|
def complete_methods(node, name)
|
476
476
|
# If the node has a receiver, then we don't need to provide local nor keyword completions. Sorbet can provide
|
477
477
|
# local and keyword completion for any file with a Sorbet level of true or higher
|
478
|
-
if
|
478
|
+
if !@sorbet_level.true_or_higher? && !node.receiver
|
479
479
|
add_local_completions(node, name)
|
480
480
|
add_keyword_completions(node, name)
|
481
481
|
end
|
482
482
|
|
483
483
|
# Sorbet can provide completion for methods invoked on self on typed true or higher files
|
484
|
-
return if
|
484
|
+
return if @sorbet_level.true_or_higher? && self_receiver?(node)
|
485
485
|
|
486
486
|
type = @type_inferrer.infer_receiver_type(@node_context)
|
487
487
|
return unless type
|
@@ -512,7 +512,7 @@ module RubyLsp
|
|
512
512
|
external_references = @node_context.fully_qualified_name != type.name
|
513
513
|
|
514
514
|
@index.method_completion_candidates(method_name, type.name).each do |entry|
|
515
|
-
next if entry.visibility !=
|
515
|
+
next if entry.visibility != :public && external_references
|
516
516
|
|
517
517
|
entry_name = entry.name
|
518
518
|
owner_name = entry.owner&.name
|
@@ -8,7 +8,7 @@ module RubyLsp
|
|
8
8
|
|
9
9
|
MAX_NUMBER_OF_DEFINITION_CANDIDATES_WITHOUT_RECEIVER = 10
|
10
10
|
|
11
|
-
#: (ResponseBuilders::CollectionResponseBuilder[(Interface::Location | Interface::LocationLink)] response_builder, GlobalState global_state,
|
11
|
+
#: (ResponseBuilders::CollectionResponseBuilder[(Interface::Location | Interface::LocationLink)] response_builder, GlobalState global_state, Symbol language_id, URI::Generic uri, NodeContext node_context, Prism::Dispatcher dispatcher, SorbetLevel sorbet_level) -> void
|
12
12
|
def initialize(response_builder, global_state, language_id, uri, node_context, dispatcher, sorbet_level) # rubocop:disable Metrics/ParameterLists
|
13
13
|
@response_builder = response_builder
|
14
14
|
@global_state = global_state
|
@@ -53,7 +53,7 @@ module RubyLsp
|
|
53
53
|
#: (Prism::CallNode node) -> void
|
54
54
|
def on_call_node_enter(node)
|
55
55
|
# Sorbet can handle go to definition for methods invoked on self on typed true or higher
|
56
|
-
return if
|
56
|
+
return if @sorbet_level.true_or_higher? && self_receiver?(node)
|
57
57
|
|
58
58
|
message = node.message
|
59
59
|
return unless message
|
@@ -62,7 +62,7 @@ module RubyLsp
|
|
62
62
|
|
63
63
|
# Until we can properly infer the receiver type in erb files (maybe with ruby-lsp-rails),
|
64
64
|
# treating method calls' type as `nil` will allow users to get some completion support first
|
65
|
-
if @language_id ==
|
65
|
+
if @language_id == :erb && inferrer_receiver_type&.name == "Object"
|
66
66
|
inferrer_receiver_type = nil
|
67
67
|
end
|
68
68
|
|
@@ -223,7 +223,7 @@ module RubyLsp
|
|
223
223
|
#: -> void
|
224
224
|
def handle_super_node_definition
|
225
225
|
# Sorbet can handle super hover on typed true or higher
|
226
|
-
return if
|
226
|
+
return if @sorbet_level.true_or_higher?
|
227
227
|
|
228
228
|
surrounding_method = @node_context.surrounding_method
|
229
229
|
return unless surrounding_method
|
@@ -276,7 +276,7 @@ module RubyLsp
|
|
276
276
|
def handle_instance_variable_definition(name)
|
277
277
|
# Sorbet enforces that all instance variables be declared on typed strict or higher, which means it will be able
|
278
278
|
# to provide all features for them
|
279
|
-
return if @sorbet_level
|
279
|
+
return if @sorbet_level.strict?
|
280
280
|
|
281
281
|
type = @type_inferrer.infer_receiver_type(@node_context)
|
282
282
|
return unless type
|
@@ -317,7 +317,7 @@ module RubyLsp
|
|
317
317
|
methods.each do |target_method|
|
318
318
|
uri = target_method.uri
|
319
319
|
full_path = uri.full_path
|
320
|
-
next if
|
320
|
+
next if @sorbet_level.true_or_higher? && (!full_path || not_in_dependencies?(full_path))
|
321
321
|
|
322
322
|
@response_builder << Interface::LocationLink.new(
|
323
323
|
target_uri: uri.to_s,
|
@@ -392,7 +392,7 @@ module RubyLsp
|
|
392
392
|
uri = entry.uri
|
393
393
|
full_path = uri.full_path
|
394
394
|
|
395
|
-
if
|
395
|
+
if !@sorbet_level.ignore? && (!full_path || not_in_dependencies?(full_path))
|
396
396
|
next
|
397
397
|
end
|
398
398
|
|
@@ -105,16 +105,13 @@ module RubyLsp
|
|
105
105
|
match = comment.location.slice.match(%r{source://.*#\d+$})
|
106
106
|
return unless match
|
107
107
|
|
108
|
-
uri =
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
end,
|
116
|
-
T.nilable(URI::Source),
|
117
|
-
)
|
108
|
+
uri = begin
|
109
|
+
URI(
|
110
|
+
match[0], #: as !nil
|
111
|
+
)
|
112
|
+
rescue URI::Error
|
113
|
+
nil
|
114
|
+
end #: as URI::Source?
|
118
115
|
return unless uri
|
119
116
|
|
120
117
|
gem_version = resolve_version(uri)
|
@@ -42,7 +42,7 @@ module RubyLsp
|
|
42
42
|
"https://gitlab.com",
|
43
43
|
].freeze #: Array[String]
|
44
44
|
|
45
|
-
#: (ResponseBuilders::Hover response_builder, GlobalState global_state, URI::Generic uri, NodeContext node_context, Prism::Dispatcher dispatcher,
|
45
|
+
#: (ResponseBuilders::Hover response_builder, GlobalState global_state, URI::Generic uri, NodeContext node_context, Prism::Dispatcher dispatcher, SorbetLevel sorbet_level) -> void
|
46
46
|
def initialize(response_builder, global_state, uri, node_context, dispatcher, sorbet_level) # rubocop:disable Metrics/ParameterLists
|
47
47
|
@response_builder = response_builder
|
48
48
|
@global_state = global_state
|
@@ -96,7 +96,7 @@ module RubyLsp
|
|
96
96
|
|
97
97
|
#: (Prism::ConstantReadNode node) -> void
|
98
98
|
def on_constant_read_node_enter(node)
|
99
|
-
return
|
99
|
+
return unless @sorbet_level.ignore?
|
100
100
|
|
101
101
|
name = RubyIndexer::Index.constant_name(node)
|
102
102
|
return if name.nil?
|
@@ -106,14 +106,14 @@ module RubyLsp
|
|
106
106
|
|
107
107
|
#: (Prism::ConstantWriteNode node) -> void
|
108
108
|
def on_constant_write_node_enter(node)
|
109
|
-
return
|
109
|
+
return unless @sorbet_level.ignore?
|
110
110
|
|
111
111
|
generate_hover(node.name.to_s, node.name_loc)
|
112
112
|
end
|
113
113
|
|
114
114
|
#: (Prism::ConstantPathNode node) -> void
|
115
115
|
def on_constant_path_node_enter(node)
|
116
|
-
return
|
116
|
+
return unless @sorbet_level.ignore?
|
117
117
|
|
118
118
|
name = RubyIndexer::Index.constant_name(node)
|
119
119
|
return if name.nil?
|
@@ -128,7 +128,7 @@ module RubyLsp
|
|
128
128
|
return
|
129
129
|
end
|
130
130
|
|
131
|
-
return if
|
131
|
+
return if @sorbet_level.true_or_higher? && self_receiver?(node)
|
132
132
|
|
133
133
|
message = node.message
|
134
134
|
return unless message
|
@@ -283,7 +283,7 @@ module RubyLsp
|
|
283
283
|
#: -> void
|
284
284
|
def handle_super_node_hover
|
285
285
|
# Sorbet can handle super hover on typed true or higher
|
286
|
-
return if
|
286
|
+
return if @sorbet_level.true_or_higher?
|
287
287
|
|
288
288
|
surrounding_method = @node_context.surrounding_method
|
289
289
|
return unless surrounding_method
|
@@ -318,7 +318,7 @@ module RubyLsp
|
|
318
318
|
def handle_instance_variable_hover(name)
|
319
319
|
# Sorbet enforces that all instance variables be declared on typed strict or higher, which means it will be able
|
320
320
|
# to provide all features for them
|
321
|
-
return if @sorbet_level
|
321
|
+
return if @sorbet_level.strict?
|
322
322
|
|
323
323
|
type = @type_inferrer.infer_receiver_type(@node_context)
|
324
324
|
return unless type
|
@@ -366,9 +366,10 @@ module RubyLsp
|
|
366
366
|
# We should only show hover for private constants if the constant is defined in the same namespace as the
|
367
367
|
# reference
|
368
368
|
first_entry = entries.first #: as !nil
|
369
|
-
|
369
|
+
full_name = first_entry.name
|
370
|
+
return if first_entry.private? && full_name != "#{@node_context.fully_qualified_name}::#{name}"
|
370
371
|
|
371
|
-
categorized_markdown_from_index_entries(
|
372
|
+
categorized_markdown_from_index_entries(full_name, entries).each do |category, content|
|
372
373
|
@response_builder.push(content, category: category)
|
373
374
|
end
|
374
375
|
end
|
@@ -6,7 +6,7 @@ module RubyLsp
|
|
6
6
|
class SignatureHelp
|
7
7
|
include Requests::Support::Common
|
8
8
|
|
9
|
-
#: (ResponseBuilders::SignatureHelp response_builder, GlobalState global_state, NodeContext node_context, Prism::Dispatcher dispatcher,
|
9
|
+
#: (ResponseBuilders::SignatureHelp response_builder, GlobalState global_state, NodeContext node_context, Prism::Dispatcher dispatcher, SorbetLevel sorbet_level) -> void
|
10
10
|
def initialize(response_builder, global_state, node_context, dispatcher, sorbet_level)
|
11
11
|
@sorbet_level = sorbet_level
|
12
12
|
@response_builder = response_builder
|
@@ -19,7 +19,7 @@ module RubyLsp
|
|
19
19
|
|
20
20
|
#: (Prism::CallNode node) -> void
|
21
21
|
def on_call_node_enter(node)
|
22
|
-
return if
|
22
|
+
return if @sorbet_level.true_or_higher?
|
23
23
|
|
24
24
|
message = node.message
|
25
25
|
return unless message
|
@@ -4,9 +4,7 @@
|
|
4
4
|
module RubyLsp
|
5
5
|
module Listeners
|
6
6
|
class SpecStyle < TestDiscovery
|
7
|
-
|
8
|
-
|
9
|
-
#: (response_builder: ResponseBuilders::TestCollection, global_state: GlobalState, dispatcher: Prism::Dispatcher, uri: URI::Generic) -> void
|
7
|
+
#: (ResponseBuilders::TestCollection, GlobalState, Prism::Dispatcher, URI::Generic) -> void
|
10
8
|
def initialize(response_builder, global_state, dispatcher, uri)
|
11
9
|
super
|
12
10
|
|
@@ -22,7 +20,7 @@ module RubyLsp
|
|
22
20
|
)
|
23
21
|
end
|
24
22
|
|
25
|
-
#: (
|
23
|
+
#: (Prism::ClassNode) -> void
|
26
24
|
def on_class_node_enter(node)
|
27
25
|
with_test_ancestor_tracking(node) do |_, ancestors|
|
28
26
|
is_spec = ancestors.include?("Minitest::Spec")
|
@@ -30,14 +28,14 @@ module RubyLsp
|
|
30
28
|
end
|
31
29
|
end
|
32
30
|
|
33
|
-
#: (
|
31
|
+
#: (Prism::ClassNode) -> void
|
34
32
|
def on_class_node_leave(node) # rubocop:disable RubyLsp/UseRegisterWithHandlerMethod
|
35
33
|
super
|
36
34
|
|
37
35
|
@spec_class_stack.pop
|
38
36
|
end
|
39
37
|
|
40
|
-
#: (
|
38
|
+
#: (Prism::CallNode) -> void
|
41
39
|
def on_call_node_enter(node)
|
42
40
|
case node.name
|
43
41
|
when :describe
|
@@ -47,7 +45,7 @@ module RubyLsp
|
|
47
45
|
end
|
48
46
|
end
|
49
47
|
|
50
|
-
#: (
|
48
|
+
#: (Prism::CallNode) -> void
|
51
49
|
def on_call_node_leave(node)
|
52
50
|
return unless node.name == :describe && !node.receiver
|
53
51
|
|
@@ -56,7 +54,7 @@ module RubyLsp
|
|
56
54
|
|
57
55
|
private
|
58
56
|
|
59
|
-
#: (
|
57
|
+
#: (Prism::CallNode) -> void
|
60
58
|
def handle_describe(node)
|
61
59
|
return if node.block.nil?
|
62
60
|
|
@@ -74,6 +72,7 @@ module RubyLsp
|
|
74
72
|
framework: :minitest,
|
75
73
|
)
|
76
74
|
@response_builder.add(test_item)
|
75
|
+
@response_builder.add_code_lens(test_item)
|
77
76
|
else
|
78
77
|
add_to_parent_test_group(description, node)
|
79
78
|
end
|
@@ -81,7 +80,7 @@ module RubyLsp
|
|
81
80
|
@describe_block_nesting << description
|
82
81
|
end
|
83
82
|
|
84
|
-
#: (
|
83
|
+
#: (Prism::CallNode) -> void
|
85
84
|
def handle_example(node)
|
86
85
|
return unless in_spec_context?
|
87
86
|
|
@@ -93,7 +92,7 @@ module RubyLsp
|
|
93
92
|
add_to_parent_test_group(description, node)
|
94
93
|
end
|
95
94
|
|
96
|
-
#: (
|
95
|
+
#: (String, Prism::CallNode) -> void
|
97
96
|
def add_to_parent_test_group(description, node)
|
98
97
|
parent_test_group = find_parent_test_group
|
99
98
|
return unless parent_test_group
|
@@ -106,6 +105,7 @@ module RubyLsp
|
|
106
105
|
framework: :minitest,
|
107
106
|
)
|
108
107
|
parent_test_group.add(test_item)
|
108
|
+
@response_builder.add_code_lens(test_item)
|
109
109
|
end
|
110
110
|
|
111
111
|
#: -> Requests::Support::TestItem?
|
@@ -129,7 +129,7 @@ module RubyLsp
|
|
129
129
|
test_group
|
130
130
|
end
|
131
131
|
|
132
|
-
#: (
|
132
|
+
#: (Prism::CallNode) -> String?
|
133
133
|
def extract_description(node)
|
134
134
|
first_argument = node.arguments&.arguments&.first
|
135
135
|
return unless first_argument
|
@@ -143,7 +143,7 @@ module RubyLsp
|
|
143
143
|
"ruby"
|
144
144
|
end #: String
|
145
145
|
|
146
|
-
#: (ResponseBuilders::TestCollection
|
146
|
+
#: (ResponseBuilders::TestCollection, GlobalState, Prism::Dispatcher, URI::Generic) -> void
|
147
147
|
def initialize(response_builder, global_state, dispatcher, uri)
|
148
148
|
super
|
149
149
|
|
@@ -165,13 +165,16 @@ module RubyLsp
|
|
165
165
|
@framework = :test_unit if ancestors.include?("Test::Unit::TestCase")
|
166
166
|
|
167
167
|
if @framework == :test_unit || non_declarative_minitest?(ancestors, name)
|
168
|
-
|
168
|
+
test_item = Requests::Support::TestItem.new(
|
169
169
|
name,
|
170
170
|
name,
|
171
171
|
@uri,
|
172
172
|
range_from_node(node),
|
173
173
|
framework: @framework,
|
174
|
-
)
|
174
|
+
)
|
175
|
+
|
176
|
+
@response_builder.add(test_item)
|
177
|
+
@response_builder.add_code_lens(test_item)
|
175
178
|
end
|
176
179
|
end
|
177
180
|
end
|
@@ -191,13 +194,15 @@ module RubyLsp
|
|
191
194
|
test_item = @response_builder[current_group_name]
|
192
195
|
return unless test_item
|
193
196
|
|
194
|
-
|
197
|
+
example_item = Requests::Support::TestItem.new(
|
195
198
|
"#{current_group_name}##{name}",
|
196
199
|
name,
|
197
200
|
@uri,
|
198
201
|
range_from_node(node),
|
199
202
|
framework: @framework,
|
200
|
-
)
|
203
|
+
)
|
204
|
+
test_item.add(example_item)
|
205
|
+
@response_builder.add_code_lens(test_item)
|
201
206
|
end
|
202
207
|
|
203
208
|
#: (Prism::CallNode node) -> void
|
@@ -13,14 +13,9 @@ module RubyLsp
|
|
13
13
|
NEW_METHOD_NAME = "new_method"
|
14
14
|
|
15
15
|
class CodeActionError < StandardError; end
|
16
|
-
|
17
|
-
class
|
18
|
-
|
19
|
-
EmptySelection = new
|
20
|
-
InvalidTargetRange = new
|
21
|
-
UnknownCodeAction = new
|
22
|
-
end
|
23
|
-
end
|
16
|
+
class EmptySelectionError < CodeActionError; end
|
17
|
+
class InvalidTargetRangeError < CodeActionError; end
|
18
|
+
class UnknownCodeActionError < CodeActionError; end
|
24
19
|
|
25
20
|
#: (RubyDocument document, GlobalState global_state, Hash[Symbol, untyped] code_action) -> void
|
26
21
|
def initialize(document, global_state, code_action)
|
@@ -31,9 +26,9 @@ module RubyLsp
|
|
31
26
|
end
|
32
27
|
|
33
28
|
# @override
|
34
|
-
#: -> (Interface::CodeAction
|
29
|
+
#: -> (Interface::CodeAction)
|
35
30
|
def perform
|
36
|
-
|
31
|
+
raise EmptySelectionError, "Invalid selection for refactor" if @document.source.empty?
|
37
32
|
|
38
33
|
case @code_action[:title]
|
39
34
|
when CodeActions::EXTRACT_TO_VARIABLE_TITLE
|
@@ -47,26 +42,30 @@ module RubyLsp
|
|
47
42
|
CodeActions::CREATE_ATTRIBUTE_ACCESSOR
|
48
43
|
create_attribute_accessor
|
49
44
|
else
|
50
|
-
|
45
|
+
raise UnknownCodeActionError, "Unknown code action: #{@code_action[:title]}"
|
51
46
|
end
|
52
47
|
end
|
53
48
|
|
54
49
|
private
|
55
50
|
|
56
|
-
#: -> (Interface::CodeAction
|
51
|
+
#: -> (Interface::CodeAction)
|
57
52
|
def switch_block_style
|
58
53
|
source_range = @code_action.dig(:data, :range)
|
59
|
-
|
54
|
+
raise EmptySelectionError, "Invalid selection for refactor" if source_range[:start] == source_range[:end]
|
60
55
|
|
61
56
|
target = @document.locate_first_within_range(
|
62
57
|
@code_action.dig(:data, :range),
|
63
58
|
node_types: [Prism::CallNode],
|
64
59
|
)
|
65
60
|
|
66
|
-
|
61
|
+
unless target.is_a?(Prism::CallNode)
|
62
|
+
raise InvalidTargetRangeError, "Couldn't find an appropriate location to place extracted refactor"
|
63
|
+
end
|
67
64
|
|
68
65
|
node = target.block
|
69
|
-
|
66
|
+
unless node.is_a?(Prism::BlockNode)
|
67
|
+
raise InvalidTargetRangeError, "Couldn't find an appropriate location to place extracted refactor"
|
68
|
+
end
|
70
69
|
|
71
70
|
indentation = " " * target.location.start_column unless node.opening_loc.slice == "do"
|
72
71
|
|
@@ -91,10 +90,10 @@ module RubyLsp
|
|
91
90
|
)
|
92
91
|
end
|
93
92
|
|
94
|
-
#: -> (Interface::CodeAction
|
93
|
+
#: -> (Interface::CodeAction)
|
95
94
|
def refactor_variable
|
96
95
|
source_range = @code_action.dig(:data, :range)
|
97
|
-
|
96
|
+
raise EmptySelectionError, "Invalid selection for refactor" if source_range[:start] == source_range[:end]
|
98
97
|
|
99
98
|
start_index, end_index = @document.find_index_by_position(source_range[:start], source_range[:end])
|
100
99
|
extracted_source = @document.source[start_index...end_index] #: as !nil
|
@@ -111,7 +110,9 @@ module RubyLsp
|
|
111
110
|
|
112
111
|
closest_statements = node_context.node
|
113
112
|
parent_statements = node_context.parent
|
114
|
-
|
113
|
+
if closest_statements.nil? || closest_statements.child_nodes.compact.empty?
|
114
|
+
raise InvalidTargetRangeError, "Couldn't find an appropriate location to place extracted refactor"
|
115
|
+
end
|
115
116
|
|
116
117
|
# Find the node with the end line closest to the requested position, so that we can place the refactor
|
117
118
|
# immediately after that closest node
|
@@ -120,7 +121,9 @@ module RubyLsp
|
|
120
121
|
distance <= 0 ? Float::INFINITY : distance
|
121
122
|
end #: as !nil
|
122
123
|
|
123
|
-
|
124
|
+
if closest_node.is_a?(Prism::MissingNode)
|
125
|
+
raise InvalidTargetRangeError, "Couldn't find an appropriate location to place extracted refactor"
|
126
|
+
end
|
124
127
|
|
125
128
|
closest_node_loc = closest_node.location
|
126
129
|
# If the parent expression is a single line block, then we have to extract it inside of the one-line block
|
@@ -151,7 +154,9 @@ module RubyLsp
|
|
151
154
|
lines = @document.source.lines
|
152
155
|
|
153
156
|
indentation_line = lines[indentation_line_number]
|
154
|
-
|
157
|
+
unless indentation_line
|
158
|
+
raise InvalidTargetRangeError, "Couldn't find an appropriate location to place extracted refactor"
|
159
|
+
end
|
155
160
|
|
156
161
|
indentation = indentation_line[/\A */] #: as !nil
|
157
162
|
.size
|
@@ -162,7 +167,9 @@ module RubyLsp
|
|
162
167
|
}
|
163
168
|
|
164
169
|
line = lines[target_line]
|
165
|
-
|
170
|
+
unless line
|
171
|
+
raise InvalidTargetRangeError, "Couldn't find an appropriate location to place extracted refactor"
|
172
|
+
end
|
166
173
|
|
167
174
|
variable_source = if line.strip.empty?
|
168
175
|
"\n#{" " * indentation}#{NEW_VARIABLE_NAME} = #{extracted_source}"
|
@@ -190,10 +197,10 @@ module RubyLsp
|
|
190
197
|
)
|
191
198
|
end
|
192
199
|
|
193
|
-
#: -> (Interface::CodeAction
|
200
|
+
#: -> (Interface::CodeAction)
|
194
201
|
def refactor_method
|
195
202
|
source_range = @code_action.dig(:data, :range)
|
196
|
-
|
203
|
+
raise EmptySelectionError, "Invalid selection for refactor" if source_range[:start] == source_range[:end]
|
197
204
|
|
198
205
|
start_index, end_index = @document.find_index_by_position(source_range[:start], source_range[:end])
|
199
206
|
extracted_source = @document.source[start_index...end_index] #: as !nil
|
@@ -206,11 +213,15 @@ module RubyLsp
|
|
206
213
|
code_units_cache: @document.code_units_cache,
|
207
214
|
)
|
208
215
|
closest_node = node_context.node
|
209
|
-
|
216
|
+
unless closest_node
|
217
|
+
raise InvalidTargetRangeError, "Couldn't find an appropriate location to place extracted refactor"
|
218
|
+
end
|
210
219
|
|
211
220
|
target_range = if closest_node.is_a?(Prism::DefNode)
|
212
221
|
end_keyword_loc = closest_node.end_keyword_loc
|
213
|
-
|
222
|
+
unless end_keyword_loc
|
223
|
+
raise InvalidTargetRangeError, "Couldn't find an appropriate location to place extracted refactor"
|
224
|
+
end
|
214
225
|
|
215
226
|
end_line = end_keyword_loc.end_line - 1
|
216
227
|
character = end_keyword_loc.end_column
|
@@ -331,7 +342,7 @@ module RubyLsp
|
|
331
342
|
indentation ? body_content.gsub(";", "\n") : "#{body_content.gsub("\n", ";")} "
|
332
343
|
end
|
333
344
|
|
334
|
-
#: -> (Interface::CodeAction
|
345
|
+
#: -> (Interface::CodeAction)
|
335
346
|
def create_attribute_accessor
|
336
347
|
source_range = @code_action.dig(:data, :range)
|
337
348
|
|
@@ -349,20 +360,12 @@ module RubyLsp
|
|
349
360
|
)
|
350
361
|
node = node_context.node
|
351
362
|
|
352
|
-
|
363
|
+
unless CodeActions::INSTANCE_VARIABLE_NODES.include?(node.class)
|
364
|
+
raise EmptySelectionError, "Invalid selection for refactor"
|
365
|
+
end
|
353
366
|
end
|
354
367
|
|
355
|
-
node =
|
356
|
-
node,
|
357
|
-
T.any(
|
358
|
-
Prism::InstanceVariableAndWriteNode,
|
359
|
-
Prism::InstanceVariableOperatorWriteNode,
|
360
|
-
Prism::InstanceVariableOrWriteNode,
|
361
|
-
Prism::InstanceVariableReadNode,
|
362
|
-
Prism::InstanceVariableTargetNode,
|
363
|
-
Prism::InstanceVariableWriteNode,
|
364
|
-
),
|
365
|
-
)
|
368
|
+
node = node #: as Prism::InstanceVariableAndWriteNode | Prism::InstanceVariableOperatorWriteNode | Prism::InstanceVariableOrWriteNode | Prism::InstanceVariableReadNode | Prism::InstanceVariableTargetNode | Prism::InstanceVariableWriteNode # rubocop:disable Layout/LineLength
|
366
369
|
|
367
370
|
node_context = @document.locate_node(
|
368
371
|
{
|
@@ -376,7 +379,9 @@ module RubyLsp
|
|
376
379
|
],
|
377
380
|
)
|
378
381
|
closest_node = node_context.node
|
379
|
-
|
382
|
+
if closest_node.nil?
|
383
|
+
raise InvalidTargetRangeError, "Couldn't find an appropriate location to place extracted refactor"
|
384
|
+
end
|
380
385
|
|
381
386
|
attribute_name = node.name[1..]
|
382
387
|
indentation = " " * (closest_node.location.start_column + 2)
|
@@ -20,20 +20,32 @@ module RubyLsp
|
|
20
20
|
|
21
21
|
#: (GlobalState global_state, URI::Generic uri, Prism::Dispatcher dispatcher) -> void
|
22
22
|
def initialize(global_state, uri, dispatcher)
|
23
|
-
@response_builder = ResponseBuilders::CollectionResponseBuilder
|
23
|
+
@response_builder = ResponseBuilders::CollectionResponseBuilder
|
24
24
|
.new #: ResponseBuilders::CollectionResponseBuilder[Interface::CodeLens]
|
25
25
|
super()
|
26
|
-
|
26
|
+
|
27
|
+
@test_builder = ResponseBuilders::TestCollection.new #: ResponseBuilders::TestCollection
|
28
|
+
|
29
|
+
if global_state.enabled_feature?(:fullTestDiscovery)
|
30
|
+
Listeners::TestStyle.new(@test_builder, global_state, dispatcher, uri)
|
31
|
+
Listeners::SpecStyle.new(@test_builder, global_state, dispatcher, uri)
|
32
|
+
else
|
33
|
+
Listeners::CodeLens.new(@response_builder, global_state, uri, dispatcher)
|
34
|
+
end
|
27
35
|
|
28
36
|
Addon.addons.each do |addon|
|
29
37
|
addon.create_code_lens_listener(@response_builder, uri, dispatcher)
|
38
|
+
|
39
|
+
if global_state.enabled_feature?(:fullTestDiscovery)
|
40
|
+
addon.create_discover_tests_listener(@test_builder, dispatcher, uri)
|
41
|
+
end
|
30
42
|
end
|
31
43
|
end
|
32
44
|
|
33
45
|
# @override
|
34
46
|
#: -> Array[Interface::CodeLens]
|
35
47
|
def perform
|
36
|
-
@response_builder.response
|
48
|
+
@response_builder.response + @test_builder.code_lens
|
37
49
|
end
|
38
50
|
end
|
39
51
|
end
|
@@ -21,7 +21,7 @@ module RubyLsp
|
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
24
|
-
#: ((RubyDocument | ERBDocument) document, GlobalState global_state, Hash[Symbol, untyped] params,
|
24
|
+
#: ((RubyDocument | ERBDocument) document, GlobalState global_state, Hash[Symbol, untyped] params, SorbetLevel sorbet_level, Prism::Dispatcher dispatcher) -> void
|
25
25
|
def initialize(document, global_state, params, sorbet_level, dispatcher)
|
26
26
|
super()
|
27
27
|
@target = nil #: Prism::Node?
|
@@ -60,7 +60,7 @@ module RubyLsp
|
|
60
60
|
],
|
61
61
|
code_units_cache: document.code_units_cache,
|
62
62
|
)
|
63
|
-
@response_builder = ResponseBuilders::CollectionResponseBuilder
|
63
|
+
@response_builder = ResponseBuilders::CollectionResponseBuilder
|
64
64
|
.new #: ResponseBuilders::CollectionResponseBuilder[Interface::CompletionItem]
|
65
65
|
|
66
66
|
Listeners::Completion.new(
|
@@ -11,12 +11,11 @@ module RubyLsp
|
|
11
11
|
class Definition < Request
|
12
12
|
extend T::Generic
|
13
13
|
|
14
|
-
#: ((RubyDocument | ERBDocument) document, GlobalState global_state, Hash[Symbol, untyped] position, Prism::Dispatcher dispatcher,
|
14
|
+
#: ((RubyDocument | ERBDocument) document, GlobalState global_state, Hash[Symbol, untyped] position, Prism::Dispatcher dispatcher, SorbetLevel sorbet_level) -> void
|
15
15
|
def initialize(document, global_state, position, dispatcher, sorbet_level)
|
16
16
|
super()
|
17
|
-
@response_builder = ResponseBuilders::CollectionResponseBuilder
|
18
|
-
|
19
|
-
].new #: ResponseBuilders::CollectionResponseBuilder[(Interface::Location | Interface::LocationLink)]
|
17
|
+
@response_builder = ResponseBuilders::CollectionResponseBuilder
|
18
|
+
.new #: ResponseBuilders::CollectionResponseBuilder[(Interface::Location | Interface::LocationLink)]
|
20
19
|
@dispatcher = dispatcher
|
21
20
|
|
22
21
|
char_position, _ = document.find_index_by_position(position)
|