From 34fce3ca9d0efddd22a9df7df2b53d027c580d36 Mon Sep 17 00:00:00 2001 From: Yuya Nishihara Date: Sat, 4 May 2024 16:55:05 +0900 Subject: [PATCH] cli: extract functions that map fileset/revset/template errors to hints --- cli/src/command_error.rs | 138 ++++++++++++++++++++++----------------- 1 file changed, 78 insertions(+), 60 deletions(-) diff --git a/cli/src/command_error.rs b/cli/src/command_error.rs index c1a740bb3..d30de4fa1 100644 --- a/cli/src/command_error.rs +++ b/cli/src/command_error.rs @@ -433,15 +433,7 @@ impl From for CommandError { impl From for CommandError { fn from(err: FilesetParseError) -> Self { - let hint = match err.kind() { - FilesetParseErrorKind::NoSuchFunction { - name: _, - candidates, - } => format_similarity_hint(candidates), - FilesetParseErrorKind::InvalidArguments { .. } - | FilesetParseErrorKind::Expression(_) => find_source_parse_error_hint(&err), - _ => None, - }; + let hint = fileset_parse_error_hint(&err); let mut cmd_err = user_error_with_message(format!("Failed to parse fileset: {}", err.kind()), err); cmd_err.extend_hints(hint); @@ -451,33 +443,7 @@ impl From for CommandError { impl From for CommandError { fn from(err: RevsetParseError) -> Self { - // Only for the bottom error, which is usually the root cause - let bottom_err = iter::successors(Some(&err), |e| e.origin()).last().unwrap(); - let hint = match bottom_err.kind() { - RevsetParseErrorKind::NotPrefixOperator { - op: _, - similar_op, - description, - } - | RevsetParseErrorKind::NotPostfixOperator { - op: _, - similar_op, - description, - } - | RevsetParseErrorKind::NotInfixOperator { - op: _, - similar_op, - description, - } => Some(format!("Did you mean '{similar_op}' for {description}?")), - RevsetParseErrorKind::NoSuchFunction { - name: _, - candidates, - } => format_similarity_hint(candidates), - RevsetParseErrorKind::InvalidFunctionArguments { .. } => { - find_source_parse_error_hint(bottom_err) - } - _ => None, - }; + let hint = revset_parse_error_hint(&err); let mut cmd_err = user_error_with_message(format!("Failed to parse revset: {}", err.kind()), err); cmd_err.extend_hints(hint); @@ -487,18 +453,7 @@ impl From for CommandError { impl From for CommandError { fn from(err: RevsetResolutionError) -> Self { - let hint = match &err { - RevsetResolutionError::NoSuchRevision { - name: _, - candidates, - } => format_similarity_hint(candidates), - RevsetResolutionError::EmptyString - | RevsetResolutionError::WorkspaceMissingWorkingCopy { .. } - | RevsetResolutionError::AmbiguousCommitIdPrefix(_) - | RevsetResolutionError::AmbiguousChangeIdPrefix(_) - | RevsetResolutionError::StoreError(_) - | RevsetResolutionError::Other(_) => None, - }; + let hint = revset_resolution_error_hint(&err); let mut cmd_err = user_error(err); cmd_err.extend_hints(hint); cmd_err @@ -516,18 +471,7 @@ impl From for CommandError { impl From for CommandError { fn from(err: TemplateParseError) -> Self { - // Only for the bottom error, which is usually the root cause - let bottom_err = iter::successors(Some(&err), |e| e.origin()).last().unwrap(); - let hint = match bottom_err.kind() { - TemplateParseErrorKind::NoSuchKeyword { candidates, .. } - | TemplateParseErrorKind::NoSuchFunction { candidates, .. } - | TemplateParseErrorKind::NoSuchMethod { candidates, .. } => { - format_similarity_hint(candidates) - } - TemplateParseErrorKind::InvalidArguments { .. } - | TemplateParseErrorKind::Expression(_) => find_source_parse_error_hint(bottom_err), - _ => None, - }; + let hint = template_parse_error_hint(&err); let mut cmd_err = user_error_with_message(format!("Failed to parse template: {}", err.kind()), err); cmd_err.extend_hints(hint); @@ -591,6 +535,64 @@ fn file_pattern_parse_error_hint(err: &FilePatternParseError) -> Option } } +fn fileset_parse_error_hint(err: &FilesetParseError) -> Option { + match err.kind() { + FilesetParseErrorKind::NoSuchFunction { + name: _, + candidates, + } => format_similarity_hint(candidates), + FilesetParseErrorKind::InvalidArguments { .. } | FilesetParseErrorKind::Expression(_) => { + find_source_parse_error_hint(&err) + } + _ => None, + } +} + +fn revset_parse_error_hint(err: &RevsetParseError) -> Option { + // Only for the bottom error, which is usually the root cause + let bottom_err = iter::successors(Some(err), |e| e.origin()).last().unwrap(); + match bottom_err.kind() { + RevsetParseErrorKind::NotPrefixOperator { + op: _, + similar_op, + description, + } + | RevsetParseErrorKind::NotPostfixOperator { + op: _, + similar_op, + description, + } + | RevsetParseErrorKind::NotInfixOperator { + op: _, + similar_op, + description, + } => Some(format!("Did you mean '{similar_op}' for {description}?")), + RevsetParseErrorKind::NoSuchFunction { + name: _, + candidates, + } => format_similarity_hint(candidates), + RevsetParseErrorKind::InvalidFunctionArguments { .. } => { + find_source_parse_error_hint(bottom_err) + } + _ => None, + } +} + +fn revset_resolution_error_hint(err: &RevsetResolutionError) -> Option { + match err { + RevsetResolutionError::NoSuchRevision { + name: _, + candidates, + } => format_similarity_hint(candidates), + RevsetResolutionError::EmptyString + | RevsetResolutionError::WorkspaceMissingWorkingCopy { .. } + | RevsetResolutionError::AmbiguousCommitIdPrefix(_) + | RevsetResolutionError::AmbiguousChangeIdPrefix(_) + | RevsetResolutionError::StoreError(_) + | RevsetResolutionError::Other(_) => None, + } +} + fn string_pattern_parse_error_hint(err: &StringPatternParseError) -> Option { match err { StringPatternParseError::InvalidKind(_) => { @@ -600,6 +602,22 @@ fn string_pattern_parse_error_hint(err: &StringPatternParseError) -> Option Option { + // Only for the bottom error, which is usually the root cause + let bottom_err = iter::successors(Some(err), |e| e.origin()).last().unwrap(); + match bottom_err.kind() { + TemplateParseErrorKind::NoSuchKeyword { candidates, .. } + | TemplateParseErrorKind::NoSuchFunction { candidates, .. } + | TemplateParseErrorKind::NoSuchMethod { candidates, .. } => { + format_similarity_hint(candidates) + } + TemplateParseErrorKind::InvalidArguments { .. } | TemplateParseErrorKind::Expression(_) => { + find_source_parse_error_hint(bottom_err) + } + _ => None, + } +} + const BROKEN_PIPE_EXIT_CODE: u8 = 3; pub(crate) fn handle_command_result(ui: &mut Ui, result: Result<(), CommandError>) -> ExitCode {