2024-08-06 01:03:23 +00:00
|
|
|
package main
|
|
|
|
|
2024-08-07 06:51:51 +00:00
|
|
|
import (
|
2024-08-18 03:27:03 +00:00
|
|
|
"regexp"
|
2024-08-07 06:51:51 +00:00
|
|
|
"strings"
|
|
|
|
)
|
|
|
|
|
2024-10-16 05:07:05 +00:00
|
|
|
type lookupResultClass struct {
|
|
|
|
PackageName string
|
|
|
|
}
|
|
|
|
|
|
|
|
type lookupResultTypedef struct {
|
|
|
|
PackageName string
|
|
|
|
Typedef CppTypedef
|
|
|
|
}
|
|
|
|
|
|
|
|
type lookupResultEnum struct {
|
|
|
|
PackageName string
|
|
|
|
Enum CppEnum
|
|
|
|
}
|
|
|
|
|
2024-08-26 10:48:37 +00:00
|
|
|
var (
|
2024-10-16 05:07:05 +00:00
|
|
|
KnownClassnames map[string]lookupResultClass // Entries of the form QFoo::Bar if it is an inner class
|
|
|
|
KnownTypedefs map[string]lookupResultTypedef
|
|
|
|
KnownEnums map[string]lookupResultEnum
|
2024-08-26 10:48:37 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
func init() {
|
2024-10-16 05:07:05 +00:00
|
|
|
KnownClassnames = make(map[string]lookupResultClass)
|
|
|
|
KnownTypedefs = make(map[string]lookupResultTypedef)
|
|
|
|
KnownEnums = make(map[string]lookupResultEnum)
|
2024-08-26 10:48:37 +00:00
|
|
|
}
|
|
|
|
|
2024-08-07 06:56:14 +00:00
|
|
|
type CppParameter struct {
|
2024-09-18 01:08:18 +00:00
|
|
|
ParameterName string
|
|
|
|
ParameterType string
|
|
|
|
Const bool
|
|
|
|
Pointer bool
|
|
|
|
PointerCount int
|
|
|
|
ByRef bool
|
|
|
|
Optional bool
|
|
|
|
|
|
|
|
QtCppOriginalType *CppParameter // If we rewrote QStringList->QList<String>, this field contains the original QStringList. Otherwise, it's blank
|
2024-08-26 10:49:33 +00:00
|
|
|
}
|
|
|
|
|
2024-09-18 00:11:48 +00:00
|
|
|
func (p *CppParameter) ApplyTypedef(matchedUnderlyingType CppParameter) {
|
2024-09-18 01:08:18 +00:00
|
|
|
if p.QtCppOriginalType == nil {
|
|
|
|
tmp := *p // Copy
|
|
|
|
p.QtCppOriginalType = &tmp // Overwrite once only, at the earliest base type
|
|
|
|
}
|
|
|
|
p.ParameterType = matchedUnderlyingType.ParameterType
|
2024-08-27 08:05:38 +00:00
|
|
|
|
|
|
|
// If this was a pointer to a typedef'd type, or a typedef of a pointer type, we need to preserve that
|
2024-09-18 00:11:48 +00:00
|
|
|
p.Const = p.Const || matchedUnderlyingType.Const
|
|
|
|
p.Pointer = p.Pointer || matchedUnderlyingType.Pointer
|
|
|
|
p.PointerCount += matchedUnderlyingType.PointerCount
|
|
|
|
p.ByRef = p.ByRef || matchedUnderlyingType.ByRef
|
|
|
|
p.Optional = p.Optional || matchedUnderlyingType.Optional
|
2024-08-26 10:49:33 +00:00
|
|
|
}
|
|
|
|
|
2024-09-14 06:26:59 +00:00
|
|
|
func (p *CppParameter) PointerTo() CppParameter {
|
|
|
|
ret := *p // Copy
|
|
|
|
ret.Pointer = true
|
|
|
|
ret.PointerCount++
|
|
|
|
return ret
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *CppParameter) ConstCast(isConst bool) CppParameter {
|
|
|
|
ret := *p // Copy
|
|
|
|
ret.Const = isConst
|
|
|
|
return ret
|
|
|
|
}
|
|
|
|
|
2024-09-18 01:08:18 +00:00
|
|
|
func (p *CppParameter) GetQtCppType() *CppParameter {
|
|
|
|
if p.QtCppOriginalType != nil {
|
2024-09-18 00:11:48 +00:00
|
|
|
return p.QtCppOriginalType
|
2024-08-26 10:48:37 +00:00
|
|
|
}
|
|
|
|
|
2024-09-18 01:08:18 +00:00
|
|
|
return p
|
2024-08-26 10:48:37 +00:00
|
|
|
}
|
|
|
|
|
2024-09-19 07:39:17 +00:00
|
|
|
func (p CppParameter) QFlagsOf() (CppParameter, bool) {
|
|
|
|
|
|
|
|
if strings.HasPrefix(p.ParameterType, `QFlags<`) {
|
|
|
|
ret := parseSingleTypeString(p.ParameterType[7 : len(p.ParameterType)-1])
|
|
|
|
ret.ParameterName = p.ParameterName + "_qf"
|
|
|
|
return ret, true
|
2024-09-18 00:11:48 +00:00
|
|
|
}
|
|
|
|
|
2024-09-19 07:39:17 +00:00
|
|
|
if under := p.QtCppOriginalType; under != nil {
|
|
|
|
if strings.HasPrefix(under.ParameterType, `QFlags<`) {
|
|
|
|
ret := parseSingleTypeString(under.ParameterType[7 : len(under.ParameterType)-1])
|
|
|
|
ret.ParameterName = under.ParameterName + "_qf"
|
|
|
|
return ret, true
|
|
|
|
}
|
2024-08-29 05:16:36 +00:00
|
|
|
}
|
2024-09-19 07:39:17 +00:00
|
|
|
|
|
|
|
return CppParameter{}, false
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p CppParameter) IsFlagType() bool {
|
|
|
|
_, ok := p.QFlagsOf()
|
|
|
|
return ok
|
2024-08-29 05:16:36 +00:00
|
|
|
}
|
|
|
|
|
2024-08-08 07:06:14 +00:00
|
|
|
func (p CppParameter) QtClassType() bool {
|
2024-08-26 10:48:37 +00:00
|
|
|
|
2024-08-28 05:59:34 +00:00
|
|
|
// Maybe if it's an inner class
|
|
|
|
if _, ok := KnownClassnames[p.ParameterType]; ok {
|
|
|
|
return true
|
2024-08-26 10:48:37 +00:00
|
|
|
}
|
|
|
|
|
2024-08-29 05:17:12 +00:00
|
|
|
if p.ParameterType == "QString" {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
2024-08-28 05:59:34 +00:00
|
|
|
return false
|
2024-08-08 07:06:14 +00:00
|
|
|
}
|
|
|
|
|
2024-09-04 06:54:10 +00:00
|
|
|
func (p CppParameter) IsKnownEnum() bool {
|
|
|
|
_, ok := KnownEnums[p.ParameterType]
|
|
|
|
return ok
|
|
|
|
}
|
|
|
|
|
2024-08-11 04:37:18 +00:00
|
|
|
func (p CppParameter) QListOf() (CppParameter, bool) {
|
|
|
|
if strings.HasPrefix(p.ParameterType, "QList<") && strings.HasSuffix(p.ParameterType, `>`) {
|
2024-09-14 06:26:59 +00:00
|
|
|
ret := parseSingleTypeString(p.ParameterType[6 : len(p.ParameterType)-1])
|
|
|
|
ret.ParameterName = p.ParameterName + "_lv"
|
|
|
|
return ret, true
|
2024-08-11 04:37:18 +00:00
|
|
|
}
|
|
|
|
|
2024-08-16 23:29:31 +00:00
|
|
|
if strings.HasPrefix(p.ParameterType, "QVector<") && strings.HasSuffix(p.ParameterType, `>`) {
|
2024-09-14 06:26:59 +00:00
|
|
|
ret := parseSingleTypeString(p.ParameterType[8 : len(p.ParameterType)-1])
|
|
|
|
ret.ParameterName = p.ParameterName + "_vv"
|
|
|
|
return ret, true
|
2024-08-16 23:29:31 +00:00
|
|
|
}
|
|
|
|
|
2024-08-11 04:37:18 +00:00
|
|
|
return CppParameter{}, false
|
|
|
|
}
|
|
|
|
|
2024-08-15 07:53:01 +00:00
|
|
|
func (p CppParameter) QMapOf() bool {
|
|
|
|
return strings.HasPrefix(p.ParameterType, `QMap<`) ||
|
|
|
|
strings.HasPrefix(p.ParameterType, `QHash<`) // TODO support this
|
|
|
|
}
|
|
|
|
|
2024-08-17 02:11:11 +00:00
|
|
|
func (p CppParameter) QPairOf() bool {
|
|
|
|
return strings.HasPrefix(p.ParameterType, `QPair<`) // TODO support this
|
|
|
|
}
|
|
|
|
|
2024-09-17 09:48:26 +00:00
|
|
|
func (p CppParameter) QSetOf() (CppParameter, bool) {
|
|
|
|
if strings.HasPrefix(p.ParameterType, `QSet<`) {
|
|
|
|
ret := parseSingleTypeString(p.ParameterType[5 : len(p.ParameterType)-1])
|
|
|
|
ret.ParameterName = p.ParameterName + "_sv"
|
|
|
|
return ret, true
|
|
|
|
}
|
|
|
|
|
|
|
|
return CppParameter{}, false
|
2024-08-19 07:15:05 +00:00
|
|
|
}
|
|
|
|
|
2024-08-14 06:33:47 +00:00
|
|
|
func (p CppParameter) IntType() bool {
|
2024-08-25 03:31:21 +00:00
|
|
|
|
2024-09-17 21:35:53 +00:00
|
|
|
if p.IsKnownEnum() {
|
2024-08-25 05:50:14 +00:00
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
2024-08-14 06:33:47 +00:00
|
|
|
switch p.ParameterType {
|
2024-08-15 07:49:05 +00:00
|
|
|
case "int", "unsigned int", "uint",
|
2024-10-11 05:37:38 +00:00
|
|
|
"short", "unsigned short", "ushort", "qint16", "quint16", "uint16_t", "int16_t",
|
2024-08-15 07:49:05 +00:00
|
|
|
"qint8", "quint8",
|
2024-08-29 07:01:12 +00:00
|
|
|
"unsigned char", "signed char", "uchar",
|
2024-10-11 05:37:38 +00:00
|
|
|
"long", "unsigned long", "ulong", "qint32", "quint32", "int32_t", "uint32_t",
|
2024-08-15 07:49:05 +00:00
|
|
|
"longlong", "ulonglong", "qlonglong", "qulonglong", "qint64", "quint64", "int64_t", "uint64_t", "long long", "unsigned long long",
|
2024-08-25 03:31:21 +00:00
|
|
|
"qintptr", "quintptr", "uintptr_t", "intptr_t",
|
2024-08-23 23:45:36 +00:00
|
|
|
"qsizetype", "size_t",
|
2024-09-18 00:11:48 +00:00
|
|
|
"QIntegerForSizeof<void *>::Unsigned",
|
2024-09-18 01:43:25 +00:00
|
|
|
"QIntegerForSizeof<void *>::Signed",
|
2024-10-08 05:21:59 +00:00
|
|
|
"QIntegerForSizeof<std::size_t>::Signed",
|
2024-08-26 10:51:21 +00:00
|
|
|
"qptrdiff", "ptrdiff_t",
|
2024-08-14 06:33:47 +00:00
|
|
|
"double", "float", "qreal":
|
|
|
|
return true
|
2024-08-25 03:31:21 +00:00
|
|
|
|
|
|
|
case "char":
|
|
|
|
// Only count char as an integer type with cast assertions if it's
|
|
|
|
// not possibly a char* string in disguise
|
|
|
|
// (However, unsigned chars are always like ints)
|
|
|
|
return !p.Pointer
|
|
|
|
|
2024-08-14 06:33:47 +00:00
|
|
|
default:
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-08-07 06:56:14 +00:00
|
|
|
type CppProperty struct {
|
|
|
|
PropertyName string
|
|
|
|
PropertyType string
|
|
|
|
Visibility string
|
2024-08-06 01:03:23 +00:00
|
|
|
}
|
|
|
|
|
2024-08-07 06:56:14 +00:00
|
|
|
type CppMethod struct {
|
2024-08-22 07:20:12 +00:00
|
|
|
MethodName string // C++ method name, unless OverrideMethodName is set, in which case a nice alternative name
|
|
|
|
OverrideMethodName string // C++ method name, present only if we changed the target
|
2024-08-09 23:45:19 +00:00
|
|
|
ReturnType CppParameter // Name not used
|
|
|
|
Parameters []CppParameter
|
2024-08-18 03:24:04 +00:00
|
|
|
IsStatic bool
|
2024-08-18 03:56:48 +00:00
|
|
|
IsSignal bool
|
2024-08-28 06:47:23 +00:00
|
|
|
IsConst bool
|
2024-09-07 03:25:25 +00:00
|
|
|
HiddenParams []CppParameter // Populated if there is an overload with more parameters
|
2024-09-01 05:50:58 +00:00
|
|
|
LinuxOnly bool
|
2024-08-06 01:03:23 +00:00
|
|
|
}
|
|
|
|
|
2024-09-11 06:04:32 +00:00
|
|
|
func (m CppMethod) CppCallTarget() string {
|
|
|
|
if m.OverrideMethodName != "" {
|
|
|
|
return m.OverrideMethodName
|
|
|
|
}
|
|
|
|
return m.MethodName
|
|
|
|
}
|
|
|
|
|
2024-09-11 06:06:17 +00:00
|
|
|
func (m *CppMethod) Rename(newName string) {
|
|
|
|
if m.OverrideMethodName == "" {
|
|
|
|
m.OverrideMethodName = m.MethodName
|
|
|
|
} else {
|
|
|
|
// If it was already set, we're already a level of overload resolution deep - preserve it
|
|
|
|
}
|
|
|
|
|
|
|
|
m.MethodName = newName
|
|
|
|
}
|
|
|
|
|
2024-08-18 03:57:29 +00:00
|
|
|
func IsArgcArgv(params []CppParameter, pos int) bool {
|
|
|
|
// Check if the arguments starting at position=pos are the argc/argv pattern.
|
2024-08-17 02:10:59 +00:00
|
|
|
// QApplication/QGuiApplication constructors are the only expected example of this.
|
2024-08-18 03:57:29 +00:00
|
|
|
return (len(params) > pos+1 &&
|
|
|
|
params[pos].ParameterName == "argc" &&
|
|
|
|
params[pos].ParameterType == "int" &&
|
|
|
|
params[pos].ByRef &&
|
|
|
|
params[pos+1].ParameterName == "argv" &&
|
2024-08-28 06:22:05 +00:00
|
|
|
params[pos+1].ParameterType == "char") &&
|
|
|
|
params[pos+1].Pointer &&
|
|
|
|
params[pos+1].PointerCount == 2
|
2024-08-18 03:57:29 +00:00
|
|
|
}
|
|
|
|
|
2024-08-18 03:57:40 +00:00
|
|
|
func IsReceiverMethod(params []CppParameter, pos int) bool {
|
|
|
|
// Check if the arguments starting at position=pos are the receiver/member pattern.
|
|
|
|
// QMenu->addAction is the main example of this
|
|
|
|
return (len(params) > pos+1 &&
|
|
|
|
params[pos].ParameterName == "receiver" &&
|
|
|
|
params[pos].ParameterType == "QObject" &&
|
|
|
|
params[pos].Pointer &&
|
|
|
|
params[pos+1].ParameterName == "member" &&
|
|
|
|
params[pos+1].ParameterType == "char" &&
|
|
|
|
params[pos+1].Pointer)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (nm CppMethod) IsReceiverMethod() bool {
|
|
|
|
// Returns true if any of the parameters use the receiever-method pattern
|
|
|
|
for i := 0; i < len(nm.Parameters); i++ {
|
|
|
|
if IsReceiverMethod(nm.Parameters, i) {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
2024-08-17 02:10:59 +00:00
|
|
|
}
|
|
|
|
|
2024-08-07 06:56:14 +00:00
|
|
|
func (nm CppMethod) SafeMethodName() string {
|
2024-08-18 07:01:23 +00:00
|
|
|
|
|
|
|
tmp := nm.MethodName
|
|
|
|
|
|
|
|
// Strip redundant Qt prefix, we know these are all Qt functions
|
|
|
|
if strings.HasPrefix(tmp, "qt_") {
|
|
|
|
tmp = tmp[3:]
|
|
|
|
}
|
|
|
|
|
2024-08-07 06:51:51 +00:00
|
|
|
// Operator-overload methods have names not representable in binding
|
|
|
|
// languages. Replace more specific cases first
|
|
|
|
replacer := strings.NewReplacer(
|
|
|
|
|
|
|
|
`==`, `Equal`,
|
2024-08-14 06:26:51 +00:00
|
|
|
`!=`, `NotEqual`,
|
2024-08-07 06:51:51 +00:00
|
|
|
`>=`, `GreaterOrEqual`,
|
|
|
|
`<=`, `LesserOrEqual`,
|
|
|
|
`=`, `Assign`,
|
2024-08-15 07:51:58 +00:00
|
|
|
|
|
|
|
`<<`, `ShiftLeft`, // Qt classes use it more for stream functions e.g. in QDataStream
|
|
|
|
`>>`, `ShiftRight`,
|
2024-08-07 06:51:51 +00:00
|
|
|
`>`, `Greater`,
|
|
|
|
`<`, `Lesser`,
|
|
|
|
|
|
|
|
`+`, `Plus`,
|
|
|
|
`-`, `Minus`,
|
|
|
|
`*`, `Multiply`,
|
|
|
|
`/`, `Divide`,
|
|
|
|
`%`, `Modulo`,
|
|
|
|
|
|
|
|
`&&`, `LogicalAnd`,
|
|
|
|
`||`, `LogicalOr`,
|
|
|
|
`!`, `Not`,
|
|
|
|
`&`, `BitwiseAnd`,
|
|
|
|
`|`, `BitwiseOr`,
|
|
|
|
`~`, `BitwiseXor`,
|
|
|
|
`^`, `BitwiseNot`,
|
|
|
|
|
|
|
|
`->`, `PointerDereference`,
|
|
|
|
`[]`, `Subscript`,
|
|
|
|
`()`, `Call`,
|
|
|
|
)
|
2024-08-18 07:01:23 +00:00
|
|
|
tmp = replacer.Replace(tmp)
|
2024-08-08 05:51:46 +00:00
|
|
|
|
|
|
|
// Also make the first letter uppercase so it becomes public in Go
|
2024-08-18 03:27:03 +00:00
|
|
|
tmp = titleCase(tmp)
|
|
|
|
|
|
|
|
// Also replace any underscore_case with CamelCase
|
|
|
|
tmp = regexp.MustCompile(`_([a-z])`).ReplaceAllStringFunc(tmp, func(match string) string { return strings.ToUpper(match[1:]) })
|
|
|
|
|
|
|
|
return tmp
|
2024-08-07 06:51:51 +00:00
|
|
|
}
|
|
|
|
|
2024-08-26 10:51:21 +00:00
|
|
|
type CppEnumEntry struct {
|
|
|
|
EntryName string
|
|
|
|
EntryValue string
|
|
|
|
}
|
|
|
|
|
|
|
|
type CppEnum struct {
|
2024-09-04 06:54:10 +00:00
|
|
|
EnumName string
|
2024-09-17 21:35:53 +00:00
|
|
|
UnderlyingType CppParameter
|
2024-09-04 06:54:10 +00:00
|
|
|
Entries []CppEnumEntry
|
2024-08-26 10:51:21 +00:00
|
|
|
}
|
|
|
|
|
2024-08-07 06:56:14 +00:00
|
|
|
type CppClass struct {
|
|
|
|
ClassName string
|
2024-08-10 00:53:26 +00:00
|
|
|
Abstract bool
|
2024-08-07 06:56:14 +00:00
|
|
|
Ctors []CppMethod // only use the parameters
|
2024-08-10 00:54:26 +00:00
|
|
|
Inherits []string // other class names
|
2024-08-07 06:56:14 +00:00
|
|
|
Methods []CppMethod
|
|
|
|
Props []CppProperty
|
2024-08-20 08:10:57 +00:00
|
|
|
CanDelete bool
|
2024-08-25 07:08:28 +00:00
|
|
|
|
2024-08-26 10:45:52 +00:00
|
|
|
ChildTypedefs []CppTypedef
|
2024-08-25 07:08:28 +00:00
|
|
|
ChildClassdefs []CppClass
|
2024-08-26 10:51:21 +00:00
|
|
|
ChildEnums []CppEnum
|
2024-08-06 01:03:23 +00:00
|
|
|
}
|
|
|
|
|
2024-08-14 06:26:42 +00:00
|
|
|
type CppTypedef struct {
|
2024-08-16 23:25:54 +00:00
|
|
|
Alias string
|
2024-08-26 10:49:33 +00:00
|
|
|
UnderlyingType CppParameter
|
2024-08-14 06:26:42 +00:00
|
|
|
}
|
|
|
|
|
2024-08-07 06:56:14 +00:00
|
|
|
type CppParsedHeader struct {
|
2024-08-26 10:45:11 +00:00
|
|
|
Filename string
|
2024-08-14 06:26:42 +00:00
|
|
|
Typedefs []CppTypedef
|
2024-08-26 10:51:21 +00:00
|
|
|
Enums []CppEnum
|
2024-08-14 06:26:42 +00:00
|
|
|
Classes []CppClass
|
2024-08-06 01:03:23 +00:00
|
|
|
}
|
2024-08-19 07:11:36 +00:00
|
|
|
|
|
|
|
func (c CppParsedHeader) Empty() bool {
|
|
|
|
return len(c.Typedefs) == 0 &&
|
2024-10-08 05:22:14 +00:00
|
|
|
len(c.Enums) == 0 &&
|
2024-08-19 07:11:36 +00:00
|
|
|
len(c.Classes) == 0
|
|
|
|
}
|
2024-08-27 07:12:08 +00:00
|
|
|
|
|
|
|
func (c *CppParsedHeader) AddContentFrom(other *CppParsedHeader) {
|
|
|
|
c.Classes = append(c.Classes, other.Classes...)
|
|
|
|
c.Enums = append(c.Enums, other.Enums...)
|
|
|
|
c.Typedefs = append(c.Typedefs, other.Typedefs...)
|
|
|
|
}
|