Skip to content

Commit 712415f

Browse files
mmahroussfda-odoo
authored andcommitted
[FIX] server: adapt all_members to be correct
1 parent feed9f2 commit 712415f

File tree

4 files changed

+134
-93
lines changed

4 files changed

+134
-93
lines changed

server/src/core/model.rs

Lines changed: 60 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -208,22 +208,73 @@ impl Model {
208208
} else {
209209
symbols.push((s.clone(), None));
210210
}
211-
if with_inheritance { //TODO wrong, should be recursive
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-
}
211+
if !with_inheritance {
212+
continue;
213+
}
214+
let inherited_models = s.borrow().as_class_sym()._model.as_ref().unwrap().inherit.clone();
215+
for inherited_model in inherited_models.iter() {
216+
if !seen_inherited_models.contains(inherited_model) {
217+
seen_inherited_models.insert(inherited_model.clone());
218+
if let Some(model) = session.sync_odoo.models.get(inherited_model).cloned() {
219+
symbols.extend(model.borrow().all_symbols_helper(session, from_module.clone(), true, seen_inherited_models));
220220
}
221221
}
222222
}
223223
}
224224
symbols
225225
}
226226

227+
pub fn all_symbols_inherits(&self, session: &mut SessionInfo, from_module: Option<Rc<RefCell<Symbol>>>) -> (Vec<(Rc<RefCell<Symbol>>, Option<OYarn>)>, Vec<(Rc<RefCell<Symbol>>, Option<OYarn>)>) {
228+
let mut visited_models = HashSet::new();
229+
self.all_inherits_helper(session, from_module, &mut visited_models)
230+
}
231+
232+
fn all_inherits_helper(&self, session: &mut SessionInfo, from_module: Option<Rc<RefCell<Symbol>>>, visited_models: &mut HashSet<String>) -> (Vec<(Rc<RefCell<Symbol>>, Option<OYarn>)>, Vec<(Rc<RefCell<Symbol>>, Option<OYarn>)>) {
233+
if visited_models.contains(&self.name) {
234+
return (Vec::new(), Vec::new());
235+
}
236+
visited_models.insert(self.name.clone());
237+
let mut symbols = Vec::new();
238+
let mut inherits_symbols = Vec::new();
239+
for s in self.symbols.iter() {
240+
if let Some(from_module) = from_module.as_ref() {
241+
let module = s.borrow().find_module();
242+
if let Some(module) = module {
243+
if ModuleSymbol::is_in_deps(session, &from_module, &module.borrow().as_module_package().dir_name) {
244+
symbols.push((s.clone(), None));
245+
} else {
246+
symbols.push((s.clone(), Some(module.borrow().as_module_package().dir_name.clone())));
247+
}
248+
} else {
249+
session.log_message(MessageType::WARNING, "A model should be declared in a module.".to_string());
250+
}
251+
} else {
252+
symbols.push((s.clone(), None));
253+
}
254+
// First get results from normal inherit
255+
// To make sure we visit all of inherit before inherits, since it is DFS
256+
// Only inherits in the tree that are not already visited will be processed in the next iteration
257+
let inherited_models = s.borrow().as_class_sym()._model.as_ref().unwrap().inherit.clone();
258+
for inherited_model in inherited_models.iter() {
259+
if let Some(model) = session.sync_odoo.models.get(inherited_model).cloned() {
260+
let (main_result, inherits_result) = model.borrow().all_inherits_helper(session, from_module.clone(), visited_models);
261+
symbols.extend(main_result);
262+
inherits_symbols.extend(inherits_result);
263+
}
264+
}
265+
for (inherits_model, _) in s.borrow().as_class_sym()._model.as_ref().unwrap().inherits.clone() {
266+
if let Some(model) = session.sync_odoo.models.get(&inherits_model).cloned() {
267+
let (main_result, inherits_result) = model.borrow().all_inherits_helper(session, from_module.clone(), visited_models);
268+
// Everything that is in inherits should be added to inherits_symbols, regardless of whether
269+
// it was in inherit or inherits. Since we need that distinction to later only get fields
270+
inherits_symbols.extend(main_result);
271+
inherits_symbols.extend(inherits_result);
272+
}
273+
}
274+
}
275+
(symbols, inherits_symbols)
276+
}
277+
227278
pub fn add_dependent(&mut self, symbol: &Rc<RefCell<Symbol>>) {
228279
self.dependents.insert(symbol.clone());
229280
}

