mapper

package module
v0.0.0-...-849e097 Latest Latest
Warning

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

Go to latest
Published: Sep 22, 2021 License: MIT Imports: 12 Imported by: 0

README

mapper

Generate code that maps struct to struct.

Similar projects:

  • builder: generate builder for private fields
  • getter: generate getters for private struct fields, with inlining

Design thoughts

  • should not include pointer. Mapping requires one struct and returns one struct or error.
  • should not allow context (?). Is there a need to pass context in mapping?
  • Elem refers to the base type, so slice or pointer type User has Elem User

See the examples folder for results.

Basic

Field

The mapper should be able to map type A to type B, given that both types:

  • both must have the same number of fields the target fields can be more than the source fields, and they may reference the same source fields. All target fields must have a corresponding mapping from the source fields, unless they are ignored.
  • both must not be a pointer (it does not make sense for mapping pointer to non-pointer) sql.NullString can be converted to pointer string. As long as there are imported functions that allows the transformation, it should be valid
  • both names must match, and could be altered through alias
  • both types must match. If there is an imported function F, then the param P must match the source S and the result R must match the target T. F(P)->R is F(S)->T
type Mapper interface {
	AtoB (A) B
}

type A struct {
	ID string
}

type B struct {
	ID string
}

Expected:

type MapperImpl struct {}

func (m MapperImpl) AtoB(a A) B {
	return B{
		ID: a.ID
	}
}

Method

When A has a method that maps to the name of B's field, we should be able to use that.

  • if that method returns a tuple error, AtoB should also return a tuple error
  • both names must match
  • both types must match
type Mapper interface {
	AtoB (A) B
}

type A struct {
	id string
}
func (a A) ID() string {
	return a.id
}

type B struct {
	ID string
}

Expected:

type MapperImpl struct {}

func (m MapperImpl) AtoB(a A) B {
	return B{
		ID: a.ID()
	}
}

Error

Nested

Slice and Variadic

Tags

Renaming Field and Methods

Ignore

Func

Interface and Struct

TODO

  • better error handling
  • handle exported and private fields
  • refactor using TDD

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func IsIdentical

func IsIdentical(lhs, rhs types.Type) bool

func IsPointer

func IsPointer(T types.Type) bool

func IsSlice

func IsSlice(T types.Type) bool

func IsStruct

func IsStruct(T types.Type) bool

func IsUnderlyingError

func IsUnderlyingError(T types.Type) bool

func IsUnderlyingIdentical

func IsUnderlyingIdentical(lhs, rhs types.Type) bool

func New

func New(fn Generator) error

func NewInterfaceMethods

func NewInterfaceMethods(T types.Type) map[string]*Func

func NewTypeName

func NewTypeName(T types.Type) *types.TypeName

func NewUnderlyingType

func NewUnderlyingType(T types.Type) types.Type

NewUnderlyingType extracts the underlying type of a Type.

func NormFunc

func NormFunc(name string, fn *types.Func) *types.Func

NormFunc generates a new func with the normalize type - no pointers, slice etc.

func NormFuncFromTypes

func NormFuncFromTypes(name string, param, result types.Type) *types.Func

func UnderlyingSignature

func UnderlyingSignature(T types.Type) string

func UnderlyingString

func UnderlyingString(T types.Type, q types.Qualifier) string

func Walk

func Walk(visitor Visitor, T types.Type) bool

Types

type Func

type Func struct {
	Name string
	// pkg name can be different from package path, e.g. github.com/alextanhongpin/mapper/examples
	// can have package `main` instead of `examples`.
	Obj     *types.TypeName
	Pkg     string
	PkgPath string
	From    *FuncArg
	To      *FuncArg
	Error   bool
	Fn      *types.Func // Store the original

	Norm *Func
	// contains filtered or unexported fields
}

func NewFunc

func NewFunc(fn *types.Func, obj *types.TypeName) *Func

func (*Func) Normalize

func (f *Func) Normalize() *Func

func (*Func) NormalizedName

func (f *Func) NormalizedName() string

func (*Func) RequiresInputPointer

func (f *Func) RequiresInputPointer(in types.Type) bool

RequiresInputPointer returns true if the input needs to be converted into a pointer.

func (*Func) RequiresInputValue

func (f *Func) RequiresInputValue(in types.Type) bool

RequiresInputValue returns true if the input needs to be converted into a value.

func (*Func) Signature

func (f *Func) Signature() string

Signature returns the conversion from A to B without error, pointers, slice etc. func mapAToB(A) B

type FuncArg

type FuncArg struct {
	Name     string
	Type     types.Type
	Obj      *types.TypeName
	Variadic bool
}

func NewFuncArg

func NewFuncArg(name string, T types.Type, variadic bool) *FuncArg

type Generator

type Generator func(opt Option) error

type InterfaceVisitor

type InterfaceVisitor struct {
	// contains filtered or unexported fields
}

func (*InterfaceVisitor) Visit

func (v *InterfaceVisitor) Visit(T types.Type) bool

