Skip to content

Commit

Permalink
Mergify cli/js_errors into DenoError.
Browse files Browse the repository at this point in the history
  • Loading branch information
kitsonk committed Jun 12, 2019
1 parent 09569f6 commit 9a7e219
Show file tree
Hide file tree
Showing 6 changed files with 308 additions and 188 deletions.
2 changes: 1 addition & 1 deletion cli/deno_dir.rs
Expand Up @@ -6,9 +6,9 @@ use crate::errors::DenoResult;
use crate::errors::ErrorKind;
use crate::fs as deno_fs;
use crate::http_util;
use crate::js_errors::SourceMapGetter;
use crate::msg;
use crate::progress::Progress;
use crate::source_maps::SourceMapGetter;
use crate::tokio_util;
use crate::version;
use dirs;
Expand Down
151 changes: 149 additions & 2 deletions cli/errors.rs
@@ -1,16 +1,20 @@
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
use crate::ansi;
use crate::diagnostics;
use crate::import_map;
use crate::js_errors;
pub use crate::msg::ErrorKind;
use crate::resolve_addr::ResolveAddrError;
use crate::source_maps::apply_source_map;
use crate::source_maps::SourceMapGetter;
use deno::JSError;
use deno::StackFrame;
use hyper;
#[cfg(unix)]
use nix::{errno::Errno, Error as UnixError};
use std;
use std::fmt;
use std::io;
use std::str;
use url;

pub type DenoResult<T> = std::result::Result<T, DenoError>;
Expand All @@ -31,6 +35,85 @@ enum Repr {
JSError(JSError),
}

/// Wrapper around JSError which provides color to_string.
struct JSErrorColor<'a>(pub &'a JSError);

impl<'a> fmt::Display for JSErrorColor<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let e = self.0;
if e.script_resource_name.is_some() {
let script_resource_name = e.script_resource_name.as_ref().unwrap();
// Avoid showing internal code from gen/cli/bundle/main.js
if script_resource_name != "gen/cli/bundle/main.js"
&& script_resource_name != "gen/cli/bundle/compiler.js"
{
if e.line_number.is_some() && e.start_column.is_some() {
assert!(e.line_number.is_some());
assert!(e.start_column.is_some());
let script_line_column = format_script_line_column(
script_resource_name,
e.line_number.unwrap() - 1,
e.start_column.unwrap() - 1,
);
write!(f, "{}", script_line_column)?;
}
if e.source_line.is_some() {
write!(f, "\n{}\n", e.source_line.as_ref().unwrap())?;
let mut s = String::new();
for i in 0..e.end_column.unwrap() {
if i >= e.start_column.unwrap() {
s.push('^');
} else {
s.push(' ');
}
}
writeln!(f, "{}", ansi::red_bold(s))?;
}
}
}

write!(f, "{}", ansi::bold(e.message.clone()))?;

for frame in &e.frames {
write!(f, "\n{}", StackFrameColor(&frame).to_string())?;
}
Ok(())
}
}

struct StackFrameColor<'a>(&'a StackFrame);

impl<'a> fmt::Display for StackFrameColor<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let frame = self.0;
// Note when we print to string, we change from 0-indexed to 1-indexed.
let function_name = ansi::italic_bold(frame.function_name.clone());
let script_line_column =
format_script_line_column(&frame.script_name, frame.line, frame.column);

if !frame.function_name.is_empty() {
write!(f, " at {} ({})", function_name, script_line_column)
} else if frame.is_eval {
write!(f, " at eval ({})", script_line_column)
} else {
write!(f, " at {}", script_line_column)
}
}
}

fn format_script_line_column(
script_name: &str,
line: i64,
column: i64,
) -> String {
// TODO match this style with how typescript displays errors.
let line = ansi::yellow((1 + line).to_string());
let column = ansi::yellow((1 + column).to_string());
let script_name = ansi::cyan(script_name.to_string());
format!("{}:{}:{}", script_name, line, column)
}

