mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-13 13:48:50 +00:00
Collect visibility of items during nameres
This commit is contained in:
parent
c31dae2aca
commit
79c90b5641
6 changed files with 63 additions and 19 deletions
|
@ -21,6 +21,7 @@ use crate::{
|
|||
nameres::{BuiltinShadowMode, CrateDefMap},
|
||||
path::{ModPath, PathKind},
|
||||
per_ns::PerNs,
|
||||
visibility::{ResolvedVisibility, Visibility},
|
||||
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))
|
||||
}
|
||||
|
||||
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
|
||||
// the result.
|
||||
pub(super) fn resolve_path_fp_with_macro(
|
||||
|
|
|
@ -16,12 +16,15 @@ use hir_expand::{
|
|||
use ra_arena::{impl_arena_id, Arena, RawId};
|
||||
use ra_prof::profile;
|
||||
use ra_syntax::{
|
||||
ast::{self, AttrsOwner, NameOwner},
|
||||
ast::{self, AttrsOwner, NameOwner, VisibilityOwner},
|
||||
AstNode,
|
||||
};
|
||||
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).
|
||||
///
|
||||
|
@ -138,6 +141,7 @@ pub struct ImportData {
|
|||
pub(super) is_prelude: bool,
|
||||
pub(super) is_extern_crate: bool,
|
||||
pub(super) is_macro_use: bool,
|
||||
pub(super) visibility: Visibility,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
|
@ -148,6 +152,7 @@ impl_arena_id!(Def);
|
|||
pub(super) struct DefData {
|
||||
pub(super) name: Name,
|
||||
pub(super) kind: DefKind,
|
||||
pub(super) visibility: Visibility,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||
|
@ -218,6 +223,7 @@ impl RawItemsCollector {
|
|||
|
||||
fn add_item(&mut self, current_module: Option<Module>, item: ast::ModuleItem) {
|
||||
let attrs = self.parse_attrs(&item);
|
||||
let visibility = Visibility::from_ast_with_hygiene(item.visibility(), &self.hygiene);
|
||||
let (kind, name) = match item {
|
||||
ast::ModuleItem::Module(module) => {
|
||||
self.add_module(current_module, module);
|
||||
|
@ -266,7 +272,7 @@ impl RawItemsCollector {
|
|||
};
|
||||
if let Some(name) = 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));
|
||||
}
|
||||
}
|
||||
|
@ -302,6 +308,7 @@ impl RawItemsCollector {
|
|||
// FIXME: cfg_attr
|
||||
let is_prelude = use_item.has_atom_attr("prelude_import");
|
||||
let attrs = self.parse_attrs(&use_item);
|
||||
let visibility = Visibility::from_ast_with_hygiene(use_item.visibility(), &self.hygiene);
|
||||
|
||||
let mut buf = Vec::new();
|
||||
ModPath::expand_use_item(
|
||||
|
@ -315,6 +322,7 @@ impl RawItemsCollector {
|
|||
is_prelude,
|
||||
is_extern_crate: false,
|
||||
is_macro_use: false,
|
||||
visibility: visibility.clone(),
|
||||
};
|
||||
buf.push(import_data);
|
||||
},
|
||||
|
@ -331,6 +339,8 @@ impl RawItemsCollector {
|
|||
) {
|
||||
if let Some(name_ref) = extern_crate.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 attrs = self.parse_attrs(&extern_crate);
|
||||
// FIXME: cfg_attr
|
||||
|
@ -342,6 +352,7 @@ impl RawItemsCollector {
|
|||
is_prelude: false,
|
||||
is_extern_crate: true,
|
||||
is_macro_use,
|
||||
visibility,
|
||||
};
|
||||
self.push_import(current_module, attrs, import_data);
|
||||
}
|
||||
|
|
|
@ -238,15 +238,12 @@ impl Resolver {
|
|||
visibility: &Visibility,
|
||||
) -> Option<ResolvedVisibility> {
|
||||
match visibility {
|
||||
Visibility::Module(mod_path) => {
|
||||
let resolved = self.resolve_module_path_in_items(db, &mod_path).take_types()?;
|
||||
match resolved {
|
||||
ModuleDefId::ModuleId(m) => Some(ResolvedVisibility::Module(m)),
|
||||
_ => {
|
||||
// error: visibility needs to refer to module
|
||||
None
|
||||
}
|
||||
}
|
||||
Visibility::Module(_) => {
|
||||
let (item_map, module) = match self.module() {
|
||||
Some(it) => it,
|
||||
None => return None,
|
||||
};
|
||||
item_map.resolve_visibility(db, module, visibility)
|
||||
}
|
||||
Visibility::Public => Some(ResolvedVisibility::Public),
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ use std::sync::Arc;
|
|||
|
||||
use either::Either;
|
||||
|
||||
use hir_expand::InFile;
|
||||
use hir_expand::{hygiene::Hygiene, InFile};
|
||||
use ra_syntax::ast::{self, VisibilityOwner};
|
||||
|
||||
use crate::{
|
||||
|
@ -73,14 +73,20 @@ impl Visibility {
|
|||
}
|
||||
|
||||
fn from_ast(db: &impl DefDatabase, node: InFile<Option<ast::Visibility>>) -> Visibility {
|
||||
let file_id = node.file_id;
|
||||
let node = match node.value {
|
||||
Self::from_ast_with_hygiene(node.value, &Hygiene::new(db, node.file_id))
|
||||
}
|
||||
|
||||
pub(crate) fn from_ast_with_hygiene(
|
||||
node: Option<ast::Visibility>,
|
||||
hygiene: &Hygiene,
|
||||
) -> Visibility {
|
||||
let node = match node {
|
||||
None => return Visibility::private(),
|
||||
Some(node) => node,
|
||||
};
|
||||
match node.kind() {
|
||||
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 {
|
||||
None => return Visibility::private(),
|
||||
Some(path) => path,
|
||||
|
|
|
@ -1064,6 +1064,7 @@ impl AstNode for ExternCrateItem {
|
|||
}
|
||||
}
|
||||
impl ast::AttrsOwner for ExternCrateItem {}
|
||||
impl ast::VisibilityOwner for ExternCrateItem {}
|
||||
impl ExternCrateItem {
|
||||
pub fn name_ref(&self) -> Option<NameRef> {
|
||||
AstChildren::new(&self.syntax).next()
|
||||
|
@ -2006,6 +2007,7 @@ impl AstNode for ModuleItem {
|
|||
}
|
||||
}
|
||||
impl ast::AttrsOwner for ModuleItem {}
|
||||
impl ast::VisibilityOwner for ModuleItem {}
|
||||
impl ModuleItem {}
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct Name {
|
||||
|
@ -3893,6 +3895,7 @@ impl AstNode for UseItem {
|
|||
}
|
||||
}
|
||||
impl ast::AttrsOwner for UseItem {}
|
||||
impl ast::VisibilityOwner for UseItem {}
|
||||
impl UseItem {
|
||||
pub fn use_tree(&self) -> Option<UseTree> {
|
||||
AstChildren::new(&self.syntax).next()
|
||||
|
|
|
@ -412,7 +412,7 @@ Grammar(
|
|||
"ModuleItem": (
|
||||
enum: ["StructDef", "UnionDef", "EnumDef", "FnDef", "TraitDef", "TypeAliasDef", "ImplBlock",
|
||||
"UseItem", "ExternCrateItem", "ConstDef", "StaticDef", "Module" ],
|
||||
traits: ["AttrsOwner"],
|
||||
traits: ["AttrsOwner", "VisibilityOwner"],
|
||||
),
|
||||
"ImplItem": (
|
||||
enum: ["FnDef", "TypeAliasDef", "ConstDef"],
|
||||
|
@ -683,7 +683,7 @@ Grammar(
|
|||
]
|
||||
),
|
||||
"UseItem": (
|
||||
traits: ["AttrsOwner"],
|
||||
traits: ["AttrsOwner", "VisibilityOwner"],
|
||||
options: [ "UseTree" ],
|
||||
),
|
||||
"UseTree": (
|
||||
|
@ -696,7 +696,7 @@ Grammar(
|
|||
collections: [("use_trees", "UseTree")]
|
||||
),
|
||||
"ExternCrateItem": (
|
||||
traits: ["AttrsOwner"],
|
||||
traits: ["AttrsOwner", "VisibilityOwner"],
|
||||
options: ["NameRef", "Alias"],
|
||||
),
|
||||
"ArgList": (
|
||||
|
|
Loading…
Reference in a new issue