Skip to content

Commit

Permalink
Fix needless_doctest_main span
Browse files Browse the repository at this point in the history
  • Loading branch information
Andre Bogus committed Mar 3, 2020
1 parent f44181e commit baae1f9
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 9 deletions.
1 change: 1 addition & 0 deletions clippy_lints/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ semver = "0.9.0"
# NOTE: cargo requires serde feat in its url dep
# see <https://github.com/rust-lang/rust/pull/63587#issuecomment-522343864>
url = { version = "2.1.0", features = ["serde"] }
bytecount = "0.6.0"

[features]
deny-warnings = []
27 changes: 21 additions & 6 deletions clippy_lints/src/doc.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
use crate::utils::{get_trait_def_id, implements_trait, is_entrypoint_fn, match_type, paths, return_ty, span_lint};
use crate::utils::{
get_trait_def_id, implements_trait, is_entrypoint_fn, match_type, paths, return_ty, snippet_opt, span_lint,
};
use bytecount::count;
use if_chain::if_chain;
use itertools::Itertools;
use rustc::lint::in_external_macro;
Expand Down Expand Up @@ -357,9 +360,9 @@ fn check_attrs<'a>(cx: &LateContext<'_, '_>, valid_idents: &FxHashSet<String>, a

match (previous.0, current.0) {
(Text(previous), Text(current)) => {
let mut previous = previous.to_string();
previous.push_str(&current);
Ok((Text(previous.into()), previous_range))
let text = (previous.to_string() + &current).into();
let range = previous_range.start..current_range.end;
Ok((Text(text), range))
},
(previous, current) => Err(((previous, previous_range), (current, current_range))),
}
Expand Down Expand Up @@ -413,6 +416,12 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
};
let (begin, span) = spans[index];
if in_code {
let lo = span.lo() + BytePos::from_usize(range.start - begin);
let span = Span::new(
lo,
lo + BytePos::from_usize(text.len() + count(text.as_bytes(), b'\n') * 4),
span.ctxt(),
);
check_code(cx, &text, span);
} else {
// Adjust for the beginning of the current `Event`
Expand All @@ -429,8 +438,14 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
static LEAVE_MAIN_PATTERNS: &[&str] = &["static", "fn main() {}", "extern crate", "async fn main() {"];

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");
if let Some(comment) = snippet_opt(cx, span) {
if let Some(offset) = comment.find("fn main() {") {
if !LEAVE_MAIN_PATTERNS.iter().any(|p| text.contains(p)) {
let lo = span.lo() + BytePos::from_usize(offset);
let span = Span::new(lo, lo + BytePos::from_usize("fn main()".len()), span.ctxt());
span_lint(cx, NEEDLESS_DOCTEST_MAIN, span, "needless `fn main` in doctest");
}
}
}
}

Expand Down
11 changes: 11 additions & 0 deletions tests/ui/needless_doc_main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,17 @@
/// unimplemented!();
/// }
/// ```
///
/// This should also lint, and have correct span
///
/// ```
/// use std::io::Write as _;
///
/// fn main() {
/// let x = String::new();
/// write!(x, "Hallo");
/// }
/// ```
fn bad_doctest() {}

/// # Examples
Expand Down
12 changes: 9 additions & 3 deletions tests/ui/needless_doc_main.stderr
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
error: needless `fn main` in doctest
--> $DIR/needless_doc_main.rs:7:4
--> $DIR/needless_doc_main.rs:7:5
|
LL | /// fn main() {
| ^^^^^^^^^^^^
| ^^^^^^^^^
|
= note: `-D clippy::needless-doctest-main` implied by `-D warnings`

error: aborting due to previous error
error: needless `fn main` in doctest
--> $DIR/needless_doc_main.rs:17:5
|
LL | /// fn main() {
| ^^^^^^^^^

error: aborting due to 2 previous errors

0 comments on commit baae1f9

Please sign in to comment.