1
1
//! FIXME: write short doc here
2
2
3
+ use std:: str:: FromStr ;
3
4
use std:: sync:: Arc ;
4
5
5
6
use ra_cfg:: CfgOptions ;
6
7
use 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 } ;
8
9
9
10
use crate :: {
10
- Analysis , AnalysisChange , AnalysisHost , CrateGraph , Edition :: Edition2018 , FileId , FilePosition ,
11
- FileRange , SourceRootId ,
11
+ Analysis , AnalysisChange , AnalysisHost , CrateGraph , Edition , FileId , FilePosition , FileRange ,
12
+ SourceRootId ,
12
13
} ;
13
14
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
+
14
74
/// Mock analysis is used in test to bootstrap an AnalysisHost/Analysis
15
75
/// from a set of in-memory files.
16
76
#[ derive( Debug , Default ) ]
17
77
pub struct MockAnalysis {
18
- files : Vec < ( String , String ) > ,
78
+ files : Vec < MockFileData > ,
19
79
}
20
80
21
81
impl MockAnalysis {
@@ -35,7 +95,7 @@ impl MockAnalysis {
35
95
pub fn with_files ( fixture : & str ) -> MockAnalysis {
36
96
let mut res = MockAnalysis :: new ( ) ;
37
97
for entry in parse_fixture ( fixture) {
38
- res. add_file ( & entry. meta , & entry . text ) ;
98
+ res. add_file_fixture ( entry) ;
39
99
}
40
100
res
41
101
}
@@ -48,38 +108,52 @@ impl MockAnalysis {
48
108
for entry in parse_fixture ( fixture) {
49
109
if entry. text . contains ( CURSOR_MARKER ) {
50
110
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) ) ;
52
112
} else {
53
- res. add_file ( & entry. meta , & entry . text ) ;
113
+ res. add_file_fixture ( entry) ;
54
114
}
55
115
}
56
116
let position = position. expect ( "expected a marker (<|>)" ) ;
57
117
( res, position)
58
118
}
59
119
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
+
60
134
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 ( ) ) ) ;
63
137
file_id
64
138
}
65
139
pub fn add_file_with_position ( & mut self , path : & str , text : & str ) -> FilePosition {
66
140
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) ) ;
69
143
FilePosition { file_id, offset }
70
144
}
71
145
pub fn add_file_with_range ( & mut self , path : & str , text : & str ) -> FileRange {
72
146
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) ) ;
75
149
FileRange { file_id, range }
76
150
}
77
151
pub fn id_of ( & self , path : & str ) -> FileId {
78
152
let ( idx, _) = self
79
153
. files
80
154
. iter ( )
81
155
. enumerate ( )
82
- . find ( |( _, ( p , _text ) ) | path == p )
156
+ . find ( |( _, data ) | path == data . path ( ) )
83
157
. expect ( "no file in this mock" ) ;
84
158
FileId ( idx as u32 + 1 )
85
159
}
@@ -90,29 +164,32 @@ impl MockAnalysis {
90
164
change. add_root ( source_root, true ) ;
91
165
let mut crate_graph = CrateGraph :: default ( ) ;
92
166
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 ( ) ;
94
169
assert ! ( path. starts_with( '/' ) ) ;
95
170
let path = RelativePathBuf :: from_path ( & path[ 1 ..] ) . unwrap ( ) ;
171
+ let cfg_options = data. cfg_options ( ) ;
96
172
let file_id = FileId ( i as u32 + 1 ) ;
97
- let cfg_options = CfgOptions :: default ( ) ;
173
+ let edition = data. edition ( ) ;
174
+ let env = data. env ( ) ;
98
175
if path == "/lib.rs" || path == "/main.rs" {
99
176
root_crate = Some ( crate_graph. add_crate_root (
100
177
file_id,
101
- Edition2018 ,
178
+ edition ,
102
179
None ,
103
180
cfg_options,
104
- Env :: default ( ) ,
181
+ env ,
105
182
Default :: default ( ) ,
106
183
Default :: default ( ) ,
107
184
) ) ;
108
185
} else if path. ends_with ( "/lib.rs" ) {
109
186
let crate_name = path. parent ( ) . unwrap ( ) . file_name ( ) . unwrap ( ) ;
110
187
let other_crate = crate_graph. add_crate_root (
111
188
file_id,
112
- Edition2018 ,
189
+ edition ,
113
190
Some ( CrateName :: new ( crate_name) . unwrap ( ) ) ,
114
191
cfg_options,
115
- Env :: default ( ) ,
192
+ env ,
116
193
Default :: default ( ) ,
117
194
Default :: default ( ) ,
118
195
) ;
@@ -122,7 +199,7 @@ impl MockAnalysis {
122
199
. unwrap ( ) ;
123
200
}
124
201
}
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 ( ) ) ) ;
126
203
}
127
204
change. set_crate_graph ( crate_graph) ;
128
205
host. apply_change ( change) ;
@@ -131,6 +208,10 @@ impl MockAnalysis {
131
208
pub fn analysis ( self ) -> Analysis {
132
209
self . analysis_host ( ) . analysis ( )
133
210
}
211
+
212
+ fn next_id ( & self ) -> FileId {
213
+ FileId ( ( self . files . len ( ) + 1 ) as u32 )
214
+ }
134
215
}
135
216
136
217
/// Creates analysis from a multi-file fixture, returns positions marked with <|>.
0 commit comments