@@ -5,15 +5,15 @@ use std::path::PathBuf;
55use std:: { cell:: RefCell , rc:: Rc } ;
66
77use crate :: constants:: SymType ;
8- use crate :: core:: evaluation:: { Evaluation , EvaluationValue } ;
8+ use crate :: core:: evaluation:: { Evaluation , EvaluationValue , ExprOrIdent } ;
99use 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 ;
1313use crate :: features:: ast_utils:: AstUtils ;
1414use crate :: features:: features_utils:: FeaturesUtils ;
1515use crate :: features:: xml_ast_utils:: { XmlAstResult , XmlAstUtils } ;
16- use crate :: oyarn;
16+ use crate :: { S , oyarn} ;
1717use crate :: threads:: SessionInfo ;
1818use crate :: utils:: PathSanitizer as _;
1919
@@ -149,33 +149,91 @@ impl DefinitionFeature {
149149 compute_symbols. len ( ) > 0
150150 }
151151
152+ pub fn add_display_name_compute_methods ( session : & mut SessionInfo , links : & mut Vec < LocationLink > , expr : & ExprOrIdent , file_symbol : & Rc < RefCell < Symbol > > , offset : usize ) {
153+ // now we want `_compute_display_name` definition(s)
154+ // we need the symbol of the model/ then we run get member symbol
155+ // to do that, we need the expr, match it to attribute, get the value, get its evals
156+ // with those evals, we run get_member_symbol on `_compute_display_name`
157+ let crate :: core:: evaluation:: ExprOrIdent :: Expr ( Expr :: Attribute ( attr_expr) ) = expr else {
158+ return ;
159+ } ;
160+ let ( analyse_ast_result, _range) = AstUtils :: get_symbols ( session, file_symbol, offset as u32 , & crate :: core:: evaluation:: ExprOrIdent :: Expr ( & attr_expr. value ) ) ;
161+ let eval_ptrs = analyse_ast_result. evaluations . iter ( ) . flat_map ( |eval| Symbol :: follow_ref ( eval. symbol . get_symbol_ptr ( ) , session, & mut None , false , false , None ) ) . collect :: < Vec < _ > > ( ) ;
162+ let maybe_module = file_symbol. borrow ( ) . find_module ( ) ;
163+ let symbols = eval_ptrs. iter ( ) . flat_map ( |eval_ptr| {
164+ let Some ( symbol) = eval_ptr. upgrade_weak ( ) else {
165+ return vec ! [ ] ;
166+ } ;
167+ symbol. borrow ( ) . get_member_symbol ( session, & S ! ( "_compute_display_name" ) , maybe_module. clone ( ) , false , false , true , false ) . 0
168+ } ) . collect :: < Vec < _ > > ( ) ;
169+ for symbol in symbols {
170+ if let Some ( file) = symbol. borrow ( ) . get_file ( ) {
171+ for path in file. upgrade ( ) . unwrap ( ) . borrow ( ) . paths ( ) . iter ( ) {
172+ let full_path = match file. upgrade ( ) . unwrap ( ) . borrow ( ) . typ ( ) {
173+ SymType :: PACKAGE ( _) => PathBuf :: from ( path) . join ( format ! ( "__init__.py{}" , file. upgrade( ) . unwrap( ) . borrow( ) . as_package( ) . i_ext( ) ) ) . sanitize ( ) ,
174+ _ => path. clone ( )
175+ } ;
176+ let range = if symbol. borrow ( ) . has_range ( ) {
177+ if symbol. borrow ( ) . range ( ) . contains ( TextSize :: new ( offset as u32 ) ) {
178+ continue ; //skip if we are already on the definition
179+ }
180+ session. sync_odoo . get_file_mgr ( ) . borrow ( ) . text_range_to_range ( session, & full_path, & symbol. borrow ( ) . range ( ) )
181+ } else {
182+ Range :: default ( )
183+ } ;
184+ links. push ( LocationLink {
185+ origin_selection_range : None ,
186+ target_uri : FileMgr :: pathname2uri ( & full_path) ,
187+ target_selection_range : range,
188+ target_range : range,
189+ } ) ;
190+ }
191+ }
192+ }
193+ }
194+
152195 pub fn get_location ( session : & mut SessionInfo ,
153196 file_symbol : & Rc < RefCell < Symbol > > ,
154197 file_info : & Rc < RefCell < FileInfo > > ,
155198 line : u32 ,
156199 character : u32
157200 ) -> Option < GotoDefinitionResponse > {
158201 let offset = file_info. borrow ( ) . position_to_offset ( line, character) ;
159- let ( analyse_ast_result, _range, call_expr) = AstUtils :: get_symbols ( session, file_symbol, file_info, offset as u32 ) ;
202+ let file_info_ast_clone = file_info. borrow ( ) . file_info_ast . clone ( ) ;
203+ let file_info_ast_ref = file_info_ast_clone. borrow ( ) ;
204+ let ( expr, call_expr) = AstUtils :: get_expr ( & file_info_ast_ref, offset as u32 ) ;
205+ let Some ( expr) = expr else {
206+ return None ;
207+ } ;
208+ let ( analyse_ast_result, _range) = AstUtils :: get_symbols ( session, file_symbol, offset as u32 , & expr) ;
160209 if analyse_ast_result. evaluations . is_empty ( ) {
161210 return None ;
162211 }
163212 let mut links = vec ! [ ] ;
164213 let mut evaluations = analyse_ast_result. evaluations . clone ( ) ;
165214 // Filter out magic fields
215+ let mut dislay_name_found = false ;
166216 evaluations. retain ( |eval| {
167217 // Filter out, variables, whose parents are a class, whose name is one of the magic fields, and have the same range as their parent
168218 let eval_sym = eval. symbol . get_symbol ( session, & mut None , & mut vec ! [ ] , None ) ;
169219 let Some ( eval_sym) = eval_sym. upgrade_weak ( ) else { return true ; } ;
170220 if !MAGIC_FIELDS . contains ( & eval_sym. borrow ( ) . name ( ) . as_str ( ) ) || eval_sym. borrow ( ) . typ ( ) != SymType :: VARIABLE || !eval_sym. borrow ( ) . is_field ( session) {
171221 return true ;
172222 }
223+ if eval_sym. borrow ( ) . name ( ) == "display_name" {
224+ dislay_name_found = true ;
225+ }
173226 let Some ( parent_sym) = eval_sym. borrow ( ) . parent ( ) . and_then ( |parent| parent. upgrade ( ) ) else { return true ; } ;
174227 if parent_sym. borrow ( ) . typ ( ) != SymType :: CLASS {
175228 return true ;
176229 }
177230 eval_sym. borrow ( ) . range ( ) != parent_sym. borrow ( ) . range ( )
178231 } ) ;
232+ if dislay_name_found {
233+ DefinitionFeature :: add_display_name_compute_methods ( session, & mut links, & expr, file_symbol, offset) ;
234+ }
235+ drop ( expr) ;
236+ drop ( file_info_ast_ref) ;
179237 let mut index = 0 ;
180238 while index < evaluations. len ( ) {
181239 let eval = evaluations[ index] . clone ( ) ;
0 commit comments