mirror of
https://github.com/mappu/miqt.git
synced 2024-12-22 17:08:38 +00:00
genbindings: more accurate parameter types
This commit is contained in:
parent
6174c4c243
commit
4b803eb453
@ -11,8 +11,6 @@ func parseHeader(inner []interface{}) (*CppParsedHeader, error) {
|
|||||||
|
|
||||||
var ret CppParsedHeader
|
var ret CppParsedHeader
|
||||||
|
|
||||||
fmt.Printf("package miqt\n\n")
|
|
||||||
|
|
||||||
for _, node := range inner {
|
for _, node := range inner {
|
||||||
|
|
||||||
node, ok := node.(map[string]interface{})
|
node, ok := node.(map[string]interface{})
|
||||||
@ -96,7 +94,13 @@ nextMethod:
|
|||||||
panic("unexpected access visibility '" + access + "'")
|
panic("unexpected access visibility '" + access + "'")
|
||||||
}
|
}
|
||||||
|
|
||||||
case "CXXConstructorDecl", "":
|
case "FriendDecl":
|
||||||
|
// Safe to ignore
|
||||||
|
|
||||||
|
case "CXXConstructorDecl":
|
||||||
|
// panic("TODO")
|
||||||
|
|
||||||
|
case "CXXDestructorDecl":
|
||||||
// panic("TODO")
|
// panic("TODO")
|
||||||
|
|
||||||
case "CXXMethodDecl":
|
case "CXXMethodDecl":
|
||||||
@ -117,18 +121,23 @@ nextMethod:
|
|||||||
if qualType, ok := typobj["qualType"].(string); ok {
|
if qualType, ok := typobj["qualType"].(string); ok {
|
||||||
// The qualType is the whole type of the method, including its parameter types
|
// The qualType is the whole type of the method, including its parameter types
|
||||||
// If anything here is too complicated, skip the whole method
|
// If anything here is too complicated, skip the whole method
|
||||||
if strings.Contains(qualType, `::`) {
|
|
||||||
log.Printf("Skipping method %q with complex type %q", mm.MethodName, qualType)
|
var err error = nil
|
||||||
continue nextMethod
|
mm.ReturnType, mm.Parameters, err = parseTypeString(qualType)
|
||||||
|
if err != nil {
|
||||||
|
if errors.Is(err, ErrTooComplex) {
|
||||||
|
log.Printf("Skipping method %q with complex type %q", mm.MethodName, qualType)
|
||||||
|
continue nextMethod
|
||||||
|
}
|
||||||
|
// Real error
|
||||||
|
return CppClass{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// We only want up to the first ( character
|
|
||||||
mm.ReturnType, _, _ = strings.Cut(qualType, `(`)
|
|
||||||
mm.ReturnType = strings.TrimSpace(mm.ReturnType)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if methodInner, ok := node["inner"].([]interface{}); ok {
|
if methodInner, ok := node["inner"].([]interface{}); ok {
|
||||||
|
paramCounter := 0
|
||||||
for _, methodObj := range methodInner {
|
for _, methodObj := range methodInner {
|
||||||
methodObj, ok := methodObj.(map[string]interface{})
|
methodObj, ok := methodObj.(map[string]interface{})
|
||||||
if !ok {
|
if !ok {
|
||||||
@ -140,26 +149,14 @@ nextMethod:
|
|||||||
// Parameter variable
|
// Parameter variable
|
||||||
parmName, _ := methodObj["name"].(string) // n.b. may be unnamed
|
parmName, _ := methodObj["name"].(string) // n.b. may be unnamed
|
||||||
if parmName == "" {
|
if parmName == "" {
|
||||||
parmName = fmt.Sprintf("param%d", len(mm.Parameters)+1)
|
parmName = fmt.Sprintf("param%d", paramCounter+1)
|
||||||
}
|
}
|
||||||
|
|
||||||
var parmType string
|
// Update the name for the existing nth parameter
|
||||||
if typobj, ok := node["type"].(map[string]interface{}); ok {
|
mm.Parameters[paramCounter].ParameterName = parmName
|
||||||
if qualType, ok := typobj["qualType"].(string); ok {
|
paramCounter++
|
||||||
parmType = qualType
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO fixup parameters
|
// TODO If this parameter is optional, expand it into multiple function overloads
|
||||||
// Reference -> pointer
|
|
||||||
// Remove const
|
|
||||||
// Remove extra () -- if there are more than expected, skip method with complex type
|
|
||||||
// If this parameter is optional, expand it into multiple function overloads
|
|
||||||
|
|
||||||
mm.Parameters = append(mm.Parameters, CppParameter{
|
|
||||||
ParameterName: parmName,
|
|
||||||
ParameterType: parmType,
|
|
||||||
})
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// Something else inside a declaration??
|
// Something else inside a declaration??
|
||||||
@ -177,3 +174,71 @@ nextMethod:
|
|||||||
|
|
||||||
return ret, nil // done
|
return ret, nil // done
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var ErrTooComplex error = errors.New("Type declaration is too complex to parse")
|
||||||
|
|
||||||
|
// parseTypeString converts a string like
|
||||||
|
// - `QString (const char *, const char *, int)`
|
||||||
|
// - `void (const QKeySequence \u0026)`
|
||||||
|
// into its (A) return type and (B) separate parameter types.
|
||||||
|
// These clang strings never contain the parameter's name, so the names here are
|
||||||
|
// not filled in.
|
||||||
|
func parseTypeString(typeString string) (CppParameter, []CppParameter, error) {
|
||||||
|
|
||||||
|
if strings.Contains(typeString, `::`) {
|
||||||
|
return CppParameter{}, nil, ErrTooComplex
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cut to exterior-most (, ) pair
|
||||||
|
opos := strings.Index(typeString, `(`)
|
||||||
|
epos := strings.LastIndex(typeString, `)`)
|
||||||
|
|
||||||
|
if opos == -1 || epos == -1 {
|
||||||
|
return CppParameter{}, nil, fmt.Errorf("Type string %q missing brackets")
|
||||||
|
}
|
||||||
|
|
||||||
|
returnType := parseSingleTypeString(strings.TrimSpace(typeString[0:opos]))
|
||||||
|
|
||||||
|
inner := typeString[opos+1 : epos]
|
||||||
|
|
||||||
|
// Should be no more brackets
|
||||||
|
if strings.ContainsAny(inner, `()`) {
|
||||||
|
return CppParameter{}, nil, ErrTooComplex
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parameters are separated by commas and nesting can not be possible
|
||||||
|
params := strings.Split(inner, `,`)
|
||||||
|
|
||||||
|
ret := make([]CppParameter, 0, len(params))
|
||||||
|
for _, p := range params {
|
||||||
|
|
||||||
|
insert := parseSingleTypeString(p)
|
||||||
|
|
||||||
|
if insert.ParameterType != "" {
|
||||||
|
ret = append(ret, insert)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return returnType, ret, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseSingleTypeString(p string) CppParameter {
|
||||||
|
|
||||||
|
tokens := strings.Split(strings.TrimSpace(p), " ")
|
||||||
|
insert := CppParameter{}
|
||||||
|
for _, tok := range tokens {
|
||||||
|
if tok == "const" {
|
||||||
|
insert.Const = true
|
||||||
|
} else if tok == "&" { // U+0026
|
||||||
|
insert.ByRef = true
|
||||||
|
} else if tok == "*" {
|
||||||
|
insert.Pointer = true
|
||||||
|
} else {
|
||||||
|
// Valid part of the type name
|
||||||
|
insert.ParameterType += " " + tok
|
||||||
|
}
|
||||||
|
}
|
||||||
|
insert.ParameterType = strings.TrimSpace(insert.ParameterType)
|
||||||
|
|
||||||
|
return insert
|
||||||
|
}
|
||||||
|
@ -6,7 +6,12 @@ import (
|
|||||||
|
|
||||||
type CppParameter struct {
|
type CppParameter struct {
|
||||||
ParameterName string
|
ParameterName string
|
||||||
ParameterType string
|
ParameterType string
|
||||||
|
Const bool
|
||||||
|
Pointer bool
|
||||||
|
ByRef bool
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type CppProperty struct {
|
type CppProperty struct {
|
||||||
@ -17,7 +22,7 @@ type CppProperty struct {
|
|||||||
|
|
||||||
type CppMethod struct {
|
type CppMethod struct {
|
||||||
MethodName string
|
MethodName string
|
||||||
ReturnType string
|
ReturnType CppParameter // Name not used
|
||||||
Parameters []CppParameter
|
Parameters []CppParameter
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user