mirror of
https://github.com/nushell/nushell.git
synced 2025-08-09 00:54:56 +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:
@ -1,508 +0,0 @@
|
||||
use miette::Diagnostic;
|
||||
use nu_protocol::{Span, Type};
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Clone, Debug, Error, Diagnostic)]
|
||||
pub enum ParseError {
|
||||
/// The parser encountered unexpected tokens, when the code should have
|
||||
/// finished. You should remove these or finish adding what you intended
|
||||
/// to add.
|
||||
#[error("Extra tokens in code.")]
|
||||
#[diagnostic(code(nu::parser::extra_tokens), help("Try removing them."))]
|
||||
ExtraTokens(#[label = "extra tokens"] Span),
|
||||
|
||||
#[error("Extra positional argument.")]
|
||||
#[diagnostic(code(nu::parser::extra_positional), help("Usage: {0}"))]
|
||||
ExtraPositional(String, #[label = "extra positional argument"] Span),
|
||||
|
||||
#[error("Required positional parameter after optional parameter")]
|
||||
#[diagnostic(code(nu::parser::required_after_optional))]
|
||||
RequiredAfterOptional(
|
||||
String,
|
||||
#[label = "required parameter {0} after optional parameter"] Span,
|
||||
),
|
||||
|
||||
#[error("Unexpected end of code.")]
|
||||
#[diagnostic(code(nu::parser::unexpected_eof))]
|
||||
UnexpectedEof(String, #[label("expected closing {0}")] Span),
|
||||
|
||||
#[error("Unclosed delimiter.")]
|
||||
#[diagnostic(code(nu::parser::unclosed_delimiter))]
|
||||
Unclosed(String, #[label("unclosed {0}")] Span),
|
||||
|
||||
#[error("Unbalanced delimiter.")]
|
||||
#[diagnostic(code(nu::parser::unbalanced_delimiter))]
|
||||
Unbalanced(String, String, #[label("unbalanced {0} and {1}")] Span),
|
||||
|
||||
#[error("Parse mismatch during operation.")]
|
||||
#[diagnostic(code(nu::parser::parse_mismatch))]
|
||||
Expected(String, #[label("expected {0}")] Span),
|
||||
|
||||
#[error("Missing || inside closure")]
|
||||
#[diagnostic(
|
||||
code(nu::parser::closure_missing_pipe),
|
||||
help("Try add || to the beginning of closure")
|
||||
)]
|
||||
ClosureMissingPipe(#[label("Parsing as a closure, but || is missing")] Span),
|
||||
|
||||
#[error("Type mismatch during operation.")]
|
||||
#[diagnostic(code(nu::parser::type_mismatch))]
|
||||
Mismatch(String, String, #[label("expected {0}, found {1}")] Span), // expected, found, span
|
||||
|
||||
#[error("The '&&' operator is not supported in Nushell")]
|
||||
#[diagnostic(
|
||||
code(nu::parser::shell_andand),
|
||||
help("use ';' instead of the shell '&&', or 'and' instead of the boolean '&&'")
|
||||
)]
|
||||
ShellAndAnd(#[label("instead of '&&', use ';' or 'and'")] Span),
|
||||
|
||||
#[error("The '||' operator is not supported in Nushell")]
|
||||
#[diagnostic(
|
||||
code(nu::parser::shell_oror),
|
||||
help("use 'try' instead of the shell '||', or 'or' instead of the boolean '||'")
|
||||
)]
|
||||
ShellOrOr(#[label("instead of '||', use 'try' or 'or'")] Span),
|
||||
|
||||
#[error("The '2>' shell operation is 'err>' in Nushell.")]
|
||||
#[diagnostic(code(nu::parser::shell_err))]
|
||||
ShellErrRedirect(#[label("use 'err>' instead of '2>' in Nushell")] Span),
|
||||
|
||||
#[error("The '2>&1' shell operation is 'out+err>' in Nushell.")]
|
||||
#[diagnostic(
|
||||
code(nu::parser::shell_outerr),
|
||||
help("Nushell redirection will write all of stdout before stderr.")
|
||||
)]
|
||||
ShellOutErrRedirect(#[label("use 'out+err>' instead of '2>&1' in Nushell")] Span),
|
||||
|
||||
#[error("Types mismatched for operation.")]
|
||||
#[diagnostic(
|
||||
code(nu::parser::unsupported_operation),
|
||||
help("Change {2} or {4} to be the right types and try again.")
|
||||
)]
|
||||
UnsupportedOperation(
|
||||
#[label = "doesn't support these values."] Span,
|
||||
#[label("{2}")] Span,
|
||||
Type,
|
||||
#[label("{4}")] Span,
|
||||
Type,
|
||||
),
|
||||
|
||||
#[error("Capture of mutable variable.")]
|
||||
#[diagnostic(code(nu::parser::expected_keyword))]
|
||||
CaptureOfMutableVar(#[label("capture of mutable variable")] Span),
|
||||
|
||||
#[error("Expected keyword.")]
|
||||
#[diagnostic(code(nu::parser::expected_keyword))]
|
||||
ExpectedKeyword(String, #[label("expected {0}")] Span),
|
||||
|
||||
#[error("Unexpected keyword.")]
|
||||
#[diagnostic(
|
||||
code(nu::parser::unexpected_keyword),
|
||||
help("'{0}' keyword is allowed only in a module.")
|
||||
)]
|
||||
UnexpectedKeyword(String, #[label("unexpected {0}")] Span),
|
||||
|
||||
#[error("Can't create alias to parser keyword.")]
|
||||
#[diagnostic(
|
||||
code(nu::parser::cant_alias_keyword),
|
||||
help("Only the following keywords can be aliased: {0}.")
|
||||
)]
|
||||
CantAliasKeyword(String, #[label("not supported in alias")] Span),
|
||||
|
||||
#[error("Can't create alias to expression.")]
|
||||
#[diagnostic(
|
||||
code(nu::parser::cant_alias_expression),
|
||||
help("Only command calls can be aliased.")
|
||||
)]
|
||||
CantAliasExpression(String, #[label("aliasing {0} is not supported")] Span),
|
||||
|
||||
#[error("Unknown operator")]
|
||||
#[diagnostic(code(nu::parser::unknown_operator), help("{1}"))]
|
||||
UnknownOperator(
|
||||
&'static str,
|
||||
&'static str,
|
||||
#[label("Operator '{0}' not supported")] Span,
|
||||
),
|
||||
|
||||
#[error("Statement used in pipeline.")]
|
||||
#[diagnostic(
|
||||
code(nu::parser::unexpected_keyword),
|
||||
help(
|
||||
"'{0}' keyword is not allowed in pipeline. Use '{0}' by itself, outside of a pipeline."
|
||||
)
|
||||
)]
|
||||
BuiltinCommandInPipeline(String, #[label("not allowed in pipeline")] Span),
|
||||
|
||||
#[error("{0} statement used in pipeline.")]
|
||||
#[diagnostic(
|
||||
code(nu::parser::unexpected_keyword),
|
||||
help(
|
||||
"Assigning '{1}' to '{2}' does not produce a value to be piped. If the pipeline result is meant to be assigned to '{2}', use '{0} {2} = ({1} | ...)'."
|
||||
)
|
||||
)]
|
||||
AssignInPipeline(String, String, String, #[label("'{0}' in pipeline")] Span),
|
||||
|
||||
#[error("Let used with builtin variable name.")]
|
||||
#[diagnostic(
|
||||
code(nu::parser::let_builtin_var),
|
||||
help("'{0}' is the name of a builtin Nushell variable. `let` cannot assign to it.")
|
||||
)]
|
||||
LetBuiltinVar(String, #[label("already a builtin variable")] Span),
|
||||
|
||||
#[error("Const used with builtin variable name.")]
|
||||
#[diagnostic(
|
||||
code(nu::parser::let_builtin_var),
|
||||
help("'{0}' is the name of a builtin Nushell variable. `const` cannot assign to it.")
|
||||
)]
|
||||
ConstBuiltinVar(String, #[label("already a builtin variable")] Span),
|
||||
|
||||
#[error("Mut used with builtin variable name.")]
|
||||
#[diagnostic(
|
||||
code(nu::parser::let_builtin_var),
|
||||
help("'{0}' is the name of a builtin Nushell variable. `mut` cannot assign to it.")
|
||||
)]
|
||||
MutBuiltinVar(String, #[label("already a builtin variable")] Span),
|
||||
|
||||
#[error("Incorrect value")]
|
||||
#[diagnostic(code(nu::parser::incorrect_value), help("{2}"))]
|
||||
IncorrectValue(String, #[label("unexpected {0}")] Span, String),
|
||||
|
||||
#[error("Multiple rest params.")]
|
||||
#[diagnostic(code(nu::parser::multiple_rest_params))]
|
||||
MultipleRestParams(#[label = "multiple rest params"] Span),
|
||||
|
||||
#[error("Variable not found.")]
|
||||
#[diagnostic(code(nu::parser::variable_not_found))]
|
||||
VariableNotFound(#[label = "variable not found"] Span),
|
||||
|
||||
#[error("Variable name not supported.")]
|
||||
#[diagnostic(code(nu::parser::variable_not_valid))]
|
||||
VariableNotValid(#[label = "variable name can't contain spaces or quotes"] Span),
|
||||
|
||||
#[error("Alias name not supported.")]
|
||||
#[diagnostic(code(nu::parser::variable_not_valid))]
|
||||
AliasNotValid(
|
||||
#[label = "alias name can't be a number, a filesize, or contain a hash # or caret ^"] Span,
|
||||
),
|
||||
|
||||
#[error("Command name not supported.")]
|
||||
#[diagnostic(code(nu::parser::variable_not_valid))]
|
||||
CommandDefNotValid(
|
||||
#[label = "command name can't be a number, a filesize, or contain a hash # or caret ^"]
|
||||
Span,
|
||||
),
|
||||
|
||||
#[error("Module not found.")]
|
||||
#[diagnostic(
|
||||
code(nu::parser::module_not_found),
|
||||
help("module files and their paths must be available before your script is run as parsing occurs before anything is evaluated")
|
||||
)]
|
||||
ModuleNotFound(#[label = "module not found"] Span),
|
||||
|
||||
#[error("Cyclical module import.")]
|
||||
#[diagnostic(code(nu::parser::cyclical_module_import), help("{0}"))]
|
||||
CyclicalModuleImport(String, #[label = "detected cyclical module import"] Span),
|
||||
|
||||
#[error("Can't export {0} named same as the module.")]
|
||||
#[diagnostic(
|
||||
code(nu::parser::named_as_module),
|
||||
help("Module {1} can't export {0} named the same as the module. Either change the module name, or export `main` custom command.")
|
||||
)]
|
||||
NamedAsModule(
|
||||
String,
|
||||
String,
|
||||
#[label = "can't export from module {1}"] Span,
|
||||
),
|
||||
|
||||
#[error("Can't export alias defined as 'main'.")]
|
||||
#[diagnostic(
|
||||
code(nu::parser::export_main_alias_not_allowed),
|
||||
help("Exporting aliases as 'main' is not allowed. Either rename the alias or convert it to a custom command.")
|
||||
)]
|
||||
ExportMainAliasNotAllowed(#[label = "can't export from module"] Span),
|
||||
|
||||
#[error("Active overlay not found.")]
|
||||
#[diagnostic(code(nu::parser::active_overlay_not_found))]
|
||||
ActiveOverlayNotFound(#[label = "not an active overlay"] Span),
|
||||
|
||||
#[error("Overlay prefix mismatch.")]
|
||||
#[diagnostic(
|
||||
code(nu::parser::overlay_prefix_mismatch),
|
||||
help("Overlay {0} already exists {1} a prefix. To add it again, do it {1} the --prefix flag.")
|
||||
)]
|
||||
OverlayPrefixMismatch(
|
||||
String,
|
||||
String,
|
||||
#[label = "already exists {1} a prefix"] Span,
|
||||
),
|
||||
|
||||
#[error("Module or overlay not found.")]
|
||||
#[diagnostic(
|
||||
code(nu::parser::module_or_overlay_not_found),
|
||||
help("Requires either an existing overlay, a module, or an import pattern defining a module.")
|
||||
)]
|
||||
ModuleOrOverlayNotFound(#[label = "not a module or an overlay"] Span),
|
||||
|
||||
#[error("Cannot remove the last overlay.")]
|
||||
#[diagnostic(
|
||||
code(nu::parser::cant_remove_last_overlay),
|
||||
help("At least one overlay must always be active.")
|
||||
)]
|
||||
CantRemoveLastOverlay(#[label = "this is the last overlay, can't remove it"] Span),
|
||||
|
||||
#[error("Cannot hide default overlay.")]
|
||||
#[diagnostic(
|
||||
code(nu::parser::cant_hide_default_overlay),
|
||||
help("'{0}' is a default overlay. Default overlays cannot be hidden.")
|
||||
)]
|
||||
CantHideDefaultOverlay(String, #[label = "can't hide overlay"] Span),
|
||||
|
||||
#[error("Cannot add overlay.")]
|
||||
#[diagnostic(code(nu::parser::cant_add_overlay_help), help("{0}"))]
|
||||
CantAddOverlayHelp(String, #[label = "cannot add this overlay"] Span),
|
||||
|
||||
#[error("Not found.")]
|
||||
#[diagnostic(code(nu::parser::not_found))]
|
||||
NotFound(#[label = "did not find anything under this name"] Span),
|
||||
|
||||
#[error("Duplicate command definition within a block.")]
|
||||
#[diagnostic(code(nu::parser::duplicate_command_def))]
|
||||
DuplicateCommandDef(#[label = "defined more than once"] Span),
|
||||
|
||||
#[error("Unknown command.")]
|
||||
#[diagnostic(
|
||||
code(nu::parser::unknown_command),
|
||||
// TODO: actual suggestions like "Did you mean `foo`?"
|
||||
)]
|
||||
UnknownCommand(#[label = "unknown command"] Span),
|
||||
|
||||
#[error("Non-UTF8 string.")]
|
||||
#[diagnostic(code(nu::parser::non_utf8))]
|
||||
NonUtf8(#[label = "non-UTF8 string"] Span),
|
||||
|
||||
#[error("The `{0}` command doesn't have flag `{1}`.")]
|
||||
#[diagnostic(code(nu::parser::unknown_flag), help("{3}"))]
|
||||
UnknownFlag(String, String, #[label = "unknown flag"] Span, String),
|
||||
|
||||
#[error("Unknown type.")]
|
||||
#[diagnostic(code(nu::parser::unknown_type))]
|
||||
UnknownType(#[label = "unknown type"] Span),
|
||||
|
||||
#[error("Missing flag argument.")]
|
||||
#[diagnostic(code(nu::parser::missing_flag_param))]
|
||||
MissingFlagParam(String, #[label = "flag missing {0} argument"] Span),
|
||||
|
||||
#[error("Batches of short flags can't take arguments.")]
|
||||
#[diagnostic(code(nu::parser::short_flag_arg_cant_take_arg))]
|
||||
ShortFlagBatchCantTakeArg(#[label = "short flag batches can't take args"] Span),
|
||||
|
||||
#[error("Missing required positional argument.")]
|
||||
#[diagnostic(code(nu::parser::missing_positional), help("Usage: {2}"))]
|
||||
MissingPositional(String, #[label("missing {0}")] Span, String),
|
||||
|
||||
#[error("Missing argument to `{1}`.")]
|
||||
#[diagnostic(code(nu::parser::keyword_missing_arg))]
|
||||
KeywordMissingArgument(
|
||||
String,
|
||||
String,
|
||||
#[label("missing {0} value that follows {1}")] Span,
|
||||
),
|
||||
|
||||
#[error("Missing type.")]
|
||||
#[diagnostic(code(nu::parser::missing_type))]
|
||||
MissingType(#[label = "expected type"] Span),
|
||||
|
||||
#[error("Type mismatch.")]
|
||||
#[diagnostic(code(nu::parser::type_mismatch))]
|
||||
TypeMismatch(Type, Type, #[label("expected {0}, found {1}")] Span), // expected, found, span
|
||||
|
||||
#[error("Missing required flag.")]
|
||||
#[diagnostic(code(nu::parser::missing_required_flag))]
|
||||
MissingRequiredFlag(String, #[label("missing required flag {0}")] Span),
|
||||
|
||||
#[error("Incomplete math expression.")]
|
||||
#[diagnostic(code(nu::parser::incomplete_math_expression))]
|
||||
IncompleteMathExpression(#[label = "incomplete math expression"] Span),
|
||||
|
||||
#[error("Unknown state.")]
|
||||
#[diagnostic(code(nu::parser::unknown_state))]
|
||||
UnknownState(String, #[label("{0}")] Span),
|
||||
|
||||
#[error("Internal error.")]
|
||||
#[diagnostic(code(nu::parser::unknown_state))]
|
||||
InternalError(String, #[label("{0}")] Span),
|
||||
|
||||
#[error("Parser incomplete.")]
|
||||
#[diagnostic(code(nu::parser::parser_incomplete))]
|
||||
IncompleteParser(#[label = "parser support missing for this expression"] Span),
|
||||
|
||||
#[error("Rest parameter needs a name.")]
|
||||
#[diagnostic(code(nu::parser::rest_needs_name))]
|
||||
RestNeedsName(#[label = "needs a parameter name"] Span),
|
||||
|
||||
#[error("Parameter not correct type.")]
|
||||
#[diagnostic(code(nu::parser::parameter_mismatch_type))]
|
||||
ParameterMismatchType(
|
||||
String,
|
||||
String,
|
||||
String,
|
||||
#[label = "parameter {0} needs to be '{1}' instead of '{2}'"] Span,
|
||||
),
|
||||
|
||||
#[error("Extra columns.")]
|
||||
#[diagnostic(code(nu::parser::extra_columns))]
|
||||
ExtraColumns(
|
||||
usize,
|
||||
#[label("expected {0} column{}", if *.0 == 1 { "" } else { "s" })] Span,
|
||||
),
|
||||
|
||||
#[error("Missing columns.")]
|
||||
#[diagnostic(code(nu::parser::missing_columns))]
|
||||
MissingColumns(
|
||||
usize,
|
||||
#[label("expected {0} column{}", if *.0 == 1 { "" } else { "s" })] Span,
|
||||
),
|
||||
|
||||
#[error("{0}")]
|
||||
#[diagnostic(code(nu::parser::assignment_mismatch))]
|
||||
AssignmentMismatch(String, String, #[label("{1}")] Span),
|
||||
|
||||
#[error("Missing import pattern.")]
|
||||
#[diagnostic(code(nu::parser::missing_import_pattern))]
|
||||
MissingImportPattern(#[label = "needs an import pattern"] Span),
|
||||
|
||||
#[error("Wrong import pattern structure.")]
|
||||
#[diagnostic(code(nu::parser::missing_import_pattern))]
|
||||
WrongImportPattern(#[label = "invalid import pattern structure"] Span),
|
||||
|
||||
#[error("Export not found.")]
|
||||
#[diagnostic(code(nu::parser::export_not_found))]
|
||||
ExportNotFound(#[label = "could not find imports"] Span),
|
||||
|
||||
#[error("File not found")]
|
||||
#[diagnostic(
|
||||
code(nu::parser::sourced_file_not_found),
|
||||
help("sourced files need to be available before your script is run")
|
||||
)]
|
||||
SourcedFileNotFound(String, #[label("File not found: {0}")] Span),
|
||||
|
||||
#[error("File not found")]
|
||||
#[diagnostic(
|
||||
code(nu::parser::registered_file_not_found),
|
||||
help("registered files need to be available before your script is run")
|
||||
)]
|
||||
RegisteredFileNotFound(String, #[label("File not found: {0}")] Span),
|
||||
|
||||
#[error("File not found")]
|
||||
#[diagnostic(code(nu::parser::file_not_found))]
|
||||
FileNotFound(String, #[label("File not found: {0}")] Span),
|
||||
|
||||
/// Error while trying to read a file
|
||||
///
|
||||
/// ## Resolution
|
||||
///
|
||||
/// The error will show the result from a file operation
|
||||
#[error("Error trying to read file")]
|
||||
#[diagnostic(code(nu::shell::error_reading_file))]
|
||||
ReadingFile(String, #[label("{0}")] Span),
|
||||
|
||||
/// Tried assigning non-constant value to a constant
|
||||
///
|
||||
/// ## Resolution
|
||||
///
|
||||
/// Only a subset of expressions are allowed to be assigned as a constant during parsing.
|
||||
#[error("Not a constant.")]
|
||||
#[diagnostic(
|
||||
code(nu::parser::not_a_constant),
|
||||
help("Only a subset of expressions are allowed constants during parsing. Try using the 'const' command or typing the value literally.")
|
||||
)]
|
||||
NotAConstant(#[label = "Value is not a parse-time constant"] Span),
|
||||
|
||||
#[error("Invalid literal")] // <problem> in <entity>.
|
||||
#[diagnostic()]
|
||||
InvalidLiteral(String, String, #[label("{0} in {1}")] Span),
|
||||
|
||||
#[error("{0}")]
|
||||
#[diagnostic()]
|
||||
LabeledError(String, String, #[label("{1}")] Span),
|
||||
}
|
||||
|
||||
impl ParseError {
|
||||
pub fn span(&self) -> Span {
|
||||
match self {
|
||||
ParseError::ExtraTokens(s) => *s,
|
||||
ParseError::ExtraPositional(_, s) => *s,
|
||||
ParseError::UnexpectedEof(_, s) => *s,
|
||||
ParseError::Unclosed(_, s) => *s,
|
||||
ParseError::Unbalanced(_, _, s) => *s,
|
||||
ParseError::Expected(_, s) => *s,
|
||||
ParseError::Mismatch(_, _, s) => *s,
|
||||
ParseError::UnsupportedOperation(_, _, _, s, _) => *s,
|
||||
ParseError::ExpectedKeyword(_, s) => *s,
|
||||
ParseError::UnexpectedKeyword(_, s) => *s,
|
||||
ParseError::CantAliasKeyword(_, s) => *s,
|
||||
ParseError::CantAliasExpression(_, s) => *s,
|
||||
ParseError::BuiltinCommandInPipeline(_, s) => *s,
|
||||
ParseError::AssignInPipeline(_, _, _, s) => *s,
|
||||
ParseError::LetBuiltinVar(_, s) => *s,
|
||||
ParseError::MutBuiltinVar(_, s) => *s,
|
||||
ParseError::ConstBuiltinVar(_, s) => *s,
|
||||
ParseError::CaptureOfMutableVar(s) => *s,
|
||||
ParseError::IncorrectValue(_, s, _) => *s,
|
||||
ParseError::MultipleRestParams(s) => *s,
|
||||
ParseError::VariableNotFound(s) => *s,
|
||||
ParseError::VariableNotValid(s) => *s,
|
||||
ParseError::AliasNotValid(s) => *s,
|
||||
ParseError::CommandDefNotValid(s) => *s,
|
||||
ParseError::ModuleNotFound(s) => *s,
|
||||
ParseError::NamedAsModule(_, _, s) => *s,
|
||||
ParseError::ExportMainAliasNotAllowed(s) => *s,
|
||||
ParseError::CyclicalModuleImport(_, s) => *s,
|
||||
ParseError::ModuleOrOverlayNotFound(s) => *s,
|
||||
ParseError::ActiveOverlayNotFound(s) => *s,
|
||||
ParseError::OverlayPrefixMismatch(_, _, s) => *s,
|
||||
ParseError::CantRemoveLastOverlay(s) => *s,
|
||||
ParseError::CantHideDefaultOverlay(_, s) => *s,
|
||||
ParseError::CantAddOverlayHelp(_, s) => *s,
|
||||
ParseError::NotFound(s) => *s,
|
||||
ParseError::DuplicateCommandDef(s) => *s,
|
||||
ParseError::UnknownCommand(s) => *s,
|
||||
ParseError::NonUtf8(s) => *s,
|
||||
ParseError::UnknownFlag(_, _, s, _) => *s,
|
||||
ParseError::RequiredAfterOptional(_, s) => *s,
|
||||
ParseError::UnknownType(s) => *s,
|
||||
ParseError::MissingFlagParam(_, s) => *s,
|
||||
ParseError::ShortFlagBatchCantTakeArg(s) => *s,
|
||||
ParseError::MissingPositional(_, s, _) => *s,
|
||||
ParseError::KeywordMissingArgument(_, _, s) => *s,
|
||||
ParseError::MissingType(s) => *s,
|
||||
ParseError::TypeMismatch(_, _, s) => *s,
|
||||
ParseError::MissingRequiredFlag(_, s) => *s,
|
||||
ParseError::IncompleteMathExpression(s) => *s,
|
||||
ParseError::UnknownState(_, s) => *s,
|
||||
ParseError::InternalError(_, s) => *s,
|
||||
ParseError::IncompleteParser(s) => *s,
|
||||
ParseError::RestNeedsName(s) => *s,
|
||||
ParseError::ParameterMismatchType(_, _, _, s) => *s,
|
||||
ParseError::ExtraColumns(_, s) => *s,
|
||||
ParseError::MissingColumns(_, s) => *s,
|
||||
ParseError::AssignmentMismatch(_, _, s) => *s,
|
||||
ParseError::MissingImportPattern(s) => *s,
|
||||
ParseError::WrongImportPattern(s) => *s,
|
||||
ParseError::ExportNotFound(s) => *s,
|
||||
ParseError::SourcedFileNotFound(_, s) => *s,
|
||||
ParseError::RegisteredFileNotFound(_, s) => *s,
|
||||
ParseError::FileNotFound(_, s) => *s,
|
||||
ParseError::ReadingFile(_, s) => *s,
|
||||
ParseError::LabeledError(_, _, s) => *s,
|
||||
ParseError::ShellAndAnd(s) => *s,
|
||||
ParseError::ShellOrOr(s) => *s,
|
||||
ParseError::ShellErrRedirect(s) => *s,
|
||||
ParseError::ShellOutErrRedirect(s) => *s,
|
||||
ParseError::UnknownOperator(_, _, s) => *s,
|
||||
ParseError::InvalidLiteral(_, _, s) => *s,
|
||||
ParseError::NotAConstant(s) => *s,
|
||||
ParseError::ClosureMissingPipe(s) => *s,
|
||||
}
|
||||
}
|
||||
}
|
@ -1,8 +1,7 @@
|
||||
use crate::ParseError;
|
||||
use nu_protocol::{
|
||||
ast::{Expr, Expression},
|
||||
engine::StateWorkingSet,
|
||||
Span, Value,
|
||||
ParseError, Span, Value,
|
||||
};
|
||||
|
||||
/// Evaluate a constant value at parse time
|
||||
|
@ -1,5 +1,4 @@
|
||||
use crate::ParseError;
|
||||
use nu_protocol::Span;
|
||||
use nu_protocol::{ParseError, Span};
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||
pub enum TokenContents {
|
||||
|
@ -1,5 +1,4 @@
|
||||
mod deparse;
|
||||
mod errors;
|
||||
mod eval;
|
||||
mod flatten;
|
||||
mod known_external;
|
||||
@ -11,7 +10,6 @@ mod parser;
|
||||
mod type_check;
|
||||
|
||||
pub use deparse::{escape_for_script_arg, escape_quote_string};
|
||||
pub use errors::ParseError;
|
||||
pub use flatten::{
|
||||
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
|
||||
/// 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)]
|
||||
pub struct LiteCommand {
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,13 +1,13 @@
|
||||
use nu_protocol::{
|
||||
ast::{Expr, Expression, MatchPattern, Pattern},
|
||||
engine::StateWorkingSet,
|
||||
Span, SyntaxShape, Type, VarId,
|
||||
ParseError, Span, SyntaxShape, Type, VarId,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
lex, lite_parse,
|
||||
parser::{is_variable, parse_value},
|
||||
LiteElement, ParseError,
|
||||
LiteElement,
|
||||
};
|
||||
|
||||
pub fn garbage(span: Span) -> MatchPattern {
|
||||
@ -17,29 +17,20 @@ pub fn garbage(span: Span) -> MatchPattern {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_match_pattern(
|
||||
working_set: &mut StateWorkingSet,
|
||||
span: Span,
|
||||
) -> (Expression, Option<ParseError>) {
|
||||
pub fn parse_match_pattern(working_set: &mut StateWorkingSet, span: Span) -> Expression {
|
||||
working_set.enter_scope();
|
||||
let (output, err) = parse_pattern(working_set, span);
|
||||
let output = parse_pattern(working_set, span);
|
||||
working_set.exit_scope();
|
||||
|
||||
(
|
||||
Expression {
|
||||
expr: Expr::MatchPattern(Box::new(output)),
|
||||
span,
|
||||
ty: Type::Any,
|
||||
custom_completion: None,
|
||||
},
|
||||
err,
|
||||
)
|
||||
Expression {
|
||||
expr: Expr::MatchPattern(Box::new(output)),
|
||||
span,
|
||||
ty: Type::Any,
|
||||
custom_completion: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_pattern(
|
||||
working_set: &mut StateWorkingSet,
|
||||
span: Span,
|
||||
) -> (MatchPattern, Option<ParseError>) {
|
||||
pub fn parse_pattern(working_set: &mut StateWorkingSet, span: Span) -> MatchPattern {
|
||||
let bytes = working_set.get_span_contents(span);
|
||||
|
||||
if bytes.starts_with(b"$") {
|
||||
@ -52,23 +43,18 @@ pub fn parse_pattern(
|
||||
// List pattern
|
||||
parse_list_pattern(working_set, span)
|
||||
} else if bytes == b"_" {
|
||||
(
|
||||
MatchPattern {
|
||||
pattern: Pattern::IgnoreValue,
|
||||
span,
|
||||
},
|
||||
None,
|
||||
)
|
||||
MatchPattern {
|
||||
pattern: Pattern::IgnoreValue,
|
||||
span,
|
||||
}
|
||||
} else {
|
||||
// Literal value
|
||||
let (value, error) = parse_value(working_set, span, &SyntaxShape::Any, &[]);
|
||||
(
|
||||
MatchPattern {
|
||||
pattern: Pattern::Value(value),
|
||||
span,
|
||||
},
|
||||
error,
|
||||
)
|
||||
let value = parse_value(working_set, span, &SyntaxShape::Any, &[]);
|
||||
|
||||
MatchPattern {
|
||||
pattern: Pattern::Value(value),
|
||||
span,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -88,34 +74,21 @@ fn parse_variable_pattern_helper(working_set: &mut StateWorkingSet, span: Span)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_variable_pattern(
|
||||
working_set: &mut StateWorkingSet,
|
||||
span: Span,
|
||||
) -> (MatchPattern, Option<ParseError>) {
|
||||
pub fn parse_variable_pattern(working_set: &mut StateWorkingSet, span: Span) -> MatchPattern {
|
||||
if let Some(var_id) = parse_variable_pattern_helper(working_set, span) {
|
||||
(
|
||||
MatchPattern {
|
||||
pattern: Pattern::Variable(var_id),
|
||||
span,
|
||||
},
|
||||
None,
|
||||
)
|
||||
MatchPattern {
|
||||
pattern: Pattern::Variable(var_id),
|
||||
span,
|
||||
}
|
||||
} else {
|
||||
(
|
||||
garbage(span),
|
||||
Some(ParseError::Expected("valid variable name".into(), span)),
|
||||
)
|
||||
working_set.error(ParseError::Expected("valid variable name".into(), span));
|
||||
garbage(span)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_list_pattern(
|
||||
working_set: &mut StateWorkingSet,
|
||||
span: Span,
|
||||
) -> (MatchPattern, Option<ParseError>) {
|
||||
pub fn parse_list_pattern(working_set: &mut StateWorkingSet, span: Span) -> MatchPattern {
|
||||
let bytes = working_set.get_span_contents(span);
|
||||
|
||||
let mut error = None;
|
||||
|
||||
let mut start = span.start;
|
||||
let mut end = span.end;
|
||||
|
||||
@ -125,17 +98,21 @@ pub fn parse_list_pattern(
|
||||
if bytes.ends_with(b"]") {
|
||||
end -= 1;
|
||||
} 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 source = working_set.get_span_contents(inner_span);
|
||||
|
||||
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);
|
||||
error = error.or(err);
|
||||
if let Some(err) = err {
|
||||
working_set.error(err);
|
||||
}
|
||||
|
||||
let mut args = vec![];
|
||||
|
||||
@ -167,14 +144,13 @@ pub fn parse_list_pattern(
|
||||
break;
|
||||
} else {
|
||||
args.push(garbage(command.parts[spans_idx]));
|
||||
error = error.or(Some(ParseError::Expected(
|
||||
working_set.error(ParseError::Expected(
|
||||
"valid variable name".into(),
|
||||
command.parts[spans_idx],
|
||||
)));
|
||||
));
|
||||
}
|
||||
} else {
|
||||
let (arg, err) = parse_pattern(working_set, command.parts[spans_idx]);
|
||||
error = error.or(err);
|
||||
let arg = parse_pattern(working_set, command.parts[spans_idx]);
|
||||
|
||||
args.push(arg);
|
||||
};
|
||||
@ -185,47 +161,41 @@ pub fn parse_list_pattern(
|
||||
}
|
||||
}
|
||||
|
||||
(
|
||||
MatchPattern {
|
||||
pattern: Pattern::List(args),
|
||||
span,
|
||||
},
|
||||
error,
|
||||
)
|
||||
MatchPattern {
|
||||
pattern: Pattern::List(args),
|
||||
span,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_record_pattern(
|
||||
working_set: &mut StateWorkingSet,
|
||||
span: Span,
|
||||
) -> (MatchPattern, Option<ParseError>) {
|
||||
let bytes = working_set.get_span_contents(span);
|
||||
pub fn parse_record_pattern(working_set: &mut StateWorkingSet, span: Span) -> MatchPattern {
|
||||
let mut bytes = working_set.get_span_contents(span);
|
||||
|
||||
let mut error = None;
|
||||
let mut start = span.start;
|
||||
let mut end = span.end;
|
||||
|
||||
if bytes.starts_with(b"{") {
|
||||
start += 1;
|
||||
} else {
|
||||
error = error.or_else(|| {
|
||||
Some(ParseError::Expected(
|
||||
"{".into(),
|
||||
Span::new(start, start + 1),
|
||||
))
|
||||
});
|
||||
working_set.error(ParseError::Expected(
|
||||
"{".into(),
|
||||
Span::new(start, start + 1),
|
||||
));
|
||||
bytes = working_set.get_span_contents(span);
|
||||
}
|
||||
|
||||
if bytes.ends_with(b"}") {
|
||||
end -= 1;
|
||||
} 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 source = working_set.get_span_contents(inner_span);
|
||||
|
||||
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 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
|
||||
let field = String::from_utf8_lossy(&bytes[1..]).to_string();
|
||||
|
||||
let (pattern, err) = parse_variable_pattern(working_set, tokens[idx].span);
|
||||
error = error.or(err);
|
||||
let pattern = parse_variable_pattern(working_set, tokens[idx].span);
|
||||
|
||||
(field, pattern)
|
||||
} else {
|
||||
@ -245,22 +214,17 @@ pub fn parse_record_pattern(
|
||||
|
||||
idx += 1;
|
||||
if idx == tokens.len() {
|
||||
return (
|
||||
garbage(span),
|
||||
Some(ParseError::Expected("record".into(), span)),
|
||||
);
|
||||
working_set.error(ParseError::Expected("record".into(), span));
|
||||
return garbage(span);
|
||||
}
|
||||
let colon = working_set.get_span_contents(tokens[idx].span);
|
||||
idx += 1;
|
||||
if idx == tokens.len() || colon != b":" {
|
||||
//FIXME: need better error
|
||||
return (
|
||||
garbage(span),
|
||||
Some(ParseError::Expected("record".into(), span)),
|
||||
);
|
||||
working_set.error(ParseError::Expected("record".into(), span));
|
||||
return garbage(span);
|
||||
}
|
||||
let (pattern, err) = parse_pattern(working_set, tokens[idx].span);
|
||||
error = error.or(err);
|
||||
let pattern = parse_pattern(working_set, tokens[idx].span);
|
||||
|
||||
(field, pattern)
|
||||
};
|
||||
@ -269,11 +233,8 @@ pub fn parse_record_pattern(
|
||||
output.push((field, pattern));
|
||||
}
|
||||
|
||||
(
|
||||
MatchPattern {
|
||||
pattern: Pattern::Record(output),
|
||||
span,
|
||||
},
|
||||
error,
|
||||
)
|
||||
MatchPattern {
|
||||
pattern: Pattern::Record(output),
|
||||
span,
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,8 +1,7 @@
|
||||
use crate::ParseError;
|
||||
use nu_protocol::{
|
||||
ast::{Bits, Boolean, Comparison, Expr, Expression, Math, Operator},
|
||||
engine::StateWorkingSet,
|
||||
Type,
|
||||
ParseError, Type,
|
||||
};
|
||||
|
||||
pub fn type_compatible(lhs: &Type, rhs: &Type) -> bool {
|
||||
|
@ -1,5 +1,5 @@
|
||||
use nu_parser::{lex, lex_signature, ParseError, Token, TokenContents};
|
||||
use nu_protocol::Span;
|
||||
use nu_parser::{lex, lex_signature, Token, TokenContents};
|
||||
use nu_protocol::{ParseError, Span};
|
||||
|
||||
#[test]
|
||||
fn lex_basic() {
|
||||
|
@ -1,11 +1,10 @@
|
||||
use nu_parser::ParseError;
|
||||
use nu_parser::*;
|
||||
use nu_protocol::ast::{Call, PathMember};
|
||||
use nu_protocol::Span;
|
||||
use nu_protocol::{
|
||||
ast::{Expr, Expression, PipelineElement},
|
||||
engine::{Command, EngineState, Stack, StateWorkingSet},
|
||||
PipelineData, ShellError, Signature, SyntaxShape,
|
||||
ParseError, PipelineData, ShellError, Signature, SyntaxShape,
|
||||
};
|
||||
|
||||
#[cfg(test)]
|
||||
@ -53,7 +52,9 @@ fn test_int(
|
||||
let engine_state = EngineState::new();
|
||||
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(parse_err) = err {
|
||||
@ -265,9 +266,9 @@ fn test_parse_any() {
|
||||
let engine_state = EngineState::new();
|
||||
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)) => {
|
||||
println!("test: {test:?}, error: {e:#?}");
|
||||
}
|
||||
@ -281,9 +282,9 @@ pub fn parse_int() {
|
||||
let engine_state = EngineState::new();
|
||||
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);
|
||||
let expressions = &block[0];
|
||||
assert_eq!(expressions.len(), 1);
|
||||
@ -304,9 +305,9 @@ pub fn parse_int_with_underscores() {
|
||||
let engine_state = EngineState::new();
|
||||
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);
|
||||
let expressions = &block[0];
|
||||
assert_eq!(expressions.len(), 1);
|
||||
@ -334,9 +335,9 @@ pub fn parse_cell_path() {
|
||||
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);
|
||||
let expressions = &block[0];
|
||||
assert_eq!(expressions.len(), 1);
|
||||
@ -388,12 +389,9 @@ pub fn parse_cell_path_optional() {
|
||||
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 {
|
||||
dbg!(err);
|
||||
panic!();
|
||||
}
|
||||
assert!(working_set.parse_errors.is_empty());
|
||||
|
||||
assert_eq!(block.len(), 1);
|
||||
let expressions = &block[0];
|
||||
@ -439,9 +437,9 @@ pub fn parse_binary_with_hex_format() {
|
||||
let engine_state = EngineState::new();
|
||||
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);
|
||||
let expressions = &block[0];
|
||||
assert_eq!(expressions.len(), 1);
|
||||
@ -457,9 +455,9 @@ pub fn parse_binary_with_incomplete_hex_format() {
|
||||
let engine_state = EngineState::new();
|
||||
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);
|
||||
let expressions = &block[0];
|
||||
assert_eq!(expressions.len(), 1);
|
||||
@ -475,9 +473,9 @@ pub fn parse_binary_with_binary_format() {
|
||||
let engine_state = EngineState::new();
|
||||
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);
|
||||
let expressions = &block[0];
|
||||
assert_eq!(expressions.len(), 1);
|
||||
@ -493,9 +491,9 @@ pub fn parse_binary_with_incomplete_binary_format() {
|
||||
let engine_state = EngineState::new();
|
||||
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);
|
||||
let expressions = &block[0];
|
||||
assert_eq!(expressions.len(), 1);
|
||||
@ -511,9 +509,9 @@ pub fn parse_binary_with_octal_format() {
|
||||
let engine_state = EngineState::new();
|
||||
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);
|
||||
let expressions = &block[0];
|
||||
assert_eq!(expressions.len(), 1);
|
||||
@ -529,9 +527,9 @@ pub fn parse_binary_with_incomplete_octal_format() {
|
||||
let engine_state = EngineState::new();
|
||||
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);
|
||||
let expressions = &block[0];
|
||||
assert_eq!(expressions.len(), 1);
|
||||
@ -547,9 +545,9 @@ pub fn parse_binary_with_invalid_octal_format() {
|
||||
let engine_state = EngineState::new();
|
||||
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);
|
||||
let expressions = &block[0];
|
||||
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
|
||||
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);
|
||||
let expressions = &block[0];
|
||||
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'));
|
||||
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);
|
||||
|
||||
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'));
|
||||
working_set.add_decl(sig.predeclare());
|
||||
|
||||
let (_, err) = parse(&mut working_set, None, b"foo --jazz", true, &[]);
|
||||
assert!(matches!(err, Some(ParseError::MissingFlagParam(..))));
|
||||
parse(&mut working_set, None, b"foo --jazz", true, &[]);
|
||||
assert!(matches!(
|
||||
working_set.parse_errors.first(),
|
||||
Some(ParseError::MissingFlagParam(..))
|
||||
));
|
||||
}
|
||||
|
||||
#[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'));
|
||||
working_set.add_decl(sig.predeclare());
|
||||
|
||||
let (_, err) = parse(&mut working_set, None, b"foo -j", true, &[]);
|
||||
assert!(matches!(err, Some(ParseError::MissingFlagParam(..))));
|
||||
parse(&mut working_set, None, b"foo -j", true, &[]);
|
||||
assert!(matches!(
|
||||
working_set.parse_errors.first(),
|
||||
Some(ParseError::MissingFlagParam(..))
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -641,9 +645,9 @@ pub fn parse_call_too_many_shortflag_args() {
|
||||
.named("--jazz", SyntaxShape::Int, "jazz!!", Some('j'))
|
||||
.named("--math", SyntaxShape::Int, "math!!", Some('m'));
|
||||
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,
|
||||
working_set.parse_errors.first(),
|
||||
Some(ParseError::ShortFlagBatchCantTakeArg(..))
|
||||
));
|
||||
}
|
||||
@ -655,8 +659,11 @@ pub fn parse_call_unknown_shorthand() {
|
||||
|
||||
let sig = Signature::build("foo").switch("--jazz", "jazz!!", Some('j'));
|
||||
working_set.add_decl(sig.predeclare());
|
||||
let (_, err) = parse(&mut working_set, None, b"foo -mj", true, &[]);
|
||||
assert!(matches!(err, Some(ParseError::UnknownFlag(..))));
|
||||
parse(&mut working_set, None, b"foo -mj", true, &[]);
|
||||
assert!(matches!(
|
||||
working_set.parse_errors.first(),
|
||||
Some(ParseError::UnknownFlag(..))
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -666,8 +673,11 @@ pub fn parse_call_extra_positional() {
|
||||
|
||||
let sig = Signature::build("foo").switch("--jazz", "jazz!!", Some('j'));
|
||||
working_set.add_decl(sig.predeclare());
|
||||
let (_, err) = parse(&mut working_set, None, b"foo -j 100", true, &[]);
|
||||
assert!(matches!(err, Some(ParseError::ExtraPositional(..))));
|
||||
parse(&mut working_set, None, b"foo -j 100", true, &[]);
|
||||
assert!(matches!(
|
||||
working_set.parse_errors.first(),
|
||||
Some(ParseError::ExtraPositional(..))
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -677,8 +687,11 @@ pub fn parse_call_missing_req_positional() {
|
||||
|
||||
let sig = Signature::build("foo").required("jazz", SyntaxShape::Int, "jazz!!");
|
||||
working_set.add_decl(sig.predeclare());
|
||||
let (_, err) = parse(&mut working_set, None, b"foo", true, &[]);
|
||||
assert!(matches!(err, Some(ParseError::MissingPositional(..))));
|
||||
parse(&mut working_set, None, b"foo", true, &[]);
|
||||
assert!(matches!(
|
||||
working_set.parse_errors.first(),
|
||||
Some(ParseError::MissingPositional(..))
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -688,17 +701,20 @@ pub fn parse_call_missing_req_flag() {
|
||||
|
||||
let sig = Signature::build("foo").required_named("--jazz", SyntaxShape::Int, "jazz!!", None);
|
||||
working_set.add_decl(sig.predeclare());
|
||||
let (_, err) = parse(&mut working_set, None, b"foo", true, &[]);
|
||||
assert!(matches!(err, Some(ParseError::MissingRequiredFlag(..))));
|
||||
parse(&mut working_set, None, b"foo", true, &[]);
|
||||
assert!(matches!(
|
||||
working_set.parse_errors.first(),
|
||||
Some(ParseError::MissingRequiredFlag(..))
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_nothing_comparison_eq() {
|
||||
let engine_state = EngineState::new();
|
||||
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);
|
||||
|
||||
let expressions = &block[0];
|
||||
@ -719,9 +735,9 @@ fn test_nothing_comparison_eq() {
|
||||
fn test_nothing_comparison_neq() {
|
||||
let engine_state = EngineState::new();
|
||||
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);
|
||||
|
||||
let expressions = &block[0];
|
||||
@ -746,9 +762,9 @@ mod string {
|
||||
let engine_state = EngineState::new();
|
||||
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);
|
||||
let expressions = &block[0];
|
||||
assert_eq!(expressions.len(), 1);
|
||||
@ -769,9 +785,9 @@ mod string {
|
||||
let engine_state = EngineState::new();
|
||||
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);
|
||||
|
||||
let expressions = &block[0];
|
||||
@ -801,9 +817,9 @@ mod string {
|
||||
let engine_state = EngineState::new();
|
||||
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);
|
||||
let expressions = &block[0];
|
||||
@ -832,7 +848,7 @@ mod string {
|
||||
let engine_state = EngineState::new();
|
||||
let mut working_set = StateWorkingSet::new(&engine_state);
|
||||
|
||||
let (block, err) = parse(
|
||||
let block = parse(
|
||||
&mut working_set,
|
||||
None,
|
||||
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);
|
||||
let expressions = &block[0];
|
||||
@ -871,7 +887,7 @@ mod string {
|
||||
let engine_state = EngineState::new();
|
||||
let mut working_set = StateWorkingSet::new(&engine_state);
|
||||
|
||||
let (block, err) = parse(
|
||||
let block = parse(
|
||||
&mut working_set,
|
||||
None,
|
||||
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);
|
||||
let expressions = &block[0];
|
||||
@ -914,7 +930,7 @@ mod string {
|
||||
false,
|
||||
);
|
||||
|
||||
let (_block, err) = parse(
|
||||
parse(
|
||||
&mut working_set,
|
||||
None,
|
||||
br#"
|
||||
@ -924,7 +940,7 @@ mod string {
|
||||
&[],
|
||||
);
|
||||
|
||||
assert!(err.is_none());
|
||||
assert!(working_set.parse_errors.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -939,7 +955,7 @@ mod string {
|
||||
false,
|
||||
);
|
||||
|
||||
let (_block, err) = parse(
|
||||
parse(
|
||||
&mut working_set,
|
||||
None,
|
||||
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 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);
|
||||
|
||||
let expressions = &block[0];
|
||||
@ -995,9 +1011,9 @@ mod range {
|
||||
let engine_state = EngineState::new();
|
||||
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);
|
||||
|
||||
let expressions = &block[0];
|
||||
@ -1027,9 +1043,9 @@ mod range {
|
||||
let engine_state = EngineState::new();
|
||||
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);
|
||||
|
||||
let expressions = &block[0];
|
||||
@ -1059,9 +1075,9 @@ mod range {
|
||||
let engine_state = EngineState::new();
|
||||
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);
|
||||
|
||||
let expressions = &block[0];
|
||||
@ -1093,9 +1109,9 @@ mod range {
|
||||
|
||||
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);
|
||||
|
||||
let expressions = &block[1];
|
||||
@ -1127,7 +1143,7 @@ mod range {
|
||||
|
||||
working_set.add_decl(Box::new(Let));
|
||||
|
||||
let (block, err) = parse(
|
||||
let block = parse(
|
||||
&mut working_set,
|
||||
None,
|
||||
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);
|
||||
|
||||
let expressions = &block[1];
|
||||
@ -1165,9 +1181,9 @@ mod range {
|
||||
let engine_state = EngineState::new();
|
||||
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);
|
||||
|
||||
let expressions = &block[0];
|
||||
@ -1197,9 +1213,9 @@ mod range {
|
||||
let engine_state = EngineState::new();
|
||||
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);
|
||||
|
||||
let expressions = &block[0];
|
||||
@ -1229,9 +1245,9 @@ mod range {
|
||||
let engine_state = EngineState::new();
|
||||
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);
|
||||
|
||||
let expressions = &block[0];
|
||||
@ -1261,9 +1277,9 @@ mod range {
|
||||
let engine_state = EngineState::new();
|
||||
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);
|
||||
|
||||
let expressions = &block[0];
|
||||
@ -1293,9 +1309,9 @@ mod range {
|
||||
let engine_state = EngineState::new();
|
||||
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 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);
|
||||
|
||||
let expressions = &block[0];
|
||||
@ -1680,9 +1696,9 @@ mod input_types {
|
||||
let input =
|
||||
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);
|
||||
|
||||
let expressions = &block[2];
|
||||
@ -1711,9 +1727,9 @@ mod input_types {
|
||||
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 (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);
|
||||
|
||||
let expressions = &block[1];
|
||||
@ -1743,9 +1759,9 @@ mod input_types {
|
||||
let input = r#"
|
||||
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);
|
||||
|
||||
let expressions = &block[1];
|
||||
@ -1787,9 +1803,9 @@ mod input_types {
|
||||
let mut working_set = StateWorkingSet::new(&engine_state);
|
||||
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);
|
||||
|
||||
let expressions = &block[0];
|
||||
@ -1832,7 +1848,7 @@ mod input_types {
|
||||
let (block, delta) = {
|
||||
let mut working_set = StateWorkingSet::new(&engine_state);
|
||||
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())
|
||||
};
|
||||
@ -1893,9 +1909,9 @@ mod input_types {
|
||||
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 (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);
|
||||
|
||||
let expressions = &block[0];
|
||||
@ -1947,9 +1963,9 @@ mod input_types {
|
||||
];
|
||||
|
||||
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}");
|
||||
}
|
||||
}
|
||||
@ -1960,7 +1976,7 @@ mod input_types {
|
||||
add_declarations(&mut engine_state);
|
||||
|
||||
let mut working_set = StateWorkingSet::new(&engine_state);
|
||||
let (_, err) = parse(
|
||||
parse(
|
||||
&mut working_set,
|
||||
None,
|
||||
b"if false { 'a' } else { $foo }",
|
||||
@ -1968,9 +1984,10 @@ mod input_types {
|
||||
&[],
|
||||
);
|
||||
|
||||
let err = err.unwrap();
|
||||
|
||||
assert!(matches!(err, ParseError::VariableNotFound(_)));
|
||||
assert!(matches!(
|
||||
working_set.parse_errors.first(),
|
||||
Some(ParseError::VariableNotFound(_))
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -1979,7 +1996,7 @@ mod input_types {
|
||||
add_declarations(&mut engine_state);
|
||||
|
||||
let mut working_set = StateWorkingSet::new(&engine_state);
|
||||
let (_, err) = parse(
|
||||
parse(
|
||||
&mut working_set,
|
||||
None,
|
||||
b"if false { 'a' } else $foo { 'b' }",
|
||||
@ -1987,8 +2004,9 @@ mod input_types {
|
||||
&[],
|
||||
);
|
||||
|
||||
let err = err.unwrap();
|
||||
|
||||
assert!(matches!(err, ParseError::VariableNotFound(_)));
|
||||
assert!(matches!(
|
||||
working_set.parse_errors.first(),
|
||||
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 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 => {
|
||||
assert_eq!(block.len(), 1);
|
||||
let expressions = &block[0];
|
||||
|
Reference in New Issue
Block a user