Don't classify NameRef paths inside attribute TokenTrees

This commit is contained in:
Lukas Wirth 2021-06-30 21:29:40 +02:00
parent 1b9b2d1f40
commit 04f1104179
3 changed files with 22 additions and 14 deletions

View file

@ -1,5 +1,3 @@
use std::iter::successors;
use syntax::{ast, AstNode, T}; use syntax::{ast, AstNode, T};
use crate::{AssistContext, AssistId, AssistKind, Assists}; 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<()> { pub(crate) fn split_import(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
let colon_colon = ctx.find_token_syntax_at_offset(T![::])?; let colon_colon = ctx.find_token_syntax_at_offset(T![::])?;
let path = ast::Path::cast(colon_colon.parent()?)?.qualifier()?; 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); let new_tree = use_tree.split_prefix(&path);
if new_tree == use_tree { if new_tree == use_tree {

View file

@ -383,14 +383,17 @@ impl NameRefClass {
} }
} }
} }
let top_path = path.top_path();
if let Some(resolved) = sema.resolve_path(&path) { let is_attribute_path = top_path
return if path.syntax().ancestors().find_map(ast::Attr::cast).is_some() { .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 { match resolved {
// Don't wanna collide with builtin attributes here like `test` hence guard // Don't wanna collide with builtin attributes here like `test` hence guard
PathResolution::Def(module @ ModuleDef::Module(_)) PathResolution::Def(module @ ModuleDef::Module(_)) if path == top_path => {
if path.parent_path().is_some() =>
{
Some(NameRefClass::Definition(Definition::ModuleDef(module))) Some(NameRefClass::Definition(Definition::ModuleDef(module)))
} }
PathResolution::Macro(mac) if mac.kind() == hir::MacroKind::Attr => { PathResolution::Macro(mac) if mac.kind() == hir::MacroKind::Attr => {
@ -398,10 +401,10 @@ impl NameRefClass {
} }
_ => None, _ => 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)?; let extern_crate = ast::ExternCrate::cast(parent)?;

View file

@ -336,6 +336,14 @@ impl ast::Path {
pub fn qualifiers(&self) -> impl Iterator<Item = ast::Path> + Clone { pub fn qualifiers(&self) -> impl Iterator<Item = ast::Path> + Clone {
successors(self.qualifier(), |p| p.qualifier()) 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 { impl ast::Use {