diff options
| author | Esteban Küber <esteban@kuber.com.ar> | 2019-05-21 17:47:23 -0700 |
|---|---|---|
| committer | Esteban Küber <esteban@kuber.com.ar> | 2019-05-25 11:55:50 -0700 |
| commit | 609ffa1a890fd6b8b0364cd7b35bf1d45abf82d0 (patch) | |
| tree | dbd09e2fa625c27c100cb21e6b196c9f45b5ec27 /src/libsyntax | |
| parent | 02f5786a324c40b2d8b2d0df98456e48fb45d30c (diff) | |
| download | rust-609ffa1a890fd6b8b0364cd7b35bf1d45abf82d0.tar.gz rust-609ffa1a890fd6b8b0364cd7b35bf1d45abf82d0.zip | |
Reword malformed attribute input diagnostics
- Handle empty `cfg_attr` attribute - Reword empty `derive` attribute error - Use consistend error message: "malformed `attrname` attribute input" - Provide suggestions when possible - Move note/help to label/suggestion - Use consistent wording "ill-formed" -> "malformed" - Move diagnostic logic out of parser
Diffstat (limited to 'src/libsyntax')
| -rw-r--r-- | src/libsyntax/attr/builtin.rs | 10 | ||||
| -rw-r--r-- | src/libsyntax/config.rs | 16 | ||||
| -rw-r--r-- | src/libsyntax/ext/derive.rs | 10 | ||||
| -rw-r--r-- | src/libsyntax/feature_gate.rs | 50 |
4 files changed, 74 insertions, 12 deletions
diff --git a/src/libsyntax/attr/builtin.rs b/src/libsyntax/attr/builtin.rs index 65ca96afab1..b96f13335b2 100644 --- a/src/libsyntax/attr/builtin.rs +++ b/src/libsyntax/attr/builtin.rs @@ -92,7 +92,15 @@ pub fn find_unwind_attr(diagnostic: Option<&Handler>, attrs: &[Attribute]) -> Op } diagnostic.map(|d| { - span_err!(d, attr.span, E0633, "malformed `#[unwind]` attribute"); + struct_span_err!(d, attr.span, E0633, "malformed `unwind` attribute input") + .span_label(attr.span, "invalid argument") + .span_suggestions( + attr.span, + "the allowed arguments are `allowed` and `aborts`", + (vec!["allowed", "aborts"]).into_iter() + .map(|s| format!("#[unwind({})]", s)), + Applicability::MachineApplicable, + ).emit(); }); } } diff --git a/src/libsyntax/config.rs b/src/libsyntax/config.rs index c82936afa3d..fc413caa428 100644 --- a/src/libsyntax/config.rs +++ b/src/libsyntax/config.rs @@ -94,6 +94,22 @@ impl<'a> StripUnconfigured<'a> { if !attr.check_name(sym::cfg_attr) { return vec![attr]; } + if attr.tokens.len() == 0 { + self.sess.span_diagnostic + .struct_span_err( + attr.span, + "malformed `cfg_attr` attribute input", + ).span_suggestion( + attr.span, + "missing condition and attribute", + "#[cfg_attr(condition, attribute, other_attribute, ...)]".to_owned(), + Applicability::HasPlaceholders, + ).note("for more information, visit \ + <https://doc.rust-lang.org/reference/conditional-compilation.html\ + #the-cfg_attr-attribute>") + .emit(); + return Vec::new(); + } let (cfg_predicate, expanded_attrs) = match attr.parse(self.sess, |parser| { parser.expect(&token::OpenDelim(token::Paren))?; diff --git a/src/libsyntax/ext/derive.rs b/src/libsyntax/ext/derive.rs index 6e789c4c708..4db206094d3 100644 --- a/src/libsyntax/ext/derive.rs +++ b/src/libsyntax/ext/derive.rs @@ -5,6 +5,7 @@ use crate::ext::base::ExtCtxt; use crate::ext::build::AstBuilder; use crate::parse::parser::PathStyle; use crate::symbol::{Symbol, sym}; +use crate::errors::Applicability; use syntax_pos::Span; @@ -17,8 +18,13 @@ pub fn collect_derives(cx: &mut ExtCtxt<'_>, attrs: &mut Vec<ast::Attribute>) -> return true; } if !attr.is_meta_item_list() { - cx.span_err(attr.span, - "attribute must be of the form `#[derive(Trait1, Trait2, ...)]`"); + cx.struct_span_err(attr.span, "malformed `derive` attribute input") + .span_suggestion( + attr.span, + "missing traits to be derived", + "#[derive(Trait1, Trait2, ...)]".to_owned(), + Applicability::HasPlaceholders, + ).emit(); return false; } diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 6a049b80aca..b2646efe3e4 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -25,7 +25,7 @@ use crate::parse::{token, ParseSess}; use crate::symbol::{Symbol, kw, sym}; use crate::tokenstream::TokenTree; -use errors::{DiagnosticBuilder, Handler}; +use errors::{Applicability, DiagnosticBuilder, Handler}; use rustc_data_structures::fx::FxHashMap; use rustc_target::spec::abi::Abi; use syntax_pos::{Span, DUMMY_SP}; @@ -1422,7 +1422,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ Normal, template!( Word, - List: r#"/*opt*/ since = "version", /*opt*/ note = "reason"#, + List: r#"/*opt*/ since = "version", /*opt*/ note = "reason""#, NameValueStr: "reason" ), Ungated @@ -1858,24 +1858,32 @@ impl<'a> PostExpansionVisitor<'a> { match attr.parse_meta(self.context.parse_sess) { Ok(meta) => if !should_skip(name) && !template.compatible(&meta.node) { + let error_msg = format!("malformed `{}` attribute input", name); let mut msg = "attribute must be of the form ".to_owned(); + let mut suggestions = vec![]; let mut first = true; if template.word { first = false; - msg.push_str(&format!("`#[{}{}]`", name, "")); + let code = format!("#[{}]", name); + msg.push_str(&format!("`{}`", &code)); + suggestions.push(code); } if let Some(descr) = template.list { if !first { msg.push_str(" or "); } first = false; - msg.push_str(&format!("`#[{}({})]`", name, descr)); + let code = format!("#[{}({})]", name, descr); + msg.push_str(&format!("`{}`", &code)); + suggestions.push(code); } if let Some(descr) = template.name_value_str { if !first { msg.push_str(" or "); } - msg.push_str(&format!("`#[{} = \"{}\"]`", name, descr)); + let code = format!("#[{} = \"{}\"]", name, descr); + msg.push_str(&format!("`{}`", &code)); + suggestions.push(code); } if should_warn(name) { self.context.parse_sess.buffer_lint( @@ -1885,7 +1893,17 @@ impl<'a> PostExpansionVisitor<'a> { &msg, ); } else { - self.context.parse_sess.span_diagnostic.span_err(meta.span, &msg); + self.context.parse_sess.span_diagnostic.struct_span_err(meta.span, &error_msg) + .span_suggestions( + meta.span, + if suggestions.len() == 1 { + "must be of the form" + } else { + "the following are the possible correct uses" + }, + suggestions.into_iter(), + Applicability::HasPlaceholders, + ).emit(); } } Err(mut err) => err.emit(), @@ -2298,6 +2316,8 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute], let mut err = struct_span_err!(span_handler, span, E0557, "feature has been removed"); if let Some(reason) = reason { err.span_note(span, reason); + } else { + err.span_label(span, "feature has been removed"); } err.emit(); } @@ -2379,12 +2399,24 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute], None => continue, }; + let bad_input = |span| { + struct_span_err!(span_handler, span, E0556, "malformed `feature` attribute input") + }; + for mi in list { let name = match mi.ident() { Some(ident) if mi.is_word() => ident.name, - _ => { - span_err!(span_handler, mi.span(), E0556, - "malformed feature, expected just one word"); + Some(ident) => { + bad_input(mi.span()).span_suggestion( + mi.span(), + "expected just one word", + format!("{}", ident.name), + Applicability::MaybeIncorrect, + ).emit(); + continue + } + None => { + bad_input(mi.span()).span_label(mi.span(), "expected just one word").emit(); continue } }; |
