Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/ide_completion/src/config.rs')
-rw-r--r--crates/ide_completion/src/config.rs44
1 files changed, 44 insertions, 0 deletions
diff --git a/crates/ide_completion/src/config.rs b/crates/ide_completion/src/config.rs
index c300ce887b..b28b59b0a5 100644
--- a/crates/ide_completion/src/config.rs
+++ b/crates/ide_completion/src/config.rs
@@ -5,6 +5,8 @@
//! completions if we are allowed to.
use ide_db::helpers::{insert_use::InsertUseConfig, SnippetCap};
+use itertools::Itertools;
+use syntax::ast;
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct CompletionConfig {
@@ -15,4 +17,46 @@ pub struct CompletionConfig {
pub add_call_argument_snippets: bool,
pub snippet_cap: Option<SnippetCap>,
pub insert_use: InsertUseConfig,
+ pub postfix_snippets: Vec<PostfixSnippet>,
+}
+
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub struct PostfixSnippet {
+ pub label: String,
+ snippet: String,
+ pub description: Option<String>,
+ pub requires: Box<[String]>,
+}
+
+impl PostfixSnippet {
+ pub fn new(
+ label: String,
+ snippet: &[String],
+ description: &[String],
+ requires: &[String],
+ ) -> Option<Self> {
+ // validate that these are indeed simple paths
+ if requires.iter().any(|path| match ast::Path::parse(path) {
+ Ok(path) => path.segments().any(|seg| {
+ !matches!(seg.kind(), Some(ast::PathSegmentKind::Name(_)))
+ || seg.generic_arg_list().is_some()
+ }),
+ Err(_) => true,
+ }) {
+ return None;
+ }
+ let snippet = snippet.iter().join("\n");
+ let description = description.iter().join("\n");
+ let description = if description.is_empty() { None } else { Some(description) };
+ Some(PostfixSnippet {
+ label,
+ snippet,
+ description,
+ requires: requires.iter().cloned().collect(), // Box::into doesn't work as that has a Copy bound 😒
+ })
+ }
+
+ pub fn snippet(&self, receiver: &str) -> String {
+ self.snippet.replace("$receiver", receiver)
+ }
}