diff options
Diffstat (limited to 'cli/fmt_errors.rs')
-rw-r--r-- | cli/fmt_errors.rs | 178 |
1 files changed, 148 insertions, 30 deletions
diff --git a/cli/fmt_errors.rs b/cli/fmt_errors.rs index 8432d36c2..333c47756 100644 --- a/cli/fmt_errors.rs +++ b/cli/fmt_errors.rs @@ -3,30 +3,156 @@ use crate::colors; use crate::source_maps::apply_source_map; use crate::source_maps::SourceMapGetter; -use deno_core::error::AnyError; -use deno_core::error::JsError as CoreJsError; +use deno_core::error::{AnyError, JsError as CoreJsError, JsStackFrame}; use std::error::Error; use std::fmt; use std::ops::Deref; const SOURCE_ABBREV_THRESHOLD: usize = 150; -pub fn format_location(filename: &str, line: i64, col: i64) -> String { - format!( - "{}:{}:{}", - colors::cyan(filename), - colors::yellow(&line.to_string()), - colors::yellow(&col.to_string()) - ) +fn default_color(s: &str, internal: bool) -> String { + if internal { + colors::gray(s).to_string() + } else { + s.to_string() + } +} + +fn cyan(s: &str, internal: bool) -> String { + if internal { + colors::gray(s).to_string() + } else { + colors::cyan(s).to_string() + } +} + +fn yellow(s: &str, internal: bool) -> String { + if internal { + colors::gray(s).to_string() + } else { + colors::yellow(s).to_string() + } +} + +fn italic_bold(s: &str, internal: bool) -> String { + if internal { + colors::italic_bold_gray(s).to_string() + } else { + colors::italic_bold(s).to_string() + } +} + +// Keep in sync with `cli/rt/40_error_stack.js`. +pub fn format_location(frame: &JsStackFrame) -> String { + let internal = frame + .file_name + .as_ref() + .map_or(false, |f| f.starts_with("deno:")); + if frame.is_native { + return cyan("native", internal); + } + let mut result = String::new(); + if let Some(file_name) = &frame.file_name { + result += &cyan(&file_name, internal); + } else { + if frame.is_eval { + result += &(cyan(&frame.eval_origin.as_ref().unwrap(), internal) + ", "); + } + result += &cyan("<anonymous>", internal); + } + if let Some(line_number) = frame.line_number { + result += &format!( + "{}{}", + default_color(":", internal), + yellow(&line_number.to_string(), internal) + ); + if let Some(column_number) = frame.column_number { + result += &format!( + "{}{}", + default_color(":", internal), + yellow(&column_number.to_string(), internal) + ); + } + } + result +} + +// Keep in sync with `cli/rt/40_error_stack.js`. +fn format_frame(frame: &JsStackFrame) -> String { + let internal = frame + .file_name + .as_ref() + .map_or(false, |f| f.starts_with("deno:")); + let is_method_call = + !(frame.is_top_level.unwrap_or_default() || frame.is_constructor); + let mut result = String::new(); + if frame.is_async { + result += &colors::gray("async ").to_string(); + } + if frame.is_promise_all { + result += &italic_bold( + &format!( + "Promise.all (index {})", + frame.promise_index.unwrap_or_default().to_string() + ), + internal, + ); + return result; + } + if is_method_call { + let mut formatted_method = String::new(); + if let Some(function_name) = &frame.function_name { + if let Some(type_name) = &frame.type_name { + if !function_name.starts_with(type_name) { + formatted_method += &format!("{}.", type_name); + } + } + formatted_method += &function_name; + if let Some(method_name) = &frame.method_name { + if !function_name.ends_with(method_name) { + formatted_method += &format!(" [as {}]", method_name); + } + } + } else { + if let Some(type_name) = &frame.type_name { + formatted_method += &format!("{}.", type_name); + } + if let Some(method_name) = &frame.method_name { + formatted_method += &method_name + } else { + formatted_method += "<anonymous>"; + } + } + result += &italic_bold(&formatted_method, internal); + } else if frame.is_constructor { + result += &colors::gray("new ").to_string(); + if let Some(function_name) = &frame.function_name { + result += &italic_bold(&function_name, internal); + } else { + result += &cyan("<anonymous>", internal); + } + } else if let Some(function_name) = &frame.function_name { + result += &italic_bold(&function_name, internal); + } else { + result += &format_location(frame); + return result; + } + result += &format!( + " {}{}{}", + default_color("(", internal), + format_location(frame), + default_color(")", internal) + ); + result } -pub fn format_stack( +fn format_stack( is_error: bool, message_line: &str, source_line: Option<&str>, start_column: Option<i64>, end_column: Option<i64>, - formatted_frames: &[String], + frames: &[JsStackFrame], level: usize, ) -> String { let mut s = String::new(); @@ -38,11 +164,11 @@ pub fn format_stack( is_error, level, )); - for formatted_frame in formatted_frames { + for frame in frames { s.push_str(&format!( "\n{:indent$} at {}", "", - formatted_frame, + format_frame(frame), indent = level )); } @@ -128,31 +254,23 @@ impl Deref for JsError { impl fmt::Display for JsError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let mut formatted_frames = self.0.formatted_frames.clone(); - - // The formatted_frames passed from prepareStackTrace() are colored. - if !colors::use_color() { - formatted_frames = formatted_frames - .iter() - .map(|s| colors::strip_ansi_codes(s).to_string()) - .collect(); - } + let mut frames = self.0.frames.clone(); // When the stack frame array is empty, but the source location given by // (script_resource_name, line_number, start_column + 1) exists, this is // likely a syntax error. For the sake of formatting we treat it like it was // given as a single stack frame. - if formatted_frames.is_empty() + if frames.is_empty() && self.0.script_resource_name.is_some() && self.0.line_number.is_some() && self.0.start_column.is_some() { - formatted_frames = vec![format_location( - self.0.script_resource_name.as_ref().unwrap(), - self.0.line_number.unwrap(), - self.0.start_column.unwrap() + 1, - )] - }; + frames = vec![JsStackFrame::from_location( + self.0.script_resource_name.clone(), + self.0.line_number, + self.0.start_column.map(|n| n + 1), + )]; + } write!( f, @@ -163,7 +281,7 @@ impl fmt::Display for JsError { self.0.source_line.as_deref(), self.0.start_column, self.0.end_column, - &formatted_frames, + &frames, 0 ) )?; |