From 6d15cc6d2bf4445c94bc5af029ca6893ffc649c4 Mon Sep 17 00:00:00 2001 From: Ivan Vlasic Date: Thu, 2 Dec 2021 14:33:55 +0100 Subject: [PATCH] add option to extract api struct name part of #98 --- cli/controller/generate.go | 50 ++++++++++++++++++ cli/controller/generate_test.go | 51 +++++++++++++++++++ .../testdata/generate/new_wrong_type/ping.go | 3 ++ .../testdata/generate/no_new/ping.go | 3 ++ .../testdata/generate/parameters/ping.go | 7 +++ .../testdata/generate/ping_ptr/ping.go | 7 +++ .../testdata/generate/ping_struct/ping.go | 7 +++ .../testdata/generate/return_value/ping.go | 7 +++ .../testdata/generate/return_values/ping.go | 7 +++ 9 files changed, 142 insertions(+) create mode 100644 cli/controller/generate_test.go create mode 100644 cli/controller/testdata/generate/new_wrong_type/ping.go create mode 100644 cli/controller/testdata/generate/no_new/ping.go create mode 100644 cli/controller/testdata/generate/parameters/ping.go create mode 100644 cli/controller/testdata/generate/ping_ptr/ping.go create mode 100644 cli/controller/testdata/generate/ping_struct/ping.go create mode 100644 cli/controller/testdata/generate/return_value/ping.go create mode 100644 cli/controller/testdata/generate/return_values/ping.go diff --git a/cli/controller/generate.go b/cli/controller/generate.go index 2c0f1e78..1568ec84 100644 --- a/cli/controller/generate.go +++ b/cli/controller/generate.go @@ -3,6 +3,9 @@ package controller import ( "errors" "fmt" + "go/ast" + "go/parser" + "go/token" "io/ioutil" "os" "os/exec" @@ -255,3 +258,50 @@ func saveFile(in []byte, path string) error { } return nil } + +func extractApiStructName(api, dir string) (string, error) { + pkgs, err := parser.ParseDir(token.NewFileSet(), dir, nil, parser.AllErrors) + if err != nil { + return "", log.Wrap(err) + } + pkg, ok := pkgs[api] + if !ok { + return "", log.Wrapf("package %s doesn't exist in folder %s", api, dir) + } + for _, v := range pkg.Files { + for _, o := range v.Scope.Objects { + if o.Name == "New" && o.Kind.String() == "func" { + decl, ok := o.Decl.(*ast.FuncDecl) + if !ok { + return "", log.Wrapf("could not find declaration of function New") + } + if len(decl.Type.Params.List) > 0 { + return "", log.Wrapf("function New should have no parameters") + } + rl := decl.Type.Results.List + if len(rl) > 1 { + return "", log.Wrapf("too many return values for New") + } + var idExpr ast.Expr + expr, ok := rl[0].Type.(*ast.StarExpr) + if ok { + idExpr = expr.X + } else { + idExpr = rl[0].Type + } + ident, ok := idExpr.(*ast.Ident) + if ok && ident.Obj != nil { + ft, ok := ident.Obj.Decl.(*ast.TypeSpec) + if ok { + _, ok := ft.Type.(*ast.StructType) + if ok { + return ident.Name, nil + } + } + } + return "", log.Wrapf("return value of New is not struct or pointer to struct") + } + } + } + return "", log.Wrapf("could not find function New for api %s", api) +} diff --git a/cli/controller/generate_test.go b/cli/controller/generate_test.go new file mode 100644 index 00000000..1ccaeabb --- /dev/null +++ b/cli/controller/generate_test.go @@ -0,0 +1,51 @@ +package controller + +import ( + "fmt" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestExtractApiStructNamePtr(t *testing.T) { + stc, err := extractApiStructName("ping", "testdata/generate/ping_ptr") + require.NoError(t, err) + assert.Equal(t, "Ping", stc) +} + +func TestExtractApiStructNameStruct(t *testing.T) { + stc, err := extractApiStructName("ping", "testdata/generate/ping_struct") + require.NoError(t, err) + assert.Equal(t, "Ping", stc) +} + +func TestExtractApiStructNameNoNew(t *testing.T) { + _, err := extractApiStructName("ping", "testdata/generate/no_new") + fmt.Println(err) + require.Error(t, err) +} + +func TestExtractApiStructNameNewWithParameters(t *testing.T) { + _, err := extractApiStructName("ping", "testdata/generate/parameters") + fmt.Println(err) + require.Error(t, err) +} + +func TestExtractApiStructNameTooManyValues(t *testing.T) { + _, err := extractApiStructName("ping", "testdata/generate/return_values") + fmt.Println(err) + require.Error(t, err) +} + +func TestExtractApiStructNameWrongValue(t *testing.T) { + _, err := extractApiStructName("ping", "testdata/generate/return_value") + fmt.Println(err) + require.Error(t, err) +} + +func TestExtractApiStructNameNewWrongType(t *testing.T) { + _, err := extractApiStructName("ping", "testdata/generate/new_wrong_type") + fmt.Println(err) + require.Error(t, err) +} diff --git a/cli/controller/testdata/generate/new_wrong_type/ping.go b/cli/controller/testdata/generate/new_wrong_type/ping.go new file mode 100644 index 00000000..e721eadc --- /dev/null +++ b/cli/controller/testdata/generate/new_wrong_type/ping.go @@ -0,0 +1,3 @@ +package ping + +const New = "this should be a function" diff --git a/cli/controller/testdata/generate/no_new/ping.go b/cli/controller/testdata/generate/no_new/ping.go new file mode 100644 index 00000000..fdafc73b --- /dev/null +++ b/cli/controller/testdata/generate/no_new/ping.go @@ -0,0 +1,3 @@ +package ping + +type Ping struct{} diff --git a/cli/controller/testdata/generate/parameters/ping.go b/cli/controller/testdata/generate/parameters/ping.go new file mode 100644 index 00000000..e7cb2b15 --- /dev/null +++ b/cli/controller/testdata/generate/parameters/ping.go @@ -0,0 +1,7 @@ +package ping + +type Ping struct{} + +func New(par string) *Ping { + return Ping{} +} diff --git a/cli/controller/testdata/generate/ping_ptr/ping.go b/cli/controller/testdata/generate/ping_ptr/ping.go new file mode 100644 index 00000000..59dcbf71 --- /dev/null +++ b/cli/controller/testdata/generate/ping_ptr/ping.go @@ -0,0 +1,7 @@ +package ping + +type Ping struct{} + +func New() *Ping { + return &Ping{} +} diff --git a/cli/controller/testdata/generate/ping_struct/ping.go b/cli/controller/testdata/generate/ping_struct/ping.go new file mode 100644 index 00000000..df3ad829 --- /dev/null +++ b/cli/controller/testdata/generate/ping_struct/ping.go @@ -0,0 +1,7 @@ +package ping + +type Ping struct{} + +func New() Ping { + return Ping{} +} diff --git a/cli/controller/testdata/generate/return_value/ping.go b/cli/controller/testdata/generate/return_value/ping.go new file mode 100644 index 00000000..e2d7fe40 --- /dev/null +++ b/cli/controller/testdata/generate/return_value/ping.go @@ -0,0 +1,7 @@ +package ping + +type Ping struct{} + +func New() int { + return -1 +} diff --git a/cli/controller/testdata/generate/return_values/ping.go b/cli/controller/testdata/generate/return_values/ping.go new file mode 100644 index 00000000..ea4d6047 --- /dev/null +++ b/cli/controller/testdata/generate/return_values/ping.go @@ -0,0 +1,7 @@ +package ping + +type Ping struct{} + +func New() (*Ping, error) { + return Ping{} +}