@@ -283,20 +283,64 @@ pub fn path_to_uri(path: &str) -> anyhow::Result<Uri> {
283283 . canonicalize ( )
284284 . unwrap_or_else ( |_| path_obj. to_path_buf ( ) ) ;
285285
286- let path_str = canonical_path. to_string_lossy ( ) . replace ( '\\' , "/" ) ;
287-
288- let uri_str = if path_str. len ( ) > 2 && & path_str[ 1 ..2 ] == ":" {
289- // Windows path like C:/... -> file:///C:/...
290- format ! ( "file:///{}" , path_str)
291- } else if path_str. starts_with ( '/' ) {
292- // Unix absolute path /path -> file:///path
293- format ! ( "file://{}" , path_str)
286+ let absolute_path = if canonical_path. is_absolute ( ) {
287+ canonical_path
294288 } else {
295- // Relative path -> file:///path
296- format ! ( "file:///{}" , path_str)
289+ std:: env:: current_dir ( ) ?. join ( canonical_path)
297290 } ;
298291
299- uri_str
292+ let url = url:: Url :: from_file_path ( & absolute_path)
293+ . map_err ( |_| anyhow:: anyhow!( "Failed to convert path to Url: {:?}" , absolute_path) ) ?;
294+
295+ url. as_str ( )
300296 . parse ( )
301297 . map_err ( |e| anyhow:: anyhow!( "Failed to parse URI: {}" , e) )
302298}
299+
300+ #[ cfg( test) ]
301+ mod tests {
302+ use super :: * ;
303+
304+ #[ test]
305+ fn test_path_to_uri_with_spaces ( ) {
306+ let path = if cfg ! ( target_os = "windows" ) {
307+ r"C:\Users\max\dev\anycode\code copy.ts"
308+ } else {
309+ "/Users/max/dev/anycode/code copy.ts"
310+ } ;
311+ let uri = path_to_uri ( path) . unwrap ( ) ;
312+ assert ! ( uri. to_string( ) . contains( "code%20copy.ts" ) ) ;
313+ }
314+
315+ #[ test]
316+ fn test_path_to_uri_relative ( ) {
317+ let path = "src/utils.rs" ;
318+ let uri = path_to_uri ( path) . unwrap ( ) ;
319+ assert ! ( uri. to_string( ) . starts_with( "file:///" ) ) ;
320+ assert ! ( uri. to_string( ) . ends_with( "src/utils.rs" ) ) ;
321+ }
322+
323+ #[ test]
324+ fn test_path_to_uri_cyrillic ( ) {
325+ let path = if cfg ! ( target_os = "windows" ) {
326+ r"C:\Users\max\dev\anycode\привет мир.ts"
327+ } else {
328+ "/Users/max/dev/anycode/привет мир.ts"
329+ } ;
330+ let uri = path_to_uri ( path) . unwrap ( ) ;
331+ assert ! ( uri. to_string( ) . contains( "%20" ) ) ;
332+ // "привет" in UTF-8 percent-encoded is %D0%BF%D1%80%D0%B8%D0%B2%D0%B5%D1%82
333+ assert ! ( uri. to_string( ) . contains( "%D0%BF%D1%80%D0%B8%D0%B2%D0%B5%D1%82" ) ) ;
334+ }
335+
336+ #[ test]
337+ fn test_path_to_uri_special_chars ( ) {
338+ let path = if cfg ! ( target_os = "windows" ) {
339+ r"C:\Users\max\dev\anycode\file#name?.ts"
340+ } else {
341+ "/Users/max/dev/anycode/file#name?.ts"
342+ } ;
343+ let uri = path_to_uri ( path) . unwrap ( ) ;
344+ assert ! ( uri. to_string( ) . contains( "file%23name%3F.ts" ) ) ;
345+ }
346+ }
0 commit comments