server/src/core/python_odoo_builder.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -198,8 +198,7 @@ impl PythonOdooBuilder {
198198
drop(_inherits);
199199
drop(symbol);
200200
//Add inherits from delegate=True from fields
201-
let mut all_fields = HashMap::new();
202-
Symbol::all_members(&self.symbol, session, &mut all_fields, false, true, false, None, &mut None, false);
201+
let all_fields = Symbol::all_members(&self.symbol, session, false, true, false, None, false);
203202
for (field_name, symbols) in all_fields.iter() {
204203
for (symbol, _deps) in symbols.iter() {
205204
if let Some(evals) = symbol.borrow().evaluations() {

server/src/core/symbols/symbol.rs

Lines changed: 71 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -2214,30 +2214,30 @@ impl Symbol {
22142214
let mut iter: Vec<Rc<RefCell<Symbol>>> = Vec::new();
22152215
match self {
22162216
Symbol::File(_) => {
2217-
for symbol in self.iter_symbols().flat_map(|(name, hashmap)| hashmap.into_iter().flat_map(|(_, vec)| vec.clone())) {
2217+
for symbol in self.iter_symbols().flat_map(|(_, hashmap)| hashmap.into_iter().flat_map(|(_, vec)| vec.clone())) {
22182218
iter.push(symbol.clone());
22192219
}
22202220
},
22212221
Symbol::Class(_) => {
2222-
for symbol in self.iter_symbols().flat_map(|(name, hashmap)| hashmap.into_iter().flat_map(|(_, vec)| vec.clone())) {
2222+
for symbol in self.iter_symbols().flat_map(|(_, hashmap)| hashmap.into_iter().flat_map(|(_, vec)| vec.clone())) {
22232223
iter.push(symbol.clone());
22242224
}
22252225
},
22262226
Symbol::Function(_) => {
2227-
for symbol in self.iter_symbols().flat_map(|(name, hashmap)| hashmap.iter().flat_map(|(_, vec)| vec.clone())) {
2227+
for symbol in self.iter_symbols().flat_map(|(_, hashmap)| hashmap.iter().flat_map(|(_, vec)| vec.clone())) {
22282228
iter.push(symbol.clone());
22292229
}
22302230
},
22312231
Symbol::Package(PackageSymbol::Module(m)) => {
2232-
for symbol in self.iter_symbols().flat_map(|(name, hashmap)| hashmap.iter().flat_map(|(_, vec)| vec.clone())) {
2232+
for symbol in self.iter_symbols().flat_map(|(_, hashmap)| hashmap.iter().flat_map(|(_, vec)| vec.clone())) {
22332233
iter.push(symbol.clone());
22342234
}
22352235
for symbol in m.module_symbols.values().cloned() {
22362236
iter.push(symbol.clone());
22372237
}
22382238
},
22392239
Symbol::Package(PackageSymbol::PythonPackage(p)) => {
2240-
for symbol in self.iter_symbols().flat_map(|(name, hashmap)| hashmap.iter().flat_map(|(_, vec)| vec.clone())) {
2240+
for symbol in self.iter_symbols().flat_map(|(_, hashmap)| hashmap.iter().flat_map(|(_, vec)| vec.clone())) {
22412241
iter.push(symbol.clone());
22422242
}
22432243
for symbol in p.module_symbols.values().cloned() {
@@ -2261,77 +2261,81 @@ impl Symbol {
22612261

22622262
//store in result all available members for symbol: sub symbols, base class elements and models symbols
22632263
//TODO is order right of Vec in HashMap? if we take first or last in it, do we have the last effective value?
2264-
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) {
2265-
if acc.is_none() {
2266-
*acc = Some(HashSet::new());
2267-
}
2264+
pub fn all_members(
2265+
symbol: &Rc<RefCell<Symbol>>,
2266+
session: &mut SessionInfo,
2267+
with_co_models: bool,
2268+
only_fields: bool,
2269+
only_methods: bool,
2270+
from_module: Option<Rc<RefCell<Symbol>>>,
2271+
is_super: bool) -> HashMap<OYarn, Vec<(Rc<RefCell<Symbol>>, Option<OYarn>)>>{
2272+
let mut result: HashMap<OYarn, Vec<(Rc<RefCell<Symbol>>, Option<OYarn>)>> = HashMap::new();
2273+
let mut acc: HashSet<Tree> = HashSet::new();
2274+
Symbol::_all_members(symbol, session, &mut result, with_co_models, only_fields, only_methods, from_module, &mut acc, is_super);
2275+
return result;
2276+
}
2277+
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 HashSet<Tree>, is_super: bool) {
22682278
let tree = symbol.borrow().get_tree();
2269-
if acc.as_mut().unwrap().contains(&tree) {
2279+
if acc.contains(&tree) {
22702280
return;
22712281
}
2272-
acc.as_mut().unwrap().insert(tree);
2282+
acc.insert(tree);
2283+
let mut append_result = |symbol: Rc<RefCell<Symbol>>, dep: Option<OYarn>| {
2284+
let name = symbol.borrow().name().clone();
2285+
if let Some(vec) = result.get_mut(&name) {
2286+
vec.push((symbol, dep));
2287+
} else {
2288+
result.insert(name.clone(), vec![(symbol, dep)]);
2289+
}
2290+
};
22732291
let typ = symbol.borrow().typ();
22742292
match typ {
22752293
SymType::CLASS => {
22762294
// Skip current class symbols for super
22772295
if !is_super{
22782296
for symbol in symbol.borrow().all_symbols() {
2279-
if only_fields && !symbol.borrow().is_field(session){
2297+
if (only_fields && !symbol.borrow().is_field(session)) || (only_methods && symbol.borrow().typ() != SymType::FUNCTION) {
22802298
continue;
22812299
}
2282-
if only_methods && symbol.borrow().typ() != SymType::FUNCTION {
2283-
continue;
2284-
}
2285-
let name = symbol.borrow().name().clone();
2286-
if let Some(vec) = result.get_mut(&name) {
2287-
vec.push((symbol, None));
2288-
} else {
2289-
result.insert(name.clone(), vec![(symbol, None)]);
2290-
}
2300+
append_result(symbol, None);
22912301
}
22922302
}
2303+
let mut bases: PtrWeakHashSet<Weak<RefCell<Symbol>>> = PtrWeakHashSet::new();
2304+
symbol.borrow().as_class_sym().bases.iter().for_each(|base| {
2305+
base.upgrade().map(|b| bases.insert(b));
2306+
});
22932307
if with_co_models {
2294-
let sym = symbol.borrow();
2295-
let model_data = sym.as_class_sym()._model.as_ref();
2296-
if let Some(model_data) = model_data {
2297-
if let Some(model) = session.sync_odoo.models.get(&model_data.name).cloned() {
2298-
for (model_sym, dependency) in model.borrow().all_symbols(session, from_module.clone(), true) {
2299-
if dependency.is_none() && !Rc::ptr_eq(symbol, &model_sym) {
2300-
for s in model_sym.borrow().all_symbols() {
2301-
if only_fields && !s.borrow().is_field(session){
2302-
continue;
2303-
}
2304-
if only_methods && symbol.borrow().typ() != SymType::FUNCTION{
2305-
continue;
2306-
}
2307-
let name = s.borrow().name().clone();
2308-
if let Some(vec) = result.get_mut(&name) {
2309-
vec.push((s, Some(model_sym.borrow().name().clone())));
2310-
} else {
2311-
result.insert(name.clone(), vec![(s, Some(model_sym.borrow().name().clone()))]);
2312-
}
2313-
}
2314-
//add fields from _inherits
2315-
if let Some(model_data) = model_sym.borrow().as_class_sym()._model.as_ref() {
2316-
for (inherits_model, inherits_field) in model_data.inherits.iter() {
2317-
let inherits_model_sym = session.sync_odoo.models.get(inherits_model).cloned();
2318-
if let Some(inherits_model_sym) = inherits_model_sym {
2319-
for (model_symbol, deps) in inherits_model_sym.borrow().all_symbols(session, from_module.clone(), true).iter().filter(|(x, deps)| deps.is_none()) {
2320-
for (field_name, field_symbols) in Symbol::all_fields(&model_symbol, session, from_module.clone()) {
2321-
for (s, deps) in field_symbols.iter().filter(|(x, deps)| deps.is_none()) {
2322-
if let Some(vec) = result.get_mut(&field_name) {
2323-
vec.push((s.clone(), Some(model_sym.borrow().name().clone())));
2324-
} else {
2325-
result.insert(field_name.clone(), vec![(s.clone(), Some(model_sym.borrow().name().clone()))]);
2326-
}
2327-
}
2328-
}
2329-
}
2330-
}
2331-
}
2332-
}
2333-
}
2308+
let Some(model) = symbol.borrow().as_class_sym()._model.as_ref().and_then(|model_data|
2309+
session.sync_odoo.models.get(&model_data.name).cloned()
2310+
) else {
2311+
return;
2312+
};
2313+
// no recursion because it is handled in all_symbols_inherits
2314+
let (model_symbols, model_inherits_symbols) = model.borrow().all_symbols_inherits(session, from_module.clone());
2315+
for (model_sym, dependency) in model_symbols {
2316+
if dependency.is_some() || Rc::ptr_eq(symbol, &model_sym) {
2317+
continue;
2318+
}
2319+
model_sym.borrow().as_class_sym().bases.iter().for_each(|base| {
2320+
base.upgrade().map(|b| bases.insert(b));
2321+
});
2322+
for s in model_sym.borrow().all_symbols() {
2323+
if (only_fields && !s.borrow().is_field(session)) || (only_methods && s.borrow().typ() != SymType::FUNCTION) {
2324+
continue;
23342325
}
2326+
append_result(s, Some(model_sym.borrow().name().clone()));
2327+
}
2328+
}
2329+
for (model_sym, dependency) in model_inherits_symbols {
2330+
if dependency.is_some() || Rc::ptr_eq(symbol, &model_sym) {
2331+
continue;
2332+
}
2333+
model_sym.borrow().as_class_sym().bases.iter().for_each(|base| {
2334+
base.upgrade().map(|b| bases.insert(b));
2335+
});
2336+
// for inherits symbols, we only add fields
2337+
for s in model_sym.borrow().all_symbols().filter(|s| s.borrow().is_field(session)) {
2338+
append_result(s, Some(model_sym.borrow().name().clone()));
23352339
}
23362340
}
23372341
}
@@ -2340,23 +2344,14 @@ impl Symbol {
23402344
//no comodel as we will search for co-model from original class (what about overrided _name?)
23412345
//TODO what about base of co-models classes?
23422346
if let Some(base) = base.upgrade() {
2343-
Symbol::all_members(&base, session, result, false, only_fields, only_methods, from_module.clone(), acc, false);
2347+
Symbol::_all_members(&base, session, result, false, only_fields, only_methods, from_module.clone(), acc, false);
23442348
}
23452349
}
23462350
},
2347-
_ => {
2348-
for symbol in symbol.borrow().all_symbols() {
2349-
if only_fields && !symbol.borrow().is_field(session){
2350-
continue;
2351-
}
2352-
let name = symbol.borrow().name().clone();
2353-
if let Some(vec) = result.get_mut(&name) {
2354-
vec.push((symbol, None));
2355-
} else {
2356-
result.insert(name.clone(), vec![(symbol, None)]);
2357-
}
2358-
}
2359-
}
2351+
// if not class just add it to result
2352+
_ => symbol.borrow().all_symbols().for_each(|s|
2353+
if !(only_fields && !s.borrow().is_field(session)) {append_result(s, None)}
2354+
)
23602355
}
23612356
}
23622357

@@ -2634,9 +2629,7 @@ impl Symbol {
26342629
}
26352630

26362631
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>)>> {
2637-
let mut all_fields = HashMap::new();
2638-
Symbol::all_members(symbol, session, &mut all_fields, true, true, false, from_module.clone(), &mut None, false);
2639-
all_fields
2632+
Symbol::all_members(symbol, session, true, true, false, from_module.clone(), false)
26402633
}
26412634

26422635
/* similar to get_symbol: will return the symbol that is under this one with the specified name.

server/src/features/completion.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -941,8 +941,7 @@ fn add_nested_field_names(
941941
}
942942
if let Some(object) = &obj {
943943
if index == split_expr.len() - 1 {
944-
let mut all_symbols: HashMap<OYarn, Vec<(Rc<RefCell<Symbol>>, Option<OYarn>)>> = HashMap::new();
945-
Symbol::all_members(&object, session, &mut all_symbols, true, true, false, from_module.clone(), &mut None, false);
944+
let all_symbols = Symbol::all_members(&object, session, true, true, false, from_module.clone(), false);
946945
for (_symbol_name, symbols) in all_symbols {
947946
//we could use symbol_name to remove duplicated names, but it would hide functions vs variables
948947
if _symbol_name.starts_with(name) {
@@ -1000,8 +999,7 @@ fn add_model_attributes(
1000999
only_methods: bool,
10011000
attribute_name: &str
10021001
){
1003-
let mut all_symbols: HashMap<OYarn, Vec<(Rc<RefCell<Symbol>>, Option<OYarn>)>> = HashMap::new();
1004-
Symbol::all_members(&parent_sym, session, &mut all_symbols, true, only_fields, only_methods, from_module.clone(), &mut None, is_super);
1002+
let all_symbols = Symbol::all_members(&parent_sym, session, true, only_fields, only_methods, from_module.clone(), is_super);
10051003
for (_symbol_name, symbols) in all_symbols {
10061004
//we could use symbol_name to remove duplicated names, but it would hide functions vs variables
10071005
if _symbol_name.starts_with(attribute_name) {

0 commit comments

Comments
 (0)