1 //! This file provides snippet completions, like `pd` => `eprintln!(...)`.
3 use hir::Documentation;
4 use ide_db::{imports::insert_use::ImportScope, SnippetCap};
7 context::{ExprCtx, ItemListKind, PathCompletionCtx, Qualified},
9 CompletionContext, CompletionItem, CompletionItemKind, Completions, SnippetScope,
12 pub(crate) fn complete_expr_snippet(
13 acc: &mut Completions,
14 ctx: &CompletionContext<'_>,
15 path_ctx: &PathCompletionCtx,
16 &ExprCtx { in_block_expr, .. }: &ExprCtx,
18 if !matches!(path_ctx.qualified, Qualified::No) {
21 if !ctx.qualifier_ctx.none() {
25 let cap = match ctx.config.snippet_cap {
30 if !ctx.config.snippets.is_empty() {
31 add_custom_completions(acc, ctx, cap, SnippetScope::Expr);
35 snippet(ctx, cap, "pd", "eprintln!(\"$0 = {:?}\", $0);").add_to(acc);
36 snippet(ctx, cap, "ppd", "eprintln!(\"$0 = {:#?}\", $0);").add_to(acc);
52 pub(crate) fn complete_item_snippet(
53 acc: &mut Completions,
54 ctx: &CompletionContext<'_>,
55 path_ctx: &PathCompletionCtx,
58 if !matches!(path_ctx.qualified, Qualified::No) {
61 if !ctx.qualifier_ctx.none() {
64 let cap = match ctx.config.snippet_cap {
69 if !ctx.config.snippets.is_empty() {
70 add_custom_completions(acc, ctx, cap, SnippetScope::Item);
73 // Test-related snippets shouldn't be shown in blocks.
74 if let ItemListKind::SourceFile | ItemListKind::Module = kind {
75 let mut item = snippet(
90 item.lookup_by("tmod");
93 let mut item = snippet(
96 "tfn (Test function)",
103 item.lookup_by("tfn");
121 fn snippet(ctx: &CompletionContext<'_>, cap: SnippetCap, label: &str, snippet: &str) -> Builder {
122 let mut item = CompletionItem::new(CompletionItemKind::Snippet, ctx.source_range(), label);
123 item.insert_snippet(cap, snippet);
127 fn add_custom_completions(
128 acc: &mut Completions,
129 ctx: &CompletionContext<'_>,
133 if ImportScope::find_insert_use_container(&ctx.token.parent()?, &ctx.sema).is_none() {
136 ctx.config.prefix_snippets().filter(|(_, snip)| snip.scope == scope).for_each(
138 let imports = match snip.imports(ctx) {
139 Some(imports) => imports,
142 let body = snip.snippet();
143 let mut builder = snippet(ctx, cap, trigger, &body);
144 builder.documentation(Documentation::new(format!("```rust\n{}\n```", body)));
145 for import in imports.into_iter() {
146 builder.add_import(import);
148 builder.set_detail(snip.description.clone());
158 tests::{check_edit_with_config, TEST_CONFIG},
159 CompletionConfig, Snippet,
163 fn custom_snippet_completion() {
164 check_edit_with_config(
166 snippets: vec![Snippet::new(
169 &["ControlFlow::Break(())".into()],
171 &["core::ops::ControlFlow".into()],
172 crate::SnippetScope::Expr,
183 use core::ops::ControlFlow;
185 fn main() { ControlFlow::Break(()) }