ruby-lsp 0.23.12 → 0.23.13
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/rubocop/cop/ruby_lsp/use_language_server_aliases.rb +1 -1
- data/lib/ruby_indexer/lib/ruby_indexer/configuration.rb +31 -40
- data/lib/ruby_indexer/lib/ruby_indexer/declaration_listener.rb +56 -22
- data/lib/ruby_indexer/lib/ruby_indexer/enhancement.rb +1 -1
- data/lib/ruby_indexer/lib/ruby_indexer/entry.rb +15 -18
- data/lib/ruby_indexer/lib/ruby_indexer/index.rb +8 -11
- data/lib/ruby_indexer/lib/ruby_indexer/prefix_tree.rb +2 -2
- data/lib/ruby_indexer/lib/ruby_indexer/rbs_indexer.rb +1 -1
- data/lib/ruby_indexer/lib/ruby_indexer/reference_finder.rb +2 -2
- data/lib/ruby_indexer/test/configuration_test.rb +10 -1
- data/lib/ruby_indexer/test/method_test.rb +26 -0
- data/lib/ruby_indexer/test/rbs_indexer_test.rb +1 -1
- data/lib/ruby_lsp/addon.rb +12 -4
- data/lib/ruby_lsp/base_server.rb +19 -22
- data/lib/ruby_lsp/client_capabilities.rb +6 -6
- data/lib/ruby_lsp/document.rb +13 -13
- data/lib/ruby_lsp/erb_document.rb +7 -9
- data/lib/ruby_lsp/global_state.rb +21 -24
- data/lib/ruby_lsp/listeners/code_lens.rb +59 -48
- data/lib/ruby_lsp/listeners/completion.rb +2 -2
- data/lib/ruby_lsp/listeners/definition.rb +2 -2
- data/lib/ruby_lsp/listeners/document_highlight.rb +62 -80
- data/lib/ruby_lsp/listeners/document_link.rb +34 -43
- data/lib/ruby_lsp/listeners/document_symbol.rb +1 -1
- data/lib/ruby_lsp/listeners/folding_ranges.rb +1 -1
- data/lib/ruby_lsp/listeners/hover.rb +43 -52
- data/lib/ruby_lsp/listeners/inlay_hints.rb +1 -1
- data/lib/ruby_lsp/listeners/semantic_highlighting.rb +11 -14
- data/lib/ruby_lsp/listeners/signature_help.rb +2 -2
- data/lib/ruby_lsp/listeners/spec_style.rb +15 -59
- data/lib/ruby_lsp/listeners/test_discovery.rb +89 -0
- data/lib/ruby_lsp/listeners/test_style.rb +47 -81
- data/lib/ruby_lsp/node_context.rb +4 -4
- data/lib/ruby_lsp/rbs_document.rb +1 -1
- data/lib/ruby_lsp/requests/code_actions.rb +9 -12
- data/lib/ruby_lsp/requests/code_lens.rb +2 -4
- data/lib/ruby_lsp/requests/completion.rb +3 -5
- data/lib/ruby_lsp/requests/completion_resolve.rb +1 -1
- data/lib/ruby_lsp/requests/definition.rb +4 -5
- data/lib/ruby_lsp/requests/diagnostics.rb +2 -2
- data/lib/ruby_lsp/requests/discover_tests.rb +3 -2
- data/lib/ruby_lsp/requests/document_highlight.rb +2 -4
- data/lib/ruby_lsp/requests/document_link.rb +2 -4
- data/lib/ruby_lsp/requests/document_symbol.rb +1 -1
- data/lib/ruby_lsp/requests/folding_ranges.rb +3 -8
- data/lib/ruby_lsp/requests/formatting.rb +2 -2
- data/lib/ruby_lsp/requests/go_to_relevant_file.rb +3 -3
- data/lib/ruby_lsp/requests/hover.rb +2 -2
- data/lib/ruby_lsp/requests/inlay_hints.rb +2 -4
- data/lib/ruby_lsp/requests/on_type_formatting.rb +10 -13
- data/lib/ruby_lsp/requests/prepare_rename.rb +1 -1
- data/lib/ruby_lsp/requests/range_formatting.rb +2 -2
- data/lib/ruby_lsp/requests/references.rb +1 -1
- data/lib/ruby_lsp/requests/rename.rb +2 -2
- data/lib/ruby_lsp/requests/request.rb +2 -2
- data/lib/ruby_lsp/requests/selection_ranges.rb +2 -2
- data/lib/ruby_lsp/requests/semantic_highlighting.rb +5 -7
- data/lib/ruby_lsp/requests/show_syntax_tree.rb +1 -1
- data/lib/ruby_lsp/requests/signature_help.rb +2 -2
- data/lib/ruby_lsp/requests/support/common.rb +1 -1
- data/lib/ruby_lsp/requests/support/rubocop_diagnostic.rb +15 -21
- data/lib/ruby_lsp/requests/support/rubocop_formatter.rb +2 -2
- data/lib/ruby_lsp/requests/support/rubocop_runner.rb +12 -18
- data/lib/ruby_lsp/requests/support/sorbet.rb +28 -31
- data/lib/ruby_lsp/requests/support/source_uri.rb +11 -14
- data/lib/ruby_lsp/requests/support/syntax_tree_formatter.rb +5 -9
- data/lib/ruby_lsp/requests/support/test_item.rb +4 -9
- data/lib/ruby_lsp/requests/type_hierarchy_supertypes.rb +1 -1
- data/lib/ruby_lsp/requests/workspace_symbol.rb +1 -1
- data/lib/ruby_lsp/response_builders/collection_response_builder.rb +1 -1
- data/lib/ruby_lsp/response_builders/document_symbol.rb +2 -5
- data/lib/ruby_lsp/response_builders/hover.rb +5 -8
- data/lib/ruby_lsp/response_builders/semantic_highlighting.rb +41 -47
- data/lib/ruby_lsp/response_builders/signature_help.rb +1 -1
- data/lib/ruby_lsp/response_builders/test_collection.rb +1 -1
- data/lib/ruby_lsp/ruby_document.rb +7 -20
- data/lib/ruby_lsp/ruby_lsp_reporter_plugin.rb +7 -4
- data/lib/ruby_lsp/scope.rb +1 -1
- data/lib/ruby_lsp/server.rb +9 -1
- data/lib/ruby_lsp/setup_bundler.rb +36 -42
- data/lib/ruby_lsp/static_docs.rb +4 -7
- data/lib/ruby_lsp/store.rb +9 -12
- data/lib/ruby_lsp/test_reporter.rb +140 -4
- data/lib/ruby_lsp/test_unit_test_runner.rb +10 -8
- data/lib/ruby_lsp/utils.rb +10 -16
- metadata +3 -2
@@ -6,55 +6,49 @@ module RubyLsp
|
|
6
6
|
class Hover
|
7
7
|
include Requests::Support::Common
|
8
8
|
|
9
|
-
ALLOWED_TARGETS =
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
[
|
45
|
-
"https://github.com",
|
46
|
-
"https://gitlab.com",
|
47
|
-
].freeze,
|
48
|
-
T::Array[String],
|
49
|
-
)
|
9
|
+
ALLOWED_TARGETS = [
|
10
|
+
Prism::CallNode,
|
11
|
+
Prism::ConstantReadNode,
|
12
|
+
Prism::ConstantWriteNode,
|
13
|
+
Prism::ConstantPathNode,
|
14
|
+
Prism::GlobalVariableAndWriteNode,
|
15
|
+
Prism::GlobalVariableOperatorWriteNode,
|
16
|
+
Prism::GlobalVariableOrWriteNode,
|
17
|
+
Prism::GlobalVariableReadNode,
|
18
|
+
Prism::GlobalVariableTargetNode,
|
19
|
+
Prism::GlobalVariableWriteNode,
|
20
|
+
Prism::InstanceVariableReadNode,
|
21
|
+
Prism::InstanceVariableAndWriteNode,
|
22
|
+
Prism::InstanceVariableOperatorWriteNode,
|
23
|
+
Prism::InstanceVariableOrWriteNode,
|
24
|
+
Prism::InstanceVariableTargetNode,
|
25
|
+
Prism::InstanceVariableWriteNode,
|
26
|
+
Prism::SymbolNode,
|
27
|
+
Prism::StringNode,
|
28
|
+
Prism::InterpolatedStringNode,
|
29
|
+
Prism::SuperNode,
|
30
|
+
Prism::ForwardingSuperNode,
|
31
|
+
Prism::YieldNode,
|
32
|
+
Prism::ClassVariableAndWriteNode,
|
33
|
+
Prism::ClassVariableOperatorWriteNode,
|
34
|
+
Prism::ClassVariableOrWriteNode,
|
35
|
+
Prism::ClassVariableReadNode,
|
36
|
+
Prism::ClassVariableTargetNode,
|
37
|
+
Prism::ClassVariableWriteNode,
|
38
|
+
] #: Array[singleton(Prism::Node)]
|
39
|
+
|
40
|
+
ALLOWED_REMOTE_PROVIDERS = [
|
41
|
+
"https://github.com",
|
42
|
+
"https://gitlab.com",
|
43
|
+
].freeze #: Array[String]
|
50
44
|
|
51
45
|
#: (ResponseBuilders::Hover response_builder, GlobalState global_state, URI::Generic uri, NodeContext node_context, Prism::Dispatcher dispatcher, RubyDocument::SorbetLevel sorbet_level) -> void
|
52
46
|
def initialize(response_builder, global_state, uri, node_context, dispatcher, sorbet_level) # rubocop:disable Metrics/ParameterLists
|
53
47
|
@response_builder = response_builder
|
54
48
|
@global_state = global_state
|
55
|
-
@index =
|
56
|
-
@type_inferrer =
|
57
|
-
@path =
|
49
|
+
@index = global_state.index #: RubyIndexer::Index
|
50
|
+
@type_inferrer = global_state.type_inferrer #: TypeInferrer
|
51
|
+
@path = uri.to_standardized_path #: String?
|
58
52
|
@node_context = node_context
|
59
53
|
@sorbet_level = sorbet_level
|
60
54
|
|
@@ -387,14 +381,11 @@ module RubyLsp
|
|
387
381
|
spec = Gem::Specification.find_by_name(first_argument.content)
|
388
382
|
return unless spec
|
389
383
|
|
390
|
-
info =
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
].find { |text| !text.nil? && !text.empty? },
|
396
|
-
String,
|
397
|
-
)
|
384
|
+
info = [
|
385
|
+
spec.description,
|
386
|
+
spec.summary,
|
387
|
+
"This rubygem does not have a description or summary.",
|
388
|
+
].find { |text| !text.nil? && !text.empty? } #: String
|
398
389
|
|
399
390
|
# Remove leading whitespace if a heredoc was used for the summary or description
|
400
391
|
info = info.gsub(/^ +/, "")
|
@@ -6,7 +6,7 @@ module RubyLsp
|
|
6
6
|
class InlayHints
|
7
7
|
include Requests::Support::Common
|
8
8
|
|
9
|
-
RESCUE_STRING_LENGTH =
|
9
|
+
RESCUE_STRING_LENGTH = "rescue".length #: Integer
|
10
10
|
|
11
11
|
#: (ResponseBuilders::CollectionResponseBuilder[Interface::InlayHint] response_builder, RequestConfig hints_configuration, Prism::Dispatcher dispatcher) -> void
|
12
12
|
def initialize(response_builder, hints_configuration, dispatcher)
|
@@ -6,24 +6,21 @@ module RubyLsp
|
|
6
6
|
class SemanticHighlighting
|
7
7
|
include Requests::Support::Common
|
8
8
|
|
9
|
-
SPECIAL_RUBY_METHODS =
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
].flatten.map(&:to_s).freeze,
|
17
|
-
T::Array[String],
|
18
|
-
)
|
9
|
+
SPECIAL_RUBY_METHODS = [
|
10
|
+
Module.instance_methods(false),
|
11
|
+
Kernel.instance_methods(false),
|
12
|
+
Kernel.methods(false),
|
13
|
+
Bundler::Dsl.instance_methods(false),
|
14
|
+
Module.private_instance_methods(false),
|
15
|
+
].flatten.map(&:to_s).freeze #: Array[String]
|
19
16
|
|
20
17
|
#: (Prism::Dispatcher dispatcher, ResponseBuilders::SemanticHighlighting response_builder) -> void
|
21
18
|
def initialize(dispatcher, response_builder)
|
22
19
|
@response_builder = response_builder
|
23
|
-
@special_methods =
|
24
|
-
@current_scope =
|
25
|
-
@inside_regex_capture =
|
26
|
-
@inside_implicit_node =
|
20
|
+
@special_methods = nil #: Array[String]?
|
21
|
+
@current_scope = Scope.new #: Scope
|
22
|
+
@inside_regex_capture = false #: bool
|
23
|
+
@inside_implicit_node = false #: bool
|
27
24
|
|
28
25
|
dispatcher.register(
|
29
26
|
self,
|
@@ -11,8 +11,8 @@ module RubyLsp
|
|
11
11
|
@sorbet_level = sorbet_level
|
12
12
|
@response_builder = response_builder
|
13
13
|
@global_state = global_state
|
14
|
-
@index =
|
15
|
-
@type_inferrer =
|
14
|
+
@index = global_state.index #: RubyIndexer::Index
|
15
|
+
@type_inferrer = global_state.type_inferrer #: TypeInferrer
|
16
16
|
@node_context = node_context
|
17
17
|
dispatcher.register(self, :on_call_node_enter)
|
18
18
|
end
|
@@ -3,28 +3,20 @@
|
|
3
3
|
|
4
4
|
module RubyLsp
|
5
5
|
module Listeners
|
6
|
-
class SpecStyle
|
6
|
+
class SpecStyle < TestDiscovery
|
7
7
|
extend T::Sig
|
8
|
-
include Requests::Support::Common
|
9
|
-
|
10
|
-
DYNAMIC_REFERENCE_MARKER = "<dynamic_reference>"
|
11
8
|
|
12
9
|
#: (response_builder: ResponseBuilders::TestCollection, global_state: GlobalState, dispatcher: Prism::Dispatcher, uri: URI::Generic) -> void
|
13
10
|
def initialize(response_builder, global_state, dispatcher, uri)
|
14
|
-
|
15
|
-
|
16
|
-
@
|
17
|
-
@
|
18
|
-
@nesting = T.let([], T::Array[String])
|
19
|
-
@describe_block_nesting = T.let([], T::Array[String])
|
20
|
-
@spec_class_stack = T.let([], T::Array[T::Boolean])
|
11
|
+
super
|
12
|
+
|
13
|
+
@describe_block_nesting = [] #: Array[String]
|
14
|
+
@spec_class_stack = [] #: Array[bool]
|
21
15
|
|
22
16
|
dispatcher.register(
|
23
17
|
self,
|
18
|
+
# Common handlers registered in parent class
|
24
19
|
:on_class_node_enter,
|
25
|
-
:on_class_node_leave,
|
26
|
-
:on_module_node_enter,
|
27
|
-
:on_module_node_leave,
|
28
20
|
:on_call_node_enter, # e.g. `describe` or `it`
|
29
21
|
:on_call_node_leave,
|
30
22
|
)
|
@@ -32,46 +24,16 @@ module RubyLsp
|
|
32
24
|
|
33
25
|
#: (node: Prism::ClassNode) -> void
|
34
26
|
def on_class_node_enter(node)
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
fully_qualified_name = RubyIndexer::Index.actual_nesting(@nesting, name).join("::")
|
40
|
-
|
41
|
-
attached_ancestors = begin
|
42
|
-
@index.linearized_ancestors_of(fully_qualified_name)
|
43
|
-
rescue RubyIndexer::Index::NonExistingNamespaceError
|
44
|
-
# When there are dynamic parts in the constant path, we will not have indexed the namespace. We can still
|
45
|
-
# provide test functionality if the class inherits directly from Test::Unit::TestCase or Minitest::Test
|
46
|
-
[node.superclass&.slice].compact
|
27
|
+
with_test_ancestor_tracking(node) do |_, ancestors|
|
28
|
+
is_spec = ancestors.include?("Minitest::Spec")
|
29
|
+
@spec_class_stack.push(is_spec)
|
47
30
|
end
|
48
|
-
|
49
|
-
is_spec = attached_ancestors.include?("Minitest::Spec")
|
50
|
-
@spec_class_stack.push(is_spec)
|
51
|
-
|
52
|
-
@nesting << name
|
53
|
-
end
|
54
|
-
|
55
|
-
#: (node: Prism::ModuleNode) -> void
|
56
|
-
def on_module_node_enter(node)
|
57
|
-
@visibility_stack << :public
|
58
|
-
|
59
|
-
name = constant_name(node.constant_path)
|
60
|
-
name ||= name_with_dynamic_reference(node.constant_path)
|
61
|
-
|
62
|
-
@nesting << name
|
63
|
-
end
|
64
|
-
|
65
|
-
#: (node: Prism::ModuleNode) -> void
|
66
|
-
def on_module_node_leave(node)
|
67
|
-
@visibility_stack.pop
|
68
|
-
@nesting.pop
|
69
31
|
end
|
70
32
|
|
71
33
|
#: (node: Prism::ClassNode) -> void
|
72
|
-
def on_class_node_leave(node)
|
73
|
-
|
74
|
-
|
34
|
+
def on_class_node_leave(node) # rubocop:disable RubyLsp/UseRegisterWithHandlerMethod
|
35
|
+
super
|
36
|
+
|
75
37
|
@spec_class_stack.pop
|
76
38
|
end
|
77
39
|
|
@@ -109,7 +71,7 @@ module RubyLsp
|
|
109
71
|
description,
|
110
72
|
@uri,
|
111
73
|
range_from_node(node),
|
112
|
-
|
74
|
+
framework: :minitest,
|
113
75
|
)
|
114
76
|
@response_builder.add(test_item)
|
115
77
|
else
|
@@ -141,7 +103,7 @@ module RubyLsp
|
|
141
103
|
description,
|
142
104
|
@uri,
|
143
105
|
range_from_node(node),
|
144
|
-
|
106
|
+
framework: :minitest,
|
145
107
|
)
|
146
108
|
parent_test_group.add(test_item)
|
147
109
|
end
|
@@ -155,7 +117,7 @@ module RubyLsp
|
|
155
117
|
end
|
156
118
|
return unless root_group_name
|
157
119
|
|
158
|
-
test_group =
|
120
|
+
test_group = @response_builder[root_group_name] #: Requests::Support::TestItem?
|
159
121
|
return unless test_group
|
160
122
|
|
161
123
|
return test_group unless nested_describe_groups
|
@@ -188,12 +150,6 @@ module RubyLsp
|
|
188
150
|
|
189
151
|
T.must(@spec_class_stack.last)
|
190
152
|
end
|
191
|
-
|
192
|
-
#: (node: Prism::ConstantPathNode | Prism::ConstantReadNode | Prism::ConstantPathTargetNode | Prism::CallNode | Prism::MissingNode) -> String
|
193
|
-
def name_with_dynamic_reference(node)
|
194
|
-
slice = node.slice
|
195
|
-
slice.gsub(/((?<=::)|^)[a-z]\w*/, DYNAMIC_REFERENCE_MARKER)
|
196
|
-
end
|
197
153
|
end
|
198
154
|
end
|
199
155
|
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module RubyLsp
|
5
|
+
module Listeners
|
6
|
+
class TestDiscovery
|
7
|
+
extend T::Helpers
|
8
|
+
abstract!
|
9
|
+
|
10
|
+
include Requests::Support::Common
|
11
|
+
|
12
|
+
DYNAMIC_REFERENCE_MARKER = "<dynamic_reference>"
|
13
|
+
|
14
|
+
#: (ResponseBuilders::TestCollection response_builder, GlobalState global_state, Prism::Dispatcher dispatcher, URI::Generic uri) -> void
|
15
|
+
def initialize(response_builder, global_state, dispatcher, uri)
|
16
|
+
@response_builder = response_builder
|
17
|
+
@uri = uri
|
18
|
+
@index = global_state.index #: RubyIndexer::Index
|
19
|
+
@visibility_stack = [:public] #: Array[Symbol]
|
20
|
+
@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
|
+
end
|
29
|
+
|
30
|
+
#: (Prism::ModuleNode node) -> void
|
31
|
+
def on_module_node_enter(node)
|
32
|
+
@visibility_stack << :public
|
33
|
+
|
34
|
+
name = constant_name(node.constant_path)
|
35
|
+
name ||= name_with_dynamic_reference(node.constant_path)
|
36
|
+
|
37
|
+
@nesting << name
|
38
|
+
end
|
39
|
+
|
40
|
+
#: (Prism::ModuleNode node) -> void
|
41
|
+
def on_module_node_leave(node)
|
42
|
+
@visibility_stack.pop
|
43
|
+
@nesting.pop
|
44
|
+
end
|
45
|
+
|
46
|
+
#: (Prism::ClassNode node) -> void
|
47
|
+
def on_class_node_leave(node)
|
48
|
+
@visibility_stack.pop
|
49
|
+
@nesting.pop
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
#: (String? name) -> String
|
55
|
+
def calc_fully_qualified_name(name)
|
56
|
+
RubyIndexer::Index.actual_nesting(@nesting, name).join("::")
|
57
|
+
end
|
58
|
+
|
59
|
+
#: (Prism::ClassNode node, String fully_qualified_name) -> Array[String]
|
60
|
+
def calc_attached_ancestors(node, fully_qualified_name)
|
61
|
+
@index.linearized_ancestors_of(fully_qualified_name)
|
62
|
+
rescue RubyIndexer::Index::NonExistingNamespaceError
|
63
|
+
# When there are dynamic parts in the constant path, we will not have indexed the namespace. We can still
|
64
|
+
# provide test functionality if the class inherits directly from Test::Unit::TestCase or Minitest::Test
|
65
|
+
[node.superclass&.slice].compact
|
66
|
+
end
|
67
|
+
|
68
|
+
#: (Prism::ConstantPathNode | Prism::ConstantReadNode | Prism::ConstantPathTargetNode | Prism::CallNode | Prism::MissingNode node) -> String
|
69
|
+
def name_with_dynamic_reference(node)
|
70
|
+
slice = node.slice
|
71
|
+
slice.gsub(/((?<=::)|^)[a-z]\w*/, DYNAMIC_REFERENCE_MARKER)
|
72
|
+
end
|
73
|
+
|
74
|
+
#: (Prism::ClassNode node, ^(String name, Array[String] ancestors) -> void block) -> void
|
75
|
+
def with_test_ancestor_tracking(node, &block)
|
76
|
+
@visibility_stack << :public
|
77
|
+
name = constant_name(node.constant_path)
|
78
|
+
name ||= name_with_dynamic_reference(node.constant_path)
|
79
|
+
|
80
|
+
fully_qualified_name = calc_fully_qualified_name(name)
|
81
|
+
attached_ancestors = calc_attached_ancestors(node, fully_qualified_name)
|
82
|
+
|
83
|
+
block.call(fully_qualified_name, attached_ancestors)
|
84
|
+
|
85
|
+
@nesting << name
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -3,7 +3,7 @@
|
|
3
3
|
|
4
4
|
module RubyLsp
|
5
5
|
module Listeners
|
6
|
-
class TestStyle
|
6
|
+
class TestStyle < TestDiscovery
|
7
7
|
class << self
|
8
8
|
# Resolves the minimal set of commands required to execute the requested tests
|
9
9
|
#: (Array[Hash[Symbol, untyped]]) -> Array[String]
|
@@ -24,6 +24,7 @@ module RubyLsp
|
|
24
24
|
until queue.empty?
|
25
25
|
item = T.must(queue.shift)
|
26
26
|
tags = Set.new(item[:tags])
|
27
|
+
next unless tags.include?("framework:minitest") || tags.include?("framework:test_unit")
|
27
28
|
|
28
29
|
children = item[:children]
|
29
30
|
uri = URI(item[:uri])
|
@@ -31,7 +32,12 @@ module RubyLsp
|
|
31
32
|
next unless path
|
32
33
|
|
33
34
|
if tags.include?("test_dir")
|
34
|
-
|
35
|
+
if children.empty?
|
36
|
+
full_files.concat(Dir.glob(
|
37
|
+
"#{path}/**/{*_test,test_*}.rb",
|
38
|
+
File::Constants::FNM_EXTGLOB | File::Constants::FNM_PATHNAME,
|
39
|
+
))
|
40
|
+
end
|
35
41
|
elsif tags.include?("test_file")
|
36
42
|
full_files << path if children.empty?
|
37
43
|
elsif tags.include?("test_group")
|
@@ -40,7 +46,7 @@ module RubyLsp
|
|
40
46
|
unless children.any? && children.all? { |child| child[:tags].include?("test_group") }
|
41
47
|
aggregated_tests[path][item[:label]] = { tags: tags, examples: [] }
|
42
48
|
end
|
43
|
-
|
49
|
+
else
|
44
50
|
class_name, method_name = item[:id].split("#")
|
45
51
|
aggregated_tests[path][class_name][:examples] << method_name
|
46
52
|
aggregated_tests[path][class_name][:tags].merge(tags)
|
@@ -55,7 +61,7 @@ module RubyLsp
|
|
55
61
|
# Separate groups into Minitest and Test Unit. You can have both frameworks in the same file, but you cannot
|
56
62
|
# have a group belongs to both at the same time
|
57
63
|
minitest_groups, test_unit_groups = groups_and_examples.partition do |_, info|
|
58
|
-
info[:tags].include?("minitest")
|
64
|
+
info[:tags].include?("framework:minitest")
|
59
65
|
end
|
60
66
|
|
61
67
|
if minitest_groups.any?
|
@@ -67,7 +73,10 @@ module RubyLsp
|
|
67
73
|
end
|
68
74
|
end
|
69
75
|
|
70
|
-
|
76
|
+
unless full_files.empty?
|
77
|
+
commands << "#{BASE_COMMAND} -Itest -e \"ARGV.each { |f| require f }\" #{full_files.join(" ")}"
|
78
|
+
end
|
79
|
+
|
71
80
|
commands
|
72
81
|
end
|
73
82
|
|
@@ -77,7 +86,10 @@ module RubyLsp
|
|
77
86
|
def handle_minitest_groups(file_path, groups_and_examples)
|
78
87
|
regexes = groups_and_examples.flat_map do |group, info|
|
79
88
|
examples = info[:examples]
|
80
|
-
group_regex = Shellwords.escape(group).gsub(
|
89
|
+
group_regex = Shellwords.escape(group).gsub(
|
90
|
+
Shellwords.escape(TestDiscovery::DYNAMIC_REFERENCE_MARKER),
|
91
|
+
".*",
|
92
|
+
)
|
81
93
|
if examples.empty?
|
82
94
|
"^#{group_regex}(#|::)"
|
83
95
|
elsif examples.length == 1
|
@@ -100,7 +112,10 @@ module RubyLsp
|
|
100
112
|
def handle_test_unit_groups(file_path, groups_and_examples)
|
101
113
|
groups_and_examples.map do |group, info|
|
102
114
|
examples = info[:examples]
|
103
|
-
group_regex = Shellwords.escape(group).gsub(
|
115
|
+
group_regex = Shellwords.escape(group).gsub(
|
116
|
+
Shellwords.escape(TestDiscovery::DYNAMIC_REFERENCE_MARKER),
|
117
|
+
".*",
|
118
|
+
)
|
104
119
|
command = +"#{BASE_COMMAND} -Itest #{file_path} --testcase \"/^#{group_regex}$/\""
|
105
120
|
|
106
121
|
unless examples.empty?
|
@@ -118,33 +133,26 @@ module RubyLsp
|
|
118
133
|
|
119
134
|
include Requests::Support::Common
|
120
135
|
|
136
|
+
MINITEST_REPORTER_PATH = File.expand_path("../ruby_lsp_reporter_plugin.rb", __dir__) #: String
|
137
|
+
TEST_UNIT_REPORTER_PATH = File.expand_path("../test_unit_test_runner.rb", __dir__) #: String
|
121
138
|
ACCESS_MODIFIERS = [:public, :private, :protected].freeze
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
"ruby"
|
129
|
-
end,
|
130
|
-
String,
|
131
|
-
)
|
139
|
+
BASE_COMMAND = begin
|
140
|
+
Bundler.with_original_env { Bundler.default_lockfile }
|
141
|
+
"bundle exec ruby"
|
142
|
+
rescue Bundler::GemfileNotFound
|
143
|
+
"ruby"
|
144
|
+
end #: String
|
132
145
|
|
133
146
|
#: (ResponseBuilders::TestCollection response_builder, GlobalState global_state, Prism::Dispatcher dispatcher, URI::Generic uri) -> void
|
134
147
|
def initialize(response_builder, global_state, dispatcher, uri)
|
135
|
-
|
136
|
-
|
137
|
-
@
|
138
|
-
@visibility_stack = T.let([:public], T::Array[Symbol])
|
139
|
-
@nesting = T.let([], T::Array[String])
|
140
|
-
@framework_tag = T.let(:minitest, Symbol)
|
148
|
+
super
|
149
|
+
|
150
|
+
@framework = :minitest #: Symbol
|
141
151
|
|
142
152
|
dispatcher.register(
|
143
153
|
self,
|
154
|
+
# Common handlers registered in parent class
|
144
155
|
:on_class_node_enter,
|
145
|
-
:on_class_node_leave,
|
146
|
-
:on_module_node_enter,
|
147
|
-
:on_module_node_leave,
|
148
156
|
:on_def_node_enter,
|
149
157
|
:on_call_node_enter,
|
150
158
|
:on_call_node_leave,
|
@@ -153,55 +161,19 @@ module RubyLsp
|
|
153
161
|
|
154
162
|
#: (Prism::ClassNode node) -> void
|
155
163
|
def on_class_node_enter(node)
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
end
|
169
|
-
|
170
|
-
@framework_tag = :test_unit if attached_ancestors.include?("Test::Unit::TestCase")
|
171
|
-
|
172
|
-
if @framework_tag == :test_unit || non_declarative_minitest?(attached_ancestors, fully_qualified_name)
|
173
|
-
@response_builder.add(Requests::Support::TestItem.new(
|
174
|
-
fully_qualified_name,
|
175
|
-
fully_qualified_name,
|
176
|
-
@uri,
|
177
|
-
range_from_node(node),
|
178
|
-
tags: [@framework_tag],
|
179
|
-
))
|
164
|
+
with_test_ancestor_tracking(node) do |name, ancestors|
|
165
|
+
@framework = :test_unit if ancestors.include?("Test::Unit::TestCase")
|
166
|
+
|
167
|
+
if @framework == :test_unit || non_declarative_minitest?(ancestors, name)
|
168
|
+
@response_builder.add(Requests::Support::TestItem.new(
|
169
|
+
name,
|
170
|
+
name,
|
171
|
+
@uri,
|
172
|
+
range_from_node(node),
|
173
|
+
framework: @framework,
|
174
|
+
))
|
175
|
+
end
|
180
176
|
end
|
181
|
-
|
182
|
-
@nesting << name
|
183
|
-
end
|
184
|
-
|
185
|
-
#: (Prism::ModuleNode node) -> void
|
186
|
-
def on_module_node_enter(node)
|
187
|
-
@visibility_stack << :public
|
188
|
-
|
189
|
-
name = constant_name(node.constant_path)
|
190
|
-
name ||= name_with_dynamic_reference(node.constant_path)
|
191
|
-
|
192
|
-
@nesting << name
|
193
|
-
end
|
194
|
-
|
195
|
-
#: (Prism::ModuleNode node) -> void
|
196
|
-
def on_module_node_leave(node)
|
197
|
-
@visibility_stack.pop
|
198
|
-
@nesting.pop
|
199
|
-
end
|
200
|
-
|
201
|
-
#: (Prism::ClassNode node) -> void
|
202
|
-
def on_class_node_leave(node)
|
203
|
-
@visibility_stack.pop
|
204
|
-
@nesting.pop
|
205
177
|
end
|
206
178
|
|
207
179
|
#: (Prism::DefNode node) -> void
|
@@ -224,7 +196,7 @@ module RubyLsp
|
|
224
196
|
name,
|
225
197
|
@uri,
|
226
198
|
range_from_node(node),
|
227
|
-
|
199
|
+
framework: @framework,
|
228
200
|
))
|
229
201
|
end
|
230
202
|
|
@@ -259,12 +231,6 @@ module RubyLsp
|
|
259
231
|
rescue RubyIndexer::Index::NonExistingNamespaceError
|
260
232
|
true
|
261
233
|
end
|
262
|
-
|
263
|
-
#: ((Prism::ConstantPathNode | Prism::ConstantReadNode | Prism::ConstantPathTargetNode | Prism::CallNode | Prism::MissingNode) node) -> String
|
264
|
-
def name_with_dynamic_reference(node)
|
265
|
-
slice = node.slice
|
266
|
-
slice.gsub(/((?<=::)|^)[a-z]\w*/, DYNAMIC_REFERENCE_MARKER)
|
267
|
-
end
|
268
234
|
end
|
269
235
|
end
|
270
236
|
end
|
@@ -25,13 +25,13 @@ module RubyLsp
|
|
25
25
|
@call_node = call_node
|
26
26
|
|
27
27
|
nesting, surrounding_method = handle_nesting_nodes(nesting_nodes)
|
28
|
-
@nesting =
|
29
|
-
@surrounding_method =
|
28
|
+
@nesting = nesting #: Array[String]
|
29
|
+
@surrounding_method = surrounding_method #: String?
|
30
30
|
end
|
31
31
|
|
32
32
|
#: -> String
|
33
33
|
def fully_qualified_name
|
34
|
-
@fully_qualified_name ||=
|
34
|
+
@fully_qualified_name ||= @nesting.join("::") #: String?
|
35
35
|
end
|
36
36
|
|
37
37
|
#: -> Array[Symbol]
|
@@ -55,7 +55,7 @@ module RubyLsp
|
|
55
55
|
#: (Array[(Prism::ClassNode | Prism::ModuleNode | Prism::SingletonClassNode | Prism::DefNode | Prism::BlockNode | Prism::LambdaNode | Prism::ProgramNode)] nodes) -> [Array[String], String?]
|
56
56
|
def handle_nesting_nodes(nodes)
|
57
57
|
nesting = []
|
58
|
-
surrounding_method =
|
58
|
+
surrounding_method = nil #: String?
|
59
59
|
|
60
60
|
@nesting_nodes.each do |node|
|
61
61
|
case node
|
@@ -9,7 +9,7 @@ module RubyLsp
|
|
9
9
|
|
10
10
|
#: (source: String, version: Integer, uri: URI::Generic, global_state: GlobalState) -> void
|
11
11
|
def initialize(source:, version:, uri:, global_state:)
|
12
|
-
@syntax_error =
|
12
|
+
@syntax_error = false #: bool
|
13
13
|
super
|
14
14
|
end
|
15
15
|
|