Skip to content

Commit

Permalink
#25: Add TypesEmbeddedWith & TypesImplement
Browse files Browse the repository at this point in the history
  • Loading branch information
kcmvp committed May 17, 2024
1 parent 77c29f7 commit f830c8f
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 9 deletions.
9 changes: 9 additions & 0 deletions internal/sample/controller/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,14 @@ func LoginHandler(ctx gin.Context) {

}

type EmbeddedGroup struct {
gin.RouterGroup
}

type GroupWithNonEmbedded struct {
group gin.RouterGroup
}

type MyRouterGroup struct{}

func (m MyRouterGroup) Use(handlerFunc ...gin.HandlerFunc) gin.IRoutes {
Expand Down Expand Up @@ -96,3 +104,4 @@ func (m MyRouterGroup) Group(s string, handlerFunc ...gin.HandlerFunc) *gin.Rout
}

var _ gin.IRouter = (*MyRouterGroup)(nil)
var _ gin.IRouter = (*EmbeddedGroup)(nil)
42 changes: 33 additions & 9 deletions type.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,33 @@ func AllTypes() Types {
return typs
}

func TypesEmbeddedWith(embeds ...string) Types {
panic("to be implemented")
func TypesEmbeddedWith(embeddedType string) Types {
eType, ok := internal.Arch().Type(embeddedType)
if !ok {
log.Fatalf("can not find interface %s", embeddedType)
}
var typMap sync.Map
lo.ForEach(internal.Arch().Packages(), func(pkg *internal.Package, index int) {
if strings.HasPrefix(pkg.ID(), internal.Arch().Module()) &&
(pkg.ID() == eType.Package() || lo.Contains(pkg.Imports(), eType.Package())) {
lop.ForEach(pkg.Types(), func(typ internal.Type, index int) {
if str, ok := typ.Raw().Underlying().(*types.Struct); ok {
for i := 0; i < str.NumFields(); i++ {
if v := str.Field(i); v.Embedded() && types.Identical(v.Type(), eType.Raw()) {
typMap.Store(index, typ)
}
}
}
})
}
})
var typs Types
typMap.Range(func(_, value any) bool {
typs = append(typs, value.(internal.Type))
return true
})
return typs

}

// TypesImplement return all the types implement the interface
Expand All @@ -33,20 +58,19 @@ func TypesImplement(interName string) Types {
log.Fatalf("can not find interface %s", interName)
}
var typMap sync.Map
lop.ForEach(internal.Arch().Packages(), func(pkg *internal.Package, index int) {
lo.ForEach(internal.Arch().Packages(), func(pkg *internal.Package, index int) {
if strings.HasPrefix(pkg.ID(), internal.Arch().Module()) &&
(pkg.ID() == interType.Package() || lo.Contains(pkg.Imports(), interType.Package())) {
implementations := lo.Filter(pkg.Types(), func(typ internal.Type, _ int) bool {
return !strings.HasSuffix(typ.Name(), interName) && types.Implements(typ.Raw(), interType.Raw().Underlying().(*types.Interface))
lop.ForEach(pkg.Types(), func(typ internal.Type, index int) {
if !strings.HasSuffix(typ.Name(), interName) && types.Implements(typ.Raw(), interType.Raw().Underlying().(*types.Interface)) {
typMap.Store(index, typ)
}
})
if len(implementations) > 0 {
typMap.Store(pkg.ID(), implementations)
}
}
})
var typs Types
typMap.Range(func(_, value any) bool {
typs = append(typs, value.([]internal.Type)...)
typs = append(typs, value.(internal.Type))
return true
})
return typs
Expand Down
28 changes: 28 additions & 0 deletions type_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ func TestAllTypes(t *testing.T) {
"github.com/kcmvp/archunit/internal/sample/repository.FF",
"github.com/kcmvp/archunit/internal/sample/repository.UserRepository",
"github.com/kcmvp/archunit/internal/sample/controller.MyRouterGroup",
"github.com/kcmvp/archunit/internal/sample/controller.EmbeddedGroup",
"github.com/kcmvp/archunit/internal/sample/controller.GroupWithNonEmbedded",
}
assert.ElementsMatch(t, expected, typs)
}
Expand Down Expand Up @@ -77,3 +79,29 @@ func TestTypeImplement(t *testing.T) {
})
}
}

func TestTypesEmbeddedWith(t *testing.T) {
tests := []struct {
interType string
implementation []string
}{
{
interType: "github.com/gin-gonic/gin.RouterGroup",
implementation: []string{
"github.com/kcmvp/archunit/internal/sample/controller.EmbeddedGroup",
},
},
{
interType: "github.com/gin-gonic/gin.IRouter",
implementation: []string{},
},
}
for _, test := range tests {
t.Run(test.interType, func(t *testing.T) {
types := lo.Map(TypesEmbeddedWith(test.interType), func(item internal.Type, _ int) string {
return item.Name()
})
assert.ElementsMatch(t, test.implementation, types)
})
}
}

0 comments on commit f830c8f

Please sign in to comment.