diff options
Diffstat (limited to 'crates/ra_hir/src/nameres/crate_def_map/tests.rs')
-rw-r--r-- | crates/ra_hir/src/nameres/crate_def_map/tests.rs | 265 |
1 files changed, 265 insertions, 0 deletions
diff --git a/crates/ra_hir/src/nameres/crate_def_map/tests.rs b/crates/ra_hir/src/nameres/crate_def_map/tests.rs new file mode 100644 index 000000000..a56dbaf90 --- /dev/null +++ b/crates/ra_hir/src/nameres/crate_def_map/tests.rs | |||
@@ -0,0 +1,265 @@ | |||
1 | use std::sync::Arc; | ||
2 | |||
3 | use ra_db::SourceDatabase; | ||
4 | use test_utils::covers; | ||
5 | use insta::assert_snapshot_matches; | ||
6 | |||
7 | use crate::{Crate, mock::{MockDatabase, CrateGraphFixture}, nameres::Resolution}; | ||
8 | |||
9 | use super::*; | ||
10 | |||
11 | fn compute_crate_def_map(fixture: &str, graph: Option<CrateGraphFixture>) -> Arc<CrateDefMap> { | ||
12 | let mut db = MockDatabase::with_files(fixture); | ||
13 | if let Some(graph) = graph { | ||
14 | db.set_crate_graph_from_fixture(graph); | ||
15 | } | ||
16 | let crate_id = db.crate_graph().iter().next().unwrap(); | ||
17 | let krate = Crate { crate_id }; | ||
18 | collector::crate_def_map_query(&db, krate) | ||
19 | } | ||
20 | |||
21 | fn render_crate_def_map(map: &CrateDefMap) -> String { | ||
22 | let mut buf = String::new(); | ||
23 | go(&mut buf, map, "\ncrate", map.root); | ||
24 | return buf; | ||
25 | |||
26 | fn go(buf: &mut String, map: &CrateDefMap, path: &str, module: ModuleId) { | ||
27 | *buf += path; | ||
28 | *buf += "\n"; | ||
29 | for (name, res) in map.modules[module].scope.items.iter() { | ||
30 | *buf += &format!("{}: {}\n", name, dump_resolution(res)) | ||
31 | } | ||
32 | for (name, child) in map.modules[module].children.iter() { | ||
33 | let path = path.to_string() + &format!("::{}", name); | ||
34 | go(buf, map, &path, *child); | ||
35 | } | ||
36 | } | ||
37 | |||
38 | fn dump_resolution(resolution: &Resolution) -> &'static str { | ||
39 | match (resolution.def.types.is_some(), resolution.def.values.is_some()) { | ||
40 | (true, true) => "t v", | ||
41 | (true, false) => "t", | ||
42 | (false, true) => "v", | ||
43 | (false, false) => "_", | ||
44 | } | ||
45 | } | ||
46 | } | ||
47 | |||
48 | fn def_map(fixtute: &str) -> String { | ||
49 | let dm = compute_crate_def_map(fixtute, None); | ||
50 | render_crate_def_map(&dm) | ||
51 | } | ||
52 | |||
53 | fn def_map_with_crate_graph(fixtute: &str, graph: CrateGraphFixture) -> String { | ||
54 | let dm = compute_crate_def_map(fixtute, Some(graph)); | ||
55 | render_crate_def_map(&dm) | ||
56 | } | ||
57 | |||
58 | #[test] | ||
59 | fn crate_def_map_smoke_test() { | ||
60 | let map = def_map( | ||
61 | " | ||
62 | //- /lib.rs | ||
63 | mod foo; | ||
64 | struct S; | ||
65 | |||
66 | //- /foo/mod.rs | ||
67 | pub mod bar; | ||
68 | fn f() {} | ||
69 | |||
70 | //- /foo/bar.rs | ||
71 | pub struct Baz; | ||
72 | enum E { V } | ||
73 | ", | ||
74 | ); | ||
75 | assert_snapshot_matches!(map, @r###" | ||
76 | crate | ||
77 | S: t v | ||
78 | |||
79 | crate::foo | ||
80 | f: v | ||
81 | |||
82 | crate::foo::bar | ||
83 | Baz: t v | ||
84 | E: t | ||
85 | "### | ||
86 | ) | ||
87 | } | ||
88 | |||
89 | #[test] | ||
90 | fn macro_rules_are_globally_visible() { | ||
91 | let map = def_map( | ||
92 | " | ||
93 | //- /lib.rs | ||
94 | macro_rules! structs { | ||
95 | ($($i:ident),*) => { | ||
96 | $(struct $i { field: u32 } )* | ||
97 | } | ||
98 | } | ||
99 | structs!(Foo); | ||
100 | mod nested; | ||
101 | |||
102 | //- /nested.rs | ||
103 | structs!(Bar, Baz); | ||
104 | ", | ||
105 | ); | ||
106 | assert_snapshot_matches!(map, @r###" | ||
107 | crate | ||
108 | Foo: t v | ||
109 | |||
110 | crate::nested | ||
111 | Bar: t v | ||
112 | Baz: t v | ||
113 | "###); | ||
114 | } | ||
115 | |||
116 | #[test] | ||
117 | fn macro_rules_can_define_modules() { | ||
118 | let map = def_map( | ||
119 | " | ||
120 | //- /lib.rs | ||
121 | macro_rules! m { | ||
122 | ($name:ident) => { mod $name; } | ||
123 | } | ||
124 | m!(n1); | ||
125 | |||
126 | //- /n1.rs | ||
127 | m!(n2) | ||
128 | //- /n1/n2.rs | ||
129 | struct X; | ||
130 | ", | ||
131 | ); | ||
132 | assert_snapshot_matches!(map, @r###" | ||
133 | crate | ||
134 | |||
135 | crate::n1 | ||
136 | |||
137 | crate::n1::n2 | ||
138 | X: t v | ||
139 | "###); | ||
140 | } | ||
141 | |||
142 | #[test] | ||
143 | fn macro_rules_from_other_crates_are_visible() { | ||
144 | let map = def_map_with_crate_graph( | ||
145 | " | ||
146 | //- /main.rs | ||
147 | foo::structs!(Foo, Bar) | ||
148 | mod bar; | ||
149 | |||
150 | //- /bar.rs | ||
151 | use crate::*; | ||
152 | |||
153 | //- /lib.rs | ||
154 | #[macro_export] | ||
155 | macro_rules! structs { | ||
156 | ($($i:ident),*) => { | ||
157 | $(struct $i { field: u32 } )* | ||
158 | } | ||
159 | } | ||
160 | ", | ||
161 | crate_graph! { | ||
162 | "main": ("/main.rs", ["foo"]), | ||
163 | "foo": ("/lib.rs", []), | ||
164 | }, | ||
165 | ); | ||
166 | assert_snapshot_matches!(map, @r###" | ||
167 | crate | ||
168 | Foo: t v | ||
169 | Bar: t v | ||
170 | |||
171 | crate::bar | ||
172 | Foo: t v | ||
173 | Bar: t v | ||
174 | "###); | ||
175 | } | ||
176 | |||
177 | #[test] | ||
178 | fn std_prelude() { | ||
179 | covers!(std_prelude); | ||
180 | let map = def_map_with_crate_graph( | ||
181 | " | ||
182 | //- /main.rs | ||
183 | use Foo::*; | ||
184 | |||
185 | //- /lib.rs | ||
186 | mod prelude; | ||
187 | #[prelude_import] | ||
188 | use prelude::*; | ||
189 | |||
190 | //- /prelude.rs | ||
191 | pub enum Foo { Bar, Baz }; | ||
192 | ", | ||
193 | crate_graph! { | ||
194 | "main": ("/main.rs", ["test_crate"]), | ||
195 | "test_crate": ("/lib.rs", []), | ||
196 | }, | ||
197 | ); | ||
198 | assert_snapshot_matches!(map, @r###" | ||
199 | crate | ||
200 | Bar: t v | ||
201 | Baz: t v | ||
202 | "###); | ||
203 | } | ||
204 | |||
205 | #[test] | ||
206 | fn glob_across_crates() { | ||
207 | covers!(glob_across_crates); | ||
208 | let map = def_map_with_crate_graph( | ||
209 | " | ||
210 | //- /main.rs | ||
211 | use test_crate::*; | ||
212 | |||
213 | //- /lib.rs | ||
214 | pub struct Baz; | ||
215 | ", | ||
216 | crate_graph! { | ||
217 | "main": ("/main.rs", ["test_crate"]), | ||
218 | "test_crate": ("/lib.rs", []), | ||
219 | }, | ||
220 | ); | ||
221 | assert_snapshot_matches!(map, @r###" | ||
222 | crate | ||
223 | Baz: t v | ||
224 | "### | ||
225 | ); | ||
226 | } | ||
227 | |||
228 | #[test] | ||
229 | fn item_map_enum_importing() { | ||
230 | covers!(item_map_enum_importing); | ||
231 | let map = def_map( | ||
232 | " | ||
233 | //- /lib.rs | ||
234 | enum E { V } | ||
235 | use self::E::V; | ||
236 | ", | ||
237 | ); | ||
238 | assert_snapshot_matches!(map, @r###" | ||
239 | crate | ||
240 | V: t v | ||
241 | E: t | ||
242 | "### | ||
243 | ); | ||
244 | } | ||
245 | |||
246 | #[test] | ||
247 | fn glob_enum() { | ||
248 | covers!(glob_enum); | ||
249 | let map = def_map( | ||
250 | " | ||
251 | //- /lib.rs | ||
252 | enum Foo { | ||
253 | Bar, Baz | ||
254 | } | ||
255 | use self::Foo::*; | ||
256 | ", | ||
257 | ); | ||
258 | assert_snapshot_matches!(map, @r###" | ||
259 | crate | ||
260 | Foo: t | ||
261 | Bar: t v | ||
262 | Baz: t v | ||
263 | "### | ||
264 | ); | ||
265 | } | ||