From 92a60151bf9c9f9c09ea841bb6e440599a8e6400 Mon Sep 17 00:00:00 2001 From: Andre Bogus Date: Wed, 15 Jan 2020 19:07:13 +0100 Subject: [PATCH] use syn in needless_doctest_main lint --- clippy_lints/Cargo.toml | 7 +++---- clippy_lints/src/doc.rs | 33 +++++++++++++++++++++++++++++---- 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index dae403cbb4f1..7bda7b6309c1 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -25,14 +25,13 @@ matches = "0.1.7" pulldown-cmark = "0.6.0" quine-mc_cluskey = "0.2.2" regex-syntax = "0.6" +semver = "0.9.0" serde = { version = "1.0", features = ["derive"] } smallvec = { version = "1", features = ["union"] } +syn = { version = "1.0", features = ["full"] } toml = "0.5.3" unicode-normalization = "0.1" -semver = "0.9.0" -# NOTE: cargo requires serde feat in its url dep -# see -url = { version = "2.1.0", features = ["serde"] } +url = "2.1.0" [features] deny-warnings = [] diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs index dd09499c0ceb..5aeb9e853a51 100644 --- a/clippy_lints/src/doc.rs +++ b/clippy_lints/src/doc.rs @@ -395,11 +395,36 @@ fn check_doc<'a, Events: Iterator, Range bool { + match item { + syn::Item::Const(..) | syn::Item::Static(..) | syn::Item::ExternCrate(..) | syn::Item::ForeignMod(..) => true, + _ => false, + } +} -fn check_code(cx: &LateContext<'_, '_>, text: &str, span: Span) { - if text.contains("fn main() {") && !LEAVE_MAIN_PATTERNS.iter().any(|p| text.contains(p)) { - span_lint(cx, NEEDLESS_DOCTEST_MAIN, span, "needless `fn main` in doctest"); +// check a syn Item for non-empty `fn main() { .. }` +fn is_default_main_fn(item: &syn::Item) -> bool { + match item { + syn::Item::Fn(syn::ItemFn { ref sig, ref block, .. }) => { + !block.stmts.is_empty() + && sig.ident == "main" + && match sig.output { + syn::ReturnType::Default => true, + syn::ReturnType::Type(_, ref ty) => match **ty { + syn::Type::Tuple(syn::TypeTuple { ref elems, .. }) => elems.is_empty(), + _ => false, + }, + } + }, + _ => false, + } +} + +fn check_code(cx: &LateContext<'_, '_>, code: &str, span: Span) { + if let Ok(file) = syn::parse_file(code) { + if file.items.iter().any(is_default_main_fn) && !file.items.iter().any(needs_main) { + span_lint(cx, NEEDLESS_DOCTEST_MAIN, span, "needless `fn main` in doctest"); + } } }