11use crate :: binder;
22use crate :: binder:: Binder ;
33use crate :: resolve;
4- use rowan:: TextSize ;
4+ use crate :: symbols:: Name ;
5+ use rowan:: { TextRange , TextSize } ;
56use squawk_syntax:: ast:: { self , AstNode } ;
67
78/// `VSCode` has some theming options based on these types.
@@ -16,15 +17,18 @@ pub struct InlayHint {
1617 pub position : TextSize ,
1718 pub label : String ,
1819 pub kind : InlayHintKind ,
20+ pub target : Option < TextRange > ,
1921}
2022
2123pub fn inlay_hints ( file : & ast:: SourceFile ) -> Vec < InlayHint > {
2224 let mut hints = vec ! [ ] ;
2325 let binder = binder:: bind ( file) ;
2426
2527 for node in file. syntax ( ) . descendants ( ) {
26- if let Some ( call_expr) = ast:: CallExpr :: cast ( node) {
28+ if let Some ( call_expr) = ast:: CallExpr :: cast ( node. clone ( ) ) {
2729 inlay_hint_call_expr ( & mut hints, file, & binder, call_expr) ;
30+ } else if let Some ( insert) = ast:: Insert :: cast ( node) {
31+ inlay_hint_insert ( & mut hints, file, & binder, insert) ;
2832 }
2933 }
3034
@@ -59,10 +63,12 @@ fn inlay_hint_call_expr(
5963 for ( param, arg) in param_list. params ( ) . zip ( arg_list. args ( ) ) {
6064 if let Some ( param_name) = param. name ( ) {
6165 let arg_start = arg. syntax ( ) . text_range ( ) . start ( ) ;
66+ let target = Some ( param_name. syntax ( ) . text_range ( ) ) ;
6267 hints. push ( InlayHint {
6368 position : arg_start,
6469 label : format ! ( "{}: " , param_name. syntax( ) . text( ) ) ,
6570 kind : InlayHintKind :: Parameter ,
71+ target,
6672 } ) ;
6773 }
6874 }
@@ -71,6 +77,62 @@ fn inlay_hint_call_expr(
7177 Some ( ( ) )
7278}
7379
80+ fn inlay_hint_insert (
81+ hints : & mut Vec < InlayHint > ,
82+ file : & ast:: SourceFile ,
83+ binder : & Binder ,
84+ insert : ast:: Insert ,
85+ ) -> Option < ( ) > {
86+ let values = insert. values ( ) ?;
87+ let row_list = values. row_list ( ) ?;
88+
89+ let columns: Vec < ( Name , Option < TextRange > ) > = if let Some ( column_list) = insert. column_list ( ) {
90+ let table_arg_list = resolve:: resolve_insert_table_columns ( file, binder, & insert) ;
91+
92+ column_list
93+ . columns ( )
94+ . filter_map ( |col| {
95+ let col_name = resolve:: extract_column_name ( & col) ?;
96+ let target = table_arg_list
97+ . as_ref ( )
98+ . and_then ( |list| resolve:: find_column_in_table ( list, & col_name) ) ;
99+ Some ( ( col_name, target) )
100+ } )
101+ . collect ( )
102+ } else {
103+ let table_arg_list = resolve:: resolve_insert_table_columns ( file, binder, & insert) ?;
104+
105+ table_arg_list
106+ . args ( )
107+ . filter_map ( |arg| {
108+ if let ast:: TableArg :: Column ( column) = arg
109+ && let Some ( name) = column. name ( )
110+ {
111+ let col_name = Name :: new ( name. syntax ( ) . text ( ) . to_string ( ) ) ;
112+ let target = Some ( name. syntax ( ) . text_range ( ) ) ;
113+ Some ( ( col_name, target) )
114+ } else {
115+ None
116+ }
117+ } )
118+ . collect ( )
119+ } ;
120+
121+ for row in row_list. rows ( ) {
122+ for ( ( column_name, target) , expr) in columns. iter ( ) . zip ( row. exprs ( ) ) {
123+ let expr_start = expr. syntax ( ) . text_range ( ) . start ( ) ;
124+ hints. push ( InlayHint {
125+ position : expr_start,
126+ label : format ! ( "{}: " , column_name) ,
127+ kind : InlayHintKind :: Parameter ,
128+ target : * target,
129+ } ) ;
130+ }
131+ }
132+
133+ Some ( ( ) )
134+ }
135+
74136#[ cfg( test) ]
75137mod test {
76138 use crate :: inlay_hints:: inlay_hints;
@@ -216,4 +278,68 @@ select foo(1, 2);
216278 ╰╴ ───
217279 " ) ;
218280 }
281+
282+ #[ test]
283+ fn insert_with_column_list ( ) {
284+ assert_snapshot ! ( check_inlay_hints( "
285+ create table t (column_a int, column_b int, column_c text);
286+ insert into t (column_a, column_c) values (1, 'foo');
287+ " ) , @r"
288+ inlay hints:
289+ ╭▸
290+ 3 │ insert into t (column_a, column_c) values (column_a: 1, column_c: 'foo');
291+ ╰╴ ────────── ──────────
292+ " ) ;
293+ }
294+
295+ #[ test]
296+ fn insert_without_column_list ( ) {
297+ assert_snapshot ! ( check_inlay_hints( "
298+ create table t (column_a int, column_b int, column_c text);
299+ insert into t values (1, 2, 'foo');
300+ " ) , @r"
301+ inlay hints:
302+ ╭▸
303+ 3 │ insert into t values (column_a: 1, column_b: 2, column_c: 'foo');
304+ ╰╴ ────────── ────────── ──────────
305+ " ) ;
306+ }
307+
308+ #[ test]
309+ fn insert_multiple_rows ( ) {
310+ assert_snapshot ! ( check_inlay_hints( "
311+ create table t (x int, y int);
312+ insert into t values (1, 2), (3, 4);
313+ " ) , @r"
314+ inlay hints:
315+ ╭▸
316+ 3 │ insert into t values (x: 1, y: 2), (x: 3, y: 4);
317+ ╰╴ ─── ─── ─── ───
318+ " ) ;
319+ }
320+
321+ #[ test]
322+ fn insert_no_create_table ( ) {
323+ assert_snapshot ! ( check_inlay_hints( "
324+ insert into t (a, b) values (1, 2);
325+ " ) , @r"
326+ inlay hints:
327+ ╭▸
328+ 2 │ insert into t (a, b) values (a: 1, b: 2);
329+ ╰╴ ─── ───
330+ " ) ;
331+ }
332+
333+ #[ test]
334+ fn insert_more_values_than_columns ( ) {
335+ assert_snapshot ! ( check_inlay_hints( "
336+ create table t (a int, b int);
337+ insert into t values (1, 2, 3);
338+ " ) , @r"
339+ inlay hints:
340+ ╭▸
341+ 3 │ insert into t values (a: 1, b: 2, 3);
342+ ╰╴ ─── ───
343+ " ) ;
344+ }
219345}
0 commit comments