From d0e1d414eb798875cdc751083b35eb63e3df1365 Mon Sep 17 00:00:00 2001 From: Randy Reddig Date: Tue, 29 Oct 2024 16:08:39 -0600 Subject: [PATCH] cmd/wit-bindgen-go, wit/bindgen: use logging.Logger; add -v and -vv for verbose and debug logging --- cmd/wit-bindgen-go/cmd/generate/generate.go | 21 ++++++++++------- cmd/wit-bindgen-go/main.go | 10 +++++++++ wit/bindgen/generator.go | 25 ++++++++++++++++----- wit/bindgen/options.go | 25 +++++++++++++++++++++ 4 files changed, 67 insertions(+), 14 deletions(-) diff --git a/cmd/wit-bindgen-go/cmd/generate/generate.go b/cmd/wit-bindgen-go/cmd/generate/generate.go index b01cf4bf..e4483670 100644 --- a/cmd/wit-bindgen-go/cmd/generate/generate.go +++ b/cmd/wit-bindgen-go/cmd/generate/generate.go @@ -11,6 +11,7 @@ import ( "github.com/bytecodealliance/wasm-tools-go/internal/go/gen" "github.com/bytecodealliance/wasm-tools-go/internal/witcli" "github.com/bytecodealliance/wasm-tools-go/wit/bindgen" + "github.com/bytecodealliance/wasm-tools-go/wit/logging" "github.com/urfave/cli/v3" ) @@ -66,6 +67,7 @@ var Command = &cli.Command{ // Config is the configuration for the `generate` command. type config struct { + logger logging.Logger dryRun bool out string outPerm os.FileMode @@ -90,6 +92,7 @@ func action(ctx context.Context, cmd *cli.Command) error { packages, err := bindgen.Go(res, bindgen.GeneratedBy(cmd.Root().Name), + bindgen.Logger(cfg.logger), bindgen.World(cfg.world), bindgen.PackageRoot(cfg.pkgRoot), bindgen.Versioned(cfg.versioned), @@ -103,6 +106,7 @@ func action(ctx context.Context, cmd *cli.Command) error { } func parseFlags(cmd *cli.Command) (*config, error) { + logger := witcli.Logger(cmd.Bool("verbose"), cmd.Bool("debug")) dryRun := cmd.Bool("dry-run") out := cmd.String("out") @@ -110,7 +114,7 @@ func parseFlags(cmd *cli.Command) (*config, error) { if err != nil { return nil, err } - fmt.Fprintf(os.Stderr, "Output dir: %s\n", out) + logger.Infof("Output dir: %s\n", out) outPerm := info.Mode().Perm() pkgRoot := cmd.String("package-root") @@ -120,7 +124,7 @@ func parseFlags(cmd *cli.Command) (*config, error) { return nil, err } } - fmt.Fprintf(os.Stderr, "Package root: %s\n", pkgRoot) + logger.Infof("Package root: %s\n", pkgRoot) path, err := witcli.LoadPath(cmd.Args().Slice()...) if err != nil { @@ -128,6 +132,7 @@ func parseFlags(cmd *cli.Command) (*config, error) { } return &config{ + logger, dryRun, out, outPerm, @@ -141,13 +146,13 @@ func parseFlags(cmd *cli.Command) (*config, error) { } func writeGoPackages(packages []*gen.Package, cfg *config) error { - fmt.Fprintf(os.Stderr, "Generated %d package(s)\n", len(packages)) + cfg.logger.Infof("Generated %d Go package(s)\n", len(packages)) for _, pkg := range packages { if !pkg.HasContent() { - fmt.Fprintf(os.Stderr, "Skipping empty package: %s\n", pkg.Path) + cfg.logger.Debugf("Skipped empty package: %s\n", pkg.Path) continue } - fmt.Fprintf(os.Stderr, "Generated package: %s\n", pkg.Path) + cfg.logger.Infof("Generated package: %s\n", pkg.Path) for _, filename := range codec.SortedKeys(pkg.Files) { file := pkg.Files[filename] @@ -155,7 +160,7 @@ func writeGoPackages(packages []*gen.Package, cfg *config) error { path := filepath.Join(dir, file.Name) if !file.HasContent() { - fmt.Fprintf(os.Stderr, "Skipping empty file: %s\n", path) + cfg.logger.Debugf("\tSkipping empty file: %s\n", path) continue } @@ -168,9 +173,9 @@ func writeGoPackages(packages []*gen.Package, cfg *config) error { if content == nil { return err } - fmt.Fprintf(os.Stderr, "Error formatting file: %v\n", err) + cfg.logger.Errorf("\tError formatting file: %v\n", err) } else { - fmt.Fprintf(os.Stderr, "Generated file: %s\n", path) + cfg.logger.Infof("\t%s\n", path) } if cfg.dryRun { diff --git a/cmd/wit-bindgen-go/main.go b/cmd/wit-bindgen-go/main.go index 7ba58427..c6799bab 100644 --- a/cmd/wit-bindgen-go/main.go +++ b/cmd/wit-bindgen-go/main.go @@ -39,6 +39,16 @@ var Command = &cli.Command{ Name: "force-wit", Usage: "force loading WIT via wasm-tools", }, + &cli.BoolFlag{ + Name: "verbose", + Aliases: []string{"v"}, + Usage: "print verbose logging messages", + }, + &cli.BoolFlag{ + Name: "debug", + Aliases: []string{"vv"}, + Usage: "print debug logging messages", + }, }, Action: action, } diff --git a/wit/bindgen/generator.go b/wit/bindgen/generator.go index a1c6c63e..8fc500f6 100644 --- a/wit/bindgen/generator.go +++ b/wit/bindgen/generator.go @@ -8,6 +8,7 @@ import ( "errors" "fmt" "go/token" + "io" "path" "path/filepath" "runtime" @@ -20,6 +21,7 @@ import ( "github.com/bytecodealliance/wasm-tools-go/internal/go/gen" "github.com/bytecodealliance/wasm-tools-go/internal/stringio" "github.com/bytecodealliance/wasm-tools-go/wit" + "github.com/bytecodealliance/wasm-tools-go/wit/logging" ) const ( @@ -139,6 +141,9 @@ func newGenerator(res *wit.Resolve, opts ...Option) (*generator, error) { if err != nil { return nil, err } + if g.opts.logger == nil { + g.opts.logger = logging.NewLogger(io.Discard, logging.LevelNever) + } if g.opts.generatedBy == "" { _, file, _, _ := runtime.Caller(0) _, g.opts.generatedBy = filepath.Split(filepath.Dir(filepath.Dir(file))) @@ -166,7 +171,7 @@ func (g *generator) generate() ([]*gen.Package, error) { func (g *generator) detectVersionedPackages() { if g.opts.versioned { g.versioned = true - // fmt.Fprintf(os.Stderr, "Generated versions for all package(s)\n") + g.opts.logger.Infof("Generated versions for all package(s)\n") return } packages := make(map[string]string) @@ -180,9 +185,9 @@ func (g *generator) detectVersionedPackages() { packages[path] = pkg.Name.String() } } - // if g.versioned { - // fmt.Fprintf(os.Stderr, "Multiple versions of package(s) detected\n") - // } + if g.versioned { + g.opts.logger.Infof("Multiple versions of package(s) detected\n") + } } // define marks a world, interface, type, or function as defined. @@ -199,7 +204,7 @@ func (g *generator) define(dir wit.Direction, v wit.Node) (defined bool) { // Options might override the Go package, including combining multiple // WIT interfaces and/or worlds into a single Go package. func (g *generator) defineWorlds() error { - // fmt.Fprintf(os.Stderr, "Generating Go for %d world(s)\n", len(g.res.Worlds)) + g.opts.logger.Infof("Generating Go for %d world(s)\n", len(g.res.Worlds)) for i, w := range g.res.Worlds { if w.Match(g.opts.world) || (g.opts.world == "" && i == len(g.res.Worlds)-1) { err := g.defineWorld(w) @@ -493,7 +498,15 @@ func (g *generator) declareTypeDef(file *gen.File, dir wit.Direction, t *wit.Typ g.types[otherDir][t] = decl g.define(otherDir, t) // Mark this type as defined } - // fmt.Fprintf(os.Stderr, "Type:\t%s.%s\n\t%s.%s\n", owner.String(), name, decl.Package.Path, decl.Name) + + { + name := "(anonymous)" + if t.Name != nil { + name = *t.Name + } + g.opts.logger.Debugf("Type:\t%s.%s\n\t%s.%s\n", + g.moduleNames[t.Owner], name, file.Package.Path, decl.name) + } // Predeclare own and borrow for resource types. if experimentPredeclareHandles { diff --git a/wit/bindgen/options.go b/wit/bindgen/options.go index 5fff418e..0e15fdfb 100644 --- a/wit/bindgen/options.go +++ b/wit/bindgen/options.go @@ -1,5 +1,11 @@ package bindgen +import ( + "log/slog" + + "github.com/bytecodealliance/wasm-tools-go/wit/logging" +) + // Option represents a single configuration option for this package. type Option interface { applyOption(*options) error @@ -12,6 +18,9 @@ func (f optionFunc) applyOption(opts *options) error { } type options struct { + logger logging.Logger + slogger *slog.Logger + // generatedBy is the name of the program that generates code with this package. generatedBy string @@ -40,6 +49,22 @@ func (opts *options) apply(o ...Option) error { return nil } +// Logger returns an [Option] that specifies a [logging.Logger] for logging. +func Logger(logger logging.Logger) Option { + return optionFunc(func(opts *options) error { + opts.logger = logger + return nil + }) +} + +// Slogger returns an [Option] that specifies a [slog.Slogger] for logging. +func Slogger(logger *slog.Logger) Option { + return optionFunc(func(opts *options) error { + opts.slogger = logger + return nil + }) +} + // GeneratedBy returns an [Option] that specifies the name of the program or package // that will appear in the "Code generated by ..." header on generated files. func GeneratedBy(name string) Option {