valast

package module
v1.4.4 Latest Latest
Warning

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

Go to latest
Published: Aug 8, 2023 License: Apache-2.0, MIT, Apache-2.0, + 1 more Imports: 16 Imported by: 12

README

valast - convert Go values to their AST Hexops logo

Go Reference

Go CI codecov Go Report Card

Valast converts Go values at runtime into their go/ast equivalent, e.g.:

x := &foo.Bar{
    a: "hello world!",
    B: 1.234,
}
fmt.Println(valast.String(x))

Prints string:

&foo.Bar{a: "hello world!", B: 1.234}

What is this useful for?

This can be useful for debugging and testing, you may think of it as a more comprehensive and configurable version of the fmt package's %+v and %#v formatting directives. It is similar to e.g. repr in Python.

Features

  • Produces Go code via a go/ast, defers formatting to the best-in-class Go formatter gofumpt.
  • Fully handles unexported fields, types, and values (optional.)
  • Strong emphasis on being used for producing valid Go code that can be copy & pasted directly into e.g. tests.
  • Extensively tested, over 88 tests and handling numerous edge cases (such as pointers to unaddressable literal values like &"foo" properly, and even finding bugs in alternative packages').

Alternatives comparison

The following are alternatives to Valast, making note of the differences we found that let us to create Valast:

You may also wish to look at autogold and go-cmp, which aim to solve the "compare Go values in a test" problem.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Addr added in v1.2.0

func Addr(v interface{}) interface{}

DEPRECATED: use valast.Ptr instead.

Addr returns a pointer to the given value.

It is the only way to create a reference to certain values within a Go expression, for example since &"hello" is illegal, it can instead be written in a single expression as:

valast.Addr("hello").(*string)

func AddrInterface added in v1.2.0

func AddrInterface(v, pointerToType interface{}) interface{}

AddrInterface returns a pointer to the given interface value, which is determined to be of type T. For example, since &MyInterface(MyValue{}) is illegal, it can instead be written in a single expression as:

valast.AddrInterface(&MyValue{}, (*MyInterface)(nil))

The second parameter should be a pointer to the interface type. This is needed because reflect.ValueOf(&v).Type() returns *MyValue not MyInterface, due to reflect.ValueOf taking an interface{} parameter and losing that type information.

func DefaultPackagePathToName

func DefaultPackagePathToName(path string) (string, error)

DefaultPackagePathToName loads the specified package from disk to determine the package name.

func Ptr added in v1.4.4

func Ptr[V any](v V) *V

Ptr returns a pointer to the given value.

func String

func String(v interface{}) string

String converts the value v into the equivalent Go literal syntax.

It is an opinionated helper for the more extensive AST function.

If any error occurs, it will be returned as the string value. If handling errors is desired then consider using the AST function directly.

func StringWithOptions

func StringWithOptions(v interface{}, opt *Options) string

StringWithOptions converts the value v into the equivalent Go literal syntax, with the specified options.

It is an opinionated helper for the more extensive AST function.

If any error occurs, it will be returned as the string value. If handling errors is desired then consider using the AST function directly.

Types

type ErrInvalidType

type ErrInvalidType struct {
	// Value is the actual value that was being converted.
	Value interface{}
}

ErrInvalidType describes that the value is of a type that cannot be converted to an AST.

func (*ErrInvalidType) Error

func (e *ErrInvalidType) Error() string

Error implements the error interface.

type Options

type Options struct {
	// Unqualify, if true, indicates that types should be unqualified. e.g.:
	//
	// 	int(8)           -> 8
	// 	Bar{}            -> Bar{}
	// 	string("foobar") -> "foobar"
	//
	// This is set to true automatically when operating within a context where type qualification
	// is definitively not needed, e.g. when producing values for a struct or map.
	Unqualify bool

	// PackagePath, if non-zero, describes that the literal is being produced within the described
	// package path, and thus type selectors `pkg.Foo` should just be written `Foo` if the package
	// path and name match.
	PackagePath string

	// PackageName, if non-zero, describes that the literal is being produced within the described
	// package name, and thus type selectors `pkg.Foo` should just be written `Foo` if the package
	// path and name match.
	PackageName string

	// ExportedOnly indicates if only exported fields and values should be included.
	ExportedOnly bool

	// PackagePathToName, if non-nil, is called to convert a Go package path to the package name
	// written in its source. The default is DefaultPackagePathToName
	PackagePathToName func(path string) (string, error)
}

Options describes options for the conversion process.

type Result

type Result struct {
	// AST is the actual Go AST expression for the value.
	//
	// If Options.ExportedOnly == true, and the input value was unexported this field will be nil.
	AST ast.Expr

	// OmittedUnexported indicates if unexported fields were omitted or not. Only indicative if
	// Options.ExportedOnly == true.
	OmittedUnexported bool

	// RequiresUnexported indicates if the AST requires access to unexported types/values outside
	// of the package specified in the Options, and is thus invalid code.
	RequiresUnexported bool

	// Packages is the list of packages that are used in the AST.
	Packages []string
}

Result is a result from converting a Go value into its AST.

func AST

func AST(v reflect.Value, opt *Options) (Result, error)

AST converts the given value into its equivalent Go AST expression.

The input must be one of these kinds:

bool
int, int8, int16, int32, int64
uint, uint8, uint16, uint32, uint64
uintptr
float32, float64
complex64, complex128
array
interface
map
ptr
slice
string
struct
unsafe pointer

The input type is reflect.Value instead of interface{}, specifically to allow converting interfaces derived from struct fields or other reflection which would otherwise be lost if the input type is interface{}.

Cyclic data structures will have their cyclic pointer values emitted twice, followed by a nil value. e.g. for a structure `foo` with field `bar` which points to the original `foo`:

&foo{id: 123, bar: &foo{id: 123, bar: nil}}

Directories

Path Synopsis
internal
bypass
Package bypass allows bypassing reflect restrictions on accessing unexported struct fields.
Package bypass allows bypassing reflect restrictions on accessing unexported struct fields.

Jump to

Keyboard shortcuts

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