mirror of
https://github.com/nushell/nushell.git
synced 2025-05-07 19:44:25 +02:00
Refactor to support multiple parse errors (#8765)
# Description This is a pretty heavy refactor of the parser to support multiple parser errors. It has a few issues we should address before landing: - [x] In some cases, error quality has gotten worse `1 / "bob"` for example - [x] if/else isn't currently parsing correctly - probably others # User-Facing Changes This may have error quality degradation as we adjust to the new error reporting mechanism. # 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 -A clippy::needless_collect` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass - `cargo run -- crates/nu-utils/standard_library/tests.nu` 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:
parent
e54b867e8e
commit
aded2c1937
@ -34,9 +34,9 @@ pub fn evaluate_commands(
|
|||||||
|
|
||||||
let mut working_set = StateWorkingSet::new(engine_state);
|
let mut working_set = StateWorkingSet::new(engine_state);
|
||||||
|
|
||||||
let (output, err) = parse(&mut working_set, None, commands.item.as_bytes(), false, &[]);
|
let output = parse(&mut working_set, None, commands.item.as_bytes(), false, &[]);
|
||||||
if let Some(err) = err {
|
if let Some(err) = working_set.parse_errors.first() {
|
||||||
report_error(&working_set, &err);
|
report_error(&working_set, err);
|
||||||
|
|
||||||
std::process::exit(1);
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
|
@ -120,7 +120,7 @@ impl NuCompleter {
|
|||||||
let pos = offset + pos;
|
let pos = offset + pos;
|
||||||
let config = self.engine_state.get_config();
|
let config = self.engine_state.get_config();
|
||||||
|
|
||||||
let (output, _err) = parse(&mut working_set, Some("completer"), &new_line, false, &[]);
|
let output = parse(&mut working_set, Some("completer"), &new_line, false, &[]);
|
||||||
|
|
||||||
for pipeline in output.pipelines.into_iter() {
|
for pipeline in output.pipelines.into_iter() {
|
||||||
for pipeline_element in pipeline.elements {
|
for pipeline_element in pipeline.elements {
|
||||||
|
@ -1,14 +1,12 @@
|
|||||||
use crate::util::eval_source;
|
use crate::util::eval_source;
|
||||||
use nu_command::util::report_error;
|
use nu_command::util::report_error;
|
||||||
#[cfg(feature = "plugin")]
|
#[cfg(feature = "plugin")]
|
||||||
use nu_parser::ParseError;
|
|
||||||
#[cfg(feature = "plugin")]
|
|
||||||
use nu_path::canonicalize_with;
|
use nu_path::canonicalize_with;
|
||||||
use nu_protocol::engine::{EngineState, Stack, StateWorkingSet};
|
use nu_protocol::engine::{EngineState, Stack, StateWorkingSet};
|
||||||
#[cfg(feature = "plugin")]
|
|
||||||
use nu_protocol::Spanned;
|
|
||||||
use nu_protocol::{HistoryFileFormat, PipelineData};
|
use nu_protocol::{HistoryFileFormat, PipelineData};
|
||||||
#[cfg(feature = "plugin")]
|
#[cfg(feature = "plugin")]
|
||||||
|
use nu_protocol::{ParseError, Spanned};
|
||||||
|
#[cfg(feature = "plugin")]
|
||||||
use nu_utils::utils::perf;
|
use nu_utils::utils::perf;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
@ -97,7 +97,7 @@ pub(crate) fn add_menus(
|
|||||||
{
|
{
|
||||||
let (block, _) = {
|
let (block, _) = {
|
||||||
let mut working_set = StateWorkingSet::new(&engine_state);
|
let mut working_set = StateWorkingSet::new(&engine_state);
|
||||||
let (output, _) = parse(
|
let output = parse(
|
||||||
&mut working_set,
|
&mut working_set,
|
||||||
Some(name), // format!("entry #{}", entry_num)
|
Some(name), // format!("entry #{}", entry_num)
|
||||||
definition.as_bytes(),
|
definition.as_bytes(),
|
||||||
|
@ -789,7 +789,7 @@ pub fn eval_string_with_input(
|
|||||||
) -> Result<Value, ShellError> {
|
) -> Result<Value, ShellError> {
|
||||||
let (block, delta) = {
|
let (block, delta) = {
|
||||||
let mut working_set = StateWorkingSet::new(engine_state);
|
let mut working_set = StateWorkingSet::new(engine_state);
|
||||||
let (output, _) = parse(&mut working_set, None, source.as_bytes(), false, &[]);
|
let output = parse(&mut working_set, None, source.as_bytes(), false, &[]);
|
||||||
|
|
||||||
(output, working_set.render())
|
(output, working_set.render())
|
||||||
};
|
};
|
||||||
|
@ -18,10 +18,7 @@ impl Highlighter for NuHighlighter {
|
|||||||
trace!("highlighting: {}", line);
|
trace!("highlighting: {}", line);
|
||||||
|
|
||||||
let mut working_set = StateWorkingSet::new(&self.engine_state);
|
let mut working_set = StateWorkingSet::new(&self.engine_state);
|
||||||
let block = {
|
let block = parse(&mut working_set, None, line.as_bytes(), false, &[]);
|
||||||
let (block, _) = parse(&mut working_set, None, line.as_bytes(), false, &[]);
|
|
||||||
block
|
|
||||||
};
|
|
||||||
let (shapes, global_span_offset) = {
|
let (shapes, global_span_offset) = {
|
||||||
let shapes = flatten_block(&working_set, &block);
|
let shapes = flatten_block(&working_set, &block);
|
||||||
(shapes, self.engine_state.next_span_start())
|
(shapes, self.engine_state.next_span_start())
|
||||||
|
@ -113,7 +113,8 @@ fn gather_env_vars(
|
|||||||
span,
|
span,
|
||||||
}) = parts.get(0)
|
}) = parts.get(0)
|
||||||
{
|
{
|
||||||
let bytes = engine_state.get_span_contents(span);
|
let mut working_set = StateWorkingSet::new(engine_state);
|
||||||
|
let bytes = working_set.get_span_contents(*span);
|
||||||
|
|
||||||
if bytes.len() < 2 {
|
if bytes.len() < 2 {
|
||||||
report_capture_error(
|
report_capture_error(
|
||||||
@ -125,9 +126,12 @@ fn gather_env_vars(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let (bytes, parse_error) = unescape_unquote_string(bytes, *span);
|
let (bytes, err) = unescape_unquote_string(bytes, *span);
|
||||||
|
if let Some(err) = err {
|
||||||
|
working_set.error(err);
|
||||||
|
}
|
||||||
|
|
||||||
if parse_error.is_some() {
|
if working_set.parse_errors.first().is_some() {
|
||||||
report_capture_error(
|
report_capture_error(
|
||||||
engine_state,
|
engine_state,
|
||||||
&String::from_utf8_lossy(contents),
|
&String::from_utf8_lossy(contents),
|
||||||
@ -153,7 +157,8 @@ fn gather_env_vars(
|
|||||||
span,
|
span,
|
||||||
}) = parts.get(2)
|
}) = parts.get(2)
|
||||||
{
|
{
|
||||||
let bytes = engine_state.get_span_contents(span);
|
let mut working_set = StateWorkingSet::new(engine_state);
|
||||||
|
let bytes = working_set.get_span_contents(*span);
|
||||||
|
|
||||||
if bytes.len() < 2 {
|
if bytes.len() < 2 {
|
||||||
report_capture_error(
|
report_capture_error(
|
||||||
@ -165,9 +170,12 @@ fn gather_env_vars(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let (bytes, parse_error) = unescape_unquote_string(bytes, *span);
|
let (bytes, err) = unescape_unquote_string(bytes, *span);
|
||||||
|
if let Some(err) = err {
|
||||||
|
working_set.error(err);
|
||||||
|
}
|
||||||
|
|
||||||
if parse_error.is_some() {
|
if working_set.parse_errors.first().is_some() {
|
||||||
report_capture_error(
|
report_capture_error(
|
||||||
engine_state,
|
engine_state,
|
||||||
&String::from_utf8_lossy(contents),
|
&String::from_utf8_lossy(contents),
|
||||||
@ -209,16 +217,16 @@ pub fn eval_source(
|
|||||||
|
|
||||||
let (block, delta) = {
|
let (block, delta) = {
|
||||||
let mut working_set = StateWorkingSet::new(engine_state);
|
let mut working_set = StateWorkingSet::new(engine_state);
|
||||||
let (output, err) = parse(
|
let output = parse(
|
||||||
&mut working_set,
|
&mut working_set,
|
||||||
Some(fname), // format!("entry #{}", entry_num)
|
Some(fname), // format!("entry #{}", entry_num)
|
||||||
source,
|
source,
|
||||||
false,
|
false,
|
||||||
&[],
|
&[],
|
||||||
);
|
);
|
||||||
if let Some(err) = err {
|
if let Some(err) = working_set.parse_errors.first() {
|
||||||
set_last_exit_code(stack, 1);
|
set_last_exit_code(stack, 1);
|
||||||
report_error(&working_set, &err);
|
report_error(&working_set, err);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
use nu_parser::{parse, ParseError};
|
use nu_parser::parse;
|
||||||
use nu_protocol::engine::{EngineState, StateWorkingSet};
|
use nu_protocol::{
|
||||||
|
engine::{EngineState, StateWorkingSet},
|
||||||
|
ParseError,
|
||||||
|
};
|
||||||
use reedline::{ValidationResult, Validator};
|
use reedline::{ValidationResult, Validator};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
@ -10,9 +13,12 @@ pub struct NuValidator {
|
|||||||
impl Validator for NuValidator {
|
impl Validator for NuValidator {
|
||||||
fn validate(&self, line: &str) -> ValidationResult {
|
fn validate(&self, line: &str) -> ValidationResult {
|
||||||
let mut working_set = StateWorkingSet::new(&self.engine_state);
|
let mut working_set = StateWorkingSet::new(&self.engine_state);
|
||||||
let (_, err) = parse(&mut working_set, None, line.as_bytes(), false, &[]);
|
parse(&mut working_set, None, line.as_bytes(), false, &[]);
|
||||||
|
|
||||||
if matches!(err, Some(ParseError::UnexpectedEof(..))) {
|
if matches!(
|
||||||
|
working_set.parse_errors.first(),
|
||||||
|
Some(ParseError::UnexpectedEof(..))
|
||||||
|
) {
|
||||||
ValidationResult::Incomplete
|
ValidationResult::Incomplete
|
||||||
} else {
|
} else {
|
||||||
ValidationResult::Complete
|
ValidationResult::Complete
|
||||||
|
@ -663,8 +663,8 @@ fn run_external_completion(block: &str, input: &str) -> Vec<Suggestion> {
|
|||||||
let (dir, _, mut engine_state, mut stack) = new_engine();
|
let (dir, _, mut engine_state, mut stack) = new_engine();
|
||||||
let (_, delta) = {
|
let (_, delta) = {
|
||||||
let mut working_set = StateWorkingSet::new(&engine_state);
|
let mut working_set = StateWorkingSet::new(&engine_state);
|
||||||
let (block, err) = parse(&mut working_set, None, block.as_bytes(), false, &[]);
|
let block = parse(&mut working_set, None, block.as_bytes(), false, &[]);
|
||||||
assert!(err.is_none());
|
assert!(working_set.parse_errors.is_empty());
|
||||||
|
|
||||||
(block, working_set.render())
|
(block, working_set.render())
|
||||||
};
|
};
|
||||||
|
@ -146,9 +146,9 @@ pub fn merge_input(
|
|||||||
let (block, delta) = {
|
let (block, delta) = {
|
||||||
let mut working_set = StateWorkingSet::new(engine_state);
|
let mut working_set = StateWorkingSet::new(engine_state);
|
||||||
|
|
||||||
let (block, err) = parse(&mut working_set, None, input, false, &[]);
|
let block = parse(&mut working_set, None, input, false, &[]);
|
||||||
|
|
||||||
assert!(err.is_none());
|
assert!(working_set.parse_errors.is_empty());
|
||||||
|
|
||||||
(block, working_set.render())
|
(block, working_set.render())
|
||||||
};
|
};
|
||||||
|
@ -126,9 +126,9 @@ fn eval_pipeline_without_terminal_expression(
|
|||||||
|
|
||||||
pub fn parse(contents: &str, engine_state: &EngineState) -> (Block, StateDelta) {
|
pub fn parse(contents: &str, engine_state: &EngineState) -> (Block, StateDelta) {
|
||||||
let mut working_set = StateWorkingSet::new(engine_state);
|
let mut working_set = StateWorkingSet::new(engine_state);
|
||||||
let (output, err) = nu_parser::parse(&mut working_set, None, contents.as_bytes(), false, &[]);
|
let output = nu_parser::parse(&mut working_set, None, contents.as_bytes(), false, &[]);
|
||||||
|
|
||||||
if let Some(err) = err {
|
if let Some(err) = working_set.parse_errors.first() {
|
||||||
panic!("test parse error in `{contents}`: {err:?}")
|
panic!("test parse error in `{contents}`: {err:?}")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,7 +50,7 @@ pub fn test_dataframe(cmds: Vec<Box<dyn Command + 'static>>) {
|
|||||||
|
|
||||||
let (block, delta) = {
|
let (block, delta) = {
|
||||||
let mut working_set = StateWorkingSet::new(&engine_state);
|
let mut working_set = StateWorkingSet::new(&engine_state);
|
||||||
let (output, err) = parse(
|
let output = parse(
|
||||||
&mut working_set,
|
&mut working_set,
|
||||||
None,
|
None,
|
||||||
example.example.as_bytes(),
|
example.example.as_bytes(),
|
||||||
@ -58,7 +58,7 @@ pub fn test_dataframe(cmds: Vec<Box<dyn Command + 'static>>) {
|
|||||||
&[],
|
&[],
|
||||||
);
|
);
|
||||||
|
|
||||||
if let Some(err) = err {
|
if let Some(err) = working_set.parse_errors.first() {
|
||||||
panic!("test parse error in `{}`: {:?}", example.example, err)
|
panic!("test parse error in `{}`: {:?}", example.example, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,8 +41,10 @@ impl Command for Ast {
|
|||||||
let pipeline: Spanned<String> = call.req(engine_state, stack, 0)?;
|
let pipeline: Spanned<String> = call.req(engine_state, stack, 0)?;
|
||||||
let mut working_set = StateWorkingSet::new(engine_state);
|
let mut working_set = StateWorkingSet::new(engine_state);
|
||||||
|
|
||||||
let (block_output, error_output) =
|
let block_output = parse(&mut working_set, None, pipeline.item.as_bytes(), false, &[]);
|
||||||
parse(&mut working_set, None, pipeline.item.as_bytes(), false, &[]);
|
|
||||||
|
let error_output = working_set.parse_errors.first();
|
||||||
|
|
||||||
let block_value = Value::String {
|
let block_value = Value::String {
|
||||||
val: format!("{block_output:#?}"),
|
val: format!("{block_output:#?}"),
|
||||||
span: pipeline.span,
|
span: pipeline.span,
|
||||||
|
@ -64,10 +64,9 @@ impl Command for FromNuon {
|
|||||||
let engine_state = engine_state.clone();
|
let engine_state = engine_state.clone();
|
||||||
|
|
||||||
let mut working_set = StateWorkingSet::new(&engine_state);
|
let mut working_set = StateWorkingSet::new(&engine_state);
|
||||||
let mut error = None;
|
|
||||||
let (mut block, err) =
|
let mut block =
|
||||||
nu_parser::parse(&mut working_set, None, string_input.as_bytes(), false, &[]);
|
nu_parser::parse(&mut working_set, None, string_input.as_bytes(), false, &[]);
|
||||||
error = error.or(err);
|
|
||||||
|
|
||||||
if let Some(pipeline) = block.pipelines.get(1) {
|
if let Some(pipeline) = block.pipelines.get(1) {
|
||||||
if let Some(element) = pipeline.elements.get(0) {
|
if let Some(element) = pipeline.elements.get(0) {
|
||||||
@ -146,7 +145,7 @@ impl Command for FromNuon {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(err) = error {
|
if let Some(err) = working_set.parse_errors.first() {
|
||||||
return Err(ShellError::GenericError(
|
return Err(ShellError::GenericError(
|
||||||
"error when parsing nuon text".into(),
|
"error when parsing nuon text".into(),
|
||||||
"could not parse nuon text".into(),
|
"could not parse nuon text".into(),
|
||||||
|
@ -166,10 +166,10 @@ pub fn eval_hook(
|
|||||||
vars.push((var_id, val));
|
vars.push((var_id, val));
|
||||||
}
|
}
|
||||||
|
|
||||||
let (output, err) =
|
let output =
|
||||||
parse(&mut working_set, Some("hook"), val.as_bytes(), false, &[]);
|
parse(&mut working_set, Some("hook"), val.as_bytes(), false, &[]);
|
||||||
if let Some(err) = err {
|
if let Some(err) = working_set.parse_errors.first() {
|
||||||
report_error(&working_set, &err);
|
report_error(&working_set, err);
|
||||||
|
|
||||||
return Err(ShellError::UnsupportedConfigValue(
|
return Err(ShellError::UnsupportedConfigValue(
|
||||||
"valid source code".into(),
|
"valid source code".into(),
|
||||||
|
@ -290,8 +290,8 @@ fn format_record(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
FormatOperation::ValueNeedEval(_col_name, span) => {
|
FormatOperation::ValueNeedEval(_col_name, span) => {
|
||||||
let (exp, may_parse_err) = parse_expression(working_set, &[*span], &[], false);
|
let exp = parse_expression(working_set, &[*span], &[], false);
|
||||||
match may_parse_err {
|
match working_set.parse_errors.first() {
|
||||||
None => {
|
None => {
|
||||||
let parsed_result = eval_expression(engine_state, stack, &exp);
|
let parsed_result = eval_expression(engine_state, stack, &exp);
|
||||||
if let Ok(val) = parsed_result {
|
if let Ok(val) = parsed_result {
|
||||||
|
@ -260,9 +260,14 @@ fn heuristic_parse_file(
|
|||||||
call: &Call,
|
call: &Call,
|
||||||
is_debug: bool,
|
is_debug: bool,
|
||||||
) -> Result<PipelineData, ShellError> {
|
) -> Result<PipelineData, ShellError> {
|
||||||
let (filename, err) = unescape_unquote_string(path.as_bytes(), call.head);
|
let starting_error_count = working_set.parse_errors.len();
|
||||||
if err.is_none() {
|
let bytes = working_set.get_span_contents(call.head);
|
||||||
if let Ok(contents) = std::fs::read(&path) {
|
let (filename, err) = unescape_unquote_string(bytes, call.head);
|
||||||
|
if let Some(err) = err {
|
||||||
|
working_set.error(err);
|
||||||
|
}
|
||||||
|
if starting_error_count == working_set.parse_errors.len() {
|
||||||
|
if let Ok(contents) = std::fs::read(path) {
|
||||||
match parse_script(
|
match parse_script(
|
||||||
working_set,
|
working_set,
|
||||||
Some(filename.as_str()),
|
Some(filename.as_str()),
|
||||||
@ -314,13 +319,17 @@ fn parse_module(
|
|||||||
let end = working_set.next_span_start();
|
let end = working_set.next_span_start();
|
||||||
|
|
||||||
let new_span = Span::new(start, end);
|
let new_span = Span::new(start, end);
|
||||||
let (_, _, _, err) = parse_module_block(working_set, new_span, filename.as_bytes(), &[]);
|
let starting_error_count = working_set.parse_errors.len();
|
||||||
|
parse_module_block(working_set, new_span, filename.as_bytes(), &[]);
|
||||||
|
|
||||||
if err.is_some() {
|
if starting_error_count != working_set.parse_errors.len() {
|
||||||
if is_debug {
|
if is_debug {
|
||||||
let msg = format!(
|
let msg = format!(
|
||||||
r#"Found : {}"#,
|
r#"Found : {}"#,
|
||||||
err.expect("Unable to parse content as module")
|
working_set
|
||||||
|
.parse_errors
|
||||||
|
.first()
|
||||||
|
.expect("Unable to parse content as module")
|
||||||
);
|
);
|
||||||
Err(ShellError::GenericError(
|
Err(ShellError::GenericError(
|
||||||
"Failed to parse content".to_string(),
|
"Failed to parse content".to_string(),
|
||||||
@ -344,9 +353,16 @@ fn parse_script(
|
|||||||
is_debug: bool,
|
is_debug: bool,
|
||||||
span: Span,
|
span: Span,
|
||||||
) -> Result<PipelineData, ShellError> {
|
) -> Result<PipelineData, ShellError> {
|
||||||
let (_, err) = parse(working_set, filename, contents, false, &[]);
|
let starting_error_count = working_set.parse_errors.len();
|
||||||
if err.is_some() {
|
parse(working_set, filename, contents, false, &[]);
|
||||||
let msg = format!(r#"Found : {}"#, err.expect("Unable to parse content"));
|
if starting_error_count != working_set.parse_errors.len() {
|
||||||
|
let msg = format!(
|
||||||
|
r#"Found : {}"#,
|
||||||
|
working_set
|
||||||
|
.parse_errors
|
||||||
|
.first()
|
||||||
|
.expect("Unable to parse content")
|
||||||
|
);
|
||||||
if is_debug {
|
if is_debug {
|
||||||
Err(ShellError::GenericError(
|
Err(ShellError::GenericError(
|
||||||
"Failed to parse content".to_string(),
|
"Failed to parse content".to_string(),
|
||||||
@ -369,9 +385,14 @@ fn parse_file_script(
|
|||||||
call: &Call,
|
call: &Call,
|
||||||
is_debug: bool,
|
is_debug: bool,
|
||||||
) -> Result<PipelineData, ShellError> {
|
) -> Result<PipelineData, ShellError> {
|
||||||
let (filename, err) = unescape_unquote_string(path.as_bytes(), call.head);
|
let starting_error_count = working_set.parse_errors.len();
|
||||||
if err.is_none() {
|
let bytes = working_set.get_span_contents(call.head);
|
||||||
if let Ok(contents) = std::fs::read(&path) {
|
let (filename, err) = unescape_unquote_string(bytes, call.head);
|
||||||
|
if let Some(err) = err {
|
||||||
|
working_set.error(err)
|
||||||
|
}
|
||||||
|
if starting_error_count == working_set.parse_errors.len() {
|
||||||
|
if let Ok(contents) = std::fs::read(path) {
|
||||||
parse_script(
|
parse_script(
|
||||||
working_set,
|
working_set,
|
||||||
Some(filename.as_str()),
|
Some(filename.as_str()),
|
||||||
@ -393,8 +414,13 @@ fn parse_file_module(
|
|||||||
call: &Call,
|
call: &Call,
|
||||||
is_debug: bool,
|
is_debug: bool,
|
||||||
) -> Result<PipelineData, ShellError> {
|
) -> Result<PipelineData, ShellError> {
|
||||||
let (filename, err) = unescape_unquote_string(path.as_bytes(), call.head);
|
let starting_error_count = working_set.parse_errors.len();
|
||||||
if err.is_none() {
|
let bytes = working_set.get_span_contents(call.head);
|
||||||
|
let (filename, err) = unescape_unquote_string(bytes, call.head);
|
||||||
|
if let Some(err) = err {
|
||||||
|
working_set.error(err);
|
||||||
|
}
|
||||||
|
if starting_error_count == working_set.parse_errors.len() {
|
||||||
if let Ok(contents) = std::fs::read(path) {
|
if let Ok(contents) = std::fs::read(path) {
|
||||||
parse_module(working_set, Some(filename), &contents, is_debug, call.head)
|
parse_module(working_set, Some(filename), &contents, is_debug, call.head)
|
||||||
} else {
|
} else {
|
||||||
|
@ -55,7 +55,7 @@ fn eval_source2(
|
|||||||
) -> Result<PipelineData, ShellError> {
|
) -> Result<PipelineData, ShellError> {
|
||||||
let (mut block, delta) = {
|
let (mut block, delta) = {
|
||||||
let mut working_set = StateWorkingSet::new(engine_state);
|
let mut working_set = StateWorkingSet::new(engine_state);
|
||||||
let (output, err) = parse(
|
let output = parse(
|
||||||
&mut working_set,
|
&mut working_set,
|
||||||
Some(fname), // format!("entry #{}", entry_num)
|
Some(fname), // format!("entry #{}", entry_num)
|
||||||
source,
|
source,
|
||||||
@ -63,7 +63,7 @@ fn eval_source2(
|
|||||||
&[],
|
&[],
|
||||||
);
|
);
|
||||||
|
|
||||||
if let Some(err) = err {
|
if let Some(err) = working_set.parse_errors.first() {
|
||||||
return Err(ShellError::IOError(err.to_string()));
|
return Err(ShellError::IOError(err.to_string()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
use crate::ParseError;
|
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
ast::{Expr, Expression},
|
ast::{Expr, Expression},
|
||||||
engine::StateWorkingSet,
|
engine::StateWorkingSet,
|
||||||
Span, Value,
|
ParseError, Span, Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Evaluate a constant value at parse time
|
/// Evaluate a constant value at parse time
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
use crate::ParseError;
|
use nu_protocol::{ParseError, Span};
|
||||||
use nu_protocol::Span;
|
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||||
pub enum TokenContents {
|
pub enum TokenContents {
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
mod deparse;
|
mod deparse;
|
||||||
mod errors;
|
|
||||||
mod eval;
|
mod eval;
|
||||||
mod flatten;
|
mod flatten;
|
||||||
mod known_external;
|
mod known_external;
|
||||||
@ -11,7 +10,6 @@ mod parser;
|
|||||||
mod type_check;
|
mod type_check;
|
||||||
|
|
||||||
pub use deparse::{escape_for_script_arg, escape_quote_string};
|
pub use deparse::{escape_for_script_arg, escape_quote_string};
|
||||||
pub use errors::ParseError;
|
|
||||||
pub use flatten::{
|
pub use flatten::{
|
||||||
flatten_block, flatten_expression, flatten_pipeline, flatten_pipeline_element, FlatShape,
|
flatten_block, flatten_expression, flatten_pipeline, flatten_pipeline_element, FlatShape,
|
||||||
};
|
};
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
/// Lite parsing converts a flat stream of tokens from the lexer to a syntax element structure that
|
/// Lite parsing converts a flat stream of tokens from the lexer to a syntax element structure that
|
||||||
/// can be parsed.
|
/// can be parsed.
|
||||||
use crate::{ParseError, Token, TokenContents};
|
use crate::{Token, TokenContents};
|
||||||
|
|
||||||
use nu_protocol::{ast::Redirection, Span};
|
use nu_protocol::{ast::Redirection, ParseError, Span};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct LiteCommand {
|
pub struct LiteCommand {
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,13 +1,13 @@
|
|||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
ast::{Expr, Expression, MatchPattern, Pattern},
|
ast::{Expr, Expression, MatchPattern, Pattern},
|
||||||
engine::StateWorkingSet,
|
engine::StateWorkingSet,
|
||||||
Span, SyntaxShape, Type, VarId,
|
ParseError, Span, SyntaxShape, Type, VarId,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
lex, lite_parse,
|
lex, lite_parse,
|
||||||
parser::{is_variable, parse_value},
|
parser::{is_variable, parse_value},
|
||||||
LiteElement, ParseError,
|
LiteElement,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn garbage(span: Span) -> MatchPattern {
|
pub fn garbage(span: Span) -> MatchPattern {
|
||||||
@ -17,29 +17,20 @@ pub fn garbage(span: Span) -> MatchPattern {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_match_pattern(
|
pub fn parse_match_pattern(working_set: &mut StateWorkingSet, span: Span) -> Expression {
|
||||||
working_set: &mut StateWorkingSet,
|
|
||||||
span: Span,
|
|
||||||
) -> (Expression, Option<ParseError>) {
|
|
||||||
working_set.enter_scope();
|
working_set.enter_scope();
|
||||||
let (output, err) = parse_pattern(working_set, span);
|
let output = parse_pattern(working_set, span);
|
||||||
working_set.exit_scope();
|
working_set.exit_scope();
|
||||||
|
|
||||||
(
|
Expression {
|
||||||
Expression {
|
expr: Expr::MatchPattern(Box::new(output)),
|
||||||
expr: Expr::MatchPattern(Box::new(output)),
|
span,
|
||||||
span,
|
ty: Type::Any,
|
||||||
ty: Type::Any,
|
custom_completion: None,
|
||||||
custom_completion: None,
|
}
|
||||||
},
|
|
||||||
err,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_pattern(
|
pub fn parse_pattern(working_set: &mut StateWorkingSet, span: Span) -> MatchPattern {
|
||||||
working_set: &mut StateWorkingSet,
|
|
||||||
span: Span,
|
|
||||||
) -> (MatchPattern, Option<ParseError>) {
|
|
||||||
let bytes = working_set.get_span_contents(span);
|
let bytes = working_set.get_span_contents(span);
|
||||||
|
|
||||||
if bytes.starts_with(b"$") {
|
if bytes.starts_with(b"$") {
|
||||||
@ -52,23 +43,18 @@ pub fn parse_pattern(
|
|||||||
// List pattern
|
// List pattern
|
||||||
parse_list_pattern(working_set, span)
|
parse_list_pattern(working_set, span)
|
||||||
} else if bytes == b"_" {
|
} else if bytes == b"_" {
|
||||||
(
|
MatchPattern {
|
||||||
MatchPattern {
|
pattern: Pattern::IgnoreValue,
|
||||||
pattern: Pattern::IgnoreValue,
|
span,
|
||||||
span,
|
}
|
||||||
},
|
|
||||||
None,
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
// Literal value
|
// Literal value
|
||||||
let (value, error) = parse_value(working_set, span, &SyntaxShape::Any, &[]);
|
let value = parse_value(working_set, span, &SyntaxShape::Any, &[]);
|
||||||
(
|
|
||||||
MatchPattern {
|
MatchPattern {
|
||||||
pattern: Pattern::Value(value),
|
pattern: Pattern::Value(value),
|
||||||
span,
|
span,
|
||||||
},
|
}
|
||||||
error,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,34 +74,21 @@ fn parse_variable_pattern_helper(working_set: &mut StateWorkingSet, span: Span)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_variable_pattern(
|
pub fn parse_variable_pattern(working_set: &mut StateWorkingSet, span: Span) -> MatchPattern {
|
||||||
working_set: &mut StateWorkingSet,
|
|
||||||
span: Span,
|
|
||||||
) -> (MatchPattern, Option<ParseError>) {
|
|
||||||
if let Some(var_id) = parse_variable_pattern_helper(working_set, span) {
|
if let Some(var_id) = parse_variable_pattern_helper(working_set, span) {
|
||||||
(
|
MatchPattern {
|
||||||
MatchPattern {
|
pattern: Pattern::Variable(var_id),
|
||||||
pattern: Pattern::Variable(var_id),
|
span,
|
||||||
span,
|
}
|
||||||
},
|
|
||||||
None,
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
(
|
working_set.error(ParseError::Expected("valid variable name".into(), span));
|
||||||
garbage(span),
|
garbage(span)
|
||||||
Some(ParseError::Expected("valid variable name".into(), span)),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_list_pattern(
|
pub fn parse_list_pattern(working_set: &mut StateWorkingSet, span: Span) -> MatchPattern {
|
||||||
working_set: &mut StateWorkingSet,
|
|
||||||
span: Span,
|
|
||||||
) -> (MatchPattern, Option<ParseError>) {
|
|
||||||
let bytes = working_set.get_span_contents(span);
|
let bytes = working_set.get_span_contents(span);
|
||||||
|
|
||||||
let mut error = None;
|
|
||||||
|
|
||||||
let mut start = span.start;
|
let mut start = span.start;
|
||||||
let mut end = span.end;
|
let mut end = span.end;
|
||||||
|
|
||||||
@ -125,17 +98,21 @@ pub fn parse_list_pattern(
|
|||||||
if bytes.ends_with(b"]") {
|
if bytes.ends_with(b"]") {
|
||||||
end -= 1;
|
end -= 1;
|
||||||
} else {
|
} else {
|
||||||
error = error.or_else(|| Some(ParseError::Unclosed("]".into(), Span::new(end, end))));
|
working_set.error(ParseError::Unclosed("]".into(), Span::new(end, end)));
|
||||||
}
|
}
|
||||||
|
|
||||||
let inner_span = Span::new(start, end);
|
let inner_span = Span::new(start, end);
|
||||||
let source = working_set.get_span_contents(inner_span);
|
let source = working_set.get_span_contents(inner_span);
|
||||||
|
|
||||||
let (output, err) = lex(source, inner_span.start, &[b'\n', b'\r', b','], &[], true);
|
let (output, err) = lex(source, inner_span.start, &[b'\n', b'\r', b','], &[], true);
|
||||||
error = error.or(err);
|
if let Some(err) = err {
|
||||||
|
working_set.error(err);
|
||||||
|
}
|
||||||
|
|
||||||
let (output, err) = lite_parse(&output);
|
let (output, err) = lite_parse(&output);
|
||||||
error = error.or(err);
|
if let Some(err) = err {
|
||||||
|
working_set.error(err);
|
||||||
|
}
|
||||||
|
|
||||||
let mut args = vec![];
|
let mut args = vec![];
|
||||||
|
|
||||||
@ -167,14 +144,13 @@ pub fn parse_list_pattern(
|
|||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
args.push(garbage(command.parts[spans_idx]));
|
args.push(garbage(command.parts[spans_idx]));
|
||||||
error = error.or(Some(ParseError::Expected(
|
working_set.error(ParseError::Expected(
|
||||||
"valid variable name".into(),
|
"valid variable name".into(),
|
||||||
command.parts[spans_idx],
|
command.parts[spans_idx],
|
||||||
)));
|
));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let (arg, err) = parse_pattern(working_set, command.parts[spans_idx]);
|
let arg = parse_pattern(working_set, command.parts[spans_idx]);
|
||||||
error = error.or(err);
|
|
||||||
|
|
||||||
args.push(arg);
|
args.push(arg);
|
||||||
};
|
};
|
||||||
@ -185,47 +161,41 @@ pub fn parse_list_pattern(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
(
|
MatchPattern {
|
||||||
MatchPattern {
|
pattern: Pattern::List(args),
|
||||||
pattern: Pattern::List(args),
|
span,
|
||||||
span,
|
}
|
||||||
},
|
|
||||||
error,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_record_pattern(
|
pub fn parse_record_pattern(working_set: &mut StateWorkingSet, span: Span) -> MatchPattern {
|
||||||
working_set: &mut StateWorkingSet,
|
let mut bytes = working_set.get_span_contents(span);
|
||||||
span: Span,
|
|
||||||
) -> (MatchPattern, Option<ParseError>) {
|
|
||||||
let bytes = working_set.get_span_contents(span);
|
|
||||||
|
|
||||||
let mut error = None;
|
|
||||||
let mut start = span.start;
|
let mut start = span.start;
|
||||||
let mut end = span.end;
|
let mut end = span.end;
|
||||||
|
|
||||||
if bytes.starts_with(b"{") {
|
if bytes.starts_with(b"{") {
|
||||||
start += 1;
|
start += 1;
|
||||||
} else {
|
} else {
|
||||||
error = error.or_else(|| {
|
working_set.error(ParseError::Expected(
|
||||||
Some(ParseError::Expected(
|
"{".into(),
|
||||||
"{".into(),
|
Span::new(start, start + 1),
|
||||||
Span::new(start, start + 1),
|
));
|
||||||
))
|
bytes = working_set.get_span_contents(span);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if bytes.ends_with(b"}") {
|
if bytes.ends_with(b"}") {
|
||||||
end -= 1;
|
end -= 1;
|
||||||
} else {
|
} else {
|
||||||
error = error.or_else(|| Some(ParseError::Unclosed("}".into(), Span::new(end, end))));
|
working_set.error(ParseError::Unclosed("}".into(), Span::new(end, end)));
|
||||||
}
|
}
|
||||||
|
|
||||||
let inner_span = Span::new(start, end);
|
let inner_span = Span::new(start, end);
|
||||||
let source = working_set.get_span_contents(inner_span);
|
let source = working_set.get_span_contents(inner_span);
|
||||||
|
|
||||||
let (tokens, err) = lex(source, start, &[b'\n', b'\r', b','], &[b':'], true);
|
let (tokens, err) = lex(source, start, &[b'\n', b'\r', b','], &[b':'], true);
|
||||||
error = error.or(err);
|
if let Some(err) = err {
|
||||||
|
working_set.error(err);
|
||||||
|
}
|
||||||
|
|
||||||
let mut output = vec![];
|
let mut output = vec![];
|
||||||
let mut idx = 0;
|
let mut idx = 0;
|
||||||
@ -236,8 +206,7 @@ pub fn parse_record_pattern(
|
|||||||
// If this is a variable, treat it as both the name of the field and the pattern
|
// If this is a variable, treat it as both the name of the field and the pattern
|
||||||
let field = String::from_utf8_lossy(&bytes[1..]).to_string();
|
let field = String::from_utf8_lossy(&bytes[1..]).to_string();
|
||||||
|
|
||||||
let (pattern, err) = parse_variable_pattern(working_set, tokens[idx].span);
|
let pattern = parse_variable_pattern(working_set, tokens[idx].span);
|
||||||
error = error.or(err);
|
|
||||||
|
|
||||||
(field, pattern)
|
(field, pattern)
|
||||||
} else {
|
} else {
|
||||||
@ -245,22 +214,17 @@ pub fn parse_record_pattern(
|
|||||||
|
|
||||||
idx += 1;
|
idx += 1;
|
||||||
if idx == tokens.len() {
|
if idx == tokens.len() {
|
||||||
return (
|
working_set.error(ParseError::Expected("record".into(), span));
|
||||||
garbage(span),
|
return garbage(span);
|
||||||
Some(ParseError::Expected("record".into(), span)),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
let colon = working_set.get_span_contents(tokens[idx].span);
|
let colon = working_set.get_span_contents(tokens[idx].span);
|
||||||
idx += 1;
|
idx += 1;
|
||||||
if idx == tokens.len() || colon != b":" {
|
if idx == tokens.len() || colon != b":" {
|
||||||
//FIXME: need better error
|
//FIXME: need better error
|
||||||
return (
|
working_set.error(ParseError::Expected("record".into(), span));
|
||||||
garbage(span),
|
return garbage(span);
|
||||||
Some(ParseError::Expected("record".into(), span)),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
let (pattern, err) = parse_pattern(working_set, tokens[idx].span);
|
let pattern = parse_pattern(working_set, tokens[idx].span);
|
||||||
error = error.or(err);
|
|
||||||
|
|
||||||
(field, pattern)
|
(field, pattern)
|
||||||
};
|
};
|
||||||
@ -269,11 +233,8 @@ pub fn parse_record_pattern(
|
|||||||
output.push((field, pattern));
|
output.push((field, pattern));
|
||||||
}
|
}
|
||||||
|
|
||||||
(
|
MatchPattern {
|
||||||
MatchPattern {
|
pattern: Pattern::Record(output),
|
||||||
pattern: Pattern::Record(output),
|
span,
|
||||||
span,
|
}
|
||||||
},
|
|
||||||
error,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,8 +1,7 @@
|
|||||||
use crate::ParseError;
|
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
ast::{Bits, Boolean, Comparison, Expr, Expression, Math, Operator},
|
ast::{Bits, Boolean, Comparison, Expr, Expression, Math, Operator},
|
||||||
engine::StateWorkingSet,
|
engine::StateWorkingSet,
|
||||||
Type,
|
ParseError, Type,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn type_compatible(lhs: &Type, rhs: &Type) -> bool {
|
pub fn type_compatible(lhs: &Type, rhs: &Type) -> bool {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use nu_parser::{lex, lex_signature, ParseError, Token, TokenContents};
|
use nu_parser::{lex, lex_signature, Token, TokenContents};
|
||||||
use nu_protocol::Span;
|
use nu_protocol::{ParseError, Span};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn lex_basic() {
|
fn lex_basic() {
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
use nu_parser::ParseError;
|
|
||||||
use nu_parser::*;
|
use nu_parser::*;
|
||||||
use nu_protocol::ast::{Call, PathMember};
|
use nu_protocol::ast::{Call, PathMember};
|
||||||
use nu_protocol::Span;
|
use nu_protocol::Span;
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
ast::{Expr, Expression, PipelineElement},
|
ast::{Expr, Expression, PipelineElement},
|
||||||
engine::{Command, EngineState, Stack, StateWorkingSet},
|
engine::{Command, EngineState, Stack, StateWorkingSet},
|
||||||
PipelineData, ShellError, Signature, SyntaxShape,
|
ParseError, PipelineData, ShellError, Signature, SyntaxShape,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@ -53,7 +52,9 @@ fn test_int(
|
|||||||
let engine_state = EngineState::new();
|
let engine_state = EngineState::new();
|
||||||
let mut working_set = StateWorkingSet::new(&engine_state);
|
let mut working_set = StateWorkingSet::new(&engine_state);
|
||||||
|
|
||||||
let (block, err) = parse(&mut working_set, None, test, true, &[]);
|
let block = parse(&mut working_set, None, test, true, &[]);
|
||||||
|
|
||||||
|
let err = working_set.parse_errors.first();
|
||||||
|
|
||||||
if let Some(err_pat) = expected_err {
|
if let Some(err_pat) = expected_err {
|
||||||
if let Some(parse_err) = err {
|
if let Some(parse_err) = err {
|
||||||
@ -265,9 +266,9 @@ fn test_parse_any() {
|
|||||||
let engine_state = EngineState::new();
|
let engine_state = EngineState::new();
|
||||||
let mut working_set = StateWorkingSet::new(&engine_state);
|
let mut working_set = StateWorkingSet::new(&engine_state);
|
||||||
|
|
||||||
let (block, err) = parse(&mut working_set, None, test, true, &[]);
|
let block = parse(&mut working_set, None, test, true, &[]);
|
||||||
|
|
||||||
match (block, err) {
|
match (block, working_set.parse_errors.first()) {
|
||||||
(_, Some(e)) => {
|
(_, Some(e)) => {
|
||||||
println!("test: {test:?}, error: {e:#?}");
|
println!("test: {test:?}, error: {e:#?}");
|
||||||
}
|
}
|
||||||
@ -281,9 +282,9 @@ pub fn parse_int() {
|
|||||||
let engine_state = EngineState::new();
|
let engine_state = EngineState::new();
|
||||||
let mut working_set = StateWorkingSet::new(&engine_state);
|
let mut working_set = StateWorkingSet::new(&engine_state);
|
||||||
|
|
||||||
let (block, err) = parse(&mut working_set, None, b"3", true, &[]);
|
let block = parse(&mut working_set, None, b"3", true, &[]);
|
||||||
|
|
||||||
assert!(err.is_none());
|
assert!(working_set.parse_errors.is_empty());
|
||||||
assert_eq!(block.len(), 1);
|
assert_eq!(block.len(), 1);
|
||||||
let expressions = &block[0];
|
let expressions = &block[0];
|
||||||
assert_eq!(expressions.len(), 1);
|
assert_eq!(expressions.len(), 1);
|
||||||
@ -304,9 +305,9 @@ pub fn parse_int_with_underscores() {
|
|||||||
let engine_state = EngineState::new();
|
let engine_state = EngineState::new();
|
||||||
let mut working_set = StateWorkingSet::new(&engine_state);
|
let mut working_set = StateWorkingSet::new(&engine_state);
|
||||||
|
|
||||||
let (block, err) = parse(&mut working_set, None, b"420_69_2023", true, &[]);
|
let block = parse(&mut working_set, None, b"420_69_2023", true, &[]);
|
||||||
|
|
||||||
assert!(err.is_none());
|
assert!(working_set.parse_errors.is_empty());
|
||||||
assert_eq!(block.len(), 1);
|
assert_eq!(block.len(), 1);
|
||||||
let expressions = &block[0];
|
let expressions = &block[0];
|
||||||
assert_eq!(expressions.len(), 1);
|
assert_eq!(expressions.len(), 1);
|
||||||
@ -334,9 +335,9 @@ pub fn parse_cell_path() {
|
|||||||
false,
|
false,
|
||||||
);
|
);
|
||||||
|
|
||||||
let (block, err) = parse(&mut working_set, None, b"$foo.bar.baz", true, &[]);
|
let block = parse(&mut working_set, None, b"$foo.bar.baz", true, &[]);
|
||||||
|
|
||||||
assert!(err.is_none());
|
assert!(working_set.parse_errors.is_empty());
|
||||||
assert_eq!(block.len(), 1);
|
assert_eq!(block.len(), 1);
|
||||||
let expressions = &block[0];
|
let expressions = &block[0];
|
||||||
assert_eq!(expressions.len(), 1);
|
assert_eq!(expressions.len(), 1);
|
||||||
@ -388,12 +389,9 @@ pub fn parse_cell_path_optional() {
|
|||||||
false,
|
false,
|
||||||
);
|
);
|
||||||
|
|
||||||
let (block, err) = parse(&mut working_set, None, b"$foo.bar?.baz", true, &[]);
|
let block = parse(&mut working_set, None, b"$foo.bar?.baz", true, &[]);
|
||||||
|
|
||||||
if let Some(err) = err {
|
assert!(working_set.parse_errors.is_empty());
|
||||||
dbg!(err);
|
|
||||||
panic!();
|
|
||||||
}
|
|
||||||
|
|
||||||
assert_eq!(block.len(), 1);
|
assert_eq!(block.len(), 1);
|
||||||
let expressions = &block[0];
|
let expressions = &block[0];
|
||||||
@ -439,9 +437,9 @@ pub fn parse_binary_with_hex_format() {
|
|||||||
let engine_state = EngineState::new();
|
let engine_state = EngineState::new();
|
||||||
let mut working_set = StateWorkingSet::new(&engine_state);
|
let mut working_set = StateWorkingSet::new(&engine_state);
|
||||||
|
|
||||||
let (block, err) = parse(&mut working_set, None, b"0x[13]", true, &[]);
|
let block = parse(&mut working_set, None, b"0x[13]", true, &[]);
|
||||||
|
|
||||||
assert!(err.is_none());
|
assert!(working_set.parse_errors.is_empty());
|
||||||
assert_eq!(block.len(), 1);
|
assert_eq!(block.len(), 1);
|
||||||
let expressions = &block[0];
|
let expressions = &block[0];
|
||||||
assert_eq!(expressions.len(), 1);
|
assert_eq!(expressions.len(), 1);
|
||||||
@ -457,9 +455,9 @@ pub fn parse_binary_with_incomplete_hex_format() {
|
|||||||
let engine_state = EngineState::new();
|
let engine_state = EngineState::new();
|
||||||
let mut working_set = StateWorkingSet::new(&engine_state);
|
let mut working_set = StateWorkingSet::new(&engine_state);
|
||||||
|
|
||||||
let (block, err) = parse(&mut working_set, None, b"0x[3]", true, &[]);
|
let block = parse(&mut working_set, None, b"0x[3]", true, &[]);
|
||||||
|
|
||||||
assert!(err.is_none());
|
assert!(working_set.parse_errors.is_empty());
|
||||||
assert_eq!(block.len(), 1);
|
assert_eq!(block.len(), 1);
|
||||||
let expressions = &block[0];
|
let expressions = &block[0];
|
||||||
assert_eq!(expressions.len(), 1);
|
assert_eq!(expressions.len(), 1);
|
||||||
@ -475,9 +473,9 @@ pub fn parse_binary_with_binary_format() {
|
|||||||
let engine_state = EngineState::new();
|
let engine_state = EngineState::new();
|
||||||
let mut working_set = StateWorkingSet::new(&engine_state);
|
let mut working_set = StateWorkingSet::new(&engine_state);
|
||||||
|
|
||||||
let (block, err) = parse(&mut working_set, None, b"0b[1010 1000]", true, &[]);
|
let block = parse(&mut working_set, None, b"0b[1010 1000]", true, &[]);
|
||||||
|
|
||||||
assert!(err.is_none());
|
assert!(working_set.parse_errors.is_empty());
|
||||||
assert_eq!(block.len(), 1);
|
assert_eq!(block.len(), 1);
|
||||||
let expressions = &block[0];
|
let expressions = &block[0];
|
||||||
assert_eq!(expressions.len(), 1);
|
assert_eq!(expressions.len(), 1);
|
||||||
@ -493,9 +491,9 @@ pub fn parse_binary_with_incomplete_binary_format() {
|
|||||||
let engine_state = EngineState::new();
|
let engine_state = EngineState::new();
|
||||||
let mut working_set = StateWorkingSet::new(&engine_state);
|
let mut working_set = StateWorkingSet::new(&engine_state);
|
||||||
|
|
||||||
let (block, err) = parse(&mut working_set, None, b"0b[10]", true, &[]);
|
let block = parse(&mut working_set, None, b"0b[10]", true, &[]);
|
||||||
|
|
||||||
assert!(err.is_none());
|
assert!(working_set.parse_errors.is_empty());
|
||||||
assert_eq!(block.len(), 1);
|
assert_eq!(block.len(), 1);
|
||||||
let expressions = &block[0];
|
let expressions = &block[0];
|
||||||
assert_eq!(expressions.len(), 1);
|
assert_eq!(expressions.len(), 1);
|
||||||
@ -511,9 +509,9 @@ pub fn parse_binary_with_octal_format() {
|
|||||||
let engine_state = EngineState::new();
|
let engine_state = EngineState::new();
|
||||||
let mut working_set = StateWorkingSet::new(&engine_state);
|
let mut working_set = StateWorkingSet::new(&engine_state);
|
||||||
|
|
||||||
let (block, err) = parse(&mut working_set, None, b"0o[250]", true, &[]);
|
let block = parse(&mut working_set, None, b"0o[250]", true, &[]);
|
||||||
|
|
||||||
assert!(err.is_none());
|
assert!(working_set.parse_errors.is_empty());
|
||||||
assert_eq!(block.len(), 1);
|
assert_eq!(block.len(), 1);
|
||||||
let expressions = &block[0];
|
let expressions = &block[0];
|
||||||
assert_eq!(expressions.len(), 1);
|
assert_eq!(expressions.len(), 1);
|
||||||
@ -529,9 +527,9 @@ pub fn parse_binary_with_incomplete_octal_format() {
|
|||||||
let engine_state = EngineState::new();
|
let engine_state = EngineState::new();
|
||||||
let mut working_set = StateWorkingSet::new(&engine_state);
|
let mut working_set = StateWorkingSet::new(&engine_state);
|
||||||
|
|
||||||
let (block, err) = parse(&mut working_set, None, b"0o[2]", true, &[]);
|
let block = parse(&mut working_set, None, b"0o[2]", true, &[]);
|
||||||
|
|
||||||
assert!(err.is_none());
|
assert!(working_set.parse_errors.is_empty());
|
||||||
assert_eq!(block.len(), 1);
|
assert_eq!(block.len(), 1);
|
||||||
let expressions = &block[0];
|
let expressions = &block[0];
|
||||||
assert_eq!(expressions.len(), 1);
|
assert_eq!(expressions.len(), 1);
|
||||||
@ -547,9 +545,9 @@ pub fn parse_binary_with_invalid_octal_format() {
|
|||||||
let engine_state = EngineState::new();
|
let engine_state = EngineState::new();
|
||||||
let mut working_set = StateWorkingSet::new(&engine_state);
|
let mut working_set = StateWorkingSet::new(&engine_state);
|
||||||
|
|
||||||
let (block, err) = parse(&mut working_set, None, b"0b[90]", true, &[]);
|
let block = parse(&mut working_set, None, b"0b[90]", true, &[]);
|
||||||
|
|
||||||
assert!(err.is_none());
|
assert!(working_set.parse_errors.is_empty());
|
||||||
assert_eq!(block.len(), 1);
|
assert_eq!(block.len(), 1);
|
||||||
let expressions = &block[0];
|
let expressions = &block[0];
|
||||||
assert_eq!(expressions.len(), 1);
|
assert_eq!(expressions.len(), 1);
|
||||||
@ -567,9 +565,9 @@ pub fn parse_binary_with_multi_byte_char() {
|
|||||||
|
|
||||||
// found using fuzzing, Rust can panic if you slice into this string
|
// found using fuzzing, Rust can panic if you slice into this string
|
||||||
let contents = b"0x[\xEF\xBF\xBD]";
|
let contents = b"0x[\xEF\xBF\xBD]";
|
||||||
let (block, err) = parse(&mut working_set, None, contents, true, &[]);
|
let block = parse(&mut working_set, None, contents, true, &[]);
|
||||||
|
|
||||||
assert!(err.is_none());
|
assert!(working_set.parse_errors.is_empty());
|
||||||
assert_eq!(block.len(), 1);
|
assert_eq!(block.len(), 1);
|
||||||
let expressions = &block[0];
|
let expressions = &block[0];
|
||||||
assert_eq!(expressions.len(), 1);
|
assert_eq!(expressions.len(), 1);
|
||||||
@ -588,9 +586,9 @@ pub fn parse_call() {
|
|||||||
let sig = Signature::build("foo").named("--jazz", SyntaxShape::Int, "jazz!!", Some('j'));
|
let sig = Signature::build("foo").named("--jazz", SyntaxShape::Int, "jazz!!", Some('j'));
|
||||||
working_set.add_decl(sig.predeclare());
|
working_set.add_decl(sig.predeclare());
|
||||||
|
|
||||||
let (block, err) = parse(&mut working_set, None, b"foo", true, &[]);
|
let block = parse(&mut working_set, None, b"foo", true, &[]);
|
||||||
|
|
||||||
assert!(err.is_none());
|
assert!(working_set.parse_errors.is_empty());
|
||||||
assert_eq!(block.len(), 1);
|
assert_eq!(block.len(), 1);
|
||||||
|
|
||||||
let expressions = &block[0];
|
let expressions = &block[0];
|
||||||
@ -616,8 +614,11 @@ pub fn parse_call_missing_flag_arg() {
|
|||||||
let sig = Signature::build("foo").named("jazz", SyntaxShape::Int, "jazz!!", Some('j'));
|
let sig = Signature::build("foo").named("jazz", SyntaxShape::Int, "jazz!!", Some('j'));
|
||||||
working_set.add_decl(sig.predeclare());
|
working_set.add_decl(sig.predeclare());
|
||||||
|
|
||||||
let (_, err) = parse(&mut working_set, None, b"foo --jazz", true, &[]);
|
parse(&mut working_set, None, b"foo --jazz", true, &[]);
|
||||||
assert!(matches!(err, Some(ParseError::MissingFlagParam(..))));
|
assert!(matches!(
|
||||||
|
working_set.parse_errors.first(),
|
||||||
|
Some(ParseError::MissingFlagParam(..))
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -628,8 +629,11 @@ pub fn parse_call_missing_short_flag_arg() {
|
|||||||
let sig = Signature::build("foo").named("--jazz", SyntaxShape::Int, "jazz!!", Some('j'));
|
let sig = Signature::build("foo").named("--jazz", SyntaxShape::Int, "jazz!!", Some('j'));
|
||||||
working_set.add_decl(sig.predeclare());
|
working_set.add_decl(sig.predeclare());
|
||||||
|
|
||||||
let (_, err) = parse(&mut working_set, None, b"foo -j", true, &[]);
|
parse(&mut working_set, None, b"foo -j", true, &[]);
|
||||||
assert!(matches!(err, Some(ParseError::MissingFlagParam(..))));
|
assert!(matches!(
|
||||||
|
working_set.parse_errors.first(),
|
||||||
|
Some(ParseError::MissingFlagParam(..))
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -641,9 +645,9 @@ pub fn parse_call_too_many_shortflag_args() {
|
|||||||
.named("--jazz", SyntaxShape::Int, "jazz!!", Some('j'))
|
.named("--jazz", SyntaxShape::Int, "jazz!!", Some('j'))
|
||||||
.named("--math", SyntaxShape::Int, "math!!", Some('m'));
|
.named("--math", SyntaxShape::Int, "math!!", Some('m'));
|
||||||
working_set.add_decl(sig.predeclare());
|
working_set.add_decl(sig.predeclare());
|
||||||
let (_, err) = parse(&mut working_set, None, b"foo -mj", true, &[]);
|
parse(&mut working_set, None, b"foo -mj", true, &[]);
|
||||||
assert!(matches!(
|
assert!(matches!(
|
||||||
err,
|
working_set.parse_errors.first(),
|
||||||
Some(ParseError::ShortFlagBatchCantTakeArg(..))
|
Some(ParseError::ShortFlagBatchCantTakeArg(..))
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@ -655,8 +659,11 @@ pub fn parse_call_unknown_shorthand() {
|
|||||||
|
|
||||||
let sig = Signature::build("foo").switch("--jazz", "jazz!!", Some('j'));
|
let sig = Signature::build("foo").switch("--jazz", "jazz!!", Some('j'));
|
||||||
working_set.add_decl(sig.predeclare());
|
working_set.add_decl(sig.predeclare());
|
||||||
let (_, err) = parse(&mut working_set, None, b"foo -mj", true, &[]);
|
parse(&mut working_set, None, b"foo -mj", true, &[]);
|
||||||
assert!(matches!(err, Some(ParseError::UnknownFlag(..))));
|
assert!(matches!(
|
||||||
|
working_set.parse_errors.first(),
|
||||||
|
Some(ParseError::UnknownFlag(..))
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -666,8 +673,11 @@ pub fn parse_call_extra_positional() {
|
|||||||
|
|
||||||
let sig = Signature::build("foo").switch("--jazz", "jazz!!", Some('j'));
|
let sig = Signature::build("foo").switch("--jazz", "jazz!!", Some('j'));
|
||||||
working_set.add_decl(sig.predeclare());
|
working_set.add_decl(sig.predeclare());
|
||||||
let (_, err) = parse(&mut working_set, None, b"foo -j 100", true, &[]);
|
parse(&mut working_set, None, b"foo -j 100", true, &[]);
|
||||||
assert!(matches!(err, Some(ParseError::ExtraPositional(..))));
|
assert!(matches!(
|
||||||
|
working_set.parse_errors.first(),
|
||||||
|
Some(ParseError::ExtraPositional(..))
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -677,8 +687,11 @@ pub fn parse_call_missing_req_positional() {
|
|||||||
|
|
||||||
let sig = Signature::build("foo").required("jazz", SyntaxShape::Int, "jazz!!");
|
let sig = Signature::build("foo").required("jazz", SyntaxShape::Int, "jazz!!");
|
||||||
working_set.add_decl(sig.predeclare());
|
working_set.add_decl(sig.predeclare());
|
||||||
let (_, err) = parse(&mut working_set, None, b"foo", true, &[]);
|
parse(&mut working_set, None, b"foo", true, &[]);
|
||||||
assert!(matches!(err, Some(ParseError::MissingPositional(..))));
|
assert!(matches!(
|
||||||
|
working_set.parse_errors.first(),
|
||||||
|
Some(ParseError::MissingPositional(..))
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -688,17 +701,20 @@ pub fn parse_call_missing_req_flag() {
|
|||||||
|
|
||||||
let sig = Signature::build("foo").required_named("--jazz", SyntaxShape::Int, "jazz!!", None);
|
let sig = Signature::build("foo").required_named("--jazz", SyntaxShape::Int, "jazz!!", None);
|
||||||
working_set.add_decl(sig.predeclare());
|
working_set.add_decl(sig.predeclare());
|
||||||
let (_, err) = parse(&mut working_set, None, b"foo", true, &[]);
|
parse(&mut working_set, None, b"foo", true, &[]);
|
||||||
assert!(matches!(err, Some(ParseError::MissingRequiredFlag(..))));
|
assert!(matches!(
|
||||||
|
working_set.parse_errors.first(),
|
||||||
|
Some(ParseError::MissingRequiredFlag(..))
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_nothing_comparison_eq() {
|
fn test_nothing_comparison_eq() {
|
||||||
let engine_state = EngineState::new();
|
let engine_state = EngineState::new();
|
||||||
let mut working_set = StateWorkingSet::new(&engine_state);
|
let mut working_set = StateWorkingSet::new(&engine_state);
|
||||||
let (block, err) = parse(&mut working_set, None, b"2 == null", true, &[]);
|
let block = parse(&mut working_set, None, b"2 == null", true, &[]);
|
||||||
|
|
||||||
assert!(err.is_none());
|
assert!(working_set.parse_errors.is_empty());
|
||||||
assert_eq!(block.len(), 1);
|
assert_eq!(block.len(), 1);
|
||||||
|
|
||||||
let expressions = &block[0];
|
let expressions = &block[0];
|
||||||
@ -719,9 +735,9 @@ fn test_nothing_comparison_eq() {
|
|||||||
fn test_nothing_comparison_neq() {
|
fn test_nothing_comparison_neq() {
|
||||||
let engine_state = EngineState::new();
|
let engine_state = EngineState::new();
|
||||||
let mut working_set = StateWorkingSet::new(&engine_state);
|
let mut working_set = StateWorkingSet::new(&engine_state);
|
||||||
let (block, err) = parse(&mut working_set, None, b"2 != null", true, &[]);
|
let block = parse(&mut working_set, None, b"2 != null", true, &[]);
|
||||||
|
|
||||||
assert!(err.is_none());
|
assert!(working_set.parse_errors.is_empty());
|
||||||
assert_eq!(block.len(), 1);
|
assert_eq!(block.len(), 1);
|
||||||
|
|
||||||
let expressions = &block[0];
|
let expressions = &block[0];
|
||||||
@ -746,9 +762,9 @@ mod string {
|
|||||||
let engine_state = EngineState::new();
|
let engine_state = EngineState::new();
|
||||||
let mut working_set = StateWorkingSet::new(&engine_state);
|
let mut working_set = StateWorkingSet::new(&engine_state);
|
||||||
|
|
||||||
let (block, err) = parse(&mut working_set, None, b"\"hello nushell\"", true, &[]);
|
let block = parse(&mut working_set, None, b"\"hello nushell\"", true, &[]);
|
||||||
|
|
||||||
assert!(err.is_none());
|
assert!(working_set.parse_errors.is_empty());
|
||||||
assert_eq!(block.len(), 1);
|
assert_eq!(block.len(), 1);
|
||||||
let expressions = &block[0];
|
let expressions = &block[0];
|
||||||
assert_eq!(expressions.len(), 1);
|
assert_eq!(expressions.len(), 1);
|
||||||
@ -769,9 +785,9 @@ mod string {
|
|||||||
let engine_state = EngineState::new();
|
let engine_state = EngineState::new();
|
||||||
let mut working_set = StateWorkingSet::new(&engine_state);
|
let mut working_set = StateWorkingSet::new(&engine_state);
|
||||||
|
|
||||||
let (block, err) = parse(&mut working_set, None, b"$\"hello (39 + 3)\"", true, &[]);
|
let block = parse(&mut working_set, None, b"$\"hello (39 + 3)\"", true, &[]);
|
||||||
|
|
||||||
assert!(err.is_none());
|
assert!(working_set.parse_errors.is_empty());
|
||||||
assert_eq!(block.len(), 1);
|
assert_eq!(block.len(), 1);
|
||||||
|
|
||||||
let expressions = &block[0];
|
let expressions = &block[0];
|
||||||
@ -801,9 +817,9 @@ mod string {
|
|||||||
let engine_state = EngineState::new();
|
let engine_state = EngineState::new();
|
||||||
let mut working_set = StateWorkingSet::new(&engine_state);
|
let mut working_set = StateWorkingSet::new(&engine_state);
|
||||||
|
|
||||||
let (block, err) = parse(&mut working_set, None, b"$\"hello \\(39 + 3)\"", true, &[]);
|
let block = parse(&mut working_set, None, b"$\"hello \\(39 + 3)\"", true, &[]);
|
||||||
|
|
||||||
assert!(err.is_none());
|
assert!(working_set.parse_errors.is_empty());
|
||||||
|
|
||||||
assert_eq!(block.len(), 1);
|
assert_eq!(block.len(), 1);
|
||||||
let expressions = &block[0];
|
let expressions = &block[0];
|
||||||
@ -832,7 +848,7 @@ mod string {
|
|||||||
let engine_state = EngineState::new();
|
let engine_state = EngineState::new();
|
||||||
let mut working_set = StateWorkingSet::new(&engine_state);
|
let mut working_set = StateWorkingSet::new(&engine_state);
|
||||||
|
|
||||||
let (block, err) = parse(
|
let block = parse(
|
||||||
&mut working_set,
|
&mut working_set,
|
||||||
None,
|
None,
|
||||||
b"$\"hello \\\\(39 + 3)\"",
|
b"$\"hello \\\\(39 + 3)\"",
|
||||||
@ -840,7 +856,7 @@ mod string {
|
|||||||
&[],
|
&[],
|
||||||
);
|
);
|
||||||
|
|
||||||
assert!(err.is_none());
|
assert!(working_set.parse_errors.is_empty());
|
||||||
|
|
||||||
assert_eq!(block.len(), 1);
|
assert_eq!(block.len(), 1);
|
||||||
let expressions = &block[0];
|
let expressions = &block[0];
|
||||||
@ -871,7 +887,7 @@ mod string {
|
|||||||
let engine_state = EngineState::new();
|
let engine_state = EngineState::new();
|
||||||
let mut working_set = StateWorkingSet::new(&engine_state);
|
let mut working_set = StateWorkingSet::new(&engine_state);
|
||||||
|
|
||||||
let (block, err) = parse(
|
let block = parse(
|
||||||
&mut working_set,
|
&mut working_set,
|
||||||
None,
|
None,
|
||||||
b"$\"\\(1 + 3)\\(7 - 5)\"",
|
b"$\"\\(1 + 3)\\(7 - 5)\"",
|
||||||
@ -879,7 +895,7 @@ mod string {
|
|||||||
&[],
|
&[],
|
||||||
);
|
);
|
||||||
|
|
||||||
assert!(err.is_none());
|
assert!(working_set.parse_errors.is_empty());
|
||||||
|
|
||||||
assert_eq!(block.len(), 1);
|
assert_eq!(block.len(), 1);
|
||||||
let expressions = &block[0];
|
let expressions = &block[0];
|
||||||
@ -914,7 +930,7 @@ mod string {
|
|||||||
false,
|
false,
|
||||||
);
|
);
|
||||||
|
|
||||||
let (_block, err) = parse(
|
parse(
|
||||||
&mut working_set,
|
&mut working_set,
|
||||||
None,
|
None,
|
||||||
br#"
|
br#"
|
||||||
@ -924,7 +940,7 @@ mod string {
|
|||||||
&[],
|
&[],
|
||||||
);
|
);
|
||||||
|
|
||||||
assert!(err.is_none());
|
assert!(working_set.parse_errors.is_empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -939,7 +955,7 @@ mod string {
|
|||||||
false,
|
false,
|
||||||
);
|
);
|
||||||
|
|
||||||
let (_block, err) = parse(
|
parse(
|
||||||
&mut working_set,
|
&mut working_set,
|
||||||
None,
|
None,
|
||||||
br#"
|
br#"
|
||||||
@ -949,7 +965,7 @@ mod string {
|
|||||||
&[],
|
&[],
|
||||||
);
|
);
|
||||||
|
|
||||||
assert!(err.is_none());
|
assert!(working_set.parse_errors.is_empty());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -963,9 +979,9 @@ mod range {
|
|||||||
let engine_state = EngineState::new();
|
let engine_state = EngineState::new();
|
||||||
let mut working_set = StateWorkingSet::new(&engine_state);
|
let mut working_set = StateWorkingSet::new(&engine_state);
|
||||||
|
|
||||||
let (block, err) = parse(&mut working_set, None, b"0..10", true, &[]);
|
let block = parse(&mut working_set, None, b"0..10", true, &[]);
|
||||||
|
|
||||||
assert!(err.is_none());
|
assert!(working_set.parse_errors.is_empty());
|
||||||
assert_eq!(block.len(), 1);
|
assert_eq!(block.len(), 1);
|
||||||
|
|
||||||
let expressions = &block[0];
|
let expressions = &block[0];
|
||||||
@ -995,9 +1011,9 @@ mod range {
|
|||||||
let engine_state = EngineState::new();
|
let engine_state = EngineState::new();
|
||||||
let mut working_set = StateWorkingSet::new(&engine_state);
|
let mut working_set = StateWorkingSet::new(&engine_state);
|
||||||
|
|
||||||
let (block, err) = parse(&mut working_set, None, b"0..<10", true, &[]);
|
let block = parse(&mut working_set, None, b"0..<10", true, &[]);
|
||||||
|
|
||||||
assert!(err.is_none());
|
assert!(working_set.parse_errors.is_empty());
|
||||||
assert_eq!(block.len(), 1);
|
assert_eq!(block.len(), 1);
|
||||||
|
|
||||||
let expressions = &block[0];
|
let expressions = &block[0];
|
||||||
@ -1027,9 +1043,9 @@ mod range {
|
|||||||
let engine_state = EngineState::new();
|
let engine_state = EngineState::new();
|
||||||
let mut working_set = StateWorkingSet::new(&engine_state);
|
let mut working_set = StateWorkingSet::new(&engine_state);
|
||||||
|
|
||||||
let (block, err) = parse(&mut working_set, None, b"10..0", true, &[]);
|
let block = parse(&mut working_set, None, b"10..0", true, &[]);
|
||||||
|
|
||||||
assert!(err.is_none());
|
assert!(working_set.parse_errors.is_empty());
|
||||||
assert_eq!(block.len(), 1);
|
assert_eq!(block.len(), 1);
|
||||||
|
|
||||||
let expressions = &block[0];
|
let expressions = &block[0];
|
||||||
@ -1059,9 +1075,9 @@ mod range {
|
|||||||
let engine_state = EngineState::new();
|
let engine_state = EngineState::new();
|
||||||
let mut working_set = StateWorkingSet::new(&engine_state);
|
let mut working_set = StateWorkingSet::new(&engine_state);
|
||||||
|
|
||||||
let (block, err) = parse(&mut working_set, None, b"(3 - 3)..<(8 + 2)", true, &[]);
|
let block = parse(&mut working_set, None, b"(3 - 3)..<(8 + 2)", true, &[]);
|
||||||
|
|
||||||
assert!(err.is_none());
|
assert!(working_set.parse_errors.is_empty());
|
||||||
assert_eq!(block.len(), 1);
|
assert_eq!(block.len(), 1);
|
||||||
|
|
||||||
let expressions = &block[0];
|
let expressions = &block[0];
|
||||||
@ -1093,9 +1109,9 @@ mod range {
|
|||||||
|
|
||||||
working_set.add_decl(Box::new(Let));
|
working_set.add_decl(Box::new(Let));
|
||||||
|
|
||||||
let (block, err) = parse(&mut working_set, None, b"let a = 2; $a..10", true, &[]);
|
let block = parse(&mut working_set, None, b"let a = 2; $a..10", true, &[]);
|
||||||
|
|
||||||
assert!(err.is_none());
|
assert!(working_set.parse_errors.is_empty());
|
||||||
assert_eq!(block.len(), 2);
|
assert_eq!(block.len(), 2);
|
||||||
|
|
||||||
let expressions = &block[1];
|
let expressions = &block[1];
|
||||||
@ -1127,7 +1143,7 @@ mod range {
|
|||||||
|
|
||||||
working_set.add_decl(Box::new(Let));
|
working_set.add_decl(Box::new(Let));
|
||||||
|
|
||||||
let (block, err) = parse(
|
let block = parse(
|
||||||
&mut working_set,
|
&mut working_set,
|
||||||
None,
|
None,
|
||||||
b"let a = 2; $a..<($a + 10)",
|
b"let a = 2; $a..<($a + 10)",
|
||||||
@ -1135,7 +1151,7 @@ mod range {
|
|||||||
&[],
|
&[],
|
||||||
);
|
);
|
||||||
|
|
||||||
assert!(err.is_none());
|
assert!(working_set.parse_errors.is_empty());
|
||||||
assert_eq!(block.len(), 2);
|
assert_eq!(block.len(), 2);
|
||||||
|
|
||||||
let expressions = &block[1];
|
let expressions = &block[1];
|
||||||
@ -1165,9 +1181,9 @@ mod range {
|
|||||||
let engine_state = EngineState::new();
|
let engine_state = EngineState::new();
|
||||||
let mut working_set = StateWorkingSet::new(&engine_state);
|
let mut working_set = StateWorkingSet::new(&engine_state);
|
||||||
|
|
||||||
let (block, err) = parse(&mut working_set, None, b"0..", true, &[]);
|
let block = parse(&mut working_set, None, b"0..", true, &[]);
|
||||||
|
|
||||||
assert!(err.is_none());
|
assert!(working_set.parse_errors.is_empty());
|
||||||
assert_eq!(block.len(), 1);
|
assert_eq!(block.len(), 1);
|
||||||
|
|
||||||
let expressions = &block[0];
|
let expressions = &block[0];
|
||||||
@ -1197,9 +1213,9 @@ mod range {
|
|||||||
let engine_state = EngineState::new();
|
let engine_state = EngineState::new();
|
||||||
let mut working_set = StateWorkingSet::new(&engine_state);
|
let mut working_set = StateWorkingSet::new(&engine_state);
|
||||||
|
|
||||||
let (block, err) = parse(&mut working_set, None, b"..10", true, &[]);
|
let block = parse(&mut working_set, None, b"..10", true, &[]);
|
||||||
|
|
||||||
assert!(err.is_none());
|
assert!(working_set.parse_errors.is_empty());
|
||||||
assert_eq!(block.len(), 1);
|
assert_eq!(block.len(), 1);
|
||||||
|
|
||||||
let expressions = &block[0];
|
let expressions = &block[0];
|
||||||
@ -1229,9 +1245,9 @@ mod range {
|
|||||||
let engine_state = EngineState::new();
|
let engine_state = EngineState::new();
|
||||||
let mut working_set = StateWorkingSet::new(&engine_state);
|
let mut working_set = StateWorkingSet::new(&engine_state);
|
||||||
|
|
||||||
let (block, err) = parse(&mut working_set, None, b"-10..-3", true, &[]);
|
let block = parse(&mut working_set, None, b"-10..-3", true, &[]);
|
||||||
|
|
||||||
assert!(err.is_none());
|
assert!(working_set.parse_errors.is_empty());
|
||||||
assert_eq!(block.len(), 1);
|
assert_eq!(block.len(), 1);
|
||||||
|
|
||||||
let expressions = &block[0];
|
let expressions = &block[0];
|
||||||
@ -1261,9 +1277,9 @@ mod range {
|
|||||||
let engine_state = EngineState::new();
|
let engine_state = EngineState::new();
|
||||||
let mut working_set = StateWorkingSet::new(&engine_state);
|
let mut working_set = StateWorkingSet::new(&engine_state);
|
||||||
|
|
||||||
let (block, err) = parse(&mut working_set, None, b"2.0..4.0..10.0", true, &[]);
|
let block = parse(&mut working_set, None, b"2.0..4.0..10.0", true, &[]);
|
||||||
|
|
||||||
assert!(err.is_none());
|
assert!(working_set.parse_errors.is_empty());
|
||||||
assert_eq!(block.len(), 1);
|
assert_eq!(block.len(), 1);
|
||||||
|
|
||||||
let expressions = &block[0];
|
let expressions = &block[0];
|
||||||
@ -1293,9 +1309,9 @@ mod range {
|
|||||||
let engine_state = EngineState::new();
|
let engine_state = EngineState::new();
|
||||||
let mut working_set = StateWorkingSet::new(&engine_state);
|
let mut working_set = StateWorkingSet::new(&engine_state);
|
||||||
|
|
||||||
let (_, err) = parse(&mut working_set, None, b"(0)..\"a\"", true, &[]);
|
parse(&mut working_set, None, b"(0)..\"a\"", true, &[]);
|
||||||
|
|
||||||
assert!(err.is_some());
|
assert!(!working_set.parse_errors.is_empty());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1616,9 +1632,9 @@ mod input_types {
|
|||||||
let mut working_set = StateWorkingSet::new(&engine_state);
|
let mut working_set = StateWorkingSet::new(&engine_state);
|
||||||
let input = r#"ls | to-custom | group-by name other"#;
|
let input = r#"ls | to-custom | group-by name other"#;
|
||||||
|
|
||||||
let (block, err) = parse(&mut working_set, None, input.as_bytes(), true, &[]);
|
let block = parse(&mut working_set, None, input.as_bytes(), true, &[]);
|
||||||
|
|
||||||
assert!(err.is_none());
|
assert!(working_set.parse_errors.is_empty());
|
||||||
assert_eq!(block.len(), 1);
|
assert_eq!(block.len(), 1);
|
||||||
|
|
||||||
let expressions = &block[0];
|
let expressions = &block[0];
|
||||||
@ -1680,9 +1696,9 @@ mod input_types {
|
|||||||
let input =
|
let input =
|
||||||
r#"let a = (ls | to-custom | group-by name other); let b = (1+3); $a | agg sum"#;
|
r#"let a = (ls | to-custom | group-by name other); let b = (1+3); $a | agg sum"#;
|
||||||
|
|
||||||
let (block, err) = parse(&mut working_set, None, input.as_bytes(), true, &[]);
|
let block = parse(&mut working_set, None, input.as_bytes(), true, &[]);
|
||||||
|
|
||||||
assert!(err.is_none());
|
assert!(working_set.parse_errors.is_empty());
|
||||||
assert_eq!(block.len(), 3);
|
assert_eq!(block.len(), 3);
|
||||||
|
|
||||||
let expressions = &block[2];
|
let expressions = &block[2];
|
||||||
@ -1711,9 +1727,9 @@ mod input_types {
|
|||||||
let mut working_set = StateWorkingSet::new(&engine_state);
|
let mut working_set = StateWorkingSet::new(&engine_state);
|
||||||
let input = r#"let a = (ls | to-custom | group-by name other); ($a + $a) | agg sum"#;
|
let input = r#"let a = (ls | to-custom | group-by name other); ($a + $a) | agg sum"#;
|
||||||
|
|
||||||
let (block, err) = parse(&mut working_set, None, input.as_bytes(), true, &[]);
|
let block = parse(&mut working_set, None, input.as_bytes(), true, &[]);
|
||||||
|
|
||||||
assert!(err.is_none());
|
assert!(working_set.parse_errors.is_empty());
|
||||||
assert_eq!(block.len(), 2);
|
assert_eq!(block.len(), 2);
|
||||||
|
|
||||||
let expressions = &block[1];
|
let expressions = &block[1];
|
||||||
@ -1743,9 +1759,9 @@ mod input_types {
|
|||||||
let input = r#"
|
let input = r#"
|
||||||
let a = (ls | to-custom | group-by name other); [1 2 3] | to-custom; [1 2 3] | to-custom"#;
|
let a = (ls | to-custom | group-by name other); [1 2 3] | to-custom; [1 2 3] | to-custom"#;
|
||||||
|
|
||||||
let (block, err) = parse(&mut working_set, None, input.as_bytes(), true, &[]);
|
let block = parse(&mut working_set, None, input.as_bytes(), true, &[]);
|
||||||
|
|
||||||
assert!(err.is_none());
|
assert!(working_set.parse_errors.is_empty());
|
||||||
assert_eq!(block.len(), 3);
|
assert_eq!(block.len(), 3);
|
||||||
|
|
||||||
let expressions = &block[1];
|
let expressions = &block[1];
|
||||||
@ -1787,9 +1803,9 @@ mod input_types {
|
|||||||
let mut working_set = StateWorkingSet::new(&engine_state);
|
let mut working_set = StateWorkingSet::new(&engine_state);
|
||||||
let input = r#"ls | group-by name"#;
|
let input = r#"ls | group-by name"#;
|
||||||
|
|
||||||
let (block, err) = parse(&mut working_set, None, input.as_bytes(), true, &[]);
|
let block = parse(&mut working_set, None, input.as_bytes(), true, &[]);
|
||||||
|
|
||||||
assert!(err.is_none());
|
assert!(working_set.parse_errors.is_empty());
|
||||||
assert_eq!(block.len(), 1);
|
assert_eq!(block.len(), 1);
|
||||||
|
|
||||||
let expressions = &block[0];
|
let expressions = &block[0];
|
||||||
@ -1832,7 +1848,7 @@ mod input_types {
|
|||||||
let (block, delta) = {
|
let (block, delta) = {
|
||||||
let mut working_set = StateWorkingSet::new(&engine_state);
|
let mut working_set = StateWorkingSet::new(&engine_state);
|
||||||
let input = r#"ls | to-custom | group-by name other | agg ("b" | min)"#;
|
let input = r#"ls | to-custom | group-by name other | agg ("b" | min)"#;
|
||||||
let (block, _) = parse(&mut working_set, None, input.as_bytes(), true, &[]);
|
let block = parse(&mut working_set, None, input.as_bytes(), true, &[]);
|
||||||
|
|
||||||
(block, working_set.render())
|
(block, working_set.render())
|
||||||
};
|
};
|
||||||
@ -1893,9 +1909,9 @@ mod input_types {
|
|||||||
let mut working_set = StateWorkingSet::new(&engine_state);
|
let mut working_set = StateWorkingSet::new(&engine_state);
|
||||||
let input = r#"[[a b]; [1 2] [3 4]] | to-custom | with-column [ ("a" | min) ("b" | min) ] | collect"#;
|
let input = r#"[[a b]; [1 2] [3 4]] | to-custom | with-column [ ("a" | min) ("b" | min) ] | collect"#;
|
||||||
|
|
||||||
let (block, err) = parse(&mut working_set, None, input.as_bytes(), true, &[]);
|
let block = parse(&mut working_set, None, input.as_bytes(), true, &[]);
|
||||||
|
|
||||||
assert!(err.is_none());
|
assert!(working_set.parse_errors.is_empty());
|
||||||
assert_eq!(block.len(), 1);
|
assert_eq!(block.len(), 1);
|
||||||
|
|
||||||
let expressions = &block[0];
|
let expressions = &block[0];
|
||||||
@ -1947,9 +1963,9 @@ mod input_types {
|
|||||||
];
|
];
|
||||||
|
|
||||||
for input in inputs {
|
for input in inputs {
|
||||||
let (block, err) = parse(&mut working_set, None, input.as_bytes(), true, &[]);
|
let block = parse(&mut working_set, None, input.as_bytes(), true, &[]);
|
||||||
|
|
||||||
assert!(err.is_none(), "testing: {input}");
|
assert!(working_set.parse_errors.is_empty());
|
||||||
assert_eq!(block.len(), 2, "testing: {input}");
|
assert_eq!(block.len(), 2, "testing: {input}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1960,7 +1976,7 @@ mod input_types {
|
|||||||
add_declarations(&mut engine_state);
|
add_declarations(&mut engine_state);
|
||||||
|
|
||||||
let mut working_set = StateWorkingSet::new(&engine_state);
|
let mut working_set = StateWorkingSet::new(&engine_state);
|
||||||
let (_, err) = parse(
|
parse(
|
||||||
&mut working_set,
|
&mut working_set,
|
||||||
None,
|
None,
|
||||||
b"if false { 'a' } else { $foo }",
|
b"if false { 'a' } else { $foo }",
|
||||||
@ -1968,9 +1984,10 @@ mod input_types {
|
|||||||
&[],
|
&[],
|
||||||
);
|
);
|
||||||
|
|
||||||
let err = err.unwrap();
|
assert!(matches!(
|
||||||
|
working_set.parse_errors.first(),
|
||||||
assert!(matches!(err, ParseError::VariableNotFound(_)));
|
Some(ParseError::VariableNotFound(_))
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -1979,7 +1996,7 @@ mod input_types {
|
|||||||
add_declarations(&mut engine_state);
|
add_declarations(&mut engine_state);
|
||||||
|
|
||||||
let mut working_set = StateWorkingSet::new(&engine_state);
|
let mut working_set = StateWorkingSet::new(&engine_state);
|
||||||
let (_, err) = parse(
|
parse(
|
||||||
&mut working_set,
|
&mut working_set,
|
||||||
None,
|
None,
|
||||||
b"if false { 'a' } else $foo { 'b' }",
|
b"if false { 'a' } else $foo { 'b' }",
|
||||||
@ -1987,8 +2004,9 @@ mod input_types {
|
|||||||
&[],
|
&[],
|
||||||
);
|
);
|
||||||
|
|
||||||
let err = err.unwrap();
|
assert!(matches!(
|
||||||
|
working_set.parse_errors.first(),
|
||||||
assert!(matches!(err, ParseError::VariableNotFound(_)));
|
Some(ParseError::VariableNotFound(_))
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,9 +14,9 @@ pub fn do_test(test: &[u8], expected: &str, error_contains: Option<&str>) {
|
|||||||
let engine_state = EngineState::new();
|
let engine_state = EngineState::new();
|
||||||
let mut working_set = StateWorkingSet::new(&engine_state);
|
let mut working_set = StateWorkingSet::new(&engine_state);
|
||||||
|
|
||||||
let (block, err) = parse(&mut working_set, None, test, true, &[]);
|
let block = parse(&mut working_set, None, test, true, &[]);
|
||||||
|
|
||||||
match err {
|
match working_set.parse_errors.first() {
|
||||||
None => {
|
None => {
|
||||||
assert_eq!(block.len(), 1);
|
assert_eq!(block.len(), 1);
|
||||||
let expressions = &block[0];
|
let expressions = &block[0];
|
||||||
|
@ -2,11 +2,11 @@ use fancy_regex::Regex;
|
|||||||
use lru::LruCache;
|
use lru::LruCache;
|
||||||
|
|
||||||
use super::{Command, EnvVars, OverlayFrame, ScopeFrame, Stack, Visibility, DEFAULT_OVERLAY_NAME};
|
use super::{Command, EnvVars, OverlayFrame, ScopeFrame, Stack, Visibility, DEFAULT_OVERLAY_NAME};
|
||||||
use crate::Value;
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ast::Block, AliasId, BlockId, Config, DeclId, Example, Module, ModuleId, OverlayId, ShellError,
|
ast::Block, AliasId, BlockId, Config, DeclId, Example, Module, ModuleId, OverlayId, ShellError,
|
||||||
Signature, Span, Type, VarId, Variable,
|
Signature, Span, Type, VarId, Variable,
|
||||||
};
|
};
|
||||||
|
use crate::{ParseError, Value};
|
||||||
use core::panic;
|
use core::panic;
|
||||||
use std::borrow::Borrow;
|
use std::borrow::Borrow;
|
||||||
use std::num::NonZeroUsize;
|
use std::num::NonZeroUsize;
|
||||||
@ -1035,6 +1035,7 @@ pub struct StateWorkingSet<'a> {
|
|||||||
pub currently_parsed_cwd: Option<PathBuf>,
|
pub currently_parsed_cwd: Option<PathBuf>,
|
||||||
/// All previously parsed module files. Used to protect against circular imports.
|
/// All previously parsed module files. Used to protect against circular imports.
|
||||||
pub parsed_module_files: Vec<PathBuf>,
|
pub parsed_module_files: Vec<PathBuf>,
|
||||||
|
pub parse_errors: Vec<ParseError>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A temporary placeholder for expression types. It is used to keep track of the input types
|
/// A temporary placeholder for expression types. It is used to keep track of the input types
|
||||||
@ -1218,9 +1219,14 @@ impl<'a> StateWorkingSet<'a> {
|
|||||||
type_scope: TypeScope::default(),
|
type_scope: TypeScope::default(),
|
||||||
currently_parsed_cwd: permanent_state.currently_parsed_cwd.clone(),
|
currently_parsed_cwd: permanent_state.currently_parsed_cwd.clone(),
|
||||||
parsed_module_files: vec![],
|
parsed_module_files: vec![],
|
||||||
|
parse_errors: vec![],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn error(&mut self, parse_error: ParseError) {
|
||||||
|
self.parse_errors.push(parse_error)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn num_files(&self) -> usize {
|
pub fn num_files(&self) -> usize {
|
||||||
self.delta.num_files() + self.permanent_state.num_files()
|
self.delta.num_files() + self.permanent_state.num_files()
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ mod exportable;
|
|||||||
mod id;
|
mod id;
|
||||||
mod lev_distance;
|
mod lev_distance;
|
||||||
mod module;
|
mod module;
|
||||||
|
mod parse_error;
|
||||||
mod pipeline_data;
|
mod pipeline_data;
|
||||||
#[cfg(feature = "plugin")]
|
#[cfg(feature = "plugin")]
|
||||||
mod plugin_signature;
|
mod plugin_signature;
|
||||||
@ -28,6 +29,7 @@ pub use example::*;
|
|||||||
pub use exportable::*;
|
pub use exportable::*;
|
||||||
pub use id::*;
|
pub use id::*;
|
||||||
pub use module::*;
|
pub use module::*;
|
||||||
|
pub use parse_error::ParseError;
|
||||||
pub use pipeline_data::*;
|
pub use pipeline_data::*;
|
||||||
#[cfg(feature = "plugin")]
|
#[cfg(feature = "plugin")]
|
||||||
pub use plugin_signature::*;
|
pub use plugin_signature::*;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
|
use crate::{Span, Type};
|
||||||
use miette::Diagnostic;
|
use miette::Diagnostic;
|
||||||
use nu_protocol::{Span, Type};
|
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
#[derive(Clone, Debug, Error, Diagnostic)]
|
#[derive(Clone, Debug, Error, Diagnostic)]
|
@ -64,15 +64,15 @@ pub(crate) fn parse_commandline_args(
|
|||||||
let mut working_set = StateWorkingSet::new(engine_state);
|
let mut working_set = StateWorkingSet::new(engine_state);
|
||||||
working_set.add_decl(Box::new(Nu));
|
working_set.add_decl(Box::new(Nu));
|
||||||
|
|
||||||
let (output, err) = parse(
|
let output = parse(
|
||||||
&mut working_set,
|
&mut working_set,
|
||||||
None,
|
None,
|
||||||
commandline_args.as_bytes(),
|
commandline_args.as_bytes(),
|
||||||
false,
|
false,
|
||||||
&[],
|
&[],
|
||||||
);
|
);
|
||||||
if let Some(err) = err {
|
if let Some(err) = working_set.parse_errors.first() {
|
||||||
report_error(&working_set, &err);
|
report_error(&working_set, err);
|
||||||
|
|
||||||
std::process::exit(1);
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
|
@ -3,10 +3,9 @@ use log::info;
|
|||||||
use nu_cli::read_plugin_file;
|
use nu_cli::read_plugin_file;
|
||||||
use nu_cli::{eval_config_contents, eval_source};
|
use nu_cli::{eval_config_contents, eval_source};
|
||||||
use nu_command::util::report_error;
|
use nu_command::util::report_error;
|
||||||
use nu_parser::ParseError;
|
|
||||||
use nu_path::canonicalize_with;
|
use nu_path::canonicalize_with;
|
||||||
use nu_protocol::engine::{EngineState, Stack, StateWorkingSet};
|
use nu_protocol::engine::{EngineState, Stack, StateWorkingSet};
|
||||||
use nu_protocol::{PipelineData, Spanned};
|
use nu_protocol::{ParseError, PipelineData, Spanned};
|
||||||
use nu_utils::{get_default_config, get_default_env};
|
use nu_utils::{get_default_config, get_default_env};
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
|
@ -22,7 +22,7 @@ fn find_id(
|
|||||||
location: &Value,
|
location: &Value,
|
||||||
) -> Option<(Id, usize, Span)> {
|
) -> Option<(Id, usize, Span)> {
|
||||||
let offset = working_set.next_span_start();
|
let offset = working_set.next_span_start();
|
||||||
let (block, _) = parse(working_set, Some(file_path), file, false, &[]);
|
let block = parse(working_set, Some(file_path), file, false, &[]);
|
||||||
|
|
||||||
let flattened = flatten_block(working_set, &block);
|
let flattened = flatten_block(working_set, &block);
|
||||||
|
|
||||||
@ -78,9 +78,9 @@ pub fn check(engine_state: &mut EngineState, file_path: &String) {
|
|||||||
|
|
||||||
if let Ok(contents) = file {
|
if let Ok(contents) = file {
|
||||||
let offset = working_set.next_span_start();
|
let offset = working_set.next_span_start();
|
||||||
let (block, err) = parse(&mut working_set, Some(file_path), &contents, false, &[]);
|
let block = parse(&mut working_set, Some(file_path), &contents, false, &[]);
|
||||||
|
|
||||||
if let Some(err) = err {
|
for err in &working_set.parse_errors {
|
||||||
let mut span = err.span();
|
let mut span = err.span();
|
||||||
span.start -= offset;
|
span.start -= offset;
|
||||||
span.end -= offset;
|
span.end -= offset;
|
||||||
|
12
src/run.rs
12
src/run.rs
@ -62,21 +62,21 @@ fn load_standard_library(
|
|||||||
working_set.add_file(name.clone(), content);
|
working_set.add_file(name.clone(), content);
|
||||||
let end = working_set.next_span_start();
|
let end = working_set.next_span_start();
|
||||||
|
|
||||||
let (_, module, comments, parse_error) = parse_module_block(
|
let (_, module, comments) = parse_module_block(
|
||||||
&mut working_set,
|
&mut working_set,
|
||||||
Span::new(start, end),
|
Span::new(start, end),
|
||||||
name.as_bytes(),
|
name.as_bytes(),
|
||||||
&[],
|
&[],
|
||||||
);
|
);
|
||||||
|
|
||||||
if let Some(err) = parse_error {
|
if let Some(err) = working_set.parse_errors.first() {
|
||||||
report_error(&working_set, &err);
|
report_error(&working_set, err);
|
||||||
}
|
}
|
||||||
|
|
||||||
let (_, parse_error) = parse(&mut working_set, Some(&name), content, true, &[]);
|
parse(&mut working_set, Some(&name), content, true, &[]);
|
||||||
|
|
||||||
if let Some(err) = parse_error {
|
if let Some(err) = working_set.parse_errors.first() {
|
||||||
report_error(&working_set, &err);
|
report_error(&working_set, err);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: change this when #8505 is merged
|
// TODO: change this when #8505 is merged
|
||||||
|
@ -224,7 +224,7 @@ pub fn nu_repl() {
|
|||||||
// Eval the REPL line
|
// Eval the REPL line
|
||||||
let (block, delta) = {
|
let (block, delta) = {
|
||||||
let mut working_set = StateWorkingSet::new(&engine_state);
|
let mut working_set = StateWorkingSet::new(&engine_state);
|
||||||
let (block, err) = parse(
|
let block = parse(
|
||||||
&mut working_set,
|
&mut working_set,
|
||||||
Some(&format!("line{i}")),
|
Some(&format!("line{i}")),
|
||||||
line.as_bytes(),
|
line.as_bytes(),
|
||||||
@ -232,8 +232,8 @@ pub fn nu_repl() {
|
|||||||
&[],
|
&[],
|
||||||
);
|
);
|
||||||
|
|
||||||
if let Some(err) = err {
|
if let Some(err) = working_set.parse_errors.first() {
|
||||||
outcome_err(&engine_state, &err);
|
outcome_err(&engine_state, err);
|
||||||
}
|
}
|
||||||
(block, working_set.render())
|
(block, working_set.render())
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user