Skip to content

Commit

Permalink
[IMP] server: model dependencies on function and use is_in_deps
Browse files Browse the repository at this point in the history
Model dependencies now rebuild based on from_module only, and accept Functions as dependents
  • Loading branch information
fda-odoo committed Jan 24, 2025
1 parent 4a0f139 commit c10c6d8
Show file tree
Hide file tree
Showing 7 changed files with 58 additions and 33 deletions.
21 changes: 10 additions & 11 deletions server/src/core/evaluation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ pub type Context = HashMap<String, ContextValue>;
* diagnostics: a vec the hook can fill to add diagnostics
* file_symbol: if provided, can be used to add dependencies
*/
type GetSymbolHook = fn (session: &mut SessionInfo, eval: &EvaluationSymbol, context: &mut Option<Context>, diagnostics: &mut Vec<Diagnostic>, file_symbol: Option<Rc<RefCell<Symbol>>>) -> EvaluationSymbolWeak;
type GetSymbolHook = fn (session: &mut SessionInfo, eval: &EvaluationSymbol, context: &mut Option<Context>, diagnostics: &mut Vec<Diagnostic>, scope: Option<Rc<RefCell<Symbol>>>) -> EvaluationSymbolWeak;


#[derive(Debug, Clone)]
Expand Down Expand Up @@ -316,7 +316,7 @@ impl Evaluation {
match self.symbol.sym {
EvaluationSymbolPtr::WEAK(_) => {
//take the weak by get_symbol instead of the match
let symbol_eval_weak = self.symbol.get_symbol(session, &mut None, &mut vec![], None);
let symbol_eval_weak = self.symbol.get_symbol(session, &mut None, &mut vec![], Some(function.clone()));
let out_of_scope = Symbol::follow_ref(&symbol_eval_weak, session, &mut None, true, false, Some(function.clone()), &mut vec![]);
for weak_sym in out_of_scope {
if !weak_sym.weak.is_expired() {
Expand Down Expand Up @@ -614,7 +614,7 @@ impl Evaluation {
}
let mut context = Some(base_eval[0].symbol.context.clone());
//TODO context should give params
let base_sym_weak_eval= base_eval[0].symbol.get_symbol(session, &mut context, &mut diagnostics, None);
let base_sym_weak_eval= base_eval[0].symbol.get_symbol(session, &mut context, &mut diagnostics, None); //TODO is parent right? if there is multiple chained evaluation, we should not give it?
let base_sym = base_sym_weak_eval.weak.upgrade();
if let Some(base_sym) = base_sym {
if base_sym.borrow().typ() == SymType::CLASS {
Expand All @@ -629,7 +629,7 @@ impl Evaluation {
if class_eval.len() != 1 {
return AnalyzeAstResult::from_only_diagnostics(diagnostics);
}
let class_sym_weak_eval= class_eval[0].symbol.get_symbol(session, &mut context, &mut diagnostics, None);
let class_sym_weak_eval= class_eval[0].symbol.get_symbol(session, &mut context, &mut diagnostics, Some(parent.clone())); //TODO is parent right? if there is multiple chained evaluation, we should not give it?
class_sym_weak_eval.weak.upgrade().and_then(|class_sym|{
let class_sym_weak_eval = &Symbol::follow_ref(&EvaluationSymbolWeak::new(
Rc::downgrade(&class_sym), None, false
Expand Down Expand Up @@ -660,7 +660,7 @@ impl Evaluation {
}
let object_or_type_weak_eval = &Symbol::follow_ref(
&object_or_type_eval[0].symbol.get_symbol(
session, &mut context, &mut diagnostics, None),
session, &mut context, &mut diagnostics, Some(parent)),
session, &mut None, false, false, None, &mut diagnostics)[0];
is_instance = object_or_type_weak_eval.instance;
}
Expand Down Expand Up @@ -758,7 +758,6 @@ impl Evaluation {
&base_sym.borrow().as_func(),
expr,
context.as_ref().unwrap().get_key_value(&S!("parent")).unwrap_or((&S!(""), &ContextValue::SYMBOL(Weak::new()))).1.as_symbol(),

from_module,
on_instance));
}
Expand All @@ -779,7 +778,7 @@ impl Evaluation {
if base_evals.len() == 0 || (base_evals.len() > 0 && base_evals[0].symbol.get_symbol(session, &mut None, &mut diagnostics, None).weak.is_expired()) {
return AnalyzeAstResult::from_only_diagnostics(diagnostics);
}
let base_ref = base_evals[0].symbol.get_symbol(session, &mut None, &mut diagnostics, Some(parent.borrow().get_file().unwrap().upgrade().unwrap().clone()));
let base_ref = base_evals[0].symbol.get_symbol(session, &mut None, &mut diagnostics, Some(parent.clone()));
let bases = Symbol::follow_ref(&base_ref, session, &mut None, false, false, None, &mut diagnostics);
for ibase in bases.iter() {
let base_loc = ibase.weak.upgrade();
Expand Down Expand Up @@ -834,7 +833,7 @@ impl Evaluation {
if eval_left.len() == 0 || (eval_left.len() > 0 && eval_left[0].symbol.get_symbol(session, &mut None, &mut diagnostics, None).weak.is_expired()) { //TODO set context?
return AnalyzeAstResult::from_only_diagnostics(diagnostics);
}
let base = &eval_left[0].symbol.get_symbol(session, &mut None, &mut diagnostics, None); //TODO set context?
let base = &eval_left[0].symbol.get_symbol(session, &mut None, &mut diagnostics, Some(parent.clone())); //TODO set context?
let bases = Symbol::follow_ref(&base, session, &mut None, false, false, None, &mut diagnostics);
if bases.len() != 1 {
return AnalyzeAstResult::from_only_diagnostics(diagnostics);
Expand All @@ -854,7 +853,7 @@ impl Evaluation {
context.as_mut().unwrap().insert(S!("args"), ContextValue::STRING(value));
let old_range = context.as_mut().unwrap().remove(&S!("range"));
context.as_mut().unwrap().insert(S!("range"), ContextValue::RANGE(sub.slice.range()));
let hook_result = hook(session, &get_item_eval.symbol, context, &mut diagnostics, Some(parent.borrow().get_file().unwrap().upgrade().unwrap().clone()));
let hook_result = hook(session, &get_item_eval.symbol, context, &mut diagnostics, Some(parent.clone()));
if !hook_result.weak.is_expired() {
evals.push(Evaluation::eval_from_symbol(&hook_result.weak, hook_result.instance));
}
Expand Down Expand Up @@ -1209,15 +1208,15 @@ impl EvaluationSymbol {
}
}

pub fn get_symbol(&self, session: &mut SessionInfo, context: &mut Option<Context>, diagnostics: &mut Vec<Diagnostic>, file_symbol: Option<Rc<RefCell<Symbol>>>) -> EvaluationSymbolWeak {
pub fn get_symbol(&self, session: &mut SessionInfo, context: &mut Option<Context>, diagnostics: &mut Vec<Diagnostic>, scope: Option<Rc<RefCell<Symbol>>>) -> EvaluationSymbolWeak {
let mut full_context = self.context.clone();
//extend with local elements
if let Some(context) = context {
full_context.extend(context.clone());
}
if self.get_symbol_hook.is_some() {
let hook = self.get_symbol_hook.unwrap();
return hook(session, self, &mut Some(full_context), diagnostics, file_symbol);
return hook(session, self, &mut Some(full_context), diagnostics, scope);
}
match &self.sym {
EvaluationSymbolPtr::WEAK(w) => {
Expand Down
29 changes: 23 additions & 6 deletions server/src/core/model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ use lsp_types::MessageType;
use weak_table::PtrWeakHashSet;
use std::collections::HashSet;

use crate::constants::BuildStatus;
use crate::constants::BuildSteps;
use crate::constants::SymType;
use crate::threads::SessionInfo;

use super::symbols::module_symbol::ModuleSymbol;
Expand Down Expand Up @@ -79,13 +82,14 @@ impl Model {
}

pub fn add_symbol(&mut self, session: &mut SessionInfo, symbol: Rc<RefCell<Symbol>>) {
self.symbols.insert(symbol);
self.add_dependents_to_validation(session);
self.symbols.insert(symbol.clone());
let from_module = symbol.borrow().find_module();
self.add_dependents_to_validation(session, from_module);
}

pub fn remove_symbol(&mut self, session: &mut SessionInfo, symbol: &Rc<RefCell<Symbol>>) {
pub fn remove_symbol(&mut self, session: &mut SessionInfo, symbol: &Rc<RefCell<Symbol>>, from_module: Option<Rc<RefCell<Symbol>>>) {
self.symbols.remove(symbol);
self.add_dependents_to_validation(session);
self.add_dependents_to_validation(session, from_module);
}

pub fn get_symbols(&self, session: &mut SessionInfo, from_module: Rc<RefCell<Symbol>>) -> impl Iterator<Item= Rc<RefCell<Symbol>>> {
Expand Down Expand Up @@ -149,10 +153,23 @@ impl Model {
self.dependents.insert(symbol.clone());
}

pub fn add_dependents_to_validation(&self, session: &mut SessionInfo) {
pub fn add_dependents_to_validation(&self, session: &mut SessionInfo, module_change: Option<Rc<RefCell<Symbol>>>) {
for dep in self.dependents.iter() {
dep.borrow_mut().invalidate_sub_functions(session);
session.sync_odoo.add_to_validations(dep.clone());
let module = dep.borrow().find_module();
if module_change.is_none() || module.is_none() || ModuleSymbol::is_in_deps(session, &module.as_ref().unwrap(), &module_change.as_ref().unwrap().borrow().as_module_package().dir_name, &mut None) {
let typ = dep.borrow().typ().clone();
match typ {
SymType::FUNCTION => {
dep.borrow_mut().set_build_status(BuildSteps::ARCH_EVAL, BuildStatus::PENDING);
dep.borrow_mut().set_build_status(BuildSteps::ODOO, BuildStatus::PENDING);
session.sync_odoo.add_to_validations(dep.clone());
},
_ => {
session.sync_odoo.add_to_validations(dep.clone());
}
}
}
}
}
}
2 changes: 1 addition & 1 deletion server/src/core/python_arch_eval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -690,7 +690,7 @@ impl PythonArchEval {
let (eval, diags) = Evaluation::eval_from_ast(session, &item.context_expr, parent, &with_stmt.range.start());
let mut evals = vec![];
for eval in eval.iter() {
let symbol = eval.symbol.get_symbol(session, &mut None, &mut self.diagnostics, Some(self.file.clone()));
let symbol = eval.symbol.get_symbol(session, &mut None, &mut self.diagnostics, Some(variable_rc.borrow().parent_file_or_function().unwrap().upgrade().unwrap().clone()));
if let Some(symbol) = symbol.weak.upgrade() {
let _enter_ = symbol.borrow().get_symbol(&(vec![], vec![S!("__enter__")]), u32::MAX);
if let Some(_enter_) = _enter_.last() {
Expand Down
16 changes: 8 additions & 8 deletions server/src/core/python_arch_eval_hooks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -411,7 +411,7 @@ impl PythonArchEvalHooks {
}
}

pub fn eval_env_get_item(session: &mut SessionInfo, evaluation_sym: &EvaluationSymbol, context: &mut Option<Context>, diagnostics: &mut Vec<Diagnostic>, file_symbol: Option<Rc<RefCell<Symbol>>>) -> EvaluationSymbolWeak
pub fn eval_env_get_item(session: &mut SessionInfo, evaluation_sym: &EvaluationSymbol, context: &mut Option<Context>, diagnostics: &mut Vec<Diagnostic>, scope: Option<Rc<RefCell<Symbol>>>) -> EvaluationSymbolWeak
{
if let Some(context) = context {
let arg = context.get(&S!("args"));
Expand All @@ -431,8 +431,8 @@ impl PythonArchEvalHooks {
} else {
from_module = None;
}
if let Some(file_symbol) = file_symbol {
let mut f = file_symbol.borrow_mut();
if let Some(scope) = scope {
let mut f = scope.borrow_mut();
f.add_model_dependencies(model);
}
let model = model.clone();
Expand Down Expand Up @@ -508,14 +508,14 @@ impl PythonArchEvalHooks {
EvaluationSymbolWeak::new(Weak::new(), Some(true), false)
}

pub fn eval_registry_get_item(session: &mut SessionInfo, evaluation_sym: &EvaluationSymbol, context: &mut Option<Context>, diagnostics: &mut Vec<Diagnostic>, file_symbol: Option<Rc<RefCell<Symbol>>>) -> EvaluationSymbolWeak
pub fn eval_registry_get_item(session: &mut SessionInfo, evaluation_sym: &EvaluationSymbol, context: &mut Option<Context>, diagnostics: &mut Vec<Diagnostic>, scope: Option<Rc<RefCell<Symbol>>>) -> EvaluationSymbolWeak
{
let mut result = PythonArchEvalHooks::eval_env_get_item(session, evaluation_sym, context, diagnostics, file_symbol);
let mut result = PythonArchEvalHooks::eval_env_get_item(session, evaluation_sym, context, diagnostics, scope);
result.instance = Some(false);
result
}

fn eval_test_cursor(session: &mut SessionInfo, evaluation_sym: &EvaluationSymbol, context: &mut Option<Context>, diagnostics: &mut Vec<Diagnostic>, file_symbol: Option<Rc<RefCell<Symbol>>>) -> EvaluationSymbolWeak
fn eval_test_cursor(session: &mut SessionInfo, evaluation_sym: &EvaluationSymbol, context: &mut Option<Context>, diagnostics: &mut Vec<Diagnostic>, scope: Option<Rc<RefCell<Symbol>>>) -> EvaluationSymbolWeak
{
if context.is_some() && context.as_ref().unwrap().get(&S!("test_mode")).unwrap_or(&ContextValue::BOOLEAN(false)).as_bool() {
let test_cursor_sym = session.sync_odoo.get_symbol(&(vec![S!("odoo"), S!("sql_db")], vec![S!("TestCursor")]), u32::MAX);
Expand All @@ -528,7 +528,7 @@ impl PythonArchEvalHooks {
evaluation_sym.get_weak().clone()
}

fn eval_get(session: &mut SessionInfo, evaluation_sym: &EvaluationSymbol, context: &mut Option<Context>, diagnostics: &mut Vec<Diagnostic>, file_symbol: Option<Rc<RefCell<Symbol>>>) -> EvaluationSymbolWeak
fn eval_get(session: &mut SessionInfo, evaluation_sym: &EvaluationSymbol, context: &mut Option<Context>, diagnostics: &mut Vec<Diagnostic>, scope: Option<Rc<RefCell<Symbol>>>) -> EvaluationSymbolWeak
{
if context.is_some() {
let parent_instance = context.as_ref().unwrap().get(&S!("parent_instance"));
Expand Down Expand Up @@ -571,7 +571,7 @@ impl PythonArchEvalHooks {
}]);
}

fn eval_relational(session: &mut SessionInfo, evaluation_sym: &EvaluationSymbol, context: &mut Option<Context>, diagnostics: &mut Vec<Diagnostic>, file_symbol: Option<Rc<RefCell<Symbol>>>) -> EvaluationSymbolWeak
fn eval_relational(session: &mut SessionInfo, evaluation_sym: &EvaluationSymbol, context: &mut Option<Context>, diagnostics: &mut Vec<Diagnostic>, scope: Option<Rc<RefCell<Symbol>>>) -> EvaluationSymbolWeak
{
if context.is_none() {
return evaluation_sym.get_symbol(session, &mut None, diagnostics, None);
Expand Down
5 changes: 4 additions & 1 deletion server/src/core/symbols/function_symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ use std::{cell::RefCell, collections::HashMap, rc::{Rc, Weak}};

use lsp_types::Diagnostic;
use ruff_text_size::{TextRange, TextSize};
use weak_table::PtrWeakHashSet;

use crate::{constants::{BuildStatus, BuildSteps, SymType}, core::evaluation::{Context, Evaluation}, threads::SessionInfo};
use crate::{constants::{BuildStatus, BuildSteps, SymType}, core::{evaluation::{Context, Evaluation}, model::Model}, threads::SessionInfo};

use super::{symbol::Symbol, symbol_mgr::{SectionRange, SymbolMgr}};

Expand Down Expand Up @@ -34,6 +35,7 @@ pub struct FunctionSymbol {
pub ast_indexes: Vec<u16>, //list of index to reach the corresponding ast node from file ast
pub diagnostics: HashMap<BuildSteps, Vec<Diagnostic>>, //only temporary used for CLASS and FUNCTION to be collected like others are stored on FileInfo
pub evaluations: Vec<Evaluation>, //Vec, because sometimes a single allocation can be ambiguous, like ''' a = "5" if X else 5 '''
pub model_dependencies: PtrWeakHashSet<Weak<RefCell<Model>>>,
pub weak_self: Option<Weak<RefCell<Symbol>>>,
pub parent: Option<Weak<RefCell<Symbol>>>,
pub arch_status: BuildStatus,
Expand Down Expand Up @@ -75,6 +77,7 @@ impl FunctionSymbol {
arch_eval_status: BuildStatus::PENDING,
odoo_status: BuildStatus::PENDING,
validation_status: BuildStatus::PENDING,
model_dependencies: PtrWeakHashSet::new(),
sections: vec![],
symbols: HashMap::new(),
ext_symbols: HashMap::new(),
Expand Down
10 changes: 8 additions & 2 deletions server/src/core/symbols/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1176,6 +1176,10 @@ impl Symbol {
f.model_dependencies.insert(model.clone());
model.borrow_mut().add_dependent(&self.weak_self().unwrap().upgrade().unwrap());
},
Symbol::Function(f) => {
f.model_dependencies.insert(model.clone());
model.borrow_mut().add_dependent(&self.weak_self().unwrap().upgrade().unwrap());
}
_ => {}
}
}
Expand Down Expand Up @@ -1238,7 +1242,8 @@ impl Symbol {
if let Some(model_data) = &class.borrow().as_class_sym()._model {
let model = session.sync_odoo.models.get(&model_data.name).cloned();
if let Some(model) = model {
model.borrow().add_dependents_to_validation(session);
let from_module = class.borrow().find_module();
model.borrow().add_dependents_to_validation(session, from_module);
}
}
}
Expand Down Expand Up @@ -1281,6 +1286,7 @@ impl Symbol {
if DEBUG_MEMORY && (mut_symbol.typ() == SymType::FILE || matches!(mut_symbol.typ(), SymType::PACKAGE(_))) {
info!("Unloading symbol {:?} at {:?}", mut_symbol.name(), mut_symbol.paths());
}
let module = mut_symbol.find_module();
//unload symbol
let parent = mut_symbol.parent().as_ref().unwrap().upgrade().unwrap().clone();
let mut parent_bw = parent.borrow_mut();
Expand Down Expand Up @@ -1310,7 +1316,7 @@ impl Symbol {
if let Some(model_data) = c._model.as_ref() {
let model = session.sync_odoo.models.get(&model_data.name).cloned();
if let Some(model) = model {
model.borrow_mut().remove_symbol(session, &ref_to_unload);
model.borrow_mut().remove_symbol(session, &ref_to_unload, module);
}
}
},
Expand Down
Loading

0 comments on commit c10c6d8

Please sign in to comment.