Skip to content

Commit 7c47eaa

Browse files
committed
update
1 parent 2cda1fc commit 7c47eaa

File tree

1 file changed

+89
-16
lines changed

1 file changed

+89
-16
lines changed

crates/oxc_diagnostics/src/service.rs

Lines changed: 89 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -139,19 +139,20 @@ impl DiagnosticService {
139139
source_start: u32,
140140
diagnostics: Vec<OxcDiagnostic>,
141141
) -> Vec<Error> {
142-
#[cfg(test)]
143-
let is_jetbrains = false;
144-
#[cfg(not(test))]
145-
let is_jetbrains =
146-
std::env::var("TERMINAL_EMULATOR").is_ok_and(|x| x.eq("JetBrains-JediTerm"));
142+
let is_jetbrains = if cfg!(test) {
143+
false
144+
} else {
145+
std::env::var("TERMINAL_EMULATOR").is_ok_and(|x| x.eq("JetBrains-JediTerm"))
146+
};
147147

148148
let path_ref = path.as_ref();
149-
let path_display = if is_jetbrains { from_file_path(path_ref) } else { None };
150-
let path_display = path_display.unwrap_or_else(|| {
151-
let relative_path = path_ref.strip_prefix(cwd).unwrap_or(path_ref).to_string_lossy();
152-
let normalized_path = relative_path.cow_replace('\\', "/");
153-
normalized_path.to_string()
154-
});
149+
let path_display = if is_jetbrains { from_file_path(path_ref) } else { None }
150+
.unwrap_or_else(|| {
151+
let relative_path =
152+
path_ref.strip_prefix(cwd).unwrap_or(path_ref).to_string_lossy();
153+
let normalized_path = relative_path.cow_replace('\\', "/");
154+
normalized_path.to_string()
155+
});
155156

156157
let source = Arc::new(NamedSource::new(path_display, source_text.to_owned()));
157158
diagnostics
@@ -302,14 +303,17 @@ fn from_file_path<A: AsRef<Path>>(path: A) -> Option<String> {
302303
};
303304

304305
if cfg!(windows) {
305-
// we want to parse a triple-slash path for Windows paths
306+
// we want to write a triple-slash path for Windows paths
306307
// it's a shorthand for `file://localhost/C:/Windows` with the `localhost` omitted.
307-
// We encode the driver Letter `C:` as well. LSP Specification allows it.
308-
// https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#uri
308+
let mut components = fragment.components();
309+
let drive = components.next();
310+
309311
Some(format!(
310-
"file:///{}",
312+
"file:///{:?}:/{}",
313+
drive.unwrap().as_os_str().to_string_lossy(),
311314
percent_encoding::utf8_percent_encode(
312-
&fragment.to_string_lossy().cow_replace('\\', "/"),
315+
// Skip the drive character.
316+
&components.collect::<PathBuf>().to_string_lossy().cow_replace('\\', "/"),
313317
&ASCII_SET
314318
)
315319
))
@@ -350,3 +354,72 @@ fn strict_canonicalize<P: AsRef<Path>>(path: P) -> std::io::Result<PathBuf> {
350354
let canon = std::fs::canonicalize(path)?;
351355
impl_(canon)
352356
}
357+
358+
#[cfg(test)]
359+
mod tests {
360+
use crate::service::from_file_path;
361+
use std::path::PathBuf;
362+
363+
fn with_schema(path: &str) -> String {
364+
const EXPECTED_SCHEMA: &str = if cfg!(windows) { "file:///" } else { "file://" };
365+
format!("{EXPECTED_SCHEMA}{path}")
366+
}
367+
368+
#[test]
369+
#[cfg(windows)]
370+
fn test_idempotent_canonicalization() {
371+
let lhs = strict_canonicalize(Path::new(".")).unwrap();
372+
let rhs = strict_canonicalize(&lhs).unwrap();
373+
assert_eq!(lhs, rhs);
374+
}
375+
376+
#[test]
377+
#[cfg(unix)]
378+
fn test_path_to_uri() {
379+
let paths = [
380+
PathBuf::from("/some/path/to/file.txt"),
381+
PathBuf::from("/some/path/to/file with spaces.txt"),
382+
PathBuf::from("/some/path/[[...rest]]/file.txt"),
383+
PathBuf::from("/some/path/to/файл.txt"),
384+
PathBuf::from("/some/path/to/文件.txt"),
385+
];
386+
387+
let expected = [
388+
with_schema("/some/path/to/file.txt"),
389+
with_schema("/some/path/to/file%20with%20spaces.txt"),
390+
with_schema("/some/path/%5B%5B...rest%5D%5D/file.txt"),
391+
with_schema("/some/path/to/%D1%84%D0%B0%D0%B9%D0%BB.txt"),
392+
with_schema("/some/path/to/%E6%96%87%E4%BB%B6.txt"),
393+
];
394+
395+
for (path, expected) in paths.iter().zip(expected) {
396+
let uri = from_file_path(path).unwrap();
397+
assert_eq!(uri.to_string(), expected);
398+
}
399+
}
400+
401+
#[test]
402+
#[cfg(windows)]
403+
fn test_path_to_uri_windows() {
404+
let paths = [
405+
PathBuf::from("C:\\some\\path\\to\\file.txt"),
406+
PathBuf::from("C:\\some\\path\\to\\file with spaces.txt"),
407+
PathBuf::from("C:\\some\\path\\[[...rest]]\\file.txt"),
408+
PathBuf::from("C:\\some\\path\\to\\файл.txt"),
409+
PathBuf::from("C:\\some\\path\\to\\文件.txt"),
410+
];
411+
412+
let expected = [
413+
with_schema("C:/some/path/to/file.txt"),
414+
with_schema("C:/some/path/to/file%20with%20spaces.txt"),
415+
with_schema("C:/some/path/%5B%5B...rest%5D%5D/file.txt"),
416+
with_schema("C:/some/path/to/%D1%84%D0%B0%D0%B9%D0%BB.txt"),
417+
with_schema("C:/some/path/to/%E6%96%87%E4%BB%B6.txt"),
418+
];
419+
420+
for (path, expected) in paths.iter().zip(expected) {
421+
let uri = Uri::from_file_path(path).unwrap();
422+
assert_eq!(uri.to_string(), expected);
423+
}
424+
}
425+
}

0 commit comments

Comments
 (0)