aboutsummaryrefslogtreecommitdiffstats
path: root/sources/shiboken2/ApiExtractor
diff options
context:
space:
mode:
Diffstat (limited to 'sources/shiboken2/ApiExtractor')
-rw-r--r--sources/shiboken2/ApiExtractor/CMakeLists.txt78
-rw-r--r--sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp431
-rw-r--r--sources/shiboken2/ApiExtractor/abstractmetabuilder.h2
-rw-r--r--sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h45
-rw-r--r--sources/shiboken2/ApiExtractor/abstractmetalang.cpp42
-rw-r--r--sources/shiboken2/ApiExtractor/abstractmetalang.h19
-rw-r--r--sources/shiboken2/ApiExtractor/apiextractor.cpp1
-rw-r--r--sources/shiboken2/ApiExtractor/messages.cpp6
-rw-r--r--sources/shiboken2/ApiExtractor/messages.h2
-rw-r--r--sources/shiboken2/ApiExtractor/parser/codemodel.cpp56
-rw-r--r--sources/shiboken2/ApiExtractor/parser/codemodel.h6
-rw-r--r--sources/shiboken2/ApiExtractor/tests/CMakeLists.txt24
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testabstractmetatype.cpp2
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testaddfunction.cpp37
-rw-r--r--sources/shiboken2/ApiExtractor/typedatabase.cpp5
-rw-r--r--sources/shiboken2/ApiExtractor/typesystem.cpp107
-rw-r--r--sources/shiboken2/ApiExtractor/typesystem.h25
-rw-r--r--sources/shiboken2/ApiExtractor/typesystem_p.h7
-rw-r--r--sources/shiboken2/ApiExtractor/typesystem_typedefs.h4
19 files changed, 455 insertions, 444 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&amp;)' 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&amp;)' 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 &currentPath) :
+ 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;