Skip to content

Commit eebb3a9

Browse files
committed
[IMP] Handle asset odoo nodes
1 parent a5e855b commit eebb3a9

File tree

6 files changed

+223
-3
lines changed

6 files changed

+223
-3
lines changed

server/src/core/diagnostic_codes_list.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -457,4 +457,44 @@ OLS05056, DiagnosticSetting::Error, "Model '{0}' not found",
457457
* Field not found in model
458458
*/
459459
OLS05057, DiagnosticSetting::Error, "Field '{0}' not found in model '{1}'",
460+
/**
461+
* The attribute is not valid for <asset> nodes.
462+
*/
463+
OLS05058, DiagnosticSetting::Error, "Invalid attribute {0} in asset node",
464+
/**
465+
* A <asset> node must have an id attribute.
466+
*/
467+
OLS05059, DiagnosticSetting::Error, "asset node must contain an id attribute",
468+
/**
469+
* A <asset> node must have a name attribute.
470+
*/
471+
OLS05060, DiagnosticSetting::Error, "asset node must contain a name attribute",
472+
/**
473+
* The attribute is not valid for <bundle> nodes inside <asset>.
474+
*/
475+
OLS05061, DiagnosticSetting::Error, "Invalid attribute {0} in the bundle node under asset",
476+
/**
477+
* The attribute is not valid for <path> nodes inside <asset>.
478+
*/
479+
OLS05062, DiagnosticSetting::Error, "Invalid attribute {0} in the path node under asset",
480+
/**
481+
* Only bundle, path, or field nodes are allowed as children of <asset>.
482+
*/
483+
OLS05063, DiagnosticSetting::Error, "Invalid child node {0} in asset node. Only bundle, path, or field allowed",
484+
/**
485+
* bundle node is required inside <asset>.
486+
*/
487+
OLS05064, DiagnosticSetting::Error, "Bundle node is required inside <asset>",
488+
/**
489+
* path node is required inside <asset>.
490+
*/
491+
OLS05065, DiagnosticSetting::Error, "Path node is required inside <asset>",
492+
/**
493+
* Bundle node in asset cannot be empty.
494+
*/
495+
OLS05066, DiagnosticSetting::Error, "Bundle node in asset cannot be empty",
496+
/**
497+
* Path node in asset cannot be empty.
498+
*/
499+
OLS05067, DiagnosticSetting::Error, "Path node in asset cannot be empty",
460500
}

server/src/core/xml_arch_builder_rng_validation.rs

Lines changed: 125 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use std::rc::Rc;
33
use lsp_types::{Diagnostic, Position, Range};
44
use roxmltree::Node;
55

6-
use crate::{constants::OYarn, core::{diagnostics::{create_diagnostic, DiagnosticCode}, odoo::SyncOdoo, xml_data::{OdooData, XmlDataDelete, OdooDataField, XmlDataMenuItem, OdooDataRecord, XmlDataTemplate}}, oyarn, threads::SessionInfo, Sy};
6+
use crate::{Sy, constants::OYarn, core::{diagnostics::{DiagnosticCode, create_diagnostic}, odoo::SyncOdoo, xml_data::{OdooData, OdooDataField, OdooDataRecord, XmlDataAsset, XmlDataDelete, XmlDataMenuItem, XmlDataTemplate}}, oyarn, threads::SessionInfo};
77

88
use super::xml_arch_builder::XmlArchBuilder;
99

