Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir/src/symbols.rs')
-rw-r--r--crates/hir/src/symbols.rs90
1 files changed, 60 insertions, 30 deletions
diff --git a/crates/hir/src/symbols.rs b/crates/hir/src/symbols.rs
index d8c624e5c6..073142670d 100644
--- a/crates/hir/src/symbols.rs
+++ b/crates/hir/src/symbols.rs
@@ -1,5 +1,7 @@
//! File symbol extraction.
+use std::marker::PhantomData;
+
use base_db::FxIndexSet;
use either::Either;
use hir_def::{
@@ -18,23 +20,24 @@ use hir_ty::{
};
use intern::Symbol;
use rustc_hash::FxHashMap;
-use syntax::{AstNode, AstPtr, SmolStr, SyntaxNode, SyntaxNodePtr, ToSmolStr, ast::HasName};
+use syntax::{AstNode, AstPtr, SyntaxNode, SyntaxNodePtr, ToSmolStr, ast::HasName};
use crate::{HasCrate, Module, ModuleDef, Semantics};
/// The actual data that is stored in the index. It should be as compact as
/// possible.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct FileSymbol {
+pub struct FileSymbol<'db> {
pub name: Symbol,
pub def: ModuleDef,
pub loc: DeclarationLocation,
- pub container_name: Option<SmolStr>,
+ pub container_name: Option<Symbol>,
/// Whether this symbol is a doc alias for the original symbol.
pub is_alias: bool,
pub is_assoc: bool,
pub is_import: bool,
pub do_not_complete: Complete,
+ _marker: PhantomData<&'db ()>,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -61,27 +64,33 @@ struct SymbolCollectorWork {
parent: Option<Name>,
}
-pub struct SymbolCollector<'a> {
- db: &'a dyn HirDatabase,
- symbols: FxIndexSet<FileSymbol>,
+pub struct SymbolCollector<'db> {
+ db: &'db dyn HirDatabase,
+ symbols: FxIndexSet<FileSymbol<'db>>,
work: Vec<SymbolCollectorWork>,
- current_container_name: Option<SmolStr>,
+ current_container_name: Option<Symbol>,
+ collect_pub_only: bool,
}
/// Given a [`ModuleId`] and a [`HirDatabase`], use the DefMap for the module's crate to collect
/// all symbols that should be indexed for the given module.
impl<'a> SymbolCollector<'a> {
- pub fn new(db: &'a dyn HirDatabase) -> Self {
+ pub fn new(db: &'a dyn HirDatabase, collect_pub_only: bool) -> Self {
SymbolCollector {
db,
symbols: Default::default(),
work: Default::default(),
current_container_name: None,
+ collect_pub_only,
}
}
- pub fn new_module(db: &dyn HirDatabase, module: Module) -> Box<[FileSymbol]> {
- let mut symbol_collector = SymbolCollector::new(db);
+ pub fn new_module(
+ db: &'a dyn HirDatabase,
+ module: Module,
+ collect_pub_only: bool,
+ ) -> Box<[FileSymbol<'a>]> {
+ let mut symbol_collector = SymbolCollector::new(db, collect_pub_only);
symbol_collector.collect(module);
symbol_collector.finish()
}
@@ -99,7 +108,7 @@ impl<'a> SymbolCollector<'a> {
}
}
- pub fn finish(self) -> Box<[FileSymbol]> {
+ pub fn finish(self) -> Box<[FileSymbol<'a>]> {
self.symbols.into_iter().collect()
}
@@ -108,12 +117,16 @@ impl<'a> SymbolCollector<'a> {
tracing::info!(?work, "SymbolCollector::do_work");
self.db.unwind_if_revision_cancelled();
- let parent_name = work.parent.map(|name| name.as_str().to_smolstr());
+ let parent_name = work.parent.map(|name| Symbol::intern(name.as_str()));
self.with_container_name(parent_name, |s| s.collect_from_module(work.module_id));
}
fn collect_from_module(&mut self, module_id: ModuleId) {
- let push_decl = |this: &mut Self, def, name| {
+ let collect_pub_only = self.collect_pub_only;
+ let push_decl = |this: &mut Self, def: ModuleDefId, name, vis| {
+ if collect_pub_only && vis != Visibility::Public {
+ return;
+ }
match def {
ModuleDefId::ModuleId(id) => this.push_module(id, name),
ModuleDefId::FunctionId(id) => {
@@ -125,7 +138,7 @@ impl<'a> SymbolCollector<'a> {
}
ModuleDefId::AdtId(AdtId::EnumId(id)) => {
this.push_decl(id, name, false, None);
- let enum_name = this.db.enum_signature(id).name.as_str().to_smolstr();
+ let enum_name = Symbol::intern(this.db.enum_signature(id).name.as_str());
this.with_container_name(Some(enum_name), |this| {
let variants = id.enum_variants(this.db);
for (variant_id, variant_name, _) in &variants.variants {
@@ -175,6 +188,9 @@ impl<'a> SymbolCollector<'a> {
};
let mut push_import = |this: &mut Self, i: ImportId, name: &Name, def: ModuleDefId, vis| {
+ if collect_pub_only && vis != Visibility::Public {
+ return;
+ }
let source = import_child_source_cache
.entry(i.use_)
.or_insert_with(|| i.use_.child_source(this.db));
@@ -204,11 +220,15 @@ impl<'a> SymbolCollector<'a> {
is_assoc: false,
is_import: true,
do_not_complete: Complete::Yes,
+ _marker: PhantomData,
});
};
let push_extern_crate =
|this: &mut Self, i: ExternCrateId, name: &Name, def: ModuleDefId, vis| {
+ if collect_pub_only && vis != Visibility::Public {
+ return;
+ }
let loc = i.lookup(this.db);
let source = loc.source(this.db);
let rename = source.value.rename().and_then(|rename| rename.name());
@@ -235,11 +255,12 @@ impl<'a> SymbolCollector<'a> {
is_assoc: false,
is_import: false,
do_not_complete: Complete::Yes,
+ _marker: PhantomData,
});
};
let def_map = module_id.def_map(self.db);
- let scope = &def_map[module_id.local_id].scope;
+ let scope = &def_map[module_id].scope;
for impl_id in scope.impls() {
self.collect_from_impl(impl_id);
@@ -258,7 +279,7 @@ impl<'a> SymbolCollector<'a> {
continue;
}
// self is a declaration
- push_decl(self, def, name)
+ push_decl(self, def, name, vis)
}
for (name, Item { def, vis, import }) in scope.macros() {
@@ -271,7 +292,7 @@ impl<'a> SymbolCollector<'a> {
continue;
}
// self is a declaration
- push_decl(self, def.into(), name)
+ push_decl(self, ModuleDefId::MacroId(def), name, vis)
}
for (name, Item { def, vis, import }) in scope.values() {
@@ -283,7 +304,7 @@ impl<'a> SymbolCollector<'a> {
continue;
}
// self is a declaration
- push_decl(self, def, name)
+ push_decl(self, def, name, vis)
}
for const_id in scope.unnamed_consts() {
@@ -304,16 +325,16 @@ impl<'a> SymbolCollector<'a> {
}
fn collect_from_body(&mut self, body_id: impl Into<DefWithBodyId>, name: Option<Name>) {
+ if self.collect_pub_only {
+ return;
+ }
let body_id = body_id.into();
let body = self.db.body(body_id);
// Descend into the blocks and enqueue collection of all modules within.
for (_, def_map) in body.blocks(self.db) {
for (id, _) in def_map.modules() {
- self.work.push(SymbolCollectorWork {
- module_id: def_map.module_id(id),
- parent: name.clone(),
- });
+ self.work.push(SymbolCollectorWork { module_id: id, parent: name.clone() });
}
}
}
@@ -328,8 +349,13 @@ impl<'a> SymbolCollector<'a> {
)
.to_smolstr(),
);
- self.with_container_name(impl_name, |s| {
+ self.with_container_name(impl_name.as_deref().map(Symbol::intern), |s| {
for &(ref name, assoc_item_id) in &impl_id.impl_items(self.db).items {
+ if s.collect_pub_only && s.db.assoc_visibility(assoc_item_id) != Visibility::Public
+ {
+ continue;
+ }
+
s.push_assoc_item(assoc_item_id, name, None)
}
})
@@ -337,14 +363,14 @@ impl<'a> SymbolCollector<'a> {
fn collect_from_trait(&mut self, trait_id: TraitId, trait_do_not_complete: Complete) {
let trait_data = self.db.trait_signature(trait_id);
- self.with_container_name(Some(trait_data.name.as_str().into()), |s| {
+ self.with_container_name(Some(Symbol::intern(trait_data.name.as_str())), |s| {
for &(ref name, assoc_item_id) in &trait_id.trait_items(self.db).items {
s.push_assoc_item(assoc_item_id, name, Some(trait_do_not_complete));
}
});
}
- fn with_container_name(&mut self, container_name: Option<SmolStr>, f: impl FnOnce(&mut Self)) {
+ fn with_container_name(&mut self, container_name: Option<Symbol>, f: impl FnOnce(&mut Self)) {
if let Some(container_name) = container_name {
let prev = self.current_container_name.replace(container_name);
f(self);
@@ -392,12 +418,12 @@ impl<'a> SymbolCollector<'a> {
let mut do_not_complete = Complete::Yes;
if let Some(attrs) = def.attrs(self.db) {
- do_not_complete = Complete::extract(matches!(def, ModuleDef::Trait(_)), &attrs);
+ do_not_complete = Complete::extract(matches!(def, ModuleDef::Trait(_)), attrs.attrs);
if let Some(trait_do_not_complete) = trait_do_not_complete {
do_not_complete = Complete::for_trait_item(trait_do_not_complete, do_not_complete);
}
- for alias in attrs.doc_aliases() {
+ for alias in attrs.doc_aliases(self.db) {
self.symbols.insert(FileSymbol {
name: alias.clone(),
def,
@@ -407,6 +433,7 @@ impl<'a> SymbolCollector<'a> {
is_assoc,
is_import: false,
do_not_complete,
+ _marker: PhantomData,
});
}
}
@@ -420,6 +447,7 @@ impl<'a> SymbolCollector<'a> {
is_assoc,
is_import: false,
do_not_complete,
+ _marker: PhantomData,
});
do_not_complete
@@ -427,7 +455,7 @@ impl<'a> SymbolCollector<'a> {
fn push_module(&mut self, module_id: ModuleId, name: &Name) {
let def_map = module_id.def_map(self.db);
- let module_data = &def_map[module_id.local_id];
+ let module_data = &def_map[module_id];
let Some(declaration) = module_data.origin.declaration() else { return };
let module = declaration.to_node(self.db);
let Some(name_node) = module.name() else { return };
@@ -441,9 +469,9 @@ impl<'a> SymbolCollector<'a> {
let mut do_not_complete = Complete::Yes;
if let Some(attrs) = def.attrs(self.db) {
- do_not_complete = Complete::extract(matches!(def, ModuleDef::Trait(_)), &attrs);
+ do_not_complete = Complete::extract(matches!(def, ModuleDef::Trait(_)), attrs.attrs);
- for alias in attrs.doc_aliases() {
+ for alias in attrs.doc_aliases(self.db) {
self.symbols.insert(FileSymbol {
name: alias.clone(),
def,
@@ -453,6 +481,7 @@ impl<'a> SymbolCollector<'a> {
is_assoc: false,
is_import: false,
do_not_complete,
+ _marker: PhantomData,
});
}
}
@@ -466,6 +495,7 @@ impl<'a> SymbolCollector<'a> {
is_assoc: false,
is_import: false,
do_not_complete,
+ _marker: PhantomData,
});
}
}