aboutsummaryrefslogtreecommitdiff
path: root/crates/ide_completion
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ide_completion')
-rw-r--r--crates/ide_completion/src/completions/keyword.rs20
-rw-r--r--crates/ide_completion/src/completions/snippet.rs14
-rw-r--r--crates/ide_completion/src/completions/trait_impl.rs18
-rw-r--r--crates/ide_completion/src/context.rs10
-rw-r--r--crates/ide_completion/src/patterns.rs7
5 files changed, 33 insertions, 36 deletions
diff --git a/crates/ide_completion/src/completions/keyword.rs b/crates/ide_completion/src/completions/keyword.rs
index 0ca97a0e4..ba13d3707 100644
--- a/crates/ide_completion/src/completions/keyword.rs
+++ b/crates/ide_completion/src/completions/keyword.rs
@@ -5,8 +5,8 @@ use std::iter;
5use syntax::{SyntaxKind, T}; 5use syntax::{SyntaxKind, T};
6 6
7use crate::{ 7use crate::{
8 patterns::ImmediateLocation, CompletionContext, CompletionItem, CompletionItemKind, 8 context::PathCompletionContext, patterns::ImmediateLocation, CompletionContext, CompletionItem,
9 CompletionKind, Completions, 9 CompletionItemKind, CompletionKind, Completions,
10}; 10};
11 11
12pub(crate) fn complete_use_tree_keyword(acc: &mut Completions, ctx: &CompletionContext) { 12pub(crate) fn complete_use_tree_keyword(acc: &mut Completions, ctx: &CompletionContext) {
@@ -128,8 +128,15 @@ pub(crate) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte
128 add_keyword("mut", "mut "); 128 add_keyword("mut", "mut ");
129 } 129 }
130 130
131 if ctx.in_loop_body { 131 let (can_be_stmt, in_loop_body) = match ctx.path_context {
132 if ctx.can_be_stmt() { 132 Some(PathCompletionContext {
133 is_trivial_path: true, can_be_stmt, in_loop_body, ..
134 }) => (can_be_stmt, in_loop_body),
135 _ => return,
136 };
137
138 if in_loop_body {
139 if can_be_stmt {
133 add_keyword("continue", "continue;"); 140 add_keyword("continue", "continue;");
134 add_keyword("break", "break;"); 141 add_keyword("break", "break;");
135 } else { 142 } else {
@@ -138,9 +145,6 @@ pub(crate) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte
138 } 145 }
139 } 146 }
140 147
141 if !ctx.is_trivial_path() {
142 return;
143 }
144 let fn_def = match &ctx.function_def { 148 let fn_def = match &ctx.function_def {
145 Some(it) => it, 149 Some(it) => it,
146 None => return, 150 None => return,
@@ -148,7 +152,7 @@ pub(crate) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte
148 152
149 add_keyword( 153 add_keyword(
150 "return", 154 "return",
151 match (ctx.can_be_stmt(), fn_def.ret_type().is_some()) { 155 match (can_be_stmt, fn_def.ret_type().is_some()) {
152 (true, true) => "return $0;", 156 (true, true) => "return $0;",
153 (true, false) => "return;", 157 (true, false) => "return;",
154 (false, true) => "return $0", 158 (false, true) => "return $0",
diff --git a/crates/ide_completion/src/completions/snippet.rs b/crates/ide_completion/src/completions/snippet.rs
index 59a338e7b..b9862de67 100644
--- a/crates/ide_completion/src/completions/snippet.rs
+++ b/crates/ide_completion/src/completions/snippet.rs
@@ -3,8 +3,8 @@
3use ide_db::helpers::SnippetCap; 3use ide_db::helpers::SnippetCap;
4 4
5use crate::{ 5use crate::{
6 item::Builder, CompletionContext, CompletionItem, CompletionItemKind, CompletionKind, 6 context::PathCompletionContext, item::Builder, CompletionContext, CompletionItem,
7 Completions, 7 CompletionItemKind, CompletionKind, Completions,
8}; 8};
9 9
10fn snippet(ctx: &CompletionContext, cap: SnippetCap, label: &str, snippet: &str) -> Builder { 10fn snippet(ctx: &CompletionContext, cap: SnippetCap, label: &str, snippet: &str) -> Builder {
@@ -14,15 +14,21 @@ fn snippet(ctx: &CompletionContext, cap: SnippetCap, label: &str, snippet: &str)
14} 14}
15 15
16pub(crate) fn complete_expr_snippet(acc: &mut Completions, ctx: &CompletionContext) { 16pub(crate) fn complete_expr_snippet(acc: &mut Completions, ctx: &CompletionContext) {
17 if !(ctx.is_trivial_path() && ctx.function_def.is_some()) { 17 if ctx.function_def.is_none() {
18 return; 18 return;
19 } 19 }
20
21 let can_be_stmt = match ctx.path_context {
22 Some(PathCompletionContext { is_trivial_path: true, can_be_stmt, .. }) => can_be_stmt,
23 _ => return,
24 };
25
20 let cap = match ctx.config.snippet_cap { 26 let cap = match ctx.config.snippet_cap {
21 Some(it) => it, 27 Some(it) => it,
22 None => return, 28 None => return,
23 }; 29 };
24 30
25 if ctx.can_be_stmt() { 31 if can_be_stmt {
26 snippet(ctx, cap, "pd", "eprintln!(\"$0 = {:?}\", $0);").add_to(acc); 32 snippet(ctx, cap, "pd", "eprintln!(\"$0 = {:?}\", $0);").add_to(acc);
27 snippet(ctx, cap, "ppd", "eprintln!(\"$0 = {:#?}\", $0);").add_to(acc); 33 snippet(ctx, cap, "ppd", "eprintln!(\"$0 = {:#?}\", $0);").add_to(acc);
28 } 34 }
diff --git a/crates/ide_completion/src/completions/trait_impl.rs b/crates/ide_completion/src/completions/trait_impl.rs
index 968c0254d..a60e5f43c 100644
--- a/crates/ide_completion/src/completions/trait_impl.rs
+++ b/crates/ide_completion/src/completions/trait_impl.rs
@@ -34,20 +34,13 @@
34use hir::{self, HasAttrs, HasSource}; 34use hir::{self, HasAttrs, HasSource};
35use ide_db::{traits::get_missing_assoc_items, SymbolKind}; 35use ide_db::{traits::get_missing_assoc_items, SymbolKind};
36use syntax::{ 36use syntax::{
37 ast::{self, edit, Impl}, 37 ast::{self, edit},
38 display::function_declaration, 38 display::function_declaration,
39 AstNode, SyntaxElement, SyntaxKind, SyntaxNode, TextRange, T, 39 AstNode, SyntaxElement, SyntaxKind, SyntaxNode, SyntaxToken, TextRange, T,
40}; 40};
41use text_edit::TextEdit; 41use text_edit::TextEdit;
42 42
43use crate::{ 43use crate::{CompletionContext, CompletionItem, CompletionItemKind, CompletionKind, Completions};
44 CompletionContext,
45 CompletionItem,
46 CompletionItemKind,
47 CompletionKind,
48 Completions,
49 // display::function_declaration,
50};
51 44
52#[derive(Debug, PartialEq, Eq)] 45#[derive(Debug, PartialEq, Eq)]
53enum ImplCompletionKind { 46enum ImplCompletionKind {
@@ -58,7 +51,7 @@ enum ImplCompletionKind {
58} 51}
59 52
60pub(crate) fn complete_trait_impl(acc: &mut Completions, ctx: &CompletionContext) { 53pub(crate) fn complete_trait_impl(acc: &mut Completions, ctx: &CompletionContext) {
61 if let Some((kind, trigger, impl_def)) = completion_match(ctx) { 54 if let Some((kind, trigger, impl_def)) = completion_match(ctx.token.clone()) {
62 get_missing_assoc_items(&ctx.sema, &impl_def).into_iter().for_each(|item| match item { 55 get_missing_assoc_items(&ctx.sema, &impl_def).into_iter().for_each(|item| match item {
63 hir::AssocItem::Function(fn_item) 56 hir::AssocItem::Function(fn_item)
64 if kind == ImplCompletionKind::All || kind == ImplCompletionKind::Fn => 57 if kind == ImplCompletionKind::All || kind == ImplCompletionKind::Fn =>
@@ -80,8 +73,7 @@ pub(crate) fn complete_trait_impl(acc: &mut Completions, ctx: &CompletionContext
80 } 73 }
81} 74}
82 75
83fn completion_match(ctx: &CompletionContext) -> Option<(ImplCompletionKind, SyntaxNode, Impl)> { 76fn completion_match(mut token: SyntaxToken) -> Option<(ImplCompletionKind, SyntaxNode, ast::Impl)> {
84 let mut token = ctx.token.clone();
85 // For keyword without name like `impl .. { fn $0 }`, the current position is inside 77 // For keyword without name like `impl .. { fn $0 }`, the current position is inside
86 // the whitespace token, which is outside `FN` syntax node. 78 // the whitespace token, which is outside `FN` syntax node.
87 // We need to follow the previous token in this case. 79 // We need to follow the previous token in this case.
diff --git a/crates/ide_completion/src/context.rs b/crates/ide_completion/src/context.rs
index 7e4b14926..6177caa12 100644
--- a/crates/ide_completion/src/context.rs
+++ b/crates/ide_completion/src/context.rs
@@ -43,6 +43,7 @@ pub(crate) struct PathCompletionContext {
43 pub(super) can_be_stmt: bool, 43 pub(super) can_be_stmt: bool,
44 /// `true` if we expect an expression at the cursor position. 44 /// `true` if we expect an expression at the cursor position.
45 pub(super) is_expr: bool, 45 pub(super) is_expr: bool,
46 pub(super) in_loop_body: bool,
46} 47}
47 48
48#[derive(Copy, Clone, Debug, PartialEq, Eq)] 49#[derive(Copy, Clone, Debug, PartialEq, Eq)]
@@ -94,7 +95,6 @@ pub(crate) struct CompletionContext<'a> {
94 pub(super) active_parameter: Option<ActiveParameter>, 95 pub(super) active_parameter: Option<ActiveParameter>,
95 pub(super) locals: Vec<(String, Local)>, 96 pub(super) locals: Vec<(String, Local)>,
96 97
97 pub(super) in_loop_body: bool,
98 pub(super) incomplete_let: bool, 98 pub(super) incomplete_let: bool,
99 99
100 no_completion_required: bool, 100 no_completion_required: bool,
@@ -160,7 +160,6 @@ impl<'a> CompletionContext<'a> {
160 path_context: None, 160 path_context: None,
161 active_parameter: ActiveParameter::at(db, position), 161 active_parameter: ActiveParameter::at(db, position),
162 locals, 162 locals,
163 in_loop_body: false,
164 incomplete_let: false, 163 incomplete_let: false,
165 no_completion_required: false, 164 no_completion_required: false,
166 }; 165 };
@@ -324,10 +323,6 @@ impl<'a> CompletionContext<'a> {
324 self.path_context.as_ref().and_then(|it| it.path_qual.as_ref()) 323 self.path_context.as_ref().and_then(|it| it.path_qual.as_ref())
325 } 324 }
326 325
327 pub(crate) fn can_be_stmt(&self) -> bool {
328 self.path_context.as_ref().map_or(false, |it| it.can_be_stmt)
329 }
330
331 fn fill_impl_def(&mut self) { 326 fn fill_impl_def(&mut self) {
332 self.impl_def = self 327 self.impl_def = self
333 .sema 328 .sema
@@ -453,7 +448,6 @@ impl<'a> CompletionContext<'a> {
453 let for_is_prev2 = for_is_prev2(syntax_element.clone()); 448 let for_is_prev2 = for_is_prev2(syntax_element.clone());
454 (fn_is_prev && !inside_impl_trait_block) || for_is_prev2 449 (fn_is_prev && !inside_impl_trait_block) || for_is_prev2
455 }; 450 };
456 self.in_loop_body = is_in_loop_body(syntax_element.clone());
457 451
458 self.incomplete_let = 452 self.incomplete_let =
459 syntax_element.ancestors().take(6).find_map(ast::LetStmt::cast).map_or(false, |it| { 453 syntax_element.ancestors().take(6).find_map(ast::LetStmt::cast).map_or(false, |it| {
@@ -584,7 +578,9 @@ impl<'a> CompletionContext<'a> {
584 is_path_type: false, 578 is_path_type: false,
585 can_be_stmt: false, 579 can_be_stmt: false,
586 is_expr: false, 580 is_expr: false,
581 in_loop_body: false,
587 }); 582 });
583 path_ctx.in_loop_body = is_in_loop_body(name_ref.syntax());
588 let path = segment.parent_path(); 584 let path = segment.parent_path();
589 585
590 if let Some(p) = path.syntax().parent() { 586 if let Some(p) = path.syntax().parent() {
diff --git a/crates/ide_completion/src/patterns.rs b/crates/ide_completion/src/patterns.rs
index 251d76fe9..ee87bf461 100644
--- a/crates/ide_completion/src/patterns.rs
+++ b/crates/ide_completion/src/patterns.rs
@@ -272,9 +272,8 @@ fn test_for_is_prev2() {
272 check_pattern_is_applicable(r"for i i$0", for_is_prev2); 272 check_pattern_is_applicable(r"for i i$0", for_is_prev2);
273} 273}
274 274
275pub(crate) fn is_in_loop_body(element: SyntaxElement) -> bool { 275pub(crate) fn is_in_loop_body(node: &SyntaxNode) -> bool {
276 element 276 node.ancestors()
277 .ancestors()
278 .take_while(|it| it.kind() != FN && it.kind() != CLOSURE_EXPR) 277 .take_while(|it| it.kind() != FN && it.kind() != CLOSURE_EXPR)
279 .find_map(|it| { 278 .find_map(|it| {
280 let loop_body = match_ast! { 279 let loop_body = match_ast! {
@@ -285,7 +284,7 @@ pub(crate) fn is_in_loop_body(element: SyntaxElement) -> bool {
285 _ => None, 284 _ => None,
286 } 285 }
287 }; 286 };
288 loop_body.filter(|it| it.syntax().text_range().contains_range(element.text_range())) 287 loop_body.filter(|it| it.syntax().text_range().contains_range(node.text_range()))
289 }) 288 })
290 .is_some() 289 .is_some()
291} 290}