Skip to content

Commit 73048ab

Browse files
committed
[IMP] server: detect "delegate=True" for inherits in models
1 parent d14a3ba commit 73048ab

File tree

7 files changed

+103
-7
lines changed

7 files changed

+103
-7
lines changed

server/src/core/evaluation.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -611,6 +611,39 @@ impl Evaluation {
611611
(None, value.diagnostics)
612612
}
613613

614+
/* Given an Expr, try to return the represented Boolean. None if it can't be achieved */
615+
pub fn expr_to_bool(session: &mut SessionInfo, ast: &Expr, parent: Rc<RefCell<Symbol>>, max_infer: &TextSize, diagnostics: &mut Vec<Diagnostic>) -> (Option<bool>, Vec<Diagnostic>) {
616+
let from_module;
617+
if let Some(module) = parent.borrow().find_module() {
618+
from_module = ContextValue::MODULE(Rc::downgrade(&module));
619+
} else {
620+
from_module = ContextValue::BOOLEAN(false);
621+
}
622+
let mut context: Option<Context> = Some(HashMap::from([
623+
(S!("module"), from_module),
624+
(S!("range"), ContextValue::RANGE(ast.range()))
625+
]));
626+
let value = Evaluation::analyze_ast(session, &ExprOrIdent::Expr(ast), parent, max_infer, &mut context, &mut vec![]);
627+
if value.evaluations.len() == 1 { //only handle strict evaluations
628+
let eval = &value.evaluations[0];
629+
let v = eval.follow_ref_and_get_value(session, &mut None, diagnostics);
630+
if let Some(v) = v {
631+
match v {
632+
EvaluationValue::CONSTANT(v) => {
633+
match v {
634+
Expr::BooleanLiteral(s) => {
635+
return (Some(s.value), value.diagnostics);
636+
},
637+
_ => {}
638+
}
639+
},
640+
_ => {}
641+
}
642+
}
643+
}
644+
(None, value.diagnostics)
645+
}
646+
614647

