diff --git a/server/src/core/python_validator.rs b/server/src/core/python_validator.rs index d04d3792..70e81de6 100644 --- a/server/src/core/python_validator.rs +++ b/server/src/core/python_validator.rs @@ -115,6 +115,9 @@ impl PythonValidator { session.current_noqa = old_noqa; } drop(file_info); + if self.sym_stack[0].borrow().typ() == SymType::PACKAGE(PackageType::MODULE) { + ModuleSymbol::validate_manifest(&self.sym_stack[0], session); + } let mut file_info = file_info_rc.borrow_mut(); file_info.replace_diagnostics(BuildSteps::VALIDATION, self.diagnostics.clone()); }, diff --git a/server/src/core/symbols/module_symbol.rs b/server/src/core/symbols/module_symbol.rs index 0d3be8f9..2b64b1d7 100644 --- a/server/src/core/symbols/module_symbol.rs +++ b/server/src/core/symbols/module_symbol.rs @@ -4,6 +4,7 @@ use ruff_text_size::{Ranged, TextRange}; use tracing::{error, info}; use weak_table::{PtrWeakHashSet, PtrWeakKeyHashMap}; use std::collections::{HashMap, HashSet}; +use std::ffi::OsStr; use crate::core::csv_arch_builder::CsvArchBuilder; use crate::core::diagnostics::{create_diagnostic, DiagnosticCode}; @@ -50,6 +51,7 @@ pub struct ModuleSymbol { pub parent: Option>>, pub not_found_paths: Vec<(BuildSteps, Vec)>, pub not_found_data: HashMap, + pub not_found_models: HashMap, pub in_workspace: bool, pub model_dependencies: PtrWeakHashSet>>, //always on validation level, as odoo step is always required pub dependencies: Vec>>>>>, @@ -76,6 +78,7 @@ impl ModuleSymbol { is_external, not_found_paths: vec![], not_found_data: HashMap::new(), + not_found_models: HashMap::new(), in_workspace: false, root_path: dir_path.sanitize(), loaded: false, @@ -151,7 +154,6 @@ impl ModuleSymbol { let manifest_file_info = session.sync_odoo.get_file_mgr().borrow().get_file_info(&manifest_path.sanitize()).expect("file not found in cache").clone(); let mut manifest_file_info = (*manifest_file_info).borrow_mut(); manifest_file_info.replace_diagnostics(crate::constants::BuildSteps::ARCH, diagnostics); - manifest_file_info.publish_diagnostics(session); } /* Load manifest to identify the module characteristics. @@ -352,6 +354,38 @@ impl ModuleSymbol { diagnostics } + pub fn validate_manifest(symbol: &Rc>, session: &mut SessionInfo){ + let data_paths = symbol.borrow().as_module_package().data.clone(); + let mut diagnostics = vec![]; + for (data_url, data_range) in data_paths.iter() { + // validate csv file names, check that their models exist + let path = PathBuf::from(symbol.borrow().paths()[0].clone()).join(data_url); + if path.extension().unwrap_or_default() != "csv" || !path.exists(){ + continue; + } + let Some(model_name) = path.file_stem().and_then(OsStr::to_str).map(|n| Sy!(n.to_string())) else { + continue; + }; + let maybe_model = session.sync_odoo.models.get(&model_name).cloned(); + let model_exists = maybe_model.as_ref().map(|m| m.borrow_mut().has_symbols()).unwrap_or(false); + if !model_exists { + if let Some(diagnostic) = create_diagnostic(session, DiagnosticCode::OLS05056, &[&model_name]) { + diagnostics.push(Diagnostic { + range: Range::new(Position::new(data_range.start().to_u32(), 0), Position::new(data_range.end().to_u32(), 0)), + ..diagnostic.clone() + }); + } + symbol.borrow_mut().as_module_package_mut().not_found_models.insert(model_name.clone(), BuildSteps::VALIDATION); + session.sync_odoo.get_main_entry().borrow_mut().not_found_symbols_for_models.insert(symbol.clone()); + } + } + let manifest_path = PathBuf::from(symbol.borrow().as_module_package().root_path.clone()).join("__manifest__.py"); + let manifest_file_info = session.sync_odoo.get_file_mgr().borrow().get_file_info(&manifest_path.sanitize()).expect("file not found in cache").clone(); + let mut manifest_file_info = (*manifest_file_info).borrow_mut(); + manifest_file_info.replace_diagnostics(crate::constants::BuildSteps::VALIDATION, diagnostics); + manifest_file_info.publish_diagnostics(session); + } + pub fn load_data(symbol: &Rc>, session: &mut SessionInfo) { let data_paths = symbol.borrow().as_module_package().data.clone(); for (data_url, _data_range) in data_paths.iter() { diff --git a/server/src/core/symbols/symbol.rs b/server/src/core/symbols/symbol.rs index 27953c11..4f4e8f39 100644 --- a/server/src/core/symbols/symbol.rs +++ b/server/src/core/symbols/symbol.rs @@ -1231,6 +1231,7 @@ impl Symbol { match self { Symbol::File(f) => Some(&f.not_found_models), Symbol::XmlFileSymbol(f) => Some(&f.not_found_models), + Symbol::Package(PackageSymbol::Module(m)) => Some(&m.not_found_models), Symbol::Root(_) => None, Symbol::Namespace(_) => None, Symbol::DiskDir(_) => None, @@ -1247,6 +1248,7 @@ impl Symbol { match self { Symbol::File(f) => Some(&mut f.not_found_models), Symbol::XmlFileSymbol(f) => Some(&mut f.not_found_models), + Symbol::Package(PackageSymbol::Module(m)) => Some(&mut m.not_found_models), Symbol::Root(_) => None, Symbol::Namespace(_) => None, Symbol::DiskDir(_) => None,