diff options
| author | flip1995 <9744647+flip1995@users.noreply.github.com> | 2018-07-30 11:29:23 +0200 |
|---|---|---|
| committer | flip1995 <9744647+flip1995@users.noreply.github.com> | 2018-07-30 16:10:41 +0200 |
| commit | 57c77426ae6b4f9380a85a2aed80dc0900e7b93c (patch) | |
| tree | 53c45b4b88720b12078c6d5f237b8bcbaa714000 | |
| parent | 4b466ee4f94d7c17b0634495dc959e6f5dd4cc5a (diff) | |
| download | rust-57c77426ae6b4f9380a85a2aed80dc0900e7b93c.tar.gz rust-57c77426ae6b4f9380a85a2aed80dc0900e7b93c.zip | |
Check if the lint_name is from a tool and if the tool_lint exists
| -rw-r--r-- | src/librustc/lint/context.rs | 64 | ||||
| -rw-r--r-- | src/librustc/lint/levels.rs | 36 |
2 files changed, 71 insertions, 29 deletions
diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 14cfaa81533..15630157722 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -42,7 +42,7 @@ use util::nodemap::FxHashMap; use std::default::Default as StdDefault; use syntax::ast; use syntax::edition; -use syntax_pos::{MultiSpan, Span}; +use syntax_pos::{MultiSpan, Span, symbol::LocalInternedString}; use errors::DiagnosticBuilder; use hir; 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 /// message, and an optional new name (`None` if removed). 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 { @@ -288,7 +294,7 @@ impl LintStore { sess: &Session, lint_name: &str, 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::Warning(ref msg, _) => { Some(sess.struct_warn(msg)) @@ -296,6 +302,7 @@ impl LintStore { CheckLintNameResult::NoLint => { Some(struct_err!(sess, E0602, "unknown lint: `{}`", lint_name)) } + CheckLintNameResult::Tool(_) => unreachable!(), }; if let Some(mut db) = db { @@ -319,26 +326,41 @@ impl LintStore { /// it emits non-fatal warnings and there are *two* lint passes that /// inspect attributes, this is only run from the late pass to avoid /// printing duplicate warnings. - pub fn check_lint_name(&self, lint_name: &str) -> CheckLintNameResult { - match self.by_name.get(lint_name) { - Some(&Renamed(ref new_name, _)) => { - CheckLintNameResult::Warning( - format!("lint `{}` has been renamed to `{}`", lint_name, new_name), - Some(new_name.to_owned()) - ) - }, - Some(&Removed(ref reason)) => { - CheckLintNameResult::Warning( - format!("lint `{}` has been removed: `{}`", lint_name, reason), - None - ) - }, - None => { - match self.lint_groups.get(lint_name) { - None => CheckLintNameResult::NoLint, - Some(ids) => CheckLintNameResult::Ok(&ids.0), - } + pub fn check_lint_name( + &self, + lint_name: &str, + 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), + Some(new_name.to_owned()), + ), + Some(&Removed(ref reason)) => CheckLintNameResult::Warning( + format!("lint `{}` has been removed: `{}`", lint_name, reason), + None, + ), + None => match self.lint_groups.get(&*complete_name) { + None => CheckLintNameResult::NoLint, + Some(ids) => CheckLintNameResult::Ok(&ids.0), + }, Some(&Id(ref id)) => CheckLintNameResult::Ok(slice::from_ref(id)), } } diff --git a/src/librustc/lint/levels.rs b/src/librustc/lint/levels.rs index b7b6aba970b..6a29b8c3e3e 100644 --- a/src/librustc/lint/levels.rs +++ b/src/librustc/lint/levels.rs @@ -227,8 +227,10 @@ impl<'a> LintLevelsBuilder<'a> { continue } }; - if let Some(lint_tool) = word.is_scoped() { - if !self.sess.features_untracked().tool_lints { + let tool_name = if let Some(lint_tool) = word.is_scoped() { + 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, "tool_lints", word.span, @@ -236,8 +238,7 @@ impl<'a> LintLevelsBuilder<'a> { &format!("scoped lint `{}` is experimental", word.ident)); } - - if !attr::is_known_lint_tool(lint_tool) { + if !known_tool { span_err!( sess, lint_tool.span, @@ -247,10 +248,16 @@ impl<'a> LintLevelsBuilder<'a> { ); } - continue - } + if gate_feature || !known_tool { + continue + } + + Some(lint_tool.as_str()) + } else { + None + }; 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) => { let src = LintSource::Node(name, li.span); 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 => {} CheckLintNameResult::Warning(msg, renamed) => { @@ -298,7 +318,7 @@ impl<'a> LintLevelsBuilder<'a> { if name.as_str().chars().any(|c| c.is_uppercase()) { let name_lower = name.as_str().to_lowercase().to_string(); if let CheckLintNameResult::NoLint = - store.check_lint_name(&name_lower) { + store.check_lint_name(&name_lower, tool_name) { db.emit(); } else { db.span_suggestion_with_applicability( |
