Skip to content

Commit

Permalink
feat: copy slice
Browse files Browse the repository at this point in the history
  • Loading branch information
reedom committed Oct 10, 2022
1 parent b193240 commit 174d64b
Show file tree
Hide file tree
Showing 6 changed files with 136 additions and 0 deletions.
35 changes: 35 additions & 0 deletions pkg/builder/assignment.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,14 @@ func (b *assignmentBuilder) structFieldAndStructGettersAndFields(lhs bmodel.Node
return
}

if util.IsSliceType(lhs.ExprType()) && util.IsSliceType(rhs.ExprType()) {
a, err = b.sliceToSlice(lhs, rhs)
if a != nil || err != nil {
logger.Printf("%v: assignment found: sliceCopy(%v, %v)", methodPosStr, lhsExpr, rhs.AssignExpr())
return true
}
}

if c, ok := b.castNode(lhs.ExprType(), rhs); ok {
rhsExpr := c.AssignExpr()
logger.Printf("%v: assignment found: %v = %v", methodPosStr, lhsExpr, rhsExpr)
Expand Down Expand Up @@ -333,3 +341,30 @@ func (b *assignmentBuilder) resolveExpr(matcher *option.IdentMatcher, root bmode
}
return
}

func (b *assignmentBuilder) sliceToSlice(lhs, rhs bmodel.Node) (a gmodel.Assignment, err error) {
lhsElem := util.SliceElement(lhs.ExprType())
rhsElem := util.SliceElement(rhs.ExprType())
if lhsElem == nil || rhsElem == nil {
return
}

if types.AssignableTo(rhsElem, lhsElem) {
if util.IsBasicType(rhsElem) {
a = gmodel.SliceAssignment{
LHS: lhs.AssignExpr(),
RHS: rhs.AssignExpr(),
Typ: "[]" + lhsElem.String(),
}
} else {
a = gmodel.SliceLoopAssignment{
LHS: lhs.AssignExpr(),
RHS: rhs.AssignExpr(),
Typ: "[]" + b.imports.TypeName(lhsElem),
}
}
return
}

return
}
28 changes: 28 additions & 0 deletions pkg/generator/model/assignment.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,3 +124,31 @@ func (c SliceAssignment) String() string {
func (c SliceAssignment) RetError() bool {
return false
}

type SliceLoopAssignment struct {
LHS string
RHS string
Typ string
}

func (c SliceLoopAssignment) String() string {
var sb strings.Builder
sb.WriteString("if ")
sb.WriteString(c.RHS)
sb.WriteString(" != nil {\n")
sb.WriteString(c.LHS)
sb.WriteString(" = make(")
sb.WriteString(c.Typ)
sb.WriteString(", len(")
sb.WriteString(c.RHS)
sb.WriteString("))\nfor i, e := range ")
sb.WriteString(c.RHS)
sb.WriteString("{\n")
sb.WriteString(c.LHS)
sb.WriteString("[i] = e\n}\n}\n")
return sb.String()
}

func (c SliceLoopAssignment) RetError() bool {
return false
}
17 changes: 17 additions & 0 deletions pkg/util/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,16 @@ func IsInvalidType(t types.Type) bool {
return false
}

func IsSliceType(t types.Type) bool {
_, ok := t.(*types.Slice)
return ok
}

func IsBasicType(t types.Type) bool {
_, ok := t.(*types.Basic)
return ok
}

func IsStructType(t types.Type) bool {
_, ok := t.Underlying().(*types.Struct)
return ok
Expand Down Expand Up @@ -79,6 +89,13 @@ func Deref(typ types.Type) (types.Type, bool) {
return typ, false
}

func SliceElement(t types.Type) types.Type {
if slice, ok := t.(*types.Slice); ok {
return slice.Elem()
}
return nil
}

func RemoveObject(file *ast.File, obj types.Object) {
nodes, _ := ToAstNode(file, obj)
for _, node := range nodes {
Expand Down
32 changes: 32 additions & 0 deletions tests/fixtures/usecase/slice/setup.gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 20 additions & 0 deletions tests/fixtures/usecase/slice/setup.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//go:build convergen

package slice

type SrcType struct {
IntSlice []int
DataSlice []Data
}

type DstType struct {
IntSlice []int
DataSlice []Data
}

type Data struct{}

//go:generate go run github.com/reedom/convergen
type Convergen interface {
Copy(*SrcType) *DstType
}
4 changes: 4 additions & 0 deletions tests/usecases_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ func TestUseCases(t *testing.T) {
source: "fixtures/usecase/simple/setup.go",
expected: "fixtures/usecase/simple/setup.gen.go",
},
{
source: "fixtures/usecase/slice/setup.go",
expected: "fixtures/usecase/slice/setup.gen.go",
},
{
source: "fixtures/usecase/stringer/setup.go",
expected: "fixtures/usecase/stringer/setup.gen.go",
Expand Down

0 comments on commit 174d64b

Please sign in to comment.