From 314c776f4f0970e0bc89c7295785bf115df105e7 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Thu, 2 Mar 2017 20:46:04 -0800 Subject: [PATCH] Add emoji in errors --- codegen/src/decorators/derive_form.rs | 8 ++--- codegen/src/decorators/error.rs | 4 +-- codegen/src/decorators/route.rs | 6 ++-- codegen/src/lib.rs | 1 + codegen/src/parser/error.rs | 22 ++++++------- codegen/src/parser/param.rs | 4 +-- codegen/src/parser/route.rs | 46 +++++++++++++-------------- codegen/src/parser/uri.rs | 22 ++++++------- codegen/src/utils/mod.rs | 18 +++++++++++ 9 files changed, 75 insertions(+), 56 deletions(-) diff --git a/codegen/src/decorators/derive_form.rs b/codegen/src/decorators/derive_form.rs index 13bc34f7..0ac35903 100644 --- a/codegen/src/decorators/derive_form.rs +++ b/codegen/src/decorators/derive_form.rs @@ -13,7 +13,7 @@ use syntax_ext::deriving::generic::MethodDef; use syntax_ext::deriving::generic::{StaticStruct, Substructure, TraitDef, ty}; use syntax_ext::deriving::generic::combine_substructure as c_s; -use utils::strip_ty_lifetimes; +use utils::*; static ONLY_STRUCTS_ERR: &'static str = "`FromForm` can only be derived for \ structures with named fields."; @@ -37,15 +37,15 @@ fn get_struct_lifetime(ecx: &mut ExtCtxt, item: &Annotatable, span: Span) Some(lifetime_name) } _ => { - ecx.span_err(item.span, "cannot have more than one \ + span_err(ecx, item.span, "cannot have more than one \ lifetime parameter when deriving `FromForm`."); None } } }, - _ => ecx.span_fatal(span, ONLY_STRUCTS_ERR) + _ => span_fatal(ecx, span, ONLY_STRUCTS_ERR) }, - _ => ecx.span_fatal(span, ONLY_STRUCTS_ERR) + _ => span_fatal(ecx, span, ONLY_STRUCTS_ERR) } } diff --git a/codegen/src/decorators/error.rs b/codegen/src/decorators/error.rs index d7810673..5aeb3e63 100644 --- a/codegen/src/decorators/error.rs +++ b/codegen/src/decorators/error.rs @@ -25,7 +25,7 @@ impl ErrorGenerateExt for ErrorParams { let input_args = &self.annotated_fn.decl().inputs; if input_args.len() > 2 { let sp = self.annotated_fn.span(); - ecx.struct_span_err(sp, "error handlers can have at most 2 arguments") + struct_span_err(ecx, sp, "error handlers can have at most 2 arguments") .help(arg_help).emit() } @@ -35,7 +35,7 @@ impl ErrorGenerateExt for ErrorParams { TyKind::Rptr(..) => Some(req), TyKind::Path(..) => Some(err), _ => { - ecx.struct_span_err(ty.span, "unexpected error handler argument") + struct_span_err(ecx, ty.span, "unexpected error handler argument") .help(arg_help).emit(); None } diff --git a/codegen/src/decorators/route.rs b/codegen/src/decorators/route.rs index c147afbd..249d5eb3 100644 --- a/codegen/src/decorators/route.rs +++ b/codegen/src/decorators/route.rs @@ -52,8 +52,8 @@ impl RouteGenerateExt for RouteParams { fn missing_declared_err(&self, ecx: &ExtCtxt, arg: &Spanned) { let fn_span = self.annotated_fn.span(); let msg = format!("'{}' is declared as an argument...", arg.node); - ecx.span_err(arg.span, &msg); - ecx.span_err(fn_span, "...but isn't in the function signature."); + span_err(ecx, arg.span, &msg); + span_err(ecx, fn_span, "...but isn't in the function signature."); } fn gen_form(&self, @@ -181,7 +181,7 @@ impl RouteGenerateExt for RouteParams { !a.named(&p.node.name) }) } else { - ecx.span_err(a.pat.span, "route argument names must be identifiers"); + span_err(ecx, a.pat.span, "route argument names must be identifiers"); false } }; diff --git a/codegen/src/lib.rs b/codegen/src/lib.rs index 1be81f2e..e3f455ae 100644 --- a/codegen/src/lib.rs +++ b/codegen/src/lib.rs @@ -121,6 +121,7 @@ extern crate syntax; extern crate syntax_ext; extern crate syntax_pos; +extern crate rustc_errors; extern crate rustc_plugin; extern crate rocket; diff --git a/codegen/src/parser/error.rs b/codegen/src/parser/error.rs index f9cd651d..e3b6d37d 100644 --- a/codegen/src/parser/error.rs +++ b/codegen/src/parser/error.rs @@ -4,7 +4,7 @@ use syntax::codemap::{Span, Spanned, dummy_spanned}; use rocket::http::Status; -use utils::{span, MetaItemExt}; +use utils::*; use super::Function; /// This structure represents the parsed `error` attribute. @@ -23,21 +23,21 @@ impl ErrorParams { annotated: &Annotatable) -> ErrorParams { let function = Function::from(annotated).unwrap_or_else(|item_sp| { - ecx.span_err(sp, "this attribute can only be used on functions..."); - ecx.span_fatal(item_sp, "...but was applied to the item above."); + span_err(ecx, sp, "this attribute can only be used on functions..."); + span_fatal(ecx, item_sp, "...but was applied to the item above."); }); let meta_items = meta_item.meta_item_list().unwrap_or_else(|| { - ecx.struct_span_fatal(sp, "incorrect use of attribute") + struct_span_fatal(ecx, sp, "incorrect use of attribute") .help("attributes in Rocket must have the form: #[name(...)]") .emit(); - ecx.span_fatal(sp, "malformed attribute"); + span_fatal(ecx, sp, "malformed attribute"); }); if meta_items.len() < 1 { - ecx.span_fatal(sp, "attribute requires the `code` parameter"); + span_fatal(ecx, sp, "attribute requires the `code` parameter"); } else if meta_items.len() > 1 { - ecx.span_fatal(sp, "attribute can only have one `code` parameter"); + span_fatal(ecx, sp, "attribute can only have one `code` parameter"); } ErrorParams { @@ -50,7 +50,7 @@ impl ErrorParams { fn parse_code(ecx: &ExtCtxt, meta_item: &NestedMetaItem) -> Spanned { let code_from_u128 = |n: Spanned| { if n.node < 400 || n.node > 599 { - ecx.span_err(n.span, "code must be >= 400 and <= 599."); + span_err(ecx, n.span, "code must be >= 400 and <= 599."); span(0, n.span) } else if Status::from_code(n.node as u16).is_none() { ecx.span_warn(n.span, "status code is unknown."); @@ -63,16 +63,16 @@ fn parse_code(ecx: &ExtCtxt, meta_item: &NestedMetaItem) -> Spanned { let sp = meta_item.span(); if let Some((name, lit)) = meta_item.name_value() { if name != &"code" { - ecx.span_err(sp, "the first key, if any, must be 'code'"); + span_err(ecx, sp, "the first key, if any, must be 'code'"); } else if let LitKind::Int(n, _) = lit.node { return code_from_u128(span(n, lit.span)) } else { - ecx.span_err(lit.span, "`code` value must be an integer") + span_err(ecx, lit.span, "`code` value must be an integer") } } else if let Some(n) = meta_item.int_lit() { return code_from_u128(span(n, sp)) } else { - ecx.struct_span_err(sp, r#"expected `code = int` or an integer literal"#) + struct_span_err(ecx, sp, r#"expected `code = int` or an integer literal"#) .help(r#"you can specify the code directly as an integer, e.g: #[error(404)], or as a key-value pair, e.g: $[error(code = 404)]"#) diff --git a/codegen/src/parser/param.rs b/codegen/src/parser/param.rs index 4d0d3449..80fb6fe6 100644 --- a/codegen/src/parser/param.rs +++ b/codegen/src/parser/param.rs @@ -2,7 +2,7 @@ use syntax::ast::Ident; use syntax::ext::base::ExtCtxt; use syntax::codemap::{Span, Spanned, BytePos}; -use utils::span; +use utils::*; #[derive(Debug)] pub enum Param { @@ -41,7 +41,7 @@ impl<'s, 'a, 'c> Iterator for ParamIter<'s, 'a, 'c> { fn next(&mut self) -> Option { let err = |ecx: &ExtCtxt, sp: Span, msg: &str| { - ecx.span_err(sp, msg); + span_err(ecx, sp, msg); None }; diff --git a/codegen/src/parser/route.rs b/codegen/src/parser/route.rs index fc8bc00a..b451afe5 100644 --- a/codegen/src/parser/route.rs +++ b/codegen/src/parser/route.rs @@ -5,7 +5,7 @@ use syntax::ast::*; use syntax::ext::base::{ExtCtxt, Annotatable}; use syntax::codemap::{Span, Spanned, dummy_spanned}; -use utils::{span, MetaItemExt, SpanExt, is_valid_ident}; +use utils::*; use super::{Function, ParamIter}; use super::keyvalue::KVSpanned; use super::uri::validate_uri; @@ -40,19 +40,19 @@ impl RouteParams { annotated: &Annotatable) -> RouteParams { let function = Function::from(annotated).unwrap_or_else(|item_sp| { - ecx.span_err(sp, "this attribute can only be used on functions..."); - ecx.span_fatal(item_sp, "...but was applied to the item above."); + span_err(ecx, sp, "this attribute can only be used on functions..."); + span_fatal(ecx, item_sp, "...but was applied to the item above."); }); let meta_items = meta_item.meta_item_list().unwrap_or_else(|| { - ecx.struct_span_err(sp, "incorrect use of attribute") + struct_span_err(ecx, sp, "incorrect use of attribute") .help("attributes in Rocket must have the form: #[name(...)]") .emit(); - ecx.span_fatal(sp, "malformed attribute"); + span_fatal(ecx, sp, "malformed attribute"); }); if meta_items.len() < 1 { - ecx.span_fatal(sp, "attribute requires at least 1 parameter"); + span_fatal(ecx, sp, "attribute requires at least 1 parameter"); } // Figure out the method. If it is known (i.e, because we're parsing a @@ -64,10 +64,10 @@ impl RouteParams { }; if attr_params.len() < 1 { - ecx.struct_span_err(sp, "attribute requires at least a path") + struct_span_err(ecx, sp, "attribute requires at least a path") .help(r#"example: #[get("/my/path")] or #[get(path = "/hi")]"#) .emit(); - ecx.span_fatal(sp, "malformed attribute"); + span_fatal(ecx, sp, "malformed attribute"); } // Parse the required path and optional query parameters. @@ -79,7 +79,7 @@ impl RouteParams { for param in &attr_params[1..] { let kv_opt = kv_from_nested(param); if kv_opt.is_none() { - ecx.span_err(param.span(), "expected key = value"); + span_err(ecx, param.span(), "expected key = value"); continue; } @@ -90,7 +90,7 @@ impl RouteParams { "format" => format = parse_opt(ecx, &kv, parse_format), _ => { let msg = format!("'{}' is not a known parameter", kv.key()); - ecx.span_err(kv.span, &msg); + span_err(ecx, kv.span, &msg); continue; } } @@ -108,7 +108,7 @@ impl RouteParams { // Sanity check: `data` should only be used with payload methods. if let Some(ref data_param) = data { if !method.node.supports_payload() { - ecx.struct_span_err(data_param.span, "`data` route parameters \ + struct_span_err(ecx, data_param.span, "`data` route parameters \ can only be used with payload supporting methods") .note(&format!("'{}' does not support payloads", method.node)) .emit(); @@ -160,9 +160,9 @@ pub fn param_to_ident(ecx: &ExtCtxt, s: Spanned<&str>) -> Option> return Some(span(Ident::from_str(param), s.span.trim(1))); } - ecx.span_err(s.span, "parameter name must be alphanumeric"); + span_err(ecx, s.span, "parameter name must be alphanumeric"); } else { - ecx.span_err(s.span, "parameters must start with '<' and end with '>'"); + span_err(ecx, s.span, "parameters must start with '<' and end with '>'"); } None @@ -176,12 +176,12 @@ fn parse_method(ecx: &ExtCtxt, meta_item: &NestedMetaItem) -> Spanned { } } else { let msg = format!("'{}' is not a valid HTTP method.", word.name()); - ecx.span_err(word.span(), &msg); + span_err(ecx, word.span(), &msg); } } // Fallthrough. Return default method. - ecx.struct_span_err(meta_item.span, "expected a valid HTTP method") + struct_span_err(ecx, meta_item.span, "expected a valid HTTP method") .help("valid methods are: GET, PUT, POST, DELETE, PATCH") .emit(); @@ -194,16 +194,16 @@ fn parse_path(ecx: &ExtCtxt, let sp = meta_item.span(); if let Some((name, lit)) = meta_item.name_value() { if name != &"path" { - ecx.span_err(sp, "the first key, if any, must be 'path'"); + span_err(ecx, sp, "the first key, if any, must be 'path'"); } else if let LitKind::Str(ref s, _) = lit.node { return validate_uri(ecx, &s.as_str(), lit.span); } else { - ecx.span_err(lit.span, "`path` value must be a string") + span_err(ecx, lit.span, "`path` value must be a string") } } else if let Some(s) = meta_item.str_lit() { return validate_uri(ecx, &s.as_str(), sp); } else { - ecx.struct_span_err(sp, r#"expected `path = string` or a path string"#) + struct_span_err(ecx, sp, r#"expected `path = string` or a path string"#) .help(r#"you can specify the path directly as a string, \ e.g: "/hello/world", or as a key-value pair, \ e.g: path = "/hello/world" "#) @@ -229,7 +229,7 @@ fn parse_data(ecx: &ExtCtxt, kv: &KVSpanned) -> Ident { } let err_string = r#"`data` value must be a parameter, e.g: ""`"#; - ecx.struct_span_fatal(kv.span, err_string) + struct_span_fatal(ecx, kv.span, err_string) .help(r#"data, if specified, must be a key-value pair where the key is `data` and the value is a string with a single parameter inside '<' '>'. e.g: data = """#) @@ -245,10 +245,10 @@ fn parse_rank(ecx: &ExtCtxt, kv: &KVSpanned) -> isize { return n as isize; } else { let msg = format!("rank must be less than or equal to {}", max); - ecx.span_err(kv.value.span, msg.as_str()); + span_err(ecx, kv.value.span, msg.as_str()); } } else { - ecx.struct_span_err(kv.span, r#"`rank` value must be an int"#) + struct_span_err(ecx, kv.span, r#"`rank` value must be an int"#) .help(r#"the rank, if specified, must be a key-value pair where the key is `rank` and the value is an integer. e.g: rank = 1, or e.g: rank = 10"#) @@ -268,11 +268,11 @@ fn parse_format(ecx: &ExtCtxt, kv: &KVSpanned) -> ContentType { return ct; } else { - ecx.span_err(kv.value.span, "malformed content-type"); + span_err(ecx, kv.value.span, "malformed content-type"); } } - ecx.struct_span_err(kv.span, r#"`format` must be a "content/type""#) + struct_span_err(ecx, kv.span, r#"`format` must be a "content/type""#) .help(r#"format, if specified, must be a key-value pair where the key is `format` and the value is a string representing the content-type accepted. e.g: format = "application/json""#) diff --git a/codegen/src/parser/uri.rs b/codegen/src/parser/uri.rs index 693fcabe..28094b54 100644 --- a/codegen/src/parser/uri.rs +++ b/codegen/src/parser/uri.rs @@ -4,7 +4,7 @@ use syntax::ext::base::ExtCtxt; use rocket::http::uri::URI; use super::route::param_to_ident; -use utils::{span, SpanExt, is_valid_ident}; +use utils::*; // We somewhat arbitrarily enforce absolute paths. This is mostly because we // want the initial "/" to represent the mount point. Empty segments are @@ -14,11 +14,11 @@ use utils::{span, SpanExt, is_valid_ident}; fn valid_path(ecx: &ExtCtxt, uri: &URI, sp: Span) -> bool { let cleaned = uri.to_string(); if !uri.as_str().starts_with('/') { - ecx.struct_span_err(sp, "route paths must be absolute") + struct_span_err(ecx, sp, "route paths must be absolute") .note(&format!("expected {:?}, found {:?}", cleaned, uri.as_str())) .emit() } else if cleaned != uri.as_str() { - ecx.struct_span_err(sp, "paths cannot contain empty segments") + struct_span_err(ecx, sp, "paths cannot contain empty segments") .note(&format!("expected {:?}, found {:?}", cleaned, uri.as_str())) .emit() } else { @@ -39,7 +39,7 @@ fn valid_segments(ecx: &ExtCtxt, uri: &URI, sp: Span) -> bool { // If we're iterating after a '..' param, that's a hard error. if let Some(span) = segments_span { let rem_sp = sp.trim_left(index).trim_right(1); - ecx.struct_span_err(rem_sp, "text after a trailing '..' param") + struct_span_err(ecx, rem_sp, "text after a trailing '..' param") .help("a segments param must be the final text in a path") .span_note(span, "trailing param is here") .emit(); @@ -55,13 +55,13 @@ fn valid_segments(ecx: &ExtCtxt, uri: &URI, sp: Span) -> bool { } if param.is_empty() { - ecx.span_err(span, "parameters cannot be empty"); + span_err(ecx, span, "parameters cannot be empty"); } else if !is_valid_ident(param) { - ecx.struct_span_err(span, "parameter names must be valid identifiers") + struct_span_err(ecx, span, "parameter names must be valid identifiers") .note(&format!("{:?} is not a valid identifier", param)) .emit(); } else if param.starts_with('_') { - ecx.struct_span_err(span, "parameters cannot be ignored") + struct_span_err(ecx, span, "parameters cannot be ignored") .note(&format!("{:?} is being ignored", param)) .emit(); } else { @@ -71,11 +71,11 @@ fn valid_segments(ecx: &ExtCtxt, uri: &URI, sp: Span) -> bool { validated = false; } else if segment.starts_with("<") { if segment[1..].contains("<") || segment.contains(">") { - ecx.struct_span_err(span, "malformed parameter") + struct_span_err(ecx, span, "malformed parameter") .help("parameters must be of the form ''") .emit(); } else { - ecx.struct_span_err(span, "parameter is missing a closing bracket") + struct_span_err(ecx, span, "parameter is missing a closing bracket") .help(&format!("perhaps you meant '{}>'?", segment)) .emit(); } @@ -83,11 +83,11 @@ fn valid_segments(ecx: &ExtCtxt, uri: &URI, sp: Span) -> bool { validated = false; } else if URI::percent_encode(segment) != segment { if segment.contains("<") || segment.contains(">") { - ecx.struct_span_err(span, "malformed parameter") + struct_span_err(ecx, span, "malformed parameter") .help("parameters must be of the form ''") .emit(); } else { - ecx.span_err(span, "segment contains invalid characters"); + span_err(ecx, span, "segment contains invalid characters"); } validated = false; diff --git a/codegen/src/utils/mod.rs b/codegen/src/utils/mod.rs index 41664c53..ec9c3535 100644 --- a/codegen/src/utils/mod.rs +++ b/codegen/src/utils/mod.rs @@ -10,6 +10,8 @@ pub use self::parser_ext::ParserExt; pub use self::ident_ext::IdentExt; pub use self::span_ext::SpanExt; +use rustc_errors::DiagnosticBuilder; + use std::convert::AsRef; use syntax; @@ -43,6 +45,22 @@ pub fn sep_by_tok(ecx: &ExtCtxt, things: &[T], token: Token) -> Vec(cx: &'cx ExtCtxt, sp: Span, error: &str) -> DiagnosticBuilder<'cx> { + cx.struct_span_err(sp, &format!("😭 {}", error)) +} + +pub fn struct_span_fatal<'cx>(cx: &'cx ExtCtxt, sp: Span, error: &str) -> DiagnosticBuilder<'cx> { + cx.struct_span_err(sp, &format!("💀 {}", error)) +} + +pub fn span_err(cx: &ExtCtxt, sp: Span, error: &str) { + cx.span_err(sp, &format!("😭 {}", error)) +} + +pub fn span_fatal(cx: &ExtCtxt, sp: Span, error: &str) -> ! { + cx.span_fatal(sp, &format!("💀 {}", error)) +} + pub fn option_as_expr(ecx: &ExtCtxt, opt: &Option) -> P { match *opt { Some(ref item) => quote_expr!(ecx, Some($item)),