feat: Go 1.18 compatibility because of missing any type

also reduce usage of reflect and use type switches
This commit is contained in:
Cyrill Schumacher 2022-08-16 16:50:05 +02:00
parent 6d65df09cf
commit 099876a04e
3 changed files with 75 additions and 87 deletions

View File

@ -4,6 +4,7 @@ type ScalarType string
const ( const (
ScalarTypeString ScalarType = "string" ScalarTypeString ScalarType = "string"
ScalarTypeAny ScalarType = "any"
ScalarTypeByte ScalarType = "byte" ScalarTypeByte ScalarType = "byte"
ScalarTypeNumber ScalarType = "number" ScalarTypeNumber ScalarType = "number"
ScalarTypeBool ScalarType = "bool" ScalarTypeBool ScalarType = "bool"

View File

@ -110,7 +110,7 @@ func getFileImports(file *ast.File, packageName string) (imports fileImportSpecM
name: standardImportName(importPath), name: standardImportName(importPath),
path: importPath, path: importPath,
} }
//trace(" import >>>>>>>>>>>>>>>>>>>>", importName, importPath) // trace(" import >>>>>>>>>>>>>>>>>>>>", importName, importPath)
} }
} }
} }
@ -135,7 +135,6 @@ func readFields(fieldList *ast.FieldList, fileImports fileImportSpecMap) (fields
} }
trace("done reading fields") trace("done reading fields")
return return
} }
func readServicesInPackage(pkg *ast.Package, packageName string, serviceMap map[string]string) (services ServiceList, err error) { func readServicesInPackage(pkg *ast.Package, packageName string, serviceMap map[string]string) (services ServiceList, err error) {
@ -193,7 +192,6 @@ func loadConstants(pkg *ast.Package) map[string]*ast.BasicLit {
} }
} }
return constants return constants
} }
func Read( func Read(
@ -278,7 +276,6 @@ func Read(
func fixFieldStructs(fields []*Field, structs map[string]*Struct, scalars map[string]*Scalar) { func fixFieldStructs(fields []*Field, structs map[string]*Struct, scalars map[string]*Scalar) {
for _, f := range fields { for _, f := range fields {
if f.Value.StructType != nil { if f.Value.StructType != nil {
// do we have that struct or is it a hidden scalar // do we have that struct or is it a hidden scalar
name := f.Value.StructType.FullName() name := f.Value.StructType.FullName()
@ -320,7 +317,7 @@ func collectTypes(goPaths []string, gomod config.Namespace, missingTypes map[str
fullNameParts := strings.Split(fullName, ".") fullNameParts := strings.Split(fullName, ".")
fullNameParts = fullNameParts[:len(fullNameParts)-1] fullNameParts = fullNameParts[:len(fullNameParts)-1]
//path := fullNameParts[:len(fullNameParts)-1][0] // path := fullNameParts[:len(fullNameParts)-1][0]
packageName := strings.Join(fullNameParts, ".") packageName := strings.Join(fullNameParts, ".")
@ -377,7 +374,7 @@ func collectTypes(goPaths []string, gomod config.Namespace, missingTypes map[str
} }
newNumMissingTypes := len(missingTypeNames()) newNumMissingTypes := len(missingTypeNames())
if newNumMissingTypes > 0 && newNumMissingTypes == lastNumMissing { if newNumMissingTypes > 0 && newNumMissingTypes == lastNumMissing {
//packageStructs, structOK := scannedPackageStructs[packageName] // packageStructs, structOK := scannedPackageStructs[packageName]
for scalarName, scalars := range scannedPackageScalars { for scalarName, scalars := range scannedPackageScalars {
fmt.Println("scanned scalars ", scalarName) fmt.Println("scanned scalars ", scalarName)
for _, scalar := range scalars { for _, scalar := range scalars {
@ -488,16 +485,17 @@ func getTypesInPackage(
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
return structs, scalars, nil return structs, scalars, nil
} }
func getStructTypeForField(value *Value) *StructType { func getStructTypeForField(value *Value) *StructType {
//field.Value.StructType // field.Value.StructType
var strType *StructType var strType *StructType
switch true { switch true {
case value.StructType != nil: case value.StructType != nil:
strType = value.StructType strType = value.StructType
//case field.Value.ArrayType // case field.Value.ArrayType
case value.Map != nil: case value.Map != nil:
strType = getStructTypeForField(value.Map.Value) strType = getStructTypeForField(value.Map.Value)
case value.Array != nil: case value.Array != nil:
@ -507,12 +505,12 @@ func getStructTypeForField(value *Value) *StructType {
} }
func getScalarForField(value *Value) *Scalar { func getScalarForField(value *Value) *Scalar {
//field.Value.StructType // field.Value.StructType
var scalarType *Scalar var scalarType *Scalar
switch true { switch true {
case value.Scalar != nil: case value.Scalar != nil:
scalarType = value.Scalar scalarType = value.Scalar
//case field.Value.ArrayType // case field.Value.ArrayType
case value.Map != nil: case value.Map != nil:
scalarType = getScalarForField(value.Map.Value) scalarType = getScalarForField(value.Map.Value)
case value.Array != nil: case value.Array != nil:
@ -552,5 +550,3 @@ func collectStructTypes(fields []*Field, structTypes map[string]bool) {
} }
} }
} }
//func collectStructs(goPath, structs)

View File

@ -7,7 +7,7 @@ import (
"reflect" "reflect"
"strings" "strings"
yaml "gopkg.in/yaml.v2" "gopkg.in/yaml.v2"
) )
var ReaderTrace = false var ReaderTrace = false
@ -34,9 +34,9 @@ func readStructs(pkg *ast.Package, packageName string) (structs map[string]*Stru
structType.IsError = true structType.IsError = true
} }
} }
//jsonDump(errorTypes) // jsonDump(errorTypes)
//jsonDump(scalarTypes) // jsonDump(scalarTypes)
//jsonDump(structs) // jsonDump(structs)
return return
} }
@ -45,6 +45,7 @@ func trace(args ...interface{}) {
fmt.Fprintln(os.Stderr, args...) fmt.Fprintln(os.Stderr, args...)
} }
} }
func traceData(args ...interface{}) { func traceData(args ...interface{}) {
if ReaderTrace { if ReaderTrace {
for _, arg := range args { for _, arg := range args {
@ -105,6 +106,8 @@ func getScalarFromAstIdent(ident *ast.Ident) ScalarType {
switch ident.Name { switch ident.Name {
case "string": case "string":
return ScalarTypeString return ScalarTypeString
case "any":
return ScalarTypeAny
case "bool": case "bool":
return ScalarTypeBool return ScalarTypeBool
case "byte": case "byte":
@ -137,6 +140,7 @@ func getTypesFromAstType(ident *ast.Ident) (structType string, scalarType Scalar
func readAstType(v *Value, fieldIdent *ast.Ident, fileImports fileImportSpecMap) { func readAstType(v *Value, fieldIdent *ast.Ident, fileImports fileImportSpecMap) {
structType, scalarType := getTypesFromAstType(fieldIdent) structType, scalarType := getTypesFromAstType(fieldIdent)
v.ScalarType = scalarType v.ScalarType = scalarType
if len(structType) > 0 { if len(structType) > 0 {
v.StructType = &StructType{ v.StructType = &StructType{
Name: structType, Name: structType,
@ -145,31 +149,27 @@ func readAstType(v *Value, fieldIdent *ast.Ident, fileImports fileImportSpecMap)
} else { } else {
v.GoScalarType = fieldIdent.Name v.GoScalarType = fieldIdent.Name
if fieldIdent.Obj != nil && fieldIdent.Obj.Decl != nil && reflect.ValueOf(fieldIdent.Obj.Decl).Type().String() == "*ast.TypeSpec" { if fieldIdent.Obj != nil && fieldIdent.Obj.Decl != nil && reflect.ValueOf(fieldIdent.Obj.Decl).Type().String() == "*ast.TypeSpec" {
//typeSpec := fieldIdent.Obj.Decl.(*ast.TypeSpec) // typeSpec := fieldIdent.Obj.Decl.(*ast.TypeSpec)
//fmt.Println("-------------------------------------->", fieldIdent.Name, reflect.ValueOf(typeSpec.Type).Type()) // fmt.Println("-------------------------------------->", fieldIdent.Name, reflect.ValueOf(typeSpec.Type).Type())
v.Scalar = &Scalar{ v.Scalar = &Scalar{
Package: fileImports.getPackagePath(""), Package: fileImports.getPackagePath(""),
Name: fieldIdent.Name, Name: fieldIdent.Name,
Type: scalarType, Type: scalarType,
} }
//jsonDump(v)
} }
} }
//
} }
func readAstStarExpr(v *Value, starExpr *ast.StarExpr, fileImports fileImportSpecMap) { func readAstStarExpr(v *Value, starExpr *ast.StarExpr, fileImports fileImportSpecMap) {
v.IsPtr = true v.IsPtr = true
switch reflect.ValueOf(starExpr.X).Type().String() { switch starExprType := starExpr.X.(type) {
case "*ast.Ident": case *ast.Ident:
ident := starExpr.X.(*ast.Ident) readAstType(v, starExprType, fileImports)
readAstType(v, ident, fileImports) case *ast.StructType:
case "*ast.StructType":
// nested anonymous // nested anonymous
readAstStructType(v, starExpr.X.(*ast.StructType), fileImports) readAstStructType(v, starExprType, fileImports)
case "*ast.SelectorExpr": case *ast.SelectorExpr:
readAstSelectorExpr(v, starExpr.X.(*ast.SelectorExpr), fileImports) readAstSelectorExpr(v, starExprType, fileImports)
default: default:
trace("a pointer on what", reflect.ValueOf(starExpr.X).Type().String()) trace("a pointer on what", reflect.ValueOf(starExpr.X).Type().String())
} }
@ -179,11 +179,11 @@ func readAstMapType(m *Map, mapType *ast.MapType, fileImports fileImportSpecMap)
trace(" map key", mapType.Key, reflect.ValueOf(mapType.Key).Type().String()) trace(" map key", mapType.Key, reflect.ValueOf(mapType.Key).Type().String())
trace(" map value", mapType.Value, reflect.ValueOf(mapType.Value).Type().String()) trace(" map value", mapType.Value, reflect.ValueOf(mapType.Value).Type().String())
// key // key
switch reflect.ValueOf(mapType.Key).Type().String() { switch keyType := mapType.Key.(type) {
case "*ast.Ident": case *ast.Ident:
_, scalarType := getTypesFromAstType(mapType.Key.(*ast.Ident)) _, scalarType := getTypesFromAstType(keyType)
m.KeyType = string(scalarType) m.KeyType = string(scalarType)
m.KeyGoType = mapType.Key.(*ast.Ident).Name m.KeyGoType = keyType.Name
default: default:
// todo: implement support for "*ast.Scalar" type (sca) // todo: implement support for "*ast.Scalar" type (sca)
// this is important for scalar types in map keys // this is important for scalar types in map keys
@ -204,25 +204,25 @@ func readAstMapType(m *Map, mapType *ast.MapType, fileImports fileImportSpecMap)
// }) // })
//}) //})
//fmt.Println("--------------------------->", reflect.ValueOf(mapType.Key).Type().String()) // fmt.Println("--------------------------->", reflect.ValueOf(mapType.Key).Type().String())
} }
// value // value
m.Value.loadExpr(mapType.Value, fileImports) m.Value.loadExpr(mapType.Value, fileImports)
} }
func readAstSelectorExpr(v *Value, selectorExpr *ast.SelectorExpr, fileImports fileImportSpecMap) { func readAstSelectorExpr(v *Value, selectorExpr *ast.SelectorExpr, fileImports fileImportSpecMap) {
switch reflect.ValueOf(selectorExpr.X).Type().String() { switch selExpType := selectorExpr.X.(type) {
case "*ast.Ident": case *ast.Ident:
// that could be the package name // that could be the package name
//selectorIdent := selectorExpr.X.(*ast.Ident) // selectorIdent := selectorExpr.X.(*ast.Ident)
// fmt.Println(selectorExpr, selectorExpr.X.(*ast.Ident)) // fmt.Println(selectorExpr, selectorExpr.X.(*ast.Ident))
readAstType(v, selectorExpr.X.(*ast.Ident), fileImports) readAstType(v, selExpType, fileImports)
if v.StructType != nil { if v.StructType != nil {
v.StructType.Package = fileImports.getPackagePath(v.StructType.Name) v.StructType.Package = fileImports.getPackagePath(v.StructType.Name)
v.StructType.Name = selectorExpr.Sel.Name v.StructType.Name = selectorExpr.Sel.Name
} }
//fmt.Println(selectorExpr.X.(*ast.Ident).Name, ".", selectorExpr.Sel) // fmt.Println(selectorExpr.X.(*ast.Ident).Name, ".", selectorExpr.Sel)
//readAstType(v, selectorExpr.Sel, fileImports) // readAstType(v, selectorExpr.Sel, fileImports)
default: default:
trace("selectorExpr.Sel !?", selectorExpr.X, reflect.ValueOf(selectorExpr.X).Type().String()) trace("selectorExpr.Sel !?", selectorExpr.X, reflect.ValueOf(selectorExpr.X).Type().String())
} }
@ -235,54 +235,52 @@ func readAstStructType(v *Value, structType *ast.StructType, fileImports fileImp
func readAstInterfaceType(v *Value, interfaceType *ast.InterfaceType, fileImports fileImportSpecMap) { func readAstInterfaceType(v *Value, interfaceType *ast.InterfaceType, fileImports fileImportSpecMap) {
v.IsInterface = true v.IsInterface = true
} }
func (v *Value) loadExpr(expr ast.Expr, fileImports fileImportSpecMap) { func (v *Value) loadExpr(expr ast.Expr, fileImports fileImportSpecMap) {
switch expr.(type) {
switch reflect.ValueOf(expr).Type().String() { case *ast.ArrayType:
case "*ast.ArrayType":
fieldArray := expr.(*ast.ArrayType) fieldArray := expr.(*ast.ArrayType)
v.Array = &Array{Value: &Value{}} v.Array = &Array{Value: &Value{}}
switch reflect.ValueOf(fieldArray.Elt).Type().String() { switch faEltType := fieldArray.Elt.(type) {
case "*ast.ArrayType": case *ast.ArrayType:
//readAstArrayType(v.Array.Value, fieldArray.Elt.(*ast.ArrayType), fileImports) // readAstArrayType(v.Array.Value, fieldArray.Elt.(*ast.ArrayType), fileImports)
v.Array.Value.loadExpr(fieldArray.Elt.(*ast.ArrayType), fileImports) v.Array.Value.loadExpr(faEltType, fileImports)
case "*ast.Ident": case *ast.Ident:
readAstType(v.Array.Value, fieldArray.Elt.(*ast.Ident), fileImports) readAstType(v.Array.Value, faEltType, fileImports)
case "*ast.StarExpr": case *ast.StarExpr:
readAstStarExpr(v.Array.Value, fieldArray.Elt.(*ast.StarExpr), fileImports) readAstStarExpr(v.Array.Value, faEltType, fileImports)
case "*ast.MapType": case *ast.MapType:
v.Array.Value.Map = &Map{ v.Array.Value.Map = &Map{
Value: &Value{}, Value: &Value{},
} }
readAstMapType(v.Array.Value.Map, fieldArray.Elt.(*ast.MapType), fileImports) readAstMapType(v.Array.Value.Map, faEltType, fileImports)
case "*ast.SelectorExpr": case *ast.SelectorExpr:
readAstSelectorExpr(v.Array.Value, fieldArray.Elt.(*ast.SelectorExpr), fileImports) readAstSelectorExpr(v.Array.Value, faEltType, fileImports)
case "*ast.StructType": case *ast.StructType:
readAstStructType(v.Array.Value, fieldArray.Elt.(*ast.StructType), fileImports) readAstStructType(v.Array.Value, faEltType, fileImports)
case "*ast.InterfaceType": case *ast.InterfaceType:
readAstInterfaceType(v.Array.Value, fieldArray.Elt.(*ast.InterfaceType), fileImports) readAstInterfaceType(v.Array.Value, faEltType, fileImports)
default: default:
trace("---------------------> array of", reflect.ValueOf(fieldArray.Elt).Type().String()) trace("---------------------> array of", reflect.ValueOf(fieldArray.Elt).Type().String())
} }
case "*ast.Ident": case *ast.Ident:
fieldIdent := expr.(*ast.Ident) fieldIdent := expr.(*ast.Ident)
readAstType(v, fieldIdent, fileImports) readAstType(v, fieldIdent, fileImports)
case "*ast.StarExpr": case *ast.StarExpr:
// a pointer on sth // a pointer on sth
readAstStarExpr(v, expr.(*ast.StarExpr), fileImports) readAstStarExpr(v, expr.(*ast.StarExpr), fileImports)
case "*ast.MapType": case *ast.MapType:
v.Map = &Map{ v.Map = &Map{
Value: &Value{}, Value: &Value{},
} }
readAstMapType(v.Map, expr.(*ast.MapType), fileImports) readAstMapType(v.Map, expr.(*ast.MapType), fileImports)
case "*ast.SelectorExpr": case *ast.SelectorExpr:
readAstSelectorExpr(v, expr.(*ast.SelectorExpr), fileImports) readAstSelectorExpr(v, expr.(*ast.SelectorExpr), fileImports)
case "*ast.StructType": case *ast.StructType:
readAstStructType(v, expr.(*ast.StructType), fileImports) readAstStructType(v, expr.(*ast.StructType), fileImports)
case "*ast.InterfaceType": case *ast.InterfaceType:
readAstInterfaceType(v, expr.(*ast.InterfaceType), fileImports) readAstInterfaceType(v, expr.(*ast.InterfaceType), fileImports)
default: default:
trace("what kind of field ident would that be ?!", reflect.ValueOf(expr).Type().String()) trace("what kind of field ident would that be ?!", reflect.ValueOf(expr).Type().String())
@ -295,6 +293,7 @@ func readField(astField *ast.Field, fileImports fileImportSpecMap) (name string,
name = astField.Names[0].Name name = astField.Names[0].Name
} }
v = &Value{} v = &Value{}
v.loadExpr(astField.Type, fileImports) v.loadExpr(astField.Type, fileImports)
if astField.Tag != nil { if astField.Tag != nil {
jsonInfo = extractJSONInfo(astField.Tag.Value[1 : len(astField.Tag.Value)-1]) jsonInfo = extractJSONInfo(astField.Tag.Value[1 : len(astField.Tag.Value)-1])
@ -303,7 +302,6 @@ func readField(astField *ast.Field, fileImports fileImportSpecMap) (name string,
} }
func readFieldList(fieldList []*ast.Field, fileImports fileImportSpecMap) (fields []*Field) { func readFieldList(fieldList []*ast.Field, fileImports fileImportSpecMap) (fields []*Field) {
fields = []*Field{}
for _, field := range fieldList { for _, field := range fieldList {
name, value, jsonInfo := readField(field, fileImports) name, value, jsonInfo := readField(field, fileImports)
if len(name) == 0 { if len(name) == 0 {
@ -328,23 +326,18 @@ func readFieldList(fieldList []*ast.Field, fileImports fileImportSpecMap) (field
func extractErrorTypes(file *ast.File, packageName string, errorTypes map[string]bool) (err error) { func extractErrorTypes(file *ast.File, packageName string, errorTypes map[string]bool) (err error) {
for _, d := range file.Decls { for _, d := range file.Decls {
if reflect.ValueOf(d).Type().String() == "*ast.FuncDecl" { if funcDecl, ok := d.(*ast.FuncDecl); ok {
funcDecl := d.(*ast.FuncDecl)
if funcDecl.Recv != nil && len(funcDecl.Recv.List) == 1 { if funcDecl.Recv != nil && len(funcDecl.Recv.List) == 1 {
firstReceiverField := funcDecl.Recv.List[0] firstReceiverField := funcDecl.Recv.List[0]
if "*ast.StarExpr" == reflect.ValueOf(firstReceiverField.Type).Type().String() { if starExpr, ok := firstReceiverField.Type.(*ast.StarExpr); ok {
starExpr := firstReceiverField.Type.(*ast.StarExpr) if ident, ok := starExpr.X.(*ast.Ident); ok {
if "*ast.Ident" == reflect.ValueOf(starExpr.X).Type().String() {
ident := starExpr.X.(*ast.Ident)
if funcDecl.Name.Name == "Error" && funcDecl.Type.Params.NumFields() == 0 && funcDecl.Type.Results.NumFields() == 1 { if funcDecl.Name.Name == "Error" && funcDecl.Type.Params.NumFields() == 0 && funcDecl.Type.Results.NumFields() == 1 {
returnValueField := funcDecl.Type.Results.List[0] returnValueField := funcDecl.Type.Results.List[0]
refl := reflect.ValueOf(returnValueField.Type) if returnValueIdent, ok := returnValueField.Type.(*ast.Ident); ok {
if refl.Type().String() == "*ast.Ident" {
returnValueIdent := returnValueField.Type.(*ast.Ident)
if returnValueIdent.Name == "string" { if returnValueIdent.Name == "string" {
errorTypes[packageName+"."+ident.Name] = true errorTypes[packageName+"."+ident.Name] = true
} }
//fmt.Println("error for:", ident.Name, returnValueIdent.Name) // fmt.Println("error for:", ident.Name, returnValueIdent.Name)
} }
} }
} }
@ -361,12 +354,9 @@ func extractTypes(file *ast.File, packageName string, structs map[string]*Struct
if obj.Kind == ast.Typ && obj.Decl != nil { if obj.Kind == ast.Typ && obj.Decl != nil {
structName := packageName + "." + name structName := packageName + "." + name
if reflect.ValueOf(obj.Decl).Type().String() == "*ast.TypeSpec" { if typeSpec, ok := obj.Decl.(*ast.TypeSpec); ok {
typeSpec := obj.Decl.(*ast.TypeSpec) switch tst := typeSpec.Type.(type) {
typeSpecRefl := reflect.ValueOf(typeSpec.Type) case *ast.StructType:
typeName := typeSpecRefl.Type().String()
switch typeName {
case "*ast.StructType":
structs[structName] = &Struct{ structs[structName] = &Struct{
Name: name, Name: name,
Fields: []*Field{}, Fields: []*Field{},
@ -375,7 +365,8 @@ func extractTypes(file *ast.File, packageName string, structs map[string]*Struct
structType := typeSpec.Type.(*ast.StructType) structType := typeSpec.Type.(*ast.StructType)
trace("StructType", obj.Name) trace("StructType", obj.Name)
structs[structName].Fields = readFieldList(structType.Fields.List, fileImports) structs[structName].Fields = readFieldList(structType.Fields.List, fileImports)
case "*ast.Ident":
case *ast.Ident:
trace("Scalar", obj.Name) trace("Scalar", obj.Name)
scalarIdent := typeSpec.Type.(*ast.Ident) scalarIdent := typeSpec.Type.(*ast.Ident)
scalarTypes[structName] = &Scalar{ scalarTypes[structName] = &Scalar{
@ -383,7 +374,7 @@ func extractTypes(file *ast.File, packageName string, structs map[string]*Struct
Package: packageName, Package: packageName,
Type: getScalarFromAstIdent(scalarIdent), Type: getScalarFromAstIdent(scalarIdent),
} }
case "*ast.ArrayType": case *ast.ArrayType:
arrayValue := &Value{} arrayValue := &Value{}
arrayValue.loadExpr(typeSpec.Type, fileImports) arrayValue.loadExpr(typeSpec.Type, fileImports)
structs[structName] = &Struct{ structs[structName] = &Struct{
@ -391,7 +382,7 @@ func extractTypes(file *ast.File, packageName string, structs map[string]*Struct
Package: packageName, Package: packageName,
Array: arrayValue.Array, Array: arrayValue.Array,
} }
case "*ast.MapType": case *ast.MapType:
mapValue := &Value{} mapValue := &Value{}
mapValue.loadExpr(typeSpec.Type, fileImports) mapValue.loadExpr(typeSpec.Type, fileImports)
structs[structName] = &Struct{ structs[structName] = &Struct{
@ -400,7 +391,7 @@ func extractTypes(file *ast.File, packageName string, structs map[string]*Struct
Map: mapValue.Map, Map: mapValue.Map,
} }
default: default:
fmt.Println(" ignoring", obj.Name, typeSpecRefl.Type().String()) fmt.Printf(" ignoring %s %T\n", obj.Name, tst)
} }
} }
} }