mirror of
https://github.com/rust-lang/rust-clippy
synced 2024-11-14 08:57:30 +00:00
use hashset not map for keeping track of seen macro refs
remove stdout, fix clippy warnings, fmtcar
This commit is contained in:
parent
ede366be63
commit
8ffbf6f94d
5 changed files with 97 additions and 100 deletions
|
@ -2,7 +2,7 @@ use crate::utils::{in_macro, snippet, span_lint_and_sugg};
|
|||
use hir::def::{DefKind, Res};
|
||||
use if_chain::if_chain;
|
||||
use rustc_ast::ast;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir as hir;
|
||||
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
||||
|
@ -29,7 +29,7 @@ declare_clippy_lint! {
|
|||
|
||||
const BRACKETS: &[char] = &['<', '>'];
|
||||
|
||||
/// MacroRefData includes the name of the macro
|
||||
/// `MacroRefData` includes the name of the macro
|
||||
/// and the path from `SourceMap::span_to_filename`.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct MacroRefData {
|
||||
|
@ -38,11 +38,11 @@ pub struct MacroRefData {
|
|||
}
|
||||
|
||||
impl MacroRefData {
|
||||
pub fn new(name: String, span: Span, ecx: &LateContext<'_, '_>) -> Self {
|
||||
pub fn new(name: &str, span: Span, ecx: &LateContext<'_, '_>) -> Self {
|
||||
let mut path = ecx.sess().source_map().span_to_filename(span).to_string();
|
||||
|
||||
// std lib paths are <::std::module::file type>
|
||||
// so remove brackets and space
|
||||
// so remove brackets, space and type.
|
||||
if path.contains('<') {
|
||||
path = path.replace(BRACKETS, "");
|
||||
}
|
||||
|
@ -57,13 +57,12 @@ impl MacroRefData {
|
|||
}
|
||||
|
||||
#[derive(Default)]
|
||||
#[allow(clippy::module_name_repetitions)]
|
||||
pub struct MacroUseImports {
|
||||
/// the actual import path used and the span of the attribute above it.
|
||||
imports: Vec<(String, Span)>,
|
||||
/// the span of the macro reference and the `MacroRefData`
|
||||
/// for the use of the macro.
|
||||
/// TODO make this FxHashSet<Span> to guard against inserting already found macros
|
||||
collected: FxHashMap<Span, MacroRefData>,
|
||||
/// the span of the macro reference, kept to ensure only one reference is used per macro call.
|
||||
collected: FxHashSet<Span>,
|
||||
mac_refs: Vec<(Span, MacroRefData)>,
|
||||
}
|
||||
|
||||
|
@ -80,14 +79,9 @@ impl<'l, 'txc> LateLintPass<'l, 'txc> for MacroUseImports {
|
|||
.find(|attr| attr.ident().map(|s| s.to_string()) == Some("macro_use".to_string()));
|
||||
if let Res::Def(DefKind::Mod, id) = path.res;
|
||||
then {
|
||||
// println!("{:#?}", lcx.tcx.def_path_str(id));
|
||||
for kid in lcx.tcx.item_children(id).iter() {
|
||||
// println!("{:#?}", kid);
|
||||
if let Res::Def(DefKind::Macro(_mac_type), mac_id) = kid.res {
|
||||
let span = mac_attr.span.clone();
|
||||
|
||||
// println!("{:#?}", lcx.tcx.def_path_str(mac_id));
|
||||
|
||||
let span = mac_attr.span;
|
||||
self.imports.push((lcx.tcx.def_path_str(mac_id), span));
|
||||
}
|
||||
}
|
||||
|
@ -96,10 +90,9 @@ impl<'l, 'txc> LateLintPass<'l, 'txc> for MacroUseImports {
|
|||
let call_site = item.span.source_callsite();
|
||||
let name = snippet(lcx, lcx.sess().source_map().span_until_char(call_site, '!'), "_");
|
||||
if let Some(callee) = item.span.source_callee() {
|
||||
if !self.collected.contains_key(&call_site) {
|
||||
let mac = MacroRefData::new(name.to_string(), callee.def_site, lcx);
|
||||
self.mac_refs.push((call_site, mac.clone()));
|
||||
self.collected.insert(call_site, mac);
|
||||
if !self.collected.contains(&call_site) {
|
||||
self.mac_refs.push((call_site, MacroRefData::new(&name, callee.def_site, lcx)));
|
||||
self.collected.insert(call_site);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -111,18 +104,16 @@ impl<'l, 'txc> LateLintPass<'l, 'txc> for MacroUseImports {
|
|||
let call_site = attr.span.source_callsite();
|
||||
let name = snippet(lcx, lcx.sess().source_map().span_until_char(call_site, '!'), "_");
|
||||
if let Some(callee) = attr.span.source_callee() {
|
||||
if !self.collected.contains_key(&call_site) {
|
||||
println!("{:?}\n{:#?}", call_site, attr);
|
||||
|
||||
if !self.collected.contains(&call_site) {
|
||||
let name = if name.contains("::") {
|
||||
name.split("::").last().unwrap().to_string()
|
||||
} else {
|
||||
name.to_string()
|
||||
};
|
||||
|
||||
let mac = MacroRefData::new(name, callee.def_site, lcx);
|
||||
self.mac_refs.push((call_site, mac.clone()));
|
||||
self.collected.insert(call_site, mac);
|
||||
self.mac_refs
|
||||
.push((call_site, MacroRefData::new(&name, callee.def_site, lcx)));
|
||||
self.collected.insert(call_site);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -132,16 +123,16 @@ impl<'l, 'txc> LateLintPass<'l, 'txc> for MacroUseImports {
|
|||
let call_site = expr.span.source_callsite();
|
||||
let name = snippet(lcx, lcx.sess().source_map().span_until_char(call_site, '!'), "_");
|
||||
if let Some(callee) = expr.span.source_callee() {
|
||||
if !self.collected.contains_key(&call_site) {
|
||||
if !self.collected.contains(&call_site) {
|
||||
let name = if name.contains("::") {
|
||||
name.split("::").last().unwrap().to_string()
|
||||
} else {
|
||||
name.to_string()
|
||||
};
|
||||
|
||||
let mac = MacroRefData::new(name, callee.def_site, lcx);
|
||||
self.mac_refs.push((call_site, mac.clone()));
|
||||
self.collected.insert(call_site, mac);
|
||||
self.mac_refs
|
||||
.push((call_site, MacroRefData::new(&name, callee.def_site, lcx)));
|
||||
self.collected.insert(call_site);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -151,16 +142,16 @@ impl<'l, 'txc> LateLintPass<'l, 'txc> for MacroUseImports {
|
|||
let call_site = stmt.span.source_callsite();
|
||||
let name = snippet(lcx, lcx.sess().source_map().span_until_char(call_site, '!'), "_");
|
||||
if let Some(callee) = stmt.span.source_callee() {
|
||||
if !self.collected.contains_key(&call_site) {
|
||||
if !self.collected.contains(&call_site) {
|
||||
let name = if name.contains("::") {
|
||||
name.split("::").last().unwrap().to_string()
|
||||
} else {
|
||||
name.to_string()
|
||||
};
|
||||
|
||||
let mac = MacroRefData::new(name, callee.def_site, lcx);
|
||||
self.mac_refs.push((call_site, mac.clone()));
|
||||
self.collected.insert(call_site, mac);
|
||||
self.mac_refs
|
||||
.push((call_site, MacroRefData::new(&name, callee.def_site, lcx)));
|
||||
self.collected.insert(call_site);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -170,10 +161,10 @@ impl<'l, 'txc> LateLintPass<'l, 'txc> for MacroUseImports {
|
|||
let call_site = pat.span.source_callsite();
|
||||
let name = snippet(lcx, lcx.sess().source_map().span_until_char(call_site, '!'), "_");
|
||||
if let Some(callee) = pat.span.source_callee() {
|
||||
if !self.collected.contains_key(&call_site) {
|
||||
let mac = MacroRefData::new(name.to_string(), callee.def_site, lcx);
|
||||
self.mac_refs.push((call_site, mac.clone()));
|
||||
self.collected.insert(call_site, mac);
|
||||
if !self.collected.contains(&call_site) {
|
||||
self.mac_refs
|
||||
.push((call_site, MacroRefData::new(&name, callee.def_site, lcx)));
|
||||
self.collected.insert(call_site);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -183,22 +174,18 @@ impl<'l, 'txc> LateLintPass<'l, 'txc> for MacroUseImports {
|
|||
let call_site = ty.span.source_callsite();
|
||||
let name = snippet(lcx, lcx.sess().source_map().span_until_char(call_site, '!'), "_");
|
||||
if let Some(callee) = ty.span.source_callee() {
|
||||
if !self.collected.contains_key(&call_site) {
|
||||
let mac = MacroRefData::new(name.to_string(), callee.def_site, lcx);
|
||||
self.mac_refs.push((call_site, mac.clone()));
|
||||
self.collected.insert(call_site, mac);
|
||||
if !self.collected.contains(&call_site) {
|
||||
self.mac_refs
|
||||
.push((call_site, MacroRefData::new(&name, callee.def_site, lcx)));
|
||||
self.collected.insert(call_site);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn check_crate_post(&mut self, lcx: &LateContext<'_, '_>, _krate: &hir::Crate<'_>) {
|
||||
for (import, span) in self.imports.iter() {
|
||||
let matched = self
|
||||
.mac_refs
|
||||
.iter()
|
||||
.find(|(_span, mac)| import.ends_with(&mac.name))
|
||||
.is_some();
|
||||
for (import, span) in &self.imports {
|
||||
let matched = self.mac_refs.iter().any(|(_span, mac)| import.ends_with(&mac.name));
|
||||
|
||||
if matched {
|
||||
self.mac_refs.retain(|(_span, mac)| !import.ends_with(&mac.name));
|
||||
|
@ -218,30 +205,8 @@ impl<'l, 'txc> LateLintPass<'l, 'txc> for MacroUseImports {
|
|||
if !self.mac_refs.is_empty() {
|
||||
// TODO if not empty we found one we could not make a suggestion for
|
||||
// such as std::prelude::v1 or something else I haven't thought of.
|
||||
// println!("{:#?}", self.mac_refs);
|
||||
// If we defer the calling of span_lint_and_sugg we can make a decision about its
|
||||
// applicability?
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const PRELUDE: &[&str] = &[
|
||||
"marker", "ops", "convert", "iter", "option", "result", "borrow", "boxed", "string", "vec", "macros",
|
||||
];
|
||||
|
||||
/// This is somewhat of a fallback for imports from `std::prelude` because they
|
||||
/// are not recognized by `LateLintPass::check_item` `lcx.tcx.item_children(id)`
|
||||
fn make_path(mac: &MacroRefData, use_path: &str) -> String {
|
||||
let segs = mac.path.split("::").filter(|s| *s != "").collect::<Vec<_>>();
|
||||
|
||||
if segs.starts_with(&["std"]) && PRELUDE.iter().any(|m| segs.contains(m)) {
|
||||
return format!(
|
||||
"std::prelude::{} is imported by default, remove `use` statement",
|
||||
mac.name
|
||||
);
|
||||
}
|
||||
|
||||
if use_path.split("::").count() == 1 {
|
||||
return format!("{}::{}", use_path, mac.name);
|
||||
}
|
||||
|
||||
mac.path.clone()
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ pub mod inner {
|
|||
|
||||
// ITEM
|
||||
#[macro_export]
|
||||
macro_rules! inner_mod {
|
||||
macro_rules! inner_mod_macro {
|
||||
() => {
|
||||
#[allow(dead_code)]
|
||||
pub struct Tardis;
|
||||
|
@ -27,7 +27,7 @@ pub mod inner {
|
|||
|
||||
// EXPR
|
||||
#[macro_export]
|
||||
macro_rules! function {
|
||||
macro_rules! function_macro {
|
||||
() => {
|
||||
if true {
|
||||
} else {
|
||||
|
@ -37,7 +37,7 @@ macro_rules! function {
|
|||
|
||||
// TYPE
|
||||
#[macro_export]
|
||||
macro_rules! ty_mac {
|
||||
macro_rules! ty_macro {
|
||||
() => {
|
||||
Vec<u8>
|
||||
};
|
||||
|
@ -46,7 +46,7 @@ macro_rules! ty_mac {
|
|||
mod extern_exports {
|
||||
pub(super) mod private_inner {
|
||||
#[macro_export]
|
||||
macro_rules! pub_in_private {
|
||||
macro_rules! pub_in_private_macro {
|
||||
($name:ident) => {
|
||||
let $name = String::from("secrets and lies");
|
||||
};
|
||||
|
|
|
@ -12,8 +12,6 @@ extern crate macro_use_helper as mac;
|
|||
extern crate clippy_mini_macro_test as mini_mac;
|
||||
|
||||
mod a {
|
||||
#[macro_use]
|
||||
use std::prelude;
|
||||
#[macro_use]
|
||||
use mac;
|
||||
#[macro_use]
|
||||
|
@ -26,15 +24,13 @@ mod a {
|
|||
|
||||
fn main() {
|
||||
pub_macro!();
|
||||
inner_mod!();
|
||||
pub_in_private!(_var);
|
||||
function!();
|
||||
let v: ty_mac!() = Vec::default();
|
||||
inner_mod_macro!();
|
||||
pub_in_private_macro!(_var);
|
||||
function_macro!();
|
||||
let v: ty_macro!() = Vec::default();
|
||||
|
||||
inner::try_err!();
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
println!();
|
||||
}
|
||||
fn main() {}
|
||||
|
|
|
@ -1,10 +1,46 @@
|
|||
error: `macro_use` attributes are no longer needed in the Rust 2018 edition
|
||||
--> $DIR/macro_use_imports.rs:5:1
|
||||
--> $DIR/macro_use_imports.rs:15:5
|
||||
|
|
||||
LL | #[macro_use]
|
||||
| ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use std::prelude::<macro name>`
|
||||
| ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::pub_macro`
|
||||
|
|
||||
= note: `-D clippy::macro-use-imports` implied by `-D warnings`
|
||||
|
||||
error: aborting due to previous error
|
||||
error: `macro_use` attributes are no longer needed in the Rust 2018 edition
|
||||
--> $DIR/macro_use_imports.rs:15:5
|
||||
|
|
||||
LL | #[macro_use]
|
||||
| ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::inner_mod_macro`
|
||||
|
||||
error: `macro_use` attributes are no longer needed in the Rust 2018 edition
|
||||
--> $DIR/macro_use_imports.rs:15:5
|
||||
|
|
||||
LL | #[macro_use]
|
||||
| ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::function_macro`
|
||||
|
||||
error: `macro_use` attributes are no longer needed in the Rust 2018 edition
|
||||
--> $DIR/macro_use_imports.rs:15:5
|
||||
|
|
||||
LL | #[macro_use]
|
||||
| ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::ty_macro`
|
||||
|
||||
error: `macro_use` attributes are no longer needed in the Rust 2018 edition
|
||||
--> $DIR/macro_use_imports.rs:15:5
|
||||
|
|
||||
LL | #[macro_use]
|
||||
| ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::pub_in_private_macro`
|
||||
|
||||
error: `macro_use` attributes are no longer needed in the Rust 2018 edition
|
||||
--> $DIR/macro_use_imports.rs:17:5
|
||||
|
|
||||
LL | #[macro_use]
|
||||
| ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mini_mac::ClippyMiniMacroTest`
|
||||
|
||||
error: `macro_use` attributes are no longer needed in the Rust 2018 edition
|
||||
--> $DIR/macro_use_imports.rs:19:5
|
||||
|
|
||||
LL | #[macro_use]
|
||||
| ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use mac::inner::try_err`
|
||||
|
||||
error: aborting due to 7 previous errors
|
||||
|
||||
|
|
Loading…
Reference in a new issue