Skip to content

Commit 2917ee0

Browse files
authored
Merge pull request #275 from kwonoj/fix-normalize-path
2 parents 75c5b18 + 9f14942 commit 2917ee0

File tree

11 files changed

+95
-13
lines changed

11 files changed

+95
-13
lines changed

Cargo.lock

Lines changed: 10 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ resolver = "2"
1212
#lto = true
1313

1414
[workspace.dependencies]
15-
istanbul-oxide = { path = "./packages/istanbul-oxide", version = "0.0.28" }
15+
istanbul-oxide = { path = "./packages/istanbul-oxide", version = "0.0.29" }
1616
swc-coverage-instrument = { path = "./packages/swc-coverage-instrument" }
1717

1818
getrandom = { version = "0.2.15" }
@@ -24,5 +24,6 @@ resolver = "2"
2424
swc_core = { version = "31.1.0" }
2525
tracing = { version = "0.1.37" }
2626
tracing-subscriber = { version = "0.3.17" }
27+
typed-path = { version = "0.11.0" }
2728
wasm-bindgen = { version = "0.2.92" }
2829
wax = { version = "0.6.0" }

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "swc-plugin-coverage-instrument",
3-
"version": "0.0.28",
3+
"version": "0.0.29",
44
"description": "SWC coverage instrumentation plugin",
55
"main": "./target/wasm32-wasip1/release/swc_plugin_coverage.wasm",
66
"napi": {

packages/istanbul-oxide/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ edition = "2021"
55
license = "MIT"
66
name = "istanbul-oxide"
77
repository = "https://github.com/kwonoj/swc-coverage-instrument"
8-
version = "0.0.28"
8+
version = "0.0.29"
99

1010
[dependencies]
1111
indexmap = { workspace = true, features = ["serde"] }

packages/swc-coverage-instrument/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ edition = "2021"
55
license = "MIT"
66
name = "swc-coverage-instrument"
77
repository = "https://github.com/kwonoj/swc-coverage-instrument"
8-
version = "0.0.28"
8+
version = "0.0.29"
99

1010
[dependencies]
1111
istanbul-oxide = { workspace = true }

packages/swc-plugin-coverage/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ edition = "2021"
55
license = "MIT"
66
name = "swc-plugin-coverage"
77
repository = "https://github.com/kwonoj/swc-coverage-instrument"
8-
version = "0.0.28"
8+
version = "0.0.29"
99

1010
[lib]
1111
crate-type = ["cdylib"]
@@ -16,4 +16,5 @@ swc-coverage-instrument = { workspace = true }
1616
swc_core = { workspace = true, features = ["ecma_plugin_transform"] }
1717
tracing = { workspace = true }
1818
tracing-subscriber = { workspace = true, features = ["fmt"] }
19+
typed-path = { workspace = true }
1920
wax = { workspace = true }

packages/swc-plugin-coverage/src/lib.rs

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,23 @@ use swc_coverage_instrument::{
1010
};
1111

1212
use tracing_subscriber::fmt::format::FmtSpan;
13+
use typed_path::Utf8TypedPath;
1314
use wax::Pattern;
1415

16+
/// Normalize a file path to use forward slashes for consistent glob matching
17+
fn normalize_path_for_glob_matching(path: &str) -> String {
18+
let typed_path = Utf8TypedPath::derive(path);
19+
if typed_path.is_windows() {
20+
typed_path.with_unix_encoding().to_string()
21+
} else if path.contains('\\') {
22+
// Fallback: if the path contains backslashes but wasn't detected as Windows,
23+
// still normalize it by replacing backslashes with forward slashes
24+
path.replace('\\', "/")
25+
} else {
26+
path.to_string()
27+
}
28+
}
29+
1530
fn initialize_instrumentation_log(log_options: &InstrumentLogOptions) {
1631
let log_level = match log_options.level.as_deref() {
1732
Some("error") => Some(tracing::Level::ERROR),
@@ -64,7 +79,8 @@ pub fn process(program: Program, metadata: TransformPluginProgramMetadata) -> Pr
6479
if let Some(exclude) = &instrument_options.unstable_exclude {
6580
match wax::any(exclude.iter().map(|s| s.as_ref()).collect::<Vec<&str>>()) {
6681
Ok(p) => {
67-
if p.is_match(filename) {
82+
let normalized_filename = normalize_path_for_glob_matching(filename);
83+
if p.is_match(normalized_filename.as_str()) {
6884
return program;
6985
}
7086
}
@@ -86,3 +102,41 @@ pub fn process(program: Program, metadata: TransformPluginProgramMetadata) -> Pr
86102

87103
program.apply(&mut visit_mut_pass(visitor))
88104
}
105+
106+
#[cfg(test)]
107+
mod tests {
108+
use super::*;
109+
110+
#[test]
111+
fn test_normalize_path_for_glob_matching() {
112+
// Test Windows paths are normalized to Unix-style
113+
let result = normalize_path_for_glob_matching(r"C:\Users\project\test\index.test.ts");
114+
println!("Windows path result: {}", result);
115+
// The typed-path crate converts Windows paths to Unix format, but may strip the drive letter
116+
// The important thing is that backslashes are converted to forward slashes
117+
assert!(result.contains("/Users/project/test/index.test.ts"));
118+
119+
// Test mixed separators are normalized
120+
let result = normalize_path_for_glob_matching(r"C:\Users/project\test/file.js");
121+
println!("Mixed separators result: {}", result);
122+
assert!(result.contains("/Users/project/test/file.js"));
123+
124+
// Test Unix paths remain unchanged
125+
assert_eq!(
126+
normalize_path_for_glob_matching("/home/user/project/src/utils/helper.js"),
127+
"/home/user/project/src/utils/helper.js"
128+
);
129+
130+
// Test relative Unix paths remain unchanged
131+
assert_eq!(
132+
normalize_path_for_glob_matching("src/components/Button.tsx"),
133+
"src/components/Button.tsx"
134+
);
135+
136+
// Test that backslashes are converted to forward slashes
137+
let windows_path = r"project\src\test\file.ts";
138+
let result = normalize_path_for_glob_matching(windows_path);
139+
println!("Relative Windows path result: {}", result);
140+
assert!(result.contains("project/src/test/file.ts"));
141+
}
142+
}

spec/plugin.spec.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,26 @@ ${code}
2929
);
3030
});
3131

32+
it("should normalize paths", () => {
33+
const code = `console.log('hello world');`;
34+
35+
const output = instrumentSync(
36+
code,
37+
"C:\\Users\\project\\test\\index.test.ts",
38+
undefined,
39+
{
40+
unstableExclude: ["**/test/**"],
41+
},
42+
);
43+
44+
assert.equal(
45+
output.code,
46+
`"use strict";
47+
${code}
48+
`,
49+
);
50+
});
51+
3252
it("should preserve emotion styled component labels with template literals", () => {
3353
// This reproduces the issue from GitHub #247
3454
// Input: code AFTER emotion processing (as shown in the GitHub issue)

spec/swc-coverage-custom-transform/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ napi-derive = { version = "2.12.3", default-features = false, features = [
2121
] }
2222
serde = { version = "1.0.203", features = ["derive"] }
2323
serde_json = { version = "1.0.120", features = ["unbounded_depth"] }
24-
swc-coverage-instrument = { version = "0.0.28", path = "../../packages/swc-coverage-instrument" }
24+
swc-coverage-instrument = { version = "0.0.29", path = "../../packages/swc-coverage-instrument" }
2525
swc_core = { version = "31.1.0", features = [
2626
"common_concurrent",
2727
"ecma_transforms",

0 commit comments

Comments
 (0)