type NamedVisitor

type NamedVisitor struct {
	// contains filtered or unexported fields
}

func NewNamedVisitor

func NewNamedVisitor(T types.Type) *NamedVisitor

func (NamedVisitor) Methods

func (v NamedVisitor) Methods() map[string]*Func

func (NamedVisitor) Obj

func (v NamedVisitor) Obj() *types.TypeName

func (NamedVisitor) Pkg

func (v NamedVisitor) Pkg() *types.Package

func (*NamedVisitor) Visit

func (v *NamedVisitor) Visit(T types.Type) bool

type Option

type Option struct {
	In      string // The input path, with the file name, e.g. yourpath/yourfile.go
	Out     string // The output path, with the mapper name, e.g. yourpath/yourfile_gen.go
	Pkg     *types.Package
	PkgName string // The pkgName
	PkgPath string // The pkgPath
	Suffix  string
	DryRun  bool
	Prune   bool
	Items   []OptionItem
}

type OptionItem

type OptionItem struct {
	Name string
	Type types.Type
	Path string
}

type StructField

type StructField struct {
	Name string `example:"Name"`
	// Useful when the output directory doesn't match the existing ones.
	Pkg      string // e.g. yourpkg
	PkgPath  string // e.g. github.com/your-org/yourpkg
	Exported bool   // e.g. true
	Tag      *Tag   // e.g. `map:"RenameField,CustomFunction"`
	Ordinal  int    // The original position of the struct field.
	Type     types.Type
}

StructField for the example below.

type Foo struct {
 Name sql.NullString `json:"name"
}

type StructFields

type StructFields map[string]StructField

func NewStructFields

func NewStructFields(T types.Type) StructFields

func (StructFields) WithTags

func (s StructFields) WithTags() StructFields

type StructVisitor

type StructVisitor struct {
	// contains filtered or unexported fields
}

func NewStructVisitor

func NewStructVisitor() *StructVisitor

func (*StructVisitor) Visit

func (v *StructVisitor) Visit(T types.Type) bool

type Tag

type Tag struct {
	Name          string
	FieldOrMethod rune
	// If the pkgPath is not set, we assume it to be the same as the current root directory.
	PkgPath string `example:"github.com/your.org/yourpkg"`
	Pkg     string `example:"yourpkg"`
	// If the `pkg` is not empty, it could most likely be an interface or struct method.
	TypeName string `example:"YourStruct|YourInterface"`
	// If `pkg` is empty, then this is a pure function import.
	Func   string `example:"YourMethod"`
	Tag    string
	Ignore bool
}

func NewTag

func NewTag(tag string) (*Tag, bool)

func (Tag) HasFunc

func (t Tag) HasFunc() bool

func (Tag) IsAlias

func (t Tag) IsAlias() bool

IsAlias returns true if there is a name suggested for mapping.

func (Tag) IsField

func (t Tag) IsField() bool

func (Tag) IsFunc

func (t Tag) IsFunc() bool

func (Tag) IsImported

func (t Tag) IsImported() bool

func (Tag) IsMethod

func (t Tag) IsMethod() bool

func (Tag) Var

func (t Tag) Var() string

type TypeNames

type TypeNames struct {
	// contains filtered or unexported fields
}

func (TypeNames) Items

func (t TypeNames) Items() []string

func (*TypeNames) Set

func (t *TypeNames) Set(val string) error

func (TypeNames) String

func (t TypeNames) String() string

type UnderlyingVisitor

type UnderlyingVisitor struct {
	// contains filtered or unexported fields
}

func NewUnderlyingVisitor

func NewUnderlyingVisitor(T types.Type) *UnderlyingVisitor

func (UnderlyingVisitor) IsArray

func (u UnderlyingVisitor) IsArray() (bool, int64)

func (UnderlyingVisitor) IsPointer

func (u UnderlyingVisitor) IsPointer() bool

func (UnderlyingVisitor) IsSlice

func (u UnderlyingVisitor) IsSlice() bool

func (UnderlyingVisitor) Obj

func (u UnderlyingVisitor) Obj() *types.TypeName

func (UnderlyingVisitor) Pkg

func (u UnderlyingVisitor) Pkg() *types.Package

func (UnderlyingVisitor) Type

func (u UnderlyingVisitor) Type() types.Type

func (UnderlyingVisitor) Underlying

func (u UnderlyingVisitor) Underlying() types.Type

func (*UnderlyingVisitor) Visit

func (v *UnderlyingVisitor) Visit(T types.Type) bool

type Visitor

type Visitor interface {
	Visit(T types.Type) bool
}

Directories

Path Synopsis
cmd
rename-field
rename demonstrates how to use the `map` tag to customize the name for the mapper.
rename demonstrates how to use the `map` tag to customize the name for the mapper.
rename-method
rename demonstrates how to use the `map` tag to customize the name for the mapper.
rename demonstrates how to use the `map` tag to customize the name for the mapper.

Jump to

Keyboard shortcuts

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