cli: show hint for inner fileset/revset/template errors

Note that find_source_parse_error_hint() has recursion, but it should terminate
because err.source() shouldn't have a cycle.
This commit is contained in:
Yuya Nishihara 2024-05-04 17:02:14 +09:00
parent 34fce3ca9d
commit f1fd1d8071
2 changed files with 38 additions and 4 deletions

View file

@ -516,8 +516,18 @@ fn find_source_parse_error_hint(err: &dyn error::Error) -> Option<String> {
let source = err.source()?; let source = err.source()?;
if let Some(source) = source.downcast_ref() { if let Some(source) = source.downcast_ref() {
file_pattern_parse_error_hint(source) file_pattern_parse_error_hint(source)
} else if let Some(source) = source.downcast_ref() {
fileset_parse_error_hint(source)
} else if let Some(source) = source.downcast_ref() {
revset_parse_error_hint(source)
} else if let Some(source) = source.downcast_ref() {
revset_resolution_error_hint(source)
} else if let Some(UserRevsetEvaluationError::Resolution(source)) = source.downcast_ref() {
revset_resolution_error_hint(source)
} else if let Some(source) = source.downcast_ref() { } else if let Some(source) = source.downcast_ref() {
string_pattern_parse_error_hint(source) string_pattern_parse_error_hint(source)
} else if let Some(source) = source.downcast_ref() {
template_parse_error_hint(source)
} else { } else {
None None
} }

View file

@ -742,17 +742,41 @@ fn test_log_contained_in() {
let stderr = test_env.jj_cmd_failure( let stderr = test_env.jj_cmd_failure(
&repo_path, &repo_path,
&["log", "-r::", "-T", &template_for_revset("unknown_symbol")], &["log", "-r::", "-T", &template_for_revset("author(x:'y')")],
);
insta::assert_snapshot!(stderr, @r###"
Error: Failed to parse template: Failed to parse revset
Caused by:
1: --> 5:28
|
5 | if(self.contained_in("author(x:'y')"), "[contained_in]"),
| ^-------------^
|
= Failed to parse revset
2: --> 1:8
|
1 | author(x:'y')
| ^---^
|
= Function "author": Invalid string pattern
3: Invalid string pattern kind "x:"
Hint: Try prefixing with one of `exact:`, `glob:` or `substring:`
"###);
let stderr = test_env.jj_cmd_failure(
&repo_path,
&["log", "-r::", "-T", &template_for_revset("maine")],
); );
insta::assert_snapshot!(stderr, @r###" insta::assert_snapshot!(stderr, @r###"
Error: Failed to parse template: Failed to evaluate revset Error: Failed to parse template: Failed to evaluate revset
Caused by: Caused by:
1: --> 5:28 1: --> 5:28
| |
5 | if(self.contained_in("unknown_symbol"), "[contained_in]"), 5 | if(self.contained_in("maine"), "[contained_in]"),
| ^--------------^ | ^-----^
| |
= Failed to evaluate revset = Failed to evaluate revset
2: Revision "unknown_symbol" doesn't exist 2: Revision "maine" doesn't exist
Hint: Did you mean "main"?
"###); "###);
} }