mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-27 05:23:24 +00:00
Merge #5755
5755: Make hygiene private to hir r=davidlattimore a=matklad Co-authored-by: Aleksey Kladov <aleksey.kladov@gmail.com>
This commit is contained in:
commit
f1f73649a6
4 changed files with 39 additions and 16 deletions
|
@ -883,6 +883,13 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AssocItem {
|
impl AssocItem {
|
||||||
|
pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
|
||||||
|
match self {
|
||||||
|
AssocItem::Function(it) => Some(it.name(db)),
|
||||||
|
AssocItem::Const(it) => it.name(db),
|
||||||
|
AssocItem::TypeAlias(it) => Some(it.name(db)),
|
||||||
|
}
|
||||||
|
}
|
||||||
pub fn module(self, db: &dyn HirDatabase) -> Module {
|
pub fn module(self, db: &dyn HirDatabase) -> Module {
|
||||||
match self {
|
match self {
|
||||||
AssocItem::Function(f) => f.module(db),
|
AssocItem::Function(f) => f.module(db),
|
||||||
|
|
|
@ -52,8 +52,12 @@ pub use hir_def::{
|
||||||
type_ref::{Mutability, TypeRef},
|
type_ref::{Mutability, TypeRef},
|
||||||
};
|
};
|
||||||
pub use hir_expand::{
|
pub use hir_expand::{
|
||||||
hygiene::Hygiene, name::Name, HirFileId, InFile, MacroCallId, MacroCallLoc,
|
name::Name, HirFileId, InFile, MacroCallId, MacroCallLoc, /* FIXME */ MacroDefId,
|
||||||
MacroDefId, /* FIXME */
|
|
||||||
MacroFile, Origin,
|
MacroFile, Origin,
|
||||||
};
|
};
|
||||||
pub use hir_ty::display::HirDisplay;
|
pub use hir_ty::display::HirDisplay;
|
||||||
|
|
||||||
|
// These are negative re-exports: pub using these names is forbidden, they
|
||||||
|
// should remain private to hir internals.
|
||||||
|
#[allow(unused)]
|
||||||
|
use hir_expand::hygiene::Hygiene;
|
||||||
|
|
|
@ -502,18 +502,19 @@ impl<'db> SemanticsImpl<'db> {
|
||||||
fn scope(&self, node: &SyntaxNode) -> SemanticsScope<'db> {
|
fn scope(&self, node: &SyntaxNode) -> SemanticsScope<'db> {
|
||||||
let node = self.find_file(node.clone());
|
let node = self.find_file(node.clone());
|
||||||
let resolver = self.analyze2(node.as_ref(), None).resolver;
|
let resolver = self.analyze2(node.as_ref(), None).resolver;
|
||||||
SemanticsScope { db: self.db, resolver }
|
SemanticsScope { db: self.db, file_id: node.file_id, resolver }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn scope_at_offset(&self, node: &SyntaxNode, offset: TextSize) -> SemanticsScope<'db> {
|
fn scope_at_offset(&self, node: &SyntaxNode, offset: TextSize) -> SemanticsScope<'db> {
|
||||||
let node = self.find_file(node.clone());
|
let node = self.find_file(node.clone());
|
||||||
let resolver = self.analyze2(node.as_ref(), Some(offset)).resolver;
|
let resolver = self.analyze2(node.as_ref(), Some(offset)).resolver;
|
||||||
SemanticsScope { db: self.db, resolver }
|
SemanticsScope { db: self.db, file_id: node.file_id, resolver }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn scope_for_def(&self, def: Trait) -> SemanticsScope<'db> {
|
fn scope_for_def(&self, def: Trait) -> SemanticsScope<'db> {
|
||||||
|
let file_id = self.db.lookup_intern_trait(def.id).id.file_id;
|
||||||
let resolver = def.id.resolver(self.db.upcast());
|
let resolver = def.id.resolver(self.db.upcast());
|
||||||
SemanticsScope { db: self.db, resolver }
|
SemanticsScope { db: self.db, file_id, resolver }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn analyze(&self, node: &SyntaxNode) -> SourceAnalyzer {
|
fn analyze(&self, node: &SyntaxNode) -> SourceAnalyzer {
|
||||||
|
@ -709,6 +710,7 @@ fn find_root(node: &SyntaxNode) -> SyntaxNode {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct SemanticsScope<'a> {
|
pub struct SemanticsScope<'a> {
|
||||||
pub db: &'a dyn HirDatabase,
|
pub db: &'a dyn HirDatabase,
|
||||||
|
file_id: HirFileId,
|
||||||
resolver: Resolver,
|
resolver: Resolver,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -752,6 +754,14 @@ impl<'a> SemanticsScope<'a> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Resolve a path as-if it was written at the given scope. This is
|
||||||
|
/// necessary a heuristic, as it doesn't take hygiene into account.
|
||||||
|
pub fn resolve_hypothetical(&self, path: &ast::Path) -> Option<PathResolution> {
|
||||||
|
let hygiene = Hygiene::new(self.db.upcast(), self.file_id);
|
||||||
|
let path = Path::from_src(path.clone(), &hygiene)?;
|
||||||
|
self.resolve_hir_path(&path)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn resolve_hir_path(&self, path: &Path) -> Option<PathResolution> {
|
pub fn resolve_hir_path(&self, path: &Path) -> Option<PathResolution> {
|
||||||
resolve_hir_path(self.db, &self.resolver, path)
|
resolve_hir_path(self.db, &self.resolver, path)
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,6 @@ use test_utils::mark;
|
||||||
|
|
||||||
pub(crate) struct ResolutionScope<'db> {
|
pub(crate) struct ResolutionScope<'db> {
|
||||||
scope: hir::SemanticsScope<'db>,
|
scope: hir::SemanticsScope<'db>,
|
||||||
hygiene: hir::Hygiene,
|
|
||||||
node: SyntaxNode,
|
node: SyntaxNode,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -201,11 +200,7 @@ impl<'db> ResolutionScope<'db> {
|
||||||
.unwrap_or_else(|| file.syntax().clone());
|
.unwrap_or_else(|| file.syntax().clone());
|
||||||
let node = pick_node_for_resolution(node);
|
let node = pick_node_for_resolution(node);
|
||||||
let scope = sema.scope(&node);
|
let scope = sema.scope(&node);
|
||||||
ResolutionScope {
|
ResolutionScope { scope, node }
|
||||||
scope,
|
|
||||||
hygiene: hir::Hygiene::new(sema.db, resolve_context.file_id.into()),
|
|
||||||
node,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the function in which SSR was invoked, if any.
|
/// Returns the function in which SSR was invoked, if any.
|
||||||
|
@ -214,24 +209,31 @@ impl<'db> ResolutionScope<'db> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_path(&self, path: &ast::Path) -> Option<hir::PathResolution> {
|
fn resolve_path(&self, path: &ast::Path) -> Option<hir::PathResolution> {
|
||||||
let hir_path = hir::Path::from_src(path.clone(), &self.hygiene)?;
|
|
||||||
// First try resolving the whole path. This will work for things like
|
// First try resolving the whole path. This will work for things like
|
||||||
// `std::collections::HashMap`, but will fail for things like
|
// `std::collections::HashMap`, but will fail for things like
|
||||||
// `std::collections::HashMap::new`.
|
// `std::collections::HashMap::new`.
|
||||||
if let Some(resolution) = self.scope.resolve_hir_path(&hir_path) {
|
if let Some(resolution) = self.scope.resolve_hypothetical(&path) {
|
||||||
return Some(resolution);
|
return Some(resolution);
|
||||||
}
|
}
|
||||||
// Resolution failed, try resolving the qualifier (e.g. `std::collections::HashMap` and if
|
// Resolution failed, try resolving the qualifier (e.g. `std::collections::HashMap` and if
|
||||||
// that succeeds, then iterate through the candidates on the resolved type with the provided
|
// that succeeds, then iterate through the candidates on the resolved type with the provided
|
||||||
// name.
|
// name.
|
||||||
let resolved_qualifier = self.scope.resolve_hir_path_qualifier(&hir_path.qualifier()?)?;
|
let resolved_qualifier = self.scope.resolve_hypothetical(&path.qualifier()?)?;
|
||||||
if let hir::PathResolution::Def(hir::ModuleDef::Adt(adt)) = resolved_qualifier {
|
if let hir::PathResolution::Def(hir::ModuleDef::Adt(adt)) = resolved_qualifier {
|
||||||
|
let name = path.segment()?.name_ref()?;
|
||||||
adt.ty(self.scope.db).iterate_path_candidates(
|
adt.ty(self.scope.db).iterate_path_candidates(
|
||||||
self.scope.db,
|
self.scope.db,
|
||||||
self.scope.module()?.krate(),
|
self.scope.module()?.krate(),
|
||||||
&self.scope.traits_in_scope(),
|
&self.scope.traits_in_scope(),
|
||||||
Some(hir_path.segments().last()?.name),
|
None,
|
||||||
|_ty, assoc_item| Some(hir::PathResolution::AssocItem(assoc_item)),
|
|_ty, assoc_item| {
|
||||||
|
let item_name = assoc_item.name(self.scope.db)?;
|
||||||
|
if item_name.to_string().as_str() == name.text().as_str() {
|
||||||
|
Some(hir::PathResolution::AssocItem(assoc_item))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
},
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
|
Loading…
Reference in a new issue