forked from extern/nushell
enable flag value type checking (#11311)
# Description Fixes: #11310 # User-Facing Changes After the change, the following code will go to error: ```nushell > def a [--x: int = 3] { "aa" } > let y = "aa" > a --x=$y Error: nu::parser::type_mismatch × Type mismatch. ╭─[entry #32:2:1] 2 │ let y = "aa" 3 │ a --x=$y · ─┬ · ╰── expected int, found string ╰──── ```
This commit is contained in:
parent
1cecb37628
commit
697f3c03f1
@ -344,6 +344,37 @@ pub fn parse_external_call(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn ensure_flag_arg_type(
|
||||||
|
working_set: &mut StateWorkingSet,
|
||||||
|
arg_name: String,
|
||||||
|
arg: Expression,
|
||||||
|
arg_shape: &SyntaxShape,
|
||||||
|
long_name_span: Span,
|
||||||
|
) -> (Spanned<String>, Expression) {
|
||||||
|
if !type_compatible(&arg.ty, &arg_shape.to_type()) {
|
||||||
|
working_set.error(ParseError::TypeMismatch(
|
||||||
|
arg_shape.to_type(),
|
||||||
|
arg.ty,
|
||||||
|
arg.span,
|
||||||
|
));
|
||||||
|
(
|
||||||
|
Spanned {
|
||||||
|
item: arg_name,
|
||||||
|
span: long_name_span,
|
||||||
|
},
|
||||||
|
Expression::garbage(arg.span),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
(
|
||||||
|
Spanned {
|
||||||
|
item: arg_name,
|
||||||
|
span: long_name_span,
|
||||||
|
},
|
||||||
|
arg,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn parse_long_flag(
|
fn parse_long_flag(
|
||||||
working_set: &mut StateWorkingSet,
|
working_set: &mut StateWorkingSet,
|
||||||
spans: &[Span],
|
spans: &[Span],
|
||||||
@ -368,25 +399,21 @@ fn parse_long_flag(
|
|||||||
span.start += long_name_len + 3; //offset by long flag and '='
|
span.start += long_name_len + 3; //offset by long flag and '='
|
||||||
|
|
||||||
let arg = parse_value(working_set, span, arg_shape);
|
let arg = parse_value(working_set, span, arg_shape);
|
||||||
|
let (arg_name, val_expression) = ensure_flag_arg_type(
|
||||||
(
|
working_set,
|
||||||
Some(Spanned {
|
long_name,
|
||||||
item: long_name,
|
arg,
|
||||||
span: Span::new(arg_span.start, arg_span.start + long_name_len + 2),
|
arg_shape,
|
||||||
}),
|
Span::new(arg_span.start, arg_span.start + long_name_len + 2),
|
||||||
Some(arg),
|
);
|
||||||
)
|
(Some(arg_name), Some(val_expression))
|
||||||
} else if let Some(arg) = spans.get(*spans_idx + 1) {
|
} else if let Some(arg) = spans.get(*spans_idx + 1) {
|
||||||
let arg = parse_value(working_set, *arg, arg_shape);
|
let arg = parse_value(working_set, *arg, arg_shape);
|
||||||
|
|
||||||
*spans_idx += 1;
|
*spans_idx += 1;
|
||||||
(
|
let (arg_name, val_expression) =
|
||||||
Some(Spanned {
|
ensure_flag_arg_type(working_set, long_name, arg, arg_shape, arg_span);
|
||||||
item: long_name,
|
(Some(arg_name), Some(val_expression))
|
||||||
span: arg_span,
|
|
||||||
}),
|
|
||||||
Some(arg),
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
working_set.error(ParseError::MissingFlagParam(
|
working_set.error(ParseError::MissingFlagParam(
|
||||||
arg_shape.to_string(),
|
arg_shape.to_string(),
|
||||||
@ -411,13 +438,14 @@ fn parse_long_flag(
|
|||||||
|
|
||||||
let arg = parse_value(working_set, span, &SyntaxShape::Boolean);
|
let arg = parse_value(working_set, span, &SyntaxShape::Boolean);
|
||||||
|
|
||||||
(
|
let (arg_name, val_expression) = ensure_flag_arg_type(
|
||||||
Some(Spanned {
|
working_set,
|
||||||
item: long_name,
|
long_name,
|
||||||
span: Span::new(arg_span.start, arg_span.start + long_name_len + 2),
|
arg,
|
||||||
}),
|
&SyntaxShape::Boolean,
|
||||||
Some(arg),
|
Span::new(arg_span.start, arg_span.start + long_name_len + 2),
|
||||||
)
|
);
|
||||||
|
(Some(arg_name), Some(val_expression))
|
||||||
} else {
|
} else {
|
||||||
(
|
(
|
||||||
Some(Spanned {
|
Some(Spanned {
|
||||||
|
@ -73,6 +73,14 @@ fn custom_switch1() -> TestResult {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn custom_flag_with_type_checking() -> TestResult {
|
||||||
|
fail_test(
|
||||||
|
r#"def florb [--dry-run: int] { $dry_run }; let y = "3"; florb --dry-run=$y"#,
|
||||||
|
"type_mismatch",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn custom_switch2() -> TestResult {
|
fn custom_switch2() -> TestResult {
|
||||||
run_test(
|
run_test(
|
||||||
|
Loading…
Reference in New Issue
Block a user