@@ -102,6 +102,8 @@ pub struct ChangeFixture {
102
102
pub change : Change ,
103
103
}
104
104
105
+ const SOURCE_ROOT_PREFIX : & str = "/" ;
106
+
105
107
impl ChangeFixture {
106
108
pub fn parse ( ra_fixture : & str ) -> ChangeFixture {
107
109
Self :: parse_with_proc_macros ( ra_fixture, Vec :: new ( ) )
@@ -131,7 +133,6 @@ impl ChangeFixture {
131
133
132
134
let mut file_set = FileSet :: default ( ) ;
133
135
let mut current_source_root_kind = SourceRootKind :: Local ;
134
- let source_root_prefix = "/" . to_string ( ) ;
135
136
let mut file_id = FileId ( 0 ) ;
136
137
let mut roots = Vec :: new ( ) ;
137
138
@@ -151,19 +152,23 @@ impl ChangeFixture {
151
152
entry. text . clone ( )
152
153
} ;
153
154
154
- let meta = FileMeta :: from ( entry) ;
155
- assert ! ( meta. path. starts_with( & source_root_prefix ) ) ;
155
+ let meta = FileMeta :: from_fixture ( entry, current_source_root_kind ) ;
156
+ assert ! ( meta. path. starts_with( SOURCE_ROOT_PREFIX ) ) ;
156
157
if !meta. deps . is_empty ( ) {
157
158
assert ! ( meta. krate. is_some( ) , "can't specify deps without naming the crate" )
158
159
}
159
160
160
- if let Some ( kind) = & meta. introduce_new_source_root {
161
- let root = match current_source_root_kind {
161
+ if let Some ( kind) = meta. introduce_new_source_root {
162
+ assert ! (
163
+ meta. krate. is_some( ) ,
164
+ "new_source_root meta doesn't make sense without crate meta"
165
+ ) ;
166
+ let prev_kind = mem:: replace ( & mut current_source_root_kind, kind) ;
167
+ let prev_root = match prev_kind {
162
168
SourceRootKind :: Local => SourceRoot :: new_local ( mem:: take ( & mut file_set) ) ,
163
169
SourceRootKind :: Library => SourceRoot :: new_library ( mem:: take ( & mut file_set) ) ,
164
170
} ;
165
- roots. push ( root) ;
166
- current_source_root_kind = * kind;
171
+ roots. push ( prev_root) ;
167
172
}
168
173
169
174
if let Some ( ( krate, origin, version) ) = meta. krate {
@@ -185,7 +190,7 @@ impl ChangeFixture {
185
190
Some ( toolchain) ,
186
191
) ;
187
192
let prev = crates. insert ( crate_name. clone ( ) , crate_id) ;
188
- assert ! ( prev. is_none( ) ) ;
193
+ assert ! ( prev. is_none( ) , "multiple crates with same name: {}" , crate_name ) ;
189
194
for dep in meta. deps {
190
195
let prelude = meta. extern_prelude . contains ( & dep) ;
191
196
let dep = CrateName :: normalize_dashes ( & dep) ;
@@ -442,51 +447,74 @@ struct FileMeta {
442
447
target_data_layout : Option < String > ,
443
448
}
444
449
445
- fn parse_crate ( crate_str : String ) -> ( String , CrateOrigin , Option < String > ) {
446
- if let Some ( ( a, b) ) = crate_str. split_once ( '@' ) {
447
- let ( version, origin) = match b. split_once ( ':' ) {
448
- Some ( ( "CratesIo" , data) ) => match data. split_once ( ',' ) {
449
- Some ( ( version, url) ) => {
450
- ( version, CrateOrigin :: Local { repo : Some ( url. to_owned ( ) ) , name : None } )
451
- }
452
- _ => panic ! ( "Bad crates.io parameter: {data}" ) ,
453
- } ,
454
- _ => panic ! ( "Bad string for crate origin: {b}" ) ,
455
- } ;
456
- ( a. to_owned ( ) , origin, Some ( version. to_string ( ) ) )
457
- } else {
458
- let crate_origin = match LangCrateOrigin :: from ( & * crate_str) {
459
- LangCrateOrigin :: Other => CrateOrigin :: Local { repo : None , name : None } ,
460
- origin => CrateOrigin :: Lang ( origin) ,
461
- } ;
462
- ( crate_str, crate_origin, None )
463
- }
464
- }
465
-
466
- impl From < Fixture > for FileMeta {
467
- fn from ( f : Fixture ) -> FileMeta {
450
+ impl FileMeta {
451
+ fn from_fixture ( f : Fixture , current_source_root_kind : SourceRootKind ) -> Self {
468
452
let mut cfg = CfgOptions :: default ( ) ;
469
- f. cfg_atoms . iter ( ) . for_each ( |it| cfg. insert_atom ( it. into ( ) ) ) ;
470
- f. cfg_key_values . iter ( ) . for_each ( |( k, v) | cfg. insert_key_value ( k. into ( ) , v. into ( ) ) ) ;
453
+ for ( k, v) in f. cfgs {
454
+ if let Some ( v) = v {
455
+ cfg. insert_key_value ( k. into ( ) , v. into ( ) ) ;
456
+ } else {
457
+ cfg. insert_atom ( k. into ( ) ) ;
458
+ }
459
+ }
460
+
461
+ let introduce_new_source_root = f. introduce_new_source_root . map ( |kind| match & * kind {
462
+ "local" => SourceRootKind :: Local ,
463
+ "library" => SourceRootKind :: Library ,
464
+ invalid => panic ! ( "invalid source root kind '{invalid}'" ) ,
465
+ } ) ;
466
+ let current_source_root_kind =
467
+ introduce_new_source_root. unwrap_or ( current_source_root_kind) ;
468
+
471
469
let deps = f. deps ;
472
- FileMeta {
470
+ Self {
473
471
path : f. path ,
474
- krate : f. krate . map ( parse_crate) ,
472
+ krate : f. krate . map ( |it| parse_crate ( it , current_source_root_kind , f . library ) ) ,
475
473
extern_prelude : f. extern_prelude . unwrap_or_else ( || deps. clone ( ) ) ,
476
474
deps,
477
475
cfg,
478
- edition : f. edition . as_ref ( ) . map_or ( Edition :: CURRENT , |v| Edition :: from_str ( v) . unwrap ( ) ) ,
476
+ edition : f. edition . map_or ( Edition :: CURRENT , |v| Edition :: from_str ( & v) . unwrap ( ) ) ,
479
477
env : f. env . into_iter ( ) . collect ( ) ,
480
- introduce_new_source_root : f. introduce_new_source_root . map ( |kind| match & * kind {
481
- "local" => SourceRootKind :: Local ,
482
- "library" => SourceRootKind :: Library ,
483
- invalid => panic ! ( "invalid source root kind '{invalid}'" ) ,
484
- } ) ,
478
+ introduce_new_source_root,
485
479
target_data_layout : f. target_data_layout ,
486
480
}
487
481
}
488
482
}
489
483
484
+ fn parse_crate (
485
+ crate_str : String ,
486
+ current_source_root_kind : SourceRootKind ,
487
+ explicit_non_workspace_member : bool ,
488
+ ) -> ( String , CrateOrigin , Option < String > ) {
489
+ // syntax:
490
+ // "my_awesome_crate"
491
+ // "[email protected] ,http://example.com"
492
+ let ( name, repo, version) = if let Some ( ( name, remain) ) = crate_str. split_once ( '@' ) {
493
+ let ( version, repo) =
494
+ remain. split_once ( ',' ) . expect ( "crate meta: found '@' without version and url" ) ;
495
+ ( name. to_owned ( ) , Some ( repo. to_owned ( ) ) , Some ( version. to_owned ( ) ) )
496
+ } else {
497
+ ( crate_str, None , None )
498
+ } ;
499
+
500
+ let non_workspace_member = explicit_non_workspace_member
501
+ || matches ! ( current_source_root_kind, SourceRootKind :: Library ) ;
502
+
503
+ let origin = match LangCrateOrigin :: from ( & * name) {
504
+ LangCrateOrigin :: Other => {
505
+ let name = name. clone ( ) ;
506
+ if non_workspace_member {
507
+ CrateOrigin :: Library { repo, name }
508
+ } else {
509
+ CrateOrigin :: Local { repo, name : Some ( name) }
510
+ }
511
+ }
512
+ origin => CrateOrigin :: Lang ( origin) ,
513
+ } ;
514
+
515
+ ( name, origin, version)
516
+ }
517
+
490
518
// Identity mapping
491
519
#[ derive( Debug ) ]
492
520
struct IdentityProcMacroExpander ;
0 commit comments