Skip to content

Commit

Permalink
feat: make match against crate name case insensitive (#69)
Browse files Browse the repository at this point in the history
* feat: make match against crate name case insensitive
* add tests for case insensitive match
  • Loading branch information
LorenzSchueler authored Apr 6, 2023
1 parent 105525a commit 46c999d
Showing 1 changed file with 45 additions and 5 deletions.
50 changes: 45 additions & 5 deletions src/search_unused.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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.
Expand Down Expand Up @@ -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#"
Expand All @@ -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 };")?);
Expand Down

0 comments on commit 46c999d

Please sign in to comment.