ruby-lsp 0.23.11 → 0.23.16
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 +123 -169
- data/lib/ruby_indexer/lib/ruby_indexer/enhancement.rb +9 -7
- data/lib/ruby_indexer/lib/ruby_indexer/entry.rb +92 -202
- data/lib/ruby_indexer/lib/ruby_indexer/index.rb +116 -222
- 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 +22 -45
- 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 +5 -9
- 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 +139 -135
- data/lib/ruby_indexer/test/instance_variables_test.rb +37 -37
- data/lib/ruby_indexer/test/method_test.rb +143 -117
- data/lib/ruby_indexer/test/prefix_tree_test.rb +13 -13
- data/lib/ruby_indexer/test/rbs_indexer_test.rb +65 -71
- data/lib/ruby_indexer/test/test_case.rb +2 -2
- 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 +39 -45
- data/lib/ruby_lsp/erb_document.rb +36 -40
- 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 +60 -66
- data/lib/ruby_lsp/listeners/definition.rb +38 -52
- data/lib/ruby_lsp/listeners/document_highlight.rb +123 -150
- data/lib/ruby_lsp/listeners/document_link.rb +46 -63
- 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 +83 -102
- 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 +11 -26
- 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 +160 -88
- data/lib/ruby_lsp/node_context.rb +12 -39
- data/lib/ruby_lsp/rbs_document.rb +8 -6
- data/lib/ruby_lsp/requests/code_action_resolve.rb +24 -25
- data/lib/ruby_lsp/requests/code_actions.rb +14 -26
- data/lib/ruby_lsp/requests/code_lens.rb +6 -17
- 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 +8 -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 +87 -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 +8 -37
- data/lib/ruby_lsp/requests/rename.rb +19 -42
- data/lib/ruby_lsp/requests/request.rb +7 -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 +16 -51
- 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 +10 -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 +13 -18
- 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 +6 -10
- data/lib/ruby_lsp/ruby_document.rb +24 -62
- data/lib/ruby_lsp/scope.rb +7 -11
- data/lib/ruby_lsp/scripts/compose_bundle.rb +6 -4
- data/lib/ruby_lsp/server.rb +147 -79
- data/lib/ruby_lsp/setup_bundler.rb +65 -60
- data/lib/ruby_lsp/static_docs.rb +11 -7
- data/lib/ruby_lsp/store.rb +24 -42
- data/lib/ruby_lsp/test_helper.rb +2 -12
- data/lib/ruby_lsp/test_reporters/lsp_reporter.rb +164 -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 +49 -83
- metadata +9 -3
@@ -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,12 @@ 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 = T.
|
62
|
+
target = parent #: Prism::Node
|
63
|
+
parent = T.cast(target, Prism::ConstantPathNode).parent #: Prism::Node?
|
76
64
|
|
77
65
|
while parent && cover?(parent.location, position)
|
78
66
|
target = parent
|
@@ -83,7 +71,7 @@ module RubyLsp
|
|
83
71
|
end
|
84
72
|
|
85
73
|
# Checks if a given location covers the position requested
|
86
|
-
|
74
|
+
#: (Prism::Location? location, Hash[Symbol, untyped] position) -> bool
|
87
75
|
def covers_position?(location, position)
|
88
76
|
return false unless location
|
89
77
|
|
@@ -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: T::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, RubyDocument::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 | T::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
|
|
@@ -8,12 +8,11 @@ module RubyLsp
|
|
8
8
|
# WARNING: Methods in this class may be used by Ruby LSP add-ons such as
|
9
9
|
# https://github.com/Shopify/ruby-lsp-rails, or add-ons by created by developers outside of Shopify, so be
|
10
10
|
# cautious of changing anything.
|
11
|
-
extend T::Sig
|
12
11
|
extend T::Helpers
|
13
12
|
|
14
13
|
requires_ancestor { Kernel }
|
15
14
|
|
16
|
-
|
15
|
+
#: (Prism::Node node) -> Interface::Range
|
17
16
|
def range_from_node(node)
|
18
17
|
loc = node.location
|
19
18
|
|
@@ -26,7 +25,7 @@ module RubyLsp
|
|
26
25
|
)
|
27
26
|
end
|
28
27
|
|
29
|
-
|
28
|
+
#: ((Prism::Location | RubyIndexer::Location) location) -> Interface::Range
|
30
29
|
def range_from_location(location)
|
31
30
|
Interface::Range.new(
|
32
31
|
start: Interface::Position.new(
|
@@ -37,15 +36,7 @@ module RubyLsp
|
|
37
36
|
)
|
38
37
|
end
|
39
38
|
|
40
|
-
|
41
|
-
params(
|
42
|
-
node: Prism::Node,
|
43
|
-
title: String,
|
44
|
-
command_name: String,
|
45
|
-
arguments: T.nilable(T::Array[T.untyped]),
|
46
|
-
data: T.nilable(T::Hash[T.untyped, T.untyped]),
|
47
|
-
).returns(Interface::CodeLens)
|
48
|
-
end
|
39
|
+
#: (Prism::Node node, title: String, command_name: String, arguments: Array[untyped]?, data: Hash[untyped, untyped]?) -> Interface::CodeLens
|
49
40
|
def create_code_lens(node, title:, command_name:, arguments:, data:)
|
50
41
|
range = range_from_node(node)
|
51
42
|
|
@@ -60,26 +51,22 @@ module RubyLsp
|
|
60
51
|
)
|
61
52
|
end
|
62
53
|
|
63
|
-
|
54
|
+
#: (String file_path) -> bool?
|
64
55
|
def not_in_dependencies?(file_path)
|
65
56
|
BUNDLE_PATH &&
|
66
|
-
!file_path.start_with?(
|
57
|
+
!file_path.start_with?(
|
58
|
+
BUNDLE_PATH, #: as !nil
|
59
|
+
) &&
|
67
60
|
!file_path.start_with?(RbConfig::CONFIG["rubylibdir"])
|
68
61
|
end
|
69
62
|
|
70
|
-
|
63
|
+
#: (Prism::CallNode node) -> bool
|
71
64
|
def self_receiver?(node)
|
72
65
|
receiver = node.receiver
|
73
66
|
receiver.nil? || receiver.is_a?(Prism::SelfNode)
|
74
67
|
end
|
75
68
|
|
76
|
-
|
77
|
-
params(
|
78
|
-
title: String,
|
79
|
-
entries: T.any(T::Array[RubyIndexer::Entry], RubyIndexer::Entry),
|
80
|
-
max_entries: T.nilable(Integer),
|
81
|
-
).returns(T::Hash[Symbol, String])
|
82
|
-
end
|
69
|
+
#: (String title, (Array[RubyIndexer::Entry] | RubyIndexer::Entry) entries, ?Integer? max_entries) -> Hash[Symbol, String]
|
83
70
|
def categorized_markdown_from_index_entries(title, entries, max_entries = nil)
|
84
71
|
markdown_title = "```ruby\n#{title}\n```"
|
85
72
|
definitions = []
|
@@ -112,14 +99,7 @@ module RubyLsp
|
|
112
99
|
}
|
113
100
|
end
|
114
101
|
|
115
|
-
|
116
|
-
params(
|
117
|
-
title: String,
|
118
|
-
entries: T.any(T::Array[RubyIndexer::Entry], RubyIndexer::Entry),
|
119
|
-
max_entries: T.nilable(Integer),
|
120
|
-
extra_links: T.nilable(String),
|
121
|
-
).returns(String)
|
122
|
-
end
|
102
|
+
#: (String title, (Array[RubyIndexer::Entry] | RubyIndexer::Entry) entries, ?Integer? max_entries, ?extra_links: String?) -> String
|
123
103
|
def markdown_from_index_entries(title, entries, max_entries = nil, extra_links: nil)
|
124
104
|
categorized_markdown = categorized_markdown_from_index_entries(title, entries, max_entries)
|
125
105
|
|
@@ -135,22 +115,12 @@ module RubyLsp
|
|
135
115
|
MARKDOWN
|
136
116
|
end
|
137
117
|
|
138
|
-
|
139
|
-
params(
|
140
|
-
node: T.any(
|
141
|
-
Prism::ConstantPathNode,
|
142
|
-
Prism::ConstantReadNode,
|
143
|
-
Prism::ConstantPathTargetNode,
|
144
|
-
Prism::CallNode,
|
145
|
-
Prism::MissingNode,
|
146
|
-
),
|
147
|
-
).returns(T.nilable(String))
|
148
|
-
end
|
118
|
+
#: ((Prism::ConstantPathNode | Prism::ConstantReadNode | Prism::ConstantPathTargetNode | Prism::CallNode | Prism::MissingNode) node) -> String?
|
149
119
|
def constant_name(node)
|
150
120
|
RubyIndexer::Index.constant_name(node)
|
151
121
|
end
|
152
122
|
|
153
|
-
|
123
|
+
#: ((Prism::ModuleNode | Prism::ClassNode) node) -> String?
|
154
124
|
def namespace_constant_name(node)
|
155
125
|
path = node.constant_path
|
156
126
|
case path
|
@@ -162,14 +132,9 @@ module RubyLsp
|
|
162
132
|
# Iterates over each part of a constant path, so that we can easily push response items for each section of the
|
163
133
|
# name. For example, for `Foo::Bar::Baz`, this method will invoke the block with `Foo`, then `Bar` and finally
|
164
134
|
# `Baz`.
|
165
|
-
|
166
|
-
params(
|
167
|
-
node: Prism::Node,
|
168
|
-
block: T.proc.params(part: Prism::Node).void,
|
169
|
-
).void
|
170
|
-
end
|
135
|
+
#: (Prism::Node node) { (Prism::Node part) -> void } -> void
|
171
136
|
def each_constant_path_part(node, &block)
|
172
|
-
current =
|
137
|
+
current = node #: Prism::Node?
|
173
138
|
|
174
139
|
while current.is_a?(Prism::ConstantPathNode)
|
175
140
|
block.call(current)
|
@@ -177,7 +142,7 @@ module RubyLsp
|
|
177
142
|
end
|
178
143
|
end
|
179
144
|
|
180
|
-
|
145
|
+
#: (RubyIndexer::Entry entry) -> Integer?
|
181
146
|
def kind_for_entry(entry)
|
182
147
|
case entry
|
183
148
|
when RubyIndexer::Entry::Class
|
@@ -195,7 +160,7 @@ module RubyLsp
|
|
195
160
|
end
|
196
161
|
end
|
197
162
|
|
198
|
-
|
163
|
+
#: (RubyDocument::SorbetLevel sorbet_level) -> bool
|
199
164
|
def sorbet_level_true_or_higher?(sorbet_level)
|
200
165
|
sorbet_level == RubyDocument::SorbetLevel::True || sorbet_level == RubyDocument::SorbetLevel::Strict
|
201
166
|
end
|
@@ -5,40 +5,32 @@ module RubyLsp
|
|
5
5
|
module Requests
|
6
6
|
module Support
|
7
7
|
class RuboCopDiagnostic
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
begin
|
24
|
-
gem("rubocop", ">= 1.64.0")
|
25
|
-
true
|
26
|
-
rescue LoadError
|
27
|
-
false
|
28
|
-
end,
|
29
|
-
T::Boolean,
|
30
|
-
)
|
8
|
+
RUBOCOP_TO_LSP_SEVERITY = {
|
9
|
+
info: Constant::DiagnosticSeverity::HINT,
|
10
|
+
refactor: Constant::DiagnosticSeverity::INFORMATION,
|
11
|
+
convention: Constant::DiagnosticSeverity::INFORMATION,
|
12
|
+
warning: Constant::DiagnosticSeverity::WARNING,
|
13
|
+
error: Constant::DiagnosticSeverity::ERROR,
|
14
|
+
fatal: Constant::DiagnosticSeverity::ERROR,
|
15
|
+
}.freeze #: Hash[Symbol, Integer]
|
16
|
+
|
17
|
+
ENHANCED_DOC_URL = begin
|
18
|
+
gem("rubocop", ">= 1.64.0")
|
19
|
+
true
|
20
|
+
rescue LoadError
|
21
|
+
false
|
22
|
+
end #: bool
|
31
23
|
|
32
24
|
# TODO: avoid passing document once we have alternative ways to get at
|
33
25
|
# encoding and file source
|
34
|
-
|
26
|
+
#: (RubyDocument document, ::RuboCop::Cop::Offense offense, URI::Generic uri) -> void
|
35
27
|
def initialize(document, offense, uri)
|
36
28
|
@document = document
|
37
29
|
@offense = offense
|
38
30
|
@uri = uri
|
39
31
|
end
|
40
32
|
|
41
|
-
|
33
|
+
#: -> Array[Interface::CodeAction]
|
42
34
|
def to_lsp_code_actions
|
43
35
|
code_actions = []
|
44
36
|
|
@@ -48,7 +40,7 @@ module RubyLsp
|
|
48
40
|
code_actions
|
49
41
|
end
|
50
42
|
|
51
|
-
|
43
|
+
#: (::RuboCop::Config config) -> Interface::Diagnostic
|
52
44
|
def to_lsp_diagnostic(config)
|
53
45
|
# highlighted_area contains the begin and end position of the first line
|
54
46
|
# This ensures that multiline offenses don't clutter the editor
|
@@ -78,19 +70,19 @@ module RubyLsp
|
|
78
70
|
|
79
71
|
private
|
80
72
|
|
81
|
-
|
73
|
+
#: -> String
|
82
74
|
def message
|
83
75
|
message = @offense.message
|
84
76
|
message += "\n\nThis offense is not auto-correctable.\n" unless correctable?
|
85
77
|
message
|
86
78
|
end
|
87
79
|
|
88
|
-
|
80
|
+
#: -> Integer?
|
89
81
|
def severity
|
90
82
|
RUBOCOP_TO_LSP_SEVERITY[@offense.severity.name]
|
91
83
|
end
|
92
84
|
|
93
|
-
|
85
|
+
#: (::RuboCop::Config config) -> Interface::CodeDescription?
|
94
86
|
def code_description(config)
|
95
87
|
cop = RuboCopRunner.find_cop_by_name(@offense.cop_name)
|
96
88
|
return unless cop
|
@@ -103,7 +95,7 @@ module RubyLsp
|
|
103
95
|
Interface::CodeDescription.new(href: doc_url) if doc_url
|
104
96
|
end
|
105
97
|
|
106
|
-
|
98
|
+
#: -> Interface::CodeAction
|
107
99
|
def autocorrect_action
|
108
100
|
Interface::CodeAction.new(
|
109
101
|
title: "Autocorrect #{@offense.cop_name}",
|
@@ -123,7 +115,7 @@ module RubyLsp
|
|
123
115
|
)
|
124
116
|
end
|
125
117
|
|
126
|
-
|
118
|
+
#: -> Array[Interface::TextEdit]
|
127
119
|
def offense_replacements
|
128
120
|
@offense.corrector.as_replacements.map do |range, replacement|
|
129
121
|
Interface::TextEdit.new(
|
@@ -136,7 +128,7 @@ module RubyLsp
|
|
136
128
|
end
|
137
129
|
end
|
138
130
|
|
139
|
-
|
131
|
+
#: -> Interface::CodeAction
|
140
132
|
def disable_line_action
|
141
133
|
Interface::CodeAction.new(
|
142
134
|
title: "Disable #{@offense.cop_name} for this line",
|
@@ -155,7 +147,7 @@ module RubyLsp
|
|
155
147
|
)
|
156
148
|
end
|
157
149
|
|
158
|
-
|
150
|
+
#: -> Array[Interface::TextEdit]
|
159
151
|
def line_disable_comment
|
160
152
|
new_text = if @offense.source_line.include?(" # rubocop:disable ")
|
161
153
|
",#{@offense.cop_name}"
|
@@ -178,7 +170,7 @@ module RubyLsp
|
|
178
170
|
[inline_comment]
|
179
171
|
end
|
180
172
|
|
181
|
-
|
173
|
+
#: (String line) -> Integer
|
182
174
|
def length_of_line(line)
|
183
175
|
if @document.encoding == Encoding::UTF_16LE
|
184
176
|
line_length = 0
|
@@ -197,7 +189,7 @@ module RubyLsp
|
|
197
189
|
# When `RuboCop::LSP.enable` is called, contextual autocorrect will not offer itself
|
198
190
|
# as `correctable?` to prevent annoying changes while typing. Instead check if
|
199
191
|
# a corrector is present. If it is, then that means some code transformation can be applied.
|
200
|
-
|
192
|
+
#: -> bool
|
201
193
|
def correctable?
|
202
194
|
!@offense.corrector.nil?
|
203
195
|
end
|