Skip to content

Commit 313e0cf

Browse files
committed
refactor(language_server): introduce helper path_to_uri
1 parent bbf7107 commit 313e0cf

File tree

5 files changed

+71
-0
lines changed

5 files changed

+71
-0
lines changed

Cargo.lock

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

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,7 @@ nonmax = "0.5.5"
204204
num-bigint = "0.4.6"
205205
num-traits = "0.2.19"
206206
papaya = "0.2.1"
207+
percent-encoding = "2.3.1"
207208
petgraph = { version = "0.8.1", default-features = false }
208209
phf = "0.11.3"
209210
phf_codegen = "0.11.3"

crates/oxc_language_server/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ globset = { workspace = true }
3333
ignore = { workspace = true, features = ["simd-accel"] }
3434
log = { workspace = true }
3535
papaya = { workspace = true }
36+
percent-encoding = { workspace = true }
3637
rustc-hash = { workspace = true }
3738
serde = { workspace = true, features = ["derive"] }
3839
serde_json = { workspace = true }

crates/oxc_language_server/src/main.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ mod linter;
3030
mod options;
3131
#[cfg(test)]
3232
mod tester;
33+
mod uri_ext;
3334
mod worker;
3435

3536
type ConcurrentHashMap<K, V> = papaya::HashMap<K, V, FxBuildHasher>;
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
use std::{path::{Path, PathBuf}, str::FromStr};
2+
3+
use percent_encoding::AsciiSet;
4+
use tower_lsp_server::lsp_types::Uri;
5+
6+
fn path_to_uri(path: &PathBuf) -> Uri {
7+
let path_str = normalize_path_with_utf8_percent_encode(path);
8+
Uri::from_str(&format!("file://{}", path_str.to_string_lossy())).expect("Failed to create URI from path")
9+
}
10+
11+
const ASCII_SET: AsciiSet = percent_encoding::NON_ALPHANUMERIC.remove(b'.');
12+
13+
/// Normalize a path by removing `.` and resolving `..` components,
14+
/// without touching the filesystem.
15+
pub fn normalize_path_with_utf8_percent_encode<P: AsRef<Path>>(path: P) -> PathBuf {
16+
let mut result = PathBuf::new();
17+
let components = path.as_ref().components();
18+
19+
for component in components {
20+
match component {
21+
std::path::Component::Prefix(_) => {
22+
// Keep the prefix (e.g., drive letter on Windows)
23+
result.push(component.as_os_str());
24+
}
25+
std::path::Component::RootDir => {
26+
// Keep the root directory
27+
result.push(component.as_os_str());
28+
}
29+
std::path::Component::Normal(part) => {
30+
// Normal components are added to the path
31+
result.push(percent_encoding::utf8_percent_encode(&part.to_str().unwrap(), &ASCII_SET).to_string());
32+
}
33+
_ => {}
34+
}
35+
}
36+
37+
result
38+
}
39+
#[cfg(test)]
40+
mod test {
41+
use std::path::PathBuf;
42+
43+
use crate::uri_ext::path_to_uri;
44+
45+
46+
#[test]
47+
fn test_path_to_uri() {
48+
let path = PathBuf::from("/some/path/to/file.txt");
49+
let uri = path_to_uri(&path);
50+
assert_eq!(uri.to_string(), "file:///some/path/to/file.txt");
51+
}
52+
53+
#[test]
54+
fn test_path_to_uri_with_spaces() {
55+
let path = PathBuf::from("/some/path/to/file with spaces.txt");
56+
let uri = path_to_uri(&path);
57+
assert_eq!(uri.to_string(), "file:///some/path/to/file%20with%20spaces.txt");
58+
}
59+
60+
#[test]
61+
62+
fn test_path_to_uri_with_special_characters() {
63+
let path = PathBuf::from("/some/path/[[...rest]]/file.txt");
64+
let uri = path_to_uri(&path);
65+
assert_eq!(uri.to_string(), "file:///some/path/%5B%5B...rest%5D%5D/file.txt");
66+
}
67+
}

0 commit comments

Comments
 (0)