about summary refs log tree commit diff
path: root/src/tools/lint-docs
diff options
context:
space:
mode:
authorEric Huss <eric@huss.org>2020-11-28 13:29:51 -0800
committerEric Huss <eric@huss.org>2020-11-28 13:39:02 -0800
commitd2d91b42a577e033387918addac937b3f9062f5e (patch)
tree8d3c54828022241c284f458b1969e5e0206c7437 /src/tools/lint-docs
parentf17e6487b2315d3cc3826fb8badeb7d4959b3ffd (diff)
downloadrust-d2d91b42a577e033387918addac937b3f9062f5e.tar.gz
rust-d2d91b42a577e033387918addac937b3f9062f5e.zip
lint-docs: Add --validate flag to validate lint docs separately.
Diffstat (limited to 'src/tools/lint-docs')
-rw-r--r--src/tools/lint-docs/src/groups.rs27
-rw-r--r--src/tools/lint-docs/src/lib.rs43
-rw-r--r--src/tools/lint-docs/src/main.rs5
3 files changed, 57 insertions, 18 deletions
diff --git a/src/tools/lint-docs/src/groups.rs b/src/tools/lint-docs/src/groups.rs
index db667264d2f..0a69b18a332 100644
--- a/src/tools/lint-docs/src/groups.rs
+++ b/src/tools/lint-docs/src/groups.rs
@@ -5,6 +5,7 @@ use std::fmt::Write;
 use std::fs;
 use std::process::Command;
 
+/// Descriptions of rustc lint groups.
 static GROUP_DESCRIPTIONS: &[(&str, &str)] = &[
     ("unused", "Lints that detect things being declared but not used, or excess syntax"),
     ("rustdoc", "Rustdoc-specific lints"),
@@ -86,17 +87,27 @@ impl<'a> LintExtractor<'a> {
         result.push_str("|-------|-------------|-------|\n");
         result.push_str("| warnings | All lints that are set to issue warnings | See [warn-by-default] for the default set of warnings |\n");
         for (group_name, group_lints) in groups {
-            let description = GROUP_DESCRIPTIONS
-                .iter()
-                .find(|(n, _)| n == group_name)
-                .ok_or_else(|| {
-                    format!(
+            let description = match GROUP_DESCRIPTIONS.iter().find(|(n, _)| n == group_name) {
+                Some((_, desc)) => desc,
+                None if self.validate => {
+                    return Err(format!(
                         "lint group `{}` does not have a description, \
-                         please update the GROUP_DESCRIPTIONS list",
+                         please update the GROUP_DESCRIPTIONS list in \
+                         src/tools/lint-docs/src/groups.rs",
                         group_name
                     )
-                })?
-                .1;
+                    .into());
+                }
+                None => {
+                    eprintln!(
+                        "warning: lint group `{}` is missing from the GROUP_DESCRIPTIONS list\n\
+                         If this is a new lint group, please update the GROUP_DESCRIPTIONS in \
+                         src/tools/lint-docs/src/groups.rs",
+                        group_name
+                    );
+                    continue;
+                }
+            };
             to_link.extend(group_lints);
             let brackets: Vec<_> = group_lints.iter().map(|l| format!("[{}]", l)).collect();
             write!(result, "| {} | {} | {} |\n", group_name, description, brackets.join(", "))
diff --git a/src/tools/lint-docs/src/lib.rs b/src/tools/lint-docs/src/lib.rs
index aafd33301ea..dc878b718ad 100644
--- a/src/tools/lint-docs/src/lib.rs
+++ b/src/tools/lint-docs/src/lib.rs
@@ -19,6 +19,8 @@ pub struct LintExtractor<'a> {
     pub rustc_target: &'a str,
     /// Verbose output.
     pub verbose: bool,
+    /// Validate the style and the code example.
+    pub validate: bool,
 }
 
 struct Lint {
@@ -122,7 +124,7 @@ impl<'a> LintExtractor<'a> {
         let contents = fs::read_to_string(path)
             .map_err(|e| format!("could not read {}: {}", path.display(), e))?;
         let mut lines = contents.lines().enumerate();
-        loop {
+        'outer: loop {
             // Find a lint declaration.
             let lint_start = loop {
                 match lines.next() {
@@ -158,12 +160,22 @@ impl<'a> LintExtractor<'a> {
                                 )
                             })?;
                             if doc_lines.is_empty() {
-                                return Err(format!(
-                                    "did not find doc lines for lint `{}` in {}",
-                                    name,
-                                    path.display()
-                                )
-                                .into());
+                                if self.validate {
+                                    return Err(format!(
+                                        "did not find doc lines for lint `{}` in {}",
+                                        name,
+                                        path.display()
+                                    )
+                                    .into());
+                                } else {
+                                    eprintln!(
+                                        "warning: lint `{}` in {} does not define any doc lines, \
+                                         these are required for the lint documentation",
+                                        name,
+                                        path.display()
+                                    );
+                                    continue 'outer;
+                                }
                             }
                             break (doc_lines, name);
                         }
@@ -234,13 +246,26 @@ impl<'a> LintExtractor<'a> {
             // Rustdoc lints are documented in the rustdoc book, don't check these.
             return Ok(());
         }
-        lint.check_style()?;
+        if self.validate {
+            lint.check_style()?;
+        }
         // Unfortunately some lints have extra requirements that this simple test
         // setup can't handle (like extern crates). An alternative is to use a
         // separate test suite, and use an include mechanism such as mdbook's
         // `{{#rustdoc_include}}`.
         if !lint.is_ignored() {
-            self.replace_produces(lint)?;
+            if let Err(e) = self.replace_produces(lint) {
+                if self.validate {
+                    return Err(e);
+                }
+                eprintln!(
+                    "warning: the code example in lint `{}` in {} failed to \
+                     generate the expected output: {}",
+                    lint.name,
+                    lint.path.display(),
+                    e
+                );
+            }
         }
         Ok(())
     }
diff --git a/src/tools/lint-docs/src/main.rs b/src/tools/lint-docs/src/main.rs
index 9b75ab45fca..922e70402f2 100644
--- a/src/tools/lint-docs/src/main.rs
+++ b/src/tools/lint-docs/src/main.rs
@@ -3,7 +3,7 @@ use std::path::PathBuf;
 
 fn main() {
     if let Err(e) = doit() {
-        println!("error: {}", e);
+        eprintln!("error: {}", e);
         std::process::exit(1);
     }
 }
@@ -15,6 +15,7 @@ fn doit() -> Result<(), Box<dyn Error>> {
     let mut rustc_path = None;
     let mut rustc_target = None;
     let mut verbose = false;
+    let mut validate = false;
     while let Some(arg) = args.next() {
         match arg.as_str() {
             "--src" => {
@@ -42,6 +43,7 @@ fn doit() -> Result<(), Box<dyn Error>> {
                 };
             }
             "-v" | "--verbose" => verbose = true,
+            "--validate" => validate = true,
             s => return Err(format!("unexpected argument `{}`", s).into()),
         }
     }
@@ -63,6 +65,7 @@ fn doit() -> Result<(), Box<dyn Error>> {
         rustc_path: &rustc_path.unwrap(),
         rustc_target: &rustc_target.unwrap(),
         verbose,
+        validate,
     };
     le.extract_lint_docs()
 }