|
1 | 1 | mod test_utils; |
2 | 2 |
|
3 | | -use std::{env::vars_os, process::Stdio}; |
| 3 | +use std::{env::vars_os, ffi::OsString}; |
4 | 4 |
|
5 | 5 | use fspy::{AccessMode, PathAccessIterable}; |
6 | 6 | use test_log::test; |
7 | 7 |
|
8 | | -/// Find the oxlint executable in test_bins |
9 | | -fn find_oxlint() -> std::path::PathBuf { |
10 | | - let test_bins_dir = std::path::Path::new(env!("CARGO_MANIFEST_DIR")) |
| 8 | +/// Get the test_bins/.bin directory path |
| 9 | +fn test_bins_bin_dir() -> std::path::PathBuf { |
| 10 | + std::path::Path::new(env!("CARGO_MANIFEST_DIR")) |
11 | 11 | .parent() |
12 | 12 | .unwrap() |
13 | 13 | .join("vite_task_bin") |
14 | 14 | .join("test_bins") |
15 | 15 | .join("node_modules") |
16 | | - .join(".bin"); |
| 16 | + .join(".bin") |
| 17 | +} |
17 | 18 |
|
| 19 | +/// Find the oxlint executable in test_bins |
| 20 | +fn find_oxlint() -> std::path::PathBuf { |
| 21 | + let test_bins_dir = test_bins_bin_dir(); |
18 | 22 | which::which_in("oxlint", Some(&test_bins_dir), std::env::current_dir().unwrap()) |
19 | 23 | .expect("oxlint not found in test_bins/node_modules/.bin") |
20 | 24 | } |
21 | 25 |
|
22 | 26 | async fn track_oxlint(dir: &std::path::Path, args: &[&str]) -> anyhow::Result<PathAccessIterable> { |
23 | 27 | let oxlint_path = find_oxlint(); |
24 | 28 | let mut command = fspy::Command::new(&oxlint_path); |
25 | | - command.args(args).stdout(Stdio::null()).stderr(Stdio::null()).envs(vars_os()).current_dir(dir); |
| 29 | + |
| 30 | + // Build PATH with test_bins/.bin prepended so oxlint can find tsgolint |
| 31 | + let test_bins_dir = test_bins_bin_dir(); |
| 32 | + let new_path = if let Some(existing_path) = std::env::var_os("PATH") { |
| 33 | + let mut paths = vec![test_bins_dir.as_os_str().to_owned()]; |
| 34 | + paths.extend(std::env::split_paths(&existing_path).map(|p| p.into_os_string())); |
| 35 | + std::env::join_paths(paths)? |
| 36 | + } else { |
| 37 | + OsString::from(&test_bins_dir) |
| 38 | + }; |
| 39 | + |
| 40 | + command |
| 41 | + .args(args) |
| 42 | + .envs(vars_os().filter(|(k, _)| !k.eq_ignore_ascii_case("PATH"))) |
| 43 | + .env("PATH", new_path) |
| 44 | + .current_dir(dir); |
26 | 45 |
|
27 | 46 | let child = command.spawn().await?; |
28 | 47 | let termination = child.wait_handle.await?; |
@@ -64,3 +83,40 @@ async fn oxlint_reads_directory() -> anyhow::Result<()> { |
64 | 83 | test_utils::assert_contains(&accesses, &tmpdir_path, AccessMode::READ_DIR); |
65 | 84 | Ok(()) |
66 | 85 | } |
| 86 | + |
| 87 | +/// Test oxlint with TypeScript type-aware linting (--tsconfig) |
| 88 | +/// This reproduces a crash in fspy_preload_windows on Windows: |
| 89 | +/// "unsafe precondition(s) violated: slice::from_raw_parts requires the pointer to be aligned and non-null" |
| 90 | +#[test(tokio::test)] |
| 91 | +async fn oxlint_type_aware() -> anyhow::Result<()> { |
| 92 | + let tmpdir = tempfile::tempdir()?; |
| 93 | + // on macOS, tmpdir.path() may be a symlink, so we need to canonicalize it |
| 94 | + let tmpdir_path = std::fs::canonicalize(tmpdir.path())?; |
| 95 | + |
| 96 | + // Create a simple TypeScript file |
| 97 | + let ts_file = tmpdir_path.join("index.ts"); |
| 98 | + std::fs::write( |
| 99 | + &ts_file, |
| 100 | + r#" |
| 101 | +import type { Foo } from './types'; |
| 102 | +declare const _foo: Foo; |
| 103 | +"#, |
| 104 | + )?; |
| 105 | + |
| 106 | + // Run oxlint without --type-aware first |
| 107 | + let accesses = track_oxlint(&tmpdir_path, &[""]).await?; |
| 108 | + let access_to_types_ts = accesses.iter().find(|access| { |
| 109 | + let os_str = access.path.to_cow_os_str(); |
| 110 | + os_str.as_encoded_bytes().ends_with(b"\\types.ts") |
| 111 | + || os_str.as_encoded_bytes().ends_with(b"/types.ts") |
| 112 | + }); |
| 113 | + assert_eq!(access_to_types_ts, None, "oxlint should not read types.ts without --type-aware"); |
| 114 | + |
| 115 | + // Run oxlint with --type-aware to enable type-aware linting |
| 116 | + let accesses = track_oxlint(&tmpdir_path, &["--type-aware"]).await?; |
| 117 | + |
| 118 | + // Check that oxlint read types.ts |
| 119 | + test_utils::assert_contains(&accesses, &tmpdir_path.join("types.ts"), AccessMode::READ); |
| 120 | + |
| 121 | + Ok(()) |
| 122 | +} |
0 commit comments