Documentation

Overview

    Package namer has support for making different type naming systems.

    This is because sometimes you want to refer to the literal type, sometimes you want to make a name for the thing you're generating, and you want to make the name based on the type. For example, if you have `type foo string`, you want to be able to generate something like `func FooPrinter(f *foo) { Print(string(*f)) }`; that is, you want to refer to a public name, a literal name, and the underlying literal name.

    This package supports the idea of a "Namer" and a set of "NameSystems" to support these use cases.

    Additionally, a "RawNamer" can optionally keep track of what needs to be imported.

    Index

    Constants

    View Source
    const (
    	// GoSeperator is used to split go import paths.
    	// Forward slash is used instead of filepath.Seperator because it is the
    	// only universally-accepted path delimiter and the only delimiter not
    	// potentially forbidden by Go compilers. (In particular gc does not allow
    	// the use of backslashes in import paths.)
    	// See https://golang.org/ref/spec#Import_declarations.
    	// See also https://github.com/kubernetes/gengo/issues/83#issuecomment-367040772.
    	GoSeperator = "/"
    )

    Variables

    This section is empty.

    Functions

    func IC

    func IC(in string) string

      IC ensures the first character is uppercase.

      func IL

      func IL(in string) string

        IL ensures the first character is lowercase.

        func IsPrivateGoName

        func IsPrivateGoName(name string) bool

          Returns whether a name is a private Go name.

          func Joiner

          func Joiner(first, others func(string) string) func(pre string, in []string, post string) string

            Joiner lets you specify functions that preprocess the various components of a name before joining them. You can construct e.g. camelCase or CamelCase or any other way of joining words. (See the IC and IL convenience functions.)

            func NewAllLowercasePluralNamer

            func NewAllLowercasePluralNamer(exceptions map[string]string) *pluralNamer

              NewAllLowercasePluralNamer returns a namer that returns the plural form of the input type's name, with all letters in lowercase.

              func NewPrivatePluralNamer

              func NewPrivatePluralNamer(exceptions map[string]string) *pluralNamer

                NewPrivatePluralNamer returns a namer that returns the plural form of the input type's name, starting with a lowercase letter.

                func NewPublicPluralNamer

                func NewPublicPluralNamer(exceptions map[string]string) *pluralNamer

                  NewPublicPluralNamer returns a namer that returns the plural form of the input type's name, starting with a uppercase letter.

                  func NewRawNamer

                  func NewRawNamer(pkg string, tracker ImportTracker) *rawNamer

                    NewRawNamer will return a Namer that makes a name by which you would directly refer to a type, optionally keeping track of the import paths necessary to reference the names it provides. Tracker may be nil. The 'pkg' is the full package name, in which the Namer is used - all types from that package will be referenced by just type name without referencing the package.

                    For example, if the type is map[string]int, a raw namer will literally return "map[string]int".

                    Or if the type, in package foo, is "type Bar struct { ... }", then the raw namer will return "foo.Bar" as the name of the type, and if 'tracker' was not nil, will record that package foo needs to be imported.

                    Types

                    type DefaultImportTracker

                    type DefaultImportTracker struct {
                    
                    	// Returns true if a given types is an invalid type and should be ignored.
                    	IsInvalidType func(*types.Type) bool
                    	// Returns the final local name for the given name
                    	LocalName func(types.Name) string
                    	// Returns the "import" line for a given (path, name).
                    	PrintImport func(string, string) string
                    	// contains filtered or unexported fields
                    }

                      ImportTracker may be passed to a namer.RawNamer, to track the imports needed for the types it names.

                      TODO: pay attention to the package name (instead of renaming every package).

                      func NewDefaultImportTracker

                      func NewDefaultImportTracker(local types.Name) DefaultImportTracker

                      func (*DefaultImportTracker) AddType

                      func (tracker *DefaultImportTracker) AddType(t *types.Type)

                      func (*DefaultImportTracker) AddTypes

                      func (tracker *DefaultImportTracker) AddTypes(types ...*types.Type)

                      func (*DefaultImportTracker) ImportLines

                      func (tracker *DefaultImportTracker) ImportLines() []string

                      func (*DefaultImportTracker) LocalNameOf

                      func (tracker *DefaultImportTracker) LocalNameOf(path string) string

                        LocalNameOf returns the name you would use to refer to the package at the specified path within the body of a file.

                        func (*DefaultImportTracker) PathOf

                        func (tracker *DefaultImportTracker) PathOf(localName string) (string, bool)

                          PathOf returns the path that a given localName is referring to within the body of a file.

                          type ImportTracker

                          type ImportTracker interface {
                          	AddType(*types.Type)
                          	LocalNameOf(packagePath string) string
                          	PathOf(localName string) (string, bool)
                          	ImportLines() []string
                          }

                            ImportTracker allows a raw namer to keep track of the packages needed for import. You can implement yourself or use the one in the generation package.

                            type NameStrategy

                            type NameStrategy struct {
                            	Prefix, Suffix string
                            	Join           func(pre string, parts []string, post string) string
                            
                            	// Add non-meaningful package directory names here (e.g. "proto") and
                            	// they will be ignored.
                            	IgnoreWords map[string]bool
                            
                            	// If > 0, prepend exactly that many package directory names (or as
                            	// many as there are).  Package names listed in "IgnoreWords" will be
                            	// ignored.
                            	//
                            	// For example, if Ignore words lists "proto" and type Foo is in
                            	// pkg/server/frobbing/proto, then a value of 1 will give a type name
                            	// of FrobbingFoo, 2 gives ServerFrobbingFoo, etc.
                            	PrependPackageNames int
                            
                            	// A cache of names thus far assigned by this namer.
                            	Names
                            }

                              NameStrategy is a general Namer. The easiest way to use it is to copy the Public/PrivateNamer variables, and modify the members you wish to change.

                              The Name method produces a name for the given type, of the forms: Anonymous types: <Prefix><Type description><Suffix> Named types: <Prefix><Optional Prepended Package name(s)><Original name><Suffix>

                              In all cases, every part of the name is run through the capitalization functions.

                              The IgnoreWords map can be set if you have directory names that are semantically meaningless for naming purposes, e.g. "proto".

                              Prefix and Suffix can be used to disambiguate parallel systems of type names. For example, if you want to generate an interface and an implementation, you might want to suffix one with "Interface" and the other with "Implementation". Another common use-- if you want to generate private types, and one of your source types could be "string", you can't use the default lowercase private namer. You'll have to add a suffix or prefix.

                              func NewPrivateNamer

                              func NewPrivateNamer(prependPackageNames int, ignoreWords ...string) *NameStrategy

                                NewPrivateNamer is a helper function that returns a namer that makes camelCase names. See the NameStrategy struct for an explanation of the arguments to this constructor.

                                func NewPublicNamer

                                func NewPublicNamer(prependPackageNames int, ignoreWords ...string) *NameStrategy

                                  NewPublicNamer is a helper function that returns a namer that makes CamelCase names. See the NameStrategy struct for an explanation of the arguments to this constructor.

                                  func (*NameStrategy) Name

                                  func (ns *NameStrategy) Name(t *types.Type) string

                                    See the comment on NameStrategy.

                                    type NameSystems

                                    type NameSystems map[string]Namer

                                      NameSystems is a map of a system name to a namer for that system.

                                      type Namer

                                      type Namer interface {
                                      	Name(*types.Type) string
                                      }

                                        Namer takes a type, and assigns a name.

                                        The purpose of this complexity is so that you can assign coherent side-by-side systems of names for the types. For example, you might want a public interface, a private implementation struct, and also to reference literally the type name.

                                        Note that it is safe to call your own Name() function recursively to find the names of keys, elements, etc. This is because anonymous types can't have cycles in their names, and named types don't require the sort of recursion that would be problematic.

                                        type Names

                                        type Names map[*types.Type]string

                                          Names is a map from Type to name, as defined by some Namer.

                                          type Orderer

                                          type Orderer struct {
                                          	Namer
                                          }

                                            Orderer produces an ordering of types given a Namer.

                                            func (*Orderer) OrderTypes

                                            func (o *Orderer) OrderTypes(typeList []*types.Type) []*types.Type

                                              OrderTypes assigns a name to every type, and returns a list sorted by those names.

                                              func (*Orderer) OrderUniverse

                                              func (o *Orderer) OrderUniverse(u types.Universe) []*types.Type

                                                OrderUniverse assigns a name to every type in the Universe, including Types, Functions and Variables, and returns a list sorted by those names.