Skip to content

Commit 69cf49c

Browse files
committed
[IMP] refactor definition to get symbol and build location by after
1 parent a741d53 commit 69cf49c

File tree

1 file changed

+111
-84
lines changed

1 file changed

+111
-84
lines changed

server/src/features/definition.rs

Lines changed: 111 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,30 @@ use crate::core::file_mgr::{FileInfo, FileMgr};
1010
use crate::core::odoo::SyncOdoo;
1111
use crate::core::python_odoo_builder::MAGIC_FIELDS;
1212
use crate::core::symbols::symbol::Symbol;
13+
use crate::core::xml_data::OdooData;
1314
use crate::features::ast_utils::AstUtils;
1415
use crate::features::features_utils::FeaturesUtils;
1516
use crate::features::xml_ast_utils::{XmlAstResult, XmlAstUtils};
1617
use crate::{S, oyarn};
1718
use crate::threads::SessionInfo;
1819
use crate::utils::PathSanitizer as _;
1920

21+
pub enum DefinitionSourceType {
22+
Symbol(Rc<RefCell<Symbol>>),
23+
OdooData(OdooData),
24+
Module(Rc<RefCell<Symbol>>),
25+
}
26+
27+
pub struct DefinitionSource {
28+
source: DefinitionSourceType,
29+
origin_selection_range: Option<Range>,
30+
}
31+
2032
pub struct DefinitionFeature {}
2133

