ruby-lsp 0.12.2 → 0.12.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +1 -0
- data/VERSION +1 -1
- data/exe/ruby-lsp-doctor +2 -2
- data/lib/ruby_indexer/lib/ruby_indexer/{visitor.rb → collector.rb} +108 -59
- data/lib/ruby_indexer/lib/ruby_indexer/configuration.rb +8 -3
- data/lib/ruby_indexer/lib/ruby_indexer/entry.rb +9 -3
- data/lib/ruby_indexer/lib/ruby_indexer/index.rb +22 -4
- data/lib/ruby_indexer/ruby_indexer.rb +1 -1
- data/lib/ruby_indexer/test/index_test.rb +53 -0
- data/lib/ruby_indexer/test/method_test.rb +14 -0
- data/lib/ruby_lsp/document.rb +7 -9
- data/lib/ruby_lsp/executor.rb +29 -24
- data/lib/ruby_lsp/internal.rb +4 -0
- data/lib/ruby_lsp/requests/code_action_resolve.rb +8 -4
- data/lib/ruby_lsp/requests/completion.rb +49 -3
- data/lib/ruby_lsp/requests/definition.rb +52 -25
- data/lib/ruby_lsp/requests/document_highlight.rb +18 -8
- data/lib/ruby_lsp/requests/folding_ranges.rb +1 -1
- data/lib/ruby_lsp/requests/hover.rb +20 -0
- data/lib/ruby_lsp/requests/inlay_hints.rb +39 -1
- data/lib/ruby_lsp/requests/on_type_formatting.rb +16 -1
- data/lib/ruby_lsp/requests/semantic_highlighting.rb +13 -5
- data/lib/ruby_lsp/requests/support/common.rb +22 -2
- data/lib/ruby_lsp/requests/support/dependency_detector.rb +0 -1
- data/lib/ruby_lsp/requests/workspace_symbol.rb +4 -11
- data/lib/ruby_lsp/ruby_document.rb +14 -0
- data/lib/ruby_lsp/setup_bundler.rb +2 -0
- data/lib/ruby_lsp/store.rb +1 -3
- data/lib/ruby_lsp/utils.rb +9 -0
- metadata +8 -7
@@ -87,15 +87,19 @@ module RubyLsp
|
|
87
87
|
:start,
|
88
88
|
:line,
|
89
89
|
) && closest_node_loc.end_line - 1 >= source_range.dig(:end, :line)
|
90
|
-
|
91
|
-
target_line =
|
90
|
+
indentation_line_number = closest_node_loc.start_line - 1
|
91
|
+
target_line = indentation_line_number
|
92
92
|
else
|
93
93
|
target_line = closest_node_loc.end_line
|
94
|
-
|
94
|
+
indentation_line_number = closest_node_loc.end_line - 1
|
95
95
|
end
|
96
96
|
|
97
97
|
lines = @document.source.lines
|
98
|
-
|
98
|
+
|
99
|
+
indentation_line = lines[indentation_line_number]
|
100
|
+
return Error::InvalidTargetRange unless indentation_line
|
101
|
+
|
102
|
+
indentation = T.must(indentation_line[/\A */]).size
|
99
103
|
|
100
104
|
target_range = {
|
101
105
|
start: { line: target_line, character: indentation },
|
@@ -6,9 +6,14 @@ module RubyLsp
|
|
6
6
|
# ![Completion demo](../../completion.gif)
|
7
7
|
#
|
8
8
|
# The [completion](https://microsoft.github.io/language-server-protocol/specification#textDocument_completion)
|
9
|
-
# suggests possible completions according to what the developer is typing.
|
10
|
-
#
|
11
|
-
#
|
9
|
+
# suggests possible completions according to what the developer is typing.
|
10
|
+
#
|
11
|
+
# Currently supported targets:
|
12
|
+
# - Classes
|
13
|
+
# - Modules
|
14
|
+
# - Constants
|
15
|
+
# - Require paths
|
16
|
+
# - Methods invoked on self only
|
12
17
|
#
|
13
18
|
# # Example
|
14
19
|
#
|
@@ -45,6 +50,7 @@ module RubyLsp
|
|
45
50
|
:on_string_node_enter,
|
46
51
|
:on_constant_path_node_enter,
|
47
52
|
:on_constant_read_node_enter,
|
53
|
+
:on_call_node_enter,
|
48
54
|
)
|
49
55
|
end
|
50
56
|
|
@@ -118,8 +124,48 @@ module RubyLsp
|
|
118
124
|
end
|
119
125
|
end
|
120
126
|
|
127
|
+
sig { params(node: Prism::CallNode).void }
|
128
|
+
def on_call_node_enter(node)
|
129
|
+
return if DependencyDetector.instance.typechecker
|
130
|
+
return unless self_receiver?(node)
|
131
|
+
|
132
|
+
name = node.message
|
133
|
+
return unless name
|
134
|
+
|
135
|
+
receiver_entries = @index[@nesting.join("::")]
|
136
|
+
return unless receiver_entries
|
137
|
+
|
138
|
+
receiver = T.must(receiver_entries.first)
|
139
|
+
|
140
|
+
candidates = T.cast(@index.prefix_search(name), T::Array[T::Array[RubyIndexer::Entry::Method]])
|
141
|
+
candidates.each do |entries|
|
142
|
+
entry = entries.find { |e| e.owner&.name == receiver.name }
|
143
|
+
next unless entry
|
144
|
+
|
145
|
+
@_response << build_method_completion(entry, node)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
121
149
|
private
|
122
150
|
|
151
|
+
sig { params(entry: RubyIndexer::Entry::Method, node: Prism::CallNode).returns(Interface::CompletionItem) }
|
152
|
+
def build_method_completion(entry, node)
|
153
|
+
name = entry.name
|
154
|
+
parameters = entry.parameters
|
155
|
+
new_text = parameters.empty? ? name : "#{name}(#{parameters.map(&:name).join(", ")})"
|
156
|
+
|
157
|
+
Interface::CompletionItem.new(
|
158
|
+
label: name,
|
159
|
+
filter_text: name,
|
160
|
+
text_edit: Interface::TextEdit.new(range: range_from_node(node), new_text: new_text),
|
161
|
+
kind: Constant::CompletionItemKind::METHOD,
|
162
|
+
label_details: Interface::CompletionItemLabelDetails.new(
|
163
|
+
description: entry.file_name,
|
164
|
+
),
|
165
|
+
documentation: markdown_from_index_entries(name, entry),
|
166
|
+
)
|
167
|
+
end
|
168
|
+
|
123
169
|
sig { params(label: String, node: Prism::StringNode).returns(Interface::CompletionItem) }
|
124
170
|
def build_completion(label, node)
|
125
171
|
Interface::CompletionItem.new(
|
@@ -9,7 +9,12 @@ module RubyLsp
|
|
9
9
|
# request](https://microsoft.github.io/language-server-protocol/specification#textDocument_definition) jumps to the
|
10
10
|
# definition of the symbol under the cursor.
|
11
11
|
#
|
12
|
-
# Currently
|
12
|
+
# Currently supported targets:
|
13
|
+
# - Classes
|
14
|
+
# - Modules
|
15
|
+
# - Constants
|
16
|
+
# - Require paths
|
17
|
+
# - Methods invoked on self only
|
13
18
|
#
|
14
19
|
# # Example
|
15
20
|
#
|
@@ -75,8 +80,52 @@ module RubyLsp
|
|
75
80
|
sig { params(node: Prism::CallNode).void }
|
76
81
|
def on_call_node_enter(node)
|
77
82
|
message = node.name
|
78
|
-
return unless message == :require || message == :require_relative
|
79
83
|
|
84
|
+
if message == :require || message == :require_relative
|
85
|
+
handle_require_definition(node)
|
86
|
+
else
|
87
|
+
handle_method_definition(node)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
sig { params(node: Prism::ConstantPathNode).void }
|
92
|
+
def on_constant_path_node_enter(node)
|
93
|
+
find_in_index(node.slice)
|
94
|
+
end
|
95
|
+
|
96
|
+
sig { params(node: Prism::ConstantReadNode).void }
|
97
|
+
def on_constant_read_node_enter(node)
|
98
|
+
find_in_index(node.slice)
|
99
|
+
end
|
100
|
+
|
101
|
+
private
|
102
|
+
|
103
|
+
sig { params(node: Prism::CallNode).void }
|
104
|
+
def handle_method_definition(node)
|
105
|
+
return unless self_receiver?(node)
|
106
|
+
|
107
|
+
message = node.message
|
108
|
+
return unless message
|
109
|
+
|
110
|
+
target_method = @index.resolve_method(message, @nesting.join("::"))
|
111
|
+
return unless target_method
|
112
|
+
|
113
|
+
location = target_method.location
|
114
|
+
file_path = target_method.file_path
|
115
|
+
return if defined_in_gem?(file_path)
|
116
|
+
|
117
|
+
@_response = Interface::Location.new(
|
118
|
+
uri: URI::Generic.from_path(path: file_path).to_s,
|
119
|
+
range: Interface::Range.new(
|
120
|
+
start: Interface::Position.new(line: location.start_line - 1, character: location.start_column),
|
121
|
+
end: Interface::Position.new(line: location.end_line - 1, character: location.end_column),
|
122
|
+
),
|
123
|
+
)
|
124
|
+
end
|
125
|
+
|
126
|
+
sig { params(node: Prism::CallNode).void }
|
127
|
+
def handle_require_definition(node)
|
128
|
+
message = node.name
|
80
129
|
arguments = node.arguments
|
81
130
|
return unless arguments
|
82
131
|
|
@@ -116,18 +165,6 @@ module RubyLsp
|
|
116
165
|
end
|
117
166
|
end
|
118
167
|
|
119
|
-
sig { params(node: Prism::ConstantPathNode).void }
|
120
|
-
def on_constant_path_node_enter(node)
|
121
|
-
find_in_index(node.slice)
|
122
|
-
end
|
123
|
-
|
124
|
-
sig { params(node: Prism::ConstantReadNode).void }
|
125
|
-
def on_constant_read_node_enter(node)
|
126
|
-
find_in_index(node.slice)
|
127
|
-
end
|
128
|
-
|
129
|
-
private
|
130
|
-
|
131
168
|
sig { params(value: String).void }
|
132
169
|
def find_in_index(value)
|
133
170
|
entries = @index.resolve(value, @nesting)
|
@@ -138,23 +175,13 @@ module RubyLsp
|
|
138
175
|
first_entry = T.must(entries.first)
|
139
176
|
return if first_entry.visibility == :private && first_entry.name != "#{@nesting.join("::")}::#{value}"
|
140
177
|
|
141
|
-
bundle_path = begin
|
142
|
-
Bundler.bundle_path.to_s
|
143
|
-
rescue Bundler::GemfileNotFound
|
144
|
-
nil
|
145
|
-
end
|
146
|
-
|
147
178
|
@_response = entries.filter_map do |entry|
|
148
179
|
location = entry.location
|
149
180
|
# If the project has Sorbet, then we only want to handle go to definition for constants defined in gems, as an
|
150
181
|
# additional behavior on top of jumping to RBIs. Sorbet can already handle go to definition for all constants
|
151
182
|
# in the project, even if the files are typed false
|
152
183
|
file_path = entry.file_path
|
153
|
-
if
|
154
|
-
!file_path.start_with?(RbConfig::CONFIG["rubylibdir"])
|
155
|
-
|
156
|
-
next
|
157
|
-
end
|
184
|
+
next if defined_in_gem?(file_path)
|
158
185
|
|
159
186
|
Interface::Location.new(
|
160
187
|
uri: URI::Generic.from_path(path: file_path).to_s,
|
@@ -97,7 +97,8 @@ module RubyLsp
|
|
97
97
|
Prism::LocalVariableWriteNode,
|
98
98
|
Prism::BlockParameterNode,
|
99
99
|
Prism::RequiredParameterNode,
|
100
|
-
Prism::
|
100
|
+
Prism::RequiredKeywordParameterNode,
|
101
|
+
Prism::OptionalKeywordParameterNode,
|
101
102
|
Prism::RestParameterNode,
|
102
103
|
Prism::OptionalParameterNode,
|
103
104
|
Prism::KeywordRestParameterNode,
|
@@ -137,8 +138,9 @@ module RubyLsp
|
|
137
138
|
Prism::ClassVariableReadNode, Prism::ClassVariableTargetNode, Prism::ClassVariableWriteNode,
|
138
139
|
Prism::LocalVariableAndWriteNode, Prism::LocalVariableOperatorWriteNode, Prism::LocalVariableOrWriteNode,
|
139
140
|
Prism::LocalVariableReadNode, Prism::LocalVariableTargetNode, Prism::LocalVariableWriteNode,
|
140
|
-
Prism::CallNode, Prism::BlockParameterNode, Prism::
|
141
|
-
Prism::
|
141
|
+
Prism::CallNode, Prism::BlockParameterNode, Prism::RequiredKeywordParameterNode,
|
142
|
+
Prism::RequiredKeywordParameterNode, Prism::KeywordRestParameterNode, Prism::OptionalParameterNode,
|
143
|
+
Prism::RequiredParameterNode, Prism::RestParameterNode
|
142
144
|
target
|
143
145
|
end
|
144
146
|
|
@@ -171,7 +173,8 @@ module RubyLsp
|
|
171
173
|
:on_constant_path_and_write_node_enter,
|
172
174
|
:on_constant_path_operator_write_node_enter,
|
173
175
|
:on_local_variable_write_node_enter,
|
174
|
-
:
|
176
|
+
:on_required_keyword_parameter_node_enter,
|
177
|
+
:on_optional_keyword_parameter_node_enter,
|
175
178
|
:on_rest_parameter_node_enter,
|
176
179
|
:on_optional_parameter_node_enter,
|
177
180
|
:on_keyword_rest_parameter_node_enter,
|
@@ -359,8 +362,15 @@ module RubyLsp
|
|
359
362
|
add_highlight(Constant::DocumentHighlightKind::WRITE, node.name_loc)
|
360
363
|
end
|
361
364
|
|
362
|
-
sig { params(node: Prism::
|
363
|
-
def
|
365
|
+
sig { params(node: Prism::RequiredKeywordParameterNode).void }
|
366
|
+
def on_required_keyword_parameter_node_enter(node)
|
367
|
+
return unless matches?(node, LOCAL_NODES)
|
368
|
+
|
369
|
+
add_highlight(Constant::DocumentHighlightKind::WRITE, node.name_loc)
|
370
|
+
end
|
371
|
+
|
372
|
+
sig { params(node: Prism::OptionalKeywordParameterNode).void }
|
373
|
+
def on_optional_keyword_parameter_node_enter(node)
|
364
374
|
return unless matches?(node, LOCAL_NODES)
|
365
375
|
|
366
376
|
add_highlight(Constant::DocumentHighlightKind::WRITE, node.name_loc)
|
@@ -551,8 +561,8 @@ module RubyLsp
|
|
551
561
|
Prism::ClassVariableTargetNode, Prism::ClassVariableWriteNode, Prism::LocalVariableAndWriteNode,
|
552
562
|
Prism::LocalVariableOperatorWriteNode, Prism::LocalVariableOrWriteNode, Prism::LocalVariableReadNode,
|
553
563
|
Prism::LocalVariableTargetNode, Prism::LocalVariableWriteNode, Prism::DefNode, Prism::BlockParameterNode,
|
554
|
-
Prism::
|
555
|
-
Prism::RequiredParameterNode, Prism::RestParameterNode
|
564
|
+
Prism::RequiredKeywordParameterNode, Prism::OptionalKeywordParameterNode, Prism::KeywordRestParameterNode,
|
565
|
+
Prism::OptionalParameterNode, Prism::RequiredParameterNode, Prism::RestParameterNode
|
556
566
|
|
557
567
|
node.name.to_s
|
558
568
|
when Prism::CallNode
|
@@ -94,7 +94,7 @@ module RubyLsp
|
|
94
94
|
opening_loc = node.opening_loc
|
95
95
|
closing_loc = node.closing_loc
|
96
96
|
|
97
|
-
add_lines_range(opening_loc.start_line, closing_loc.
|
97
|
+
add_lines_range(opening_loc.start_line, closing_loc.start_line - 1) if opening_loc && closing_loc
|
98
98
|
end
|
99
99
|
|
100
100
|
sig { params(node: Prism::ArrayNode).void }
|
@@ -51,6 +51,7 @@ module RubyLsp
|
|
51
51
|
:on_constant_read_node_enter,
|
52
52
|
:on_constant_write_node_enter,
|
53
53
|
:on_constant_path_node_enter,
|
54
|
+
:on_call_node_enter,
|
54
55
|
)
|
55
56
|
end
|
56
57
|
|
@@ -95,6 +96,25 @@ module RubyLsp
|
|
95
96
|
generate_hover(node.slice, node.location)
|
96
97
|
end
|
97
98
|
|
99
|
+
sig { params(node: Prism::CallNode).void }
|
100
|
+
def on_call_node_enter(node)
|
101
|
+
return if DependencyDetector.instance.typechecker
|
102
|
+
return unless self_receiver?(node)
|
103
|
+
|
104
|
+
message = node.message
|
105
|
+
return unless message
|
106
|
+
|
107
|
+
target_method = @index.resolve_method(message, @nesting.join("::"))
|
108
|
+
return unless target_method
|
109
|
+
|
110
|
+
location = target_method.location
|
111
|
+
|
112
|
+
@_response = Interface::Hover.new(
|
113
|
+
range: range_from_location(location),
|
114
|
+
contents: markdown_from_index_entries(message, target_method),
|
115
|
+
)
|
116
|
+
end
|
117
|
+
|
98
118
|
private
|
99
119
|
|
100
120
|
sig { params(name: String, location: Prism::Location).void }
|
@@ -18,6 +18,16 @@ module RubyLsp
|
|
18
18
|
# puts "handle some rescue"
|
19
19
|
# end
|
20
20
|
# ```
|
21
|
+
#
|
22
|
+
# # Example
|
23
|
+
#
|
24
|
+
# ```ruby
|
25
|
+
# var = "foo"
|
26
|
+
# {
|
27
|
+
# var: var, # Label "var" goes here in cases where the value is omitted
|
28
|
+
# a: "hello",
|
29
|
+
# }
|
30
|
+
# ```
|
21
31
|
class InlayHints < Listener
|
22
32
|
extend T::Sig
|
23
33
|
extend T::Generic
|
@@ -36,7 +46,7 @@ module RubyLsp
|
|
36
46
|
@_response = T.let([], ResponseType)
|
37
47
|
@range = range
|
38
48
|
|
39
|
-
dispatcher.register(self, :on_rescue_node_enter)
|
49
|
+
dispatcher.register(self, :on_rescue_node_enter, :on_implicit_node_enter)
|
40
50
|
end
|
41
51
|
|
42
52
|
sig { params(node: Prism::RescueNode).void }
|
@@ -53,6 +63,34 @@ module RubyLsp
|
|
53
63
|
tooltip: "StandardError is implied in a bare rescue",
|
54
64
|
)
|
55
65
|
end
|
66
|
+
|
67
|
+
sig { params(node: Prism::ImplicitNode).void }
|
68
|
+
def on_implicit_node_enter(node)
|
69
|
+
return unless visible?(node, @range)
|
70
|
+
|
71
|
+
node_value = node.value
|
72
|
+
loc = node.location
|
73
|
+
tooltip = ""
|
74
|
+
node_name = ""
|
75
|
+
case node_value
|
76
|
+
when Prism::CallNode
|
77
|
+
node_name = node_value.name
|
78
|
+
tooltip = "This is a method call. Method name: #{node_name}"
|
79
|
+
when Prism::ConstantReadNode
|
80
|
+
node_name = node_value.name
|
81
|
+
tooltip = "This is a constant: #{node_name}"
|
82
|
+
when Prism::LocalVariableReadNode
|
83
|
+
node_name = node_value.name
|
84
|
+
tooltip = "This is a local variable: #{node_name}"
|
85
|
+
end
|
86
|
+
|
87
|
+
@_response << Interface::InlayHint.new(
|
88
|
+
position: { line: loc.start_line - 1, character: loc.start_column + node_name.length + 1 },
|
89
|
+
label: node_name,
|
90
|
+
padding_left: true,
|
91
|
+
tooltip: tooltip,
|
92
|
+
)
|
93
|
+
end
|
56
94
|
end
|
57
95
|
end
|
58
96
|
end
|
@@ -51,7 +51,14 @@ module RubyLsp
|
|
51
51
|
if (comment_match = @previous_line.match(/^#(\s*)/))
|
52
52
|
handle_comment_line(T.must(comment_match[1]))
|
53
53
|
elsif @document.syntax_error?
|
54
|
-
|
54
|
+
match = /(?<=<<(-|~))(?<quote>['"`]?)(?<delimiter>\w+)\k<quote>/.match(@previous_line)
|
55
|
+
heredoc_delimiter = match && match.named_captures["delimiter"]
|
56
|
+
|
57
|
+
if heredoc_delimiter
|
58
|
+
handle_heredoc_end(heredoc_delimiter)
|
59
|
+
else
|
60
|
+
handle_statement_end
|
61
|
+
end
|
55
62
|
end
|
56
63
|
end
|
57
64
|
|
@@ -121,6 +128,14 @@ module RubyLsp
|
|
121
128
|
end
|
122
129
|
end
|
123
130
|
|
131
|
+
sig { params(delimiter: String).void }
|
132
|
+
def handle_heredoc_end(delimiter)
|
133
|
+
indents = " " * @indentation
|
134
|
+
add_edit_with_text("\n")
|
135
|
+
add_edit_with_text("#{indents}#{delimiter}")
|
136
|
+
move_cursor_to(@position[:line], @indentation + 2)
|
137
|
+
end
|
138
|
+
|
124
139
|
sig { params(spaces: String).void }
|
125
140
|
def handle_comment_line(spaces)
|
126
141
|
add_edit_with_text("##{spaces}")
|
@@ -135,7 +135,8 @@ module RubyLsp
|
|
135
135
|
:on_local_variable_write_node_enter,
|
136
136
|
:on_local_variable_read_node_enter,
|
137
137
|
:on_block_parameter_node_enter,
|
138
|
-
:
|
138
|
+
:on_required_keyword_parameter_node_enter,
|
139
|
+
:on_optional_keyword_parameter_node_enter,
|
139
140
|
:on_keyword_rest_parameter_node_enter,
|
140
141
|
:on_optional_parameter_node_enter,
|
141
142
|
:on_required_parameter_node_enter,
|
@@ -252,11 +253,18 @@ module RubyLsp
|
|
252
253
|
@current_scope << name.to_sym if name
|
253
254
|
end
|
254
255
|
|
255
|
-
sig { params(node: Prism::
|
256
|
-
def
|
257
|
-
|
258
|
-
|
256
|
+
sig { params(node: Prism::RequiredKeywordParameterNode).void }
|
257
|
+
def on_required_keyword_parameter_node_enter(node)
|
258
|
+
@current_scope << node.name
|
259
|
+
return unless visible?(node, @range)
|
260
|
+
|
261
|
+
location = node.name_loc
|
262
|
+
add_token(location.copy(length: location.length - 1), :parameter)
|
263
|
+
end
|
259
264
|
|
265
|
+
sig { params(node: Prism::OptionalKeywordParameterNode).void }
|
266
|
+
def on_optional_keyword_parameter_node_enter(node)
|
267
|
+
@current_scope << node.name
|
260
268
|
return unless visible?(node, @range)
|
261
269
|
|
262
270
|
location = node.name_loc
|
@@ -9,6 +9,9 @@ module RubyLsp
|
|
9
9
|
# https://github.com/Shopify/ruby-lsp-rails, or addons by created by developers outside of Shopify, so be
|
10
10
|
# cautious of changing anything.
|
11
11
|
extend T::Sig
|
12
|
+
extend T::Helpers
|
13
|
+
|
14
|
+
requires_ancestor { Kernel }
|
12
15
|
|
13
16
|
sig { params(node: Prism::Node).returns(Interface::Range) }
|
14
17
|
def range_from_node(node)
|
@@ -66,12 +69,29 @@ module RubyLsp
|
|
66
69
|
)
|
67
70
|
end
|
68
71
|
|
69
|
-
sig { params(
|
72
|
+
sig { params(file_path: String).returns(T.nilable(T::Boolean)) }
|
73
|
+
def defined_in_gem?(file_path)
|
74
|
+
DependencyDetector.instance.typechecker && BUNDLE_PATH && !file_path.start_with?(T.must(BUNDLE_PATH)) &&
|
75
|
+
!file_path.start_with?(RbConfig::CONFIG["rubylibdir"])
|
76
|
+
end
|
77
|
+
|
78
|
+
sig { params(node: Prism::CallNode).returns(T::Boolean) }
|
79
|
+
def self_receiver?(node)
|
80
|
+
receiver = node.receiver
|
81
|
+
receiver.nil? || receiver.is_a?(Prism::SelfNode)
|
82
|
+
end
|
83
|
+
|
84
|
+
sig do
|
85
|
+
params(
|
86
|
+
title: String,
|
87
|
+
entries: T.any(T::Array[RubyIndexer::Entry], RubyIndexer::Entry),
|
88
|
+
).returns(Interface::MarkupContent)
|
89
|
+
end
|
70
90
|
def markdown_from_index_entries(title, entries)
|
71
91
|
markdown_title = "```ruby\n#{title}\n```"
|
72
92
|
definitions = []
|
73
93
|
content = +""
|
74
|
-
entries.each do |entry|
|
94
|
+
Array(entries).each do |entry|
|
75
95
|
loc = entry.location
|
76
96
|
|
77
97
|
# We always handle locations as zero based. However, for file links in Markdown we need them to be one
|
@@ -66,7 +66,6 @@ module RubyLsp
|
|
66
66
|
|
67
67
|
sig { returns(T::Array[String]) }
|
68
68
|
def dependencies
|
69
|
-
# NOTE: If changing this behaviour, it's likely that the VS Code extension will also need changed.
|
70
69
|
@dependencies ||= T.let(
|
71
70
|
begin
|
72
71
|
Bundler.with_original_env { Bundler.default_gemfile }
|
@@ -20,6 +20,7 @@ module RubyLsp
|
|
20
20
|
#
|
21
21
|
class WorkspaceSymbol
|
22
22
|
extend T::Sig
|
23
|
+
include Support::Common
|
23
24
|
|
24
25
|
sig { params(query: T.nilable(String), index: RubyIndexer::Index).void }
|
25
26
|
def initialize(query, index)
|
@@ -29,21 +30,11 @@ module RubyLsp
|
|
29
30
|
|
30
31
|
sig { returns(T::Array[Interface::WorkspaceSymbol]) }
|
31
32
|
def run
|
32
|
-
bundle_path = begin
|
33
|
-
Bundler.bundle_path.to_s
|
34
|
-
rescue Bundler::GemfileNotFound
|
35
|
-
nil
|
36
|
-
end
|
37
|
-
|
38
33
|
@index.fuzzy_search(@query).filter_map do |entry|
|
39
34
|
# If the project is using Sorbet, we let Sorbet handle symbols defined inside the project itself and RBIs, but
|
40
35
|
# we still return entries defined in gems to allow developers to jump directly to the source
|
41
36
|
file_path = entry.file_path
|
42
|
-
if
|
43
|
-
!file_path.start_with?(RbConfig::CONFIG["rubylibdir"])
|
44
|
-
|
45
|
-
next
|
46
|
-
end
|
37
|
+
next if defined_in_gem?(file_path)
|
47
38
|
|
48
39
|
# We should never show private symbols when searching the entire workspace
|
49
40
|
next if entry.visibility == :private
|
@@ -82,6 +73,8 @@ module RubyLsp
|
|
82
73
|
Constant::SymbolKind::NAMESPACE
|
83
74
|
when RubyIndexer::Entry::Constant
|
84
75
|
Constant::SymbolKind::CONSTANT
|
76
|
+
when RubyIndexer::Entry::Method
|
77
|
+
entry.name == "initialize" ? Constant::SymbolKind::CONSTRUCTOR : Constant::SymbolKind::METHOD
|
85
78
|
end
|
86
79
|
end
|
87
80
|
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module RubyLsp
|
5
|
+
class RubyDocument < Document
|
6
|
+
sig { override.returns(Prism::ParseResult) }
|
7
|
+
def parse
|
8
|
+
return @parse_result unless @needs_parsing
|
9
|
+
|
10
|
+
@needs_parsing = false
|
11
|
+
@parse_result = Prism.parse(@source)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -12,6 +12,8 @@ require "time"
|
|
12
12
|
# the Ruby LSP without including the gem in their application's Gemfile while at the same time giving us access to the
|
13
13
|
# exact locked versions of dependencies.
|
14
14
|
|
15
|
+
Bundler.ui.level = :silent
|
16
|
+
|
15
17
|
module RubyLsp
|
16
18
|
class SetupBundler
|
17
19
|
extend T::Sig
|
data/lib/ruby_lsp/store.rb
CHANGED
@@ -1,8 +1,6 @@
|
|
1
1
|
# typed: strict
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
require "ruby_lsp/document"
|
5
|
-
|
6
4
|
module RubyLsp
|
7
5
|
class Store
|
8
6
|
extend T::Sig
|
@@ -40,7 +38,7 @@ module RubyLsp
|
|
40
38
|
|
41
39
|
sig { params(uri: URI::Generic, source: String, version: Integer).void }
|
42
40
|
def set(uri:, source:, version:)
|
43
|
-
document =
|
41
|
+
document = RubyDocument.new(source: source, version: version, uri: uri, encoding: @encoding)
|
44
42
|
@state[uri.to_s] = document
|
45
43
|
end
|
46
44
|
|
data/lib/ruby_lsp/utils.rb
CHANGED
@@ -8,6 +8,15 @@ module RubyLsp
|
|
8
8
|
# This freeze is not redundant since the interpolated string is mutable
|
9
9
|
WORKSPACE_URI = T.let(URI::Generic.from_path(path: Dir.pwd), URI::Generic)
|
10
10
|
|
11
|
+
BUNDLE_PATH = T.let(
|
12
|
+
begin
|
13
|
+
Bundler.bundle_path.to_s
|
14
|
+
rescue Bundler::GemfileNotFound
|
15
|
+
nil
|
16
|
+
end,
|
17
|
+
T.nilable(String),
|
18
|
+
)
|
19
|
+
|
11
20
|
# A notification to be sent to the client
|
12
21
|
class Message
|
13
22
|
extend T::Sig
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby-lsp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.12.
|
4
|
+
version: 0.12.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Shopify
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-11-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: language_server-protocol
|
@@ -30,20 +30,20 @@ dependencies:
|
|
30
30
|
requirements:
|
31
31
|
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: 0.
|
33
|
+
version: 0.17.1
|
34
34
|
- - "<"
|
35
35
|
- !ruby/object:Gem::Version
|
36
|
-
version: '0.
|
36
|
+
version: '0.18'
|
37
37
|
type: :runtime
|
38
38
|
prerelease: false
|
39
39
|
version_requirements: !ruby/object:Gem::Requirement
|
40
40
|
requirements:
|
41
41
|
- - ">="
|
42
42
|
- !ruby/object:Gem::Version
|
43
|
-
version: 0.
|
43
|
+
version: 0.17.1
|
44
44
|
- - "<"
|
45
45
|
- !ruby/object:Gem::Version
|
46
|
-
version: '0.
|
46
|
+
version: '0.18'
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: sorbet-runtime
|
49
49
|
requirement: !ruby/object:Gem::Requirement
|
@@ -78,12 +78,12 @@ files:
|
|
78
78
|
- lib/rubocop/cop/ruby_lsp/use_language_server_aliases.rb
|
79
79
|
- lib/rubocop/cop/ruby_lsp/use_register_with_handler_method.rb
|
80
80
|
- lib/ruby-lsp.rb
|
81
|
+
- lib/ruby_indexer/lib/ruby_indexer/collector.rb
|
81
82
|
- lib/ruby_indexer/lib/ruby_indexer/configuration.rb
|
82
83
|
- lib/ruby_indexer/lib/ruby_indexer/entry.rb
|
83
84
|
- lib/ruby_indexer/lib/ruby_indexer/index.rb
|
84
85
|
- lib/ruby_indexer/lib/ruby_indexer/indexable_path.rb
|
85
86
|
- lib/ruby_indexer/lib/ruby_indexer/prefix_tree.rb
|
86
|
-
- lib/ruby_indexer/lib/ruby_indexer/visitor.rb
|
87
87
|
- lib/ruby_indexer/ruby_indexer.rb
|
88
88
|
- lib/ruby_indexer/test/classes_and_modules_test.rb
|
89
89
|
- lib/ruby_indexer/test/configuration_test.rb
|
@@ -132,6 +132,7 @@ files:
|
|
132
132
|
- lib/ruby_lsp/requests/support/source_uri.rb
|
133
133
|
- lib/ruby_lsp/requests/support/syntax_tree_formatting_runner.rb
|
134
134
|
- lib/ruby_lsp/requests/workspace_symbol.rb
|
135
|
+
- lib/ruby_lsp/ruby_document.rb
|
135
136
|
- lib/ruby_lsp/server.rb
|
136
137
|
- lib/ruby_lsp/setup_bundler.rb
|
137
138
|
- lib/ruby_lsp/store.rb
|