From 794d347ec68fa969ffed231d0844a59a215d2344 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartek=20Iwa=C5=84czuk?= Date: Thu, 5 Sep 2024 13:49:07 +0100 Subject: fix: add suggestion how to fix importing CJS module (#21764) ``` $ cat exports_error.js Object.defineProperty(exports, "__esModule", { value: true }); $ deno exports_error.js error: Uncaught (in promise) ReferenceError: exports is not defined Object.defineProperty(exports, "__esModule", { value: true }); ^ at file:///exports_error.js:1:23 info: Deno doesn't support CommonJS modules without `.cjs` extension. hint: Rewrite this module to ESM or change the file extension to `.cjs`. ``` --- runtime/fmt_errors.rs | 63 +++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 61 insertions(+), 2 deletions(-) (limited to 'runtime/fmt_errors.rs') diff --git a/runtime/fmt_errors.rs b/runtime/fmt_errors.rs index 4687dbd47..b2cec2a5a 100644 --- a/runtime/fmt_errors.rs +++ b/runtime/fmt_errors.rs @@ -20,6 +20,34 @@ struct IndexedErrorReference<'a> { index: usize, } +#[derive(Debug)] +enum FixSuggestionKind { + Info, + Hint, +} + +#[derive(Debug)] +pub struct FixSuggestion<'a> { + kind: FixSuggestionKind, + message: &'a str, +} + +impl<'a> FixSuggestion<'a> { + pub fn info(message: &'a str) -> Self { + Self { + kind: FixSuggestionKind::Info, + message, + } + } + + pub fn hint(message: &'a str) -> Self { + Self { + kind: FixSuggestionKind::Hint, + message, + } + } +} + struct AnsiColors; impl deno_core::error::ErrorFormat for AnsiColors { @@ -129,6 +157,7 @@ fn format_aggregated_error( index: nested_circular_reference_index, }), false, + vec![], ); for line in error_string.trim_start_matches("Uncaught ").lines() { @@ -143,6 +172,7 @@ fn format_js_error_inner( js_error: &JsError, circular: Option, include_source_code: bool, + suggestions: Vec, ) -> String { let mut s = String::new(); @@ -190,7 +220,7 @@ fn format_js_error_inner( let error_string = if is_caused_by_circular { cyan(format!("[Circular *{}]", circular.unwrap().index)).to_string() } else { - format_js_error_inner(cause, circular, false) + format_js_error_inner(cause, circular, false, vec![]) }; write!( @@ -200,6 +230,21 @@ fn format_js_error_inner( ) .unwrap(); } + if !suggestions.is_empty() { + write!(s, "\n\n").unwrap(); + for (index, suggestion) in suggestions.iter().enumerate() { + write!(s, " ").unwrap(); + match suggestion.kind { + FixSuggestionKind::Hint => write!(s, "{} ", cyan("hint:")).unwrap(), + FixSuggestionKind::Info => write!(s, "{} ", yellow("info:")).unwrap(), + }; + write!(s, "{}", suggestion.message).unwrap(); + if index != (suggestions.len() - 1) { + writeln!(s).unwrap(); + } + } + } + s } @@ -211,7 +256,21 @@ pub fn format_js_error(js_error: &JsError) -> String { index: 1, }); - format_js_error_inner(js_error, circular, true) + format_js_error_inner(js_error, circular, true, vec![]) +} + +/// Format a [`JsError`] for terminal output, printing additional suggestions. +pub fn format_js_error_with_suggestions( + js_error: &JsError, + suggestions: Vec, +) -> String { + let circular = + find_recursive_cause(js_error).map(|reference| IndexedErrorReference { + reference, + index: 1, + }); + + format_js_error_inner(js_error, circular, true, suggestions) } #[cfg(test)] -- cgit v1.2.3