]> git.lizzy.rs Git - rust.git/blobdiff - crates/ide_completion/src/completions/postfix.rs
feat: Add very simplistic ident completion for format_args! macro input
[rust.git] / crates / ide_completion / src / completions / postfix.rs
index 87b5d6c4720cb48b2e524e70b3c8785d0c680e6d..e8e0c7ea9f1d1b65d7e66e8a3a206d4bcefe3a09 100644 (file)
@@ -2,9 +2,9 @@
 
 mod format_like;
 
-use hir::Documentation;
+use hir::{Documentation, HasAttrs};
 use ide_db::{
-    helpers::{insert_use::ImportScope, FamousDefs, SnippetCap},
+    helpers::{insert_use::ImportScope, SnippetCap},
     ty_filter::TryEnum,
 };
 use syntax::{
 use text_edit::TextEdit;
 
 use crate::{
-    completions::postfix::format_like::add_format_like_completions,
-    context::CompletionContext,
-    item::{Builder, CompletionKind},
-    patterns::ImmediateLocation,
-    CompletionItem, CompletionItemKind, CompletionRelevance, Completions, SnippetScope,
+    completions::postfix::format_like::add_format_like_completions, context::CompletionContext,
+    item::Builder, patterns::ImmediateLocation, CompletionItem, CompletionItemKind,
+    CompletionRelevance, Completions, SnippetScope,
 };
 
 pub(crate) fn complete_postfix(acc: &mut Completions, ctx: &CompletionContext) {
@@ -45,8 +43,9 @@ pub(crate) fn complete_postfix(acc: &mut Completions, ctx: &CompletionContext) {
 
     // Suggest .await syntax for types that implement Future trait
     if receiver_ty.impls_future(ctx.db) {
-        let mut item = CompletionItem::new(CompletionKind::Keyword, ctx.source_range(), "await");
-        item.kind(CompletionItemKind::Keyword).detail("expr.await");
+        let mut item =
+            CompletionItem::new(CompletionItemKind::Keyword, ctx.source_range(), "await");
+        item.detail("expr.await");
         item.add_to(acc);
     }
 
@@ -60,6 +59,22 @@ pub(crate) fn complete_postfix(acc: &mut Completions, ctx: &CompletionContext) {
         None => return,
     };
 
+    if let Some(drop_trait) = ctx.famous_defs().core_ops_Drop() {
+        if receiver_ty.impls_trait(ctx.db, drop_trait, &[]) {
+            if let &[hir::AssocItem::Function(drop_fn)] = &*drop_trait.items(ctx.db) {
+                cov_mark::hit!(postfix_drop_completion);
+                // FIXME: check that `drop` is in scope, use fully qualified path if it isn't/if shadowed
+                let mut item = postfix_snippet(
+                    "drop",
+                    "fn drop(&mut self)",
+                    &format!("drop($0{})", receiver_text),
+                );
+                item.set_documentation(drop_fn.docs(ctx.db));
+                item.add_to(acc);
+            }
+        }
+    }
+
     if !ctx.config.snippets.is_empty() {
         add_custom_postfix_completions(acc, ctx, &postfix_snippet, &receiver_text);
     }
@@ -108,7 +123,7 @@ pub(crate) fn complete_postfix(acc: &mut Completions, ctx: &CompletionContext) {
         )
         .add_to(acc);
         postfix_snippet("not", "!expr", &format!("!{}", receiver_text)).add_to(acc);
-    } else if let Some(trait_) = FamousDefs(&ctx.sema, ctx.krate).core_iter_IntoIterator() {
+    } else if let Some(trait_) = ctx.famous_defs().core_iter_IntoIterator() {
         if receiver_ty.impls_trait(ctx.db, trait_, &[]) {
             postfix_snippet(
                 "for",
@@ -164,10 +179,7 @@ pub(crate) fn complete_postfix(acc: &mut Completions, ctx: &CompletionContext) {
     }
 
     postfix_snippet("box", "Box::new(expr)", &format!("Box::new({})", receiver_text)).add_to(acc);
-    postfix_snippet("ok", "Ok(expr)", &format!("Ok({})", receiver_text)).add_to(acc);
-    postfix_snippet("err", "Err(expr)", &format!("Err({})", receiver_text)).add_to(acc);
-    postfix_snippet("some", "Some(expr)", &format!("Some({})", receiver_text)).add_to(acc);
-    postfix_snippet("dbg", "dbg!(expr)", &format!("dbg!({})", receiver_text)).add_to(acc);
+    postfix_snippet("dbg", "dbg!(expr)", &format!("dbg!({})", receiver_text)).add_to(acc); // fixme
     postfix_snippet("dbgr", "dbg!(&expr)", &format!("dbg!(&{})", receiver_text)).add_to(acc);
     postfix_snippet("call", "function(expr)", &format!("${{1}}({})", receiver_text)).add_to(acc);
 
@@ -213,6 +225,10 @@ fn build_postfix_snippet_builder<'ctx>(
 ) -> Option<impl Fn(&str, &str, &str) -> Builder + 'ctx> {
     let receiver_syntax = receiver.syntax();
     let receiver_range = ctx.sema.original_range_opt(receiver_syntax)?.range;
+    if ctx.source_range().end() < receiver_range.start() {
+        // This shouldn't happen, yet it does. I assume this might be due to an incorrect token mapping.
+        return None;
+    }
     let delete_range = TextRange::new(receiver_range.start(), ctx.source_range().end());
 
     // Wrapping impl Fn in an option ruins lifetime inference for the parameters in a way that
@@ -224,8 +240,9 @@ fn build<'ctx>(
     ) -> impl Fn(&str, &str, &str) -> Builder + 'ctx {
         move |label, detail, snippet| {
             let edit = TextEdit::replace(delete_range, snippet.to_string());
-            let mut item = CompletionItem::new(CompletionKind::Postfix, ctx.source_range(), label);
-            item.detail(detail).kind(CompletionItemKind::Snippet).snippet_edit(cap, edit);
+            let mut item =
+                CompletionItem::new(CompletionItemKind::Snippet, ctx.source_range(), label);
+            item.detail(detail).snippet_edit(cap, edit);
             if ctx.original_token.text() == label {
                 let relevance =
                     CompletionRelevance { exact_postfix_snippet_match: true, ..Default::default() };
@@ -244,8 +261,7 @@ fn add_custom_postfix_completions(
     postfix_snippet: impl Fn(&str, &str, &str) -> Builder,
     receiver_text: &str,
 ) -> Option<()> {
-    let import_scope =
-        ImportScope::find_insert_use_container_with_macros(&ctx.token.parent()?, &ctx.sema)?;
+    let import_scope = ImportScope::find_insert_use_container(&ctx.token.parent()?, &ctx.sema)?;
     ctx.config.postfix_snippets().filter(|(_, snip)| snip.scope == SnippetScope::Expr).for_each(
         |(trigger, snippet)| {
             let imports = match snippet.imports(ctx, &import_scope) {
@@ -296,9 +312,6 @@ fn main() {
                 sn refm  &mut expr
                 sn match match expr {}
                 sn box   Box::new(expr)
-                sn ok    Ok(expr)
-                sn err   Err(expr)
-                sn some  Some(expr)
                 sn dbg   dbg!(expr)
                 sn dbgr  dbg!(&expr)
                 sn call  function(expr)
@@ -329,9 +342,6 @@ fn main() {
                 sn refm  &mut expr
                 sn match match expr {}
                 sn box   Box::new(expr)
-                sn ok    Ok(expr)
-                sn err   Err(expr)
-                sn some  Some(expr)
                 sn dbg   dbg!(expr)
                 sn dbgr  dbg!(&expr)
                 sn call  function(expr)
@@ -353,9 +363,6 @@ fn main() {
                 sn refm  &mut expr
                 sn match match expr {}
                 sn box   Box::new(expr)
-                sn ok    Ok(expr)
-                sn err   Err(expr)
-                sn some  Some(expr)
                 sn dbg   dbg!(expr)
                 sn dbgr  dbg!(&expr)
                 sn call  function(expr)
@@ -382,9 +389,6 @@ fn main() {
                 sn refm  &mut expr
                 sn match match expr {}
                 sn box   Box::new(expr)
-                sn ok    Ok(expr)
-                sn err   Err(expr)
-                sn some  Some(expr)
                 sn dbg   dbg!(expr)
                 sn dbgr  dbg!(&expr)
                 sn call  function(expr)