mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-28 04:45:05 +00:00
Split glob import map to per-ns, switch ExprCollector to use a simpler push_res
This commit is contained in:
parent
de9e964e4a
commit
76755ce176
4 changed files with 110 additions and 33 deletions
|
@ -26,7 +26,7 @@ use crate::{
|
||||||
dummy_expr_id, ArithOp, Array, BinaryOp, BindingAnnotation, CmpOp, Expr, ExprId, Literal,
|
dummy_expr_id, ArithOp, Array, BinaryOp, BindingAnnotation, CmpOp, Expr, ExprId, Literal,
|
||||||
LogicOp, MatchArm, Ordering, Pat, PatId, RecordFieldPat, RecordLitField, Statement,
|
LogicOp, MatchArm, Ordering, Pat, PatId, RecordFieldPat, RecordLitField, Statement,
|
||||||
},
|
},
|
||||||
item_scope::{BuiltinShadowMode, ImportType},
|
item_scope::BuiltinShadowMode,
|
||||||
item_tree::{FileItemTreeId, ItemTree, ItemTreeNode},
|
item_tree::{FileItemTreeId, ItemTree, ItemTreeNode},
|
||||||
path::{GenericArgs, Path},
|
path::{GenericArgs, Path},
|
||||||
type_ref::{Mutability, Rawness, TypeRef},
|
type_ref::{Mutability, Rawness, TypeRef},
|
||||||
|
@ -81,7 +81,6 @@ pub(super) fn lower(
|
||||||
map
|
map
|
||||||
},
|
},
|
||||||
expander,
|
expander,
|
||||||
import_types: FxHashMap::default(),
|
|
||||||
}
|
}
|
||||||
.collect(params, body)
|
.collect(params, body)
|
||||||
}
|
}
|
||||||
|
@ -94,7 +93,6 @@ struct ExprCollector<'a> {
|
||||||
source_map: BodySourceMap,
|
source_map: BodySourceMap,
|
||||||
|
|
||||||
item_trees: FxHashMap<HirFileId, Arc<ItemTree>>,
|
item_trees: FxHashMap<HirFileId, Arc<ItemTree>>,
|
||||||
import_types: FxHashMap<Name, ImportType>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ExprCollector<'_> {
|
impl ExprCollector<'_> {
|
||||||
|
@ -713,10 +711,8 @@ impl ExprCollector<'_> {
|
||||||
_ => true,
|
_ => true,
|
||||||
};
|
};
|
||||||
self.body.item_scope.push_res(
|
self.body.item_scope.push_res(
|
||||||
&mut self.import_types,
|
|
||||||
name.as_name(),
|
name.as_name(),
|
||||||
crate::per_ns::PerNs::from_def(def, vis, has_constructor),
|
crate::per_ns::PerNs::from_def(def, vis, has_constructor),
|
||||||
ImportType::Named,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,12 +4,12 @@
|
||||||
use hir_expand::name::Name;
|
use hir_expand::name::Name;
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use ra_db::CrateId;
|
use ra_db::CrateId;
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::{FxHashMap, FxHashSet};
|
||||||
use test_utils::mark;
|
use test_utils::mark;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
db::DefDatabase, per_ns::PerNs, visibility::Visibility, AdtId, BuiltinType, HasModule, ImplId,
|
db::DefDatabase, per_ns::PerNs, visibility::Visibility, AdtId, BuiltinType, HasModule, ImplId,
|
||||||
Lookup, MacroDefId, ModuleDefId, TraitId,
|
LocalModuleId, Lookup, MacroDefId, ModuleDefId, TraitId,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
|
@ -19,13 +19,6 @@ pub(crate) enum ImportType {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ImportType {
|
impl ImportType {
|
||||||
fn is_glob(&self) -> bool {
|
|
||||||
match self {
|
|
||||||
ImportType::Glob => true,
|
|
||||||
ImportType::Named => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_named(&self) -> bool {
|
fn is_named(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
ImportType::Glob => false,
|
ImportType::Glob => false,
|
||||||
|
@ -34,6 +27,13 @@ impl ImportType {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
pub struct PerNsGlobImports {
|
||||||
|
types: FxHashSet<(LocalModuleId, Name)>,
|
||||||
|
values: FxHashSet<(LocalModuleId, Name)>,
|
||||||
|
macros: FxHashSet<(LocalModuleId, Name)>,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, PartialEq, Eq)]
|
#[derive(Debug, Default, PartialEq, Eq)]
|
||||||
pub struct ItemScope {
|
pub struct ItemScope {
|
||||||
visible: FxHashMap<Name, PerNs>,
|
visible: FxHashMap<Name, PerNs>,
|
||||||
|
@ -145,30 +145,65 @@ impl ItemScope {
|
||||||
self.legacy_macros.insert(name, mac);
|
self.legacy_macros.insert(name, mac);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn push_res(
|
pub(crate) fn push_res(&mut self, name: Name, def: PerNs) -> bool {
|
||||||
|
let mut changed = false;
|
||||||
|
let existing = self.visible.entry(name).or_default();
|
||||||
|
|
||||||
|
if existing.types.is_none() && def.types.is_some() {
|
||||||
|
existing.types = def.types;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if existing.values.is_none() && def.values.is_some() {
|
||||||
|
existing.values = def.values;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if existing.macros.is_none() && def.macros.is_some() {
|
||||||
|
existing.macros = def.macros;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
changed
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn push_res_with_import(
|
||||||
&mut self,
|
&mut self,
|
||||||
existing_import_map: &mut FxHashMap<Name, ImportType>,
|
glob_imports: &mut PerNsGlobImports,
|
||||||
name: Name,
|
lookup: (LocalModuleId, Name),
|
||||||
def: PerNs,
|
def: PerNs,
|
||||||
def_import_type: ImportType,
|
def_import_type: ImportType,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let mut changed = false;
|
let mut changed = false;
|
||||||
let existing = self.visible.entry(name.clone()).or_default();
|
let existing = self.visible.entry(lookup.1.clone()).or_default();
|
||||||
let existing_import_type = existing_import_map.entry(name).or_insert(def_import_type);
|
|
||||||
|
|
||||||
macro_rules! check_changed {
|
macro_rules! check_changed {
|
||||||
($changed:ident, ($existing:ident/$def:ident).$field:ident, $existing_import_type:ident, $def_import_type:ident) => {
|
(
|
||||||
|
$changed:ident,
|
||||||
|
( $existing:ident / $def:ident ) . $field:ident,
|
||||||
|
$glob_imports:ident [ $lookup:ident ],
|
||||||
|
$def_import_type:ident
|
||||||
|
) => {
|
||||||
match ($existing.$field, $def.$field) {
|
match ($existing.$field, $def.$field) {
|
||||||
(None, Some(_)) => {
|
(None, Some(_)) => {
|
||||||
*existing_import_type = $def_import_type;
|
match $def_import_type {
|
||||||
|
ImportType::Glob => {
|
||||||
|
$glob_imports.$field.insert($lookup.clone());
|
||||||
|
}
|
||||||
|
ImportType::Named => {
|
||||||
|
$glob_imports.$field.remove(&$lookup);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$existing.$field = $def.$field;
|
$existing.$field = $def.$field;
|
||||||
$changed = true;
|
$changed = true;
|
||||||
}
|
}
|
||||||
(Some(_), Some(_))
|
(Some(_), Some(_))
|
||||||
if $existing_import_type.is_glob() && $def_import_type.is_named() =>
|
if $glob_imports.$field.contains(&$lookup)
|
||||||
|
&& $def_import_type.is_named() =>
|
||||||
{
|
{
|
||||||
mark::hit!(import_shadowed);
|
mark::hit!(import_shadowed);
|
||||||
*$existing_import_type = $def_import_type;
|
$glob_imports.$field.remove(&$lookup);
|
||||||
$existing.$field = $def.$field;
|
$existing.$field = $def.$field;
|
||||||
$changed = true;
|
$changed = true;
|
||||||
}
|
}
|
||||||
|
@ -177,9 +212,9 @@ impl ItemScope {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
check_changed!(changed, (existing / def).types, existing_import_type, def_import_type);
|
check_changed!(changed, (existing / def).types, glob_imports[lookup], def_import_type);
|
||||||
check_changed!(changed, (existing / def).values, existing_import_type, def_import_type);
|
check_changed!(changed, (existing / def).values, glob_imports[lookup], def_import_type);
|
||||||
check_changed!(changed, (existing / def).macros, existing_import_type, def_import_type);
|
check_changed!(changed, (existing / def).macros, glob_imports[lookup], def_import_type);
|
||||||
|
|
||||||
changed
|
changed
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ use test_utils::mark;
|
||||||
use crate::{
|
use crate::{
|
||||||
attr::Attrs,
|
attr::Attrs,
|
||||||
db::DefDatabase,
|
db::DefDatabase,
|
||||||
item_scope::ImportType,
|
item_scope::{ImportType, PerNsGlobImports},
|
||||||
item_tree::{
|
item_tree::{
|
||||||
self, FileItemTreeId, ItemTree, ItemTreeId, MacroCall, Mod, ModItem, ModKind, StructDefKind,
|
self, FileItemTreeId, ItemTree, ItemTreeId, MacroCall, Mod, ModItem, ModKind, StructDefKind,
|
||||||
},
|
},
|
||||||
|
@ -81,7 +81,7 @@ pub(super) fn collect_defs(db: &dyn DefDatabase, mut def_map: CrateDefMap) -> Cr
|
||||||
mod_dirs: FxHashMap::default(),
|
mod_dirs: FxHashMap::default(),
|
||||||
cfg_options,
|
cfg_options,
|
||||||
proc_macros,
|
proc_macros,
|
||||||
import_types: FxHashMap::default(),
|
from_glob_import: Default::default(),
|
||||||
};
|
};
|
||||||
collector.collect();
|
collector.collect();
|
||||||
collector.finish()
|
collector.finish()
|
||||||
|
@ -188,7 +188,7 @@ struct DefCollector<'a> {
|
||||||
mod_dirs: FxHashMap<LocalModuleId, ModDir>,
|
mod_dirs: FxHashMap<LocalModuleId, ModDir>,
|
||||||
cfg_options: &'a CfgOptions,
|
cfg_options: &'a CfgOptions,
|
||||||
proc_macros: Vec<(Name, ProcMacroExpander)>,
|
proc_macros: Vec<(Name, ProcMacroExpander)>,
|
||||||
import_types: FxHashMap<Name, ImportType>,
|
from_glob_import: PerNsGlobImports,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DefCollector<'_> {
|
impl DefCollector<'_> {
|
||||||
|
@ -595,9 +595,9 @@ impl DefCollector<'_> {
|
||||||
let scope = &mut self.def_map.modules[module_id].scope;
|
let scope = &mut self.def_map.modules[module_id].scope;
|
||||||
let mut changed = false;
|
let mut changed = false;
|
||||||
for (name, res) in resolutions {
|
for (name, res) in resolutions {
|
||||||
changed |= scope.push_res(
|
changed |= scope.push_res_with_import(
|
||||||
&mut self.import_types,
|
&mut self.from_glob_import,
|
||||||
name.clone(),
|
(module_id, name.clone()),
|
||||||
res.with_visibility(vis),
|
res.with_visibility(vis),
|
||||||
import_type,
|
import_type,
|
||||||
);
|
);
|
||||||
|
@ -1184,7 +1184,7 @@ mod tests {
|
||||||
mod_dirs: FxHashMap::default(),
|
mod_dirs: FxHashMap::default(),
|
||||||
cfg_options: &CfgOptions::default(),
|
cfg_options: &CfgOptions::default(),
|
||||||
proc_macros: Default::default(),
|
proc_macros: Default::default(),
|
||||||
import_types: FxHashMap::default(),
|
from_glob_import: Default::default(),
|
||||||
};
|
};
|
||||||
collector.collect();
|
collector.collect();
|
||||||
collector.def_map
|
collector.def_map
|
||||||
|
|
|
@ -1739,6 +1739,52 @@ fn main() {
|
||||||
assert_eq!(t, "u32");
|
assert_eq!(t, "u32");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This test is actually testing the shadowing behavior within ra_hir_def. It
|
||||||
|
// lives here because the testing infrastructure in ra_hir_def isn't currently
|
||||||
|
// capable of asserting the necessary conditions.
|
||||||
|
#[test]
|
||||||
|
fn should_be_shadowing_imports() {
|
||||||
|
let t = type_at(
|
||||||
|
r#"
|
||||||
|
mod a {
|
||||||
|
pub fn foo() -> i8 {0}
|
||||||
|
pub struct foo { a: i8 }
|
||||||
|
}
|
||||||
|
mod b { pub fn foo () -> u8 {0} }
|
||||||
|
mod c { pub struct foo { a: u8 } }
|
||||||
|
mod d {
|
||||||
|
pub use super::a::*;
|
||||||
|
pub use super::c::foo;
|
||||||
|
pub use super::b::foo;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
d::foo()<|>;
|
||||||
|
}"#,
|
||||||
|
);
|
||||||
|
assert_eq!(t, "u8");
|
||||||
|
|
||||||
|
let t = type_at(
|
||||||
|
r#"
|
||||||
|
mod a {
|
||||||
|
pub fn foo() -> i8 {0}
|
||||||
|
pub struct foo { a: i8 }
|
||||||
|
}
|
||||||
|
mod b { pub fn foo () -> u8 {0} }
|
||||||
|
mod c { pub struct foo { a: u8 } }
|
||||||
|
mod d {
|
||||||
|
pub use super::a::*;
|
||||||
|
pub use super::c::foo;
|
||||||
|
pub use super::b::foo;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
d::foo{a:0<|>};
|
||||||
|
}"#,
|
||||||
|
);
|
||||||
|
assert_eq!(t, "u8");
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn closure_return() {
|
fn closure_return() {
|
||||||
assert_snapshot!(
|
assert_snapshot!(
|
||||||
|
|
Loading…
Reference in a new issue