diff --git a/cmd/genbindings/clang2il.go b/cmd/genbindings/clang2il.go index 6c5fca35..54b28035 100644 --- a/cmd/genbindings/clang2il.go +++ b/cmd/genbindings/clang2il.go @@ -165,6 +165,48 @@ nextTopLevel: return &ret, nil // done } +// shouldPreferQualType returns true if we should use the qualType instead of +// the desugared type based on certain type patterns +func shouldPreferQualType(qualType string) bool { + if strings.Contains(qualType, "intptr") || strings.Contains(qualType, "_t") || + strings.HasPrefix(qualType, "uint") || strings.Contains(qualType, "ushort") || + strings.Contains(qualType, "quint") || strings.Contains(qualType, "qint") || + strings.Contains(qualType, "qptrdiff") || strings.HasPrefix(qualType, "qsize") || + strings.HasPrefix(qualType, "QList<") || strings.HasPrefix(qualType, "QPair<") || + strings.HasPrefix(qualType, "QIntegerForSizeof<") { + return true + } + return false +} + +// getPreferredType returns either the desugared type or qual type based on our rules +func getPreferredType(node interface{}) string { + if node == nil { + return "" + } + + nodeMap, ok := node.(map[string]interface{}) + if !ok { + return "" + } + + var desugared, qualType string + if d, ok := nodeMap["desugaredQualType"].(string); ok { + desugared = d + } + if q, ok := nodeMap["qualType"].(string); ok { + qualType = q + } + + if qualType != "" && shouldPreferQualType(qualType) { + return qualType + } + if desugared != "" { + return desugared + } + return qualType +} + // processTypedef parses a single C++ typedef into our intermediate format. func processTypedef(node map[string]interface{}, addNamePrefix string) (CppTypedef, error) { // Must have a name @@ -174,7 +216,8 @@ func processTypedef(node map[string]interface{}, addNamePrefix string) (CppTyped } if typ, ok := node["type"].(map[string]interface{}); ok { - if qualType, ok := typ["qualType"].(string); ok { + qualType := getPreferredType(typ) + if qualType != "" { return CppTypedef{ Alias: addNamePrefix + nodename, UnderlyingType: parseSingleTypeString(qualType), @@ -264,7 +307,8 @@ func processClassType(node map[string]interface{}, addNamePrefix string) (CppCla } if typ, ok := base["type"].(map[string]interface{}); ok { - if qualType, ok := typ["qualType"].(string); ok { + qualType := getPreferredType(typ) + if qualType != "" { ret.DirectInherits = append(ret.DirectInherits, qualType) } } @@ -512,8 +556,9 @@ func processEnum(node map[string]interface{}, addNamePrefix string) (CppEnum, er // Underlying type ret.UnderlyingType = parseSingleTypeString("int") if nodefut, ok := node["fixedUnderlyingType"].(map[string]interface{}); ok { - if nodequal, ok := nodefut["qualType"].(string); ok { - ret.UnderlyingType = parseSingleTypeString(nodequal) + qualType := getPreferredType(nodefut) + if qualType != "" { + ret.UnderlyingType = parseSingleTypeString(qualType) } } @@ -652,11 +697,11 @@ nextEnumEntry: func parseMethod(node map[string]interface{}, mm *CppMethod) error { if typobj, ok := node["type"].(map[string]interface{}); ok { - if qualType, ok := typobj["qualType"].(string); ok { + qualType := getPreferredType(typobj) + if qualType != "" { // The qualType is the whole type of the method, including its parameter types // If anything here is too complicated, skip the whole method - - var err error = nil + var err error mm.ReturnType, mm.Parameters, mm.IsConst, err = parseTypeString(qualType) if err != nil { return err diff --git a/cmd/genbindings/clang2il_test.go b/cmd/genbindings/clang2il_test.go index a07372b2..e84c6ee5 100644 --- a/cmd/genbindings/clang2il_test.go +++ b/cmd/genbindings/clang2il_test.go @@ -14,27 +14,27 @@ func TestParseMethodTypes(t *testing.T) { } cases := []testCase{ - testCase{ + { input: "void (bool)", expectReturn: CppParameter{ParameterType: "void"}, expectParams: []CppParameter{ - CppParameter{ParameterType: "bool"}, + {ParameterType: "bool"}, }, }, - testCase{ + { input: "bool (QList>, QString)", expectReturn: CppParameter{ParameterType: "bool"}, expectParams: []CppParameter{ - CppParameter{ParameterType: "QList>"}, - CppParameter{ParameterType: "QString"}, + {ParameterType: "QList>"}, + {ParameterType: "QString"}, }, // expectErr: true, }, - testCase{ + { input: "bool (QList)", expectReturn: CppParameter{ParameterType: "bool"}, expectParams: []CppParameter{ - CppParameter{ParameterType: "QList"}, + {ParameterType: "QList"}, }, }, } diff --git a/cmd/genbindings/transformchildclasses_test.go b/cmd/genbindings/transformchildclasses_test.go index 456b5fac..1656ae21 100644 --- a/cmd/genbindings/transformchildclasses_test.go +++ b/cmd/genbindings/transformchildclasses_test.go @@ -9,17 +9,17 @@ func TestChildClassesExtract(t *testing.T) { src := CppParsedHeader{ Classes: []CppClass{ - CppClass{ + { ClassName: "Parent", ChildClassdefs: []CppClass{ - CppClass{ + { ClassName: "Parent::Child", ChildClassdefs: []CppClass{ - CppClass{ + { ClassName: "Parent::Child::Grandchild", }, }, diff --git a/cmd/genbindings/transformtypedefs_test.go b/cmd/genbindings/transformtypedefs_test.go index a1cf4d20..e8f0a3c1 100644 --- a/cmd/genbindings/transformtypedefs_test.go +++ b/cmd/genbindings/transformtypedefs_test.go @@ -12,11 +12,11 @@ func TestTransformTypedefs(t *testing.T) { return CppParsedHeader{ Classes: []CppClass{ - CppClass{ + { ClassName: "QTestClass", Ctors: []CppMethod{ - CppMethod{ + { Parameters: []CppParameter{ parseSingleTypeString(typeName), }, diff --git a/cmd/genbindings/util.go b/cmd/genbindings/util.go index 41735380..3ff32adc 100644 --- a/cmd/genbindings/util.go +++ b/cmd/genbindings/util.go @@ -1,9 +1,9 @@ package main import ( - "strconv" "encoding/json" "log" + "strconv" "strings" ) @@ -12,7 +12,7 @@ func maybeSuffix(counter int) string { return "" } - return strconv.Itoa(counter+1) + return strconv.Itoa(counter + 1) } func titleCase(s string) string { @@ -53,4 +53,4 @@ func slice_copy[T comparable](input []T) []T { ret[i] = elem } return ret -} \ No newline at end of file +}