about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEric Huss <eric@huss.org>2020-09-11 08:55:59 -0700
committerEric Huss <eric@huss.org>2020-09-13 08:48:03 -0700
commitce014be0b9d0325ad9e6ecb8c93b3c8186b18089 (patch)
tree9af4c5e58eaed788e9af39f201a144317a6d9e4b
parent45c1e0ae07b9581d8c2d2b39315ac7cc79475d75 (diff)
Link rustdoc lint docs to the rustdoc book.
-rw-r--r--compiler/rustc_session/src/lint/builtin.rs138
-rw-r--r--src/bootstrap/doc.rs3
-rw-r--r--src/doc/rustdoc/src/lints.md58
-rw-r--r--src/tools/lint-docs/src/lib.rs36
-rw-r--r--src/tools/lint-docs/src/main.rs11
5 files changed, 88 insertions, 158 deletions
diff --git a/compiler/rustc_session/src/lint/builtin.rs b/compiler/rustc_session/src/lint/builtin.rs
index 4c0c7fae29b..22030a842db 100644
--- a/compiler/rustc_session/src/lint/builtin.rs
+++ b/compiler/rustc_session/src/lint/builtin.rs
@@ -1817,35 +1817,10 @@ declare_lint! {
 
 declare_lint! {
     /// The `broken_intra_doc_links` lint detects failures in resolving
-    /// intra-doc link targets. This is a `rustdoc` only lint, and only works
-    /// on the [**nightly channel**].
+    /// intra-doc link targets. This is a `rustdoc` only lint, see the
+    /// documentation in the [rustdoc book].
     ///
-    /// [**nightly channel**]: https://doc.rust-lang.org/book/appendix-07-nightly-rust.html
-    ///
-    /// ### Example
-    ///
-    /// ```rust,rustdoc
-    /// /// This is a doc comment.
-    /// ///
-    /// /// See also [`bar`].
-    /// pub fn foo() {
-    /// }
-    /// ```
-    ///
-    /// {{produces}}
-    ///
-    /// ### Explanation
-    ///
-    /// `rustdoc` allows [linking to items by name][intra] which will
-    /// automatically generate links in the documentation to the item. This
-    /// lint is issued when `rustdoc` is unable to find the named item. Check
-    /// that the name is correct, that it is in scope, or if you need to
-    /// qualify it with a path. If you intended to have square brackets appear
-    /// literally in the text, surround the brackets with backticks such as ``
-    /// `[example]` `` to indicate a code span, or prefix it with a backslash
-    /// such as `\[example]`.
-    ///
-    /// [intra]: https://doc.rust-lang.org/nightly/rustdoc/unstable-features.html#linking-to-items-by-name
+    /// [rustdoc book]: ../../../rustdoc/lints.html#broken_intra_doc_links
     pub BROKEN_INTRA_DOC_LINKS,
     Warn,
     "failures in resolving intra-doc link targets"
@@ -1854,27 +1829,9 @@ declare_lint! {
 declare_lint! {
     /// The `invalid_codeblock_attributes` lint detects code block attributes
     /// in documentation examples that have potentially mis-typed values. This
-    /// is a `rustdoc` only lint.
-    ///
-    /// ### Example
+    /// is a `rustdoc` only lint, see the documentation in the [rustdoc book].
     ///
-    /// ```rust,rustdoc
-    /// /// Example.
-    /// ///
-    /// /// ```should-panic
-    /// /// assert_eq!(1, 2);
-    /// /// ```
-    /// pub fn foo() {}
-    /// ```
-    ///
-    /// {{produces}}
-    ///
-    /// ### Explanation
-    ///
-    /// This lint is issued when `rustdoc` detects an example code block
-    /// attribute that appears similar to a valid one. In the example above,
-    /// the correct form is `should_panic`. This helps detect typo mistakes
-    /// for some common attributes.
+    /// [rustdoc book]: ../../../rustdoc/lints.html#invalid_codeblock_attributes
     pub INVALID_CODEBLOCK_ATTRIBUTES,
     Warn,
     "codeblock attribute looks a lot like a known one"
@@ -1882,24 +1839,10 @@ declare_lint! {
 
 declare_lint! {
     /// The `missing_crate_level_docs` lint detects if documentation is
-    /// missing at the crate root. This is a `rustdoc` only lint. This is a
-    /// `rustdoc` only lint.
-    ///
-    /// ### Example
-    ///
-    /// ```rust,rustdoc
-    /// #![deny(missing_crate_level_docs)]
-    /// ```
-    ///
-    /// {{produces}}
-    ///
-    /// ### Explanation
+    /// missing at the crate root. This is a `rustdoc` only lint, see the
+    /// documentation in the [rustdoc book].
     ///
-    /// This lint causes `rustdoc` to check if the crate root is missing
-    /// documentation. This is currently "allow" by default, but it is
-    /// intended to make this a warning in the future. This is intended as a
-    /// means to introduce new users on *how* to document their crate by
-    /// pointing them to some instructions on how to get started.
+    /// [rustdoc book]: ../../../rustdoc/lints.html#missing_crate_level_docs
     pub MISSING_CRATE_LEVEL_DOCS,
     Allow,
     "detects crates with no crate-level documentation"
@@ -1908,43 +1851,9 @@ declare_lint! {
 declare_lint! {
     /// The `missing_doc_code_examples` lint detects publicly-exported items
     /// without code samples in their documentation. This is a `rustdoc` only
-    /// lint, and only works on the [**nightly channel**].
+    /// lint, see the documentation in the [rustdoc book].
     ///
-    /// [**nightly channel**]: https://doc.rust-lang.org/book/appendix-07-nightly-rust.html
-    ///
-    /// ### Example
-    ///
-    /// ```rust,rustdoc
-    /// #![warn(missing_doc_code_examples)]
-    ///
-    /// /// There is no code example!
-    /// pub fn no_code_example() {}
-    /// ```
-    ///
-    /// {{produces}}
-    ///
-    /// ### Explanation
-    ///
-    /// This lint is to ensure a high level of quality for documentation. Code
-    /// examples can be very useful to see how to use an API. To add an
-    /// example, include a markdown code block with an example of how to use
-    /// the item, such as:
-    ///
-    /// ```rust
-    /// /// Adds one to the number given.
-    /// ///
-    /// /// # Examples
-    /// ///
-    /// /// ```
-    /// /// let arg = 5;
-    /// /// let answer = my_crate::add_one(arg);
-    /// ///
-    /// /// assert_eq!(6, answer);
-    /// /// ```
-    /// pub fn add_one(x: i32) -> i32 {
-    ///     x + 1
-    /// }
-    /// ```
+    /// [rustdoc book]: ../../../rustdoc/lints.html#missing_doc_code_examples
     pub MISSING_DOC_CODE_EXAMPLES,
     Allow,
     "detects publicly-exported items without code samples in their documentation"
@@ -1952,31 +1861,10 @@ declare_lint! {
 
 declare_lint! {
     /// The `private_doc_tests` lint detects code samples in docs of private
-    /// items not documented by `rustdoc`. This is a `rustdoc` only lint.
-    ///
-    /// ### Example
-    ///
-    /// ```rust,rustdoc
-    /// #![deny(private_doc_tests)]
+    /// items not documented by `rustdoc`. This is a `rustdoc` only lint, see
+    /// the documentation in the [rustdoc book].
     ///
-    /// mod foo {
-    ///     /// private doc test
-    ///     ///
-    ///     /// ```
-    ///     /// assert!(false);
-    ///     /// ```
-    ///     fn bar() {}
-    /// }
-    /// ```
-    ///
-    /// {{produces}}
-    ///
-    /// ### Explanation
-    ///
-    /// Because documentation examples link against the public API of the
-    /// crate, it is not possible for an example to access a private item.
-    /// This means it was likely a mistake to add a code example to a private
-    /// item.
+    /// [rustdoc book]: ../../../rustdoc/lints.html#private_doc_tests
     pub PRIVATE_DOC_TESTS,
     Allow,
     "detects code samples in docs of private items not documented by rustdoc"
diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs
index be5182b939d..98a0119e4df 100644
--- a/src/bootstrap/doc.rs
+++ b/src/bootstrap/doc.rs
@@ -756,7 +756,6 @@ impl Step for RustcBook {
         // The tool runs `rustc` for extracting output examples, so it needs a
         // functional sysroot.
         builder.ensure(compile::Std { compiler: self.compiler, target: self.target });
-        let rustdoc = builder.rustdoc(self.compiler);
         let mut cmd = builder.tool_cmd(Tool::LintDocs);
         cmd.arg("--src");
         cmd.arg(builder.src.join("compiler"));
@@ -764,8 +763,6 @@ impl Step for RustcBook {
         cmd.arg(&out_listing);
         cmd.arg("--rustc");
         cmd.arg(rustc);
-        cmd.arg("--rustdoc");
-        cmd.arg(rustdoc);
         if builder.config.verbose() {
             cmd.arg("--verbose");
         }
diff --git a/src/doc/rustdoc/src/lints.md b/src/doc/rustdoc/src/lints.md
index 8e2869fef55..ce292c60460 100644
--- a/src/doc/rustdoc/src/lints.md
+++ b/src/doc/rustdoc/src/lints.md
@@ -49,6 +49,30 @@ warning: missing documentation for a function
    | ^^^^^^^^^^^^^^^^^^^^^
 ```
 
+## missing_crate_level_docs
+
+This lint is **allowed by default**. It detects if there is no documentation
+at the crate root. For example:
+
+```rust
+#![warn(missing_crate_level_docs)]
+```
+
+This will generate the following warning:
+
+```text
+warning: no documentation found for this crate's top-level module
+  |
+  = help: The following guide may be of use:
+          https://doc.rust-lang.org/nightly/rustdoc/how-to-write-documentation.html
+```
+
+This is currently "allow" by default, but it is intended to make this a
+warning in the future. This is intended as a means to introduce new users on
+*how* to document their crate by pointing them to some instructions on how to
+get started, without providing overwhelming warnings like `missing_docs`
+might.
+
 ## missing_doc_code_examples
 
 This lint is **allowed by default** and is **nightly-only**. It detects when a documentation block
@@ -117,3 +141,37 @@ warning: Documentation test in private item
  8 | |     /// ```
    | |___________^
 ```
+
+## invalid_codeblock_attributes
+
+This lint **warns by default**. It detects code block attributes in
+documentation examples that have potentially mis-typed values. For example:
+
+```rust
+/// Example.
+///
+/// ```should-panic
+/// assert_eq!(1, 2);
+/// ```
+pub fn foo() {}
+```
+
+Which will give:
+
+```text
+warning: unknown attribute `should-panic`. Did you mean `should_panic`?
+ --> src/lib.rs:1:1
+  |
+1 | / /// Example.
+2 | | ///
+3 | | /// ```should-panic
+4 | | /// assert_eq!(1, 2);
+5 | | /// ```
+  | |_______^
+  |
+  = note: `#[warn(invalid_codeblock_attributes)]` on by default
+  = help: the code block will either not be tested if not marked as a rust one or won't fail if it doesn't panic when running
+```
+
+In the example above, the correct form is `should_panic`. This helps detect
+typo mistakes for some common attributes.
diff --git a/src/tools/lint-docs/src/lib.rs b/src/tools/lint-docs/src/lib.rs
index b1e14ea6c46..a8e3278fc66 100644
--- a/src/tools/lint-docs/src/lib.rs
+++ b/src/tools/lint-docs/src/lib.rs
@@ -15,6 +15,12 @@ struct Lint {
     lineno: usize,
 }
 
+impl Lint {
+    fn doc_contains(&self, text: &str) -> bool {
+        self.doc.iter().any(|line| line.contains(text))
+    }
+}
+
 #[derive(Clone, Copy, PartialEq)]
 enum Level {
     Allow,
@@ -37,12 +43,11 @@ pub fn extract_lint_docs(
     src_path: &Path,
     out_path: &Path,
     rustc_path: &Path,
-    rustdoc_path: &Path,
     verbose: bool,
 ) -> Result<(), Box<dyn Error>> {
     let mut lints = gather_lints(src_path)?;
     for lint in &mut lints {
-        generate_output_example(lint, rustc_path, rustdoc_path, verbose).map_err(|e| {
+        generate_output_example(lint, rustc_path, verbose).map_err(|e| {
             format!(
                 "failed to test example in lint docs for `{}` in {}:{}: {}",
                 lint.name,
@@ -197,7 +202,6 @@ fn lint_name(line: &str) -> Result<String, &'static str> {
 fn generate_output_example(
     lint: &mut Lint,
     rustc_path: &Path,
-    rustdoc_path: &Path,
     verbose: bool,
 ) -> Result<(), Box<dyn Error>> {
     // Explicit list of lints that are allowed to not have an example. Please
@@ -214,15 +218,19 @@ fn generate_output_example(
     ) {
         return Ok(());
     }
+    if lint.doc_contains("[rustdoc book]") && !lint.doc_contains("{{produces}}") {
+        // Rustdoc lints are documented in the rustdoc book, don't check these.
+        return Ok(());
+    }
     check_style(lint)?;
-    replace_produces(lint, rustc_path, rustdoc_path, verbose)?;
+    replace_produces(lint, rustc_path, verbose)?;
     Ok(())
 }
 
 /// Checks the doc style of the lint.
 fn check_style(lint: &Lint) -> Result<(), Box<dyn Error>> {
     for expected in &["### Example", "### Explanation", "{{produces}}"] {
-        if !lint.doc.iter().any(|line| line.contains(expected)) {
+        if !lint.doc_contains(expected) {
             return Err(format!("lint docs should contain the line `{}`", expected).into());
         }
     }
@@ -243,7 +251,6 @@ fn check_style(lint: &Lint) -> Result<(), Box<dyn Error>> {
 fn replace_produces(
     lint: &mut Lint,
     rustc_path: &Path,
-    rustdoc_path: &Path,
     verbose: bool,
 ) -> Result<(), Box<dyn Error>> {
     let mut lines = lint.doc.iter_mut();
@@ -283,14 +290,8 @@ fn replace_produces(
             match lines.next() {
                 Some(line) if line.is_empty() => {}
                 Some(line) if line == "{{produces}}" => {
-                    let output = generate_lint_output(
-                        &lint.name,
-                        &example,
-                        &options,
-                        rustc_path,
-                        rustdoc_path,
-                        verbose,
-                    )?;
+                    let output =
+                        generate_lint_output(&lint.name, &example, &options, rustc_path, verbose)?;
                     line.replace_range(
                         ..,
                         &format!(
@@ -318,7 +319,6 @@ fn generate_lint_output(
     example: &[&mut String],
     options: &[&str],
     rustc_path: &Path,
-    rustdoc_path: &Path,
     verbose: bool,
 ) -> Result<String, Box<dyn Error>> {
     if verbose {
@@ -327,8 +327,7 @@ fn generate_lint_output(
     let tempdir = tempfile::TempDir::new()?;
     let tempfile = tempdir.path().join("lint_example.rs");
     let mut source = String::new();
-    let is_rustdoc = options.contains(&"rustdoc");
-    let needs_main = !example.iter().any(|line| line.contains("fn main")) && !is_rustdoc;
+    let needs_main = !example.iter().any(|line| line.contains("fn main"));
     // Remove `# ` prefix for hidden lines.
     let unhidden =
         example.iter().map(|line| if line.starts_with("# ") { &line[2..] } else { line });
@@ -354,8 +353,7 @@ fn generate_lint_output(
     }
     fs::write(&tempfile, source)
         .map_err(|e| format!("failed to write {}: {}", tempfile.display(), e))?;
-    let program = if is_rustdoc { rustdoc_path } else { rustc_path };
-    let mut cmd = Command::new(program);
+    let mut cmd = Command::new(rustc_path);
     if options.contains(&"edition2015") {
         cmd.arg("--edition=2015");
     } else {
diff --git a/src/tools/lint-docs/src/main.rs b/src/tools/lint-docs/src/main.rs
index 4b824596b46..45d97bd4317 100644
--- a/src/tools/lint-docs/src/main.rs
+++ b/src/tools/lint-docs/src/main.rs
@@ -13,7 +13,6 @@ fn doit() -> Result<(), Box<dyn Error>> {
     let mut src_path = None;
     let mut out_path = None;
     let mut rustc_path = None;
-    let mut rustdoc_path = None;
     let mut verbose = false;
     while let Some(arg) = args.next() {
         match arg.as_str() {
@@ -35,12 +34,6 @@ fn doit() -> Result<(), Box<dyn Error>> {
                     None => return Err("--rustc requires a value".into()),
                 };
             }
-            "--rustdoc" => {
-                rustdoc_path = match args.next() {
-                    Some(s) => Some(PathBuf::from(s)),
-                    None => return Err("--rustdoc requires a value".into()),
-                };
-            }
             "-v" | "--verbose" => verbose = true,
             s => return Err(format!("unexpected argument `{}`", s).into()),
         }
@@ -54,14 +47,10 @@ fn doit() -> Result<(), Box<dyn Error>> {
     if rustc_path.is_none() {
         return Err("--rustc must be specified to the path of rustc".into());
     }
-    if rustdoc_path.is_none() {
-        return Err("--rustdoc must be specified to the path of rustdoc".into());
-    }
     lint_docs::extract_lint_docs(
         &src_path.unwrap(),
         &out_path.unwrap(),
         &rustc_path.unwrap(),
-        &rustdoc_path.unwrap(),
         verbose,
     )
 }