Revert "Span ID Refactor (Step 2): Make Call SpanId-friendly (#13268)" (#13292)

This reverts commit 0cfd5fbece.

The original PR messed up syntax higlighting of aliases and causes
panics of completion in the presence of alias.

<!--
if this PR closes one or more issues, you can automatically link the PR
with
them by using one of the [*linking
keywords*](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword),
e.g.
- this PR should close #xxxx
- fixes #xxxx

you can also mention related issues, PRs or discussions!
-->

# Description
<!--
Thank you for improving Nushell. Please, check our [contributing
guide](../CONTRIBUTING.md) and talk to the core team before making major
changes.

Description of your pull request goes here. **Provide examples and/or
screenshots** if your changes affect the user experience.
-->

# User-Facing Changes
<!-- List of all changes that impact the user experience here. This
helps us keep track of breaking changes. -->

# Tests + Formatting
<!--
Don't forget to add tests that cover your changes.

Make sure you've run and fixed any issues with these commands:

- `cargo fmt --all -- --check` to check standard code formatting (`cargo
fmt --all` applies these changes)
- `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used` to
check that you're using the standard code style
- `cargo test --workspace` to check that all tests pass (on Windows make
sure to [enable developer
mode](https://learn.microsoft.com/en-us/windows/apps/get-started/developer-mode-features-and-debugging))
- `cargo run -- -c "use toolkit.nu; toolkit test stdlib"` to run the
tests for the standard library

> **Note**
> from `nushell` you can also use the `toolkit` as follows
> ```bash
> use toolkit.nu # or use an `env_change` hook to activate it
automatically
> toolkit check pr
> ```
-->

# After Submitting
<!-- If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
-->
This commit is contained in:
Jakub Žádník 2024-07-04 00:02:13 +03:00 committed by GitHub
parent ca7a2ae1d6
commit 3fae77209a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
31 changed files with 296 additions and 468 deletions

View file

@ -62,7 +62,7 @@ impl Command for KeybindingsList {
.collect()
} else {
call.named_iter()
.flat_map(|(argument, _, _, _)| get_records(argument.item.as_str(), call.head))
.flat_map(|(argument, _, _)| get_records(argument.item.as_str(), call.head))
.collect()
};

View file

@ -7,7 +7,7 @@ use nu_protocol::{
ast::{Argument, Call, Expr, Expression},
debugger::WithoutDebug,
engine::{Stack, StateWorkingSet},
PipelineData, Span, Spanned, Type, Value,
PipelineData, Span, Type, Value,
};
use nu_utils::IgnoreCaseExt;
use std::collections::HashMap;
@ -53,21 +53,18 @@ impl Completer for CustomCompletion {
&Call {
decl_id: self.decl_id,
head: span,
arguments: Spanned {
item: vec![
Argument::Positional(Expression::new_unknown(
Expr::String(self.line.clone()),
Span::unknown(),
Type::String,
)),
Argument::Positional(Expression::new_unknown(
Expr::Int(line_pos as i64),
Span::unknown(),
Type::Int,
)),
],
span: Span::unknown(),
},
arguments: vec![
Argument::Positional(Expression::new_unknown(
Expr::String(self.line.clone()),
Span::unknown(),
Type::String,
)),
Argument::Positional(Expression::new_unknown(
Expr::Int(line_pos as i64),
Span::unknown(),
Type::Int,
)),
],
parser_info: HashMap::new(),
},
PipelineData::empty(),

View file

@ -400,7 +400,7 @@ fn find_matching_block_end_in_expr(
}
}
Expr::Call(call) => call.arguments.item.iter().find_map(|arg| {
Expr::Call(call) => call.arguments.iter().find_map(|arg| {
arg.expr().and_then(|expr| {
find_matching_block_end_in_expr(
line,

View file

@ -49,7 +49,7 @@ impl Command for BytesBuild {
_input: PipelineData,
) -> Result<PipelineData, ShellError> {
let mut output = vec![];
for val in call.rest_iter_flattened(&engine_state, 0, |expr| {
for val in call.rest_iter_flattened(0, |expr| {
let eval_expression = get_eval_expression(engine_state);
eval_expression(engine_state, stack, expr)
})? {

View file

@ -111,11 +111,11 @@ fn get_arguments(
) -> Vec<Value> {
let mut arg_value = vec![];
let span = Span::test_data();
for arg in &call.arguments.item {
for arg in &call.arguments {
match arg {
// I think the second argument to Argument::Named is the short name, but I'm not really sure.
// Please fix it if it's wrong. :)
Argument::Named((name, short, opt_expr, _)) => {
Argument::Named((name, short, opt_expr)) => {
let arg_type = "named";
let arg_value_name = name.item.clone();
let arg_value_name_span_start = name.span.start as i64;

View file

@ -104,7 +104,7 @@ confusing the id/parent_id hierarchy. The --expr flag is helpful for investigati
collect_values,
collect_exprs,
collect_lines,
call.span(&engine_state),
call.span(),
);
let lock_err = |_| ShellError::GenericError {
@ -125,12 +125,12 @@ confusing the id/parent_id hierarchy. The --expr flag is helpful for investigati
let pipeline_data = result?;
// Collect the output
let _ = pipeline_data.into_value(call.span(&engine_state));
let _ = pipeline_data.into_value(call.span());
Ok(engine_state
.deactivate_debugger()
.map_err(lock_err)?
.report(engine_state, call.span(&engine_state))?
.report(engine_state, call.span())?
.into_pipeline_data())
}

View file

@ -177,12 +177,7 @@ impl Command for Open {
let block = engine_state.get_block(block_id);
eval_block(engine_state, stack, block, stream)
} else {
decl.run(
engine_state,
stack,
&Call::new(call_span, call.arguments_span()),
stream,
)
decl.run(engine_state, stack, &Call::new(call_span), stream)
};
output.push(command_output.map_err(|inner| {
ShellError::GenericError{

View file

@ -398,7 +398,7 @@ fn convert_to_extension(
let eval_block = get_eval_block(engine_state);
eval_block(engine_state, stack, block, input)
} else {
decl.run(engine_state, stack, &Call::new(span, span.past()), input)
decl.run(engine_state, stack, &Call::new(span), input)
}
} else {
Ok(input)

View file

@ -103,7 +103,7 @@ pub fn get_rest_for_glob_pattern(
let mut output = vec![];
let eval_expression = get_eval_expression(engine_state);
for result in call.rest_iter_flattened(&engine_state, starting_pos, |expr| {
for result in call.rest_iter_flattened(starting_pos, |expr| {
let result = eval_expression(engine_state, stack, expr);
match result {
Err(e) => Err(e),

View file

@ -141,7 +141,7 @@ fn from_csv(
} else {
return Err(ShellError::NonUtf8Custom {
msg: "separator should be a single char or a 4-byte unicode".into(),
span: call.span(&engine_state),
span: call.span(),
});
}
}

View file

@ -3,7 +3,6 @@ use nu_color_config::StyleComputer;
use nu_engine::command_prelude::*;
use nu_protocol::ast::{Expr, Expression};
use nu_protocol::engine::UNKNOWN_SPAN_ID;
use std::collections::VecDeque;
#[derive(Clone)]
@ -144,7 +143,7 @@ pub fn cal(
style_computer,
)?;
let mut table_no_index = Call::new(Span::unknown(), Span::unknown());
let mut table_no_index = Call::new(Span::unknown());
table_no_index.add_named((
Spanned {
item: "index".to_string(),
@ -156,7 +155,6 @@ pub fn cal(
Span::unknown(),
Type::Bool,
)),
UNKNOWN_SPAN_ID,
));
let cal_table_output =

View file

@ -412,7 +412,7 @@ fn display(help: &str, engine_state: &EngineState, stack: &mut Stack, span: Span
let result = decl.run(
engine_state,
stack,
&Call::new(span, span.past()),
&Call::new(span),
Value::string(item, Span::unknown()).into_pipeline_data(),
);

View file

@ -547,7 +547,7 @@ fn transform_response_using_content_type(
Some(converter_id) => engine_state.get_decl(converter_id).run(
engine_state,
stack,
&Call::new(span, span.past()),
&Call::new(span),
output,
),
None => Ok(output),

View file

@ -58,12 +58,7 @@ impl Command for IsTerminal {
_ => {
return Err(ShellError::IncompatibleParametersSingle {
msg: "Only one stream may be checked".into(),
span: Span::merge_many(
call.arguments
.item
.iter()
.map(|arg| arg.span(&engine_state)),
),
span: Span::merge_many(call.arguments.iter().map(|arg| arg.span())),
});
}
};

View file

@ -375,12 +375,8 @@ fn write_pipeline_data(
Arc::make_mut(&mut engine_state.config).use_ansi_coloring = false;
// Invoke the `table` command.
let output = crate::Table.run(
&engine_state,
&mut stack,
&Call::new(Span::unknown(), Span::unknown()),
data,
)?;
let output =
crate::Table.run(&engine_state, &mut stack, &Call::new(Span::unknown()), data)?;
// Write the output.
for value in output {

View file

@ -127,7 +127,7 @@ impl Command for Table {
return Ok(val.into_pipeline_data());
}
let cfg = parse_table_config(engine_state, call, engine_state, stack)?;
let cfg = parse_table_config(call, engine_state, stack)?;
let input = CmdInput::new(engine_state, stack, call, input);
// reset vt processing, aka ansi because illbehaved externals can break it
@ -247,7 +247,6 @@ impl TableConfig {
}
fn parse_table_config(
engine_state: &EngineState,
call: &Call,
state: &EngineState,
stack: &mut Stack,
@ -270,9 +269,9 @@ fn parse_table_config(
flatten_separator,
},
};
let theme = get_theme_flag(engine_state, call, state, stack)?
.unwrap_or_else(|| get_config(state, stack).table_mode);
let index = get_index_flag(engine_state, call, state, stack)?;
let theme =
get_theme_flag(call, state, stack)?.unwrap_or_else(|| get_config(state, stack).table_mode);
let index = get_index_flag(call, state, stack)?;
let term_width = get_width_param(width_param);
@ -286,7 +285,6 @@ fn parse_table_config(
}
fn get_index_flag(
engine_state: &EngineState,
call: &Call,
state: &EngineState,
stack: &mut Stack,
@ -310,7 +308,7 @@ fn get_index_flag(
Err(ShellError::UnsupportedInput {
msg: String::from("got a negative integer"),
input: val.to_string(),
msg_span: call.span(&engine_state),
msg_span: call.span(),
input_span: internal_span,
})
} else {
@ -321,14 +319,13 @@ fn get_index_flag(
_ => Err(ShellError::CantConvert {
to_type: String::from("index"),
from_type: String::new(),
span: call.span(&engine_state),
span: call.span(),
help: Some(String::from("supported values: [bool, int, nothing]")),
}),
}
}
fn get_theme_flag(
engine_state: &EngineState,
call: &Call,
state: &EngineState,
stack: &mut Stack,
@ -338,7 +335,7 @@ fn get_theme_flag(
TableMode::from_str(&theme).map_err(|err| ShellError::CantConvert {
to_type: String::from("theme"),
from_type: String::from("string"),
span: call.span(&engine_state),
span: call.span(),
help: Some(format!("{}, but found '{}'.", err, theme)),
})
})

View file

@ -113,7 +113,7 @@ impl CallExt for Call {
let stack = &mut stack.use_call_arg_out_dest();
let mut output = vec![];
for result in self.rest_iter_flattened(&engine_state, starting_pos, |expr| {
for result in self.rest_iter_flattened(starting_pos, |expr| {
eval_expression::<WithoutDebug>(engine_state, stack, expr)
})? {
output.push(FromValue::from_value(result)?);

View file

@ -48,7 +48,7 @@ fn nu_highlight_string(code_string: &str, engine_state: &EngineState, stack: &mu
if let Ok(output) = decl.run(
engine_state,
stack,
&Call::new(Span::unknown(), Span::unknown()),
&Call::new(Span::unknown()),
Value::string(code_string, Span::unknown()).into_pipeline_data(),
) {
let result = output.into_value(Span::unknown());
@ -241,10 +241,7 @@ fn get_documentation(
&Call {
decl_id,
head: span,
arguments: Spanned {
item: vec![],
span: span.past(),
},
arguments: vec![],
parser_info: HashMap::new(),
},
PipelineData::Value(Value::list(vals, span), None),
@ -276,7 +273,7 @@ fn get_documentation(
match decl.run(
engine_state,
stack,
&Call::new(Span::unknown(), Span::unknown()),
&Call::new(Span::unknown()),
Value::string(example.example, Span::unknown()).into_pipeline_data(),
) {
Ok(output) => {
@ -299,7 +296,7 @@ fn get_documentation(
}
if let Some(result) = &example.result {
let mut table_call = Call::new(Span::unknown(), Span::unknown());
let mut table_call = Call::new(Span::unknown());
if example.example.ends_with("--collapse") {
// collapse the result
table_call.add_named((
@ -309,7 +306,6 @@ fn get_documentation(
},
None,
None,
UNKNOWN_SPAN_ID,
))
} else {
// expand the result
@ -320,7 +316,6 @@ fn get_documentation(
},
None,
None,
UNKNOWN_SPAN_ID,
))
}
let table = engine_state
@ -373,17 +368,13 @@ fn get_ansi_color_for_component_or_default(
// Call ansi command using argument
if let Some(argument) = argument_opt {
if let Some(decl_id) = engine_state.find_decl(b"ansi", &[]) {
let arg_span = argument.span(&engine_state);
if let Ok(result) = eval_call::<WithoutDebug>(
engine_state,
caller_stack,
&Call {
decl_id,
head: span,
arguments: Spanned {
item: vec![argument],
span: arg_span,
},
arguments: vec![argument],
parser_info: HashMap::new(),
},
PipelineData::Empty,

View file

@ -26,7 +26,7 @@ pub fn eval_call<D: DebugContext>(
}
let decl = engine_state.get_decl(call.decl_id);
if !decl.is_known_external() && call.named_iter().any(|(flag, _, _, _)| flag.item == "help") {
if !decl.is_known_external() && call.named_iter().any(|(flag, _, _)| flag.item == "help") {
let help = get_full_help(decl, engine_state, caller_stack);
Ok(Value::string(help, call.head).into_pipeline_data())
} else if let Some(block_id) = decl.block_id() {
@ -100,7 +100,6 @@ pub fn eval_call<D: DebugContext>(
let mut rest_items = vec![];
for result in call.rest_iter_flattened(
&engine_state,
decl.signature().required_positional.len()
+ decl.signature().optional_positional.len(),
|expr| eval_expression::<D>(engine_state, caller_stack, expr),
@ -214,16 +213,8 @@ fn eval_external(
})?;
let command = engine_state.get_decl(decl_id);
let spans: Vec<Span> = args
.iter()
.map(|arg| match arg {
ExternalArgument::Regular(expr) | ExternalArgument::Spread(expr) => {
expr.span(&engine_state)
}
})
.collect();
let mut call = Call::new(head.span(&engine_state), Span::concat(&spans));
let mut call = Call::new(head.span(&engine_state));
call.add_positional(head.clone());

View file

@ -252,7 +252,7 @@ fn flatten_expression_into(
}
let arg_start = output.len();
for arg in &call.arguments.item {
for arg in &call.arguments {
match arg {
Argument::Positional(positional) | Argument::Unknown(positional) => {
flatten_expression_into(working_set, positional, output)

View file

@ -43,7 +43,7 @@ impl Command for KnownExternal {
let command = engine_state.get_decl(decl_id);
let mut extern_call = Call::new(head_span, call.arguments_span());
let mut extern_call = Call::new(head_span);
let extern_name = if let Some(name_bytes) = engine_state.find_decl_name(call.decl_id, &[]) {
String::from_utf8_lossy(name_bytes)
@ -78,7 +78,7 @@ impl Command for KnownExternal {
));
}
for arg in &call.arguments.item {
for arg in &call.arguments {
match arg {
Argument::Positional(positional) => extern_call.add_positional(positional.clone()),
Argument::Named(named) => {

View file

@ -21,9 +21,8 @@ pub use nu_protocol::parser_path::*;
pub use parse_keywords::*;
pub use parser::{
is_math_expression_like, named_arg_span, parse, parse_block, parse_expression,
parse_external_call, parse_unit_value, trim_quotes, trim_quotes_str, unescape_unquote_string,
DURATION_UNIT_GROUPS,
is_math_expression_like, parse, parse_block, parse_expression, parse_external_call,
parse_unit_value, trim_quotes, trim_quotes_str, unescape_unquote_string, DURATION_UNIT_GROUPS,
};
#[cfg(feature = "plugin")]

View file

@ -123,8 +123,8 @@ pub fn parse_keyword(working_set: &mut StateWorkingSet, lite_command: &LiteComma
// Apply parse keyword side effects
let cmd = working_set.get_decl(call.decl_id);
// check help flag first.
if call.named_iter().any(|(flag, _, _, _)| flag.item == "help") {
let call_span = call.span(working_set);
if call.named_iter().any(|(flag, _, _)| flag.item == "help") {
let call_span = call.span();
return Pipeline::from_vec(vec![Expression::new(
working_set,
Expr::Call(call),
@ -1056,7 +1056,7 @@ pub fn parse_alias(
// First from comments, if any are present
false => working_set.build_usage(&lite_command.comments),
// Then from the command itself
true => match alias_call.arguments.item.get(1) {
true => match alias_call.arguments.get(1) {
Some(Argument::Positional(Expression {
expr: Expr::Keyword(kw),
..
@ -1258,10 +1258,7 @@ pub fn parse_export_in_module(
let mut call = Box::new(Call {
head: spans[0],
decl_id: export_decl_id,
arguments: Spanned {
item: vec![],
span: spans[0].past(),
},
arguments: vec![],
parser_info: HashMap::new(),
});
@ -2266,21 +2263,13 @@ pub fn parse_module(
.find_decl(b"module")
.expect("internal error: missing module command");
let args_span = Span::concat(&[
module_name_or_path_expr.span(working_set),
block_expr.span(working_set),
]);
let call = Box::new(Call {
head: Span::concat(&spans[..split_id]),
decl_id: module_decl_id,
arguments: Spanned {
item: vec![
Argument::Positional(module_name_or_path_expr),
Argument::Positional(block_expr),
],
span: args_span,
},
arguments: vec![
Argument::Positional(module_name_or_path_expr),
Argument::Positional(block_expr),
],
parser_info: HashMap::new(),
});
@ -2712,7 +2701,7 @@ pub fn parse_hide(working_set: &mut StateWorkingSet, lite_command: &LiteCommand)
}
pub fn parse_overlay_new(working_set: &mut StateWorkingSet, call: Box<Call>) -> Pipeline {
let call_span = call.span(working_set);
let call_span = call.span();
let (overlay_name, _) = if let Some(expr) = call.positional_nth(0) {
match eval_constant(working_set, expr) {
@ -2761,7 +2750,7 @@ pub fn parse_overlay_new(working_set: &mut StateWorkingSet, call: Box<Call>) ->
}
pub fn parse_overlay_use(working_set: &mut StateWorkingSet, call: Box<Call>) -> Pipeline {
let call_span = call.span(working_set);
let call_span = call.span();
let (overlay_name, overlay_name_span) = if let Some(expr) = call.positional_nth(0) {
match eval_constant(working_set, expr) {
@ -2984,7 +2973,7 @@ pub fn parse_overlay_use(working_set: &mut StateWorkingSet, call: Box<Call>) ->
}
pub fn parse_overlay_hide(working_set: &mut StateWorkingSet, call: Box<Call>) -> Pipeline {
let call_span = call.span(working_set);
let call_span = call.span();
let (overlay_name, overlay_name_span) = if let Some(expr) = call.positional_nth(0) {
match eval_constant(working_set, expr) {
@ -3124,16 +3113,10 @@ pub fn parse_let(working_set: &mut StateWorkingSet, spans: &[Span]) -> Pipeline
}
}
let args_span =
Span::concat(&[lvalue.span(working_set), rvalue.span(working_set)]);
let call = Box::new(Call {
decl_id,
head: spans[0],
arguments: Spanned {
item: vec![Argument::Positional(lvalue), Argument::Positional(rvalue)],
span: args_span,
},
arguments: vec![Argument::Positional(lvalue), Argument::Positional(rvalue)],
parser_info: HashMap::new(),
});
@ -3276,16 +3259,10 @@ pub fn parse_const(working_set: &mut StateWorkingSet, spans: &[Span]) -> Pipelin
}
}
let args_span =
Span::concat(&[lvalue.span(working_set), rvalue.span(working_set)]);
let call = Box::new(Call {
decl_id,
head: spans[0],
arguments: Spanned {
item: vec![Argument::Positional(lvalue), Argument::Positional(rvalue)],
span: args_span,
},
arguments: vec![Argument::Positional(lvalue), Argument::Positional(rvalue)],
parser_info: HashMap::new(),
});
@ -3401,16 +3378,10 @@ pub fn parse_mut(working_set: &mut StateWorkingSet, spans: &[Span]) -> Pipeline
}
}
let args_span =
Span::concat(&[lvalue.span(working_set), rvalue.span(working_set)]);
let call = Box::new(Call {
decl_id,
head: spans[0],
arguments: Spanned {
item: vec![Argument::Positional(lvalue), Argument::Positional(rvalue)],
span: args_span,
},
arguments: vec![Argument::Positional(lvalue), Argument::Positional(rvalue)],
parser_info: HashMap::new(),
});
@ -3913,8 +3884,8 @@ pub fn parse_plugin_use(working_set: &mut StateWorkingSet, call: Box<Call>) -> P
let plugin_config = call
.named_iter()
.find(|(arg_name, _, _, _)| arg_name.item == "plugin-config")
.map(|(_, _, expr, _)| {
.find(|(arg_name, _, _)| arg_name.item == "plugin-config")
.map(|(_, _, expr)| {
let expr = expr
.as_ref()
.expect("--plugin-config arg should have been checked already");
@ -3990,7 +3961,7 @@ pub fn parse_plugin_use(working_set: &mut StateWorkingSet, call: Box<Call>) -> P
working_set.error(err);
}
let call_span = call.span(working_set);
let call_span = call.span();
Pipeline::from_vec(vec![Expression::new(
working_set,
@ -4176,6 +4147,6 @@ fn detect_params_in_name(
/// Run has_flag_const and push possible error to working_set
fn has_flag_const(working_set: &mut StateWorkingSet, call: &Call, name: &str) -> Result<bool, ()> {
call.has_flag_const(working_set, name).map_err(|err| {
working_set.error(err.wrap(working_set, call.span(working_set)));
working_set.error(err.wrap(working_set, call.span()));
})
}

View file

@ -160,7 +160,7 @@ pub(crate) fn check_call(
call: &Call,
) {
// Allow the call to pass if they pass in the help flag
if call.named_iter().any(|(n, _, _, _)| n.item == "help") {
if call.named_iter().any(|(n, _, _)| n.item == "help") {
return;
}
@ -180,7 +180,7 @@ pub(crate) fn check_call(
if let Some(last) = call.positional_iter().last() {
working_set.error(ParseError::MissingPositional(
argument.name.clone(),
Span::new(last.span(working_set).end, last.span(working_set).end),
Span::new(last.span.end, last.span.end),
sig.call_signature(),
));
return;
@ -199,7 +199,7 @@ pub(crate) fn check_call(
if let Some(last) = call.positional_iter().last() {
working_set.error(ParseError::MissingPositional(
missing.name.clone(),
Span::new(last.span(working_set).end, last.span(working_set).end),
Span::new(last.span.end, last.span.end),
sig.call_signature(),
))
} else {
@ -211,10 +211,7 @@ pub(crate) fn check_call(
}
} else {
for req_flag in sig.named.iter().filter(|x| x.required) {
if call
.named_iter()
.all(|(n, _, _, _)| n.item != req_flag.long)
{
if call.named_iter().all(|(n, _, _)| n.item != req_flag.long) {
working_set.error(ParseError::MissingRequiredFlag(
req_flag.long.clone(),
command,
@ -489,19 +486,18 @@ fn ensure_flag_arg_type(
arg_shape: &SyntaxShape,
long_name_span: Span,
) -> (Spanned<String>, Expression) {
let arg_span = arg.span(working_set);
if !type_compatible(&arg.ty, &arg_shape.to_type()) {
working_set.error(ParseError::TypeMismatch(
arg_shape.to_type(),
arg.ty,
arg_span,
arg.span,
));
(
Spanned {
item: arg_name,
span: long_name_span,
},
Expression::garbage(working_set, arg_span),
Expression::garbage(working_set, arg.span),
)
} else {
(
@ -920,25 +916,6 @@ pub struct ParsedInternalCall {
pub output: Type,
}
// moved from call.rs since span creation must be done at parse time now
pub fn named_arg_span(
working_set: &StateWorkingSet,
named: &Spanned<String>,
short: &Option<Spanned<String>>,
expr: &Option<Expression>,
) -> Span {
let start = named.span.start;
let end = if let Some(expr) = expr {
expr.span(&working_set).end
} else if let Some(short) = short {
short.span.end
} else {
named.span.end
};
Span::new(start, end)
}
pub fn parse_internal_call(
working_set: &mut StateWorkingSet,
command_span: Span,
@ -947,7 +924,7 @@ pub fn parse_internal_call(
) -> ParsedInternalCall {
trace!("parsing: internal call (decl id: {})", decl_id);
let mut call = Call::new(command_span, Span::concat(spans));
let mut call = Call::new(command_span);
call.decl_id = decl_id;
call.head = command_span;
let _ = working_set.add_span(call.head);
@ -1025,9 +1002,7 @@ pub fn parse_internal_call(
call.add_unknown(arg);
} else {
let named_span = named_arg_span(working_set, &long_name, &None, &arg);
let named_span_id = working_set.add_span(named_span);
call.add_named((long_name, None, arg, named_span_id));
call.add_named((long_name, None, arg));
}
spans_idx += 1;
@ -1078,30 +1053,27 @@ pub fn parse_internal_call(
if flag.long.is_empty() {
if let Some(short) = flag.short {
let named = Spanned {
item: String::new(),
span: spans[spans_idx],
};
let short = Some(Spanned {
item: short.to_string(),
span: spans[spans_idx],
});
let expr = Some(arg);
let named_span =
named_arg_span(working_set, &named, &short, &expr);
let named_span_id = working_set.add_span(named_span);
call.add_named((named, short, expr, named_span_id));
call.add_named((
Spanned {
item: String::new(),
span: spans[spans_idx],
},
Some(Spanned {
item: short.to_string(),
span: spans[spans_idx],
}),
Some(arg),
));
}
} else {
let named = Spanned {
item: flag.long.clone(),
span: spans[spans_idx],
};
let short = None;
let expr = Some(arg);
let named_span = named_arg_span(working_set, &named, &short, &expr);
let named_span_id = working_set.add_span(named_span);
call.add_named((named, short, expr, named_span_id));
call.add_named((
Spanned {
item: flag.long.clone(),
span: spans[spans_idx],
},
None,
Some(arg),
));
}
spans_idx += 1;
} else {
@ -1112,29 +1084,27 @@ pub fn parse_internal_call(
}
} else if flag.long.is_empty() {
if let Some(short) = flag.short {
let named = Spanned {
item: String::new(),
span: spans[spans_idx],
};
let short = Some(Spanned {
item: short.to_string(),
span: spans[spans_idx],
});
let expr = None;
let named_span = named_arg_span(working_set, &named, &short, &expr);
let named_span_id = working_set.add_span(named_span);
call.add_named((named, short, expr, named_span_id));
call.add_named((
Spanned {
item: String::new(),
span: spans[spans_idx],
},
Some(Spanned {
item: short.to_string(),
span: spans[spans_idx],
}),
None,
));
}
} else {
let named = Spanned {
item: flag.long.clone(),
span: spans[spans_idx],
};
let short = None;
let expr = None;
let named_span = named_arg_span(working_set, &named, &short, &expr);
let named_span_id = working_set.add_span(named_span);
call.add_named((named, short, expr, named_span_id));
call.add_named((
Spanned {
item: flag.long.clone(),
span: spans[spans_idx],
},
None,
None,
));
}
}
}
@ -1214,13 +1184,12 @@ pub fn parse_internal_call(
);
let arg = if !type_compatible(&positional.shape.to_type(), &arg.ty) {
let arg_ty = arg.ty.clone();
working_set.error(ParseError::TypeMismatch(
positional.shape.to_type(),
arg_ty,
arg.span(working_set),
arg.ty,
arg.span,
));
Expression::garbage(working_set, arg.span(working_set))
Expression::garbage(working_set, arg.span)
} else {
arg
};
@ -1342,7 +1311,7 @@ pub fn parse_call(working_set: &mut StateWorkingSet, spans: &[Span], head: Span)
trace!("parsing: alias of external call");
let mut head = head.clone();
head.span_id = working_set.add_span(spans[0]); // replacing the spans preserves syntax highlighting
head.span = spans[0]; // replacing the spans preserves syntax highlighting
let mut final_args = args.clone().into_vec();
for arg_span in &spans[1..] {
@ -3037,15 +3006,13 @@ pub fn parse_import_pattern(working_set: &mut StateWorkingSet, spans: &[Span]) -
for item in list {
match item {
ListItem::Item(expr) => {
let contents =
working_set.get_span_contents(expr.span(working_set));
output
.push((trim_quotes(contents).to_vec(), expr.span(working_set)));
let contents = working_set.get_span_contents(expr.span);
output.push((trim_quotes(contents).to_vec(), expr.span));
}
ListItem::Spread(_, spread) => {
working_set.error(ParseError::WrongImportPattern(
"cannot spread in an import pattern".into(),
spread.span(working_set),
spread.span,
))
}
}
@ -3055,7 +3022,7 @@ pub fn parse_import_pattern(working_set: &mut StateWorkingSet, spans: &[Span]) -
.members
.push(ImportPatternMember::List { names: output });
} else {
working_set.error(ParseError::ExportNotFound(result.span(working_set)));
working_set.error(ParseError::ExportNotFound(result.span));
return Expression::new(
working_set,
Expr::ImportPattern(Box::new(import_pattern)),
@ -3812,7 +3779,7 @@ pub fn parse_signature_helper(working_set: &mut StateWorkingSet, span: Span) ->
format!(
"expected default value to be `{var_type}`"
),
expression.span(working_set),
expression.span,
),
)
}
@ -3825,7 +3792,7 @@ pub fn parse_signature_helper(working_set: &mut StateWorkingSet, span: Span) ->
Some(constant)
} else {
working_set.error(ParseError::NonConstantDefaultValue(
expression.span(working_set),
expression.span,
));
None
};
@ -3839,7 +3806,7 @@ pub fn parse_signature_helper(working_set: &mut StateWorkingSet, span: Span) ->
working_set.error(ParseError::AssignmentMismatch(
"Rest parameter was given a default value".into(),
"can't have default value".into(),
expression.span(working_set),
expression.span,
))
}
Arg::Flag {
@ -3852,7 +3819,7 @@ pub fn parse_signature_helper(working_set: &mut StateWorkingSet, span: Span) ->
},
type_annotated,
} => {
let expression_span = expression.span(working_set);
let expression_span = expression.span;
*default_value = if let Ok(value) =
eval_constant(working_set, &expression)
@ -4098,7 +4065,7 @@ fn parse_table_row(
list.into_iter()
.map(|item| match item {
ListItem::Item(expr) => Ok(expr),
ListItem::Spread(_, spread) => Err(spread.span(working_set)),
ListItem::Spread(_, spread) => Err(spread.span),
})
.collect::<Result<_, _>>()
.map(|exprs| (exprs, span))
@ -4173,7 +4140,7 @@ fn parse_table_expression(working_set: &mut StateWorkingSet, span: Span) -> Expr
}
Ordering::Greater => {
let span = {
let start = list[head.len()].span(working_set).start;
let start = list[head.len()].span.start;
let end = span.end;
Span::new(start, end)
};
@ -4212,7 +4179,7 @@ fn parse_table_expression(working_set: &mut StateWorkingSet, span: Span) -> Expr
};
let ty = if working_set.parse_errors.len() == errors {
let (ty, errs) = table_type(working_set, &head, &rows);
let (ty, errs) = table_type(&head, &rows);
working_set.parse_errors.extend(errs);
ty
} else {
@ -4227,11 +4194,7 @@ fn parse_table_expression(working_set: &mut StateWorkingSet, span: Span) -> Expr
Expression::new(working_set, Expr::Table(table), span, ty)
}
fn table_type(
working_set: &StateWorkingSet,
head: &[Expression],
rows: &[Vec<Expression>],
) -> (Type, Vec<ParseError>) {
fn table_type(head: &[Expression], rows: &[Vec<Expression>]) -> (Type, Vec<ParseError>) {
let mut errors = vec![];
let mut rows = rows.to_vec();
let mut mk_ty = || -> Type {
@ -4261,7 +4224,7 @@ fn table_type(
if let Some(str) = expr.as_string() {
str
} else {
errors.push(mk_error(expr.span(&working_set)));
errors.push(mk_error(expr.span));
String::from("{ column }")
}
})
@ -5152,7 +5115,7 @@ pub fn parse_math_expression(
working_set.error(err);
}
let op_span = Span::append(lhs.span(working_set), rhs.span(working_set));
let op_span = Span::append(lhs.span, rhs.span);
expr_stack.push(Expression::new(
working_set,
Expr::BinaryOp(Box::new(lhs), Box::new(op), Box::new(rhs)),
@ -5188,7 +5151,7 @@ pub fn parse_math_expression(
working_set.error(err)
}
let binary_op_span = Span::append(lhs.span(working_set), rhs.span(working_set));
let binary_op_span = Span::append(lhs.span, rhs.span);
expr_stack.push(Expression::new(
working_set,
Expr::BinaryOp(Box::new(lhs), Box::new(op), Box::new(rhs)),
@ -5369,10 +5332,7 @@ pub fn parse_expression(working_set: &mut StateWorkingSet, spans: &[Span]) -> Ex
let expr = Expr::Call(Box::new(Call {
head: Span::unknown(),
decl_id,
arguments: Spanned {
item: arguments,
span: Span::concat(spans),
},
arguments,
parser_info: HashMap::new(),
}));
@ -6134,7 +6094,7 @@ pub fn discover_captures_in_expr(
}
}
for arg in &call.arguments.item {
for arg in &call.arguments {
match arg {
Argument::Named(named) => {
if let Some(arg) = &named.2 {
@ -6289,7 +6249,7 @@ pub fn discover_captures_in_expr(
}
Expr::Var(var_id) => {
if (*var_id > ENV_VARIABLE_ID || *var_id == IN_VARIABLE_ID) && !seen.contains(var_id) {
output.push((*var_id, expr.span(&working_set)));
output.push((*var_id, expr.span));
}
}
Expr::VarDecl(var_id) => {
@ -6334,7 +6294,7 @@ fn wrap_element_with_collect(
}
fn wrap_expr_with_collect(working_set: &mut StateWorkingSet, expr: &Expression) -> Expression {
let span = expr.span(working_set);
let span = expr.span;
if let Some(decl_id) = working_set.find_decl(b"collect") {
let mut output = vec![];
@ -6364,15 +6324,14 @@ fn wrap_expr_with_collect(working_set: &mut StateWorkingSet, expr: &Expression)
Type::Any,
)));
let named = Spanned {
item: "keep-env".to_string(),
span: Span::unknown(),
};
let short = None;
let expr = None;
let named_span = named_arg_span(working_set, &named, &short, &expr);
let named_span_id = working_set.add_span(named_span);
output.push(Argument::Named((named, short, expr, named_span_id)));
output.push(Argument::Named((
Spanned {
item: "keep-env".to_string(),
span: Span::new(0, 0),
},
None,
None,
)));
// The containing, synthetic call to `collect`.
// We don't want to have a real span as it will confuse flattening
@ -6380,11 +6339,8 @@ fn wrap_expr_with_collect(working_set: &mut StateWorkingSet, expr: &Expression)
Expression::new(
working_set,
Expr::Call(Box::new(Call {
head: Span::unknown(),
arguments: Spanned {
item: output,
span: Span::unknown(),
},
head: Span::new(0, 0),
arguments: output,
decl_id,
parser_info: HashMap::new(),
})),

View file

@ -598,12 +598,9 @@ pub fn parse_call_short_flag_batch_arg_allowed() {
if let Expr::Call(call) = &element.expr.expr {
assert_eq!(call.decl_id, 0);
assert_eq!(call.arguments.item.len(), 2);
matches!(call.arguments.item[0], Argument::Named((_, None, None, _)));
matches!(
call.arguments.item[1],
Argument::Named((_, None, Some(_), _))
);
assert_eq!(call.arguments.len(), 2);
matches!(call.arguments[0], Argument::Named((_, None, None)));
matches!(call.arguments[1], Argument::Named((_, None, Some(_))));
}
}
@ -2153,7 +2150,7 @@ mod input_types {
assert!(pipeline.elements[3].redirection.is_none());
match &pipeline.elements[3].expr.expr {
Expr::Call(call) => {
let arg = &call.arguments.item[0];
let arg = &call.arguments[0];
match arg {
Argument::Positional(a) => match &a.expr {
Expr::FullCellPath(path) => match &path.head.expr {
@ -2350,92 +2347,3 @@ mod operator {
);
}
}
#[cfg(test)]
mod test {
use nu_parser::named_arg_span;
use nu_protocol::ast::{Argument, Call, Expression};
use nu_protocol::engine::{EngineState, StateWorkingSet};
use nu_protocol::{Span, Spanned};
#[test]
fn argument_span_named() {
let engine_state = EngineState::new();
let mut working_set = StateWorkingSet::new(&engine_state);
let named_span = Span::new(2, 3);
let short_span = Span::new(5, 7);
let expr_span = Span::new(11, 13);
let _ = working_set.add_span(named_span);
let _ = working_set.add_span(short_span);
let _ = working_set.add_span(expr_span);
let named = Spanned {
item: "named".to_string(),
span: named_span,
};
let short = Spanned {
item: "short".to_string(),
span: short_span,
};
let expr = Expression::garbage(&mut working_set, expr_span);
let arg_span = named_arg_span(&working_set, &named, &None, &None);
assert_eq!(Span::new(2, 3), arg_span);
let arg_span = named_arg_span(&working_set, &named, &Some(short.clone()), &None);
assert_eq!(Span::new(2, 7), arg_span);
let arg_span = named_arg_span(&working_set, &named, &None, &Some(expr.clone()));
assert_eq!(Span::new(2, 13), arg_span);
let arg_span = named_arg_span(
&working_set,
&named,
&Some(short.clone()),
&Some(expr.clone()),
);
assert_eq!(Span::new(2, 13), arg_span);
}
#[test]
fn argument_span_positional() {
let engine_state = EngineState::new();
let mut working_set = StateWorkingSet::new(&engine_state);
let span = Span::new(2, 3);
let _ = working_set.add_span(span);
let expr = Expression::garbage(&mut working_set, span);
let arg = Argument::Positional(expr);
assert_eq!(span, arg.span(&working_set));
}
#[test]
fn argument_span_unknown() {
let engine_state = EngineState::new();
let mut working_set = StateWorkingSet::new(&engine_state);
let span = Span::new(2, 3);
let _ = working_set.add_span(span);
let expr = Expression::garbage(&mut working_set, span);
let arg = Argument::Unknown(expr);
assert_eq!(span, arg.span(&working_set));
}
#[test]
fn call_arguments_span() {
let engine_state = EngineState::new();
let mut working_set = StateWorkingSet::new(&engine_state);
let arg1_span = Span::new(2, 3);
let arg2_span = Span::new(5, 7);
let mut call = Call::new(Span::new(0, 1), Span::concat(&[arg1_span, arg2_span]));
call.add_positional(Expression::garbage(&mut working_set, arg1_span));
call.add_positional(Expression::garbage(&mut working_set, arg2_span));
assert_eq!(Span::new(2, 7), call.arguments_span());
}
}

View file

@ -34,12 +34,11 @@ impl EvaluatedCall {
stack: &mut Stack,
eval_expression_fn: fn(&EngineState, &mut Stack, &Expression) -> Result<Value, ShellError>,
) -> Result<Self, ShellError> {
let positional = call.rest_iter_flattened(&engine_state, 0, |expr| {
eval_expression_fn(engine_state, stack, expr)
})?;
let positional =
call.rest_iter_flattened(0, |expr| eval_expression_fn(engine_state, stack, expr))?;
let mut named = Vec::with_capacity(call.named_len());
for (string, _, expr, _) in call.named_iter() {
for (string, _, expr) in call.named_iter() {
let value = match expr {
None => None,
Some(expr) => Some(eval_expression_fn(engine_state, stack, expr)?),

View file

@ -4,47 +4,42 @@ use serde::{Deserialize, Serialize};
use crate::{
ast::Expression, engine::StateWorkingSet, eval_const::eval_constant, DeclId, FromValue,
GetSpan, ShellError, Span, SpanId, Spanned, Value,
ShellError, Span, Spanned, Value,
};
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum Argument {
Positional(Expression),
Named(
(
Spanned<String>,
Option<Spanned<String>>,
Option<Expression>,
SpanId,
),
),
Named((Spanned<String>, Option<Spanned<String>>, Option<Expression>)),
Unknown(Expression), // unknown argument used in "fall-through" signatures
Spread(Expression), // a list spread to fill in rest arguments
}
impl Argument {
pub fn span_id(&self) -> SpanId {
match self {
Argument::Positional(e) => e.span_id,
Argument::Named((_, _, _, span_id)) => *span_id,
Argument::Unknown(e) => e.span_id,
Argument::Spread(e) => e.span_id,
}
}
/// The span for an argument
pub fn span(&self, state: &impl GetSpan) -> Span {
pub fn span(&self) -> Span {
match self {
Argument::Positional(e) => e.span(state),
Argument::Named((_, _, _, span_id)) => state.get_span(*span_id),
Argument::Unknown(e) => e.span(state),
Argument::Spread(e) => e.span(state),
Argument::Positional(e) => e.span,
Argument::Named((named, short, expr)) => {
let start = named.span.start;
let end = if let Some(expr) = expr {
expr.span.end
} else if let Some(short) = short {
short.span.end
} else {
named.span.end
};
Span::new(start, end)
}
Argument::Unknown(e) => e.span,
Argument::Spread(e) => e.span,
}
}
pub fn expr(&self) -> Option<&Expression> {
match self {
Argument::Named((_, _, expr, _)) => expr.as_ref(),
Argument::Named((_, _, expr)) => expr.as_ref(),
Argument::Positional(expr) | Argument::Unknown(expr) | Argument::Spread(expr) => {
Some(expr)
}
@ -63,20 +58,17 @@ pub struct Call {
/// identifier of the declaration to call
pub decl_id: DeclId,
pub head: Span,
pub arguments: Spanned<Vec<Argument>>,
pub arguments: Vec<Argument>,
/// this field is used by the parser to pass additional command-specific information
pub parser_info: HashMap<String, Expression>,
}
impl Call {
pub fn new(head: Span, args_span: Span) -> Call {
pub fn new(head: Span) -> Call {
Self {
decl_id: 0,
head,
arguments: Spanned {
item: vec![],
span: args_span,
},
arguments: vec![],
parser_info: HashMap::new(),
}
}
@ -88,20 +80,23 @@ impl Call {
/// If there are one or more arguments the span encompasses the start of the first argument to
/// end of the last argument
pub fn arguments_span(&self) -> Span {
self.arguments.span
let past = self.head.past();
let start = self
.arguments
.first()
.map(|a| a.span())
.unwrap_or(past)
.start;
let end = self.arguments.last().map(|a| a.span()).unwrap_or(past).end;
Span::new(start, end)
}
pub fn named_iter(
&self,
) -> impl Iterator<
Item = &(
Spanned<String>,
Option<Spanned<String>>,
Option<Expression>,
SpanId,
),
> {
self.arguments.item.iter().filter_map(|arg| match arg {
) -> impl Iterator<Item = &(Spanned<String>, Option<Spanned<String>>, Option<Expression>)> {
self.arguments.iter().filter_map(|arg| match arg {
Argument::Named(named) => Some(named),
Argument::Positional(_) => None,
Argument::Unknown(_) => None,
@ -111,15 +106,9 @@ impl Call {
pub fn named_iter_mut(
&mut self,
) -> impl Iterator<
Item = &mut (
Spanned<String>,
Option<Spanned<String>>,
Option<Expression>,
SpanId,
),
> {
self.arguments.item.iter_mut().filter_map(|arg| match arg {
) -> impl Iterator<Item = &mut (Spanned<String>, Option<Spanned<String>>, Option<Expression>)>
{
self.arguments.iter_mut().filter_map(|arg| match arg {
Argument::Named(named) => Some(named),
Argument::Positional(_) => None,
Argument::Unknown(_) => None,
@ -133,31 +122,25 @@ impl Call {
pub fn add_named(
&mut self,
named: (
Spanned<String>,
Option<Spanned<String>>,
Option<Expression>,
SpanId,
),
named: (Spanned<String>, Option<Spanned<String>>, Option<Expression>),
) {
self.arguments.item.push(Argument::Named(named));
self.arguments.push(Argument::Named(named));
}
pub fn add_positional(&mut self, positional: Expression) {
self.arguments.item.push(Argument::Positional(positional));
self.arguments.push(Argument::Positional(positional));
}
pub fn add_unknown(&mut self, unknown: Expression) {
self.arguments.item.push(Argument::Unknown(unknown));
self.arguments.push(Argument::Unknown(unknown));
}
pub fn add_spread(&mut self, args: Expression) {
self.arguments.item.push(Argument::Spread(args));
self.arguments.push(Argument::Spread(args));
}
pub fn positional_iter(&self) -> impl Iterator<Item = &Expression> {
self.arguments
.item
.iter()
.take_while(|arg| match arg {
Argument::Spread(_) => false, // Don't include positional arguments given to rest parameter
@ -185,7 +168,6 @@ impl Call {
// todo maybe rewrite to be more elegant or something
let args = self
.arguments
.item
.iter()
.filter_map(|arg| match arg {
Argument::Named(_) => None,
@ -276,9 +258,9 @@ impl Call {
) -> Result<Vec<T>, ShellError> {
let mut output = vec![];
for result in self.rest_iter_flattened(&working_set, starting_pos, |expr| {
eval_constant(working_set, expr)
})? {
for result in
self.rest_iter_flattened(starting_pos, |expr| eval_constant(working_set, expr))?
{
output.push(FromValue::from_value(result)?);
}
@ -287,7 +269,6 @@ impl Call {
pub fn rest_iter_flattened<F>(
&self,
state: &impl GetSpan,
start: usize,
mut eval: F,
) -> Result<Vec<Value>, ShellError>
@ -301,11 +282,7 @@ impl Call {
if spread {
match result {
Value::List { mut vals, .. } => output.append(&mut vals),
_ => {
return Err(ShellError::CannotSpreadAsList {
span: expr.span(state),
})
}
_ => return Err(ShellError::CannotSpreadAsList { span: expr.span }),
}
} else {
output.push(result);
@ -333,23 +310,23 @@ impl Call {
}
}
pub fn span(&self, state: &impl GetSpan) -> Span {
pub fn span(&self) -> Span {
let mut span = self.head;
for positional in self.positional_iter() {
if positional.span(state).end > span.end {
span.end = positional.span(state).end;
if positional.span.end > span.end {
span.end = positional.span.end;
}
}
for (named, _, val, _) in self.named_iter() {
for (named, _, val) in self.named_iter() {
if named.span.end > span.end {
span.end = named.span.end;
}
if let Some(val) = &val {
if val.span(state).end > span.end {
span.end = val.span(state).end;
if val.span.end > span.end {
span.end = val.span.end;
}
}
}
@ -357,3 +334,77 @@ impl Call {
span
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::engine::EngineState;
#[test]
fn argument_span_named() {
let engine_state = EngineState::new();
let mut working_set = StateWorkingSet::new(&engine_state);
let named = Spanned {
item: "named".to_string(),
span: Span::new(2, 3),
};
let short = Spanned {
item: "short".to_string(),
span: Span::new(5, 7),
};
let expr = Expression::garbage(&mut working_set, Span::new(11, 13));
let arg = Argument::Named((named.clone(), None, None));
assert_eq!(Span::new(2, 3), arg.span());
let arg = Argument::Named((named.clone(), Some(short.clone()), None));
assert_eq!(Span::new(2, 7), arg.span());
let arg = Argument::Named((named.clone(), None, Some(expr.clone())));
assert_eq!(Span::new(2, 13), arg.span());
let arg = Argument::Named((named.clone(), Some(short.clone()), Some(expr.clone())));
assert_eq!(Span::new(2, 13), arg.span());
}
#[test]
fn argument_span_positional() {
let engine_state = EngineState::new();
let mut working_set = StateWorkingSet::new(&engine_state);
let span = Span::new(2, 3);
let expr = Expression::garbage(&mut working_set, span);
let arg = Argument::Positional(expr);
assert_eq!(span, arg.span());
}
#[test]
fn argument_span_unknown() {
let engine_state = EngineState::new();
let mut working_set = StateWorkingSet::new(&engine_state);
let span = Span::new(2, 3);
let expr = Expression::garbage(&mut working_set, span);
let arg = Argument::Unknown(expr);
assert_eq!(span, arg.span());
}
#[test]
fn call_arguments_span() {
let engine_state = EngineState::new();
let mut working_set = StateWorkingSet::new(&engine_state);
let mut call = Call::new(Span::new(0, 1));
call.add_positional(Expression::garbage(&mut working_set, Span::new(2, 3)));
call.add_positional(Expression::garbage(&mut working_set, Span::new(5, 7)));
assert_eq!(Span::new(2, 7), call.arguments_span());
}
}

View file

@ -173,7 +173,7 @@ impl Expression {
Expr::Binary(_) => false,
Expr::Bool(_) => false,
Expr::Call(call) => {
for arg in &call.arguments.item {
for arg in &call.arguments {
match arg {
Argument::Positional(expr)
| Argument::Unknown(expr)
@ -366,7 +366,7 @@ impl Expression {
if replaced.contains_span(call.head) {
call.head = new_span;
}
for arg in call.arguments.item.iter_mut() {
for arg in call.arguments.iter_mut() {
match arg {
Argument::Positional(expr)
| Argument::Unknown(expr)

View file

@ -1023,32 +1023,16 @@ impl<'a> StateWorkingSet<'a> {
impl<'a> GetSpan for &'a StateWorkingSet<'a> {
fn get_span(&self, span_id: SpanId) -> Span {
get_span(self, span_id)
}
}
impl<'a> GetSpan for &'a mut StateWorkingSet<'a> {
fn get_span(&self, span_id: SpanId) -> Span {
get_span(self, span_id)
}
}
impl<'a> GetSpan for StateWorkingSet<'a> {
fn get_span(&self, span_id: SpanId) -> Span {
get_span(self, span_id)
}
}
fn get_span(working_set: &StateWorkingSet, span_id: SpanId) -> Span {
let num_permanent_spans = working_set.permanent_state.num_spans();
if span_id.0 < num_permanent_spans {
working_set.permanent_state.get_span(span_id)
} else {
*working_set
.delta
.spans
.get(span_id.0 - num_permanent_spans)
.expect("internal error: missing span")
let num_permanent_spans = self.permanent_state.num_spans();
if span_id.0 < num_permanent_spans {
self.permanent_state.get_span(span_id)
} else {
*self
.delta
.spans
.get(span_id.0 - num_permanent_spans)
.expect("internal error: missing span")
}
}
}

View file

@ -301,7 +301,7 @@ fn eval_const_call(
return Err(ShellError::NotAConstCommand { span: call.head });
}
if !decl.is_known_external() && call.named_iter().any(|(flag, _, _, _)| flag.item == "help") {
if !decl.is_known_external() && call.named_iter().any(|(flag, _, _)| flag.item == "help") {
// It would require re-implementing get_full_help() for const evaluation. Assuming that
// getting help messages at parse-time is rare enough, we can simply disallow it.
return Err(ShellError::NotAConstHelp { span: call.head });

View file

@ -567,7 +567,7 @@ impl PipelineData {
if command.block_id().is_some() {
self.write_all_and_flush(engine_state, no_newline, to_stderr)
} else {
let call = Call::new(Span::unknown(), Span::unknown());
let call = Call::new(Span::new(0, 0));
let table = command.run(engine_state, stack, &call, self)?;
table.write_all_and_flush(engine_state, no_newline, to_stderr)
}