/// Create a new simple DenoError.
pub fn new(kind: ErrorKind, msg: String) -> DenoError {
DenoError {
repr: Repr::Simple(kind, msg),
Expand Down Expand Up @@ -102,6 +185,15 @@ impl DenoError {
Repr::JSError(ref _err) => ErrorKind::JSError,
}
}

pub fn apply_source_map<G: SourceMapGetter>(self, getter: &G) -> Self {
if let Repr::JSError(js_error) = self.repr {
return DenoError {
repr: Repr::JSError(apply_source_map(&js_error, getter)),
};
}
self
}
}

impl fmt::Display for DenoError {
Expand All @@ -113,7 +205,7 @@ impl fmt::Display for DenoError {
Repr::HyperErr(ref err) => err.fmt(f),
Repr::ImportMapErr(ref err) => f.pad(&err.msg),
Repr::Diagnostic(ref err) => err.fmt(f),
Repr::JSError(ref err) => js_errors::JSErrorColor(err).fmt(f),
Repr::JSError(ref err) => JSErrorColor(err).fmt(f),
}
}
}
Expand Down Expand Up @@ -275,3 +367,58 @@ pub fn err_check(r: Result<(), DenoError>) {
panic!(e.to_string());
}
}

#[cfg(test)]
mod tests {
use super::*;
use crate::ansi::strip_ansi_codes;

fn error1() -> JSError {
JSError {
message: "Error: foo bar".to_string(),
source_line: None,
script_resource_name: None,
line_number: None,
start_position: None,
end_position: None,
error_level: None,
start_column: None,
end_column: None,
frames: vec![
StackFrame {
line: 4,
column: 16,
script_name: "foo_bar.ts".to_string(),
function_name: "foo".to_string(),
is_eval: false,
is_constructor: false,
is_wasm: false,
},
StackFrame {
line: 5,
column: 20,
script_name: "bar_baz.ts".to_string(),
function_name: "qat".to_string(),
is_eval: false,
is_constructor: false,
is_wasm: false,
},
StackFrame {
line: 1,
column: 1,
script_name: "deno_main.js".to_string(),
function_name: "".to_string(),
is_eval: false,
is_constructor: false,
is_wasm: false,
},
],
}
}

#[test]
fn js_error_to_string() {
let e = error1();
assert_eq!("Error: foo bar\n at foo (foo_bar.ts:5:17)\n at qat (bar_baz.ts:6:21)\n at deno_main.js:2:2", strip_ansi_codes(&e.to_string()));
}
}
2 changes: 1 addition & 1 deletion cli/main.rs
Expand Up @@ -26,7 +26,6 @@ mod global_timer;
mod http_body;
mod http_util;
mod import_map;
pub mod js_errors;
pub mod msg;
pub mod msg_util;
pub mod ops;
Expand All @@ -36,6 +35,7 @@ mod repl;
pub mod resolve_addr;
pub mod resources;
mod signal;
pub mod source_maps;
mod startup_data;
pub mod state;
mod tokio_util;
Expand Down
7 changes: 3 additions & 4 deletions cli/ops.rs
Expand Up @@ -11,7 +11,6 @@ use crate::errors::DenoResult;
use crate::errors::ErrorKind;
use crate::fs as deno_fs;
use crate::http_util;
use crate::js_errors::apply_source_map;
use crate::msg;
use crate::msg_util;
use crate::rand;
Expand Down Expand Up @@ -389,11 +388,11 @@ fn op_format_error(
let orig_error = String::from(inner.error().unwrap());

let js_error = JSError::from_v8_exception(&orig_error).unwrap();
let js_error_mapped = apply_source_map(&js_error, &state.dir);
let js_error_string = DenoError::from(js_error_mapped).to_string();
let error_mapped = DenoError::from(js_error).apply_source_map(&state.dir);
let error_string = error_mapped.to_string();

let mut builder = FlatBufferBuilder::new();
let new_error = builder.create_string(&js_error_string);
let new_error = builder.create_string(&error_string);

let inner = msg::FormatErrorRes::create(
&mut builder,
Expand Down

0 comments on commit 9a7e219

Please sign in to comment.