Skip to content

Commit d006351

Browse files
committed
fix(completion): missing local variables
1 parent 607a9c7 commit d006351

File tree

4 files changed

+30
-2
lines changed

4 files changed

+30
-2
lines changed

crates/nu-cli/tests/completions/mod.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1980,6 +1980,20 @@ fn variables_completions() {
19801980
match_suggestions(&expected, &suggestions);
19811981
}
19821982

1983+
#[test]
1984+
fn local_variable_completion() {
1985+
let (_, _, engine, stack) = new_engine();
1986+
let mut completer = NuCompleter::new(Arc::new(engine), Arc::new(stack));
1987+
1988+
let completion_str =
1989+
"def test [foo?: string, --fooo: bool, ...foooo] { let fooooo = true; $foo";
1990+
let suggestions = completer.complete(completion_str, completion_str.len());
1991+
1992+
// https://github.com/nushell/nushell/issues/15291
1993+
let expected: Vec<_> = vec!["$foo", "$fooo", "$foooo", "$fooooo"];
1994+
match_suggestions(&expected, &suggestions);
1995+
}
1996+
19831997
#[test]
19841998
fn record_cell_path_completions() {
19851999
let (_, _, mut engine, mut stack) = new_engine();

crates/nu-lsp/src/completion.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,12 @@ impl LanguageServer {
2323
// fallback to default completer where
2424
// the text is truncated to `location` and
2525
// an extra placeholder token is inserted for correct parsing
26+
let is_variable = file_text
27+
.get(..location)
28+
.and_then(|s| s.rsplit(' ').next())
29+
.is_some_and(|last_word| last_word.starts_with('$'));
2630
let need_fallback = location == 0
31+
|| is_variable
2732
|| file_text
2833
.get(location - 1..location)
2934
.and_then(|s| s.chars().next())

crates/nu-parser/src/parse_keywords.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -595,7 +595,12 @@ fn parse_def_inner(
595595
let mut new_errors = working_set.parse_errors[starting_error_count..].to_vec();
596596
working_set.parse_errors.truncate(starting_error_count);
597597

598-
working_set.exit_scope();
598+
if new_errors
599+
.iter()
600+
.all(|e| !matches!(e, ParseError::Unclosed(token, _) if token == "}"))
601+
{
602+
working_set.exit_scope();
603+
}
599604

600605
let call_span = Span::concat(spans);
601606
let decl = working_set.get_decl(decl_id);

crates/nu-parser/src/parser.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5090,6 +5090,7 @@ pub fn parse_closure_expression(
50905090

50915091
let mut start = span.start;
50925092
let mut end = span.end;
5093+
let mut is_unclosed = false;
50935094

50945095
if bytes.starts_with(b"{") {
50955096
start += 1;
@@ -5101,6 +5102,7 @@ pub fn parse_closure_expression(
51015102
end -= 1;
51025103
} else {
51035104
working_set.error(ParseError::Unclosed("}".into(), Span::new(end, end)));
5105+
is_unclosed = true;
51045106
}
51055107

51065108
let inner_span = Span::new(start, end);
@@ -5197,7 +5199,9 @@ pub fn parse_closure_expression(
51975199

51985200
output.span = Some(span);
51995201

5200-
working_set.exit_scope();
5202+
if !is_unclosed {
5203+
working_set.exit_scope();
5204+
}
52015205

52025206
let block_id = working_set.add_block(Arc::new(output));
52035207

0 commit comments

Comments
 (0)