update dependencies (#6267)
Signed-off-by: hongming <coder.scala@gmail.com>
(cherry picked from commit cfebd96a1f)
This commit is contained in:
31
vendor/k8s.io/gengo/v2/generator/doc.go
generated
vendored
Normal file
31
vendor/k8s.io/gengo/v2/generator/doc.go
generated
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
Copyright 2015 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Package generator defines an interface for code generators to implement.
|
||||
//
|
||||
// To use this package, you'll implement the "Package" and "Generator"
|
||||
// interfaces; you'll call NewContext to load up the types you want to work
|
||||
// with, and then you'll call one or more of the Execute methods. See the
|
||||
// interface definitions for explanations. All output will have gofmt called on
|
||||
// it automatically, so you do not need to worry about generating correct
|
||||
// indentation.
|
||||
//
|
||||
// This package also exposes SnippetWriter. SnippetWriter reduces to a minimum
|
||||
// the boilerplate involved in setting up a template from go's text/template
|
||||
// package. Additionally, all naming systems in the Context will be added as
|
||||
// functions to the parsed template, so that they can be called directly from
|
||||
// your templates!
|
||||
package generator // import "k8s.io/gengo/v2/generator"
|
||||
50
vendor/k8s.io/gengo/v2/generator/error_tracker.go
generated
vendored
Normal file
50
vendor/k8s.io/gengo/v2/generator/error_tracker.go
generated
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
Copyright 2015 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package generator
|
||||
|
||||
import (
|
||||
"io"
|
||||
)
|
||||
|
||||
// ErrorTracker tracks errors to the underlying writer, so that you can ignore
|
||||
// them until you're ready to return.
|
||||
type ErrorTracker struct {
|
||||
io.Writer
|
||||
err error
|
||||
}
|
||||
|
||||
// NewErrorTracker makes a new error tracker; note that it implements io.Writer.
|
||||
func NewErrorTracker(w io.Writer) *ErrorTracker {
|
||||
return &ErrorTracker{Writer: w}
|
||||
}
|
||||
|
||||
// Write intercepts calls to Write.
|
||||
func (et *ErrorTracker) Write(p []byte) (n int, err error) {
|
||||
if et.err != nil {
|
||||
return 0, et.err
|
||||
}
|
||||
n, err = et.Writer.Write(p)
|
||||
if err != nil {
|
||||
et.err = err
|
||||
}
|
||||
return n, err
|
||||
}
|
||||
|
||||
// Error returns nil if no error has occurred, otherwise it returns the error.
|
||||
func (et *ErrorTracker) Error() error {
|
||||
return et.err
|
||||
}
|
||||
266
vendor/k8s.io/gengo/v2/generator/execute.go
generated
vendored
Normal file
266
vendor/k8s.io/gengo/v2/generator/execute.go
generated
vendored
Normal file
@@ -0,0 +1,266 @@
|
||||
/*
|
||||
Copyright 2015 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package generator
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/tools/imports"
|
||||
"k8s.io/gengo/v2/namer"
|
||||
"k8s.io/gengo/v2/types"
|
||||
"k8s.io/klog/v2"
|
||||
)
|
||||
|
||||
// ExecuteTargets runs the generators for the provided targets.
|
||||
func (c *Context) ExecuteTargets(targets []Target) error {
|
||||
klog.V(5).Infof("ExecuteTargets: %d targets", len(targets))
|
||||
|
||||
var errs []error
|
||||
for _, tgt := range targets {
|
||||
if err := c.ExecuteTarget(tgt); err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
}
|
||||
if len(errs) > 0 {
|
||||
return fmt.Errorf("some targets had errors: %w", errors.Join(errs...))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type DefaultFileType struct {
|
||||
Format func([]byte) ([]byte, error)
|
||||
Assemble func(io.Writer, *File)
|
||||
}
|
||||
|
||||
func (ft DefaultFileType) AssembleFile(f *File, pathname string) error {
|
||||
klog.V(5).Infof("Assembling file %q", pathname)
|
||||
|
||||
destFile, err := os.Create(pathname)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer destFile.Close()
|
||||
|
||||
b := &bytes.Buffer{}
|
||||
et := NewErrorTracker(b)
|
||||
ft.Assemble(et, f)
|
||||
if et.Error() != nil {
|
||||
return et.Error()
|
||||
}
|
||||
if formatted, err := ft.Format(b.Bytes()); err != nil {
|
||||
err = fmt.Errorf("unable to format file %q (%v)", pathname, err)
|
||||
// Write the file anyway, so they can see what's going wrong and fix the generator.
|
||||
if _, err2 := destFile.Write(b.Bytes()); err2 != nil {
|
||||
return err2
|
||||
}
|
||||
return err
|
||||
} else {
|
||||
_, err = destFile.Write(formatted)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
func assembleGoFile(w io.Writer, f *File) {
|
||||
w.Write(f.Header)
|
||||
fmt.Fprintf(w, "package %v\n\n", f.PackageName)
|
||||
|
||||
if len(f.Imports) > 0 {
|
||||
fmt.Fprint(w, "import (\n")
|
||||
for i := range f.Imports {
|
||||
if strings.Contains(i, "\"") {
|
||||
// they included quotes, or are using the
|
||||
// `name "path/to/pkg"` format.
|
||||
fmt.Fprintf(w, "\t%s\n", i)
|
||||
} else {
|
||||
fmt.Fprintf(w, "\t%q\n", i)
|
||||
}
|
||||
}
|
||||
fmt.Fprint(w, ")\n\n")
|
||||
}
|
||||
|
||||
if f.Vars.Len() > 0 {
|
||||
fmt.Fprint(w, "var (\n")
|
||||
w.Write(f.Vars.Bytes())
|
||||
fmt.Fprint(w, ")\n\n")
|
||||
}
|
||||
|
||||
if f.Consts.Len() > 0 {
|
||||
fmt.Fprint(w, "const (\n")
|
||||
w.Write(f.Consts.Bytes())
|
||||
fmt.Fprint(w, ")\n\n")
|
||||
}
|
||||
|
||||
w.Write(f.Body.Bytes())
|
||||
}
|
||||
|
||||
func importsWrapper(src []byte) ([]byte, error) {
|
||||
return imports.Process("", src, nil)
|
||||
}
|
||||
|
||||
func NewGoFile() *DefaultFileType {
|
||||
return &DefaultFileType{
|
||||
Format: importsWrapper,
|
||||
Assemble: assembleGoFile,
|
||||
}
|
||||
}
|
||||
|
||||
// format should be one line only, and not end with \n.
|
||||
func addIndentHeaderComment(b *bytes.Buffer, format string, args ...interface{}) {
|
||||
if b.Len() > 0 {
|
||||
fmt.Fprintf(b, "\n// "+format+"\n", args...)
|
||||
} else {
|
||||
fmt.Fprintf(b, "// "+format+"\n", args...)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Context) filteredBy(f func(*Context, *types.Type) bool) *Context {
|
||||
c2 := *c
|
||||
c2.Order = []*types.Type{}
|
||||
for _, t := range c.Order {
|
||||
if f(c, t) {
|
||||
c2.Order = append(c2.Order, t)
|
||||
}
|
||||
}
|
||||
return &c2
|
||||
}
|
||||
|
||||
// make a new context; inheret c.Namers, but add on 'namers'. In case of a name
|
||||
// collision, the namer in 'namers' wins.
|
||||
func (c *Context) addNameSystems(namers namer.NameSystems) *Context {
|
||||
if namers == nil {
|
||||
return c
|
||||
}
|
||||
c2 := *c
|
||||
// Copy the existing name systems so we don't corrupt a parent context
|
||||
c2.Namers = namer.NameSystems{}
|
||||
for k, v := range c.Namers {
|
||||
c2.Namers[k] = v
|
||||
}
|
||||
|
||||
for name, namer := range namers {
|
||||
c2.Namers[name] = namer
|
||||
}
|
||||
return &c2
|
||||
}
|
||||
|
||||
// ExecuteTarget runs the generators for a single target.
|
||||
func (c *Context) ExecuteTarget(tgt Target) error {
|
||||
tgtDir := tgt.Dir()
|
||||
if tgtDir == "" {
|
||||
return fmt.Errorf("no directory for target %s", tgt.Path())
|
||||
}
|
||||
klog.V(5).Infof("Executing target %q (%q)", tgt.Name(), tgtDir)
|
||||
|
||||
// Filter out any types the *package* doesn't care about.
|
||||
packageContext := c.filteredBy(tgt.Filter)
|
||||
|
||||
if err := os.MkdirAll(tgtDir, 0755); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
files := map[string]*File{}
|
||||
for _, g := range tgt.Generators(packageContext) {
|
||||
// Filter out types the *generator* doesn't care about.
|
||||
genContext := packageContext.filteredBy(g.Filter)
|
||||
// Now add any extra name systems defined by this generator
|
||||
genContext = genContext.addNameSystems(g.Namers(genContext))
|
||||
|
||||
fileType := g.FileType()
|
||||
if len(fileType) == 0 {
|
||||
return fmt.Errorf("generator %q must specify a file type", g.Name())
|
||||
}
|
||||
f := files[g.Filename()]
|
||||
if f == nil {
|
||||
// This is the first generator to reference this file, so start it.
|
||||
f = &File{
|
||||
Name: g.Filename(),
|
||||
FileType: fileType,
|
||||
PackageName: tgt.Name(),
|
||||
PackagePath: tgt.Path(),
|
||||
PackageDir: tgt.Dir(),
|
||||
Header: tgt.Header(g.Filename()),
|
||||
Imports: map[string]struct{}{},
|
||||
}
|
||||
files[f.Name] = f
|
||||
} else if f.FileType != g.FileType() {
|
||||
return fmt.Errorf("file %q already has type %q, but generator %q wants to use type %q", f.Name, f.FileType, g.Name(), g.FileType())
|
||||
}
|
||||
|
||||
if vars := g.PackageVars(genContext); len(vars) > 0 {
|
||||
addIndentHeaderComment(&f.Vars, "Package-wide variables from generator %q.", g.Name())
|
||||
for _, v := range vars {
|
||||
if _, err := fmt.Fprintf(&f.Vars, "%s\n", v); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
if consts := g.PackageConsts(genContext); len(consts) > 0 {
|
||||
addIndentHeaderComment(&f.Consts, "Package-wide consts from generator %q.", g.Name())
|
||||
for _, v := range consts {
|
||||
if _, err := fmt.Fprintf(&f.Consts, "%s\n", v); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
if err := genContext.executeBody(&f.Body, g); err != nil {
|
||||
return err
|
||||
}
|
||||
if imports := g.Imports(genContext); len(imports) > 0 {
|
||||
for _, i := range imports {
|
||||
f.Imports[i] = struct{}{}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var errs []error
|
||||
for _, f := range files {
|
||||
finalPath := filepath.Join(tgtDir, f.Name)
|
||||
assembler, ok := c.FileTypes[f.FileType]
|
||||
if !ok {
|
||||
return fmt.Errorf("the file type %q registered for file %q does not exist in the context", f.FileType, f.Name)
|
||||
}
|
||||
if err := assembler.AssembleFile(f, finalPath); err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
}
|
||||
if len(errs) > 0 {
|
||||
return fmt.Errorf("errors in target %q: %w", tgt.Path(), errors.Join(errs...))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Context) executeBody(w io.Writer, generator Generator) error {
|
||||
et := NewErrorTracker(w)
|
||||
if err := generator.Init(c, et); err != nil {
|
||||
return err
|
||||
}
|
||||
for _, t := range c.Order {
|
||||
if err := generator.GenerateType(c, t, et); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err := generator.Finalize(c, et); err != nil {
|
||||
return err
|
||||
}
|
||||
return et.Error()
|
||||
}
|
||||
214
vendor/k8s.io/gengo/v2/generator/generator.go
generated
vendored
Normal file
214
vendor/k8s.io/gengo/v2/generator/generator.go
generated
vendored
Normal file
@@ -0,0 +1,214 @@
|
||||
/*
|
||||
Copyright 2015 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package generator
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
|
||||
"k8s.io/gengo/v2/namer"
|
||||
"k8s.io/gengo/v2/parser"
|
||||
"k8s.io/gengo/v2/types"
|
||||
)
|
||||
|
||||
// Target describes a Go package into which code will be generated. A single
|
||||
// Target may have many Generators, each of which emits one file.
|
||||
type Target interface {
|
||||
// Name returns the package short name (as in `package foo`).
|
||||
Name() string
|
||||
// Path returns the package import path (as in `import "example.com/foo"`).
|
||||
Path() string
|
||||
// Dir returns the location of the resulting package on disk. This may be
|
||||
// the same directory as an input package (when generating code in-place)
|
||||
// or a different directory entirely.
|
||||
Dir() string
|
||||
|
||||
// Filter should return true if this package cares about this type.
|
||||
// Otherwise, this type will be omitted from the type ordering for
|
||||
// this package.
|
||||
Filter(*Context, *types.Type) bool
|
||||
|
||||
// Header should return a header for the file, including comment markers.
|
||||
// Useful for copyright notices and doc strings. Include an
|
||||
// autogeneration notice! Do not include the "package x" line.
|
||||
Header(filename string) []byte
|
||||
|
||||
// Generators returns the list of generators for this package. It is
|
||||
// allowed for more than one generator to write to the same file.
|
||||
// A Context is passed in case the list of generators depends on the
|
||||
// input types.
|
||||
Generators(*Context) []Generator
|
||||
}
|
||||
|
||||
type File struct {
|
||||
Name string
|
||||
FileType string
|
||||
PackageName string
|
||||
Header []byte
|
||||
PackagePath string
|
||||
PackageDir string
|
||||
Imports map[string]struct{}
|
||||
Vars bytes.Buffer
|
||||
Consts bytes.Buffer
|
||||
Body bytes.Buffer
|
||||
}
|
||||
|
||||
type FileType interface {
|
||||
AssembleFile(f *File, path string) error
|
||||
}
|
||||
|
||||
// Generator is the contract for anything that wants to do auto-generation.
|
||||
// It's expected that the io.Writers passed to the below functions will be
|
||||
// ErrorTrackers; this allows implementations to not check for io errors,
|
||||
// making more readable code.
|
||||
//
|
||||
// The call order for the functions that take a Context is:
|
||||
// 1. Filter() // Subsequent calls see only types that pass this.
|
||||
// 2. Namers() // Subsequent calls see the namers provided by this.
|
||||
// 3. PackageVars()
|
||||
// 4. PackageConsts()
|
||||
// 5. Init()
|
||||
// 6. GenerateType() // Called N times, once per type in the context's Order.
|
||||
// 7. Imports()
|
||||
//
|
||||
// You may have multiple generators for the same file.
|
||||
type Generator interface {
|
||||
// The name of this generator. Will be included in generated comments.
|
||||
Name() string
|
||||
|
||||
// Filter should return true if this generator cares about this type.
|
||||
// (otherwise, GenerateType will not be called.)
|
||||
//
|
||||
// Filter is called before any of the generator's other functions;
|
||||
// subsequent calls will get a context with only the types that passed
|
||||
// this filter.
|
||||
Filter(*Context, *types.Type) bool
|
||||
|
||||
// If this generator needs special namers, return them here. These will
|
||||
// override the original namers in the context if there is a collision.
|
||||
// You may return nil if you don't need special names. These names will
|
||||
// be available in the context passed to the rest of the generator's
|
||||
// functions.
|
||||
//
|
||||
// A use case for this is to return a namer that tracks imports.
|
||||
Namers(*Context) namer.NameSystems
|
||||
|
||||
// Init should write an init function, and any other content that's not
|
||||
// generated per-type. (It's not intended for generator specific
|
||||
// initialization! Do that when your Target constructs the
|
||||
// Generators.)
|
||||
Init(*Context, io.Writer) error
|
||||
|
||||
// Finalize should write finish up functions, and any other content that's not
|
||||
// generated per-type.
|
||||
Finalize(*Context, io.Writer) error
|
||||
|
||||
// PackageVars should emit an array of variable lines. They will be
|
||||
// placed in a var ( ... ) block. There's no need to include a leading
|
||||
// \t or trailing \n.
|
||||
PackageVars(*Context) []string
|
||||
|
||||
// PackageConsts should emit an array of constant lines. They will be
|
||||
// placed in a const ( ... ) block. There's no need to include a leading
|
||||
// \t or trailing \n.
|
||||
PackageConsts(*Context) []string
|
||||
|
||||
// GenerateType should emit the code for a particular type.
|
||||
GenerateType(*Context, *types.Type, io.Writer) error
|
||||
|
||||
// Imports should return a list of necessary imports. They will be
|
||||
// formatted correctly. You do not need to include quotation marks,
|
||||
// return only the package name; alternatively, you can also return
|
||||
// imports in the format `name "path/to/pkg"`. Imports will be called
|
||||
// after Init, PackageVars, PackageConsts, and GenerateType, to allow
|
||||
// you to keep track of what imports you actually need.
|
||||
Imports(*Context) []string
|
||||
|
||||
// Preferred file name of this generator, not including a path. It is
|
||||
// allowed for multiple generators to use the same filename, but it's
|
||||
// up to you to make sure they don't have colliding import names.
|
||||
// TODO: provide per-file import tracking, removing the requirement
|
||||
// that generators coordinate..
|
||||
Filename() string
|
||||
|
||||
// A registered file type in the context to generate this file with. If
|
||||
// the FileType is not found in the context, execution will stop.
|
||||
FileType() string
|
||||
}
|
||||
|
||||
// Context is global context for individual generators to consume.
|
||||
type Context struct {
|
||||
// A map from the naming system to the names for that system. E.g., you
|
||||
// might have public names and several private naming systems.
|
||||
Namers namer.NameSystems
|
||||
|
||||
// All the types, in case you want to look up something.
|
||||
Universe types.Universe
|
||||
|
||||
// All the user-specified packages. This is after recursive expansion.
|
||||
Inputs []string
|
||||
|
||||
// The canonical ordering of the types (will be filtered by both the
|
||||
// Target's and Generator's Filter methods).
|
||||
Order []*types.Type
|
||||
|
||||
// A set of types this context can process. If this is empty or nil,
|
||||
// the default "go" filetype will be provided.
|
||||
FileTypes map[string]FileType
|
||||
|
||||
// Allows generators to add packages at runtime.
|
||||
parser *parser.Parser
|
||||
}
|
||||
|
||||
// NewContext generates a context from the given parser, naming systems, and
|
||||
// the naming system you wish to construct the canonical ordering from.
|
||||
func NewContext(p *parser.Parser, nameSystems namer.NameSystems, canonicalOrderName string) (*Context, error) {
|
||||
universe, err := p.NewUniverse()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
c := &Context{
|
||||
Namers: namer.NameSystems{},
|
||||
Universe: universe,
|
||||
Inputs: p.UserRequestedPackages(),
|
||||
FileTypes: map[string]FileType{
|
||||
GoFileType: NewGoFile(),
|
||||
},
|
||||
parser: p,
|
||||
}
|
||||
|
||||
for name, systemNamer := range nameSystems {
|
||||
c.Namers[name] = systemNamer
|
||||
if name == canonicalOrderName {
|
||||
orderer := namer.Orderer{Namer: systemNamer}
|
||||
c.Order = orderer.OrderUniverse(universe)
|
||||
}
|
||||
}
|
||||
return c, nil
|
||||
}
|
||||
|
||||
// LoadPackages adds Go packages to the context.
|
||||
func (c *Context) LoadPackages(patterns ...string) ([]*types.Package, error) {
|
||||
return c.parser.LoadPackagesTo(&c.Universe, patterns...)
|
||||
}
|
||||
|
||||
// FindPackages expands Go package patterns into a list of package import
|
||||
// paths, akin to `go list -find`.
|
||||
func (c *Context) FindPackages(patterns ...string) ([]string, error) {
|
||||
return c.parser.FindPackages(patterns...)
|
||||
}
|
||||
61
vendor/k8s.io/gengo/v2/generator/go_generator.go
generated
vendored
Normal file
61
vendor/k8s.io/gengo/v2/generator/go_generator.go
generated
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
Copyright 2015 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package generator
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"k8s.io/gengo/v2/namer"
|
||||
"k8s.io/gengo/v2/types"
|
||||
)
|
||||
|
||||
const (
|
||||
GoFileType = "go"
|
||||
)
|
||||
|
||||
// GoGenerator implements a do-nothing Generator for Go files. It can be
|
||||
// used as a base for custom Generators, which embed it and then define the
|
||||
// methods they need to specialize.
|
||||
type GoGenerator struct {
|
||||
// OutputFilename is used as the Generator's name, and filename.
|
||||
OutputFilename string
|
||||
|
||||
// Body, if present, will be used as the return from the "Init" method.
|
||||
// This causes it to be static content for the entire file if no other
|
||||
// generator touches the file.
|
||||
OptionalBody []byte
|
||||
}
|
||||
|
||||
func (gg GoGenerator) Name() string { return gg.OutputFilename }
|
||||
func (gg GoGenerator) Filter(*Context, *types.Type) bool { return true }
|
||||
func (gg GoGenerator) Namers(*Context) namer.NameSystems { return nil }
|
||||
func (gg GoGenerator) Imports(*Context) []string { return []string{} }
|
||||
func (gg GoGenerator) PackageVars(*Context) []string { return []string{} }
|
||||
func (gg GoGenerator) PackageConsts(*Context) []string { return []string{} }
|
||||
func (gg GoGenerator) GenerateType(*Context, *types.Type, io.Writer) error { return nil }
|
||||
func (gg GoGenerator) Filename() string { return gg.OutputFilename }
|
||||
func (gg GoGenerator) FileType() string { return GoFileType }
|
||||
func (gg GoGenerator) Finalize(*Context, io.Writer) error { return nil }
|
||||
|
||||
func (gg GoGenerator) Init(c *Context, w io.Writer) error {
|
||||
_, err := w.Write(gg.OptionalBody)
|
||||
return err
|
||||
}
|
||||
|
||||
var (
|
||||
_ = Generator(GoGenerator{})
|
||||
)
|
||||
89
vendor/k8s.io/gengo/v2/generator/import_tracker.go
generated
vendored
Normal file
89
vendor/k8s.io/gengo/v2/generator/import_tracker.go
generated
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
Copyright 2015 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package generator
|
||||
|
||||
import (
|
||||
"go/token"
|
||||
"strings"
|
||||
|
||||
"k8s.io/klog/v2"
|
||||
|
||||
"k8s.io/gengo/v2/namer"
|
||||
"k8s.io/gengo/v2/types"
|
||||
)
|
||||
|
||||
// NewImportTrackerForPackage creates a new import tracker which is aware
|
||||
// of a generator's output package. The tracker will not add import lines
|
||||
// when symbols or types are added from the same package, and LocalNameOf
|
||||
// will return empty string for the output package.
|
||||
//
|
||||
// e.g.:
|
||||
//
|
||||
// tracker := NewImportTrackerForPackage("bar.com/pkg/foo")
|
||||
// tracker.AddSymbol(types.Name{"bar.com/pkg/foo.MyType"})
|
||||
// tracker.AddSymbol(types.Name{"bar.com/pkg/baz.MyType"})
|
||||
// tracker.AddSymbol(types.Name{"bar.com/pkg/baz/baz.MyType"})
|
||||
//
|
||||
// tracker.LocalNameOf("bar.com/pkg/foo") -> ""
|
||||
// tracker.LocalNameOf("bar.com/pkg/baz") -> "baz"
|
||||
// tracker.LocalNameOf("bar.com/pkg/baz/baz") -> "bazbaz"
|
||||
// tracker.ImportLines() -> {`baz "bar.com/pkg/baz"`, `bazbaz "bar.com/pkg/baz/baz"`}
|
||||
func NewImportTrackerForPackage(local string, typesToAdd ...*types.Type) *namer.DefaultImportTracker {
|
||||
tracker := namer.NewDefaultImportTracker(types.Name{Package: local})
|
||||
tracker.IsInvalidType = func(*types.Type) bool { return false }
|
||||
tracker.LocalName = func(name types.Name) string { return goTrackerLocalName(&tracker, name) }
|
||||
tracker.PrintImport = func(path, name string) string { return name + " \"" + path + "\"" }
|
||||
|
||||
tracker.AddTypes(typesToAdd...)
|
||||
return &tracker
|
||||
}
|
||||
|
||||
func NewImportTracker(typesToAdd ...*types.Type) *namer.DefaultImportTracker {
|
||||
return NewImportTrackerForPackage("", typesToAdd...)
|
||||
}
|
||||
|
||||
func goTrackerLocalName(tracker namer.ImportTracker, t types.Name) string {
|
||||
path := t.Package
|
||||
|
||||
// Using backslashes in package names causes gengo to produce Go code which
|
||||
// will not compile with the gc compiler. See the comment on GoSeperator.
|
||||
if strings.ContainsRune(path, '\\') {
|
||||
klog.Warningf("Warning: backslash used in import path '%v', this is unsupported.\n", path)
|
||||
}
|
||||
|
||||
dirs := strings.Split(path, namer.GoSeperator)
|
||||
for n := len(dirs) - 1; n >= 0; n-- {
|
||||
// follow kube convention of not having anything between directory names
|
||||
name := strings.Join(dirs[n:], "")
|
||||
name = strings.ReplaceAll(name, "_", "")
|
||||
// These characters commonly appear in import paths for go
|
||||
// packages, but aren't legal go names. So we'll sanitize.
|
||||
name = strings.ReplaceAll(name, ".", "")
|
||||
name = strings.ReplaceAll(name, "-", "")
|
||||
if _, found := tracker.PathOf(name); found {
|
||||
// This name collides with some other package
|
||||
continue
|
||||
}
|
||||
|
||||
// If the import name is a Go keyword, prefix with an underscore.
|
||||
if token.Lookup(name).IsKeyword() {
|
||||
name = "_" + name
|
||||
}
|
||||
return name
|
||||
}
|
||||
panic("can't find import for " + path)
|
||||
}
|
||||
77
vendor/k8s.io/gengo/v2/generator/simple_target.go
generated
vendored
Normal file
77
vendor/k8s.io/gengo/v2/generator/simple_target.go
generated
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
Copyright 2015 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package generator
|
||||
|
||||
import (
|
||||
"k8s.io/gengo/v2/types"
|
||||
)
|
||||
|
||||
// SimpleTarget is implements Target in terms of static configuration.
|
||||
// The package name, path, and dir are required to be non-empty.
|
||||
type SimpleTarget struct {
|
||||
// PkgName is the name of the resulting package (as in "package xxxx").
|
||||
// Required.
|
||||
PkgName string
|
||||
// PkgPath is the canonical Go import-path of the resulting package (as in
|
||||
// "import example.com/xxxx/yyyy"). Required.
|
||||
PkgPath string
|
||||
// PkgDir is the location of the resulting package on disk (which may not
|
||||
// exist yet). It may be absolute or relative to CWD. Required.
|
||||
PkgDir string
|
||||
|
||||
// HeaderComment is emitted at the top of every output file. Optional.
|
||||
HeaderComment []byte
|
||||
|
||||
// PkgDocComment is emitted after the header comment for a "doc.go" file.
|
||||
// Optional.
|
||||
PkgDocComment []byte
|
||||
|
||||
// FilterFunc will be called to implement Target.Filter. Optional.
|
||||
FilterFunc func(*Context, *types.Type) bool
|
||||
|
||||
// GeneratorsFunc will be called to implement Target.Generators. Optional.
|
||||
GeneratorsFunc func(*Context) []Generator
|
||||
}
|
||||
|
||||
func (st SimpleTarget) Name() string { return st.PkgName }
|
||||
func (st SimpleTarget) Path() string { return st.PkgPath }
|
||||
func (st SimpleTarget) Dir() string { return st.PkgDir }
|
||||
|
||||
func (st SimpleTarget) Filter(c *Context, t *types.Type) bool {
|
||||
if st.FilterFunc != nil {
|
||||
return st.FilterFunc(c, t)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (st SimpleTarget) Generators(c *Context) []Generator {
|
||||
if st.GeneratorsFunc != nil {
|
||||
return st.GeneratorsFunc(c)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (st SimpleTarget) Header(filename string) []byte {
|
||||
if filename == "doc.go" {
|
||||
return append(st.HeaderComment, st.PkgDocComment...)
|
||||
}
|
||||
return st.HeaderComment
|
||||
}
|
||||
|
||||
var (
|
||||
_ = Target(SimpleTarget{})
|
||||
)
|
||||
154
vendor/k8s.io/gengo/v2/generator/snippet_writer.go
generated
vendored
Normal file
154
vendor/k8s.io/gengo/v2/generator/snippet_writer.go
generated
vendored
Normal file
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
Copyright 2015 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package generator
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"runtime"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
// SnippetWriter is an attempt to make the template library usable.
|
||||
// Methods are chainable, and you don't have to check Error() until you're all
|
||||
// done.
|
||||
type SnippetWriter struct {
|
||||
w io.Writer
|
||||
context *Context
|
||||
// Left & right delimiters. text/template defaults to "{{" and "}}"
|
||||
// which is totally unusable for go code based templates.
|
||||
left, right string
|
||||
funcMap template.FuncMap
|
||||
err error
|
||||
}
|
||||
|
||||
// w is the destination; left and right are the delimiters; @ and $ are both
|
||||
// reasonable choices.
|
||||
//
|
||||
// c is used to make a function for every naming system, to which you can pass
|
||||
// a type and get the corresponding name.
|
||||
func NewSnippetWriter(w io.Writer, c *Context, left, right string) *SnippetWriter {
|
||||
sw := &SnippetWriter{
|
||||
w: w,
|
||||
context: c,
|
||||
left: left,
|
||||
right: right,
|
||||
funcMap: template.FuncMap{},
|
||||
}
|
||||
for name, namer := range c.Namers {
|
||||
sw.funcMap[name] = namer.Name
|
||||
}
|
||||
return sw
|
||||
}
|
||||
|
||||
// Do parses format and runs args through it. You can have arbitrary logic in
|
||||
// the format (see the text/template documentation), but consider running many
|
||||
// short templates with ordinary go logic in between--this may be more
|
||||
// readable. Do is chainable. Any error causes every other call to do to be
|
||||
// ignored, and the error will be returned by Error(). So you can check it just
|
||||
// once, at the end of your function.
|
||||
//
|
||||
// 'args' can be quite literally anything; read the text/template documentation
|
||||
// for details. Maps and structs work particularly nicely. Conveniently, the
|
||||
// types package is designed to have structs that are easily referencable from
|
||||
// the template language.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// sw := generator.NewSnippetWriter(outBuffer, context, "$", "$")
|
||||
// sw.Do(`The public type name is: $.type|public$`, map[string]interface{}{"type": t})
|
||||
// return sw.Error()
|
||||
//
|
||||
// Where:
|
||||
// - "$" starts a template directive
|
||||
// - "." references the entire thing passed as args
|
||||
// - "type" therefore sees a map and looks up the key "type"
|
||||
// - "|" means "pass the thing on the left to the thing on the right"
|
||||
// - "public" is the name of a naming system, so the SnippetWriter has given
|
||||
// the template a function called "public" that takes a *types.Type and
|
||||
// returns the naming system's name. E.g., if the type is "string" this might
|
||||
// return "String".
|
||||
// - the second "$" ends the template directive.
|
||||
//
|
||||
// The map is actually not necessary. The below does the same thing:
|
||||
//
|
||||
// sw.Do(`The public type name is: $.|public$`, t)
|
||||
//
|
||||
// You may or may not find it more readable to use the map with a descriptive
|
||||
// key, but if you want to pass more than one arg, the map or a custom struct
|
||||
// becomes a requirement. You can do arbitrary logic inside these templates,
|
||||
// but you should consider doing the logic in go and stitching them together
|
||||
// for the sake of your readers.
|
||||
//
|
||||
// TODO: Change Do() to optionally take a list of pairs of parameters (key, value)
|
||||
// and have it construct a combined map with that and args.
|
||||
func (s *SnippetWriter) Do(format string, args interface{}) *SnippetWriter {
|
||||
if s.err != nil {
|
||||
return s
|
||||
}
|
||||
// Name the template by source file:line so it can be found when
|
||||
// there's an error.
|
||||
_, file, line, _ := runtime.Caller(1)
|
||||
tmpl, err := template.
|
||||
New(fmt.Sprintf("%s:%d", file, line)).
|
||||
Delims(s.left, s.right).
|
||||
Funcs(s.funcMap).
|
||||
Parse(format)
|
||||
if err != nil {
|
||||
s.err = err
|
||||
return s
|
||||
}
|
||||
err = tmpl.Execute(s.w, args)
|
||||
if err != nil {
|
||||
s.err = err
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// Args exists to make it convenient to construct arguments for
|
||||
// SnippetWriter.Do.
|
||||
type Args map[interface{}]interface{}
|
||||
|
||||
// With makes a copy of a and adds the given key, value pair.
|
||||
func (a Args) With(key, value interface{}) Args {
|
||||
a2 := Args{key: value}
|
||||
for k, v := range a {
|
||||
a2[k] = v
|
||||
}
|
||||
return a2
|
||||
}
|
||||
|
||||
// WithArgs makes a copy of a and adds the given arguments.
|
||||
func (a Args) WithArgs(rhs Args) Args {
|
||||
a2 := Args{}
|
||||
for k, v := range rhs {
|
||||
a2[k] = v
|
||||
}
|
||||
for k, v := range a {
|
||||
a2[k] = v
|
||||
}
|
||||
return a2
|
||||
}
|
||||
|
||||
func (s *SnippetWriter) Out() io.Writer {
|
||||
return s.w
|
||||
}
|
||||
|
||||
// Error returns any encountered error.
|
||||
func (s *SnippetWriter) Error() error {
|
||||
return s.err
|
||||
}
|
||||
Reference in New Issue
Block a user