mirror of
https://github.com/stashapp/stash.git
synced 2025-12-06 08:26:00 +01:00
* Bump golang.org/x/text from 0.3.7 to 0.3.8 Bumps [golang.org/x/text](https://github.com/golang/text) from 0.3.7 to 0.3.8. - [Release notes](https://github.com/golang/text/releases) - [Commits](https://github.com/golang/text/compare/v0.3.7...v0.3.8) --- updated-dependencies: - dependency-name: golang.org/x/text dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> * Update go dependencies * Update x/net --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
176 lines
4.9 KiB
Go
176 lines
4.9 KiB
Go
package code
|
|
|
|
import (
|
|
"fmt"
|
|
"go/types"
|
|
)
|
|
|
|
// CompatibleTypes isnt a strict comparison, it allows for pointer differences
|
|
func CompatibleTypes(expected types.Type, actual types.Type) error {
|
|
// Special case to deal with pointer mismatches
|
|
{
|
|
expectedPtr, expectedIsPtr := expected.(*types.Pointer)
|
|
actualPtr, actualIsPtr := actual.(*types.Pointer)
|
|
|
|
if expectedIsPtr && actualIsPtr {
|
|
return CompatibleTypes(expectedPtr.Elem(), actualPtr.Elem())
|
|
}
|
|
if expectedIsPtr && !actualIsPtr {
|
|
return CompatibleTypes(expectedPtr.Elem(), actual)
|
|
}
|
|
if !expectedIsPtr && actualIsPtr {
|
|
return CompatibleTypes(expected, actualPtr.Elem())
|
|
}
|
|
}
|
|
|
|
switch expected := expected.(type) {
|
|
case *types.Slice:
|
|
if actual, ok := actual.(*types.Slice); ok {
|
|
return CompatibleTypes(expected.Elem(), actual.Elem())
|
|
}
|
|
|
|
case *types.Array:
|
|
if actual, ok := actual.(*types.Array); ok {
|
|
if expected.Len() != actual.Len() {
|
|
return fmt.Errorf("array length differs")
|
|
}
|
|
|
|
return CompatibleTypes(expected.Elem(), actual.Elem())
|
|
}
|
|
|
|
case *types.Basic:
|
|
if actualBasic, ok := actual.(*types.Basic); ok {
|
|
if similarBasicKind(actualBasic.Kind()) != expected.Kind() {
|
|
return fmt.Errorf("basic kind differs, %s != %s", expected.Name(), actualBasic.Name())
|
|
}
|
|
|
|
return nil
|
|
} else if actual, ok := actual.(*types.Named); ok {
|
|
if underlyingBasic, ok := actual.Underlying().(*types.Basic); ok {
|
|
return CompatibleTypes(expected, underlyingBasic)
|
|
}
|
|
}
|
|
|
|
case *types.Struct:
|
|
if actual, ok := actual.(*types.Struct); ok {
|
|
if expected.NumFields() != actual.NumFields() {
|
|
return fmt.Errorf("number of struct fields differ")
|
|
}
|
|
|
|
for i := 0; i < expected.NumFields(); i++ {
|
|
if expected.Field(i).Name() != actual.Field(i).Name() {
|
|
return fmt.Errorf("struct field %d name differs, %s != %s", i, expected.Field(i).Name(), actual.Field(i).Name())
|
|
}
|
|
if err := CompatibleTypes(expected.Field(i).Type(), actual.Field(i).Type()); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
case *types.Tuple:
|
|
if actual, ok := actual.(*types.Tuple); ok {
|
|
if expected.Len() != actual.Len() {
|
|
return fmt.Errorf("tuple length differs, %d != %d", expected.Len(), actual.Len())
|
|
}
|
|
|
|
for i := 0; i < expected.Len(); i++ {
|
|
if err := CompatibleTypes(expected.At(i).Type(), actual.At(i).Type()); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
case *types.Signature:
|
|
if actual, ok := actual.(*types.Signature); ok {
|
|
if err := CompatibleTypes(expected.Params(), actual.Params()); err != nil {
|
|
return err
|
|
}
|
|
if err := CompatibleTypes(expected.Results(), actual.Results()); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
case *types.Interface:
|
|
if actual, ok := actual.(*types.Interface); ok {
|
|
if expected.NumMethods() != actual.NumMethods() {
|
|
return fmt.Errorf("interface method count differs, %d != %d", expected.NumMethods(), actual.NumMethods())
|
|
}
|
|
|
|
for i := 0; i < expected.NumMethods(); i++ {
|
|
if expected.Method(i).Name() != actual.Method(i).Name() {
|
|
return fmt.Errorf("interface method %d name differs, %s != %s", i, expected.Method(i).Name(), actual.Method(i).Name())
|
|
}
|
|
if err := CompatibleTypes(expected.Method(i).Type(), actual.Method(i).Type()); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
case *types.Map:
|
|
if actual, ok := actual.(*types.Map); ok {
|
|
if err := CompatibleTypes(expected.Key(), actual.Key()); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := CompatibleTypes(expected.Elem(), actual.Elem()); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
case *types.Chan:
|
|
if actual, ok := actual.(*types.Chan); ok {
|
|
return CompatibleTypes(expected.Elem(), actual.Elem())
|
|
}
|
|
|
|
case *types.Named:
|
|
if actual, ok := actual.(*types.Named); ok {
|
|
if NormalizeVendor(expected.Obj().Pkg().Path()) != NormalizeVendor(actual.Obj().Pkg().Path()) {
|
|
return fmt.Errorf(
|
|
"package name of named type differs, %s != %s",
|
|
NormalizeVendor(expected.Obj().Pkg().Path()),
|
|
NormalizeVendor(actual.Obj().Pkg().Path()),
|
|
)
|
|
}
|
|
|
|
if expected.Obj().Name() != actual.Obj().Name() {
|
|
return fmt.Errorf(
|
|
"named type name differs, %s != %s",
|
|
NormalizeVendor(expected.Obj().Name()),
|
|
NormalizeVendor(actual.Obj().Name()),
|
|
)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// Before models are generated all missing references will be Invalid Basic references.
|
|
// lets assume these are valid too.
|
|
if actual, ok := actual.(*types.Basic); ok && actual.Kind() == types.Invalid {
|
|
return nil
|
|
}
|
|
|
|
default:
|
|
return fmt.Errorf("missing support for %T", expected)
|
|
}
|
|
|
|
return fmt.Errorf("type mismatch %T != %T", expected, actual)
|
|
}
|
|
|
|
func similarBasicKind(kind types.BasicKind) types.BasicKind {
|
|
switch kind {
|
|
case types.Int8, types.Int16:
|
|
return types.Int64
|
|
case types.Uint, types.Uint8, types.Uint16, types.Uint32: // exclude Uint64: it still needs scalar with custom marshalling/unmarshalling because it is bigger then int64
|
|
return types.Int64
|
|
default:
|
|
return kind
|
|
}
|
|
}
|