Reduce visibility of non-proc-macros
proc-macro crates only export proc-macros, but currently other items are also considered public (and show up in completion)
This commit is contained in:
parent
069045015c
commit
baab72e611
3 changed files with 85 additions and 0 deletions
|
@ -5,10 +5,12 @@ use std::collections::hash_map::Entry;
|
|||
|
||||
use base_db::CrateId;
|
||||
use hir_expand::name::Name;
|
||||
use hir_expand::MacroDefKind;
|
||||
use once_cell::sync::Lazy;
|
||||
use rustc_hash::{FxHashMap, FxHashSet};
|
||||
use test_utils::mark;
|
||||
|
||||
use crate::ModuleId;
|
||||
use crate::{
|
||||
db::DefDatabase, per_ns::PerNs, visibility::Visibility, AdtId, BuiltinType, HasModule, ImplId,
|
||||
LocalModuleId, Lookup, MacroDefId, ModuleDefId, TraitId,
|
||||
|
@ -265,6 +267,29 @@ impl ItemScope {
|
|||
pub(crate) fn collect_legacy_macros(&self) -> FxHashMap<Name, MacroDefId> {
|
||||
self.legacy_macros.clone()
|
||||
}
|
||||
|
||||
/// Marks everything that is not a procedural macro as private to `this_module`.
|
||||
pub(crate) fn censor_non_proc_macros(&mut self, this_module: ModuleId) {
|
||||
for vis in self
|
||||
.types
|
||||
.values_mut()
|
||||
.chain(self.values.values_mut())
|
||||
.map(|(_, v)| v)
|
||||
.chain(self.unnamed_trait_imports.values_mut())
|
||||
{
|
||||
*vis = Visibility::Module(this_module);
|
||||
}
|
||||
|
||||
for (mac, vis) in self.macros.values_mut() {
|
||||
if let MacroDefKind::ProcMacro(_) = mac.kind {
|
||||
// FIXME: Technically this is insufficient since reexports of proc macros are also
|
||||
// forbidden. Practically nobody does that.
|
||||
continue;
|
||||
}
|
||||
|
||||
*vis = Visibility::Module(this_module);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PerNs {
|
||||
|
|
|
@ -87,6 +87,7 @@ pub(super) fn collect_defs(db: &dyn DefDatabase, mut def_map: CrateDefMap) -> Cr
|
|||
mod_dirs: FxHashMap::default(),
|
||||
cfg_options,
|
||||
proc_macros,
|
||||
exports_proc_macros: false,
|
||||
from_glob_import: Default::default(),
|
||||
};
|
||||
collector.collect();
|
||||
|
@ -203,6 +204,7 @@ struct DefCollector<'a> {
|
|||
mod_dirs: FxHashMap<LocalModuleId, ModDir>,
|
||||
cfg_options: &'a CfgOptions,
|
||||
proc_macros: Vec<(Name, ProcMacroExpander)>,
|
||||
exports_proc_macros: bool,
|
||||
from_glob_import: PerNsGlobImports,
|
||||
}
|
||||
|
||||
|
@ -260,9 +262,25 @@ impl DefCollector<'_> {
|
|||
self.record_resolved_import(directive)
|
||||
}
|
||||
self.unresolved_imports = unresolved_imports;
|
||||
|
||||
// FIXME: This condition should instead check if this is a `proc-macro` type crate.
|
||||
if self.exports_proc_macros {
|
||||
// A crate exporting procedural macros is not allowed to export anything else.
|
||||
//
|
||||
// Additionally, while the proc macro entry points must be `pub`, they are not publicly
|
||||
// exported in type/value namespace. This function reduces the visibility of all items
|
||||
// in the crate root that aren't proc macros.
|
||||
let root = self.def_map.root;
|
||||
let root = &mut self.def_map.modules[root];
|
||||
root.scope.censor_non_proc_macros(ModuleId {
|
||||
krate: self.def_map.krate,
|
||||
local_id: self.def_map.root,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fn resolve_proc_macro(&mut self, name: &Name) {
|
||||
self.exports_proc_macros = true;
|
||||
let macro_def = match self.proc_macros.iter().find(|(n, _)| n == name) {
|
||||
Some((_, expander)) => MacroDefId {
|
||||
ast_id: None,
|
||||
|
@ -1310,6 +1328,7 @@ mod tests {
|
|||
mod_dirs: FxHashMap::default(),
|
||||
cfg_options: &CfgOptions::default(),
|
||||
proc_macros: Default::default(),
|
||||
exports_proc_macros: false,
|
||||
from_glob_import: Default::default(),
|
||||
};
|
||||
collector.collect();
|
||||
|
|
|
@ -699,3 +699,44 @@ fn resolves_proc_macros() {
|
|||
"#]],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn proc_macro_censoring() {
|
||||
// Make sure that only proc macros are publicly exported from proc-macro crates.
|
||||
|
||||
check(
|
||||
r"
|
||||
//- /main.rs crate:main deps:macros
|
||||
pub use macros::*;
|
||||
|
||||
//- /macros.rs crate:macros
|
||||
pub struct TokenStream;
|
||||
|
||||
#[proc_macro]
|
||||
pub fn function_like_macro(args: TokenStream) -> TokenStream {
|
||||
args
|
||||
}
|
||||
|
||||
#[proc_macro_attribute]
|
||||
pub fn attribute_macro(_args: TokenStream, item: TokenStream) -> TokenStream {
|
||||
item
|
||||
}
|
||||
|
||||
#[proc_macro_derive(DummyTrait)]
|
||||
pub fn derive_macro(_item: TokenStream) -> TokenStream {
|
||||
TokenStream
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! mbe {
|
||||
() => {};
|
||||
}
|
||||
",
|
||||
expect![[r#"
|
||||
crate
|
||||
DummyTrait: m
|
||||
attribute_macro: m
|
||||
function_like_macro: m
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue