Skip to content

Commit d14a3ba

Browse files
committed
[IMP] server: check for field validity on xml record
1 parent 7d26dfe commit d14a3ba

File tree

9 files changed

+117
-60
lines changed

9 files changed

+117
-60
lines changed

server/error_code.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,3 +332,6 @@ A menuitem is specifying an action that has not been declared before the menuite
332332
### OLS30449
333333
"Group with id XXXX does not exist"
334334
A menuitem is specifying a group that has not been declared before the menuitem
335+
336+
### OLS30450
337+
"model no in"

server/src/core/model.rs

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -185,26 +185,43 @@ impl Model {
185185

186186
/* Return all symbols that build this model.
187187
It returns the symbol and an optional string that represents the module name that should be added to dependencies to be used.
188+
if with_inheritance is true, it will also return symbols from inherited models (NOT Base classes).
188189
*/
189-
pub fn all_symbols(&self, session: &mut SessionInfo, from_module: Option<Rc<RefCell<Symbol>>>) -> Vec<(Rc<RefCell<Symbol>>, Option<OYarn>)> {
190-
let mut symbol = Vec::new();
190+
pub fn all_symbols(&self, session: &mut SessionInfo, from_module: Option<Rc<RefCell<Symbol>>>, with_inheritance: bool) -> Vec<(Rc<RefCell<Symbol>>, Option<OYarn>)> {
191+
self.all_symbols_helper(session, from_module, with_inheritance, &mut HashSet::new())
192+
}
193+
194+
fn all_symbols_helper(&self, session: &mut SessionInfo, from_module: Option<Rc<RefCell<Symbol>>>, with_inheritance: bool, seen_inherited_models: &mut HashSet<OYarn>) -> Vec<(Rc<RefCell<Symbol>>, Option<OYarn>)> {
195+
let mut symbols = Vec::new();
191196
for s in self.symbols.iter() {
192197
if let Some(from_module) = from_module.as_ref() {
193198
let module = s.borrow().find_module();
194199
if let Some(module) = module {
195200
if ModuleSymbol::is_in_deps(session, &from_module, &module.borrow().as_module_package().dir_name) {
196-
symbol.push((s, None));
201+
symbols.push((s.clone(), None));
197202
} else {
198-
symbol.push((s, Some(module.borrow().as_module_package().dir_name.clone())));
203+
symbols.push((s.clone(), Some(module.borrow().as_module_package().dir_name.clone())));
199204
}
200205
} else {
201206
session.log_message(MessageType::WARNING, "A model should be declared in a module.".to_string());
202207
}
203208
} else {
204-
symbol.push((s.clone(), None));
209+
symbols.push((s.clone(), None));
210+
}
211+
if with_inheritance {
212+
let inherited_models = s.borrow().as_class_sym()._model.as_ref().unwrap().inherit.clone();
213+
for inherited_model in inherited_models.iter() {
214+
if !seen_inherited_models.contains(inherited_model) {
215+
seen_inherited_models.insert(inherited_model.clone());
216+
let model = session.sync_odoo.models.get(inherited_model).cloned();
217+
if let Some(model) = model {
218+
symbols.extend(model.borrow().all_symbols_helper(session, from_module.clone(), true, seen_inherited_models));
219+
}
220+
}
221+
}
205222
}
206223
}
207-
symbol
224+
symbols
208225
}
209226

210227
pub fn add_dependent(&mut self, symbol: &Rc<RefCell<Symbol>>) {

server/src/core/python_arch_eval.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -542,7 +542,7 @@ impl PythonArchEval {
542542
let Some(model) = session.sync_odoo.models.get(&model_data.name).cloned() else {
543543
continue;
544544
};
545-
let model_classes = model.borrow().all_symbols(session, parent_class.find_module());
545+
let model_classes = model.borrow().all_symbols(session, parent_class.find_module(), false);
546546
let fn_name = self.sym_stack[0].borrow().name().clone();
547547
let allowed_fields: HashSet<_> = model_classes.iter().filter_map(|(sym, _)| sym.borrow().as_class_sym()._model.as_ref().unwrap().computes.get(&fn_name).cloned()).flatten().collect();
548548
if allowed_fields.is_empty() {

server/src/core/python_odoo_builder.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ impl PythonOdooBuilder {
6969
end: 1,
7070
}),
7171
xml_id: Some(xml_id_model_name),
72+
fields: vec![]
7273
}));
7374
});
7475
session.sync_odoo.models.insert(model_name.clone(), Rc::new(RefCell::new(model)));

server/src/core/symbols/symbol.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2294,7 +2294,7 @@ impl Symbol {
22942294
let model_data = sym.as_class_sym()._model.as_ref();
22952295
if let Some(model_data) = model_data {
22962296
if let Some(model) = session.sync_odoo.models.get(&model_data.name).cloned() {
2297-
for (model_sym, dependency) in model.borrow().all_symbols(session, from_module.clone()) {
2297+
for (model_sym, dependency) in model.borrow().all_symbols(session, from_module.clone(), true) {
22982298
if dependency.is_none() && !Rc::ptr_eq(symbol, &model_sym) {
22992299
for s in model_sym.borrow().all_symbols() {
23002300
if only_fields && !s.borrow().is_field(session){
@@ -2317,7 +2317,7 @@ impl Symbol {
23172317
}
23182318
let bases = symbol.borrow().as_class_sym().bases.clone();
23192319
for base in bases.iter() {
2320-
//no comodel as we will process only model in base class (overrided _name?)
2320+
//no comodel as we will search for co-model from original class (what about overrided _name?)
23212321
if let Some(base) = base.upgrade() {
23222322
Symbol::all_members(&base, session, result, false, only_fields, only_methods, from_module.clone(), acc, false);
23232323
}

server/src/core/xml_arch_builder_rng_validation.rs

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use regex::Regex;
66
use roxmltree::Node;
77
use tracing::{error, warn};
88

9-
use crate::{constants::{BuildStatus, BuildSteps, OYarn, EXTENSION_NAME}, core::xml_data::{XmlData, XmlDataActWindow, XmlDataDelete, XmlDataMenuItem, XmlDataRecord, XmlDataReport, XmlDataTemplate}, oyarn, threads::SessionInfo, Sy, S};
9+
use crate::{constants::{BuildStatus, BuildSteps, OYarn, EXTENSION_NAME}, core::xml_data::{XmlData, XmlDataActWindow, XmlDataDelete, XmlDataField, XmlDataMenuItem, XmlDataRecord, XmlDataReport, XmlDataTemplate}, oyarn, threads::SessionInfo, Sy, S};
1010

1111
use super::{file_mgr::FileInfo, odoo::SyncOdoo, symbols::{symbol::Symbol, xml_file_symbol::XmlFileSymbol}, xml_arch_builder::XmlArchBuilder};
1212

@@ -240,9 +240,16 @@ impl XmlArchBuilder {
240240
None));
241241
return false;
242242
}
243-
243+
let mut data = XmlDataRecord {
244+
file_symbol: Rc::downgrade(&self.xml_symbol),
245+
model: (oyarn!("{}", node.attribute("model").unwrap()), node.attribute_node("model").unwrap().range()),
246+
xml_id: found_id.clone().map(|id| oyarn!("{}", id)),
247+
fields: vec![]
248+
};
244249
for child in node.children().filter(|n| n.is_element()) {
245-
if !self.load_field(session, &child, diagnostics) {
250+
if let Some(field) = self.load_field(session, &child, diagnostics) {
251+
data.fields.push(field);
252+
} else {
246253
diagnostics.push(Diagnostic::new(
247254
Range { start: Position::new(child.range().start as u32, 0), end: Position::new(child.range().end as u32, 0) },
248255
Some(DiagnosticSeverity::ERROR),
@@ -253,17 +260,13 @@ impl XmlArchBuilder {
253260
None));
254261
}
255262
}
256-
let data = XmlData::RECORD(XmlDataRecord {
257-
file_symbol: Rc::downgrade(&self.xml_symbol),
258-
model: (oyarn!("{}", node.attribute("model").unwrap()), node.attribute_node("model").unwrap().range()),
259-
xml_id: found_id.clone().map(|id| oyarn!("{}", id)),
260-
});
263+
let data = XmlData::RECORD(data);
261264
self.on_operation_creation(session, found_id, node, data, diagnostics);
262265
true
263266
}
264267

265-
fn load_field(&mut self, session: &mut SessionInfo, node: &Node, diagnostics: &mut Vec<Diagnostic>) -> bool {
266-
if node.tag_name().name() != "field" { return false; }
268+
fn load_field(&mut self, session: &mut SessionInfo, node: &Node, diagnostics: &mut Vec<Diagnostic>) -> Option<XmlDataField> {
269+
if node.tag_name().name() != "field" { return None; }
267270
if node.attribute("name").is_none() {
268271
diagnostics.push(Diagnostic::new(
269272
Range { start: Position::new(node.range().start as u32, 0), end: Position::new(node.range().end as u32, 0) },
@@ -288,7 +291,7 @@ impl XmlArchBuilder {
288291
format!("field node cannot have more than one of the attributes type, ref, eval or search"),
289292
None,
290293
None));
291-
return false;
294+
return None;
292295
}
293296
let mut is_xml_or_html = false;
294297
if let Some(field_type) = node.attribute("type") {
@@ -416,7 +419,10 @@ impl XmlArchBuilder {
416419
None));
417420
}
418421
}
419-
true
422+
Some(XmlDataField {
423+
name: oyarn!("{}", node.attribute("name").unwrap()),
424+
range: node.attribute_node("name").unwrap().range(),
425+
})
420426
}
421427

422428
fn load_value(&mut self, session: &mut SessionInfo, node: &Node, diagnostics: &mut Vec<Diagnostic>) -> bool {

server/src/core/xml_data.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,13 @@ pub struct XmlDataRecord {
2020
pub file_symbol: Weak<RefCell<Symbol>>,
2121
pub model: (OYarn, Range<usize>),
2222
pub xml_id: Option<OYarn>,
23+
pub fields: Vec<XmlDataField>,
24+
}
25+
26+
#[derive(Debug, Clone)]
27+
pub struct XmlDataField {
28+
pub name: OYarn,
29+
pub range: Range<usize>,
2330
}
2431

2532
#[derive(Debug, Clone)]

0 commit comments

Comments
 (0)