diff options
author | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2019-04-24 14:24:06 +0200 |
---|---|---|
committer | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2019-04-24 14:24:09 +0200 |
commit | 8b892f71b749a623724ccecca881972a33c9d559 (patch) | |
tree | 88d7a2371481cafd559d4895efa41b6f166ed8ac /sources/shiboken2 | |
parent | fff6ea0059b7394869166a01674a9afa230bc3a9 (diff) | |
parent | a7038d87ba6ec3b2beeee166930c24f290f6478f (diff) |
Merge remote-tracking branch 'origin/5.12' into 5.13
Change-Id: I28805a29caa05e996b490ba46e27ddbc243cc074
Diffstat (limited to 'sources/shiboken2')
55 files changed, 741 insertions, 774 deletions
diff --git a/sources/shiboken2/ApiExtractor/CMakeLists.txt b/sources/shiboken2/ApiExtractor/CMakeLists.txt index 4c0ac7b30..147fda377 100644 --- a/sources/shiboken2/ApiExtractor/CMakeLists.txt +++ b/sources/shiboken2/ApiExtractor/CMakeLists.txt @@ -2,30 +2,8 @@ project(apiextractor) cmake_minimum_required(VERSION 3.1) cmake_policy(VERSION 3.1) -find_package(LibXml2 2.6.32) -find_package(LibXslt 1.1.19) -option(DISABLE_DOCSTRINGS "Disable documentation extraction." FALSE) - -set (USE_LIBXSLT 0) -if (NOT DISABLE_DOCSTRINGS) - if (LIBXSLT_FOUND AND LIBXML2_FOUND) - add_definitions(-DHAVE_LIBXSLT) - set (USE_LIBXSLT 1) - else() - message(WARNING "libxslt and/or libxml not found, falling back to QtXmlPatterns (QTBUG-66925)") - endif() -endif() - -if(BUILD_TESTS) - set(LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR}/tests) -endif () - -set(QT_USE_QTCORE 1) -set(QT_USE_QTXML 1) -add_definitions(-DQT_PLUGIN) -add_definitions(-DQT_SHARED) -add_definitions(-DRXX_ALLOCATOR_INIT_0) +set(CMAKE_AUTOMOC ON) set(apiextractor_SRC apiextractor.cpp @@ -50,45 +28,37 @@ parser/codemodel.cpp parser/enumvalue.cpp ) -set(APIEXTRACTOR_EXTRA_INCLUDES ${CLANG_EXTRA_INCLUDES}) -set(APIEXTRACTOR_EXTRA_LIBRARIES ${CLANG_EXTRA_LIBRARIES}) +add_library(apiextractor STATIC ${apiextractor_SRC}) +target_include_directories(apiextractor PRIVATE ${CLANG_EXTRA_INCLUDES} + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/parser + ${CMAKE_CURRENT_SOURCE_DIR}/parser/rpp) +target_link_libraries(apiextractor PUBLIC Qt5::Core) +target_link_libraries(apiextractor PRIVATE ${CLANG_EXTRA_LIBRARIES}) if (NOT DISABLE_DOCSTRINGS) - set(apiextractor_SRC - ${apiextractor_SRC} - docparser.cpp - doxygenparser.cpp - qtdocparser.cpp - ) - set(APIEXTRACTOR_EXTRA_INCLUDES ${APIEXTRACTOR_EXTRA_INCLUDES}) - set(APIEXTRACTOR_EXTRA_LIBRARIES ${APIEXTRACTOR_EXTRA_LIBRARIES}) - if (USE_LIBXSLT) - list(APPEND APIEXTRACTOR_EXTRA_INCLUDES ${LIBXSLT_INCLUDE_DIR} ${LIBXML2_INCLUDE_DIR}) - list(APPEND APIEXTRACTOR_EXTRA_LIBRARIES ${LIBXSLT_LIBRARIES} ${LIBXML2_LIBRARIES}) + target_sources(apiextractor PRIVATE docparser.cpp + doxygenparser.cpp + qtdocparser.cpp) + target_link_libraries(apiextractor PUBLIC Qt5::Xml Qt5::XmlPatterns) + + if (LIBXSLT_FOUND AND LIBXML2_FOUND) + target_compile_definitions(apiextractor PUBLIC HAVE_LIBXSLT) + target_include_directories(apiextractor + PRIVATE ${LIBXSLT_INCLUDE_DIR} ${LIBXML2_INCLUDE_DIR}) + target_link_libraries(apiextractor + PRIVATE ${LIBXSLT_LIBRARIES} ${LIBXML2_LIBRARIES}) + else() + message(WARNING + "libxslt and/or libxml not found, falling back to QtXmlPatterns (QTBUG-66925)") endif() endif() set(LIB_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}" CACHE PATH "The subdirectory relative to the install prefix where libraries will be installed (default is /lib${LIB_SUFFIX})" FORCE) -set(CMAKE_AUTOMOC ON) - -include_directories(${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_CURRENT_BINARY_DIR} - ${CMAKE_CURRENT_SOURCE_DIR}/parser - ${CMAKE_CURRENT_SOURCE_DIR}/parser/rpp - ${APIEXTRACTOR_EXTRA_INCLUDES} - ${Qt5Core_INCLUDE_DIRS} - ${Qt5Xml_INCLUDE_DIRS} - ) - -add_library(apiextractor STATIC ${apiextractor_SRC} ${apiextractor_RCCS_SRC}) -target_link_libraries(apiextractor - ${Qt5Xml_LIBRARIES} - ${Qt5XmlPatterns_LIBRARIES} - ${APIEXTRACTOR_EXTRA_LIBRARIES} - ) - if (BUILD_TESTS) + set(LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR}/tests) enable_testing() add_subdirectory(tests) endif() diff --git a/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp b/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp index e62a2a78a..6e95e79e7 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp +++ b/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp @@ -111,7 +111,7 @@ static QStringList parseTemplateType(const QString& name) { return result; } -AbstractMetaBuilderPrivate::AbstractMetaBuilderPrivate() : m_currentClass(0), +AbstractMetaBuilderPrivate::AbstractMetaBuilderPrivate() : m_logDirectory(QLatin1String(".") + QDir::separator()), m_skipDeprecated(false) { @@ -192,7 +192,7 @@ void AbstractMetaBuilderPrivate::checkFunctionModifications() QString name = signature.trimmed(); name.truncate(name.indexOf(QLatin1Char('('))); - AbstractMetaClass *clazz = AbstractMetaClass::findClass(m_metaClasses, centry->qualifiedCppName()); + AbstractMetaClass *clazz = AbstractMetaClass::findClass(m_metaClasses, centry); if (!clazz) continue; @@ -223,13 +223,14 @@ void AbstractMetaBuilderPrivate::checkFunctionModifications() } } -AbstractMetaClass *AbstractMetaBuilderPrivate::argumentToClass(const ArgumentModelItem &argument) +AbstractMetaClass *AbstractMetaBuilderPrivate::argumentToClass(const ArgumentModelItem &argument, + AbstractMetaClass *currentClass) { AbstractMetaClass* returned = 0; - AbstractMetaType *type = translateType(argument->type()); + AbstractMetaType *type = translateType(argument->type(), currentClass); if (type && type->typeEntry() && type->typeEntry()->isComplex()) { const TypeEntry *entry = type->typeEntry(); - returned = AbstractMetaClass::findClass(m_metaClasses, entry->name()); + returned = AbstractMetaClass::findClass(m_metaClasses, entry); } delete type; return returned; @@ -238,11 +239,12 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::argumentToClass(const ArgumentMod /** * Checks the argument of a hash function and flags the type if it is a complex type */ -void AbstractMetaBuilderPrivate::registerHashFunction(const FunctionModelItem &function_item) +void AbstractMetaBuilderPrivate::registerHashFunction(const FunctionModelItem &function_item, + AbstractMetaClass *currentClass) { ArgumentList arguments = function_item->arguments(); if (arguments.size() == 1) { - if (AbstractMetaClass *cls = argumentToClass(arguments.at(0))) + if (AbstractMetaClass *cls = argumentToClass(arguments.at(0), currentClass)) cls->setHasHashFunction(true); } } @@ -251,13 +253,14 @@ void AbstractMetaBuilderPrivate::registerHashFunction(const FunctionModelItem &f * Check if a class has a debug stream operator that can be used as toString */ -void AbstractMetaBuilderPrivate::registerToStringCapability(const FunctionModelItem &function_item) +void AbstractMetaBuilderPrivate::registerToStringCapability(const FunctionModelItem &function_item, + AbstractMetaClass *currentClass) { ArgumentList arguments = function_item->arguments(); if (arguments.size() == 2) { if (arguments.at(0)->type().toString() == QLatin1String("QDebug")) { const ArgumentModelItem &arg = arguments.at(1); - if (AbstractMetaClass *cls = argumentToClass(arg)) { + if (AbstractMetaClass *cls = argumentToClass(arg, currentClass)) { if (arg->type().indirections() < 2) cls->setToStringCapability(true); } @@ -265,28 +268,28 @@ void AbstractMetaBuilderPrivate::registerToStringCapability(const FunctionModelI } } -void AbstractMetaBuilderPrivate::traverseOperatorFunction(const FunctionModelItem &item) +void AbstractMetaBuilderPrivate::traverseOperatorFunction(const FunctionModelItem &item, + AbstractMetaClass *currentClass) { if (item->accessPolicy() != CodeModel::Public) return; ArgumentList arguments = item->arguments(); - AbstractMetaClass* baseoperandClass; bool firstArgumentIsSelf = true; bool unaryOperator = false; - baseoperandClass = argumentToClass(arguments.at(0)); + auto baseoperandClass = argumentToClass(arguments.at(0), currentClass); if (arguments.size() == 1) { unaryOperator = true; } else if (!baseoperandClass || !(baseoperandClass->typeEntry()->codeGeneration() & TypeEntry::GenerateTargetLang)) { - baseoperandClass = argumentToClass(arguments.at(1)); + baseoperandClass = argumentToClass(arguments.at(1), currentClass); firstArgumentIsSelf = false; } else { - AbstractMetaType *type = translateType(item->type()); + AbstractMetaType *type = translateType(item->type(), currentClass); const TypeEntry *retType = type ? type->typeEntry() : nullptr; - AbstractMetaClass* otherArgClass = argumentToClass(arguments.at(1)); + AbstractMetaClass *otherArgClass = argumentToClass(arguments.at(1), currentClass); if (otherArgClass && retType && (retType->isValue() || retType->isObject()) && retType != baseoperandClass->typeEntry() @@ -298,9 +301,7 @@ void AbstractMetaBuilderPrivate::traverseOperatorFunction(const FunctionModelIte } if (baseoperandClass) { - AbstractMetaClass* oldCurrentClass = m_currentClass; - m_currentClass = baseoperandClass; - AbstractMetaFunction *metaFunction = traverseFunction(item); + AbstractMetaFunction *metaFunction = traverseFunction(item, baseoperandClass); if (metaFunction) { // Strip away first argument, since that is the containing object AbstractMetaArgumentList arguments = metaFunction->arguments(); @@ -333,22 +334,19 @@ void AbstractMetaBuilderPrivate::traverseOperatorFunction(const FunctionModelIte } else { delete metaFunction; } - - m_currentClass = oldCurrentClass; } } -void AbstractMetaBuilderPrivate::traverseStreamOperator(const FunctionModelItem &item) +void AbstractMetaBuilderPrivate::traverseStreamOperator(const FunctionModelItem &item, + AbstractMetaClass *currentClass) { ArgumentList arguments = item->arguments(); if (arguments.size() == 2 && item->accessPolicy() == CodeModel::Public) { - AbstractMetaClass* streamClass = argumentToClass(arguments.at(0)); - AbstractMetaClass* streamedClass = argumentToClass(arguments.at(1)); + AbstractMetaClass *streamClass = argumentToClass(arguments.at(0), currentClass); + AbstractMetaClass *streamedClass = argumentToClass(arguments.at(1), currentClass); if (streamClass && streamedClass && (streamClass->isStream())) { - AbstractMetaClass *oldCurrentClass = m_currentClass; - m_currentClass = streamedClass; - AbstractMetaFunction *streamFunction = traverseFunction(item); + AbstractMetaFunction *streamFunction = traverseFunction(item, streamedClass); if (streamFunction) { streamFunction->setFunctionType(AbstractMetaFunction::GlobalScopeFunction); @@ -385,7 +383,6 @@ void AbstractMetaBuilderPrivate::traverseStreamOperator(const FunctionModelItem else funcClass->typeEntry()->addExtraInclude(streamClass->typeEntry()->include()); - m_currentClass = oldCurrentClass; } else { delete streamFunction; } @@ -394,27 +391,6 @@ void AbstractMetaBuilderPrivate::traverseStreamOperator(const FunctionModelItem } } -void AbstractMetaBuilderPrivate::fixQObjectForScope(const FileModelItem &dom, - const TypeDatabase *types, - const NamespaceModelItem &scope) -{ - const ClassList &scopeClasses = scope->classes(); - for (const ClassModelItem &item : scopeClasses) { - QString qualifiedName = item->qualifiedName().join(colonColon()); - TypeEntry* entry = types->findType(qualifiedName); - if (entry) { - if (isQObject(dom, qualifiedName) && entry->isComplex()) - static_cast<ComplexTypeEntry *>(entry)->setQObject(true); - } - } - - const NamespaceList &namespaces = scope->namespaces(); - for (const NamespaceModelItem &n : namespaces) { - if (scope != n) - fixQObjectForScope(dom, types, n); - } -} - void AbstractMetaBuilderPrivate::sortLists() { for (AbstractMetaClass *cls : qAsConst(m_metaClasses)) @@ -450,17 +426,14 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom) pushScope(dom); - // fix up QObject's in the type system.. - fixQObjectForScope(dom, types, dom); - // Start the generation... const ClassList &typeValues = dom->classes(); ReportHandler::setProgressReference(typeValues); for (const ClassModelItem &item : typeValues) { ReportHandler::progress(QStringLiteral("Generating class model (%1)...") .arg(typeValues.size())); - if (AbstractMetaClass *cls = traverseClass(dom, item)) - addAbstractMetaClass(cls); + if (AbstractMetaClass *cls = traverseClass(dom, item, nullptr)) + addAbstractMetaClass(cls, item.data()); } // We need to know all global enums @@ -481,9 +454,8 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom) for (const NamespaceModelItem &item : namespaceTypeValues) { ReportHandler::progress(QStringLiteral("Generating namespace model (%1)...") .arg(namespaceTypeValues.size())); - AbstractMetaClass *metaClass = traverseNamespace(dom, item); - if (metaClass) - m_metaClasses << metaClass; + if (AbstractMetaClass *metaClass = traverseNamespace(dom, item)) + addAbstractMetaClass(metaClass, item.data()); } // Go through all typedefs to see if we have defined any @@ -493,8 +465,8 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom) for (const TypeDefModelItem &typeDef : typeDefs) { ReportHandler::progress(QStringLiteral("Resolving typedefs (%1)...") .arg(typeDefs.size())); - if (AbstractMetaClass *cls = traverseTypeDef(dom, typeDef)) - addAbstractMetaClass(cls); + if (AbstractMetaClass *cls = traverseTypeDef(dom, typeDef, nullptr)) + addAbstractMetaClass(cls, typeDef.data()); } traverseTypesystemTypedefs(); @@ -515,7 +487,7 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom) if (!funcEntry || !funcEntry->generateCode()) continue; - AbstractMetaFunction* metaFunc = traverseFunction(func); + AbstractMetaFunction* metaFunc = traverseFunction(func, nullptr); if (!metaFunc) continue; @@ -579,7 +551,7 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom) && !entry->isCustom() && !entry->isVariant() && (entry->generateCode() & TypeEntry::GenerateTargetLang) - && !AbstractMetaClass::findClass(m_metaClasses, entry->qualifiedCppName())) { + && !AbstractMetaClass::findClass(m_metaClasses, entry)) { qCWarning(lcShiboken).noquote().nospace() << QStringLiteral("type '%1' is specified in typesystem, but not defined. This could potentially lead to compilation errors.") .arg(entry->qualifiedCppName()); @@ -622,13 +594,13 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom) { const FunctionList &hashFunctions = dom->findFunctions(QLatin1String("qHash")); for (const FunctionModelItem &item : hashFunctions) - registerHashFunction(item); + registerHashFunction(item, nullptr); } { const FunctionList &streamOps = dom->findFunctions(QLatin1String("operator<<")); for (const FunctionModelItem &item : streamOps) - registerToStringCapability(item); + registerToStringCapability(item, nullptr); } { @@ -656,14 +628,14 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom) binaryOperators.append(dom->findFunctions(QStringLiteral("operator>"))); for (const FunctionModelItem &item : qAsConst(binaryOperators)) - traverseOperatorFunction(item); + traverseOperatorFunction(item, nullptr); } { const FunctionList streamOperators = dom->findFunctions(QLatin1String("operator<<")) + dom->findFunctions(QLatin1String("operator>>")); for (const FunctionModelItem &item : streamOperators) - traverseStreamOperator(item); + traverseStreamOperator(item, nullptr); } checkFunctionModifications(); @@ -688,21 +660,19 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom) sortLists(); - m_currentClass = 0; - // Functions added to the module on the type system. const AddedFunctionList &globalUserFunctions = types->globalUserFunctions(); - for (const AddedFunction &addedFunc : globalUserFunctions) { + for (const AddedFunctionPtr &addedFunc : globalUserFunctions) { AbstractMetaFunction* metaFunc = traverseFunction(addedFunc); if (Q_UNLIKELY(!metaFunc)) { qFatal("Unable to traverse added global function \"%s\".", - qPrintable(addedFunc.name())); + qPrintable(addedFunc->name())); } metaFunc->setFunctionType(AbstractMetaFunction::NormalFunction); m_globalFunctions << metaFunc; } - std::puts(""); + m_itemToClass.clear(); } static bool metaEnumLessThan(const AbstractMetaEnum *e1, const AbstractMetaEnum *e2) @@ -742,9 +712,11 @@ void AbstractMetaBuilder::setLogDirectory(const QString& logDir) d->m_logDirectory.append(QDir::separator()); } -void AbstractMetaBuilderPrivate::addAbstractMetaClass(AbstractMetaClass *cls) +void AbstractMetaBuilderPrivate::addAbstractMetaClass(AbstractMetaClass *cls, + const _CodeModelItem *item) { cls->setOriginalAttributes(cls->attributes()); + m_itemToClass.insert(item, cls); if (cls->typeEntry()->isContainer()) { m_templates << cls; } else if (cls->typeEntry()->isSmartPointer()) { @@ -763,9 +735,10 @@ void AbstractMetaBuilderPrivate::addAbstractMetaClass(AbstractMetaClass *cls) AbstractMetaClass *AbstractMetaBuilderPrivate::traverseNamespace(const FileModelItem &dom, const NamespaceModelItem &namespaceItem) { - QString namespaceName = - (!m_namespacePrefix.isEmpty() ? m_namespacePrefix + colonColon() : QString()) - + namespaceItem->name(); + QString namespaceName = currentScope()->qualifiedName().join(colonColon()); + if (!namespaceName.isEmpty()) + namespaceName.append(colonColon()); + namespaceName.append(namespaceItem->name()); NamespaceTypeEntry *type = TypeDatabase::instance()->findNamespaceType(namespaceName); if (TypeDatabase::instance()->isClassRejected(namespaceName)) { @@ -784,8 +757,6 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseNamespace(const FileModel *metaClass += AbstractMetaAttributes::Public; - m_currentClass = metaClass; - if (ReportHandler::isDebug(ReportHandler::SparseDebug)) { qCDebug(lcShiboken) << QStringLiteral("namespace '%1.%2'").arg(metaClass->package(), namespaceItem->name()); @@ -794,15 +765,14 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseNamespace(const FileModel traverseEnums(namespaceItem, metaClass, namespaceItem->enumsDeclarations()); pushScope(namespaceItem); - m_namespacePrefix = currentScope()->qualifiedName().join(colonColon()); const ClassList &classes = namespaceItem->classes(); for (const ClassModelItem &cls : classes) { - AbstractMetaClass* mjc = traverseClass(dom, cls); + AbstractMetaClass* mjc = traverseClass(dom, cls, metaClass); if (mjc) { metaClass->addInnerClass(mjc); mjc->setEnclosingClass(metaClass); - addAbstractMetaClass(mjc); + addAbstractMetaClass(mjc, cls.data()); } } @@ -810,11 +780,11 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseNamespace(const FileModel // specific typedefs to be used as classes. const TypeDefList typeDefs = namespaceItem->typeDefs(); for (const TypeDefModelItem &typeDef : typeDefs) { - AbstractMetaClass *cls = traverseTypeDef(dom, typeDef); + AbstractMetaClass *cls = traverseTypeDef(dom, typeDef, metaClass); if (cls) { metaClass->addInnerClass(cls); cls->setEnclosingClass(metaClass); - addAbstractMetaClass(cls); + addAbstractMetaClass(cls, typeDef.data()); } } @@ -824,14 +794,11 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseNamespace(const FileModel if (mjc) { metaClass->addInnerClass(mjc); mjc->setEnclosingClass(metaClass); - addAbstractMetaClass(mjc); + addAbstractMetaClass(mjc, ni.data()); } } - m_currentClass = 0; - popScope(); - m_namespacePrefix = currentScope()->qualifiedName().join(colonColon()); if (!type->include().isValid()) setInclude(type, namespaceItem->fileName()); @@ -872,8 +839,8 @@ AbstractMetaEnum *AbstractMetaBuilderPrivate::traverseEnum(const EnumModelItem & QString enumName = enumItem->name(); QString className; - if (m_currentClass) - className = m_currentClass->typeEntry()->qualifiedCppName(); + if (enclosing) + className = enclosing->typeEntry()->qualifiedCppName(); QString rejectReason; if (TypeDatabase::instance()->isEnumRejected(className, enumName, &rejectReason)) { @@ -883,8 +850,8 @@ AbstractMetaEnum *AbstractMetaBuilderPrivate::traverseEnum(const EnumModelItem & return 0; } - const bool rejectionWarning = !m_currentClass - || (m_currentClass->typeEntry()->codeGeneration() & TypeEntry::GenerateTargetLang); + const bool rejectionWarning = !enclosing + || (enclosing->typeEntry()->codeGeneration() & TypeEntry::GenerateTargetLang); if (!typeEntry) { if (rejectionWarning) @@ -983,15 +950,16 @@ AbstractMetaEnum *AbstractMetaBuilderPrivate::traverseEnum(const EnumModelItem & } AbstractMetaClass* AbstractMetaBuilderPrivate::traverseTypeDef(const FileModelItem &dom, - const TypeDefModelItem &typeDef) + const TypeDefModelItem &typeDef, + AbstractMetaClass *currentClass) { TypeDatabase* types = TypeDatabase::instance(); QString className = stripTemplateArgs(typeDef->name()); QString fullClassName = className; // we have an inner class - if (m_currentClass) { - fullClassName = stripTemplateArgs(m_currentClass->typeEntry()->qualifiedCppName()) + if (currentClass) { + fullClassName = stripTemplateArgs(currentClass->typeEntry()->qualifiedCppName()) + colonColon() + fullClassName; } @@ -1011,9 +979,6 @@ AbstractMetaClass* AbstractMetaBuilderPrivate::traverseTypeDef(const FileModelIt if (!type) return 0; - if (type->isObject()) - static_cast<ObjectTypeEntry *>(type)->setQObject(isQObject(dom, stripTemplateArgs(typeDef->type().qualifiedName().join(colonColon())))); - AbstractMetaClass *metaClass = new AbstractMetaClass; metaClass->setTypeDef(true); metaClass->setTypeEntry(type); @@ -1041,19 +1006,20 @@ void AbstractMetaBuilderPrivate::traverseTypesystemTypedefs() metaClass->setBaseClassNames(QStringList(te->sourceType())); *metaClass += AbstractMetaAttributes::Public; fillAddedFunctions(metaClass); - addAbstractMetaClass(metaClass); + addAbstractMetaClass(metaClass, nullptr); } } AbstractMetaClass *AbstractMetaBuilderPrivate::traverseClass(const FileModelItem &dom, - const ClassModelItem &classItem) + const ClassModelItem &classItem, + AbstractMetaClass *currentClass) { QString className = stripTemplateArgs(classItem->name()); QString fullClassName = className; // we have inner an class - if (m_currentClass) { - fullClassName = stripTemplateArgs(m_currentClass->typeEntry()->qualifiedCppName()) + if (currentClass) { + fullClassName = stripTemplateArgs(currentClass->typeEntry()->qualifiedCppName()) + colonColon() + fullClassName; } @@ -1076,9 +1042,6 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseClass(const FileModelItem return 0; } - if (type->isObject()) - ((ObjectTypeEntry*)type)->setQObject(isQObject(dom, fullClassName)); - AbstractMetaClass *metaClass = new AbstractMetaClass; metaClass->setTypeEntry(type); @@ -1097,9 +1060,6 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseClass(const FileModelItem if (type->stream()) metaClass->setStream(true); - AbstractMetaClass* oldCurrentClass = m_currentClass; - m_currentClass = metaClass; - if (ReportHandler::isDebug(ReportHandler::SparseDebug)) { const QString message = type->isContainer() ? QStringLiteral("container: '%1'").arg(fullClassName) @@ -1126,11 +1086,11 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseClass(const FileModelItem { const ClassList &innerClasses = classItem->classes(); for (const ClassModelItem &ci : innerClasses) { - AbstractMetaClass *cl = traverseClass(dom, ci); + AbstractMetaClass *cl = traverseClass(dom, ci, metaClass); if (cl) { cl->setEnclosingClass(metaClass); metaClass->addInnerClass(cl); - m_metaClasses << cl; + addAbstractMetaClass(cl, ci.data()); } } @@ -1140,16 +1100,13 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseClass(const FileModelItem // specific typedefs to be used as classes. const TypeDefList typeDefs = classItem->typeDefs(); for (const TypeDefModelItem &typeDef : typeDefs) { - AbstractMetaClass *cls = traverseTypeDef(dom, typeDef); + AbstractMetaClass *cls = traverseTypeDef(dom, typeDef, metaClass); if (cls) { cls->setEnclosingClass(metaClass); - addAbstractMetaClass(cls); + addAbstractMetaClass(cls, typeDef.data()); } } - - m_currentClass = oldCurrentClass; - // Set the default include file name if (!type->include().isValid()) setInclude(type, classItem->fileName()); @@ -1170,48 +1127,22 @@ void AbstractMetaBuilderPrivate::traverseScopeMembers(ScopeModelItem item, traverseClassMembers(ci); } -AbstractMetaClass* AbstractMetaBuilderPrivate::currentTraversedClass(ScopeModelItem item) -{ - QString className = stripTemplateArgs(item->name()); - QString fullClassName = className; - - // This is an inner class - if (m_currentClass) - fullClassName = stripTemplateArgs(m_currentClass->typeEntry()->qualifiedCppName()) + colonColon() + fullClassName; - - AbstractMetaClass *metaClass = AbstractMetaClass::findClass(m_metaClasses, fullClassName); - if (!metaClass) - metaClass = AbstractMetaClass::findClass(m_templates, fullClassName); - - if (!metaClass) - metaClass = AbstractMetaClass::findClass(m_smartPointers, fullClassName); - return metaClass; -} - void AbstractMetaBuilderPrivate::traverseClassMembers(ClassModelItem item) { - AbstractMetaClass* metaClass = currentTraversedClass(item); + AbstractMetaClass* metaClass = m_itemToClass.value(item.data()); if (!metaClass) return; - AbstractMetaClass* oldCurrentClass = m_currentClass; - m_currentClass = metaClass; - // Class members traverseScopeMembers(item, metaClass); - - m_currentClass = oldCurrentClass; } void AbstractMetaBuilderPrivate::traverseNamespaceMembers(NamespaceModelItem item) { - AbstractMetaClass* metaClass = currentTraversedClass(item); + AbstractMetaClass* metaClass = m_itemToClass.value(item.data()); if (!metaClass) return; - AbstractMetaClass* oldCurrentClass = m_currentClass; - m_currentClass = metaClass; - // Namespace members traverseScopeMembers(item, metaClass); @@ -1219,7 +1150,6 @@ void AbstractMetaBuilderPrivate::traverseNamespaceMembers(NamespaceModelItem ite for (const NamespaceModelItem &ni : item->namespaces()) traverseNamespaceMembers(ni); - m_currentClass = oldCurrentClass; } static inline QString fieldSignatureWithType(const VariableModelItem &field) @@ -1234,10 +1164,10 @@ static inline QString qualifiedFieldSignatureWithType(const QString &className, } AbstractMetaField *AbstractMetaBuilderPrivate::traverseField(const VariableModelItem &field, - const AbstractMetaClass *cls) + AbstractMetaClass *cls) { QString fieldName = field->name(); - QString className = m_currentClass->typeEntry()->qualifiedCppName(); + QString className = cls->typeEntry()->qualifiedCppName(); // Ignore friend decl. if (field->isFriend()) @@ -1259,14 +1189,14 @@ AbstractMetaField *AbstractMetaBuilderPrivate::traverseField(const VariableModel metaField->setEnclosingClass(cls); TypeInfo fieldType = field->type(); - AbstractMetaType *metaType = translateType(fieldType); + AbstractMetaType *metaType = translateType(fieldType, cls); if (!metaType) { const QString type = TypeInfo::resolveType(fieldType, currentScope()).qualifiedName().join(colonColon()); - if (m_currentClass->typeEntry()->codeGeneration() & TypeEntry::GenerateTargetLang) { + if (cls->typeEntry()->codeGeneration() & TypeEntry::GenerateTargetLang) { qCWarning(lcShiboken).noquote().nospace() << QStringLiteral("skipping field '%1::%2' with unmatched type '%3'") - .arg(m_currentClass->name(), fieldName, type); + .arg(cls->name(), fieldName, type); } delete metaField; return 0; @@ -1369,14 +1299,15 @@ static bool _compareAbstractMetaFunctions(const AbstractMetaFunction* func, cons } AbstractMetaFunctionList AbstractMetaBuilderPrivate::classFunctionList(const ScopeModelItem &scopeItem, - AbstractMetaClass::Attributes *constructorAttributes) + AbstractMetaClass::Attributes *constructorAttributes, + AbstractMetaClass *currentClass) { *constructorAttributes = 0; AbstractMetaFunctionList result; const FunctionList &scopeFunctionList = scopeItem->functions(); result.reserve(scopeFunctionList.size()); for (const FunctionModelItem &function : scopeFunctionList) { - if (AbstractMetaFunction *metaFunction = traverseFunction(function)) { + if (AbstractMetaFunction *metaFunction = traverseFunction(function, currentClass)) { result.append(metaFunction); } else if (function->functionType() == CodeModel::Constructor) { auto arguments = function->arguments(); @@ -1416,7 +1347,7 @@ void AbstractMetaBuilderPrivate::traverseFunctions(ScopeModelItem scopeItem, { AbstractMetaAttributes::Attributes constructorAttributes; const AbstractMetaFunctionList functions = - classFunctionList(scopeItem, &constructorAttributes); + classFunctionList(scopeItem, &constructorAttributes, metaClass); metaClass->setAttributes(metaClass->attributes() | constructorAttributes); for (AbstractMetaFunction *metaFunction : functions){ @@ -1477,12 +1408,6 @@ void AbstractMetaBuilderPrivate::traverseFunctions(ScopeModelItem scopeItem, .arg(metaFunction->name(), metaClass->name()); } - if (metaFunction->isSignal() && !metaClass->isQObject()) { - qCWarning(lcShiboken).noquote().nospace() - << QStringLiteral("signal '%1' in non-QObject class '%2'") - .arg(metaFunction->name(), metaClass->name()); - } - if (metaFunction->isConversionOperator()) fixReturnTypeOfConversionOperator(metaFunction); @@ -1506,10 +1431,10 @@ void AbstractMetaBuilderPrivate::fillAddedFunctions(AbstractMetaClass *metaClass { // Add the functions added by the typesystem const AddedFunctionList &addedFunctions = metaClass->typeEntry()->addedFunctions(); - for (const AddedFunction &addedFunc : addedFunctions) { + for (const AddedFunctionPtr &addedFunc : addedFunctions) { if (!traverseFunction(addedFunc, metaClass)) { qFatal("Unable to traverse function \"%s\" added to \"%s\".", - qPrintable(addedFunc.name()), qPrintable(metaClass->name())); + qPrintable(addedFunc->name()), qPrintable(metaClass->name())); } } } @@ -1663,29 +1588,19 @@ void AbstractMetaBuilderPrivate::traverseEnums(const ScopeModelItem &scopeItem, } } -AbstractMetaFunction* AbstractMetaBuilderPrivate::traverseFunction(const AddedFunction& addedFunc) +AbstractMetaFunction* AbstractMetaBuilderPrivate::traverseFunction(const AddedFunctionPtr &addedFunc) { return traverseFunction(addedFunc, 0); } -AbstractMetaFunction* AbstractMetaBuilderPrivate::traverseFunction(const AddedFunction& addedFunc, +AbstractMetaFunction* AbstractMetaBuilderPrivate::traverseFunction(const AddedFunctionPtr &addedFunc, AbstractMetaClass *metaClass) { - AbstractMetaFunction *metaFunction = new AbstractMetaFunction; - metaFunction->setConstant(addedFunc.isConstant()); - metaFunction->setName(addedFunc.name()); - metaFunction->setOriginalName(addedFunc.name()); - AbstractMetaClass::Attributes visibility = - addedFunc.access() == AddedFunction::Public - ? AbstractMetaAttributes::Public : AbstractMetaAttributes::Protected; - metaFunction->setVisibility(visibility); - metaFunction->setUserAdded(true); - AbstractMetaAttributes::Attribute isStatic = addedFunc.isStatic() ? AbstractMetaFunction::Static : AbstractMetaFunction::None; - metaFunction->setAttributes(metaFunction->attributes() | AbstractMetaAttributes::FinalInTargetLang | isStatic); - metaFunction->setType(translateType(addedFunc.returnType())); - - - QVector<AddedFunction::TypeInfo> args = addedFunc.arguments(); + AbstractMetaFunction *metaFunction = new AbstractMetaFunction(addedFunc); + metaFunction->setType(translateType(addedFunc->returnType())); + + + QVector<AddedFunction::TypeInfo> args = addedFunc->arguments(); AbstractMetaArgumentList metaArguments; for (int i = 0; i < args.count(); ++i) { @@ -1695,7 +1610,7 @@ AbstractMetaFunction* AbstractMetaBuilderPrivate::traverseFunction(const AddedFu if (Q_UNLIKELY(!type)) { qCWarning(lcShiboken, "Unable to translate type \"%s\" of argument %d of added function \"%s\".", - qPrintable(typeInfo.name), i + 1, qPrintable(addedFunc.name())); + qPrintable(typeInfo.name), i + 1, qPrintable(addedFunc->name())); delete metaFunction; return nullptr; } @@ -1734,11 +1649,11 @@ AbstractMetaFunction* AbstractMetaBuilderPrivate::traverseFunction(const AddedFu //use relace-default-expression for set default value QString replacedExpression; - if (m_currentClass) - replacedExpression = metaFunction->replacedDefaultExpression(m_currentClass, i + 1); + if (metaClass) + replacedExpression = metaFunction->replacedDefaultExpression(metaClass, i + 1); if (!replacedExpression.isEmpty()) { - if (!metaFunction->removedDefaultExpression(m_currentClass, i + 1)) { + if (!metaFunction->removedDefaultExpression(metaClass, i + 1)) { metaArg->setDefaultValueExpression(replacedExpression); metaArg->setOriginalDefaultValueExpression(replacedExpression); } @@ -1747,7 +1662,7 @@ AbstractMetaFunction* AbstractMetaBuilderPrivate::traverseFunction(const AddedFu metaFunction->setOriginalAttributes(metaFunction->attributes()); if (!metaArguments.isEmpty()) - fixArgumentNames(metaFunction, metaFunction->modifications(m_currentClass)); + fixArgumentNames(metaFunction, metaFunction->modifications(metaClass)); if (metaClass) { const AbstractMetaArgumentList fargs = metaFunction->arguments(); @@ -1864,20 +1779,21 @@ static bool applyArrayArgumentModifications(const FunctionModificationList &func return true; } -AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(const FunctionModelItem &functionItem) +AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(const FunctionModelItem &functionItem, + AbstractMetaClass *currentClass) { if (functionItem->isDeleted() || !functionItem->templateParameters().isEmpty()) return nullptr; QString functionName = functionItem->name(); QString className; - if (m_currentClass) { + if (currentClass) { // Clang: Skip qt_metacast(), qt_metacall(), expanded from Q_OBJECT // and overridden metaObject(), QGADGET helpers if (functionName == QLatin1String("qt_check_for_QGADGET_macro") || functionName.startsWith(QLatin1String("qt_meta"))) { return nullptr; } - className = m_currentClass->typeEntry()->qualifiedCppName(); + className = currentClass->typeEntry()->qualifiedCppName(); if (functionName == QLatin1String("metaObject") && className != QLatin1String("QObject")) return nullptr; } @@ -1960,7 +1876,7 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(const Functio break; case AbstractMetaFunction::ConstructorFunction: metaFunction->setExplicit(functionItem->isExplicit()); - metaFunction->setName(m_currentClass->name()); + metaFunction->setName(currentClass->name()); break; default: { TypeInfo returnType = functionItem->type(); @@ -1973,7 +1889,7 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(const Functio AbstractMetaType *type = nullptr; if (!returnType.isVoid()) { - type = translateType(returnType, true, &errorMessage); + type = translateType(returnType, currentClass, true, &errorMessage); if (!type) { const QString reason = msgUnmatchedReturnType(functionItem, errorMessage); qCWarning(lcShiboken, "%s", @@ -2009,12 +1925,12 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(const Functio return nullptr; } - AbstractMetaType *metaType = translateType(arg->type(), true, &errorMessage); + AbstractMetaType *metaType = translateType(arg->type(), currentClass, true, &errorMessage); if (!metaType) { // If an invalid argument has a default value, simply remove it if (arg->defaultValue()) { - if (!m_currentClass - || (m_currentClass->typeEntry()->codeGeneration() + if (!currentClass + || (currentClass->typeEntry()->codeGeneration() & TypeEntry::GenerateTargetLang)) { qCWarning(lcShiboken).noquote().nospace() << "Stripping argument #" << (i + 1) << " of " @@ -2046,7 +1962,7 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(const Functio metaFunction->setArguments(metaArguments); - const FunctionModificationList functionMods = metaFunction->modifications(m_currentClass); + const FunctionModificationList functionMods = metaFunction->modifications(currentClass); for (const FunctionModification &mod : functionMods) { if (mod.exceptionHandling() != TypeSystem::ExceptionHandling::Unspecified) @@ -2062,8 +1978,8 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(const Functio //use relace-default-expression for set default value QString replacedExpression; - if (m_currentClass) { - replacedExpression = metaFunction->replacedDefaultExpression(m_currentClass, i + 1); + if (currentClass) { + replacedExpression = metaFunction->replacedDefaultExpression(currentClass, i + 1); } else { if (!functionMods.isEmpty()) { QVector<ArgumentModification> argMods = functionMods.constFirst().argument_mods; @@ -2075,10 +1991,10 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(const Functio bool hasDefaultValue = false; if (arg->defaultValue() || !replacedExpression.isEmpty()) { QString expr = arg->defaultValueExpression(); - expr = fixDefaultValue(arg, metaArg->type(), metaFunction, m_currentClass, i); + expr = fixDefaultValue(arg, metaArg->type(), metaFunction, currentClass, i); metaArg->setOriginalDefaultValueExpression(expr); - if (metaFunction->removedDefaultExpression(m_currentClass, i + 1)) { + if (metaFunction->removedDefaultExpression(currentClass, i + 1)) { expr.clear(); } else if (!replacedExpression.isEmpty()) { expr = replacedExpression; @@ -2092,7 +2008,7 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(const Functio && !metaArg->hasName() && !metaFunction->isOperatorOverload() && !metaFunction->isSignal() - && metaFunction->argumentName(i+1, false, m_currentClass).isEmpty()) { + && metaFunction->argumentName(i + 1, false, currentClass).isEmpty()) { qCWarning(lcShiboken).noquote().nospace() << QStringLiteral("Argument %1 on function '%2::%3' has default expression but does not have name.") .arg(i+1).arg(className, metaFunction->minimalSignature()); @@ -2110,9 +2026,9 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(const Functio } // Determine class special functions - if (m_currentClass && metaFunction->arguments().size() == 1) { + if (currentClass && metaFunction->arguments().size() == 1) { const AbstractMetaType *argType = metaFunction->arguments().constFirst()->type(); - if (argType->typeEntry() == m_currentClass->typeEntry() && argType->indirections() == 0) { + if (argType->typeEntry() == currentClass->typeEntry() && argType->indirections() == 0) { if (metaFunction->name() == QLatin1String("operator=")) { switch (argType->referenceType()) { case NoReference: @@ -2212,10 +2128,11 @@ static const TypeEntry* findTypeEntryUsingContext(const AbstractMetaClass* metaC } AbstractMetaType *AbstractMetaBuilderPrivate::translateType(const TypeInfo &_typei, + AbstractMetaClass *currentClass, bool resolveType, QString *errorMessage) { - return translateTypeStatic(_typei, m_currentClass, this, resolveType, errorMessage); + return translateTypeStatic(_typei, currentClass, this, resolveType, errorMessage); } AbstractMetaType *AbstractMetaBuilderPrivate::translateTypeStatic(const TypeInfo &_typei, @@ -2575,38 +2492,6 @@ QString AbstractMetaBuilderPrivate::fixDefaultValue(const ArgumentModelItem &ite return expr; } -bool AbstractMetaBuilderPrivate::isQObject(const FileModelItem &dom, const QString &qualifiedName) -{ - if (qualifiedName == QLatin1String("QObject")) - return true; - - ClassModelItem classItem = dom->findClass(qualifiedName); - - if (!classItem) { - QStringList names = qualifiedName.split(colonColon()); - NamespaceModelItem ns = dom; - for (int i = 0; i < names.size() - 1 && ns; ++i) - ns = ns->findNamespace(names.at(i)); - if (ns && names.size() >= 2) - classItem = ns->findClass(names.at(names.size() - 1)); - } - - if (!classItem) - return false; - - if (classItem->extendsClass(QLatin1String("QObject"))) - return true; - - const QVector<_ClassModelItem::BaseClass> &baseClasses = classItem->baseClasses(); - for (const _ClassModelItem::BaseClass &baseClass : baseClasses) { - if (isQObject(dom, baseClass.name)) - return true; - } - - return false; -} - - bool AbstractMetaBuilderPrivate::isEnum(const FileModelItem &dom, const QStringList& qualified_name) { CodeModelItem item = dom->model()->findItem(qualified_name, dom); @@ -2910,21 +2795,19 @@ bool AbstractMetaBuilderPrivate::inheritTemplate(AbstractMetaClass *subclass, void AbstractMetaBuilderPrivate::parseQ_Property(AbstractMetaClass *metaClass, const QStringList &declarations) { - for (int i = 0; i < declarations.size(); ++i) { - const QString &p = declarations.at(i); - - QStringList l = p.split(QLatin1Char(' ')); + const QStringList scopes = currentScope()->qualifiedName(); + for (int i = 0; i < declarations.size(); ++i) { + const auto propertyTokens = declarations.at(i).splitRef(QLatin1Char(' ')); - QStringList qualifiedScopeName = currentScope()->qualifiedName(); - AbstractMetaType* type = 0; - QString scope; - for (int j = qualifiedScopeName.size(); j >= 0; --j) { - scope = j > 0 ? QStringList(qualifiedScopeName.mid(0, j)).join(colonColon()) + colonColon() : QString(); + AbstractMetaType *type = nullptr; + for (int j = scopes.size(); j >= 0; --j) { + QStringList qualifiedName = scopes.mid(0, j); + qualifiedName.append(propertyTokens.at(0).toString()); TypeInfo info; - info.setQualifiedName((scope + l.at(0)).split(colonColon())); + info.setQualifiedName(qualifiedName); - type = translateType(info); + type = translateType(info, metaClass); if (type) break; } @@ -2932,23 +2815,23 @@ void AbstractMetaBuilderPrivate::parseQ_Property(AbstractMetaClass *metaClass, if (!type) { qCWarning(lcShiboken).noquote().nospace() << QStringLiteral("Unable to decide type of property: '%1' in class '%2'") - .arg(l.at(0), metaClass->name()); + .arg(propertyTokens.at(0).toString(), metaClass->name()); continue; } QPropertySpec* spec = new QPropertySpec(type->typeEntry()); - spec->setName(l.at(1)); + spec->setName(propertyTokens.at(1).toString()); spec->setIndex(i); - for (int pos = 2; pos + 1 < l.size(); pos += 2) { - if (l.at(pos) == QLatin1String("READ")) - spec->setRead(l.at(pos + 1)); - else if (l.at(pos) == QLatin1String("WRITE")) - spec->setWrite(l.at(pos + 1)); - else if (l.at(pos) == QLatin1String("DESIGNABLE")) - spec->setDesignable(l.at(pos + 1)); - else if (l.at(pos) == QLatin1String("RESET")) - spec->setReset(l.at(pos + 1)); + for (int pos = 2; pos + 1 < propertyTokens.size(); pos += 2) { + if (propertyTokens.at(pos) == QLatin1String("READ")) + spec->setRead(propertyTokens.at(pos + 1).toString()); + else if (propertyTokens.at(pos) == QLatin1String("WRITE")) + spec->setWrite(propertyTokens.at(pos + 1).toString()); + else if (propertyTokens.at(pos) == QLatin1String("DESIGNABLE")) + spec->setDesignable(propertyTokens.at(pos + 1).toString()); + else if (propertyTokens.at(pos) == QLatin1String("RESET")) + spec->setReset(propertyTokens.at(pos + 1).toString()); } metaClass->addPropertySpec(spec); @@ -3214,16 +3097,60 @@ void AbstractMetaBuilder::setGlobalHeader(const QString& globalHeader) d->m_globalHeader = QFileInfo(globalHeader); } +void AbstractMetaBuilder::setHeaderPaths(const HeaderPaths &hp) +{ + for (const auto & h: hp) { + if (h.type != HeaderType::Framework && h.type != HeaderType::FrameworkSystem) + d->m_headerPaths.append(QFile::decodeName(h.path)); + } +} + void AbstractMetaBuilder::setSkipDeprecated(bool value) { d->m_skipDeprecated = value; } +// PYSIDE-975: When receiving an absolute path name from the code model, try +// to resolve it against the include paths set on shiboken in order to recreate +// relative paths like #include <foo/bar.h>. + +static inline bool isFileSystemSlash(QChar c) +{ + return c == QLatin1Char('/') || c == QLatin1Char('\\'); +} + +static bool matchHeader(const QString &headerPath, const QString &fileName) +{ +#if defined(Q_OS_WIN) || defined(Q_OS_DARWIN) + static const Qt::CaseSensitivity caseSensitivity = Qt::CaseInsensitive; +#else + static const Qt::CaseSensitivity caseSensitivity = Qt::CaseSensitive; +#endif + const int pathSize = headerPath.size(); + return fileName.size() > pathSize + && isFileSystemSlash(fileName.at(pathSize)) + && fileName.startsWith(headerPath, caseSensitivity); +} + void AbstractMetaBuilderPrivate::setInclude(TypeEntry *te, const QString &fileName) const { - QFileInfo info(fileName); - if (m_globalHeader.fileName() != info.fileName()) - te->setInclude(Include(Include::IncludePath, info.fileName())); + auto it = m_resolveIncludeHash.find(fileName); + if (it == m_resolveIncludeHash.end()) { + QFileInfo info(fileName); + if (m_globalHeader.fileName() == info.fileName()) + return; + + int bestMatchLength = 0; + for (const auto &headerPath : m_headerPaths) { + if (headerPath.size() > bestMatchLength && matchHeader(headerPath, fileName)) + bestMatchLength = headerPath.size(); + } + const QString include = bestMatchLength > 0 + ? fileName.right(fileName.size() - bestMatchLength - 1) + : info.fileName(); + it = m_resolveIncludeHash.insert(fileName, {Include::IncludePath, include}); + } + te->setInclude(it.value()); } #ifndef QT_NO_DEBUG_STREAM diff --git a/sources/shiboken2/ApiExtractor/abstractmetabuilder.h b/sources/shiboken2/ApiExtractor/abstractmetabuilder.h index ed89060ac..1789ca2aa 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetabuilder.h +++ b/sources/shiboken2/ApiExtractor/abstractmetabuilder.h @@ -30,6 +30,7 @@ #define ABSTRACTMETABUILDER_H #include "abstractmetalang_typedefs.h" +#include "header_paths.h" #include "dependency.h" #include "clangparser/compilersupport.h" @@ -85,6 +86,7 @@ public: * filled. */ void setGlobalHeader(const QString& globalHeader); + void setHeaderPaths(const HeaderPaths &h); void setSkipDeprecated(bool value); diff --git a/sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h b/sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h index d8203a586..3c0039f0e 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h +++ b/sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h @@ -60,15 +60,17 @@ public: ScopeModelItem currentScope() const { return m_scopes.constLast(); } - AbstractMetaClass *argumentToClass(const ArgumentModelItem &); + AbstractMetaClass *argumentToClass(const ArgumentModelItem &, + AbstractMetaClass *currentClass); - void addAbstractMetaClass(AbstractMetaClass *cls); + void addAbstractMetaClass(AbstractMetaClass *cls, const _CodeModelItem *item); AbstractMetaClass *traverseTypeDef(const FileModelItem &dom, - const TypeDefModelItem &typeDef); + const TypeDefModelItem &typeDef, + AbstractMetaClass *currentClass); void traverseTypesystemTypedefs(); AbstractMetaClass *traverseClass(const FileModelItem &dom, - const ClassModelItem &item); - AbstractMetaClass *currentTraversedClass(ScopeModelItem item); + const ClassModelItem &item, + AbstractMetaClass *currentClass); void traverseScopeMembers(ScopeModelItem item, AbstractMetaClass *metaClass); void traverseClassMembers(ClassModelItem scopeItem); void traverseNamespaceMembers(NamespaceModelItem scopeItem); @@ -80,24 +82,30 @@ public: void traverseEnums(const ScopeModelItem &item, AbstractMetaClass *parent, const QStringList &enumsDeclarations); AbstractMetaFunctionList classFunctionList(const ScopeModelItem &scopeItem, - AbstractMetaClass::Attributes *constructorAttributes); + AbstractMetaClass::Attributes *constructorAttributes, + AbstractMetaClass *currentClass); AbstractMetaFunctionList templateClassFunctionList(const ScopeModelItem &scopeItem, AbstractMetaClass *metaClass, bool *constructorRejected); void traverseFunctions(ScopeModelItem item, AbstractMetaClass *parent); void applyFunctionModifications(AbstractMetaFunction* func); void traverseFields(const ScopeModelItem &item, AbstractMetaClass *parent); - void traverseStreamOperator(const FunctionModelItem &functionItem); - void traverseOperatorFunction(const FunctionModelItem &item); - AbstractMetaFunction* traverseFunction(const AddedFunction &addedFunc); - AbstractMetaFunction* traverseFunction(const AddedFunction &addedFunc, + void traverseStreamOperator(const FunctionModelItem &functionItem, + AbstractMetaClass *currentClass); + void traverseOperatorFunction(const FunctionModelItem &item, + AbstractMetaClass *currentClass); + AbstractMetaFunction* traverseFunction(const AddedFunctionPtr &addedFunc); + AbstractMetaFunction* traverseFunction(const AddedFunctionPtr &addedFunc, AbstractMetaClass *metaClass); - AbstractMetaFunction *traverseFunction(const FunctionModelItem &function); + AbstractMetaFunction *traverseFunction(const FunctionModelItem &function, + AbstractMetaClass *currentClass); AbstractMetaField *traverseField(const VariableModelItem &field, - const AbstractMetaClass *cls); + AbstractMetaClass *cls); void checkFunctionModifications(); - void registerHashFunction(const FunctionModelItem &functionItem); - void registerToStringCapability(const FunctionModelItem &functionItem); + void registerHashFunction(const FunctionModelItem &functionItem, + AbstractMetaClass *currentClass); + void registerToStringCapability(const FunctionModelItem &functionItem, + AbstractMetaClass *currentClass); /** * A conversion operator function should not have its owner class as @@ -124,6 +132,7 @@ public: int argumentIndex); AbstractMetaType *translateType(const AddedFunction::TypeInfo &typeInfo); AbstractMetaType *translateType(const TypeInfo &type, + AbstractMetaClass *currentClass, bool resolveType = true, QString *errorMessage = nullptr); static AbstractMetaType *translateTypeStatic(const TypeInfo &type, @@ -149,9 +158,6 @@ public: bool isQObject(const FileModelItem &dom, const QString &qualifiedName); bool isEnum(const FileModelItem &dom, const QStringList &qualifiedName); - void fixQObjectForScope(const FileModelItem &dom, const TypeDatabase *types, - const NamespaceModelItem &item); - void sortLists(); AbstractMetaArgumentList reverseList(const AbstractMetaArgumentList &list); void setInclude(TypeEntry *te, const QString &fileName) const; @@ -163,6 +169,7 @@ public: AbstractMetaClassList m_metaClasses; AbstractMetaClassList m_templates; AbstractMetaClassList m_smartPointers; + QHash<const _CodeModelItem *, AbstractMetaClass *> m_itemToClass; AbstractMetaFunctionList m_globalFunctions; AbstractMetaEnumList m_globalEnums; @@ -175,14 +182,14 @@ public: QHash<const TypeEntry *, AbstractMetaEnum *> m_enums; - AbstractMetaClass *m_currentClass; QList<ScopeModelItem> m_scopes; - QString m_namespacePrefix; QSet<AbstractMetaClass *> m_setupInheritanceDone; QString m_logDirectory; QFileInfo m_globalHeader; + QStringList m_headerPaths; + mutable QHash<QString, Include> m_resolveIncludeHash; bool m_skipDeprecated; }; diff --git a/sources/shiboken2/ApiExtractor/abstractmetalang.cpp b/sources/shiboken2/ApiExtractor/abstractmetalang.cpp index 95f8048cd..512efef58 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetalang.cpp +++ b/sources/shiboken2/ApiExtractor/abstractmetalang.cpp @@ -288,8 +288,7 @@ AbstractMetaType::TypeUsagePattern AbstractMetaType::determineUsagePattern() con if (m_typeEntry->isObject()) { if (indirections() == 0 && m_referenceType == NoReference) return ValuePattern; - return static_cast<const ComplexTypeEntry *>(m_typeEntry)->isQObject() - ? QObjectPattern : ObjectPattern; + return ObjectPattern; } if (m_typeEntry->isContainer() && indirections() == 0) @@ -322,8 +321,7 @@ void AbstractMetaType::decideUsagePattern() // const-references to pointers can be passed as pointers setReferenceType(NoReference); setConstant(false); - pattern = static_cast<const ComplexTypeEntry *>(m_typeEntry)->isQObject() - ? QObjectPattern : ObjectPattern; + pattern = ObjectPattern; } setTypeUsagePattern(pattern); } @@ -454,10 +452,32 @@ QDebug operator<<(QDebug d, const AbstractMetaArgument *aa) * AbstractMetaFunction */ +AbstractMetaFunction::AbstractMetaFunction(const AddedFunctionPtr &addedFunc) : + AbstractMetaFunction() +{ + m_addedFunction = addedFunc; + setConstant(addedFunc->isConstant()); + setName(addedFunc->name()); + setOriginalName(addedFunc->name()); + auto atts = attributes() | AbstractMetaAttributes::FinalInTargetLang; + switch (addedFunc->access()) { + case AddedFunction::InvalidAccess: + break; + case AddedFunction::Protected: + atts |= AbstractMetaAttributes::Protected; + break; + case AddedFunction::Public: + atts |= AbstractMetaAttributes::Public; + break; + } + if (addedFunc->isStatic()) + atts |= AbstractMetaFunction::Static; + setAttributes(atts); +} + AbstractMetaFunction::AbstractMetaFunction() : m_constant(false), m_reverse(false), - m_userAdded(false), m_explicit(false), m_pointerOperator(false), m_isCallOperator(false) @@ -581,6 +601,7 @@ AbstractMetaFunction *AbstractMetaFunction::copy() const cpy->setExceptionSpecification(m_exceptionSpecification); cpy->setAllowThreadModification(m_allowThreadModification); cpy->setExceptionHandlingModification(m_exceptionHandlingModification); + cpy->m_addedFunction = m_addedFunction; for (AbstractMetaArgument *arg : m_arguments) cpy->addArgument(arg->copy()); @@ -944,6 +965,8 @@ QString AbstractMetaFunction::debugSignature() const FunctionModificationList AbstractMetaFunction::modifications(const AbstractMetaClass* implementor) const { + if (!m_addedFunction.isNull()) + return m_addedFunction->modifications; if (!implementor) implementor = ownerClass(); @@ -1281,7 +1304,7 @@ void AbstractMetaFunction::formatDebugVerbose(QDebug &d) const d << " [const]"; if (m_reverse) d << " [reverse]"; - if (m_userAdded) + if (isUserAdded()) d << " [userAdded]"; if (m_explicit) d << " [explicit]"; @@ -1636,9 +1659,14 @@ bool AbstractMetaClass::isNamespace() const return m_typeEntry->isNamespace(); } +static bool qObjectPredicate(const AbstractMetaClass *c) +{ + return c->qualifiedCppName() == QLatin1String("QObject"); +} + bool AbstractMetaClass::isQObject() const { - return m_typeEntry->isQObject(); + return qObjectPredicate(this) || recurseClassHierarchy(this, qObjectPredicate) != nullptr; } QString AbstractMetaClass::qualifiedCppName() const diff --git a/sources/shiboken2/ApiExtractor/abstractmetalang.h b/sources/shiboken2/ApiExtractor/abstractmetalang.h index 0c652a39a..ef4cef2b4 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetalang.h +++ b/sources/shiboken2/ApiExtractor/abstractmetalang.h @@ -301,7 +301,6 @@ public: EnumPattern, ValuePattern, ObjectPattern, - QObjectPattern, ValuePointerPattern, NativePointerPattern, NativePointerAsArrayPattern, // "int*" as "int[]" @@ -376,12 +375,6 @@ public: return m_pattern == EnumPattern; } - // returns true if the type is used as a QObject * - bool isQObject() const - { - return m_pattern == QObjectPattern; - } - // returns true if the type is used as an object, e.g. Xxx * bool isObject() const { @@ -790,6 +783,7 @@ public: Q_FLAG(CompareResultFlag) AbstractMetaFunction(); + explicit AbstractMetaFunction(const AddedFunctionPtr &addedFunc); ~AbstractMetaFunction(); QString name() const @@ -1010,14 +1004,7 @@ public: } /// Returns true if the AbstractMetaFunction was added by the user via the type system description. - bool isUserAdded() const - { - return m_userAdded; - } - void setUserAdded(bool userAdded) - { - m_userAdded = userAdded; - } + bool isUserAdded() const { return !m_addedFunction.isNull(); } QString toString() const { @@ -1125,9 +1112,9 @@ private: const AbstractMetaClass *m_declaringClass = nullptr; QPropertySpec *m_propertySpec = nullptr; AbstractMetaArgumentList m_arguments; + AddedFunctionPtr m_addedFunction; uint m_constant : 1; uint m_reverse : 1; - uint m_userAdded : 1; uint m_explicit : 1; uint m_pointerOperator : 1; uint m_isCallOperator : 1; diff --git a/sources/shiboken2/ApiExtractor/apiextractor.cpp b/sources/shiboken2/ApiExtractor/apiextractor.cpp index e301d891f..fbe7664e9 100644 --- a/sources/shiboken2/ApiExtractor/apiextractor.cpp +++ b/sources/shiboken2/ApiExtractor/apiextractor.cpp @@ -224,6 +224,7 @@ bool ApiExtractor::run() m_builder->setLogDirectory(m_logDirectory); m_builder->setGlobalHeader(m_cppFileName); m_builder->setSkipDeprecated(m_skipDeprecated); + m_builder->setHeaderPaths(m_includePaths); QByteArrayList arguments; arguments.reserve(m_includePaths.size() + 1); for (const HeaderPath &headerPath : qAsConst(m_includePaths)) diff --git a/sources/shiboken2/ApiExtractor/messages.cpp b/sources/shiboken2/ApiExtractor/messages.cpp index fa4c75743..fdae2359b 100644 --- a/sources/shiboken2/ApiExtractor/messages.cpp +++ b/sources/shiboken2/ApiExtractor/messages.cpp @@ -167,6 +167,12 @@ QString msgSkippingFunction(const FunctionModelItem &functionItem, return result; } +QString msgCannotResolveEntity(const QString &name, const QString &reason) +{ + return QLatin1String("Cannot resolve entity \"") + name + + QLatin1String("\": ") + reason; +} + QString msgCannotSetArrayUsage(const QString &function, int i, const QString &reason) { return function + QLatin1String(": Cannot use parameter ") diff --git a/sources/shiboken2/ApiExtractor/messages.h b/sources/shiboken2/ApiExtractor/messages.h index 539332aef..30b13fbf8 100644 --- a/sources/shiboken2/ApiExtractor/messages.h +++ b/sources/shiboken2/ApiExtractor/messages.h @@ -68,6 +68,8 @@ QString msgUnmatchedReturnType(const FunctionModelItem &functionItem, QString msgSkippingFunction(const FunctionModelItem &functionItem, const QString &signature, const QString &why); +QString msgCannotResolveEntity(const QString &name, const QString &reason); + QString msgCannotSetArrayUsage(const QString &function, int i, const QString &reason); QString msgUnableToTranslateType(const QString &t, const QString &why); diff --git a/sources/shiboken2/ApiExtractor/parser/codemodel.cpp b/sources/shiboken2/ApiExtractor/parser/codemodel.cpp index 8bc9b24ac..9a845b04a 100644 --- a/sources/shiboken2/ApiExtractor/parser/codemodel.cpp +++ b/sources/shiboken2/ApiExtractor/parser/codemodel.cpp @@ -83,37 +83,35 @@ FileModelItem CodeModel::findFile(const QString &name) const return findModelItem(m_files, name); } -CodeModelItem CodeModel::findItem(const QStringList &qualifiedName, CodeModelItem scope) const -{ - for (int i = 0; i < qualifiedName.size(); ++i) { - // ### Extend to look for members etc too. - const QString &name = qualifiedName.at(i); - - if (NamespaceModelItem ns = qSharedPointerDynamicCast<_NamespaceModelItem>(scope)) { - if (NamespaceModelItem tmp_ns = ns->findNamespace(name)) { - scope = tmp_ns; - continue; - } - } - - if (ScopeModelItem ss = qSharedPointerDynamicCast<_ScopeModelItem>(scope)) { - if (ClassModelItem cs = ss->findClass(name)) { - scope = cs; - } else if (EnumModelItem es = ss->findEnum(name)) { - if (i == qualifiedName.size() - 1) - return es; - } else if (TypeDefModelItem tp = ss->findTypeDef(name)) { - if (i == qualifiedName.size() - 1) - return tp; - } else { - // If we don't find the name in the scope chain we - // need to return an empty item to indicate failure... - return CodeModelItem(); +static CodeModelItem findRecursion(const ScopeModelItem &scope, + const QStringList &qualifiedName, int segment = 0) +{ + const QString &nameSegment = qualifiedName.at(segment); + if (segment == qualifiedName.size() - 1) { // Leaf item + if (ClassModelItem cs = scope->findClass(nameSegment)) + return cs; + if (EnumModelItem es = scope->findEnum(nameSegment)) + return es; + if (TypeDefModelItem tp = scope->findTypeDef(nameSegment)) + return tp; + return CodeModelItem(); + } + if (auto nestedClass = scope->findClass(nameSegment)) + return findRecursion(nestedClass, qualifiedName, segment + 1); + if (auto namespaceItem = qSharedPointerDynamicCast<_NamespaceModelItem>(scope)) { + for (const auto &nestedNamespace : namespaceItem->namespaces()) { + if (nestedNamespace->name() == nameSegment) { + if (auto item = findRecursion(nestedNamespace, qualifiedName, segment + 1)) + return item; } } } + return CodeModelItem(); +} - return scope; +CodeModelItem CodeModel::findItem(const QStringList &qualifiedName, const ScopeModelItem &scope) const +{ + return findRecursion(scope, qualifiedName); } #ifndef QT_NO_DEBUG_STREAM @@ -160,7 +158,7 @@ bool TypeInfo::isVoid() const && m_qualifiedName.constFirst() == QLatin1String("void"); } -TypeInfo TypeInfo::resolveType(TypeInfo const &__type, CodeModelItem __scope) +TypeInfo TypeInfo::resolveType(TypeInfo const &__type, const ScopeModelItem &__scope) { CodeModel *__model = __scope->model(); Q_ASSERT(__model != 0); @@ -168,7 +166,7 @@ TypeInfo TypeInfo::resolveType(TypeInfo const &__type, CodeModelItem __scope) return TypeInfo::resolveType(__model->findItem(__type.qualifiedName(), __scope), __type, __scope); } -TypeInfo TypeInfo::resolveType(CodeModelItem __item, TypeInfo const &__type, CodeModelItem __scope) +TypeInfo TypeInfo::resolveType(CodeModelItem __item, TypeInfo const &__type, const ScopeModelItem &__scope) { // Copy the type and replace with the proper qualified name. This // only makes sence to do if we're actually getting a resolved diff --git a/sources/shiboken2/ApiExtractor/parser/codemodel.h b/sources/shiboken2/ApiExtractor/parser/codemodel.h index 0296a8cb2..64415e07b 100644 --- a/sources/shiboken2/ApiExtractor/parser/codemodel.h +++ b/sources/shiboken2/ApiExtractor/parser/codemodel.h @@ -82,7 +82,7 @@ public: void addFile(FileModelItem item); FileModelItem findFile(const QString &name) const; - CodeModelItem findItem(const QStringList &qualifiedName, CodeModelItem scope) const; + CodeModelItem findItem(const QStringList &qualifiedName, const ScopeModelItem &scope) const; private: FileList m_files; @@ -202,7 +202,7 @@ public: QString toString() const; static TypeInfo combine(const TypeInfo &__lhs, const TypeInfo &__rhs); - static TypeInfo resolveType(TypeInfo const &__type, CodeModelItem __scope); + static TypeInfo resolveType(TypeInfo const &__type, const ScopeModelItem &__scope); #ifndef QT_NO_DEBUG_STREAM void formatDebug(QDebug &d) const; @@ -219,7 +219,7 @@ public: private: friend class TypeInfoTemplateArgumentHandler; - static TypeInfo resolveType(CodeModelItem item, TypeInfo const &__type, CodeModelItem __scope); + static TypeInfo resolveType(CodeModelItem item, TypeInfo const &__type, const ScopeModelItem &__scope); QStringList m_qualifiedName; QStringList m_arrayElements; diff --git a/sources/shiboken2/ApiExtractor/tests/CMakeLists.txt b/sources/shiboken2/ApiExtractor/tests/CMakeLists.txt index e100ef493..a36cc17de 100644 --- a/sources/shiboken2/ApiExtractor/tests/CMakeLists.txt +++ b/sources/shiboken2/ApiExtractor/tests/CMakeLists.txt @@ -1,9 +1,3 @@ -find_package(Qt5Core) -find_package(Qt5Gui) -find_package(Qt5Test) -find_package(Qt5Xml) -find_package(Qt5XmlPatterns) - set(CMAKE_AUTORCC ON) macro(declare_test testname) @@ -15,19 +9,13 @@ macro(declare_test testname) if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${testname}.qrc") list(APPEND SOURCES "${testname}.qrc") endif () + add_executable(${testname} ${SOURCES}) - include_directories(${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_CURRENT_BINARY_DIR} - ${apiextractor_SOURCE_DIR} - ${Qt5Test_INCLUDE_DIRS} - ) - link_directories(${APIEXTRACTOR_EXTRA_LINK_DIRECTORIES}) - target_link_libraries(${testname} - ${Qt5XmlPatterns_LIBRARIES} - ${Qt5Test_LIBRARIES} - ${Qt5Core_LIBRARIES} - ${Qt5Gui_LIBRARIES} - apiextractor) + target_include_directories(${testname} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_BINARY_DIR} + ${apiextractor_SOURCE_DIR} + ) + target_link_libraries(${testname} PRIVATE apiextractor Qt5::Test) add_test(${testname} ${testname}) if (INSTALL_TESTS) install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/${testname} diff --git a/sources/shiboken2/ApiExtractor/tests/testabstractmetatype.cpp b/sources/shiboken2/ApiExtractor/tests/testabstractmetatype.cpp index fc67ebba5..63434b3a5 100644 --- a/sources/shiboken2/ApiExtractor/tests/testabstractmetatype.cpp +++ b/sources/shiboken2/ApiExtractor/tests/testabstractmetatype.cpp @@ -85,7 +85,6 @@ void TestAbstractMetaType::testConstCharPtrType() QVERIFY(!rtype->isObject()); QVERIFY(!rtype->isPrimitive()); // const char* differs from char, so it's not considered a primitive type by apiextractor QVERIFY(rtype->isNativePointer()); - QVERIFY(!rtype->isQObject()); QCOMPARE(rtype->referenceType(), NoReference); QVERIFY(!rtype->isValue()); QVERIFY(!rtype->isValuePointer()); @@ -159,7 +158,6 @@ void TestAbstractMetaType::testCharType() QVERIFY(!rtype->isObject()); QVERIFY(rtype->isPrimitive()); QVERIFY(!rtype->isNativePointer()); - QVERIFY(!rtype->isQObject()); QCOMPARE(rtype->referenceType(), NoReference); QVERIFY(!rtype->isValue()); QVERIFY(!rtype->isValuePointer()); diff --git a/sources/shiboken2/ApiExtractor/tests/testaddfunction.cpp b/sources/shiboken2/ApiExtractor/tests/testaddfunction.cpp index db49942c9..8c443527e 100644 --- a/sources/shiboken2/ApiExtractor/tests/testaddfunction.cpp +++ b/sources/shiboken2/ApiExtractor/tests/testaddfunction.cpp @@ -71,26 +71,32 @@ void TestAddFunction::testParsingFuncNameAndConstness() void TestAddFunction::testAddFunction() { - const char cppCode[] = "struct B {}; struct A { void a(int); };\n"; - const char xmlCode[] = "\ - <typesystem package='Foo'>\n\ - <primitive-type name='int'/>\n\ - <primitive-type name='float'/>\n\ - <value-type name='B'/>\n\ - <value-type name='A'>\n\ - <add-function signature='b(int, float = 4.6, const B&)' return-type='int' access='protected'>\n\ - </add-function>\n\ - </value-type>\n\ - </typesystem>\n"; + const char cppCode[] = R"CPP( +struct B {}; +struct A { + void a(int); +};)CPP"; + const char xmlCode[] = R"XML( +<typesystem package='Foo'> + <primitive-type name='int'/> + <primitive-type name='float'/> + <value-type name='B'/> + <value-type name='A'> + <add-function signature='b(int, float = 4.6, const B&)' return-type='int' access='protected'/> + <add-function signature='operator()(int)' return-type='int' access='public'/> + </value-type> +</typesystem>)XML"; + QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); QVERIFY(!builder.isNull()); TypeDatabase* typeDb = TypeDatabase::instance(); AbstractMetaClassList classes = builder->classes(); const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); QVERIFY(classA); - QCOMPARE(classA->functions().count(), 4); // default ctor, default copy ctor, func a() and the added function + QCOMPARE(classA->functions().count(), 5); // default ctor, default copy ctor, func a() and the added functions - AbstractMetaFunction* addedFunc = classA->functions().last(); + auto addedFunc = classA->findFunction(QLatin1String("b")); + QVERIFY(addedFunc); QCOMPARE(addedFunc->visibility(), AbstractMetaFunction::Protected); QCOMPARE(addedFunc->functionType(), AbstractMetaFunction::NormalFunction); QVERIFY(addedFunc->isUserAdded()); @@ -109,6 +115,9 @@ void TestAddFunction::testAddFunction() QCOMPARE(args[0]->type()->typeEntry(), returnType->typeEntry()); QCOMPARE(args[1]->defaultValueExpression(), QLatin1String("4.6")); QCOMPARE(args[2]->type()->typeEntry(), typeDb->findType(QLatin1String("B"))); + + auto addedCallOperator = classA->findFunction(QLatin1String("operator()")); + QVERIFY(addedCallOperator); } void TestAddFunction::testAddFunctionConstructor() @@ -265,7 +274,7 @@ void TestAddFunction::testAddFunctionAtModuleLevel() QCOMPARE(addedFuncs.size(), 1); - FunctionModificationList mods = typeDb->functionModifications(QLatin1String("func(int,int)")); + const FunctionModificationList mods = addedFuncs.constFirst()->modifications; QCOMPARE(mods.size(), 1); QVERIFY(mods.first().isCodeInjection()); diff --git a/sources/shiboken2/ApiExtractor/typedatabase.cpp b/sources/shiboken2/ApiExtractor/typedatabase.cpp index 4ce2790f5..a8c69d376 100644 --- a/sources/shiboken2/ApiExtractor/typedatabase.cpp +++ b/sources/shiboken2/ApiExtractor/typedatabase.cpp @@ -430,8 +430,8 @@ void TypeDatabase::addGlobalUserFunctions(const AddedFunctionList &functions) AddedFunctionList TypeDatabase::findGlobalUserFunctions(const QString& name) const { AddedFunctionList addedFunctions; - for (const AddedFunction &func : m_globalUserFunctions) { - if (func.name() == name) + for (const AddedFunctionPtr &func : m_globalUserFunctions) { + if (func->name() == name) addedFunctions.append(func); } return addedFunctions; @@ -802,7 +802,6 @@ void ComplexTypeEntry::formatDebug(QDebug &d) const { TypeEntry::formatDebug(d); FORMAT_NONEMPTY_STRING("targetLangName", m_targetLangName) - FORMAT_BOOL("QObject", m_qobject) FORMAT_BOOL("polymorphicBase", m_polymorphicBase) FORMAT_BOOL("genericClass", m_genericClass) FORMAT_BOOL("deleteInMainThread", m_deleteInMainThread) diff --git a/sources/shiboken2/ApiExtractor/typesystem.cpp b/sources/shiboken2/ApiExtractor/typesystem.cpp index ad97e40ee..318a52e2e 100644 --- a/sources/shiboken2/ApiExtractor/typesystem.cpp +++ b/sources/shiboken2/ApiExtractor/typesystem.cpp @@ -40,6 +40,7 @@ #include <QtCore/QStringAlgorithms> #include <QtCore/QXmlStreamAttributes> #include <QtCore/QXmlStreamReader> +#include <QtCore/QXmlStreamEntityResolver> #include <algorithm> @@ -105,6 +106,8 @@ static inline QString yesAttributeValue() { return QStringLiteral("yes"); } static inline QString trueAttributeValue() { return QStringLiteral("true"); } static inline QString falseAttributeValue() { return QStringLiteral("false"); } +static inline QString callOperator() { return QStringLiteral("operator()"); } + static QVector<CustomConversion *> customConversionsForReview; // Set a regular expression for rejection from text. By legacy, those are fixed @@ -437,12 +440,75 @@ static QString msgUnusedAttributes(const QStringRef &tag, const QXmlStreamAttrib return result; } +// QXmlStreamEntityResolver::resolveEntity(publicId, systemId) is not +// implemented; resolve via undeclared entities instead. +class TypeSystemEntityResolver : public QXmlStreamEntityResolver +{ +public: + explicit TypeSystemEntityResolver(const QString ¤tPath) : + m_currentPath(currentPath) {} + + QString resolveUndeclaredEntity(const QString &name) override; + +private: + QString readFile(const QString &entityName, QString *errorMessage) const; + + const QString m_currentPath; + QHash<QString, QString> m_cache; +}; + +QString TypeSystemEntityResolver::readFile(const QString &entityName, QString *errorMessage) const +{ + QString fileName = entityName; + if (!fileName.contains(QLatin1Char('.'))) + fileName += QLatin1String(".xml"); + QString path = TypeDatabase::instance()->modifiedTypesystemFilepath(fileName, m_currentPath); + if (!QFileInfo::exists(path)) // PySide2-specific hack + fileName.prepend(QLatin1String("typesystem_")); + path = TypeDatabase::instance()->modifiedTypesystemFilepath(fileName, m_currentPath); + if (!QFileInfo::exists(path)) { + *errorMessage = QLatin1String("Unable to resolve: ") + entityName; + return QString(); + } + QFile file(path); + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { + *errorMessage = msgCannotOpenForReading(file); + return QString(); + } + QString result = QString::fromUtf8(file.readAll()).trimmed(); + // Remove license header comments on which QXmlStreamReader chokes + if (result.startsWith(QLatin1String("<!--"))) { + const int commentEnd = result.indexOf(QLatin1String("-->")); + if (commentEnd != -1) { + result.remove(0, commentEnd + 3); + result = result.trimmed(); + } + } + return result; +} + +QString TypeSystemEntityResolver::resolveUndeclaredEntity(const QString &name) +{ + auto it = m_cache.find(name); + if (it == m_cache.end()) { + QString errorMessage; + it = m_cache.insert(name, readFile(name, &errorMessage)); + if (it.value().isEmpty()) { // The parser will fail and display the line number. + qCWarning(lcShiboken, "%s", + qPrintable(msgCannotResolveEntity(name, errorMessage))); + } + } + return it.value(); +} + Handler::Handler(TypeDatabase *database, bool generate) : m_database(database), m_generate(generate ? TypeEntry::GenerateAll : TypeEntry::GenerateForSubclass) { } +Handler::~Handler() = default; + static QString readerFileName(const QXmlStreamReader &reader) { const QFile *file = qobject_cast<const QFile *>(reader.device()); @@ -582,6 +648,8 @@ bool Handler::parse(QXmlStreamReader &reader) const QString fileName = readerFileName(reader); if (!fileName.isEmpty()) m_currentPath = QFileInfo(fileName).absolutePath(); + m_entityResolver.reset(new TypeSystemEntityResolver(m_currentPath)); + reader.setEntityResolver(m_entityResolver.data()); while (!reader.atEnd()) { switch (reader.readNext()) { @@ -674,6 +742,17 @@ bool Handler::endElement(const QStringRef &localName) } } break; + case StackElement::AddFunction: { + // Leaving add-function: Assign all modifications to the added function + StackElementContext *top = m_contextStack.top(); + const int modIndex = top->addedFunctionModificationIndex; + top->addedFunctionModificationIndex = -1; + Q_ASSERT(modIndex >= 0); + Q_ASSERT(!top->addedFunctions.isEmpty()); + while (modIndex < top->functionMods.size()) + top->addedFunctions.last()->modifications.append(top->functionMods.takeAt(modIndex)); + } + break; case StackElement::NativeToTarget: case StackElement::AddConversion: { CustomConversion* customConversion = static_cast<TypeEntry*>(m_current->entry)->customConversion(); @@ -2009,8 +2088,8 @@ bool Handler::parseAddFunction(const QXmlStreamReader &, return false; } - AddedFunction func(signature, returnType); - func.setStatic(staticFunction); + AddedFunctionPtr func(new AddedFunction(signature, returnType)); + func->setStatic(staticFunction); if (!signature.contains(QLatin1Char('('))) signature += QLatin1String("()"); m_currentSignature = signature; @@ -2021,10 +2100,12 @@ bool Handler::parseAddFunction(const QXmlStreamReader &, m_error = QString::fromLatin1("Bad access type '%1'").arg(access); return false; } - func.setAccess(a); + func->setAccess(a); } m_contextStack.top()->addedFunctions << func; + m_contextStack.top()->addedFunctionModificationIndex = + m_contextStack.top()->functionMods.size(); FunctionModification mod; if (!mod.setSignature(m_currentSignature, &m_error)) @@ -3231,7 +3312,10 @@ AddedFunction::AddedFunction(QString signature, const QString &returnType) : Q_ASSERT(!returnType.isEmpty()); m_returnType = parseType(returnType); signature = signature.trimmed(); - int endPos = signature.indexOf(QLatin1Char('(')); + // Skip past "operator()(...)" + const int parenStartPos = signature.startsWith(callOperator()) + ? callOperator().size() : 0; + int endPos = signature.indexOf(QLatin1Char('('), parenStartPos); if (endPos < 0) { m_isConst = false; m_name = signature; @@ -3413,7 +3497,6 @@ ComplexTypeEntry::ComplexTypeEntry(const QString &name, TypeEntry::Type t, const QVersionNumber &vr) : TypeEntry(name, t, vr), m_qualifiedCppName(name), - m_qobject(false), m_polymorphicBase(false), m_genericClass(false), m_deleteInMainThread(false) @@ -3483,6 +3566,20 @@ static const QSet<QString> &primitiveCppTypes() return result; } +void TypeEntry::setInclude(const Include &inc) +{ + // This is a workaround for preventing double inclusion of the QSharedPointer implementation + // header, which does not use header guards. In the previous parser this was not a problem + // because the Q_QDOC define was set, and the implementation header was never included. + if (inc.name().endsWith(QLatin1String("qsharedpointer_impl.h"))) { + QString path = inc.name(); + path.remove(QLatin1String("_impl")); + m_include = Include(inc.type(), path); + } else { + m_include = inc; + } +} + bool TypeEntry::isCppPrimitive() const { if (!isPrimitive()) diff --git a/sources/shiboken2/ApiExtractor/typesystem.h b/sources/shiboken2/ApiExtractor/typesystem.h index 96d0bb5fd..f089bb6e0 100644 --- a/sources/shiboken2/ApiExtractor/typesystem.h +++ b/sources/shiboken2/ApiExtractor/typesystem.h @@ -476,6 +476,8 @@ struct AddedFunction return m_isStatic; } + FunctionModificationList modifications; + private: QString m_name; QVector<TypeInfo> m_arguments; @@ -835,16 +837,7 @@ public: { return m_include; } - void setInclude(const Include &inc) - { - // This is a workaround for preventing double inclusion of the QSharedPointer implementation - // header, which does not use header guards. In the previous parser this was not a problem - // because the Q_QDOC define was set, and the implementation header was never included. - if (inc.name() == QLatin1String("qsharedpointer_impl.h")) - m_include = Include(inc.type(), QLatin1String("qsharedpointer.h")); - else - m_include = inc; - } + void setInclude(const Include &inc); // Replace conversionRule arg to CodeSnip in future version /// Set the type convertion rule @@ -1278,7 +1271,7 @@ public: { m_addedFunctions = addedFunctions; } - void addNewFunction(const AddedFunction &addedFunction) + void addNewFunction(const AddedFunctionPtr &addedFunction) { m_addedFunctions << addedFunction; } @@ -1293,15 +1286,6 @@ public: return m_fieldMods; } - bool isQObject() const - { - return m_qobject; - } - void setQObject(bool qobject) - { - m_qobject = qobject; - } - QString defaultSuperclass() const { return m_defaultSuperclass; @@ -1419,7 +1403,6 @@ private: QString m_qualifiedCppName; QString m_targetLangName; - uint m_qobject : 1; uint m_polymorphicBase : 1; uint m_genericClass : 1; uint m_deleteInMainThread : 1; diff --git a/sources/shiboken2/ApiExtractor/typesystem_p.h b/sources/shiboken2/ApiExtractor/typesystem_p.h index a119b2a97..f6b0717f4 100644 --- a/sources/shiboken2/ApiExtractor/typesystem_p.h +++ b/sources/shiboken2/ApiExtractor/typesystem_p.h @@ -29,11 +29,13 @@ #define TYPESYSTEM_P_H #include <QStack> +#include <QtCore/QScopedPointer> #include "typesystem.h" QT_FORWARD_DECLARE_CLASS(QXmlStreamAttributes) QT_FORWARD_DECLARE_CLASS(QXmlStreamReader) +class TypeSystemEntityResolver; class TypeDatabase; class StackElement { @@ -132,12 +134,16 @@ struct StackElementContext FunctionModificationList functionMods; FieldModificationList fieldMods; DocModificationList docModifications; + int addedFunctionModificationIndex = -1; }; class Handler { public: + Q_DISABLE_COPY(Handler) + Handler(TypeDatabase* database, bool generate); + ~Handler(); bool parse(QXmlStreamReader &reader); @@ -255,6 +261,7 @@ private: QString m_currentSignature; QString m_currentPath; + QScopedPointer<TypeSystemEntityResolver> m_entityResolver; }; #endif diff --git a/sources/shiboken2/ApiExtractor/typesystem_typedefs.h b/sources/shiboken2/ApiExtractor/typesystem_typedefs.h index dc6e5cbcc..5cea587ed 100644 --- a/sources/shiboken2/ApiExtractor/typesystem_typedefs.h +++ b/sources/shiboken2/ApiExtractor/typesystem_typedefs.h @@ -31,6 +31,7 @@ #include <QtCore/QHash> #include <QtCore/QList> +#include <QtCore/QSharedPointer> #include <QtCore/QVector> class CodeSnip; @@ -40,7 +41,8 @@ struct AddedFunction; struct FieldModification; struct FunctionModification; -typedef QVector<AddedFunction> AddedFunctionList; +using AddedFunctionPtr = QSharedPointer<AddedFunction>; +using AddedFunctionList = QVector<AddedFunctionPtr>; typedef QVector<CodeSnip> CodeSnipList; typedef QVector<DocModification> DocModificationList; typedef QVector<FieldModification> FieldModificationList; diff --git a/sources/shiboken2/CMakeLists.txt b/sources/shiboken2/CMakeLists.txt index 1e52c4297..12429c657 100644 --- a/sources/shiboken2/CMakeLists.txt +++ b/sources/shiboken2/CMakeLists.txt @@ -11,10 +11,24 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/data/") include(helpers) include(shiboken_helpers) -find_package(Qt5 5.12 REQUIRED COMPONENTS Core Xml XmlPatterns) - option(BUILD_TESTS "Build tests." TRUE) option(USE_PYTHON_VERSION "Use specific python version to build shiboken2." "") +option(DISABLE_DOCSTRINGS "Disable documentation extraction." FALSE) + +find_package(Qt5 5.12 REQUIRED COMPONENTS Core) +find_package(Qt5Xml 5.12) +find_package(Qt5XmlPatterns 5.12) +find_package(LibXml2 2.6.32) +find_package(LibXslt 1.1.19) +if(BUILD_TESTS) + find_package(Qt5Test 5.12 REQUIRED) +endif() + +if(NOT Qt5XmlPatterns_FOUND OR NOT Qt5Xml_FOUND) + set(DISABLE_DOCSTRINGS TRUE) + message(WARNING + "Documentation will not be built due to missing dependency (no Qt5XmlPatterns found).") +endif() # Don't display "up-to-date / install" messages when installing, to reduce visual clutter. if (QUIET_BUILD) diff --git a/sources/shiboken2/doc/typesystem_specifying_types.rst b/sources/shiboken2/doc/typesystem_specifying_types.rst index f4016bc2c..ac1121461 100644 --- a/sources/shiboken2/doc/typesystem_specifying_types.rst +++ b/sources/shiboken2/doc/typesystem_specifying_types.rst @@ -3,6 +3,30 @@ Specifying Types .. _typesystem: +Including Snippets +^^^^^^^^^^^^^^^^^^ + +There might be repetitive XML code, for example function modifications that +need to be done on classes that are not related by type inheritance. +It is possible to split out such snippets and include them via an entity reference. + +.. code-block:: xml + + <typesystem> + <object-type name="A"> + &common_function_modifications; + </object-type> + <object-type name="B"> + &common_function_modifications; + </object-type> + </typesystem> + +The entity name is interpreted as file name (with suffix **xml**) appended and resolved +in the type system paths passed as command line argument. + +Note that this is not a standard externally parsed entity due to the limitations +of the underlying parser. + typesystem ^^^^^^^^^^ diff --git a/sources/shiboken2/generator/CMakeLists.txt b/sources/shiboken2/generator/CMakeLists.txt index 943e8d19b..745c366f5 100644 --- a/sources/shiboken2/generator/CMakeLists.txt +++ b/sources/shiboken2/generator/CMakeLists.txt @@ -1,8 +1,5 @@ project(shibokengenerator) -find_package(Qt5Xml) -find_package(Qt5XmlPatterns) - set(shiboken2_SRC generator.cpp shiboken2/cppgenerator.cpp @@ -12,29 +9,23 @@ shiboken2/shibokengenerator.cpp main.cpp ) -if (NOT DISABLE_DOCSTRINGS) - set(shiboken2_SRC ${shiboken2_SRC} qtdoc/qtdocgenerator.cpp) - add_definitions(-DDOCSTRINGS_ENABLED) -endif() - -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/shiboken2 +add_executable(shiboken2 ${shiboken2_SRC}) +add_executable(Shiboken2::shiboken2 ALIAS shiboken2) +add_dependencies(shiboken2 apiextractor) +set_target_properties(shiboken2 PROPERTIES OUTPUT_NAME shiboken2${shiboken2_SUFFIX}) +target_include_directories(shiboken2 PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/shiboken2 ${CMAKE_CURRENT_SOURCE_DIR}/qtdoc ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ${apiextractor_SOURCE_DIR} - ${Qt5Core_INCLUDE_DIRS} - ${Qt5XmlPatterns_INCLUDE_DIRS} ) - -add_executable(shiboken2 ${shiboken2_SRC}) -add_executable(Shiboken2::shiboken2 ALIAS shiboken2) -add_dependencies(shiboken2 apiextractor) -set_target_properties(shiboken2 PROPERTIES OUTPUT_NAME shiboken2${shiboken2_SUFFIX}) -target_link_libraries(shiboken2 - apiextractor - ${Qt5Core_LIBRARIES} - ${Qt5XmlPatterns_LIBRARIES} - ) +target_link_libraries(shiboken2 apiextractor Qt5::Core) +if (NOT DISABLE_DOCSTRINGS) + target_sources(shiboken2 PRIVATE qtdoc/qtdocgenerator.cpp) + target_compile_definitions(shiboken2 PUBLIC DOCSTRINGS_ENABLED) + target_link_libraries(shiboken2 Qt5::XmlPatterns) +endif() configure_file(shibokenconfig.h.in "${CMAKE_CURRENT_BINARY_DIR}/shibokenconfig.h" @ONLY) diff --git a/sources/shiboken2/generator/generator.cpp b/sources/shiboken2/generator/generator.cpp index 91e940f51..87758e533 100644 --- a/sources/shiboken2/generator/generator.cpp +++ b/sources/shiboken2/generator/generator.cpp @@ -421,7 +421,7 @@ bool Generator::generate() for (const AbstractMetaType *type : qAsConst(m_d->instantiatedSmartPointers)) { AbstractMetaClass *smartPointerClass = - AbstractMetaClass::findClass(m_d->apiextractor->smartPointers(), type->name()); + AbstractMetaClass::findClass(m_d->apiextractor->smartPointers(), type->typeEntry()); GeneratorContext context(smartPointerClass, type, true); if (!generateFileForContext(context)) return false; @@ -538,7 +538,7 @@ bool Generator::isObjectType(const TypeEntry* type) } bool Generator::isObjectType(const ComplexTypeEntry* type) { - return type->isObject() || type->isQObject(); + return type->isObject(); } bool Generator::isObjectType(const AbstractMetaClass* metaClass) { diff --git a/sources/shiboken2/generator/main.cpp b/sources/shiboken2/generator/main.cpp index 094990b64..1817f6b03 100644 --- a/sources/shiboken2/generator/main.cpp +++ b/sources/shiboken2/generator/main.cpp @@ -373,8 +373,10 @@ static void parseIncludePathOption(const QString &option, HeaderType headerType, const QStringList includePathListList = it.value().split(pathSplitter, QString::SkipEmptyParts); args.erase(it); - for (const QString &s : includePathListList) - extractor.addIncludePath(HeaderPath{QFile::encodeName(s), headerType}); + for (const QString &s : includePathListList) { + auto path = QFile::encodeName(QDir::cleanPath(s)); + extractor.addIncludePath(HeaderPath{path, headerType}); + } } } diff --git a/sources/shiboken2/generator/qtdoc/CMakeLists.txt b/sources/shiboken2/generator/qtdoc/CMakeLists.txt deleted file mode 100644 index 1361ba8f1..000000000 --- a/sources/shiboken2/generator/qtdoc/CMakeLists.txt +++ /dev/null @@ -1,21 +0,0 @@ -project(qtdoc_generator) - -set(qtdoc_generator_SRC -qtdocgenerator.cpp -) - -include_directories(${generators_SOURCE_DIR} - ${Qt5Core_INCLUDE_DIRS} - ${APIEXTRACTOR_INCLUDE_DIR}) -add_executable(docgenerator main.cpp) -set_target_properties(docgenerator PROPERTIES OUTPUT_NAME docgenerator${generator_SUFFIX}) - -target_link_libraries(docgenerator ${Qt5Core_LIBRARES}) - -add_library(qtdoc_generator SHARED ${qtdoc_generator_SRC}) -target_link_libraries(qtdoc_generator ${APIEXTRACTOR_LIBRARY} ${Qt5Core_LIBRARES} genrunner) -set_property(TARGET qtdoc_generator PROPERTY PREFIX "") - -install(TARGETS qtdoc_generator DESTINATION ${generator_plugin_DIR}) -install(TARGETS docgenerator DESTINATION bin) - diff --git a/sources/shiboken2/generator/qtdoc/qtdocgenerator.cpp b/sources/shiboken2/generator/qtdoc/qtdocgenerator.cpp index 05729f4b5..6abfde7c9 100644 --- a/sources/shiboken2/generator/qtdoc/qtdocgenerator.cpp +++ b/sources/shiboken2/generator/qtdoc/qtdocgenerator.cpp @@ -1872,7 +1872,7 @@ QString QtDocGenerator::parseArgDocStyle(const AbstractMetaClass* /* cppClass */ defValue.replace(QLatin1String("::"), QLatin1String(".")); if (defValue == QLatin1String("nullptr")) defValue = none(); - else if (defValue == QLatin1String("0") && (arg->type()->isQObject() || arg->type()->isObject())) + else if (defValue == QLatin1String("0") && arg->type()->isObject()) defValue = none(); } ret += QLatin1Char('=') + defValue; diff --git a/sources/shiboken2/generator/shiboken2/CMakeLists.txt b/sources/shiboken2/generator/shiboken2/CMakeLists.txt deleted file mode 100644 index 5c1b612dd..000000000 --- a/sources/shiboken2/generator/shiboken2/CMakeLists.txt +++ /dev/null @@ -1,28 +0,0 @@ -project(shibokengenerator) - -set(shiboken_SRC -../generator.cpp -cppgenerator.cpp -headergenerator.cpp -overloaddata.cpp -shibokengenerator.cpp -main.cpp -) - -include_directories(${generators_SOURCE_DIR} - ${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_CURRENT_BINARY_DIR} - ${APIEXTRACTOR_INCLUDE_DIR} - ${Qt5Core_INCLUDE_DIRS} - ) - -add_executable(shiboken2 ${shiboken_SRC}) -set_target_properties(shiboken2 PROPERTIES OUTPUT_NAME shiboken2${shiboken_SUFFIX}) -target_link_libraries(shiboken2 - ${APIEXTRACTOR_LIBRARY} - ${Qt5Core_LIBRARIES} - ) - -configure_file(shibokenconfig.h.in "${CMAKE_CURRENT_BINARY_DIR}/shibokenconfig.h" @ONLY) - -install(TARGETS shiboken2 DESTINATION bin) diff --git a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp index 2fedf9ae1..29220c739 100644 --- a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp +++ b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp @@ -664,7 +664,7 @@ void CppGenerator::generateClass(QTextStream &s, GeneratorContext &classContext) s << NULL_PTR; s << "}," << endl; } - s << INDENT << '{' << NULL_PTR << "} // Sentinel" << endl; + s << INDENT << '{' << NULL_PTR << "} // Sentinel" << endl; s << "};" << endl << endl; } @@ -907,7 +907,6 @@ void CppGenerator::writeVirtualMethodNative(QTextStream&s, const AbstractMetaFun QTextStream ac(&argConv); const PrimitiveTypeEntry* argType = (const PrimitiveTypeEntry*) arg->type()->typeEntry(); bool convert = argType->isObject() - || arg->type()->isQObject() || argType->isValue() || arg->type()->isValuePointer() || arg->type()->isNativePointer() @@ -3076,7 +3075,7 @@ QString CppGenerator::argumentNameFromIndex(const AbstractMetaFunction* func, in AbstractMetaType *returnType = getTypeWithoutContainer(funcType); if (returnType) { pyArgName = QLatin1String(PYTHON_RETURN_VAR); - *wrappedClass = AbstractMetaClass::findClass(classes(), returnType->typeEntry()->name()); + *wrappedClass = AbstractMetaClass::findClass(classes(), returnType->typeEntry()); } else { QString message = QLatin1String("Invalid Argument index (0, return value) on function modification: ") + (funcType ? funcType->name() : QLatin1String("void")) + QLatin1Char(' '); @@ -3090,7 +3089,7 @@ QString CppGenerator::argumentNameFromIndex(const AbstractMetaFunction* func, in AbstractMetaType* argType = getTypeWithoutContainer(func->arguments().at(realIndex)->type()); if (argType) { - *wrappedClass = AbstractMetaClass::findClass(classes(), argType->typeEntry()->name()); + *wrappedClass = AbstractMetaClass::findClass(classes(), argType->typeEntry()); if (argIndex == 1 && !func->isConstructor() && OverloadData::isSingleArgument(getFunctionGroups(func->implementingClass())[func->name()])) @@ -4925,11 +4924,11 @@ void CppGenerator::writeClassRegister(QTextStream &s, // PYSIDE-510: Create a signatures string for the introspection feature. s << "// The signatures string for the functions." << endl; s << "// Multiple signatures have their index \"n:\" in front." << endl; - s << "const char " << initFunctionName << "_SignaturesString[] = \"\"" << endl; + s << "static const char *" << initFunctionName << "_SignatureStrings[] = {" << endl; QString line; while (signatureStream.readLineInto(&line)) - s << INDENT << '"' << line << "\\n\"" << endl; - s << ';' << endl << endl; + s << INDENT << '"' << line << "\"," << endl; + s << INDENT << NULL_PTR << "}; // Sentinel" << endl << endl; s << "void init_" << initFunctionName; s << "(PyObject* " << enclosingObjectVariable << ")" << endl; s << '{' << endl; @@ -4982,8 +4981,8 @@ void CppGenerator::writeClassRegister(QTextStream &s, // 4:typeSpec s << INDENT << '&' << chopType(pyTypeName) << "_spec," << endl; - // 5:signaturesString - s << INDENT << initFunctionName << "_SignaturesString," << endl; + // 5:signatureStrings + s << INDENT << initFunctionName << "_SignatureStrings," << endl; // 6:cppObjDtor s << INDENT; @@ -5657,7 +5656,17 @@ bool CppGenerator::finishGeneration() s << " /* m_clear */ nullptr," << endl; s << " /* m_free */ nullptr" << endl; s << "};" << endl << endl; - s << "#endif" << endl; + s << "#endif" << endl << endl; + + // PYSIDE-510: Create a signatures string for the introspection feature. + s << "// The signatures string for the global functions." << endl; + s << "// Multiple signatures have their index \"n:\" in front." << endl; + s << "static const char *" << moduleName() << "_SignatureStrings[] = {" << endl; + QString line; + while (signatureStream.readLineInto(&line)) + s << INDENT << '"' << line << "\"," << endl; + s << INDENT << NULL_PTR << "}; // Sentinel" << endl << endl; + s << "SBK_MODULE_INIT_FUNCTION_BEGIN(" << moduleName() << ")" << endl; ErrorCode errorCode(QLatin1String("SBK_MODULE_INIT_ERROR")); @@ -5788,17 +5797,9 @@ bool CppGenerator::finishGeneration() s << INDENT << "PySide::registerCleanupFunction(cleanTypesAttributes);" << endl << endl; } - // PYSIDE-510: Create a signatures string for the introspection feature. - s << "// The signatures string for the global functions." << endl; - s << "// Multiple signatures have their index \"n:\" in front." << endl; - s << "const char " << moduleName() << "_SignaturesString[] = \"\"" << endl; - QString line; - while (signatureStream.readLineInto(&line)) - s << INDENT << '"' << line << "\\n\"" << endl; - s << ';' << endl; // finish the rest of __signature__ initialization. s << INDENT << "FinishSignatureInitialization(module, " << moduleName() - << "_SignaturesString);" << endl; + << "_SignatureStrings);" << endl; if (usePySideExtensions()) { // initialize the qApp module. diff --git a/sources/shiboken2/generator/shiboken2/overloaddata.cpp b/sources/shiboken2/generator/shiboken2/overloaddata.cpp index 9f0ac51e5..becd66879 100644 --- a/sources/shiboken2/generator/shiboken2/overloaddata.cpp +++ b/sources/shiboken2/generator/shiboken2/overloaddata.cpp @@ -322,7 +322,7 @@ void OverloadData::sortNextOverloads() } // Process inheritance relationships - if (targetType->isValue() || targetType->isObject() || targetType->isQObject()) { + if (targetType->isValue() || targetType->isObject()) { const AbstractMetaClass *metaClass = AbstractMetaClass::findClass(m_generator->classes(), targetType->typeEntry()); const AbstractMetaClassList &ancestors = m_generator->getAllAncestors(metaClass); for (const AbstractMetaClass *ancestor : ancestors) { diff --git a/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp b/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp index b5069db14..002ab8cfb 100644 --- a/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp +++ b/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp @@ -373,7 +373,7 @@ QString ShibokenGenerator::fullPythonClassName(const AbstractMetaClass *metaClas return fullClassName; } -QString ShibokenGenerator::fullPythonFunctionName(const AbstractMetaFunction *func) //WS +QString ShibokenGenerator::fullPythonFunctionName(const AbstractMetaFunction *func) { QString funcName; if (func->isOperatorOverload()) @@ -729,8 +729,7 @@ QString ShibokenGenerator::getFormatUnitString(const AbstractMetaFunction* func, if (!func->typeReplaced(arg->argumentIndex() + 1).isEmpty()) { result += QLatin1Char(objType); - } else if (arg->type()->isQObject() - || arg->type()->isObject() + } else if (arg->type()->isObject() || arg->type()->isValue() || arg->type()->isValuePointer() || arg->type()->isNativePointer() diff --git a/sources/shiboken2/generator/shiboken2/shibokengenerator.h b/sources/shiboken2/generator/shiboken2/shibokengenerator.h index d2c4b3292..80b172778 100644 --- a/sources/shiboken2/generator/shiboken2/shibokengenerator.h +++ b/sources/shiboken2/generator/shiboken2/shibokengenerator.h @@ -216,7 +216,7 @@ protected: QString wrapperName(const AbstractMetaType *metaType) const; QString fullPythonClassName(const AbstractMetaClass *metaClass); - QString fullPythonFunctionName(const AbstractMetaFunction *func); //WS + QString fullPythonFunctionName(const AbstractMetaFunction *func); static QString protectedEnumSurrogateName(const AbstractMetaEnum* metaEnum); static QString protectedFieldGetterName(const AbstractMetaField* field); diff --git a/sources/shiboken2/libshiboken/basewrapper.cpp b/sources/shiboken2/libshiboken/basewrapper.cpp index a008fece8..3a043d849 100644 --- a/sources/shiboken2/libshiboken/basewrapper.cpp +++ b/sources/shiboken2/libshiboken/basewrapper.cpp @@ -744,18 +744,14 @@ introduceWrapperType(PyObject *enclosingObject, const char *typeName, const char *originalName, PyType_Spec *typeSpec, - const char *signaturesString, + const char *signatureStrings[], ObjectDestructor cppObjDtor, SbkObjectType *baseType, PyObject *baseTypes, unsigned wrapperFlags) { - if (baseType) { - typeSpec->slots[0].pfunc = reinterpret_cast<void *>(baseType); - } - else { - typeSpec->slots[0].pfunc = reinterpret_cast<void *>(SbkObject_TypeF()); - } + typeSpec->slots[0].pfunc = reinterpret_cast<void *>(baseType ? baseType : SbkObject_TypeF()); + PyObject *heaptype = PyType_FromSpecWithBases(typeSpec, baseTypes); Py_TYPE(heaptype) = SbkObjectType_TypeF(); Py_INCREF(Py_TYPE(heaptype)); @@ -769,7 +765,7 @@ introduceWrapperType(PyObject *enclosingObject, } } // PYSIDE-510: Here is the single change to support signatures. - if (SbkSpecial_Type_Ready(enclosingObject, reinterpret_cast<PyTypeObject *>(type), signaturesString) < 0) + if (SbkSpecial_Type_Ready(enclosingObject, reinterpret_cast<PyTypeObject *>(type), signatureStrings) < 0) return nullptr; initPrivateData(type); @@ -779,20 +775,14 @@ introduceWrapperType(PyObject *enclosingObject, setOriginalName(type, originalName); setDestructorFunction(type, cppObjDtor); + PyObject *ob_type = reinterpret_cast<PyObject *>(type); - if (wrapperFlags & InnerClass) { - if (PyDict_SetItemString(enclosingObject, typeName, reinterpret_cast<PyObject *>(type)) == 0) - return type; - else - return nullptr; - } + if (wrapperFlags & InnerClass) + return PyDict_SetItemString(enclosingObject, typeName, ob_type) == 0 ? type : nullptr; - //PyModule_AddObject steals type's reference. - Py_INCREF(reinterpret_cast<PyObject *>(type)); - if (PyModule_AddObject(enclosingObject, typeName, reinterpret_cast<PyObject *>(type)) == 0) { - return type; - } - return nullptr; + // PyModule_AddObject steals type's reference. + Py_INCREF(ob_type); + return PyModule_AddObject(enclosingObject, typeName, ob_type) == 0 ? type : nullptr; } void setSubTypeInitHook(SbkObjectType* type, SubTypeInitHook func) diff --git a/sources/shiboken2/libshiboken/basewrapper.h b/sources/shiboken2/libshiboken/basewrapper.h index e1cc64ba9..d12b7222b 100644 --- a/sources/shiboken2/libshiboken/basewrapper.h +++ b/sources/shiboken2/libshiboken/basewrapper.h @@ -219,7 +219,7 @@ LIBSHIBOKEN_API SbkObjectType *introduceWrapperType(PyObject *enclosingObject, const char *typeName, const char *originalName, PyType_Spec *typeSpec, - const char *signaturesString, + const char *signatureStrings[], ObjectDestructor cppObjDtor, SbkObjectType *baseType, PyObject *baseTypes, diff --git a/sources/shiboken2/libshiboken/pep384impl.h b/sources/shiboken2/libshiboken/pep384impl.h index d883677ce..ffbc570a8 100644 --- a/sources/shiboken2/libshiboken/pep384impl.h +++ b/sources/shiboken2/libshiboken/pep384impl.h @@ -316,6 +316,7 @@ LIBSHIBOKEN_API void PyBuffer_Release(Pep_buffer *view); #else #define Pep_buffer Py_buffer +#define PepType_AS_BUFFER(type) ((type)->tp_as_buffer) #endif /* Py_LIMITED_API */ diff --git a/sources/shiboken2/libshiboken/signature.cpp b/sources/shiboken2/libshiboken/signature.cpp index dea4c9b09..3defca7d2 100644 --- a/sources/shiboken2/libshiboken/signature.cpp +++ b/sources/shiboken2/libshiboken/signature.cpp @@ -46,7 +46,6 @@ extern "C" /* * The documentation is located in file signature_doc.rst */ - #include "signature.h" #include <structmember.h> @@ -62,6 +61,7 @@ extern "C" #define PYTHON_NEEDS_ITERATOR_FLAG (!PYTHON_IS_PYTHON3) #define PYTHON_EXPOSES_METHODDESCR (PYTHON_IS_PYTHON3) #define PYTHON_NO_TYPE_IN_FUNCTIONS (!PYTHON_IS_PYTHON3 || Py_LIMITED_API) +#define PYTHON_HAS_INT_AND_LONG (!PYTHON_IS_PYTHON3) // These constants are still in use: #define PYTHON_USES_D_COMMON (PY_VERSION_HEX >= 0x03020000) @@ -72,15 +72,15 @@ typedef struct safe_globals_struc { PyObject *arg_dict; PyObject *map_dict; // init part 2: run module - PyObject *sigparse_func; - PyObject *createsig_func; + PyObject *pyside_type_init_func; + PyObject *create_signature_func; PyObject *seterror_argument_func; PyObject *make_helptext_func; } safe_globals_struc, *safe_globals; static safe_globals pyside_globals = 0; -static PyObject *GetClassKey(PyObject *ob); +static PyObject *GetTypeKey(PyObject *ob); static PyObject *GetSignature_Function(PyObject *, const char *); static PyObject *GetSignature_TypeMod(PyObject *, const char *); @@ -101,8 +101,8 @@ CreateSignature(PyObject *props, PyObject *key) * This is so much simpler than using all the attributes explicitly * to support '_signature_is_functionlike()'. */ - return PyObject_CallFunction(pyside_globals->createsig_func, - (char *)"(OO)", props, key); + return PyObject_CallFunction(pyside_globals->create_signature_func, + const_cast<char *>("(OO)"), props, key); } static PyObject * @@ -139,10 +139,10 @@ _get_class_of_cf(PyObject *ob_cf) } } - PyObject *typemod = (PyType_Check(selftype) || PyModule_Check(selftype)) - ? selftype : (PyObject *)Py_TYPE(selftype); - Py_INCREF(typemod); - return typemod; + PyObject *obtype_mod = (PyType_Check(selftype) || PyModule_Check(selftype)) + ? selftype : reinterpret_cast<PyObject *>(Py_TYPE(selftype)); + Py_INCREF(obtype_mod); + return obtype_mod; } static PyObject * @@ -198,24 +198,24 @@ static PyObject * compute_name_key(PyObject *ob) { if (PyType_Check(ob)) - return GetClassKey(ob); + return GetTypeKey(ob); Shiboken::AutoDecRef func_name(get_funcname(ob)); - Shiboken::AutoDecRef type_key(GetClassKey(GetClassOfFunc(ob))); + Shiboken::AutoDecRef type_key(GetTypeKey(GetClassOfFunc(ob))); return Py_BuildValue("(OO)", type_key.object(), func_name.object()); } static int build_name_key_to_func(PyObject *obtype) { - PyTypeObject *type = (PyTypeObject *)obtype; + PyTypeObject *type = reinterpret_cast<PyTypeObject *>(obtype); PyMethodDef *meth = type->tp_methods; if (meth == 0) return 0; - Shiboken::AutoDecRef type_key(GetClassKey(obtype)); - for (; meth->ml_name != NULL; meth++) { - Shiboken::AutoDecRef func(PyCFunction_NewEx(meth, obtype, NULL)); + Shiboken::AutoDecRef type_key(GetTypeKey(obtype)); + for (; meth->ml_name != nullptr; meth++) { + Shiboken::AutoDecRef func(PyCFunction_NewEx(meth, obtype, nullptr)); Shiboken::AutoDecRef func_name(get_funcname(func)); Shiboken::AutoDecRef name_key(Py_BuildValue("(OO)", type_key.object(), func_name.object())); if (func.isNull() || name_key.isNull() @@ -240,7 +240,7 @@ name_key_to_func(PyObject *ob) PyObject *ret = PyDict_GetItem(pyside_globals->map_dict, name_key); if (ret == nullptr) { // do a lazy initialization - Shiboken::AutoDecRef type_key(GetClassKey(GetClassOfFunc(ob))); + Shiboken::AutoDecRef type_key(GetTypeKey(GetClassOfFunc(ob))); PyObject *type = PyDict_GetItem(pyside_globals->map_dict, type_key); if (type == nullptr) @@ -274,10 +274,10 @@ pyside_wd_get___signature__(PyObject *ob, const char *modifier) } static PyObject * -pyside_tp_get___signature__(PyObject *typemod, const char *modifier) +pyside_tp_get___signature__(PyObject *obtype_mod, const char *modifier) { init_module_2(); - return GetSignature_TypeMod(typemod, modifier); + return GetSignature_TypeMod(obtype_mod, modifier); } // forward @@ -285,13 +285,13 @@ static PyObject * GetSignature_Cached(PyObject *props, const char *sig_kind, const char *modifier); static PyObject * -GetClassKey(PyObject *ob) +GetTypeKey(PyObject *ob) { assert(PyType_Check(ob) || PyModule_Check(ob)); /* - * We obtain a unique key using the module name and the class name. + * We obtain a unique key using the module name and the type name. * - * The class name is a bit funny when modules are nested. + * The type name is a bit funny when modules are nested. * Example: * * "sample.Photon.ValueIdentity" is a class. @@ -326,32 +326,32 @@ TypeKey_to_PropsDict(PyObject *type_key, PyObject *obtype) empty_dict = PyDict_New(); dict = empty_dict; } - if (PyTuple_Check(dict)) - dict = PySide_BuildSignatureProps(obtype); + if (!PyDict_Check(dict)) + dict = PySide_BuildSignatureProps(type_key); return dict; } static PyObject * -GetSignature_Function(PyObject *ob_func, const char *modifier) +GetSignature_Function(PyObject *obfunc, const char *modifier) { // make sure that we look into PyCFunction, only... - if (Py_TYPE(ob_func) == PepFunction_TypePtr) + if (Py_TYPE(obfunc) == PepFunction_TypePtr) Py_RETURN_NONE; - Shiboken::AutoDecRef typemod(GetClassOfFunc(ob_func)); - Shiboken::AutoDecRef type_key(GetClassKey(typemod)); + Shiboken::AutoDecRef obtype_mod(GetClassOfFunc(obfunc)); + Shiboken::AutoDecRef type_key(GetTypeKey(obtype_mod)); if (type_key.isNull()) Py_RETURN_NONE; - PyObject *dict = TypeKey_to_PropsDict(type_key, typemod); + PyObject *dict = TypeKey_to_PropsDict(type_key, obtype_mod); if (dict == nullptr) return nullptr; - Shiboken::AutoDecRef func_name(PyObject_GetAttrString(ob_func, "__name__")); + Shiboken::AutoDecRef func_name(PyObject_GetAttrString(obfunc, "__name__")); PyObject *props = !func_name.isNull() ? PyDict_GetItem(dict, func_name) : nullptr; if (props == nullptr) Py_RETURN_NONE; - int flags = PyCFunction_GET_FLAGS(ob_func); + int flags = PyCFunction_GET_FLAGS(obfunc); const char *sig_kind; - if (PyModule_Check(typemod)) + if (PyModule_Check(obtype_mod)) sig_kind = "function"; else if (flags & METH_CLASS) sig_kind = "classmethod"; @@ -367,7 +367,7 @@ GetSignature_Wrapper(PyObject *ob, const char *modifier) { Shiboken::AutoDecRef func_name(PyObject_GetAttrString(ob, "__name__")); Shiboken::AutoDecRef objclass(PyObject_GetAttrString(ob, "__objclass__")); - Shiboken::AutoDecRef class_key(GetClassKey(objclass)); + Shiboken::AutoDecRef class_key(GetTypeKey(objclass)); if (func_name.isNull() || objclass.isNull() || class_key.isNull()) return nullptr; @@ -384,7 +384,7 @@ static PyObject * GetSignature_TypeMod(PyObject *ob, const char *modifier) { Shiboken::AutoDecRef ob_name(PyObject_GetAttrString(ob, "__name__")); - Shiboken::AutoDecRef ob_key(GetClassKey(ob)); + Shiboken::AutoDecRef ob_key(GetTypeKey(ob)); PyObject *dict = TypeKey_to_PropsDict(ob_key, ob); if (dict == nullptr) @@ -430,9 +430,9 @@ static safe_globals_struc * init_phase_1(void) { { - safe_globals_struc *p = (safe_globals_struc *) - malloc(sizeof(safe_globals_struc)); - if (p == NULL) + safe_globals_struc *p = reinterpret_cast<safe_globals_struc *> + (malloc(sizeof(safe_globals_struc))); + if (p == nullptr) goto error; /* * Initializing module signature_bootstrap. @@ -479,7 +479,6 @@ init_phase_1(void) PyObject *mdict = PyModule_GetDict(p->helper_module); if (PyDict_SetItemString(mdict, "__builtins__", PyEval_GetBuiltins()) < 0) goto error; - /* * Unpack an embedded ZIP file with more signature modules. * They will be loaded later with the zipimporter. @@ -488,11 +487,13 @@ init_phase_1(void) const char **block_ptr = (const char **)PySide_CompressedSignaturePackage; int npieces = 0; PyObject *piece, *zipped_string_sequence = PyList_New(0); + if (zipped_string_sequence == nullptr) + return nullptr; for (; **block_ptr != 0; ++block_ptr) { npieces++; // we avoid the string/unicode dilemma by not using PyString_XXX: piece = Py_BuildValue("s", *block_ptr); - if (piece == NULL || PyList_Append(zipped_string_sequence, piece) < 0) + if (piece == nullptr || PyList_Append(zipped_string_sequence, piece) < 0) goto error; } if (PyDict_SetItemString(mdict, "zipstring_sequence", zipped_string_sequence) < 0) @@ -501,12 +502,12 @@ init_phase_1(void) // build a dict for diverse mappings p->map_dict = PyDict_New(); - if (p->map_dict == NULL) + if (p->map_dict == nullptr) goto error; // build a dict for the prepared arguments p->arg_dict = PyDict_New(); - if (p->arg_dict == NULL + if (p->arg_dict == nullptr || PyObject_SetAttrString(p->helper_module, "pyside_arg_dict", p->arg_dict) < 0) goto error; return p; @@ -514,7 +515,7 @@ init_phase_1(void) error: PyErr_Print(); PyErr_SetString(PyExc_SystemError, "could not initialize part 1"); - return NULL; + return nullptr; } static int @@ -524,7 +525,7 @@ init_phase_2(safe_globals_struc *p, PyMethodDef *methods) PyMethodDef *ml; // The single function to be called, but maybe more to come. - for (ml = methods; ml->ml_name != NULL; ml++) { + for (ml = methods; ml->ml_name != nullptr; ml++) { PyObject *v = PyCFunction_NewEx(ml, nullptr, nullptr); if (v == nullptr || PyObject_SetAttrString(p->helper_module, ml->ml_name, v) != 0) @@ -532,24 +533,24 @@ init_phase_2(safe_globals_struc *p, PyMethodDef *methods) Py_DECREF(v); } PyObject *bootstrap_func = PyObject_GetAttrString(p->helper_module, "bootstrap"); - if (bootstrap_func == NULL) + if (bootstrap_func == nullptr) goto error; // The return value of the bootstrap function is the loader module. - PyObject *loader = PyObject_CallFunction(bootstrap_func, (char *)"()"); + PyObject *loader = PyObject_CallFunction(bootstrap_func, const_cast<char *>("()")); if (loader == nullptr) goto error; // now the loader should be initialized - p->sigparse_func = PyObject_GetAttrString(loader, "pyside_type_init"); - if (p->sigparse_func == NULL) + p->pyside_type_init_func = PyObject_GetAttrString(loader, "pyside_type_init"); + if (p->pyside_type_init_func == nullptr) goto error; - p->createsig_func = PyObject_GetAttrString(loader, "create_signature"); - if (p->createsig_func == NULL) + p->create_signature_func = PyObject_GetAttrString(loader, "create_signature"); + if (p->create_signature_func == nullptr) goto error; p->seterror_argument_func = PyObject_GetAttrString(loader, "seterror_argument"); - if (p->seterror_argument_func == NULL) + if (p->seterror_argument_func == nullptr) goto error; p->make_helptext_func = PyObject_GetAttrString(loader, "make_helptext"); - if (p->make_helptext_func == NULL) + if (p->make_helptext_func == nullptr) goto error; return 0; } @@ -568,7 +569,7 @@ _fixup_getset(PyTypeObject *type, const char *name, PyGetSetDef *new_gsp) */ PyGetSetDef *gsp = type->tp_getset; if (gsp != nullptr) { - for (; gsp->name != NULL; gsp++) { + for (; gsp->name != nullptr; gsp++) { if (strcmp(gsp->name, name) == 0) { new_gsp->set = gsp->set; new_gsp->doc = gsp->doc; @@ -592,7 +593,7 @@ add_more_getsets(PyTypeObject *type, PyGetSetDef *gsp, PyObject **old_descr) assert(PyType_Check(type)); PyType_Ready(type); PyObject *dict = type->tp_dict; - for (; gsp->name != NULL; gsp++) { + for (; gsp->name != nullptr; gsp++) { PyObject *have_descr = PyDict_GetItemString(dict, gsp->name); if (have_descr != nullptr) { assert(strcmp(gsp->name, "__doc__") == 0); @@ -730,7 +731,7 @@ get_signature(PyObject *self, PyObject *args) init_module_1(); if (!PyArg_ParseTuple(args, "O|s", &ob, &modifier)) - return NULL; + return nullptr; if (Py_TYPE(ob) == PepFunction_TypePtr) Py_RETURN_NONE; @@ -784,15 +785,17 @@ PySide_PatchTypes(void) static int init_done = 0; if (!init_done) { - Shiboken::AutoDecRef md(PyObject_GetAttrString((PyObject *)&PyString_Type, "split")); // method-descriptor - Shiboken::AutoDecRef wd(PyObject_GetAttrString((PyObject *)Py_TYPE(Py_True), "__add__")); // wrapper-descriptor - if (md.isNull() || wd.isNull() - || PyType_Ready(Py_TYPE(md)) < 0 + Shiboken::AutoDecRef meth_descr(PyObject_GetAttrString( + reinterpret_cast<PyObject *>(&PyString_Type), "split")); + Shiboken::AutoDecRef wrap_descr(PyObject_GetAttrString( + reinterpret_cast<PyObject *>(Py_TYPE(Py_True)), "__add__")); + if (meth_descr.isNull() || wrap_descr.isNull() + || PyType_Ready(Py_TYPE(meth_descr)) < 0 || add_more_getsets(PepMethodDescr_TypePtr, new_PyMethodDescr_getsets, &old_md_doc_descr) < 0 || add_more_getsets(&PyCFunction_Type, new_PyCFunction_getsets, &old_cf_doc_descr) < 0 || add_more_getsets(PepStaticMethod_TypePtr, new_PyStaticMethod_getsets, &old_sm_doc_descr) < 0 || add_more_getsets(&PyType_Type, new_PyType_getsets, &old_tp_doc_descr) < 0 - || add_more_getsets(Py_TYPE(wd), new_PyWrapperDescr_getsets, &old_wd_doc_descr) < 0 + || add_more_getsets(Py_TYPE(wrap_descr), new_PyWrapperDescr_getsets, &old_wd_doc_descr) < 0 ) return -1; #ifndef _WIN32 @@ -819,52 +822,32 @@ init_module_1(void) } static int -PySide_BuildSignatureArgs(PyObject *module, PyObject *type, - const char *signatures) +PySide_BuildSignatureArgs(PyObject *obtype_mod, const char *signatures[]) { - PyObject *type_key, *arg_tup; - init_module_1(); - arg_tup = Py_BuildValue("(Os)", type, signatures); - if (arg_tup == NULL) - return -1; - /* - * We either get a module name or the dict of an EnclosingObject. - * We can ignore the EnclosingObject since we get full name info - * from the type. - */ - if (!PyModule_Check(module)) - assert(PyDict_Check(module)); + Shiboken::AutoDecRef type_key(GetTypeKey(obtype_mod)); /* - * Normally, we would now just call the Python function with the - * arguments and then continue processing. - * But it is much better to delay the second part until it is - * really needed. Why? - * - * - by doing it late, we save initialization time when no signatures - * are requested, - * - by calling the python function late, we can freely import PySide - * without recursion problems. + * PYSIDE-996: Avoid string overflow in MSVC, which has a limit of + * 2**15 unicode characters (64 K memory). + * Instead of one huge string, we take a ssize_t that is the + * address of a string array. It will not be turned into a real + * string list until really used by Python. This is quite optimal. */ - type_key = GetClassKey(type); - if (type_key == nullptr) - return -1; - if (PyDict_SetItem(pyside_globals->arg_dict, type_key, arg_tup) < 0) + Shiboken::AutoDecRef numkey(Py_BuildValue("n", signatures)); + if (type_key.isNull() || numkey.isNull() + || PyDict_SetItem(pyside_globals->arg_dict, type_key, numkey) < 0) return -1; /* - * We record also a mapping from type key to type. This helps to lazily - * initialize the Py_LIMITED_API in name_key_to_func(). + * We record also a mapping from type key to type/module. This helps to + * lazily initialize the Py_LIMITED_API in name_key_to_func(). */ - - if (PyDict_SetItem(pyside_globals->map_dict, type_key, type) < 0) - return -1; - return 0; + return PyDict_SetItem(pyside_globals->map_dict, type_key, obtype_mod) == 0 ? 0 : -1; } static PyMethodDef signature_methods[] = { {"get_signature", (PyCFunction)get_signature, METH_VARARGS, "get the __signature__, but pass an optional string parameter"}, - {NULL, NULL} + {nullptr, nullptr} }; static void @@ -881,7 +864,26 @@ init_module_2(void) } static PyObject * -PySide_BuildSignatureProps(PyObject *classmod) +_address_to_stringlist(PyObject *numkey) +{ + ssize_t address = PyNumber_AsSsize_t(numkey, PyExc_ValueError); + if (address == -1 && PyErr_Occurred()) + return nullptr; + char **sig_strings = reinterpret_cast<char **>(address); + PyObject *res_list = PyList_New(0); + if (res_list == nullptr) + return nullptr; + for (; *sig_strings != nullptr; ++sig_strings) { + char *sig_str = *sig_strings; + Shiboken::AutoDecRef pystr(Py_BuildValue("s", sig_str)); + if (pystr.isNull() || PyList_Append(res_list, pystr) < 0) + return nullptr; + } + return res_list; +} + +static PyObject * +PySide_BuildSignatureProps(PyObject *type_key) { /* * Here is the second part of the function. @@ -890,13 +892,16 @@ PySide_BuildSignatureProps(PyObject *classmod) * them by the function result. */ init_module_2(); - Shiboken::AutoDecRef type_key(GetClassKey(classmod)); - if (type_key.isNull()) + if (type_key == nullptr) + return nullptr; + PyObject *numkey = PyDict_GetItem(pyside_globals->arg_dict, type_key); + Shiboken::AutoDecRef strings(_address_to_stringlist(numkey)); + if (strings.isNull()) return nullptr; - PyObject *arg_tup = PyDict_GetItem(pyside_globals->arg_dict, type_key); - if (arg_tup == nullptr) + Shiboken::AutoDecRef arg_tup(Py_BuildValue("(OO)", type_key, strings.object())); + if (arg_tup.isNull()) return nullptr; - PyObject *dict = PyObject_CallObject(pyside_globals->sigparse_func, arg_tup); + PyObject *dict = PyObject_CallObject(pyside_globals->pyside_type_init_func, arg_tup); if (dict == nullptr) { if (PyErr_Occurred()) return nullptr; @@ -905,44 +910,27 @@ PySide_BuildSignatureProps(PyObject *classmod) empty_dict = PyDict_New(); return empty_dict; } - // We replace the arguments by the result dict. if (PyDict_SetItem(pyside_globals->arg_dict, type_key, dict) < 0) return nullptr; return dict; } -int -SbkSpecial_Type_Ready(PyObject *module, PyTypeObject *type, - const char *signatures) -{ - int ret; - if (PyType_Ready(type) < 0) - return -1; - ret = PySide_BuildSignatureArgs(module, (PyObject *)type, signatures); - if (ret < 0) { - PyErr_Print(); - PyErr_SetNone(PyExc_ImportError); - } - return ret; -} - static int _finish_nested_classes(PyObject *dict); static int _build_func_to_type(PyObject *obtype); static int -PySide_FinishSignatures(PyObject *module, const char *signatures) +PySide_FinishSignatures(PyObject *module, const char *signatures[]) { /* * Initialization of module functions and resolving of static methods. */ - const char *name = PyModule_GetName(module); - if (name == NULL) + if (name == nullptr) return -1; // we abuse the call for types, since they both have a __name__ attribute. - if (PySide_BuildSignatureArgs(module, module, signatures) < 0) + if (PySide_BuildSignatureArgs(module, signatures) < 0) return -1; /* @@ -972,7 +960,7 @@ _finish_nested_classes(PyObject *obdict) PyTypeObject *subtype; Py_ssize_t pos = 0; - if (obdict == NULL) + if (obdict == nullptr) return -1; while (PyDict_Next(obdict, &pos, &key, &value)) { if (PyType_Check(value)) { @@ -1011,7 +999,7 @@ _build_func_to_type(PyObject *obtype) if (meth == 0) return 0; - for (; meth->ml_name != NULL; meth++) { + for (; meth->ml_name != nullptr; meth++) { /* * It is possible that a method is overwritten by another * attribute with the same name. This case was obviously provoked @@ -1027,7 +1015,7 @@ _build_func_to_type(PyObject *obtype) PyObject *descr = PyDict_GetItemString(dict, meth->ml_name); const char *look_attr = meth->ml_flags & METH_STATIC ? "__func__" : "__name__"; int check_name = meth->ml_flags & METH_STATIC ? 0 : 1; - if (descr == NULL) + if (descr == nullptr) return -1; // We first check all methods if one is hidden by something else. @@ -1036,7 +1024,8 @@ _build_func_to_type(PyObject *obtype) if (look.isNull() || (check_name && PyObject_RichCompareBool(look, given, Py_EQ) != 1)) { PyErr_Clear(); - Shiboken::AutoDecRef cfunc(PyCFunction_NewEx(meth, (PyObject*)type, NULL)); + Shiboken::AutoDecRef cfunc(PyCFunction_NewEx(meth, + reinterpret_cast<PyObject*>(type), nullptr)); if (cfunc.isNull()) return -1; if (meth->ml_flags & METH_STATIC) @@ -1069,8 +1058,23 @@ _build_func_to_type(PyObject *obtype) return 0; } +int +SbkSpecial_Type_Ready(PyObject *module, PyTypeObject *type, + const char *signatures[]) +{ + if (PyType_Ready(type) < 0) + return -1; + PyObject *ob_type = reinterpret_cast<PyObject *>(type); + int ret = PySide_BuildSignatureArgs(ob_type, signatures); + if (ret < 0) { + PyErr_Print(); + PyErr_SetNone(PyExc_ImportError); + } + return ret; +} + void -FinishSignatureInitialization(PyObject *module, const char *signatures) +FinishSignatureInitialization(PyObject *module, const char *signatures[]) { /* * This function is called at the very end of a module initialization. diff --git a/sources/shiboken2/libshiboken/signature.h b/sources/shiboken2/libshiboken/signature.h index c850698a6..6b477c52e 100644 --- a/sources/shiboken2/libshiboken/signature.h +++ b/sources/shiboken2/libshiboken/signature.h @@ -45,8 +45,8 @@ extern "C" { -LIBSHIBOKEN_API int SbkSpecial_Type_Ready(PyObject *, PyTypeObject *, const char *); //WS -LIBSHIBOKEN_API void FinishSignatureInitialization(PyObject *, const char *); +LIBSHIBOKEN_API int SbkSpecial_Type_Ready(PyObject *, PyTypeObject *, const char *[]); +LIBSHIBOKEN_API void FinishSignatureInitialization(PyObject *, const char *[]); LIBSHIBOKEN_API void SetError_Argument(PyObject *, const char *); } // extern "C" diff --git a/sources/shiboken2/shibokenmodule/CMakeLists.txt b/sources/shiboken2/shibokenmodule/CMakeLists.txt index 61c38c5d7..09731240f 100644 --- a/sources/shiboken2/shibokenmodule/CMakeLists.txt +++ b/sources/shiboken2/shibokenmodule/CMakeLists.txt @@ -3,14 +3,9 @@ project(shibokenmodule) configure_file("${CMAKE_CURRENT_SOURCE_DIR}/shibokenmodule.txt.in" "${CMAKE_CURRENT_BINARY_DIR}/shibokenmodule.txt" @ONLY) +set(sample_SRC ${CMAKE_CURRENT_BINARY_DIR}/shiboken2/shiboken2_module_wrapper.cpp) -set(sample_SRC -${CMAKE_CURRENT_BINARY_DIR}/shiboken2/shiboken2_module_wrapper.cpp -) - -set(shibokenmodule_TYPESYSTEM -${CMAKE_CURRENT_SOURCE_DIR}/typesystem_shiboken.xml -) +set(shibokenmodule_TYPESYSTEM ${CMAKE_CURRENT_SOURCE_DIR}/typesystem_shiboken.xml) add_custom_command( OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/mjb_rejected_classes.log" @@ -24,19 +19,16 @@ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMMENT "Running generator for 'shiboken2'..." ) -include_directories(${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_SOURCE_DIR} - ${libshiboken_SOURCE_DIR} - ${libshiboken_BINARY_DIR}) add_library(shibokenmodule MODULE ${sample_SRC}) +target_include_directories(shibokenmodule PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_SOURCE_DIR}) set_property(TARGET shibokenmodule PROPERTY PREFIX "") set_property(TARGET shibokenmodule PROPERTY OUTPUT_NAME "shiboken2${PYTHON_EXTENSION_SUFFIX}") if(WIN32) set_property(TARGET shibokenmodule PROPERTY SUFFIX ".pyd") endif() -target_link_libraries(shibokenmodule - libshiboken) +target_link_libraries(shibokenmodule PUBLIC libshiboken) add_dependencies(shibokenmodule shiboken2) create_generator_target(shibokenmodule) diff --git a/sources/shiboken2/shibokenmodule/__init__.py.in b/sources/shiboken2/shibokenmodule/__init__.py.in index 066fd3584..ed6ce5623 100644 --- a/sources/shiboken2/shibokenmodule/__init__.py.in +++ b/sources/shiboken2/shibokenmodule/__init__.py.in @@ -3,7 +3,26 @@ __version_info__ = (@shiboken_MAJOR_VERSION@, @shiboken_MINOR_VERSION@, @shiboke # PYSIDE-932: Python 2 cannot import 'zipfile' for embedding while being imported, itself. # We simply pre-load all imports for the signature extension. -import sys, zipfile, base64, marshal, io, contextlib +# Also, PyInstaller seems not always to be reliable in finding modules. +# We explicitly import everything that is needed: +import sys +import os +import zipfile +import base64 +import marshal +import io +import contextlib +import textwrap +import traceback +import types +import struct +import re +import tempfile +import keyword +import functools +if sys.version_info[0] == 3: + # PyInstaller seems to sometimes fail: + import typing from .shiboken2 import * diff --git a/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/loader.py b/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/loader.py index a564aedb9..6c76483a0 100644 --- a/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/loader.py +++ b/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/loader.py @@ -119,7 +119,6 @@ from shibokensupport import signature signature.get_signature = signature_bootstrap.get_signature del signature_bootstrap - def _get_modname(mod): return mod.__spec__.name if getattr(mod, "__spec__", None) else mod.__name__ diff --git a/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/mapping.py b/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/mapping.py index 9a8ee4c4e..306103304 100644 --- a/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/mapping.py +++ b/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/mapping.py @@ -418,6 +418,9 @@ def init_QtCore(): "PySide2.QtCore.quint32": int, "PySide2.QtCore.quint64": int, "PySide2.QtCore.quint8": int, + "PySide2.QtCore.short": int, + "PySide2.QtCore.unsigned short": int, + "PySide2.QtCore.signed char": Char, "PySide2.QtCore.uchar": Char, "PySide2.QtCore.unsigned char": Char, # 5.9 "PySide2.QtCore.long": int, diff --git a/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/parser.py b/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/parser.py index 09e78f1b0..72ca35757 100644 --- a/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/parser.py +++ b/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/parser.py @@ -224,7 +224,6 @@ def _resolve_type(thing, line): return _resolve_value(thing, None, line) def calculate_props(line): - line = line.strip() res = _parse_line(line) arglist = res["arglist"] annotations = {} @@ -257,8 +256,7 @@ def calculate_props(line): props["multi"] = res["multi"] return props -def fixup_multilines(sig_str): - lines = list(line.strip() for line in sig_str.strip().splitlines()) +def fixup_multilines(lines): res = [] multi_lines = [] for line in lines: @@ -282,15 +280,11 @@ def fixup_multilines(sig_str): res.append(line) return res -def pyside_type_init(typemod, sig_str): +def pyside_type_init(type_key, sig_strings): dprint() - if type(typemod) is types.ModuleType: - dprint("Initialization of module '{}'".format(typemod.__name__)) - else: - dprint("Initialization of type '{}.{}'".format(typemod.__module__, - typemod.__name__)) + dprint("Initialization of type key '{}'".format(type_key)) update_mapping() - lines = fixup_multilines(sig_str) + lines = fixup_multilines(sig_strings) ret = {} multi_props = [] for line in lines: diff --git a/sources/shiboken2/tests/CMakeLists.txt b/sources/shiboken2/tests/CMakeLists.txt index c06c56f6d..085a4344c 100644 --- a/sources/shiboken2/tests/CMakeLists.txt +++ b/sources/shiboken2/tests/CMakeLists.txt @@ -1,6 +1,3 @@ -find_package(Qt5 REQUIRED COMPONENTS Core) -include_directories(${Qt5Core_INCLUDE_DIRS}) - add_subdirectory(libminimal) if(NOT DEFINED MINIMAL_TESTS) add_subdirectory(libsample) diff --git a/sources/shiboken2/tests/dumpcodemodel/CMakeLists.txt b/sources/shiboken2/tests/dumpcodemodel/CMakeLists.txt index af18cb3c8..7c6d60fe2 100644 --- a/sources/shiboken2/tests/dumpcodemodel/CMakeLists.txt +++ b/sources/shiboken2/tests/dumpcodemodel/CMakeLists.txt @@ -1,5 +1,6 @@ add_executable(dumpcodemodel main.cpp) -include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${apiextractor_SOURCE_DIR} ${Qt5Core_INCLUDE_DIRS}) +target_include_directories(dumpcodemodel + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${apiextractor_SOURCE_DIR}) -target_link_libraries(dumpcodemodel apiextractor ${Qt5Core_LIBRARIES}) +target_link_libraries(dumpcodemodel PUBLIC apiextractor Qt5::Core) diff --git a/sources/shiboken2/tests/libminimal/CMakeLists.txt b/sources/shiboken2/tests/libminimal/CMakeLists.txt index a25892571..f906bdb84 100644 --- a/sources/shiboken2/tests/libminimal/CMakeLists.txt +++ b/sources/shiboken2/tests/libminimal/CMakeLists.txt @@ -6,8 +6,8 @@ listuser.cpp typedef.cpp ) -include_directories(${CMAKE_CURRENT_SOURCE_DIR}) -add_definitions("-DLIBMINIMAL_BUILD") add_library(libminimal SHARED ${libminimal_SRC}) +target_include_directories(libminimal PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) +target_compile_definitions(libminimal PRIVATE LIBMINIMAL_BUILD) set_property(TARGET libminimal PROPERTY PREFIX "") diff --git a/sources/shiboken2/tests/libother/CMakeLists.txt b/sources/shiboken2/tests/libother/CMakeLists.txt index 9b3cf5552..6aba91e13 100644 --- a/sources/shiboken2/tests/libother/CMakeLists.txt +++ b/sources/shiboken2/tests/libother/CMakeLists.txt @@ -7,12 +7,10 @@ otherobjecttype.cpp othermultiplederived.cpp ) -add_definitions("-DLIBOTHER_BUILD") add_library(libother SHARED ${libother_SRC}) +target_include_directories(libother PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) +target_compile_definitions(libother PRIVATE LIBOTHER_BUILD) +target_link_libraries(libother PUBLIC libsample) set_property(TARGET libother PROPERTY PREFIX "") -include_directories(${CMAKE_CURRENT_SOURCE_DIR} - ${libsample_SOURCE_DIR} - ${libsample_SOURCE_DIR}/..) -target_link_libraries(libother libsample) diff --git a/sources/shiboken2/tests/libsample/CMakeLists.txt b/sources/shiboken2/tests/libsample/CMakeLists.txt index ae3d40312..170829fbc 100644 --- a/sources/shiboken2/tests/libsample/CMakeLists.txt +++ b/sources/shiboken2/tests/libsample/CMakeLists.txt @@ -51,8 +51,8 @@ expression.cpp filter.cpp ) -include_directories(${CMAKE_CURRENT_SOURCE_DIR}) -add_definitions("-DLIBSAMPLE_BUILD") add_library(libsample SHARED ${libsample_SRC}) +target_include_directories(libsample PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) +target_compile_definitions(libsample PRIVATE LIBSAMPLE_BUILD) set_property(TARGET libsample PROPERTY PREFIX "") diff --git a/sources/shiboken2/tests/libsmart/CMakeLists.txt b/sources/shiboken2/tests/libsmart/CMakeLists.txt index 66c27cdae..152c57f25 100644 --- a/sources/shiboken2/tests/libsmart/CMakeLists.txt +++ b/sources/shiboken2/tests/libsmart/CMakeLists.txt @@ -4,8 +4,8 @@ set(libsmart_SRC smart.cpp ) -include_directories(${CMAKE_CURRENT_SOURCE_DIR}) -add_definitions("-DLIBSMART_BUILD") add_library(libsmart SHARED ${libsmart_SRC}) +target_include_directories(libsmart PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) +target_compile_definitions(libsmart PRIVATE LIBSMART_BUILD) set_property(TARGET libsmart PROPERTY PREFIX "") diff --git a/sources/shiboken2/tests/minimalbinding/CMakeLists.txt b/sources/shiboken2/tests/minimalbinding/CMakeLists.txt index 7301e1882..ffeb086a0 100644 --- a/sources/shiboken2/tests/minimalbinding/CMakeLists.txt +++ b/sources/shiboken2/tests/minimalbinding/CMakeLists.txt @@ -24,18 +24,13 @@ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMMENT "Running generator for 'minimal' test binding..." ) -include_directories(${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_SOURCE_DIR} - ${libminimal_SOURCE_DIR} - ${libshiboken_SOURCE_DIR} - ${libshiboken_BINARY_DIR}) add_library(minimal MODULE ${minimal_SRC}) +target_include_directories(minimal PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) +target_link_libraries(minimal PUBLIC libminimal libshiboken) set_property(TARGET minimal PROPERTY PREFIX "") set_property(TARGET minimal PROPERTY OUTPUT_NAME "minimal${PYTHON_EXTENSION_SUFFIX}") if(WIN32) set_property(TARGET minimal PROPERTY SUFFIX ".pyd") endif() -target_link_libraries(minimal - libminimal - libshiboken) + create_generator_target(minimal) diff --git a/sources/shiboken2/tests/minimalbinding/typesystem_minimal.xml b/sources/shiboken2/tests/minimalbinding/typesystem_minimal.xml index 968b27c53..03b88a970 100644 --- a/sources/shiboken2/tests/minimalbinding/typesystem_minimal.xml +++ b/sources/shiboken2/tests/minimalbinding/typesystem_minimal.xml @@ -1,4 +1,4 @@ -<?xml version="1.0"?> +<?xml version="1.0" encoding="UTF-8"?> <typesystem package="minimal"> <primitive-type name="bool"/> <primitive-type name="int"/> diff --git a/sources/shiboken2/tests/otherbinding/CMakeLists.txt b/sources/shiboken2/tests/otherbinding/CMakeLists.txt index 44855e297..bc5c4bdad 100644 --- a/sources/shiboken2/tests/otherbinding/CMakeLists.txt +++ b/sources/shiboken2/tests/otherbinding/CMakeLists.txt @@ -26,26 +26,17 @@ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMMENT "Running generator for 'other' test binding..." ) -include_directories(${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_SOURCE_DIR} - ${libother_SOURCE_DIR} - ${libsample_SOURCE_DIR} - ${libsample_SOURCE_DIR}/.. - ${sample_BINARY_DIR} - ${sample_BINARY_DIR}/sample - ${libshiboken_SOURCE_DIR} - ${libshiboken_BINARY_DIR}) add_library(other MODULE ${other_SRC}) +target_include_directories(other PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} + ${sample_BINARY_DIR}/sample) +target_link_libraries(other PUBLIC libother libsample libshiboken) set_property(TARGET other PROPERTY PREFIX "") set_property(TARGET other PROPERTY OUTPUT_NAME "other${PYTHON_EXTENSION_SUFFIX}") if(WIN32) set_property(TARGET other PROPERTY SUFFIX ".pyd") endif() -target_link_libraries(other - libother - libsample - libshiboken) + add_dependencies(other sample) create_generator_target(other) diff --git a/sources/shiboken2/tests/otherbinding/typesystem_other.xml b/sources/shiboken2/tests/otherbinding/typesystem_other.xml index 63ccdd518..2932dafb3 100644 --- a/sources/shiboken2/tests/otherbinding/typesystem_other.xml +++ b/sources/shiboken2/tests/otherbinding/typesystem_other.xml @@ -1,4 +1,4 @@ -<?xml version="1.0"?> +<?xml version="1.0" encoding="UTF-8"?> <typesystem package="other"> <load-typesystem name="typesystem_sample.xml" generate="no" /> diff --git a/sources/shiboken2/tests/samplebinding/CMakeLists.txt b/sources/shiboken2/tests/samplebinding/CMakeLists.txt index 9ecbd98e6..61090d30e 100644 --- a/sources/shiboken2/tests/samplebinding/CMakeLists.txt +++ b/sources/shiboken2/tests/samplebinding/CMakeLists.txt @@ -137,19 +137,14 @@ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMMENT "Running generator for 'sample' test binding..." ) -include_directories(${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_SOURCE_DIR} - ${libsample_SOURCE_DIR} - ${libshiboken_SOURCE_DIR} - ${libshiboken_BINARY_DIR}) add_library(sample MODULE ${sample_SRC}) +target_include_directories(sample PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) +target_link_libraries(sample PUBLIC libsample libshiboken) set_property(TARGET sample PROPERTY PREFIX "") set_property(TARGET sample PROPERTY OUTPUT_NAME "sample${PYTHON_EXTENSION_SUFFIX}") if(WIN32) set_property(TARGET sample PROPERTY SUFFIX ".pyd") endif() -target_link_libraries(sample - libsample - libshiboken) + create_generator_target(sample) diff --git a/sources/shiboken2/tests/samplebinding/typesystem_sample.xml b/sources/shiboken2/tests/samplebinding/typesystem_sample.xml index 78ceaab43..19b4948a1 100644 --- a/sources/shiboken2/tests/samplebinding/typesystem_sample.xml +++ b/sources/shiboken2/tests/samplebinding/typesystem_sample.xml @@ -1,4 +1,4 @@ -<?xml version="1.0"?> +<?xml version="1.0" encoding="UTF-8"?> <typesystem package="sample"> <suppress-warning text="Duplicate type entry: 'sample'" /> <suppress-warning text="Duplicate type entry: 'SampleNamespace'" /> diff --git a/sources/shiboken2/tests/smartbinding/CMakeLists.txt b/sources/shiboken2/tests/smartbinding/CMakeLists.txt index ed6bcef0a..88a7bc059 100644 --- a/sources/shiboken2/tests/smartbinding/CMakeLists.txt +++ b/sources/shiboken2/tests/smartbinding/CMakeLists.txt @@ -27,19 +27,14 @@ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMMENT "Running generator for 'smart' test binding..." ) -include_directories(${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_SOURCE_DIR} - ${libsmart_SOURCE_DIR} - ${libshiboken_SOURCE_DIR} - ${libshiboken_BINARY_DIR}) add_library(smart MODULE ${smart_SRC}) +target_include_directories(smart PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) +target_link_libraries(smart PUBLIC libsmart libshiboken) set_property(TARGET smart PROPERTY PREFIX "") set_property(TARGET smart PROPERTY OUTPUT_NAME "smart${PYTHON_EXTENSION_SUFFIX}") if(WIN32) set_property(TARGET smart PROPERTY SUFFIX ".pyd") endif() -target_link_libraries(smart - libsmart - libshiboken) + create_generator_target(smart) diff --git a/sources/shiboken2/tests/smartbinding/typesystem_smart.xml b/sources/shiboken2/tests/smartbinding/typesystem_smart.xml index aea1c2f73..0bb485957 100644 --- a/sources/shiboken2/tests/smartbinding/typesystem_smart.xml +++ b/sources/shiboken2/tests/smartbinding/typesystem_smart.xml @@ -1,4 +1,4 @@ -<?xml version="1.0"?> +<?xml version="1.0" encoding="UTF-8"?> <typesystem package="smart"> <primitive-type name="int" /> <primitive-type name="char" /> |