mirror of
				https://github.com/k3s-io/kubernetes.git
				synced 2025-10-31 13:50:01 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			216 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			216 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| /*
 | |
| 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 protobuf
 | |
| 
 | |
| import (
 | |
| 	"fmt"
 | |
| 	"go/ast"
 | |
| 	"log"
 | |
| 	"os"
 | |
| 	"path/filepath"
 | |
| 	"reflect"
 | |
| 	"strings"
 | |
| 
 | |
| 	"k8s.io/gengo/generator"
 | |
| 	"k8s.io/gengo/types"
 | |
| )
 | |
| 
 | |
| func newProtobufPackage(packagePath, packageName string, generateAll bool, omitFieldTypes map[types.Name]struct{}) *protobufPackage {
 | |
| 	pkg := &protobufPackage{
 | |
| 		DefaultPackage: generator.DefaultPackage{
 | |
| 			// The protobuf package name (foo.bar.baz)
 | |
| 			PackageName: packageName,
 | |
| 			// A path segment relative to the GOPATH root (foo/bar/baz)
 | |
| 			PackagePath: packagePath,
 | |
| 			HeaderText: []byte(
 | |
| 				`
 | |
| // This file was autogenerated by go-to-protobuf. Do not edit it manually!
 | |
| 
 | |
| `),
 | |
| 			PackageDocumentation: []byte(fmt.Sprintf(
 | |
| 				`// Package %s is an autogenerated protobuf IDL.
 | |
| `, packageName)),
 | |
| 		},
 | |
| 		GenerateAll:    generateAll,
 | |
| 		OmitFieldTypes: omitFieldTypes,
 | |
| 	}
 | |
| 	pkg.FilterFunc = pkg.filterFunc
 | |
| 	pkg.GeneratorFunc = pkg.generatorFunc
 | |
| 	return pkg
 | |
| }
 | |
| 
 | |
| // protobufPackage contains the protobuf implementation of Package.
 | |
| type protobufPackage struct {
 | |
| 	generator.DefaultPackage
 | |
| 
 | |
| 	// If true, this package has been vendored into our source tree and thus can
 | |
| 	// only be generated by changing the vendor tree.
 | |
| 	Vendored bool
 | |
| 
 | |
| 	// If true, generate protobuf serializations for all public types.
 | |
| 	// If false, only generate protobuf serializations for structs that
 | |
| 	// request serialization.
 | |
| 	GenerateAll bool
 | |
| 
 | |
| 	// A list of types to filter to; if not specified all types will be included.
 | |
| 	FilterTypes map[types.Name]struct{}
 | |
| 
 | |
| 	// If true, omit any gogoprotobuf extensions not defined as types.
 | |
| 	OmitGogo bool
 | |
| 
 | |
| 	// A list of field types that will be excluded from the output struct
 | |
| 	OmitFieldTypes map[types.Name]struct{}
 | |
| 
 | |
| 	// A list of names that this package exports
 | |
| 	LocalNames map[string]struct{}
 | |
| 
 | |
| 	// A list of type names in this package that will need marshaller rewriting
 | |
| 	// to remove synthetic protobuf fields.
 | |
| 	OptionalTypeNames map[string]struct{}
 | |
| 
 | |
| 	// A list of struct tags to generate onto named struct fields
 | |
| 	StructTags map[string]map[string]string
 | |
| 
 | |
| 	// An import tracker for this package
 | |
| 	Imports *ImportTracker
 | |
| }
 | |
| 
 | |
| func (p *protobufPackage) Clean(outputBase string) error {
 | |
| 	for _, s := range []string{p.ImportPath(), p.OutputPath()} {
 | |
| 		if err := os.Remove(filepath.Join(outputBase, s)); err != nil && !os.IsNotExist(err) {
 | |
| 			return err
 | |
| 		}
 | |
| 	}
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| func (p *protobufPackage) ProtoTypeName() types.Name {
 | |
| 	return types.Name{
 | |
| 		Name:    p.Path(),       // the go path "foo/bar/baz"
 | |
| 		Package: p.Name(),       // the protobuf package "foo.bar.baz"
 | |
| 		Path:    p.ImportPath(), // the path of the import to get the proto
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (p *protobufPackage) filterFunc(c *generator.Context, t *types.Type) bool {
 | |
| 	switch t.Kind {
 | |
| 	case types.Func, types.Chan:
 | |
| 		return false
 | |
| 	case types.Struct:
 | |
| 		if t.Name.Name == "struct{}" {
 | |
| 			return false
 | |
| 		}
 | |
| 	case types.Builtin:
 | |
| 		return false
 | |
| 	case types.Alias:
 | |
| 		if !isOptionalAlias(t) {
 | |
| 			return false
 | |
| 		}
 | |
| 	case types.Slice, types.Array, types.Map:
 | |
| 		return false
 | |
| 	case types.Pointer:
 | |
| 		return false
 | |
| 	}
 | |
| 	if _, ok := isFundamentalProtoType(t); ok {
 | |
| 		return false
 | |
| 	}
 | |
| 	_, ok := p.FilterTypes[t.Name]
 | |
| 	return ok
 | |
| }
 | |
| 
 | |
| func (p *protobufPackage) HasGoType(name string) bool {
 | |
| 	_, ok := p.LocalNames[name]
 | |
| 	return ok
 | |
| }
 | |
| 
 | |
| func (p *protobufPackage) OptionalTypeName(name string) bool {
 | |
| 	_, ok := p.OptionalTypeNames[name]
 | |
| 	return ok
 | |
| }
 | |
| 
 | |
| func (p *protobufPackage) ExtractGeneratedType(t *ast.TypeSpec) bool {
 | |
| 	if !p.HasGoType(t.Name.Name) {
 | |
| 		return false
 | |
| 	}
 | |
| 
 | |
| 	switch s := t.Type.(type) {
 | |
| 	case *ast.StructType:
 | |
| 		for i, f := range s.Fields.List {
 | |
| 			if len(f.Tag.Value) == 0 {
 | |
| 				continue
 | |
| 			}
 | |
| 			tag := strings.Trim(f.Tag.Value, "`")
 | |
| 			protobufTag := reflect.StructTag(tag).Get("protobuf")
 | |
| 			if len(protobufTag) == 0 {
 | |
| 				continue
 | |
| 			}
 | |
| 			if len(f.Names) > 1 {
 | |
| 				log.Printf("WARNING: struct %s field %d %s: defined multiple names but single protobuf tag", t.Name.Name, i, f.Names[0].Name)
 | |
| 				// TODO hard error?
 | |
| 			}
 | |
| 			if p.StructTags == nil {
 | |
| 				p.StructTags = make(map[string]map[string]string)
 | |
| 			}
 | |
| 			m := p.StructTags[t.Name.Name]
 | |
| 			if m == nil {
 | |
| 				m = make(map[string]string)
 | |
| 				p.StructTags[t.Name.Name] = m
 | |
| 			}
 | |
| 			m[f.Names[0].Name] = tag
 | |
| 		}
 | |
| 	default:
 | |
| 		log.Printf("WARNING: unexpected Go AST type definition: %#v", t)
 | |
| 	}
 | |
| 
 | |
| 	return true
 | |
| }
 | |
| 
 | |
| func (p *protobufPackage) generatorFunc(c *generator.Context) []generator.Generator {
 | |
| 	generators := []generator.Generator{}
 | |
| 
 | |
| 	p.Imports.AddNullable()
 | |
| 
 | |
| 	generators = append(generators, &genProtoIDL{
 | |
| 		DefaultGen: generator.DefaultGen{
 | |
| 			OptionalName: "generated",
 | |
| 		},
 | |
| 		localPackage:   types.Name{Package: p.PackageName, Path: p.PackagePath},
 | |
| 		localGoPackage: types.Name{Package: p.PackagePath, Name: p.GoPackageName()},
 | |
| 		imports:        p.Imports,
 | |
| 		generateAll:    p.GenerateAll,
 | |
| 		omitGogo:       p.OmitGogo,
 | |
| 		omitFieldTypes: p.OmitFieldTypes,
 | |
| 	})
 | |
| 	return generators
 | |
| }
 | |
| 
 | |
| func (p *protobufPackage) GoPackageName() string {
 | |
| 	return filepath.Base(p.PackagePath)
 | |
| }
 | |
| 
 | |
| func (p *protobufPackage) ImportPath() string {
 | |
| 	return filepath.Join(p.PackagePath, "generated.proto")
 | |
| }
 | |
| 
 | |
| func (p *protobufPackage) OutputPath() string {
 | |
| 	return filepath.Join(p.PackagePath, "generated.pb.go")
 | |
| }
 | |
| 
 | |
| var (
 | |
| 	_ = generator.Package(&protobufPackage{})
 | |
| )
 |