615648
/**
616649
analyze_ast will extract all known information about an ast:

server/src/core/model.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ impl Model {
208208
} else {
209209
symbols.push((s.clone(), None));
210210
}
211-
if with_inheritance {
211+
if with_inheritance { //TODO wrong, should be recursive
212212
let inherited_models = s.borrow().as_class_sym()._model.as_ref().unwrap().inherit.clone();
213213
for inherited_model in inherited_models.iter() {
214214
if !seen_inherited_models.contains(inherited_model) {

server/src/core/python_arch_eval_hooks.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use std::cmp::Ordering;
22
use std::collections::HashMap;
3+
use std::ops::Index;
34
use std::rc::Rc;
45
use std::rc::Weak;
56
use std::cell::RefCell;
@@ -872,6 +873,7 @@ impl PythonArchEvalHooks {
872873
"comodel_name",
873874
"related",
874875
"compute",
876+
"delegate",
875877
];
876878
contexts_to_add.extend(
877879
context_arguments.into_iter()
@@ -886,6 +888,11 @@ impl PythonArchEvalHooks {
886888
if let Some(related_string) = maybe_related_string {
887889
context.insert(S!(arg_name), ContextValue::STRING(related_string.to_string()));
888890
context.insert(format!("{arg_name}_arg_range"), ContextValue::RANGE(arg_range.clone()));
891+
} else {
892+
let maybe_boolean = Evaluation::expr_to_bool(session, field_name_expr, parent.clone(), &parameters.range.start(), &mut vec![]).0;
893+
if let Some(boolean) = maybe_boolean {
894+
context.insert(S!(arg_name), ContextValue::BOOLEAN(boolean));
895+
}
889896
}
890897
}
891898

server/src/core/python_odoo_builder.rs

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use std::cmp::Ordering;
2-
use std::collections::HashSet;
2+
use std::collections::{HashMap, HashSet};
33
use std::rc::Rc;
44
use std::cell::RefCell;
55
use lsp_types::notification::ShowMessage;
@@ -163,6 +163,33 @@ impl PythonOdooBuilder {
163163
}
164164
}
165165
}
166+
drop(_inherits);
167+
drop(symbol);
168+
//Add inherits from delegate=True from fields
169+
let mut all_fields = HashMap::new();
170+
Symbol::all_members(&self.symbol, session, &mut all_fields, false, true, false, None, &mut None, false);
171+
for (field_name, symbols) in all_fields.iter() {
172+
for (symbol, _deps) in symbols.iter() {
173+
if let Some(evals) = symbol.borrow().evaluations() {
174+
for eval in evals.iter() {
175+
let symbol_weak = eval.symbol.get_symbol_as_weak(session, &mut None, diagnostics, self.symbol.borrow().get_file().unwrap().upgrade());
176+
if let Some(eval_symbol) = symbol_weak.weak.upgrade() {
177+
if eval_symbol.borrow().name() == &Sy!("Many2one") {
178+
let context = &symbol_weak.context;
179+
if let Some(delegate) = context.get("delegate") {
180+
if delegate.as_bool() == true {
181+
if let Some(comodel) = context.get("comodel_name") {
182+
let comodel_name = oyarn!("{}", comodel.as_string());
183+
self.symbol.borrow_mut().as_class_sym_mut()._model.as_mut().unwrap().inherits.push((comodel_name, field_name.clone()));
184+
}
185+
}
186+
}
187+
}
188+
}
189+
}
190+
}
191+
}
192+
}
166193
}
167194

168195
fn _get_attribute(session: &mut SessionInfo, loc_sym: &mut Symbol, attr: &String, diagnostics: &mut Vec<Diagnostic>) -> Option<EvaluationValue> {

server/src/core/python_validator.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use std::rc::Rc;
66
use std::cell::RefCell;
77
use std::path::PathBuf;
88
use lsp_types::{Diagnostic, DiagnosticSeverity, NumberOrString, Position, Range};
9+
use crate::core::evaluation::ContextValue;
910
use crate::{constants::*, oyarn, Sy};
1011
use crate::core::symbols::symbol::Symbol;
1112
use crate::core::odoo::SyncOdoo;
@@ -392,7 +393,7 @@ impl PythonValidator {
392393
if !symbol.borrow().is_field_class(session){
393394
continue;
394395
}
395-
if let Some(related_field_name) = eval_weak.as_weak().context.get(&S!("related")).map(|ctx_val| ctx_val.as_string()) {
396+
if let Some(related_field_name) = eval_weak.as_weak().context.get(&S!("related")).filter(|val| matches!(val, ContextValue::STRING(s))).map(|ctx_val| ctx_val.as_string()) {
396397
let Some(special_arg_range) = eval_weak.as_weak().context.get(&S!("related_arg_range")).map(|ctx_val| ctx_val.as_text_range()) else {
397398
continue;
398399
};

server/src/core/symbols/symbol.rs

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2258,7 +2258,7 @@ impl Symbol {
22582258
iter.into_iter()
22592259
}
22602260

2261-
//store in result all available members for self: sub symbols, base class elements and models symbols
2261+
//store in result all available members for symbol: sub symbols, base class elements and models symbols
22622262
//TODO is order right of Vec in HashMap? if we take first or last in it, do we have the last effective value?
22632263
pub fn all_members(symbol: &Rc<RefCell<Symbol>>, session: &mut SessionInfo, result: &mut HashMap<OYarn, Vec<(Rc<RefCell<Symbol>>, Option<OYarn>)>>, with_co_models: bool, only_fields: bool, only_methods: bool, from_module: Option<Rc<RefCell<Symbol>>>, acc: &mut Option<HashSet<Tree>>, is_super: bool) {
22642264
if acc.is_none() {
@@ -2278,7 +2278,7 @@ impl Symbol {
22782278
if only_fields && !symbol.borrow().is_field(session){
22792279
continue;
22802280
}
2281-
if only_methods && symbol.borrow().typ() != SymType::FUNCTION{
2281+
if only_methods && symbol.borrow().typ() != SymType::FUNCTION {
22822282
continue;
22832283
}
22842284
let name = symbol.borrow().name().clone();
@@ -2315,9 +2315,29 @@ impl Symbol {
23152315
}
23162316
}
23172317
}
2318+
//add fields from _inherits
2319+
if let Some(model_data) = model_sym.borrow().as_class_sym()._model.as_ref() {
2320+
for (inherits_model, inherits_field) in model_data.inherits.iter() {
2321+
let inherits_model_sym = session.sync_odoo.models.get(inherits_model).cloned();
2322+
if let Some(inherits_model_sym) = inherits_model_sym {
2323+
for (model_symbol, deps) in inherits_model_sym.borrow().all_symbols(session, from_module.clone(), true).iter().filter(|(x, deps)| deps.is_none()) {
2324+
for (field_name, field_symbols) in Symbol::all_fields(&model_symbol, session, from_module.clone()) {
2325+
for (s, deps) in field_symbols.iter().filter(|(x, deps)| deps.is_none()) {
2326+
if let Some(vec) = result.get_mut(&field_name) {
2327+
vec.push((s.clone(), Some(model_sym.borrow().name().clone())));
2328+
} else {
2329+
result.insert(field_name.clone(), vec![(s.clone(), Some(model_sym.borrow().name().clone()))]);
2330+
}
2331+
}
2332+
}
2333+
}
2334+
}
2335+
}
2336+
}
23182337
let bases = symbol.borrow().as_class_sym().bases.clone();
23192338
for base in bases.iter() {
23202339
//no comodel as we will search for co-model from original class (what about overrided _name?)
2340+
//TODO what about base of co-models classes?
23212341
if let Some(base) = base.upgrade() {
23222342
Symbol::all_members(&base, session, result, false, only_fields, only_methods, from_module.clone(), acc, false);
23232343
}
@@ -2338,6 +2358,9 @@ impl Symbol {
23382358
}
23392359
}
23402360
}
2361+
2362+
2363+
23412364
/* return the Symbol (class, function or file) the closest to the given offset */
23422365
pub fn get_scope_symbol(file_symbol: Rc<RefCell<Symbol>>, offset: u32, is_param: bool) -> Rc<RefCell<Symbol>> {
23432366
let mut result = file_symbol.clone();
@@ -2572,6 +2595,12 @@ impl Symbol {
25722595
false
25732596
}
25742597

2598+
pub fn all_fields(symbol: &Rc<RefCell<Symbol>>, session: &mut SessionInfo, from_module: Option<Rc<RefCell<Symbol>>>) -> HashMap<OYarn, Vec<(Rc<RefCell<Symbol>>, Option<OYarn>)>> {
2599+
let mut all_fields = HashMap::new();
2600+
Symbol::all_members(symbol, session, &mut all_fields, true, true, false, from_module.clone(), &mut None, false);
2601+
all_fields
2602+
}
2603+
25752604
/* similar to get_symbol: will return the symbol that is under this one with the specified name.
25762605
However, if the symbol is a class or a model, it will search in the base class or in comodel classes
25772606
if not all, it will return the first found. If all, the all found symbols are returned, but the first one

server/src/core/xml_validation.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,7 @@ impl XmlValidator {
8888
for main_sym in main_symbols.iter() {
8989
dependencies.push(main_sym.borrow().get_file().unwrap().upgrade().unwrap());
9090
}
91-
let mut all_fields = HashMap::new();
92-
Symbol::all_members(&main_symbols[0], session, &mut all_fields, true, true, false, Some(module.clone()), &mut None, false);
91+
let all_fields = Symbol::all_fields(&main_symbols[0], session, Some(module.clone()));
9392
for field in &xml_data_record.fields {
9493
let declared_field = all_fields.get(&field.name);
9594
if let Some(declared_field) = declared_field {

0 commit comments

Comments
 (0)