Cargo.lock 🔗
@@ -5046,6 +5046,7 @@ dependencies = [
"anyhow",
"arrayvec",
"collections",
+ "futures 0.3.31",
"gpui",
"indoc",
"language",
Agus Zubiaga created
Cargo.lock | 1
crates/edit_prediction_context/Cargo.toml | 1
crates/edit_prediction_context/src/tree_sitter_index.rs | 178 ++++++++--
3 files changed, 134 insertions(+), 46 deletions(-)
@@ -5046,6 +5046,7 @@ dependencies = [
"anyhow",
"arrayvec",
"collections",
+ "futures 0.3.31",
"gpui",
"indoc",
"language",
@@ -26,6 +26,7 @@ workspace-hack.workspace = true
worktree.workspace = true
[dev-dependencies]
+futures.workspace = true
gpui = { workspace = true, features = ["test-support"] }
indoc.workspace = true
language = { workspace = true, features = ["test-support"] }
@@ -385,10 +385,11 @@ mod tests {
use super::*;
use std::{path::Path, sync::Arc};
+ use futures::channel::oneshot;
use gpui::TestAppContext;
use indoc::indoc;
use language::{Language, LanguageConfig, LanguageMatcher, tree_sitter_rust};
- use project::{FakeFs, Project};
+ use project::{FakeFs, Project, ProjectItem};
use serde_json::json;
use settings::SettingsStore;
use util::path;
@@ -397,7 +398,135 @@ mod tests {
#[gpui::test]
async fn test_unopen_indexed_files(cx: &mut TestAppContext) {
- init_test(cx);
+ let (project, index) = init_test(cx).await;
+
+ index.read_with(cx, |index, cx| {
+ let decls = index.declarations_for_identifier::<8>("main", cx);
+ assert_eq!(decls.len(), 2);
+
+ let decl = expect_file_decl("c.rs", &decls[0], &project, cx);
+ assert_eq!(decl.identifier, "main".into());
+ assert_eq!(decl.item_range, 32..279);
+
+ let decl = expect_file_decl("a.rs", &decls[1], &project, cx);
+ assert_eq!(decl.identifier, "main".into());
+ assert_eq!(decl.item_range, 0..97);
+ });
+ }
+
+ #[gpui::test]
+ async fn test_declarations_limt(cx: &mut TestAppContext) {
+ let (_, index) = init_test(cx).await;
+
+ // todo! test with buffers
+ index.read_with(cx, |index, cx| {
+ let decls = index.declarations_for_identifier::<1>("main", cx);
+ assert_eq!(decls.len(), 1);
+ });
+ }
+
+ #[gpui::test]
+ async fn test_buffer_shadow(cx: &mut TestAppContext) {
+ let (project, index) = init_test(cx).await;
+
+ let buffer = project
+ .update(cx, |project, cx| {
+ let project_path = project.find_project_path("c.rs", cx).unwrap();
+ project.open_buffer(project_path, cx)
+ })
+ .await
+ .unwrap();
+
+ cx.run_until_parked();
+
+ index.read_with(cx, |index, cx| {
+ let decls = index.declarations_for_identifier::<8>("main", cx);
+ assert_eq!(decls.len(), 2);
+
+ let decl = expect_buffer_decl("c.rs", &decls[0], cx);
+ assert_eq!(decl.identifier, "main".into());
+ assert_eq!(decl.item_range.to_offset(&buffer.read(cx)), 32..279);
+
+ expect_file_decl("a.rs", &decls[1], &project, cx);
+ });
+
+ // Drop the buffer and wait for release
+ let (release_tx, release_rx) = oneshot::channel();
+ cx.update(|cx| {
+ cx.observe_release(&buffer, |_, _| {
+ release_tx.send(()).ok();
+ })
+ .detach();
+ });
+ drop(buffer);
+ cx.run_until_parked();
+ release_rx.await.ok();
+ cx.run_until_parked();
+
+ index.read_with(cx, |index, cx| {
+ let decls = index.declarations_for_identifier::<8>("main", cx);
+ assert_eq!(decls.len(), 2);
+ expect_file_decl("c.rs", &decls[0], &project, cx);
+ expect_file_decl("a.rs", &decls[1], &project, cx);
+ });
+ }
+
+ fn expect_buffer_decl<'a>(
+ path: &str,
+ declaration: &'a Declaration,
+ cx: &App,
+ ) -> &'a BufferDeclaration {
+ if let Declaration::Buffer {
+ declaration,
+ buffer,
+ } = declaration
+ {
+ assert_eq!(
+ buffer
+ .upgrade()
+ .unwrap()
+ .read(cx)
+ .project_path(cx)
+ .unwrap()
+ .path
+ .as_ref(),
+ Path::new(path),
+ );
+ declaration
+ } else {
+ panic!("Expected a buffer declaration, found {:?}", declaration);
+ }
+ }
+
+ fn expect_file_decl<'a>(
+ path: &str,
+ declaration: &'a Declaration,
+ project: &Entity<Project>,
+ cx: &App,
+ ) -> &'a FileDeclaration {
+ if let Declaration::File { declaration, file } = declaration {
+ assert_eq!(
+ project
+ .read(cx)
+ .path_for_entry(*file, cx)
+ .unwrap()
+ .path
+ .as_ref(),
+ Path::new(path),
+ );
+ declaration
+ } else {
+ panic!("Expected a file declaration, found {:?}", declaration);
+ }
+ }
+
+ async fn init_test(cx: &mut TestAppContext) -> (Entity<Project>, Entity<TreeSitterIndex>) {
+ cx.update(|cx| {
+ let settings_store = SettingsStore::test(cx);
+ cx.set_global(settings_store);
+ language::init(cx);
+ Project::init_settings(cx);
+ });
let fs = FakeFs::new(cx.executor());
fs.insert_tree(
@@ -469,42 +598,8 @@ mod tests {
let index = cx.new(|cx| TreeSitterIndex::new(&project, cx));
cx.run_until_parked();
- index.read_with(cx, |index, cx| {
- let decls = index.declarations_for_identifier::<8>("main", cx);
- assert_eq!(decls.len(), 2);
- if let Declaration::File { declaration, file } = &decls[0] {
- assert_eq!(
- project
- .read(cx)
- .path_for_entry(*file, cx)
- .unwrap()
- .path
- .as_ref(),
- Path::new("c.rs"),
- );
- assert_eq!(declaration.identifier, "main".into());
- assert_eq!(declaration.item_range, 32..279);
- } else {
- panic!();
- }
-
- if let Declaration::File { declaration, file } = &decls[1] {
- assert_eq!(
- project
- .read(cx)
- .path_for_entry(*file, cx)
- .unwrap()
- .path
- .as_ref(),
- Path::new("a.rs"),
- );
- assert_eq!(declaration.identifier, "main".into());
- assert_eq!(declaration.item_range, 0..97);
- } else {
- panic!();
- }
- });
+ (project, index)
}
fn rust_lang() -> Language {
@@ -522,15 +617,6 @@ mod tests {
.with_outline_query(include_str!("../../languages/src/rust/outline.scm"))
.unwrap()
}
-
- fn init_test(cx: &mut TestAppContext) {
- cx.update(|cx| {
- let settings_store = SettingsStore::test(cx);
- cx.set_global(settings_store);
- language::init(cx);
- Project::init_settings(cx);
- });
- }
}
/*