@@ -44,6 +44,10 @@ pub fn hover(file: &ast::SourceFile, offset: TextSize) -> Option<String> {
4444 return hover_function ( file, & name_ref, & binder) ;
4545 }
4646
47+ if is_aggregate_ref ( & name_ref) {
48+ return hover_aggregate ( file, & name_ref, & binder) ;
49+ }
50+
4751 if is_select_function_call ( & name_ref) {
4852 // Try function first, but fall back to column if no function found
4953 // (handles function-call-style column access like `select a(t)`)
@@ -85,6 +89,14 @@ pub fn hover(file: &ast::SourceFile, offset: TextSize) -> Option<String> {
8589 return format_create_function ( & create_function, & binder) ;
8690 }
8791
92+ if let Some ( create_aggregate) = name
93+ . syntax ( )
94+ . ancestors ( )
95+ . find_map ( ast:: CreateAggregate :: cast)
96+ {
97+ return format_create_aggregate ( & create_aggregate, & binder) ;
98+ }
99+
88100 if let Some ( create_schema) = name. syntax ( ) . ancestors ( ) . find_map ( ast:: CreateSchema :: cast) {
89101 return format_create_schema ( & create_schema) ;
90102 }
@@ -353,6 +365,15 @@ fn is_function_ref(name_ref: &ast::NameRef) -> bool {
353365 false
354366}
355367
368+ fn is_aggregate_ref ( name_ref : & ast:: NameRef ) -> bool {
369+ for ancestor in name_ref. syntax ( ) . ancestors ( ) {
370+ if ast:: DropAggregate :: can_cast ( ancestor. kind ( ) ) {
371+ return true ;
372+ }
373+ }
374+ false
375+ }
376+
356377fn is_select_function_call ( name_ref : & ast:: NameRef ) -> bool {
357378 let mut in_call_expr = false ;
358379 let mut in_arg_list = false ;
@@ -498,6 +519,53 @@ fn function_schema(
498519 search_path. first ( ) . map ( |s| s. to_string ( ) )
499520}
500521
522+ fn hover_aggregate (
523+ file : & ast:: SourceFile ,
524+ name_ref : & ast:: NameRef ,
525+ binder : & binder:: Binder ,
526+ ) -> Option < String > {
527+ let aggregate_ptr = resolve:: resolve_name_ref ( binder, name_ref) ?;
528+
529+ let root = file. syntax ( ) ;
530+ let aggregate_name_node = aggregate_ptr. to_node ( root) ;
531+
532+ let create_aggregate = aggregate_name_node
533+ . ancestors ( )
534+ . find_map ( ast:: CreateAggregate :: cast) ?;
535+
536+ format_create_aggregate ( & create_aggregate, binder)
537+ }
538+
539+ fn format_create_aggregate (
540+ create_aggregate : & ast:: CreateAggregate ,
541+ binder : & binder:: Binder ,
542+ ) -> Option < String > {
543+ let path = create_aggregate. path ( ) ?;
544+ let segment = path. segment ( ) ?;
545+ let name = segment. name ( ) ?;
546+ let aggregate_name = name. syntax ( ) . text ( ) . to_string ( ) ;
547+
548+ let schema = if let Some ( qualifier) = path. qualifier ( ) {
549+ qualifier. syntax ( ) . text ( ) . to_string ( )
550+ } else {
551+ aggregate_schema ( create_aggregate, binder) ?
552+ } ;
553+
554+ let param_list = create_aggregate. param_list ( ) ?;
555+ let params = param_list. syntax ( ) . text ( ) . to_string ( ) ;
556+
557+ Some ( format ! ( "aggregate {}.{}{}" , schema, aggregate_name, params) )
558+ }
559+
560+ fn aggregate_schema (
561+ create_aggregate : & ast:: CreateAggregate ,
562+ binder : & binder:: Binder ,
563+ ) -> Option < String > {
564+ let position = create_aggregate. syntax ( ) . text_range ( ) . start ( ) ;
565+ let search_path = binder. search_path_at ( position) ;
566+ search_path. first ( ) . map ( |s| s. to_string ( ) )
567+ }
568+
501569#[ cfg( test) ]
502570mod test {
503571 use crate :: hover:: hover;
@@ -1003,6 +1071,114 @@ drop function foo$0();
10031071 " ) ;
10041072 }
10051073
1074+ #[ test]
1075+ fn hover_on_drop_function_overloaded ( ) {
1076+ assert_snapshot ! ( check_hover( "
1077+ create function add(complex) returns complex as $$ select null $$ language sql;
1078+ create function add(bigint) returns bigint as $$ select 1 $$ language sql;
1079+ drop function add$0(complex);
1080+ " ) , @r"
1081+ hover: function public.add(complex) returns complex
1082+ ╭▸
1083+ 4 │ drop function add(complex);
1084+ ╰╴ ─ hover
1085+ " ) ;
1086+ }
1087+
1088+ #[ test]
1089+ fn hover_on_drop_function_second_overload ( ) {
1090+ assert_snapshot ! ( check_hover( "
1091+ create function add(complex) returns complex as $$ select null $$ language sql;
1092+ create function add(bigint) returns bigint as $$ select 1 $$ language sql;
1093+ drop function add$0(bigint);
1094+ " ) , @r"
1095+ hover: function public.add(bigint) returns bigint
1096+ ╭▸
1097+ 4 │ drop function add(bigint);
1098+ ╰╴ ─ hover
1099+ " ) ;
1100+ }
1101+
1102+ #[ test]
1103+ fn hover_on_drop_aggregate ( ) {
1104+ assert_snapshot ! ( check_hover( "
1105+ create aggregate myavg(int) (sfunc = int4_avg_accum, stype = _int8);
1106+ drop aggregate myavg$0(int);
1107+ " ) , @r"
1108+ hover: aggregate public.myavg(int)
1109+ ╭▸
1110+ 3 │ drop aggregate myavg(int);
1111+ ╰╴ ─ hover
1112+ " ) ;
1113+ }
1114+
1115+ #[ test]
1116+ fn hover_on_drop_aggregate_with_schema ( ) {
1117+ assert_snapshot ! ( check_hover( "
1118+ create aggregate myschema.myavg(int) (sfunc = int4_avg_accum, stype = _int8);
1119+ drop aggregate myschema.myavg$0(int);
1120+ " ) , @r"
1121+ hover: aggregate myschema.myavg(int)
1122+ ╭▸
1123+ 3 │ drop aggregate myschema.myavg(int);
1124+ ╰╴ ─ hover
1125+ " ) ;
1126+ }
1127+
1128+ #[ test]
1129+ fn hover_on_create_aggregate_definition ( ) {
1130+ assert_snapshot ! ( check_hover( "
1131+ create aggregate myavg$0(int) (sfunc = int4_avg_accum, stype = _int8);
1132+ " ) , @r"
1133+ hover: aggregate public.myavg(int)
1134+ ╭▸
1135+ 2 │ create aggregate myavg(int) (sfunc = int4_avg_accum, stype = _int8);
1136+ ╰╴ ─ hover
1137+ " ) ;
1138+ }
1139+
1140+ #[ test]
1141+ fn hover_on_drop_aggregate_with_search_path ( ) {
1142+ assert_snapshot ! ( check_hover( r#"
1143+ set search_path to myschema;
1144+ create aggregate myavg(int) (sfunc = int4_avg_accum, stype = _int8);
1145+ drop aggregate myavg$0(int);
1146+ "# ) , @r"
1147+ hover: aggregate myschema.myavg(int)
1148+ ╭▸
1149+ 4 │ drop aggregate myavg(int);
1150+ ╰╴ ─ hover
1151+ " ) ;
1152+ }
1153+
1154+ #[ test]
1155+ fn hover_on_drop_aggregate_overloaded ( ) {
1156+ assert_snapshot ! ( check_hover( "
1157+ create aggregate sum(complex) (sfunc = complex_add, stype = complex, initcond = '(0,0)');
1158+ create aggregate sum(bigint) (sfunc = bigint_add, stype = bigint, initcond = '0');
1159+ drop aggregate sum$0(complex);
1160+ " ) , @r"
1161+ hover: aggregate public.sum(complex)
1162+ ╭▸
1163+ 4 │ drop aggregate sum(complex);
1164+ ╰╴ ─ hover
1165+ " ) ;
1166+ }
1167+
1168+ #[ test]
1169+ fn hover_on_drop_aggregate_second_overload ( ) {
1170+ assert_snapshot ! ( check_hover( "
1171+ create aggregate sum(complex) (sfunc = complex_add, stype = complex, initcond = '(0,0)');
1172+ create aggregate sum(bigint) (sfunc = bigint_add, stype = bigint, initcond = '0');
1173+ drop aggregate sum$0(bigint);
1174+ " ) , @r"
1175+ hover: aggregate public.sum(bigint)
1176+ ╭▸
1177+ 4 │ drop aggregate sum(bigint);
1178+ ╰╴ ─ hover
1179+ " ) ;
1180+ }
1181+
10061182 #[ test]
10071183 fn hover_on_select_function_call ( ) {
10081184 assert_snapshot ! ( check_hover( "
0 commit comments