ruby-lsp 0.21.0 → 0.22.1
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/VERSION +1 -1
- data/exe/ruby-lsp +1 -1
- data/exe/ruby-lsp-launcher +0 -3
- data/lib/ruby_indexer/lib/ruby_indexer/configuration.rb +6 -0
- data/lib/ruby_indexer/lib/ruby_indexer/declaration_listener.rb +179 -59
- data/lib/ruby_indexer/lib/ruby_indexer/enhancement.rb +31 -28
- data/lib/ruby_indexer/lib/ruby_indexer/index.rb +10 -10
- data/lib/ruby_indexer/test/classes_and_modules_test.rb +2 -2
- data/lib/ruby_indexer/test/configuration_test.rb +10 -0
- data/lib/ruby_indexer/test/constant_test.rb +8 -8
- data/lib/ruby_indexer/test/enhancements_test.rb +134 -38
- data/lib/ruby_indexer/test/index_test.rb +39 -0
- data/lib/ruby_indexer/test/method_test.rb +114 -1
- data/lib/ruby_lsp/client_capabilities.rb +8 -1
- data/lib/ruby_lsp/global_state.rb +15 -3
- data/lib/ruby_lsp/internal.rb +1 -0
- data/lib/ruby_lsp/listeners/document_highlight.rb +91 -4
- data/lib/ruby_lsp/listeners/document_symbol.rb +37 -4
- data/lib/ruby_lsp/requests/definition.rb +2 -0
- data/lib/ruby_lsp/requests/document_highlight.rb +7 -1
- data/lib/ruby_lsp/requests/hover.rb +2 -0
- data/lib/ruby_lsp/requests/support/rubocop_runner.rb +1 -0
- data/lib/ruby_lsp/server.rb +35 -43
- data/lib/ruby_lsp/setup_bundler.rb +46 -25
- data/lib/ruby_lsp/store.rb +0 -4
- data/lib/ruby_lsp/utils.rb +55 -0
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: efd5671eae595026a17c3114a00de1053865ac828726dd7ac5a66548f6b1ad56
|
4
|
+
data.tar.gz: ccf5b7af12a6e1e327cc2d458be11f39a9ac7319ab9049863ed5a74e333e8a6f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8fbcdfaac508788a17fb3b7e939ce290e33049a0080ff6260abfaeb609ee76a033234ccc2efa5724587e9c4cbf4552e2cd5d2cb0af1186971b8ed06fec290cb3
|
7
|
+
data.tar.gz: 3e37acf250618e60df2addbce7f9acf86df4bf3e771b7b49c4cd8f4ad326ea82e3d41ad80c5ce71e3b0429dab98385df51f4645824cd419e32dac5ea13778760
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.22.1
|
data/exe/ruby-lsp
CHANGED
@@ -54,7 +54,7 @@ rescue OptionParser::InvalidOption => e
|
|
54
54
|
exit(1)
|
55
55
|
end
|
56
56
|
|
57
|
-
# When we're running without bundler, then we need to make sure the
|
57
|
+
# When we're running without bundler, then we need to make sure the composed bundle is fully configured and re-execute
|
58
58
|
# using `BUNDLE_GEMFILE=.ruby-lsp/Gemfile bundle exec ruby-lsp` so that we have access to the gems that are a part of
|
59
59
|
# the application's bundle
|
60
60
|
if ENV["BUNDLE_GEMFILE"].nil?
|
data/exe/ruby-lsp-launcher
CHANGED
@@ -74,9 +74,6 @@ rescue StandardError => e
|
|
74
74
|
# If Bundler.setup fails, we need to restore the original $LOAD_PATH so that we can still require the Ruby LSP server
|
75
75
|
# in degraded mode
|
76
76
|
$LOAD_PATH.unshift(File.expand_path("../lib", __dir__))
|
77
|
-
ensure
|
78
|
-
require "fileutils"
|
79
|
-
FileUtils.rm(bundle_env_path) if File.exist?(bundle_env_path)
|
80
77
|
end
|
81
78
|
|
82
79
|
error_path = File.join(".ruby-lsp", "install_error")
|
@@ -109,6 +109,12 @@ module RubyIndexer
|
|
109
109
|
|
110
110
|
indexables = T.let([], T::Array[IndexablePath])
|
111
111
|
|
112
|
+
# Handle top level files separately. The path below is an optimization to prevent descending down directories that
|
113
|
+
# are going to be excluded anyway, so we need to handle top level scripts separately
|
114
|
+
Dir.glob(File.join(@workspace_path, "*.rb"), flags).each do |path|
|
115
|
+
indexables << IndexablePath.new(nil, path)
|
116
|
+
end
|
117
|
+
|
112
118
|
# Add user specified patterns
|
113
119
|
@included_patterns.each do |pattern|
|
114
120
|
load_path_entry = T.let(nil, T.nilable(String))
|
@@ -18,13 +18,12 @@ module RubyIndexer
|
|
18
18
|
parse_result: Prism::ParseResult,
|
19
19
|
file_path: String,
|
20
20
|
collect_comments: T::Boolean,
|
21
|
-
enhancements: T::Array[Enhancement],
|
22
21
|
).void
|
23
22
|
end
|
24
|
-
def initialize(index, dispatcher, parse_result, file_path, collect_comments: false
|
23
|
+
def initialize(index, dispatcher, parse_result, file_path, collect_comments: false)
|
25
24
|
@index = index
|
26
25
|
@file_path = file_path
|
27
|
-
@enhancements =
|
26
|
+
@enhancements = T.let(Enhancement.all(self), T::Array[Enhancement])
|
28
27
|
@visibility_stack = T.let([Entry::Visibility::PUBLIC], T::Array[Entry::Visibility])
|
29
28
|
@comments_by_line = T.let(
|
30
29
|
parse_result.comments.to_h do |c|
|
@@ -37,6 +36,7 @@ module RubyIndexer
|
|
37
36
|
parse_result.code_units_cache(@index.configuration.encoding),
|
38
37
|
T.any(T.proc.params(arg0: Integer).returns(Integer), Prism::CodeUnitsCache),
|
39
38
|
)
|
39
|
+
@source_lines = T.let(parse_result.source.lines, T::Array[String])
|
40
40
|
|
41
41
|
# The nesting stack we're currently inside. Used to determine the fully qualified name of constants, but only
|
42
42
|
# stored by unresolved aliases which need the original nesting to be lazily resolved
|
@@ -85,15 +85,9 @@ module RubyIndexer
|
|
85
85
|
|
86
86
|
sig { params(node: Prism::ClassNode).void }
|
87
87
|
def on_class_node_enter(node)
|
88
|
-
@visibility_stack.push(Entry::Visibility::PUBLIC)
|
89
88
|
constant_path = node.constant_path
|
90
|
-
name = constant_path.slice
|
91
|
-
|
92
|
-
comments = collect_comments(node)
|
93
|
-
|
94
89
|
superclass = node.superclass
|
95
|
-
|
96
|
-
nesting = actual_nesting(name)
|
90
|
+
nesting = actual_nesting(constant_path.slice)
|
97
91
|
|
98
92
|
parent_class = case superclass
|
99
93
|
when Prism::ConstantReadNode, Prism::ConstantPathNode
|
@@ -112,53 +106,29 @@ module RubyIndexer
|
|
112
106
|
end
|
113
107
|
end
|
114
108
|
|
115
|
-
|
109
|
+
add_class(
|
116
110
|
nesting,
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
comments,
|
121
|
-
parent_class,
|
111
|
+
node.location,
|
112
|
+
constant_path.location,
|
113
|
+
parent_class_name: parent_class,
|
114
|
+
comments: collect_comments(node),
|
122
115
|
)
|
123
|
-
|
124
|
-
@owner_stack << entry
|
125
|
-
@index.add(entry)
|
126
|
-
@stack << name
|
127
116
|
end
|
128
117
|
|
129
118
|
sig { params(node: Prism::ClassNode).void }
|
130
119
|
def on_class_node_leave(node)
|
131
|
-
|
132
|
-
@owner_stack.pop
|
133
|
-
@visibility_stack.pop
|
120
|
+
pop_namespace_stack
|
134
121
|
end
|
135
122
|
|
136
123
|
sig { params(node: Prism::ModuleNode).void }
|
137
124
|
def on_module_node_enter(node)
|
138
|
-
@visibility_stack.push(Entry::Visibility::PUBLIC)
|
139
125
|
constant_path = node.constant_path
|
140
|
-
|
141
|
-
|
142
|
-
comments = collect_comments(node)
|
143
|
-
|
144
|
-
entry = Entry::Module.new(
|
145
|
-
actual_nesting(name),
|
146
|
-
@file_path,
|
147
|
-
Location.from_prism_location(node.location, @code_units_cache),
|
148
|
-
Location.from_prism_location(constant_path.location, @code_units_cache),
|
149
|
-
comments,
|
150
|
-
)
|
151
|
-
|
152
|
-
@owner_stack << entry
|
153
|
-
@index.add(entry)
|
154
|
-
@stack << name
|
126
|
+
add_module(constant_path.slice, node.location, constant_path.location, comments: collect_comments(node))
|
155
127
|
end
|
156
128
|
|
157
129
|
sig { params(node: Prism::ModuleNode).void }
|
158
130
|
def on_module_node_leave(node)
|
159
|
-
|
160
|
-
@owner_stack.pop
|
161
|
-
@visibility_stack.pop
|
131
|
+
pop_namespace_stack
|
162
132
|
end
|
163
133
|
|
164
134
|
sig { params(node: Prism::SingletonClassNode).void }
|
@@ -200,9 +170,7 @@ module RubyIndexer
|
|
200
170
|
|
201
171
|
sig { params(node: Prism::SingletonClassNode).void }
|
202
172
|
def on_singleton_class_node_leave(node)
|
203
|
-
|
204
|
-
@owner_stack.pop
|
205
|
-
@visibility_stack.pop
|
173
|
+
pop_namespace_stack
|
206
174
|
end
|
207
175
|
|
208
176
|
sig { params(node: Prism::MultiWriteNode).void }
|
@@ -314,10 +282,13 @@ module RubyIndexer
|
|
314
282
|
@visibility_stack.push(Entry::Visibility::PRIVATE)
|
315
283
|
when :module_function
|
316
284
|
handle_module_function(node)
|
285
|
+
when :private_class_method
|
286
|
+
@visibility_stack.push(Entry::Visibility::PRIVATE)
|
287
|
+
handle_private_class_method(node)
|
317
288
|
end
|
318
289
|
|
319
290
|
@enhancements.each do |enhancement|
|
320
|
-
enhancement.on_call_node_enter(
|
291
|
+
enhancement.on_call_node_enter(node)
|
321
292
|
rescue StandardError => e
|
322
293
|
@indexing_errors << <<~MSG
|
323
294
|
Indexing error in #{@file_path} with '#{enhancement.class.name}' on call node enter enhancement: #{e.message}
|
@@ -329,7 +300,7 @@ module RubyIndexer
|
|
329
300
|
def on_call_node_leave(node)
|
330
301
|
message = node.name
|
331
302
|
case message
|
332
|
-
when :public, :protected, :private
|
303
|
+
when :public, :protected, :private, :private_class_method
|
333
304
|
# We want to restore the visibility stack when we leave a method definition with a visibility modifier
|
334
305
|
# e.g. `private def foo; end`
|
335
306
|
if node.arguments&.arguments&.first&.is_a?(Prism::DefNode)
|
@@ -338,7 +309,7 @@ module RubyIndexer
|
|
338
309
|
end
|
339
310
|
|
340
311
|
@enhancements.each do |enhancement|
|
341
|
-
enhancement.on_call_node_leave(
|
312
|
+
enhancement.on_call_node_leave(node)
|
342
313
|
rescue StandardError => e
|
343
314
|
@indexing_errors << <<~MSG
|
344
315
|
Indexing error in #{@file_path} with '#{enhancement.class.name}' on call node leave enhancement: #{e.message}
|
@@ -463,6 +434,98 @@ module RubyIndexer
|
|
463
434
|
)
|
464
435
|
end
|
465
436
|
|
437
|
+
sig do
|
438
|
+
params(
|
439
|
+
name: String,
|
440
|
+
node_location: Prism::Location,
|
441
|
+
signatures: T::Array[Entry::Signature],
|
442
|
+
visibility: Entry::Visibility,
|
443
|
+
comments: T.nilable(String),
|
444
|
+
).void
|
445
|
+
end
|
446
|
+
def add_method(name, node_location, signatures, visibility: Entry::Visibility::PUBLIC, comments: nil)
|
447
|
+
location = Location.from_prism_location(node_location, @code_units_cache)
|
448
|
+
|
449
|
+
@index.add(Entry::Method.new(
|
450
|
+
name,
|
451
|
+
@file_path,
|
452
|
+
location,
|
453
|
+
location,
|
454
|
+
comments,
|
455
|
+
signatures,
|
456
|
+
visibility,
|
457
|
+
@owner_stack.last,
|
458
|
+
))
|
459
|
+
end
|
460
|
+
|
461
|
+
sig do
|
462
|
+
params(
|
463
|
+
name: String,
|
464
|
+
full_location: Prism::Location,
|
465
|
+
name_location: Prism::Location,
|
466
|
+
comments: T.nilable(String),
|
467
|
+
).void
|
468
|
+
end
|
469
|
+
def add_module(name, full_location, name_location, comments: nil)
|
470
|
+
location = Location.from_prism_location(full_location, @code_units_cache)
|
471
|
+
name_loc = Location.from_prism_location(name_location, @code_units_cache)
|
472
|
+
|
473
|
+
entry = Entry::Module.new(
|
474
|
+
actual_nesting(name),
|
475
|
+
@file_path,
|
476
|
+
location,
|
477
|
+
name_loc,
|
478
|
+
comments,
|
479
|
+
)
|
480
|
+
|
481
|
+
advance_namespace_stack(name, entry)
|
482
|
+
end
|
483
|
+
|
484
|
+
sig do
|
485
|
+
params(
|
486
|
+
name_or_nesting: T.any(String, T::Array[String]),
|
487
|
+
full_location: Prism::Location,
|
488
|
+
name_location: Prism::Location,
|
489
|
+
parent_class_name: T.nilable(String),
|
490
|
+
comments: T.nilable(String),
|
491
|
+
).void
|
492
|
+
end
|
493
|
+
def add_class(name_or_nesting, full_location, name_location, parent_class_name: nil, comments: nil)
|
494
|
+
nesting = name_or_nesting.is_a?(Array) ? name_or_nesting : actual_nesting(name_or_nesting)
|
495
|
+
entry = Entry::Class.new(
|
496
|
+
nesting,
|
497
|
+
@file_path,
|
498
|
+
Location.from_prism_location(full_location, @code_units_cache),
|
499
|
+
Location.from_prism_location(name_location, @code_units_cache),
|
500
|
+
comments,
|
501
|
+
parent_class_name,
|
502
|
+
)
|
503
|
+
|
504
|
+
advance_namespace_stack(T.must(nesting.last), entry)
|
505
|
+
end
|
506
|
+
|
507
|
+
sig { params(block: T.proc.params(index: Index, base: Entry::Namespace).void).void }
|
508
|
+
def register_included_hook(&block)
|
509
|
+
owner = @owner_stack.last
|
510
|
+
return unless owner
|
511
|
+
|
512
|
+
@index.register_included_hook(owner.name) do |index, base|
|
513
|
+
block.call(index, base)
|
514
|
+
end
|
515
|
+
end
|
516
|
+
|
517
|
+
sig { void }
|
518
|
+
def pop_namespace_stack
|
519
|
+
@stack.pop
|
520
|
+
@owner_stack.pop
|
521
|
+
@visibility_stack.pop
|
522
|
+
end
|
523
|
+
|
524
|
+
sig { returns(T.nilable(Entry::Namespace)) }
|
525
|
+
def current_owner
|
526
|
+
@owner_stack.last
|
527
|
+
end
|
528
|
+
|
466
529
|
private
|
467
530
|
|
468
531
|
sig do
|
@@ -661,8 +724,7 @@ module RubyIndexer
|
|
661
724
|
comments = +""
|
662
725
|
|
663
726
|
start_line = node.location.start_line - 1
|
664
|
-
start_line -= 1 unless
|
665
|
-
|
727
|
+
start_line -= 1 unless comment_exists_at?(start_line)
|
666
728
|
start_line.downto(1) do |line|
|
667
729
|
comment = @comments_by_line[line]
|
668
730
|
break unless comment
|
@@ -683,6 +745,11 @@ module RubyIndexer
|
|
683
745
|
comments
|
684
746
|
end
|
685
747
|
|
748
|
+
sig { params(line: Integer).returns(T::Boolean) }
|
749
|
+
def comment_exists_at?(line)
|
750
|
+
@comments_by_line.key?(line) || !@source_lines[line - 1].to_s.strip.empty?
|
751
|
+
end
|
752
|
+
|
686
753
|
sig { params(name: String).returns(String) }
|
687
754
|
def fully_qualify_name(name)
|
688
755
|
if @stack.empty? || name.start_with?("::")
|
@@ -746,16 +813,22 @@ module RubyIndexer
|
|
746
813
|
return unless arguments
|
747
814
|
|
748
815
|
arguments.each do |node|
|
749
|
-
next unless node.is_a?(Prism::ConstantReadNode) || node.is_a?(Prism::ConstantPathNode)
|
750
|
-
|
751
|
-
|
752
|
-
|
753
|
-
owner.mixin_operations << Entry::Include.new(node.full_name)
|
754
|
-
when :prepend
|
755
|
-
owner.mixin_operations << Entry::Prepend.new(node.full_name)
|
756
|
-
when :extend
|
816
|
+
next unless node.is_a?(Prism::ConstantReadNode) || node.is_a?(Prism::ConstantPathNode) ||
|
817
|
+
(node.is_a?(Prism::SelfNode) && operation == :extend)
|
818
|
+
|
819
|
+
if node.is_a?(Prism::SelfNode)
|
757
820
|
singleton = @index.existing_or_new_singleton_class(owner.name)
|
758
|
-
singleton.mixin_operations << Entry::Include.new(
|
821
|
+
singleton.mixin_operations << Entry::Include.new(owner.name)
|
822
|
+
else
|
823
|
+
case operation
|
824
|
+
when :include
|
825
|
+
owner.mixin_operations << Entry::Include.new(node.full_name)
|
826
|
+
when :prepend
|
827
|
+
owner.mixin_operations << Entry::Prepend.new(node.full_name)
|
828
|
+
when :extend
|
829
|
+
singleton = @index.existing_or_new_singleton_class(owner.name)
|
830
|
+
singleton.mixin_operations << Entry::Include.new(node.full_name)
|
831
|
+
end
|
759
832
|
end
|
760
833
|
rescue Prism::ConstantPathNode::DynamicPartsInConstantPathError,
|
761
834
|
Prism::ConstantPathNode::MissingNodesInConstantPathError
|
@@ -805,6 +878,45 @@ module RubyIndexer
|
|
805
878
|
end
|
806
879
|
end
|
807
880
|
|
881
|
+
sig { params(node: Prism::CallNode).void }
|
882
|
+
def handle_private_class_method(node)
|
883
|
+
node.arguments&.arguments&.each do |argument|
|
884
|
+
string_or_symbol_nodes = case argument
|
885
|
+
when Prism::StringNode, Prism::SymbolNode
|
886
|
+
[argument]
|
887
|
+
when Prism::ArrayNode
|
888
|
+
argument.elements
|
889
|
+
else
|
890
|
+
[]
|
891
|
+
end
|
892
|
+
|
893
|
+
unless string_or_symbol_nodes.empty?
|
894
|
+
# pop the visibility off since there isn't a method definition following `private_class_method`
|
895
|
+
@visibility_stack.pop
|
896
|
+
end
|
897
|
+
|
898
|
+
string_or_symbol_nodes.each do |string_or_symbol_node|
|
899
|
+
method_name = case string_or_symbol_node
|
900
|
+
when Prism::StringNode
|
901
|
+
string_or_symbol_node.content
|
902
|
+
when Prism::SymbolNode
|
903
|
+
string_or_symbol_node.value
|
904
|
+
end
|
905
|
+
next unless method_name
|
906
|
+
|
907
|
+
owner_name = @owner_stack.last&.name
|
908
|
+
next unless owner_name
|
909
|
+
|
910
|
+
entries = @index.resolve_method(method_name, @index.existing_or_new_singleton_class(owner_name).name)
|
911
|
+
next unless entries
|
912
|
+
|
913
|
+
entries.each do |entry|
|
914
|
+
entry.visibility = Entry::Visibility::PRIVATE
|
915
|
+
end
|
916
|
+
end
|
917
|
+
end
|
918
|
+
end
|
919
|
+
|
808
920
|
sig { returns(Entry::Visibility) }
|
809
921
|
def current_visibility
|
810
922
|
T.must(@visibility_stack.last)
|
@@ -910,5 +1022,13 @@ module RubyIndexer
|
|
910
1022
|
|
911
1023
|
corrected_nesting
|
912
1024
|
end
|
1025
|
+
|
1026
|
+
sig { params(short_name: String, entry: Entry::Namespace).void }
|
1027
|
+
def advance_namespace_stack(short_name, entry)
|
1028
|
+
@visibility_stack.push(Entry::Visibility::PUBLIC)
|
1029
|
+
@owner_stack << entry
|
1030
|
+
@index.add(entry)
|
1031
|
+
@stack << short_name
|
1032
|
+
end
|
913
1033
|
end
|
914
1034
|
end
|
@@ -8,38 +8,41 @@ module RubyIndexer
|
|
8
8
|
|
9
9
|
abstract!
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
|
11
|
+
@enhancements = T.let([], T::Array[T::Class[Enhancement]])
|
12
|
+
|
13
|
+
class << self
|
14
|
+
extend T::Sig
|
15
|
+
|
16
|
+
sig { params(child: T::Class[Enhancement]).void }
|
17
|
+
def inherited(child)
|
18
|
+
@enhancements << child
|
19
|
+
super
|
20
|
+
end
|
21
|
+
|
22
|
+
sig { params(listener: DeclarationListener).returns(T::Array[Enhancement]) }
|
23
|
+
def all(listener)
|
24
|
+
@enhancements.map { |enhancement| enhancement.new(listener) }
|
25
|
+
end
|
26
|
+
|
27
|
+
# Only available for testing purposes
|
28
|
+
sig { void }
|
29
|
+
def clear
|
30
|
+
@enhancements.clear
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
sig { params(listener: DeclarationListener).void }
|
35
|
+
def initialize(listener)
|
36
|
+
@listener = listener
|
14
37
|
end
|
15
38
|
|
16
39
|
# The `on_extend` indexing enhancement is invoked whenever an extend is encountered in the code. It can be used to
|
17
40
|
# register for an included callback, similar to what `ActiveSupport::Concern` does in order to auto-extend the
|
18
41
|
# `ClassMethods` modules
|
19
|
-
sig
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
code_units_cache: T.any(
|
25
|
-
T.proc.params(arg0: Integer).returns(Integer),
|
26
|
-
Prism::CodeUnitsCache,
|
27
|
-
),
|
28
|
-
).void
|
29
|
-
end
|
30
|
-
def on_call_node_enter(owner, node, file_path, code_units_cache); end
|
31
|
-
|
32
|
-
sig do
|
33
|
-
overridable.params(
|
34
|
-
owner: T.nilable(Entry::Namespace),
|
35
|
-
node: Prism::CallNode,
|
36
|
-
file_path: String,
|
37
|
-
code_units_cache: T.any(
|
38
|
-
T.proc.params(arg0: Integer).returns(Integer),
|
39
|
-
Prism::CodeUnitsCache,
|
40
|
-
),
|
41
|
-
).void
|
42
|
-
end
|
43
|
-
def on_call_node_leave(owner, node, file_path, code_units_cache); end
|
42
|
+
sig { overridable.params(node: Prism::CallNode).void }
|
43
|
+
def on_call_node_enter(node); end # rubocop:disable RubyLsp/UseRegisterWithHandlerMethod
|
44
|
+
|
45
|
+
sig { overridable.params(node: Prism::CallNode).void }
|
46
|
+
def on_call_node_leave(node); end # rubocop:disable RubyLsp/UseRegisterWithHandlerMethod
|
44
47
|
end
|
45
48
|
end
|
@@ -7,6 +7,7 @@ module RubyIndexer
|
|
7
7
|
|
8
8
|
class UnresolvableAliasError < StandardError; end
|
9
9
|
class NonExistingNamespaceError < StandardError; end
|
10
|
+
class IndexNotEmptyError < StandardError; end
|
10
11
|
|
11
12
|
# The minimum Jaro-Winkler similarity score for an entry to be considered a match for a given fuzzy search query
|
12
13
|
ENTRY_SIMILARITY_THRESHOLD = 0.7
|
@@ -39,9 +40,6 @@ module RubyIndexer
|
|
39
40
|
# Holds the linearized ancestors list for every namespace
|
40
41
|
@ancestors = T.let({}, T::Hash[String, T::Array[String]])
|
41
42
|
|
42
|
-
# List of classes that are enhancing the index
|
43
|
-
@enhancements = T.let([], T::Array[Enhancement])
|
44
|
-
|
45
43
|
# Map of module name to included hooks that have to be executed when we include the given module
|
46
44
|
@included_hooks = T.let(
|
47
45
|
{},
|
@@ -51,12 +49,6 @@ module RubyIndexer
|
|
51
49
|
@configuration = T.let(RubyIndexer::Configuration.new, Configuration)
|
52
50
|
end
|
53
51
|
|
54
|
-
# Register an enhancement to the index. Enhancements must conform to the `Enhancement` interface
|
55
|
-
sig { params(enhancement: Enhancement).void }
|
56
|
-
def register_enhancement(enhancement)
|
57
|
-
@enhancements << enhancement
|
58
|
-
end
|
59
|
-
|
60
52
|
# Register an included `hook` that will be executed when `module_name` is included into any namespace
|
61
53
|
sig { params(module_name: String, hook: T.proc.params(index: Index, base: Entry::Namespace).void).void }
|
62
54
|
def register_included_hook(module_name, &hook)
|
@@ -360,6 +352,15 @@ module RubyIndexer
|
|
360
352
|
).void
|
361
353
|
end
|
362
354
|
def index_all(indexable_paths: @configuration.indexables, &block)
|
355
|
+
# When troubleshooting an indexing issue, e.g. through irb, it's not obvious that `index_all` will augment the
|
356
|
+
# existing index values, meaning it may contain 'stale' entries. This check ensures that the user is aware of this
|
357
|
+
# behavior and can take appropriate action.
|
358
|
+
# binding.break
|
359
|
+
if @entries.any?
|
360
|
+
raise IndexNotEmptyError,
|
361
|
+
"The index is not empty. To prevent invalid entries, `index_all` can only be called once."
|
362
|
+
end
|
363
|
+
|
363
364
|
RBSIndexer.new(self).index_ruby_core
|
364
365
|
# Calculate how many paths are worth 1% of progress
|
365
366
|
progress_step = (indexable_paths.length / 100.0).ceil
|
@@ -386,7 +387,6 @@ module RubyIndexer
|
|
386
387
|
result,
|
387
388
|
indexable_path.full_path,
|
388
389
|
collect_comments: collect_comments,
|
389
|
-
enhancements: @enhancements,
|
390
390
|
)
|
391
391
|
dispatcher.dispatch(result.value)
|
392
392
|
|
@@ -302,10 +302,10 @@ module RubyIndexer
|
|
302
302
|
RUBY
|
303
303
|
|
304
304
|
b_const = @index["A::B"].first
|
305
|
-
|
305
|
+
assert_predicate(b_const, :private?)
|
306
306
|
|
307
307
|
c_const = @index["A::C"].first
|
308
|
-
|
308
|
+
assert_predicate(c_const, :private?)
|
309
309
|
|
310
310
|
d_const = @index["A::D"].first
|
311
311
|
assert_equal(Entry::Visibility::PUBLIC, d_const.visibility)
|
@@ -160,5 +160,15 @@ module RubyIndexer
|
|
160
160
|
)
|
161
161
|
end
|
162
162
|
end
|
163
|
+
|
164
|
+
def test_includes_top_level_files
|
165
|
+
Dir.mktmpdir do |dir|
|
166
|
+
FileUtils.touch(File.join(dir, "find_me.rb"))
|
167
|
+
@config.workspace_path = dir
|
168
|
+
|
169
|
+
indexables = @config.indexables
|
170
|
+
assert(indexables.find { |i| File.basename(i.full_path) == "find_me.rb" })
|
171
|
+
end
|
172
|
+
end
|
163
173
|
end
|
164
174
|
end
|
@@ -130,13 +130,13 @@ module RubyIndexer
|
|
130
130
|
RUBY
|
131
131
|
|
132
132
|
b_const = @index["A::B"].first
|
133
|
-
|
133
|
+
assert_predicate(b_const, :private?)
|
134
134
|
|
135
135
|
c_const = @index["A::C"].first
|
136
|
-
|
136
|
+
assert_predicate(c_const, :private?)
|
137
137
|
|
138
138
|
d_const = @index["A::D"].first
|
139
|
-
|
139
|
+
assert_predicate(d_const, :public?)
|
140
140
|
end
|
141
141
|
|
142
142
|
def test_marking_constants_as_private_reopening_namespaces
|
@@ -163,13 +163,13 @@ module RubyIndexer
|
|
163
163
|
RUBY
|
164
164
|
|
165
165
|
a_const = @index["A::B::CONST_A"].first
|
166
|
-
|
166
|
+
assert_predicate(a_const, :private?)
|
167
167
|
|
168
168
|
b_const = @index["A::B::CONST_B"].first
|
169
|
-
|
169
|
+
assert_predicate(b_const, :private?)
|
170
170
|
|
171
171
|
c_const = @index["A::B::CONST_C"].first
|
172
|
-
|
172
|
+
assert_predicate(c_const, :private?)
|
173
173
|
end
|
174
174
|
|
175
175
|
def test_marking_constants_as_private_with_receiver
|
@@ -187,10 +187,10 @@ module RubyIndexer
|
|
187
187
|
RUBY
|
188
188
|
|
189
189
|
a_const = @index["A::B::CONST_A"].first
|
190
|
-
|
190
|
+
assert_predicate(a_const, :private?)
|
191
191
|
|
192
192
|
b_const = @index["A::B::CONST_B"].first
|
193
|
-
|
193
|
+
assert_predicate(b_const, :private?)
|
194
194
|
end
|
195
195
|
|
196
196
|
def test_indexing_constant_aliases
|