diff --git a/server/error_code.md b/server/error_code.md index fbec9ba..d3e2660 100644 --- a/server/error_code.md +++ b/server/error_code.md @@ -43,6 +43,10 @@ If your code is working fine, it can happen if you use too many "import *" that "Multiple definition found for base class". The extension is unable to handle a base class that has multiple possible definitions. This warning should disappear in the future +### OLS20006 +"Deprecation Warning: Since 17.0: odoo.tests.common.Form is deprecated, use odoo.tests.Form" +Form is no longer available on odoo.tests.common, thus it should not be imported from there. + ### OLS20201 "The active key is deprecated". diff --git a/server/src/core/evaluation.rs b/server/src/core/evaluation.rs index 8d9e535..02811af 100644 --- a/server/src/core/evaluation.rs +++ b/server/src/core/evaluation.rs @@ -11,6 +11,7 @@ use crate::core::odoo::SyncOdoo; use crate::threads::SessionInfo; use crate::S; +use super::file_mgr::FileMgr; use super::python_validator::PythonValidator; use super::symbols::symbol::Symbol; use super::symbols::symbol_mgr::SectionIndex; @@ -549,7 +550,11 @@ impl Evaluation { for ibase in bases.iter() { let base_loc = ibase.0.upgrade(); if let Some(base_loc) = base_loc { - let attributes = base_loc.borrow().get_member_symbol(session, &expr.attr.to_string(), module.clone(), false, true, &mut diagnostics); + let (attributes, mut attributes_diagnostics) = base_loc.borrow().get_member_symbol(session, &expr.attr.to_string(), module.clone(), false, true); + for diagnostic in attributes_diagnostics.iter_mut(){ + diagnostic.range = FileMgr::textRange_to_temporary_Range(&expr.range()) + } + diagnostics.extend(attributes_diagnostics); if !attributes.is_empty() { let mut eval = Evaluation::eval_from_symbol(&Rc::downgrade(attributes.first().unwrap())); eval.symbol.context = context.as_ref().unwrap().clone(); diff --git a/server/src/core/file_mgr.rs b/server/src/core/file_mgr.rs index efc6782..2d1e540 100644 --- a/server/src/core/file_mgr.rs +++ b/server/src/core/file_mgr.rs @@ -98,7 +98,7 @@ impl FileInfo { end: Position::new(err.location.end().to_u32(), 0)}, Some(DiagnosticSeverity::ERROR), Some(NumberOrString::String(S!("OLS30001"))), - None, + Some(EXTENSION_NAME.to_string()), err.error.to_string(), None, None)); diff --git a/server/src/core/python_arch_eval_hooks.rs b/server/src/core/python_arch_eval_hooks.rs index 97fbe7a..83dabef 100644 --- a/server/src/core/python_arch_eval_hooks.rs +++ b/server/src/core/python_arch_eval_hooks.rs @@ -276,7 +276,7 @@ impl PythonArchEvalHooks { diagnostics.push(Diagnostic::new(range, Some(DiagnosticSeverity::ERROR), Some(NumberOrString::String(S!("OLS30101"))), - None, + Some(EXTENSION_NAME.to_string()), S!("This model is not in the dependencies of your module."), None, None @@ -288,7 +288,7 @@ impl PythonArchEvalHooks { diagnostics.push(Diagnostic::new(range, Some(DiagnosticSeverity::ERROR), Some(NumberOrString::String(S!("OLS30102"))), - None, + Some(EXTENSION_NAME.to_string()), S!("Unknown model. Check your addons path"), None, None @@ -459,4 +459,4 @@ impl PythonArchEvalHooks { range: None, }]); } -} \ No newline at end of file +} diff --git a/server/src/core/python_odoo_builder.rs b/server/src/core/python_odoo_builder.rs index 2873807..cdc5439 100644 --- a/server/src/core/python_odoo_builder.rs +++ b/server/src/core/python_odoo_builder.rs @@ -179,7 +179,7 @@ impl PythonOdooBuilder { } fn _get_attribute(&mut self, session: &mut SessionInfo, loc_sym: &mut Symbol, attr: &String) -> Option { - let attr_sym = loc_sym.get_member_symbol(session, attr, None, true, false, &mut self.diagnostics); + let (attr_sym, _) = loc_sym.get_member_symbol(session, attr, None, true, false); if attr_sym.len() == 0 { return None; } @@ -329,4 +329,4 @@ impl PythonOdooBuilder { } true } -} \ No newline at end of file +} diff --git a/server/src/core/python_validator.rs b/server/src/core/python_validator.rs index 2f829d8..a0c2ec3 100644 --- a/server/src/core/python_validator.rs +++ b/server/src/core/python_validator.rs @@ -392,7 +392,7 @@ impl PythonValidator { Range::new(Position::new(range.start().to_u32(), 0), Position::new(range.end().to_u32(), 0)), Some(DiagnosticSeverity::ERROR), Some(NumberOrString::String(S!("OLS30102"))), - None, + Some(EXTENSION_NAME.to_string()), S!("Unknown model. Check your addons path"), None, None) @@ -404,7 +404,7 @@ impl PythonValidator { Range::new(Position::new(range.start().to_u32(), 0), Position::new(range.end().to_u32(), 0)), Some(DiagnosticSeverity::ERROR), Some(NumberOrString::String(S!("OLS30102"))), - None, + Some(EXTENSION_NAME.to_string()), S!("Unknown model. Check your addons path"), None, None) @@ -414,4 +414,4 @@ impl PythonValidator { //TODO do we want to raise something? } } -} \ No newline at end of file +} diff --git a/server/src/core/symbols/symbol.rs b/server/src/core/symbols/symbol.rs index 34dce9a..c0485a8 100644 --- a/server/src/core/symbols/symbol.rs +++ b/server/src/core/symbols/symbol.rs @@ -5,6 +5,7 @@ use weak_table::traits::WeakElement; use crate::constants::*; use crate::core::evaluation::{Context, Evaluation}; +use crate::core::file_mgr::FileMgr; use crate::core::odoo::SyncOdoo; use crate::core::python_arch_eval::PythonArchEval; use crate::threads::SessionInfo; @@ -17,7 +18,7 @@ use std::path::PathBuf; use std::rc::{Rc, Weak}; use std::cell::RefCell; use std::{u32, vec}; -use lsp_types::Diagnostic; +use lsp_types::{Diagnostic, DiagnosticSeverity, DiagnosticTag, NumberOrString, Position, Range}; use crate::core::symbols::function_symbol::FunctionSymbol; use crate::core::symbols::module_symbol::ModuleSymbol; @@ -1537,19 +1538,43 @@ impl Symbol { symbols.into_iter() } + /* Hook for get_member_symbol + Position is set to [0,0], because inside the method there is no concept of the current position. + The setting of the position is then delegated to the calling function. + TODO Consider refactoring. + */ + fn member_symbol_hook(&self, name: &String, diagnostics: &mut Vec){ + if name == "Form"{ + let tree = self.get_tree(); + if tree == (vec![S!("odoo"), S!("tests"), S!("common")], vec!()){ + diagnostics.push(Diagnostic::new(Range::new(Position::new(0,0),Position::new(0,0)), + Some(DiagnosticSeverity::WARNING), + Some(NumberOrString::String(S!("OLS20006"))), + Some(EXTENSION_NAME.to_string()), + S!("Deprecation Warning: Since 17.0: odoo.tests.common.Form is deprecated, use odoo.tests.Form"), + None, + Some(vec![DiagnosticTag::DEPRECATED]), + ) + ); + } + } + } + /* similar to get_symbol: will return the symbol that is under this one with the specified name. However, if the symbol is a class or a model, it will search in the base class or in comodel classes if not all, it will return the first found. If all, the all found symbols are returned, but the first one is the one that is overriding others. :param: from_module: optional, can change the from_module of the given class */ - pub fn get_member_symbol(&self, session: &mut SessionInfo, name: &String, from_module: Option>>, prevent_comodel: bool, all: bool, diagnostics: &mut Vec) -> Vec>> { + pub fn get_member_symbol(&self, session: &mut SessionInfo, name: &String, from_module: Option>>, prevent_comodel: bool, all: bool) -> (Vec>>, Vec) { let mut result: Vec>> = vec![]; + let mut diagnostics: Vec = vec![]; + self.member_symbol_hook(name, &mut diagnostics); let mod_sym = self.get_module_symbol(name); if let Some(mod_sym) = mod_sym { if all { result.push(mod_sym); } else { - return vec![mod_sym]; + return (vec![mod_sym], diagnostics); } } let content_sym = self.get_content_symbol(name, u32::MAX); @@ -1557,7 +1582,7 @@ impl Symbol { if all { result.extend(content_sym); } else { - return content_sym; + return (content_sym, diagnostics); } } if self.typ() == SymType::CLASS && self.as_class_sym()._model.is_some() && !prevent_comodel { @@ -1568,31 +1593,33 @@ impl Symbol { if self.is_equal(&loc_sym) { continue; } - let attribut = loc_sym.borrow().get_member_symbol(session, name, None, true, all, diagnostics); + let (attribut, att_diagnostic) = loc_sym.borrow().get_member_symbol(session, name, None, true, all); + diagnostics.extend(att_diagnostic); if all { result.extend(attribut); } else { - return attribut; + return (attribut, diagnostics); } } } } if !all && result.len() != 0 { - return result; + return (result, diagnostics); } if self.typ() == SymType::CLASS { for base in self.as_class_sym().bases.iter() { - let s = base.borrow().get_member_symbol(session, name, from_module.clone(), prevent_comodel, all, diagnostics); - if s.len() != 0 { + let (s, s_diagnostic) = base.borrow().get_member_symbol(session, name, from_module.clone(), prevent_comodel, all); + diagnostics.extend(s_diagnostic); + if s.len() != 0 { if all { result.extend(s); } else { - return s; + return (s, diagnostics); } } } } - result + (result, diagnostics) } pub fn is_equal(&self, other: &Rc>) -> bool {