@@ -34,6 +34,7 @@ pub enum ExpectedType {
3434 CLASS ( Rc < RefCell < Symbol > > ) ,
3535 SIMPLE_FIELD ( Option < OYarn > ) ,
3636 NESTED_FIELD ( Option < OYarn > ) ,
37+ EXTERNAL_FIELD ( OYarn ) , // Like in inverse_name='field_name', we attach the comodel_name
3738 METHOD_NAME ,
3839 INHERITS ,
3940}
@@ -641,35 +642,44 @@ fn complete_call(session: &mut SessionInfo, file: &Rc<RefCell<Symbol>>, expr_cal
641642 return complete_expr ( arg, session, file, offset, is_param, & vec ! [ ] ) ;
642643 }
643644 }
644- for keyword in expr_call. arguments . keywords . iter ( ) {
645- if offset <= keyword. value . range ( ) . start ( ) . to_usize ( ) || offset > keyword. value . range ( ) . end ( ) . to_usize ( ) {
645+ let Some ( keyword) = expr_call. arguments . keywords . iter ( ) . find ( |arg|
646+ offset > arg. range ( ) . start ( ) . to_usize ( ) && offset <= arg. range ( ) . end ( ) . to_usize ( ) ) else {
647+ return None ;
648+ } ;
649+ for callable_eval in callable_evals. iter ( ) {
650+ let callable = callable_eval. symbol . get_symbol_as_weak ( session, & mut None , & mut vec ! [ ] , None ) ;
651+ let Some ( callable_sym) = callable. weak . upgrade ( ) else { continue } ;
652+ if callable_sym. borrow ( ) . typ ( ) != SymType :: CLASS || !callable_sym. borrow ( ) . is_field_class ( session) {
646653 continue ;
647654 }
648- for callable_eval in callable_evals. iter ( ) {
649- let callable = callable_eval. symbol . get_symbol_as_weak ( session, & mut None , & mut vec ! [ ] , None ) ;
650- let Some ( callable_sym) = callable. weak . upgrade ( ) else { continue } ;
651- if callable_sym. borrow ( ) . typ ( ) != SymType :: CLASS || !callable_sym. borrow ( ) . is_field_class ( session) {
652- continue ;
655+ let Some ( expected_type) = keyword. arg . as_ref ( ) . and_then ( |kw_arg_id|
656+ match kw_arg_id. id . as_str ( ) {
657+ "related" => Some ( vec ! [ ExpectedType :: NESTED_FIELD ( Some ( oyarn!( "{}" , callable_sym. borrow( ) . name( ) ) ) ) ] ) ,
658+ "comodel_name" => if callable_sym. borrow ( ) . is_specific_field_class ( session, & [ "Many2one" , "One2many" , "Many2many" ] ) {
659+ Some ( vec ! [ ExpectedType :: MODEL_NAME ] )
660+ } else {
661+ None
662+ } ,
663+ "inverse_name" => {
664+ if let Some ( Expr :: StringLiteral ( expr) ) = expr_call. arguments . args . first ( ) {
665+ Some ( vec ! [ ExpectedType :: EXTERNAL_FIELD ( Sy !( expr. value. to_string( ) ) ) ] )
666+ } else {
667+ expr_call. arguments . keywords . iter ( ) . find ( |kw| kw. arg . as_ref ( ) . map ( |arg| arg. id == "comodel_name" ) . unwrap_or ( false ) )
668+ . and_then ( |kw| match & kw. value {
669+ Expr :: StringLiteral ( expr) => Some ( vec ! [ ExpectedType :: EXTERNAL_FIELD ( Sy !( expr. value. to_string( ) ) ) ] ) ,
670+ _ => None
671+ } )
672+ }
673+ } ,
674+ "inverse" | "search" | "compute" => Some ( vec ! [ ExpectedType :: METHOD_NAME ] ) ,
675+ _ => None ,
653676 }
654- let Some ( expected_type) = keyword. arg . as_ref ( ) . and_then ( |kw_arg_id|
655- match kw_arg_id. id . as_str ( ) {
656- "related" => Some ( vec ! [ ExpectedType :: NESTED_FIELD ( Some ( oyarn!( "{}" , callable_sym. borrow( ) . name( ) ) ) ) ] ) ,
657- "comodel_name" => if callable_sym. borrow ( ) . is_specific_field_class ( session, & [ "Many2one" , "One2many" , "Many2many" ] ) {
658- Some ( vec ! [ ExpectedType :: MODEL_NAME ] )
659- } else {
660- None
661- } ,
662- "inverse" | "search" | "compute" => Some ( vec ! [ ExpectedType :: METHOD_NAME ] ) ,
663- _ => None ,
664- }
665- ) else {
666- continue ;
667- } ;
668- return complete_expr ( & keyword. value , session, file, offset, is_param, & expected_type) ;
669- }
670- return complete_expr ( & keyword. value , session, file, offset, is_param, & vec ! [ ] ) ;
677+ ) else {
678+ continue ;
679+ } ;
680+ return complete_expr ( & keyword. value , session, file, offset, is_param, & expected_type) ;
671681 }
672- None
682+ return complete_expr ( & keyword . value , session , file , offset , is_param , & vec ! [ ] ) ;
673683}
674684
675685fn complete_string_literal ( session : & mut SessionInfo , file : & Rc < RefCell < Symbol > > , expr_string_literal : & ruff_python_ast:: ExprStringLiteral , _offset : usize , _is_param : bool , expected_type : & Vec < ExpectedType > ) -> Option < CompletionResponse > {
@@ -774,6 +784,15 @@ fn complete_string_literal(session: &mut SessionInfo, file: &Rc<RefCell<Symbol>>
774784 _ => unreachable ! ( )
775785 }
776786 } ,
787+ ExpectedType :: EXTERNAL_FIELD ( model_name) => {
788+ let Some ( model) = session. sync_odoo . models . get ( & oyarn ! ( "{}" , model_name) ) . cloned ( ) else {
789+ break ;
790+ } ;
791+ let main_syms = model. borrow ( ) . get_main_symbols ( session, current_module. clone ( ) ) ;
792+ main_syms. iter ( ) . for_each ( |model_sym| {
793+ add_model_attributes ( session, & mut items, current_module. clone ( ) , model_sym. clone ( ) , false , true , false , expr_string_literal. value . to_str ( ) , & Some ( S ! ( "Many2one" ) ) )
794+ } ) ;
795+ } ,
777796 ExpectedType :: CLASS ( _) => { } ,
778797 ExpectedType :: INHERITS => { } ,
779798 }
0 commit comments