about summary refs log tree commit diff
path: root/clippy_dev
diff options
context:
space:
mode:
authorflip1995 <hello@philkrones.com>2020-10-09 12:45:29 +0200
committerflip1995 <hello@philkrones.com>2020-10-09 12:45:29 +0200
commitfbf2430f0279adb8132efe60b16f8dd7b6a2acb3 (patch)
tree3e66912301876dca6c85f7a0dc9feb03d6cd1fbe /clippy_dev
parentadb7fc6283711c881186ca85bb9ac3bb8add099b (diff)
downloadrust-fbf2430f0279adb8132efe60b16f8dd7b6a2acb3.tar.gz
rust-fbf2430f0279adb8132efe60b16f8dd7b6a2acb3.zip
Merge commit '2f6439ae6a6803d030cceb3ee14c9150e91b328b' into clippyup
Diffstat (limited to 'clippy_dev')
-rw-r--r--clippy_dev/Cargo.toml2
-rw-r--r--clippy_dev/src/lib.rs43
-rw-r--r--clippy_dev/src/main.rs20
-rw-r--r--clippy_dev/src/serve.rs64
4 files changed, 108 insertions, 21 deletions
diff --git a/clippy_dev/Cargo.toml b/clippy_dev/Cargo.toml
index c861efc8afb..b8a4a20114b 100644
--- a/clippy_dev/Cargo.toml
+++ b/clippy_dev/Cargo.toml
@@ -8,8 +8,8 @@ edition = "2018"
 bytecount = "0.6"
 clap = "2.33"
 itertools = "0.9"
+opener = "0.4"
 regex = "1"
-lazy_static = "1.0"
 shell-escape = "0.1"
 walkdir = "2"
 
diff --git a/clippy_dev/src/lib.rs b/clippy_dev/src/lib.rs
index 5baa31d5cde..43cb2954b74 100644
--- a/clippy_dev/src/lib.rs
+++ b/clippy_dev/src/lib.rs
@@ -1,42 +1,47 @@
 #![cfg_attr(feature = "deny-warnings", deny(warnings))]
+#![feature(once_cell)]
 
 use itertools::Itertools;
-use lazy_static::lazy_static;
 use regex::Regex;
 use std::collections::HashMap;
 use std::ffi::OsStr;
 use std::fs;
+use std::lazy::SyncLazy;
 use std::path::{Path, PathBuf};
 use walkdir::WalkDir;
 
 pub mod fmt;
 pub mod new_lint;
 pub mod ra_setup;
+pub mod serve;
 pub mod stderr_length_check;
 pub mod update_lints;
 
