3
3
4
4
use super :: token_info:: TokenInfo ;
5
5
use crate :: common:: DocumentCache ;
6
- use i_slint_compiler:: langtype:: { ElementType , PropertyLookupResult , Type } ;
7
- use i_slint_compiler:: parser:: SyntaxToken ;
6
+ use i_slint_compiler:: langtype:: { ElementType , Type } ;
7
+ use i_slint_compiler:: object_tree:: ElementRc ;
8
+ use i_slint_compiler:: parser:: { syntax_nodes, SyntaxNode , SyntaxToken } ;
8
9
use itertools:: Itertools as _;
9
10
use lsp_types:: { Hover , HoverContents , MarkupContent } ;
10
11
@@ -34,41 +35,85 @@ pub fn get_tooltip(document_cache: &mut DocumentCache, token: SyntaxToken) -> Op
34
35
from_slint_code ( & format ! ( "{} := {} {{ /*...*/ }}" , e. id, e. base_type) )
35
36
}
36
37
}
37
- TokenInfo :: NamedReference ( nr) => {
38
- let prop_info = nr. element ( ) . borrow ( ) . lookup_property ( nr. name ( ) ) ;
39
- from_prop_result ( prop_info) ?
40
- }
38
+ TokenInfo :: NamedReference ( nr) => from_property_in_element ( & nr. element ( ) , nr. name ( ) ) ?,
41
39
TokenInfo :: EnumerationValue ( v) => from_slint_code ( & format ! ( "{}.{}" , v. enumeration. name, v) ) ,
42
40
TokenInfo :: FileName ( _) => return None ,
43
41
// Todo: this can happen when there is some syntax error
44
42
TokenInfo :: LocalProperty ( _) | TokenInfo :: LocalCallback ( _) => return None ,
45
- TokenInfo :: IncompleteNamedReference ( el, name) => {
46
- let prop_info = el. lookup_property ( & name) ;
47
- from_prop_result ( prop_info) ?
48
- }
43
+ TokenInfo :: IncompleteNamedReference ( el, name) => from_property_in_type ( & el, & name) ?,
49
44
} ;
50
45
51
46
Some ( Hover { contents : HoverContents :: Markup ( contents) , range : None } )
52
47
}
53
48
54
- fn from_prop_result ( prop_info : PropertyLookupResult ) -> Option < MarkupContent > {
49
+ fn from_property_in_element ( element : & ElementRc , name : & str ) -> Option < MarkupContent > {
50
+ if let Some ( decl) = element. borrow ( ) . property_declarations . get ( name) {
51
+ return property_tooltip (
52
+ & decl. property_type ,
53
+ decl. node . as_ref ( ) ,
54
+ name,
55
+ decl. pure . unwrap_or ( false ) ,
56
+ ) ;
57
+ }
58
+ from_property_in_type ( & element. borrow ( ) . base_type , name)
59
+ }
60
+
61
+ fn from_property_in_type ( base : & ElementType , name : & str ) -> Option < MarkupContent > {
62
+ match base {
63
+ ElementType :: Component ( c) => from_property_in_element ( & c. root_element , name) ,
64
+ ElementType :: Builtin ( b) => {
65
+ let resolved_name = b. native_class . lookup_alias ( name) . unwrap_or ( name) ;
66
+ let info = b. properties . get ( resolved_name) ?;
67
+ property_tooltip ( & info. ty , None , name, false )
68
+ }
69
+ _ => None ,
70
+ }
71
+ }
72
+
73
+ fn property_tooltip (
74
+ ty : & Type ,
75
+ node : Option < & SyntaxNode > ,
76
+ name : & str ,
77
+ pure : bool ,
78
+ ) -> Option < MarkupContent > {
79
+ let pure = if pure { "pure " } else { "" } ;
55
80
let ret_ty =
56
81
|ty : & Type | if matches ! ( ty, Type :: Void ) { String :: new ( ) } else { format ! ( " -> {}" , ty) } ;
57
-
58
- let pure = if prop_info. declared_pure . is_some_and ( |x| x) { "pure " } else { "" } ;
59
- if let Type :: Callback ( callback) = & prop_info. property_type {
82
+ if let Type :: Callback ( callback) = ty {
60
83
let ret = ret_ty ( & callback. return_type ) ;
61
- let args = callback. args . iter ( ) . map ( |x| x. to_string ( ) ) . join ( ", " ) ;
62
- Some ( from_slint_code ( & format ! ( "{pure}callback {}({args}){ret}" , prop_info. resolved_name) ) )
63
- } else if let Type :: Function ( function) = & prop_info. property_type {
84
+ let args =
85
+ if let Some ( node) = node. cloned ( ) . and_then ( syntax_nodes:: CallbackDeclaration :: new) {
86
+ callback
87
+ . args
88
+ . iter ( )
89
+ . zip ( node. CallbackDeclarationParameter ( ) )
90
+ . map ( |( ty, n) | {
91
+ if let Some ( id) = n. DeclaredIdentifier ( ) {
92
+ format ! ( "{}: {ty}" , id. text( ) )
93
+ } else {
94
+ ty. to_string ( )
95
+ }
96
+ } )
97
+ . join ( ", " )
98
+ } else {
99
+ callback. args . iter ( ) . map ( |x| x. to_string ( ) ) . join ( ", " )
100
+ } ;
101
+ Some ( from_slint_code ( & format ! ( "{pure}callback {name}({args}){ret}" ) ) )
102
+ } else if let Type :: Function ( function) = & ty {
64
103
let ret = ret_ty ( & function. return_type ) ;
65
- let args = function. args . iter ( ) . map ( |x| x. to_string ( ) ) . join ( ", " ) ;
66
- Some ( from_slint_code ( & format ! ( "{pure}function {}({args}){ret}" , prop_info. resolved_name) ) )
67
- } else if prop_info. property_type . is_property_type ( ) {
68
- Some ( from_slint_code ( & format ! (
69
- "property <{}> {}" ,
70
- prop_info. property_type, prop_info. resolved_name
71
- ) ) )
104
+ let args = if let Some ( node) = node. cloned ( ) . and_then ( syntax_nodes:: Function :: new) {
105
+ function
106
+ . args
107
+ . iter ( )
108
+ . zip ( node. ArgumentDeclaration ( ) )
109
+ . map ( |( ty, n) | format ! ( "{}: {ty}" , n. DeclaredIdentifier ( ) . text( ) ) )
110
+ . join ( ", " )
111
+ } else {
112
+ function. args . iter ( ) . map ( |x| x. to_string ( ) ) . join ( ", " )
113
+ } ;
114
+ Some ( from_slint_code ( & format ! ( "{pure}function {name}({args}){ret}" ) ) )
115
+ } else if ty. is_property_type ( ) {
116
+ Some ( from_slint_code ( & format ! ( "property <{ty}> {name}" ) ) )
72
117
} else {
73
118
None
74
119
}
@@ -94,6 +139,7 @@ mod tests {
94
139
#[ test]
95
140
fn test_tooltip ( ) {
96
141
let source = r#"
142
+ import { StandardTableView } from "std-widgets.slint";
97
143
global Glob {
98
144
in-out property <{a:int,b:float}> hello_world;
99
145
callback cb(string, int) -> [int];
@@ -124,6 +170,9 @@ export component Test {
124
170
background: red;
125
171
border-color: self.background;
126
172
}
173
+ StandardTableView {
174
+ row-pointer-event => { }
175
+ }
127
176
}"# ;
128
177
let ( mut dc, uri, _) = crate :: language:: test:: loaded_document_cache ( source. into ( ) ) ;
129
178
let doc = dc. get_document ( & uri) . unwrap ( ) . node . clone ( ) . unwrap ( ) ;
@@ -184,9 +233,14 @@ export component Test {
184
233
get_tooltip ( & mut dc, find_tk ( "Glob.cb(" , 6 . into ( ) ) ) ,
185
234
"```slint\n callback cb(string, int) -> [int]\n ```" ,
186
235
) ;
236
+ assert_tooltip (
237
+ get_tooltip ( & mut dc, find_tk ( "row-pointer-event" , 0 . into ( ) ) ) ,
238
+ // Fixme: this uses LogicalPoint instead of Point because of implementation details
239
+ "```slint\n callback row-pointer-event(row-index: int, event: PointerEvent, mouse-position: LogicalPosition)\n ```" ,
240
+ ) ;
187
241
assert_tooltip (
188
242
get_tooltip ( & mut dc, find_tk ( "fn_glob(local-prop)" , 1 . into ( ) ) ) ,
189
- "```slint\n pure function fn-glob(int)\n ```" ,
243
+ "```slint\n pure function fn-glob(abc: int)\n ```" ,
190
244
) ;
191
245
assert_tooltip (
192
246
get_tooltip ( & mut dc, find_tk ( "root.fn_loc" , 8 . into ( ) ) ) ,
0 commit comments