use std::collections::HashSet;
use cairo_lang_defs::db::{DefsGroup, defs_group_input};
use cairo_lang_defs::ids::ModuleId;
use cairo_lang_filesystem::db::{FilesGroup, files_group_input};
use cairo_lang_semantic::db::{SemanticGroup, semantic_group_input};
use cairo_lang_utils::ordered_hash_map::OrderedHashMap;
use lsp_types::Url;
use salsa::Setter;
use crate::lang::db::AnalysisDatabase;
use crate::lang::lsp::LsProtoGroup;
use crate::lang::proc_macros::db::ProcMacroGroup;
#[tracing::instrument(skip_all)]
pub fn migrate_to_fresh_database(
old_db: &AnalysisDatabase,
open_files: &HashSet<Url>,
) -> AnalysisDatabase {
let mut new_db = AnalysisDatabase::new();
migrate_default_plugins(&mut new_db, old_db);
migrate_proc_macro_state(&mut new_db, old_db);
migrate_file_overrides(&mut new_db, old_db, open_files);
migrate_crate_model_inputs(&mut new_db, old_db);
new_db
}
fn migrate_default_plugins(new_db: &mut AnalysisDatabase, old_db: &AnalysisDatabase) {
defs_group_input(new_db).set_default_macro_plugins(new_db).to(Some(
old_db.default_macro_plugins().iter().map(|&id| id.long(old_db).clone()).collect(),
));
defs_group_input(new_db).set_default_inline_macro_plugins(new_db).to(Some(
old_db
.default_inline_macro_plugins()
.iter()
.map(|(name, &id)| (name.clone(), id.long(old_db).clone()))
.collect(),
));
semantic_group_input(new_db).set_default_analyzer_plugins(new_db).to(Some(
old_db.default_analyzer_plugins().iter().map(|&id| id.long(old_db).clone()).collect(),
));
}
fn migrate_proc_macro_state(new_db: &mut AnalysisDatabase, old_db: &AnalysisDatabase) {
let old_db_input = old_db.proc_macro_input();
new_db
.proc_macro_input()
.set_proc_macro_server_status(new_db)
.to(old_db_input.proc_macro_server_status(old_db));
new_db
.proc_macro_input()
.set_attribute_macro_resolution(new_db)
.to(old_db_input.attribute_macro_resolution(old_db).clone());
new_db
.proc_macro_input()
.set_derive_macro_resolution(new_db)
.to(old_db_input.derive_macro_resolution(old_db).clone());
new_db
.proc_macro_input()
.set_inline_macro_resolution(new_db)
.to(old_db_input.inline_macro_resolution(old_db).clone());
}
fn migrate_file_overrides(
new_db: &mut AnalysisDatabase,
old_db: &AnalysisDatabase,
open_files: &HashSet<Url>,
) {
let overrides = old_db.file_overrides();
let mut new_overrides: OrderedHashMap<_, _> = Default::default();
for uri in open_files {
let Some(file_id) = old_db.file_for_url(uri) else {
continue;
};
let file_input = file_id.long(old_db).into_file_input(old_db);
if let Some(content) = overrides.get(&file_id) {
new_overrides.insert(file_input, content.to_string().into());
}
}
for crate_id in old_db.crate_configs().keys() {
let Ok(file_id) = old_db.module_main_file(ModuleId::CrateRoot(*crate_id)) else {
continue;
};
let file_input = file_id.long(old_db).into_file_input(old_db);
if let Some(content) = overrides.get(&file_id) {
new_overrides.insert(file_input, content.to_string().into());
}
}
files_group_input(new_db).set_file_overrides(new_db).to(Some(new_overrides));
}
fn migrate_crate_model_inputs(new_db: &mut AnalysisDatabase, old_db: &AnalysisDatabase) {
files_group_input(new_db)
.set_crate_configs(new_db)
.to(files_group_input(old_db).crate_configs(old_db).clone());
defs_group_input(new_db)
.set_macro_plugin_overrides(new_db)
.to(Some(old_db.macro_plugin_overrides_input().clone()));
defs_group_input(new_db)
.set_inline_macro_plugin_overrides(new_db)
.to(Some(old_db.inline_macro_plugin_overrides_input().clone()));
semantic_group_input(new_db)
.set_analyzer_plugin_overrides(new_db)
.to(Some(old_db.analyzer_plugin_overrides_input().clone()));
}