-lazy_static! {
-    static ref DEC_CLIPPY_LINT_RE: Regex = Regex::new(
+static DEC_CLIPPY_LINT_RE: SyncLazy<Regex> = SyncLazy::new(|| {
+    Regex::new(
         r#"(?x)
-        declare_clippy_lint!\s*[\{(]
-        (?:\s+///.*)*
-        \s+pub\s+(?P<name>[A-Z_][A-Z_0-9]*)\s*,\s*
-        (?P<cat>[a-z_]+)\s*,\s*
-        "(?P<desc>(?:[^"\\]+|\\(?s).(?-s))*)"\s*[})]
-    "#
+    declare_clippy_lint!\s*[\{(]
+    (?:\s+///.*)*
+    \s+pub\s+(?P<name>[A-Z_][A-Z_0-9]*)\s*,\s*
+    (?P<cat>[a-z_]+)\s*,\s*
+    "(?P<desc>(?:[^"\\]+|\\(?s).(?-s))*)"\s*[})]
+"#,
     )
-    .unwrap();
-    static ref DEC_DEPRECATED_LINT_RE: Regex = Regex::new(
+    .unwrap()
+});
+
+static DEC_DEPRECATED_LINT_RE: SyncLazy<Regex> = SyncLazy::new(|| {
+    Regex::new(
         r#"(?x)
-        declare_deprecated_lint!\s*[{(]\s*
-        (?:\s+///.*)*
-        \s+pub\s+(?P<name>[A-Z_][A-Z_0-9]*)\s*,\s*
-        "(?P<desc>(?:[^"\\]+|\\(?s).(?-s))*)"\s*[})]
-    "#
+    declare_deprecated_lint!\s*[{(]\s*
+    (?:\s+///.*)*
+    \s+pub\s+(?P<name>[A-Z_][A-Z_0-9]*)\s*,\s*
+    "(?P<desc>(?:[^"\\]+|\\(?s).(?-s))*)"\s*[})]
+"#,
     )
-    .unwrap();
-    static ref NL_ESCAPE_RE: Regex = Regex::new(r#"\\\n\s*"#).unwrap();
-}
+    .unwrap()
+});
+static NL_ESCAPE_RE: SyncLazy<Regex> = SyncLazy::new(|| Regex::new(r#"\\\n\s*"#).unwrap());
 
 pub static DOCS_LINK: &str = "https://rust-lang.github.io/rust-clippy/master/index.html";
 
diff --git a/clippy_dev/src/main.rs b/clippy_dev/src/main.rs
index 281037ae37c..7a8cbd5251d 100644
--- a/clippy_dev/src/main.rs
+++ b/clippy_dev/src/main.rs
@@ -1,7 +1,7 @@
 #![cfg_attr(feature = "deny-warnings", deny(warnings))]
 
 use clap::{App, Arg, SubCommand};
-use clippy_dev::{fmt, new_lint, ra_setup, stderr_length_check, update_lints};
+use clippy_dev::{fmt, new_lint, ra_setup, serve, stderr_length_check, update_lints};
 
 fn main() {
     let matches = App::new("Clippy developer tooling")
@@ -100,6 +100,19 @@ fn main() {
                         .required(true),
                 ),
         )
+        .subcommand(
+            SubCommand::with_name("serve")
+                .about("Launch a local 'ALL the Clippy Lints' website in a browser")
+                .arg(
+                    Arg::with_name("port")
+                        .long("port")
+                        .short("p")
+                        .help("Local port for the http server")
+                        .default_value("8000")
+                        .validator_os(serve::validate_port),
+                )
+                .arg(Arg::with_name("lint").help("Which lint's page to load initially (optional)")),
+        )
         .get_matches();
 
     match matches.subcommand() {
@@ -129,6 +142,11 @@ fn main() {
             stderr_length_check::check();
         },
         ("ra-setup", Some(matches)) => ra_setup::run(matches.value_of("rustc-repo-path")),
+        ("serve", Some(matches)) => {
+            let port = matches.value_of("port").unwrap().parse().unwrap();
+            let lint = matches.value_of("lint");
+            serve::run(port, lint);
+        },
         _ => {},
     }
 }
diff --git a/clippy_dev/src/serve.rs b/clippy_dev/src/serve.rs
new file mode 100644
index 00000000000..a46c0e4d3f0
--- /dev/null
+++ b/clippy_dev/src/serve.rs
@@ -0,0 +1,64 @@
+use std::ffi::{OsStr, OsString};
+use std::path::Path;
+use std::process::Command;
+use std::thread;
+use std::time::{Duration, SystemTime};
+
+pub fn run(port: u16, lint: Option<&str>) -> ! {
+    let mut url = Some(match lint {
+        None => format!("http://localhost:{}", port),
+        Some(lint) => format!("http://localhost:{}/#{}", port, lint),
+    });
+
+    loop {
+        if mtime("util/gh-pages/lints.json") < mtime("clippy_lints/src") {
+            Command::new("python3")
+                .arg("util/export.py")
+                .spawn()
+                .unwrap()
+                .wait()
+                .unwrap();
+        }
+        if let Some(url) = url.take() {
+            thread::spawn(move || {
+                Command::new("python3")
+                    .arg("-m")
+                    .arg("http.server")
+                    .arg(port.to_string())
+                    .current_dir("util/gh-pages")
+                    .spawn()
+                    .unwrap();
+                // Give some time for python to start
+                thread::sleep(Duration::from_millis(500));
+                // Launch browser after first export.py has completed and http.server is up
+                let _ = opener::open(url);
+            });
+        }
+        thread::sleep(Duration::from_millis(1000));
+    }
+}
+
+fn mtime(path: impl AsRef<Path>) -> SystemTime {
+    let path = path.as_ref();
+    if path.is_dir() {
+        path.read_dir()
+            .into_iter()
+            .flatten()
+            .flatten()
+            .map(|entry| mtime(&entry.path()))
+            .max()
+            .unwrap_or(SystemTime::UNIX_EPOCH)
+    } else {
+        path.metadata()
+            .and_then(|metadata| metadata.modified())
+            .unwrap_or(SystemTime::UNIX_EPOCH)
+    }
+}
+
+#[allow(clippy::missing_errors_doc)]
+pub fn validate_port(arg: &OsStr) -> Result<(), OsString> {
+    match arg.to_string_lossy().parse::<u16>() {
+        Ok(_port) => Ok(()),
+        Err(err) => Err(OsString::from(err.to_string())),
+    }
+}