diff --git a/src/search_unused.rs b/src/search_unused.rs index 1e642df..1f3dc37 100644 --- a/src/search_unused.rs +++ b/src/search_unused.rs @@ -77,12 +77,15 @@ fn make_line_regexp(name: &str) -> String { // Syntax documentation: https://docs.rs/regex/latest/regex/#syntax // // Breaking down this regular expression: given a line, - // - `use (::)?{name}(::|;| as)`: matches `use foo;`, `use foo::bar`, `use foo as bar;`, with + // - `use (::)?(?i){name}(?-i)(::|;| as)`: matches `use foo;`, `use foo::bar`, `use foo as bar;`, with // an optional "::" in front of the crate's name. - // - `\b({name})::`: matches `foo::X`, but not `barfoo::X`. `\b` means word boundary, so + // - `\b(?i){name}(?-i)::`: matches `foo::X`, but not `barfoo::X`. `\b` means word boundary, so // putting it before the crate's name ensures there's no polluting prefix. - // - `extern crate {name}( |;)`: matches `extern crate foo`, or `extern crate foo as bar`. - format!(r#"use (::)?{name}(::|;| as)|\b{name}::|extern crate {name}( |;)"#) + // - `extern crate (?i){name}(?-i)( |;)`: matches `extern crate foo`, or `extern crate foo as bar`. + // - `(?i){name}(?-i)` makes the match against the crate's name case insensitive + format!( + r#"use (::)?(?i){name}(?-i)(::|;| as)|\b(?i){name}(?-i)::|extern crate (?i){name}(?-i)( |;)"# + ) } fn make_multiline_regexp(name: &str) -> String { @@ -91,7 +94,8 @@ fn make_multiline_regexp(name: &str) -> String { // Breaking down this Terrible regular expression: tries to match compound `use as` statements, // as in `use { X as Y };`, with possibly multiple-lines in between. Will match the first `};` // that it finds, which *should* be the end of the use statement, but oh well. - format!(r#"use \{{\s[^;]*{name}\s*as\s*[^;]*\}};"#) + // `(?i){name}(?-i)` makes the match against the crate's name case insensitive. + format!(r#"use \{{\s[^;]*(?i){name}(?-i)\s*as\s*[^;]*\}};"#) } /// Returns all the paths to the Rust source files for a crate contained at the given path. @@ -491,6 +495,26 @@ fn test_regexp() -> anyhow::Result<()> { assert!(test_one("log", "extern crate log as logging")?); assert!(test_one("log", r#"log::info!("fyi")"#)?); + assert!(test_one("Log", "use log;")?); + assert!(test_one("Log", "use ::log;")?); + assert!(test_one("Log", "use log::{self};")?); + assert!(test_one("Log", "use log::*;")?); + assert!(test_one("Log", "use log::info;")?); + assert!(test_one("Log", "use log as logging;")?); + assert!(test_one("Log", "extern crate log;")?); + assert!(test_one("Log", "extern crate log as logging")?); + assert!(test_one("Log", r#"log::info!("fyi")"#)?); + + assert!(test_one("log", "use Log;")?); + assert!(test_one("log", "use ::Log;")?); + assert!(test_one("log", "use Log::{self};")?); + assert!(test_one("log", "use Log::*;")?); + assert!(test_one("log", "use Log::info;")?); + assert!(test_one("log", "use Log as logging;")?); + assert!(test_one("log", "extern crate Log;")?); + assert!(test_one("log", "extern crate Log as logging")?); + assert!(test_one("log", r#"Log::info!("fyi")"#)?); + assert!(test_one( "bitflags", r#" @@ -499,6 +523,22 @@ bitflags::macro! { "# )?); + assert!(test_one( + "Bitflags", + r#" +use std::fmt; +bitflags::macro! { +"# + )?); + + assert!(test_one( + "bitflags", + r#" +use std::fmt; +Bitflags::macro! { +"# + )?); + // Compound `use as` statements. Here come the nightmares... assert!(test_one("log", "use { log as logging };")?); assert!(!test_one("lol", "use { log as logging };")?);