Add an alias denylist for expansions (#4871)

This commit is contained in:
JT
2022-03-19 08:03:57 +13:00
committed by GitHub
parent 5a1af4d661
commit 983d115bc0
18 changed files with 516 additions and 159 deletions

View File

@ -208,6 +208,7 @@ pub fn check_name<'a>(
pub fn parse_external_call(
working_set: &mut StateWorkingSet,
spans: &[Span],
expand_aliases_denylist: &[usize],
) -> (Expression, Option<ParseError>) {
let mut args = vec![];
@ -235,10 +236,17 @@ pub fn parse_external_call(
new_spans.extend(&spans[1..])
}
working_set.enter_scope();
working_set.hide_alias(&head_contents);
let (mut result, err) = parse_external_call(working_set, &new_spans);
working_set.exit_scope();
let expand_aliases_denylist = if let Some(alias_id) = working_set.find_alias(&head_contents)
{
let mut expand_aliases_denylist = expand_aliases_denylist.to_vec();
expand_aliases_denylist.push(alias_id);
expand_aliases_denylist
} else {
expand_aliases_denylist.to_vec()
};
let (mut result, err) =
parse_external_call(working_set, &new_spans, &expand_aliases_denylist);
result.replace_span(working_set, expansion_span, orig_span);
return (result, err);
@ -247,7 +255,7 @@ pub fn parse_external_call(
let mut error = None;
let head = if head_contents.starts_with(b"$") || head_contents.starts_with(b"(") {
let (arg, err) = parse_expression(working_set, &[head_span], true);
let (arg, err) = parse_expression(working_set, &[head_span], expand_aliases_denylist);
error = error.or(err);
Box::new(arg)
} else {
@ -263,11 +271,12 @@ pub fn parse_external_call(
let contents = working_set.get_span_contents(*span);
if contents.starts_with(b"$") || contents.starts_with(b"(") {
let (arg, err) = parse_dollar_expr(working_set, *span);
let (arg, err) = parse_dollar_expr(working_set, *span, expand_aliases_denylist);
error = error.or(err);
args.push(arg);
} else if contents.starts_with(b"(") {
let (arg, err) = parse_full_cell_path(working_set, None, *span);
let (arg, err) =
parse_full_cell_path(working_set, None, *span, expand_aliases_denylist);
error = error.or(err);
args.push(arg);
} else {
@ -295,6 +304,7 @@ fn parse_long_flag(
spans: &[Span],
spans_idx: &mut usize,
sig: &Signature,
expand_aliases_denylist: &[usize],
) -> (
Option<Spanned<String>>,
Option<Expression>,
@ -317,7 +327,8 @@ fn parse_long_flag(
let mut span = arg_span;
span.start += long_name_len + 3; //offset by long flag and '='
let (arg, err) = parse_value(working_set, span, arg_shape);
let (arg, err) =
parse_value(working_set, span, arg_shape, expand_aliases_denylist);
(
Some(Spanned {
@ -331,7 +342,8 @@ fn parse_long_flag(
err,
)
} else if let Some(arg) = spans.get(*spans_idx + 1) {
let (arg, err) = parse_value(working_set, *arg, arg_shape);
let (arg, err) =
parse_value(working_set, *arg, arg_shape, expand_aliases_denylist);
*spans_idx += 1;
(
@ -554,6 +566,7 @@ pub fn parse_multispan_value(
spans: &[Span],
spans_idx: &mut usize,
shape: &SyntaxShape,
expand_aliases_denylist: &[usize],
) -> (Expression, Option<ParseError>) {
let mut error = None;
@ -568,7 +581,8 @@ pub fn parse_multispan_value(
}
SyntaxShape::RowCondition => {
trace!("parsing: row condition");
let (arg, err) = parse_row_condition(working_set, &spans[*spans_idx..]);
let (arg, err) =
parse_row_condition(working_set, &spans[*spans_idx..], expand_aliases_denylist);
error = error.or(err);
*spans_idx = spans.len() - 1;
@ -577,7 +591,12 @@ pub fn parse_multispan_value(
SyntaxShape::MathExpression => {
trace!("parsing: math expression");
let (arg, err) = parse_math_expression(working_set, &spans[*spans_idx..], None);
let (arg, err) = parse_math_expression(
working_set,
&spans[*spans_idx..],
None,
expand_aliases_denylist,
);
error = error.or(err);
*spans_idx = spans.len() - 1;
@ -586,7 +605,8 @@ pub fn parse_multispan_value(
SyntaxShape::Expression => {
trace!("parsing: expression");
let (arg, err) = parse_expression(working_set, &spans[*spans_idx..], true);
let (arg, err) =
parse_expression(working_set, &spans[*spans_idx..], expand_aliases_denylist);
error = error.or(err);
*spans_idx = spans.len() - 1;
@ -595,7 +615,8 @@ pub fn parse_multispan_value(
SyntaxShape::ImportPattern => {
trace!("parsing: import pattern");
let (arg, err) = parse_import_pattern(working_set, &spans[*spans_idx..]);
let (arg, err) =
parse_import_pattern(working_set, &spans[*spans_idx..], expand_aliases_denylist);
error = error.or(err);
*spans_idx = spans.len() - 1;
@ -649,7 +670,8 @@ pub fn parse_multispan_value(
);
}
let keyword_span = spans[*spans_idx - 1];
let (expr, err) = parse_multispan_value(working_set, spans, spans_idx, arg);
let (expr, err) =
parse_multispan_value(working_set, spans, spans_idx, arg, expand_aliases_denylist);
error = error.or(err);
let ty = expr.ty.clone();
@ -667,7 +689,7 @@ pub fn parse_multispan_value(
// All other cases are single-span values
let arg_span = spans[*spans_idx];
let (arg, err) = parse_value(working_set, arg_span, shape);
let (arg, err) = parse_value(working_set, arg_span, shape, expand_aliases_denylist);
error = error.or(err);
(arg, error)
@ -680,6 +702,7 @@ pub fn parse_internal_call(
command_span: Span,
spans: &[Span],
decl_id: usize,
expand_aliases_denylist: &[usize],
) -> (Box<Call>, Option<ParseError>) {
trace!("parsing: internal call (decl id: {})", decl_id);
@ -706,7 +729,13 @@ pub fn parse_internal_call(
let arg_span = spans[spans_idx];
// Check if we're on a long flag, if so, parse
let (long_name, arg, err) = parse_long_flag(working_set, spans, &mut spans_idx, &signature);
let (long_name, arg, err) = parse_long_flag(
working_set,
spans,
&mut spans_idx,
&signature,
expand_aliases_denylist,
);
if let Some(long_name) = long_name {
// We found a long flag, like --bar
error = error.or(err);
@ -729,7 +758,8 @@ pub fn parse_internal_call(
for flag in short_flags {
if let Some(arg_shape) = flag.arg {
if let Some(arg) = spans.get(spans_idx + 1) {
let (arg, err) = parse_value(working_set, *arg, &arg_shape);
let (arg, err) =
parse_value(working_set, *arg, &arg_shape, expand_aliases_denylist);
error = error.or(err);
call.named.push((
@ -793,6 +823,7 @@ pub fn parse_internal_call(
&spans[..end],
&mut spans_idx,
&positional.shape,
expand_aliases_denylist,
);
error = error.or(err);
@ -839,8 +870,8 @@ pub fn parse_internal_call(
pub fn parse_call(
working_set: &mut StateWorkingSet,
spans: &[Span],
expand_aliases: bool,
head: Span,
expand_aliases_denylist: &[usize],
) -> (Expression, Option<ParseError>) {
trace!("parsing: call");
@ -883,9 +914,9 @@ pub fn parse_call(
name.extend(name_part);
}
if expand_aliases {
// If the word is an alias, expand it and re-parse the expression
if let Some(alias_id) = working_set.find_alias(&name) {
// If the word is an alias, expand it and re-parse the expression
if let Some(alias_id) = working_set.find_alias(&name) {
if !expand_aliases_denylist.contains(&alias_id) {
trace!("expanding alias");
let expansion = working_set.get_alias(alias_id);
@ -901,17 +932,15 @@ pub fn parse_call(
new_spans.extend(&spans[(pos + 1)..]);
}
let alias_id = working_set.hide_alias(&name);
let mut expand_aliases_denylist = expand_aliases_denylist.to_vec();
expand_aliases_denylist.push(alias_id);
let lite_command = LiteCommand {
comments: vec![],
parts: new_spans.clone(),
};
let (mut result, err) = parse_builtin_commands(working_set, &lite_command);
if let Some(frame) = working_set.delta.scope.last_mut() {
if let Some(alias_id) = alias_id {
frame.aliases.insert(name.clone(), alias_id);
}
}
let (mut result, err) =
parse_builtin_commands(working_set, &lite_command, &expand_aliases_denylist);
let mut result = result.expressions.remove(0);
@ -976,6 +1005,7 @@ pub fn parse_call(
span(&spans[cmd_start..pos]),
&spans[pos..],
decl_id,
expand_aliases_denylist,
);
(
Expression {
@ -992,7 +1022,8 @@ pub fn parse_call(
trace!("parsing: range {:?} ", bytes);
if let (Some(b'.'), Some(b'.')) = (bytes.get(0), bytes.get(1)) {
trace!("-- found leading range indicator");
let (range_expr, range_err) = parse_range(working_set, spans[0]);
let (range_expr, range_err) =
parse_range(working_set, spans[0], expand_aliases_denylist);
if range_err.is_none() {
trace!("-- successfully parsed range");
return (range_expr, range_err);
@ -1001,7 +1032,7 @@ pub fn parse_call(
trace!("parsing: external call");
// Otherwise, try external command
parse_external_call(working_set, spans)
parse_external_call(working_set, spans, expand_aliases_denylist)
}
}
@ -1201,6 +1232,7 @@ pub fn parse_number(token: &[u8], span: Span) -> (Expression, Option<ParseError>
pub fn parse_range(
working_set: &mut StateWorkingSet,
span: Span,
expand_aliases_denylist: &[usize],
) -> (Expression, Option<ParseError>) {
trace!("parsing: range");
@ -1279,7 +1311,12 @@ pub fn parse_range(
None
} else {
let from_span = Span::new(span.start, span.start + dotdot_pos[0]);
match parse_value(working_set, from_span, &SyntaxShape::Number) {
match parse_value(
working_set,
from_span,
&SyntaxShape::Number,
expand_aliases_denylist,
) {
(expression, None) => Some(Box::new(expression)),
_ => {
return (
@ -1294,7 +1331,12 @@ pub fn parse_range(
None
} else {
let to_span = Span::new(range_op_span.end, span.end);
match parse_value(working_set, to_span, &SyntaxShape::Number) {
match parse_value(
working_set,
to_span,
&SyntaxShape::Number,
expand_aliases_denylist,
) {
(expression, None) => Some(Box::new(expression)),
_ => {
return (
@ -1321,7 +1363,12 @@ pub fn parse_range(
let next_op_span = Span::new(span.start + pos, span.start + pos + "..".len());
let next_span = Span::new(next_op_span.end, range_op_span.start);
match parse_value(working_set, next_span, &SyntaxShape::Number) {
match parse_value(
working_set,
next_span,
&SyntaxShape::Number,
expand_aliases_denylist,
) {
(expression, None) => (Some(Box::new(expression)), next_op_span),
_ => {
return (
@ -1354,22 +1401,24 @@ pub fn parse_range(
pub(crate) fn parse_dollar_expr(
working_set: &mut StateWorkingSet,
span: Span,
expand_aliases_denylist: &[usize],
) -> (Expression, Option<ParseError>) {
trace!("parsing: dollar expression");
let contents = working_set.get_span_contents(span);
if contents.starts_with(b"$\"") || contents.starts_with(b"$'") {
parse_string_interpolation(working_set, span)
} else if let (expr, None) = parse_range(working_set, span) {
parse_string_interpolation(working_set, span, expand_aliases_denylist)
} else if let (expr, None) = parse_range(working_set, span, expand_aliases_denylist) {
(expr, None)
} else {
parse_full_cell_path(working_set, None, span)
parse_full_cell_path(working_set, None, span, expand_aliases_denylist)
}
}
pub fn parse_string_interpolation(
working_set: &mut StateWorkingSet,
span: Span,
expand_aliases_denylist: &[usize],
) -> (Expression, Option<ParseError>) {
#[derive(PartialEq, Eq, Debug)]
enum InterpolationMode {
@ -1469,7 +1518,8 @@ pub fn parse_string_interpolation(
end: b + 1,
};
let (expr, err) = parse_full_cell_path(working_set, None, span);
let (expr, err) =
parse_full_cell_path(working_set, None, span, expand_aliases_denylist);
error = error.or(err);
output.push(expr);
}
@ -1515,7 +1565,8 @@ pub fn parse_string_interpolation(
end,
};
let (expr, err) = parse_full_cell_path(working_set, None, span);
let (expr, err) =
parse_full_cell_path(working_set, None, span, expand_aliases_denylist);
error = error.or(err);
output.push(expr);
}
@ -1692,6 +1743,7 @@ pub fn parse_full_cell_path(
working_set: &mut StateWorkingSet,
implicit_head: Option<VarId>,
span: Span,
expand_aliases_denylist: &[usize],
) -> (Expression, Option<ParseError>) {
let full_cell_span = span;
let source = working_set.get_span_contents(span);
@ -1730,7 +1782,7 @@ pub fn parse_full_cell_path(
let (output, err) = lite_parse(&output);
error = error.or(err);
let (output, err) = parse_block(working_set, &output, true);
let (output, err) = parse_block(working_set, &output, true, expand_aliases_denylist);
error = error.or(err);
let block_id = working_set.add_block(output);
@ -1748,7 +1800,8 @@ pub fn parse_full_cell_path(
} else if bytes.starts_with(b"[") {
trace!("parsing: table head of full cell path");
let (output, err) = parse_table_expression(working_set, head.span);
let (output, err) =
parse_table_expression(working_set, head.span, expand_aliases_denylist);
error = error.or(err);
tokens.next();
@ -1756,7 +1809,7 @@ pub fn parse_full_cell_path(
(output, true)
} else if bytes.starts_with(b"{") {
trace!("parsing: record head of full cell path");
let (output, err) = parse_record(working_set, head.span);
let (output, err) = parse_record(working_set, head.span, expand_aliases_denylist);
error = error.or(err);
tokens.next();
@ -2519,6 +2572,7 @@ pub fn parse_type(_working_set: &StateWorkingSet, bytes: &[u8]) -> Type {
pub fn parse_import_pattern(
working_set: &mut StateWorkingSet,
spans: &[Span],
expand_aliases_denylist: &[usize],
) -> (Expression, Option<ParseError>) {
let mut error = None;
@ -2553,8 +2607,12 @@ pub fn parse_import_pattern(
None,
)
} else if tail.starts_with(b"[") {
let (result, err) =
parse_list_expression(working_set, *tail_span, &SyntaxShape::String);
let (result, err) = parse_list_expression(
working_set,
*tail_span,
&SyntaxShape::String,
expand_aliases_denylist,
);
error = error.or(err);
let mut output = vec![];
@ -2725,6 +2783,7 @@ pub fn expand_to_cell_path(
working_set: &mut StateWorkingSet,
expression: &mut Expression,
var_id: VarId,
expand_aliases_denylist: &[usize],
) {
if let Expression {
expr: Expr::String(_),
@ -2733,7 +2792,8 @@ pub fn expand_to_cell_path(
} = expression
{
// Re-parse the string as if it were a cell-path
let (new_expression, _err) = parse_full_cell_path(working_set, Some(var_id), *span);
let (new_expression, _err) =
parse_full_cell_path(working_set, Some(var_id), *span, expand_aliases_denylist);
*expression = new_expression;
}
@ -2742,9 +2802,11 @@ pub fn expand_to_cell_path(
pub fn parse_row_condition(
working_set: &mut StateWorkingSet,
spans: &[Span],
expand_aliases_denylist: &[usize],
) -> (Expression, Option<ParseError>) {
let var_id = working_set.add_variable(b"$it".to_vec(), span(spans), Type::Unknown);
let (expression, err) = parse_math_expression(working_set, spans, Some(var_id));
let (expression, err) =
parse_math_expression(working_set, spans, Some(var_id), expand_aliases_denylist);
let span = span(spans);
let block_id = match expression.expr {
@ -2783,6 +2845,7 @@ pub fn parse_row_condition(
pub fn parse_signature(
working_set: &mut StateWorkingSet,
span: Span,
expand_aliases_denylist: &[usize],
) -> (Expression, Option<ParseError>) {
let bytes = working_set.get_span_contents(span);
@ -2810,7 +2873,8 @@ pub fn parse_signature(
error = error.or_else(|| Some(ParseError::Unclosed("]".into(), Span { start: end, end })));
}
let (sig, err) = parse_signature_helper(working_set, Span { start, end });
let (sig, err) =
parse_signature_helper(working_set, Span { start, end }, expand_aliases_denylist);
error = error.or(err);
(
@ -2827,6 +2891,7 @@ pub fn parse_signature(
pub fn parse_signature_helper(
working_set: &mut StateWorkingSet,
span: Span,
expand_aliases_denylist: &[usize],
) -> (Box<Signature>, Option<ParseError>) {
#[allow(clippy::enum_variant_names)]
enum ParseMode {
@ -3105,8 +3170,12 @@ pub fn parse_signature_helper(
}
ParseMode::DefaultValueMode => {
if let Some(last) = args.last_mut() {
let (expression, err) =
parse_value(working_set, span, &SyntaxShape::Any);
let (expression, err) = parse_value(
working_set,
span,
&SyntaxShape::Any,
expand_aliases_denylist,
);
error = error.or(err);
//TODO check if we're replacing a custom parameter already
@ -3279,6 +3348,7 @@ pub fn parse_list_expression(
working_set: &mut StateWorkingSet,
span: Span,
element_shape: &SyntaxShape,
expand_aliases_denylist: &[usize],
) -> (Expression, Option<ParseError>) {
let bytes = working_set.get_span_contents(span);
@ -3314,8 +3384,13 @@ pub fn parse_list_expression(
let mut spans_idx = 0;
while spans_idx < arg.parts.len() {
let (arg, err) =
parse_multispan_value(working_set, &arg.parts, &mut spans_idx, element_shape);
let (arg, err) = parse_multispan_value(
working_set,
&arg.parts,
&mut spans_idx,
element_shape,
expand_aliases_denylist,
);
error = error.or(err);
if let Some(ref ctype) = contained_type {
@ -3351,6 +3426,7 @@ pub fn parse_list_expression(
pub fn parse_table_expression(
working_set: &mut StateWorkingSet,
original_span: Span,
expand_aliases_denylist: &[usize],
) -> (Expression, Option<ParseError>) {
let bytes = working_set.get_span_contents(original_span);
let mut error = None;
@ -3389,7 +3465,12 @@ pub fn parse_table_expression(
),
1 => {
// List
parse_list_expression(working_set, original_span, &SyntaxShape::Any)
parse_list_expression(
working_set,
original_span,
&SyntaxShape::Any,
expand_aliases_denylist,
)
}
_ => {
let mut table_headers = vec![];
@ -3398,6 +3479,7 @@ pub fn parse_table_expression(
working_set,
output.block[0].commands[0].parts[0],
&SyntaxShape::List(Box::new(SyntaxShape::Any)),
expand_aliases_denylist,
);
error = error.or(err);
@ -3415,6 +3497,7 @@ pub fn parse_table_expression(
working_set,
*part,
&SyntaxShape::List(Box::new(SyntaxShape::Any)),
expand_aliases_denylist,
);
error = error.or(err);
if let Expression {
@ -3460,6 +3543,7 @@ pub fn parse_block_expression(
working_set: &mut StateWorkingSet,
shape: &SyntaxShape,
span: Span,
expand_aliases_denylist: &[usize],
) -> (Expression, Option<ParseError>) {
trace!("parsing: block expression");
@ -3526,7 +3610,8 @@ pub fn parse_block_expression(
start: start_point,
end: end_point,
};
let (signature, err) = parse_signature_helper(working_set, signature_span);
let (signature, err) =
parse_signature_helper(working_set, signature_span, expand_aliases_denylist);
error = error.or(err);
(Some((signature, signature_span)), amt_to_skip)
@ -3584,7 +3669,7 @@ pub fn parse_block_expression(
}
}
let (mut output, err) = parse_block(working_set, &output, false);
let (mut output, err) = parse_block(working_set, &output, false, expand_aliases_denylist);
error = error.or(err);
if let Some(signature) = signature {
@ -3626,6 +3711,7 @@ pub fn parse_value(
working_set: &mut StateWorkingSet,
span: Span,
shape: &SyntaxShape,
expand_aliases_denylist: &[usize],
) -> (Expression, Option<ParseError>) {
let bytes = working_set.get_span_contents(span);
@ -3699,24 +3785,26 @@ pub fn parse_value(
}
match bytes[0] {
b'$' => return parse_dollar_expr(working_set, span),
b'$' => return parse_dollar_expr(working_set, span, expand_aliases_denylist),
b'(' => {
if let (expr, None) = parse_range(working_set, span) {
if let (expr, None) = parse_range(working_set, span, expand_aliases_denylist) {
return (expr, None);
} else {
return parse_full_cell_path(working_set, None, span);
return parse_full_cell_path(working_set, None, span, expand_aliases_denylist);
}
}
b'{' => {
if !matches!(shape, SyntaxShape::Block(..)) {
if let (expr, None) = parse_full_cell_path(working_set, None, span) {
if let (expr, None) =
parse_full_cell_path(working_set, None, span, expand_aliases_denylist)
{
return (expr, None);
}
}
if matches!(shape, SyntaxShape::Block(_)) || matches!(shape, SyntaxShape::Any) {
return parse_block_expression(working_set, shape, span);
return parse_block_expression(working_set, shape, span, expand_aliases_denylist);
} else if matches!(shape, SyntaxShape::Record) {
return parse_record(working_set, span);
return parse_record(working_set, span, expand_aliases_denylist);
} else {
return (
Expression::garbage(span),
@ -3741,7 +3829,8 @@ pub fn parse_value(
match shape {
SyntaxShape::Custom(shape, custom_completion) => {
let (mut expression, err) = parse_value(working_set, span, shape);
let (mut expression, err) =
parse_value(working_set, span, shape, expand_aliases_denylist);
expression.custom_completion = Some(*custom_completion);
(expression, err)
}
@ -3750,14 +3839,14 @@ pub fn parse_value(
SyntaxShape::Duration => parse_duration(working_set, span),
SyntaxShape::DateTime => parse_datetime(working_set, span),
SyntaxShape::Filesize => parse_filesize(working_set, span),
SyntaxShape::Range => parse_range(working_set, span),
SyntaxShape::Range => parse_range(working_set, span, expand_aliases_denylist),
SyntaxShape::Filepath => parse_filepath(working_set, span),
SyntaxShape::GlobPattern => parse_glob_pattern(working_set, span),
SyntaxShape::String => parse_string(working_set, span),
SyntaxShape::Binary => parse_binary(working_set, span),
SyntaxShape::Signature => {
if bytes.starts_with(b"[") {
parse_signature(working_set, span)
parse_signature(working_set, span, expand_aliases_denylist)
} else {
(
Expression::garbage(span),
@ -3767,7 +3856,7 @@ pub fn parse_value(
}
SyntaxShape::List(elem) => {
if bytes.starts_with(b"[") {
parse_list_expression(working_set, span, elem)
parse_list_expression(working_set, span, elem, expand_aliases_denylist)
} else {
(
Expression::garbage(span),
@ -3777,7 +3866,7 @@ pub fn parse_value(
}
SyntaxShape::Table => {
if bytes.starts_with(b"[") {
parse_table_expression(working_set, span)
parse_table_expression(working_set, span, expand_aliases_denylist)
} else {
(
Expression::garbage(span),
@ -3829,7 +3918,7 @@ pub fn parse_value(
SyntaxShape::Any => {
if bytes.starts_with(b"[") {
//parse_value(working_set, span, &SyntaxShape::Table)
parse_full_cell_path(working_set, None, span)
parse_full_cell_path(working_set, None, span, expand_aliases_denylist)
} else {
let shapes = [
SyntaxShape::Binary,
@ -3844,7 +3933,9 @@ pub fn parse_value(
SyntaxShape::String,
];
for shape in shapes.iter() {
if let (s, None) = parse_value(working_set, span, shape) {
if let (s, None) =
parse_value(working_set, span, shape, expand_aliases_denylist)
{
return (s, None);
}
}
@ -3906,6 +3997,7 @@ pub fn parse_math_expression(
working_set: &mut StateWorkingSet,
spans: &[Span],
lhs_row_var_id: Option<VarId>,
expand_aliases_denylist: &[usize],
) -> (Expression, Option<ParseError>) {
// As the expr_stack grows, we increase the required precedence to grow larger
// If, at any time, the operator we're looking at is the same or lower precedence
@ -3923,7 +4015,12 @@ pub fn parse_math_expression(
let mut last_prec = 1000000;
let mut error = None;
let (lhs, err) = parse_value(working_set, spans[0], &SyntaxShape::Any);
let (lhs, err) = parse_value(
working_set,
spans[0],
&SyntaxShape::Any,
expand_aliases_denylist,
);
error = error.or(err);
idx += 1;
@ -3947,7 +4044,12 @@ pub fn parse_math_expression(
break;
}
let (rhs, err) = parse_value(working_set, spans[idx], &SyntaxShape::Any);
let (rhs, err) = parse_value(
working_set,
spans[idx],
&SyntaxShape::Any,
expand_aliases_denylist,
);
error = error.or(err);
if op_prec <= last_prec && expr_stack.len() > 1 {
@ -3965,7 +4067,7 @@ pub fn parse_math_expression(
.expect("internal error: expression stack empty");
if let Some(row_var_id) = lhs_row_var_id {
expand_to_cell_path(working_set, &mut lhs, row_var_id);
expand_to_cell_path(working_set, &mut lhs, row_var_id, expand_aliases_denylist);
}
let (result_ty, err) = math_result_type(working_set, &mut lhs, &mut op, &mut rhs);
@ -3999,7 +4101,7 @@ pub fn parse_math_expression(
.expect("internal error: expression stack empty");
if let Some(row_var_id) = lhs_row_var_id {
expand_to_cell_path(working_set, &mut lhs, row_var_id);
expand_to_cell_path(working_set, &mut lhs, row_var_id, expand_aliases_denylist);
}
let (result_ty, err) = math_result_type(working_set, &mut lhs, &mut op, &mut rhs);
@ -4024,7 +4126,7 @@ pub fn parse_math_expression(
pub fn parse_expression(
working_set: &mut StateWorkingSet,
spans: &[Span],
expand_aliases: bool,
expand_aliases_denylist: &[usize],
) -> (Expression, Option<ParseError>) {
let mut pos = 0;
let mut shorthand = vec![];
@ -4092,56 +4194,110 @@ pub fn parse_expression(
.iter()
.any(|x| x == bytes)
{
parse_math_expression(working_set, &spans[pos..], None)
parse_math_expression(working_set, &spans[pos..], None, expand_aliases_denylist)
} else {
// For now, check for special parses of certain keywords
match bytes {
b"def" => (
parse_call(working_set, &spans[pos..], expand_aliases, spans[0]).0,
parse_call(
working_set,
&spans[pos..],
spans[0],
expand_aliases_denylist,
)
.0,
Some(ParseError::BuiltinCommandInPipeline("def".into(), spans[0])),
),
b"extern" => (
parse_call(working_set, &spans[pos..], expand_aliases, spans[0]).0,
parse_call(
working_set,
&spans[pos..],
spans[0],
expand_aliases_denylist,
)
.0,
Some(ParseError::BuiltinCommandInPipeline(
"extern".into(),
spans[0],
)),
),
b"let" => (
parse_call(working_set, &spans[pos..], expand_aliases, spans[0]).0,
parse_call(
working_set,
&spans[pos..],
spans[0],
expand_aliases_denylist,
)
.0,
Some(ParseError::BuiltinCommandInPipeline("let".into(), spans[0])),
),
b"alias" => (
parse_call(working_set, &spans[pos..], expand_aliases, spans[0]).0,
parse_call(
working_set,
&spans[pos..],
spans[0],
expand_aliases_denylist,
)
.0,
Some(ParseError::BuiltinCommandInPipeline(
"alias".into(),
spans[0],
)),
),
b"module" => (
parse_call(working_set, &spans[pos..], expand_aliases, spans[0]).0,
parse_call(
working_set,
&spans[pos..],
spans[0],
expand_aliases_denylist,
)
.0,
Some(ParseError::BuiltinCommandInPipeline(
"module".into(),
spans[0],
)),
),
b"use" => (
parse_call(working_set, &spans[pos..], expand_aliases, spans[0]).0,
parse_call(
working_set,
&spans[pos..],
spans[0],
expand_aliases_denylist,
)
.0,
Some(ParseError::BuiltinCommandInPipeline("use".into(), spans[0])),
),
b"source" => (
parse_call(working_set, &spans[pos..], expand_aliases, spans[0]).0,
parse_call(
working_set,
&spans[pos..],
spans[0],
expand_aliases_denylist,
)
.0,
Some(ParseError::BuiltinCommandInPipeline(
"source".into(),
spans[0],
)),
),
b"export" => (
parse_call(working_set, &spans[pos..], expand_aliases, spans[0]).0,
parse_call(
working_set,
&spans[pos..],
spans[0],
expand_aliases_denylist,
)
.0,
Some(ParseError::UnexpectedKeyword("export".into(), spans[0])),
),
b"hide" => (
parse_call(working_set, &spans[pos..], expand_aliases, spans[0]).0,
parse_call(
working_set,
&spans[pos..],
spans[0],
expand_aliases_denylist,
)
.0,
Some(ParseError::BuiltinCommandInPipeline(
"hide".into(),
spans[0],
@ -4149,15 +4305,26 @@ pub fn parse_expression(
),
#[cfg(feature = "plugin")]
b"register" => (
parse_call(working_set, &spans[pos..], expand_aliases, spans[0]).0,
parse_call(
working_set,
&spans[pos..],
spans[0],
expand_aliases_denylist,
)
.0,
Some(ParseError::BuiltinCommandInPipeline(
"plugin".into(),
spans[0],
)),
),
b"for" => parse_for(working_set, spans),
_ => parse_call(working_set, &spans[pos..], expand_aliases, spans[0]),
b"for" => parse_for(working_set, spans, expand_aliases_denylist),
_ => parse_call(
working_set,
&spans[pos..],
spans[0],
expand_aliases_denylist,
),
}
};
@ -4240,21 +4407,22 @@ pub fn parse_variable(
pub fn parse_builtin_commands(
working_set: &mut StateWorkingSet,
lite_command: &LiteCommand,
expand_aliases_denylist: &[usize],
) -> (Pipeline, Option<ParseError>) {
let name = working_set.get_span_contents(lite_command.parts[0]);
match name {
b"def" | b"def-env" => parse_def(working_set, lite_command),
b"extern" => parse_extern(working_set, lite_command),
b"let" => parse_let(working_set, &lite_command.parts),
b"def" | b"def-env" => parse_def(working_set, lite_command, expand_aliases_denylist),
b"extern" => parse_extern(working_set, lite_command, expand_aliases_denylist),
b"let" => parse_let(working_set, &lite_command.parts, expand_aliases_denylist),
b"for" => {
let (expr, err) = parse_for(working_set, &lite_command.parts);
let (expr, err) = parse_for(working_set, &lite_command.parts, expand_aliases_denylist);
(Pipeline::from_vec(vec![expr]), err)
}
b"alias" => parse_alias(working_set, &lite_command.parts),
b"module" => parse_module(working_set, &lite_command.parts),
b"use" => parse_use(working_set, &lite_command.parts),
b"source" => parse_source(working_set, &lite_command.parts),
b"alias" => parse_alias(working_set, &lite_command.parts, expand_aliases_denylist),
b"module" => parse_module(working_set, &lite_command.parts, expand_aliases_denylist),
b"use" => parse_use(working_set, &lite_command.parts, expand_aliases_denylist),
b"source" => parse_source(working_set, &lite_command.parts, expand_aliases_denylist),
b"export" => (
garbage_pipeline(&lite_command.parts),
Some(ParseError::UnexpectedKeyword(
@ -4262,11 +4430,12 @@ pub fn parse_builtin_commands(
lite_command.parts[0],
)),
),
b"hide" => parse_hide(working_set, &lite_command.parts),
b"hide" => parse_hide(working_set, &lite_command.parts, expand_aliases_denylist),
#[cfg(feature = "plugin")]
b"register" => parse_register(working_set, &lite_command.parts),
b"register" => parse_register(working_set, &lite_command.parts, expand_aliases_denylist),
_ => {
let (expr, err) = parse_expression(working_set, &lite_command.parts, true);
let (expr, err) =
parse_expression(working_set, &lite_command.parts, expand_aliases_denylist);
(Pipeline::from_vec(vec![expr]), err)
}
}
@ -4275,6 +4444,7 @@ pub fn parse_builtin_commands(
pub fn parse_record(
working_set: &mut StateWorkingSet,
span: Span,
expand_aliases_denylist: &[usize],
) -> (Expression, Option<ParseError>) {
let bytes = working_set.get_span_contents(span);
@ -4312,7 +4482,12 @@ pub fn parse_record(
let mut idx = 0;
while idx < tokens.len() {
let (field, err) = parse_value(working_set, tokens[idx].span, &SyntaxShape::Any);
let (field, err) = parse_value(
working_set,
tokens[idx].span,
&SyntaxShape::Any,
expand_aliases_denylist,
);
error = error.or(err);
idx += 1;
@ -4331,7 +4506,12 @@ pub fn parse_record(
Some(ParseError::Expected("record".into(), span)),
);
}
let (value, err) = parse_value(working_set, tokens[idx].span, &SyntaxShape::Any);
let (value, err) = parse_value(
working_set,
tokens[idx].span,
&SyntaxShape::Any,
expand_aliases_denylist,
);
error = error.or(err);
idx += 1;
@ -4353,6 +4533,7 @@ pub fn parse_block(
working_set: &mut StateWorkingSet,
lite_block: &LiteBlock,
scoped: bool,
expand_aliases_denylist: &[usize],
) -> (Block, Option<ParseError>) {
trace!("parsing block: {:?}", lite_block);
@ -4366,7 +4547,11 @@ pub fn parse_block(
// that share the same block can see each other
for pipeline in &lite_block.block {
if pipeline.commands.len() == 1 {
if let Some(err) = parse_def_predecl(working_set, &pipeline.commands[0].parts) {
if let Some(err) = parse_def_predecl(
working_set,
&pipeline.commands[0].parts,
expand_aliases_denylist,
) {
error = error.or(Some(err));
}
}
@ -4382,7 +4567,8 @@ pub fn parse_block(
.commands
.iter()
.map(|command| {
let (expr, err) = parse_expression(working_set, &command.parts, true);
let (expr, err) =
parse_expression(working_set, &command.parts, expand_aliases_denylist);
if error.is_none() {
error = err;
@ -4402,8 +4588,11 @@ pub fn parse_block(
expressions: output,
}
} else {
let (mut pipeline, err) =
parse_builtin_commands(working_set, &pipeline.commands[0]);
let (mut pipeline, err) = parse_builtin_commands(
working_set,
&pipeline.commands[0],
expand_aliases_denylist,
);
if idx == 0 {
if let Some(let_decl_id) = working_set.find_decl(b"let") {
@ -4776,6 +4965,7 @@ pub fn parse(
fname: Option<&str>,
contents: &[u8],
scoped: bool,
expand_aliases_denylist: &[usize],
) -> (Block, Option<ParseError>) {
trace!("starting top-level parse");
@ -4796,7 +4986,7 @@ pub fn parse(
let (output, err) = lite_parse(&output);
error = error.or(err);
let (mut output, err) = parse_block(working_set, &output, scoped);
let (mut output, err) = parse_block(working_set, &output, scoped, expand_aliases_denylist);
error = error.or(err);
let mut seen = vec![];