ruby-lsp 0.23.11 → 0.23.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +2 -2
- data/VERSION +1 -1
- data/exe/ruby-lsp-launcher +20 -11
- data/lib/rubocop/cop/ruby_lsp/use_language_server_aliases.rb +1 -1
- data/lib/rubocop/cop/ruby_lsp/use_register_with_handler_method.rb +3 -5
- data/lib/ruby_indexer/lib/ruby_indexer/configuration.rb +82 -116
- data/lib/ruby_indexer/lib/ruby_indexer/declaration_listener.rb +134 -183
- data/lib/ruby_indexer/lib/ruby_indexer/enhancement.rb +9 -10
- data/lib/ruby_indexer/lib/ruby_indexer/entry.rb +97 -217
- data/lib/ruby_indexer/lib/ruby_indexer/index.rb +139 -281
- data/lib/ruby_indexer/lib/ruby_indexer/location.rb +4 -27
- data/lib/ruby_indexer/lib/ruby_indexer/prefix_tree.rb +18 -19
- data/lib/ruby_indexer/lib/ruby_indexer/rbs_indexer.rb +23 -55
- data/lib/ruby_indexer/lib/ruby_indexer/reference_finder.rb +47 -61
- data/lib/ruby_indexer/lib/ruby_indexer/uri.rb +17 -19
- data/lib/ruby_indexer/lib/ruby_indexer/visibility_scope.rb +7 -11
- data/lib/ruby_indexer/test/class_variables_test.rb +14 -14
- data/lib/ruby_indexer/test/classes_and_modules_test.rb +65 -40
- data/lib/ruby_indexer/test/configuration_test.rb +48 -7
- data/lib/ruby_indexer/test/constant_test.rb +34 -34
- data/lib/ruby_indexer/test/enhancements_test.rb +1 -1
- data/lib/ruby_indexer/test/index_test.rb +146 -135
- data/lib/ruby_indexer/test/instance_variables_test.rb +37 -37
- data/lib/ruby_indexer/test/method_test.rb +149 -123
- data/lib/ruby_indexer/test/prefix_tree_test.rb +13 -13
- data/lib/ruby_indexer/test/rbs_indexer_test.rb +68 -73
- data/lib/ruby_indexer/test/test_case.rb +9 -3
- data/lib/ruby_indexer/test/uri_test.rb +15 -2
- data/lib/ruby_lsp/addon.rb +44 -71
- data/lib/ruby_lsp/base_server.rb +29 -32
- data/lib/ruby_lsp/client_capabilities.rb +10 -12
- data/lib/ruby_lsp/document.rb +40 -54
- data/lib/ruby_lsp/erb_document.rb +37 -41
- data/lib/ruby_lsp/global_state.rb +52 -57
- data/lib/ruby_lsp/internal.rb +2 -0
- data/lib/ruby_lsp/listeners/code_lens.rb +82 -89
- data/lib/ruby_lsp/listeners/completion.rb +67 -73
- data/lib/ruby_lsp/listeners/definition.rb +44 -58
- data/lib/ruby_lsp/listeners/document_highlight.rb +123 -150
- data/lib/ruby_lsp/listeners/document_link.rb +50 -70
- data/lib/ruby_lsp/listeners/document_symbol.rb +38 -52
- data/lib/ruby_lsp/listeners/folding_ranges.rb +40 -43
- data/lib/ruby_lsp/listeners/hover.rb +92 -110
- data/lib/ruby_lsp/listeners/inlay_hints.rb +4 -11
- data/lib/ruby_lsp/listeners/semantic_highlighting.rb +54 -56
- data/lib/ruby_lsp/listeners/signature_help.rb +12 -27
- data/lib/ruby_lsp/listeners/spec_style.rb +155 -0
- data/lib/ruby_lsp/listeners/test_discovery.rb +89 -0
- data/lib/ruby_lsp/listeners/test_style.rb +167 -90
- data/lib/ruby_lsp/node_context.rb +12 -39
- data/lib/ruby_lsp/rbs_document.rb +9 -7
- data/lib/ruby_lsp/requests/code_action_resolve.rb +63 -59
- data/lib/ruby_lsp/requests/code_actions.rb +14 -26
- data/lib/ruby_lsp/requests/code_lens.rb +20 -19
- data/lib/ruby_lsp/requests/completion.rb +7 -20
- data/lib/ruby_lsp/requests/completion_resolve.rb +6 -6
- data/lib/ruby_lsp/requests/definition.rb +7 -17
- data/lib/ruby_lsp/requests/diagnostics.rb +8 -11
- data/lib/ruby_lsp/requests/discover_tests.rb +18 -5
- data/lib/ruby_lsp/requests/document_highlight.rb +5 -15
- data/lib/ruby_lsp/requests/document_link.rb +6 -17
- data/lib/ruby_lsp/requests/document_symbol.rb +5 -8
- data/lib/ruby_lsp/requests/folding_ranges.rb +7 -15
- data/lib/ruby_lsp/requests/formatting.rb +6 -9
- data/lib/ruby_lsp/requests/go_to_relevant_file.rb +85 -0
- data/lib/ruby_lsp/requests/hover.rb +10 -20
- data/lib/ruby_lsp/requests/inlay_hints.rb +6 -17
- data/lib/ruby_lsp/requests/on_type_formatting.rb +32 -40
- data/lib/ruby_lsp/requests/prepare_rename.rb +4 -9
- data/lib/ruby_lsp/requests/prepare_type_hierarchy.rb +5 -15
- data/lib/ruby_lsp/requests/range_formatting.rb +5 -6
- data/lib/ruby_lsp/requests/references.rb +9 -53
- data/lib/ruby_lsp/requests/rename.rb +20 -46
- data/lib/ruby_lsp/requests/request.rb +8 -19
- data/lib/ruby_lsp/requests/selection_ranges.rb +6 -6
- data/lib/ruby_lsp/requests/semantic_highlighting.rb +16 -35
- data/lib/ruby_lsp/requests/show_syntax_tree.rb +7 -8
- data/lib/ruby_lsp/requests/signature_help.rb +8 -26
- data/lib/ruby_lsp/requests/support/annotation.rb +4 -10
- data/lib/ruby_lsp/requests/support/common.rb +15 -55
- data/lib/ruby_lsp/requests/support/rubocop_diagnostic.rb +27 -35
- data/lib/ruby_lsp/requests/support/rubocop_formatter.rb +11 -14
- data/lib/ruby_lsp/requests/support/rubocop_runner.rb +22 -34
- data/lib/ruby_lsp/requests/support/selection_range.rb +1 -3
- data/lib/ruby_lsp/requests/support/sorbet.rb +29 -38
- data/lib/ruby_lsp/requests/support/source_uri.rb +20 -32
- data/lib/ruby_lsp/requests/support/syntax_tree_formatter.rb +12 -19
- data/lib/ruby_lsp/requests/support/test_item.rb +16 -14
- data/lib/ruby_lsp/requests/type_hierarchy_supertypes.rb +5 -6
- data/lib/ruby_lsp/requests/workspace_symbol.rb +4 -4
- data/lib/ruby_lsp/response_builders/collection_response_builder.rb +5 -5
- data/lib/ruby_lsp/response_builders/document_symbol.rb +14 -19
- data/lib/ruby_lsp/response_builders/hover.rb +11 -14
- data/lib/ruby_lsp/response_builders/response_builder.rb +1 -1
- data/lib/ruby_lsp/response_builders/semantic_highlighting.rb +60 -88
- data/lib/ruby_lsp/response_builders/signature_help.rb +5 -6
- data/lib/ruby_lsp/response_builders/test_collection.rb +43 -10
- data/lib/ruby_lsp/ruby_document.rb +24 -92
- data/lib/ruby_lsp/scope.rb +7 -11
- data/lib/ruby_lsp/scripts/compose_bundle.rb +6 -4
- data/lib/ruby_lsp/server.rb +182 -99
- data/lib/ruby_lsp/setup_bundler.rb +65 -60
- data/lib/ruby_lsp/static_docs.rb +11 -7
- data/lib/ruby_lsp/store.rb +29 -47
- data/lib/ruby_lsp/test_helper.rb +2 -12
- data/lib/ruby_lsp/test_reporters/lsp_reporter.rb +191 -0
- data/lib/ruby_lsp/test_reporters/minitest_reporter.rb +105 -0
- data/lib/ruby_lsp/test_reporters/test_unit_reporter.rb +94 -0
- data/lib/ruby_lsp/type_inferrer.rb +13 -14
- data/lib/ruby_lsp/utils.rb +92 -83
- metadata +9 -3
@@ -13,16 +13,7 @@ module RubyLsp
|
|
13
13
|
# For writable elements like constants or variables, their read/write occurrences should be highlighted differently.
|
14
14
|
# This is achieved by sending different "kind" attributes to the editor (2 for read and 3 for write).
|
15
15
|
class DocumentHighlight < Request
|
16
|
-
|
17
|
-
|
18
|
-
sig do
|
19
|
-
params(
|
20
|
-
global_state: GlobalState,
|
21
|
-
document: T.any(RubyDocument, ERBDocument),
|
22
|
-
position: T::Hash[Symbol, T.untyped],
|
23
|
-
dispatcher: Prism::Dispatcher,
|
24
|
-
).void
|
25
|
-
end
|
16
|
+
#: (GlobalState global_state, (RubyDocument | ERBDocument) document, Hash[Symbol, untyped] position, Prism::Dispatcher dispatcher) -> void
|
26
17
|
def initialize(global_state, document, position, dispatcher)
|
27
18
|
super()
|
28
19
|
char_position, _ = document.find_index_by_position(position)
|
@@ -34,10 +25,8 @@ module RubyLsp
|
|
34
25
|
code_units_cache: document.code_units_cache,
|
35
26
|
)
|
36
27
|
|
37
|
-
@response_builder =
|
38
|
-
ResponseBuilders::CollectionResponseBuilder[Interface::DocumentHighlight]
|
39
|
-
ResponseBuilders::CollectionResponseBuilder[Interface::DocumentHighlight],
|
40
|
-
)
|
28
|
+
@response_builder = ResponseBuilders::CollectionResponseBuilder
|
29
|
+
.new #: ResponseBuilders::CollectionResponseBuilder[Interface::DocumentHighlight]
|
41
30
|
Listeners::DocumentHighlight.new(
|
42
31
|
@response_builder,
|
43
32
|
node_context.node,
|
@@ -47,7 +36,8 @@ module RubyLsp
|
|
47
36
|
)
|
48
37
|
end
|
49
38
|
|
50
|
-
|
39
|
+
# @override
|
40
|
+
#: -> Array[Interface::DocumentHighlight]
|
51
41
|
def perform
|
52
42
|
@response_builder.response
|
53
43
|
end
|
@@ -9,34 +9,23 @@ module RubyLsp
|
|
9
9
|
# makes `# source://PATH_TO_FILE#line` comments in a Ruby/RBI file clickable if the file exists.
|
10
10
|
# When the user clicks the link, it'll open that location.
|
11
11
|
class DocumentLink < Request
|
12
|
-
extend T::Sig
|
13
|
-
|
14
12
|
class << self
|
15
|
-
|
16
|
-
|
17
|
-
sig { returns(Interface::DocumentLinkOptions) }
|
13
|
+
#: -> Interface::DocumentLinkOptions
|
18
14
|
def provider
|
19
15
|
Interface::DocumentLinkOptions.new(resolve_provider: false)
|
20
16
|
end
|
21
17
|
end
|
22
18
|
|
23
|
-
|
24
|
-
params(
|
25
|
-
uri: URI::Generic,
|
26
|
-
comments: T::Array[Prism::Comment],
|
27
|
-
dispatcher: Prism::Dispatcher,
|
28
|
-
).void
|
29
|
-
end
|
19
|
+
#: (URI::Generic uri, Array[Prism::Comment] comments, Prism::Dispatcher dispatcher) -> void
|
30
20
|
def initialize(uri, comments, dispatcher)
|
31
21
|
super()
|
32
|
-
@response_builder =
|
33
|
-
ResponseBuilders::CollectionResponseBuilder[Interface::DocumentLink]
|
34
|
-
ResponseBuilders::CollectionResponseBuilder[Interface::DocumentLink],
|
35
|
-
)
|
22
|
+
@response_builder = ResponseBuilders::CollectionResponseBuilder
|
23
|
+
.new #: ResponseBuilders::CollectionResponseBuilder[Interface::DocumentLink]
|
36
24
|
Listeners::DocumentLink.new(@response_builder, uri, comments, dispatcher)
|
37
25
|
end
|
38
26
|
|
39
|
-
|
27
|
+
# @override
|
28
|
+
#: -> Array[Interface::DocumentLink]
|
40
29
|
def perform
|
41
30
|
@response_builder.response
|
42
31
|
end
|
@@ -13,21 +13,17 @@ module RubyLsp
|
|
13
13
|
# In VS Code, symbol search known as 'Go To Symbol in Editor' and can be accessed with Ctrl/Cmd-Shift-O,
|
14
14
|
# or by opening the command palette and inserting an `@` symbol.
|
15
15
|
class DocumentSymbol < Request
|
16
|
-
extend T::Sig
|
17
|
-
|
18
16
|
class << self
|
19
|
-
|
20
|
-
|
21
|
-
sig { returns(Interface::DocumentSymbolOptions) }
|
17
|
+
#: -> Interface::DocumentSymbolOptions
|
22
18
|
def provider
|
23
19
|
Interface::DocumentSymbolOptions.new
|
24
20
|
end
|
25
21
|
end
|
26
22
|
|
27
|
-
|
23
|
+
#: (URI::Generic uri, Prism::Dispatcher dispatcher) -> void
|
28
24
|
def initialize(uri, dispatcher)
|
29
25
|
super()
|
30
|
-
@response_builder =
|
26
|
+
@response_builder = ResponseBuilders::DocumentSymbol.new #: ResponseBuilders::DocumentSymbol
|
31
27
|
Listeners::DocumentSymbol.new(@response_builder, uri, dispatcher)
|
32
28
|
|
33
29
|
Addon.addons.each do |addon|
|
@@ -35,7 +31,8 @@ module RubyLsp
|
|
35
31
|
end
|
36
32
|
end
|
37
33
|
|
38
|
-
|
34
|
+
# @override
|
35
|
+
#: -> Array[Interface::DocumentSymbol]
|
39
36
|
def perform
|
40
37
|
@response_builder.response
|
41
38
|
end
|
@@ -8,31 +8,23 @@ module RubyLsp
|
|
8
8
|
# The [folding ranges](https://microsoft.github.io/language-server-protocol/specification#textDocument_foldingRange)
|
9
9
|
# request informs the editor of the ranges where and how code can be folded.
|
10
10
|
class FoldingRanges < Request
|
11
|
-
extend T::Sig
|
12
|
-
|
13
11
|
class << self
|
14
|
-
|
15
|
-
|
16
|
-
sig { returns(TrueClass) }
|
12
|
+
#: -> TrueClass
|
17
13
|
def provider
|
18
14
|
true
|
19
15
|
end
|
20
16
|
end
|
21
17
|
|
22
|
-
|
18
|
+
#: (Array[Prism::Comment] comments, Prism::Dispatcher dispatcher) -> void
|
23
19
|
def initialize(comments, dispatcher)
|
24
20
|
super()
|
25
|
-
@response_builder =
|
26
|
-
ResponseBuilders::CollectionResponseBuilder[Interface::FoldingRange]
|
27
|
-
|
28
|
-
)
|
29
|
-
@listener = T.let(
|
30
|
-
Listeners::FoldingRanges.new(@response_builder, comments, dispatcher),
|
31
|
-
Listeners::FoldingRanges,
|
32
|
-
)
|
21
|
+
@response_builder = ResponseBuilders::CollectionResponseBuilder
|
22
|
+
.new #: ResponseBuilders::CollectionResponseBuilder[Interface::FoldingRange]
|
23
|
+
@listener = Listeners::FoldingRanges.new(@response_builder, comments, dispatcher) #: Listeners::FoldingRanges
|
33
24
|
end
|
34
25
|
|
35
|
-
|
26
|
+
# @override
|
27
|
+
#: -> Array[Interface::FoldingRange]
|
36
28
|
def perform
|
37
29
|
@listener.finalize_response!
|
38
30
|
@response_builder.response
|
@@ -7,28 +7,25 @@ module RubyLsp
|
|
7
7
|
# request uses RuboCop to fix auto-correctable offenses in the document. This requires enabling format on save and
|
8
8
|
# registering the ruby-lsp as the Ruby formatter.
|
9
9
|
class Formatting < Request
|
10
|
-
extend T::Sig
|
11
|
-
|
12
10
|
class Error < StandardError; end
|
13
11
|
|
14
12
|
class << self
|
15
|
-
|
16
|
-
|
17
|
-
sig { returns(TrueClass) }
|
13
|
+
#: -> TrueClass
|
18
14
|
def provider
|
19
15
|
true
|
20
16
|
end
|
21
17
|
end
|
22
18
|
|
23
|
-
|
19
|
+
#: (GlobalState global_state, RubyDocument document) -> void
|
24
20
|
def initialize(global_state, document)
|
25
21
|
super()
|
26
22
|
@document = document
|
27
|
-
@active_formatter =
|
28
|
-
@uri =
|
23
|
+
@active_formatter = global_state.active_formatter #: Support::Formatter?
|
24
|
+
@uri = document.uri #: URI::Generic
|
29
25
|
end
|
30
26
|
|
31
|
-
|
27
|
+
# @override
|
28
|
+
#: -> (Array[Interface::TextEdit] & Object)?
|
32
29
|
def perform
|
33
30
|
return unless @active_formatter
|
34
31
|
return if @document.syntax_error?
|
@@ -0,0 +1,85 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module RubyLsp
|
5
|
+
module Requests
|
6
|
+
# GoTo Relevant File is a custom [LSP
|
7
|
+
# request](https://microsoft.github.io/language-server-protocol/specification#requestMessage)
|
8
|
+
# that navigates to the relevant file for the current document.
|
9
|
+
# Currently, it supports source code file <> test file navigation.
|
10
|
+
class GoToRelevantFile < Request
|
11
|
+
TEST_KEYWORDS = ["test", "spec", "integration_test"]
|
12
|
+
|
13
|
+
TEST_PREFIX_PATTERN = /^(#{TEST_KEYWORDS.join("_|")}_)/
|
14
|
+
TEST_SUFFIX_PATTERN = /(_#{TEST_KEYWORDS.join("|_")})$/
|
15
|
+
TEST_PATTERN = /#{TEST_PREFIX_PATTERN}|#{TEST_SUFFIX_PATTERN}/
|
16
|
+
|
17
|
+
TEST_PREFIX_GLOB = "#{TEST_KEYWORDS.join("_,")}_" #: String
|
18
|
+
TEST_SUFFIX_GLOB = "_#{TEST_KEYWORDS.join(",_")}" #: String
|
19
|
+
|
20
|
+
#: (String path, String workspace_path) -> void
|
21
|
+
def initialize(path, workspace_path)
|
22
|
+
super()
|
23
|
+
|
24
|
+
@workspace_path = workspace_path
|
25
|
+
@path = path.delete_prefix(workspace_path) #: String
|
26
|
+
end
|
27
|
+
|
28
|
+
# @override
|
29
|
+
#: -> Array[String]
|
30
|
+
def perform
|
31
|
+
find_relevant_paths
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
#: -> Array[String]
|
37
|
+
def find_relevant_paths
|
38
|
+
candidate_paths = Dir.glob(File.join("**", relevant_filename_pattern))
|
39
|
+
return [] if candidate_paths.empty?
|
40
|
+
|
41
|
+
find_most_similar_with_jaccard(candidate_paths).map { File.join(@workspace_path, _1) }
|
42
|
+
end
|
43
|
+
|
44
|
+
#: -> String
|
45
|
+
def relevant_filename_pattern
|
46
|
+
input_basename = File.basename(@path, File.extname(@path))
|
47
|
+
|
48
|
+
relevant_basename_pattern =
|
49
|
+
if input_basename.match?(TEST_PATTERN)
|
50
|
+
input_basename.gsub(TEST_PATTERN, "")
|
51
|
+
else
|
52
|
+
"{{#{TEST_PREFIX_GLOB}}#{input_basename},#{input_basename}{#{TEST_SUFFIX_GLOB}}}"
|
53
|
+
end
|
54
|
+
|
55
|
+
"#{relevant_basename_pattern}#{File.extname(@path)}"
|
56
|
+
end
|
57
|
+
|
58
|
+
# Using the Jaccard algorithm to determine the similarity between the
|
59
|
+
# input path and the candidate relevant file paths.
|
60
|
+
# Ref: https://en.wikipedia.org/wiki/Jaccard_index
|
61
|
+
# The main idea of this algorithm is to take the size of interaction and divide
|
62
|
+
# it by the size of union between two sets (in our case the elements in each set
|
63
|
+
# would be the parts of the path separated by path divider.)
|
64
|
+
#: (Array[String] candidates) -> Array[String]
|
65
|
+
def find_most_similar_with_jaccard(candidates)
|
66
|
+
dirs = get_dir_parts(@path)
|
67
|
+
|
68
|
+
_, results = candidates
|
69
|
+
.group_by do |other_path|
|
70
|
+
other_dirs = get_dir_parts(other_path)
|
71
|
+
# Similarity score between the two directories
|
72
|
+
(dirs & other_dirs).size.to_f / (dirs | other_dirs).size
|
73
|
+
end
|
74
|
+
.max_by(&:first)
|
75
|
+
|
76
|
+
results || []
|
77
|
+
end
|
78
|
+
|
79
|
+
#: (String path) -> Set[String]
|
80
|
+
def get_dir_parts(path)
|
81
|
+
Set.new(File.dirname(path).split(File::SEPARATOR))
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -8,13 +8,10 @@ module RubyLsp
|
|
8
8
|
# The [hover request](https://microsoft.github.io/language-server-protocol/specification#textDocument_hover)
|
9
9
|
# displays the documentation for the symbol currently under the cursor.
|
10
10
|
class Hover < Request
|
11
|
-
extend T::Sig
|
12
11
|
extend T::Generic
|
13
12
|
|
14
13
|
class << self
|
15
|
-
|
16
|
-
|
17
|
-
sig { returns(Interface::HoverOptions) }
|
14
|
+
#: -> Interface::HoverOptions
|
18
15
|
def provider
|
19
16
|
Interface::HoverOptions.new
|
20
17
|
end
|
@@ -22,15 +19,7 @@ module RubyLsp
|
|
22
19
|
|
23
20
|
ResponseType = type_member { { fixed: T.nilable(Interface::Hover) } }
|
24
21
|
|
25
|
-
|
26
|
-
params(
|
27
|
-
document: T.any(RubyDocument, ERBDocument),
|
28
|
-
global_state: GlobalState,
|
29
|
-
position: T::Hash[Symbol, T.untyped],
|
30
|
-
dispatcher: Prism::Dispatcher,
|
31
|
-
sorbet_level: RubyDocument::SorbetLevel,
|
32
|
-
).void
|
33
|
-
end
|
22
|
+
#: ((RubyDocument | ERBDocument) document, GlobalState global_state, Hash[Symbol, untyped] position, Prism::Dispatcher dispatcher, SorbetLevel sorbet_level) -> void
|
34
23
|
def initialize(document, global_state, position, dispatcher, sorbet_level)
|
35
24
|
super()
|
36
25
|
|
@@ -48,8 +37,8 @@ module RubyLsp
|
|
48
37
|
|
49
38
|
if should_refine_target?(parent, target)
|
50
39
|
target = determine_target(
|
51
|
-
|
52
|
-
|
40
|
+
target, #: as !nil
|
41
|
+
parent, #: as !nil
|
53
42
|
position,
|
54
43
|
)
|
55
44
|
elsif position_outside_target?(position, target)
|
@@ -59,9 +48,9 @@ module RubyLsp
|
|
59
48
|
# Don't need to instantiate any listeners if there's no target
|
60
49
|
return unless target
|
61
50
|
|
62
|
-
@target =
|
51
|
+
@target = target #: Prism::Node?
|
63
52
|
uri = document.uri
|
64
|
-
@response_builder =
|
53
|
+
@response_builder = ResponseBuilders::Hover.new #: ResponseBuilders::Hover
|
65
54
|
Listeners::Hover.new(@response_builder, global_state, uri, node_context, dispatcher, sorbet_level)
|
66
55
|
Addon.addons.each do |addon|
|
67
56
|
addon.create_hover_listener(@response_builder, node_context, dispatcher)
|
@@ -70,7 +59,8 @@ module RubyLsp
|
|
70
59
|
@dispatcher = dispatcher
|
71
60
|
end
|
72
61
|
|
73
|
-
|
62
|
+
# @override
|
63
|
+
#: -> ResponseType
|
74
64
|
def perform
|
75
65
|
return unless @target
|
76
66
|
|
@@ -88,14 +78,14 @@ module RubyLsp
|
|
88
78
|
|
89
79
|
private
|
90
80
|
|
91
|
-
|
81
|
+
#: (Prism::Node? parent, Prism::Node? target) -> bool
|
92
82
|
def should_refine_target?(parent, target)
|
93
83
|
(Listeners::Hover::ALLOWED_TARGETS.include?(parent.class) &&
|
94
84
|
!Listeners::Hover::ALLOWED_TARGETS.include?(target.class)) ||
|
95
85
|
(parent.is_a?(Prism::ConstantPathNode) && target.is_a?(Prism::ConstantReadNode))
|
96
86
|
end
|
97
87
|
|
98
|
-
|
88
|
+
#: (Hash[Symbol, untyped] position, Prism::Node? target) -> bool
|
99
89
|
def position_outside_target?(position, target)
|
100
90
|
case target
|
101
91
|
when Prism::GlobalVariableAndWriteNode,
|
@@ -9,35 +9,24 @@ module RubyLsp
|
|
9
9
|
# are labels added directly in the code that explicitly show the user something that might
|
10
10
|
# otherwise just be implied.
|
11
11
|
class InlayHints < Request
|
12
|
-
extend T::Sig
|
13
|
-
|
14
12
|
class << self
|
15
|
-
|
16
|
-
|
17
|
-
sig { returns(Interface::InlayHintOptions) }
|
13
|
+
#: -> Interface::InlayHintOptions
|
18
14
|
def provider
|
19
15
|
Interface::InlayHintOptions.new(resolve_provider: false)
|
20
16
|
end
|
21
17
|
end
|
22
18
|
|
23
|
-
|
24
|
-
params(
|
25
|
-
document: T.any(RubyDocument, ERBDocument),
|
26
|
-
hints_configuration: RequestConfig,
|
27
|
-
dispatcher: Prism::Dispatcher,
|
28
|
-
).void
|
29
|
-
end
|
19
|
+
#: ((RubyDocument | ERBDocument) document, RequestConfig hints_configuration, Prism::Dispatcher dispatcher) -> void
|
30
20
|
def initialize(document, hints_configuration, dispatcher)
|
31
21
|
super()
|
32
22
|
|
33
|
-
@response_builder =
|
34
|
-
ResponseBuilders::CollectionResponseBuilder[Interface::InlayHint]
|
35
|
-
ResponseBuilders::CollectionResponseBuilder[Interface::InlayHint],
|
36
|
-
)
|
23
|
+
@response_builder = ResponseBuilders::CollectionResponseBuilder
|
24
|
+
.new #: ResponseBuilders::CollectionResponseBuilder[Interface::InlayHint]
|
37
25
|
Listeners::InlayHints.new(@response_builder, hints_configuration, dispatcher)
|
38
26
|
end
|
39
27
|
|
40
|
-
|
28
|
+
# @override
|
29
|
+
#: -> Array[Interface::InlayHint]
|
41
30
|
def perform
|
42
31
|
@response_builder.response
|
43
32
|
end
|
@@ -6,12 +6,8 @@ module RubyLsp
|
|
6
6
|
# The [on type formatting](https://microsoft.github.io/language-server-protocol/specification#textDocument_onTypeFormatting)
|
7
7
|
# request formats code as the user is typing. For example, automatically adding `end` to class definitions.
|
8
8
|
class OnTypeFormatting < Request
|
9
|
-
extend T::Sig
|
10
|
-
|
11
9
|
class << self
|
12
|
-
|
13
|
-
|
14
|
-
sig { returns(Interface::DocumentOnTypeFormattingRegistrationOptions) }
|
10
|
+
#: -> Interface::DocumentOnTypeFormattingRegistrationOptions
|
15
11
|
def provider
|
16
12
|
Interface::DocumentOnTypeFormattingRegistrationOptions.new(
|
17
13
|
document_selector: nil,
|
@@ -21,38 +17,29 @@ module RubyLsp
|
|
21
17
|
end
|
22
18
|
end
|
23
19
|
|
24
|
-
END_REGEXES =
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
)
|
32
|
-
|
33
|
-
sig do
|
34
|
-
params(
|
35
|
-
document: RubyDocument,
|
36
|
-
position: T::Hash[Symbol, T.untyped],
|
37
|
-
trigger_character: String,
|
38
|
-
client_name: String,
|
39
|
-
).void
|
40
|
-
end
|
20
|
+
END_REGEXES = [
|
21
|
+
/\b(if|unless|for|while|until)\b($|\s|\()/,
|
22
|
+
/\b(class|module|def|case)\b($|\s)/,
|
23
|
+
/.*\s\bdo\b($|\s)/,
|
24
|
+
] #: Array[Regexp]
|
25
|
+
|
26
|
+
#: (RubyDocument document, Hash[Symbol, untyped] position, String trigger_character, String client_name) -> void
|
41
27
|
def initialize(document, position, trigger_character, client_name)
|
42
28
|
super()
|
43
29
|
@document = document
|
44
|
-
@lines =
|
30
|
+
@lines = @document.source.lines #: Array[String]
|
45
31
|
line = @lines[[position[:line] - 1, 0].max]
|
46
32
|
|
47
|
-
@indentation =
|
48
|
-
@previous_line =
|
33
|
+
@indentation = line ? find_indentation(line) : 0 #: Integer
|
34
|
+
@previous_line = line ? line.strip.chomp : "" #: String
|
49
35
|
@position = position
|
50
|
-
@edits =
|
36
|
+
@edits = [] #: Array[Interface::TextEdit]
|
51
37
|
@trigger_character = trigger_character
|
52
38
|
@client_name = client_name
|
53
39
|
end
|
54
40
|
|
55
|
-
|
41
|
+
# @override
|
42
|
+
#: -> (Array[Interface::TextEdit] & Object)
|
56
43
|
def perform
|
57
44
|
case @trigger_character
|
58
45
|
when "{"
|
@@ -60,8 +47,13 @@ module RubyLsp
|
|
60
47
|
when "|"
|
61
48
|
handle_pipe if @document.syntax_error?
|
62
49
|
when "\n"
|
63
|
-
|
64
|
-
|
50
|
+
# If the previous line is a simple comment, we'll add a comment continuation
|
51
|
+
# But if it's a RBS signature starting with `#:`, we'll ignore it
|
52
|
+
# so users can immediately continue typing the method definition
|
53
|
+
if (comment_match = @previous_line.match(/^#(?!:)(\s*)/))
|
54
|
+
handle_comment_line(
|
55
|
+
comment_match[1], #: as !nil
|
56
|
+
)
|
65
57
|
elsif @document.syntax_error?
|
66
58
|
match = /(<<((-|~)?))(?<quote>['"`]?)(?<delimiter>\w+)\k<quote>/.match(@previous_line)
|
67
59
|
heredoc_delimiter = match && match.named_captures["delimiter"]
|
@@ -81,12 +73,12 @@ module RubyLsp
|
|
81
73
|
|
82
74
|
private
|
83
75
|
|
84
|
-
|
76
|
+
#: -> void
|
85
77
|
def handle_pipe
|
86
78
|
current_line = @lines[@position[:line]]
|
87
79
|
return unless /((?<=do)|(?<={))\s+\|/.match?(current_line)
|
88
80
|
|
89
|
-
line =
|
81
|
+
line = current_line #: as !nil
|
90
82
|
|
91
83
|
# If the user inserts the closing pipe manually to the end of the block argument, we need to avoid adding
|
92
84
|
# an additional one and remove the previous one. This also helps to remove the user who accidentally
|
@@ -112,7 +104,7 @@ module RubyLsp
|
|
112
104
|
move_cursor_to(@position[:line], @position[:character])
|
113
105
|
end
|
114
106
|
|
115
|
-
|
107
|
+
#: -> void
|
116
108
|
def handle_curly_brace
|
117
109
|
return unless /".*#\{/.match?(@previous_line)
|
118
110
|
|
@@ -120,7 +112,7 @@ module RubyLsp
|
|
120
112
|
move_cursor_to(@position[:line], @position[:character])
|
121
113
|
end
|
122
114
|
|
123
|
-
|
115
|
+
#: -> void
|
124
116
|
def handle_statement_end
|
125
117
|
# If a keyword occurs in a line which appears be a comment or a string, we will not try to format it, since
|
126
118
|
# it could be a coincidental match. This approach is not perfect, but it should cover most cases.
|
@@ -142,7 +134,7 @@ module RubyLsp
|
|
142
134
|
end
|
143
135
|
end
|
144
136
|
|
145
|
-
|
137
|
+
#: (String delimiter) -> void
|
146
138
|
def handle_heredoc_end(delimiter)
|
147
139
|
indents = " " * @indentation
|
148
140
|
add_edit_with_text("\n")
|
@@ -150,12 +142,12 @@ module RubyLsp
|
|
150
142
|
move_cursor_to(@position[:line], @indentation + 2)
|
151
143
|
end
|
152
144
|
|
153
|
-
|
145
|
+
#: (String spaces) -> void
|
154
146
|
def handle_comment_line(spaces)
|
155
147
|
add_edit_with_text("##{spaces}")
|
156
148
|
end
|
157
149
|
|
158
|
-
|
150
|
+
#: (String text, ?Hash[Symbol, untyped] position) -> void
|
159
151
|
def add_edit_with_text(text, position = @position)
|
160
152
|
pos = Interface::Position.new(
|
161
153
|
line: position[:line],
|
@@ -168,9 +160,9 @@ module RubyLsp
|
|
168
160
|
)
|
169
161
|
end
|
170
162
|
|
171
|
-
|
163
|
+
#: (Integer line, Integer character) -> void
|
172
164
|
def move_cursor_to(line, character)
|
173
|
-
return unless /Visual Studio Code|Cursor/.match?(@client_name)
|
165
|
+
return unless /Visual Studio Code|Cursor|VSCodium/.match?(@client_name)
|
174
166
|
|
175
167
|
position = Interface::Position.new(
|
176
168
|
line: line,
|
@@ -189,7 +181,7 @@ module RubyLsp
|
|
189
181
|
)
|
190
182
|
end
|
191
183
|
|
192
|
-
|
184
|
+
#: (String line) -> Integer
|
193
185
|
def find_indentation(line)
|
194
186
|
count = 0
|
195
187
|
|
@@ -202,7 +194,7 @@ module RubyLsp
|
|
202
194
|
count
|
203
195
|
end
|
204
196
|
|
205
|
-
|
197
|
+
#: -> void
|
206
198
|
def auto_indent_after_end_keyword
|
207
199
|
current_line = @lines[@position[:line]]
|
208
200
|
return unless current_line && current_line.strip == "end"
|
@@ -7,22 +7,17 @@ module RubyLsp
|
|
7
7
|
# [prepare_rename](https://microsoft.github.io/language-server-protocol/specification#textDocument_prepareRename)
|
8
8
|
# # request checks the validity of a rename operation at a given location.
|
9
9
|
class PrepareRename < Request
|
10
|
-
extend T::Sig
|
11
10
|
include Support::Common
|
12
11
|
|
13
|
-
|
14
|
-
params(
|
15
|
-
document: RubyDocument,
|
16
|
-
position: T::Hash[Symbol, T.untyped],
|
17
|
-
).void
|
18
|
-
end
|
12
|
+
#: (RubyDocument document, Hash[Symbol, untyped] position) -> void
|
19
13
|
def initialize(document, position)
|
20
14
|
super()
|
21
15
|
@document = document
|
22
|
-
@position =
|
16
|
+
@position = position #: Hash[Symbol, Integer]
|
23
17
|
end
|
24
18
|
|
25
|
-
|
19
|
+
# @override
|
20
|
+
#: -> Interface::Range?
|
26
21
|
def perform
|
27
22
|
char_position, _ = @document.find_index_by_position(@position)
|
28
23
|
|
@@ -9,26 +9,16 @@ module RubyLsp
|
|
9
9
|
#
|
10
10
|
# Currently only supports supertypes due to a limitation of the index.
|
11
11
|
class PrepareTypeHierarchy < Request
|
12
|
-
extend T::Sig
|
13
|
-
|
14
12
|
include Support::Common
|
15
13
|
|
16
14
|
class << self
|
17
|
-
|
18
|
-
|
19
|
-
sig { returns(Interface::TypeHierarchyOptions) }
|
15
|
+
#: -> Interface::TypeHierarchyOptions
|
20
16
|
def provider
|
21
17
|
Interface::TypeHierarchyOptions.new
|
22
18
|
end
|
23
19
|
end
|
24
20
|
|
25
|
-
|
26
|
-
params(
|
27
|
-
document: T.any(RubyDocument, ERBDocument),
|
28
|
-
index: RubyIndexer::Index,
|
29
|
-
position: T::Hash[Symbol, T.untyped],
|
30
|
-
).void
|
31
|
-
end
|
21
|
+
#: ((RubyDocument | ERBDocument) document, RubyIndexer::Index index, Hash[Symbol, untyped] position) -> void
|
32
22
|
def initialize(document, index, position)
|
33
23
|
super()
|
34
24
|
|
@@ -37,7 +27,8 @@ module RubyLsp
|
|
37
27
|
@position = position
|
38
28
|
end
|
39
29
|
|
40
|
-
|
30
|
+
# @override
|
31
|
+
#: -> Array[Interface::TypeHierarchyItem]?
|
41
32
|
def perform
|
42
33
|
context = @document.locate_node(
|
43
34
|
@position,
|
@@ -58,8 +49,7 @@ module RubyLsp
|
|
58
49
|
|
59
50
|
# While the spec allows for multiple entries, VSCode seems to only support one
|
60
51
|
# We'll just return the first one for now
|
61
|
-
first_entry =
|
62
|
-
|
52
|
+
first_entry = entries.first #: as !nil
|
63
53
|
range = range_from_location(first_entry.location)
|
64
54
|
|
65
55
|
[
|
@@ -6,18 +6,17 @@ module RubyLsp
|
|
6
6
|
# The [range formatting](https://microsoft.github.io/language-server-protocol/specification#textDocument_rangeFormatting)
|
7
7
|
# is used to format a selection or to format on paste.
|
8
8
|
class RangeFormatting < Request
|
9
|
-
|
10
|
-
|
11
|
-
sig { params(global_state: GlobalState, document: RubyDocument, params: T::Hash[Symbol, T.untyped]).void }
|
9
|
+
#: (GlobalState global_state, RubyDocument document, Hash[Symbol, untyped] params) -> void
|
12
10
|
def initialize(global_state, document, params)
|
13
11
|
super()
|
14
12
|
@document = document
|
15
|
-
@uri =
|
13
|
+
@uri = document.uri #: URI::Generic
|
16
14
|
@params = params
|
17
|
-
@active_formatter =
|
15
|
+
@active_formatter = global_state.active_formatter #: Support::Formatter?
|
18
16
|
end
|
19
17
|
|
20
|
-
|
18
|
+
# @override
|
19
|
+
#: -> Array[Interface::TextEdit]?
|
21
20
|
def perform
|
22
21
|
return unless @active_formatter
|
23
22
|
return if @document.syntax_error?
|