internal: Refactor FamousDefs builtin crate search

This commit is contained in:
Lukas Wirth 2022-03-26 21:22:35 +01:00
parent 259182b50b
commit ef92453dfe
16 changed files with 146 additions and 105 deletions

View File

@ -10,7 +10,7 @@
use vfs::{file_set::FileSet, VfsPath};
use crate::{
input::{CrateName, CrateOrigin},
input::{CrateName, CrateOrigin, LangCrateOrigin},
Change, CrateDisplayName, CrateGraph, CrateId, Dependency, Edition, Env, FileId, FilePosition,
FileRange, ProcMacro, ProcMacroExpander, ProcMacroExpansionError, SourceDatabaseExt,
SourceRoot, SourceRootId,
@ -196,7 +196,7 @@ pub fn parse_with_proc_macros(
Env::default(),
Default::default(),
false,
Default::default(),
CrateOrigin::CratesIo { repo: None },
);
} else {
for (from, to, prelude) in crate_deps {
@ -233,7 +233,7 @@ pub fn parse_with_proc_macros(
Env::default(),
Vec::new(),
false,
CrateOrigin::Lang,
CrateOrigin::Lang(LangCrateOrigin::Core),
);
for krate in all_crates {
@ -270,7 +270,7 @@ pub fn parse_with_proc_macros(
Env::default(),
proc_macro,
true,
CrateOrigin::Lang,
CrateOrigin::CratesIo { repo: None },
);
for krate in all_crates {
@ -406,7 +406,11 @@ fn parse_crate(crate_str: String) -> (String, CrateOrigin, Option<String>) {
};
(a.to_owned(), origin, Some(version.to_string()))
} else {
(crate_str, CrateOrigin::Unknown, None)
let crate_origin = match &*crate_str {
"std" => CrateOrigin::Lang(LangCrateOrigin::Std),
_ => CrateOrigin::CratesIo { repo: None },
};
(crate_str, crate_origin, None)
}
}

View File

@ -117,21 +117,22 @@ fn deref(&self) -> &str {
}
/// Origin of the crates. It is used in emitting monikers.
#[derive(Debug, Clone)]
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum CrateOrigin {
/// Crates that are from crates.io official registry,
CratesIo { repo: Option<String> },
/// Crates that are provided by the language, like std, core, proc-macro, ...
Lang,
/// Crates that we don't know their origin.
// Ideally this enum should cover all cases, and then we remove this variant.
Unknown,
Lang(LangCrateOrigin),
}
impl Default for CrateOrigin {
fn default() -> Self {
Self::Unknown
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum LangCrateOrigin {
Alloc,
Core,
ProcMacro,
Std,
Test,
Other,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
@ -585,6 +586,8 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
#[cfg(test)]
mod tests {
use crate::CrateOrigin;
use super::{CfgOptions, CrateGraph, CrateName, Dependency, Edition::Edition2018, Env, FileId};
#[test]
@ -600,7 +603,7 @@ fn detect_cyclic_dependency_indirect() {
Env::default(),
Default::default(),
false,
Default::default(),
CrateOrigin::CratesIo { repo: None },
);
let crate2 = graph.add_crate_root(
FileId(2u32),
@ -612,7 +615,7 @@ fn detect_cyclic_dependency_indirect() {
Env::default(),
Default::default(),
false,
Default::default(),
CrateOrigin::CratesIo { repo: None },
);
let crate3 = graph.add_crate_root(
FileId(3u32),
@ -624,7 +627,7 @@ fn detect_cyclic_dependency_indirect() {
Env::default(),
Default::default(),
false,
Default::default(),
CrateOrigin::CratesIo { repo: None },
);
assert!(graph
.add_dep(crate1, Dependency::new(CrateName::new("crate2").unwrap(), crate2))
@ -650,7 +653,7 @@ fn detect_cyclic_dependency_direct() {
Env::default(),
Default::default(),
false,
Default::default(),
CrateOrigin::CratesIo { repo: None },
);
let crate2 = graph.add_crate_root(
FileId(2u32),
@ -662,7 +665,7 @@ fn detect_cyclic_dependency_direct() {
Env::default(),
Default::default(),
false,
Default::default(),
CrateOrigin::CratesIo { repo: None },
);
assert!(graph
.add_dep(crate1, Dependency::new(CrateName::new("crate2").unwrap(), crate2))
@ -685,7 +688,7 @@ fn it_works() {
Env::default(),
Default::default(),
false,
Default::default(),
CrateOrigin::CratesIo { repo: None },
);
let crate2 = graph.add_crate_root(
FileId(2u32),
@ -697,7 +700,7 @@ fn it_works() {
Env::default(),
Default::default(),
false,
Default::default(),
CrateOrigin::CratesIo { repo: None },
);
let crate3 = graph.add_crate_root(
FileId(3u32),
@ -709,7 +712,7 @@ fn it_works() {
Env::default(),
Default::default(),
false,
Default::default(),
CrateOrigin::CratesIo { repo: None },
);
assert!(graph
.add_dep(crate1, Dependency::new(CrateName::new("crate2").unwrap(), crate2))
@ -732,7 +735,7 @@ fn dashes_are_normalized() {
Env::default(),
Default::default(),
false,
Default::default(),
CrateOrigin::CratesIo { repo: None },
);
let crate2 = graph.add_crate_root(
FileId(2u32),
@ -744,7 +747,7 @@ fn dashes_are_normalized() {
Env::default(),
Default::default(),
false,
Default::default(),
CrateOrigin::CratesIo { repo: None },
);
assert!(graph
.add_dep(

View File

@ -12,8 +12,8 @@
change::Change,
input::{
CrateData, CrateDisplayName, CrateGraph, CrateId, CrateName, CrateOrigin, Dependency,
Edition, Env, ProcMacro, ProcMacroExpander, ProcMacroExpansionError, ProcMacroId,
ProcMacroKind, SourceRoot, SourceRootId,
Edition, Env, LangCrateOrigin, ProcMacro, ProcMacroExpander, ProcMacroExpansionError,
ProcMacroId, ProcMacroKind, SourceRoot, SourceRootId,
},
};
pub use salsa::{self, Cancelled};

View File

@ -148,6 +148,10 @@ pub fn origin(self, db: &dyn HirDatabase) -> CrateOrigin {
db.crate_graph()[self.id].origin.clone()
}
pub fn is_builtin(self, db: &dyn HirDatabase) -> bool {
matches!(self.origin(db), CrateOrigin::Lang(_))
}
pub fn dependencies(self, db: &dyn HirDatabase) -> Vec<CrateDependency> {
db.crate_graph()[self.id]
.dependencies
@ -155,7 +159,7 @@ pub fn dependencies(self, db: &dyn HirDatabase) -> Vec<CrateDependency> {
.map(|dep| {
let krate = Crate { id: dep.crate_id };
let name = dep.as_name();
CrateDependency { krate, name }
CrateDependency { krate, name, }
})
.collect()
}
@ -1741,10 +1745,8 @@ pub fn str() -> BuiltinType {
BuiltinType { inner: hir_def::builtin_type::BuiltinType::Str }
}
pub fn ty(self, db: &dyn HirDatabase, module: Module) -> Type {
let resolver = module.id.resolver(db.upcast());
Type::new_with_resolver(db, &resolver, TyBuilder::builtin(self.inner))
.expect("crate not present in resolver")
pub fn ty(self, db: &dyn HirDatabase) -> Type {
Type::new_for_crate(db.crate_graph().iter().next().unwrap(), TyBuilder::builtin(self.inner))
}
pub fn name(self) -> Name {
@ -2619,6 +2621,7 @@ pub(crate) fn new_with_resolver(
let krate = resolver.krate()?;
Some(Type::new_with_resolver_inner(db, krate, resolver, ty))
}
pub(crate) fn new_with_resolver_inner(
db: &dyn HirDatabase,
krate: CrateId,
@ -2631,6 +2634,10 @@ pub(crate) fn new_with_resolver_inner(
Type { krate, env: environment, ty }
}
pub(crate) fn new_for_crate(krate: CrateId, ty: Ty) -> Type {
Type { krate, env: Arc::new(TraitEnvironment::empty(krate)), ty }
}
pub fn reference(inner: &Type, m: Mutability) -> Type {
inner.derived(
TyKind::Ref(

View File

@ -63,10 +63,7 @@ pub(crate) fn goto_implementation(
Definition::Trait(trait_) => impls_for_trait(&sema, trait_),
Definition::Adt(adt) => impls_for_ty(&sema, adt.ty(sema.db)),
Definition::TypeAlias(alias) => impls_for_ty(&sema, alias.ty(sema.db)),
Definition::BuiltinType(builtin) => {
let module = sema.to_module_def(position.file_id)?;
impls_for_ty(&sema, builtin.ty(sema.db, module))
}
Definition::BuiltinType(builtin) => impls_for_ty(&sema, builtin.ty(sema.db)),
Definition::Function(f) => {
let assoc = f.as_assoc_item(sema.db)?;
let name = assoc.name(sema.db)?;

View File

@ -64,7 +64,7 @@ macro_rules! eprintln {
use ide_db::{
base_db::{
salsa::{self, ParallelDatabase},
Env, FileLoader, FileSet, SourceDatabase, VfsPath,
CrateOrigin, Env, FileLoader, FileSet, SourceDatabase, VfsPath,
},
symbol_index, LineIndexDatabase,
};
@ -232,7 +232,7 @@ pub fn from_single_file(text: String) -> (Analysis, FileId) {
Env::default(),
Default::default(),
false,
Default::default(),
CrateOrigin::CratesIo { repo: None },
);
change.change_file(file_id, Some(Arc::new(text)));
change.set_crate_graph(crate_graph);

View File

@ -3,7 +3,7 @@
use hir::{db::DefDatabase, AsAssocItem, AssocItemContainer, Crate, Name, Semantics};
use ide_db::{
base_db::{CrateOrigin, FileId, FileLoader, FilePosition},
base_db::{CrateOrigin, FileId, FileLoader, FilePosition, LangCrateOrigin},
defs::{Definition, IdentClass},
helpers::pick_best_token,
RootDatabase,
@ -151,11 +151,20 @@ pub(crate) fn def_to_moniker(
let name = krate.display_name(db)?.to_string();
let (repo, version) = match krate.origin(db) {
CrateOrigin::CratesIo { repo } => (repo?, krate.version(db)?),
CrateOrigin::Lang => (
CrateOrigin::Lang(lang) => (
"https://github.com/rust-lang/rust/".to_string(),
"compiler_version".to_string(),
format!(
"https://github.com/rust-lang/rust/library/{}",
match lang {
LangCrateOrigin::Alloc => "alloc",
LangCrateOrigin::Core => "core",
LangCrateOrigin::ProcMacro => "proc_macro",
LangCrateOrigin::Std => "std",
LangCrateOrigin::Test => "test",
LangCrateOrigin::Other => "",
}
),
),
CrateOrigin::Unknown => return None,
};
PackageInformation { name, repo, version }
},

View File

@ -3,7 +3,6 @@
use hir::{AsAssocItem, HasVisibility, Semantics};
use ide_db::{
defs::{Definition, IdentClass, NameClass, NameRefClass},
famous_defs::FamousDefs,
RootDatabase, SymbolKind,
};
use rustc_hash::FxHashMap;
@ -472,14 +471,12 @@ fn highlight_def(
Definition::ToolModule(_) => Highlight::new(HlTag::Symbol(SymbolKind::ToolModule)),
};
let famous_defs = FamousDefs(sema, krate);
let def_crate = def.module(db).map(hir::Module::krate).or_else(|| match def {
Definition::Module(module) => Some(module.krate()),
_ => None,
});
let is_from_other_crate = def_crate != krate;
let is_from_builtin_crate =
def_crate.map_or(false, |def_crate| famous_defs.builtin_crates().any(|it| def_crate == it));
let is_from_builtin_crate = def_crate.map_or(false, |def_crate| def_crate.is_builtin(db));
let is_builtin_type = matches!(def, Definition::BuiltinType(_));
let is_public = def.visibility(db) == Some(hir::Visibility::Public);
@ -525,10 +522,9 @@ fn highlight_method_call(
h |= HlMod::Trait;
}
let famous_defs = FamousDefs(sema, krate);
let def_crate = func.module(sema.db).krate();
let is_from_other_crate = Some(def_crate) != krate;
let is_from_builtin_crate = famous_defs.builtin_crates().any(|it| def_crate == it);
let is_from_builtin_crate = def_crate.is_builtin(sema.db);
let is_public = func.visibility(sema.db) == hir::Visibility::Public;
if is_from_other_crate {

View File

@ -43,5 +43,5 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
</style>
<pre><code><span class="keyword">extern</span> <span class="keyword">crate</span> <span class="module crate_root default_library library">std</span><span class="semicolon">;</span>
<span class="keyword">extern</span> <span class="keyword">crate</span> <span class="module crate_root default_library library">alloc</span> <span class="keyword">as</span> <span class="module crate_root default_library declaration library">abc</span><span class="semicolon">;</span>
<span class="keyword">extern</span> <span class="keyword">crate</span> <span class="module crate_root library">alloc</span> <span class="keyword">as</span> <span class="module crate_root declaration library">abc</span><span class="semicolon">;</span>
</code></pre>

View File

@ -600,8 +600,7 @@ fn handle_as_ref_str(
db: &dyn HirDatabase,
famous_defs: &FamousDefs,
) -> Option<ReferenceConversionType> {
let module = famous_defs.1?.root_module(db);
let str_type = hir::BuiltinType::str().ty(db, module);
let str_type = hir::BuiltinType::str().ty(db);
ty.impls_trait(db, famous_defs.core_convert_AsRef()?, &[str_type])
.then(|| ReferenceConversionType::AsRefStr)

View File

@ -159,13 +159,7 @@ fn pattern_path_completion(
hir::PathResolution::Def(hir::ModuleDef::Adt(hir::Adt::Union(u))) => {
u.ty(ctx.db)
}
hir::PathResolution::Def(hir::ModuleDef::BuiltinType(ty)) => {
let module = match ctx.module {
Some(m) => m,
None => return,
};
ty.ty(ctx.db, module)
}
hir::PathResolution::Def(hir::ModuleDef::BuiltinType(ty)) => ty.ty(ctx.db),
_ => return,
};

View File

@ -1,7 +1,6 @@
//! Completion of paths, i.e. `some::prefix::$0`.
use hir::{ScopeDef, Trait};
use ide_db::famous_defs::FamousDefs;
use rustc_hash::FxHashSet;
use syntax::ast;
@ -26,7 +25,7 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
};
let traits_in_scope = |ctx: &CompletionContext| {
let mut traits_in_scope = ctx.scope.visible_traits();
if let Some(drop) = FamousDefs(&ctx.sema, ctx.krate).core_ops_Drop() {
if let Some(drop) = ctx.famous_defs().core_ops_Drop() {
traits_in_scope.remove(&drop.into());
}
traits_in_scope
@ -133,12 +132,8 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
ty
}
hir::ModuleDef::BuiltinType(builtin) => {
let module = match ctx.module {
Some(it) => it,
None => return,
};
cov_mark::hit!(completes_primitive_assoc_const);
builtin.ty(ctx.db, module)
builtin.ty(ctx.db)
}
_ => unreachable!(),
};

View File

@ -1,4 +1,6 @@
//! See [`FamousDefs`].
use base_db::{CrateOrigin, LangCrateOrigin, SourceDatabase};
use hir::{Crate, Enum, Macro, Module, ScopeDef, Semantics, Trait};
use crate::RootDatabase;
@ -21,11 +23,23 @@
#[allow(non_snake_case)]
impl FamousDefs<'_, '_> {
pub fn std(&self) -> Option<Crate> {
self.find_crate("std")
self.find_lang_crate(LangCrateOrigin::Std)
}
pub fn core(&self) -> Option<Crate> {
self.find_crate("core")
self.find_lang_crate(LangCrateOrigin::Core)
}
pub fn alloc(&self) -> Option<Crate> {
self.find_lang_crate(LangCrateOrigin::Alloc)
}
pub fn test(&self) -> Option<Crate> {
self.find_lang_crate(LangCrateOrigin::Test)
}
pub fn proc_macro(&self) -> Option<Crate> {
self.find_lang_crate(LangCrateOrigin::ProcMacro)
}
pub fn core_cmp_Ord(&self) -> Option<Trait> {
@ -88,18 +102,6 @@ pub fn core_macros_builtin_derive(&self) -> Option<Macro> {
self.find_macro("core:macros:builtin:derive")
}
pub fn alloc(&self) -> Option<Crate> {
self.find_crate("alloc")
}
pub fn test(&self) -> Option<Crate> {
self.find_crate("test")
}
pub fn proc_macro(&self) -> Option<Crate> {
self.find_crate("proc_macro")
}
pub fn builtin_crates(&self) -> impl Iterator<Item = Crate> {
IntoIterator::into_iter([
self.std(),
@ -139,11 +141,15 @@ fn find_module(&self, path: &str) -> Option<Module> {
}
}
fn find_crate(&self, name: &str) -> Option<Crate> {
fn find_lang_crate(&self, origin: LangCrateOrigin) -> Option<Crate> {
let krate = self.1?;
let db = self.0.db;
let res =
krate.dependencies(db).into_iter().find(|dep| dep.name.to_smol_str() == name)?.krate;
let crate_graph = self.0.db.crate_graph();
let res = krate
.dependencies(db)
.into_iter()
.find(|dep| crate_graph[dep.krate.into()].origin == CrateOrigin::Lang(origin))?
.krate;
Some(res)
}
@ -151,8 +157,16 @@ fn find_def(&self, path: &str) -> Option<ScopeDef> {
let db = self.0.db;
let mut path = path.split(':');
let trait_ = path.next_back()?;
let std_crate = path.next()?;
let std_crate = self.find_crate(std_crate)?;
let lang_crate = path.next()?;
let lang_crate = match lang_crate {
"core" => LangCrateOrigin::Core,
"alloc" => LangCrateOrigin::Alloc,
"test" => LangCrateOrigin::Test,
"proc_macro" => LangCrateOrigin::ProcMacro,
"std" => LangCrateOrigin::Std,
_ => return None,
};
let std_crate = self.find_lang_crate(lang_crate)?;
let mut module = std_crate.root_module(db);
for segment in path {
module = module.children(db).find_map(|child| {

View File

@ -734,13 +734,7 @@ fn def_to_ty(sema: &Semantics<RootDatabase>, def: &Definition) -> Option<hir::Ty
match def {
Definition::Adt(adt) => Some(adt.ty(sema.db)),
Definition::TypeAlias(it) => Some(it.ty(sema.db)),
Definition::BuiltinType(it) => {
let graph = sema.db.crate_graph();
let krate = graph.iter().next()?;
let root_file = graph[krate].root_file_id;
let module = sema.to_module_def(root_file)?;
Some(it.ty(sema.db, module))
}
Definition::BuiltinType(it) => Some(it.ty(sema.db)),
Definition::SelfType(it) => Some(it.self_ty(sema.db)),
_ => None,
}

View File

@ -1261,7 +1261,9 @@ fn rust_project_hello_world_project_model() {
},
],
proc_macro: [],
origin: Lang,
origin: Lang(
Alloc,
),
is_proc_macro: false,
},
CrateId(
@ -1291,7 +1293,9 @@ fn rust_project_hello_world_project_model() {
},
dependencies: [],
proc_macro: [],
origin: Lang,
origin: Lang(
Other,
),
is_proc_macro: false,
},
CrateId(
@ -1321,7 +1325,9 @@ fn rust_project_hello_world_project_model() {
},
dependencies: [],
proc_macro: [],
origin: Lang,
origin: Lang(
Other,
),
is_proc_macro: false,
},
CrateId(
@ -1361,7 +1367,9 @@ fn rust_project_hello_world_project_model() {
},
],
proc_macro: [],
origin: Lang,
origin: Lang(
ProcMacro,
),
is_proc_macro: false,
},
CrateId(
@ -1391,7 +1399,9 @@ fn rust_project_hello_world_project_model() {
},
dependencies: [],
proc_macro: [],
origin: Lang,
origin: Lang(
Core,
),
is_proc_macro: false,
},
CrateId(
@ -1490,7 +1500,9 @@ fn rust_project_hello_world_project_model() {
},
dependencies: [],
proc_macro: [],
origin: Lang,
origin: Lang(
Other,
),
is_proc_macro: false,
},
CrateId(
@ -1520,7 +1532,9 @@ fn rust_project_hello_world_project_model() {
},
dependencies: [],
proc_macro: [],
origin: Lang,
origin: Lang(
Other,
),
is_proc_macro: false,
},
CrateId(
@ -1550,7 +1564,9 @@ fn rust_project_hello_world_project_model() {
},
dependencies: [],
proc_macro: [],
origin: Lang,
origin: Lang(
Other,
),
is_proc_macro: false,
},
CrateId(
@ -1580,7 +1596,9 @@ fn rust_project_hello_world_project_model() {
},
dependencies: [],
proc_macro: [],
origin: Lang,
origin: Lang(
Test,
),
is_proc_macro: false,
},
CrateId(
@ -1692,7 +1710,9 @@ fn rust_project_hello_world_project_model() {
},
],
proc_macro: [],
origin: Lang,
origin: Lang(
Std,
),
is_proc_macro: false,
},
CrateId(
@ -1722,7 +1742,9 @@ fn rust_project_hello_world_project_model() {
},
dependencies: [],
proc_macro: [],
origin: Lang,
origin: Lang(
Other,
),
is_proc_macro: false,
},
},

View File

@ -7,7 +7,7 @@
use anyhow::{format_err, Context, Result};
use base_db::{
CrateDisplayName, CrateGraph, CrateId, CrateName, CrateOrigin, Dependency, Edition, Env,
FileId, ProcMacro,
FileId, LangCrateOrigin, ProcMacro,
};
use cfg::{CfgDiff, CfgOptions};
use paths::{AbsPath, AbsPathBuf};
@ -487,7 +487,7 @@ fn project_json_to_crate_graph(
if krate.display_name.is_some() {
CrateOrigin::CratesIo { repo: krate.repository.clone() }
} else {
CrateOrigin::Unknown
CrateOrigin::CratesIo { repo: None }
},
),
)
@ -710,7 +710,7 @@ fn detached_files_to_crate_graph(
Env::default(),
Vec::new(),
false,
CrateOrigin::Unknown,
CrateOrigin::CratesIo { repo: None },
);
public_deps.add(detached_file_crate, &mut crate_graph);
@ -908,7 +908,14 @@ fn sysroot_to_crate_graph(
env,
proc_macro,
false,
CrateOrigin::Lang,
CrateOrigin::Lang(match &*sysroot[krate].name {
"alloc" => LangCrateOrigin::Alloc,
"core" => LangCrateOrigin::Core,
"proc_macro" => LangCrateOrigin::ProcMacro,
"std" => LangCrateOrigin::Std,
"test" => LangCrateOrigin::Test,
_ => LangCrateOrigin::Other,
}),
);
Some((krate, crate_id))
})