ruby-lsp 0.23.23 → 0.26.1
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/exe/ruby-lsp +10 -4
- data/exe/ruby-lsp-check +0 -4
- data/exe/ruby-lsp-launcher +25 -11
- data/exe/ruby-lsp-test-exec +3 -15
- data/lib/rubocop/cop/ruby_lsp/use_language_server_aliases.rb +0 -1
- data/lib/rubocop/cop/ruby_lsp/use_register_with_handler_method.rb +0 -1
- data/lib/ruby_indexer/lib/ruby_indexer/declaration_listener.rb +7 -1
- data/lib/ruby_indexer/lib/ruby_indexer/enhancement.rb +1 -4
- data/lib/ruby_indexer/lib/ruby_indexer/entry.rb +10 -19
- data/lib/ruby_indexer/lib/ruby_indexer/index.rb +29 -7
- data/lib/ruby_indexer/lib/ruby_indexer/reference_finder.rb +12 -8
- data/lib/ruby_indexer/test/configuration_test.rb +1 -2
- data/lib/ruby_indexer/test/index_test.rb +39 -0
- data/lib/ruby_indexer/test/instance_variables_test.rb +24 -0
- data/lib/ruby_indexer/test/method_test.rb +17 -0
- data/lib/ruby_indexer/test/rbs_indexer_test.rb +2 -2
- data/lib/ruby_indexer/test/reference_finder_test.rb +79 -14
- data/lib/ruby_lsp/addon.rb +44 -15
- data/lib/ruby_lsp/base_server.rb +34 -26
- data/lib/ruby_lsp/document.rb +162 -52
- data/lib/ruby_lsp/erb_document.rb +8 -3
- data/lib/ruby_lsp/global_state.rb +21 -0
- data/lib/ruby_lsp/internal.rb +0 -2
- data/lib/ruby_lsp/listeners/completion.rb +14 -3
- data/lib/ruby_lsp/listeners/hover.rb +7 -0
- data/lib/ruby_lsp/listeners/inlay_hints.rb +5 -3
- data/lib/ruby_lsp/listeners/spec_style.rb +7 -8
- data/lib/ruby_lsp/listeners/test_discovery.rb +18 -15
- data/lib/ruby_lsp/listeners/test_style.rb +14 -13
- data/lib/ruby_lsp/requests/code_action_resolve.rb +3 -3
- data/lib/ruby_lsp/requests/code_lens.rb +9 -3
- data/lib/ruby_lsp/requests/completion.rb +1 -1
- data/lib/ruby_lsp/requests/definition.rb +1 -1
- data/lib/ruby_lsp/requests/discover_tests.rb +2 -2
- data/lib/ruby_lsp/requests/document_highlight.rb +1 -1
- data/lib/ruby_lsp/requests/hover.rb +1 -1
- data/lib/ruby_lsp/requests/inlay_hints.rb +3 -3
- data/lib/ruby_lsp/requests/on_type_formatting.rb +1 -1
- data/lib/ruby_lsp/requests/prepare_rename.rb +1 -1
- data/lib/ruby_lsp/requests/references.rb +10 -6
- data/lib/ruby_lsp/requests/rename.rb +8 -6
- data/lib/ruby_lsp/requests/request.rb +6 -7
- data/lib/ruby_lsp/requests/selection_ranges.rb +1 -1
- data/lib/ruby_lsp/requests/show_syntax_tree.rb +1 -1
- data/lib/ruby_lsp/requests/signature_help.rb +1 -1
- data/lib/ruby_lsp/requests/support/common.rb +1 -3
- data/lib/ruby_lsp/requests/support/formatter.rb +16 -15
- data/lib/ruby_lsp/requests/support/rubocop_formatter.rb +2 -2
- data/lib/ruby_lsp/requests/support/rubocop_runner.rb +13 -3
- data/lib/ruby_lsp/response_builders/response_builder.rb +6 -8
- data/lib/ruby_lsp/ruby_document.rb +10 -5
- data/lib/ruby_lsp/server.rb +93 -108
- data/lib/ruby_lsp/setup_bundler.rb +59 -25
- data/lib/ruby_lsp/static_docs.rb +1 -0
- data/lib/ruby_lsp/store.rb +0 -10
- data/lib/ruby_lsp/test_helper.rb +1 -4
- data/lib/ruby_lsp/test_reporters/lsp_reporter.rb +13 -8
- data/lib/ruby_lsp/test_reporters/minitest_reporter.rb +17 -4
- data/lib/ruby_lsp/utils.rb +47 -11
- data/static_docs/break.md +103 -0
- metadata +2 -16
- data/lib/ruby_lsp/load_sorbet.rb +0 -62
@@ -56,6 +56,17 @@ module RubyLsp
|
|
56
56
|
@enabled_feature_flags = {} #: Hash[Symbol, bool]
|
57
57
|
@mutex = Mutex.new #: Mutex
|
58
58
|
@telemetry_machine_id = nil #: String?
|
59
|
+
@feature_configuration = {
|
60
|
+
inlayHint: RequestConfig.new({
|
61
|
+
enableAll: false,
|
62
|
+
implicitRescue: false,
|
63
|
+
implicitHashValue: false,
|
64
|
+
}),
|
65
|
+
codeLens: RequestConfig.new({
|
66
|
+
enableAll: false,
|
67
|
+
enableTestCodeLens: true,
|
68
|
+
}),
|
69
|
+
} #: Hash[Symbol, RequestConfig]
|
59
70
|
end
|
60
71
|
|
61
72
|
#: [T] { -> T } -> T
|
@@ -175,9 +186,19 @@ module RubyLsp
|
|
175
186
|
@enabled_feature_flags = enabled_flags if enabled_flags
|
176
187
|
|
177
188
|
@telemetry_machine_id = options.dig(:initializationOptions, :telemetryMachineId)
|
189
|
+
|
190
|
+
options.dig(:initializationOptions, :featuresConfiguration)&.each do |feature_name, config|
|
191
|
+
@feature_configuration[feature_name]&.merge!(config)
|
192
|
+
end
|
193
|
+
|
178
194
|
notifications
|
179
195
|
end
|
180
196
|
|
197
|
+
#: (Symbol) -> RequestConfig?
|
198
|
+
def feature_configuration(feature_name)
|
199
|
+
@feature_configuration[feature_name]
|
200
|
+
end
|
201
|
+
|
181
202
|
#: (Symbol flag) -> bool?
|
182
203
|
def enabled_feature?(flag)
|
183
204
|
@enabled_feature_flags[:all] || @enabled_feature_flags[flag]
|
data/lib/ruby_lsp/internal.rb
CHANGED
@@ -6,8 +6,6 @@
|
|
6
6
|
yarp_require_paths = Gem.loaded_specs["yarp"]&.full_require_paths
|
7
7
|
$LOAD_PATH.delete_if { |path| yarp_require_paths.include?(path) } if yarp_require_paths
|
8
8
|
|
9
|
-
require "sorbet-runtime"
|
10
|
-
|
11
9
|
# Set Bundler's UI level to silent as soon as possible to prevent any prints to STDOUT
|
12
10
|
require "bundler"
|
13
11
|
Bundler.ui.level = :silent
|
@@ -445,11 +445,14 @@ module RubyLsp
|
|
445
445
|
return unless arguments_node
|
446
446
|
|
447
447
|
path_node_to_complete = arguments_node.arguments.first
|
448
|
-
|
449
448
|
return unless path_node_to_complete.is_a?(Prism::StringNode)
|
450
449
|
|
451
|
-
|
450
|
+
# If the file is unsaved (e.g.: untitled:Untitled-1), we can't provide relative completion as we don't know
|
451
|
+
# where the user intends to save it
|
452
|
+
full_path = @uri.to_standardized_path
|
453
|
+
return unless full_path
|
452
454
|
|
455
|
+
origin_dir = Pathname.new(full_path).dirname
|
453
456
|
content = path_node_to_complete.content
|
454
457
|
# if the path is not a directory, glob all possible next characters
|
455
458
|
# for example ../somethi| (where | is the cursor position)
|
@@ -516,6 +519,14 @@ module RubyLsp
|
|
516
519
|
|
517
520
|
entry_name = entry.name
|
518
521
|
owner_name = entry.owner&.name
|
522
|
+
new_text = entry_name
|
523
|
+
|
524
|
+
if entry_name.end_with?("=")
|
525
|
+
method_name = entry_name.delete_suffix("=")
|
526
|
+
|
527
|
+
# For writer methods, format as assignment and prefix "self." when no receiver is specified
|
528
|
+
new_text = node.receiver.nil? ? "self.#{method_name} = " : "#{method_name} = "
|
529
|
+
end
|
519
530
|
|
520
531
|
label_details = Interface::CompletionItemLabelDetails.new(
|
521
532
|
description: entry.file_name,
|
@@ -525,7 +536,7 @@ module RubyLsp
|
|
525
536
|
label: entry_name,
|
526
537
|
filter_text: entry_name,
|
527
538
|
label_details: label_details,
|
528
|
-
text_edit: Interface::TextEdit.new(range: range, new_text:
|
539
|
+
text_edit: Interface::TextEdit.new(range: range, new_text: new_text),
|
529
540
|
kind: Constant::CompletionItemKind::METHOD,
|
530
541
|
data: {
|
531
542
|
owner_name: owner_name,
|
@@ -7,6 +7,7 @@ module RubyLsp
|
|
7
7
|
include Requests::Support::Common
|
8
8
|
|
9
9
|
ALLOWED_TARGETS = [
|
10
|
+
Prism::BreakNode,
|
10
11
|
Prism::CallNode,
|
11
12
|
Prism::ConstantReadNode,
|
12
13
|
Prism::ConstantWriteNode,
|
@@ -54,6 +55,7 @@ module RubyLsp
|
|
54
55
|
|
55
56
|
dispatcher.register(
|
56
57
|
self,
|
58
|
+
:on_break_node_enter,
|
57
59
|
:on_constant_read_node_enter,
|
58
60
|
:on_constant_write_node_enter,
|
59
61
|
:on_constant_path_node_enter,
|
@@ -84,6 +86,11 @@ module RubyLsp
|
|
84
86
|
)
|
85
87
|
end
|
86
88
|
|
89
|
+
#: (Prism::BreakNode node) -> void
|
90
|
+
def on_break_node_enter(node)
|
91
|
+
handle_keyword_documentation(node.keyword)
|
92
|
+
end
|
93
|
+
|
87
94
|
#: (Prism::StringNode node) -> void
|
88
95
|
def on_string_node_enter(node)
|
89
96
|
if @path && File.basename(@path) == GEMFILE_NAME
|
@@ -8,10 +8,12 @@ module RubyLsp
|
|
8
8
|
|
9
9
|
RESCUE_STRING_LENGTH = "rescue".length #: Integer
|
10
10
|
|
11
|
-
#: (ResponseBuilders::CollectionResponseBuilder[Interface::InlayHint]
|
12
|
-
def initialize(
|
11
|
+
#: (GlobalState, ResponseBuilders::CollectionResponseBuilder[Interface::InlayHint], Prism::Dispatcher) -> void
|
12
|
+
def initialize(global_state, response_builder, dispatcher)
|
13
13
|
@response_builder = response_builder
|
14
|
-
@hints_configuration =
|
14
|
+
@hints_configuration = ( # rubocop:disable Style/RedundantParentheses
|
15
|
+
global_state.feature_configuration(:inlayHint) #: as !nil
|
16
|
+
) #: RequestConfig
|
15
17
|
|
16
18
|
dispatcher.register(self, :on_rescue_node_enter, :on_implicit_node_enter)
|
17
19
|
end
|
@@ -19,21 +19,20 @@ module RubyLsp
|
|
19
19
|
|
20
20
|
#: (ResponseBuilders::TestCollection, GlobalState, Prism::Dispatcher, URI::Generic) -> void
|
21
21
|
def initialize(response_builder, global_state, dispatcher, uri)
|
22
|
-
super
|
22
|
+
super(response_builder, global_state, uri)
|
23
23
|
|
24
24
|
@spec_group_id_stack = [] #: Array[Group?]
|
25
25
|
|
26
|
-
|
27
|
-
|
28
|
-
# Common handlers registered in parent class
|
26
|
+
register_events(
|
27
|
+
dispatcher,
|
29
28
|
:on_class_node_enter,
|
30
|
-
:on_call_node_enter,
|
29
|
+
:on_call_node_enter,
|
31
30
|
:on_call_node_leave,
|
32
31
|
)
|
33
32
|
end
|
34
33
|
|
35
34
|
#: (Prism::ClassNode) -> void
|
36
|
-
def on_class_node_enter(node)
|
35
|
+
def on_class_node_enter(node) # rubocop:disable RubyLsp/UseRegisterWithHandlerMethod
|
37
36
|
with_test_ancestor_tracking(node) do |name, ancestors|
|
38
37
|
@spec_group_id_stack << (ancestors.include?("Minitest::Spec") ? ClassGroup.new(name) : nil)
|
39
38
|
end
|
@@ -58,7 +57,7 @@ module RubyLsp
|
|
58
57
|
end
|
59
58
|
|
60
59
|
#: (Prism::CallNode) -> void
|
61
|
-
def on_call_node_enter(node)
|
60
|
+
def on_call_node_enter(node) # rubocop:disable RubyLsp/UseRegisterWithHandlerMethod
|
62
61
|
return unless in_spec_context?
|
63
62
|
|
64
63
|
case node.name
|
@@ -70,7 +69,7 @@ module RubyLsp
|
|
70
69
|
end
|
71
70
|
|
72
71
|
#: (Prism::CallNode) -> void
|
73
|
-
def on_call_node_leave(node)
|
72
|
+
def on_call_node_leave(node) # rubocop:disable RubyLsp/UseRegisterWithHandlerMethod
|
74
73
|
return unless node.name == :describe && !node.receiver
|
75
74
|
|
76
75
|
current_group = @spec_group_id_stack.last
|
@@ -3,32 +3,23 @@
|
|
3
3
|
|
4
4
|
module RubyLsp
|
5
5
|
module Listeners
|
6
|
+
# @abstract
|
6
7
|
class TestDiscovery
|
7
|
-
extend T::Helpers
|
8
|
-
abstract!
|
9
|
-
|
10
8
|
include Requests::Support::Common
|
11
9
|
|
12
10
|
DYNAMIC_REFERENCE_MARKER = "<dynamic_reference>"
|
13
11
|
|
14
|
-
#: (ResponseBuilders::TestCollection response_builder, GlobalState global_state,
|
15
|
-
def initialize(response_builder, global_state,
|
12
|
+
#: (ResponseBuilders::TestCollection response_builder, GlobalState global_state, URI::Generic uri) -> void
|
13
|
+
def initialize(response_builder, global_state, uri)
|
16
14
|
@response_builder = response_builder
|
17
15
|
@uri = uri
|
18
16
|
@index = global_state.index #: RubyIndexer::Index
|
19
17
|
@visibility_stack = [:public] #: Array[Symbol]
|
20
18
|
@nesting = [] #: Array[String]
|
21
|
-
|
22
|
-
dispatcher.register(
|
23
|
-
self,
|
24
|
-
:on_class_node_leave,
|
25
|
-
:on_module_node_enter,
|
26
|
-
:on_module_node_leave,
|
27
|
-
)
|
28
19
|
end
|
29
20
|
|
30
21
|
#: (Prism::ModuleNode node) -> void
|
31
|
-
def on_module_node_enter(node)
|
22
|
+
def on_module_node_enter(node) # rubocop:disable RubyLsp/UseRegisterWithHandlerMethod
|
32
23
|
@visibility_stack << :public
|
33
24
|
|
34
25
|
name = constant_name(node.constant_path)
|
@@ -38,19 +29,31 @@ module RubyLsp
|
|
38
29
|
end
|
39
30
|
|
40
31
|
#: (Prism::ModuleNode node) -> void
|
41
|
-
def on_module_node_leave(node)
|
32
|
+
def on_module_node_leave(node) # rubocop:disable RubyLsp/UseRegisterWithHandlerMethod
|
42
33
|
@visibility_stack.pop
|
43
34
|
@nesting.pop
|
44
35
|
end
|
45
36
|
|
46
37
|
#: (Prism::ClassNode node) -> void
|
47
|
-
def on_class_node_leave(node)
|
38
|
+
def on_class_node_leave(node) # rubocop:disable RubyLsp/UseRegisterWithHandlerMethod
|
48
39
|
@visibility_stack.pop
|
49
40
|
@nesting.pop
|
50
41
|
end
|
51
42
|
|
52
43
|
private
|
53
44
|
|
45
|
+
#: (Prism::Dispatcher, *Symbol) -> void
|
46
|
+
def register_events(dispatcher, *events)
|
47
|
+
unique_events = events.dup.push(
|
48
|
+
:on_class_node_leave,
|
49
|
+
:on_module_node_enter,
|
50
|
+
:on_module_node_leave,
|
51
|
+
)
|
52
|
+
|
53
|
+
unique_events.uniq!
|
54
|
+
dispatcher.register(self, *unique_events)
|
55
|
+
end
|
56
|
+
|
54
57
|
#: (String? name) -> String
|
55
58
|
def calc_fully_qualified_name(name)
|
56
59
|
RubyIndexer::Index.actual_nesting(@nesting, name).join("::")
|
@@ -75,8 +75,9 @@ module RubyLsp
|
|
75
75
|
|
76
76
|
unless full_files.empty?
|
77
77
|
specs, tests = full_files.partition { |path| spec?(path) }
|
78
|
-
|
79
|
-
commands << "#{
|
78
|
+
|
79
|
+
commands << "#{COMMAND} -Itest -e \"ARGV.each { |f| require f }\" #{tests.join(" ")}" if tests.any?
|
80
|
+
commands << "#{COMMAND} -Ispec -e \"ARGV.each { |f| require f }\" #{specs.join(" ")}" if specs.any?
|
80
81
|
end
|
81
82
|
|
82
83
|
commands
|
@@ -113,7 +114,7 @@ module RubyLsp
|
|
113
114
|
end
|
114
115
|
|
115
116
|
load_path = spec?(file_path) ? "-Ispec" : "-Itest"
|
116
|
-
"#{
|
117
|
+
"#{COMMAND} #{load_path} #{file_path} --name \"/#{regex}/\""
|
117
118
|
end
|
118
119
|
|
119
120
|
#: (String, Hash[String, Hash[Symbol, untyped]]) -> Array[String]
|
@@ -124,7 +125,7 @@ module RubyLsp
|
|
124
125
|
Shellwords.escape(TestDiscovery::DYNAMIC_REFERENCE_MARKER),
|
125
126
|
".*",
|
126
127
|
)
|
127
|
-
command = +"#{
|
128
|
+
command = +"#{COMMAND} -Itest #{file_path} --testcase \"/^#{group_regex}\\$/\""
|
128
129
|
|
129
130
|
unless examples.empty?
|
130
131
|
command << if examples.length == 1
|
@@ -143,24 +144,24 @@ module RubyLsp
|
|
143
144
|
|
144
145
|
MINITEST_REPORTER_PATH = File.expand_path("../test_reporters/minitest_reporter.rb", __dir__) #: String
|
145
146
|
TEST_UNIT_REPORTER_PATH = File.expand_path("../test_reporters/test_unit_reporter.rb", __dir__) #: String
|
146
|
-
ACCESS_MODIFIERS = [:public, :private, :protected].freeze
|
147
147
|
BASE_COMMAND = begin
|
148
148
|
Bundler.with_original_env { Bundler.default_lockfile }
|
149
149
|
"bundle exec ruby"
|
150
150
|
rescue Bundler::GemfileNotFound
|
151
151
|
"ruby"
|
152
152
|
end #: String
|
153
|
+
COMMAND = "#{BASE_COMMAND} -r#{MINITEST_REPORTER_PATH} -r#{TEST_UNIT_REPORTER_PATH}" #: String
|
154
|
+
ACCESS_MODIFIERS = [:public, :private, :protected].freeze
|
153
155
|
|
154
156
|
#: (ResponseBuilders::TestCollection, GlobalState, Prism::Dispatcher, URI::Generic) -> void
|
155
157
|
def initialize(response_builder, global_state, dispatcher, uri)
|
156
|
-
super
|
158
|
+
super(response_builder, global_state, uri)
|
157
159
|
|
158
160
|
@framework = :minitest #: Symbol
|
159
161
|
@parent_stack = [@response_builder] #: Array[(Requests::Support::TestItem | ResponseBuilders::TestCollection)?]
|
160
162
|
|
161
|
-
|
162
|
-
|
163
|
-
# Common handlers registered in parent class
|
163
|
+
register_events(
|
164
|
+
dispatcher,
|
164
165
|
:on_class_node_enter,
|
165
166
|
:on_def_node_enter,
|
166
167
|
:on_call_node_enter,
|
@@ -169,7 +170,7 @@ module RubyLsp
|
|
169
170
|
end
|
170
171
|
|
171
172
|
#: (Prism::ClassNode node) -> void
|
172
|
-
def on_class_node_enter(node)
|
173
|
+
def on_class_node_enter(node) # rubocop:disable RubyLsp/UseRegisterWithHandlerMethod
|
173
174
|
with_test_ancestor_tracking(node) do |name, ancestors|
|
174
175
|
@framework = :test_unit if ancestors.include?("Test::Unit::TestCase")
|
175
176
|
|
@@ -210,7 +211,7 @@ module RubyLsp
|
|
210
211
|
end
|
211
212
|
|
212
213
|
#: (Prism::DefNode node) -> void
|
213
|
-
def on_def_node_enter(node)
|
214
|
+
def on_def_node_enter(node) # rubocop:disable RubyLsp/UseRegisterWithHandlerMethod
|
214
215
|
return if @visibility_stack.last != :public
|
215
216
|
|
216
217
|
name = node.name.to_s
|
@@ -232,7 +233,7 @@ module RubyLsp
|
|
232
233
|
end
|
233
234
|
|
234
235
|
#: (Prism::CallNode node) -> void
|
235
|
-
def on_call_node_enter(node)
|
236
|
+
def on_call_node_enter(node) # rubocop:disable RubyLsp/UseRegisterWithHandlerMethod
|
236
237
|
name = node.name
|
237
238
|
return unless ACCESS_MODIFIERS.include?(name)
|
238
239
|
|
@@ -240,7 +241,7 @@ module RubyLsp
|
|
240
241
|
end
|
241
242
|
|
242
243
|
#: (Prism::CallNode node) -> void
|
243
|
-
def on_call_node_leave(node)
|
244
|
+
def on_call_node_leave(node) # rubocop:disable RubyLsp/UseRegisterWithHandlerMethod
|
244
245
|
name = node.name
|
245
246
|
return unless ACCESS_MODIFIERS.include?(name)
|
246
247
|
return unless node.arguments&.arguments
|
@@ -100,7 +100,7 @@ module RubyLsp
|
|
100
100
|
|
101
101
|
# Find the closest statements node, so that we place the refactor in a valid position
|
102
102
|
node_context = RubyDocument
|
103
|
-
.locate(@document.
|
103
|
+
.locate(@document.ast,
|
104
104
|
start_index,
|
105
105
|
node_types: [
|
106
106
|
Prism::StatementsNode,
|
@@ -207,7 +207,7 @@ module RubyLsp
|
|
207
207
|
|
208
208
|
# Find the closest method declaration node, so that we place the refactor in a valid position
|
209
209
|
node_context = RubyDocument.locate(
|
210
|
-
@document.
|
210
|
+
@document.ast,
|
211
211
|
start_index,
|
212
212
|
node_types: [Prism::DefNode],
|
213
213
|
code_units_cache: @document.code_units_cache,
|
@@ -365,7 +365,7 @@ module RubyLsp
|
|
365
365
|
end
|
366
366
|
end
|
367
367
|
|
368
|
-
node = node #: as Prism::InstanceVariableAndWriteNode | Prism::InstanceVariableOperatorWriteNode | Prism::InstanceVariableOrWriteNode | Prism::InstanceVariableReadNode | Prism::InstanceVariableTargetNode | Prism::InstanceVariableWriteNode
|
368
|
+
node = node #: as Prism::InstanceVariableAndWriteNode | Prism::InstanceVariableOperatorWriteNode | Prism::InstanceVariableOrWriteNode | Prism::InstanceVariableReadNode | Prism::InstanceVariableTargetNode | Prism::InstanceVariableWriteNode
|
369
369
|
|
370
370
|
node_context = @document.locate_node(
|
371
371
|
{
|
@@ -27,10 +27,16 @@ module RubyLsp
|
|
27
27
|
@document = document
|
28
28
|
@test_builder = ResponseBuilders::TestCollection.new #: ResponseBuilders::TestCollection
|
29
29
|
uri = document.uri
|
30
|
+
file_path = uri.full_path
|
31
|
+
code_lens_config = global_state.feature_configuration(:codeLens)
|
32
|
+
test_lenses_enabled = (!code_lens_config || code_lens_config.enabled?(:enableTestCodeLens)) &&
|
33
|
+
file_path && File.fnmatch?(TEST_PATH_PATTERN, file_path, File::FNM_PATHNAME | File::FNM_EXTGLOB)
|
30
34
|
|
31
35
|
if global_state.enabled_feature?(:fullTestDiscovery)
|
32
|
-
|
33
|
-
|
36
|
+
if test_lenses_enabled
|
37
|
+
Listeners::TestStyle.new(@test_builder, global_state, dispatcher, uri)
|
38
|
+
Listeners::SpecStyle.new(@test_builder, global_state, dispatcher, uri)
|
39
|
+
end
|
34
40
|
else
|
35
41
|
Listeners::CodeLens.new(@response_builder, global_state, uri, dispatcher)
|
36
42
|
end
|
@@ -38,7 +44,7 @@ module RubyLsp
|
|
38
44
|
Addon.addons.each do |addon|
|
39
45
|
addon.create_code_lens_listener(@response_builder, uri, dispatcher)
|
40
46
|
|
41
|
-
if global_state.enabled_feature?(:fullTestDiscovery)
|
47
|
+
if global_state.enabled_feature?(:fullTestDiscovery) && test_lenses_enabled
|
42
48
|
addon.create_discover_tests_listener(@test_builder, dispatcher, uri)
|
43
49
|
end
|
44
50
|
end
|
@@ -43,7 +43,7 @@ module RubyLsp
|
|
43
43
|
addon.create_discover_tests_listener(@response_builder, @dispatcher, @document.uri)
|
44
44
|
end
|
45
45
|
|
46
|
-
@dispatcher.visit(@document.
|
46
|
+
@dispatcher.visit(@document.ast)
|
47
47
|
else
|
48
48
|
@global_state.synchronize do
|
49
49
|
RubyIndexer::DeclarationListener.new(
|
@@ -64,7 +64,7 @@ module RubyLsp
|
|
64
64
|
# Dispatch the events both for indexing the test file and discovering the tests. The order here is
|
65
65
|
# important because we need the index to be aware of the existing classes/modules/methods before the test
|
66
66
|
# listeners can do their work
|
67
|
-
@dispatcher.visit(@document.
|
67
|
+
@dispatcher.visit(@document.ast)
|
68
68
|
end
|
69
69
|
end
|
70
70
|
|
@@ -24,7 +24,7 @@ module RubyLsp
|
|
24
24
|
delegate_request_if_needed!(global_state, document, char_position)
|
25
25
|
|
26
26
|
node_context = RubyDocument.locate(
|
27
|
-
document.
|
27
|
+
document.ast,
|
28
28
|
char_position,
|
29
29
|
node_types: Listeners::Hover::ALLOWED_TARGETS,
|
30
30
|
code_units_cache: document.code_units_cache,
|
@@ -16,13 +16,13 @@ module RubyLsp
|
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
|
-
#: ((RubyDocument | ERBDocument)
|
20
|
-
def initialize(
|
19
|
+
#: (GlobalState, (RubyDocument | ERBDocument), Prism::Dispatcher) -> void
|
20
|
+
def initialize(global_state, document, dispatcher)
|
21
21
|
super()
|
22
22
|
|
23
23
|
@response_builder = ResponseBuilders::CollectionResponseBuilder
|
24
24
|
.new #: ResponseBuilders::CollectionResponseBuilder[Interface::InlayHint]
|
25
|
-
Listeners::InlayHints.new(@response_builder,
|
25
|
+
Listeners::InlayHints.new(global_state, @response_builder, dispatcher)
|
26
26
|
end
|
27
27
|
|
28
28
|
# @override
|
@@ -162,7 +162,7 @@ module RubyLsp
|
|
162
162
|
|
163
163
|
#: (Integer line, Integer character) -> void
|
164
164
|
def move_cursor_to(line, character)
|
165
|
-
return unless /Visual Studio Code|Cursor|VSCodium/.match?(@client_name)
|
165
|
+
return unless /Visual Studio Code|Cursor|VSCodium|Windsurf/.match?(@client_name)
|
166
166
|
|
167
167
|
position = Interface::Position.new(
|
168
168
|
line: line,
|
@@ -22,7 +22,7 @@ module RubyLsp
|
|
22
22
|
char_position, _ = @document.find_index_by_position(@position)
|
23
23
|
|
24
24
|
node_context = RubyDocument.locate(
|
25
|
-
@document.
|
25
|
+
@document.ast,
|
26
26
|
char_position,
|
27
27
|
node_types: [Prism::ConstantReadNode, Prism::ConstantPathNode, Prism::ConstantPathTargetNode],
|
28
28
|
code_units_cache: @document.code_units_cache,
|
@@ -26,7 +26,7 @@ module RubyLsp
|
|
26
26
|
char_position, _ = @document.find_index_by_position(position)
|
27
27
|
|
28
28
|
node_context = RubyDocument.locate(
|
29
|
-
@document.
|
29
|
+
@document.ast,
|
30
30
|
char_position,
|
31
31
|
node_types: [
|
32
32
|
Prism::ConstantReadNode,
|
@@ -55,7 +55,7 @@ module RubyLsp
|
|
55
55
|
)
|
56
56
|
end
|
57
57
|
|
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,
|
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,
|
59
59
|
|
60
60
|
reference_target = create_reference_target(target, node_context)
|
61
61
|
return @locations unless reference_target
|
@@ -66,7 +66,7 @@ module RubyLsp
|
|
66
66
|
# of reading from disk
|
67
67
|
next if @store.key?(uri)
|
68
68
|
|
69
|
-
parse_result = Prism.
|
69
|
+
parse_result = Prism.parse_lex_file(path)
|
70
70
|
collect_references(reference_target, parse_result, uri)
|
71
71
|
rescue Errno::EISDIR, Errno::ENOENT
|
72
72
|
# If `path` is a directory, just ignore it and continue. If the file doesn't exist, then we also ignore it.
|
@@ -101,13 +101,17 @@ module RubyLsp
|
|
101
101
|
Prism::InstanceVariableReadNode,
|
102
102
|
Prism::InstanceVariableTargetNode,
|
103
103
|
Prism::InstanceVariableWriteNode
|
104
|
-
|
104
|
+
receiver_type = @global_state.type_inferrer.infer_receiver_type(node_context)
|
105
|
+
return unless receiver_type
|
106
|
+
|
107
|
+
ancestors = @global_state.index.linearized_ancestors_of(receiver_type.name)
|
108
|
+
RubyIndexer::ReferenceFinder::InstanceVariableTarget.new(target_node.name.to_s, ancestors)
|
105
109
|
when Prism::CallNode, Prism::DefNode
|
106
110
|
RubyIndexer::ReferenceFinder::MethodTarget.new(target_node.name.to_s)
|
107
111
|
end
|
108
112
|
end
|
109
113
|
|
110
|
-
#: (RubyIndexer::ReferenceFinder::Target target, Prism::
|
114
|
+
#: (RubyIndexer::ReferenceFinder::Target target, Prism::LexResult parse_result, URI::Generic uri) -> void
|
111
115
|
def collect_references(target, parse_result, uri)
|
112
116
|
dispatcher = Prism::Dispatcher.new
|
113
117
|
finder = RubyIndexer::ReferenceFinder.new(
|
@@ -117,7 +121,7 @@ module RubyLsp
|
|
117
121
|
uri,
|
118
122
|
include_declarations: @params.dig(:context, :includeDeclaration) || true,
|
119
123
|
)
|
120
|
-
dispatcher.visit(parse_result.value)
|
124
|
+
dispatcher.visit(parse_result.value.first)
|
121
125
|
|
122
126
|
finder.references.each do |reference|
|
123
127
|
@locations << Interface::Location.new(
|
@@ -34,7 +34,7 @@ module RubyLsp
|
|
34
34
|
char_position, _ = @document.find_index_by_position(@position)
|
35
35
|
|
36
36
|
node_context = RubyDocument.locate(
|
37
|
-
@document.
|
37
|
+
@document.ast,
|
38
38
|
char_position,
|
39
39
|
node_types: [Prism::ConstantReadNode, Prism::ConstantPathNode, Prism::ConstantPathTargetNode],
|
40
40
|
code_units_cache: @document.code_units_cache,
|
@@ -136,25 +136,27 @@ module RubyLsp
|
|
136
136
|
next if @store.key?(uri)
|
137
137
|
|
138
138
|
parse_result = Prism.parse_file(path)
|
139
|
-
edits = collect_changes(target, parse_result, name, uri)
|
139
|
+
edits = collect_changes(target, parse_result.value, name, uri)
|
140
140
|
changes[uri.to_s] = edits unless edits.empty?
|
141
141
|
rescue Errno::EISDIR, Errno::ENOENT
|
142
142
|
# If `path` is a directory, just ignore it and continue. If the file doesn't exist, then we also ignore it.
|
143
143
|
end
|
144
144
|
|
145
145
|
@store.each do |uri, document|
|
146
|
-
|
146
|
+
next unless document.is_a?(RubyDocument) || document.is_a?(ERBDocument)
|
147
|
+
|
148
|
+
edits = collect_changes(target, document.ast, name, document.uri)
|
147
149
|
changes[uri] = edits unless edits.empty?
|
148
150
|
end
|
149
151
|
|
150
152
|
changes
|
151
153
|
end
|
152
154
|
|
153
|
-
#: (RubyIndexer::ReferenceFinder::Target target, Prism::
|
154
|
-
def collect_changes(target,
|
155
|
+
#: (RubyIndexer::ReferenceFinder::Target target, Prism::Node ast, String name, URI::Generic uri) -> Array[Interface::TextEdit]
|
156
|
+
def collect_changes(target, ast, name, uri)
|
155
157
|
dispatcher = Prism::Dispatcher.new
|
156
158
|
finder = RubyIndexer::ReferenceFinder.new(target, @global_state.index, dispatcher, uri)
|
157
|
-
dispatcher.visit(
|
159
|
+
dispatcher.visit(ast)
|
158
160
|
|
159
161
|
finder.references.map do |reference|
|
160
162
|
adjust_reference_for_edit(name, reference)
|
@@ -3,16 +3,15 @@
|
|
3
3
|
|
4
4
|
module RubyLsp
|
5
5
|
module Requests
|
6
|
+
# @abstract
|
6
7
|
class Request
|
7
|
-
extend T::Helpers
|
8
|
-
extend T::Sig
|
9
|
-
|
10
8
|
class InvalidFormatter < StandardError; end
|
11
9
|
|
12
|
-
abstract
|
13
|
-
|
14
|
-
|
15
|
-
|
10
|
+
# @abstract
|
11
|
+
#: -> untyped
|
12
|
+
def perform
|
13
|
+
raise AbstractMethodInvokedError
|
14
|
+
end
|
16
15
|
|
17
16
|
private
|
18
17
|
|
@@ -27,7 +27,7 @@ module RubyLsp
|
|
27
27
|
delegate_request_if_needed!(global_state, document, char_position)
|
28
28
|
|
29
29
|
node_context = RubyDocument.locate(
|
30
|
-
document.
|
30
|
+
document.ast,
|
31
31
|
char_position,
|
32
32
|
node_types: [Prism::CallNode],
|
33
33
|
code_units_cache: document.code_units_cache,
|