@@ -22,6 +22,10 @@ pub fn hover(file: &ast::SourceFile, offset: TextSize) -> Option<String> {
2222 if is_index_ref ( & name_ref) {
2323 return hover_index ( file, & name_ref, & binder) ;
2424 }
25+
26+ if is_function_ref ( & name_ref) {
27+ return hover_function ( file, & name_ref, & binder) ;
28+ }
2529 }
2630
2731 if let Some ( name) = ast:: Name :: cast ( parent) {
@@ -38,6 +42,14 @@ pub fn hover(file: &ast::SourceFile, offset: TextSize) -> Option<String> {
3842 if let Some ( create_index) = name. syntax ( ) . ancestors ( ) . find_map ( ast:: CreateIndex :: cast) {
3943 return format_create_index ( & create_index, & binder) ;
4044 }
45+
46+ if let Some ( create_function) = name
47+ . syntax ( )
48+ . ancestors ( )
49+ . find_map ( ast:: CreateFunction :: cast)
50+ {
51+ return format_create_function ( & create_function, & binder) ;
52+ }
4153 }
4254
4355 None
@@ -278,6 +290,68 @@ fn is_index_ref(name_ref: &ast::NameRef) -> bool {
278290 false
279291}
280292
293+ fn is_function_ref ( name_ref : & ast:: NameRef ) -> bool {
294+ for ancestor in name_ref. syntax ( ) . ancestors ( ) {
295+ if ast:: DropFunction :: can_cast ( ancestor. kind ( ) ) {
296+ return true ;
297+ }
298+ }
299+ false
300+ }
301+
302+ fn hover_function (
303+ file : & ast:: SourceFile ,
304+ name_ref : & ast:: NameRef ,
305+ binder : & binder:: Binder ,
306+ ) -> Option < String > {
307+ let function_ptr = resolve:: resolve_name_ref ( binder, name_ref) ?;
308+
309+ let root = file. syntax ( ) ;
310+ let function_name_node = function_ptr. to_node ( root) ;
311+
312+ let create_function = function_name_node
313+ . ancestors ( )
314+ . find_map ( ast:: CreateFunction :: cast) ?;
315+
316+ format_create_function ( & create_function, binder)
317+ }
318+
319+ fn format_create_function (
320+ create_function : & ast:: CreateFunction ,
321+ binder : & binder:: Binder ,
322+ ) -> Option < String > {
323+ let path = create_function. path ( ) ?;
324+ let segment = path. segment ( ) ?;
325+ let name = segment. name ( ) ?;
326+ let function_name = name. syntax ( ) . text ( ) . to_string ( ) ;
327+
328+ let schema = if let Some ( qualifier) = path. qualifier ( ) {
329+ qualifier. syntax ( ) . text ( ) . to_string ( )
330+ } else {
331+ function_schema ( create_function, binder) ?
332+ } ;
333+
334+ let param_list = create_function. param_list ( ) ?;
335+ let params = param_list. syntax ( ) . text ( ) . to_string ( ) ;
336+
337+ let ret_type = create_function. ret_type ( ) ?;
338+ let return_type = ret_type. syntax ( ) . text ( ) . to_string ( ) ;
339+
340+ Some ( format ! (
341+ "function {}.{}{} {}" ,
342+ schema, function_name, params, return_type
343+ ) )
344+ }
345+
346+ fn function_schema (
347+ create_function : & ast:: CreateFunction ,
348+ binder : & binder:: Binder ,
349+ ) -> Option < String > {
350+ let position = create_function. syntax ( ) . text_range ( ) . start ( ) ;
351+ let search_path = binder. search_path_at ( position) ;
352+ search_path. first ( ) . map ( |s| s. to_string ( ) )
353+ }
354+
281355#[ cfg( test) ]
282356mod test {
283357 use crate :: hover:: hover;
@@ -718,4 +792,68 @@ drop index idx_x$0;
718792 ╰╴ ─ hover
719793 " ) ;
720794 }
795+
796+ #[ test]
797+ fn hover_on_drop_function ( ) {
798+ assert_snapshot ! ( check_hover( "
799+ create function foo() returns int as $$ select 1 $$ language sql;
800+ drop function foo$0();
801+ " ) , @r"
802+ hover: function public.foo() returns int
803+ ╭▸
804+ 3 │ drop function foo();
805+ ╰╴ ─ hover
806+ " ) ;
807+ }
808+
809+ #[ test]
810+ fn hover_on_drop_function_with_schema ( ) {
811+ assert_snapshot ! ( check_hover( "
812+ create function myschema.foo() returns int as $$ select 1 $$ language sql;
813+ drop function myschema.foo$0();
814+ " ) , @r"
815+ hover: function myschema.foo() returns int
816+ ╭▸
817+ 3 │ drop function myschema.foo();
818+ ╰╴ ─ hover
819+ " ) ;
820+ }
821+
822+ #[ test]
823+ fn hover_on_create_function_definition ( ) {
824+ assert_snapshot ! ( check_hover( "
825+ create function foo$0() returns int as $$ select 1 $$ language sql;
826+ " ) , @r"
827+ hover: function public.foo() returns int
828+ ╭▸
829+ 2 │ create function foo() returns int as $$ select 1 $$ language sql;
830+ ╰╴ ─ hover
831+ " ) ;
832+ }
833+
834+ #[ test]
835+ fn hover_on_create_function_with_explicit_schema ( ) {
836+ assert_snapshot ! ( check_hover( "
837+ create function myschema.foo$0() returns int as $$ select 1 $$ language sql;
838+ " ) , @r"
839+ hover: function myschema.foo() returns int
840+ ╭▸
841+ 2 │ create function myschema.foo() returns int as $$ select 1 $$ language sql;
842+ ╰╴ ─ hover
843+ " ) ;
844+ }
845+
846+ #[ test]
847+ fn hover_on_drop_function_with_search_path ( ) {
848+ assert_snapshot ! ( check_hover( r#"
849+ set search_path to myschema;
850+ create function foo() returns int as $$ select 1 $$ language sql;
851+ drop function foo$0();
852+ "# ) , @r"
853+ hover: function myschema.foo() returns int
854+ ╭▸
855+ 4 │ drop function foo();
856+ ╰╴ ─ hover
857+ " ) ;
858+ }
721859}
0 commit comments