This commit is contained in:
Lukas Wirth 2021-06-07 20:45:17 +02:00
parent b29e8ed994
commit 2987e05f15
5 changed files with 33 additions and 36 deletions

View File

@ -5,8 +5,8 @@
use syntax::{SyntaxKind, T}; use syntax::{SyntaxKind, T};
use crate::{ use crate::{
patterns::ImmediateLocation, CompletionContext, CompletionItem, CompletionItemKind, context::PathCompletionContext, patterns::ImmediateLocation, CompletionContext, CompletionItem,
CompletionKind, Completions, CompletionItemKind, CompletionKind, Completions,
}; };
pub(crate) fn complete_use_tree_keyword(acc: &mut Completions, ctx: &CompletionContext) { pub(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
add_keyword("mut", "mut "); add_keyword("mut", "mut ");
} }
if ctx.in_loop_body { let (can_be_stmt, in_loop_body) = match ctx.path_context {
if ctx.can_be_stmt() { Some(PathCompletionContext {
is_trivial_path: true, can_be_stmt, in_loop_body, ..
}) => (can_be_stmt, in_loop_body),
_ => return,
};
if in_loop_body {
if can_be_stmt {
add_keyword("continue", "continue;"); add_keyword("continue", "continue;");
add_keyword("break", "break;"); add_keyword("break", "break;");
} else { } else {
@ -138,9 +145,6 @@ pub(crate) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte
} }
} }
if !ctx.is_trivial_path() {
return;
}
let fn_def = match &ctx.function_def { let fn_def = match &ctx.function_def {
Some(it) => it, Some(it) => it,
None => return, None => return,
@ -148,7 +152,7 @@ pub(crate) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte
add_keyword( add_keyword(
"return", "return",
match (ctx.can_be_stmt(), fn_def.ret_type().is_some()) { match (can_be_stmt, fn_def.ret_type().is_some()) {
(true, true) => "return $0;", (true, true) => "return $0;",
(true, false) => "return;", (true, false) => "return;",
(false, true) => "return $0", (false, true) => "return $0",

View File

@ -3,8 +3,8 @@
use ide_db::helpers::SnippetCap; use ide_db::helpers::SnippetCap;
use crate::{ use crate::{
item::Builder, CompletionContext, CompletionItem, CompletionItemKind, CompletionKind, context::PathCompletionContext, item::Builder, CompletionContext, CompletionItem,
Completions, CompletionItemKind, CompletionKind, Completions,
}; };
fn snippet(ctx: &CompletionContext, cap: SnippetCap, label: &str, snippet: &str) -> Builder { fn snippet(ctx: &CompletionContext, cap: SnippetCap, label: &str, snippet: &str) -> Builder {
@ -14,15 +14,21 @@ fn snippet(ctx: &CompletionContext, cap: SnippetCap, label: &str, snippet: &str)
} }
pub(crate) fn complete_expr_snippet(acc: &mut Completions, ctx: &CompletionContext) { pub(crate) fn complete_expr_snippet(acc: &mut Completions, ctx: &CompletionContext) {
if !(ctx.is_trivial_path() && ctx.function_def.is_some()) { if ctx.function_def.is_none() {
return; return;
} }
let can_be_stmt = match ctx.path_context {
Some(PathCompletionContext { is_trivial_path: true, can_be_stmt, .. }) => can_be_stmt,
_ => return,
};
let cap = match ctx.config.snippet_cap { let cap = match ctx.config.snippet_cap {
Some(it) => it, Some(it) => it,
None => return, None => return,
}; };
if ctx.can_be_stmt() { if can_be_stmt {
snippet(ctx, cap, "pd", "eprintln!(\"$0 = {:?}\", $0);").add_to(acc); snippet(ctx, cap, "pd", "eprintln!(\"$0 = {:?}\", $0);").add_to(acc);
snippet(ctx, cap, "ppd", "eprintln!(\"$0 = {:#?}\", $0);").add_to(acc); snippet(ctx, cap, "ppd", "eprintln!(\"$0 = {:#?}\", $0);").add_to(acc);
} }

View File

@ -34,20 +34,13 @@
use hir::{self, HasAttrs, HasSource}; use hir::{self, HasAttrs, HasSource};
use ide_db::{traits::get_missing_assoc_items, SymbolKind}; use ide_db::{traits::get_missing_assoc_items, SymbolKind};
use syntax::{ use syntax::{
ast::{self, edit, Impl}, ast::{self, edit},
display::function_declaration, display::function_declaration,
AstNode, SyntaxElement, SyntaxKind, SyntaxNode, TextRange, T, AstNode, SyntaxElement, SyntaxKind, SyntaxNode, SyntaxToken, TextRange, T,
}; };
use text_edit::TextEdit; use text_edit::TextEdit;
use crate::{ use crate::{CompletionContext, CompletionItem, CompletionItemKind, CompletionKind, Completions};
CompletionContext,
CompletionItem,
CompletionItemKind,
CompletionKind,
Completions,
// display::function_declaration,
};
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq)]
enum ImplCompletionKind { enum ImplCompletionKind {
@ -58,7 +51,7 @@ enum ImplCompletionKind {
} }
pub(crate) fn complete_trait_impl(acc: &mut Completions, ctx: &CompletionContext) { pub(crate) fn complete_trait_impl(acc: &mut Completions, ctx: &CompletionContext) {
if let Some((kind, trigger, impl_def)) = completion_match(ctx) { if let Some((kind, trigger, impl_def)) = completion_match(ctx.token.clone()) {
get_missing_assoc_items(&ctx.sema, &impl_def).into_iter().for_each(|item| match item { get_missing_assoc_items(&ctx.sema, &impl_def).into_iter().for_each(|item| match item {
hir::AssocItem::Function(fn_item) hir::AssocItem::Function(fn_item)
if kind == ImplCompletionKind::All || kind == ImplCompletionKind::Fn => if kind == ImplCompletionKind::All || kind == ImplCompletionKind::Fn =>
@ -80,8 +73,7 @@ pub(crate) fn complete_trait_impl(acc: &mut Completions, ctx: &CompletionContext
} }
} }
fn completion_match(ctx: &CompletionContext) -> Option<(ImplCompletionKind, SyntaxNode, Impl)> { fn completion_match(mut token: SyntaxToken) -> Option<(ImplCompletionKind, SyntaxNode, ast::Impl)> {
let mut token = ctx.token.clone();
// For keyword without name like `impl .. { fn $0 }`, the current position is inside // For keyword without name like `impl .. { fn $0 }`, the current position is inside
// the whitespace token, which is outside `FN` syntax node. // the whitespace token, which is outside `FN` syntax node.
// We need to follow the previous token in this case. // We need to follow the previous token in this case.

View File

@ -43,6 +43,7 @@ pub(crate) struct PathCompletionContext {
pub(super) can_be_stmt: bool, pub(super) can_be_stmt: bool,
/// `true` if we expect an expression at the cursor position. /// `true` if we expect an expression at the cursor position.
pub(super) is_expr: bool, pub(super) is_expr: bool,
pub(super) in_loop_body: bool,
} }
#[derive(Copy, Clone, Debug, PartialEq, Eq)] #[derive(Copy, Clone, Debug, PartialEq, Eq)]
@ -94,7 +95,6 @@ pub(crate) struct CompletionContext<'a> {
pub(super) active_parameter: Option<ActiveParameter>, pub(super) active_parameter: Option<ActiveParameter>,
pub(super) locals: Vec<(String, Local)>, pub(super) locals: Vec<(String, Local)>,
pub(super) in_loop_body: bool,
pub(super) incomplete_let: bool, pub(super) incomplete_let: bool,
no_completion_required: bool, no_completion_required: bool,
@ -160,7 +160,6 @@ pub(super) fn new(
path_context: None, path_context: None,
active_parameter: ActiveParameter::at(db, position), active_parameter: ActiveParameter::at(db, position),
locals, locals,
in_loop_body: false,
incomplete_let: false, incomplete_let: false,
no_completion_required: false, no_completion_required: false,
}; };
@ -324,10 +323,6 @@ pub(crate) fn path_qual(&self) -> Option<&ast::Path> {
self.path_context.as_ref().and_then(|it| it.path_qual.as_ref()) self.path_context.as_ref().and_then(|it| it.path_qual.as_ref())
} }
pub(crate) fn can_be_stmt(&self) -> bool {
self.path_context.as_ref().map_or(false, |it| it.can_be_stmt)
}
fn fill_impl_def(&mut self) { fn fill_impl_def(&mut self) {
self.impl_def = self self.impl_def = self
.sema .sema
@ -453,7 +448,6 @@ fn fill(
let for_is_prev2 = for_is_prev2(syntax_element.clone()); let for_is_prev2 = for_is_prev2(syntax_element.clone());
(fn_is_prev && !inside_impl_trait_block) || for_is_prev2 (fn_is_prev && !inside_impl_trait_block) || for_is_prev2
}; };
self.in_loop_body = is_in_loop_body(syntax_element.clone());
self.incomplete_let = self.incomplete_let =
syntax_element.ancestors().take(6).find_map(ast::LetStmt::cast).map_or(false, |it| { syntax_element.ancestors().take(6).find_map(ast::LetStmt::cast).map_or(false, |it| {
@ -584,7 +578,9 @@ fn classify_name_ref(&mut self, original_file: &SyntaxNode, name_ref: ast::NameR
is_path_type: false, is_path_type: false,
can_be_stmt: false, can_be_stmt: false,
is_expr: false, is_expr: false,
in_loop_body: false,
}); });
path_ctx.in_loop_body = is_in_loop_body(name_ref.syntax());
let path = segment.parent_path(); let path = segment.parent_path();
if let Some(p) = path.syntax().parent() { if let Some(p) = path.syntax().parent() {

View File

@ -272,9 +272,8 @@ fn test_for_is_prev2() {
check_pattern_is_applicable(r"for i i$0", for_is_prev2); check_pattern_is_applicable(r"for i i$0", for_is_prev2);
} }
pub(crate) fn is_in_loop_body(element: SyntaxElement) -> bool { pub(crate) fn is_in_loop_body(node: &SyntaxNode) -> bool {
element node.ancestors()
.ancestors()
.take_while(|it| it.kind() != FN && it.kind() != CLOSURE_EXPR) .take_while(|it| it.kind() != FN && it.kind() != CLOSURE_EXPR)
.find_map(|it| { .find_map(|it| {
let loop_body = match_ast! { let loop_body = match_ast! {
@ -285,7 +284,7 @@ pub(crate) fn is_in_loop_body(element: SyntaxElement) -> bool {
_ => None, _ => None,
} }
}; };
loop_body.filter(|it| it.syntax().text_range().contains_range(element.text_range())) loop_body.filter(|it| it.syntax().text_range().contains_range(node.text_range()))
}) })
.is_some() .is_some()
} }