@@ -48,6 +48,8 @@ func ExportTypes(ts *guts.Typescript) {
4848 node .Modifiers = append (node .Modifiers , bindings .ModifierExport )
4949 case * bindings.VariableStatement :
5050 node .Modifiers = append (node .Modifiers , bindings .ModifierExport )
51+ case * bindings.Enum :
52+ node .Modifiers = append (node .Modifiers , bindings .ModifierExport )
5153 default :
5254 panic (fmt .Sprintf ("unexpected node type %T for exporting" , node ))
5355 }
@@ -72,12 +74,56 @@ func ReadOnly(ts *guts.Typescript) {
7274 }
7375 }
7476 case * bindings.VariableStatement :
77+ case * bindings.Enum :
78+ // Enums are immutable by default
7579 default :
7680 panic ("unexpected node type for exporting" )
7781 }
7882 })
7983}
8084
85+ // TrimEnumPrefix removes the enum name from the member names.
86+ func TrimEnumPrefix (ts * guts.Typescript ) {
87+ ts .ForEach (func (key string , node bindings.Node ) {
88+ enum , ok := node .(* bindings.Enum )
89+ if ! ok {
90+ return
91+ }
92+
93+ for _ , member := range enum .Members {
94+ member .Name = strings .TrimPrefix (member .Name , enum .Name .Name )
95+ }
96+ })
97+ }
98+
99+ // EnumAsTypes uses types to handle enums rather than using 'enum'.
100+ // An enum will look like:
101+ // type EnumString = "bar" | "baz" | "foo" | "qux";
102+ func EnumAsTypes (ts * guts.Typescript ) {
103+ ts .ForEach (func (key string , node bindings.Node ) {
104+ enum , ok := node .(* bindings.Enum )
105+ if ! ok {
106+ return
107+ }
108+
109+ // Convert the enum to a union type
110+ union := & bindings.UnionType {
111+ Types : make ([]bindings.ExpressionType , 0 , len (enum .Members )),
112+ }
113+ for _ , member := range enum .Members {
114+ union .Types = append (union .Types , member .Value )
115+ }
116+
117+ // Replace the enum with an alias type
118+ ts .ReplaceNode (key , & bindings.Alias {
119+ Name : enum .Name ,
120+ Modifiers : enum .Modifiers ,
121+ Type : union ,
122+ Source : enum .Source ,
123+ })
124+ })
125+ }
126+
81127// EnumLists adds a constant that lists all the values in a given enum.
82128// Example:
83129// type MyEnum = string
@@ -86,72 +132,53 @@ func ReadOnly(ts *guts.Typescript) {
86132// EnumBar = "bar"
87133// )
88134// const MyEnums: string = ["foo", "bar"] <-- this is added
135+ // TODO: Enums were changed to use proper enum types. This should be
136+ // updated to support that. EnumLists only works with EnumAsTypes used first.
89137func EnumLists (ts * guts.Typescript ) {
90138 addNodes := make (map [string ]bindings.Node )
91139 ts .ForEach (func (key string , node bindings.Node ) {
92- switch node := node .(type ) {
93140 // Find the enums, and make a list of values.
94141 // Only support primitive types.
95- case * bindings.Alias :
96- if union , ok := node .Type .(* bindings.UnionType ); ok {
97- if len (union .Types ) == 0 {
98- return
99- }
100-
101- var expectedType * bindings.LiteralType
102- // This might be a union type, if all elements are the same literal type.
103- for _ , t := range union .Types {
104- value , ok := t .(* bindings.LiteralType )
105- if ! ok {
106- return
107- }
108- if expectedType == nil {
109- expectedType = value
110- continue
111- }
112-
113- if reflect .TypeOf (expectedType .Value ) != reflect .TypeOf (value .Value ) {
114- return
115- }
116- }
142+ _ , union , ok := isGoEnum (node )
143+ if ! ok {
144+ return
145+ }
117146
118- values := make ([]bindings.ExpressionType , 0 , len (union .Types ))
119- for _ , t := range union .Types {
120- values = append (values , t )
121- }
147+ values := make ([]bindings.ExpressionType , 0 , len (union .Types ))
148+ for _ , t := range union .Types {
149+ values = append (values , t )
150+ }
122151
123- // Pluralize the name
124- name := key + "s"
125- switch key [len (key )- 1 ] {
126- case 'x' , 's' , 'z' :
127- name = key + "es"
128- }
129- if strings .HasSuffix (key , "ch" ) || strings .HasSuffix (key , "sh" ) {
130- name = key + "es"
131- }
152+ // Pluralize the name
153+ name := key + "s"
154+ switch key [len (key )- 1 ] {
155+ case 'x' , 's' , 'z' :
156+ name = key + "es"
157+ }
158+ if strings .HasSuffix (key , "ch" ) || strings .HasSuffix (key , "sh" ) {
159+ name = key + "es"
160+ }
132161
133- addNodes [name ] = & bindings.VariableStatement {
134- Modifiers : []bindings.Modifier {},
135- Declarations : & bindings.VariableDeclarationList {
136- Declarations : []* bindings.VariableDeclaration {
137- {
138- // TODO: Fix this with Identifier's instead of "string"
139- Name : bindings.Identifier {Name : name },
140- ExclamationMark : false ,
141- Type : & bindings.ArrayType {
142- // The type is the enum type
143- Node : bindings .Reference (bindings.Identifier {Name : key }),
144- },
145- Initializer : & bindings.ArrayLiteralType {
146- Elements : values ,
147- },
148- },
162+ addNodes [name ] = & bindings.VariableStatement {
163+ Modifiers : []bindings.Modifier {},
164+ Declarations : & bindings.VariableDeclarationList {
165+ Declarations : []* bindings.VariableDeclaration {
166+ {
167+ // TODO: Fix this with Identifier's instead of "string"
168+ Name : bindings.Identifier {Name : name },
169+ ExclamationMark : false ,
170+ Type : & bindings.ArrayType {
171+ // The type is the enum type
172+ Node : bindings .Reference (bindings.Identifier {Name : key }),
173+ },
174+ Initializer : & bindings.ArrayLiteralType {
175+ Elements : values ,
149176 },
150- Flags : bindings .NodeFlagsConstant ,
151177 },
152- Source : bindings.Source {},
153- }
154- }
178+ },
179+ Flags : bindings .NodeFlagsConstant ,
180+ },
181+ Source : bindings.Source {},
155182 }
156183 })
157184
@@ -305,3 +332,38 @@ func (v *notNullMaps) Visit(node bindings.Node) walk.Visitor {
305332
306333 return v
307334}
335+
336+ func isGoEnum (n bindings.Node ) (* bindings.Alias , * bindings.UnionType , bool ) {
337+ al , ok := n .(* bindings.Alias )
338+ if ! ok {
339+ return nil , nil , false
340+ }
341+
342+ union , ok := al .Type .(* bindings.UnionType )
343+ if ! ok {
344+ return nil , nil , false
345+ }
346+
347+ if len (union .Types ) == 0 {
348+ return nil , nil , false
349+ }
350+
351+ var expectedType * bindings.LiteralType
352+ // This might be a union type, if all elements are the same literal type.
353+ for _ , t := range union .Types {
354+ value , ok := t .(* bindings.LiteralType )
355+ if ! ok {
356+ return nil , nil , false
357+ }
358+ if expectedType == nil {
359+ expectedType = value
360+ continue
361+ }
362+
363+ if reflect .TypeOf (expectedType .Value ) != reflect .TypeOf (value .Value ) {
364+ return nil , nil , false
365+ }
366+ }
367+
368+ return al , union , true
369+ }
0 commit comments