From 522f66545ffe709527dc2102aefe738ffe9ecc17 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Fri, 3 Jun 2022 16:25:37 +0200 Subject: [PATCH] Remove prev-sibling completion machinery --- crates/ide-completion/src/completions/expr.rs | 7 ++- crates/ide-completion/src/context.rs | 28 +++++---- crates/ide-completion/src/patterns.rs | 62 +------------------ 3 files changed, 21 insertions(+), 76 deletions(-) diff --git a/crates/ide-completion/src/completions/expr.rs b/crates/ide-completion/src/completions/expr.rs index ae7b42e3056..780869bb8c2 100644 --- a/crates/ide-completion/src/completions/expr.rs +++ b/crates/ide-completion/src/completions/expr.rs @@ -15,12 +15,12 @@ pub(crate) fn complete_expr_path(acc: &mut Completions, ctx: &CompletionContext) return; } - let (is_absolute_path, qualifier, in_block_expr, in_loop_body, is_func_update) = + let (is_absolute_path, qualifier, in_block_expr, in_loop_body, is_func_update, after_if_expr) = match ctx.nameref_ctx() { Some(NameRefContext { path_ctx: Some(PathCompletionCtx { - kind: PathKind::Expr { in_block_expr, in_loop_body }, + kind: PathKind::Expr { in_block_expr, in_loop_body, after_if_expr }, is_absolute_path, qualifier, .. @@ -33,6 +33,7 @@ pub(crate) fn complete_expr_path(acc: &mut Completions, ctx: &CompletionContext) *in_block_expr, *in_loop_body, record_expr.as_ref().map_or(false, |&(_, it)| it), + *after_if_expr, ), _ => return, }; @@ -202,7 +203,7 @@ pub(crate) fn complete_expr_path(acc: &mut Completions, ctx: &CompletionContext) add_keyword("let", "let"); } - if ctx.after_if() { + if after_if_expr { add_keyword("else", "else {\n $0\n}"); add_keyword("else if", "else if $1 {\n $0\n}"); } diff --git a/crates/ide-completion/src/context.rs b/crates/ide-completion/src/context.rs index ccc7c107468..6068a9eb32c 100644 --- a/crates/ide-completion/src/context.rs +++ b/crates/ide-completion/src/context.rs @@ -15,7 +15,7 @@ use ide_db::{ use syntax::{ algo::{find_node_at_offset, non_trivia_sibling}, ast::{self, AttrKind, HasArgList, HasName, NameOrNameRef}, - match_ast, AstNode, AstToken, NodeOrToken, + match_ast, AstNode, AstToken, Direction, NodeOrToken, SyntaxKind::{self, *}, SyntaxNode, SyntaxToken, TextRange, TextSize, T, }; @@ -23,8 +23,8 @@ use text_edit::Indel; use crate::{ patterns::{ - determine_location, determine_prev_sibling, is_in_loop_body, is_in_token_of_for_loop, - previous_token, ImmediateLocation, ImmediatePrevSibling, + determine_location, is_in_loop_body, is_in_token_of_for_loop, previous_token, + ImmediateLocation, }, CompletionConfig, }; @@ -48,6 +48,7 @@ pub(super) enum PathKind { Expr { in_block_expr: bool, in_loop_body: bool, + after_if_expr: bool, }, Type { in_tuple_struct: bool, @@ -264,7 +265,6 @@ pub(crate) struct CompletionContext<'a> { pub(super) incomplete_let: bool, pub(super) completion_location: Option, - pub(super) prev_sibling: Option, pub(super) previous_token: Option, pub(super) ident_ctx: IdentContext, @@ -345,10 +345,6 @@ impl<'a> CompletionContext<'a> { matches!(self.completion_location, Some(ImmediateLocation::RefExpr)) } - pub(crate) fn after_if(&self) -> bool { - matches!(self.prev_sibling, Some(ImmediatePrevSibling::IfExpr)) - } - // FIXME: This shouldn't exist pub(crate) fn is_path_disallowed(&self) -> bool { !self.qualifier_ctx.none() @@ -527,7 +523,6 @@ impl<'a> CompletionContext<'a> { impl_def: None, incomplete_let: false, completion_location: None, - prev_sibling: None, previous_token: None, // dummy value, will be overwritten ident_ctx: IdentContext::UnexpandedAttrTT { fake_attribute_under_caret: None }, @@ -922,7 +917,6 @@ impl<'a> CompletionContext<'a> { }; self.completion_location = determine_location(&self.sema, original_file, offset, &name_like); - self.prev_sibling = determine_prev_sibling(&name_like); self.impl_def = self .sema .token_ancestors_with_macros(self.token.clone()) @@ -1169,6 +1163,13 @@ impl<'a> CompletionContext<'a> { find_node_in_file_compensated(original_file, &record_expr).zip(Some(true)); } }; + let after_if_expr = |node: SyntaxNode| { + let prev_expr = (|| { + let prev_sibling = non_trivia_sibling(node.into(), Direction::Prev)?.into_node()?; + ast::ExprStmt::cast(prev_sibling)?.expr() + })(); + matches!(prev_expr, Some(ast::Expr::IfExpr(_))) + }; // We do not want to generate path completions when we are sandwiched between an item decl signature and its body. // ex. trait Foo $0 {} @@ -1226,7 +1227,9 @@ impl<'a> CompletionContext<'a> { path_ctx.has_call_parens = it.syntax().parent().map_or(false, |it| ast::CallExpr::can_cast(it.kind())); let in_block_expr = is_in_block(it.syntax()); let in_loop_body = is_in_loop_body(it.syntax()); - Some(PathKind::Expr { in_block_expr, in_loop_body }) + let after_if_expr = after_if_expr(it.syntax().clone()); + + Some(PathKind::Expr { in_block_expr, in_loop_body, after_if_expr }) }, ast::TupleStructPat(it) => { path_ctx.has_call_parens = true; @@ -1274,8 +1277,9 @@ impl<'a> CompletionContext<'a> { return Some(parent.and_then(ast::MacroExpr::cast).map(|it| { let in_loop_body = is_in_loop_body(it.syntax()); let in_block_expr = is_in_block(it.syntax()); + let after_if_expr = after_if_expr(it.syntax().clone()); fill_record_expr(it.syntax()); - PathKind::Expr { in_block_expr, in_loop_body } + PathKind::Expr { in_block_expr, in_loop_body, after_if_expr } })); }, } diff --git a/crates/ide-completion/src/patterns.rs b/crates/ide-completion/src/patterns.rs index 34bfa4517cf..9abbfaa4072 100644 --- a/crates/ide-completion/src/patterns.rs +++ b/crates/ide-completion/src/patterns.rs @@ -7,9 +7,8 @@ use hir::Semantics; use ide_db::RootDatabase; use syntax::{ - algo::non_trivia_sibling, ast::{self, HasLoopBody, HasName}, - match_ast, AstNode, Direction, SyntaxElement, + match_ast, AstNode, SyntaxElement, SyntaxKind::*, SyntaxNode, SyntaxToken, TextRange, TextSize, }; @@ -17,12 +16,6 @@ use syntax::{ #[cfg(test)] use crate::tests::check_pattern_is_applicable; -/// Immediate previous node to what we are completing. -#[derive(Copy, Clone, Debug, PartialEq, Eq)] -pub(crate) enum ImmediatePrevSibling { - IfExpr, -} - #[derive(Clone, Debug, PartialEq, Eq)] pub(crate) enum TypeAnnotation { Let(Option), @@ -46,45 +39,6 @@ pub(crate) enum ImmediateLocation { GenericArgList(ast::GenericArgList), } -pub(crate) fn determine_prev_sibling(name_like: &ast::NameLike) -> Option { - let node = match name_like { - ast::NameLike::NameRef(name_ref) => maximize_name_ref(name_ref), - ast::NameLike::Name(n) => n.syntax().clone(), - ast::NameLike::Lifetime(lt) => lt.syntax().clone(), - }; - let node = match node.parent().and_then(ast::MacroCall::cast) { - // When a path is being typed after the name of a trait/type of an impl it is being - // parsed as a macro, so when the trait/impl has a block following it an we are between the - // name and block the macro will attach the block to itself so maximizing fails to take - // that into account - // FIXME path expr and statement have a similar problem with attrs - Some(call) - if call.excl_token().is_none() - && call.token_tree().map_or(false, |t| t.l_curly_token().is_some()) - && call.semicolon_token().is_none() => - { - call.syntax().clone() - } - _ => node, - }; - let prev_sibling = non_trivia_sibling(node.into(), Direction::Prev)?.into_node()?; - let res = match_ast! { - match prev_sibling { - ast::ExprStmt(it) => { - let node = it.expr().filter(|_| it.semicolon_token().is_none())?.syntax().clone(); - match_ast! { - match node { - ast::IfExpr(_) => ImmediatePrevSibling::IfExpr, - _ => return None, - } - } - }, - _ => return None, - } - }; - Some(res) -} - pub(crate) fn determine_location( sema: &Semantics, original_file: &SyntaxNode, @@ -316,22 +270,8 @@ mod tests { ); } - fn check_prev_sibling(code: &str, sibling: impl Into>) { - check_pattern_is_applicable(code, |e| { - let name = &e.parent().and_then(ast::NameLike::cast).expect("Expected a namelike"); - assert_eq!(determine_prev_sibling(name), sibling.into()); - true - }); - } - #[test] fn test_ref_expr_loc() { check_location(r"fn my_fn() { let x = &m$0 foo; }", ImmediateLocation::RefExpr); } - - #[test] - fn test_if_expr_prev_sibling() { - check_prev_sibling(r"fn foo() { if true {} w$0", ImmediatePrevSibling::IfExpr); - check_prev_sibling(r"fn foo() { if true {}; w$0", None); - } }