Rename remaining mentions of "inline completion" to "edit prediction" (#35512)
Release Notes: - N/A
This commit is contained in:
parent
85885723a9
commit
65018c28c0
43 changed files with 480 additions and 498 deletions
372
crates/editor/src/edit_prediction_tests.rs
Normal file
372
crates/editor/src/edit_prediction_tests.rs
Normal file
|
@ -0,0 +1,372 @@
|
|||
use edit_prediction::EditPredictionProvider;
|
||||
use gpui::{Entity, prelude::*};
|
||||
use indoc::indoc;
|
||||
use multi_buffer::{Anchor, MultiBufferSnapshot, ToPoint};
|
||||
use project::Project;
|
||||
use std::ops::Range;
|
||||
use text::{Point, ToOffset};
|
||||
|
||||
use crate::{
|
||||
EditPrediction, editor_tests::init_test, test::editor_test_context::EditorTestContext,
|
||||
};
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_edit_prediction_insert(cx: &mut gpui::TestAppContext) {
|
||||
init_test(cx, |_| {});
|
||||
|
||||
let mut cx = EditorTestContext::new(cx).await;
|
||||
let provider = cx.new(|_| FakeEditPredictionProvider::default());
|
||||
assign_editor_completion_provider(provider.clone(), &mut cx);
|
||||
cx.set_state("let absolute_zero_celsius = ˇ;");
|
||||
|
||||
propose_edits(&provider, vec![(28..28, "-273.15")], &mut cx);
|
||||
cx.update_editor(|editor, window, cx| editor.update_visible_edit_prediction(window, cx));
|
||||
|
||||
assert_editor_active_edit_completion(&mut cx, |_, edits| {
|
||||
assert_eq!(edits.len(), 1);
|
||||
assert_eq!(edits[0].1.as_str(), "-273.15");
|
||||
});
|
||||
|
||||
accept_completion(&mut cx);
|
||||
|
||||
cx.assert_editor_state("let absolute_zero_celsius = -273.15ˇ;")
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_edit_prediction_modification(cx: &mut gpui::TestAppContext) {
|
||||
init_test(cx, |_| {});
|
||||
|
||||
let mut cx = EditorTestContext::new(cx).await;
|
||||
let provider = cx.new(|_| FakeEditPredictionProvider::default());
|
||||
assign_editor_completion_provider(provider.clone(), &mut cx);
|
||||
cx.set_state("let pi = ˇ\"foo\";");
|
||||
|
||||
propose_edits(&provider, vec![(9..14, "3.14159")], &mut cx);
|
||||
cx.update_editor(|editor, window, cx| editor.update_visible_edit_prediction(window, cx));
|
||||
|
||||
assert_editor_active_edit_completion(&mut cx, |_, edits| {
|
||||
assert_eq!(edits.len(), 1);
|
||||
assert_eq!(edits[0].1.as_str(), "3.14159");
|
||||
});
|
||||
|
||||
accept_completion(&mut cx);
|
||||
|
||||
cx.assert_editor_state("let pi = 3.14159ˇ;")
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_edit_prediction_jump_button(cx: &mut gpui::TestAppContext) {
|
||||
init_test(cx, |_| {});
|
||||
|
||||
let mut cx = EditorTestContext::new(cx).await;
|
||||
let provider = cx.new(|_| FakeEditPredictionProvider::default());
|
||||
assign_editor_completion_provider(provider.clone(), &mut cx);
|
||||
|
||||
// Cursor is 2+ lines above the proposed edit
|
||||
cx.set_state(indoc! {"
|
||||
line 0
|
||||
line ˇ1
|
||||
line 2
|
||||
line 3
|
||||
line
|
||||
"});
|
||||
|
||||
propose_edits(
|
||||
&provider,
|
||||
vec![(Point::new(4, 3)..Point::new(4, 3), " 4")],
|
||||
&mut cx,
|
||||
);
|
||||
|
||||
cx.update_editor(|editor, window, cx| editor.update_visible_edit_prediction(window, cx));
|
||||
assert_editor_active_move_completion(&mut cx, |snapshot, move_target| {
|
||||
assert_eq!(move_target.to_point(&snapshot), Point::new(4, 3));
|
||||
});
|
||||
|
||||
// When accepting, cursor is moved to the proposed location
|
||||
accept_completion(&mut cx);
|
||||
cx.assert_editor_state(indoc! {"
|
||||
line 0
|
||||
line 1
|
||||
line 2
|
||||
line 3
|
||||
linˇe
|
||||
"});
|
||||
|
||||
// Cursor is 2+ lines below the proposed edit
|
||||
cx.set_state(indoc! {"
|
||||
line 0
|
||||
line
|
||||
line 2
|
||||
line 3
|
||||
line ˇ4
|
||||
"});
|
||||
|
||||
propose_edits(
|
||||
&provider,
|
||||
vec![(Point::new(1, 3)..Point::new(1, 3), " 1")],
|
||||
&mut cx,
|
||||
);
|
||||
|
||||
cx.update_editor(|editor, window, cx| editor.update_visible_edit_prediction(window, cx));
|
||||
assert_editor_active_move_completion(&mut cx, |snapshot, move_target| {
|
||||
assert_eq!(move_target.to_point(&snapshot), Point::new(1, 3));
|
||||
});
|
||||
|
||||
// When accepting, cursor is moved to the proposed location
|
||||
accept_completion(&mut cx);
|
||||
cx.assert_editor_state(indoc! {"
|
||||
line 0
|
||||
linˇe
|
||||
line 2
|
||||
line 3
|
||||
line 4
|
||||
"});
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_edit_prediction_invalidation_range(cx: &mut gpui::TestAppContext) {
|
||||
init_test(cx, |_| {});
|
||||
|
||||
let mut cx = EditorTestContext::new(cx).await;
|
||||
let provider = cx.new(|_| FakeEditPredictionProvider::default());
|
||||
assign_editor_completion_provider(provider.clone(), &mut cx);
|
||||
|
||||
// Cursor is 3+ lines above the proposed edit
|
||||
cx.set_state(indoc! {"
|
||||
line 0
|
||||
line ˇ1
|
||||
line 2
|
||||
line 3
|
||||
line 4
|
||||
line
|
||||
"});
|
||||
let edit_location = Point::new(5, 3);
|
||||
|
||||
propose_edits(
|
||||
&provider,
|
||||
vec![(edit_location..edit_location, " 5")],
|
||||
&mut cx,
|
||||
);
|
||||
|
||||
cx.update_editor(|editor, window, cx| editor.update_visible_edit_prediction(window, cx));
|
||||
assert_editor_active_move_completion(&mut cx, |snapshot, move_target| {
|
||||
assert_eq!(move_target.to_point(&snapshot), edit_location);
|
||||
});
|
||||
|
||||
// If we move *towards* the completion, it stays active
|
||||
cx.set_selections_state(indoc! {"
|
||||
line 0
|
||||
line 1
|
||||
line ˇ2
|
||||
line 3
|
||||
line 4
|
||||
line
|
||||
"});
|
||||
assert_editor_active_move_completion(&mut cx, |snapshot, move_target| {
|
||||
assert_eq!(move_target.to_point(&snapshot), edit_location);
|
||||
});
|
||||
|
||||
// If we move *away* from the completion, it is discarded
|
||||
cx.set_selections_state(indoc! {"
|
||||
line ˇ0
|
||||
line 1
|
||||
line 2
|
||||
line 3
|
||||
line 4
|
||||
line
|
||||
"});
|
||||
cx.editor(|editor, _, _| {
|
||||
assert!(editor.active_edit_prediction.is_none());
|
||||
});
|
||||
|
||||
// Cursor is 3+ lines below the proposed edit
|
||||
cx.set_state(indoc! {"
|
||||
line
|
||||
line 1
|
||||
line 2
|
||||
line 3
|
||||
line ˇ4
|
||||
line 5
|
||||
"});
|
||||
let edit_location = Point::new(0, 3);
|
||||
|
||||
propose_edits(
|
||||
&provider,
|
||||
vec![(edit_location..edit_location, " 0")],
|
||||
&mut cx,
|
||||
);
|
||||
|
||||
cx.update_editor(|editor, window, cx| editor.update_visible_edit_prediction(window, cx));
|
||||
assert_editor_active_move_completion(&mut cx, |snapshot, move_target| {
|
||||
assert_eq!(move_target.to_point(&snapshot), edit_location);
|
||||
});
|
||||
|
||||
// If we move *towards* the completion, it stays active
|
||||
cx.set_selections_state(indoc! {"
|
||||
line
|
||||
line 1
|
||||
line 2
|
||||
line ˇ3
|
||||
line 4
|
||||
line 5
|
||||
"});
|
||||
assert_editor_active_move_completion(&mut cx, |snapshot, move_target| {
|
||||
assert_eq!(move_target.to_point(&snapshot), edit_location);
|
||||
});
|
||||
|
||||
// If we move *away* from the completion, it is discarded
|
||||
cx.set_selections_state(indoc! {"
|
||||
line
|
||||
line 1
|
||||
line 2
|
||||
line 3
|
||||
line 4
|
||||
line ˇ5
|
||||
"});
|
||||
cx.editor(|editor, _, _| {
|
||||
assert!(editor.active_edit_prediction.is_none());
|
||||
});
|
||||
}
|
||||
|
||||
fn assert_editor_active_edit_completion(
|
||||
cx: &mut EditorTestContext,
|
||||
assert: impl FnOnce(MultiBufferSnapshot, &Vec<(Range<Anchor>, String)>),
|
||||
) {
|
||||
cx.editor(|editor, _, cx| {
|
||||
let completion_state = editor
|
||||
.active_edit_prediction
|
||||
.as_ref()
|
||||
.expect("editor has no active completion");
|
||||
|
||||
if let EditPrediction::Edit { edits, .. } = &completion_state.completion {
|
||||
assert(editor.buffer().read(cx).snapshot(cx), edits);
|
||||
} else {
|
||||
panic!("expected edit completion");
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn assert_editor_active_move_completion(
|
||||
cx: &mut EditorTestContext,
|
||||
assert: impl FnOnce(MultiBufferSnapshot, Anchor),
|
||||
) {
|
||||
cx.editor(|editor, _, cx| {
|
||||
let completion_state = editor
|
||||
.active_edit_prediction
|
||||
.as_ref()
|
||||
.expect("editor has no active completion");
|
||||
|
||||
if let EditPrediction::Move { target, .. } = &completion_state.completion {
|
||||
assert(editor.buffer().read(cx).snapshot(cx), *target);
|
||||
} else {
|
||||
panic!("expected move completion");
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn accept_completion(cx: &mut EditorTestContext) {
|
||||
cx.update_editor(|editor, window, cx| {
|
||||
editor.accept_edit_prediction(&crate::AcceptEditPrediction, window, cx)
|
||||
})
|
||||
}
|
||||
|
||||
fn propose_edits<T: ToOffset>(
|
||||
provider: &Entity<FakeEditPredictionProvider>,
|
||||
edits: Vec<(Range<T>, &str)>,
|
||||
cx: &mut EditorTestContext,
|
||||
) {
|
||||
let snapshot = cx.buffer_snapshot();
|
||||
let edits = edits.into_iter().map(|(range, text)| {
|
||||
let range = snapshot.anchor_after(range.start)..snapshot.anchor_before(range.end);
|
||||
(range, text.into())
|
||||
});
|
||||
|
||||
cx.update(|_, cx| {
|
||||
provider.update(cx, |provider, _| {
|
||||
provider.set_edit_prediction(Some(edit_prediction::EditPrediction {
|
||||
id: None,
|
||||
edits: edits.collect(),
|
||||
edit_preview: None,
|
||||
}))
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
fn assign_editor_completion_provider(
|
||||
provider: Entity<FakeEditPredictionProvider>,
|
||||
cx: &mut EditorTestContext,
|
||||
) {
|
||||
cx.update_editor(|editor, window, cx| {
|
||||
editor.set_edit_prediction_provider(Some(provider), window, cx);
|
||||
})
|
||||
}
|
||||
|
||||
#[derive(Default, Clone)]
|
||||
pub struct FakeEditPredictionProvider {
|
||||
pub completion: Option<edit_prediction::EditPrediction>,
|
||||
}
|
||||
|
||||
impl FakeEditPredictionProvider {
|
||||
pub fn set_edit_prediction(&mut self, completion: Option<edit_prediction::EditPrediction>) {
|
||||
self.completion = completion;
|
||||
}
|
||||
}
|
||||
|
||||
impl EditPredictionProvider for FakeEditPredictionProvider {
|
||||
fn name() -> &'static str {
|
||||
"fake-completion-provider"
|
||||
}
|
||||
|
||||
fn display_name() -> &'static str {
|
||||
"Fake Completion Provider"
|
||||
}
|
||||
|
||||
fn show_completions_in_menu() -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn is_enabled(
|
||||
&self,
|
||||
_buffer: &gpui::Entity<language::Buffer>,
|
||||
_cursor_position: language::Anchor,
|
||||
_cx: &gpui::App,
|
||||
) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn is_refreshing(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn refresh(
|
||||
&mut self,
|
||||
_project: Option<Entity<Project>>,
|
||||
_buffer: gpui::Entity<language::Buffer>,
|
||||
_cursor_position: language::Anchor,
|
||||
_debounce: bool,
|
||||
_cx: &mut gpui::Context<Self>,
|
||||
) {
|
||||
}
|
||||
|
||||
fn cycle(
|
||||
&mut self,
|
||||
_buffer: gpui::Entity<language::Buffer>,
|
||||
_cursor_position: language::Anchor,
|
||||
_direction: edit_prediction::Direction,
|
||||
_cx: &mut gpui::Context<Self>,
|
||||
) {
|
||||
}
|
||||
|
||||
fn accept(&mut self, _cx: &mut gpui::Context<Self>) {}
|
||||
|
||||
fn discard(&mut self, _cx: &mut gpui::Context<Self>) {}
|
||||
|
||||
fn suggest<'a>(
|
||||
&mut self,
|
||||
_buffer: &gpui::Entity<language::Buffer>,
|
||||
_cursor_position: language::Anchor,
|
||||
_cx: &mut gpui::Context<Self>,
|
||||
) -> Option<edit_prediction::EditPrediction> {
|
||||
self.completion.clone()
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue