This commit is contained in:
Jake Heinz 2021-11-27 11:25:05 +00:00
parent dca8f612d0
commit 0447be7589
5 changed files with 170 additions and 41 deletions

View File

@ -40,16 +40,13 @@ use hir_def::{
adt::{ReprKind, VariantData},
body::{BodyDiagnostic, SyntheticSyntax},
expr::{BindingAnnotation, LabelId, Pat, PatId},
item_tree::ItemTreeNode,
lang_item::LangItemTarget,
nameres,
per_ns::PerNs,
resolver::{HasResolver, Resolver},
src::HasSource as _,
AdtId, AssocContainerId, AssocItemId, AssocItemLoc, AttrDefId, ConstId, ConstParamId,
DefWithBodyId, EnumId, FunctionId, GenericDefId, HasModule, ImplId, LifetimeParamId,
LocalEnumVariantId, LocalFieldId, Lookup, ModuleId, StaticId, StructId, TraitId, TypeAliasId,
TypeParamId, UnionId,
AssocContainerId, AssocItemId, AttrDefId, ConstId, ConstParamId, DefWithBodyId, EnumId,
FunctionId, GenericDefId, HasModule, ImplId, LifetimeParamId, LocalEnumVariantId, LocalFieldId,
StaticId, StructId, TraitId, TypeAliasId, TypeParamId, UnionId,
};
use hir_expand::{name::name, MacroCallKind, MacroDefId, MacroDefKind};
use hir_ty::{
@ -109,10 +106,19 @@ pub use {
attr::{Attr, Attrs, AttrsWithOwner, Documentation},
find_path::PrefixKind,
import_map,
nameres::ModuleSource,
item_scope::ItemScope,
item_tree::ItemTreeNode,
nameres::{DefMap, ModuleData, ModuleOrigin, ModuleSource},
path::{ModPath, PathKind},
src::HasSource as DefHasSource, // xx: I don't like this shadowing of HasSource... :(
type_ref::{Mutability, TypeRef},
visibility::Visibility,
AdtId,
AssocItemLoc,
ItemLoc,
Lookup,
ModuleDefId,
ModuleId,
},
hir_expand::{
name::{known, Name},

View File

@ -148,7 +148,7 @@ pub enum ModuleOrigin {
}
impl ModuleOrigin {
fn declaration(&self) -> Option<AstId<ast::Module>> {
pub fn declaration(&self) -> Option<AstId<ast::Module>> {
match self {
ModuleOrigin::File { declaration: module, .. }
| ModuleOrigin::Inline { definition: module, .. } => Some(*module),

View File

@ -4,8 +4,8 @@ use std::fmt;
use either::Either;
use hir::{
AssocItem, Documentation, FieldSource, HasAttrs, HasSource, HirDisplay, InFile, ModuleSource,
Semantics,
db::AstDatabase, AssocItem, Documentation, FieldSource, HasAttrs, HasSource, HirDisplay,
InFile, ModuleSource, Semantics,
};
use ide_db::{
base_db::{FileId, FileRange},
@ -170,7 +170,7 @@ impl NavigationTarget {
impl ToNav for FileSymbol {
fn to_nav(&self, db: &RootDatabase) -> NavigationTarget {
NavigationTarget {
file_id: self.file_id,
file_id: self.file_id.original_file(db),
name: self.name.clone(),
kind: Some(match self.kind {
FileSymbolKind::Function => SymbolKind::Function,
@ -517,8 +517,8 @@ impl TryToNav for hir::ConstParam {
/// e.g. `struct Name`, `enum Name`, `fn Name`
pub(crate) fn description_from_symbol(db: &RootDatabase, symbol: &FileSymbol) -> Option<String> {
let sema = Semantics::new(db);
let parse = sema.parse(symbol.file_id);
let node = symbol.ptr.to_node(parse.syntax());
let syntax = sema.db.parse_or_expand(symbol.file_id)?;
let node = symbol.ptr.to_node(&syntax);
match_ast! {
match node {

View File

@ -4,6 +4,7 @@
//! are located in different caches, with different APIs.
use either::Either;
use hir::{
db::AstDatabase,
import_map::{self, ImportKind},
AsAssocItem, Crate, ItemInNs, Semantics,
};
@ -135,7 +136,7 @@ fn get_name_definition(
let _p = profile::span("get_name_definition");
let file_id = import_candidate.file_id;
let candidate_node = import_candidate.ptr.to_node(sema.parse(file_id).syntax());
let candidate_node = import_candidate.ptr.to_node(&sema.db.parse_or_expand(file_id)?);
let candidate_name_node = if candidate_node.kind() != NAME {
candidate_node.children().find(|it| it.kind() == NAME)?
} else {

View File

@ -33,7 +33,10 @@ use base_db::{
CrateId, FileId, SourceDatabaseExt, SourceRootId,
};
use fst::{self, Streamer};
use hir::db::DefDatabase;
use hir::{
db::DefDatabase, AdtId, AssocItemLoc, DefHasSource, HirFileId, ItemLoc, ItemScope,
ItemTreeNode, Lookup, ModuleData, ModuleDefId, ModuleId,
};
use rayon::prelude::*;
use rustc_hash::{FxHashMap, FxHashSet};
use syntax::{
@ -202,21 +205,29 @@ pub fn crate_symbols(db: &RootDatabase, krate: CrateId, query: Query) -> Vec<Fil
// that instead?
let def_map = db.crate_def_map(krate);
let mut files = Vec::new();
let mut modules = vec![def_map.root()];
while let Some(module) = modules.pop() {
let data = &def_map[module];
files.extend(data.origin.file_id());
modules.extend(data.children.values());
}
// let mut files = Vec::new();
// let mut modules = vec![def_map.root()];
// while let Some(module) = modules.pop() {
// let data = &def_map[module];
// files.extend(data.origin.file_id());
// modules.extend(data.children.values());
// }
let snap = Snap(db.snapshot());
// let snap = Snap(db.snapshot());
let buf = files
.par_iter()
.map_with(snap, |db, &file_id| db.0.file_symbols(file_id))
.collect::<Vec<_>>();
let buf = buf.iter().map(|it| &**it).collect::<Vec<_>>();
// let buf = files
// .par_iter()
// .map_with(snap, |db, &file_id| db.0.file_symbols(file_id))
// .collect::<Vec<_>>();
// todo: make this fast!!!
// how do i salsa this?
let buf: Vec<_> = def_map
.modules()
.map(|(_, module_data)| SymbolIndex::new(module_data_to_file_symbols(db, module_data)))
.collect();
let buf = buf.iter().collect::<Vec<_>>();
query.search(&buf)
}
@ -364,7 +375,7 @@ impl Query {
/// possible.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct FileSymbol {
pub file_id: FileId,
pub file_id: HirFileId,
pub name: SmolStr,
pub kind: FileSymbolKind,
pub range: TextRange,
@ -456,23 +467,134 @@ fn to_file_symbol(node: &SyntaxNode, file_id: FileId) -> Option<FileSymbol> {
to_symbol(node).map(move |(name, ptr, name_range)| FileSymbol {
name,
kind: match node.kind() {
FN => FileSymbolKind::Function,
STRUCT => FileSymbolKind::Struct,
ENUM => FileSymbolKind::Enum,
TRAIT => FileSymbolKind::Trait,
MODULE => FileSymbolKind::Module,
TYPE_ALIAS => FileSymbolKind::TypeAlias,
CONST => FileSymbolKind::Const,
STATIC => FileSymbolKind::Static,
MACRO_RULES => FileSymbolKind::Macro,
MACRO_DEF => FileSymbolKind::Macro,
UNION => FileSymbolKind::Union,
FN => FileSymbolKind::Function, // FunctionId
STRUCT => FileSymbolKind::Struct, // AdtId::StructId
ENUM => FileSymbolKind::Enum, // AdtId::EnumId
TRAIT => FileSymbolKind::Trait, // TraitId
MODULE => FileSymbolKind::Module, // ModuleId
TYPE_ALIAS => FileSymbolKind::TypeAlias, // TypeAliasId
CONST => FileSymbolKind::Const, // ConstId
STATIC => FileSymbolKind::Static, // StaticId
MACRO_RULES => FileSymbolKind::Macro, // via ItemScope::macros
MACRO_DEF => FileSymbolKind::Macro, // via ItemScope::macros
UNION => FileSymbolKind::Union, // AdtId::UnionId
kind => unreachable!("{:?}", kind),
},
range: node.text_range(),
ptr,
file_id,
file_id: file_id.into(),
name_range: Some(name_range),
container_name: None,
})
}
fn module_data_to_file_symbols(db: &dyn DefDatabase, module_data: &ModuleData) -> Vec<FileSymbol> {
let mut symbols = Vec::new();
collect_symbols_from_item_scope(db, &mut symbols, &module_data.scope);
// todo: collect macros from scope.macros().
symbols
}
fn collect_symbols_from_item_scope(
db: &dyn DefDatabase,
symbols: &mut Vec<FileSymbol>,
scope: &ItemScope,
) {
// todo: dedupe code.
fn decl_assoc<L, T>(db: &dyn DefDatabase, id: L, kind: FileSymbolKind) -> Option<FileSymbol>
where
L: Lookup<Data = AssocItemLoc<T>>,
T: ItemTreeNode,
<T as ItemTreeNode>::Source: HasName,
{
let loc = id.lookup(db);
let source = loc.source(db);
let name = source.value.name()?;
let file_id = loc.id.file_id();
let name_range = name.syntax().text_range();
let name = name.text().into();
let ptr = SyntaxNodePtr::new(source.value.syntax());
Some(FileSymbol {
name,
kind,
range: source.value.syntax().text_range(),
// todo: fill out based on loc.container.
container_name: None,
file_id,
name_range: Some(name_range),
ptr,
})
}
fn decl<L, T>(db: &dyn DefDatabase, id: L, kind: FileSymbolKind) -> Option<FileSymbol>
where
L: Lookup<Data = ItemLoc<T>>,
T: ItemTreeNode,
<T as ItemTreeNode>::Source: HasName,
{
let loc = id.lookup(db);
let source = loc.source(db);
let name = source.value.name()?;
let file_id = loc.id.file_id();
let name_range = name.syntax().text_range();
let name = name.text().into();
let ptr = SyntaxNodePtr::new(source.value.syntax());
Some(FileSymbol {
name,
kind,
range: source.value.syntax().text_range(),
container_name: None,
file_id,
name_range: Some(name_range),
ptr,
})
}
fn decl_module(db: &dyn DefDatabase, module_id: ModuleId) -> Option<FileSymbol> {
let def_map = module_id.def_map(db);
let module_data = &def_map[module_id.local_id];
let declaration = module_data.origin.declaration()?;
let file_id = match module_data.origin.file_id() {
Some(file_id) => file_id.into(),
None => declaration.file_id,
};
let module = declaration.to_node(db.upcast());
let name = module.name()?;
let name_range = name.syntax().text_range();
let name = name.text().into();
let ptr = SyntaxNodePtr::new(module.syntax());
Some(FileSymbol {
name,
kind: FileSymbolKind::Module,
range: module.syntax().text_range(),
container_name: None,
file_id,
name_range: Some(name_range),
ptr,
})
}
let symbols_iter = scope.declarations().filter_map(|module_def_id| match module_def_id {
ModuleDefId::ModuleId(module_id) => decl_module(db, module_id),
ModuleDefId::FunctionId(function_id) => {
decl_assoc(db, function_id, FileSymbolKind::Function)
}
ModuleDefId::AdtId(AdtId::StructId(struct_id)) => {
decl(db, struct_id, FileSymbolKind::Struct)
}
ModuleDefId::AdtId(AdtId::EnumId(enum_id)) => decl(db, enum_id, FileSymbolKind::Enum),
ModuleDefId::AdtId(AdtId::UnionId(union_id)) => decl(db, union_id, FileSymbolKind::Union),
ModuleDefId::EnumVariantId(_) => None,
ModuleDefId::ConstId(const_id) => decl_assoc(db, const_id, FileSymbolKind::Const),
ModuleDefId::StaticId(static_id) => decl(db, static_id, FileSymbolKind::Static),
ModuleDefId::TraitId(trait_id) => decl(db, trait_id, FileSymbolKind::Trait),
ModuleDefId::TypeAliasId(alias_id) => decl_assoc(db, alias_id, FileSymbolKind::TypeAlias),
ModuleDefId::BuiltinType(_) => None,
});
symbols.extend(symbols_iter);
}