@@ -10,6 +10,7 @@ pub use language::*;
1010use  lsp:: { LanguageServerBinary ,  LanguageServerName } ; 
1111use  regex:: Regex ; 
1212use  smol:: fs:: { self } ; 
13+ use  std:: fmt:: Display ; 
1314use  std:: { 
1415    any:: Any , 
1516    borrow:: Cow , 
@@ -444,6 +445,10 @@ const RUST_PACKAGE_TASK_VARIABLE: VariableName =
444445const  RUST_BIN_NAME_TASK_VARIABLE :  VariableName  =
445446    VariableName :: Custom ( Cow :: Borrowed ( "RUST_BIN_NAME" ) ) ; 
446447
448+ /// The bin kind (bin/example) corresponding to the current file in Cargo.toml 
449+ const  RUST_BIN_KIND_TASK_VARIABLE :  VariableName  =
450+     VariableName :: Custom ( Cow :: Borrowed ( "RUST_BIN_KIND" ) ) ; 
451+ 
447452const  RUST_MAIN_FUNCTION_TASK_VARIABLE :  VariableName  =
448453    VariableName :: Custom ( Cow :: Borrowed ( "_rust_main_function_end" ) ) ; 
449454
@@ -469,12 +474,16 @@ impl ContextProvider for RustContextProvider {
469474            . is_some ( ) ; 
470475
471476        if  is_main_function { 
472-             if  let  Some ( ( package_name ,  bin_name ) )  = local_abs_path. and_then ( |path| { 
477+             if  let  Some ( target )  = local_abs_path. and_then ( |path| { 
473478                package_name_and_bin_name_from_abs_path ( path,  project_env. as_ref ( ) ) 
474479            } )  { 
475480                return  Task :: ready ( Ok ( TaskVariables :: from_iter ( [ 
476-                     ( RUST_PACKAGE_TASK_VARIABLE . clone ( ) ,  package_name) , 
477-                     ( RUST_BIN_NAME_TASK_VARIABLE . clone ( ) ,  bin_name) , 
481+                     ( RUST_PACKAGE_TASK_VARIABLE . clone ( ) ,  target. package_name ) , 
482+                     ( RUST_BIN_NAME_TASK_VARIABLE . clone ( ) ,  target. target_name ) , 
483+                     ( 
484+                         RUST_BIN_KIND_TASK_VARIABLE . clone ( ) , 
485+                         target. target_kind . to_string ( ) , 
486+                     ) , 
478487                ] ) ) ) ; 
479488            } 
480489        } 
@@ -568,16 +577,17 @@ impl ContextProvider for RustContextProvider {
568577            } , 
569578            TaskTemplate  { 
570579                label:  format!( 
571-                     "cargo run -p {} --bin  {}" , 
580+                     "cargo run -p {} --{}  {}" , 
572581                    RUST_PACKAGE_TASK_VARIABLE . template_value( ) , 
582+                     RUST_BIN_KIND_TASK_VARIABLE . template_value( ) , 
573583                    RUST_BIN_NAME_TASK_VARIABLE . template_value( ) , 
574584                ) , 
575585                command:  "cargo" . into( ) , 
576586                args:  vec![ 
577587                    "run" . into( ) , 
578588                    "-p" . into( ) , 
579589                    RUST_PACKAGE_TASK_VARIABLE . template_value( ) , 
580-                     "--bin"  . into ( ) , 
590+                     format! ( "--{}"  ,   RUST_BIN_KIND_TASK_VARIABLE . template_value ( ) ) , 
581591                    RUST_BIN_NAME_TASK_VARIABLE . template_value( ) , 
582592                ] , 
583593                cwd:  Some ( "$ZED_DIRNAME" . to_owned( ) ) , 
@@ -635,10 +645,42 @@ struct CargoTarget {
635645    src_path :  String , 
636646} 
637647
648+ #[ derive( Debug ,  PartialEq ) ]  
649+ enum  TargetKind  { 
650+     Bin , 
651+     Example , 
652+ } 
653+ 
654+ impl  Display  for  TargetKind  { 
655+     fn  fmt ( & self ,  f :  & mut  std:: fmt:: Formatter < ' _ > )  -> std:: fmt:: Result  { 
656+         match  self  { 
657+             TargetKind :: Bin  => write ! ( f,  "bin" ) , 
658+             TargetKind :: Example  => write ! ( f,  "example" ) , 
659+         } 
660+     } 
661+ } 
662+ 
663+ impl  TryFrom < & str >  for  TargetKind  { 
664+     type  Error  = ( ) ; 
665+     fn  try_from ( value :  & str )  -> Result < Self ,  ( ) >  { 
666+         match  value { 
667+             "bin"  => Ok ( Self :: Bin ) , 
668+             "example"  => Ok ( Self :: Example ) , 
669+             _ => Err ( ( ) ) , 
670+         } 
671+     } 
672+ } 
673+ /// Which package and binary target are we in? 
674+ struct  TargetInfo  { 
675+     package_name :  String , 
676+     target_name :  String , 
677+     target_kind :  TargetKind , 
678+ } 
679+ 
638680fn  package_name_and_bin_name_from_abs_path ( 
639681    abs_path :  & Path , 
640682    project_env :  Option < & HashMap < String ,  String > > , 
641- )  -> Option < ( String ,   String ) >  { 
683+ )  -> Option < TargetInfo >  { 
642684    let  mut  command = util:: command:: new_std_command ( "cargo" ) ; 
643685    if  let  Some ( envs)  = project_env { 
644686        command. envs ( envs) ; 
@@ -656,24 +698,34 @@ fn package_name_and_bin_name_from_abs_path(
656698    let  metadata:  CargoMetadata  = serde_json:: from_slice ( & output) . log_err ( ) ?; 
657699
658700    retrieve_package_id_and_bin_name_from_metadata ( metadata,  abs_path) . and_then ( 
659-         |( package_id,  bin_name) | { 
701+         |( package_id,  bin_name,  target_kind ) | { 
660702            let  package_name = package_name_from_pkgid ( & package_id) ; 
661703
662-             package_name. map ( |package_name| ( package_name. to_owned ( ) ,  bin_name) ) 
704+             package_name. map ( |package_name| TargetInfo  { 
705+                 package_name :  package_name. to_owned ( ) , 
706+                 target_name :  bin_name, 
707+                 target_kind, 
708+             } ) 
663709        } , 
664710    ) 
665711} 
666712
667713fn  retrieve_package_id_and_bin_name_from_metadata ( 
668714    metadata :  CargoMetadata , 
669715    abs_path :  & Path , 
670- )  -> Option < ( String ,  String ) >  { 
716+ )  -> Option < ( String ,  String ,   TargetKind ) >  { 
671717    for  package in  metadata. packages  { 
672718        for  target in  package. targets  { 
673-             let  is_bin = target. kind . iter ( ) . any ( |kind| kind == "bin" ) ; 
719+             let  Some ( bin_kind)  = target
720+                 . kind 
721+                 . iter ( ) 
722+                 . find_map ( |kind| TargetKind :: try_from ( kind. as_ref ( ) ) . ok ( ) ) 
723+             else  { 
724+                 continue ; 
725+             } ; 
674726            let  target_path = PathBuf :: from ( target. src_path ) ; 
675-             if  target_path == abs_path && is_bin  { 
676-                 return  Some ( ( package. id ,  target. name ) ) ; 
727+             if  target_path == abs_path { 
728+                 return  Some ( ( package. id ,  target. name ,  bin_kind ) ) ; 
677729            } 
678730        } 
679731    } 
@@ -1066,14 +1118,28 @@ mod tests {
10661118            ( 
10671119                r#"{"packages":[{"id":"path+file:///path/to/zed/crates/zed#0.131.0","targets":[{"name":"zed","kind":["bin"],"src_path":"/path/to/zed/src/main.rs"}]}]}"# , 
10681120                "/path/to/zed/src/main.rs" , 
1069-                 Some ( ( "path+file:///path/to/zed/crates/zed#0.131.0" ,  "zed" ) ) , 
1121+                 Some ( ( 
1122+                     "path+file:///path/to/zed/crates/zed#0.131.0" , 
1123+                     "zed" , 
1124+                     TargetKind :: Bin , 
1125+                 ) ) , 
10701126            ) , 
10711127            ( 
10721128                r#"{"packages":[{"id":"path+file:///path/to/custom-package#[email protected] ","targets":[{"name":"my-custom-bin","kind":["bin"],"src_path":"/path/to/custom-package/src/main.rs"}]}]}"# ,  10731129                "/path/to/custom-package/src/main.rs" , 
10741130                Some ( ( 
10751131                    "path+file:///path/to/custom-package#[email protected] " ,  10761132                    "my-custom-bin" , 
1133+                     TargetKind :: Bin , 
1134+                 ) ) , 
1135+             ) , 
1136+             ( 
1137+                 r#"{"packages":[{"id":"path+file:///path/to/custom-package#[email protected] ","targets":[{"name":"my-custom-bin","kind":["example"],"src_path":"/path/to/custom-package/src/main.rs"}]}]}"# ,  1138+                 "/path/to/custom-package/src/main.rs" , 
1139+                 Some ( ( 
1140+                     "path+file:///path/to/custom-package#[email protected] " ,  1141+                     "my-custom-bin" , 
1142+                     TargetKind :: Example , 
10771143                ) ) , 
10781144            ) , 
10791145            ( 
@@ -1088,7 +1154,7 @@ mod tests {
10881154
10891155            assert_eq ! ( 
10901156                retrieve_package_id_and_bin_name_from_metadata( metadata,  absolute_path) , 
1091-                 expected. map( |( pkgid,  bin ) | ( pkgid. to_owned( ) ,  bin . to_owned( ) ) ) 
1157+                 expected. map( |( pkgid,  name ,  kind ) | ( pkgid. to_owned( ) ,  name . to_owned( ) ,  kind ) ) 
10921158            ) ; 
10931159        } 
10941160    } 
0 commit comments