11use std:: collections:: HashMap ;
22use std:: env;
3+ use std:: borrow:: Cow ;
34use std:: path:: { Path , PathBuf } ;
45
56use tokio:: sync:: Mutex ;
@@ -8,6 +9,7 @@ use crate::shared::process_core::tokio_command;
89#[ cfg( target_os = "windows" ) ]
910use crate :: shared:: process_core:: { build_cmd_c_command, resolve_windows_executable} ;
1011use crate :: types:: WorkspaceEntry ;
12+ use crate :: utils:: normalize_windows_namespace_path;
1113
1214use super :: helpers:: resolve_workspace_root;
1315
@@ -132,8 +134,12 @@ fn build_launch_args(
132134 strategy : Option < LineAwareLaunchStrategy > ,
133135) -> Vec < String > {
134136 let mut launch_args = args. to_vec ( ) ;
137+ let path: Cow < ' _ , str > = match strategy {
138+ Some ( _) => Cow :: Owned ( normalize_windows_namespace_path ( path) ) ,
139+ None => Cow :: Borrowed ( path) ,
140+ } ;
135141 if let Some ( ( line, column) ) = normalize_open_location ( line, column) {
136- let located_path = format_path_with_location ( path, line, column) ;
142+ let located_path = format_path_with_location ( & path, line, column) ;
137143 match strategy {
138144 Some ( LineAwareLaunchStrategy :: GotoFlag ) => {
139145 launch_args. push ( "--goto" . to_string ( ) ) ;
@@ -143,12 +149,12 @@ fn build_launch_args(
143149 launch_args. push ( located_path) ;
144150 }
145151 None => {
146- launch_args. push ( path. to_string ( ) ) ;
152+ launch_args. push ( path. into_owned ( ) ) ;
147153 }
148154 }
149155 return launch_args;
150156 }
151- launch_args. push ( path. to_string ( ) ) ;
157+ launch_args. push ( path. into_owned ( ) ) ;
152158 launch_args
153159}
154160
@@ -186,13 +192,8 @@ pub(crate) async fn open_workspace_in_core(
186192 if trimmed. is_empty ( ) {
187193 return Err ( "Missing app or command" . to_string ( ) ) ;
188194 }
189- let launch_args = build_launch_args (
190- & path,
191- & args,
192- line,
193- column,
194- command_launch_strategy ( trimmed) ,
195- ) ;
195+ let launch_args =
196+ build_launch_args ( & path, & args, line, column, command_launch_strategy ( trimmed) ) ;
196197
197198 #[ cfg( target_os = "windows" ) ]
198199 let mut cmd = {
@@ -380,6 +381,85 @@ mod tests {
380381 ) ;
381382 }
382383
384+ #[ test]
385+ fn builds_goto_args_with_windows_namespace_path_sanitized ( ) {
386+ let args = build_launch_args (
387+ r"\\?\I:\gpt-projects\json-composer\src\App.tsx" ,
388+ & [ "--reuse-window" . to_string ( ) ] ,
389+ Some ( 33 ) ,
390+ Some ( 7 ) ,
391+ Some ( LineAwareLaunchStrategy :: GotoFlag ) ,
392+ ) ;
393+
394+ assert_eq ! (
395+ args,
396+ vec![
397+ "--reuse-window" . to_string( ) ,
398+ "--goto" . to_string( ) ,
399+ r"I:\gpt-projects\json-composer\src\App.tsx:33:7" . to_string( ) ,
400+ ]
401+ ) ;
402+ }
403+
404+ #[ test]
405+ fn builds_goto_args_with_lowercase_unc_namespace_path_sanitized ( ) {
406+ let args = build_launch_args (
407+ r"\\?\unc\server\share\repo\src\App.tsx" ,
408+ & [ "--reuse-window" . to_string ( ) ] ,
409+ Some ( 12 ) ,
410+ Some ( 2 ) ,
411+ Some ( LineAwareLaunchStrategy :: GotoFlag ) ,
412+ ) ;
413+
414+ assert_eq ! (
415+ args,
416+ vec![
417+ "--reuse-window" . to_string( ) ,
418+ "--goto" . to_string( ) ,
419+ r"\\server\share\repo\src\App.tsx:12:2" . to_string( ) ,
420+ ]
421+ ) ;
422+ }
423+
424+ #[ test]
425+ fn preserves_namespace_path_for_unknown_targets ( ) {
426+ let args = build_launch_args (
427+ r"\\?\I:\very\long\workspace" ,
428+ & [ "--foreground" . to_string ( ) ] ,
429+ None ,
430+ None ,
431+ None ,
432+ ) ;
433+
434+ assert_eq ! (
435+ args,
436+ vec![
437+ "--foreground" . to_string( ) ,
438+ r"\\?\I:\very\long\workspace" . to_string( ) ,
439+ ]
440+ ) ;
441+ }
442+
443+ #[ test]
444+ fn preserves_non_drive_namespace_path_for_line_aware_targets ( ) {
445+ let args = build_launch_args (
446+ r"\\?\Volume{01234567-89ab-cdef-0123-456789abcdef}\repo\src\App.tsx" ,
447+ & [ ] ,
448+ Some ( 5 ) ,
449+ None ,
450+ Some ( LineAwareLaunchStrategy :: GotoFlag ) ,
451+ ) ;
452+
453+ assert_eq ! (
454+ args,
455+ vec![
456+ "--goto" . to_string( ) ,
457+ r"\\?\Volume{01234567-89ab-cdef-0123-456789abcdef}\repo\src\App.tsx:5"
458+ . to_string( ) ,
459+ ]
460+ ) ;
461+ }
462+
383463 #[ test]
384464 fn builds_line_suffixed_path_for_zed_targets ( ) {
385465 let args = build_launch_args (
0 commit comments