Skip to content

Commit

Permalink
wip1
Browse files Browse the repository at this point in the history
  • Loading branch information
jmattheis committed Jun 11, 2024
1 parent ae1b2c8 commit 8655b4a
Show file tree
Hide file tree
Showing 38 changed files with 321 additions and 153 deletions.
8 changes: 8 additions & 0 deletions builder/basic.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ func (*Basic) Build(_ Generator, _ *MethodContext, sourceID *xtype.JenID, source
return nil, sourceID, nil
}

func (b *Basic) Assign(gen Generator, ctx *MethodContext, assignTo *jen.Statement, sourceID *xtype.JenID, source, target *xtype.Type, errPath ErrorPath) ([]jen.Code, *Error) {
return ToAssignable(assignTo)(b.Build(gen, ctx, sourceID, source, target, errPath))
}

// BasicTargetPointerRule handles edge conditions if the target type is a pointer.
type BasicTargetPointerRule struct{}

Expand Down Expand Up @@ -49,3 +53,7 @@ func (*BasicTargetPointerRule) Build(gen Generator, ctx *MethodContext, sourceID

return stmt, xtype.OtherID(newID), err
}

func (b *BasicTargetPointerRule) Assign(gen Generator, ctx *MethodContext, assignTo *jen.Statement, sourceID *xtype.JenID, source, target *xtype.Type, errPath ErrorPath) ([]jen.Code, *Error) {
return ToAssignable(assignTo)(b.Build(gen, ctx, sourceID, source, target, errPath))
}
23 changes: 23 additions & 0 deletions builder/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,13 @@ type Builder interface {
sourceID *xtype.JenID,
source, target *xtype.Type,
path ErrorPath) ([]jen.Code, *xtype.JenID, *Error)

Assign(gen Generator,
ctx *MethodContext,
assignTo *jen.Statement,
sourceID *xtype.JenID,
source, target *xtype.Type,
path ErrorPath) ([]jen.Code, *Error)
}

// Generator checks all existing builders if they can create a conversion implementations for the given source and target type
Expand All @@ -31,6 +38,12 @@ type Generator interface {
source, target *xtype.Type,
path ErrorPath) ([]jen.Code, *xtype.JenID, *Error)

Assign(ctx *MethodContext,
assignTo *jen.Statement,
sourceID *xtype.JenID,
source, target *xtype.Type,
path ErrorPath) ([]jen.Code, *Error)

CallMethod(
ctx *MethodContext,
method *method.Definition,
Expand All @@ -43,6 +56,16 @@ type Generator interface {
id *jen.Statement) (jen.Code, bool)
}

func ToAssignable(assignTo *jen.Statement) func(stmt []jen.Code, nextID *xtype.JenID, err *Error) ([]jen.Code, *Error) {
return func(stmt []jen.Code, nextID *xtype.JenID, err *Error) ([]jen.Code, *Error) {
if err != nil {
return nil, err
}
stmt = append(stmt, assignTo.Clone().Op("=").Add(nextID.Code))
return stmt, nil
}
}