@@ -36,7 +36,9 @@ impl XmlArchBuilder {
3636
|| self.load_template(session, &child, diagnostics)
3737
|| self.load_delete(session, &child, diagnostics)
3838
|| self.load_function(session, &child, diagnostics)
39-
|| child.is_text() || child.is_comment()) {
39+
|| self.load_asset(session, &child, diagnostics)
40+
|| child.is_text() || child.is_comment()
41+
) {
4042
if let Some(diagnostic) = create_diagnostic(session, DiagnosticCode::OLS05005, &[child.tag_name().name(), node.tag_name().name()]) {
4143
diagnostics.push(
4244
Diagnostic {
@@ -603,4 +605,125 @@ impl XmlArchBuilder {
603605
}
604606
true
605607
}
608+
609+
fn load_asset(&mut self, session: &mut SessionInfo, node: &Node, diagnostics: &mut Vec<Diagnostic>) -> bool {
610+
if node.tag_name().name() != "asset" { return false; }
611+
// Validate required attributes: id, name
612+
let mut found_id = None;
613+
let mut has_name = false;
614+
for attr in node.attributes() {
615+
match attr.name() {
616+
"id" => { found_id = Some(attr.value().to_string()); },
617+
"name" => { has_name = true; },
618+
"active" => {},
619+
_ => {
620+
if let Some(diagnostic) = create_diagnostic(session, DiagnosticCode::OLS05058, &[attr.name()]) {
621+
diagnostics.push(Diagnostic {
622+
range: Range { start: Position::new(attr.range().start as u32, 0), end: Position::new(attr.range().end as u32, 0) },
623+
..diagnostic.clone()
624+
});
625+
}
626+
}
627+
}
628+
}
629+
if found_id.is_none() {
630+
if let Some(diagnostic) = create_diagnostic(session, DiagnosticCode::OLS05059, &[]) {
631+
diagnostics.push(Diagnostic {
632+
range: Range { start: Position::new(node.range().start as u32, 0), end: Position::new(node.range().end as u32, 0) },
633+
..diagnostic.clone()
634+
});
635+
}
636+
}
637+
else if !has_name {
638+
if let Some(diagnostic) = create_diagnostic(session, DiagnosticCode::OLS05060, &[]) {
639+
diagnostics.push(Diagnostic {
640+
range: Range { start: Position::new(node.range().start as u32, 0), end: Position::new(node.range().end as u32, 0) },
641+
..diagnostic.clone()
642+
});
643+
}
644+
}
645+
// Validate children: must be bundle, path, or field
646+
let (mut has_bundle, mut has_path) = (false, false);
647+
for child in node.children().filter(|n| n.is_element()) {
648+
match child.tag_name().name() {
649+
"bundle" => {
650+
has_bundle = true;
651+
for attr in child.attributes() {
652+
if attr.name() != "directive" {
653+
if let Some(diagnostic) = create_diagnostic(session, DiagnosticCode::OLS05061, &[attr.name()]) {
654+
diagnostics.push(Diagnostic {
655+
range: Range { start: Position::new(attr.range().start as u32, 0), end: Position::new(attr.range().end as u32, 0) },
656+
..diagnostic.clone()
657+
});
658+
}
659+
}
660+
}
661+
if child.text().is_none() {
662+
if let Some(diagnostic) = create_diagnostic(session, DiagnosticCode::OLS05066, &[]) {
663+
diagnostics.push(Diagnostic {
664+
range: Range { start: Position::new(child.range().start as u32, 0), end: Position::new(child.range().end as u32, 0) },
665+
..diagnostic.clone()
666+
});
667+
}
668+
}
669+
},
670+
"path" => {
671+
has_path = true;
672+
if child.attributes().count() > 0 {
673+
for attr in child.attributes() {
674+
if let Some(diagnostic) = create_diagnostic(session, DiagnosticCode::OLS05062, &[attr.name()]) {
675+
diagnostics.push(Diagnostic {
676+
range: Range { start: Position::new(attr.range().start as u32, 0), end: Position::new(attr.range().end as u32, 0) },
677+
..diagnostic.clone()
678+
});
679+
}
680+
}
681+
}
682+
if child.text().is_none() {
683+
if let Some(diagnostic) = create_diagnostic(session, DiagnosticCode::OLS05067, &[]) {
684+
diagnostics.push(Diagnostic {
685+
range: Range { start: Position::new(child.range().start as u32, 0), end: Position::new(child.range().end as u32, 0) },
686+
..diagnostic.clone()
687+
});
688+
}
689+
}
690+
},
691+
"field" => {
692+
self.load_field(session, &child, diagnostics);
693+
},
694+
"active" => {},
695+
_ => {
696+
if let Some(diagnostic) = create_diagnostic(session, DiagnosticCode::OLS05063, &[child.tag_name().name()]) {
697+
diagnostics.push(Diagnostic {
698+
range: Range { start: Position::new(child.range().start as u32, 0), end: Position::new(child.range().end as u32, 0) },
699+
..diagnostic.clone()
700+
});
701+
}
702+
}
703+
}
704+
}
705+
if !has_bundle {
706+
if let Some(diagnostic) = create_diagnostic(session, DiagnosticCode::OLS05064, &[]) {
707+
diagnostics.push(Diagnostic {
708+
range: Range { start: Position::new(node.range().start as u32, 0), end: Position::new(node.range().end as u32, 0) },
709+
..diagnostic.clone()
710+
});
711+
}
712+
}
713+
if !has_path {
714+
if let Some(diagnostic) = create_diagnostic(session, DiagnosticCode::OLS05065, &[]) {
715+
diagnostics.push(Diagnostic {
716+
range: Range { start: Position::new(node.range().start as u32, 0), end: Position::new(node.range().end as u32, 0) },
717+
..diagnostic.clone()
718+
});
719+
}
720+
}
721+
let data = OdooData::ASSET(XmlDataAsset {
722+
file_symbol: Rc::downgrade(&self.xml_symbol),
723+
xml_id: found_id.clone().map(|id| oyarn!("{}", id)),
724+
range: node.range().clone(),
725+
});
726+
self.on_operation_creation(session, found_id, node, data, diagnostics);
727+
true
728+
}
606729
}

server/src/core/xml_data.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ pub enum OdooData {
88
RECORD(OdooDataRecord),
99
MENUITEM(XmlDataMenuItem),
1010
TEMPLATE(XmlDataTemplate),
11+
ASSET(XmlDataAsset),
1112
DELETE(XmlDataDelete),
1213
}
1314

@@ -43,6 +44,13 @@ pub struct XmlDataTemplate {
4344
pub range: Range<usize>,
4445
}
4546

47+
#[derive(Debug, Clone)]
48+
pub struct XmlDataAsset {
49+
pub file_symbol: Weak<RefCell<Symbol>>,
50+
pub xml_id: Option<OYarn>,
51+
pub range: Range<usize>,
52+
}
53+
4654
#[derive(Debug, Clone)]
4755
pub struct XmlDataDelete {
4856
pub file_symbol: Weak<RefCell<Symbol>>,
@@ -67,6 +75,9 @@ impl OdooData {
6775
OdooData::DELETE(delete) => {
6876
delete.file_symbol = Rc::downgrade(xml_symbol);
6977
},
78+
OdooData::ASSET(asset) => {
79+
asset.file_symbol = Rc::downgrade(xml_symbol);
80+
}
7081
}
7182
}
7283

@@ -76,6 +87,7 @@ impl OdooData {
7687
OdooData::MENUITEM(menu_item) => menu_item.range.clone(),
7788
OdooData::TEMPLATE(template) => template.range.clone(),
7889
OdooData::DELETE(delete) => delete.range.clone(),
90+
OdooData::ASSET(asset) => asset.range.clone(),
7991
}
8092
}
8193

@@ -103,6 +115,9 @@ impl OdooData {
103115
},
104116
OdooData::DELETE(delete) => {
105117
Some(delete.file_symbol.clone())
118+
},
119+
OdooData::ASSET(asset) => {
120+
Some(asset.file_symbol.clone())
106121
}
107122
}
108123
}

