Skip to content

Commit

Permalink
feat: support enums in go runtime
Browse files Browse the repository at this point in the history
  • Loading branch information
worstell committed Mar 6, 2024
1 parent b869dff commit a551877
Show file tree
Hide file tree
Showing 16 changed files with 681 additions and 83 deletions.
2 changes: 1 addition & 1 deletion backend/schema/metadatacalls.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ func (m *MetadataCalls) String() string {
w += len(str)
fmt.Fprint(out, str)
}
fmt.Fprintln(out)
fmt.Fprint(out)
return out.String()
}

Expand Down
1 change: 0 additions & 1 deletion backend/schema/schema_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ module todo {
verb create(todo.CreateRequest) todo.CreateResponse
calls todo.destroy
verb destroy(builtin.HttpRequest<todo.DestroyRequest>) builtin.HttpResponse<todo.DestroyResponse, String>
ingress http GET /todo/destroy/{id}
}
Expand Down
29 changes: 29 additions & 0 deletions backend/schema/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,22 @@ func ValidateModule(module *Module) error {
return next()
})
merr = cleanErrors(merr)
sort.SliceStable(module.Decls, func(i, j int) bool {
priority := map[reflect.Type]int{
reflect.TypeOf(&Enum{}): 1,
reflect.TypeOf(&Data{}): 2,
reflect.TypeOf(&Verb{}): 3,
}
typeI := reflect.TypeOf(module.Decls[i])
typeJ := reflect.TypeOf(module.Decls[j])
if priority[typeI] == priority[typeJ] {
// Sort by name within the same type.
nameI := getDeclName(module.Decls[i])
nameJ := getDeclName(module.Decls[j])
return nameI < nameJ
}
return priority[typeI] < priority[typeJ]
})
return errors.Join(merr...)
}

Expand Down Expand Up @@ -309,3 +325,16 @@ func cleanErrors(merr []error) []error {
})
return merr
}

func getDeclName(decl Decl) string {
v := reflect.ValueOf(decl)
if v.Kind() == reflect.Ptr {
v = v.Elem()
}
if n := v.FieldByName("Name"); n.IsValid() {
if name, ok := n.Interface().(string); ok {
return name
}
}
return ""
}
89 changes: 89 additions & 0 deletions buildengine/build_go_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package buildengine

import (
"testing"

"github.com/TBD54566975/ftl/backend/schema"
)

func TestGenerateGoModule(t *testing.T) {
sch := &schema.Schema{
Modules: []*schema.Module{
schema.Builtins(),
{Name: "other", Decls: []schema.Decl{
&schema.Enum{
Name: "Color",
Type: &schema.String{},
Variants: []*schema.EnumVariant{
{Name: "Red", Value: &schema.StringValue{Value: "Red"}},
{Name: "Blue", Value: &schema.StringValue{Value: "Blue"}},
{Name: "Green", Value: &schema.StringValue{Value: "Green"}},
},
},
&schema.Enum{
Name: "ColorInt",
Type: &schema.Int{},
Variants: []*schema.EnumVariant{
{Name: "RedInt", Value: &schema.IntValue{Value: 0}},
{Name: "BlueInt", Value: &schema.IntValue{Value: 1}},
{Name: "GreenInt", Value: &schema.IntValue{Value: 2}},
},
},
&schema.Data{Name: "EchoRequest"},
&schema.Data{Name: "EchoResponse"},
&schema.Verb{
Name: "echo",
Request: &schema.DataRef{Name: "EchoRequest"},
Response: &schema.DataRef{Name: "EchoResponse"},
},
}},
{Name: "test"},
},
}
expected := `// Code generated by FTL. DO NOT EDIT.
//ftl:module other
package other
import (
"context"
)
var _ = context.Background
//ftl:enum
type Color string
const (
Red Color = "Red"
Blue Color = "Blue"
Green Color = "Green"
)
//ftl:enum
type ColorInt int
const (
RedInt ColorInt = 0
BlueInt ColorInt = 1
GreenInt ColorInt = 2
)
type EchoRequest struct {
}
type EchoResponse struct {
}
//ftl:verb
func Echo(context.Context, EchoRequest) (EchoResponse, error) {
panic("Verb stubs should not be called directly, instead use github.com/TBD54566975/ftl/runtime-go/ftl.Call()")
}
`
bctx := buildContext{
moduleDir: "testdata/modules/another",
buildDir: "_ftl",
sch: sch,
}
testBuild(t, bctx, []assertion{
assertGeneratedModule("go/modules/other/external_module.go", expected),
})
}
36 changes: 5 additions & 31 deletions buildengine/build_kotlin.go
Original file line number Diff line number Diff line change
Expand Up @@ -158,36 +158,7 @@ var scaffoldFuncs = scaffolder.FuncMap{
"imports": func(m *schema.Module) []string {
imports := sets.NewSet[string]()
_ = schema.Visit(m, func(n schema.Node, next func() error) error {
switch n := n.(type) {
case *schema.DataRef:
decl := m.Resolve(schema.Ref{
Module: n.Module,
Name: n.Name,
})
if decl != nil {
if data, ok := decl.Decl.(*schema.Data); ok {
if len(data.Fields) == 0 {
imports.Add("ftl.builtin.Empty")
break
}
}
}

if n.Module == "" {
break
}

imports.Add("ftl." + n.Module + "." + n.Name)

for _, tp := range n.TypeParameters {
tpRef, err := schema.ParseDataRef(tp.String())
if err != nil {
return err
}
if tpRef.Module != "" && tpRef.Module != m.Name {
imports.Add("ftl." + tpRef.Module + "." + tpRef.Name)
}
}
switch n.(type) {
case *schema.Verb:
imports.Append("xyz.block.ftl.Context", "xyz.block.ftl.Ignore", "xyz.block.ftl.Verb")

Expand All @@ -214,12 +185,15 @@ func genType(module *schema.Module, t schema.Type) string {
if decl != nil {
if data, ok := decl.Decl.(*schema.Data); ok {
if len(data.Fields) == 0 {
return "Empty"
return "ftl.builtin.Empty"
}
}
}

desc := t.Name
if t.Module != "" {
desc = "ftl." + t.Module + "." + desc
}
if len(t.TypeParameters) > 0 {
desc += "<"
for i, tp := range t.TypeParameters {
Expand Down
Loading

0 comments on commit a551877

Please sign in to comment.