diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index bc9f990706754..8e4289dc16c16 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -4571,6 +4571,23 @@ impl Editor { _: &AcceptInlineCompletion, cx: &mut ViewContext, ) { + let buffer = self.buffer.read(cx); + let snapshot = buffer.snapshot(cx); + let selection = self.selections.newest_adjusted(cx); + let cursor = selection.head(); + let current_indent = snapshot.indent_size_for_line(MultiBufferRow(cursor.row)); + let suggested_indents = snapshot.suggested_indents([cursor.row], cx); + if let Some(suggested_indent) = suggested_indents.get(&MultiBufferRow(cursor.row)).copied() + { + if cursor.column < suggested_indent.len + && cursor.column <= current_indent.len + && current_indent.len <= suggested_indent.len + { + self.tab(&Default::default(), cx); + return; + } + } + if self.show_inline_completions_in_menu(cx) { self.hide_context_menu(cx); } diff --git a/crates/editor/src/inline_completion_tests.rs b/crates/editor/src/inline_completion_tests.rs index 82eb286e973eb..a80f8dc62a615 100644 --- a/crates/editor/src/inline_completion_tests.rs +++ b/crates/editor/src/inline_completion_tests.rs @@ -1,8 +1,9 @@ use gpui::{prelude::*, Model}; use indoc::indoc; use inline_completion::InlineCompletionProvider; +use language::{Language, LanguageConfig}; use multi_buffer::{Anchor, MultiBufferSnapshot, ToPoint}; -use std::ops::Range; +use std::{num::NonZeroU32, ops::Range, sync::Arc}; use text::{Point, ToOffset}; use crate::{ @@ -122,6 +123,54 @@ async fn test_inline_completion_jump_button(cx: &mut gpui::TestAppContext) { "}); } +#[gpui::test] +async fn test_indentation(cx: &mut gpui::TestAppContext) { + init_test(cx, |settings| { + settings.defaults.tab_size = NonZeroU32::new(4) + }); + + let language = Arc::new( + Language::new( + LanguageConfig::default(), + Some(tree_sitter_rust::LANGUAGE.into()), + ) + .with_indents_query(r#"(_ "(" ")" @end) @indent"#) + .unwrap(), + ); + + let mut cx = EditorTestContext::new(cx).await; + cx.update_buffer(|buffer, cx| buffer.set_language(Some(language), cx)); + let provider = cx.new_model(|_| FakeInlineCompletionProvider::default()); + assign_editor_completion_provider(provider.clone(), &mut cx); + + cx.set_state(indoc! {" + const a: A = ( + ˇ + ); + "}); + + propose_edits( + &provider, + vec![(Point::new(1, 0)..Point::new(1, 0), " const function()")], + &mut cx, + ); + cx.update_editor(|editor, cx| editor.update_visible_inline_completion(cx)); + + assert_editor_active_edit_completion(&mut cx, |_, edits| { + assert_eq!(edits.len(), 1); + assert_eq!(edits[0].1.as_str(), " const function()"); + }); + + // When the cursor is before the suggested indentation level, accepting a + // completion should just indent. + accept_completion(&mut cx); + cx.assert_editor_state(indoc! {" + const a: A = ( + ˇ + ); + "}); +} + #[gpui::test] async fn test_inline_completion_invalidation_range(cx: &mut gpui::TestAppContext) { init_test(cx, |_| {});