Renames + fixes

Michael Sloan and Agus created

Co-authored-by: Agus <agus@zed.dev>

Change summary

crates/edit_prediction_context/src/declaration.rs             | 205 ++++
crates/edit_prediction_context/src/declaration_scoring.rs     |  37 
crates/edit_prediction_context/src/edit_prediction_context.rs |   8 
crates/edit_prediction_context/src/outline.rs                 |  12 
crates/edit_prediction_context/src/reference.rs               |   2 
crates/edit_prediction_context/src/syntax_index.rs            | 212 ----
6 files changed, 242 insertions(+), 234 deletions(-)

Detailed changes

crates/edit_prediction_context/src/declaration.rs 🔗

@@ -0,0 +1,205 @@
+use gpui::{App, WeakEntity};
+use language::{Buffer, BufferSnapshot, LanguageId};
+use project::ProjectEntryId;
+use std::borrow::Cow;
+use std::ops::{Deref, Range};
+use std::sync::Arc;
+use text::{Anchor, Bias, OffsetRangeExt, ToOffset};
+
+use crate::outline::OutlineDeclaration;
+
+#[derive(Debug, Clone, Eq, PartialEq, Hash)]
+pub struct Identifier {
+    pub name: Arc<str>,
+    pub language_id: LanguageId,
+}
+
+slotmap::new_key_type! {
+    pub struct DeclarationId;
+}
+
+#[derive(Debug, Clone)]
+pub enum Declaration {
+    File {
+        project_entry_id: ProjectEntryId,
+        declaration: FileDeclaration,
+    },
+    Buffer {
+        buffer: WeakEntity<Buffer>,
+        declaration: BufferDeclaration,
+    },
+}
+
+const ITEM_TEXT_TRUNCATION_LENGTH: usize = 1024;
+
+impl Declaration {
+    pub fn identifier(&self) -> &Identifier {
+        match self {
+            Declaration::File { declaration, .. } => &declaration.identifier,
+            Declaration::Buffer { declaration, .. } => &declaration.identifier,
+        }
+    }
+
+    pub fn project_entry_id(&self, cx: &App) -> Option<ProjectEntryId> {
+        match self {
+            Declaration::File {
+                project_entry_id, ..
+            } => Some(*project_entry_id),
+            Declaration::Buffer { buffer, .. } => buffer
+                .read_with(cx, |buffer, _cx| {
+                    project::File::from_dyn(buffer.file())
+                        .and_then(|file| file.project_entry_id(cx))
+                })
+                .ok()
+                .flatten(),
+        }
+    }
+
+    pub fn item_text(&self, cx: &App) -> (Cow<'_, str>, bool) {
+        match self {
+            Declaration::File { declaration, .. } => (
+                declaration.text.as_ref().into(),
+                declaration.text_is_truncated,
+            ),
+            Declaration::Buffer {
+                buffer,
+                declaration,
+            } => buffer
+                .read_with(cx, |buffer, _cx| {
+                    let (range, is_truncated) = expand_range_to_line_boundaries_and_truncate(
+                        &declaration.item_range,
+                        ITEM_TEXT_TRUNCATION_LENGTH,
+                        buffer.deref(),
+                    );
+                    (
+                        buffer.text_for_range(range).collect::<Cow<str>>(),
+                        is_truncated,
+                    )
+                })
+                .unwrap_or_default(),
+        }
+    }
+
+    pub fn signature_text(&self, cx: &App) -> (Cow<'_, str>, bool) {
+        match self {
+            Declaration::File { declaration, .. } => (
+                declaration.text[declaration.signature_range_in_text.clone()].into(),
+                declaration.signature_is_truncated,
+            ),
+            Declaration::Buffer {
+                buffer,
+                declaration,
+            } => buffer
+                .read_with(cx, |buffer, _cx| {
+                    let (range, is_truncated) = expand_range_to_line_boundaries_and_truncate(
+                        &declaration.signature_range,
+                        ITEM_TEXT_TRUNCATION_LENGTH,
+                        buffer.deref(),
+                    );
+                    (
+                        buffer.text_for_range(range).collect::<Cow<str>>(),
+                        is_truncated,
+                    )
+                })
+                .unwrap_or_default(),
+        }
+    }
+}
+
+fn expand_range_to_line_boundaries_and_truncate<T: ToOffset>(
+    range: &Range<T>,
+    limit: usize,
+    buffer: &text::BufferSnapshot,
+) -> (Range<usize>, bool) {
+    let mut point_range = range.to_point(buffer);
+    point_range.start.column = 0;
+    point_range.end.row += 1;
+    point_range.end.column = 0;
+
+    let mut item_range = point_range.to_offset(buffer);
+    let is_truncated = item_range.len() > limit;
+    if is_truncated {
+        item_range.end = item_range.start + limit;
+    }
+    item_range.end = buffer.clip_offset(item_range.end, Bias::Left);
+    (item_range, is_truncated)
+}
+
+#[derive(Debug, Clone)]
+pub struct FileDeclaration {
+    pub parent: Option<DeclarationId>,
+    pub identifier: Identifier,
+    /// offset range of the declaration in the file, expanded to line boundaries and truncated
+    pub item_range_in_file: Range<usize>,
+    /// text of `item_range_in_file`
+    pub text: Arc<str>,
+    /// whether `text` was truncated
+    pub text_is_truncated: bool,
+    /// offset range of the signature within `text`
+    pub signature_range_in_text: Range<usize>,
+    /// whether `signature` was truncated
+    pub signature_is_truncated: bool,
+}
+
+impl FileDeclaration {
+    pub fn from_outline(
+        declaration: OutlineDeclaration,
+        snapshot: &BufferSnapshot,
+    ) -> FileDeclaration {
+        let (item_range_in_file, text_is_truncated) = expand_range_to_line_boundaries_and_truncate(
+            &declaration.item_range,
+            ITEM_TEXT_TRUNCATION_LENGTH,
+            snapshot,
+        );
+
+        // TODO: consider logging if unexpected
+        let signature_start = declaration
+            .signature_range
+            .start
+            .saturating_sub(item_range_in_file.start);
+        let mut signature_end = declaration
+            .signature_range
+            .end
+            .saturating_sub(item_range_in_file.start);
+        let signature_is_truncated = signature_end > item_range_in_file.len();
+        if signature_is_truncated {
+            signature_end = item_range_in_file.len();
+        }
+
+        FileDeclaration {
+            parent: None,
+            identifier: declaration.identifier,
+            signature_range_in_text: signature_start..signature_end,
+            signature_is_truncated,
+            text: snapshot
+                .text_for_range(item_range_in_file.clone())
+                .collect::<String>()
+                .into(),
+            text_is_truncated,
+            item_range_in_file,
+        }
+    }
+}
+
+#[derive(Debug, Clone)]
+pub struct BufferDeclaration {
+    pub parent: Option<DeclarationId>,
+    pub identifier: Identifier,
+    pub item_range: Range<Anchor>,
+    pub signature_range: Range<Anchor>,
+}
+
+impl BufferDeclaration {
+    pub fn from_outline(declaration: OutlineDeclaration, snapshot: &BufferSnapshot) -> Self {
+        // use of anchor_before is a guess that the proper behavior is to expand to include
+        // insertions immediately before the declaration, but not for insertions immediately after
+        Self {
+            parent: None,
+            identifier: declaration.identifier,
+            item_range: snapshot.anchor_before(declaration.item_range.start)
+                ..snapshot.anchor_before(declaration.item_range.end),
+            signature_range: snapshot.anchor_before(declaration.signature_range.start)
+                ..snapshot.anchor_before(declaration.signature_range.end),
+        }
+    }
+}

crates/edit_prediction_context/src/scored_declaration.rs → crates/edit_prediction_context/src/declaration_scoring.rs 🔗

@@ -1,16 +1,13 @@
-use collections::HashSet;
 use gpui::{App, Entity};
 use itertools::Itertools as _;
 use language::BufferSnapshot;
-use project::ProjectEntryId;
 use serde::Serialize;
 use std::{collections::HashMap, ops::Range};
 use strum::EnumIter;
 use text::{OffsetRangeExt, Point, ToPoint};
 
 use crate::{
-    Declaration, EditPredictionExcerpt, EditPredictionExcerptText, TreeSitterIndex,
-    outline::Identifier,
+    Declaration, EditPredictionExcerpt, EditPredictionExcerptText, Identifier, SyntaxIndex,
     reference::{Reference, ReferenceRegion},
     text_similarity::{IdentifierOccurrences, jaccard_similarity, weighted_overlap_coefficient},
 };
@@ -54,7 +51,7 @@ impl ScoredSnippet {
 }
 
 fn scored_snippets(
-    index: Entity<TreeSitterIndex>,
+    index: Entity<SyntaxIndex>,
     excerpt: &EditPredictionExcerpt,
     excerpt_text: &EditPredictionExcerptText,
     identifier_to_references: HashMap<Identifier, Vec<Reference>>,
@@ -66,10 +63,6 @@ fn scored_snippets(
         IdentifierOccurrences::within_string(&excerpt_text.body);
     let cursor_point = cursor_offset.to_point(&current_buffer);
 
-    // todo! ask michael why we needed this
-    // if let Some(cursor_within_excerpt) = cursor_offset.checked_sub(excerpt.range.start) {
-    // } else {
-    // };
     let start_point = Point::new(cursor_point.row.saturating_sub(2), 0);
     let end_point = Point::new(cursor_point.row + 1, 0);
     let adjacent_identifier_occurrences = IdentifierOccurrences::within_string(
@@ -91,7 +84,7 @@ fn scored_snippets(
                 .iter()
                 .filter_map(|declaration| match declaration {
                     Declaration::Buffer {
-                        declaration,
+                        declaration: buffer_declaration,
                         buffer,
                     } => {
                         let is_same_file = buffer
@@ -100,13 +93,16 @@ fn scored_snippets(
 
                         if is_same_file {
                             range_intersection(
-                                &declaration.item_range.to_offset(&current_buffer),
+                                &buffer_declaration.item_range.to_offset(&current_buffer),
                                 &excerpt.range,
                             )
                             .is_none()
                             .then(|| {
-                                let declaration_line =
-                                    declaration.item_range.start.to_point(current_buffer).row;
+                                let declaration_line = buffer_declaration
+                                    .item_range
+                                    .start
+                                    .to_point(current_buffer)
+                                    .row;
                                 (
                                     true,
                                     (cursor_point.row as i32 - declaration_line as i32).abs()
@@ -120,7 +116,7 @@ fn scored_snippets(
                     }
                     Declaration::File { .. } => {
                         // We can assume that a file declaration is in a different file,
-                        // because the current onemust be open
+                        // because the current one must be open
                         Some((false, 0, declaration))
                     }
                 })
@@ -199,9 +195,10 @@ fn score_snippet(
         .min()
         .unwrap();
 
-    let item_source_occurrences = IdentifierOccurrences::within_string(&declaration.item_text(cx));
+    let item_source_occurrences =
+        IdentifierOccurrences::within_string(&declaration.item_text(cx).0);
     let item_signature_occurrences =
-        IdentifierOccurrences::within_string(&declaration.signature_text(cx));
+        IdentifierOccurrences::within_string(&declaration.signature_text(cx).0);
     let containing_range_vs_item_jaccard = jaccard_similarity(
         containing_range_identifier_occurrences,
         &item_source_occurrences,
@@ -327,9 +324,7 @@ mod tests {
     use text::ToOffset;
     use util::path;
 
-    use crate::{
-        EditPredictionExcerptOptions, references_in_excerpt, tree_sitter_index::TreeSitterIndex,
-    };
+    use crate::{EditPredictionExcerptOptions, references_in_excerpt};
 
     #[gpui::test]
     async fn test_call_site(cx: &mut TestAppContext) {
@@ -382,7 +377,7 @@ mod tests {
 
     async fn init_test(
         cx: &mut TestAppContext,
-    ) -> (Entity<Project>, Entity<TreeSitterIndex>, LanguageId) {
+    ) -> (Entity<Project>, Entity<SyntaxIndex>, LanguageId) {
         cx.update(|cx| {
             let settings_store = SettingsStore::test(cx);
             cx.set_global(settings_store);
@@ -460,7 +455,7 @@ mod tests {
         let lang_id = lang.id();
         language_registry.add(Arc::new(lang));
 
-        let index = cx.new(|cx| TreeSitterIndex::new(&project, cx));
+        let index = cx.new(|cx| SyntaxIndex::new(&project, cx));
         cx.run_until_parked();
 
         (project, index, lang_id)

crates/edit_prediction_context/src/edit_prediction_context.rs 🔗

@@ -1,10 +1,12 @@
+mod declaration;
+mod declaration_scoring;
 mod excerpt;
 mod outline;
 mod reference;
-mod scored_declaration;
+mod syntax_index;
 mod text_similarity;
-mod tree_sitter_index;
 
+pub use declaration::{BufferDeclaration, Declaration, FileDeclaration, Identifier};
 pub use excerpt::{EditPredictionExcerpt, EditPredictionExcerptOptions, EditPredictionExcerptText};
 pub use reference::references_in_excerpt;
-pub use tree_sitter_index::{BufferDeclaration, Declaration, FileDeclaration, TreeSitterIndex};
+pub use syntax_index::SyntaxIndex;

crates/edit_prediction_context/src/outline.rs 🔗

@@ -1,5 +1,7 @@
-use language::{BufferSnapshot, LanguageId, SyntaxMapMatches};
-use std::{cmp::Reverse, ops::Range, sync::Arc};
+use language::{BufferSnapshot, SyntaxMapMatches};
+use std::{cmp::Reverse, ops::Range};
+
+use crate::declaration::Identifier;
 
 // TODO:
 //
@@ -18,12 +20,6 @@ pub struct OutlineDeclaration {
     pub signature_range: Range<usize>,
 }
 
-#[derive(Debug, Clone, Eq, PartialEq, Hash)]
-pub struct Identifier {
-    pub name: Arc<str>,
-    pub language_id: LanguageId,
-}
-
 pub fn declarations_in_buffer(buffer: &BufferSnapshot) -> Vec<OutlineDeclaration> {
     declarations_overlapping_range(0..buffer.len(), buffer)
 }

crates/edit_prediction_context/src/reference.rs 🔗

@@ -3,8 +3,8 @@ use std::collections::HashMap;
 use std::ops::Range;
 
 use crate::{
+    declaration::Identifier,
     excerpt::{EditPredictionExcerpt, EditPredictionExcerptText},
-    outline::Identifier,
 };
 
 #[derive(Debug)]

crates/edit_prediction_context/src/tree_sitter_index.rs → crates/edit_prediction_context/src/syntax_index.rs 🔗

@@ -1,17 +1,16 @@
 use collections::{HashMap, HashSet};
 use gpui::{App, AppContext as _, Context, Entity, Task, WeakEntity};
-use language::{Buffer, BufferEvent, BufferSnapshot};
+use language::{Buffer, BufferEvent};
 use project::buffer_store::{BufferStore, BufferStoreEvent};
 use project::worktree_store::{WorktreeStore, WorktreeStoreEvent};
 use project::{PathChange, Project, ProjectEntryId, ProjectPath};
 use slotmap::SlotMap;
-use std::borrow::Cow;
-use std::ops::{Deref, Range};
-use std::sync::Arc;
-use text::{Anchor, Bias, OffsetRangeExt, ToOffset};
 use util::{ResultExt as _, debug_panic, some_or_debug_panic};
 
-use crate::outline::{Identifier, OutlineDeclaration, declarations_in_buffer};
+use crate::declaration::{
+    BufferDeclaration, Declaration, DeclarationId, FileDeclaration, Identifier,
+};
+use crate::outline::declarations_in_buffer;
 
 // TODO:
 //
@@ -36,13 +35,7 @@ use crate::outline::{Identifier, OutlineDeclaration, declarations_in_buffer};
 //
 // * Use queue for parsing
 
-const ITEM_TEXT_TRUNCATION_LENGTH: usize = 1024;
-
-slotmap::new_key_type! {
-    pub struct DeclarationId;
-}
-
-pub struct TreeSitterIndex {
+pub struct SyntaxIndex {
     declarations: SlotMap<DeclarationId, Declaration>,
     identifiers: HashMap<Identifier, HashSet<DeclarationId>>,
     files: HashMap<ProjectEntryId, FileState>,
@@ -62,136 +55,7 @@ struct BufferState {
     task: Option<Task<()>>,
 }
 
-#[derive(Debug, Clone)]
-pub enum Declaration {
-    File {
-        project_entry_id: ProjectEntryId,
-        declaration: FileDeclaration,
-    },
-    Buffer {
-        buffer: WeakEntity<Buffer>,
-        declaration: BufferDeclaration,
-    },
-}
-
-impl Declaration {
-    fn identifier(&self) -> &Identifier {
-        match self {
-            Declaration::File { declaration, .. } => &declaration.identifier,
-            Declaration::Buffer { declaration, .. } => &declaration.identifier,
-        }
-    }
-
-    pub fn project_entry_id(&self, cx: &App) -> Option<ProjectEntryId> {
-        match self {
-            Declaration::File {
-                project_entry_id, ..
-            } => Some(*project_entry_id),
-            Declaration::Buffer { buffer, .. } => buffer
-                .read_with(cx, |buffer, _cx| {
-                    project::File::from_dyn(buffer.file())
-                        .and_then(|file| file.project_entry_id(cx))
-                })
-                .ok()
-                .flatten(),
-        }
-    }
-
-    pub fn item_text(&self, cx: &App) -> (Cow<'_, str>, bool) {
-        match self {
-            Declaration::File { declaration, .. } => (
-                declaration.text.as_ref().into(),
-                declaration.text_is_truncated,
-            ),
-            Declaration::Buffer {
-                buffer,
-                declaration,
-            } => buffer
-                .read_with(cx, |buffer, _cx| {
-                    let (range, is_truncated) = expand_range_to_line_boundaries_and_truncate(
-                        &declaration.item_range,
-                        ITEM_TEXT_TRUNCATION_LENGTH,
-                        buffer.deref(),
-                    );
-                    (
-                        buffer.text_for_range(range).collect::<Cow<str>>(),
-                        is_truncated,
-                    )
-                })
-                .unwrap_or_default(),
-        }
-    }
-
-    pub fn signature_text(&self, cx: &App) -> (Cow<'_, str>, bool) {
-        match self {
-            Declaration::File { declaration, .. } => (
-                declaration.text[declaration.signature_range_in_text.clone()].into(),
-                declaration.signature_is_truncated,
-            ),
-            Declaration::Buffer {
-                buffer,
-                declaration,
-            } => buffer
-                .read_with(cx, |buffer, _cx| {
-                    let (range, is_truncated) = expand_range_to_line_boundaries_and_truncate(
-                        &declaration.signature_range,
-                        ITEM_TEXT_TRUNCATION_LENGTH,
-                        buffer.deref(),
-                    );
-                    (
-                        buffer.text_for_range(range).collect::<Cow<str>>(),
-                        is_truncated,
-                    )
-                })
-                .unwrap_or_default(),
-        }
-    }
-}
-
-fn expand_range_to_line_boundaries_and_truncate<T: ToOffset>(
-    range: &Range<T>,
-    limit: usize,
-    buffer: &text::BufferSnapshot,
-) -> (Range<usize>, bool) {
-    let mut point_range = range.to_point(buffer);
-    point_range.start.column = 0;
-    point_range.end.row += 1;
-    point_range.end.column = 0;
-
-    let mut item_range = point_range.to_offset(buffer);
-    let is_truncated = item_range.len() > limit;
-    if is_truncated {
-        item_range.end = item_range.start + limit;
-    }
-    item_range.end = buffer.clip_offset(item_range.end, Bias::Left);
-    (item_range, is_truncated)
-}
-
-#[derive(Debug, Clone)]
-pub struct FileDeclaration {
-    pub parent: Option<DeclarationId>,
-    pub identifier: Identifier,
-    /// offset range of the declaration in the file, expanded to line boundaries and truncated
-    pub item_range_in_file: Range<usize>,
-    /// text of `item_range_in_file`
-    pub text: Arc<str>,
-    /// whether `text` was truncated
-    pub text_is_truncated: bool,
-    /// offset range of the signature within `text`
-    pub signature_range_in_text: Range<usize>,
-    /// whether `signature` was truncated
-    pub signature_is_truncated: bool,
-}
-
-#[derive(Debug, Clone)]
-pub struct BufferDeclaration {
-    pub parent: Option<DeclarationId>,
-    pub identifier: Identifier,
-    pub item_range: Range<Anchor>,
-    pub signature_range: Range<Anchor>,
-}
-
-impl TreeSitterIndex {
+impl SyntaxIndex {
     pub fn new(project: &Entity<Project>, cx: &mut Context<Self>) -> Self {
         let mut this = Self {
             declarations: SlotMap::with_key(),
@@ -579,61 +443,6 @@ impl TreeSitterIndex {
     }
 }
 
-impl BufferDeclaration {
-    pub fn from_outline(declaration: OutlineDeclaration, snapshot: &BufferSnapshot) -> Self {
-        // use of anchor_before is a guess that the proper behavior is to expand to include
-        // insertions immediately before the declaration, but not for insertions immediately after
-        Self {
-            parent: None,
-            identifier: declaration.identifier,
-            item_range: snapshot.anchor_before(declaration.item_range.start)
-                ..snapshot.anchor_before(declaration.item_range.end),
-            signature_range: snapshot.anchor_before(declaration.signature_range.start)
-                ..snapshot.anchor_before(declaration.signature_range.end),
-        }
-    }
-}
-
-impl FileDeclaration {
-    pub fn from_outline(
-        declaration: OutlineDeclaration,
-        snapshot: &BufferSnapshot,
-    ) -> FileDeclaration {
-        let (item_range_in_file, text_is_truncated) = expand_range_to_line_boundaries_and_truncate(
-            &declaration.item_range,
-            ITEM_TEXT_TRUNCATION_LENGTH,
-            snapshot,
-        );
-
-        // TODO: consider logging if unexpected
-        let signature_start = declaration
-            .signature_range
-            .start
-            .saturating_sub(item_range_in_file.start);
-        let mut signature_end = declaration
-            .signature_range
-            .end
-            .saturating_sub(item_range_in_file.start);
-        let signature_is_truncated = signature_end > item_range_in_file.len();
-        if signature_is_truncated {
-            signature_end = item_range_in_file.len();
-        }
-
-        FileDeclaration {
-            parent: None,
-            identifier: declaration.identifier,
-            signature_range_in_text: signature_start..signature_end,
-            signature_is_truncated,
-            text: snapshot
-                .text_for_range(item_range_in_file.clone())
-                .collect::<String>()
-                .into(),
-            text_is_truncated,
-            item_range_in_file,
-        }
-    }
-}
-
 #[cfg(test)]
 mod tests {
     use super::*;
@@ -646,9 +455,10 @@ mod tests {
     use project::{FakeFs, Project, ProjectItem};
     use serde_json::json;
     use settings::SettingsStore;
+    use text::OffsetRangeExt as _;
     use util::path;
 
-    use crate::tree_sitter_index::TreeSitterIndex;
+    use crate::syntax_index::SyntaxIndex;
 
     #[gpui::test]
     async fn test_unopen_indexed_files(cx: &mut TestAppContext) {
@@ -863,7 +673,7 @@ mod tests {
 
     async fn init_test(
         cx: &mut TestAppContext,
-    ) -> (Entity<Project>, Entity<TreeSitterIndex>, LanguageId) {
+    ) -> (Entity<Project>, Entity<SyntaxIndex>, LanguageId) {
         cx.update(|cx| {
             let settings_store = SettingsStore::test(cx);
             cx.set_global(settings_store);
@@ -941,7 +751,7 @@ mod tests {
         let lang_id = lang.id();
         language_registry.add(Arc::new(lang));
 
-        let index = cx.new(|cx| TreeSitterIndex::new(&project, cx));
+        let index = cx.new(|cx| SyntaxIndex::new(&project, cx));
         cx.run_until_parked();
 
         (project, index, lang_id)