From 62d307def92a76f1168041c146b81653cd56af6e Mon Sep 17 00:00:00 2001 From: Matt Toohey Date: Thu, 23 May 2024 09:45:47 +1000 Subject: [PATCH 1/2] Revert "fix: support inlined or aliased structs as type enum variants (#1535)" This reverts commit 21df7771a92b9c4ee396d020c8f145da5a06ec52. # Conflicts: # go-runtime/compile/schema_test.go # go-runtime/compile/testdata/failing/failing.go --- .../testdata/projects/another/another.go | 1 + buildengine/testdata/projects/other/other.go | 12 +-- buildengine/testdata/type_registry_main.go | 22 ++--- go-runtime/compile/build.go | 13 --- .../external_module.go | 2 +- go-runtime/compile/schema.go | 98 ++++++++----------- go-runtime/compile/schema_test.go | 34 ++----- .../compile/testdata/failing/failing.go | 6 -- go-runtime/compile/testdata/one/one.go | 23 ----- 9 files changed, 71 insertions(+), 140 deletions(-) diff --git a/buildengine/testdata/projects/another/another.go b/buildengine/testdata/projects/another/another.go index 29db36055a..3feeb64258 100644 --- a/buildengine/testdata/projects/another/another.go +++ b/buildengine/testdata/projects/another/another.go @@ -27,6 +27,7 @@ type One int func (One) typeEnum() {} +//ftl:typealias export type Two string func (Two) typeEnum() {} diff --git a/buildengine/testdata/projects/other/other.go b/buildengine/testdata/projects/other/other.go index fba9dbf85c..01a8c2e900 100644 --- a/buildengine/testdata/projects/other/other.go +++ b/buildengine/testdata/projects/other/other.go @@ -35,21 +35,21 @@ type MyTime time.Time func (MyTime) tag() {} -type MyList []string +type List []string -func (MyList) tag() {} +func (List) tag() {} -type MyMap map[string]string +type Map map[string]string -func (MyMap) tag() {} +func (Map) tag() {} type MyString string func (MyString) tag() {} -type MyStruct struct{} +type Struct struct{} -func (MyStruct) tag() {} +func (Struct) tag() {} type MyOption ftl.Option[string] diff --git a/buildengine/testdata/type_registry_main.go b/buildengine/testdata/type_registry_main.go index c3fbba29c6..72dbbdcaee 100644 --- a/buildengine/testdata/type_registry_main.go +++ b/buildengine/testdata/type_registry_main.go @@ -32,17 +32,17 @@ func main() { *new(other.B), ), reflection.WithSumType[other.TypeEnum]( - *new(other.MyBool), - *new(other.MyBytes), - *new(other.MyFloat), - *new(other.MyInt), - *new(other.MyTime), - *new(other.MyList), - *new(other.MyMap), - *new(other.MyString), - *new(other.MyStruct), - *new(other.MyOption), - *new(other.MyUnit), + *new(other.Bool), + *new(other.Bytes), + *new(other.Float), + *new(other.Int), + *new(other.Time), + *new(other.List), + *new(other.Map), + *new(other.String), + *new(other.Struct), + *new(other.Option), + *new(other.Unit), ), ) ctx = reflection.ContextWithTypeRegistry(ctx, tr) diff --git a/go-runtime/compile/build.go b/go-runtime/compile/build.go index 82b36edac8..f027d2fcd2 100644 --- a/go-runtime/compile/build.go +++ b/go-runtime/compile/build.go @@ -350,19 +350,6 @@ var scaffoldFuncs = scaffolder.FuncMap{ return out }, "schemaType": schemaType, - // A standalone enum variant is one that is purely an alias to a type and does not appear - // elsewhere in the schema. - "isStandaloneEnumVariant": func(v schema.EnumVariant) bool { - tv, ok := v.Value.(*schema.TypeValue) - if !ok { - return false - } - if ref, ok := tv.Value.(*schema.Ref); ok { - return ref.Name != v.Name - } - - return false - }, } func schemaType(t schema.Type) string { diff --git a/go-runtime/compile/external-module-template/_ftl/go/modules/{{ range .NonMainModules }}{{ push .Name . }}{{ end }}/external_module.go b/go-runtime/compile/external-module-template/_ftl/go/modules/{{ range .NonMainModules }}{{ push .Name . }}{{ end }}/external_module.go index 2c55ad8d27..3af5a9754c 100644 --- a/go-runtime/compile/external-module-template/_ftl/go/modules/{{ range .NonMainModules }}{{ push .Name . }}{{ end }}/external_module.go +++ b/go-runtime/compile/external-module-template/_ftl/go/modules/{{ range .NonMainModules }}{{ push .Name . }}{{ end }}/external_module.go @@ -31,7 +31,7 @@ const ( {{$enumInterfaceFuncName := enumInterfaceFunc . -}} type {{.Name|title}} interface { {{$enumInterfaceFuncName}}() } {{- range .Variants }} -{{if (or (basicType $ .) (isStandaloneEnumVariant .))}} +{{if basicType $ .}} type {{.Name|title}} {{type $ .Value.Value}} {{end}} func ({{.Name|title}}) {{$enumInterfaceFuncName}}() {} diff --git a/go-runtime/compile/schema.go b/go-runtime/compile/schema.go index 926a193e37..7f6b301dec 100644 --- a/go-runtime/compile/schema.go +++ b/go-runtime/compile/schema.go @@ -240,7 +240,7 @@ func extractTypeDeclsForNode(pctx *parseContext, node *ast.GenDecl) { switch dir := dir.(type) { case *directiveEnum: typ := pctx.pkg.TypesInfo.TypeOf(t.Type) - switch underlying := typ.Underlying().(type) { + switch typ.Underlying().(type) { case *types.Basic: enum := &schema.Enum{ Pos: goPosToSchemaPos(node.Pos()), @@ -252,23 +252,6 @@ func extractTypeDeclsForNode(pctx *parseContext, node *ast.GenDecl) { pctx.module.Decls = append(pctx.module.Decls, enum) pctx.nativeNames[enum] = nativeName case *types.Interface: - if underlying.NumMethods() == 0 { - pctx.errors.add(errorf(node, "enum discriminator %q must define at least one method", t.Name.Name)) - break - } - - hasExportedMethod := false - for i, n := 0, underlying.NumMethods(); i < n; i++ { - if underlying.Method(i).Exported() { - pctx.errors.add(noEndColumnErrorf(underlying.Method(i).Pos(), "enum discriminator %q cannot "+ - "contain exported methods", t.Name.Name)) - hasExportedMethod = true - } - } - if hasExportedMethod { - break - } - enum := &schema.Enum{ Pos: goPosToSchemaPos(node.Pos()), Comments: visitComments(node.Doc), @@ -688,7 +671,7 @@ func visitGenDecl(pctx *parseContext, node *ast.GenDecl) { } } } else if _, ok := dir.(*directiveTypeAlias); ok { - decl, ok := pctx.getDeclForTypeName(t.Name.Name).Get() + decl, ok := pctx.getDeclForTypeName(t.Name.Name) if !ok { pctx.errors.add(errorf(node, "could not find type alias declaration for %q", t.Name.Name)) return @@ -799,7 +782,10 @@ func maybeVisitTypeEnumVariant(pctx *parseContext, node *ast.GenDecl, directives isExported := enum.IsExported() for _, dir := range directives { if exportableDir, ok := dir.(exportable); ok { - isExported = exportableDir.IsExported() || isExported + if enum.Export && !exportableDir.IsExported() { + pctx.errors.add(errorf(node, "parent enum %q is exported, but directive %q on %q is not: all variants of exported enums that have a directive must be explicitly exported as well", enumName, exportableDir, t.Name.Name)) + } + isExported = exportableDir.IsExported() } } vType, ok := visitTypeValue(pctx, named, t.Type, nil, isExported).Get() @@ -879,11 +865,7 @@ func visitTypeValue(pctx *parseContext, named *types.Named, tnode ast.Expr, inde } default: - variantNode := pctx.pkg.TypesInfo.TypeOf(tnode) - if _, ok := variantNode.(*types.Struct); ok { - variantNode = named - } - if typ, ok := visitType(pctx, tnode.Pos(), variantNode, isExported).Get(); ok { + if typ, ok := visitType(pctx, tnode.Pos(), named, isExported).Get(); ok { return optional.Some(&schema.TypeValue{Value: typ}) } else { pctx.errors.add(errorf(tnode, "unsupported type %q for type enum variant", named)) @@ -1256,14 +1238,20 @@ func visitType(pctx *parseContext, pos token.Pos, tnode types.Type, isExported b if tparam, ok := tnode.(*types.TypeParam); ok { return optional.Some[schema.Type](&schema.Ref{Pos: goPosToSchemaPos(pos), Name: tparam.Obj().Id()}) } - if named, ok := tnode.(*types.Named); ok { // Handle refs to type aliases and enums, rather than the underlying type. - decl, ok := pctx.getDeclForTypeName(named.Obj().Name()).Get() + decl, ok := pctx.getDeclForTypeName(named.Obj().Name()) if ok { switch decl.(type) { case *schema.TypeAlias, *schema.Enum: - return visitNamedRef(pctx, pos, named, isExported) + if isExported { + pctx.markAsExported(decl) + } + return optional.Some[schema.Type](&schema.Ref{ + Pos: goPosToSchemaPos(pos), + Module: pctx.module.Name, + Name: strcase.ToUpperCamel(named.Obj().Name()), + }) case *schema.Data, *schema.Verb, *schema.Config, *schema.Secret, *schema.Database, *schema.FSM: } } @@ -1272,8 +1260,12 @@ func visitType(pctx *parseContext, pos token.Pos, tnode types.Type, isExported b switch underlying := tnode.Underlying().(type) { case *types.Basic: if named, ok := tnode.(*types.Named); ok { - return visitNamedRef(pctx, pos, named, isExported) + ref, doneWithVisit := visitNamedRef(pctx, pos, named) + if doneWithVisit { + return ref + } } + switch underlying.Kind() { case types.String: return optional.Some[schema.Type](&schema.String{Pos: goPosToSchemaPos(pos)}) @@ -1340,7 +1332,10 @@ func visitType(pctx *parseContext, pos token.Pos, tnode types.Type, isExported b return optional.Some[schema.Type](&schema.Any{Pos: goPosToSchemaPos(pos)}) } if named, ok := tnode.(*types.Named); ok { - return visitNamedRef(pctx, pos, named, isExported) + ref, doneWithVisit := visitNamedRef(pctx, pos, named) + if doneWithVisit { + return ref + } } return optional.None[schema.Type]() @@ -1349,39 +1344,32 @@ func visitType(pctx *parseContext, pos token.Pos, tnode types.Type, isExported b } } -func visitNamedRef(pctx *parseContext, pos token.Pos, named *types.Named, isExported bool) optional.Option[schema.Type] { +func visitNamedRef(pctx *parseContext, pos token.Pos, named *types.Named) (optional.Option[schema.Type], bool) { if named.Obj().Pkg() == nil { - return optional.None[schema.Type]() + return optional.None[schema.Type](), false } - - // Update the visibility of the reference if the referencer is exported (ensuring refs are transitively - // exported as needed). - if isExported { - if decl, ok := pctx.getDeclForTypeName(named.Obj().Name()).Get(); ok { - pctx.markAsExported(decl) - } - } - nodePath := named.Obj().Pkg().Path() - destModule := pctx.module.Name + var ref *schema.Ref if !pctx.isPathInPkg(nodePath) { if strings.HasPrefix(nodePath, pctx.pkg.PkgPath+"/") { pctx.errors.add(noEndColumnErrorf(pos, "unsupported type %s from subpackage", named.Obj().Pkg().Path()+"."+named.Obj().Name())) - return optional.None[schema.Type]() + return optional.None[schema.Type](), true } else if !strings.HasPrefix(named.Obj().Pkg().Path(), "ftl/") { pctx.errors.add(noEndColumnErrorf(pos, "unsupported external type %q", named.Obj().Pkg().Path()+"."+named.Obj().Name())) - return optional.None[schema.Type]() + return optional.None[schema.Type](), true } base := path.Dir(pctx.pkg.PkgPath) - destModule = path.Base(strings.TrimPrefix(nodePath, base+"/")) - } - ref := &schema.Ref{ - Pos: goPosToSchemaPos(pos), - Module: destModule, - Name: strcase.ToUpperCamel(named.Obj().Name()), + destModule := path.Base(strings.TrimPrefix(nodePath, base+"/")) + ref = &schema.Ref{ + Pos: goPosToSchemaPos(pos), + Module: destModule, + Name: named.Obj().Name(), + } + return optional.Some[schema.Type](ref), true } - return optional.Some[schema.Type](ref) + return optional.None[schema.Type](), false + } func visitMap(pctx *parseContext, pos token.Pos, tnode *types.Map, isExported bool) optional.Option[schema.Type] { @@ -1539,7 +1527,7 @@ func (p *parseContext) isPathInPkg(path string) bool { // getEnumForTypeName returns the enum and interface for a given type name. func (p *parseContext) getEnumForTypeName(name string) (optional.Option[*schema.Enum], optional.Option[*types.Interface]) { - aDecl, ok := p.getDeclForTypeName(name).Get() + aDecl, ok := p.getDeclForTypeName(name) if !ok { return optional.None[*schema.Enum](), optional.None[*types.Interface]() } @@ -1558,7 +1546,7 @@ func (p *parseContext) getEnumForTypeName(name string) (optional.Option[*schema. return optional.Some(decl), optional.None[*types.Interface]() } -func (p *parseContext) getDeclForTypeName(name string) optional.Option[schema.Decl] { +func (p *parseContext) getDeclForTypeName(name string) (enum schema.Decl, ok bool) { for _, decl := range p.module.Decls { nativeName, ok := p.nativeNames[decl] if !ok { @@ -1567,9 +1555,9 @@ func (p *parseContext) getDeclForTypeName(name string) optional.Option[schema.De if nativeName != p.pkg.Name+"."+name { continue } - return optional.Some(decl) + return decl, true } - return optional.None[schema.Decl]() + return nil, false } func (p *parseContext) markAsExported(node schema.Node) { diff --git a/go-runtime/compile/schema_test.go b/go-runtime/compile/schema_test.go index 4e9fac48da..2f2614e7f9 100644 --- a/go-runtime/compile/schema_test.go +++ b/go-runtime/compile/schema_test.go @@ -65,7 +65,7 @@ func TestExtractModuleSchema(t *testing.T) { } // Comments about ColorInt. - export enum ColorInt: Int { + enum ColorInt: Int { // RedInt is a color. RedInt = 0 BlueInt = 1 @@ -92,13 +92,6 @@ func TestExtractModuleSchema(t *testing.T) { Two = 2 } - export enum TypeEnum { - Option String? - InlineStruct one.InlineStruct - AliasedStruct one.UnderlyingStruct - ValueEnum one.ColorInt - } - data Config { field String } @@ -114,9 +107,6 @@ func TestExtractModuleSchema(t *testing.T) { export data ExportedStruct { } - export data InlineStruct { - } - export data Nested { } @@ -150,9 +140,6 @@ func TestExtractModuleSchema(t *testing.T) { data SourceResp { } - export data UnderlyingStruct { - } - data WithoutDirectiveStruct { } @@ -323,7 +310,7 @@ func TestExtractModuleSchemaNamedTypes(t *testing.T) { assert.Equal(t, normaliseString(expected), normaliseString(actual.String())) } -func TestParsedirectives(t *testing.T) { +func TestParseDirectives(t *testing.T) { tests := []struct { name string input string @@ -452,19 +439,16 @@ func TestErrorReporting(t *testing.T) { `90:2-12: struct field unexported must be exported by starting with an uppercase letter`, `102:2-24: cannot attach enum value to BadValueEnum because it is a variant of type enum TypeEnum, not a value enum`, `109:2-41: cannot attach enum value to BadValueEnumOrderDoesntMatter because it is a variant of type enum TypeEnum, not a value enum`, + `118:1-26: parent enum "ExportedTypeEnum" is exported, but directive "ftl:data" on "PrivateData" is not: all variants of exported enums that have a directive must be explicitly exported as well`, `122:21-60: config and secret names must be valid identifiers`, `128:1-26: only one directive expected for type alias`, `144:1-35: type can not be a variant of more than 1 type enums (TypeEnum1, TypeEnum2)`, - `150:27-27: enum discriminator "TypeEnum3" cannot contain exported methods`, - `153:1-35: enum discriminator "NoMethodsTypeEnum" must define at least one method`, - `156:1-2: could not find enum called NoMethodsTypeEnum`, - `158:2-2: unsupported type ftl/failing/child.ChildStruct from subpackage`, - `158:2-6: unsupported type "ftl/failing/child.ChildStruct" for field "Data"`, - `159:2-2: unsupported type ftl/failing/child.ChildString from subpackage`, - `159:2-8: unsupported type "ftl/failing/child.ChildString" for field "String"`, - `163:1-1: unsupported type ftl/failing/child.ChildStruct from subpackage`, - "163:1-33: could not find enum called NoMethodsTypeEnum", - `163:1-33: unsupported type "struct{Name string}" for type alias`, + `152:2-2: unsupported type ftl/failing/child.ChildStruct from subpackage`, + `152:2-6: unsupported type "ftl/failing/child.ChildStruct" for field "Data"`, + `153:2-2: unsupported type ftl/failing/child.ChildString from subpackage`, + `153:2-8: unsupported type "ftl/failing/child.ChildString" for field "String"`, + `157:1-1: unsupported type ftl/failing/child.ChildStruct from subpackage`, + `157:1-33: unsupported type "struct{Name string}" for type alias`, } assert.Equal(t, expected, actual) } diff --git a/go-runtime/compile/testdata/failing/failing.go b/go-runtime/compile/testdata/failing/failing.go index 976fd3d559..058013659d 100644 --- a/go-runtime/compile/testdata/failing/failing.go +++ b/go-runtime/compile/testdata/failing/failing.go @@ -146,12 +146,6 @@ type ConformsToTwoTypeEnums string func (ConformsToTwoTypeEnums) typeEnum1() {} func (ConformsToTwoTypeEnums) typeEnum2() {} -//ftl:enum -type TypeEnum3 interface{ ExportedMethod() } - -//ftl:enum -type NoMethodsTypeEnum interface{} - //ftl:data type StructUsingSubpackage struct { Message string `json:"message"` diff --git a/go-runtime/compile/testdata/one/one.go b/go-runtime/compile/testdata/one/one.go index 48dca4ac9b..6f7140a4fa 100644 --- a/go-runtime/compile/testdata/one/one.go +++ b/go-runtime/compile/testdata/one/one.go @@ -64,29 +64,6 @@ func (List) blobOrList() {} type Nested struct { } -//ftl:enum -type TypeEnum interface { - tag() -} - -type Option ftl.Option[string] - -func (Option) tag() {} - -type InlineStruct struct{} - -func (InlineStruct) tag() {} - -type AliasedStruct UnderlyingStruct - -func (AliasedStruct) tag() {} - -type UnderlyingStruct struct{} - -type ValueEnum ColorInt - -func (ValueEnum) tag() {} - //ftl:enum type PrivateEnum interface{ privateEnum() } From c04c7c341085df74ff6b99803f2f01e7b9c41986 Mon Sep 17 00:00:00 2001 From: Matt Toohey Date: Thu, 23 May 2024 09:47:54 +1000 Subject: [PATCH 2/2] Revert "fix: do not treat subpackage paths as part of the current package (#1530)" This reverts commit 3f74d1c4e86ecada949e7cfed6022b661adde79e. # Conflicts: # go-runtime/compile/schema.go # go-runtime/compile/schema_test.go # go-runtime/compile/testdata/failing/failing.go --- go-runtime/compile/schema.go | 42 ++------- go-runtime/compile/schema_test.go | 86 +++++++++---------- .../compile/testdata/failing/child/child.go | 7 -- .../compile/testdata/failing/failing.go | 16 ---- 4 files changed, 47 insertions(+), 104 deletions(-) delete mode 100644 go-runtime/compile/testdata/failing/child/child.go diff --git a/go-runtime/compile/schema.go b/go-runtime/compile/schema.go index 7f6b301dec..c9a7e1649e 100644 --- a/go-runtime/compile/schema.go +++ b/go-runtime/compile/schema.go @@ -23,7 +23,6 @@ import ( "github.com/TBD54566975/ftl/backend/schema/strcase" "github.com/TBD54566975/ftl/internal/errors" "github.com/TBD54566975/ftl/internal/goast" - islices "github.com/TBD54566975/ftl/internal/slices" ) var ( @@ -1075,10 +1074,6 @@ func visitStruct(pctx *parseContext, pos token.Pos, tnode types.Type, isExported } nodePath := named.Obj().Pkg().Path() if !pctx.isPathInPkg(nodePath) { - if strings.HasPrefix(nodePath, pctx.pkg.PkgPath+"/") { - pctx.errors.add(noEndColumnErrorf(pos, "unsupported struct %s from subpackage", named.Obj().Name())) - return optional.None[*schema.Ref]() - } destModule, ok := ftlModuleFromGoModule(nodePath).Get() if !ok { pctx.errors.add(tokenErrorf(pos, nodePath, "struct declared in non-FTL module %s", nodePath)) @@ -1306,14 +1301,9 @@ func visitType(pctx *parseContext, pos token.Pos, tnode types.Type, isExported b default: nodePath := named.Obj().Pkg().Path() - if !pctx.isPathInPkg(nodePath) { - if !strings.HasPrefix(nodePath, "ftl/") { - pctx.errors.add(noEndColumnErrorf(pos, "unsupported external type %s", nodePath+"."+named.Obj().Name())) - return optional.None[schema.Type]() - } else if strings.HasPrefix(nodePath, pctx.pkg.PkgPath+"/") { - pctx.errors.add(noEndColumnErrorf(pos, "unsupported type %s from subpackage", nodePath+"."+named.Obj().Name())) - return optional.None[schema.Type]() - } + if !pctx.isPathInPkg(nodePath) && !strings.HasPrefix(nodePath, "ftl/") { + pctx.errors.add(noEndColumnErrorf(pos, "unsupported external type %s", nodePath+"."+named.Obj().Name())) + return optional.None[schema.Type]() } if ref, ok := visitStruct(pctx, pos, tnode, isExported).Get(); ok { return optional.Some[schema.Type](ref) @@ -1351,10 +1341,7 @@ func visitNamedRef(pctx *parseContext, pos token.Pos, named *types.Named) (optio nodePath := named.Obj().Pkg().Path() var ref *schema.Ref if !pctx.isPathInPkg(nodePath) { - if strings.HasPrefix(nodePath, pctx.pkg.PkgPath+"/") { - pctx.errors.add(noEndColumnErrorf(pos, "unsupported type %s from subpackage", named.Obj().Pkg().Path()+"."+named.Obj().Name())) - return optional.None[schema.Type](), true - } else if !strings.HasPrefix(named.Obj().Pkg().Path(), "ftl/") { + if !strings.HasPrefix(named.Obj().Pkg().Path(), "ftl/") { pctx.errors.add(noEndColumnErrorf(pos, "unsupported external type %q", named.Obj().Pkg().Path()+"."+named.Obj().Name())) return optional.None[schema.Type](), true @@ -1503,26 +1490,11 @@ func (p *parseContext) pathEnclosingInterval(start, end token.Pos) (pkg *package return nil, nil, false } -// isPathInPkg checks that the path is within the current package -// -// if it is in a subpackage, it will return false func (p *parseContext) isPathInPkg(path string) bool { - // find all packages whose path is a prefix of the given path - pkgs := islices.Filter(p.pkgs, func(pkg *packages.Package) bool { - if path == pkg.PkgPath { - return true - } - return strings.HasPrefix(path, pkg.PkgPath+"/") - }) - if len(pkgs) == 0 { - return false + if path == p.pkg.PkgPath { + return true } - // sort so we know if the current package is the longest prefix - paths := islices.Map(pkgs, func(pkg *packages.Package) string { - return pkg.PkgPath - }) - slices.Sort(paths) - return paths[len(paths)-1] == p.pkg.PkgPath + return strings.HasPrefix(path, p.pkg.PkgPath+"/") } // getEnumForTypeName returns the enum and interface for a given type name. diff --git a/go-runtime/compile/schema_test.go b/go-runtime/compile/schema_test.go index 2f2614e7f9..ccb971501b 100644 --- a/go-runtime/compile/schema_test.go +++ b/go-runtime/compile/schema_test.go @@ -403,52 +403,46 @@ func TestErrorReporting(t *testing.T) { filename := filepath.Join(pwd, `testdata/failing/failing.go`) actual := slices.Map(r.MustGet().Errors, func(e *schema.Error) string { return strings.TrimPrefix(e.Error(), filename+":") }) expected := []string{ - `11:13-34: first argument to config and secret declarations must be the name as a string literal`, - `14:18-52: duplicate config declaration at 13:18-52`, - `17:18-52: duplicate secret declaration at 16:18-52`, - `20:14-44: duplicate database declaration at 19:14-44`, - `23:2-10: unsupported type "error" for field "BadParam"`, - `26:2-17: unsupported type "uint64" for field "AnotherBadParam"`, - `29:3-3: unexpected token "export" (expected Directive)`, - `35:36-39: unsupported request type "ftl/failing.Request"`, - `35:50-50: unsupported response type "ftl/failing.Response"`, - `36:16-29: call first argument must be a function but is an unresolved reference to lib.OtherFunc`, - `36:16-29: call first argument must be a function in an ftl module`, - `37:2-46: call must have exactly three arguments`, - `38:16-25: call first argument must be a function in an ftl module`, - `43:1-2: must have at most two parameters (context.Context, struct)`, - `43:69-69: unsupported response type "ftl/failing.Response"`, - `48:22-27: first parameter must be of type context.Context but is ftl/failing.Request`, - `48:37-43: second parameter must be a struct but is string`, - `48:53-53: unsupported response type "ftl/failing.Response"`, - `53:43-47: second parameter must not be ftl.Unit`, - `53:59-59: unsupported response type "ftl/failing.Response"`, - `58:1-2: first parameter must be context.Context`, - `58:18-18: unsupported response type "ftl/failing.Response"`, - `63:1-2: must have at most two results (struct, error)`, - `63:41-44: unsupported request type "ftl/failing.Request"`, - `68:1-2: must at least return an error`, - `68:36-39: unsupported request type "ftl/failing.Request"`, - `72:35-38: unsupported request type "ftl/failing.Request"`, - `72:48-48: must return an error but is ftl/failing.Response`, - `77:41-44: unsupported request type "ftl/failing.Request"`, - `77:55-55: first result must be a struct but is string`, - `77:63-63: must return an error but is string`, - `77:63-63: second result must not be ftl.Unit`, - `84:1-1: duplicate verb name "WrongResponse"`, - `90:2-12: struct field unexported must be exported by starting with an uppercase letter`, - `102:2-24: cannot attach enum value to BadValueEnum because it is a variant of type enum TypeEnum, not a value enum`, - `109:2-41: cannot attach enum value to BadValueEnumOrderDoesntMatter because it is a variant of type enum TypeEnum, not a value enum`, - `118:1-26: parent enum "ExportedTypeEnum" is exported, but directive "ftl:data" on "PrivateData" is not: all variants of exported enums that have a directive must be explicitly exported as well`, - `122:21-60: config and secret names must be valid identifiers`, - `128:1-26: only one directive expected for type alias`, - `144:1-35: type can not be a variant of more than 1 type enums (TypeEnum1, TypeEnum2)`, - `152:2-2: unsupported type ftl/failing/child.ChildStruct from subpackage`, - `152:2-6: unsupported type "ftl/failing/child.ChildStruct" for field "Data"`, - `153:2-2: unsupported type ftl/failing/child.ChildString from subpackage`, - `153:2-8: unsupported type "ftl/failing/child.ChildString" for field "String"`, - `157:1-1: unsupported type ftl/failing/child.ChildStruct from subpackage`, - `157:1-33: unsupported type "struct{Name string}" for type alias`, + `10:13-34: first argument to config and secret declarations must be the name as a string literal`, + `13:18-52: duplicate config declaration at 12:18-52`, + `16:18-52: duplicate secret declaration at 15:18-52`, + `19:14-44: duplicate database declaration at 18:14-44`, + `22:2-10: unsupported type "error" for field "BadParam"`, + `25:2-17: unsupported type "uint64" for field "AnotherBadParam"`, + `28:3-3: unexpected token "export" (expected Directive)`, + `34:36-39: unsupported request type "ftl/failing.Request"`, + `34:50-50: unsupported response type "ftl/failing.Response"`, + `35:16-29: call first argument must be a function but is an unresolved reference to lib.OtherFunc`, + `35:16-29: call first argument must be a function in an ftl module`, + `36:2-46: call must have exactly three arguments`, + `37:16-25: call first argument must be a function in an ftl module`, + `42:1-2: must have at most two parameters (context.Context, struct)`, + `42:69-69: unsupported response type "ftl/failing.Response"`, + `47:22-27: first parameter must be of type context.Context but is ftl/failing.Request`, + `47:37-43: second parameter must be a struct but is string`, + `47:53-53: unsupported response type "ftl/failing.Response"`, + `52:43-47: second parameter must not be ftl.Unit`, + `52:59-59: unsupported response type "ftl/failing.Response"`, + `57:1-2: first parameter must be context.Context`, + `57:18-18: unsupported response type "ftl/failing.Response"`, + `62:1-2: must have at most two results (struct, error)`, + `62:41-44: unsupported request type "ftl/failing.Request"`, + `67:1-2: must at least return an error`, + `67:36-39: unsupported request type "ftl/failing.Request"`, + `71:35-38: unsupported request type "ftl/failing.Request"`, + `71:48-48: must return an error but is ftl/failing.Response`, + `76:41-44: unsupported request type "ftl/failing.Request"`, + `76:55-55: first result must be a struct but is string`, + `76:63-63: must return an error but is string`, + `76:63-63: second result must not be ftl.Unit`, + `83:1-1: duplicate verb name "WrongResponse"`, + `89:2-12: struct field unexported must be exported by starting with an uppercase letter`, + `101:2-24: cannot attach enum value to BadValueEnum because it is a variant of type enum TypeEnum, not a value enum`, + `108:2-41: cannot attach enum value to BadValueEnumOrderDoesntMatter because it is a variant of type enum TypeEnum, not a value enum`, + `117:1-26: parent enum "ExportedTypeEnum" is exported, but directive "ftl:data" on "PrivateData" is not: all variants of exported enums that have a directive must be explicitly exported as well`, + `121:21-60: config and secret names must be valid identifiers`, + `127:1-26: only one directive expected for type alias`, + `143:1-35: type can not be a variant of more than 1 type enums (TypeEnum1, TypeEnum2)`, } assert.Equal(t, expected, actual) } diff --git a/go-runtime/compile/testdata/failing/child/child.go b/go-runtime/compile/testdata/failing/child/child.go deleted file mode 100644 index 2754d93352..0000000000 --- a/go-runtime/compile/testdata/failing/child/child.go +++ /dev/null @@ -1,7 +0,0 @@ -package child - -type ChildStruct struct { - Name string -} - -type ChildString string diff --git a/go-runtime/compile/testdata/failing/failing.go b/go-runtime/compile/testdata/failing/failing.go index 058013659d..880db2b379 100644 --- a/go-runtime/compile/testdata/failing/failing.go +++ b/go-runtime/compile/testdata/failing/failing.go @@ -2,7 +2,6 @@ package failing import ( "context" - "ftl/failing/child" lib "github.com/TBD54566975/ftl/go-runtime/compile/testdata" "github.com/TBD54566975/ftl/go-runtime/ftl" @@ -145,18 +144,3 @@ type ConformsToTwoTypeEnums string func (ConformsToTwoTypeEnums) typeEnum1() {} func (ConformsToTwoTypeEnums) typeEnum2() {} - -//ftl:data -type StructUsingSubpackage struct { - Message string `json:"message"` - Data child.ChildStruct `json:"data"` - String child.ChildString `json:"string"` -} - -//ftl:typealias -type TypeAlias child.ChildStruct - -func aFunc() { - // nothing wrong with using a child struct normally - _ = child.ChildStruct{} -}