Skip to content

Commit 0308c41

Browse files
committed
[ty] Improve autocomplete suppressions of keywords in variable bindings
Autocomplete suggestions were not suppressed correctly during some variable bindings if the parameter name was currently matching a keyword. E.g. `def f(foo<CURSOR>` was handled correctly but not `def f(in<CURSOR>`.
1 parent 04781fe commit 0308c41

File tree

1 file changed

+57
-0
lines changed

1 file changed

+57
-0
lines changed

crates/ty_ide/src/completion.rs

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1365,6 +1365,24 @@ fn is_in_variable_binding(parsed: &ParsedModuleRef, offset: TextSize, typed: Opt
13651365
type_param.name.range.contains_range(range)
13661366
}
13671367
ast::AnyNodeRef::StmtFor(stmt_for) => stmt_for.target.range().contains_range(range),
1368+
// The AST does not produce `ast::AnyNodeRef::Parameter` nodes for keywords
1369+
// or otherwise invalid syntax. Rather they are captured in a
1370+
// `ast::AnyNodeRef::Parameters` node as "empty space". To ensure
1371+
// we still suppress suggestions even when the syntax is technically
1372+
// invalid we extract the token under the cursor and check if it makes
1373+
// up that "empty space" inside the Parameters Node. If it does, we know
1374+
// that we are still binding variables, just that the current state is
1375+
// syntatically invalid. Hence we suppress autocomplete suggestons
1376+
// also in those cases.
1377+
ast::AnyNodeRef::Parameters(params) => {
1378+
if !params.range.contains_range(range) {
1379+
return false;
1380+
}
1381+
params
1382+
.iter()
1383+
.map(|param| param.range())
1384+
.all(|r| !r.contains_range(range))
1385+
}
13681386
_ => false,
13691387
})
13701388
}
@@ -5274,6 +5292,45 @@ def foo(p<CURSOR>
52745292
);
52755293
}
52765294

5295+
#[test]
5296+
fn no_completions_in_function_param_keyword() {
5297+
let builder = completion_test_builder(
5298+
"\
5299+
def foo(in<CURSOR>
5300+
",
5301+
);
5302+
assert_snapshot!(
5303+
builder.build().snapshot(),
5304+
@"<No completions found>",
5305+
);
5306+
}
5307+
5308+
#[test]
5309+
fn no_completions_in_function_param_multi_keyword() {
5310+
let builder = completion_test_builder(
5311+
"\
5312+
def foo(param, in<CURSOR>
5313+
",
5314+
);
5315+
assert_snapshot!(
5316+
builder.build().snapshot(),
5317+
@"<No completions found>",
5318+
);
5319+
}
5320+
5321+
#[test]
5322+
fn no_completions_in_function_param_multi_keyword_middle() {
5323+
let builder = completion_test_builder(
5324+
"\
5325+
def foo(param, in<CURSOR>, param_two
5326+
",
5327+
);
5328+
assert_snapshot!(
5329+
builder.build().snapshot(),
5330+
@"<No completions found>",
5331+
);
5332+
}
5333+
52775334
#[test]
52785335
fn no_completions_in_function_type_param() {
52795336
let builder = completion_test_builder(

0 commit comments

Comments
 (0)