Skip to content
This repository has been archived by the owner on Jun 19, 2024. It is now read-only.

Commit

Permalink
Handles fields with pointers (#5)
Browse files Browse the repository at this point in the history
* Upgraded dependencies to their latest versions

* Indicate whether the field is a pointer to an array type

* Appends '&' to generated code for pointer references
  • Loading branch information
tiagoangelototvs authored Jun 23, 2023
1 parent e063204 commit 463ab2e
Show file tree
Hide file tree
Showing 8 changed files with 112 additions and 84 deletions.
10 changes: 5 additions & 5 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ require (
github.com/go-ozzo/ozzo-validation/v4 v4.3.0
github.com/gookit/color v1.5.3
github.com/ku/go-change-case v0.0.1
github.com/lmittmann/tint v0.3.2
github.com/lmittmann/tint v0.3.4
github.com/pkg/errors v0.9.1
github.com/samber/lo v1.38.1
github.com/spf13/cobra v1.7.0
github.com/stretchr/testify v1.8.2
github.com/stretchr/testify v1.8.4
github.com/wk8/go-ordered-map/v2 v2.1.7
golang.org/x/exp v0.0.0-20230425010034-47ecfdc1ba53
golang.org/x/mod v0.10.0
golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1
golang.org/x/mod v0.11.0
)

require (
Expand All @@ -27,6 +27,6 @@ require (
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
golang.org/x/sys v0.8.0 // indirect
golang.org/x/sys v0.9.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
25 changes: 10 additions & 15 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLf
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/ku/go-change-case v0.0.1 h1:Dym6yulm/ma+XRgH1SG2CIOLk2biWpSFf6mMPtg3ic8=
github.com/ku/go-change-case v0.0.1/go.mod h1:7rNOPNKPrCdjm8+iDIKgs87tZuyPJkhnStQZIOT3Pss=
github.com/lmittmann/tint v0.3.2 h1:PU2S17rAGhz5mo5shxnybv6Vwz7E08/RlOeWrwabuyg=
github.com/lmittmann/tint v0.3.2/go.mod h1:w5kXnXdS9aMMlo2eFRTyEPrSRywqAi44wbSUxIBfd38=
github.com/lmittmann/tint v0.3.4 h1:QOr2U9GKQfNsNhKPhL7PexQm0mqkRmvuy1UrZb6AidM=
github.com/lmittmann/tint v0.3.4/go.mod h1:vYasuAV5qbz2TYeUK+sj8iURGIl9T/WOlh4qzYGP16I=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
Expand All @@ -37,26 +37,21 @@ github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRM
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/wk8/go-ordered-map/v2 v2.1.7 h1:aUZ1xBMdbvY8wnNt77qqo4nyT3y0pX4Usat48Vm+hik=
github.com/wk8/go-ordered-map/v2 v2.1.7/go.mod h1:9Xvgm2mV2kSq2SAm0Y608tBmu8akTzI7c2bz7/G7ZN4=
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no=
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM=
golang.org/x/exp v0.0.0-20230425010034-47ecfdc1ba53 h1:5llv2sWeaMSnA3w2kS57ouQQ4pudlXrR0dCgw51QK9o=
golang.org/x/exp v0.0.0-20230425010034-47ecfdc1ba53/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w=
golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk=
golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 h1:k/i9J1pBpvlfR+9QsetwPyERsqu1GIbi967PQMq3Ivc=
golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w=
golang.org/x/mod v0.11.0 h1:bUO06HqtnRcc/7l71XBe4WcqTZ+3AH1J59zWDDwLKgU=
golang.org/x/mod v0.11.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s=
golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
13 changes: 11 additions & 2 deletions internal/code/calls.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,16 +157,25 @@ func (g *PointerGetterCall) Statement() *jen.Statement {

switch KindOf(g.Field) {
case FieldKindNative:
var assigment1, assigment2 *jen.Statement
if !g.Field.Pointer {
assigment1 = jen.Id(fieldName).Op(":").Id(flagValue)
assigment2 = jen.Id(structName).Dot(fieldName).Op("=").Id(flagValue)
} else {
assigment1 = jen.Id(fieldName).Op(":").Op("&").Id(flagValue)
assigment2 = jen.Id(structName).Dot(fieldName).Op("=").Op("&").Id(flagValue)
}

return jen.If(jen.List(jen.Id(flagValue), jen.Err()).Op(":=").
Id("cf").Dot("flags").Dot(g.CobraMethod()).Call(jen.Lit(g.Flag())), jen.Err().Op("!=").Nil()).
Block(
jen.Return().List(returnId, jen.Qual("fmt", "Errorf").Call(jen.Lit("error retrieving \""+g.Flag()+"\" from command flags: %w"), jen.Err())),
).Else().If(g.CompareToDefaultValue(jen.Id(flagValue).Op("!=")).Op("&&").Id(structName).Op("==").Nil()).
Block(
jen.Id(structName).Op("=").Op("&").Qual(g.Struct.Package.Path, g.Struct.Name).Values(jen.Id(fieldName).Op(":").Id(flagValue)),
jen.Id(structName).Op("=").Op("&").Qual(g.Struct.Package.Path, g.Struct.Name).Values(assigment1),
).Else().If(g.CompareToDefaultValue(jen.Id(flagValue).Op("!="))).
Block(
jen.Id(structName).Dot(fieldName).Op("=").Id(flagValue),
assigment2,
)
case FieldKindStruct, FieldKindTCloudTag, FieldKindStringMap:
if g.Field.Pointer {
Expand Down
2 changes: 2 additions & 0 deletions internal/code/generator.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"path"

changecase "github.com/ku/go-change-case"

"github.com/totvs-cloud/pflagstruct/internal/dir"
"github.com/totvs-cloud/pflagstruct/projscan"
)
Expand Down Expand Up @@ -71,6 +72,7 @@ func (g *Generator) Generate(directory string, structName string, destination st
Prefix: prefix,
Struct: field.StructRef,
Pointer: field.Pointer,
ArrayPointer: field.ArrayPointer,
})
case FieldKindStringMap:
getterMethods = append(getterMethods, &MapGetterMethod{
Expand Down
21 changes: 16 additions & 5 deletions internal/code/methods.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ type TagsGetterMethod struct {
Prefix string
Struct *projscan.Struct
Pointer bool
ArrayPointer bool
}

func (t *TagsGetterMethod) MethodName() string {
Expand Down Expand Up @@ -149,10 +150,6 @@ func (t *TagsGetterMethod) Flag() string {

func (t *TagsGetterMethod) Statement() *jen.Statement {
receiver := jen.Id("cf").Op("*").Id(t.FlagsBuilderName)
returns := []jen.Code{
jen.Index().Op("*").Qual(t.Struct.Package.Path, t.Struct.Name),
jen.Error(),
}

calls := []jen.Code{
jen.List(jen.Id("tagStrList"), jen.Id("err")).Op(":=").Id("cf").Dot("flags").Dot("GetStringSlice").Call(jen.Lit(t.Flag())),
Expand All @@ -167,7 +164,21 @@ func (t *TagsGetterMethod) Statement() *jen.Statement {
t.ResultAssignment().Values(jen.Id("Name").Op(":").Id("parts").Index(jen.Lit(0)), jen.Id("Value").Op(":").Id("parts").Index(jen.Lit(1))))),
}

calls = append(calls, jen.Return().List(jen.Id("resultingTags"), jen.Nil()))
var returns []jen.Code
if !t.ArrayPointer {
returns = []jen.Code{
jen.Index().Op("*").Qual(t.Struct.Package.Path, t.Struct.Name),
jen.Error(),
}

calls = append(calls, jen.Return().List(jen.Id("resultingTags"), jen.Nil()))
} else {
returns = []jen.Code{
jen.Op("*").Index().Op("*").Qual(t.Struct.Package.Path, t.Struct.Name),
jen.Error(),
}
calls = append(calls, jen.Return().List(jen.Op("&").Id("resultingTags"), jen.Nil()))
}

return jen.Func().Params(receiver).Id(t.MethodName()).Params().Params(returns...).Block(calls...)
}
Expand Down
105 changes: 57 additions & 48 deletions internal/scan/fld/finder.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"strings"

"github.com/pkg/errors"

"github.com/totvs-cloud/pflagstruct/internal/syntree"
"github.com/totvs-cloud/pflagstruct/projscan"
)
Expand Down Expand Up @@ -62,33 +63,36 @@ func (f *Finder) buildField(expr ast.Expr, st *projscan.Struct, proj *projscan.P
case *ast.StarExpr:
// it means that the field type is a pointer
return f.buildField(x.X, st, proj, &projscan.Field{
Name: field.Name,
Type: field.Type,
Doc: field.Doc,
StructRef: field.StructRef,
Pointer: true,
Array: field.Array,
Name: field.Name,
Type: field.Type,
Doc: field.Doc,
StructRef: field.StructRef,
Pointer: true,
Array: field.Array,
ArrayPointer: field.ArrayPointer,
})
case *ast.ArrayType:
// it means that the field type is an array
return f.buildField(x.Elt, st, proj, &projscan.Field{
Name: field.Name,
Type: field.Type,
Doc: field.Doc,
StructRef: field.StructRef,
Pointer: field.Pointer,
Array: true,
Name: field.Name,
Type: field.Type,
Doc: field.Doc,
StructRef: field.StructRef,
Pointer: false,
Array: true,
ArrayPointer: field.Pointer,
})
case *ast.Ident:
// it means that the field type is either a built-in type or a struct from the same package
if projscan.FieldType(x.Name).IsValid() {
return &projscan.Field{
Name: field.Name,
Type: projscan.FieldType(x.Name),
Doc: field.Doc,
StructRef: field.StructRef,
Pointer: field.Pointer,
Array: field.Array,
Name: field.Name,
Type: projscan.FieldType(x.Name),
Doc: field.Doc,
StructRef: field.StructRef,
Pointer: field.Pointer,
Array: field.Array,
ArrayPointer: field.ArrayPointer,
}, nil
}

Expand All @@ -98,12 +102,13 @@ func (f *Finder) buildField(expr ast.Expr, st *projscan.Struct, proj *projscan.P
}

return &projscan.Field{
Name: field.Name,
Type: projscan.FieldType(x.Name),
Doc: field.Doc,
StructRef: structRef,
Pointer: field.Pointer,
Array: field.Array,
Name: field.Name,
Type: projscan.FieldType(x.Name),
Doc: field.Doc,
StructRef: structRef,
Pointer: field.Pointer,
Array: field.Array,
ArrayPointer: field.ArrayPointer,
}, nil
case *ast.SelectorExpr:
// it means that the field type is a struct from another package
Expand All @@ -124,47 +129,51 @@ func (f *Finder) buildField(expr ast.Expr, st *projscan.Struct, proj *projscan.P
}

return &projscan.Field{
Name: field.Name,
Type: projscan.FieldType(fmt.Sprintf("%s.%s", pkg.Name, x.Sel.Name)),
Doc: field.Doc,
StructRef: structRef,
Pointer: field.Pointer,
Array: field.Array,
Name: field.Name,
Type: projscan.FieldType(fmt.Sprintf("%s.%s", pkg.Name, x.Sel.Name)),
Doc: field.Doc,
StructRef: structRef,
Pointer: field.Pointer,
Array: field.Array,
ArrayPointer: field.ArrayPointer,
}, nil
}
case *ast.MapType:
// it means that the field type is a map
key, err := f.buildField(x.Key, st, proj, &projscan.Field{
Name: field.Name,
Type: "",
Doc: field.Doc,
StructRef: nil,
Pointer: false,
Array: false,
Name: field.Name,
Type: "",
Doc: field.Doc,
StructRef: nil,
Pointer: false,
Array: false,
ArrayPointer: false,
})
if err != nil {
return nil, err
}

value, err := f.buildField(x.Value, st, proj, &projscan.Field{
Name: field.Name,
Type: "",
Doc: field.Doc,
StructRef: nil,
Pointer: false,
Array: false,
Name: field.Name,
Type: "",
Doc: field.Doc,
StructRef: nil,
Pointer: false,
Array: false,
ArrayPointer: false,
})
if err != nil {
return nil, err
}

return &projscan.Field{
Name: field.Name,
Type: projscan.FieldType(fmt.Sprintf("map[%s]%s", key.Type, value.Type)),
Doc: field.Doc,
StructRef: field.StructRef,
Pointer: field.Pointer,
Array: field.Array,
Name: field.Name,
Type: projscan.FieldType(fmt.Sprintf("map[%s]%s", key.Type, value.Type)),
Doc: field.Doc,
StructRef: field.StructRef,
Pointer: field.Pointer,
Array: field.Array,
ArrayPointer: field.ArrayPointer,
}, nil
}

Expand Down
7 changes: 4 additions & 3 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,14 @@ import (
"github.com/lmittmann/tint"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"golang.org/x/exp/slog"

"github.com/totvs-cloud/pflagstruct/internal/code"
scanfld "github.com/totvs-cloud/pflagstruct/internal/scan/fld"
scanpkg "github.com/totvs-cloud/pflagstruct/internal/scan/pkg"
scanproj "github.com/totvs-cloud/pflagstruct/internal/scan/proj"
scanst "github.com/totvs-cloud/pflagstruct/internal/scan/st"
"github.com/totvs-cloud/pflagstruct/internal/syntree"
"golang.org/x/exp/slog"
)

var (
Expand Down Expand Up @@ -107,13 +108,13 @@ func fatal(err error) {
}

func main() {
options := tint.Options{TimeFormat: time.Kitchen}
options := &tint.Options{TimeFormat: time.Kitchen}
if debug {
options.AddSource = true
options.Level = slog.LevelDebug
}

slog.SetDefault(slog.New(options.NewHandler(os.Stderr)))
slog.SetDefault(slog.New(tint.NewHandler(os.Stderr, options)))

cmd, err := NewCommand()
if err != nil {
Expand Down
13 changes: 7 additions & 6 deletions projscan/field.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,13 @@ import (

// Field represents a field of a struct.
type Field struct {
Name string // Name of the field
Type FieldType // Type of the field
Doc string // Documentation for the field
StructRef *Struct // Reference to the struct that contains this field
Pointer bool // Indicates whether the field is a pointer type or not
Array bool // Indicates whether the field is an array type or not
Name string // Name of the field
Type FieldType // Type of the field
Doc string // Documentation for the field
StructRef *Struct // Reference to the struct that contains this field
Pointer bool // Indicates whether the field is a pointer type or not
Array bool // Indicates whether the field is an array type or not
ArrayPointer bool // Indicates whether the field is a pointer to an array type or not
}

// FieldType defines the available field types in Go
Expand Down

0 comments on commit 463ab2e

Please sign in to comment.