Categorygithub.com/shabbyrobe/structer
modulepackage
0.0.0-20200209062959-a6481346f603
Repository: https://github.com/shabbyrobe/structer.git
Documentation: pkg.go.dev

# README

Structer

Note: This badly needed a lick of paint before Go Modules came onto the scene, and should now be considered obsolete/unmaintained. Having said that, if you depend on this and you run into trouble with it, please open an issue and I'll see if I can help.


Structer is a tool for dismantling struct definitions to try to ease the agony of code generation.

Structer requires Go 1.9.

It ties together go/types <https://godoc.org/go/types>_ and go/ast <https://godoc.org/go/ast>_ to try to simplify recursively walking through a type declaration, importing relevant pacakges and extracting required code and documentation.

The API is very much a moving target at this point - the main use case is supporting my alternative msgp code generator <https://github.com/shabbyrobe/msgpgen>_ (which supplements msgp <https://github.com/tinylib/msgp>_ with some sorely needed conveniences), but any reports of other use cases that could be supported would be great!

Efficiency is not a major goal of this project - sewing together the disparate and disjointed APIs of go/types, go/ast and go/doc is the overriding priority.

The core of structer is the TypePackageSet, which allows you to import complete packages and their ASTs::

tpset := structer.NewTypePackageSet()
pkg, err := tpset.Import("path/to/pkg")

You can then recursively walk type definitions (importing external defs as you like by calling back to TypePackageSet) in order to generate code. Either fully implement structer.TypeVisitor yourself, or just part of it using structer.PartialTypeVisitor::

ppv := &structer.PartialTypeVisitor{
    EnterStructFunc: func(s s structer.StructInfo) error {
        return nil
    },
    LeaveStructFunc: func(s structer.StructInfo) error {
        return nil
    },
    EnterFieldFunc: func(s s structer.StructInfo, field *types.Var, tag string) error {
        return nil
    },
    LeaveFieldFunc: func(s s structer.StructInfo, field *types.Var, tag string) error {
        return nil
    },
    VisitBasic(t *types.Basic) error {
        fmt.Printf("Found basic leaf node %s", t.String())
        return nil
    },
    VisitNamed(t *types.Named) error {
        fmt.Printf("Found named leaf node %s, importing", t.String())
        _, err := tpset.ImportNamed(t)
        return err
    },
}

Walk will visit every part of a compound type declaration and stop only at types.Basic or types.Named declarations.

Walk shouldn't even have trouble with this crazy thing::

type Pants struct {
    Foo struct {
        Bar map[struct{ X, Y int}]map[struct{ Y, Z int}]struct {
            Baz []*Pants
        }
    }
}

Structer also allows you to extract all constant values across all imported packages that have a certain type::

tpset := structer.NewTypePackageSet()
pkg, err := tpset.Import("path/to/pkg")
consts, err := tpset.ExtractConstants(structer.NewTypeName("path/to/pkg", "MyEnum"), false)

Known limitations

  • API is very unstable
  • Not enough tests yet
  • Poor documentation
  • TypeVisitor should possibly have EnterMap and LeaveMap. EnterMapKey and LeaveMapValue may be sufficient, but they're less clear.

# Packages

No description provided by the author

# Functions

types.Implements is a bit more low level - this will report true if the iface is a named type with an underlying interface, and also if the checked type is assignable as a pointer as well as without.
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
WAT?.
No description provided by the author
Walk walks a type recursively, visiting each child type using the visitor provided.

# Constants

Log code indicating an error was returned by types.Config.Check, but execution continued.
Log code indicating an error occurred in the types.Config.Error callback, but execution continued.
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author

# Variables

No description provided by the author
No description provided by the author
step over the current node.

# Structs

No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
MultiVisitor allows you to wrap multiple visitors and call each of them in sequence for each node in the type definition.
PartialTypeVisitor allows you to conveniently construct a visitor using only a handful of the Visit/Enter/Leave methods provided by the TypeVisitor interface.
No description provided by the author
No description provided by the author
TypePackageSet collects information about the types in all of the imported packages.

# Interfaces

No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author

# Type aliases

No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author