// MethodContext exposes information for the current method.
type MethodContext struct {
*namer.Namer
Expand Down
27 changes: 27 additions & 0 deletions builder/default.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,30 @@ func buildTargetVar(gen Generator, ctx *MethodContext, sourceID *xtype.JenID, so
ctx.SetErrorTargetVar(jen.Id(name))
return stmt, jen.Id(name), nil
}

func assignTargetVar(gen Generator, ctx *MethodContext, assignTo *jen.Statement, sourceID *xtype.JenID, source, target *xtype.Type, errPath ErrorPath) ([]jen.Code, *Error) {
if ctx.Conf.Constructor == nil ||
ctx.Conf.Source.String != source.String ||
ctx.Conf.Target.String != target.String {
return []jen.Code{}, nil
}

callTarget := target
toPointer := target.Pointer && !ctx.Conf.Constructor.Target.Pointer
if toPointer {
callTarget = target.PointerInner
}

stmt, nextID, err := gen.CallMethod(ctx, ctx.Conf.Constructor, sourceID, source, callTarget, errPath)
if err != nil {
return nil, err
}

if toPointer {
pstmt, pointerID := nextID.Pointer(callTarget, ctx.Name)
stmt = append(stmt, pstmt...)
nextID = pointerID
}

return []jen.Code{assignTo.Clone().Op("=").Add(nextID.Code)}, nil
}
4 changes: 4 additions & 0 deletions builder/enum.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,10 @@ func (*Enum) Build(gen Generator, ctx *MethodContext, sourceID *xtype.JenID, sou
return stmt, xtype.VariableID(nameVar), nil
}

func (s *Enum) Assign(gen Generator, ctx *MethodContext, assignTo *jen.Statement, sourceID *xtype.JenID, source, target *xtype.Type, path ErrorPath) ([]jen.Code, *Error) {
return ToAssignable(assignTo)(s.Build(gen, ctx, sourceID, source, target, path))
}

func caseAction(gen Generator, ctx *MethodContext, nameVar *jen.Statement, target *xtype.Type, targetEnum *xtype.Enum, targetName string, sourceID *xtype.JenID, errPath ErrorPath) (jen.Code, *Error) {
if config.IsEnumAction(targetName) {
switch targetName {
Expand Down
30 changes: 29 additions & 1 deletion builder/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ func (*List) Matches(_ *MethodContext, source, target *xtype.Type) bool {
}

// Build creates conversion source code for the given source and target type.
func (*List) Build(gen Generator, ctx *MethodContext, sourceID *xtype.JenID, source, target *xtype.Type, path ErrorPath) ([]jen.Code, *xtype.JenID, *Error) {
func (l *List) Build(gen Generator, ctx *MethodContext, sourceID *xtype.JenID, source, target *xtype.Type, path ErrorPath) ([]jen.Code, *xtype.JenID, *Error) {
ctx.SetErrorTargetVar(jen.Nil())
targetSlice := ctx.Name(target.ID())
index := ctx.Index()
Expand Down Expand Up @@ -52,3 +52,31 @@ func (*List) Build(gen Generator, ctx *MethodContext, sourceID *xtype.JenID, sou

return stmt, xtype.VariableID(jen.Id(targetSlice)), nil
}

Check failure on line 54 in builder/list.go

View workflow job for this annotation

GitHub Actions / lint

File is not `gofumpt`-ed with `-extra` (gofumpt)
func (*List) Assign(gen Generator, ctx *MethodContext, assignTo *jen.Statement, sourceID *xtype.JenID, source, target *xtype.Type, path ErrorPath) ([]jen.Code, *Error) {
ctx.SetErrorTargetVar(jen.Nil())
index := ctx.Index()

indexedSource := xtype.VariableID(sourceID.Code.Clone().Index(jen.Id(index)))

forBlock, err := gen.Assign(ctx, assignTo.Clone().Index(jen.Id(index)), indexedSource, source.ListInner, target.ListInner, path.Index(jen.Id(index)))
if err != nil {
return nil, err.Lift(&Path{
SourceID: "[]",
SourceType: source.ListInner.String,
TargetID: "[]",
TargetType: target.ListInner.String,
})
}
forStmt := jen.For(jen.Id(index).Op(":=").Lit(0), jen.Id(index).Op("<").Len(sourceID.Code.Clone()), jen.Id(index).Op("++")).
Block(forBlock...)

if source.ListFixed {
return []jen.Code{forStmt}, nil
}
return []jen.Code{
jen.If(sourceID.Code.Clone().Op("!=").Nil()).Block(
assignTo.Clone().Op("=").Make(target.TypeAsJen(), jen.Len(sourceID.Code.Clone())),
forStmt,
),
}, nil
}
30 changes: 20 additions & 10 deletions builder/map.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,43 +14,53 @@ func (*Map) Matches(_ *MethodContext, source, target *xtype.Type) bool {
}

// Build creates conversion source code for the given source and target type.
func (*Map) Build(gen Generator, ctx *MethodContext, sourceID *xtype.JenID, source, target *xtype.Type, errPath ErrorPath) ([]jen.Code, *xtype.JenID, *Error) {
func (m *Map) Build(gen Generator, ctx *MethodContext, sourceID *xtype.JenID, source, target *xtype.Type, errPath ErrorPath) ([]jen.Code, *xtype.JenID, *Error) {
ctx.SetErrorTargetVar(jen.Nil())
targetMap := ctx.Name(target.ID())

stmt, err := m.Assign(gen, ctx, jen.Id(targetMap), sourceID, source, target, errPath)
if err != nil {
return nil, nil, err
}

stmt = append([]jen.Code{jen.Var().Add(jen.Id(targetMap), target.TypeAsJen())}, stmt...)
return stmt, xtype.VariableID(jen.Id(targetMap)), nil
}

func (*Map) Assign(gen Generator, ctx *MethodContext, assignTo *jen.Statement, sourceID *xtype.JenID, source, target *xtype.Type, errPath ErrorPath) ([]jen.Code, *Error) {
ctx.SetErrorTargetVar(jen.Nil())
key, value := ctx.Map()

errPath = errPath.Key(jen.Id(key))

block, newKey, err := gen.Build(ctx, xtype.VariableID(jen.Id(key)), source.MapKey, target.MapKey, errPath)
block, keyID, err := gen.Build(ctx, xtype.VariableID(jen.Id(key)), source.MapKey, target.MapKey, errPath)
if err != nil {
return nil, nil, err.Lift(&Path{
return nil, err.Lift(&Path{
SourceID: "[]",
SourceType: "<mapkey> " + source.MapKey.String,
TargetID: "[]",
TargetType: "<mapkey> " + target.MapKey.String,
})
}
valueStmt, valueKey, err := gen.Build(
ctx, xtype.VariableID(jen.Id(value)), source.MapValue, target.MapValue, errPath)
valueStmt, err := gen.Assign(
ctx, assignTo.Clone().Index(keyID.Code), xtype.VariableID(jen.Id(value)), source.MapValue, target.MapValue, errPath)
if err != nil {
return nil, nil, err.Lift(&Path{
return nil, err.Lift(&Path{
SourceID: "[]",
SourceType: "<mapvalue> " + source.MapValue.String,
TargetID: "[]",
TargetType: "<mapvalue> " + target.MapValue.String,
})
}
block = append(block, valueStmt...)
block = append(block, jen.Id(targetMap).Index(newKey.Code).Op("=").Add(valueKey.Code))

stmt := []jen.Code{
jen.Var().Add(jen.Id(targetMap), target.TypeAsJen()),
jen.If(sourceID.Code.Clone().Op("!=").Nil()).Block(
jen.Id(targetMap).Op("=").Make(target.TypeAsJen(), jen.Len(sourceID.Code.Clone())),
assignTo.Clone().Op("=").Make(target.TypeAsJen(), jen.Len(sourceID.Code.Clone())),
jen.For(jen.List(jen.Id(key), jen.Id(value)).Op(":=").Range().Add(sourceID.Code)).
Block(block...),
),
}

return stmt, xtype.VariableID(jen.Id(targetMap)), nil
return stmt, nil
}
87 changes: 87 additions & 0 deletions builder/pointer.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,44 @@ func (*Pointer) Build(gen Generator, ctx *MethodContext, sourceID *xtype.JenID,
return stmt, xtype.VariableID(outerVar), err
}

func (*Pointer) Assign(gen Generator, ctx *MethodContext, assignTo *jen.Statement, sourceID *xtype.JenID, source, target *xtype.Type, errPath ErrorPath) ([]jen.Code, *Error) {
ctx.SetErrorTargetVar(jen.Nil())

stmt, err := assignTargetVar(gen, ctx, assignTo, sourceID, source, target, errPath)
if err != nil {
return nil, err
}

valueSourceID := jen.Op("*").Add(sourceID.Code.Clone())
if !source.PointerInner.Basic {
valueSourceID = jen.Parens(valueSourceID)
}

innerID := xtype.OtherID(valueSourceID)
innerID.ParentPointer = sourceID
nextBlock, id, err := gen.Build(
ctx, innerID, source.PointerInner, target.PointerInner, errPath)
if err != nil {
return nil, err.Lift(&Path{
SourceID: "*",
SourceType: source.PointerInner.String,
TargetID: "*",
TargetType: target.PointerInner.String,
})
}

pstmt, tmpID := id.Pointer(target.PointerInner, ctx.Name)

ifBlock := append(nextBlock, pstmt...)
ifBlock = append(ifBlock, assignTo.Clone().Op("=").Add(tmpID.Code))

stmt = append(stmt,
jen.If(sourceID.Code.Clone().Op("!=").Nil()).Block(ifBlock...),
)

return stmt, err
}

// SourcePointer handles type were only the source is a pointer.
type SourcePointer struct{}

Expand Down Expand Up @@ -94,6 +132,37 @@ func (*SourcePointer) Build(gen Generator, ctx *MethodContext, sourceID *xtype.J
return stmt, xtype.VariableID(valueVar), nil
}

func (*SourcePointer) Assign(gen Generator, ctx *MethodContext, assignTo *jen.Statement, sourceID *xtype.JenID, source, target *xtype.Type, path ErrorPath) ([]jen.Code, *Error) {
valueSourceID := jen.Op("*").Add(sourceID.Code.Clone())
if !source.PointerInner.Basic {
valueSourceID = jen.Parens(valueSourceID)
}

innerID := xtype.OtherID(valueSourceID)
innerID.ParentPointer = sourceID

stmt, err := assignTargetVar(gen, ctx, assignTo, sourceID, source, target, path)
if err != nil {
return nil, err
}

nextInner, nextID, err := gen.Build(ctx, innerID, source.PointerInner, target, path)
if err != nil {
return nil, err.Lift(&Path{
SourceID: "*",
SourceType: source.PointerInner.String,
})
}

stmt = append(stmt,
jen.If(sourceID.Code.Clone().Op("!=").Nil()).Block(
append(nextInner, assignTo.Clone().Op("=").Add(nextID.Code))...,
),
)

return stmt, nil
}

// TargetPointer handles type were only the target is a pointer.
type TargetPointer struct{}

Expand All @@ -119,3 +188,21 @@ func (*TargetPointer) Build(gen Generator, ctx *MethodContext, sourceID *xtype.J
stmt = append(stmt, pstmt...)
return stmt, nextID, nil
}

func (*TargetPointer) Assign(gen Generator, ctx *MethodContext, assignTo *jen.Statement, sourceID *xtype.JenID, source, target *xtype.Type, path ErrorPath) ([]jen.Code, *Error) {
ctx.SetErrorTargetVar(jen.Nil())
stmt, id, err := gen.Build(ctx, sourceID, source, target.PointerInner, path)
if err != nil {
return nil, err.Lift(&Path{
SourceID: "*",
SourceType: source.String,
TargetID: "*",
TargetType: target.PointerInner.String,
})
}

pstmt, nextID := id.Pointer(target.PointerInner, ctx.Name)
stmt = append(stmt, pstmt...)
stmt = append(stmt, assignTo.Clone().Op("=").Add(nextID.Code))
return stmt, nil
}
4 changes: 4 additions & 0 deletions builder/skipcopy.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,7 @@ func (*SkipCopy) Matches(ctx *MethodContext, source, target *xtype.Type) bool {
func (*SkipCopy) Build(_ Generator, _ *MethodContext, sourceID *xtype.JenID, _, _ *xtype.Type, _ ErrorPath) ([]jen.Code, *xtype.JenID, *Error) {
return nil, sourceID, nil
}

func (*SkipCopy) Assign(_ Generator, _ *MethodContext, assignTo *jen.Statement, sourceID *xtype.JenID, _, _ *xtype.Type, _ ErrorPath) ([]jen.Code, *Error) {
return []jen.Code{assignTo.Clone().Op("=").Add(sourceID.Code)}, nil
}
7 changes: 5 additions & 2 deletions builder/struct.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,12 +74,11 @@ func (*Struct) Build(gen Generator, ctx *MethodContext, sourceID *xtype.JenID, s
}
stmt = append(stmt, mapStmt...)

fieldStmt, fieldID, err := gen.Build(ctx, nextID, nextSource, targetFieldType, targetFieldPath)
fieldStmt, err := gen.Assign(ctx, nameVar.Clone().Dot(targetField.Name()), nextID, nextSource, targetFieldType, targetFieldPath)
if err != nil {
return nil, nil, err.Lift(lift...)
}
stmt = append(stmt, fieldStmt...)
stmt = append(stmt, nameVar.Clone().Dot(targetField.Name()).Op("=").Add(fieldID.Code))
} else {
def := fieldMapping.Function

Expand Down Expand Up @@ -134,6 +133,10 @@ func (*Struct) Build(gen Generator, ctx *MethodContext, sourceID *xtype.JenID, s
return stmt, xtype.VariableID(nameVar), nil
}

func (s *Struct) Assign(gen Generator, ctx *MethodContext, assignTo *jen.Statement, sourceID *xtype.JenID, source, target *xtype.Type, path ErrorPath) ([]jen.Code, *Error) {
return ToAssignable(assignTo)(s.Build(gen, ctx, sourceID, source, target, path))
}

func mapField(
gen Generator,
ctx *MethodContext,
Expand Down
4 changes: 4 additions & 0 deletions builder/underlying.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@ You have to disable enum or useUnderlyingTypeMethods to resolve the setting conf
return stmt, id, err
}

func (u *UseUnderlyingTypeMethods) Assign(gen Generator, ctx *MethodContext, assignTo *jen.Statement, sourceID *xtype.JenID, source, target *xtype.Type, errPath ErrorPath) ([]jen.Code, *Error) {
return ToAssignable(assignTo)(u.Build(gen, ctx, sourceID, source, target, errPath))
}

func findUnderlyingExtendMapping(ctx *MethodContext, source, target *xtype.Type) (underlyingSource, underlyingTarget bool) {
if source.Named {
if ctx.HasMethod(source.NamedType.Underlying(), target.NamedType) {
Expand Down
Loading

0 comments on commit 8655b4a

Please sign in to comment.