Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

mkunion serde, go:tag support, simplification of x/shape #91

Merged
merged 121 commits into from
Jan 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
121 commits
Select commit Hold shift + click to select a range
3ee9e79
x/shape: improve typescript generation
widmogrod Dec 15, 2023
e795eaa
mkunion: update main.go to generate typescript from all shapes
widmogrod Dec 15, 2023
614eeb6
my-app: regenerate typescript types
widmogrod Dec 15, 2023
3678db2
x/shape supports tags in comments like //go:tag json:"name,omitempty"
widmogrod Dec 15, 2023
f1b87b0
x/shape refactor InferredInfo methods
widmogrod Dec 15, 2023
3a6b1f7
cmd: update shape.InferredInfo change of signatures
widmogrod Dec 15, 2023
404f7ea
big set of changes for "serde" support and better type extraction in …
widmogrod Dec 17, 2023
ea71b27
mkunion serde works
widmogrod Dec 17, 2023
4c2e8ba
my-app: leverages new features
widmogrod Dec 17, 2023
6b4bd46
cmd/mkunion serde generates serialisation in the same file name
widmogrod Dec 17, 2023
77390c6
x/schema: remove it from code generation
widmogrod Dec 17, 2023
66e171f
x/shape improvements to type extraction
widmogrod Dec 19, 2023
466ae33
x/shared: register types as well (helps with x/schema)
widmogrod Dec 19, 2023
27ec842
x/schema: crazy refactor, remove {From,To}JSON and leverage x/shape
widmogrod Dec 19, 2023
455e7fd
x/storage/predicate: leverage new x/schema
widmogrod Dec 19, 2023
d1f2210
x/storage/storage: leverage new x/schema
widmogrod Dec 19, 2023
d7576dd
x/taskqueue: leverage new x/schema
widmogrod Dec 19, 2023
9ee17bf
x/workflow: leverage new x/schema
widmogrod Dec 19, 2023
49e5444
x/schema: better primitive support and reflection
widmogrod Dec 19, 2023
2e22984
x/shape: better LookupRefs implementation
widmogrod Dec 19, 2023
d8d2220
my-app: remove completely x/schema {From,To}JSON
widmogrod Dec 19, 2023
22090bb
example: add type hints
widmogrod Dec 19, 2023
13ad5d0
x/generators: serde_json_tagged.go supports x/shape.AliasLike generation
widmogrod Dec 19, 2023
9ee73bd
x/storage/predicate: regenerated JSONMarshal using `go:tag serde:"json"`
widmogrod Dec 19, 2023
7e5a3af
x/generators serde_json_tagged.go respects go tag `json:"name"`
widmogrod Dec 19, 2023
a8d6649
x/schema use shape.LookupShape
widmogrod Dec 19, 2023
9d244a0
x/shape type instantiation now copy tags as well
widmogrod Dec 19, 2023
80b1f89
x/storage/predicate now leverage x/shape.LookupShape
widmogrod Dec 19, 2023
94172ae
x/storage: refactor to leverage x/shape and x/schema generic features
widmogrod Dec 19, 2023
ae274f7
x/taskqueue: updated to use x/storage with generics
widmogrod Dec 19, 2023
7c73671
x/workflow: leverage new x/storage with generics
widmogrod Dec 19, 2023
3461872
x/storage: commit regenerated models
widmogrod Dec 19, 2023
85df1f5
x/generators/testutils: update test
widmogrod Dec 19, 2023
208915b
x/storage/typed now allow for 1:1 mapping for filters, order by as type
widmogrod Dec 21, 2023
24acf88
x/taskqueue: use generics
widmogrod Dec 21, 2023
0ab7821
x/schema: GetShapeSchemaLocation fix Alias behaviour
widmogrod Dec 21, 2023
fac7ea7
my-app: app profiling capabilities
widmogrod Dec 22, 2023
b5b052b
x/shape: IsBinary(shape) function
widmogrod Dec 23, 2023
7120f47
x/shape {To,From}GoReflect optimise operations on []byte
widmogrod Dec 23, 2023
364680a
use logrus
widmogrod Dec 23, 2023
f5a7818
prevent default form bahaviour
widmogrod Dec 23, 2023
c344afd
x/schema: use shape.LookupShapeReflectAndIndex
widmogrod Dec 23, 2023
4879492
x/shape: introduce LookupShapeReflectAndIndex
widmogrod Dec 23, 2023
5154020
x/storage/schemaless: introduce AppendLoger interface
widmogrod Dec 23, 2023
2a5369e
x/storage/schemaless/typedful: TypedLocation extracted as separate st…
widmogrod Dec 23, 2023
b56be07
x/storage/schemaless/typedful: TypedRepoWithAggregator use
widmogrod Dec 23, 2023
63295d6
x/storage/schemaless/typedful: dummy TypedAppendLog
widmogrod Dec 23, 2023
2cba0f0
x/taskqueue: use schemaless.AppendLoger
widmogrod Dec 23, 2023
cf9fe77
my-app: now use typed task queue
widmogrod Dec 23, 2023
f5af94a
my-app: submit callbacks
widmogrod Dec 23, 2023
0a95997
my-app: paginated table and sorting with x/schemaless integration
widmogrod Dec 23, 2023
32a5396
my-app: paginated table row selection
widmogrod Dec 24, 2023
da9d570
my-app: deser_json use shared.JSONMarshal in few cases
widmogrod Dec 24, 2023
498a285
x/storege: regenerate
widmogrod Dec 24, 2023
fb9439f
x/workflow: test json serialization
widmogrod Dec 24, 2023
c04cbc1
my-app: introduce flow and states updating
widmogrod Dec 24, 2023
13cbade
my-app: Paginated table actions on selected items
widmogrod Dec 24, 2023
f320d1b
x/workflow: support parent run scheduling
widmogrod Dec 24, 2023
e23ca13
regenerate serde
widmogrod Dec 24, 2023
d1fb43d
my-app: render parentRunID
widmogrod Dec 24, 2023
eacf208
workflow: simplify ParentRunID
widmogrod Dec 24, 2023
3e747ea
my-app: ParentRunID refactor
widmogrod Dec 24, 2023
c14c15f
x/storage: regenerate
widmogrod Dec 24, 2023
7c286bb
x/workflow: try recover accepts RunID
widmogrod Dec 25, 2023
869ad2b
regenerate
widmogrod Dec 25, 2023
cf6f431
my-app: try recover from error workflow state demo
widmogrod Dec 25, 2023
0e57f5c
my-app: render workflow on state list
widmogrod Dec 26, 2023
d48a885
x/workflow: update schema to string function
widmogrod Dec 26, 2023
f87a4e7
x/generators: remove schema generator
widmogrod Dec 30, 2023
1e50e1b
x/generators: introduce generator for x/shape designed to be used for…
widmogrod Dec 30, 2023
237b105
x/generators: extract padLeftTabs functions
widmogrod Dec 30, 2023
d53070b
x/generators: shape_generator now register shapes in init() function
widmogrod Dec 30, 2023
b803016
x/shape: introduce Register function and make sure that LookupShape s…
widmogrod Dec 30, 2023
173e652
different packages use x/shape.ErrShapeNotFound in panic situations
widmogrod Dec 30, 2023
516fe2e
x/shape: LookupShape and LookupShapeOnDisk don't share cache
widmogrod Dec 30, 2023
2e3a7eb
x/shape: regenerate it
widmogrod Dec 30, 2023
f593276
x/schema: shape regeneration
widmogrod Dec 30, 2023
e970d08
x/schema/testutil: generate using all extensions
widmogrod Dec 30, 2023
57c1741
s/generator: deser_json_generator use LookupShapeOnDisk
widmogrod Dec 30, 2023
71fb3b7
s/generators: shape_tagged improvments
widmogrod Dec 30, 2023
fd7eb77
make sure that packages can run using x/shape inmemory registry
widmogrod Dec 30, 2023
0743a9a
tests now use extracted structs
widmogrod Dec 30, 2023
c938c80
commit regenerated files
widmogrod Dec 30, 2023
81db028
cmd/mkunion: serde now generates also shapes
widmogrod Dec 30, 2023
c7ce3c7
x/generators: don't unmarshal when pointer is null
widmogrod Dec 30, 2023
eebd748
regenerate
widmogrod Dec 30, 2023
caa768c
x/generators: significant refactor for old ones to allow import and i…
widmogrod Dec 31, 2023
dd049d4
x/shape: better type rendering
widmogrod Dec 31, 2023
0467965
cmd/mkunion: now leverage new generators format
widmogrod Dec 31, 2023
16ccb08
x/generators: better support of AliasLike json serde, but still needs…
widmogrod Jan 1, 2024
ed3d68c
x/shared: JSONMarshalMap and JSONUnmarshalMap
widmogrod Jan 1, 2024
5352cf4
x/schema: generate proper unmarshall methods
widmogrod Jan 1, 2024
8f0a2ac
x/storage: regenerate types
widmogrod Jan 1, 2024
a683d41
x/workflow: test serde for complex types
widmogrod Jan 1, 2024
03726d0
x/generators/testutils: introduce new edge cases and examples
widmogrod Jan 3, 2024
e1be6dd
x/generators/deser_json: check for nulls and change import extraction
widmogrod Jan 3, 2024
54fd874
x/generators: refactor out TemplateHelperShapeVariantToName
widmogrod Jan 3, 2024
ca5f1a2
x/generators: serde_json_tagged massive refactoring, now union and st…
widmogrod Jan 3, 2024
d6365f0
x/generators: shape_tagged.go generation improved
widmogrod Jan 3, 2024
4906c70
x/generators: shape_generator now use tagged generation
widmogrod Jan 3, 2024
d9c82f0
x/storage: regenerate
widmogrod Jan 3, 2024
07829fc
x/shape: from ast recognise array len
widmogrod Jan 3, 2024
0131ad3
x/shape: better type indexing propagation
widmogrod Jan 3, 2024
6e2df43
x/shape: StructLike has IsPointer attribute
widmogrod Jan 3, 2024
abb8b81
x/shape: more accurate type rendering
widmogrod Jan 3, 2024
b0575aa
x/shape: change usage of IndexWith
widmogrod Jan 3, 2024
7140658
x/generators: rename deser_json_generator.go to SerdeJSONUnion
widmogrod Jan 3, 2024
08f8a7a
x/generators: rename shape_generator.go to shape_union.go
widmogrod Jan 3, 2024
ab978a1
x/generators: remove helpers
widmogrod Jan 3, 2024
cbe0621
cmd/mkunion: remove helpers
widmogrod Jan 3, 2024
184f328
x/schema: refactor shape.IndexWith
widmogrod Jan 3, 2024
8c3289c
regenerate
widmogrod Jan 3, 2024
094ade9
my-app: regenerate typescript
widmogrod Jan 3, 2024
44871de
x/generators: Serde JSON optimisation for binary types
widmogrod Jan 3, 2024
710918e
x/schema: simplify go:generate
widmogrod Jan 3, 2024
e1ea524
regenerate
widmogrod Jan 3, 2024
0303891
x/shape: TypeScript renderer, now can follow references and follow pa…
widmogrod Jan 3, 2024
ea9faad
cmd/mkunion: shape-export now follows references
widmogrod Jan 3, 2024
3717938
my-app: use shape export to generate typescript types
widmogrod Jan 3, 2024
3efdeab
x/shape": change log to debug
widmogrod Jan 3, 2024
56cda3b
myu-app: commit generated typescript types
widmogrod Jan 3, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cmd/mkfunc/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ func main() {

match := generators.FunctionMatchGenerator{
Header: "// Code generated by mkfunc. DO NOT EDIT.",
PackageName: inferred.PackageName,
PackageName: inferred.PackageName(),
MaxSize: c.Int("max-size"),
}

Expand Down
243 changes: 197 additions & 46 deletions cmd/mkunion/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,16 @@ import (
"syscall"
)

type extractImports interface {
ExtractImports(x shape.Shape) generators.PkgMap
SkipImportsAndPackage(x bool)
}

type extractInitFuncs interface {
ExtractImportFuncs(s shape.Shape) []string
SkipInitFunc(flag bool)
}

func main() {
ctx, _ := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)

Expand Down Expand Up @@ -93,42 +103,38 @@ func main() {
return err
}

unionNames := c.StringSlice("name")
if len(unionNames) == 0 {
unionNames = inferred.PossibleUnionTypes()
}

for _, unionName := range unionNames {
options := []generators.GenerateOption{
generators.WithPackageName(inferred.PackageName),
var unions []*shape.UnionLike
for _, unionName := range c.StringSlice("name") {
union := inferred.RetrieveUnion(unionName)
if union == nil {
return fmt.Errorf("union %s not found in %s", unionName, sourcePath)
}

if !c.Bool("no-compact") {
options = append(options, generators.WithBufferedImports())
}
unions = append(unions, union)
}

helper := generators.NewHelper(options...)
union := inferred.RetrieveUnion(unionName)
if len(unions) == 0 {
unions = inferred.RetrieveUnions()
}

for _, union := range unions {
if union == nil {
return fmt.Errorf("union %s not found in %s", unionName, sourcePath)
return fmt.Errorf("union %s not found in %s", union.Name, sourcePath)
}

jsonGenerator := generators.NewDeSerJSONGenerator(union, helper)
shapeGenerator := generators.NewShapeGenerator(union, helper)
visitor := generators.NewVisitorGenerator(union, helper)
schema := generators.NewSchemaGenerator(union, helper)
jsonGenerator := generators.SerdeJSONUnion(union)
shapeGenerator := generators.NewShapeUnion(union)
visitor := generators.NewVisitorGenerator(union)

// ensures that order of generators is always the same
// ensures that order of generators2 is always the same
generatorsList := []string{
"visitor",
"schema",
"shape",
"json",
}

generators := map[string]generators.Generator{
generators2 := map[string]generators.Generator{
"visitor": visitor,
"schema": schema,
"shape": shapeGenerator,
"json": jsonGenerator,
}
Expand All @@ -148,12 +154,12 @@ func main() {

for _, name := range skipExtension {
log.Infof("skip extension %s", name)
delete(generators, name)
delete(generators2, name)
}

if c.Bool("no-compact") {
for _, name := range generatorsList {
g, ok := generators[name]
g, ok := generators2[name]
if !ok {
continue
}
Expand All @@ -172,35 +178,58 @@ func main() {
}
}
} else {
body := bytes.Buffer{}
packageName := union.PkgName
pkgMap := make(generators.PkgMap)
initFunc := make(generators.InitFuncs, 0, 0)
shapesContents := bytes.Buffer{}

for _, name := range generatorsList {
g, ok := generators[name]
g, ok := generators2[name]
if !ok {
continue
}
if gen, ok := g.(extractImports); ok {
gen.SkipImportsAndPackage(true)
}
if gen, ok := g.(extractInitFuncs); ok {
gen.SkipInitFunc(true)
}

b, err := g.Generate()
if err != nil {
return fmt.Errorf("failed to generate %s for %s in %s: %w", name, union.Name, sourcePath, err)
}
body.WriteString(fmt.Sprintf("//mkunion-extension:%s\n", name))
body.Write(b)
body.WriteString("\n")
}

header := bytes.Buffer{}
header.WriteString(helper.RenderBufferedHeader())
header.WriteString(helper.RenderBufferedImport())
log.Infof(helper.RenderBufferedImport())
if gen, ok := g.(extractImports); ok {
gen.ExtractImports(union)
pkgMap = generators.MergePkgMaps(pkgMap,
gen.ExtractImports(union),
)
}
if gen, ok := g.(extractInitFuncs); ok {
initFunc = append(initFunc, gen.ExtractImportFuncs(union)...)
}

fileName := baseName + "_" + strings.ToLower(union.Name) + "_gen.go"
log.Infof("writing %s", fileName)
shapesContents.WriteString(fmt.Sprintf("//mkunion-extension:%s\n", name))
shapesContents.Write(b)
shapesContents.WriteString("\n")
}

header.Write(body.Bytes())
contents := "// Code generated by mkunion. DO NOT EDIT.\n"
contents += fmt.Sprintf("package %s\n\n", packageName)
contents += generators.GenerateImports(pkgMap)
contents += generators.GenerateInitFunc(initFunc)
contents += shapesContents.String()

err = os.WriteFile(path.Join(cwd, fileName), header.Bytes(), 0644)
fileName := path.Join(
path.Dir(sourcePath),
fmt.Sprintf("%s_%s_gen.go", baseName, strings.ToLower(union.Name)),
)

log.Infof("writing %s", fileName)
err = os.WriteFile(fileName, []byte(contents), 0644)
if err != nil {
return fmt.Errorf("failed to write %s for %s in %s: %w", "gen", union.Name, sourcePath, err)
return fmt.Errorf("failed to write(2) %s for %s in %s: %w", "gen", union.Name, sourcePath, err)
}
}
}
Expand Down Expand Up @@ -257,10 +286,123 @@ func main() {
},
},
{
Name: "shape-export",
Name: "serde",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "type",
DefaultText: "json",
},
&cli.StringSliceFlag{
Name: "input-go-file",
Aliases: []string{"i", "input"},
Usage: `When not provided, it will try to use GOFILE environment variable, used when combined with //go:generate mkunion -name=MyUnionType`,
TakesFile: true,
},
&cli.BoolFlag{
Name: "verbose",
Aliases: []string{"v"},
Required: false,
Value: false,
},
},
Action: func(c *cli.Context) error {
if c.Bool("verbose") {
log.SetLevel(log.DebugLevel)
}

sourcePaths := c.StringSlice("input-go-file")
if len(sourcePaths) == 0 && os.Getenv("GOFILE") != "" {
cwd, _ := syscall.Getwd()
sourceName := path.Base(os.Getenv("GOFILE"))
sourcePaths = []string{
path.Join(cwd, sourceName),
}
}

if len(sourcePaths) == 0 {
// show usage
cli.ShowAppHelpAndExit(c, 1)
}

for _, sourcePath := range sourcePaths {
inferred, err := shape.InferFromFile(sourcePath)
if err != nil {
return fmt.Errorf("failed inferring shape in %s; %w", sourcePath, err)
}

shapes := inferred.RetrieveShapesTaggedAs("serde")
if len(shapes) == 0 {
log.Infof("no shape found in %s", sourcePath)
continue
}

packageName := "main"
pkgMap := make(generators.PkgMap)
initFunc := make(generators.InitFuncs, 0, 0)
shapesContents := bytes.Buffer{}

for _, x := range shapes {
packageName = shape.ToGoPkgName(x)
genSerde := generators.NewSerdeJSONTagged(x)
genSerde.SkipImportsAndPackage(true)

genShape := generators.NewShapeTagged(x)
genShape.SkipImportsAndPackage(true)
genShape.SkipInitFunc(true)

contents := "//serde:json\n"
contents, err = genSerde.Generate()
if err != nil {
return fmt.Errorf("failed to generate json serde for %s in %s: %w", shape.ToGoTypeName(x), sourcePath, err)
}
shapesContents.WriteString(contents)

contents = "//shape\n"
contents, err = genShape.Generate()
if err != nil {
return fmt.Errorf("failed to generate shape for %s in %s: %w", shape.ToGoTypeName(x), sourcePath, err)
}
shapesContents.WriteString(contents)

pkgMap = generators.MergePkgMaps(pkgMap,
genSerde.ExtractImports(x),
genShape.ExtractImports(x),
)

initFunc = append(initFunc, genShape.ExtractImportFuncs(x)...)
}

contents := "// Code generated by mkunion. DO NOT EDIT.\n"
contents += fmt.Sprintf("package %s\n\n", packageName)
contents += generators.GenerateImports(pkgMap)
contents += generators.GenerateInitFunc(initFunc)
contents += shapesContents.String()

sourceName := path.Base(sourcePath)
baseName := strings.TrimSuffix(sourceName, path.Ext(sourceName))
fileName := path.Join(
path.Dir(sourcePath),
fmt.Sprintf("%s_serde_gen.go", baseName),
)

log.Infof("writing %s", fileName)
err = os.WriteFile(fileName, []byte(contents), 0644)
if err != nil {
return fmt.Errorf("failed to write serialiser in %s: %w", sourcePath, err)
}

return nil
}

return nil
},
},
{
Name: "shape-export",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "language",
Aliases: []string{"lang"},
DefaultText: "typescript",
},
&cli.StringFlag{
Expand All @@ -273,8 +415,18 @@ func main() {
Usage: `When not provided, it will try to use GOFILE environment variable, used when combined with //go:generate mkunion -name=MyUnionType`,
TakesFile: true,
},
&cli.BoolFlag{
Name: "verbose",
Aliases: []string{"v"},
Required: false,
Value: false,
},
},
Action: func(c *cli.Context) error {
if c.Bool("verbose") {
log.SetLevel(log.DebugLevel)
}

sourcePaths := c.StringSlice("input-go-file")
if len(sourcePaths) == 0 && os.Getenv("GOFILE") != "" {
cwd, _ := syscall.Getwd()
Expand All @@ -297,15 +449,14 @@ func main() {
return err
}

for _, union := range inferred.RetrieveUnions() {
tsr.AddUnion(union)
}

for _, structLike := range inferred.RetrieveStructs() {
tsr.AddStruct(structLike)
for _, x := range inferred.RetrieveShapes() {
tsr.AddShape(x)
tsr.FollowRef(x)
}
}

tsr.FollowImports()

err := tsr.WriteToDir(c.String("output-dir"))
if err != nil {
return fmt.Errorf("failed to write to dir %s: %w", c.String("output-dir"), err)
Expand Down
20 changes: 20 additions & 0 deletions example/my-app/functions.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"image/jpeg"
"image/png"
"io"
"math/rand"
"os"
)

Expand All @@ -31,6 +32,25 @@ var functions = map[string]workflow.Function{
Result: schema.MkString(a + b),
}, nil
},
"concat_error": func(body *workflow.FunctionInput) (*workflow.FunctionOutput, error) {
args := body.Args
a, ok := schema.As[string](args[0])
if !ok {
return nil, fmt.Errorf("expected string, got %T", args[0])
}
b, ok := schema.As[string](args[1])
if !ok {
return nil, fmt.Errorf("expected string, got %T", args[1])
}

if rand.Float32() > 0.5 {
return nil, fmt.Errorf("random error")
}

return &workflow.FunctionOutput{
Result: schema.MkString(a + b),
}, nil
},
"genimageb64": func(body *workflow.FunctionInput) (*workflow.FunctionOutput, error) {
args := body.Args
_, ok := schema.As[string](args[0])
Expand Down
Loading