add typo suggestion to unknown attribute error

This commit is contained in:
Andy Russell 2019-01-25 14:29:47 -05:00
parent da6ab956e1
commit 5e67021172
No known key found for this signature in database
GPG Key ID: BE2221033EDBC374
6 changed files with 108 additions and 8 deletions

View File

@ -19,7 +19,9 @@ use syntax::ext::base::{Annotatable, MacroKind, SyntaxExtension};
use syntax::ext::expand::{AstFragment, Invocation, InvocationKind};
use syntax::ext::hygiene::{self, Mark};
use syntax::ext::tt::macro_rules;
use syntax::feature_gate::{feature_err, is_builtin_attr_name, GateIssue};
use syntax::feature_gate::{
feature_err, is_builtin_attr_name, AttributeGate, GateIssue, Stability, BUILTIN_ATTRIBUTES,
};
use syntax::symbol::{Symbol, keywords};
use syntax::visit::Visitor;
use syntax::util::lev_distance::find_best_match_for_name;
@ -310,15 +312,18 @@ impl<'a> Resolver<'a> {
if !features.rustc_attrs {
let msg = "unless otherwise specified, attributes with the prefix \
`rustc_` are reserved for internal compiler diagnostics";
feature_err(&self.session.parse_sess, "rustc_attrs", path.span,
GateIssue::Language, &msg).emit();
self.report_unknown_attribute(path.span, &name, msg, "rustc_attrs");
}
} else if !features.custom_attribute {
let msg = format!("The attribute `{}` is currently unknown to the \
compiler and may have meaning added to it in the \
future", path);
feature_err(&self.session.parse_sess, "custom_attribute", path.span,
GateIssue::Language, &msg).emit();
self.report_unknown_attribute(
path.span,
&name,
&msg,
"custom_attribute",
);
}
}
} else {
@ -339,6 +344,61 @@ impl<'a> Resolver<'a> {
Ok((def, self.get_macro(def)))
}
fn report_unknown_attribute(&self, span: Span, name: &str, msg: &str, feature: &str) {
let mut err = feature_err(
&self.session.parse_sess,
feature,
span,
GateIssue::Language,
&msg,
);
let features = self.session.features_untracked();
let attr_candidates = BUILTIN_ATTRIBUTES
.iter()
.filter_map(|(name, _, _, gate)| {
if name.starts_with("rustc_") && !features.rustc_attrs {
return None;
}
match gate {
AttributeGate::Gated(Stability::Unstable, ..)
if self.session.opts.unstable_features.is_nightly_build() =>
{
Some(name)
}
AttributeGate::Gated(Stability::Deprecated(..), ..) => Some(name),
AttributeGate::Ungated => Some(name),
_ => None,
}
})
.map(|name| Symbol::intern(name))
.chain(
// Add built-in macro attributes as well.
self.builtin_macros.iter().filter_map(|(name, binding)| {
match binding.macro_kind() {
Some(MacroKind::Attr) => Some(*name),
_ => None,
}
}),
)
.collect::<Vec<_>>();
let lev_suggestion = find_best_match_for_name(attr_candidates.iter(), &name, None);
if let Some(suggestion) = lev_suggestion {
err.span_suggestion(
span,
"a built-in attribute with a similar name exists",
suggestion.to_string(),
Applicability::MaybeIncorrect,
);
}
err.emit();
}
pub fn resolve_macro_to_def_inner(
&mut self,
path: &ast::Path,

View File

@ -2,7 +2,7 @@ error[E0658]: The attribute `marco_use` is currently unknown to the compiler and
--> $DIR/issue-49074.rs:3:3
|
LL | #[marco_use] // typo
| ^^^^^^^^^
| ^^^^^^^^^ help: a built-in attribute with a similar name exists: `macro_use`
|
= help: add #![feature(custom_attribute)] to the crate attributes to enable

View File

@ -14,7 +14,7 @@ error[E0658]: The attribute `macro_reexport` is currently unknown to the compile
--> $DIR/macro-reexport-removed.rs:5:3
|
LL | #[macro_reexport(macro_one)] //~ ERROR attribute `macro_reexport` is currently unknown
| ^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^ help: a built-in attribute with a similar name exists: `macro_export`
|
= help: add #![feature(custom_attribute)] to the crate attributes to enable

View File

@ -2,7 +2,7 @@ error[E0658]: The attribute `derive_A` is currently unknown to the compiler and
--> $DIR/derive-still-gated.rs:8:3
|
LL | #[derive_A] //~ ERROR attribute `derive_A` is currently unknown
| ^^^^^^^^
| ^^^^^^^^ help: a built-in attribute with a similar name exists: `derive`
|
= help: add #![feature(custom_attribute)] to the crate attributes to enable

View File

@ -0,0 +1,13 @@
#[deprcated] //~ ERROR E0658
fn foo() {} //~| HELP a built-in attribute with a similar name exists
//~| SUGGESTION deprecated
//~| HELP add #![feature(custom_attribute)] to the crate attributes to enable
#[tests] //~ ERROR E0658
fn bar() {} //~| HELP a built-in attribute with a similar name exists
//~| SUGGESTION test
//~| HELP add #![feature(custom_attribute)] to the crate attributes to enable
#[rustc_err] //~ ERROR E0658
fn main() {} //~| HELP add #![feature(rustc_attrs)] to the crate attributes to enable
// don't suggest rustc attributes

View File

@ -0,0 +1,27 @@
error[E0658]: unless otherwise specified, attributes with the prefix `rustc_` are reserved for internal compiler diagnostics (see issue #29642)
--> $DIR/attribute-typos.rs:11:3
|
LL | #[rustc_err] //~ ERROR E0658
| ^^^^^^^^^
|
= help: add #![feature(rustc_attrs)] to the crate attributes to enable
error[E0658]: The attribute `tests` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
--> $DIR/attribute-typos.rs:6:3
|
LL | #[tests] //~ ERROR E0658
| ^^^^^ help: a built-in attribute with a similar name exists: `test`
|
= help: add #![feature(custom_attribute)] to the crate attributes to enable
error[E0658]: The attribute `deprcated` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
--> $DIR/attribute-typos.rs:1:3
|
LL | #[deprcated] //~ ERROR E0658
| ^^^^^^^^^ help: a built-in attribute with a similar name exists: `deprecated`
|
= help: add #![feature(custom_attribute)] to the crate attributes to enable
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0658`.