Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 68 additions & 3 deletions rust/rubydex/src/indexing/rbs_indexer.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
//! Visit the RBS AST and create type definitions.

use ruby_rbs::node::{
self, ClassNode, CommentNode, ConstantNode, ExtendNode, GlobalNode, IncludeNode, ModuleNode, Node, NodeList,
PrependNode, TypeNameNode, Visit,
self, AliasKind, ClassNode, CommentNode, ConstantNode, ExtendNode, GlobalNode, IncludeNode, ModuleNode, Node,
NodeList, PrependNode, TypeNameNode, Visit,
};

use crate::diagnostic::Rule;
use crate::indexing::local_graph::LocalGraph;
use crate::model::comment::Comment;
use crate::model::definitions::{
ClassDefinition, ConstantDefinition, Definition, DefinitionFlags, ExtendDefinition, GlobalVariableDefinition,
IncludeDefinition, Mixin, ModuleDefinition, PrependDefinition,
IncludeDefinition, MethodAliasDefinition, Mixin, ModuleDefinition, PrependDefinition,
};
use crate::model::document::Document;
use crate::model::ids::{DefinitionId, NameId, ReferenceId, UriId};
Expand Down Expand Up @@ -324,6 +324,37 @@ impl Visit for RBSIndexer<'_> {
Mixin::Extend(ExtendDefinition::new(ref_id))
});
}

fn visit_alias_node(&mut self, alias_node: &node::AliasNode) {
if alias_node.kind() != AliasKind::Instance {
return;
}

let lexical_nesting_id = self.parent_lexical_scope_id();

let mut new_name = Self::bytes_to_string(alias_node.new_name().name());
let mut old_name = Self::bytes_to_string(alias_node.old_name().name());
new_name.push_str("()");
old_name.push_str("()");

let new_name_str_id = self.local_graph.intern_string(new_name);
let old_name_str_id = self.local_graph.intern_string(old_name);

let offset = Offset::from_rbs_location(&alias_node.location());
let comments = Self::collect_comments(alias_node.comment());

let definition = Definition::MethodAlias(Box::new(MethodAliasDefinition::new(
new_name_str_id,
old_name_str_id,
self.uri_id,
offset,
comments,
Self::flags(&alias_node.annotations()),
lexical_nesting_id,
)));

self.register_definition(definition, lexical_nesting_id);
}
}

#[cfg(test)]
Expand All @@ -336,6 +367,7 @@ mod tests {
use crate::{
assert_def_comments_eq, assert_def_mixins_eq, assert_def_name_eq, assert_def_name_offset_eq, assert_def_str_eq,
assert_def_superclass_ref_eq, assert_definition_at, assert_local_diagnostics_eq, assert_no_local_diagnostics,
assert_string_eq,
};

fn index_source(source: &str) -> LocalGraphTest {
Expand Down Expand Up @@ -714,4 +746,37 @@ mod tests {
assert!(def.flags().contains(DefinitionFlags::DEPRECATED));
});
}

#[test]
fn index_alias_node() {
let context = index_source({
"
class Foo
# Some documentation
alias bar baz
alias qux quux
alias self.singleton_bar self.singleton_baz
end
"
});

assert_no_local_diagnostics!(&context);

// Singleton alias is ignored, so only class + 2 instance aliases
assert_eq!(context.graph().definitions().len(), 3);

assert_definition_at!(&context, "1:1-6:4", Class, |class_def| {
assert_definition_at!(&context, "3:3-3:16", MethodAlias, |def| {
assert_string_eq!(&context, def.new_name_str_id(), "bar()");
assert_string_eq!(&context, def.old_name_str_id(), "baz()");
assert_def_comments_eq!(&context, def, ["Some documentation\n"]);
assert_eq!(class_def.id(), def.lexical_nesting_id().unwrap());
});

assert_definition_at!(&context, "4:3-4:17", MethodAlias, |def| {
assert_string_eq!(&context, def.new_name_str_id(), "qux()");
assert_string_eq!(&context, def.old_name_str_id(), "quux()");
});
});
}
}
33 changes: 33 additions & 0 deletions rust/rubydex/src/resolution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4967,4 +4967,37 @@ mod tests {
assert_declaration_exists!(context, "Baz");
assert_constant_reference_to!(context, "CONST", "file:///reopen.rb:5:5-5:10");
}

#[test]
fn rbs_method_alias_resolution() {
let mut context = GraphTest::new();
context.index_uri("file:///foo.rb", {
r"
class Foo
def bar; end
end

module Baz
def original; end
end
"
});
context.index_rbs_uri("file:///test.rbs", {
r"
class Foo
alias qux bar
end

module Baz
alias copy original
end
"
});
context.resolve();

assert_no_diagnostics!(&context);

assert_members_eq!(context, "Foo", ["bar()", "qux()"]);
assert_members_eq!(context, "Baz", ["copy()", "original()"]);
}
}
Loading