Merge pull request #128 from nushell/fix_missing_params

Fix missing param error and custom flag values
This commit is contained in:
JT 2021-10-12 10:22:34 +13:00 committed by GitHub
commit 9f02307bd7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 91 additions and 10 deletions

View File

@ -84,6 +84,9 @@ impl Highlighter for NuHighlighter {
Style::new().fg(nu_ansi_term::Color::Yellow).bold(), Style::new().fg(nu_ansi_term::Color::Yellow).bold(),
next_token, next_token,
)), )),
FlatShape::Flag => {
output.push((Style::new().fg(nu_ansi_term::Color::Yellow), next_token))
}
FlatShape::Filepath => output.push(( FlatShape::Filepath => output.push((
Style::new().fg(nu_ansi_term::Color::Yellow).bold(), Style::new().fg(nu_ansi_term::Color::Yellow).bold(),
next_token, next_token,

View File

@ -1,6 +1,6 @@
use nu_protocol::ast::{Block, Call, Expr, Expression, Operator, Statement}; use nu_protocol::ast::{Block, Call, Expr, Expression, Operator, Statement};
use nu_protocol::engine::EvaluationContext; use nu_protocol::engine::EvaluationContext;
use nu_protocol::{Range, ShellError, Span, Type, Unit, Value}; use nu_protocol::{Range, ShellError, Span, Spanned, Type, Unit, Value};
pub fn eval_operator(op: &Expression) -> Result<Operator, ShellError> { pub fn eval_operator(op: &Expression) -> Result<Operator, ShellError> {
match op { match op {
@ -60,6 +60,29 @@ fn eval_call(context: &EvaluationContext, call: &Call, input: Value) -> Result<V
}, },
) )
} }
for named in decl.signature().named {
for call_named in &call.named {
if call_named.0.item == named.long {
let var_id = named
.var_id
.expect("internal error: all custom parameters must have var_ids");
if let Some(arg) = &call_named.1 {
let result = eval_expression(&state, arg)?;
state.add_var(var_id, result);
} else {
state.add_var(
var_id,
Value::Bool {
val: true,
span: call.head,
},
)
}
}
}
}
let engine_state = state.engine_state.borrow(); let engine_state = state.engine_state.borrow();
let block = engine_state.get_block(block_id); let block = engine_state.get_block(block_id);
eval_block(&state, block, input) eval_block(&state, block, input)
@ -98,7 +121,13 @@ fn eval_external(
} }
if last_expression { if last_expression {
call.named.push(("last_expression".into(), None)) call.named.push((
Spanned {
item: "last_expression".into(),
span: Span::unknown(),
},
None,
))
} }
command.run(context, &call, input) command.run(context, &call, input)

View File

@ -18,6 +18,7 @@ pub enum FlatShape {
Filepath, Filepath,
GlobPattern, GlobPattern,
Variable, Variable,
Flag,
Custom(String), Custom(String),
} }
@ -61,6 +62,12 @@ pub fn flatten_expression(
for positional in &call.positional { for positional in &call.positional {
output.extend(flatten_expression(working_set, positional)); output.extend(flatten_expression(working_set, positional));
} }
for named in &call.named {
output.push((named.0.span, FlatShape::Flag));
if let Some(expr) = &named.1 {
output.extend(flatten_expression(working_set, expr));
}
}
output output
} }
Expr::ExternalCall(_, name_span, args) => { Expr::ExternalCall(_, name_span, args) => {

View File

@ -57,7 +57,7 @@ fn check_call(command: Span, sig: &Signature, call: &Call) -> Option<ParseError>
Some(ParseError::MissingPositional(missing.name.clone(), command)) Some(ParseError::MissingPositional(missing.name.clone(), command))
} else { } else {
for req_flag in sig.named.iter().filter(|x| x.required) { for req_flag in sig.named.iter().filter(|x| x.required) {
if call.named.iter().all(|(n, _)| n != &req_flag.long) { if call.named.iter().all(|(n, _)| n.item != req_flag.long) {
return Some(ParseError::MissingRequiredFlag( return Some(ParseError::MissingRequiredFlag(
req_flag.long.clone(), req_flag.long.clone(),
command, command,
@ -478,7 +478,13 @@ pub fn parse_internal_call(
if let Some(long_name) = long_name { if let Some(long_name) = long_name {
// We found a long flag, like --bar // We found a long flag, like --bar
error = error.or(err); error = error.or(err);
call.named.push((long_name, arg)); call.named.push((
Spanned {
item: long_name,
span: arg_span,
},
arg,
));
spans_idx += 1; spans_idx += 1;
continue; continue;
} }
@ -500,13 +506,25 @@ pub fn parse_internal_call(
let (arg, err) = parse_value(working_set, *arg, &arg_shape); let (arg, err) = parse_value(working_set, *arg, &arg_shape);
error = error.or(err); error = error.or(err);
call.named.push((flag.long.clone(), Some(arg))); call.named.push((
Spanned {
item: flag.long.clone(),
span: spans[spans_idx],
},
Some(arg),
));
spans_idx += 1; spans_idx += 1;
} else { } else {
error = error.or(Some(ParseError::MissingFlagParam(arg_span))) error = error.or(Some(ParseError::MissingFlagParam(arg_span)))
} }
} else { } else {
call.named.push((flag.long.clone(), None)); call.named.push((
Spanned {
item: flag.long.clone(),
span: spans[spans_idx],
},
None,
));
} }
} }
spans_idx += 1; spans_idx += 1;
@ -1850,7 +1868,18 @@ pub fn parse_signature(
if bytes.starts_with(b"[") { if bytes.starts_with(b"[") {
start += 1; start += 1;
} else {
error = error.or_else(|| {
Some(ParseError::Expected(
"[".into(),
Span {
start,
end: start + 1,
},
))
});
} }
if bytes.ends_with(b"]") { if bytes.ends_with(b"]") {
end -= 1; end -= 1;
} else { } else {

View File

@ -1,5 +1,5 @@
use super::Expression; use super::Expression;
use crate::{DeclId, Span}; use crate::{DeclId, Span, Spanned};
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Call { pub struct Call {
@ -7,7 +7,7 @@ pub struct Call {
pub decl_id: DeclId, pub decl_id: DeclId,
pub head: Span, pub head: Span,
pub positional: Vec<Expression>, pub positional: Vec<Expression>,
pub named: Vec<(String, Option<Expression>)>, pub named: Vec<(Spanned<String>, Option<Expression>)>,
} }
impl Default for Call { impl Default for Call {
@ -28,7 +28,7 @@ impl Call {
pub fn has_flag(&self, flag_name: &str) -> bool { pub fn has_flag(&self, flag_name: &str) -> bool {
for name in &self.named { for name in &self.named {
if flag_name == name.0 { if flag_name == name.0.item {
return true; return true;
} }
} }
@ -38,7 +38,7 @@ impl Call {
pub fn get_flag_expr(&self, flag_name: &str) -> Option<Expression> { pub fn get_flag_expr(&self, flag_name: &str) -> Option<Expression> {
for name in &self.named { for name in &self.named {
if flag_name == name.0 { if flag_name == name.0.item {
return name.1.clone(); return name.1.clone();
} }
} }

View File

@ -709,3 +709,16 @@ fn missing_column_error() -> TestResult {
"cannot find column", "cannot find column",
) )
} }
#[test]
fn missing_parameters() -> TestResult {
fail_test(r#"def foo {}"#, "expected [")
}
#[test]
fn flag_param_value() -> TestResult {
run_test(
r#"def foo [--bob: int] { $bob + 100 }; foo --bob 55"#,
"155",
)
}