Still complete parentheses & method call arguments if there are existing parentheses, but they are after a newline
This commit is contained in:
parent
45f2d3c67a
commit
db9c18e44e
2 changed files with 76 additions and 3 deletions
|
|
@ -883,9 +883,10 @@ fn classify_name_ref(
|
|||
},
|
||||
ast::MethodCallExpr(method) => {
|
||||
let receiver = find_opt_node_in_file(original_file, method.receiver());
|
||||
let has_parens = has_parens(&method);
|
||||
let kind = NameRefKind::DotAccess(DotAccess {
|
||||
receiver_ty: receiver.as_ref().and_then(|it| sema.type_of_expr(it)),
|
||||
kind: DotAccessKind::Method { has_parens: method.arg_list().is_some_and(|it| it.l_paren_token().is_some()) },
|
||||
kind: DotAccessKind::Method { has_parens },
|
||||
receiver,
|
||||
ctx: DotAccessExprCtx { in_block_expr: is_in_block(method.syntax()), in_breakable: is_in_breakable(method.syntax()) }
|
||||
});
|
||||
|
|
@ -1372,7 +1373,7 @@ fn classify_name_ref(
|
|||
}
|
||||
}
|
||||
|
||||
path_ctx.has_call_parens = it.syntax().parent().is_some_and(|it| ast::CallExpr::can_cast(it.kind()));
|
||||
path_ctx.has_call_parens = it.syntax().parent().is_some_and(|it| ast::CallExpr::cast(it).is_some_and(|it| has_parens(&it)));
|
||||
|
||||
make_path_kind_expr(it.into())
|
||||
},
|
||||
|
|
@ -1401,7 +1402,7 @@ fn classify_name_ref(
|
|||
match parent {
|
||||
ast::PathType(it) => make_path_kind_type(it.into()),
|
||||
ast::PathExpr(it) => {
|
||||
path_ctx.has_call_parens = it.syntax().parent().is_some_and(|it| ast::CallExpr::can_cast(it.kind()));
|
||||
path_ctx.has_call_parens = it.syntax().parent().is_some_and(|it| ast::CallExpr::cast(it).is_some_and(|it| has_parens(&it)));
|
||||
|
||||
make_path_kind_expr(it.into())
|
||||
},
|
||||
|
|
@ -1559,6 +1560,30 @@ fn classify_name_ref(
|
|||
Some((NameRefContext { nameref, kind: NameRefKind::Path(path_ctx) }, qualifier_ctx))
|
||||
}
|
||||
|
||||
/// When writing in the middle of some code the following situation commonly occurs (`|` denotes the cursor):
|
||||
/// ```ignore
|
||||
/// value.method|
|
||||
/// (1, 2, 3)
|
||||
/// ```
|
||||
/// Here, we want to complete the method parentheses & arguments (if the corresponding settings are on),
|
||||
/// but the thing is parsed as a method call with parentheses. Therefore we use heuristics: if the parentheses
|
||||
/// are on the next line, consider them non-existent.
|
||||
fn has_parens(node: &dyn HasArgList) -> bool {
|
||||
let Some(arg_list) = node.arg_list() else { return false };
|
||||
if arg_list.l_paren_token().is_none() {
|
||||
return false;
|
||||
}
|
||||
let prev_siblings = iter::successors(arg_list.syntax().prev_sibling_or_token(), |it| {
|
||||
it.prev_sibling_or_token()
|
||||
});
|
||||
prev_siblings
|
||||
.take_while(|syntax| syntax.kind().is_trivia())
|
||||
.filter_map(|syntax| {
|
||||
syntax.into_token().filter(|token| token.kind() == SyntaxKind::WHITESPACE)
|
||||
})
|
||||
.all(|whitespace| !whitespace.text().contains('\n'))
|
||||
}
|
||||
|
||||
fn pattern_context_for(
|
||||
sema: &Semantics<'_, RootDatabase>,
|
||||
original_file: &SyntaxNode,
|
||||
|
|
|
|||
|
|
@ -2126,3 +2126,51 @@ fn main() {
|
|||
"#]],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn call_parens_with_newline() {
|
||||
check_edit(
|
||||
"foo",
|
||||
r#"
|
||||
fn foo(v: i32) {}
|
||||
|
||||
fn bar() {
|
||||
foo$0
|
||||
()
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
fn foo(v: i32) {}
|
||||
|
||||
fn bar() {
|
||||
foo(${1:v});$0
|
||||
()
|
||||
}
|
||||
"#,
|
||||
);
|
||||
check_edit(
|
||||
"foo",
|
||||
r#"
|
||||
struct Foo;
|
||||
impl Foo {
|
||||
fn foo(&self, v: i32) {}
|
||||
}
|
||||
|
||||
fn bar() {
|
||||
Foo.foo$0
|
||||
()
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
struct Foo;
|
||||
impl Foo {
|
||||
fn foo(&self, v: i32) {}
|
||||
}
|
||||
|
||||
fn bar() {
|
||||
Foo.foo(${1:v});$0
|
||||
()
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue