Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions tpl/debug/debug.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
package debug

import (
"reflect"
"sort"

"github.com/sanity-io/litter"

"github.com/gohugoio/hugo/deps"
Expand All @@ -38,3 +41,51 @@ type Namespace struct {
func (ns *Namespace) Dump(val any) string {
return litter.Sdump(val)
}

// List returns the fields and methods of the struct/pointer or keys of the map.
func (ns *Namespace) List(val interface{}) []string {
values := make([]string, 0)

v := reflect.ValueOf(val)

// If the type is struct
if v.Kind() == reflect.Struct {
for i := 0; i < v.NumField(); i++ {
if v.Type().Field(i).IsExported() {
values = append(values, v.Type().Field(i).Name)
}
}

for i := 0; i < v.NumMethod(); i++ {
if v.Type().Method(i).IsExported() {
values = append(values, v.Type().Method(i).Name)
}
}
}

// If the type is pointer
if v.Kind() == reflect.Ptr {
for i := 0; i < reflect.Indirect(v).NumField(); i++ {
if v.Elem().Type().Field(i).IsExported() {
values = append(values, v.Elem().Type().Field(i).Name)
}
}

for i := 0; i < v.NumMethod(); i++ {
if v.Type().Method(i).IsExported() {
values = append(values, v.Type().Method(i).Name)
}
}
}

// If the type is map
if v.Kind() == reflect.Map {
iter := v.MapRange()
for iter.Next() {
values = append(values, iter.Key().String())
}
}

sort.Strings(values)
return values
}
67 changes: 67 additions & 0 deletions tpl/debug/debug_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package debug

import (
"testing"

qt "github.com/frankban/quicktest"
)

type User struct {
Name string
Phone string
city string
}

func (u User) GetName() string {
return u.Name
}

func (u User) GetPhone() string {
return u.Phone
}

func (u *User) getCity() string {
return u.city
}

func (u *User) GetPhoneAndCity() string {
return u.Phone + u.city
}

func TestList(t *testing.T) {
user := User{"a name", "9876543210", "SF"}
ns := Namespace{}

t.Run("struct", func(t *testing.T) {
c := qt.New(t)
result := ns.List(user)
c.Assert(len(result), qt.Equals, 4)
c.Assert(result[0], qt.Equals, "GetName")
c.Assert(result[1], qt.Equals, "GetPhone")
c.Assert(result[2], qt.Equals, "Name")
c.Assert(result[3], qt.Equals, "Phone")
})

t.Run("pointer", func(t *testing.T) {
c := qt.New(t)
result := ns.List(&user)
c.Assert(len(result), qt.Equals, 5)
c.Assert(result[0], qt.Equals, "GetName")
c.Assert(result[1], qt.Equals, "GetPhone")
c.Assert(result[2], qt.Equals, "GetPhoneAndCity")
c.Assert(result[3], qt.Equals, "Name")
c.Assert(result[4], qt.Equals, "Phone")
})

t.Run("map", func(t *testing.T) {
c := qt.New(t)
mapTestCase := map[string]string{
"name": "a name",
"phone": "a phone",
}
result := ns.List(mapTestCase)
c.Assert(result[0], qt.Equals, "name")
c.Assert(result[1], qt.Equals, "phone")
})

}