Move ModuleScope to a new module
This commit is contained in:
parent
49aac9ef63
commit
0f212b3798
5 changed files with 114 additions and 108 deletions
|
@ -17,7 +17,8 @@ use rustc_hash::FxHashMap;
|
||||||
use crate::{
|
use crate::{
|
||||||
db::DefDatabase,
|
db::DefDatabase,
|
||||||
expr::{Expr, ExprId, Pat, PatId},
|
expr::{Expr, ExprId, Pat, PatId},
|
||||||
nameres::{BuiltinShadowMode, CrateDefMap},
|
item_scope::BuiltinShadowMode,
|
||||||
|
nameres::CrateDefMap,
|
||||||
path::{ModPath, Path},
|
path::{ModPath, Path},
|
||||||
src::HasSource,
|
src::HasSource,
|
||||||
DefWithBodyId, HasModule, Lookup, ModuleDefId, ModuleId,
|
DefWithBodyId, HasModule, Lookup, ModuleDefId, ModuleId,
|
||||||
|
|
|
@ -1 +1,106 @@
|
||||||
|
use hir_expand::name::Name;
|
||||||
|
use once_cell::sync::Lazy;
|
||||||
|
use rustc_hash::FxHashMap;
|
||||||
|
|
||||||
|
use crate::{per_ns::PerNs, BuiltinType, LocalImportId, MacroDefId, ModuleDefId, TraitId};
|
||||||
|
|
||||||
|
#[derive(Debug, Default, PartialEq, Eq)]
|
||||||
|
pub struct ModuleScope {
|
||||||
|
pub(crate) items: FxHashMap<Name, Resolution>,
|
||||||
|
/// Macros visable in current module in legacy textual scope
|
||||||
|
///
|
||||||
|
/// For macros invoked by an unquatified identifier like `bar!()`, `legacy_macros` will be searched in first.
|
||||||
|
/// If it yields no result, then it turns to module scoped `macros`.
|
||||||
|
/// It macros with name quatified with a path like `crate::foo::bar!()`, `legacy_macros` will be skipped,
|
||||||
|
/// and only normal scoped `macros` will be searched in.
|
||||||
|
///
|
||||||
|
/// Note that this automatically inherit macros defined textually before the definition of module itself.
|
||||||
|
///
|
||||||
|
/// Module scoped macros will be inserted into `items` instead of here.
|
||||||
|
// FIXME: Macro shadowing in one module is not properly handled. Non-item place macros will
|
||||||
|
// be all resolved to the last one defined if shadowing happens.
|
||||||
|
pub(crate) legacy_macros: FxHashMap<Name, MacroDefId>,
|
||||||
|
}
|
||||||
|
|
||||||
|
static BUILTIN_SCOPE: Lazy<FxHashMap<Name, Resolution>> = Lazy::new(|| {
|
||||||
|
BuiltinType::ALL
|
||||||
|
.iter()
|
||||||
|
.map(|(name, ty)| {
|
||||||
|
(name.clone(), Resolution { def: PerNs::types(ty.clone().into()), import: None })
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
});
|
||||||
|
|
||||||
|
/// Shadow mode for builtin type which can be shadowed by module.
|
||||||
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
|
pub enum BuiltinShadowMode {
|
||||||
|
// Prefer Module
|
||||||
|
Module,
|
||||||
|
// Prefer Other Types
|
||||||
|
Other,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Legacy macros can only be accessed through special methods like `get_legacy_macros`.
|
||||||
|
/// Other methods will only resolve values, types and module scoped macros only.
|
||||||
|
impl ModuleScope {
|
||||||
|
pub fn entries<'a>(&'a self) -> impl Iterator<Item = (&'a Name, &'a Resolution)> + 'a {
|
||||||
|
//FIXME: shadowing
|
||||||
|
self.items.iter().chain(BUILTIN_SCOPE.iter())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn declarations(&self) -> impl Iterator<Item = ModuleDefId> + '_ {
|
||||||
|
self.entries()
|
||||||
|
.filter_map(|(_name, res)| if res.import.is_none() { Some(res.def) } else { None })
|
||||||
|
.flat_map(|per_ns| {
|
||||||
|
per_ns.take_types().into_iter().chain(per_ns.take_values().into_iter())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Iterate over all module scoped macros
|
||||||
|
pub fn macros<'a>(&'a self) -> impl Iterator<Item = (&'a Name, MacroDefId)> + 'a {
|
||||||
|
self.items
|
||||||
|
.iter()
|
||||||
|
.filter_map(|(name, res)| res.def.take_macros().map(|macro_| (name, macro_)))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Iterate over all legacy textual scoped macros visable at the end of the module
|
||||||
|
pub fn legacy_macros<'a>(&'a self) -> impl Iterator<Item = (&'a Name, MacroDefId)> + 'a {
|
||||||
|
self.legacy_macros.iter().map(|(name, def)| (name, *def))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get a name from current module scope, legacy macros are not included
|
||||||
|
pub fn get(&self, name: &Name, shadow: BuiltinShadowMode) -> Option<&Resolution> {
|
||||||
|
match shadow {
|
||||||
|
BuiltinShadowMode::Module => self.items.get(name).or_else(|| BUILTIN_SCOPE.get(name)),
|
||||||
|
BuiltinShadowMode::Other => {
|
||||||
|
let item = self.items.get(name);
|
||||||
|
if let Some(res) = item {
|
||||||
|
if let Some(ModuleDefId::ModuleId(_)) = res.def.take_types() {
|
||||||
|
return BUILTIN_SCOPE.get(name).or(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
item.or_else(|| BUILTIN_SCOPE.get(name))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn traits<'a>(&'a self) -> impl Iterator<Item = TraitId> + 'a {
|
||||||
|
self.items.values().filter_map(|r| match r.def.take_types() {
|
||||||
|
Some(ModuleDefId::TraitId(t)) => Some(t),
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn get_legacy_macro(&self, name: &Name) -> Option<MacroDefId> {
|
||||||
|
self.legacy_macros.get(name).copied()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Default)]
|
||||||
|
pub struct Resolution {
|
||||||
|
/// None for unresolved
|
||||||
|
pub def: PerNs,
|
||||||
|
/// ident by which this is imported into local scope.
|
||||||
|
pub import: Option<LocalImportId>,
|
||||||
|
}
|
||||||
|
|
|
@ -57,8 +57,7 @@ mod tests;
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use hir_expand::{diagnostics::DiagnosticSink, name::Name, InFile, MacroDefId};
|
use hir_expand::{diagnostics::DiagnosticSink, name::Name, InFile};
|
||||||
use once_cell::sync::Lazy;
|
|
||||||
use ra_arena::Arena;
|
use ra_arena::Arena;
|
||||||
use ra_db::{CrateId, Edition, FileId, FilePosition};
|
use ra_db::{CrateId, Edition, FileId, FilePosition};
|
||||||
use ra_prof::profile;
|
use ra_prof::profile;
|
||||||
|
@ -69,12 +68,12 @@ use ra_syntax::{
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
builtin_type::BuiltinType,
|
|
||||||
db::DefDatabase,
|
db::DefDatabase,
|
||||||
|
item_scope::{BuiltinShadowMode, ModuleScope},
|
||||||
nameres::{diagnostics::DefDiagnostic, path_resolution::ResolveMode},
|
nameres::{diagnostics::DefDiagnostic, path_resolution::ResolveMode},
|
||||||
path::ModPath,
|
path::ModPath,
|
||||||
per_ns::PerNs,
|
per_ns::PerNs,
|
||||||
AstId, ImplId, LocalImportId, LocalModuleId, ModuleDefId, ModuleId, TraitId,
|
AstId, ImplId, LocalModuleId, ModuleDefId, ModuleId,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Contains all top-level defs from a macro-expanded crate
|
/// Contains all top-level defs from a macro-expanded crate
|
||||||
|
@ -174,107 +173,6 @@ pub struct ModuleData {
|
||||||
pub impls: Vec<ImplId>,
|
pub impls: Vec<ImplId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, PartialEq, Eq)]
|
|
||||||
pub struct ModuleScope {
|
|
||||||
items: FxHashMap<Name, Resolution>,
|
|
||||||
/// Macros visable in current module in legacy textual scope
|
|
||||||
///
|
|
||||||
/// For macros invoked by an unquatified identifier like `bar!()`, `legacy_macros` will be searched in first.
|
|
||||||
/// If it yields no result, then it turns to module scoped `macros`.
|
|
||||||
/// It macros with name quatified with a path like `crate::foo::bar!()`, `legacy_macros` will be skipped,
|
|
||||||
/// and only normal scoped `macros` will be searched in.
|
|
||||||
///
|
|
||||||
/// Note that this automatically inherit macros defined textually before the definition of module itself.
|
|
||||||
///
|
|
||||||
/// Module scoped macros will be inserted into `items` instead of here.
|
|
||||||
// FIXME: Macro shadowing in one module is not properly handled. Non-item place macros will
|
|
||||||
// be all resolved to the last one defined if shadowing happens.
|
|
||||||
legacy_macros: FxHashMap<Name, MacroDefId>,
|
|
||||||
}
|
|
||||||
|
|
||||||
static BUILTIN_SCOPE: Lazy<FxHashMap<Name, Resolution>> = Lazy::new(|| {
|
|
||||||
BuiltinType::ALL
|
|
||||||
.iter()
|
|
||||||
.map(|(name, ty)| {
|
|
||||||
(name.clone(), Resolution { def: PerNs::types(ty.clone().into()), import: None })
|
|
||||||
})
|
|
||||||
.collect()
|
|
||||||
});
|
|
||||||
|
|
||||||
/// Shadow mode for builtin type which can be shadowed by module.
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
|
||||||
pub enum BuiltinShadowMode {
|
|
||||||
// Prefer Module
|
|
||||||
Module,
|
|
||||||
// Prefer Other Types
|
|
||||||
Other,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Legacy macros can only be accessed through special methods like `get_legacy_macros`.
|
|
||||||
/// Other methods will only resolve values, types and module scoped macros only.
|
|
||||||
impl ModuleScope {
|
|
||||||
pub fn entries<'a>(&'a self) -> impl Iterator<Item = (&'a Name, &'a Resolution)> + 'a {
|
|
||||||
//FIXME: shadowing
|
|
||||||
self.items.iter().chain(BUILTIN_SCOPE.iter())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn declarations(&self) -> impl Iterator<Item = ModuleDefId> + '_ {
|
|
||||||
self.entries()
|
|
||||||
.filter_map(|(_name, res)| if res.import.is_none() { Some(res.def) } else { None })
|
|
||||||
.flat_map(|per_ns| {
|
|
||||||
per_ns.take_types().into_iter().chain(per_ns.take_values().into_iter())
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Iterate over all module scoped macros
|
|
||||||
pub fn macros<'a>(&'a self) -> impl Iterator<Item = (&'a Name, MacroDefId)> + 'a {
|
|
||||||
self.items
|
|
||||||
.iter()
|
|
||||||
.filter_map(|(name, res)| res.def.take_macros().map(|macro_| (name, macro_)))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Iterate over all legacy textual scoped macros visable at the end of the module
|
|
||||||
pub fn legacy_macros<'a>(&'a self) -> impl Iterator<Item = (&'a Name, MacroDefId)> + 'a {
|
|
||||||
self.legacy_macros.iter().map(|(name, def)| (name, *def))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get a name from current module scope, legacy macros are not included
|
|
||||||
pub fn get(&self, name: &Name, shadow: BuiltinShadowMode) -> Option<&Resolution> {
|
|
||||||
match shadow {
|
|
||||||
BuiltinShadowMode::Module => self.items.get(name).or_else(|| BUILTIN_SCOPE.get(name)),
|
|
||||||
BuiltinShadowMode::Other => {
|
|
||||||
let item = self.items.get(name);
|
|
||||||
if let Some(res) = item {
|
|
||||||
if let Some(ModuleDefId::ModuleId(_)) = res.def.take_types() {
|
|
||||||
return BUILTIN_SCOPE.get(name).or(item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
item.or_else(|| BUILTIN_SCOPE.get(name))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn traits<'a>(&'a self) -> impl Iterator<Item = TraitId> + 'a {
|
|
||||||
self.items.values().filter_map(|r| match r.def.take_types() {
|
|
||||||
Some(ModuleDefId::TraitId(t)) => Some(t),
|
|
||||||
_ => None,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_legacy_macro(&self, name: &Name) -> Option<MacroDefId> {
|
|
||||||
self.legacy_macros.get(name).copied()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Default)]
|
|
||||||
pub struct Resolution {
|
|
||||||
/// None for unresolved
|
|
||||||
pub def: PerNs,
|
|
||||||
/// ident by which this is imported into local scope.
|
|
||||||
pub import: Option<LocalImportId>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CrateDefMap {
|
impl CrateDefMap {
|
||||||
pub(crate) fn crate_def_map_query(
|
pub(crate) fn crate_def_map_query(
|
||||||
// Note that this doesn't have `+ AstDatabase`!
|
// Note that this doesn't have `+ AstDatabase`!
|
||||||
|
|
|
@ -18,9 +18,10 @@ use test_utils::tested_by;
|
||||||
use crate::{
|
use crate::{
|
||||||
attr::Attrs,
|
attr::Attrs,
|
||||||
db::DefDatabase,
|
db::DefDatabase,
|
||||||
|
item_scope::Resolution,
|
||||||
nameres::{
|
nameres::{
|
||||||
diagnostics::DefDiagnostic, mod_resolution::ModDir, path_resolution::ReachedFixedPoint,
|
diagnostics::DefDiagnostic, mod_resolution::ModDir, path_resolution::ReachedFixedPoint,
|
||||||
raw, BuiltinShadowMode, CrateDefMap, ModuleData, ModuleOrigin, Resolution, ResolveMode,
|
raw, BuiltinShadowMode, CrateDefMap, ModuleData, ModuleOrigin, ResolveMode,
|
||||||
},
|
},
|
||||||
path::{ModPath, PathKind},
|
path::{ModPath, PathKind},
|
||||||
per_ns::PerNs,
|
per_ns::PerNs,
|
||||||
|
|
|
@ -14,7 +14,8 @@ use crate::{
|
||||||
db::DefDatabase,
|
db::DefDatabase,
|
||||||
expr::{ExprId, PatId},
|
expr::{ExprId, PatId},
|
||||||
generics::GenericParams,
|
generics::GenericParams,
|
||||||
nameres::{BuiltinShadowMode, CrateDefMap},
|
item_scope::BuiltinShadowMode,
|
||||||
|
nameres::CrateDefMap,
|
||||||
path::{ModPath, PathKind},
|
path::{ModPath, PathKind},
|
||||||
per_ns::PerNs,
|
per_ns::PerNs,
|
||||||
AdtId, AssocContainerId, ConstId, ContainerId, DefWithBodyId, EnumId, EnumVariantId,
|
AdtId, AssocContainerId, ConstId, ContainerId, DefWithBodyId, EnumId, EnumVariantId,
|
||||||
|
|
Loading…
Add table
Reference in a new issue