use rustc_span::{sym, FileName, Pos};
use std::io;
use std::ops::Range;
+use std::thread;
use url::Url;
declare_clippy_lint! {
- /// **What it does:** Checks for the presence of `_`, `::` or camel-case words
+ /// ### What it does
+ /// Checks for the presence of `_`, `::` or camel-case words
/// outside ticks in documentation.
///
- /// **Why is this bad?** *Rustdoc* supports markdown formatting, `_`, `::` and
+ /// ### Why is this bad?
+ /// *Rustdoc* supports markdown formatting, `_`, `::` and
/// camel-case probably indicates some code which should be included between
/// ticks. `_` can also be used for emphasis in markdown, this lint tries to
/// consider that.
///
- /// **Known problems:** Lots of bad docs won’t be fixed, what the lint checks
+ /// ### Known problems
+ /// Lots of bad docs won’t be fixed, what the lint checks
/// for is limited, and there are still false positives. HTML elements and their
/// content are not linted.
///
/// `[`SmallVec<[T; INLINE_CAPACITY]>`]` and then [`SmallVec<[T; INLINE_CAPACITY]>`]: SmallVec
/// would fail.
///
- /// **Examples:**
+ /// ### Examples
/// ```rust
/// /// Do something with the foo_bar parameter. See also
/// /// that::other::module::foo.
}
declare_clippy_lint! {
- /// **What it does:** Checks for the doc comments of publicly visible
+ /// ### What it does
+ /// Checks for the doc comments of publicly visible
/// unsafe functions and warns if there is no `# Safety` section.
///
- /// **Why is this bad?** Unsafe functions should document their safety
+ /// ### Why is this bad?
+ /// Unsafe functions should document their safety
/// preconditions, so that users can be sure they are using them safely.
///
- /// **Known problems:** None.
- ///
- /// **Examples:**
+ /// ### Examples
/// ```rust
///# type Universe = ();
/// /// This function should really be documented
}
declare_clippy_lint! {
- /// **What it does:** Checks the doc comments of publicly visible functions that
+ /// ### What it does
+ /// Checks the doc comments of publicly visible functions that
/// return a `Result` type and warns if there is no `# Errors` section.
///
- /// **Why is this bad?** Documenting the type of errors that can be returned from a
+ /// ### Why is this bad?
+ /// Documenting the type of errors that can be returned from a
/// function can help callers write code to handle the errors appropriately.
///
- /// **Known problems:** None.
- ///
- /// **Examples:**
- ///
+ /// ### Examples
/// Since the following function returns a `Result` it has an `# Errors` section in
/// its doc comment:
///
}
declare_clippy_lint! {
- /// **What it does:** Checks the doc comments of publicly visible functions that
+ /// ### What it does
+ /// Checks the doc comments of publicly visible functions that
/// may panic and warns if there is no `# Panics` section.
///
- /// **Why is this bad?** Documenting the scenarios in which panicking occurs
+ /// ### Why is this bad?
+ /// Documenting the scenarios in which panicking occurs
/// can help callers who do not want to panic to avoid those situations.
///
- /// **Known problems:** None.
- ///
- /// **Examples:**
- ///
+ /// ### Examples
/// Since the following function may panic it has a `# Panics` section in
/// its doc comment:
///
}
declare_clippy_lint! {
- /// **What it does:** Checks for `fn main() { .. }` in doctests
+ /// ### What it does
+ /// Checks for `fn main() { .. }` in doctests
///
- /// **Why is this bad?** The test can be shorter (and likely more readable)
+ /// ### Why is this bad?
+ /// The test can be shorter (and likely more readable)
/// if the `fn main()` is left implicit.
///
- /// **Known problems:** None.
- ///
- /// **Examples:**
+ /// ### Examples
/// ``````rust
/// /// An example of a doctest with a `main()` function
/// ///
FootnoteReference(text) | Text(text) => {
let (begin, span) = get_current_span(spans, range.start);
paragraph_span = paragraph_span.with_hi(span.hi());
- ticks_unbalanced |= text.contains('`');
+ ticks_unbalanced |= text.contains('`') && !in_code;
if Some(&text) == in_link.as_ref() || ticks_unbalanced {
// Probably a link of the form `<http://example.com>`
// Which are represented as a link to "http://example.com" with
}
fn check_code(cx: &LateContext<'_>, text: &str, edition: Edition, span: Span) {
- fn has_needless_main(code: &str, edition: Edition) -> bool {
+ fn has_needless_main(code: String, edition: Edition) -> bool {
rustc_driver::catch_fatal_errors(|| {
- rustc_span::with_session_globals(edition, || {
- let filename = FileName::anon_source_code(code);
+ rustc_span::create_session_globals_then(edition, || {
+ let filename = FileName::anon_source_code(&code);
let sm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
let emitter = EmitterWriter::new(box io::sink(), None, false, false, false, None, false);
let handler = Handler::with_emitter(false, None, box emitter);
let sess = ParseSess::with_span_handler(handler, sm);
- let mut parser = match maybe_new_parser_from_source_str(&sess, filename, code.into()) {
+ let mut parser = match maybe_new_parser_from_source_str(&sess, filename, code) {
Ok(p) => p,
Err(errs) => {
for mut err in errs {
.unwrap_or_default()
}
- if has_needless_main(text, edition) {
+ // Because of the global session, we need to create a new session in a different thread with
+ // the edition we need.
+ let text = text.to_owned();
+ if thread::spawn(move || has_needless_main(text, edition))
+ .join()
+ .expect("thread::spawn failed")
+ {
span_lint(cx, NEEDLESS_DOCTEST_MAIN, span, "needless `fn main` in doctest");
}
}