Skip to content

Commit db8f39c

Browse files
committed
Auto merge of rust-lang#14797 - Veykril:symbol-query, r=Veykril
fix: Fix perf regression from symbol index refactor Should fix the regressions introduced by rust-lang/rust-analyzer#14715 by partially rolling back the PR
2 parents a7944a9 + 2e03b19 commit db8f39c

File tree

3 files changed

+434
-13
lines changed

3 files changed

+434
-13
lines changed

crates/hir/src/symbols.rs

+88-11
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
//! File symbol extraction.
22
3+
use base_db::FileRange;
34
use hir_def::{
4-
AdtId, AssocItemId, DefWithBodyId, HasModule, ImplId, MacroId, ModuleDefId, ModuleId, TraitId,
5+
src::HasSource, AdtId, AssocItemId, DefWithBodyId, HasModule, ImplId, Lookup, MacroId,
6+
ModuleDefId, ModuleId, TraitId,
57
};
8+
use hir_expand::{HirFileId, InFile};
69
use hir_ty::db::HirDatabase;
7-
use syntax::SmolStr;
10+
use syntax::{ast::HasName, AstNode, SmolStr, SyntaxNode, SyntaxNodePtr};
811

9-
use crate::{Module, ModuleDef};
12+
use crate::{Module, ModuleDef, Semantics};
1013

1114
/// The actual data that is stored in the index. It should be as compact as
1215
/// possible.
@@ -15,6 +18,45 @@ pub struct FileSymbol {
1518
// even though name can be derived from the def, we store it for efficiency
1619
pub name: SmolStr,
1720
pub def: ModuleDef,
21+
pub loc: DeclarationLocation,
22+
pub container_name: Option<SmolStr>,
23+
}
24+
25+
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
26+
pub struct DeclarationLocation {
27+
/// The file id for both the `ptr` and `name_ptr`.
28+
pub hir_file_id: HirFileId,
29+
/// This points to the whole syntax node of the declaration.
30+
pub ptr: SyntaxNodePtr,
31+
/// This points to the [`syntax::ast::Name`] identifier of the declaration.
32+
pub name_ptr: SyntaxNodePtr,
33+
}
34+
35+
impl DeclarationLocation {
36+
pub fn syntax<DB: HirDatabase>(&self, sema: &Semantics<'_, DB>) -> SyntaxNode {
37+
let root = sema.parse_or_expand(self.hir_file_id);
38+
self.ptr.to_node(&root)
39+
}
40+
41+
pub fn original_range(&self, db: &dyn HirDatabase) -> FileRange {
42+
let node = resolve_node(db, self.hir_file_id, &self.ptr);
43+
node.as_ref().original_file_range(db.upcast())
44+
}
45+
46+
pub fn original_name_range(&self, db: &dyn HirDatabase) -> Option<FileRange> {
47+
let node = resolve_node(db, self.hir_file_id, &self.name_ptr);
48+
node.as_ref().original_file_range_opt(db.upcast())
49+
}
50+
}
51+
52+
fn resolve_node(
53+
db: &dyn HirDatabase,
54+
file_id: HirFileId,
55+
ptr: &SyntaxNodePtr,
56+
) -> InFile<SyntaxNode> {
57+
let root = db.parse_or_expand(file_id);
58+
let node = ptr.to_node(&root);
59+
InFile::new(file_id, node)
1860
}
1961

2062
/// Represents an outstanding module that the symbol collector must collect symbols from.
@@ -193,17 +235,52 @@ impl<'a> SymbolCollector<'a> {
193235
}
194236
}
195237

196-
fn push_decl(&mut self, id: impl Into<ModuleDefId>) {
197-
let def = ModuleDef::from(id.into());
198-
if let Some(name) = def.name(self.db) {
199-
self.symbols.push(FileSymbol { name: name.to_smol_str(), def });
200-
}
238+
fn push_decl<L>(&mut self, id: L)
239+
where
240+
L: Lookup + Into<ModuleDefId>,
241+
<L as Lookup>::Data: HasSource,
242+
<<L as Lookup>::Data as HasSource>::Value: HasName,
243+
{
244+
self.push_file_symbol(|s| {
245+
let loc = id.lookup(s.db.upcast());
246+
let source = loc.source(s.db.upcast());
247+
let name_node = source.value.name()?;
248+
Some(FileSymbol {
249+
name: name_node.text().into(),
250+
def: ModuleDef::from(id.into()),
251+
container_name: s.current_container_name.clone(),
252+
loc: DeclarationLocation {
253+
hir_file_id: source.file_id,
254+
ptr: SyntaxNodePtr::new(source.value.syntax()),
255+
name_ptr: SyntaxNodePtr::new(name_node.syntax()),
256+
},
257+
})
258+
})
201259
}
202260

203261
fn push_module(&mut self, module_id: ModuleId) {
204-
let def = Module::from(module_id);
205-
if let Some(name) = def.name(self.db) {
206-
self.symbols.push(FileSymbol { name: name.to_smol_str(), def: ModuleDef::Module(def) });
262+
self.push_file_symbol(|s| {
263+
let def_map = module_id.def_map(s.db.upcast());
264+
let module_data = &def_map[module_id.local_id];
265+
let declaration = module_data.origin.declaration()?;
266+
let module = declaration.to_node(s.db.upcast());
267+
let name_node = module.name()?;
268+
Some(FileSymbol {
269+
name: name_node.text().into(),
270+
def: ModuleDef::Module(module_id.into()),
271+
container_name: s.current_container_name.clone(),
272+
loc: DeclarationLocation {
273+
hir_file_id: declaration.file_id,
274+
ptr: SyntaxNodePtr::new(module.syntax()),
275+
name_ptr: SyntaxNodePtr::new(name_node.syntax()),
276+
},
277+
})
278+
})
279+
}
280+
281+
fn push_file_symbol(&mut self, f: impl FnOnce(&Self) -> Option<FileSymbol>) {
282+
if let Some(file_symbol) = f(self) {
283+
self.symbols.push(file_symbol);
207284
}
208285
}
209286
}

0 commit comments

Comments
 (0)