8000 [IMP] server: load external sources on-the-fly · odoo/odoo-ls@8561425 · GitHub
[go: up one dir, main page]

Skip to content

Commit 8561425

Browse files
committed
[IMP] server: load external sources on-the-fly
1 parent e2e1efe commit 8561425

File tree

3 files changed

+154
-124
lines changed

3 files changed

+154
-124
lines changed

server/src/core/python_arch_eval.rs

Lines changed: 13 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ use lsp_types::{Diagnostic, DiagnosticSeverity, NumberOrString, Position, Range}
99
use tracing::{debug, trace, warn};
1010

1111
use crate::constants::*;
12-
use crate::core::import_resolver::resolve_import_stmt;
1312
use crate::core::odoo::SyncOdoo;
1413
use crate::core::symbols::symbol::Symbol;
1514
use crate::core::evaluation::Evaluation;
@@ -22,9 +21,9 @@ use super::config::DiagMissingImportsMode;
2221
use super::entry_point::EntryPoint;
2322
use super::evaluation::{ContextValue, EvaluationSymbolPtr, EvaluationSymbolWeak};
2423
use super::file_mgr::FileMgr;
25-
use super::import_resolver::ImportResult;
2624
use super::python_arch_eval_hooks::PythonArchEvalHooks;
2725
use super::symbols::function_symbol::FunctionSymbol;
26+
use super::symbols::variable_symbol::{ImportInformation, VariableSymbol};
2827

2928

3029
#[derive(Debug, Clone)]
@@ -179,122 +178,25 @@ impl PythonArchEval {
179178
}
180179
}
181180

