Skip to content

Commit c75541a

Browse files
committed
Improve handling of class variables, aliases and constant aliases
1 parent 9e7450d commit c75541a

File tree

3 files changed

+101
-7
lines changed

3 files changed

+101
-7
lines changed

lib/ruby_indexer/lib/ruby_indexer/index.rb

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -198,13 +198,14 @@ def prefix_search(query, nesting = nil)
198198
#: (String? query) -> Array[Entry]
199199
def fuzzy_search(query)
200200
unless query
201-
entries = @entries.filter_map do |_name, entries|
201+
entries = @entries.values.filter_map do |entries|
202202
next if entries.first.is_a?(Entry::SingletonClass)
203203

204204
entries
205205
end
206-
207-
return entries.flatten
206+
return entries.flat_map do |entries|
207+
skip_unresolved_entries(entries)
208+
end
208209
end
209210

210211
normalized_query = query.gsub("::", "").downcase
@@ -216,7 +217,9 @@ def fuzzy_search(query)
216217
[entries, -similarity] if similarity > ENTRY_SIMILARITY_THRESHOLD
217218
end
218219
results.sort_by!(&:last)
219-
results.flat_map(&:first)
220+
results.flat_map do |entries, _similarity|
221+
skip_unresolved_entries(entries)
222+
end
220223
end
221224

222225
#: (String? name, String receiver_name) -> Array[(Entry::Member | Entry::MethodAlias)]
@@ -1054,5 +1057,34 @@ def resolve_method_alias(entry, receiver_name, seen_names)
10541057
original_entries << resolved_alias
10551058
resolved_alias
10561059
end
1060+
1061+
# Attempts to resolve an entry if it is an unresolved constant or method alias.
1062+
# Returns the resolved entry, or nil if it cannot be resolved.
1063+
#: (Entry) -> Entry?
1064+
def resolve_entry(entry)
1065+
case entry
1066+
when Entry::UnresolvedConstantAlias
1067+
resolved_entry = resolve_alias(entry, [])
1068+
resolved_entry unless resolved_entry.is_a?(Entry::UnresolvedConstantAlias)
1069+
when Entry::UnresolvedMethodAlias
1070+
resolved_entry = resolve_method_alias(entry, entry.owner&.name || "", [])
1071+
resolved_entry unless resolved_entry.is_a?(Entry::UnresolvedMethodAlias)
1072+
else
1073+
entry
1074+
end
1075+
end
1076+
1077+
# Filters and resolves entries, skipping those that remain unresolved.
1078+
# Returns an array of successfully resolved entries.
1079+
#: (Array[Entry]) -> Array[Entry?]
1080+
def skip_unresolved_entries(entries)
1081+
entries.filter_map do |entry|
1082+
resolved_entry = resolve_entry(entry)
1083+
1084+
next unless resolved_entry
1085+
1086+
resolved_entry
1087+
end
1088+
end
10571089
end
10581090
end

lib/ruby_lsp/requests/support/common.rb

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -140,21 +140,28 @@ def each_constant_path_part(node, &block)
140140
end
141141
end
142142

143-
#: (RubyIndexer::Entry entry) -> Integer?
143+
#: (RubyIndexer::Entry entry) -> Integer
144144
def kind_for_entry(entry)
145145
case entry
146146
when RubyIndexer::Entry::Class
147147
Constant::SymbolKind::CLASS
148148
when RubyIndexer::Entry::Module
149149
Constant::SymbolKind::NAMESPACE
150-
when RubyIndexer::Entry::Constant
150+
when RubyIndexer::Entry::Constant, RubyIndexer::Entry::ConstantAlias
151151
Constant::SymbolKind::CONSTANT
152152
when RubyIndexer::Entry::Method
153153
entry.name == "initialize" ? Constant::SymbolKind::CONSTRUCTOR : Constant::SymbolKind::METHOD
154154
when RubyIndexer::Entry::Accessor
155155
Constant::SymbolKind::PROPERTY
156-
when RubyIndexer::Entry::InstanceVariable
156+
when RubyIndexer::Entry::InstanceVariable, RubyIndexer::Entry::ClassVariable
157157
Constant::SymbolKind::FIELD
158+
when RubyIndexer::Entry::MethodAlias
159+
Constant::SymbolKind::METHOD
160+
else
161+
# Kind shold be represented by one of
162+
# [SymbolKind](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#symbolKind) variants
163+
# $stderr.puts("Unknonw symbol kind #{entry.inspect}. Kind should be represented by one of SymbolKind enum variants. Please report this as a bug")
164+
Constant::SymbolKind::NULL
158165
end
159166
end
160167
end

test/requests/workspace_symbol_test.rb

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,61 @@ def bar; end
108108
assert_equal(RubyLsp::Constant::SymbolKind::PROPERTY, result&.kind)
109109
end
110110

111+
def test_returns_resolved_method_alias
112+
@index.index_single(URI::Generic.from_path(path: "/fake.rb"), <<~RUBY)
113+
class Foo
114+
def test
115+
end
116+
alias whatever test
117+
alias_method :bar, :to_a
118+
alias_method "baz", "to_a"
119+
end
120+
RUBY
121+
122+
result = RubyLsp::Requests::WorkspaceSymbol.new(@global_state, "whatever").perform.first
123+
assert_equal("whatever", result&.name)
124+
assert_equal(RubyLsp::Constant::SymbolKind::METHOD, result&.kind)
125+
126+
result = RubyLsp::Requests::WorkspaceSymbol.new(@global_state, "bar").perform
127+
assert_empty(result)
128+
129+
result = RubyLsp::Requests::WorkspaceSymbol.new(@global_state, "bag").perform
130+
assert_empty(result)
131+
end
132+
133+
def test_returns_resolved_constant_alias
134+
@index.index_single(URI::Generic.from_path(path: "/fake.rb"), <<~RUBY)
135+
OK = 'OK'
136+
class Foo
137+
BOK = OK
138+
BAD = AD
139+
end
140+
RUBY
141+
142+
result = RubyLsp::Requests::WorkspaceSymbol.new(@global_state, "OK").perform.first
143+
assert_equal("OK", result&.name)
144+
assert_equal(RubyLsp::Constant::SymbolKind::CONSTANT, result&.kind)
145+
146+
result = RubyLsp::Requests::WorkspaceSymbol.new(@global_state, "Foo::OK").perform.first
147+
assert_equal("Foo::BOK", result&.name)
148+
assert_equal(RubyLsp::Constant::SymbolKind::CONSTANT, result&.kind)
149+
150+
result = RubyLsp::Requests::WorkspaceSymbol.new(@global_state, "BAD").perform
151+
assert_empty(result)
152+
end
153+
154+
def test_returns_class_variable
155+
@index.index_single(URI::Generic.from_path(path: "/fake.rb"), <<~RUBY)
156+
class Foo
157+
@@test = '123'
158+
end
159+
RUBY
160+
161+
result = RubyLsp::Requests::WorkspaceSymbol.new(@global_state, "test").perform.first
162+
assert_equal("@@test", result&.name)
163+
assert_equal(RubyLsp::Constant::SymbolKind::FIELD, result&.kind)
164+
end
165+
111166
def test_returns_symbols_from_unsaved_files
112167
@index.index_single(URI("untitled:Untitled-1"), <<~RUBY)
113168
class Foo; end

0 commit comments

Comments
 (0)