From b1c64c753f0d3143dd0630c148b526e9b549c81b Mon Sep 17 00:00:00 2001 From: andig Date: Sat, 6 Sep 2025 13:44:56 +0200 Subject: [PATCH] chore: enable multi-line decorators (#23431) --- cmd/decorate/decorate.go | 66 +++++++++++++++++++++++++++++++++++----- 1 file changed, 58 insertions(+), 8 deletions(-) diff --git a/cmd/decorate/decorate.go b/cmd/decorate/decorate.go index c8ac3101b..b1beba1d2 100644 --- a/cmd/decorate/decorate.go +++ b/cmd/decorate/decorate.go @@ -1,6 +1,7 @@ package main import ( + "bufio" "bytes" _ "embed" "fmt" @@ -20,7 +21,13 @@ import ( "golang.org/x/tools/imports" ) -//go:generate go tool decorate -f decorateTest -b api.Charger -t "api.MeterEnergy,TotalEnergy,func() (float64, error)" -t "api.PhaseSwitcher,Phases1p3p,func(int) error" -t "api.PhaseGetter,GetPhases,func() (int, error)" +// go:generate go tool decorate -f decorateTest -b api.Charger -t "api.MeterEnergy,TotalEnergy,func() (float64, error)" -t "api.PhaseSwitcher,Phases1p3p,func(int) error" -t "api.PhaseGetter,GetPhases,func() (int, error)" +//go:generate go tool decorate +//evcc:function decorateTest +//evcc:basetype api.Charger +//evcc:type api.MeterEnergy,TotalEnergy,func() (float64, error) +//evcc:type api.PhaseSwitcher,Phases1p3p,func(int) error +//evcc:type api.PhaseGetter,GetPhases,func() (int, error) //go:embed decorate.tpl var srcTmpl string @@ -198,7 +205,7 @@ COMBO: var ( target = pflag.StringP("out", "o", "", "output file") pkg = pflag.StringP("package", "p", "", "package name") - function = pflag.StringP("function", "f", "decorate", "function name") + function = pflag.StringP("function", "f", "", "function name") base = pflag.StringP("base", "b", "", "base type") ret = pflag.StringP("return", "r", "", "return type") types = pflag.StringArrayP("type", "t", nil, "comma-separated list of type definitions") @@ -212,15 +219,64 @@ func Usage() { pflag.PrintDefaults() } +func parseFile(file string, function, basetype, returntype *string, types *[]string) error { + f, err := os.Open(file) + if err != nil { + return err + } + defer f.Close() + + scanner := bufio.NewScanner(f) + for scanner.Scan() { + line := scanner.Text() + + if s, ok := strings.CutPrefix(line, "//evcc:"); ok { + segs := strings.SplitN(s, " ", 2) + if len(segs) != 2 { + panic("invalid segments: " + s) + } + + switch segs[0] { + case "function": + *function = segs[1] + case "basetype": + *basetype = segs[1] + case "returntype": + *returntype = segs[1] + case "type": + *types = append(*types, segs[1]) + default: + panic("invalid directive //evcc:" + segs[0]) + } + } + } + + return scanner.Err() +} + func main() { pflag.Usage = Usage pflag.Parse() + // read target from go:generate + gofile, ok := os.LookupEnv("GOFILE") + if *target == "" && ok { + gofile := strings.TrimSuffix(gofile, ".go") + "_decorators.go" + target = &gofile + } + // read target from go:generate if gopkg, ok := os.LookupEnv("GOPACKAGE"); *pkg == "" && ok { pkg = &gopkg } + if *function == "" { + if err := parseFile(gofile, function, base, ret, types); err != nil { + fmt.Println(err) + os.Exit(2) + } + } + if *base == "" || *pkg == "" || len(*types) == 0 { Usage() os.Exit(2) @@ -242,12 +298,6 @@ func main() { var out io.Writer = os.Stdout - // read target from go:generate - if gofile, ok := os.LookupEnv("GOFILE"); *target == "" && ok { - gofile = strings.TrimSuffix(gofile, ".go") + "_decorators.go" - target = &gofile - } - var name string if target != nil { name = *target