|
1 | 1 | use std::sync::Arc;
|
2 | 2 |
|
3 |
| -use base_db::SourceDatabaseExt; |
| 3 | +use base_db::{salsa::SweepStrategy, SourceDatabaseExt}; |
| 4 | + |
| 5 | +use crate::{AdtId, ModuleDefId}; |
4 | 6 |
|
5 | 7 | use super::*;
|
6 | 8 |
|
@@ -163,3 +165,73 @@ m!(Z);
|
163 | 165 | assert_eq!(n_reparsed_macros, 0);
|
164 | 166 | }
|
165 | 167 | }
|
| 168 | + |
| 169 | +#[test] |
| 170 | +fn item_tree_prevents_reparsing() { |
| 171 | + // The `ItemTree` is used by both name resolution and the various queries in `adt.rs` and |
| 172 | + // `data.rs`. After computing the `ItemTree` and deleting the parse tree, we should be able to |
| 173 | + // run those other queries without triggering a reparse. |
| 174 | + |
| 175 | + let (db, pos) = TestDB::with_position( |
| 176 | + r#" |
| 177 | +pub struct S; |
| 178 | +pub union U {} |
| 179 | +pub enum E { |
| 180 | + Variant, |
| 181 | +} |
| 182 | +pub fn f(_: S) { $0 } |
| 183 | +pub trait Tr {} |
| 184 | +impl Tr for () {} |
| 185 | +pub const C: u8 = 0; |
| 186 | +pub static ST: u8 = 0; |
| 187 | +pub type Ty = (); |
| 188 | +"#, |
| 189 | + ); |
| 190 | + let krate = db.test_crate(); |
| 191 | + { |
| 192 | + let events = db.log_executed(|| { |
| 193 | + db.file_item_tree(pos.file_id.into()); |
| 194 | + }); |
| 195 | + let n_calculated_item_trees = events.iter().filter(|it| it.contains("item_tree")).count(); |
| 196 | + assert_eq!(n_calculated_item_trees, 1); |
| 197 | + let n_parsed_files = events.iter().filter(|it| it.contains("parse(")).count(); |
| 198 | + assert_eq!(n_parsed_files, 1); |
| 199 | + } |
| 200 | + |
| 201 | + // Delete the parse tree. |
| 202 | + let sweep = SweepStrategy::default().discard_values().sweep_all_revisions(); |
| 203 | + base_db::ParseQuery.in_db(&db).sweep(sweep); |
| 204 | + |
| 205 | + { |
| 206 | + let events = db.log_executed(|| { |
| 207 | + let crate_def_map = db.crate_def_map(krate); |
| 208 | + let (_, module_data) = crate_def_map.modules.iter().last().unwrap(); |
| 209 | + assert_eq!(module_data.scope.resolutions().count(), 8); |
| 210 | + assert_eq!(module_data.scope.impls().count(), 1); |
| 211 | + |
| 212 | + for imp in module_data.scope.impls() { |
| 213 | + db.impl_data(imp); |
| 214 | + } |
| 215 | + |
| 216 | + for (_, res) in module_data.scope.resolutions() { |
| 217 | + match res.values.or(res.types).unwrap().0 { |
| 218 | + ModuleDefId::FunctionId(f) => drop(db.function_data(f)), |
| 219 | + ModuleDefId::AdtId(adt) => match adt { |
| 220 | + AdtId::StructId(it) => drop(db.struct_data(it)), |
| 221 | + AdtId::UnionId(it) => drop(db.union_data(it)), |
| 222 | + AdtId::EnumId(it) => drop(db.enum_data(it)), |
| 223 | + }, |
| 224 | + ModuleDefId::ConstId(it) => drop(db.const_data(it)), |
| 225 | + ModuleDefId::StaticId(it) => drop(db.static_data(it)), |
| 226 | + ModuleDefId::TraitId(it) => drop(db.trait_data(it)), |
| 227 | + ModuleDefId::TypeAliasId(it) => drop(db.type_alias_data(it)), |
| 228 | + ModuleDefId::EnumVariantId(_) |
| 229 | + | ModuleDefId::ModuleId(_) |
| 230 | + | ModuleDefId::BuiltinType(_) => unreachable!(), |
| 231 | + } |
| 232 | + } |
| 233 | + }); |
| 234 | + let n_reparsed_files = events.iter().filter(|it| it.contains("parse(")).count(); |
| 235 | + assert_eq!(n_reparsed_files, 0); |
| 236 | + } |
| 237 | +} |
0 commit comments