Skip to content

Commit 53bff9b

Browse files
mmahroussfda-odoo
authored andcommitted
[IMP] server: add diagnostic for model shadowing
1 parent 7aa664b commit 53bff9b

File tree

2 files changed

+37
-4
lines changed

2 files changed

+37
-4
lines changed

server/src/core/diagnostic_codes_list.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,11 @@ OLS03018, DiagnosticSetting::Error, "Method does not exist on current model",
146146
* Consider marking the modified field with the compute method
147147
*/
148148
OLS03019, DiagnosticSetting::Error, "Compute method not set to modify this field",
149+
/**
150+
* _name is set on a class which creaes a model, but the name is already used by another model.
151+
* Hence, this model is shadowing an existing model.
152+
*/
153+
OLS03020, DiagnosticSetting::Warning, "Model {0} is shadowing an existing model in dependencies",
149154
/**
150155
* A __manifest__.py file should be evaluated with a literal_eval to a single dictionary.
151156
* Do not store any other information in it.

server/src/core/python_odoo_builder.rs

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,13 @@ use std::cmp::Ordering;
22
use std::collections::HashSet;
33
use std::rc::Rc;
44
use std::cell::RefCell;
5-
use lsp_types::notification::ShowMessage;
6-
use lsp_types::MessageType;
75
use ruff_python_ast::Expr;
8-
use lsp_types::{Diagnostic, ShowMessageParams, notification::Notification};
6+
use lsp_types::Diagnostic;
7+
use ruff_text_size::TextRange;
98
use tracing::error;
109
use weak_table::PtrWeakHashSet;
10+
use crate::core::diagnostics::{create_diagnostic, DiagnosticCode};
11+
use crate::core::file_mgr::{FileMgr};
1112

1213
use crate::constants::{OYarn, SymType};
1314
use crate::core::model::{Model, ModelData};
@@ -49,7 +50,34 @@ impl PythonOdooBuilder {
4950
self._add_magic_fields(session);
5051
let model_name = sym.borrow().as_class_sym()._model.as_ref().unwrap().name.clone();
5152
match session.sync_odoo.models.get(&model_name).cloned(){
52-
Some(model) => model.borrow_mut().add_symbol(session, sym.clone()),
53+
Some(model) => {
54+
let inherited_model_names = sym.borrow().as_class_sym()._model.as_ref().unwrap().inherit.clone();
55+
if !inherited_model_names.contains(&model_name)
56+
&& !model.borrow().get_main_symbols(session, sym.borrow().find_module()).is_empty(){
57+
// This a model with a name that already exists in models and in dependencies,
58+
// and it is not inherited, so it is basically shadowing the existing model.
59+
let _name = sym.borrow().get_symbol(&(vec![], vec![Sy!("_name")]), u32::MAX);
60+
if let Some(_name) = _name.last() {
61+
let mut range = _name.borrow().range().clone();
62+
// Try to get the string value range, otherwise stick to _name var range.
63+
if let Some(eval_range) = _name.borrow().evaluations().unwrap().iter().find_map(|e|
64+
match e.follow_ref_and_get_value(session, &mut None, &mut diagnostics) {
65+
Some(EvaluationValue::CONSTANT(Expr::StringLiteral(_))) => e.range,
66+
_ => None,
67+
}
68+
) {
69+
range = TextRange::new(range.start(), eval_range.end());
70+
}
71+
if let Some(diagnostic) = create_diagnostic(&session, DiagnosticCode::OLS03020, &[&model_name]) {
72+
diagnostics.push(Diagnostic {
73+
range: FileMgr::textRange_to_temporary_Range(&range),
74+
..diagnostic
75+
});
76+
}
77+
}
78+
}
79+
model.borrow_mut().add_symbol(session, sym.clone())
80+
},
5381
None => {
5482
let model = Model::new(model_name.clone(), sym.clone());
5583
session.sync_odoo.modules.get("base").map(|module| {

0 commit comments

Comments
 (0)