11use rowan:: TextRange ;
22use squawk_syntax:: ast:: { self , AstNode } ;
33
4- use crate :: binder;
4+ use crate :: binder:: { self , extract_string_literal } ;
55use crate :: resolve:: { resolve_function_info, resolve_table_info, resolve_type_info} ;
66
77#[ derive( Debug ) ]
@@ -10,6 +10,7 @@ pub enum DocumentSymbolKind {
1010 Function ,
1111 Type ,
1212 Column ,
13+ Variant ,
1314}
1415
1516#[ derive( Debug ) ]
@@ -126,13 +127,28 @@ fn create_type_symbol(
126127 let full_range = create_type. syntax ( ) . text_range ( ) ;
127128 let focus_range = name_node. syntax ( ) . text_range ( ) ;
128129
130+ let mut children = vec ! [ ] ;
131+ if let Some ( variant_list) = create_type. variant_list ( ) {
132+ for variant in variant_list. variants ( ) {
133+ if let Some ( variant_symbol) = create_variant_symbol ( variant) {
134+ children. push ( variant_symbol) ;
135+ }
136+ }
137+ } else if let Some ( column_list) = create_type. column_list ( ) {
138+ for column in column_list. columns ( ) {
139+ if let Some ( column_symbol) = create_column_symbol ( column) {
140+ children. push ( column_symbol) ;
141+ }
142+ }
143+ }
144+
129145 Some ( DocumentSymbol {
130146 name,
131147 detail : None ,
132148 kind : DocumentSymbolKind :: Type ,
133149 full_range,
134150 focus_range,
135- children : vec ! [ ] ,
151+ children,
136152 } )
137153}
138154
@@ -155,6 +171,23 @@ fn create_column_symbol(column: ast::Column) -> Option<DocumentSymbol> {
155171 } )
156172}
157173
174+ fn create_variant_symbol ( variant : ast:: Variant ) -> Option < DocumentSymbol > {
175+ let literal = variant. literal ( ) ?;
176+ let name = extract_string_literal ( & literal) ?;
177+
178+ let full_range = variant. syntax ( ) . text_range ( ) ;
179+ let focus_range = literal. syntax ( ) . text_range ( ) ;
180+
181+ Some ( DocumentSymbol {
182+ name,
183+ detail : None ,
184+ kind : DocumentSymbolKind :: Variant ,
185+ full_range,
186+ focus_range,
187+ children : vec ! [ ] ,
188+ } )
189+ }
190+
158191#[ cfg( test) ]
159192mod tests {
160193 use super :: * ;
@@ -197,6 +230,7 @@ mod tests {
197230 DocumentSymbolKind :: Function => "function" ,
198231 DocumentSymbolKind :: Type => "type" ,
199232 DocumentSymbolKind :: Column => "column" ,
233+ DocumentSymbolKind :: Variant => "variant" ,
200234 } ;
201235
202236 let title = if let Some ( detail) = & symbol. detail {
@@ -227,10 +261,14 @@ mod tests {
227261 . map ( |child| {
228262 let kind = match child. kind {
229263 DocumentSymbolKind :: Column => "column" ,
230- _ => unreachable ! ( "only columns can be children" ) ,
264+ DocumentSymbolKind :: Variant => "variant" ,
265+ _ => unreachable ! ( "only columns and variants can be children" ) ,
231266 } ;
232- let detail = & child. detail . as_ref ( ) . unwrap ( ) ;
233- format ! ( "{}: {} {}" , kind, child. name, detail)
267+ if let Some ( detail) = & child. detail {
268+ format ! ( "{}: {} {}" , kind, child. name, detail)
269+ } else {
270+ format ! ( "{}: {}" , kind, child. name)
271+ }
234272 } )
235273 . collect ( ) ;
236274
@@ -392,7 +430,16 @@ create function my_schema.hello() returns void as $$ select 1; $$ language sql;
392430 │ ┬───────────┯━━━━━───────────────────────────────
393431 │ │ │
394432 │ │ focus range
395- ╰╴full range
433+ │ full range
434+ │
435+ ⸬
436+ 1 │ create type status as enum ('active', 'inactive');
437+ │ ┯━━━━━━━ ┯━━━━━━━━━
438+ │ │ │
439+ │ │ full range for `variant: inactive`
440+ │ │ focus range
441+ │ full range for `variant: active`
442+ ╰╴ focus range
396443 "
397444 ) ;
398445 }
@@ -408,7 +455,43 @@ create function my_schema.hello() returns void as $$ select 1; $$ language sql;
408455 │ ┬───────────┯━━━━━────────────────────────
409456 │ │ │
410457 │ │ focus range
411- ╰╴full range
458+ │ full range
459+ │
460+ ⸬
461+ 1 │ create type person as (name text, age int);
462+ │ ┯━━━───── ┯━━────
463+ │ │ │
464+ │ │ full range for `column: age int`
465+ │ │ focus range
466+ │ full range for `column: name text`
467+ ╰╴ focus range
468+ "
469+ ) ;
470+ }
471+
472+ #[ test]
473+ fn create_type_composite_multiple_columns ( ) {
474+ assert_snapshot ! (
475+ symbols( "create type address as (street text, city text, zip varchar(10));" ) ,
476+ @r"
477+ info: type: public.address
478+ ╭▸
479+ 1 │ create type address as (street text, city text, zip varchar(10));
480+ │ ┬───────────┯━━━━━━─────────────────────────────────────────────
481+ │ │ │
482+ │ │ focus range
483+ │ full range
484+ │
485+ ⸬
486+ 1 │ create type address as (street text, city text, zip varchar(10));
487+ │ ┯━━━━━───── ┯━━━───── ┯━━────────────
488+ │ │ │ │
489+ │ │ │ full range for `column: zip varchar(10)`
490+ │ │ │ focus range
491+ │ │ full range for `column: city text`
492+ │ │ focus range
493+ │ full range for `column: street text`
494+ ╰╴ focus range
412495 "
413496 ) ;
414497 }
@@ -424,7 +507,45 @@ create function my_schema.hello() returns void as $$ select 1; $$ language sql;
424507 │ ┬────────────────────┯━━━━━───────────────────────────────
425508 │ │ │
426509 │ │ focus range
427- ╰╴full range
510+ │ full range
511+ │
512+ ⸬
513+ 1 │ create type myschema.status as enum ('active', 'inactive');
514+ │ ┯━━━━━━━ ┯━━━━━━━━━
515+ │ │ │
516+ │ │ full range for `variant: inactive`
517+ │ │ focus range
518+ │ full range for `variant: active`
519+ ╰╴ focus range
520+ "
521+ ) ;
522+ }
523+
524+ #[ test]
525+ fn create_type_enum_multiple_variants ( ) {
526+ assert_snapshot ! (
527+ symbols( "create type priority as enum ('low', 'medium', 'high', 'urgent');" ) ,
528+ @r"
529+ info: type: public.priority
530+ ╭▸
531+ 1 │ create type priority as enum ('low', 'medium', 'high', 'urgent');
532+ │ ┬───────────┯━━━━━━━────────────────────────────────────────────
533+ │ │ │
534+ │ │ focus range
535+ │ full range
536+ │
537+ ⸬
538+ 1 │ create type priority as enum ('low', 'medium', 'high', 'urgent');
539+ │ ┯━━━━ ┯━━━━━━━ ┯━━━━━ ┯━━━━━━━
540+ │ │ │ │ │
541+ │ │ │ │ full range for `variant: urgent`
542+ │ │ │ │ focus range
543+ │ │ │ full range for `variant: high`
544+ │ │ │ focus range
545+ │ │ full range for `variant: medium`
546+ │ │ focus range
547+ │ full range for `variant: low`
548+ ╰╴ focus range
428549 "
429550 ) ;
430551 }
0 commit comments