Skip to content

Commit

Permalink
Merge pull request #1951 from Shopify/gh1940/alias-support
Browse files Browse the repository at this point in the history
Add support for method aliases when indexing
  • Loading branch information
nikijiandani authored Jun 5, 2024
2 parents 2d0a508 + b72ac02 commit c827208
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 0 deletions.
54 changes: 54 additions & 0 deletions lib/ruby_indexer/lib/ruby_indexer/declaration_listener.rb
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ def initialize(index, dispatcher, parse_result, file_path)
:on_instance_variable_operator_write_node_enter,
:on_instance_variable_or_write_node_enter,
:on_instance_variable_target_node_enter,
:on_alias_method_node_enter,
)
end

Expand Down Expand Up @@ -209,6 +210,8 @@ def on_call_node_enter(node)
handle_attribute(node, reader: false, writer: true)
when :attr_accessor
handle_attribute(node, reader: true, writer: true)
when :alias_method
handle_alias_method(node)
when :include, :prepend, :extend
handle_module_operation(node, message)
when :public
Expand Down Expand Up @@ -338,6 +341,20 @@ def on_instance_variable_target_node_enter(node)
)
end

sig { params(node: Prism::AliasMethodNode).void }
def on_alias_method_node_enter(node)
method_name = node.new_name.slice
comments = collect_comments(node)
@index << Entry::UnresolvedMethodAlias.new(
method_name,
node.old_name.slice,
@owner_stack.last,
@file_path,
node.new_name.location,
comments,
)
end

private

sig { params(node: Prism::CallNode).void }
Expand Down Expand Up @@ -365,6 +382,43 @@ def handle_private_constant(node)
entries&.each { |entry| entry.visibility = Entry::Visibility::PRIVATE }
end

sig { params(node: Prism::CallNode).void }
def handle_alias_method(node)
arguments = node.arguments&.arguments
return unless arguments

new_name, old_name = arguments
return unless new_name && old_name

new_name_value = case new_name
when Prism::StringNode
new_name.content
when Prism::SymbolNode
new_name.value
end

return unless new_name_value

old_name_value = case old_name
when Prism::StringNode
old_name.content
when Prism::SymbolNode
old_name.value
end

return unless old_name_value

comments = collect_comments(node)
@index << Entry::UnresolvedMethodAlias.new(
new_name_value,
old_name_value,
@owner_stack.last,
@file_path,
new_name.location,
comments,
)
end

sig do
params(
node: T.any(
Expand Down
28 changes: 28 additions & 0 deletions lib/ruby_indexer/lib/ruby_indexer/entry.rb
Original file line number Diff line number Diff line change
Expand Up @@ -469,5 +469,33 @@ def initialize(name, file_path, location, comments, owner)
@owner = owner
end
end

class UnresolvedMethodAlias < Entry
extend T::Sig

sig { returns(String) }
attr_reader :new_name, :old_name

sig { returns(T.nilable(Entry::Namespace)) }
attr_reader :owner

sig do
params(
new_name: String,
old_name: String,
owner: T.nilable(Entry::Namespace),
file_path: String,
location: Prism::Location,
comments: T::Array[String],
).void
end
def initialize(new_name, old_name, owner, file_path, location, comments) # rubocop:disable Metrics/ParameterLists
super(new_name, file_path, location, comments)

@new_name = new_name
@old_name = old_name
@owner = owner
end
end
end
end
20 changes: 20 additions & 0 deletions lib/ruby_indexer/test/method_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -378,5 +378,25 @@ def third; end
entry = T.must(@index["third"]&.first)
assert_equal("Foo", T.must(entry.owner).name)
end

def test_keeps_track_of_aliases
index(<<~RUBY)
class Foo
alias whatever to_s
alias_method :foo, :to_a
alias_method "bar", "to_a"
# These two are not indexed because they are dynamic or incomplete
alias_method baz, :to_a
alias_method :baz
end
RUBY

assert_entry("whatever", Entry::UnresolvedMethodAlias, "/fake/path/foo.rb:1-8:1-16")
assert_entry("foo", Entry::UnresolvedMethodAlias, "/fake/path/foo.rb:2-15:2-19")
assert_entry("bar", Entry::UnresolvedMethodAlias, "/fake/path/foo.rb:3-15:3-20")
# Foo plus 3 valid aliases
assert_equal(4, @index.instance_variable_get(:@entries).length)
end
end
end
1 change: 1 addition & 0 deletions lib/ruby_indexer/test/test_case.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ def index(source)

def assert_entry(expected_name, type, expected_location, visibility: nil)
entries = @index[expected_name]
refute_nil(entries, "Expected #{expected_name} to be indexed")
refute_empty(entries, "Expected #{expected_name} to be indexed")

entry = entries.first
Expand Down

0 comments on commit c827208

Please sign in to comment.