server/src/core/xml_validation.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use std::{cell::RefCell, cmp::Ordering, collections::{HashMap, HashSet}, rc::Rc}
33
use lsp_types::{Diagnostic, Position, Range};
44
use tracing::{info, trace};
55

6-
use crate::{Sy, constants::{BuildSteps, DEBUG_STEPS, OYarn}, core::{diagnostics::{DiagnosticCode, create_diagnostic}, entry_point::{EntryPoint, EntryPointType}, evaluation::ContextValue, file_mgr::FileInfo, model::Model, odoo::SyncOdoo, symbols::symbol::Symbol, xml_data::{OdooData, OdooDataRecord, XmlDataDelete, XmlDataMenuItem, XmlDataTemplate}}, oyarn, threads::SessionInfo, utils::compare_semver};
6+
use crate::{Sy, constants::{BuildSteps, DEBUG_STEPS, OYarn}, core::{diagnostics::{DiagnosticCode, create_diagnostic}, entry_point::{EntryPoint, EntryPointType}, evaluation::ContextValue, file_mgr::FileInfo, model::Model, odoo::SyncOdoo, symbols::symbol::Symbol, xml_data::{OdooData, OdooDataRecord, XmlDataAsset, XmlDataDelete, XmlDataMenuItem, XmlDataTemplate}}, oyarn, threads::SessionInfo, utils::compare_semver};
77

88

99

