diff --git a/README.md b/README.md index 9e9a338..9bc0d10 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ [![Go Report Card](https://goreportcard.com/badge/github.com/foomo/gocontemplate)](https://goreportcard.com/report/github.com/foomo/gocontemplate) [![GoDoc](https://godoc.org/github.com/foomo/gocontemplate?status.svg)](https://godoc.org/github.com/foomo/gocontemplate) -> A code generation helper, that +> A code generation helper. Wrapper library around `golang.org/x/tools/go/packages` to filter only defined types and their dependencies. diff --git a/pkg/assume/doc.go b/pkg/assume/doc.go new file mode 100644 index 0000000..8714675 --- /dev/null +++ b/pkg/assume/doc.go @@ -0,0 +1 @@ +package assume diff --git a/tc.go b/pkg/assume/t.go similarity index 58% rename from tc.go rename to pkg/assume/t.go index d63530e..f74968c 100644 --- a/tc.go +++ b/pkg/assume/t.go @@ -1,7 +1,7 @@ -package gocontemplate +package assume -// TC type conversion helper -func TC[T any](input any) T { +// T type conversion helper +func T[T any](input any) T { var output T if input == nil { return output diff --git a/config.go b/pkg/contemplate/config.go similarity index 67% rename from config.go rename to pkg/contemplate/config.go index 372f3e7..26a89d4 100644 --- a/config.go +++ b/pkg/contemplate/config.go @@ -1,10 +1,10 @@ -package gocontemplate +package contemplate type Config struct { - Packages []*ConfigPackage `json:"packages" yaml:"packages"` + Packages []*PackageConfig `json:"packages" yaml:"packages"` } -func (c *Config) Package(path string) *ConfigPackage { +func (c *Config) Package(path string) *PackageConfig { for _, value := range c.Packages { if value.Path == path { return value diff --git a/contemplate.go b/pkg/contemplate/contemplate.go similarity index 60% rename from contemplate.go rename to pkg/contemplate/contemplate.go index 08e6831..8bb3679 100644 --- a/contemplate.go +++ b/pkg/contemplate/contemplate.go @@ -1,10 +1,11 @@ -package gocontemplate +package contemplate import ( "go/ast" "go/types" "slices" + "github.com/foomo/gocontemplate/pkg/assume" "golang.org/x/exp/maps" "golang.org/x/tools/go/packages" ) @@ -34,7 +35,7 @@ func (s *Contemplate) LookupExpr(name string) ast.Expr { func (s *Contemplate) LookupTypesByType(obj types.Object) []types.Object { var ret []types.Object - expr := TC[*ast.Ident](s.LookupExpr(obj.Name())) + expr := assume.T[*ast.Ident](s.LookupExpr(obj.Name())) if expr == nil { return nil } @@ -43,17 +44,17 @@ func (s *Contemplate) LookupTypesByType(obj types.Object) []types.Object { for _, object := range pkg.Types() { switch objectType := object.(type) { case *types.Const: - if objectTypeNamed := TC[*types.Named](objectType.Type()); objectTypeNamed != nil { + if objectTypeNamed := assume.T[*types.Named](objectType.Type()); objectTypeNamed != nil { if objectTypeNamed.Obj() == obj { ret = append(ret, objectType) } } case *types.TypeName: if objectExpr := pkg.LookupExpr(object.Name()); objectExpr != nil { - if objectExprIdent := TC[*ast.Ident](objectExpr); objectExprIdent != nil { - if objectExprDecl := TC[*ast.TypeSpec](objectExprIdent.Obj.Decl); objectExprDecl != nil { + if objectExprIdent := assume.T[*ast.Ident](objectExpr); objectExprIdent != nil { + if objectExprDecl := assume.T[*ast.TypeSpec](objectExprIdent.Obj.Decl); objectExprDecl != nil { if objectExprType, ok := pkg.pkg.TypesInfo.Types[objectExprDecl.Type]; ok { - if objectExprTypeNamed := TC[*types.Named](objectExprType.Type); objectExprTypeNamed != nil { + if objectExprTypeNamed := assume.T[*types.Named](objectExprType.Type); objectExprTypeNamed != nil { if objectExprTypeNamed.Obj() == obj { ret = append(ret, objectType) } @@ -84,7 +85,7 @@ func (s *Contemplate) addPackages(pkgs ...*packages.Package) { } } -func (s *Contemplate) addPackagesConfigs(confs ...*ConfigPackage) { +func (s *Contemplate) addPackagesConfigs(confs ...*PackageConfig) { for _, conf := range confs { s.Package(conf.Path).AddScopeTypes(conf.Types...) } @@ -101,10 +102,6 @@ func (s *Contemplate) LookupAstIdentDefsByDeclType(input types.TypeAndValue) []t } } } - // for _, p := range s.pkgs { - // pkgs = append(pkgs, p) - // addImports(p) - // } var ret []types.Object for _, p := range pkgs { @@ -114,18 +111,6 @@ func (s *Contemplate) LookupAstIdentDefsByDeclType(input types.TypeAndValue) []t ret = append(ret, child) } } - - // for defAstIdent, defTypeObject := range p.TypesInfo.Defs { - // if defAstIdent != nil && defAstIdent.Obj != nil && defTypeObject != nil { - // if declValueSpec := TC[*ast.ValueSpec](defAstIdent.Obj.Decl); declValueSpec != nil { - // if declValueSpecIdent := TC[*ast.Ident](declValueSpec.Type); declValueSpecIdent != nil { - // if declValueSpecIdent.Obj == input.Obj { - // ret[defAstIdent] = defTypeObject - // } - // } - // } - // } - // } } return ret } @@ -136,36 +121,4 @@ func (s *Contemplate) addPackageTypeNames(pkg *packages.Package, typeNames ...st } // add request scopes s.Packages[pkg.PkgPath].AddScopeTypes(typeNames...) - - // for k, v := range s.Packages[pkg.PkgPath].Imports { - // s.addPackageTypeNames(k, v...) - // } - // check underlying added scopes - // for _, name := range added { - // s.typesType(pkg, s.Packages[pkg.PkgPath].Scope[name].Underlying()) - // } } - -// func (s *Loader) typesType(pkg *packages.Package, v types.Type) { -// switch t := v.(type) { -// case *types.Struct: -// // iterate fields -// for i := range t.NumFields() { -// s.typesVar(pkg, t.Field(i)) -// } -// default: -// fmt.Println(t) -// } -// } - -// func (s *Loader) typesVar(pkg *packages.Package, v *types.Var) { -// if !v.Exported() { -// return -// } -// switch t := v.Type().(type) { -// case *types.Named: -// if p, ok := pkg.Imports[v.Pkg().Path()]; ok { -// s.addPackageTypeNames(p, t.Obj().Name()) -// } -// } -// } diff --git a/contemplate_test.go b/pkg/contemplate/contemplate_test.go similarity index 76% rename from contemplate_test.go rename to pkg/contemplate/contemplate_test.go index c9d733f..d3b402b 100644 --- a/contemplate_test.go +++ b/pkg/contemplate/contemplate_test.go @@ -1,9 +1,9 @@ -package gocontemplate_test +package contemplate_test import ( "testing" - "github.com/foomo/gocontemplate" + "github.com/foomo/gocontemplate/pkg/contemplate" _ "github.com/foomo/sesamy-go" // force inclusion _ "github.com/foomo/sesamy-go/event/params" // force inclusion "github.com/stretchr/testify/assert" @@ -12,8 +12,8 @@ import ( func TestNewLoader(t *testing.T) { t.Parallel() - goctpl, err := gocontemplate.Load(&gocontemplate.Config{ - Packages: []*gocontemplate.ConfigPackage{ + goctpl, err := contemplate.Load(&contemplate.Config{ + Packages: []*contemplate.PackageConfig{ { Path: "github.com/foomo/sesamy-go/event", Types: []string{"PageView"}, @@ -27,8 +27,8 @@ func TestNewLoader(t *testing.T) { func TestLoader_LookupTypesByType(t *testing.T) { t.Parallel() - goctpl, err := gocontemplate.Load(&gocontemplate.Config{ - Packages: []*gocontemplate.ConfigPackage{ + goctpl, err := contemplate.Load(&contemplate.Config{ + Packages: []*contemplate.PackageConfig{ { Path: "github.com/foomo/sesamy-go/event", Types: []string{"PageView"}, diff --git a/load.go b/pkg/contemplate/load.go similarity index 96% rename from load.go rename to pkg/contemplate/load.go index f234b61..b2096ac 100644 --- a/load.go +++ b/pkg/contemplate/load.go @@ -1,4 +1,4 @@ -package gocontemplate +package contemplate import ( "golang.org/x/tools/go/packages" diff --git a/package.go b/pkg/contemplate/package.go similarity index 79% rename from package.go rename to pkg/contemplate/package.go index dda3981..d9f5cea 100644 --- a/package.go +++ b/pkg/contemplate/package.go @@ -1,10 +1,10 @@ -package gocontemplate +package contemplate import ( "go/ast" "go/types" - "strings" + "github.com/foomo/gocontemplate/pkg/assume" "golang.org/x/tools/go/packages" ) @@ -105,11 +105,11 @@ func (s *Package) LookupScopeExpr(name string) ast.Expr { func (s *Package) FilterExprsByTypeExpr(expr ast.Expr) []ast.Expr { var ret []ast.Expr - if exprIdent := TC[*ast.Ident](expr); exprIdent != nil { + if exprIdent := assume.T[*ast.Ident](expr); exprIdent != nil { for _, child := range s.exprs { - if childIdent := TC[*ast.Ident](child); childIdent != nil && childIdent.Obj != nil { - if childDecl := TC[*ast.ValueSpec](childIdent.Obj.Decl); childDecl != nil { - if childDeclType := TC[*ast.Ident](childDecl.Type); childDeclType != nil { + if childIdent := assume.T[*ast.Ident](child); childIdent != nil && childIdent.Obj != nil { + if childDecl := assume.T[*ast.ValueSpec](childIdent.Obj.Decl); childDecl != nil { + if childDeclType := assume.T[*ast.Ident](childDecl.Type); childDeclType != nil { if childDeclType.Obj == exprIdent.Obj { ret = append(ret, child) } @@ -147,7 +147,8 @@ func (s *Package) addScopeTypeAstExpr(input ast.Expr) { case *ast.Ident: if t.Obj != nil { s.addScopeTypeAstObject(t.Obj.Decl) - } else { + } + if t.IsExported() { s.l.addPackageTypeNames(s.pkg, t.Name) } case *ast.StructType: @@ -157,35 +158,45 @@ func (s *Package) addScopeTypeAstExpr(input ast.Expr) { case *ast.IndexExpr: s.addScopeTypeAstExpr(t.X) s.addScopeTypeAstExpr(t.Index) + case *ast.ArrayType: + s.addScopeTypeAstExpr(t.Elt) case *ast.SelectorExpr: s.addScopeTypeAstSelectorExpr(t) + default: + // fmt.Println(input, t) } } func (s *Package) addScopeTypeAstSelectorExpr(input *ast.SelectorExpr) { - if x := TC[*ast.Ident](input.X); x != nil { - if xPkgName := TC[*types.PkgName](s.pkg.TypesInfo.Uses[x]); xPkgName != nil { - if selIdent := TC[*ast.Ident](input.Sel); selIdent != nil { - for node, object := range s.pkg.TypesInfo.Implicits { - if object == xPkgName { - if nodeImportSepc := TC[*ast.ImportSpec](node); nodeImportSepc != nil { - v := strings.Trim(nodeImportSepc.Path.Value, "\"") - s.l.addPackageTypeNames(s.pkg.Imports[v], selIdent.Name) - } - } - } - } - } + if inputTypeNamed := assume.T[*types.Named](s.pkg.TypesInfo.TypeOf(input)); inputTypeNamed != nil { + s.l.addPackageTypeNames(s.pkg.Imports[inputTypeNamed.Obj().Pkg().Path()], inputTypeNamed.Obj().Name()) } } func (s *Package) addScopeTypeAstObject(input any) { switch t := input.(type) { case *ast.TypeSpec: + s.addScopeTypeAstFieldList(t.TypeParams) s.addScopeTypeAstExpr(t.Type) } } +func (s *Package) addScopeTypeAstFieldList(input *ast.FieldList) { + if input != nil { + for _, field := range input.List { + s.addScopeTypeAstField(field) + } + } +} + +func (s *Package) addScopeTypeAstField(input *ast.Field) { + // switch t := input.(type) { + // case *ast.TypeSpec: + // s.addScopeTypeAstFieldList(t.TypeParams) + // s.addScopeTypeAstExpr(t.Type) + // } +} + func (s *Package) addExprs(source map[*ast.Ident]types.Object) { for expr, object := range source { if object != nil { diff --git a/configpackage.go b/pkg/contemplate/packageconfig.go similarity index 64% rename from configpackage.go rename to pkg/contemplate/packageconfig.go index bbfb60e..5e6d467 100644 --- a/configpackage.go +++ b/pkg/contemplate/packageconfig.go @@ -1,6 +1,6 @@ -package gocontemplate +package contemplate -type ConfigPackage struct { +type PackageConfig struct { Path string `json:"path" yaml:"path"` Types []string `json:"types" yaml:"types"` }