@@ -14,8 +14,12 @@ use std::{
1414 path:: { Path , PathBuf } ,
1515} ;
1616
17+ pub use ra_cfg:: CfgOptions ;
18+
1719use serde_json:: Value ;
1820use text_size:: { TextRange , TextSize } ;
21+ pub use relative_path:: { RelativePath , RelativePathBuf } ;
22+ pub use rustc_hash:: FxHashMap ;
1923
2024pub use difference:: Changeset as __Changeset;
2125
@@ -159,6 +163,33 @@ pub fn add_cursor(text: &str, offset: TextSize) -> String {
159163pub struct FixtureEntry {
160164 pub meta : String ,
161165 pub text : String ,
166+
167+ pub parsed_meta : FixtureMeta ,
168+ }
169+
170+ #[ derive( Debug , Eq , PartialEq ) ]
171+ pub enum FixtureMeta {
172+ Root { path : RelativePathBuf } ,
173+ File ( FileMeta ) ,
174+ }
175+
176+ #[ derive( Debug , Eq , PartialEq ) ]
177+ pub struct FileMeta {
178+ pub path : RelativePathBuf ,
179+ pub krate : Option < String > ,
180+ pub deps : Vec < String > ,
181+ pub cfg : ra_cfg:: CfgOptions ,
182+ pub edition : Option < String > ,
183+ pub env : FxHashMap < String , String > ,
184+ }
185+
186+ impl FixtureMeta {
187+ pub fn path ( & self ) -> & RelativePath {
188+ match self {
189+ FixtureMeta :: Root { path } => & path,
190+ FixtureMeta :: File ( f) => & f. path ,
191+ }
192+ }
162193}
163194
164195/// Parses text which looks like this:
@@ -200,7 +231,8 @@ The offending line: {:?}"#,
200231 for line in lines. by_ref ( ) {
201232 if line. starts_with ( "//-" ) {
202233 let meta = line[ "//-" . len ( ) ..] . trim ( ) . to_string ( ) ;
203- res. push ( FixtureEntry { meta, text : String :: new ( ) } )
234+ let parsed_meta = parse_meta ( & meta) ;
235+ res. push ( FixtureEntry { meta, parsed_meta, text : String :: new ( ) } )
204236 } else if let Some ( entry) = res. last_mut ( ) {
205237 entry. text . push_str ( line) ;
206238 entry. text . push ( '\n' ) ;
@@ -209,6 +241,58 @@ The offending line: {:?}"#,
209241 res
210242}
211243
244+ //- /lib.rs crate:foo deps:bar,baz cfg:foo=a,bar=b env:OUTDIR=path/to,OTHER=foo
245+ fn parse_meta ( meta : & str ) -> FixtureMeta {
246+ let components = meta. split_ascii_whitespace ( ) . collect :: < Vec < _ > > ( ) ;
247+
248+ if components[ 0 ] == "root" {
249+ let path: RelativePathBuf = components[ 1 ] . into ( ) ;
250+ assert ! ( path. starts_with( "/" ) && path. ends_with( "/" ) ) ;
251+ return FixtureMeta :: Root { path } ;
252+ }
253+
254+ let path: RelativePathBuf = components[ 0 ] . into ( ) ;
255+ assert ! ( path. starts_with( "/" ) ) ;
256+
257+ let mut krate = None ;
258+ let mut deps = Vec :: new ( ) ;
259+ let mut edition = None ;
260+ let mut cfg = CfgOptions :: default ( ) ;
261+ let mut env = FxHashMap :: default ( ) ;
262+ for component in components[ 1 ..] . iter ( ) {
263+ let ( key, value) = split1 ( component, ':' ) . unwrap ( ) ;
264+ match key {
265+ "crate" => krate = Some ( value. to_string ( ) ) ,
266+ "deps" => deps = value. split ( ',' ) . map ( |it| it. to_string ( ) ) . collect ( ) ,
267+ "edition" => edition = Some ( value. to_string ( ) ) ,
268+ "cfg" => {
269+ for key in value. split ( ',' ) {
270+ match split1 ( key, '=' ) {
271+ None => cfg. insert_atom ( key. into ( ) ) ,
272+ Some ( ( k, v) ) => cfg. insert_key_value ( k. into ( ) , v. into ( ) ) ,
273+ }
274+ }
275+ }
276+ "env" => {
277+ for key in value. split ( ',' ) {
278+ if let Some ( ( k, v) ) = split1 ( key, '=' ) {
279+ env. insert ( k. into ( ) , v. into ( ) ) ;
280+ }
281+ }
282+ }
283+ _ => panic ! ( "bad component: {:?}" , component) ,
284+ }
285+ }
286+
287+ FixtureMeta :: File ( FileMeta { path, krate, deps, edition, cfg, env } )
288+ }
289+
290+ fn split1 ( haystack : & str , delim : char ) -> Option < ( & str , & str ) > {
291+ let idx = haystack. find ( delim) ?;
292+ Some ( ( & haystack[ ..idx] , & haystack[ idx + delim. len_utf8 ( ) ..] ) )
293+ }
294+
295+
212296/// Adjusts the indentation of the first line to the minimum indentation of the rest of the lines.
213297/// This allows fixtures to start off in a different indentation, e.g. to align the first line with
214298/// the other lines visually:
@@ -288,6 +372,18 @@ struct Bar;
288372 )
289373}
290374
375+ #[ test]
376+ fn parse_fixture_gets_full_meta ( ) {
377+ let fixture = r"
378+ //- /lib.rs crate:foo deps:bar,baz cfg:foo=a,bar=b,atom env:OUTDIR=path/to,OTHER=foo
379+ " ;
380+ let parsed = parse_fixture ( fixture) ;
381+ assert_eq ! ( 1 , parsed. len( ) ) ;
382+
383+ let parsed = & parsed[ 0 ] ;
384+ assert_eq ! ( "\n " , parsed. text) ;
385+ }
386+
291387/// Same as `parse_fixture`, except it allow empty fixture
292388pub fn parse_single_fixture ( fixture : & str ) -> Option < FixtureEntry > {
293389 if !fixture. lines ( ) . any ( |it| it. trim_start ( ) . starts_with ( "//-" ) ) {
0 commit comments