gen

package
v0.4.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 8, 2024 License: MIT Imports: 12 Imported by: 0

Documentation

Overview

Package gen implements an enumeration generator.

Enumerations are described by a configuration. Each enumeration defines a type name and one or more enumerator values.

Type Structure

The generated type is a struct containing an unexported small integer index to the string representation of the enumerator. Enumerators of the type can be compared for equality by value, and can be used as map keys. The zero value represents an unknown (invalid) enumerator; the Valid method reports whether an enumerator is valid (i.e., non-zero).

The String method returns a string representation for each enumerator, which defaults to the enumerator's base name. The Enum method returns the name of the enumeration type.

Enumerations generated by this package all satisfy this interface:

type EnumType interface {
   Enum() string   // return the enumeration type name
   Index() int     // return the integer index of the enumerator
   String() string // return the string representation of an enumerator
   Valid() bool    // report whether the receiver is a valid nonzero enumerator
}

Callers wishing to accept arbitrary enumerations may define this interface. It is not exported by the gen package to discourage inappropriate dependency on the code generator.

Configuration

The gen.Config type defines a set of enumerations to generate in a single package. The general structure of a config in YAML is:

package: "name"        # the name of the output package (required)

enum:                  # a list of enumeration types to generate

  - type: "Name"       # the type name for this enum
    prefix: "x"        # (optional) prefix to append to each enumerator name
    zero: "Bad"        # (optional) name of zero enumerator

    doc: "text"        # (optional) documentation comment for the enum type
    val-doc: "text"    # (optional) aggregate documentation for the values

    constructor: true  # construct a New* function to convert strings to enumerators
    flag-value: true   # implement the flag.Value interface on this enum
    text-marshal: true # implement the TextMarshaler/Unmarshaler interfaces on this enum

    values:
      - name: A        # the name of the first enumerator (required)
        doc: "text"    # (optional) documentation for this enumerator
        text: "aaa"    # (optional) string text for the enumerator
        index: 25      # (optional) integer index for the enumerator

      - name: B        # ... additional enumerators
      - name: C

  - type: "Other"
    values:
      - name: X
      - name: Y
Example
package main

import (
	"log"
	"os"

	"github.com/creachadair/enumgen/gen"
)

const input = `package example
/*enumgen:type Example

# package example inferred from the declaration above.
# The type name assigned by the enumgen: comment.

doc: Example is an example enumeration.
values:
  - name: Good
    doc: upsides
  - name: Bad
    doc: downsides
  - name: Ugly
    doc: what it says on the tin
*/
`

func main() {
	cfg, err := gen.ConfigFromSource("example.go", []byte(input))
	if err != nil {
		log.Fatalf("Parse: %v", err)
	}
	if err := cfg.Generate(os.Stdout); err != nil {
		log.Fatalf("Generate: %v", err)
	}
}
Output:

// Code generated by enumgen. DO NOT EDIT.

package example

// Example is an example enumeration.
type Example struct{ _Example uint8 }

// Enum returns the name of the enumeration type for Example.
func (Example) Enum() string { return "Example" }

// String returns the string representation of Example v.
func (v Example) String() string { return _str_Example[v._Example] }

// Valid reports whether v is a valid non-zero Example value.
func (v Example) Valid() bool { return v._Example > 0 && int(v._Example) < len(_str_Example) }

// Index returns the integer index of Example v.
func (v Example) Index() int { return int(v._Example) }

var (
	_str_Example = []string{"<invalid>", "Good", "Bad", "Ugly"}

	Good = Example{1} // upsides
	Bad  = Example{2} // downsides
	Ugly = Example{3} // what it says on the tin
)

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Config

type Config struct {
	Package string  // package name for the generated file (required)
	Enum    []*Enum // enumerations to generate (at least one is required)
}

A Config specifies a collection of enumerations in a single package.

func ConfigFromGoFile added in v0.2.2

func ConfigFromGoFile(path string) (*Config, error)

ConfigFromGoFile reads and parses the Go file specified by path, and extracts a YAML config from each first comment block tagged enumgen:type found in the file. An error results if no such comment is found.

func ConfigFromSource added in v0.0.5

func ConfigFromSource(path string, text []byte) (*Config, error)

ConfigFromSource parses a config from the text of a Go source file. The path is used to for diagnostics.

func ConfigFromYAML added in v0.4.2

func ConfigFromYAML(path string) (*Config, error)

ConfigFromYAML reads and parses the YAML config file specified by path.

func LoadPackage added in v0.4.0

func LoadPackage() (*Config, error)

LoadPackage reads and parses a combined YAML configuration from the Go files stored in the current working directory.

An error is reported if the current working directory does not contain any Go source files with enumeration configurations in them, or if the files match multiple package names.

func ParseConfig

func ParseConfig(r io.Reader) (*Config, error)

ParseConfig parses a YAML configuration text from r.

func (*Config) Generate

func (c *Config) Generate(w io.Writer) error

Generate generates the enumerations defined by c into w as Go source text.

If there is an error formatting the generated code, the unformatted code is still written to w before reporting the error. The caller should NOT use the output in case of error. Any error means there is a bug in the generator, and the output is written only to support debugging.

type Enum

type Enum struct {
	Type   string   // enumeration type name (required)
	Values []*Value // the enumeration values (required)

	// If set, this prefix is prepended to each enumerator's variable name.
	// Otherwise, the variable name matches the Name field of the value.
	Prefix string

	// If set, this text is added as a doc comment for the enumeration.
	// Multiple lines are OK. The text should not contain comment markers.
	Doc string

	// If set, a variable is defined for the zero value with this name.
	// Typically a name like "Unknown" or "Invalid" makes sense.
	// Otherwise, no variable is defined for the zero value; the caller can
	// still construct a zero value explicitly if needed.
	//
	// Documentation and text for the zero value can be provided by including an
	// entry with this name in the list of values. Otherwise the zero value will
	// be undocumented and use a default string. The index of the zero value is
	// always 0, even if explicitly specified.
	Zero string

	// If set, this text is inserted at the top of the var block in the
	// generated code for the enumerator values.
	ValDoc string `yaml:"val-doc"`

	// If true, generate a New function to convert strings to enumerators.
	Constructor bool `yaml:"constructor"`

	// If true, generate methods to implement flag.Value for the type.
	FlagValue bool `yaml:"flag-value"`

	// If true, implement encoding.TextMarshaler for the type.
	TextMarshal bool `yaml:"text-marshal"`
}

An Enum defines an enumeration type.

The generated type for an enumeration is a struct with an unexported pointer to the string representation of the enumerator. This representation allows cheap pointer comparisons, and users of the type outside the package cannot create new non-zero values of the type. The zero value is explicitly defined as the "unknown" value for an enumeration.

type Value

type Value struct {
	Name string // enumerator name (required)

	// If set, this text is added as a doc comment for the enumerator value.  If
	// it is a single line, it is added as a line comment; otherwise it is
	// placed before the enumerator. The text should not contain comment markers.
	// The placeholder {name} will be replaced with the final generated name of
	// the enumerator.
	Doc string

	// If set, this text is used as the string representation of the value.
	// Otherwise, the Name field is used.
	Text string

	// If non-nil, this value is used as the index of the value.  Otherwise the
	// index is one greater than the previous value's index.
	Index *int
}

A Value defines a single enumerator.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL