Skip to content

Commit

Permalink
feat: backport xast package to v28 (partial backport #3770) (#4108)
Browse files Browse the repository at this point in the history
* feat: backport xast package to v28

Co-authored-by: Danilo Pantani <[email protected]>
  • Loading branch information
julienrbrt and Pantani authored May 3, 2024
1 parent dec7a98 commit ddf17ce
Show file tree
Hide file tree
Showing 10 changed files with 1,857 additions and 14 deletions.
4 changes: 4 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## Unreleased

### Features

- [#4108](https://github.com/ignite/cli/pull/4108) Add `xast` package (cherry-picked from [#3770](https://github.com/ignite/cli/pull/3770))

### Changes

- [#3959](https://github.com/ignite/cli/pull/3959) Remove app name prefix from the `.gitignore` file
Expand Down
57 changes: 56 additions & 1 deletion ignite/pkg/goanalysis/goanalysis.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ func DiscoverMain(path string) (pkgPaths []string, err error) {

return nil
})

if err != nil {
return nil, err
}
Expand Down Expand Up @@ -338,3 +337,59 @@ func ReplaceCode(pkgPath, oldFunctionName, newFunction string) (err error) {
}
return nil
}

// HasAnyStructFieldsInPkg finds the struct within a package folder and checks
// if any of the fields are defined in the struct.
func HasAnyStructFieldsInPkg(pkgPath, structName string, fields []string) (bool, error) {
absPath, err := filepath.Abs(pkgPath)
if err != nil {
return false, err
}
fileSet := token.NewFileSet()
all, err := parser.ParseDir(fileSet, absPath, nil, parser.ParseComments)
if err != nil {
return false, err
}

fieldsNames := make(map[string]struct{})
for _, field := range fields {
fieldsNames[strings.ToLower(field)] = struct{}{}
}

exist := false
for _, pkg := range all {
for _, f := range pkg.Files {
ast.Inspect(f, func(x ast.Node) bool {
typeSpec, ok := x.(*ast.TypeSpec)
if !ok {
return true
}

if _, ok := typeSpec.Type.(*ast.StructType); !ok ||
typeSpec.Name.Name != structName ||
typeSpec.Type == nil {
return true
}

// Check if the struct has fields.
structType, ok := typeSpec.Type.(*ast.StructType)
if !ok {
return true
}

// Iterate through the fields of the struct.
for _, field := range structType.Fields.List {
for _, fieldName := range field.Names {
if _, ok := fieldsNames[strings.ToLower(fieldName.Name)]; !ok {
continue
}
exist = true
return false
}
}
return true
})
}
}
return exist, nil
}
118 changes: 105 additions & 13 deletions ignite/pkg/goanalysis/goanalysis_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,92 +145,92 @@ func createMainFiles(tmpDir string, mainFiles []string) (pathsWithMain []string,
func TestFuncVarExists(t *testing.T) {
tests := []struct {
name string
testfile string
testFile string
goImport string
methodSignature string
want bool
}{
{
name: "test a declaration inside a method success",
testfile: "testdata/varexist",
testFile: "testdata/varexist",
methodSignature: "Background",
goImport: "context",
want: true,
},
{
name: "test global declaration success",
testfile: "testdata/varexist",
testFile: "testdata/varexist",
methodSignature: "Join",
goImport: "path/filepath",
want: true,
},
{
name: "test a declaration inside an if and inside a method success",
testfile: "testdata/varexist",
testFile: "testdata/varexist",
methodSignature: "SplitList",
goImport: "path/filepath",
want: true,
},
{
name: "test global variable success assign",
testfile: "testdata/varexist",
testFile: "testdata/varexist",
methodSignature: "New",
goImport: "errors",
want: true,
},
{
name: "test invalid import",
testfile: "testdata/varexist",
testFile: "testdata/varexist",
methodSignature: "Join",
goImport: "errors",
want: false,
},
{
name: "test invalid case sensitive assign",
testfile: "testdata/varexist",
testFile: "testdata/varexist",
methodSignature: "join",
goImport: "context",
want: false,
},
{
name: "test invalid struct assign",
testfile: "testdata/varexist",
testFile: "testdata/varexist",
methodSignature: "fooStruct",
goImport: "context",
want: false,
},
{
name: "test invalid method signature",
testfile: "testdata/varexist",
testFile: "testdata/varexist",
methodSignature: "fooMethod",
goImport: "context",
want: false,
},
{
name: "test not found name",
testfile: "testdata/varexist",
testFile: "testdata/varexist",
methodSignature: "Invalid",
goImport: "context",
want: false,
},
{
name: "test invalid assign with wrong",
testfile: "testdata/varexist",
testFile: "testdata/varexist",
methodSignature: "invalid.New",
goImport: "context",
want: false,
},
{
name: "test invalid assign with wrong",
testfile: "testdata/varexist",
testFile: "testdata/varexist",
methodSignature: "SplitList",
goImport: "path/filepath",
want: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
appPkg, _, err := xast.ParseFile(tt.testfile)
appPkg, _, err := xast.ParseFile(tt.testFile)
require.NoError(t, err)

got := goanalysis.FuncVarExists(appPkg, tt.goImport, tt.methodSignature)
Expand Down Expand Up @@ -577,3 +577,95 @@ func NewMethod1() {
})
}
}

func TestHasStructFieldsInPkg(t *testing.T) {
tests := []struct {
name string
path string
structName string
fields []string
err error
want bool
}{
{
name: "test a value with an empty struct",
path: "testdata",
structName: "emptyStruct",
fields: []string{"name"},
want: false,
},
{
name: "test no value with an empty struct",
path: "testdata",
structName: "emptyStruct",
fields: []string{""},
want: false,
},
{
name: "test a valid field into single field struct",
path: "testdata",
structName: "fooStruct",
fields: []string{"name"},
want: true,
},
{
name: "test a not valid field into single field struct",
path: "testdata",
structName: "fooStruct",
fields: []string{"baz"},
want: false,
},
{
name: "test a not valid field into struct",
path: "testdata",
structName: "bazStruct",
fields: []string{"baz"},
want: false,
},
{
name: "test a valid field into struct",
path: "testdata",
structName: "bazStruct",
fields: []string{"name"},
want: true,
},
{
name: "test two valid fields into struct",
path: "testdata",
structName: "bazStruct",
fields: []string{"name", "title"},
want: true,
},
{
name: "test a valid and a not valid fields into struct",
path: "testdata",
structName: "bazStruct",
fields: []string{"foo", "title"},
want: true,
},
{
name: "test three not valid fields into struct",
path: "testdata",
structName: "bazStruct",
fields: []string{"foo", "baz", "bla"},
want: false,
},
{
name: "invalid path",
path: "invalid_path",
err: os.ErrNotExist,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := goanalysis.HasAnyStructFieldsInPkg(tt.path, tt.structName, tt.fields)
if tt.err != nil {
require.Error(t, err)
require.ErrorIs(t, err, tt.err)
return
}
require.NoError(t, err)
require.Equal(t, tt.want, got)
})
}
}
13 changes: 13 additions & 0 deletions ignite/pkg/goanalysis/testdata/fieldexist.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package goanalysis

type (
emptyStruct struct{}
fooStruct struct {
name string
}
bazStruct struct {
name string
title string
description string
}
)
Loading

0 comments on commit ddf17ce

Please sign in to comment.