ruby-lsp 0.13.3 → 0.14.2
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 +6 -2
- data/VERSION +1 -1
- data/exe/ruby-lsp-doctor +2 -0
- data/lib/rubocop/cop/ruby_lsp/use_register_with_handler_method.rb +4 -8
- data/lib/ruby_indexer/lib/ruby_indexer/collector.rb +5 -1
- data/lib/ruby_indexer/lib/ruby_indexer/configuration.rb +4 -2
- data/lib/ruby_indexer/lib/ruby_indexer/index.rb +10 -5
- data/lib/ruby_indexer/test/classes_and_modules_test.rb +9 -0
- data/lib/ruby_indexer/test/index_test.rb +54 -3
- data/lib/ruby_lsp/addon.rb +34 -17
- data/lib/ruby_lsp/check_docs.rb +8 -8
- data/lib/ruby_lsp/executor.rb +28 -10
- data/lib/ruby_lsp/internal.rb +8 -6
- data/lib/ruby_lsp/listeners/code_lens.rb +54 -55
- data/lib/ruby_lsp/listeners/completion.rb +22 -18
- data/lib/ruby_lsp/listeners/definition.rb +31 -29
- data/lib/ruby_lsp/listeners/document_highlight.rb +6 -11
- data/lib/ruby_lsp/listeners/document_link.rb +6 -12
- data/lib/ruby_lsp/listeners/document_symbol.rb +194 -55
- data/lib/ruby_lsp/listeners/folding_ranges.rb +19 -23
- data/lib/ruby_lsp/listeners/hover.rb +36 -34
- data/lib/ruby_lsp/listeners/inlay_hints.rb +7 -13
- data/lib/ruby_lsp/listeners/semantic_highlighting.rb +54 -124
- data/lib/ruby_lsp/listeners/signature_help.rb +15 -14
- data/lib/ruby_lsp/requests/code_lens.rb +11 -19
- data/lib/ruby_lsp/requests/completion.rb +7 -9
- data/lib/ruby_lsp/requests/definition.rb +10 -22
- data/lib/ruby_lsp/requests/document_highlight.rb +7 -5
- data/lib/ruby_lsp/requests/document_link.rb +7 -6
- data/lib/ruby_lsp/requests/document_symbol.rb +5 -11
- data/lib/ruby_lsp/requests/folding_ranges.rb +11 -6
- data/lib/ruby_lsp/requests/hover.rb +18 -24
- data/lib/ruby_lsp/requests/inlay_hints.rb +7 -8
- data/lib/ruby_lsp/requests/on_type_formatting.rb +12 -2
- data/lib/ruby_lsp/requests/semantic_highlighting.rb +10 -8
- data/lib/ruby_lsp/requests/signature_help.rb +53 -18
- data/lib/ruby_lsp/requests/support/common.rb +38 -10
- data/lib/ruby_lsp/requests/support/dependency_detector.rb +5 -1
- data/lib/ruby_lsp/requests.rb +0 -1
- data/lib/ruby_lsp/response_builders/collection_response_builder.rb +29 -0
- data/lib/ruby_lsp/response_builders/document_symbol.rb +57 -0
- data/lib/ruby_lsp/response_builders/hover.rb +49 -0
- data/lib/ruby_lsp/response_builders/response_builder.rb +16 -0
- data/lib/ruby_lsp/response_builders/semantic_highlighting.rb +199 -0
- data/lib/ruby_lsp/response_builders/signature_help.rb +28 -0
- data/lib/ruby_lsp/response_builders.rb +13 -0
- data/lib/ruby_lsp/server.rb +3 -3
- data/lib/ruby_lsp/setup_bundler.rb +64 -23
- data/lib/ruby_lsp/store.rb +4 -4
- metadata +17 -11
- data/lib/ruby_lsp/listener.rb +0 -33
- data/lib/ruby_lsp/requests/support/semantic_token_encoder.rb +0 -73
@@ -30,7 +30,6 @@ module RubyLsp
|
|
30
30
|
# ```
|
31
31
|
class DocumentSymbol < Request
|
32
32
|
extend T::Sig
|
33
|
-
extend T::Generic
|
34
33
|
|
35
34
|
class << self
|
36
35
|
extend T::Sig
|
@@ -46,25 +45,20 @@ module RubyLsp
|
|
46
45
|
end
|
47
46
|
end
|
48
47
|
|
49
|
-
ResponseType = type_member { { fixed: T::Array[Interface::DocumentSymbol] } }
|
50
|
-
|
51
48
|
sig { params(dispatcher: Prism::Dispatcher).void }
|
52
49
|
def initialize(dispatcher)
|
53
50
|
super()
|
54
|
-
@
|
55
|
-
|
56
|
-
T::Array[Listener[ResponseType]],
|
57
|
-
)
|
51
|
+
@response_builder = T.let(ResponseBuilders::DocumentSymbol.new, ResponseBuilders::DocumentSymbol)
|
52
|
+
Listeners::DocumentSymbol.new(@response_builder, dispatcher)
|
58
53
|
|
59
54
|
Addon.addons.each do |addon|
|
60
|
-
|
61
|
-
@listeners << addon_listener if addon_listener
|
55
|
+
addon.create_document_symbol_listener(@response_builder, dispatcher)
|
62
56
|
end
|
63
57
|
end
|
64
58
|
|
65
|
-
sig { override.returns(
|
59
|
+
sig { override.returns(T::Array[Interface::DocumentSymbol]) }
|
66
60
|
def perform
|
67
|
-
@
|
61
|
+
@response_builder.response
|
68
62
|
end
|
69
63
|
end
|
70
64
|
end
|
@@ -19,7 +19,6 @@ module RubyLsp
|
|
19
19
|
# ```
|
20
20
|
class FoldingRanges < Request
|
21
21
|
extend T::Sig
|
22
|
-
extend T::Generic
|
23
22
|
|
24
23
|
class << self
|
25
24
|
extend T::Sig
|
@@ -30,17 +29,23 @@ module RubyLsp
|
|
30
29
|
end
|
31
30
|
end
|
32
31
|
|
33
|
-
ResponseType = type_member { { fixed: T::Array[Interface::FoldingRange] } }
|
34
|
-
|
35
32
|
sig { params(comments: T::Array[Prism::Comment], dispatcher: Prism::Dispatcher).void }
|
36
33
|
def initialize(comments, dispatcher)
|
37
34
|
super()
|
38
|
-
@
|
35
|
+
@response_builder = T.let(
|
36
|
+
ResponseBuilders::CollectionResponseBuilder[Interface::FoldingRange].new,
|
37
|
+
ResponseBuilders::CollectionResponseBuilder[Interface::FoldingRange],
|
38
|
+
)
|
39
|
+
@listener = T.let(
|
40
|
+
Listeners::FoldingRanges.new(@response_builder, comments, dispatcher),
|
41
|
+
Listeners::FoldingRanges,
|
42
|
+
)
|
39
43
|
end
|
40
44
|
|
41
|
-
sig { override.returns(
|
45
|
+
sig { override.returns(T::Array[Interface::FoldingRange]) }
|
42
46
|
def perform
|
43
|
-
@listener.
|
47
|
+
@listener.finalize_response!
|
48
|
+
@response_builder.response
|
44
49
|
end
|
45
50
|
end
|
46
51
|
end
|
@@ -41,51 +41,45 @@ module RubyLsp
|
|
41
41
|
end
|
42
42
|
def initialize(document, index, position, dispatcher, typechecker_enabled)
|
43
43
|
super()
|
44
|
-
target
|
44
|
+
@target = T.let(nil, T.nilable(Prism::Node))
|
45
|
+
@target, parent, nesting = document.locate_node(
|
45
46
|
position,
|
46
47
|
node_types: Listeners::Hover::ALLOWED_TARGETS,
|
47
48
|
)
|
48
49
|
|
49
50
|
if (Listeners::Hover::ALLOWED_TARGETS.include?(parent.class) &&
|
50
|
-
!Listeners::Hover::ALLOWED_TARGETS.include?(target.class)) ||
|
51
|
-
(parent.is_a?(Prism::ConstantPathNode) && target.is_a?(Prism::ConstantReadNode))
|
52
|
-
target = parent
|
51
|
+
!Listeners::Hover::ALLOWED_TARGETS.include?(@target.class)) ||
|
52
|
+
(parent.is_a?(Prism::ConstantPathNode) && @target.is_a?(Prism::ConstantReadNode))
|
53
|
+
@target = parent
|
53
54
|
end
|
54
55
|
|
55
|
-
@listeners = T.let([], T::Array[Listener[ResponseType]])
|
56
|
-
|
57
56
|
# Don't need to instantiate any listeners if there's no target
|
58
|
-
return unless target
|
57
|
+
return unless @target
|
59
58
|
|
60
59
|
uri = document.uri
|
61
|
-
@
|
62
|
-
|
63
|
-
T::Array[Listener[ResponseType]],
|
64
|
-
)
|
60
|
+
@response_builder = T.let(ResponseBuilders::Hover.new, ResponseBuilders::Hover)
|
61
|
+
Listeners::Hover.new(@response_builder, uri, nesting, index, dispatcher, typechecker_enabled)
|
65
62
|
Addon.addons.each do |addon|
|
66
|
-
|
67
|
-
@listeners << addon_listener if addon_listener
|
63
|
+
addon.create_hover_listener(@response_builder, nesting, index, dispatcher)
|
68
64
|
end
|
69
65
|
|
70
|
-
@target = T.let(target, Prism::Node)
|
71
66
|
@dispatcher = dispatcher
|
72
67
|
end
|
73
68
|
|
74
69
|
sig { override.returns(ResponseType) }
|
75
70
|
def perform
|
76
|
-
@
|
77
|
-
responses = @listeners.map(&:response).compact
|
78
|
-
|
79
|
-
first_response, *other_responses = responses
|
71
|
+
return unless @target
|
80
72
|
|
81
|
-
|
73
|
+
@dispatcher.dispatch_once(@target)
|
82
74
|
|
83
|
-
|
84
|
-
T.must(other_responses).each do |other_response|
|
85
|
-
first_response.contents.value << "\n\n" << other_response.contents.value
|
86
|
-
end
|
75
|
+
return if @response_builder.empty?
|
87
76
|
|
88
|
-
|
77
|
+
Interface::Hover.new(
|
78
|
+
contents: Interface::MarkupContent.new(
|
79
|
+
kind: "markdown",
|
80
|
+
value: @response_builder.response,
|
81
|
+
),
|
82
|
+
)
|
89
83
|
end
|
90
84
|
end
|
91
85
|
end
|
@@ -40,7 +40,6 @@ module RubyLsp
|
|
40
40
|
# ```
|
41
41
|
class InlayHints < Request
|
42
42
|
extend T::Sig
|
43
|
-
extend T::Generic
|
44
43
|
|
45
44
|
class << self
|
46
45
|
extend T::Sig
|
@@ -51,8 +50,6 @@ module RubyLsp
|
|
51
50
|
end
|
52
51
|
end
|
53
52
|
|
54
|
-
ResponseType = type_member { { fixed: T::Array[Interface::InlayHint] } }
|
55
|
-
|
56
53
|
sig do
|
57
54
|
params(
|
58
55
|
document: Document,
|
@@ -65,15 +62,17 @@ module RubyLsp
|
|
65
62
|
super()
|
66
63
|
start_line = range.dig(:start, :line)
|
67
64
|
end_line = range.dig(:end, :line)
|
68
|
-
|
69
|
-
|
70
|
-
|
65
|
+
|
66
|
+
@response_builder = T.let(
|
67
|
+
ResponseBuilders::CollectionResponseBuilder[Interface::InlayHint].new,
|
68
|
+
ResponseBuilders::CollectionResponseBuilder[Interface::InlayHint],
|
71
69
|
)
|
70
|
+
Listeners::InlayHints.new(@response_builder, start_line..end_line, hints_configuration, dispatcher)
|
72
71
|
end
|
73
72
|
|
74
|
-
sig { override.returns(
|
73
|
+
sig { override.returns(T::Array[Interface::InlayHint]) }
|
75
74
|
def perform
|
76
|
-
@
|
75
|
+
@response_builder.response
|
77
76
|
end
|
78
77
|
end
|
79
78
|
end
|
@@ -38,8 +38,15 @@ module RubyLsp
|
|
38
38
|
T::Array[Regexp],
|
39
39
|
)
|
40
40
|
|
41
|
-
sig
|
42
|
-
|
41
|
+
sig do
|
42
|
+
params(
|
43
|
+
document: Document,
|
44
|
+
position: T::Hash[Symbol, T.untyped],
|
45
|
+
trigger_character: String,
|
46
|
+
client_name: String,
|
47
|
+
).void
|
48
|
+
end
|
49
|
+
def initialize(document, position, trigger_character, client_name)
|
43
50
|
super()
|
44
51
|
@document = document
|
45
52
|
@lines = T.let(@document.source.lines, T::Array[String])
|
@@ -50,6 +57,7 @@ module RubyLsp
|
|
50
57
|
@position = position
|
51
58
|
@edits = T.let([], T::Array[Interface::TextEdit])
|
52
59
|
@trigger_character = trigger_character
|
60
|
+
@client_name = client_name
|
53
61
|
end
|
54
62
|
|
55
63
|
sig { override.returns(T.all(T::Array[Interface::TextEdit], Object)) }
|
@@ -170,6 +178,8 @@ module RubyLsp
|
|
170
178
|
|
171
179
|
sig { params(line: Integer, character: Integer).void }
|
172
180
|
def move_cursor_to(line, character)
|
181
|
+
return if @client_name != "Visual Studio Code"
|
182
|
+
|
173
183
|
position = Interface::Position.new(
|
174
184
|
line: line,
|
175
185
|
character: character,
|
@@ -22,9 +22,6 @@ module RubyLsp
|
|
22
22
|
# ```
|
23
23
|
class SemanticHighlighting < Request
|
24
24
|
extend T::Sig
|
25
|
-
extend T::Generic
|
26
|
-
|
27
|
-
ResponseType = type_member { { fixed: T::Array[Listeners::SemanticHighlighting::SemanticToken] } }
|
28
25
|
|
29
26
|
class << self
|
30
27
|
extend T::Sig
|
@@ -34,8 +31,8 @@ module RubyLsp
|
|
34
31
|
Interface::SemanticTokensRegistrationOptions.new(
|
35
32
|
document_selector: { scheme: "file", language: "ruby" },
|
36
33
|
legend: Interface::SemanticTokensLegend.new(
|
37
|
-
token_types:
|
38
|
-
token_modifiers:
|
34
|
+
token_types: ResponseBuilders::SemanticHighlighting::TOKEN_TYPES.keys,
|
35
|
+
token_modifiers: ResponseBuilders::SemanticHighlighting::TOKEN_MODIFIERS.keys,
|
39
36
|
),
|
40
37
|
range: true,
|
41
38
|
full: { delta: false },
|
@@ -46,12 +43,17 @@ module RubyLsp
|
|
46
43
|
sig { params(dispatcher: Prism::Dispatcher, range: T.nilable(T::Range[Integer])).void }
|
47
44
|
def initialize(dispatcher, range: nil)
|
48
45
|
super()
|
49
|
-
@
|
46
|
+
@response_builder = T.let(ResponseBuilders::SemanticHighlighting.new, ResponseBuilders::SemanticHighlighting)
|
47
|
+
Listeners::SemanticHighlighting.new(dispatcher, @response_builder, range: range)
|
48
|
+
|
49
|
+
Addon.addons.each do |addon|
|
50
|
+
addon.create_semantic_highlighting_listener(@response_builder, dispatcher)
|
51
|
+
end
|
50
52
|
end
|
51
53
|
|
52
|
-
sig { override.returns(
|
54
|
+
sig { override.returns(Interface::SemanticTokens) }
|
53
55
|
def perform
|
54
|
-
@
|
56
|
+
@response_builder.response
|
55
57
|
end
|
56
58
|
end
|
57
59
|
end
|
@@ -26,7 +26,6 @@ module RubyLsp
|
|
26
26
|
# ```
|
27
27
|
class SignatureHelp < Request
|
28
28
|
extend T::Sig
|
29
|
-
extend T::Generic
|
30
29
|
|
31
30
|
class << self
|
32
31
|
extend T::Sig
|
@@ -40,8 +39,6 @@ module RubyLsp
|
|
40
39
|
end
|
41
40
|
end
|
42
41
|
|
43
|
-
ResponseType = type_member { { fixed: T.nilable(T.any(Interface::SignatureHelp, T::Hash[Symbol, T.untyped])) } }
|
44
|
-
|
45
42
|
sig do
|
46
43
|
params(
|
47
44
|
document: Document,
|
@@ -53,34 +50,72 @@ module RubyLsp
|
|
53
50
|
end
|
54
51
|
def initialize(document, index, position, context, dispatcher)
|
55
52
|
super()
|
56
|
-
current_signature = context && context[:activeSignatureHelp]
|
57
53
|
target, parent, nesting = document.locate_node(
|
58
|
-
{ line: position[:line], character: position[:character]
|
54
|
+
{ line: position[:line], character: position[:character] },
|
59
55
|
node_types: [Prism::CallNode],
|
60
56
|
)
|
61
57
|
|
62
|
-
|
63
|
-
# method call incorrectly. To correct that, we check if there's an active signature with the same name as the
|
64
|
-
# parent node and then replace the target
|
65
|
-
if current_signature && parent.is_a?(Prism::CallNode)
|
66
|
-
active_signature = current_signature[:activeSignature] || 0
|
67
|
-
|
68
|
-
if current_signature.dig(:signatures, active_signature, :label)&.start_with?(parent.message)
|
69
|
-
target = parent
|
70
|
-
end
|
71
|
-
end
|
58
|
+
target = adjust_for_nested_target(target, parent, position)
|
72
59
|
|
73
60
|
@target = T.let(target, T.nilable(Prism::Node))
|
74
61
|
@dispatcher = dispatcher
|
75
|
-
@
|
62
|
+
@response_builder = T.let(ResponseBuilders::SignatureHelp.new, ResponseBuilders::SignatureHelp)
|
63
|
+
Listeners::SignatureHelp.new(@response_builder, nesting, index, dispatcher)
|
76
64
|
end
|
77
65
|
|
78
|
-
sig { override.returns(
|
66
|
+
sig { override.returns(T.nilable(Interface::SignatureHelp)) }
|
79
67
|
def perform
|
80
68
|
return unless @target
|
81
69
|
|
82
70
|
@dispatcher.dispatch_once(@target)
|
83
|
-
@
|
71
|
+
@response_builder.response
|
72
|
+
end
|
73
|
+
|
74
|
+
private
|
75
|
+
|
76
|
+
# Adjust the target of signature help in the case where we have nested method calls. This is necessary so that we
|
77
|
+
# select the right target in a situation like this:
|
78
|
+
#
|
79
|
+
# foo(another_method_call)
|
80
|
+
#
|
81
|
+
# In that case, we want to provide signature help for `foo` and not `another_method_call`.
|
82
|
+
sig do
|
83
|
+
params(
|
84
|
+
target: T.nilable(Prism::Node),
|
85
|
+
parent: T.nilable(Prism::Node),
|
86
|
+
position: T::Hash[Symbol, T.untyped],
|
87
|
+
).returns(T.nilable(Prism::Node))
|
88
|
+
end
|
89
|
+
def adjust_for_nested_target(target, parent, position)
|
90
|
+
# If the parent node is not a method call, then make no adjustments
|
91
|
+
return target unless parent.is_a?(Prism::CallNode)
|
92
|
+
# If the parent is a method call, but the target isn't, then return the parent
|
93
|
+
return parent unless target.is_a?(Prism::CallNode)
|
94
|
+
|
95
|
+
# If both are method calls, we check the arguments of the inner method call. If there are no arguments, then
|
96
|
+
# we're providing signature help for the outer method call.
|
97
|
+
#
|
98
|
+
# If there are arguments, then we check if the arguments node covers the requested position. If it doesn't
|
99
|
+
# cover, then we're providing signature help for the outer method call.
|
100
|
+
arguments = target.arguments
|
101
|
+
arguments.nil? || !node_covers?(arguments, position) ? parent : target
|
102
|
+
end
|
103
|
+
|
104
|
+
sig { params(node: Prism::Node, position: T::Hash[Symbol, T.untyped]).returns(T::Boolean) }
|
105
|
+
def node_covers?(node, position)
|
106
|
+
location = node.location
|
107
|
+
start_line = location.start_line - 1
|
108
|
+
start_character = location.start_column
|
109
|
+
end_line = location.end_line - 1
|
110
|
+
end_character = location.end_column
|
111
|
+
|
112
|
+
start_covered = start_line < position[:line] ||
|
113
|
+
(start_line == position[:line] && start_character <= position[:character])
|
114
|
+
|
115
|
+
end_covered = end_line > position[:line] ||
|
116
|
+
(end_line == position[:line] && end_character >= position[:character])
|
117
|
+
|
118
|
+
start_covered && end_covered
|
84
119
|
end
|
85
120
|
end
|
86
121
|
end
|
@@ -86,9 +86,9 @@ module RubyLsp
|
|
86
86
|
params(
|
87
87
|
title: String,
|
88
88
|
entries: T.any(T::Array[RubyIndexer::Entry], RubyIndexer::Entry),
|
89
|
-
).returns(
|
89
|
+
).returns(T::Hash[Symbol, String])
|
90
90
|
end
|
91
|
-
def
|
91
|
+
def categorized_markdown_from_index_entries(title, entries)
|
92
92
|
markdown_title = "```ruby\n#{title}\n```"
|
93
93
|
definitions = []
|
94
94
|
content = +""
|
@@ -108,16 +108,44 @@ module RubyLsp
|
|
108
108
|
content << "\n\n#{entry.comments.join("\n")}" unless entry.comments.empty?
|
109
109
|
end
|
110
110
|
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
111
|
+
{
|
112
|
+
title: markdown_title,
|
113
|
+
links: "**Definitions**: #{definitions.join(" | ")}",
|
114
|
+
documentation: content,
|
115
|
+
}
|
116
|
+
end
|
115
117
|
|
116
|
-
|
118
|
+
sig do
|
119
|
+
params(
|
120
|
+
title: String,
|
121
|
+
entries: T.any(T::Array[RubyIndexer::Entry], RubyIndexer::Entry),
|
122
|
+
).returns(String)
|
123
|
+
end
|
124
|
+
def markdown_from_index_entries(title, entries)
|
125
|
+
categorized_markdown = categorized_markdown_from_index_entries(title, entries)
|
117
126
|
|
118
|
-
|
119
|
-
|
120
|
-
|
127
|
+
<<~MARKDOWN.chomp
|
128
|
+
#{categorized_markdown[:title]}
|
129
|
+
|
130
|
+
#{categorized_markdown[:links]}
|
131
|
+
|
132
|
+
#{categorized_markdown[:documentation]}
|
133
|
+
MARKDOWN
|
134
|
+
end
|
135
|
+
|
136
|
+
sig do
|
137
|
+
params(
|
138
|
+
node: T.any(
|
139
|
+
Prism::ConstantPathNode,
|
140
|
+
Prism::ConstantReadNode,
|
141
|
+
Prism::ConstantPathTargetNode,
|
142
|
+
),
|
143
|
+
).returns(T.nilable(String))
|
144
|
+
end
|
145
|
+
def constant_name(node)
|
146
|
+
node.full_name
|
147
|
+
rescue Prism::ConstantPathNode::DynamicPartsInConstantPathError
|
148
|
+
nil
|
121
149
|
end
|
122
150
|
end
|
123
151
|
end
|
@@ -63,7 +63,11 @@ module RubyLsp
|
|
63
63
|
def detect_typechecker
|
64
64
|
return false if ENV["RUBY_LSP_BYPASS_TYPECHECKER"]
|
65
65
|
|
66
|
-
|
66
|
+
Bundler.with_original_env do
|
67
|
+
Bundler.locked_gems.specs.any? { |spec| spec.name == "sorbet-static" }
|
68
|
+
end
|
69
|
+
rescue Bundler::GemfileNotFound
|
70
|
+
false
|
67
71
|
end
|
68
72
|
|
69
73
|
sig { returns(T::Array[String]) }
|
data/lib/ruby_lsp/requests.rb
CHANGED
@@ -50,7 +50,6 @@ module RubyLsp
|
|
50
50
|
module Support
|
51
51
|
autoload :RuboCopDiagnostic, "ruby_lsp/requests/support/rubocop_diagnostic"
|
52
52
|
autoload :SelectionRange, "ruby_lsp/requests/support/selection_range"
|
53
|
-
autoload :SemanticTokenEncoder, "ruby_lsp/requests/support/semantic_token_encoder"
|
54
53
|
autoload :Annotation, "ruby_lsp/requests/support/annotation"
|
55
54
|
autoload :Sorbet, "ruby_lsp/requests/support/sorbet"
|
56
55
|
autoload :RailsDocumentClient, "ruby_lsp/requests/support/rails_document_client"
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module RubyLsp
|
5
|
+
module ResponseBuilders
|
6
|
+
class CollectionResponseBuilder < ResponseBuilder
|
7
|
+
extend T::Sig
|
8
|
+
extend T::Generic
|
9
|
+
|
10
|
+
ResponseType = type_member { { upper: Object } }
|
11
|
+
|
12
|
+
sig { void }
|
13
|
+
def initialize
|
14
|
+
super
|
15
|
+
@items = T.let([], T::Array[ResponseType])
|
16
|
+
end
|
17
|
+
|
18
|
+
sig { params(item: ResponseType).void }
|
19
|
+
def <<(item)
|
20
|
+
@items << item
|
21
|
+
end
|
22
|
+
|
23
|
+
sig { override.returns(T::Array[ResponseType]) }
|
24
|
+
def response
|
25
|
+
@items
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module RubyLsp
|
5
|
+
module ResponseBuilders
|
6
|
+
class DocumentSymbol < ResponseBuilder
|
7
|
+
ResponseType = type_member { { fixed: T::Array[Interface::DocumentSymbol] } }
|
8
|
+
|
9
|
+
class SymbolHierarchyRoot
|
10
|
+
extend T::Sig
|
11
|
+
|
12
|
+
sig { returns(T::Array[Interface::DocumentSymbol]) }
|
13
|
+
attr_reader :children
|
14
|
+
|
15
|
+
sig { void }
|
16
|
+
def initialize
|
17
|
+
@children = T.let([], T::Array[Interface::DocumentSymbol])
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
extend T::Sig
|
22
|
+
|
23
|
+
sig { void }
|
24
|
+
def initialize
|
25
|
+
super
|
26
|
+
@stack = T.let(
|
27
|
+
[SymbolHierarchyRoot.new],
|
28
|
+
T::Array[T.any(SymbolHierarchyRoot, Interface::DocumentSymbol)],
|
29
|
+
)
|
30
|
+
end
|
31
|
+
|
32
|
+
sig { params(symbol: Interface::DocumentSymbol).void }
|
33
|
+
def push(symbol)
|
34
|
+
@stack << symbol
|
35
|
+
end
|
36
|
+
|
37
|
+
alias_method(:<<, :push)
|
38
|
+
|
39
|
+
sig { returns(T.nilable(Interface::DocumentSymbol)) }
|
40
|
+
def pop
|
41
|
+
if @stack.size > 1
|
42
|
+
T.cast(@stack.pop, Interface::DocumentSymbol)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
sig { returns(T.any(SymbolHierarchyRoot, Interface::DocumentSymbol)) }
|
47
|
+
def last
|
48
|
+
T.must(@stack.last)
|
49
|
+
end
|
50
|
+
|
51
|
+
sig { override.returns(T::Array[Interface::DocumentSymbol]) }
|
52
|
+
def response
|
53
|
+
T.must(@stack.first).children
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module RubyLsp
|
5
|
+
module ResponseBuilders
|
6
|
+
class Hover < ResponseBuilder
|
7
|
+
ResponseType = type_member { { fixed: String } }
|
8
|
+
|
9
|
+
extend T::Sig
|
10
|
+
extend T::Generic
|
11
|
+
|
12
|
+
sig { void }
|
13
|
+
def initialize
|
14
|
+
super
|
15
|
+
|
16
|
+
@response = T.let(
|
17
|
+
{
|
18
|
+
title: +"",
|
19
|
+
links: +"",
|
20
|
+
documentation: +"",
|
21
|
+
},
|
22
|
+
T::Hash[Symbol, String],
|
23
|
+
)
|
24
|
+
end
|
25
|
+
|
26
|
+
sig { params(content: String, category: Symbol).void }
|
27
|
+
def push(content, category:)
|
28
|
+
hover_content = @response[category]
|
29
|
+
if hover_content
|
30
|
+
hover_content << content + "\n"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
sig { returns(T::Boolean) }
|
35
|
+
def empty?
|
36
|
+
@response.values.all?(&:empty?)
|
37
|
+
end
|
38
|
+
|
39
|
+
sig { override.returns(ResponseType) }
|
40
|
+
def response
|
41
|
+
result = T.must(@response[:title])
|
42
|
+
result << "\n" << @response[:links] if @response[:links]
|
43
|
+
result << "\n" << @response[:documentation] if @response[:documentation]
|
44
|
+
|
45
|
+
result.strip
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module RubyLsp
|
5
|
+
module ResponseBuilders
|
6
|
+
class ResponseBuilder
|
7
|
+
extend T::Sig
|
8
|
+
extend T::Generic
|
9
|
+
|
10
|
+
abstract!
|
11
|
+
|
12
|
+
sig { abstract.returns(T.anything) }
|
13
|
+
def response; end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|