@@ -7,10 +7,11 @@ use std::path::Path;
77use std:: sync:: atomic:: Ordering :: Relaxed ;
88use std:: sync:: Arc ;
99
10+ use fomat_macros:: fomat;
1011use lasso:: Spur ;
1112use log:: { debug, warn} ;
1213use miette:: diagnostic;
13- use odoo_lsp:: component:: ComponentTemplate ;
14+ use odoo_lsp:: component:: { ComponentTemplate , PropType } ;
1415use odoo_lsp:: index:: { interner, PathSymbol } ;
1516use odoo_lsp:: model:: { Field , FieldKind } ;
1617use odoo_lsp:: template:: gather_templates;
@@ -375,7 +376,12 @@ impl Backend {
375376 Some ( RefKind :: TInherit ) | Some ( RefKind :: TName ) | Some ( RefKind :: TCall ) => {
376377 self . jump_def_template_name ( needle)
377378 }
378- Some ( RefKind :: PropOf ( component) ) => self . jump_def_component_prop ( component, needle) ,
379+ Some ( RefKind :: PropOf ( component) ) => {
380+ if let Some ( ( handler, _) ) = needle. split_once ( '.' ) {
381+ needle = handler;
382+ }
383+ self . jump_def_component_prop ( component, needle)
384+ }
379385 Some ( RefKind :: Id ) => self . jump_def_xml_id ( needle, uri) ,
380386 Some ( RefKind :: PyExpr ( py_offset) ) => {
381387 let mut parser = Parser :: new ( ) ;
@@ -448,7 +454,7 @@ impl Backend {
448454 return Ok ( None ) ;
449455 } ;
450456
451- let lsp_range = offset_range_to_lsp_range (
457+ let mut lsp_range = offset_range_to_lsp_range (
452458 ref_range. clone ( ) . map_unit ( |unit| ByteOffset ( unit + relative_offset) ) ,
453459 rope. clone ( ) ,
454460 ) ;
@@ -528,7 +534,48 @@ impl Backend {
528534 offset_range_to_lsp_range ( range. map_unit ( |rel_unit| ByteOffset ( rel_unit + anchor) ) , rope. clone ( ) ) ,
529535 )
530536 }
531- Some ( RefKind :: TName ) | Some ( RefKind :: PropOf ( ..) ) | Some ( RefKind :: Component ) | None => {
537+ Some ( RefKind :: Component ) => Ok ( self . hover_component ( needle, lsp_range) ) ,
538+ Some ( RefKind :: PropOf ( component_key) ) => {
539+ if let Some ( ( handler, _) ) = needle. split_once ( '.' ) {
540+ // accept handler.bind syntax as well
541+ if let Some ( lsp_range) = lsp_range. as_mut ( ) {
542+ lsp_range. end . character = lsp_range. start . character + handler. len ( ) as u32 ;
543+ }
544+ needle = handler;
545+ }
546+ let prop = some ! ( interner( ) . get( needle) ) ;
547+ let component = some ! ( interner( ) . get( component_key) ) ;
548+ let component = some ! ( self . index. components. get( & component. into( ) ) ) ;
549+ let field = some ! ( component. props. get( & prop. into( ) ) ) ;
550+ let type_descriptor = field. type_ & !( PropType :: Optional | PropType :: Array ) ;
551+ let needs_paren = field. type_ . contains ( PropType :: Array ) && type_descriptor. iter ( ) . count ( ) > 1 ;
552+ let contents = fomat ! {
553+ "(property) " ( component_key) "." ( needle)
554+ if field. type_. contains( PropType :: Optional ) { "?" } ": "
555+ if needs_paren { "(" }
556+ for type_ in type_descriptor. iter( ) {
557+ match type_ {
558+ PropType :: String => { "string" }
559+ PropType :: Number => { "number" }
560+ PropType :: Boolean => { "boolean" }
561+ PropType :: Object => { "object" }
562+ PropType :: Function => { "Function" }
563+ _ => { "unknown" }
564+ }
565+ }
566+ separated { " | " }
567+ if needs_paren { ")" }
568+ if field. type_. contains( PropType :: Array ) { "[]" }
569+ } ;
570+ Ok ( Some ( Hover {
571+ range : lsp_range,
572+ contents : HoverContents :: Scalar ( MarkedString :: LanguageString ( LanguageString {
573+ language : "ts" . to_string ( ) ,
574+ value : contents,
575+ } ) ) ,
576+ } ) )
577+ }
578+ Some ( RefKind :: TName ) | None => {
532579 #[ cfg( not( debug_assertions) ) ]
533580 return Ok ( None ) ;
534581
0 commit comments