diff --git a/cli/tests/test_log_command.rs b/cli/tests/test_log_command.rs index 37505865e..e7bdcc88e 100644 --- a/cli/tests/test_log_command.rs +++ b/cli/tests/test_log_command.rs @@ -454,16 +454,16 @@ fn test_log_bad_short_prefixes() { test_env.add_config(r#"revsets.short-prefixes = "!nval!d""#); let stderr = test_env.jj_cmd_failure(&repo_path, &["status"]); insta::assert_snapshot!(stderr, - @r###" + @r" Config error: Invalid `revsets.short-prefixes` Caused by: --> 1:1 | 1 | !nval!d | ^--- | - = expected or + = expected or For help, see https://jj-vcs.github.io/jj/latest/config/. - "###); + "); // Warn on resolution of short prefixes test_env.add_config("revsets.short-prefixes = 'missing'"); diff --git a/cli/tests/test_revset_output.rs b/cli/tests/test_revset_output.rs index dbcc4f584..385bfc3e6 100644 --- a/cli/tests/test_revset_output.rs +++ b/cli/tests/test_revset_output.rs @@ -266,15 +266,15 @@ fn test_bad_function_call() { "###); let stderr = test_env.jj_cmd_failure(&repo_path, &["log", "-r", "remote_bookmarks(=foo)"]); - insta::assert_snapshot!(stderr, @r###" + insta::assert_snapshot!(stderr, @r" Error: Failed to parse revset: Syntax error Caused by: --> 1:18 | 1 | remote_bookmarks(=foo) | ^--- | - = expected or - "###); + = expected or + "); let stderr = test_env.jj_cmd_failure(&repo_path, &["log", "-r", "remote_bookmarks(remote=)"]); insta::assert_snapshot!(stderr, @r###" @@ -601,20 +601,20 @@ fn test_bad_alias_decl() { insta::assert_snapshot!(stdout, @r###" ◆ zzzzzzzz root() 00000000 "###); - insta::assert_snapshot!(stderr, @r###" + insta::assert_snapshot!(stderr, @r#" Warning: Failed to load "revset-aliases."bad"": --> 1:1 | 1 | "bad" | ^--- | - = expected or + = expected or Warning: Failed to load "revset-aliases.badfn(a, a)": --> 1:7 | 1 | badfn(a, a) | ^--^ | = Redefinition of function parameter - "###); + "#); } #[test] diff --git a/lib/src/revset.pest b/lib/src/revset.pest index 80449743a..caed8d9cd 100644 --- a/lib/src/revset.pest +++ b/lib/src/revset.pest @@ -18,6 +18,12 @@ identifier_part = @{ (ASCII_ALPHANUMERIC | "_" | "/")+ } identifier = @{ identifier_part ~ (("." | "-" | "+") ~ identifier_part)* } +// TODO: remove "/", ".", "+" for consistency with fileset? +strict_identifier_part = @{ (ASCII_ALPHANUMERIC | "_" | "/")+ } +strict_identifier = @{ + strict_identifier_part ~ (("." | "-" | "+") ~ strict_identifier_part)* +} + symbol = _{ identifier | string_literal @@ -68,19 +74,19 @@ infix_op = _{ union_op | intersection_op | difference_op | compat_add_op | compa function = { function_name ~ "(" ~ whitespace* ~ function_arguments ~ whitespace* ~ ")" } function_name = @{ (ASCII_ALPHA | "_") ~ (ASCII_ALPHANUMERIC | "_")* } -keyword_argument = { identifier ~ whitespace* ~ "=" ~ whitespace* ~ expression } +keyword_argument = { strict_identifier ~ whitespace* ~ "=" ~ whitespace* ~ expression } argument = _{ keyword_argument | expression } function_arguments = { argument ~ (whitespace* ~ "," ~ whitespace* ~ argument)* ~ (whitespace* ~ ",")? | "" } formal_parameters = { - identifier ~ (whitespace* ~ "," ~ whitespace* ~ identifier)* ~ (whitespace* ~ ",")? + strict_identifier ~ (whitespace* ~ "," ~ whitespace* ~ strict_identifier)* ~ (whitespace* ~ ",")? | "" } // TODO: change rhs to string_literal to require quoting? #2101 -string_pattern = { identifier ~ pattern_kind_op ~ symbol } +string_pattern = { strict_identifier ~ pattern_kind_op ~ symbol } primary = { "(" ~ whitespace* ~ expression ~ whitespace* ~ ")" @@ -108,7 +114,7 @@ expression = { ~ (whitespace* ~ infix_op ~ whitespace* ~ (negate_op ~ whitespace*)* ~ range_expression)* } -program_modifier = { identifier ~ pattern_kind_op ~ !":" } +program_modifier = { strict_identifier ~ pattern_kind_op ~ !":" } program = _{ SOI ~ whitespace* ~ (program_modifier ~ whitespace*)? ~ expression ~ whitespace* ~ EOI } @@ -117,5 +123,5 @@ function_alias_declaration = { function_name ~ "(" ~ whitespace* ~ formal_parameters ~ whitespace* ~ ")" } alias_declaration = _{ - SOI ~ (function_alias_declaration | identifier) ~ EOI + SOI ~ (function_alias_declaration | strict_identifier) ~ EOI } diff --git a/lib/src/revset_parser.rs b/lib/src/revset_parser.rs index 95d12c224..7c3b5282d 100644 --- a/lib/src/revset_parser.rs +++ b/lib/src/revset_parser.rs @@ -58,7 +58,7 @@ const FUNCTION_CALL_PARSER: FunctionCallParser = FunctionCallParser { function_name_rule: Rule::function_name, function_arguments_rule: Rule::function_arguments, keyword_argument_rule: Rule::keyword_argument, - argument_name_rule: Rule::identifier, + argument_name_rule: Rule::strict_identifier, argument_value_rule: Rule::expression, }; @@ -83,6 +83,8 @@ impl Rule { Rule::whitespace => None, Rule::identifier_part => None, Rule::identifier => None, + Rule::strict_identifier_part => None, + Rule::strict_identifier => None, Rule::symbol => None, Rule::string_escape => None, Rule::string_content_char => None, @@ -469,7 +471,7 @@ pub(super) fn parse_program(revset_str: &str) -> Result { let (lhs, op) = first.into_inner().collect_tuple().unwrap(); let rhs = pairs.next().unwrap(); - assert_eq!(lhs.as_rule(), Rule::identifier); + assert_eq!(lhs.as_rule(), Rule::strict_identifier); assert_eq!(op.as_rule(), Rule::pattern_kind_op); assert_eq!(rhs.as_rule(), Rule::expression); let span = lhs.as_span().start_pos().span(&rhs.as_span().end_pos()); @@ -629,7 +631,7 @@ fn parse_primary_node(pair: Pair) -> Result { let (lhs, op, rhs) = first.into_inner().collect_tuple().unwrap(); - assert_eq!(lhs.as_rule(), Rule::identifier); + assert_eq!(lhs.as_rule(), Rule::strict_identifier); assert_eq!(op.as_rule(), Rule::pattern_kind_op); let kind = lhs.as_str(); let value = parse_as_string_literal(rhs); @@ -691,7 +693,7 @@ impl AliasDeclarationParser for RevsetAliasParser { let mut pairs = RevsetParser::parse(Rule::alias_declaration, source)?; let first = pairs.next().unwrap(); match first.as_rule() { - Rule::identifier => Ok(AliasDeclaration::Symbol(first.as_str().to_owned())), + Rule::strict_identifier => Ok(AliasDeclaration::Symbol(first.as_str().to_owned())), Rule::function_alias_declaration => { let (name_pair, params_pair) = first.into_inner().collect_tuple().unwrap(); assert_eq!(name_pair.as_rule(), Rule::function_name); @@ -701,7 +703,7 @@ impl AliasDeclarationParser for RevsetAliasParser { let params = params_pair .into_inner() .map(|pair| match pair.as_rule() { - Rule::identifier => pair.as_str().to_owned(), + Rule::strict_identifier => pair.as_str().to_owned(), r => panic!("unexpected formal parameter rule {r:?}"), }) .collect_vec();