Include vendored crates in StaticIndex

StaticIndex::compute filters out modules from libraries. This makes an
exceptions for vendored libraries, ie libraries actually defined inside
the workspace being indexed.

This aims to solve https://bugzilla.mozilla.org/show_bug.cgi?id=1846041
In general StaticIndex is meant for code browsers, which likely want to
index all visible source files.
This commit is contained in:
Nicolas Guichard 2024-08-02 19:55:37 +02:00
parent b23142209e
commit 6dcc4e34c2
3 changed files with 54 additions and 24 deletions

View file

@ -3,9 +3,12 @@
use hir::{db::HirDatabase, Crate, HirFileIdExt, Module, Semantics}; use hir::{db::HirDatabase, Crate, HirFileIdExt, Module, Semantics};
use ide_db::{ use ide_db::{
base_db::SourceRootDatabase, defs::Definition, documentation::Documentation, base_db::{SourceRootDatabase, VfsPath},
famous_defs::FamousDefs, helpers::get_definition, FileId, FileRange, FxHashMap, FxHashSet, defs::Definition,
RootDatabase, documentation::Documentation,
famous_defs::FamousDefs,
helpers::get_definition,
FileId, FileRange, FxHashMap, FxHashSet, RootDatabase,
}; };
use syntax::{AstNode, SyntaxKind::*, SyntaxNode, TextRange, T}; use syntax::{AstNode, SyntaxKind::*, SyntaxNode, TextRange, T};
@ -227,13 +230,16 @@ impl StaticIndex<'_> {
self.files.push(result); self.files.push(result);
} }
pub fn compute(analysis: &Analysis) -> StaticIndex<'_> { pub fn compute<'a>(analysis: &'a Analysis, workspace_root: &VfsPath) -> StaticIndex<'a> {
let db = &*analysis.db; let db = &*analysis.db;
let work = all_modules(db).into_iter().filter(|module| { let work = all_modules(db).into_iter().filter(|module| {
let file_id = module.definition_source_file_id(db).original_file(db); let file_id = module.definition_source_file_id(db).original_file(db);
let source_root = db.file_source_root(file_id.into()); let source_root = db.file_source_root(file_id.into());
let source_root = db.source_root(source_root); let source_root = db.source_root(source_root);
!source_root.is_library let is_vendored = source_root
.path_for_file(&file_id.into())
.is_some_and(|module_path| module_path.starts_with(workspace_root));
!source_root.is_library || is_vendored
}); });
let mut this = StaticIndex { let mut this = StaticIndex {
files: vec![], files: vec![],
@ -259,12 +265,13 @@ impl StaticIndex<'_> {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::{fixture, StaticIndex}; use crate::{fixture, StaticIndex};
use ide_db::{FileRange, FxHashSet}; use ide_db::{base_db::VfsPath, FileRange, FxHashSet};
use syntax::TextSize; use syntax::TextSize;
fn check_all_ranges(ra_fixture: &str) { fn check_all_ranges(ra_fixture: &str) {
let (analysis, ranges) = fixture::annotations_without_marker(ra_fixture); let (analysis, ranges) = fixture::annotations_without_marker(ra_fixture);
let s = StaticIndex::compute(&analysis); let s =
StaticIndex::compute(&analysis, &VfsPath::new_virtual_path("/workspace".to_owned()));
let mut range_set: FxHashSet<_> = ranges.iter().map(|it| it.0).collect(); let mut range_set: FxHashSet<_> = ranges.iter().map(|it| it.0).collect();
for f in s.files { for f in s.files {
for (range, _) in f.tokens { for (range, _) in f.tokens {
@ -283,7 +290,8 @@ mod tests {
#[track_caller] #[track_caller]
fn check_definitions(ra_fixture: &str) { fn check_definitions(ra_fixture: &str) {
let (analysis, ranges) = fixture::annotations_without_marker(ra_fixture); let (analysis, ranges) = fixture::annotations_without_marker(ra_fixture);
let s = StaticIndex::compute(&analysis); let s =
StaticIndex::compute(&analysis, &VfsPath::new_virtual_path("/workspace".to_owned()));
let mut range_set: FxHashSet<_> = ranges.iter().map(|it| it.0).collect(); let mut range_set: FxHashSet<_> = ranges.iter().map(|it| it.0).collect();
for (_, t) in s.tokens.iter() { for (_, t) in s.tokens.iter() {
if let Some(t) = t.definition { if let Some(t) = t.definition {
@ -326,7 +334,7 @@ enum E { X(Foo) }
fn multi_crate() { fn multi_crate() {
check_definitions( check_definitions(
r#" r#"
//- /main.rs crate:main deps:foo //- /workspace/main.rs crate:main deps:foo
use foo::func; use foo::func;
@ -335,7 +343,7 @@ fn main() {
//^^^^ //^^^^
func(); func();
} }
//- /foo/lib.rs crate:foo //- /workspace/foo/lib.rs crate:foo
pub func() { pub func() {
@ -344,6 +352,24 @@ pub func() {
); );
} }
#[test]
fn vendored_crate() {
check_all_ranges(
r#"
//- /workspace/main.rs crate:main deps:external,vendored
struct Main(i32);
//^^^^ ^^^
//- /external/lib.rs new_source_root:library crate:external@0.1.0,https://a.b/foo.git library
struct ExternalLibrary(i32);
//- /workspace/vendored/lib.rs new_source_root:library crate:vendored@0.1.0,https://a.b/bar.git library
struct VendoredLibrary(i32);
//^^^^^^^^^^^^^^^ ^^^
"#,
);
}
#[test] #[test]
fn derives() { fn derives() {
check_all_ranges( check_all_ranges(

View file

@ -287,6 +287,7 @@ impl flags::Lsif {
let manifest = ProjectManifest::discover_single(&path)?; let manifest = ProjectManifest::discover_single(&path)?;
let workspace = ProjectWorkspace::load(manifest, &cargo_config, no_progress)?; let workspace = ProjectWorkspace::load(manifest, &cargo_config, no_progress)?;
let root = workspace.workspace_root().to_owned();
let (db, vfs, _proc_macro) = let (db, vfs, _proc_macro) =
load_workspace(workspace, &cargo_config.extra_env, &load_cargo_config)?; load_workspace(workspace, &cargo_config.extra_env, &load_cargo_config)?;
@ -294,7 +295,7 @@ impl flags::Lsif {
let db = host.raw_database(); let db = host.raw_database();
let analysis = host.analysis(); let analysis = host.analysis();
let si = StaticIndex::compute(&analysis); let si = StaticIndex::compute(&analysis, &root.into());
let mut lsif = LsifManager::new(&analysis, db, &vfs); let mut lsif = LsifManager::new(&analysis, db, &vfs);
lsif.add_vertex(lsif::Vertex::MetaData(lsif::MetaData { lsif.add_vertex(lsif::Vertex::MetaData(lsif::MetaData {

View file

@ -63,7 +63,7 @@ impl flags::Scip {
let db = host.raw_database(); let db = host.raw_database();
let analysis = host.analysis(); let analysis = host.analysis();
let si = StaticIndex::compute(&analysis); let si = StaticIndex::compute(&analysis, &root.clone().into());
let metadata = scip_types::Metadata { let metadata = scip_types::Metadata {
version: scip_types::ProtocolVersion::UnspecifiedProtocolVersion.into(), version: scip_types::ProtocolVersion::UnspecifiedProtocolVersion.into(),
@ -334,6 +334,7 @@ mod test {
use ide::{FilePosition, TextSize}; use ide::{FilePosition, TextSize};
use scip::symbol::format_symbol; use scip::symbol::format_symbol;
use test_fixture::ChangeFixture; use test_fixture::ChangeFixture;
use vfs::VfsPath;
fn position(ra_fixture: &str) -> (AnalysisHost, FilePosition) { fn position(ra_fixture: &str) -> (AnalysisHost, FilePosition) {
let mut host = AnalysisHost::default(); let mut host = AnalysisHost::default();
@ -351,7 +352,8 @@ mod test {
let (host, position) = position(ra_fixture); let (host, position) = position(ra_fixture);
let analysis = host.analysis(); let analysis = host.analysis();
let si = StaticIndex::compute(&analysis); let si =
StaticIndex::compute(&analysis, &VfsPath::new_virtual_path("/workspace".to_owned()));
let FilePosition { file_id, offset } = position; let FilePosition { file_id, offset } = position;
@ -384,7 +386,7 @@ mod test {
fn basic() { fn basic() {
check_symbol( check_symbol(
r#" r#"
//- /lib.rs crate:main deps:foo //- /workspace/lib.rs crate:main deps:foo
use foo::example_mod::func; use foo::example_mod::func;
fn main() { fn main() {
func$0(); func$0();
@ -485,7 +487,7 @@ pub mod module {
fn symbol_for_field() { fn symbol_for_field() {
check_symbol( check_symbol(
r#" r#"
//- /lib.rs crate:main deps:foo //- /workspace/lib.rs crate:main deps:foo
use foo::St; use foo::St;
fn main() { fn main() {
let x = St { a$0: 2 }; let x = St { a$0: 2 };
@ -503,7 +505,7 @@ pub mod module {
fn symbol_for_param() { fn symbol_for_param() {
check_symbol( check_symbol(
r#" r#"
//- /lib.rs crate:main deps:foo //- /workspace/lib.rs crate:main deps:foo
use foo::example_mod::func; use foo::example_mod::func;
fn main() { fn main() {
func(42); func(42);
@ -521,7 +523,7 @@ pub mod example_mod {
fn symbol_for_closure_param() { fn symbol_for_closure_param() {
check_symbol( check_symbol(
r#" r#"
//- /lib.rs crate:main deps:foo //- /workspace/lib.rs crate:main deps:foo
use foo::example_mod::func; use foo::example_mod::func;
fn main() { fn main() {
func(); func();
@ -541,7 +543,7 @@ pub mod example_mod {
fn local_symbol_for_local() { fn local_symbol_for_local() {
check_symbol( check_symbol(
r#" r#"
//- /lib.rs crate:main deps:foo //- /workspace/lib.rs crate:main deps:foo
use foo::module::func; use foo::module::func;
fn main() { fn main() {
func(); func();
@ -561,13 +563,13 @@ pub mod example_mod {
fn global_symbol_for_pub_struct() { fn global_symbol_for_pub_struct() {
check_symbol( check_symbol(
r#" r#"
//- /lib.rs crate:main //- /workspace/lib.rs crate:main
mod foo; mod foo;
fn main() { fn main() {
let _bar = foo::Bar { i: 0 }; let _bar = foo::Bar { i: 0 };
} }
//- /foo.rs //- /workspace/foo.rs
pub struct Bar$0 { pub struct Bar$0 {
pub i: i32, pub i: i32,
} }
@ -580,13 +582,13 @@ pub mod example_mod {
fn global_symbol_for_pub_struct_reference() { fn global_symbol_for_pub_struct_reference() {
check_symbol( check_symbol(
r#" r#"
//- /lib.rs crate:main //- /workspace/lib.rs crate:main
mod foo; mod foo;
fn main() { fn main() {
let _bar = foo::Bar$0 { i: 0 }; let _bar = foo::Bar$0 { i: 0 };
} }
//- /foo.rs //- /workspace/foo.rs
pub struct Bar { pub struct Bar {
pub i: i32, pub i: i32,
} }
@ -599,7 +601,7 @@ pub mod example_mod {
fn symbol_for_for_type_alias() { fn symbol_for_for_type_alias() {
check_symbol( check_symbol(
r#" r#"
//- /lib.rs crate:main //- /workspace/lib.rs crate:main
pub type MyTypeAlias$0 = u8; pub type MyTypeAlias$0 = u8;
"#, "#,
"rust-analyzer cargo main . MyTypeAlias#", "rust-analyzer cargo main . MyTypeAlias#",
@ -615,7 +617,8 @@ pub mod example_mod {
host.raw_database_mut().apply_change(change_fixture.change); host.raw_database_mut().apply_change(change_fixture.change);
let analysis = host.analysis(); let analysis = host.analysis();
let si = StaticIndex::compute(&analysis); let si =
StaticIndex::compute(&analysis, &VfsPath::new_virtual_path("/workspace".to_owned()));
let file = si.files.first().unwrap(); let file = si.files.first().unwrap();
let (_, token_id) = file.tokens.first().unwrap(); let (_, token_id) = file.tokens.first().unwrap();