diff --git a/crates/nu-command/tests/commands/alias.rs b/crates/nu-command/tests/commands/alias.rs index d271cdeb13..645c3f6227 100644 --- a/crates/nu-command/tests/commands/alias.rs +++ b/crates/nu-command/tests/commands/alias.rs @@ -114,7 +114,19 @@ fn alias_wont_recurse2() { }) } -// Isuue https://github.com/nushell/nushell/issues/8103 +#[test] +fn alias_invalid_expression() { + let actual = nu!(r#" alias spam = 'foo' "#); + assert!(actual.err.contains("cant_alias_expression")); + + let actual = nu!(r#" alias spam = ([1 2 3] | length) "#); + assert!(actual.err.contains("cant_alias_expression")); + + let actual = nu!(r#" alias spam = 0..12 "#); + assert!(actual.err.contains("cant_alias_expression")); +} + +// Issue https://github.com/nushell/nushell/issues/8103 #[test] fn alias_multiword_name() { let actual = nu!(r#"alias `foo bar` = echo 'test'; foo bar"#); diff --git a/crates/nu-command/tests/commands/help.rs b/crates/nu-command/tests/commands/help.rs index 6789195eca..ec9df6577d 100644 --- a/crates/nu-command/tests/commands/help.rs +++ b/crates/nu-command/tests/commands/help.rs @@ -259,8 +259,8 @@ fn help_module_sorted_aliases() { "spam.nu", r#" module SPAM { - export alias z = 'z' - export alias a = 'a' + export alias z = echo 'z' + export alias a = echo 'a' } "#, )]); diff --git a/crates/nu-command/tests/commands/source_env.rs b/crates/nu-command/tests/commands/source_env.rs index bf09bf1b44..56b20d4860 100644 --- a/crates/nu-command/tests/commands/source_env.rs +++ b/crates/nu-command/tests/commands/source_env.rs @@ -274,9 +274,9 @@ fn source_env_is_scoped() { sandbox.with_files(vec![FileWithContentToBeTrimmed( "spam.nu", r#" - def no-name-similar-to-this [] { 'no-name-similar-to-this' } - alias nor-similar-to-this = 'nor-similar-to-this' - "#, + def no-name-similar-to-this [] { 'no-name-similar-to-this' } + alias nor-similar-to-this = echo 'nor-similar-to-this' + "#, )]); let inp = &[r#"source-env spam.nu"#, r#"no-name-similar-to-this"#]; diff --git a/crates/nu-parser/src/errors.rs b/crates/nu-parser/src/errors.rs index 37991cf614..af347107c6 100644 --- a/crates/nu-parser/src/errors.rs +++ b/crates/nu-parser/src/errors.rs @@ -109,6 +109,13 @@ pub enum ParseError { )] 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( @@ -434,6 +441,7 @@ impl ParseError { 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, diff --git a/crates/nu-parser/src/parse_keywords.rs b/crates/nu-parser/src/parse_keywords.rs index b8bdb87d28..28908b7286 100644 --- a/crates/nu-parser/src/parse_keywords.rs +++ b/crates/nu-parser/src/parse_keywords.rs @@ -18,13 +18,14 @@ pub const PLUGIN_DIRS_VAR: &str = "NU_PLUGIN_DIRS"; use crate::{ eval::{eval_constant, value_as_string}, + is_math_expression_like, known_external::KnownExternal, lex, lite_parser::{lite_parse, LiteCommand, LiteElement}, parser::{ - check_call, check_name, garbage, garbage_pipeline, parse, parse_call, parse_import_pattern, - parse_internal_call, parse_multispan_value, parse_signature, parse_string, parse_value, - parse_var_with_opt_type, trim_quotes, ParsedInternalCall, + check_call, check_name, garbage, garbage_pipeline, parse, parse_call, parse_expression, + parse_import_pattern, parse_internal_call, parse_multispan_value, parse_signature, + parse_string, parse_value, parse_var_with_opt_type, trim_quotes, ParsedInternalCall, }, unescape_unquote_string, ParseError, Token, TokenContents, }; @@ -798,6 +799,27 @@ pub fn parse_alias( let replacement_spans = &spans[(split_id + 2)..]; + if is_math_expression_like(working_set, replacement_spans[0], expand_aliases_denylist) { + // TODO: Maybe we need to implement a Display trait for Expression? + let (expr, _) = parse_expression( + working_set, + replacement_spans, + expand_aliases_denylist, + false, + ); + + let msg = format!("{:?}", expr.expr); + let msg_parts: Vec<&str> = msg.split('(').collect(); + + return ( + alias_pipeline, + Some(ParseError::CantAliasExpression( + msg_parts[0].to_string(), + replacement_spans[0], + )), + ); + } + let (expr, err) = parse_call( working_set, replacement_spans,