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 crate::{
patterns::ImmediateLocation, CompletionContext, CompletionItem, CompletionItemKind,
CompletionKind, Completions,
context::PathCompletionContext, patterns::ImmediateLocation, CompletionContext, CompletionItem,
CompletionItemKind, CompletionKind, Completions,
};
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 ");
}
if ctx.in_loop_body {
if ctx.can_be_stmt() {
let (can_be_stmt, in_loop_body) = match ctx.path_context {
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("break", "break;");
} 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 {
Some(it) => it,
None => return,
@ -148,7 +152,7 @@ pub(crate) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte
add_keyword(
"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, false) => "return;",
(false, true) => "return $0",

View File

@ -3,8 +3,8 @@
use ide_db::helpers::SnippetCap;
use crate::{
item::Builder, CompletionContext, CompletionItem, CompletionItemKind, CompletionKind,
Completions,
context::PathCompletionContext, item::Builder, CompletionContext, CompletionItem,
CompletionItemKind, CompletionKind, Completions,
};
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) {
if !(ctx.is_trivial_path() && ctx.function_def.is_some()) {
if ctx.function_def.is_none() {
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 {
Some(it) => it,
None => return,
};
if ctx.can_be_stmt() {
if can_be_stmt {
snippet(ctx, cap, "pd", "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 ide_db::{traits::get_missing_assoc_items, SymbolKind};
use syntax::{
ast::{self, edit, Impl},
ast::{self, edit},
display::function_declaration,
AstNode, SyntaxElement, SyntaxKind, SyntaxNode, TextRange, T,
AstNode, SyntaxElement, SyntaxKind, SyntaxNode, SyntaxToken, TextRange, T,
};
use text_edit::TextEdit;
use crate::{
CompletionContext,
CompletionItem,
CompletionItemKind,
CompletionKind,
Completions,
// display::function_declaration,
};
use crate::{CompletionContext, CompletionItem, CompletionItemKind, CompletionKind, Completions};
#[derive(Debug, PartialEq, Eq)]
enum ImplCompletionKind {
@ -58,7 +51,7 @@ enum ImplCompletionKind {
}
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 {
hir::AssocItem::Function(fn_item)
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)> {
let mut token = ctx.token.clone();
fn completion_match(mut token: SyntaxToken) -> Option<(ImplCompletionKind, SyntaxNode, ast::Impl)> {
// For keyword without name like `impl .. { fn $0 }`, the current position is inside
// the whitespace token, which is outside `FN` syntax node.
// 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,
/// `true` if we expect an expression at the cursor position.
pub(super) is_expr: bool,
pub(super) in_loop_body: bool,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
@ -94,7 +95,6 @@ pub(crate) struct CompletionContext<'a> {
pub(super) active_parameter: Option<ActiveParameter>,
pub(super) locals: Vec<(String, Local)>,
pub(super) in_loop_body: bool,
pub(super) incomplete_let: bool,
no_completion_required: bool,
@ -160,7 +160,6 @@ pub(super) fn new(
path_context: None,
active_parameter: ActiveParameter::at(db, position),
locals,
in_loop_body: false,
incomplete_let: 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())
}
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) {
self.impl_def = self
.sema
@ -453,7 +448,6 @@ fn fill(
let for_is_prev2 = for_is_prev2(syntax_element.clone());
(fn_is_prev && !inside_impl_trait_block) || for_is_prev2
};
self.in_loop_body = is_in_loop_body(syntax_element.clone());
self.incomplete_let =
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,
can_be_stmt: 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();
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);
}
pub(crate) fn is_in_loop_body(element: SyntaxElement) -> bool {
element
.ancestors()
pub(crate) fn is_in_loop_body(node: &SyntaxNode) -> bool {
node.ancestors()
.take_while(|it| it.kind() != FN && it.kind() != CLOSURE_EXPR)
.find_map(|it| {
let loop_body = match_ast! {
@ -285,7 +284,7 @@ pub(crate) fn is_in_loop_body(element: SyntaxElement) -> bool {
_ => 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()
}