From 3c17643b3085682a695f0e6d80483edc00d04cb3 Mon Sep 17 00:00:00 2001 From: Jeremy Kolb Date: Mon, 28 Jan 2019 09:26:32 -0500 Subject: Go to Implementation for structs and enums --- crates/ra_ide_api/src/impls.rs | 121 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 crates/ra_ide_api/src/impls.rs (limited to 'crates/ra_ide_api/src/impls.rs') diff --git a/crates/ra_ide_api/src/impls.rs b/crates/ra_ide_api/src/impls.rs new file mode 100644 index 000000000..16a05758a --- /dev/null +++ b/crates/ra_ide_api/src/impls.rs @@ -0,0 +1,121 @@ +use ra_db::{SourceDatabase}; +use ra_syntax::{ + AstNode, ast, + algo::find_node_at_offset, +}; +use hir::{db::HirDatabase, source_binder}; + +use crate::{FilePosition, NavigationTarget, db::RootDatabase, RangeInfo}; + +pub(crate) fn goto_implementation( + db: &RootDatabase, + position: FilePosition, +) -> Option>> { + let file = db.parse(position.file_id); + let syntax = file.syntax(); + + let krate_id = db.crate_for(position.file_id).pop()?; + let krate = hir::Crate { crate_id: krate_id }; + let module = source_binder::module_from_position(db, position)?; + + let node = find_node_at_offset::(syntax, position.offset)?; + let ty = match node.kind() { + ast::NominalDefKind::StructDef(def) => { + source_binder::struct_from_module(db, module, &def).ty(db) + } + ast::NominalDefKind::EnumDef(def) => { + source_binder::enum_from_module(db, module, &def).ty(db) + } + }; + + let impls = db.impls_in_crate(krate); + + let navs = impls + .lookup_impl_blocks(db, &ty) + .map(|(module, imp)| NavigationTarget::from_impl_block(db, module, &imp)); + + Some(RangeInfo::new(node.syntax().range(), navs.collect())) +} + +#[cfg(test)] +mod tests { + use crate::mock_analysis::analysis_and_position; + + fn check_goto(fixuture: &str, expected: &[&str]) { + let (analysis, pos) = analysis_and_position(fixuture); + + let navs = analysis.goto_implementation(pos).unwrap().unwrap().info; + assert_eq!(navs.len(), expected.len()); + navs.into_iter() + .enumerate() + .for_each(|(i, nav)| nav.assert_match(expected[i])); + } + + #[test] + fn goto_implementation_works() { + check_goto( + " + //- /lib.rs + struct Foo<|>; + impl Foo {} + ", + &["impl IMPL_BLOCK FileId(1) [12; 23)"], + ); + } + + #[test] + fn goto_implementation_works_multiple_blocks() { + check_goto( + " + //- /lib.rs + struct Foo<|>; + impl Foo {} + impl Foo {} + ", + &[ + "impl IMPL_BLOCK FileId(1) [12; 23)", + "impl IMPL_BLOCK FileId(1) [24; 35)", + ], + ); + } + + #[test] + fn goto_implementation_works_multiple_mods() { + check_goto( + " + //- /lib.rs + struct Foo<|>; + mod a { + impl super::Foo {} + } + mod b { + impl super::Foo {} + } + ", + &[ + "impl IMPL_BLOCK FileId(1) [24; 42)", + "impl IMPL_BLOCK FileId(1) [57; 75)", + ], + ); + } + + #[test] + fn goto_implementation_works_multiple_files() { + check_goto( + " + //- /lib.rs + struct Foo<|>; + mod a; + mod b; + //- /a.rs + impl crate::Foo {} + //- /b.rs + impl crate::Foo {} + ", + &[ + "impl IMPL_BLOCK FileId(2) [0; 18)", + "impl IMPL_BLOCK FileId(3) [0; 18)", + ], + ); + } +} -- cgit v1.2.3 From 04eb15856bd183db3a1785b7cb74e0c32fd78a39 Mon Sep 17 00:00:00 2001 From: kjeremy Date: Wed, 30 Jan 2019 13:18:21 -0500 Subject: Resolve crate --- crates/ra_ide_api/src/impls.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'crates/ra_ide_api/src/impls.rs') diff --git a/crates/ra_ide_api/src/impls.rs b/crates/ra_ide_api/src/impls.rs index 16a05758a..469d56d63 100644 --- a/crates/ra_ide_api/src/impls.rs +++ b/crates/ra_ide_api/src/impls.rs @@ -14,9 +14,8 @@ pub(crate) fn goto_implementation( let file = db.parse(position.file_id); let syntax = file.syntax(); - let krate_id = db.crate_for(position.file_id).pop()?; - let krate = hir::Crate { crate_id: krate_id }; let module = source_binder::module_from_position(db, position)?; + let krate = module.krate(db)?; let node = find_node_at_offset::(syntax, position.offset)?; let ty = match node.kind() { -- cgit v1.2.3