1
Fork 0

Check if the lint_name is from a tool and if the tool_lint exists

This commit is contained in:
flip1995 2018-07-30 11:29:23 +02:00
parent 4b466ee4f9
commit 57c77426ae
No known key found for this signature in database
GPG key ID: 9F184E1164831181
2 changed files with 71 additions and 29 deletions

View file

@ -42,7 +42,7 @@ use util::nodemap::FxHashMap;
use std::default::Default as StdDefault; use std::default::Default as StdDefault;
use syntax::ast; use syntax::ast;
use syntax::edition; use syntax::edition;
use syntax_pos::{MultiSpan, Span}; use syntax_pos::{MultiSpan, Span, symbol::LocalInternedString};
use errors::DiagnosticBuilder; use errors::DiagnosticBuilder;
use hir; use hir;
use hir::def_id::LOCAL_CRATE; use hir::def_id::LOCAL_CRATE;
@ -133,6 +133,12 @@ pub enum CheckLintNameResult<'a> {
/// The lint is either renamed or removed. This is the warning /// The lint is either renamed or removed. This is the warning
/// message, and an optional new name (`None` if removed). /// message, and an optional new name (`None` if removed).
Warning(String, Option<String>), Warning(String, Option<String>),
/// The lint is from a tool. If the Option is None, then either
/// the lint does not exist in the tool or the code was not
/// compiled with the tool and therefore the lint was never
/// added to the `LintStore`. Otherwise the `LintId` will be
/// returned as if it where a rustc lint.
Tool(Option<&'a [LintId]>),
} }
impl LintStore { impl LintStore {
@ -288,7 +294,7 @@ impl LintStore {
sess: &Session, sess: &Session,
lint_name: &str, lint_name: &str,
level: Level) { level: Level) {
let db = match self.check_lint_name(lint_name) { let db = match self.check_lint_name(lint_name, None) {
CheckLintNameResult::Ok(_) => None, CheckLintNameResult::Ok(_) => None,
CheckLintNameResult::Warning(ref msg, _) => { CheckLintNameResult::Warning(ref msg, _) => {
Some(sess.struct_warn(msg)) Some(sess.struct_warn(msg))
@ -296,6 +302,7 @@ impl LintStore {
CheckLintNameResult::NoLint => { CheckLintNameResult::NoLint => {
Some(struct_err!(sess, E0602, "unknown lint: `{}`", lint_name)) Some(struct_err!(sess, E0602, "unknown lint: `{}`", lint_name))
} }
CheckLintNameResult::Tool(_) => unreachable!(),
}; };
if let Some(mut db) = db { if let Some(mut db) = db {
@ -319,26 +326,41 @@ impl LintStore {
/// it emits non-fatal warnings and there are *two* lint passes that /// it emits non-fatal warnings and there are *two* lint passes that
/// inspect attributes, this is only run from the late pass to avoid /// inspect attributes, this is only run from the late pass to avoid
/// printing duplicate warnings. /// printing duplicate warnings.
pub fn check_lint_name(&self, lint_name: &str) -> CheckLintNameResult { pub fn check_lint_name(
match self.by_name.get(lint_name) { &self,
Some(&Renamed(ref new_name, _)) => { lint_name: &str,
CheckLintNameResult::Warning( tool_name: Option<LocalInternedString>,
) -> CheckLintNameResult {
let complete_name = if let Some(tool_name) = tool_name {
format!("{}::{}", tool_name, lint_name)
} else {
lint_name.to_string()
};
if let Some(_) = tool_name {
match self.by_name.get(&complete_name) {
None => match self.lint_groups.get(&*complete_name) {
None => return CheckLintNameResult::Tool(None),
Some(ids) => return CheckLintNameResult::Tool(Some(&ids.0)),
},
Some(&Id(ref id)) => return CheckLintNameResult::Tool(Some(slice::from_ref(id))),
// If the lint was registered as removed or renamed by the lint tool, we don't need
// to treat tool_lints and rustc lints different and can use the code below.
_ => {}
}
}
match self.by_name.get(&complete_name) {
Some(&Renamed(ref new_name, _)) => CheckLintNameResult::Warning(
format!("lint `{}` has been renamed to `{}`", lint_name, new_name), format!("lint `{}` has been renamed to `{}`", lint_name, new_name),
Some(new_name.to_owned()) Some(new_name.to_owned()),
) ),
}, Some(&Removed(ref reason)) => CheckLintNameResult::Warning(
Some(&Removed(ref reason)) => {
CheckLintNameResult::Warning(
format!("lint `{}` has been removed: `{}`", lint_name, reason), format!("lint `{}` has been removed: `{}`", lint_name, reason),
None None,
) ),
}, None => match self.lint_groups.get(&*complete_name) {
None => {
match self.lint_groups.get(lint_name) {
None => CheckLintNameResult::NoLint, None => CheckLintNameResult::NoLint,
Some(ids) => CheckLintNameResult::Ok(&ids.0), Some(ids) => CheckLintNameResult::Ok(&ids.0),
} },
}
Some(&Id(ref id)) => CheckLintNameResult::Ok(slice::from_ref(id)), Some(&Id(ref id)) => CheckLintNameResult::Ok(slice::from_ref(id)),
} }
} }

View file

@ -227,8 +227,10 @@ impl<'a> LintLevelsBuilder<'a> {
continue continue
} }
}; };
if let Some(lint_tool) = word.is_scoped() { let tool_name = if let Some(lint_tool) = word.is_scoped() {
if !self.sess.features_untracked().tool_lints { let gate_feature = !self.sess.features_untracked().tool_lints;
let known_tool = attr::is_known_lint_tool(lint_tool);
if gate_feature {
feature_gate::emit_feature_err(&sess.parse_sess, feature_gate::emit_feature_err(&sess.parse_sess,
"tool_lints", "tool_lints",
word.span, word.span,
@ -236,8 +238,7 @@ impl<'a> LintLevelsBuilder<'a> {
&format!("scoped lint `{}` is experimental", &format!("scoped lint `{}` is experimental",
word.ident)); word.ident));
} }
if !known_tool {
if !attr::is_known_lint_tool(lint_tool) {
span_err!( span_err!(
sess, sess,
lint_tool.span, lint_tool.span,
@ -247,10 +248,16 @@ impl<'a> LintLevelsBuilder<'a> {
); );
} }
if gate_feature || !known_tool {
continue continue
} }
Some(lint_tool.as_str())
} else {
None
};
let name = word.name(); let name = word.name();
match store.check_lint_name(&name.as_str()) { match store.check_lint_name(&name.as_str(), tool_name) {
CheckLintNameResult::Ok(ids) => { CheckLintNameResult::Ok(ids) => {
let src = LintSource::Node(name, li.span); let src = LintSource::Node(name, li.span);
for id in ids { for id in ids {
@ -258,6 +265,19 @@ impl<'a> LintLevelsBuilder<'a> {
} }
} }
CheckLintNameResult::Tool(result) => {
if let Some(ids) = result {
let complete_name = &format!("{}::{}", tool_name.unwrap(), name);
let src = LintSource::Node(Symbol::intern(complete_name), li.span);
for id in ids {
specs.insert(*id, (level, src));
}
}
//FIXME: if Tool(None) is returned than the lint either does not exist in
//the lint tool or the code doesn't get compiled with the lint tool and
//therefore the lint cannot exist.
}
_ if !self.warn_about_weird_lints => {} _ if !self.warn_about_weird_lints => {}
CheckLintNameResult::Warning(msg, renamed) => { CheckLintNameResult::Warning(msg, renamed) => {
@ -298,7 +318,7 @@ impl<'a> LintLevelsBuilder<'a> {
if name.as_str().chars().any(|c| c.is_uppercase()) { if name.as_str().chars().any(|c| c.is_uppercase()) {
let name_lower = name.as_str().to_lowercase().to_string(); let name_lower = name.as_str().to_lowercase().to_string();
if let CheckLintNameResult::NoLint = if let CheckLintNameResult::NoLint =
store.check_lint_name(&name_lower) { store.check_lint_name(&name_lower, tool_name) {
db.emit(); db.emit();
} else { } else {
db.span_suggestion_with_applicability( db.span_suggestion_with_applicability(