miqt/cmd/genbindings/exceptions.go

293 lines
11 KiB
Go

package main
import (
"path/filepath"
"strings"
)
func InsertTypedefs() {
// Seed well-known typedefs
// QString is deleted from this binding
KnownTypedefs["QStringList"] = lookupResultTypedef{"qt", CppTypedef{"QStringList", parseSingleTypeString("QList<QString>")}}
// FIXME this isn't picked up automatically because QFile inherits QFileDevice and the name refers to its parent class
KnownTypedefs["QFile::FileTime"] = lookupResultTypedef{"qt", CppTypedef{"QFile::FileTime", parseSingleTypeString("QFileDevice::FileTime")}}
// n.b. Qt 5 only
KnownTypedefs["QLineF::IntersectionType"] = lookupResultTypedef{"qt", CppTypedef{"QLineF::IntersectionType", parseSingleTypeString("QLineF::IntersectType")}}
// Not sure the reason for this one
KnownTypedefs["QSocketDescriptor::DescriptorType"] = lookupResultTypedef{"qt", CppTypedef{"QSocketDescriptor::DescriptorType", parseSingleTypeString("QSocketNotifier::Type")}}
// QFile doesn't see QFileDevice parent class enum
KnownTypedefs["QFile::Permissions"] = lookupResultTypedef{"qt", CppTypedef{"QFile::Permissions", parseSingleTypeString("QFileDevice::Permissions")}}
KnownTypedefs["QFileDevice::Permissions"] = lookupResultTypedef{"qt", CppTypedef{"QFile::Permissions", parseSingleTypeString("QFlags<QFileDevice::Permission>")}}
}
func AllowHeader(fullpath string) bool {
fname := filepath.Base(fullpath)
if strings.HasSuffix(fname, `_impl.h`) {
return false // Not meant to be imported
}
fname_lc := strings.ToLower(fname)
if strings.Contains(fname_lc, `opengl`) || strings.Contains(fname_lc, `vulkan`) {
return false // Too hard
}
switch fname {
case "qatomic_bootstrap.h",
"qatomic_cxx11.h",
"qatomic_msvc.h",
"qgenericatomic.h", // Clang error
"qt_windows.h", // Clang error
"qmaccocoaviewcontainer_mac.h", // Needs NSView* headers. TODO allow with darwin build tag
"qmacnativewidget_mac.h", // Needs NSView* headers. TODO allow with darwin build tag
"qstring.h", // QString does not exist in this binding
"qbytearray.h", // QByteArray does not exist in this binding
"qlist.h", // QList does not exist in this binding
"qvector.h": // QVector does not exist in this binding
return false
}
return true
}
func ImportHeaderForClass(className string) bool {
if className[0] != 'Q' {
return false
}
// TODO this could be implict by checking if files exist in known header paths
if strings.HasPrefix(className, "QPlatform") {
// e.g. QPlatformPixmap, QPlatformWindow, QPlatformScreen
// These classes don't have a <> version to include
return false
}
switch className {
case "QGraphicsEffectSource", // e.g. qgraphicseffect.h
"QAbstractConcatenable", // qstringbuilder.h
"QTextEngine", // qtextlayout.h
"QText": // e.g. qtextcursor.h
return false
}
return true
}
func AllowClass(className string) bool {
if strings.HasSuffix(className, "Private") {
return false
}
if strings.Contains(className, "QPrivateSignal") {
return false
}
switch className {
case
"QTextStreamManipulator", // Only seems to contain garbage methods
"QException", // Extends std::exception, too hard
"QUnhandledException", // As above (child class)
"QItemSelection", // Extends a QList<>, too hard
"QXmlStreamAttributes", // Extends a QList<>, too hard
"QPolygon", "QPolygonF": // Extends a QVector<QPoint> template class, too hard
return false
}
return true
}
func AllowSignal(mm CppMethod) bool {
switch mm.MethodName {
case `metaObject`, `qt_metacast`:
return false
default:
return true
}
}
func AllowMethod(mm CppMethod) error {
for _, p := range mm.Parameters {
if strings.HasSuffix(p.ParameterType, "Private") {
return ErrTooComplex // Skip private type
}
}
if strings.HasSuffix(mm.ReturnType.ParameterType, "Private") {
return ErrTooComplex // Skip private type
}
if mm.IsReceiverMethod() {
// Non-projectable receiver pattern parameters
return ErrTooComplex
}
return nil // OK, allow
}
func CheckComplexity(p CppParameter, isReturnType bool) error {
if p.QMapOf() {
return ErrTooComplex // Example???
}
if p.QPairOf() {
return ErrTooComplex // e.g. QGradientStop
}
if t, ok := p.QSetOf(); ok {
if err := CheckComplexity(t, isReturnType); err != nil {
return err
}
}
if t, ok := p.QListOf(); ok {
if err := CheckComplexity(t, isReturnType); err != nil { // e.g. QGradientStops is a QVector<> (OK) of QGradientStop (not OK)
return err
}
}
if strings.Contains(p.ParameterType, "(*)") { // Function pointer.
return ErrTooComplex // e.g. QAccessible_InstallFactory
}
if strings.HasPrefix(p.ParameterType, "StringResult<") {
return ErrTooComplex // e.g. qcborstreamreader.h
}
if strings.HasPrefix(p.ParameterType, "QScopedPointer<") {
return ErrTooComplex // e.g. qbrush.h
}
if strings.HasPrefix(p.ParameterType, "QExplicitlySharedDataPointer<") {
return ErrTooComplex // e.g. qpicture.h
}
if strings.HasPrefix(p.ParameterType, "QSharedDataPointer<") {
return ErrTooComplex // e.g. qurlquery.h
}
if strings.HasPrefix(p.ParameterType, "QTypedArrayData<") {
return ErrTooComplex // e.g. qbitarray.h
}
if strings.HasPrefix(p.ParameterType, "QGenericMatrix<") {
return ErrTooComplex // e.g. qmatrix4x4.h
}
if strings.HasPrefix(p.ParameterType, "QUrlTwoFlags<") {
return ErrTooComplex // e.g. qurl.h
}
if strings.HasPrefix(p.ParameterType, "std::") {
// std::initializer e.g. qcborarray.h
// std::string QByteArray->toStdString(). There are QString overloads already
// std::nullptr_t Qcborstreamwriter
// std::chrono::nanoseconds QDeadlineTimer_RemainingTimeAsDuration
// std::seed_seq QRandom
return ErrTooComplex
}
if strings.Contains(p.ParameterType, `Iterator::value_type`) {
return ErrTooComplex // e.g. qcbormap
}
if strings.Contains(p.ParameterType, `::QPrivate`) {
return ErrTooComplex // e.g. QAbstractItemModel::QPrivateSignal
}
if strings.Contains(p.GetQtCppType().ParameterType, `::DataPtr`) {
return ErrTooComplex // e.g. QImage::data_ptr()
}
// Some QFoo constructors take a QFooPrivate
// QIcon also returns a QIconPrivate
if p.ParameterType[0] == 'Q' && strings.HasSuffix(p.ParameterType, "Private") {
return ErrTooComplex
}
// If any parameters are QString*, skip the method
// QDebug constructor
// QXmlStreamWriter constructor
// QFile::moveToTrash
// QLockFile::getLockInfo
// QTextDecoder::toUnicode
// QTextStream::readLineInto
// QFileDialog::getOpenFileName selectedFilter* param
if p.ParameterType == "QString" && p.Pointer && !isReturnType { // Out-parameters
return ErrTooComplex
}
// QBuffer can accept a raw pointer to an internal QByteArray, but that
// doesn't work when QByteArray is deleted
// QDataStream
if p.ParameterType == "QByteArray" && p.Pointer && !isReturnType {
return ErrTooComplex
}
if p.ParameterType == "QFormLayout::ItemRole" && p.Pointer && !isReturnType { // Out-parameters in QFormLayout
return ErrTooComplex
}
if p.Pointer && p.PointerCount >= 2 { // Out-parameters
if p.ParameterType != "char" {
return ErrTooComplex // e.g. QGraphicsItem_IsBlockedByModalPanel1
}
if p.ParameterType == "char" && p.ParameterName == "xpm" {
// Array parameters:
// - QPixmap and QImage ctors from an xpm char*[]
// TODO support these
return ErrTooComplex
}
}
switch p.ParameterType {
case
"QList<QVariant>", // e.g. QVariant constructor - this has a deleted copy-constructor so we can't get it over the CABI boundary by value
"QPolygon", "QPolygonF", // QPolygon extends a template type
"QGenericMatrix", "QMatrix3x3", // extends a template type
"QLatin1String", "QStringView", // e.g. QColor constructors and QColor::SetNamedColor() overloads. These are usually optional alternatives to QString
"QStringRef", // e.g. QLocale::toLongLong and similar overloads. As above
"qfloat16", // e.g. QDataStream - there is no such half-float type in C or Go
"char16_t", // e.g. QChar() constructor overload, just unnecessary
"char32_t", // e.g. QDebug().operator<< overload, unnecessary
"wchar_t", // e.g. qstringview.h overloads, unnecessary
"FILE", // e.g. qfile.h constructors
"qInternalCallback", // e.g. qnamespace.h
"QGraphicsEffectSource", // e.g. used by qgraphicseffect.h, but the definition is in ????
"QXmlStreamEntityDeclarations", // e.g. qxmlstream.h. The class definition was blacklisted for ???? reason so don't allow it as a parameter either
"QXmlStreamNamespaceDeclarations", // e.g. qxmlstream.h. As above
"QXmlStreamNotationDeclarations", // e.g. qxmlstream.h. As above
"QXmlStreamAttributes", // e.g. qxmlstream.h
"QtMsgType", // e.g. qdebug.h TODO Defined in qlogging.h, but omitted because it's predefined in qglobal.h, and our clangexec is too agressive
"QTextStreamFunction", // e.g. qdebug.h
"QFactoryInterface", // qfactoryinterface.h
"QItemSelection", // used by qabstractproxymodel.h, also blocked in AllowClass above, class extends a List<T>
"QTextStreamManipulator", // used by qdebug.h, also blocked in AllowClass above
"QException", // used by qfutureinterface.h, also blocked in AllowClass above
"QTextEngine", // used by qtextlayout.h, also blocked in ImportHeaderForClass above
"QVulkanInstance", // e.g. qwindow.h. Not tackling vulkan yet
"QPlatformNativeInterface", // e.g. QGuiApplication::platformNativeInterface(). Private type, could probably expose as uintptr. n.b. Changes in Qt6
"QPlatformBackingStore", // e.g. qbackingstore.h, as below
"QPlatformMenuBar", // e.g. qfutureinterface.h, as below
"QPlatformOffscreenSurface", // e.g. qoffscreensurface.h, as below
"QPlatformPixmap", // e.g. qpixmap.h. as below
"QPlatformScreen", // e.g. qscreen.h. as below
"QPlatformWindow", // e.g. qwindow.h, as below
"QPlatformSurface", // e.g. qsurface.h. as below
"QPlatformMenu": // e.g. QMenu_PlatformMenu. Defined in the QPA, could probably expose as uintptr
return ErrTooComplex
}
// Should be OK
return nil
}
// LinuxWindowsCompatCheck checks if the parameter is incompatible between the
// generated headers (generated on Linux) with other OSes such as Windows.
// These methods will be blocked on non-Linux OSes.
func LinuxWindowsCompatCheck(p CppParameter) bool {
if p.GetQtCppType().ParameterType == "Q_PID" {
return true // int64 on Linux, _PROCESS_INFORMATION* on Windows
}
if p.GetQtCppType().ParameterType == "QSocketDescriptor::DescriptorType" {
return true // uintptr_t-compatible on Linux, void* on Windows
}
return false
}