@@ -10,18 +10,30 @@ use crate::core::file_mgr::{FileInfo, FileMgr};
1010use crate :: core:: odoo:: SyncOdoo ;
1111use crate :: core:: python_odoo_builder:: MAGIC_FIELDS ;
1212use crate :: core:: symbols:: symbol:: Symbol ;
13+ use crate :: core:: xml_data:: OdooData ;
1314use crate :: features:: ast_utils:: AstUtils ;
1415use crate :: features:: features_utils:: FeaturesUtils ;
1516use crate :: features:: xml_ast_utils:: { XmlAstResult , XmlAstUtils } ;
1617use crate :: { S , oyarn} ;
1718use crate :: threads:: SessionInfo ;
1819use 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+
2032pub struct DefinitionFeature { }
2133
2234impl 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