mirror of
https://github.com/nushell/nushell.git
synced 2025-08-09 09:35:44 +02:00
fix rest parameter spans (#16176)
Closes #16071 # Description Rest parameter variables are now fully spanned, instead of just the first value: ```diff def foo [...rest] { metadata $rest | view span $in.span.start $in.span.end } foo 1 2 -1 +1 2 ```
This commit is contained in:
@ -1159,6 +1159,7 @@ fn gather_arguments(
|
|||||||
|
|
||||||
// Arguments that didn't get consumed by required/optional
|
// Arguments that didn't get consumed by required/optional
|
||||||
let mut rest = vec![];
|
let mut rest = vec![];
|
||||||
|
let mut rest_span: Option<Span> = None;
|
||||||
|
|
||||||
// If we encounter a spread, all further positionals should go to rest
|
// If we encounter a spread, all further positionals should go to rest
|
||||||
let mut always_spread = false;
|
let mut always_spread = false;
|
||||||
@ -1178,12 +1179,19 @@ fn gather_arguments(
|
|||||||
}
|
}
|
||||||
callee_stack.add_var(var_id, val);
|
callee_stack.add_var(var_id, val);
|
||||||
} else {
|
} else {
|
||||||
|
rest_span = Some(rest_span.map_or(val.span(), |s| s.append(val.span())));
|
||||||
rest.push(val);
|
rest.push(val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Argument::Spread { vals, .. } => {
|
Argument::Spread {
|
||||||
|
vals,
|
||||||
|
span: spread_span,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
if let Value::List { vals, .. } = vals {
|
if let Value::List { vals, .. } = vals {
|
||||||
rest.extend(vals);
|
rest.extend(vals);
|
||||||
|
// Rest variable should span the spread syntax, not the list values
|
||||||
|
rest_span = Some(rest_span.map_or(spread_span, |s| s.append(spread_span)));
|
||||||
// All further positional args should go to spread
|
// All further positional args should go to spread
|
||||||
always_spread = true;
|
always_spread = true;
|
||||||
} else if let Value::Error { error, .. } = vals {
|
} else if let Value::Error { error, .. } = vals {
|
||||||
@ -1218,7 +1226,7 @@ fn gather_arguments(
|
|||||||
|
|
||||||
// Add the collected rest of the arguments if a spread argument exists
|
// Add the collected rest of the arguments if a spread argument exists
|
||||||
if let Some(rest_arg) = &block.signature.rest_positional {
|
if let Some(rest_arg) = &block.signature.rest_positional {
|
||||||
let rest_span = rest.first().map(|v| v.span()).unwrap_or(call_head);
|
let rest_span = rest_span.unwrap_or(call_head);
|
||||||
let var_id = expect_positional_var_id(rest_arg, rest_span)?;
|
let var_id = expect_positional_var_id(rest_arg, rest_span)?;
|
||||||
callee_stack.add_var(var_id, Value::list(rest, rest_span));
|
callee_stack.add_var(var_id, Value::list(rest, rest_span));
|
||||||
}
|
}
|
||||||
|
@ -439,6 +439,14 @@ fn better_operator_spans() -> TestResult {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn call_rest_arg_span() -> TestResult {
|
||||||
|
run_test(
|
||||||
|
r#"let l = [2, 3]; def foo [...rest] { metadata $rest | view span $in.span.start $in.span.end }; foo 1 ...$l"#,
|
||||||
|
"1 ...$l",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn range_right_exclusive() -> TestResult {
|
fn range_right_exclusive() -> TestResult {
|
||||||
run_test(r#"[1, 4, 5, 8, 9] | slice 1..<3 | math sum"#, "9")
|
run_test(r#"[1, 4, 5, 8, 9] | slice 1..<3 | math sum"#, "9")
|
||||||
|
Reference in New Issue
Block a user