@@ -6,6 +6,7 @@ use ra_db::{
6
6
} ;
7
7
use relative_path:: RelativePathBuf ;
8
8
use test_utils:: { parse_fixture, CURSOR_MARKER , extract_offset} ;
9
+ use rustc_hash:: FxHashMap ;
9
10
10
11
use crate :: { db, HirInterner } ;
11
12
@@ -21,82 +22,107 @@ pub struct MockDatabase {
21
22
events : Mutex < Option < Vec < salsa:: Event < MockDatabase > > > > ,
22
23
runtime : salsa:: Runtime < MockDatabase > ,
23
24
interner : Arc < HirInterner > ,
24
- file_counter : u32 ,
25
+ files : FxHashMap < String , FileId > ,
25
26
}
26
27
27
28
impl panic:: RefUnwindSafe for MockDatabase { }
28
29
29
30
impl MockDatabase {
30
- pub fn with_files ( fixture : & str ) -> ( MockDatabase , SourceRoot ) {
31
- let ( db, source_root , position) = MockDatabase :: from_fixture ( fixture) ;
31
+ pub fn with_files ( fixture : & str ) -> MockDatabase {
32
+ let ( db, position) = MockDatabase :: from_fixture ( fixture) ;
32
33
assert ! ( position. is_none( ) ) ;
33
- ( db , source_root )
34
+ db
34
35
}
35
36
36
37
pub fn with_single_file ( text : & str ) -> ( MockDatabase , SourceRoot , FileId ) {
37
38
let mut db = MockDatabase :: default ( ) ;
38
39
let mut source_root = SourceRoot :: default ( ) ;
39
- let file_id = db. add_file ( WORKSPACE , & mut source_root, "/main.rs" , text) ;
40
+ let file_id = db. add_file ( WORKSPACE , "/" , & mut source_root, "/main.rs" , text) ;
40
41
db. set_source_root ( WORKSPACE , Arc :: new ( source_root. clone ( ) ) ) ;
41
42
( db, source_root, file_id)
42
43
}
43
44
44
45
pub fn with_position ( fixture : & str ) -> ( MockDatabase , FilePosition ) {
45
- let ( db, _ , position) = MockDatabase :: from_fixture ( fixture) ;
46
+ let ( db, position) = MockDatabase :: from_fixture ( fixture) ;
46
47
let position = position. expect ( "expected a marker ( <|> )" ) ;
47
48
( db, position)
48
49
}
49
50
50
- fn from_fixture ( fixture : & str ) -> ( MockDatabase , SourceRoot , Option < FilePosition > ) {
51
+ pub fn file_id_of ( & self , path : & str ) -> FileId {
52
+ match self . files . get ( path) {
53
+ Some ( it) => * it,
54
+ None => panic ! ( "unknown file: {:?}\n existing files:\n {:#?}" , path, self . files) ,
55
+ }
56
+ }
57
+
58
+ fn from_fixture ( fixture : & str ) -> ( MockDatabase , Option < FilePosition > ) {
51
59
let mut db = MockDatabase :: default ( ) ;
52
60
53
- let ( source_root , pos) = db. add_fixture ( WORKSPACE , fixture) ;
61
+ let pos = db. add_fixture ( fixture) ;
54
62
55
- ( db, source_root , pos)
63
+ ( db, pos)
56
64
}
57
65
58
- pub fn add_fixture (
59
- & mut self ,
60
- source_root_id : SourceRootId ,
61
- fixture : & str ,
62
- ) -> ( SourceRoot , Option < FilePosition > ) {
66
+ fn add_fixture ( & mut self , fixture : & str ) -> Option < FilePosition > {
63
67
let mut position = None ;
64
68
let mut source_root = SourceRoot :: default ( ) ;
69
+ let mut source_root_id = WORKSPACE ;
70
+ let mut source_root_prefix = "/" . to_string ( ) ;
65
71
for entry in parse_fixture ( fixture) {
72
+ if entry. meta . starts_with ( "root" ) {
73
+ self . set_source_root ( source_root_id, Arc :: new ( source_root) ) ;
74
+ source_root = SourceRoot :: default ( ) ;
75
+
76
+ source_root_id = SourceRootId ( source_root_id. 0 + 1 ) ;
77
+ source_root_prefix = entry. meta [ "root" . len ( ) ..] . trim ( ) . to_string ( ) ;
78
+ continue ;
79
+ }
66
80
if entry. text . contains ( CURSOR_MARKER ) {
67
81
assert ! ( position. is_none( ) , "only one marker (<|>) per fixture is allowed" ) ;
68
82
position = Some ( self . add_file_with_position (
69
83
source_root_id,
84
+ & source_root_prefix,
70
85
& mut source_root,
71
86
& entry. meta ,
72
87
& entry. text ,
73
88
) ) ;
74
89
} else {
75
- self . add_file ( source_root_id, & mut source_root, & entry. meta , & entry. text ) ;
90
+ self . add_file (
91
+ source_root_id,
92
+ & source_root_prefix,
93
+ & mut source_root,
94
+ & entry. meta ,
95
+ & entry. text ,
96
+ ) ;
76
97
}
77
98
}
78
- self . set_source_root ( source_root_id, Arc :: new ( source_root. clone ( ) ) ) ;
79
- ( source_root , position)
99
+ self . set_source_root ( source_root_id, Arc :: new ( source_root) ) ;
100
+ position
80
101
}
81
102
82
103
fn add_file (
83
104
& mut self ,
84
105
source_root_id : SourceRootId ,
106
+ source_root_prefix : & str ,
85
107
source_root : & mut SourceRoot ,
86
108
path : & str ,
87
109
text : & str ,
88
110
) -> FileId {
89
- assert ! ( path. starts_with( '/' ) ) ;
90
- let is_crate_root = path == "/lib.rs" || path == "/main.rs" ;
111
+ assert ! ( source_root_prefix. starts_with( '/' ) ) ;
112
+ assert ! ( source_root_prefix. ends_with( '/' ) ) ;
113
+ assert ! ( path. starts_with( source_root_prefix) ) ;
114
+ let rel_path = RelativePathBuf :: from_path ( & path[ source_root_prefix. len ( ) ..] ) . unwrap ( ) ;
115
+
116
+ let is_crate_root = rel_path == "lib.rs" || rel_path == "/main.rs" ;
91
117
92
- let path = RelativePathBuf :: from_path ( & path [ 1 .. ] ) . unwrap ( ) ;
93
- let file_id = FileId ( self . file_counter ) ;
94
- self . file_counter += 1 ;
118
+ let file_id = FileId ( self . files . len ( ) as u32 ) ;
119
+ let prev = self . files . insert ( path . to_string ( ) , file_id ) ;
120
+ assert ! ( prev . is_none ( ) , "duplicate files in the text fixture" ) ;
95
121
let text = Arc :: new ( text. to_string ( ) ) ;
96
122
self . set_file_text ( file_id, text) ;
97
- self . set_file_relative_path ( file_id, path . clone ( ) ) ;
123
+ self . set_file_relative_path ( file_id, rel_path . clone ( ) ) ;
98
124
self . set_file_source_root ( file_id, source_root_id) ;
99
- source_root. files . insert ( path , file_id) ;
125
+ source_root. files . insert ( rel_path , file_id) ;
100
126
101
127
if is_crate_root {
102
128
let mut crate_graph = CrateGraph :: default ( ) ;
@@ -109,12 +135,13 @@ impl MockDatabase {
109
135
fn add_file_with_position (
110
136
& mut self ,
111
137
source_root_id : SourceRootId ,
138
+ source_root_prefix : & str ,
112
139
source_root : & mut SourceRoot ,
113
140
path : & str ,
114
141
text : & str ,
115
142
) -> FilePosition {
116
143
let ( offset, text) = extract_offset ( text) ;
117
- let file_id = self . add_file ( source_root_id, source_root, path, & text) ;
144
+ let file_id = self . add_file ( source_root_id, source_root_prefix , source_root, path, & text) ;
118
145
FilePosition { file_id, offset }
119
146
}
120
147
}
@@ -138,7 +165,7 @@ impl Default for MockDatabase {
138
165
events : Default :: default ( ) ,
139
166
runtime : salsa:: Runtime :: default ( ) ,
140
167
interner : Default :: default ( ) ,
141
- file_counter : 0 ,
168
+ files : FxHashMap :: default ( ) ,
142
169
} ;
143
170
db. set_crate_graph ( Default :: default ( ) ) ;
144
171
db
@@ -151,7 +178,8 @@ impl salsa::ParallelDatabase for MockDatabase {
151
178
events : Default :: default ( ) ,
152
179
runtime : self . runtime . snapshot ( self ) ,
153
180
interner : Arc :: clone ( & self . interner ) ,
154
- file_counter : self . file_counter ,
181
+ // only the root database can be used to get file_id by path.
182
+ files : FxHashMap :: default ( ) ,
155
183
} )
156
184
}
157
185
}
0 commit comments