Skip to content

Commit

Permalink
Feature based code generation
Browse files Browse the repository at this point in the history
  • Loading branch information
jonastheis committed Oct 5, 2023
1 parent 455595b commit 413d0e5
Show file tree
Hide file tree
Showing 5 changed files with 140 additions and 0 deletions.
64 changes: 64 additions & 0 deletions codegen/features/cmd/cmd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// Package gen/cmd allows to generate .go source files using the go:generate command.
// Use with "cmd [templateFile] [outputFile] [typeName] [typeReceiver] [Features separated by space]".
//
// In the template the following are available:
// - typeName as {{.Name}}
// - typeReceiver as {{.Receiver}}
// - Features are available via map and can be evaluated as {{if index .Features "extended"}}
package main

import (
"bytes"
"fmt"
"go/format"
"os"
"strings"
"text/template"

"github.com/iotaledger/hive.go/lo"
)

func main() {
if len(os.Args) < 6 {
printUsage("not enough parameters")
}

templateFilePath := os.Args[1]
conf := newConfiguration(os.Args[2], os.Args[3], os.Args[4], os.Args[5])

funcs := template.FuncMap{
"firstLower": func(s string) string {
return strings.ToLower(s[0:1]) + s[1:]
},
}

tmplFile := lo.PanicOnErr(os.ReadFile(templateFilePath))

tmpl := template.Must(
template.New("gen").
Funcs(funcs).
Parse(string(tmplFile)),
)

buffer := new(bytes.Buffer)
panicOnError(tmpl.Execute(buffer, conf))

formattedOutput := lo.PanicOnErr(format.Source(buffer.Bytes()))

panicOnError(os.WriteFile(conf.FileName, formattedOutput, 0600))
}

// printUsage prints the usage of the variadic code generator in case of an error.
func printUsage(errorMsg string) {
_, _ = fmt.Fprintf(os.Stderr, "Error:\t%s\n\n", errorMsg)
_, _ = fmt.Fprintf(os.Stderr, "Usage of gen/cmd:\n")
_, _ = fmt.Fprintf(os.Stderr, "\tcmd [templateFile] [outputFile] [typeName] [typeReceiver] [features separated by space]\n")

os.Exit(2)
}

func panicOnError(err error) {
if err != nil {
panic(err)
}
}
31 changes: 31 additions & 0 deletions codegen/features/cmd/configuration.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package main

import (
"fmt"
"strings"
)

type configuration struct {
FileName string
Name string
Receiver string
Features map[string]bool
}

func newConfiguration(fileName, name, receiver, featuresStr string) *configuration {
features := make(map[string]bool)
for _, feature := range strings.Split(featuresStr, " ") {
features[feature] = true
}

return &configuration{
FileName: fileName,
Name: name,
Receiver: strings.ToLower(receiver),
Features: features,
}
}

func (c *configuration) String() string {
return fmt.Sprintf("configuration{\n\tFileName:%s,\n\tName:%s,\n\tReceiver:%s,\n\tFeatures:%v,\n}\n", c.FileName, c.Name, c.Receiver, c.Features)
}
19 changes: 19 additions & 0 deletions codegen/features/example/example.gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 21 additions & 0 deletions codegen/features/example/example.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package iotago

// Code generated by go generate; DO NOT EDIT. Check gen/ directory instead.

const (
// {{.Name}}Length defines the length of an {{.Name}}.
{{.Name}}Length = 32
)

var (
Empty{{.Name}} = {{.Name}}{}
)

// {{.Name}} is a 32 byte hash value.
type {{.Name}} [{{.Name}}Length]byte

{{if index .Features "example_feature"}}
func ({{.Receiver}} {{.Name}}) ExampleFeature() string {
return "ExampleFeature"
}
{{end}}
5 changes: 5 additions & 0 deletions codegen/features/example/identifier_gen.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
//go:build ignore

package gen

//go:generate go run ../cmd example.tmpl example.gen.go ExampleName e "example_feature"

0 comments on commit 413d0e5

Please sign in to comment.