From e1396bde73900c638112c34bbf1b9b7e31a20a0d Mon Sep 17 00:00:00 2001 From: Duong Quoc Khanh Date: Sat, 11 Feb 2023 21:26:00 +0900 Subject: [PATCH 1/2] Don't trigger postfix completion `if` block which has an `else` block Discard postfix completion if the next_non_trivia_sibling of dot_token is an ELSE_KW. --- .../ide-completion/src/completions/postfix.rs | 12 +++++++++++ crates/ide-completion/src/context/analysis.rs | 20 +++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/crates/ide-completion/src/completions/postfix.rs b/crates/ide-completion/src/completions/postfix.rs index 90c523735d..c55bd9aaae 100644 --- a/crates/ide-completion/src/completions/postfix.rs +++ b/crates/ide-completion/src/completions/postfix.rs @@ -747,4 +747,16 @@ fn main() { "#, ); } + + #[test] + fn no_postfix_completions_in_if_block_that_has_an_else() { + check( + r#" +fn test() { + if true {}.$0 else {} +} +"#, + expect![[r#""#]], + ); + } } diff --git a/crates/ide-completion/src/context/analysis.rs b/crates/ide-completion/src/context/analysis.rs index 4bff665ab1..48066736c5 100644 --- a/crates/ide-completion/src/context/analysis.rs +++ b/crates/ide-completion/src/context/analysis.rs @@ -605,6 +605,26 @@ fn classify_name_ref( }, _ => false, }; + + let reciever_is_part_of_indivisible_expression = match &receiver { + Some(ast::Expr::IfExpr(_)) => { + let next_sibling = field.dot_token().and_then(|token| { + let dot_token = original_file.covering_element(token.text_range()); + let next_sibling = dot_token.as_token().and_then(|t| t.next_token()).and_then(|t| next_non_trivia_sibling(t.into())); + next_sibling + }); + match next_sibling { + Some(syntax::NodeOrToken::Node(n)) => n.first_child_or_token().map(|t| t.kind()) == Some(SyntaxKind::ELSE_KW), + Some(syntax::NodeOrToken::Token(t)) => t.kind() == SyntaxKind::ELSE_KW, + None => false + } + }, + _ => false + }; + if reciever_is_part_of_indivisible_expression { + return None; + } + let kind = NameRefKind::DotAccess(DotAccess { receiver_ty: receiver.as_ref().and_then(|it| sema.type_of_expr(it)), kind: DotAccessKind::Field { receiver_is_ambiguous_float_literal }, From 0285acc5f791e1d2bf652abb88ffeb0a75c1165a Mon Sep 17 00:00:00 2001 From: Duong Quoc Khanh Date: Mon, 13 Feb 2023 20:11:04 +0900 Subject: [PATCH 2/2] Find `next_non_trivia_token` of `name_ref`. --- crates/ide-completion/src/context/analysis.rs | 28 ++++++++++++------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/crates/ide-completion/src/context/analysis.rs b/crates/ide-completion/src/context/analysis.rs index 48066736c5..4c66f95903 100644 --- a/crates/ide-completion/src/context/analysis.rs +++ b/crates/ide-completion/src/context/analysis.rs @@ -608,16 +608,8 @@ fn classify_name_ref( let reciever_is_part_of_indivisible_expression = match &receiver { Some(ast::Expr::IfExpr(_)) => { - let next_sibling = field.dot_token().and_then(|token| { - let dot_token = original_file.covering_element(token.text_range()); - let next_sibling = dot_token.as_token().and_then(|t| t.next_token()).and_then(|t| next_non_trivia_sibling(t.into())); - next_sibling - }); - match next_sibling { - Some(syntax::NodeOrToken::Node(n)) => n.first_child_or_token().map(|t| t.kind()) == Some(SyntaxKind::ELSE_KW), - Some(syntax::NodeOrToken::Token(t)) => t.kind() == SyntaxKind::ELSE_KW, - None => false - } + let next_token_kind = next_non_trivia_token(name_ref.syntax().clone()).map(|t| t.kind()); + next_token_kind == Some(SyntaxKind::ELSE_KW) }, _ => false }; @@ -1337,6 +1329,22 @@ fn previous_non_trivia_token(e: impl Into) -> Option None } +fn next_non_trivia_token(e: impl Into) -> Option { + let mut token = match e.into() { + SyntaxElement::Node(n) => n.last_token()?, + SyntaxElement::Token(t) => t, + } + .next_token(); + while let Some(inner) = token { + if !inner.kind().is_trivia() { + return Some(inner); + } else { + token = inner.next_token(); + } + } + None +} + fn next_non_trivia_sibling(ele: SyntaxElement) -> Option { let mut e = ele.next_sibling_or_token(); while let Some(inner) = e {