Add emoji in errors

This commit is contained in:
Manish Goregaokar 2017-03-02 20:46:04 -08:00
parent 6be902162d
commit 314c776f4f
9 changed files with 75 additions and 56 deletions

View File

@ -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)
}
}

View File

@ -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
}

View File

@ -52,8 +52,8 @@ impl RouteGenerateExt for RouteParams {
fn missing_declared_err<T: Display>(&self, ecx: &ExtCtxt, arg: &Spanned<T>) {
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
}
};

View File

@ -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;

View File

@ -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<u16> {
let code_from_u128 = |n: Spanned<u128>| {
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<u16> {
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)]"#)

View File

@ -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<Param> {
let err = |ecx: &ExtCtxt, sp: Span, msg: &str| {
ecx.span_err(sp, msg);
span_err(ecx, sp, msg);
None
};

View File

@ -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<Spanned<Ident>>
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<Method> {
}
} 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<LitKind>) -> Ident {
}
let err_string = r#"`data` value must be a parameter, e.g: "<name>"`"#;
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 = "<user_form>""#)
@ -245,10 +245,10 @@ fn parse_rank(ecx: &ExtCtxt, kv: &KVSpanned<LitKind>) -> 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<LitKind>) -> 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""#)

View File

@ -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 '<param>'")
.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 '<param>'")
.emit();
} else {
ecx.span_err(span, "segment contains invalid characters");
span_err(ecx, span, "segment contains invalid characters");
}
validated = false;

View File

@ -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<T>(ecx: &ExtCtxt, things: &[T], token: Token) -> Vec<TokenTree
output
}
pub fn struct_span_err<'cx>(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<T: ToTokens>(ecx: &ExtCtxt, opt: &Option<T>) -> P<Expr> {
match *opt {
Some(ref item) => quote_expr!(ecx, Some($item)),