diff --git a/common/enum/generictype/generictype.go b/common/enum/generictype/generictype.go index 42a0c4b..eb4b8a1 100644 --- a/common/enum/generictype/generictype.go +++ b/common/enum/generictype/generictype.go @@ -174,25 +174,31 @@ var Root = &GenericType{ kinds: []string{}, } -// genericTypeLookup provides fast mapping from reflect.Kind to GenericType. -var genericTypeLookup map[string]*GenericType +// lookupByKind provides lookups from reflect.Kind.String to GenericType. +var lookupByKind map[string]*GenericType -// init() initializes the genericTypeLookup map. +// lookupByType provides lookups from generic type string to GenericType. +var lookupByType map[string]*GenericType + +// init() initializes the lookupByKind map. func init() { - genericTypeLookup = map[string]*GenericType{} - pathDefaultLookup = map[string]string{} + lookupByKind = map[string]*GenericType{} + lookupByType = map[string]*GenericType{} // mapTypes is a utility function to create map entries for the given GenericType. mapTypes := func(t *GenericType) { for _, k := range t.kinds { // Panic if duplicate type mappings exist. - if genericTypeLookup[k] != nil { - panic(fmt.Sprintf("duplicate GenericType mapping for %q", t)) + if lookupByKind[k] != nil { + panic(fmt.Sprintf("duplicate lookupByKind mapping for %q", k)) } - genericTypeLookup[k] = t + lookupByKind[k] = t } - pathDefaultLookup[t.String()] = t.PathDefault() + if lookupByType[t.String()] != nil { + panic(fmt.Sprintf("duplicate lookupByType mapping for %q", t.String())) + } + lookupByType[t.String()] = t } mapTypes(Invalid) @@ -210,11 +216,13 @@ func init() { mapTypes(Interface) mapTypes(Pointer) + + mapTypes(Root) } // GenericTypeOf returns the GenericType of the given reflect.Value. func GenericTypeOf(v reflect.Value) *GenericType { - if t := genericTypeLookup[v.Kind().String()]; t != nil { + if t := lookupByKind[v.Kind().String()]; t != nil { if t == Invalid { // Return invalid types immediately. return t @@ -223,7 +231,7 @@ func GenericTypeOf(v reflect.Value) *GenericType { // Look for special types. if v.Type().PkgPath() != "" { fullPath := FullPathOf(v) - if specialType := genericTypeLookup[fullPath]; specialType != nil { + if specialType := lookupByKind[fullPath]; specialType != nil { return specialType } } @@ -242,6 +250,19 @@ func GenericTypeOf(v reflect.Value) *GenericType { return Invalid } +// FromType returns the GenericType associated with a given string or nil if not found. +func FromType(typeString string) *GenericType { + return lookupByType[typeString] +} + +// PathDefaultOfType returns the path default for a given generic type string. +func PathDefaultOfType(typeString string) string { + if gt := FromType(typeString); gt != nil { + return gt.PathDefault() + } + return typeString +} + // FullPathOf returns the full package path for a Value. func FullPathOf(v reflect.Value) string { return fmt.Sprintf("%s.%s", v.Type().PkgPath(), v.Type().Name()) @@ -259,14 +280,3 @@ func tryConversion(v reflect.Value, t reflect.Type) (newValue reflect.Value, ok return v.Convert(t), true } - -// pathDefaultLookup provides fast mapping from genericType.String to pathDefault -var pathDefaultLookup map[string]string - -// PathDefaultOfType returns the path default for a given generic type string. -func PathDefaultOfType(typeString string) string { - if p := pathDefaultLookup[typeString]; p != "" { - return p - } - return typeString -} diff --git a/common/types/typenode.go b/common/types/typenode.go index 950d863..fa92130 100644 --- a/common/types/typenode.go +++ b/common/types/typenode.go @@ -22,8 +22,7 @@ type TypeNode struct { Nullable bool `json:",omitempty"` // Generic type of element. - TypeCategory string - Type string + Type string // TypeRef holds the name of a type (e.g. struct) TypeRef string `json:",omitempty"` @@ -69,7 +68,6 @@ func NewRootNode(name, dialect string) *TypeNode { r := NewTypeNode(name, dialect) r.Type = generictype.Root.String() - r.TypeCategory = generictype.Root.Category().String() return r } @@ -194,7 +192,6 @@ func (t *TypeNode) Copy() *TypeNode { n.Parent = nil n.Description = t.Description n.Type = t.Type - n.TypeCategory = t.TypeCategory n.TypeRef = t.TypeRef n.Error = t.Error n.MetaKey = t.MetaKey @@ -222,7 +219,6 @@ func (t *TypeNode) CopyWithoutNative() *TypeNode { n.Parent = nil n.Description = t.Description n.Type = t.Type - n.TypeCategory = t.TypeCategory n.TypeRef = t.TypeRef n.Error = t.Error n.MetaKey = t.MetaKey diff --git a/main_test.go b/main_test.go index ef1462b..2a54f4e 100644 --- a/main_test.go +++ b/main_test.go @@ -3,13 +3,6 @@ package main import ( "encoding/json" "fmt" - "github.com/ghodss/yaml" - "github.com/gitmann/b9schema-golang/common/util" - "github.com/gitmann/b9schema-golang/fixtures" - "github.com/gitmann/b9schema-golang/reflector" - "github.com/gitmann/b9schema-golang/renderer" - "github.com/gitmann/b9schema-golang/renderer/openapi" - "github.com/gitmann/b9schema-golang/renderer/simple" "io" "os" "os/exec" @@ -18,6 +11,14 @@ import ( "testing" "time" "unsafe" + + "github.com/ghodss/yaml" + "github.com/gitmann/b9schema-golang/common/util" + "github.com/gitmann/b9schema-golang/fixtures" + "github.com/gitmann/b9schema-golang/reflector" + "github.com/gitmann/b9schema-golang/renderer" + "github.com/gitmann/b9schema-golang/renderer/openapi" + "github.com/gitmann/b9schema-golang/renderer/simple" ) const ( @@ -3186,7 +3187,7 @@ func validateOpenAPI(t *testing.T, name, yamlStr string) bool { } if err := cmd.Start(); err != nil { - t.Errorf("TEST_FAIL %s: cmd start err=%s", name, err) + t.Errorf("TEST_FAIL %s: cmd start err=%s\nIs swagger-cli installed? 'npm install -g @apidevtools/swagger-cli'", name, err) return false } diff --git a/reflector/reflector.go b/reflector/reflector.go index 59c0fe4..185a876 100644 --- a/reflector/reflector.go +++ b/reflector/reflector.go @@ -85,7 +85,6 @@ func (r *Reflector) reflectTypeImpl(ancestorTypeRef types.AncestorTypeRef, curre // Get generic type for value. genericType := generictype.GenericTypeOf(v) currentElem.Type = genericType.String() - currentElem.TypeCategory = genericType.Category().String() // ERROR CHECKING // Check for invalid types. These may panic on some operations so we exit quickly with minimal reflection. diff --git a/renderer/simple/simple.go b/renderer/simple/simple.go index a00b36a..2fb1f51 100644 --- a/renderer/simple/simple.go +++ b/renderer/simple/simple.go @@ -87,8 +87,12 @@ func (r *SimpleRenderer) Path(t *types.TypeNode) []string { } // Type. - var typePart string - if t.TypeCategory == typecategory.Invalid.String() { + var typePart, typeCategory string + if gt := generictype.FromType(t.Type); gt != nil { + typeCategory = gt.Category().String() + } + + if typeCategory == typecategory.Invalid.String() { typePart = t.Type } else { typePart = generictype.PathDefaultOfType(t.Type)