diff --git a/server/Cargo.toml b/server/Cargo.toml index 2bdcb077..4841204c 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -29,6 +29,7 @@ tracing-panic = "0.1.2" winapi = { version = "0.3.9", features = ["winbase", "processthreadsapi", "synchapi", "handleapi"] } ctrlc = "3.4.4" once_cell = "1.20.1" +generational-arena = "0.2.9" [target.'cfg(any(target_os = "linux", target_os = "macos"))'.dependencies] nix = { version = "0.29.0", features = ["process"] } diff --git a/server/src/core/odoo.rs b/server/src/core/odoo.rs index eb7d3377..e5001f92 100644 --- a/server/src/core/odoo.rs +++ b/server/src/core/odoo.rs @@ -9,6 +9,7 @@ use std::rc::{Rc, Weak}; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; use std::time::Instant; +use generational_arena::{Arena, Index}; use lsp_server::ResponseError; use lsp_types::*; use request::{RegisterCapability, Request, WorkspaceConfiguration}; @@ -51,21 +52,23 @@ pub struct SyncOdoo { pub version_micro: u32, pub full_version: String, pub config: Config, - pub symbols: Option>>, + pub symbols: Option, pub stubs_dirs: Vec, pub stdlib_dir: String, file_mgr: Rc>, - pub modules: HashMap>>, - pub models: HashMap>>, + pub modules: HashMap, //weak + pub models: HashMap, //weak pub interrupt_rebuild: Arc, - rebuild_arch: PtrWeakHashSet>>, - rebuild_arch_eval: PtrWeakHashSet>>, - rebuild_odoo: PtrWeakHashSet>>, - rebuild_validation: PtrWeakHashSet>>, + rebuild_arch: HashSet, //weak + rebuild_arch_eval: HashSet, //weak + rebuild_odoo: HashSet, //weak + rebuild_validation: HashSet, //weak pub state_init: InitState, - pub not_found_symbols: PtrWeakHashSet>>, + pub not_found_symbols: HashSet, //weak pub load_odoo_addons: bool, //indicate if we want to load odoo addons or not - pub need_rebuild: bool //if true, the next process_rebuilds will drop everything and rebuild everything + pub need_rebuild: bool, //if true, the next process_rebuilds will drop everything and rebuild everything + + pub symbol_arena: Arena, } unsafe impl Send for SyncOdoo {} @@ -73,15 +76,15 @@ unsafe impl Send for SyncOdoo {} impl SyncOdoo { pub fn new() -> Self { - let symbols = Symbol::new_root(); - symbols.borrow_mut().as_root_mut().weak_self = Some(Rc::downgrade(&symbols)); // manually set weakself for root symbols + let mut arena = Arena::new(); + let root = Symbol::new_root(&mut arena); let sync_odoo = Self { version_major: 0, version_minor: 0, version_micro: 0, full_version: "0.0.0".to_string(), config: Config::new(), - symbols: Some(symbols), + symbols: Some(root), file_mgr: Rc::new(RefCell::new(FileMgr::new())), stubs_dirs: vec![env::current_dir().unwrap().join("typeshed").join("stubs").sanitize(), env::current_dir().unwrap().join("additional_stubs").sanitize()], @@ -89,20 +92,22 @@ impl SyncOdoo { modules: HashMap::new(), models: HashMap::new(), interrupt_rebuild: Arc::new(AtomicBool::new(false)), - rebuild_arch: PtrWeakHashSet::new(), - rebuild_arch_eval: PtrWeakHashSet::new(), - rebuild_odoo: PtrWeakHashSet::new(), - rebuild_validation: PtrWeakHashSet::new(), + rebuild_arch: HashSet::new(), + rebuild_arch_eval: HashSet::new(), + rebuild_odoo: HashSet::new(), + rebuild_validation: HashSet::new(), state_init: InitState::NOT_READY, - not_found_symbols: PtrWeakHashSet::new(), + not_found_symbols: HashSet::new(), load_odoo_addons: true, need_rebuild: false, + symbol_arena: arena, }; sync_odoo } pub fn reset(session: &mut SessionInfo, config: Config) { - let symbols = Symbol::new_root(); + session.sync_odoo.symbol_arena.clear(); + let symbols = Symbol::new_root(&mut session.sync_odoo.symbol_arena); session.log_message(MessageType::INFO, S!("Resetting Database...")); info!("Resetting database..."); session.sync_odoo.version_major = 0; @@ -117,12 +122,12 @@ impl SyncOdoo { session.sync_odoo.stdlib_dir = env::current_dir().unwrap().join("typeshed").join("stdlib").sanitize(); session.sync_odoo.modules = HashMap::new(); session.sync_odoo.models = HashMap::new(); - session.sync_odoo.rebuild_arch = PtrWeakHashSet::new(); - session.sync_odoo.rebuild_arch_eval = PtrWeakHashSet::new(); - session.sync_odoo.rebuild_odoo = PtrWeakHashSet::new(); - session.sync_odoo.rebuild_validation = PtrWeakHashSet::new(); + session.sync_odoo.rebuild_arch = HashSet::new(); + session.sync_odoo.rebuild_arch_eval = HashSet::new(); + session.sync_odoo.rebuild_odoo = HashSet::new(); + session.sync_odoo.rebuild_validation = HashSet::new(); session.sync_odoo.state_init = InitState::NOT_READY; - session.sync_odoo.not_found_symbols = PtrWeakHashSet::new(); + session.sync_odoo.not_found_symbols = HashSet::new(); session.sync_odoo.load_odoo_addons = true; session.sync_odoo.need_rebuild = false; SyncOdoo::init(session, config); @@ -153,7 +158,7 @@ impl SyncOdoo { info!("stub {:?} - {}", stub, found) } { - let mut root_symbol = session.sync_odoo.symbols.as_ref().unwrap().borrow_mut(); + let root_symbol = session.sync_odoo.symbol_arena.get_mut(session.sync_odoo.symbols.as_ref().unwrap().clone()).unwrap(); root_symbol.add_path(session.sync_odoo.stdlib_dir.clone()); for stub_dir in session.sync_odoo.stubs_dirs.iter() { root_symbol.add_path(stub_dir.clone()); @@ -165,6 +170,7 @@ impl SyncOdoo { session.send_notification("$Odoo/loadingStatusUpdate", "stop"); return; } + drop(root_symbol); let output = output.unwrap(); if output.status.success() { let stdout = String::from_utf8_lossy(&output.stdout); @@ -176,6 +182,7 @@ impl SyncOdoo { if pathbuf.is_dir() { let final_path = pathbuf.sanitize(); session.log_message(MessageType::INFO, format!("Adding sys.path: {}", final_path)); + let root_symbol = session.sync_odoo.symbol_arena.get_mut(session.sync_odoo.symbols.as_ref().unwrap().clone()).unwrap(); root_symbol.add_path(final_path.clone()); root_symbol.as_root_mut().sys_path.push(final_path.clone()); } @@ -273,7 +280,8 @@ impl SyncOdoo { session.sync_odoo.version_micro = _version_micro; session.sync_odoo.full_version = _full_version; //build base - session.sync_odoo.symbols.as_ref().unwrap().borrow_mut().add_path(session.sync_odoo.config.odoo_path.clone()); + let root_symbol = session.sync_odoo.symbol_arena.get_mut(session.sync_odoo.symbols.as_ref().unwrap().clone()).unwrap(); + root_symbol.add_path(session.sync_odoo.config.odoo_path.clone()); if session.sync_odoo.symbols.is_none() { panic!("Odoo root symbol not found") } @@ -294,7 +302,7 @@ impl SyncOdoo { let addon_symbol = addon_symbol[0].clone(); if odoo_addon_path.exists() { if session.sync_odoo.load_odoo_addons { - addon_symbol.borrow_mut().add_path( + session.get_sym_mut(addon_symbol).unwrap().add_path( odoo_addon_path.sanitize() ); } @@ -303,10 +311,10 @@ impl SyncOdoo { session.log_message(MessageType::ERROR, format!("Unable to find odoo addons path at {}", odoo_addon_path.sanitize())); return false; } - for addon in session.sync_odoo.config.addons.iter() { + for addon in session.sync_odoo.config.addons.clone().iter() { let addon_path = PathBuf::from(addon); if addon_path.exists() { - addon_symbol.borrow_mut().add_path( + session.get_sym_mut(addon_symbol).unwrap().add_path( addon_path.sanitize() ); } @@ -317,7 +325,7 @@ impl SyncOdoo { fn build_modules(session: &mut SessionInfo) { { let addons_symbol = session.sync_odoo.get_symbol(&tree(vec!["odoo", "addons"], vec![]), u32::MAX)[0].clone(); - let addons_path = addons_symbol.borrow_mut().paths().clone(); + let addons_path = session.get_sym_mut(addons_symbol).unwrap().paths().clone(); for addon_path in addons_path.iter() { info!("searching modules in {}", addon_path); if PathBuf::from(addon_path).exists() { @@ -347,12 +355,12 @@ impl SyncOdoo { session.sync_odoo.state_init = InitState::ODOO_READY; } - pub fn get_symbol(&self, tree: &Tree, position: u32) -> Vec>> { - self.symbols.as_ref().unwrap().borrow_mut().get_symbol(&tree, position) + pub fn get_symbol(&self, tree: &Tree, position: u32) -> Vec { + self.symbol_arena.get(self.symbols.as_ref().unwrap().clone()).unwrap().get_symbol(&tree, position) } - fn pop_item(&mut self, step: BuildSteps) -> Option>> { - let mut arc_sym: Option>> = None; + fn pop_item(&mut self, step: BuildSteps) -> Option { + let mut index: Option = None; //Part 1: Find the symbol with a unmutable set { let set = match step { @@ -361,33 +369,35 @@ impl SyncOdoo { BuildSteps::VALIDATION => &self.rebuild_validation, _ => &self.rebuild_arch }; - let mut selected_sym: Option>> = None; + let mut selected_sym: Option = None; let mut selected_count: u32 = 999999999; let mut current_count: u32; - for sym in &*set { + for weak_sym_index in &*set { current_count = 0; - let file = sym.borrow().get_file().unwrap().upgrade().unwrap(); - let file = file.borrow(); - for (index, dep_set) in file.get_all_dependencies(step).iter().enumerate() { - let index_set = match index { - x if x == BuildSteps::ARCH as usize => &self.rebuild_arch, - x if x == BuildSteps::ARCH_EVAL as usize => &self.rebuild_arch_eval, - x if x == BuildSteps::VALIDATION as usize => &self.rebuild_validation, - _ => continue, - }; - current_count += - dep_set.iter().filter(|dep| index_set.contains(dep)).count() as u32; - } - if current_count < selected_count { - selected_sym = Some(sym.clone()); - selected_count = current_count; - if current_count == 0 { - break; + //check that Index is still a valid one + if let Some(sym) = self.symbol_arena.get(weak_sym_index.clone()) { + let file = self.symbol_arena.get(sym.get_file().unwrap()).unwrap(); + for (index, dep_set) in file.get_all_dependencies(step).iter().enumerate() { + let index_set = match index { + x if x == BuildSteps::ARCH as usize => &self.rebuild_arch, + x if x == BuildSteps::ARCH_EVAL as usize => &self.rebuild_arch_eval, + x if x == BuildSteps::VALIDATION as usize => &self.rebuild_validation, + _ => continue, + }; + current_count += + dep_set.iter().filter(|dep| index_set.contains(dep)).count() as u32; + } + if current_count < selected_count { + selected_sym = Some(weak_sym_index.clone()); + selected_count = current_count; + if current_count == 0 { + break; + } } } } if selected_sym.is_some() { - arc_sym = selected_sym.map(|x| x.clone()); + index = selected_sym.map(|x| x.clone()); } } { @@ -397,11 +407,10 @@ impl SyncOdoo { BuildSteps::VALIDATION => &mut self.rebuild_validation, _ => &mut self.rebuild_arch }; - if arc_sym.is_none() { - set.clear(); //remove any potential dead weak ref + if index.is_none() { return None; } - let arc_sym_unwrapped = arc_sym.unwrap(); + let arc_sym_unwrapped = index.unwrap(); if !set.remove(&arc_sym_unwrapped) { panic!("Unable to remove selected symbol from rebuild set") } @@ -418,54 +427,54 @@ impl SyncOdoo { while !session.sync_odoo.need_rebuild && (!session.sync_odoo.rebuild_arch.is_empty() || !session.sync_odoo.rebuild_arch_eval.is_empty() || !session.sync_odoo.rebuild_odoo.is_empty() || !session.sync_odoo.rebuild_validation.is_empty()) { trace!("remains: {:?} - {:?} - {:?} - {:?}", session.sync_odoo.rebuild_arch.len(), session.sync_odoo.rebuild_arch_eval.len(), session.sync_odoo.rebuild_odoo.len(), session.sync_odoo.rebuild_validation.len()); let sym = session.sync_odoo.pop_item(BuildSteps::ARCH); - if let Some(sym_rc) = sym { - let tree = sym_rc.borrow().get_tree(); + if let Some(sym_idx) = sym { + let tree = session.get_sym(sym_idx).unwrap().get_tree(); if already_arch_rebuilt.contains(&tree) { info!("Already arch rebuilt, skipping"); continue; } already_arch_rebuilt.insert(tree); //TODO should delete previous first - let mut builder = PythonArchBuilder::new(sym_rc); + let mut builder = PythonArchBuilder::new(sym_idx); builder.load_arch(session); continue; } let sym = session.sync_odoo.pop_item(BuildSteps::ARCH_EVAL); - if let Some(sym_rc) = sym { - let tree = sym_rc.borrow().get_tree(); + if let Some(sym_idx) = sym { + let tree = session.get_sym(sym_idx).unwrap().get_tree(); if already_arch_eval_rebuilt.contains(&tree) { info!("Already arch eval rebuilt, skipping"); continue; } already_arch_eval_rebuilt.insert(tree); //TODO should delete previous first - let mut builder = PythonArchEval::new(sym_rc); + let mut builder = PythonArchEval::new(sym_idx); builder.eval_arch(session); continue; } let sym = session.sync_odoo.pop_item(BuildSteps::ODOO); - if let Some(sym_rc) = sym { - let tree = sym_rc.borrow().get_tree(); + if let Some(sym_idx) = sym { + let tree = session.get_sym(sym_idx).unwrap().get_tree(); if already_odoo_rebuilt.contains(&tree) { info!("Already odoo rebuilt, skipping"); continue; } already_odoo_rebuilt.insert(tree); //TODO should delete previous first - let mut builder = PythonOdooBuilder::new(sym_rc); + let mut builder = PythonOdooBuilder::new(sym_idx); builder.load_odoo_content(session); continue; } let sym = session.sync_odoo.pop_item(BuildSteps::VALIDATION); - if let Some(sym_rc) = sym { - let tree = sym_rc.borrow_mut().get_tree(); + if let Some(sym_idx) = sym { + let tree = session.get_sym(sym_idx).unwrap().get_tree(); if already_validation_rebuilt.contains(&tree) { info!("Already validation rebuilt, skipping"); continue; } already_validation_rebuilt.insert(tree); //TODO should delete previous first - let mut validator = PythonValidator::new(sym_rc); + let mut validator = PythonValidator::new(sym_idx); validator.validate(session); if session.sync_odoo.state_init == InitState::ODOO_READY && session.sync_odoo.interrupt_rebuild.load(Ordering::SeqCst) { session.sync_odoo.interrupt_rebuild.store(false, Ordering::SeqCst); @@ -482,73 +491,74 @@ impl SyncOdoo { } } - pub fn rebuild_arch_now(session: &mut SessionInfo, symbol: &Rc>) { + pub fn rebuild_arch_now(session: &mut SessionInfo, symbol: &Index) { session.sync_odoo.rebuild_arch.remove(symbol); let mut builder = PythonArchBuilder::new(symbol.clone()); builder.load_arch(session); } - pub fn add_to_rebuild_arch(&mut self, symbol: Rc>) { - trace!("ADDED TO ARCH - {}", symbol.borrow().paths().first().unwrap_or(symbol.borrow().name())); - if symbol.borrow().build_status(BuildSteps::ARCH) != BuildStatus::IN_PROGRESS { + pub fn add_to_rebuild_arch(&mut self, symbol: Index) { + let sym = self.symbol_arena.get_mut(symbol).unwrap(); + trace!("ADDED TO ARCH - {}", sym.paths().first().unwrap_or(sym.name())); + if sym.build_status(BuildSteps::ARCH) != BuildStatus::IN_PROGRESS { let sym_clone = symbol.clone(); - let mut sym_borrowed = sym_clone.borrow_mut(); - sym_borrowed.set_build_status(BuildSteps::ARCH, BuildStatus::PENDING); - sym_borrowed.set_build_status(BuildSteps::ARCH_EVAL, BuildStatus::PENDING); - sym_borrowed.set_build_status(BuildSteps::ODOO, BuildStatus::PENDING); - sym_borrowed.set_build_status(BuildSteps::VALIDATION, BuildStatus::PENDING); + sym.set_build_status(BuildSteps::ARCH, BuildStatus::PENDING); + sym.set_build_status(BuildSteps::ARCH_EVAL, BuildStatus::PENDING); + sym.set_build_status(BuildSteps::ODOO, BuildStatus::PENDING); + sym.set_build_status(BuildSteps::VALIDATION, BuildStatus::PENDING); self.rebuild_arch.insert(symbol); } } - pub fn add_to_rebuild_arch_eval(&mut self, symbol: Rc>) { - trace!("ADDED TO EVAL - {}", symbol.borrow().paths().first().unwrap_or(symbol.borrow().name())); - if symbol.borrow().build_status(BuildSteps::ARCH_EVAL) != BuildStatus::IN_PROGRESS { + pub fn add_to_rebuild_arch_eval(&mut self, symbol: Index) { + let sym = self.symbol_arena.get_mut(symbol).unwrap(); + trace!("ADDED TO EVAL - {}", sym.paths().first().unwrap_or(sym.name())); + if sym.build_status(BuildSteps::ARCH_EVAL) != BuildStatus::IN_PROGRESS { let sym_clone = symbol.clone(); - let mut sym_borrowed = sym_clone.borrow_mut(); - sym_borrowed.set_build_status(BuildSteps::ARCH_EVAL, BuildStatus::PENDING); - sym_borrowed.set_build_status(BuildSteps::ODOO, BuildStatus::PENDING); - sym_borrowed.set_build_status(BuildSteps::VALIDATION, BuildStatus::PENDING); + sym.set_build_status(BuildSteps::ARCH_EVAL, BuildStatus::PENDING); + sym.set_build_status(BuildSteps::ODOO, BuildStatus::PENDING); + sym.set_build_status(BuildSteps::VALIDATION, BuildStatus::PENDING); self.rebuild_arch_eval.insert(symbol); } } - pub fn add_to_init_odoo(&mut self, symbol: Rc>) { - trace!("ADDED TO ODOO - {}", symbol.borrow().paths().first().unwrap_or(symbol.borrow().name())); - if symbol.borrow().build_status(BuildSteps::ODOO) != BuildStatus::IN_PROGRESS { + pub fn add_to_init_odoo(&mut self, symbol: Index) { + let sym = self.symbol_arena.get_mut(symbol).unwrap(); + trace!("ADDED TO ODOO - {}", sym.paths().first().unwrap_or(sym.name())); + if sym.build_status(BuildSteps::ODOO) != BuildStatus::IN_PROGRESS { let sym_clone = symbol.clone(); - let mut sym_borrowed = sym_clone.borrow_mut(); - sym_borrowed.set_build_status(BuildSteps::ODOO, BuildStatus::PENDING); - sym_borrowed.set_build_status(BuildSteps::VALIDATION, BuildStatus::PENDING); + sym.set_build_status(BuildSteps::ODOO, BuildStatus::PENDING); + sym.set_build_status(BuildSteps::VALIDATION, BuildStatus::PENDING); self.rebuild_odoo.insert(symbol); } } - pub fn add_to_validations(&mut self, symbol: Rc>) { - trace!("ADDED TO VALIDATION - {}", symbol.borrow().paths().first().unwrap_or(symbol.borrow().name())); - if symbol.borrow().build_status(BuildSteps::VALIDATION) != BuildStatus::IN_PROGRESS { - symbol.borrow_mut().set_build_status(BuildSteps::VALIDATION, BuildStatus::PENDING); + pub fn add_to_validations(&mut self, symbol: Index) { + let sym = self.symbol_arena.get_mut(symbol).unwrap(); + trace!("ADDED TO VALIDATION - {}", sym.paths().first().unwrap_or(sym.name())); + if sym.build_status(BuildSteps::VALIDATION) != BuildStatus::IN_PROGRESS { + sym.set_build_status(BuildSteps::VALIDATION, BuildStatus::PENDING); self.rebuild_validation.insert(symbol); } } - pub fn remove_from_rebuild_arch(&mut self, symbol: &Rc>) { + pub fn remove_from_rebuild_arch(&mut self, symbol: &Index) { self.rebuild_arch.remove(symbol); } - pub fn remove_from_rebuild_arch_eval(&mut self, symbol: &Rc>) { + pub fn remove_from_rebuild_arch_eval(&mut self, symbol: &Index) { self.rebuild_arch_eval.remove(symbol); } - pub fn remove_from_rebuild_odoo(&mut self, symbol: &Rc>) { + pub fn remove_from_rebuild_odoo(&mut self, symbol: &Index) { self.rebuild_odoo.remove(symbol); } - pub fn remove_from_rebuild_validation(&mut self, symbol: &Rc>) { + pub fn remove_from_rebuild_validation(&mut self, symbol: &Index) { self.rebuild_validation.remove(symbol); } - pub fn is_in_rebuild(&self, symbol: &Rc>, step: BuildSteps) -> bool { + pub fn is_in_rebuild(&self, symbol: &Index, step: BuildSteps) -> bool { if step == BuildSteps::ARCH { return self.rebuild_arch.contains(symbol); } @@ -573,9 +583,9 @@ impl SyncOdoo { pub fn tree_from_path(&self, path: &PathBuf) -> Result { //First check in odoo, before anywhere else { - let odoo_sym = self.symbols.as_ref().unwrap().borrow().get_symbol(&tree(vec!["odoo", "addons"], vec![]), u32::MAX); - let odoo_sym = odoo_sym[0].clone(); - for addon_path in odoo_sym.borrow().paths().iter() { + let odoo_sym = self.get_symbol(&tree(vec!["odoo", "addons"], vec![]), u32::MAX); + let odoo_sym = self.symbol_arena.get(odoo_sym[0]).unwrap(); + for addon_path in odoo_sym.paths().iter() { if path.starts_with(addon_path) { let path = path.strip_prefix(addon_path).unwrap().to_path_buf(); let mut tree: Tree = (vec![S!("odoo"), S!("addons")], vec![]); @@ -589,7 +599,7 @@ impl SyncOdoo { } } } - for root_path in self.symbols.as_ref().unwrap().borrow().paths().iter() { + for root_path in self.symbol_arena.get(self.symbols.unwrap()).unwrap().paths().iter() { if path.starts_with(root_path) { let path = path.strip_prefix(root_path).unwrap().to_path_buf(); let mut tree: Tree = (vec![], vec![]); @@ -605,43 +615,43 @@ impl SyncOdoo { Err("Path not found in any module") } - pub fn _unload_path(session: &mut SessionInfo, path: &PathBuf, clean_cache: bool) -> Result>, String> { + pub fn _unload_path(session: &mut SessionInfo, path: &PathBuf, clean_cache: bool) -> Result { let ub_symbol = session.sync_odoo.symbols.as_ref().unwrap().clone(); - let symbol = ub_symbol.borrow(); + let symbol = session.get_sym(ub_symbol).unwrap(); let path_symbol = symbol.get_symbol(&session.sync_odoo.tree_from_path(&path).unwrap(), u32::MAX); + drop(symbol); if path_symbol.is_empty() { return Err("Symbol not found".to_string()); } - let path_symbol = path_symbol[0].clone(); - let parent = path_symbol.borrow().parent().clone().unwrap().upgrade().unwrap(); + let path_symbol = path_symbol[0]; + let parent_idx = session.get_sym(path_symbol).unwrap().parent().unwrap(); if clean_cache { let file_mgr = session.sync_odoo.file_mgr.clone(); let mut file_mgr = file_mgr.borrow_mut(); file_mgr.delete_path(session, &path.sanitize()); - let mut to_del = Vec::from_iter(path_symbol.borrow_mut().all_module_symbol().map(|x| x.clone())); + let mut to_del = Vec::from_iter(session.get_sym_mut(path_symbol).unwrap().all_module_symbol().map(|x| x.clone())); let mut index = 0; while index < to_del.len() { - file_mgr.delete_path(session, &to_del[index].borrow().paths()[0]); - let mut to_del_child = Vec::from_iter(to_del[index].borrow().all_module_symbol().map(|x| x.clone())); + file_mgr.delete_path(session, &session.get_sym(to_del[index]).unwrap().paths()[0]); + let mut to_del_child = Vec::from_iter(session.get_sym(to_del[index]).unwrap().all_module_symbol().map(|x| x.clone())); to_del.append(&mut to_del_child); index += 1; } } - drop(symbol); - Symbol::unload(session, path_symbol.clone()); - Ok(parent) + Symbol::unload(session, path_symbol); + Ok(parent_idx) } - pub fn create_new_symbol(session: &mut SessionInfo, path: PathBuf, parent: Rc>, require_module: bool) -> Option<(Rc>,Tree)> { + pub fn create_new_symbol(session: &mut SessionInfo, path: PathBuf, parent: Index, require_module: bool) -> Option<(Index,Tree)> { let mut path = path.clone(); if path.ends_with("__init__.py") || path.ends_with("__init__.pyi") || path.ends_with("__manifest__.py") { path.pop(); } - let _arc_symbol = Symbol::create_from_path(session, &path, parent, require_module); - if _arc_symbol.is_some() { - let _arc_symbol = _arc_symbol.unwrap(); - session.sync_odoo.add_to_rebuild_arch(_arc_symbol.clone()); - return Some((_arc_symbol.clone(), _arc_symbol.borrow().get_tree().clone())); + let symbol_idx = Symbol::create_from_path(session, &path, parent, require_module); + if symbol_idx.is_some() { + let symbol_idx = symbol_idx.unwrap(); + session.sync_odoo.add_to_rebuild_arch(symbol_idx.clone()); + return Some((symbol_idx.clone(), session.get_sym(symbol_idx).unwrap().get_tree().clone())); } None } @@ -650,13 +660,13 @@ impl SyncOdoo { from the not_found_symbols list to the rebuild list. Return True is something should be rebuilt */ pub fn search_symbols_to_rebuild(session: &mut SessionInfo, tree: &Tree) -> bool { let flat_tree = vec![tree.0.clone(), tree.1.clone()].concat(); - let mut found_sym: PtrWeakHashSet>> = PtrWeakHashSet::new(); + let mut found_sym: HashSet = HashSet::new(); let mut need_rebuild = false; let mut to_add = vec![vec![], vec![], vec![], vec![]]; //list of symbols to add after the loop (borrow issue) - for s in session.sync_odoo.not_found_symbols.iter() { + for s in session.sync_odoo.not_found_symbols.clone().iter() { let mut index: i32 = 0; //i32 sa we could go in negative values - while (index as usize) < s.borrow().not_found_paths().len() { - let (step, not_found_tree) = s.borrow().not_found_paths()[index as usize].clone(); + while (index as usize) < session.get_sym(s.clone()).unwrap().not_found_paths().len() { + let (step, not_found_tree) = session.get_sym(s.clone()).unwrap().not_found_paths()[index as usize].clone(); if flat_tree[..cmp::min(not_found_tree.len(), flat_tree.len())] == not_found_tree[..cmp::min(not_found_tree.len(), flat_tree.len())] { need_rebuild = true; match step { @@ -674,12 +684,12 @@ impl SyncOdoo { }, _ => {} } - s.borrow_mut().not_found_paths_mut().remove(index as usize); + session.get_sym_mut(s.clone()).unwrap().not_found_paths_mut().remove(index as usize); index -= 1; } index += 1; } - if s.borrow().not_found_paths().len() == 0 { + if session.get_sym(s.clone()).unwrap().not_found_paths().len() == 0 { found_sym.insert(s.clone()); } } @@ -693,7 +703,7 @@ impl SyncOdoo { session.sync_odoo.add_to_init_odoo(s.clone()); } for s in to_add[3].iter() { - s.borrow_mut().invalidate_sub_functions(session); + session.get_sym_mut(s.clone()).unwrap().invalidate_sub_functions(); session.sync_odoo.add_to_validations(s.clone()); } for sym in found_sym.iter() { @@ -702,8 +712,8 @@ impl SyncOdoo { need_rebuild } - pub fn get_file_symbol(&self, path: &PathBuf) -> Option>> { - let symbol = self.symbols.as_ref().unwrap().borrow(); + pub fn get_file_symbol(&self, path: &PathBuf) -> Option { + let symbol = self.symbol_arena.get(self.symbols.as_ref().unwrap().clone()).unwrap(); let tree = &self.tree_from_path(&path); if let Ok(tree) = tree { return symbol.get_symbol(tree, u32::MAX).get(0).cloned(); @@ -718,10 +728,10 @@ impl SyncOdoo { while symbols.len() > 0 { let s = symbols.pop(); if let Some(s) = s { - if s.borrow().in_workspace() && vec![SymType::FILE, SymType::PACKAGE].contains(&s.borrow().typ()) { + if session.get_sym(s).unwrap().in_workspace() && vec![SymType::FILE, SymType::PACKAGE].contains(&session.get_sym(s).unwrap().typ()) { session.sync_odoo.add_to_rebuild_arch_eval(s.clone()); } - symbols.extend(s.borrow().all_module_symbol().map(|x| {x.clone()}) ); + symbols.extend(session.get_sym(s).unwrap().all_module_symbol().map(|x| {x.clone()}) ); } } SyncOdoo::process_rebuilds(session); diff --git a/server/src/core/python_arch_builder.rs b/server/src/core/python_arch_builder.rs index 3bc9c4e8..0a3bfb97 100644 --- a/server/src/core/python_arch_builder.rs +++ b/server/src/core/python_arch_builder.rs @@ -2,6 +2,7 @@ use std::rc::Rc; use std::cell::RefCell; use std::vec; use anyhow::Error; +use generational_arena::Index; use ruff_text_size::{Ranged, TextRange}; use ruff_python_ast::{Alias, Expr, Identifier, Stmt, StmtAnnAssign, StmtAssign, StmtClassDef, StmtFor, StmtFunctionDef, StmtIf, StmtTry, StmtWith}; use lsp_types::Diagnostic; @@ -26,16 +27,16 @@ use super::symbols::function_symbol::Argument; #[derive(Debug)] pub struct PythonArchBuilder { - file: Rc>, + file: Index, file_mode: bool, current_step: BuildSteps, - sym_stack: Vec>>, + sym_stack: Vec, __all_symbols_to_add: Vec<(String, TextRange)>, diagnostics: Vec } impl PythonArchBuilder { - pub fn new(symbol: Rc>) -> PythonArchBuilder { + pub fn new(symbol: Index) -> PythonArchBuilder { PythonArchBuilder { file: symbol.clone(), //dummy, evaluated in load_arch file_mode: false, //dummy, evaluated in load_arch diff --git a/server/src/core/python_arch_eval.rs b/server/src/core/python_arch_eval.rs index ccceadb2..bfa88c64 100644 --- a/server/src/core/python_arch_eval.rs +++ b/server/src/core/python_arch_eval.rs @@ -3,6 +3,7 @@ use std::rc::Rc; use std::cell::RefCell; use std::{u32, vec}; +use generational_arena::Index; use ruff_text_size::{Ranged, TextRange}; use ruff_python_ast::{Alias, Expr, Identifier, Stmt, StmtAnnAssign, StmtAssign, StmtClassDef, StmtFor, StmtFunctionDef, StmtIf, StmtReturn, StmtTry, StmtWith}; use lsp_types::{Diagnostic, DiagnosticSeverity, NumberOrString, Position, Range}; @@ -30,17 +31,17 @@ use super::symbols::function_symbol::FunctionSymbol; #[derive(Debug, Clone)] pub struct PythonArchEval { - file: Rc>, + file: Index, file_mode: bool, current_step: BuildSteps, - sym_stack: Vec>>, + sym_stack: Vec, diagnostics: Vec, safe_import: Vec, ast_indexes: Vec, } impl PythonArchEval { - pub fn new(symbol: Rc>) -> PythonArchEval { + pub fn new(symbol: Index) -> PythonArchEval { PythonArchEval { file: symbol.clone(), //dummy, evaluated in eval_arch file_mode: false, //dummy, evaluated in eval_arch diff --git a/server/src/core/python_odoo_builder.rs b/server/src/core/python_odoo_builder.rs index 5523b66e..65ce0cbc 100644 --- a/server/src/core/python_odoo_builder.rs +++ b/server/src/core/python_odoo_builder.rs @@ -1,6 +1,7 @@ use std::path::PathBuf; use std::rc::Rc; use std::cell::RefCell; +use generational_arena::Index; use lsp_types::notification::ShowMessage; use lsp_types::MessageType; use ruff_python_ast::Expr; @@ -17,13 +18,13 @@ use crate::S; use super::evaluation::EvaluationValue; pub struct PythonOdooBuilder { - symbol: Rc>, + symbol: Index, diagnostics: Vec, } impl PythonOdooBuilder { - pub fn new(symbol: Rc>) -> PythonOdooBuilder { + pub fn new(symbol: Index) -> PythonOdooBuilder { PythonOdooBuilder { symbol: symbol, diagnostics: vec![] diff --git a/server/src/core/python_validator.rs b/server/src/core/python_validator.rs index 92bbbce7..c2950872 100644 --- a/server/src/core/python_validator.rs +++ b/server/src/core/python_validator.rs @@ -1,3 +1,4 @@ +use generational_arena::Index; use ruff_python_ast::{Alias, Expr, Identifier, Stmt, StmtAnnAssign, StmtAssign, StmtClassDef, StmtTry}; use ruff_text_size::{Ranged, TextRange}; use tracing::{trace, warn}; @@ -23,17 +24,17 @@ use super::python_arch_eval::PythonArchEval; #[derive(Debug)] pub struct PythonValidator { file_mode: bool, - sym_stack: Vec>>, + sym_stack: Vec, pub diagnostics: Vec, //collect diagnostic from arch and arch_eval too from inner functions, but put everything at Validation level safe_imports: Vec, - current_module: Option>> + current_module: Option } /* PythonValidator operate on a single Symbol. Unlike other steps, it can be done on symbol containing code (file and functions only. Not class, variable, namespace). It will validate this node and run a validator on all subsymbol and dependencies. It will try to inference the return type of functions if it is not annotated; */ impl PythonValidator { - pub fn new(symbol: Rc>) -> Self { + pub fn new(symbol: Index) -> Self { Self { file_mode: true, sym_stack: vec![symbol], diff --git a/server/src/core/symbols/file_symbol.rs b/server/src/core/symbols/file_symbol.rs index 7d9d1d4c..45de85f1 100644 --- a/server/src/core/symbols/file_symbol.rs +++ b/server/src/core/symbols/file_symbol.rs @@ -1,7 +1,8 @@ +use generational_arena::Index; use weak_table::PtrWeakHashSet; -use crate::{constants::{BuildStatus, BuildSteps}, core::model::Model}; -use std::{cell::RefCell, collections::HashMap, rc::{Rc, Weak}}; +use crate::{constants::{BuildStatus, BuildSteps}, core::model::Model, threads::SessionInfo}; +use std::{cell::RefCell, collections::{HashMap, HashSet}, rc::{Rc, Weak}}; use super::{symbol::Symbol, symbol_mgr::{SectionRange, SymbolMgr}}; @@ -10,21 +11,21 @@ pub struct FileSymbol { pub name: String, pub path: String, pub is_external: bool, - pub weak_self: Option>>, - pub parent: Option>>, + pub self_index: Option, + pub parent: Option, pub arch_status: BuildStatus, pub arch_eval_status: BuildStatus, pub odoo_status: BuildStatus, pub validation_status: BuildStatus, pub not_found_paths: Vec<(BuildSteps, Vec)>, pub in_workspace: bool, - pub model_dependencies: PtrWeakHashSet>>, //always on validation level, as odoo step is always required - pub dependencies: [Vec>>>; 4], - pub dependents: [Vec>>>; 3], + pub model_dependencies: HashSet, //always on validation level, as odoo step is always required + pub dependencies: [Vec>; 4], + pub dependents: [Vec>; 3], //Trait SymbolMgr pub sections: Vec, - pub symbols: HashMap>>>>, + pub symbols: HashMap>>, //--- dynamics variables pub ext_symbols: HashMap>>>, } @@ -36,7 +37,7 @@ impl FileSymbol { name, path, is_external, - weak_self: None, + self_index: None, parent: None, arch_status: BuildStatus::PENDING, arch_eval_status: BuildStatus::PENDING, @@ -47,46 +48,46 @@ impl FileSymbol { sections: vec![], symbols: HashMap::new(), ext_symbols: HashMap::new(), - model_dependencies: PtrWeakHashSet::new(), + model_dependencies: HashSet::new(), dependencies: [ vec![ //ARCH - PtrWeakHashSet::new() //ARCH + HashSet::new() //ARCH ], vec![ //ARCH_EVAL - PtrWeakHashSet::new() //ARCH + HashSet::new() //ARCH ], vec![ - PtrWeakHashSet::new(), // ARCH - PtrWeakHashSet::new(), //ARCH_EVAL - PtrWeakHashSet::new() //ODOO + HashSet::new(), // ARCH + HashSet::new(), //ARCH_EVAL + HashSet::new() //ODOO ], vec![ - PtrWeakHashSet::new(), // ARCH - PtrWeakHashSet::new(), //ARCH_EVAL - PtrWeakHashSet::new() //ODOO + HashSet::new(), // ARCH + HashSet::new(), //ARCH_EVAL + HashSet::new() //ODOO ]], dependents: [ vec![ //ARCH - PtrWeakHashSet::new(), //ARCH - PtrWeakHashSet::new(), //ARCH_EVAL - PtrWeakHashSet::new(), //ODOO - PtrWeakHashSet::new(), //VALIDATION + HashSet::new(), //ARCH + HashSet::new(), //ARCH_EVAL + HashSet::new(), //ODOO + HashSet::new(), //VALIDATION ], vec![ //ARCH_EVAL - PtrWeakHashSet::new(), //ODOO - PtrWeakHashSet::new() //VALIDATION + HashSet::new(), //ODOO + HashSet::new() //VALIDATION ], vec![ //ODOO - PtrWeakHashSet::new(), //ODOO - PtrWeakHashSet::new() //VALIDATION + HashSet::new(), //ODOO + HashSet::new() //VALIDATION ]], }; res._init_symbol_mgr(); res } - pub fn add_symbol(&mut self, content: &Rc>, section: u32) { - let sections = self.symbols.entry(content.borrow().name().clone()).or_insert_with(|| HashMap::new()); + pub fn add_symbol(&mut self, session: &mut SessionInfo, content: Index, section: u32) { + let sections = self.symbols.entry(session.get_sym(content).unwrap().name().clone()).or_insert_with(|| HashMap::new()); let section_vec = sections.entry(section).or_insert_with(|| vec![]); section_vec.push(content.clone()); } diff --git a/server/src/core/symbols/module_symbol.rs b/server/src/core/symbols/module_symbol.rs index d23fae5c..57a3fff9 100644 --- a/server/src/core/symbols/module_symbol.rs +++ b/server/src/core/symbols/module_symbol.rs @@ -1,3 +1,4 @@ +use generational_arena::Index; use lsp_types::{Diagnostic, DiagnosticSeverity, DiagnosticTag, NumberOrString, Position, Range}; use ruff_python_ast::{Expr, Stmt}; use ruff_text_size::{Ranged, TextRange}; @@ -40,8 +41,8 @@ pub struct ModuleSymbol { pub arch_eval_status: BuildStatus, pub odoo_status: BuildStatus, pub validation_status: BuildStatus, - pub weak_self: Option>>, - pub parent: Option>>, + pub self_index: Option, + pub parent: Option, pub not_found_paths: Vec<(BuildSteps, Vec)>, pub in_workspace: bool, pub model_dependencies: PtrWeakHashSet>>, //always on validation level, as odoo step is always required @@ -71,7 +72,7 @@ impl ModuleSymbol { dir_name: String::new(), depends: vec!("base".to_string()), data: Vec::new(), - weak_self: None, + self_index: None, parent: None, module_symbols: HashMap::new(), arch_status: BuildStatus::PENDING, @@ -302,7 +303,7 @@ impl ModuleSymbol { if !session.sync_odoo.modules.contains_key(depend) { let module = find_module(session, odoo_addons.clone(), depend); if module.is_none() { - session.sync_odoo.not_found_symbols.insert(symbol.weak_self().as_ref().unwrap().upgrade().expect("The symbol must be in the tree")); + session.sync_odoo.not_found_symbols.insert(symbol.self_index().as_ref().unwrap().clone()); symbol.not_found_paths_mut().push((BuildSteps::ARCH, vec![S!("odoo"), S!("addons"), depend.clone()])); diagnostics.push(Diagnostic::new( Range::new(Position::new(0, 0), Position::new(0, 1)), @@ -320,52 +321,50 @@ impl ModuleSymbol { symbol.add_dependency(&mut module, BuildSteps::ARCH, BuildSteps::ARCH); } } else { - let module = session.sync_odoo.modules.get(depend).unwrap().upgrade().unwrap(); - let mut module = (*module).borrow_mut(); + let mut module = session.get_sym_mut(session.sync_odoo.modules.get(depend).unwrap().clone()).unwrap(); symbol.add_dependency(&mut module, BuildSteps::ARCH, BuildSteps::ARCH) } } (diagnostics, loaded) } - fn _load_data(_symbol: Rc>, _odoo: &mut SyncOdoo) -> Vec { + fn _load_data(_symbol: Index, _odoo: &mut SyncOdoo) -> Vec { vec![] } - fn _load_arch(symbol: Rc>, session: &mut SessionInfo) -> Vec { - let root_path = (*symbol).borrow().as_module_package().root_path.clone(); + fn _load_arch(symbol: Index, session: &mut SessionInfo) -> Vec { + let root_path = session.get_sym(symbol).unwrap().as_module_package().root_path.clone(); let tests_path = PathBuf::from(root_path).join("tests"); if tests_path.exists() { - let rc_symbol = Symbol::create_from_path(session, &tests_path, symbol, false); - if rc_symbol.is_some() && rc_symbol.as_ref().unwrap().borrow().typ() != SymType::NAMESPACE { - let rc_symbol = rc_symbol.unwrap(); - session.sync_odoo.add_to_rebuild_arch(rc_symbol); + let symbol_idx = Symbol::create_from_path(session, &tests_path, symbol, false); + if symbol_idx.is_some() && session.get_sym(symbol_idx.unwrap()).unwrap().typ() != SymType::NAMESPACE { + let symbol_idx = symbol_idx.unwrap(); + session.sync_odoo.add_to_rebuild_arch(symbol_idx); } } vec![] } - pub fn is_in_deps(session: &mut SessionInfo, symbol: &Rc>, dir_name: &String, acc: &mut Option>) -> bool { - if symbol.borrow().as_module_package().dir_name == *dir_name || symbol.borrow().as_module_package().depends.contains(dir_name) { + pub fn is_in_deps(session: &mut SessionInfo, symbol: &Index, dir_name: &String, acc: &mut Option>) -> bool { + if session.get_sym(symbol.clone()).unwrap().as_module_package().dir_name == *dir_name || session.get_sym(symbol.clone()).unwrap().as_module_package().depends.contains(dir_name) { return true; } if acc.is_none() { *acc = Some(HashSet::new()); } - for dep in symbol.borrow().as_module_package().depends.iter() { + for dep in session.get_sym(symbol.clone()).unwrap().as_module_package().depends.clone().iter() { if acc.as_ref().unwrap().contains(dep) { continue; } - let dep_module = session.sync_odoo.modules.get(dep); + let dep_module = session.sync_odoo.modules.get(dep).cloned(); if let Some(dep_module) = dep_module { - let dep_module = dep_module.upgrade(); - if dep_module.is_none() { + if session.get_sym(dep_module.clone()).is_none() { continue; } - if ModuleSymbol::is_in_deps(session, dep_module.as_ref().unwrap(), dir_name, acc) { + if ModuleSymbol::is_in_deps(session, &dep_module, dir_name, acc) { return true; } - acc.as_mut().unwrap().insert(dep_module.as_ref().unwrap().borrow().as_module_package().dir_name.clone()); + acc.as_mut().unwrap().insert(session.get_sym(dep_module.clone()).unwrap().as_module_package().dir_name.clone()); } } false diff --git a/server/src/core/symbols/namespace_symbol.rs b/server/src/core/symbols/namespace_symbol.rs index 04ec09f9..9cecf439 100644 --- a/server/src/core/symbols/namespace_symbol.rs +++ b/server/src/core/symbols/namespace_symbol.rs @@ -1,6 +1,9 @@ +use generational_arena::Index; use weak_table::PtrWeakHashSet; -use std::{cell::RefCell, collections::HashMap, rc::{Rc, Weak}}; +use std::{cell::RefCell, collections::{HashMap, HashSet}, rc::{Rc, Weak}}; + +use crate::threads::SessionInfo; use super::symbol::Symbol; @@ -8,7 +11,7 @@ use super::symbol::Symbol; #[derive(Debug)] pub struct NamespaceDirectory { pub path: String, - pub module_symbols: HashMap>>, + pub module_symbols: HashMap, } #[derive(Debug)] @@ -16,11 +19,11 @@ pub struct NamespaceSymbol { pub name: String, pub directories: Vec, pub is_external: bool, - pub weak_self: Option>>, - pub parent: Option>>, + pub self_index: Option, + pub parent: Option, pub in_workspace: bool, - pub dependencies: [Vec>>>; 4], - pub dependents: [Vec>>>; 3], + pub dependencies: [Vec>; 4], + pub dependents: [Vec>; 3], } impl NamespaceSymbol { @@ -37,59 +40,59 @@ impl NamespaceSymbol { name, directories: directories, is_external, - weak_self: None, + self_index: None, parent: None, in_workspace: false, dependencies: [ vec![ //ARCH - PtrWeakHashSet::new() //ARCH + HashSet::new() //ARCH ], vec![ //ARCH_EVAL - PtrWeakHashSet::new() //ARCH + HashSet::new() //ARCH ], vec![ - PtrWeakHashSet::new(), // ARCH - PtrWeakHashSet::new(), //ARCH_EVAL - PtrWeakHashSet::new() //ODOO + HashSet::new(), // ARCH + HashSet::new(), //ARCH_EVAL + HashSet::new() //ODOO ], vec![ - PtrWeakHashSet::new(), // ARCH - PtrWeakHashSet::new(), //ARCH_EVAL - PtrWeakHashSet::new() //ODOO + HashSet::new(), // ARCH + HashSet::new(), //ARCH_EVAL + HashSet::new() //ODOO ]], dependents: [ vec![ //ARCH - PtrWeakHashSet::new(), //ARCH - PtrWeakHashSet::new(), //ARCH_EVAL - PtrWeakHashSet::new(), //ODOO - PtrWeakHashSet::new(), //VALIDATION + HashSet::new(), //ARCH + HashSet::new(), //ARCH_EVAL + HashSet::new(), //ODOO + HashSet::new(), //VALIDATION ], vec![ //ARCH_EVAL - PtrWeakHashSet::new(), //ODOO - PtrWeakHashSet::new() //VALIDATION + HashSet::new(), //ODOO + HashSet::new() //VALIDATION ], vec![ //ODOO - PtrWeakHashSet::new(), //ODOO - PtrWeakHashSet::new() //VALIDATION + HashSet::new(), //ODOO + HashSet::new() //VALIDATION ]], } } - pub fn add_file(&mut self, file: &Rc>) { + pub fn add_file(&mut self, file: &Symbol) { let mut best_index: i32 = -1; let mut best_length: i32 = -1; let mut index = 0; while index < self.directories.len() { - if file.borrow().paths()[0].starts_with(&self.directories[index as usize].path) && self.directories[index as usize].path.len() as i32 > best_length { + if file.paths()[0].starts_with(&self.directories[index as usize].path) && self.directories[index as usize].path.len() as i32 > best_length { best_index = index as i32; best_length = self.directories[index as usize].path.len() as i32; } index += 1; } if best_index == -1 { - panic!("Not valid path found to add the file ({}) to namespace {} with directories {:?}", file.borrow().paths()[0], self.name, self.directories); + panic!("Not valid path found to add the file ({}) to namespace {} with directories {:?}", file.paths()[0], self.name, self.directories); } else { - self.directories[best_index as usize].module_symbols.insert(file.borrow().name().clone(), file.clone()); + self.directories[best_index as usize].module_symbols.insert(file.name().clone(), file.self_index().unwrap()); } } diff --git a/server/src/core/symbols/package_symbol.rs b/server/src/core/symbols/package_symbol.rs index f7754cb9..d3943293 100644 --- a/server/src/core/symbols/package_symbol.rs +++ b/server/src/core/symbols/package_symbol.rs @@ -1,3 +1,4 @@ +use generational_arena::Index; use weak_table::PtrWeakHashSet; use crate::{constants::{BuildStatus, BuildSteps}, core::model::Model, threads::SessionInfo, S}; @@ -28,13 +29,13 @@ impl PackageSymbol { PackageSymbol::Module(m) => &m.name, } } - pub fn parent(&self) -> Option>> { + pub fn parent(&self) -> Option { match self { PackageSymbol::Module(m) => m.parent.clone(), PackageSymbol::PythonPackage(p) => p.parent.clone() } } - pub fn set_parent(&mut self, parent: Option>>) { + pub fn set_parent(&mut self, parent: Option) { match self { PackageSymbol::Module(m) => m.parent = parent, PackageSymbol::PythonPackage(p) => p.parent = parent, @@ -102,8 +103,8 @@ pub struct PythonPackageSymbol { pub path: String, pub i_ext: String, pub is_external: bool, - pub weak_self: Option>>, - pub parent: Option>>, + pub self_index: Option, + pub parent: Option, pub arch_status: BuildStatus, pub arch_eval_status: BuildStatus, pub odoo_status: BuildStatus, @@ -130,7 +131,7 @@ impl PythonPackageSymbol { path, is_external, i_ext: S!(""), - weak_self: None, + self_index: None, parent: None, arch_status: BuildStatus::PENDING, arch_eval_status: BuildStatus::PENDING, diff --git a/server/src/core/symbols/root_symbol.rs b/server/src/core/symbols/root_symbol.rs index 972052f1..8b393ba4 100644 --- a/server/src/core/symbols/root_symbol.rs +++ b/server/src/core/symbols/root_symbol.rs @@ -1,3 +1,5 @@ +use generational_arena::Index; + use crate::{threads::SessionInfo, S}; use std::{cell::RefCell, collections::HashMap, rc::{Rc, Weak}}; @@ -8,8 +10,8 @@ pub struct RootSymbol { pub name: String, pub paths: Vec, pub sys_path: Vec, //sys path are stored in paths too, but this list identifies them - pub weak_self: Option>>, - pub parent: Option>>, + pub self_index: Option, + pub parent: Option, pub module_symbols: HashMap>>, } @@ -20,7 +22,7 @@ impl RootSymbol { name: S!("Root"), paths: vec![], sys_path: vec![], - weak_self: None, + self_index: None, parent: None, module_symbols: HashMap::new(), } diff --git a/server/src/core/symbols/symbol.rs b/server/src/core/symbols/symbol.rs index a2400957..4207163b 100644 --- a/server/src/core/symbols/symbol.rs +++ b/server/src/core/symbols/symbol.rs @@ -1,3 +1,4 @@ +use generational_arena::{Arena, Index}; use ruff_text_size::{TextSize, TextRange}; use tracing::{info, trace}; use weak_table::traits::WeakElement; @@ -11,7 +12,7 @@ use crate::threads::SessionInfo; use crate::utils::{PathSanitizer as _}; use crate::S; use core::panic; -use std::collections::{HashMap, VecDeque}; +use std::collections::{HashMap, HashSet, VecDeque}; use weak_table::PtrWeakHashSet; use std::path::PathBuf; use std::rc::{Rc, Weak}; @@ -44,10 +45,10 @@ pub enum Symbol { } impl Symbol { - pub fn new_root() -> Rc> { - let root = Rc::new(RefCell::new(Symbol::Root(RootSymbol::new()))); - root.borrow_mut().set_weak_self(Rc::downgrade(&root)); - root + pub fn new_root(arena: &mut Arena) -> Index { + let index = arena.insert(Symbol::Root(RootSymbol::new())); + arena[index].self_index = index; + index } //Create a sub-symbol that is representing a file @@ -516,21 +517,21 @@ impl Symbol { } } - pub fn weak_self(&self) -> Option>> { + pub fn self_index(&self) -> Option { match self { - Symbol::Root(r) => r.weak_self.clone(), - Symbol::Namespace(n) => n.weak_self.clone(), - Symbol::Package(PackageSymbol::Module(m)) => m.weak_self.clone(), - Symbol::Package(PackageSymbol::PythonPackage(p)) => p.weak_self.clone(), - Symbol::File(f) => f.weak_self.clone(), - Symbol::Compiled(c) => c.weak_self.clone(), - Symbol::Class(c) => c.weak_self.clone(), - Symbol::Function(f) => f.weak_self.clone(), - Symbol::Variable(v) => v.weak_self.clone(), + Symbol::Root(r) => r.self_index.clone(), + Symbol::Namespace(n) => n.self_index.clone(), + Symbol::Package(PackageSymbol::Module(m)) => m.self_index.clone(), + Symbol::Package(PackageSymbol::PythonPackage(p)) => p.self_index.clone(), + Symbol::File(f) => f.self_index.clone(), + Symbol::Compiled(c) => c.self_index.clone(), + Symbol::Class(c) => c.self_index.clone(), + Symbol::Function(f) => f.self_index.clone(), + Symbol::Variable(v) => v.self_index.clone(), } } - pub fn parent(&self) -> Option>> { + pub fn parent(&self) -> Option { match self { Symbol::Root(r) => r.parent.clone(), Symbol::Namespace(n) => n.parent.clone(), @@ -543,7 +544,7 @@ impl Symbol { } } - fn set_parent(&mut self, parent: Option>>) { + fn set_parent(&mut self, parent: Option) { match self { Symbol::Root(_) => panic!(), Symbol::Namespace(n) => n.parent = parent, @@ -637,7 +638,7 @@ impl Symbol { _ => {false} } } - pub fn all_module_symbol(&self) -> Box>> + '_> { + pub fn all_module_symbol(&self) -> Box + '_> { match self { Symbol::Root(r) => Box::new(r.module_symbols.values()), Symbol::Namespace(n) => { @@ -859,7 +860,7 @@ impl Symbol { } ///Given a path, create the appropriated symbol and attach it to the given parent - pub fn create_from_path(session: &mut SessionInfo, path: &PathBuf, parent: Rc>, require_module: bool) -> Option>> { + pub fn create_from_path(session: &mut SessionInfo, path: &PathBuf, parent: Index, require_module: bool) -> Option { let name: String = path.with_extension("").components().last().unwrap().as_os_str().to_str().unwrap().to_string(); let path_str = path.sanitize(); if path_str.ends_with(".py") || path_str.ends_with(".pyi") { @@ -932,10 +933,10 @@ impl Symbol { res } - pub fn get_symbol(&self, tree: &Tree, position: u32) -> Vec>> { + pub fn get_symbol(&self, tree: &Tree, position: u32) -> Vec { let symbol_tree_files: &Vec = &tree.0; let symbol_tree_content: &Vec = &tree.1; - let mut iter_sym: Vec>> = vec![]; + let mut iter_sym: Vec = vec![]; if symbol_tree_files.len() != 0 { let _mod_iter_sym = self.get_module_symbol(&symbol_tree_files[0]); if _mod_iter_sym.is_none() { @@ -1088,7 +1089,7 @@ impl Symbol { } } - pub fn get_all_dependencies(&self, step: BuildSteps) -> &Vec>>> { + pub fn get_all_dependencies(&self, step: BuildSteps) -> &Vec> { if step == BuildSteps::SYNTAX { panic!("Can't get dependencies for syntax step") } @@ -1245,7 +1246,7 @@ impl Symbol { } } - pub fn invalidate_sub_functions(&mut self, _session: &mut SessionInfo) { + pub fn invalidate_sub_functions(&mut self) { if vec![SymType::PACKAGE, SymType::FILE].contains(&self.typ()) { for func in self.iter_inner_functions() { func.borrow_mut().evaluations_mut().unwrap().clear(); @@ -1255,7 +1256,7 @@ impl Symbol { } } - pub fn unload(session: &mut SessionInfo, symbol: Rc>) { + pub fn unload(session: &mut SessionInfo, symbol: Index) { /* Unload the symbol and its children. Mark all dependents symbols as 'to_revalidate' */ let mut vec_to_unload: VecDeque>> = VecDeque::from([symbol.clone()]); while vec_to_unload.len() > 0 { @@ -1301,16 +1302,6 @@ impl Symbol { } } - pub fn get_rc(&self) -> Option>> { - if self.weak_self().is_none() { - return None; - } - if let Some(v) = &self.weak_self() { - return Some(v.upgrade().unwrap()); - } - None - } - pub fn is_file_content(&self) -> bool{ match self { Symbol::Root(_) | Symbol::Namespace(_) | Symbol::Package(_) | Symbol::File(_) | Symbol::Compiled(_) => false, @@ -1330,23 +1321,23 @@ impl Symbol { return Symbol::is_symbol_in_parents(&parent, to_test); } - fn set_weak_self(&mut self, weak_self: Weak>) { + fn set_self_index(&mut self, self_index: Index) { match self { - Symbol::Root(r) => r.weak_self = Some(weak_self), - Symbol::Namespace(n) => n.weak_self = Some(weak_self), - Symbol::Package(PackageSymbol::Module(m)) => m.weak_self = Some(weak_self), - Symbol::Package(PackageSymbol::PythonPackage(p)) => p.weak_self = Some(weak_self), - Symbol::File(f) => f.weak_self = Some(weak_self), - Symbol::Compiled(c) => c.weak_self = Some(weak_self), - Symbol::Class(c) => c.weak_self = Some(weak_self), - Symbol::Function(f) => f.weak_self = Some(weak_self), - Symbol::Variable(v) => v.weak_self = Some(weak_self), + Symbol::Root(r) => r.self_index = Some(self_index), + Symbol::Namespace(n) => n.self_index = Some(self_index), + Symbol::Package(PackageSymbol::Module(m)) => m.self_index = Some(self_index), + Symbol::Package(PackageSymbol::PythonPackage(p)) => p.self_index = Some(self_index), + Symbol::File(f) => f.self_index = Some(self_index), + Symbol::Compiled(c) => c.self_index = Some(self_index), + Symbol::Class(c) => c.self_index = Some(self_index), + Symbol::Function(f) => f.self_index = Some(self_index), + Symbol::Variable(v) => v.self_index = Some(self_index), } } - pub fn get_in_parents(&self, sym_types: &Vec, stop_same_file: bool) -> Option>> { + pub fn get_in_parents(&self, sym_types: &Vec, stop_same_file: bool) -> Option { if sym_types.contains(&self.typ()) { - return self.weak_self().clone(); + return self.self_index().clone(); } if stop_same_file && vec![SymType::FILE, SymType::PACKAGE].contains(&self.typ()) { return None; @@ -1357,8 +1348,8 @@ impl Symbol { return None; } - pub fn has_rc_in_parents(&self, rc: Rc>, stop_same_file: bool) -> bool { - if Rc::ptr_eq(&self.weak_self().unwrap().upgrade().unwrap(), &rc) { + pub fn has_rc_in_parents(&self, rc: Index, stop_same_file: bool) -> bool { + if Rc::ptr_eq(&self.self_index().unwrap().upgrade().unwrap(), &rc) { return true; } if stop_same_file && vec![SymType::FILE, SymType::PACKAGE].contains(&self.typ()) { @@ -1424,9 +1415,9 @@ impl Symbol { symbol.borrow_mut().set_parent(None); } - pub fn get_file(&self) -> Option>> { + pub fn get_file(&self) -> Option { if self.typ() == SymType::FILE || self.typ() == SymType::PACKAGE { - return self.weak_self().clone(); + return self.self_index().clone(); } if self.parent().is_some() { return self.parent().as_ref().unwrap().upgrade().unwrap().borrow_mut().get_file(); @@ -1434,9 +1425,9 @@ impl Symbol { return None; } - pub fn parent_file_or_function(&self) -> Option>> { + pub fn parent_file_or_function(&self) -> Option { if self.typ() == SymType::FILE || self.typ() == SymType::PACKAGE || self.typ() == SymType::FUNCTION { - return self.weak_self().clone(); + return self.self_index().clone(); } if self.parent().is_some() { return self.parent().as_ref().unwrap().upgrade().unwrap().borrow_mut().parent_file_or_function(); @@ -1444,13 +1435,13 @@ impl Symbol { return None; } - pub fn find_module(&self) -> Option>> { + pub fn find_module(&self, session: &mut SessionInfo) -> Option { match self { Symbol::Package(PackageSymbol::Module(m)) => {return self.get_rc();} _ => {} } if let Some(parent) = self.parent().as_ref() { - return parent.upgrade().unwrap().borrow().find_module(); + return parent.upgrade().unwrap().borrow().find_module(session); } return None; } @@ -1467,7 +1458,7 @@ impl Symbol { ==== next_refs on the 'a' in the print will return a SymbolRef to Test and one to Object */ - pub fn next_refs(session: &mut SessionInfo, symbol: &Symbol, diagnostics: &mut Vec) -> VecDeque<(Weak>, bool)> { + pub fn next_refs(session: &mut SessionInfo, symbol: &Symbol, diagnostics: &mut Vec) -> VecDeque<(Index, bool)> { match symbol { Symbol::Variable(v) => { let mut res = VecDeque::new(); diff --git a/server/src/features/completion.rs b/server/src/features/completion.rs index 76dcb054..1942e971 100644 --- a/server/src/features/completion.rs +++ b/server/src/features/completion.rs @@ -1,4 +1,5 @@ use std::{cell::RefCell, rc::Rc}; +use generational_arena::Index; use lsp_types::{CompletionItem, CompletionItemKind, CompletionItemLabelDetails, CompletionList, CompletionResponse, MarkupContent}; use ruff_python_ast::{ExceptHandler, Expr, ExprAttribute, ExprIf, ExprName, ExprSubscript, ExprYield, Stmt, StmtGlobal, StmtImport, StmtImportFrom, StmtNonlocal}; use ruff_text_size::Ranged; @@ -27,7 +28,7 @@ pub struct CompletionFeature; impl CompletionFeature { pub fn autocomplete(session: &mut SessionInfo, - file_symbol: &Rc>, + file_symbol: &Index, file_info: &Rc>, line: u32, character: u32 diff --git a/server/src/features/definition.rs b/server/src/features/definition.rs index 9f87856b..30b01e77 100644 --- a/server/src/features/definition.rs +++ b/server/src/features/definition.rs @@ -1,5 +1,6 @@ use std::path::PathBuf; use std::{cell::RefCell, rc::Rc}; +use generational_arena::Index; use ruff_text_size::TextRange; use lsp_types::{GotoDefinitionResponse, Location, Range}; @@ -18,7 +19,7 @@ pub struct DefinitionFeature {} impl DefinitionFeature { pub fn get_location(session: &mut SessionInfo, - file_symbol: &Rc>, + file_symbol: &Index, file_info: &Rc>, line: u32, character: u32 diff --git a/server/src/features/hover.rs b/server/src/features/hover.rs index e89ee012..a4e6a184 100644 --- a/server/src/features/hover.rs +++ b/server/src/features/hover.rs @@ -1,3 +1,4 @@ +use generational_arena::Index; use ruff_text_size::TextRange; use lsp_types::{Hover, HoverContents, MarkupContent, Range}; use weak_table::traits::WeakElement; @@ -17,7 +18,7 @@ pub struct HoverFeature {} impl HoverFeature { - pub fn get_hover(session: &mut SessionInfo, file_symbol: &Rc>, file_info: &Rc>, line: u32, character: u32) -> Option { + pub fn get_hover(session: &mut SessionInfo, file_symbol: &Index, file_info: &Rc>, line: u32, character: u32) -> Option { let offset = file_info.borrow().position_to_offset(line, character); let (analyse_ast_result, range): (AnalyzeAstResult, Option) = AstUtils::get_symbols(session, file_symbol, file_info, offset as u32); let evals = analyse_ast_result.evaluations; diff --git a/server/src/threads.rs b/server/src/threads.rs index 9128e25a..abc212bb 100644 --- a/server/src/threads.rs +++ b/server/src/threads.rs @@ -1,6 +1,7 @@ use std::{path::PathBuf, sync::{atomic::Ordering, Arc, Mutex}, time::Instant}; use crossbeam_channel::{Receiver, Sender, TryRecvError}; +use generational_arena::Index; use lsp_server::{Message, RequestId, Response, ResponseError}; use lsp_types::{notification::{DidChangeConfiguration, DidChangeTextDocument, DidChangeWatchedFiles, DidChangeWorkspaceFolders, DidCloseTextDocument, DidCreateFiles, DidDeleteFiles, DidOpenTextDocument, DidRenameFiles, DidSaveTextDocument, LogMessage, @@ -10,7 +11,7 @@ use serde::{de::DeserializeOwned, Serialize}; use serde_json::Value; use tracing::{error, warn}; -use crate::{core::{config::RefreshMode, odoo::{Odoo, SyncOdoo}}, server::ServerError, S}; +use crate::{core::{config::RefreshMode, odoo::{Odoo, SyncOdoo}, symbols::symbol::Symbol}, server::ServerError, S}; pub struct SessionInfo<'a> { sender: Sender, @@ -117,6 +118,16 @@ impl <'a> SessionInfo<'a> { delayed_process_sender: delayed_process_sender } } + + /* shortens get item expression */ + pub fn get_sym(&self, index: Index) -> Option<&Symbol> { + self.sync_odoo.symbol_arena.get(index) + } + + /* shortens get item expression */ + pub fn get_sym_mut(&mut self, index: Index) -> Option<&mut Symbol> { + self.sync_odoo.symbol_arena.get_mut(index) + } } fn to_value(result: Result, ResponseError>) -> (Option, Option) {