@@ -18,6 +18,10 @@ pub fn hover(file: &ast::SourceFile, offset: TextSize) -> Option<String> {
1818 if is_table_ref ( & name_ref) {
1919 return hover_table ( file, & name_ref, & binder) ;
2020 }
21+
22+ if is_index_ref ( & name_ref) {
23+ return hover_index ( file, & name_ref, & binder) ;
24+ }
2125 }
2226
2327 if let Some ( name) = ast:: Name :: cast ( parent) {
@@ -30,6 +34,10 @@ pub fn hover(file: &ast::SourceFile, offset: TextSize) -> Option<String> {
3034 if let Some ( create_table) = name. syntax ( ) . ancestors ( ) . find_map ( ast:: CreateTable :: cast) {
3135 return format_create_table ( & create_table, & binder) ;
3236 }
37+
38+ if let Some ( create_index) = name. syntax ( ) . ancestors ( ) . find_map ( ast:: CreateIndex :: cast) {
39+ return format_create_index ( & create_index, & binder) ;
40+ }
3341 }
3442
3543 None
@@ -116,6 +124,23 @@ fn hover_table(
116124 format_create_table ( & create_table, binder)
117125}
118126
127+ fn hover_index (
128+ file : & ast:: SourceFile ,
129+ name_ref : & ast:: NameRef ,
130+ binder : & binder:: Binder ,
131+ ) -> Option < String > {
132+ let index_ptr = resolve:: resolve_name_ref ( binder, name_ref) ?;
133+
134+ let root = file. syntax ( ) ;
135+ let index_name_node = index_ptr. to_node ( root) ;
136+
137+ let create_index = index_name_node
138+ . ancestors ( )
139+ . find_map ( ast:: CreateIndex :: cast) ?;
140+
141+ format_create_index ( & create_index, binder)
142+ }
143+
119144// Insert inferred schema into the create table hover info
120145fn format_create_table ( create_table : & ast:: CreateTable , binder : & binder:: Binder ) -> Option < String > {
121146 let path = create_table. path ( ) ?;
@@ -156,6 +181,57 @@ fn table_name_offset(create_table: &ast::CreateTable, path: &ast::Path) -> Optio
156181 Some ( ( name_start - create_table_start) . into ( ) )
157182}
158183
184+ // Insert inferred schema for index name and table name
185+ fn format_create_index ( create_index : & ast:: CreateIndex , binder : & binder:: Binder ) -> Option < String > {
186+ let mut text = create_index. syntax ( ) . text ( ) . to_string ( ) ;
187+ let create_index_start = create_index. syntax ( ) . text_range ( ) . start ( ) ;
188+
189+ let Some ( index_schema_str) = index_schema ( create_index, binder) else {
190+ return Some ( text) ;
191+ } ;
192+
193+ let mut insertions = vec ! [ ] ;
194+
195+ if let Some ( name) = create_index. name ( ) {
196+ let has_schema = name
197+ . syntax ( )
198+ . parent ( )
199+ . map ( |p| ast:: Path :: can_cast ( p. kind ( ) ) )
200+ . unwrap_or ( false ) ;
201+
202+ if !has_schema {
203+ let name_start = name. syntax ( ) . text_range ( ) . start ( ) ;
204+ let offset: usize = ( name_start - create_index_start) . into ( ) ;
205+ insertions. push ( ( offset, format ! ( "{}." , index_schema_str) ) ) ;
206+ }
207+ }
208+
209+ if let Some ( relation_name) = create_index. relation_name ( )
210+ && let Some ( path) = relation_name. path ( )
211+ && path. qualifier ( ) . is_none ( )
212+ {
213+ let ( table_schema, _) = resolve:: resolve_table_info ( binder, & path) ?;
214+ let segment = path. segment ( ) ?;
215+ let name_ref = segment. name_ref ( ) ?;
216+ let table_name_start = name_ref. syntax ( ) . text_range ( ) . start ( ) ;
217+ let offset: usize = ( table_name_start - create_index_start) . into ( ) ;
218+ insertions. push ( ( offset, format ! ( "{}." , table_schema) ) ) ;
219+ }
220+
221+ insertions. sort_by ( |a, b| b. 0 . cmp ( & a. 0 ) ) ;
222+ for ( offset, schema_str) in insertions {
223+ text. insert_str ( offset, & schema_str) ;
224+ }
225+
226+ Some ( text)
227+ }
228+
229+ fn index_schema ( create_index : & ast:: CreateIndex , binder : & binder:: Binder ) -> Option < String > {
230+ let position = create_index. syntax ( ) . text_range ( ) . start ( ) ;
231+ let search_path = binder. search_path_at ( position) ;
232+ search_path. first ( ) . map ( |s| s. to_string ( ) )
233+ }
234+
159235fn is_column_ref ( name_ref : & ast:: NameRef ) -> bool {
160236 let mut in_partition_item = false ;
161237
@@ -193,6 +269,15 @@ fn is_table_ref(name_ref: &ast::NameRef) -> bool {
193269 false
194270}
195271
272+ fn is_index_ref ( name_ref : & ast:: NameRef ) -> bool {
273+ for ancestor in name_ref. syntax ( ) . ancestors ( ) {
274+ if ast:: DropIndex :: can_cast ( ancestor. kind ( ) ) {
275+ return true ;
276+ }
277+ }
278+ false
279+ }
280+
196281#[ cfg( test) ]
197282mod test {
198283 use crate :: hover:: hover;
@@ -236,13 +321,6 @@ mod test {
236321 None
237322 }
238323
239- fn hover_not_found ( sql : & str ) {
240- assert ! (
241- check_hover_( sql) . is_none( ) ,
242- "Should not find hover information"
243- ) ;
244- }
245-
246324 #[ test]
247325 fn hover_column_in_create_index ( ) {
248326 assert_snapshot ! ( check_hover( "
@@ -390,13 +468,16 @@ create index idx on t$0(id);
390468 }
391469
392470 #[ test]
393- fn hover_not_on_index_name ( ) {
394- hover_not_found (
395- "
471+ fn hover_on_index_name_in_create ( ) {
472+ assert_snapshot ! ( check_hover( "
396473create table users(id int);
397474create index idx$0 on users(id);
398- " ,
399- ) ;
475+ " ) , @r"
476+ hover: create index public.idx on public.users(id)
477+ ╭▸
478+ 3 │ create index idx on users(id);
479+ ╰╴ ─ hover
480+ " ) ;
400481 }
401482
402483 #[ test]
@@ -571,4 +652,70 @@ create table t(id int, email$0 text, name varchar(100));
571652 ╰╴ ─ hover
572653 " ) ;
573654 }
655+
656+ #[ test]
657+ fn hover_on_drop_table ( ) {
658+ assert_snapshot ! ( check_hover( "
659+ create table users(id int, email text);
660+ drop table users$0;
661+ " ) , @r"
662+ hover: create table public.users(id int, email text)
663+ ╭▸
664+ 3 │ drop table users;
665+ ╰╴ ─ hover
666+ " ) ;
667+ }
668+
669+ #[ test]
670+ fn hover_on_drop_table_with_schema ( ) {
671+ assert_snapshot ! ( check_hover( "
672+ create table myschema.users(id int);
673+ drop table myschema.users$0;
674+ " ) , @r"
675+ hover: create table myschema.users(id int)
676+ ╭▸
677+ 3 │ drop table myschema.users;
678+ ╰╴ ─ hover
679+ " ) ;
680+ }
681+
682+ #[ test]
683+ fn hover_on_drop_temp_table ( ) {
684+ assert_snapshot ! ( check_hover( "
685+ create temp table t(x bigint);
686+ drop table t$0;
687+ " ) , @r"
688+ hover: create temp table pg_temp.t(x bigint)
689+ ╭▸
690+ 3 │ drop table t;
691+ ╰╴ ─ hover
692+ " ) ;
693+ }
694+
695+ #[ test]
696+ fn hover_on_create_index_definition ( ) {
697+ assert_snapshot ! ( check_hover( "
698+ create table t(x bigint);
699+ create index idx$0 on t(x);
700+ " ) , @r"
701+ hover: create index public.idx on public.t(x)
702+ ╭▸
703+ 3 │ create index idx on t(x);
704+ ╰╴ ─ hover
705+ " ) ;
706+ }
707+
708+ #[ test]
709+ fn hover_on_drop_index ( ) {
710+ assert_snapshot ! ( check_hover( "
711+ create table t(x bigint);
712+ create index idx_x on t(x);
713+ drop index idx_x$0;
714+ " ) , @r"
715+ hover: create index public.idx_x on public.t(x)
716+ ╭▸
717+ 4 │ drop index idx_x;
718+ ╰╴ ─ hover
719+ " ) ;
720+ }
574721}
0 commit comments