11//! FIXME: write short doc here
22
3+ use std:: str:: FromStr ;
34use std:: sync:: Arc ;
45
56use ra_cfg:: CfgOptions ;
67use ra_db:: { CrateName , Env , RelativePathBuf } ;
7- use test_utils:: { extract_offset, extract_range, parse_fixture, CURSOR_MARKER } ;
8+ use test_utils:: { extract_offset, extract_range, parse_fixture, FixtureEntry , CURSOR_MARKER } ;
89
910use crate :: {
10- Analysis , AnalysisChange , AnalysisHost , CrateGraph , Edition :: Edition2018 , FileId , FilePosition ,
11- FileRange , SourceRootId ,
11+ Analysis , AnalysisChange , AnalysisHost , CrateGraph , Edition , FileId , FilePosition , FileRange ,
12+ SourceRootId ,
1213} ;
1314
15+ #[ derive( Debug ) ]
16+ enum MockFileData {
17+ Plain { path : String , content : String } ,
18+ Fixture ( FixtureEntry ) ,
19+ }
20+
21+ impl MockFileData {
22+ fn new ( path : String , content : String ) -> Self {
23+ // `Self::Plain` causes a false warning: 'variant is never constructed: `Plain` '
24+ // see https://github.com/rust-lang/rust/issues/69018
25+ MockFileData :: Plain { path, content }
26+ }
27+
28+ fn path ( & self ) -> & str {
29+ match self {
30+ MockFileData :: Plain { path, .. } => path. as_str ( ) ,
31+ MockFileData :: Fixture ( f) => f. meta . path ( ) . as_str ( ) ,
32+ }
33+ }
34+
35+ fn content ( & self ) -> & str {
36+ match self {
37+ MockFileData :: Plain { content, .. } => content,
38+ MockFileData :: Fixture ( f) => f. text . as_str ( ) ,
39+ }
40+ }
41+
42+ fn cfg_options ( & self ) -> CfgOptions {
43+ match self {
44+ MockFileData :: Fixture ( f) => {
45+ f. meta . cfg_options ( ) . map_or_else ( Default :: default, |o| o. clone ( ) )
46+ }
47+ _ => CfgOptions :: default ( ) ,
48+ }
49+ }
50+
51+ fn edition ( & self ) -> Edition {
52+ match self {
53+ MockFileData :: Fixture ( f) => {
54+ f. meta . edition ( ) . map_or ( Edition :: Edition2018 , |v| Edition :: from_str ( v) . unwrap ( ) )
55+ }
56+ _ => Edition :: Edition2018 ,
57+ }
58+ }
59+
60+ fn env ( & self ) -> Env {
61+ match self {
62+ MockFileData :: Fixture ( f) => Env :: from ( f. meta . env ( ) ) ,
63+ _ => Env :: default ( ) ,
64+ }
65+ }
66+ }
67+
68+ impl From < FixtureEntry > for MockFileData {
69+ fn from ( fixture : FixtureEntry ) -> Self {
70+ Self :: Fixture ( fixture)
71+ }
72+ }
73+
1474/// Mock analysis is used in test to bootstrap an AnalysisHost/Analysis
1575/// from a set of in-memory files.
1676#[ derive( Debug , Default ) ]
1777pub struct MockAnalysis {
18- files : Vec < ( String , String ) > ,
78+ files : Vec < MockFileData > ,
1979}
2080
2181impl MockAnalysis {
@@ -35,7 +95,7 @@ impl MockAnalysis {
3595 pub fn with_files ( fixture : & str ) -> MockAnalysis {
3696 let mut res = MockAnalysis :: new ( ) ;
3797 for entry in parse_fixture ( fixture) {
38- res. add_file ( & entry. meta , & entry . text ) ;
98+ res. add_file_fixture ( entry) ;
3999 }
40100 res
41101 }
@@ -48,38 +108,52 @@ impl MockAnalysis {
48108 for entry in parse_fixture ( fixture) {
49109 if entry. text . contains ( CURSOR_MARKER ) {
50110 assert ! ( position. is_none( ) , "only one marker (<|>) per fixture is allowed" ) ;
51- position = Some ( res. add_file_with_position ( & entry. meta , & entry . text ) ) ;
111+ position = Some ( res. add_file_fixture_with_position ( entry) ) ;
52112 } else {
53- res. add_file ( & entry. meta , & entry . text ) ;
113+ res. add_file_fixture ( entry) ;
54114 }
55115 }
56116 let position = position. expect ( "expected a marker (<|>)" ) ;
57117 ( res, position)
58118 }
59119
120+ pub fn add_file_fixture ( & mut self , fixture : FixtureEntry ) -> FileId {
121+ let file_id = self . next_id ( ) ;
122+ self . files . push ( MockFileData :: from ( fixture) ) ;
123+ file_id
124+ }
125+
126+ pub fn add_file_fixture_with_position ( & mut self , mut fixture : FixtureEntry ) -> FilePosition {
127+ let ( offset, text) = extract_offset ( & fixture. text ) ;
128+ fixture. text = text;
129+ let file_id = self . next_id ( ) ;
130+ self . files . push ( MockFileData :: from ( fixture) ) ;
131+ FilePosition { file_id, offset }
132+ }
133+
60134 pub fn add_file ( & mut self , path : & str , text : & str ) -> FileId {
61- let file_id = FileId ( ( self . files . len ( ) + 1 ) as u32 ) ;
62- self . files . push ( ( path. to_string ( ) , text. to_string ( ) ) ) ;
135+ let file_id = self . next_id ( ) ;
136+ self . files . push ( MockFileData :: new ( path. to_string ( ) , text. to_string ( ) ) ) ;
63137 file_id
64138 }
65139 pub fn add_file_with_position ( & mut self , path : & str , text : & str ) -> FilePosition {
66140 let ( offset, text) = extract_offset ( text) ;
67- let file_id = FileId ( ( self . files . len ( ) + 1 ) as u32 ) ;
68- self . files . push ( ( path. to_string ( ) , text) ) ;
141+ let file_id = self . next_id ( ) ;
142+ self . files . push ( MockFileData :: new ( path. to_string ( ) , text) ) ;
69143 FilePosition { file_id, offset }
70144 }
71145 pub fn add_file_with_range ( & mut self , path : & str , text : & str ) -> FileRange {
72146 let ( range, text) = extract_range ( text) ;
73- let file_id = FileId ( ( self . files . len ( ) + 1 ) as u32 ) ;
74- self . files . push ( ( path. to_string ( ) , text) ) ;
147+ let file_id = self . next_id ( ) ;
148+ self . files . push ( MockFileData :: new ( path. to_string ( ) , text) ) ;
75149 FileRange { file_id, range }
76150 }
77151 pub fn id_of ( & self , path : & str ) -> FileId {
78152 let ( idx, _) = self
79153 . files
80154 . iter ( )
81155 . enumerate ( )
82- . find ( |( _, ( p , _text ) ) | path == p )
156+ . find ( |( _, data ) | path == data . path ( ) )
83157 . expect ( "no file in this mock" ) ;
84158 FileId ( idx as u32 + 1 )
85159 }
@@ -90,29 +164,32 @@ impl MockAnalysis {
90164 change. add_root ( source_root, true ) ;
91165 let mut crate_graph = CrateGraph :: default ( ) ;
92166 let mut root_crate = None ;
93- for ( i, ( path, contents) ) in self . files . into_iter ( ) . enumerate ( ) {
167+ for ( i, data) in self . files . into_iter ( ) . enumerate ( ) {
168+ let path = data. path ( ) ;
94169 assert ! ( path. starts_with( '/' ) ) ;
95170 let path = RelativePathBuf :: from_path ( & path[ 1 ..] ) . unwrap ( ) ;
171+ let cfg_options = data. cfg_options ( ) ;
96172 let file_id = FileId ( i as u32 + 1 ) ;
97- let cfg_options = CfgOptions :: default ( ) ;
173+ let edition = data. edition ( ) ;
174+ let env = data. env ( ) ;
98175 if path == "/lib.rs" || path == "/main.rs" {
99176 root_crate = Some ( crate_graph. add_crate_root (
100177 file_id,
101- Edition2018 ,
178+ edition ,
102179 None ,
103180 cfg_options,
104- Env :: default ( ) ,
181+ env ,
105182 Default :: default ( ) ,
106183 Default :: default ( ) ,
107184 ) ) ;
108185 } else if path. ends_with ( "/lib.rs" ) {
109186 let crate_name = path. parent ( ) . unwrap ( ) . file_name ( ) . unwrap ( ) ;
110187 let other_crate = crate_graph. add_crate_root (
111188 file_id,
112- Edition2018 ,
189+ edition ,
113190 Some ( CrateName :: new ( crate_name) . unwrap ( ) ) ,
114191 cfg_options,
115- Env :: default ( ) ,
192+ env ,
116193 Default :: default ( ) ,
117194 Default :: default ( ) ,
118195 ) ;
@@ -122,7 +199,7 @@ impl MockAnalysis {
122199 . unwrap ( ) ;
123200 }
124201 }
125- change. add_file ( source_root, file_id, path, Arc :: new ( contents ) ) ;
202+ change. add_file ( source_root, file_id, path, Arc :: new ( data . content ( ) . to_owned ( ) ) ) ;
126203 }
127204 change. set_crate_graph ( crate_graph) ;
128205 host. apply_change ( change) ;
@@ -131,6 +208,10 @@ impl MockAnalysis {
131208 pub fn analysis ( self ) -> Analysis {
132209 self . analysis_host ( ) . analysis ( )
133210 }
211+
212+ fn next_id ( & self ) -> FileId {
213+ FileId ( ( self . files . len ( ) + 1 ) as u32 )
214+ }
134215}
135216
136217/// Creates analysis from a multi-file fixture, returns positions marked with <|>.
0 commit comments