diff --git a/crates/ide_assists/src/handlers/split_import.rs b/crates/ide_assists/src/handlers/split_import.rs index 446f305444e..090df25cbde 100644 --- a/crates/ide_assists/src/handlers/split_import.rs +++ b/crates/ide_assists/src/handlers/split_import.rs @@ -1,5 +1,3 @@ -use std::iter::successors; - use syntax::{ast, AstNode, T}; use crate::{AssistContext, AssistId, AssistKind, Assists}; @@ -18,9 +16,8 @@ use crate::{AssistContext, AssistId, AssistKind, Assists}; pub(crate) fn split_import(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { let colon_colon = ctx.find_token_syntax_at_offset(T![::])?; let path = ast::Path::cast(colon_colon.parent()?)?.qualifier()?; - let top_path = successors(Some(path.clone()), |it| it.parent_path()).last()?; - let use_tree = top_path.syntax().ancestors().find_map(ast::UseTree::cast)?; + let use_tree = path.top_path().syntax().ancestors().find_map(ast::UseTree::cast)?; let new_tree = use_tree.split_prefix(&path); if new_tree == use_tree { diff --git a/crates/ide_db/src/defs.rs b/crates/ide_db/src/defs.rs index 452d87fe75e..02eb55ac35f 100644 --- a/crates/ide_db/src/defs.rs +++ b/crates/ide_db/src/defs.rs @@ -383,14 +383,17 @@ impl NameRefClass { } } } - - if let Some(resolved) = sema.resolve_path(&path) { - return if path.syntax().ancestors().find_map(ast::Attr::cast).is_some() { + let top_path = path.top_path(); + let is_attribute_path = top_path + .syntax() + .ancestors() + .find_map(ast::Attr::cast) + .map(|attr| attr.path().as_ref() == Some(&top_path)); + return match is_attribute_path { + Some(true) => sema.resolve_path(&path).and_then(|resolved| { match resolved { // Don't wanna collide with builtin attributes here like `test` hence guard - PathResolution::Def(module @ ModuleDef::Module(_)) - if path.parent_path().is_some() => - { + PathResolution::Def(module @ ModuleDef::Module(_)) if path == top_path => { Some(NameRefClass::Definition(Definition::ModuleDef(module))) } PathResolution::Macro(mac) if mac.kind() == hir::MacroKind::Attr => { @@ -398,10 +401,10 @@ impl NameRefClass { } _ => None, } - } else { - Some(NameRefClass::Definition(resolved.into())) - }; - } + }), + Some(false) => None, + None => sema.resolve_path(&path).map(Into::into).map(NameRefClass::Definition), + }; } let extern_crate = ast::ExternCrate::cast(parent)?; diff --git a/crates/syntax/src/ast/node_ext.rs b/crates/syntax/src/ast/node_ext.rs index 826efdfe87b..49c478b817a 100644 --- a/crates/syntax/src/ast/node_ext.rs +++ b/crates/syntax/src/ast/node_ext.rs @@ -336,6 +336,14 @@ impl ast::Path { pub fn qualifiers(&self) -> impl Iterator<Item = ast::Path> + Clone { successors(self.qualifier(), |p| p.qualifier()) } + + pub fn top_path(&self) -> ast::Path { + let mut this = self.clone(); + while let Some(path) = this.parent_path() { + this = path; + } + this + } } impl ast::Use {