diff options
| author | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2019-11-22 12:20:42 +0100 |
|---|---|---|
| committer | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2019-11-22 12:20:42 +0100 |
| commit | 5a74c902555ed6bce4b45889adfdaa1123b64ace (patch) | |
| tree | a378fa998f66d80293deb1b237ed83738efd4cde | |
| parent | 259c8245ef6d9c2d6f0e1abd0983338d87ddb09a (diff) | |
| parent | 1323cd8ac47060bb70e54103c0a4e18d3886e703 (diff) | |
Merge remote-tracking branch 'origin/5.14' into 5.15
Change-Id: Id29d1bc3d4b1430afebaa8115049df482892f33a
44 files changed, 744 insertions, 387 deletions
diff --git a/sources/pyside2/doc/CMakeLists.txt b/sources/pyside2/doc/CMakeLists.txt index 9d5a5a0a8..ee0fc0c51 100644 --- a/sources/pyside2/doc/CMakeLists.txt +++ b/sources/pyside2/doc/CMakeLists.txt @@ -96,7 +96,6 @@ add_custom_target(qdoc SOURCE "pyside.qdocconf") add_custom_target(apidoc - COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}/rst COMMAND ${SHIBOKEN_PYTHON_INTERPRETER} ${SPHINX_BUILD} -b html ${CMAKE_CURRENT_BINARY_DIR}/rst html #copying shiboken2 (including ApiExtractor) doc htmls COMMENT "Copying over the Shiboken2 doc HTMLs..." @@ -110,6 +109,7 @@ add_custom_target(apidoc configure_file("conf.py.in" "rst/conf.py" @ONLY) add_custom_target("docrsts" + COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}/rst COMMAND Shiboken2::shiboken2 --generator-set=qtdoc ${docHeader} --include-paths="${QT_INCLUDE_DIR}${PATH_SEP}${pyside2_SOURCE_DIR}${PATH_SEP}${TS_ROOT}" --api-version=${SUPPORTED_QT_VERSION} @@ -117,9 +117,9 @@ add_custom_target("docrsts" --library-source-dir=${QT_SRC_DIR} --documentation-data-dir=${DOC_DATA_DIR}/webxml --output-directory=${CMAKE_CURRENT_BINARY_DIR}/rst - --documentation-code-snippets-dir=${CMAKE_CURRENT_SOURCE_DIR}/codesnippets/doc/src/snippets${PATH_SEP}${CMAKE_CURRENT_SOURCE_DIR}/codesnippets/examples - --documentation-extra-sections-dir=${CMAKE_CURRENT_SOURCE_DIR}/extras - --additional-documentation=${CMAKE_CURRENT_LIST_DIR}/additionaldocs.lst + --documentation-code-snippets-dir=${CMAKE_CURRENT_BINARY_DIR}/rst/codesnippets/doc/src/snippets${PATH_SEP}${CMAKE_CURRENT_BINARY_DIR}/rst/codesnippets/examples + --documentation-extra-sections-dir=${CMAKE_CURRENT_BINARY_DIR}/rst/extras + --additional-documentation=${CMAKE_CURRENT_BINARY_DIR}/rst/additionaldocs.lst ${CMAKE_CURRENT_BINARY_DIR}/typesystem_doc.xml WORKING_DIRECTORY ${${module}_SOURCE_DIR} COMMENT "Running generator to generate documentation..." diff --git a/sources/pyside2/doc/extras/PySide.QtCore.ClassInfo.rst b/sources/pyside2/doc/extras/QtCore.ClassInfo.rst index d2267be9c..d2267be9c 100644 --- a/sources/pyside2/doc/extras/PySide.QtCore.ClassInfo.rst +++ b/sources/pyside2/doc/extras/QtCore.ClassInfo.rst diff --git a/sources/pyside2/doc/extras/PySide.QtCore.Signal.rst b/sources/pyside2/doc/extras/QtCore.Signal.rst index 16c640831..16c640831 100644 --- a/sources/pyside2/doc/extras/PySide.QtCore.Signal.rst +++ b/sources/pyside2/doc/extras/QtCore.Signal.rst diff --git a/sources/pyside2/doc/extras/PySide.QtCore.Slot.rst b/sources/pyside2/doc/extras/QtCore.Slot.rst index 3bc64c03a..3bc64c03a 100644 --- a/sources/pyside2/doc/extras/PySide.QtCore.Slot.rst +++ b/sources/pyside2/doc/extras/QtCore.Slot.rst diff --git a/sources/pyside2/doc/extras/PySide.QtCore.rst b/sources/pyside2/doc/extras/QtCore.rst index d3277a418..d3277a418 100644 --- a/sources/pyside2/doc/extras/PySide.QtCore.rst +++ b/sources/pyside2/doc/extras/QtCore.rst diff --git a/sources/pyside2/doc/extras/PySide.QtGui.rst b/sources/pyside2/doc/extras/QtGui.rst index e16329c38..e16329c38 100644 --- a/sources/pyside2/doc/extras/PySide.QtGui.rst +++ b/sources/pyside2/doc/extras/QtGui.rst diff --git a/sources/pyside2/doc/extras/PySide.QtHelp.rst b/sources/pyside2/doc/extras/QtHelp.rst index 239f4faa6..239f4faa6 100644 --- a/sources/pyside2/doc/extras/PySide.QtHelp.rst +++ b/sources/pyside2/doc/extras/QtHelp.rst diff --git a/sources/pyside2/doc/extras/PySide.QtMultimedia.rst b/sources/pyside2/doc/extras/QtMultimedia.rst index 5088db4d0..5088db4d0 100644 --- a/sources/pyside2/doc/extras/PySide.QtMultimedia.rst +++ b/sources/pyside2/doc/extras/QtMultimedia.rst diff --git a/sources/pyside2/doc/extras/PySide.QtNetwork.rst b/sources/pyside2/doc/extras/QtNetwork.rst index 07303b157..07303b157 100644 --- a/sources/pyside2/doc/extras/PySide.QtNetwork.rst +++ b/sources/pyside2/doc/extras/QtNetwork.rst diff --git a/sources/pyside2/doc/extras/PySide.QtOpenGL.rst b/sources/pyside2/doc/extras/QtOpenGL.rst index 38783d9fd..38783d9fd 100644 --- a/sources/pyside2/doc/extras/PySide.QtOpenGL.rst +++ b/sources/pyside2/doc/extras/QtOpenGL.rst diff --git a/sources/pyside2/doc/extras/PySide.QtScript.rst b/sources/pyside2/doc/extras/QtScript.rst index 8ce7681ec..8ce7681ec 100644 --- a/sources/pyside2/doc/extras/PySide.QtScript.rst +++ b/sources/pyside2/doc/extras/QtScript.rst diff --git a/sources/pyside2/doc/extras/PySide.QtScriptTools.rst b/sources/pyside2/doc/extras/QtScriptTools.rst index a54ed914b..a54ed914b 100644 --- a/sources/pyside2/doc/extras/PySide.QtScriptTools.rst +++ b/sources/pyside2/doc/extras/QtScriptTools.rst diff --git a/sources/pyside2/doc/extras/PySide.QtSql.rst b/sources/pyside2/doc/extras/QtSql.rst index fcdd6ba02..fcdd6ba02 100644 --- a/sources/pyside2/doc/extras/PySide.QtSql.rst +++ b/sources/pyside2/doc/extras/QtSql.rst diff --git a/sources/pyside2/doc/extras/PySide.QtSvg.rst b/sources/pyside2/doc/extras/QtSvg.rst index 7817e532f..7817e532f 100644 --- a/sources/pyside2/doc/extras/PySide.QtSvg.rst +++ b/sources/pyside2/doc/extras/QtSvg.rst diff --git a/sources/pyside2/doc/extras/PySide.QtTest.rst b/sources/pyside2/doc/extras/QtTest.rst index 0b89a22d4..0b89a22d4 100644 --- a/sources/pyside2/doc/extras/PySide.QtTest.rst +++ b/sources/pyside2/doc/extras/QtTest.rst diff --git a/sources/pyside2/doc/extras/PySide.QtUiTools.rst b/sources/pyside2/doc/extras/QtUiTools.rst index 553224527..553224527 100644 --- a/sources/pyside2/doc/extras/PySide.QtUiTools.rst +++ b/sources/pyside2/doc/extras/QtUiTools.rst diff --git a/sources/pyside2/doc/extras/PySide.QtWebKit.rst b/sources/pyside2/doc/extras/QtWebKit.rst index 58f9230a7..58f9230a7 100644 --- a/sources/pyside2/doc/extras/PySide.QtWebKit.rst +++ b/sources/pyside2/doc/extras/QtWebKit.rst diff --git a/sources/pyside2/doc/extras/PySide.QtXml.rst b/sources/pyside2/doc/extras/QtXml.rst index 4b48ef21e..4b48ef21e 100644 --- a/sources/pyside2/doc/extras/PySide.QtXml.rst +++ b/sources/pyside2/doc/extras/QtXml.rst diff --git a/sources/pyside2/doc/extras/PySide.QtXmlPatterns.rst b/sources/pyside2/doc/extras/QtXmlPatterns.rst index 99254ad62..99254ad62 100644 --- a/sources/pyside2/doc/extras/PySide.QtXmlPatterns.rst +++ b/sources/pyside2/doc/extras/QtXmlPatterns.rst diff --git a/sources/pyside2/tests/QtGui/pyside_reload_test.py b/sources/pyside2/tests/QtGui/pyside_reload_test.py index c3e8c218e..cd045047a 100644 --- a/sources/pyside2/tests/QtGui/pyside_reload_test.py +++ b/sources/pyside2/tests/QtGui/pyside_reload_test.py @@ -41,8 +41,8 @@ sys.path.append(workdir) def reload_module(moduleName): if py3k.IS_PY3K: - import imp - imp.reload(moduleName) + import importlib + importlib.reload(moduleName) else: reload(moduleName) @@ -53,8 +53,8 @@ def increment_module_value(): modfile.close() if not sys.dont_write_bytecode: if py3k.IS_PY3K: - import imp - cacheFile = imp.cache_from_source(dst) + import importlib.util + cacheFile = importlib.util.cache_from_source(dst) else: cacheFile = dst + 'c' os.remove(cacheFile) diff --git a/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp b/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp index 73a887577..12dafb47d 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp +++ b/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp @@ -836,13 +836,15 @@ AbstractMetaEnum *AbstractMetaBuilderPrivate::traverseEnum(const EnumModelItem & QString qualifiedName = enumItem->qualifiedName().join(colonColon()); TypeEntry *typeEntry = nullptr; + const TypeEntry *enclosingTypeEntry = enclosing ? enclosing->typeEntry() : nullptr; if (enumItem->accessPolicy() == CodeModel::Private) { QStringList names = enumItem->qualifiedName(); const QString &enumName = names.constLast(); QString nspace; if (names.size() > 1) nspace = QStringList(names.mid(0, names.size() - 1)).join(colonColon()); - typeEntry = new EnumTypeEntry(nspace, enumName, QVersionNumber(0, 0)); + typeEntry = new EnumTypeEntry(nspace, enumName, QVersionNumber(0, 0), + enclosingTypeEntry); TypeDatabase::instance()->addType(typeEntry); } else if (enumItem->enumKind() != AnonymousEnum) { typeEntry = TypeDatabase::instance()->findType(qualifiedName); @@ -862,8 +864,8 @@ AbstractMetaEnum *AbstractMetaBuilderPrivate::traverseEnum(const EnumModelItem & QString enumName = enumItem->name(); QString className; - if (enclosing) - className = enclosing->typeEntry()->qualifiedCppName(); + if (enclosingTypeEntry) + className = enclosingTypeEntry->qualifiedCppName(); QString rejectReason; if (TypeDatabase::instance()->isEnumRejected(className, enumName, &rejectReason)) { @@ -963,7 +965,8 @@ AbstractMetaEnum *AbstractMetaBuilderPrivate::traverseEnum(const EnumModelItem & } EnumValueTypeEntry *enumValue = new EnumValueTypeEntry(prefix + e->name(), e->stringValue(), - enumTypeEntry, enumTypeEntry->version()); + enumTypeEntry, enumTypeEntry->version(), + enumTypeEntry->parent()); TypeDatabase::instance()->addType(enumValue); if (e->value().isNullValue()) enumTypeEntry->setNullValue(enumValue); @@ -1097,9 +1100,11 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseClass(const FileModelItem TemplateParameterList template_parameters = classItem->templateParameters(); QVector<TypeEntry *> template_args; template_args.clear(); + auto argumentParent = metaClass->typeEntry()->typeSystemTypeEntry(); for (int i = 0; i < template_parameters.size(); ++i) { const TemplateParameterModelItem ¶m = template_parameters.at(i); - TemplateArgumentEntry *param_type = new TemplateArgumentEntry(param->name(), type->version()); + auto param_type = new TemplateArgumentEntry(param->name(), type->version(), + argumentParent); param_type->setOrdinal(i); template_args.append(param_type); } @@ -2251,7 +2256,9 @@ AbstractMetaType *AbstractMetaBuilderPrivate::translateTypeStatic(const TypeInfo if (_ok) arrayType->setArrayElementCount(int(elems)); } - arrayType->setTypeEntry(new ArrayTypeEntry(elementType->typeEntry() , elementType->typeEntry()->version())); + auto elementTypeEntry = elementType->typeEntry(); + arrayType->setTypeEntry(new ArrayTypeEntry(elementTypeEntry, elementTypeEntry->version(), + elementTypeEntry->parent())); arrayType->decideUsagePattern(); elementType = arrayType; @@ -2675,7 +2682,8 @@ bool AbstractMetaBuilderPrivate::inheritTemplate(AbstractMetaClass *subclass, t = typeDb->findType(typeName); if (!t) { t = new EnumValueTypeEntry(typeName, typeName, nullptr, - QVersionNumber(0, 0)); + QVersionNumber(0, 0), + subclass->typeEntry()->parent()); t->setCodeGeneration(0); typeDb->addType(t); } diff --git a/sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h b/sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h index 30df236d6..b381a62cd 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h +++ b/sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h @@ -37,6 +37,7 @@ #include <QSet> #include <QFileInfo> +#include <QVector> class TypeDatabase; @@ -187,7 +188,7 @@ public: QHash<const TypeEntry *, AbstractMetaEnum *> m_enums; - QList<NamespaceModelItem> m_scopes; + QVector<NamespaceModelItem> m_scopes; QSet<AbstractMetaClass *> m_setupInheritanceDone; diff --git a/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.cpp b/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.cpp index 8d1b4debf..a5b153499 100644 --- a/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.cpp +++ b/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.cpp @@ -40,7 +40,7 @@ #include <QtCore/QStack> #include <QtCore/QVector> -#include <string.h> +#include <cstring> #include <ctype.h> #if QT_VERSION < 0x050800 @@ -202,6 +202,8 @@ public: template <class Item> void qualifyTypeDef(const CXCursor &typeRefCursor, const QSharedPointer<Item> &item) const; + bool visitHeader(const char *cFileName) const; + BaseVisitor *m_baseVisitor; CodeModel *m_model; @@ -665,31 +667,62 @@ Builder::~Builder() delete d; } -static inline bool compareHeaderName(const char *haystack, const char *needle) +static const char *cBaseName(const char *fileName) { - const char *lastSlash = strrchr(haystack, '/'); + const char *lastSlash = std::strrchr(fileName, '/'); #ifdef Q_OS_WIN if (lastSlash == nullptr) - lastSlash = strrchr(haystack, '\\'); + lastSlash = std::strrchr(fileName, '\\'); #endif - if (lastSlash == nullptr) - lastSlash = haystack; - else - ++lastSlash; + return lastSlash != nullptr ? (lastSlash + 1) : fileName; +} + +static inline bool cCompareFileName(const char *f1, const char *f2) +{ #ifdef Q_OS_WIN - return _stricmp(lastSlash, needle) == 0; + return _stricmp(f1, f2) == 0; #else - return strcmp(lastSlash, needle) == 0; + return std::strcmp(f1, f2) == 0; #endif } #ifdef Q_OS_UNIX -static bool cStringStartsWith(const char *prefix, const char *str) +template<size_t N> +static bool cStringStartsWith(const char *str, const char (&prefix)[N]) { - return strncmp(prefix, str, strlen(prefix)) == 0; + return std::strncmp(prefix, str, N - 1) == 0; } #endif +bool BuilderPrivate::visitHeader(const char *cFileName) const +{ + // Resolve OpenGL typedefs although the header is considered a system header. + const char *baseName = cBaseName(cFileName); + if (cCompareFileName(baseName, "gl.h")) + return true; +#if defined(Q_OS_LINUX) || defined(Q_OS_MACOS) + if (cStringStartsWith(cFileName, "/usr/include/stdint.h")) + return true; +#endif +#ifdef Q_OS_LINUX + if (cStringStartsWith(cFileName, "/usr/include/stdlib.h") + || cStringStartsWith(cFileName, "/usr/include/sys/types.h")) { + return true; + } +#endif // Q_OS_LINUX +#ifdef Q_OS_MACOS + // Parse the following system headers to get the correct typdefs for types like + // int32_t, which are used in the macOS implementation of OpenGL framework. + if (cCompareFileName(baseName, "gltypes.h") + || cStringStartsWith(cFileName, "/usr/include/_types") + || cStringStartsWith(cFileName, "/usr/include/_types") + || cStringStartsWith(cFileName, "/usr/include/sys/_types")) { + return true; + } +#endif // Q_OS_MACOS + return false; +} + bool Builder::visitLocation(const CXSourceLocation &location) const { if (clang_Location_isInSystemHeader(location) == 0) @@ -701,28 +734,12 @@ bool Builder::visitLocation(const CXSourceLocation &location) const clang_getExpansionLocation(location, &file, &line, &column, &offset); const CXString cxFileName = clang_getFileName(file); // Has been observed to be 0 for invalid locations + bool result = false; if (const char *cFileName = clang_getCString(cxFileName)) { - // Resolve OpenGL typedefs although the header is considered a system header. - const bool visitHeader = compareHeaderName(cFileName, "gl.h") -#if defined(Q_OS_LINUX) || defined(Q_OS_MACOS) - || cStringStartsWith("/usr/include/stdint.h", cFileName) -#endif -#if defined(Q_OS_LINUX) - || cStringStartsWith("/usr/include/stdlib.h", cFileName) - || cStringStartsWith("/usr/include/sys/types.h", cFileName) -#elif defined(Q_OS_MACOS) - // Parse the following system headers to get the correct typdefs for types like - // int32_t, which are used in the macOS implementation of OpenGL framework. - || compareHeaderName(cFileName, "gltypes.h") - || cStringStartsWith("/usr/include/_types", cFileName) - || cStringStartsWith("/usr/include/sys/_types", cFileName) -#endif - ; + result = d->visitHeader(cFileName); clang_disposeString(cxFileName); - if (visitHeader) - return true; } - return false; + return result; } FileModelItem Builder::dom() const diff --git a/sources/shiboken2/ApiExtractor/header_paths.h b/sources/shiboken2/ApiExtractor/header_paths.h index 0c25702ef..c9b5144c8 100644 --- a/sources/shiboken2/ApiExtractor/header_paths.h +++ b/sources/shiboken2/ApiExtractor/header_paths.h @@ -30,7 +30,7 @@ #define HEADER_PATHS_H #include <QByteArray> -#include <QList> +#include <QVector> #include <QString> enum class HeaderType @@ -67,6 +67,6 @@ public: } }; -using HeaderPaths = QList<HeaderPath>; +using HeaderPaths = QVector<HeaderPath>; #endif // HEADER_PATHS_H diff --git a/sources/shiboken2/ApiExtractor/messages.cpp b/sources/shiboken2/ApiExtractor/messages.cpp index 5b3a57fcc..b60e1f73b 100644 --- a/sources/shiboken2/ApiExtractor/messages.cpp +++ b/sources/shiboken2/ApiExtractor/messages.cpp @@ -328,6 +328,18 @@ QString msgConversionTypesDiffer(const QString &varType, const QString &conversi return result; } +QString msgCannotFindSmartPointer(const QString &instantiationType, + const AbstractMetaClassList &pointers) +{ + QString result; + QTextStream str(&result); + str << "Unable to find smart pointer type for " << instantiationType << " (known types:"; + for (auto t : pointers) + str << ' ' << t->fullName(); + str << ")."; + return result; +} + // main.cpp QString msgLeftOverArguments(const QMap<QString, QString> &remainingArgs) @@ -463,6 +475,11 @@ QString msgInvalidRegularExpression(const QString &pattern, const QString &why) return QLatin1String("Invalid pattern \"") + pattern + QLatin1String("\": ") + why; } +QString msgNoRootTypeSystemEntry() +{ + return QLatin1String("Type system entry appears out of order, there does not seem to be a root type system element."); +} + // qtdocgenerator.cpp QString msgTagWarning(const QXmlStreamReader &reader, const QString &context, diff --git a/sources/shiboken2/ApiExtractor/messages.h b/sources/shiboken2/ApiExtractor/messages.h index 2fee0de8f..5bbd7ba58 100644 --- a/sources/shiboken2/ApiExtractor/messages.h +++ b/sources/shiboken2/ApiExtractor/messages.h @@ -117,6 +117,9 @@ QString msgCannotUseEnumAsInt(const QString &name); QString msgConversionTypesDiffer(const QString &varType, const QString &conversionType); +QString msgCannotFindSmartPointer(const QString &instantiationType, + const AbstractMetaClassList &pointers); + QString msgLeftOverArguments(const QMap<QString, QString> &remainingArgs); QString msgInvalidVersion(const QString &package, const QString &version); @@ -128,6 +131,8 @@ QString msgExtendingNamespaceRequiresPattern(const QString &name); QString msgInvalidRegularExpression(const QString &pattern, const QString &why); +QString msgNoRootTypeSystemEntry(); + QString msgCyclicDependency(const QString &funcName, const QString &graphName, const QVector<const AbstractMetaFunction *> &involvedConversions); diff --git a/sources/shiboken2/ApiExtractor/typesystem.cpp b/sources/shiboken2/ApiExtractor/typesystem.cpp index a1b98cd45..a5572354f 100644 --- a/sources/shiboken2/ApiExtractor/typesystem.cpp +++ b/sources/shiboken2/ApiExtractor/typesystem.cpp @@ -43,8 +43,9 @@ static QString strings_jobject = QLatin1String("jobject"); static inline QString callOperator() { return QStringLiteral("operator()"); } -PrimitiveTypeEntry::PrimitiveTypeEntry(const QString &name, const QVersionNumber &vr) : - TypeEntry(name, PrimitiveType, vr), +PrimitiveTypeEntry::PrimitiveTypeEntry(const QString &name, const QVersionNumber &vr, + const TypeEntry *parent) : + TypeEntry(name, PrimitiveType, vr, parent), m_preferredTargetLangType(true) { } @@ -80,6 +81,12 @@ CodeSnipList TypeEntry::codeSnips() const return m_codeSnips; } +void TypeEntry::addExtraInclude(const Include &newInclude) +{ + if (!m_extraIncludes.contains(newInclude)) + m_extraIncludes.append(newInclude); +} + QString Modification::accessModifierString() const { if (isPrivate()) return QLatin1String("private"); @@ -611,8 +618,9 @@ AddedFunction::TypeInfo AddedFunction::TypeInfo::fromSignature(const QString& si } ComplexTypeEntry::ComplexTypeEntry(const QString &name, TypeEntry::Type t, - const QVersionNumber &vr) : - TypeEntry(name, t, vr), + const QVersionNumber &vr, + const TypeEntry *parent) : + TypeEntry(name, t, vr, parent), m_qualifiedCppName(name), m_polymorphicBase(false), m_genericClass(false), @@ -711,10 +719,12 @@ bool TypeEntry::isCppPrimitive() const return typeName.contains(QLatin1Char(' ')) || primitiveCppTypes().contains(typeName); } -TypeEntry::TypeEntry(const QString &name, TypeEntry::Type t, const QVersionNumber &vr) : +TypeEntry::TypeEntry(const QString &name, TypeEntry::Type t, const QVersionNumber &vr, + const TypeEntry *parent) : + m_parent(parent), m_name(name), - m_type(t), - m_version(vr) + m_version(vr), + m_type(t) { } @@ -723,6 +733,15 @@ TypeEntry::~TypeEntry() delete m_customConversion; } +const TypeSystemTypeEntry *TypeEntry::typeSystemTypeEntry() const +{ + for (auto e = this; e; e = e->parent()) { + if (e->type() == TypeEntry::TypeSystemType) + return static_cast<const TypeSystemTypeEntry *>(e); + } + return nullptr; +} + bool TypeEntry::hasCustomConversion() const { return m_customConversion != nullptr; @@ -754,8 +773,9 @@ void TypeEntry::useAsTypedef(const TypeEntry *source) TypeEntry::TypeEntry(const TypeEntry &) = default; -TypeSystemTypeEntry::TypeSystemTypeEntry(const QString &name, const QVersionNumber &vr) : - TypeEntry(name, TypeSystemType, vr) +TypeSystemTypeEntry::TypeSystemTypeEntry(const QString &name, const QVersionNumber &vr, + const TypeEntry *parent) : + TypeEntry(name, TypeSystemType, vr, parent) { } @@ -767,7 +787,7 @@ TypeEntry *TypeSystemTypeEntry::clone() const TypeSystemTypeEntry::TypeSystemTypeEntry(const TypeSystemTypeEntry &) = default; VoidTypeEntry::VoidTypeEntry() : - TypeEntry(QLatin1String("void"), VoidType, QVersionNumber(0, 0)) + TypeEntry(QLatin1String("void"), VoidType, QVersionNumber(0, 0), nullptr) { } @@ -779,7 +799,7 @@ TypeEntry *VoidTypeEntry::clone() const VoidTypeEntry::VoidTypeEntry(const VoidTypeEntry &) = default; VarargsTypeEntry::VarargsTypeEntry() : - TypeEntry(QLatin1String("..."), VarargsType, QVersionNumber(0, 0)) + TypeEntry(QLatin1String("..."), VarargsType, QVersionNumber(0, 0), nullptr) { } @@ -790,8 +810,9 @@ TypeEntry *VarargsTypeEntry::clone() const VarargsTypeEntry::VarargsTypeEntry(const VarargsTypeEntry &) = default; -TemplateArgumentEntry::TemplateArgumentEntry(const QString &name, const QVersionNumber &vr) : - TypeEntry(name, TemplateArgumentType, vr) +TemplateArgumentEntry::TemplateArgumentEntry(const QString &name, const QVersionNumber &vr, + const TypeEntry *parent) : + TypeEntry(name, TemplateArgumentType, vr, parent) { } @@ -802,8 +823,9 @@ TypeEntry *TemplateArgumentEntry::clone() const TemplateArgumentEntry::TemplateArgumentEntry(const TemplateArgumentEntry &) = default; -ArrayTypeEntry::ArrayTypeEntry(const TypeEntry *nested_type, const QVersionNumber &vr) : - TypeEntry(QLatin1String("Array"), ArrayType, vr), +ArrayTypeEntry::ArrayTypeEntry(const TypeEntry *nested_type, const QVersionNumber &vr, + const TypeEntry *parent) : + TypeEntry(QLatin1String("Array"), ArrayType, vr, parent), m_nestedType(nested_type) { Q_ASSERT(m_nestedType); @@ -829,9 +851,10 @@ TypeEntry *ArrayTypeEntry::clone() const ArrayTypeEntry::ArrayTypeEntry(const ArrayTypeEntry &) = default; EnumTypeEntry::EnumTypeEntry(const QString &nspace, const QString &enumName, - const QVersionNumber &vr) : + const QVersionNumber &vr, + const TypeEntry *parent) : TypeEntry(nspace.isEmpty() ? enumName : nspace + QLatin1String("::") + enumName, - EnumType, vr), + EnumType, vr, parent), m_qualifier(nspace), m_targetLangName(enumName) { @@ -844,8 +867,8 @@ QString EnumTypeEntry::targetLangName() const EnumValueTypeEntry::EnumValueTypeEntry(const QString &name, const QString &value, const EnumTypeEntry *enclosingEnum, - const QVersionNumber &vr) : - TypeEntry(name, TypeEntry::EnumValue, vr), + const QVersionNumber &vr, const TypeEntry *parent) : + TypeEntry(name, TypeEntry::EnumValue, vr, parent), m_value(value), m_enclosingEnum(enclosingEnum) { @@ -858,16 +881,17 @@ TypeEntry *EnumValueTypeEntry::clone() const EnumValueTypeEntry::EnumValueTypeEntry(const EnumValueTypeEntry &) = default; -FlagsTypeEntry::FlagsTypeEntry(const QString &name, const QVersionNumber &vr) : - TypeEntry(name, FlagsType, vr) +FlagsTypeEntry::FlagsTypeEntry(const QString &name, const QVersionNumber &vr, + const TypeEntry *parent) : + TypeEntry(name, FlagsType, vr, parent) { } /* A typedef entry allows for specifying template specializations in the * typesystem XML file. */ TypedefEntry::TypedefEntry(const QString &name, const QString &sourceType, - const QVersionNumber &vr) : - ComplexTypeEntry(name, TypedefType, vr), + const QVersionNumber &vr, const TypeEntry *parent) : + ComplexTypeEntry(name, TypedefType, vr, parent), m_sourceType(sourceType) { } @@ -880,8 +904,9 @@ TypeEntry *TypedefEntry::clone() const TypedefEntry::TypedefEntry(const TypedefEntry &) = default; ContainerTypeEntry::ContainerTypeEntry(const QString &name, Type type, - const QVersionNumber &vr) : - ComplexTypeEntry(name, ContainerType, vr), + const QVersionNumber &vr, + const TypeEntry *parent) : + ComplexTypeEntry(name, ContainerType, vr, parent), m_type(type) { setCodeGeneration(GenerateForSubclass); @@ -891,8 +916,8 @@ SmartPointerTypeEntry::SmartPointerTypeEntry(const QString &name, const QString &getterName, const QString &smartPointerType, const QString &refCountMethodName, - const QVersionNumber &vr) : - ComplexTypeEntry(name, SmartPointerType, vr), + const QVersionNumber &vr, const TypeEntry *parent) : + ComplexTypeEntry(name, SmartPointerType, vr, parent), m_getterName(getterName), m_smartPointerType(smartPointerType), m_refCountMethodName(refCountMethodName) @@ -906,8 +931,9 @@ TypeEntry *SmartPointerTypeEntry::clone() const SmartPointerTypeEntry::SmartPointerTypeEntry(const SmartPointerTypeEntry &) = default; -NamespaceTypeEntry::NamespaceTypeEntry(const QString &name, const QVersionNumber &vr) : - ComplexTypeEntry(name, NamespaceType, vr) +NamespaceTypeEntry::NamespaceTypeEntry(const QString &name, const QVersionNumber &vr, + const TypeEntry *parent) : + ComplexTypeEntry(name, NamespaceType, vr, parent) { } @@ -931,8 +957,9 @@ bool NamespaceTypeEntry::matchesFile(const QString &needle) const return m_filePattern.match(needle).hasMatch(); } -ValueTypeEntry::ValueTypeEntry(const QString &name, const QVersionNumber &vr) : - ComplexTypeEntry(name, BasicValueType, vr) +ValueTypeEntry::ValueTypeEntry(const QString &name, const QVersionNumber &vr, + const TypeEntry *parent) : + ComplexTypeEntry(name, BasicValueType, vr, parent) { } @@ -953,8 +980,9 @@ TypeEntry *ValueTypeEntry::clone() const ValueTypeEntry::ValueTypeEntry(const ValueTypeEntry &) = default; -ValueTypeEntry::ValueTypeEntry(const QString &name, Type t, const QVersionNumber &vr) : - ComplexTypeEntry(name, t, vr) +ValueTypeEntry::ValueTypeEntry(const QString &name, Type t, const QVersionNumber &vr, + const TypeEntry *parent) : + ComplexTypeEntry(name, t, vr, parent) { } @@ -1092,8 +1120,9 @@ void CustomConversion::TargetToNativeConversion::setConversion(const QString& co m_d->conversion = conversion; } -InterfaceTypeEntry::InterfaceTypeEntry(const QString &name, const QVersionNumber &vr) : - ComplexTypeEntry(name, InterfaceType, vr) +InterfaceTypeEntry::InterfaceTypeEntry(const QString &name, const QVersionNumber &vr, + const TypeEntry *parent) : + ComplexTypeEntry(name, InterfaceType, vr, parent) { } @@ -1116,8 +1145,9 @@ TypeEntry *InterfaceTypeEntry::clone() const InterfaceTypeEntry::InterfaceTypeEntry(const InterfaceTypeEntry &) = default; FunctionTypeEntry::FunctionTypeEntry(const QString &name, const QString &signature, - const QVersionNumber &vr) : - TypeEntry(name, FunctionType, vr) + const QVersionNumber &vr, + const TypeEntry *parent) : + TypeEntry(name, FunctionType, vr, parent) { addSignature(signature); } @@ -1129,8 +1159,9 @@ TypeEntry *FunctionTypeEntry::clone() const FunctionTypeEntry::FunctionTypeEntry(const FunctionTypeEntry &) = default; -ObjectTypeEntry::ObjectTypeEntry(const QString &name, const QVersionNumber &vr) - : ComplexTypeEntry(name, ObjectType, vr) +ObjectTypeEntry::ObjectTypeEntry(const QString &name, const QVersionNumber &vr, + const TypeEntry *parent) + : ComplexTypeEntry(name, ObjectType, vr, parent) { } diff --git a/sources/shiboken2/ApiExtractor/typesystem.h b/sources/shiboken2/ApiExtractor/typesystem.h index 48733053d..6d7a9d450 100644 --- a/sources/shiboken2/ApiExtractor/typesystem.h +++ b/sources/shiboken2/ApiExtractor/typesystem.h @@ -543,6 +543,7 @@ private: }; class CustomConversion; +class TypeSystemTypeEntry; class TypeEntry { @@ -591,7 +592,8 @@ public: }; Q_ENUM(CodeGeneration) - explicit TypeEntry(const QString &name, Type t, const QVersionNumber &vr); + explicit TypeEntry(const QString &name, Type t, const QVersionNumber &vr, + const TypeEntry *parent); virtual ~TypeEntry(); @@ -599,6 +601,11 @@ public: { return m_type; } + + const TypeEntry *parent() const { return m_parent; } + void setParent(const TypeEntry *p) { m_parent = p; } + const TypeSystemTypeEntry *typeSystemTypeEntry() const; + bool isPrimitive() const { return m_type == PrimitiveType; @@ -836,13 +843,7 @@ public: { m_extraIncludes = includes; } - void addExtraInclude(const Include &include) - { - if (!m_includesUsed.value(include.name(), false)) { - m_extraIncludes << include; - m_includesUsed[include.name()] = true; - } - } + void addExtraInclude(const Include &newInclude); Include include() const { @@ -905,29 +906,30 @@ protected: TypeEntry(const TypeEntry &); private: + const TypeEntry *m_parent; QString m_name; QString m_targetLangPackage; - Type m_type; - uint m_codeGeneration = GenerateAll; CustomFunction m_customConstructor; CustomFunction m_customDestructor; CodeSnipList m_codeSnips; DocModificationList m_docModifications; IncludeList m_extraIncludes; Include m_include; - QHash<QString, bool> m_includesUsed; QString m_conversionRule; - bool m_stream = false; QVersionNumber m_version; CustomConversion *m_customConversion = nullptr; + uint m_codeGeneration = GenerateAll; int m_revision = 0; int m_sbkIndex = 0; + Type m_type; + bool m_stream = false; }; class TypeSystemTypeEntry : public TypeEntry { public: - explicit TypeSystemTypeEntry(const QString &name, const QVersionNumber &vr); + explicit TypeSystemTypeEntry(const QString &name, const QVersionNumber &vr, + const TypeEntry *parent); TypeEntry *clone() const override; @@ -960,7 +962,8 @@ protected: class TemplateArgumentEntry : public TypeEntry { public: - explicit TemplateArgumentEntry(const QString &name, const QVersionNumber &vr); + explicit TemplateArgumentEntry(const QString &name, const QVersionNumber &vr, + const TypeEntry *parent); int ordinal() const { @@ -983,7 +986,8 @@ private: class ArrayTypeEntry : public TypeEntry { public: - explicit ArrayTypeEntry(const TypeEntry *nested_type, const QVersionNumber &vr); + explicit ArrayTypeEntry(const TypeEntry *nested_type, const QVersionNumber &vr, + const TypeEntry *parent); void setNestedTypeEntry(TypeEntry *nested) { @@ -1010,7 +1014,8 @@ private: class PrimitiveTypeEntry : public TypeEntry { public: - explicit PrimitiveTypeEntry(const QString &name, const QVersionNumber &vr); + explicit PrimitiveTypeEntry(const QString &name, const QVersionNumber &vr, + const TypeEntry *parent); QString targetLangName() const override; void setTargetLangName(const QString &targetLangName) @@ -1090,7 +1095,8 @@ class EnumTypeEntry : public TypeEntry { public: explicit EnumTypeEntry(const QString &nspace, const QString &enumName, - const QVersionNumber &vr); + const QVersionNumber &vr, + const TypeEntry *parent); QString targetLangName() const override; QString targetLangQualifier() const; @@ -1156,7 +1162,10 @@ private: class EnumValueTypeEntry : public TypeEntry { public: - explicit EnumValueTypeEntry(const QString& name, const QString& value, const EnumTypeEntry* enclosingEnum, const QVersionNumber &vr); + explicit EnumValueTypeEntry(const QString& name, const QString& value, + const EnumTypeEntry* enclosingEnum, + const QVersionNumber &vr, + const TypeEntry *parent); QString value() const { return m_value; } const EnumTypeEntry* enclosingEnum() const { return m_enclosingEnum; } @@ -1174,7 +1183,8 @@ private: class FlagsTypeEntry : public TypeEntry { public: - explicit FlagsTypeEntry(const QString &name, const QVersionNumber &vr); + explicit FlagsTypeEntry(const QString &name, const QVersionNumber &vr, + const TypeEntry *parent); QString qualifiedTargetLangName() const override; QString targetLangName() const override; @@ -1233,7 +1243,8 @@ public: Unknown }; - explicit ComplexTypeEntry(const QString &name, Type t, const QVersionNumber &vr); + explicit ComplexTypeEntry(const QString &name, Type t, const QVersionNumber &vr, + const TypeEntry *parent); bool isComplex() const override; @@ -1434,7 +1445,8 @@ class TypedefEntry : public ComplexTypeEntry public: explicit TypedefEntry(const QString &name, const QString &sourceType, - const QVersionNumber &vr); + const QVersionNumber &vr, + const TypeEntry *parent); QString sourceType() const { return m_sourceType; } void setSourceType(const QString &s) { m_sourceType =s; } @@ -1480,7 +1492,8 @@ public: }; Q_ENUM(Type) - explicit ContainerTypeEntry(const QString &name, Type type, const QVersionNumber &vr); + explicit ContainerTypeEntry(const QString &name, Type type, const QVersionNumber &vr, + const TypeEntry *parent); Type type() const { @@ -1510,7 +1523,8 @@ public: const QString &getterName, const QString &smartPointerType, const QString &refCountMethodName, - const QVersionNumber &vr); + const QVersionNumber &vr, + const TypeEntry *parent); QString getter() const { @@ -1536,7 +1550,8 @@ private: class NamespaceTypeEntry : public ComplexTypeEntry { public: - explicit NamespaceTypeEntry(const QString &name, const QVersionNumber &vr); + explicit NamespaceTypeEntry(const QString &name, const QVersionNumber &vr, + const TypeEntry *parent); TypeEntry *clone() const override; @@ -1566,7 +1581,8 @@ private: class ValueTypeEntry : public ComplexTypeEntry { public: - explicit ValueTypeEntry(const QString &name, const QVersionNumber &vr); + explicit ValueTypeEntry(const QString &name, const QVersionNumber &vr, + const TypeEntry *parent); bool isValue() const override; @@ -1575,14 +1591,16 @@ public: TypeEntry *clone() const override; protected: - explicit ValueTypeEntry(const QString &name, Type t, const QVersionNumber &vr); + explicit ValueTypeEntry(const QString &name, Type t, const QVersionNumber &vr, + const TypeEntry *parent); ValueTypeEntry(const ValueTypeEntry &); }; class InterfaceTypeEntry : public ComplexTypeEntry { public: - explicit InterfaceTypeEntry(const QString &name, const QVersionNumber &vr); + explicit InterfaceTypeEntry(const QString &name, const QVersionNumber &vr, + const TypeEntry *parent); static QString interfaceName(const QString &name) { @@ -1615,7 +1633,8 @@ class FunctionTypeEntry : public TypeEntry { public: explicit FunctionTypeEntry(const QString& name, const QString& signature, - const QVersionNumber &vr); + const QVersionNumber &vr, + const TypeEntry *parent); void addSignature(const QString& signature) { m_signatures << signature; @@ -1643,7 +1662,8 @@ private: class ObjectTypeEntry : public ComplexTypeEntry { public: - explicit ObjectTypeEntry(const QString &name, const QVersionNumber &vr); + explicit ObjectTypeEntry(const QString &name, const QVersionNumber &vr, + const TypeEntry *parent); InterfaceTypeEntry *designatedInterface() const override; void setDesignatedInterface(InterfaceTypeEntry *entry) diff --git a/sources/shiboken2/ApiExtractor/typesystemparser.cpp b/sources/shiboken2/ApiExtractor/typesystemparser.cpp index 5440de5c0..6ecdf1dc9 100644 --- a/sources/shiboken2/ApiExtractor/typesystemparser.cpp +++ b/sources/shiboken2/ApiExtractor/typesystemparser.cpp @@ -1040,6 +1040,19 @@ static QString checkSignatureError(const QString& signature, const QString& tag) return QString(); } +inline const TypeEntry *TypeSystemParser::currentParentTypeEntry() const +{ + return m_current ? m_current->entry : nullptr; +} + +bool TypeSystemParser::checkRootElement() +{ + const bool ok = currentParentTypeEntry() != nullptr; + if (!ok) + m_error = msgNoRootTypeSystemEntry(); + return ok; +} + void TypeSystemParser::applyCommonAttributes(TypeEntry *type, QXmlStreamAttributes *attributes) const { type->setCodeGeneration(m_generate); @@ -1057,7 +1070,11 @@ FlagsTypeEntry * QXmlStreamAttributes *attributes) { - FlagsTypeEntry *ftype = new FlagsTypeEntry(QLatin1String("QFlags<") + name + QLatin1Char('>'), since); + if (!checkRootElement()) + return nullptr; + auto ftype = new FlagsTypeEntry(QLatin1String("QFlags<") + name + QLatin1Char('>'), + since, + currentParentTypeEntry()->typeSystemTypeEntry()); ftype->setOriginator(enumEntry); ftype->setTargetLangPackage(enumEntry->targetLangPackage()); // Try to get the guess the qualified flag name @@ -1096,6 +1113,8 @@ SmartPointerTypeEntry * const QString &name, const QVersionNumber &since, QXmlStreamAttributes *attributes) { + if (!checkRootElement()) + return nullptr; QString smartPointerType; QString getter; QString refCountMethodName; @@ -1138,7 +1157,8 @@ SmartPointerTypeEntry * return nullptr; } - auto *type = new SmartPointerTypeEntry(name, getter, smartPointerType, refCountMethodName, since); + auto *type = new SmartPointerTypeEntry(name, getter, smartPointerType, + refCountMethodName, since, currentParentTypeEntry()); applyCommonAttributes(type, attributes); return type; } @@ -1148,7 +1168,9 @@ PrimitiveTypeEntry * const QString &name, const QVersionNumber &since, QXmlStreamAttributes *attributes) { - auto *type = new PrimitiveTypeEntry(name, since); + if (!checkRootElement()) + return nullptr; + auto *type = new PrimitiveTypeEntry(name, since, currentParentTypeEntry()); applyCommonAttributes(type, attributes); for (int i = attributes->size() - 1; i >= 0; --i) { const QStringRef name = attributes->at(i).qualifiedName(); @@ -1181,6 +1203,8 @@ ContainerTypeEntry * const QString &name, const QVersionNumber &since, QXmlStreamAttributes *attributes) { + if (!checkRootElement()) + return nullptr; const int typeIndex = indexOfAttribute(*attributes, u"type"); if (typeIndex == -1) { m_error = QLatin1String("no 'type' attribute specified"); @@ -1192,7 +1216,7 @@ ContainerTypeEntry * m_error = QLatin1String("there is no container of type ") + typeName.toString(); return nullptr; } - auto *type = new ContainerTypeEntry(name, containerType, since); + auto *type = new ContainerTypeEntry(name, containerType, since, currentParentTypeEntry()); applyCommonAttributes(type, attributes); return type; } @@ -1202,6 +1226,8 @@ EnumTypeEntry * const QString &fullName, const QVersionNumber &since, QXmlStreamAttributes *attributes) { + if (!checkRootElement()) + return nullptr; QString scope; QString name = fullName; const int sep = fullName.lastIndexOf(colonColon()); @@ -1209,7 +1235,7 @@ EnumTypeEntry * scope = fullName.left(sep); name = fullName.right(fullName.size() - sep - 2); } - auto *entry = new EnumTypeEntry(scope, name, since); + auto *entry = new EnumTypeEntry(scope, name, since, currentParentTypeEntry()); applyCommonAttributes(entry, attributes); entry->setTargetLangPackage(m_defaultPackage); @@ -1247,7 +1273,9 @@ ObjectTypeEntry * const QString &name, const QVersionNumber &since, QXmlStreamAttributes *attributes) { - auto *otype = new ObjectTypeEntry(name, since); + if (!checkRootElement()) + return nullptr; + auto *otype = new ObjectTypeEntry(name, since, currentParentTypeEntry()); applyCommonAttributes(otype, attributes); QString targetLangName = name; bool generate = true; @@ -1261,8 +1289,8 @@ ObjectTypeEntry * } } - InterfaceTypeEntry *itype = - new InterfaceTypeEntry(InterfaceTypeEntry::interfaceName(targetLangName), since); + auto itype = new InterfaceTypeEntry(InterfaceTypeEntry::interfaceName(targetLangName), + since, currentParentTypeEntry()); if (generate) itype->setCodeGeneration(m_generate); @@ -1279,7 +1307,9 @@ NamespaceTypeEntry * const QString &name, const QVersionNumber &since, QXmlStreamAttributes *attributes) { - QScopedPointer<NamespaceTypeEntry> result(new NamespaceTypeEntry(name, since)); + if (!checkRootElement()) + return nullptr; + QScopedPointer<NamespaceTypeEntry> result(new NamespaceTypeEntry(name, since, currentParentTypeEntry())); applyCommonAttributes(result.data(), attributes); applyComplexTypeAttributes(reader, result.data(), attributes); for (int i = attributes->size() - 1; i >= 0; --i) { @@ -1320,7 +1350,9 @@ ValueTypeEntry * const QString &name, const QVersionNumber &since, QXmlStreamAttributes *attributes) { - auto *typeEntry = new ValueTypeEntry(name, since); + if (!checkRootElement()) + return nullptr; + auto *typeEntry = new ValueTypeEntry(name, since, currentParentTypeEntry()); applyCommonAttributes(typeEntry, attributes); const int defaultCtIndex = indexOfAttribute(*attributes, u"default-constructor"); @@ -1334,6 +1366,8 @@ FunctionTypeEntry * const QString &name, const QVersionNumber &since, QXmlStreamAttributes *attributes) { + if (!checkRootElement()) + return nullptr; const int signatureIndex = indexOfAttribute(*attributes, signatureAttribute()); if (signatureIndex == -1) { m_error = msgMissingAttribute(signatureAttribute()); @@ -1345,7 +1379,7 @@ FunctionTypeEntry * TypeEntry *existingType = m_database->findType(name); if (!existingType) { - auto *result = new FunctionTypeEntry(name, signature, since); + auto *result = new FunctionTypeEntry(name, signature, since, currentParentTypeEntry()); applyCommonAttributes(result, attributes); return result; } @@ -1366,6 +1400,8 @@ TypedefEntry * const QVersionNumber &since, QXmlStreamAttributes *attributes) { + if (!checkRootElement()) + return nullptr; if (m_current && m_current->type != StackElement::Root && m_current->type != StackElement::NamespaceTypeEntry) { m_error = QLatin1String("typedef entries must be nested in namespaces or type system."); @@ -1377,7 +1413,7 @@ TypedefEntry * return nullptr; } const QString sourceType = attributes->takeAt(sourceIndex).value().toString(); - auto result = new TypedefEntry(name, sourceType, since); + auto result = new TypedefEntry(name, sourceType, since, currentParentTypeEntry()); applyCommonAttributes(result, attributes); return result; } @@ -1618,8 +1654,10 @@ TypeSystemTypeEntry *TypeSystemParser::parseRootElement(const QXmlStreamReader & auto *moduleEntry = const_cast<TypeSystemTypeEntry *>(m_database->findTypeSystemType(m_defaultPackage)); const bool add = moduleEntry == nullptr; - if (add) - moduleEntry = new TypeSystemTypeEntry(m_defaultPackage, since); + if (add) { + moduleEntry = new TypeSystemTypeEntry(m_defaultPackage, since, + currentParentTypeEntry()); + } moduleEntry->setCodeGeneration(m_generate); if ((m_generate == TypeEntry::GenerateForSubclass || @@ -2691,7 +2729,9 @@ bool TypeSystemParser::startElement(const QXmlStreamReader &reader) switch (element->type) { case StackElement::CustomTypeEntry: - element->entry = new TypeEntry(name, TypeEntry::CustomType, since); + if (!checkRootElement()) + return false; + element->entry = new TypeEntry(name, TypeEntry::CustomType, since, m_current->entry); break; case StackElement::PrimitiveTypeEntry: element->entry = parsePrimitiveTypeEntry(reader, name, since, &attributes); @@ -2745,7 +2785,9 @@ bool TypeSystemParser::startElement(const QXmlStreamReader &reader) return false; break; case StackElement::ObjectTypeEntry: - element->entry = new ObjectTypeEntry(name, since); + if (!checkRootElement()) + return false; + element->entry = new ObjectTypeEntry(name, since, currentParentTypeEntry()); applyCommonAttributes(element->entry, &attributes); applyComplexTypeAttributes(reader, static_cast<ComplexTypeEntry *>(element->entry), &attributes); break; diff --git a/sources/shiboken2/ApiExtractor/typesystemparser.h b/sources/shiboken2/ApiExtractor/typesystemparser.h index aaf22353e..afe68a689 100644 --- a/sources/shiboken2/ApiExtractor/typesystemparser.h +++ b/sources/shiboken2/ApiExtractor/typesystemparser.h @@ -162,6 +162,8 @@ private: bool importFileElement(const QXmlStreamAttributes &atts); + const TypeEntry *currentParentTypeEntry() const; + bool checkRootElement(); void applyCommonAttributes(TypeEntry *type, QXmlStreamAttributes *attributes) const; PrimitiveTypeEntry * parsePrimitiveTypeEntry(const QXmlStreamReader &, const QString &name, diff --git a/sources/shiboken2/data/shiboken_helpers.cmake b/sources/shiboken2/data/shiboken_helpers.cmake index 8111fa61f..5d7ff56bb 100644 --- a/sources/shiboken2/data/shiboken_helpers.cmake +++ b/sources/shiboken2/data/shiboken_helpers.cmake @@ -221,15 +221,20 @@ macro(set_quiet_build) endmacro() macro(get_python_extension_suffix) - # Result of imp.get_suffixes() depends on the platform, but generally looks something like: - # [('.cpython-34m-x86_64-linux-gnu.so', 'rb', 3), ('.cpython-34m.so', 'rb', 3), - # ('.abi3.so', 'rb', 3), ('.so', 'rb', 3), ('.py', 'r', 1), ('.pyc', 'rb', 2)] - # We pick the first most detailed one, strip of the file extension part. + # Result of importlib.machinery.EXTENSION_SUFFIXES depends on the platform, + # but generally looks something like: + # ['.cpython-38-x86_64-linux-gnu.so', '.abi3.so', '.so'] + # We pick the first most detailed one. execute_process( COMMAND ${PYTHON_EXECUTABLE} -c "if True: - import imp, re - first_suffix = imp.get_suffixes()[0][0] + import re + try: + from importlib import machinery + first_suffix = machinery.EXTENSION_SUFFIXES[0] + except AttributeError: + import imp + first_suffix = imp.get_suffixes()[0][0] res = re.search(r'^(.+)\\.', first_suffix) if res: first_suffix = res.group(1) diff --git a/sources/shiboken2/generator/generator.cpp b/sources/shiboken2/generator/generator.cpp index 7c6e921c7..484b1f641 100644 --- a/sources/shiboken2/generator/generator.cpp +++ b/sources/shiboken2/generator/generator.cpp @@ -430,9 +430,16 @@ bool Generator::generate() return false; } + const auto smartPointers = m_d->apiextractor->smartPointers(); for (const AbstractMetaType *type : qAsConst(m_d->instantiatedSmartPointers)) { AbstractMetaClass *smartPointerClass = - AbstractMetaClass::findClass(m_d->apiextractor->smartPointers(), type->typeEntry()); + AbstractMetaClass::findClass(smartPointers, type->typeEntry()); + if (!smartPointerClass) { + qCWarning(lcShiboken, "%s", + qPrintable(msgCannotFindSmartPointer(type->cppSignature(), + smartPointers))); + return false; + } GeneratorContext context(smartPointerClass, type, true); if (!generateFileForContext(context)) return false; diff --git a/sources/shiboken2/generator/qtdoc/qtdocgenerator.cpp b/sources/shiboken2/generator/qtdoc/qtdocgenerator.cpp index 86abf21b0..de023f079 100644 --- a/sources/shiboken2/generator/qtdoc/qtdocgenerator.cpp +++ b/sources/shiboken2/generator/qtdoc/qtdocgenerator.cpp @@ -438,15 +438,15 @@ QString QtXmlToSphinx::resolveContextForMethod(const QString& methodName) const } if (metaClass) { - QList<const AbstractMetaFunction*> funcList; + AbstractMetaFunctionList funcList; const AbstractMetaFunctionList &methods = metaClass->queryFunctionsByName(methodName); - for (const AbstractMetaFunction *func : methods) { + for (AbstractMetaFunction *func : methods) { if (methodName == func->name()) funcList.append(func); } const AbstractMetaClass *implementingClass = nullptr; - for (const AbstractMetaFunction *func : qAsConst(funcList)) { + for (AbstractMetaFunction *func : qAsConst(funcList)) { implementingClass = func->implementingClass(); if (implementingClass->name() == currentClass) break; @@ -847,7 +847,7 @@ void QtXmlToSphinx::handleTableTag(QXmlStreamReader& reader) m_tableHasHeader = false; } else if (token == QXmlStreamReader::EndElement) { // write the table on m_output - m_currentTable.enableHeader(m_tableHasHeader); + m_currentTable.setHeaderEnabled(m_tableHasHeader); m_currentTable.normalize(); m_output << ensureEndl << m_currentTable; m_currentTable.clear(); @@ -864,7 +864,7 @@ void QtXmlToSphinx::handleTermTag(QXmlStreamReader& reader) } else if (token == QXmlStreamReader::EndElement) { TableCell cell; cell.data = popOutputBuffer().trimmed(); - m_currentTable << (TableRow() << cell); + m_currentTable.appendRow(TableRow(1, cell)); } } @@ -874,7 +874,7 @@ void QtXmlToSphinx::handleItemTag(QXmlStreamReader& reader) QXmlStreamReader::TokenType token = reader.tokenType(); if (token == QXmlStreamReader::StartElement) { if (m_currentTable.isEmpty()) - m_currentTable << TableRow(); + m_currentTable.appendRow({}); TableRow& row = m_currentTable.last(); TableCell cell; cell.colSpan = reader.attributes().value(QLatin1String("colspan")).toShort(); @@ -896,7 +896,7 @@ void QtXmlToSphinx::handleRowTag(QXmlStreamReader& reader) QXmlStreamReader::TokenType token = reader.tokenType(); if (token == QXmlStreamReader::StartElement) { m_tableHasHeader = reader.name() == QLatin1String("header"); - m_currentTable << TableRow(); + m_currentTable.appendRow({}); } } @@ -919,8 +919,8 @@ void QtXmlToSphinx::handleListTag(QXmlStreamReader& reader) if (token == QXmlStreamReader::StartElement) { listType = webXmlListType(reader.attributes().value(QLatin1String("type"))); if (listType == EnumeratedList) { - m_currentTable << TableRow{TableCell(QLatin1String("Constant")), - TableCell(QLatin1String("Description"))}; + m_currentTable.appendRow(TableRow{TableCell(QLatin1String("Constant")), + TableCell(QLatin1String("Description"))}); m_tableHasHeader = true; } INDENT.indent--; @@ -943,7 +943,7 @@ void QtXmlToSphinx::handleListTag(QXmlStreamReader& reader) } break; case EnumeratedList: - m_currentTable.enableHeader(m_tableHasHeader); + m_currentTable.setHeaderEnabled(m_tableHasHeader); m_currentTable.normalize(); m_output << ensureEndl << m_currentTable; break; @@ -1328,53 +1328,49 @@ void QtXmlToSphinx::Table::normalize() if (m_normalized || isEmpty()) return; - int row; - int col; - QtXmlToSphinx::Table& self = *this; - //QDoc3 generates tables with wrong number of columns. We have to //check and if necessary, merge the last columns. int maxCols = -1; - for (const auto &row : qAsConst(self)) { + for (const auto &row : qAsConst(m_rows)) { if (row.count() > maxCols) maxCols = row.count(); } if (maxCols <= 0) return; // add col spans - for (row = 0; row < count(); ++row) { - for (col = 0; col < at(row).count(); ++col) { - QtXmlToSphinx::TableCell& cell = self[row][col]; + for (int row = 0; row < m_rows.count(); ++row) { + for (int col = 0; col < m_rows.at(row).count(); ++col) { + QtXmlToSphinx::TableCell& cell = m_rows[row][col]; bool mergeCols = (col >= maxCols); if (cell.colSpan > 0) { QtXmlToSphinx::TableCell newCell; newCell.colSpan = -1; for (int i = 0, max = cell.colSpan-1; i < max; ++i) { - self[row].insert(col+1, newCell); + m_rows[row].insert(col + 1, newCell); } cell.colSpan = 0; col++; } else if (mergeCols) { - self[row][maxCols - 1].data += QLatin1Char(' ') + cell.data; + m_rows[row][maxCols - 1].data += QLatin1Char(' ') + cell.data; } } } // row spans - const int numCols = first().count(); - for (col = 0; col < numCols; ++col) { - for (row = 0; row < count(); ++row) { - if (col < self[row].count()) { - QtXmlToSphinx::TableCell& cell = self[row][col]; + const int numCols = m_rows.constFirst().count(); + for (int col = 0; col < numCols; ++col) { + for (int row = 0; row < m_rows.count(); ++row) { + if (col < m_rows[row].count()) { + QtXmlToSphinx::TableCell& cell = m_rows[row][col]; if (cell.rowSpan > 0) { QtXmlToSphinx::TableCell newCell; newCell.rowSpan = -1; int targetRow = row + 1; const int targetEndRow = - std::min(targetRow + cell.rowSpan - 1, count()); + std::min(targetRow + cell.rowSpan - 1, m_rows.count()); cell.rowSpan = 0; for ( ; targetRow < targetEndRow; ++targetRow) - self[targetRow].insert(col, newCell); + m_rows[targetRow].insert(col, newCell); row++; } } @@ -1385,20 +1381,26 @@ void QtXmlToSphinx::Table::normalize() QTextStream& operator<<(QTextStream& s, const QtXmlToSphinx::Table &table) { - if (table.isEmpty()) - return s; + table.format(s); + return s; +} - if (!table.isNormalized()) { +void QtXmlToSphinx::Table::format (QTextStream& s) const +{ + if (isEmpty()) + return; + + if (!isNormalized()) { qCDebug(lcShiboken) << "Attempt to print an unnormalized table!"; - return s; + return; } // calc width and height of each column and row - const int headerColumnCount = table.constFirst().count(); + const int headerColumnCount = m_rows.constFirst().count(); QVector<int> colWidths(headerColumnCount); - QVector<int> rowHeights(table.count()); - for (int i = 0, maxI = table.count(); i < maxI; ++i) { - const QtXmlToSphinx::TableRow& row = table[i]; + QVector<int> rowHeights(m_rows.count()); + for (int i = 0, maxI = m_rows.count(); i < maxI; ++i) { + const QtXmlToSphinx::TableRow& row = m_rows.at(i); for (int j = 0, maxJ = std::min(row.count(), colWidths.size()); j < maxJ; ++j) { const QVector<QStringRef> rowLines = row[j].data.splitRef(QLatin1Char('\n')); // cache this would be a good idea for (const QStringRef &str : rowLines) @@ -1408,7 +1410,7 @@ QTextStream& operator<<(QTextStream& s, const QtXmlToSphinx::Table &table) } if (!*std::max_element(colWidths.begin(), colWidths.end())) - return s; // empty table (table with empty cells) + return; // empty table (table with empty cells) // create a horizontal line to be used later. QString horizontalLine = QLatin1String("+"); @@ -1418,8 +1420,8 @@ QTextStream& operator<<(QTextStream& s, const QtXmlToSphinx::Table &table) } // write table rows - for (int i = 0, maxI = table.count(); i < maxI; ++i) { // for each row - const QtXmlToSphinx::TableRow& row = table[i]; + for (int i = 0, maxI = m_rows.count(); i < maxI; ++i) { // for each row + const QtXmlToSphinx::TableRow& row = m_rows.at(i); // print line s << INDENT << '+'; @@ -1427,7 +1429,7 @@ QTextStream& operator<<(QTextStream& s, const QtXmlToSphinx::Table &table) char c; if (col >= row.length() || row[col].rowSpan == -1) c = ' '; - else if (i == 1 && table.hasHeader()) + else if (i == 1 && hasHeader()) c = '='; else c = '-'; @@ -1461,7 +1463,6 @@ QTextStream& operator<<(QTextStream& s, const QtXmlToSphinx::Table &table) } s << INDENT << horizontalLine << endl; s << endl; - return s; } static QString getFuncName(const AbstractMetaFunction* cppFunc) { @@ -2159,7 +2160,7 @@ static void writeFancyToc(QTextStream& s, const QStringList& items, int cols = 4 currentColData.clear(); i = 0; } - table << row; + table.appendRow(row); table.normalize(); s << ".. container:: pysidetoc" << endl << endl; s << table; @@ -2192,11 +2193,19 @@ void QtDocGenerator::writeModuleDocumentation() /* Avoid showing "Detailed Description for *every* class in toc tree */ Indentation indentation(INDENT); + // Store the it.key() in a QString so that it can be stripped off unwanted + // information when neeeded. For example, the RST files in the extras directory + // doesn't include the PySide# prefix in their names. + const QString moduleName = it.key(); + const int lastIndex = moduleName.lastIndexOf(QLatin1Char('.')); // Search for extra-sections if (!m_extraSectionDir.isEmpty()) { QDir extraSectionDir(m_extraSectionDir); - QStringList fileList = extraSectionDir.entryList(QStringList() << (it.key() + QLatin1String("?*.rst")), QDir::Files); + if (!extraSectionDir.exists()) + qCWarning(lcShiboken) << m_extraSectionDir << "doesn't exist"; + + QStringList fileList = extraSectionDir.entryList(QStringList() << (moduleName.mid(lastIndex + 1) + QLatin1String("?*.rst")), QDir::Files); QStringList::iterator it2 = fileList.begin(); for (; it2 != fileList.end(); ++it2) { QString origFileName(*it2); @@ -2230,7 +2239,7 @@ void QtDocGenerator::writeModuleDocumentation() s << "--------------------" << endl << endl; // module doc is always wrong and C++istic, so go straight to the extra directory! - QFile moduleDoc(m_extraSectionDir + QLatin1Char('/') + it.key() + QLatin1String(".rst")); + QFile moduleDoc(m_extraSectionDir + QLatin1Char('/') + moduleName.mid(lastIndex + 1) + QLatin1String(".rst")); if (moduleDoc.open(QIODevice::ReadOnly | QIODevice::Text)) { s << moduleDoc.readAll(); moduleDoc.close(); diff --git a/sources/shiboken2/generator/qtdoc/qtdocgenerator.h b/sources/shiboken2/generator/qtdoc/qtdocgenerator.h index 53e292d22..56cb9c4bb 100644 --- a/sources/shiboken2/generator/qtdoc/qtdocgenerator.h +++ b/sources/shiboken2/generator/qtdoc/qtdocgenerator.h @@ -67,13 +67,16 @@ public: TableCell(const char* text) : data(QLatin1String(text)) {} }; - using TableRow = QList<TableCell>; - class Table : public QList<TableRow> + using TableRow = QVector<TableCell>; + + class Table { public: Table() = default; - void enableHeader(bool enable) + bool isEmpty() const { return m_rows.isEmpty(); } + + void setHeaderEnabled(bool enable) { m_hasHeader = enable; } @@ -92,10 +95,19 @@ public: void clear() { m_normalized = false; - QList<TableRow>::clear(); + m_rows.clear(); } + void appendRow(const TableRow &row) { m_rows.append(row); } + + const TableRow &constFirst() { return m_rows.constFirst(); } + TableRow &first() { return m_rows.first(); } + TableRow &last() { return m_rows.last(); } + + void format (QTextStream& s) const; + private: + QVector<TableRow> m_rows; bool m_hasHeader = false; bool m_normalized = false; }; diff --git a/sources/shiboken2/tests/libsmart/smart.cpp b/sources/shiboken2/tests/libsmart/smart.cpp index 8d85d67a1..6a4deb50a 100644 --- a/sources/shiboken2/tests/libsmart/smart.cpp +++ b/sources/shiboken2/tests/libsmart/smart.cpp @@ -28,10 +28,52 @@ #include "smart.h" -bool shouldPrint() { +#include <algorithm> +#include <iostream> + +static inline bool shouldPrint() +{ return Registry::getInstance()->shouldPrint(); } +void SharedPtrBase::logDefaultConstructor(const void *t) +{ + if (shouldPrint()) + std::cout << "shared_ptr default constructor " << t << '\n'; +} + +void SharedPtrBase::logConstructor(const void *t, const void *pointee) +{ + if (shouldPrint()) { + std::cout << "shared_ptr constructor " << t << " with pointer " + << pointee << '\n'; + } +} + +void SharedPtrBase::logCopyConstructor(const void *t, const void *refData) +{ + if (shouldPrint()) { + std::cout << "shared_ptr copy constructor " << t << " with pointer " + << refData << '\n'; + } +} + +void SharedPtrBase::logAssignment(const void *t, const void *refData) +{ + if (shouldPrint()) { + std::cout << "shared_ptr assignment operator " << t << " with pointer " + << refData << "\n"; + } +} + +void SharedPtrBase::logDestructor(const void *t, int remainingRefCount) +{ + if (shouldPrint()) { + std::cout << "shared_ptr destructor " << t << " remaining refcount " + << remainingRefCount << '\n'; + } +} + Obj::Obj() : m_integer(123), m_internalInteger(new Integer) { Registry::getInstance()->add(this); @@ -143,10 +185,9 @@ Registry *Registry::getInstance() return ®istry; } -Registry::Registry() : m_printStuff(false) -{ +Registry::Registry() = default; -} +Registry::~Registry() = default; void Registry::add(Obj *p) { diff --git a/sources/shiboken2/tests/libsmart/smart.h b/sources/shiboken2/tests/libsmart/smart.h index 3347b22c1..6238f27d5 100644 --- a/sources/shiboken2/tests/libsmart/smart.h +++ b/sources/shiboken2/tests/libsmart/smart.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2017 The Qt Company Ltd. +** Copyright (C) 2019 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the test suite of Qt for Python. @@ -29,193 +29,9 @@ #ifndef SMART_H #define SMART_H -#include <algorithm> -#include <iostream> -#include <vector> - -#include "libsmartmacros.h" - -// Forward declarations. -template <class T> -class SharedPtr; -class Integer; -class Obj; - -LIB_SMART_API bool shouldPrint(); - -// Used to track which C++ objects are alive. -class LIB_SMART_API Registry { -public: - static Registry *getInstance(); - - void add(Obj *p); - void add(Integer *p); - void remove(Obj *p); - void remove(Integer *p); - int countObjects() const; - int countIntegers() const; - bool shouldPrint() const; - void setShouldPrint(bool flag); - -protected: - Registry(); - -private: - bool m_printStuff; - std::vector<Obj *> m_objects; - std::vector<Integer *> m_integers; -}; - -template <class T> -class RefData { -public: - RefData(T *ptr) : m_refCount(1), m_heldPtr(ptr) {} - ~RefData() { delete m_heldPtr; } - int inc() { return ++m_refCount; } - int dec() { return --m_refCount; } - int useCount() { return m_refCount; } - int m_refCount; - T *m_heldPtr; -}; - -template <class T> -class SharedPtr { -public: - SharedPtr() : m_refData(nullptr) { - if (shouldPrint()) - std::cout << "shared_ptr default constructor " << this << "\n"; - } - - SharedPtr(T *v) - { - if (shouldPrint()) - std::cout << "shared_ptr constructor " << this << " with pointer " << v << "\n"; - if (v) - m_refData = new RefData<T>(v); - } - - SharedPtr(const SharedPtr<T> &other) : m_refData(other.m_refData) - { - if (shouldPrint()) - std::cout << "shared_ptr copy constructor " << this << " with pointer " - << other.m_refData << "\n"; - if (m_refData) - m_refData->inc(); - } - - SharedPtr<T> &operator=(const SharedPtr<T>& other) - { - if (this != &other) { - if (shouldPrint()) - std::cout << "shared_ptr assignment operator " << this << " with pointer " - << other.m_refData << "\n"; - if (m_refData && m_refData->dec() == 0) - delete m_refData; - m_refData = other.m_refData; - if (m_refData) - m_refData->inc(); - } - return *this; - } - - T *data() const - { - if (m_refData) - return m_refData->m_heldPtr; - return nullptr; - } - - int useCount() const - { - if (m_refData) - return m_refData->useCount(); - return 0; - } - - void dummyMethod1() - { - - } - - T& operator*() const - { - // Crashes if smart pointer is empty (just like std::shared_ptr). - return *(m_refData->m_heldPtr); - } - - T *operator->() const - { - if (m_refData) - return m_refData->m_heldPtr; - return nullptr; - } - - bool operator!() const - { - return !m_refData || !m_refData->m_heldPtr; - } - - bool isNull() const - { - return !m_refData || !m_refData->m_heldPtr; - } - - operator bool() const - { - return m_refData && m_refData->m_heldPtr; - } - - ~SharedPtr() - { - if (m_refData) { - if (shouldPrint()) - std::cout << "shared_ptr destructor " << this << " remaining refcount " - << m_refData->useCount() - 1 << "\n"; - } - if (m_refData && m_refData->dec() == 0) - delete m_refData; - } - - RefData<T> *m_refData; -}; - -class LIB_SMART_API Integer { -public: - Integer(); - Integer(const Integer &other); - Integer &operator=(const Integer &other); - ~Integer(); - void printInteger(); - int m_int; -}; - -namespace Smart { -class LIB_SMART_API Integer2 : public Integer { -public: - Integer2(); - Integer2(const Integer2 &other); -}; -} - - -// Couldn't name it Object because it caused some namespace clashes. -class LIB_SMART_API Obj { -public: - Obj(); - virtual ~Obj(); - - void printObj(); - Integer takeInteger(Integer val); - SharedPtr<Obj> giveSharedPtrToObj(); - std::vector<SharedPtr<Obj> > giveSharedPtrToObjList(int size); - SharedPtr<Integer> giveSharedPtrToInteger(); - SharedPtr<Smart::Integer2> giveSharedPtrToInteger2(); - int takeSharedPtrToObj(SharedPtr<Obj> pObj); - int takeSharedPtrToInteger(SharedPtr<Integer> pInt); - - int m_integer; - Integer *m_internalInteger; -}; +#include "smart_sharedptr.h" +#include "smart_integer.h" +#include "smart_obj.h" +#include "smart_registry.h" #endif // SMART_H - diff --git a/sources/shiboken2/tests/libsmart/smart_integer.h b/sources/shiboken2/tests/libsmart/smart_integer.h new file mode 100644 index 000000000..3756f68b0 --- /dev/null +++ b/sources/shiboken2/tests/libsmart/smart_integer.h @@ -0,0 +1,52 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of Qt for Python. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef SMART_INTEGER_H +#define SMART_INTEGER_H + +#include "libsmartmacros.h" + +class LIB_SMART_API Integer { +public: + Integer(); + Integer(const Integer &other); + Integer &operator=(const Integer &other); + ~Integer(); + void printInteger(); + int m_int; +}; + +namespace Smart { +class LIB_SMART_API Integer2 : public Integer { +public: + Integer2(); + Integer2(const Integer2 &other); +}; +} // namespace Smart + +#endif // SMART_INTEGER_H diff --git a/sources/shiboken2/tests/libsmart/smart_obj.h b/sources/shiboken2/tests/libsmart/smart_obj.h new file mode 100644 index 000000000..12425366e --- /dev/null +++ b/sources/shiboken2/tests/libsmart/smart_obj.h @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of Qt for Python. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef SMART_OBJ_H +#define SMART_OBJ_H + +#include "libsmartmacros.h" +#include "smart_sharedptr.h" + +#include <vector> + +class Integer; +class Obj; +namespace Smart { class Integer2; } + +// Couldn't name it Object because it caused some namespace clashes. +class LIB_SMART_API Obj { +public: + Obj(); + virtual ~Obj(); + + void printObj(); + Integer takeInteger(Integer val); + SharedPtr<Obj> giveSharedPtrToObj(); + std::vector<SharedPtr<Obj> > giveSharedPtrToObjList(int size); + SharedPtr<Integer> giveSharedPtrToInteger(); + SharedPtr<Smart::Integer2> giveSharedPtrToInteger2(); + int takeSharedPtrToObj(SharedPtr<Obj> pObj); + int takeSharedPtrToInteger(SharedPtr<Integer> pInt); + + int m_integer; + Integer *m_internalInteger; +}; + +#endif // SMART_OBJ_H diff --git a/sources/shiboken2/tests/libsmart/smart_registry.h b/sources/shiboken2/tests/libsmart/smart_registry.h new file mode 100644 index 000000000..6171ddb59 --- /dev/null +++ b/sources/shiboken2/tests/libsmart/smart_registry.h @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of Qt for Python. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef SMART_REGISTRY_H +#define SMART_REGISTRY_H + +#include <vector> + +#include "libsmartmacros.h" + +class Obj; +class Integer; + +// Used to track which C++ objects are alive. +class LIB_SMART_API Registry { +public: + static Registry *getInstance(); + ~Registry(); + + Registry(const Registry &) = delete; + Registry &operator=(const Registry &) = delete; + Registry(Registry &&) = delete; + Registry &operator=(Registry &&) = delete; + + void add(Obj *p); + void add(Integer *p); + void remove(Obj *p); + void remove(Integer *p); + int countObjects() const; + int countIntegers() const; + bool shouldPrint() const; + void setShouldPrint(bool flag); + +protected: + Registry(); + +private: + std::vector<Obj *> m_objects; + std::vector<Integer *> m_integers; + bool m_printStuff = false; +}; + +#endif // SMART_REGISTRY_H diff --git a/sources/shiboken2/tests/libsmart/smart_sharedptr.h b/sources/shiboken2/tests/libsmart/smart_sharedptr.h new file mode 100644 index 000000000..84184e1f8 --- /dev/null +++ b/sources/shiboken2/tests/libsmart/smart_sharedptr.h @@ -0,0 +1,140 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of Qt for Python. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef SMART_SHARED_PTR_H +#define SMART_SHARED_PTR_H + +#include "libsmartmacros.h" + +template <class T> +class RefData { +public: + RefData(T *ptr) : m_refCount(1), m_heldPtr(ptr) {} + ~RefData() { delete m_heldPtr; } + int inc() { return ++m_refCount; } + int dec() { return --m_refCount; } + int useCount() { return m_refCount; } + int m_refCount; + T *m_heldPtr; +}; + +struct SharedPtrBase +{ + LIB_SMART_API static void logDefaultConstructor(const void *t); + LIB_SMART_API static void logConstructor(const void *t, const void *pointee); + LIB_SMART_API static void logCopyConstructor(const void *t, const void *refData); + LIB_SMART_API static void logAssignment(const void *t, const void *refData); + LIB_SMART_API static void logDestructor(const void *t, int remainingRefCount); +}; + +template <class T> +class SharedPtr : public SharedPtrBase { +public: + SharedPtr() { logDefaultConstructor(this); } + + SharedPtr(T *v) + { + logConstructor(this, v); + if (v) + m_refData = new RefData<T>(v); + } + + SharedPtr(const SharedPtr<T> &other) : m_refData(other.m_refData) + { + logCopyConstructor(this, other.m_refData); + if (m_refData) + m_refData->inc(); + } + + SharedPtr<T> &operator=(const SharedPtr<T>& other) + { + if (this != &other) { + logAssignment(this, other.m_refData); + if (m_refData && m_refData->dec() == 0) + delete m_refData; + m_refData = other.m_refData; + if (m_refData) + m_refData->inc(); + } + return *this; + } + + T *data() const + { + return m_refData ? m_refData->m_heldPtr : nullptr; + } + + int useCount() const + { + return m_refData ? m_refData->useCount() : 0; + } + + void dummyMethod1() + { + + } + + T& operator*() const + { + // Crashes if smart pointer is empty (just like std::shared_ptr). + return *(m_refData->m_heldPtr); + } + + T *operator->() const + { + return m_refData ? m_refData->m_heldPtr : nullptr; + } + + bool operator!() const + { + return !m_refData || !m_refData->m_heldPtr; + } + + bool isNull() const + { + return !m_refData || !m_refData->m_heldPtr; + } + + operator bool() const + { + return m_refData && m_refData->m_heldPtr; + } + + ~SharedPtr() + { + if (m_refData) + logDestructor(this, m_refData->useCount() - 1); + if (m_refData && m_refData->dec() == 0) + delete m_refData; + } + +private: + RefData<T> *m_refData = nullptr; +}; + +#endif // SMART_SHARED_PTR_H diff --git a/checklibs.py b/tools/checklibs.py index 18aa11e93..18aa11e93 100644 --- a/checklibs.py +++ b/tools/checklibs.py diff --git a/tools/create_changelog.py b/tools/create_changelog.py index d9ab24731..d28af1a7f 100644 --- a/tools/create_changelog.py +++ b/tools/create_changelog.py @@ -149,6 +149,7 @@ def git_command(versions: List[str], pattern: str): command += " {}..{}".format(versions[0], versions[1]) command += " | git cat-file --batch" command += " | grep -o -E \"^[0-9a-f]{40}\"" + task_number_re = re.compile(r'^.*-(\d+)\s*$') print("{}: {}".format(git_command.__name__, command), file=sys.stderr) out_sha1, err = Popen(command, stdout=PIPE, shell=True).communicate() if err: @@ -168,20 +169,25 @@ def git_command(versions: List[str], pattern: str): if not task: continue + task_number = -1 + task_number_match = task_number_re.match(task) + if task_number_match: + task_number = int(task_number_match.group(1)) + entry = {"title": title, "task": task, "task-number": task_number} if "shiboken" in title: if sha not in shiboken2_commits: - shiboken2_commits[sha] = {"title": title, "task": task} + shiboken2_commits[sha] = entry else: if sha not in pyside2_commits: - pyside2_commits[sha] = {"title": title, "task": task} + pyside2_commits[sha] = entry def create_fixes_log(versions: List[str]) -> None: - git_command(versions, "Fixes") + git_command(versions, "Fixes: ") def create_task_log(versions: List[str]) -> None: - git_command(versions, "Task-number") + git_command(versions, "Task-number: ") def gen_list(d: Dict[str, Dict[str, str]]) -> str: @@ -192,9 +198,7 @@ def gen_list(d: Dict[str, Dict[str, str]]) -> str: def sort_dict(d: Dict[str, Dict[str, str]]) -> Dict[str, Dict[str, str]]: - return dict(sorted(d.items(), - key=lambda kv: "{:5d}".format( - int(kv[1]['task'].replace("PYSIDE-", ""))))) + return dict(sorted(d.items(), key=lambda kv: kv[1]['task-number'])) if __name__ == "__main__": diff --git a/debug_windows.py b/tools/debug_windows.py index ab1c03aba..ab1c03aba 100644 --- a/debug_windows.py +++ b/tools/debug_windows.py diff --git a/missing_bindings.py b/tools/missing_bindings.py index 8f3c0b808..8f3c0b808 100644 --- a/missing_bindings.py +++ b/tools/missing_bindings.py |
