Skip to content

Add a matcher for windows path backslashes #102

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,14 @@ jobs:
- os: windows-latest
host_target: i686-pc-windows-msvc
runs-on: ${{ matrix.os }}
# Run tests under a directory with a space in it to double check the windows path heuristic
defaults:
run:
working-directory: "dir with spaces/ui test"
steps:
- uses: actions/checkout@v3
with:
path: "dir with spaces/ui test"
- uses: dtolnay/rust-toolchain@stable
- name: Build
run: cargo build --verbose
Expand Down
3 changes: 1 addition & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,7 @@ distance = "0.4.0"
[dependencies.regex]
version = "1.5.5"
default-features = false
# Features chosen to match those required by env_logger, to avoid rebuilds
features = ["perf", "std"]
features = ["perf", "std", "unicode-gencat"]

[dependencies.color-eyre]
version = "0.6.1"
Expand Down
9 changes: 5 additions & 4 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,12 @@ pub struct Config {
/// `None` to run on the host, otherwise a target triple
pub target: Option<String>,
/// Filters applied to stderr output before processing it.
/// By default contains a filter for replacing backslashes with regular slashes.
/// On windows, contains a filter to replace `\n` with `\r\n`.
/// By default contains a filter for replacing backslashes in paths with
/// regular slashes.
/// On windows, contains a filter to remove `\r`.
pub stderr_filters: Filter,
/// Filters applied to stdout output before processing it.
/// On windows, contains a filter to replace `\n` with `\r\n`.
/// On windows, contains a filter to remove `\r`.
pub stdout_filters: Filter,
/// The folder in which to start searching for .rs files
pub root_dir: PathBuf,
Expand Down Expand Up @@ -58,7 +59,7 @@ impl Config {
host: None,
target: None,
stderr_filters: vec![
(Match::Exact(vec![b'\\']), b"/"),
(Match::PathBackslash, b"/"),
#[cfg(windows)]
(Match::Exact(vec![b'\r']), b""),
],
Expand Down
28 changes: 25 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@ use bstr::ByteSlice;
pub use color_eyre;
use color_eyre::eyre::{eyre, Result};
use crossbeam_channel::{unbounded, Receiver, Sender};
use lazy_static::lazy_static;
use parser::{ErrorMatch, Revisioned};
use regex::bytes::Regex;
use regex::bytes::{Captures, Regex};
use rustc_stderr::{Diagnostics, Level, Message};
use status_emitter::StatusEmitter;
use std::borrow::Cow;
Expand Down Expand Up @@ -49,12 +50,33 @@ pub enum Match {
Regex(Regex),
/// If the exact byte sequence is found, the filter applies
Exact(Vec<u8>),
/// Uses a heuristic to find backslashes in windows style paths
PathBackslash,
}
impl Match {
fn replace_all<'a>(&self, text: &'a [u8], replacement: &[u8]) -> Cow<'a, [u8]> {
match self {
Match::Regex(regex) => regex.replace_all(text, replacement),
Match::Exact(needle) => text.replace(needle, replacement).into(),
Match::PathBackslash => {
lazy_static! {
static ref PATH_RE: Regex = Regex::new(
r#"(?x)
(?:
# Match paths to files with extensions that don't include spaces
\\(?:[\pL\pN.\-_']+[/\\])*[\pL\pN.\-_']+\.\pL+
|
# Allow spaces in absolute paths
[A-Z]:\\(?:[\pL\pN.\-_'\ ]+[/\\])+
)"#,
)
.unwrap();
}

PATH_RE.replace_all(text, |caps: &Captures<'_>| {
caps[0].replace(r"\", replacement)
})
}
}
}
}
Expand Down Expand Up @@ -1051,8 +1073,8 @@ fn normalize(
text = text.replace(lib_path, "RUSTLIB");
}

for (regex, replacement) in filters {
text = regex.replace_all(&text, replacement).into_owned();
for (rule, replacement) in filters {
text = rule.replace_all(&text, replacement).into_owned();
}

for (from, to) in comments
Expand Down
3 changes: 2 additions & 1 deletion tests/integrations/basic/Cargo.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ tests/actual_tests/executable.rs ... ok
tests/actual_tests/foomp-rustfix.rs ... ok
tests/actual_tests/foomp.rs ... ok
tests/actual_tests/unicode.rs ... ok
tests/actual_tests/windows_paths.rs ... ok
tests/actual_tests/subdir/aux_proc_macro.rs ... ok

test result: ok. 7 tests passed, 0 ignored, 0 filtered out
test result: ok. 8 tests passed, 0 ignored, 0 filtered out

25 changes: 25 additions & 0 deletions tests/integrations/basic/tests/actual_tests/windows_paths.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
fn main() {
let () = "escapes stay as backslashes: \t\r\n";
//~^ ERROR: mismatched types

let () = r"absolute: C:\foo\file.rs";
//~^ ERROR: mismatched types
let () = r"absolute, spaces: C:\foo bar\file.rs";
//~^ ERROR: mismatched types
let () = r"absolute, spaces, dir: C:\foo bar\some dir\";
//~^ ERROR: mismatched types
let () = r"absolute, spaces, no extension: C:\foo bar\some file";
//~^ ERROR: mismatched types

let () = r"relative: foo\file.rs";
//~^ ERROR: mismatched types

let () = r"unicode: Ryū\file.rs";
//~^ ERROR: mismatched types

let () = r"mixed seperators: C:\foo/../bar\";
//~^ ERROR: mismatched types

let () = r"unsupported: foo\bar";
//~^ ERROR: mismatched types
}
75 changes: 75 additions & 0 deletions tests/integrations/basic/tests/actual_tests/windows_paths.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
error[E0308]: mismatched types
--> $DIR/windows_paths.rs:2:9
|
2 | let () = "escapes stay as backslashes: \t\r\n";
| ^^ ------------------------------------- this expression has type `&str`
| |
| expected `str`, found `()`

error[E0308]: mismatched types
--> $DIR/windows_paths.rs:5:9
|
5 | let () = r"absolute: C:/foo/file.rs";
| ^^ --------------------------- this expression has type `&str`
| |
| expected `str`, found `()`

error[E0308]: mismatched types
--> $DIR/windows_paths.rs:7:9
|
7 | let () = r"absolute, spaces: C:/foo bar/file.rs";
| ^^ --------------------------------------- this expression has type `&str`
| |
| expected `str`, found `()`

error[E0308]: mismatched types
--> $DIR/windows_paths.rs:9:9
|
9 | let () = r"absolute, spaces, dir: C:/foo bar/some dir/";
| ^^ ---------------------------------------------- this expression has type `&str`
| |
| expected `str`, found `()`

error[E0308]: mismatched types
--> $DIR/windows_paths.rs:11:9
|
11 | let () = r"absolute, spaces, no extension: C:/foo bar/some file";
| ^^ ------------------------------------------------------- this expression has type `&str`
| |
| expected `str`, found `()`

error[E0308]: mismatched types
--> $DIR/windows_paths.rs:14:9
|
14 | let () = r"relative: foo/file.rs";
| ^^ ------------------------ this expression has type `&str`
| |
| expected `str`, found `()`

error[E0308]: mismatched types
--> $DIR/windows_paths.rs:17:9
|
17 | let () = r"unicode: Ryū/file.rs";
| ^^ ----------------------- this expression has type `&str`
| |
| expected `str`, found `()`

error[E0308]: mismatched types
--> $DIR/windows_paths.rs:20:9
|
20 | let () = r"mixed seperators: C:/foo/../bar/";
| ^^ ----------------------------------- this expression has type `&str`
| |
| expected `str`, found `()`

error[E0308]: mismatched types
--> $DIR/windows_paths.rs:23:9
|
23 | let () = r"unsupported: foo\bar";
| ^^ ----------------------- this expression has type `&str`
| |
| expected `str`, found `()`

error: aborting due to 9 previous errors

For more information about this error, try `rustc --explain E0308`.