mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-26 20:09:19 +00:00
feat: Resolve builtin-attr and tools in ide layer
This commit is contained in:
parent
4691a0647b
commit
e58af219a4
15 changed files with 209 additions and 99 deletions
|
@ -29,8 +29,9 @@ use syntax::{
|
|||
};
|
||||
|
||||
use crate::{
|
||||
db::HirDatabase, semantics::PathResolution, Adt, BuiltinType, Const, Field, Function, Local,
|
||||
MacroDef, ModuleDef, Static, Struct, Trait, Type, TypeAlias, TypeParam, Variant,
|
||||
db::HirDatabase, semantics::PathResolution, Adt, BuiltinAttr, BuiltinType, Const, Field,
|
||||
Function, Local, MacroDef, ModuleDef, Static, Struct, Tool, Trait, Type, TypeAlias, TypeParam,
|
||||
Variant,
|
||||
};
|
||||
use base_db::CrateId;
|
||||
|
||||
|
@ -246,18 +247,6 @@ impl SourceAnalyzer {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn resolve_path_as_macro(
|
||||
&self,
|
||||
db: &dyn HirDatabase,
|
||||
path: &ast::Path,
|
||||
) -> Option<MacroDef> {
|
||||
// This must be a normal source file rather than macro file.
|
||||
let hygiene = Hygiene::new(db.upcast(), self.file_id);
|
||||
let ctx = body::LowerCtx::with_hygiene(db.upcast(), &hygiene);
|
||||
let hir_path = Path::from_src(path.clone(), &ctx)?;
|
||||
resolve_hir_path_as_macro(db, &self.resolver, &hir_path)
|
||||
}
|
||||
|
||||
pub(crate) fn resolve_path(
|
||||
&self,
|
||||
db: &dyn HirDatabase,
|
||||
|
@ -318,15 +307,6 @@ impl SourceAnalyzer {
|
|||
let ctx = body::LowerCtx::with_hygiene(db.upcast(), &hygiene);
|
||||
let hir_path = Path::from_src(path.clone(), &ctx)?;
|
||||
|
||||
// Case where path is a qualifier of another path, e.g. foo::bar::Baz where we are
|
||||
// trying to resolve foo::bar.
|
||||
if let Some(outer_path) = parent().and_then(ast::Path::cast) {
|
||||
if let Some(qualifier) = outer_path.qualifier() {
|
||||
if path == &qualifier {
|
||||
return resolve_hir_path_qualifier(db, &self.resolver, &hir_path);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Case where path is a qualifier of a use tree, e.g. foo::bar::{Baz, Qux} where we are
|
||||
// trying to resolve foo::bar.
|
||||
if let Some(use_tree) = parent().and_then(ast::UseTree::cast) {
|
||||
|
@ -337,10 +317,50 @@ impl SourceAnalyzer {
|
|||
}
|
||||
}
|
||||
|
||||
if parent().map_or(false, |it| ast::Visibility::can_cast(it.kind())) {
|
||||
let is_path_of_attr = path
|
||||
.top_path()
|
||||
.syntax()
|
||||
.ancestors()
|
||||
.nth(2) // Path -> Meta -> Attr
|
||||
.map_or(false, |it| ast::Attr::can_cast(it.kind()));
|
||||
|
||||
// Case where path is a qualifier of another path, e.g. foo::bar::Baz where we are
|
||||
// trying to resolve foo::bar.
|
||||
if let Some(outer_path) = path.parent_path() {
|
||||
if let Some(qualifier) = outer_path.qualifier() {
|
||||
if path == &qualifier {
|
||||
return resolve_hir_path_qualifier(db, &self.resolver, &hir_path);
|
||||
}
|
||||
}
|
||||
} else if is_path_of_attr {
|
||||
let res = resolve_hir_path_as_macro(db, &self.resolver, &hir_path);
|
||||
return match res {
|
||||
Some(_) => res.map(PathResolution::Macro),
|
||||
None => path.as_single_name_ref().and_then(|name_ref| {
|
||||
if let Some(builtin) = BuiltinAttr::by_name(&name_ref.text()) {
|
||||
Some(PathResolution::BuiltinAttr(builtin))
|
||||
} else if let Some(tool) = Tool::by_name(&name_ref.text()) {
|
||||
Some(PathResolution::Tool(tool))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
let res = if parent().map_or(false, |it| ast::Visibility::can_cast(it.kind())) {
|
||||
resolve_hir_path_qualifier(db, &self.resolver, &hir_path)
|
||||
} else {
|
||||
resolve_hir_path_(db, &self.resolver, &hir_path, prefer_value_ns)
|
||||
};
|
||||
match res {
|
||||
Some(_) => res,
|
||||
None if is_path_of_attr => path
|
||||
.first_segment()
|
||||
.and_then(|seg| seg.name_ref())
|
||||
.and_then(|name_ref| Tool::by_name(&name_ref.text()))
|
||||
.map(PathResolution::Tool),
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue