ruby-lsp 0.16.6 → 0.17.0
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 +21 -4
- data/exe/ruby-lsp-check +1 -3
- data/exe/ruby-lsp-doctor +1 -4
- data/lib/core_ext/uri.rb +3 -0
- data/lib/ruby_indexer/lib/ruby_indexer/{collector.rb → declaration_listener.rb} +258 -140
- data/lib/ruby_indexer/lib/ruby_indexer/entry.rb +101 -12
- data/lib/ruby_indexer/lib/ruby_indexer/index.rb +187 -12
- data/lib/ruby_indexer/ruby_indexer.rb +1 -1
- data/lib/ruby_indexer/test/classes_and_modules_test.rb +106 -10
- data/lib/ruby_indexer/test/configuration_test.rb +4 -5
- data/lib/ruby_indexer/test/constant_test.rb +11 -8
- data/lib/ruby_indexer/test/index_test.rb +528 -0
- data/lib/ruby_indexer/test/instance_variables_test.rb +131 -0
- data/lib/ruby_indexer/test/method_test.rb +93 -0
- data/lib/ruby_indexer/test/test_case.rb +3 -1
- data/lib/ruby_lsp/addon.rb +8 -8
- data/lib/ruby_lsp/document.rb +3 -3
- data/lib/ruby_lsp/internal.rb +1 -0
- data/lib/ruby_lsp/listeners/code_lens.rb +11 -0
- data/lib/ruby_lsp/listeners/completion.rb +144 -51
- data/lib/ruby_lsp/listeners/definition.rb +77 -12
- data/lib/ruby_lsp/listeners/document_highlight.rb +1 -1
- data/lib/ruby_lsp/listeners/document_link.rb +1 -1
- data/lib/ruby_lsp/listeners/hover.rb +60 -6
- data/lib/ruby_lsp/listeners/semantic_highlighting.rb +59 -3
- data/lib/ruby_lsp/listeners/signature_help.rb +4 -4
- data/lib/ruby_lsp/node_context.rb +28 -0
- data/lib/ruby_lsp/requests/code_action_resolve.rb +73 -2
- data/lib/ruby_lsp/requests/code_actions.rb +16 -15
- data/lib/ruby_lsp/requests/completion.rb +22 -13
- data/lib/ruby_lsp/requests/completion_resolve.rb +26 -10
- data/lib/ruby_lsp/requests/definition.rb +21 -5
- data/lib/ruby_lsp/requests/document_highlight.rb +2 -2
- data/lib/ruby_lsp/requests/hover.rb +5 -6
- data/lib/ruby_lsp/requests/on_type_formatting.rb +8 -4
- data/lib/ruby_lsp/requests/signature_help.rb +3 -3
- data/lib/ruby_lsp/requests/support/common.rb +20 -1
- data/lib/ruby_lsp/requests/workspace_symbol.rb +3 -1
- data/lib/ruby_lsp/server.rb +10 -4
- metadata +10 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3060dd91df98bd5412edff61c4f4df8d14d2f3be8c92e33e138cbf078e44ee72
|
4
|
+
data.tar.gz: 8e30d6027e4d2ccd2466c756519a79f53787d9700a43819d985886bf2eaaa721
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cda5116c872c174850448251864538357c6344f6d902f673f99cc9276a70034f9d446bba3b8e8465c4c26b0964c918afd186188cba00d8fe3b95de10b97fab20
|
7
|
+
data.tar.gz: b56637e2becb36b8df37847d44d743f2dc89c9db602e33d66ed4a54920f4f66bddec5017abdefb2ecee86bf35762c4a69bfb3e419c351fdfd17f8ddcfacd1b67
|
data/README.md
CHANGED
@@ -33,7 +33,7 @@ The Ruby LSP features include
|
|
33
33
|
- Completion for classes, modules, constants and require paths
|
34
34
|
- Fuzzy search classes, modules and constants anywhere in the project and its dependencies (workspace symbol)
|
35
35
|
|
36
|
-
Adding method support for definition, completion, hover and workspace symbol is
|
36
|
+
Adding method support for definition, completion, hover and workspace symbol is partially supported, but not yet complete. Follow progress in https://github.com/Shopify/ruby-lsp/issues/899
|
37
37
|
|
38
38
|
See complete information about features [here](https://shopify.github.io/ruby-lsp/RubyLsp/Requests.html).
|
39
39
|
|
@@ -50,7 +50,7 @@ editor. Do not install the `ruby-lsp` gem manually.
|
|
50
50
|
|
51
51
|
### With other editors
|
52
52
|
|
53
|
-
See [editors](EDITORS.md) for community instructions on setting up the Ruby LSP.
|
53
|
+
See [editors](EDITORS.md) for community instructions on setting up the Ruby LSP, which current includes Emacs, Neovim, Sublime Text, and Zed.
|
54
54
|
|
55
55
|
The gem can be installed by doing
|
56
56
|
```shell
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.17.0
|
data/exe/ruby-lsp
CHANGED
@@ -18,6 +18,10 @@ parser = OptionParser.new do |opts|
|
|
18
18
|
options[:debug] = true
|
19
19
|
end
|
20
20
|
|
21
|
+
opts.on("--time-index", "Measure the time it takes to index the project") do
|
22
|
+
options[:time_index] = true
|
23
|
+
end
|
24
|
+
|
21
25
|
opts.on(
|
22
26
|
"--branch [BRANCH]",
|
23
27
|
"Launch the Ruby LSP using the specified branch rather than the release version",
|
@@ -80,14 +84,27 @@ if options[:debug]
|
|
80
84
|
end
|
81
85
|
|
82
86
|
begin
|
83
|
-
|
84
|
-
$stdout = $stderr
|
87
|
+
ENV.delete("RUBY_DEBUG_IRB_CONSOLE")
|
85
88
|
require "debug/open_nonstop"
|
86
89
|
rescue LoadError
|
87
90
|
$stderr.puts("You need to install the debug gem to use the --debug flag")
|
88
|
-
ensure
|
89
|
-
$stdout = original_stdout
|
90
91
|
end
|
91
92
|
end
|
92
93
|
|
94
|
+
if options[:time_index]
|
95
|
+
require "benchmark"
|
96
|
+
|
97
|
+
index = RubyIndexer::Index.new
|
98
|
+
|
99
|
+
result = Benchmark.realtime { index.index_all }
|
100
|
+
entries = index.instance_variable_get(:@entries)
|
101
|
+
entries_by_entry_type = entries.values.flatten.group_by(&:class)
|
102
|
+
|
103
|
+
puts <<~MSG
|
104
|
+
Ruby LSP v#{RubyLsp::VERSION}: Indexing took #{result.round(5)} seconds and generated:
|
105
|
+
- #{entries_by_entry_type.map { |k, v| "#{k.name.split("::").last}: #{v.size}" }.join("\n- ")}
|
106
|
+
MSG
|
107
|
+
return
|
108
|
+
end
|
109
|
+
|
93
110
|
RubyLsp::Server.new.start
|
data/exe/ruby-lsp-check
CHANGED
@@ -47,9 +47,7 @@ index = RubyIndexer::Index.new
|
|
47
47
|
indexables = RubyIndexer.configuration.indexables
|
48
48
|
|
49
49
|
indexables.each_with_index do |indexable, i|
|
50
|
-
|
51
|
-
collector = RubyIndexer::Collector.new(index, result, indexable.full_path)
|
52
|
-
collector.collect(result.value)
|
50
|
+
index.index_single(indexable)
|
53
51
|
rescue => e
|
54
52
|
errors[indexable.full_path] = e
|
55
53
|
ensure
|
data/exe/ruby-lsp-doctor
CHANGED
@@ -19,8 +19,5 @@ puts "Globbing for indexable files"
|
|
19
19
|
|
20
20
|
RubyIndexer.configuration.indexables.each do |indexable|
|
21
21
|
puts "indexing: #{indexable.full_path}"
|
22
|
-
|
23
|
-
result = Prism.parse(content)
|
24
|
-
collector = RubyIndexer::Collector.new(index, result, indexable.full_path)
|
25
|
-
collector.collect(result.value)
|
22
|
+
index.index_single(indexable)
|
26
23
|
end
|
data/lib/core_ext/uri.rb
CHANGED
@@ -11,6 +11,9 @@ module URI
|
|
11
11
|
# On Windows, if the path begins with the disk name, we need to add a leading slash to make it a valid URI
|
12
12
|
escaped_path = if /^[A-Z]:/i.match?(path)
|
13
13
|
DEFAULT_PARSER.escape("/#{path}")
|
14
|
+
elsif path.start_with?("//?/")
|
15
|
+
# Some paths on Windows start with "//?/". This is a special prefix that allows for long file paths
|
16
|
+
DEFAULT_PARSER.escape(path.delete_prefix("//?"))
|
14
17
|
else
|
15
18
|
DEFAULT_PARSER.escape(path)
|
16
19
|
end
|
@@ -2,79 +2,118 @@
|
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
module RubyIndexer
|
5
|
-
class
|
5
|
+
class DeclarationListener
|
6
6
|
extend T::Sig
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
def initialize(index, parse_result, file_path)
|
8
|
+
sig do
|
9
|
+
params(index: Index, dispatcher: Prism::Dispatcher, parse_result: Prism::ParseResult, file_path: String).void
|
10
|
+
end
|
11
|
+
def initialize(index, dispatcher, parse_result, file_path)
|
12
12
|
@index = index
|
13
13
|
@file_path = file_path
|
14
|
-
@
|
14
|
+
@visibility_stack = T.let([Entry::Visibility::PUBLIC], T::Array[Entry::Visibility])
|
15
15
|
@comments_by_line = T.let(
|
16
16
|
parse_result.comments.to_h do |c|
|
17
17
|
[c.location.start_line, c]
|
18
18
|
end,
|
19
19
|
T::Hash[Integer, Prism::Comment],
|
20
20
|
)
|
21
|
-
@
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
@stack.pop
|
70
|
-
end
|
21
|
+
@inside_def = T.let(false, T::Boolean)
|
22
|
+
|
23
|
+
# The nesting stack we're currently inside. Used to determine the fully qualified name of constants, but only
|
24
|
+
# stored by unresolved aliases which need the original nesting to be lazily resolved
|
25
|
+
@stack = T.let([], T::Array[String])
|
26
|
+
|
27
|
+
# A stack of namespace entries that represent where we currently are. Used to properly assign methods to an owner
|
28
|
+
@owner_stack = T.let([], T::Array[Entry::Namespace])
|
29
|
+
|
30
|
+
dispatcher.register(
|
31
|
+
self,
|
32
|
+
:on_class_node_enter,
|
33
|
+
:on_class_node_leave,
|
34
|
+
:on_module_node_enter,
|
35
|
+
:on_module_node_leave,
|
36
|
+
:on_def_node_enter,
|
37
|
+
:on_def_node_leave,
|
38
|
+
:on_call_node_enter,
|
39
|
+
:on_call_node_leave,
|
40
|
+
:on_multi_write_node_enter,
|
41
|
+
:on_constant_path_write_node_enter,
|
42
|
+
:on_constant_path_or_write_node_enter,
|
43
|
+
:on_constant_path_operator_write_node_enter,
|
44
|
+
:on_constant_path_and_write_node_enter,
|
45
|
+
:on_constant_or_write_node_enter,
|
46
|
+
:on_constant_write_node_enter,
|
47
|
+
:on_constant_or_write_node_enter,
|
48
|
+
:on_constant_and_write_node_enter,
|
49
|
+
:on_constant_operator_write_node_enter,
|
50
|
+
:on_instance_variable_write_node_enter,
|
51
|
+
:on_instance_variable_and_write_node_enter,
|
52
|
+
:on_instance_variable_operator_write_node_enter,
|
53
|
+
:on_instance_variable_or_write_node_enter,
|
54
|
+
:on_instance_variable_target_node_enter,
|
55
|
+
)
|
56
|
+
end
|
57
|
+
|
58
|
+
sig { params(node: Prism::ClassNode).void }
|
59
|
+
def on_class_node_enter(node)
|
60
|
+
@visibility_stack.push(Entry::Visibility::PUBLIC)
|
61
|
+
name = node.constant_path.location.slice
|
62
|
+
|
63
|
+
comments = collect_comments(node)
|
64
|
+
|
65
|
+
superclass = node.superclass
|
66
|
+
parent_class = case superclass
|
67
|
+
when Prism::ConstantReadNode, Prism::ConstantPathNode
|
68
|
+
superclass.slice
|
71
69
|
end
|
70
|
+
|
71
|
+
nesting = name.start_with?("::") ? [name.delete_prefix("::")] : @stack + [name.delete_prefix("::")]
|
72
|
+
|
73
|
+
entry = Entry::Class.new(
|
74
|
+
nesting,
|
75
|
+
@file_path,
|
76
|
+
node.location,
|
77
|
+
comments,
|
78
|
+
parent_class,
|
79
|
+
)
|
80
|
+
|
81
|
+
@owner_stack << entry
|
82
|
+
@index << entry
|
83
|
+
@stack << name
|
72
84
|
end
|
73
85
|
|
74
|
-
|
86
|
+
sig { params(node: Prism::ClassNode).void }
|
87
|
+
def on_class_node_leave(node)
|
88
|
+
@stack.pop
|
89
|
+
@owner_stack.pop
|
90
|
+
@visibility_stack.pop
|
91
|
+
end
|
92
|
+
|
93
|
+
sig { params(node: Prism::ModuleNode).void }
|
94
|
+
def on_module_node_enter(node)
|
95
|
+
@visibility_stack.push(Entry::Visibility::PUBLIC)
|
96
|
+
name = node.constant_path.location.slice
|
97
|
+
|
98
|
+
comments = collect_comments(node)
|
99
|
+
|
100
|
+
nesting = name.start_with?("::") ? [name.delete_prefix("::")] : @stack + [name.delete_prefix("::")]
|
101
|
+
entry = Entry::Module.new(nesting, @file_path, node.location, comments)
|
102
|
+
|
103
|
+
@owner_stack << entry
|
104
|
+
@index << entry
|
105
|
+
@stack << name
|
106
|
+
end
|
107
|
+
|
108
|
+
sig { params(node: Prism::ModuleNode).void }
|
109
|
+
def on_module_node_leave(node)
|
110
|
+
@stack.pop
|
111
|
+
@owner_stack.pop
|
112
|
+
@visibility_stack.pop
|
113
|
+
end
|
75
114
|
|
76
115
|
sig { params(node: Prism::MultiWriteNode).void }
|
77
|
-
def
|
116
|
+
def on_multi_write_node_enter(node)
|
78
117
|
value = node.value
|
79
118
|
values = value.is_a?(Prism::ArrayNode) && value.opening_loc ? value.elements : []
|
80
119
|
|
@@ -94,7 +133,7 @@ module RubyIndexer
|
|
94
133
|
end
|
95
134
|
|
96
135
|
sig { params(node: Prism::ConstantPathWriteNode).void }
|
97
|
-
def
|
136
|
+
def on_constant_path_write_node_enter(node)
|
98
137
|
# ignore variable constants like `var::FOO` or `self.class::FOO`
|
99
138
|
target = node.target
|
100
139
|
return unless target.parent.nil? || target.parent.is_a?(Prism::ConstantReadNode)
|
@@ -104,7 +143,7 @@ module RubyIndexer
|
|
104
143
|
end
|
105
144
|
|
106
145
|
sig { params(node: Prism::ConstantPathOrWriteNode).void }
|
107
|
-
def
|
146
|
+
def on_constant_path_or_write_node_enter(node)
|
108
147
|
# ignore variable constants like `var::FOO` or `self.class::FOO`
|
109
148
|
target = node.target
|
110
149
|
return unless target.parent.nil? || target.parent.is_a?(Prism::ConstantReadNode)
|
@@ -114,7 +153,7 @@ module RubyIndexer
|
|
114
153
|
end
|
115
154
|
|
116
155
|
sig { params(node: Prism::ConstantPathOperatorWriteNode).void }
|
117
|
-
def
|
156
|
+
def on_constant_path_operator_write_node_enter(node)
|
118
157
|
# ignore variable constants like `var::FOO` or `self.class::FOO`
|
119
158
|
target = node.target
|
120
159
|
return unless target.parent.nil? || target.parent.is_a?(Prism::ConstantReadNode)
|
@@ -124,7 +163,7 @@ module RubyIndexer
|
|
124
163
|
end
|
125
164
|
|
126
165
|
sig { params(node: Prism::ConstantPathAndWriteNode).void }
|
127
|
-
def
|
166
|
+
def on_constant_path_and_write_node_enter(node)
|
128
167
|
# ignore variable constants like `var::FOO` or `self.class::FOO`
|
129
168
|
target = node.target
|
130
169
|
return unless target.parent.nil? || target.parent.is_a?(Prism::ConstantReadNode)
|
@@ -134,13 +173,31 @@ module RubyIndexer
|
|
134
173
|
end
|
135
174
|
|
136
175
|
sig { params(node: Prism::ConstantWriteNode).void }
|
137
|
-
def
|
176
|
+
def on_constant_write_node_enter(node)
|
177
|
+
name = fully_qualify_name(node.name.to_s)
|
178
|
+
add_constant(node, name)
|
179
|
+
end
|
180
|
+
|
181
|
+
sig { params(node: Prism::ConstantOrWriteNode).void }
|
182
|
+
def on_constant_or_write_node_enter(node)
|
183
|
+
name = fully_qualify_name(node.name.to_s)
|
184
|
+
add_constant(node, name)
|
185
|
+
end
|
186
|
+
|
187
|
+
sig { params(node: Prism::ConstantAndWriteNode).void }
|
188
|
+
def on_constant_and_write_node_enter(node)
|
189
|
+
name = fully_qualify_name(node.name.to_s)
|
190
|
+
add_constant(node, name)
|
191
|
+
end
|
192
|
+
|
193
|
+
sig { params(node: Prism::ConstantOperatorWriteNode).void }
|
194
|
+
def on_constant_operator_write_node_enter(node)
|
138
195
|
name = fully_qualify_name(node.name.to_s)
|
139
196
|
add_constant(node, name)
|
140
197
|
end
|
141
198
|
|
142
199
|
sig { params(node: Prism::CallNode).void }
|
143
|
-
def
|
200
|
+
def on_call_node_enter(node)
|
144
201
|
message = node.name
|
145
202
|
|
146
203
|
case message
|
@@ -152,17 +209,36 @@ module RubyIndexer
|
|
152
209
|
handle_attribute(node, reader: false, writer: true)
|
153
210
|
when :attr_accessor
|
154
211
|
handle_attribute(node, reader: true, writer: true)
|
155
|
-
when :include
|
156
|
-
|
157
|
-
when :
|
158
|
-
|
212
|
+
when :include, :prepend, :extend
|
213
|
+
handle_module_operation(node, message)
|
214
|
+
when :public
|
215
|
+
@visibility_stack.push(Entry::Visibility::PUBLIC)
|
216
|
+
when :protected
|
217
|
+
@visibility_stack.push(Entry::Visibility::PROTECTED)
|
218
|
+
when :private
|
219
|
+
@visibility_stack.push(Entry::Visibility::PRIVATE)
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
sig { params(node: Prism::CallNode).void }
|
224
|
+
def on_call_node_leave(node)
|
225
|
+
message = node.name
|
226
|
+
case message
|
227
|
+
when :public, :protected, :private
|
228
|
+
# We want to restore the visibility stack when we leave a method definition with a visibility modifier
|
229
|
+
# e.g. `private def foo; end`
|
230
|
+
if node.arguments&.arguments&.first&.is_a?(Prism::DefNode)
|
231
|
+
@visibility_stack.pop
|
232
|
+
end
|
159
233
|
end
|
160
234
|
end
|
161
235
|
|
162
236
|
sig { params(node: Prism::DefNode).void }
|
163
|
-
def
|
237
|
+
def on_def_node_enter(node)
|
238
|
+
@inside_def = true
|
164
239
|
method_name = node.name.to_s
|
165
240
|
comments = collect_comments(node)
|
241
|
+
|
166
242
|
case node.receiver
|
167
243
|
when nil
|
168
244
|
@index << Entry::InstanceMethod.new(
|
@@ -171,7 +247,8 @@ module RubyIndexer
|
|
171
247
|
node.location,
|
172
248
|
comments,
|
173
249
|
node.parameters,
|
174
|
-
|
250
|
+
current_visibility,
|
251
|
+
@owner_stack.last,
|
175
252
|
)
|
176
253
|
when Prism::SelfNode
|
177
254
|
@index << Entry::SingletonMethod.new(
|
@@ -180,11 +257,89 @@ module RubyIndexer
|
|
180
257
|
node.location,
|
181
258
|
comments,
|
182
259
|
node.parameters,
|
183
|
-
|
260
|
+
current_visibility,
|
261
|
+
@owner_stack.last,
|
184
262
|
)
|
185
263
|
end
|
186
264
|
end
|
187
265
|
|
266
|
+
sig { params(node: Prism::DefNode).void }
|
267
|
+
def on_def_node_leave(node)
|
268
|
+
@inside_def = false
|
269
|
+
end
|
270
|
+
|
271
|
+
sig { params(node: Prism::InstanceVariableWriteNode).void }
|
272
|
+
def on_instance_variable_write_node_enter(node)
|
273
|
+
name = node.name.to_s
|
274
|
+
return if name == "@"
|
275
|
+
|
276
|
+
@index << Entry::InstanceVariable.new(
|
277
|
+
name,
|
278
|
+
@file_path,
|
279
|
+
node.name_loc,
|
280
|
+
collect_comments(node),
|
281
|
+
@owner_stack.last,
|
282
|
+
)
|
283
|
+
end
|
284
|
+
|
285
|
+
sig { params(node: Prism::InstanceVariableAndWriteNode).void }
|
286
|
+
def on_instance_variable_and_write_node_enter(node)
|
287
|
+
name = node.name.to_s
|
288
|
+
return if name == "@"
|
289
|
+
|
290
|
+
@index << Entry::InstanceVariable.new(
|
291
|
+
name,
|
292
|
+
@file_path,
|
293
|
+
node.name_loc,
|
294
|
+
collect_comments(node),
|
295
|
+
@owner_stack.last,
|
296
|
+
)
|
297
|
+
end
|
298
|
+
|
299
|
+
sig { params(node: Prism::InstanceVariableOperatorWriteNode).void }
|
300
|
+
def on_instance_variable_operator_write_node_enter(node)
|
301
|
+
name = node.name.to_s
|
302
|
+
return if name == "@"
|
303
|
+
|
304
|
+
@index << Entry::InstanceVariable.new(
|
305
|
+
name,
|
306
|
+
@file_path,
|
307
|
+
node.name_loc,
|
308
|
+
collect_comments(node),
|
309
|
+
@owner_stack.last,
|
310
|
+
)
|
311
|
+
end
|
312
|
+
|
313
|
+
sig { params(node: Prism::InstanceVariableOrWriteNode).void }
|
314
|
+
def on_instance_variable_or_write_node_enter(node)
|
315
|
+
name = node.name.to_s
|
316
|
+
return if name == "@"
|
317
|
+
|
318
|
+
@index << Entry::InstanceVariable.new(
|
319
|
+
name,
|
320
|
+
@file_path,
|
321
|
+
node.name_loc,
|
322
|
+
collect_comments(node),
|
323
|
+
@owner_stack.last,
|
324
|
+
)
|
325
|
+
end
|
326
|
+
|
327
|
+
sig { params(node: Prism::InstanceVariableTargetNode).void }
|
328
|
+
def on_instance_variable_target_node_enter(node)
|
329
|
+
name = node.name.to_s
|
330
|
+
return if name == "@"
|
331
|
+
|
332
|
+
@index << Entry::InstanceVariable.new(
|
333
|
+
name,
|
334
|
+
@file_path,
|
335
|
+
node.location,
|
336
|
+
collect_comments(node),
|
337
|
+
@owner_stack.last,
|
338
|
+
)
|
339
|
+
end
|
340
|
+
|
341
|
+
private
|
342
|
+
|
188
343
|
sig { params(node: Prism::CallNode).void }
|
189
344
|
def handle_private_constant(node)
|
190
345
|
arguments = node.arguments&.arguments
|
@@ -207,7 +362,7 @@ module RubyIndexer
|
|
207
362
|
# The private_constant method does not resolve the constant name. It always points to a constant that needs to
|
208
363
|
# exist in the current namespace
|
209
364
|
entries = @index[fully_qualify_name(name)]
|
210
|
-
entries&.each { |entry| entry.visibility =
|
365
|
+
entries&.each { |entry| entry.visibility = Entry::Visibility::PRIVATE }
|
211
366
|
end
|
212
367
|
|
213
368
|
sig do
|
@@ -240,62 +395,16 @@ module RubyIndexer
|
|
240
395
|
|
241
396
|
# If the right hand side is another constant assignment, we need to visit it because that constant has to be
|
242
397
|
# indexed too
|
243
|
-
@queue.prepend(value)
|
244
398
|
Entry::UnresolvedAlias.new(value.name.to_s, @stack.dup, name, @file_path, node.location, comments)
|
245
399
|
when Prism::ConstantPathWriteNode, Prism::ConstantPathOrWriteNode, Prism::ConstantPathOperatorWriteNode,
|
246
400
|
Prism::ConstantPathAndWriteNode
|
247
401
|
|
248
|
-
@queue.prepend(value)
|
249
402
|
Entry::UnresolvedAlias.new(value.target.slice, @stack.dup, name, @file_path, node.location, comments)
|
250
403
|
else
|
251
404
|
Entry::Constant.new(name, @file_path, node.location, comments)
|
252
405
|
end
|
253
406
|
end
|
254
407
|
|
255
|
-
sig { params(node: Prism::ModuleNode).void }
|
256
|
-
def add_module_entry(node)
|
257
|
-
name = node.constant_path.location.slice
|
258
|
-
unless /^[A-Z:]/.match?(name)
|
259
|
-
@queue << node.body
|
260
|
-
return
|
261
|
-
end
|
262
|
-
|
263
|
-
comments = collect_comments(node)
|
264
|
-
@current_owner = Entry::Module.new(fully_qualify_name(name), @file_path, node.location, comments)
|
265
|
-
@index << @current_owner
|
266
|
-
@stack << name
|
267
|
-
@queue.prepend(node.body, LEAVE_EVENT)
|
268
|
-
end
|
269
|
-
|
270
|
-
sig { params(node: Prism::ClassNode).void }
|
271
|
-
def add_class_entry(node)
|
272
|
-
name = node.constant_path.location.slice
|
273
|
-
|
274
|
-
unless /^[A-Z:]/.match?(name)
|
275
|
-
@queue << node.body
|
276
|
-
return
|
277
|
-
end
|
278
|
-
|
279
|
-
comments = collect_comments(node)
|
280
|
-
|
281
|
-
superclass = node.superclass
|
282
|
-
parent_class = case superclass
|
283
|
-
when Prism::ConstantReadNode, Prism::ConstantPathNode
|
284
|
-
superclass.slice
|
285
|
-
end
|
286
|
-
|
287
|
-
@current_owner = Entry::Class.new(
|
288
|
-
fully_qualify_name(name),
|
289
|
-
@file_path,
|
290
|
-
node.location,
|
291
|
-
comments,
|
292
|
-
parent_class,
|
293
|
-
)
|
294
|
-
@index << @current_owner
|
295
|
-
@stack << name
|
296
|
-
@queue.prepend(node.body, LEAVE_EVENT)
|
297
|
-
end
|
298
|
-
|
299
408
|
sig { params(node: Prism::Node).returns(T::Array[String]) }
|
300
409
|
def collect_comments(node)
|
301
410
|
comments = []
|
@@ -350,39 +459,48 @@ module RubyIndexer
|
|
350
459
|
|
351
460
|
next unless name && loc
|
352
461
|
|
353
|
-
@index << Entry::Accessor.new(name, @file_path, loc, comments, @
|
354
|
-
@index << Entry::Accessor.new(
|
462
|
+
@index << Entry::Accessor.new(name, @file_path, loc, comments, current_visibility, @owner_stack.last) if reader
|
463
|
+
@index << Entry::Accessor.new(
|
464
|
+
"#{name}=",
|
465
|
+
@file_path,
|
466
|
+
loc,
|
467
|
+
comments,
|
468
|
+
current_visibility,
|
469
|
+
@owner_stack.last,
|
470
|
+
) if writer
|
355
471
|
end
|
356
472
|
end
|
357
473
|
|
358
|
-
sig { params(node: Prism::CallNode).void }
|
359
|
-
def handle_include(node)
|
360
|
-
handle_module_operation(node, :included_modules)
|
361
|
-
end
|
362
|
-
|
363
|
-
sig { params(node: Prism::CallNode).void }
|
364
|
-
def handle_prepend(node)
|
365
|
-
handle_module_operation(node, :prepended_modules)
|
366
|
-
end
|
367
|
-
|
368
474
|
sig { params(node: Prism::CallNode, operation: Symbol).void }
|
369
475
|
def handle_module_operation(node, operation)
|
370
|
-
return
|
476
|
+
return if @inside_def
|
477
|
+
|
478
|
+
owner = @owner_stack.last
|
479
|
+
return unless owner
|
371
480
|
|
372
481
|
arguments = node.arguments&.arguments
|
373
482
|
return unless arguments
|
374
483
|
|
375
|
-
|
376
|
-
|
377
|
-
|
484
|
+
arguments.each do |node|
|
485
|
+
next unless node.is_a?(Prism::ConstantReadNode) || node.is_a?(Prism::ConstantPathNode)
|
486
|
+
|
487
|
+
case operation
|
488
|
+
when :include
|
489
|
+
owner.mixin_operations << Entry::Include.new(node.full_name)
|
490
|
+
when :prepend
|
491
|
+
owner.mixin_operations << Entry::Prepend.new(node.full_name)
|
492
|
+
when :extend
|
493
|
+
owner.mixin_operations << Entry::Extend.new(node.full_name)
|
378
494
|
end
|
379
|
-
rescue Prism::ConstantPathNode::DynamicPartsInConstantPathError
|
380
|
-
|
381
|
-
#
|
382
|
-
# index it
|
495
|
+
rescue Prism::ConstantPathNode::DynamicPartsInConstantPathError,
|
496
|
+
Prism::ConstantPathNode::MissingNodesInConstantPathError
|
497
|
+
# Do nothing
|
383
498
|
end
|
384
|
-
|
385
|
-
|
499
|
+
end
|
500
|
+
|
501
|
+
sig { returns(Entry::Visibility) }
|
502
|
+
def current_visibility
|
503
|
+
T.must(@visibility_stack.last)
|
386
504
|
end
|
387
505
|
end
|
388
506
|
end
|