Collect visibility of items during nameres

This commit is contained in:
Florian Diebold 2019-12-24 23:45:14 +01:00
parent c31dae2aca
commit 79c90b5641
6 changed files with 63 additions and 19 deletions

View File

@ -21,6 +21,7 @@ use crate::{
nameres::{BuiltinShadowMode, CrateDefMap}, nameres::{BuiltinShadowMode, CrateDefMap},
path::{ModPath, PathKind}, path::{ModPath, PathKind},
per_ns::PerNs, per_ns::PerNs,
visibility::{ResolvedVisibility, Visibility},
AdtId, CrateId, EnumVariantId, LocalModuleId, ModuleDefId, ModuleId, AdtId, CrateId, EnumVariantId, LocalModuleId, ModuleDefId, ModuleId,
}; };
@ -64,6 +65,32 @@ impl CrateDefMap {
self.extern_prelude.get(name).map_or(PerNs::none(), |&it| PerNs::types(it)) self.extern_prelude.get(name).map_or(PerNs::none(), |&it| PerNs::types(it))
} }
pub(crate) fn resolve_visibility(
&self,
db: &impl DefDatabase,
original_module: LocalModuleId,
visibility: &Visibility,
) -> Option<ResolvedVisibility> {
match visibility {
Visibility::Module(path) => {
let (result, remaining) =
self.resolve_path(db, original_module, &path, BuiltinShadowMode::Module);
if remaining.is_some() {
return None;
}
let types = result.take_types()?;
match types {
ModuleDefId::ModuleId(m) => Some(ResolvedVisibility::Module(m)),
_ => {
// error: visibility needs to refer to module
None
}
}
}
Visibility::Public => Some(ResolvedVisibility::Public),
}
}
// Returns Yes if we are sure that additions to `ItemMap` wouldn't change // Returns Yes if we are sure that additions to `ItemMap` wouldn't change
// the result. // the result.
pub(super) fn resolve_path_fp_with_macro( pub(super) fn resolve_path_fp_with_macro(

View File

@ -16,12 +16,15 @@ use hir_expand::{
use ra_arena::{impl_arena_id, Arena, RawId}; use ra_arena::{impl_arena_id, Arena, RawId};
use ra_prof::profile; use ra_prof::profile;
use ra_syntax::{ use ra_syntax::{
ast::{self, AttrsOwner, NameOwner}, ast::{self, AttrsOwner, NameOwner, VisibilityOwner},
AstNode, AstNode,
}; };
use test_utils::tested_by; use test_utils::tested_by;
use crate::{attr::Attrs, db::DefDatabase, path::ModPath, FileAstId, HirFileId, InFile}; use crate::{
attr::Attrs, db::DefDatabase, path::ModPath, visibility::Visibility, FileAstId, HirFileId,
InFile,
};
/// `RawItems` is a set of top-level items in a file (except for impls). /// `RawItems` is a set of top-level items in a file (except for impls).
/// ///
@ -138,6 +141,7 @@ pub struct ImportData {
pub(super) is_prelude: bool, pub(super) is_prelude: bool,
pub(super) is_extern_crate: bool, pub(super) is_extern_crate: bool,
pub(super) is_macro_use: bool, pub(super) is_macro_use: bool,
pub(super) visibility: Visibility,
} }
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@ -148,6 +152,7 @@ impl_arena_id!(Def);
pub(super) struct DefData { pub(super) struct DefData {
pub(super) name: Name, pub(super) name: Name,
pub(super) kind: DefKind, pub(super) kind: DefKind,
pub(super) visibility: Visibility,
} }
#[derive(Debug, PartialEq, Eq, Clone, Copy)] #[derive(Debug, PartialEq, Eq, Clone, Copy)]
@ -218,6 +223,7 @@ impl RawItemsCollector {
fn add_item(&mut self, current_module: Option<Module>, item: ast::ModuleItem) { fn add_item(&mut self, current_module: Option<Module>, item: ast::ModuleItem) {
let attrs = self.parse_attrs(&item); let attrs = self.parse_attrs(&item);
let visibility = Visibility::from_ast_with_hygiene(item.visibility(), &self.hygiene);
let (kind, name) = match item { let (kind, name) = match item {
ast::ModuleItem::Module(module) => { ast::ModuleItem::Module(module) => {
self.add_module(current_module, module); self.add_module(current_module, module);
@ -266,7 +272,7 @@ impl RawItemsCollector {
}; };
if let Some(name) = name { if let Some(name) = name {
let name = name.as_name(); let name = name.as_name();
let def = self.raw_items.defs.alloc(DefData { name, kind }); let def = self.raw_items.defs.alloc(DefData { name, kind, visibility });
self.push_item(current_module, attrs, RawItemKind::Def(def)); self.push_item(current_module, attrs, RawItemKind::Def(def));
} }
} }
@ -302,6 +308,7 @@ impl RawItemsCollector {
// FIXME: cfg_attr // FIXME: cfg_attr
let is_prelude = use_item.has_atom_attr("prelude_import"); let is_prelude = use_item.has_atom_attr("prelude_import");
let attrs = self.parse_attrs(&use_item); let attrs = self.parse_attrs(&use_item);
let visibility = Visibility::from_ast_with_hygiene(use_item.visibility(), &self.hygiene);
let mut buf = Vec::new(); let mut buf = Vec::new();
ModPath::expand_use_item( ModPath::expand_use_item(
@ -315,6 +322,7 @@ impl RawItemsCollector {
is_prelude, is_prelude,
is_extern_crate: false, is_extern_crate: false,
is_macro_use: false, is_macro_use: false,
visibility: visibility.clone(),
}; };
buf.push(import_data); buf.push(import_data);
}, },
@ -331,6 +339,8 @@ impl RawItemsCollector {
) { ) {
if let Some(name_ref) = extern_crate.name_ref() { if let Some(name_ref) = extern_crate.name_ref() {
let path = ModPath::from_name_ref(&name_ref); let path = ModPath::from_name_ref(&name_ref);
let visibility =
Visibility::from_ast_with_hygiene(extern_crate.visibility(), &self.hygiene);
let alias = extern_crate.alias().and_then(|a| a.name()).map(|it| it.as_name()); let alias = extern_crate.alias().and_then(|a| a.name()).map(|it| it.as_name());
let attrs = self.parse_attrs(&extern_crate); let attrs = self.parse_attrs(&extern_crate);
// FIXME: cfg_attr // FIXME: cfg_attr
@ -342,6 +352,7 @@ impl RawItemsCollector {
is_prelude: false, is_prelude: false,
is_extern_crate: true, is_extern_crate: true,
is_macro_use, is_macro_use,
visibility,
}; };
self.push_import(current_module, attrs, import_data); self.push_import(current_module, attrs, import_data);
} }

View File

@ -238,15 +238,12 @@ impl Resolver {
visibility: &Visibility, visibility: &Visibility,
) -> Option<ResolvedVisibility> { ) -> Option<ResolvedVisibility> {
match visibility { match visibility {
Visibility::Module(mod_path) => { Visibility::Module(_) => {
let resolved = self.resolve_module_path_in_items(db, &mod_path).take_types()?; let (item_map, module) = match self.module() {
match resolved { Some(it) => it,
ModuleDefId::ModuleId(m) => Some(ResolvedVisibility::Module(m)), None => return None,
_ => { };
// error: visibility needs to refer to module item_map.resolve_visibility(db, module, visibility)
None
}
}
} }
Visibility::Public => Some(ResolvedVisibility::Public), Visibility::Public => Some(ResolvedVisibility::Public),
} }

View File

@ -4,7 +4,7 @@ use std::sync::Arc;
use either::Either; use either::Either;
use hir_expand::InFile; use hir_expand::{hygiene::Hygiene, InFile};
use ra_syntax::ast::{self, VisibilityOwner}; use ra_syntax::ast::{self, VisibilityOwner};
use crate::{ use crate::{
@ -73,14 +73,20 @@ impl Visibility {
} }
fn from_ast(db: &impl DefDatabase, node: InFile<Option<ast::Visibility>>) -> Visibility { fn from_ast(db: &impl DefDatabase, node: InFile<Option<ast::Visibility>>) -> Visibility {
let file_id = node.file_id; Self::from_ast_with_hygiene(node.value, &Hygiene::new(db, node.file_id))
let node = match node.value { }
pub(crate) fn from_ast_with_hygiene(
node: Option<ast::Visibility>,
hygiene: &Hygiene,
) -> Visibility {
let node = match node {
None => return Visibility::private(), None => return Visibility::private(),
Some(node) => node, Some(node) => node,
}; };
match node.kind() { match node.kind() {
ast::VisibilityKind::In(path) => { ast::VisibilityKind::In(path) => {
let path = ModPath::from_src(path, &hir_expand::hygiene::Hygiene::new(db, file_id)); let path = ModPath::from_src(path, hygiene);
let path = match path { let path = match path {
None => return Visibility::private(), None => return Visibility::private(),
Some(path) => path, Some(path) => path,

View File

@ -1064,6 +1064,7 @@ impl AstNode for ExternCrateItem {
} }
} }
impl ast::AttrsOwner for ExternCrateItem {} impl ast::AttrsOwner for ExternCrateItem {}
impl ast::VisibilityOwner for ExternCrateItem {}
impl ExternCrateItem { impl ExternCrateItem {
pub fn name_ref(&self) -> Option<NameRef> { pub fn name_ref(&self) -> Option<NameRef> {
AstChildren::new(&self.syntax).next() AstChildren::new(&self.syntax).next()
@ -2006,6 +2007,7 @@ impl AstNode for ModuleItem {
} }
} }
impl ast::AttrsOwner for ModuleItem {} impl ast::AttrsOwner for ModuleItem {}
impl ast::VisibilityOwner for ModuleItem {}
impl ModuleItem {} impl ModuleItem {}
#[derive(Debug, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Name { pub struct Name {
@ -3893,6 +3895,7 @@ impl AstNode for UseItem {
} }
} }
impl ast::AttrsOwner for UseItem {} impl ast::AttrsOwner for UseItem {}
impl ast::VisibilityOwner for UseItem {}
impl UseItem { impl UseItem {
pub fn use_tree(&self) -> Option<UseTree> { pub fn use_tree(&self) -> Option<UseTree> {
AstChildren::new(&self.syntax).next() AstChildren::new(&self.syntax).next()

View File

@ -412,7 +412,7 @@ Grammar(
"ModuleItem": ( "ModuleItem": (
enum: ["StructDef", "UnionDef", "EnumDef", "FnDef", "TraitDef", "TypeAliasDef", "ImplBlock", enum: ["StructDef", "UnionDef", "EnumDef", "FnDef", "TraitDef", "TypeAliasDef", "ImplBlock",
"UseItem", "ExternCrateItem", "ConstDef", "StaticDef", "Module" ], "UseItem", "ExternCrateItem", "ConstDef", "StaticDef", "Module" ],
traits: ["AttrsOwner"], traits: ["AttrsOwner", "VisibilityOwner"],
), ),
"ImplItem": ( "ImplItem": (
enum: ["FnDef", "TypeAliasDef", "ConstDef"], enum: ["FnDef", "TypeAliasDef", "ConstDef"],
@ -683,7 +683,7 @@ Grammar(
] ]
), ),
"UseItem": ( "UseItem": (
traits: ["AttrsOwner"], traits: ["AttrsOwner", "VisibilityOwner"],
options: [ "UseTree" ], options: [ "UseTree" ],
), ),
"UseTree": ( "UseTree": (
@ -696,7 +696,7 @@ Grammar(
collections: [("use_trees", "UseTree")] collections: [("use_trees", "UseTree")]
), ),
"ExternCrateItem": ( "ExternCrateItem": (
traits: ["AttrsOwner"], traits: ["AttrsOwner", "VisibilityOwner"],
options: ["NameRef", "Alias"], options: ["NameRef", "Alias"],
), ),
"ArgList": ( "ArgList": (