@@ -67,6 +67,7 @@ impl XmlValidator {
6767
OdooData::MENUITEM(xml_data_menu_item) => self.validate_menu_item(session, module, xml_data_menu_item, diagnostics, dependencies, model_dependencies, missing_model_dependencies),
6868
OdooData::TEMPLATE(xml_data_template) => self.validate_template(session, module, xml_data_template, diagnostics, dependencies, model_dependencies, missing_model_dependencies),
6969
OdooData::DELETE(xml_data_delete) => self.validate_delete(session, module, xml_data_delete, diagnostics, dependencies, model_dependencies, missing_model_dependencies),
70+
OdooData::ASSET(xml_data_asset) => self.validate_asset(session, module, xml_data_asset, diagnostics, dependencies, model_dependencies, missing_model_dependencies),
7071
}
7172
}
7273
fn validate_record(&self, session: &mut SessionInfo, module: &Rc<RefCell<Symbol>>, xml_data_record: &OdooDataRecord, diagnostics: &mut Vec<Diagnostic>, dependencies: &mut Vec<Rc<RefCell<Symbol>>>, model_dependencies: &mut Vec<Rc<RefCell<Model>>>, missing_model_dependencies: &mut HashSet<OYarn>) {
@@ -254,4 +255,8 @@ impl XmlValidator {
254255
fn validate_delete(&self, _session: &mut SessionInfo, _module: &Rc<RefCell<Symbol>>, _xml_data_delete: &XmlDataDelete, _diagnostics: &mut Vec<Diagnostic>, _dependencies: &mut Vec<Rc<RefCell<Symbol>>>, _model_dependencies: &mut Vec<Rc<RefCell<Model>>>, _missing_model_dependencies: &mut HashSet<OYarn>) {
255256

256257
}
258+
259+
fn validate_asset(&self, _session: &mut SessionInfo, _module: &Rc<RefCell<Symbol>>, _xml_data_asset: &XmlDataAsset, _diagnostics: &mut Vec<Diagnostic>, _dependencies: &mut Vec<Rc<RefCell<Symbol>>>, _model_dependencies: &mut Vec<Rc<RefCell<Model>>>, _missing_model_dependencies: &mut HashSet<OYarn>) {
260+
261+
}
257262
}

server/tests/data/addons/module_for_diagnostics/data/bikes.xml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,4 +92,31 @@
9292
<record id="bikes.bike" model="bikes.bike"><field name="fine"/></record> <!-- OLS05057 -->
9393
<record id="bikes.bike" model="ir.ui.view"><field name="model">module_2.empty_model</field></record> <!-- OLS05055 -->
9494
<record id="bikes.bike" model="ir.ui.view"><field name="model">wrong.model</field></record> <!-- OLS05056 -->
95+
<asset invalid="invalid" id="id" name="name"> <!-- OLS05058 -->
96+
<bundle>data</bundle>
97+
<path>ols_tests/tests/something.scss</path>
98+
</asset>
99+
<asset name="no_id"> <!-- OLS05059 -->
100+
<bundle>data</bundle>
101+
<path>ols_tests/tests/something.scss</path>
102+
</asset>
103+
<asset id="no_name"> <!-- OLS05060 -->
104+
<bundle>data</bundle>
105+
<path>ols_tests/tests/something.scss</path>
106+
</asset>
107+
<asset id="id" name="name" active="false">
108+
<bundle invalid_tag="t" directive="directive_is_allowed">data</bundle> <!-- OLS05061 -->
109+
<path invalid_tag="t">ols_tests/tests/something.scss</path> <!-- OLS05062 -->
110+
<invalid /> <!-- OLS05063 -->
111+
</asset>
112+
<asset id="id" name="name" active="false">
113+
<path>ols_tests/tests/something.scss</path> <!-- OLS05064 -->
114+
</asset>
115+
<asset id="id" name="name" active="false">
116+
<bundle>data</bundle> <!-- OLS05065 -->
117+
</asset>
118+
<asset id="id" name="name" active="false">
119+
<bundle></bundle> <!-- OLS05066 -->
120+
<path></path> <!-- OLS05067 -->
121+
</asset>
95122
</odoo>

server/tests/diagnostics/ols05000s.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,16 @@ fn test_ols05000s_xml_file() {
9292
check_xml_diag("OLS05057", 91);
9393
check_xml_diag("OLS05055", 92);
9494
check_xml_diag("OLS05056", 93);
95+
check_xml_diag("OLS05058", 94);
96+
check_xml_diag("OLS05059", 98);
97+
check_xml_diag("OLS05060", 102);
98+
check_xml_diag("OLS05061", 107);
99+
check_xml_diag("OLS05062", 108);
100+
check_xml_diag("OLS05063", 109);
101+
check_xml_diag("OLS05064", 112);
102+
check_xml_diag("OLS05065", 115);
103+
check_xml_diag("OLS05066", 118);
104+
check_xml_diag("OLS05067", 119);
95105
}
96106

97107
#[test]

0 commit comments

Comments
 (0)