2234
impl DefinitionFeature {
2335

24-
fn check_for_domain_field(session: &mut SessionInfo, eval: &Evaluation, file_symbol: &Rc<RefCell<Symbol>>, call_expr: &Option<ExprCall>, offset: usize, links: &mut Vec<LocationLink>) -> bool {
36+
fn check_for_domain_field(session: &mut SessionInfo, eval: &Evaluation, file_symbol: &Rc<RefCell<Symbol>>, call_expr: &Option<ExprCall>, offset: usize, sources: &mut Vec<DefinitionSource>) -> bool {
2537
let (field_name, field_range) = if let Some(eval_value) = eval.value.as_ref() {
2638
if let EvaluationValue::CONSTANT(Expr::StringLiteral(expr)) = eval_value {
2739
(expr.value.to_string(), expr.range)
@@ -36,22 +48,21 @@ impl DefinitionFeature {
3648
let string_domain_fields = FeaturesUtils::find_argument_symbols(
3749
session, Symbol::get_scope_symbol(file_symbol.clone(), offset as u32, false), module, &field_name, call_expr, offset, field_range
3850
);
51+
let mut domain_found = false;
3952
string_domain_fields.iter().for_each(|(field, field_range)|{
40-
if let Some(file_sym) = field.borrow().get_file().and_then(|file_sym_weak| file_sym_weak.upgrade()){
41-
let path = file_sym.borrow().paths()[0].clone();
42-
let range = session.sync_odoo.get_file_mgr().borrow().text_range_to_range(session, &path, &field.borrow().range());
43-
links.push(LocationLink{
44-
origin_selection_range: Some(session.sync_odoo.get_file_mgr().borrow().text_range_to_range(session, file_symbol.borrow().paths().first().as_ref().unwrap(), &field_range)),
45-
target_uri: FileMgr::pathname2uri(&path),
46-
target_selection_range: range,
47-
target_range: range,
53+
if let Some(_) = field.borrow().get_file().and_then(|file_sym_weak| file_sym_weak.upgrade()){
54+
domain_found = true;
55+
sources.push(DefinitionSource {
56+
source:
57+
DefinitionSourceType::Symbol(field.clone()),
58+
origin_selection_range: Some(session.sync_odoo.get_file_mgr().borrow().text_range_to_range(session, file_symbol.borrow().paths().first().as_ref().unwrap(), &field_range))
4859
});
4960
}
5061
});
51-
string_domain_fields.len() > 0
62+
domain_found
5263
}
5364

54-
fn check_for_model_string(session: &mut SessionInfo, eval: &Evaluation, file_symbol: &Rc<RefCell<Symbol>>, links: &mut Vec<LocationLink>) -> bool {
65+
fn check_for_model_string(session: &mut SessionInfo, eval: &Evaluation, file_symbol: &Rc<RefCell<Symbol>>, sources: &mut Vec<DefinitionSource>) -> bool {
5566
let value = if let Some(eval_value) = eval.value.as_ref() {
5667
if let EvaluationValue::CONSTANT(Expr::StringLiteral(expr)) = eval_value {
5768
oyarn!("{}", expr.value.to_string())
@@ -76,22 +87,16 @@ impl DefinitionFeature {
7687
continue; // if we are already on the class, skip, unless it is the only result
7788
}
7889
}
79-
if let Some(model_file_sym) = class_symbol.get_file().and_then(|model_file_sym_weak| model_file_sym_weak.upgrade()){
80-
let path = model_file_sym.borrow().get_symbol_first_path();
81-
let range = session.sync_odoo.get_file_mgr().borrow().text_range_to_range(session, &path, &class_symbol.range());
82-
model_found = true;
83-
links.push(LocationLink{
84-
origin_selection_range: eval.range.map(|r| session.sync_odoo.get_file_mgr().borrow().text_range_to_range(session, file_symbol.borrow().paths().first().as_ref().unwrap(), &r)),
85-
target_uri: FileMgr::pathname2uri(&path),
86-
target_selection_range: range,
87-
target_range: range,
88-
});
89-
}
90+
model_found = true;
91+
sources.push(DefinitionSource {
92+
source: DefinitionSourceType::Symbol(class_symbol_rc.clone()),
93+
origin_selection_range: eval.range.map(|r| session.sync_odoo.get_file_mgr().borrow().text_range_to_range(session, file_symbol.borrow().paths().first().as_ref().unwrap(), &r))
94+
});
9095
}
9196
model_found
9297
}
9398

94-
fn check_for_module_string(session: &mut SessionInfo, eval: &Evaluation, file_symbol: &Rc<RefCell<Symbol>>, file_path: &String, links: &mut Vec<LocationLink>) -> bool {
99+
fn check_for_module_string(session: &mut SessionInfo, eval: &Evaluation, file_symbol: &Rc<RefCell<Symbol>>, file_path: &String, sources: &mut Vec<DefinitionSource>) -> bool {
95100
if file_symbol.borrow().typ() != SymType::PACKAGE(PackageType::MODULE) || !file_path.ends_with("__manifest__.py") {
96101
// If not on manifest, we don't check for modules
97102
return false;
@@ -108,17 +113,14 @@ impl DefinitionFeature {
108113
let Some(module) = session.sync_odoo.modules.get(&oyarn!("{}", value)).and_then(|m| m.upgrade()) else {
109114
return false;
110115
};
111-
let path = PathBuf::from(module.borrow().paths()[0].clone()).join("__manifest__.py").sanitize();
112-
links.push(LocationLink{
116+
sources.push(DefinitionSource{
117+
source: DefinitionSourceType::Module(module.clone()),
113118
origin_selection_range: None,
114-
target_uri: FileMgr::pathname2uri(&path),
115-
target_selection_range: Range::default(),
116-
target_range: Range::default(),
117119
});
118120
true
119121
}
120122

121-
fn check_for_xml_id_string(session: &mut SessionInfo, eval: &Evaluation, file_symbol: &Rc<RefCell<Symbol>>, links: &mut Vec<LocationLink>) -> bool {
123+
fn check_for_xml_id_string(session: &mut SessionInfo, eval: &Evaluation, file_symbol: &Rc<RefCell<Symbol>>, sources: &mut Vec<DefinitionSource>) -> bool {
122124
let value = if let Some(eval_value) = eval.value.as_ref() {
123125
if let EvaluationValue::CONSTANT(Expr::StringLiteral(expr)) = eval_value {
124126
oyarn!("{}", expr.value.to_string())
@@ -134,20 +136,18 @@ impl DefinitionFeature {
134136
let file = xml_id.get_file_symbol();
135137
if let Some(file) = file {
136138
if let Some(file) = file.upgrade() {
137-
let range = session.sync_odoo.get_file_mgr().borrow().std_range_to_range(session, &file.borrow().paths()[0], &xml_id.get_range());
138139
xml_found = true;
139-
links.push(LocationLink {
140-
origin_selection_range: eval.range.map(|r| session.sync_odoo.get_file_mgr().borrow().text_range_to_range(session, file_symbol.borrow().paths().first().as_ref().unwrap(), &r)),
141-
target_uri: FileMgr::pathname2uri(&file.borrow().paths()[0]),
142-
target_range: range,
143-
target_selection_range: range });
140+
sources.push(DefinitionSource{
141+
source: DefinitionSourceType::OdooData(xml_id.clone()),
142+
origin_selection_range: eval.range.map(|r| session.sync_odoo.get_file_mgr().borrow().text_range_to_range(session, file_symbol.borrow().paths().first().as_ref().unwrap(), &r))
143+
});
144144
}
145145
}
146146
}
147147
xml_found
148148
}
149149

150-
fn check_for_compute_string(session: &mut SessionInfo, eval: &Evaluation, file_symbol: &Rc<RefCell<Symbol>>, call_expr: &Option<ExprCall>, offset: usize, links: &mut Vec<LocationLink>) -> bool {
150+
fn check_for_compute_string(session: &mut SessionInfo, eval: &Evaluation, file_symbol: &Rc<RefCell<Symbol>>, call_expr: &Option<ExprCall>, offset: usize, sources: &mut Vec<DefinitionSource>) -> bool {
151151
let value = if let Some(eval_value) = eval.value.as_ref() {
152152
if let EvaluationValue::CONSTANT(Expr::StringLiteral(expr)) = eval_value {
153153
expr.value.to_string()
@@ -161,22 +161,20 @@ impl DefinitionFeature {
161161
let method_symbols = FeaturesUtils::find_kwarg_methods_symbols(
162162
session, Symbol::get_scope_symbol(file_symbol.clone(), offset as u32, false), file_symbol.borrow().find_module(), &value, call_expr, &offset
163163
);
164+
let mut method_found = false;
164165
method_symbols.iter().for_each(|field|{
165166
if let Some(file_sym) = field.borrow().get_file().and_then(|file_sym_weak| file_sym_weak.upgrade()){
166-
let path = file_sym.borrow().paths()[0].clone();
167-
let range = session.sync_odoo.get_file_mgr().borrow().text_range_to_range(session, &path, &field.borrow().range());
168-
links.push(LocationLink{
169-
origin_selection_range: eval.range.map(|r| session.sync_odoo.get_file_mgr().borrow().text_range_to_range(session, file_symbol.borrow().paths().first().as_ref().unwrap(), &r)),
170-
target_uri: FileMgr::pathname2uri(&path),
171-
target_selection_range: range,
172-
target_range: range,
167+
method_found = true;
168+
sources.push(DefinitionSource {
169+
source: DefinitionSourceType::Symbol(field.clone()),
170+
origin_selection_range: eval.range.map(|r| session.sync_odoo.get_file_mgr().borrow().text_range_to_range(session, file_symbol.borrow().paths().first().as_ref().unwrap(), &r))
173171
});
174172
}
175173
});
176-
method_symbols.len() > 0
174+
method_found
177175
}
178176

179-
pub fn add_display_name_compute_methods(session: &mut SessionInfo, links: &mut Vec<LocationLink>, expr: &ExprOrIdent, file_symbol: &Rc<RefCell<Symbol>>, offset: usize) {
177+
pub fn add_display_name_compute_methods(session: &mut SessionInfo, sources: &mut Vec<DefinitionSource>, expr: &ExprOrIdent, file_symbol: &Rc<RefCell<Symbol>>, offset: usize) {
180178
// now we want `_compute_display_name` definition(s)
181179
// we need the symbol of the model/ then we run get member symbol
182180
// to do that, we need the expr, match it to attribute, get the value, get its evals
@@ -208,31 +206,29 @@ impl DefinitionFeature {
208206
} else {
209207
Range::default()
210208
};
211-
links.push(LocationLink{
209+
sources.push(DefinitionSource {
210+
source: DefinitionSourceType::Symbol(symbol.clone()),
212211
origin_selection_range: None,
213-
target_uri: FileMgr::pathname2uri(&full_path),
214-
target_selection_range: range,
215-
target_range: range,
216212
});
217213
}
218214
}
219215
}
220216
}
221217

222-
pub fn get_location(session: &mut SessionInfo,
218+
pub fn get_symbols(session: &mut SessionInfo,
223219
file_symbol: &Rc<RefCell<Symbol>>,
224220
file_info: &Rc<RefCell<FileInfo>>,
225221
line: u32,
226222
character: u32
227-
) -> Option<GotoDefinitionResponse> {
223+
) -> Vec<DefinitionSource> {
228224
let offset = file_info.borrow().position_to_offset(line, character, session.sync_odoo.encoding);
229225
let file_info_ast_clone = file_info.borrow().file_info_ast.clone();
230226
let file_info_ast_ref = file_info_ast_clone.borrow();
231227
let (analyse_ast_result, _range, expr, call_expr) = AstUtils::get_symbols(session, &file_info_ast_ref, file_symbol, offset as u32);
232228
if analyse_ast_result.evaluations.is_empty() {
233-
return None;
229+
return vec![];
234230
}
235-
let mut links = vec![];
231+
let mut definition_sources = vec![];
236232
let mut evaluations = analyse_ast_result.evaluations.clone();
237233
// Filter out magic fields
238234
let mut dislay_name_found = false;
@@ -253,17 +249,17 @@ impl DefinitionFeature {
253249
eval_sym.borrow().range() != parent_sym.borrow().range()
254250
});
255251
if let Some(expr) = expr && dislay_name_found {
256-
DefinitionFeature::add_display_name_compute_methods(session, &mut links, &expr, file_symbol, offset);
252+
DefinitionFeature::add_display_name_compute_methods(session, &mut definition_sources, &expr, file_symbol, offset);
257253
}
258254
drop(file_info_ast_ref);
259255
let mut index = 0;
260256
while index < evaluations.len() {
261257
let eval = evaluations[index].clone();
262-
if DefinitionFeature::check_for_domain_field(session, &eval, file_symbol, &call_expr, offset, &mut links) ||
263-
DefinitionFeature::check_for_compute_string(session, &eval, file_symbol,&call_expr, offset, &mut links) ||
264-
DefinitionFeature::check_for_module_string(session, &eval, file_symbol, &file_info.borrow().uri, &mut links) ||
265-
DefinitionFeature::check_for_model_string(session, &eval, file_symbol, &mut links) ||
266-
DefinitionFeature::check_for_xml_id_string(session, &eval, file_symbol, &mut links) {
258+
if DefinitionFeature::check_for_domain_field(session, &eval, file_symbol, &call_expr, offset, &mut definition_sources) ||
259+
DefinitionFeature::check_for_compute_string(session, &eval, file_symbol,&call_expr, offset, &mut definition_sources) ||
260+
DefinitionFeature::check_for_module_string(session, &eval, file_symbol, &file_info.borrow().uri, &mut definition_sources) ||
261+
DefinitionFeature::check_for_model_string(session, &eval, file_symbol, &mut definition_sources) ||
262+
DefinitionFeature::check_for_xml_id_string(session, &eval, file_symbol, &mut definition_sources) {
267263
index += 1;
268264
continue;
269265
}
@@ -276,36 +272,67 @@ impl DefinitionFeature {
276272
index += 1;
277273
continue;
278274
};
279-
if let Some(file) = symbol.borrow().get_file() {
280-
//For import variable, we should take the next evaluation if we are at the same location than the offset, as the get_symbol will return the current import variable (special case as the definition is from outside the file)
281-
if symbol.borrow().typ() == SymType::VARIABLE && symbol.borrow().as_variable().is_import_variable && Rc::ptr_eq(&file.upgrade().unwrap(), file_symbol) && symbol.borrow().has_range() && symbol.borrow().range().contains(TextSize::new(offset as u32)) {
282-
evaluations.remove(index);
283-
let symbol = symbol.borrow();
284-
let sym_eval = symbol.evaluations();
285-
if let Some(sym_eval) = sym_eval {
286-
evaluations = [evaluations.clone(), sym_eval.clone()].concat();
287-
}
288-
continue;
289-
}
290-
for path in file.upgrade().unwrap().borrow().paths().iter() {
291-
let full_path = match file.upgrade().unwrap().borrow().typ() {
292-
SymType::PACKAGE(_) => PathBuf::from(path).join(format!("__init__.py{}", file.upgrade().unwrap().borrow().as_package().i_ext())).sanitize(),
293-
_ => path.clone()
294-
};
295-
let range = if symbol.borrow().has_range() {
296-
session.sync_odoo.get_file_mgr().borrow().text_range_to_range(session, &full_path, &symbol.borrow().range())
297-
} else {
298-
Range::default()
299-
};
300-
links.push(LocationLink{
301-
origin_selection_range: None,
302-
target_uri: FileMgr::pathname2uri(&full_path),
275+
definition_sources.push(DefinitionSource{
276+
source: DefinitionSourceType::Symbol(symbol.clone()),
277+
origin_selection_range: None
278+
});
279+
index += 1;
280+
}
281+
definition_sources
282+
}
283+
284+
pub fn definition_source_to_location(session: &mut SessionInfo, def: &DefinitionSource) -> Option<LocationLink> {
285+
match &def.source {
286+
DefinitionSourceType::Symbol(symbol) => {
287+
if let Some(file_symbol) = symbol.borrow().get_file().and_then(|file_sym_weak| file_sym_weak.upgrade()){
288+
let path = file_symbol.borrow().get_symbol_first_path();
289+
let range = session.sync_odoo.get_file_mgr().borrow().text_range_to_range(session, &path, &symbol.borrow().range());
290+
return Some(LocationLink{
291+
origin_selection_range: def.origin_selection_range.clone(),
292+
target_uri: FileMgr::pathname2uri(&path),
303293
target_selection_range: range,
304294
target_range: range,
305295
});
306296
}
297+
},
298+
DefinitionSourceType::Module(module) => {
299+
let path = PathBuf::from(module.borrow().paths()[0].clone()).join("__manifest__.py").sanitize();
300+
return Some(LocationLink{
301+
origin_selection_range: None,
302+
target_uri: FileMgr::pathname2uri(&path),
303+
target_selection_range: Range::default(),
304+
target_range: Range::default(),
305+
});
306+
},
307+
DefinitionSourceType::OdooData(xml_id) => {
308+
let file = xml_id.get_file_symbol();
309+
if let Some(file) = file {
310+
if let Some(file) = file.upgrade() {
311+
let range = session.sync_odoo.get_file_mgr().borrow().std_range_to_range(session, &file.borrow().paths()[0], &xml_id.get_range());
312+
return Some(LocationLink {
313+
origin_selection_range: def.origin_selection_range.clone(),
314+
target_uri: FileMgr::pathname2uri(&file.borrow().paths()[0]),
315+
target_range: range,
316+
target_selection_range: range });
317+
}
318+
}
319+
}
320+
}
321+
None
322+
}
323+
324+
pub fn get_location(session: &mut SessionInfo,
325+
file_symbol: &Rc<RefCell<Symbol>>,
326+
file_info: &Rc<RefCell<FileInfo>>,
327+
line: u32,
328+
character: u32
329+
) -> Option<GotoDefinitionResponse> {
330+
let definitions_sources = DefinitionFeature::get_symbols(session, file_symbol, file_info, line, character);
331+
let mut links = vec![];
332+
for def in definitions_sources.iter() {
333+
if let Some(link) = DefinitionFeature::definition_source_to_location(session, def) {
334+
links.push(link);
307335
}
308-
index += 1;
309336
}
310337
Some(GotoDefinitionResponse::Link(links))
311338
}

0 commit comments

Comments
 (0)