mirror of
https://github.com/tailscale/tailscale.git
synced 2025-04-21 14:11:56 +00:00
util/codegen: add package
This is a package for shared utilities used in doing codegen programs. The inaugural API is for writing gofmt'd code to a file. Signed-off-by: Josh Bleecher Snyder <josh@tailscale.com>
This commit is contained in:
parent
4da559d7cc
commit
fb66ff7c78
@ -18,15 +18,14 @@ import (
|
|||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/ast"
|
"go/ast"
|
||||||
"go/format"
|
|
||||||
"go/token"
|
"go/token"
|
||||||
"go/types"
|
"go/types"
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"golang.org/x/tools/go/packages"
|
"golang.org/x/tools/go/packages"
|
||||||
|
"tailscale.com/util/codegen"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -130,17 +129,12 @@ func main() {
|
|||||||
fmt.Fprintf(contents, ")\n\n")
|
fmt.Fprintf(contents, ")\n\n")
|
||||||
contents.Write(buf.Bytes())
|
contents.Write(buf.Bytes())
|
||||||
|
|
||||||
out, err := format.Source(contents.Bytes())
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("%s, in source:\n%s", err, contents.Bytes())
|
|
||||||
}
|
|
||||||
|
|
||||||
output := *flagOutput
|
output := *flagOutput
|
||||||
if output == "" {
|
if output == "" {
|
||||||
flag.Usage()
|
flag.Usage()
|
||||||
os.Exit(2)
|
os.Exit(2)
|
||||||
}
|
}
|
||||||
if err := ioutil.WriteFile(output, out, 0644); err != nil {
|
if err := codegen.WriteFormatted(contents.Bytes(), output); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
40
util/codegen/codegen.go
Normal file
40
util/codegen/codegen.go
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
// Copyright (c) 2021 Tailscale Inc & AUTHORS All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Package codegen contains shared utilities for generating code.
|
||||||
|
package codegen
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"go/format"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
// WriteFormatted writes code to path.
|
||||||
|
// It runs gofmt on it before writing;
|
||||||
|
// if gofmt fails, it writes code unchanged.
|
||||||
|
// Errors can include I/O errors and gofmt errors.
|
||||||
|
//
|
||||||
|
// The advantage of always writing code to path,
|
||||||
|
// even if gofmt fails, is that it makes debugging easier.
|
||||||
|
// The code can be long, but you need it in order to debug.
|
||||||
|
// It is nicer to work with it in a file than a terminal.
|
||||||
|
// It is also easier to interpret gofmt errors
|
||||||
|
// with an editor providing file and line numbers.
|
||||||
|
func WriteFormatted(code []byte, path string) error {
|
||||||
|
out, fmterr := format.Source(code)
|
||||||
|
if fmterr != nil {
|
||||||
|
out = code
|
||||||
|
}
|
||||||
|
ioerr := os.WriteFile(path, out, 0644)
|
||||||
|
// Prefer I/O errors. They're usually easier to fix,
|
||||||
|
// and until they're fixed you can't do much else.
|
||||||
|
if ioerr != nil {
|
||||||
|
return ioerr
|
||||||
|
}
|
||||||
|
if fmterr != nil {
|
||||||
|
return fmt.Errorf("%s:%v", path, fmterr)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user