Skip to content

Commit 87cfc88

Browse files
Merge pull request #21032 from A4-Tacks/no-semicolon-in-arg-list
Fix complete unit return semicolon in arg-list
2 parents b272c35 + 7890856 commit 87cfc88

File tree

2 files changed

+36
-44
lines changed

2 files changed

+36
-44
lines changed

crates/ide-completion/src/context.rs

Lines changed: 15 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ mod analysis;
44
#[cfg(test)]
55
mod tests;
66

7-
use std::{iter, ops::ControlFlow};
7+
use std::iter;
88

99
use base_db::RootQueryDb as _;
1010
use hir::{
@@ -21,7 +21,6 @@ use syntax::{
2121
SyntaxKind::{self, *},
2222
SyntaxToken, T, TextRange, TextSize,
2323
ast::{self, AttrKind, NameOrNameRef},
24-
match_ast,
2524
};
2625

2726
use crate::{
@@ -817,48 +816,20 @@ impl<'db> CompletionContext<'db> {
817816
.extend(exclude_traits.iter().map(|&t| (t.into(), AutoImportExclusionType::Always)));
818817

819818
// FIXME: This should be part of `CompletionAnalysis` / `expand_and_analyze`
820-
let complete_semicolon = if config.add_semicolon_to_unit {
821-
let inside_closure_ret = token.parent_ancestors().try_for_each(|ancestor| {
822-
match_ast! {
823-
match ancestor {
824-
ast::BlockExpr(_) => ControlFlow::Break(false),
825-
ast::ClosureExpr(_) => ControlFlow::Break(true),
826-
_ => ControlFlow::Continue(())
827-
}
828-
}
829-
});
830-
831-
if inside_closure_ret == ControlFlow::Break(true) {
832-
CompleteSemicolon::DoNotComplete
833-
} else {
834-
let next_non_trivia_token =
835-
std::iter::successors(token.next_token(), |it| it.next_token())
836-
.find(|it| !it.kind().is_trivia());
837-
let in_match_arm = token.parent_ancestors().try_for_each(|ancestor| {
838-
if ast::MatchArm::can_cast(ancestor.kind()) {
839-
ControlFlow::Break(true)
840-
} else if matches!(
841-
ancestor.kind(),
842-
SyntaxKind::EXPR_STMT | SyntaxKind::BLOCK_EXPR
843-
) {
844-
ControlFlow::Break(false)
845-
} else {
846-
ControlFlow::Continue(())
847-
}
848-
});
849-
// FIXME: This will assume expr macros are not inside match, we need to somehow go to the "parent" of the root node.
850-
let in_match_arm = match in_match_arm {
851-
ControlFlow::Continue(()) => false,
852-
ControlFlow::Break(it) => it,
853-
};
854-
let complete_token = if in_match_arm { T![,] } else { T![;] };
855-
if next_non_trivia_token.map(|it| it.kind()) == Some(complete_token) {
856-
CompleteSemicolon::DoNotComplete
857-
} else if in_match_arm {
858-
CompleteSemicolon::CompleteComma
859-
} else {
860-
CompleteSemicolon::CompleteSemi
861-
}
819+
let complete_semicolon = if !config.add_semicolon_to_unit {
820+
CompleteSemicolon::DoNotComplete
821+
} else if let Some(term_node) =
822+
sema.token_ancestors_with_macros(token.clone()).find(|node| {
823+
matches!(node.kind(), BLOCK_EXPR | MATCH_ARM | CLOSURE_EXPR | ARG_LIST | PAREN_EXPR)
824+
})
825+
{
826+
let next_token = iter::successors(token.next_token(), |it| it.next_token())
827+
.map(|it| it.kind())
828+
.find(|kind| !kind.is_trivia());
829+
match term_node.kind() {
830+
MATCH_ARM if next_token != Some(T![,]) => CompleteSemicolon::CompleteComma,
831+
BLOCK_EXPR if next_token != Some(T![;]) => CompleteSemicolon::CompleteSemi,
832+
_ => CompleteSemicolon::DoNotComplete,
862833
}
863834
} else {
864835
CompleteSemicolon::DoNotComplete

crates/ide-completion/src/render/function.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -884,6 +884,27 @@ fn baz(_: impl FnOnce()) {}
884884
fn bar() {
885885
baz(|| foo()$0);
886886
}
887+
"#,
888+
);
889+
}
890+
891+
#[test]
892+
fn no_semicolon_in_arg_list() {
893+
check_edit(
894+
r#"foo"#,
895+
r#"
896+
fn foo() {}
897+
fn baz(_: impl FnOnce()) {}
898+
fn bar() {
899+
baz(fo$0);
900+
}
901+
"#,
902+
r#"
903+
fn foo() {}
904+
fn baz(_: impl FnOnce()) {}
905+
fn bar() {
906+
baz(foo()$0);
907+
}
887908
"#,
888909
);
889910
}

0 commit comments

Comments
 (0)