]> git.proxmox.com Git - rustc.git/blame - src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/incremental.rs
New upstream version 1.76.0+dfsg1
[rustc.git] / src / tools / rust-analyzer / crates / hir-def / src / nameres / tests / incremental.rs
CommitLineData
4b012472 1use base_db::{SourceDatabase, SourceDatabaseExt};
fe692bf9 2use triomphe::Arc;
064997fb 3
4b012472
FG
4use crate::{
5 db::DefDatabase,
6 nameres::tests::{TestDB, WithFixture},
7 AdtId, ModuleDefId,
8};
064997fb
FG
9
10fn check_def_map_is_not_recomputed(ra_fixture_initial: &str, ra_fixture_change: &str) {
11 let (mut db, pos) = TestDB::with_position(ra_fixture_initial);
4b012472
FG
12 let krate = {
13 let crate_graph = db.crate_graph();
14 // Some of these tests use minicore/proc-macros which will be injected as the first crate
15 crate_graph.iter().last().unwrap()
16 };
064997fb
FG
17 {
18 let events = db.log_executed(|| {
19 db.crate_def_map(krate);
20 });
9c376795 21 assert!(format!("{events:?}").contains("crate_def_map"), "{events:#?}")
064997fb 22 }
fe692bf9 23 db.set_file_text(pos.file_id, Arc::from(ra_fixture_change));
064997fb
FG
24
25 {
26 let events = db.log_executed(|| {
27 db.crate_def_map(krate);
28 });
9c376795 29 assert!(!format!("{events:?}").contains("crate_def_map"), "{events:#?}")
064997fb
FG
30 }
31}
32
33#[test]
34fn typing_inside_a_function_should_not_invalidate_def_map() {
35 check_def_map_is_not_recomputed(
36 r"
4b012472
FG
37//- /lib.rs
38mod foo;$0
064997fb 39
4b012472 40use crate::foo::bar::Baz;
064997fb 41
4b012472
FG
42enum E { A, B }
43use E::*;
064997fb 44
4b012472
FG
45fn foo() -> i32 {
46 1 + 1
47}
064997fb 48
4b012472
FG
49#[cfg(never)]
50fn no() {}
51//- /foo/mod.rs
52pub mod bar;
064997fb 53
4b012472
FG
54//- /foo/bar.rs
55pub struct Baz;
56",
064997fb 57 r"
4b012472 58mod foo;
064997fb 59
4b012472 60use crate::foo::bar::Baz;
064997fb 61
4b012472
FG
62enum E { A, B }
63use E::*;
064997fb 64
4b012472 65fn foo() -> i32 { 92 }
064997fb 66
4b012472
FG
67#[cfg(never)]
68fn no() {}
69",
064997fb
FG
70 );
71}
72
73#[test]
74fn typing_inside_a_macro_should_not_invalidate_def_map() {
4b012472
FG
75 check_def_map_is_not_recomputed(
76 r"
77//- /lib.rs
78macro_rules! m {
79 ($ident:ident) => {
80 fn f() {
81 $ident + $ident;
82 };
83 }
84}
85mod foo;
86
87//- /foo/mod.rs
88pub mod bar;
89
90//- /foo/bar.rs
91$0
92m!(X);
93
94pub struct S {}
95",
064997fb 96 r"
4b012472
FG
97m!(Y);
98
99pub struct S {}
100",
064997fb 101 );
4b012472
FG
102}
103
104#[test]
105fn typing_inside_an_attribute_should_not_invalidate_def_map() {
106 check_def_map_is_not_recomputed(
107 r"
108//- proc_macros: identity
109//- /lib.rs
110mod foo;
111
112//- /foo/mod.rs
113pub mod bar;
114
115//- /foo/bar.rs
116$0
117#[proc_macros::identity]
118fn f() {}
119",
120 r"
121#[proc_macros::identity]
122fn f() { foo }
123",
124 );
125}
126
127#[test]
128fn typing_inside_an_attribute_arg_should_not_invalidate_def_map() {
129 check_def_map_is_not_recomputed(
130 r"
131//- proc_macros: identity
132//- /lib.rs
133mod foo;
134
135//- /foo/mod.rs
136pub mod bar;
137
138//- /foo/bar.rs
139$0
140#[proc_macros::identity]
141fn f() {}
142",
143 r"
144#[proc_macros::identity(foo)]
145fn f() {}
146",
147 );
148}
149#[test]
150fn typing_inside_macro_heavy_file_should_not_invalidate_def_map() {
151 check_def_map_is_not_recomputed(
152 r"
153//- proc_macros: identity, derive_identity
154//- /lib.rs
155macro_rules! m {
156 ($ident:ident) => {
157 fn fm() {
158 $ident + $ident;
159 };
064997fb 160 }
4b012472
FG
161}
162mod foo;
064997fb 163
4b012472
FG
164//- /foo/mod.rs
165pub mod bar;
166
167//- /foo/bar.rs
168$0
169fn f() {}
170
171m!(X);
172macro_rules! m2 {
173 ($ident:ident) => {
174 fn f2() {
175 $ident + $ident;
176 };
064997fb
FG
177 }
178}
4b012472
FG
179m2!(X);
180
181#[proc_macros::identity]
182#[derive(proc_macros::DeriveIdentity)]
183pub struct S {}
184",
185 r"
186fn f() {0}
187
188m!(X);
189macro_rules! m2 {
190 ($ident:ident) => {
191 fn f2() {
192 $ident + $ident;
193 };
194 }
195}
196m2!(X);
197
198#[proc_macros::identity]
199#[derive(proc_macros::DeriveIdentity)]
200pub struct S {}
201",
202 );
203}
204
205#[test]
206fn typing_inside_a_derive_should_not_invalidate_def_map() {
207 check_def_map_is_not_recomputed(
208 r"
209//- proc_macros: derive_identity
210//- minicore:derive
211//- /lib.rs
212mod foo;
213
214//- /foo/mod.rs
215pub mod bar;
216
217//- /foo/bar.rs
218$0
219#[derive(proc_macros::DeriveIdentity)]
220#[allow()]
221struct S;
222",
223 r"
224#[derive(proc_macros::DeriveIdentity)]
225#[allow(dead_code)]
226struct S;
227",
228 );
229}
064997fb
FG
230
231#[test]
fe692bf9 232fn typing_inside_a_function_should_not_invalidate_item_expansions() {
064997fb
FG
233 let (mut db, pos) = TestDB::with_position(
234 r#"
235//- /lib.rs
236macro_rules! m {
237 ($ident:ident) => {
238 fn $ident() { };
239 }
240}
241mod foo;
242
243//- /foo/mod.rs
244pub mod bar;
245
246//- /foo/bar.rs
247m!(X);
248fn quux() { 1$0 }
249m!(Y);
250m!(Z);
251"#,
252 );
253 let krate = db.test_crate();
254 {
255 let events = db.log_executed(|| {
256 let crate_def_map = db.crate_def_map(krate);
257 let (_, module_data) = crate_def_map.modules.iter().last().unwrap();
258 assert_eq!(module_data.scope.resolutions().count(), 4);
259 });
260 let n_recalculated_item_trees = events.iter().filter(|it| it.contains("item_tree")).count();
261 assert_eq!(n_recalculated_item_trees, 6);
262 let n_reparsed_macros =
fe692bf9 263 events.iter().filter(|it| it.contains("parse_macro_expansion(")).count();
064997fb
FG
264 assert_eq!(n_reparsed_macros, 3);
265 }
266
267 let new_text = r#"
268m!(X);
269fn quux() { 92 }
270m!(Y);
271m!(Z);
272"#;
fe692bf9 273 db.set_file_text(pos.file_id, Arc::from(new_text));
064997fb
FG
274
275 {
276 let events = db.log_executed(|| {
277 let crate_def_map = db.crate_def_map(krate);
278 let (_, module_data) = crate_def_map.modules.iter().last().unwrap();
279 assert_eq!(module_data.scope.resolutions().count(), 4);
280 });
281 let n_recalculated_item_trees = events.iter().filter(|it| it.contains("item_tree")).count();
282 assert_eq!(n_recalculated_item_trees, 1);
283 let n_reparsed_macros =
fe692bf9 284 events.iter().filter(|it| it.contains("parse_macro_expansion(")).count();
064997fb
FG
285 assert_eq!(n_reparsed_macros, 0);
286 }
287}
288
289#[test]
290fn item_tree_prevents_reparsing() {
291 // The `ItemTree` is used by both name resolution and the various queries in `adt.rs` and
292 // `data.rs`. After computing the `ItemTree` and deleting the parse tree, we should be able to
293 // run those other queries without triggering a reparse.
294
295 let (db, pos) = TestDB::with_position(
296 r#"
297pub struct S;
298pub union U {}
299pub enum E {
300 Variant,
301}
302pub fn f(_: S) { $0 }
303pub trait Tr {}
304impl Tr for () {}
305pub const C: u8 = 0;
306pub static ST: u8 = 0;
307pub type Ty = ();
308"#,
309 );
310 let krate = db.test_crate();
311 {
312 let events = db.log_executed(|| {
313 db.file_item_tree(pos.file_id.into());
314 });
315 let n_calculated_item_trees = events.iter().filter(|it| it.contains("item_tree")).count();
316 assert_eq!(n_calculated_item_trees, 1);
317 let n_parsed_files = events.iter().filter(|it| it.contains("parse(")).count();
318 assert_eq!(n_parsed_files, 1);
319 }
320
321 // Delete the parse tree.
322 base_db::ParseQuery.in_db(&db).purge();
323
324 {
325 let events = db.log_executed(|| {
326 let crate_def_map = db.crate_def_map(krate);
327 let (_, module_data) = crate_def_map.modules.iter().last().unwrap();
328 assert_eq!(module_data.scope.resolutions().count(), 8);
329 assert_eq!(module_data.scope.impls().count(), 1);
330
331 for imp in module_data.scope.impls() {
332 db.impl_data(imp);
333 }
334
335 for (_, res) in module_data.scope.resolutions() {
781aab86 336 match res.values.map(|(a, _, _)| a).or(res.types.map(|(a, _, _)| a)).unwrap() {
add651ee 337 ModuleDefId::FunctionId(f) => _ = db.function_data(f),
064997fb 338 ModuleDefId::AdtId(adt) => match adt {
add651ee
FG
339 AdtId::StructId(it) => _ = db.struct_data(it),
340 AdtId::UnionId(it) => _ = db.union_data(it),
341 AdtId::EnumId(it) => _ = db.enum_data(it),
064997fb 342 },
add651ee
FG
343 ModuleDefId::ConstId(it) => _ = db.const_data(it),
344 ModuleDefId::StaticId(it) => _ = db.static_data(it),
345 ModuleDefId::TraitId(it) => _ = db.trait_data(it),
346 ModuleDefId::TraitAliasId(it) => _ = db.trait_alias_data(it),
347 ModuleDefId::TypeAliasId(it) => _ = db.type_alias_data(it),
064997fb
FG
348 ModuleDefId::EnumVariantId(_)
349 | ModuleDefId::ModuleId(_)
350 | ModuleDefId::MacroId(_)
351 | ModuleDefId::BuiltinType(_) => unreachable!(),
352 }
353 }
354 });
355 let n_reparsed_files = events.iter().filter(|it| it.contains("parse(")).count();
356 assert_eq!(n_reparsed_files, 0);
357 }
358}