Detailed changes
@@ -1671,6 +1671,7 @@ mod tests {
trigger_kind: CompletionTriggerKind::TRIGGER_CHARACTER,
trigger_character: Some("@".into()),
},
+ false,
window,
cx,
)
@@ -23009,7 +23009,7 @@ fn snippet_completions(
});
}
- for snippets in scopes.into_iter() {
+ for (_scope, snippets) in scopes.into_iter() {
// Sort snippets by word count to match longer snippet prefixes first.
let mut sorted_snippet_candidates = snippets
.iter()
@@ -11083,6 +11083,50 @@ async fn test_snippet_indentation(cx: &mut TestAppContext) {
Ė"});
}
+#[gpui::test]
+async fn test_snippet_with_multi_word_prefix(cx: &mut TestAppContext) {
+ init_test(cx, |_| {});
+
+ let mut cx = EditorTestContext::new(cx).await;
+ cx.update_editor(|editor, window, cx| {
+ editor.project().unwrap().update(cx, |project, cx| {
+ project.snippets().update(cx, |snippets, cx| {
+ let snippet = project::snippet_provider::Snippet {
+ prefix: "multi word".to_string(),
+ body: "this is many words".to_string(),
+ description: "description".to_string(),
+ name: "multi-word snippet test".to_string(),
+ };
+ snippets.add_snippet_for_test(
+ None,
+ PathBuf::from("test_snippets.json"),
+ vec![Arc::new(snippet)],
+ cx,
+ );
+ });
+ })
+ });
+
+ cx.set_state("mĖ");
+ cx.simulate_input("u");
+
+ cx.update_editor(|editor, window, cx| {
+ let CodeContextMenu::Completions(context_menu) = editor.context_menu.borrow().unwrap()
+ else {
+ panic!("expected completion menu")
+ };
+ assert!(context_menu.visible());
+ let completions = context_menu;
+
+ assert!(
+ completions
+ .iter()
+ .any(|c| c.string.as_str() == "multi word"),
+ "Expected to find 'multi word' snippet in completions"
+ );
+ });
+}
+
#[gpui::test]
async fn test_document_format_during_save(cx: &mut TestAppContext) {
init_test(cx, |_| {});
@@ -13584,7 +13628,14 @@ async fn test_completion_mode(cx: &mut TestAppContext) {
cx.set_state(&run.initial_state);
cx.update_editor(|editor, window, cx| {
- editor.show_completions(&ShowCompletions { trigger: None }, window, cx);
+ editor.show_completions(
+ &ShowCompletions {
+ trigger: None,
+ snippets_only: false,
+ },
+ window,
+ cx,
+ );
});
let counter = Arc::new(AtomicUsize::new(0));
@@ -18,6 +18,7 @@ test-support = [
"client/test-support",
"language/test-support",
"settings/test-support",
+ "snippet_provider/test-support",
"text/test-support",
"prettier/test-support",
"worktree/test-support",
@@ -109,6 +110,7 @@ pretty_assertions.workspace = true
release_channel.workspace = true
rpc = { workspace = true, features = ["test-support"] }
settings = { workspace = true, features = ["test-support"] }
+snippet_provider = { workspace = true, features = ["test-support"] }
unindent.workspace = true
util = { workspace = true, features = ["test-support"] }
worktree = { workspace = true, features = ["test-support"] }
@@ -105,6 +105,7 @@ use search_history::SearchHistory;
use settings::{InvalidSettingsError, Settings, SettingsLocation, SettingsStore};
use smol::channel::Receiver;
use snippet::Snippet;
+pub use snippet_provider;
use snippet_provider::SnippetProvider;
use std::{
borrow::Cow,
@@ -8,6 +8,9 @@ license = "GPL-3.0-or-later"
[lints]
workspace = true
+[features]
+test-support = []
+
[dependencies]
anyhow.workspace = true
collections.workspace = true
@@ -235,6 +235,20 @@ impl SnippetProvider {
user_snippets
}
+ #[cfg(any(test, feature = "test-support"))]
+ pub fn add_snippet_for_test(
+ &mut self,
+ language: SnippetKind,
+ path: PathBuf,
+ snippet: Vec<Arc<Snippet>>,
+ cx: &mut Context<Self>,
+ ) {
+ self.snippets
+ .entry(language)
+ .or_default()
+ .insert(path, snippet);
+ }
+
pub fn snippets_for(&self, language: SnippetKind, cx: &App) -> Vec<Arc<Snippet>> {
let mut requested_snippets = self.lookup_snippets::<true>(&language, cx);