mirror of
https://github.com/tailscale/tailscale.git
synced 2025-04-19 05:02:34 +00:00
util/codegen: add NamedTypes
And use it in cmd/cloner. Signed-off-by: Josh Bleecher Snyder <josh@tailscale.com>
This commit is contained in:
parent
367a973dc2
commit
d8a8f70000
@ -17,8 +17,6 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/ast"
|
|
||||||
"go/token"
|
|
||||||
"go/types"
|
"go/types"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
@ -62,33 +60,13 @@ func main() {
|
|||||||
pkg := pkgs[0]
|
pkg := pkgs[0]
|
||||||
buf := new(bytes.Buffer)
|
buf := new(bytes.Buffer)
|
||||||
imports := make(map[string]struct{})
|
imports := make(map[string]struct{})
|
||||||
|
namedTypes := codegen.NamedTypes(pkg)
|
||||||
for _, typeName := range typeNames {
|
for _, typeName := range typeNames {
|
||||||
found := false
|
typ, ok := namedTypes[typeName]
|
||||||
for _, file := range pkg.Syntax {
|
|
||||||
for _, d := range file.Decls {
|
|
||||||
decl, ok := d.(*ast.GenDecl)
|
|
||||||
if !ok || decl.Tok != token.TYPE {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
for _, s := range decl.Specs {
|
|
||||||
spec, ok := s.(*ast.TypeSpec)
|
|
||||||
if !ok || spec.Name.Name != typeName {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
typeNameObj := pkg.TypesInfo.Defs[spec.Name]
|
|
||||||
typ, ok := typeNameObj.Type().(*types.Named)
|
|
||||||
if !ok {
|
if !ok {
|
||||||
continue
|
|
||||||
}
|
|
||||||
pkg := typeNameObj.Pkg()
|
|
||||||
gen(buf, imports, typ, pkg)
|
|
||||||
found = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !found {
|
|
||||||
log.Fatalf("could not find type %s", typeName)
|
log.Fatalf("could not find type %s", typeName)
|
||||||
}
|
}
|
||||||
|
gen(buf, imports, typ, pkg.Types)
|
||||||
}
|
}
|
||||||
|
|
||||||
w := func(format string, args ...interface{}) {
|
w := func(format string, args ...interface{}) {
|
||||||
|
@ -8,9 +8,13 @@ package codegen
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"go/ast"
|
||||||
"go/format"
|
"go/format"
|
||||||
|
"go/token"
|
||||||
"go/types"
|
"go/types"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
"golang.org/x/tools/go/packages"
|
||||||
)
|
)
|
||||||
|
|
||||||
// WriteFormatted writes code to path.
|
// WriteFormatted writes code to path.
|
||||||
@ -41,6 +45,32 @@ func WriteFormatted(code []byte, path string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NamedTypes returns all named types in pkg, keyed by their type name.
|
||||||
|
func NamedTypes(pkg *packages.Package) map[string]*types.Named {
|
||||||
|
nt := make(map[string]*types.Named)
|
||||||
|
for _, file := range pkg.Syntax {
|
||||||
|
for _, d := range file.Decls {
|
||||||
|
decl, ok := d.(*ast.GenDecl)
|
||||||
|
if !ok || decl.Tok != token.TYPE {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for _, s := range decl.Specs {
|
||||||
|
spec, ok := s.(*ast.TypeSpec)
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
typeNameObj := pkg.TypesInfo.Defs[spec.Name]
|
||||||
|
typ, ok := typeNameObj.Type().(*types.Named)
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
nt[spec.Name.Name] = typ
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nt
|
||||||
|
}
|
||||||
|
|
||||||
// AssertStructUnchanged generates code that asserts at compile time that type t is unchanged.
|
// AssertStructUnchanged generates code that asserts at compile time that type t is unchanged.
|
||||||
// tname is the named type corresponding to t.
|
// tname is the named type corresponding to t.
|
||||||
// ctx is a single-word context for this assertion, such as "Clone".
|
// ctx is a single-word context for this assertion, such as "Clone".
|
||||||
|
Loading…
x
Reference in New Issue
Block a user