@@ -10,6 +10,7 @@ pub use language::*;
10
10
use lsp:: { LanguageServerBinary , LanguageServerName } ;
11
11
use regex:: Regex ;
12
12
use smol:: fs:: { self } ;
13
+ use std:: fmt:: Display ;
13
14
use std:: {
14
15
any:: Any ,
15
16
borrow:: Cow ,
@@ -444,6 +445,10 @@ const RUST_PACKAGE_TASK_VARIABLE: VariableName =
444
445
const RUST_BIN_NAME_TASK_VARIABLE : VariableName =
445
446
VariableName :: Custom ( Cow :: Borrowed ( "RUST_BIN_NAME" ) ) ;
446
447
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
+
447
452
const RUST_MAIN_FUNCTION_TASK_VARIABLE : VariableName =
448
453
VariableName :: Custom ( Cow :: Borrowed ( "_rust_main_function_end" ) ) ;
449
454
@@ -469,12 +474,16 @@ impl ContextProvider for RustContextProvider {
469
474
. is_some ( ) ;
470
475
471
476
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| {
473
478
package_name_and_bin_name_from_abs_path ( path, project_env. as_ref ( ) )
474
479
} ) {
475
480
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
+ ) ,
478
487
] ) ) ) ;
479
488
}
480
489
}
@@ -568,16 +577,17 @@ impl ContextProvider for RustContextProvider {
568
577
} ,
569
578
TaskTemplate {
570
579
label: format!(
571
- "cargo run -p {} --bin {}" ,
580
+ "cargo run -p {} --{} {}" ,
572
581
RUST_PACKAGE_TASK_VARIABLE . template_value( ) ,
582
+ RUST_BIN_KIND_TASK_VARIABLE . template_value( ) ,
573
583
RUST_BIN_NAME_TASK_VARIABLE . template_value( ) ,
574
584
) ,
575
585
command: "cargo" . into( ) ,
576
586
args: vec![
577
587
"run" . into( ) ,
578
588
"-p" . into( ) ,
579
589
RUST_PACKAGE_TASK_VARIABLE . template_value( ) ,
580
- "--bin" . into ( ) ,
590
+ format! ( "--{}" , RUST_BIN_KIND_TASK_VARIABLE . template_value ( ) ) ,
581
591
RUST_BIN_NAME_TASK_VARIABLE . template_value( ) ,
582
592
] ,
583
593
cwd: Some ( "$ZED_DIRNAME" . to_owned( ) ) ,
@@ -635,10 +645,42 @@ struct CargoTarget {
635
645
src_path : String ,
636
646
}
637
647
648
+ #[ derive( 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
+
638
680
fn package_name_and_bin_name_from_abs_path (
639
681
abs_path : & Path ,
640
682
project_env : Option < & HashMap < String , String > > ,
641
- ) -> Option < ( String , String ) > {
683
+ ) -> Option < TargetInfo > {
642
684
let mut command = util:: command:: new_std_command ( "cargo" ) ;
643
685
if let Some ( envs) = project_env {
644
686
command. envs ( envs) ;
@@ -656,24 +698,34 @@ fn package_name_and_bin_name_from_abs_path(
656
698
let metadata: CargoMetadata = serde_json:: from_slice ( & output) . log_err ( ) ?;
657
699
658
700
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 ) | {
660
702
let package_name = package_name_from_pkgid ( & package_id) ;
661
703
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
+ } )
663
709
} ,
664
710
)
665
711
}
666
712
667
713
fn retrieve_package_id_and_bin_name_from_metadata (
668
714
metadata : CargoMetadata ,
669
715
abs_path : & Path ,
670
- ) -> Option < ( String , String ) > {
716
+ ) -> Option < ( String , String , TargetKind ) > {
671
717
for package in metadata. packages {
672
718
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
+ } ;
674
726
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 ) ) ;
677
729
}
678
730
}
679
731
}
0 commit comments