implement inherited_visibility in collector

This commit is contained in:
Hongxu Xu 2022-06-14 23:23:15 +08:00
parent 3f60e71a12
commit ded412d56b
6 changed files with 153 additions and 85 deletions

View file

@ -15,8 +15,8 @@ use crate::{
type_ref::{TraitRef, TypeBound, TypeRef}, type_ref::{TraitRef, TypeBound, TypeRef},
visibility::RawVisibility, visibility::RawVisibility,
AssocItemId, AstIdWithPath, ConstId, ConstLoc, FunctionId, FunctionLoc, HasModule, ImplId, AssocItemId, AstIdWithPath, ConstId, ConstLoc, FunctionId, FunctionLoc, HasModule, ImplId,
Intern, ItemContainerId, Lookup, Macro2Id, MacroRulesId, ModuleId, ProcMacroId, StaticId, InheritedVisibilityLoc, Intern, ItemContainerId, Lookup, Macro2Id, MacroRulesId, ModuleId,
TraitId, TypeAliasId, TypeAliasLoc, ProcMacroId, StaticId, TraitId, TypeAliasId, TypeAliasLoc,
}; };
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
@ -41,6 +41,12 @@ impl FunctionData {
let item_tree = loc.id.item_tree(db); let item_tree = loc.id.item_tree(db);
let func = &item_tree[loc.id.value]; let func = &item_tree[loc.id.value];
let visibility = if let Some(inherited_vis) = loc.inherited_visibility {
inherited_vis.tree_id.item_tree(db)[inherited_vis.raw_visibility_id].clone()
} else {
item_tree[func.visibility].clone()
};
let enabled_params = func let enabled_params = func
.params .params
.clone() .clone()
@ -93,7 +99,7 @@ impl FunctionData {
ret_type: func.ret_type.clone(), ret_type: func.ret_type.clone(),
async_ret_type: func.async_ret_type.clone(), async_ret_type: func.async_ret_type.clone(),
attrs: item_tree.attrs(db, krate, ModItem::from(loc.id.value).into()), attrs: item_tree.attrs(db, krate, ModItem::from(loc.id.value).into()),
visibility: item_tree[func.visibility].clone(), visibility,
abi: func.abi.clone(), abi: func.abi.clone(),
legacy_const_generics_indices, legacy_const_generics_indices,
flags, flags,
@ -171,11 +177,16 @@ impl TypeAliasData {
let loc = typ.lookup(db); let loc = typ.lookup(db);
let item_tree = loc.id.item_tree(db); let item_tree = loc.id.item_tree(db);
let typ = &item_tree[loc.id.value]; let typ = &item_tree[loc.id.value];
let visibility = if let Some(inherited_vis) = loc.inherited_visibility {
inherited_vis.tree_id.item_tree(db)[inherited_vis.raw_visibility_id].clone()
} else {
item_tree[typ.visibility].clone()
};
Arc::new(TypeAliasData { Arc::new(TypeAliasData {
name: typ.name.clone(), name: typ.name.clone(),
type_ref: typ.type_ref.clone(), type_ref: typ.type_ref.clone(),
visibility: item_tree[typ.visibility].clone(), visibility,
is_extern: matches!(loc.container, ItemContainerId::ExternBlockId(_)), is_extern: matches!(loc.container, ItemContainerId::ExternBlockId(_)),
bounds: typ.bounds.to_vec(), bounds: typ.bounds.to_vec(),
}) })
@ -221,6 +232,7 @@ impl TraitData {
module_id, module_id,
tr_loc.id.file_id(), tr_loc.id.file_id(),
ItemContainerId::TraitId(tr), ItemContainerId::TraitId(tr),
Some(InheritedVisibilityLoc::new(tr_def.visibility, tr_loc.id.tree_id())),
); );
collector.collect(tr_loc.id.tree_id(), &tr_def.items); collector.collect(tr_loc.id.tree_id(), &tr_def.items);
@ -288,6 +300,7 @@ impl ImplData {
module_id, module_id,
impl_loc.id.file_id(), impl_loc.id.file_id(),
ItemContainerId::ImplId(id), ItemContainerId::ImplId(id),
None,
); );
collector.collect(impl_loc.id.tree_id(), &impl_def.items); collector.collect(impl_loc.id.tree_id(), &impl_def.items);
@ -385,11 +398,16 @@ impl ConstData {
let loc = konst.lookup(db); let loc = konst.lookup(db);
let item_tree = loc.id.item_tree(db); let item_tree = loc.id.item_tree(db);
let konst = &item_tree[loc.id.value]; let konst = &item_tree[loc.id.value];
let visibility = if let Some(inherited_vis) = loc.inherited_visibility {
inherited_vis.tree_id.item_tree(db)[inherited_vis.raw_visibility_id].clone()
} else {
item_tree[konst.visibility].clone()
};
Arc::new(ConstData { Arc::new(ConstData {
name: konst.name.clone(), name: konst.name.clone(),
type_ref: konst.type_ref.clone(), type_ref: konst.type_ref.clone(),
visibility: item_tree[konst.visibility].clone(), visibility,
}) })
} }
} }
@ -428,6 +446,8 @@ struct AssocItemCollector<'a> {
items: Vec<(Name, AssocItemId)>, items: Vec<(Name, AssocItemId)>,
attr_calls: Vec<(AstId<ast::Item>, MacroCallId)>, attr_calls: Vec<(AstId<ast::Item>, MacroCallId)>,
inherited_visibility: Option<InheritedVisibilityLoc>,
} }
impl<'a> AssocItemCollector<'a> { impl<'a> AssocItemCollector<'a> {
@ -436,6 +456,7 @@ impl<'a> AssocItemCollector<'a> {
module_id: ModuleId, module_id: ModuleId,
file_id: HirFileId, file_id: HirFileId,
container: ItemContainerId, container: ItemContainerId,
inherited_visibility: Option<InheritedVisibilityLoc>,
) -> Self { ) -> Self {
Self { Self {
db, db,
@ -446,6 +467,8 @@ impl<'a> AssocItemCollector<'a> {
items: Vec::new(), items: Vec::new(),
attr_calls: Vec::new(), attr_calls: Vec::new(),
inherited_visibility,
} }
} }
@ -488,8 +511,11 @@ impl<'a> AssocItemCollector<'a> {
match item { match item {
AssocItem::Function(id) => { AssocItem::Function(id) => {
let item = &item_tree[id]; let item = &item_tree[id];
let def = let def = FunctionLoc {
FunctionLoc { container: self.container, id: ItemTreeId::new(tree_id, id) } container: self.container,
id: ItemTreeId::new(tree_id, id),
inherited_visibility: self.inherited_visibility,
}
.intern(self.db); .intern(self.db);
self.items.push((item.name.clone(), def.into())); self.items.push((item.name.clone(), def.into()));
} }
@ -499,8 +525,11 @@ impl<'a> AssocItemCollector<'a> {
Some(name) => name, Some(name) => name,
None => continue, None => continue,
}; };
let def = let def = ConstLoc {
ConstLoc { container: self.container, id: ItemTreeId::new(tree_id, id) } container: self.container,
id: ItemTreeId::new(tree_id, id),
inherited_visibility: self.inherited_visibility,
}
.intern(self.db); .intern(self.db);
self.items.push((name, def.into())); self.items.push((name, def.into()));
} }
@ -509,6 +538,7 @@ impl<'a> AssocItemCollector<'a> {
let def = TypeAliasLoc { let def = TypeAliasLoc {
container: self.container, container: self.container,
id: ItemTreeId::new(tree_id, id), id: ItemTreeId::new(tree_id, id),
inherited_visibility: self.inherited_visibility,
} }
.intern(self.db); .intern(self.db);
self.items.push((item.name.clone(), def.into())); self.items.push((item.name.clone(), def.into()));

View file

@ -1,6 +1,6 @@
//! AST -> `ItemTree` lowering code. //! AST -> `ItemTree` lowering code.
use std::{collections::hash_map::Entry, mem, sync::Arc}; use std::{collections::hash_map::Entry, sync::Arc};
use hir_expand::{ast_id_map::AstIdMap, hygiene::Hygiene, HirFileId}; use hir_expand::{ast_id_map::AstIdMap, hygiene::Hygiene, HirFileId};
use syntax::ast::{self, HasModuleItem}; use syntax::ast::{self, HasModuleItem};

View file

@ -359,39 +359,39 @@ trait Tr<'a, T: 'a>: Super where Self: for<'a> Tr<'a, T> {}
) )
} }
#[test] // #[test]
fn inherit_visibility() { // fn inherit_visibility() {
check( // check(
r#" // r#"
pub(crate) enum En { // pub(crate) enum En {
Var1(u8), // Var1(u8),
Var2 { // Var2 {
fld: u8, // fld: u8,
}, // },
} // }
pub(crate) trait Tr { // pub(crate) trait Tr {
fn f(); // fn f();
fn method(&self) {} // fn method(&self) {}
} // }
"#, // "#,
expect![[r#" // expect![[r#"
pub(crate) enum En { // pub(crate) enum En {
Var1( // Var1(
pub(crate) 0: u8, // pub(crate) 0: u8,
), // ),
Var2 { // Var2 {
pub(crate) fld: u8, // pub(crate) fld: u8,
}, // },
} // }
pub(crate) trait Tr<Self> { // pub(crate) trait Tr<Self> {
pub(crate) fn f() -> (); // pub(crate) fn f() -> ();
pub(crate) fn method( // pub(crate) fn method(
_: &Self, // self // _: &Self, // self
) -> () { ... } // ) -> () { ... }
} // }
"#]], // "#]],
) // )
} // }

View file

@ -70,7 +70,7 @@ use hir_expand::{
AstId, ExpandError, ExpandTo, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefId, AstId, ExpandError, ExpandTo, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefId,
MacroDefKind, UnresolvedMacro, MacroDefKind, UnresolvedMacro,
}; };
use item_tree::ExternBlock; use item_tree::{ExternBlock, RawVisibilityId, TreeId};
use la_arena::Idx; use la_arena::Idx;
use nameres::DefMap; use nameres::DefMap;
use stdx::impl_from; use stdx::impl_from;
@ -156,20 +156,25 @@ impl<N: ItemTreeNode> Hash for ItemLoc<N> {
} }
} }
#[derive(Debug)] #[derive(Debug, Clone, Copy)]
pub struct InheritedVisibilityLoc {
pub raw_visibility_id: RawVisibilityId,
pub tree_id: TreeId,
}
impl InheritedVisibilityLoc {
pub fn new(visibility_id: RawVisibilityId, tree_id: TreeId) -> Self {
Self { raw_visibility_id: visibility_id, tree_id }
}
}
#[derive(Debug, Clone, Copy)]
pub struct AssocItemLoc<N: ItemTreeNode> { pub struct AssocItemLoc<N: ItemTreeNode> {
pub container: ItemContainerId, pub container: ItemContainerId,
pub id: ItemTreeId<N>, pub id: ItemTreeId<N>,
pub inherited_visibility: Option<InheritedVisibilityLoc>,
} }
impl<N: ItemTreeNode> Clone for AssocItemLoc<N> {
fn clone(&self) -> Self {
Self { container: self.container, id: self.id }
}
}
impl<N: ItemTreeNode> Copy for AssocItemLoc<N> {}
impl<N: ItemTreeNode> PartialEq for AssocItemLoc<N> { impl<N: ItemTreeNode> PartialEq for AssocItemLoc<N> {
fn eq(&self, other: &Self) -> bool { fn eq(&self, other: &Self) -> bool {
self.container == other.container && self.id == other.id self.container == other.container && self.id == other.id

View file

@ -1549,8 +1549,12 @@ impl ModCollector<'_, '_> {
} }
ModItem::Function(id) => { ModItem::Function(id) => {
let it = &self.item_tree[id]; let it = &self.item_tree[id];
let fn_id = let fn_id = FunctionLoc {
FunctionLoc { container, id: ItemTreeId::new(self.tree_id, id) }.intern(db); container,
id: ItemTreeId::new(self.tree_id, id),
inherited_visibility: None,
}
.intern(db);
let vis = resolve_vis(def_map, &self.item_tree[it.visibility]); let vis = resolve_vis(def_map, &self.item_tree[it.visibility]);
if self.def_collector.is_proc_macro { if self.def_collector.is_proc_macro {
@ -1613,8 +1617,12 @@ impl ModCollector<'_, '_> {
} }
ModItem::Const(id) => { ModItem::Const(id) => {
let it = &self.item_tree[id]; let it = &self.item_tree[id];
let const_id = let const_id = ConstLoc {
ConstLoc { container, id: ItemTreeId::new(self.tree_id, id) }.intern(db); container,
id: ItemTreeId::new(self.tree_id, id),
inherited_visibility: None,
}
.intern(db);
match &it.name { match &it.name {
Some(name) => { Some(name) => {
@ -1635,7 +1643,11 @@ impl ModCollector<'_, '_> {
let vis = resolve_vis(def_map, &self.item_tree[it.visibility]); let vis = resolve_vis(def_map, &self.item_tree[it.visibility]);
update_def( update_def(
self.def_collector, self.def_collector,
StaticLoc { container, id: ItemTreeId::new(self.tree_id, id) } StaticLoc {
container,
id: ItemTreeId::new(self.tree_id, id),
inherited_visibility: None,
}
.intern(db) .intern(db)
.into(), .into(),
&it.name, &it.name,
@ -1663,7 +1675,11 @@ impl ModCollector<'_, '_> {
let vis = resolve_vis(def_map, &self.item_tree[it.visibility]); let vis = resolve_vis(def_map, &self.item_tree[it.visibility]);
update_def( update_def(
self.def_collector, self.def_collector,
TypeAliasLoc { container, id: ItemTreeId::new(self.tree_id, id) } TypeAliasLoc {
container,
id: ItemTreeId::new(self.tree_id, id),
inherited_visibility: None,
}
.intern(db) .intern(db)
.into(), .into(),
&it.name, &it.name,

View file

@ -13,7 +13,7 @@ fn check(ra_fixture: &str, expect: Expect) {
} }
fn check_with_config(config: CompletionConfig, ra_fixture: &str, expect: Expect) { fn check_with_config(config: CompletionConfig, ra_fixture: &str, expect: Expect) {
let actual = completion_list_with_config(config, ra_fixture, true, None); let actual = completion_list_with_config(config, ra_fixture, false, None);
expect.assert_eq(&actual) expect.assert_eq(&actual)
} }
@ -679,20 +679,10 @@ fn main() {
expect![[r#" expect![[r#"
me by_macro() (as MyTrait) fn(&self) me by_macro() (as MyTrait) fn(&self)
me not_by_macro() (as MyTrait) fn(&self) me not_by_macro() (as MyTrait) fn(&self)
sn box Box::new(expr)
sn call function(expr)
sn dbg dbg!(expr)
sn dbgr dbg!(&expr)
sn let let
sn letm let mut
sn match match expr {}
sn ref &expr
sn refm &mut expr
"#]], "#]],
) )
} }
#[test] #[test]
fn completes_fn_in_pub_trait_generated_by_recursive_macro() { fn completes_fn_in_pub_trait_generated_by_recursive_macro() {
let mut config = TEST_CONFIG.clone(); let mut config = TEST_CONFIG.clone();
@ -733,15 +723,42 @@ fn main() {
expect![[r#" expect![[r#"
me by_macro() (as MyTrait) fn(&self) me by_macro() (as MyTrait) fn(&self)
me not_by_macro() (as MyTrait) fn(&self) me not_by_macro() (as MyTrait) fn(&self)
sn box Box::new(expr) "#]],
sn call function(expr) )
sn dbg dbg!(expr) }
sn dbgr dbg!(&expr)
sn let let #[test]
sn letm let mut fn completes_const_in_pub_trait_generated_by_macro() {
sn match match expr {} let mut config = TEST_CONFIG.clone();
sn ref &expr config.enable_private_editable = false;
sn refm &mut expr
check_with_config(
config,
r#"
mod other_mod {
macro_rules! make_const {
($name:ident) => {
const $name: u8 = 1;
};
}
pub trait MyTrait {
make_const! { by_macro }
}
pub struct Foo {}
impl MyTrait for Foo {}
}
fn main() {
use other_mod::{Foo, MyTrait};
let f = Foo {};
Foo::$0
}
"#,
expect![[r#"
ct by_macro (as MyTrait) pub const by_macro: u8
"#]], "#]],
) )
} }