182-
fn _match_diag_config(&self, odoo: &mut SyncOdoo, symbol: &Rc<RefCell<Symbol>>) -> bool {
183-
let import_diag_level = &odoo.config.diag_missing_imports;
184-
if *import_diag_level == DiagMissingImportsMode::None {
185-
return false
186-
}
187-
if *import_diag_level == DiagMissingImportsMode::All {
188-
return true
189-
}
190-
if *import_diag_level == DiagMissingImportsMode::OnlyOdoo {
191-
let tree = symbol.borrow().get_tree();
192-
if tree.0.len() > 0 && tree.0[0] == "odoo" {
193-
return true;
194-
}
195-
}
196-
false
197-
}
198-
199-
///Follow the evaluations of sym_ref, evaluate files if needed, and return true if the end evaluation contains from_sym
200-
fn check_for_loop_evaluation(&mut self, session: &mut SessionInfo, sym_ref: Rc<RefCell<Symbol>>, from_sym: &Rc<RefCell<Symbol>>) -> bool {
201-
let sym_ref_cl = sym_ref.clone();
202-
let syms_followed = Symbol::follow_ref(&EvaluationSymbolPtr::WEAK(EvaluationSymbolWeak::new(
203-
Rc::downgrade(&sym_ref_cl), None, false
204-
)), session, &mut None, false, false, None, &mut self.diagnostics);
205-
for sym in syms_followed.iter() {
206-
let sym = sym.upgrade_weak();
207-
if let Some(sym) = sym {
208-
if sym.borrow().evaluations().is_some() && sym.borrow().evaluations().unwrap().is_empty() {
209-
let file_sym = sym_ref.borrow().get_file();
210-
if file_sym.is_some() {
211-
let rc_file_sym = file_sym.as_ref().unwrap().upgrade().unwrap();
212-
if rc_file_sym.borrow_mut().build_status(BuildSteps::ARCH_EVAL) == BuildStatus::PENDING && session.sync_odoo.is_in_rebuild(&rc_file_sym, BuildSteps::ARCH_EVAL) {
213-
session.sync_odoo.remove_from_rebuild_arch_eval(&rc_file_sym);
214-
let mut builder = PythonArchEval::new(self.entry_point.clone(), rc_file_sym);
215-
builder.eval_arch(session);
216-
if self.check_for_loop_evaluation(session, sym_ref.clone(), from_sym) {
217-
return true;
218-
}
219-
}
220-
}
221-
}
222-
if Rc::ptr_eq(&sym, &from_sym) {
223-
return true;
224-
}
225-
}
226-
}
227-
false
228-
}
229-
230181
fn eval_symbols_from_import_stmt(&mut self, session: &mut SessionInfo, from_stmt: Option<&Identifier>, name_aliases: &[Alias], level: Option<u32>, range: &TextRange) {
231182
if name_aliases.len() == 1 && name_aliases[0].name.to_string() == "*" {
232183
return;
233184
}
234-
let import_results: Vec<ImportResult> = resolve_import_stmt(
235-
session,
236-
&self.file,
237-
from_stmt,
238-
name_aliases,
239-
level,
240-
&mut Some(&mut self.diagnostics));
241-
242-
for _import_result in import_results.iter() {
243-
let variable = self.sym_stack.last().unwrap().borrow_mut().get_positioned_symbol(&_import_result.name, &_import_result.range);
185+
for alias in name_aliases {
186+
let var_name = alias.asname.as_ref().unwrap_or(&alias.name).to_string().clone();
187+
let variable = self.sym_stack.last().unwrap().borrow_mut().get_positioned_symbol(&var_name, &alias.range);
244188
let Some(variable) = variable.clone() else {
245189
continue;
246190
};
247-
if _import_result.found {
248-
let import_sym_ref = _import_result.symbol.clone();
249-
let has_loop = self.check_for_loop_evaluation(session, import_sym_ref, &variable);
250-
if !has_loop { //anti-loop. We want to be sure we are not evaluating to the same sym
251-
variable.borrow_mut().set_evaluations(vec![Evaluation::eval_from_symbol(&Rc::downgrade(&_import_result.symbol), None)]);
252-
let file_of_import_symbol = _import_result.symbol.borrow().get_file();
253-
if let Some(import_file) = file_of_import_symbol {
254-
let import_file = import_file.upgrade().unwrap();
255-
if !Rc::ptr_eq(&self.file, &import_file) {
256-
self.file.borrow_mut().add_dependency(&mut import_file.borrow_mut(), self.current_step, BuildSteps::ARCH);
257-
}
258-
}
259-
} else {
260-
let mut file_tree = [_import_result.file_tree.0.clone(), _import_result.file_tree.1.clone()].concat();
261-
file_tree.extend(_import_result.name.split(".").map(str::to_string));
262-
self.file.borrow_mut().not_found_paths_mut().push((self.current_step, file_tree.clone()));
263-
self.entry_point.borrow_mut().not_found_symbols.insert(self.file.clone());
264-
if self._match_diag_config(session.sync_odoo, &_import_result.symbol) {
265-
self.diagnostics.push(Diagnostic::new(
266-
Range::new(Position::new(_import_result.range.start().to_u32(), 0), Position::new(_import_result.range.end().to_u32(), 0)),
267-
Some(DiagnosticSeverity::WARNING),
268-
Some(NumberOrString::String(S!("OLS20004"))),
269-
Some(EXTENSION_NAME.to_string()),
270-
format!("Failed to evaluate import {}", file_tree.clone().join(".")),
271-
None,
272-
None,
273-
));
274-
}
275-
}
276-
277-
} else {
278-
let mut file_tree = [_import_result.file_tree.0.clone(), _import_result.file_tree.1.clone()].concat();
279-
file_tree.extend(_import_result.name.split(".").map(str::to_string));
280-
if BUILT_IN_LIBS.contains(&file_tree[0].as_str()) {
281-
continue;
282-
}
283-
if !self.safe_import.last().unwrap() {
284-
self.file.borrow_mut().not_found_paths_mut().push((self.current_step, file_tree.clone()));
285-
self.entry_point.borrow_mut().not_found_symbols.insert(self.file.clone());
286-
if self._match_diag_config(session.sync_odoo, &_import_result.symbol) {
287-
self.diagnostics.push(Diagnostic::new(
288-
Range::new(Position::new(_import_result.range.start().to_u32(), 0), Position::new(_import_result.range.end().to_u32(), 0)),
289-
Some(DiagnosticSeverity::WARNING),
290-
Some(NumberOrString::String(S!("OLS20001"))),
291-
Some(EXTENSION_NAME.to_string()),
292-
format!("{} not found", file_tree.clone().join(".")),
293-
None,
294-
None,
295-
));
296-
}
297-
}
191+
variable.borrow_mut().as_variable_mut().import_information = Some(ImportInformation {
192+
from: from_stmt.cloned(),
193+
level: level,
194+
alias: alias.clone(),
195+
import_step: self.current_step.clone()
196+
});
197+
//In workspace we evaluate imports as we want to raise diagnostics if not found. If outside of the workspace, let's keep only information to lazy load them
198+
if self.file.borrow().in_workspace() || !self.file.borrow().is_external() {
199+
VariableSymbol::load_from_import_information(session, variable, &self.file, &self.entry_point, &mut self.diagnostics);
298200
}
299201
}
300202
}

server/src/core/symbols/symbol.rs

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1716,11 +1716,10 @@ impl Symbol {
17161716
pub fn next_refs(session: &mut SessionInfo, symbol_rc: Rc<RefCell<Symbol>>, context: &mut Option<Context>, symbol_context: &Context, stop_on_type: bool, diagnostics: &mut Vec<Diagnostic>) -> VecDeque<EvaluationSymbolPtr> {
17171717
//if current symbol is a descriptor, we have to resolve __get__ method before going further
17181718
let mut res = VecDeque::new();
1719-
let symbol = &*symbol_rc.borrow();
17201719
if let Some(base_attr) = symbol_context.get(&S!("base_attr")) {
17211720
let base_attr = base_attr.as_symbol().upgrade();
17221721
if let Some(base_attr) = base_attr {
1723-
let attribute_type_sym = symbol;
1722+
let attribute_type_sym = &*symbol_rc.borrow();
17241723
//TODO shouldn't we set the from_module in the call to get_member_symbol?
17251724
let get_method = attribute_type_sym.get_member_symbol(session, &S!("__get__"), None, true, false, true, false).0.first().cloned();
17261725
match get_method {
@@ -1758,7 +1757,16 @@ impl Symbol {
17581757
}
17591758
}
17601759
}
1761-
if let Symbol::Variable(v) = symbol {
1760+
let symbol_type = symbol_rc.borrow().typ().clone();
1761 F438 +
if symbol_type == SymType::VARIABLE {
1762+
if symbol_rc.borrow().as_variable().is_import_variable.clone() {
1763+
let file = symbol_rc.borrow().get_file().unwrap().clone();
1764+
let file = file.upgrade().expect("invalid weak value");
1765+
let entry_point = file.borrow().get_entry().unwrap();
1766+
VariableSymbol::load_from_import_information(session, symbol_rc.clone(), &file, &entry_point, diagnostics);
1767+
}
1768+
}
1769+
if let Symbol::Variable(v) = &*symbol_rc.borrow() {
17621770
for eval in v.evaluations.iter() {
17631771
let ctx = &mut Some(symbol_context.clone().into_iter().chain(context.clone().unwrap_or(HashMap::new()).into_iter()).collect::<HashMap<_, _>>());
17641772
let mut sym = eval.symbol.get_symbol(session, ctx, diagnostics, None);
@@ -1816,21 +1824,21 @@ impl Symbol {
18161824
continue;
18171825
}
18181826
let sym_rc = sym.unwrap();
1819-
let sym = sym_rc.borrow();
1820-
match *sym {
1821-
Symbol::Variable(ref v) => {
1822-
if stop_on_type && matches!(next_ref_weak.is_instance(), Some(false)) && !v.is_import_variable {
1827+
let sym_type = sym_rc.borrow().typ();
1828+
match sym_type {
1829+
SymType::VARIABLE => {
1830+
if stop_on_type && matches!(next_ref_weak.is_instance(), Some(false)) && !sym_rc.borrow().as_variable().is_import_variable {
18231831
continue;
18241832
}
1825-
if stop_on_value && v.evaluations.len() == 1 && v.evaluations[0].value.is_some() {
1833+
if stop_on_value && sym_rc.borrow().as_variable().evaluations.len() == 1 && sym_rc.borrow().as_variable().evaluations[0].value.is_some() {
18261834
continue;
18271835
}
1828-
if max_scope.is_some() && !sym.has_rc_in_parents(max_scope.as_ref().unwrap().clone(), true) {
1836+
if max_scope.is_some() && !sym_rc.borrow().has_rc_in_parents(max_scope.as_ref().unwrap().clone(), true) {
18291837
continue;
18301838
}
1831-
if v.evaluations.is_empty() && can_eval_external {
1839+
if sym_rc.borrow().as_variable().evaluations.is_empty() && can_eval_external {
18321840
//no evaluation? let's check that the file has been evaluated
1833-
let file_symbol = sym.get_file();
1841+
let file_symbol = sym_rc.borrow().get_file();
18341842
if let Some(file_symbol) = file_symbol {
18351843
if file_symbol.upgrade().expect("invalid weak value").borrow().build_status(BuildSteps::ARCH) == BuildStatus::PENDING &&
18361844
session.sync_odoo.is_in_rebuild(&file_symbol.upgrade().unwrap(), BuildSteps::ARCH_EVAL) { //TODO check ARCH ?
@@ -1849,7 +1857,7 @@ impl Symbol {
18491857
}
18501858
}
18511859
},
1852-
Symbol::Class(_) => {
1860+
SymType::CLASS => {
18531861
//On class, follow descriptor declarations
18541862
let next_sym_refs = Symbol::next_refs(session, sym_rc.clone(), context, &next_ref_weak.context, stop_on_type, &mut vec![]);
18551863
if !next_sym_refs.is_empty() {
@@ -2121,6 +2129,7 @@ impl Symbol {
21212129
pub fn is_field(&self, session: &mut SessionInfo) -> bool {
21222130
match self.typ() {
21232131
SymType::VARIABLE => {
2132+
//TODO resolve lazy loading
21242133
if let Some(evals) = self.evaluations().as_ref() {
21252134
for eval in evals.iter() {
21262135
let symbol = eval.symbol.get_symbol(session, &mut None, &mut vec![], None);
@@ -2154,6 +2163,7 @@ impl Symbol {
21542163
pub fn is_specific_field(&self, session: &mut SessionInfo, field_names: &[&str]) -> bool {
21552164
match self.typ() {
21562165
SymType::VARIABLE => {
2166+
//TODO resolve lazy loading
21572167
if let Some(evals) = self.evaluations().as_ref() {
21582168
for eval in evals.iter() {
21592169
let symbol = eval.symbol.get_symbol(session, &mut None, &mut vec![], None);

0 commit comments

Comments
 (0)
0