diff options
Diffstat (limited to 'sources/shiboken2')
181 files changed, 7696 insertions, 20940 deletions
diff --git a/sources/shiboken2/ApiExtractor/CMakeLists.txt b/sources/shiboken2/ApiExtractor/CMakeLists.txt index 26ae03173..f2af51c02 100644 --- a/sources/shiboken2/ApiExtractor/CMakeLists.txt +++ b/sources/shiboken2/ApiExtractor/CMakeLists.txt @@ -27,11 +27,17 @@ add_definitions(-DQT_PLUGIN) add_definitions(-DQT_SHARED) add_definitions(-DRXX_ALLOCATOR_INIT_0) +# Pass the path to the clang includes dir, so it headers like stdarg.h. +if(UNIX AND NOT APPLE) + add_definitions(-DCLANG_BUILTIN_INCLUDES_DIR="${CLANG_BUILTIN_INCLUDES_DIR}") +else() + add_definitions(-DCLANG_BUILTIN_INCLUDES_DIR="") +endif() + set(apiextractor_SRC apiextractor.cpp abstractmetabuilder.cpp abstractmetalang.cpp -asttoxml.cpp fileout.cpp graph.cpp reporthandler.cpp @@ -39,28 +45,19 @@ typeparser.cpp typesystem.cpp include.cpp typedatabase.cpp -parser/ast.cpp -parser/binder.cpp -parser/class_compiler.cpp +# Clang +clangparser/compilersupport.cpp +clangparser/clangparser.cpp +clangparser/clangbuilder.cpp +clangparser/clangdebugutils.cpp +clangparser/clangutils.cpp +# Old parser parser/codemodel.cpp -parser/codemodel_finder.cpp -parser/compiler_utils.cpp -parser/control.cpp -parser/declarator_compiler.cpp -parser/default_visitor.cpp -parser/dumptree.cpp -parser/lexer.cpp -parser/list.cpp -parser/name_compiler.cpp -parser/parser.cpp -parser/smallobject.cpp -parser/tokens.cpp -parser/type_compiler.cpp -parser/visitor.cpp -parser/rpp/builtin-macros.cpp -parser/rpp/preprocessor.cpp ) +set(APIEXTRACTOR_EXTRA_INCLUDES ${CLANG_EXTRA_INCLUDES}) +set(APIEXTRACTOR_EXTRA_LIBRARIES ${CLANG_EXTRA_LIBRARIES}) + if (NOT DISABLE_DOCSTRINGS) set(apiextractor_SRC ${apiextractor_SRC} @@ -68,16 +65,12 @@ if (NOT DISABLE_DOCSTRINGS) doxygenparser.cpp qtdocparser.cpp ) - set(APIEXTRACTOR_EXTRA_INCLUDES ${LIBXSLT_INCLUDE_DIR} ${LIBXML2_INCLUDE_DIR}) - set(APIEXTRACTOR_EXTRA_LIBRARIES ${LIBXSLT_LIBRARIES} ${LIBXML2_LIBRARIES}) -else() - set(APIEXTRACTOR_EXTRA_INCLUDES "") - set(APIEXTRACTOR_EXTRA_LIBRARIES "") + set(APIEXTRACTOR_EXTRA_INCLUDES ${APIEXTRACTOR_EXTRA_INCLUDES} ${LIBXSLT_INCLUDE_DIR} ${LIBXML2_INCLUDE_DIR}) + set(APIEXTRACTOR_EXTRA_LIBRARIES ${APIEXTRACTOR_EXTRA_LIBRARIES} ${LIBXSLT_LIBRARIES} ${LIBXML2_LIBRARIES}) 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) -qt5_add_resources(apiextractor_RCCS_SRC generator.qrc) set(CMAKE_AUTOMOC ON) include_directories(${CMAKE_CURRENT_SOURCE_DIR} diff --git a/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp b/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp index e71841ec3..37b82e99f 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp +++ b/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp @@ -30,18 +30,16 @@ #include "reporthandler.h" #include "typedatabase.h" -#include "parser/ast.h" -#include "parser/binder.h" -#include "parser/control.h" -#include "parser/default_visitor.h" -#include "parser/dumptree.h" -#include "parser/lexer.h" -#include "parser/parser.h" -#include "parser/tokens.h" +#include <clangparser/clangbuilder.h> +#include <clangparser/clangutils.h> + +#include "parser/codemodel.h" #include <QDebug> +#include <QDir> #include <QFile> #include <QFileInfo> +#include <QRegularExpression> #include <QTextCodec> #include <QTextStream> #include <QVariant> @@ -165,23 +163,48 @@ QSet<QString> AbstractMetaBuilder::qtMetaTypeDeclaredTypeNames() const return d->m_qmetatypeDeclaredTypenames; } +static QString msgNoFunctionForModification(const QString &signature, const QString &className, + const QStringList &possibleSignatures, + const AbstractMetaFunctionList &allFunctions) +{ + QString result; + QTextStream str(&result); + str << "signature '" << signature << "' for function modification in '" + << className << "' not found."; + if (possibleSignatures.isEmpty()) { + str << " No candidates were found. Member functions: "; + for (int f = 0, size = allFunctions.size(); f < size; ++f) { + if (f) + str << ", "; + str << allFunctions.at(f)->minimalSignature(); + } + } else { + str << " Possible candidates: " << possibleSignatures.join(QLatin1String(", ")); + } + return result; +} + void AbstractMetaBuilderPrivate::checkFunctionModifications() { TypeDatabase *types = TypeDatabase::instance(); - SingleTypeEntryHash entryHash = types->entries(); - QList<TypeEntry*> entries = entryHash.values(); + const SingleTypeEntryHash entryHash = types->entries(); - foreach (TypeEntry* entry, entries) { + for (SingleTypeEntryHash::const_iterator it = entryHash.cbegin(), end = entryHash.cend(); it != end; ++it) { + const TypeEntry *entry = it.value(); if (!entry) continue; if (!entry->isComplex() || entry->codeGeneration() == TypeEntry::GenerateNothing) continue; - ComplexTypeEntry* centry = static_cast<ComplexTypeEntry*>(entry); + const ComplexTypeEntry* centry = static_cast<const ComplexTypeEntry*>(entry); + + if (!(centry->codeGeneration() & TypeEntry::GenerateTargetLang)) + continue; + FunctionModificationList modifications = centry->functionModifications(); - foreach (const FunctionModification &modification, modifications) { - QString signature = modification.signature; + for (const FunctionModification &modification : qAsConst(modifications)) { + QString signature = modification.signature(); QString name = signature.trimmed(); name.truncate(name.indexOf(QLatin1Char('('))); @@ -190,11 +213,12 @@ void AbstractMetaBuilderPrivate::checkFunctionModifications() if (!clazz) continue; - AbstractMetaFunctionList functions = clazz->functions(); + const AbstractMetaFunctionList functions = clazz->functions(); bool found = false; QStringList possibleSignatures; - foreach (AbstractMetaFunction *function, functions) { - if (function->minimalSignature() == signature && function->implementingClass() == clazz) { + for (AbstractMetaFunction *function : functions) { + if (function->implementingClass() == clazz + && modification.matches(function->minimalSignature())) { found = true; break; } @@ -207,8 +231,8 @@ void AbstractMetaBuilderPrivate::checkFunctionModifications() if (!found) { qCWarning(lcShiboken).noquote().nospace() - << QStringLiteral("signature '%1' for function modification in '%2' not found. Possible candidates: %3") - .arg(signature, clazz->qualifiedCppName(), possibleSignatures.join(QLatin1String(", "))); + << msgNoFunctionForModification(signature, clazz->qualifiedCppName(), + possibleSignatures, functions); } } } @@ -227,41 +251,6 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::argumentToClass(ArgumentModelItem return returned; } -AbstractMetaClass *AbstractMetaBuilder::createMetaClass() -{ - return new AbstractMetaClass(); -} - -AbstractMetaEnum *AbstractMetaBuilder::createMetaEnum() -{ - return new AbstractMetaEnum(); -} - -AbstractMetaEnumValue *AbstractMetaBuilder::createMetaEnumValue() -{ - return new AbstractMetaEnumValue(); -} - -AbstractMetaField *AbstractMetaBuilder::createMetaField() -{ - return new AbstractMetaField(); -} - -AbstractMetaFunction *AbstractMetaBuilder::createMetaFunction() -{ - return new AbstractMetaFunction(); -} - -AbstractMetaArgument *AbstractMetaBuilder::createMetaArgument() -{ - return new AbstractMetaArgument(); -} - -AbstractMetaType *AbstractMetaBuilder::createMetaType() -{ - return new AbstractMetaType(); -} - /** * Checks the argument of a hash function and flags the type if it is a complex type */ @@ -329,7 +318,7 @@ void AbstractMetaBuilderPrivate::traverseOperatorFunction(FunctionModelItem item AbstractMetaClass* oldCurrentClass = m_currentClass; m_currentClass = baseoperandClass; AbstractMetaFunction *metaFunction = traverseFunction(item); - if (metaFunction && !metaFunction->isInvalid()) { + if (metaFunction) { // Strip away first argument, since that is the containing object AbstractMetaArgumentList arguments = metaFunction->arguments(); if (firstArgumentIsSelf || unaryOperator) { @@ -378,8 +367,7 @@ void AbstractMetaBuilderPrivate::traverseStreamOperator(FunctionModelItem item) m_currentClass = streamedClass; AbstractMetaFunction *streamFunction = traverseFunction(item); - if (streamFunction && !streamFunction->isInvalid()) { - QString name = item->name(); + if (streamFunction) { streamFunction->setFunctionType(AbstractMetaFunction::GlobalScopeFunction); // Strip first argument, since that is the containing object AbstractMetaArgumentList arguments = streamFunction->arguments(); @@ -390,7 +378,7 @@ void AbstractMetaBuilderPrivate::traverseStreamOperator(FunctionModelItem item) streamFunction->setArguments(arguments); - *streamFunction += AbstractMetaAttributes::Final; + *streamFunction += AbstractMetaAttributes::FinalInTargetLang; *streamFunction += AbstractMetaAttributes::Public; streamFunction->setOriginalAttributes(streamFunction->attributes()); @@ -427,7 +415,8 @@ void AbstractMetaBuilderPrivate::fixQObjectForScope(const FileModelItem &dom, const TypeDatabase *types, const NamespaceModelItem &scope) { - foreach (const ClassModelItem &item, scope->classes()) { + const ClassList &scopeClasses = scope->classes(); + for (const ClassModelItem &item : scopeClasses) { QString qualifiedName = item->qualifiedName().join(colonColon()); TypeEntry* entry = types->findType(qualifiedName); if (entry) { @@ -437,7 +426,7 @@ void AbstractMetaBuilderPrivate::fixQObjectForScope(const FileModelItem &dom, } const NamespaceList &namespaces = scope->namespaces(); - foreach (const NamespaceModelItem &n, namespaces) { + for (const NamespaceModelItem &n : namespaces) { if (scope != n) fixQObjectForScope(dom, types, n); } @@ -445,29 +434,26 @@ void AbstractMetaBuilderPrivate::fixQObjectForScope(const FileModelItem &dom, void AbstractMetaBuilderPrivate::sortLists() { - foreach (AbstractMetaClass *cls, m_metaClasses) + for (AbstractMetaClass *cls : qAsConst(m_metaClasses)) cls->sortFunctions(); } -FileModelItem AbstractMetaBuilderPrivate::buildDom(QIODevice *input) +FileModelItem AbstractMetaBuilderPrivate::buildDom(const QByteArrayList &arguments, + unsigned clangFlags) { - Q_ASSERT(input); - - if (!input->isOpen() && !input->open(QIODevice::ReadOnly)) - return FileModelItem(); - - QByteArray contents = input->readAll(); - input->close(); - - Control control; - Parser p(&control); - pool __pool; - - TranslationUnitAST* ast = p.parse(contents, contents.size(), &__pool); - - CodeModel model; - Binder binder(&model, p.location()); - return binder.run(ast); + clang::Builder builder; + FileModelItem result = clang::parse(arguments, clangFlags, builder) + ? builder.dom() : FileModelItem(); + const clang::BaseVisitor::Diagnostics &diagnostics = builder.diagnostics(); + if (const int diagnosticsCount = diagnostics.size()) { + QDebug d = qWarning(); + d.nospace(); + d.noquote(); + d << "Clang: " << diagnosticsCount << " diagnostic messages:\n"; + for (int i = 0; i < diagnosticsCount; ++i) + d << " " << diagnostics.at(i) << '\n'; + } + return result; } void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom) @@ -482,7 +468,7 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom) // Start the generation... const ClassList &typeValues = dom->classes(); ReportHandler::setProgressReference(typeValues); - foreach (const ClassModelItem &item, typeValues) { + for (const ClassModelItem &item : typeValues) { ReportHandler::progress(QLatin1String("Generating class model...")); AbstractMetaClass *cls = traverseClass(dom, item); if (!cls) @@ -492,8 +478,9 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom) } // We need to know all global enums - ReportHandler::setProgressReference(dom->enums()); - foreach (const EnumModelItem &item, dom->enums()) { + const EnumList &enums = dom->enums(); + ReportHandler::setProgressReference(enums); + for (const EnumModelItem &item : enums) { ReportHandler::progress(QLatin1String("Generating enum model...")); AbstractMetaEnum *metaEnum = traverseEnum(item, 0, QSet<QString>()); if (metaEnum) { @@ -504,7 +491,7 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom) const QSet<NamespaceModelItem> &namespaceTypeValues = dom->uniqueNamespaces(); ReportHandler::setProgressReference(namespaceTypeValues); - foreach (NamespaceModelItem item, namespaceTypeValues) { + for (const NamespaceModelItem &item : namespaceTypeValues) { ReportHandler::progress(QLatin1String("Generating namespace model...")); AbstractMetaClass *metaClass = traverseNamespace(dom, item); if (metaClass) @@ -513,9 +500,9 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom) // Go through all typedefs to see if we have defined any // specific typedefs to be used as classes. - TypeDefList typeDefs = dom->typeDefs(); + const TypeDefList typeDefs = dom->typeDefs(); ReportHandler::setProgressReference(typeDefs); - foreach (const TypeDefModelItem &typeDef, typeDefs) { + for (const TypeDefModelItem &typeDef : typeDefs) { ReportHandler::progress(QLatin1String("Resolving typedefs...")); AbstractMetaClass* cls = traverseTypeDef(dom, typeDef); addAbstractMetaClass(cls); @@ -523,14 +510,15 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom) figureOutEnumValues(); - foreach (const ClassModelItem &item, typeValues) + for (const ClassModelItem &item : typeValues) traverseClassMembers(item); - foreach (const NamespaceModelItem &item, namespaceTypeValues) + for (const NamespaceModelItem &item : namespaceTypeValues) traverseNamespaceMembers(item); // Global functions - foreach (const FunctionModelItem &func, dom->functions()) { + const FunctionList &functions = dom->functions(); + for (const FunctionModelItem &func : functions) { if (func->accessPolicy() != CodeModel::Public || func->name().startsWith(QLatin1String("operator"))) continue; @@ -558,14 +546,14 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom) } ReportHandler::setProgressReference(m_metaClasses); - foreach (AbstractMetaClass* cls, m_metaClasses) { + for (AbstractMetaClass *cls : qAsConst(m_metaClasses)) { ReportHandler::progress(QLatin1String("Fixing class inheritance...")); if (!cls->isInterface() && !cls->isNamespace()) setupInheritance(cls); } ReportHandler::setProgressReference(m_metaClasses); - foreach (AbstractMetaClass* cls, m_metaClasses) { + for (AbstractMetaClass *cls : qAsConst(m_metaClasses)) { ReportHandler::progress(QLatin1String("Detecting inconsistencies in class model...")); cls->fixFunctions(); @@ -574,7 +562,9 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom) << QStringLiteral("class '%1' does not have an entry in the type system") .arg(cls->name()); } else { - bool couldAddDefaultCtors = !cls->isFinalInCpp() && !cls->isInterface() && !cls->isNamespace(); + const bool couldAddDefaultCtors = cls->isConstructible() + && !cls->isInterface() && !cls->isNamespace() + && (cls->attributes() & AbstractMetaAttributes::HasRejectedConstructor) == 0; if (couldAddDefaultCtors) { if (!cls->hasConstructors()) cls->addDefaultConstructor(); @@ -586,11 +576,10 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom) if (cls->isAbstract() && !cls->isInterface()) cls->typeEntry()->setLookupName(cls->typeEntry()->targetLangName() + QLatin1String("$ConcreteWrapper")); } - TypeEntryHash allEntries = types->allEntries(); + const TypeEntryHash allEntries = types->allEntries(); ReportHandler::progress(QLatin1String("Detecting inconsistencies in typesystem...")); - foreach (QList<TypeEntry*> entries, allEntries) { - foreach (TypeEntry* entry, entries) { - + for (TypeEntryHash::const_iterator it = allEntries.cbegin(), end = allEntries.cend(); it != end; ++it) { + for (TypeEntry *entry : it.value()) { if (entry->isPrimitive()) continue; @@ -600,15 +589,17 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom) && !entry->isContainer() && !entry->isCustom() && !entry->isVariant() + && (entry->generateCode() & TypeEntry::GenerateTargetLang) && !AbstractMetaClass::findClass(m_metaClasses, entry->qualifiedCppName())) { qCWarning(lcShiboken).noquote().nospace() << QStringLiteral("type '%1' is specified in typesystem, but not defined. This could potentially lead to compilation errors.") .arg(entry->qualifiedCppName()); } else if (entry->generateCode() && entry->type() == TypeEntry::FunctionType) { const FunctionTypeEntry* fte = static_cast<const FunctionTypeEntry*>(entry); - foreach (const QString &signature, fte->signatures()) { + const QStringList &signatures = fte->signatures(); + for (const QString &signature : signatures) { bool ok = false; - foreach (AbstractMetaFunction* func, m_globalFunctions) { + for (AbstractMetaFunction* func : qAsConst(m_globalFunctions)) { if (signature == func->minimalSignature()) { ok = true; break; @@ -620,7 +611,7 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom) .arg(signature); } } - } else if (entry->isEnum()) { + } else if (entry->isEnum() && (entry->generateCode() & TypeEntry::GenerateTargetLang)) { const QString name = ((EnumTypeEntry*) entry)->targetLangQualifier(); AbstractMetaClass *cls = AbstractMetaClass::findClass(m_metaClasses, name); @@ -628,7 +619,7 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom) if (cls) { enumFound = cls->findEnum(entry->targetLangName()); } else { // Global enum - foreach (AbstractMetaEnum* metaEnum, m_enums) { + for (AbstractMetaEnum *metaEnum : qAsConst(m_enums)) { if (metaEnum->typeEntry() == entry) { enumFound = true; break; @@ -647,14 +638,14 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom) } { - FunctionList hashFunctions = dom->findFunctions(QLatin1String("qHash")); - foreach (const FunctionModelItem &item, hashFunctions) + const FunctionList &hashFunctions = dom->findFunctions(QLatin1String("qHash")); + for (const FunctionModelItem &item : hashFunctions) registerHashFunction(item); } { - FunctionList hashFunctions = dom->findFunctions(QLatin1String("operator<<")); - foreach (const FunctionModelItem &item, hashFunctions) + const FunctionList &streamOps = dom->findFunctions(QLatin1String("operator<<")); + for (const FunctionModelItem &item : streamOps) registerToStringCapability(item); } @@ -671,7 +662,7 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom) const FunctionList potentiallyBinaryOperators = dom->findFunctions(QStringLiteral("operator*")) + dom->findFunctions(QStringLiteral("operator&")); - foreach (const FunctionModelItem &item, potentiallyBinaryOperators) { + for (const FunctionModelItem &item : potentiallyBinaryOperators) { if (!item->arguments().isEmpty()) binaryOperators.append(item); } @@ -682,14 +673,14 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom) binaryOperators.append(dom->findFunctions(QStringLiteral("operator~"))); binaryOperators.append(dom->findFunctions(QStringLiteral("operator>"))); - foreach (const FunctionModelItem &item, binaryOperators) + for (const FunctionModelItem &item : qAsConst(binaryOperators)) traverseOperatorFunction(item); } { - FunctionList streamOperators = dom->findFunctions(QLatin1String("operator<<")) - + dom->findFunctions(QLatin1String("operator>>")); - foreach (const FunctionModelItem &item, streamOperators) + const FunctionList streamOperators = dom->findFunctions(QLatin1String("operator<<")) + + dom->findFunctions(QLatin1String("operator>>")); + for (const FunctionModelItem &item : streamOperators) traverseStreamOperator(item); } @@ -699,7 +690,7 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom) // sort all classes topologically m_metaClasses = classesTopologicalSorted(); - foreach (AbstractMetaClass* cls, m_metaClasses) { + for (AbstractMetaClass* cls : qAsConst(m_metaClasses)) { // setupEquals(cls); // setupComparable(cls); setupClonable(cls); @@ -719,7 +710,8 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom) m_currentClass = 0; // Functions added to the module on the type system. - foreach (const AddedFunction &addedFunc, types->globalUserFunctions()) { + const AddedFunctionList &globalUserFunctions = types->globalUserFunctions(); + for (const AddedFunction &addedFunc : globalUserFunctions) { AbstractMetaFunction* metaFunc = traverseFunction(addedFunc); metaFunc->setFunctionType(AbstractMetaFunction::NormalFunction); m_globalFunctions << metaFunc; @@ -728,13 +720,15 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom) std::puts(""); } -bool AbstractMetaBuilder::build(QIODevice *input) +bool AbstractMetaBuilder::build(const QByteArrayList &arguments, unsigned clangFlags) { - FileModelItem dom = d->buildDom(input); - const bool result = dom.data() != Q_NULLPTR; - if (result) - d->traverseDom(dom); - return result; + const FileModelItem dom = d->buildDom(arguments, clangFlags); + if (dom.isNull()) + return false; + if (ReportHandler::isDebug(ReportHandler::MediumDebug)) + qCDebug(lcShiboken) << dom.data(); + d->traverseDom(dom); + return true; } void AbstractMetaBuilder::setLogDirectory(const QString& logDir) @@ -784,7 +778,7 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseNamespace(const FileModel return 0; } - AbstractMetaClass* metaClass = q->createMetaClass(); + AbstractMetaClass* metaClass = new AbstractMetaClass; metaClass->setTypeEntry(type); *metaClass += AbstractMetaAttributes::Public; @@ -801,8 +795,8 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseNamespace(const FileModel pushScope(namespaceItem); m_namespacePrefix = currentScope()->qualifiedName().join(colonColon()); - ClassList classes = namespaceItem->classes(); - foreach (const ClassModelItem &cls, classes) { + const ClassList &classes = namespaceItem->classes(); + for (const ClassModelItem &cls : classes) { AbstractMetaClass* mjc = traverseClass(dom, cls); if (mjc) { metaClass->addInnerClass(mjc); @@ -814,7 +808,7 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseNamespace(const FileModel // Go through all typedefs to see if we have defined any // specific typedefs to be used as classes. const TypeDefList typeDefs = namespaceItem->typeDefs(); - foreach (const TypeDefModelItem &typeDef, typeDefs) { + for (const TypeDefModelItem &typeDef : typeDefs) { AbstractMetaClass *cls = traverseTypeDef(dom, typeDef); if (cls) { metaClass->addInnerClass(cls); @@ -825,7 +819,7 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseNamespace(const FileModel // Traverse namespaces recursively const QSet<NamespaceModelItem> &innerNamespaces = namespaceItem->uniqueNamespaces(); - foreach (const NamespaceModelItem &ni, innerNamespaces) { + for (const NamespaceModelItem &ni : innerNamespaces) { AbstractMetaClass* mjc = traverseNamespace(dom, ni); if (mjc) { metaClass->addInnerClass(mjc); @@ -985,8 +979,8 @@ void AbstractMetaBuilderPrivate::figureOutEnumValuesForClass(AbstractMetaClass * if (classes->contains(metaClass)) return; - AbstractMetaEnumList enums = metaClass->enums(); - foreach (AbstractMetaEnum* e, enums) { + const AbstractMetaEnumList &enums = metaClass->enums(); + for (AbstractMetaEnum* e : enums) { if (!e) { qCWarning(lcShiboken).noquote().nospace() << "bad enum in class " << metaClass->name(); continue; @@ -1009,10 +1003,10 @@ void AbstractMetaBuilderPrivate::figureOutEnumValues() // Keep a set of classes that we already traversed. We use this to // enforce that we traverse base classes prior to subclasses. QSet<AbstractMetaClass*> classes; - foreach (AbstractMetaClass *c, m_metaClasses) + for (AbstractMetaClass *c : qAsConst(m_metaClasses)) figureOutEnumValuesForClass(c, &classes); - foreach (AbstractMetaEnum* metaEnum, m_globalEnums) { + for (AbstractMetaEnum* metaEnum : qAsConst(m_globalEnums)) { AbstractMetaEnumValueList enumValues = metaEnum->values(); int value = 0; for (int i = 0; i < enumValues.size(); ++i) { @@ -1025,9 +1019,11 @@ void AbstractMetaBuilderPrivate::figureOutEnumValues() void AbstractMetaBuilderPrivate::figureOutDefaultEnumArguments() { - foreach (AbstractMetaClass* metaClass, m_metaClasses) { - foreach (AbstractMetaFunction* metaFunction, metaClass->functions()) { - foreach (AbstractMetaArgument *arg, metaFunction->arguments()) { + for (AbstractMetaClass* metaClass : qAsConst(m_metaClasses)) { + const AbstractMetaFunctionList &functions = metaClass->functions(); + for (AbstractMetaFunction* metaFunction : functions) { + const AbstractMetaArgumentList &arguments = metaFunction->arguments(); + for (AbstractMetaArgument *arg : arguments) { QString expr = arg->defaultValueExpression(); if (expr.isEmpty()) continue; @@ -1053,7 +1049,7 @@ AbstractMetaEnum *AbstractMetaBuilderPrivate::traverseEnum(EnumModelItem enumIte TypeEntry* typeEntry = 0; if (enumItem->accessPolicy() == CodeModel::Private) { QStringList names = enumItem->qualifiedName(); - QString enumName = names.last(); + QString enumName = names.constLast(); QString nspace; if (names.size() > 1) nspace = QStringList(names.mid(0, names.size() - 1)).join(colonColon()); @@ -1063,7 +1059,8 @@ AbstractMetaEnum *AbstractMetaBuilderPrivate::traverseEnum(EnumModelItem enumIte typeEntry = TypeDatabase::instance()->findType(qualifiedName); } else { QStringList tmpQualifiedName = enumItem->qualifiedName(); - foreach (const EnumeratorModelItem& enumValue, enumItem->enumerators()) { + const EnumeratorList &enums = enumItem->enumerators(); + for (const EnumeratorModelItem& enumValue : enums) { tmpQualifiedName.removeLast(); tmpQualifiedName << enumValue->name(); qualifiedName = tmpQualifiedName.join(colonColon()); @@ -1079,22 +1076,26 @@ AbstractMetaEnum *AbstractMetaBuilderPrivate::traverseEnum(EnumModelItem enumIte if (m_currentClass) className = m_currentClass->typeEntry()->qualifiedCppName(); - if (TypeDatabase::instance()->isEnumRejected(className, enumName)) { + QString rejectReason; + if (TypeDatabase::instance()->isEnumRejected(className, enumName, &rejectReason)) { if (typeEntry) typeEntry->setCodeGeneration(TypeEntry::GenerateNothing); - m_rejectedEnums.insert(qualifiedName, AbstractMetaBuilder::GenerationDisabled); + m_rejectedEnums.insert(qualifiedName + rejectReason, AbstractMetaBuilder::GenerationDisabled); return 0; } - if (!typeEntry || !typeEntry->isEnum()) { - qCWarning(lcShiboken).noquote().nospace() - << QStringLiteral("enum '%1' does not have a type entry or is not an enum") + if ((!typeEntry || !typeEntry->isEnum())) { + if (!m_currentClass || + (m_currentClass->typeEntry()->codeGeneration() & TypeEntry::GenerateTargetLang)) { + qCWarning(lcShiboken).noquote().nospace() + << QStringLiteral("enum '%1' does not have a type entry or is not an enum") .arg(qualifiedName); + } m_rejectedEnums.insert(qualifiedName, AbstractMetaBuilder::NotInTypeSystem); return 0; } - AbstractMetaEnum *metaEnum = q->createMetaEnum(); + AbstractMetaEnum *metaEnum = new AbstractMetaEnum; if (enumsDeclarations.contains(qualifiedName) || enumsDeclarations.contains(enumName)) { metaEnum->setHasQEnumsDeclaration(true); @@ -1119,9 +1120,10 @@ AbstractMetaEnum *AbstractMetaBuilderPrivate::traverseEnum(EnumModelItem enumIte if (ReportHandler::isDebug(ReportHandler::MediumDebug)) qCDebug(lcShiboken) << " - traversing enum " << metaEnum->fullName(); - foreach (const EnumeratorModelItem &value, enumItem->enumerators()) { + const EnumeratorList &enums = enumItem->enumerators(); + for (const EnumeratorModelItem &value : enums) { - AbstractMetaEnumValue *metaEnumValue = q->createMetaEnumValue(); + AbstractMetaEnumValue *metaEnumValue = new AbstractMetaEnumValue; metaEnumValue->setName(value->name()); // Deciding the enum value... @@ -1148,7 +1150,8 @@ AbstractMetaEnum *AbstractMetaBuilderPrivate::traverseEnum(EnumModelItem enumIte metaEnum->setOriginalAttributes(metaEnum->attributes()); // Register all enum values on Type database - foreach(EnumeratorModelItem e, enumItem->enumerators()) { + const EnumeratorList &enumerators = enumItem->enumerators(); + for (const EnumeratorModelItem &e : enumerators) { QString name; if (enclosing) { name += enclosing->name(); @@ -1194,7 +1197,7 @@ AbstractMetaClass* AbstractMetaBuilderPrivate::traverseTypeDef(const FileModelIt if (type->isObject()) static_cast<ObjectTypeEntry *>(type)->setQObject(isQObject(dom, stripTemplateArgs(typeDef->type().qualifiedName().join(colonColon())))); - AbstractMetaClass *metaClass = q->createMetaClass(); + AbstractMetaClass *metaClass = new AbstractMetaClass; metaClass->setTypeDef(true); metaClass->setTypeEntry(type); metaClass->setBaseClassNames(QStringList() << typeDef->type().qualifiedName().join(colonColon())); @@ -1253,9 +1256,20 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseClass(const FileModelItem if (type->isObject()) ((ObjectTypeEntry*)type)->setQObject(isQObject(dom, fullClassName)); - AbstractMetaClass *metaClass = q->createMetaClass(); + AbstractMetaClass *metaClass = new AbstractMetaClass; metaClass->setTypeEntry(type); - metaClass->setBaseClassNames(classItem->baseClasses()); + + if (classItem->isFinal()) + *metaClass += AbstractMetaAttributes::FinalCppClass; + + QStringList baseClassNames; + const QVector<_ClassModelItem::BaseClass> &baseClasses = classItem->baseClasses(); + for (const _ClassModelItem::BaseClass &baseClass : baseClasses) { + if (baseClass.accessPolicy == CodeModel::Public) + baseClassNames.append(baseClass.name); + } + + metaClass->setBaseClassNames(baseClassNames); *metaClass += AbstractMetaAttributes::Public; if (type->stream()) metaClass->setStream(true); @@ -1271,7 +1285,7 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseClass(const FileModelItem } TemplateParameterList template_parameters = classItem->templateParameters(); - QList<TypeEntry *> template_args; + QVector<TypeEntry *> template_args; template_args.clear(); for (int i = 0; i < template_parameters.size(); ++i) { const TemplateParameterModelItem ¶m = template_parameters.at(i); @@ -1288,7 +1302,7 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseClass(const FileModelItem // Inner classes { const ClassList &innerClasses = classItem->classes(); - foreach (const ClassModelItem &ci, innerClasses) { + for (const ClassModelItem &ci : innerClasses) { AbstractMetaClass *cl = traverseClass(dom, ci); if (cl) { cl->setEnclosingClass(metaClass); @@ -1302,7 +1316,7 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseClass(const FileModelItem // Go through all typedefs to see if we have defined any // specific typedefs to be used as classes. const TypeDefList typeDefs = classItem->typeDefs(); - foreach (const TypeDefModelItem &typeDef, typeDefs) { + for (const TypeDefModelItem &typeDef : typeDefs) { AbstractMetaClass *cls = traverseTypeDef(dom, typeDef); if (cls) { cls->setEnclosingClass(metaClass); @@ -1329,7 +1343,7 @@ void AbstractMetaBuilderPrivate::traverseScopeMembers(ScopeModelItem item, // Inner classes const ClassList &innerClasses = item->classes(); - foreach (const ClassModelItem& ci, innerClasses) + for (const ClassModelItem& ci : innerClasses) traverseClassMembers(ci); } @@ -1380,7 +1394,7 @@ void AbstractMetaBuilderPrivate::traverseNamespaceMembers(NamespaceModelItem ite // Inner namespaces const QSet<NamespaceModelItem> &innerNamespaces = item->uniqueNamespaces(); - foreach (const NamespaceModelItem &ni, innerNamespaces) + for (const NamespaceModelItem &ni : innerNamespaces) traverseNamespaceMembers(ni); m_currentClass = oldCurrentClass; @@ -1410,14 +1424,15 @@ AbstractMetaField *AbstractMetaBuilderPrivate::traverseField(VariableModelItem f if (field->accessPolicy() == CodeModel::Private) return 0; - if (TypeDatabase::instance()->isFieldRejected(className, fieldName)) { - m_rejectedFields.insert(qualifiedFieldSignatureWithType(className, field), + QString rejectReason; + if (TypeDatabase::instance()->isFieldRejected(className, fieldName, &rejectReason)) { + m_rejectedFields.insert(qualifiedFieldSignatureWithType(className, field) + rejectReason, AbstractMetaBuilder::GenerationDisabled); return 0; } - AbstractMetaField *metaField = q->createMetaField(); + AbstractMetaField *metaField = new AbstractMetaField; metaField->setName(fieldName); metaField->setEnclosingClass(cls); @@ -1427,9 +1442,11 @@ AbstractMetaField *AbstractMetaBuilderPrivate::traverseField(VariableModelItem f if (!metaType || !ok) { const QString type = TypeInfo::resolveType(fieldType, currentScope()).qualifiedName().join(colonColon()); - qCWarning(lcShiboken).noquote().nospace() - << QStringLiteral("skipping field '%1::%2' with unmatched type '%3'") - .arg(m_currentClass->name(), fieldName, type); + if (m_currentClass->typeEntry()->codeGeneration() & TypeEntry::GenerateTargetLang) { + qCWarning(lcShiboken).noquote().nospace() + << QStringLiteral("skipping field '%1::%2' with unmatched type '%3'") + .arg(m_currentClass->name(), fieldName, type); + } delete metaField; return 0; } @@ -1455,7 +1472,8 @@ AbstractMetaField *AbstractMetaBuilderPrivate::traverseField(VariableModelItem f void AbstractMetaBuilderPrivate::traverseFields(ScopeModelItem scope_item, AbstractMetaClass *metaClass) { - foreach (const VariableModelItem &field, scope_item->variables()) { + const VariableList &variables = scope_item->variables(); + for (const VariableModelItem &field : variables) { AbstractMetaField* metaField = traverseField(field, metaClass); if (metaField && !metaField->isModifiedRemoved()) { @@ -1478,11 +1496,6 @@ void AbstractMetaBuilderPrivate::setupFunctionDefaults(AbstractMetaFunction *met if (metaFunction->name() == QLatin1String("operator_equal")) metaClass->setHasEqualsOperator(true); - - if (!metaFunction->isFinalInTargetLang() - && metaFunction->isRemovedFrom(metaClass, TypeSystem::TargetLangCode)) { - *metaFunction += AbstractMetaAttributes::FinalInCpp; - } } void AbstractMetaBuilderPrivate::fixReturnTypeOfConversionOperator(AbstractMetaFunction *metaFunction) @@ -1491,7 +1504,9 @@ void AbstractMetaBuilderPrivate::fixReturnTypeOfConversionOperator(AbstractMetaF return; TypeDatabase* types = TypeDatabase::instance(); - QString castTo = metaFunction->name().remove(QRegExp(QLatin1String("^operator "))).trimmed(); + static const QRegularExpression operatorRegExp(QStringLiteral("^operator ")); + Q_ASSERT(operatorRegExp.isValid()); + QString castTo = metaFunction->name().remove(operatorRegExp).trimmed(); if (castTo.endsWith(QLatin1Char('&'))) castTo.chop(1); @@ -1502,7 +1517,7 @@ void AbstractMetaBuilderPrivate::fixReturnTypeOfConversionOperator(AbstractMetaF if (!retType) return; - AbstractMetaType* metaType = q->createMetaType(); + AbstractMetaType* metaType = new AbstractMetaType; metaType->setTypeEntry(retType); metaFunction->replaceType(metaType); } @@ -1542,7 +1557,7 @@ static bool _compareAbstractMetaFunctions(const AbstractMetaFunction* func, cons // "QList(const QList &)" to "QList(const QList<T> &)". static bool _fixFunctionModelItemTypes(FunctionModelItem& function, const AbstractMetaClass* metaClass) { - const QList<TypeEntry *> &templateTypes = metaClass->templateArguments(); + const QVector<TypeEntry *> &templateTypes = metaClass->templateArguments(); if (templateTypes.isEmpty()) return false; @@ -1577,14 +1592,18 @@ static bool _fixFunctionModelItemTypes(FunctionModelItem& function, const Abstra return templateTypeFixed; } -AbstractMetaFunctionList AbstractMetaBuilderPrivate::classFunctionList(const ScopeModelItem &scopeItem) +AbstractMetaFunctionList AbstractMetaBuilderPrivate::classFunctionList(const ScopeModelItem &scopeItem, + bool *constructorRejected) { + *constructorRejected = false; AbstractMetaFunctionList result; const FunctionList &scopeFunctionList = scopeItem->functions(); result.reserve(scopeFunctionList.size()); - foreach (const FunctionModelItem &function, scopeItem->functions()) { + for (const FunctionModelItem &function : scopeFunctionList) { if (AbstractMetaFunction *metaFunction = traverseFunction(function)) result.append(metaFunction); + else if (function->functionType() == CodeModel::Constructor) + *constructorRejected = true; } return result; } @@ -1613,15 +1632,17 @@ private: }; AbstractMetaFunctionList AbstractMetaBuilderPrivate::templateClassFunctionList(const ScopeModelItem &scopeItem, - AbstractMetaClass *metaClass) + AbstractMetaClass *metaClass, + bool *constructorRejected) { AbstractMetaFunctionList result; AbstractMetaFunctionList unchangedFunctions; + *constructorRejected = false; const FunctionList &scopeFunctionList = scopeItem->functions(); result.reserve(scopeFunctionList.size()); unchangedFunctions.reserve(scopeFunctionList.size()); - foreach (FunctionModelItem function, scopeItem->functions()) { + for (FunctionModelItem function : scopeFunctionList) { // This fixes method's arguments and return types that are templates // but the template variable wasn't declared in the C++ header. const bool templateTypeFixed =_fixFunctionModelItemTypes(function, metaClass); @@ -1629,11 +1650,13 @@ AbstractMetaFunctionList AbstractMetaBuilderPrivate::templateClassFunctionList(c result.append(metaFunction); if (!templateTypeFixed) unchangedFunctions.append(metaFunction); + } else if (function->functionType() == CodeModel::Constructor) { + *constructorRejected = true; } } - const AbstractMetaFunctionList::ConstIterator unchangedBegin = unchangedFunctions.begin(); - const AbstractMetaFunctionList::ConstIterator unchangedEnd = unchangedFunctions.end(); + const AbstractMetaFunctionList::ConstIterator unchangedBegin = unchangedFunctions.cbegin(); + const AbstractMetaFunctionList::ConstIterator unchangedEnd = unchangedFunctions.cend(); for (int i = result.size() - 1; i >= 0; --i) { AbstractMetaFunction *function = result.at(i); if (!unchangedFunctions.contains(function) @@ -1647,12 +1670,15 @@ AbstractMetaFunctionList AbstractMetaBuilderPrivate::templateClassFunctionList(c void AbstractMetaBuilderPrivate::traverseFunctions(ScopeModelItem scopeItem, AbstractMetaClass *metaClass) { - + bool constructorRejected = false; const AbstractMetaFunctionList functions = metaClass->templateArguments().isEmpty() - ? classFunctionList(scopeItem) - : templateClassFunctionList(scopeItem, metaClass); + ? classFunctionList(scopeItem, &constructorRejected) + : templateClassFunctionList(scopeItem, metaClass, &constructorRejected); + + if (constructorRejected) + *metaClass += AbstractMetaAttributes::HasRejectedConstructor; - foreach (AbstractMetaFunction *metaFunction, functions) { + for (AbstractMetaFunction *metaFunction : functions){ metaFunction->setOriginalAttributes(metaFunction->attributes()); if (metaClass->isNamespace()) *metaFunction += AbstractMetaAttributes::Static; @@ -1680,24 +1706,26 @@ void AbstractMetaBuilderPrivate::traverseFunctions(ScopeModelItem scopeItem, } const bool isInvalidDestructor = metaFunction->isDestructor() && metaFunction->isPrivate(); - const bool isInvalidConstructor = metaFunction->isConstructor() - && ((metaFunction->isPrivate() && metaFunction->functionType() == AbstractMetaFunction::ConstructorFunction) - || metaFunction->isInvalid()); + const bool isInvalidConstructor = metaFunction->functionType() == AbstractMetaFunction::ConstructorFunction + && metaFunction->isPrivate(); + if (isInvalidConstructor) + metaClass->setHasPrivateConstructor(true); if ((isInvalidDestructor || isInvalidConstructor) && !metaClass->hasNonPrivateConstructor()) { - *metaClass += AbstractMetaAttributes::Final; + *metaClass += AbstractMetaAttributes::FinalInTargetLang; } else if (metaFunction->isConstructor() && !metaFunction->isPrivate()) { - *metaClass -= AbstractMetaAttributes::Final; + *metaClass -= AbstractMetaAttributes::FinalInTargetLang; metaClass->setHasNonPrivateConstructor(true); } // Classes with virtual destructors should always have a shell class // (since we aren't registering the destructors, we need this extra check) - if (metaFunction->isDestructor() && !metaFunction->isFinal()) + if (metaFunction->isDestructor() && metaFunction->isVirtual() + && metaFunction->visibility() != AbstractMetaAttributes::Private) { metaClass->setForceShellClass(true); + } if (!metaFunction->isDestructor() - && !metaFunction->isInvalid() && !(metaFunction->isPrivate() && metaFunction->functionType() == AbstractMetaFunction::ConstructorFunction)) { setupFunctionDefaults(metaFunction, metaClass); @@ -1736,15 +1764,16 @@ void AbstractMetaBuilderPrivate::traverseFunctions(ScopeModelItem scopeItem, void AbstractMetaBuilderPrivate::fillAddedFunctions(AbstractMetaClass *metaClass) { // Add the functions added by the typesystem - foreach (const AddedFunction &addedFunc, metaClass->typeEntry()->addedFunctions()) + const AddedFunctionList &addedFunctions = metaClass->typeEntry()->addedFunctions(); + for (const AddedFunction &addedFunc : addedFunctions) traverseFunction(addedFunc, metaClass); } void AbstractMetaBuilderPrivate::applyFunctionModifications(AbstractMetaFunction *func) { - FunctionModificationList mods = func->modifications(func->implementingClass()); + const FunctionModificationList &mods = func->modifications(func->implementingClass()); AbstractMetaFunction& funcRef = *func; - foreach (const FunctionModification &mod, mods) { + for (const FunctionModification &mod : mods) { if (mod.isRenameModifier()) { func->setOriginalName(func->name()); func->setName(mod.renamedTo()); @@ -1783,10 +1812,10 @@ bool AbstractMetaBuilderPrivate::setupInheritance(AbstractMetaClass *metaClass) QStringList baseClasses = metaClass->baseClassNames(); // we only support our own containers and ONLY if there is only one baseclass - if (baseClasses.size() == 1 && baseClasses.first().contains(QLatin1Char('<'))) { + if (baseClasses.size() == 1 && baseClasses.constFirst().contains(QLatin1Char('<'))) { TypeParser::Info info; ComplexTypeEntry* baseContainerType; - AbstractMetaClass* templ = findTemplateClass(baseClasses.first(), metaClass, &info, &baseContainerType); + AbstractMetaClass* templ = findTemplateClass(baseClasses.constFirst(), metaClass, &info, &baseContainerType); if (templ) { setupInheritance(templ); inheritTemplate(metaClass, templ, info); @@ -1808,7 +1837,7 @@ bool AbstractMetaBuilderPrivate::setupInheritance(AbstractMetaClass *metaClass) qCWarning(lcShiboken).noquote().nospace() << QStringLiteral("template baseclass '%1' of '%2' is not known") - .arg(baseClasses.first(), metaClass->name()); + .arg(baseClasses.constFirst(), metaClass->name()); return false; } @@ -1866,8 +1895,8 @@ bool AbstractMetaBuilderPrivate::setupInheritance(AbstractMetaClass *metaClass) } metaClass->addInterface(iface); - AbstractMetaClassList interfaces = iface->interfaces(); - foreach (AbstractMetaClass* iface, interfaces) + const AbstractMetaClassList &interfaces = iface->interfaces(); + for (AbstractMetaClass* iface : interfaces) metaClass->addInterface(iface); } } @@ -1879,8 +1908,8 @@ void AbstractMetaBuilderPrivate::traverseEnums(ScopeModelItem scopeItem, AbstractMetaClass *metaClass, const QStringList &enumsDeclarations) { - EnumList enums = scopeItem->enums(); - foreach (const EnumModelItem &enumItem, enums) { + const EnumList &enums = scopeItem->enums(); + for (const EnumModelItem &enumItem : enums) { AbstractMetaEnum* metaEnum = traverseEnum(enumItem, metaClass, QSet<QString>::fromList(enumsDeclarations)); if (metaEnum) { metaClass->addEnum(metaEnum); @@ -1897,7 +1926,7 @@ AbstractMetaFunction* AbstractMetaBuilderPrivate::traverseFunction(const AddedFu AbstractMetaFunction* AbstractMetaBuilderPrivate::traverseFunction(const AddedFunction& addedFunc, AbstractMetaClass *metaClass) { - AbstractMetaFunction *metaFunction = q->createMetaFunction(); + AbstractMetaFunction *metaFunction = new AbstractMetaFunction; metaFunction->setConstant(addedFunc.isConstant()); metaFunction->setName(addedFunc.name()); metaFunction->setOriginalName(addedFunc.name()); @@ -1907,16 +1936,16 @@ AbstractMetaFunction* AbstractMetaBuilderPrivate::traverseFunction(const AddedFu metaFunction->setVisibility(visibility); metaFunction->setUserAdded(true); AbstractMetaAttributes::Attribute isStatic = addedFunc.isStatic() ? AbstractMetaFunction::Static : AbstractMetaFunction::None; - metaFunction->setAttributes(metaFunction->attributes() | AbstractMetaAttributes::Final | isStatic); + metaFunction->setAttributes(metaFunction->attributes() | AbstractMetaAttributes::FinalInTargetLang | isStatic); metaFunction->setType(translateType(addedFunc.version(), addedFunc.returnType())); - QList<AddedFunction::TypeInfo> args = addedFunc.arguments(); + QVector<AddedFunction::TypeInfo> args = addedFunc.arguments(); AbstractMetaArgumentList metaArguments; for (int i = 0; i < args.count(); ++i) { AddedFunction::TypeInfo& typeInfo = args[i]; - AbstractMetaArgument *metaArg = q->createMetaArgument(); + AbstractMetaArgument *metaArg = new AbstractMetaArgument; AbstractMetaType* type = translateType(addedFunc.version(), typeInfo); decideUsagePattern(type); metaArg->setType(type); @@ -1969,7 +1998,8 @@ AbstractMetaFunction* AbstractMetaBuilderPrivate::traverseFunction(const AddedFu } metaFunction->setOriginalAttributes(metaFunction->attributes()); - fixArgumentNames(metaFunction); + if (!metaArguments.isEmpty()) + fixArgumentNames(metaFunction, metaFunction->modifications(m_currentClass)); if (metaClass) { const AbstractMetaArgumentList fargs = metaFunction->arguments(); @@ -1978,7 +2008,7 @@ AbstractMetaFunction* AbstractMetaBuilderPrivate::traverseFunction(const AddedFu if (metaFunction->name() == metaClass->name()) { metaFunction->setFunctionType(AbstractMetaFunction::ConstructorFunction); if (fargs.size() == 1) { - const TypeEntry *te = fargs.first()->type()->typeEntry(); + const TypeEntry *te = fargs.constFirst()->type()->typeEntry(); if (te->isCustom()) metaFunction->setExplicit(true); if (te->name() == metaFunction->name()) @@ -1997,12 +2027,10 @@ AbstractMetaFunction* AbstractMetaBuilderPrivate::traverseFunction(const AddedFu return metaFunction; } -void AbstractMetaBuilderPrivate::fixArgumentNames(AbstractMetaFunction *func) +void AbstractMetaBuilderPrivate::fixArgumentNames(AbstractMetaFunction *func, const FunctionModificationList &mods) { - if (func->arguments().isEmpty()) - return; - foreach (const FunctionModification &mod, func->modifications(m_currentClass)) { - foreach (const ArgumentModification &argMod, mod.argument_mods) { + for (const FunctionModification &mod : mods) { + for (const ArgumentModification &argMod : mod.argument_mods) { if (!argMod.renamed_to.isEmpty()) { AbstractMetaArgument* arg = func->arguments().at(argMod.index - 1); arg->setOriginalName(arg->name()); @@ -2011,62 +2039,158 @@ void AbstractMetaBuilderPrivate::fixArgumentNames(AbstractMetaFunction *func) } } - int i = 1; - foreach (AbstractMetaArgument* arg, func->arguments()) { - if (arg->name().isEmpty()) - arg->setName(QLatin1String("arg__") + QString::number(i), false); - ++i; + AbstractMetaArgumentList arguments = func->arguments(); + for (int i = 0, size = arguments.size(); i < size; ++i) { + if (arguments.at(i)->name().isEmpty()) + arguments[i]->setName(QLatin1String("arg__") + QString::number(i + 1), false); } } static QString functionSignature(FunctionModelItem functionItem) { QStringList args; - foreach (const ArgumentModelItem &arg, functionItem->arguments()) + const ArgumentList &arguments = functionItem->arguments(); + for (const ArgumentModelItem &arg : arguments) args << arg->type().toString(); return functionItem->name() + QLatin1Char('(') + args.join(QLatin1Char(',')) + QLatin1Char(')'); } -static inline QString functionSignatureWithReturnType(FunctionModelItem functionItem) +static inline QString qualifiedFunctionSignatureWithType(const FunctionModelItem &functionItem, + const QString &className = QString()) +{ + QString result = functionItem->type().toString() + QLatin1Char(' '); + if (!className.isEmpty()) + result += className + colonColon(); + result += functionSignature(functionItem); + return result; +} + +static inline QString msgUnmatchedParameterType(const ArgumentModelItem &arg, int n) { - return functionSignature(functionItem) - + QStringLiteral(" -> ") + functionItem->type().toString(); + QString result; + QTextStream str(&result); + str << "unmatched type '" << arg->type().toString() << "' in parameter #" + << (n + 1); + if (!arg->name().isEmpty()) + str << " \"" << arg->name() << '"'; + return result; } -static inline QString qualifiedFunctionSignatureWithType(const QString &className, - FunctionModelItem functionItem) +static inline QString msgVoidParameterType(const ArgumentModelItem &arg, int n) { - return className + colonColon() + functionSignatureWithReturnType(functionItem); + QString result; + QTextStream str(&result); + str << "'void' encountered at parameter #" << (n + 1); + if (!arg->name().isEmpty()) + str << " \"" << arg->name() << '"'; + return result; +} + +static inline AbstractMetaFunction::FunctionType functionTypeFromCodeModel(CodeModel::FunctionType ft) +{ + AbstractMetaFunction::FunctionType result = AbstractMetaFunction::NormalFunction; + switch (ft) { + case CodeModel::Constructor: + result = AbstractMetaFunction::ConstructorFunction; + break; + case CodeModel::CopyConstructor: + result = AbstractMetaFunction::CopyConstructorFunction; + break; + case CodeModel::MoveConstructor: + result = AbstractMetaFunction::MoveConstructorFunction; + break; + case CodeModel::Destructor: + result = AbstractMetaFunction::DestructorFunction; + break; + case CodeModel::Normal: + break; + case CodeModel::Signal: + result = AbstractMetaFunction::SignalFunction; + break; + case CodeModel::Slot: + result = AbstractMetaFunction::SlotFunction; + break; + } + return result; +} + +static inline QString msgCannotSetArrayUsage(const QString &function, int i, const QString &reason) +{ + return function + QLatin1String(": Cannot use parameter ") + QString::number(i + 1) + + QLatin1String(" as an array: ") + reason; +} + +bool AbstractMetaBuilderPrivate::setArrayArgumentType(AbstractMetaFunction *func, + const FunctionModelItem &functionItem, + int i) +{ + if (i < 0 || i >= func->arguments().size()) { + qCWarning(lcShiboken).noquote() + << msgCannotSetArrayUsage(func->minimalSignature(), i, + QLatin1String("Index out of range.")); + return false; + } + AbstractMetaType *metaType = func->arguments().at(i)->type(); + if (metaType->indirections() == 0) { + qCWarning(lcShiboken).noquote() + << msgCannotSetArrayUsage(func->minimalSignature(), i, + QLatin1String("Type does not have indirections.")); + return false; + } + TypeInfo elementType = functionItem->arguments().at(i)->type(); + elementType.setIndirections(elementType.indirections() - 1); + bool ok; + AbstractMetaType *element = translateType(elementType, &ok); + if (element == nullptr || !ok) { + qCWarning(lcShiboken).noquote() + << msgCannotSetArrayUsage(func->minimalSignature(), i, + QLatin1String("Cannot translate element type ") + elementType.toString()); + return false; + } + metaType->setArrayElementType(element); + metaType->setTypeUsagePattern(AbstractMetaType::NativePointerAsArrayPattern); + return true; } AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(FunctionModelItem functionItem) { + if (!functionItem->templateParameters().isEmpty()) + return nullptr; QString functionName = functionItem->name(); QString className; - QString rejectedFunctionSignature; - if (m_currentClass) + if (m_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(); + if (functionName == QLatin1String("metaObject") && className != QLatin1String("QObject")) + return nullptr; + } + + // Store original signature with unresolved typedefs for message/log purposes + const QString originalQualifiedSignatureWithReturn = + qualifiedFunctionSignatureWithType(functionItem, className); - if (TypeDatabase::instance()->isFunctionRejected(className, functionName)) { - rejectedFunctionSignature = qualifiedFunctionSignatureWithType(className, functionItem); - m_rejectedFunctions.insert(rejectedFunctionSignature, AbstractMetaBuilder::GenerationDisabled); + QString rejectReason; + if (TypeDatabase::instance()->isFunctionRejected(className, functionName, &rejectReason)) { + m_rejectedFunctions.insert(originalQualifiedSignatureWithReturn + rejectReason, AbstractMetaBuilder::GenerationDisabled); return 0; } else if (TypeDatabase::instance()->isFunctionRejected(className, - functionSignature(functionItem))) { - rejectedFunctionSignature = qualifiedFunctionSignatureWithType(className, functionItem); - m_rejectedFunctions.insert(rejectedFunctionSignature, AbstractMetaBuilder::GenerationDisabled); + functionSignature(functionItem), &rejectReason)) { + m_rejectedFunctions.insert(originalQualifiedSignatureWithReturn + rejectReason, AbstractMetaBuilder::GenerationDisabled); return 0; } - Q_ASSERT(functionItem->functionType() == CodeModel::Normal - || functionItem->functionType() == CodeModel::Signal - || functionItem->functionType() == CodeModel::Slot); - if (functionItem->isFriend()) return 0; - AbstractMetaFunction *metaFunction = q->createMetaFunction(); + AbstractMetaFunction *metaFunction = new AbstractMetaFunction; + // Additional check for assignment/move assignment down below + metaFunction->setFunctionType(functionTypeFromCodeModel(functionItem->functionType())); metaFunction->setConstant(functionItem->isConstant()); if (ReportHandler::isDebug(ReportHandler::MediumDebug)) @@ -2078,18 +2202,22 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(FunctionModel if (functionItem->isAbstract()) *metaFunction += AbstractMetaAttributes::Abstract; - if (!metaFunction->isAbstract()) - *metaFunction += AbstractMetaAttributes::Native; - - if (!functionItem->isVirtual()) - *metaFunction += AbstractMetaAttributes::Final; + if (functionItem->isVirtual()) { + *metaFunction += AbstractMetaAttributes::VirtualCppMethod; + if (functionItem->isOverride()) + *metaFunction += AbstractMetaAttributes::OverriddenCppMethod; + if (functionItem->isFinal()) + *metaFunction += AbstractMetaAttributes::FinalCppMethod; + } else { + *metaFunction += AbstractMetaAttributes::FinalInTargetLang; + } if (functionItem->isInvokable()) *metaFunction += AbstractMetaAttributes::Invokable; if (functionItem->isStatic()) { *metaFunction += AbstractMetaAttributes::Static; - *metaFunction += AbstractMetaAttributes::Final; + *metaFunction += AbstractMetaAttributes::FinalInTargetLang; } // Access rights @@ -2100,43 +2228,39 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(FunctionModel else *metaFunction += AbstractMetaAttributes::Protected; - - QString strippedClassName = className; - int cc_pos = strippedClassName.lastIndexOf(colonColon()); - if (cc_pos > 0) - strippedClassName = strippedClassName.mid(cc_pos + 2); - - TypeInfo functionType = functionItem->type(); - if (functionName.startsWith(QLatin1Char('~'))) { - metaFunction->setFunctionType(AbstractMetaFunction::DestructorFunction); - metaFunction->setInvalid(true); - } else if (stripTemplateArgs(functionName) == strippedClassName) { - metaFunction->setFunctionType(AbstractMetaFunction::ConstructorFunction); - // Check for Copy/Move down below + switch (metaFunction->functionType()) { + case AbstractMetaFunction::DestructorFunction: + break; + case AbstractMetaFunction::ConstructorFunction: metaFunction->setExplicit(functionItem->isExplicit()); metaFunction->setName(m_currentClass->name()); - } else { + break; + default: { + TypeInfo returnType = functionItem->type(); + + if (TypeDatabase::instance()->isReturnTypeRejected(className, returnType.toString(), &rejectReason)) { + m_rejectedFunctions.insert(originalQualifiedSignatureWithReturn + rejectReason, AbstractMetaBuilder::GenerationDisabled); + delete metaFunction; + return nullptr; + } + bool ok; - AbstractMetaType* type = translateType(functionType, &ok); + AbstractMetaType *type = translateType(returnType, &ok); if (!ok) { Q_ASSERT(type == 0); qCWarning(lcShiboken).noquote().nospace() - << QStringLiteral("skipping function '%1::%2', unmatched return type '%3'") - .arg(className, functionItem->name(), + << QStringLiteral("skipping function '%1', unmatched return type '%2'") + .arg(originalQualifiedSignatureWithReturn, functionItem->type().toString()); - rejectedFunctionSignature = qualifiedFunctionSignatureWithType(className, functionItem); - m_rejectedFunctions.insert(rejectedFunctionSignature, AbstractMetaBuilder::UnmatchedReturnType); - metaFunction->setInvalid(true); - return metaFunction; + m_rejectedFunctions.insert(originalQualifiedSignatureWithReturn, AbstractMetaBuilder::UnmatchedReturnType); + delete metaFunction; + return nullptr; } metaFunction->setType(type); - - if (functionItem->functionType() == CodeModel::Signal) - metaFunction->setFunctionType(AbstractMetaFunction::SignalFunction); - else if (functionItem->functionType() == CodeModel::Slot) - metaFunction->setFunctionType(AbstractMetaFunction::SlotFunction); + } + break; } ArgumentList arguments = functionItem->arguments(); @@ -2144,7 +2268,7 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(FunctionModel if (arguments.size() == 1) { ArgumentModelItem arg = arguments.at(0); TypeInfo type = arg->type(); - if (type.qualifiedName().first() == QLatin1String("void") && type.indirections() == 0) + if (type.qualifiedName().constFirst() == QLatin1String("void") && type.indirections() == 0) arguments.pop_front(); } @@ -2153,32 +2277,40 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(FunctionModel for (int i = 0; i < arguments.size(); ++i) { ArgumentModelItem arg = arguments.at(i); + if (TypeDatabase::instance()->isArgumentTypeRejected(className, arg->type().toString(), &rejectReason)) { + m_rejectedFunctions.insert(originalQualifiedSignatureWithReturn + rejectReason, AbstractMetaBuilder::GenerationDisabled); + delete metaFunction; + return nullptr; + } + bool ok; AbstractMetaType* metaType = translateType(arg->type(), &ok); if (!ok) { Q_ASSERT(metaType == 0); + const QString reason = msgUnmatchedParameterType(arg, i); qCWarning(lcShiboken).noquote().nospace() - << QStringLiteral("skipping function '%1::%2', unmatched parameter type '%3'") - .arg(className, functionItem->name(), arg->type().toString()); - rejectedFunctionSignature = qualifiedFunctionSignatureWithType(className, functionItem); + << QStringLiteral("skipping function '%1', %2") + .arg(originalQualifiedSignatureWithReturn, reason); + const QString rejectedFunctionSignature = originalQualifiedSignatureWithReturn + + QLatin1String(": ") + reason; m_rejectedFunctions.insert(rejectedFunctionSignature, AbstractMetaBuilder::UnmatchedArgumentType); - metaFunction->setInvalid(true); - return metaFunction; + delete metaFunction; + return nullptr; } if (metaType == Q_NULLPTR) { + const QString reason = msgVoidParameterType(arg, i); qCWarning(lcShiboken).noquote().nospace() - << QString::fromLatin1("skipping function '%1::%2', 'void' encountered at parameter " - "position %3, but it can only be the the first and only " - "parameter") - .arg(className, functionItem->name()).arg(i); - rejectedFunctionSignature = qualifiedFunctionSignatureWithType(className, functionItem); + << QString::fromLatin1("skipping function '%1': %2") + .arg(originalQualifiedSignatureWithReturn, reason); + const QString rejectedFunctionSignature = originalQualifiedSignatureWithReturn + + QLatin1String(": ") + reason; m_rejectedFunctions.insert(rejectedFunctionSignature, AbstractMetaBuilder::UnmatchedArgumentType); - metaFunction->setInvalid(true); - return metaFunction; + delete metaFunction; + return nullptr; } - AbstractMetaArgument *metaArgument = q->createMetaArgument(); + AbstractMetaArgument *metaArgument = new AbstractMetaArgument; metaArgument->setType(metaType); metaArgument->setName(arg->name()); @@ -2200,9 +2332,9 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(FunctionModel } else { FunctionModificationList mods = TypeDatabase::instance()->functionModifications(metaFunction->minimalSignature()); if (!mods.isEmpty()) { - QList<ArgumentModification> argMods = mods.first().argument_mods; + QVector<ArgumentModification> argMods = mods.constFirst().argument_mods; if (!argMods.isEmpty()) - replacedExpression = argMods.first().replacedDefaultExpression; + replacedExpression = argMods.constFirst().replacedDefaultExpression; } } @@ -2238,26 +2370,22 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(FunctionModel } - fixArgumentNames(metaFunction); + if (!metaArguments.isEmpty()) { + const FunctionModificationList &mods = metaFunction->modifications(m_currentClass); + fixArgumentNames(metaFunction, mods); + for (const FunctionModification &mod : mods) { + for (const ArgumentModification &argMod : mod.argument_mods) { + if (argMod.array) + setArrayArgumentType(metaFunction, functionItem, argMod.index - 1); + } + } + } // Determine class special functions if (m_currentClass && metaFunction->arguments().size() == 1) { - const AbstractMetaType *argType = metaFunction->arguments().first()->type(); + const AbstractMetaType *argType = metaFunction->arguments().constFirst()->type(); if (argType->typeEntry() == m_currentClass->typeEntry() && argType->indirections() == 0) { - if (metaFunction->isConstructor()) { - switch (argType->referenceType()) { - case NoReference: - metaFunction->setFunctionType(AbstractMetaFunction::CopyConstructorFunction); - break; - case LValueReference: - if (argType->isConstant()) - metaFunction->setFunctionType(AbstractMetaFunction::CopyConstructorFunction); - break; - case RValueReference: - metaFunction->setFunctionType(AbstractMetaFunction::MoveConstructorFunction); - break; - } - } else if (metaFunction->name() == QLatin1String("operator=")) { + if (metaFunction->name() == QLatin1String("operator=")) { switch (argType->referenceType()) { case NoReference: metaFunction->setFunctionType(AbstractMetaFunction::AssignmentOperatorFunction); @@ -2320,20 +2448,20 @@ AbstractMetaType *AbstractMetaBuilderPrivate::translateType(double vr, msg += QLatin1String("Remember to inform the full qualified name for the type you want to use.\nCandidates are:\n"); candidates.sort(); - foreach (const QString& candidate, candidates) { + for (const QString& candidate : qAsConst(candidates)) { msg += QLatin1String(" ") + candidate + QLatin1Char('\n'); } qFatal(qPrintable(msg), NULL); } - AbstractMetaType *metaType = q->createMetaType(); + AbstractMetaType *metaType = new AbstractMetaType; metaType->setTypeEntry(type); metaType->setIndirections(typeInfo.indirections); if (typeInfo.isReference) metaType->setReferenceType(LValueReference); metaType->setConstant(typeInfo.isConstant); if (isTemplate) { - foreach (const QString& templateArg, templateArgs) { + for (const QString& templateArg : qAsConst(templateArgs)) { AbstractMetaType* metaArgType = translateType(vr, AddedFunction::TypeInfo::fromSignature(templateArg)); metaType->addInstantiation(metaArgType); } @@ -2403,45 +2531,57 @@ AbstractMetaType *AbstractMetaBuilderPrivate::translateType(const TypeInfo &_typ return 0; } - // 2. Handle pointers specified as arrays with unspecified size - bool arrayOfUnspecifiedSize = false; - if (typeInfo.arrays.size() > 0) { - arrayOfUnspecifiedSize = true; - for (int i = 0; i < typeInfo.arrays.size(); ++i) - arrayOfUnspecifiedSize = arrayOfUnspecifiedSize && typeInfo.arrays.at(i).isEmpty(); - - if (!arrayOfUnspecifiedSize) { - TypeInfo newInfo; - //newInfo.setArguments(typei.arguments()); - newInfo.setIndirections(typei.indirections()); - newInfo.setConstant(typei.isConstant()); - newInfo.setFunctionPointer(typei.isFunctionPointer()); - newInfo.setQualifiedName(typei.qualifiedName()); - newInfo.setReferenceType(typei.referenceType()); - newInfo.setVolatile(typei.isVolatile()); - - AbstractMetaType* elementType = translateType(newInfo, ok); - if (!(*ok)) - return 0; + // 2. Handle arrays. + // 2.1 Handle char arrays with unspecified size (aka "const char[]") as "const char*" with + // NativePointerPattern usage. + bool oneDimensionalArrayOfUnspecifiedSize = + typeInfo.arrays.size() == 1 + && typeInfo.arrays[0].isEmpty(); + + bool isConstCharStarCase = + oneDimensionalArrayOfUnspecifiedSize + && typeInfo.qualified_name.size() == 1 + && typeInfo.qualified_name[0] == QStringLiteral("char") + && typeInfo.indirections == 0 + && typeInfo.is_constant == 1 + && typeInfo.is_busted == 0 + && typeInfo.referenceType == NoReference + && typeInfo.template_instantiations.size() == 0; + + if (isConstCharStarCase) + typeInfo.indirections += typeInfo.arrays.size(); + + // 2.2 Handle regular arrays. + if (typeInfo.arrays.size() > 0 && !isConstCharStarCase) { + TypeInfo newInfo; + //newInfo.setArguments(typei.arguments()); + newInfo.setIndirections(typei.indirections()); + newInfo.setConstant(typei.isConstant()); + newInfo.setFunctionPointer(typei.isFunctionPointer()); + newInfo.setQualifiedName(typei.qualifiedName()); + newInfo.setReferenceType(typei.referenceType()); + newInfo.setVolatile(typei.isVolatile()); + + AbstractMetaType* elementType = translateType(newInfo, ok); + if (!(*ok)) + return 0; - for (int i = typeInfo.arrays.size() - 1; i >= 0; --i) { - QString s = typeInfo.arrays.at(i); + for (int i = typeInfo.arrays.size() - 1; i >= 0; --i) { + AbstractMetaType *arrayType = new AbstractMetaType; + arrayType->setArrayElementType(elementType); + if (!typeInfo.arrays.at(i).isEmpty()) { bool _ok; - int elems = findOutValueFromString(s, _ok); - - AbstractMetaType *arrayType = q->createMetaType(); - arrayType->setArrayElementCount(elems); - arrayType->setArrayElementType(elementType); - arrayType->setTypeEntry(new ArrayTypeEntry(elementType->typeEntry() , elementType->typeEntry()->version())); - decideUsagePattern(arrayType); - - elementType = arrayType; + const int elems = findOutValueFromString(typeInfo.arrays.at(i), _ok); + if (_ok) + arrayType->setArrayElementCount(elems); } + arrayType->setTypeEntry(new ArrayTypeEntry(elementType->typeEntry() , elementType->typeEntry()->version())); + decideUsagePattern(arrayType); - return elementType; - } else { - typeInfo.indirections += typeInfo.arrays.size(); + elementType = arrayType; } + + return elementType; } QStringList qualifierList = typeInfo.qualified_name; @@ -2472,7 +2612,8 @@ AbstractMetaType *AbstractMetaBuilderPrivate::translateType(const TypeInfo &_typ // 5.1.1 - Try using the class parents' scopes if (!type && !m_currentClass->baseClassNames().isEmpty()) { - foreach (const AbstractMetaClass* cls, getBaseClasses(m_currentClass)) { + const AbstractMetaClassList &baseClasses = getBaseClasses(m_currentClass); + for (const AbstractMetaClass *cls : baseClasses) { type = findTypeEntryUsingContext(cls, qualifiedName); if (type) break; @@ -2495,8 +2636,8 @@ AbstractMetaType *AbstractMetaBuilderPrivate::translateType(const TypeInfo &_typ // 8. No? Check if the current class is a template and this type is one // of the parameters. if (!type && m_currentClass) { - QList<TypeEntry *> template_args = m_currentClass->templateArguments(); - foreach (TypeEntry *te, template_args) { + const QVector<TypeEntry *> &template_args = m_currentClass->templateArguments(); + for (TypeEntry *te : template_args) { if (te->name() == qualifiedName) type = te; } @@ -2537,14 +2678,14 @@ AbstractMetaType *AbstractMetaBuilderPrivate::translateType(const TypeInfo &_typ // These are only implicit and should not appear in code... Q_ASSERT(!type->isInterface()); - AbstractMetaType *metaType = q->createMetaType(); + AbstractMetaType *metaType = new AbstractMetaType; metaType->setTypeEntry(type); metaType->setIndirections(typeInfo.indirections); metaType->setReferenceType(typeInfo.referenceType); metaType->setConstant(typeInfo.is_constant); metaType->setOriginalTypeDescription(_typei.toString()); - foreach (const TypeParser::Info &ta, typeInfo.template_instantiations) { + for (const TypeParser::Info &ta : qAsConst(typeInfo.template_instantiations)) { TypeInfo info; info.setConstant(ta.is_constant); info.setReferenceType(ta.referenceType); @@ -2585,8 +2726,9 @@ int AbstractMetaBuilderPrivate::findOutValueFromString(const QString &stringValu // This is a very lame way to handle expression evaluation, // but it is not critical and will do for the time being. - static QRegExp variableNameRegExp(QLatin1String("^[a-zA-Z_][a-zA-Z0-9_]*$")); - if (!variableNameRegExp.exactMatch(stringValue)) { + static const QRegularExpression variableNameRegExp(QStringLiteral("^[a-zA-Z_][a-zA-Z0-9_]*$")); + Q_ASSERT(variableNameRegExp.isValid()); + if (!variableNameRegExp.match(stringValue).hasMatch()) { ok = true; return 0; } @@ -2597,12 +2739,10 @@ int AbstractMetaBuilderPrivate::findOutValueFromString(const QString &stringValu return enumValue->value(); } - foreach (AbstractMetaEnum* metaEnum, m_globalEnums) { - foreach (AbstractMetaEnumValue* ev, metaEnum->values()) { - if (ev->name() == stringValue) { - ok = true; - return ev->value(); - } + for (AbstractMetaEnum *metaEnum : qAsConst(m_globalEnums)) { + if (const AbstractMetaEnumValue *ev = metaEnum->findEnumValue(stringValue)) { + ok = true; + return ev->value(); } } @@ -2647,23 +2787,28 @@ QString AbstractMetaBuilderPrivate::fixDefaultValue(ArgumentModelItem item, if (!isNumber && expr.indexOf(colonColon()) < 0) { // Add the enum/flag scope to default value, making it usable // from other contexts beside its owner class hierarchy - QRegExp typeRegEx(QLatin1String("[^<]*[<]([^:]*::).*")); - typeRegEx.indexIn(type->minimalSignature()); - expr = typeRegEx.cap(1) + expr; + static const QRegularExpression typeRegEx(QStringLiteral("[^<]*[<]([^:]*::).*")); + Q_ASSERT(typeRegEx.isValid()); + const QRegularExpressionMatch match = typeRegEx.match(type->minimalSignature()); + if (match.hasMatch()) + expr.prepend(match.captured(1)); } } else if (type->isContainer() && expr.contains(QLatin1Char('<'))) { - QRegExp typeRegEx(QLatin1String("[^<]*<(.*)>")); - typeRegEx.indexIn(type->minimalSignature()); - QRegExp defaultRegEx(QLatin1String("([^<]*<).*(>[^>]*)")); - defaultRegEx.indexIn(expr); - expr = defaultRegEx.cap(1) + typeRegEx.cap(1) + defaultRegEx.cap(2); + static const QRegularExpression typeRegEx(QStringLiteral("[^<]*<(.*)>")); + Q_ASSERT(typeRegEx.isValid()); + const QRegularExpressionMatch typeMatch = typeRegEx.match(type->minimalSignature()); + static const QRegularExpression defaultRegEx(QLatin1String("([^<]*<).*(>[^>]*)")); + Q_ASSERT(defaultRegEx.isValid()); + const QRegularExpressionMatch defaultMatch = defaultRegEx.match(expr); + if (typeMatch.hasMatch() && defaultMatch.hasMatch()) + expr = defaultMatch.captured(1) + typeMatch.captured(1) + defaultMatch.captured(2); } else { // Here the default value is supposed to be a constructor, // a class field, or a constructor receiving a class field - QRegExp defaultRegEx(QLatin1String("([^\\(]*\\(|)([^\\)]*)(\\)|)")); - defaultRegEx.indexIn(expr); - - QString defaultValueCtorName = defaultRegEx.cap(1); + static const QRegularExpression defaultRegEx(QStringLiteral("([^\\(]*\\(|)([^\\)]*)(\\)|)")); + Q_ASSERT(defaultRegEx.isValid()); + const QRegularExpressionMatch defaultMatch = defaultRegEx.match(expr); + QString defaultValueCtorName = defaultMatch.hasMatch() ? defaultMatch.captured(1) : QString(); if (defaultValueCtorName.endsWith(QLatin1Char('('))) defaultValueCtorName.chop(1); @@ -2671,20 +2816,22 @@ QString AbstractMetaBuilderPrivate::fixDefaultValue(ArgumentModelItem item, // resolved argument type as a reference. // The following regular expression extracts any // use of namespaces/scopes from the type string. - QRegExp typeRegEx(QLatin1String("^(?:const[\\s]+|)([\\w:]*::|)([A-Za-z_]\\w*)\\s*[&\\*]?$")); - typeRegEx.indexIn(type->minimalSignature()); + static const QRegularExpression typeRegEx(QLatin1String("^(?:const[\\s]+|)([\\w:]*::|)([A-Za-z_]\\w*)\\s*[&\\*]?$")); + Q_ASSERT(typeRegEx.isValid()); + const QRegularExpressionMatch typeMatch = typeRegEx.match(type->minimalSignature()); - QString typeNamespace = typeRegEx.cap(1); - QString typeCtorName = typeRegEx.cap(2); + QString typeNamespace = typeMatch.hasMatch() ? typeMatch.captured(1) : QString(); + QString typeCtorName = typeMatch.hasMatch() ? typeMatch.captured(2) : QString(); if (!typeNamespace.isEmpty() && defaultValueCtorName == typeCtorName) expr.prepend(typeNamespace); // Fix scope if the parameter is a field of the current class if (implementingClass) { - foreach (const AbstractMetaField* field, implementingClass->fields()) { - if (defaultRegEx.cap(2) == field->name()) { - expr = defaultRegEx.cap(1) + implementingClass->name() - + colonColon() + defaultRegEx.cap(2) + defaultRegEx.cap(3); + const AbstractMetaFieldList &fields = implementingClass->fields(); + for (const AbstractMetaField *field : fields) { + if (defaultMatch.hasMatch() && defaultMatch.captured(2) == field->name()) { + expr = defaultMatch.captured(1) + implementingClass->name() + + colonColon() + defaultMatch.captured(2) + defaultMatch.captured(3); break; } } @@ -2717,19 +2864,19 @@ bool AbstractMetaBuilderPrivate::isQObject(const FileModelItem &dom, const QStri classItem = ns->findClass(names.at(names.size() - 1)); } - bool isqobject = classItem && classItem->extendsClass(QLatin1String("QObject")); + if (classItem == nullptr) + return false; - if (classItem && !isqobject) { - QStringList baseClasses = classItem->baseClasses(); - for (int i = 0; i < baseClasses.count(); ++i) { + if (classItem->extendsClass(QLatin1String("QObject"))) + return true; - isqobject = isQObject(dom, baseClasses.at(i)); - if (isqobject) - break; - } + const QVector<_ClassModelItem::BaseClass> &baseClasses = classItem->baseClasses(); + for (const _ClassModelItem::BaseClass &baseClass : baseClasses) { + if (isQObject(dom, baseClass.name)) + return true; } - return isqobject; + return false; } @@ -2766,7 +2913,7 @@ AbstractMetaClass* AbstractMetaBuilderPrivate::findTemplateClass(const QString & QString qualifiedName = info->qualified_name.join(colonColon()); AbstractMetaClass* templ = 0; - foreach (AbstractMetaClass *c, m_templates) { + for (AbstractMetaClass *c : qAsConst(m_templates)) { if (c->typeEntry()->name() == qualifiedName) { templ = c; break; @@ -2789,7 +2936,8 @@ AbstractMetaClass* AbstractMetaBuilderPrivate::findTemplateClass(const QString & AbstractMetaClassList AbstractMetaBuilderPrivate::getBaseClasses(const AbstractMetaClass *metaClass) const { AbstractMetaClassList baseClasses; - foreach (const QString& parent, metaClass->baseClassNames()) { + const QStringList &baseClassNames = metaClass->baseClassNames(); + for (const QString& parent : baseClassNames) { AbstractMetaClass* cls = 0; if (parent.contains(QLatin1Char('<'))) cls = findTemplateClass(parent, metaClass); @@ -2806,14 +2954,15 @@ bool AbstractMetaBuilderPrivate::ancestorHasPrivateCopyConstructor(const Abstrac { if (metaClass->hasPrivateCopyConstructor()) return true; - foreach (const AbstractMetaClass* cls, getBaseClasses(metaClass)) { + const AbstractMetaClassList &baseClasses = getBaseClasses(metaClass); + for (const AbstractMetaClass *cls : baseClasses) { if (ancestorHasPrivateCopyConstructor(cls)) return true; } return false; } -AbstractMetaType* AbstractMetaBuilderPrivate::inheritTemplateType(const QList<AbstractMetaType *> &templateTypes, +AbstractMetaType* AbstractMetaBuilderPrivate::inheritTemplateType(const QVector<AbstractMetaType *> &templateTypes, const AbstractMetaType *metaType, bool *ok) { @@ -2865,8 +3014,8 @@ bool AbstractMetaBuilderPrivate::inheritTemplate(AbstractMetaClass *subclass, const AbstractMetaClass *templateClass, const TypeParser::Info &info) { - QList<TypeParser::Info> targs = info.template_instantiations; - QList<AbstractMetaType*> templateTypes; + QVector<TypeParser::Info> targs = info.template_instantiations; + QVector<AbstractMetaType *> templateTypes; if (subclass->isTypeDef()) { subclass->setHasCloneOperator(templateClass->hasCloneOperator()); @@ -2878,7 +3027,7 @@ bool AbstractMetaBuilderPrivate::inheritTemplate(AbstractMetaClass *subclass, subclass->setHasVirtualDestructor(templateClass->hasVirtualDestructor()); } - foreach (const TypeParser::Info &i, targs) { + for (const TypeParser::Info &i : qAsConst(targs)) { QString typeName = i.qualified_name.join(colonColon()); QStringList possibleNames; possibleNames << subclass->qualifiedCppName() + colonColon() + typeName; @@ -2890,16 +3039,14 @@ bool AbstractMetaBuilderPrivate::inheritTemplate(AbstractMetaClass *subclass, TypeDatabase* typeDb = TypeDatabase::instance(); TypeEntry* t = 0; QString templateParamName; - foreach (const QString &possibleName, possibleNames) { + for (const QString &possibleName : qAsConst(possibleNames)) { t = typeDb->findType(possibleName); - if (t) { - QString templateParamName = possibleName; + if (t) break; - } } if (t) { - AbstractMetaType *temporaryType = q->createMetaType(); + AbstractMetaType *temporaryType = new AbstractMetaType; temporaryType->setTypeEntry(t); temporaryType->setConstant(i.is_constant); temporaryType->setReferenceType(i.referenceType); @@ -2914,7 +3061,8 @@ bool AbstractMetaBuilderPrivate::inheritTemplate(AbstractMetaClass *subclass, } AbstractMetaFunctionList funcs = subclass->functions(); - foreach (const AbstractMetaFunction* function, templateClass->functions()) { + const AbstractMetaFunctionList &templateClassFunctions = templateClass->functions(); + for (const AbstractMetaFunction *function : templateClassFunctions) { if (function->isModifiedRemoved(TypeSystem::All)) continue; @@ -2929,7 +3077,8 @@ bool AbstractMetaBuilderPrivate::inheritTemplate(AbstractMetaClass *subclass, continue; } - foreach (AbstractMetaArgument* argument, function->arguments()) { + const AbstractMetaArgumentList &arguments = function->arguments(); + for (AbstractMetaArgument *argument : arguments) { AbstractMetaType* atype = argument->type(); AbstractMetaArgument *arg = argument->copy(); @@ -2980,7 +3129,7 @@ bool AbstractMetaBuilderPrivate::inheritTemplate(AbstractMetaClass *subclass, FunctionModificationList mods = function->modifications(templateClass); for (int i = 0; i < mods.size(); ++i) { FunctionModification mod = mods.at(i); - mod.signature = f->minimalSignature(); + mod.setSignature(f->minimalSignature()); // If we ever need it... Below is the code to do // substitution of the template instantation type inside @@ -3041,8 +3190,6 @@ void AbstractMetaBuilderPrivate::parseQ_Property(AbstractMetaClass *metaClass, continue; } - QString typeName = scope + l.at(0); - QPropertySpec* spec = new QPropertySpec(type->typeEntry()); spec->setName(l.at(1)); spec->setIndex(i); @@ -3068,7 +3215,7 @@ static AbstractMetaFunction* findCopyCtor(AbstractMetaClass* cls) AbstractMetaFunctionList functions = cls->queryFunctions(AbstractMetaClass::Invisible); functions << cls->queryFunctions(AbstractMetaClass::Visible); - foreach (AbstractMetaFunction* f, functions) { + for (AbstractMetaFunction *f : qAsConst(functions)) { const AbstractMetaFunction::FunctionType t = f->functionType(); if (t == AbstractMetaFunction::CopyConstructorFunction || t == AbstractMetaFunction::AssignmentOperatorFunction) return f; @@ -3088,11 +3235,11 @@ void AbstractMetaBuilderPrivate::setupClonable(AbstractMetaClass *cls) QQueue<AbstractMetaClass*> baseClasses; if (cls->baseClass()) baseClasses.enqueue(cls->baseClass()); - baseClasses << cls->interfaces(); + baseClasses << cls->interfaces().toList(); while (!baseClasses.isEmpty()) { AbstractMetaClass* currentClass = baseClasses.dequeue(); - baseClasses << currentClass->interfaces(); + baseClasses << currentClass->interfaces().toList(); if (currentClass->baseClass()) baseClasses.enqueue(currentClass->baseClass()); @@ -3108,8 +3255,8 @@ void AbstractMetaBuilderPrivate::setupClonable(AbstractMetaClass *cls) void AbstractMetaBuilderPrivate::setupExternalConversion(AbstractMetaClass *cls) { - AbstractMetaFunctionList convOps = cls->operatorOverloads(AbstractMetaClass::ConversionOp); - foreach (AbstractMetaFunction* func, convOps) { + const AbstractMetaFunctionList &convOps = cls->operatorOverloads(AbstractMetaClass::ConversionOp); + for (AbstractMetaFunction *func : convOps) { if (func->isModifiedRemoved()) continue; AbstractMetaClass *metaClass = AbstractMetaClass::findClass(m_metaClasses, func->type()->typeEntry()); @@ -3117,7 +3264,8 @@ void AbstractMetaBuilderPrivate::setupExternalConversion(AbstractMetaClass *cls) continue; metaClass->addExternalConversionOperator(func); } - foreach (AbstractMetaClass* innerClass, cls->innerClasses()) + const AbstractMetaClassList &innerClasses = cls->innerClasses(); + for (AbstractMetaClass *innerClass : innerClasses) setupExternalConversion(innerClass); } @@ -3197,7 +3345,7 @@ AbstractMetaClassList AbstractMetaBuilderPrivate::classesTopologicalSorted(const const AbstractMetaClassList& classList = cppClass ? cppClass->innerClasses() : m_metaClasses; int i = 0; - foreach (AbstractMetaClass* clazz, classList) { + for (AbstractMetaClass *clazz : classList) { if (map.contains(clazz->qualifiedCppName())) continue; map[clazz->qualifiedCppName()] = i; @@ -3207,7 +3355,7 @@ AbstractMetaClassList AbstractMetaBuilderPrivate::classesTopologicalSorted(const Graph graph(map.count()); - foreach (const Dependency &dep, additionalDependencies) { + for (const Dependency &dep : additionalDependencies) { const int parentIndex = map.value(dep.parent, -1); const int childIndex = map.value(dep.child, -1); if (parentIndex >= 0 && childIndex >= 0) { @@ -3220,14 +3368,16 @@ AbstractMetaClassList AbstractMetaBuilderPrivate::classesTopologicalSorted(const } // TODO choose a better name to these regexs - QRegExp regex1(QLatin1String("\\(.*\\)")); - QRegExp regex2(QLatin1String("::.*")); - foreach (AbstractMetaClass* clazz, classList) { + static const QRegularExpression regex1(QStringLiteral("\\(.*\\)")); + Q_ASSERT(regex1.isValid()); + static const QRegularExpression regex2(QStringLiteral("::.*")); + Q_ASSERT(regex2.isValid()); + for (AbstractMetaClass *clazz : classList) { if (clazz->enclosingClass() && map.contains(clazz->enclosingClass()->qualifiedCppName())) graph.addEdge(map[clazz->enclosingClass()->qualifiedCppName()], map[clazz->qualifiedCppName()]); - AbstractMetaClassList bases = getBaseClasses(clazz); - foreach(AbstractMetaClass* baseClass, bases) { + const AbstractMetaClassList &bases = getBaseClasses(clazz); + for (AbstractMetaClass *baseClass : bases) { // Fix polymorphic expression if (clazz->baseClass() == baseClass) clazz->setBaseClass(baseClass); @@ -3236,8 +3386,10 @@ AbstractMetaClassList AbstractMetaBuilderPrivate::classesTopologicalSorted(const graph.addEdge(map[baseClass->qualifiedCppName()], map[clazz->qualifiedCppName()]); } - foreach (AbstractMetaFunction* func, clazz->functions()) { - foreach (AbstractMetaArgument* arg, func->arguments()) { + const AbstractMetaFunctionList &functions = clazz->functions(); + for (AbstractMetaFunction *func : functions) { + const AbstractMetaArgumentList &arguments = func->arguments(); + for (AbstractMetaArgument *arg : arguments) { // check methods with default args QString defaultExpression = arg->originalDefaultValueExpression(); if (!defaultExpression.isEmpty()) { @@ -3251,7 +3403,7 @@ AbstractMetaClassList AbstractMetaBuilderPrivate::classesTopologicalSorted(const QString exprClassName = clazz->qualifiedCppName() + colonColon() + defaultExpression; if (!map.contains(exprClassName)) { bool found = false; - foreach(AbstractMetaClass* baseClass, bases) { + for (AbstractMetaClass *baseClass : bases) { exprClassName = baseClass->qualifiedCppName() + colonColon() + defaultExpression; if (map.contains(exprClassName)) { found = true; @@ -3287,7 +3439,7 @@ AbstractMetaClassList AbstractMetaBuilderPrivate::classesTopologicalSorted(const << "Cyclic dependency found! Graph can be found at " << QDir::toNativeSeparators(tempFile.fileName()); } else { - foreach (int i, unmappedResult) { + for (int i : qAsConst(unmappedResult)) { Q_ASSERT(reverseMap.contains(i)); if (!reverseMap[i]->isInterface()) result << reverseMap[i]; @@ -3308,7 +3460,7 @@ AbstractMetaArgumentList AbstractMetaBuilderPrivate::reverseList(const AbstractM AbstractMetaArgumentList ret; int index = list.size(); - foreach (AbstractMetaArgument* arg, list) { + for (AbstractMetaArgument *arg : list) { arg->setArgumentIndex(index); ret.prepend(arg); index--; diff --git a/sources/shiboken2/ApiExtractor/abstractmetabuilder.h b/sources/shiboken2/ApiExtractor/abstractmetabuilder.h index b4a36a1b6..33631d00f 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetabuilder.h +++ b/sources/shiboken2/ApiExtractor/abstractmetabuilder.h @@ -71,7 +71,7 @@ public: AbstractMetaClassList classesTopologicalSorted(const AbstractMetaClass *cppClass = Q_NULLPTR, const Dependencies &additionalDependencies = Dependencies()) const; - bool build(QIODevice* input); + bool build(const QByteArrayList &arguments, unsigned clangFlags = 0); void setLogDirectory(const QString& logDir); /** @@ -85,15 +85,6 @@ public: void formatDebug(QDebug &d) const; #endif -protected: - virtual AbstractMetaClass *createMetaClass(); - virtual AbstractMetaEnum *createMetaEnum(); - virtual AbstractMetaEnumValue *createMetaEnumValue(); - virtual AbstractMetaField *createMetaField(); - virtual AbstractMetaFunction *createMetaFunction(); - virtual AbstractMetaArgument *createMetaArgument(); - virtual AbstractMetaType *createMetaType(); - private: friend class AbstractMetaBuilderPrivate; AbstractMetaBuilderPrivate *d; diff --git a/sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h b/sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h index f9eb4bb46..9e15541f6 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h +++ b/sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h @@ -46,7 +46,7 @@ public: AbstractMetaBuilderPrivate(); ~AbstractMetaBuilderPrivate(); - static FileModelItem buildDom(QIODevice *input); + static FileModelItem buildDom(const QByteArrayList &arguments, unsigned clangFlags); void traverseDom(const FileModelItem &dom); void dumpLog() const; @@ -56,7 +56,7 @@ public: void pushScope(ScopeModelItem item) { m_scopes << item; } - ScopeModelItem currentScope() const { return m_scopes.last(); } + ScopeModelItem currentScope() const { return m_scopes.constLast(); } AbstractMetaClass *argumentToClass(ArgumentModelItem); @@ -81,9 +81,11 @@ public: const QSet<QString> &enumsDeclarations); void traverseEnums(ScopeModelItem item, AbstractMetaClass *parent, const QStringList &enumsDeclarations); - AbstractMetaFunctionList classFunctionList(const ScopeModelItem &scopeItem); + AbstractMetaFunctionList classFunctionList(const ScopeModelItem &scopeItem, + bool *constructorRejected); AbstractMetaFunctionList templateClassFunctionList(const ScopeModelItem &scopeItem, - AbstractMetaClass *metaClass); + AbstractMetaClass *metaClass, + bool *constructorRejected); void traverseFunctions(ScopeModelItem item, AbstractMetaClass *parent); void applyFunctionModifications(AbstractMetaFunction* func); void traverseFields(ScopeModelItem item, AbstractMetaClass *parent); @@ -140,7 +142,7 @@ public: bool inheritTemplate(AbstractMetaClass *subclass, const AbstractMetaClass *templateClass, const TypeParser::Info &info); - AbstractMetaType *inheritTemplateType(const QList<AbstractMetaType *> &templateTypes, + AbstractMetaType *inheritTemplateType(const QVector<AbstractMetaType *> &templateTypes, const AbstractMetaType *metaType, bool *ok = Q_NULLPTR); @@ -153,7 +155,10 @@ public: void sortLists(); AbstractMetaArgumentList reverseList(const AbstractMetaArgumentList &list); void setInclude(TypeEntry *te, const QString &fileName) const; - void fixArgumentNames(AbstractMetaFunction *func); + void fixArgumentNames(AbstractMetaFunction *func, const FunctionModificationList &mods); + bool setArrayArgumentType(AbstractMetaFunction *func, + const FunctionModelItem &functionItem, int i); + void fillAddedFunctions(AbstractMetaClass *metaClass); AbstractMetaBuilder *q; diff --git a/sources/shiboken2/ApiExtractor/abstractmetalang.cpp b/sources/shiboken2/ApiExtractor/abstractmetalang.cpp index b861f1b2f..4e507cd38 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetalang.cpp +++ b/sources/shiboken2/ApiExtractor/abstractmetalang.cpp @@ -26,8 +26,6 @@ ** ****************************************************************************/ -#include <QStack> - #include "abstractmetalang.h" #include "reporthandler.h" #include "typedatabase.h" @@ -38,6 +36,9 @@ # include <QtCore/QMetaObject> #endif +#include <QtCore/QRegularExpression> +#include <QtCore/QStack> + #ifndef QT_NO_DEBUG_STREAM QDebug operator<<(QDebug d, const AbstractMetaAttributes *aa) { @@ -58,7 +59,14 @@ QDebug operator<<(QDebug d, const AbstractMetaAttributes *aa) * AbstractMetaVariable */ -AbstractMetaVariable::AbstractMetaVariable(const AbstractMetaVariable &other) +AbstractMetaVariable::AbstractMetaVariable() = default; + +AbstractMetaVariable::~AbstractMetaVariable() +{ + delete m_type; +} + +void AbstractMetaVariable::assignMetaVariable(const AbstractMetaVariable &other) { m_originalName = other.m_originalName; m_name = other.m_name; @@ -85,20 +93,28 @@ QDebug operator<<(QDebug d, const AbstractMetaVariable *av) #endif // !QT_NO_DEBUG_STREAM /******************************************************************************* + * AbstractMetaAttributes + */ + +AbstractMetaAttributes::AbstractMetaAttributes() = default; +AbstractMetaAttributes::~AbstractMetaAttributes() = default; + +void AbstractMetaAttributes::assignMetaAttributes(const AbstractMetaAttributes &other) +{ + m_attributes = other.m_attributes; + m_originalAttributes = other.m_originalAttributes; + m_doc = other.m_doc; +} + +/******************************************************************************* * AbstractMetaType */ -AbstractMetaType::AbstractMetaType() - :m_typeEntry(0), - m_arrayElementCount(0), - m_arrayElementType(0), - m_originalTemplateType(0), - m_pattern(InvalidPattern), +AbstractMetaType::AbstractMetaType() : m_constant(false), m_cppInstantiation(true), m_indirections(0), - m_reserved(0), - m_referenceType(NoReference) + m_reserved(0) { } @@ -113,11 +129,18 @@ QString AbstractMetaType::package() const return m_typeEntry->targetLangPackage(); } +static QString lastNameSegment(QString name) +{ + const int index = name.lastIndexOf(QStringLiteral("::")); + if (index >= 0) + name.remove(0, index + 2); + return name; +} + QString AbstractMetaType::name() const { if (m_name.isNull()) - // avoid constLast to stay Qt 5.5 compatible - m_name = m_typeEntry->targetLangName().split(QLatin1String("::")).last(); + m_name = lastNameSegment(m_typeEntry->targetLangName()); return m_name; } @@ -146,41 +169,30 @@ AbstractMetaType *AbstractMetaType::copy() const return cpy; } -QString AbstractMetaType::cppSignature() const +AbstractMetaTypeCList AbstractMetaType::nestedArrayTypes() const { - if (m_cachedCppSignature.isEmpty()) { - if (isConstant()) - m_cachedCppSignature += QLatin1String("const "); - - m_cachedCppSignature += typeEntry()->qualifiedCppName(); - - if (hasInstantiationInCpp()) { - AbstractMetaTypeList types = instantiations(); - m_cachedCppSignature += QLatin1Char('<'); - for (int i = 0; i < types.count(); ++i) { - if (i > 0) - m_cachedCppSignature += QLatin1String(", "); - m_cachedCppSignature += types[i]->cppSignature(); - } - m_cachedCppSignature += QLatin1String(" >"); - } - - if (indirections() || m_referenceType != NoReference) { - m_cachedCppSignature += QLatin1Char(' '); - if (indirections()) - m_cachedCppSignature += QString(indirections(), QLatin1Char('*')); - switch (referenceType()) { - case NoReference: - break; - case LValueReference: - m_cachedCppSignature += QLatin1Char('&'); - break; - case RValueReference: - m_cachedCppSignature += QLatin1String("&&"); - break; - } + AbstractMetaTypeCList result; + switch (m_pattern) { + case ArrayPattern: + for (const AbstractMetaType *t = this; t->typeUsagePattern() == ArrayPattern; ) { + const AbstractMetaType *elt = t->arrayElementType(); + result.append(elt); + t = elt; } + break; + case NativePointerAsArrayPattern: + result.append(m_arrayElementType); + break; + default: + break; } + return result; +} + +QString AbstractMetaType::cppSignature() const +{ + if (m_cachedCppSignature.isEmpty()) + m_cachedCppSignature = formatSignature(false); return m_cachedCppSignature; } @@ -200,30 +212,6 @@ AbstractMetaType::TypeUsagePattern AbstractMetaType::determineUsagePattern() con if (m_typeEntry->isVarargs()) return VarargsPattern; - if (m_typeEntry->isString() && indirections() == 0 - && (isConstant() == (m_referenceType == LValueReference) - || isConstant())) { - return StringPattern; - } - - if (m_typeEntry->isChar() - && indirections() == 0 - && isConstant() == (m_referenceType == LValueReference)) { - return CharPattern; - } - - if (m_typeEntry->isJObjectWrapper() - && indirections() == 0 - && isConstant() == (m_referenceType == LValueReference)) { - return JObjectWrapperPattern; - } - - if (m_typeEntry->isVariant() - && indirections() == 0 - && isConstant() == (m_referenceType == LValueReference)) { - return VariantPattern; - } - if (m_typeEntry->isEnum() && actualIndirections() == 0) return EnumPattern; @@ -247,11 +235,6 @@ AbstractMetaType::TypeUsagePattern AbstractMetaType::determineUsagePattern() con if (m_typeEntry->isArray()) return ArrayPattern; - if (m_typeEntry->isThread()) { - Q_ASSERT(indirections() == 1); - return ThreadPattern; - } - if (m_typeEntry->isValue()) return indirections() == 1 ? ValuePointerPattern : ValuePattern; @@ -279,7 +262,7 @@ void AbstractMetaType::decideUsagePattern() bool AbstractMetaType::hasTemplateChildren() const { QStack<AbstractMetaType *> children; - children << m_children.toVector(); + children << m_children; // Recursively iterate over the children / descendants of the type, to check if any of them // corresponds to a template argument type. @@ -287,7 +270,7 @@ bool AbstractMetaType::hasTemplateChildren() const AbstractMetaType *child = children.pop(); if (child->typeEntry()->isTemplateArgument()) return true; - children << child->m_children.toVector(); + children << child->m_children; } return false; @@ -300,10 +283,26 @@ QDebug operator<<(QDebug d, const AbstractMetaType *at) d.noquote(); d.nospace(); d << "AbstractMetaType("; - if (at) + if (at) { d << at->name(); - else + if (d.verbosity() > 2) { + d << ", typeEntry=" << at->typeEntry() << ", signature=\"" + << at->cppSignature() << "\", pattern=" + << at->typeUsagePattern(); + if (at->indirections()) + d << ", indirections=" << at->indirections(); + if (at->referenceType()) + d << ", reftype=" << at->referenceType(); + if (at->isConstant()) + d << ", [const]"; + if (at->isArray()) { + d << ", array of \"" << at->arrayElementType()->cppSignature() + << "\", arrayElementCount=" << at->arrayElementCount(); + } + } + } else { d << '0'; + } d << ')'; return d; } @@ -312,9 +311,22 @@ QDebug operator<<(QDebug d, const AbstractMetaType *at) /******************************************************************************* * AbstractMetaArgument */ + +AbstractMetaArgument::AbstractMetaArgument() = default; + +void AbstractMetaArgument::assignMetaArgument(const AbstractMetaArgument &other) +{ + assignMetaVariable(other); + m_expression = other.m_expression; + m_originalExpression = other.m_originalExpression; + m_argumentIndex = other.m_argumentIndex; +} + AbstractMetaArgument *AbstractMetaArgument::copy() const { - return new AbstractMetaArgument(*this); + AbstractMetaArgument *copy = new AbstractMetaArgument; + copy->assignMetaArgument(*this); + return copy; } #ifndef QT_NO_DEBUG_STREAM @@ -336,6 +348,17 @@ QDebug operator<<(QDebug d, const AbstractMetaArgument *aa) /******************************************************************************* * AbstractMetaFunction */ + +AbstractMetaFunction::AbstractMetaFunction() + : m_constant(false), + m_reverse(false), + m_userAdded(false), + m_explicit(false), + m_pointerOperator(false), + m_isCallOperator(false) +{ +} + AbstractMetaFunction::~AbstractMetaFunction() { qDeleteAll(m_arguments); @@ -347,8 +370,8 @@ AbstractMetaFunction::~AbstractMetaFunction() */ bool AbstractMetaFunction::isModifiedRemoved(int types) const { - FunctionModificationList mods = modifications(implementingClass()); - foreach (const FunctionModification &mod, mods) { + const FunctionModificationList &mods = modifications(implementingClass()); + for (const FunctionModification &mod : mods) { if (!mod.isRemoveModifier()) continue; @@ -359,64 +382,6 @@ bool AbstractMetaFunction::isModifiedRemoved(int types) const return false; } -bool AbstractMetaFunction::needsCallThrough() const -{ - if (ownerClass()->isInterface()) - return false; - if (referenceCounts(implementingClass()).size() > 0) - return true; - if (argumentsHaveNativeId() || !isStatic()) - return true; - - foreach (const AbstractMetaArgument *arg, arguments()) { - if (arg->type()->isArray() || arg->type()->isTargetLangEnum() || arg->type()->isTargetLangFlags()) - return true; - } - - if (type() && (type()->isArray() || type()->isTargetLangEnum() || type()->isTargetLangFlags())) - return true; - - for (int i = -1; i <= arguments().size(); ++i) { - TypeSystem::Ownership owner = this->ownership(implementingClass(), TypeSystem::TargetLangCode, i); - if (owner != TypeSystem::InvalidOwnership) - return true; - } - - return false; -} - -bool AbstractMetaFunction::needsSuppressUncheckedWarning() const -{ - for (int i = -1; i <= arguments().size(); ++i) { - QList<ReferenceCount> referenceCounts = this->referenceCounts(implementingClass(), i); - foreach (const ReferenceCount &referenceCount, referenceCounts) { - if (referenceCount.action != ReferenceCount::Set) - return true; - } - } - return false; -} - -QString AbstractMetaFunction::marshalledName() const -{ - QString returned = QLatin1String("__qt_") + name(); - AbstractMetaArgumentList arguments = this->arguments(); - foreach (const AbstractMetaArgument *arg, arguments) { - returned += QLatin1Char('_'); - if (arg->type()->isNativePointer()) { - returned += QLatin1String("nativepointer"); - } else if (arg->type()->isIntegerEnum() || arg->type()->isIntegerFlags()) { - returned += QLatin1String("int"); - } else { - QString a = arg->type()->name(); - a.replace(QLatin1String("[]"), QLatin1String("_3")); - a.replace(QLatin1Char('.'), QLatin1Char('_')); - returned += a; - } - } - return returned; -} - bool AbstractMetaFunction::operator<(const AbstractMetaFunction &other) const { return compareTo(&other) & NameLessThan; @@ -498,19 +463,18 @@ AbstractMetaFunction::CompareResult AbstractMetaFunction::compareTo(const Abstra AbstractMetaFunction *AbstractMetaFunction::copy() const { AbstractMetaFunction *cpy = new AbstractMetaFunction; + cpy->assignMetaAttributes(*this); cpy->setName(name()); cpy->setOriginalName(originalName()); cpy->setOwnerClass(ownerClass()); cpy->setImplementingClass(implementingClass()); cpy->setFunctionType(functionType()); - cpy->setAttributes(attributes()); cpy->setDeclaringClass(declaringClass()); if (type()) cpy->setType(type()->copy()); cpy->setConstant(isConstant()); - cpy->setOriginalAttributes(originalAttributes()); - foreach (AbstractMetaArgument *arg, arguments()) + for (AbstractMetaArgument *arg : m_arguments) cpy->addArgument(arg->copy()); Q_ASSERT((!type() && !cpy->type()) @@ -525,7 +489,7 @@ bool AbstractMetaFunction::usesRValueReferences() const return true; if (m_type && m_type->referenceType() == RValueReference) return true; - foreach (const AbstractMetaArgument *a, m_arguments) { + for (const AbstractMetaArgument *a : m_arguments) { if (a->type()->referenceType() == RValueReference) return true; } @@ -600,13 +564,13 @@ int AbstractMetaFunction::actualMinimumArgumentCount() const } // Returns reference counts for argument at idx, or all arguments if idx == -2 -QList<ReferenceCount> AbstractMetaFunction::referenceCounts(const AbstractMetaClass *cls, int idx) const +QVector<ReferenceCount> AbstractMetaFunction::referenceCounts(const AbstractMetaClass *cls, int idx) const { - QList<ReferenceCount> returned; + QVector<ReferenceCount> returned; - FunctionModificationList mods = this->modifications(cls); - foreach (const FunctionModification &mod, mods) { - foreach (const ArgumentModification &argumentMod, mod.argument_mods) { + const FunctionModificationList &mods = this->modifications(cls); + for (const FunctionModification &mod : mods) { + for (const ArgumentModification &argumentMod : mod.argument_mods) { if (argumentMod.index != idx && idx != -2) continue; returned += argumentMod.referenceCounts; @@ -619,9 +583,9 @@ QList<ReferenceCount> AbstractMetaFunction::referenceCounts(const AbstractMetaCl ArgumentOwner AbstractMetaFunction::argumentOwner(const AbstractMetaClass *cls, int idx) const { - FunctionModificationList mods = this->modifications(cls); - foreach (const FunctionModification &mod, mods) { - foreach (const ArgumentModification &argumentMod, mod.argument_mods) { + const FunctionModificationList &mods = this->modifications(cls); + for (const FunctionModification &mod : mods) { + for (const ArgumentModification &argumentMod : mod.argument_mods) { if (argumentMod.index != idx) continue; return argumentMod.owner; @@ -633,9 +597,9 @@ ArgumentOwner AbstractMetaFunction::argumentOwner(const AbstractMetaClass *cls, QString AbstractMetaFunction::replacedDefaultExpression(const AbstractMetaClass *cls, int key) const { - FunctionModificationList modifications = this->modifications(cls); - foreach (const FunctionModification &modification, modifications) { - foreach (const ArgumentModification &argumentModification, modification.argument_mods) { + const FunctionModificationList &modifications = this->modifications(cls); + for (const FunctionModification &modification : modifications) { + for (const ArgumentModification &argumentModification : modification.argument_mods) { if (argumentModification.index == key && !argumentModification.replacedDefaultExpression.isEmpty()) { return argumentModification.replacedDefaultExpression; @@ -648,9 +612,9 @@ QString AbstractMetaFunction::replacedDefaultExpression(const AbstractMetaClass bool AbstractMetaFunction::removedDefaultExpression(const AbstractMetaClass *cls, int key) const { - FunctionModificationList modifications = this->modifications(cls); - foreach (const FunctionModification &modification, modifications) { - foreach (const ArgumentModification &argumentModification, modification.argument_mods) { + const FunctionModificationList &modifications = this->modifications(cls); + for (const FunctionModification &modification : modifications) { + for (const ArgumentModification &argumentModification : modification.argument_mods) { if (argumentModification.index == key && argumentModification.removedDefaultExpression) { return true; @@ -661,77 +625,15 @@ bool AbstractMetaFunction::removedDefaultExpression(const AbstractMetaClass *cls return false; } -bool AbstractMetaFunction::resetObjectAfterUse(int argumentIdx) const -{ - const AbstractMetaClass *cls = declaringClass(); - FunctionModificationList modifications = this->modifications(cls); - foreach (const FunctionModification &modification, modifications) { - foreach (const ArgumentModification &argumentModification, modification.argument_mods) { - if (argumentModification.index == argumentIdx && argumentModification.resetAfterUse) - return true; - } - } - - return false; -} - -QString AbstractMetaFunction::nullPointerDefaultValue(const AbstractMetaClass *mainClass, int argumentIdx) const -{ - Q_ASSERT(nullPointersDisabled(mainClass, argumentIdx)); - - const AbstractMetaClass *cls = mainClass; - if (!cls) - cls = implementingClass(); - - do { - FunctionModificationList modifications = this->modifications(cls); - foreach (const FunctionModification &modification, modifications) { - foreach (const ArgumentModification &argumentModification, modification.argument_mods) { - if (argumentModification.index == argumentIdx - && argumentModification.noNullPointers) { - return argumentModification.nullPointerDefaultValue; - } - } - } - cls = cls->baseClass(); - } while (cls && !mainClass); // Once when mainClass, or once for all base classes of implementing class - - return QString(); - -} - -bool AbstractMetaFunction::nullPointersDisabled(const AbstractMetaClass *mainClass, int argumentIdx) const -{ - const AbstractMetaClass *cls = mainClass; - if (!cls) - cls = implementingClass(); - - do { - FunctionModificationList modifications = this->modifications(cls); - foreach (const FunctionModification &modification, modifications) { - foreach (const ArgumentModification &argumentModification, modification.argument_mods) { - if (argumentModification.index == argumentIdx - && argumentModification.noNullPointers) { - return true; - } - } - } - - cls = cls->baseClass(); - } while (cls && !mainClass); // Once when mainClass, or once for all base classes of implementing class - - return false; -} - QString AbstractMetaFunction::conversionRule(TypeSystem::Language language, int key) const { - FunctionModificationList modifications = this->modifications(declaringClass()); - foreach (const FunctionModification &modification, modifications) { - foreach (const ArgumentModification &argumentModification, modification.argument_mods) { + const FunctionModificationList &modifications = this->modifications(declaringClass()); + for (const FunctionModification &modification : modifications) { + for (const ArgumentModification &argumentModification : modification.argument_mods) { if (argumentModification.index != key) continue; - foreach (const CodeSnip &snip, argumentModification.conversion_rules) { + for (const CodeSnip &snip : argumentModification.conversion_rules) { if (snip.language == language && !snip.code().isEmpty()) return snip.code(); } @@ -743,9 +645,9 @@ QString AbstractMetaFunction::conversionRule(TypeSystem::Language language, int QString AbstractMetaFunction::argumentReplaced(int key) const { - FunctionModificationList modifications = this->modifications(declaringClass()); - foreach (const FunctionModification &modification, modifications) { - foreach (const ArgumentModification &argumentModification, modification.argument_mods) { + const FunctionModificationList &modifications = this->modifications(declaringClass()); + for (const FunctionModification &modification : modifications) { + for (const ArgumentModification &argumentModification : modification.argument_mods) { if (argumentModification.index == key && !argumentModification.replace_value.isEmpty()) return argumentModification.replace_value; } @@ -757,9 +659,9 @@ QString AbstractMetaFunction::argumentReplaced(int key) const // FIXME If we remove a arg. in the method at the base class, it will not reflect here. bool AbstractMetaFunction::argumentRemoved(int key) const { - FunctionModificationList modifications = this->modifications(declaringClass()); - foreach (const FunctionModification &modification, modifications) { - foreach (const ArgumentModification &argumentModification, modification.argument_mods) { + const FunctionModificationList &modifications = this->modifications(declaringClass()); + for (const FunctionModification &modification : modifications) { + for (const ArgumentModification &argumentModification : modification.argument_mods) { if (argumentModification.index == key) { if (argumentModification.removed) return true; @@ -772,8 +674,8 @@ bool AbstractMetaFunction::argumentRemoved(int key) const bool AbstractMetaFunction::isVirtualSlot() const { - FunctionModificationList modifications = this->modifications(declaringClass()); - foreach (const FunctionModification &modification, modifications) { + const FunctionModificationList &modifications = this->modifications(declaringClass()); + for (const FunctionModification &modification : modifications) { if (modification.isVirtualSlot()) return true; } @@ -781,51 +683,20 @@ bool AbstractMetaFunction::isVirtualSlot() const return false; } -bool AbstractMetaFunction::disabledGarbageCollection(const AbstractMetaClass *cls, int key) const -{ - typedef QHash<TypeSystem::Language, TypeSystem::Ownership>::const_iterator OwnershipMapIt; - - FunctionModificationList modifications = this->modifications(cls); - foreach (const FunctionModification &modification, modifications) { - foreach (const ArgumentModification &argumentModification, modification.argument_mods) { - if (argumentModification.index != key) - continue; - - for (OwnershipMapIt it = argumentModification.ownerships.cbegin(), end = argumentModification.ownerships.cend(); it != end; ++it) { - if (it.value() == TypeSystem::CppOwnership) - return true; - } - - } - } - - return false; -} - bool AbstractMetaFunction::isDeprecated() const { - FunctionModificationList modifications = this->modifications(declaringClass()); - foreach (const FunctionModification &modification, modifications) { + const FunctionModificationList &modifications = this->modifications(declaringClass()); + for (const FunctionModification &modification : modifications) { if (modification.isDeprecated()) return true; } return false; } -bool AbstractMetaFunction::isThread() const -{ - FunctionModificationList modifications = this->modifications(declaringClass()); - foreach (const FunctionModification &modification, modifications) { - if (modification.isThread()) - return true; - } - return false; -} - bool AbstractMetaFunction::allowThread() const { - FunctionModificationList modifications = this->modifications(declaringClass()); - foreach (const FunctionModification &modification, modifications) { + const FunctionModificationList &modifications = this->modifications(declaringClass()); + for (const FunctionModification &modification : modifications) { if (modification.allowThread()) return true; } @@ -835,9 +706,9 @@ bool AbstractMetaFunction::allowThread() const TypeSystem::Ownership AbstractMetaFunction::ownership(const AbstractMetaClass *cls, TypeSystem::Language language, int key) const { - FunctionModificationList modifications = this->modifications(cls); - foreach (const FunctionModification &modification, modifications) { - foreach (const ArgumentModification &argumentModification, modification.argument_mods) { + const FunctionModificationList &modifications = this->modifications(cls); + for (const FunctionModification &modification : modifications) { + for (const ArgumentModification &argumentModification : modification.argument_mods) { if (argumentModification.index == key) return argumentModification.ownerships.value(language, TypeSystem::InvalidOwnership); } @@ -853,8 +724,8 @@ bool AbstractMetaFunction::isRemovedFromAllLanguages(const AbstractMetaClass *cl bool AbstractMetaFunction::isRemovedFrom(const AbstractMetaClass *cls, TypeSystem::Language language) const { - FunctionModificationList modifications = this->modifications(cls); - foreach (const FunctionModification &modification, modifications) { + const FunctionModificationList &modifications = this->modifications(cls); + for (const FunctionModification &modification : modifications) { if ((modification.removal & language) == language) return true; } @@ -865,9 +736,9 @@ bool AbstractMetaFunction::isRemovedFrom(const AbstractMetaClass *cls, TypeSyste QString AbstractMetaFunction::typeReplaced(int key) const { - FunctionModificationList modifications = this->modifications(declaringClass()); - foreach (const FunctionModification &modification, modifications) { - foreach (const ArgumentModification &argumentModification, modification.argument_mods) { + const FunctionModificationList &modifications = this->modifications(declaringClass()); + for (const FunctionModification &modification : modifications) { + for (const ArgumentModification &argumentModification : modification.argument_mods) { if (argumentModification.index == key && !argumentModification.modified_type.isEmpty()) { return argumentModification.modified_type; @@ -909,6 +780,21 @@ QString AbstractMetaFunction::minimalSignature() const return minimalSignature; } +QString AbstractMetaFunction::debugSignature() const +{ + QString result; + const bool isOverride = attributes() & AbstractMetaFunction::OverriddenCppMethod; + const bool isFinal = attributes() & AbstractMetaFunction::FinalCppMethod; + if (!isOverride && !isFinal && (attributes() & AbstractMetaFunction::VirtualCppMethod)) + result += QLatin1String("virtual "); + result += minimalSignature(); + if (isOverride) + result += QLatin1String(" override"); + if (isFinal) + result += QLatin1String(" final"); + return result; +} + FunctionModificationList AbstractMetaFunction::modifications(const AbstractMetaClass* implementor) const { if (!implementor) @@ -923,19 +809,14 @@ FunctionModificationList AbstractMetaFunction::modifications(const AbstractMetaC if ((implementor == implementor->baseClass()) || (implementor == implementingClass() && (mods.size() > 0))) break; - foreach (const AbstractMetaClass* interface, implementor->interfaces()) { + const AbstractMetaClassList &interfaces = implementor->interfaces(); + for (const AbstractMetaClass *interface : interfaces) mods += this->modifications(interface); - } implementor = implementor->baseClass(); } return mods; } -bool AbstractMetaFunction::hasModifications(const AbstractMetaClass *implementor) const -{ - return !modifications(implementor).isEmpty(); -} - QString AbstractMetaFunction::argumentName(int index, bool /* create */, const AbstractMetaClass * /* implementor */) const @@ -950,7 +831,8 @@ bool AbstractMetaFunction::isCallOperator() const bool AbstractMetaFunction::hasInjectedCode() const { - foreach (const FunctionModification &mod, modifications(ownerClass())) { + const FunctionModificationList &mods = modifications(ownerClass()); + for (const FunctionModification &mod : mods) { if (mod.isCodeInjection()) return true; } @@ -960,12 +842,12 @@ bool AbstractMetaFunction::hasInjectedCode() const CodeSnipList AbstractMetaFunction::injectedCodeSnips(TypeSystem::CodeSnipPosition position, TypeSystem::Language language) const { CodeSnipList result; - foreach (const FunctionModification &mod, modifications(ownerClass())) { + const FunctionModificationList &mods = modifications(ownerClass()); + for (const FunctionModification &mod : mods) { if (mod.isCodeInjection()) { - QList<CodeSnip>::const_iterator it = mod.snips.constBegin(); - for (;it != mod.snips.constEnd(); ++it) { - if ((it->language & language) && (it->position == position || position == TypeSystem::CodeSnipPositionAny)) - result << *it; + for (const CodeSnip &snip : mod.snips) { + if ((snip.language & language) && (snip.position == position || position == TypeSystem::CodeSnipPositionAny)) + result << snip; } } } @@ -974,10 +856,11 @@ CodeSnipList AbstractMetaFunction::injectedCodeSnips(TypeSystem::CodeSnipPositio bool AbstractMetaFunction::hasSignatureModifications() const { - foreach (const FunctionModification &mod, modifications()) { + const FunctionModificationList &mods = modifications(); + for (const FunctionModification &mod : mods) { if (mod.isRenameModifier()) return true; - foreach (const ArgumentModification &argmod, mod.argument_mods) { + for (const ArgumentModification &argmod : mod.argument_mods) { // since zero represents the return type and we're // interested only in checking the function arguments, // it will be ignored. @@ -990,8 +873,9 @@ bool AbstractMetaFunction::hasSignatureModifications() const bool AbstractMetaFunction::isConversionOperator(QString funcName) { - static QRegExp opRegEx(QLatin1String("^operator(?:\\s+(?:const|volatile))?\\s+(\\w+\\s*)&?$")); - return opRegEx.indexIn(funcName) > -1; + static const QRegularExpression opRegEx(QStringLiteral("^operator(?:\\s+(?:const|volatile))?\\s+(\\w+\\s*)&?$")); + Q_ASSERT(opRegEx.isValid()); + return opRegEx.match(funcName).hasMatch(); } bool AbstractMetaFunction::isOperatorOverload(QString funcName) @@ -999,12 +883,13 @@ bool AbstractMetaFunction::isOperatorOverload(QString funcName) if (isConversionOperator(funcName)) return true; - static QRegExp opRegEx(QLatin1String("^operator([+\\-\\*/%=&\\|\\^\\<>!][=]?" + static const QRegularExpression opRegEx(QLatin1String("^operator([+\\-\\*/%=&\\|\\^\\<>!][=]?" "|\\+\\+|\\-\\-|&&|\\|\\||<<[=]?|>>[=]?|~" "|\\[\\]|\\s+delete\\[?\\]?" "|\\(\\)" "|\\s+new\\[?\\]?)$")); - return opRegEx.indexIn(funcName) > -1; + Q_ASSERT(opRegEx.isValid()); + return opRegEx.match(funcName).hasMatch(); } bool AbstractMetaFunction::isCastOperator() const @@ -1127,14 +1012,14 @@ bool AbstractMetaFunction::isInplaceOperator() const bool AbstractMetaFunction::isVirtual() const { - return !isFinal() && !isSignal() && !isStatic() && !isFinalInCpp() && !isConstructor(); + return attributes() & AbstractMetaAttributes::VirtualCppMethod; } QString AbstractMetaFunction::modifiedName() const { if (m_cachedModifiedName.isEmpty()) { - FunctionModificationList mods = modifications(implementingClass()); - foreach (const FunctionModification &mod, mods) { + const FunctionModificationList &mods = modifications(implementingClass()); + for (const FunctionModification &mod : mods) { if (mod.isRenameModifier()) { m_cachedModifiedName = mod.renamedToName; break; @@ -1146,46 +1031,6 @@ QString AbstractMetaFunction::modifiedName() const return m_cachedModifiedName; } -QString AbstractMetaFunction::targetLangSignature(bool minimal) const -{ - QString s; - - // Attributes... - if (!minimal) { - // Return type - if (type()) - s += type()->name() + QLatin1Char(' '); - else - s += QLatin1String("void "); - } - - s += modifiedName(); - s += QLatin1Char('('); - - int j = 0; - for (int i = 0; i < m_arguments.size(); ++i) { - if (argumentRemoved(i + 1)) - continue; - if (j) { - s += QLatin1Char(','); - if (!minimal) - s += QLatin1Char(' '); - } - s += m_arguments.at(i)->type()->name(); - - if (!minimal) { - s += QLatin1Char(' '); - s += m_arguments.at(i)->name(); - } - ++j; - } - - s += QLatin1Char(')'); - - return s; -} - - bool function_sorter(AbstractMetaFunction *a, AbstractMetaFunction *b) { return a->signature() < b->signature(); @@ -1194,7 +1039,7 @@ bool function_sorter(AbstractMetaFunction *a, AbstractMetaFunction *b) #ifndef QT_NO_DEBUG_STREAM static inline void formatMetaFunctionBrief(QDebug &d, const AbstractMetaFunction *af) { - d << '"' << af->minimalSignature() << '"'; + d << '"' << af->debugSignature() << '"'; } void AbstractMetaFunction::formatDebugVerbose(QDebug &d) const @@ -1208,8 +1053,6 @@ void AbstractMetaFunction::formatDebugVerbose(QDebug &d) const d << "), signature=\"" << minimalSignature() << '"'; if (m_constant) d << " [const]"; - if (m_invalid) - d << " [invalid]"; if (m_reverse) d << " [reverse]"; if (m_userAdded) @@ -1256,15 +1099,34 @@ QDebug operator<<(QDebug d, const AbstractMetaFunction *af) /******************************************************************************* * AbstractMetaClass */ + +AbstractMetaClass::AbstractMetaClass() + : m_hasVirtuals(false), + m_isPolymorphic(false), + m_hasNonpublic(false), + m_hasVirtualSlots(false), + m_hasNonPrivateConstructor(false), + m_hasPrivateConstructor(false), + m_functionsFixed(false), + m_hasPrivateDestructor(false), + m_hasProtectedDestructor(false), + m_hasVirtualDestructor(false), + m_forceShellClass(false), + m_hasHashFunction(false), + m_hasEqualsOperator(false), + m_hasCloneOperator(false), + m_isTypeDef(false), + m_hasToStringCapability(false) +{ +} + AbstractMetaClass::~AbstractMetaClass() { qDeleteAll(m_functions); qDeleteAll(m_fields); qDeleteAll(m_enums); - if (hasTemplateBaseClassInstantiations()) { - foreach (AbstractMetaType* inst, templateBaseClassInstantiations()) - delete inst; - } + if (hasTemplateBaseClassInstantiations()) + qDeleteAll(templateBaseClassInstantiations()); } /******************************************************************************* @@ -1300,7 +1162,7 @@ AbstractMetaClass *AbstractMetaClass::extractInterface() iface->setTypeEntry(typeEntry()->designatedInterface()); - foreach (AbstractMetaFunction *function, functions()) { + for (AbstractMetaFunction *function : qAsConst(m_functions)) { if (!function->isConstructor()) iface->addFunction(function->copy()); } @@ -1308,7 +1170,7 @@ AbstractMetaClass *AbstractMetaClass::extractInterface() // iface->setEnums(enums()); // setEnums(AbstractMetaEnumList()); - foreach (const AbstractMetaField *field, fields()) { + for (const AbstractMetaField *field : qAsConst(m_fields)) { if (field->isPublic()) { AbstractMetaField *new_field = field->copy(); new_field->setEnclosingClass(iface); @@ -1329,8 +1191,7 @@ AbstractMetaClass *AbstractMetaClass::extractInterface() AbstractMetaFunctionList AbstractMetaClass::queryFunctionsByName(const QString &name) const { AbstractMetaFunctionList returned; - AbstractMetaFunctionList functions = this->functions(); - foreach (AbstractMetaFunction *function, functions) { + for (AbstractMetaFunction *function : m_functions) { if (function->name() == name) returned.append(function); } @@ -1353,7 +1214,7 @@ AbstractMetaFunctionList AbstractMetaClass::functionsInTargetLang() const // Only public functions in final classes // default_flags |= isFinal() ? WasPublic : 0; FunctionQueryOptions public_flags; - if (isFinal()) + if (isFinalInTargetLang()) public_flags |= WasPublic; // Constructors @@ -1374,33 +1235,18 @@ AbstractMetaFunctionList AbstractMetaClass::functionsInTargetLang() const return returned; } -AbstractMetaFunctionList AbstractMetaClass::virtualFunctions() const -{ - AbstractMetaFunctionList list = functionsInShellClass(); - - AbstractMetaFunctionList returned; - foreach (AbstractMetaFunction *f, list) { - if (!f->isFinalInCpp() || f->isVirtualSlot()) - returned += f; - } - - return returned; -} - AbstractMetaFunctionList AbstractMetaClass::implicitConversions() const { if (!hasCloneOperator() && !hasExternalConversionOperators()) return AbstractMetaFunctionList(); AbstractMetaFunctionList returned; - AbstractMetaFunctionList list = queryFunctions(Constructors); - - list.append(externalConversionOperators()); + const AbstractMetaFunctionList list = queryFunctions(Constructors) + externalConversionOperators(); // Exclude anything that uses rvalue references, be it a move // constructor "QPolygon(QPolygon &&)" or something else like // "QPolygon(QVector<QPoint> &&)". - foreach (AbstractMetaFunction *f, list) { + for (AbstractMetaFunction *f : list) { if ((f->actualMinimumArgumentCount() == 1 || f->arguments().size() == 1 || f->isConversionOperator()) && !f->isExplicit() && f->functionType() != AbstractMetaFunction::CopyConstructorFunction @@ -1415,9 +1261,9 @@ AbstractMetaFunctionList AbstractMetaClass::implicitConversions() const AbstractMetaFunctionList AbstractMetaClass::operatorOverloads(OperatorQueryOptions query) const { - AbstractMetaFunctionList list = queryFunctions(OperatorOverloads | Visible); + const AbstractMetaFunctionList &list = queryFunctions(OperatorOverloads | Visible); AbstractMetaFunctionList returned; - foreach (AbstractMetaFunction *f, list) { + for (AbstractMetaFunction *f : list) { if (((query & ArithmeticOp) && f->isArithmeticOperator()) || ((query & BitwiseOp) && f->isBitwiseOperator()) || ((query & ComparisonOp) && f->isComparisonOperator()) @@ -1432,18 +1278,9 @@ AbstractMetaFunctionList AbstractMetaClass::operatorOverloads(OperatorQueryOptio return returned; } -bool AbstractMetaClass::hasOperatorOverload() const -{ - foreach (const AbstractMetaFunction *f, m_functions) { - if (f->ownerClass() == f->implementingClass() && f->isOperatorOverload() && !f->isPrivate()) - return true; - } - return false; -} - bool AbstractMetaClass::hasArithmeticOperatorOverload() const { - foreach (const AbstractMetaFunction *f, m_functions) { + for (const AbstractMetaFunction *f : m_functions) { if (f->ownerClass() == f->implementingClass() && f->isArithmeticOperator() && !f->isPrivate()) return true; } @@ -1452,7 +1289,7 @@ bool AbstractMetaClass::hasArithmeticOperatorOverload() const bool AbstractMetaClass::hasBitwiseOperatorOverload() const { - foreach (const AbstractMetaFunction *f, m_functions) { + for (const AbstractMetaFunction *f : m_functions) { if (f->ownerClass() == f->implementingClass() && f->isBitwiseOperator() && !f->isPrivate()) return true; } @@ -1461,7 +1298,7 @@ bool AbstractMetaClass::hasBitwiseOperatorOverload() const bool AbstractMetaClass::hasComparisonOperatorOverload() const { - foreach (const AbstractMetaFunction *f, m_functions) { + for (const AbstractMetaFunction *f : m_functions) { if (f->ownerClass() == f->implementingClass() && f->isComparisonOperator() && !f->isPrivate()) return true; } @@ -1470,79 +1307,13 @@ bool AbstractMetaClass::hasComparisonOperatorOverload() const bool AbstractMetaClass::hasLogicalOperatorOverload() const { - foreach (const AbstractMetaFunction *f, m_functions) { + for (const AbstractMetaFunction *f : m_functions) { if (f->ownerClass() == f->implementingClass() && f->isLogicalOperator() && !f->isPrivate()) return true; } return false; } -bool AbstractMetaClass::hasSubscriptOperatorOverload() const -{ - foreach (const AbstractMetaFunction *f, m_functions) { - if (f->ownerClass() == f->implementingClass() && f->isSubscriptOperator() && !f->isPrivate()) - return true; - } - return false; -} - -bool AbstractMetaClass::hasAssignmentOperatorOverload() const -{ - foreach (const AbstractMetaFunction *f, m_functions) { - if (f->ownerClass() == f->implementingClass() && f->isAssignmentOperator() && !f->isPrivate()) - return true; - } - return false; -} - -bool AbstractMetaClass::hasConversionOperatorOverload() const -{ - foreach (const AbstractMetaFunction *f, m_functions) { - if (f->ownerClass() == f->implementingClass() && f->isConversionOperator() && !f->isPrivate()) - return true; - } - return false; -} - -/******************************************************************************* - * Returns a list of all functions that should be declared and implemented in - * the shell class which is generated as a wrapper on top of the actual C++ class - */ -AbstractMetaFunctionList AbstractMetaClass::functionsInShellClass() const -{ - // Only functions and only protected and public functions - FunctionQueryOptions default_flags = NormalFunctions | Visible | WasVisible | NotRemovedFromShell; - - // All virtual functions - AbstractMetaFunctionList returned = queryFunctions(VirtualFunctions | default_flags); - - // All functions explicitly set to be implemented by the shell class - // (mainly superclass functions that are hidden by other declarations) - returned += queryFunctions(ForcedShellFunctions | default_flags); - - // All functions explicitly set to be virtual slots - returned += queryFunctions(VirtualSlots | default_flags); - - return returned; -} - -/******************************************************************************* - * Returns a list of all functions that require a public override function to - * be generated in the shell class. This includes all functions that were originally - * protected in the superclass. - */ -AbstractMetaFunctionList AbstractMetaClass::publicOverrideFunctions() const -{ - return queryFunctions(NormalFunctions | WasProtected | FinalInCppFunctions | NotRemovedFromTargetLang) - + queryFunctions(Signals | WasProtected | FinalInCppFunctions | NotRemovedFromTargetLang); -} - -AbstractMetaFunctionList AbstractMetaClass::virtualOverrideFunctions() const -{ - return queryFunctions(NormalFunctions | NonEmptyFunctions | Visible | VirtualInCppFunctions | NotRemovedFromShell) + - queryFunctions(Signals | NonEmptyFunctions | Visible | VirtualInCppFunctions | NotRemovedFromShell); -} - void AbstractMetaClass::sortFunctions() { qSort(m_functions.begin(), m_functions.end(), function_sorter); @@ -1555,46 +1326,19 @@ void AbstractMetaClass::setFunctions(const AbstractMetaFunctionList &functions) // Functions must be sorted by name before next loop sortFunctions(); - QString currentName; - bool hasVirtuals = false; - AbstractMetaFunctionList finalFunctions; - foreach (AbstractMetaFunction *f, m_functions) { + for (AbstractMetaFunction *f : qAsConst(m_functions)) { f->setOwnerClass(this); m_hasVirtualSlots = m_hasVirtualSlots || f->isVirtualSlot(); m_hasVirtuals = m_hasVirtuals || f->isVirtualSlot() || hasVirtualDestructor(); m_isPolymorphic = m_isPolymorphic || m_hasVirtuals; m_hasNonpublic = m_hasNonpublic || !f->isPublic(); - - // If we have non-virtual overloads of a virtual function, we have to implement - // all the overloads in the shell class to override the hiding rule - if (currentName == f->name()) { - hasVirtuals = hasVirtuals || !f->isFinal(); - if (f->isFinal()) - finalFunctions += f; - } else { - if (hasVirtuals && finalFunctions.size() > 0) { - foreach (AbstractMetaFunction *final_function, finalFunctions) { - *final_function += AbstractMetaAttributes::ForceShellImplementation; - - qCWarning(lcShiboken).noquote().nospace() - << QStringLiteral("hiding of function '%1' in class '%2'") - .arg(final_function->name(), name()); - } - } - - hasVirtuals = !f->isFinal(); - finalFunctions.clear(); - if (f->isFinal()) - finalFunctions += f; - currentName = f->name(); - } } } bool AbstractMetaClass::hasFieldAccessors() const { - foreach (const AbstractMetaField *field, fields()) { + for (const AbstractMetaField *field : m_fields) { if (field->getter() || field->setter()) return true; } @@ -1604,7 +1348,8 @@ bool AbstractMetaClass::hasFieldAccessors() const bool AbstractMetaClass::hasDefaultToStringFunction() const { - foreach (AbstractMetaFunction *f, queryFunctionsByName(QLatin1String("toString"))) { + const AbstractMetaFunctionList &funcs = queryFunctionsByName(QLatin1String("toString")); + for (const AbstractMetaFunction *f : funcs) { if (!f->actualMinimumArgumentCount()) return true; } @@ -1622,7 +1367,7 @@ void AbstractMetaClass::addFunction(AbstractMetaFunction *function) Q_ASSERT(false); //memory leak m_hasVirtualSlots |= function->isVirtualSlot(); - m_hasVirtuals |= !function->isFinal() || function->isVirtualSlot() || hasVirtualDestructor(); + m_hasVirtuals |= function->isVirtual() || function->isVirtualSlot() || hasVirtualDestructor(); m_isPolymorphic |= m_hasVirtuals; m_hasNonpublic |= !function->isPublic(); } @@ -1632,7 +1377,7 @@ bool AbstractMetaClass::hasSignal(const AbstractMetaFunction *other) const if (!other->isSignal()) return false; - foreach (const AbstractMetaFunction *f, functions()) { + for (const AbstractMetaFunction *f : m_functions) { if (f->isSignal() && f->compareTo(other) & AbstractMetaFunction::EqualName) return other->modifiedName() == f->modifiedName(); } @@ -1643,7 +1388,7 @@ bool AbstractMetaClass::hasSignal(const AbstractMetaFunction *other) const QString AbstractMetaClass::name() const { - return QString(m_typeEntry->targetLangName()).split(QLatin1String("::")).last(); + return lastNameSegment(m_typeEntry->targetLangName()); } void AbstractMetaClass::setBaseClass(AbstractMetaClass *baseClass) @@ -1685,7 +1430,7 @@ bool AbstractMetaClass::hasFunction(const QString &str) const const AbstractMetaFunction* AbstractMetaClass::findFunction(const QString& functionName) const { - foreach (const AbstractMetaFunction *f, functions()) { + for (const AbstractMetaFunction *f : m_functions) { if (f->name() == functionName) return f; } @@ -1694,7 +1439,7 @@ const AbstractMetaFunction* AbstractMetaClass::findFunction(const QString& funct bool AbstractMetaClass::hasProtectedFunctions() const { - foreach (AbstractMetaFunction *func, m_functions) { + for (AbstractMetaFunction *func : m_functions) { if (func->isProtected()) return true; } @@ -1703,7 +1448,7 @@ bool AbstractMetaClass::hasProtectedFunctions() const bool AbstractMetaClass::hasProtectedFields() const { - foreach (const AbstractMetaField *field, fields()) { + for (const AbstractMetaField *field : m_fields) { if (field->isProtected()) return true; } @@ -1715,15 +1460,6 @@ bool AbstractMetaClass::hasProtectedMembers() const return hasProtectedFields() || hasProtectedFunctions(); } -bool AbstractMetaClass::generateShellClass() const -{ - return m_forceShellClass || - (!isFinal() - && (hasVirtualFunctions() - || hasProtectedFunctions() - || hasFieldAccessors())); -} - QPropertySpec *AbstractMetaClass::propertySpecForRead(const QString &name) const { for (int i = 0; i < m_propertySpecs.size(); ++i) @@ -1775,16 +1511,14 @@ void AbstractMetaClass::setTemplateBaseClassInstantiations(AbstractMetaTypeList& static bool functions_contains(const AbstractMetaFunctionList &l, const AbstractMetaFunction *func) { - foreach (const AbstractMetaFunction *f, l) { + for (const AbstractMetaFunction *f : l) { if ((f->compareTo(func) & AbstractMetaFunction::PrettySimilar) == AbstractMetaFunction::PrettySimilar) return true; } return false; } -AbstractMetaField::AbstractMetaField() : m_getter(0), m_setter(0), m_class(0) -{ -} +AbstractMetaField::AbstractMetaField() = default; AbstractMetaField::~AbstractMetaField() { @@ -1795,12 +1529,9 @@ AbstractMetaField::~AbstractMetaField() AbstractMetaField *AbstractMetaField::copy() const { AbstractMetaField *returned = new AbstractMetaField; - returned->setEnclosingClass(0); - returned->setAttributes(attributes()); - returned->setName(name()); - returned->setType(type()->copy()); - returned->setOriginalAttributes(originalAttributes()); - + returned->assignMetaVariable(*this); + returned->assignMetaAttributes(*this); + returned->setEnclosingClass(nullptr); return returned; } @@ -1809,8 +1540,8 @@ AbstractMetaField *AbstractMetaField::copy() const */ bool AbstractMetaField::isModifiedRemoved(int types) const { - FieldModificationList mods = modifications(); - foreach (const FieldModification &mod, mods) { + const FieldModificationList &mods = modifications(); + for (const FieldModification &mod : mods) { if (!mod.isRemoveModifier()) continue; @@ -1840,9 +1571,7 @@ static AbstractMetaFunction *createXetter(const AbstractMetaField *g, const QStr f->setImplementingClass(g->enclosingClass()); f->setDeclaringClass(g->enclosingClass()); - AbstractMetaAttributes::Attributes attr = AbstractMetaAttributes::Native - | AbstractMetaAttributes::Final - | type; + AbstractMetaAttributes::Attributes attr = AbstractMetaAttributes::FinalInTargetLang | type; if (g->isStatic()) attr |= AbstractMetaAttributes::Static; if (g->isPublic()) @@ -1854,8 +1583,8 @@ static AbstractMetaFunction *createXetter(const AbstractMetaField *g, const QStr f->setAttributes(attr); f->setOriginalAttributes(attr); - FieldModificationList mods = g->modifications(); - foreach (const FieldModification &mod, mods) { + const FieldModificationList &mods = g->modifications(); + for (const FieldModification &mod : mods) { if (mod.isRenameModifier()) f->setName(mod.renamedTo()); if (mod.isAccessModifier()) { @@ -1874,10 +1603,10 @@ static AbstractMetaFunction *createXetter(const AbstractMetaField *g, const QStr FieldModificationList AbstractMetaField::modifications() const { - FieldModificationList mods = enclosingClass()->typeEntry()->fieldModifications(); + const FieldModificationList &mods = enclosingClass()->typeEntry()->fieldModifications(); FieldModificationList returned; - foreach (const FieldModification &mod, mods) { + for (const FieldModification &mod : mods) { if (mod.name == name()) returned += mod; } @@ -1994,7 +1723,8 @@ bool AbstractMetaClass::hasConstructors() const bool AbstractMetaClass::hasCopyConstructor() const { - foreach (const AbstractMetaFunction* ctor, queryFunctions(Constructors)) { + const AbstractMetaFunctionList &ctors = queryFunctions(Constructors); + for (const AbstractMetaFunction* ctor : ctors) { if (ctor->functionType() == AbstractMetaFunction::CopyConstructorFunction) return true; } @@ -2003,7 +1733,8 @@ bool AbstractMetaClass::hasCopyConstructor() const bool AbstractMetaClass::hasPrivateCopyConstructor() const { - foreach (const AbstractMetaFunction* ctor, queryFunctions(Constructors)) { + const AbstractMetaFunctionList &ctors = queryFunctions(Constructors); + for (const AbstractMetaFunction *ctor : ctors) { if (ctor->functionType() == AbstractMetaFunction::CopyConstructorFunction && ctor->isPrivate()) return true; } @@ -2020,10 +1751,7 @@ void AbstractMetaClass::addDefaultConstructor() f->setArguments(AbstractMetaArgumentList()); f->setDeclaringClass(this); - AbstractMetaAttributes::Attributes attr = AbstractMetaAttributes::Native; - attr |= AbstractMetaAttributes::Public; - attr |= AbstractMetaAttributes::Final; - f->setAttributes(attr); + f->setAttributes(AbstractMetaAttributes::Public | AbstractMetaAttributes::FinalInTargetLang); f->setImplementingClass(this); f->setOriginalAttributes(f->attributes()); @@ -2051,8 +1779,7 @@ void AbstractMetaClass::addDefaultCopyConstructor(bool isPrivate) arg->setName(name()); f->addArgument(arg); - AbstractMetaAttributes::Attributes attr = AbstractMetaAttributes::Native; - attr |= AbstractMetaAttributes::Final; + AbstractMetaAttributes::Attributes attr = AbstractMetaAttributes::FinalInTargetLang; if (isPrivate) attr |= AbstractMetaAttributes::Private; else @@ -2077,21 +1804,11 @@ AbstractMetaFunctionList AbstractMetaClass::queryFunctions(FunctionQueryOptions { AbstractMetaFunctionList functions; - foreach (AbstractMetaFunction *f, m_functions) { - - if ((query & VirtualSlots) && !f->isVirtualSlot()) - continue; - + for (AbstractMetaFunction *f : m_functions) { if ((query & NotRemovedFromTargetLang) && f->isRemovedFrom(f->implementingClass(), TypeSystem::TargetLangCode)) continue; - if ((query & NotRemovedFromTargetLang) && !f->isFinal() && f->isRemovedFrom(f->declaringClass(), TypeSystem::TargetLangCode)) - continue; - - if ((query & NotRemovedFromShell) && f->isRemovedFrom(f->implementingClass(), TypeSystem::ShellCode)) - continue; - - if ((query & NotRemovedFromShell) && !f->isFinal() && f->isRemovedFrom(f->declaringClass(), TypeSystem::ShellCode)) + if ((query & NotRemovedFromTargetLang) && f->isVirtual() && f->isRemovedFrom(f->declaringClass(), TypeSystem::TargetLangCode)) continue; if ((query & Visible) && f->isPrivate()) @@ -2109,35 +1826,18 @@ AbstractMetaFunctionList AbstractMetaClass::queryFunctions(FunctionQueryOptions if ((query & WasPublic) && !f->wasPublic()) continue; - if ((query & WasVisible) && f->wasPrivate()) - continue; - - if ((query & WasProtected) && !f->wasProtected()) - continue; - if ((query & ClassImplements) && f->ownerClass() != f->implementingClass()) continue; - if ((query & Inconsistent) && (f->isFinalInTargetLang() || !f->isFinalInCpp() || f->isStatic())) - continue; - if ((query & FinalInTargetLangFunctions) && !f->isFinalInTargetLang()) continue; - if ((query & FinalInCppFunctions) && !f->isFinalInCpp()) - continue; - - if ((query & VirtualInCppFunctions) && f->isFinalInCpp()) + if ((query & VirtualInCppFunctions) && !f->isVirtual()) continue; if ((query & Signals) && (!f->isSignal())) continue; - if ((query & ForcedShellFunctions) && - (!f->isForcedShellImplementation() || !f->isFinal())) { - continue; - } - if ((query & Constructors) && (!f->isConstructor() || f->ownerClass() != f->implementingClass())) continue; @@ -2152,24 +1852,15 @@ AbstractMetaFunctionList AbstractMetaClass::queryFunctions(FunctionQueryOptions continue; }*/ - if ((query & VirtualFunctions) && (f->isFinal() || f->isSignal() || f->isStatic())) - continue; - if ((query & StaticFunctions) && (!f->isStatic() || f->isSignal())) continue; if ((query & NonStaticFunctions) && (f->isStatic())) continue; - if ((query & NonEmptyFunctions) && (f->isEmptyFunction())) - continue; - if ((query & NormalFunctions) && (f->isSignal())) continue; - if ((query & AbstractFunctions) && !f->isAbstract()) - continue; - if ((query & OperatorOverloads) && !f->isOperatorOverload()) continue; @@ -2199,8 +1890,10 @@ void AbstractMetaClass::addInterface(AbstractMetaClass *interface) if (m_extractedInterface && m_extractedInterface != interface) m_extractedInterface->addInterface(interface); + #if 0 - foreach (AbstractMetaFunction *function, interface->functions()) + const AbstractMetaFunctionList &funcs = interface->functions(); + for (AbstractMetaFunction *function : funcs) if (!hasFunction(function) && !function->isConstructor()) { AbstractMetaFunction *cpy = function->copy(); cpy->setImplementingClass(this); @@ -2210,8 +1903,8 @@ void AbstractMetaClass::addInterface(AbstractMetaClass *interface) *cpy += AbstractMetaAttributes::InterfaceFunction; // Copy the modifications in interface into the implementing classes. - FunctionModificationList mods = function->modifications(interface); - foreach (const FunctionModification &mod, mods) + const FunctionModificationList &mods = function->modifications(interface); + for (const FunctionModification &mod : mods) m_typeEntry->addFunctionModification(mod); // It should be mostly safe to assume that when we implement an interface @@ -2228,7 +1921,7 @@ void AbstractMetaClass::addInterface(AbstractMetaClass *interface) void AbstractMetaClass::setInterfaces(const AbstractMetaClassList &interfaces) { m_interfaces = interfaces; - foreach (const AbstractMetaClass* interface, interfaces) { + for (const AbstractMetaClass *interface : interfaces) { if (interface) m_isPolymorphic |= interface->isPolymorphic(); } @@ -2237,7 +1930,7 @@ void AbstractMetaClass::setInterfaces(const AbstractMetaClassList &interfaces) AbstractMetaEnum *AbstractMetaClass::findEnum(const QString &enumName) { - foreach (AbstractMetaEnum *e, m_enums) { + for (AbstractMetaEnum *e : qAsConst(m_enums)) { if (e->name() == enumName) return e; } @@ -2245,59 +1938,26 @@ AbstractMetaEnum *AbstractMetaClass::findEnum(const QString &enumName) if (typeEntry()->designatedInterface()) return extractInterface()->findEnum(enumName); - return 0; + return nullptr; } - - - -/*! Recursivly searches for the enum value named \a enumValueName in - this class and its superclasses and interfaces. Values belonging to - \a meta_enum are excluded from the search. +/*! Recursively searches for the enum value named \a enumValueName in + this class and its superclasses and interfaces. */ -AbstractMetaEnumValue *AbstractMetaClass::findEnumValue(const QString &enumValueName, AbstractMetaEnum *meta_enum) -{ - foreach (AbstractMetaEnum *e, m_enums) { - if (e != meta_enum) - continue; - foreach (AbstractMetaEnumValue *v, e->values()) { - if (v->name() == enumValueName) - return v; - } - } - - if (typeEntry()->designatedInterface()) - return extractInterface()->findEnumValue(enumValueName, meta_enum); - - if (baseClass()) - return baseClass()->findEnumValue(enumValueName, meta_enum); - - return 0; -} - - -/*! - * Searches through all of this class' enums for a value matching the - * name \a enumValueName. The name is excluding the class/namespace - * prefix. The function recursivly searches interfaces and baseclasses - * of this class. - */ -AbstractMetaEnum *AbstractMetaClass::findEnumForValue(const QString &enumValueName) +AbstractMetaEnumValue *AbstractMetaClass::findEnumValue(const QString &enumValueName) { - foreach (AbstractMetaEnum *e, m_enums) { - foreach (AbstractMetaEnumValue *v, e->values()) { - if (v->name() == enumValueName) - return e; - } + for (AbstractMetaEnum *e : qAsConst(m_enums)) { + if (AbstractMetaEnumValue *v = e->findEnumValue(enumValueName)) + return v; } if (typeEntry()->designatedInterface()) - return extractInterface()->findEnumForValue(enumValueName); + return extractInterface()->findEnumValue(enumValueName); if (baseClass()) - return baseClass()->findEnumForValue(enumValueName); + return baseClass()->findEnumValue(enumValueName); - return 0; + return nullptr; } @@ -2316,8 +1976,8 @@ static void addExtraIncludeForType(AbstractMetaClass *metaClass, const AbstractM } if (type->hasInstantiations()) { - AbstractMetaTypeList instantiations = type->instantiations(); - foreach (const AbstractMetaType *instantiation, instantiations) + const AbstractMetaTypeList &instantiations = type->instantiations(); + for (const AbstractMetaType *instantiation : instantiations) addExtraIncludeForType(metaClass, instantiation); } } @@ -2328,9 +1988,9 @@ static void addExtraIncludesForFunction(AbstractMetaClass *metaClass, const Abst Q_ASSERT(meta_function); addExtraIncludeForType(metaClass, meta_function->type()); - AbstractMetaArgumentList arguments = meta_function->arguments(); - foreach (AbstractMetaArgument *argument, arguments) - addExtraIncludeForType(metaClass, argument->type()); + const AbstractMetaArgumentList &arguments = meta_function->arguments(); + for (AbstractMetaArgument *argument : arguments) + addExtraIncludeForType(metaClass, argument->type()); } void AbstractMetaClass::fixFunctions() @@ -2395,9 +2055,6 @@ void AbstractMetaClass::fixFunctions() // Same function, propegate virtual... if (!(cmp & AbstractMetaFunction::EqualAttributes)) { if (!f->isEmptyFunction()) { - if (!sf->isFinalInCpp() && f->isFinalInCpp()) { - *f -= AbstractMetaAttributes::FinalInCpp; - } if (!sf->isFinalInTargetLang() && f->isFinalInTargetLang()) { *f -= AbstractMetaAttributes::FinalInTargetLang; } @@ -2432,7 +2089,6 @@ void AbstractMetaClass::fixFunctions() if (f->isPrivate()) { f->setFunctionType(AbstractMetaFunction::EmptyFunction); *f += AbstractMetaAttributes::FinalInTargetLang; - *f += AbstractMetaAttributes::FinalInCpp; } } @@ -2448,8 +2104,8 @@ void AbstractMetaClass::fixFunctions() bool hasNonFinalModifier = false; bool isBaseImplPrivate = false; - FunctionModificationList mods = sf->modifications(sf->implementingClass()); - foreach (const FunctionModification &mod, mods) { + const FunctionModificationList &mods = sf->modifications(sf->implementingClass()); + for (const FunctionModification &mod : mods) { if (mod.isNonFinal()) { hasNonFinalModifier = true; break; @@ -2495,7 +2151,7 @@ void AbstractMetaClass::fixFunctions() funcsToAdd << sf; } - foreach (AbstractMetaFunction *f, funcsToAdd) + for (AbstractMetaFunction *f : qAsConst(funcsToAdd)) funcs << f->copy(); if (superClass) @@ -2506,9 +2162,9 @@ void AbstractMetaClass::fixFunctions() bool hasPrivateConstructors = false; bool hasPublicConstructors = false; - foreach (AbstractMetaFunction *func, funcs) { - FunctionModificationList mods = func->modifications(this); - foreach (const FunctionModification &mod, mods) { + for (AbstractMetaFunction *func : qAsConst(funcs)) { + const FunctionModificationList &mods = func->modifications(this); + for (const FunctionModification &mod : mods) { if (mod.isRenameModifier()) { func->setName(mod.renamedTo()); } @@ -2517,7 +2173,7 @@ void AbstractMetaClass::fixFunctions() // Make sure class is abstract if one of the functions is if (func->isAbstract()) { (*this) += AbstractMetaAttributes::Abstract; - (*this) -= AbstractMetaAttributes::Final; + (*this) -= AbstractMetaAttributes::FinalInTargetLang; } if (func->isConstructor()) { @@ -2537,75 +2193,72 @@ void AbstractMetaClass::fixFunctions() if (hasPrivateConstructors && !hasPublicConstructors) { (*this) += AbstractMetaAttributes::Abstract; - (*this) -= AbstractMetaAttributes::Final; - } - - foreach (AbstractMetaFunction *f1, funcs) { - foreach (AbstractMetaFunction *f2, funcs) { - if (f1 != f2) { - const AbstractMetaFunction::CompareResult cmp = f1->compareTo(f2); - if ((cmp & AbstractMetaFunction::EqualName) - && !f1->isFinalInCpp() - && f2->isFinalInCpp()) { - *f2 += AbstractMetaAttributes::FinalOverload; - } - } - } + (*this) -= AbstractMetaAttributes::FinalInTargetLang; } setFunctions(funcs); } +static inline QString formatArraySize(int e) +{ + QString result; + result += QLatin1Char('['); + if (e >= 0) + result += QString::number(e); + result += QLatin1Char(']'); + return result; +} -QString AbstractMetaType::minimalSignature() const +QString AbstractMetaType::formatSignature(bool minimal) const { - QString minimalSignature; + QString result; if (isConstant()) - minimalSignature += QLatin1String("const "); - minimalSignature += typeEntry()->qualifiedCppName(); - if (hasInstantiations()) { - AbstractMetaTypeList instantiations = this->instantiations(); - minimalSignature += QLatin1String("< "); - for (int i = 0; i < instantiations.size(); ++i) { + result += QLatin1String("const "); + if (isArray()) { + // Build nested array dimensions a[2][3] in correct order + result += m_arrayElementType->minimalSignature(); + const int arrayPos = result.indexOf(QLatin1Char('[')); + if (arrayPos != -1) + result.insert(arrayPos, formatArraySize(m_arrayElementCount)); + else + result.append(formatArraySize(m_arrayElementCount)); + } else { + result += typeEntry()->qualifiedCppName(); + } + if (!m_instantiations.isEmpty()) { + result += QLatin1Char('<'); + if (minimal) + result += QLatin1Char(' '); + for (int i = 0, size = m_instantiations.size(); i < size; ++i) { if (i > 0) - minimalSignature += QLatin1Char(','); - minimalSignature += instantiations[i]->minimalSignature(); + result += QLatin1Char(','); + result += m_instantiations.at(i)->minimalSignature(); } - minimalSignature += QLatin1String(" >"); + result += QLatin1String(" >"); } - for (int j = 0; j < indirections(); ++j) - minimalSignature += QLatin1Char('*'); + if (!minimal && (m_indirections != 0 || m_referenceType != NoReference)) + result += QLatin1Char(' '); + if (m_indirections) + result += QString(m_indirections, QLatin1Char('*')); switch (referenceType()) { case NoReference: break; case LValueReference: - minimalSignature += QLatin1Char('&'); + result += QLatin1Char('&'); break; case RValueReference: - minimalSignature += QLatin1String("&&"); + result += QLatin1String("&&"); break; } - - return minimalSignature; -} - -bool AbstractMetaType::hasNativeId() const -{ - return (isQObject() || isValue() || isObject()) && typeEntry()->isNativeIdBased(); -} - -bool AbstractMetaType::isTargetLangEnum() const -{ - return isEnum() && !static_cast<const EnumTypeEntry *>(typeEntry())->forceInteger(); + return result; } -bool AbstractMetaType::isTargetLangFlags() const +bool AbstractMetaType::isCppPrimitive() const { - return isFlags() && !static_cast<const FlagsTypeEntry *>(typeEntry())->forceInteger(); + return m_pattern == PrimitivePattern && m_typeEntry->isCppPrimitive(); } - /******************************************************************************* * Other stuff... */ @@ -2641,40 +2294,26 @@ AbstractMetaEnum *AbstractMetaClass::findEnum(const AbstractMetaClassList &class return metaClass->findEnum(enumName); } -AbstractMetaEnumValue *AbstractMetaEnumValueList::find(const QString &name) const -{ - for (int i = 0; i < size(); ++i) { - if (name == at(i)->name()) - return at(i); - } - return 0; -} - AbstractMetaEnumValue *AbstractMetaClass::findEnumValue(const AbstractMetaClassList &classes, const QString &name) { - QStringList lst = name.split(QLatin1String("::")); + const QVector<QStringRef> lst = name.splitRef(QLatin1String("::")); if (lst.size() > 1) { - QString prefixName = lst.at(0); - QString enumName = lst.at(1); - - AbstractMetaClass* cl = findClass(classes, prefixName); - if (cl) - return cl->findEnumValue(enumName, 0); + const QStringRef prefixName = lst.at(0); + const QStringRef enumName = lst.at(1); + if (AbstractMetaClass *cl = findClass(classes, prefixName.toString())) + return cl->findEnumValue(enumName.toString()); } - foreach (AbstractMetaClass* metaClass, classes) { - foreach(AbstractMetaEnum* metaEnum, metaClass->enums()) { - AbstractMetaEnumValue* enumValue = metaClass->findEnumValue(name, metaEnum); - if (enumValue) - return enumValue; - } + for (AbstractMetaClass *metaClass : classes) { + if (AbstractMetaEnumValue *enumValue = metaClass->findEnumValue(name)) + return enumValue; } qCWarning(lcShiboken).noquote().nospace() << QStringLiteral("no matching enum '%1'").arg(name); - return 0; + return nullptr; } /*! @@ -2688,17 +2327,17 @@ AbstractMetaClass *AbstractMetaClass::findClass(const AbstractMetaClassList &cla if (name.isEmpty()) return 0; - foreach (AbstractMetaClass *c, classes) { + for (AbstractMetaClass *c : classes) { if (c->qualifiedCppName() == name) return c; } - foreach (AbstractMetaClass *c, classes) { + for (AbstractMetaClass *c : classes) { if (c->fullName() == name) return c; } - foreach (AbstractMetaClass *c, classes) { + for (AbstractMetaClass *c : classes) { if (c->name() == name) return c; } @@ -2709,7 +2348,7 @@ AbstractMetaClass *AbstractMetaClass::findClass(const AbstractMetaClassList &cla AbstractMetaClass *AbstractMetaClass::findClass(const AbstractMetaClassList &classes, const TypeEntry* typeEntry) { - foreach (AbstractMetaClass* c, classes) { + for (AbstractMetaClass* c : classes) { if (c->typeEntry() == typeEntry) return c; } @@ -2725,6 +2364,8 @@ QDebug operator<<(QDebug d, const AbstractMetaClass *ac) d << "AbstractMetaClass("; if (ac) { d << '"' << ac->fullName() << '"'; + if (ac->attributes() & AbstractMetaAttributes::FinalCppClass) + d << " [final]"; if (ac->m_baseClass) d << ", inherits \"" << ac->m_baseClass->name() << '"'; const AbstractMetaEnumList &enums = ac->enums(); @@ -2765,6 +2406,43 @@ QDebug operator<<(QDebug d, const AbstractMetaClass *ac) } #endif // !QT_NO_DEBUG_STREAM +/******************************************************************************* +* AbstractMetaEnum +*/ + +AbstractMetaEnum::AbstractMetaEnum() : + m_hasQenumsDeclaration(false) +{ +} + +AbstractMetaEnum::~AbstractMetaEnum() +{ + qDeleteAll(m_enumValues); +} + +template <class String> +AbstractMetaEnumValue *findMatchingEnumValue(const AbstractMetaEnumValueList &list, const String &value) +{ + for (AbstractMetaEnumValue *enumValue : list) { + if (enumValue->name() == value) + return enumValue; + } + return nullptr; +} + +// Find enum values for "enum Enum { e1 }" either for "e1" or "Enum::e1" +AbstractMetaEnumValue *AbstractMetaEnum::findEnumValue(const QString &value) const +{ + if (isAnonymous()) + return findMatchingEnumValue(m_enumValues, value); + const int sepPos = value.indexOf(QLatin1String("::")); + if (sepPos == -1) + return findMatchingEnumValue(m_enumValues, value); + return name() == value.leftRef(sepPos) + ? findMatchingEnumValue(m_enumValues, value.rightRef(value.size() - sepPos - 2)) + : nullptr; +} + QString AbstractMetaEnum::name() const { return m_typeEntry->targetLangName(); diff --git a/sources/shiboken2/ApiExtractor/abstractmetalang.h b/sources/shiboken2/ApiExtractor/abstractmetalang.h index 26702d3a2..45a55e570 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetalang.h +++ b/sources/shiboken2/ApiExtractor/abstractmetalang.h @@ -71,11 +71,12 @@ public: Target }; - Documentation() - : m_format(Documentation::Native) {} + Documentation() {} Documentation(const QString& value, Format fmt = Documentation::Native) - : m_data(value), m_format(fmt) {} + : m_data(value.trimmed()), m_format(fmt) {} + + bool isEmpty() const { return m_data.isEmpty(); } QString value() const { @@ -84,7 +85,8 @@ public: void setValue(const QString& value, Format fmt = Documentation::Native) { - m_data = value; m_format = fmt; + m_data = value.trimmed(); + m_format = fmt; } Documentation::Format format() const @@ -94,15 +96,17 @@ public: private: QString m_data; - Format m_format; + Format m_format = Documentation::Native; }; class AbstractMetaAttributes { + Q_DISABLE_COPY(AbstractMetaAttributes) Q_GADGET public: - AbstractMetaAttributes() : m_attributes(0), m_originalAttributes(0) {}; + AbstractMetaAttributes(); + virtual ~AbstractMetaAttributes(); enum Attribute { None = 0x00000000, @@ -113,29 +117,26 @@ public: Friendly = 0x00000008, Visibility = 0x0000000f, - Native = 0x00000010, Abstract = 0x00000020, Static = 0x00000040, FinalInTargetLang = 0x00000080, - FinalInCpp = 0x00000100, - ForceShellImplementation = 0x00000200, GetterFunction = 0x00000400, SetterFunction = 0x00000800, - FinalOverload = 0x00001000, - InterfaceFunction = 0x00002000, - PropertyReader = 0x00004000, PropertyWriter = 0x00008000, PropertyResetter = 0x00010000, - Fake = 0x00020000, - Invokable = 0x00040000, - Final = FinalInTargetLang | FinalInCpp + HasRejectedConstructor = 0x00080000, + + FinalCppClass = 0x00100000, + VirtualCppMethod = 0x00200000, + OverriddenCppMethod = 0x00400000, + FinalCppMethod = 0x00800000 }; Q_DECLARE_FLAGS(Attributes, Attribute) Q_FLAG(Attribute) @@ -180,26 +181,11 @@ public: m_attributes &= ~attribute; } - bool isNative() const - { - return m_attributes & Native; - } - - bool isFinal() const - { - return (m_attributes & Final) == Final; - } - bool isFinalInTargetLang() const { return m_attributes & FinalInTargetLang; } - bool isFinalInCpp() const - { - return m_attributes & FinalInCpp; - } - bool isAbstract() const { return m_attributes & Abstract; @@ -210,21 +196,6 @@ public: return m_attributes & Static; } - bool isForcedShellImplementation() const - { - return m_attributes & ForceShellImplementation; - } - - bool isInterfaceFunction() const - { - return m_attributes & InterfaceFunction; - } - - bool isFinalOverload() const - { - return m_attributes & FinalOverload; - } - bool isInvokable() const { return m_attributes & Invokable; @@ -295,6 +266,9 @@ public: return m_doc; } +protected: + void assignMetaAttributes(const AbstractMetaAttributes &other); + private: Attributes m_attributes; Attributes m_originalAttributes; @@ -318,19 +292,15 @@ public: FlagsPattern, EnumPattern, ValuePattern, - StringPattern, - CharPattern, ObjectPattern, QObjectPattern, ValuePointerPattern, NativePointerPattern, + NativePointerAsArrayPattern, // "int*" as "int[]" ContainerPattern, SmartPointerPattern, - VariantPattern, VarargsPattern, - JObjectWrapperPattern, - ArrayPattern, - ThreadPattern + ArrayPattern }; Q_ENUM(TypeUsagePattern) @@ -381,15 +351,8 @@ public: { m_cppInstantiation = incpp; } - bool hasInstantiationInCpp() const - { - return hasInstantiations() && m_cppInstantiation; - } - - QString minimalSignature() const; - // true when the type is a QtJambiObject subclass - bool hasNativeId() const; + QString minimalSignature() const { return formatSignature(true); } // returns true if the typs is used as a non complex primitive, no & or *'s bool isPrimitive() const @@ -397,6 +360,8 @@ public: return m_pattern == PrimitivePattern; } + bool isCppPrimitive() const; + // returns true if the type is used as an enum bool isEnum() const { @@ -438,36 +403,12 @@ public: return m_pattern == NativePointerPattern; } - // returns true if the type was originally a QString or const QString & or equivalent for QLatin1String - bool isTargetLangString() const - { - return m_pattern == StringPattern; - } - - // returns true if the type was originally a QChar or const QChar & - bool isTargetLangChar() const - { - return m_pattern == CharPattern; - } - - // return true if the type was originally a QVariant or const QVariant & - bool isVariant() const - { - return m_pattern == VariantPattern; - } - // return true if the type was originally a varargs bool isVarargs() const { return m_pattern == VarargsPattern; } - // return true if the type was originally a JObjectWrapper or const JObjectWrapper & - bool isJObjectWrapper() const - { - return m_pattern == JObjectWrapperPattern; - } - // returns true if the type was used as a container bool isContainer() const { @@ -483,12 +424,6 @@ public: return m_pattern == FlagsPattern; } - // returns true if the type was used as a thread - bool isThread() const - { - return m_pattern == ThreadPattern; - } - bool isConstant() const { return m_constant; @@ -501,30 +436,6 @@ public: ReferenceType referenceType() const { return m_referenceType; } void setReferenceType(ReferenceType ref) { m_referenceType = ref; } - /** - * Says if the type is to be implemented using target language - * equivalent of C++ enums, i.e. not plain ints. - * /return true if the type is to be implemented using target - * language enums - */ - bool isTargetLangEnum() const; - bool isIntegerEnum() const - { - return isEnum() && !isTargetLangEnum(); - } - - /** - * Says if the type is to be implemented using target language - * equivalent of Qt's QFlags, i.e. not plain ints. - * /return true if the type is to be implemented using target - * language QFlags - */ - bool isTargetLangFlags() const; - bool isIntegerFlags() const - { - return isFlags() && !isTargetLangFlags(); - } - int actualIndirections() const { return m_indirections + (m_referenceType == LValueReference ? 1 : 0); @@ -556,6 +467,8 @@ public: m_arrayElementType = t; } + AbstractMetaTypeCList nestedArrayTypes() const; + QString cppSignature() const; AbstractMetaType *copy() const; @@ -611,27 +524,28 @@ public: private: TypeUsagePattern determineUsagePattern() const; + QString formatSignature(bool minimal) const; - const TypeEntry *m_typeEntry; + const TypeEntry *m_typeEntry = nullptr; AbstractMetaTypeList m_instantiations; QString m_package; mutable QString m_name; mutable QString m_cachedCppSignature; QString m_originalTypeDescription; - int m_arrayElementCount; - const AbstractMetaType *m_arrayElementType; - const AbstractMetaType *m_originalTemplateType; + int m_arrayElementCount = -1; + const AbstractMetaType *m_arrayElementType = nullptr; + const AbstractMetaType *m_originalTemplateType = nullptr; - TypeUsagePattern m_pattern; + TypeUsagePattern m_pattern = InvalidPattern; uint m_constant : 1; uint m_cppInstantiation : 1; int m_indirections : 4; uint m_reserved : 26; // unused - ReferenceType m_referenceType; + ReferenceType m_referenceType = NoReference; AbstractMetaTypeList m_children; - Q_DISABLE_COPY(AbstractMetaType); + Q_DISABLE_COPY(AbstractMetaType) }; #ifndef QT_NO_DEBUG_STREAM @@ -640,14 +554,11 @@ QDebug operator<<(QDebug d, const AbstractMetaType *at); class AbstractMetaVariable { + Q_DISABLE_COPY(AbstractMetaVariable) public: - AbstractMetaVariable() : m_type(0), m_hasName(false) {} - AbstractMetaVariable(const AbstractMetaVariable &other); + AbstractMetaVariable(); - virtual ~AbstractMetaVariable() - { - delete m_type; - } + virtual ~AbstractMetaVariable(); AbstractMetaType *type() const { @@ -695,11 +606,14 @@ public: return m_doc; } +protected: + void assignMetaVariable(const AbstractMetaVariable &other); + private: QString m_originalName; QString m_name; - AbstractMetaType *m_type; - bool m_hasName; + AbstractMetaType *m_type = nullptr; + bool m_hasName = false; Documentation m_doc; }; @@ -711,7 +625,7 @@ QDebug operator<<(QDebug d, const AbstractMetaVariable *av); class AbstractMetaArgument : public AbstractMetaVariable { public: - AbstractMetaArgument() : m_argumentIndex(0) {}; + AbstractMetaArgument(); QString defaultValueExpression() const { @@ -747,10 +661,14 @@ public: } AbstractMetaArgument *copy() const; + +protected: + void assignMetaArgument(const AbstractMetaArgument &other); + private: QString m_expression; QString m_originalExpression; - int m_argumentIndex; + int m_argumentIndex = 0; friend class AbstractMetaClass; }; @@ -787,9 +705,9 @@ public: AbstractMetaField *copy() const; private: - mutable AbstractMetaFunction *m_getter; - mutable AbstractMetaFunction *m_setter; - const AbstractMetaClass *m_class; + mutable AbstractMetaFunction *m_getter = nullptr; + mutable AbstractMetaFunction *m_setter = nullptr; + const AbstractMetaClass *m_class = nullptr; }; #ifndef QT_NO_DEBUG_STREAM @@ -833,24 +751,7 @@ public: Q_DECLARE_FLAGS(CompareResult, CompareResultFlag) Q_FLAG(CompareResultFlag) - AbstractMetaFunction() - : m_typeEntry(0), - m_functionType(NormalFunction), - m_type(0), - m_class(0), - m_implementingClass(0), - m_declaringClass(0), - m_propertySpec(0), - m_constant(false), - m_invalid(false), - m_reverse(false), - m_userAdded(false), - m_explicit(false), - m_pointerOperator(false), - m_isCallOperator(false) - { - } - + AbstractMetaFunction(); ~AbstractMetaFunction(); QString name() const @@ -941,29 +842,14 @@ public: bool isBinaryOperator() const { return arityOfOperator() == 2; } bool isInplaceOperator() const; - // TODO: ths function *should* know if it is virtual - // instead of asking to your implementing class. bool isVirtual() const; - bool isThread() const; bool allowThread() const; QString modifiedName() const; QString minimalSignature() const; + QString debugSignature() const; // including virtual/override/final, etc., for debugging only. QStringList possibleIntrospectionCompatibleSignatures() const; - QString marshalledName() const; - - // true if one or more of the arguments are of QtJambiObject subclasses - bool argumentsHaveNativeId() const - { - foreach (const AbstractMetaArgument *arg, m_arguments) { - if (arg->type()->hasNativeId()) - return true; - } - - return false; - } - bool isModifiedRemoved(int types = TypeSystem::All) const; AbstractMetaType *type() const @@ -1013,8 +899,6 @@ public: m_implementingClass = cls; } - bool needsCallThrough() const; - AbstractMetaArgumentList arguments() const { return m_arguments; @@ -1029,14 +913,6 @@ public: } int actualMinimumArgumentCount() const; - void setInvalid(bool on) - { - m_invalid = on; - } - bool isInvalid() const - { - return m_invalid; - } bool isDeprecated() const; bool isDestructor() const { @@ -1079,15 +955,6 @@ public: bool usesRValueReferences() const; QStringList introspectionCompatibleSignatures(const QStringList &resolvedArguments = QStringList()) const; QString signature() const; - QString targetLangSignature(bool minimal = false) const; - bool shouldReturnThisObject() const - { - return QLatin1String("this") == argumentReplaced(0); - } - bool shouldIgnoreReturnValue() const - { - return QLatin1String("void") == argumentReplaced(0); - } bool isConstant() const { @@ -1122,17 +989,9 @@ public: QString replacedDefaultExpression(const AbstractMetaClass *cls, int idx) const; bool removedDefaultExpression(const AbstractMetaClass *cls, int idx) const; QString conversionRule(TypeSystem::Language language, int idx) const; - QList<ReferenceCount> referenceCounts(const AbstractMetaClass *cls, int idx = -2) const; + QVector<ReferenceCount> referenceCounts(const AbstractMetaClass *cls, int idx = -2) const; ArgumentOwner argumentOwner(const AbstractMetaClass *cls, int idx) const; - bool nullPointersDisabled(const AbstractMetaClass *cls = 0, int argument_idx = 0) const; - QString nullPointerDefaultValue(const AbstractMetaClass *cls = 0, int argument_idx = 0) const; - - bool resetObjectAfterUse(int argument_idx) const; - - // Returns whether garbage collection is disabled for the argument in any context - bool disabledGarbageCollection(const AbstractMetaClass *cls, int key) const; - // Returns the ownership rules for the given argument in the given context TypeSystem::Ownership ownership(const AbstractMetaClass *cls, TypeSystem::Language language, int idx) const; @@ -1144,9 +1003,7 @@ public: bool argumentRemoved(int) const; QString argumentReplaced(int key) const; - bool needsSuppressUncheckedWarning() const; - bool hasModifications(const AbstractMetaClass *implementor) const; /** * Verifies if any modification to the function is an inject code. * \return true if there is inject code modifications to the function. @@ -1206,16 +1063,15 @@ private: mutable QString m_cachedSignature; mutable QString m_cachedModifiedName; - FunctionTypeEntry* m_typeEntry; - FunctionType m_functionType; - AbstractMetaType *m_type; - const AbstractMetaClass *m_class; - const AbstractMetaClass *m_implementingClass; - const AbstractMetaClass *m_declaringClass; - QPropertySpec *m_propertySpec; + FunctionTypeEntry* m_typeEntry = nullptr; + FunctionType m_functionType = NormalFunction; + AbstractMetaType *m_type = nullptr; + const AbstractMetaClass *m_class = nullptr; + const AbstractMetaClass *m_implementingClass = nullptr; + const AbstractMetaClass *m_declaringClass = nullptr; + QPropertySpec *m_propertySpec = nullptr; AbstractMetaArgumentList m_arguments; uint m_constant : 1; - uint m_invalid : 1; uint m_reverse : 1; uint m_userAdded : 1; uint m_explicit : 1; @@ -1232,10 +1088,7 @@ QDebug operator<<(QDebug d, const AbstractMetaFunction *af); class AbstractMetaEnumValue { public: - AbstractMetaEnumValue() - : m_valueSet(false), m_value(0) - { - } + AbstractMetaEnumValue() {} int value() const { @@ -1244,7 +1097,6 @@ public: void setValue(int value) { - m_valueSet = true; m_value = value; } @@ -1268,11 +1120,6 @@ public: m_name = name; } - bool isValueSet() const - { - return m_valueSet; - } - void setDocumentation(const Documentation& doc) { m_doc = doc; @@ -1287,27 +1134,16 @@ private: QString m_name; QString m_stringValue; - bool m_valueSet; - int m_value; + int m_value = 0; Documentation m_doc; }; - -class AbstractMetaEnumValueList : public QList<AbstractMetaEnumValue *> -{ -public: - AbstractMetaEnumValue *find(const QString &name) const; -}; - class AbstractMetaEnum : public AbstractMetaAttributes { public: - AbstractMetaEnum() : m_typeEntry(0), m_class(0), m_hasQenumsDeclaration(false) {} - ~AbstractMetaEnum() - { - qDeleteAll(m_enumValues); - } + AbstractMetaEnum(); + ~AbstractMetaEnum(); AbstractMetaEnumValueList values() const { @@ -1319,6 +1155,8 @@ public: m_enumValues << enumValue; } + AbstractMetaEnumValue *findEnumValue(const QString &value) const; + QString name() const; QString qualifier() const; @@ -1365,8 +1203,8 @@ public: private: AbstractMetaEnumValueList m_enumValues; - EnumTypeEntry *m_typeEntry; - AbstractMetaClass *m_class; + EnumTypeEntry *m_typeEntry = nullptr; + AbstractMetaClass *m_class = nullptr; uint m_hasQenumsDeclaration : 1; }; @@ -1382,29 +1220,19 @@ public: enum FunctionQueryOption { Constructors = 0x0000001, // Only constructors //Destructors = 0x0000002, // Only destructors. Not included in class. - VirtualFunctions = 0x0000004, // Only virtual functions (virtual in both TargetLang and C++) FinalInTargetLangFunctions = 0x0000008, // Only functions that are non-virtual in TargetLang - FinalInCppFunctions = 0x0000010, // Only functions that are non-virtual in C++ ClassImplements = 0x0000020, // Only functions implemented by the current class - Inconsistent = 0x0000040, // Only inconsistent functions (inconsistent virtualness in TargetLang/C++) StaticFunctions = 0x0000080, // Only static functions Signals = 0x0000100, // Only signals NormalFunctions = 0x0000200, // Only functions that aren't signals Visible = 0x0000400, // Only public and protected functions - ForcedShellFunctions = 0x0000800, // Only functions that are overridden to be implemented in the shell class WasPublic = 0x0001000, // Only functions that were originally public - WasProtected = 0x0002000, // Only functions that were originally protected NonStaticFunctions = 0x0004000, // No static functions Empty = 0x0008000, // Empty overrides of abstract functions Invisible = 0x0010000, // Only private functions VirtualInCppFunctions = 0x0020000, // Only functions that are virtual in C++ - NonEmptyFunctions = 0x0040000, // Only functions with target language API implementations VirtualInTargetLangFunctions = 0x0080000, // Only functions which are virtual in TargetLang - AbstractFunctions = 0x0100000, // Only abstract functions - WasVisible = 0x0200000, // Only functions that were public or protected in the original code NotRemovedFromTargetLang = 0x0400000, // Only functions that have not been removed from TargetLang - NotRemovedFromShell = 0x0800000, // Only functions that have not been removed from the shell class - VirtualSlots = 0x1000000, // Only functions that are set as virtual slots in the type system OperatorOverloads = 0x2000000 // Only functions that are operator overloads }; Q_DECLARE_FLAGS(FunctionQueryOptions, FunctionQueryOption) @@ -1426,32 +1254,8 @@ public: Q_DECLARE_FLAGS(OperatorQueryOptions, OperatorQueryOption) Q_FLAG(OperatorQueryOption) - AbstractMetaClass() - : m_hasVirtuals(false), - m_isPolymorphic(false), - m_hasNonpublic(false), - m_hasVirtualSlots(false), - m_hasNonPrivateConstructor(false), - m_functionsFixed(false), - m_hasPrivateDestructor(false), - m_hasProtectedDestructor(false), - m_hasVirtualDestructor(false), - m_forceShellClass(false), - m_hasHashFunction(false), - m_hasEqualsOperator(false), - m_hasCloneOperator(false), - m_isTypeDef(false), - m_hasToStringCapability(false), - m_enclosingClass(0), - m_baseClass(0), - m_templateBaseClass(0), - m_extractedInterface(0), - m_typeEntry(0), - m_stream(false) - { - } - - virtual ~AbstractMetaClass(); + AbstractMetaClass(); + ~AbstractMetaClass(); AbstractMetaClass *extractInterface(); void fixFunctions(); @@ -1485,6 +1289,16 @@ public: m_hasNonPrivateConstructor = value; } + bool hasPrivateConstructor() const + { + return m_hasPrivateConstructor; + } + + void setHasPrivateConstructor(bool value) + { + m_hasPrivateConstructor = value; + } + bool hasPrivateDestructor() const { return m_hasPrivateDestructor; @@ -1515,14 +1329,15 @@ public: m_hasVirtualDestructor = value; } + bool isConstructible() const + { + return (hasNonPrivateConstructor() || !hasPrivateConstructor()) && !hasPrivateDestructor(); + } + AbstractMetaFunctionList queryFunctionsByName(const QString &name) const; AbstractMetaFunctionList queryFunctions(FunctionQueryOptions query) const; AbstractMetaFunctionList functionsInTargetLang() const; - AbstractMetaFunctionList functionsInShellClass() const; inline AbstractMetaFunctionList cppSignalFunctions() const; - AbstractMetaFunctionList publicOverrideFunctions() const; - AbstractMetaFunctionList virtualOverrideFunctions() const; - AbstractMetaFunctionList virtualFunctions() const; AbstractMetaFunctionList implicitConversions() const; /** @@ -1535,14 +1350,10 @@ public: */ AbstractMetaFunctionList operatorOverloads(OperatorQueryOptions query = AllOperators) const; - bool hasOperatorOverload() const; bool hasArithmeticOperatorOverload() const; bool hasBitwiseOperatorOverload() const; bool hasComparisonOperatorOverload() const; bool hasLogicalOperatorOverload() const; - bool hasSubscriptOperatorOverload() const; - bool hasAssignmentOperatorOverload() const; - bool hasConversionOperatorOverload() const; AbstractMetaFieldList fields() const { @@ -1574,8 +1385,7 @@ public: } AbstractMetaEnum *findEnum(const QString &enumName); - AbstractMetaEnum *findEnumForValue(const QString &enumName); - AbstractMetaEnumValue *findEnumValue(const QString &enumName, AbstractMetaEnum *meta_enum); + AbstractMetaEnumValue *findEnumValue(const QString &enumName); AbstractMetaClassList interfaces() const { @@ -1655,22 +1465,12 @@ public: m_forceShellClass = on; } - bool generateShellClass() const; - bool hasVirtualSlots() const { return m_hasVirtualSlots; } /** - * Says if a class has any virtual functions of its own. - * \return true if the class implements any virtual methods - */ - bool hasVirtualFunctions() const - { - return !isFinal() && m_hasVirtuals; - } - /** * Says if the class that declares or inherits a virtual function. * \return true if the class implements or inherits any virtual methods */ @@ -1698,12 +1498,12 @@ public: bool hasProtectedMembers() const; - QList<TypeEntry *> templateArguments() const + QVector<TypeEntry *> templateArguments() const { return m_templateArgs; } - void setTemplateArguments(const QList<TypeEntry *> &args) + void setTemplateArguments(const QVector<TypeEntry *> &args) { m_templateArgs = args; } @@ -1772,7 +1572,7 @@ public: m_propertySpecs << spec; } - QList<QPropertySpec *> propertySpecs() const + QVector<QPropertySpec *> propertySpecs() const { return m_propertySpecs; } @@ -1855,6 +1655,7 @@ private: uint m_hasNonpublic : 1; uint m_hasVirtualSlots : 1; uint m_hasNonPrivateConstructor : 1; + uint m_hasPrivateConstructor : 1; uint m_functionsFixed : 1; uint m_hasPrivateDestructor : 1; uint m_hasProtectedDestructor : 1; @@ -1866,25 +1667,25 @@ private: uint m_isTypeDef : 1; uint m_hasToStringCapability : 1; - const AbstractMetaClass *m_enclosingClass; - AbstractMetaClass *m_baseClass; - const AbstractMetaClass *m_templateBaseClass; + const AbstractMetaClass *m_enclosingClass = nullptr; + AbstractMetaClass *m_baseClass = nullptr; + const AbstractMetaClass *m_templateBaseClass = nullptr; AbstractMetaFunctionList m_functions; AbstractMetaFieldList m_fields; AbstractMetaEnumList m_enums; AbstractMetaClassList m_interfaces; - AbstractMetaClass *m_extractedInterface; - QList<QPropertySpec *> m_propertySpecs; + AbstractMetaClass *m_extractedInterface = nullptr; + QVector<QPropertySpec *> m_propertySpecs; AbstractMetaClassList m_innerClasses; AbstractMetaFunctionList m_externalConversionOperators; QStringList m_baseClassNames; - QList<TypeEntry *> m_templateArgs; - ComplexTypeEntry *m_typeEntry; + QVector<TypeEntry *> m_templateArgs; + ComplexTypeEntry *m_typeEntry = nullptr; // FunctionModelItem m_qDebugStreamFunction; - bool m_stream; + bool m_stream = false; }; Q_DECLARE_OPERATORS_FOR_FLAGS(AbstractMetaClass::FunctionQueryOptions) @@ -1893,10 +1694,7 @@ Q_DECLARE_OPERATORS_FOR_FLAGS(AbstractMetaClass::OperatorQueryOptions) class QPropertySpec { public: - QPropertySpec(const TypeEntry *type) - : m_type(type), - m_index(-1) - {} + explicit QPropertySpec(const TypeEntry *type) : m_type(type) {} const TypeEntry *type() const { @@ -1970,7 +1768,7 @@ private: QString m_designable; QString m_reset; const TypeEntry *m_type; - int m_index; + int m_index = -1; }; inline AbstractMetaFunctionList AbstractMetaClass::cppSignalFunctions() const diff --git a/sources/shiboken2/ApiExtractor/abstractmetalang_typedefs.h b/sources/shiboken2/ApiExtractor/abstractmetalang_typedefs.h index dd6573b78..6522ba2dd 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetalang_typedefs.h +++ b/sources/shiboken2/ApiExtractor/abstractmetalang_typedefs.h @@ -29,21 +29,23 @@ #ifndef ABSTRACTMETALANG_TYPEDEFS_H #define ABSTRACTMETALANG_TYPEDEFS_H -#include <QtCore/QList> +#include <QtCore/QVector> class AbstractMetaClass; class AbstractMetaField; class AbstractMetaArgument; class AbstractMetaEnum; -class AbstractMetaEnumValueList; +class AbstractMetaEnumValue; class AbstractMetaFunction; class AbstractMetaType; -typedef QList<AbstractMetaArgument *> AbstractMetaArgumentList; -typedef QList<AbstractMetaClass *> AbstractMetaClassList; -typedef QList<AbstractMetaEnum *> AbstractMetaEnumList; -typedef QList<AbstractMetaField *> AbstractMetaFieldList; -typedef QList<AbstractMetaFunction *> AbstractMetaFunctionList; -typedef QList<AbstractMetaType *> AbstractMetaTypeList; +typedef QVector<AbstractMetaArgument *> AbstractMetaArgumentList; +typedef QVector<AbstractMetaClass *> AbstractMetaClassList; +typedef QVector<AbstractMetaEnum *> AbstractMetaEnumList; +typedef QVector<AbstractMetaEnumValue *> AbstractMetaEnumValueList; +typedef QVector<AbstractMetaField *> AbstractMetaFieldList; +typedef QVector<AbstractMetaFunction *> AbstractMetaFunctionList; +typedef QVector<AbstractMetaType *> AbstractMetaTypeList; +typedef QVector<const AbstractMetaType *> AbstractMetaTypeCList; #endif // ABSTRACTMETALANG_TYPEDEFS_H diff --git a/sources/shiboken2/ApiExtractor/apiextractor.cpp b/sources/shiboken2/ApiExtractor/apiextractor.cpp index 371ccf559..6508d378a 100644 --- a/sources/shiboken2/ApiExtractor/apiextractor.cpp +++ b/sources/shiboken2/ApiExtractor/apiextractor.cpp @@ -32,27 +32,21 @@ #include <QDir> #include <QDebug> #include <QTemporaryFile> +#include <algorithm> #include <iostream> +#include <iterator> #include "reporthandler.h" #include "typesystem.h" #include "fileout.h" -#include "parser/rpp/pp.h" #include "abstractmetabuilder.h" #include "typedatabase.h" #include "typesystem.h" -static bool preprocess(const QString& sourceFile, - QFile& targetFile, - const QStringList& includes); - ApiExtractor::ApiExtractor() : m_builder(0) { - static bool qrcInitialized = false; - if (!qrcInitialized) - Q_INIT_RESOURCE(generator); // Environment TYPESYSTEMPATH - QString envTypesystemPaths = QFile::decodeName(getenv("TYPESYSTEMPATH")); + QString envTypesystemPaths = QFile::decodeName(qgetenv("TYPESYSTEMPATH")); if (!envTypesystemPaths.isEmpty()) TypeDatabase::instance()->addTypesystemPath(envTypesystemPaths); } @@ -69,16 +63,16 @@ void ApiExtractor::addTypesystemSearchPath (const QString& path) void ApiExtractor::addTypesystemSearchPath(const QStringList& paths) { - foreach (const QString &path, paths) + for (const QString &path : paths) addTypesystemSearchPath(path); } -void ApiExtractor::addIncludePath(const QString& path) +void ApiExtractor::addIncludePath(const HeaderPath& path) { m_includePaths << path; } -void ApiExtractor::addIncludePath(const QStringList& paths) +void ApiExtractor::addIncludePath(const HeaderPaths& paths) { m_includePaths << paths; } @@ -174,8 +168,9 @@ QSet<QString> ApiExtractor::qtMetaTypeDeclaredTypeNames() const static const AbstractMetaEnum* findEnumOnClasses(AbstractMetaClassList metaClasses, const EnumTypeEntry* typeEntry) { const AbstractMetaEnum* result = 0; - foreach (const AbstractMetaClass* metaClass, metaClasses) { - foreach (const AbstractMetaEnum* metaEnum, metaClass->enums()) { + for (const AbstractMetaClass* metaClass : qAsConst(metaClasses)) { + const AbstractMetaEnumList &enums = metaClass->enums(); + for (const AbstractMetaEnum *metaEnum : enums) { if (metaEnum->typeEntry() == typeEntry) { result = metaEnum; break; @@ -192,7 +187,8 @@ const AbstractMetaEnum* ApiExtractor::findAbstractMetaEnum(const EnumTypeEntry* { if (!typeEntry) return 0; - foreach (AbstractMetaEnum* metaEnum, m_builder->globalEnums()) { + const AbstractMetaEnumList &globalEnums = m_builder->globalEnums(); + for (AbstractMetaEnum* metaEnum : globalEnums) { if (metaEnum->typeEntry() == typeEntry) return metaEnum; } @@ -235,93 +231,43 @@ bool ApiExtractor::run() if (m_builder) return false; - if (m_typeSystemFileName.isEmpty()) { - std::cerr << "You must specify a Type System file." << std::endl; - return false; - } else if (!TypeDatabase::instance()->parseFile(m_typeSystemFileName)) { + if (!TypeDatabase::instance()->parseFile(m_typeSystemFileName)) { std::cerr << "Cannot parse file: " << qPrintable(m_typeSystemFileName); return false; } - QTemporaryFile ppFile; -#ifndef NDEBUG - ppFile.setAutoRemove(false); -#endif + const QString pattern = QDir::tempPath() + QLatin1Char('/') + + QFileInfo(m_cppFileName).baseName() + QStringLiteral("_XXXXXX.hpp"); + QTemporaryFile ppFile(pattern); + bool autoRemove = !qEnvironmentVariableIsSet("KEEP_TEMP_FILES"); // make sure that a tempfile can be written if (!ppFile.open()) { - std::cerr << "could not create tempfile in " << qPrintable(QDir::tempPath()); - return false; - } - - // run rpp pre-processor - if (!preprocess(m_cppFileName, ppFile, m_includePaths)) { - std::cerr << "Preprocessor failed on file: " << qPrintable(m_cppFileName); + std::cerr << "could not create tempfile " << qPrintable(pattern) + << ": " << qPrintable(ppFile.errorString()) << '\n'; return false; } - ppFile.seek(0); + ppFile.write("#include \""); + ppFile.write(m_cppFileName.toLocal8Bit()); + ppFile.write("\"\n"); + const QString preprocessedCppFileName = ppFile.fileName(); + ppFile.close(); m_builder = new AbstractMetaBuilder; m_builder->setLogDirectory(m_logDirectory); m_builder->setGlobalHeader(m_cppFileName); - m_builder->build(&ppFile); - - return true; -} - -static bool preprocess(const QString& sourceFile, - QFile& targetFile, - const QStringList& includes) -{ - rpp::pp_environment env; - rpp::pp preprocess(env); - - rpp::pp_null_output_iterator null_out; - - const char *ppconfig = ":/trolltech/generator/pp-qt-configuration"; - - const QString fileName = QLatin1String(ppconfig); - QFile file(fileName); - if (!file.open(QFile::ReadOnly)) { - std::cerr << "Preprocessor configuration file not found " << ppconfig << std::endl; - return false; - } - - QByteArray ba = file.readAll(); - file.close(); - preprocess.operator()(ba.constData(), ba.constData() + ba.size(), null_out); - - preprocess.push_include_path("."); - foreach (const QString &include, includes) - preprocess.push_include_path(QDir::toNativeSeparators(include).toStdString()); - preprocess.push_include_path("/usr/include"); - - QString currentDir = QDir::current().absolutePath(); - QFileInfo sourceInfo(sourceFile); - if (!sourceInfo.exists()) { - std::cerr << "File not found " << qPrintable(sourceFile) << std::endl; - return false; + QByteArrayList arguments; + arguments.reserve(m_includePaths.size() + 1); + for (const HeaderPath &headerPath : qAsConst(m_includePaths)) + arguments.append(HeaderPath::includeOption(headerPath)); + arguments.append(QFile::encodeName(preprocessedCppFileName)); + qCDebug(lcShiboken) << __FUNCTION__ << arguments; + const bool result = m_builder->build(arguments); + if (!result) + autoRemove = false; + if (!autoRemove) { + ppFile.setAutoRemove(false); + std::cerr << "Keeping temporary file: " << qPrintable(QDir::toNativeSeparators(preprocessedCppFileName)) << '\n'; } - QDir::setCurrent(sourceInfo.absolutePath()); - - std::string result; - result.reserve(20 * 1024); // 20K - - result += "# 1 \"builtins\"\n"; - result += "# 1 \""; - result += sourceFile.toStdString(); - result += "\"\n"; - - preprocess.file(sourceInfo.fileName().toStdString(), - rpp::pp_output_iterator<std::string> (result)); - - QDir::setCurrent(currentDir); - - if (!targetFile.open(QIODevice::ReadWrite | QIODevice::Text)) { - std::cerr << "Failed to write preprocessed file: " << qPrintable(targetFile.fileName()) << std::endl; - return false; - } - - targetFile.write(result.c_str(), result.length()); - return true; + return result; } #ifndef QT_NO_DEBUG_STREAM diff --git a/sources/shiboken2/ApiExtractor/apiextractor.h b/sources/shiboken2/ApiExtractor/apiextractor.h index 1080ff507..ac90f5b2f 100644 --- a/sources/shiboken2/ApiExtractor/apiextractor.h +++ b/sources/shiboken2/ApiExtractor/apiextractor.h @@ -33,6 +33,8 @@ #include "dependency.h" #include "abstractmetalang_typedefs.h" #include "apiextractormacros.h" +#include "header_paths.h" +#include "typedatabase_typedefs.h" #include "typesystem_typedefs.h" #include <QStringList> @@ -67,9 +69,9 @@ public: void setSilent(bool value); void addTypesystemSearchPath(const QString& path); void addTypesystemSearchPath(const QStringList& paths); - void addIncludePath(const QString& path); - void addIncludePath(const QStringList& paths); - QStringList includePaths() const { return m_includePaths; } + void addIncludePath(const HeaderPath& path); + void addIncludePath(const HeaderPaths& paths); + HeaderPaths includePaths() const { return m_includePaths; } void setLogDirectory(const QString& logDir); bool setApiVersion(const QString& package, const QString& version); void setDropTypeEntries(QString dropEntries); @@ -94,7 +96,7 @@ public: private: QString m_typeSystemFileName; QString m_cppFileName; - QStringList m_includePaths; + HeaderPaths m_includePaths; AbstractMetaBuilder* m_builder; QString m_logDirectory; diff --git a/sources/shiboken2/ApiExtractor/asttoxml.cpp b/sources/shiboken2/ApiExtractor/asttoxml.cpp deleted file mode 100644 index 7a2f1261e..000000000 --- a/sources/shiboken2/ApiExtractor/asttoxml.cpp +++ /dev/null @@ -1,160 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "asttoxml.h" -#include "parser/control.h" -#include "parser/parser.h" -#include "parser/binder.h" - - -#include <QtCore/QXmlStreamWriter> -#include <QtCore/QTextStream> -#include <QtCore/QTextCodec> -#include <QtCore/QFile> - -typedef QHash<QString, EnumModelItem> EnumMap; -typedef QHash<QString, FunctionModelItem> FunctionModelItemMap; -typedef QHash<QString, ClassModelItem> ClassModelItemMap; -typedef QHash<QString, NamespaceModelItem> NamespaceModelItemMap; - -void astToXML(QString name) -{ - QFile file(name); - - if (!file.open(QFile::ReadOnly)) - return; - - QTextStream stream(&file); - stream.setCodec(QTextCodec::codecForName("UTF-8")); - QByteArray contents = stream.readAll().toUtf8(); - file.close(); - - Control control; - Parser p(&control); - pool __pool; - - TranslationUnitAST *ast = p.parse(contents, contents.size(), &__pool); - - CodeModel model; - Binder binder(&model, p.location()); - FileModelItem dom = binder.run(ast); - - QFile outputFile; - if (!outputFile.open(stdout, QIODevice::WriteOnly)) - return; - - QXmlStreamWriter s(&outputFile); - s.setAutoFormatting(true); - - s.writeStartElement(QLatin1String("code")); - - const NamespaceList &namespaces = dom->namespaces(); - foreach (const NamespaceModelItem &n, namespaces) - writeOutNamespace(s, n); - - const ClassList &classList = dom->classes(); - foreach (const ClassModelItem &c, classList) - writeOutClass(s, c); - - s.writeEndElement(); -} - -void writeOutNamespace(QXmlStreamWriter &s, const NamespaceModelItem &item) -{ - s.writeStartElement(QLatin1String("namespace")); - s.writeAttribute(QLatin1String("name"), item->name()); - - const NamespaceList &namespaces = item->namespaces(); - foreach (const NamespaceModelItem &n, namespaces) - writeOutNamespace(s, n); - - const ClassList &classList = item->classes(); - foreach (const ClassModelItem &c, classList) - writeOutClass(s, c); - - const EnumList &enums = item->enums(); - foreach (const EnumModelItem &e, enums) - writeOutEnum(s, e); - - s.writeEndElement(); -} - -void writeOutEnum(QXmlStreamWriter &s, const EnumModelItem &item) -{ - QString qualifiedName = item->qualifiedName().join(QLatin1String("::")); - s.writeStartElement(QLatin1String("enum")); - s.writeAttribute(QLatin1String("name"), qualifiedName); - - EnumeratorList enumList = item->enumerators(); - for (int i = 0; i < enumList.size() ; i++) { - s.writeStartElement(QLatin1String("enumerator")); - if (!enumList[i]->value().isEmpty()) - s.writeAttribute(QLatin1String("value"), enumList[i]->value()); - s.writeCharacters(enumList[i]->name()); - - s.writeEndElement(); - } - s.writeEndElement(); -} - -void writeOutFunction(QXmlStreamWriter &s, const FunctionModelItem &item) -{ - QString qualifiedName = item->qualifiedName().join(QLatin1String("::")); - s.writeStartElement(QLatin1String("function")); - s.writeAttribute(QLatin1String("name"), qualifiedName); - - ArgumentList arguments = item->arguments(); - for (int i = 0; i < arguments.size() ; i++) { - s.writeStartElement(QLatin1String("argument")); - s.writeAttribute(QLatin1String("type"), arguments[i]->type().qualifiedName().join(QLatin1String("::"))); - s.writeEndElement(); - } - s.writeEndElement(); -} - -void writeOutClass(QXmlStreamWriter &s, const ClassModelItem &item) -{ - QString qualifiedName = item->qualifiedName().join(QLatin1String("::")); - s.writeStartElement(QLatin1String("class")); - s.writeAttribute(QLatin1String("name"), qualifiedName); - - const EnumList &enums = item->enums(); - foreach (const EnumModelItem &e, enums) - writeOutEnum(s, e); - - const FunctionList &functionList = item->functions(); - foreach (const FunctionModelItem &func, functionList) - writeOutFunction(s, func); - - const ClassList &classList = item->classes(); - foreach (const ClassModelItem &c, classList) - writeOutClass(s, c); - - s.writeEndElement(); -} - diff --git a/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.cpp b/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.cpp new file mode 100644 index 000000000..1ed054d91 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.cpp @@ -0,0 +1,858 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "clangbuilder.h" +#include "compilersupport.h" +#include "clangutils.h" + +#include <codemodel.h> + +#include <QtCore/QDebug> +#include <QtCore/QDir> +#include <QtCore/QHash> +#include <QtCore/QMap> +#include <QtCore/QString> +#include <QtCore/QStack> +#include <QtCore/QVector> + +#include <string.h> + +#if QT_VERSION < 0x050800 +# define Q_FALLTHROUGH() (void)0 +#endif + +namespace clang { + +static inline QString colonColon() { return QStringLiteral("::"); } +static inline QString templateBrackets() { return QStringLiteral("<>"); } + +static inline bool isClassCursor(const CXCursor &c) +{ + return c.kind == CXCursor_ClassDecl || c.kind == CXCursor_StructDecl + || c.kind == CXCursor_ClassTemplate + || c.kind == CXCursor_ClassTemplatePartialSpecialization; +} + +static inline bool withinClassDeclaration(const CXCursor &cursor) +{ + return isClassCursor(clang_getCursorLexicalParent(cursor)); +} + +static QString fixTypeName(QString t) +{ + // Fix "Foo &" -> "Foo&", similarly "Bar **" -> "Bar**" + int pos = t.size() - 1; + for (; pos >= 0 && (t.at(pos) == QLatin1Char('&') || t.at(pos) == QLatin1Char('*')); --pos) {} + if (pos > 0 && t.at(pos) == QLatin1Char(' ')) + t.remove(pos, 1); + return t; +} + +// Insert template parameter to class name: "Foo<>" -> "Foo<T1>" -> "Foo<T1,T2>" +// This needs to be done immediately when template parameters are encountered since +// the class name "Foo<T1,T2>" is the scope for nested items. +static bool insertTemplateParameterIntoClassName(const QString &parmName, QString *name) +{ + if (Q_UNLIKELY(!name->endsWith(QLatin1Char('>')))) + return false; + const bool needsComma = name->at(name->size() - 2) != QLatin1Char('<'); + const int insertionPos = name->size() - 1; + name->insert(insertionPos, parmName); + if (needsComma) + name->insert(insertionPos, QLatin1Char(',')); + return true; +} + +static inline bool insertTemplateParameterIntoClassName(const QString &parmName, + const ClassModelItem &item) +{ + QString name = item->name(); + const bool result = insertTemplateParameterIntoClassName(parmName, &name); + item->setName(name); + return result; +} + +static inline CodeModel::AccessPolicy accessPolicy(CX_CXXAccessSpecifier access) +{ + CodeModel::AccessPolicy result = CodeModel::Public; + switch (access) { + case CX_CXXProtected: + result = CodeModel::Protected; + break; + case CX_CXXPrivate: + result = CodeModel::Private; + break; + default: + break; + } + return result; +} + +static void setFileName(const CXCursor &cursor, _CodeModelItem *item) +{ + const SourceRange range = getCursorRange(cursor); + if (!range.first.file.isEmpty()) { // Has been observed to be 0 for invalid locations + item->setFileName(QDir::cleanPath(range.first.file)); + item->setStartPosition(int(range.first.line), int(range.first.column)); + item->setEndPosition(int(range.second.line), int(range.second.column)); + } +} + +class BuilderPrivate { +public: + typedef QHash<CXCursor, ClassModelItem> CursorClassHash; + typedef QHash<CXCursor, TypeDefModelItem> CursorTypedefHash; + + explicit BuilderPrivate(BaseVisitor *bv) : m_baseVisitor(bv), m_model(new CodeModel) + { + m_scopeStack.push(NamespaceModelItem(new _FileModelItem(m_model))); + } + + // Determine scope from top item. Note that the scope list does not necessarily + // match the scope stack in case of forward-declared inner classes whose definition + // appears in the translation unit while the scope is the outer class. + void updateScope() + { + if (m_scopeStack.size() <= 1) + m_scope.clear(); + else + m_scope = m_scopeStack.back()->scope() << m_scopeStack.back()->name(); + } + + void pushScope(const ScopeModelItem &i) + { + m_scopeStack.push(i); + updateScope(); + } + + void popScope() + { + m_scopeStack.pop(); + updateScope(); + } + + bool addClass(const CXCursor &cursor, CodeModel::ClassType t); + FunctionModelItem createFunction(const CXCursor &cursor, + CodeModel::FunctionType t = CodeModel::Normal) const; + FunctionModelItem createMemberFunction(const CXCursor &cursor) const; + void qualifyConstructor(const CXCursor &cursor); + TypeInfo createTypeInfo(const CXType &type) const; + TypeInfo createTypeInfo(const CXCursor &cursor) const + { return createTypeInfo(clang_getCursorType(cursor)); } + + TemplateParameterModelItem createTemplateParameter(const CXCursor &cursor) const; + TemplateParameterModelItem createNonTypeTemplateParameter(const CXCursor &cursor) const; + void addField(const CXCursor &cursor); + + QString cursorValueExpression(BaseVisitor *bv, const CXCursor &cursor) const; + void addBaseClass(const CXCursor &cursor); + + template <class Item> + void qualifyTypeDef(const CXCursor &typeRefCursor, const QSharedPointer<Item> &item) const; + + BaseVisitor *m_baseVisitor; + CodeModel *m_model; + + QStack<ScopeModelItem> m_scopeStack; + QStringList m_scope; + // Store all classes by cursor so that base classes can be found and inner + // classes can be correctly parented in case of forward-declared inner classes + // (QMetaObject::Connection) + CursorClassHash m_cursorClassHash; + CursorTypedefHash m_cursorTypedefHash; + + ClassModelItem m_currentClass; + EnumModelItem m_currentEnum; + FunctionModelItem m_currentFunction; + ArgumentModelItem m_currentArgument; + VariableModelItem m_currentField; + + int m_anonymousEnumCount = 0; + CodeModel::FunctionType m_currentFunctionType = CodeModel::Normal; +}; + +bool BuilderPrivate::addClass(const CXCursor &cursor, CodeModel::ClassType t) +{ + QString className = getCursorSpelling(cursor); + m_currentClass.reset(new _ClassModelItem(m_model, className)); + setFileName(cursor, m_currentClass.data()); + m_currentClass->setClassType(t); + // Some inner class? Note that it does not need to be (lexically) contained in a + // class since it is possible to forward declare an inner class: + // class QMetaObject { class Connection; } + // class QMetaObject::Connection {} + const CXCursor semPar = clang_getCursorSemanticParent(cursor); + if (isClassCursor(semPar)) { + const CursorClassHash::const_iterator it = m_cursorClassHash.constFind(semPar); + if (it == m_cursorClassHash.constEnd()) { + const QString message = QStringLiteral("Unable to find parent of inner class ") + className; + const Diagnostic d(message, cursor, CXDiagnostic_Error); + qWarning() << d; + m_baseVisitor->appendDiagnostic(d); + return false; + } + const ClassModelItem &containingClass = it.value(); + containingClass->addClass(m_currentClass); + m_currentClass->setScope(containingClass->scope() << containingClass->name()); + } else { + m_currentClass->setScope(m_scope); + m_scopeStack.back()->addClass(m_currentClass); + } + pushScope(m_currentClass); + m_cursorClassHash.insert(cursor, m_currentClass); + return true; +} + +FunctionModelItem BuilderPrivate::createFunction(const CXCursor &cursor, + CodeModel::FunctionType t) const +{ + QString name = getCursorSpelling(cursor); + // Apply type fixes to "operator X &" -> "operator X&" + if (name.startsWith(QLatin1String("operator "))) + name = fixTypeName(name); + FunctionModelItem result(new _FunctionModelItem(m_model, name)); + setFileName(cursor, result.data()); + result->setType(createTypeInfo(clang_getCursorResultType(cursor))); + result->setFunctionType(t); + result->setScope(m_scope); + result->setStatic(clang_Cursor_getStorageClass(cursor) == CX_SC_Static); + return result; +} + +static inline CodeModel::FunctionType functionTypeFromCursor(const CXCursor &cursor) +{ + CodeModel::FunctionType result = CodeModel::Normal; + switch (cursor.kind) { + case CXCursor_Constructor: + if (clang_CXXConstructor_isCopyConstructor(cursor) != 0) + result = CodeModel::CopyConstructor; + else if (clang_CXXConstructor_isMoveConstructor(cursor) != 0) + result = CodeModel::MoveConstructor; + else + result = CodeModel::Constructor; + break; + case CXCursor_Destructor: + result = CodeModel::Destructor; + break; + default: + break; + } + return result; +} + +FunctionModelItem BuilderPrivate::createMemberFunction(const CXCursor &cursor) const +{ + const CodeModel::FunctionType functionType = + m_currentFunctionType == CodeModel::Signal || m_currentFunctionType == CodeModel::Slot + ? m_currentFunctionType // by annotation + : functionTypeFromCursor(cursor); + FunctionModelItem result = createFunction(cursor, functionType); + result->setAccessPolicy(accessPolicy(clang_getCXXAccessSpecifier(cursor))); + result->setConstant(clang_CXXMethod_isConst(cursor) != 0); + result->setStatic(clang_CXXMethod_isStatic(cursor) != 0); + result->setVirtual(clang_CXXMethod_isVirtual(cursor) != 0); + result->setAbstract(clang_CXXMethod_isPureVirtual(cursor) != 0); + return result; +} + +// For CXCursor_Constructor, on endToken(). +void BuilderPrivate::qualifyConstructor(const CXCursor &cursor) +{ + // Clang does not tell us whether a constructor is explicit, preventing it + // from being used for implicit conversions. Try to guess whether a + // constructor is explicit in the C++99 sense (1 parameter) by checking for + // isConvertingConstructor() == 0. Fixme: The notion of "isConvertingConstructor" + // should be used in the code model instead of "explicit" + if (clang_CXXConstructor_isDefaultConstructor(cursor) == 0 + && m_currentFunction->arguments().size() == 1 + && clang_CXXConstructor_isCopyConstructor(cursor) == 0 + && clang_CXXConstructor_isMoveConstructor(cursor) == 0) { + m_currentFunction->setExplicit(clang_CXXConstructor_isConvertingConstructor(cursor) == 0); + } +} + +TemplateParameterModelItem BuilderPrivate::createTemplateParameter(const CXCursor &cursor) const +{ + return TemplateParameterModelItem(new _TemplateParameterModelItem(m_model, getCursorSpelling(cursor))); +} + +TemplateParameterModelItem BuilderPrivate::createNonTypeTemplateParameter(const CXCursor &cursor) const +{ + TemplateParameterModelItem result = createTemplateParameter(cursor); + result->setType(createTypeInfo(cursor)); + return result; +} + +// CXCursor_VarDecl, CXCursor_FieldDecl cursors +void BuilderPrivate::addField(const CXCursor &cursor) +{ + VariableModelItem field(new _VariableModelItem(m_model, getCursorSpelling(cursor))); + field->setAccessPolicy(accessPolicy(clang_getCXXAccessSpecifier(cursor))); + field->setScope(m_scope); + field->setType(createTypeInfo(cursor)); + field->setMutable(clang_CXXField_isMutable(cursor) != 0); + m_currentField = field; + m_scopeStack.back()->addVariable(field); +} + +// Array helpers: Parse "a[2][4]" into a list of dimensions + +struct ArrayDimensionResult +{ + QVector<QStringRef> dimensions; + int position; +}; + +static ArrayDimensionResult arrayDimensions(const QString &typeName) +{ + ArrayDimensionResult result; + result.position = typeName.indexOf(QLatin1Char('[')); + for (int openingPos = result.position; openingPos != -1; ) { + const int closingPos = typeName.indexOf(QLatin1Char(']'), openingPos + 1); + if (closingPos == -1) + break; + result.dimensions.append(typeName.midRef(openingPos + 1, closingPos - openingPos - 1)); + openingPos = typeName.indexOf(QLatin1Char('['), closingPos + 1); + } + return result; +} + +// Array helpers: Parse "a[2][4]" into a list of dimensions or "" for none +static QStringList parseArrayArgs(const CXType &type, QString *typeName) +{ + const ArrayDimensionResult dimensions = arrayDimensions(*typeName); + Q_ASSERT(!dimensions.dimensions.isEmpty()); + + QStringList result; + // get first dimension from clang, preferably. + // "a[]" is seen as pointer by Clang, set special indicator "" + const long long size = clang_getArraySize(type); + result.append(size >= 0 ? QString::number(size) : QString()); + // Parse out remaining dimensions + for (int i = 1, count = dimensions.dimensions.size(); i < count; ++i) + result.append(dimensions.dimensions.at(i).toString()); + typeName->truncate(dimensions.position); + return result; +} + +TypeInfo BuilderPrivate::createTypeInfo(const CXType &type) const +{ + if (type.kind == CXType_Pointer) { // Check for function pointers, first. + const CXType pointeeType = clang_getPointeeType(type); + const int argCount = clang_getNumArgTypes(pointeeType); + if (argCount >= 0) { + TypeInfo result = createTypeInfo(clang_getResultType(pointeeType)); + result.setFunctionPointer(true); + for (int a = 0; a < argCount; ++a) + result.addArgument(createTypeInfo(clang_getArgType(pointeeType, unsigned(a)))); + return result; + } + } + + TypeInfo typeInfo; + QString typeName = fixTypeName(getTypeName(type)); + + int indirections = 0; + // "int **" + for ( ; typeName.endsWith(QLatin1Char('*')) ; ++indirections) + typeName.chop(1); + typeInfo.setIndirections(indirections); + // "int &&" + if (typeName.endsWith(QLatin1String("&&"))) { + typeName.chop(2); + typeInfo.setReferenceType(RValueReference); + } else if (typeName.endsWith(QLatin1Char('&'))) { // "int &" + typeName.chop(1); + typeInfo.setReferenceType(LValueReference); + } + + // "int [3], int[]" + if (type.kind == CXType_ConstantArray || type.kind == CXType_IncompleteArray + || type.kind == CXType_VariableArray || type.kind == CXType_DependentSizedArray) { + typeInfo.setArrayElements(parseArrayArgs(type, &typeName)); + } + + bool isConstant = clang_isConstQualifiedType(type) != 0; + // A "char *const" parameter, is considered to be const-qualified by Clang, but + // not in the TypeInfo sense (corresponds to "char *" and not "const char *"). + if (type.kind == CXType_Pointer && isConstant && typeName.endsWith(QLatin1String("const"))) { + typeName.chop(5); + typeName = typeName.trimmed(); + isConstant = false; + } + // Clang has been observed to return false for "const int .." + if (!isConstant && typeName.startsWith(QLatin1String("const "))) { + typeName.remove(0, 6); + isConstant = true; + } + typeInfo.setConstant(isConstant); + + // clang_isVolatileQualifiedType() returns true for "volatile int", but not for "volatile int *" + if (typeName.startsWith(QLatin1String("volatile "))) { + typeName.remove(0, 9); + typeInfo.setVolatile(true); + } + + typeName = typeName.trimmed(); + + typeInfo.setQualifiedName(typeName.split(colonColon())); + // 3320:CINDEX_LINKAGE int clang_getNumArgTypes(CXType T); function ptr types? + return typeInfo; +} + +// extract an expression from the cursor via source +// CXCursor_EnumConstantDecl, ParmDecl (a = Flag1 | Flag2) +QString BuilderPrivate::cursorValueExpression(BaseVisitor *bv, const CXCursor &cursor) const +{ + BaseVisitor::CodeSnippet snippet = bv->getCodeSnippet(cursor); + const char *equalSign = std::find(snippet.first, snippet.second, '='); + if (equalSign == snippet.second) + return QString(); + ++equalSign; + return QString::fromLocal8Bit(equalSign, int(snippet.second - equalSign)).trimmed(); +} + +// Add a base class to the current class from CXCursor_CXXBaseSpecifier +void BuilderPrivate::addBaseClass(const CXCursor &cursor) +{ + const CXType inheritedType = clang_getCursorType(cursor); // Note spelling has "struct baseClass", + QString baseClassName = getTypeName(inheritedType); // use type. + const CXCursor declCursor = clang_getTypeDeclaration(inheritedType); + const CursorClassHash::const_iterator it = m_cursorClassHash.constFind(declCursor); + const CodeModel::AccessPolicy access = accessPolicy(clang_getCXXAccessSpecifier(cursor)); + if (it == m_cursorClassHash.constEnd()) { + // Set unqualified name. This happens in cases like "class X : public std::list<...>" + // "template<class T> class Foo : public T" and standard types like true_type, false_type. + m_currentClass->addBaseClass(baseClassName, access); + return; + } + // Completely qualify the class name by looking it up and taking its scope + // plus the actual baseClass stripped off any scopes. Consider: + // namespace std { + // template <class T> class vector {}; + // namespace n { + // class Foo : public vector<int> {}; + // } + // } + // should have "std::vector<int>" as base class (whereas the type of the base class is + // "std::vector<T>"). + const QStringList &baseScope = it.value()->scope(); + if (!baseScope.isEmpty()) { + const int lastSep = baseClassName.lastIndexOf(colonColon()); + if (lastSep >= 0) + baseClassName.remove(0, lastSep + colonColon().size()); + baseClassName.prepend(colonColon()); + baseClassName.prepend(baseScope.join(colonColon())); + } + m_currentClass->addBaseClass(baseClassName, access); +} + +static inline CXCursor definitionFromTypeRef(const CXCursor &typeRefCursor) +{ + Q_ASSERT(typeRefCursor.kind == CXCursor_TypeRef); + return clang_getTypeDeclaration(clang_getCursorType(typeRefCursor)); +} + +// Qualify function arguments or fields that are typedef'ed from another scope: +// enum ConversionFlag {}; +// typedef QFlags<ConversionFlag> ConversionFlags; +// class QTextCodec { +// enum ConversionFlag {}; +// typedef QFlags<ConversionFlag> ConversionFlags; +// struct ConverterState { +// explicit ConverterState(ConversionFlags); +// ^^ qualify to QTextCodec::ConversionFlags +// ConversionFlags m_flags; +// ^^ ditto + +template <class Item> // ArgumentModelItem, VariableModelItem +void BuilderPrivate::qualifyTypeDef(const CXCursor &typeRefCursor, const QSharedPointer<Item> &item) const +{ + typedef typename CursorTypedefHash::const_iterator ConstIt; + + TypeInfo type = item->type(); + if (type.qualifiedName().size() == 1) { // item's type is unqualified. + const ConstIt it = m_cursorTypedefHash.constFind(definitionFromTypeRef(typeRefCursor)); + if (it != m_cursorTypedefHash.constEnd() && !it.value()->scope().isEmpty()) { + type.setQualifiedName(it.value()->scope() + type.qualifiedName()); + item->setType(type); + } + } +} + +Builder::Builder() +{ + d = new BuilderPrivate(this); +} + +Builder::~Builder() +{ + delete d; +} + +static inline bool compareHeaderName(const char *haystack, const char *needle) +{ + const char *lastSlash = strrchr(haystack, '/'); +#ifdef Q_OS_WIN + if (lastSlash == nullptr) + lastSlash = strrchr(haystack, '\\'); +#endif + if (lastSlash == nullptr) + lastSlash = haystack; + else + ++lastSlash; +#ifdef Q_OS_WIN + return _stricmp(lastSlash, needle) == 0; +#else + return strcmp(lastSlash, needle) == 0; +#endif +} + +#ifdef Q_OS_UNIX +static bool cStringStartsWith(const char *prefix, const char *str) +{ + return strncmp(prefix, str, strlen(prefix)) == 0; +} +#endif + +bool Builder::visitLocation(const CXSourceLocation &location) const +{ + if (clang_Location_isInSystemHeader(location) == 0) + return true; + CXFile file; // void * + unsigned line; + unsigned column; + unsigned offset; + clang_getExpansionLocation(location, &file, &line, &column, &offset); + const CXString cxFileName = clang_getFileName(file); + // Has been observed to be 0 for invalid locations + if (const char *cFileName = clang_getCString(cxFileName)) { + // Resolve OpenGL typedefs although the header is considered a system header. + const bool visitHeader = compareHeaderName(cFileName, "gl.h") +#if defined(Q_OS_LINUX) || defined(Q_OS_MACOS) + || cStringStartsWith("/usr/include/stdint.h", cFileName) +#endif +#if defined(Q_OS_LINUX) + || cStringStartsWith("/usr/include/stdlib.h", cFileName) + || cStringStartsWith("/usr/include/sys/types.h", cFileName) +#elif defined(Q_OS_MACOS) + // Parse the following system headers to get the correct typdefs for types like + // int32_t, which are used in the macOS implementation of OpenGL framework. + || compareHeaderName(cFileName, "gltypes.h") + || cStringStartsWith("/usr/include/_types", cFileName) + || cStringStartsWith("/usr/include/sys/_types", cFileName) +#endif + ; + clang_disposeString(cxFileName); + if (visitHeader) + return true; + } + return false; +} + +FileModelItem Builder::dom() const +{ + Q_ASSERT(!d->m_scopeStack.isEmpty()); + return qSharedPointerDynamicCast<_FileModelItem>(d->m_scopeStack.constFirst()); +} + +static QString msgOutOfOrder(const CXCursor &cursor, const char *expectedScope) +{ + return getCursorKindName(cursor.kind) + QLatin1Char(' ') + + getCursorSpelling(cursor) + QLatin1String(" encountered outside ") + + QLatin1String(expectedScope) + QLatin1Char('.'); +} + +static CodeModel::ClassType codeModelClassTypeFromCursor(CXCursorKind kind) +{ + CodeModel::ClassType result = CodeModel::Class; + if (kind == CXCursor_UnionDecl) + result = CodeModel::Union; + else if (kind == CXCursor_StructDecl) + result = CodeModel::Struct; + return result; +} + +BaseVisitor::StartTokenResult Builder::startToken(const CXCursor &cursor) +{ + switch (cursor.kind) { + case CXCursor_CXXAccessSpecifier: + d->m_currentFunctionType = CodeModel::Normal; + break; + case CXCursor_AnnotateAttr: { + const QString annotation = getCursorSpelling(cursor); + if (annotation == QLatin1String("qt_slot")) + d->m_currentFunctionType = CodeModel::Slot; + else if (annotation == QLatin1String("qt_signal")) + d->m_currentFunctionType = CodeModel::Signal; + else + d->m_currentFunctionType = CodeModel::Normal; + } + break; + case CXCursor_CXXBaseSpecifier: + if (d->m_currentClass.isNull()) { + const Diagnostic d(msgOutOfOrder(cursor, "class"), cursor, CXDiagnostic_Error); + qWarning() << d; + appendDiagnostic(d); + return Error; + } + d->addBaseClass(cursor); + break; + case CXCursor_ClassDecl: + case CXCursor_UnionDecl: + case CXCursor_StructDecl: + if (clang_isCursorDefinition(cursor) == 0) + return Skip; + if (!d->addClass(cursor, codeModelClassTypeFromCursor(cursor.kind))) + return Error; + break; + case CXCursor_ClassTemplate: + case CXCursor_ClassTemplatePartialSpecialization: + if (clang_isCursorDefinition(cursor) == 0) + return Skip; + d->addClass(cursor, CodeModel::Class); + d->m_currentClass->setName(d->m_currentClass->name() + templateBrackets()); + d->m_scope.back() += templateBrackets(); + break; + case CXCursor_EnumDecl: { + QString name = getCursorSpelling(cursor); + const bool anonymous = name.isEmpty(); + if (anonymous) + name = QStringLiteral("enum_") + QString::number(++d->m_anonymousEnumCount); + d->m_currentEnum.reset(new _EnumModelItem(d->m_model, name)); + setFileName(cursor, d->m_currentEnum.data()); + d->m_currentEnum->setScope(d->m_scope); + d->m_currentEnum->setAnonymous(anonymous); + if (!qSharedPointerDynamicCast<_ClassModelItem>(d->m_scopeStack.back()).isNull()) + d->m_currentEnum->setAccessPolicy(accessPolicy(clang_getCXXAccessSpecifier(cursor))); + d->m_scopeStack.back()->addEnum(d->m_currentEnum); + } + break; + case CXCursor_EnumConstantDecl: { + const QString name = getCursorSpelling(cursor); + if (d->m_currentEnum.isNull()) { + const Diagnostic d(msgOutOfOrder(cursor, "enum"), cursor, CXDiagnostic_Error); + qWarning() << d; + appendDiagnostic(d); + return Error; + } + EnumeratorModelItem enumConstant(new _EnumeratorModelItem(d->m_model, name)); + enumConstant->setValue(d->cursorValueExpression(this, cursor)); + d->m_currentEnum->addEnumerator(enumConstant); + } + break; + case CXCursor_VarDecl: + // static class members are seen as CXCursor_VarDecl + if (!d->m_currentClass.isNull() && isClassCursor(clang_getCursorSemanticParent(cursor))) { + d->addField(cursor); + d->m_currentField->setStatic(true); + } + break; + case CXCursor_FieldDecl: + d->addField(cursor); + break; +#if CINDEX_VERSION_MAJOR > 0 || CINDEX_VERSION_MINOR >= 37 // Clang 4.0 + case CXCursor_FriendDecl: + return Skip; +#endif + case CXCursor_Constructor: + case CXCursor_Destructor: // Note: Also use clang_CXXConstructor_is..Constructor? + case CXCursor_CXXMethod: + case CXCursor_ConversionFunction: + // Skip inline member functions outside class, only go by declarations inside class + if (!withinClassDeclaration(cursor)) + return Skip; + d->m_currentFunction = d->createMemberFunction(cursor); + d->m_scopeStack.back()->addFunction(d->m_currentFunction); + break; + // Not fully supported, currently, seen as normal function + // Note: May appear inside class (member template) or outside (free template). + case CXCursor_FunctionTemplate: { + const CXCursor semParent = clang_getCursorSemanticParent(cursor); + if (isClassCursor(semParent)) { + if (semParent == clang_getCursorLexicalParent(cursor)) { + d->m_currentFunction = d->createMemberFunction(cursor); + d->m_scopeStack.back()->addFunction(d->m_currentFunction); + break; + } else { + return Skip; // inline member functions outside class + } + } + } + Q_FALLTHROUGH(); // fall through to free template function. + case CXCursor_FunctionDecl: + d->m_currentFunction = d->createFunction(cursor); + d->m_scopeStack.back()->addFunction(d->m_currentFunction); + break; + case CXCursor_Namespace: { + const QString name = getCursorSpelling(cursor); + const NamespaceModelItem parentNamespaceItem = qSharedPointerDynamicCast<_NamespaceModelItem>(d->m_scopeStack.back()); + if (parentNamespaceItem.isNull()) { + const QString message = msgOutOfOrder(cursor, "namespace") + + QLatin1String(" (current scope: ") + d->m_scopeStack.back()->name() + QLatin1Char(')'); + const Diagnostic d(message, cursor, CXDiagnostic_Error); + qWarning() << d; + appendDiagnostic(d); + return Error; + } + // If possible, continue existing namespace (as otherwise, all headers + // where a namespace is continued show up in the type database). + NamespaceModelItem namespaceItem = parentNamespaceItem->findNamespace(name); + if (namespaceItem.isNull()) { + namespaceItem.reset(new _NamespaceModelItem(d->m_model, name)); + setFileName(cursor, namespaceItem.data()); + namespaceItem->setScope(d->m_scope); + parentNamespaceItem->addNamespace(namespaceItem); + } + d->pushScope(namespaceItem); + } + break; + case CXCursor_ParmDecl: + // Skip in case of nested CXCursor_ParmDecls in case one parameter is a function pointer + // and function pointer typedefs. + if (d->m_currentArgument.isNull() && !d->m_currentFunction.isNull()) { + const QString name = getCursorSpelling(cursor); + d->m_currentArgument.reset(new _ArgumentModelItem(d->m_model, name)); + d->m_currentArgument->setType(d->createTypeInfo(cursor)); + d->m_currentFunction->addArgument(d->m_currentArgument); + QString defaultValueExpression = d->cursorValueExpression(this, cursor); + if (!defaultValueExpression.isEmpty()) { + d->m_currentArgument->setDefaultValueExpression(defaultValueExpression); + d->m_currentArgument->setDefaultValue(true); + } + } else { + return Skip; + } + break; + case CXCursor_TemplateTypeParameter: + case CXCursor_NonTypeTemplateParameter: { + const TemplateParameterModelItem tItem = cursor.kind == CXCursor_TemplateTemplateParameter + ? d->createTemplateParameter(cursor) : d->createNonTypeTemplateParameter(cursor); + // Apply to function/member template? + if (!d->m_currentFunction.isNull()) { + d->m_currentFunction->setTemplateParameters(d->m_currentFunction->templateParameters() << tItem); + } else if (!d->m_currentClass.isNull()) { // Apply to class + const QString &tplParmName = tItem->name(); + if (Q_UNLIKELY(!insertTemplateParameterIntoClassName(tplParmName, d->m_currentClass) + || !insertTemplateParameterIntoClassName(tplParmName, &d->m_scope.back()))) { + const QString message = QStringLiteral("Error inserting template parameter \"") + tplParmName + + QStringLiteral("\" into ") + d->m_currentClass->name(); + const Diagnostic d(message, cursor, CXDiagnostic_Error); + qWarning() << d; + appendDiagnostic(d); + return Error; + } + d->m_currentClass->setTemplateParameters(d->m_currentClass->templateParameters() << tItem); + } + } + break; + case CXCursor_TypeAliasDecl: + case CXCursor_TypeAliasTemplateDecl: // May contain nested CXCursor_TemplateTypeParameter + return Skip; + case CXCursor_TypedefDecl: { + const QString name = getCursorSpelling(cursor); + TypeDefModelItem item(new _TypeDefModelItem(d->m_model, name)); + setFileName(cursor, item.data()); + item->setType(d->createTypeInfo(clang_getTypedefDeclUnderlyingType(cursor))); + item->setScope(d->m_scope); + d->m_scopeStack.back()->addTypeDef(item); + d->m_cursorTypedefHash.insert(cursor, item); + } + break; + case CXCursor_TypeRef: + if (!d->m_currentFunction.isNull()) { + if (d->m_currentArgument.isNull()) + d->qualifyTypeDef(cursor, d->m_currentFunction); // return type + else + d->qualifyTypeDef(cursor, d->m_currentArgument); + } else if (!d->m_currentField.isNull()) { + d->qualifyTypeDef(cursor, d->m_currentField); + } + break; + case CXCursor_CXXFinalAttr: + if (!d->m_currentFunction.isNull()) + d->m_currentFunction->setFinal(true); + else if (!d->m_currentClass.isNull()) + d->m_currentClass->setFinal(true); + break; + case CXCursor_CXXOverrideAttr: + if (!d->m_currentFunction.isNull()) + d->m_currentFunction->setOverride(true); + break; + default: + break; + } + return BaseVisitor::Recurse; +} + +bool Builder::endToken(const CXCursor &cursor) +{ + switch (cursor.kind) { + case CXCursor_UnionDecl: + case CXCursor_ClassDecl: + case CXCursor_StructDecl: + case CXCursor_ClassTemplate: + case CXCursor_ClassTemplatePartialSpecialization: + d->popScope(); + // Continue in outer class after leaving inner class? + if (ClassModelItem lastClass = qSharedPointerDynamicCast<_ClassModelItem>(d->m_scopeStack.back())) + d->m_currentClass = lastClass; + else + d->m_currentClass.clear(); + d->m_currentFunctionType = CodeModel::Normal; + break; + case CXCursor_EnumDecl: + d->m_currentEnum.clear(); + break; + case CXCursor_VarDecl: + case CXCursor_FieldDecl: + d->m_currentField.clear(); + break; + case CXCursor_Constructor: + d->qualifyConstructor(cursor); + d->m_currentFunction.clear(); + break; + case CXCursor_Destructor: + case CXCursor_CXXMethod: + case CXCursor_FunctionDecl: + case CXCursor_FunctionTemplate: + d->m_currentFunction.clear(); + break; + case CXCursor_Namespace: + d->popScope(); + break; + case CXCursor_ParmDecl: + d->m_currentArgument.clear(); + break; + default: + break; + } + return true; +} + +} // namespace clang diff --git a/sources/shiboken2/ApiExtractor/parser/dumptree.h b/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.h index 5d91c6ef1..c97b7d2b7 100644 --- a/sources/shiboken2/ApiExtractor/parser/dumptree.h +++ b/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.h @@ -1,7 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org> +** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of PySide2. @@ -27,25 +26,33 @@ ** ****************************************************************************/ +#ifndef CLANGBUILDER_H +#define CLANGBUILDER_H -#ifndef DUMPTREE_H -#define DUMPTREE_H +#include "clangparser.h" -#include "default_visitor.h" +#include <codemodel_fwd.h> -class DumpTree: protected DefaultVisitor -{ +namespace clang { + +class BuilderPrivate; + +class Builder : public BaseVisitor { public: - DumpTree(); + Builder(); + ~Builder(); + + bool visitLocation(const CXSourceLocation &location) const override; + + StartTokenResult startToken(const CXCursor &cursor) override; + bool endToken(const CXCursor &cursor) override; - void dump(AST *node) { - visit(node); - } + FileModelItem dom() const; -protected: - virtual void visit(AST *node); +private: + BuilderPrivate *d; }; -#endif // DUMPTREE_H +} // namespace clang -// kate: space-indent on; indent-width 2; replace-tabs on; +#endif // CLANGBUILDER_H diff --git a/sources/shiboken2/ApiExtractor/clangparser/clangdebugutils.cpp b/sources/shiboken2/ApiExtractor/clangparser/clangdebugutils.cpp new file mode 100644 index 000000000..8d0fd098a --- /dev/null +++ b/sources/shiboken2/ApiExtractor/clangparser/clangdebugutils.cpp @@ -0,0 +1,150 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "clangdebugutils.h" +#include "clangutils.h" + +#include <QtCore/QDebug> +#include <QtCore/QString> + +#include <string.h> + +#ifndef QT_NO_DEBUG_STREAM + +#ifdef Q_OS_WIN +const char pathSep = '\\'; +#else +const char pathSep = '/'; +#endif + +static const char *baseName(const char *fileName) +{ + const char *b = strrchr(fileName, pathSep); + return b ? b + 1 : fileName; +} + +QDebug operator<<(QDebug s, const CXString &cs) +{ + s << clang_getCString(cs); + return s; +} + +QDebug operator<<(QDebug s, CXCursorKind cursorKind) // Enum +{ + const CXString kindName = clang_getCursorKindSpelling(cursorKind); + s << kindName; + clang_disposeString(kindName); + return s; +} + +static const char *accessSpecsStrings[] +{ + // CX_CXXInvalidAccessSpecifier, CX_CXXPublic, CX_CXXProtected, CX_CXXPrivate + "invalid", "public", "protected", "private" +}; + +QDebug operator<<(QDebug s, CX_CXXAccessSpecifier ac) +{ + s << accessSpecsStrings[ac]; + return s; +} + +QDebug operator<<(QDebug s, const CXType &t) +{ + CXString typeSpelling = clang_getTypeSpelling(t); + s << typeSpelling; + clang_disposeString(typeSpelling); + return s; +} + +QDebug operator<<(QDebug s, const CXCursor &cursor) +{ + QDebugStateSaver saver(s); + s.nospace(); + s.noquote(); + const CXCursorKind kind = clang_getCursorKind(cursor); + s << kind; + if (kind >= CXCursor_FirstInvalid && kind <= CXCursor_LastInvalid) + return s; + const CXType type = clang_getCursorType(cursor); + switch (kind) { + case CXCursor_CXXAccessSpecifier: + s << ' ' << clang_getCXXAccessSpecifier(cursor); + break; + case CXCursor_CXXBaseSpecifier: + s << ", inherits=\"" << clang::getCursorSpelling(clang_getTypeDeclaration(type)) << '"'; + break; + case CXCursor_CXXMethod: + case CXCursor_FunctionDecl: + case CXCursor_ConversionFunction: + s << ", result type=\"" << clang_getCursorResultType(cursor) << '"'; + break; + case CXCursor_TypedefDecl: + s << ", underlyingType=\"" << clang_getTypedefDeclUnderlyingType(cursor) << '"'; + break; + default: + break; + } + + if (type.kind != CXType_Invalid) + s << ", type=\"" << type << '"'; + if (clang_Cursor_hasAttrs(cursor)) + s << ", [attrs]"; + + const QString cursorSpelling = clang::getCursorSpelling(cursor); + if (!cursorSpelling.isEmpty()) + s << ", spelling=\"" << cursorSpelling << '"'; + CXString cursorDisplay = clang_getCursorDisplayName(cursor); + if (const char *dpy = clang_getCString(cursorDisplay)) { + const QString display = QString::fromUtf8(dpy); + if (display != cursorSpelling) + s << ", display=\"" << dpy << '"'; + } + clang_disposeString(cursorDisplay); + return s; +} + +QDebug operator<<(QDebug s, const CXSourceLocation &location) +{ + QDebugStateSaver saver(s); + s.nospace(); + CXFile file; // void * + unsigned line; + unsigned column; + unsigned offset; + clang_getExpansionLocation(location, &file, &line, &column, &offset); + const CXString cxFileName = clang_getFileName(file); + // Has been observed to be 0 for invalid locations + if (const char *cFileName = clang_getCString(cxFileName)) + s << baseName(cFileName) << ':'; + s << line << ':' << column; + clang_disposeString(cxFileName); + return s; +} + +#endif // !QT_NO_DEBUG_STREAM diff --git a/sources/shiboken2/ApiExtractor/parser/compiler_utils.h b/sources/shiboken2/ApiExtractor/clangparser/clangdebugutils.h index 849baf5aa..323efdd2a 100644 --- a/sources/shiboken2/ApiExtractor/parser/compiler_utils.h +++ b/sources/shiboken2/ApiExtractor/clangparser/clangdebugutils.h @@ -1,7 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org> +** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of PySide2. @@ -27,24 +26,23 @@ ** ****************************************************************************/ +#ifndef CLANGDEBUGUTILS_H +#define CLANGDEBUGUTILS_H -#ifndef COMPILER_UTILS_H -#define COMPILER_UTILS_H +#include <QtCore/QtGlobal> -#include <utility> +#include <clang-c/Index.h> -#include "codemodel.h" +QT_FORWARD_DECLARE_CLASS(QDebug) +QT_FORWARD_DECLARE_CLASS(QString) -struct TypeSpecifierAST; -struct DeclaratorAST; -class TokenStream; -class Binder; +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug s, const CXString &cs); +QDebug operator<<(QDebug s, CXCursorKind cursorKind); +QDebug operator<<(QDebug s, CX_CXXAccessSpecifier ac); +QDebug operator<<(QDebug s, const CXType &t); +QDebug operator<<(QDebug s, const CXCursor &cursor); +QDebug operator<<(QDebug s, const CXSourceLocation &location); +#endif // !QT_NO_DEBUG_STREAM -namespace CompilerUtils -{ - -TypeInfo typeDescription(TypeSpecifierAST *type_specifier, DeclaratorAST *declarator, Binder *binder); - -} // namespace CompilerUtils - -#endif // COMPILER_UTILS_H +#endif // CLANGDEBUGUTILS_H diff --git a/sources/shiboken2/ApiExtractor/clangparser/clangparser.cpp b/sources/shiboken2/ApiExtractor/clangparser/clangparser.cpp new file mode 100644 index 000000000..16a7a3147 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/clangparser/clangparser.cpp @@ -0,0 +1,272 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "clangparser.h" +#include "clangutils.h" +#include "clangdebugutils.h" +#include "compilersupport.h" + +#include <QtCore/QByteArrayList> +#include <QtCore/QDebug> +#include <QtCore/QDir> +#include <QtCore/QFile> +#include <QtCore/QScopedArrayPointer> +#include <QtCore/QString> + +namespace clang { + +SourceFileCache::Snippet SourceFileCache::getCodeSnippet(const CXCursor &cursor) +{ + Snippet result(nullptr, nullptr); + const SourceRange range = getCursorRange(cursor); + if (range.first.file.isEmpty() || range.second.file != range.first.file) + return result; + FileBufferCache::Iterator it = m_fileBufferCache.find(range.first.file); + if (it == m_fileBufferCache.end()) { + QFile file(range.first.file); + if (!file.open(QIODevice::ReadOnly)) { + qWarning().noquote().nospace() + << "Can't open " << QDir::toNativeSeparators(range.first.file) + << ": " << file.errorString(); + return result; + } + it = m_fileBufferCache.insert(range.first.file, file.readAll()); + } + + const unsigned pos = range.first.offset; + const unsigned end = range.second.offset; + const QByteArray &contents = it.value(); + if (end >= unsigned(contents.size())) { + qWarning().noquote().nospace() << "Range end " << end << " is above size of " + << range.first.file << " (" << contents.size() << ')'; + return result; + } + result.first = contents.constData() + pos; + result.second = contents.constData() + end; + return result; +} + +BaseVisitor::BaseVisitor() = default; +BaseVisitor::~BaseVisitor() = default; + +bool BaseVisitor::visitLocation(const CXSourceLocation &location) const +{ + return clang_Location_isFromMainFile(location) != 0; +} + +BaseVisitor::StartTokenResult BaseVisitor::cbHandleStartToken(const CXCursor &cursor) +{ + switch (cursor.kind) { + default: + break; + } + + return startToken(cursor); +} + +bool BaseVisitor::cbHandleEndToken(const CXCursor &cursor, StartTokenResult startResult) +{ + const bool result = startResult != Recurse || endToken(cursor); + switch (cursor.kind) { + default: + break; + } + + return result; +} + +BaseVisitor::CodeSnippet BaseVisitor::getCodeSnippet(const CXCursor &cursor) +{ + CodeSnippet result = m_fileCache.getCodeSnippet(cursor); + if (result.first == nullptr) + appendDiagnostic(Diagnostic(QStringLiteral("Unable to retrieve code snippet."), cursor, CXDiagnostic_Error)); + return result; +} + +QString BaseVisitor::getCodeSnippetString(const CXCursor &cursor) +{ + CodeSnippet result = m_fileCache.getCodeSnippet(cursor); + return result.first != nullptr + ? QString::fromUtf8(result.first, int(result.second - result.first)) + : QString(); +} + +static CXChildVisitResult + visitorCallback(CXCursor cursor, CXCursor /* parent */, CXClientData clientData) +{ + BaseVisitor *bv = reinterpret_cast<BaseVisitor *>(clientData); + + const CXSourceLocation location = clang_getCursorLocation(cursor); + if (!bv->visitLocation(location)) + return CXChildVisit_Continue; + + const BaseVisitor::StartTokenResult startResult = bv->cbHandleStartToken(cursor); + switch (startResult) { + case clang::BaseVisitor::Error: + return CXChildVisit_Break; + case clang::BaseVisitor::Skip: + break; + case clang::BaseVisitor::Recurse: + clang_visitChildren(cursor, visitorCallback, clientData); + break; + } + + if (!bv->cbHandleEndToken(cursor, startResult)) + return CXChildVisit_Break; + + return CXChildVisit_Continue; +} + +BaseVisitor::Diagnostics BaseVisitor::diagnostics() const +{ + return m_diagnostics; +} + +void BaseVisitor::setDiagnostics(const Diagnostics &d) +{ + m_diagnostics = d; +} + +void BaseVisitor::appendDiagnostic(const Diagnostic &d) +{ + m_diagnostics.append(d); +} + +static inline const char **byteArrayListToFlatArgV(const QByteArrayList &bl) +{ + const char **result = new const char *[bl.size() + 1]; + result[bl.size()] = nullptr; + std::transform(bl.cbegin(), bl.cend(), result, + [] (const QByteArray &a) { return a.constData(); }); + return result; +} + +static QByteArray msgCreateTranslationUnit(const QByteArrayList clangArgs, unsigned flags) +{ + QByteArray result = "clang_parseTranslationUnit2(0x"; + result += QByteArray::number(flags, 16); + const int count = clangArgs.size(); + result += ", cmd[" + QByteArray::number(count) + "]="; + for (int i = 0; i < count; ++i) { + const QByteArray &arg = clangArgs.at(i); + if (i) + result += ' '; + const bool quote = arg.contains(' ') || arg.contains('('); + if (quote) + result += '"'; + result += arg; + if (quote) + result += '"'; + } + result += ')'; + return result; +} + +static CXTranslationUnit createTranslationUnit(CXIndex index, + const QByteArrayList &args, + unsigned flags = 0) +{ + // courtesy qdoc + const unsigned defaultFlags = CXTranslationUnit_SkipFunctionBodies + | CXTranslationUnit_Incomplete; + + static const QByteArrayList defaultArgs = { +#if defined(Q_CC_MSVC) && _MSC_VER > 1900 + "-std=c++1z", // Fixes constexpr errors in MSVC2017 library headers with Clang 4.1 +#else + "-std=c++14", // ! otherwise, t.h is parsed as "C" +#endif +#ifndef Q_OS_WIN + "-fPIC", +#endif + "-fno-exceptions", // Workaround for clang bug http://reviews.llvm.org/D17988 +#ifdef Q_OS_MACOS + "-Wno-expansion-to-defined", // Workaround for warnings in Darwin stdlib, see + // https://github.com/darlinghq/darling/issues/204 +#endif + "-Wno-constant-logical-operand" + }; + + const QByteArrayList clangArgs = emulatedCompilerOptions() + defaultArgs + args; + QScopedArrayPointer<const char *> argv(byteArrayListToFlatArgV(clangArgs)); + qDebug().noquote().nospace() << msgCreateTranslationUnit(clangArgs, flags); + + CXTranslationUnit tu; + CXErrorCode err = clang_parseTranslationUnit2(index, nullptr, argv.data(), + clangArgs.size(), nullptr, 0, + defaultFlags | flags, &tu); + if (err || !tu) { + qWarning().noquote().nospace() << "Could not parse " + << clangArgs.constLast().constData() << ", error code: " << err; + return nullptr; + } + return tu; +} + +/* clangFlags are flags to clang_parseTranslationUnit2() such as + * CXTranslationUnit_KeepGoing (from CINDEX_VERSION_MAJOR/CINDEX_VERSION_MINOR 0.35) + */ + +bool parse(const QByteArrayList &clangArgs, unsigned clangFlags, BaseVisitor &bv) +{ + CXIndex index = clang_createIndex(0 /* excludeDeclarationsFromPCH */, + 1 /* displayDiagnostics */); + if (!index) { + qWarning() << "clang_createIndex() failed!"; + return false; + } + + CXTranslationUnit translationUnit = createTranslationUnit(index, clangArgs, clangFlags); + if (!translationUnit) + return false; + + CXCursor rootCursor = clang_getTranslationUnitCursor(translationUnit); + + clang_visitChildren(rootCursor, visitorCallback, reinterpret_cast<CXClientData>(&bv)); + + QVector<Diagnostic> diagnostics = getDiagnostics(translationUnit); + diagnostics.append(bv.diagnostics()); + bv.setDiagnostics(diagnostics); + + const bool ok = maxSeverity(diagnostics) < CXDiagnostic_Error; + if (!ok) { + QDebug debug = qWarning(); + debug.noquote(); + debug.nospace(); + debug << "Errors in " + << QDir::toNativeSeparators(QFile::decodeName(clangArgs.constLast())) << ":\n"; + for (const Diagnostic &diagnostic : qAsConst(diagnostics)) + debug << diagnostic << '\n'; + } + + clang_disposeTranslationUnit(translationUnit); + clang_disposeIndex(index); + return ok; +} + +} // namespace clang diff --git a/sources/shiboken2/ApiExtractor/clangparser/clangparser.h b/sources/shiboken2/ApiExtractor/clangparser/clangparser.h new file mode 100644 index 000000000..ef1424f17 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/clangparser/clangparser.h @@ -0,0 +1,93 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef CLANGPARSER_H +#define CLANGPARSER_H + +#include <clang-c/Index.h> + +#include <QtCore/QByteArrayList> +#include <QtCore/QHash> +#include <QtCore/QPair> +#include <QtCore/QString> +#include <QtCore/QVector> + +namespace clang { + +struct Diagnostic; + +class SourceFileCache { +public: + typedef QPair<const char *, const char *> Snippet; + + Snippet getCodeSnippet(const CXCursor &cursor); + +private: + typedef QHash<QString, QByteArray> FileBufferCache; + + FileBufferCache m_fileBufferCache; +}; + +class BaseVisitor { + Q_DISABLE_COPY(BaseVisitor) +public: + typedef QVector<Diagnostic> Diagnostics; + typedef SourceFileCache::Snippet CodeSnippet; + + enum StartTokenResult { Error, Skip, Recurse }; + + BaseVisitor(); + virtual ~BaseVisitor(); + + // Whether location should be visited. + // defaults to clang_Location_isFromMainFile() + virtual bool visitLocation(const CXSourceLocation &location) const; + + virtual StartTokenResult startToken(const CXCursor &cursor) = 0; + virtual bool endToken(const CXCursor &cursor) = 0; + + StartTokenResult cbHandleStartToken(const CXCursor &cursor); + bool cbHandleEndToken(const CXCursor &cursor, StartTokenResult startResult); + + CodeSnippet getCodeSnippet(const CXCursor &cursor); + QString getCodeSnippetString(const CXCursor &cursor); + + Diagnostics diagnostics() const; + void setDiagnostics(const Diagnostics &d); + void appendDiagnostic(const Diagnostic &d); + +private: + SourceFileCache m_fileCache; + Diagnostics m_diagnostics; +}; + +bool parse(const QByteArrayList &clangArgs, unsigned clangFlags, BaseVisitor &ctx); + +} // namespace clang + +#endif // !CLANGPARSER_H diff --git a/sources/shiboken2/ApiExtractor/clangparser/clangutils.cpp b/sources/shiboken2/ApiExtractor/clangparser/clangutils.cpp new file mode 100644 index 000000000..f30a585bc --- /dev/null +++ b/sources/shiboken2/ApiExtractor/clangparser/clangutils.cpp @@ -0,0 +1,227 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "clangutils.h" + +#include <QtCore/QDebug> +#include <QtCore/QDir> +#include <QtCore/QHashFunctions> +#include <QtCore/QProcess> + +bool operator==(const CXCursor &c1, const CXCursor &c2) +{ + return c1.kind == c2.kind + && c1.xdata == c2.xdata + && std::equal(c1.data, c1.data + sizeof(c1.data) / sizeof(c1.data[0]), c2.data); +} + +uint qHash(const CXCursor &c, uint seed) +{ + return qHash(c.kind) ^ qHash(c.xdata) ^ qHash(c.data[0]) + ^ qHash(c.data[1]) ^ qHash(c.data[2]) ^ seed; +} + +namespace clang { + +SourceLocation getExpansionLocation(const CXSourceLocation &location) +{ + SourceLocation result; + CXFile file; // void * + clang_getExpansionLocation(location, &file, &result.line, &result.column, &result.offset); + const CXString cxFileName = clang_getFileName(file); + // Has been observed to be 0 for invalid locations + if (const char *cFileName = clang_getCString(cxFileName)) + result.file = QString::fromUtf8(cFileName); + clang_disposeString(cxFileName); + return result; +} + +SourceLocation getCursorLocation(const CXCursor &cursor) +{ + const CXSourceRange extent = clang_getCursorExtent(cursor); + return getExpansionLocation(clang_getRangeStart(extent)); +} + +CXString getFileNameFromLocation(const CXSourceLocation &location) +{ + CXFile file; + unsigned line; + unsigned column; + unsigned offset; + clang_getExpansionLocation(location, &file, &line, &column, &offset); + return clang_getFileName(file); +} + +SourceRange getCursorRange(const CXCursor &cursor) +{ + const CXSourceRange extent = clang_getCursorExtent(cursor); + return qMakePair(getExpansionLocation(clang_getRangeStart(extent)), + getExpansionLocation(clang_getRangeEnd(extent))); +} + +QString getCursorKindName(CXCursorKind cursorKind) +{ + CXString kindName = clang_getCursorKindSpelling(cursorKind); + const QString result = QString::fromUtf8(clang_getCString(kindName)); + clang_disposeString(kindName); + return result; +} + +QString getCursorSpelling(const CXCursor &cursor) +{ + CXString cursorSpelling = clang_getCursorSpelling(cursor); + const QString result = QString::fromUtf8(clang_getCString(cursorSpelling)); + clang_disposeString(cursorSpelling); + return result; +} + +QString getCursorDisplayName(const CXCursor &cursor) +{ + CXString displayName = clang_getCursorDisplayName(cursor); + const QString result = QString::fromUtf8(clang_getCString(displayName)); + clang_disposeString(displayName); + return result; +} + +QString getTypeName(const CXType &type) +{ + CXString typeSpelling = clang_getTypeSpelling(type); + const QString result = QString::fromUtf8(clang_getCString(typeSpelling)); + clang_disposeString(typeSpelling); + return result; +} + +Diagnostic::Diagnostic(const QString &m, const CXCursor &c, CXDiagnosticSeverity s) + : message(m), location(getCursorLocation(c)), source(Other), severity(s) +{ +} + +Diagnostic Diagnostic::fromCXDiagnostic(CXDiagnostic cd) +{ + Diagnostic result; + result.source = Clang; + CXString spelling = clang_getDiagnosticSpelling(cd); + result.message = QString::fromUtf8(clang_getCString(spelling)); + clang_disposeString(spelling); + result.severity = clang_getDiagnosticSeverity(cd); + result.location = getExpansionLocation(clang_getDiagnosticLocation(cd)); + + CXDiagnosticSet childDiagnostics = clang_getChildDiagnostics(cd); + if (const unsigned childCount = clang_getNumDiagnosticsInSet(childDiagnostics)) { + result.childMessages.reserve(int(childCount)); + const unsigned format = clang_defaultDiagnosticDisplayOptions(); + for (unsigned i = 0; i < childCount; ++i) { + CXDiagnostic childDiagnostic = clang_getDiagnosticInSet(childDiagnostics, i); + CXString cdm = clang_formatDiagnostic(childDiagnostic, format); + result.childMessages.append(QString::fromUtf8(clang_getCString(cdm))); + clang_disposeString(cdm); + clang_disposeDiagnostic(childDiagnostic); + } + } + + return result; +} + +QVector<Diagnostic> getDiagnostics(CXTranslationUnit tu) +{ + QVector<Diagnostic> result; + const unsigned count = clang_getNumDiagnostics(tu); + result.reserve(int(count)); + for (unsigned i = 0; i < count; ++i) { + const CXDiagnostic d = clang_getDiagnostic(tu, i); + result.append(Diagnostic::fromCXDiagnostic(d)); + clang_disposeDiagnostic(d); + } + return result; +} + +CXDiagnosticSeverity maxSeverity(const QVector<Diagnostic> &ds) +{ + CXDiagnosticSeverity result = CXDiagnostic_Ignored; + for (const Diagnostic& d : ds) { + if (d.severity > result) + result = d.severity; + } + return result; +} + +#ifndef QT_NO_DEBUG_STREAM + +QDebug operator<<(QDebug s, const SourceLocation &l) +{ + QDebugStateSaver saver(s); + s.nospace(); + s.noquote(); + s << QDir::toNativeSeparators(l.file) << ':' << l.line; + if (l.column) + s << ':' << l.column; + return s; +} + +// Roughly follow g++ format: +// file.cpp:214:37: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast] +QDebug operator<<(QDebug s, const Diagnostic &d) +{ + QDebugStateSaver saver(s); + s.nospace(); + s.noquote(); + s << d.location << ": "; + switch (d.severity) { + case CXDiagnostic_Ignored: + s << "ignored"; + break; + case CXDiagnostic_Note: + s << "note"; + break; + case CXDiagnostic_Warning: + s << "warning"; + break; + case CXDiagnostic_Error: + s << "error"; + break; + case CXDiagnostic_Fatal: + s << "fatal"; + break; + } + s << ": " << d.message; + + if (d.source != Diagnostic::Clang) + s << " [other]"; + + if (const int childMessagesCount = d.childMessages.size()) { + s << '\n'; + for (int i = 0; i < childMessagesCount; ++i) + s << " " << d.childMessages.at(i) << '\n'; + } + + return s; +} + +#endif // QT_NO_DEBUG_STREAM + +} // namespace clang diff --git a/sources/shiboken2/ApiExtractor/clangparser/clangutils.h b/sources/shiboken2/ApiExtractor/clangparser/clangutils.h new file mode 100644 index 000000000..3437f51eb --- /dev/null +++ b/sources/shiboken2/ApiExtractor/clangparser/clangutils.h @@ -0,0 +1,101 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef CLANGUTILS_H +#define CLANGUTILS_H + +#include <clang-c/Index.h> +#include <QtCore/QPair> +#include <QtCore/QString> +#include <QtCore/QVector> + +QT_FORWARD_DECLARE_CLASS(QDebug) + +bool operator==(const CXCursor &c1, const CXCursor &c2); +uint qHash(const CXCursor &c, uint seed = 0); + +namespace clang { + +QString getCursorKindName(CXCursorKind cursorKind); +QString getCursorSpelling(const CXCursor &cursor); +QString getCursorDisplayName(const CXCursor &cursor); +QString getTypeName(const CXType &type); +inline QString getCursorTypeName(const CXCursor &cursor) + { return getTypeName(clang_getCursorType(cursor)); } +inline QString getCursorResultTypeName(const CXCursor &cursor) + { return getTypeName(clang_getCursorResultType(cursor)); } + +inline bool isCursorValid(const CXCursor &c) +{ + return c.kind < CXCursor_FirstInvalid || c.kind > CXCursor_LastInvalid; +} + +struct SourceLocation +{ + int compare(const SourceLocation &rhs) const; + + QString file; + unsigned line = 0; + unsigned column = 0; + unsigned offset = 0; +}; + +SourceLocation getExpansionLocation(const CXSourceLocation &location); + +typedef QPair<SourceLocation, SourceLocation> SourceRange; + +SourceLocation getCursorLocation(const CXCursor &cursor); +CXString getFileNameFromLocation(const CXSourceLocation &location); +SourceRange getCursorRange(const CXCursor &cursor); + +struct Diagnostic { + enum Source { Clang, Other }; + + Diagnostic() : source(Clang) {} + // Clang + static Diagnostic fromCXDiagnostic(CXDiagnostic cd); + // Other + explicit Diagnostic(const QString &m, const CXCursor &c, CXDiagnosticSeverity s = CXDiagnostic_Warning); + + QString message; + QStringList childMessages; + SourceLocation location; + Source source; + CXDiagnosticSeverity severity; +}; + +QVector<Diagnostic> getDiagnostics(CXTranslationUnit tu); +CXDiagnosticSeverity maxSeverity(const QVector<Diagnostic> &ds); + +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug, const SourceLocation &); +QDebug operator<<(QDebug, const Diagnostic &); +#endif // QT_NO_DEBUG_STREAM +} // namespace clang + +#endif // CLANGUTILS_H diff --git a/sources/shiboken2/ApiExtractor/clangparser/compilersupport.cpp b/sources/shiboken2/ApiExtractor/clangparser/compilersupport.cpp new file mode 100644 index 000000000..e9af23bc5 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/clangparser/compilersupport.cpp @@ -0,0 +1,202 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "compilersupport.h" +#include "header_paths.h" + +#include <QtCore/QDebug> +#include <QtCore/QProcess> +#include <QtCore/QStringList> +#include <QtCore/QVersionNumber> + +#include <string.h> +#include <algorithm> +#include <iterator> + +namespace clang { + +static bool runProcess(const QString &program, const QStringList &arguments, + QByteArray *stdOutIn = nullptr, QByteArray *stdErrIn = nullptr) +{ + QProcess process; + process.start(program, arguments, QProcess::ReadWrite); + if (!process.waitForStarted()) { + qWarning().noquote().nospace() << "Unable to start " + << process.program() << ": " << process.errorString(); + return false; + } + process.closeWriteChannel(); + const bool finished = process.waitForFinished(); + const QByteArray stdErr = process.readAllStandardError(); + if (stdErrIn) + *stdErrIn = stdErr; + if (stdOutIn) + *stdOutIn = process.readAllStandardOutput(); + + if (!finished) { + qWarning().noquote().nospace() << process.program() << " timed out: " << stdErr; + process.kill(); + return false; + } + + if (process.exitStatus() != QProcess::NormalExit) { + qWarning().noquote().nospace() << process.program() << " crashed: " << stdErr; + return false; + } + + if (process.exitCode() != 0) { + qWarning().noquote().nospace() << process.program() << " exited " + << process.exitCode() << ": " << stdErr; + return false; + } + + return true; +} + +#if defined(Q_CC_GNU) + +static QByteArray frameworkPath() { return QByteArrayLiteral(" (framework directory)"); } + +// Determine g++'s internal include paths from the output of +// g++ -E -x c++ - -v </dev/null +// Output looks like: +// #include <...> search starts here: +// /usr/local/include +// /System/Library/Frameworks (framework directory) +// End of search list. +static HeaderPaths gppInternalIncludePaths(const QString &compiler) +{ + HeaderPaths result; + QStringList arguments; + arguments << QStringLiteral("-E") << QStringLiteral("-x") << QStringLiteral("c++") + << QStringLiteral("-") << QStringLiteral("-v"); + QByteArray stdOut; + QByteArray stdErr; + if (!runProcess(compiler, arguments, &stdOut, &stdErr)) + return result; + const QByteArrayList stdErrLines = stdErr.split('\n'); + bool isIncludeDir = false; + for (const QByteArray &line : stdErrLines) { + if (isIncludeDir) { + if (line.startsWith(QByteArrayLiteral("End of search list"))) { + isIncludeDir = false; + } else { + HeaderPath headerPath(line.trimmed()); + if (headerPath.path.endsWith(frameworkPath())) { + headerPath.m_isFramework = true; + headerPath.path.truncate(headerPath.path.size() - frameworkPath().size()); + } + result.append(headerPath); + } + } else if (line.startsWith(QByteArrayLiteral("#include <...> search starts here"))) { + isIncludeDir = true; + } + } + return result; +} +#endif // Q_CC_MSVC + +// Detect Vulkan as supported from Qt 5.10 by checking the environment variables. +static void detectVulkan(HeaderPaths *headerPaths) +{ + static const char *vulkanVariables[] = {"VULKAN_SDK", "VK_SDK_PATH"}; + for (const char *vulkanVariable : vulkanVariables) { + if (qEnvironmentVariableIsSet(vulkanVariable)) { + headerPaths->append(HeaderPath(qgetenv(vulkanVariable) + QByteArrayLiteral("/include"))); + break; + } + } +} + +#if defined(Q_CC_GNU) +static inline bool isRedHat74() +{ + if (QSysInfo::productType() != QLatin1String("rhel")) + return false; + const QVersionNumber osVersion = QVersionNumber::fromString(QSysInfo::productVersion()); + return osVersion.isNull() || osVersion >= QVersionNumber(7, 4); +} +#endif // Q_CC_GNU + +// For MSVC, we set the MS compatibility version and let Clang figure out its own +// options and include paths. +// For the others, we pass "-nostdinc" since libclang tries to add it's own system +// include paths, which together with the clang compiler paths causes some clash +// which causes std types not being found and construct -I/-F options from the +// include paths of the host compiler. + +#ifdef Q_CC_CLANG +static QByteArray noStandardIncludeOption() { return QByteArrayLiteral("-nostdinc"); } +#endif + +// Returns clang options needed for emulating the host compiler +QByteArrayList emulatedCompilerOptions() +{ + QByteArrayList result; +#if defined(Q_CC_MSVC) + HeaderPaths headerPaths; + result.append(QByteArrayLiteral("-fms-compatibility-version=19")); + result.append(QByteArrayLiteral("-Wno-microsoft-enum-value")); +#elif defined(Q_CC_CLANG) + HeaderPaths headerPaths = gppInternalIncludePaths(QStringLiteral("clang++")); + result.append(noStandardIncludeOption()); +#elif defined(Q_CC_GNU) + HeaderPaths headerPaths; + + // The clang builtin includes directory is used to find the definitions for intrinsic functions + // and builtin types. It is necessary to use the clang includes to prevent redefinition errors. + // The default toolchain includes should be picked up automatically by clang without specifying + // them implicitly. + QByteArray clangBuiltinIncludesDir(CLANG_BUILTIN_INCLUDES_DIR); + + if (!clangBuiltinIncludesDir.isEmpty()) { + result.append(QByteArrayLiteral("-isystem")); + result.append(clangBuiltinIncludesDir); + } + // Append the c++ include paths since Clang is unable to find <list> etc + // on RHEL 7.4 with g++ 6.3. A fix for this has been added to Clang 5.0, + // so, the code can be removed once Clang 5.0 is the minimum version. + if (isRedHat74()) { + const HeaderPaths gppPaths = gppInternalIncludePaths(QStringLiteral("g++")); + for (const HeaderPath &h : gppPaths) { + if (h.path.contains("c++")) + headerPaths.append(h); + } + } +#else + HeaderPaths headerPaths; +#endif + detectVulkan(&headerPaths); + std::transform(headerPaths.cbegin(), headerPaths.cend(), + std::back_inserter(result), [](const HeaderPath &p) { + return HeaderPath::includeOption(p, true); + }); + return result; +} + +} // namespace clang diff --git a/sources/shiboken2/ApiExtractor/parser/list.cpp b/sources/shiboken2/ApiExtractor/clangparser/compilersupport.h index 2d2a78700..f556da551 100644 --- a/sources/shiboken2/ApiExtractor/parser/list.cpp +++ b/sources/shiboken2/ApiExtractor/clangparser/compilersupport.h @@ -1,7 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org> +** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of PySide2. @@ -27,7 +26,15 @@ ** ****************************************************************************/ +#ifndef COMPILERSUPPORT_H +#define COMPILERSUPPORT_H -#include "list.h" +#include <QtCore/QByteArrayList> -// kate: space-indent on; indent-width 2; replace-tabs on; +namespace clang { + +QByteArrayList emulatedCompilerOptions(); + +} // namespace clang + +#endif // COMPILERSUPPORT_H diff --git a/sources/shiboken2/ApiExtractor/doc/conf.py.in b/sources/shiboken2/ApiExtractor/doc/conf.py.in index 70750c899..3a42707ad 100644 --- a/sources/shiboken2/ApiExtractor/doc/conf.py.in +++ b/sources/shiboken2/ApiExtractor/doc/conf.py.in @@ -151,8 +151,6 @@ html_split_index = False # If true, links to the reST sources are added to the pages. html_show_sourcelink = False -html_add_permalinks = True; - # If true, an OpenSearch description file will be output, and all pages will # contain a <link> tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. diff --git a/sources/shiboken2/ApiExtractor/doc/typesystem_specifying_types.rst b/sources/shiboken2/ApiExtractor/doc/typesystem_specifying_types.rst index 0d24a6d52..646e76043 100644 --- a/sources/shiboken2/ApiExtractor/doc/typesystem_specifying_types.rst +++ b/sources/shiboken2/ApiExtractor/doc/typesystem_specifying_types.rst @@ -150,6 +150,7 @@ enum-type <typesystem> <enum-type name="..." identified-by-value="..." + class="yes | no" since="..." flags="yes | no" flags-revision="..." @@ -179,6 +180,10 @@ enum-type Notice that the **enum-type** tag can either have **name** or **identified-by-value** but not both. + The *optional* boolean attribute **class** specifies whether the underlying + enumeration is a C++ 11 enumeration class. In that case, the enumeration values + need to be qualified by the enumeration name to match the C++ Syntax. + The **revision** attribute can be used to specify a revision for each type, easing the production of ABI compatible bindings. diff --git a/sources/shiboken2/ApiExtractor/docparser.cpp b/sources/shiboken2/ApiExtractor/docparser.cpp index 4ec1da299..1d1783f05 100644 --- a/sources/shiboken2/ApiExtractor/docparser.cpp +++ b/sources/shiboken2/ApiExtractor/docparser.cpp @@ -29,6 +29,8 @@ #include "abstractmetalang.h" #include "typesystem.h" #include <QtCore/QDebug> +#include <QtCore/QDir> +#include <QtCore/QTextStream> #include <QtXmlPatterns/QXmlQuery> #include <QBuffer> @@ -49,7 +51,7 @@ QString DocParser::getDocumentation(QXmlQuery& xquery, const QString& query, const DocModificationList& mods) const { QString doc = execXQuery(xquery, query); - return applyDocModifications(mods, doc); + return applyDocModifications(mods, doc.trimmed()); } QString DocParser::execXQuery(QXmlQuery& xquery, const QString& query) const @@ -69,6 +71,77 @@ QString DocParser::execXQuery(QXmlQuery& xquery, const QString& query) const return result; } +bool DocParser::skipForQuery(const AbstractMetaFunction *func) +{ + // Skip private functions and copies created by AbstractMetaClass::fixFunctions() + if (!func || func->isPrivate() + || func->isModifiedRemoved() + || func->declaringClass() != func->ownerClass() + || func->isCastOperator()) { + return true; + } + switch (func->functionType()) { + case AbstractMetaFunction::MoveConstructorFunction: + case AbstractMetaFunction::AssignmentOperatorFunction: + case AbstractMetaFunction::MoveAssignmentOperatorFunction: + return true; + default: + break; + } + return false; +} + +AbstractMetaFunctionList DocParser::documentableFunctions(const AbstractMetaClass *metaClass) +{ + AbstractMetaFunctionList result = metaClass->functionsInTargetLang(); + for (int i = result.size() - 1; i >= 0; --i) { + if (DocParser::skipForQuery(result.at(i)) || result.at(i)->isUserAdded()) + result.removeAt(i); + } + return result; +} + +QString DocParser::msgCannotFindDocumentation(const QString &fileName, + const char *what, const QString &name, + const QString &query) +{ + QString result; + QTextStream(&result) << "Cannot find documentation for " << what + << ' ' << name << " in:\n " << QDir::toNativeSeparators(fileName) + << "\n using query:\n " << query; + return result; +} + +QString DocParser::msgCannotFindDocumentation(const QString &fileName, + const AbstractMetaClass *metaClass, + const AbstractMetaFunction *function, + const QString &query) +{ + return msgCannotFindDocumentation(fileName, "function", + metaClass->name() + QLatin1String("::") + function->name() + QLatin1String("()"), + query); +} + +QString DocParser::msgCannotFindDocumentation(const QString &fileName, + const AbstractMetaClass *metaClass, + const AbstractMetaEnum *e, + const QString &query) +{ + return msgCannotFindDocumentation(fileName, "enum", + metaClass->name() + QLatin1String("::") + e->name(), + query); +} + +QString DocParser::msgCannotFindDocumentation(const QString &fileName, + const AbstractMetaClass *metaClass, + const AbstractMetaField *f, + const QString &query) +{ + return msgCannotFindDocumentation(fileName, "field", + metaClass->name() + QLatin1String("::") + f->name(), + query); +} + namespace { @@ -100,11 +173,11 @@ struct XslResources QString DocParser::applyDocModifications(const DocModificationList& mods, const QString& xml) const { - if (mods.isEmpty()) + if (mods.isEmpty() || xml.isEmpty()) return xml; bool hasXPathBasedModification = false; - foreach (DocModification mod, mods) { + for (const DocModification &mod : mods) { if (mod.mode() == TypeSystem::DocModificationXPathReplace) { hasXPathBasedModification = true; break; @@ -126,7 +199,7 @@ QString DocParser::applyDocModifications(const DocModificationList& mods, const "</xsl:copy>\n" "</xsl:template>\n" ); - foreach (DocModification mod, mods) { + for (const DocModification &mod : mods) { if (mod.mode() == TypeSystem::DocModificationXPathReplace) { QString xpath = mod.xpath(); xpath.replace(QLatin1Char('"'), QLatin1String(""")); @@ -169,6 +242,6 @@ QString DocParser::applyDocModifications(const DocModificationList& mods, const } Q_ASSERT(result != xml); - return result; + return result.trimmed(); } diff --git a/sources/shiboken2/ApiExtractor/docparser.h b/sources/shiboken2/ApiExtractor/docparser.h index 5573f6851..1770815b0 100644 --- a/sources/shiboken2/ApiExtractor/docparser.h +++ b/sources/shiboken2/ApiExtractor/docparser.h @@ -29,6 +29,7 @@ #define DOCPARSER_H #include "typesystem_typedefs.h" +#include "abstractmetalang_typedefs.h" #include <QtCore/QString> @@ -110,10 +111,31 @@ public: */ virtual Documentation retrieveModuleDocumentation(const QString& name) = 0; + static bool skipForQuery(const AbstractMetaFunction *func); + protected: QString getDocumentation(QXmlQuery& xquery, const QString& query, const DocModificationList& mods) const; + + static AbstractMetaFunctionList documentableFunctions(const AbstractMetaClass *metaClass); + + static QString msgCannotFindDocumentation(const QString &fileName, + const char *what, const QString &name, + const QString &query); + static QString msgCannotFindDocumentation(const QString &fileName, + const AbstractMetaClass *metaClass, + const AbstractMetaFunction *function, + const QString &query); + static QString msgCannotFindDocumentation(const QString &fileName, + const AbstractMetaClass *metaClass, + const AbstractMetaEnum *e, + const QString &query); + static QString msgCannotFindDocumentation(const QString &fileName, + const AbstractMetaClass *metaClass, + const AbstractMetaField *f, + const QString &query); + private: QString m_packageName; QString m_docDataDir; diff --git a/sources/shiboken2/ApiExtractor/doxygenparser.cpp b/sources/shiboken2/ApiExtractor/doxygenparser.cpp index f7d868f8d..1cffa3b67 100644 --- a/sources/shiboken2/ApiExtractor/doxygenparser.cpp +++ b/sources/shiboken2/ApiExtractor/doxygenparser.cpp @@ -96,20 +96,16 @@ void DoxygenParser::fillDocumentation(AbstractMetaClass* metaClass) xquery.setFocus(QUrl(doxyFilePath)); // Get class documentation - QString classDoc = getDocumentation(xquery, QLatin1String("/doxygen/compounddef/detaileddescription"), + const QString classQuery = QLatin1String("/doxygen/compounddef/detaileddescription"); + QString classDoc = getDocumentation(xquery, classQuery, metaClass->typeEntry()->docModifications()); - if (classDoc.isEmpty()) { - qCWarning(lcShiboken).noquote().nospace() - << "Can't find documentation for class \"" << metaClass->name() << "\"."; - } + if (classDoc.isEmpty()) + qCWarning(lcShiboken(), "%s", qPrintable(msgCannotFindDocumentation(doxyFilePath, "class", metaClass->name(), classQuery))); metaClass->setDocumentation(classDoc); //Functions Documentation - AbstractMetaFunctionList funcs = metaClass->functionsInTargetLang(); - foreach (AbstractMetaFunction *func, funcs) { - if (!func || func->isPrivate()) - continue; - + const AbstractMetaFunctionList &funcs = DocParser::documentableFunctions(metaClass); + for (AbstractMetaFunction *func : funcs) { QString query = QLatin1String("/doxygen/compounddef/sectiondef"); // properties if (func->isPropertyReader() || func->isPropertyWriter() @@ -128,8 +124,8 @@ void DoxygenParser::fillDocumentation(AbstractMetaClass* metaClass) query += QLatin1String("/../argsstring[text()=\"") + args + QLatin1String("\"]"); } else { int i = 1; - foreach (AbstractMetaArgument* arg, func->arguments()) { - QString type; + const AbstractMetaArgumentList &arguments = func->arguments(); + for (AbstractMetaArgument *arg : arguments) { if (!arg->type()->isPrimitive()) { query += QLatin1String("/../param[") + QString::number(i) + QLatin1String("]/type/ref[text()=\"") @@ -150,28 +146,40 @@ void DoxygenParser::fillDocumentation(AbstractMetaClass* metaClass) query += QLatin1String("/../detaileddescription)[1]"); } QString doc = getDocumentation(xquery, query, DocModificationList()); + if (doc.isEmpty()) { + qCWarning(lcShiboken(), "%s", + qPrintable(msgCannotFindDocumentation(doxyFilePath, metaClass, func, query))); + } func->setDocumentation(doc); isProperty = false; } //Fields - AbstractMetaFieldList fields = metaClass->fields(); - foreach (AbstractMetaField *field, fields) { + const AbstractMetaFieldList &fields = metaClass->fields(); + for (AbstractMetaField *field : fields) { if (field->isPrivate()) return; QString query = QLatin1String("/doxygen/compounddef/sectiondef/memberdef/name[text()=\"") + field->name() + QLatin1String("\"]/../detaileddescription"); QString doc = getDocumentation(xquery, query, DocModificationList()); + if (doc.isEmpty()) { + qCWarning(lcShiboken(), "%s", + qPrintable(msgCannotFindDocumentation(doxyFilePath, metaClass, field, query))); + } field->setDocumentation(doc); } //Enums - AbstractMetaEnumList enums = metaClass->enums(); - foreach (AbstractMetaEnum *meta_enum, enums) { + const AbstractMetaEnumList &enums = metaClass->enums(); + for (AbstractMetaEnum *meta_enum : enums) { QString query = QLatin1String("/doxygen/compounddef/sectiondef/memberdef[@kind=\"enum\"]/name[text()=\"") + meta_enum->name() + QLatin1String("\"]/.."); QString doc = getDocumentation(xquery, query, DocModificationList()); + if (doc.isEmpty()) { + qCWarning(lcShiboken(), "%s", + qPrintable(msgCannotFindDocumentation(doxyFilePath, metaClass, meta_enum, query))); + } meta_enum->setDocumentation(doc); } diff --git a/sources/shiboken2/ApiExtractor/doxygenparser.h b/sources/shiboken2/ApiExtractor/doxygenparser.h index 7314cfe3b..3f9ca5142 100644 --- a/sources/shiboken2/ApiExtractor/doxygenparser.h +++ b/sources/shiboken2/ApiExtractor/doxygenparser.h @@ -35,9 +35,9 @@ class DoxygenParser : public DocParser { public: DoxygenParser() {} - virtual void fillDocumentation(AbstractMetaClass *metaClass); - virtual Documentation retrieveModuleDocumentation(); - virtual Documentation retrieveModuleDocumentation(const QString& name); + void fillDocumentation(AbstractMetaClass *metaClass) override; + Documentation retrieveModuleDocumentation() override; + Documentation retrieveModuleDocumentation(const QString& name) override; }; #endif // DOXYGENPARSER_H diff --git a/sources/shiboken2/ApiExtractor/fileout.cpp b/sources/shiboken2/ApiExtractor/fileout.cpp index c97347fe1..be0023c3c 100644 --- a/sources/shiboken2/ApiExtractor/fileout.cpp +++ b/sources/shiboken2/ApiExtractor/fileout.cpp @@ -39,15 +39,15 @@ bool FileOut::dummy = false; bool FileOut::diff = false; #ifdef Q_OS_LINUX -const char* colorDelete = "\033[31m"; -const char* colorAdd = "\033[32m"; -const char* colorInfo = "\033[36m"; -const char* colorReset = "\033[0m"; +static const char colorDelete[] = "\033[31m"; +static const char colorAdd[] = "\033[32m"; +static const char colorInfo[] = "\033[36m"; +static const char colorReset[] = "\033[0m"; #else -const char* colorDelete = ""; -const char* colorAdd = ""; -const char* colorInfo = ""; -const char* colorReset = ""; +static const char colorDelete[] = ""; +static const char colorAdd[] = ""; +static const char colorInfo[] = ""; +static const char colorReset[] = ""; #endif FileOut::FileOut(QString n): diff --git a/sources/shiboken2/ApiExtractor/generator.qrc b/sources/shiboken2/ApiExtractor/generator.qrc deleted file mode 100644 index 2d82b37cb..000000000 --- a/sources/shiboken2/ApiExtractor/generator.qrc +++ /dev/null @@ -1,5 +0,0 @@ -<!DOCTYPE RCC><RCC version="1.0"> -<qresource prefix="/trolltech/generator/"> -<file alias="pp-qt-configuration">parser/rpp/pp-qt-configuration</file> -</qresource> -</RCC> diff --git a/sources/shiboken2/ApiExtractor/graph.cpp b/sources/shiboken2/ApiExtractor/graph.cpp index e6ee660dc..6ba4d994a 100644 --- a/sources/shiboken2/ApiExtractor/graph.cpp +++ b/sources/shiboken2/ApiExtractor/graph.cpp @@ -127,8 +127,7 @@ void Graph::dumpDot(const QHash< int, QString >& nodeNames, const QString& fileN QTextStream s(&output); s << "digraph D {\n"; for (int i = 0; i < m_d->edges.size(); ++i) { - GraphPrivate::EdgeIterator it = m_d->edges[i].begin(); - for (;it != m_d->edges[i].end(); ++it) + for (auto it = m_d->edges[i].cbegin(), end = m_d->edges[i].cend(); it != end; ++it) s << '"' << nodeNames[i] << "\" -> \"" << nodeNames[*it] << "\"\n"; } s << "}\n"; diff --git a/sources/shiboken2/ApiExtractor/parser/class_compiler.h b/sources/shiboken2/ApiExtractor/header_paths.h index 09b727fe6..f70709b7c 100644 --- a/sources/shiboken2/ApiExtractor/parser/class_compiler.h +++ b/sources/shiboken2/ApiExtractor/header_paths.h @@ -1,7 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org> +** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of PySide2. @@ -27,51 +26,41 @@ ** ****************************************************************************/ +#ifndef HEADER_PATHS_H +#define HEADER_PATHS_H -#ifndef CLASS_COMPILER_H -#define CLASS_COMPILER_H +#include <QByteArray> +#include <QList> +#include <QString> -#include <QtCore/qglobal.h> -#include <QtCore/QStringList> - -#include <default_visitor.h> -#include <name_compiler.h> -#include <type_compiler.h> - -class TokenStream; -class Binder; - -class ClassCompiler: protected DefaultVisitor -{ +class HeaderPath { public: - ClassCompiler(Binder *binder); - virtual ~ClassCompiler(); + explicit HeaderPath(const QByteArray &p = QByteArray()) : path(p), m_isFramework(false) {} + explicit HeaderPath(const QString &s = QString(), bool isFramework = false) : + path(s.toLatin1()), m_isFramework(isFramework) {} - inline QString name() const - { - return _M_name; - } + QByteArray path; + bool m_isFramework; // macOS framework path - inline QStringList baseClasses() const + static QByteArray includeOption(const HeaderPath &p, bool systemInclude = false) { - return _M_base_classes; - } + QByteArray option; - void run(ClassSpecifierAST *node); + if (p.m_isFramework) { + if (systemInclude) + option = QByteArrayLiteral("-iframework"); + else + option = QByteArrayLiteral("-F"); + } else if (systemInclude) { + option = QByteArrayLiteral("-isystem"); + } else { + option = QByteArrayLiteral("-I"); + } -protected: - virtual void visitClassSpecifier(ClassSpecifierAST *node); - virtual void visitBaseSpecifier(BaseSpecifierAST *node); - -private: - Binder *_M_binder; - TokenStream *_M_token_stream; - QString _M_name; - QStringList _M_base_classes; - NameCompiler name_cc; - TypeCompiler type_cc; + return option + p.path; + } }; -#endif // CLASS_COMPILER_H +typedef QList<HeaderPath> HeaderPaths; -// kate: space-indent on; indent-width 2; replace-tabs on; +#endif // HEADER_PATHS_H diff --git a/sources/shiboken2/ApiExtractor/include.h b/sources/shiboken2/ApiExtractor/include.h index e4ff5b309..dc4965e1a 100644 --- a/sources/shiboken2/ApiExtractor/include.h +++ b/sources/shiboken2/ApiExtractor/include.h @@ -30,7 +30,7 @@ #define INCLUDE_H #include <QString> -#include <QList> +#include <QVector> QT_BEGIN_NAMESPACE class QTextStream; @@ -87,6 +87,6 @@ QTextStream& operator<<(QTextStream& out, const Include& include); QDebug operator<<(QDebug d, const Include &i); #endif -typedef QList<Include> IncludeList; +typedef QVector<Include> IncludeList; #endif diff --git a/sources/shiboken2/ApiExtractor/parser/ast.cpp b/sources/shiboken2/ApiExtractor/parser/ast.cpp deleted file mode 100644 index a744704fe..000000000 --- a/sources/shiboken2/ApiExtractor/parser/ast.cpp +++ /dev/null @@ -1,38 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "ast.h" -#include "lexer.h" - -QString AST::toString(TokenStream *stream) const -{ - const Token &tk = stream->token((int) start_token); - const Token &end_tk = stream->token((int) end_token); - return QString::fromLatin1(tk.text + tk.position, end_tk.position - tk.position); -} diff --git a/sources/shiboken2/ApiExtractor/parser/ast.h b/sources/shiboken2/ApiExtractor/parser/ast.h deleted file mode 100644 index 7640b7c38..000000000 --- a/sources/shiboken2/ApiExtractor/parser/ast.h +++ /dev/null @@ -1,884 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#ifndef AST_H -#define AST_H - -#include "smallobject.h" -#include "list.h" - -#include <QString> - -#define DECLARE_AST_NODE(k) \ - enum { __node_kind = Kind_##k }; - -class TokenStream; - -struct AccessSpecifierAST; -struct AsmDefinitionAST; -struct BaseClauseAST; -struct BaseSpecifierAST; -struct BinaryExpressionAST; -struct CastExpressionAST; -struct ClassMemberAccessAST; -struct ClassSpecifierAST; -struct CompoundStatementAST; -struct ConditionAST; -struct ConditionalExpressionAST; -struct CppCastExpressionAST; -struct CtorInitializerAST; -struct DeclarationAST; -struct DeclarationStatementAST; -struct DeclaratorAST; -struct DeleteExpressionAST; -struct DoStatementAST; -struct ElaboratedTypeSpecifierAST; -struct EnumSpecifierAST; -struct EnumeratorAST; -struct ExceptionSpecificationAST; -struct ExpressionAST; -struct ExpressionOrDeclarationStatementAST; -struct ExpressionStatementAST; -struct ForStatementAST; -struct FunctionCallAST; -struct FunctionDefinitionAST; -struct IfStatementAST; -struct IncrDecrExpressionAST; -struct InitDeclaratorAST; -struct InitializerAST; -struct InitializerClauseAST; -struct LabeledStatementAST; -struct LinkageBodyAST; -struct LinkageSpecificationAST; -struct MemInitializerAST; -struct NameAST; -struct NamespaceAST; -struct NamespaceAliasDefinitionAST; -struct NewDeclaratorAST; -struct NewExpressionAST; -struct NewInitializerAST; -struct NewTypeIdAST; -struct OperatorAST; -struct OperatorFunctionIdAST; -struct ParameterDeclarationAST; -struct ParameterDeclarationClauseAST; -struct PostfixExpressionAST; -struct PrimaryExpressionAST; -struct PtrOperatorAST; -struct PtrToMemberAST; -struct ReturnStatementAST; -struct SimpleDeclarationAST; -struct SimpleTypeSpecifierAST; -struct SizeofExpressionAST; -struct StatementAST; -struct StringLiteralAST; -struct SubscriptExpressionAST; -struct SwitchStatementAST; -struct TemplateArgumentAST; -struct TemplateDeclarationAST; -struct TemplateParameterAST; -struct ThrowExpressionAST; -struct TranslationUnitAST; -struct TryBlockStatementAST; -struct TypeIdAST; -struct TypeIdentificationAST; -struct TypeParameterAST; -struct TypeSpecifierAST; -struct TypedefAST; -struct UnaryExpressionAST; -struct UnqualifiedNameAST; -struct UsingAST; -struct UsingDirectiveAST; -struct WhileStatementAST; -struct WinDeclSpecAST; -struct QPropertyAST; -struct QEnumsAST; - -struct AST -{ - enum NODE_KIND { - Kind_UNKNOWN = 0, - - Kind_AccessSpecifier, - Kind_AsmDefinition, - Kind_BaseClause, - Kind_BaseSpecifier, - Kind_BinaryExpression, - Kind_CastExpression, - Kind_ClassMemberAccess, - Kind_ClassSpecifier, - Kind_CompoundStatement, - Kind_Condition, - Kind_ConditionalExpression, - Kind_CppCastExpression, - Kind_CtorInitializer, - Kind_DeclarationStatement, - Kind_Declarator, - Kind_DeleteExpression, - Kind_DoStatement, - Kind_ElaboratedTypeSpecifier, - Kind_EnumSpecifier, - Kind_Enumerator, - Kind_ExceptionSpecification, - Kind_ExpressionOrDeclarationStatement, - Kind_ExpressionStatement, - Kind_ForStatement, - Kind_FunctionCall, - Kind_FunctionDefinition, - Kind_IfStatement, - Kind_IncrDecrExpression, - Kind_InitDeclarator, - Kind_Initializer, - Kind_InitializerClause, - Kind_LabeledStatement, - Kind_LinkageBody, - Kind_LinkageSpecification, - Kind_MemInitializer, - Kind_Name, - Kind_Namespace, - Kind_NamespaceAliasDefinition, - Kind_NewDeclarator, - Kind_NewExpression, - Kind_NewInitializer, - Kind_NewTypeId, - Kind_Operator, - Kind_OperatorFunctionId, - Kind_ParameterDeclaration, - Kind_ParameterDeclarationClause, - Kind_PostfixExpression, - Kind_PrimaryExpression, - Kind_PtrOperator, - Kind_PtrToMember, - Kind_ReturnStatement, - Kind_SimpleDeclaration, - Kind_SimpleTypeSpecifier, - Kind_SizeofExpression, - Kind_StringLiteral, - Kind_SubscriptExpression, - Kind_SwitchStatement, - Kind_TemplateArgument, - Kind_TemplateDeclaration, - Kind_TemplateParameter, - Kind_ThrowExpression, - Kind_TranslationUnit, - Kind_TryBlockStatement, - Kind_TypeId, - Kind_TypeIdentification, - Kind_TypeParameter, - Kind_Typedef, - Kind_UnaryExpression, - Kind_UnqualifiedName, - Kind_Using, - Kind_UsingDirective, - Kind_WhileStatement, - Kind_WinDeclSpec, - Kind_QPropertyAST, - Kind_ForwardDeclarationSpecifier, - Kind_QEnumsAST, - - NODE_KIND_COUNT - }; - - QString toString(TokenStream *stream) const; - - int kind; - - std::size_t start_token; - std::size_t end_token; -}; - -struct TypeSpecifierAST: public AST -{ - const ListNode<std::size_t> *cv; -}; - -struct StatementAST: public AST -{ -}; - -struct ExpressionAST: public AST -{ -}; - -struct DeclarationAST: public AST -{ -}; - -struct AccessSpecifierAST: public DeclarationAST -{ - DECLARE_AST_NODE(AccessSpecifier) - - const ListNode<std::size_t> *specs; -}; - -struct AsmDefinitionAST: public DeclarationAST -{ - DECLARE_AST_NODE(AsmDefinition) - - const ListNode<std::size_t> *cv; -}; - -struct BaseClauseAST: public AST -{ // ### kill me - DECLARE_AST_NODE(BaseClause) - - const ListNode<BaseSpecifierAST*> *base_specifiers; -}; - -struct BaseSpecifierAST: public AST -{ - DECLARE_AST_NODE(BaseSpecifier) - - std::size_t virt; - std::size_t access_specifier; - NameAST *name; -}; - -struct BinaryExpressionAST: public ExpressionAST -{ - DECLARE_AST_NODE(BinaryExpression) - - std::size_t op; - ExpressionAST *left_expression; - ExpressionAST *right_expression; -}; - -struct CastExpressionAST: public ExpressionAST -{ - DECLARE_AST_NODE(CastExpression) - - TypeIdAST *type_id; - ExpressionAST *expression; -}; - -struct ClassMemberAccessAST: public ExpressionAST -{ - DECLARE_AST_NODE(ClassMemberAccess) - - std::size_t op; - NameAST *name; -}; - -struct ClassSpecifierAST: public TypeSpecifierAST -{ - DECLARE_AST_NODE(ClassSpecifier) - - WinDeclSpecAST *win_decl_specifiers; - std::size_t class_key; - NameAST *name; - BaseClauseAST *base_clause; - const ListNode<DeclarationAST*> *member_specs; -}; - -struct ForwardDeclarationSpecifierAST: public TypeSpecifierAST -{ - DECLARE_AST_NODE(ForwardDeclarationSpecifier) - - std::size_t class_key; - NameAST *name; - BaseClauseAST *base_clause; -}; - -struct CompoundStatementAST: public StatementAST -{ - DECLARE_AST_NODE(CompoundStatement) - - const ListNode<StatementAST*> *statements; -}; - -struct ConditionAST: public AST -{ - DECLARE_AST_NODE(Condition) - - TypeSpecifierAST *type_specifier; - DeclaratorAST *declarator; - ExpressionAST *expression; -}; - -struct ConditionalExpressionAST: public ExpressionAST -{ - DECLARE_AST_NODE(ConditionalExpression) - - ExpressionAST *condition; - ExpressionAST *left_expression; - ExpressionAST *right_expression; -}; - -struct CppCastExpressionAST: public ExpressionAST -{ - DECLARE_AST_NODE(CppCastExpression) - - std::size_t op; - TypeIdAST *type_id; - ExpressionAST *expression; - const ListNode<ExpressionAST*> *sub_expressions; -}; - -struct CtorInitializerAST: public AST -{ - DECLARE_AST_NODE(CtorInitializer) - - std::size_t colon; - const ListNode<MemInitializerAST*> *member_initializers; -}; - -struct DeclarationStatementAST: public StatementAST -{ - DECLARE_AST_NODE(DeclarationStatement) - - DeclarationAST *declaration; -}; - -struct DeclaratorAST: public AST -{ - DECLARE_AST_NODE(Declarator) - - const ListNode<PtrOperatorAST*> *ptr_ops; - DeclaratorAST *sub_declarator; - NameAST *id; - ExpressionAST *bit_expression; - const ListNode<ExpressionAST*> *array_dimensions; - ParameterDeclarationClauseAST *parameter_declaration_clause; - const ListNode<std::size_t> *fun_cv; - ExceptionSpecificationAST *exception_spec; -}; - -struct DeleteExpressionAST: public ExpressionAST -{ - DECLARE_AST_NODE(DeleteExpression) - - std::size_t scope_token; - std::size_t delete_token; - std::size_t lbracket_token; - std::size_t rbracket_token; - ExpressionAST *expression; -}; - -struct DoStatementAST: public StatementAST -{ - DECLARE_AST_NODE(DoStatement) - - StatementAST *statement; - ExpressionAST *expression; -}; - -struct ElaboratedTypeSpecifierAST: public TypeSpecifierAST -{ - DECLARE_AST_NODE(ElaboratedTypeSpecifier) - - std::size_t type; - NameAST *name; -}; - -struct EnumSpecifierAST: public TypeSpecifierAST -{ - DECLARE_AST_NODE(EnumSpecifier) - - NameAST *name; - const ListNode<EnumeratorAST*> *enumerators; -}; - -struct EnumeratorAST: public AST -{ - DECLARE_AST_NODE(Enumerator) - - std::size_t id; - ExpressionAST *expression; -}; - -struct ExceptionSpecificationAST: public AST -{ - DECLARE_AST_NODE(ExceptionSpecification) - - std::size_t ellipsis; - const ListNode<TypeIdAST*> *type_ids; -}; - -struct ExpressionOrDeclarationStatementAST: public StatementAST -{ - DECLARE_AST_NODE(ExpressionOrDeclarationStatement) - - StatementAST *expression; - StatementAST *declaration; -}; - -struct ExpressionStatementAST: public StatementAST -{ - DECLARE_AST_NODE(ExpressionStatement) - - ExpressionAST *expression; -}; - -struct FunctionCallAST: public ExpressionAST -{ - DECLARE_AST_NODE(FunctionCall) - - ExpressionAST *arguments; -}; - -struct FunctionDefinitionAST: public DeclarationAST -{ - DECLARE_AST_NODE(FunctionDefinition) - - const ListNode<std::size_t> *storage_specifiers; - const ListNode<std::size_t> *function_specifiers; - TypeSpecifierAST *type_specifier; - InitDeclaratorAST *init_declarator; - StatementAST *function_body; - WinDeclSpecAST *win_decl_specifiers; -}; - -struct ForStatementAST: public StatementAST -{ - DECLARE_AST_NODE(ForStatement) - - StatementAST *init_statement; - ConditionAST *condition; - ExpressionAST *expression; - StatementAST *statement; -}; - -struct IfStatementAST: public StatementAST -{ - DECLARE_AST_NODE(IfStatement) - - ConditionAST *condition; - StatementAST *statement; - StatementAST *else_statement; -}; - -struct IncrDecrExpressionAST: public ExpressionAST -{ - DECLARE_AST_NODE(IncrDecrExpression) - - std::size_t op; -}; - -struct InitDeclaratorAST: public AST -{ - DECLARE_AST_NODE(InitDeclarator) - - DeclaratorAST *declarator; - InitializerAST *initializer; -}; - -struct InitializerAST: public AST -{ - DECLARE_AST_NODE(Initializer) - - InitializerClauseAST *initializer_clause; - ExpressionAST *expression; -}; - -struct InitializerClauseAST: public AST -{ - DECLARE_AST_NODE(InitializerClause) - - ExpressionAST *expression; -}; - -struct LabeledStatementAST: public StatementAST -{ - DECLARE_AST_NODE(LabeledStatement) -}; - -struct LinkageBodyAST: public AST -{ - DECLARE_AST_NODE(LinkageBody) - - const ListNode<DeclarationAST*> *declarations; -}; - -struct LinkageSpecificationAST: public DeclarationAST -{ - DECLARE_AST_NODE(LinkageSpecification) - - std::size_t extern_type; - LinkageBodyAST *linkage_body; - DeclarationAST *declaration; -}; - -struct MemInitializerAST: public AST -{ - DECLARE_AST_NODE(MemInitializer) - - NameAST *initializer_id; - ExpressionAST *expression; -}; - -struct NameAST: public AST -{ - DECLARE_AST_NODE(Name) - - bool global; - const ListNode<UnqualifiedNameAST*> *qualified_names; - UnqualifiedNameAST *unqualified_name; -}; - -struct NamespaceAST: public DeclarationAST -{ - DECLARE_AST_NODE(Namespace) - - std::size_t namespace_name; - LinkageBodyAST *linkage_body; -}; - -struct NamespaceAliasDefinitionAST: public DeclarationAST -{ - DECLARE_AST_NODE(NamespaceAliasDefinition) - - std::size_t namespace_name; - NameAST *alias_name; -}; - -struct NewDeclaratorAST: public AST -{ - DECLARE_AST_NODE(NewDeclarator) - - PtrOperatorAST *ptr_op; - NewDeclaratorAST *sub_declarator; - const ListNode<ExpressionAST*> *expressions; -}; - -struct NewExpressionAST: public ExpressionAST -{ - DECLARE_AST_NODE(NewExpression) - - std::size_t scope_token; - std::size_t new_token; - ExpressionAST *expression; - TypeIdAST *type_id; - NewTypeIdAST *new_type_id; - NewInitializerAST *new_initializer; -}; - -struct NewInitializerAST: public AST -{ - DECLARE_AST_NODE(NewInitializer) - - ExpressionAST *expression; -}; - -struct NewTypeIdAST: public AST -{ - DECLARE_AST_NODE(NewTypeId) - - TypeSpecifierAST *type_specifier; - NewInitializerAST *new_initializer; - NewDeclaratorAST *new_declarator; -}; - -struct OperatorAST: public AST -{ - DECLARE_AST_NODE(Operator) - - std::size_t op; - std::size_t open; - std::size_t close; -}; - -struct OperatorFunctionIdAST: public AST -{ - DECLARE_AST_NODE(OperatorFunctionId) - - OperatorAST *op; - TypeSpecifierAST *type_specifier; - const ListNode<PtrOperatorAST*> *ptr_ops; -}; - -struct ParameterDeclarationAST: public AST -{ - DECLARE_AST_NODE(ParameterDeclaration) - - TypeSpecifierAST *type_specifier; - DeclaratorAST *declarator; - ExpressionAST *expression; -}; - -struct ParameterDeclarationClauseAST: public AST -{ - DECLARE_AST_NODE(ParameterDeclarationClause) - - const ListNode<ParameterDeclarationAST*> *parameter_declarations; - std::size_t ellipsis; -}; - -struct PostfixExpressionAST: public ExpressionAST -{ - DECLARE_AST_NODE(PostfixExpression) - - TypeSpecifierAST *type_specifier; - ExpressionAST *expression; - const ListNode<ExpressionAST*> *sub_expressions; -}; - -struct PrimaryExpressionAST: public ExpressionAST -{ - DECLARE_AST_NODE(PrimaryExpression) - - StringLiteralAST *literal; - std::size_t token; - StatementAST *expression_statement; - ExpressionAST *sub_expression; - NameAST *name; -}; - -struct PtrOperatorAST: public AST -{ - DECLARE_AST_NODE(PtrOperator) - - const ListNode<std::size_t> *cv; - std::size_t op; - PtrToMemberAST *mem_ptr; -}; - -struct PtrToMemberAST: public AST -{ - DECLARE_AST_NODE(PtrToMember) -}; - -struct ReturnStatementAST: public StatementAST -{ - DECLARE_AST_NODE(ReturnStatement) - - ExpressionAST *expression; -}; - -struct SimpleDeclarationAST: public DeclarationAST -{ - DECLARE_AST_NODE(SimpleDeclaration) - - const ListNode<std::size_t> *storage_specifiers; - const ListNode<std::size_t> *function_specifiers; - TypeSpecifierAST *type_specifier; - const ListNode<InitDeclaratorAST*> *init_declarators; - WinDeclSpecAST *win_decl_specifiers; -}; - -struct SimpleTypeSpecifierAST: public TypeSpecifierAST -{ - DECLARE_AST_NODE(SimpleTypeSpecifier) - - const ListNode<std::size_t> *integrals; - std::size_t type_of; - TypeIdAST *type_id; - ExpressionAST *expression; - NameAST *name; -}; - -struct SizeofExpressionAST: public ExpressionAST -{ - DECLARE_AST_NODE(SizeofExpression) - - std::size_t sizeof_token; - TypeIdAST *type_id; - ExpressionAST *expression; -}; - -struct StringLiteralAST: public AST -{ - DECLARE_AST_NODE(StringLiteral) - - const ListNode<std::size_t> *literals; -}; - -struct SubscriptExpressionAST: public ExpressionAST -{ - DECLARE_AST_NODE(SubscriptExpression) - - ExpressionAST *subscript; -}; - -struct SwitchStatementAST: public StatementAST -{ - DECLARE_AST_NODE(SwitchStatement) - - ConditionAST *condition; - StatementAST *statement; -}; - -struct TemplateArgumentAST: public AST -{ - DECLARE_AST_NODE(TemplateArgument) - - TypeIdAST *type_id; - ExpressionAST *expression; -}; - -struct TemplateDeclarationAST: public DeclarationAST -{ - DECLARE_AST_NODE(TemplateDeclaration) - - std::size_t exported; - const ListNode<TemplateParameterAST*> *template_parameters; - DeclarationAST* declaration; -}; - -struct TemplateParameterAST: public AST -{ - DECLARE_AST_NODE(TemplateParameter) - - TypeParameterAST *type_parameter; - ParameterDeclarationAST *parameter_declaration; -}; - -struct ThrowExpressionAST: public ExpressionAST -{ - DECLARE_AST_NODE(ThrowExpression) - - std::size_t throw_token; - ExpressionAST *expression; -}; - -struct TranslationUnitAST: public AST -{ - DECLARE_AST_NODE(TranslationUnit) - - const ListNode<DeclarationAST*> *declarations; -}; - -struct TryBlockStatementAST: public StatementAST -{ - DECLARE_AST_NODE(TryBlockStatement) -}; - -struct TypeIdAST: public AST -{ - DECLARE_AST_NODE(TypeId) - - TypeSpecifierAST *type_specifier; - DeclaratorAST *declarator; -}; - -struct TypeIdentificationAST: public ExpressionAST -{ - DECLARE_AST_NODE(TypeIdentification) - - std::size_t typename_token; - NameAST *name; - ExpressionAST *expression; -}; - -struct TypeParameterAST: public AST -{ - DECLARE_AST_NODE(TypeParameter) - - std::size_t type; - NameAST *name; - TypeIdAST *type_id; - const ListNode<TemplateParameterAST*> *template_parameters; - NameAST *template_name; -}; - -struct TypedefAST: public DeclarationAST -{ - DECLARE_AST_NODE(Typedef) - - TypeSpecifierAST *type_specifier; - const ListNode<InitDeclaratorAST*> *init_declarators; -}; - -struct UnaryExpressionAST: public ExpressionAST -{ - DECLARE_AST_NODE(UnaryExpression) - - std::size_t op; - ExpressionAST *expression; -}; - -struct UnqualifiedNameAST: public AST -{ - DECLARE_AST_NODE(UnqualifiedName) - - std::size_t tilde; - std::size_t id; - OperatorFunctionIdAST *operator_id; - const ListNode<TemplateArgumentAST*> *template_arguments; -}; - -struct UsingAST: public DeclarationAST -{ - DECLARE_AST_NODE(Using) - - std::size_t type_name; - NameAST *name; -}; - -struct UsingDirectiveAST: public DeclarationAST -{ - DECLARE_AST_NODE(UsingDirective) - - NameAST *name; -}; - -struct WhileStatementAST: public StatementAST -{ - DECLARE_AST_NODE(WhileStatement) - - ConditionAST *condition; - StatementAST *statement; -}; - -struct WinDeclSpecAST: public AST -{ - DECLARE_AST_NODE(WinDeclSpec) - - std::size_t specifier; - std::size_t modifier; -}; - -struct QPropertyAST : public DeclarationAST -{ - DECLARE_AST_NODE(QPropertyAST) -}; - -struct QEnumsAST : public DeclarationAST -{ - DECLARE_AST_NODE(QEnumsAST) -}; - -template <class _Tp> -_Tp *CreateNode(pool *memory_pool) -{ - _Tp *node = reinterpret_cast<_Tp*>(memory_pool->allocate(sizeof(_Tp), strideof(_Tp))); - node->kind = _Tp::__node_kind; - return node; -} - -template <class _Tp> -_Tp ast_cast(AST *item) -{ - if (item && static_cast<_Tp>(0)->__node_kind == item->kind) - return static_cast<_Tp>(item); - - return 0; -} - -#endif // AST_H diff --git a/sources/shiboken2/ApiExtractor/parser/binder.cpp b/sources/shiboken2/ApiExtractor/parser/binder.cpp deleted file mode 100644 index 709f86c56..000000000 --- a/sources/shiboken2/ApiExtractor/parser/binder.cpp +++ /dev/null @@ -1,866 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "binder.h" -#include "lexer.h" -#include "control.h" -#include "symbol.h" -#include "codemodel_finder.h" -#include "class_compiler.h" -#include "compiler_utils.h" -#include "tokens.h" -#include "dumptree.h" - -#include <iostream> -#include <QDebug> - -Binder::Binder(CodeModel *__model, LocationManager &__location, Control *__control) - : _M_model(__model), - _M_location(__location), - _M_token_stream(&_M_location.token_stream), - _M_control(__control), - _M_current_function_type(CodeModel::Normal), - type_cc(this), - name_cc(this), - decl_cc(this) -{ - _M_qualified_types.insert(QLatin1String("char"), QString()); - _M_qualified_types.insert(QLatin1String("double"), QString()); - _M_qualified_types.insert(QLatin1String("float"), QString()); - _M_qualified_types.insert(QLatin1String("int"), QString()); - _M_qualified_types.insert(QLatin1String("long"), QString()); - _M_qualified_types.insert(QLatin1String("short"), QString()); - _M_qualified_types.insert(QLatin1String("void"), QString()); -} - -Binder::~Binder() -{ -} - -FileModelItem Binder::run(AST *node) -{ - FileModelItem old = _M_current_file; - _M_current_access = CodeModel::Public; - - _M_current_file.reset(new _FileModelItem(model())); - updateItemPosition(_M_current_file, node); - visit(node); - FileModelItem result = _M_current_file; - - _M_current_file = old; // restore - - return result; -} - -ScopeModelItem Binder::currentScope() -{ - if (_M_current_class) - return _M_current_class; - else if (_M_current_namespace) - return _M_current_namespace; - - return _M_current_file; -} - -TemplateParameterList Binder::changeTemplateParameters(TemplateParameterList templateParameters) -{ - TemplateParameterList old = _M_current_template_parameters; - _M_current_template_parameters = templateParameters; - return old; -} - -CodeModel::FunctionType Binder::changeCurrentFunctionType(CodeModel::FunctionType functionType) -{ - CodeModel::FunctionType old = _M_current_function_type; - _M_current_function_type = functionType; - return old; -} - -CodeModel::AccessPolicy Binder::changeCurrentAccess(CodeModel::AccessPolicy accessPolicy) -{ - CodeModel::AccessPolicy old = _M_current_access; - _M_current_access = accessPolicy; - return old; -} - -NamespaceModelItem Binder::changeCurrentNamespace(NamespaceModelItem item) -{ - NamespaceModelItem old = _M_current_namespace; - _M_current_namespace = item; - return old; -} - -ClassModelItem Binder::changeCurrentClass(ClassModelItem item) -{ - ClassModelItem old = _M_current_class; - _M_current_class = item; - return old; -} - -FunctionModelItem Binder::changeCurrentFunction(FunctionModelItem item) -{ - FunctionModelItem old = _M_current_function; - _M_current_function = item; - return old; -} - -int Binder::decode_token(std::size_t index) const -{ - return _M_token_stream->kind(index); -} - -CodeModel::AccessPolicy Binder::decode_access_policy(std::size_t index) const -{ - switch (decode_token(index)) { - case Token_class: - return CodeModel::Private; - - case Token_struct: - case Token_union: - return CodeModel::Public; - - default: - return CodeModel::Public; - } -} - -CodeModel::ClassType Binder::decode_class_type(std::size_t index) const -{ - switch (decode_token(index)) { - case Token_class: - return CodeModel::Class; - case Token_struct: - return CodeModel::Struct; - case Token_union: - return CodeModel::Union; - default: - std::cerr << "** WARNING unrecognized class type" << std::endl; - } - return CodeModel::Class; -} - -const NameSymbol *Binder::decode_symbol(std::size_t index) const -{ - return _M_token_stream->symbol(index); -} - -void Binder::visitAccessSpecifier(AccessSpecifierAST *node) -{ - const ListNode<std::size_t> *it = node->specs; - if (!it) - return; - - it = it->toFront(); - const ListNode<std::size_t> *end = it; - - do { - switch (decode_token(it->element)) { - default: - break; - - case Token_public: - changeCurrentAccess(CodeModel::Public); - changeCurrentFunctionType(CodeModel::Normal); - break; - case Token_protected: - changeCurrentAccess(CodeModel::Protected); - changeCurrentFunctionType(CodeModel::Normal); - break; - case Token_private: - changeCurrentAccess(CodeModel::Private); - changeCurrentFunctionType(CodeModel::Normal); - break; - case Token_signals: - changeCurrentAccess(CodeModel::Protected); - changeCurrentFunctionType(CodeModel::Signal); - break; - case Token_slots: - changeCurrentFunctionType(CodeModel::Slot); - break; - } - it = it->next; - } while (it != end); -} - -void Binder::visitSimpleDeclaration(SimpleDeclarationAST *node) -{ - visit(node->type_specifier); - - if (const ListNode<InitDeclaratorAST*> *it = node->init_declarators) { - it = it->toFront(); - const ListNode<InitDeclaratorAST*> *end = it; - do { - InitDeclaratorAST *init_declarator = it->element; - declare_symbol(node, init_declarator); - it = it->next; - } while (it != end); - } -} - -void Binder::declare_symbol(SimpleDeclarationAST *node, InitDeclaratorAST *init_declarator) -{ - DeclaratorAST *declarator = init_declarator->declarator; - - while (declarator && declarator->sub_declarator) - declarator = declarator->sub_declarator; - - NameAST *id = declarator->id; - if (!declarator->id) { - std::cerr << "** WARNING expected a declarator id" << std::endl; - return; - } - - CodeModelFinder finder(model(), this); - ScopeModelItem symbolScope = finder.resolveScope(id, currentScope()); - if (!symbolScope) { - name_cc.run(id); - std::cerr << "** WARNING scope not found for symbol:" - << qPrintable(name_cc.name()) << std::endl; - return; - } - - decl_cc.run(declarator); - - if (decl_cc.isFunction()) { - name_cc.run(id->unqualified_name); - - FunctionModelItem fun(new _FunctionModelItem(model(), name_cc.name())); - updateItemPosition(fun, node); - fun->setAccessPolicy(_M_current_access); - fun->setFunctionType(_M_current_function_type); - fun->setAbstract(init_declarator->initializer != 0); - fun->setConstant(declarator->fun_cv != 0); - fun->setTemplateParameters(_M_current_template_parameters); - applyStorageSpecifiers(node->storage_specifiers, fun); - applyFunctionSpecifiers(node->function_specifiers, fun); - - // build the type - TypeInfo typeInfo = CompilerUtils::typeDescription(node->type_specifier, - declarator, - this); - - fun->setType(qualifyType(typeInfo, symbolScope->qualifiedName())); - - - fun->setVariadics(decl_cc.isVariadics()); - - // ... and the signature - foreach (const DeclaratorCompiler::Parameter &p, decl_cc.parameters()) { - ArgumentModelItem arg(new _ArgumentModelItem(model(), p.name)); - arg->setType(qualifyType(p.type, _M_context)); - arg->setDefaultValue(p.defaultValue); - if (p.defaultValue) - arg->setDefaultValueExpression(p.defaultValueExpression); - fun->addArgument(arg); - } - - fun->setScope(symbolScope->qualifiedName()); - symbolScope->addFunction(fun); - } else { - VariableModelItem var(new _VariableModelItem(model())); - updateItemPosition(var, node); - var->setTemplateParameters(_M_current_template_parameters); - var->setAccessPolicy(_M_current_access); - name_cc.run(id->unqualified_name); - var->setName(name_cc.name()); - // Possible bug, because second parameter uses declarator instead of - // init_declarator->declarator like in DeclaratorCompiler::visitParameterDeclaration, - // but it doesn't seem to affect anything because the generator doesn't currently use - // variable declarations, only function declarations (because it cares about the API only, - // variable declarations are not exposed to the target language). - // See PYSIDE-455. - TypeInfo typeInfo = CompilerUtils::typeDescription(node->type_specifier, - declarator, - this); - if (declarator != init_declarator->declarator - && init_declarator->declarator->parameter_declaration_clause) { - typeInfo.setFunctionPointer(true); - decl_cc.run(init_declarator->declarator); - foreach (const DeclaratorCompiler::Parameter &p, decl_cc.parameters()) - typeInfo.addArgument(p.type); - } - - var->setType(qualifyType(typeInfo, _M_context)); - applyStorageSpecifiers(node->storage_specifiers, var); - - var->setScope(symbolScope->qualifiedName()); - symbolScope->addVariable(var); - } -} - -void Binder::visitFunctionDefinition(FunctionDefinitionAST *node) -{ - Q_ASSERT(node->init_declarator); - - ScopeModelItem scope = currentScope(); - - InitDeclaratorAST *init_declarator = node->init_declarator; - DeclaratorAST *declarator = init_declarator->declarator; - - // in the case of "void (func)()" or "void ((func))()" we need to - // skip to the inner most. This is in line with how the declarator - // node is generated in 'parser.cpp' - while (declarator && declarator->sub_declarator) - declarator = declarator->sub_declarator; - if (!declarator->id) { - std::cerr << "** WARNING temp hack for Qt 5.6.0: " - << "skipped a class that inherits from a private class" - << std::endl; - return; - } - Q_ASSERT(declarator->id); - - CodeModelFinder finder(model(), this); - - ScopeModelItem functionScope = finder.resolveScope(declarator->id, scope); - if (!functionScope) { - name_cc.run(declarator->id); - std::cerr << "** WARNING scope not found for function definition:" - << qPrintable(name_cc.name()) << std::endl - << "\tdefinition *ignored*" - << std::endl; - return; - } - - decl_cc.run(declarator); - - Q_ASSERT(!decl_cc.id().isEmpty()); - - FunctionModelItem - old = changeCurrentFunction(FunctionModelItem(new _FunctionModelItem(_M_model))); - _M_current_function->setScope(functionScope->qualifiedName()); - updateItemPosition(_M_current_function, node); - - Q_ASSERT(declarator->id->unqualified_name); - name_cc.run(declarator->id->unqualified_name); - QString unqualified_name = name_cc.name(); - - _M_current_function->setName(unqualified_name); - TypeInfo tmp_type = CompilerUtils::typeDescription(node->type_specifier, - declarator, this); - - _M_current_function->setType(qualifyType(tmp_type, _M_context)); - _M_current_function->setAccessPolicy(_M_current_access); - _M_current_function->setFunctionType(_M_current_function_type); - _M_current_function->setConstant(declarator->fun_cv); - _M_current_function->setTemplateParameters(_M_current_template_parameters); - - applyStorageSpecifiers(node->storage_specifiers, - _M_current_function); - applyFunctionSpecifiers(node->function_specifiers, - _M_current_function); - - _M_current_function->setVariadics(decl_cc.isVariadics()); - - foreach (const DeclaratorCompiler::Parameter &p, decl_cc.parameters()) { - ArgumentModelItem arg(new _ArgumentModelItem(model(), p.name)); - arg->setType(qualifyType(p.type, functionScope->qualifiedName())); - arg->setDefaultValue(p.defaultValue); - if (p.defaultValue) - arg->setDefaultValueExpression(p.defaultValueExpression); - _M_current_function->addArgument(arg); - } - - FunctionModelItem prototype = _M_current_function; - FunctionModelItem declared = functionScope->declaredFunction(prototype); - - // try to find a function declaration for this definition.. - if (!declared) { - functionScope->addFunction(prototype); - } else { - applyFunctionSpecifiers(node->function_specifiers, declared); - - // fix the function type and the access policy - _M_current_function->setAccessPolicy(declared->accessPolicy()); - _M_current_function->setFunctionType(declared->functionType()); - } - - changeCurrentFunction(old); -} - -void Binder::visitTemplateDeclaration(TemplateDeclarationAST *node) -{ - const ListNode<TemplateParameterAST*> *it = node->template_parameters; - if (!it) { - // QtScript: we want to visit the declaration still, so that - // e.g. QMetaTypeId<Foo> is added to the code model - visit(node->declaration); - return; - } - - TemplateParameterList savedTemplateParameters = changeTemplateParameters(TemplateParameterList()); - - it = it->toFront(); - const ListNode<TemplateParameterAST*> *end = it; - - TemplateParameterList templateParameters; - do { - TemplateParameterAST *parameter = it->element; - TypeParameterAST *type_parameter = parameter->type_parameter; - - NameAST *name; - if (!type_parameter) { - // A hacky hack to work around missing support for parameter declarations in - // templates. We just need the to get the name of the variable, since we - // aren't actually compiling these anyway. We are still not supporting much - // more, but we are refusing to fail for a few more declarations - if (!parameter->parameter_declaration || - !parameter->parameter_declaration->declarator || - !parameter->parameter_declaration->declarator->id) { - - /*std::cerr << "** WARNING template declaration not supported ``"; - Token const &tk = _M_token_stream->token ((int) node->start_token); - Token const &end_tk = _M_token_stream->token ((int) node->declaration->start_token); - - std::cerr << std::string (&tk.text[tk.position], (end_tk.position) - tk.position) << "''" - << std::endl << std::endl;*/ - - changeTemplateParameters(savedTemplateParameters); - return; - - } - - name = parameter->parameter_declaration->declarator->id; - } else { - int tk = decode_token(type_parameter->type); - if (tk != Token_typename && tk != Token_class) { - /*std::cerr << "** WARNING template declaration not supported ``"; - Token const &tk = _M_token_stream->token ((int) node->start_token); - Token const &end_tk = _M_token_stream->token ((int) node->declaration->start_token); - - std::cerr << std::string (&tk.text[tk.position], (end_tk.position) - tk.position) << "''" - << std::endl << std::endl;*/ - - changeTemplateParameters(savedTemplateParameters); - return; - } - assert(tk == Token_typename || tk == Token_class); - - name = type_parameter->name; - } - - - name_cc.run(name); - const TemplateParameterModelItem p(new _TemplateParameterModelItem(model(), name_cc.name())); - _M_current_template_parameters.append(p); - it = it->next; - } while (it != end); - - visit(node->declaration); - - changeTemplateParameters(savedTemplateParameters); -} - -void Binder::visitTypedef(TypedefAST *node) -{ - const ListNode<InitDeclaratorAST*> *it = node->init_declarators; - if (!it) - return; - - it = it->toFront(); - const ListNode<InitDeclaratorAST*> *end = it; - - do { - InitDeclaratorAST *init_declarator = it->element; - it = it->next; - - Q_ASSERT(init_declarator->declarator); - - // the name - decl_cc.run(init_declarator->declarator); - QString alias_name = decl_cc.id(); - - if (alias_name.isEmpty()) { - std::cerr << "** WARNING anonymous typedef not supported! ``"; - Token const &tk = _M_token_stream->token((int) node->start_token); - Token const &end_tk = _M_token_stream->token((int) node->end_token); - - std::cerr << std::string(&tk.text[tk.position], end_tk.position - tk.position) << "''" - << std::endl << std::endl; - continue; - } - - // build the type - TypeInfo typeInfo = CompilerUtils::typeDescription(node->type_specifier, - init_declarator->declarator, - this); - DeclaratorAST *decl = init_declarator->declarator; - while (decl && decl->sub_declarator) - decl = decl->sub_declarator; - - if (decl != init_declarator->declarator - && init_declarator->declarator->parameter_declaration_clause) { - typeInfo.setFunctionPointer(true); - decl_cc.run(init_declarator->declarator); - foreach (const DeclaratorCompiler::Parameter &p, decl_cc.parameters()) - typeInfo.addArgument(p.type); - } - - ScopeModelItem scope = currentScope(); - DeclaratorAST *declarator = init_declarator->declarator; - CodeModelFinder finder(model(), this); - ScopeModelItem typedefScope = finder.resolveScope(declarator->id, scope); - - TypeDefModelItem typeDef(new _TypeDefModelItem(model())); - updateItemPosition(typeDef, node); - typeDef->setName(alias_name); - typeDef->setType(qualifyType(typeInfo, currentScope()->qualifiedName())); - typeDef->setScope(typedefScope->qualifiedName()); - _M_qualified_types[typeDef->qualifiedName().join(QLatin1Char('.'))] = QString(); - currentScope()->addTypeDef(typeDef); - } while (it != end); -} - -void Binder::visitNamespace(NamespaceAST *node) -{ - bool anonymous = (node->namespace_name == 0); - - ScopeModelItem scope = currentScope(); - - NamespaceModelItem old; - if (!anonymous) { - QString name = decode_symbol(node->namespace_name)->as_string(); - - QStringList qualified_name = scope->qualifiedName(); - qualified_name += name; - const CodeModelItem nsI = _M_model->findItem(qualified_name, _M_current_file); - NamespaceModelItem ns = qSharedPointerDynamicCast<_NamespaceModelItem>(nsI); - if (!ns) { - ns.reset(new _NamespaceModelItem(_M_model)); - updateItemPosition(ns, node); - ns->setName(name); - ns->setScope(scope->qualifiedName()); - } - old = changeCurrentNamespace(ns); - - _M_context.append(name); - } - - DefaultVisitor::visitNamespace(node); - - if (!anonymous) { - Q_ASSERT(scope->kind() == _CodeModelItem::Kind_Namespace - || scope->kind() == _CodeModelItem::Kind_File); - - _M_context.removeLast(); - - if (const NamespaceModelItem ns = qSharedPointerDynamicCast<_NamespaceModelItem>(scope)) - ns->addNamespace(_M_current_namespace); - - changeCurrentNamespace(old); - } -} - -void Binder::visitForwardDeclarationSpecifier(ForwardDeclarationSpecifierAST *node) -{ - name_cc.run(node->name); - if (name_cc.name().isEmpty()) - return; - - ScopeModelItem scope = currentScope(); - _M_qualified_types[(scope->qualifiedName() + name_cc.qualifiedName()).join(QLatin1Char('.'))] = QString(); -} - -void Binder::visitClassSpecifier(ClassSpecifierAST *node) -{ - ClassCompiler class_cc(this); - class_cc.run(node); - - if (class_cc.name().isEmpty()) { - // anonymous not supported - return; - } - - Q_ASSERT(node->name && node->name->unqualified_name); - - ScopeModelItem scope = currentScope(); - - ClassModelItem old = changeCurrentClass(ClassModelItem(new _ClassModelItem(_M_model))); - updateItemPosition(_M_current_class, node); - _M_current_class->setName(class_cc.name()); - - QStringList baseClasses = class_cc.baseClasses(); - TypeInfo info; - for (int i = 0; i < baseClasses.size(); ++i) { - info.setQualifiedName(baseClasses.at(i).split(QLatin1String("::"))); - baseClasses[i] = qualifyType(info, scope->qualifiedName()).qualifiedName().join(QLatin1String("::")); - } - - _M_current_class->setBaseClasses(baseClasses); - _M_current_class->setClassType(decode_class_type(node->class_key)); - _M_current_class->setTemplateParameters(_M_current_template_parameters); - - if (!_M_current_template_parameters.isEmpty()) { - QString name = _M_current_class->name(); - name += QLatin1Char('<'); - for (int i = 0; i < _M_current_template_parameters.size(); ++i) { - if (i > 0) - name += QLatin1Char(','); - - name += _M_current_template_parameters.at(i)->name(); - } - - name += QLatin1Char('>'); - _M_current_class->setName(name); - } - - CodeModel::AccessPolicy oldAccessPolicy = changeCurrentAccess(decode_access_policy(node->class_key)); - CodeModel::FunctionType oldFunctionType = changeCurrentFunctionType(CodeModel::Normal); - - _M_current_class->setScope(scope->qualifiedName()); - _M_qualified_types[_M_current_class->qualifiedName().join(QLatin1Char('.'))] = QString(); - - scope->addClass(_M_current_class); - - name_cc.run(node->name->unqualified_name); - _M_context.append(name_cc.name()); - visitNodes(this, node->member_specs); - _M_context.removeLast(); - - changeCurrentClass(old); - changeCurrentAccess(oldAccessPolicy); - changeCurrentFunctionType(oldFunctionType); -} - -void Binder::visitLinkageSpecification(LinkageSpecificationAST *node) -{ - DefaultVisitor::visitLinkageSpecification(node); -} - -void Binder::visitUsing(UsingAST *node) -{ - DefaultVisitor::visitUsing(node); -} - -void Binder::visitEnumSpecifier(EnumSpecifierAST *node) -{ - CodeModelFinder finder(model(), this); - ScopeModelItem scope = currentScope(); - ScopeModelItem enumScope = finder.resolveScope(node->name, scope); - - name_cc.run(node->name); - QString name = name_cc.name(); - - bool isAnonymous = name.isEmpty(); - if (isAnonymous) { - // anonymous enum - QString key = _M_context.join(QLatin1String("::")); - int current = ++_M_anonymous_enums[key]; - name += QLatin1String("enum_"); - name += QString::number(current); - } - - _M_current_enum.reset(new _EnumModelItem(model())); - _M_current_enum->setAccessPolicy(_M_current_access); - updateItemPosition(_M_current_enum, node); - _M_current_enum->setName(name); - _M_current_enum->setAnonymous(isAnonymous); - _M_current_enum->setScope(enumScope->qualifiedName()); - - _M_qualified_types[_M_current_enum->qualifiedName().join(QLatin1Char('.'))] = QString(); - - enumScope->addEnum(_M_current_enum); - - DefaultVisitor::visitEnumSpecifier(node); - - _M_current_enum.clear(); -} - -static QString strip_preprocessor_lines(const QString &name) -{ - QStringList lst = name.split(QLatin1Char('\n')); - QString s; - for (int i = 0; i < lst.size(); ++i) { - if (!lst.at(i).startsWith(QLatin1Char('#'))) - s += lst.at(i); - } - return s.trimmed(); -} - -void Binder::visitEnumerator(EnumeratorAST *node) -{ - Q_ASSERT(_M_current_enum); - EnumeratorModelItem e(new _EnumeratorModelItem(model())); - updateItemPosition(e, node); - e->setName(decode_symbol(node->id)->as_string()); - - if (ExpressionAST *expr = node->expression) { - const Token &start_token = _M_token_stream->token((int) expr->start_token); - const Token &end_token = _M_token_stream->token((int) expr->end_token); - const QString token = QString::fromUtf8(&start_token.text[start_token.position], - (int)(end_token.position - start_token.position)); - QString lines = strip_preprocessor_lines(token.trimmed()); - lines.remove(QLatin1Char(' ')); - e->setValue(lines); - } - - _M_current_enum->addEnumerator(e); -} - -void Binder::visitUsingDirective(UsingDirectiveAST *node) -{ - DefaultVisitor::visitUsingDirective(node); -} - -void Binder::visitQEnums(QEnumsAST *node) -{ - const Token &start = _M_token_stream->token((int) node->start_token); - const Token &end = _M_token_stream->token((int) node->end_token); - QStringList enum_list = QString::fromLatin1(start.text + start.position, - end.position - start.position).split(QLatin1Char(' ')); - - ScopeModelItem scope = currentScope(); - for (int i = 0; i < enum_list.size(); ++i) - scope->addEnumsDeclaration(enum_list.at(i)); -} - -void Binder::visitQProperty(QPropertyAST *node) -{ - const Token &start = _M_token_stream->token((int) node->start_token); - const Token &end = _M_token_stream->token((int) node->end_token); - QString property = QString::fromLatin1(start.text + start.position, - end.position - start.position); - _M_current_class->addPropertyDeclaration(property); -} - -void Binder::applyStorageSpecifiers(const ListNode<std::size_t> *it, MemberModelItem item) -{ - if (!it) - return; - - it = it->toFront(); - const ListNode<std::size_t> *end = it; - - do { - switch (decode_token(it->element)) { - default: - break; - - case Token_friend: - item->setFriend(true); - break; - case Token_auto: - item->setAuto(true); - break; - case Token_register: - item->setRegister(true); - break; - case Token_static: - item->setStatic(true); - break; - case Token_extern: - item->setExtern(true); - break; - case Token_mutable: - item->setMutable(true); - break; - } - it = it->next; - } while (it != end); -} - -void Binder::applyFunctionSpecifiers(const ListNode<std::size_t> *it, FunctionModelItem item) -{ - if (!it) - return; - - it = it->toFront(); - const ListNode<std::size_t> *end = it; - - do { - switch (decode_token(it->element)) { - default: - break; - - case Token_inline: - item->setInline(true); - break; - - case Token_virtual: - item->setVirtual(true); - break; - - case Token_explicit: - item->setExplicit(true); - break; - - case Token_Q_INVOKABLE: - item->setInvokable(true); - break; - } - it = it->next; - } while (it != end); -} - -TypeInfo Binder::qualifyType(const TypeInfo &type, const QStringList &context) const -{ - // ### Potentially improve to use string list in the name table to - if (!context.size()) { - // ### We can assume that this means global namespace for now... - return type; - } else if (_M_qualified_types.contains(type.qualifiedName().join(QLatin1Char('.')))) { - return type; - } else { - QStringList expanded = context; - expanded << type.qualifiedName(); - if (_M_qualified_types.contains(expanded.join(QLatin1Char('.')))) { - TypeInfo modified_type = type; - modified_type.setQualifiedName(expanded); - return modified_type; - } else { - CodeModelItem scope = model()->findItem(context, _M_current_file); - - if (ClassModelItem klass = qSharedPointerDynamicCast<_ClassModelItem>(scope)) { - foreach (const QString &base, klass->baseClasses()) { - QStringList ctx = context; - ctx.removeLast(); - ctx.append(base); - - TypeInfo qualified = qualifyType(type, ctx); - if (qualified != type) - return qualified; - } - } - - QStringList copy = context; - copy.removeLast(); - return qualifyType(type, copy); - } - } -} - -void Binder::updateItemPosition(CodeModelItem item, AST *node) -{ - QString filename; - int line, column; - - assert(node); - _M_location.positionAt(_M_token_stream->position(node->start_token), &line, &column, &filename); - item->setFileName(filename); -} diff --git a/sources/shiboken2/ApiExtractor/parser/binder.h b/sources/shiboken2/ApiExtractor/parser/binder.h deleted file mode 100644 index cd8d93a95..000000000 --- a/sources/shiboken2/ApiExtractor/parser/binder.h +++ /dev/null @@ -1,133 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#ifndef BINDER_H -#define BINDER_H - -#include "default_visitor.h" -#include "codemodel.h" -#include "type_compiler.h" -#include "name_compiler.h" -#include "declarator_compiler.h" - -class TokenStream; -class LocationManager; -class Control; -struct NameSymbol; - -class Binder: protected DefaultVisitor -{ -public: - Binder(CodeModel *__model, LocationManager &__location, Control *__control = 0); - virtual ~Binder(); - - inline TokenStream *tokenStream() const - { - return _M_token_stream; - } - - inline CodeModel *model() const - { - return _M_model; - } - - ScopeModelItem currentScope(); - - FileModelItem run(AST *node); - -// utils - TypeInfo qualifyType(const TypeInfo &type, const QStringList &context) const; - -protected: - virtual void visitAccessSpecifier(AccessSpecifierAST *); - virtual void visitClassSpecifier(ClassSpecifierAST *); - virtual void visitEnumSpecifier(EnumSpecifierAST *); - virtual void visitEnumerator(EnumeratorAST *); - virtual void visitFunctionDefinition(FunctionDefinitionAST *); - virtual void visitLinkageSpecification(LinkageSpecificationAST *); - virtual void visitNamespace(NamespaceAST *); - virtual void visitSimpleDeclaration(SimpleDeclarationAST *); - virtual void visitTemplateDeclaration(TemplateDeclarationAST *); - virtual void visitTypedef(TypedefAST *); - virtual void visitUsing(UsingAST *); - virtual void visitUsingDirective(UsingDirectiveAST *); - virtual void visitQProperty(QPropertyAST *); - virtual void visitForwardDeclarationSpecifier(ForwardDeclarationSpecifierAST *); - virtual void visitQEnums(QEnumsAST *); - -private: - - int decode_token(std::size_t index) const; - const NameSymbol *decode_symbol(std::size_t index) const; - CodeModel::AccessPolicy decode_access_policy(std::size_t index) const; - CodeModel::ClassType decode_class_type(std::size_t index) const; - - CodeModel::FunctionType changeCurrentFunctionType(CodeModel::FunctionType functionType); - CodeModel::AccessPolicy changeCurrentAccess(CodeModel::AccessPolicy accessPolicy); - NamespaceModelItem changeCurrentNamespace(NamespaceModelItem item); - ClassModelItem changeCurrentClass(ClassModelItem item); - FunctionModelItem changeCurrentFunction(FunctionModelItem item); - TemplateParameterList changeTemplateParameters(TemplateParameterList templateParameters); - - void declare_symbol(SimpleDeclarationAST *node, InitDeclaratorAST *init_declarator); - - void applyStorageSpecifiers(const ListNode<std::size_t> *storage_specifiers, MemberModelItem item); - void applyFunctionSpecifiers(const ListNode<std::size_t> *it, FunctionModelItem item); - - void updateItemPosition(CodeModelItem item, AST *node); - -private: - CodeModel *_M_model; - LocationManager &_M_location; - TokenStream *_M_token_stream; - Control *_M_control; - - CodeModel::FunctionType _M_current_function_type; - CodeModel::AccessPolicy _M_current_access; - FileModelItem _M_current_file; - NamespaceModelItem _M_current_namespace; - ClassModelItem _M_current_class; - FunctionModelItem _M_current_function; - EnumModelItem _M_current_enum; - QStringList _M_context; - TemplateParameterList _M_current_template_parameters; // ### check me - QHash<QString, QString> _M_qualified_types; - QHash<QString, int> _M_anonymous_enums; - void dummy() { - _M_control=0; - } - -protected: - TypeCompiler type_cc; - NameCompiler name_cc; - DeclaratorCompiler decl_cc; -}; - -#endif // BINDER_H diff --git a/sources/shiboken2/ApiExtractor/parser/class_compiler.cpp b/sources/shiboken2/ApiExtractor/parser/class_compiler.cpp deleted file mode 100644 index 3387412ff..000000000 --- a/sources/shiboken2/ApiExtractor/parser/class_compiler.cpp +++ /dev/null @@ -1,71 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#include "class_compiler.h" -#include "lexer.h" -#include "binder.h" - -ClassCompiler::ClassCompiler(Binder *binder) - : _M_binder(binder), - _M_token_stream(binder->tokenStream()), - name_cc(_M_binder), - type_cc(_M_binder) -{ -} - -ClassCompiler::~ClassCompiler() -{ -} - -void ClassCompiler::run(ClassSpecifierAST *node) -{ - name_cc.run(node->name); - _M_name = name_cc.name(); - _M_base_classes.clear(); - - visit(node); -} - -void ClassCompiler::visitClassSpecifier(ClassSpecifierAST *node) -{ - visit(node->base_clause); -} - -void ClassCompiler::visitBaseSpecifier(BaseSpecifierAST *node) -{ - name_cc.run(node->name); - QString name = name_cc.name(); - - if (!name.isEmpty()) - _M_base_classes.append(name); -} - - -// kate: space-indent on; indent-width 2; replace-tabs on; diff --git a/sources/shiboken2/ApiExtractor/parser/codemodel.cpp b/sources/shiboken2/ApiExtractor/parser/codemodel.cpp index a5024c4a3..a35ca314b 100644 --- a/sources/shiboken2/ApiExtractor/parser/codemodel.cpp +++ b/sources/shiboken2/ApiExtractor/parser/codemodel.cpp @@ -47,9 +47,9 @@ private: }; template <class T> -static QSharedPointer<T> findModelItem(const QList<QSharedPointer<T> > &list, const QString &name) +static QSharedPointer<T> findModelItem(const QVector<QSharedPointer<T> > &list, const QString &name) { - typedef typename QList<QSharedPointer<T> >::const_iterator It; + typedef typename QVector<QSharedPointer<T> >::const_iterator It; const It it = std::find_if(list.begin(), list.end(), ModelItemNamePredicate<T>(name)); return it != list.end() ? *it : QSharedPointer<T>(); } @@ -221,7 +221,7 @@ QString TypeInfo::toString() const tmp += QLatin1Char(')'); } - foreach(QString elt, arrayElements()) { + for (const QString &elt : m_arrayElements) { tmp += QLatin1Char('['); tmp += elt; tmp += QLatin1Char(']'); @@ -230,7 +230,7 @@ QString TypeInfo::toString() const return tmp; } -bool TypeInfo::operator==(const TypeInfo &other) +bool TypeInfo::operator==(const TypeInfo &other) const { if (arrayElements().count() != other.arrayElements().count()) return false; @@ -514,16 +514,6 @@ _ClassModelItem::~_ClassModelItem() { } -QStringList _ClassModelItem::baseClasses() const -{ - return m_baseClasses; -} - -void _ClassModelItem::setBaseClasses(const QStringList &baseClasses) -{ - m_baseClasses = baseClasses; -} - TemplateParameterList _ClassModelItem::templateParameters() const { return m_templateParameters; @@ -534,14 +524,21 @@ void _ClassModelItem::setTemplateParameters(const TemplateParameterList &templat m_templateParameters = templateParameters; } -void _ClassModelItem::addBaseClass(const QString &baseClass) +void _ClassModelItem::addBaseClass(const QString &name, CodeModel::AccessPolicy accessPolicy) { + _ClassModelItem::BaseClass baseClass; + baseClass.name = name; + baseClass.accessPolicy = accessPolicy; m_baseClasses.append(baseClass); } bool _ClassModelItem::extendsClass(const QString &name) const { - return m_baseClasses.contains(name); + for (const BaseClass &bc : m_baseClasses) { + if (bc.name == name) + return true; + } + return false; } void _ClassModelItem::setClassType(CodeModel::ClassType type) @@ -578,8 +575,17 @@ static void formatModelItemList(QDebug &d, const char *prefix, const List &l, void _ClassModelItem::formatDebug(QDebug &d) const { _CodeModelItem::formatDebug(d); - if (!m_baseClasses.isEmpty()) - d << ", inherits=" << m_baseClasses; + if (!m_baseClasses.isEmpty()) { + if (m_final) + d << " [final]"; + d << ", inherits="; + d << ", inherits="; + for (int i = 0, size = m_baseClasses.size(); i < size; ++i) { + if (i) + d << ", "; + d << m_baseClasses.at(i).name << " (" << m_baseClasses.at(i).accessPolicy << ')'; + } + } formatModelItemList(d, ", templateParameters=", m_templateParameters); formatScopeItemsDebug(d); } @@ -588,7 +594,7 @@ void _ClassModelItem::formatDebug(QDebug &d) const // --------------------------------------------------------------------------- FunctionModelItem _ScopeModelItem::declaredFunction(FunctionModelItem item) { - foreach (const FunctionModelItem &fun, m_functions) { + for (const FunctionModelItem &fun : qAsConst(m_functions)) { if (fun->name() == item->name() && fun->isSimilar(item)) return fun; @@ -730,7 +736,7 @@ EnumModelItem _ScopeModelItem::findEnum(const QString &name) const FunctionList _ScopeModelItem::findFunctions(const QString &name) const { FunctionList result; - foreach (const FunctionModelItem &func, m_functions) { + for (const FunctionModelItem &func : m_functions) { if (func->name() == name) result.append(func); } @@ -742,6 +748,14 @@ _NamespaceModelItem::~_NamespaceModelItem() { } +QSet<NamespaceModelItem> _NamespaceModelItem::uniqueNamespaces() const +{ + QSet<NamespaceModelItem> result; + for (const NamespaceModelItem &n : m_namespaces) + result.insert(n); + return result; +} + void _NamespaceModelItem::addNamespace(NamespaceModelItem item) { m_namespaces.append(item); @@ -875,6 +889,26 @@ bool _FunctionModelItem::isInline() const return m_isInline; } +bool _FunctionModelItem::isOverride() const +{ + return m_isOverride; +} + +void _FunctionModelItem::setOverride(bool o) +{ + m_isOverride = o; +} + +bool _FunctionModelItem::isFinal() const +{ + return m_isFinal; +} + +void _FunctionModelItem::setFinal(bool f) +{ + m_isFinal = f; +} + void _FunctionModelItem::setInline(bool isInline) { m_isInline = isInline; @@ -918,6 +952,12 @@ void _FunctionModelItem::formatDebug(QDebug &d) const d << ", type=" << m_functionType; if (m_isInline) d << " [inline]"; + if (m_isVirtual) + d << " [virtual]"; + if (m_isOverride) + d << " [override]"; + if (m_isFinal) + d << " [final]"; if (m_isAbstract) d << " [abstract]"; if (m_isExplicit) diff --git a/sources/shiboken2/ApiExtractor/parser/codemodel.h b/sources/shiboken2/ApiExtractor/parser/codemodel.h index 811cfec3e..2aaea1f78 100644 --- a/sources/shiboken2/ApiExtractor/parser/codemodel.h +++ b/sources/shiboken2/ApiExtractor/parser/codemodel.h @@ -35,7 +35,6 @@ #include "codemodel_enums.h" #include <QtCore/QHash> -#include <QtCore/QList> #include <QtCore/QSet> #include <QtCore/QString> #include <QtCore/QStringList> @@ -57,6 +56,10 @@ public: enum FunctionType { Normal, + Constructor, + CopyConstructor, + MoveConstructor, + Destructor, Signal, Slot }; @@ -158,21 +161,18 @@ public: m_arrayElements = arrayElements; } - QList<TypeInfo> arguments() const - { - return m_arguments; - } + QVector<TypeInfo> arguments() const { return m_arguments; } - void setArguments(const QList<TypeInfo> &arguments); + void setArguments(const QVector<TypeInfo> &arguments); void addArgument(const TypeInfo &arg) { m_arguments.append(arg); } - bool operator==(const TypeInfo &other); + bool operator==(const TypeInfo &other) const; - bool operator!=(const TypeInfo &other) + bool operator!=(const TypeInfo &other) const { return !(*this == other); } @@ -193,7 +193,7 @@ private: QStringList m_qualifiedName; QStringList m_arrayElements; - QList<TypeInfo> m_arguments; + QVector<TypeInfo> m_arguments; union { uint flags; @@ -320,7 +320,7 @@ public: FunctionModelItem declaredFunction(FunctionModelItem item); #ifndef QT_NO_DEBUG_STREAM - void formatDebug(QDebug &d) const Q_DECL_OVERRIDE; + void formatDebug(QDebug &d) const override; #endif protected: @@ -349,16 +349,21 @@ class _ClassModelItem: public _ScopeModelItem public: DECLARE_MODEL_NODE(Class) + struct BaseClass + { + QString name; + CodeModel::AccessPolicy accessPolicy = CodeModel::Public; + }; + explicit _ClassModelItem(CodeModel *model, int kind = __node_kind) : _ScopeModelItem(model, kind), m_classType(CodeModel::Class) {} explicit _ClassModelItem(CodeModel *model, const QString &name, int kind = __node_kind) : _ScopeModelItem(model, name, kind), m_classType(CodeModel::Class) {} ~_ClassModelItem(); - QStringList baseClasses() const; + QVector<BaseClass> baseClasses() const { return m_baseClasses; } - void setBaseClasses(const QStringList &baseClasses); - void addBaseClass(const QString &baseClass); + void addBaseClass(const QString &name, CodeModel::AccessPolicy accessPolicy); TemplateParameterList templateParameters() const; void setTemplateParameters(const TemplateParameterList &templateParameters); @@ -371,16 +376,20 @@ public: void addPropertyDeclaration(const QString &propertyDeclaration); QStringList propertyDeclarations() const { return m_propertyDeclarations; } + bool isFinal() const { return m_final; } + void setFinal(bool f) { m_final = f; } + #ifndef QT_NO_DEBUG_STREAM - void formatDebug(QDebug &d) const Q_DECL_OVERRIDE; + void formatDebug(QDebug &d) const override; #endif private: - QStringList m_baseClasses; + QVector<BaseClass> m_baseClasses; TemplateParameterList m_templateParameters; CodeModel::ClassType m_classType; QStringList m_propertyDeclarations; + bool m_final = false; }; class _NamespaceModelItem: public _ScopeModelItem @@ -395,14 +404,14 @@ public: ~_NamespaceModelItem(); NamespaceList namespaces() const { return m_namespaces; } - QSet<NamespaceModelItem> uniqueNamespaces() const { return m_namespaces.toSet(); } + QSet<NamespaceModelItem> uniqueNamespaces() const; void addNamespace(NamespaceModelItem item); NamespaceModelItem findNamespace(const QString &name) const; #ifndef QT_NO_DEBUG_STREAM - void formatDebug(QDebug &d) const Q_DECL_OVERRIDE; + void formatDebug(QDebug &d) const override; #endif private: @@ -442,7 +451,7 @@ public: void setDefaultValueExpression(const QString &expr) { m_defaultValueExpression = expr; } #ifndef QT_NO_DEBUG_STREAM - void formatDebug(QDebug &d) const Q_DECL_OVERRIDE; + void formatDebug(QDebug &d) const override; #endif private: @@ -496,7 +505,7 @@ public: void setType(const TypeInfo &type); #ifndef QT_NO_DEBUG_STREAM - void formatDebug(QDebug &d) const Q_DECL_OVERRIDE; + void formatDebug(QDebug &d) const override; #endif private: @@ -540,6 +549,12 @@ public: bool isVirtual() const; void setVirtual(bool isVirtual); + bool isOverride() const; + void setOverride(bool o); + + bool isFinal() const; + void setFinal(bool f); + bool isInline() const; void setInline(bool isInline); @@ -558,7 +573,7 @@ public: bool isSimilar(FunctionModelItem other) const; #ifndef QT_NO_DEBUG_STREAM - void formatDebug(QDebug &d) const Q_DECL_OVERRIDE; + void formatDebug(QDebug &d) const override; #endif private: @@ -567,6 +582,8 @@ private: union { struct { uint m_isVirtual: 1; + uint m_isOverride: 1; + uint m_isFinal: 1; uint m_isInline: 1; uint m_isAbstract: 1; uint m_isExplicit: 1; @@ -602,7 +619,7 @@ public: void setType(const TypeInfo &type); #ifndef QT_NO_DEBUG_STREAM - void formatDebug(QDebug &d) const Q_DECL_OVERRIDE; + void formatDebug(QDebug &d) const override; #endif private: @@ -629,7 +646,7 @@ public: void setAnonymous(bool anonymous); #ifndef QT_NO_DEBUG_STREAM - void formatDebug(QDebug &d) const Q_DECL_OVERRIDE; + void formatDebug(QDebug &d) const override; #endif private: @@ -653,7 +670,7 @@ public: void setValue(const QString &value); #ifndef QT_NO_DEBUG_STREAM - void formatDebug(QDebug &d) const Q_DECL_OVERRIDE; + void formatDebug(QDebug &d) const override; #endif private: @@ -678,7 +695,7 @@ public: void setDefaultValue(bool defaultValue); #ifndef QT_NO_DEBUG_STREAM - void formatDebug(QDebug &d) const Q_DECL_OVERRIDE; + void formatDebug(QDebug &d) const override; #endif private: diff --git a/sources/shiboken2/ApiExtractor/parser/codemodel_finder.cpp b/sources/shiboken2/ApiExtractor/parser/codemodel_finder.cpp deleted file mode 100644 index 57f8ae0cf..000000000 --- a/sources/shiboken2/ApiExtractor/parser/codemodel_finder.cpp +++ /dev/null @@ -1,103 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "codemodel_finder.h" -#include "codemodel.h" -#include "binder.h" - -CodeModelFinder::CodeModelFinder(CodeModel *model, Binder *binder) - : _M_model(model), - _M_binder(binder), - _M_token_stream(binder->tokenStream()), - name_cc(_M_binder), - _M_resolve_policy(ResolveItem) -{ -} - -CodeModelFinder::~CodeModelFinder() -{ -} - -ScopeModelItem CodeModelFinder::resolveScope(NameAST *name, ScopeModelItem scope) -{ - Q_ASSERT(scope); - - ResolvePolicy saved_resolve_policy = _M_resolve_policy; - _M_resolve_policy = ResolveScope; - - ScopeModelItem old = changeCurrentScope(scope); - - visit(name); - ScopeModelItem result = _M_current_scope; - - changeCurrentScope(old); // restore - - _M_resolve_policy = saved_resolve_policy; - - return result; -} - -ScopeModelItem CodeModelFinder::changeCurrentScope(ScopeModelItem scope) -{ - ScopeModelItem old = _M_current_scope; - _M_current_scope = scope; - return old; -} - -void CodeModelFinder::visitName(NameAST *node) -{ - visitNodes(this, node->qualified_names); - - if (_M_resolve_policy == ResolveItem) - visit(node->unqualified_name); -} - -void CodeModelFinder::visitUnqualifiedName(UnqualifiedNameAST *node) -{ - if (!_M_current_scope) { - // nothing to do - return; - } - - name_cc.run(node); - QString id = name_cc.name(); - - if (ClassModelItem klass = _M_current_scope->findClass(id)) { - _M_current_scope = klass; - } else if (NamespaceModelItem parentNamespace = qSharedPointerDynamicCast<_NamespaceModelItem>(_M_current_scope)) { - NamespaceModelItem ns = parentNamespace->findNamespace(id); - _M_current_scope = ns; - } else if (FileModelItem file = qSharedPointerDynamicCast<_FileModelItem>(_M_current_scope)) { - NamespaceModelItem ns = file->findNamespace(id); - _M_current_scope = ns; - } -} - -// kate: space-indent on; indent-width 2; replace-tabs on; - diff --git a/sources/shiboken2/ApiExtractor/parser/codemodel_finder.h b/sources/shiboken2/ApiExtractor/parser/codemodel_finder.h deleted file mode 100644 index 0217cbac6..000000000 --- a/sources/shiboken2/ApiExtractor/parser/codemodel_finder.h +++ /dev/null @@ -1,75 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#ifndef CODEMODEL_FINDER_H -#define CODEMODEL_FINDER_H - -#include <default_visitor.h> -#include <codemodel_fwd.h> -#include <name_compiler.h> - -class TokenStream; -class Binder; - -class CodeModelFinder: protected DefaultVisitor -{ - enum ResolvePolicy { - ResolveScope, - ResolveItem - }; - -public: - CodeModelFinder(CodeModel *model, Binder *binder); - virtual ~CodeModelFinder(); - - ScopeModelItem resolveScope(NameAST *name, ScopeModelItem scope); - - inline CodeModel *model() const - { - return _M_model; - } - -protected: - virtual void visitName(NameAST *node); - virtual void visitUnqualifiedName(UnqualifiedNameAST *node); - - ScopeModelItem changeCurrentScope(ScopeModelItem scope); - -private: - CodeModel *_M_model; - Binder *_M_binder; - TokenStream *_M_token_stream; - NameCompiler name_cc; - - ScopeModelItem _M_current_scope; - ResolvePolicy _M_resolve_policy; -}; - -#endif // CODEMODEL_FINDER_H diff --git a/sources/shiboken2/ApiExtractor/parser/codemodel_fwd.h b/sources/shiboken2/ApiExtractor/parser/codemodel_fwd.h index 676bda872..d5a9f2850 100644 --- a/sources/shiboken2/ApiExtractor/parser/codemodel_fwd.h +++ b/sources/shiboken2/ApiExtractor/parser/codemodel_fwd.h @@ -31,7 +31,7 @@ #ifndef CODEMODEL_FWD_H #define CODEMODEL_FWD_H -#include <QtCore/QList> +#include <QtCore/QVector> #include <QtCore/QSharedPointer> // forward declarations @@ -65,18 +65,18 @@ typedef QSharedPointer<_TypeDefModelItem> TypeDefModelItem; typedef QSharedPointer<_VariableModelItem> VariableModelItem; typedef QSharedPointer<_MemberModelItem> MemberModelItem; -typedef QList<ArgumentModelItem> ArgumentList; -typedef QList<ClassModelItem> ClassList; -typedef QList<CodeModelItem> ItemList; -typedef QList<EnumModelItem> EnumList; -typedef QList<EnumeratorModelItem> EnumeratorList; -typedef QList<FileModelItem> FileList; -typedef QList<FunctionModelItem> FunctionList; -typedef QList<NamespaceModelItem> NamespaceList; -typedef QList<ScopeModelItem> ScopeList; -typedef QList<TemplateParameterModelItem> TemplateParameterList; -typedef QList<TypeDefModelItem> TypeDefList; -typedef QList<VariableModelItem> VariableList; -typedef QList<MemberModelItem> MemberList; +typedef QVector<ArgumentModelItem> ArgumentList; +typedef QVector<ClassModelItem> ClassList; +typedef QVector<CodeModelItem> ItemList; +typedef QVector<EnumModelItem> EnumList; +typedef QVector<EnumeratorModelItem> EnumeratorList; +typedef QVector<FileModelItem> FileList; +typedef QVector<FunctionModelItem> FunctionList; +typedef QVector<NamespaceModelItem> NamespaceList; +typedef QVector<ScopeModelItem> ScopeList; +typedef QVector<TemplateParameterModelItem> TemplateParameterList; +typedef QVector<TypeDefModelItem> TypeDefList; +typedef QVector<VariableModelItem> VariableList; +typedef QVector<MemberModelItem> MemberList; #endif // CODEMODEL_FWD_H diff --git a/sources/shiboken2/ApiExtractor/parser/compiler_utils.cpp b/sources/shiboken2/ApiExtractor/parser/compiler_utils.cpp deleted file mode 100644 index 95a9db6c3..000000000 --- a/sources/shiboken2/ApiExtractor/parser/compiler_utils.cpp +++ /dev/null @@ -1,55 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#include "compiler_utils.h" -#include "type_compiler.h" -#include "name_compiler.h" -#include "declarator_compiler.h" -#include "ast.h" -#include "binder.h" - -TypeInfo CompilerUtils::typeDescription(TypeSpecifierAST *type_specifier, DeclaratorAST *declarator, Binder *binder) -{ - TypeCompiler type_cc(binder); - DeclaratorCompiler decl_cc(binder); - - type_cc.run(type_specifier); - decl_cc.run(declarator); - - TypeInfo typeInfo; - typeInfo.setQualifiedName(type_cc.qualifiedName()); - typeInfo.setConstant(type_cc.isConstant()); - typeInfo.setVolatile(type_cc.isVolatile()); - typeInfo.setReferenceType(decl_cc.isReference() ? LValueReference : NoReference); - typeInfo.setIndirections(decl_cc.indirection()); - typeInfo.setArrayElements(decl_cc.arrayElements()); - - return typeInfo; -} diff --git a/sources/shiboken2/ApiExtractor/parser/control.cpp b/sources/shiboken2/ApiExtractor/parser/control.cpp deleted file mode 100644 index f86fa16bb..000000000 --- a/sources/shiboken2/ApiExtractor/parser/control.cpp +++ /dev/null @@ -1,135 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#include "control.h" -#include "lexer.h" - -Control::Control() - : current_context(0), - _M_skipFunctionBody(false), - _M_lexer(0), - _M_parser(0) -{ - pushContext(); - - declareTypedef(findOrInsertName("__builtin_va_list", - strlen("__builtin_va_list")), 0); -} - -Control::~Control() -{ - popContext(); - - Q_ASSERT(current_context == 0); -} - -Lexer *Control::changeLexer(Lexer *lexer) -{ - Lexer *old = _M_lexer; - _M_lexer = lexer; - return old; -} - -Parser *Control::changeParser(Parser *parser) -{ - Parser *old = _M_parser; - _M_parser = parser; - return old; -} - -Type *Control::lookupType(const NameSymbol *name) const -{ - Q_ASSERT(current_context != 0); - - return current_context->resolve(name); -} - -void Control::declare(const NameSymbol *name, Type *type) -{ - //printf("*** Declare:"); - //printSymbol(name); - //putchar('\n'); - Q_ASSERT(current_context != 0); - - current_context->bind(name, type); -} - -void Control::pushContext() -{ - // printf("+Context\n"); - Context *new_context = new Context; - new_context->parent = current_context; - current_context = new_context; -} - -void Control::popContext() -{ - // printf("-Context\n"); - Q_ASSERT(current_context != 0); - - Context *old_context = current_context; - current_context = current_context->parent; - - delete old_context; -} - -void Control::declareTypedef(const NameSymbol *name, Declarator *d) -{ - // printf("declared typedef:"); - // printSymbol(name); - // printf("\n"); - stl_typedef_table.insert(name, d); -} - -bool Control::isTypedef(const NameSymbol *name) const -{ - // printf("is typedef:"); - // printSymbol(name); - // printf("= %d\n", (stl_typedef_table.find(name) != stl_typedef_table.end())); - - return stl_typedef_table.contains(name); -} - -QList<Control::ErrorMessage> Control::errorMessages() const -{ - return _M_error_messages; -} - -void Control::clearErrorMessages() -{ - _M_error_messages.clear(); -} - -void Control::reportError(const ErrorMessage &errmsg) -{ - _M_error_messages.append(errmsg); -} - -// kate: space-indent on; indent-width 2; replace-tabs on; diff --git a/sources/shiboken2/ApiExtractor/parser/control.h b/sources/shiboken2/ApiExtractor/parser/control.h deleted file mode 100644 index 92635299e..000000000 --- a/sources/shiboken2/ApiExtractor/parser/control.h +++ /dev/null @@ -1,165 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#ifndef CONTROL_H -#define CONTROL_H - -#include "symbol.h" -#include "smallobject.h" - -#include <QtCore/QHash> - -struct Declarator; -struct Type; -class Lexer; -class Parser; - -struct Context { - Context *parent; - - inline void bind(const NameSymbol *name, Type *type) { - symbol_table.insert(name, type); - } - - inline Type *resolve(const NameSymbol *name) const { - if (Type *type = symbol_table.value(name)) - return type; - else if (parent) - return parent->resolve(name); - - return 0; - } - - typedef QHash<const NameSymbol*, Type*> symbol_table_t; - - symbol_table_t symbol_table; -}; - -class Control -{ -public: - class ErrorMessage - { - public: - ErrorMessage(): - _M_line(0), - _M_column(0) {} - - inline int line() const { - return _M_line; - } - inline void setLine(int line) { - _M_line = line; - } - - inline int column() const { - return _M_column; - } - inline void setColumn(int column) { - _M_column = column; - } - - inline QString fileName() const { - return _M_fileName; - } - inline void setFileName(const QString &fileName) { - _M_fileName = fileName; - } - - inline QString message() const { - return _M_message; - } - inline void setMessage(const QString &message) { - _M_message = message; - } - - private: - int _M_line; - int _M_column; - QString _M_fileName; - QString _M_message; - }; - - Control(); - ~Control(); - - inline bool skipFunctionBody() const { - return _M_skipFunctionBody; - } - inline void setSkipFunctionBody(bool skip) { - _M_skipFunctionBody = skip; - } - - Lexer *changeLexer(Lexer *lexer); - Parser *changeParser(Parser *parser); - - Lexer *currentLexer() const { - return _M_lexer; - } - Parser *currentParser() const { - return _M_parser; - } - - Context *current_context; - - inline Context *currentContext() const { - return current_context; - } - - void pushContext(); - void popContext(); - - Type *lookupType(const NameSymbol *name) const; - void declare(const NameSymbol *name, Type *type); - - inline const NameSymbol *findOrInsertName(const char *data, size_t count) { - return name_table.findOrInsert(data, count); - } - - void declareTypedef(const NameSymbol *name, Declarator *d); - bool isTypedef(const NameSymbol *name) const; - - void reportError(const ErrorMessage &errmsg); - QList<ErrorMessage> errorMessages() const; - void clearErrorMessages(); - -private: - NameTable name_table; - QHash<const NameSymbol*, Declarator*> stl_typedef_table; - bool _M_skipFunctionBody; - Lexer *_M_lexer; - Parser *_M_parser; - - QList<ErrorMessage> _M_error_messages; -}; - -#endif // CONTROL_H - -// kate: space-indent on; indent-width 2; replace-tabs on; diff --git a/sources/shiboken2/ApiExtractor/parser/declarator_compiler.cpp b/sources/shiboken2/ApiExtractor/parser/declarator_compiler.cpp deleted file mode 100644 index e27ea5842..000000000 --- a/sources/shiboken2/ApiExtractor/parser/declarator_compiler.cpp +++ /dev/null @@ -1,167 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#include "declarator_compiler.h" -#include "name_compiler.h" -#include "type_compiler.h" -#include "compiler_utils.h" -#include "lexer.h" -#include "binder.h" -#include "tokens.h" - -#include <qdebug.h> - -DeclaratorCompiler::DeclaratorCompiler(Binder *binder) - : _M_binder(binder), _M_token_stream(binder->tokenStream()) -{ -} - -void DeclaratorCompiler::run(DeclaratorAST *node) -{ - _M_id.clear(); - _M_parameters.clear(); - _M_array.clear(); - _M_function = false; - _M_reference = false; - _M_variadics = false; - _M_indirection = 0; - - if (node) { - NameCompiler name_cc(_M_binder); - - DeclaratorAST *decl = node; - while (decl && decl->sub_declarator) - decl = decl->sub_declarator; - - Q_ASSERT(decl != 0); - - name_cc.run(decl->id); - _M_id = name_cc.name(); - _M_function = (node->parameter_declaration_clause != 0); - if (node->parameter_declaration_clause && node->parameter_declaration_clause->ellipsis) - _M_variadics = true; - - visitNodes(this, node->ptr_ops); - visit(node->parameter_declaration_clause); - - if (const ListNode<ExpressionAST*> *it = node->array_dimensions) { - it->toFront(); - const ListNode<ExpressionAST*> *end = it; - - do { - QString elt; - if (ExpressionAST *expr = it->element) { - const Token &start_token = _M_token_stream->token((int) expr->start_token); - const Token &end_token = _M_token_stream->token((int) expr->end_token); - - elt += QString::fromUtf8(&start_token.text[start_token.position], - (int)(end_token.position - start_token.position)).trimmed(); - } - - _M_array.append(elt); - - it = it->next; - } while (it != end); - } - } -} - -void DeclaratorCompiler::visitPtrOperator(PtrOperatorAST *node) -{ - std::size_t op = _M_token_stream->kind(node->op); - - switch (op) { - case '&': - _M_reference = true; - break; - case '*': - ++_M_indirection; - break; - - default: - break; - } - - if (node->mem_ptr) { -#if defined(__GNUC__) -#warning "ptr to mem -- not implemented" -#endif - } -} - -void DeclaratorCompiler::visitParameterDeclaration(ParameterDeclarationAST *node) -{ - Parameter p; - DeclaratorCompiler decl_cc(_M_binder); - - // Find the innermost declarator, to extract the name / id of the declaration. - DeclaratorAST *declarator = node->declarator; - while (declarator && declarator->sub_declarator) - declarator = declarator->sub_declarator; - decl_cc.run(declarator); - p.name = decl_cc.id(); - - // Use the original declarator to extract the type. - p.type = CompilerUtils::typeDescription(node->type_specifier, node->declarator, _M_binder); - - // In case if the declarator is a function pointer, extract the arguments of the declarator - // parameter clause. This only works for top-declarator function pointers, it will fail to - // determine nested function pointers. - if (declarator != node->declarator - && node->declarator->parameter_declaration_clause) { - p.type.setFunctionPointer(true); - decl_cc.run(node->declarator); - foreach (const DeclaratorCompiler::Parameter &innerParam, decl_cc.parameters()) - p.type.addArgument(innerParam.type); - } - - if (node->expression != 0) { - const Token &start = _M_token_stream->token((int) node->expression->start_token); - const Token &end = _M_token_stream->token((int) node->expression->end_token); - int length = (int)(end.position - start.position); - - p.defaultValueExpression = QString(); - QString source = QString::fromUtf8(&start.text[start.position], length).trimmed(); - QStringList list = source.split(QLatin1Char('\n')); - - - for (int i = 0; i < list.size(); ++i) { - if (!list.at(i).startsWith(QLatin1Char('#'))) - p.defaultValueExpression += list.at(i).trimmed(); - } - - p.defaultValue = p.defaultValueExpression.size() > 0; - - } - - _M_parameters.append(p); -} - -// kate: space-indent on; indent-width 2; replace-tabs on; diff --git a/sources/shiboken2/ApiExtractor/parser/declarator_compiler.h b/sources/shiboken2/ApiExtractor/parser/declarator_compiler.h deleted file mode 100644 index f67bd4672..000000000 --- a/sources/shiboken2/ApiExtractor/parser/declarator_compiler.h +++ /dev/null @@ -1,101 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#ifndef DECLARATOR_COMPILER_H -#define DECLARATOR_COMPILER_H - -#include "default_visitor.h" -#include "codemodel.h" - -#include <QtCore/QString> -#include <QtCore/QList> - -class TokenStream; -class Binder; - -class DeclaratorCompiler: protected DefaultVisitor -{ -public: - struct Parameter { - TypeInfo type; - QString name; - QString defaultValueExpression; - bool defaultValue; - - Parameter(): defaultValue(false) {} - }; - -public: - DeclaratorCompiler(Binder *binder); - - void run(DeclaratorAST *node); - - inline QString id() const { - return _M_id; - } - inline QStringList arrayElements() const { - return _M_array; - } - inline bool isFunction() const { - return _M_function; - } - inline bool isVariadics() const { - return _M_variadics; - } - inline bool isReference() const { - return _M_reference; - } - inline int indirection() const { - return _M_indirection; - } - inline QList<Parameter> parameters() const { - return _M_parameters; - } - -protected: - virtual void visitPtrOperator(PtrOperatorAST *node); - virtual void visitParameterDeclaration(ParameterDeclarationAST *node); - -private: - Binder *_M_binder; - TokenStream *_M_token_stream; - - bool _M_function; - bool _M_reference; - bool _M_variadics; - int _M_indirection; - QString _M_id; - QStringList _M_array; - QList<Parameter> _M_parameters; -}; - -#endif // DECLARATOR_COMPILER_H - -// kate: space-indent on; indent-width 2; replace-tabs on; diff --git a/sources/shiboken2/ApiExtractor/parser/default_visitor.cpp b/sources/shiboken2/ApiExtractor/parser/default_visitor.cpp deleted file mode 100644 index e330abcbb..000000000 --- a/sources/shiboken2/ApiExtractor/parser/default_visitor.cpp +++ /dev/null @@ -1,464 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#include "default_visitor.h" - -void DefaultVisitor::visitAccessSpecifier(AccessSpecifierAST *) -{ - // nothing to do -} - -void DefaultVisitor::visitAsmDefinition(AsmDefinitionAST *) -{ - // nothing to do -} - -void DefaultVisitor::visitBaseClause(BaseClauseAST *node) -{ - visitNodes(this, node->base_specifiers); -} - -void DefaultVisitor::visitBaseSpecifier(BaseSpecifierAST *node) -{ - visit(node->name); -} - -void DefaultVisitor::visitBinaryExpression(BinaryExpressionAST *node) -{ - visit(node->left_expression); - visit(node->right_expression); -} - -void DefaultVisitor::visitCastExpression(CastExpressionAST *node) -{ - visit(node->type_id); - visit(node->expression); -} - -void DefaultVisitor::visitClassMemberAccess(ClassMemberAccessAST *node) -{ - visit(node->name); -} - -void DefaultVisitor::visitClassSpecifier(ClassSpecifierAST *node) -{ - visit(node->win_decl_specifiers); - visit(node->name); - visit(node->base_clause); - visitNodes(this, node->member_specs); -} - -void DefaultVisitor::visitCompoundStatement(CompoundStatementAST *node) -{ - visitNodes(this, node->statements); -} - -void DefaultVisitor::visitCondition(ConditionAST *node) -{ - visit(node->type_specifier); - visit(node->declarator); - visit(node->expression); -} - -void DefaultVisitor::visitConditionalExpression(ConditionalExpressionAST *node) -{ - visit(node->condition); - visit(node->left_expression); - visit(node->right_expression); -} - -void DefaultVisitor::visitCppCastExpression(CppCastExpressionAST *node) -{ - visit(node->type_id); - visit(node->expression); - visitNodes(this, node->sub_expressions); -} - -void DefaultVisitor::visitCtorInitializer(CtorInitializerAST *node) -{ - visitNodes(this, node->member_initializers); -} - -void DefaultVisitor::visitDeclarationStatement(DeclarationStatementAST *node) -{ - visit(node->declaration); -} - -void DefaultVisitor::visitDeclarator(DeclaratorAST *node) -{ - visit(node->sub_declarator); - visitNodes(this, node->ptr_ops); - visit(node->id); - visit(node->bit_expression); - visitNodes(this, node->array_dimensions); - visit(node->parameter_declaration_clause); - visit(node->exception_spec); -} - -void DefaultVisitor::visitDeleteExpression(DeleteExpressionAST *node) -{ - visit(node->expression); -} - -void DefaultVisitor::visitDoStatement(DoStatementAST *node) -{ - visit(node->statement); - visit(node->expression); -} - -void DefaultVisitor::visitElaboratedTypeSpecifier(ElaboratedTypeSpecifierAST *node) -{ - visit(node->name); -} - -void DefaultVisitor::visitEnumSpecifier(EnumSpecifierAST *node) -{ - visit(node->name); - visitNodes(this, node->enumerators); -} - -void DefaultVisitor::visitEnumerator(EnumeratorAST *node) -{ - visit(node->expression); -} - -void DefaultVisitor::visitExceptionSpecification(ExceptionSpecificationAST *node) -{ - visitNodes(this, node->type_ids); -} - -void DefaultVisitor::visitExpressionOrDeclarationStatement(ExpressionOrDeclarationStatementAST *node) -{ - visit(node->expression); - visit(node->declaration); -} - -void DefaultVisitor::visitExpressionStatement(ExpressionStatementAST *node) -{ - visit(node->expression); -} - -void DefaultVisitor::visitForStatement(ForStatementAST *node) -{ - visit(node->init_statement); - visit(node->condition); - visit(node->expression); - visit(node->statement); -} - -void DefaultVisitor::visitFunctionCall(FunctionCallAST *node) -{ - visit(node->arguments); -} - -void DefaultVisitor::visitFunctionDefinition(FunctionDefinitionAST *node) -{ - visit(node->type_specifier); - visit(node->init_declarator); - visit(node->function_body); - visit(node->win_decl_specifiers); -} - -void DefaultVisitor::visitIfStatement(IfStatementAST *node) -{ - visit(node->condition); - visit(node->statement); - visit(node->else_statement); -} - -void DefaultVisitor::visitIncrDecrExpression(IncrDecrExpressionAST *) -{ - // nothing to do -} - -void DefaultVisitor::visitInitDeclarator(InitDeclaratorAST *node) -{ - visit(node->declarator); - visit(node->initializer); -} - -void DefaultVisitor::visitInitializer(InitializerAST *node) -{ - visit(node->initializer_clause); - visit(node->expression); -} - -void DefaultVisitor::visitInitializerClause(InitializerClauseAST *node) -{ - visit(node->expression); -} - -void DefaultVisitor::visitLabeledStatement(LabeledStatementAST *) -{ - // nothing to do -} - -void DefaultVisitor::visitLinkageBody(LinkageBodyAST *node) -{ - visitNodes(this, node->declarations); -} - -void DefaultVisitor::visitLinkageSpecification(LinkageSpecificationAST *node) -{ - visit(node->linkage_body); - visit(node->declaration); -} - -void DefaultVisitor::visitMemInitializer(MemInitializerAST *node) -{ - visit(node->initializer_id); - visit(node->expression); -} - -void DefaultVisitor::visitName(NameAST *node) -{ - visitNodes(this, node->qualified_names); - visit(node->unqualified_name); -} - -void DefaultVisitor::visitNamespace(NamespaceAST *node) -{ - visit(node->linkage_body); -} - -void DefaultVisitor::visitNamespaceAliasDefinition(NamespaceAliasDefinitionAST *node) -{ - visit(node->alias_name); -} - -void DefaultVisitor::visitNewDeclarator(NewDeclaratorAST *node) -{ - visit(node->ptr_op); - visit(node->sub_declarator); - visitNodes(this, node->expressions); -} - -void DefaultVisitor::visitNewExpression(NewExpressionAST *node) -{ - visit(node->expression); - visit(node->type_id); - visit(node->new_type_id); - visit(node->new_initializer); -} - -void DefaultVisitor::visitNewInitializer(NewInitializerAST *node) -{ - visit(node->expression); -} - -void DefaultVisitor::visitNewTypeId(NewTypeIdAST *node) -{ - visit(node->type_specifier); - visit(node->new_initializer); - visit(node->new_declarator); -} - -void DefaultVisitor::visitOperator(OperatorAST *) -{ - // nothing to do -} - -void DefaultVisitor::visitOperatorFunctionId(OperatorFunctionIdAST *node) -{ - visit(node->op); - visit(node->type_specifier); - visitNodes(this, node->ptr_ops); -} - -void DefaultVisitor::visitParameterDeclaration(ParameterDeclarationAST *node) -{ - visit(node->type_specifier); - visit(node->declarator); - visit(node->expression); -} - -void DefaultVisitor::visitParameterDeclarationClause(ParameterDeclarationClauseAST *node) -{ - visitNodes(this, node->parameter_declarations); -} - -void DefaultVisitor::visitPostfixExpression(PostfixExpressionAST *node) -{ - visit(node->type_specifier); - visit(node->expression); - visitNodes(this, node->sub_expressions); -} - -void DefaultVisitor::visitPrimaryExpression(PrimaryExpressionAST *node) -{ - visit(node->literal); - visit(node->expression_statement); - visit(node->sub_expression); - visit(node->name); -} - -void DefaultVisitor::visitPtrOperator(PtrOperatorAST *node) -{ - visit(node->mem_ptr); -} - -void DefaultVisitor::visitPtrToMember(PtrToMemberAST *) -{ - // nothing to do -} - -void DefaultVisitor::visitReturnStatement(ReturnStatementAST *node) -{ - visit(node->expression); -} - -void DefaultVisitor::visitSimpleDeclaration(SimpleDeclarationAST *node) -{ - visit(node->type_specifier); - visitNodes(this, node->init_declarators); - visit(node->win_decl_specifiers); -} - -void DefaultVisitor::visitSimpleTypeSpecifier(SimpleTypeSpecifierAST *node) -{ - visit(node->name); - visit(node->type_id); - visit(node->expression); -} - -void DefaultVisitor::visitSizeofExpression(SizeofExpressionAST *node) -{ - visit(node->type_id); - visit(node->expression); -} - -void DefaultVisitor::visitStringLiteral(StringLiteralAST *) -{ - // nothing to do -} - -void DefaultVisitor::visitSubscriptExpression(SubscriptExpressionAST *node) -{ - visit(node->subscript); -} - -void DefaultVisitor::visitSwitchStatement(SwitchStatementAST *node) -{ - visit(node->condition); - visit(node->statement); -} - -void DefaultVisitor::visitTemplateArgument(TemplateArgumentAST *node) -{ - visit(node->type_id); - visit(node->expression); -} - -void DefaultVisitor::visitTemplateDeclaration(TemplateDeclarationAST *node) -{ - visitNodes(this, node->template_parameters); - visit(node->declaration); -} - -void DefaultVisitor::visitTemplateParameter(TemplateParameterAST *node) -{ - visit(node->type_parameter); - visit(node->parameter_declaration); -} - -void DefaultVisitor::visitThrowExpression(ThrowExpressionAST *node) -{ - visit(node->expression); -} - -void DefaultVisitor::visitTranslationUnit(TranslationUnitAST *node) -{ - visitNodes(this, node->declarations); -} - -void DefaultVisitor::visitTryBlockStatement(TryBlockStatementAST *) -{ - // nothing to do -} - -void DefaultVisitor::visitTypeId(TypeIdAST *node) -{ - visit(node->type_specifier); - visit(node->declarator); -} - -void DefaultVisitor::visitTypeIdentification(TypeIdentificationAST *node) -{ - visit(node->name); - visit(node->expression); -} - -void DefaultVisitor::visitTypeParameter(TypeParameterAST *node) -{ - visit(node->name); - visit(node->type_id); - visitNodes(this, node->template_parameters); - visit(node->template_name); -} - -void DefaultVisitor::visitTypedef(TypedefAST *node) -{ - visit(node->type_specifier); - visitNodes(this, node->init_declarators); -} - -void DefaultVisitor::visitUnaryExpression(UnaryExpressionAST *node) -{ - visit(node->expression); -} - -void DefaultVisitor::visitUnqualifiedName(UnqualifiedNameAST *node) -{ - visit(node->operator_id); - visitNodes(this, node->template_arguments); -} - -void DefaultVisitor::visitUsing(UsingAST *node) -{ - visit(node->name); -} - -void DefaultVisitor::visitUsingDirective(UsingDirectiveAST *node) -{ - visit(node->name); -} - -void DefaultVisitor::visitWhileStatement(WhileStatementAST *node) -{ - visit(node->condition); - visit(node->statement); -} - -void DefaultVisitor::visitWinDeclSpec(WinDeclSpecAST *) -{ - // nothing to do -} - -// kate: space-indent on; indent-width 2; replace-tabs on; diff --git a/sources/shiboken2/ApiExtractor/parser/default_visitor.h b/sources/shiboken2/ApiExtractor/parser/default_visitor.h deleted file mode 100644 index 1eef8cc85..000000000 --- a/sources/shiboken2/ApiExtractor/parser/default_visitor.h +++ /dev/null @@ -1,123 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#ifndef DEFAULT_VISITOR_H -#define DEFAULT_VISITOR_H - -#include "visitor.h" - -class DefaultVisitor: public Visitor -{ -public: - DefaultVisitor() {} - -protected: - virtual void visitAccessSpecifier(AccessSpecifierAST *); - virtual void visitAsmDefinition(AsmDefinitionAST *); - virtual void visitBaseClause(BaseClauseAST *); - virtual void visitBaseSpecifier(BaseSpecifierAST *); - virtual void visitBinaryExpression(BinaryExpressionAST *); - virtual void visitCastExpression(CastExpressionAST *); - virtual void visitClassMemberAccess(ClassMemberAccessAST *); - virtual void visitClassSpecifier(ClassSpecifierAST *); - virtual void visitCompoundStatement(CompoundStatementAST *); - virtual void visitCondition(ConditionAST *); - virtual void visitConditionalExpression(ConditionalExpressionAST *); - virtual void visitCppCastExpression(CppCastExpressionAST *); - virtual void visitCtorInitializer(CtorInitializerAST *); - virtual void visitDeclarationStatement(DeclarationStatementAST *); - virtual void visitDeclarator(DeclaratorAST *); - virtual void visitDeleteExpression(DeleteExpressionAST *); - virtual void visitDoStatement(DoStatementAST *); - virtual void visitElaboratedTypeSpecifier(ElaboratedTypeSpecifierAST *); - virtual void visitEnumSpecifier(EnumSpecifierAST *); - virtual void visitEnumerator(EnumeratorAST *); - virtual void visitExceptionSpecification(ExceptionSpecificationAST *); - virtual void visitExpressionOrDeclarationStatement(ExpressionOrDeclarationStatementAST *); - virtual void visitExpressionStatement(ExpressionStatementAST *); - virtual void visitForStatement(ForStatementAST *); - virtual void visitFunctionCall(FunctionCallAST *); - virtual void visitFunctionDefinition(FunctionDefinitionAST *); - virtual void visitIfStatement(IfStatementAST *); - virtual void visitIncrDecrExpression(IncrDecrExpressionAST *); - virtual void visitInitDeclarator(InitDeclaratorAST *); - virtual void visitInitializer(InitializerAST *); - virtual void visitInitializerClause(InitializerClauseAST *); - virtual void visitLabeledStatement(LabeledStatementAST *); - virtual void visitLinkageBody(LinkageBodyAST *); - virtual void visitLinkageSpecification(LinkageSpecificationAST *); - virtual void visitMemInitializer(MemInitializerAST *); - virtual void visitName(NameAST *); - virtual void visitNamespace(NamespaceAST *); - virtual void visitNamespaceAliasDefinition(NamespaceAliasDefinitionAST *); - virtual void visitNewDeclarator(NewDeclaratorAST *); - virtual void visitNewExpression(NewExpressionAST *); - virtual void visitNewInitializer(NewInitializerAST *); - virtual void visitNewTypeId(NewTypeIdAST *); - virtual void visitOperator(OperatorAST *); - virtual void visitOperatorFunctionId(OperatorFunctionIdAST *); - virtual void visitParameterDeclaration(ParameterDeclarationAST *); - virtual void visitParameterDeclarationClause(ParameterDeclarationClauseAST *); - virtual void visitPostfixExpression(PostfixExpressionAST *); - virtual void visitPrimaryExpression(PrimaryExpressionAST *); - virtual void visitPtrOperator(PtrOperatorAST *); - virtual void visitPtrToMember(PtrToMemberAST *); - virtual void visitReturnStatement(ReturnStatementAST *); - virtual void visitSimpleDeclaration(SimpleDeclarationAST *); - virtual void visitSimpleTypeSpecifier(SimpleTypeSpecifierAST *); - virtual void visitSizeofExpression(SizeofExpressionAST *); - virtual void visitStringLiteral(StringLiteralAST *); - virtual void visitSubscriptExpression(SubscriptExpressionAST *); - virtual void visitSwitchStatement(SwitchStatementAST *); - virtual void visitTemplateArgument(TemplateArgumentAST *); - virtual void visitTemplateDeclaration(TemplateDeclarationAST *); - virtual void visitTemplateParameter(TemplateParameterAST *); - virtual void visitThrowExpression(ThrowExpressionAST *); - virtual void visitTranslationUnit(TranslationUnitAST *); - virtual void visitTryBlockStatement(TryBlockStatementAST *); - virtual void visitTypeId(TypeIdAST *); - virtual void visitTypeIdentification(TypeIdentificationAST *); - virtual void visitTypeParameter(TypeParameterAST *); - virtual void visitTypedef(TypedefAST *); - virtual void visitUnaryExpression(UnaryExpressionAST *); - virtual void visitUnqualifiedName(UnqualifiedNameAST *); - virtual void visitUsing(UsingAST *); - virtual void visitUsingDirective(UsingDirectiveAST *); - virtual void visitWhileStatement(WhileStatementAST *); - virtual void visitWinDeclSpec(WinDeclSpecAST *); - -private: - typedef void (Visitor::*visitor_fun_ptr)(AST *); - static visitor_fun_ptr _S_table[]; -}; - -#endif // VISITOR_H - -// kate: space-indent on; indent-width 2; replace-tabs on; diff --git a/sources/shiboken2/ApiExtractor/parser/dumptree.cpp b/sources/shiboken2/ApiExtractor/parser/dumptree.cpp deleted file mode 100644 index 0a7444c14..000000000 --- a/sources/shiboken2/ApiExtractor/parser/dumptree.cpp +++ /dev/null @@ -1,131 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#include "dumptree.h" - -#include <QtCore/QString> -#include <QtCore/qdebug.h> - -static char const * const names[] = { - 0, - "AccessSpecifier", - "AsmDefinition", - "BaseClause", - "BaseSpecifier", - "BinaryExpression", - "CastExpression", - "ClassMemberAccess", - "ClassSpecifier", - "CompoundStatement", - "Condition", - "ConditionalExpression", - "CppCastExpression", - "CtorInitializer", - "DeclarationStatement", - "Declarator", - "DeleteExpression", - "DoStatement", - "ElaboratedTypeSpecifier", - "EnumSpecifier", - "Enumerator", - "ExceptionSpecification", - "ExpressionOrDeclarationStatement", - "ExpressionStatement", - "ForStatement", - "FunctionCall", - "FunctionDefinition", - "IfStatement", - "IncrDecrExpression", - "InitDeclarator", - "Initializer", - "InitializerClause", - "LabeledStatement", - "LinkageBody", - "LinkageSpecification", - "MemInitializer", - "Name", - "Namespace", - "NamespaceAliasDefinition", - "NewDeclarator", - "NewExpression", - "NewInitializer", - "NewTypeId", - "Operator", - "OperatorFunctionId", - "ParameterDeclaration", - "ParameterDeclarationClause", - "PostfixExpression", - "PrimaryExpression", - "PtrOperator", - "PtrToMember", - "ReturnStatement", - "SimpleDeclaration", - "SimpleTypeSpecifier", - "SizeofExpression", - "StringLiteral", - "SubscriptExpression", - "SwitchStatement", - "TemplateArgument", - "TemplateDeclaration", - "TemplateParameter", - "ThrowExpression", - "TranslationUnit", - "TryBlockStatement", - "TypeId", - "TypeIdentification", - "TypeParameter", - "Typedef", - "UnaryExpression", - "UnqualifiedName", - "Using", - "UsingDirective", - "WhileStatement", - "WinDeclSpec" -}; - -DumpTree::DumpTree() -{ -} - -void DumpTree::visit(AST *node) -{ - static int indent = 0; - - - if (node) - qDebug() << QByteArray(indent * 2, ' ').constData() << names[node->kind] - << '[' << node->start_token << ", " << node->end_token << ']'; - - ++indent; - DefaultVisitor::visit(node); - --indent; -} - -// kate: space-indent on; indent-width 2; replace-tabs on; diff --git a/sources/shiboken2/ApiExtractor/parser/lexer.cpp b/sources/shiboken2/ApiExtractor/parser/lexer.cpp deleted file mode 100644 index 3fcf3b561..000000000 --- a/sources/shiboken2/ApiExtractor/parser/lexer.cpp +++ /dev/null @@ -1,1726 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#include "lexer.h" -#include "tokens.h" -#include "control.h" - -#include <cctype> -#include <iostream> - -scan_fun_ptr Lexer::s_scan_keyword_table[] = { - &Lexer::scanKeyword0, &Lexer::scanKeyword0, - &Lexer::scanKeyword2, &Lexer::scanKeyword3, - &Lexer::scanKeyword4, &Lexer::scanKeyword5, - &Lexer::scanKeyword6, &Lexer::scanKeyword7, - &Lexer::scanKeyword8, &Lexer::scanKeyword9, - &Lexer::scanKeyword10, &Lexer::scanKeyword11, - &Lexer::scanKeyword12, &Lexer::scanKeyword13, - &Lexer::scanKeyword14, &Lexer::scanKeyword0, - &Lexer::scanKeyword16 -}; - -void LocationManager::extract_line(int offset, int *line, QString *filename) const -{ - *line = 0; - if (token_stream.size() < 1) - return; - - const unsigned char *begin_buffer = reinterpret_cast<const unsigned char *>(token_stream[0].text); - const unsigned char *cursor = begin_buffer + offset; - - ++cursor; // skip '#' - if (std::isspace(*cursor) && std::isdigit(*(cursor + 1))) { - ++cursor; - char buffer[1024], *cp = buffer; - do { - *cp++ = *cursor++; - } while (std::isdigit(*cursor)); - *cp = '\0'; - int l = strtol(buffer, 0, 0); - - Q_ASSERT(std::isspace(*cursor)); - ++cursor; - - Q_ASSERT(*cursor == '"'); - ++cursor; - - cp = buffer; - while (*cursor && *cursor != '"') { - *cp++ = *cursor++; - } - *cp = '\0'; - Q_ASSERT(*cursor == '"'); - ++cursor; - - *filename = QLatin1String(buffer); - *line = l; - // printf("filename: %s line: %d\n", buffer, line); - } -} - -void LocationManager::positionAt(std::size_t offset, int *line, int *column, - QString *filename) const -{ - int ppline = 0; - int ppcolumn = 0; - line_table.positionAt(offset, &ppline, &ppcolumn); - - int base_line = 0; - extract_line((int) line_table[ppline-1], &base_line, filename); - - int line2 = 0; - int column2 = 0; - location_table.positionAt((int) line_table[ppline-1], &line2, &column2); - - location_table.positionAt(offset, line, column); - *line = base_line + *line - line2 - 1; -} - -scan_fun_ptr Lexer::s_scan_table[256]; -bool Lexer::s_initialized = false; - -void Lexer::tokenize(const char *contents, std::size_t size) -{ - if (!s_initialized) - initialize_scan_table(); - - token_stream.resize(1024); - token_stream[0].kind = Token_EOF; - token_stream[0].text = contents; - - index = 1; - - cursor = (const unsigned char *) contents; - begin_buffer = (const unsigned char *) contents; - end_buffer = cursor + size; - - location_table.resize(1024); - location_table[0] = 0; - location_table.current_line = 1; - - line_table.resize(1024); - line_table[0] = 0; - line_table.current_line = 1; - - do { - if (index == token_stream.size()) - token_stream.resize(token_stream.size() * 2); - - Token *current_token = &token_stream[(int) index]; - current_token->text = reinterpret_cast<const char*>(begin_buffer); - current_token->position = cursor - begin_buffer; - (this->*s_scan_table[*cursor])(); - current_token->size = cursor - begin_buffer - current_token->position; - } while (cursor < end_buffer); - - if (index == token_stream.size()) - token_stream.resize(token_stream.size() * 2); - - Q_ASSERT(index < token_stream.size()); - token_stream[(int) index].position = cursor - begin_buffer; - token_stream[(int) index].kind = Token_EOF; -} - -void Lexer::reportError(const QString& msg) -{ - int line = 0; - int column = 0; - QString fileName; - - std::size_t tok = token_stream.cursor(); - _M_location.positionAt(token_stream.position(tok), - &line, &column, &fileName); - - Control::ErrorMessage errmsg; - errmsg.setLine(line + 1); - errmsg.setColumn(column); - errmsg.setFileName(fileName); - errmsg.setMessage(QLatin1String("** LEXER ERROR ") + msg); - control->reportError(errmsg); -} - -void Lexer::initialize_scan_table() -{ - s_initialized = true; - - for (int i = 0; i < 256; ++i) { - if (isspace(i)) - s_scan_table[i] = &Lexer::scan_white_spaces; - else if (isalpha(i) || i == '_') - s_scan_table[i] = &Lexer::scan_identifier_or_keyword; - else if (isdigit(i)) - s_scan_table[i] = &Lexer::scan_int_constant; - else - s_scan_table[i] = &Lexer::scan_invalid_input; - } - - s_scan_table[int('L')] = &Lexer::scan_identifier_or_literal; - s_scan_table[int('\n')] = &Lexer::scan_newline; - s_scan_table[int('#')] = &Lexer::scan_preprocessor; - - s_scan_table[int('\'')] = &Lexer::scan_char_constant; - s_scan_table[int('"')] = &Lexer::scan_string_constant; - - s_scan_table[int('.')] = &Lexer::scan_int_constant; - - s_scan_table[int('!')] = &Lexer::scan_not; - s_scan_table[int('%')] = &Lexer::scan_remainder; - s_scan_table[int('&')] = &Lexer::scan_and; - s_scan_table[int('(')] = &Lexer::scan_left_paren; - s_scan_table[int(')')] = &Lexer::scan_right_paren; - s_scan_table[int('*')] = &Lexer::scan_star; - s_scan_table[int('+')] = &Lexer::scan_plus; - s_scan_table[int(',')] = &Lexer::scan_comma; - s_scan_table[int('-')] = &Lexer::scan_minus; - s_scan_table[int('/')] = &Lexer::scan_divide; - s_scan_table[int(':')] = &Lexer::scan_colon; - s_scan_table[int(';')] = &Lexer::scan_semicolon; - s_scan_table[int('<')] = &Lexer::scan_less; - s_scan_table[int('=')] = &Lexer::scan_equal; - s_scan_table[int('>')] = &Lexer::scan_greater; - s_scan_table[int('?')] = &Lexer::scan_question; - s_scan_table[int('[')] = &Lexer::scan_left_bracket; - s_scan_table[int(']')] = &Lexer::scan_right_bracket; - s_scan_table[int('^')] = &Lexer::scan_xor; - s_scan_table[int('{')] = &Lexer::scan_left_brace; - s_scan_table[int('|')] = &Lexer::scan_or; - s_scan_table[int('}')] = &Lexer::scan_right_brace; - s_scan_table[int('~')] = &Lexer::scan_tilde; - - s_scan_table[0] = &Lexer::scan_EOF; -} - -void Lexer::scan_preprocessor() -{ - if (line_table.current_line == line_table.size()) - line_table.resize(line_table.current_line * 2); - - line_table[(int) line_table.current_line++] = (cursor - begin_buffer); - - while (*cursor && *cursor != '\n') - ++cursor; - - if (*cursor != '\n') - reportError(QLatin1String("expected newline")); -} - -void Lexer::scan_char_constant() -{ - const unsigned char *begin = cursor; - - ++cursor; - while (*cursor && *cursor != '\'') { - if (*cursor == '\n') - reportError(QLatin1String("did not expect newline")); - - if (*cursor == '\\') - ++cursor; - ++cursor; - } - - if (*cursor != '\'') - reportError(QLatin1String("expected \'")); - - ++cursor; - - token_stream[(int) index].extra.symbol = - control->findOrInsertName((const char*) begin, cursor - begin); - - token_stream[(int) index++].kind = Token_char_literal; -} - -void Lexer::scan_string_constant() -{ - const unsigned char *begin = cursor; - - ++cursor; - while (*cursor && *cursor != '"') { - if (*cursor == '\n') - reportError(QLatin1String("did not expect newline")); - - if (*cursor == '\\') - ++cursor; - ++cursor; - } - - if (*cursor != '"') - reportError(QLatin1String("expected \"")); - - ++cursor; - - token_stream[(int) index].extra.symbol = - control->findOrInsertName((const char*) begin, cursor - begin); - - token_stream[(int) index++].kind = Token_string_literal; -} - -void Lexer::scan_newline() -{ - if (location_table.current_line == location_table.size()) - location_table.resize(location_table.current_line * 2); - - location_table[(int) location_table.current_line++] = (cursor - begin_buffer); - ++cursor; -} - -void Lexer::scan_white_spaces() -{ - while (isspace(*cursor)) { - if (*cursor == '\n') - scan_newline(); - else - ++cursor; - } -} - -void Lexer::scan_identifier_or_literal() -{ - switch (*(cursor + 1)) { - case '\'': - ++cursor; - scan_char_constant(); - break; - - case '\"': - ++cursor; - scan_string_constant(); - break; - - default: - scan_identifier_or_keyword(); - break; - } -} - -void Lexer::scan_identifier_or_keyword() -{ - const unsigned char *skip = cursor; - while (isalnum(*skip) || *skip == '_') - ++skip; - - int n = skip - cursor; - Token *current_token = &token_stream[(int) index]; - (this->*s_scan_keyword_table[n < 17 ? n : 0])(); - - if (current_token->kind == Token_identifier) { - current_token->extra.symbol = - control->findOrInsertName((const char*) cursor, n); - } - - cursor = skip; -} - -void Lexer::scan_int_constant() -{ - if (*cursor == '.' && !std::isdigit(*(cursor + 1))) { - scan_dot(); - return; - } - - const unsigned char *begin = cursor; - - while (isalnum(*cursor) || *cursor == '.') - ++cursor; - - token_stream[(int) index].extra.symbol = - control->findOrInsertName((const char*) begin, cursor - begin); - - token_stream[(int) index++].kind = Token_number_literal; -} - -void Lexer::scan_not() -{ - /* - '!' ::= not - '!=' ::= not_equal - */ - - ++cursor; - - if (*cursor == '=') { - ++cursor; - token_stream[(int) index++].kind = Token_not_eq; - } else { - token_stream[(int) index++].kind = '!'; - } -} - -void Lexer::scan_remainder() -{ - /* - '%' ::= remainder - '%=' ::= remainder_equal - */ - - ++cursor; - - if (*cursor == '=') { - ++cursor; - token_stream[(int) index++].kind = Token_assign; - } else { - token_stream[(int) index++].kind = '%'; - } -} - -void Lexer::scan_and() -{ - /* - '&&' ::= and_and - '&' ::= and - '&=' ::= and_equal - */ - - ++cursor; - if (*cursor == '=') { - ++cursor; - token_stream[(int) index++].kind = Token_assign; - } else if (*cursor == '&') { - ++cursor; - token_stream[(int) index++].kind = Token_and; - } else { - token_stream[(int) index++].kind = '&'; - } -} - -void Lexer::scan_left_paren() -{ - ++cursor; - token_stream[(int) index++].kind = '('; -} - -void Lexer::scan_right_paren() -{ - ++cursor; - token_stream[(int) index++].kind = ')'; -} - -void Lexer::scan_star() -{ - /* - '*' ::= star - '*=' ::= star_equal - */ - - ++cursor; - - if (*cursor == '=') { - ++cursor; - token_stream[(int) index++].kind = Token_assign; - } else { - token_stream[(int) index++].kind = '*'; - } -} - -void Lexer::scan_plus() -{ - /* - '+' ::= plus - '++' ::= incr - '+=' ::= plus_equal - */ - - ++cursor; - if (*cursor == '=') { - ++cursor; - token_stream[(int) index++].kind = Token_assign; - } else if (*cursor == '+') { - ++cursor; - token_stream[(int) index++].kind = Token_incr; - } else { - token_stream[(int) index++].kind = '+'; - } -} - -void Lexer::scan_comma() -{ - ++cursor; - token_stream[(int) index++].kind = ','; -} - -void Lexer::scan_minus() -{ - /* - '-' ::= minus - '--' ::= decr - '-=' ::= minus_equal - '->' ::= left_arrow - */ - - ++cursor; - if (*cursor == '=') { - ++cursor; - token_stream[(int) index++].kind = Token_assign; - } else if (*cursor == '-') { - ++cursor; - token_stream[(int) index++].kind = Token_decr; - } else if (*cursor == '>') { - ++cursor; - token_stream[(int) index++].kind = Token_arrow; - if (*cursor == '*') { - ++cursor; - token_stream[(int) index++].kind = Token_ptrmem; - } - } else { - token_stream[(int) index++].kind = '-'; - } -} - -void Lexer::scan_dot() -{ - /* - '.' ::= dot - '...' ::= ellipsis - */ - - ++cursor; - if (*cursor == '.' && *(cursor + 1) == '.') { - cursor += 2; - token_stream[(int) index++].kind = Token_ellipsis; - } else if (*cursor == '.' && *(cursor + 1) == '*') { - cursor += 2; - token_stream[(int) index++].kind = Token_ptrmem; - } else - token_stream[(int) index++].kind = '.'; -} - -void Lexer::scan_divide() -{ - /* - '/' ::= divide - '/=' ::= divide_equal - */ - - ++cursor; - - if (*cursor == '=') { - ++cursor; - token_stream[(int) index++].kind = Token_assign; - } else { - token_stream[(int) index++].kind = '/'; - } -} - -void Lexer::scan_colon() -{ - ++cursor; - if (*cursor == ':') { - ++cursor; - token_stream[(int) index++].kind = Token_scope; - } else { - token_stream[(int) index++].kind = ':'; - } -} - -void Lexer::scan_semicolon() -{ - ++cursor; - token_stream[(int) index++].kind = ';'; -} - -void Lexer::scan_less() -{ - /* - '<' ::= less - '<<' ::= left_shift - '<<=' ::= left_shift_equal - '<=' ::= less_equal - */ - - ++cursor; - if (*cursor == '=') { - ++cursor; - token_stream[(int) index++].kind = Token_leq; - } else if (*cursor == '<') { - ++cursor; - if (*cursor == '=') { - ++cursor; - token_stream[(int) index++].kind = Token_assign; - } else { - token_stream[(int) index++].kind = Token_shift; - } - } else { - token_stream[(int) index++].kind = '<'; - } -} - -void Lexer::scan_equal() -{ - /* - '=' ::= equal - '==' ::= equal_equal - */ - ++cursor; - - if (*cursor == '=') { - ++cursor; - token_stream[(int) index++].kind = Token_eq; - } else { - token_stream[(int) index++].kind = '='; - } -} - -void Lexer::scan_greater() -{ - /* - '>' ::= greater - '>=' ::= greater_equal - '>>' ::= right_shift - '>>=' ::= right_shift_equal - */ - - ++cursor; - if (*cursor == '=') { - ++cursor; - token_stream[(int) index++].kind = Token_geq; - } else if (*cursor == '>') { - ++cursor; - if (*cursor == '=') { - ++cursor; - token_stream[(int) index++].kind = Token_assign; - } else { - token_stream[(int) index++].kind = Token_shift; - } - } else { - token_stream[(int) index++].kind = '>'; - } -} - -void Lexer::scan_question() -{ - ++cursor; - token_stream[(int) index++].kind = '?'; -} - -void Lexer::scan_left_bracket() -{ - ++cursor; - token_stream[(int) index++].kind = '['; -} - -void Lexer::scan_right_bracket() -{ - ++cursor; - token_stream[(int) index++].kind = ']'; -} - -void Lexer::scan_xor() -{ - /* - '^' ::= xor - '^=' ::= xor_equal - */ - ++cursor; - - if (*cursor == '=') { - ++cursor; - token_stream[(int) index++].kind = Token_assign; - } else { - token_stream[(int) index++].kind = '^'; - } -} - -void Lexer::scan_left_brace() -{ - ++cursor; - token_stream[(int) index++].kind = '{'; -} - -void Lexer::scan_or() -{ - /* - '|' ::= or - '|=' ::= or_equal - '||' ::= or_or - */ - ++cursor; - if (*cursor == '=') { - ++cursor; - token_stream[(int) index++].kind = Token_assign; - } else if (*cursor == '|') { - ++cursor; - token_stream[(int) index++].kind = Token_or; - } else { - token_stream[(int) index++].kind = '|'; - } -} - -void Lexer::scan_right_brace() -{ - ++cursor; - token_stream[(int) index++].kind = '}'; -} - -void Lexer::scan_tilde() -{ - ++cursor; - token_stream[(int) index++].kind = '~'; -} - -void Lexer::scan_EOF() -{ - ++cursor; - token_stream[(int) index++].kind = Token_EOF; -} - -void Lexer::scan_invalid_input() -{ - QString errmsg(QLatin1String("invalid input: %1")); - reportError(errmsg); - ++cursor; -} - -void LocationTable::positionAt(std::size_t offset, int max_line, - int *line, int *column) const -{ - if (!(line && column && max_line != 0)) - return; - - int first = 0; - int len = max_line; - int half; - int middle; - - while (len > 0) { - half = len >> 1; - middle = first; - - middle += half; - - if (lines[middle] < offset) { - first = middle; - ++first; - len = len - half - 1; - } else - len = half; - } - - *line = std::max(first, 1); - *column = (int)(offset - lines[*line - 1] - 1); - - if (*column < 0) { - *column = 0; - } -} - -void Lexer::scanKeyword0() -{ - token_stream[(int) index++].kind = Token_identifier; -} - -void Lexer::scanKeyword2() -{ - switch (*cursor) { - case 'i': - if (*(cursor + 1) == 'f') { - token_stream[(int) index++].kind = Token_if; - return; - } - break; - - case 'd': - if (*(cursor + 1) == 'o') { - token_stream[(int) index++].kind = Token_do; - return; - } - break; - - case 'o': - if (*(cursor + 1) == 'r') { - token_stream[(int) index++].kind = Token_or; - return; - } - break; - - } - token_stream[(int) index++].kind = Token_identifier; -} - -void Lexer::scanKeyword3() -{ - switch (*cursor) { - case 'a': - if (*(cursor + 1) == 'n' && - *(cursor + 2) == 'd') { - token_stream[(int) index++].kind = Token_and; - return; - } - if (*(cursor + 1) == 's' && - *(cursor + 2) == 'm') { - token_stream[(int) index++].kind = Token_asm; - return; - } - break; - - case 'f': - if (*(cursor + 1) == 'o' && - *(cursor + 2) == 'r') { - token_stream[(int) index++].kind = Token_for; - return; - } - break; - - case 'i': - if (*(cursor + 1) == 'n' && - *(cursor + 2) == 't') { - token_stream[(int) index++].kind = Token_int; - return; - } - break; - - case 'n': - if (*(cursor + 1) == 'e' && - *(cursor + 2) == 'w') { - token_stream[(int) index++].kind = Token_new; - return; - } - if (*(cursor + 1) == 'o' && - *(cursor + 2) == 't') { - token_stream[(int) index++].kind = Token_not; - return; - } - break; - - case 't': - if (*(cursor + 1) == 'r' && - *(cursor + 2) == 'y') { - token_stream[(int) index++].kind = Token_try; - return; - } - break; - - case 'x': - if (*(cursor + 1) == 'o' && - *(cursor + 2) == 'r') { - token_stream[(int) index++].kind = Token_xor; - return; - } - break; - - } - token_stream[(int) index++].kind = Token_identifier; -} - -void Lexer::scanKeyword4() -{ - switch (*cursor) { - case 'a': - if (*(cursor + 1) == 'u' && - *(cursor + 2) == 't' && - *(cursor + 3) == 'o') { - token_stream[(int) index++].kind = Token_auto; - return; - } - break; - - case 'c': - if (*(cursor + 1) == 'a' && - *(cursor + 2) == 's' && - *(cursor + 3) == 'e') { - token_stream[(int) index++].kind = Token_case; - return; - } - if (*(cursor + 1) == 'h' && - *(cursor + 2) == 'a' && - *(cursor + 3) == 'r') { - token_stream[(int) index++].kind = Token_char; - return; - } - break; - - case 'b': - if (*(cursor + 1) == 'o' && - *(cursor + 2) == 'o' && - *(cursor + 3) == 'l') { - token_stream[(int) index++].kind = Token_bool; - return; - } - break; - - case 'e': - if (*(cursor + 1) == 'l' && - *(cursor + 2) == 's' && - *(cursor + 3) == 'e') { - token_stream[(int) index++].kind = Token_else; - return; - } - if (*(cursor + 1) == 'm' && - *(cursor + 2) == 'i' && - *(cursor + 3) == 't') { - token_stream[(int) index++].kind = Token_emit; - return; - } - if (*(cursor + 1) == 'n' && - *(cursor + 2) == 'u' && - *(cursor + 3) == 'm') { - token_stream[(int) index++].kind = Token_enum; - return; - } - break; - - case 'g': - if (*(cursor + 1) == 'o' && - *(cursor + 2) == 't' && - *(cursor + 3) == 'o') { - token_stream[(int) index++].kind = Token_goto; - return; - } - break; - - case 'l': - if (*(cursor + 1) == 'o' && - *(cursor + 2) == 'n' && - *(cursor + 3) == 'g') { - token_stream[(int) index++].kind = Token_long; - return; - } - break; - - case 't': - if (*(cursor + 1) == 'h' && - *(cursor + 2) == 'i' && - *(cursor + 3) == 's') { - token_stream[(int) index++].kind = Token_this; - return; - } - break; - - case 'v': - if (*(cursor + 1) == 'o' && - *(cursor + 2) == 'i' && - *(cursor + 3) == 'd') { - token_stream[(int) index++].kind = Token_void; - return; - } - break; - - } - token_stream[(int) index++].kind = Token_identifier; -} - -void Lexer::scanKeyword5() -{ - switch (*cursor) { - case 'c': - if (*(cursor + 1) == 'a' && - *(cursor + 2) == 't' && - *(cursor + 3) == 'c' && - *(cursor + 4) == 'h') { - token_stream[(int) index++].kind = Token_catch; - return; - } - if (*(cursor + 1) == 'l' && - *(cursor + 2) == 'a' && - *(cursor + 3) == 's' && - *(cursor + 4) == 's') { - token_stream[(int) index++].kind = Token_class; - return; - } - if (*(cursor + 1) == 'o' && - *(cursor + 2) == 'm' && - *(cursor + 3) == 'p' && - *(cursor + 4) == 'l') { - token_stream[(int) index++].kind = Token_compl; - return; - } - if (*(cursor + 1) == 'o' && - *(cursor + 2) == 'n' && - *(cursor + 3) == 's' && - *(cursor + 4) == 't') { - token_stream[(int) index++].kind = Token_const; - return; - } - break; - - case 'b': - if (*(cursor + 1) == 'i' && - *(cursor + 2) == 't' && - *(cursor + 3) == 'o' && - *(cursor + 4) == 'r') { - token_stream[(int) index++].kind = Token_bitor; - return; - } - if (*(cursor + 1) == 'r' && - *(cursor + 2) == 'e' && - *(cursor + 3) == 'a' && - *(cursor + 4) == 'k') { - token_stream[(int) index++].kind = Token_break; - return; - } - break; - - case 'f': - if (*(cursor + 1) == 'l' && - *(cursor + 2) == 'o' && - *(cursor + 3) == 'a' && - *(cursor + 4) == 't') { - token_stream[(int) index++].kind = Token_float; - return; - } - break; - - case 'o': - if (*(cursor + 1) == 'r' && - *(cursor + 2) == '_' && - *(cursor + 3) == 'e' && - *(cursor + 4) == 'q') { - token_stream[(int) index++].kind = Token_or_eq; - return; - } - break; - - case 's': - if (*(cursor + 1) == 'h' && - *(cursor + 2) == 'o' && - *(cursor + 3) == 'r' && - *(cursor + 4) == 't') { - token_stream[(int) index++].kind = Token_short; - return; - } - if (*(cursor + 1) == 'l' && - *(cursor + 2) == 'o' && - *(cursor + 3) == 't' && - *(cursor + 4) == 's') { - token_stream[(int) index++].kind = Token_slots; - return; - } - break; - - case 'u': - if (*(cursor + 1) == 'n' && - *(cursor + 2) == 'i' && - *(cursor + 3) == 'o' && - *(cursor + 4) == 'n') { - token_stream[(int) index++].kind = Token_union; - return; - } - if (*(cursor + 1) == 's' && - *(cursor + 2) == 'i' && - *(cursor + 3) == 'n' && - *(cursor + 4) == 'g') { - token_stream[(int) index++].kind = Token_using; - return; - } - break; - - case 't': - if (*(cursor + 1) == 'h' && - *(cursor + 2) == 'r' && - *(cursor + 3) == 'o' && - *(cursor + 4) == 'w') { - token_stream[(int) index++].kind = Token_throw; - return; - } - break; - - case 'w': - if (*(cursor + 1) == 'h' && - *(cursor + 2) == 'i' && - *(cursor + 3) == 'l' && - *(cursor + 4) == 'e') { - token_stream[(int) index++].kind = Token_while; - return; - } - break; - - } - token_stream[(int) index++].kind = Token_identifier; -} - -void Lexer::scanKeyword6() -{ - switch (*cursor) { - case 'a': - if (*(cursor + 1) == 'n' && - *(cursor + 2) == 'd' && - *(cursor + 3) == '_' && - *(cursor + 4) == 'e' && - *(cursor + 5) == 'q') { - token_stream[(int) index++].kind = Token_and_eq; - return; - } - break; - - case 'b': - if (*(cursor + 1) == 'i' && - *(cursor + 2) == 't' && - *(cursor + 3) == 'a' && - *(cursor + 4) == 'n' && - *(cursor + 5) == 'd') { - token_stream[(int) index++].kind = Token_bitand; - return; - } - break; - - case 'e': - if (*(cursor + 1) == 'x' && - *(cursor + 2) == 'p' && - *(cursor + 3) == 'o' && - *(cursor + 4) == 'r' && - *(cursor + 5) == 't') { - token_stream[(int) index++].kind = Token_export; - return; - } - if (*(cursor + 1) == 'x' && - *(cursor + 2) == 't' && - *(cursor + 3) == 'e' && - *(cursor + 4) == 'r' && - *(cursor + 5) == 'n') { - token_stream[(int) index++].kind = Token_extern; - return; - } - break; - - case 'd': - if (*(cursor + 1) == 'e' && - *(cursor + 2) == 'l' && - *(cursor + 3) == 'e' && - *(cursor + 4) == 't' && - *(cursor + 5) == 'e') { - token_stream[(int) index++].kind = Token_delete; - return; - } - if (*(cursor + 1) == 'o' && - *(cursor + 2) == 'u' && - *(cursor + 3) == 'b' && - *(cursor + 4) == 'l' && - *(cursor + 5) == 'e') { - token_stream[(int) index++].kind = Token_double; - return; - } - break; - - case 'f': - if (*(cursor + 1) == 'r' && - *(cursor + 2) == 'i' && - *(cursor + 3) == 'e' && - *(cursor + 4) == 'n' && - *(cursor + 5) == 'd') { - token_stream[(int) index++].kind = Token_friend; - return; - } - break; - - case 'i': - if (*(cursor + 1) == 'n' && - *(cursor + 2) == 'l' && - *(cursor + 3) == 'i' && - *(cursor + 4) == 'n' && - *(cursor + 5) == 'e') { - token_stream[(int) index++].kind = Token_inline; - return; - } - break; - - case 'K': - if (*(cursor + 1) == '_' && - *(cursor + 2) == 'D' && - *(cursor + 3) == 'C' && - *(cursor + 4) == 'O' && - *(cursor + 5) == 'P') { - token_stream[(int) index++].kind = Token_K_DCOP; - return; - } - break; - - case 'n': - if (*(cursor + 1) == 'o' && - *(cursor + 2) == 't' && - *(cursor + 3) == '_' && - *(cursor + 4) == 'e' && - *(cursor + 5) == 'q') { - token_stream[(int) index++].kind = Token_not_eq; - return; - } - break; - - case 'p': - if (*(cursor + 1) == 'u' && - *(cursor + 2) == 'b' && - *(cursor + 3) == 'l' && - *(cursor + 4) == 'i' && - *(cursor + 5) == 'c') { - token_stream[(int) index++].kind = Token_public; - return; - } - break; - - case 's': - if (*(cursor + 1) == 'i' && - *(cursor + 2) == 'g' && - *(cursor + 3) == 'n' && - *(cursor + 4) == 'e' && - *(cursor + 5) == 'd') { - token_stream[(int) index++].kind = Token_signed; - return; - } - if (*(cursor + 1) == 'i' && - *(cursor + 2) == 'z' && - *(cursor + 3) == 'e' && - *(cursor + 4) == 'o' && - *(cursor + 5) == 'f') { - token_stream[(int) index++].kind = Token_sizeof; - return; - } - if (*(cursor + 1) == 't' && - *(cursor + 2) == 'a' && - *(cursor + 3) == 't' && - *(cursor + 4) == 'i' && - *(cursor + 5) == 'c') { - token_stream[(int) index++].kind = Token_static; - return; - } - if (*(cursor + 1) == 't' && - *(cursor + 2) == 'r' && - *(cursor + 3) == 'u' && - *(cursor + 4) == 'c' && - *(cursor + 5) == 't') { - token_stream[(int) index++].kind = Token_struct; - return; - } - if (*(cursor + 1) == 'w' && - *(cursor + 2) == 'i' && - *(cursor + 3) == 't' && - *(cursor + 4) == 'c' && - *(cursor + 5) == 'h') { - token_stream[(int) index++].kind = Token_switch; - return; - } - break; - - case 'r': - if (*(cursor + 1) == 'e' && - *(cursor + 2) == 't' && - *(cursor + 3) == 'u' && - *(cursor + 4) == 'r' && - *(cursor + 5) == 'n') { - token_stream[(int) index++].kind = Token_return; - return; - } - break; - - case 't': - if (*(cursor + 1) == 'y' && - *(cursor + 2) == 'p' && - *(cursor + 3) == 'e' && - *(cursor + 4) == 'i' && - *(cursor + 5) == 'd') { - token_stream[(int) index++].kind = Token_typeid; - return; - } - break; - - case 'x': - if (*(cursor + 1) == 'o' && - *(cursor + 2) == 'r' && - *(cursor + 3) == '_' && - *(cursor + 4) == 'e' && - *(cursor + 5) == 'q') { - token_stream[(int) index++].kind = Token_xor_eq; - return; - } - break; - - case 'k': - if (*(cursor + 1) == '_' && - *(cursor + 2) == 'd' && - *(cursor + 3) == 'c' && - *(cursor + 4) == 'o' && - *(cursor + 5) == 'p') { - token_stream[(int) index++].kind = Token_k_dcop; - return; - } - break; - - case 'Q': - if (*(cursor + 1) == '_' && - *(cursor + 2) == 'E' && - *(cursor + 3) == 'N' && - *(cursor + 4) == 'U' && - *(cursor + 5) == 'M') { // Qt5.5 - token_stream[(int) index++].kind = Token_Q_ENUM; - return; - } - break; - - } - token_stream[(int) index++].kind = Token_identifier; -} - -void Lexer::scanKeyword7() -{ - switch (*cursor) { - case 'd': - if (*(cursor + 1) == 'e' && - *(cursor + 2) == 'f' && - *(cursor + 3) == 'a' && - *(cursor + 4) == 'u' && - *(cursor + 5) == 'l' && - *(cursor + 6) == 't') { - token_stream[(int) index++].kind = Token_default; - return; - } - break; - - case 'm': - if (*(cursor + 1) == 'u' && - *(cursor + 2) == 't' && - *(cursor + 3) == 'a' && - *(cursor + 4) == 'b' && - *(cursor + 5) == 'l' && - *(cursor + 6) == 'e') { - token_stream[(int) index++].kind = Token_mutable; - return; - } - break; - - case 'p': - if (*(cursor + 1) == 'r' && - *(cursor + 2) == 'i' && - *(cursor + 3) == 'v' && - *(cursor + 4) == 'a' && - *(cursor + 5) == 't' && - *(cursor + 6) == 'e') { - token_stream[(int) index++].kind = Token_private; - return; - } - break; - case 's': - if (*(cursor + 1) == 'i' && - *(cursor + 2) == 'g' && - *(cursor + 3) == 'n' && - *(cursor + 4) == 'a' && - *(cursor + 5) == 'l' && - *(cursor + 6) == 's') { - token_stream[(int) index++].kind = Token_signals; - return; - } - break; - case 't': - if (*(cursor + 1) == 'y' && - *(cursor + 2) == 'p' && - *(cursor + 3) == 'e' && - *(cursor + 4) == 'd' && - *(cursor + 5) == 'e' && - *(cursor + 6) == 'f') { - token_stream[(int) index++].kind = Token_typedef; - return; - } - break; - - case 'v': - if (*(cursor + 1) == 'i' && - *(cursor + 2) == 'r' && - *(cursor + 3) == 't' && - *(cursor + 4) == 'u' && - *(cursor + 5) == 'a' && - *(cursor + 6) == 'l') { - token_stream[(int) index++].kind = Token_virtual; - return; - } - break; - - case 'Q': - if (*(cursor + 1) == '_' && - *(cursor + 2) == 'E' && - *(cursor + 3) == 'N' && - *(cursor + 4) == 'U' && - *(cursor + 5) == 'M' && - *(cursor + 6) == 'S') { - token_stream[(int) index++].kind = Token_Q_ENUMS; - return; - } - break; - - } - token_stream[(int) index++].kind = Token_identifier; -} - -void Lexer::scanKeyword8() -{ - switch (*cursor) { - case '_': - if (*(cursor + 1) == '_' && - *(cursor + 2) == 't' && - *(cursor + 3) == 'y' && - *(cursor + 4) == 'p' && - *(cursor + 5) == 'e' && - *(cursor + 6) == 'o' && - *(cursor + 7) == 'f') { - token_stream[(int) index++].kind = Token___typeof; - return; - } - break; - - case 'c': - if (*(cursor + 1) == 'o' && - *(cursor + 2) == 'n' && - *(cursor + 3) == 't' && - *(cursor + 4) == 'i' && - *(cursor + 5) == 'n' && - *(cursor + 6) == 'u' && - *(cursor + 7) == 'e') { - token_stream[(int) index++].kind = Token_continue; - return; - } - break; - - case 'e': - if (*(cursor + 1) == 'x' && - *(cursor + 2) == 'p' && - *(cursor + 3) == 'l' && - *(cursor + 4) == 'i' && - *(cursor + 5) == 'c' && - *(cursor + 6) == 'i' && - *(cursor + 7) == 't') { - token_stream[(int) index++].kind = Token_explicit; - return; - } - break; - - case 'n': - if (*(cursor + 1) == 'o' && - *(cursor + 2) == 'e' && - *(cursor + 3) == 'x' && - *(cursor + 4) == 'c' && - *(cursor + 5) == 'e' && - *(cursor + 6) == 'p' && - *(cursor + 7) == 't') { - token_stream[(int) index++].kind = Token_noexcept; - return; - } - break; - - case 'o': - if (*(cursor + 1) == 'p' && - *(cursor + 2) == 'e' && - *(cursor + 3) == 'r' && - *(cursor + 4) == 'a' && - *(cursor + 5) == 't' && - *(cursor + 6) == 'o' && - *(cursor + 7) == 'r') { - token_stream[(int) index++].kind = Token_operator; - return; - } - break; - - case 'Q': - if (*(cursor + 1) == '_' && - *(cursor + 2) == 'O' && - *(cursor + 3) == 'B' && - *(cursor + 4) == 'J' && - *(cursor + 5) == 'E' && - *(cursor + 6) == 'C' && - *(cursor + 7) == 'T') { - token_stream[(int) index++].kind = Token_Q_OBJECT; - return; - } - break; - - case 'r': - if (*(cursor + 1) == 'e' && - *(cursor + 2) == 'g' && - *(cursor + 3) == 'i' && - *(cursor + 4) == 's' && - *(cursor + 5) == 't' && - *(cursor + 6) == 'e' && - *(cursor + 7) == 'r') { - token_stream[(int) index++].kind = Token_register; - return; - } - break; - - case 'u': - if (*(cursor + 1) == 'n' && - *(cursor + 2) == 's' && - *(cursor + 3) == 'i' && - *(cursor + 4) == 'g' && - *(cursor + 5) == 'n' && - *(cursor + 6) == 'e' && - *(cursor + 7) == 'd') { - token_stream[(int) index++].kind = Token_unsigned; - return; - } - break; - - case 't': - if (*(cursor + 1) == 'e' && - *(cursor + 2) == 'm' && - *(cursor + 3) == 'p' && - *(cursor + 4) == 'l' && - *(cursor + 5) == 'a' && - *(cursor + 6) == 't' && - *(cursor + 7) == 'e') { - token_stream[(int) index++].kind = Token_template; - return; - } - if (*(cursor + 1) == 'y' && - *(cursor + 2) == 'p' && - *(cursor + 3) == 'e' && - *(cursor + 4) == 'n' && - *(cursor + 5) == 'a' && - *(cursor + 6) == 'm' && - *(cursor + 7) == 'e') { - token_stream[(int) index++].kind = Token_typename; - return; - } - break; - - case 'v': - if (*(cursor + 1) == 'o' && - *(cursor + 2) == 'l' && - *(cursor + 3) == 'a' && - *(cursor + 4) == 't' && - *(cursor + 5) == 'i' && - *(cursor + 6) == 'l' && - *(cursor + 7) == 'e') { - token_stream[(int) index++].kind = Token_volatile; - return; - } - break; - - } - token_stream[(int) index++].kind = Token_identifier; -} - -void Lexer::scanKeyword9() -{ - switch (*cursor) { - case 'p': - if (*(cursor + 1) == 'r' && - *(cursor + 2) == 'o' && - *(cursor + 3) == 't' && - *(cursor + 4) == 'e' && - *(cursor + 5) == 'c' && - *(cursor + 6) == 't' && - *(cursor + 7) == 'e' && - *(cursor + 8) == 'd') { - token_stream[(int) index++].kind = Token_protected; - return; - } - break; - - case 'n': - if (*(cursor + 1) == 'a' && - *(cursor + 2) == 'm' && - *(cursor + 3) == 'e' && - *(cursor + 4) == 's' && - *(cursor + 5) == 'p' && - *(cursor + 6) == 'a' && - *(cursor + 7) == 'c' && - *(cursor + 8) == 'e') { - token_stream[(int) index++].kind = Token_namespace; - return; - } - break; - - } - token_stream[(int) index++].kind = Token_identifier; -} - -void Lexer::scanKeyword10() -{ - switch (*cursor) { - case 'c': - if (*(cursor + 1) == 'o' && - *(cursor + 2) == 'n' && - *(cursor + 3) == 's' && - *(cursor + 4) == 't' && - *(cursor + 5) == '_' && - *(cursor + 6) == 'c' && - *(cursor + 7) == 'a' && - *(cursor + 8) == 's' && - *(cursor + 9) == 't') { - token_stream[(int) index++].kind = Token_const_cast; - return; - } - break; - - case 'Q': - if (*(cursor + 1) == '_' && - *(cursor + 2) == 'P' && - *(cursor + 3) == 'R' && - *(cursor + 4) == 'O' && - *(cursor + 5) == 'P' && - *(cursor + 6) == 'E' && - *(cursor + 7) == 'R' && - *(cursor + 8) == 'T' && - *(cursor + 9) == 'Y') { - token_stream[(int) index++].kind = Token_Q_PROPERTY; - return; - } - - break; - } - - token_stream[(int) index++].kind = Token_identifier; -} - -void Lexer::scanKeyword11() -{ - switch (*cursor) { - case 'Q': - if (*(cursor + 1) == '_' && - *(cursor + 2) == 'I' && - *(cursor + 3) == 'N' && - *(cursor + 4) == 'V' && - *(cursor + 5) == 'O' && - *(cursor + 6) == 'K' && - *(cursor + 7) == 'A' && - *(cursor + 8) == 'B' && - *(cursor + 9) == 'L' && - *(cursor + 10) == 'E') { - token_stream[(int) index++].kind = Token_Q_INVOKABLE; - return; - } - break; - - case 's': - if (*(cursor + 1) == 't' && - *(cursor + 2) == 'a' && - *(cursor + 3) == 't' && - *(cursor + 4) == 'i' && - *(cursor + 5) == 'c' && - *(cursor + 6) == '_' && - *(cursor + 7) == 'c' && - *(cursor + 8) == 'a' && - *(cursor + 9) == 's' && - *(cursor + 10) == 't') { - token_stream[(int) index++].kind = Token_static_cast; - return; - } - break; - - } - token_stream[(int) index++].kind = Token_identifier; -} - -void Lexer::scanKeyword12() -{ - switch (*cursor) { - case 'd': - if (*(cursor + 1) == 'y' && - *(cursor + 2) == 'n' && - *(cursor + 3) == 'a' && - *(cursor + 4) == 'm' && - *(cursor + 5) == 'i' && - *(cursor + 6) == 'c' && - *(cursor + 7) == '_' && - *(cursor + 8) == 'c' && - *(cursor + 9) == 'a' && - *(cursor + 10) == 's' && - *(cursor + 11) == 't') { - token_stream[(int) index++].kind = Token_dynamic_cast; - return; - } - break; - - } - token_stream[(int) index++].kind = Token_identifier; -} - -void Lexer::scanKeyword13() -{ - switch (*cursor) { - case '_': - if (*(cursor + 1) == '_' && - *(cursor + 2) == 'a' && - *(cursor + 3) == 't' && - *(cursor + 4) == 't' && - *(cursor + 5) == 'r' && - *(cursor + 6) == 'i' && - *(cursor + 7) == 'b' && - *(cursor + 8) == 'u' && - *(cursor + 9) == 't' && - *(cursor + 10) == 'e' && - *(cursor + 11) == '_' && - *(cursor + 12) == '_') { - token_stream[(int) index++].kind = Token___attribute__; - return; - } - break; - } - token_stream[(int) index++].kind = Token_identifier; -} - -void Lexer::scanKeyword14() -{ - switch (*cursor) { - case 'k': - if (*(cursor + 1) == '_' && - *(cursor + 2) == 'd' && - *(cursor + 3) == 'c' && - *(cursor + 4) == 'o' && - *(cursor + 5) == 'p' && - *(cursor + 6) == '_' && - *(cursor + 7) == 's' && - *(cursor + 8) == 'i' && - *(cursor + 9) == 'g' && - *(cursor + 10) == 'n' && - *(cursor + 11) == 'a' && - *(cursor + 12) == 'l' && - *(cursor + 13) == 's') { - token_stream[(int) index++].kind = Token_k_dcop_signals; - return; - } - break; - } - token_stream[(int) index++].kind = Token_identifier; -} - -void Lexer::scanKeyword16() -{ - switch (*cursor) { - case 'r': - if (*(cursor + 1) == 'e' && - *(cursor + 2) == 'i' && - *(cursor + 3) == 'n' && - *(cursor + 4) == 't' && - *(cursor + 5) == 'e' && - *(cursor + 6) == 'r' && - *(cursor + 7) == 'p' && - *(cursor + 8) == 'r' && - *(cursor + 9) == 'e' && - *(cursor + 10) == 't' && - *(cursor + 11) == '_' && - *(cursor + 12) == 'c' && - *(cursor + 13) == 'a' && - *(cursor + 14) == 's' && - *(cursor + 15) == 't') { - token_stream[(int) index++].kind = Token_reinterpret_cast; - return; - } - break; - } - - token_stream[(int) index++].kind = Token_identifier; -} - -// kate: space-indent on; indent-width 2; replace-tabs on; diff --git a/sources/shiboken2/ApiExtractor/parser/lexer.h b/sources/shiboken2/ApiExtractor/parser/lexer.h deleted file mode 100644 index 7144355e4..000000000 --- a/sources/shiboken2/ApiExtractor/parser/lexer.h +++ /dev/null @@ -1,295 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#ifndef LEXER_H -#define LEXER_H - -#include "symbol.h" - -#include <QtCore/QString> -#include <cstdlib> -#include <cassert> - -struct NameSymbol; -class Lexer; -class Control; - -typedef void (Lexer::*scan_fun_ptr)(); - -class Token -{ -public: - int kind; - std::size_t position; - std::size_t size; - char const *text; - - union { - const NameSymbol *symbol; - std::size_t right_brace; - } extra; -}; - -class LocationTable -{ -private: - LocationTable(const LocationTable &source); - void operator = (const LocationTable &source); - -public: - inline LocationTable(std::size_t size = 1024) - : lines(0), - line_count(0), - current_line(0) { - resize(size); - } - - inline ~LocationTable() { - free(lines); - } - - inline std::size_t size() const { - return line_count; - } - - void resize(std::size_t size) { - Q_ASSERT(size > 0); - lines = (std::size_t*) ::realloc(lines, sizeof(std::size_t) * size); - line_count = size; - } - - void positionAt(std::size_t offset, int *line, int *column) const { - positionAt(offset, (int) current_line, line, column); - } - - void positionAt(std::size_t offset, int max_line, int *line, int *column) const; - - inline std::size_t &operator[](int index) { - return lines[index]; - } - -private: - std::size_t *lines; - std::size_t line_count; - std::size_t current_line; - - friend class Lexer; -}; - -class TokenStream -{ -private: - TokenStream(const TokenStream &); - void operator = (const TokenStream &); - -public: - inline TokenStream(std::size_t size = 1024) - : tokens(0), - index(0), - token_count(0) { - resize(size); - } - - inline ~TokenStream() { - ::free(tokens); - } - - inline std::size_t size() const { - return token_count; - } - - inline std::size_t cursor() const { - return index; - } - - inline void rewind(int i) { - index = i; - } - - void resize(std::size_t size) { - Q_ASSERT(size > 0); - tokens = (Token*) ::realloc(tokens, sizeof(Token) * size); - token_count = size; - } - - inline std::size_t nextToken() { - return index++; - } - - inline int lookAhead(std::size_t i = 0) const { - return tokens[index + i].kind; - } - - inline int kind(std::size_t i) const { - return tokens[i].kind; - } - - inline std::size_t position(std::size_t i) const { - return tokens[i].position; - } - - inline const NameSymbol *symbol(std::size_t i) const { - return tokens[i].extra.symbol; - } - - inline std::size_t matchingBrace(std::size_t i) const { - return tokens[i].extra.right_brace; - } - - inline Token &operator[](int index) { - return tokens[index]; - } - - inline const Token &token(int index) const { - return tokens[index]; - } - -private: - Token *tokens; - std::size_t index; - std::size_t token_count; - -private: - friend class Lexer; -}; - -class LocationManager -{ - LocationManager(LocationManager const &__other); - void operator = (LocationManager const &__other); - -public: - LocationManager(TokenStream &__token_stream, - LocationTable &__location_table, - LocationTable &__line_table): - token_stream(__token_stream), - location_table(__location_table), - line_table(__line_table) {} - - void positionAt(std::size_t offset, int *line, int *column, - QString *filename) const; - - void extract_line(int offset, int *line, QString *filename) const; - - TokenStream &token_stream; - LocationTable &location_table; - LocationTable &line_table; -}; - -class Lexer -{ -public: - Lexer(LocationManager &__location, Control *__control): - _M_location(__location), - token_stream(_M_location.token_stream), - location_table(_M_location.location_table), - line_table(_M_location.line_table), - control(__control) {} - - void tokenize(const char *contents, std::size_t size); - - LocationManager &_M_location; - TokenStream &token_stream; - LocationTable &location_table; - LocationTable &line_table; - -private: - void reportError(const QString& msg); - - void initialize_scan_table(); - void scan_newline(); - void scan_white_spaces(); - void scan_identifier_or_keyword(); - void scan_identifier_or_literal(); - void scan_int_constant(); - void scan_char_constant(); - void scan_string_constant(); - void scan_invalid_input(); - void scan_preprocessor(); - - // keywords - void scanKeyword0(); - void scanKeyword2(); - void scanKeyword3(); - void scanKeyword4(); - void scanKeyword5(); - void scanKeyword6(); - void scanKeyword7(); - void scanKeyword8(); - void scanKeyword9(); - void scanKeyword10(); - void scanKeyword11(); - void scanKeyword12(); - void scanKeyword13(); - void scanKeyword14(); - void scanKeyword16(); - - // operators - void scan_not(); - void scan_remainder(); - void scan_and(); - void scan_left_paren(); - void scan_right_paren(); - void scan_star(); - void scan_plus(); - void scan_comma(); - void scan_minus(); - void scan_dot(); - void scan_divide(); - void scan_colon(); - void scan_semicolon(); - void scan_less(); - void scan_equal(); - void scan_greater(); - void scan_question(); - void scan_left_bracket(); - void scan_right_bracket(); - void scan_xor(); - void scan_left_brace(); - void scan_or(); - void scan_right_brace(); - void scan_tilde(); - void scan_EOF(); - -private: - Control *control; - const unsigned char *cursor; - const unsigned char *begin_buffer; - const unsigned char *end_buffer; - std::size_t index; - - static scan_fun_ptr s_scan_table[]; - static scan_fun_ptr s_scan_keyword_table[]; - static bool s_initialized; -}; - -#endif // LEXER_H - -// kate: space-indent on; indent-width 2; replace-tabs on; diff --git a/sources/shiboken2/ApiExtractor/parser/list.h b/sources/shiboken2/ApiExtractor/parser/list.h deleted file mode 100644 index 764fafffd..000000000 --- a/sources/shiboken2/ApiExtractor/parser/list.h +++ /dev/null @@ -1,105 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#ifndef FASTLIST_H -#define FASTLIST_H - -#include "smallobject.h" - -template <typename Tp> -struct ListNode { - Tp element; - int index; - mutable const ListNode<Tp> *next; - - static ListNode *create(const Tp &element, pool *p) { - ListNode<Tp> *node = new(p->allocate(sizeof(ListNode), strideof(ListNode))) ListNode(); - node->element = element; - node->index = 0; - node->next = node; - - return node; - } - - static ListNode *create(const ListNode *n1, const Tp &element, pool *p) { - ListNode<Tp> *n2 = ListNode::create(element, p); - - n2->index = n1->index + 1; - n2->next = n1->next; - n1->next = n2; - - return n2; - } - - inline ListNode<Tp>() { } - - inline const ListNode<Tp> *at(int index) const { - const ListNode<Tp> *node = this; - while (index != node->index) - node = node->next; - - return node; - } - - inline bool hasNext() const { - return index < next->index; - } - - inline int count() const { - return 1 + toBack()->index; - } - - inline const ListNode<Tp> *toFront() const { - return toBack()->next; - } - - inline const ListNode<Tp> *toBack() const { - const ListNode<Tp> *node = this; - while (node->hasNext()) - node = node->next; - - return node; - } -}; - -template <class Tp> -inline const ListNode<Tp> *snoc(const ListNode<Tp> *list, - const Tp &element, pool *p) -{ - if (!list) - return ListNode<Tp>::create(element, p); - - return ListNode<Tp>::create(list->toBack(), element, p); -} - -#endif // FASTLIST_H - -// kate: space-indent on; indent-width 2; replace-tabs on; - diff --git a/sources/shiboken2/ApiExtractor/parser/name_compiler.cpp b/sources/shiboken2/ApiExtractor/parser/name_compiler.cpp deleted file mode 100644 index 338d81c25..000000000 --- a/sources/shiboken2/ApiExtractor/parser/name_compiler.cpp +++ /dev/null @@ -1,139 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#include "name_compiler.h" -#include "type_compiler.h" -#include "declarator_compiler.h" -#include "lexer.h" -#include "symbol.h" -#include "binder.h" - -#include <QtCore/qdebug.h> - -NameCompiler::NameCompiler(Binder *binder) - : _M_binder(binder), _M_token_stream(binder->tokenStream()) -{ -} - -QString NameCompiler::decode_operator(std::size_t index) const -{ - const Token &tk = _M_token_stream->token((int) index); - return QString::fromUtf8(&tk.text[tk.position], (int) tk.size); -} - -QString NameCompiler::internal_run(AST *node) -{ - _M_name.clear(); - visit(node); - return name(); -} - -void NameCompiler::visitUnqualifiedName(UnqualifiedNameAST *node) -{ - QString tmp_name; - - if (node->tilde) - tmp_name += QLatin1String("~"); - - if (node->id) - tmp_name += _M_token_stream->symbol(node->id)->as_string(); - - if (OperatorFunctionIdAST *op_id = node->operator_id) { -#if defined(__GNUC__) -#warning "NameCompiler::visitUnqualifiedName() -- implement me" -#endif - - if (op_id->op && op_id->op->op) { - tmp_name += QLatin1String("operator"); - tmp_name += decode_operator(op_id->op->op); - if (op_id->op->close) - tmp_name += decode_operator(op_id->op->close); - } else if (op_id->type_specifier) { -#if defined(__GNUC__) -#warning "don't use an hardcoded string as cast' name" -#endif - Token const &tk = _M_token_stream->token((int) op_id->start_token); - Token const &end_tk = _M_token_stream->token((int) op_id->end_token); - tmp_name += QString::fromLatin1(&tk.text[tk.position], - (int)(end_tk.position - tk.position)).trimmed(); - } - } - - _M_name += tmp_name; - if (node->template_arguments) { - // ### cleanup - _M_name.last() += QLatin1String("<"); - visitNodes(this, node->template_arguments); - _M_name.last().truncate(_M_name.last().count() - 1); // remove the last ',' - _M_name.last() += QLatin1String(">"); - } - -} - -void NameCompiler::visitTemplateArgument(TemplateArgumentAST *node) -{ - if (node->type_id && node->type_id->type_specifier) { - TypeCompiler type_cc(_M_binder); - type_cc.run(node->type_id->type_specifier); - - DeclaratorCompiler decl_cc(_M_binder); - decl_cc.run(node->type_id->declarator); - - if (type_cc.isConstant()) - _M_name.last() += QLatin1String("const "); - - QStringList q = type_cc.qualifiedName(); - - if (q.count() == 1) { -#if defined (RXX_RESOLVE_TYPEDEF) // ### it'll break :( - TypeInfo tp; - tp.setQualifiedName(q); - tp = TypeInfo::resolveType(tp, _M_binder->currentScope()->toItem()); - q = tp.qualifiedName(); -#endif - - if (CodeModelItem item = _M_binder->model()->findItem(q, _M_binder->currentScope())) { - if (item->name() == q.last()) - q = item->qualifiedName(); - } - } - - _M_name.last() += q.join(QLatin1String("::")); - - if (decl_cc.isReference()) - _M_name.last() += QLatin1Char('&'); - if (decl_cc.indirection()) - _M_name.last() += QString(decl_cc.indirection(), QLatin1Char('*')); - - _M_name.last() += QLatin1Char(','); - } -} - -// kate: space-indent on; indent-width 2; replace-tabs on; diff --git a/sources/shiboken2/ApiExtractor/parser/name_compiler.h b/sources/shiboken2/ApiExtractor/parser/name_compiler.h deleted file mode 100644 index 431d401f8..000000000 --- a/sources/shiboken2/ApiExtractor/parser/name_compiler.h +++ /dev/null @@ -1,74 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#ifndef NAME_COMPILER_H -#define NAME_COMPILER_H - -#include "default_visitor.h" -#include <QtCore/QStringList> - -class TokenStream; -class Binder; - -class NameCompiler: protected DefaultVisitor -{ -public: - NameCompiler(Binder *binder); - - void run(NameAST *node) { - internal_run(node); - } - void run(UnqualifiedNameAST *node) { - internal_run(node); - } - - QString name() const { - return _M_name.join(QLatin1String("::")); - } - QStringList qualifiedName() const { - return _M_name; - } - -protected: - virtual void visitUnqualifiedName(UnqualifiedNameAST *node); - virtual void visitTemplateArgument(TemplateArgumentAST *node); - - QString internal_run(AST *node); - QString decode_operator(std::size_t index) const; - -private: - Binder *_M_binder; - TokenStream *_M_token_stream; - QStringList _M_name; -}; - -#endif // NAME_COMPILER_H - -// kate: space-indent on; indent-width 2; replace-tabs on; diff --git a/sources/shiboken2/ApiExtractor/parser/parser.cpp b/sources/shiboken2/ApiExtractor/parser/parser.cpp deleted file mode 100644 index 60d034e83..000000000 --- a/sources/shiboken2/ApiExtractor/parser/parser.cpp +++ /dev/null @@ -1,4075 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ - - -// c++ support -#include "parser.h" -#include "tokens.h" -#include "lexer.h" -#include "control.h" - -#include <cstdlib> - -#define ADVANCE(tk, descr) \ - { \ - if (token_stream.lookAhead() != tk) { \ - tokenRequiredError(tk); \ - return false; \ - } \ - token_stream.nextToken(); \ - } - -#define ADVANCE_NR(tk, descr) \ - do { \ - if (token_stream.lookAhead() != tk) { \ - tokenRequiredError(tk); \ - } \ - else \ - token_stream.nextToken(); \ - } while (0) - -#define CHECK(tk) \ - do { \ - if (token_stream.lookAhead() != tk) { \ - return false; \ - } \ - token_stream.nextToken(); \ - } while (0) - -#define UPDATE_POS(_node, start, end) \ - do { \ - (_node)->start_token = start; \ - (_node)->end_token = end; \ - } while (0) - -Parser::Parser(Control *c) - : _M_location(token_stream, location_table, line_table), - control(c), - lexer(_M_location, control) -{ - _M_block_errors = false; -} - -Parser::~Parser() -{ -} - -void Parser::advance() -{ - token_stream.nextToken(); -} - -TranslationUnitAST *Parser::parse(const char *contents, - std::size_t size, pool *p) -{ - _M_block_errors = false; - _M_pool = p; - lexer.tokenize(contents, size); - token_stream.nextToken(); // skip the first token - - Lexer *oldLexer = control->changeLexer(&lexer); - Parser *oldParser = control->changeParser(this); - - TranslationUnitAST *ast = 0; - parseTranslationUnit(ast); - - control->changeLexer(oldLexer); - control->changeParser(oldParser); - - return ast; -} - -bool Parser::parseWinDeclSpec(WinDeclSpecAST *&node) -{ - if (token_stream.lookAhead() != Token_identifier) - return false; - - std::size_t start = token_stream.cursor(); - - const NameSymbol *name_symbol = token_stream.symbol(token_stream.cursor()); - QString name = name_symbol->as_string(); - if (name != QLatin1String("__declspec")) - return false; - std::size_t specifier = token_stream.cursor(); - - token_stream.nextToken(); - if (token_stream.lookAhead() != '(') - return false; - - token_stream.nextToken(); - if (token_stream.lookAhead() != Token_identifier) - return false; - std::size_t modifier = token_stream.cursor(); - - token_stream.nextToken(); - if (token_stream.lookAhead() != ')') - return false; - - token_stream.nextToken(); - - node = CreateNode<WinDeclSpecAST>(_M_pool); - node->specifier = specifier; - node->modifier = modifier; - - UPDATE_POS(node, start, token_stream.cursor()); - - return true; -} - -void Parser::tokenRequiredError(int token) -{ - QString err; - - err += QLatin1String("expected token "); - err += QLatin1String("``"); - err += QLatin1String(token_name(token)); - err += QLatin1String("'' found ``"); - err += QLatin1String(token_name(token_stream.lookAhead())); - err += QLatin1String("''"); - - reportError(err); -} - -void Parser::syntaxError() -{ - QString err; - - err += QLatin1String("unexpected token "); - err += QLatin1String("``"); - err += QLatin1String(token_name(token_stream.lookAhead())); - err += QLatin1String("''"); - - reportError(err); -} - -void Parser::reportError(const QString& msg) -{ - if (!_M_block_errors) { - int line, column; - QString fileName; - - std::size_t tok = token_stream.cursor(); - location().positionAt(token_stream.position(tok), - &line, &column, &fileName); - - Control::ErrorMessage errmsg; - errmsg.setLine(line + 1); - errmsg.setColumn(column); - errmsg.setFileName(fileName); - errmsg.setMessage(QLatin1String("** PARSER ERROR ") + msg); - control->reportError(errmsg); - } -} - -bool Parser::skipUntil(int token) -{ - while (token_stream.lookAhead()) { - if (token_stream.lookAhead() == token) - return true; - - token_stream.nextToken(); - } - - return false; -} - -bool Parser::skipUntilDeclaration() -{ - while (token_stream.lookAhead()) { - - switch (token_stream.lookAhead()) { - case ';': - case '~': - case Token_scope: - case Token_identifier: - case Token_operator: - case Token_char: - case Token_wchar_t: - case Token_bool: - case Token_short: - case Token_int: - case Token_long: - case Token_signed: - case Token_unsigned: - case Token_float: - case Token_double: - case Token_void: - case Token_extern: - case Token_namespace: - case Token_using: - case Token_typedef: - case Token_asm: - case Token_template: - case Token_export: - - case Token_const: // cv - case Token_volatile: // cv - - case Token_public: - case Token_protected: - case Token_private: - case Token_signals: // Qt - case Token_slots: // Qt - return true; - - default: - token_stream.nextToken(); - } - } - - return false; -} - -bool Parser::skipUntilStatement() -{ - while (token_stream.lookAhead()) { - switch (token_stream.lookAhead()) { - case ';': - case '{': - case '}': - case Token_const: - case Token_volatile: - case Token_identifier: - case Token_case: - case Token_default: - case Token_if: - case Token_switch: - case Token_while: - case Token_do: - case Token_for: - case Token_break: - case Token_continue: - case Token_return: - case Token_goto: - case Token_try: - case Token_catch: - case Token_throw: - case Token_char: - case Token_wchar_t: - case Token_bool: - case Token_short: - case Token_int: - case Token_long: - case Token_signed: - case Token_unsigned: - case Token_float: - case Token_double: - case Token_void: - case Token_class: - case Token_struct: - case Token_union: - case Token_enum: - case Token_scope: - case Token_template: - case Token_using: - return true; - - default: - token_stream.nextToken(); - } - } - - return false; -} - -bool Parser::skip(int l, int r) -{ - int count = 0; - while (token_stream.lookAhead()) { - int tk = token_stream.lookAhead(); - - if (tk == l) - ++count; - else if (tk == r) - --count; - else if (l != '{' && (tk == '{' || tk == '}' || tk == ';')) - return false; - - if (!count) - return true; - - token_stream.nextToken(); - } - - return false; -} - -bool Parser::parseName(NameAST *&node, bool acceptTemplateId) -{ - std::size_t start = token_stream.cursor(); - - WinDeclSpecAST *winDeclSpec = 0; - parseWinDeclSpec(winDeclSpec); - - NameAST *ast = CreateNode<NameAST>(_M_pool); - - if (token_stream.lookAhead() == Token_scope) { - ast->global = true; - token_stream.nextToken(); - } - - std::size_t idx = token_stream.cursor(); - - while (true) { - UnqualifiedNameAST *n = 0; - if (!parseUnqualifiedName(n)) - return false; - - if (token_stream.lookAhead() == Token_scope) { - token_stream.nextToken(); - - ast->qualified_names - = snoc(ast->qualified_names, n, _M_pool); - - if (token_stream.lookAhead() == Token_template) { - /// skip optional template #### @todo CHECK - token_stream.nextToken(); - } - } else { - Q_ASSERT(n); - if (!acceptTemplateId) { - token_stream.rewind((int) n->start_token); - parseUnqualifiedName(n, false); - } - - ast->unqualified_name = n; - break; - } - } - - if (idx == token_stream.cursor()) - return false; - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - - return true; -} - -bool Parser::parseTranslationUnit(TranslationUnitAST *&node) -{ - std::size_t start = token_stream.cursor(); - TranslationUnitAST *ast = CreateNode<TranslationUnitAST>(_M_pool); - - while (token_stream.lookAhead()) { - std::size_t startDecl = token_stream.cursor(); - - DeclarationAST *declaration = 0; - if (parseDeclaration(declaration)) { - ast->declarations = - snoc(ast->declarations, declaration, _M_pool); - } else { - // error recovery - if (startDecl == token_stream.cursor()) { - // skip at least one token - token_stream.nextToken(); - } - - skipUntilDeclaration(); - } - } - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - - return true; -} - -bool Parser::parseDeclaration(DeclarationAST *&node) -{ - std::size_t start = token_stream.cursor(); - - switch (token_stream.lookAhead()) { - case ';': - token_stream.nextToken(); - return true; - - case Token_extern: - return parseLinkageSpecification(node); - - case Token_namespace: - return parseNamespace(node); - - case Token_using: - return parseUsing(node); - - case Token_typedef: - return parseTypedef(node); - - case Token_asm: - return parseAsmDefinition(node); - - case Token_Q_ENUMS: - case Token_Q_ENUM: - // Qt5: - // These two Q_ENUM tokens map to the same handler. - // If that turns out to be wrong, then write a new one - // named parseQ_ENUM - return parseQ_ENUMS(node); - - case Token_template: - case Token_export: - return parseTemplateDeclaration(node); - - default: { - const ListNode<std::size_t> *cv = 0; - parseCvQualify(cv); - - const ListNode<std::size_t> *storageSpec = 0; - parseStorageClassSpecifier(storageSpec); - - parseCvQualify(cv); - - TypeSpecifierAST *spec = 0; - if (parseEnumSpecifier(spec) - || parseClassSpecifier(spec) - || parseForwardDeclarationSpecifier(spec)) { - parseCvQualify(cv); - - spec->cv = cv; - - const ListNode<InitDeclaratorAST*> *declarators = 0; - parseInitDeclaratorList(declarators); - ADVANCE(';', ";"); - - SimpleDeclarationAST *ast = - CreateNode<SimpleDeclarationAST>(_M_pool); - - ast->storage_specifiers = storageSpec; - ast->type_specifier = spec; - ast->init_declarators = declarators; - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - - return true; - } - } - } // end switch - - token_stream.rewind((int) start); - return parseDeclarationInternal(node); -} - -bool Parser::parseLinkageSpecification(DeclarationAST *&node) -{ - std::size_t start = token_stream.cursor(); - - CHECK(Token_extern); - - LinkageSpecificationAST *ast = CreateNode<LinkageSpecificationAST>(_M_pool); - - if (token_stream.lookAhead() == Token_string_literal) { - ast->extern_type = token_stream.cursor(); - token_stream.nextToken(); - } - - if (token_stream.lookAhead() == '{') - parseLinkageBody(ast->linkage_body); - else if (!parseDeclaration(ast->declaration)) - reportError(QLatin1String("Declaration syntax error")); - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - - return true; -} - -bool Parser::parseLinkageBody(LinkageBodyAST *&node) -{ - std::size_t start = token_stream.cursor(); - - CHECK('{'); - - LinkageBodyAST *ast = CreateNode<LinkageBodyAST>(_M_pool); - - while (token_stream.lookAhead()) { - int tk = token_stream.lookAhead(); - - if (tk == '}') - break; - - std::size_t startDecl = token_stream.cursor(); - - DeclarationAST *declaration = 0; - if (parseDeclaration(declaration)) { - ast->declarations = snoc(ast->declarations, declaration, _M_pool); - } else { - // error recovery - if (startDecl == token_stream.cursor()) { - // skip at least one token - token_stream.nextToken(); - } - - skipUntilDeclaration(); - } - } - - if (token_stream.lookAhead() != '}') - reportError(QLatin1String("} expected")); - else - token_stream.nextToken(); - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - - return true; -} - -bool Parser::parseNamespace(DeclarationAST *&node) -{ - std::size_t start = token_stream.cursor(); - - CHECK(Token_namespace); - - std::size_t namespace_name = 0; - if (token_stream.lookAhead() == Token_identifier) { - namespace_name = token_stream.cursor(); - token_stream.nextToken(); - } - - if (token_stream.lookAhead() == '=') { - // namespace alias - token_stream.nextToken(); - - NameAST *name = 0; - if (parseName(name)) { - ADVANCE(';', ";"); - - NamespaceAliasDefinitionAST *ast - = CreateNode<NamespaceAliasDefinitionAST>(_M_pool); - ast->namespace_name = namespace_name; - ast->alias_name = name; - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - return true; - } else { - reportError(QLatin1String("namespace expected")); - return false; - } - } else if (token_stream.lookAhead() != '{') { - reportError(QLatin1String("{ expected")); - return false; - } - - NamespaceAST *ast = CreateNode<NamespaceAST>(_M_pool); - ast->namespace_name = namespace_name; - parseLinkageBody(ast->linkage_body); - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - - return true; -} - -bool Parser::parseUsing(DeclarationAST *&node) -{ - std::size_t start = token_stream.cursor(); - - CHECK(Token_using); - - if (token_stream.lookAhead() == Token_namespace) - return parseUsingDirective(node); - - UsingAST *ast = CreateNode<UsingAST>(_M_pool); - - if (token_stream.lookAhead() == Token_typename) { - ast->type_name = token_stream.cursor(); - token_stream.nextToken(); - } - - if (!parseName(ast->name)) - return false; - - ADVANCE(';', ";"); - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - - return true; -} - -bool Parser::parseUsingDirective(DeclarationAST *&node) -{ - std::size_t start = token_stream.cursor(); - - CHECK(Token_namespace); - - NameAST *name = 0; - if (!parseName(name)) { - reportError(QLatin1String("Namespace name expected")); - return false; - } - - ADVANCE(';', ";"); - - UsingDirectiveAST *ast = CreateNode<UsingDirectiveAST>(_M_pool); - ast->name = name; - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - - return true; -} - - -bool Parser::parseOperatorFunctionId(OperatorFunctionIdAST *&node) -{ - std::size_t start = token_stream.cursor(); - - CHECK(Token_operator); - - OperatorFunctionIdAST *ast = CreateNode<OperatorFunctionIdAST>(_M_pool); - - if (!parseOperator(ast->op)) { - ast->op = 0; - - // parse cast operator - const ListNode<std::size_t> *cv = 0; - parseCvQualify(cv); - - if (!parseSimpleTypeSpecifier(ast->type_specifier)) { - syntaxError(); - return false; - } - - parseCvQualify(cv); - ast->type_specifier->cv = cv; - - PtrOperatorAST *ptr_op = 0; - while (parsePtrOperator(ptr_op)) - ast->ptr_ops = snoc(ast->ptr_ops, ptr_op, _M_pool); - } - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - return true; -} - -bool Parser::parseTemplateArgumentList(const ListNode<TemplateArgumentAST*> *&node, - bool reportError) -{ - TemplateArgumentAST *templArg = 0; - if (!parseTemplateArgument(templArg)) - return false; - - node = snoc(node, templArg, _M_pool); - - while (token_stream.lookAhead() == ',') { - token_stream.nextToken(); - - if (!parseTemplateArgument(templArg)) { - if (reportError) { - syntaxError(); - break; - } - - node = 0; - return false; - } - - node = snoc(node, templArg, _M_pool); - } - - return true; -} - -bool Parser::parseTypedef(DeclarationAST *&node) -{ - std::size_t start = token_stream.cursor(); - - CHECK(Token_typedef); - - TypeSpecifierAST *spec = 0; - if (!parseTypeSpecifierOrClassSpec(spec)) { - reportError(QLatin1String("Need a type specifier to declare")); - return false; - } - - const ListNode<InitDeclaratorAST*> *declarators = 0; - if (!parseInitDeclaratorList(declarators)) { - //reportError(("Need an identifier to declare")); - //return false; - } - - ADVANCE(';', ";"); - - TypedefAST *ast = CreateNode<TypedefAST>(_M_pool); - ast->type_specifier = spec; - ast->init_declarators = declarators; - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - - return true; -} - -bool Parser::parseAsmDefinition(DeclarationAST *&node) -{ - std::size_t start = token_stream.cursor(); - - ADVANCE(Token_asm, "asm"); - - const ListNode<std::size_t> *cv = 0; - parseCvQualify(cv); - -#if defined(__GNUC__) -#warning "implement me" -#endif - skip('(', ')'); - token_stream.nextToken(); - ADVANCE(';', ";"); - - AsmDefinitionAST *ast = CreateNode<AsmDefinitionAST>(_M_pool); - ast->cv = cv; - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - - return true; -} - -bool Parser::parseTemplateDeclaration(DeclarationAST *&node) -{ - std::size_t start = token_stream.cursor(); - - std::size_t exported = 0; - if (token_stream.lookAhead() == Token_export) { - exported = token_stream.cursor(); - token_stream.nextToken(); - } - - CHECK(Token_template); - - const ListNode<TemplateParameterAST*> *params = 0; - if (token_stream.lookAhead() == '<') { - token_stream.nextToken(); - parseTemplateParameterList(params); - - ADVANCE('>', ">"); - } - - DeclarationAST *declaration = 0; - if (!parseDeclaration(declaration)) - reportError(QLatin1String("expected a declaration")); - - TemplateDeclarationAST *ast = CreateNode<TemplateDeclarationAST>(_M_pool); - ast->exported = exported; - ast->template_parameters = params; - ast->declaration = declaration; - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - - return true; -} - -bool Parser::parseOperator(OperatorAST *&node) -{ - std::size_t start = token_stream.cursor(); - - OperatorAST *ast = CreateNode<OperatorAST>(_M_pool); - - switch (token_stream.lookAhead()) { - case Token_new: - case Token_delete: { - ast->op = token_stream.cursor(); - token_stream.nextToken(); - - if (token_stream.lookAhead() == '[' - && token_stream.lookAhead(1) == ']') { - ast->open = token_stream.cursor(); - token_stream.nextToken(); - - ast->close = token_stream.cursor(); - token_stream.nextToken(); - } - } - break; - - case '+': - case '-': - case '*': - case '/': - case '%': - case '^': - case '&': - case '|': - case '~': - case '!': - case '=': - case '<': - case '>': - case ',': - case Token_assign: - case Token_shift: - case Token_eq: - case Token_not_eq: - case Token_leq: - case Token_geq: - case Token_and: - case Token_or: - case Token_incr: - case Token_decr: - case Token_ptrmem: - case Token_arrow: - ast->op = token_stream.cursor(); - token_stream.nextToken(); - break; - - default: - if (token_stream.lookAhead() == '(' - && token_stream.lookAhead(1) == ')') { - ast->op = ast->open = token_stream.cursor(); - token_stream.nextToken(); - ast->close = token_stream.cursor(); - token_stream.nextToken(); - } else if (token_stream.lookAhead() == '[' - && token_stream.lookAhead(1) == ']') { - ast->op = ast->open = token_stream.cursor(); - token_stream.nextToken(); - ast->close = token_stream.cursor(); - token_stream.nextToken(); - } else { - return false; - } - } - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - - return true; -} - -bool Parser::parseCvQualify(const ListNode<std::size_t> *&node) -{ - std::size_t start = token_stream.cursor(); - - int tk; - while (0 != (tk = token_stream.lookAhead()) - && (tk == Token_const || tk == Token_volatile)) { - node = snoc(node, token_stream.cursor(), _M_pool); - token_stream.nextToken(); - } - - return start != token_stream.cursor(); -} - -bool Parser::parseSimpleTypeSpecifier(TypeSpecifierAST *&node, - bool onlyIntegral) -{ - std::size_t start = token_stream.cursor(); - bool isIntegral = false; - bool done = false; - - const ListNode<std::size_t> *integrals = 0; - - while (!done) { - switch (token_stream.lookAhead()) { - case Token_char: - case Token_wchar_t: - case Token_bool: - case Token_short: - case Token_int: - case Token_long: - case Token_signed: - case Token_unsigned: - case Token_float: - case Token_double: - case Token_void: - integrals = snoc(integrals, token_stream.cursor(), _M_pool); - isIntegral = true; - token_stream.nextToken(); - break; - - default: - done = true; - } - } - - SimpleTypeSpecifierAST *ast = CreateNode<SimpleTypeSpecifierAST>(_M_pool); - if (isIntegral) { - ast->integrals = integrals; - } else if (token_stream.lookAhead() == Token___typeof) { - ast->type_of = token_stream.cursor(); - token_stream.nextToken(); - - if (token_stream.lookAhead() == '(') { - token_stream.nextToken(); - - std::size_t saved = token_stream.cursor(); - parseTypeId(ast->type_id); - if (token_stream.lookAhead() != ')') { - ast->type_id = 0; - token_stream.rewind((int) saved); - parseUnaryExpression(ast->expression); - } - ADVANCE(')', ")"); - } else { - parseUnaryExpression(ast->expression); - } - } else if (onlyIntegral) { - token_stream.rewind((int) start); - return false; - } else { - if (!parseName(ast->name, true)) { - ast->name = 0; - token_stream.rewind((int) start); - return false; - } - } - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - - return true; -} - -bool Parser::parsePtrOperator(PtrOperatorAST *&node) -{ - int tk = token_stream.lookAhead(); - - if (tk != '&' && tk != '*' - && tk != Token_scope && tk != Token_identifier) { - return false; - } - - std::size_t start = token_stream.cursor(); - - PtrOperatorAST *ast = CreateNode<PtrOperatorAST>(_M_pool); - - switch (token_stream.lookAhead()) { - case '&': - case '*': - ast->op = token_stream.cursor(); - token_stream.nextToken(); - break; - - case Token_scope: - case Token_identifier: { - if (!parsePtrToMember(ast->mem_ptr)) { - token_stream.rewind((int) start); - return false; - } - } - break; - - default: - Q_ASSERT(0); - break; - } - - parseCvQualify(ast->cv); - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - - return true; -} - -bool Parser::parseTemplateArgument(TemplateArgumentAST *&node) -{ - std::size_t start = token_stream.cursor(); - - TypeIdAST *typeId = 0; - ExpressionAST *expr = 0; - - if (!parseTypeId(typeId) || (token_stream.lookAhead() != ',' - && token_stream.lookAhead() != '>')) { - token_stream.rewind((int) start); - - if (!parseLogicalOrExpression(expr, true)) - return false; - } - - TemplateArgumentAST *ast = CreateNode<TemplateArgumentAST>(_M_pool); - ast->type_id = typeId; - ast->expression = expr; - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - - return true; -} - -bool Parser::parseTypeSpecifier(TypeSpecifierAST *&node) -{ - std::size_t start = token_stream.cursor(); - - const ListNode<std::size_t> *cv = 0; - parseCvQualify(cv); - - TypeSpecifierAST *ast = 0; - if (!parseElaboratedTypeSpecifier(ast) && !parseSimpleTypeSpecifier(ast)) { - token_stream.rewind((int) start); - return false; - } - - parseCvQualify(cv); - ast->cv = cv; - - node = ast; - - return true; -} - -bool Parser::parseDeclarator(DeclaratorAST *&node) -{ - std::size_t start = token_stream.cursor(); - - DeclaratorAST *ast = CreateNode<DeclaratorAST>(_M_pool); - - //fprintf(stderr, "[%s-%s] ast->ptr_ops: %p\n", __FILE__, __FUNCTION__, ast->ptr_ops); - - DeclaratorAST *decl = 0; - NameAST *declId = 0; - - PtrOperatorAST *ptrOp = 0; - while (parsePtrOperator(ptrOp)) - ast->ptr_ops = snoc(ast->ptr_ops, ptrOp, _M_pool); - - if (token_stream.lookAhead() == '(') { - token_stream.nextToken(); - - if (!parseDeclarator(decl)) - return false; - - ast->sub_declarator = decl; - - CHECK(')'); - } else { - if (token_stream.lookAhead() == ':') { - // unnamed bitfield - } else if (parseName(declId, true)) { - ast->id = declId; - } else { - token_stream.rewind((int) start); - return false; - } - - if (token_stream.lookAhead() == ':') { - token_stream.nextToken(); - - if (!parseConstantExpression(ast->bit_expression)) - reportError(QLatin1String("Constant expression expected")); - - goto update_pos; - } - } - - { - bool isVector = true; - - while (token_stream.lookAhead() == '[') { - token_stream.nextToken(); - - ExpressionAST *expr = 0; - parseCommaExpression(expr); - - ADVANCE(']', "]"); - - ast->array_dimensions = snoc(ast->array_dimensions, expr, _M_pool); - isVector = true; - } - - bool skipParen = false; - if (token_stream.lookAhead() == Token_identifier - && token_stream.lookAhead(1) == '(' - && token_stream.lookAhead(2) == '(') { - token_stream.nextToken(); - token_stream.nextToken(); - skipParen = true; - } - - int tok = token_stream.lookAhead(); - if (ast->sub_declarator - && !(isVector || tok == '(' || tok == ',' - || tok == ';' || tok == '=')) { - token_stream.rewind((int) start); - return false; - } - - std::size_t index = token_stream.cursor(); - if (token_stream.lookAhead() == '(') { - token_stream.nextToken(); - - ParameterDeclarationClauseAST *params = 0; - if (!parseParameterDeclarationClause(params)) { - token_stream.rewind((int) index); - goto update_pos; - } - - ast->parameter_declaration_clause = params; - - if (token_stream.lookAhead() != ')') { - token_stream.rewind((int) index); - goto update_pos; - } - - token_stream.nextToken(); // skip ')' - - parseCvQualify(ast->fun_cv); - parseNoExcept(); - parseExceptionSpecification(ast->exception_spec); - - if (token_stream.lookAhead() == Token___attribute__) - parse_Attribute__(); - } - - if (skipParen) { - if (token_stream.lookAhead() != ')') - reportError(QLatin1String("')' expected")); - else - token_stream.nextToken(); - } - } - -update_pos: - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - - return true; -} - -bool Parser::parseAbstractDeclarator(DeclaratorAST *&node) -{ - std::size_t start = token_stream.cursor(); - - DeclaratorAST *ast = CreateNode<DeclaratorAST>(_M_pool); - DeclaratorAST *decl = 0; - - PtrOperatorAST *ptrOp = 0; - while (parsePtrOperator(ptrOp)) - ast->ptr_ops = snoc(ast->ptr_ops, ptrOp, _M_pool); - - int index = (int) token_stream.cursor(); - if (token_stream.lookAhead() == '(') { - token_stream.nextToken(); - - if (!parseAbstractDeclarator(decl)) { - token_stream.rewind((int) index); - goto label1; - } - - ast->sub_declarator = decl; - - if (token_stream.lookAhead() != ')') { - token_stream.rewind((int) start); - return false; - } - token_stream.nextToken(); - } else if (token_stream.lookAhead() == ':') { - token_stream.nextToken(); - if (!parseConstantExpression(ast->bit_expression)) { - ast->bit_expression = 0; - reportError(QLatin1String("Constant expression expected")); - } - goto update_pos; - } - -label1: { - bool isVector = true; - - while (token_stream.lookAhead() == '[') { - token_stream.nextToken(); - - ExpressionAST *expr = 0; - parseCommaExpression(expr); - - ADVANCE(']', "]"); - - ast->array_dimensions = snoc(ast->array_dimensions, expr, _M_pool); - isVector = true; - } - - int tok = token_stream.lookAhead(); - if (ast->sub_declarator - && !(isVector || tok == '(' || tok == ',' - || tok == ';' || tok == '=')) { - token_stream.rewind((int) start); - return false; - } - - int index = (int) token_stream.cursor(); - if (token_stream.lookAhead() == '(') { - token_stream.nextToken(); - - ParameterDeclarationClauseAST *params = 0; - if (!parseParameterDeclarationClause(params)) { - token_stream.rewind((int) index); - goto update_pos; - } - - ast->parameter_declaration_clause = params; - - if (token_stream.lookAhead() != ')') { - token_stream.rewind((int) index); - goto update_pos; - } - - token_stream.nextToken(); // skip ')' - - parseCvQualify(ast->fun_cv); - parseExceptionSpecification(ast->exception_spec); - } - } - -update_pos: - if (token_stream.cursor() == start) - return false; - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - - return true; -} - -bool Parser::parseEnumSpecifier(TypeSpecifierAST *&node) -{ - std::size_t start = token_stream.cursor(); - - CHECK(Token_enum); - - NameAST *name = 0; - parseName(name); - - if (token_stream.lookAhead() != '{') { - token_stream.rewind((int) start); - return false; - } - token_stream.nextToken(); - - EnumSpecifierAST *ast = CreateNode<EnumSpecifierAST>(_M_pool); - ast->name = name; - - EnumeratorAST *enumerator = 0; - if (parseEnumerator(enumerator)) { - ast->enumerators = snoc(ast->enumerators, enumerator, _M_pool); - - while (token_stream.lookAhead() == ',') { - token_stream.nextToken(); - - if (!parseEnumerator(enumerator)) { - //reportError(("Enumerator expected")); - break; - } - - ast->enumerators = snoc(ast->enumerators, enumerator, _M_pool); - } - } - - ADVANCE_NR('}', "}"); - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - - return true; -} - -bool Parser::parseTemplateParameterList(const ListNode<TemplateParameterAST*> *&node) -{ - TemplateParameterAST *param = 0; - if (!parseTemplateParameter(param)) - return false; - - node = snoc(node, param, _M_pool); - - while (token_stream.lookAhead() == ',') { - token_stream.nextToken(); - - if (!parseTemplateParameter(param)) { - syntaxError(); - break; - } else { - node = snoc(node, param, _M_pool); - } - } - - return true; -} - -bool Parser::parseTemplateParameter(TemplateParameterAST *&node) -{ - std::size_t start = token_stream.cursor(); - TemplateParameterAST *ast = CreateNode<TemplateParameterAST>(_M_pool); - - int tk = token_stream.lookAhead(); - - if ((tk == Token_class || tk == Token_typename || tk == Token_template) - && parseTypeParameter(ast->type_parameter)) { - // nothing to do - } else if (!parseParameterDeclaration(ast->parameter_declaration)) - return false; - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - - return true; -} - -bool Parser::parseTypeParameter(TypeParameterAST *&node) -{ - std::size_t start = token_stream.cursor(); - - TypeParameterAST *ast = CreateNode<TypeParameterAST>(_M_pool); - ast->type = start; - - switch (token_stream.lookAhead()) { - case Token_class: - case Token_typename: { - token_stream.nextToken(); // skip class - - // parse optional name - if (parseName(ast->name, true)) { - if (token_stream.lookAhead() == '=') { - token_stream.nextToken(); - - if (!parseTypeId(ast->type_id)) { - //syntaxError(); - token_stream.rewind((int) start); - return false; - } - } else if (token_stream.lookAhead() != ',' - && token_stream.lookAhead() != '>') { - token_stream.rewind((int) start); - return false; - } - } - } - break; - - case Token_template: { - token_stream.nextToken(); // skip template - ADVANCE('<', "<"); - - if (!parseTemplateParameterList(ast->template_parameters)) - return false; - - ADVANCE('>', ">"); - - if (token_stream.lookAhead() == Token_class) - token_stream.nextToken(); - - // parse optional name - if (parseName(ast->name, true)) { - if (token_stream.lookAhead() == '=') { - token_stream.nextToken(); - - if (!parseTypeId(ast->type_id)) { - syntaxError(); - return false; - } - } - } - - if (token_stream.lookAhead() == '=') { - token_stream.nextToken(); - - parseName(ast->template_name, true); - } - } - break; - - default: - return false; - - } // end switch - - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - return true; -} - -bool Parser::parseStorageClassSpecifier(const ListNode<std::size_t> *&node) -{ - std::size_t start = token_stream.cursor(); - - int tk; - while (0 != (tk = token_stream.lookAhead()) - && (tk == Token_friend || tk == Token_auto - || tk == Token_register || tk == Token_static - || tk == Token_extern || tk == Token_mutable)) { - node = snoc(node, token_stream.cursor(), _M_pool); - token_stream.nextToken(); - } - - return start != token_stream.cursor(); -} - -bool Parser::parseFunctionSpecifier(const ListNode<std::size_t> *&node) -{ - std::size_t start = token_stream.cursor(); - - int tk; - while (0 != (tk = token_stream.lookAhead()) - && (tk == Token_inline || tk == Token_virtual - || tk == Token_explicit || tk == Token_Q_INVOKABLE)) { - node = snoc(node, token_stream.cursor(), _M_pool); - token_stream.nextToken(); - } - - return start != token_stream.cursor(); -} - -bool Parser::parseTypeId(TypeIdAST *&node) -{ - /// @todo implement the AST for typeId - std::size_t start = token_stream.cursor(); - - TypeSpecifierAST *spec = 0; - if (!parseTypeSpecifier(spec)) { - token_stream.rewind((int) start); - return false; - } - - DeclaratorAST *decl = 0; - parseAbstractDeclarator(decl); - - TypeIdAST *ast = CreateNode<TypeIdAST>(_M_pool); - ast->type_specifier = spec; - ast->declarator = decl; - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - - return true; -} - -bool Parser::parseInitDeclaratorList(const ListNode<InitDeclaratorAST*> *&node) -{ - InitDeclaratorAST *decl = 0; - if (!parseInitDeclarator(decl)) - return false; - - node = snoc(node, decl, _M_pool); - - while (token_stream.lookAhead() == ',') { - token_stream.nextToken(); - - if (!parseInitDeclarator(decl)) { - syntaxError(); - break; - } - node = snoc(node, decl, _M_pool); - } - - return true; -} - -bool Parser::parseParameterDeclarationClause(ParameterDeclarationClauseAST *&node) -{ - std::size_t start = token_stream.cursor(); - - ParameterDeclarationClauseAST *ast - = CreateNode<ParameterDeclarationClauseAST>(_M_pool); - - if (!parseParameterDeclarationList(ast->parameter_declarations)) { - if (token_stream.lookAhead() == ')') - goto good; - - if (token_stream.lookAhead() == Token_ellipsis - && token_stream.lookAhead(1) == ')') { - ast->ellipsis = token_stream.cursor(); - goto good; - } - - return false; - } - -good: - - if (token_stream.lookAhead() == Token_ellipsis) { - ast->ellipsis = token_stream.cursor(); - token_stream.nextToken(); - } - - /// @todo add ellipsis - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - - return true; -} - -bool Parser::parseParameterDeclarationList(const ListNode<ParameterDeclarationAST*> *&node) -{ - std::size_t start = token_stream.cursor(); - - ParameterDeclarationAST *param = 0; - if (!parseParameterDeclaration(param)) { - token_stream.rewind((int) start); - return false; - } - - node = snoc(node, param, _M_pool); - - while (token_stream.lookAhead() == ',') { - token_stream.nextToken(); - - if (token_stream.lookAhead() == Token_ellipsis) - break; - - if (!parseParameterDeclaration(param)) { - token_stream.rewind((int) start); - return false; - } - node = snoc(node, param, _M_pool); - } - - return true; -} - -bool Parser::parseParameterDeclaration(ParameterDeclarationAST *&node) -{ - std::size_t start = token_stream.cursor(); - - const ListNode<std::size_t> *storage = 0; - parseStorageClassSpecifier(storage); - - // parse decl spec - TypeSpecifierAST *spec = 0; - if (!parseTypeSpecifier(spec)) { - token_stream.rewind((int) start); - return false; - } - - int index = (int) token_stream.cursor(); - - DeclaratorAST *decl = 0; - if (!parseDeclarator(decl)) { - token_stream.rewind((int) index); - - // try with abstract declarator - parseAbstractDeclarator(decl); - } - - ExpressionAST *expr = 0; - if (token_stream.lookAhead() == '=') { - token_stream.nextToken(); - if (!parseLogicalOrExpression(expr, true)) - reportError(QLatin1String("Expression expected")); - } - - ParameterDeclarationAST *ast = CreateNode<ParameterDeclarationAST>(_M_pool); - ast->type_specifier = spec; - ast->declarator = decl; - ast->expression = expr; - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - - return true; -} - -bool Parser::parse_Attribute__() -{ - token_stream.nextToken(); - - ADVANCE('(', "("); - - ExpressionAST *expr = 0; - parseExpression(expr); - - if (token_stream.lookAhead() != ')') { - reportError(QLatin1String("')' expected")); - return false; - } else { - token_stream.nextToken(); - } - return true; -} - -QString Parser::tokenText(AST *ast) const -{ - if (!ast) - return QString(); - - int start_token = ast->start_token; - int end_token = ast->end_token; - - Token const &tk = token_stream.token(start_token); - Token const &end_tk = token_stream.token(end_token); - - return QString::fromLatin1(&tk.text[tk.position], - (int)(end_tk.position - tk.position)).trimmed(); -} - -bool Parser::parseForwardDeclarationSpecifier(TypeSpecifierAST *&node) -{ - std::size_t start = token_stream.cursor(); - - int kind = token_stream.lookAhead(); - if (kind != Token_class && kind != Token_struct && kind != Token_union) - return false; - - std::size_t class_key = token_stream.cursor(); - token_stream.nextToken(); - - NameAST *name = 0; - if (!parseName(name, false)) { - token_stream.rewind((int) start); - return false; - } - - BaseClauseAST *bases = 0; - if (token_stream.lookAhead() == ':') { - if (!parseBaseClause(bases)) { - token_stream.rewind((int) start); - return false; - } - } - - if (token_stream.lookAhead() != ';') { - token_stream.rewind((int) start); - return false; - } - - ForwardDeclarationSpecifierAST *ast = CreateNode<ForwardDeclarationSpecifierAST>(_M_pool); - ast->class_key = class_key; - ast->name = name; - ast->base_clause = bases; - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - - return true; -} - -bool Parser::parseClassSpecifier(TypeSpecifierAST *&node) -{ - std::size_t start = token_stream.cursor(); - - int kind = token_stream.lookAhead(); - if (kind != Token_class && kind != Token_struct && kind != Token_union) - return false; - - std::size_t class_key = token_stream.cursor(); - token_stream.nextToken(); - - WinDeclSpecAST *winDeclSpec = 0; - parseWinDeclSpec(winDeclSpec); - - if (token_stream.lookAhead() == Token___attribute__) - parse_Attribute__(); - - while (token_stream.lookAhead() == Token_identifier - && token_stream.lookAhead(1) == Token_identifier) - token_stream.nextToken(); - - NameAST *name = 0; - parseName(name, true); - - BaseClauseAST *bases = 0; - - if (token_stream.lookAhead() == ':') { - if (!parseBaseClause(bases)) - skipUntil('{'); - } - - if (token_stream.lookAhead() != '{') { - - token_stream.rewind((int) start); - return false; - } - - ADVANCE('{', "{"); - - ClassSpecifierAST *ast = CreateNode<ClassSpecifierAST>(_M_pool); - ast->win_decl_specifiers = winDeclSpec; - ast->class_key = class_key; - ast->name = name; - ast->base_clause = bases; - - while (token_stream.lookAhead()) { - if (token_stream.lookAhead() == '}') - break; - - std::size_t startDecl = token_stream.cursor(); - - DeclarationAST *memSpec = 0; - if (!parseMemberSpecification(memSpec)) { - if (startDecl == token_stream.cursor()) - token_stream.nextToken(); // skip at least one token - skipUntilDeclaration(); - } else - ast->member_specs = snoc(ast->member_specs, memSpec, _M_pool); - } - - ADVANCE_NR('}', "}"); - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - - return true; -} - -bool Parser::parseAccessSpecifier(DeclarationAST *&node) -{ - std::size_t start = token_stream.cursor(); - - const ListNode<std::size_t> *specs = 0; - - bool done = false; - while (!done) { - switch (token_stream.lookAhead()) { - case Token_signals: - case Token_slots: - case Token_k_dcop: - case Token_k_dcop_signals: - case Token_public: - case Token_protected: - case Token_private: - specs = snoc(specs, token_stream.cursor(), _M_pool); - token_stream.nextToken(); - break; - - default: - done = true; - break; - } - } - - if (!specs) - return false; - - ADVANCE(':', ":"); - - AccessSpecifierAST *ast = CreateNode<AccessSpecifierAST>(_M_pool); - ast->specs = specs; - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - - return true; -} - -bool Parser::parseMemberSpecification(DeclarationAST *&node) -{ - std::size_t start = token_stream.cursor(); - - if (token_stream.lookAhead() == ';') { - token_stream.nextToken(); - return true; - } else if (token_stream.lookAhead() == Token_Q_OBJECT - || token_stream.lookAhead() == Token_K_DCOP) { - token_stream.nextToken(); - return true; - } else if (parseTypedef(node)) { - return true; - } else if (parseUsing(node)) { - return true; - } else if (parseTemplateDeclaration(node)) { - return true; - } else if (parseAccessSpecifier(node)) { - return true; - } else if (parseQ_PROPERTY(node)) { - return true; - } else if (parseQ_ENUMS(node)) { - return true; - } - - token_stream.rewind((int) start); - - const ListNode<std::size_t> *cv = 0; - parseCvQualify(cv); - - const ListNode<std::size_t> *storageSpec = 0; - parseStorageClassSpecifier(storageSpec); - - parseCvQualify(cv); - - TypeSpecifierAST *spec = 0; - if (parseEnumSpecifier(spec) || parseClassSpecifier(spec)) { - parseCvQualify(cv); - spec->cv = cv; - - const ListNode<InitDeclaratorAST*> *declarators = 0; - parseInitDeclaratorList(declarators); - ADVANCE(';', ";"); - - SimpleDeclarationAST *ast = CreateNode<SimpleDeclarationAST>(_M_pool); - ast->type_specifier = spec; - ast->init_declarators = declarators; - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - - return true; - } - - token_stream.rewind((int) start); - return parseDeclarationInternal(node); -} - -bool Parser::parseCtorInitializer(CtorInitializerAST *&node) -{ - std::size_t start = token_stream.cursor(); - - CHECK(':'); - - CtorInitializerAST *ast = CreateNode<CtorInitializerAST>(_M_pool); - ast->colon = start; - - if (!parseMemInitializerList(ast->member_initializers)) - reportError(QLatin1String("Member initializers expected")); - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - - return true; -} - -bool Parser::parseElaboratedTypeSpecifier(TypeSpecifierAST *&node) -{ - std::size_t start = token_stream.cursor(); - - int tk = token_stream.lookAhead(); - if (tk == Token_class - || tk == Token_struct - || tk == Token_union - || tk == Token_enum - || tk == Token_typename) { - std::size_t type = token_stream.cursor(); - token_stream.nextToken(); - - NameAST *name = 0; - if (parseName(name, true)) { - ElaboratedTypeSpecifierAST *ast - = CreateNode<ElaboratedTypeSpecifierAST>(_M_pool); - - ast->type = type; - ast->name = name; - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - - return true; - } - } - - token_stream.rewind((int) start); - return false; -} - -bool Parser::parseNoExcept() -{ - // right now we only accept 'noexcept' with no conditional - CHECK(Token_noexcept); - - return true; -} - -bool Parser::parseExceptionSpecification(ExceptionSpecificationAST *&node) -{ - std::size_t start = token_stream.cursor(); - - CHECK(Token_throw); - ADVANCE('(', "("); - - ExceptionSpecificationAST *ast = CreateNode<ExceptionSpecificationAST>(_M_pool); - - if (token_stream.lookAhead() == Token_ellipsis) { - ast->ellipsis = token_stream.cursor(); - token_stream.nextToken(); - } else { - parseTypeIdList(ast->type_ids); - } - - ADVANCE(')', ")"); - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - - return true; -} - -bool Parser::parseEnumerator(EnumeratorAST *&node) -{ - std::size_t start = token_stream.cursor(); - - CHECK(Token_identifier); - std::size_t id = token_stream.cursor() - 1; - - EnumeratorAST *ast = CreateNode<EnumeratorAST>(_M_pool); - ast->id = id; - - if (token_stream.lookAhead() == '=') { - token_stream.nextToken(); - - if (!parseConstantExpression(ast->expression)) - reportError(QLatin1String("Constant expression expected")); - } - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - - return true; -} - -bool Parser::parseInitDeclarator(InitDeclaratorAST *&node) -{ - std::size_t start = token_stream.cursor(); - - DeclaratorAST *decl = 0; - if (!parseDeclarator(decl)) - return false; - - if (token_stream.lookAhead(0) == Token_asm) { - token_stream.nextToken(); - skip('(', ')'); - token_stream.nextToken(); - } - - InitializerAST *init = 0; - parseInitializer(init); - - InitDeclaratorAST *ast = CreateNode<InitDeclaratorAST>(_M_pool); - ast->declarator = decl; - ast->initializer = init; - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - - return true; -} - -bool Parser::parseBaseClause(BaseClauseAST *&node) -{ - std::size_t start = token_stream.cursor(); - - CHECK(':'); - - BaseSpecifierAST *baseSpec = 0; - if (!parseBaseSpecifier(baseSpec)) - return false; - - BaseClauseAST *ast = CreateNode<BaseClauseAST>(_M_pool); - ast->base_specifiers = snoc(ast->base_specifiers, baseSpec, _M_pool); - - while (token_stream.lookAhead() == ',') { - token_stream.nextToken(); - - if (!parseBaseSpecifier(baseSpec)) { - reportError(QLatin1String("Base class specifier expected")); - break; - } - ast->base_specifiers = snoc(ast->base_specifiers, baseSpec, _M_pool); - } - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - - return true; -} - -bool Parser::parseInitializer(InitializerAST *&node) -{ - std::size_t start = token_stream.cursor(); - - int tk = token_stream.lookAhead(); - if (tk != '=' && tk != '(') - return false; - - InitializerAST *ast = CreateNode<InitializerAST>(_M_pool); - - if (tk == '=') { - token_stream.nextToken(); - - if (!parseInitializerClause(ast->initializer_clause)) - reportError(QLatin1String("Initializer clause expected")); - - } else if (tk == '(') { - token_stream.nextToken(); - parseCommaExpression(ast->expression); - CHECK(')'); - } - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - - return true; -} - -bool Parser::parseMemInitializerList(const ListNode<MemInitializerAST*> *&node) -{ - MemInitializerAST *init = 0; - - if (!parseMemInitializer(init)) - return false; - - node = snoc(node, init, _M_pool); - - while (token_stream.lookAhead() == ',') { - token_stream.nextToken(); - - if (!parseMemInitializer(init)) - break; - - node = snoc(node, init, _M_pool); - } - - return true; -} - -bool Parser::parseMemInitializer(MemInitializerAST *&node) -{ - std::size_t start = token_stream.cursor(); - - NameAST *initId = 0; - if (!parseName(initId, true)) { - reportError(QLatin1String("Identifier expected")); - return false; - } - - ADVANCE('(', "("); - ExpressionAST *expr = 0; - parseCommaExpression(expr); - ADVANCE(')', ")"); - - MemInitializerAST *ast = CreateNode<MemInitializerAST>(_M_pool); - ast->initializer_id = initId; - ast->expression = expr; - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - - return true; -} - -bool Parser::parseTypeIdList(const ListNode<TypeIdAST*> *&node) -{ - TypeIdAST *typeId = 0; - if (!parseTypeId(typeId)) - return false; - - node = snoc(node, typeId, _M_pool); - - while (token_stream.lookAhead() == ',') { - token_stream.nextToken(); - if (parseTypeId(typeId)) { - node = snoc(node, typeId, _M_pool); - } else { - reportError(QLatin1String("Type id expected")); - break; - } - } - - return true; -} - -bool Parser::parseBaseSpecifier(BaseSpecifierAST *&node) -{ - std::size_t start = token_stream.cursor(); - - BaseSpecifierAST *ast = CreateNode<BaseSpecifierAST>(_M_pool); - - if (token_stream.lookAhead() == Token_virtual) { - ast->virt = token_stream.cursor(); - token_stream.nextToken(); - - int tk = token_stream.lookAhead(); - if (tk == Token_public || tk == Token_protected - || tk == Token_private) { - ast->access_specifier = token_stream.cursor(); - token_stream.nextToken(); - } - } else { - int tk = token_stream.lookAhead(); - if (tk == Token_public || tk == Token_protected - || tk == Token_private) { - ast->access_specifier = token_stream.cursor(); - token_stream.nextToken(); - } - - if (token_stream.lookAhead() == Token_virtual) { - ast->virt = token_stream.cursor(); - token_stream.nextToken(); - } - } - - if (!parseName(ast->name, true)) - reportError(QLatin1String("Class name expected")); - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - - return true; -} - -bool Parser::parseInitializerClause(InitializerClauseAST *&node) -{ - std::size_t start = token_stream.cursor(); - - InitializerClauseAST *ast = CreateNode<InitializerClauseAST>(_M_pool); - - if (token_stream.lookAhead() == '{') { -#if defined(__GNUC__) -#warning "implement me" -#endif - if (skip('{', '}')) - token_stream.nextToken(); - else - reportError(QLatin1String("} missing")); - } else { - if (!parseAssignmentExpression(ast->expression)) - reportError(QLatin1String("Expression expected")); - } - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - - return true; -} - -bool Parser::parsePtrToMember(PtrToMemberAST *&node) -{ -#if defined(__GNUC__) -#warning "implemente me (AST)" -#endif - - std::size_t start = token_stream.cursor(); - - if (token_stream.lookAhead() == Token_scope) { - token_stream.nextToken(); - } - - UnqualifiedNameAST *name = 0; - while (token_stream.lookAhead() == Token_identifier) { - if (!parseUnqualifiedName(name)) - break; - - if (token_stream.lookAhead() == Token_scope - && token_stream.lookAhead(1) == '*') { - token_stream.nextToken(); - token_stream.nextToken(); - - PtrToMemberAST *ast = CreateNode<PtrToMemberAST>(_M_pool); - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - - return true; - } - - if (token_stream.lookAhead() == Token_scope) - token_stream.nextToken(); - } - - token_stream.rewind((int) start); - return false; -} - -bool Parser::parseUnqualifiedName(UnqualifiedNameAST *&node, - bool parseTemplateId) -{ - std::size_t start = token_stream.cursor(); - - std::size_t tilde = 0; - std::size_t id = 0; - OperatorFunctionIdAST *operator_id = 0; - - if (token_stream.lookAhead() == Token_identifier) { - id = token_stream.cursor(); - token_stream.nextToken(); - } else if (token_stream.lookAhead() == '~' - && token_stream.lookAhead(1) == Token_identifier) { - tilde = token_stream.cursor(); - token_stream.nextToken(); // skip ~ - - id = token_stream.cursor(); - token_stream.nextToken(); // skip classname - } else if (token_stream.lookAhead() == Token_operator) { - if (!parseOperatorFunctionId(operator_id)) - return false; - } else { - return false; - } - - UnqualifiedNameAST *ast = CreateNode<UnqualifiedNameAST>(_M_pool); - ast->tilde = tilde; - ast->id = id; - ast->operator_id = operator_id; - - if (parseTemplateId && !tilde) { - std::size_t index = token_stream.cursor(); - - if (token_stream.lookAhead() == '<') { - token_stream.nextToken(); - - // optional template arguments - parseTemplateArgumentList(ast->template_arguments); - - if (token_stream.lookAhead() == '>') { - token_stream.nextToken(); - } else { - ast->template_arguments = 0; - token_stream.rewind((int) index); - } - } - } - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - - return true; -} - -bool Parser::parseStringLiteral(StringLiteralAST *&node) -{ - std::size_t start = token_stream.cursor(); - - if (token_stream.lookAhead() != Token_string_literal) - return false; - - StringLiteralAST *ast = CreateNode<StringLiteralAST>(_M_pool); - - while (token_stream.lookAhead() == Token_string_literal) { - ast->literals = snoc(ast->literals, token_stream.cursor(), _M_pool); - token_stream.nextToken(); - } - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - - return true; -} - -bool Parser::parseExpressionStatement(StatementAST *&node) -{ - std::size_t start = token_stream.cursor(); - - ExpressionAST *expr = 0; - parseCommaExpression(expr); - - ADVANCE(';', ";"); - - ExpressionStatementAST *ast = CreateNode<ExpressionStatementAST>(_M_pool); - ast->expression = expr; - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - - return true; -} - -bool Parser::parseStatement(StatementAST *&node) -{ - std::size_t start = token_stream.cursor(); - - switch (token_stream.lookAhead()) { - case Token_while: - return parseWhileStatement(node); - - case Token_do: - return parseDoStatement(node); - - case Token_for: - return parseForStatement(node); - - case Token_if: - return parseIfStatement(node); - - case Token_switch: - return parseSwitchStatement(node); - - case Token_try: - return parseTryBlockStatement(node); - - case Token_case: - case Token_default: - return parseLabeledStatement(node); - - case Token_break: - case Token_continue: -#if defined(__GNUC__) -#warning "implement me" -#endif - token_stream.nextToken(); - ADVANCE(';', ";"); - return true; - - case Token_goto: -#if defined(__GNUC__) -#warning "implement me" -#endif - token_stream.nextToken(); - ADVANCE(Token_identifier, "identifier"); - ADVANCE(';', ";"); - return true; - - case Token_return: { - token_stream.nextToken(); - ExpressionAST *expr = 0; - parseCommaExpression(expr); - - ADVANCE(';', ";"); - - ReturnStatementAST *ast = CreateNode<ReturnStatementAST>(_M_pool); - ast->expression = expr; - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - } - return true; - - case '{': - return parseCompoundStatement(node); - - case Token_identifier: - if (parseLabeledStatement(node)) - return true; - break; - } - - return parseExpressionOrDeclarationStatement(node); -} - -bool Parser::parseExpressionOrDeclarationStatement(StatementAST *&node) -{ - bool blocked = block_errors(true); - - std::size_t start = token_stream.cursor(); - - StatementAST *decl_ast = 0; - bool maybe_amb = parseDeclarationStatement(decl_ast); - maybe_amb &= token_stream.kind(token_stream.cursor() - 1) == ';'; - - std::size_t end = token_stream.cursor(); - - token_stream.rewind((int) start); - StatementAST *expr_ast = 0; - maybe_amb &= parseExpressionStatement(expr_ast); - maybe_amb &= token_stream.kind(token_stream.cursor() - 1) == ';'; - - if (maybe_amb) { - Q_ASSERT(decl_ast && expr_ast); - ExpressionOrDeclarationStatementAST *ast = - CreateNode<ExpressionOrDeclarationStatementAST>(_M_pool); - ast->declaration = decl_ast; - ast->expression = expr_ast; - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - } else { - token_stream.rewind((int) std::max(end, token_stream.cursor())); - - node = decl_ast; - if (!node) - node = expr_ast; - } - - block_errors(blocked); - - if (!node) - syntaxError(); - - return node != 0; -} - -bool Parser::parseCondition(ConditionAST *&node, bool initRequired) -{ - std::size_t start = token_stream.cursor(); - - ConditionAST *ast = CreateNode<ConditionAST>(_M_pool); - TypeSpecifierAST *spec = 0; - - if (parseTypeSpecifier(spec)) { - ast->type_specifier = spec; - - std::size_t declarator_start = token_stream.cursor(); - - DeclaratorAST *decl = 0; - if (!parseDeclarator(decl)) { - token_stream.rewind((int) declarator_start); - if (!initRequired && !parseAbstractDeclarator(decl)) - decl = 0; - } - - if (decl && (!initRequired || token_stream.lookAhead() == '=')) { - ast->declarator = decl; - - if (token_stream.lookAhead() == '=') { - token_stream.nextToken(); - - parseExpression(ast->expression); - } - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - - return true; - } - } - - token_stream.rewind((int) start); - - if (!parseCommaExpression(ast->expression)) - return false; - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - - return true; -} - - -bool Parser::parseWhileStatement(StatementAST *&node) -{ - std::size_t start = token_stream.cursor(); - - ADVANCE(Token_while, "while"); - ADVANCE('(' , "("); - - ConditionAST *cond = 0; - if (!parseCondition(cond)) { - reportError(QLatin1String("condition expected")); - return false; - } - ADVANCE(')', ")"); - - StatementAST *body = 0; - if (!parseStatement(body)) { - reportError(QLatin1String("statement expected")); - return false; - } - - WhileStatementAST *ast = CreateNode<WhileStatementAST>(_M_pool); - ast->condition = cond; - ast->statement = body; - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - - return true; -} - -bool Parser::parseDoStatement(StatementAST *&node) -{ - std::size_t start = token_stream.cursor(); - - ADVANCE(Token_do, "do"); - - StatementAST *body = 0; - if (!parseStatement(body)) { - reportError(QLatin1String("statement expected")); - //return false; - } - - ADVANCE_NR(Token_while, "while"); - ADVANCE_NR('(' , "("); - - ExpressionAST *expr = 0; - if (!parseCommaExpression(expr)) { - reportError(QLatin1String("expression expected")); - //return false; - } - - ADVANCE_NR(')', ")"); - ADVANCE_NR(';', ";"); - - DoStatementAST *ast = CreateNode<DoStatementAST>(_M_pool); - ast->statement = body; - ast->expression = expr; - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - - return true; -} - -bool Parser::parseForStatement(StatementAST *&node) -{ - std::size_t start = token_stream.cursor(); - - ADVANCE(Token_for, "for"); - ADVANCE('(', "("); - - StatementAST *init = 0; - if (!parseForInitStatement(init)) { - reportError(QLatin1String("for initialization expected")); - return false; - } - - ConditionAST *cond = 0; - parseCondition(cond); - ADVANCE(';', ";"); - - ExpressionAST *expr = 0; - parseCommaExpression(expr); - ADVANCE(')', ")"); - - StatementAST *body = 0; - if (!parseStatement(body)) - return false; - - ForStatementAST *ast = CreateNode<ForStatementAST>(_M_pool); - ast->init_statement = init; - ast->condition = cond; - ast->expression = expr; - ast->statement = body; - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - - return true; -} - -bool Parser::parseForInitStatement(StatementAST *&node) -{ - if (parseDeclarationStatement(node)) - return true; - - return parseExpressionStatement(node); -} - -bool Parser::parseCompoundStatement(StatementAST *&node) -{ - std::size_t start = token_stream.cursor(); - - CHECK('{'); - - CompoundStatementAST *ast = CreateNode<CompoundStatementAST>(_M_pool); - - while (token_stream.lookAhead()) { - if (token_stream.lookAhead() == '}') - break; - - std::size_t startStmt = token_stream.cursor(); - - StatementAST *stmt = 0; - if (!parseStatement(stmt)) { - if (startStmt == token_stream.cursor()) - token_stream.nextToken(); - - skipUntilStatement(); - } else { - ast->statements = snoc(ast->statements, stmt, _M_pool); - } - } - - ADVANCE_NR('}', "}"); - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - - return true; -} - -bool Parser::parseIfStatement(StatementAST *&node) -{ - std::size_t start = token_stream.cursor(); - - ADVANCE(Token_if, "if"); - - ADVANCE('(' , "("); - - IfStatementAST *ast = CreateNode<IfStatementAST>(_M_pool); - - ConditionAST *cond = 0; - if (!parseCondition(cond)) { - reportError(QLatin1String("condition expected")); - return false; - } - ADVANCE(')', ")"); - - StatementAST *stmt = 0; - if (!parseStatement(stmt)) { - reportError(QLatin1String("statement expected")); - return false; - } - - ast->condition = cond; - ast->statement = stmt; - - if (token_stream.lookAhead() == Token_else) { - token_stream.nextToken(); - - if (!parseStatement(ast->else_statement)) { - reportError(QLatin1String("statement expected")); - return false; - } - } - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - - return true; -} - -bool Parser::parseSwitchStatement(StatementAST *&node) -{ - std::size_t start = token_stream.cursor(); - ADVANCE(Token_switch, "switch"); - - ADVANCE('(' , "("); - - ConditionAST *cond = 0; - if (!parseCondition(cond)) { - reportError(QLatin1String("condition expected")); - return false; - } - ADVANCE(')', ")"); - - StatementAST *stmt = 0; - if (!parseCompoundStatement(stmt)) { - syntaxError(); - return false; - } - - SwitchStatementAST *ast = CreateNode<SwitchStatementAST>(_M_pool); - ast->condition = cond; - ast->statement = stmt; - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - - return true; -} - -bool Parser::parseLabeledStatement(StatementAST *&node) -{ - switch (token_stream.lookAhead()) { - case Token_identifier: - case Token_default: - if (token_stream.lookAhead(1) == ':') { - token_stream.nextToken(); - token_stream.nextToken(); - - StatementAST *stmt = 0; - if (parseStatement(stmt)) { - node = stmt; - return true; - } - } - break; - - case Token_case: { - token_stream.nextToken(); - ExpressionAST *expr = 0; - if (!parseConstantExpression(expr)) { - reportError(QLatin1String("expression expected")); - } else if (token_stream.lookAhead() == Token_ellipsis) { - token_stream.nextToken(); - - ExpressionAST *expr2 = 0; - if (!parseConstantExpression(expr2)) - reportError(QLatin1String("expression expected")); - } - ADVANCE(':', ":"); - - StatementAST *stmt = 0; - if (parseStatement(stmt)) { - node = stmt; - return true; - } - } - break; - - } - - return false; -} - -bool Parser::parseBlockDeclaration(DeclarationAST *&node) -{ - switch (token_stream.lookAhead()) { - case Token_typedef: - return parseTypedef(node); - case Token_using: - return parseUsing(node); - case Token_asm: - return parseAsmDefinition(node); - case Token_namespace: - return parseNamespaceAliasDefinition(node); - } - - std::size_t start = token_stream.cursor(); - - const ListNode<std::size_t> *cv = 0; - parseCvQualify(cv); - - const ListNode<std::size_t> *storageSpec = 0; - parseStorageClassSpecifier(storageSpec); - - parseCvQualify(cv); - - TypeSpecifierAST *spec = 0; - if (!parseTypeSpecifierOrClassSpec(spec)) { // replace with simpleTypeSpecifier?!?! - token_stream.rewind((int) start); - return false; - } - - parseCvQualify(cv); - spec->cv = cv; - - const ListNode<InitDeclaratorAST*> *declarators = 0; - parseInitDeclaratorList(declarators); - - if (token_stream.lookAhead() != ';') { - token_stream.rewind((int) start); - return false; - } - token_stream.nextToken(); - - SimpleDeclarationAST *ast = CreateNode<SimpleDeclarationAST>(_M_pool); - ast->type_specifier = spec; - ast->init_declarators = declarators; - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - - return true; -} - -bool Parser::parseNamespaceAliasDefinition(DeclarationAST *&node) -{ - std::size_t start = token_stream.cursor(); - - CHECK(Token_namespace); - - NamespaceAliasDefinitionAST *ast - = CreateNode<NamespaceAliasDefinitionAST>(_M_pool); - - ADVANCE(Token_identifier, "identifier"); - ast->namespace_name = token_stream.cursor() - 1; - - ADVANCE('=', "="); - - if (!parseName(ast->alias_name)) - reportError(QLatin1String("Namespace name expected")); - - ADVANCE(';', ";"); - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - - return true; -} - -bool Parser::parseDeclarationStatement(StatementAST *&node) -{ - std::size_t start = token_stream.cursor(); - - DeclarationAST *decl = 0; - if (!parseBlockDeclaration(decl)) - return false; - - DeclarationStatementAST *ast = CreateNode<DeclarationStatementAST>(_M_pool); - ast->declaration = decl; - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - - return true; -} - -bool Parser::parseDeclarationInternal(DeclarationAST *&node) -{ - std::size_t start = token_stream.cursor(); - - // that is for the case '__declspec(dllexport) int ...' or - // '__declspec(dllexport) inline int ...', etc. - WinDeclSpecAST *winDeclSpec = 0; - parseWinDeclSpec(winDeclSpec); - - const ListNode<std::size_t> *funSpec = 0; - bool hasFunSpec = parseFunctionSpecifier(funSpec); - - const ListNode<std::size_t> *cv = 0; - parseCvQualify(cv); - - const ListNode<std::size_t> *storageSpec = 0; - bool hasStorageSpec = parseStorageClassSpecifier(storageSpec); - - if (hasStorageSpec && !hasFunSpec) - hasFunSpec = parseFunctionSpecifier(funSpec); - - // that is for the case 'friend __declspec(dllexport) ....' - parseWinDeclSpec(winDeclSpec); - - if (!cv) - parseCvQualify(cv); - - int index = (int) token_stream.cursor(); - NameAST *name = 0; - if (parseName(name, true) && token_stream.lookAhead() == '(') { - // no type specifier, maybe a constructor or a cast operator?? - - token_stream.rewind((int) index); - - InitDeclaratorAST *declarator = 0; - if (parseInitDeclarator(declarator)) { - switch (token_stream.lookAhead()) { - case ';': { - token_stream.nextToken(); - - SimpleDeclarationAST *ast - = CreateNode<SimpleDeclarationAST>(_M_pool); - - ast->storage_specifiers = storageSpec; - ast->function_specifiers = funSpec; - ast->init_declarators = snoc(ast->init_declarators, - declarator, _M_pool); - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - } - return true; - - case ':': { - CtorInitializerAST *ctorInit = 0; - StatementAST *funBody = 0; - - if (parseCtorInitializer(ctorInit) - && parseFunctionBody(funBody)) { - FunctionDefinitionAST *ast - = CreateNode<FunctionDefinitionAST>(_M_pool); - - ast->storage_specifiers = storageSpec; - ast->function_specifiers = funSpec; - ast->init_declarator = declarator; - ast->function_body = funBody; - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - - return true; - } - } - break; - - case '{': { - StatementAST *funBody = 0; - if (parseFunctionBody(funBody)) { - FunctionDefinitionAST *ast - = CreateNode<FunctionDefinitionAST>(_M_pool); - - ast->storage_specifiers = storageSpec; - ast->function_specifiers = funSpec; - ast->init_declarator = declarator; - ast->function_body = funBody; - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - - return true; - } - } - break; - - case '(': - case '[': - // ops!! it seems a declarator - goto start_decl; - break; - } - - } - } - -start_decl: - token_stream.rewind((int) index); - - if (token_stream.lookAhead() == Token_const - && token_stream.lookAhead(1) == Token_identifier - && token_stream.lookAhead(2) == '=') { - // constant definition - token_stream.nextToken(); // skip const - - const ListNode<InitDeclaratorAST*> *declarators = 0; - if (!parseInitDeclaratorList(declarators)) { - syntaxError(); - return false; - } - - ADVANCE(';', ";"); - -#if defined(__GNUC__) -#warning "mark the ast as constant" -#endif - SimpleDeclarationAST *ast = CreateNode<SimpleDeclarationAST>(_M_pool); - ast->init_declarators = declarators; - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - - return true; - } - - TypeSpecifierAST *spec = 0; - if (parseTypeSpecifier(spec)) { - Q_ASSERT(spec); - - if (!hasFunSpec) - parseFunctionSpecifier(funSpec); // e.g. "void inline" - - spec->cv = cv; - - const ListNode<InitDeclaratorAST*> *declarators = 0; - InitDeclaratorAST *decl = 0; - int startDeclarator = (int) token_stream.cursor(); - bool maybeFunctionDefinition = false; - - if (token_stream.lookAhead() != ';') { - if (parseInitDeclarator(decl) && token_stream.lookAhead() == '{') { - // function definition - maybeFunctionDefinition = true; - } else { - token_stream.rewind((int) startDeclarator); - if (!parseInitDeclaratorList(declarators)) { - syntaxError(); - return false; - } - } - } - - switch (token_stream.lookAhead()) { - case ';': { - token_stream.nextToken(); - SimpleDeclarationAST *ast - = CreateNode<SimpleDeclarationAST>(_M_pool); - - ast->storage_specifiers = storageSpec; - ast->function_specifiers = funSpec; - ast->type_specifier = spec; - ast->win_decl_specifiers = winDeclSpec; - ast->init_declarators = declarators; - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - } - return true; - - case '{': { - if (!maybeFunctionDefinition) { - syntaxError(); - return false; - } - - StatementAST *funBody = 0; - if (parseFunctionBody(funBody)) { - FunctionDefinitionAST *ast - = CreateNode<FunctionDefinitionAST>(_M_pool); - - ast->win_decl_specifiers = winDeclSpec; - ast->storage_specifiers = storageSpec; - ast->function_specifiers = funSpec; - ast->type_specifier = spec; - ast->init_declarator = decl; - ast->function_body = funBody; - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - - return true; - } - } - break; - } // end switch - } - - syntaxError(); - return false; -} - -bool Parser::skipFunctionBody(StatementAST *&) -{ -#if defined(__GNUC__) -#warning "Parser::skipFunctionBody() -- implement me" -#endif - Q_ASSERT(0); // ### not implemented - return 0; -} - -bool Parser::parseFunctionBody(StatementAST *&node) -{ - if (control->skipFunctionBody()) - return skipFunctionBody(node); - - return parseCompoundStatement(node); -} - -bool Parser::parseTypeSpecifierOrClassSpec(TypeSpecifierAST *&node) -{ - if (parseClassSpecifier(node)) - return true; - else if (parseEnumSpecifier(node)) - return true; - else if (parseTypeSpecifier(node)) - return true; - - return false; -} - -bool Parser::parseTryBlockStatement(StatementAST *&node) -{ -#if defined(__GNUC__) -#warning "implement me" -#endif - CHECK(Token_try); - - StatementAST *stmt = 0; - if (!parseCompoundStatement(stmt)) { - syntaxError(); - return false; - } - - if (token_stream.lookAhead() != Token_catch) { - reportError(QLatin1String("catch expected")); - return false; - } - - while (token_stream.lookAhead() == Token_catch) { - token_stream.nextToken(); - ADVANCE('(', "("); - ConditionAST *cond = 0; - if (token_stream.lookAhead() == Token_ellipsis) { - token_stream.nextToken(); - } else if (!parseCondition(cond, false)) { - reportError(QLatin1String("condition expected")); - return false; - } - ADVANCE(')', ")"); - - StatementAST *body = 0; - if (!parseCompoundStatement(body)) { - syntaxError(); - return false; - } - } - - node = stmt; - return true; -} - -bool Parser::parsePrimaryExpression(ExpressionAST *&node) -{ - std::size_t start = token_stream.cursor(); - - PrimaryExpressionAST *ast = CreateNode<PrimaryExpressionAST>(_M_pool); - - switch (token_stream.lookAhead()) { - case Token_string_literal: - parseStringLiteral(ast->literal); - break; - - case Token_number_literal: - case Token_char_literal: - case Token_true: - case Token_false: - case Token_this: - ast->token = token_stream.cursor(); - token_stream.nextToken(); - break; - - case '(': - token_stream.nextToken(); - - if (token_stream.lookAhead() == '{') { - if (!parseCompoundStatement(ast->expression_statement)) - return false; - } else { - if (!parseExpression(ast->sub_expression)) - return false; - } - - CHECK(')'); - break; - - default: - if (!parseName(ast->name)) - return false; - - break; - } - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - - return true; -} - - -/* - postfix-expression-internal: - [ expression ] - ( expression-list [opt] ) - (.|->) template [opt] id-expression - (.|->) pseudo-destructor-name - ++ - -- -*/ -bool Parser::parsePostfixExpressionInternal(ExpressionAST *&node) -{ - std::size_t start = token_stream.cursor(); - - switch (token_stream.lookAhead()) { - case '[': { - token_stream.nextToken(); - ExpressionAST *expr = 0; - parseExpression(expr); - CHECK(']'); - - SubscriptExpressionAST *ast - = CreateNode<SubscriptExpressionAST>(_M_pool); - - ast->subscript = expr; - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - } - return true; - - case '(': { - token_stream.nextToken(); - ExpressionAST *expr = 0; - parseExpression(expr); - CHECK(')'); - - FunctionCallAST *ast = CreateNode<FunctionCallAST>(_M_pool); - ast->arguments = expr; - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - } - return true; - - case '.': - case Token_arrow: { - std::size_t op = token_stream.cursor(); - token_stream.nextToken(); - - std::size_t templ = 0; - if (token_stream.lookAhead() == Token_template) { - templ = token_stream.cursor(); - token_stream.nextToken(); - } - - int saved = int(token_stream.cursor()); - NameAST *name = 0; - - if (parseName(name, true) && name->unqualified_name - && name->unqualified_name->template_arguments - && token_stream.lookAhead() == '(') { - // a template method call - // ### reverse the logic - } else { - token_stream.rewind(saved); - name = 0; - - if (!parseName(name, templ != 0)) - return false; - } - - ClassMemberAccessAST *ast = CreateNode<ClassMemberAccessAST>(_M_pool); - ast->op = op; - ast->name = name; - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - } - return true; - - case Token_incr: - case Token_decr: { - std::size_t op = token_stream.cursor(); - token_stream.nextToken(); - - IncrDecrExpressionAST *ast = CreateNode<IncrDecrExpressionAST>(_M_pool); - ast->op = op; - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - } - return true; - - default: - return false; - } -} - -/* - postfix-expression: - simple-type-specifier ( expression-list [opt] ) - primary-expression postfix-expression-internal* -*/ -bool Parser::parsePostfixExpression(ExpressionAST *&node) -{ - std::size_t start = token_stream.cursor(); - - switch (token_stream.lookAhead()) { - case Token_dynamic_cast: - case Token_static_cast: - case Token_reinterpret_cast: - case Token_const_cast: { - std::size_t castOp = token_stream.cursor(); - token_stream.nextToken(); - - CHECK('<'); - TypeIdAST *typeId = 0; - parseTypeId(typeId); - CHECK('>'); - - CHECK('('); - ExpressionAST *expr = 0; - parseCommaExpression(expr); - CHECK(')'); - - CppCastExpressionAST *ast = CreateNode<CppCastExpressionAST>(_M_pool); - ast->op = castOp; - ast->type_id = typeId; - ast->expression = expr; - - ExpressionAST *e = 0; - while (parsePostfixExpressionInternal(e)) - ast->sub_expressions = snoc(ast->sub_expressions, e, _M_pool); - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - } - return true; - - case Token_typename: { - std::size_t token = token_stream.cursor(); - token_stream.nextToken(); - - NameAST* name = 0; - if (!parseName(name, true)) - return false; - - CHECK('('); - ExpressionAST *expr = 0; - parseCommaExpression(expr); - CHECK(')'); - - TypeIdentificationAST *ast = CreateNode<TypeIdentificationAST>(_M_pool); - ast->typename_token = token; - ast->name = name; - ast->expression = expr; - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - } - return true; - - case Token_typeid: { - token_stream.nextToken(); - - CHECK('('); - TypeIdAST *typeId = 0; - parseTypeId(typeId); - CHECK(')'); - - TypeIdentificationAST *ast = CreateNode<TypeIdentificationAST>(_M_pool); - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - } - return true; - - default: - break; - } - - std::size_t saved_pos = token_stream.cursor(); - - TypeSpecifierAST *typeSpec = 0; - ExpressionAST *expr = 0; - - // let's try to parse a type - NameAST *name = 0; - if (parseName(name, true)) { - Q_ASSERT(name->unqualified_name); - - bool has_template_args = name->unqualified_name->template_arguments != 0; - - if (has_template_args && token_stream.lookAhead() == '(') { - ExpressionAST *cast_expr = 0; - if (parseCastExpression(cast_expr) - && cast_expr->kind == AST::Kind_CastExpression) { - token_stream.rewind((int) saved_pos); - parsePrimaryExpression(expr); - goto L_no_rewind; - } - } - } - - token_stream.rewind((int) saved_pos); - -L_no_rewind: - if (!expr && parseSimpleTypeSpecifier(typeSpec) - && token_stream.lookAhead() == '(') { - token_stream.nextToken(); // skip '(' - parseCommaExpression(expr); - CHECK(')'); - } else if (expr) { - typeSpec = 0; - } else { - typeSpec = 0; - token_stream.rewind((int) start); - - if (!parsePrimaryExpression(expr)) - return false; - } - - const ListNode<ExpressionAST*> *sub_expressions = 0; - ExpressionAST *sub_expression = 0; - - while (parsePostfixExpressionInternal(sub_expression)) - sub_expressions = snoc(sub_expressions, sub_expression, _M_pool); - - if (sub_expressions || !expr || (typeSpec && expr)) { - PostfixExpressionAST *ast = CreateNode<PostfixExpressionAST>(_M_pool); - ast->type_specifier = typeSpec; - ast->expression = expr; - ast->sub_expressions = sub_expressions; - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - } else - node = expr; - - return true; -} - -bool Parser::parseUnaryExpression(ExpressionAST *&node) -{ - std::size_t start = token_stream.cursor(); - - switch (token_stream.lookAhead()) { - case Token_incr: - case Token_decr: - case '*': - case '&': - case '+': - case '-': - case '!': - case '~': { - std::size_t op = token_stream.cursor(); - token_stream.nextToken(); - - ExpressionAST *expr = 0; - if (!parseCastExpression(expr)) - return false; - - UnaryExpressionAST *ast = CreateNode<UnaryExpressionAST>(_M_pool); - ast->op = op; - ast->expression = expr; - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - } - return true; - - case Token_sizeof: { - std::size_t sizeof_token = token_stream.cursor(); - token_stream.nextToken(); - - SizeofExpressionAST *ast = CreateNode<SizeofExpressionAST>(_M_pool); - ast->sizeof_token = sizeof_token; - - std::size_t index = token_stream.cursor(); - if (token_stream.lookAhead() == '(') { - token_stream.nextToken(); - if (parseTypeId(ast->type_id) && token_stream.lookAhead() == ')') { - token_stream.nextToken(); // skip ) - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - return true; - } - - ast->type_id = 0; - token_stream.rewind((int) index); - } - - if (!parseUnaryExpression(ast->expression)) - return false; - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - return true; - } - - default: - break; - } - - int token = token_stream.lookAhead(); - - if (token == Token_new - || (token == Token_scope && token_stream.lookAhead(1) == Token_new)) - return parseNewExpression(node); - - if (token == Token_delete - || (token == Token_scope && token_stream.lookAhead(1) == Token_delete)) - return parseDeleteExpression(node); - - return parsePostfixExpression(node); -} - -bool Parser::parseNewExpression(ExpressionAST *&node) -{ - std::size_t start = token_stream.cursor(); - - NewExpressionAST *ast = CreateNode<NewExpressionAST>(_M_pool); - - if (token_stream.lookAhead() == Token_scope - && token_stream.lookAhead(1) == Token_new) { - ast->scope_token = token_stream.cursor(); - token_stream.nextToken(); - } - - CHECK(Token_new); - ast->new_token = token_stream.cursor() - 1; - - if (token_stream.lookAhead() == '(') { - token_stream.nextToken(); - parseCommaExpression(ast->expression); - CHECK(')'); - } - - if (token_stream.lookAhead() == '(') { - token_stream.nextToken(); - parseTypeId(ast->type_id); - CHECK(')'); - } else { - parseNewTypeId(ast->new_type_id); - } - - parseNewInitializer(ast->new_initializer); - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - - return true; -} - -bool Parser::parseNewTypeId(NewTypeIdAST *&node) -{ - std::size_t start = token_stream.cursor(); - - TypeSpecifierAST *typeSpec = 0; - if (!parseTypeSpecifier(typeSpec)) - return false; - - NewTypeIdAST *ast = CreateNode<NewTypeIdAST>(_M_pool); - ast->type_specifier = typeSpec; - - parseNewDeclarator(ast->new_declarator); - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - - return true; -} - -bool Parser::parseNewDeclarator(NewDeclaratorAST *&node) -{ - std::size_t start = token_stream.cursor(); - - NewDeclaratorAST *ast = CreateNode<NewDeclaratorAST>(_M_pool); - - PtrOperatorAST *ptrOp = 0; - if (parsePtrOperator(ptrOp)) { - ast->ptr_op = ptrOp; - parseNewDeclarator(ast->sub_declarator); - } - - while (token_stream.lookAhead() == '[') { - token_stream.nextToken(); - ExpressionAST *expr = 0; - parseExpression(expr); - ast->expressions = snoc(ast->expressions, expr, _M_pool); - ADVANCE(']', "]"); - } - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - - return true; -} - -bool Parser::parseNewInitializer(NewInitializerAST *&node) -{ - std::size_t start = token_stream.cursor(); - - CHECK('('); - - NewInitializerAST *ast = CreateNode<NewInitializerAST>(_M_pool); - - parseCommaExpression(ast->expression); - - CHECK(')'); - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - - return true; -} - -bool Parser::parseDeleteExpression(ExpressionAST *&node) -{ - std::size_t start = token_stream.cursor(); - - DeleteExpressionAST *ast = CreateNode<DeleteExpressionAST>(_M_pool); - - if (token_stream.lookAhead() == Token_scope - && token_stream.lookAhead(1) == Token_delete) { - ast->scope_token = token_stream.cursor(); - token_stream.nextToken(); - } - - CHECK(Token_delete); - ast->delete_token = token_stream.cursor() - 1; - - if (token_stream.lookAhead() == '[') { - ast->lbracket_token = token_stream.cursor(); - token_stream.nextToken(); - CHECK(']'); - ast->rbracket_token = token_stream.cursor() - 1; - } - - if (!parseCastExpression(ast->expression)) - return false; - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - - return true; -} - -bool Parser::parseCastExpression(ExpressionAST *&node) -{ - std::size_t start = token_stream.cursor(); - - if (token_stream.lookAhead() == '(') { - token_stream.nextToken(); - - CastExpressionAST *ast = CreateNode<CastExpressionAST>(_M_pool); - - if (parseTypeId(ast->type_id)) { - if (token_stream.lookAhead() == ')') { - token_stream.nextToken(); - - if (parseCastExpression(ast->expression)) { - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - - return true; - } - } - } - } - - token_stream.rewind((int) start); - return parseUnaryExpression(node); -} - -bool Parser::parsePmExpression(ExpressionAST *&node) -{ - std::size_t start = token_stream.cursor(); - - if (!parseCastExpression(node) || !node) // ### fixme - return false; - - while (token_stream.lookAhead() == Token_ptrmem) { - std::size_t op = token_stream.cursor(); - token_stream.nextToken(); - - ExpressionAST *rightExpr = 0; - if (!parseCastExpression(rightExpr)) - return false; - - BinaryExpressionAST *ast = CreateNode<BinaryExpressionAST>(_M_pool); - ast->op = op; - ast->left_expression = node; - ast->right_expression = rightExpr; - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - } - - return true; -} - -bool Parser::parseMultiplicativeExpression(ExpressionAST *&node) -{ - std::size_t start = token_stream.cursor(); - - if (!parsePmExpression(node)) - return false; - - while (token_stream.lookAhead() == '*' - || token_stream.lookAhead() == '/' - || token_stream.lookAhead() == '%') { - std::size_t op = token_stream.cursor(); - token_stream.nextToken(); - - ExpressionAST *rightExpr = 0; - if (!parsePmExpression(rightExpr)) - return false; - - BinaryExpressionAST *ast = CreateNode<BinaryExpressionAST>(_M_pool); - ast->op = op; - ast->left_expression = node; - ast->right_expression = rightExpr; - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - } - - return true; -} - - -bool Parser::parseAdditiveExpression(ExpressionAST *&node) -{ - std::size_t start = token_stream.cursor(); - - if (!parseMultiplicativeExpression(node)) - return false; - - while (token_stream.lookAhead() == '+' || token_stream.lookAhead() == '-') { - std::size_t op = token_stream.cursor(); - token_stream.nextToken(); - - ExpressionAST *rightExpr = 0; - if (!parseMultiplicativeExpression(rightExpr)) - return false; - - BinaryExpressionAST *ast = CreateNode<BinaryExpressionAST>(_M_pool); - ast->op = op; - ast->left_expression = node; - ast->right_expression = rightExpr; - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - } - - return true; -} - -bool Parser::parseShiftExpression(ExpressionAST *&node) -{ - std::size_t start = token_stream.cursor(); - - if (!parseAdditiveExpression(node)) - return false; - - while (token_stream.lookAhead() == Token_shift) { - std::size_t op = token_stream.cursor(); - token_stream.nextToken(); - - ExpressionAST *rightExpr = 0; - if (!parseAdditiveExpression(rightExpr)) - return false; - - BinaryExpressionAST *ast = CreateNode<BinaryExpressionAST>(_M_pool); - ast->op = op; - ast->left_expression = node; - ast->right_expression = rightExpr; - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - } - - return true; -} - -bool Parser::parseRelationalExpression(ExpressionAST *&node, bool templArgs) -{ - std::size_t start = token_stream.cursor(); - - if (!parseShiftExpression(node)) - return false; - - while (token_stream.lookAhead() == '<' - || (token_stream.lookAhead() == '>' && !templArgs) - || token_stream.lookAhead() == Token_leq - || token_stream.lookAhead() == Token_geq) { - std::size_t op = token_stream.cursor(); - token_stream.nextToken(); - - ExpressionAST *rightExpr = 0; - if (!parseShiftExpression(rightExpr)) - return false; - - BinaryExpressionAST *ast = CreateNode<BinaryExpressionAST>(_M_pool); - ast->op = op; - ast->left_expression = node; - ast->right_expression = rightExpr; - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - } - - return true; -} - -bool Parser::parseEqualityExpression(ExpressionAST *&node, bool templArgs) -{ - std::size_t start = token_stream.cursor(); - - if (!parseRelationalExpression(node, templArgs)) - return false; - - while (token_stream.lookAhead() == Token_eq - || token_stream.lookAhead() == Token_not_eq) { - std::size_t op = token_stream.cursor(); - token_stream.nextToken(); - - ExpressionAST *rightExpr = 0; - if (!parseRelationalExpression(rightExpr, templArgs)) - return false; - - BinaryExpressionAST *ast = CreateNode<BinaryExpressionAST>(_M_pool); - ast->op = op; - ast->left_expression = node; - ast->right_expression = rightExpr; - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - } - - return true; -} - -bool Parser::parseAndExpression(ExpressionAST *&node, bool templArgs) -{ - std::size_t start = token_stream.cursor(); - - if (!parseEqualityExpression(node, templArgs)) - return false; - - while (token_stream.lookAhead() == '&') { - std::size_t op = token_stream.cursor(); - token_stream.nextToken(); - - ExpressionAST *rightExpr = 0; - if (!parseEqualityExpression(rightExpr, templArgs)) - return false; - - BinaryExpressionAST *ast = CreateNode<BinaryExpressionAST>(_M_pool); - ast->op = op; - ast->left_expression = node; - ast->right_expression = rightExpr; - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - } - - return true; -} - -bool Parser::parseExclusiveOrExpression(ExpressionAST *&node, bool templArgs) -{ - std::size_t start = token_stream.cursor(); - - if (!parseAndExpression(node, templArgs)) - return false; - - while (token_stream.lookAhead() == '^') { - std::size_t op = token_stream.cursor(); - token_stream.nextToken(); - - ExpressionAST *rightExpr = 0; - if (!parseAndExpression(rightExpr, templArgs)) - return false; - - BinaryExpressionAST *ast = CreateNode<BinaryExpressionAST>(_M_pool); - ast->op = op; - ast->left_expression = node; - ast->right_expression = rightExpr; - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - } - - return true; -} - -bool Parser::parseInclusiveOrExpression(ExpressionAST *&node, bool templArgs) -{ - std::size_t start = token_stream.cursor(); - - if (!parseExclusiveOrExpression(node, templArgs)) - return false; - - while (token_stream.lookAhead() == '|') { - std::size_t op = token_stream.cursor(); - token_stream.nextToken(); - - ExpressionAST *rightExpr = 0; - if (!parseExclusiveOrExpression(rightExpr, templArgs)) - return false; - - BinaryExpressionAST *ast = CreateNode<BinaryExpressionAST>(_M_pool); - ast->op = op; - ast->left_expression = node; - ast->right_expression = rightExpr; - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - } - - return true; -} - -bool Parser::parseLogicalAndExpression(ExpressionAST *&node, bool templArgs) -{ - std::size_t start = token_stream.cursor(); - - if (!parseInclusiveOrExpression(node, templArgs)) - return false; - - while (token_stream.lookAhead() == Token_and) { - std::size_t op = token_stream.cursor(); - token_stream.nextToken(); - - ExpressionAST *rightExpr = 0; - if (!parseInclusiveOrExpression(rightExpr, templArgs)) - return false; - - BinaryExpressionAST *ast = CreateNode<BinaryExpressionAST>(_M_pool); - ast->op = op; - ast->left_expression = node; - ast->right_expression = rightExpr; - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - } - - return true; -} - -bool Parser::parseLogicalOrExpression(ExpressionAST *&node, bool templArgs) -{ - std::size_t start = token_stream.cursor(); - - if (!parseLogicalAndExpression(node, templArgs)) - return false; - - while (token_stream.lookAhead() == Token_or) { - std::size_t op = token_stream.cursor(); - token_stream.nextToken(); - - ExpressionAST *rightExpr = 0; - if (!parseLogicalAndExpression(rightExpr, templArgs)) - return false; - - BinaryExpressionAST *ast = CreateNode<BinaryExpressionAST>(_M_pool); - ast->op = op; - ast->left_expression = node; - ast->right_expression = rightExpr; - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - } - - return true; -} - -bool Parser::parseConditionalExpression(ExpressionAST *&node) -{ - std::size_t start = token_stream.cursor(); - - if (!parseLogicalOrExpression(node)) - return false; - - if (token_stream.lookAhead() == '?') { - token_stream.nextToken(); - - ExpressionAST *leftExpr = 0; - if (!parseExpression(leftExpr)) - return false; - - CHECK(':'); - - ExpressionAST *rightExpr = 0; - if (!parseAssignmentExpression(rightExpr)) - return false; - - ConditionalExpressionAST *ast - = CreateNode<ConditionalExpressionAST>(_M_pool); - - ast->condition = node; - ast->left_expression = leftExpr; - ast->right_expression = rightExpr; - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - } - - return true; -} - -bool Parser::parseAssignmentExpression(ExpressionAST *&node) -{ - std::size_t start = token_stream.cursor(); - - if (token_stream.lookAhead() == Token_throw && !parseThrowExpression(node)) - return false; - else if (!parseConditionalExpression(node)) - return false; - - while (token_stream.lookAhead() == Token_assign - || token_stream.lookAhead() == '=') { - std::size_t op = token_stream.cursor(); - token_stream.nextToken(); - - ExpressionAST *rightExpr = 0; - if (!parseConditionalExpression(rightExpr)) - return false; - - BinaryExpressionAST *ast = CreateNode<BinaryExpressionAST>(_M_pool); - ast->op = op; - ast->left_expression = node; - ast->right_expression = rightExpr; - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - } - - return true; -} - -bool Parser::parseConstantExpression(ExpressionAST *&node) -{ - return parseConditionalExpression(node); -} - -bool Parser::parseExpression(ExpressionAST *&node) -{ - return parseCommaExpression(node); -} - -bool Parser::parseCommaExpression(ExpressionAST *&node) -{ - std::size_t start = token_stream.cursor(); - - if (!parseAssignmentExpression(node)) - return false; - - while (token_stream.lookAhead() == ',') { - std::size_t op = token_stream.cursor(); - token_stream.nextToken(); - - ExpressionAST *rightExpr = 0; - if (!parseAssignmentExpression(rightExpr)) - return false; - - BinaryExpressionAST *ast = CreateNode<BinaryExpressionAST>(_M_pool); - ast->op = op; - ast->left_expression = node; - ast->right_expression = rightExpr; - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - } - - return true; -} - -bool Parser::parseThrowExpression(ExpressionAST *&node) -{ - std::size_t start = token_stream.cursor(); - - CHECK(Token_throw); - - ThrowExpressionAST *ast = CreateNode<ThrowExpressionAST>(_M_pool); - ast->throw_token = token_stream.cursor() - 1; - - parseAssignmentExpression(ast->expression); - - UPDATE_POS(ast, start, token_stream.cursor()); - node = ast; - - return true; -} - -bool Parser::parseQ_ENUMS(DeclarationAST *&node) -{ - - if ((token_stream.lookAhead() != Token_Q_ENUMS) && - (token_stream.lookAhead() != Token_Q_ENUM)) - return false; - - if (token_stream.lookAhead(1) != '(') - return false; - - token_stream.nextToken(); - token_stream.nextToken(); - - int firstToken = token_stream.cursor(); - while (token_stream.lookAhead() != ')') - token_stream.nextToken(); - - QEnumsAST *ast = CreateNode<QEnumsAST>(_M_pool); - UPDATE_POS(ast, firstToken, token_stream.cursor()); - node = ast; - - token_stream.nextToken(); - - return true; -} - -bool Parser::parseQ_PROPERTY(DeclarationAST *&node) -{ - if (token_stream.lookAhead() != Token_Q_PROPERTY) - return false; - - if (token_stream.lookAhead(1) != '(') - return false; - - token_stream.nextToken(); - token_stream.nextToken(); - - int firstToken = token_stream.cursor(); - while (token_stream.lookAhead() != ')') - token_stream.nextToken(); - - QPropertyAST *ast = CreateNode<QPropertyAST>(_M_pool); - UPDATE_POS(ast, firstToken, token_stream.cursor()); - node = ast; - -// const Token &t1 = token_stream[firstToken]; -// const Token &t2 = token_stream[token_stream.cursor()]; -// printf("property: %s\n", -// qPrintable(QString::fromLatin1(t1.text + t1.position, t2.position - t1.position))); - - token_stream.nextToken(); - - return true; -} - -bool Parser::block_errors(bool block) -{ - bool current = _M_block_errors; - _M_block_errors = block; - return current; -} - -// kate: space-indent on; indent-width 2; replace-tabs on; - diff --git a/sources/shiboken2/ApiExtractor/parser/parser.h b/sources/shiboken2/ApiExtractor/parser/parser.h deleted file mode 100644 index 7aa5b9ad7..000000000 --- a/sources/shiboken2/ApiExtractor/parser/parser.h +++ /dev/null @@ -1,204 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#ifndef PARSER_H -#define PARSER_H - -#include "ast.h" -#include "lexer.h" - -#include <QtCore/QString> - -class FileSymbol; -class Control; - -class Parser -{ -public: - Parser(Control *control); - ~Parser(); - - LocationManager &location() { return _M_location; } - - TranslationUnitAST *parse(const char *contents, std::size_t size, pool *p); - -private: - void reportError(const QString& msg); - void syntaxError(); - void tokenRequiredError(int expected); - -public: - bool skipFunctionBody(StatementAST *&node); - -public: - bool parse_Attribute__(); - bool parseAbstractDeclarator(DeclaratorAST *&node); - bool parseAccessSpecifier(DeclarationAST *&node); - bool parseAdditiveExpression(ExpressionAST *&node); - bool parseAndExpression(ExpressionAST *&node, bool templArgs = false); - bool parseAsmDefinition(DeclarationAST *&node); - bool parseAssignmentExpression(ExpressionAST *&node); - bool parseBaseClause(BaseClauseAST *&node); - bool parseBaseSpecifier(BaseSpecifierAST *&node); - bool parseBlockDeclaration(DeclarationAST *&node); - bool parseCastExpression(ExpressionAST *&node); - bool parseClassSpecifier(TypeSpecifierAST *&node); - bool parseForwardDeclarationSpecifier(TypeSpecifierAST *&node); - bool parseCommaExpression(ExpressionAST *&node); - bool parseCompoundStatement(StatementAST *&node); - bool parseCondition(ConditionAST *&node, bool initRequired = true); - bool parseConditionalExpression(ExpressionAST *&node); - bool parseConstantExpression(ExpressionAST *&node); - bool parseCtorInitializer(CtorInitializerAST *&node); - bool parseCvQualify(const ListNode<std::size_t> *&node); - bool parseDeclaration(DeclarationAST *&node); - bool parseDeclarationInternal(DeclarationAST *&node); - bool parseDeclarationStatement(StatementAST *&node); - bool parseDeclarator(DeclaratorAST *&node); - bool parseDeleteExpression(ExpressionAST *&node); - bool parseDoStatement(StatementAST *&node); - bool parseElaboratedTypeSpecifier(TypeSpecifierAST *&node); - bool parseEnumSpecifier(TypeSpecifierAST *&node); - bool parseEnumerator(EnumeratorAST *&node); - bool parseEqualityExpression(ExpressionAST *&node, - bool templArgs = false); - bool parseExceptionSpecification(ExceptionSpecificationAST *&node); - bool parseExclusiveOrExpression(ExpressionAST *&node, - bool templArgs = false); - bool parseExpression(ExpressionAST *&node); - bool parseExpressionOrDeclarationStatement(StatementAST *&node); - bool parseExpressionStatement(StatementAST *&node); - bool parseForInitStatement(StatementAST *&node); - bool parseForStatement(StatementAST *&node); - bool parseFunctionBody(StatementAST *&node); - bool parseFunctionSpecifier(const ListNode<std::size_t> *&node); - bool parseIfStatement(StatementAST *&node); - bool parseInclusiveOrExpression(ExpressionAST *&node, - bool templArgs = false); - bool parseInitDeclarator(InitDeclaratorAST *&node); - bool parseInitDeclaratorList(const ListNode<InitDeclaratorAST*> *&node); - bool parseInitializer(InitializerAST *&node); - bool parseInitializerClause(InitializerClauseAST *&node); - bool parseLabeledStatement(StatementAST *&node); - bool parseLinkageBody(LinkageBodyAST *&node); - bool parseLinkageSpecification(DeclarationAST *&node); - bool parseLogicalAndExpression(ExpressionAST *&node, - bool templArgs = false); - bool parseLogicalOrExpression(ExpressionAST *&node, - bool templArgs = false); - bool parseMemInitializer(MemInitializerAST *&node); - bool parseMemInitializerList(const ListNode<MemInitializerAST*> *&node); - bool parseMemberSpecification(DeclarationAST *&node); - bool parseMultiplicativeExpression(ExpressionAST *&node); - bool parseName(NameAST *&node, bool acceptTemplateId = false); - bool parseNamespace(DeclarationAST *&node); - bool parseNamespaceAliasDefinition(DeclarationAST *&node); - bool parseNewDeclarator(NewDeclaratorAST *&node); - bool parseNewExpression(ExpressionAST *&node); - bool parseNewInitializer(NewInitializerAST *&node); - bool parseNewTypeId(NewTypeIdAST *&node); - bool parseNoExcept(); - bool parseOperator(OperatorAST *&node); - bool parseOperatorFunctionId(OperatorFunctionIdAST *&node); - bool parseParameterDeclaration(ParameterDeclarationAST *&node); - bool parseParameterDeclarationClause(ParameterDeclarationClauseAST *&node); - bool parseParameterDeclarationList(const ListNode<ParameterDeclarationAST*> *&node); - bool parsePmExpression(ExpressionAST *&node); - bool parsePostfixExpression(ExpressionAST *&node); - bool parsePostfixExpressionInternal(ExpressionAST *&node); - bool parsePrimaryExpression(ExpressionAST *&node); - bool parsePtrOperator(PtrOperatorAST *&node); - bool parsePtrToMember(PtrToMemberAST *&node); - bool parseRelationalExpression(ExpressionAST *&node, - bool templArgs = false); - bool parseShiftExpression(ExpressionAST *&node); - bool parseSimpleTypeSpecifier(TypeSpecifierAST *&node, - bool onlyIntegral = false); - bool parseStatement(StatementAST *&node); - bool parseStorageClassSpecifier(const ListNode<std::size_t> *&node); - bool parseStringLiteral(StringLiteralAST *&node); - bool parseSwitchStatement(StatementAST *&node); - bool parseTemplateArgument(TemplateArgumentAST *&node); - bool parseTemplateArgumentList(const ListNode<TemplateArgumentAST*> *&node, - bool reportError = true); - bool parseTemplateDeclaration(DeclarationAST *&node); - bool parseTemplateParameter(TemplateParameterAST *&node); - bool parseTemplateParameterList(const ListNode<TemplateParameterAST*> *&node); - bool parseThrowExpression(ExpressionAST *&node); - bool parseTranslationUnit(TranslationUnitAST *&node); - bool parseTryBlockStatement(StatementAST *&node); - bool parseTypeId(TypeIdAST *&node); - bool parseTypeIdList(const ListNode<TypeIdAST*> *&node); - bool parseTypeParameter(TypeParameterAST *&node); - bool parseTypeSpecifier(TypeSpecifierAST *&node); - bool parseTypeSpecifierOrClassSpec(TypeSpecifierAST *&node); - bool parseTypedef(DeclarationAST *&node); - bool parseUnaryExpression(ExpressionAST *&node); - bool parseUnqualifiedName(UnqualifiedNameAST *&node, - bool parseTemplateId = true); - bool parseUsing(DeclarationAST *&node); - bool parseUsingDirective(DeclarationAST *&node); - bool parseWhileStatement(StatementAST *&node); - bool parseWinDeclSpec(WinDeclSpecAST *&node); - - bool parseQ_PROPERTY(DeclarationAST *&node); - bool parseQ_ENUMS(DeclarationAST *&node); - - bool skipUntil(int token); - bool skipUntilDeclaration(); - bool skipUntilStatement(); - bool skip(int l, int r); - - void advance(); - - // private: - TokenStream token_stream; - LocationTable location_table; - LocationTable line_table; - - bool block_errors(bool block); - -private: - QString tokenText(AST *) const; - - LocationManager _M_location; - Control *control; - Lexer lexer; - pool *_M_pool; - bool _M_block_errors; - -private: - Parser(const Parser& source); - void operator = (const Parser& source); -}; - -#endif - -// kate: space-indent on; indent-width 2; replace-tabs on; diff --git a/sources/shiboken2/ApiExtractor/parser/r++.macros b/sources/shiboken2/ApiExtractor/parser/r++.macros deleted file mode 100644 index 455276c84..000000000 --- a/sources/shiboken2/ApiExtractor/parser/r++.macros +++ /dev/null @@ -1,28 +0,0 @@ - -#define __attribute__(a...) -#define __typeof__ __typeof - -#define __extension -#define __extension__ - -#define __restrict -#define __restrict__ - -#define __volatile volatile -#define __volatile__ volatile - -#define __inline inline -#define __inline__ inline - -#define __const const -#define __const__ const - -#define __asm asm -#define __asm__ asm - -#define __GNUC__ 3 -//#define __GNUC_MINOR__ 4 - -#define __ROBC__ 0 -#define __ROBC_MINOR__ 1 - diff --git a/sources/shiboken2/ApiExtractor/parser/rpp-allocator.h b/sources/shiboken2/ApiExtractor/parser/rpp-allocator.h deleted file mode 100644 index 4331ef7d4..000000000 --- a/sources/shiboken2/ApiExtractor/parser/rpp-allocator.h +++ /dev/null @@ -1,29 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "parser/rxx_allocator.h" diff --git a/sources/shiboken2/ApiExtractor/parser/rpp/builtin-macros.cpp b/sources/shiboken2/ApiExtractor/parser/rpp/builtin-macros.cpp deleted file mode 100644 index ccc150339..000000000 --- a/sources/shiboken2/ApiExtractor/parser/rpp/builtin-macros.cpp +++ /dev/null @@ -1,28 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - diff --git a/sources/shiboken2/ApiExtractor/parser/rpp/pp-cctype.h b/sources/shiboken2/ApiExtractor/parser/rpp/pp-cctype.h deleted file mode 100644 index d2e16b994..000000000 --- a/sources/shiboken2/ApiExtractor/parser/rpp/pp-cctype.h +++ /dev/null @@ -1,62 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef PP_CCTYPE_H -#define PP_CCTYPE_H - -#include <cctype> - -namespace rpp -{ - -inline bool pp_isalpha(int __ch) -{ - return std::isalpha((unsigned char) __ch) != 0; -} - -inline bool pp_isalnum(int __ch) -{ - return std::isalnum((unsigned char) __ch) != 0; -} - -inline bool pp_isdigit(int __ch) -{ - return std::isdigit((unsigned char) __ch) != 0; -} - -inline bool pp_isspace(int __ch) -{ - return std::isspace((unsigned char) __ch) != 0; -} - -} // namespace rpp - -#endif // PP_CCTYPE_H - -// kate: space-indent on; indent-width 2; replace-tabs on; diff --git a/sources/shiboken2/ApiExtractor/parser/rpp/pp-configuration b/sources/shiboken2/ApiExtractor/parser/rpp/pp-configuration deleted file mode 100644 index 15586dd88..000000000 --- a/sources/shiboken2/ApiExtractor/parser/rpp/pp-configuration +++ /dev/null @@ -1,86 +0,0 @@ -#define __DBL_MIN_EXP__ (-1021) -#define __FLT_MIN__ 1.17549435e-38F -#define __CHAR_BIT__ 8 -#define __WCHAR_MAX__ 2147483647 -#define __DBL_DENORM_MIN__ 4.9406564584124654e-324 -#define __FLT_EVAL_METHOD__ 2 -#define __DBL_MIN_10_EXP__ (-307) -#define __FINITE_MATH_ONLY__ 0 -#define __GNUC_PATCHLEVEL__ 2 -#define __SHRT_MAX__ 32767 -#define __LDBL_MAX__ 1.18973149535723176502e+4932L -#define __UINTMAX_TYPE__ long long unsigned int -#define __linux 1 -#define __unix 1 -#define __LDBL_MAX_EXP__ 16384 -#define __linux__ 1 -#define __SCHAR_MAX__ 127 -#define __USER_LABEL_PREFIX__ -#define __STDC_HOSTED__ 1 -#define __LDBL_HAS_INFINITY__ 1 -#define __DBL_DIG__ 15 -#define __FLT_EPSILON__ 1.19209290e-7F -#define __GXX_WEAK__ 1 -#define __LDBL_MIN__ 3.36210314311209350626e-4932L -#define __unix__ 1 -#define __DECIMAL_DIG__ 21 -#define __gnu_linux__ 1 -#define __LDBL_HAS_QUIET_NAN__ 1 -#define __GNUC__ 4 -#define __DBL_MAX__ 1.7976931348623157e+308 -#define __DBL_HAS_INFINITY__ 1 -#define __cplusplus 1 -#define __DEPRECATED 1 -#define __DBL_MAX_EXP__ 1024 -#define __GNUG__ 4 -#define __LONG_LONG_MAX__ 9223372036854775807LL -#define __GXX_ABI_VERSION 1002 -#define __FLT_MIN_EXP__ (-125) -#define __DBL_MIN__ 2.2250738585072014e-308 -#define __FLT_MIN_10_EXP__ (-37) -#define __DBL_HAS_QUIET_NAN__ 1 -#define __REGISTER_PREFIX__ -#define __NO_INLINE__ 1 -#define __i386 1 -#define __FLT_MANT_DIG__ 24 -#define __VERSION__ "4.0.2 20050808 (prerelease) (Ubuntu 4.0.1-4ubuntu9)" -#define i386 1 -#define __i486__ 1 -#define unix 1 -#define __i386__ 1 -#define __SIZE_TYPE__ unsigned int -#define __ELF__ 1 -#define __FLT_RADIX__ 2 -#define __LDBL_EPSILON__ 1.08420217248550443401e-19L -#define __FLT_HAS_QUIET_NAN__ 1 -#define __FLT_MAX_10_EXP__ 38 -#define __LONG_MAX__ 2147483647L -#define __FLT_HAS_INFINITY__ 1 -#define linux 1 -#define __EXCEPTIONS 1 -#define __LDBL_MANT_DIG__ 64 -#define __WCHAR_TYPE__ int -#define __FLT_DIG__ 6 -#define __INT_MAX__ 2147483647 -#define __i486 1 -#define __FLT_MAX_EXP__ 128 -#define __DBL_MANT_DIG__ 53 -#define __WINT_TYPE__ unsigned int -#define __LDBL_MIN_EXP__ (-16381) -#define __LDBL_MAX_10_EXP__ 4932 -#define __DBL_EPSILON__ 2.2204460492503131e-16 -#define __tune_i486__ 1 -#define __INTMAX_MAX__ 9223372036854775807LL -#define __FLT_DENORM_MIN__ 1.40129846e-45F -#define __FLT_MAX__ 3.40282347e+38F -#define __INTMAX_TYPE__ long long int -#define __GNUC_MINOR__ 0 -#define __DBL_MAX_10_EXP__ 308 -#define __LDBL_DENORM_MIN__ 3.64519953188247460253e-4951L -#define __PTRDIFF_TYPE__ int -#define __LDBL_MIN_10_EXP__ (-4931) -#define __LDBL_DIG__ 18 -#define _GNU_SOURCE 1 - - -#define __STDC__ diff --git a/sources/shiboken2/ApiExtractor/parser/rpp/pp-engine-bits.h b/sources/shiboken2/ApiExtractor/parser/rpp/pp-engine-bits.h deleted file mode 100644 index 3d8aee029..000000000 --- a/sources/shiboken2/ApiExtractor/parser/rpp/pp-engine-bits.h +++ /dev/null @@ -1,1300 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef PP_ENGINE_BITS_H -#define PP_ENGINE_BITS_H - -#include "pp.h" -#include <sys/stat.h> -#include <cstdio> -#include <iostream> - -namespace rpp -{ - -inline std::string pp::fix_file_path(std::string const &filename) const -{ -#if defined (PP_OS_WIN) - std::string s = filename; - for (std::string::iterator it = s.begin(); it != s.end(); ++it) { - if (*it == '/') - *it = '\\'; - } - return s; -#else - return filename; -#endif -} - -inline bool pp::is_absolute(std::string const &filename) const -{ -#if defined(PP_OS_WIN) - return filename.length() >= 3 - && filename.at(1) == ':' - && (filename.at(2) == '\\' || filename.at(2) == '/'); -#else - return filename.length() >= 1 - && filename.at(0) == '/'; -#endif -} - -template <typename _OutputIterator> -void pp::file(std::string const &filename, _OutputIterator __result) -{ - FILE *fp = std::fopen(filename.c_str(), "rb"); - if (fp != 0) { - std::string was = env.current_file; - env.current_file = filename; - file(fp, __result); - env.current_file = was; - } - //else - //std::cerr << "** WARNING file ``" << filename << " not found!" << std::endl; -} - -template <typename _OutputIterator> -void pp::file(FILE *fp, _OutputIterator __result) -{ - assert(fp != 0); - -#if defined (HAVE_MMAP) - struct stat st; - fstat(FILENO(fp), &st); - std::size_t size = st.st_size; - char *buffer = 0; - buffer = (char *) ::mmap(0, size, PROT_READ, MAP_SHARED, FILENO(fp), 0); - fclose(fp); - if (!buffer || buffer == (char*) - 1) - return; - this->operator()(buffer, buffer + size, __result); - ::munmap(buffer, size); -#else - std::string buffer; - while (!feof(fp)) { - char tmp[1024]; - int read = (int) fread(tmp, sizeof(char), 1023, fp); - tmp[read] = '\0'; - buffer += tmp; - } - fclose(fp); - this->operator()(buffer.c_str(), buffer.c_str() + buffer.size(), __result); -#endif -} - -template <typename _InputIterator> -bool pp::find_header_protection(_InputIterator __first, _InputIterator __last, std::string *__prot) -{ - int was = env.current_line; - - while (__first != __last) { - if (pp_isspace(*__first)) { - if (*__first == '\n') - ++env.current_line; - - ++__first; - } else if (_PP_internal::comment_p(__first, __last)) { - __first = skip_comment_or_divop(__first, __last); - env.current_line += skip_comment_or_divop.lines; - } else if (*__first == '#') { - __first = skip_blanks(++__first, __last); - env.current_line += skip_blanks.lines; - - if (__first != __last && *__first == 'i') { - _InputIterator __begin = __first; - __first = skip_identifier(__begin, __last); - env.current_line += skip_identifier.lines; - - std::string __directive(__begin, __first); - - if (__directive == "ifndef") { - __first = skip_blanks(__first, __last); - env.current_line += skip_blanks.lines; - - __begin = __first; - __first = skip_identifier(__first, __last); - env.current_line += skip_identifier.lines; - - if (__begin != __first && __first != __last) { - __prot->assign(__begin, __first); - return true; - } - } - } - break; - } else - break; - } - - env.current_line = was; - return false; -} - -inline pp::PP_DIRECTIVE_TYPE pp::find_directive(char const *__directive, std::size_t __size) const -{ - switch (__size) { - case 0: - return PP_UNNAMED_DIRECTIVE; - case 2: - if (__directive[0] == 'i' - && __directive[1] == 'f') - return PP_IF; - break; - - case 4: - if (__directive[0] == 'e' && !strcmp(__directive, "elif")) - return PP_ELIF; - else if (__directive[0] == 'e' && !strcmp(__directive, "else")) - return PP_ELSE; - break; - - case 5: - if (__directive[0] == 'i' && !strcmp(__directive, "ifdef")) - return PP_IFDEF; - else if (__directive[0] == 'u' && !strcmp(__directive, "undef")) - return PP_UNDEF; - else if (__directive[0] == 'e') { - if (!strcmp(__directive, "endif")) - return PP_ENDIF; - else if (!strcmp(__directive, "error")) - return PP_ERROR; - } - break; - - case 6: - if (__directive[0] == 'i' && !strcmp(__directive, "ifndef")) - return PP_IFNDEF; - else if (__directive[0] == 'd' && !strcmp(__directive, "define")) - return PP_DEFINE; - else if (__directive[0] == 'p' && !strcmp(__directive, "pragma")) - return PP_PRAGMA; - break; - - case 7: - if (__directive[0] == 'i' && !strcmp(__directive, "include")) - return PP_INCLUDE; - else if (!strcmp(__directive, "warning")) - return PP_WARNING; - break; - - case 12: - if (__directive[0] == 'i' && !strcmp(__directive, "include_next")) - return PP_INCLUDE_NEXT; - break; - - default: - break; - } - std::cerr << "** WARNING unknown directive '#" << __directive << "' at " << env.current_file << ":" << env.current_line << std::endl; - return PP_UNKNOWN_DIRECTIVE; -} - -inline bool pp::file_isdir(std::string const &__filename) const -{ - struct stat __st; - if (stat(__filename.c_str(), &__st) == 0) -#if defined(PP_OS_WIN) - return (__st.st_mode & _S_IFDIR) == _S_IFDIR; -#else - return (__st.st_mode & S_IFDIR) == S_IFDIR; -#endif - else - return false; -} - -inline bool pp::file_exists(std::string const &__filename) const -{ - struct stat __st; - return stat(__filename.c_str(), &__st) == 0; -} - -inline FILE *pp::find_include_file(std::string const &__input_filename, std::string *__filepath, - INCLUDE_POLICY __include_policy, bool __skip_current_path) const -{ - assert(__filepath != 0); - assert(! __input_filename.empty()); - - __filepath->assign(__input_filename); - - if (is_absolute(*__filepath) && !file_isdir(*__filepath)) - return std::fopen(__filepath->c_str(), "r"); - - if (! env.current_file.empty()) - _PP_internal::extract_file_path(env.current_file, __filepath); - - if (__include_policy == INCLUDE_LOCAL && ! __skip_current_path) { - std::string __tmp(*__filepath); - __tmp += __input_filename; - - if (file_exists(__tmp) && !file_isdir(__tmp)) { - __filepath->append(__input_filename); - return std::fopen(__filepath->c_str(), "r"); - } - } - - std::vector<std::string>::const_iterator it = include_paths.begin(); - - if (__skip_current_path) { - it = std::find(include_paths.begin(), include_paths.end(), *__filepath); - - if (it != include_paths.end()) - ++it; - - else - it = include_paths.begin(); - } - - for (; it != include_paths.end(); ++it) { - if (__skip_current_path && it == include_paths.begin()) - continue; - - __filepath->assign(*it); - __filepath->append(__input_filename); - - if (file_exists(*__filepath) && !file_isdir(*__filepath)) - return std::fopen(__filepath->c_str(), "r"); - -#ifdef Q_OS_MAC - // try in Framework path on Mac, if there is a path in front - // ### what about escaped slashes? - size_t slashPos = __input_filename.find('/'); - if (slashPos != std::string::npos) { - __filepath->assign(*it); - __filepath->append(__input_filename.substr(0, slashPos)); - __filepath->append(".framework/Headers/"); - __filepath->append(__input_filename.substr(slashPos + 1, std::string::npos)); - - if (file_exists(*__filepath) && !file_isdir(*__filepath)) { - return fopen(__filepath->c_str(), "r"); - } - } -#endif // Q_OS_MAC - } - - return 0; -} - -template <typename _InputIterator, typename _OutputIterator> -_InputIterator pp::handle_directive(char const *__directive, std::size_t __size, - _InputIterator __first, _InputIterator __last, _OutputIterator __result) -{ - __first = skip_blanks(__first, __last); - - PP_DIRECTIVE_TYPE d = find_directive(__directive, __size); - switch (d) { - case PP_UNNAMED_DIRECTIVE: - /* There are many boost headers that include the character '#' - * at the beginning of any line and just do nothing else with - * that unnamed directive. Well, as that's not an error so - * we'll just ignore this unnamed directive for now. - */ - ++__last; - return ++__first; - case PP_DEFINE: - if (! skipping()) - return handle_define(__first, __last); - break; - - case PP_INCLUDE: - case PP_INCLUDE_NEXT: - if (! skipping()) - return handle_include(d == PP_INCLUDE_NEXT, __first, __last, __result); - break; - - case PP_UNDEF: - if (! skipping()) - return handle_undef(__first, __last); - break; - - case PP_ELIF: - return handle_elif(__first, __last); - - case PP_ELSE: - return handle_else(__first, __last); - - case PP_ENDIF: - return handle_endif(__first, __last); - - case PP_IF: - return handle_if(__first, __last); - - case PP_IFDEF: - return handle_ifdef(false, __first, __last); - - case PP_IFNDEF: - return handle_ifdef(true, __first, __last); - - default: - break; - } - - return __first; -} - -template <typename _InputIterator, typename _OutputIterator> -_InputIterator pp::handle_include(bool __skip_current_path, _InputIterator __first, _InputIterator __last, - _OutputIterator __result) -{ - if (pp_isalpha(*__first) || *__first == '_') { - pp_macro_expander expand_include(env); - std::string name; - name.reserve(255); - expand_include(__first, __last, std::back_inserter(name)); - std::string::iterator it = skip_blanks(name.begin(), name.end()); - if (it != name.end() && !(*it == '<' || *it == '"')) { - std::cerr << "** WARNING APIExtractor does not support the use " - "of #include directives without passing either " - "\"<path/to/header.h>\" or \"./path/to/header.h\", " - "for example. Invalid use at " << env.current_file - << ":" << env.current_line << "." << std::endl; - return __last; - } - - handle_include(__skip_current_path, it, name.end(), __result); - return __first; - } - - assert(*__first == '<' || *__first == '"'); - int quote = (*__first == '"') ? '"' : '>'; - ++__first; - - _InputIterator end_name = __first; - for (; end_name != __last; ++end_name) { - assert(*end_name != '\n'); - - if (*end_name == quote) - break; - } - - std::string filename(__first, end_name); - -#ifdef PP_OS_WIN - std::replace(filename.begin(), filename.end(), '/', '\\'); -#endif - - std::string filepath; - FILE *fp = find_include_file(filename, &filepath, quote == '>' ? INCLUDE_GLOBAL : INCLUDE_LOCAL, __skip_current_path); - -#if defined (PP_HOOK_ON_FILE_INCLUDED) - PP_HOOK_ON_FILE_INCLUDED(env.current_file, fp ? filepath : filename, fp); -#endif - - if (fp != 0) { - std::string old_file = env.current_file; - env.current_file = filepath; - int __saved_lines = env.current_line; - - env.current_line = 1; - //output_line (env.current_file, 1, __result); - - file(fp, __result); - - // restore the file name and the line position - env.current_file = old_file; - env.current_line = __saved_lines; - - // sync the buffer - _PP_internal::output_line(env.current_file, env.current_line, __result); - } -#ifndef RPP_JAMBI -// else -// std::cerr << "*** WARNING " << filename << ": No such file or directory" << std::endl; -#endif - - return __first; -} - -template <typename _InputIterator, typename _OutputIterator> -void pp::operator()(_InputIterator __first, _InputIterator __last, _OutputIterator __result) -{ -#ifndef PP_NO_SMART_HEADER_PROTECTION - std::string __prot; - __prot.reserve(255); - pp_fast_string __tmp(__prot.c_str(), __prot.size()); - - if (find_header_protection(__first, __last, &__prot) - && env.resolve(&__tmp) != 0) { - // std::cerr << "** DEBUG found header protection:" << __prot << std::endl; - return; - } -#endif - - env.current_line = 1; - char __buffer[512]; - - while (true) { - __first = skip_blanks(__first, __last); - env.current_line += skip_blanks.lines; - - if (__first == __last) - break; - else if (*__first == '#') { - assert(*__first == '#'); - __first = skip_blanks(++__first, __last); - env.current_line += skip_blanks.lines; - - _InputIterator end_id = skip_identifier(__first, __last); - env.current_line += skip_identifier.lines; - std::size_t __size = end_id - __first; - - assert(__size < 512); - char *__cp = __buffer; - std::copy(__first, end_id, __cp); - __cp[__size] = '\0'; - - end_id = skip_blanks(end_id, __last); - __first = skip(end_id, __last); - - int was = env.current_line; - (void) handle_directive(__buffer, __size, end_id, __first, __result); - - if (env.current_line != was) { - env.current_line = was; - _PP_internal::output_line(env.current_file, env.current_line, __result); - } - } else if (*__first == '\n') { - // ### compress the line - *__result++ = *__first++; - ++env.current_line; - } else if (skipping()) - __first = skip(__first, __last); - else { - _PP_internal::output_line(env.current_file, env.current_line, __result); - __first = expand(__first, __last, __result); - env.current_line += expand.lines; - - if (expand.generated_lines) - _PP_internal::output_line(env.current_file, env.current_line, __result); - } - } -} - -inline pp::pp(pp_environment &__env): - env(__env), expand(env) -{ - iflevel = 0; - _M_skipping[iflevel] = 0; - _M_true_test[iflevel] = 0; -} - -inline std::back_insert_iterator<std::vector<std::string> > pp::include_paths_inserter() -{ - return std::back_inserter(include_paths); -} - -inline std::vector<std::string>::iterator pp::include_paths_begin() -{ - return include_paths.begin(); -} - -inline std::vector<std::string>::iterator pp::include_paths_end() -{ - return include_paths.end(); -} - -inline std::vector<std::string>::const_iterator pp::include_paths_begin() const -{ - return include_paths.begin(); -} - -inline std::vector<std::string>::const_iterator pp::include_paths_end() const -{ - return include_paths.end(); -} - -inline void pp::push_include_path(std::string const &__path) -{ - if (__path.empty() || __path [__path.size() - 1] != PATH_SEPARATOR) { - std::string __tmp(__path); - __tmp += PATH_SEPARATOR; - include_paths.push_back(__tmp); - } - - else - include_paths.push_back(__path); -} - -template <typename _InputIterator> -_InputIterator pp::handle_define(_InputIterator __first, _InputIterator __last) -{ - pp_macro macro; -#if defined (PP_WITH_MACRO_POSITION) - macro.file = pp_symbol::get(env.current_file); -#endif - std::string definition; - - __first = skip_blanks(__first, __last); - _InputIterator end_macro_name = skip_identifier(__first, __last); - pp_fast_string const *macro_name = pp_symbol::get(__first, end_macro_name); - __first = end_macro_name; - - if (__first != __last && *__first == '(') { - macro.function_like = true; - macro.formals.reserve(5); - - __first = skip_blanks(++__first, __last); // skip '(' - _InputIterator arg_end = skip_identifier(__first, __last); - if (__first != arg_end) - macro.formals.push_back(pp_symbol::get(__first, arg_end)); - - __first = skip_blanks(arg_end, __last); - - if (*__first == '.') { - macro.variadics = true; - while (*__first == '.') - ++__first; - } - - while (__first != __last && *__first == ',') { - __first = skip_blanks(++__first, __last); - - arg_end = skip_identifier(__first, __last); - if (__first != arg_end) - macro.formals.push_back(pp_symbol::get(__first, arg_end)); - - __first = skip_blanks(arg_end, __last); - - if (*__first == '.') { - macro.variadics = true; - while (*__first == '.') - ++__first; - } - } - - assert(*__first == ')'); - ++__first; - } - - __first = skip_blanks(__first, __last); - - /* Note: Sometimes one can include a path between brackets (for - * e.g., when defining a macro or so) so that we cannot simply - * ignore that. The in_path variable will handle this situation. - */ - bool in_path = false; - while (__first != __last && *__first != '\n') { - if ((*__first == '<' || *__first == '"') && - (*(__first + 1) != '*' && *(__first + 1) != '/')) { - in_path = true; - goto skip_path; - } - - if (in_path) { - if (*__first == '>' || *__first == '"') { - in_path = false; - goto skip_path; - } else if (*__first == ',' || *__first == ' ' || *__first == '\\') { - in_path = false; - continue; - } - } - - if (*__first == '/') { - if (*(__first + 1) != '*' && *(__first + 1) != '/') { - in_path = true; - goto skip_path; - } else { - __first = skip_comment_or_divop(__first, __last); - env.current_line += skip_comment_or_divop.lines; - if (__first == __last) - break; - } - } - - if (*__first == '\\') { - _InputIterator __begin = __first; - __begin = skip_blanks(++__begin, __last); - - if (__begin != __last && *__begin == '\n') { - ++macro.lines; - __first = skip_blanks(++__begin, __last); - definition += ' '; - continue; - } - } - -skip_path: - definition += *__first++; - } - - macro.definition = pp_symbol::get(definition); - env.bind(macro_name, macro); - - return __first; -} - -template <typename _InputIterator> -_InputIterator pp::skip(_InputIterator __first, _InputIterator __last) -{ - pp_skip_string_literal skip_string_literal; - pp_skip_char_literal skip_char_literal; - - while (__first != __last && *__first != '\n') { - if (*__first == '/') { - __first = skip_comment_or_divop(__first, __last); - env.current_line += skip_comment_or_divop.lines; - } else if (*__first == '"') { - __first = skip_string_literal(__first, __last); - env.current_line += skip_string_literal.lines; - } else if (*__first == '\'') { - __first = skip_char_literal(__first, __last); - env.current_line += skip_char_literal.lines; - } else if (*__first == '\\') { - __first = skip_blanks(++__first, __last); - env.current_line += skip_blanks.lines; - - if (__first != __last && *__first == '\n') { - ++__first; - ++env.current_line; - } - } else - ++__first; - } - - return __first; -} - -inline bool pp::test_if_level() -{ - bool result = !_M_skipping[iflevel++]; - _M_skipping[iflevel] = _M_skipping[iflevel - 1]; - _M_true_test[iflevel] = false; - return result; -} - -inline int pp::skipping() const -{ - return _M_skipping[iflevel]; -} - -template <typename _InputIterator> -_InputIterator pp::eval_primary(_InputIterator __first, _InputIterator __last, Value *result) -{ - bool expect_paren = false; - int token; - __first = next_token(__first, __last, &token); - - switch (token) { - case TOKEN_NUMBER: - result->set_long(token_value); - break; - - case TOKEN_UNUMBER: - result->set_ulong(token_uvalue); - break; - - case TOKEN_DEFINED: - __first = next_token(__first, __last, &token); - - if (token == '(') { - expect_paren = true; - __first = next_token(__first, __last, &token); - } - - if (token != TOKEN_IDENTIFIER) { - std::cerr << "** WARNING expected ``identifier'' found:" << char(token) << std::endl; - result->set_long(0); - break; - } - - result->set_long(env.resolve(token_text->c_str(), token_text->size()) != 0); - - next_token(__first, __last, &token); // skip '(' - - if (expect_paren) { - _InputIterator next = next_token(__first, __last, &token); - if (token != ')') - std::cerr << "** WARNING expected ``)''" << std::endl; - else - __first = next; - } - break; - - case TOKEN_IDENTIFIER: - result->set_long(0); - break; - - case '-': - __first = eval_primary(__first, __last, result); - result->set_long(- result->l); - return __first; - - case '+': - __first = eval_primary(__first, __last, result); - return __first; - - case '!': - __first = eval_primary(__first, __last, result); - result->set_long(result->is_zero()); - return __first; - - case '(': - __first = eval_constant_expression(__first, __last, result); - next_token(__first, __last, &token); - - if (token != ')') { - std::cerr << "** WARNING expected ``)'' = " << token << " (at " - << env.current_file << ":" << env.current_line - << ")." << std::endl; - } else { - __first = next_token(__first, __last, &token); - } - break; - - default: - result->set_long(0); - } - - return __first; -} - -template <typename _InputIterator> -_InputIterator pp::eval_multiplicative(_InputIterator __first, _InputIterator __last, Value *result) -{ - __first = eval_primary(__first, __last, result); - - int token; - _InputIterator next = next_token(__first, __last, &token); - - while (token == '*' || token == '/' || token == '%') { - Value value; - __first = eval_primary(next, __last, &value); - - if (token == '*') - result->op_mult(value); - else if (token == '/') { - if (value.is_zero()) { - std::cerr << "** WARNING division by zero" << std::endl; - result->set_long(0); - } else - result->op_div(value); - } else { - if (value.is_zero()) { - std::cerr << "** WARNING division by zero" << std::endl; - result->set_long(0); - } else - result->op_mod(value); - } - next = next_token(__first, __last, &token); - } - - return __first; -} - -template <typename _InputIterator> -_InputIterator pp::eval_additive(_InputIterator __first, _InputIterator __last, Value *result) -{ - __first = eval_multiplicative(__first, __last, result); - - int token; - _InputIterator next = next_token(__first, __last, &token); - - while (token == '+' || token == '-') { - Value value; - __first = eval_multiplicative(next, __last, &value); - - if (token == '+') - result->op_add(value); - else - result->op_sub(value); - next = next_token(__first, __last, &token); - } - - return __first; -} - -template <typename _InputIterator> -_InputIterator pp::eval_shift(_InputIterator __first, _InputIterator __last, Value *result) -{ - __first = eval_additive(__first, __last, result); - - int token; - _InputIterator next = next_token(__first, __last, &token); - - while (token == TOKEN_LT_LT || token == TOKEN_GT_GT) { - Value value; - __first = eval_additive(next, __last, &value); - - if (token == TOKEN_LT_LT) - result->op_lhs(value); - else - result->op_rhs(value); - next = next_token(__first, __last, &token); - } - - return __first; -} - -template <typename _InputIterator> -_InputIterator pp::eval_relational(_InputIterator __first, _InputIterator __last, Value *result) -{ - __first = eval_shift(__first, __last, result); - - int token; - _InputIterator next = next_token(__first, __last, &token); - - while (token == '<' - || token == '>' - || token == TOKEN_LT_EQ - || token == TOKEN_GT_EQ) { - Value value; - __first = eval_shift(next, __last, &value); - - switch (token) { - default: - assert(0); - break; - - case '<': - result->op_lt(value); - break; - - case '>': - result->op_gt(value); - break; - - case TOKEN_LT_EQ: - result->op_le(value); - break; - - case TOKEN_GT_EQ: - result->op_ge(value); - break; - } - next = next_token(__first, __last, &token); - } - - return __first; -} - -template <typename _InputIterator> -_InputIterator pp::eval_equality(_InputIterator __first, _InputIterator __last, Value *result) -{ - __first = eval_relational(__first, __last, result); - - int token; - _InputIterator next = next_token(__first, __last, &token); - - while (token == TOKEN_EQ_EQ || token == TOKEN_NOT_EQ) { - Value value; - __first = eval_relational(next, __last, &value); - - if (token == TOKEN_EQ_EQ) - result->op_eq(value); - else - result->op_ne(value); - next = next_token(__first, __last, &token); - } - - return __first; -} - -template <typename _InputIterator> -_InputIterator pp::eval_and(_InputIterator __first, _InputIterator __last, Value *result) -{ - __first = eval_equality(__first, __last, result); - - int token; - _InputIterator next = next_token(__first, __last, &token); - - while (token == '&') { - Value value; - __first = eval_equality(next, __last, &value); - result->op_bit_and(value); - next = next_token(__first, __last, &token); - } - - return __first; -} - -template <typename _InputIterator> -_InputIterator pp::eval_xor(_InputIterator __first, _InputIterator __last, Value *result) -{ - __first = eval_and(__first, __last, result); - - int token; - _InputIterator next = next_token(__first, __last, &token); - - while (token == '^') { - Value value; - __first = eval_and(next, __last, &value); - result->op_bit_xor(value); - next = next_token(__first, __last, &token); - } - - return __first; -} - -template <typename _InputIterator> -_InputIterator pp::eval_or(_InputIterator __first, _InputIterator __last, Value *result) -{ - __first = eval_xor(__first, __last, result); - - int token; - _InputIterator next = next_token(__first, __last, &token); - - while (token == '|') { - Value value; - __first = eval_xor(next, __last, &value); - result->op_bit_or(value); - next = next_token(__first, __last, &token); - } - - return __first; -} - -template <typename _InputIterator> -_InputIterator pp::eval_logical_and(_InputIterator __first, _InputIterator __last, Value *result) -{ - __first = eval_or(__first, __last, result); - - int token; - _InputIterator next = next_token(__first, __last, &token); - - while (token == TOKEN_AND_AND) { - Value value; - __first = eval_or(next, __last, &value); - result->op_and(value); - next = next_token(__first, __last, &token); - } - - return __first; -} - -template <typename _InputIterator> -_InputIterator pp::eval_logical_or(_InputIterator __first, _InputIterator __last, Value *result) -{ - __first = eval_logical_and(__first, __last, result); - - int token; - _InputIterator next = next_token(__first, __last, &token); - - while (token == TOKEN_OR_OR) { - Value value; - __first = eval_logical_and(next, __last, &value); - result->op_or(value); - next = next_token(__first, __last, &token); - } - - return __first; -} - -template <typename _InputIterator> -_InputIterator pp::eval_constant_expression(_InputIterator __first, _InputIterator __last, Value *result) -{ - __first = eval_logical_or(__first, __last, result); - - int token; - _InputIterator next = next_token(__first, __last, &token); - - if (token == '?') { - Value left_value; - __first = eval_constant_expression(next, __last, &left_value); - __first = skip_blanks(__first, __last); - - __first = next_token(__first, __last, &token); - if (token == ':') { - Value right_value; - __first = eval_constant_expression(__first, __last, &right_value); - - *result = !result->is_zero() ? left_value : right_value; - } else { - std::cerr << "** WARNING expected ``:'' = " << int (token) << std::endl; - *result = left_value; - } - } - - return __first; -} - -template <typename _InputIterator> -_InputIterator pp::eval_expression(_InputIterator __first, _InputIterator __last, Value *result) -{ - return __first = eval_constant_expression(skip_blanks(__first, __last), __last, result); -} - -template <typename _InputIterator> -_InputIterator pp::handle_if(_InputIterator __first, _InputIterator __last) -{ - if (test_if_level()) { - pp_macro_expander expand_condition(env); - std::string condition; - condition.reserve(255); - expand_condition(skip_blanks(__first, __last), __last, std::back_inserter(condition)); - - Value result; - result.set_long(0); - eval_expression(condition.c_str(), condition.c_str() + condition.size(), &result); - - _M_true_test[iflevel] = !result.is_zero(); - _M_skipping[iflevel] = result.is_zero(); - } - - return __first; -} - -template <typename _InputIterator> -_InputIterator pp::handle_else(_InputIterator __first, _InputIterator /*__last*/) -{ - if (iflevel == 0 && !skipping()) { - std::cerr << "** WARNING #else without #if" << std::endl; - } else if (iflevel > 0 && _M_skipping[iflevel - 1]) { - _M_skipping[iflevel] = true; - } else { - _M_skipping[iflevel] = _M_true_test[iflevel]; - } - - return __first; -} - -template <typename _InputIterator> -_InputIterator pp::handle_elif(_InputIterator __first, _InputIterator __last) -{ - assert(iflevel > 0); - - if (iflevel == 0 && !skipping()) { - std::cerr << "** WARNING #else without #if" << std::endl; - } else if (!_M_true_test[iflevel] && !_M_skipping[iflevel - 1]) { - Value result; - __first = eval_expression(__first, __last, &result); - _M_true_test[iflevel] = !result.is_zero(); - _M_skipping[iflevel] = result.is_zero(); - } else { - _M_skipping[iflevel] = true; - } - - return __first; -} - -template <typename _InputIterator> -_InputIterator pp::handle_endif(_InputIterator __first, _InputIterator /*__last*/) -{ - if (iflevel == 0 && !skipping()) { - std::cerr << "** WARNING #endif without #if" << std::endl; - } else { - _M_skipping[iflevel] = 0; - _M_true_test[iflevel] = 0; - - --iflevel; - } - - return __first; -} - -template <typename _InputIterator> -_InputIterator pp::handle_ifdef(bool check_undefined, _InputIterator __first, _InputIterator __last) -{ - if (test_if_level()) { - _InputIterator end_macro_name = skip_identifier(__first, __last); - - std::size_t __size; -#if defined(__SUNPRO_CC) - std::distance(__first, end_macro_name, __size); -#else - __size = std::distance(__first, end_macro_name); -#endif - assert(__size < 256); - - char __buffer [256]; - std::copy(__first, end_macro_name, __buffer); - - bool value = env.resolve(__buffer, __size) != 0; - - __first = end_macro_name; - - if (check_undefined) - value = !value; - - _M_true_test[iflevel] = value; - _M_skipping[iflevel] = !value; - } - - return __first; -} - -template <typename _InputIterator> -_InputIterator pp::handle_undef(_InputIterator __first, _InputIterator __last) -{ - __first = skip_blanks(__first, __last); - _InputIterator end_macro_name = skip_identifier(__first, __last); - assert(end_macro_name != __first); - - std::size_t __size; -#if defined(__SUNPRO_CC) - std::distance(__first, end_macro_name, __size); -#else - __size = std::distance(__first, end_macro_name); -#endif - - assert(__size < 256); - - char __buffer [256]; - std::copy(__first, end_macro_name, __buffer); - - pp_fast_string const __tmp(__buffer, __size); - env.unbind(&__tmp); - - __first = end_macro_name; - - return __first; -} - -template <typename _InputIterator> -char pp::peek_char(_InputIterator __first, _InputIterator __last) -{ - if (__first == __last) - return 0; - - return *++__first; -} - -template <typename _InputIterator> -_InputIterator pp::next_token(_InputIterator __first, _InputIterator __last, int *kind) -{ - __first = skip_blanks(__first, __last); - - if (__first == __last) { - *kind = 0; - return __first; - } - - char ch = *__first; - char ch2 = peek_char(__first, __last); - - switch (ch) { - case '/': - if (ch2 == '/' || ch2 == '*') { - __first = skip_comment_or_divop(__first, __last); - return next_token(__first, __last, kind); - } - ++__first; - *kind = '/'; - break; - - case '<': - ++__first; - if (ch2 == '<') { - ++__first; - *kind = TOKEN_LT_LT; - } else if (ch2 == '=') { - ++__first; - *kind = TOKEN_LT_EQ; - } else - *kind = '<'; - - return __first; - - case '>': - ++__first; - if (ch2 == '>') { - ++__first; - *kind = TOKEN_GT_GT; - } else if (ch2 == '=') { - ++__first; - *kind = TOKEN_GT_EQ; - } else - *kind = '>'; - - return __first; - - case '!': - ++__first; - if (ch2 == '=') { - ++__first; - *kind = TOKEN_NOT_EQ; - } else - *kind = '!'; - - return __first; - - case '=': - ++__first; - if (ch2 == '=') { - ++__first; - *kind = TOKEN_EQ_EQ; - } else - *kind = '='; - - return __first; - - case '|': - ++__first; - if (ch2 == '|') { - ++__first; - *kind = TOKEN_OR_OR; - } else - *kind = '|'; - - return __first; - - case '&': - ++__first; - if (ch2 == '&') { - ++__first; - *kind = TOKEN_AND_AND; - } else - *kind = '&'; - - return __first; - - default: - if (pp_isalpha(ch) || ch == '_') { - _InputIterator end = skip_identifier(__first, __last); - _M_current_text.assign(__first, end); - - token_text = &_M_current_text; - __first = end; - - if (*token_text == "defined") - *kind = TOKEN_DEFINED; - else - *kind = TOKEN_IDENTIFIER; - } else if (pp_isdigit(ch)) { - _InputIterator end = skip_number(__first, __last); - std::string __str(__first, __last); - char ch = __str [__str.size() - 1]; - if (ch == 'u' || ch == 'U') { - token_uvalue = strtoul(__str.c_str(), 0, 0); - *kind = TOKEN_UNUMBER; - } else { - token_value = strtol(__str.c_str(), 0, 0); - *kind = TOKEN_NUMBER; - } - __first = end; - } else - *kind = *__first++; - } - - return __first; -} - -} // namespace rpp - -#endif // PP_ENGINE_BITS_H - -// kate: space-indent on; indent-width 2; replace-tabs on; diff --git a/sources/shiboken2/ApiExtractor/parser/rpp/pp-engine.h b/sources/shiboken2/ApiExtractor/parser/rpp/pp-engine.h deleted file mode 100644 index 689d7720e..000000000 --- a/sources/shiboken2/ApiExtractor/parser/rpp/pp-engine.h +++ /dev/null @@ -1,288 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef PP_ENGINE_H -#define PP_ENGINE_H - -#include <string> -#include <vector> -#include "pp-scanner.h" -#include "pp-macro-expander.h" -#include "pp-environment.h" - -namespace rpp -{ - -struct Value { - Value() : kind(Kind_Long), l(0) {} - - enum Kind { - Kind_Long, - Kind_ULong, - }; - - Kind kind; - - union { - long l; - unsigned long ul; - }; - - inline bool is_ulong() const { - return kind == Kind_ULong; - } - - inline void set_ulong(unsigned long v) { - ul = v; - kind = Kind_ULong; - } - - inline void set_long(long v) { - l = v; - kind = Kind_Long; - } - - inline bool is_zero() const { - return l == 0; - } - -#define PP_DEFINE_BIN_OP(name, op) \ - inline Value &name (const Value &other) \ - { \ - if (is_ulong () || other.is_ulong ()) \ - set_ulong (ul op other.ul); \ - else \ - set_long (l op other.l); \ - return *this; \ - } - - PP_DEFINE_BIN_OP(op_add, +) - PP_DEFINE_BIN_OP(op_sub, -) - PP_DEFINE_BIN_OP(op_mult, *) - PP_DEFINE_BIN_OP(op_div, /) - PP_DEFINE_BIN_OP(op_mod, %) - PP_DEFINE_BIN_OP(op_lhs, <<) - PP_DEFINE_BIN_OP(op_rhs, >>) - PP_DEFINE_BIN_OP(op_lt, <) - PP_DEFINE_BIN_OP(op_gt, >) - PP_DEFINE_BIN_OP(op_le, <=) - PP_DEFINE_BIN_OP(op_ge, >=) - PP_DEFINE_BIN_OP(op_eq, ==) - PP_DEFINE_BIN_OP(op_ne, !=) - PP_DEFINE_BIN_OP(op_bit_and, &) - PP_DEFINE_BIN_OP(op_bit_or, |) - PP_DEFINE_BIN_OP(op_bit_xor, ^) - PP_DEFINE_BIN_OP(op_and, &&) - PP_DEFINE_BIN_OP(op_or, ||) - -#undef PP_DEFINE_BIN_OP -}; - -class pp -{ - pp_environment &env; - pp_macro_expander expand; - pp_skip_identifier skip_identifier; - pp_skip_comment_or_divop skip_comment_or_divop; - pp_skip_blanks skip_blanks; - pp_skip_number skip_number; - std::vector<std::string> include_paths; - std::string _M_current_text; - - enum { MAX_LEVEL = 512 }; - int _M_skipping[MAX_LEVEL]; - int _M_true_test[MAX_LEVEL]; - int iflevel; - - union { - long token_value; - unsigned long token_uvalue; - std::string *token_text; - }; - - enum INCLUDE_POLICY { - INCLUDE_GLOBAL, - INCLUDE_LOCAL - }; - - enum TOKEN_TYPE { - TOKEN_NUMBER = 1000, - TOKEN_UNUMBER, - TOKEN_IDENTIFIER, - TOKEN_DEFINED, - TOKEN_LT_LT, - TOKEN_LT_EQ, - TOKEN_GT_GT, - TOKEN_GT_EQ, - TOKEN_EQ_EQ, - TOKEN_NOT_EQ, - TOKEN_OR_OR, - TOKEN_AND_AND, - }; - - enum PP_DIRECTIVE_TYPE { - PP_UNKNOWN_DIRECTIVE, - PP_UNNAMED_DIRECTIVE, - PP_DEFINE, - PP_INCLUDE, - PP_INCLUDE_NEXT, - PP_ELIF, - PP_ELSE, - PP_ENDIF, - PP_IF, - PP_IFDEF, - PP_IFNDEF, - PP_UNDEF, - PP_PRAGMA, - PP_ERROR, - PP_WARNING - }; - -public: - pp(pp_environment &__env); - - inline std::back_insert_iterator<std::vector<std::string> > include_paths_inserter(); - - inline void push_include_path(std::string const &__path); - - inline std::vector<std::string>::iterator include_paths_begin(); - inline std::vector<std::string>::iterator include_paths_end(); - - inline std::vector<std::string>::const_iterator include_paths_begin() const; - inline std::vector<std::string>::const_iterator include_paths_end() const; - - template <typename _InputIterator> - inline _InputIterator eval_expression(_InputIterator __first, _InputIterator __last, Value *result); - - template <typename _OutputIterator> - void file(std::string const &filename, _OutputIterator __result); - - template <typename _OutputIterator> - void file(FILE *fp, _OutputIterator __result); - - template <typename _InputIterator, typename _OutputIterator> - void operator()(_InputIterator __first, _InputIterator __last, _OutputIterator __result); - -private: - inline bool file_isdir(std::string const &__filename) const; - inline bool file_exists(std::string const &__filename) const; - FILE *find_include_file(std::string const &__filename, std::string *__filepath, - INCLUDE_POLICY __include_policy, bool __skip_current_path = false) const; - - inline int skipping() const; - bool test_if_level(); - - inline std::string fix_file_path(std::string const &filename) const; - inline bool is_absolute(std::string const &filename) const; - - PP_DIRECTIVE_TYPE find_directive(char const *__directive, std::size_t __size) const; - - template <typename _InputIterator> - bool find_header_protection(_InputIterator __first, _InputIterator __last, std::string *__prot); - - template <typename _InputIterator> - _InputIterator skip(_InputIterator __first, _InputIterator __last); - - template <typename _InputIterator> - _InputIterator eval_primary(_InputIterator __first, _InputIterator __last, Value *result); - - template <typename _InputIterator> - _InputIterator eval_multiplicative(_InputIterator __first, _InputIterator __last, Value *result); - - template <typename _InputIterator> - _InputIterator eval_additive(_InputIterator __first, _InputIterator __last, Value *result); - - template <typename _InputIterator> - _InputIterator eval_shift(_InputIterator __first, _InputIterator __last, Value *result); - - template <typename _InputIterator> - _InputIterator eval_relational(_InputIterator __first, _InputIterator __last, Value *result); - - template <typename _InputIterator> - _InputIterator eval_equality(_InputIterator __first, _InputIterator __last, Value *result); - - template <typename _InputIterator> - _InputIterator eval_and(_InputIterator __first, _InputIterator __last, Value *result); - - template <typename _InputIterator> - _InputIterator eval_xor(_InputIterator __first, _InputIterator __last, Value *result); - - template <typename _InputIterator> - _InputIterator eval_or(_InputIterator __first, _InputIterator __last, Value *result); - - template <typename _InputIterator> - _InputIterator eval_logical_and(_InputIterator __first, _InputIterator __last, Value *result); - - template <typename _InputIterator> - _InputIterator eval_logical_or(_InputIterator __first, _InputIterator __last, Value *result); - - template <typename _InputIterator> - _InputIterator eval_constant_expression(_InputIterator __first, _InputIterator __last, Value *result); - - template <typename _InputIterator, typename _OutputIterator> - _InputIterator handle_directive(char const *__directive, std::size_t __size, - _InputIterator __first, _InputIterator __last, _OutputIterator __result); - - template <typename _InputIterator, typename _OutputIterator> - _InputIterator handle_include(bool skip_current_path, _InputIterator __first, _InputIterator __last, - _OutputIterator __result); - - template <typename _InputIterator> - _InputIterator handle_define(_InputIterator __first, _InputIterator __last); - - template <typename _InputIterator> - _InputIterator handle_if(_InputIterator __first, _InputIterator __last); - - template <typename _InputIterator> - _InputIterator handle_else(_InputIterator __first, _InputIterator __last); - - template <typename _InputIterator> - _InputIterator handle_elif(_InputIterator __first, _InputIterator __last); - - template <typename _InputIterator> - _InputIterator handle_endif(_InputIterator __first, _InputIterator __last); - - template <typename _InputIterator> - _InputIterator handle_ifdef(bool check_undefined, _InputIterator __first, _InputIterator __last); - - template <typename _InputIterator> - _InputIterator handle_undef(_InputIterator __first, _InputIterator __last); - - template <typename _InputIterator> - inline char peek_char(_InputIterator __first, _InputIterator __last); - - template <typename _InputIterator> - _InputIterator next_token(_InputIterator __first, _InputIterator __last, int *kind); -}; - -} // namespace rpp - -#endif // PP_ENGINE_H - -// kate: space-indent on; indent-width 2; replace-tabs on; diff --git a/sources/shiboken2/ApiExtractor/parser/rpp/pp-environment.h b/sources/shiboken2/ApiExtractor/parser/rpp/pp-environment.h deleted file mode 100644 index 23f22e483..000000000 --- a/sources/shiboken2/ApiExtractor/parser/rpp/pp-environment.h +++ /dev/null @@ -1,144 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef PP_ENVIRONMENT_H -#define PP_ENVIRONMENT_H - -#include <vector> -#include <string> -#include <cstring> -#include "pp-macro.h" - -namespace rpp -{ - -class pp_environment -{ -public: - typedef std::vector<pp_macro*>::const_iterator const_iterator; - -public: - pp_environment(): - current_line(0), - _M_hash_size(4093) { - _M_base = (pp_macro **) memset(new pp_macro* [_M_hash_size], 0, _M_hash_size * sizeof(pp_macro*)); - } - - ~pp_environment() { - for (std::size_t i = 0; i < _M_macros.size(); ++i) - delete _M_macros [i]; - - delete [] _M_base; - } - - const_iterator first_macro() const { - return _M_macros.begin(); - } - const_iterator last_macro() const { - return _M_macros.end(); - } - - inline void bind(pp_fast_string const *__name, pp_macro const &__macro) { - std::size_t h = hash_code(*__name) % _M_hash_size; - pp_macro *m = new pp_macro(__macro); - m->name = __name; - m->next = _M_base [h]; - m->hash_code = h; - _M_base [h] = m; - - _M_macros.push_back(m); - - if (_M_macros.size() == _M_hash_size) - rehash(); - } - - inline void unbind(pp_fast_string const *__name) { - if (pp_macro *m = resolve(__name)) - m->hidden = true; - } - - inline void unbind(char const *__s, std::size_t __size) { - pp_fast_string __tmp(__s, __size); - unbind(&__tmp); - } - - inline pp_macro *resolve(pp_fast_string const *__name) const { - std::size_t h = hash_code(*__name) % _M_hash_size; - pp_macro *it = _M_base [h]; - - while (it && it->name && it->hash_code == h && (*it->name != *__name || it->hidden)) - it = it->next; - - return it; - } - - inline pp_macro *resolve(char const *__data, std::size_t __size) const { - pp_fast_string const __tmp(__data, __size); - return resolve(&__tmp); - } - - std::string current_file; - int current_line; - -private: - inline std::size_t hash_code(pp_fast_string const &s) const { - std::size_t hash_value = 0; - - for (std::size_t i = 0; i < s.size(); ++i) - hash_value = (hash_value << 5) - hash_value + s.at(i); - - return hash_value; - } - - void rehash() { - delete[] _M_base; - - _M_hash_size <<= 1; - - _M_base = (pp_macro **) memset(new pp_macro* [_M_hash_size], 0, _M_hash_size * sizeof(pp_macro*)); - for (std::size_t index = 0; index < _M_macros.size(); ++index) { - pp_macro *elt = _M_macros [index]; - std::size_t h = hash_code(*elt->name) % _M_hash_size; - elt->next = _M_base [h]; - elt->hash_code = h; - _M_base [h] = elt; - } - } - -private: - std::vector<pp_macro*> _M_macros; - pp_macro **_M_base; - std::size_t _M_hash_size; -}; - -} // namespace rpp - -#endif // PP_ENVIRONMENT_H - -// kate: space-indent on; indent-width 2; replace-tabs on; diff --git a/sources/shiboken2/ApiExtractor/parser/rpp/pp-fwd.h b/sources/shiboken2/ApiExtractor/parser/rpp/pp-fwd.h deleted file mode 100644 index 2814b6d44..000000000 --- a/sources/shiboken2/ApiExtractor/parser/rpp/pp-fwd.h +++ /dev/null @@ -1,44 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef PP_FWD_H -#define PP_FWD_H - -namespace rpp -{ - -template <typename _CharT> class pp_string; - -typedef pp_string<char> pp_fast_string; - -} // namespace rpp - -#endif // PP_FWD_H - -// kate: space-indent on; indent-width 2; replace-tabs on; diff --git a/sources/shiboken2/ApiExtractor/parser/rpp/pp-internal.h b/sources/shiboken2/ApiExtractor/parser/rpp/pp-internal.h deleted file mode 100644 index 33efa0c27..000000000 --- a/sources/shiboken2/ApiExtractor/parser/rpp/pp-internal.h +++ /dev/null @@ -1,122 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef PP_INTERNAL_H -#define PP_INTERNAL_H - -#include <algorithm> -#include <string> -#include "pp.h" - -namespace rpp -{ - -namespace _PP_internal -{ - -inline void extract_file_path(const std::string &__filename, std::string *__filepath) -{ - std::size_t __index = __filename.rfind(PATH_SEPARATOR); - - if (__index == std::string::npos) - *__filepath = "/"; - - else - __filepath->assign(__filename, 0, __index + 1); -} - -template <typename _OutputIterator> -void output_line(const std::string &__filename, int __line, _OutputIterator __result) -{ - std::string __msg; - - __msg += "# "; - - char __line_descr[16]; - pp_snprintf(__line_descr, 16, "%d", __line); - __msg += __line_descr; - - __msg += " \""; - - if (__filename.empty()) - __msg += "<internal>"; - else - __msg += __filename; - - __msg += "\"\n"; - std::copy(__msg.begin(), __msg.end(), __result); -} - -template <typename _InputIterator> -inline bool comment_p(_InputIterator __first, _InputIterator __last) /*const*/ -{ - if (__first == __last) - return false; - - if (*__first != '/') - return false; - - if (++__first == __last) - return false; - - return (*__first == '/' || *__first == '*'); -} - -struct _Compare_string: public std::binary_function<bool, pp_fast_string const *, pp_fast_string const *> { - inline bool operator()(pp_fast_string const *__lhs, pp_fast_string const *__rhs) const { - return *__lhs < *__rhs; - } -}; - -struct _Equal_to_string: public std::binary_function<bool, pp_fast_string const *, pp_fast_string const *> { - inline bool operator()(pp_fast_string const *__lhs, pp_fast_string const *__rhs) const { - return *__lhs == *__rhs; - } -}; - -struct _Hash_string: public std::unary_function<std::size_t, pp_fast_string const *> { - inline std::size_t operator()(pp_fast_string const *__s) const { - char const *__ptr = __s->begin(); - std::size_t __size = __s->size(); - std::size_t __h = 0; - - for (std::size_t i = 0; i < __size; ++i) - __h = (__h << 5) - __h + __ptr [i]; - - return __h; - } -}; - -} // _PP_internal - -} // namespace rpp - -#endif // PP_INTERNAL_H - -// kate: space-indent on; indent-width 2; replace-tabs on; diff --git a/sources/shiboken2/ApiExtractor/parser/rpp/pp-iterator.h b/sources/shiboken2/ApiExtractor/parser/rpp/pp-iterator.h deleted file mode 100644 index 35964fea4..000000000 --- a/sources/shiboken2/ApiExtractor/parser/rpp/pp-iterator.h +++ /dev/null @@ -1,99 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef PP_ITERATOR_H -#define PP_ITERATOR_H - -#include <iterator> - -namespace rpp -{ - -class pp_null_output_iterator - : public std::iterator<std::output_iterator_tag, void, void, void, void> -{ -public: - pp_null_output_iterator() {} - - template <typename _Tp> - pp_null_output_iterator &operator=(_Tp const &) { - return *this; - } - - inline pp_null_output_iterator &operator *() { - return *this; - } - inline pp_null_output_iterator &operator ++ () { - return *this; - } - inline pp_null_output_iterator operator ++ (int) { - return *this; - } -}; - -template <typename _Container> -class pp_output_iterator - : public std::iterator<std::output_iterator_tag, void, void, void, void> -{ - std::string &_M_result; - -public: - explicit pp_output_iterator(std::string &__result): - _M_result(__result) {} - - inline pp_output_iterator<_Container>& operator=(const pp_output_iterator<_Container>& other) - { - _M_result = other._M_result; - return *this; - } - - inline pp_output_iterator &operator=(typename _Container::const_reference __v) { - if (_M_result.capacity() == _M_result.size()) - _M_result.reserve(_M_result.capacity() << 2); - - _M_result.push_back(__v); - return *this; - } - - inline pp_output_iterator &operator *() { - return *this; - } - inline pp_output_iterator &operator ++ () { - return *this; - } - inline pp_output_iterator operator ++ (int) { - return *this; - } -}; - -} // namespace rpp - -#endif // PP_ITERATOR_H - -// kate: space-indent on; indent-width 2; replace-tabs on; diff --git a/sources/shiboken2/ApiExtractor/parser/rpp/pp-macro-expander.h b/sources/shiboken2/ApiExtractor/parser/rpp/pp-macro-expander.h deleted file mode 100644 index db93c3214..000000000 --- a/sources/shiboken2/ApiExtractor/parser/rpp/pp-macro-expander.h +++ /dev/null @@ -1,356 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef PP_MACRO_EXPANDER_H -#define PP_MACRO_EXPANDER_H - -namespace rpp -{ - -struct pp_frame { - pp_macro *expanding_macro; - std::vector<std::string> *actuals; - - pp_frame(pp_macro *__expanding_macro, std::vector<std::string> *__actuals): - expanding_macro(__expanding_macro), actuals(__actuals) {} -}; - -class pp_macro_expander -{ - pp_environment &env; - pp_frame *frame; - - pp_skip_number skip_number; - pp_skip_identifier skip_identifier; - pp_skip_string_literal skip_string_literal; - pp_skip_char_literal skip_char_literal; - pp_skip_argument skip_argument; - pp_skip_comment_or_divop skip_comment_or_divop; - pp_skip_blanks skip_blanks; - pp_skip_whitespaces skip_whitespaces; - - std::string const *resolve_formal(pp_fast_string const *__name) { - assert(__name != 0); - - if (! frame) - return 0; - - assert(frame->expanding_macro != 0); - - std::vector<pp_fast_string const *> const formals = frame->expanding_macro->formals; - for (std::size_t index = 0; index < formals.size(); ++index) { - pp_fast_string const *formal = formals[index]; - - if (*formal != *__name) - continue; - - else if (frame->actuals && index < frame->actuals->size()) - return &(*frame->actuals)[index]; - - else - assert(0); // internal error? - } - - return 0; - } - -public: // attributes - int lines; - int generated_lines; - -public: - pp_macro_expander(pp_environment &__env, pp_frame *__frame = 0): - env(__env), frame(__frame), lines(0), generated_lines(0) {} - - template <typename _InputIterator, typename _OutputIterator> - _InputIterator operator()(_InputIterator __first, _InputIterator __last, _OutputIterator __result) { - generated_lines = 0; - __first = skip_blanks(__first, __last); - lines = skip_blanks.lines; - - while (__first != __last) { - if (*__first == '\n') { - *__result++ = *__first; - ++lines; - - __first = skip_blanks(++__first, __last); - lines += skip_blanks.lines; - - if (__first != __last && *__first == '#') - break; - } else if (*__first == '#') { - __first = skip_blanks(++__first, __last); - lines += skip_blanks.lines; - - _InputIterator end_id = skip_identifier(__first, __last); - - // ### rewrite: not safe - char name_buffer[512], *cp = name_buffer; - std::copy(__first, end_id, cp); - std::size_t name_size = end_id - __first; - name_buffer[name_size] = '\0'; - - pp_fast_string fast_name(name_buffer, name_size); - - if (std::string const *actual = resolve_formal(&fast_name)) { - *__result++ = '\"'; - - for (std::string::const_iterator it = skip_whitespaces(actual->begin(), actual->end()); - it != actual->end(); ++it) { - if (*it == '"') { - *__result++ = '\\'; - *__result++ = *it; - } - - else if (*it == '\n') { - *__result++ = '"'; - *__result++ = '\n'; - *__result++ = '"'; - } - - else - *__result++ = *it; - } - - *__result++ = '\"'; - __first = end_id; - } else - *__result++ = '#'; // ### warning message? - } else if (*__first == '\"') { - _InputIterator next_pos = skip_string_literal(__first, __last); - lines += skip_string_literal.lines; - std::copy(__first, next_pos, __result); - __first = next_pos; - } else if (*__first == '\'') { - _InputIterator next_pos = skip_char_literal(__first, __last); - lines += skip_char_literal.lines; - std::copy(__first, next_pos, __result); - __first = next_pos; - } else if (_PP_internal::comment_p(__first, __last)) { - __first = skip_comment_or_divop(__first, __last); - int n = skip_comment_or_divop.lines; - lines += n; - - while (n-- > 0) - *__result++ = '\n'; - } else if (pp_isspace(*__first)) { - for (; __first != __last; ++__first) { - if (*__first == '\n' || !pp_isspace(*__first)) - break; - } - - *__result = ' '; - } else if (pp_isdigit(*__first)) { - _InputIterator next_pos = skip_number(__first, __last); - lines += skip_number.lines; - std::copy(__first, next_pos, __result); - __first = next_pos; - } else if (pp_isalpha(*__first) || *__first == '_') { - _InputIterator name_begin = __first; - _InputIterator name_end = skip_identifier(__first, __last); - __first = name_end; // advance - - // search for the paste token - _InputIterator next = skip_blanks(__first, __last); - if (next != __last && *next == '#') { - ++next; - if (next != __last && *next == '#') - __first = skip_blanks(++next, __last); - } - - // ### rewrite: not safe - - std::ptrdiff_t name_size; -#if defined(__SUNPRO_CC) - std::distance(name_begin, name_end, name_size); -#else - name_size = std::distance(name_begin, name_end); -#endif - assert(name_size >= 0 && name_size < 512); - - char name_buffer[512], *cp = name_buffer; - std::size_t __size = name_end - name_begin; - std::copy(name_begin, name_end, cp); - name_buffer[__size] = '\0'; - - pp_fast_string fast_name(name_buffer, name_size); - - if (std::string const *actual = resolve_formal(&fast_name)) { - std::copy(actual->begin(), actual->end(), __result); - continue; - } - - static bool hide_next = false; // ### remove me - - pp_macro *macro = env.resolve(name_buffer, name_size); - if (! macro || macro->hidden || hide_next) { - hide_next = ! strcmp(name_buffer, "defined"); - - if (__size == 8 && name_buffer [0] == '_' && name_buffer [1] == '_') { - if (! strcmp(name_buffer, "__LINE__")) { - char buf [16]; - char *end = buf + pp_snprintf(buf, 16, "%d", env.current_line + lines); - - std::copy(&buf [0], end, __result); - continue; - } - - else if (! strcmp(name_buffer, "__FILE__")) { - __result++ = '"'; - std::copy(env.current_file.begin(), env.current_file.end(), __result); // ### quote - __result++ = '"'; - continue; - } - } - - std::copy(name_begin, name_end, __result); - continue; - } - - if (! macro->function_like) { - pp_macro *m = 0; - - if (macro->definition) { - macro->hidden = true; - - std::string __tmp; - __tmp.reserve(256); - - pp_macro_expander expand_macro(env); - expand_macro(macro->definition->begin(), macro->definition->end(), std::back_inserter(__tmp)); - generated_lines += expand_macro.lines; - - if (! __tmp.empty()) { - std::string::iterator __begin_id = skip_whitespaces(__tmp.begin(), __tmp.end()); - std::string::iterator __end_id = skip_identifier(__begin_id, __tmp.end()); - - if (__end_id == __tmp.end()) { - std::string __id; - __id.assign(__begin_id, __end_id); - - std::size_t x; -#if defined(__SUNPRO_CC) - std::distance(__begin_id, __end_id, x); -#else - x = std::distance(__begin_id, __end_id); -#endif - m = env.resolve(__id.c_str(), x); - } - - if (! m) - std::copy(__tmp.begin(), __tmp.end(), __result); - } - - macro->hidden = false; - } - - if (! m) - continue; - - macro = m; - } - - // function like macro - _InputIterator arg_it = skip_whitespaces(__first, __last); - - if (arg_it == __last || *arg_it != '(') { - std::copy(name_begin, name_end, __result); - lines += skip_whitespaces.lines; - __first = arg_it; - continue; - } - - std::vector<std::string> actuals; - actuals.reserve(5); - ++arg_it; // skip '(' - - pp_macro_expander expand_actual(env, frame); - - _InputIterator arg_end = skip_argument_variadics(actuals, macro, arg_it, __last); - if (arg_it != arg_end) { - std::string actual(arg_it, arg_end); - actuals.resize(actuals.size() + 1); - actuals.back().reserve(255); - expand_actual(actual.begin(), actual.end(), std::back_inserter(actuals.back())); - arg_it = arg_end; - } - - while (arg_it != __last && *arg_end == ',') { - ++arg_it; // skip ',' - - arg_end = skip_argument_variadics(actuals, macro, arg_it, __last); - std::string actual(arg_it, arg_end); - actuals.resize(actuals.size() + 1); - actuals.back().reserve(255); - expand_actual(actual.begin(), actual.end(), std::back_inserter(actuals.back())); - arg_it = arg_end; - } - - assert(arg_it != __last && *arg_it == ')'); - - ++arg_it; // skip ')' - __first = arg_it; - -#if 0 // ### enable me - assert((macro->variadics && macro->formals.size() >= actuals.size()) - || macro->formals.size() == actuals.size()); -#endif - - pp_frame frame(macro, &actuals); - pp_macro_expander expand_macro(env, &frame); - macro->hidden = true; - expand_macro(macro->definition->begin(), macro->definition->end(), __result); - macro->hidden = false; - generated_lines += expand_macro.lines; - } else - *__result++ = *__first++; - } - - return __first; - } - - template <typename _InputIterator> - _InputIterator skip_argument_variadics(std::vector<std::string> const &__actuals, pp_macro *__macro, - _InputIterator __first, _InputIterator __last) { - _InputIterator arg_end = skip_argument(__first, __last); - - while (__macro->variadics && __first != arg_end && arg_end != __last && *arg_end == ',' - && (__actuals.size() + 1) == __macro->formals.size()) { - arg_end = skip_argument(++arg_end, __last); - } - - return arg_end; - } -}; - -} // namespace rpp - -#endif // PP_MACRO_EXPANDER_H - -// kate: space-indent on; indent-width 2; replace-tabs on; diff --git a/sources/shiboken2/ApiExtractor/parser/rpp/pp-macro.h b/sources/shiboken2/ApiExtractor/parser/rpp/pp-macro.h deleted file mode 100644 index 9e95840a1..000000000 --- a/sources/shiboken2/ApiExtractor/parser/rpp/pp-macro.h +++ /dev/null @@ -1,77 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef PP_MACRO_H -#define PP_MACRO_H - -#include <vector> -#include "pp-fwd.h" - -namespace rpp -{ - -struct pp_macro { -#if defined (PP_WITH_MACRO_POSITION) - pp_fast_string const *file; -#endif - pp_fast_string const *name; - pp_fast_string const *definition; - std::vector<pp_fast_string const *> formals; - - union { - int unsigned state; - - struct { - int unsigned hidden: 1; - int unsigned function_like: 1; - int unsigned variadics: 1; - }; - }; - - int lines; - pp_macro *next; - std::size_t hash_code; - - inline pp_macro(): -#if defined (PP_WITH_MACRO_POSITION) - file(0), -#endif - name(0), - definition(0), - state(0), - lines(0), - next(0), - hash_code(0) {} -}; - -} // namespace rpp - -#endif // PP_MACRO_H - -// kate: space-indent on; indent-width 2; replace-tabs on; diff --git a/sources/shiboken2/ApiExtractor/parser/rpp/pp-qt-configuration b/sources/shiboken2/ApiExtractor/parser/rpp/pp-qt-configuration deleted file mode 100644 index ba356c323..000000000 --- a/sources/shiboken2/ApiExtractor/parser/rpp/pp-qt-configuration +++ /dev/null @@ -1,24 +0,0 @@ -#define __cplusplus 1 - -#define __STDC__ 1 - -// Qt -#define QOBJECTDEFS_H - -// not yet supported -#define Q_SLOTS slots -#define Q_SIGNALS signals -#define Q_FLAGS(a) -#define Q_PRIVATE_SLOT(a, b) -#define Q_DECLARE_INTERFACE(a,b) -#define Q_INTERFACES(a) -#define Q_GADGET -#define Q_OVERRIDE(a) -#define Q_OS_OS2 -#define Q_NO_USING_KEYWORD -#define QT_NO_QOBJECT_CHECK -#define QT_NO_MEMBER_TEMPLATES -// There are symbols in Qt that exist in Debug but -// not in release -#define QT_NO_DEBUG - diff --git a/sources/shiboken2/ApiExtractor/parser/rpp/pp-scanner.h b/sources/shiboken2/ApiExtractor/parser/rpp/pp-scanner.h deleted file mode 100644 index 0c5007e0f..000000000 --- a/sources/shiboken2/ApiExtractor/parser/rpp/pp-scanner.h +++ /dev/null @@ -1,318 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef PP_SCANNER_H -#define PP_SCANNER_H - -#include "pp-cctype.h" -#include <cassert> - -namespace rpp -{ - -struct pp_skip_blanks { - int lines; - - template <typename _InputIterator> - _InputIterator operator()(_InputIterator __first, _InputIterator __last) { - lines = 0; - - for (; __first != __last; lines += (*__first != '\n' ? 0 : 1), ++__first) { - if (*__first == '\\') { - _InputIterator __begin = __first; - ++__begin; - - if (__begin != __last && *__begin == '\n') - ++__first; - else - break; - } else if (*__first == '\n' || !pp_isspace(*__first)) - break; - } - - return __first; - } -}; - -struct pp_skip_whitespaces { - int lines; - - template <typename _InputIterator> - _InputIterator operator()(_InputIterator __first, _InputIterator __last) { - lines = 0; - - for (; __first != __last; lines += (*__first != '\n' ? 0 : 1), ++__first) { - if (! pp_isspace(*__first)) - break; - } - - return __first; - } -}; - -struct pp_skip_comment_or_divop { - int lines; - - template <typename _InputIterator> - _InputIterator operator()(_InputIterator __first, _InputIterator __last) { - enum { - MAYBE_BEGIN, - BEGIN, - MAYBE_END, - END, - IN_COMMENT, - IN_CXX_COMMENT - } state(MAYBE_BEGIN); - - lines = 0; - - for (; __first != __last; lines += (*__first != '\n' ? 0 : 1), ++__first) { - switch (state) { - default: - assert(0); - break; - - case MAYBE_BEGIN: - if (*__first != '/') - return __first; - - state = BEGIN; - break; - - case BEGIN: - if (*__first == '*') - state = IN_COMMENT; - else if (*__first == '/') - state = IN_CXX_COMMENT; - else - return __first; - break; - - case IN_COMMENT: - if (*__first == '*') - state = MAYBE_END; - break; - - case IN_CXX_COMMENT: - if (*__first == '\n') - return __first; - break; - - case MAYBE_END: - if (*__first == '/') - state = END; - else if (*__first != '*') - state = IN_COMMENT; - break; - - case END: - return __first; - } - } - - return __first; - } -}; - -struct pp_skip_identifier { - int lines; - - template <typename _InputIterator> - _InputIterator operator()(_InputIterator __first, _InputIterator __last) { - lines = 0; - - for (; __first != __last; lines += (*__first != '\n' ? 0 : 1), ++__first) { - if (! pp_isalnum(*__first) && *__first != '_') - break; - } - - return __first; - } -}; - -struct pp_skip_number { - int lines; - - template <typename _InputIterator> - _InputIterator operator()(_InputIterator __first, _InputIterator __last) { - lines = 0; - - for (; __first != __last; lines += (*__first != '\n' ? 0 : 1), ++__first) { - if (! pp_isalnum(*__first) && *__first != '.') - break; - } - - return __first; - } -}; - -struct pp_skip_string_literal { - int lines; - - template <typename _InputIterator> - _InputIterator operator()(_InputIterator __first, _InputIterator __last) { - enum { - BEGIN, - IN_STRING, - QUOTE, - END - } state(BEGIN); - - lines = 0; - - for (; __first != __last; lines += (*__first != '\n' ? 0 : 1), ++__first) { - switch (state) { - default: - assert(0); - break; - - case BEGIN: - if (*__first != '\"') - return __first; - state = IN_STRING; - break; - - case IN_STRING: - assert(*__first != '\n'); - - if (*__first == '\"') - state = END; - else if (*__first == '\\') - state = QUOTE; - break; - - case QUOTE: - state = IN_STRING; - break; - - case END: - return __first; - } - } - - return __first; - } -}; - -struct pp_skip_char_literal { - int lines; - - template <typename _InputIterator> - _InputIterator operator()(_InputIterator __first, _InputIterator __last) { - enum { - BEGIN, - IN_STRING, - QUOTE, - END - } state(BEGIN); - - lines = 0; - - for (; state != END && __first != __last; lines += (*__first != '\n' ? 0 : 1), ++__first) { - switch (state) { - default: - assert(0); - break; - - case BEGIN: - if (*__first != '\'') - return __first; - state = IN_STRING; - break; - - case IN_STRING: - assert(*__first != '\n'); - - if (*__first == '\'') - state = END; - else if (*__first == '\\') - state = QUOTE; - break; - - case QUOTE: - state = IN_STRING; - break; - } - } - - return __first; - } -}; - -struct pp_skip_argument { - pp_skip_identifier skip_number; - pp_skip_identifier skip_identifier; - pp_skip_string_literal skip_string_literal; - pp_skip_char_literal skip_char_literal; - pp_skip_comment_or_divop skip_comment_or_divop; - int lines; - - template <typename _InputIterator> - _InputIterator operator()(_InputIterator __first, _InputIterator __last) { - int depth = 0; - lines = 0; - - while (__first != __last) { - if (!depth && (*__first == ')' || *__first == ',')) - break; - else if (*__first == '(') - ++depth, ++__first; - else if (*__first == ')') - --depth, ++__first; - else if (*__first == '\"') { - __first = skip_string_literal(__first, __last); - lines += skip_string_literal.lines; - } else if (*__first == '\'') { - __first = skip_char_literal(__first, __last); - lines += skip_char_literal.lines; - } else if (*__first == '/') { - __first = skip_comment_or_divop(__first, __last); - lines += skip_comment_or_divop.lines; - } else if (pp_isalpha(*__first) || *__first == '_') { - __first = skip_identifier(__first, __last); - lines += skip_identifier.lines; - } else if (pp_isdigit(*__first)) { - __first = skip_number(__first, __last); - lines += skip_number.lines; - } else if (*__first == '\n') { - ++__first; - ++lines; - } else - ++__first; - } - - return __first; - } -}; - -} // namespace rpp - -#endif // PP_SCANNER_H - -// kate: space-indent on; indent-width 2; replace-tabs on; diff --git a/sources/shiboken2/ApiExtractor/parser/rpp/pp-string.h b/sources/shiboken2/ApiExtractor/parser/rpp/pp-string.h deleted file mode 100644 index 25db0389a..000000000 --- a/sources/shiboken2/ApiExtractor/parser/rpp/pp-string.h +++ /dev/null @@ -1,112 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef PP_STRING_H -#define PP_STRING_H - -namespace rpp -{ - -template <typename _CharT> -class pp_string -{ - typedef std::char_traits<_CharT> traits_type; - typedef std::size_t size_type; - - _CharT const *_M_begin; - std::size_t _M_size; - -public: - inline pp_string(): - _M_begin(0), _M_size(0) {} - - explicit pp_string(std::string const &__s): - _M_begin(__s.c_str()), _M_size(__s.size()) {} - - inline pp_string(_CharT const *__begin, std::size_t __size): - _M_begin(__begin), _M_size(__size) {} - - inline _CharT const *begin() const { - return _M_begin; - } - inline _CharT const *end() const { - return _M_begin + _M_size; - } - - inline _CharT at(std::size_t index) const { - return _M_begin [index]; - } - - inline std::size_t size() const { - return _M_size; - } - - inline int compare(pp_string const &__other) const { - size_type const __size = this->size(); - size_type const __osize = __other.size(); - size_type const __len = std::min(__size, __osize); - - int __r = traits_type::compare(_M_begin, __other._M_begin, __len); - if (!__r) - __r = (int)(__size - __osize); - - return __r; - } - - inline bool operator == (pp_string const &__other) const { - return compare(__other) == 0; - } - - inline bool operator != (pp_string const &__other) const { - return compare(__other) != 0; - } - - inline bool operator < (pp_string const &__other) const { - return compare(__other) < 0; - } - - inline bool operator == (char const *s) const { - std::size_t n = strlen(s); - - if (n != _M_size) - return false; - - return ! strncmp(_M_begin, s, n); - } - - inline bool operator != (char const *s) const { - return ! operator == (s); - } -}; - -} // namespace rpp - -#endif // PP_STRING_H - -// kate: space-indent on; indent-width 2; replace-tabs on; diff --git a/sources/shiboken2/ApiExtractor/parser/rpp/pp-symbol.h b/sources/shiboken2/ApiExtractor/parser/rpp/pp-symbol.h deleted file mode 100644 index 9b06d2643..000000000 --- a/sources/shiboken2/ApiExtractor/parser/rpp/pp-symbol.h +++ /dev/null @@ -1,97 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef PP_SYMBOL_H -#define PP_SYMBOL_H - -#include <cassert> -#include <iterator> -#include "pp-fwd.h" -#include "parser/rxx_allocator.h" - -namespace rpp -{ - -class pp_symbol -{ - static rxx_allocator<char> &allocator_instance() { - static rxx_allocator<char>__allocator; - return __allocator; - } - static rxx_allocator<pp_fast_string> &ppfs_allocator_instance () - { - static rxx_allocator<pp_fast_string>__ppfs_allocator; - return __ppfs_allocator; - } - -public: - static int &N() { - static int __N; - return __N; - } - - static pp_fast_string const *get(char const *__data, std::size_t __size) { - ++N(); - char *data = allocator_instance().allocate(__size + 1); - memcpy(data, __data, __size); - data[__size] = '\0'; - - pp_fast_string *where = ppfs_allocator_instance ().allocate (sizeof (pp_fast_string)); - return new(where) pp_fast_string(data, __size); - } - - template <typename _InputIterator> - static pp_fast_string const *get(_InputIterator __first, _InputIterator __last) { - ++N(); - std::ptrdiff_t __size; -#if defined(__SUNPRO_CC) - std::distance(__first, __last, __size); -#else - __size = std::distance(__first, __last); -#endif - assert(__size >= 0 && __size < 512); - - char *data = allocator_instance().allocate(__size + 1); - std::copy(__first, __last, data); - data[__size] = '\0'; - - pp_fast_string *where = ppfs_allocator_instance ().allocate (sizeof (pp_fast_string)); - return new(where) pp_fast_string(data, __size); - } - - static pp_fast_string const *get(std::string const &__s) { - return get(__s.c_str(), __s.size()); - } -}; - -} // namespace rpp - -#endif // PP_SYMBOL_H - -// kate: space-indent on; indent-width 2; replace-tabs on; diff --git a/sources/shiboken2/ApiExtractor/parser/rpp/pp.h b/sources/shiboken2/ApiExtractor/parser/rpp/pp.h deleted file mode 100644 index dfeeac432..000000000 --- a/sources/shiboken2/ApiExtractor/parser/rpp/pp.h +++ /dev/null @@ -1,96 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef PP_H -#define PP_H - -#if defined(_WIN64) || defined(WIN64) || defined(__WIN64__) \ - || defined(_WIN32) || defined(WIN32) || defined(__WIN32__) -# define PP_OS_WIN -#endif - -#include <set> -#include <map> -#include <vector> -#include <string> -#include <iterator> -#include <iostream> -#include <cassert> -#include <cctype> -#include <cstdio> - -#include <fcntl.h> - -#ifdef HAVE_MMAP -# include <sys/mman.h> -#endif - -#include <sys/stat.h> -#include <sys/types.h> - -#if (_MSC_VER >= 1400) -# define FILENO _fileno -#else -# define FILENO fileno -#endif - -#if defined (PP_OS_WIN) -# define PATH_SEPARATOR '\\' -#else -# define PATH_SEPARATOR '/' -#endif - -#if defined (RPP_JAMBI) -# include "parser/rxx_allocator.h" -#else -# include "parser/rpp-allocator.h" -#endif - -#if defined (_MSC_VER) -# define pp_snprintf _snprintf -#else -# define pp_snprintf snprintf -#endif - -#include "pp-fwd.h" -#include "pp-cctype.h" -#include "pp-string.h" -#include "pp-symbol.h" -#include "pp-internal.h" -#include "pp-iterator.h" -#include "pp-macro.h" -#include "pp-environment.h" -#include "pp-scanner.h" -#include "pp-macro-expander.h" -#include "pp-engine.h" -#include "pp-engine-bits.h" - -#endif // PP_H - -// kate: space-indent on; indent-width 2; replace-tabs on; diff --git a/sources/shiboken2/ApiExtractor/parser/rpp/preprocessor.cpp b/sources/shiboken2/ApiExtractor/parser/rpp/preprocessor.cpp deleted file mode 100644 index 315343321..000000000 --- a/sources/shiboken2/ApiExtractor/parser/rpp/preprocessor.cpp +++ /dev/null @@ -1,164 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2005 Harald Fernengel <harry@kdevelop.org> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "preprocessor.h" - -#include <string> -#include <cstdio> - -// register callback for include hooks -static void includeFileHook(const std::string &, const std::string &, FILE *); - -#define PP_HOOK_ON_FILE_INCLUDED(A, B, C) includeFileHook(A, B, C) -#include "pp.h" - -using namespace rpp; - -#include <QtCore/QtCore> - -class PreprocessorPrivate -{ -public: - QByteArray result; - pp_environment env; - QStringList includePaths; - - void initPP(pp &proc) { - foreach(QString path, includePaths) - proc.push_include_path(path.toStdString()); - } -}; - -QHash<QString, QStringList> includedFiles; - -void includeFileHook(const std::string &fileName, const std::string &filePath, FILE *) -{ - includedFiles[QString::fromStdString(fileName)].append(QString::fromStdString(filePath)); -} - -Preprocessor::Preprocessor() -{ - d = new PreprocessorPrivate; - includedFiles.clear(); -} - -Preprocessor::~Preprocessor() -{ - delete d; -} - -void Preprocessor::processFile(const QString &fileName) -{ - pp proc(d->env); - d->initPP(proc); - - d->result.reserve(d->result.size() + 20 * 1024); - - d->result += "# 1 \"" + fileName.toLatin1() + "\"\n"; // ### REMOVE ME - proc.file(fileName.toLocal8Bit().constData(), std::back_inserter(d->result)); -} - -void Preprocessor::processString(const QByteArray &str) -{ - pp proc(d->env); - d->initPP(proc); - - proc(str.begin(), str.end(), std::back_inserter(d->result)); -} - -QByteArray Preprocessor::result() const -{ - return d->result; -} - -void Preprocessor::addIncludePaths(const QStringList &includePaths) -{ - d->includePaths += includePaths; -} - -QStringList Preprocessor::macroNames() const -{ - QStringList macros; - - pp_environment::const_iterator it = d->env.first_macro(); - while (it != d->env.last_macro()) { - const pp_macro *m = *it; - macros += QString::fromLatin1(m->name->begin(), m->name->size()); - ++it; - } - - return macros; -} - -QList<Preprocessor::MacroItem> Preprocessor::macros() const -{ - QList<MacroItem> items; - - pp_environment::const_iterator it = d->env.first_macro(); - while (it != d->env.last_macro()) { - const pp_macro *m = *it; - MacroItem item; - item.name = QString::fromLatin1(m->name->begin(), m->name->size()); - item.definition = QString::fromLatin1(m->definition->begin(), - m->definition->size()); - for (size_t i = 0; i < m->formals.size(); ++i) { - item.parameters += QString::fromLatin1(m->formals[i]->begin(), - m->formals[i]->size()); - } - item.isFunctionLike = m->function_like; - -#ifdef PP_WITH_MACRO_POSITION - item.fileName = QString::fromLatin1(m->file->begin(), m->file->size()); -#endif - items += item; - - ++it; - } - - return items; -} - -/* -int main() -{ - Preprocessor pp; - - QStringList paths; - paths << "/usr/include"; - pp.addIncludePaths(paths); - - pp.processFile("pp-configuration"); - pp.processFile("/usr/include/stdio.h"); - - qDebug() << pp.result(); - - return 0; -} -*/ - diff --git a/sources/shiboken2/ApiExtractor/parser/rpp/preprocessor.h b/sources/shiboken2/ApiExtractor/parser/rpp/preprocessor.h deleted file mode 100644 index 7d00a5d09..000000000 --- a/sources/shiboken2/ApiExtractor/parser/rpp/preprocessor.h +++ /dev/null @@ -1,70 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2005 Harald Fernengel <harry@kdevelop.org> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef PREPROCESSOR_H -#define PREPROCESSOR_H - -#include <QtCore/qglobal.h> -#include <QtCore/qstring.h> -#include <QtCore/qstringlist.h> - -class PreprocessorPrivate; - -class Preprocessor -{ -public: - Preprocessor(); - ~Preprocessor(); - - void processFile(const QString &fileName); - void processString(const QByteArray &str); - - void addIncludePaths(const QStringList &includePaths); - - QByteArray result() const; - - QStringList macroNames() const; - - struct MacroItem { - QString name; - QStringList parameters; - QString definition; - bool isFunctionLike; -#ifdef PP_WITH_MACRO_POSITION - QString fileName; -#endif - }; - QList<MacroItem> macros() const; - -private: - Q_DISABLE_COPY(Preprocessor) - PreprocessorPrivate *d; -}; - -#endif diff --git a/sources/shiboken2/ApiExtractor/parser/rxx_allocator.h b/sources/shiboken2/ApiExtractor/parser/rxx_allocator.h deleted file mode 100644 index 8325edbdf..000000000 --- a/sources/shiboken2/ApiExtractor/parser/rxx_allocator.h +++ /dev/null @@ -1,146 +0,0 @@ -/* This file is part of KDevelop - Copyright 2002-2005 Roberto Raggi <roberto@kdevelop.org> - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License version 2 as published by the Free Software Foundation. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*/ - -#ifndef RXX_ALLOCATOR_H -#define RXX_ALLOCATOR_H - -#include <cstddef> -#include <cstdlib> -#include <string.h> -#include <memory> - -// Stride calculation -template <typename T> -struct Tchar { - T t; - char c; -}; - -#define strideof(T) \ - ((sizeof(Tchar<T>) > sizeof(T)) ? \ - sizeof(Tchar<T>)-sizeof(T) : sizeof(T)) - - -/**The allocator which uses fixed size blocks for allocation of its elements. -Block size is currently 64k, allocated space is not reclaimed, -if the size of the element being allocated extends the amount of free -memory in the block then a new block is allocated. - -The allocator supports standard c++ library interface but does not -make use of allocation hints. -*/ -template <class _Tp> class rxx_allocator { -public: - typedef _Tp value_type; - typedef _Tp* pointer; - typedef const _Tp* const_pointer; - typedef _Tp& reference; - typedef const _Tp& const_reference; - typedef std::size_t size_type; - typedef std::ptrdiff_t difference_type; - - static const size_type max_block_count = size_type(-1); - static const size_type _S_block_size = 1 << 16; // 64K - - rxx_allocator() { - init(); - } - - rxx_allocator(const rxx_allocator &/*__o*/) { - init(); - } - - ~rxx_allocator() { - for (size_type index = 0; index < _M_block_index + 1; ++index) - delete[] _M_storage[index]; - - ::free(_M_storage); - } - - pointer address(reference __val) { return &__val; } - const_pointer address(const_reference __val) const { return &__val; } - - /**Allocates @p __n elements continuosly in the pool. Warning! no - check is done to check if the size of those @p __n elements - fit into the block. You should assure you do not allocate more - than the size of a block.*/ - pointer allocate(size_type __n, const void* = 0) { - const size_type bytes = __n * sizeof(_Tp); - - if (_M_current_block == 0 - || _S_block_size < _M_current_index + bytes) - { - ++_M_block_index; - - _M_storage = reinterpret_cast<char**> - (::realloc(_M_storage, sizeof(char*) * (1 + _M_block_index))); - - _M_current_block = _M_storage[_M_block_index] = reinterpret_cast<char*> - (new char[_S_block_size]); - - ::memset(_M_current_block, 0, _S_block_size); - _M_current_index = 0; - } - - pointer p = reinterpret_cast<pointer> - (_M_current_block + _M_current_index); - - _M_current_index += bytes; - - return p; - } - - pointer allocate(size_type __n, size_type stride, const void* = 0) { - if (reinterpret_cast<size_type>(_M_current_block + _M_current_index) % stride > 0) - _M_current_index += stride - reinterpret_cast<size_type>(_M_current_block + _M_current_index) % stride; - return allocate(__n); - } - - /**Deallocate does nothing in this implementation.*/ - void deallocate(pointer /*__p*/, size_type /*__n*/) {} - - size_type max_size() const { return size_type(-1) / sizeof(_Tp); } - - void construct(pointer __p, const_reference __val) { new (__p) _Tp(__val); } - void destroy(pointer __p) { __p->~_Tp(); } - - template <class _Tp1> struct rebind { - typedef rxx_allocator<_Tp1> other; - }; - -private: - - void init() - { - _M_block_index = max_block_count; - _M_current_index = 0; - _M_storage = 0; - _M_current_block = 0; - } - - template <class _Tp1> rxx_allocator(const rxx_allocator<_Tp1> &__o) {} - -private: - size_type _M_block_index; - size_type _M_current_index; - char *_M_current_block; - char **_M_storage; -}; - -#endif // RXX_ALLOCATOR_H - diff --git a/sources/shiboken2/ApiExtractor/parser/smallobject.cpp b/sources/shiboken2/ApiExtractor/parser/smallobject.cpp deleted file mode 100644 index 9cee247e0..000000000 --- a/sources/shiboken2/ApiExtractor/parser/smallobject.cpp +++ /dev/null @@ -1,33 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#include "smallobject.h" - -// kate: space-indent on; indent-width 2; replace-tabs on; diff --git a/sources/shiboken2/ApiExtractor/parser/smallobject.h b/sources/shiboken2/ApiExtractor/parser/smallobject.h deleted file mode 100644 index 99e4ea44a..000000000 --- a/sources/shiboken2/ApiExtractor/parser/smallobject.h +++ /dev/null @@ -1,58 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#ifndef SMALLOBJECT_H -#define SMALLOBJECT_H - -#include "rxx_allocator.h" -#include <cstring> - -class pool -{ - rxx_allocator<char> __alloc; - -public: - inline void *allocate(std::size_t __size); - inline void *allocate(std::size_t __size, std::size_t __stride); -}; - -inline void *pool::allocate(std::size_t __size) -{ - return __alloc.allocate(__size); -} - -inline void *pool::allocate(std::size_t __size, std::size_t __stride) -{ - return __alloc.allocate(__size, __stride); -} - -#endif - -// kate: space-indent on; indent-width 2; replace-tabs on; diff --git a/sources/shiboken2/ApiExtractor/parser/symbol.h b/sources/shiboken2/ApiExtractor/parser/symbol.h deleted file mode 100644 index 588653846..000000000 --- a/sources/shiboken2/ApiExtractor/parser/symbol.h +++ /dev/null @@ -1,127 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#ifndef SYMBOL_H -#define SYMBOL_H - -#include <QtCore/QString> -#include <cstring> - -#include <QtCore/QHash> -#include <QtCore/QPair> - -struct NameSymbol -{ - const char *data; - std::size_t count; - - inline QString as_string() const - { - return QString::fromUtf8(data, (int) count); - } - - inline bool operator == (const NameSymbol &other) const - { - return count == other.count - && !std::strncmp(data, other.data, count); - } - -protected: - inline NameSymbol() {} - inline NameSymbol(const char *d, std::size_t c) - : data(d), count(c) {} - -private: - void operator = (const NameSymbol &); - - friend class NameTable; -}; - -inline uint qHash(const NameSymbol &r) -{ - uint hash_value = 0; - - for (std::size_t i = 0; i < r.count; ++i) - hash_value = (hash_value << 5) - hash_value + r.data[i]; - - return hash_value; -} - -inline uint qHash(const QPair<const char*, std::size_t> &r) -{ - uint hash_value = 0; - - for (std::size_t i = 0; i < r.second; ++i) - hash_value = (hash_value << 5) - hash_value + r.first[i]; - - return hash_value; -} - -class NameTable -{ -public: - typedef QPair<const char *, std::size_t> KeyType; - typedef QHash<KeyType, NameSymbol*> ContainerType; - -public: - NameTable() {} - - ~NameTable() - { - qDeleteAll(_M_storage); - } - - inline const NameSymbol *findOrInsert(const char *str, std::size_t len) - { - KeyType key(str, len); - - NameSymbol *name = _M_storage.value(key); - if (!name) { - name = new NameSymbol(str, len); - _M_storage.insert(key, name); - } - - return name; - } - - inline std::size_t count() const { return _M_storage.size(); } - -private: - ContainerType _M_storage; - -private: - NameTable(const NameTable &other); - void operator=(const NameTable &other); -}; - -#endif // SYMBOL_H - -// kate: space-indent on; indent-width 2; replace-tabs on; - diff --git a/sources/shiboken2/ApiExtractor/parser/tokens.cpp b/sources/shiboken2/ApiExtractor/parser/tokens.cpp deleted file mode 100644 index eace3c9fa..000000000 --- a/sources/shiboken2/ApiExtractor/parser/tokens.cpp +++ /dev/null @@ -1,256 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#include <QtCore/qglobal.h> - -#include "tokens.h" - -static char const * const _S_token_names[] = { - "K_DCOP", - "Q_OBJECT", - "Q_PROPERTY", - "__attribute__", - "__typeof", - "and", - "and_eq", - "arrow", - "asm", - "assign", - "auto", - "bitand", - "bitor", - "bool", - "break", - "case", - "catch", - "char", - "char_literal", - "class", - "comment", - "compl", - "concat", - "const", - "const_cast", - "continue", - "decr", - "default", - "delete", - "do", - "double", - "dynamic_cast", - "ellipsis", - "else", - "emit", - "enum", - "eq", - "explicit", - "export", - "extern", - "false", - "float", - "for", - "friend", - "geq", - "goto", - "identifier", - "if", - "incr", - "inline", - "int", - "k_dcop", - "k_dcop_signals", - "leq", - "long", - "mutable", - "namespace", - "new", - "noexcept", - "not", - "not_eq", - "number_literal", - "operator", - "or", - "or_eq", - "preproc", - "private", - "protected", - "ptrmem", - "public", - "register", - "reinterpret_cast", - "return", - "scope", - "shift", - "short", - "signals", - "signed", - "sizeof", - "slots", - "static", - "static_cast", - "string_literal", - "struct", - "switch", - "template", - "this", - "throw", - "true", - "try", - "typedef", - "typeid", - "typename", - "union", - "unsigned", - "using", - "virtual", - "void", - "volatile", - "wchar_t", - "while", - "whitespaces", - "xor", - "xor_eq", - "Q_ENUMS", - "Q_ENUM" -}; - -static char _S_printable[][2] = { - { char(32), '\0' }, - { char(33), '\0' }, - { char(34), '\0' }, - { char(35), '\0' }, - { char(36), '\0' }, - { char(37), '\0' }, - { char(38), '\0' }, - { char(39), '\0' }, - { char(40), '\0' }, - { char(41), '\0' }, - { char(42), '\0' }, - { char(43), '\0' }, - { char(44), '\0' }, - { char(45), '\0' }, - { char(46), '\0' }, - { char(47), '\0' }, - { char(48), '\0' }, - { char(49), '\0' }, - { char(50), '\0' }, - { char(51), '\0' }, - { char(52), '\0' }, - { char(53), '\0' }, - { char(54), '\0' }, - { char(55), '\0' }, - { char(56), '\0' }, - { char(57), '\0' }, - { char(58), '\0' }, - { char(59), '\0' }, - { char(60), '\0' }, - { char(61), '\0' }, - { char(62), '\0' }, - { char(63), '\0' }, - { char(64), '\0' }, - { char(65), '\0' }, - { char(66), '\0' }, - { char(67), '\0' }, - { char(68), '\0' }, - { char(69), '\0' }, - { char(70), '\0' }, - { char(71), '\0' }, - { char(72), '\0' }, - { char(73), '\0' }, - { char(74), '\0' }, - { char(75), '\0' }, - { char(76), '\0' }, - { char(77), '\0' }, - { char(78), '\0' }, - { char(79), '\0' }, - { char(80), '\0' }, - { char(81), '\0' }, - { char(82), '\0' }, - { char(83), '\0' }, - { char(84), '\0' }, - { char(85), '\0' }, - { char(86), '\0' }, - { char(87), '\0' }, - { char(88), '\0' }, - { char(89), '\0' }, - { char(90), '\0' }, - { char(91), '\0' }, - { char(92), '\0' }, - { char(93), '\0' }, - { char(94), '\0' }, - { char(95), '\0' }, - { char(96), '\0' }, - { char(97), '\0' }, - { char(98), '\0' }, - { char(99), '\0' }, - { char(100), '\0' }, - { char(101), '\0' }, - { char(102), '\0' }, - { char(103), '\0' }, - { char(104), '\0' }, - { char(105), '\0' }, - { char(106), '\0' }, - { char(107), '\0' }, - { char(108), '\0' }, - { char(109), '\0' }, - { char(110), '\0' }, - { char(111), '\0' }, - { char(112), '\0' }, - { char(113), '\0' }, - { char(114), '\0' }, - { char(115), '\0' }, - { char(116), '\0' }, - { char(117), '\0' }, - { char(118), '\0' }, - { char(119), '\0' }, - { char(120), '\0' }, - { char(121), '\0' }, - { char(122), '\0' }, - { char(123), '\0' }, - { char(124), '\0' }, - { char(125), '\0' }, - { char(126), '\0' }, - { char(127), '\0' }, -}; - -char const *token_name(int token) -{ - if (token == 0) - return "eof"; - else if (token >= 32 && token <= 127) - return _S_printable[token - 32]; - else if (token >= 1000) - return _S_token_names[token - 1000]; - - Q_ASSERT(0); - return 0; -} - -// kate: space-indent on; indent-width 2; replace-tabs on; diff --git a/sources/shiboken2/ApiExtractor/parser/tokens.h b/sources/shiboken2/ApiExtractor/parser/tokens.h deleted file mode 100644 index 46ec96e74..000000000 --- a/sources/shiboken2/ApiExtractor/parser/tokens.h +++ /dev/null @@ -1,152 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#ifndef TOKENS_H -#define TOKENS_H - -enum TOKEN_KIND { - Token_EOF = 0, - - Token_K_DCOP = 1000, - Token_Q_OBJECT, - Token_Q_PROPERTY, - Token___attribute__, - Token___typeof, - Token_and, - Token_and_eq, - Token_arrow, - Token_asm, - Token_assign, - Token_auto, - Token_bitand, - Token_bitor, - Token_bool, - Token_break, - Token_case, - Token_catch, - Token_char, - Token_char_literal, - Token_class, - Token_comment, - Token_compl, - Token_concat, - Token_const, - Token_const_cast, - Token_continue, - Token_decr, - Token_default, - Token_delete, - Token_do, - Token_double, - Token_dynamic_cast, - Token_ellipsis, - Token_else, - Token_emit, - Token_enum, - Token_eq, - Token_explicit, - Token_export, - Token_extern, - Token_false, - Token_float, - Token_for, - Token_friend, - Token_geq, - Token_goto, - Token_identifier, - Token_if, - Token_incr, - Token_inline, - Token_int, - Token_k_dcop, - Token_k_dcop_signals, - Token_leq, - Token_long, - Token_mutable, - Token_namespace, - Token_new, - Token_noexcept, - Token_not, - Token_not_eq, - Token_number_literal, - Token_operator, - Token_or, - Token_or_eq, - Token_preproc, - Token_private, - Token_protected, - Token_ptrmem, - Token_public, - Token_register, - Token_reinterpret_cast, - Token_return, - Token_scope, - Token_shift, - Token_short, - Token_signals, - Token_signed, - Token_sizeof, - Token_slots, - Token_static, - Token_static_cast, - Token_string_literal, - Token_struct, - Token_switch, - Token_template, - Token_this, - Token_throw, - Token_true, - Token_try, - Token_typedef, - Token_typeid, - Token_typename, - Token_union, - Token_unsigned, - Token_using, - Token_virtual, - Token_void, - Token_volatile, - Token_wchar_t, - Token_while, - Token_whitespaces, - Token_xor, - Token_xor_eq, - Token_Q_ENUMS, - Token_Q_ENUM, - Token_Q_INVOKABLE, - - TOKEN_KIND_COUNT -}; - -char const *token_name(int token); - -#endif - -// kate: space-indent on; indent-width 2; replace-tabs on; diff --git a/sources/shiboken2/ApiExtractor/parser/type_compiler.cpp b/sources/shiboken2/ApiExtractor/parser/type_compiler.cpp deleted file mode 100644 index c08f210fa..000000000 --- a/sources/shiboken2/ApiExtractor/parser/type_compiler.cpp +++ /dev/null @@ -1,134 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ - - -#include "type_compiler.h" -#include "name_compiler.h" -#include "lexer.h" -#include "symbol.h" -#include "tokens.h" -#include "binder.h" - -#include <QtCore/QString> - -TypeCompiler::TypeCompiler(Binder *binder) - : _M_binder(binder), _M_token_stream(binder->tokenStream()) -{ -} - -void TypeCompiler::run(TypeSpecifierAST *node) -{ - _M_type.clear(); - _M_cv.clear(); - - visit(node); - - if (node && node->cv) { - const ListNode<std::size_t> *it = node->cv->toFront(); - const ListNode<std::size_t> *end = it; - do { - int kind = _M_token_stream->kind(it->element); - if (!_M_cv.contains(kind)) - _M_cv.append(kind); - - it = it->next; - } while (it != end); - } -} - -void TypeCompiler::visitClassSpecifier(ClassSpecifierAST *node) -{ - visit(node->name); -} - -void TypeCompiler::visitEnumSpecifier(EnumSpecifierAST *node) -{ - visit(node->name); -} - -void TypeCompiler::visitElaboratedTypeSpecifier(ElaboratedTypeSpecifierAST *node) -{ - visit(node->name); -} - -void TypeCompiler::visitSimpleTypeSpecifier(SimpleTypeSpecifierAST *node) -{ - if (const ListNode<std::size_t> *it = node->integrals) { - it = it->toFront(); - const ListNode<std::size_t> *end = it; - QString current_item; - do { - std::size_t token = it->element; - current_item += QLatin1String(token_name(_M_token_stream->kind(token))); - current_item += QLatin1Char(' '); - it = it->next; - } while (it != end); - _M_type += current_item.trimmed(); - } else if (node->type_of) { - // ### implement me - _M_type += QLatin1String("typeof<...>"); - } - - visit(node->name); -} - -void TypeCompiler::visitName(NameAST *node) -{ - NameCompiler name_cc(_M_binder); - name_cc.run(node); - _M_type = name_cc.qualifiedName(); -} - -QStringList TypeCompiler::cvString() const -{ - QStringList lst; - - foreach (int q, cv()) { - if (q == Token_const) - lst.append(QLatin1String("const")); - else if (q == Token_volatile) - lst.append(QLatin1String("volatile")); - } - - return lst; -} - -bool TypeCompiler::isConstant() const -{ - return _M_cv.contains(Token_const); -} - -bool TypeCompiler::isVolatile() const -{ - return _M_cv.contains(Token_volatile); -} - -// kate: space-indent on; indent-width 2; replace-tabs on; diff --git a/sources/shiboken2/ApiExtractor/parser/type_compiler.h b/sources/shiboken2/ApiExtractor/parser/type_compiler.h deleted file mode 100644 index 6755b30c3..000000000 --- a/sources/shiboken2/ApiExtractor/parser/type_compiler.h +++ /dev/null @@ -1,76 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#ifndef TYPE_COMPILER_H -#define TYPE_COMPILER_H - -#include "default_visitor.h" - -#include <QtCore/QString> -#include <QtCore/QStringList> -#include <QtCore/QList> - -class TokenStream; -class Binder; - -class TypeCompiler: protected DefaultVisitor -{ -public: - TypeCompiler(Binder *binder); - - inline QStringList qualifiedName() const { return _M_type; } - inline QList<int> cv() const { return _M_cv; } - - bool isConstant() const; - bool isVolatile() const; - - QStringList cvString() const; - - void run(TypeSpecifierAST *node); - -protected: - virtual void visitClassSpecifier(ClassSpecifierAST *node); - virtual void visitEnumSpecifier(EnumSpecifierAST *node); - virtual void visitElaboratedTypeSpecifier(ElaboratedTypeSpecifierAST *node); - virtual void visitSimpleTypeSpecifier(SimpleTypeSpecifierAST *node); - - virtual void visitName(NameAST *node); - -private: - Binder *_M_binder; - TokenStream *_M_token_stream; - QStringList _M_type; - QList<int> _M_cv; -}; - -#endif // TYPE_COMPILER_H - -// kate: space-indent on; indent-width 2; replace-tabs on; - diff --git a/sources/shiboken2/ApiExtractor/parser/visitor.cpp b/sources/shiboken2/ApiExtractor/parser/visitor.cpp deleted file mode 100644 index e13e4acb3..000000000 --- a/sources/shiboken2/ApiExtractor/parser/visitor.cpp +++ /dev/null @@ -1,127 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#include "visitor.h" - -Visitor::visitor_fun_ptr Visitor::_S_table[AST::NODE_KIND_COUNT] = { - 0, - reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitAccessSpecifier), - reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitAsmDefinition), - reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitBaseClause), - reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitBaseSpecifier), - reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitBinaryExpression), - reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitCastExpression), - reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitClassMemberAccess), - reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitClassSpecifier), - reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitCompoundStatement), - reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitCondition), - reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitConditionalExpression), - reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitCppCastExpression), - reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitCtorInitializer), - reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitDeclarationStatement), - reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitDeclarator), - reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitDeleteExpression), - reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitDoStatement), - reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitElaboratedTypeSpecifier), - reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitEnumSpecifier), - reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitEnumerator), - reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitExceptionSpecification), - reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitExpressionOrDeclarationStatement), - reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitExpressionStatement), - reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitForStatement), - reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitFunctionCall), - reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitFunctionDefinition), - reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitIfStatement), - reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitIncrDecrExpression), - reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitInitDeclarator), - reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitInitializer), - reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitInitializerClause), - reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitLabeledStatement), - reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitLinkageBody), - reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitLinkageSpecification), - reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitMemInitializer), - reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitName), - reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitNamespace), - reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitNamespaceAliasDefinition), - reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitNewDeclarator), - reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitNewExpression), - reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitNewInitializer), - reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitNewTypeId), - reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitOperator), - reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitOperatorFunctionId), - reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitParameterDeclaration), - reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitParameterDeclarationClause), - reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitPostfixExpression), - reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitPrimaryExpression), - reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitPtrOperator), - reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitPtrToMember), - reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitReturnStatement), - reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitSimpleDeclaration), - reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitSimpleTypeSpecifier), - reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitSizeofExpression), - reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitStringLiteral), - reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitSubscriptExpression), - reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitSwitchStatement), - reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitTemplateArgument), - reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitTemplateDeclaration), - reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitTemplateParameter), - reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitThrowExpression), - reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitTranslationUnit), - reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitTryBlockStatement), - reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitTypeId), - reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitTypeIdentification), - reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitTypeParameter), - reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitTypedef), - reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitUnaryExpression), - reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitUnqualifiedName), - reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitUsing), - reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitUsingDirective), - reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitWhileStatement), - reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitWinDeclSpec), - reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitQProperty), - reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitForwardDeclarationSpecifier), - reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitQEnums) -}; - -Visitor::Visitor() -{ -} - -Visitor::~Visitor() -{ -} - -void Visitor::visit(AST *node) -{ - if (node) - (this->*_S_table[node->kind])(node); -} - -// kate: space-indent on; indent-width 2; replace-tabs on; diff --git a/sources/shiboken2/ApiExtractor/parser/visitor.h b/sources/shiboken2/ApiExtractor/parser/visitor.h deleted file mode 100644 index b1fbf8763..000000000 --- a/sources/shiboken2/ApiExtractor/parser/visitor.h +++ /dev/null @@ -1,145 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#ifndef VISITOR_H -#define VISITOR_H - -#include "ast.h" - -class Visitor -{ -public: - Visitor(); - virtual ~Visitor(); - - virtual void visit(AST *node); - -protected: - virtual void visitAccessSpecifier(AccessSpecifierAST *) {} - virtual void visitAsmDefinition(AsmDefinitionAST *) {} - virtual void visitBaseClause(BaseClauseAST *) {} - virtual void visitBaseSpecifier(BaseSpecifierAST *) {} - virtual void visitBinaryExpression(BinaryExpressionAST *) {} - virtual void visitCastExpression(CastExpressionAST *) {} - virtual void visitClassMemberAccess(ClassMemberAccessAST *) {} - virtual void visitClassSpecifier(ClassSpecifierAST *) {} - virtual void visitCompoundStatement(CompoundStatementAST *) {} - virtual void visitCondition(ConditionAST *) {} - virtual void visitConditionalExpression(ConditionalExpressionAST *) {} - virtual void visitCppCastExpression(CppCastExpressionAST *) {} - virtual void visitCtorInitializer(CtorInitializerAST *) {} - virtual void visitDeclarationStatement(DeclarationStatementAST *) {} - virtual void visitDeclarator(DeclaratorAST *) {} - virtual void visitDeleteExpression(DeleteExpressionAST *) {} - virtual void visitDoStatement(DoStatementAST *) {} - virtual void visitElaboratedTypeSpecifier(ElaboratedTypeSpecifierAST *) {} - virtual void visitEnumSpecifier(EnumSpecifierAST *) {} - virtual void visitEnumerator(EnumeratorAST *) {} - virtual void visitExceptionSpecification(ExceptionSpecificationAST *) {} - virtual void visitExpressionOrDeclarationStatement(ExpressionOrDeclarationStatementAST *) {} - virtual void visitExpressionStatement(ExpressionStatementAST *) {} - virtual void visitForStatement(ForStatementAST *) {} - virtual void visitFunctionCall(FunctionCallAST *) {} - virtual void visitFunctionDefinition(FunctionDefinitionAST *) {} - virtual void visitIfStatement(IfStatementAST *) {} - virtual void visitIncrDecrExpression(IncrDecrExpressionAST *) {} - virtual void visitInitDeclarator(InitDeclaratorAST *) {} - virtual void visitInitializer(InitializerAST *) {} - virtual void visitInitializerClause(InitializerClauseAST *) {} - virtual void visitLabeledStatement(LabeledStatementAST *) {} - virtual void visitLinkageBody(LinkageBodyAST *) {} - virtual void visitLinkageSpecification(LinkageSpecificationAST *) {} - virtual void visitMemInitializer(MemInitializerAST *) {} - virtual void visitName(NameAST *) {} - virtual void visitNamespace(NamespaceAST *) {} - virtual void visitNamespaceAliasDefinition(NamespaceAliasDefinitionAST *) {} - virtual void visitNewDeclarator(NewDeclaratorAST *) {} - virtual void visitNewExpression(NewExpressionAST *) {} - virtual void visitNewInitializer(NewInitializerAST *) {} - virtual void visitNewTypeId(NewTypeIdAST *) {} - virtual void visitOperator(OperatorAST *) {} - virtual void visitOperatorFunctionId(OperatorFunctionIdAST *) {} - virtual void visitParameterDeclaration(ParameterDeclarationAST *) {} - virtual void visitParameterDeclarationClause(ParameterDeclarationClauseAST *) {} - virtual void visitPostfixExpression(PostfixExpressionAST *) {} - virtual void visitPrimaryExpression(PrimaryExpressionAST *) {} - virtual void visitPtrOperator(PtrOperatorAST *) {} - virtual void visitPtrToMember(PtrToMemberAST *) {} - virtual void visitReturnStatement(ReturnStatementAST *) {} - virtual void visitSimpleDeclaration(SimpleDeclarationAST *) {} - virtual void visitSimpleTypeSpecifier(SimpleTypeSpecifierAST *) {} - virtual void visitSizeofExpression(SizeofExpressionAST *) {} - virtual void visitStringLiteral(StringLiteralAST *) {} - virtual void visitSubscriptExpression(SubscriptExpressionAST *) {} - virtual void visitSwitchStatement(SwitchStatementAST *) {} - virtual void visitTemplateArgument(TemplateArgumentAST *) {} - virtual void visitTemplateDeclaration(TemplateDeclarationAST *) {} - virtual void visitTemplateParameter(TemplateParameterAST *) {} - virtual void visitThrowExpression(ThrowExpressionAST *) {} - virtual void visitTranslationUnit(TranslationUnitAST *) {} - virtual void visitTryBlockStatement(TryBlockStatementAST *) {} - virtual void visitTypeId(TypeIdAST *) {} - virtual void visitTypeIdentification(TypeIdentificationAST *) {} - virtual void visitTypeParameter(TypeParameterAST *) {} - virtual void visitTypedef(TypedefAST *) {} - virtual void visitUnaryExpression(UnaryExpressionAST *) {} - virtual void visitUnqualifiedName(UnqualifiedNameAST *) {} - virtual void visitUsing(UsingAST *) {} - virtual void visitUsingDirective(UsingDirectiveAST *) {} - virtual void visitWhileStatement(WhileStatementAST *) {} - virtual void visitWinDeclSpec(WinDeclSpecAST *) {} - virtual void visitQProperty(QPropertyAST *) {} - virtual void visitForwardDeclarationSpecifier(ForwardDeclarationSpecifierAST *) {} - virtual void visitQEnums(QEnumsAST *) {} - -private: - typedef void (Visitor::*visitor_fun_ptr)(AST *); - static visitor_fun_ptr _S_table[]; -}; - -template <class _Tp> -void visitNodes(Visitor *v, const ListNode<_Tp> *nodes) -{ - if (!nodes) - return; - - const ListNode<_Tp> - *it = nodes->toFront(), - *end = it; - - do { - v->visit(it->element); - it = it->next; - } while (it != end); -} - -#endif // VISITOR_H - -// kate: space-indent on; indent-width 2; replace-tabs on; diff --git a/sources/shiboken2/ApiExtractor/qtdocparser.cpp b/sources/shiboken2/ApiExtractor/qtdocparser.cpp index f1421ff91..0ac87bd16 100644 --- a/sources/shiboken2/ApiExtractor/qtdocparser.cpp +++ b/sources/shiboken2/ApiExtractor/qtdocparser.cpp @@ -34,6 +34,7 @@ #include <QtXmlPatterns/QXmlQuery> #include <QtCore/QDir> #include <QtCore/QFile> +#include <QtCore/QTextStream> #include <QUrl> Documentation QtDocParser::retrieveModuleDocumentation() @@ -41,12 +42,50 @@ Documentation QtDocParser::retrieveModuleDocumentation() return retrieveModuleDocumentation(packageName()); } +static void formatFunctionArgTypeQuery(QTextStream &str, const AbstractMetaArgument *arg) +{ + const AbstractMetaType *metaType = arg->type(); + if (metaType->isConstant()) + str << "const " ; + switch (metaType->typeUsagePattern()) { + case AbstractMetaType::PrimitivePattern: + str << metaType->name(); + break; + case AbstractMetaType::FlagsPattern: { + // Modify qualified name "QFlags<Qt::AlignmentFlag>" with name "Alignment" + // to "Qt::Alignment" as seen by qdoc. + const FlagsTypeEntry *flagsEntry = static_cast<const FlagsTypeEntry *>(metaType->typeEntry()); + QString name = flagsEntry->qualifiedCppName(); + if (name.endsWith(QLatin1Char('>')) && name.startsWith(QLatin1String("QFlags<"))) { + const int lastColon = name.lastIndexOf(QLatin1Char(':')); + if (lastColon != -1) { + name.replace(lastColon + 1, name.size() - lastColon - 1, metaType->name()); + name.remove(0, 7); + } else { + name = metaType->name(); // QFlags<> of enum in global namespace + } + } + str << name; + } + break; + default: // Fully qualify enums (Qt::AlignmentFlag), nested classes, etc. + str << metaType->typeEntry()->qualifiedCppName(); + break; + } + + if (metaType->referenceType() == LValueReference) + str << " &"; + else if (metaType->referenceType() == RValueReference) + str << " &&"; + else if (metaType->indirections()) + str << ' ' << QByteArray(metaType->indirections(), '*'); +} + void QtDocParser::fillDocumentation(AbstractMetaClass* metaClass) { if (!metaClass) return; - QString scope = metaClass->name(); const AbstractMetaClass* context = metaClass->enclosingClass(); while(context) { if (context->enclosingClass() == 0) @@ -54,32 +93,35 @@ void QtDocParser::fillDocumentation(AbstractMetaClass* metaClass) context = context->enclosingClass(); } - QString filename = metaClass->qualifiedCppName().toLower(); - filename.replace(QLatin1String("::"), QLatin1String("-")); - QString sourceFile = documentationDataDirectory() + QLatin1Char('/') - + filename + QLatin1String(".xml"); - if (metaClass->enclosingClass()) - sourceFile.replace(QLatin1String("::"), QLatin1String("-")); + QString sourceFileRoot = documentationDataDirectory() + QLatin1Char('/') + + metaClass->qualifiedCppName().toLower(); + sourceFileRoot.replace(QLatin1String("::"), QLatin1String("-")); - if (!QFile::exists(sourceFile)) { + QFileInfo sourceFile(sourceFileRoot + QStringLiteral(".webxml")); + if (!sourceFile.exists()) + sourceFile.setFile(sourceFileRoot + QStringLiteral(".xml")); + if (!sourceFile.exists()) { qCWarning(lcShiboken).noquote().nospace() - << "Can't find qdoc3 file for class " << metaClass->name() << ", tried: " - << QDir::toNativeSeparators(sourceFile); + << "Can't find qdoc file for class " << metaClass->name() << ", tried: " + << QDir::toNativeSeparators(sourceFile.absoluteFilePath()); return; } QXmlQuery xquery; - xquery.setFocus(QUrl(sourceFile)); + const QString sourceFileName = sourceFile.absoluteFilePath(); + xquery.setFocus(QUrl::fromLocalFile(sourceFileName)); QString className = metaClass->name(); // Class/Namespace documentation - QString type = metaClass->isNamespace() ? QLatin1String("namespace") : QLatin1String("class"); - QString query = QLatin1String("/WebXML/document/") + type + QLatin1String("[@name=\"") - + className + QLatin1String("\"]/description"); + const QString classQuery = QLatin1String("/WebXML/document/") + + (metaClass->isNamespace() ? QLatin1String("namespace") : QLatin1String("class")) + + QLatin1String("[@name=\"") + className + QLatin1String("\"]"); + QString query = classQuery + QLatin1String("/description"); DocModificationList signedModifs, classModifs; - foreach (DocModification docModif, metaClass->typeEntry()->docModifications()) { + const DocModificationList &mods = metaClass->typeEntry()->docModifications(); + for (const DocModification &docModif : mods) { if (docModif.signature().isEmpty()) classModifs.append(docModif); else @@ -87,62 +129,49 @@ void QtDocParser::fillDocumentation(AbstractMetaClass* metaClass) } Documentation doc(getDocumentation(xquery, query, classModifs)); + if (doc.isEmpty()) + qCWarning(lcShiboken(), "%s", qPrintable(msgCannotFindDocumentation(sourceFileName, "class", className, query))); metaClass->setDocumentation(doc); //Functions Documentation - AbstractMetaFunctionList funcs = metaClass->functionsInTargetLang(); - foreach (AbstractMetaFunction *func, funcs) { - if (!func || func->isPrivate()) - continue; - - QString query = QLatin1String("/WebXML/document/") + type - + QLatin1String("[@name=\"") + className + QLatin1String("\"]"); + const AbstractMetaFunctionList &funcs = DocParser::documentableFunctions(metaClass); + for (AbstractMetaFunction *func : funcs) { + query.clear(); + QTextStream str(&query); + str << classQuery; // properties if (func->isPropertyReader() || func->isPropertyWriter() || func->isPropertyResetter()) { - query += QLatin1String("/property[@name=\"") + func->propertySpec()->name() - + QLatin1String("\"]"); + str << "/property[@name=\"" << func->propertySpec()->name() << "\"]"; } else { // normal methods - QString isConst = func->isConstant() ? QLatin1String("true") : QLatin1String("false"); - query += QLatin1String("/function[@name=\"") + func->originalName() - + QLatin1String("\" and count(parameter)=") - + QString::number(func->arguments().count()) - + QLatin1String(" and @const=\"") + isConst + QLatin1String("\"]"); - - int i = 1; - foreach (AbstractMetaArgument* arg, func->arguments()) { - QString type = arg->type()->name(); - - if (arg->type()->isConstant()) - type.prepend(QLatin1String("const ")); - - if (arg->type()->referenceType() == LValueReference) { - type += QLatin1String(" &"); - } else if (arg->type()->referenceType() == RValueReference) { - type += QLatin1String(" &&"); - } else if (arg->type()->indirections()) { - type += QLatin1Char(' '); - for (int j = 0, max = arg->type()->indirections(); j < max; ++j) - type += QLatin1Char('*'); - } - query += QLatin1String("/parameter[") + QString::number(i) - + QLatin1String("][@left=\"") + type + QLatin1String("\"]/.."); - ++i; + str << "/function[@name=\"" << func->originalName() << "\" and count(parameter)=" + << func->arguments().count() << " and @const=\"" + << (func->isConstant() ? "true" : "false") << "\"]"; + + const AbstractMetaArgumentList &arguments = func->arguments(); + for (int i = 0, size = arguments.size(); i < size; ++i) { + str << "/parameter[" << (i + 1) << "][@type=\""; + formatFunctionArgTypeQuery(str, arguments.at(i)); + str << "\"]/.."; } } - query += QLatin1String("/description"); + str << "/description"; DocModificationList funcModifs; - foreach (DocModification funcModif, signedModifs) { + for (const DocModification &funcModif : qAsConst(signedModifs)) { if (funcModif.signature() == func->minimalSignature()) funcModifs.append(funcModif); } doc.setValue(getDocumentation(xquery, query, funcModifs)); + if (doc.isEmpty()) { + qCWarning(lcShiboken(), "%s", + qPrintable(msgCannotFindDocumentation(sourceFileName, metaClass, func, query))); + } func->setDocumentation(doc); } #if 0 // Fields - AbstractMetaFieldList fields = metaClass->fields(); - foreach (AbstractMetaField *field, fields) { + const AbstractMetaFieldList &fields = metaClass->fields(); + for (AbstractMetaField *field : fields) { if (field->isPrivate()) return; @@ -152,13 +181,16 @@ void QtDocParser::fillDocumentation(AbstractMetaClass* metaClass) } #endif // Enums - AbstractMetaEnumList enums = metaClass->enums(); - foreach (AbstractMetaEnum *meta_enum, enums) { - QString query = QLatin1String("/WebXML/document/") + type - + QLatin1String("[@name=\"") - + className + QLatin1String("\"]/enum[@name=\"") - + meta_enum->name() + QLatin1String("\"]/description"); + const AbstractMetaEnumList &enums = metaClass->enums(); + for (AbstractMetaEnum *meta_enum : enums) { + query.clear(); + QTextStream(&query) << classQuery << "/enum[@name=\"" + << meta_enum->name() << "\"]/description"; doc.setValue(getDocumentation(xquery, query, DocModificationList())); + if (doc.isEmpty()) { + qCWarning(lcShiboken(), "%s", + qPrintable(msgCannotFindDocumentation(sourceFileName, metaClass, meta_enum, query))); + } meta_enum->setDocumentation(doc); } } @@ -172,9 +204,12 @@ Documentation QtDocParser::retrieveModuleDocumentation(const QString& name) QString sourceFile = documentationDataDirectory() + QLatin1Char('/') + moduleName.toLower() + QLatin1String(".xml"); + if (!QFile::exists(sourceFile)) + sourceFile = documentationDataDirectory() + QLatin1Char('/') + + moduleName.toLower() + QLatin1String("-module.webxml"); if (!QFile::exists(sourceFile)) { qCWarning(lcShiboken).noquote().nospace() - << "Can't find qdoc3 file for module " << name << ", tried: " + << "Can't find qdoc file for module " << name << ", tried: " << QDir::toNativeSeparators(sourceFile); return Documentation(); } @@ -184,5 +219,8 @@ Documentation QtDocParser::retrieveModuleDocumentation(const QString& name) // Module documentation QString query = QLatin1String("/WebXML/document/page[@name=\"") + moduleName + QLatin1String("\"]/description"); - return Documentation(getDocumentation(xquery, query, DocModificationList())); + const Documentation doc = getDocumentation(xquery, query, DocModificationList()); + if (doc.isEmpty()) + qCWarning(lcShiboken(), "%s", qPrintable(msgCannotFindDocumentation(sourceFile, "module", name, query))); + return doc; } diff --git a/sources/shiboken2/ApiExtractor/qtdocparser.h b/sources/shiboken2/ApiExtractor/qtdocparser.h index 04c491853..f6bd479cd 100644 --- a/sources/shiboken2/ApiExtractor/qtdocparser.h +++ b/sources/shiboken2/ApiExtractor/qtdocparser.h @@ -35,9 +35,9 @@ class QtDocParser : public DocParser { public: QtDocParser() {} - virtual void fillDocumentation(AbstractMetaClass* metaClass); - virtual Documentation retrieveModuleDocumentation(); - virtual Documentation retrieveModuleDocumentation(const QString& name); + void fillDocumentation(AbstractMetaClass* metaClass) override; + Documentation retrieveModuleDocumentation() override; + Documentation retrieveModuleDocumentation(const QString& name) override; }; #endif // QTDOCPARSER_H diff --git a/sources/shiboken2/ApiExtractor/reporthandler.cpp b/sources/shiboken2/ApiExtractor/reporthandler.cpp index 8abea42c6..bb3677772 100644 --- a/sources/shiboken2/ApiExtractor/reporthandler.cpp +++ b/sources/shiboken2/ApiExtractor/reporthandler.cpp @@ -52,6 +52,7 @@ static int m_suppressedCount = 0; static ReportHandler::DebugLevel m_debugLevel = ReportHandler::NoDebug; static QSet<QString> m_reportedWarnings; static QString m_progressBuffer; +static QString m_prefix; static int m_step_size = 0; static int m_step = -1; static int m_step_warning = 0; @@ -106,6 +107,11 @@ void ReportHandler::setSilent(bool silent) m_silent = silent; } +void ReportHandler::setPrefix(const QString &p) +{ + m_prefix = p; +} + void ReportHandler::messageOutput(QtMsgType type, const QMessageLogContext &context, const QString &text) { if (type == QtWarningMsg) { @@ -120,7 +126,11 @@ void ReportHandler::messageOutput(QtMsgType type, const QMessageLogContext &cont ++m_step_warning; m_reportedWarnings.insert(text); } - fprintf(stderr, "%s\n", qPrintable(qFormatLogMessage(type, context, text))); + QString message = m_prefix; + if (!message.isEmpty()) + message.append(QLatin1Char(' ')); + message.append(text); + fprintf(stderr, "%s\n", qPrintable(qFormatLogMessage(type, context, message))); } void ReportHandler::progress(const QString& str, ...) diff --git a/sources/shiboken2/ApiExtractor/reporthandler.h b/sources/shiboken2/ApiExtractor/reporthandler.h index 6896d6e86..a22e58d46 100644 --- a/sources/shiboken2/ApiExtractor/reporthandler.h +++ b/sources/shiboken2/ApiExtractor/reporthandler.h @@ -64,6 +64,8 @@ public: static bool isSilent(); static void setSilent(bool silent); + static void setPrefix(const QString &p); + private: static void messageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg); }; diff --git a/sources/shiboken2/ApiExtractor/tests/CMakeLists.txt b/sources/shiboken2/ApiExtractor/tests/CMakeLists.txt index 5429c1cb8..860a37d9d 100644 --- a/sources/shiboken2/ApiExtractor/tests/CMakeLists.txt +++ b/sources/shiboken2/ApiExtractor/tests/CMakeLists.txt @@ -16,6 +16,7 @@ macro(declare_test testname) ${apiextractor_SOURCE_DIR} ${Qt5Test_INCLUDE_DIRS} ) + link_directories(${APIEXTRACTOR_EXTRA_LINK_DIRECTORIES}) target_link_libraries(${testname} ${Qt5XmlPatterns_LIBRARIES} ${Qt5Test_LIBRARIES} diff --git a/sources/shiboken2/ApiExtractor/tests/testabstractmetaclass.cpp b/sources/shiboken2/ApiExtractor/tests/testabstractmetaclass.cpp index 028522159..9acbba675 100644 --- a/sources/shiboken2/ApiExtractor/tests/testabstractmetaclass.cpp +++ b/sources/shiboken2/ApiExtractor/tests/testabstractmetaclass.cpp @@ -57,7 +57,7 @@ void TestAbstractMetaClass::testClassNameUnderNamespace() AbstractMetaClassList classes = builder->classes(); QCOMPARE(classes.count(), 2); // 1 namespace + 1 class if (classes.first()->name() != QLatin1String("ClassName")) - classes.swap(0, 1); + qSwap(classes[0], classes[1]); QCOMPARE(classes[0]->name(), QLatin1String("ClassName")); QCOMPARE(classes[0]->qualifiedCppName(), QLatin1String("Namespace::ClassName")); @@ -71,7 +71,7 @@ void TestAbstractMetaClass::testClassNameUnderNamespace() AbstractMetaFunctionList ctors = classes[0]->queryFunctions(AbstractMetaClass::Constructors); QCOMPARE(ctors.size(), 2); if (ctors.first()->minimalSignature() != QLatin1String("ClassName()")) - ctors.swap(0, 1); + qSwap(ctors[0], ctors[1]); QCOMPARE(ctors[0]->arguments().size(), 0); QCOMPARE(ctors[0]->minimalSignature(), QLatin1String("ClassName()")); @@ -86,42 +86,66 @@ void TestAbstractMetaClass::testClassNameUnderNamespace() // QVERIFY(classes[0]->hasNonPrivateConstructor()); } +static AbstractMetaFunctionList virtualFunctions(const AbstractMetaClass *c) +{ + AbstractMetaFunctionList result; + const AbstractMetaFunctionList &functions = c->functions(); + for (AbstractMetaFunction *f : functions) { + if (f->isVirtual()) + result.append(f); + } + return result; +} + void TestAbstractMetaClass::testVirtualMethods() { - const char* cppCode ="\ - class A {\n\ - public:\n\ - virtual int pureVirtual() const = 0;\n\ - };\n\ - class B : public A {};\n\ - class C : public B {\n\ - public:\n\ - int pureVirtual() const { return 0; }\n\ - };\n"; - const char* xmlCode = "\ - <typesystem package=\"Foo\">\n\ - <primitive-type name='int'/>\n\ - <object-type name='A'/>\n\ - <object-type name='B'/>\n\ - <object-type name='C'/>\n\ - </typesystem>\n"; + const char cppCode[] =R"CPP( +class A { +public: + virtual int pureVirtual() const = 0; +}; +class B : public A {}; +class C : public B { +public: + int pureVirtual() const override { return 0; } +}; +class F final : public C { +public: + int pureVirtual() const final { return 1; } +}; +)CPP"; + + const char xmlCode[] = R"XML( +<typesystem package="Foo"> + <primitive-type name='int'/> + <object-type name='A'/> + <object-type name='B'/> + <object-type name='C'/> + <object-type name='F'/> +</typesystem> +)XML"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode)); QVERIFY(!builder.isNull()); AbstractMetaClassList classes = builder->classes(); - QCOMPARE(classes.count(), 3); + QCOMPARE(classes.count(), 4); AbstractMetaClass* a = AbstractMetaClass::findClass(classes, QLatin1String("A")); AbstractMetaClass* b = AbstractMetaClass::findClass(classes, QLatin1String("B")); AbstractMetaClass* c = AbstractMetaClass::findClass(classes, QLatin1String("C")); + const AbstractMetaClass *f = AbstractMetaClass::findClass(classes, QLatin1String("F")); + QVERIFY(f); AbstractMetaClass* no_class = 0; QCOMPARE(a->baseClass(), no_class); QCOMPARE(b->baseClass(), a); QCOMPARE(c->baseClass(), b); + QCOMPARE(f->baseClass(), c); QCOMPARE(a->functions().size(), 2); // default ctor + the pure virtual method QCOMPARE(b->functions().size(), 2); QCOMPARE(c->functions().size(), 2); + QCOMPARE(f->functions().size(), 2); + QVERIFY(f->attributes() & AbstractMetaAttributes::FinalCppClass); // implementing class, ownclass, declaringclass AbstractMetaFunction* ctorA = a->queryFunctions(AbstractMetaClass::Constructors).first(); @@ -137,17 +161,26 @@ void TestAbstractMetaClass::testVirtualMethods() QCOMPARE(ctorA->ownerClass(), a); QCOMPARE(ctorA->declaringClass(), a); - QCOMPARE(a->virtualFunctions().size(), 1); // Add a pureVirtualMethods method !? - QCOMPARE(b->virtualFunctions().size(), 1); - QCOMPARE(c->virtualFunctions().size(), 1); + const AbstractMetaFunctionList virtualFunctionsA = virtualFunctions(a); + const AbstractMetaFunctionList virtualFunctionsB = virtualFunctions(b); + const AbstractMetaFunctionList virtualFunctionsC = virtualFunctions(c); + const AbstractMetaFunctionList virtualFunctionsF = virtualFunctions(f); + QCOMPARE(virtualFunctionsA.size(), 1); // Add a pureVirtualMethods method !? + QCOMPARE(virtualFunctionsB.size(), 1); + QCOMPARE(virtualFunctionsC.size(), 1); + QCOMPARE(virtualFunctionsF.size(), 1); - AbstractMetaFunction* funcA = a->virtualFunctions().first(); - AbstractMetaFunction* funcB = b->virtualFunctions().first(); - AbstractMetaFunction* funcC = c->virtualFunctions().first(); + const AbstractMetaFunction* funcA = virtualFunctionsA.constFirst(); + const AbstractMetaFunction* funcB = virtualFunctionsB.constFirst(); + const AbstractMetaFunction* funcC = virtualFunctionsC.constFirst(); + const AbstractMetaFunction* funcF = virtualFunctionsF.constFirst(); QCOMPARE(funcA->ownerClass(), a); + QVERIFY(funcC->attributes() & AbstractMetaAttributes::VirtualCppMethod); QCOMPARE(funcB->ownerClass(), b); QCOMPARE(funcC->ownerClass(), c); + QVERIFY(funcC->attributes() & AbstractMetaAttributes::OverriddenCppMethod); + QVERIFY(funcF->attributes() & AbstractMetaAttributes::FinalCppMethod); QCOMPARE(funcA->declaringClass(), a); QCOMPARE(funcB->declaringClass(), a); @@ -361,7 +394,7 @@ void TestAbstractMetaClass::testClassDefaultConstructors() AbstractMetaFunctionList ctors = classA->queryFunctions(AbstractMetaClass::Constructors); QCOMPARE(ctors.size(), 2); if (ctors.first()->minimalSignature() != QLatin1String("A()")) - ctors.swap(0, 1); + qSwap(ctors[0], ctors[1]); QCOMPARE(ctors[0]->arguments().size(), 0); QCOMPARE(ctors[0]->minimalSignature(), QLatin1String("A()")); @@ -395,7 +428,7 @@ void TestAbstractMetaClass::testClassDefaultConstructors() ctors = classF->queryFunctions(AbstractMetaClass::Constructors); QCOMPARE(ctors.size(), 2); if (ctors.first()->minimalSignature() != QLatin1String("F(int,int)")) - ctors.swap(0, 1); + qSwap(ctors[0], ctors[1]); QCOMPARE(ctors[0]->arguments().size(), 2); QCOMPARE(ctors[0]->minimalSignature(), QLatin1String("F(int,int)")); @@ -428,7 +461,7 @@ void TestAbstractMetaClass::testClassInheritedDefaultConstructors() AbstractMetaFunctionList ctors = classA->queryFunctions(AbstractMetaClass::Constructors); QCOMPARE(ctors.size(), 2); if (ctors.first()->minimalSignature() != QLatin1String("A()")) - ctors.swap(0, 1); + qSwap(ctors[0], ctors[1]); QCOMPARE(ctors[0]->arguments().size(), 0); QCOMPARE(ctors[0]->minimalSignature(), QLatin1String("A()")); diff --git a/sources/shiboken2/ApiExtractor/tests/testaddfunction.cpp b/sources/shiboken2/ApiExtractor/tests/testaddfunction.cpp index 6e1da17ae..bcc5238bc 100644 --- a/sources/shiboken2/ApiExtractor/tests/testaddfunction.cpp +++ b/sources/shiboken2/ApiExtractor/tests/testaddfunction.cpp @@ -49,7 +49,7 @@ void TestAddFunction::testParsingFuncNameAndConstness() const char sig2[] = " _fu__nc_ ( type1, const type2, const Abc<int& , C<char*> * > * *, const type3* const ) const "; AddedFunction f2(QLatin1String(sig2), QLatin1String("const Abc<int& , C<char*> * > * *"), 0); QCOMPARE(f2.name(), QLatin1String("_fu__nc_")); - QList< AddedFunction::TypeInfo > args = f2.arguments(); + QVector< AddedFunction::TypeInfo > args = f2.arguments(); QCOMPARE(args.count(), 4); retval = f2.returnType(); QCOMPARE(retval.name, QLatin1String("Abc<int& , C<char*> * >")); @@ -423,8 +423,8 @@ void TestAddFunction::testAddFunctionOnTypedef() AbstractMetaClass* foo = AbstractMetaClass::findClass(classes, QLatin1String("FooInt")); QVERIFY(foo); QVERIFY(foo->hasNonPrivateConstructor()); - AbstractMetaFunctionList lst = foo->queryFunctions(AbstractMetaClass::Constructors); - foreach(AbstractMetaFunction* f, lst) + const AbstractMetaFunctionList &lst = foo->queryFunctions(AbstractMetaClass::Constructors); + for (const AbstractMetaFunction *f : lst) QVERIFY(f->signature().startsWith(f->name())); QCOMPARE(lst.size(), 2); const AbstractMetaFunction* method = foo->findFunction(QLatin1String("method")); diff --git a/sources/shiboken2/ApiExtractor/tests/testarrayargument.cpp b/sources/shiboken2/ApiExtractor/tests/testarrayargument.cpp index 5385c9140..cbeb216c9 100644 --- a/sources/shiboken2/ApiExtractor/tests/testarrayargument.cpp +++ b/sources/shiboken2/ApiExtractor/tests/testarrayargument.cpp @@ -58,6 +58,54 @@ void TestArrayArgument::testArrayArgumentWithSizeDefinedByInteger() QCOMPARE(arg->type()->arrayElementType()->name(), QLatin1String("double")); } +static QString functionMinimalSignature(const AbstractMetaClass *c, const QString &name) +{ + const AbstractMetaFunction *f = c->findFunction(name); + return f ? f->minimalSignature() : QString(); +} + +void TestArrayArgument::testArraySignature() +{ + const char cppCode[] ="\ + struct A {\n\ + void mi1(int arg[5]);\n\ + void mi1c(const int arg[5]);\n\ + void mi1cu(const int arg[]);\n\ + void mc1cu(const char arg[]);\n\ + void mc1cup(const char *arg[]);\n\ + void muc2(unsigned char *arg[2][3]);\n\ + void mc2c(const char *arg[5][6]);\n\ + void mc2cu(const char arg[][2]);\n\ + };\n"; + const char xmlCode[] = "\ + <typesystem package='Foo'>\n\ + <primitive-type name='char'/>\n\ + <primitive-type name='unsigned char'/>\n\ + <primitive-type name='int'/>\n\ + <object-type name='A'/>\n\ + </typesystem>\n"; + + QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); + QVERIFY(!builder.isNull()); + const AbstractMetaClass *classA = AbstractMetaClass::findClass(builder->classes(), QLatin1String("A")); + QCOMPARE(functionMinimalSignature(classA, QLatin1String("mi1")), + QLatin1String("mi1(int[5])")); + QCOMPARE(functionMinimalSignature(classA, QLatin1String("mi1c")), + QLatin1String("mi1c(const int[5])")); + QCOMPARE(functionMinimalSignature(classA, QLatin1String("mi1cu")), + QLatin1String("mi1cu(const int[])")); + QCOMPARE(functionMinimalSignature(classA, QLatin1String("mc1cu")), + QLatin1String("mc1cu(const char*)")); + QCOMPARE(functionMinimalSignature(classA, QLatin1String("mc1cup")), + QLatin1String("mc1cup(const char*[])")); + QCOMPARE(functionMinimalSignature(classA, QLatin1String("muc2")), + QLatin1String("muc2(unsigned char*[2][3])")); + QCOMPARE(functionMinimalSignature(classA, QLatin1String("mc2c")), + QLatin1String("mc2c(const char*[5][6])")); + QCOMPARE(functionMinimalSignature(classA, QLatin1String("mc2cu")), + QLatin1String("mc2cu(const char[][2])")); +} + void TestArrayArgument::testArrayArgumentWithSizeDefinedByEnumValue() { const char* cppCode ="\ @@ -80,7 +128,7 @@ void TestArrayArgument::testArrayArgumentWithSizeDefinedByEnumValue() AbstractMetaEnum* someEnum = classA->findEnum(QLatin1String("SomeEnum")); QVERIFY(someEnum); - AbstractMetaEnumValue* nvalues = classA->findEnumValue(QLatin1String("NValues"), someEnum); + AbstractMetaEnumValue *nvalues = classA->findEnumValue(QLatin1String("NValues")); QVERIFY(nvalues); const AbstractMetaArgument* arg = classA->functions().last()->arguments().first(); @@ -111,13 +159,7 @@ void TestArrayArgument::testArrayArgumentWithSizeDefinedByEnumValueFromGlobalEnu AbstractMetaEnum* someEnum = builder->globalEnums().first(); QVERIFY(someEnum); - AbstractMetaEnumValue* nvalues = 0; - foreach (AbstractMetaEnumValue* enumValue, someEnum->values()) { - if (enumValue->name() == QLatin1String("NValues")) { - nvalues = enumValue; - break; - } - } + const AbstractMetaEnumValue *nvalues = someEnum->findEnumValue(QLatin1String("NValues")); QVERIFY(nvalues); const AbstractMetaArgument* arg = classA->functions().last()->arguments().first(); diff --git a/sources/shiboken2/ApiExtractor/tests/testarrayargument.h b/sources/shiboken2/ApiExtractor/tests/testarrayargument.h index b50232ef4..45ca8e655 100644 --- a/sources/shiboken2/ApiExtractor/tests/testarrayargument.h +++ b/sources/shiboken2/ApiExtractor/tests/testarrayargument.h @@ -35,6 +35,7 @@ class TestArrayArgument : public QObject Q_OBJECT private slots: void testArrayArgumentWithSizeDefinedByInteger(); + void testArraySignature(); void testArrayArgumentWithSizeDefinedByEnumValue(); void testArrayArgumentWithSizeDefinedByEnumValueFromGlobalEnum(); }; diff --git a/sources/shiboken2/ApiExtractor/tests/testconversionoperator.cpp b/sources/shiboken2/ApiExtractor/tests/testconversionoperator.cpp index cae4a3a62..86f571328 100644 --- a/sources/shiboken2/ApiExtractor/tests/testconversionoperator.cpp +++ b/sources/shiboken2/ApiExtractor/tests/testconversionoperator.cpp @@ -65,7 +65,7 @@ void TestConversionOperator::testConversionOperator() QCOMPARE(classA->externalConversionOperators().count(), 2); AbstractMetaFunction* convOp = 0; - foreach(AbstractMetaFunction* func, classB->functions()) { + for (AbstractMetaFunction *func : classB->functions()) { if (func->isConversionOperator()) { convOp = func; break; diff --git a/sources/shiboken2/ApiExtractor/tests/testenum.cpp b/sources/shiboken2/ApiExtractor/tests/testenum.cpp index 6700239d6..55c098840 100644 --- a/sources/shiboken2/ApiExtractor/tests/testenum.cpp +++ b/sources/shiboken2/ApiExtractor/tests/testenum.cpp @@ -83,6 +83,10 @@ void TestEnum::testEnumCppSignature() AbstractMetaEnumList classEnums = classA->enums(); QCOMPARE(classEnums.first()->name(), QLatin1String("ClassEnum")); + AbstractMetaEnumValue *e = AbstractMetaClass::findEnumValue(classes, QLatin1String("CA")); + QVERIFY(e); + e = AbstractMetaClass::findEnumValue(classes, QLatin1String("ClassEnum::CA")); + QVERIFY(e); } void TestEnum::testEnumWithApiVersion() @@ -318,7 +322,7 @@ void TestEnum::testEnumValueFromExpression() AbstractMetaEnumValue* valueA4 = enumA->values().at(4); QCOMPARE(valueA4->name(), QLatin1String("ValueA4")); - QCOMPARE(valueA4->stringValue(), QLatin1String("8|ValueA3")); + QCOMPARE(valueA4->stringValue(), QLatin1String("8 |ValueA3")); QCOMPARE(valueA4->value(), 8|0xf0); AbstractMetaEnumValue* valueA5 = enumA->values().at(5); @@ -328,12 +332,12 @@ void TestEnum::testEnumValueFromExpression() AbstractMetaEnumValue* valueA6 = enumA->values().at(6); QCOMPARE(valueA6->name(), QLatin1String("ValueA6")); - QCOMPARE(valueA6->stringValue(), QLatin1String("ValueA3>>1")); + QCOMPARE(valueA6->stringValue(), QLatin1String("ValueA3 >> 1")); QCOMPARE(valueA6->value(), 0xf0 >> 1); AbstractMetaEnumValue* valueA7 = enumA->values().at(7); QCOMPARE(valueA7->name(), QLatin1String("ValueA7")); - QCOMPARE(valueA7->stringValue(), QLatin1String("ValueA3<<1")); + QCOMPARE(valueA7->stringValue(), QLatin1String("ValueA3 << 1")); QCOMPARE(valueA7->value(), 0xf0 << 1); } diff --git a/sources/shiboken2/ApiExtractor/tests/testextrainclude.cpp b/sources/shiboken2/ApiExtractor/tests/testextrainclude.cpp index 94158377e..97f0d568e 100644 --- a/sources/shiboken2/ApiExtractor/tests/testextrainclude.cpp +++ b/sources/shiboken2/ApiExtractor/tests/testextrainclude.cpp @@ -50,7 +50,7 @@ void TestExtraInclude::testClassExtraInclude() const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); QVERIFY(classA); - QList<Include> includes = classA->typeEntry()->extraIncludes(); + QVector<Include> includes = classA->typeEntry()->extraIncludes(); QCOMPARE(includes.count(), 1); QCOMPARE(includes.first().name(), QLatin1String("header.h")); } @@ -76,7 +76,7 @@ void TestExtraInclude::testGlobalExtraIncludes() TypeEntry* module = td->findType(QLatin1String("Foo")); QVERIFY(module); - QList<Include> includes = module->extraIncludes(); + QVector<Include> includes = module->extraIncludes(); QCOMPARE(includes.count(), 2); QCOMPARE(includes.first().name(), QLatin1String("header1.h")); QCOMPARE(includes.last().name(), QLatin1String("header2.h")); diff --git a/sources/shiboken2/ApiExtractor/tests/testimplicitconversions.cpp b/sources/shiboken2/ApiExtractor/tests/testimplicitconversions.cpp index 4438550b2..7e8db42f3 100644 --- a/sources/shiboken2/ApiExtractor/tests/testimplicitconversions.cpp +++ b/sources/shiboken2/ApiExtractor/tests/testimplicitconversions.cpp @@ -152,7 +152,7 @@ void TestImplicitConversions::testWithExternalConversionOperator() QCOMPARE(externalConvOps.count(), 1); const AbstractMetaFunction* convOp = 0; - foreach(const AbstractMetaFunction* func, classB->functions()) { + for (const AbstractMetaFunction *func : classB->functions()) { if (func->isConversionOperator()) convOp = func; } diff --git a/sources/shiboken2/ApiExtractor/tests/testmodifydocumentation.cpp b/sources/shiboken2/ApiExtractor/tests/testmodifydocumentation.cpp index 96bd0251b..d56186479 100644 --- a/sources/shiboken2/ApiExtractor/tests/testmodifydocumentation.cpp +++ b/sources/shiboken2/ApiExtractor/tests/testmodifydocumentation.cpp @@ -66,7 +66,7 @@ void TestModifyDocumentation::testModifyDocumentation() <para>Paragraph number 1</para>\n\ <para>Paragraph number 2</para>\n\ <para>Some changed contents here</para>\n\ -</description>\n")); +</description>")); } // We expand QTEST_MAIN macro but using QCoreApplication instead of QApplication diff --git a/sources/shiboken2/ApiExtractor/tests/testmodifyfunction.cpp b/sources/shiboken2/ApiExtractor/tests/testmodifyfunction.cpp index 0e6bdc248..dd82a0f14 100644 --- a/sources/shiboken2/ApiExtractor/tests/testmodifyfunction.cpp +++ b/sources/shiboken2/ApiExtractor/tests/testmodifyfunction.cpp @@ -32,24 +32,36 @@ #include <abstractmetalang.h> #include <typesystem.h> +void TestModifyFunction::testRenameArgument_data() +{ + QTest::addColumn<QByteArray>("pattern"); + QTest::newRow("fixed_string") << QByteArrayLiteral("method(int)"); + QTest::newRow("regular_expression") << QByteArrayLiteral("^method.*"); +} + void TestModifyFunction::testRenameArgument() { + QFETCH(QByteArray, pattern); + const char* cppCode ="\ struct A {\n\ void method(int=0);\n\ };\n"; - const char* xmlCode = "\ + const char xmlCode1[] = "\ <typesystem package='Foo'>\n\ <primitive-type name='int'/>\n\ <object-type name='A'>\n\ - <modify-function signature='method(int)'>\n\ + <modify-function signature='"; + const char xmlCode2[] = "'>\n\ <modify-argument index='1'>\n\ <rename to='otherArg'/>\n\ </modify-argument>\n\ </modify-function>\n\ </object-type>\n\ </typesystem>\n"; - QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); + + const QByteArray xmlCode = QByteArray(xmlCode1) + pattern + QByteArray(xmlCode2); + QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode.constData(), false)); QVERIFY(!builder.isNull()); AbstractMetaClassList classes = builder->classes(); const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); @@ -232,7 +244,7 @@ void TestModifyFunction::testGlobalFunctionModification() FunctionModificationList mods = TypeDatabase::instance()->functionModifications(QLatin1String("function(A*)")); QCOMPARE(mods.count(), 1); - QList<ArgumentModification> argMods = mods.first().argument_mods; + QVector<ArgumentModification> argMods = mods.first().argument_mods; QCOMPARE(argMods.count(), 1); ArgumentModification argMod = argMods.first(); QCOMPARE(argMod.replacedDefaultExpression, QLatin1String("A()")); diff --git a/sources/shiboken2/ApiExtractor/tests/testmodifyfunction.h b/sources/shiboken2/ApiExtractor/tests/testmodifyfunction.h index fcaa0f9db..6bb62daf4 100644 --- a/sources/shiboken2/ApiExtractor/tests/testmodifyfunction.h +++ b/sources/shiboken2/ApiExtractor/tests/testmodifyfunction.h @@ -37,6 +37,7 @@ class TestModifyFunction : public QObject private slots: void testOwnershipTransfer(); void testWithApiVersion(); + void testRenameArgument_data(); void testRenameArgument(); void invalidateAfterUse(); void testGlobalFunctionModification(); diff --git a/sources/shiboken2/ApiExtractor/tests/testmultipleinheritance.cpp b/sources/shiboken2/ApiExtractor/tests/testmultipleinheritance.cpp index 67c9089ce..b78e6ec01 100644 --- a/sources/shiboken2/ApiExtractor/tests/testmultipleinheritance.cpp +++ b/sources/shiboken2/ApiExtractor/tests/testmultipleinheritance.cpp @@ -61,7 +61,8 @@ void TestMultipleInheritance::testVirtualClass() const AbstractMetaClass *classD = AbstractMetaClass::findClass(classes, QLatin1String("D")); bool functionFound = false; - foreach (AbstractMetaFunction* f, classD->functions()) { + const AbstractMetaFunctionList &functions = classD->functions(); + for (AbstractMetaFunction *f : functions) { if (f->name() == QLatin1String("theBug")) { functionFound = true; break; diff --git a/sources/shiboken2/ApiExtractor/tests/testremoveoperatormethod.cpp b/sources/shiboken2/ApiExtractor/tests/testremoveoperatormethod.cpp index 6b27227d6..508cff586 100644 --- a/sources/shiboken2/ApiExtractor/tests/testremoveoperatormethod.cpp +++ b/sources/shiboken2/ApiExtractor/tests/testremoveoperatormethod.cpp @@ -105,7 +105,8 @@ void TestRemoveOperatorMethod::testRemoveOperatorMethod() removedSignatures.append(QLatin1String("operator>>(Char&)")); removedSignatures.append(QLatin1String("operator>>(String&)")); int notRemoved = classA->functions().size(); - foreach (const AbstractMetaFunction* f, classA->functions()) { + const AbstractMetaFunctionList &functions = classA->functions(); + for (const AbstractMetaFunction *f : functions) { QCOMPARE(f->isModifiedRemoved(), bool(removedSignatures.contains(f->minimalSignature()))); notRemoved -= int(f->isModifiedRemoved()); } diff --git a/sources/shiboken2/ApiExtractor/tests/testreverseoperators.cpp b/sources/shiboken2/ApiExtractor/tests/testreverseoperators.cpp index 76ba7d3b4..18d6902c2 100644 --- a/sources/shiboken2/ApiExtractor/tests/testreverseoperators.cpp +++ b/sources/shiboken2/ApiExtractor/tests/testreverseoperators.cpp @@ -53,7 +53,7 @@ void TestReverseOperators::testReverseSum() const AbstractMetaFunction* reverseOp = 0; const AbstractMetaFunction* normalOp = 0; - foreach(const AbstractMetaFunction* func, classA->functions()) { + for (const AbstractMetaFunction *func : classA->functions()) { if (func->name() == QLatin1String("operator+")) { if (func->isReverseOperator()) reverseOp = func; @@ -89,6 +89,7 @@ void TestReverseOperators::testReverseSumWithAmbiguity() </typesystem>"; QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false)); + QEXPECT_FAIL("", "Clang: Does not compile", Abort); QVERIFY(!builder.isNull()); AbstractMetaClassList classes = builder->classes(); const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); @@ -101,7 +102,7 @@ void TestReverseOperators::testReverseSumWithAmbiguity() const AbstractMetaFunction* reverseOp = 0; const AbstractMetaFunction* normalOp = 0; - foreach(const AbstractMetaFunction* func, classB->functions()) { + for (const AbstractMetaFunction *func : classB->functions()) { if (func->name() == QLatin1String("operator+")) { if (func->isReverseOperator()) reverseOp = func; diff --git a/sources/shiboken2/ApiExtractor/tests/testtemplates.cpp b/sources/shiboken2/ApiExtractor/tests/testtemplates.cpp index cb90383db..4a66264d8 100644 --- a/sources/shiboken2/ApiExtractor/tests/testtemplates.cpp +++ b/sources/shiboken2/ApiExtractor/tests/testtemplates.cpp @@ -228,6 +228,7 @@ void TestTemplates::testTemplateParameterFixup() const AbstractMetaFunction *erase = list->findFunction(QStringLiteral("erase")); QVERIFY(erase); QCOMPARE(erase->arguments().size(), 1); + QEXPECT_FAIL("", "Clang: Some other code changes the parameter type", Abort); QCOMPARE(erase->arguments().at(0)->type()->cppSignature(), QLatin1String("List::Iterator")); } diff --git a/sources/shiboken2/ApiExtractor/tests/testutil.h b/sources/shiboken2/ApiExtractor/tests/testutil.h index d4eb2fdf6..200fdb104 100644 --- a/sources/shiboken2/ApiExtractor/tests/testutil.h +++ b/sources/shiboken2/ApiExtractor/tests/testutil.h @@ -29,6 +29,9 @@ #ifndef TESTUTIL_H #define TESTUTIL_H #include <QtCore/QBuffer> +#include <QtCore/QDebug> +#include <QtCore/QDir> +#include <QtCore/QTemporaryFile> #include "abstractmetabuilder.h" #include "reporthandler.h" #include "typedatabase.h" @@ -53,9 +56,18 @@ namespace TestUtil td->parseFile(&buffer); buffer.close(); // parse C++ code - buffer.setData(cppCode); + QTemporaryFile tempSource(QDir::tempPath() + QLatin1String("/st_XXXXXX_main.cpp")); + if (!tempSource.open()) { + qWarning().noquote().nospace() << "Creation of temporary file failed: " + << tempSource.errorString(); + return nullptr; + } + QByteArrayList arguments; + arguments.append(QFile::encodeName(tempSource.fileName())); + tempSource.write(cppCode, qint64(strlen(cppCode))); + tempSource.close(); AbstractMetaBuilder *builder = new AbstractMetaBuilder; - if (!builder->build(&buffer)) { + if (!builder->build(arguments, 0)) { delete builder; return Q_NULLPTR; } diff --git a/sources/shiboken2/ApiExtractor/typedatabase.cpp b/sources/shiboken2/ApiExtractor/typedatabase.cpp index 55170d7c1..76953a51e 100644 --- a/sources/shiboken2/ApiExtractor/typedatabase.cpp +++ b/sources/shiboken2/ApiExtractor/typedatabase.cpp @@ -31,6 +31,7 @@ #include "typesystem_p.h" #include <QtCore/QFile> +#include <QtCore/QDebug> #include <QtCore/QDir> #include <QtCore/QPair> #include <QtCore/QVector> @@ -175,8 +176,8 @@ FunctionTypeEntry* TypeDatabase::findFunctionType(const QString& name) const TypeEntry* TypeDatabase::findType(const QString& name) const { - QList<TypeEntry *> entries = findTypes(name); - foreach (TypeEntry *entry, entries) { + const TypeEntryList &entries = findTypes(name); + for (TypeEntry *entry : entries) { if (entry && (!entry->isPrimitive() || static_cast<PrimitiveTypeEntry *>(entry)->preferredTargetLangType())) { return entry; @@ -185,7 +186,7 @@ TypeEntry* TypeDatabase::findType(const QString& name) const return 0; } -QList<TypeEntry *> TypeDatabase::findTypes(const QString &name) const +TypeEntryList TypeDatabase::findTypes(const QString &name) const { return m_entries.value(name); } @@ -201,12 +202,12 @@ SingleTypeEntryHash TypeDatabase::entries() const return returned; } -QList<const PrimitiveTypeEntry*> TypeDatabase::primitiveTypes() const +PrimitiveTypeEntryList TypeDatabase::primitiveTypes() const { TypeEntryHash entries = allEntries(); - QList<const PrimitiveTypeEntry*> returned; + PrimitiveTypeEntryList returned; for (TypeEntryHash::const_iterator it = entries.cbegin(), end = entries.cend(); it != end; ++it) { - foreach (TypeEntry *typeEntry, it.value()) { + for (TypeEntry *typeEntry : it.value()) { if (typeEntry->isPrimitive()) returned.append(static_cast<PrimitiveTypeEntry *>(typeEntry)); } @@ -214,75 +215,121 @@ QList<const PrimitiveTypeEntry*> TypeDatabase::primitiveTypes() const return returned; } -QList<const ContainerTypeEntry*> TypeDatabase::containerTypes() const +ContainerTypeEntryList TypeDatabase::containerTypes() const { TypeEntryHash entries = allEntries(); - QList<const ContainerTypeEntry*> returned; + ContainerTypeEntryList returned; for (TypeEntryHash::const_iterator it = entries.cbegin(), end = entries.cend(); it != end; ++it) { - foreach (TypeEntry *typeEntry, it.value()) { + for (TypeEntry *typeEntry : it.value()) { if (typeEntry->isContainer()) returned.append(static_cast<ContainerTypeEntry *>(typeEntry)); } } return returned; } -void TypeDatabase::addRejection(const QString& className, const QString& functionName, - const QString& fieldName, const QString& enumName) + +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug d, const TypeRejection &r) { - TypeRejection r; - r.class_name = className; - r.function_name = functionName; - r.field_name = fieldName; - r.enum_name = enumName; + QDebugStateSaver saver(d); + d.noquote(); + d.nospace(); + d << "TypeRejection(type=" << r.matchType << ", class=" + << r.className.pattern() << ", pattern=" << r.pattern.pattern() << ')'; + return d; +} +#endif // !QT_NO_DEBUG_STREAM +void TypeDatabase::addRejection(const TypeRejection &r) +{ m_rejections << r; } -bool TypeDatabase::isClassRejected(const QString& className) const +static inline QString msgRejectReason(const TypeRejection &r, const QString &needle = QString()) +{ + QString result; + QTextStream str(&result); + switch (r.matchType) { + case TypeRejection::ExcludeClass: + str << " matches class exclusion \"" << r.className.pattern() << '"'; + break; + case TypeRejection::Function: + case TypeRejection::Field: + case TypeRejection::Enum: + str << " matches class \"" << r.className.pattern() << "\" and \"" << r.pattern.pattern() << '"'; + break; + case TypeRejection::ArgumentType: + case TypeRejection::ReturnType: + str << " matches class \"" << r.className.pattern() << "\" and \"" << needle + << "\" matches \"" << r.pattern.pattern() << '"'; + break; + } + return result; +} + +// Match class name only +bool TypeDatabase::isClassRejected(const QString& className, QString *reason) const { - foreach (const TypeRejection& r, m_rejections) { - if (r.class_name == className && r.function_name == QLatin1String("*") - && r.field_name == QLatin1String("*") && r.enum_name == QLatin1String("*")) { + for (const TypeRejection& r : m_rejections) { + if (r.matchType == TypeRejection::ExcludeClass && r.className.match(className).hasMatch()) { + if (reason) + *reason = msgRejectReason(r); return true; } } return false; } -bool TypeDatabase::isEnumRejected(const QString& className, const QString& enumName) const +// Match class name and function/enum/field +static bool findRejection(const QVector<TypeRejection> &rejections, + TypeRejection::MatchType matchType, + const QString& className, const QString& name, + QString *reason = nullptr) { - foreach (const TypeRejection& r, m_rejections) { - if (r.enum_name == enumName - && (r.class_name == className || r.class_name == QLatin1String("*"))) { + Q_ASSERT(matchType != TypeRejection::ExcludeClass); + for (const TypeRejection& r : rejections) { + if (r.matchType == matchType && r.pattern.match(name).hasMatch() + && r.className.match(className).hasMatch()) { + if (reason) + *reason = msgRejectReason(r, name); return true; } } - return false; } +bool TypeDatabase::isEnumRejected(const QString& className, const QString& enumName, QString *reason) const +{ + return findRejection(m_rejections, TypeRejection::Enum, className, enumName, reason); +} + void TypeDatabase::addType(TypeEntry *e) { m_entries[e->qualifiedCppName()].append(e); } -bool TypeDatabase::isFunctionRejected(const QString& className, const QString& functionName) const +bool TypeDatabase::isFunctionRejected(const QString& className, const QString& functionName, + QString *reason) const { - foreach (const TypeRejection& r, m_rejections) - if (r.function_name == functionName && - (r.class_name == className || r.class_name == QLatin1String("*"))) - return true; - return false; + return findRejection(m_rejections, TypeRejection::Function, className, functionName, reason); } +bool TypeDatabase::isFieldRejected(const QString& className, const QString& fieldName, + QString *reason) const +{ + return findRejection(m_rejections, TypeRejection::Field, className, fieldName, reason); +} -bool TypeDatabase::isFieldRejected(const QString& className, const QString& fieldName) const +bool TypeDatabase::isArgumentTypeRejected(const QString& className, const QString& typeName, + QString *reason) const { - foreach (const TypeRejection& r, m_rejections) - if (r.field_name == fieldName && - (r.class_name == className || r.class_name == QLatin1String("*"))) - return true; - return false; + return findRejection(m_rejections, TypeRejection::ArgumentType, className, typeName, reason); +} + +bool TypeDatabase::isReturnTypeRejected(const QString& className, const QString& typeName, + QString *reason) const +{ + return findRejection(m_rejections, TypeRejection::ReturnType, className, typeName, reason); } FlagsTypeEntry* TypeDatabase::findFlagsType(const QString &name) const @@ -321,7 +368,7 @@ void TypeDatabase::addGlobalUserFunctions(const AddedFunctionList &functions) AddedFunctionList TypeDatabase::findGlobalUserFunctions(const QString& name) const { AddedFunctionList addedFunctions; - foreach (const AddedFunction &func, m_globalUserFunctions) { + for (const AddedFunction &func : m_globalUserFunctions) { if (func.name() == name) addedFunctions.append(func); } @@ -343,16 +390,52 @@ FunctionModificationList TypeDatabase::functionModifications(const QString& sign FunctionModificationList lst; for (int i = 0; i < m_functionMods.count(); ++i) { const FunctionModification& mod = m_functionMods.at(i); - if (mod.signature == signature) + if (mod.matches(signature)) lst << mod; } return lst; } -void TypeDatabase::addSuppressedWarning(const QString &s) +bool TypeDatabase::addSuppressedWarning(const QString &warning, QString *errorMessage) { - m_suppressedWarnings.append(s); + QString pattern; + if (warning.startsWith(QLatin1Char('^')) && warning.endsWith(QLatin1Char('$'))) { + pattern = warning; + } else { + // Legacy syntax: Use wildcards '*' (unless escaped by '\') + QVector<int> asteriskPositions; + const int warningSize = warning.size(); + for (int i = 0; i < warningSize; ++i) { + if (warning.at(i) == QLatin1Char('\\')) + ++i; + else if (warning.at(i) == QLatin1Char('*')) + asteriskPositions.append(i); + } + asteriskPositions.append(warningSize); + + pattern.append(QLatin1Char('^')); + int lastPos = 0; + for (int a = 0, aSize = asteriskPositions.size(); a < aSize; ++a) { + if (a) + pattern.append(QStringLiteral(".*")); + const int nextPos = asteriskPositions.at(a); + if (nextPos > lastPos) + pattern.append(QRegularExpression::escape(warning.mid(lastPos, nextPos - lastPos))); + lastPos = nextPos + 1; + } + pattern.append(QLatin1Char('$')); + } + + const QRegularExpression expression(pattern); + if (!expression.isValid()) { + *errorMessage = QLatin1String("Invalid message pattern \"") + warning + + QLatin1String("\": ") + expression.errorString(); + return false; + } + + m_suppressedWarnings.append(expression); + return true; } bool TypeDatabase::isSuppressedWarning(const QString& s) const @@ -360,37 +443,28 @@ bool TypeDatabase::isSuppressedWarning(const QString& s) const if (!m_suppressWarnings) return false; - foreach (const QString &_warning, m_suppressedWarnings) { - QString warning = _warning; - warning.replace(QLatin1String("\\*"), QLatin1String("&place_holder_for_asterisk;")); - - QStringList segs = warning.split(QLatin1Char('*'), QString::SkipEmptyParts); - if (!segs.size()) - continue; - - int i = 0; - int pos = s.indexOf(QString(segs.at(i++)).replace(QLatin1String("&place_holder_for_asterisk;"), QLatin1String("*"))); - //qDebug() << "s == " << s << ", warning == " << segs; - while (pos != -1) { - if (i == segs.size()) - return true; - pos = s.indexOf(QString(segs.at(i++)).replace(QLatin1String("&place_holder_for_asterisk;"), QLatin1String("*")), pos); - } + for (const QRegularExpression &warning : m_suppressedWarnings) { + if (warning.match(s).hasMatch()) + return true; } return false; } -QString TypeDatabase::modifiedTypesystemFilepath(const QString& tsFile) const +QString TypeDatabase::modifiedTypesystemFilepath(const QString& tsFile, const QString ¤tPath) const { const QFileInfo tsFi(tsFile); if (tsFi.isAbsolute()) // No point in further lookups return tsFi.absoluteFilePath(); if (tsFi.isFile()) // Make path absolute return tsFi.absoluteFilePath(); - const QString fileName = tsFi.fileName(); - foreach (const QString &path, m_typesystemPaths) { - const QFileInfo fi(path + QLatin1Char('/') + fileName); + if (!currentPath.isEmpty()) { + const QFileInfo fi(currentPath + QLatin1Char('/') + tsFile); + if (fi.isFile()) + return fi.absoluteFilePath(); + } + for (const QString &path : m_typesystemPaths) { + const QFileInfo fi(path + QLatin1Char('/') + tsFile); if (fi.isFile()) return fi.absoluteFilePath(); } @@ -399,7 +473,13 @@ QString TypeDatabase::modifiedTypesystemFilepath(const QString& tsFile) const bool TypeDatabase::parseFile(const QString &filename, bool generate) { - QString filepath = modifiedTypesystemFilepath(filename); + return parseFile(filename, QString(), generate); +} + +bool TypeDatabase::parseFile(const QString &filename, const QString ¤tPath, bool generate) +{ + + QString filepath = modifiedTypesystemFilepath(filename, currentPath); if (m_parsedTypesystemFiles.contains(filepath)) return m_parsedTypesystemFiles[filepath]; @@ -408,8 +488,11 @@ bool TypeDatabase::parseFile(const QString &filename, bool generate) QFile file(filepath); if (!file.exists()) { m_parsedTypesystemFiles[filepath] = false; - qCWarning(lcShiboken).noquote().nospace() - << "Can't find " << filename << ", typesystem paths: " << m_typesystemPaths.join(QLatin1String(", ")); + QString message = QLatin1String("Can't find ") + filename; + if (!currentPath.isEmpty()) + message += QLatin1String(", current path: ") + currentPath; + message += QLatin1String(", typesystem paths: ") + m_typesystemPaths.join(QLatin1String(", ")); + qCWarning(lcShiboken).noquote().nospace() << message; return false; } if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { @@ -440,9 +523,9 @@ bool TypeDatabase::parseFile(QIODevice* device, bool generate) PrimitiveTypeEntry *TypeDatabase::findPrimitiveType(const QString& name) const { - QList<TypeEntry*> entries = findTypes(name); + const TypeEntryList &entries = findTypes(name); - foreach (TypeEntry* entry, entries) { + for (TypeEntry *entry : entries) { if (entry && entry->isPrimitive() && static_cast<PrimitiveTypeEntry*>(entry)->preferredTargetLangType()) return static_cast<PrimitiveTypeEntry*>(entry); } @@ -452,8 +535,8 @@ PrimitiveTypeEntry *TypeDatabase::findPrimitiveType(const QString& name) const ComplexTypeEntry* TypeDatabase::findComplexType(const QString& name) const { - QList<TypeEntry*> entries = findTypes(name); - foreach (TypeEntry* entry, entries) { + const TypeEntryList &entries = findTypes(name); + for (TypeEntry *entry : entries) { if (entry && entry->isComplex()) return static_cast<ComplexTypeEntry*>(entry); } @@ -462,8 +545,8 @@ ComplexTypeEntry* TypeDatabase::findComplexType(const QString& name) const ObjectTypeEntry* TypeDatabase::findObjectType(const QString& name) const { - QList<TypeEntry*> entries = findTypes(name); - foreach (TypeEntry* entry, entries) { + const TypeEntryList &entries = findTypes(name); + for (TypeEntry *entry : entries) { if (entry && entry->isObject()) return static_cast<ObjectTypeEntry*>(entry); } @@ -472,8 +555,8 @@ ObjectTypeEntry* TypeDatabase::findObjectType(const QString& name) const NamespaceTypeEntry* TypeDatabase::findNamespaceType(const QString& name) const { - QList<TypeEntry*> entries = findTypes(name); - foreach (TypeEntry* entry, entries) { + const TypeEntryList &entries = findTypes(name); + for (TypeEntry *entry : entries) { if (entry && entry->isNamespace()) return static_cast<NamespaceTypeEntry*>(entry); } @@ -518,13 +601,13 @@ static bool compareTypeEntriesByName(const TypeEntry* t1, const TypeEntry* t2) static void _computeTypeIndexes() { TypeDatabase* tdb = TypeDatabase::instance(); - typedef QMap<int, QList<TypeEntry*> > GroupedTypeEntries; + typedef QMap<int, TypeEntryList> GroupedTypeEntries; GroupedTypeEntries groupedEntries; // Group type entries by revision numbers - TypeEntryHash allEntries = tdb->allEntries(); - foreach (QList<TypeEntry*> entryList, allEntries) { - foreach (TypeEntry* entry, entryList) { + const TypeEntryHash &allEntries = tdb->allEntries(); + for (TypeEntryHash::const_iterator tit = allEntries.cbegin(), end = allEntries.cend(); tit != end; ++tit) { + for (TypeEntry *entry : tit.value()) { if (entry->isPrimitive() || entry->isContainer() || entry->isFunction() @@ -543,12 +626,12 @@ static void _computeTypeIndexes() GroupedTypeEntries::iterator it = groupedEntries.begin(); for (; it != groupedEntries.end(); ++it) { // Remove duplicates - QList<TypeEntry*>::iterator newEnd = std::unique(it.value().begin(), it.value().end()); + TypeEntryList::iterator newEnd = std::unique(it.value().begin(), it.value().end()); it.value().erase(newEnd, it.value().end()); // Sort the type entries by name qSort(it.value().begin(), newEnd, compareTypeEntriesByName); - foreach (TypeEntry* entry, it.value()) { + for (TypeEntry *entry : qAsConst(it.value())) { (*typeEntryFields())[entry].second = maxTypeIndex++; } } @@ -614,7 +697,12 @@ QDebug operator<<(QDebug d, const TypeEntry *te) d.nospace(); d << "TypeEntry("; if (te) { - d << '"' << te->qualifiedCppName() << "\", type=" << te->type(); + const QString name = te->name(); + const QString cppName = te->qualifiedCppName(); + d << '"' << name << '"'; + if (name != cppName) + d << "\", cppName=\"" << cppName << '"'; + d << ", type=" << te->type(); if (te->include().isValid()) d << ", include=" << te->include(); const IncludeList &extraIncludes = te->extraIncludes(); @@ -640,7 +728,7 @@ QDebug operator<<(QDebug d, const TemplateEntry *te) d.nospace(); d << "TemplateEntry("; if (te) { - d << '"' << te->name() << "\", version=" << te->version(); + d << '"' << te->name() << '"'; } else { d << '0'; } diff --git a/sources/shiboken2/ApiExtractor/typedatabase.h b/sources/shiboken2/ApiExtractor/typedatabase.h index 4255cf458..dfddfc300 100644 --- a/sources/shiboken2/ApiExtractor/typedatabase.h +++ b/sources/shiboken2/ApiExtractor/typedatabase.h @@ -31,9 +31,11 @@ #include "apiextractormacros.h" #include "include.h" +#include "typedatabase_typedefs.h" #include "typesystem_enums.h" #include "typesystem_typedefs.h" +#include <QtCore/QRegularExpression> #include <QtCore/QStringList> QT_FORWARD_DECLARE_CLASS(QIODevice) @@ -95,16 +97,22 @@ public: SingleTypeEntryHash entries() const; - QList<const PrimitiveTypeEntry*> primitiveTypes() const; + PrimitiveTypeEntryList primitiveTypes() const; - QList<const ContainerTypeEntry*> containerTypes() const; + ContainerTypeEntryList containerTypes() const; - void addRejection(const QString& className, const QString& functionName, - const QString& fieldName, const QString& enumName); - bool isClassRejected(const QString& className) const; - bool isFunctionRejected(const QString& className, const QString& functionName) const; - bool isFieldRejected(const QString& className, const QString& fieldName) const; - bool isEnumRejected(const QString& className, const QString& enumName) const; + void addRejection(const TypeRejection &); + bool isClassRejected(const QString& className, QString *reason = nullptr) const; + bool isFunctionRejected(const QString& className, const QString& functionName, + QString *reason = nullptr) const; + bool isFieldRejected(const QString& className, const QString& fieldName, + QString *reason = nullptr) const; + bool isEnumRejected(const QString& className, const QString& enumName, + QString *reason = nullptr) const; + bool isArgumentTypeRejected(const QString& className, const QString& typeName, + QString *reason = nullptr) const; + bool isReturnTypeRejected(const QString& className, const QString& typeName, + QString *reason = nullptr) const; void addType(TypeEntry* e); @@ -127,13 +135,15 @@ public: void setSuppressWarnings(bool on) { m_suppressWarnings = on; } - void addSuppressedWarning(const QString &s); + bool addSuppressedWarning(const QString &warning, QString *errorMessage); bool isSuppressedWarning(const QString& s) const; static QString globalNamespaceClassName(const TypeEntry *te); bool parseFile(const QString &filename, bool generate = true); + bool parseFile(const QString &filename, const QString ¤tPath, bool generate); + bool parseFile(QIODevice* device, bool generate = true); bool setApiVersion(const QString& package, const QString& version); @@ -146,18 +156,19 @@ public: void setDropTypeEntries(QStringList dropTypeEntries); + QString modifiedTypesystemFilepath(const QString &tsFile, const QString ¤tPath = QString()) const; + #ifndef QT_NO_DEBUG_STREAM void formatDebug(QDebug &d) const; #endif private: - QList<TypeEntry *> findTypes(const QString &name) const; - QString modifiedTypesystemFilepath(const QString &tsFile) const; + TypeEntryList findTypes(const QString &name) const; bool m_suppressWarnings; TypeEntryHash m_entries; SingleTypeEntryHash m_flagsEntries; TemplateEntryHash m_templates; - QStringList m_suppressedWarnings; + QVector<QRegularExpression> m_suppressedWarnings; AddedFunctionList m_globalUserFunctions; FunctionModificationList m_functionMods; @@ -167,7 +178,7 @@ private: QStringList m_typesystemPaths; QHash<QString, bool> m_parsedTypesystemFiles; - QList<TypeRejection> m_rejections; + QVector<TypeRejection> m_rejections; QStringList m_dropTypeEntries; }; diff --git a/sources/shiboken2/ApiExtractor/asttoxml.h b/sources/shiboken2/ApiExtractor/typedatabase_typedefs.h index ed2a04833..95859a399 100644 --- a/sources/shiboken2/ApiExtractor/asttoxml.h +++ b/sources/shiboken2/ApiExtractor/typedatabase_typedefs.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of PySide2. @@ -26,21 +26,24 @@ ** ****************************************************************************/ +#ifndef TYPEDATABASE_TYPEDEFS_H +#define TYPEDATABASE_TYPEDEFS_H -#ifndef ASTTOXML -#define ASTTOXML - -#include "parser/codemodel_fwd.h" - +#include <QtCore/QHash> #include <QtCore/QString> +#include <QtCore/QVector> -QT_FORWARD_DECLARE_CLASS(QXmlStreamWriter) +class ContainerTypeEntry; +class PrimitiveTypeEntry; +class TemplateEntry; +class TypeEntry; -void astToXML(const QString name); -void writeOutNamespace(QXmlStreamWriter &s, const NamespaceModelItem &item); -void writeOutEnum(QXmlStreamWriter &s, const EnumModelItem &item); -void writeOutFunction(QXmlStreamWriter &s, const FunctionModelItem &item); -void writeOutClass(QXmlStreamWriter &s, const ClassModelItem &item); +typedef QVector<TypeEntry *> TypeEntryList; +typedef QHash<QString, TypeEntryList> TypeEntryHash; +typedef QHash<QString, TypeEntry *> SingleTypeEntryHash; +typedef QHash<QString, TemplateEntry *> TemplateEntryHash; +typedef QVector<const ContainerTypeEntry *> ContainerTypeEntryList; +typedef QVector<const PrimitiveTypeEntry *> PrimitiveTypeEntryList; -#endif // ASTTOXML +#endif // TYPEDATABASE_TYPEDEFS_H diff --git a/sources/shiboken2/ApiExtractor/typeparser.cpp b/sources/shiboken2/ApiExtractor/typeparser.cpp index 67120a1ac..09439a210 100644 --- a/sources/shiboken2/ApiExtractor/typeparser.cpp +++ b/sources/shiboken2/ApiExtractor/typeparser.cpp @@ -286,7 +286,7 @@ QString TypeParser::Info::instantiationName() const QString s(qualified_name.join(QLatin1String("::"))); if (!template_instantiations.isEmpty()) { QStringList insts; - foreach (const Info &info, template_instantiations) + for (const Info &info : template_instantiations) insts << info.toString(); s += QLatin1String("< ") + insts.join(QLatin1String(", ")) + QLatin1String(" >"); } @@ -316,3 +316,47 @@ QString TypeParser::Info::toString() const } return s; } + +#ifndef QT_NO_DEBUG_STREAM + +static void formatTypeInfo(QDebug &d, const TypeParser::Info &i) +{ + if (i.is_busted) { + d << "busted"; + return; + } + + d << '"' << i.qualified_name << '"'; + if (!i.arrays.isEmpty()) { + d << ", arrays="; + for (const QString &a : i.arrays) + d << '[' << a << ']'; + } + if (!i.template_instantiations.isEmpty()) { + d << ", template_instantiations=["; + for (int t = 0, size = i.template_instantiations.size(); t < size; ++t) { + if (t) + d << ", "; + formatTypeInfo(d, i.template_instantiations.at(t)); + } + d << ']'; + } + if (i.referenceType != NoReference) + d << ", refType=" << i.referenceType; + if (i.is_constant) + d << ", [const]"; + if (i.indirections > 0) + d << ", indirections=" << i.indirections; +} + +QDebug operator<<(QDebug d, const TypeParser::Info &i) +{ + QDebugStateSaver saver(d); + d.noquote(); + d.nospace(); + d << "TypeParser::Info("; + formatTypeInfo(d, i); + d << ')'; + return d; +} +#endif // !QT_NO_DEBUG_STREAM diff --git a/sources/shiboken2/ApiExtractor/typeparser.h b/sources/shiboken2/ApiExtractor/typeparser.h index 9ccd0992c..568223656 100644 --- a/sources/shiboken2/ApiExtractor/typeparser.h +++ b/sources/shiboken2/ApiExtractor/typeparser.h @@ -34,6 +34,9 @@ #include <QtCore/QList> #include <QtCore/QString> #include <QtCore/QStringList> +#include <QtCore/QVector> + +QT_FORWARD_DECLARE_CLASS(QDebug) class TypeParser { @@ -43,7 +46,7 @@ public: Info() : referenceType(NoReference), is_constant(false), is_busted(false), indirections(0) { } QStringList qualified_name; QStringList arrays; - QList<Info> template_instantiations; + QVector<Info> template_instantiations; ReferenceType referenceType; uint is_constant : 1; uint is_busted : 1; @@ -56,4 +59,8 @@ public: static Info parse(const QString &str, QString *errorMessage = Q_NULLPTR); }; +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug d, const TypeParser::Info &); +#endif + #endif // TYPEPARSER_H diff --git a/sources/shiboken2/ApiExtractor/typesystem.cpp b/sources/shiboken2/ApiExtractor/typesystem.cpp index 869904d43..69dccbb86 100644 --- a/sources/shiboken2/ApiExtractor/typesystem.cpp +++ b/sources/shiboken2/ApiExtractor/typesystem.cpp @@ -32,6 +32,9 @@ #include "reporthandler.h" #include <QtCore/QDir> #include <QtCore/QFile> +#include <QtCore/QFileInfo> +#include <QtCore/QRegularExpression> +#include <QtCore/QSet> #include <QtCore/QXmlStreamAttributes> #include <QtCore/QXmlStreamReader> @@ -44,11 +47,92 @@ static QString strings_jobject = QLatin1String("jobject"); static inline QString colonColon() { return QStringLiteral("::"); } static inline QString quoteAfterLineAttribute() { return QStringLiteral("quote-after-line"); } static inline QString quoteBeforeLineAttribute() { return QStringLiteral("quote-before-line"); } +static inline QString textAttribute() { return QStringLiteral("text"); } static inline QString nameAttribute() { return QStringLiteral("name"); } static inline QString sinceAttribute() { return QStringLiteral("since"); } static inline QString flagsAttribute() { return QStringLiteral("flags"); } +static inline QString classAttribute() { return QStringLiteral("class"); } +static inline QString functionNameAttribute() { return QStringLiteral("function-name"); } +static inline QString fieldNameAttribute() { return QStringLiteral("field-name"); } +static inline QString enumNameAttribute() { return QStringLiteral("enum-name"); } +static inline QString argumentTypeAttribute() { return QStringLiteral("argument-type"); } +static inline QString returnTypeAttribute() { return QStringLiteral("return-type"); } +static inline QString xPathAttribute() { return QStringLiteral("xpath"); } +static inline QString enumIdentifiedByValueAttribute() { return QStringLiteral("identified-by-value"); } + +static inline QString noAttributeValue() { return QStringLiteral("no"); } +static inline QString yesAttributeValue() { return QStringLiteral("yes"); } +static inline QString trueAttributeValue() { return QStringLiteral("true"); } +static inline QString falseAttributeValue() { return QStringLiteral("false"); } + +static QVector<CustomConversion *> customConversionsForReview; + +// Set a regular expression for rejection from text. By legacy, those are fixed +// strings, except for '*' meaning 'match all'. Enclosing in "^..$" +// indicates regular expression. +static bool setRejectionRegularExpression(const QString &patternIn, + QRegularExpression *re, + QString *errorMessage) +{ + QString pattern; + if (patternIn.startsWith(QLatin1Char('^')) && patternIn.endsWith(QLatin1Char('$'))) + pattern = patternIn; + else if (patternIn == QLatin1String("*")) + pattern = QStringLiteral("^.*$"); + else + pattern = QLatin1Char('^') + QRegularExpression::escape(patternIn) + QLatin1Char('$'); + re->setPattern(pattern); + if (!re->isValid()) { + *errorMessage = QLatin1String("Invalid pattern \"") + patternIn + + QLatin1String("\": ") + re->errorString(); + return false; + } + return true; +} + +static bool addRejection(TypeDatabase *database, const QHash<QString, QString> &attributes, + QString *errorMessage) +{ + typedef QPair<QString, TypeRejection::MatchType> AttributeMatchTypePair; + + TypeRejection rejection; + + const QString className = attributes.value(classAttribute()); + if (!setRejectionRegularExpression(className, &rejection.className, errorMessage)) + return false; + + static const AttributeMatchTypePair attributeMatchTypeMapping[] = + {{functionNameAttribute(), TypeRejection::Function}, + {fieldNameAttribute(), TypeRejection::Field}, + {enumNameAttribute(), TypeRejection::Enum}, + {argumentTypeAttribute(), TypeRejection::ArgumentType}, + {returnTypeAttribute(), TypeRejection::ReturnType} + }; + + // Search for non-empty attribute (function, field, enum) + const auto aend = attributes.cend(); + for (const AttributeMatchTypePair &mapping : attributeMatchTypeMapping) { + const auto it = attributes.constFind(mapping.first); + if (it != aend && !it.value().isEmpty()) { + if (!setRejectionRegularExpression(it.value(), &rejection.pattern, errorMessage)) + return false; + rejection.matchType = mapping.second; + database->addRejection(rejection); + return true; + } + } + + // Special case: When all fields except class are empty, completely exclude class + if (className == QLatin1String("*")) { + *errorMessage = QLatin1String("bad reject entry, neither 'class', 'function-name'" + " nor 'field' specified"); + return false; + } + rejection.matchType = TypeRejection::ExcludeClass; + database->addRejection(rejection); + return true; +} -static QList<CustomConversion*> customConversionsForReview = QList<CustomConversion*>(); Handler::Handler(TypeDatabase* database, bool generate) : m_database(database), m_generate(generate ? TypeEntry::GenerateAll : TypeEntry::GenerateForSubclass) @@ -101,18 +185,26 @@ Handler::Handler(TypeDatabase* database, bool generate) tagNames.insert(QLatin1String("no-null-pointer"), StackElement::NoNullPointers); tagNames.insert(QLatin1String("reference-count"), StackElement::ReferenceCount); tagNames.insert(QLatin1String("parent"), StackElement::ParentOwner); + tagNames.insert(QLatin1String("array"), StackElement::Array); tagNames.insert(QLatin1String("inject-documentation"), StackElement::InjectDocumentation); tagNames.insert(QLatin1String("modify-documentation"), StackElement::ModifyDocumentation); tagNames.insert(QLatin1String("add-function"), StackElement::AddFunction); } +static QString readerFileName(const QXmlStreamReader &reader) +{ + const QFile *file = qobject_cast<const QFile *>(reader.device()); + return file != nullptr ? file->fileName() : QString(); +} + static QString msgReaderError(const QXmlStreamReader &reader, const QString &what) { QString message; QTextStream str(&message); str << "Error: "; - if (const QFile *file = qobject_cast<const QFile *>(reader.device())) - str << "file=" << QDir::toNativeSeparators(file->fileName()) << ", "; + const QString fileName = readerFileName(reader); + if (!fileName.isEmpty()) + str << "file=" << QDir::toNativeSeparators(fileName) << ", "; str << "line=" << reader.lineNumber() << ", column=" << reader.columnNumber() << ", message=" << what; return message; @@ -126,6 +218,11 @@ static QString msgReaderError(const QXmlStreamReader &reader) bool Handler::parse(QXmlStreamReader &reader) { m_error.clear(); + m_currentPath.clear(); + const QString fileName = readerFileName(reader); + if (!fileName.isEmpty()) + m_currentPath = QFileInfo(fileName).absolutePath(); + while (!reader.atEnd()) { switch (reader.readNext()) { case QXmlStreamReader::NoToken: @@ -209,8 +306,9 @@ bool Handler::endElement(const QStringRef &localName) if (m_generate == TypeEntry::GenerateAll) { TypeDatabase::instance()->addGlobalUserFunctions(m_contextStack.top()->addedFunctions); TypeDatabase::instance()->addGlobalUserFunctionModifications(m_contextStack.top()->functionMods); - foreach (CustomConversion* customConversion, customConversionsForReview) { - foreach (CustomConversion::TargetToNativeConversion* toNative, customConversion->targetToNativeConversions()) + for (CustomConversion *customConversion : qAsConst(customConversionsForReview)) { + const CustomConversion::TargetToNativeConversions &toNatives = customConversion->targetToNativeConversions(); + for (CustomConversion::TargetToNativeConversion *toNative : toNatives) toNative->setSourceType(m_database->findType(toNative->sourceTypeName())); } } @@ -281,6 +379,7 @@ bool Handler::endElement(const QStringRef &localName) m_current->parent->entry->setCodeSnips(snips); break; } + Q_FALLTHROUGH(); case StackElement::NativeToTarget: case StackElement::AddConversion: m_contextStack.top()->codeSnips.last().addTemplateInstance(m_current->value.templateInstance); @@ -441,21 +540,22 @@ bool Handler::importFileElement(const QXmlStreamAttributes &atts) return true; } -bool Handler::convertBoolean(const QString &_value, const QString &attributeName, bool defaultValue) +static bool convertBoolean(const QString &value, const QString &attributeName, bool defaultValue) { - QString value = _value.toLower(); - if (value == QLatin1String("true") || value == QLatin1String("yes")) + if (value.compare(trueAttributeValue(), Qt::CaseInsensitive) == 0 + || value.compare(yesAttributeValue(), Qt::CaseInsensitive) == 0) { return true; - else if (value == QLatin1String("false") || value == QLatin1String("no")) + } + if (value.compare(falseAttributeValue(), Qt::CaseInsensitive) == 0 + || value.compare(noAttributeValue(), Qt::CaseInsensitive) == 0) { return false; - else { - QString warn = QStringLiteral("Boolean value '%1' not supported in attribute '%2'. Use 'yes' or 'no'. Defaulting to '%3'.") + } + const QString warn = QStringLiteral("Boolean value '%1' not supported in attribute '%2'. Use 'yes' or 'no'. Defaulting to '%3'.") .arg(value, attributeName, - defaultValue ? QLatin1String("yes") : QLatin1String("no")); + defaultValue ? yesAttributeValue() : noAttributeValue()); - qCWarning(lcShiboken).noquote().nospace() << warn; - return defaultValue; - } + qCWarning(lcShiboken).noquote().nospace() << warn; + return defaultValue; } static bool convertRemovalAttribute(const QString& removalAttribute, Modification& mod, QString& errorMsg) @@ -493,7 +593,8 @@ static QString getNamePrefix(StackElement* element) static QString checkSignatureError(const QString& signature, const QString& tag) { QString funcName = signature.left(signature.indexOf(QLatin1Char('('))).trimmed(); - static QRegExp whiteSpace(QLatin1String("\\s")); + static const QRegularExpression whiteSpace(QStringLiteral("\\s")); + Q_ASSERT(whiteSpace.isValid()); if (!funcName.startsWith(QLatin1String("operator ")) && funcName.contains(whiteSpace)) { return QString::fromLatin1("Error in <%1> tag signature attribute '%2'.\n" "White spaces aren't allowed in function names, " @@ -521,11 +622,10 @@ void Handler::addFlags(const QString &name, QString flagName, if (QStringList(lst.mid(0, lst.size() - 1)).join(colonColon()) != m_currentEnum->targetLangQualifier()) { qCWarning(lcShiboken).noquote().nospace() << QStringLiteral("enum %1 and flags %2 differ in qualifiers") - // avoid constFirst to stay Qt 5.5 compatible - .arg(m_currentEnum->targetLangQualifier(), lst.first()); + .arg(m_currentEnum->targetLangQualifier(), lst.constFirst()); } - ftype->setFlagsName(lst.last()); + ftype->setFlagsName(lst.constLast()); m_currentEnum->setFlags(ftype); m_database->addFlagsType(ftype); @@ -640,8 +740,8 @@ bool Handler::startElement(const QStringRef &n, const QXmlStreamAttributes &atts case StackElement::PrimitiveTypeEntry: attributes.insert(QLatin1String("target-lang-name"), QString()); attributes.insert(QLatin1String("target-lang-api-name"), QString()); - attributes.insert(QLatin1String("preferred-conversion"), QLatin1String("yes")); - attributes.insert(QLatin1String("preferred-target-lang-type"), QLatin1String("yes")); + attributes.insert(QLatin1String("preferred-conversion"), yesAttributeValue()); + attributes.insert(QLatin1String("preferred-target-lang-type"), yesAttributeValue()); attributes.insert(QLatin1String("default-constructor"), QString()); break; case StackElement::ContainerTypeEntry: @@ -657,35 +757,36 @@ bool Handler::startElement(const QStringRef &n, const QXmlStreamAttributes &atts attributes.insert(QLatin1String("flags-revision"), QString()); attributes.insert(QLatin1String("upper-bound"), QString()); attributes.insert(QLatin1String("lower-bound"), QString()); - attributes.insert(QLatin1String("force-integer"), QLatin1String("no")); - attributes.insert(QLatin1String("extensible"), QLatin1String("no")); - attributes.insert(QLatin1String("identified-by-value"), QString()); + attributes.insert(QLatin1String("force-integer"), noAttributeValue()); + attributes.insert(QLatin1String("extensible"), noAttributeValue()); + attributes.insert(enumIdentifiedByValueAttribute(), QString()); + attributes.insert(classAttribute(), falseAttributeValue()); break; case StackElement::ValueTypeEntry: attributes.insert(QLatin1String("default-constructor"), QString()); - // fall throooough + Q_FALLTHROUGH(); case StackElement::ObjectTypeEntry: - attributes.insert(QLatin1String("force-abstract"), QLatin1String("no")); - attributes.insert(QLatin1String("deprecated"), QLatin1String("no")); + attributes.insert(QLatin1String("force-abstract"), noAttributeValue()); + attributes.insert(QLatin1String("deprecated"), noAttributeValue()); attributes.insert(QLatin1String("hash-function"), QString()); - attributes.insert(QLatin1String("stream"), QLatin1String("no")); - // fall throooough + attributes.insert(QLatin1String("stream"), noAttributeValue()); + Q_FALLTHROUGH(); case StackElement::InterfaceTypeEntry: attributes[QLatin1String("default-superclass")] = m_defaultSuperclass; attributes.insert(QLatin1String("polymorphic-id-expression"), QString()); - attributes.insert(QLatin1String("delete-in-main-thread"), QLatin1String("no")); + attributes.insert(QLatin1String("delete-in-main-thread"), noAttributeValue()); attributes.insert(QLatin1String("held-type"), QString()); attributes.insert(QLatin1String("copyable"), QString()); - // fall through + Q_FALLTHROUGH(); case StackElement::NamespaceTypeEntry: attributes.insert(QLatin1String("target-lang-name"), QString()); attributes[QLatin1String("package")] = m_defaultPackage; attributes.insert(QLatin1String("expense-cost"), QLatin1String("1")); attributes.insert(QLatin1String("expense-limit"), QLatin1String("none")); - attributes.insert(QLatin1String("polymorphic-base"), QLatin1String("no")); - attributes.insert(QLatin1String("generate"), QLatin1String("yes")); + attributes.insert(QLatin1String("polymorphic-base"), noAttributeValue()); + attributes.insert(QLatin1String("generate"), yesAttributeValue()); attributes.insert(QLatin1String("target-type"), QString()); - attributes.insert(QLatin1String("generic-class"), QLatin1String("no")); + attributes.insert(QLatin1String("generic-class"), noAttributeValue()); break; case StackElement::FunctionTypeEntry: attributes.insert(QLatin1String("signature"), QString()); @@ -725,14 +826,16 @@ bool Handler::startElement(const QStringRef &n, const QXmlStreamAttributes &atts } QString rename = attributes[QLatin1String("rename")]; if (!rename.isEmpty()) { - static QRegExp functionNameRegExp(QLatin1String("^[a-zA-Z_][a-zA-Z0-9_]*$")); - if (!functionNameRegExp.exactMatch(rename)) { + static const QRegularExpression functionNameRegExp(QLatin1String("^[a-zA-Z_][a-zA-Z0-9_]*$")); + Q_ASSERT(functionNameRegExp.isValid()); + if (!functionNameRegExp.match(rename).hasMatch()) { m_error = QLatin1String("can not rename '") + signature + QLatin1String("', '") + rename + QLatin1String("' is not a valid function name"); return false; } - FunctionModification mod(since); - mod.signature = signature; + FunctionModification mod; + if (!mod.setSignature(signature, &m_error)) + return false; mod.renamedToName = attributes[QLatin1String("rename")]; mod.modifiers |= Modification::Rename; m_contextStack.top()->functionMods << mod; @@ -751,9 +854,10 @@ bool Handler::startElement(const QStringRef &n, const QXmlStreamAttributes &atts } if (element->type == StackElement::EnumTypeEntry) { + const QString identifiedByValue = attributes.value(enumIdentifiedByValueAttribute()); if (name.isEmpty()) { - name = attributes[QLatin1String("identified-by-value")]; - } else if (!attributes[QLatin1String("identified-by-value")].isEmpty()) { + name = identifiedByValue; + } else if (!identifiedByValue.isEmpty()) { m_error = QLatin1String("can't specify both 'name' and 'identified-by-value' attributes"); return false; } @@ -837,8 +941,12 @@ bool Handler::startElement(const QStringRef &n, const QXmlStreamAttributes &atts else m_currentEnum = new EnumTypeEntry(QStringList(names.mid(0, names.size() - 1)).join(colonColon()), - names.last(), since); - m_currentEnum->setAnonymous(!attributes[QLatin1String("identified-by-value")].isEmpty()); + names.constLast(), since); + if (!attributes.value(enumIdentifiedByValueAttribute()).isEmpty()) { + m_currentEnum->setEnumKind(EnumTypeEntry::AnonymousEnum); + } else if (convertBoolean(attributes.value(classAttribute()), classAttribute(), false)) { + m_currentEnum->setEnumKind(EnumTypeEntry::EnumClass); + } element->entry = m_currentEnum; m_currentEnum->setCodeGeneration(m_generate); m_currentEnum->setTargetLangPackage(m_defaultPackage); @@ -850,7 +958,8 @@ bool Handler::startElement(const QStringRef &n, const QXmlStreamAttributes &atts // put in the flags parallel... const QString flagNames = attributes.value(flagsAttribute()); if (!flagNames.isEmpty()) { - foreach (const QString &flagName, flagNames.split(QLatin1Char(','))) + const QStringList &flagNameList = flagNames.split(QLatin1Char(',')); + for (const QString &flagName : flagNameList) addFlags(name, flagName.trimmed(), attributes, since); } } @@ -872,7 +981,7 @@ bool Handler::startElement(const QStringRef &n, const QXmlStreamAttributes &atts itype->setOrigin(otype); element->entry = otype; } - // fall through + Q_FALLTHROUGH(); case StackElement::ValueTypeEntry: { if (!element->entry) { ValueTypeEntry* typeEntry = new ValueTypeEntry(name, since); @@ -882,17 +991,17 @@ bool Handler::startElement(const QStringRef &n, const QXmlStreamAttributes &atts element->entry = typeEntry; } - // fall through + Q_FALLTHROUGH(); case StackElement::NamespaceTypeEntry: if (!element->entry) element->entry = new NamespaceTypeEntry(name, since); - // fall through + Q_FALLTHROUGH(); case StackElement::ObjectTypeEntry: if (!element->entry) element->entry = new ObjectTypeEntry(name, since); - element->entry->setStream(attributes[QLatin1String("stream")] == QLatin1String("yes")); + element->entry->setStream(attributes[QLatin1String("stream")] == yesAttributeValue()); ComplexTypeEntry *ctype = static_cast<ComplexTypeEntry *>(element->entry); ctype->setTargetLangPackage(attributes[QLatin1String("package")]); @@ -908,16 +1017,6 @@ bool Handler::startElement(const QStringRef &n, const QXmlStreamAttributes &atts if (!targetLangName.isEmpty()) ctype->setTargetLangName(targetLangName); - // The expense policy - QString limit = attributes[QLatin1String("expense-limit")]; - if (!limit.isEmpty() && limit != QLatin1String("none")) { - ExpensePolicy ep; - ep.limit = limit.toInt(); - ep.cost = attributes[QLatin1String("expense-cost")]; - ctype->setExpensePolicy(ep); - } - - ctype->setIsPolymorphicBase(convertBoolean(attributes[QLatin1String("polymorphic-base")], QLatin1String("polymorphic-base"), false)); ctype->setPolymorphicIdValue(attributes[QLatin1String("polymorphic-id-expression")]); //Copyable @@ -1001,7 +1100,6 @@ bool Handler::startElement(const QStringRef &n, const QXmlStreamAttributes &atts attributes.insert(sinceAttribute(), QLatin1String("0")); fetchAttributeValues(tagName, atts, &attributes); - double since = attributes[sinceAttribute()].toDouble(); const int validParent = StackElement::TypeEntryMask | StackElement::ModifyFunction @@ -1034,8 +1132,8 @@ bool Handler::startElement(const QStringRef &n, const QXmlStreamAttributes &atts } QString signature = m_current->type & StackElement::TypeEntryMask ? QString() : m_currentSignature; - DocModification mod(mode, signature, since); - mod.format = lang; + DocModification mod(mode, signature); + mod.setFormat(lang); m_contextStack.top()->docModifications << mod; } else { m_error = QLatin1String("inject-documentation must be inside modify-function, " @@ -1045,17 +1143,17 @@ bool Handler::startElement(const QStringRef &n, const QXmlStreamAttributes &atts } else if (element->type == StackElement::ModifyDocumentation) { // check the XML tag attributes QHash<QString, QString> attributes; - attributes.insert(QLatin1String("xpath"), QString()); + attributes.insert(xPathAttribute(), QString()); attributes.insert(sinceAttribute(), QLatin1String("0")); fetchAttributeValues(tagName, atts, &attributes); - double since = attributes[sinceAttribute()].toDouble(); const int validParent = StackElement::TypeEntryMask | StackElement::ModifyFunction | StackElement::ModifyField; if (m_current->parent && m_current->parent->type & validParent) { QString signature = (m_current->type & StackElement::TypeEntryMask) ? QString() : m_currentSignature; - m_contextStack.top()->docModifications << DocModification(attributes[QLatin1String("xpath")], signature, since); + m_contextStack.top()->docModifications + << DocModification(attributes.value(xPathAttribute()), signature); } else { m_error = QLatin1String("modify-documentation must be inside modify-function, " "modify-field or other tags that creates a type"); @@ -1089,13 +1187,13 @@ bool Handler::startElement(const QStringRef &n, const QXmlStreamAttributes &atts break; case StackElement::LoadTypesystem: attributes.insert(nameAttribute(), QString()); - attributes.insert(QLatin1String("generate"), QLatin1String("yes")); + attributes.insert(QLatin1String("generate"), yesAttributeValue()); break; case StackElement::NoNullPointers: attributes.insert(QLatin1String("default-value"), QString()); break; case StackElement::SuppressedWarning: - attributes.insert(QLatin1String("text"), QString()); + attributes.insert(textAttribute(), QString()); break; case StackElement::ReplaceDefaultExpression: attributes.insert(QLatin1String("with"), QString()); @@ -1108,28 +1206,28 @@ bool Handler::startElement(const QStringRef &n, const QXmlStreamAttributes &atts attributes.insert(QLatin1String("signature"), QString()); attributes.insert(QLatin1String("return-type"), QLatin1String("void")); attributes.insert(QLatin1String("access"), QLatin1String("public")); - attributes.insert(QLatin1String("static"), QLatin1String("no")); + attributes.insert(QLatin1String("static"), noAttributeValue()); break; case StackElement::ModifyFunction: attributes.insert(QLatin1String("signature"), QString()); attributes.insert(QLatin1String("access"), QString()); attributes.insert(QLatin1String("remove"), QString()); attributes.insert(QLatin1String("rename"), QString()); - attributes.insert(QLatin1String("deprecated"), QLatin1String("no")); + attributes.insert(QLatin1String("deprecated"), noAttributeValue()); attributes.insert(QLatin1String("associated-to"), QString()); - attributes.insert(QLatin1String("virtual-slot"), QLatin1String("no")); - attributes.insert(QLatin1String("thread"), QLatin1String("no")); - attributes.insert(QLatin1String("allow-thread"), QLatin1String("no")); + attributes.insert(QLatin1String("virtual-slot"), noAttributeValue()); + attributes.insert(QLatin1String("thread"), noAttributeValue()); + attributes.insert(QLatin1String("allow-thread"), noAttributeValue()); break; case StackElement::ModifyArgument: attributes.insert(QLatin1String("index"), QString()); attributes.insert(QLatin1String("replace-value"), QString()); - attributes.insert(QLatin1String("invalidate-after-use"), QLatin1String("no")); + attributes.insert(QLatin1String("invalidate-after-use"), noAttributeValue()); break; case StackElement::ModifyField: attributes.insert(nameAttribute(), QString()); - attributes.insert(QLatin1String("write"), QLatin1String("true")); - attributes.insert(QLatin1String("read"), QLatin1String("true")); + attributes.insert(QLatin1String("write"), trueAttributeValue()); + attributes.insert(QLatin1String("read"), trueAttributeValue()); attributes.insert(QLatin1String("remove"), QString()); break; case StackElement::Access: @@ -1160,7 +1258,7 @@ bool Handler::startElement(const QStringRef &n, const QXmlStreamAttributes &atts attributes.insert(QLatin1String("file"), QString()); break; case StackElement::TargetToNative: - attributes.insert(QLatin1String("replace"), QLatin1String("yes")); + attributes.insert(QLatin1String("replace"), yesAttributeValue()); break; case StackElement::AddConversion: attributes.insert(QLatin1String("type"), QString()); @@ -1177,10 +1275,12 @@ bool Handler::startElement(const QStringRef &n, const QXmlStreamAttributes &atts attributes.insert(QLatin1String("to"), QString()); break; case StackElement::Rejection: - attributes.insert(QLatin1String("class"), QLatin1String("*")); - attributes.insert(QLatin1String("function-name"), QLatin1String("*")); - attributes.insert(QLatin1String("field-name"), QLatin1String("*")); - attributes.insert(QLatin1String("enum-name"), QLatin1String("*")); + attributes.insert(classAttribute(), QString()); + attributes.insert(functionNameAttribute(), QString()); + attributes.insert(fieldNameAttribute(), QString()); + attributes.insert(enumNameAttribute(), QString()); + attributes.insert(argumentTypeAttribute(), QString()); + attributes.insert(returnTypeAttribute(), QString()); break; case StackElement::Removal: attributes.insert(QLatin1String("class"), QLatin1String("all")); @@ -1202,6 +1302,9 @@ bool Handler::startElement(const QStringRef &n, const QXmlStreamAttributes &atts case StackElement::ParentOwner: attributes.insert(QLatin1String("index"), QString()); attributes.insert(QLatin1String("action"), QString()); + break; + case StackElement::Array: + break; default: { }; }; @@ -1238,19 +1341,18 @@ bool Handler::startElement(const QStringRef &n, const QXmlStreamAttributes &atts return false; } bool generateChild = (convertBoolean(attributes[QLatin1String("generate")], QLatin1String("generate"), true) && (m_generate == TypeEntry::GenerateAll)); - if (!m_database->parseFile(name, generateChild)) { + if (!m_database->parseFile(name, m_currentPath, generateChild)) { m_error = QStringLiteral("Failed to parse: '%1'").arg(name); return false; } } break; - case StackElement::RejectEnumValue: { + case StackElement::RejectEnumValue: if (!m_currentEnum) { m_error = QLatin1String("<reject-enum-value> node must be used inside a <enum-type> node"); return false; } - QString name = attributes[nameAttribute()]; - } break; + break; case StackElement::ReplaceType: { if (topElement.type != StackElement::ModifyArgument) { m_error = QLatin1String("Type replacement can only be specified for argument modifications"); @@ -1290,7 +1392,7 @@ bool Handler::startElement(const QStringRef &n, const QXmlStreamAttributes &atts return false; } - CodeSnip snip(since); + CodeSnip snip; snip.language = lang; m_contextStack.top()->functionMods.last().argument_mods.last().conversion_rules.append(snip); } else { @@ -1332,7 +1434,7 @@ bool Handler::startElement(const QStringRef &n, const QXmlStreamAttributes &atts m_error = QLatin1String("Native to Target conversion code can only be specified for custom conversion rules."); return false; } - m_contextStack.top()->codeSnips << CodeSnip(0); + m_contextStack.top()->codeSnips << CodeSnip(); } break; case StackElement::TargetToNative: { @@ -1340,7 +1442,7 @@ bool Handler::startElement(const QStringRef &n, const QXmlStreamAttributes &atts m_error = QLatin1String("Target to Native conversions can only be specified for custom conversion rules."); return false; } - bool replace = attributes[QLatin1String("replace")] == QLatin1String("yes"); + bool replace = attributes[QLatin1String("replace")] == yesAttributeValue(); static_cast<TypeEntry*>(m_current->entry)->customConversion()->setReplaceOriginalTargetToNativeConversions(replace); } break; @@ -1356,7 +1458,7 @@ bool Handler::startElement(const QStringRef &n, const QXmlStreamAttributes &atts } QString typeCheck = attributes[QLatin1String("check")]; static_cast<TypeEntry*>(m_current->entry)->customConversion()->addTargetToNativeConversion(sourceTypeName, typeCheck); - m_contextStack.top()->codeSnips << CodeSnip(0); + m_contextStack.top()->codeSnips << CodeSnip(); } break; case StackElement::ModifyArgument: { @@ -1388,7 +1490,7 @@ bool Handler::startElement(const QStringRef &n, const QXmlStreamAttributes &atts return false; } - ArgumentModification argumentModification = ArgumentModification(idx, since); + ArgumentModification argumentModification = ArgumentModification(idx); argumentModification.replace_value = replace_value; argumentModification.resetAfterUse = convertBoolean(attributes[QLatin1String("invalidate-after-use")], QLatin1String("invalidate-after-use"), false); m_contextStack.top()->functionMods.last().argument_mods.append(argumentModification); @@ -1444,11 +1546,15 @@ bool Handler::startElement(const QStringRef &n, const QXmlStreamAttributes &atts m_contextStack.top()->functionMods.last().argument_mods.last().ownerships[lang] = owner; } break; - case StackElement::SuppressedWarning: - if (attributes[QLatin1String("text")].isEmpty()) + case StackElement::SuppressedWarning: { + const QString suppressedWarning = attributes.value(textAttribute()); + if (suppressedWarning.isEmpty()) { qCWarning(lcShiboken) << "Suppressed warning with no text specified"; - else - m_database->addSuppressedWarning(attributes[QLatin1String("text")]); + } else { + if (!m_database->addSuppressedWarning(suppressedWarning, &m_error)) + return false; + } + } break; case StackElement::ArgumentMap: { if (!(topElement.type & StackElement::CodeSnipMask)) { @@ -1586,8 +1692,8 @@ bool Handler::startElement(const QStringRef &n, const QXmlStreamAttributes &atts QString read = attributes[QLatin1String("read")]; QString write = attributes[QLatin1String("write")]; - if (read == QLatin1String("true")) fm.modifiers |= FieldModification::Readable; - if (write == QLatin1String("true")) fm.modifiers |= FieldModification::Writable; + if (read == trueAttributeValue()) fm.modifiers |= FieldModification::Readable; + if (write == trueAttributeValue()) fm.modifiers |= FieldModification::Writable; m_contextStack.top()->fieldMods << fm; } @@ -1613,7 +1719,7 @@ bool Handler::startElement(const QStringRef &n, const QXmlStreamAttributes &atts } AddedFunction func(signature, attributes[QLatin1String("return-type")], since); - func.setStatic(attributes[QLatin1String("static")] == QLatin1String("yes")); + func.setStatic(attributes[QLatin1String("static")] == yesAttributeValue()); if (!signature.contains(QLatin1Char('('))) signature += QLatin1String("()"); m_currentSignature = signature; @@ -1632,8 +1738,9 @@ bool Handler::startElement(const QStringRef &n, const QXmlStreamAttributes &atts m_contextStack.top()->addedFunctions << func; - FunctionModification mod(since); - mod.signature = m_currentSignature; + FunctionModification mod; + if (!mod.setSignature(m_currentSignature, &m_error)) + return false; m_contextStack.top()->functionMods << mod; } break; @@ -1657,8 +1764,10 @@ bool Handler::startElement(const QStringRef &n, const QXmlStreamAttributes &atts return false; } - FunctionModification mod(since); - m_currentSignature = mod.signature = signature; + FunctionModification mod; + if (!mod.setSignature(signature, &m_error)) + return false; + m_currentSignature = signature; QString access = attributes[QLatin1String("access")].toLower(); if (!access.isEmpty()) { @@ -1746,8 +1855,8 @@ bool Handler::startElement(const QStringRef &n, const QXmlStreamAttributes &atts if (rc.action == ReferenceCount::Invalid) { m_error = QLatin1String("unrecognized value for action attribute. supported actions:"); - foreach (const QString &action, actions.keys()) - m_error += QLatin1Char(' ') + action; + for (QHash<QString, ReferenceCount::Action>::const_iterator it = actions.cbegin(), end = actions.cend(); it != end; ++it) + m_error += QLatin1Char(' ') + it.key(); } m_contextStack.top()->functionMods.last().argument_mods.last().referenceCounts.append(rc); @@ -1790,8 +1899,13 @@ bool Handler::startElement(const QStringRef &n, const QXmlStreamAttributes &atts m_contextStack.top()->functionMods.last().argument_mods.last().owner = ao; } break; - - + case StackElement::Array: + if (topElement.type != StackElement::ModifyArgument) { + m_error = QLatin1String("array must be child of modify-argument"); + return false; + } + m_contextStack.top()->functionMods.last().argument_mods.last().array = true; + break; case StackElement::InjectCode: { if (!(topElement.type & StackElement::ComplexTypeEntryMask) && (topElement.type != StackElement::AddFunction) @@ -1837,7 +1951,7 @@ bool Handler::startElement(const QStringRef &n, const QXmlStreamAttributes &atts return false; } - CodeSnip snip(since); + CodeSnip snip; snip.language = languageNames[className]; snip.position = positionNames[position]; bool in_file = false; @@ -1848,8 +1962,9 @@ bool Handler::startElement(const QStringRef &n, const QXmlStreamAttributes &atts if (m_generate != TypeEntry::GenerateForSubclass && m_generate != TypeEntry::GenerateNothing && !file_name.isEmpty()) { - if (QFile::exists(file_name)) { - QFile codeFile(file_name); + const QString resolved = m_database->modifiedTypesystemFilepath(file_name, m_currentPath); + if (QFile::exists(resolved)) { + QFile codeFile(resolved); if (codeFile.open(QIODevice::Text | QIODevice::ReadOnly)) { QString content = QLatin1String("// ========================================================================\n" "// START of custom code block [file: "); @@ -1875,7 +1990,7 @@ bool Handler::startElement(const QStringRef &n, const QXmlStreamAttributes &atts } if (topElement.type == StackElement::ModifyFunction || topElement.type == StackElement::AddFunction) { - FunctionModification mod = m_contextStack.top()->functionMods.last(); + FunctionModification mod = m_contextStack.top()->functionMods.constLast(); if (snip.language == TypeSystem::ShellDeclaration) { m_error = QLatin1String("no function implementation in shell declaration in which to inject code"); return false; @@ -1930,21 +2045,12 @@ bool Handler::startElement(const QStringRef &n, const QXmlStreamAttributes &atts } } break; - case StackElement::Rejection: { - QString cls = attributes[QLatin1String("class")]; - QString function = attributes[QLatin1String("function-name")]; - QString field = attributes[QLatin1String("field-name")]; - QString enum_ = attributes[QLatin1String("enum-name")]; - if (cls == QLatin1String("*") && function == QLatin1String("*") && field == QLatin1String("*") && enum_ == QLatin1String("*")) { - m_error = QLatin1String("bad reject entry, neither 'class', 'function-name' nor " - "'field' specified"); + case StackElement::Rejection: + if (!addRejection(m_database, attributes, &m_error)) return false; - } - m_database->addRejection(cls, function, field, enum_); - } break; case StackElement::Template: - element->value.templateEntry = new TemplateEntry(attributes[nameAttribute()], since); + element->value.templateEntry = new TemplateEntry(attributes.value(nameAttribute())); break; case StackElement::TemplateInstanceEnum: if (!(topElement.type & StackElement::CodeSnipMask) && @@ -1958,7 +2064,7 @@ bool Handler::startElement(const QStringRef &n, const QXmlStreamAttributes &atts "custom-destructors, conversion-rule, native-to-target or add-conversion tags."); return false; } - element->value.templateInstance = new TemplateInstance(attributes[nameAttribute()], since); + element->value.templateInstance = new TemplateInstance(attributes.value(nameAttribute())); break; case StackElement::Replace: if (topElement.type != StackElement::TemplateInstanceEnum) { @@ -1976,6 +2082,23 @@ bool Handler::startElement(const QStringRef &n, const QXmlStreamAttributes &atts return true; } +PrimitiveTypeEntry::PrimitiveTypeEntry(const QString &name, double vr) : + TypeEntry(name, PrimitiveType, vr), + m_preferredConversion(true), + m_preferredTargetLangType(true) +{ +} + +QString PrimitiveTypeEntry::targetLangName() const +{ + return m_targetLangName; +} + +QString PrimitiveTypeEntry::targetLangApiName() const +{ + return m_targetLangApiName; +} + PrimitiveTypeEntry *PrimitiveTypeEntry::basicReferencedTypeEntry() const { if (!m_referencedTypeEntry) @@ -1988,6 +2111,16 @@ PrimitiveTypeEntry *PrimitiveTypeEntry::basicReferencedTypeEntry() const return m_referencedTypeEntry; } +bool PrimitiveTypeEntry::preferredConversion() const +{ + return m_preferredConversion; +} + +void PrimitiveTypeEntry::setPreferredConversion(bool b) +{ + m_preferredConversion = b; +} + typedef QHash<const PrimitiveTypeEntry*, QString> PrimitiveTypeEntryTargetLangPackageMap; Q_GLOBAL_STATIC(PrimitiveTypeEntryTargetLangPackageMap, primitiveTypeEntryTargetLangPackages); @@ -2021,7 +2154,7 @@ FunctionModificationList ComplexTypeEntry::functionModifications(const QString & FunctionModificationList lst; for (int i = 0; i < m_functionMods.count(); ++i) { const FunctionModification &mod = m_functionMods.at(i); - if (mod.signature == signature) + if (mod.matches(signature)) lst << mod; } return lst; @@ -2038,6 +2171,17 @@ FieldModification ComplexTypeEntry::fieldModification(const QString &name) const return mod; } +QString ComplexTypeEntry::targetLangPackage() const +{ + return m_package; +} + +QString ComplexTypeEntry::targetLangName() const +{ + return m_targetLangName.isEmpty() ? + TypeEntry::targetLangName() : m_targetLangName; +} + // The things we do not to break the ABI... typedef QHash<const ComplexTypeEntry*, QString> ComplexTypeEntryDefaultConstructorMap; Q_GLOBAL_STATIC(ComplexTypeEntryDefaultConstructorMap, complexTypeEntryDefaultConstructors); @@ -2102,27 +2246,44 @@ QString EnumTypeEntry::targetLangQualifier() const return m_qualifier; } +QString EnumTypeEntry::qualifiedTargetLangName() const +{ + QString qualifiedName; + QString pkg = targetLangPackage(); + QString qualifier = targetLangQualifier(); + + if (!pkg.isEmpty()) + qualifiedName += pkg + QLatin1Char('.'); + if (!qualifier.isEmpty()) + qualifiedName += qualifier + QLatin1Char('.'); + qualifiedName += targetLangName(); + + return qualifiedName; +} + QString EnumTypeEntry::targetLangApiName() const { return QLatin1String("jint"); } +bool EnumTypeEntry::preferredConversion() const +{ + return false; +} + QString FlagsTypeEntry::targetLangApiName() const { return QLatin1String("jint"); } -void EnumTypeEntry::addEnumValueRedirection(const QString &rejected, const QString &usedValue) +bool FlagsTypeEntry::preferredConversion() const { - m_enumRedirections << EnumValueRedirection(rejected, usedValue); + return false; } -QString EnumTypeEntry::enumValueRedirection(const QString &value) const +QString FlagsTypeEntry::targetLangPackage() const { - for (int i = 0; i < m_enumRedirections.size(); ++i) - if (m_enumRedirections.at(i).rejected == value) - return m_enumRedirections.at(i).used; - return QString(); + return m_enum->targetLangPackage(); } QString FlagsTypeEntry::qualifiedTargetLangName() const @@ -2131,6 +2292,11 @@ QString FlagsTypeEntry::qualifiedTargetLangName() const + QLatin1Char('.') + targetLangName(); } +QString FlagsTypeEntry::targetLangName() const +{ + return m_targetLangName; +} + /*! * The Visual Studio 2002 compiler doesn't support these symbols, * which our typedefs unforntuatly expand to. @@ -2172,7 +2338,7 @@ QString TemplateInstance::expandCode() const QString CodeSnipAbstract::code() const { QString res; - foreach (const CodeSnipFragment &codeFrag, codeList) + for (const CodeSnipFragment &codeFrag : codeList) res.append(codeFrag.code()); return res; @@ -2186,9 +2352,26 @@ QString CodeSnipFragment::code() const return m_code; } +bool FunctionModification::setSignature(const QString &s, QString *errorMessage) +{ + if (s.startsWith(QLatin1Char('^'))) { + m_signaturePattern.setPattern(s); + if (!m_signaturePattern.isValid()) { + if (errorMessage) { + *errorMessage = QLatin1String("Invalid signature pattern: \"") + + s + QLatin1String("\": ") + m_signaturePattern.errorString(); + } + return false; + } + } else { + m_signature = s; + } + return true; +} + QString FunctionModification::toString() const { - QString str = signature + QLatin1String("->"); + QString str = signature() + QLatin1String("->"); if (modifiers & AccessModifierMask) { switch (modifiers & AccessModifierMask) { case Private: str += QLatin1String("private"); break; @@ -2205,7 +2388,7 @@ QString FunctionModification::toString() const if (modifiers & Writable) str += QLatin1String("writable"); if (modifiers & CodeInjection) { - foreach (const CodeSnip &s, snips) { + for (const CodeSnip &s : snips) { str += QLatin1String("\n//code injection:\n"); str += s.code(); } @@ -2220,41 +2403,11 @@ QString FunctionModification::toString() const return str; } -bool FunctionModification::operator!=(const FunctionModification& other) const -{ - return !(*this == other); -} - -bool FunctionModification::operator==(const FunctionModification& other) const -{ - if (signature != other.signature) - return false; - - if (association != other.association) - return false; - - if (modifiers != other.modifiers) - return false; - - if (removal != other.removal) - return false; - - if (m_thread != other.m_thread) - return false; - - if (m_allowThread != other.m_allowThread) - return false; - - if (m_version != other.m_version) - return false; - - return true; -} - static AddedFunction::TypeInfo parseType(const QString& signature, int startPos = 0, int* endPos = 0) { AddedFunction::TypeInfo result; - QRegExp regex(QLatin1String("\\w")); + static const QRegularExpression regex(QLatin1String("\\w")); + Q_ASSERT(regex.isValid()); int length = signature.length(); int start = signature.indexOf(regex, startPos); if (start == -1) { @@ -2318,7 +2471,9 @@ static AddedFunction::TypeInfo parseType(const QString& signature, int startPos return result; } -AddedFunction::AddedFunction(QString signature, QString returnType, double vr) : m_access(Public), m_version(vr) +AddedFunction::AddedFunction(QString signature, QString returnType, double vr) : + m_version(vr), + m_access(Public) { Q_ASSERT(!returnType.isEmpty()); m_returnType = parseType(returnType); @@ -2339,7 +2494,7 @@ AddedFunction::AddedFunction(QString signature, QString returnType, double vr) : break; } // is const? - m_isConst = signature.right(signatureLength - endPos).contains(QLatin1String("const")); + m_isConst = signature.rightRef(signatureLength - endPos).contains(QLatin1String("const")); } } @@ -2385,6 +2540,25 @@ AddedFunction::TypeInfo AddedFunction::TypeInfo::fromSignature(const QString& si return parseType(signature); } +ComplexTypeEntry::ComplexTypeEntry(const QString &name, TypeEntry::Type t, double vr) : + TypeEntry(QString(name).replace(QLatin1String(".*::"), QString()), t, vr), + m_qualifiedCppName(name), + m_qobject(false), + m_polymorphicBase(false), + m_genericClass(false) +{ +} + +bool ComplexTypeEntry::isComplex() const +{ + return true; +} + +QString ComplexTypeEntry::lookupName() const +{ + return m_lookupName.isEmpty() ? targetLangName() : m_lookupName; +} + QString ComplexTypeEntry::targetLangApiName() const { return strings_jobject; @@ -2401,6 +2575,18 @@ QString StringTypeEntry::targetLangPackage() const { return QString(); } + +bool StringTypeEntry::isNativeIdBased() const +{ + return false; +} + +CharTypeEntry::CharTypeEntry(const QString &name, double vr) : + ValueTypeEntry(name, CharType, vr) +{ + setCodeGeneration(GenerateNothing); +} + QString CharTypeEntry::targetLangApiName() const { return strings_jchar; @@ -2409,6 +2595,22 @@ QString CharTypeEntry::targetLangName() const { return strings_char; } + +QString CharTypeEntry::targetLangPackage() const +{ + return QString(); +} + +bool CharTypeEntry::isNativeIdBased() const +{ + return false; +} + +VariantTypeEntry::VariantTypeEntry(const QString &name, double vr) : + ValueTypeEntry(name, VariantType, vr) +{ +} + QString VariantTypeEntry::targetLangApiName() const { return strings_jobject; @@ -2422,6 +2624,11 @@ QString VariantTypeEntry::targetLangPackage() const return QString(); } +bool VariantTypeEntry::isNativeIdBased() const +{ + return false; +} + QString ContainerTypeEntry::typeName() const { switch(m_type) { @@ -2455,9 +2662,19 @@ QString ContainerTypeEntry::typeName() const } } -static bool strLess(const char* a, const char* b) +static const QSet<QString> &primitiveCppTypes() { - return ::strcmp(a, b) < 0; + static QSet<QString> result; + if (result.isEmpty()) { + static const char *cppTypes[] = { + "bool", "char", "double", "float", "int", + "long", "long long", "short", + "wchar_t" + }; + for (const char *cppType : cppTypes) + result.insert(QLatin1String(cppType)); + } + return result; } bool TypeEntry::isCppPrimitive() const @@ -2465,25 +2682,26 @@ bool TypeEntry::isCppPrimitive() const if (!isPrimitive()) return false; - const PrimitiveTypeEntry *referencedType = - static_cast<const PrimitiveTypeEntry *>(this)->basicReferencedTypeEntry(); - QByteArray typeName = (referencedType ? referencedType->name() : m_name).toUtf8(); - - if (typeName.contains(' ') || m_type == VoidType) + if (m_type == VoidType) return true; - // Keep this sorted!! - static const char* cppTypes[] = { "bool", "char", "double", "float", "int", "long", "long long", "short", "wchar_t" }; - const int N = sizeof(cppTypes)/sizeof(char*); - - const char** res = qBinaryFind(&cppTypes[0], &cppTypes[N], typeName.constData(), strLess); - return res != &cppTypes[N]; + const PrimitiveTypeEntry *referencedType = + static_cast<const PrimitiveTypeEntry *>(this)->basicReferencedTypeEntry(); + const QString &typeName = referencedType ? referencedType->name() : m_name; + return typeName.contains(QLatin1Char(' ')) || primitiveCppTypes().contains(typeName); } // Again, stuff to avoid ABI breakage. typedef QHash<const TypeEntry*, CustomConversion*> TypeEntryCustomConversionMap; Q_GLOBAL_STATIC(TypeEntryCustomConversionMap, typeEntryCustomConversionMap); +TypeEntry::TypeEntry(const QString &name, TypeEntry::Type t, double vr) : + m_name(name), + m_type(t), + m_version(vr) +{ +} + TypeEntry::~TypeEntry() { if (typeEntryCustomConversionMap()->contains(this)) { @@ -2511,6 +2729,131 @@ CustomConversion* TypeEntry::customConversion() const return 0; } +TypeSystemTypeEntry::TypeSystemTypeEntry(const QString &name, double vr) : + TypeEntry(name, TypeSystemType, vr) +{ +} + +VoidTypeEntry::VoidTypeEntry() : + TypeEntry(QLatin1String("void"), VoidType, 0) +{ +} + +VarargsTypeEntry::VarargsTypeEntry() : + TypeEntry(QLatin1String("..."), VarargsType, 0) +{ +} + +TemplateArgumentEntry::TemplateArgumentEntry(const QString &name, double vr) : + TypeEntry(name, TemplateArgumentType, vr) +{ +} + +ArrayTypeEntry::ArrayTypeEntry(const TypeEntry *nested_type, double vr) : + TypeEntry(QLatin1String("Array"), ArrayType, vr), + m_nestedType(nested_type) +{ + Q_ASSERT(m_nestedType); +} + +QString ArrayTypeEntry::targetLangName() const +{ + return m_nestedType->targetLangName() + QLatin1String("[]"); +} + +QString ArrayTypeEntry::targetLangApiName() const +{ + if (m_nestedType->isPrimitive()) + return m_nestedType->targetLangApiName() + QLatin1String("Array"); + else + return QLatin1String("jobjectArray"); +} + +EnumTypeEntry::EnumTypeEntry(const QString &nspace, const QString &enumName, double vr) : + TypeEntry(nspace.isEmpty() ? enumName : nspace + QLatin1String("::") + enumName, + EnumType, vr), + m_qualifier(nspace), + m_targetLangName(enumName) +{ +} + +QString EnumTypeEntry::targetLangPackage() const +{ + return m_packageName; +} + +void EnumTypeEntry::setTargetLangPackage(const QString &package) +{ + m_packageName = package; +} + +QString EnumTypeEntry::targetLangName() const +{ + return m_targetLangName; +} + +EnumValueTypeEntry::EnumValueTypeEntry(const QString& name, const QString& value, const EnumTypeEntry* enclosingEnum, double vr) : + TypeEntry(name, TypeEntry::EnumValue, vr), + m_value(value), + m_enclosingEnum(enclosingEnum) +{ +} + +FlagsTypeEntry::FlagsTypeEntry(const QString &name, double vr) : + TypeEntry(name, FlagsType, vr) +{ +} + +ContainerTypeEntry::ContainerTypeEntry(const QString &name, Type type, double vr) : + ComplexTypeEntry(name, ContainerType, vr), + m_type(type) +{ + setCodeGeneration(GenerateForSubclass); +} + +SmartPointerTypeEntry::SmartPointerTypeEntry(const QString &name, + const QString &getterName, + const QString &smartPointerType, + const QString &refCountMethodName, + double vr) : + ComplexTypeEntry(name, SmartPointerType, vr), + m_getterName(getterName), + m_smartPointerType(smartPointerType), + m_refCountMethodName(refCountMethodName) +{ +} + +NamespaceTypeEntry::NamespaceTypeEntry(const QString &name, double vr) : + ComplexTypeEntry(name, NamespaceType, vr) +{ +} + +ValueTypeEntry::ValueTypeEntry(const QString &name, double vr) : + ComplexTypeEntry(name, BasicValueType, vr) +{ +} + +bool ValueTypeEntry::isValue() const +{ + return true; +} + +bool ValueTypeEntry::isNativeIdBased() const +{ + return true; +} + +ValueTypeEntry::ValueTypeEntry(const QString &name, Type t, double vr) : + ComplexTypeEntry(name, t, vr) +{ +} + +StringTypeEntry::StringTypeEntry(const QString &name, double vr) : + ValueTypeEntry(name, StringType, vr) +{ + setCodeGeneration(GenerateNothing); +} + /* static void injectCode(ComplexTypeEntry *e, const char *signature, @@ -2563,9 +2906,7 @@ CustomConversion::CustomConversion(TypeEntry* ownerType) CustomConversion::~CustomConversion() { - foreach (TargetToNativeConversion* targetToNativeConversion, m_d->targetToNativeConversions) - delete targetToNativeConversion; - m_d->targetToNativeConversions.clear(); + qDeleteAll(m_d->targetToNativeConversions); delete m_d; } @@ -2665,3 +3006,41 @@ void CustomConversion::TargetToNativeConversion::setConversion(const QString& co { m_d->conversion = conversion; } + +InterfaceTypeEntry::InterfaceTypeEntry(const QString &name, double vr) : + ComplexTypeEntry(name, InterfaceType, vr) +{ +} + +bool InterfaceTypeEntry::isNativeIdBased() const +{ + return true; +} + +QString InterfaceTypeEntry::qualifiedCppName() const +{ + const int len = ComplexTypeEntry::qualifiedCppName().length() - interfaceName(QString()).length(); + return ComplexTypeEntry::qualifiedCppName().left(len); +} + +FunctionTypeEntry::FunctionTypeEntry(const QString &name, const QString &signature, + double vr) : + TypeEntry(name, FunctionType, vr) +{ + addSignature(signature); +} + +ObjectTypeEntry::ObjectTypeEntry(const QString &name, double vr) + : ComplexTypeEntry(name, ObjectType, vr) +{ +} + +InterfaceTypeEntry *ObjectTypeEntry::designatedInterface() const +{ + return m_interface; +} + +bool ObjectTypeEntry::isNativeIdBased() const +{ + return true; +} diff --git a/sources/shiboken2/ApiExtractor/typesystem.h b/sources/shiboken2/ApiExtractor/typesystem.h index a8ee0ced4..62d348f69 100644 --- a/sources/shiboken2/ApiExtractor/typesystem.h +++ b/sources/shiboken2/ApiExtractor/typesystem.h @@ -35,9 +35,11 @@ #include <QtCore/QHash> #include <QtCore/qobjectdefs.h> +#include <QtCore/QRegularExpression> #include <QtCore/QString> #include <QtCore/QStringList> #include <QtCore/QMap> +#include <QtCore/QVector> //Used to identify the conversion rule to avoid break API #define TARGET_CONVERSION_RULE_FLAG "0" @@ -47,6 +49,7 @@ class Indentor; class AbstractMetaType; QT_BEGIN_NAMESPACE +class QDebug; class QTextStream; QT_END_NAMESPACE @@ -59,7 +62,6 @@ class TemplateInstance; struct ReferenceCount { - ReferenceCount() {} enum Action { // 0x01 - 0xff Invalid = 0x00, Add = 0x01, @@ -73,8 +75,8 @@ struct ReferenceCount Padding = 0xffffffff }; - Action action; QString varName; + Action action = Invalid; }; struct ArgumentOwner @@ -90,27 +92,23 @@ struct ArgumentOwner ReturnIndex = 0, FirstArgumentIndex = 1 }; - ArgumentOwner() : action(ArgumentOwner::Invalid), index(ArgumentOwner::InvalidIndex) {} - Action action; - int index; + Action action = Invalid; + int index = InvalidIndex; }; class CodeSnipFragment { -private: - QString m_code; - TemplateInstance *m_instance; - public: - CodeSnipFragment(const QString &code) - : m_code(code), - m_instance(0) {} - - CodeSnipFragment(TemplateInstance *instance) - : m_instance(instance) {} + CodeSnipFragment() = default; + explicit CodeSnipFragment(const QString &code) : m_code(code) {} + explicit CodeSnipFragment(TemplateInstance *instance) : m_instance(instance) {} QString code() const; + +private: + QString m_code; + TemplateInstance *m_instance = nullptr; }; class CodeSnipAbstract @@ -126,13 +124,13 @@ public: codeList.append(CodeSnipFragment(ti)); } - QList<CodeSnipFragment> codeList; + QVector<CodeSnipFragment> codeList; }; class CustomFunction : public CodeSnipAbstract { public: - CustomFunction(const QString &n = QString()) : name(n) { } + explicit CustomFunction(const QString &n = QString()) : name(n) {} QString name; QString paramName; @@ -141,31 +139,21 @@ public: class TemplateEntry : public CodeSnipAbstract { public: - TemplateEntry(const QString &name, double vr) - : m_name(name), m_version(vr) - { - }; + explicit TemplateEntry(const QString &name) : m_name(name) {} QString name() const { return m_name; - }; - - double version() const - { - return m_version; } private: QString m_name; - double m_version; }; class TemplateInstance { public: - TemplateInstance(const QString &name, double vr) - : m_name(name), m_version(vr) {} + explicit TemplateInstance(const QString &name) : m_name(name) {} void addReplaceRule(const QString &name, const QString &value) { @@ -179,14 +167,8 @@ public: return m_name; } - double version() const - { - return m_version; - } - private: const QString m_name; - double m_version; QHash<QString, QString> replaceRules; }; @@ -194,32 +176,26 @@ private: class CodeSnip : public CodeSnipAbstract { public: - CodeSnip(double vr) : language(TypeSystem::TargetLangCode), version(vr) { } - CodeSnip(double vr, TypeSystem::Language lang) : language(lang), version(vr) { } + CodeSnip() = default; + explicit CodeSnip(TypeSystem::Language lang) : language(lang) {} - TypeSystem::Language language; - TypeSystem::CodeSnipPosition position; + TypeSystem::Language language = TypeSystem::TargetLangCode; + TypeSystem::CodeSnipPosition position = TypeSystem::CodeSnipPositionAny; ArgumentMap argumentMap; - double version; }; struct ArgumentModification { - ArgumentModification(int idx, double vr) - : removedDefaultExpression(false), removed(false), - noNullPointers(false), index(idx), version(vr) {} + ArgumentModification() : removedDefaultExpression(false), removed(false), + noNullPointers(false), array(false) {} + explicit ArgumentModification(int idx) : index(idx), removedDefaultExpression(false), removed(false), + noNullPointers(false), array(false) {} // Should the default expression be removed? - uint removedDefaultExpression : 1; - uint removed : 1; - uint noNullPointers : 1; - uint resetAfterUse : 1; - // The index of this argument - int index; // Reference count flags for this argument - QList<ReferenceCount> referenceCounts; + QVector<ReferenceCount> referenceCounts; // The text given for the new type of the argument QString modified_type; @@ -244,11 +220,17 @@ struct ArgumentModification //QObject parent(owner) of this argument ArgumentOwner owner; - //Api version - double version; - //New name QString renamed_to; + + // The index of this argument + int index = -1; + + uint removedDefaultExpression : 1; + uint removed : 1; + uint noNullPointers : 1; + uint resetAfterUse : 1; + uint array : 1; // consider "int*" to be "int[]" }; struct Modification @@ -274,8 +256,6 @@ struct Modification VirtualSlot = 0x10000 | NonFinal }; - Modification() : modifiers(0), removal(TypeSystem::NoLanguage) { } - bool isAccessModifier() const { return modifiers & AccessModifierMask; @@ -337,15 +317,13 @@ struct Modification return removal != TypeSystem::NoLanguage; } - uint modifiers; QString renamedToName; - TypeSystem::Language removal; + uint modifiers = 0; + TypeSystem::Language removal = TypeSystem::NoLanguage; }; struct FunctionModification: public Modification { - FunctionModification(double vr) : m_thread(false), m_allowThread(false), m_version(vr) {} - bool isCodeInjection() const { return modifiers & CodeInjection; @@ -366,31 +344,29 @@ struct FunctionModification: public Modification { m_allowThread = allow; } - double version() const + + bool matches(const QString &functionSignature) const { - return m_version; + return m_signature.isEmpty() + ? m_signaturePattern.match(functionSignature).hasMatch() + : m_signature == functionSignature; } - bool operator!=(const FunctionModification& other) const; - bool operator==(const FunctionModification& other) const; - + bool setSignature(const QString &s, QString *errorMessage = nullptr); + QString signature() const { return m_signature.isEmpty() ? m_signaturePattern.pattern() : m_signature; } QString toString() const; - QString signature; QString association; CodeSnipList snips; - QList<ArgumentModification> argument_mods; + QVector<ArgumentModification> argument_mods; private: - FunctionModification() {} - - bool m_thread; - bool m_allowThread; - double m_version; - - + QString m_signature; + QRegularExpression m_signaturePattern; + bool m_thread = false; + bool m_allowThread = false; }; struct FieldModification: public Modification @@ -428,18 +404,19 @@ struct AddedFunction * AbstractMetaType and AbstractMetaArgument for the AbstractMetaFunctions. */ struct TypeInfo { - TypeInfo() : isConstant(false), indirections(0), isReference(false) {} + TypeInfo() = default; static TypeInfo fromSignature(const QString& signature); QString name; - bool isConstant; - int indirections; - bool isReference; QString defaultValue; + int indirections = 0; + bool isConstant = false; + bool isReference = false; }; /// Creates a new AddedFunction with a signature and a return type. - AddedFunction(QString signature, QString returnType, double vr); + explicit AddedFunction(QString signature, QString returnType, double vr); + AddedFunction() = default; /// Returns the function name. QString name() const @@ -466,7 +443,7 @@ struct AddedFunction } /// Returns a list of argument type infos. - QList<TypeInfo> arguments() const + QVector<TypeInfo> arguments() const { return m_arguments; } @@ -495,12 +472,12 @@ struct AddedFunction } private: QString m_name; - Access m_access; - QList<TypeInfo> m_arguments; + QVector<TypeInfo> m_arguments; TypeInfo m_returnType; - bool m_isConst; - bool m_isStatic; - double m_version; + double m_version = 0; + Access m_access = Protected; + bool m_isConst = false; + bool m_isStatic = false; }; #ifndef QT_NO_DEBUG_STREAM @@ -508,28 +485,17 @@ QDebug operator<<(QDebug d, const AddedFunction::TypeInfo &ti); QDebug operator<<(QDebug d, const AddedFunction &af); #endif -struct ExpensePolicy -{ - ExpensePolicy() : limit(-1) {} - int limit; - QString cost; - bool isValid() const - { - return limit >= 0; - } -}; - class InterfaceTypeEntry; class ObjectTypeEntry; class DocModification { public: - DocModification(const QString& xpath, const QString& signature, double vr) - : format(TypeSystem::NativeCode), m_mode(TypeSystem::DocModificationXPathReplace), - m_xpath(xpath), m_signature(signature), m_version(vr) {} - DocModification(TypeSystem::DocModificationMode mode, const QString& signature, double vr) - : m_mode(mode), m_signature(signature), m_version(vr) {} + DocModification() = default; + explicit DocModification(const QString& xpath, const QString& signature) : + m_xpath(xpath), m_signature(signature) {} + explicit DocModification(TypeSystem::DocModificationMode mode, const QString& signature) : + m_signature(signature), m_mode(mode) {} void setCode(const QString& code) { m_code = code; } void setCode(const QStringRef& code) { m_code = code.toString(); } @@ -550,25 +516,23 @@ public: { return m_mode; } - double version() const - { - return m_version; - } - TypeSystem::Language format; + TypeSystem::Language format() const { return m_format; } + void setFormat(TypeSystem::Language f) { m_format = f; } private: - TypeSystem::DocModificationMode m_mode; QString m_code; QString m_xpath; QString m_signature; - double m_version; + TypeSystem::DocModificationMode m_mode = TypeSystem::DocModificationXPathReplace; + TypeSystem::Language m_format = TypeSystem::NativeCode; }; class CustomConversion; class TypeEntry { + Q_DISABLE_COPY(TypeEntry) Q_GADGET public: enum Type { @@ -609,15 +573,7 @@ public: }; Q_ENUM(CodeGeneration) - TypeEntry(const QString &name, Type t, double vr) - : m_name(name), - m_type(t), - m_codeGeneration(GenerateAll), - m_preferredConversion(true), - m_stream(false), - m_version(vr) - { - }; + explicit TypeEntry(const QString &name, Type t, double vr); virtual ~TypeEntry(); @@ -882,7 +838,13 @@ public: } void setInclude(const Include &inc) { - m_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; } // Replace conversionRule arg to CodeSnip in future version @@ -930,48 +892,42 @@ public: private: QString m_name; Type m_type; - uint m_codeGeneration; + uint m_codeGeneration = GenerateAll; CustomFunction m_customConstructor; CustomFunction m_customDestructor; - bool m_preferredConversion; + bool m_preferredConversion = true; CodeSnipList m_codeSnips; DocModificationList m_docModifications; IncludeList m_extraIncludes; Include m_include; QHash<QString, bool> m_includesUsed; QString m_conversionRule; - bool m_stream; + bool m_stream = false; double m_version; }; class TypeSystemTypeEntry : public TypeEntry { public: - TypeSystemTypeEntry(const QString &name, double vr) - : TypeEntry(name, TypeSystemType, vr) - { - }; + explicit TypeSystemTypeEntry(const QString &name, double vr); }; class VoidTypeEntry : public TypeEntry { public: - VoidTypeEntry() : TypeEntry(QLatin1String("void"), VoidType, 0) { } + VoidTypeEntry(); }; class VarargsTypeEntry : public TypeEntry { public: - VarargsTypeEntry() : TypeEntry(QLatin1String("..."), VarargsType, 0) { } + VarargsTypeEntry(); }; class TemplateArgumentEntry : public TypeEntry { public: - TemplateArgumentEntry(const QString &name, double vr) - : TypeEntry(name, TemplateArgumentType, vr), m_ordinal(0) - { - } + explicit TemplateArgumentEntry(const QString &name, double vr); int ordinal() const { @@ -983,17 +939,13 @@ public: } private: - int m_ordinal; + int m_ordinal = 0; }; class ArrayTypeEntry : public TypeEntry { public: - ArrayTypeEntry(const TypeEntry *nested_type, double vr) - : TypeEntry(QLatin1String("Array"), ArrayType, vr), m_nestedType(nested_type) - { - Q_ASSERT(m_nestedType); - } + explicit ArrayTypeEntry(const TypeEntry *nested_type, double vr); void setNestedTypeEntry(TypeEntry *nested) { @@ -1004,17 +956,8 @@ public: return m_nestedType; } - QString targetLangName() const - { - return m_nestedType->targetLangName() + QLatin1String("[]"); - } - QString targetLangApiName() const - { - if (m_nestedType->isPrimitive()) - return m_nestedType->targetLangApiName() + QLatin1String("Array"); - else - return QLatin1String("jobjectArray"); - } + QString targetLangName() const override; + QString targetLangApiName() const override; private: const TypeEntry *m_nestedType; @@ -1024,27 +967,15 @@ private: class PrimitiveTypeEntry : public TypeEntry { public: - PrimitiveTypeEntry(const QString &name, double vr) - : TypeEntry(name, PrimitiveType, vr), - m_preferredConversion(true), - m_preferredTargetLangType(true), - m_referencedTypeEntry(0) - { - } + explicit PrimitiveTypeEntry(const QString &name, double vr); - QString targetLangName() const - { - return m_targetLangName; - } + QString targetLangName() const override; void setTargetLangName(const QString &targetLangName) { m_targetLangName = targetLangName; } - QString targetLangApiName() const - { - return m_targetLangApiName; - } + QString targetLangApiName() const override; void setTargetLangApiName(const QString &targetLangApiName) { m_targetLangApiName = targetLangApiName; @@ -1088,91 +1019,48 @@ public: */ PrimitiveTypeEntry* basicReferencedTypeEntry() const; - virtual bool preferredConversion() const - { - return m_preferredConversion; - } - virtual void setPreferredConversion(bool b) - { - m_preferredConversion = b; - } + bool preferredConversion() const override; + void setPreferredConversion(bool b) override; - virtual bool preferredTargetLangType() const + bool preferredTargetLangType() const { return m_preferredTargetLangType; } - virtual void setPreferredTargetLangType(bool b) + void setPreferredTargetLangType(bool b) { m_preferredTargetLangType = b; } void setTargetLangPackage(const QString& package); - QString targetLangPackage() const; + QString targetLangPackage() const override; private: QString m_targetLangName; QString m_targetLangApiName; QString m_defaultConstructor; uint m_preferredConversion : 1; uint m_preferredTargetLangType : 1; - PrimitiveTypeEntry* m_referencedTypeEntry; -}; - -struct EnumValueRedirection -{ - EnumValueRedirection(const QString &rej, const QString &us) - : rejected(rej), - used(us) - { - } - QString rejected; - QString used; + PrimitiveTypeEntry* m_referencedTypeEntry = nullptr; }; class EnumTypeEntry : public TypeEntry { public: - EnumTypeEntry(const QString &nspace, const QString &enumName, double vr) - : TypeEntry(nspace.isEmpty() ? enumName : nspace + QLatin1String("::") + enumName, - EnumType, vr), - m_qualifier(nspace), - m_targetLangName(enumName), - m_flags(0), - m_extensible(false), - m_forceInteger(false), - m_anonymous(false) - { - } + enum EnumKind { + CEnum, // Standard C: enum Foo { value1, value2 } + AnonymousEnum, // enum { value1, value2 } + EnumClass // C++ 11 : enum class Foo { value1, value2 } + }; - QString targetLangPackage() const - { - return m_packageName; - } - void setTargetLangPackage(const QString &package) - { - m_packageName = package; - } + explicit EnumTypeEntry(const QString &nspace, const QString &enumName, double vr); - QString targetLangName() const - { - return m_targetLangName; - } - QString targetLangQualifier() const; - QString qualifiedTargetLangName() const - { - QString qualifiedName; - QString pkg = targetLangPackage(); - QString qualifier = targetLangQualifier(); + QString targetLangPackage() const override; + void setTargetLangPackage(const QString &package); - if (!pkg.isEmpty()) - qualifiedName += pkg + QLatin1Char('.'); - if (!qualifier.isEmpty()) - qualifiedName += qualifier + QLatin1Char('.'); - qualifiedName += targetLangName(); - - return qualifiedName; - } + QString targetLangName() const override; + QString targetLangQualifier() const; + QString qualifiedTargetLangName() const override; - QString targetLangApiName() const; + QString targetLangApiName() const override; QString qualifier() const { @@ -1183,10 +1071,10 @@ public: m_qualifier = q; } - virtual bool preferredConversion() const - { - return false; - } + EnumKind enumKind() const { return m_enumKind; } + void setEnumKind(EnumKind kind) { m_enumKind = kind; } + + bool preferredConversion() const override; bool isBoundsChecked() const { @@ -1229,7 +1117,7 @@ public: m_extensible = is; } - bool isEnumValueRejected(const QString &name) + bool isEnumValueRejected(const QString &name) const { return m_rejectedEnums.contains(name); } @@ -1242,9 +1130,6 @@ public: return m_rejectedEnums; } - void addEnumValueRedirection(const QString &rejected, const QString &usedValue); - QString enumValueRedirection(const QString &value) const; - bool forceInteger() const { return m_forceInteger; @@ -1254,14 +1139,7 @@ public: m_forceInteger = force; } - bool isAnonymous() const - { - return m_anonymous; - } - void setAnonymous(bool anonymous) - { - m_anonymous = anonymous; - } + bool isAnonymous() const { return m_enumKind == AnonymousEnum; } private: QString m_packageName; @@ -1272,22 +1150,21 @@ private: QString m_upperBound; QStringList m_rejectedEnums; - QList<EnumValueRedirection> m_enumRedirections; - FlagsTypeEntry *m_flags; + FlagsTypeEntry *m_flags = nullptr; + + EnumKind m_enumKind = CEnum; - bool m_extensible; - bool m_forceInteger; - bool m_anonymous; + bool m_extensible = false; + bool m_forceInteger = false; }; +// EnumValueTypeEntry is used for resolving integer type templates +// like array<EnumValue>. class EnumValueTypeEntry : public TypeEntry { public: - EnumValueTypeEntry(const QString& name, const QString& value, const EnumTypeEntry* enclosingEnum, double vr) - : TypeEntry(name, TypeEntry::EnumValue, vr), m_value(value), m_enclosingEnum(enclosingEnum) - { - } + explicit EnumValueTypeEntry(const QString& name, const QString& value, const EnumTypeEntry* enclosingEnum, double vr); QString value() const { return m_value; } const EnumTypeEntry* enclosingEnum() const { return m_enclosingEnum; } @@ -1299,20 +1176,12 @@ private: class FlagsTypeEntry : public TypeEntry { public: - FlagsTypeEntry(const QString &name, double vr) : TypeEntry(name, FlagsType, vr), m_enum(0) - { - } + explicit FlagsTypeEntry(const QString &name, double vr); - QString qualifiedTargetLangName() const; - QString targetLangName() const - { - return m_targetLangName; - } - QString targetLangApiName() const; - virtual bool preferredConversion() const - { - return false; - } + QString qualifiedTargetLangName() const override; + QString targetLangName() const override; + QString targetLangApiName() const override; + bool preferredConversion() const override; QString originalName() const { @@ -1346,15 +1215,12 @@ public: m_enum = e; } - QString targetLangPackage() const - { - return m_enum->targetLangPackage(); - } + QString targetLangPackage() const override; private: QString m_originalName; QString m_targetLangName; - EnumTypeEntry *m_enum; + EnumTypeEntry *m_enum = nullptr; }; @@ -1374,52 +1240,18 @@ public: Unknown }; - ComplexTypeEntry(const QString &name, Type t, double vr) - : TypeEntry(QString(name).replace(QLatin1String(".*::"), QString()), t, vr), - m_qualifiedCppName(name), - m_qobject(false), - m_polymorphicBase(false), - m_genericClass(false), - m_typeFlags(0), - m_copyableFlag(Unknown), - m_baseContainerType(0) - { - } - - bool isComplex() const - { - return true; - } + explicit ComplexTypeEntry(const QString &name, Type t, double vr); - ComplexTypeEntry *copy() const - { - ComplexTypeEntry *centry = new ComplexTypeEntry(name(), type(), version()); - centry->setInclude(include()); - centry->setExtraIncludes(extraIncludes()); - centry->setAddedFunctions(addedFunctions()); - centry->setFunctionModifications(functionModifications()); - centry->setFieldModifications(fieldModifications()); - centry->setQObject(isQObject()); - centry->setDefaultSuperclass(defaultSuperclass()); - centry->setCodeSnips(codeSnips()); - centry->setTargetLangPackage(targetLangPackage()); - centry->setBaseContainerType(baseContainerType()); - centry->setDefaultConstructor(defaultConstructor()); - - return centry; - } + bool isComplex() const override; void setLookupName(const QString &name) { m_lookupName = name; } - virtual QString lookupName() const - { - return m_lookupName.isEmpty() ? targetLangName() : m_lookupName; - } + QString lookupName() const override; - QString targetLangApiName() const; + QString targetLangApiName() const override; void setTypeFlags(TypeFlags flags) { @@ -1468,10 +1300,7 @@ public: return m_fieldMods; } - QString targetLangPackage() const - { - return m_package; - } + QString targetLangPackage() const override; void setTargetLangPackage(const QString &package) { m_package = package; @@ -1495,7 +1324,7 @@ public: m_defaultSuperclass = sc; } - virtual QString qualifiedCppName() const + QString qualifiedCppName() const override { return m_qualifiedCppName; } @@ -1528,16 +1357,6 @@ public: return m_heldTypeValue; } - - void setExpensePolicy(const ExpensePolicy &policy) - { - m_expensePolicy = policy; - } - const ExpensePolicy &expensePolicy() const - { - return m_expensePolicy; - } - QString targetType() const { return m_targetType; @@ -1547,12 +1366,7 @@ public: m_targetType = code; } - QString targetLangName() const - { - return m_targetLangName.isEmpty() - ? TypeEntry::targetLangName() - : m_targetLangName; - } + QString targetLangName() const override; void setTargetLangName(const QString &name) { m_targetLangName = name; @@ -1616,12 +1430,11 @@ private: QString m_heldTypeValue; QString m_lookupName; QString m_targetType; - ExpensePolicy m_expensePolicy; TypeFlags m_typeFlags; - CopyableFlag m_copyableFlag; + CopyableFlag m_copyableFlag = Unknown; QString m_hashFunction; - const ComplexTypeEntry* m_baseContainerType; + const ComplexTypeEntry* m_baseContainerType = nullptr; }; class ContainerTypeEntry : public ComplexTypeEntry @@ -1645,11 +1458,7 @@ public: }; Q_ENUM(Type) - ContainerTypeEntry(const QString &name, Type type, double vr) - : ComplexTypeEntry(name, ContainerType, vr), m_type(type) - { - setCodeGeneration(GenerateForSubclass); - } + explicit ContainerTypeEntry(const QString &name, Type type, double vr); Type type() const { @@ -1657,9 +1466,9 @@ public: } QString typeName() const; - QString targetLangName() const; - QString targetLangPackage() const; - QString qualifiedCppName() const; + QString targetLangName() const override; + QString targetLangPackage() const override; + QString qualifiedCppName() const override; static Type containerTypeFromString(QString typeName) { @@ -1688,17 +1497,11 @@ private: class SmartPointerTypeEntry : public ComplexTypeEntry { public: - SmartPointerTypeEntry(const QString &name, - const QString &getterName, - const QString &smartPointerType, - const QString &refCountMethodName, - double vr) - : ComplexTypeEntry(name, SmartPointerType, vr), - m_getterName(getterName), - m_smartPointerType(smartPointerType), - m_refCountMethodName(refCountMethodName) - { - } + explicit SmartPointerTypeEntry(const QString &name, + const QString &getterName, + const QString &smartPointerType, + const QString &refCountMethodName, + double vr); QString getter() const { @@ -1719,91 +1522,65 @@ private: class NamespaceTypeEntry : public ComplexTypeEntry { public: - NamespaceTypeEntry(const QString &name, double vr) : ComplexTypeEntry(name, NamespaceType, vr) { } + explicit NamespaceTypeEntry(const QString &name, double vr); }; class ValueTypeEntry : public ComplexTypeEntry { public: - ValueTypeEntry(const QString &name, double vr) : ComplexTypeEntry(name, BasicValueType, vr) { } + explicit ValueTypeEntry(const QString &name, double vr); - bool isValue() const - { - return true; - } + bool isValue() const override; - virtual bool isNativeIdBased() const - { - return true; - } + bool isNativeIdBased() const override; protected: - ValueTypeEntry(const QString &name, Type t, double vr) : ComplexTypeEntry(name, t, vr) { } + explicit ValueTypeEntry(const QString &name, Type t, double vr); }; class StringTypeEntry : public ValueTypeEntry { public: - StringTypeEntry(const QString &name, double vr) - : ValueTypeEntry(name, StringType, vr) - { - setCodeGeneration(GenerateNothing); - } + explicit StringTypeEntry(const QString &name, double vr); - QString targetLangApiName() const; - QString targetLangName() const; - QString targetLangPackage() const; + QString targetLangApiName() const override; + QString targetLangName() const override; + QString targetLangPackage() const override; - virtual bool isNativeIdBased() const - { - return false; - } + bool isNativeIdBased() const override; }; class CharTypeEntry : public ValueTypeEntry { public: - CharTypeEntry(const QString &name, double vr) : ValueTypeEntry(name, CharType, vr) - { - setCodeGeneration(GenerateNothing); - } + explicit CharTypeEntry(const QString &name, double vr); - QString targetLangApiName() const; - QString targetLangName() const; - QString targetLangPackage() const - { - return QString(); - } + QString targetLangApiName() const override; + QString targetLangName() const override; + QString targetLangPackage() const override; - virtual bool isNativeIdBased() const - { - return false; - } + bool isNativeIdBased() const override; }; class VariantTypeEntry: public ValueTypeEntry { public: - VariantTypeEntry(const QString &name, double vr) : ValueTypeEntry(name, VariantType, vr) { } + explicit VariantTypeEntry(const QString &name, double vr); - QString targetLangApiName() const; - QString targetLangName() const; - QString targetLangPackage() const; + QString targetLangApiName() const override; + QString targetLangName() const override; + QString targetLangPackage() const override; - virtual bool isNativeIdBased() const - { - return false; - } + bool isNativeIdBased() const override; }; class InterfaceTypeEntry : public ComplexTypeEntry { public: - InterfaceTypeEntry(const QString &name, double vr) - : ComplexTypeEntry(name, InterfaceType, vr) {} + explicit InterfaceTypeEntry(const QString &name, double vr); static QString interfaceName(const QString &name) { @@ -1819,15 +1596,8 @@ public: m_origin = origin; } - virtual bool isNativeIdBased() const - { - return true; - } - virtual QString qualifiedCppName() const - { - const int len = ComplexTypeEntry::qualifiedCppName().length() - interfaceName(QString()).length(); - return ComplexTypeEntry::qualifiedCppName().left(len); - } + bool isNativeIdBased() const override; + QString qualifiedCppName() const override; private: ObjectTypeEntry *m_origin; @@ -1837,11 +1607,7 @@ private: class FunctionTypeEntry : public TypeEntry { public: - FunctionTypeEntry(const QString& name, const QString& signature, double vr) - : TypeEntry(name, FunctionType, vr) - { - addSignature(signature); - } + explicit FunctionTypeEntry(const QString& name, const QString& signature, double vr); void addSignature(const QString& signature) { m_signatures << signature; @@ -1863,35 +1629,41 @@ private: class ObjectTypeEntry : public ComplexTypeEntry { public: - ObjectTypeEntry(const QString &name, double vr) - : ComplexTypeEntry(name, ObjectType, vr), m_interface(0) {} + explicit ObjectTypeEntry(const QString &name, double vr); - InterfaceTypeEntry *designatedInterface() const - { - return m_interface; - } + InterfaceTypeEntry *designatedInterface() const override; void setDesignatedInterface(InterfaceTypeEntry *entry) { m_interface = entry; } - virtual bool isNativeIdBased() const - { - return true; - } + bool isNativeIdBased() const override; private: - InterfaceTypeEntry *m_interface; + InterfaceTypeEntry *m_interface = nullptr; }; struct TypeRejection { - QString class_name; - QString function_name; - QString field_name; - QString enum_name; + enum MatchType + { + ExcludeClass, // Match className only + Function, // Match className and function name + Field, // Match className and field name + Enum, // Match className and enum name + ArgumentType, // Match className and argument type + ReturnType // Match className and return type + }; + + QRegularExpression className; + QRegularExpression pattern; + MatchType matchType; }; +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug d, const TypeRejection &r); +#endif + QString fixCppTypeName(const QString &name); class CustomConversion @@ -1932,7 +1704,7 @@ public: bool replaceOriginalTargetToNativeConversions() const; void setReplaceOriginalTargetToNativeConversions(bool replaceOriginalTargetToNativeConversions); - typedef QList<TargetToNativeConversion*> TargetToNativeConversions; + typedef QVector<TargetToNativeConversion*> TargetToNativeConversions; bool hasTargetToNativeConversions() const; TargetToNativeConversions& targetToNativeConversions(); const TargetToNativeConversions& targetToNativeConversions() const; diff --git a/sources/shiboken2/ApiExtractor/typesystem_p.h b/sources/shiboken2/ApiExtractor/typesystem_p.h index f2105a631..d3485726e 100644 --- a/sources/shiboken2/ApiExtractor/typesystem_p.h +++ b/sources/shiboken2/ApiExtractor/typesystem_p.h @@ -107,6 +107,7 @@ class StackElement NoNullPointers = 0x40000000, ReferenceCount = 0x80000000, ParentOwner = 0x90000000, + Array = 0xA0000000, ArgumentModifiers = 0xff000000 }; @@ -152,7 +153,6 @@ private: QHash<QString, QString> *acceptedAttributes); bool importFileElement(const QXmlStreamAttributes &atts); - bool convertBoolean(const QString &, const QString &, bool); void addFlags(const QString &name, QString flagName, const QHash<QString, QString> &attributes, double since); @@ -171,6 +171,7 @@ private: QHash<QString, StackElement::ElementType> tagNames; QString m_currentSignature; + QString m_currentPath; }; #endif diff --git a/sources/shiboken2/ApiExtractor/typesystem_typedefs.h b/sources/shiboken2/ApiExtractor/typesystem_typedefs.h index 04b669655..4f29deced 100644 --- a/sources/shiboken2/ApiExtractor/typesystem_typedefs.h +++ b/sources/shiboken2/ApiExtractor/typesystem_typedefs.h @@ -31,28 +31,19 @@ #include <QtCore/QHash> #include <QtCore/QList> +#include <QtCore/QVector> class CodeSnip; -class ContainerTypeEntry; class DocModification; -class PrimitiveTypeEntry; -class TemplateEntry; -class TypeEntry; struct AddedFunction; struct FieldModification; struct FunctionModification; -typedef QHash<QString, QList<TypeEntry *> > TypeEntryHash; -typedef QHash<QString, TypeEntry *> SingleTypeEntryHash; -typedef QHash<QString, TemplateEntry *> TemplateEntryHash; - -typedef QList<AddedFunction> AddedFunctionList; -typedef QList<CodeSnip> CodeSnipList; -typedef QList<const ContainerTypeEntry *> ContainerTypeEntryList; -typedef QList<DocModification> DocModificationList; -typedef QList<FieldModification> FieldModificationList; -typedef QList<FunctionModification> FunctionModificationList; -typedef QList<const PrimitiveTypeEntry *> PrimitiveTypeEntryList; +typedef QVector<AddedFunction> AddedFunctionList; +typedef QVector<CodeSnip> CodeSnipList; +typedef QVector<DocModification> DocModificationList; +typedef QVector<FieldModification> FieldModificationList; +typedef QVector<FunctionModification> FunctionModificationList; #endif // TYPESYSTEM_TYPEDEFS_H diff --git a/sources/shiboken2/CMakeLists.txt b/sources/shiboken2/CMakeLists.txt index 5735fea18..ccabc72e3 100644 --- a/sources/shiboken2/CMakeLists.txt +++ b/sources/shiboken2/CMakeLists.txt @@ -1,8 +1,8 @@ Include(icecc.cmake) project(shiboken2) -cmake_minimum_required(VERSION 3.0) -cmake_policy(VERSION 3.0) +cmake_minimum_required(VERSION 3.1) +cmake_policy(VERSION 3.1) set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/Modules/ ${CMAKE_MODULE_PATH}) @@ -22,6 +22,104 @@ else() find_package(PythonLibs 2.6) endif() +macro(get_python_arch) + execute_process( + COMMAND ${PYTHON_EXECUTABLE} -c "if True: + import sys + print('64' if sys.maxsize > 2**31-1 else '32') + " + OUTPUT_VARIABLE PYTHON_ARCH + OUTPUT_STRIP_TRAILING_WHITESPACE) + message("PYTHON_ARCH: " ${PYTHON_ARCH}) +endmacro() + +if (NOT PYTHON_ARCH) + get_python_arch() +endif() + +macro(get_llvm_config) + execute_process( + COMMAND ${PYTHON_EXECUTABLE} -c "if True: + import os + import sys + sys.path.append(os.path.realpath(os.path.join('${CMAKE_CURRENT_LIST_DIR}', '..', '..'))) + from utils import findLlvmConfig + llvmConfig = findLlvmConfig() + if llvmConfig: + print(llvmConfig) + " + OUTPUT_VARIABLE LLVM_CONFIG + OUTPUT_STRIP_TRAILING_WHITESPACE) + message("LLMV_CONFIG: " ${LLVM_CONFIG}) +endmacro() + +set(CLANG_DIR "") +set(CLANG_DIR_SOURCE "") + +if (DEFINED ENV{LLVM_INSTALL_DIR}) + set(CLANG_DIR $ENV{LLVM_INSTALL_DIR}) + string(REPLACE "_ARCH_" "${PYTHON_ARCH}" CLANG_DIR "${CLANG_DIR}") + set(CLANG_DIR_SOURCE "LLVM_INSTALL_DIR") +elseif (DEFINED ENV{CLANG_INSTALL_DIR}) + set(CLANG_DIR $ENV{CLANG_INSTALL_DIR}) + string(REPLACE "_ARCH_" "${PYTHON_ARCH}" CLANG_DIR "${CLANG_DIR}") + set(CLANG_DIR_SOURCE "CLANG_INSTALL_DIR") +else () + if (NOT LLVM_CONFIG) + get_llvm_config() + endif() + set(CLANG_DIR_SOURCE "${LLVM_CONFIG}") + EXEC_PROGRAM("${LLVM_CONFIG}" ARGS "--prefix" OUTPUT_VARIABLE CLANG_DIR) + if (NOT "${CLANG_DIR}" STREQUAL "") + EXEC_PROGRAM("${LLVM_CONFIG}" ARGS "--version" OUTPUT_VARIABLE CLANG_VERSION) + if (CLANG_VERSION VERSION_LESS 3.9) + message(FATAL_ERROR "LLVM version 3.9 is required (${LLVM_CONFIG} detected ${CLANG_VERSION} at ${CLANG_DIR}).") + endif() + endif() +endif() + +if ("${CLANG_DIR}" STREQUAL "") + message(FATAL_ERROR "Unable to detect CLANG location by checking LLVM_INSTALL_DIR, CLANG_INSTALL_DIR or running llvm-config.") +elseif (NOT IS_DIRECTORY ${CLANG_DIR}) + message(FATAL_ERROR "${CLANG_DIR} detected by ${CLANG_DIR_SOURCE} does not exist.") +endif() + +set(CLANG_LIB_NAME "clang") +if(MSVC) + set(CLANG_LIB_NAME "libclang") +endif() + +find_library(CLANG_LIBRARY ${CLANG_LIB_NAME} HINTS ${CLANG_DIR}/lib) +if (NOT EXISTS ${CLANG_LIBRARY}) + message(FATAL_ERROR "Unable to find Clang library ${CLANG_LIB_NAME} in ${CLANG_DIR}.") +endif() + +message(STATUS "CLANG: ${CLANG_DIR}, ${CLANG_LIBRARY} detected by ${CLANG_DIR_SOURCE}") + +# Find highest version clang builtin includes folder to pass along to shiboken. +set(CLANG_BUILTIN_INCLUDES_DIR_PREFIX ${CLANG_DIR}/lib/clang) +file(GLOB CLANG_BUILTIN_INCLUDES_DIR_VERSIONS "${CLANG_BUILTIN_INCLUDES_DIR_PREFIX}/*") + +# Sort in alphabetical order the list of version folders. +list(SORT CLANG_BUILTIN_INCLUDES_DIR_VERSIONS) + +# Reverse it so the first element is the highest version. +list(REVERSE CLANG_BUILTIN_INCLUDES_DIR_VERSIONS) + +message(STATUS "Found the following CLANG builtins includes directories: ${CLANG_BUILTIN_INCLUDES_DIR_VERSIONS}") +if(CLANG_BUILTIN_INCLUDES_DIR_VERSIONS) + # Get highest version. + list(GET CLANG_BUILTIN_INCLUDES_DIR_VERSIONS 0 CLANG_BUILTIN_INCLUDES_DIR_HIGHEST_VERSION) + if (CLANG_BUILTIN_INCLUDES_DIR_HIGHEST_VERSION) + # Set the final variable to the full include path to pass along to shiboken. + set(CLANG_BUILTIN_INCLUDES_DIR "${CLANG_BUILTIN_INCLUDES_DIR_HIGHEST_VERSION}/include") + endif() +endif() +message(STATUS "CLANG builtins includes directory chosen: ${CLANG_BUILTIN_INCLUDES_DIR}") + +set(CLANG_EXTRA_INCLUDES ${CLANG_DIR}/include) +set(CLANG_EXTRA_LIBRARIES ${CLANG_LIBRARY}) + set(SHIBOKEN_VERSION_FILE_PATH "${CMAKE_SOURCE_DIR}/shiboken_version.py") set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${SHIBOKEN_VERSION_FILE_PATH} @@ -147,6 +245,11 @@ endif() set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D QT_NO_CAST_FROM_ASCII -D QT_NO_CAST_TO_ASCII") +# Force usage of the C++11 standard, without a silent fallback +# to C++98 if the compiler does not support C++11. +set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + set(LIB_SUFFIX "" CACHE STRING "Define suffix of directory name (32/64)" ) 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) diff --git a/sources/shiboken2/data/Shiboken2Config.cmake.in b/sources/shiboken2/data/Shiboken2Config.cmake.in index 515b0d13b..7891c5a2d 100644 --- a/sources/shiboken2/data/Shiboken2Config.cmake.in +++ b/sources/shiboken2/data/Shiboken2Config.cmake.in @@ -2,4 +2,4 @@ if (NOT PYTHON_CONFIG_SUFFIX) message(STATUS "Shiboken2Config: Using default python: @PYTHON_CONFIG_SUFFIX@") SET(PYTHON_CONFIG_SUFFIX @PYTHON_CONFIG_SUFFIX@) endif() -include(@LIB_INSTALL_DIR@/cmake/Shiboken2-@shiboken2_VERSION@/Shiboken2Config${PYTHON_CONFIG_SUFFIX}.cmake) +include("@LIB_INSTALL_DIR@/cmake/Shiboken2-@shiboken2_VERSION@/Shiboken2Config${PYTHON_CONFIG_SUFFIX}.cmake") diff --git a/sources/shiboken2/doc/conf.py.in b/sources/shiboken2/doc/conf.py.in index ed61d2695..5dc7b868d 100644 --- a/sources/shiboken2/doc/conf.py.in +++ b/sources/shiboken2/doc/conf.py.in @@ -131,10 +131,6 @@ html_theme_path = ['@CMAKE_CURRENT_SOURCE_DIR@/_themes'] # using the given strftime format. #html_last_updated_fmt = '%b %d, %Y' -# If true, SmartyPants will be used to convert quotes and dashes to -# typographically correct entities. -html_use_smartypants = True - # Custom sidebar templates, maps document names to template names. #html_sidebars = { '' : ''} @@ -154,8 +150,6 @@ html_split_index = False # If true, links to the reST sources are added to the pages. html_show_sourcelink = False -html_add_permalinks = True - # If true, an OpenSearch description file will be output, and all pages will # contain a <link> tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. diff --git a/sources/shiboken2/ext/sparsehash/AUTHORS b/sources/shiboken2/ext/sparsehash/AUTHORS deleted file mode 100644 index ee92be88d..000000000 --- a/sources/shiboken2/ext/sparsehash/AUTHORS +++ /dev/null @@ -1,2 +0,0 @@ -opensource@google.com - diff --git a/sources/shiboken2/ext/sparsehash/COPYING b/sources/shiboken2/ext/sparsehash/COPYING deleted file mode 100644 index e4956cfd9..000000000 --- a/sources/shiboken2/ext/sparsehash/COPYING +++ /dev/null @@ -1,28 +0,0 @@ -Copyright (c) 2005, Google Inc. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/sources/shiboken2/ext/sparsehash/google/dense_hash_map b/sources/shiboken2/ext/sparsehash/google/dense_hash_map deleted file mode 100644 index 09b0c4428..000000000 --- a/sources/shiboken2/ext/sparsehash/google/dense_hash_map +++ /dev/null @@ -1,310 +0,0 @@ -// Copyright (c) 2005, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// ---- -// Author: Craig Silverstein -// -// This is just a very thin wrapper over densehashtable.h, just -// like sgi stl's stl_hash_map is a very thin wrapper over -// stl_hashtable. The major thing we define is operator[], because -// we have a concept of a data_type which stl_hashtable doesn't -// (it only has a key and a value). -// -// NOTE: this is exactly like sparse_hash_map.h, with the word -// "sparse" replaced by "dense", except for the addition of -// set_empty_key(). -// -// YOU MUST CALL SET_EMPTY_KEY() IMMEDIATELY AFTER CONSTRUCTION. -// -// Otherwise your program will die in mysterious ways. -// -// In other respects, we adhere mostly to the STL semantics for -// hash-map. One important exception is that insert() invalidates -// iterators entirely. On the plus side, though, erase() doesn't -// invalidate iterators at all, or even change the ordering of elements. -// -// Here are a few "power user" tips: -// -// 1) set_deleted_key(): -// If you want to use erase() you *must* call set_deleted_key(), -// in addition to set_empty_key(), after construction. -// The deleted and empty keys must differ. -// -// 2) resize(0): -// When an item is deleted, its memory isn't freed right -// away. This allows you to iterate over a hashtable, -// and call erase(), without invalidating the iterator. -// To force the memory to be freed, call resize(0). -// For tr1 compatibility, this can also be called as rehash(0). -// -// 3) min_load_factor(0.0) -// Setting the minimum load factor to 0.0 guarantees that -// the hash table will never shrink. -// -// Guide to what kind of hash_map to use: -// (1) dense_hash_map: fastest, uses the most memory -// (2) sparse_hash_map: slowest, uses the least memory -// (3) hash_map (STL): in the middle -// Typically I use sparse_hash_map when I care about space and/or when -// I need to save the hashtable on disk. I use hash_map otherwise. I -// don't personally use dense_hash_set ever; some people use it for -// small sets with lots of lookups. -// -// - dense_hash_map has, typically, a factor of 2 memory overhead (if your -// data takes up X bytes, the hash_map uses X more bytes in overhead). -// - sparse_hash_map has about 2 bits overhead per entry. -// - sparse_hash_map can be 3-7 times slower than the others for lookup and, -// especially, inserts. See time_hash_map.cc for details. -// -// See /usr/(local/)?doc/sparsehash-*/dense_hash_map.html -// for information about how to use this class. - -#ifndef _DENSE_HASH_MAP_H_ -#define _DENSE_HASH_MAP_H_ - -#include "google/sparsehash/sparseconfig.h" -#include <stdio.h> // for FILE * in read()/write() -#include <algorithm> // for the default template args -#include <functional> // for equal_to -#include <memory> // for alloc<> -#include <utility> // for pair<> -#include HASH_FUN_H // defined in config.h -#include "google/sparsehash/densehashtable.h" - - -_START_GOOGLE_NAMESPACE_ - -using STL_NAMESPACE::pair; - -template <class Key, class T, - class HashFcn = SPARSEHASH_HASH<Key>, // defined in sparseconfig.h - class EqualKey = STL_NAMESPACE::equal_to<Key>, - class Alloc = STL_NAMESPACE::allocator<T> > -class dense_hash_map { - private: - // Apparently select1st is not stl-standard, so we define our own - struct SelectKey { - const Key& operator()(const pair<const Key, T>& p) const { - return p.first; - } - }; - struct SetKey { - void operator()(pair<const Key, T>* value, const Key& new_key) const { - *const_cast<Key*>(&value->first) = new_key; - // It would be nice to clear the rest of value here as well, in - // case it's taking up a lot of memory. We do this by clearing - // the value. This assumes T has a zero-arg constructor! - value->second = T(); - } - }; - - // The actual data - typedef dense_hashtable<pair<const Key, T>, Key, HashFcn, - SelectKey, SetKey, EqualKey, Alloc> ht; - ht rep; - - public: - typedef typename ht::key_type key_type; - typedef T data_type; - typedef T mapped_type; - typedef typename ht::value_type value_type; - typedef typename ht::hasher hasher; - typedef typename ht::key_equal key_equal; - typedef Alloc allocator_type; - - typedef typename ht::size_type size_type; - typedef typename ht::difference_type difference_type; - typedef typename ht::pointer pointer; - typedef typename ht::const_pointer const_pointer; - typedef typename ht::reference reference; - typedef typename ht::const_reference const_reference; - - typedef typename ht::iterator iterator; - typedef typename ht::const_iterator const_iterator; - typedef typename ht::local_iterator local_iterator; - typedef typename ht::const_local_iterator const_local_iterator; - - // Iterator functions - iterator begin() { return rep.begin(); } - iterator end() { return rep.end(); } - const_iterator begin() const { return rep.begin(); } - const_iterator end() const { return rep.end(); } - - - // These come from tr1's unordered_map. For us, a bucket has 0 or 1 elements. - local_iterator begin(size_type i) { return rep.begin(i); } - local_iterator end(size_type i) { return rep.end(i); } - const_local_iterator begin(size_type i) const { return rep.begin(i); } - const_local_iterator end(size_type i) const { return rep.end(i); } - - // Accessor functions - // TODO(csilvers): implement Alloc get_allocator() const; - hasher hash_funct() const { return rep.hash_funct(); } - hasher hash_function() const { return hash_funct(); } - key_equal key_eq() const { return rep.key_eq(); } - - - // Constructors - explicit dense_hash_map(size_type expected_max_items_in_table = 0, - const hasher& hf = hasher(), - const key_equal& eql = key_equal()) - : rep(expected_max_items_in_table, hf, eql) { } - - template <class InputIterator> - dense_hash_map(InputIterator f, InputIterator l, - size_type expected_max_items_in_table = 0, - const hasher& hf = hasher(), - const key_equal& eql = key_equal()) - : rep(expected_max_items_in_table, hf, eql) { - rep.insert(f, l); - } - // We use the default copy constructor - // We use the default operator=() - // We use the default destructor - - void clear() { rep.clear(); } - // This clears the hash map without resizing it down to the minimum - // bucket count, but rather keeps the number of buckets constant - void clear_no_resize() { rep.clear_no_resize(); } - void swap(dense_hash_map& hs) { rep.swap(hs.rep); } - - - // Functions concerning size - size_type size() const { return rep.size(); } - size_type max_size() const { return rep.max_size(); } - bool empty() const { return rep.empty(); } - size_type bucket_count() const { return rep.bucket_count(); } - size_type max_bucket_count() const { return rep.max_bucket_count(); } - - // These are tr1 methods. bucket() is the bucket the key is or would be in. - size_type bucket_size(size_type i) const { return rep.bucket_size(i); } - size_type bucket(const key_type& key) const { return rep.bucket(key); } - float load_factor() const { - return size() * 1.0f / bucket_count(); - } - float max_load_factor() const { - float shrink, grow; - rep.get_resizing_parameters(&shrink, &grow); - return grow; - } - void max_load_factor(float new_grow) { - float shrink, grow; - rep.get_resizing_parameters(&shrink, &grow); - rep.set_resizing_parameters(shrink, new_grow); - } - // These aren't tr1 methods but perhaps ought to be. - float min_load_factor() const { - float shrink, grow; - rep.get_resizing_parameters(&shrink, &grow); - return shrink; - } - void min_load_factor(float new_shrink) { - float shrink, grow; - rep.get_resizing_parameters(&shrink, &grow); - rep.set_resizing_parameters(new_shrink, grow); - } - // Deprecated; use min_load_factor() or max_load_factor() instead. - void set_resizing_parameters(float shrink, float grow) { - return rep.set_resizing_parameters(shrink, grow); - } - - void resize(size_type hint) { rep.resize(hint); } - void rehash(size_type hint) { resize(hint); } // the tr1 name - - // Lookup routines - iterator find(const key_type& key) { return rep.find(key); } - const_iterator find(const key_type& key) const { return rep.find(key); } - - data_type& operator[](const key_type& key) { // This is our value-add! - iterator it = find(key); - if (it != end()) { - return it->second; - } else { - return insert(value_type(key, data_type())).first->second; - } - } - - size_type count(const key_type& key) const { return rep.count(key); } - - pair<iterator, iterator> equal_range(const key_type& key) { - return rep.equal_range(key); - } - pair<const_iterator, const_iterator> equal_range(const key_type& key) const { - return rep.equal_range(key); - } - - // Insertion routines - pair<iterator, bool> insert(const value_type& obj) { return rep.insert(obj); } - template <class InputIterator> - void insert(InputIterator f, InputIterator l) { rep.insert(f, l); } - void insert(const_iterator f, const_iterator l) { rep.insert(f, l); } - // required for std::insert_iterator; the passed-in iterator is ignored - iterator insert(iterator, const value_type& obj) { return insert(obj).first; } - - - // Deletion and empty routines - // THESE ARE NON-STANDARD! I make you specify an "impossible" key - // value to identify deleted and empty buckets. You can change the - // deleted key as time goes on, or get rid of it entirely to be insert-only. - void set_empty_key(const key_type& key) { // YOU MUST CALL THIS! - rep.set_empty_key(value_type(key, data_type())); // rep wants a value - } - void set_deleted_key(const key_type& key) { - rep.set_deleted_key(key); - } - void clear_deleted_key() { rep.clear_deleted_key(); } - - // These are standard - size_type erase(const key_type& key) { return rep.erase(key); } - void erase(iterator it) { rep.erase(it); } - void erase(iterator f, iterator l) { rep.erase(f, l); } - - - // Comparison - bool operator==(const dense_hash_map& hs) const { return rep == hs.rep; } - bool operator!=(const dense_hash_map& hs) const { return rep != hs.rep; } - - - // I/O -- this is an add-on for writing metainformation to disk - bool write_metadata(FILE *fp) { return rep.write_metadata(fp); } - bool read_metadata(FILE *fp) { return rep.read_metadata(fp); } - bool write_nopointer_data(FILE *fp) { return rep.write_nopointer_data(fp); } - bool read_nopointer_data(FILE *fp) { return rep.read_nopointer_data(fp); } -}; - -// We need a global swap as well -template <class Key, class T, class HashFcn, class EqualKey, class Alloc> -inline void swap(dense_hash_map<Key, T, HashFcn, EqualKey, Alloc>& hm1, - dense_hash_map<Key, T, HashFcn, EqualKey, Alloc>& hm2) { - hm1.swap(hm2); -} - -_END_GOOGLE_NAMESPACE_ - -#endif /* _DENSE_HASH_MAP_H_ */ diff --git a/sources/shiboken2/ext/sparsehash/google/dense_hash_set b/sources/shiboken2/ext/sparsehash/google/dense_hash_set deleted file mode 100644 index faa21dc59..000000000 --- a/sources/shiboken2/ext/sparsehash/google/dense_hash_set +++ /dev/null @@ -1,287 +0,0 @@ -// Copyright (c) 2005, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// --- -// Author: Craig Silverstein -// -// This is just a very thin wrapper over densehashtable.h, just -// like sgi stl's stl_hash_set is a very thin wrapper over -// stl_hashtable. The major thing we define is operator[], because -// we have a concept of a data_type which stl_hashtable doesn't -// (it only has a key and a value). -// -// This is more different from dense_hash_map than you might think, -// because all iterators for sets are const (you obviously can't -// change the key, and for sets there is no value). -// -// NOTE: this is exactly like sparse_hash_set.h, with the word -// "sparse" replaced by "dense", except for the addition of -// set_empty_key(). -// -// YOU MUST CALL SET_EMPTY_KEY() IMMEDIATELY AFTER CONSTRUCTION. -// -// Otherwise your program will die in mysterious ways. -// -// In other respects, we adhere mostly to the STL semantics for -// hash-set. One important exception is that insert() invalidates -// iterators entirely. On the plus side, though, erase() doesn't -// invalidate iterators at all, or even change the ordering of elements. -// -// Here are a few "power user" tips: -// -// 1) set_deleted_key(): -// If you want to use erase() you must call set_deleted_key(), -// in addition to set_empty_key(), after construction. -// The deleted and empty keys must differ. -// -// 2) resize(0): -// When an item is deleted, its memory isn't freed right -// away. This allows you to iterate over a hashtable, -// and call erase(), without invalidating the iterator. -// To force the memory to be freed, call resize(0). -// For tr1 compatibility, this can also be called as rehash(0). -// -// 3) min_load_factor(0.0) -// Setting the minimum load factor to 0.0 guarantees that -// the hash table will never shrink. -// -// Guide to what kind of hash_set to use: -// (1) dense_hash_set: fastest, uses the most memory -// (2) sparse_hash_set: slowest, uses the least memory -// (3) hash_set (STL): in the middle -// Typically I use sparse_hash_set when I care about space and/or when -// I need to save the hashtable on disk. I use hash_set otherwise. I -// don't personally use dense_hash_set ever; some people use it for -// small sets with lots of lookups. -// -// - dense_hash_set has, typically, a factor of 2 memory overhead (if your -// data takes up X bytes, the hash_set uses X more bytes in overhead). -// - sparse_hash_set has about 2 bits overhead per entry. -// - sparse_hash_map can be 3-7 times slower than the others for lookup and, -// especially, inserts. See time_hash_map.cc for details. -// -// See /usr/(local/)?doc/sparsehash-*/dense_hash_set.html -// for information about how to use this class. - -#ifndef _DENSE_HASH_SET_H_ -#define _DENSE_HASH_SET_H_ - -#include <google/sparsehash/sparseconfig.h> -#include <stdio.h> // for FILE * in read()/write() -#include <algorithm> // for the default template args -#include <functional> // for equal_to -#include <memory> // for alloc<> -#include <utility> // for pair<> -#include HASH_FUN_H // defined in config.h -#include <google/sparsehash/densehashtable.h> - - -_START_GOOGLE_NAMESPACE_ - -using STL_NAMESPACE::pair; - -template <class Value, - class HashFcn = SPARSEHASH_HASH<Value>, // defined in sparseconfig.h - class EqualKey = STL_NAMESPACE::equal_to<Value>, - class Alloc = STL_NAMESPACE::allocator<Value> > -class dense_hash_set { - private: - // Apparently identity is not stl-standard, so we define our own - struct Identity { - Value& operator()(Value& v) const { return v; } - const Value& operator()(const Value& v) const { return v; } - }; - struct SetKey { - void operator()(Value* value, const Value& new_key) const { - *value = new_key; - } - }; - - // The actual data - typedef dense_hashtable<Value, Value, HashFcn, - Identity, SetKey, EqualKey, Alloc> ht; - ht rep; - - public: - typedef typename ht::key_type key_type; - typedef typename ht::value_type value_type; - typedef typename ht::hasher hasher; - typedef typename ht::key_equal key_equal; - typedef Alloc allocator_type; - - typedef typename ht::size_type size_type; - typedef typename ht::difference_type difference_type; - typedef typename ht::const_pointer pointer; - typedef typename ht::const_pointer const_pointer; - typedef typename ht::const_reference reference; - typedef typename ht::const_reference const_reference; - - typedef typename ht::const_iterator iterator; - typedef typename ht::const_iterator const_iterator; - typedef typename ht::const_local_iterator local_iterator; - typedef typename ht::const_local_iterator const_local_iterator; - - - // Iterator functions -- recall all iterators are const - iterator begin() const { return rep.begin(); } - iterator end() const { return rep.end(); } - - // These come from tr1's unordered_set. For us, a bucket has 0 or 1 elements. - local_iterator begin(size_type i) const { return rep.begin(i); } - local_iterator end(size_type i) const { return rep.end(i); } - - - // Accessor functions - hasher hash_funct() const { return rep.hash_funct(); } - key_equal key_eq() const { return rep.key_eq(); } - - - // Constructors - explicit dense_hash_set(size_type expected_max_items_in_table = 0, - const hasher& hf = hasher(), - const key_equal& eql = key_equal()) - : rep(expected_max_items_in_table, hf, eql) { } - - template <class InputIterator> - dense_hash_set(InputIterator f, InputIterator l, - size_type expected_max_items_in_table = 0, - const hasher& hf = hasher(), - const key_equal& eql = key_equal()) - : rep(expected_max_items_in_table, hf, eql) { - rep.insert(f, l); - } - // We use the default copy constructor - // We use the default operator=() - // We use the default destructor - - void clear() { rep.clear(); } - // This clears the hash set without resizing it down to the minimum - // bucket count, but rather keeps the number of buckets constant - void clear_no_resize() { rep.clear_no_resize(); } - void swap(dense_hash_set& hs) { rep.swap(hs.rep); } - - - // Functions concerning size - size_type size() const { return rep.size(); } - size_type max_size() const { return rep.max_size(); } - bool empty() const { return rep.empty(); } - size_type bucket_count() const { return rep.bucket_count(); } - size_type max_bucket_count() const { return rep.max_bucket_count(); } - - // These are tr1 methods. bucket() is the bucket the key is or would be in. - size_type bucket_size(size_type i) const { return rep.bucket_size(i); } - size_type bucket(const key_type& key) const { return rep.bucket(key); } - float load_factor() const { - return size() * 1.0f / bucket_count(); - } - float max_load_factor() const { - float shrink, grow; - rep.get_resizing_parameters(&shrink, &grow); - return grow; - } - void max_load_factor(float new_grow) { - float shrink, grow; - rep.get_resizing_parameters(&shrink, &grow); - rep.set_resizing_parameters(shrink, new_grow); - } - // These aren't tr1 methods but perhaps ought to be. - float min_load_factor() const { - float shrink, grow; - rep.get_resizing_parameters(&shrink, &grow); - return shrink; - } - void min_load_factor(float new_shrink) { - float shrink, grow; - rep.get_resizing_parameters(&shrink, &grow); - rep.set_resizing_parameters(new_shrink, grow); - } - // Deprecated; use min_load_factor() or max_load_factor() instead. - void set_resizing_parameters(float shrink, float grow) { - return rep.set_resizing_parameters(shrink, grow); - } - - void resize(size_type hint) { rep.resize(hint); } - void rehash(size_type hint) { resize(hint); } // the tr1 name - - // Lookup routines - iterator find(const key_type& key) const { return rep.find(key); } - - size_type count(const key_type& key) const { return rep.count(key); } - - pair<iterator, iterator> equal_range(const key_type& key) const { - return rep.equal_range(key); - } - - // Insertion routines - pair<iterator, bool> insert(const value_type& obj) { - pair<typename ht::iterator, bool> p = rep.insert(obj); - return pair<iterator, bool>(p.first, p.second); // const to non-const - } - template <class InputIterator> - void insert(InputIterator f, InputIterator l) { rep.insert(f, l); } - void insert(const_iterator f, const_iterator l) { rep.insert(f, l); } - // required for std::insert_iterator; the passed-in iterator is ignored - iterator insert(iterator, const value_type& obj) { return insert(obj).first; } - - - // Deletion and empty routines - // THESE ARE NON-STANDARD! I make you specify an "impossible" key - // value to identify deleted and empty buckets. You can change the - // deleted key as time goes on, or get rid of it entirely to be insert-only. - void set_empty_key(const key_type& key) { rep.set_empty_key(key); } - void set_deleted_key(const key_type& key) { rep.set_deleted_key(key); } - void clear_deleted_key() { rep.clear_deleted_key(); } - - // These are standard - size_type erase(const key_type& key) { return rep.erase(key); } - void erase(iterator it) { rep.erase(it); } - void erase(iterator f, iterator l) { rep.erase(f, l); } - - - // Comparison - bool operator==(const dense_hash_set& hs) const { return rep == hs.rep; } - bool operator!=(const dense_hash_set& hs) const { return rep != hs.rep; } - - - // I/O -- this is an add-on for writing metainformation to disk - bool write_metadata(FILE *fp) { return rep.write_metadata(fp); } - bool read_metadata(FILE *fp) { return rep.read_metadata(fp); } - bool write_nopointer_data(FILE *fp) { return rep.write_nopointer_data(fp); } - bool read_nopointer_data(FILE *fp) { return rep.read_nopointer_data(fp); } -}; - -template <class Val, class HashFcn, class EqualKey, class Alloc> -inline void swap(dense_hash_set<Val, HashFcn, EqualKey, Alloc>& hs1, - dense_hash_set<Val, HashFcn, EqualKey, Alloc>& hs2) { - hs1.swap(hs2); -} - -_END_GOOGLE_NAMESPACE_ - -#endif /* _DENSE_HASH_SET_H_ */ diff --git a/sources/shiboken2/ext/sparsehash/google/sparsehash/densehashtable.h b/sources/shiboken2/ext/sparsehash/google/sparsehash/densehashtable.h deleted file mode 100644 index 33b191ec8..000000000 --- a/sources/shiboken2/ext/sparsehash/google/sparsehash/densehashtable.h +++ /dev/null @@ -1,1062 +0,0 @@ -// Copyright (c) 2005, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// --- -// Author: Craig Silverstein -// -// A dense hashtable is a particular implementation of -// a hashtable: one that is meant to minimize memory allocation. -// It does this by using an array to store all the data. We -// steal a value from the key space to indicate "empty" array -// elements (ie indices where no item lives) and another to indicate -// "deleted" elements. -// -// (Note it is possible to change the value of the delete key -// on the fly; you can even remove it, though after that point -// the hashtable is insert_only until you set it again. The empty -// value however can't be changed.) -// -// To minimize allocation and pointer overhead, we use internal -// probing, in which the hashtable is a single table, and collisions -// are resolved by trying to insert again in another bucket. The -// most cache-efficient internal probing schemes are linear probing -// (which suffers, alas, from clumping) and quadratic probing, which -// is what we implement by default. -// -// Type requirements: value_type is required to be Copy Constructible -// and Default Constructible. It is not required to be (and commonly -// isn't) Assignable. -// -// You probably shouldn't use this code directly. Use -// <google/dense_hash_map> or <google/dense_hash_set> instead. - -// You can change the following below: -// HT_OCCUPANCY_FLT -- how full before we double size -// HT_EMPTY_FLT -- how empty before we halve size -// HT_MIN_BUCKETS -- default smallest bucket size -// -// You can also change enlarge_resize_percent (which defaults to -// HT_OCCUPANCY_FLT), and shrink_resize_percent (which defaults to -// HT_EMPTY_FLT) with set_resizing_parameters(). -// -// How to decide what values to use? -// shrink_resize_percent's default of .4 * OCCUPANCY_FLT, is probably good. -// HT_MIN_BUCKETS is probably unnecessary since you can specify -// (indirectly) the starting number of buckets at construct-time. -// For enlarge_resize_percent, you can use this chart to try to trade-off -// expected lookup time to the space taken up. By default, this -// code uses quadratic probing, though you can change it to linear -// via _JUMP below if you really want to. -// -// From http://www.augustana.ca/~mohrj/courses/1999.fall/csc210/lecture_notes/hashing.html -// NUMBER OF PROBES / LOOKUP Successful Unsuccessful -// Quadratic collision resolution 1 - ln(1-L) - L/2 1/(1-L) - L - ln(1-L) -// Linear collision resolution [1+1/(1-L)]/2 [1+1/(1-L)2]/2 -// -// -- enlarge_resize_percent -- 0.10 0.50 0.60 0.75 0.80 0.90 0.99 -// QUADRATIC COLLISION RES. -// probes/successful lookup 1.05 1.44 1.62 2.01 2.21 2.85 5.11 -// probes/unsuccessful lookup 1.11 2.19 2.82 4.64 5.81 11.4 103.6 -// LINEAR COLLISION RES. -// probes/successful lookup 1.06 1.5 1.75 2.5 3.0 5.5 50.5 -// probes/unsuccessful lookup 1.12 2.5 3.6 8.5 13.0 50.0 5000.0 - -#ifndef _DENSEHASHTABLE_H_ -#define _DENSEHASHTABLE_H_ - -// The probing method -// Linear probing -// #define JUMP_(key, num_probes) ( 1 ) -// Quadratic-ish probing -#define JUMP_(key, num_probes) ( num_probes ) - - -#include "google/sparsehash/sparseconfig.h" -#include <assert.h> -#include <stdio.h> -#include <stdlib.h> // for abort() -#include <algorithm> // For swap(), eg -#include <iostream> // For cerr -#include <memory> // For uninitialized_fill, uninitialized_copy -#include <utility> // for pair<> -#include <iterator> // for facts about iterator tags -#include "google/type_traits.h" // for true_type, integral_constant, etc. - -_START_GOOGLE_NAMESPACE_ - -using STL_NAMESPACE::pair; - -// Hashtable class, used to implement the hashed associative containers -// hash_set and hash_map. - -// Value: what is stored in the table (each bucket is a Value). -// Key: something in a 1-to-1 correspondence to a Value, that can be used -// to search for a Value in the table (find() takes a Key). -// HashFcn: Takes a Key and returns an integer, the more unique the better. -// ExtractKey: given a Value, returns the unique Key associated with it. -// SetKey: given a Value* and a Key, modifies the value such that -// ExtractKey(value) == key. We guarantee this is only called -// with key == deleted_key or key == empty_key. -// EqualKey: Given two Keys, says whether they are the same (that is, -// if they are both associated with the same Value). -// Alloc: STL allocator to use to allocate memory. Currently ignored. - -template <class Value, class Key, class HashFcn, - class ExtractKey, class SetKey, class EqualKey, class Alloc> -class dense_hashtable; - -template <class V, class K, class HF, class ExK, class SetK, class EqK, class A> -struct dense_hashtable_iterator; - -template <class V, class K, class HF, class ExK, class SetK, class EqK, class A> -struct dense_hashtable_const_iterator; - -// We're just an array, but we need to skip over empty and deleted elements -template <class V, class K, class HF, class ExK, class SetK, class EqK, class A> -struct dense_hashtable_iterator { - public: - typedef dense_hashtable_iterator<V,K,HF,ExK,SetK,EqK,A> iterator; - typedef dense_hashtable_const_iterator<V,K,HF,ExK,SetK,EqK,A> const_iterator; - - typedef STL_NAMESPACE::forward_iterator_tag iterator_category; - typedef V value_type; - typedef STL_NAMESPACE::ptrdiff_t difference_type; - typedef size_t size_type; - typedef V& reference; // Value - typedef V* pointer; - - // "Real" constructor and default constructor - dense_hashtable_iterator(const dense_hashtable<V,K,HF,ExK,SetK,EqK,A> *h, - pointer it, pointer it_end, bool advance) - : ht(h), pos(it), end(it_end) { - if (advance) advance_past_empty_and_deleted(); - } - dense_hashtable_iterator() { } - // The default destructor is fine; we don't define one - // The default operator= is fine; we don't define one - - // Happy dereferencer - reference operator*() const { return *pos; } - pointer operator->() const { return &(operator*()); } - - // Arithmetic. The only hard part is making sure that - // we're not on an empty or marked-deleted array element - void advance_past_empty_and_deleted() { - while ( pos != end && (ht->test_empty(*this) || ht->test_deleted(*this)) ) - ++pos; - } - iterator& operator++() { - assert(pos != end); ++pos; advance_past_empty_and_deleted(); return *this; - } - iterator operator++(int) { iterator tmp(*this); ++*this; return tmp; } - - // Comparison. - bool operator==(const iterator& it) const { return pos == it.pos; } - bool operator!=(const iterator& it) const { return pos != it.pos; } - - - // The actual data - const dense_hashtable<V,K,HF,ExK,SetK,EqK,A> *ht; - pointer pos, end; -}; - - -// Now do it all again, but with const-ness! -template <class V, class K, class HF, class ExK, class SetK, class EqK, class A> -struct dense_hashtable_const_iterator { - public: - typedef dense_hashtable_iterator<V,K,HF,ExK,SetK,EqK,A> iterator; - typedef dense_hashtable_const_iterator<V,K,HF,ExK,SetK,EqK,A> const_iterator; - - typedef STL_NAMESPACE::forward_iterator_tag iterator_category; - typedef V value_type; - typedef STL_NAMESPACE::ptrdiff_t difference_type; - typedef size_t size_type; - typedef const V& reference; // Value - typedef const V* pointer; - - // "Real" constructor and default constructor - dense_hashtable_const_iterator( - const dense_hashtable<V,K,HF,ExK,SetK,EqK,A> *h, - pointer it, pointer it_end, bool advance) - : ht(h), pos(it), end(it_end) { - if (advance) advance_past_empty_and_deleted(); - } - dense_hashtable_const_iterator() { } - // This lets us convert regular iterators to const iterators - dense_hashtable_const_iterator(const iterator &it) - : ht(it.ht), pos(it.pos), end(it.end) { } - // The default destructor is fine; we don't define one - // The default operator= is fine; we don't define one - - // Happy dereferencer - reference operator*() const { return *pos; } - pointer operator->() const { return &(operator*()); } - - // Arithmetic. The only hard part is making sure that - // we're not on an empty or marked-deleted array element - void advance_past_empty_and_deleted() { - while ( pos != end && (ht->test_empty(*this) || ht->test_deleted(*this)) ) - ++pos; - } - const_iterator& operator++() { - assert(pos != end); ++pos; advance_past_empty_and_deleted(); return *this; - } - const_iterator operator++(int) { const_iterator tmp(*this); ++*this; return tmp; } - - // Comparison. - bool operator==(const const_iterator& it) const { return pos == it.pos; } - bool operator!=(const const_iterator& it) const { return pos != it.pos; } - - - // The actual data - const dense_hashtable<V,K,HF,ExK,SetK,EqK,A> *ht; - pointer pos, end; -}; - -template <class Value, class Key, class HashFcn, - class ExtractKey, class SetKey, class EqualKey, class Alloc> -class dense_hashtable { - public: - typedef Key key_type; - typedef Value value_type; - typedef HashFcn hasher; - typedef EqualKey key_equal; - - typedef size_t size_type; - typedef STL_NAMESPACE::ptrdiff_t difference_type; - typedef value_type* pointer; - typedef const value_type* const_pointer; - typedef value_type& reference; - typedef const value_type& const_reference; - typedef dense_hashtable_iterator<Value, Key, HashFcn, - ExtractKey, SetKey, EqualKey, Alloc> - iterator; - - typedef dense_hashtable_const_iterator<Value, Key, HashFcn, - ExtractKey, SetKey, EqualKey, Alloc> - const_iterator; - - // These come from tr1. For us they're the same as regular iterators. - typedef iterator local_iterator; - typedef const_iterator const_local_iterator; - - // How full we let the table get before we resize, by default. - // Knuth says .8 is good -- higher causes us to probe too much, - // though it saves memory. - static const float HT_OCCUPANCY_FLT; // = 0.5; - - // How empty we let the table get before we resize lower, by default. - // (0.0 means never resize lower.) - // It should be less than OCCUPANCY_FLT / 2 or we thrash resizing - static const float HT_EMPTY_FLT; // = 0.4 * HT_OCCUPANCY_FLT - - // Minimum size we're willing to let hashtables be. - // Must be a power of two, and at least 4. - // Note, however, that for a given hashtable, the initial size is a - // function of the first constructor arg, and may be >HT_MIN_BUCKETS. - static const size_t HT_MIN_BUCKETS = 4; - - // By default, if you don't specify a hashtable size at - // construction-time, we use this size. Must be a power of two, and - // at least HT_MIN_BUCKETS. - static const size_t HT_DEFAULT_STARTING_BUCKETS = 32; - - - // ITERATOR FUNCTIONS - iterator begin() { return iterator(this, table, - table + num_buckets, true); } - iterator end() { return iterator(this, table + num_buckets, - table + num_buckets, true); } - const_iterator begin() const { return const_iterator(this, table, - table+num_buckets,true);} - const_iterator end() const { return const_iterator(this, table + num_buckets, - table+num_buckets,true);} - - // These come from tr1 unordered_map. They iterate over 'bucket' n. - // For sparsehashtable, we could consider each 'group' to be a bucket, - // I guess, but I don't really see the point. We'll just consider - // bucket n to be the n-th element of the sparsetable, if it's occupied, - // or some empty element, otherwise. - local_iterator begin(size_type i) { - return local_iterator(this, table + i, table + i+1, false); - } - local_iterator end(size_type i) { - local_iterator it = begin(i); - if (!test_empty(i) && !test_deleted(i)) - ++it; - return it; - } - const_local_iterator begin(size_type i) const { - return const_local_iterator(this, table + i, table + i+1, false); - } - const_local_iterator end(size_type i) const { - const_local_iterator it = begin(i); - if (!test_empty(i) && !test_deleted(i)) - ++it; - return it; - } - - // ACCESSOR FUNCTIONS for the things we templatize on, basically - hasher hash_funct() const { return hash; } - key_equal key_eq() const { return equals; } - - private: - // Annoyingly, we can't copy values around, because they might have - // const components (they're probably pair<const X, Y>). We use - // explicit destructor invocation and placement new to get around - // this. Arg. - void set_value(value_type* dst, const value_type& src) { - dst->~value_type(); - new(dst) value_type(src); - } - - void destroy_buckets(size_type first, size_type last) { - for ( ; first != last; ++first) - table[first].~value_type(); - } - - // DELETE HELPER FUNCTIONS - // This lets the user describe a key that will indicate deleted - // table entries. This key should be an "impossible" entry -- - // if you try to insert it for real, you won't be able to retrieve it! - // (NB: while you pass in an entire value, only the key part is looked - // at. This is just because I don't know how to assign just a key.) - private: - void squash_deleted() { // gets rid of any deleted entries we have - if ( num_deleted ) { // get rid of deleted before writing - dense_hashtable tmp(*this); // copying will get rid of deleted - swap(tmp); // now we are tmp - } - assert(num_deleted == 0); - } - - public: - void set_deleted_key(const key_type &key) { - // the empty indicator (if specified) and the deleted indicator - // must be different - assert(!use_empty || !equals(key, get_key(emptyval))); - // It's only safe to change what "deleted" means if we purge deleted guys - squash_deleted(); - use_deleted = true; - delkey = key; - } - void clear_deleted_key() { - squash_deleted(); - use_deleted = false; - } - - // These are public so the iterators can use them - // True if the item at position bucknum is "deleted" marker - bool test_deleted(size_type bucknum) const { - // The num_deleted test is crucial for read(): after read(), the ht values - // are garbage, and we don't want to think some of them are deleted. - return (use_deleted && num_deleted > 0 && - equals(delkey, get_key(table[bucknum]))); - } - bool test_deleted(const iterator &it) const { - return (use_deleted && num_deleted > 0 && - equals(delkey, get_key(*it))); - } - bool test_deleted(const const_iterator &it) const { - return (use_deleted && num_deleted > 0 && - equals(delkey, get_key(*it))); - } - // Set it so test_deleted is true. true if object didn't used to be deleted - // See below (at erase()) to explain why we allow const_iterators - bool set_deleted(const_iterator &it) { - assert(use_deleted); // bad if set_deleted_key() wasn't called - bool retval = !test_deleted(it); - // &* converts from iterator to value-type - set_key(const_cast<value_type*>(&(*it)), delkey); - return retval; - } - // Set it so test_deleted is false. true if object used to be deleted - bool clear_deleted(const_iterator &it) { - assert(use_deleted); // bad if set_deleted_key() wasn't called - // happens automatically when we assign something else in its place - return test_deleted(it); - } - - // EMPTY HELPER FUNCTIONS - // This lets the user describe a key that will indicate empty (unused) - // table entries. This key should be an "impossible" entry -- - // if you try to insert it for real, you won't be able to retrieve it! - // (NB: while you pass in an entire value, only the key part is looked - // at. This is just because I don't know how to assign just a key.) - public: - // These are public so the iterators can use them - // True if the item at position bucknum is "empty" marker - bool test_empty(size_type bucknum) const { - assert(use_empty); // we always need to know what's empty! - return equals(get_key(emptyval), get_key(table[bucknum])); - } - bool test_empty(const iterator &it) const { - assert(use_empty); // we always need to know what's empty! - return equals(get_key(emptyval), get_key(*it)); - } - bool test_empty(const const_iterator &it) const { - assert(use_empty); // we always need to know what's empty! - return equals(get_key(emptyval), get_key(*it)); - } - - private: - // You can either set a range empty or an individual element - void set_empty(size_type bucknum) { - assert(use_empty); - set_value(&table[bucknum], emptyval); - } - void fill_range_with_empty(value_type* table_start, value_type* table_end) { - // Like set_empty(range), but doesn't destroy previous contents - STL_NAMESPACE::uninitialized_fill(table_start, table_end, emptyval); - } - void set_empty(size_type buckstart, size_type buckend) { - assert(use_empty); - destroy_buckets(buckstart, buckend); - fill_range_with_empty(table + buckstart, table + buckend); - } - - public: - // TODO(csilvers): change all callers of this to pass in a key instead, - // and take a const key_type instead of const value_type. - void set_empty_key(const value_type &val) { - // Once you set the empty key, you can't change it - assert(!use_empty); - // The deleted indicator (if specified) and the empty indicator - // must be different. - assert(!use_deleted || !equals(get_key(val), delkey)); - use_empty = true; - set_value(&emptyval, val); - - assert(!table); // must set before first use - // num_buckets was set in constructor even though table was NULL - table = (value_type *) malloc(num_buckets * sizeof(*table)); - assert(table); - fill_range_with_empty(table, table + num_buckets); - } - - // FUNCTIONS CONCERNING SIZE - public: - size_type size() const { return num_elements - num_deleted; } - // Buckets are always a power of 2 - size_type max_size() const { return (size_type(-1) >> 1U) + 1; } - bool empty() const { return size() == 0; } - size_type bucket_count() const { return num_buckets; } - size_type max_bucket_count() const { return max_size(); } - size_type nonempty_bucket_count() const { return num_elements; } - // These are tr1 methods. Their idea of 'bucket' doesn't map well to - // what we do. We just say every bucket has 0 or 1 items in it. - size_type bucket_size(size_type i) const { - return begin(i) == end(i) ? 0 : 1; - } - - - - private: - // Because of the above, size_type(-1) is never legal; use it for errors - static const size_type ILLEGAL_BUCKET = size_type(-1); - - private: - // This is the smallest size a hashtable can be without being too crowded - // If you like, you can give a min #buckets as well as a min #elts - size_type min_size(size_type num_elts, size_type min_buckets_wanted) { - size_type sz = HT_MIN_BUCKETS; // min buckets allowed - while ( sz < min_buckets_wanted || num_elts >= sz * enlarge_resize_percent ) - sz *= 2; - return sz; - } - - // Used after a string of deletes - void maybe_shrink() { - assert(num_elements >= num_deleted); - assert((bucket_count() & (bucket_count()-1)) == 0); // is a power of two - assert(bucket_count() >= HT_MIN_BUCKETS); - - // If you construct a hashtable with < HT_DEFAULT_STARTING_BUCKETS, - // we'll never shrink until you get relatively big, and we'll never - // shrink below HT_DEFAULT_STARTING_BUCKETS. Otherwise, something - // like "dense_hash_set<int> x; x.insert(4); x.erase(4);" will - // shrink us down to HT_MIN_BUCKETS buckets, which is too small. - if (shrink_threshold > 0 && - (num_elements-num_deleted) < shrink_threshold && - bucket_count() > HT_DEFAULT_STARTING_BUCKETS ) { - size_type sz = bucket_count() / 2; // find how much we should shrink - while ( sz > HT_DEFAULT_STARTING_BUCKETS && - (num_elements - num_deleted) < sz * shrink_resize_percent ) - sz /= 2; // stay a power of 2 - dense_hashtable tmp(*this, sz); // Do the actual resizing - swap(tmp); // now we are tmp - } - consider_shrink = false; // because we just considered it - } - - // We'll let you resize a hashtable -- though this makes us copy all! - // When you resize, you say, "make it big enough for this many more elements" - void resize_delta(size_type delta) { - if ( consider_shrink ) // see if lots of deletes happened - maybe_shrink(); - if ( bucket_count() > HT_MIN_BUCKETS && - (num_elements + delta) <= enlarge_threshold ) - return; // we're ok as we are - - // Sometimes, we need to resize just to get rid of all the - // "deleted" buckets that are clogging up the hashtable. So when - // deciding whether to resize, count the deleted buckets (which - // are currently taking up room). But later, when we decide what - // size to resize to, *don't* count deleted buckets, since they - // get discarded during the resize. - const size_type needed_size = min_size(num_elements + delta, 0); - if ( needed_size > bucket_count() ) { // we don't have enough buckets - const size_type resize_to = min_size(num_elements - num_deleted + delta, - 0); - dense_hashtable tmp(*this, resize_to); - swap(tmp); // now we are tmp - } - } - - // Increase number of buckets, assuming value_type has trivial copy - // constructor and destructor. (Really, we want it to have "trivial - // move", because that's what realloc does. But there's no way to - // capture that using type_traits, so we pretend that move(x, y) is - // equivalent to "x.~T(); new(x) T(y);" which is pretty much - // correct, if a bit conservative.) - void expand_array(size_t resize_to, true_type) { - table = (value_type *) realloc(table, resize_to * sizeof(value_type)); - assert(table); - fill_range_with_empty(table + num_buckets, table + resize_to); - } - - // Increase number of buckets, without special assumptions about value_type. - // TODO(austern): make this exception safe. Handle exceptions from - // value_type's copy constructor. - void expand_array(size_t resize_to, false_type) { - value_type* new_table = - (value_type *) malloc(resize_to * sizeof(value_type)); - assert(new_table); - STL_NAMESPACE::uninitialized_copy(table, table + num_buckets, new_table); - fill_range_with_empty(new_table + num_buckets, new_table + resize_to); - destroy_buckets(0, num_buckets); - free(table); - table = new_table; - } - - // Used to actually do the rehashing when we grow/shrink a hashtable - void copy_from(const dense_hashtable &ht, size_type min_buckets_wanted) { - clear(); // clear table, set num_deleted to 0 - - // If we need to change the size of our table, do it now - const size_type resize_to = min_size(ht.size(), min_buckets_wanted); - if ( resize_to > bucket_count() ) { // we don't have enough buckets - typedef integral_constant<bool, - (has_trivial_copy<value_type>::value && - has_trivial_destructor<value_type>::value)> - realloc_ok; // we pretend mv(x,y) == "x.~T(); new(x) T(y)" - expand_array(resize_to, realloc_ok()); - num_buckets = resize_to; - reset_thresholds(); - } - - // We use a normal iterator to get non-deleted bcks from ht - // We could use insert() here, but since we know there are - // no duplicates and no deleted items, we can be more efficient - assert((bucket_count() & (bucket_count()-1)) == 0); // a power of two - for ( const_iterator it = ht.begin(); it != ht.end(); ++it ) { - size_type num_probes = 0; // how many times we've probed - size_type bucknum; - const size_type bucket_count_minus_one = bucket_count() - 1; - for (bucknum = hash(get_key(*it)) & bucket_count_minus_one; - !test_empty(bucknum); // not empty - bucknum = (bucknum + JUMP_(key, num_probes)) & bucket_count_minus_one) { - ++num_probes; - assert(num_probes < bucket_count()); // or else the hashtable is full - } - set_value(&table[bucknum], *it); // copies the value to here - num_elements++; - } - } - - // Required by the spec for hashed associative container - public: - // Though the docs say this should be num_buckets, I think it's much - // more useful as req_elements. As a special feature, calling with - // req_elements==0 will cause us to shrink if we can, saving space. - void resize(size_type req_elements) { // resize to this or larger - if ( consider_shrink || req_elements == 0 ) - maybe_shrink(); - if ( req_elements > num_elements ) - return resize_delta(req_elements - num_elements); - } - - // Get and change the value of shrink_resize_percent and - // enlarge_resize_percent. The description at the beginning of this - // file explains how to choose the values. Setting the shrink - // parameter to 0.0 ensures that the table never shrinks. - void get_resizing_parameters(float* shrink, float* grow) const { - *shrink = shrink_resize_percent; - *grow = enlarge_resize_percent; - } - void set_resizing_parameters(float shrink, float grow) { - assert(shrink >= 0.0); - assert(grow <= 1.0); - if (shrink > grow/2.0f) - shrink = grow / 2.0f; // otherwise we thrash hashtable size - shrink_resize_percent = shrink; - enlarge_resize_percent = grow; - reset_thresholds(); - } - - // CONSTRUCTORS -- as required by the specs, we take a size, - // but also let you specify a hashfunction, key comparator, - // and key extractor. We also define a copy constructor and =. - // DESTRUCTOR -- needs to free the table - explicit dense_hashtable(size_type expected_max_items_in_table = 0, - const HashFcn& hf = HashFcn(), - const EqualKey& eql = EqualKey(), - const ExtractKey& ext = ExtractKey(), - const SetKey& set = SetKey()) - : hash(hf), equals(eql), get_key(ext), set_key(set), num_deleted(0), - use_deleted(false), use_empty(false), - delkey(), emptyval(), enlarge_resize_percent(HT_OCCUPANCY_FLT), - shrink_resize_percent(HT_EMPTY_FLT), table(NULL), - num_buckets(expected_max_items_in_table == 0 - ? HT_DEFAULT_STARTING_BUCKETS - : min_size(expected_max_items_in_table, 0)), - num_elements(0) { - // table is NULL until emptyval is set. However, we set num_buckets - // here so we know how much space to allocate once emptyval is set - reset_thresholds(); - } - - // As a convenience for resize(), we allow an optional second argument - // which lets you make this new hashtable a different size than ht - dense_hashtable(const dense_hashtable& ht, - size_type min_buckets_wanted = HT_DEFAULT_STARTING_BUCKETS) - : hash(ht.hash), equals(ht.equals), - get_key(ht.get_key), set_key(ht.set_key), num_deleted(0), - use_deleted(ht.use_deleted), use_empty(ht.use_empty), - delkey(ht.delkey), emptyval(ht.emptyval), - enlarge_resize_percent(ht.enlarge_resize_percent), - shrink_resize_percent(ht.shrink_resize_percent), table(NULL), - num_buckets(0), num_elements(0) { - reset_thresholds(); - copy_from(ht, min_buckets_wanted); // copy_from() ignores deleted entries - } - - dense_hashtable& operator= (const dense_hashtable& ht) { - if (&ht == this) return *this; // don't copy onto ourselves - clear(); - hash = ht.hash; - equals = ht.equals; - get_key = ht.get_key; - set_key = ht.set_key; - use_deleted = ht.use_deleted; - use_empty = ht.use_empty; - delkey = ht.delkey; - set_value(&emptyval, ht.emptyval); - enlarge_resize_percent = ht.enlarge_resize_percent; - shrink_resize_percent = ht.shrink_resize_percent; - copy_from(ht, HT_MIN_BUCKETS); // sets num_deleted to 0 too - return *this; - } - - ~dense_hashtable() { - if (table) { - destroy_buckets(0, num_buckets); - free(table); - } - } - - // Many STL algorithms use swap instead of copy constructors - void swap(dense_hashtable& ht) { - STL_NAMESPACE::swap(hash, ht.hash); - STL_NAMESPACE::swap(equals, ht.equals); - STL_NAMESPACE::swap(get_key, ht.get_key); - STL_NAMESPACE::swap(set_key, ht.set_key); - STL_NAMESPACE::swap(num_deleted, ht.num_deleted); - STL_NAMESPACE::swap(use_deleted, ht.use_deleted); - STL_NAMESPACE::swap(use_empty, ht.use_empty); - STL_NAMESPACE::swap(enlarge_resize_percent, ht.enlarge_resize_percent); - STL_NAMESPACE::swap(shrink_resize_percent, ht.shrink_resize_percent); - STL_NAMESPACE::swap(delkey, ht.delkey); - { value_type tmp; // for annoying reasons, swap() doesn't work - set_value(&tmp, emptyval); - set_value(&emptyval, ht.emptyval); - set_value(&ht.emptyval, tmp); - } - STL_NAMESPACE::swap(table, ht.table); - STL_NAMESPACE::swap(num_buckets, ht.num_buckets); - STL_NAMESPACE::swap(num_elements, ht.num_elements); - reset_thresholds(); - ht.reset_thresholds(); - } - - // It's always nice to be able to clear a table without deallocating it - void clear() { - if (table) - destroy_buckets(0, num_buckets); - num_buckets = min_size(0,0); // our new size - reset_thresholds(); - table = (value_type *) realloc(table, num_buckets * sizeof(*table)); - assert(table); - fill_range_with_empty(table, table + num_buckets); - num_elements = 0; - num_deleted = 0; - } - - // Clear the table without resizing it. - // Mimicks the stl_hashtable's behaviour when clear()-ing in that it - // does not modify the bucket count - void clear_no_resize() { - if (table) { - set_empty(0, num_buckets); - } - // don't consider to shrink before another erase() - reset_thresholds(); - num_elements = 0; - num_deleted = 0; - } - - // LOOKUP ROUTINES - private: - // Returns a pair of positions: 1st where the object is, 2nd where - // it would go if you wanted to insert it. 1st is ILLEGAL_BUCKET - // if object is not found; 2nd is ILLEGAL_BUCKET if it is. - // Note: because of deletions where-to-insert is not trivial: it's the - // first deleted bucket we see, as long as we don't find the key later - pair<size_type, size_type> find_position(const key_type &key) const { - size_type num_probes = 0; // how many times we've probed - const size_type bucket_count_minus_one = bucket_count() - 1; - size_type bucknum = hash(key) & bucket_count_minus_one; - size_type insert_pos = ILLEGAL_BUCKET; // where we would insert - while ( 1 ) { // probe until something happens - if ( test_empty(bucknum) ) { // bucket is empty - if ( insert_pos == ILLEGAL_BUCKET ) // found no prior place to insert - return pair<size_type,size_type>(ILLEGAL_BUCKET, bucknum); - else - return pair<size_type,size_type>(ILLEGAL_BUCKET, insert_pos); - - } else if ( test_deleted(bucknum) ) {// keep searching, but mark to insert - if ( insert_pos == ILLEGAL_BUCKET ) - insert_pos = bucknum; - - } else if ( equals(key, get_key(table[bucknum])) ) { - return pair<size_type,size_type>(bucknum, ILLEGAL_BUCKET); - } - ++num_probes; // we're doing another probe - bucknum = (bucknum + JUMP_(key, num_probes)) & bucket_count_minus_one; - assert(num_probes < bucket_count()); // don't probe too many times! - } - } - - public: - iterator find(const key_type& key) { - if ( size() == 0 ) return end(); - pair<size_type, size_type> pos = find_position(key); - if ( pos.first == ILLEGAL_BUCKET ) // alas, not there - return end(); - else - return iterator(this, table + pos.first, table + num_buckets, false); - } - - const_iterator find(const key_type& key) const { - if ( size() == 0 ) return end(); - pair<size_type, size_type> pos = find_position(key); - if ( pos.first == ILLEGAL_BUCKET ) // alas, not there - return end(); - else - return const_iterator(this, table + pos.first, table+num_buckets, false); - } - - // This is a tr1 method: the bucket a given key is in, or what bucket - // it would be put in, if it were to be inserted. Shrug. - size_type bucket(const key_type& key) const { - pair<size_type, size_type> pos = find_position(key); - return pos.first == ILLEGAL_BUCKET ? pos.second : pos.first; - } - - // Counts how many elements have key key. For maps, it's either 0 or 1. - size_type count(const key_type &key) const { - pair<size_type, size_type> pos = find_position(key); - return pos.first == ILLEGAL_BUCKET ? 0 : 1; - } - - // Likewise, equal_range doesn't really make sense for us. Oh well. - pair<iterator,iterator> equal_range(const key_type& key) { - iterator pos = find(key); // either an iterator or end - if (pos == end()) { - return pair<iterator,iterator>(pos, pos); - } else { - const iterator startpos = pos++; - return pair<iterator,iterator>(startpos, pos); - } - } - pair<const_iterator,const_iterator> equal_range(const key_type& key) const { - const_iterator pos = find(key); // either an iterator or end - if (pos == end()) { - return pair<const_iterator,const_iterator>(pos, pos); - } else { - const const_iterator startpos = pos++; - return pair<const_iterator,const_iterator>(startpos, pos); - } - } - - - // INSERTION ROUTINES - private: - // If you know *this is big enough to hold obj, use this routine - pair<iterator, bool> insert_noresize(const value_type& obj) { - // First, double-check we're not inserting delkey or emptyval - assert(!use_empty || !equals(get_key(obj), get_key(emptyval))); - assert(!use_deleted || !equals(get_key(obj), delkey)); - const pair<size_type,size_type> pos = find_position(get_key(obj)); - if ( pos.first != ILLEGAL_BUCKET) { // object was already there - return pair<iterator,bool>(iterator(this, table + pos.first, - table + num_buckets, false), - false); // false: we didn't insert - } else { // pos.second says where to put it - if ( test_deleted(pos.second) ) { // just replace if it's been del. - const_iterator delpos(this, table + pos.second, // shrug: - table + num_buckets, false);// shouldn't need const - clear_deleted(delpos); - assert( num_deleted > 0); - --num_deleted; // used to be, now it isn't - } else { - ++num_elements; // replacing an empty bucket - } - set_value(&table[pos.second], obj); - return pair<iterator,bool>(iterator(this, table + pos.second, - table + num_buckets, false), - true); // true: we did insert - } - } - - public: - // This is the normal insert routine, used by the outside world - pair<iterator, bool> insert(const value_type& obj) { - resize_delta(1); // adding an object, grow if need be - return insert_noresize(obj); - } - - // When inserting a lot at a time, we specialize on the type of iterator - template <class InputIterator> - void insert(InputIterator f, InputIterator l) { - // specializes on iterator type - insert(f, l, typename STL_NAMESPACE::iterator_traits<InputIterator>::iterator_category()); - } - - // Iterator supports operator-, resize before inserting - template <class ForwardIterator> - void insert(ForwardIterator f, ForwardIterator l, - STL_NAMESPACE::forward_iterator_tag) { - size_type n = STL_NAMESPACE::distance(f, l); // TODO(csilvers): standard? - resize_delta(n); - for ( ; n > 0; --n, ++f) - insert_noresize(*f); - } - - // Arbitrary iterator, can't tell how much to resize - template <class InputIterator> - void insert(InputIterator f, InputIterator l, - STL_NAMESPACE::input_iterator_tag) { - for ( ; f != l; ++f) - insert(*f); - } - - - // DELETION ROUTINES - size_type erase(const key_type& key) { - // First, double-check we're not trying to erase delkey or emptyval - assert(!use_empty || !equals(key, get_key(emptyval))); - assert(!use_deleted || !equals(key, delkey)); - const_iterator pos = find(key); // shrug: shouldn't need to be const - if ( pos != end() ) { - assert(!test_deleted(pos)); // or find() shouldn't have returned it - set_deleted(pos); - ++num_deleted; - consider_shrink = true; // will think about shrink after next insert - return 1; // because we deleted one thing - } else { - return 0; // because we deleted nothing - } - } - - // This is really evil: really it should be iterator, not const_iterator. - // But...the only reason keys are const is to allow lookup. - // Since that's a moot issue for deleted keys, we allow const_iterators - void erase(const_iterator pos) { - if ( pos == end() ) return; // sanity check - if ( set_deleted(pos) ) { // true if object has been newly deleted - ++num_deleted; - consider_shrink = true; // will think about shrink after next insert - } - } - - void erase(const_iterator f, const_iterator l) { - for ( ; f != l; ++f) { - if ( set_deleted(f) ) // should always be true - ++num_deleted; - } - consider_shrink = true; // will think about shrink after next insert - } - - - // COMPARISON - bool operator==(const dense_hashtable& ht) const { - if (size() != ht.size()) { - return false; - } else if (this == &ht) { - return true; - } else { - // Iterate through the elements in "this" and see if the - // corresponding element is in ht - for ( const_iterator it = begin(); it != end(); ++it ) { - const_iterator it2 = ht.find(get_key(*it)); - if ((it2 == ht.end()) || (*it != *it2)) { - return false; - } - } - return true; - } - } - bool operator!=(const dense_hashtable& ht) const { - return !(*this == ht); - } - - - // I/O - // We support reading and writing hashtables to disk. Alas, since - // I don't know how to write a hasher or key_equal, you have to make - // sure everything but the table is the same. We compact before writing - // - // NOTE: These functions are currently TODO. They've not been implemented. - bool write_metadata(FILE *fp) { - squash_deleted(); // so we don't have to worry about delkey - return false; // TODO - } - - bool read_metadata(FILE *fp) { - num_deleted = 0; // since we got rid before writing - assert(use_empty); // have to set this before calling us - if (table) free(table); // we'll make our own - // TODO: read magic number - // TODO: read num_buckets - reset_thresholds(); - table = (value_type *) malloc(num_buckets * sizeof(*table)); - assert(table); - fill_range_with_empty(table, table + num_buckets); - // TODO: read num_elements - for ( size_type i = 0; i < num_elements; ++i ) { - // TODO: read bucket_num - // TODO: set with non-empty, non-deleted value - } - return false; // TODO - } - - // If your keys and values are simple enough, we can write them to - // disk for you. "simple enough" means value_type is a POD type - // that contains no pointers. However, we don't try to normalize - // endianness - bool write_nopointer_data(FILE *fp) const { - for ( const_iterator it = begin(); it != end(); ++it ) { - // TODO: skip empty/deleted values - if ( !fwrite(&*it, sizeof(*it), 1, fp) ) return false; - } - return false; - } - - // When reading, we have to override the potential const-ness of *it - bool read_nopointer_data(FILE *fp) { - for ( iterator it = begin(); it != end(); ++it ) { - // TODO: skip empty/deleted values - if ( !fread(reinterpret_cast<void*>(&(*it)), sizeof(*it), 1, fp) ) - return false; - } - return false; - } - - private: - // The actual data - hasher hash; // required by hashed_associative_container - key_equal equals; - ExtractKey get_key; - SetKey set_key; - size_type num_deleted; // how many occupied buckets are marked deleted - bool use_deleted; // false until delkey has been set - bool use_empty; // you must do this before you start - // TODO(csilvers): make a pointer, and get rid of use_deleted (benchmark!) - key_type delkey; // which key marks deleted entries - value_type emptyval; // which key marks unused entries - float enlarge_resize_percent; // how full before resize - float shrink_resize_percent; // how empty before resize - size_type shrink_threshold; // num_buckets * shrink_resize_percent - size_type enlarge_threshold; // num_buckets * enlarge_resize_percent - value_type *table; - size_type num_buckets; - size_type num_elements; - bool consider_shrink; // true if we should try to shrink before next insert - - void reset_thresholds() { - enlarge_threshold = static_cast<size_type>(num_buckets - * enlarge_resize_percent); - shrink_threshold = static_cast<size_type>(num_buckets - * shrink_resize_percent); - consider_shrink = false; // whatever caused us to reset already considered - } -}; - -// We need a global swap as well -template <class V, class K, class HF, class ExK, class SetK, class EqK, class A> -inline void swap(dense_hashtable<V,K,HF,ExK,SetK,EqK,A> &x, - dense_hashtable<V,K,HF,ExK,SetK,EqK,A> &y) { - x.swap(y); -} - -#undef JUMP_ - -template <class V, class K, class HF, class ExK, class SetK, class EqK, class A> -const typename dense_hashtable<V,K,HF,ExK,SetK,EqK,A>::size_type -dense_hashtable<V,K,HF,ExK,SetK,EqK,A>::ILLEGAL_BUCKET; - -// How full we let the table get before we resize. Knuth says .8 is -// good -- higher causes us to probe too much, though saves memory. -// However, we go with .5, getting better performance at the cost of -// more space (a trade-off densehashtable explicitly chooses to make). -// Feel free to play around with different values, though. -template <class V, class K, class HF, class ExK, class SetK, class EqK, class A> -const float dense_hashtable<V,K,HF,ExK,SetK,EqK,A>::HT_OCCUPANCY_FLT = 0.5f; - -// How empty we let the table get before we resize lower. -// It should be less than OCCUPANCY_FLT / 2 or we thrash resizing -template <class V, class K, class HF, class ExK, class SetK, class EqK, class A> -const float dense_hashtable<V,K,HF,ExK,SetK,EqK,A>::HT_EMPTY_FLT - = 0.4f * dense_hashtable<V,K,HF,ExK,SetK,EqK,A>::HT_OCCUPANCY_FLT; - -_END_GOOGLE_NAMESPACE_ - -#endif /* _DENSEHASHTABLE_H_ */ diff --git a/sources/shiboken2/ext/sparsehash/google/sparsehash/sparseconfig.h b/sources/shiboken2/ext/sparsehash/google/sparsehash/sparseconfig.h deleted file mode 100644 index 28c85d1f4..000000000 --- a/sources/shiboken2/ext/sparsehash/google/sparsehash/sparseconfig.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * NOTE: This file is for internal use only. - * Do not use these #defines in your own program! - */ - -/* Namespace for Google classes */ -#define GOOGLE_NAMESPACE ::google - -#ifdef _MSC_VER - /* the location of the header defining hash functions */ - #define HASH_FUN_H <unordered_map> - /* the namespace of the hash<> function */ - #define HASH_NAMESPACE stdext - /* The system-provided hash function including the namespace. */ - #define SPARSEHASH_HASH HASH_NAMESPACE::hash_compare -/* libc++ does not implement the tr1 namespce, instead the - * equivalient functionality is placed in namespace std, - * so use when it targeting such systems (OS X 10.7 onwards) */ -#elif defined(_LIBCPP_VERSION) - /* the location of the header defining hash functions */ - #define HASH_FUN_H <functional> - /* the namespace of the hash<> function */ - #define HASH_NAMESPACE std - /* The system-provided hash function including the namespace. */ - #define SPARSEHASH_HASH HASH_NAMESPACE::hash -#else - /* the location of the header defining hash functions */ - #define HASH_FUN_H <tr1/functional> - /* the namespace of the hash<> function */ - #define HASH_NAMESPACE std::tr1 - /* The system-provided hash function including the namespace. */ - #define SPARSEHASH_HASH HASH_NAMESPACE::hash -#endif - -/* Define to 1 if the system has the type `long long'. */ -#define HAVE_LONG_LONG 1 - -/* the namespace where STL code like vector<> is defined */ -#define STL_NAMESPACE std - -/* Stops putting the code inside the Google namespace */ -#define _END_GOOGLE_NAMESPACE_ } - -/* Puts following code inside the Google namespace */ -#define _START_GOOGLE_NAMESPACE_ namespace google { diff --git a/sources/shiboken2/ext/sparsehash/google/type_traits.h b/sources/shiboken2/ext/sparsehash/google/type_traits.h deleted file mode 100644 index d9d4faf83..000000000 --- a/sources/shiboken2/ext/sparsehash/google/type_traits.h +++ /dev/null @@ -1,250 +0,0 @@ -// Copyright (c) 2006, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// ---- -// Author: Matt Austern -// -// Define a small subset of tr1 type traits. The traits we define are: -// is_integral -// is_floating_point -// is_pointer -// is_reference -// is_pod -// has_trivial_constructor -// has_trivial_copy -// has_trivial_assign -// has_trivial_destructor -// remove_const -// remove_volatile -// remove_cv -// remove_reference -// remove_pointer -// is_convertible -// We can add more type traits as required. - -#ifndef BASE_TYPE_TRAITS_H_ -#define BASE_TYPE_TRAITS_H_ - -#include "google/sparsehash/sparseconfig.h" -#include <utility> // For pair - -_START_GOOGLE_NAMESPACE_ - -// integral_constant, defined in tr1, is a wrapper for an integer -// value. We don't really need this generality; we could get away -// with hardcoding the integer type to bool. We use the fully -// general integer_constant for compatibility with tr1. - -template<class T, T v> -struct integral_constant { - static const T value = v; - typedef T value_type; - typedef integral_constant<T, v> type; -}; - -template <class T, T v> const T integral_constant<T, v>::value; - -// Abbreviations: true_type and false_type are structs that represent -// boolean true and false values. -typedef integral_constant<bool, true> true_type; -typedef integral_constant<bool, false> false_type; - -// Types small_ and big_ are guaranteed such that sizeof(small_) < -// sizeof(big_) -typedef char small_; - -struct big_ { - char dummy[2]; -}; - -// is_integral is false except for the built-in integer types. -template <class T> struct is_integral : false_type { }; -template<> struct is_integral<bool> : true_type { }; -template<> struct is_integral<char> : true_type { }; -template<> struct is_integral<unsigned char> : true_type { }; -template<> struct is_integral<signed char> : true_type { }; -#if defined(_MSC_VER) -// wchar_t is not by default a distinct type from unsigned short in -// Microsoft C. -// See http://msdn2.microsoft.com/en-us/library/dh8che7s(VS.80).aspx -template<> struct is_integral<__wchar_t> : true_type { }; -#else -template<> struct is_integral<wchar_t> : true_type { }; -#endif -template<> struct is_integral<short> : true_type { }; -template<> struct is_integral<unsigned short> : true_type { }; -template<> struct is_integral<int> : true_type { }; -template<> struct is_integral<unsigned int> : true_type { }; -template<> struct is_integral<long> : true_type { }; -template<> struct is_integral<unsigned long> : true_type { }; -#ifdef HAVE_LONG_LONG -template<> struct is_integral<long long> : true_type { }; -template<> struct is_integral<unsigned long long> : true_type { }; -#endif - - -// is_floating_point is false except for the built-in floating-point types. -template <class T> struct is_floating_point : false_type { }; -template<> struct is_floating_point<float> : true_type { }; -template<> struct is_floating_point<double> : true_type { }; -template<> struct is_floating_point<long double> : true_type { }; - - -// is_pointer is false except for pointer types. -template <class T> struct is_pointer : false_type { }; -template <class T> struct is_pointer<T*> : true_type { }; - - -// is_reference is false except for reference types. -template<typename T> struct is_reference : false_type {}; -template<typename T> struct is_reference<T&> : true_type {}; - - -// We can't get is_pod right without compiler help, so fail conservatively. -// We will assume it's false except for arithmetic types and pointers, -// and const versions thereof. Note that std::pair is not a POD. -template <class T> struct is_pod - : integral_constant<bool, (is_integral<T>::value || - is_floating_point<T>::value || - is_pointer<T>::value)> { }; -template <class T> struct is_pod<const T> : is_pod<T> { }; - - -// We can't get has_trivial_constructor right without compiler help, so -// fail conservatively. We will assume it's false except for: (1) types -// for which is_pod is true. (2) std::pair of types with trivial -// constructors. (3) array of a type with a trivial constructor. -// (4) const versions thereof. -template <class T> struct has_trivial_constructor : is_pod<T> { }; -template <class T, class U> struct has_trivial_constructor<std::pair<T, U> > - : integral_constant<bool, - (has_trivial_constructor<T>::value && - has_trivial_constructor<U>::value)> { }; -template <class A, int N> struct has_trivial_constructor<A[N]> - : has_trivial_constructor<A> { }; -template <class T> struct has_trivial_constructor<const T> - : has_trivial_constructor<T> { }; - -// We can't get has_trivial_copy right without compiler help, so fail -// conservatively. We will assume it's false except for: (1) types -// for which is_pod is true. (2) std::pair of types with trivial copy -// constructors. (3) array of a type with a trivial copy constructor. -// (4) const versions thereof. -template <class T> struct has_trivial_copy : is_pod<T> { }; -template <class T, class U> struct has_trivial_copy<std::pair<T, U> > - : integral_constant<bool, - (has_trivial_copy<T>::value && - has_trivial_copy<U>::value)> { }; -template <class A, int N> struct has_trivial_copy<A[N]> - : has_trivial_copy<A> { }; -template <class T> struct has_trivial_copy<const T> : has_trivial_copy<T> { }; - -// We can't get has_trivial_assign right without compiler help, so fail -// conservatively. We will assume it's false except for: (1) types -// for which is_pod is true. (2) std::pair of types with trivial copy -// constructors. (3) array of a type with a trivial assign constructor. -template <class T> struct has_trivial_assign : is_pod<T> { }; -template <class T, class U> struct has_trivial_assign<std::pair<T, U> > - : integral_constant<bool, - (has_trivial_assign<T>::value && - has_trivial_assign<U>::value)> { }; -template <class A, int N> struct has_trivial_assign<A[N]> - : has_trivial_assign<A> { }; - -// We can't get has_trivial_destructor right without compiler help, so -// fail conservatively. We will assume it's false except for: (1) types -// for which is_pod is true. (2) std::pair of types with trivial -// destructors. (3) array of a type with a trivial destructor. -// (4) const versions thereof. -template <class T> struct has_trivial_destructor : is_pod<T> { }; -template <class T, class U> struct has_trivial_destructor<std::pair<T, U> > - : integral_constant<bool, - (has_trivial_destructor<T>::value && - has_trivial_destructor<U>::value)> { }; -template <class A, int N> struct has_trivial_destructor<A[N]> - : has_trivial_destructor<A> { }; -template <class T> struct has_trivial_destructor<const T> - : has_trivial_destructor<T> { }; - -// Specified by TR1 [4.7.1] -template<typename T> struct remove_const { typedef T type; }; -template<typename T> struct remove_const<T const> { typedef T type; }; -template<typename T> struct remove_volatile { typedef T type; }; -template<typename T> struct remove_volatile<T volatile> { typedef T type; }; -template<typename T> struct remove_cv { - typedef typename remove_const<typename remove_volatile<T>::type>::type type; -}; - - -// Specified by TR1 [4.7.2] -template<typename T> struct remove_reference { typedef T type; }; -template<typename T> struct remove_reference<T&> { typedef T type; }; - -// Specified by TR1 [4.7.4] Pointer modifications. -template<typename T> struct remove_pointer { typedef T type; }; -template<typename T> struct remove_pointer<T*> { typedef T type; }; -template<typename T> struct remove_pointer<T* const> { typedef T type; }; -template<typename T> struct remove_pointer<T* volatile> { typedef T type; }; -template<typename T> struct remove_pointer<T* const volatile> { - typedef T type; }; - -// Specified by TR1 [4.6] Relationships between types -#ifndef _MSC_VER -namespace internal { - -// This class is an implementation detail for is_convertible, and you -// don't need to know how it works to use is_convertible. For those -// who care: we declare two different functions, one whose argument is -// of type To and one with a variadic argument list. We give them -// return types of different size, so we can use sizeof to trick the -// compiler into telling us which function it would have chosen if we -// had called it with an argument of type From. See Alexandrescu's -// _Modern C++ Design_ for more details on this sort of trick. - -template <typename From, typename To> -struct ConvertHelper { - static small_ Test(To); - static big_ Test(...); - static From Create(); -}; -} // namespace internal - -// Inherits from true_type if From is convertible to To, false_type otherwise. -template <typename From, typename To> -struct is_convertible - : integral_constant<bool, - sizeof(internal::ConvertHelper<From, To>::Test( - internal::ConvertHelper<From, To>::Create())) - == sizeof(small_)> { -}; -#endif - -_END_GOOGLE_NAMESPACE_ - -#endif // BASE_TYPE_TRAITS_H_ diff --git a/sources/shiboken2/generator/generator.cpp b/sources/shiboken2/generator/generator.cpp index d7f98a90f..71647a1c5 100644 --- a/sources/shiboken2/generator/generator.cpp +++ b/sources/shiboken2/generator/generator.cpp @@ -36,6 +36,7 @@ #include <QtCore/QDir> #include <QtCore/QFile> #include <QtCore/QFileInfo> +#include <QtCore/QRegularExpression> #include <QDebug> #include <typedatabase.h> @@ -48,18 +49,14 @@ struct Generator::GeneratorPrivate { int numGenerated; QStringList instantiatedContainersNames; QStringList instantiatedSmartPointerNames; - QList<const AbstractMetaType *> instantiatedContainers; - QList<const AbstractMetaType *> instantiatedSmartPointers; + QVector<const AbstractMetaType *> instantiatedContainers; + QVector<const AbstractMetaType *> instantiatedSmartPointers; }; Generator::Generator() : m_d(new GeneratorPrivate) { m_d->numGenerated = 0; - m_d->instantiatedContainers = QList<const AbstractMetaType *>(); - m_d->instantiatedSmartPointers = QList<const AbstractMetaType *>(); - m_d->instantiatedContainersNames = QStringList(); - m_d->instantiatedSmartPointerNames = QStringList(); } Generator::~Generator() @@ -73,7 +70,7 @@ bool Generator::setup(const ApiExtractor& extractor, const QMap< QString, QStrin TypeEntryHash allEntries = TypeDatabase::instance()->allEntries(); TypeEntry* entryFound = 0; for (TypeEntryHash::const_iterator it = allEntries.cbegin(), end = allEntries.cend(); it != end; ++it) { - foreach (TypeEntry *entry, it.value()) { + for (TypeEntry *entry : it.value()) { if (entry->type() == TypeEntry::TypeSystemType && entry->generateCode()) { entryFound = entry; break; @@ -120,7 +117,8 @@ void Generator::addInstantiatedContainersAndSmartPointers(const AbstractMetaType { if (!type) return; - foreach (const AbstractMetaType* t, type->instantiations()) + const AbstractMetaTypeList &instantiations = type->instantiations(); + for (const AbstractMetaType* t : instantiations) addInstantiatedContainersAndSmartPointers(t, context); if (!type->typeEntry()->isContainer() && !type->typeEntry()->isSmartPointer()) return; @@ -129,7 +127,7 @@ void Generator::addInstantiatedContainersAndSmartPointers(const AbstractMetaType QString piece = isContainer ? QStringLiteral("container") : QStringLiteral("smart pointer"); QString warning = QString::fromLatin1("Skipping instantiation of %1 '%2' because it has template" - " arguments.").arg(piece).arg(type->originalTypeDescription()); + " arguments.").arg(piece, type->originalTypeDescription()); if (!context.isEmpty()) warning.append(QStringLiteral(" Calling context: %1").arg(context)); @@ -156,7 +154,8 @@ void Generator::addInstantiatedContainersAndSmartPointers(const AbstractMetaType void Generator::collectInstantiatedContainersAndSmartPointers(const AbstractMetaFunction *func) { addInstantiatedContainersAndSmartPointers(func->type(), func->signature()); - foreach (const AbstractMetaArgument* arg, func->arguments()) + const AbstractMetaArgumentList &arguments = func->arguments(); + for (const AbstractMetaArgument *arg : arguments) addInstantiatedContainersAndSmartPointers(arg->type(), func->signature()); } @@ -164,35 +163,40 @@ void Generator::collectInstantiatedContainersAndSmartPointers(const AbstractMeta { if (!metaClass->typeEntry()->generateCode()) return; - foreach (const AbstractMetaFunction* func, metaClass->functions()) + const AbstractMetaFunctionList &funcs = metaClass->functions(); + for (const AbstractMetaFunction *func : funcs) collectInstantiatedContainersAndSmartPointers(func); - foreach (const AbstractMetaField* field, metaClass->fields()) + const AbstractMetaFieldList &fields = metaClass->fields(); + for (const AbstractMetaField *field : fields) addInstantiatedContainersAndSmartPointers(field->type(), field->name()); - foreach (AbstractMetaClass* innerClass, metaClass->innerClasses()) + const AbstractMetaClassList &innerClasses = metaClass->innerClasses(); + for (AbstractMetaClass *innerClass : innerClasses) collectInstantiatedContainersAndSmartPointers(innerClass); } void Generator::collectInstantiatedContainersAndSmartPointers() { - foreach (const AbstractMetaFunction* func, globalFunctions()) + const AbstractMetaFunctionList &funcs = globalFunctions(); + for (const AbstractMetaFunction *func : funcs) collectInstantiatedContainersAndSmartPointers(func); - foreach (const AbstractMetaClass* metaClass, classes()) + const AbstractMetaClassList &classList = classes(); + for (const AbstractMetaClass *metaClass : classList) collectInstantiatedContainersAndSmartPointers(metaClass); } -QList<const AbstractMetaType*> Generator::instantiatedContainers() const +QVector<const AbstractMetaType *> Generator::instantiatedContainers() const { return m_d->instantiatedContainers; } -QList<const AbstractMetaType*> Generator::instantiatedSmartPointers() const +QVector<const AbstractMetaType*> Generator::instantiatedSmartPointers() const { return m_d->instantiatedSmartPointers; } -QMap< QString, QString > Generator::options() const +Generator::OptionDescriptions Generator::options() const { - return QMap<QString, QString>(); + return OptionDescriptions(); } AbstractMetaClassList Generator::classes() const @@ -215,12 +219,12 @@ AbstractMetaEnumList Generator::globalEnums() const return m_d->apiextractor->globalEnums(); } -QList<const PrimitiveTypeEntry*> Generator::primitiveTypes() const +PrimitiveTypeEntryList Generator::primitiveTypes() const { return m_d->apiextractor->primitiveTypes(); } -QList<const ContainerTypeEntry*> Generator::containerTypes() const +ContainerTypeEntryList Generator::containerTypes() const { return m_d->apiextractor->containerTypes(); } @@ -351,13 +355,14 @@ QString Generator::getFileNameBaseForSmartPointer(const AbstractMetaType *smartP bool Generator::generate() { - foreach (AbstractMetaClass *cls, m_d->apiextractor->classes()) { + const AbstractMetaClassList &classList = m_d->apiextractor->classes(); + for (AbstractMetaClass *cls : classList) { GeneratorContext context(cls); if (!generateFileForContext(context)) return false; } - foreach (const AbstractMetaType *type, instantiatedSmartPointers()) { + for (const AbstractMetaType *type : qAsConst(m_d->instantiatedSmartPointers)) { AbstractMetaClass *smartPointerClass = AbstractMetaClass::findClass(m_d->apiextractor->smartPointers(), type->name()); GeneratorContext context(smartPointerClass, type, true); @@ -394,7 +399,8 @@ void Generator::replaceTemplateVariables(QString &code, const AbstractMetaFuncti if (cpp_class) code.replace(QLatin1String("%TYPE"), cpp_class->name()); - foreach (AbstractMetaArgument *arg, func->arguments()) + const AbstractMetaArgumentList &argument = func->arguments(); + for (AbstractMetaArgument *arg : argument) code.replace(QLatin1Char('%') + QString::number(arg->argumentIndex() + 1), arg->name()); //template values @@ -419,10 +425,11 @@ void Generator::replaceTemplateVariables(QString &code, const AbstractMetaFuncti QTextStream& formatCode(QTextStream &s, const QString& code, Indentor &indentor) { // detect number of spaces before the first character - QStringList lst(code.split(QLatin1Char('\n'))); - QRegExp nonSpaceRegex(QLatin1String("[^\\s]")); + const QStringList lst(code.split(QLatin1Char('\n'))); + static const QRegularExpression nonSpaceRegex(QStringLiteral("[^\\s]")); + Q_ASSERT(nonSpaceRegex.isValid()); int spacesToRemove = 0; - foreach(QString line, lst) { + for (const QString &line : lst) { if (!line.trimmed().isEmpty()) { spacesToRemove = line.indexOf(nonSpaceRegex); if (spacesToRemove == -1) @@ -431,11 +438,12 @@ QTextStream& formatCode(QTextStream &s, const QString& code, Indentor &indentor) } } - static QRegExp emptyLine(QLatin1String("\\s*[\\r]?[\\n]?\\s*")); + static const QRegularExpression emptyLine(QStringLiteral("^\\s*[\\r]?[\\n]?\\s*$")); + Q_ASSERT(emptyLine.isValid()); - foreach(QString line, lst) { - if (!line.isEmpty() && !emptyLine.exactMatch(line)) { - while (line.end()->isSpace()) + for (QString line : lst) { + if (!line.isEmpty() && !emptyLine.match(line).hasMatch()) { + while (line.constEnd()->isSpace()) line.chop(1); int limit = 0; for(int i = 0; i < spacesToRemove; ++i) { @@ -507,9 +515,12 @@ bool Generator::isVoidPointer(const AbstractMetaType* type) QString Generator::getFullTypeName(const TypeEntry* type) const { - return type->isCppPrimitive() - ? type->qualifiedCppName() - : (QLatin1String("::") + type->qualifiedCppName()); + QString result = type->qualifiedCppName(); + if (type->isArray()) + type = static_cast<const ArrayTypeEntry *>(type)->nestedTypeEntry(); + if (!type->isCppPrimitive()) + result.prepend(QLatin1String("::")); + return result; } QString Generator::getFullTypeName(const AbstractMetaType* type) const @@ -639,9 +650,9 @@ QString Generator::minimalConstructor(const AbstractMetaClass* metaClass) const if (cType->hasDefaultConstructor()) return cType->defaultConstructor(); - AbstractMetaFunctionList constructors = metaClass->queryFunctions(AbstractMetaClass::Constructors); + const AbstractMetaFunctionList &constructors = metaClass->queryFunctions(AbstractMetaClass::Constructors); int maxArgs = 0; - foreach (const AbstractMetaFunction* ctor, constructors) { + for (const AbstractMetaFunction *ctor : constructors) { if (ctor->isUserAdded() || ctor->isPrivate() || ctor->functionType() != AbstractMetaFunction::ConstructorFunction) continue; @@ -656,28 +667,29 @@ QString Generator::minimalConstructor(const AbstractMetaClass* metaClass) const QString qualifiedCppName = metaClass->typeEntry()->qualifiedCppName(); QStringList templateTypes; - foreach (TypeEntry* templateType, metaClass->templateArguments()) + const QVector<TypeEntry *> &templateArguments = metaClass->templateArguments(); + for (TypeEntry *templateType : templateArguments) templateTypes << templateType->qualifiedCppName(); // Empty constructor. if (maxArgs == 0) return QLatin1String("::") + qualifiedCppName + QLatin1String("()"); - QList<const AbstractMetaFunction*> candidates; + QVector<const AbstractMetaFunction *> candidates; // Constructors with C++ primitive types, enums or pointers only. // Start with the ones with fewer arguments. for (int i = 1; i <= maxArgs; ++i) { - foreach (const AbstractMetaFunction* ctor, constructors) { + for (const AbstractMetaFunction *ctor : constructors) { if (ctor->isUserAdded() || ctor->isPrivate() || ctor->functionType() != AbstractMetaFunction::ConstructorFunction) continue; - AbstractMetaArgumentList arguments = ctor->arguments(); + const AbstractMetaArgumentList &arguments = ctor->arguments(); if (arguments.size() != i) continue; QStringList args; - foreach (const AbstractMetaArgument* arg, arguments) { + for (const AbstractMetaArgument *arg : arguments) { const TypeEntry* type = arg->type()->typeEntry(); if (type == metaClass->typeEntry()) { args.clear(); @@ -715,9 +727,10 @@ QString Generator::minimalConstructor(const AbstractMetaClass* metaClass) const // Constructors with C++ primitive types, enums, pointers, value types, // and user defined primitive types. // Builds the minimal constructor recursively. - foreach (const AbstractMetaFunction* ctor, candidates) { + for (const AbstractMetaFunction *ctor : qAsConst(candidates)) { QStringList args; - foreach (const AbstractMetaArgument* arg, ctor->arguments()) { + const AbstractMetaArgumentList &arguments = ctor->arguments(); + for (const AbstractMetaArgument *arg : arguments) { if (arg->type()->typeEntry() == metaClass->typeEntry()) { args.clear(); break; diff --git a/sources/shiboken2/generator/generator.h b/sources/shiboken2/generator/generator.h index f734ff9d7..f0b2a5e41 100644 --- a/sources/shiboken2/generator/generator.h +++ b/sources/shiboken2/generator/generator.h @@ -30,6 +30,7 @@ #define GENERATOR_H #include <abstractmetalang_typedefs.h> +#include <typedatabase_typedefs.h> #include <dependency.h> #include <QtCore/QObject> #include <QtCore/QSharedPointer> @@ -136,6 +137,9 @@ private: class Generator { public: + typedef QPair<QString, QString> OptionDescription; + typedef QVector<OptionDescription> OptionDescriptions; + /// Optiosn used around the generator code enum Option { NoOption = 0x00000000, @@ -180,7 +184,7 @@ public: bool setup(const ApiExtractor& extractor, const QMap<QString, QString> args); - virtual QMap<QString, QString> options() const; + virtual OptionDescriptions options() const; /// Returns the classes used to generate the binding code. AbstractMetaClassList classes() const; @@ -198,10 +202,10 @@ public: AbstractMetaEnumList globalEnums() const; /// Returns all primitive types found by APIExtractor - QList<const PrimitiveTypeEntry*> primitiveTypes() const; + PrimitiveTypeEntryList primitiveTypes() const; /// Returns all container types found by APIExtractor - QList<const ContainerTypeEntry*> containerTypes() const; + ContainerTypeEntryList containerTypes() const; /// Returns an AbstractMetaEnum for a given EnumTypeEntry, or NULL if not found. const AbstractMetaEnum* findAbstractMetaEnum(const EnumTypeEntry* typeEntry) const; @@ -388,8 +392,8 @@ protected: */ virtual QString subDirectoryForPackage(QString packageName = QString()) const; - QList<const AbstractMetaType*> instantiatedContainers() const; - QList<const AbstractMetaType*> instantiatedSmartPointers() const; + QVector<const AbstractMetaType*> instantiatedContainers() const; + QVector<const AbstractMetaType*> instantiatedSmartPointers() const; static QString getSimplifiedContainerTypeName(const AbstractMetaType *type); void addInstantiatedContainersAndSmartPointers(const AbstractMetaType *type, diff --git a/sources/shiboken2/generator/main.cpp b/sources/shiboken2/generator/main.cpp index 874540e54..774775fb0 100644 --- a/sources/shiboken2/generator/main.cpp +++ b/sources/shiboken2/generator/main.cpp @@ -46,6 +46,12 @@ #define PATH_SPLITTER ":" #endif +static inline QString includePathOption() { return QStringLiteral("include-paths"); } +static inline QString frameworkIncludePathOption() { return QStringLiteral("framework-include-paths"); } +static inline QString typesystemPathOption() { return QStringLiteral("typesystem-paths"); } +static inline QString helpOption() { return QStringLiteral("help"); } +static const char helpHint[] = "Note: use --help or -h for more information.\n"; + namespace { class ArgsHandler @@ -134,14 +140,17 @@ QString ArgsHandler::errorMessage() const } } -static void printOptions(QTextStream& s, const QMap<QString, QString>& options) +typedef Generator::OptionDescriptions OptionDescriptions; + +static void printOptions(QTextStream& s, const OptionDescriptions& options) { - QMap<QString, QString>::const_iterator it = options.constBegin(); s.setFieldAlignment(QTextStream::AlignLeft); - for (; it != options.constEnd(); ++it) { - s << " --"; + for (const auto &od : options) { + s << ' '; + if (!od.first.startsWith(QLatin1Char('-'))) + s << "--"; s.setFieldWidth(38); - s << it.key() << it.value(); + s << od.first << od.second; s.setFieldWidth(0); s << endl; } @@ -156,6 +165,7 @@ static bool processProjectFile(QFile& projectFile, QMap<QString, QString>& args) return false; QStringList includePaths; + QStringList frameworkIncludePaths; QStringList typesystemPaths; QStringList apiVersions; @@ -176,6 +186,8 @@ static bool processProjectFile(QFile& projectFile, QMap<QString, QString>& args) if (key == "include-path") includePaths << QDir::toNativeSeparators(value); + else if (key == "framework-include-path") + frameworkIncludePaths << QDir::toNativeSeparators(value); else if (key == "typesystem-path") typesystemPaths << QDir::toNativeSeparators(value); else if (key == "api-version") @@ -189,10 +201,14 @@ static bool processProjectFile(QFile& projectFile, QMap<QString, QString>& args) } if (!includePaths.isEmpty()) - args.insert(QLatin1String("include-paths"), includePaths.join(QLatin1String(PATH_SPLITTER))); + args.insert(includePathOption(), includePaths.join(QLatin1String(PATH_SPLITTER))); + + if (!frameworkIncludePaths.isEmpty()) + args.insert(frameworkIncludePathOption(), + frameworkIncludePaths.join(QLatin1String(PATH_SPLITTER))); if (!typesystemPaths.isEmpty()) - args.insert(QLatin1String("typesystem-paths"), typesystemPaths.join(QLatin1String(PATH_SPLITTER))); + args.insert(typesystemPathOption(), typesystemPaths.join(QLatin1String(PATH_SPLITTER))); if (!apiVersions.isEmpty()) args.insert(QLatin1String("api-version"), apiVersions.join(QLatin1Char('|'))); return true; @@ -202,11 +218,11 @@ static QMap<QString, QString> getInitializedArguments() { QMap<QString, QString> args; QStringList arguments = QCoreApplication::arguments(); - QString appName = arguments.first(); + QString appName = arguments.constFirst(); arguments.removeFirst(); QString projectFileName; - foreach (const QString& arg, arguments) { + for (const QString &arg : qAsConst(arguments)) { if (arg.startsWith(QLatin1String("--project-file"))) { int split = arg.indexOf(QLatin1Char('=')); if (split > 0) @@ -239,6 +255,55 @@ static QMap<QString, QString> getInitializedArguments() return args; } +// Concatenate values of path arguments that can occur multiple times on the +// command line. +static void addPathOptionValue(const QString &option, const QString &value, + QMap<QString, QString> &args) +{ + const QMap<QString, QString>::iterator it = args.find(option); + if (it != args.end()) + it.value().append(QLatin1String(PATH_SPLITTER) + value); + else + args.insert(option, value); +} + +static void getCommandLineArg(QString arg, int &argNum, QMap<QString, QString> &args) +{ + if (arg.startsWith(QLatin1String("--"))) { + arg.remove(0, 2); + const int split = arg.indexOf(QLatin1Char('=')); + if (split < 0) { + args.insert(arg, QString()); + return; + } + const QString option = arg.left(split); + const QString value = arg.mid(split + 1).trimmed(); + if (option == includePathOption() || option == frameworkIncludePathOption() + || option == typesystemPathOption()) { + addPathOptionValue(option, value, args); + } else { + args.insert(option, value); + } + return; + } + if (arg.startsWith(QLatin1Char('-'))) { + arg.remove(0, 1); + if (arg.startsWith(QLatin1Char('I'))) // Shorthand path arguments -I/usr/include... + addPathOptionValue(includePathOption(), arg.mid(1), args); + else if (arg.startsWith(QLatin1Char('F'))) + addPathOptionValue(frameworkIncludePathOption(), arg.mid(1), args); + else if (arg.startsWith(QLatin1Char('T'))) + addPathOptionValue(typesystemPathOption(), arg.mid(1), args); + else if (arg == QLatin1String("h")) + args.insert(helpOption(), QString()); + else + args.insert(arg, QString()); + return; + } + argNum++; + args.insert(QStringLiteral("arg-") + QString::number(argNum), arg); +} + static QMap<QString, QString> getCommandLineArgs() { QMap<QString, QString> args = getInitializedArguments(); @@ -246,21 +311,9 @@ static QMap<QString, QString> getCommandLineArgs() arguments.removeFirst(); int argNum = 0; - foreach (const QString &carg, arguments) { - const QString &arg = carg.trimmed(); - if (arg.startsWith(QLatin1String("--"))) { - int split = arg.indexOf(QLatin1Char('=')); - if (split > 0) - args[arg.mid(2).left(split-2)] = arg.mid(split + 1).trimmed(); - else - args[arg.mid(2)] = QString(); - } else if (arg.startsWith(QLatin1Char('-'))) { - args[arg.mid(1)] = QString(); - } else { - argNum++; - args[QString::fromLatin1("arg-%1").arg(argNum)] = arg; - } - } + for (const QString &carg : qAsConst(arguments)) + getCommandLineArg(carg.trimmed(), argNum, args); + return args; } @@ -286,40 +339,47 @@ void printUsage() s << "Usage:\n " << "shiboken [options] header-file typesystem-file\n\n" << "General options:\n"; - QMap<QString, QString> generalOptions; - generalOptions.insert(QLatin1String("project-file=<file>"), - QLatin1String("text file containing a description of the binding project. Replaces and overrides command line arguments")); - generalOptions.insert(QLatin1String("debug-level=[sparse|medium|full]"), - QLatin1String("Set the debug level")); - generalOptions.insert(QLatin1String("silent"), - QLatin1String("Avoid printing any message")); - generalOptions.insert(QLatin1String("help"), - QLatin1String("Display this help and exit")); - generalOptions.insert(QLatin1String("no-suppress-warnings"), - QLatin1String("Show all warnings")); - generalOptions.insert(QLatin1String("output-directory=<path>"), - QLatin1String("The directory where the generated files will be written")); - generalOptions.insert(QLatin1String("include-paths=<path>[" PATH_SPLITTER "<path>" PATH_SPLITTER "...]"), - QLatin1String("Include paths used by the C++ parser")); - generalOptions.insert(QLatin1String("typesystem-paths=<path>[" PATH_SPLITTER "<path>" PATH_SPLITTER "...]"), - QLatin1String("Paths used when searching for typesystems")); - generalOptions.insert(QLatin1String("documentation-only"), - QLatin1String("Do not generates any code, just the documentation")); - generalOptions.insert(QLatin1String("license-file=<license-file>"), - QLatin1String("File used for copyright headers of generated files")); - generalOptions.insert(QLatin1String("version"), - QLatin1String("Output version information and exit")); - generalOptions.insert(QLatin1String("generator-set=<\"generator module\">"), - QLatin1String("generator-set to be used. e.g. qtdoc")); - generalOptions.insert(QLatin1String("api-version=<\"package mask\">,<\"version\">"), - QLatin1String("Specify the supported api version used to generate the bindings")); - generalOptions.insert(QLatin1String("drop-type-entries=\"<TypeEntry0>[;TypeEntry1;...]\""), - QLatin1String("Semicolon separated list of type system entries (classes, namespaces, global functions and enums) to be dropped from generation.")); + const QString pathSyntax = QLatin1String("<path>[" PATH_SPLITTER "<path>" PATH_SPLITTER "...]"); + OptionDescriptions generalOptions = OptionDescriptions() + << qMakePair(QLatin1String("api-version=<\"package mask\">,<\"version\">"), + QLatin1String("Specify the supported api version used to generate the bindings")) + << qMakePair(QLatin1String("debug-level=[sparse|medium|full]"), + QLatin1String("Set the debug level")) + << qMakePair(QLatin1String("documentation-only"), + QLatin1String("Do not generates any code, just the documentation")) + << qMakePair(QLatin1String("drop-type-entries=\"<TypeEntry0>[;TypeEntry1;...]\""), + QLatin1String("Semicolon separated list of type system entries (classes, namespaces, global functions and enums) to be dropped from generation.")) + << qMakePair(QLatin1String("-F") + pathSyntax, QString()) + << qMakePair(QLatin1String("framework-include-paths=") + pathSyntax, + QLatin1String("Framework include paths used by the C++ parser")) + << qMakePair(QLatin1String("generator-set=<\"generator module\">"), + QLatin1String("generator-set to be used. e.g. qtdoc")) + << qMakePair(QLatin1String("-h"), QString()) + << qMakePair(helpOption(), + QLatin1String("Display this help and exit")) + << qMakePair(QLatin1String("-I") + pathSyntax, QString()) + << qMakePair(QLatin1String("include-paths=") + pathSyntax, + QLatin1String("Include paths used by the C++ parser")) + << qMakePair(QLatin1String("license-file=<license-file>"), + QLatin1String("File used for copyright headers of generated files")) + << qMakePair(QLatin1String("no-suppress-warnings"), + QLatin1String("Show all warnings")) + << qMakePair(QLatin1String("output-directory=<path>"), + QLatin1String("The directory where the generated files will be written")) + << qMakePair(QLatin1String("project-file=<file>"), + QLatin1String("text file containing a description of the binding project. Replaces and overrides command line arguments")) + << qMakePair(QLatin1String("silent"), + QLatin1String("Avoid printing any message")) + << qMakePair(QLatin1String("-T") + pathSyntax, QString()) + << qMakePair(QLatin1String("typesystem-paths=") + pathSyntax, + QLatin1String("Paths used when searching for typesystems")) + << qMakePair(QLatin1String("version"), + QLatin1String("Output version information and exit")); printOptions(s, generalOptions); const Generators generators = shibokenGenerators() + docGenerators(); - foreach (const GeneratorPtr &generator, generators) { - QMap<QString, QString> options = generator->options(); + for (const GeneratorPtr &generator : generators) { + const OptionDescriptions options = generator->options(); if (!options.isEmpty()) { s << endl << generator->name() << " options:\n"; printOptions(s, generator->options()); @@ -437,14 +497,13 @@ int main(int argc, char *argv[]) extractor.setSuppressWarnings(false); if (argsHandler.argExists(QLatin1String("api-version"))) { - QStringList versions = argsHandler.removeArg(QLatin1String("api-version")).split(QLatin1Char('|')); - foreach (const QString &fullVersion, versions) { + const QStringList &versions = argsHandler.removeArg(QLatin1String("api-version")).split(QLatin1Char('|')); + for (const QString &fullVersion : versions) { QStringList parts = fullVersion.split(QLatin1Char(',')); QString package; QString version; - // avoid constFirst to stay Qt 5.5 compatible - package = parts.count() == 1 ? QLatin1String("*") : parts.first(); - version = parts.last(); + package = parts.count() == 1 ? QLatin1String("*") : parts.constFirst(); + version = parts.constLast(); if (!extractor.setApiVersion(package, version)) { errorPrint(msgInvalidVersion(package, version)); return EXIT_FAILURE; @@ -460,11 +519,29 @@ int main(int argc, char *argv[]) extractor.addTypesystemSearchPath(path.split(QLatin1String(PATH_SPLITTER))); path = argsHandler.removeArg(QLatin1String("include-paths")); - if (!path.isEmpty()) - extractor.addIncludePath(path.split(QLatin1String(PATH_SPLITTER))); + if (!path.isEmpty()) { + const QStringList includePathListList = path.split(QLatin1String(PATH_SPLITTER)); + for (const QString &s : qAsConst(includePathListList)) { + const bool isFramework = false; + extractor.addIncludePath(HeaderPath(s, isFramework)); + } + } + + path = argsHandler.removeArg(QLatin1String("framework-include-paths")); + if (!path.isEmpty()) { + const QStringList frameworkPathList = path.split(QLatin1String(PATH_SPLITTER)); + const bool isFramework = true; + for (const QString &s : qAsConst(frameworkPathList)) { + extractor.addIncludePath(HeaderPath(s, isFramework)); + } + } QString cppFileName = argsHandler.removeArg(QLatin1String("arg-1")); QString typeSystemFileName = argsHandler.removeArg(QLatin1String("arg-2")); + QString messagePrefix = QFileInfo(typeSystemFileName).baseName(); + if (messagePrefix.startsWith(QLatin1String("typesystem_"))) + messagePrefix.remove(0, 11); + ReportHandler::setPrefix(QLatin1Char('(') + messagePrefix + QLatin1Char(')')); /* Make sure to remove the project file's arguments (if any) and * --project-file, also the arguments of each generator before @@ -478,18 +555,20 @@ int main(int argc, char *argv[]) for ( ; it != projectFileArgs.constEnd(); ++it) argsHandler.removeArg(it.key()); } - foreach (const GeneratorPtr &generator, generators) { - QMap<QString, QString> options = generator->options(); - if (!options.isEmpty()) { - QMap<QString, QString>::const_iterator it = options.constBegin(); - for ( ; it != options.constEnd(); ++it) - argsHandler.removeArg(it.key()); - } + for (const GeneratorPtr &generator : qAsConst(generators)) { + const OptionDescriptions &options = generator->options(); + for (const auto &od : options) + argsHandler.removeArg(od.first); } if (!argsHandler.noArgs()) { errorPrint(argsHandler.errorMessage()); - std::cout << "Note: use --help option for more information." << std::endl; + std::cout << helpHint; + return EXIT_FAILURE; + } + + if (typeSystemFileName.isEmpty()) { + std::cout << "You must specify a Type System file." << std::endl << helpHint; return EXIT_FAILURE; } @@ -505,7 +584,7 @@ int main(int argc, char *argv[]) qCDebug(lcShiboken) << extractor; - foreach (const GeneratorPtr &g, generators) { + for (const GeneratorPtr &g : qAsConst(generators)) { g->setOutputDirectory(outputDirectory); g->setLicenseComment(licenseComment); if (g->setup(extractor, args)) { diff --git a/sources/shiboken2/generator/qtdoc/qtdocgenerator.cpp b/sources/shiboken2/generator/qtdoc/qtdocgenerator.cpp index a7a176907..7cce97ae1 100644 --- a/sources/shiboken2/generator/qtdoc/qtdocgenerator.cpp +++ b/sources/shiboken2/generator/qtdoc/qtdocgenerator.cpp @@ -35,6 +35,7 @@ #include <typedatabase.h> #include <algorithm> #include <QtCore/QStack> +#include <QtCore/QRegularExpression> #include <QtCore/QTextStream> #include <QtCore/QXmlStreamReader> #include <QtCore/QFile> @@ -46,36 +47,36 @@ static Indentor INDENT; static bool shouldSkip(const AbstractMetaFunction* func) { - bool skipable = func->isConstructor() - || func->isModifiedRemoved() - || func->declaringClass() != func->ownerClass() - || func->isCastOperator() - || func->name() == QLatin1String("operator="); - - // Search a const clone - if (!skipable && !func->isConstant()) { - const AbstractMetaArgumentList funcArgs = func->arguments(); - foreach (AbstractMetaFunction* f, func->ownerClass()->functions()) { - if (f != func - && f->isConstant() - && f->name() == func->name() - && f->arguments().count() == funcArgs.count()) { - // Compare each argument - bool cloneFound = true; - - const AbstractMetaArgumentList fargs = f->arguments(); - for (int i = 0, max = funcArgs.count(); i < max; ++i) { - if (funcArgs.at(i)->type()->typeEntry() != fargs.at(i)->type()->typeEntry()) { - cloneFound = false; - break; - } + // Constructors go to separate section + if (DocParser::skipForQuery(func) || func->isConstructor()) + return true; + + // Search a const clone (QImage::bits() vs QImage::bits() const) + if (func->isConstant()) + return false; + + const AbstractMetaArgumentList funcArgs = func->arguments(); + const AbstractMetaFunctionList &ownerFunctions = func->ownerClass()->functions(); + for (AbstractMetaFunction *f : ownerFunctions) { + if (f != func + && f->isConstant() + && f->name() == func->name() + && f->arguments().count() == funcArgs.count()) { + // Compare each argument + bool cloneFound = true; + + const AbstractMetaArgumentList fargs = f->arguments(); + for (int i = 0, max = funcArgs.count(); i < max; ++i) { + if (funcArgs.at(i)->type()->typeEntry() != fargs.at(i)->type()->typeEntry()) { + cloneFound = false; + break; } - if (cloneFound) - return true; } + if (cloneFound) + return true; } } - return skipable; + return false; } static bool functionSort(const AbstractMetaFunction* func1, const AbstractMetaFunction* func2) @@ -83,28 +84,106 @@ static bool functionSort(const AbstractMetaFunction* func1, const AbstractMetaFu return func1->name() < func2->name(); } -static QString createRepeatedChar(int i, char c) +class Pad +{ +public: + explicit Pad(char c, int count) : m_char(c), m_count(count) {} + + void write(QTextStream &str) const + { + for (int i = 0; i < m_count; ++i) + str << m_char; + } + +private: + const char m_char; + const int m_count; +}; + +inline QTextStream &operator<<(QTextStream &str, const Pad &pad) { - QString out; - for (int j = 0; j < i; ++j) - out += QLatin1Char(c); + pad.write(str); + return str; +} - return out; +template <class String> +static int writeEscapedRstText(QTextStream &str, const String &s) +{ + int escaped = 0; + for (const QChar &c : s) { + switch (c.unicode()) { + case '*': + case '`': + case '_': + case '\\': + str << '\\'; + ++escaped; + break; + } + str << c; + } + return s.size() + escaped; } -static QString escape(QString str) +class escape { - str.replace(QLatin1Char('*'), QLatin1String("\\*")); - str.replace(QLatin1Char('_'), QLatin1String("\\_")); +public: + explicit escape(const QStringRef &s) : m_string(s) {} + + void write(QTextStream &str) const { writeEscapedRstText(str, m_string); } + +private: + const QStringRef m_string; +}; + +inline QTextStream &operator<<(QTextStream &str, const escape &e) +{ + e.write(str); return str; } -static QString escape(const QStringRef& strref) +// Return last character of a QString-buffered stream. +static QChar lastChar(const QTextStream &str) { - QString str = strref.toString(); - return escape(str); + const QString *string = str.string(); + Q_ASSERT(string); + return string->isEmpty() ? QChar() : *(string->crbegin()); } +static QTextStream &ensureEndl(QTextStream &s) +{ + if (lastChar(s) != QLatin1Char('\n')) + s << endl; + return s; +} + +static QString msgTagWarning(const QXmlStreamReader &reader, const QString &context, + const QString &tag, const QString &message) +{ + QString result; + QTextStream str(&result); + str << "While handling <"; + const QStringRef currentTag = reader.name(); + if (currentTag.isEmpty()) + str << tag; + else + str << currentTag; + str << "> in " << context << ", line "<< reader.lineNumber() + << ": " << message; + return result; +} + +static QString msgFallbackWarning(const QXmlStreamReader &reader, const QString &context, + const QString &tag, const QString &location, const QString &identifier, + const QString &fallback) +{ + QString message = QLatin1String("Falling back to \"") + + QDir::toNativeSeparators(fallback) + QLatin1String("\" for \"") + location + + QLatin1Char('"'); + if (!identifier.isEmpty()) + message += QLatin1String(" [") + identifier + QLatin1Char(']'); + return msgTagWarning(reader, context, tag, message); +} QtXmlToSphinx::QtXmlToSphinx(QtDocGenerator* generator, const QString& doc, const QString& context) : m_context(context), m_generator(generator), m_insideBold(false), m_insideItalic(false) @@ -125,7 +204,7 @@ QtXmlToSphinx::QtXmlToSphinx(QtDocGenerator* generator, const QString& doc, cons m_handlerMap.insert(QLatin1String("argument"), &QtXmlToSphinx::handleArgumentTag); m_handlerMap.insert(QLatin1String("teletype"), &QtXmlToSphinx::handleArgumentTag); m_handlerMap.insert(QLatin1String("link"), &QtXmlToSphinx::handleLinkTag); - m_handlerMap.insert(QLatin1String("inlineimage"), &QtXmlToSphinx::handleImageTag); + m_handlerMap.insert(QLatin1String("inlineimage"), &QtXmlToSphinx::handleInlineImageTag); m_handlerMap.insert(QLatin1String("image"), &QtXmlToSphinx::handleImageTag); m_handlerMap.insert(QLatin1String("list"), &QtXmlToSphinx::handleListTag); m_handlerMap.insert(QLatin1String("term"), &QtXmlToSphinx::handleTermTag); @@ -197,34 +276,34 @@ QString QtXmlToSphinx::popOutputBuffer() return strcpy; } -QString QtXmlToSphinx::expandFunction(const QString& function) +QString QtXmlToSphinx::expandFunction(const QString& function) const { - QStringList functionSpec = function.split(QLatin1Char('.')); - QString className = functionSpec.first(); - const AbstractMetaClass* metaClass = 0; - foreach (const AbstractMetaClass* cls, m_generator->classes()) { - if (cls->name() == className) { - metaClass = cls; - break; + const int firstDot = function.indexOf(QLatin1Char('.')); + const AbstractMetaClass *metaClass = nullptr; + if (firstDot != -1) { + const QStringRef className = function.leftRef(firstDot); + const AbstractMetaClassList &classes = m_generator->classes(); + for (const AbstractMetaClass *cls : classes) { + if (cls->name() == className) { + metaClass = cls; + break; + } } } - if (metaClass) { - functionSpec.removeFirst(); - return metaClass->typeEntry()->qualifiedTargetLangName() - + QLatin1Char('.') + functionSpec.join(QLatin1Char('.')); - } else { - return function; - } + return metaClass + ? metaClass->typeEntry()->qualifiedTargetLangName() + + function.right(function.size() - firstDot) + : function; } -QString QtXmlToSphinx::resolveContextForMethod(const QString& methodName) +QString QtXmlToSphinx::resolveContextForMethod(const QString& methodName) const { - // avoid constLast to stay Qt 5.5 compatible - QString currentClass = m_context.split(QLatin1Char('.')).last(); + const QStringRef currentClass = m_context.splitRef(QLatin1Char('.')).constLast(); const AbstractMetaClass* metaClass = 0; - foreach (const AbstractMetaClass* cls, m_generator->classes()) { + const AbstractMetaClassList &classes = m_generator->classes(); + for (const AbstractMetaClass *cls : classes) { if (cls->name() == currentClass) { metaClass = cls; break; @@ -233,13 +312,14 @@ QString QtXmlToSphinx::resolveContextForMethod(const QString& methodName) if (metaClass) { QList<const AbstractMetaFunction*> funcList; - foreach (const AbstractMetaFunction* func, metaClass->queryFunctionsByName(methodName)) { + const AbstractMetaFunctionList &methods = metaClass->queryFunctionsByName(methodName); + for (const AbstractMetaFunction *func : methods) { if (methodName == func->name()) funcList.append(func); } const AbstractMetaClass* implementingClass = 0; - foreach (const AbstractMetaFunction* func, funcList) { + for (const AbstractMetaFunction *func : qAsConst(funcList)) { implementingClass = func->implementingClass(); if (implementingClass->name() == currentClass) break; @@ -290,94 +370,115 @@ QString QtXmlToSphinx::transform(const QString& doc) m_lastTagName = reader.name().toString(); } } + + if (!m_inlineImages.isEmpty()) { + // Write out inline image definitions stored in handleInlineImageTag(). + m_output << endl; + for (const InlineImage &img : qAsConst(m_inlineImages)) + m_output << ".. |" << img.tag << "| image:: " << img.href << endl; + m_output << endl; + m_inlineImages.clear(); + } + m_output.flush(); QString retval = popOutputBuffer(); Q_ASSERT(m_buffers.isEmpty()); return retval; } -QString QtXmlToSphinx::readFromLocations(const QStringList& locations, const QString& path, const QString& identifier) +static QString resolveFile(const QStringList &locations, const QString &path) { - QString result; - bool ok; - foreach (QString location, locations) { + for (QString location : locations) { location.append(QLatin1Char('/')); location.append(path); - result = readFromLocation(location, identifier, &ok); - if (ok) - break; + if (QFileInfo::exists(location)) + return location; } - if (!ok) { - qCDebug(lcShiboken).noquote().nospace() << "Couldn't read code snippet file: {" - << locations.join(QLatin1Char('|')) << '}' << path; - } - return result; + return QString(); +} +QString QtXmlToSphinx::readFromLocations(const QStringList &locations, const QString &path, + const QString &identifier, QString *errorMessage) +{ + QString result; + const QString resolvedPath = resolveFile(locations, path); + if (resolvedPath.isEmpty()) { + QTextStream(errorMessage) << "Could not resolve \"" << path << "\" in \"" + << locations.join(QLatin1String("\", \"")); + return QString(); // null + } + qCDebug(lcShiboken).noquote().nospace() << "snippet file " << path + << " [" << identifier << ']' << " resolved to " << resolvedPath; + return readFromLocation(resolvedPath, identifier, errorMessage); } -QString QtXmlToSphinx::readFromLocation(const QString& location, const QString& identifier, bool* ok) +QString QtXmlToSphinx::readFromLocation(const QString &location, const QString &identifier, + QString *errorMessage) { QFile inputFile; inputFile.setFileName(location); if (!inputFile.open(QIODevice::ReadOnly)) { - if (!ok) { - qCDebug(lcShiboken).noquote().nospace() << "Couldn't read code snippet file: " - << QDir::toNativeSeparators(inputFile.fileName()); - } else { - *ok = false; - } - return QString(); + QTextStream(errorMessage) << "Could not read code snippet file: " + << QDir::toNativeSeparators(inputFile.fileName()) + << ": " << inputFile.errorString(); + return QString(); // null } - QRegExp searchString(QLatin1String("//!\\s*\\[") + identifier + QLatin1String("\\]")); - QRegExp codeSnippetCode(QLatin1String("//!\\s*\\[[\\w\\d\\s]+\\]")); - QString code; + QString code = QLatin1String(""); // non-null + if (identifier.isEmpty()) { + while (!inputFile.atEnd()) + code += QString::fromUtf8(inputFile.readLine()); + return code; + } + + const QRegularExpression searchString(QLatin1String("//!\\s*\\[") + + identifier + QLatin1String("\\]")); + Q_ASSERT(searchString.isValid()); + static const QRegularExpression codeSnippetCode(QLatin1String("//!\\s*\\[[\\w\\d\\s]+\\]")); + Q_ASSERT(codeSnippetCode.isValid()); - bool identifierIsEmpty = identifier.isEmpty(); bool getCode = false; while (!inputFile.atEnd()) { QString line = QString::fromUtf8(inputFile.readLine()); - if (identifierIsEmpty) { - code += line; - } else if (getCode && !line.contains(searchString)) { + if (getCode && !line.contains(searchString)) { line.remove(codeSnippetCode); code += line; } else if (line.contains(searchString)) { if (getCode) break; - else - getCode = true; + getCode = true; } } - if (!identifierIsEmpty && !getCode) { - qCDebug(lcShiboken).noquote().nospace() << "Code snippet file found (" - << location << "), but snippet " << identifier << " not found."; + if (!getCode) { + QTextStream(errorMessage) << "Code snippet file found (" + << QDir::toNativeSeparators(location) << "), but snippet [" + << identifier << "] not found."; + return QString(); // null } - if (ok) - *ok = true; return code; } void QtXmlToSphinx::handleHeadingTag(QXmlStreamReader& reader) { - static QString heading; + static int headingSize = 0; static char type; static char types[] = { '-', '^' }; QXmlStreamReader::TokenType token = reader.tokenType(); if (token == QXmlStreamReader::StartElement) { - uint typeIdx = reader.attributes().value(QLatin1String("level")).toString().toInt(); + uint typeIdx = reader.attributes().value(QLatin1String("level")).toUInt(); if (typeIdx >= sizeof(types)) type = types[sizeof(types)-1]; else type = types[typeIdx]; } else if (token == QXmlStreamReader::EndElement) { - m_output << createRepeatedChar(heading.length(), type) << endl << endl; + m_output << Pad(type, headingSize) << endl << endl; } else if (token == QXmlStreamReader::Characters) { - heading = escape(reader.text()).trimmed(); - m_output << endl << endl << heading << endl; + m_output << endl << endl; + headingSize = writeEscapedRstText(m_output, reader.text().trimmed()); + m_output << endl; } } @@ -395,14 +496,14 @@ void QtXmlToSphinx::handleParaTag(QXmlStreamReader& reader) m_output << INDENT << result << endl << endl; } else if (token == QXmlStreamReader::Characters) { - QString text = escape(reader.text()); - if (!m_output.string()->isEmpty()) { + const QStringRef text = reader.text(); + const QChar end = lastChar(m_output); + if (!text.isEmpty() && INDENT.indent == 0 && !end.isNull()) { QChar start = text[0]; - QChar end = m_output.string()->at(m_output.string()->length() - 1); if ((end == QLatin1Char('*') || end == QLatin1Char('`')) && start != QLatin1Char(' ') && !start.isPunct()) m_output << '\\'; } - m_output << INDENT << text; + m_output << INDENT << escape(text); } } @@ -413,7 +514,7 @@ void QtXmlToSphinx::handleItalicTag(QXmlStreamReader& reader) m_insideItalic = !m_insideItalic; m_output << '*'; } else if (token == QXmlStreamReader::Characters) { - m_output << escape(reader.text()).trimmed(); + m_output << escape(reader.text().trimmed()); } } @@ -424,7 +525,7 @@ void QtXmlToSphinx::handleBoldTag(QXmlStreamReader& reader) m_insideBold = !m_insideBold; m_output << "**"; } else if (token == QXmlStreamReader::Characters) { - m_output << escape(reader.text()).trimmed(); + m_output << escape(reader.text().trimmed()); } } @@ -434,16 +535,102 @@ void QtXmlToSphinx::handleArgumentTag(QXmlStreamReader& reader) if (token == QXmlStreamReader::StartElement || token == QXmlStreamReader::EndElement) m_output << "``"; else if (token == QXmlStreamReader::Characters) - m_output << reader.text().toString().trimmed(); + m_output << reader.text().trimmed(); } +static inline QString functionLinkType() { return QStringLiteral("function"); } +static inline QString classLinkType() { return QStringLiteral("class"); } + +static inline QString fixLinkType(const QStringRef &type) +{ + // TODO: create a flag PROPERTY-AS-FUNCTION to ask if the properties + // are recognized as such or not in the binding + if (type == QLatin1String("property")) + return functionLinkType(); + if (type == QLatin1String("typedef")) + return classLinkType(); + return type.toString(); +} + +static inline QString linkSourceAttribute(const QString &type) +{ + if (type == functionLinkType() || type == classLinkType()) + return QLatin1String("raw"); + return type == QLatin1String("enum") || type == QLatin1String("page") + ? type : QLatin1String("href"); +} + +// "See also" links may appear as nested links: +// <see-also>QAbstractXmlReceiver<link raw="isValid()" href="qxmlquery.html#isValid" type="function">isValid()</link> +// which is handled in handleLinkTag +// or direct text: +// <see-also>rootIsDecorated()</see-also> +// which is handled here. + void QtXmlToSphinx::handleSeeAlsoTag(QXmlStreamReader& reader) { - QXmlStreamReader::TokenType token = reader.tokenType(); - if (token == QXmlStreamReader::StartElement) + switch (reader.tokenType()) { + case QXmlStreamReader::StartElement: m_output << INDENT << ".. seealso:: "; - else if (token == QXmlStreamReader::EndElement) + break; + case QXmlStreamReader::Characters: { + // Direct embedded link: <see-also>rootIsDecorated()</see-also> + const QStringRef textR = reader.text().trimmed(); + if (!textR.isEmpty()) { + const QString text = textR.toString(); + if (m_seeAlsoContext.isNull()) { + const QString type = text.endsWith(QLatin1String("()")) + ? functionLinkType() : classLinkType(); + m_seeAlsoContext.reset(handleLinkStart(type, text)); + } + handleLinkText(m_seeAlsoContext.data(), text); + } + } + break; + case QXmlStreamReader::EndElement: + if (!m_seeAlsoContext.isNull()) { // direct, no nested </link> seen + handleLinkEnd(m_seeAlsoContext.data()); + m_seeAlsoContext.reset(); + } m_output << endl; + break; + default: + break; + } +} + +static inline QString fallbackPathAttribute() { return QStringLiteral("path"); } + +static inline bool snippetComparison() +{ + return ReportHandler::debugLevel() >= ReportHandler::FullDebug; +} + +template <class Indent> // const char*/class Indentor +void formatSnippet(QTextStream &str, Indent indent, const QString &snippet) +{ + const QVector<QStringRef> lines = snippet.splitRef(QLatin1Char('\n')); + for (const QStringRef &line : lines) { + if (!line.trimmed().isEmpty()) + str << indent << line; + str << endl; + } +} + +static QString msgSnippetComparison(const QString &location, const QString &identifier, + const QString &pythonCode, const QString &fallbackCode) +{ + QString result; + QTextStream str(&result); + str << "Python snippet " << location; + if (!identifier.isEmpty()) + str << " [" << identifier << ']'; + str << ":\n"; + formatSnippet(str, " ", pythonCode); + str << "Corresponding fallback snippet:\n"; + formatSnippet(str, " ", fallbackCode); + str << "-- end --\n"; + return result; } void QtXmlToSphinx::handleSnippetTag(QXmlStreamReader& reader) @@ -458,21 +645,38 @@ void QtXmlToSphinx::handleSnippetTag(QXmlStreamReader& reader) } QString location = reader.attributes().value(QLatin1String("location")).toString(); QString identifier = reader.attributes().value(QLatin1String("identifier")).toString(); - QString code = readFromLocations(m_generator->codeSnippetDirs(), location, identifier); + QString errorMessage; + const QString pythonCode = + readFromLocations(m_generator->codeSnippetDirs(), location, identifier, &errorMessage); + if (!errorMessage.isEmpty()) + qCWarning(lcShiboken, "%s", qPrintable(msgTagWarning(reader, m_context, m_lastTagName, errorMessage))); + // Fall back to C++ snippet when "path" attribute is present. + // Also read fallback snippet when comparison is desired. + QString fallbackCode; + if ((pythonCode.isNull() || snippetComparison()) + && reader.attributes().hasAttribute(fallbackPathAttribute())) { + const QString fallback = reader.attributes().value(fallbackPathAttribute()).toString(); + if (QFileInfo::exists(fallback)) { + if (pythonCode.isNull()) + qCWarning(lcShiboken, "%s", qPrintable(msgFallbackWarning(reader, m_context, m_lastTagName, location, identifier, fallback))); + fallbackCode = readFromLocation(fallback, identifier, &errorMessage); + if (!errorMessage.isEmpty()) + qCWarning(lcShiboken, "%s", qPrintable(msgTagWarning(reader, m_context, m_lastTagName, errorMessage))); + } + } + + if (!pythonCode.isEmpty() && !fallbackCode.isEmpty() && snippetComparison()) + qCDebug(lcShiboken, "%s", qPrintable(msgSnippetComparison(location, identifier, pythonCode, fallbackCode))); + if (!consecutiveSnippet) m_output << INDENT << "::\n\n"; Indentation indentation(INDENT); - if (code.isEmpty()) { + const QString code = pythonCode.isNull() ? fallbackCode : pythonCode; + if (code.isEmpty()) m_output << INDENT << "<Code snippet \"" << location << ':' << identifier << "\" not found>" << endl; - } else { - foreach (const QString &line, code.split(QLatin1Char('\n'))) { - if (!QString(line).trimmed().isEmpty()) - m_output << INDENT << line; - - m_output << endl; - } - } + else + formatSnippet(m_output, INDENT, code); m_output << endl; } } @@ -489,7 +693,7 @@ void QtXmlToSphinx::handleDotsTag(QXmlStreamReader& reader) Indentation indentation(INDENT); pushOutputBuffer(); m_output << INDENT; - int indent = reader.attributes().value(QLatin1String("indent")).toString().toInt(); + int indent = reader.attributes().value(QLatin1String("indent")).toInt(); for (int i = 0; i < indent; ++i) m_output << ' '; } else if (token == QXmlStreamReader::Characters) { @@ -509,7 +713,7 @@ void QtXmlToSphinx::handleTableTag(QXmlStreamReader& reader) // write the table on m_output m_currentTable.enableHeader(m_tableHasHeader); m_currentTable.normalize(); - m_output << m_currentTable; + m_output << ensureEndl << m_currentTable; m_currentTable.clear(); } } @@ -537,8 +741,8 @@ void QtXmlToSphinx::handleItemTag(QXmlStreamReader& reader) m_currentTable << TableRow(); TableRow& row = m_currentTable.last(); TableCell cell; - cell.colSpan = reader.attributes().value(QLatin1String("colspan")).toString().toShort(); - cell.rowSpan = reader.attributes().value(QLatin1String("rowspan")).toString().toShort(); + cell.colSpan = reader.attributes().value(QLatin1String("colspan")).toShort(); + cell.rowSpan = reader.attributes().value(QLatin1String("rowspan")).toShort(); row << cell; pushOutputBuffer(); } else if (token == QXmlStreamReader::EndElement) { @@ -577,9 +781,9 @@ void QtXmlToSphinx::handleListTag(QXmlStreamReader& reader) if (!m_currentTable.isEmpty()) { if (listType == QLatin1String("bullet")) { m_output << endl; - foreach (TableCell cell, m_currentTable.first()) { - QStringList itemLines = cell.data.split(QLatin1Char('\n')); - m_output << INDENT << "* " << itemLines.first() << endl; + for (const TableCell &cell : m_currentTable.constFirst()) { + const QVector<QStringRef> itemLines = cell.data.splitRef(QLatin1Char('\n')); + m_output << INDENT << "* " << itemLines.constFirst() << endl; for (int i = 1, max = itemLines.count(); i < max; ++i) m_output << INDENT << " " << itemLines[i] << endl; } @@ -587,7 +791,7 @@ void QtXmlToSphinx::handleListTag(QXmlStreamReader& reader) } else if (listType == QLatin1String("enum")) { m_currentTable.enableHeader(m_tableHasHeader); m_currentTable.normalize(); - m_output << m_currentTable; + m_output << ensureEndl << m_currentTable; } } m_currentTable.clear(); @@ -596,115 +800,197 @@ void QtXmlToSphinx::handleListTag(QXmlStreamReader& reader) void QtXmlToSphinx::handleLinkTag(QXmlStreamReader& reader) { - static QString l_linktag; - static QString l_linkref; - static QString l_linktext; - static QString l_linktagending; - static QString l_type; - QXmlStreamReader::TokenType token = reader.tokenType(); - if (token == QXmlStreamReader::StartElement) { - l_linktagending = QLatin1String("` "); - if (m_insideBold) { - l_linktag.prepend(QLatin1String("**")); - l_linktagending.append(QLatin1String("**")); - } else if (m_insideItalic) { - l_linktag.prepend(QLatin1Char('*')); - l_linktagending.append(QLatin1Char('*')); - } - l_type = reader.attributes().value(QLatin1String("type")).toString(); - - // TODO: create a flag PROPERTY-AS-FUNCTION to ask if the properties - // are recognized as such or not in the binding - if (l_type == QLatin1String("property")) - l_type = QLatin1String("function"); - - if (l_type == QLatin1String("typedef")) - l_type = QLatin1String("class"); - - QString linkSource; - if (l_type == QLatin1String("function") || l_type == QLatin1String("class")) { - linkSource = QLatin1String("raw"); - } else if (l_type == QLatin1String("enum")) { - linkSource = QLatin1String("enum"); - } else if (l_type == QLatin1String("page")) { - linkSource = QLatin1String("page"); + switch (reader.tokenType()) { + case QXmlStreamReader::StartElement: { + // <link> embedded in <see-also> means the characters of <see-also> are no link. + m_seeAlsoContext.reset(); + const QString type = fixLinkType(reader.attributes().value(QLatin1String("type"))); + const QString ref = reader.attributes().value(linkSourceAttribute(type)).toString(); + m_linkContext.reset(handleLinkStart(type, ref)); + } + break; + case QXmlStreamReader::Characters: + Q_ASSERT(!m_linkContext.isNull()); + handleLinkText(m_linkContext.data(), reader.text().toString()); + break; + case QXmlStreamReader::EndElement: + Q_ASSERT(!m_linkContext.isNull()); + handleLinkEnd(m_linkContext.data()); + m_linkContext.reset(); + break; + default: + break; + } +} + +QtXmlToSphinx::LinkContext *QtXmlToSphinx::handleLinkStart(const QString &type, const QString &ref) const +{ + LinkContext *result = new LinkContext(ref, type); + + result->linkTagEnding = QLatin1String("` "); + if (m_insideBold) { + result->linkTag.prepend(QLatin1String("**")); + result->linkTagEnding.append(QLatin1String("**")); + } else if (m_insideItalic) { + result->linkTag.prepend(QLatin1Char('*')); + result->linkTagEnding.append(QLatin1Char('*')); + } + + result->linkRef.replace(QLatin1String("::"), QLatin1String(".")); + result->linkRef.remove(QLatin1String("()")); + + if (result->type == functionLinkType() && !m_context.isEmpty()) { + result->linkTag = QLatin1String(" :meth:`"); + const QVector<QStringRef> rawlinklist = result->linkRef.splitRef(QLatin1Char('.')); + if (rawlinklist.size() == 1 || rawlinklist.constFirst() == m_context) { + QString context = resolveContextForMethod(rawlinklist.constLast().toString()); + if (!result->linkRef.startsWith(context)) + result->linkRef.prepend(context + QLatin1Char('.')); } else { - linkSource = QLatin1String("href"); + result->linkRef = expandFunction(result->linkRef); } - - l_linkref = reader.attributes().value(linkSource).toString(); - l_linkref.replace(QLatin1String("::"), QLatin1String(".")); - l_linkref.remove(QLatin1String("()")); - - if (l_type == QLatin1String("function") && !m_context.isEmpty()) { - l_linktag = QLatin1String(" :meth:`"); - QStringList rawlinklist = l_linkref.split(QLatin1Char('.')); - if (rawlinklist.size() == 1 || rawlinklist.first() == m_context) { - QString context = resolveContextForMethod(rawlinklist.last()); - if (!l_linkref.startsWith(context)) - l_linkref.prepend(context + QLatin1Char('.')); - } else { - l_linkref = expandFunction(l_linkref); + } else if (result->type == functionLinkType() && m_context.isEmpty()) { + result->linkTag = QLatin1String(" :func:`"); + } else if (result->type == classLinkType()) { + result->linkTag = QLatin1String(" :class:`"); + if (const TypeEntry *type = TypeDatabase::instance()->findType(result->linkRef)) { + result->linkRef = type->qualifiedTargetLangName(); + } else { // fall back to the old heuristic if the type wasn't found. + const QVector<QStringRef> rawlinklist = result->linkRef.splitRef(QLatin1Char('.')); + QStringList splittedContext = m_context.split(QLatin1Char('.')); + if (rawlinklist.size() == 1 || rawlinklist.constFirst() == splittedContext.constLast()) { + splittedContext.removeLast(); + result->linkRef.prepend(QLatin1Char('~') + splittedContext.join(QLatin1Char('.')) + + QLatin1Char('.')); } - } else if (l_type == QLatin1String("function") && m_context.isEmpty()) { - l_linktag = QLatin1String(" :func:`"); - } else if (l_type == QLatin1String("class")) { - l_linktag = QLatin1String(" :class:`"); - TypeEntry* type = TypeDatabase::instance()->findType(l_linkref); - if (type) { - l_linkref = type->qualifiedTargetLangName(); - } else { // fall back to the old heuristic if the type wasn't found. - QStringList rawlinklist = l_linkref.split(QLatin1Char('.')); - QStringList splittedContext = m_context.split(QLatin1Char('.')); - if (rawlinklist.size() == 1 || rawlinklist.first() == splittedContext.last()) { - splittedContext.removeLast(); - l_linkref.prepend(QLatin1Char('~') + splittedContext.join(QLatin1Char('.')) - + QLatin1Char('.')); - } - } - } else if (l_type == QLatin1String("enum")) { - l_linktag = QLatin1String(" :attr:`"); - } else if (l_type == QLatin1String("page") && l_linkref == m_generator->moduleName()) { - l_linktag = QLatin1String(" :mod:`"); - } else { - l_linktag = QLatin1String(" :ref:`"); } + } else if (result->type == QLatin1String("enum")) { + result->linkTag = QLatin1String(" :attr:`"); + } else if (result->type == QLatin1String("page") && result->linkRef == m_generator->moduleName()) { + result->linkTag = QLatin1String(" :mod:`"); + } else { + result->linkTag = QLatin1String(" :ref:`"); + } + return result; +} - } else if (token == QXmlStreamReader::Characters) { - QString linktext = reader.text().toString(); - linktext.replace(QLatin1String("::"), QLatin1String(".")); - // avoid constLast to stay Qt 5.5 compatible - QString item = l_linkref.split(QLatin1Char('.')).last(); - if (l_linkref == linktext - || (l_linkref + QLatin1String("()")) == linktext - || item == linktext - || (item + QLatin1String("()")) == linktext) - l_linktext.clear(); - else - l_linktext = linktext + QLatin1Char('<'); - } else if (token == QXmlStreamReader::EndElement) { - if (!l_linktext.isEmpty()) - l_linktagending.prepend(QLatin1Char('>')); - m_output << l_linktag << l_linktext << escape(l_linkref) << l_linktagending; +void QtXmlToSphinx::handleLinkText(LinkContext *linkContext, QString linktext) const +{ + linktext.replace(QLatin1String("::"), QLatin1String(".")); + const QStringRef item = linkContext->linkRef.splitRef(QLatin1Char('.')).constLast(); + if (linkContext->linkRef == linktext + || (linkContext->linkRef + QLatin1String("()")) == linktext + || item == linktext + || (item + QLatin1String("()")) == linktext) { + linkContext->linkText.clear(); + } else { + linkContext->linkText = linktext + QLatin1Char('<'); } } -void QtXmlToSphinx::handleImageTag(QXmlStreamReader& reader) +void QtXmlToSphinx::handleLinkEnd(LinkContext *linkContext) { - QXmlStreamReader::TokenType token = reader.tokenType(); - if (token == QXmlStreamReader::StartElement) { - QString href = reader.attributes().value(QLatin1String("href")).toString(); - QString packageName = m_generator->packageName(); - packageName.replace(QLatin1Char('.'), QLatin1Char('/')); - QDir dir(m_generator->outputDirectory() + QLatin1Char('/') + packageName); - QString imgPath = dir.relativeFilePath(m_generator->libSourceDir() + QLatin1String("/doc/src/")) - + QLatin1Char('/') + href; - - if (reader.name() == QLatin1String("image")) - m_output << INDENT << ".. image:: " << imgPath << endl << endl; - else - m_output << ".. image:: " << imgPath << ' '; + if (!linkContext->linkText.isEmpty()) + linkContext->linkTagEnding.prepend(QLatin1Char('>')); + m_output << linkContext->linkTag << linkContext->linkText; + writeEscapedRstText(m_output, linkContext->linkRef); + m_output << linkContext->linkTagEnding; +} + +// Copy images that are placed in a subdirectory "images" under the webxml files +// by qdoc to a matching subdirectory under the "rst/PySide2/<module>" directory +static bool copyImage(const QString &href, const QString &docDataDir, + const QString &context, const QString &outputDir, + QString *errorMessage) +{ + const QChar slash = QLatin1Char('/'); + const int lastSlash = href.lastIndexOf(slash); + const QString imagePath = lastSlash != -1 ? href.left(lastSlash) : QString(); + const QString imageFileName = lastSlash != -1 ? href.right(href.size() - lastSlash - 1) : href; + QFileInfo imageSource(docDataDir + slash + href); + if (!imageSource.exists()) { + QTextStream(errorMessage) << "Image " << href << " does not exist in " + << QDir::toNativeSeparators(docDataDir); + return false; + } + // Determine directory from context, "Pyside2.QtGui.QPainter" ->"Pyside2/QtGui". + // FIXME: Not perfect yet, should have knowledge about namespaces (DataVis3D) or + // nested classes "Pyside2.QtGui.QTouchEvent.QTouchPoint". + QString relativeTargetDir = context; + const int lastDot = relativeTargetDir.lastIndexOf(QLatin1Char('.')); + if (lastDot != -1) + relativeTargetDir.truncate(lastDot); + relativeTargetDir.replace(QLatin1Char('.'), slash); + if (!imagePath.isEmpty()) + relativeTargetDir += slash + imagePath; + + const QString targetDir = outputDir + slash + relativeTargetDir; + const QString targetFileName = targetDir + slash + imageFileName; + if (QFileInfo::exists(targetFileName)) + return true; + if (!QFileInfo::exists(targetDir)) { + const QDir outDir(outputDir); + if (!outDir.mkpath(relativeTargetDir)) { + QTextStream(errorMessage) << "Cannot create " << QDir::toNativeSeparators(relativeTargetDir) + << " under " << QDir::toNativeSeparators(outputDir); + return false; + } + } + + QFile source(imageSource.absoluteFilePath()); + if (!source.copy(targetFileName)) { + QTextStream(errorMessage) << "Cannot copy " << QDir::toNativeSeparators(source.fileName()) + << " to " << QDir::toNativeSeparators(targetFileName) << ": " + << source.errorString(); + return false; } + qCDebug(lcShiboken()).noquote().nospace() << __FUNCTION__ << " href=\"" + << href << "\", context=\"" << context << "\", docDataDir=\"" + << docDataDir << "\", outputDir=\"" << outputDir << "\", copied \"" + << source.fileName() << "\"->\"" << targetFileName << '"'; + return true; +} + +bool QtXmlToSphinx::copyImage(const QString &href) const +{ + QString errorMessage; + const bool result = + ::copyImage(href, m_generator->docDataDir(), m_context, + m_generator->outputDirectory(), &errorMessage); + if (!result) + qCWarning(lcShiboken, "%s", qPrintable(errorMessage)); + return result; +} + +void QtXmlToSphinx::handleImageTag(QXmlStreamReader& reader) +{ + if (reader.tokenType() != QXmlStreamReader::StartElement) + return; + const QString href = reader.attributes().value(QLatin1String("href")).toString(); + if (copyImage(href)) + m_output << INDENT << ".. image:: " << href << endl << endl; +} + +void QtXmlToSphinx::handleInlineImageTag(QXmlStreamReader& reader) +{ + if (reader.tokenType() != QXmlStreamReader::StartElement) + return; + const QString href = reader.attributes().value(QLatin1String("href")).toString(); + if (!copyImage(href)) + return; + // Handle inline images by substitution references. Insert a unique tag + // enclosed by '|' and define it further down. Determine tag from the base + //file name with number. + QString tag = href; + int pos = tag.lastIndexOf(QLatin1Char('/')); + if (pos != -1) + tag.remove(0, pos + 1); + pos = tag.indexOf(QLatin1Char('.')); + if (pos != -1) + tag.truncate(pos); + tag += QString::number(m_inlineImages.size() + 1); + m_inlineImages.append(InlineImage{tag, href}); + m_output << '|' << tag << '|' << ' '; } void QtXmlToSphinx::handleRawTag(QXmlStreamReader& reader) @@ -714,8 +1000,8 @@ void QtXmlToSphinx::handleRawTag(QXmlStreamReader& reader) QString format = reader.attributes().value(QLatin1String("format")).toString(); m_output << INDENT << ".. raw:: " << format.toLower() << endl << endl; } else if (token == QXmlStreamReader::Characters) { - QStringList lst(reader.text().toString().split(QLatin1Char('\n'))); - foreach(QString row, lst) + const QVector<QStringRef> lst(reader.text().split(QLatin1Char('\n'))); + for (const QStringRef &row : lst) m_output << INDENT << INDENT << row << endl; } else if (token == QXmlStreamReader::EndElement) { m_output << endl << endl; @@ -726,12 +1012,11 @@ void QtXmlToSphinx::handleCodeTag(QXmlStreamReader& reader) { QXmlStreamReader::TokenType token = reader.tokenType(); if (token == QXmlStreamReader::StartElement) { - QString format = reader.attributes().value(QLatin1String("format")).toString(); m_output << INDENT << "::" << endl << endl; INDENT.indent++; } else if (token == QXmlStreamReader::Characters) { - QStringList lst(reader.text().toString().split(QLatin1Char('\n'))); - foreach(QString row, lst) + const QVector<QStringRef> lst(reader.text().split(QLatin1Char('\n'))); + for (const QStringRef &row : lst) m_output << INDENT << INDENT << row << endl; } else if (token == QXmlStreamReader::EndElement) { m_output << endl << endl; @@ -793,22 +1078,17 @@ void QtXmlToSphinx::handleQuoteFileTag(QXmlStreamReader& reader) QXmlStreamReader::TokenType token = reader.tokenType(); if (token == QXmlStreamReader::Characters) { QString location = reader.text().toString(); - QString identifier; location.prepend(m_generator->libSourceDir() + QLatin1Char('/')); - QString code = readFromLocation(location, identifier); - + QString errorMessage; + QString code = readFromLocation(location, QString(), &errorMessage); + if (!errorMessage.isEmpty()) + qCWarning(lcShiboken(), "%s", qPrintable(msgTagWarning(reader, m_context, m_lastTagName, errorMessage))); m_output << INDENT << "::\n\n"; Indentation indentation(INDENT); - if (code.isEmpty()) { + if (code.isEmpty()) m_output << INDENT << "<Code snippet \"" << location << "\" not found>" << endl; - } else { - foreach (QString line, code.split(QLatin1Char('\n'))) { - if (!QString(line).trimmed().isEmpty()) - m_output << INDENT << line; - - m_output << endl; - } - } + else + formatCode(m_output, code, INDENT); m_output << endl; } } @@ -877,13 +1157,14 @@ QTextStream& operator<<(QTextStream& s, const QtXmlToSphinx::Table &table) } // calc width and height of each column and row - QVector<int> colWidths(table.first().count()); + const int headerColumnCount = table.constFirst().count(); + QVector<int> colWidths(headerColumnCount); QVector<int> rowHeights(table.count()); for (int i = 0, maxI = table.count(); i < maxI; ++i) { const QtXmlToSphinx::TableRow& row = table[i]; for (int j = 0, maxJ = std::min(row.count(), colWidths.size()); j < maxJ; ++j) { - QStringList rowLines = row[j].data.split(QLatin1Char('\n')); // cache this would be a good idea - foreach (QString str, rowLines) + const QVector<QStringRef> rowLines = row[j].data.splitRef(QLatin1Char('\n')); // cache this would be a good idea + for (const QStringRef &str : rowLines) colWidths[j] = std::max(colWidths[j], str.count()); rowHeights[i] = std::max(rowHeights[i], row[j].data.count(QLatin1Char('\n')) + 1); } @@ -895,7 +1176,7 @@ QTextStream& operator<<(QTextStream& s, const QtXmlToSphinx::Table &table) // create a horizontal line to be used later. QString horizontalLine = QLatin1String("+"); for (int i = 0, max = colWidths.count(); i < max; ++i) { - horizontalLine += createRepeatedChar(colWidths[i], '-'); + horizontalLine += QString(colWidths.at(i), QLatin1Char('-')); horizontalLine += QLatin1Char('+'); } @@ -905,7 +1186,7 @@ QTextStream& operator<<(QTextStream& s, const QtXmlToSphinx::Table &table) // print line s << INDENT << '+'; - for (int col = 0, max = colWidths.count(); col < max; ++col) { + for (int col = 0; col < headerColumnCount; ++col) { char c; if (col >= row.length() || row[col].rowSpan == -1) c = ' '; @@ -913,16 +1194,17 @@ QTextStream& operator<<(QTextStream& s, const QtXmlToSphinx::Table &table) c = '='; else c = '-'; - s << createRepeatedChar(colWidths[col], c) << '+'; + s << Pad(c, colWidths.at(col)) << '+'; } s << endl; // Print the table cells for (int rowLine = 0; rowLine < rowHeights[i]; ++rowLine) { // for each line in a row - for (int j = 0, maxJ = std::min(row.count(), colWidths.size()); j < maxJ; ++j) { // for each column + int j = 0; + for (int maxJ = std::min(row.count(), headerColumnCount); j < maxJ; ++j) { // for each column const QtXmlToSphinx::TableCell& cell = row[j]; - QStringList rowLines = cell.data.split(QLatin1Char('\n')); // FIXME: Cache this!!! + const QVector<QStringRef> rowLines = cell.data.splitRef(QLatin1Char('\n')); // FIXME: Cache this!!! if (!j) // First column, so we need print the identation s << INDENT; @@ -930,10 +1212,13 @@ QTextStream& operator<<(QTextStream& s, const QtXmlToSphinx::Table &table) s << '|'; else s << ' '; - s << qSetFieldWidth(colWidths[j]) << left; - s << (rowLine < rowLines.count() ? rowLines[rowLine] : QString()); - s << qSetFieldWidth(0); + if (rowLine < rowLines.count()) + s << qSetFieldWidth(colWidths[j]) << left << rowLines.at(rowLine) << qSetFieldWidth(0); + else + s << Pad(' ', colWidths.at(j)); } + for ( ; j < headerColumnCount; ++j) // pad + s << '|' << Pad(' ', colWidths.at(j)); s << '|' << endl; } } @@ -975,8 +1260,8 @@ static QString getFuncName(const AbstractMetaFunction* cppFunc) { hashInitialized = true; } - QHash<QString, QString>::const_iterator it = operatorsHash.find(cppFunc->name()); - QString result = it != operatorsHash.end() ? it.value() : cppFunc->name(); + QHash<QString, QString>::const_iterator it = operatorsHash.constFind(cppFunc->name()); + QString result = it != operatorsHash.cend() ? it.value() : cppFunc->name(); result.replace(QLatin1String("::"), QLatin1String(".")); return result; } @@ -1007,7 +1292,8 @@ QString QtDocGenerator::fileNameForContext(GeneratorContext &context) const } } -void QtDocGenerator::writeFormatedText(QTextStream& s, const Documentation& doc, const AbstractMetaClass* metaClass) +void QtDocGenerator::writeFormattedText(QTextStream &s, const Documentation &doc, + const AbstractMetaClass *metaClass) { QString metaClassName; @@ -1018,17 +1304,24 @@ void QtDocGenerator::writeFormatedText(QTextStream& s, const Documentation& doc, QtXmlToSphinx x(this, doc.value(), metaClassName); s << x; } else { - QStringList lines = doc.value().split(QLatin1Char('\n')); - QRegExp regex(QLatin1String("\\S")); // non-space character + const QString &value = doc.value(); + const QVector<QStringRef> lines = value.splitRef(QLatin1Char('\n')); int typesystemIndentation = std::numeric_limits<int>().max(); - // check how many spaces must be removed from the begining of each line - foreach (QString line, lines) { - int idx = line.indexOf(regex); - if (idx >= 0) - typesystemIndentation = qMin(typesystemIndentation, idx); + // check how many spaces must be removed from the beginning of each line + for (const QStringRef &line : lines) { + const auto it = std::find_if(line.cbegin(), line.cend(), + [] (QChar c) { return !c.isSpace(); }); + if (it != line.cend()) + typesystemIndentation = qMin(typesystemIndentation, int(it - line.cbegin())); + } + if (typesystemIndentation == std::numeric_limits<int>().max()) + typesystemIndentation = 0; + for (const QStringRef &line : lines) { + s << INDENT + << (typesystemIndentation > 0 && typesystemIndentation < line.size() + ? line.right(line.size() - typesystemIndentation) : line) + << endl; } - foreach (QString line, lines) - s << INDENT << line.remove(0, typesystemIndentation) << endl; } s << endl; @@ -1037,7 +1330,7 @@ void QtDocGenerator::writeFormatedText(QTextStream& s, const Documentation& doc, static void writeInheritedByList(QTextStream& s, const AbstractMetaClass* metaClass, const AbstractMetaClassList& allClasses) { AbstractMetaClassList res; - foreach (AbstractMetaClass* c, allClasses) { + for (AbstractMetaClass *c : allClasses) { if (c != metaClass && c->inheritsFrom(metaClass)) res << c; } @@ -1047,7 +1340,7 @@ static void writeInheritedByList(QTextStream& s, const AbstractMetaClass* metaCl s << "**Inherited by:** "; QStringList classes; - foreach (AbstractMetaClass* c, res) + for (AbstractMetaClass *c : qAsConst(res)) classes << QLatin1String(":ref:`") + getClassTargetFullName(c, false) + QLatin1Char('`'); s << classes.join(QLatin1String(", ")) << endl << endl; } @@ -1067,9 +1360,9 @@ void QtDocGenerator::generateClass(QTextStream &s, GeneratorContext &classContex s << ".. _" << className << ":" << endl << endl; s << className << endl; - s << createRepeatedChar(className.count(), '*') << endl << endl; + s << Pad('*', className.count()) << endl << endl; - s << ".. inheritance-diagram:: " << className << endl + s << ".. inheritance-diagram:: " << getClassTargetFullName(metaClass, true) << endl << " :parts: 2" << endl << endl; // TODO: This would be a parameter in the future... @@ -1084,12 +1377,13 @@ void QtDocGenerator::generateClass(QTextStream &s, GeneratorContext &classContex AbstractMetaFunctionList functionList = metaClass->functions(); qSort(functionList.begin(), functionList.end(), functionSort); - s << "Detailed Description\n" - "--------------------\n\n"; + s << endl + << "Detailed Description\n" + "--------------------\n\n"; writeInjectDocumentation(s, TypeSystem::DocModificationPrepend, metaClass, 0); if (!writeInjectDocumentation(s, TypeSystem::DocModificationReplace, metaClass, 0)) - writeFormatedText(s, metaClass->documentation(), metaClass); + writeFormattedText(s, metaClass->documentation(), metaClass); if (!metaClass->isNamespace()) writeConstructors(s, metaClass); @@ -1098,7 +1392,7 @@ void QtDocGenerator::generateClass(QTextStream &s, GeneratorContext &classContex writeFields(s, metaClass); - foreach (AbstractMetaFunction* func, functionList) { + for (AbstractMetaFunction *func : qAsConst(functionList)) { if (shouldSkip(func)) continue; @@ -1121,7 +1415,8 @@ void QtDocGenerator::writeFunctionList(QTextStream& s, const AbstractMetaClass* QStringList slotList; QStringList staticFunctionList; - foreach (AbstractMetaFunction* func, cppClass->functions()) { + const AbstractMetaFunctionList &classFunctions = cppClass->functions(); + for (AbstractMetaFunction *func : classFunctions) { if (shouldSkip(func)) continue; @@ -1157,9 +1452,9 @@ void QtDocGenerator::writeFunctionList(QTextStream& s, const AbstractMetaClass* if ((functionList.size() > 0) || (staticFunctionList.size() > 0)) { QtXmlToSphinx::Table functionTable; - QtXmlToSphinx::TableRow row; - s << "Synopsis" << endl + s << endl + << "Synopsis" << endl << "--------" << endl << endl; writeFunctionBlock(s, QLatin1String("Functions"), functionList); @@ -1180,8 +1475,8 @@ void QtDocGenerator::writeFunctionBlock(QTextStream& s, const QString& title, QS s << ".. container:: function_list" << endl << endl; Indentation indentation(INDENT); - foreach (QString func, functions) - s << '*' << INDENT << func << endl; + for (const QString &func : qAsConst(functions)) + s << INDENT << '*' << ' ' << func << endl; s << endl << endl; } @@ -1191,9 +1486,10 @@ void QtDocGenerator::writeEnums(QTextStream& s, const AbstractMetaClass* cppClas { static const QString section_title = QLatin1String(".. attribute:: "); - foreach (AbstractMetaEnum* en, cppClass->enums()) { + const AbstractMetaEnumList &enums = cppClass->enums(); + for (AbstractMetaEnum *en : enums) { s << section_title << getClassTargetFullName(cppClass) << '.' << en->name() << endl << endl; - writeFormatedText(s, en->documentation(), cppClass); + writeFormattedText(s, en->documentation(), cppClass); if (en->typeEntry() && (en->typeEntry()->version() != 0)) s << ".. note:: This enum was introduced or modified in Qt " << en->typeEntry()->version() << endl; @@ -1205,10 +1501,11 @@ void QtDocGenerator::writeFields(QTextStream& s, const AbstractMetaClass* cppCla { static const QString section_title = QLatin1String(".. attribute:: "); - foreach (AbstractMetaField* field, cppClass->fields()) { + const AbstractMetaFieldList &fields = cppClass->fields(); + for (AbstractMetaField *field : fields) { s << section_title << getClassTargetFullName(cppClass) << "." << field->name() << endl << endl; //TODO: request for member ‘documentation’ is ambiguous - writeFormatedText(s, field->AbstractMetaAttributes::documentation(), cppClass); + writeFormattedText(s, field->AbstractMetaAttributes::documentation(), cppClass); } } @@ -1218,14 +1515,15 @@ void QtDocGenerator::writeConstructors(QTextStream& s, const AbstractMetaClass* static const QString sectionTitleSpace = QString(sectionTitle.size(), QLatin1Char(' ')); AbstractMetaFunctionList lst = cppClass->queryFunctions(AbstractMetaClass::Constructors | AbstractMetaClass::Visible); + for (int i = lst.size() - 1; i >= 0; --i) { + if (lst.at(i)->isModifiedRemoved() || lst.at(i)->functionType() == AbstractMetaFunction::MoveConstructorFunction) + lst.removeAt(i); + } bool first = true; QHash<QString, AbstractMetaArgument*> arg_map; - foreach(AbstractMetaFunction* func, lst) { - if (func->isModifiedRemoved()) - continue; - + for (AbstractMetaFunction *func : qAsConst(lst)) { if (first) { first = false; s << sectionTitle; @@ -1233,8 +1531,8 @@ void QtDocGenerator::writeConstructors(QTextStream& s, const AbstractMetaClass* s << sectionTitleSpace; } writeFunction(s, false, cppClass, func); - foreach(AbstractMetaArgument* arg, func->arguments()) - { + const AbstractMetaArgumentList &arguments = func->arguments(); + for (AbstractMetaArgument *arg : arguments) { if (!arg_map.contains(arg->name())) { arg_map.insert(arg->name(), arg); } @@ -1243,16 +1541,15 @@ void QtDocGenerator::writeConstructors(QTextStream& s, const AbstractMetaClass* s << endl; - foreach (AbstractMetaArgument* arg, arg_map.values()) { + for (QHash<QString, AbstractMetaArgument*>::const_iterator it = arg_map.cbegin(), end = arg_map.cend(); it != end; ++it) { Indentation indentation(INDENT); - writeParamerteType(s, cppClass, arg); + writeParameterType(s, cppClass, it.value()); } s << endl; - foreach (AbstractMetaFunction* func, lst) { - writeFormatedText(s, func->documentation(), cppClass); - } + for (AbstractMetaFunction *func : qAsConst(lst)) + writeFormattedText(s, func->documentation(), cppClass); } QString QtDocGenerator::parseArgDocStyle(const AbstractMetaClass* cppClass, const AbstractMetaFunction* func) @@ -1260,7 +1557,8 @@ QString QtDocGenerator::parseArgDocStyle(const AbstractMetaClass* cppClass, cons QString ret; int optArgs = 0; - foreach (AbstractMetaArgument* arg, func->arguments()) { + const AbstractMetaArgumentList &arguments = func->arguments(); + for (AbstractMetaArgument *arg : arguments) { if (func->argumentRemoved(arg->argumentIndex() + 1)) continue; @@ -1311,7 +1609,7 @@ void QtDocGenerator::writeDocSnips(QTextStream &s, invalidStrings << QLatin1String("*") << QLatin1String("//") << QLatin1String("/*") << QLatin1String("*/"); - foreach (CodeSnip snip, codeSnips) { + for (const CodeSnip &snip : codeSnips) { if ((snip.position != position) || !(snip.language & language)) continue; @@ -1325,14 +1623,13 @@ void QtDocGenerator::writeDocSnips(QTextStream &s, break; QString codeBlock = code.mid(startBlock, endBlock - startBlock); - QStringList rows = codeBlock.split(QLatin1Char('\n')); + const QStringList rows = codeBlock.split(QLatin1Char('\n')); int currenRow = 0; int offset = 0; - foreach(QString row, rows) { - foreach(QString invalidString, invalidStrings) { - row = row.remove(invalidString); - } + for (QString row : rows) { + for (const QString &invalidString : qAsConst(invalidStrings)) + row.remove(invalidString); if (row.trimmed().size() == 0) { if (currenRow == 0) @@ -1370,7 +1667,8 @@ bool QtDocGenerator::writeInjectDocumentation(QTextStream& s, Indentation indentation(INDENT); bool didSomething = false; - foreach (DocModification mod, cppClass->typeEntry()->docModifications()) { + const DocModificationList &mods = cppClass->typeEntry()->docModifications(); + for (const DocModification &mod : mods) { if (mod.mode() == mode) { bool modOk = func ? mod.signature() == func->minimalSignature() : mod.signature().isEmpty(); @@ -1378,15 +1676,15 @@ bool QtDocGenerator::writeInjectDocumentation(QTextStream& s, Documentation doc; Documentation::Format fmt; - if (mod.format == TypeSystem::NativeCode) + if (mod.format() == TypeSystem::NativeCode) fmt = Documentation::Native; - else if (mod.format == TypeSystem::TargetLangCode) + else if (mod.format() == TypeSystem::TargetLangCode) fmt = Documentation::Target; else continue; doc.setValue(mod.code() , fmt); - writeFormatedText(s, doc, cppClass); + writeFormattedText(s, doc, cppClass); didSomething = true; } } @@ -1462,31 +1760,34 @@ QString QtDocGenerator::translateToPythonType(const AbstractMetaType* type, cons return strType; } -void QtDocGenerator::writeParamerteType(QTextStream& s, const AbstractMetaClass* cppClass, const AbstractMetaArgument* arg) +void QtDocGenerator::writeParameterType(QTextStream& s, const AbstractMetaClass* cppClass, const AbstractMetaArgument* arg) { s << INDENT << ":param " << arg->name() << ": " << translateToPythonType(arg->type(), cppClass) << endl; } -void QtDocGenerator::writeFunctionParametersType(QTextStream& s, const AbstractMetaClass* cppClass, const AbstractMetaFunction* func) +void QtDocGenerator::writeFunctionParametersType(QTextStream &s, const AbstractMetaClass *cppClass, + const AbstractMetaFunction *func) { Indentation indentation(INDENT); s << endl; - foreach (AbstractMetaArgument* arg, func->arguments()) { + const AbstractMetaArgumentList &funcArgs = func->arguments(); + for (AbstractMetaArgument *arg : funcArgs) { if (func->argumentRemoved(arg->argumentIndex() + 1)) continue; - writeParamerteType(s, cppClass, arg); + writeParameterType(s, cppClass, arg); } if (!func->isConstructor() && func->type()) { QString retType; // check if the return type was modified - foreach (FunctionModification mod, func->modifications()) { - foreach (ArgumentModification argMod, mod.argument_mods) { + const FunctionModificationList &mods = func->modifications(); + for (const FunctionModification &mod : mods) { + for (const ArgumentModification &argMod : mod.argument_mods) { if (argMod.index == 0) { retType = argMod.modified_type; break; @@ -1515,7 +1816,7 @@ void QtDocGenerator::writeFunction(QTextStream& s, bool writeDoc, const Abstract s << endl; writeInjectDocumentation(s, TypeSystem::DocModificationPrepend, cppClass, func); if (!writeInjectDocumentation(s, TypeSystem::DocModificationReplace, cppClass, func)) - writeFormatedText(s, func->documentation(), cppClass); + writeFormattedText(s, func->documentation(), cppClass); writeInjectDocumentation(s, TypeSystem::DocModificationAppend, cppClass, func); } } @@ -1526,7 +1827,7 @@ static void writeFancyToc(QTextStream& s, const QStringList& items, int cols = 4 TocMap tocMap; QChar Q = QLatin1Char('Q'); QChar idx; - foreach (QString item, items) { + for (QString item : items) { if (item.isEmpty()) continue; if (item.startsWith(Q) && item.length() > 1) @@ -1551,7 +1852,7 @@ static void writeFancyToc(QTextStream& s, const QStringList& items, int cols = 4 ss << "**" << it.key() << "**" << endl << endl; i += 2; // a letter title is equivalent to two entries in space - foreach (QString item, it.value()) { + for (const QString &item : qAsConst(it.value())) { ss << "* :doc:`" << item << "`" << endl; ++i; @@ -1595,7 +1896,7 @@ bool QtDocGenerator::finishGeneration() QString title = it.key(); s << title << endl; - s << createRepeatedChar(title.length(), '*') << endl << endl; + s << Pad('*', title.length()) << endl << endl; /* Avoid showing "Detailed Description for *every* class in toc tree */ Indentation indentation(INDENT); @@ -1628,7 +1929,7 @@ bool QtDocGenerator::finishGeneration() s << INDENT << ".. toctree::" << endl; Indentation deeperIndentation(INDENT); s << INDENT << ":maxdepth: 1" << endl << endl; - foreach (QString className, it.value()) + for (const QString &className : qAsConst(it.value())) s << INDENT << className << endl; s << endl << endl; } @@ -1686,19 +1987,18 @@ bool QtDocGenerator::doSetup(const QMap<QString, QString>& args) } -QMap<QString, QString> QtDocGenerator::options() const +Generator::OptionDescriptions QtDocGenerator::options() const { - QMap<QString, QString> options; - options.insert(QLatin1String("doc-parser"), - QLatin1String("The documentation parser used to interpret the documentation input files (qdoc3|doxygen)")); - options.insert(QLatin1String("library-source-dir"), - QLatin1String("Directory where library source code is located")); - options.insert(QLatin1String("documentation-data-dir"), - QLatin1String("Directory with XML files generated by documentation tool (qdoc3 or Doxygen)")); - options.insert(QLatin1String("documentation-code-snippets-dir"), - QLatin1String("Directory used to search code snippets used by the documentation")); - options.insert(QLatin1String("documentation-extra-sections-dir"), - QLatin1String("Directory used to search for extra documentation sections")); - return options; + return OptionDescriptions() + << qMakePair(QLatin1String("doc-parser"), + QLatin1String("The documentation parser used to interpret the documentation input files (qdoc3|doxygen)")) + << qMakePair(QLatin1String("documentation-code-snippets-dir"), + QLatin1String("Directory used to search code snippets used by the documentation")) + << qMakePair(QLatin1String("documentation-data-dir"), + QLatin1String("Directory with XML files generated by documentation tool (qdoc3 or Doxygen)")) + << qMakePair(QLatin1String("documentation-extra-sections-dir"), + QLatin1String("Directory used to search for extra documentation sections")) + << qMakePair(QLatin1String("library-source-dir"), + QLatin1String("Directory where library source code is located")); } diff --git a/sources/shiboken2/generator/qtdoc/qtdocgenerator.h b/sources/shiboken2/generator/qtdoc/qtdocgenerator.h index fa8524b21..af26b7fab 100644 --- a/sources/shiboken2/generator/qtdoc/qtdocgenerator.h +++ b/sources/shiboken2/generator/qtdoc/qtdocgenerator.h @@ -30,6 +30,7 @@ #include <QtCore/QStack> #include <QtCore/QHash> +#include <QtCore/QScopedPointer> #include <QtCore/QTextStream> #include <QXmlStreamReader> #include "generator.h" @@ -48,6 +49,12 @@ class QtDocGenerator; class QtXmlToSphinx { public: + struct InlineImage + { + QString tag; + QString href; + }; + struct TableCell { short rowSpan; @@ -101,8 +108,19 @@ public: } private: - QString resolveContextForMethod(const QString& methodName); - QString expandFunction(const QString& function); + struct LinkContext + { + LinkContext(const QString &ref, const QString &lType) : linkRef(ref), type(lType) {} + + QString linkTag; + QString linkRef; + QString linkText; + QString linkTagEnding; + QString type; + }; + + QString resolveContextForMethod(const QString& methodName) const; + QString expandFunction(const QString& function) const; QString transform(const QString& doc); void handleHeadingTag(QXmlStreamReader& reader); @@ -115,6 +133,7 @@ private: void handleDotsTag(QXmlStreamReader& reader); void handleLinkTag(QXmlStreamReader& reader); void handleImageTag(QXmlStreamReader& reader); + void handleInlineImageTag(QXmlStreamReader& reader); void handleListTag(QXmlStreamReader& reader); void handleTermTag(QXmlStreamReader& reader); void handleSuperScriptTag(QXmlStreamReader& reader); @@ -133,6 +152,10 @@ private: void handleUselessTag(QXmlStreamReader& reader); void handleAnchorTag(QXmlStreamReader& reader); + LinkContext *handleLinkStart(const QString &type, const QString &ref) const; + void handleLinkText(LinkContext *linkContext, QString linktext) const; + void handleLinkEnd(LinkContext *linkContext); + typedef void (QtXmlToSphinx::*TagHandler)(QXmlStreamReader&); QHash<QString, TagHandler> m_handlerMap; QStack<TagHandler> m_handlers; @@ -143,6 +166,8 @@ private: Table m_currentTable; + QScopedPointer<LinkContext> m_linkContext; // for <link> + QScopedPointer<LinkContext> m_seeAlsoContext; // for <see-also>foo()</see-also> bool m_tableHasHeader; QString m_context; QtDocGenerator* m_generator; @@ -150,12 +175,16 @@ private: bool m_insideItalic; QString m_lastTagName; QString m_opened_anchor; + QVector<InlineImage> m_inlineImages; - QString readFromLocations(const QStringList& locations, const QString& path, const QString& identifier); - QString readFromLocation(const QString& location, const QString& identifier, bool* ok = 0); + QString readFromLocations(const QStringList &locations, const QString &path, + const QString &identifier, QString *errorMessage); + QString readFromLocation(const QString &location, const QString &identifier, + QString *errorMessage); void pushOutputBuffer(); QString popOutputBuffer(); void writeTable(Table& table); + bool copyImage(const QString &href) const; }; inline QTextStream& operator<<(QTextStream& s, const QtXmlToSphinx& xmlToSphinx) @@ -179,6 +208,8 @@ public: return m_libSourceDir; } + QString docDataDir() const { return m_docDataDir; } + bool doSetup(const QMap<QString, QString>& args); const char* name() const @@ -186,7 +217,7 @@ public: return "QtDocGenerator"; } - QMap<QString, QString> options() const; + OptionDescriptions options() const; QStringList codeSnippetDirs() const { @@ -209,13 +240,15 @@ private: void writeArguments(QTextStream &s, const AbstractMetaClass *cppClass, const AbstractMetaFunction *func); void writeFunctionSignature(QTextStream& s, const AbstractMetaClass* cppClass, const AbstractMetaFunction* func); void writeFunction(QTextStream& s, bool writeDoc, const AbstractMetaClass* cppClass, const AbstractMetaFunction* func); - void writeFunctionParametersType(QTextStream &s, const AbstractMetaClass *cppClass, const AbstractMetaFunction* func); + void writeFunctionParametersType(QTextStream &s, const AbstractMetaClass *cppClass, + const AbstractMetaFunction* func); void writeFunctionList(QTextStream& s, const AbstractMetaClass* cppClass); void writeFunctionBlock(QTextStream& s, const QString& title, QStringList& functions); - void writeParamerteType(QTextStream &s, const AbstractMetaClass *cppClass, const AbstractMetaArgument *arg); + void writeParameterType(QTextStream &s, const AbstractMetaClass *cppClass, const AbstractMetaArgument *arg); void writeConstructors(QTextStream &s, const AbstractMetaClass *cppClass); - void writeFormatedText(QTextStream& s, const Documentation& doc, const AbstractMetaClass* metaclass = 0); + void writeFormattedText(QTextStream &s, const Documentation &doc, + const AbstractMetaClass *metaclass = nullptr); bool writeInjectDocumentation(QTextStream& s, TypeSystem::DocModificationMode mode, const AbstractMetaClass* cppClass, const AbstractMetaFunction* func); void writeDocSnips(QTextStream &s, const CodeSnipList &codeSnips, TypeSystem::CodeSnipPosition position, TypeSystem::Language language); diff --git a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp index ce74c9887..be42adb0f 100644 --- a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp +++ b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp @@ -36,6 +36,7 @@ #include <QtCore/QDir> #include <QtCore/QMetaObject> +#include <QtCore/QRegularExpression> #include <QtCore/QTextStream> #include <QtCore/QDebug> #include <QMetaType> @@ -153,13 +154,15 @@ QString CppGenerator::fileNameForContext(GeneratorContext &context) const } } -QList<AbstractMetaFunctionList> CppGenerator::filterGroupedOperatorFunctions(const AbstractMetaClass* metaClass, +QVector<AbstractMetaFunctionList> CppGenerator::filterGroupedOperatorFunctions(const AbstractMetaClass* metaClass, uint queryIn) { // ( func_name, num_args ) => func_list - QMap<QPair<QString, int >, AbstractMetaFunctionList> results; + typedef QMap<QPair<QString, int >, AbstractMetaFunctionList> ResultMap; + ResultMap results; const AbstractMetaClass::OperatorQueryOptions query(queryIn); - foreach (AbstractMetaFunction* func, metaClass->operatorOverloads(query)) { + const AbstractMetaFunctionList &funcs = metaClass->operatorOverloads(query); + for (AbstractMetaFunction *func : funcs) { if (func->isModifiedRemoved() || func->usesRValueReferences() || func->name() == QLatin1String("operator[]") @@ -176,7 +179,11 @@ QList<AbstractMetaFunctionList> CppGenerator::filterGroupedOperatorFunctions(con QPair<QString, int > op(func->name(), args); results[op].append(func); } - return results.values(); + QVector<AbstractMetaFunctionList> result; + result.reserve(results.size()); + for (ResultMap::const_iterator it = results.cbegin(), end = results.cend(); it != end; ++it) + result.append(it.value()); + return result; } bool CppGenerator::hasBoolCast(const AbstractMetaClass* metaClass) const @@ -203,6 +210,13 @@ static const char includeQDebug[] = "#endif\n" "#include <QDebug>\n"; +static QString chopType(QString s) +{ + if (s.endsWith(QLatin1String("_Type"))) + s.chop(5); + return s; +} + /*! Function used to write the class generated binding code on the buffer \param s the output buffer @@ -252,7 +266,8 @@ void CppGenerator::generateClass(QTextStream &s, GeneratorContext &classContext) s << endl << "// main header" << endl << "#include \"" << headerfile << '"' << endl; s << endl << "// inner classes" << endl; - foreach (AbstractMetaClass* innerClass, metaClass->innerClasses()) { + const AbstractMetaClassList &innerClasses = metaClass->innerClasses(); + for (AbstractMetaClass *innerClass : innerClasses) { GeneratorContext innerClassContext(innerClass); if (shouldGenerate(innerClass)) { QString headerfile = fileNameForContext(innerClassContext); @@ -262,16 +277,16 @@ void CppGenerator::generateClass(QTextStream &s, GeneratorContext &classContext) } AbstractMetaEnumList classEnums = metaClass->enums(); - foreach (AbstractMetaClass* innerClass, metaClass->innerClasses()) + for (AbstractMetaClass *innerClass : innerClasses) lookForEnumsInClassesNotToBeGenerated(classEnums, innerClass); //Extra includes s << endl << "// Extra includes" << endl; - QList<Include> includes = metaClass->typeEntry()->extraIncludes(); - foreach (AbstractMetaEnum* cppEnum, classEnums) + QVector<Include> includes = metaClass->typeEntry()->extraIncludes(); + for (AbstractMetaEnum *cppEnum : qAsConst(classEnums)) includes.append(cppEnum->typeEntry()->extraIncludes()); qSort(includes.begin(), includes.end()); - foreach (const Include &inc, includes) + for (const Include &inc : qAsConst(includes)) s << inc.toString() << endl; s << endl; @@ -324,15 +339,19 @@ void CppGenerator::generateClass(QTextStream &s, GeneratorContext &classContext) s << "}\n\n"; } - foreach (const AbstractMetaFunction* func, filterFunctions(metaClass)) { - if ((func->isPrivate() && !visibilityModifiedToPrivate(func)) - || (func->isModifiedRemoved() && !func->isAbstract())) + const AbstractMetaFunctionList &funcs = filterFunctions(metaClass); + for (const AbstractMetaFunction *func : funcs) { + const bool notAbstract = !func->isAbstract(); + if ((func->isPrivate() && notAbstract && !visibilityModifiedToPrivate(func)) + || (func->isModifiedRemoved() && notAbstract)) continue; - if (func->functionType() == AbstractMetaFunction::ConstructorFunction && !func->isUserAdded()) + if (func->functionType() == AbstractMetaFunction::ConstructorFunction && !func->isUserAdded()) { writeConstructorNative(s, func); - else if ((!avoidProtectedHack() || !metaClass->hasPrivateDestructor()) - && (func->isVirtual() || func->isAbstract())) + } else if ((!avoidProtectedHack() || !metaClass->hasPrivateDestructor()) + && ((func->isVirtual() || func->isAbstract()) + && (func->attributes() & AbstractMetaAttributes::FinalCppMethod) == 0)) { writeVirtualMethodNative(s, func); + } } if (!avoidProtectedHack() || !metaClass->hasPrivateDestructor()) { @@ -357,7 +376,7 @@ void CppGenerator::generateClass(QTextStream &s, GeneratorContext &classContext) for (FunctionGroupMapIt it = functionGroups.cbegin(), end = functionGroups.cend(); it != end; ++it) { AbstractMetaFunctionList overloads; QSet<QString> seenSignatures; - foreach (AbstractMetaFunction* func, it.value()) { + for (AbstractMetaFunction *func : it.value()) { if (!func->isAssignmentOperator() && !func->usesRValueReferences() && !func->isCastOperator() @@ -375,7 +394,7 @@ void CppGenerator::generateClass(QTextStream &s, GeneratorContext &classContext) if (overloads.isEmpty()) continue; - const AbstractMetaFunction* rfunc = overloads.first(); + const AbstractMetaFunction* rfunc = overloads.constFirst(); if (m_sequenceProtocol.contains(rfunc->name()) || m_mappingProtocol.contains(rfunc->name())) continue; @@ -411,7 +430,7 @@ void CppGenerator::generateClass(QTextStream &s, GeneratorContext &classContext) AbstractMetaType *pointerToInnerType = buildAbstractMetaTypeFromString(pointerToInnerTypeName); - AbstractMetaFunction *mutableRfunc = overloads.first(); + AbstractMetaFunction *mutableRfunc = overloads.constFirst(); mutableRfunc->replaceType(pointerToInnerType); } else if (smartPointerTypeEntry->refCountMethodName().isEmpty() || smartPointerTypeEntry->refCountMethodName() != rfunc->name()) { @@ -434,8 +453,7 @@ void CppGenerator::generateClass(QTextStream &s, GeneratorContext &classContext) } } - QString className = cpythonTypeName(metaClass); - className.remove(QRegExp(QLatin1String("_Type$"))); + const QString className = chopType(cpythonTypeName(metaClass)); if (metaClass->typeEntry()->isValue() || metaClass->typeEntry()->isSmartPointer()) { writeCopyFunction(s, classContext); @@ -484,15 +502,15 @@ void CppGenerator::generateClass(QTextStream &s, GeneratorContext &classContext) } if (supportsNumberProtocol(metaClass) && !metaClass->typeEntry()->isSmartPointer()) { - QList<AbstractMetaFunctionList> opOverloads = filterGroupedOperatorFunctions( + const QVector<AbstractMetaFunctionList> opOverloads = filterGroupedOperatorFunctions( metaClass, AbstractMetaClass::ArithmeticOp | AbstractMetaClass::LogicalOp | AbstractMetaClass::BitwiseOp); - foreach (const AbstractMetaFunctionList &allOverloads, opOverloads) { + for (const AbstractMetaFunctionList &allOverloads : opOverloads) { AbstractMetaFunctionList overloads; - foreach (AbstractMetaFunction* func, allOverloads) { + for (AbstractMetaFunction *func : allOverloads) { if (!func->isModifiedRemoved() && !func->isPrivate() && (func->ownerClass() == func->implementingClass() || func->isAbstract())) @@ -521,7 +539,8 @@ void CppGenerator::generateClass(QTextStream &s, GeneratorContext &classContext) } if (shouldGenerateGetSetList(metaClass) && !classContext.forSmartPointer()) { - foreach (const AbstractMetaField* metaField, metaClass->fields()) { + const AbstractMetaFieldList &fields = metaClass->fields(); + for (const AbstractMetaField *metaField : fields) { if (metaField->isStatic()) continue; writeGetterFunction(s, metaField, classContext); @@ -532,7 +551,7 @@ void CppGenerator::generateClass(QTextStream &s, GeneratorContext &classContext) s << "// Getters and Setters for " << metaClass->name() << endl; s << "static PyGetSetDef " << cpythonGettersSettersDefinitionName(metaClass) << "[] = {" << endl; - foreach (const AbstractMetaField* metaField, metaClass->fields()) { + for (const AbstractMetaField *metaField : fields) { if (metaField->isStatic()) continue; @@ -562,7 +581,7 @@ void CppGenerator::generateClass(QTextStream &s, GeneratorContext &classContext) writeTypeDiscoveryFunction(s, metaClass); - foreach (AbstractMetaEnum* cppEnum, classEnums) { + for (AbstractMetaEnum *cppEnum : qAsConst(classEnums)) { if (cppEnum->isAnonymous() || cppEnum->isPrivate()) continue; @@ -593,7 +612,7 @@ void CppGenerator::writeConstructorNative(QTextStream& s, const AbstractMetaFunc s << " : "; writeFunctionCall(s, func); s << " {" << endl; - const AbstractMetaArgument* lastArg = func->arguments().isEmpty() ? 0 : func->arguments().last(); + const AbstractMetaArgument* lastArg = func->arguments().isEmpty() ? 0 : func->arguments().constLast(); writeCodeSnips(s, func->injectedCodeSnips(), TypeSystem::CodeSnipPositionBeginning, TypeSystem::NativeCode, func, lastArg); s << INDENT << "// ... middle" << endl; writeCodeSnips(s, func->injectedCodeSnips(), TypeSystem::CodeSnipPositionEnd, TypeSystem::NativeCode, func, lastArg); @@ -614,7 +633,8 @@ static bool allArgumentsRemoved(const AbstractMetaFunction* func) { if (func->arguments().isEmpty()) return false; - foreach (const AbstractMetaArgument* arg, func->arguments()) { + const AbstractMetaArgumentList &arguments = func->arguments(); + for (const AbstractMetaArgument *arg : arguments) { if (!func->argumentRemoved(arg->argumentIndex() + 1)) return false; } @@ -666,19 +686,24 @@ void CppGenerator::writeVirtualMethodNative(QTextStream&s, const AbstractMetaFun QString defaultReturnExpr; if (retType) { - foreach (const FunctionModification &mod, func->modifications()) { - foreach (const ArgumentModification &argMod, mod.argument_mods) { + const FunctionModificationList &mods = func->modifications(); + for (const FunctionModification &mod : mods) { + for (const ArgumentModification &argMod : mod.argument_mods) { if (argMod.index == 0 && !argMod.replacedDefaultExpression.isEmpty()) { - QRegExp regex(QLatin1String("%(\\d+)")); + static const QRegularExpression regex(QStringLiteral("%(\\d+)")); + Q_ASSERT(regex.isValid()); defaultReturnExpr = argMod.replacedDefaultExpression; - int offset = 0; - while ((offset = regex.indexIn(defaultReturnExpr, offset)) != -1) { - int argId = regex.cap(1).toInt() - 1; + for (int offset = 0; ; ) { + const QRegularExpressionMatch match = regex.match(defaultReturnExpr, offset); + if (!match.hasMatch()) + break; + const int argId = match.capturedRef(1).toInt() - 1; if (argId < 0 || argId > func->arguments().count()) { qCWarning(lcShiboken) << "The expression used in return value contains an invalid index."; break; } - defaultReturnExpr.replace(regex.cap(0), func->arguments()[argId]->name()); + defaultReturnExpr.replace(match.captured(0), func->arguments().at(argId)->name()); + offset = match.capturedStart(1); } } } @@ -709,7 +734,7 @@ void CppGenerator::writeVirtualMethodNative(QTextStream&s, const AbstractMetaFun //Write declaration/native injected code if (func->hasInjectedCode()) { CodeSnipList snips = func->injectedCodeSnips(); - const AbstractMetaArgument* lastArg = func->arguments().isEmpty() ? 0 : func->arguments().last(); + const AbstractMetaArgument* lastArg = func->arguments().isEmpty() ? 0 : func->arguments().constLast(); writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionDeclaration, TypeSystem::NativeCode, func, lastArg); s << endl; } @@ -732,7 +757,7 @@ void CppGenerator::writeVirtualMethodNative(QTextStream&s, const AbstractMetaFun CodeSnipList snips; if (func->hasInjectedCode()) { snips = func->injectedCodeSnips(); - const AbstractMetaArgument* lastArg = func->arguments().isEmpty() ? 0 : func->arguments().last(); + const AbstractMetaArgument* lastArg = func->arguments().isEmpty() ? 0 : func->arguments().constLast(); writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionBeginning, TypeSystem::ShellCode, func, lastArg); s << endl; } @@ -764,7 +789,8 @@ void CppGenerator::writeVirtualMethodNative(QTextStream&s, const AbstractMetaFun s << "PyTuple_New(0));" << endl; } else { QStringList argConversions; - foreach (const AbstractMetaArgument* arg, func->arguments()) { + const AbstractMetaArgumentList &arguments = func->arguments(); + for (const AbstractMetaArgument *arg : arguments) { if (func->argumentRemoved(arg->argumentIndex() + 1)) continue; @@ -810,8 +836,9 @@ void CppGenerator::writeVirtualMethodNative(QTextStream&s, const AbstractMetaFun bool invalidateReturn = false; QSet<int> invalidateArgs; - foreach (const FunctionModification &funcMod, func->modifications()) { - foreach (const ArgumentModification &argMod, funcMod.argument_mods) { + const FunctionModificationList &mods = func->modifications(); + for (const FunctionModification &funcMod : mods) { + for (const ArgumentModification &argMod : funcMod.argument_mods) { if (argMod.resetAfterUse && !invalidateArgs.contains(argMod.index)) { invalidateArgs.insert(argMod.index); s << INDENT << "bool invalidateArg" << argMod.index; @@ -830,7 +857,7 @@ void CppGenerator::writeVirtualMethodNative(QTextStream&s, const AbstractMetaFun if (injectedCodeUsesPySelf(func)) s << INDENT << "PyObject* pySelf = BindingManager::instance().retrieveWrapper(this);" << endl; - const AbstractMetaArgument* lastArg = func->arguments().isEmpty() ? 0 : func->arguments().last(); + const AbstractMetaArgument* lastArg = func->arguments().isEmpty() ? 0 : func->arguments().constLast(); writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionBeginning, TypeSystem::NativeCode, func, lastArg); s << endl; } @@ -908,7 +935,7 @@ void CppGenerator::writeVirtualMethodNative(QTextStream&s, const AbstractMetaFun Indentation indentation(INDENT); s << INDENT << "Shiboken::Object::releaseOwnership(" << PYTHON_RETURN_VAR ".object());" << endl; } - foreach (int argIndex, invalidateArgs) { + for (int argIndex : qAsConst(invalidateArgs)) { s << INDENT << "if (invalidateArg" << argIndex << ')' << endl; Indentation indentation(INDENT); s << INDENT << "Shiboken::Object::invalidate(PyTuple_GET_ITEM(" PYTHON_ARGS ", "; @@ -916,8 +943,9 @@ void CppGenerator::writeVirtualMethodNative(QTextStream&s, const AbstractMetaFun } - foreach (const FunctionModification &funcMod, func->modifications()) { - foreach (const ArgumentModification &argMod, funcMod.argument_mods) { + const FunctionModificationList &funcMods = func->modifications(); + for (const FunctionModification &funcMod : funcMods) { + for (const ArgumentModification &argMod : funcMod.argument_mods) { if (argMod.ownerships.contains(TypeSystem::NativeCode) && argMod.index == 0 && argMod.ownerships[TypeSystem::NativeCode] == TypeSystem::CppOwnership) { s << INDENT << "if (Shiboken::Object::checkType(" PYTHON_RETURN_VAR "))" << endl; @@ -929,7 +957,7 @@ void CppGenerator::writeVirtualMethodNative(QTextStream&s, const AbstractMetaFun if (func->hasInjectedCode()) { s << endl; - const AbstractMetaArgument* lastArg = func->arguments().isEmpty() ? 0 : func->arguments().last(); + const AbstractMetaArgument* lastArg = func->arguments().isEmpty() ? 0 : func->arguments().constLast(); writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionEnd, TypeSystem::NativeCode, func, lastArg); } @@ -1019,7 +1047,6 @@ void CppGenerator::writeEnumConverterFunctions(QTextStream& s, const TypeEntry* { if (!enumType) return; - QString enumFlagName = enumType->isFlags() ? QLatin1String("flag") : QLatin1String("enum"); QString typeName = fixedCppTypeName(enumType); QString enumPythonType = cpythonTypeNameExt(enumType); QString cppTypeName = getFullTypeName(enumType).trimmed(); @@ -1043,7 +1070,8 @@ void CppGenerator::writeEnumConverterFunctions(QTextStream& s, const TypeEntry* code.clear(); - c << INDENT << "int castCppIn = *((" << cppTypeName << "*)cppIn);" << endl; + c << INDENT << "const int castCppIn = int(*reinterpret_cast<const " + << cppTypeName << " *>(cppIn));" << endl; c << INDENT; c << "return "; if (enumType->isFlags()) @@ -1090,11 +1118,12 @@ void CppGenerator::writeConverterFunctions(QTextStream &s, const AbstractMetaCla s << "// Type conversion functions." << endl << endl; AbstractMetaEnumList classEnums = metaClass->enums(); - foreach (AbstractMetaClass* innerClass, metaClass->innerClasses()) + const AbstractMetaClassList &innerClasses = metaClass->innerClasses(); + for (AbstractMetaClass *innerClass : innerClasses) lookForEnumsInClassesNotToBeGenerated(classEnums, innerClass); if (!classEnums.isEmpty()) s << "// Python to C++ enum conversion." << endl; - foreach (const AbstractMetaEnum* metaEnum, classEnums) + for (const AbstractMetaEnum *metaEnum : qAsConst(classEnums)) writeEnumConverterFunctions(s, metaEnum); if (metaClass->isNamespace()) @@ -1204,7 +1233,8 @@ void CppGenerator::writeConverterFunctions(QTextStream &s, const AbstractMetaCla // Implicit conversions. AbstractMetaFunctionList implicitConvs; if (!customConversion || !customConversion->replaceOriginalTargetToNativeConversions()) { - foreach (AbstractMetaFunction* func, implicitConversions(metaClass->typeEntry())) { + const AbstractMetaFunctionList &allImplicitConvs = implicitConversions(metaClass->typeEntry()); + for (AbstractMetaFunction *func : allImplicitConvs) { if (!func->isUserAdded()) implicitConvs << func; } @@ -1214,7 +1244,7 @@ void CppGenerator::writeConverterFunctions(QTextStream &s, const AbstractMetaCla s << "// Implicit conversions." << endl; AbstractMetaType* targetType = buildAbstractMetaTypeFromAbstractMetaClass(metaClass); - foreach (const AbstractMetaFunction* conv, implicitConvs) { + for (const AbstractMetaFunction* conv : qAsConst(implicitConvs)) { if (conv->isModifiedRemoved()) continue; @@ -1229,7 +1259,7 @@ void CppGenerator::writeConverterFunctions(QTextStream &s, const AbstractMetaCla // Constructor that does implicit conversion. if (!conv->typeReplaced(1).isEmpty()) continue; - const AbstractMetaType* sourceType = conv->arguments().first()->type(); + const AbstractMetaType* sourceType = conv->arguments().constFirst()->type(); typeCheck = cpythonCheckFunction(sourceType); bool isUserPrimitiveWithoutTargetLangName = isUserPrimitive(sourceType) && sourceType->typeEntry()->targetLangApiName() == sourceType->typeEntry()->name(); @@ -1273,7 +1303,7 @@ void CppGenerator::writeConverterFunctions(QTextStream &s, const AbstractMetaCla } const AbstractMetaType* sourceType = conv->isConversionOperator() ? buildAbstractMetaTypeFromAbstractMetaClass(conv->ownerClass()) - : conv->arguments().first()->type(); + : conv->arguments().constFirst()->type(); writePythonToCppConversionFunctions(s, sourceType, targetType, typeCheck, toCppConv, toCppPreConv); } @@ -1288,7 +1318,7 @@ void CppGenerator::writeCustomConverterFunctions(QTextStream& s, const CustomCon if (toCppConversions.isEmpty()) return; s << "// Python to C++ conversions for type '" << customConversion->ownerType()->qualifiedCppName() << "'." << endl; - foreach (CustomConversion::TargetToNativeConversion* toNative, toCppConversions) + for (CustomConversion::TargetToNativeConversion *toNative : toCppConversions) writePythonToCppConversionFunctions(s, toNative, customConversion->ownerType()); s << endl; } @@ -1368,7 +1398,8 @@ void CppGenerator::writeConverterRegister(QTextStream &s, const AbstractMetaClas // Add implicit conversions. AbstractMetaFunctionList implicitConvs; if (!customConversion || !customConversion->replaceOriginalTargetToNativeConversions()) { - foreach (AbstractMetaFunction* func, implicitConversions(metaClass->typeEntry())) { + const AbstractMetaFunctionList &allImplicitConvs = implicitConversions(metaClass->typeEntry()); + for (AbstractMetaFunction *func : allImplicitConvs) { if (!func->isUserAdded()) implicitConvs << func; } @@ -1378,7 +1409,7 @@ void CppGenerator::writeConverterRegister(QTextStream &s, const AbstractMetaClas s << INDENT << "// Add implicit conversions to type converter." << endl; AbstractMetaType* targetType = buildAbstractMetaTypeFromAbstractMetaClass(metaClass); - foreach (const AbstractMetaFunction* conv, implicitConvs) { + for (const AbstractMetaFunction *conv : qAsConst(implicitConvs)) { if (conv->isModifiedRemoved()) continue; const AbstractMetaType* sourceType; @@ -1388,7 +1419,7 @@ void CppGenerator::writeConverterRegister(QTextStream &s, const AbstractMetaClas // Constructor that does implicit conversion. if (!conv->typeReplaced(1).isEmpty()) continue; - sourceType = conv->arguments().first()->type(); + sourceType = conv->arguments().constFirst()->type(); } QString toCpp = pythonToCppFunctionName(sourceType, targetType); QString isConv = convertibleToCppFunctionName(sourceType, targetType); @@ -1406,7 +1437,7 @@ void CppGenerator::writeCustomConverterRegister(QTextStream& s, const CustomConv if (toCppConversions.isEmpty()) return; s << INDENT << "// Add user defined implicit conversions to type converter." << endl; - foreach (CustomConversion::TargetToNativeConversion* toNative, toCppConversions) { + for (CustomConversion::TargetToNativeConversion *toNative : toCppConversions) { QString toCpp = pythonToCppFunctionName(toNative, customConversion->ownerType()); QString isConv = convertibleToCppFunctionName(toNative, customConversion->ownerType()); writeAddPythonToCppConversion(s, converterVar, toCpp, isConv); @@ -1516,8 +1547,10 @@ void CppGenerator::writeConstructorWrapper(QTextStream &s, const AbstractMetaFun QSet<QString> argNamesSet; if (usePySideExtensions() && metaClass->isQObject()) { // Write argNames variable with all known argument names. - foreach (const AbstractMetaFunction* func, overloadData.overloads()) { - foreach (const AbstractMetaArgument* arg, func->arguments()) { + const OverloadData::MetaFunctionList &overloads = overloadData.overloads(); + for (const AbstractMetaFunction *func : overloads) { + const AbstractMetaArgumentList &arguments = func->arguments(); + for (const AbstractMetaArgument *arg : arguments) { if (arg->defaultValueExpression().isEmpty() || func->argumentRemoved(arg->argumentIndex() + 1)) continue; argNamesSet << arg->name(); @@ -1595,7 +1628,7 @@ void CppGenerator::writeConstructorWrapper(QTextStream &s, const AbstractMetaFun // (first "1") and the flag indicating that the Python wrapper holds an C++ wrapper // is marked as true (the second "1"). Otherwise the default values apply: // Python owns it and C++ wrapper is false. - if (shouldGenerateCppWrapper(overloads.first()->ownerClass())) + if (shouldGenerateCppWrapper(overloads.constFirst()->ownerClass())) s << INDENT << "Shiboken::Object::setHasCppWrapper(sbkSelf, true);" << endl; // Need to check if a wrapper for same pointer is already registered // Caused by bug PYSIDE-217, where deleted objects' wrappers are not released @@ -1621,8 +1654,9 @@ void CppGenerator::writeConstructorWrapper(QTextStream &s, const AbstractMetaFun // Constructor code injections, position=end bool hasCodeInjectionsAtEnd = false; - foreach(AbstractMetaFunction* func, overloads) { - foreach (const CodeSnip &cs, func->injectedCodeSnips()) { + for (AbstractMetaFunction *func : overloads) { + const CodeSnipList &injectedCodeSnips = func->injectedCodeSnips(); + for (const CodeSnip &cs : injectedCodeSnips) { if (cs.position == TypeSystem::CodeSnipPositionEnd) { hasCodeInjectionsAtEnd = true; break; @@ -1632,9 +1666,10 @@ void CppGenerator::writeConstructorWrapper(QTextStream &s, const AbstractMetaFun if (hasCodeInjectionsAtEnd) { // FIXME: C++ arguments are not available in code injection on constructor when position = end. s << INDENT << "switch(overloadId) {" << endl; - foreach(AbstractMetaFunction* func, overloads) { + for (AbstractMetaFunction *func : overloads) { Indentation indent(INDENT); - foreach (const CodeSnip &cs, func->injectedCodeSnips()) { + const CodeSnipList &injectedCodeSnips = func->injectedCodeSnips(); + for (const CodeSnip &cs : injectedCodeSnips) { if (cs.position == TypeSystem::CodeSnipPositionEnd) { s << INDENT << "case " << metaClass->functions().indexOf(func) << ':' << endl; s << INDENT << '{' << endl; @@ -1812,10 +1847,10 @@ void CppGenerator::writeArgumentsInitializer(QTextStream& s, OverloadData& overl s << INDENT << '}'; } } - QList<int> invalidArgsLength = overloadData.invalidArgumentLengths(); + const QVector<int> invalidArgsLength = overloadData.invalidArgumentLengths(); if (!invalidArgsLength.isEmpty()) { QStringList invArgsLen; - foreach (int i, invalidArgsLength) + for (int i : qAsConst(invalidArgsLength)) invArgsLen << QStringLiteral("numArgs == %1").arg(i); if (usesNamedArguments && (!ownerClassIsQObject || minArgs > 0)) s << " else "; @@ -1943,9 +1978,11 @@ void CppGenerator::writeErrorSection(QTextStream& s, OverloadData& overloadData) s << INDENT << "Shiboken::setErrorAboutWrongArguments(" << argsVar << ", \"" << funcName << "\", 0);" << endl; } else { QStringList overloadSignatures; - foreach (const AbstractMetaFunction* f, overloadData.overloads()) { + const OverloadData::MetaFunctionList &overloads = overloadData.overloads(); + for (const AbstractMetaFunction *f : overloads) { QStringList args; - foreach(AbstractMetaArgument* arg, f->arguments()) { + const AbstractMetaArgumentList &arguments = f->arguments(); + for (AbstractMetaArgument *arg : arguments) { QString strArg; AbstractMetaType* argType = arg->type(); if (isCString(argType)) { @@ -1961,7 +1998,9 @@ void CppGenerator::writeErrorSection(QTextStream& s, OverloadData& overloadData) strArg = QLatin1String("1-unicode"); } else { strArg = ptp->name(); - strArg.remove(QRegExp(QLatin1String("^signed\\s+"))); + static const QRegularExpression regex(QStringLiteral("^signed\\s+")); + Q_ASSERT(regex.isValid()); + strArg.remove(regex); if (strArg == QLatin1String("double")) strArg = QLatin1String("float"); } @@ -2043,9 +2082,13 @@ void CppGenerator::writeInvalidPyObjectCheck(QTextStream& s, const QString& pyOb static QString pythonToCppConverterForArgumentName(const QString& argumentName) { - static QRegExp pyArgsRegex(QLatin1String(PYTHON_ARGS"(\\[\\d+[-]?\\d*\\])")); - pyArgsRegex.indexIn(argumentName); - return QLatin1String(PYTHON_TO_CPP_VAR) + pyArgsRegex.cap(1); + static const QRegularExpression pyArgsRegex(QLatin1String(PYTHON_ARGS"(\\[\\d+[-]?\\d*\\])")); + Q_ASSERT(pyArgsRegex.isValid()); + const QRegularExpressionMatch match = pyArgsRegex.match(argumentName); + QString result = QLatin1String(PYTHON_TO_CPP_VAR); + if (match.hasMatch()) + result += match.captured(1); + return result; } void CppGenerator::writeTypeCheck(QTextStream& s, const AbstractMetaType* argType, QString argumentName, bool isNumber, QString customType, bool rejectNull) @@ -2085,20 +2128,26 @@ static void checkTypeViability(const AbstractMetaFunction* func, const AbstractM if (!type || !type->typeEntry()->isPrimitive() || type->indirections() == 0 + || (type->indirections() == 1 && type->typeUsagePattern() == AbstractMetaType::NativePointerAsArrayPattern) || ShibokenGenerator::isCString(type) || func->argumentRemoved(argIdx) || !func->typeReplaced(argIdx).isEmpty() || !func->conversionRule(TypeSystem::All, argIdx).isEmpty() || func->hasInjectedCode()) return; - QString prefix; + QString message; + QTextStream str(&message); + str << "There's no user provided way (conversion rule, argument" + " removal, custom code, etc) to handle the primitive "; + if (argIdx == 0) + str << "return type '" << type->cppSignature() << '\''; + else + str << "type '" << type->cppSignature() << "' of argument " << argIdx; + str << " in function '"; if (func->ownerClass()) - prefix = func->ownerClass()->qualifiedCppName() + QLatin1String("::"); - qCWarning(lcShiboken).noquote().nospace() - << QString::fromLatin1("There's no user provided way (conversion rule, argument removal, custom code, etc) " - "to handle the primitive %1 type '%2' in function '%3%4'.") - .arg(argIdx == 0 ? QStringLiteral("return") : QStringLiteral("argument"), - type->cppSignature(), prefix, func->signature()); + str << func->ownerClass()->qualifiedCppName() << "::"; + str << func->signature() << "'."; + qCWarning(lcShiboken).noquote().nospace() << message; } static void checkTypeViability(const AbstractMetaFunction* func) @@ -2114,9 +2163,10 @@ static void checkTypeViability(const AbstractMetaFunction* func) void CppGenerator::writeTypeCheck(QTextStream& s, const OverloadData* overloadData, QString argumentName) { QSet<const TypeEntry*> numericTypes; - - foreach (OverloadData* od, overloadData->previousOverloadData()->nextOverloadData()) { - foreach (const AbstractMetaFunction* func, od->overloads()) { + const OverloadDataList &overloads = overloadData->previousOverloadData()->nextOverloadData(); + for (OverloadData *od : overloads) { + const OverloadData::MetaFunctionList &odOverloads = od->overloads(); + for (const AbstractMetaFunction *func : odOverloads) { checkTypeViability(func); const AbstractMetaType* argType = od->argument(func)->type(); if (!argType->isPrimitive()) @@ -2174,6 +2224,23 @@ const AbstractMetaType* CppGenerator::getArgumentType(const AbstractMetaFunction return argType; } +static inline QString arrayHandleType(const AbstractMetaTypeCList &nestedArrayTypes) +{ + switch (nestedArrayTypes.size()) { + case 1: + return QStringLiteral("Shiboken::Conversions::ArrayHandle<") + + nestedArrayTypes.constLast()->minimalSignature() + + QLatin1Char('>'); + case 2: + return QStringLiteral("Shiboken::Conversions::Array2Handle<") + + nestedArrayTypes.constLast()->minimalSignature() + + QStringLiteral(", ") + + QString::number(nestedArrayTypes.constFirst()->arrayElementCount()) + + QLatin1Char('>'); + } + return QString(); +} + void CppGenerator::writePythonToCppTypeConversion(QTextStream& s, const AbstractMetaType* type, const QString& pyIn, @@ -2195,7 +2262,13 @@ void CppGenerator::writePythonToCppTypeConversion(QTextStream& s, && !isCppPrimitive(type) && isNotContainerEnumOrFlags && !(treatAsPointer || isPointerOrObjectType); - QString typeName = getFullTypeNameWithoutModifiers(type); + + const AbstractMetaTypeCList nestedArrayTypes = type->nestedArrayTypes(); + const bool isCppPrimitiveArray = !nestedArrayTypes.isEmpty() + && nestedArrayTypes.constLast()->isCppPrimitive(); + QString typeName = isCppPrimitiveArray + ? arrayHandleType(nestedArrayTypes) + : getFullTypeNameWithoutModifiers(type); bool isProtectedEnum = false; @@ -2212,7 +2285,9 @@ void CppGenerator::writePythonToCppTypeConversion(QTextStream& s, } s << INDENT << typeName; - if (treatAsPointer || isPointerOrObjectType) { + if (isCppPrimitiveArray) { + s << ' ' << cppOut; + } else if (treatAsPointer || isPointerOrObjectType) { s << "* " << cppOut; if (!defaultValue.isEmpty()) s << " = " << defaultValue; @@ -2280,7 +2355,7 @@ static void addConversionRuleCodeSnippet(CodeSnipList& snippetList, QString& rul } else { rule.replace(QLatin1String("%out"), outputName); } - CodeSnip snip(0, snippetLanguage); + CodeSnip snip(snippetLanguage); snip.position = (snippetLanguage == TypeSystem::NativeCode) ? TypeSystem::CodeSnipPositionAny : TypeSystem::CodeSnipPositionBeginning; snip.addCode(rule); snippetList << snip; @@ -2289,7 +2364,8 @@ static void addConversionRuleCodeSnippet(CodeSnipList& snippetList, QString& rul void CppGenerator::writeConversionRule(QTextStream& s, const AbstractMetaFunction* func, TypeSystem::Language language) { CodeSnipList snippets; - foreach (AbstractMetaArgument* arg, func->arguments()) { + const AbstractMetaArgumentList &arguments = func->arguments(); + for (AbstractMetaArgument *arg : arguments) { QString rule = func->conversionRule(language, arg->argumentIndex() + 1); addConversionRuleCodeSnippet(snippets, rule, language, TypeSystem::TargetLangCode, arg->name(), arg->name()); @@ -2317,7 +2393,7 @@ void CppGenerator::writeOverloadedFunctionDecisor(QTextStream& s, const Overload { s << INDENT << "// Overloaded function decisor" << endl; const AbstractMetaFunction* rfunc = overloadData.referenceFunction(); - QList<const AbstractMetaFunction*> functionOverloads = overloadData.overloadsWithoutRepetition(); + const OverloadData::MetaFunctionList &functionOverloads = overloadData.overloadsWithoutRepetition(); for (int i = 0; i < functionOverloads.count(); i++) s << INDENT << "// " << i << ": " << functionOverloads.at(i)->minimalSignature() << endl; writeOverloadedFunctionDecisorEngine(s, &overloadData); @@ -2351,7 +2427,8 @@ void CppGenerator::writeOverloadedFunctionDecisorEngine(QTextStream& s, const Ov // variable to be used further on this method on the conditional that identifies default // method calls. if (!hasDefaultCall) { - foreach (const AbstractMetaFunction* func, parentOverloadData->overloads()) { + const OverloadData::MetaFunctionList &overloads = parentOverloadData->overloads(); + for (const AbstractMetaFunction *func : overloads) { if (parentOverloadData->isFinalOccurrence(func)) { referenceFunction = func; hasDefaultCall = true; @@ -2392,6 +2469,7 @@ void CppGenerator::writeOverloadedFunctionDecisorEngine(QTextStream& s, const Ov // If the next argument has a default value the decisor can perform a method call; // it just need to check if the number of arguments received from Python are equal // to the number of parameters preceding the argument with the default value. + const OverloadDataList &overloads = parentOverloadData->nextOverloadData(); if (hasDefaultCall) { isFirst = false; int numArgs = parentOverloadData->argPos() + 1; @@ -2399,7 +2477,7 @@ void CppGenerator::writeOverloadedFunctionDecisorEngine(QTextStream& s, const Ov { Indentation indent(INDENT); const AbstractMetaFunction* func = referenceFunction; - foreach (OverloadData* overloadData, parentOverloadData->nextOverloadData()) { + for (OverloadData *overloadData : overloads) { const AbstractMetaFunction* defValFunc = overloadData->getFunctionWithDefaultValue(); if (defValFunc) { func = defValFunc; @@ -2412,7 +2490,7 @@ void CppGenerator::writeOverloadedFunctionDecisorEngine(QTextStream& s, const Ov s << INDENT << '}'; } - foreach (OverloadData* overloadData, parentOverloadData->nextOverloadData()) { + for (OverloadData *overloadData : overloads) { bool signatureFound = overloadData->overloads().size() == 1 && !overloadData->getFunctionWithDefaultValue() && !overloadData->findNextArgWithDefault(); @@ -2438,7 +2516,7 @@ void CppGenerator::writeOverloadedFunctionDecisorEngine(QTextStream& s, const Ov if (func->isConstructor() && func->arguments().count() == 1) { const AbstractMetaClass* ownerClass = func->ownerClass(); const ComplexTypeEntry* baseContainerType = ownerClass->typeEntry()->baseContainerType(); - if (baseContainerType && baseContainerType == func->arguments().first()->type()->typeEntry() && isCopyable(ownerClass)) { + if (baseContainerType && baseContainerType == func->arguments().constFirst()->type()->typeEntry() && isCopyable(ownerClass)) { tck << '!' << cpythonCheckFunction(ownerClass->typeEntry()) << pyArgName << ')' << endl; Indentation indent(INDENT); tck << INDENT << "&& "; @@ -2453,17 +2531,17 @@ void CppGenerator::writeOverloadedFunctionDecisorEngine(QTextStream& s, const Ov if (od->nextOverloadData().isEmpty() || od->nextArgumentHasDefaultValue() || od->nextOverloadData().size() != 1 - || od->overloads().size() != od->nextOverloadData().first()->overloads().size()) { + || od->overloads().size() != od->nextOverloadData().constFirst()->overloads().size()) { overloadData = od; od = 0; } else { - od = od->nextOverloadData().first(); + od = od->nextOverloadData().constFirst(); } } if (usePyArgs && signatureFound) { AbstractMetaArgumentList args = refFunc->arguments(); - int lastArgIsVarargs = (int) (args.size() > 1 && args.last()->type()->isVarargs()); + int lastArgIsVarargs = (int) (args.size() > 1 && args.constLast()->type()->isVarargs()); int numArgs = args.size() - OverloadData::numberOfRemovedArguments(refFunc) - lastArgIsVarargs; typeChecks.prepend(QString::fromLatin1("numArgs %1 %2").arg(lastArgIsVarargs ? QLatin1String(">=") : QLatin1String("==")).arg(numArgs)); } else if (sequenceArgCount > 1) { @@ -2501,13 +2579,13 @@ void CppGenerator::writeOverloadedFunctionDecisorEngine(QTextStream& s, const Ov void CppGenerator::writeFunctionCalls(QTextStream &s, const OverloadData &overloadData, GeneratorContext &context) { - QList<const AbstractMetaFunction*> overloads = overloadData.overloadsWithoutRepetition(); + const OverloadData::MetaFunctionList &overloads = overloadData.overloadsWithoutRepetition(); s << INDENT << "// Call function/method" << endl; s << INDENT << (overloads.count() > 1 ? "switch (overloadId) " : "") << '{' << endl; { Indentation indent(INDENT); if (overloads.count() == 1) { - writeSingleFunctionCall(s, overloadData, overloads.first(), context); + writeSingleFunctionCall(s, overloadData, overloads.constFirst(), context); } else { for (int i = 0; i < overloads.count(); i++) { const AbstractMetaFunction* func = overloads.at(i); @@ -2818,21 +2896,22 @@ void CppGenerator::writePythonToCppConversionFunctions(QTextStream& s, const Abs QString code; QTextStream c(&code); c << INDENT << QString::fromLatin1("%1& cppOutRef = *((%1*)cppOut);").arg(cppTypeName) << endl; - code.append(toCppConversions.first()->conversion()); + code.append(toCppConversions.constFirst()->conversion()); for (int i = 0; i < containerType->instantiations().count(); ++i) { const AbstractMetaType* type = containerType->instantiations().at(i); QString typeName = getFullTypeName(type); if (type->isValue() && isValueTypeWithCopyConstructorOnly(type)) { - static QRegExp regex(QLatin1String(CONVERTTOCPP_REGEX)); - int pos = 0; - while ((pos = regex.indexIn(code, pos)) != -1) { - pos += regex.matchedLength(); - QStringList list = regex.capturedTexts(); - QString varName = list.at(1); - QString leftCode = code.left(pos); + static const QRegularExpression regex(QLatin1String(CONVERTTOCPP_REGEX)); + Q_ASSERT(regex.isValid()); + for (int pos = 0; ; ) { + const QRegularExpressionMatch match = regex.match(code, pos); + if (!match.hasMatch()) + break; + pos = match.capturedEnd(); + const QString varName = match.captured(1); QString rightCode = code.mid(pos); rightCode.replace(varName, QLatin1Char('*') + varName); - code = leftCode + rightCode; + code.replace(pos, code.size() - pos, rightCode); } typeName.append(QLatin1Char('*')); } @@ -2867,7 +2946,7 @@ void CppGenerator::writeAddPythonToCppConversion(QTextStream& s, const QString& void CppGenerator::writeNamedArgumentResolution(QTextStream& s, const AbstractMetaFunction* func, bool usePyArgs) { - AbstractMetaArgumentList args = OverloadData::getArgumentsWithDefaultValues(func); + const AbstractMetaArgumentList &args = OverloadData::getArgumentsWithDefaultValues(func); if (args.isEmpty()) return; @@ -2878,7 +2957,7 @@ void CppGenerator::writeNamedArgumentResolution(QTextStream& s, const AbstractMe { Indentation indent(INDENT); s << INDENT << "PyObject* "; - foreach (const AbstractMetaArgument* arg, args) { + for (const AbstractMetaArgument *arg : args) { int pyArgIndex = arg->argumentIndex() - OverloadData::numberOfRemovedArguments(func, arg->argumentIndex()); QString pyArgName = usePyArgs ? QString::fromLatin1(PYTHON_ARGS "[%1]").arg(pyArgIndex) @@ -2903,7 +2982,7 @@ void CppGenerator::writeNamedArgumentResolution(QTextStream& s, const AbstractMe } } s << INDENT << '}' << endl; - if (arg != args.last()) + if (arg != args.constLast()) s << INDENT; } } @@ -2953,7 +3032,8 @@ void CppGenerator::writeMethodCall(QTextStream &s, const AbstractMetaFunction *f { s << INDENT << "// " << func->minimalSignature() << (func->isReverseOperator() ? " [reverse operator]": "") << endl; if (func->isConstructor()) { - foreach (const CodeSnip &cs, func->injectedCodeSnips()) { + const CodeSnipList &snips = func->injectedCodeSnips(); + for (const CodeSnip &cs : snips) { if (cs.position == TypeSystem::CodeSnipPositionEnd) { s << INDENT << "overloadId = " << func->ownerClass()->functions().indexOf(const_cast<AbstractMetaFunction* const>(func)) << ';' << endl; break; @@ -2990,7 +3070,7 @@ void CppGenerator::writeMethodCall(QTextStream &s, const AbstractMetaFunction *f removedArgs++; } } else if (maxArgs != 0 && !func->arguments().isEmpty()) { - lastArg = func->arguments().last(); + lastArg = func->arguments().constLast(); } writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionBeginning, TypeSystem::TargetLangCode, func, lastArg); @@ -3065,7 +3145,7 @@ void CppGenerator::writeMethodCall(QTextStream &s, const AbstractMetaFunction *f firstArg.remove(1, 1); // remove the de-reference operator QString secondArg = QLatin1String(CPP_ARG0); - if (!func->isUnaryOperator() && shouldDereferenceArgumentPointer(func->arguments().first())) { + if (!func->isUnaryOperator() && shouldDereferenceArgumentPointer(func->arguments().constFirst())) { secondArg.prepend(QLatin1String("(*")); secondArg.append(QLatin1Char(')')); } @@ -3255,11 +3335,12 @@ void CppGenerator::writeMethodCall(QTextStream &s, const AbstractMetaFunction *f bool hasReturnPolicy = false; // Ownership transference between C++ and Python. - QList<ArgumentModification> ownership_mods; + QVector<ArgumentModification> ownership_mods; // Python object reference management. - QList<ArgumentModification> refcount_mods; - foreach (const FunctionModification &func_mod, func->modifications()) { - foreach (const ArgumentModification &arg_mod, func_mod.argument_mods) { + QVector<ArgumentModification> refcount_mods; + const FunctionModificationList &funcMods = func->modifications(); + for (const FunctionModification &func_mod : funcMods) { + for (const ArgumentModification &arg_mod : func_mod.argument_mods) { if (!arg_mod.ownerships.isEmpty() && arg_mod.ownerships.contains(TypeSystem::TargetLangCode)) ownership_mods.append(arg_mod); else if (!arg_mod.referenceCounts.isEmpty()) @@ -3273,7 +3354,7 @@ void CppGenerator::writeMethodCall(QTextStream &s, const AbstractMetaFunction *f if (!ownership_mods.isEmpty()) { s << endl << INDENT << "// Ownership transferences." << endl; - foreach (const ArgumentModification &arg_mod, ownership_mods) { + for (const ArgumentModification &arg_mod : qAsConst(ownership_mods)) { const AbstractMetaClass* wrappedClass = 0; QString pyArgName = argumentNameFromIndex(func, arg_mod.index, &wrappedClass); if (!wrappedClass) { @@ -3304,8 +3385,8 @@ void CppGenerator::writeMethodCall(QTextStream &s, const AbstractMetaFunction *f } } else if (!refcount_mods.isEmpty()) { - foreach (const ArgumentModification &arg_mod, refcount_mods) { - ReferenceCount refCount = arg_mod.referenceCounts.first(); + for (const ArgumentModification &arg_mod : qAsConst(refcount_mods)) { + ReferenceCount refCount = arg_mod.referenceCounts.constFirst(); if (refCount.action != ReferenceCount::Set && refCount.action != ReferenceCount::Remove && refCount.action != ReferenceCount::Add) { @@ -3331,7 +3412,7 @@ void CppGenerator::writeMethodCall(QTextStream &s, const AbstractMetaFunction *f s << INDENT << "Shiboken::Object::removeReference("; s << "reinterpret_cast<SbkObject*>(" PYTHON_SELF_VAR "), \""; - QString varName = arg_mod.referenceCounts.first().varName; + QString varName = arg_mod.referenceCounts.constFirst().varName; if (varName.isEmpty()) varName = func->minimalSignature() + QString().number(arg_mod.index); @@ -3349,15 +3430,15 @@ void CppGenerator::writeMethodCall(QTextStream &s, const AbstractMetaFunction *f QStringList CppGenerator::getAncestorMultipleInheritance(const AbstractMetaClass* metaClass) { QStringList result; - AbstractMetaClassList baseClases = getBaseClasses(metaClass); + const AbstractMetaClassList &baseClases = getBaseClasses(metaClass); if (!baseClases.isEmpty()) { - foreach (const AbstractMetaClass* baseClass, baseClases) { + for (const AbstractMetaClass *baseClass : baseClases) { result.append(QString::fromLatin1("((size_t) static_cast<const %1*>(class_ptr)) - base") .arg(baseClass->qualifiedCppName())); result.append(QString::fromLatin1("((size_t) static_cast<const %1*>((%2*)((void*)class_ptr))) - base") .arg(baseClass->qualifiedCppName(), metaClass->qualifiedCppName())); } - foreach (const AbstractMetaClass* baseClass, baseClases) + for (const AbstractMetaClass *baseClass : baseClases) result.append(getAncestorMultipleInheritance(baseClass)); } return result; @@ -3366,7 +3447,7 @@ QStringList CppGenerator::getAncestorMultipleInheritance(const AbstractMetaClass void CppGenerator::writeMultipleInheritanceInitializerFunction(QTextStream& s, const AbstractMetaClass* metaClass) { QString className = metaClass->qualifiedCppName(); - QStringList ancestors = getAncestorMultipleInheritance(metaClass); + const QStringList ancestors = getAncestorMultipleInheritance(metaClass); s << "static int mi_offsets[] = { "; for (int i = 0; i < ancestors.size(); i++) s << "-1, "; @@ -3382,7 +3463,7 @@ void CppGenerator::writeMultipleInheritanceInitializerFunction(QTextStream& s, c s << INDENT << "const " << className << "* class_ptr = reinterpret_cast<const " << className << "*>(cptr);" << endl; s << INDENT << "size_t base = (size_t) class_ptr;" << endl; - foreach (const QString &ancestor, ancestors) + for (const QString &ancestor : ancestors) s << INDENT << "offsets.insert(" << ancestor << ");" << endl; s << endl; @@ -3410,7 +3491,8 @@ void CppGenerator::writeSpecialCastFunction(QTextStream& s, const AbstractMetaCl s << "{\n"; s << INDENT << className << "* me = reinterpret_cast< ::" << className << "*>(obj);\n"; bool firstClass = true; - foreach (const AbstractMetaClass* baseClass, getAllAncestors(metaClass)) { + const AbstractMetaClassList &allAncestors = getAllAncestors(metaClass); + for (const AbstractMetaClass *baseClass : allAncestors) { s << INDENT << (!firstClass ? "else " : "") << "if (desiredType == reinterpret_cast<SbkObjectType*>(" << cpythonTypeNameExt(baseClass->typeEntry()) << "))\n"; Indentation indent(INDENT); s << INDENT << "return static_cast< ::" << baseClass->qualifiedCppName() << "*>(me);\n"; @@ -3528,10 +3610,11 @@ void CppGenerator::writeContainerConverterInitialization(QTextStream& s, const A writeAddPythonToCppConversion(s, converterObject(type), toCpp, isConv); } -void CppGenerator::writeExtendedConverterInitialization(QTextStream& s, const TypeEntry* externalType, const QList<const AbstractMetaClass*>& conversions) +void CppGenerator::writeExtendedConverterInitialization(QTextStream& s, const TypeEntry* externalType, + const QVector<const AbstractMetaClass*>& conversions) { s << INDENT << "// Extended implicit conversions for " << externalType->qualifiedTargetLangName() << '.' << endl; - foreach (const AbstractMetaClass* sourceClass, conversions) { + for (const AbstractMetaClass *sourceClass : conversions) { const QString converterVar = QLatin1String("reinterpret_cast<SbkObjectType *>(") + cppApiVariableName(externalType->targetLangPackage()) + QLatin1Char('[') + getTypeIndexVariableName(externalType) + QLatin1String("])"); @@ -3586,7 +3669,8 @@ bool CppGenerator::supportsSequenceProtocol(const AbstractMetaClass* metaClass) bool CppGenerator::shouldGenerateGetSetList(const AbstractMetaClass* metaClass) { - foreach (AbstractMetaField* f, metaClass->fields()) { + const AbstractMetaFieldList &fields = metaClass->fields(); + for (const AbstractMetaField *f : fields) { if (!f->isStatic()) return true; } @@ -3604,11 +3688,11 @@ void CppGenerator::writeClassDefinition(QTextStream &s, QString tp_hash(QLatin1Char('0')); QString tp_call = tp_hash; QString cppClassName = metaClass->qualifiedCppName(); - QString className = cpythonTypeName(metaClass); - className.remove(QRegExp(QLatin1String("_Type$"))); + const QString className = chopType(cpythonTypeName(metaClass)); QString baseClassName(QLatin1Char('0')); AbstractMetaFunctionList ctors; - foreach (AbstractMetaFunction* f, metaClass->queryFunctions(AbstractMetaClass::Constructors)) { + const AbstractMetaFunctionList &allCtors = metaClass->queryFunctions(AbstractMetaClass::Constructors); + for (AbstractMetaFunction *f : allCtors) { if (!f->isPrivate() && !f->isModifiedRemoved() && !classContext.forSmartPointer()) ctors.append(f); } @@ -3641,8 +3725,7 @@ void CppGenerator::writeClassDefinition(QTextStream &s, tp_dealloc = QLatin1String("&SbkDeallocQAppWrapper"); else tp_dealloc = QLatin1String("&SbkDeallocWrapper"); - // avoid constFirst to stay Qt 5.5 compatible - tp_init = (onlyPrivCtor || ctors.isEmpty()) ? QLatin1String("0") : cpythonFunctionName(ctors.first()); + tp_init = (onlyPrivCtor || ctors.isEmpty()) ? QLatin1String("0") : cpythonFunctionName(ctors.constFirst()); } QString tp_getattro(QLatin1Char('0')); @@ -3679,7 +3762,8 @@ void CppGenerator::writeClassDefinition(QTextStream &s, // search for special functions ShibokenGenerator::clearTpFuncs(); - foreach (AbstractMetaFunction* func, metaClass->functions()) { + const AbstractMetaFunctionList &funcs = metaClass->functions(); + for (AbstractMetaFunction *func : funcs) { if (m_tpFuncs.contains(func->name())) m_tpFuncs[func->name()] = cpythonFunctionName(func); } @@ -3788,11 +3872,7 @@ void CppGenerator::writeMappingMethods(QTextStream &s, const AbstractMetaClass *metaClass, GeneratorContext &context) { - - QMap<QString, QString> funcs; - - QHash< QString, QPair< QString, QString > >::const_iterator it = m_mappingProtocol.begin(); - for (; it != m_mappingProtocol.end(); ++it) { + for (auto it = m_mappingProtocol.cbegin(), end = m_mappingProtocol.cend(); it != end; ++it) { const AbstractMetaFunction* func = metaClass->findFunction(it.key()); if (!func) continue; @@ -3806,7 +3886,7 @@ void CppGenerator::writeMappingMethods(QTextStream &s, writeCppSelfDefinition(s, func, context); - const AbstractMetaArgument* lastArg = func->arguments().isEmpty() ? 0 : func->arguments().last(); + const AbstractMetaArgument* lastArg = func->arguments().isEmpty() ? 0 : func->arguments().constLast(); writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionAny, TypeSystem::TargetLangCode, func, lastArg); s << '}' << endl << endl; } @@ -3816,12 +3896,9 @@ void CppGenerator::writeSequenceMethods(QTextStream &s, const AbstractMetaClass *metaClass, GeneratorContext &context) { - - QMap<QString, QString> funcs; bool injectedCode = false; - QHash< QString, QPair< QString, QString > >::const_iterator it = m_sequenceProtocol.begin(); - for (; it != m_sequenceProtocol.end(); ++it) { + for (auto it = m_sequenceProtocol.cbegin(), end = m_sequenceProtocol.cend(); it != end; ++it) { const AbstractMetaFunction* func = metaClass->findFunction(it.key()); if (!func) continue; @@ -3836,7 +3913,7 @@ void CppGenerator::writeSequenceMethods(QTextStream &s, writeCppSelfDefinition(s, func, context); - const AbstractMetaArgument* lastArg = func->arguments().isEmpty() ? 0 : func->arguments().last(); + const AbstractMetaArgument* lastArg = func->arguments().isEmpty() ? 0 : func->arguments().constLast(); writeCodeSnips(s, snips,TypeSystem::CodeSnipPositionAny, TypeSystem::TargetLangCode, func, lastArg); s << '}' << endl << endl; } @@ -3900,7 +3977,7 @@ void CppGenerator::writeTypeAsMappingDefinition(QTextStream& s, const AbstractMe QString baseName = cpythonBaseName(metaClass); s << INDENT << "memset(&" << baseName << "_TypeAsMapping, 0, sizeof(PyMappingMethods));" << endl; - for (QHash<QString, QString>::const_iterator it = m_mpFuncs.cbegin(), end = m_mpFuncs.end(); it != end; ++it) { + for (auto it = m_mpFuncs.cbegin(), end = m_mpFuncs.cend(); it != end; ++it) { const QString &mpName = it.key(); if (funcs[mpName].isEmpty()) continue; @@ -3936,13 +4013,13 @@ void CppGenerator::writeTypeAsNumberDefinition(QTextStream& s, const AbstractMet nb.insert(QLatin1String("__ixor__"), QString()); nb.insert(QLatin1String("__ior__"), QString()); - QList<AbstractMetaFunctionList> opOverloads = + const QVector<AbstractMetaFunctionList> opOverloads = filterGroupedOperatorFunctions(metaClass, AbstractMetaClass::ArithmeticOp | AbstractMetaClass::LogicalOp | AbstractMetaClass::BitwiseOp); - foreach (const AbstractMetaFunctionList &opOverload, opOverloads) { + for (const AbstractMetaFunctionList &opOverload : opOverloads) { const AbstractMetaFunction* rfunc = opOverload[0]; QString opName = ShibokenGenerator::pythonOperatorFunctionName(rfunc); nb[opName] = cpythonFunctionName(rfunc); @@ -4001,8 +4078,7 @@ void CppGenerator::writeTpClearFunction(QTextStream& s, const AbstractMetaClass* void CppGenerator::writeCopyFunction(QTextStream &s, GeneratorContext &context) { const AbstractMetaClass *metaClass = context.metaClass(); - QString className = cpythonTypeName(metaClass); - className.remove(QRegExp(QLatin1String("_Type$"))); + const QString className = chopType(cpythonTypeName(metaClass)); s << "static PyObject* " << className << "___copy__(PyObject* " PYTHON_SELF_VAR ")" << endl; s << "{" << endl; writeCppSelfDefinition(s, context, false, true); @@ -4181,7 +4257,8 @@ void CppGenerator::writeRichCompareFunction(QTextStream &s, GeneratorContext &co s << INDENT << "switch (op) {" << endl; { Indentation indent(INDENT); - foreach (const AbstractMetaFunctionList &overloads, filterGroupedOperatorFunctions(metaClass, AbstractMetaClass::ComparisonOp)) { + const QVector<AbstractMetaFunctionList> &groupedFuncs = filterGroupedOperatorFunctions(metaClass, AbstractMetaClass::ComparisonOp); + for (const AbstractMetaFunctionList &overloads : groupedFuncs) { const AbstractMetaFunction* rfunc = overloads[0]; QString operatorId = ShibokenGenerator::pythonRichCompareOperatorId(rfunc); @@ -4193,15 +4270,16 @@ void CppGenerator::writeRichCompareFunction(QTextStream &s, GeneratorContext &co op = op.right(op.size() - QLatin1String("operator").size()); int alternativeNumericTypes = 0; - foreach (const AbstractMetaFunction* func, overloads) { + for (const AbstractMetaFunction *func : overloads) { if (!func->isStatic() && - ShibokenGenerator::isNumber(func->arguments()[0]->type()->typeEntry())) + ShibokenGenerator::isNumber(func->arguments().at(0)->type()->typeEntry())) alternativeNumericTypes++; } bool first = true; OverloadData overloadData(overloads, this); - foreach (OverloadData* od, overloadData.nextOverloadData()) { + const OverloadDataList &nextOverloads = overloadData.nextOverloadData(); + for (OverloadData *od : nextOverloads) { const AbstractMetaFunction* func = od->referenceFunction(); if (func->isStatic()) continue; @@ -4227,7 +4305,7 @@ void CppGenerator::writeRichCompareFunction(QTextStream &s, GeneratorContext &co // If the function is user added, use the inject code if (func->isUserAdded()) { CodeSnipList snips = func->injectedCodeSnips(); - writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionAny, TypeSystem::TargetLangCode, func, func->arguments().last()); + writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionAny, TypeSystem::TargetLangCode, func, func->arguments().constLast()); } else { QString expression = QString::fromLatin1("%1%2 %3 (%4" CPP_ARG0 ")") .arg(func->isPointerOperator() ? QLatin1String("&") : QString(), @@ -4308,7 +4386,7 @@ void CppGenerator::writeMethodDefinitionEntry(QTextStream& s, const AbstractMeta void CppGenerator::writeMethodDefinition(QTextStream& s, const AbstractMetaFunctionList overloads) { Q_ASSERT(!overloads.isEmpty()); - const AbstractMetaFunction* func = overloads.first(); + const AbstractMetaFunction* func = overloads.constFirst(); if (m_tpFuncs.contains(func->name())) return; @@ -4349,18 +4427,10 @@ void CppGenerator::writeSignatureInfo(QTextStream &s, const AbstractMetaFunction int idx = overloads.length() - 1; bool multiple = idx > 0; -// after merging, the #if may be removed! -#if QT_VERSION >= QT_VERSION_CHECK(5, 7, 0) for (const AbstractMetaFunction *f : overloads) { QStringList args; const AbstractMetaArgumentList &arguments = f->arguments(); - for (AbstractMetaArgument *arg : arguments) { -#else - foreach (const AbstractMetaFunction *f, overloads) { - QStringList args; - const AbstractMetaArgumentList &arguments = f->arguments(); - foreach (const AbstractMetaArgument *arg, arguments) { -#endif + for (const AbstractMetaArgument *arg : arguments) { QString strArg = resolveRetOrArgType(arg->type()); if (!arg->defaultValueExpression().isEmpty()) { strArg += QLatin1Char('='); @@ -4378,9 +4448,8 @@ void CppGenerator::writeSignatureInfo(QTextStream &s, const AbstractMetaFunction // now calculate the return type. s << funcName << '(' << args.join(QLatin1Char(',')) << ')'; AbstractMetaType *returnType = getTypeWithoutContainer(f->type()); - if (returnType) { + if (returnType) s << "->" << resolveRetOrArgType(returnType); - } s << endl; } } @@ -4390,7 +4459,7 @@ void CppGenerator::writeEnumsInitialization(QTextStream& s, AbstractMetaEnumList if (enums.isEmpty()) return; s << INDENT << "// Initialization of enums." << endl << endl; - foreach (const AbstractMetaEnum* cppEnum, enums) { + for (const AbstractMetaEnum *cppEnum : qAsConst(enums)) { if (cppEnum->isPrivate()) continue; writeEnumInitialization(s, cppEnum); @@ -4402,6 +4471,7 @@ void CppGenerator::writeEnumInitialization(QTextStream& s, const AbstractMetaEnu const AbstractMetaClass* enclosingClass = getProperEnclosingClassForEnum(cppEnum); const AbstractMetaClass* upper = enclosingClass ? enclosingClass->enclosingClass() : 0; bool hasUpperEnclosingClass = upper && upper->typeEntry()->codeGeneration() != TypeEntry::GenerateForSubclass; + const EnumTypeEntry *enumTypeEntry = cppEnum->typeEntry(); QString enclosingObjectVariable; if (enclosingClass) enclosingObjectVariable = QLatin1Char('&') + cpythonTypeName(enclosingClass); @@ -4414,14 +4484,17 @@ void CppGenerator::writeEnumInitialization(QTextStream& s, const AbstractMetaEnu s << (cppEnum->isAnonymous() ? "anonymous enum identified by enum value" : "enum"); s << " '" << cppEnum->name() << "'." << endl; + QString enumVarTypeObj; if (!cppEnum->isAnonymous()) { - FlagsTypeEntry* flags = cppEnum->typeEntry()->flags(); + FlagsTypeEntry* flags = enumTypeEntry->flags(); if (flags) { s << INDENT << cpythonTypeNameExt(flags) << " = PySide::QFlags::create(\"" << flags->flagsName() << "\", &" << cpythonEnumName(cppEnum) << "_as_number);" << endl; } - s << INDENT << cpythonTypeNameExt(cppEnum->typeEntry()) << " = Shiboken::Enum::"; + enumVarTypeObj = cpythonTypeNameExt(enumTypeEntry); + + s << INDENT << enumVarTypeObj << " = Shiboken::Enum::"; s << ((enclosingClass || hasUpperEnclosingClass) ? "createScopedEnum" : "createGlobalEnum"); s << '(' << enclosingObjectVariable << ',' << endl; { @@ -4441,8 +4514,9 @@ void CppGenerator::writeEnumInitialization(QTextStream& s, const AbstractMetaEnu } } - foreach (const AbstractMetaEnumValue* enumValue, cppEnum->values()) { - if (cppEnum->typeEntry()->isEnumValueRejected(enumValue->name())) + const AbstractMetaEnumValueList &enumValues = cppEnum->values(); + for (const AbstractMetaEnumValue *enumValue : enumValues) { + if (enumTypeEntry->isEnumValueRejected(enumValue->name())) continue; QString enumValueText; @@ -4450,12 +4524,16 @@ void CppGenerator::writeEnumInitialization(QTextStream& s, const AbstractMetaEnu enumValueText = QLatin1String("(long) "); if (cppEnum->enclosingClass()) enumValueText += cppEnum->enclosingClass()->qualifiedCppName() + QLatin1String("::"); + // Fully qualify the value which is required for C++ 11 enum classes. + if (!cppEnum->isAnonymous()) + enumValueText += cppEnum->name() + QLatin1String("::"); enumValueText += enumValue->name(); } else { enumValueText += QString::number(enumValue->value()); } - if (cppEnum->isAnonymous()) { + switch (enumTypeEntry->enumKind()) { + case EnumTypeEntry::AnonymousEnum: if (enclosingClass || hasUpperEnclosingClass) { s << INDENT << '{' << endl; { @@ -4478,15 +4556,27 @@ void CppGenerator::writeEnumInitialization(QTextStream& s, const AbstractMetaEnu s << INDENT << "return " << m_currentErrorCode << ';' << endl; } } - } else { + break; + case EnumTypeEntry::CEnum: { s << INDENT << "if (!Shiboken::Enum::"; s << ((enclosingClass || hasUpperEnclosingClass) ? "createScopedEnumItem" : "createGlobalEnumItem"); - s << '(' << cpythonTypeNameExt(cppEnum->typeEntry()) << ',' << endl; + s << '(' << enumVarTypeObj << ',' << endl; Indentation indent(INDENT); s << INDENT << enclosingObjectVariable << ", \"" << enumValue->name() << "\", "; s << enumValueText << "))" << endl; s << INDENT << "return " << m_currentErrorCode << ';' << endl; } + break; + case EnumTypeEntry::EnumClass: { + s << INDENT << "if (!Shiboken::Enum::createScopedEnumItem(" + << enumVarTypeObj << ',' << endl; + Indentation indent(INDENT); + s << INDENT << enumVarTypeObj<< ", \"" << enumValue->name() << "\", " + << enumValueText << "))" << endl + << INDENT << "return " << m_currentErrorCode << ';' << endl; + } + break; + } } writeEnumConverterInitialization(s, cppEnum); @@ -4500,10 +4590,12 @@ void CppGenerator::writeEnumInitialization(QTextStream& s, const AbstractMetaEnu void CppGenerator::writeSignalInitialization(QTextStream& s, const AbstractMetaClass* metaClass) { // Try to check something and print some warnings - foreach (const AbstractMetaFunction* cppSignal, metaClass->cppSignalFunctions()) { + const AbstractMetaFunctionList &signalFuncs = metaClass->cppSignalFunctions(); + for (const AbstractMetaFunction *cppSignal : signalFuncs) { if (cppSignal->declaringClass() != metaClass) continue; - foreach (AbstractMetaArgument* arg, cppSignal->arguments()) { + const AbstractMetaArgumentList &arguments = cppSignal->arguments(); + for (AbstractMetaArgument *arg : arguments) { AbstractMetaType* metaType = arg->type(); const QByteArray origType = QMetaObject::normalizedType(qPrintable(metaType->originalTypeDescription())); @@ -4704,9 +4796,8 @@ void CppGenerator::writeClassRegister(QTextStream &s, s << "// Multiple signatures have their index \"n:\" in front." << endl; s << "const char " << initFunctionName << "_SignaturesString[] = \"\"" << endl; QString line; - while (signatureStream.readLineInto(&line)) { + while (signatureStream.readLineInto(&line)) s << INDENT << '"' << line << "\\n\"" << endl; - } s << ';' << endl << endl; s << "void init_" << initFunctionName; s << "(PyObject* " << enclosingObjectVariable << ")" << endl; @@ -4747,7 +4838,7 @@ void CppGenerator::writeClassRegister(QTextStream &s, if (metaClass->baseClassNames().size() > 1) { s << INDENT << "PyObject* " << pyTypeBasesVariable << " = PyTuple_Pack(" << baseClasses.size() << ',' << endl; QStringList bases; - foreach (const AbstractMetaClass* base, baseClasses) + for (const AbstractMetaClass *base : baseClasses) bases << QLatin1String("(PyObject*)") + cpythonTypeNameExt(base->typeEntry()); Indentation indent(INDENT); QString separator; @@ -4842,7 +4933,8 @@ void CppGenerator::writeClassRegister(QTextStream &s, } AbstractMetaEnumList classEnums = metaClass->enums(); - foreach (AbstractMetaClass* innerClass, metaClass->innerClasses()) + const AbstractMetaClassList &innerClasses = metaClass->innerClasses(); + for (AbstractMetaClass *innerClass : innerClasses) lookForEnumsInClassesNotToBeGenerated(classEnums, innerClass); ErrorCode errorCode(QString::null); @@ -4852,7 +4944,8 @@ void CppGenerator::writeClassRegister(QTextStream &s, writeSignalInitialization(s, metaClass); // Write static fields - foreach (const AbstractMetaField* field, metaClass->fields()) { + const AbstractMetaFieldList &fields = metaClass->fields(); + for (const AbstractMetaField *field : fields) { if (!field->isStatic()) continue; s << INDENT << QLatin1String("PyDict_SetItemString(") + cpythonTypeName(metaClass) + QLatin1String(".super.ht_type.tp_dict, \""); @@ -4897,7 +4990,7 @@ void CppGenerator::writeInitQtMetaTypeFunctionBody(QTextStream &s, GeneratorCont const AbstractMetaClass* enclosingClass = metaClass->enclosingClass(); while (enclosingClass) { if (enclosingClass->typeEntry()->generateCode()) - nameVariants << (enclosingClass->name() + QLatin1String("::") + nameVariants.last()); + nameVariants << (enclosingClass->name() + QLatin1String("::") + nameVariants.constLast()); enclosingClass = enclosingClass->enclosingClass(); } @@ -4912,7 +5005,8 @@ void CppGenerator::writeInitQtMetaTypeFunctionBody(QTextStream &s, GeneratorCont bool canBeValue = false; if (!isObjectType(metaClass)) { // check if there's a empty ctor - foreach (AbstractMetaFunction* func, metaClass->functions()) { + const AbstractMetaFunctionList &funcs = metaClass->functions(); + for (AbstractMetaFunction *func : funcs) { if (func->isConstructor() && !func->arguments().count()) { canBeValue = true; break; @@ -4921,7 +5015,7 @@ void CppGenerator::writeInitQtMetaTypeFunctionBody(QTextStream &s, GeneratorCont } if (canBeValue) { - foreach (const QString &name, nameVariants) { + for (const QString &name : qAsConst(nameVariants)) { if (name == QLatin1String("iterator")) { qCWarning(lcShiboken).noquote().nospace() << QString::fromLatin1("%1:%2 FIXME:\n" @@ -4935,9 +5029,10 @@ void CppGenerator::writeInitQtMetaTypeFunctionBody(QTextStream &s, GeneratorCont } } - foreach (AbstractMetaEnum* metaEnum, metaClass->enums()) { + const AbstractMetaEnumList &enums = metaClass->enums(); + for (AbstractMetaEnum *metaEnum : enums) { if (!metaEnum->isPrivate() && !metaEnum->isAnonymous()) { - foreach (const QString &name, nameVariants) + for (const QString &name : qAsConst(nameVariants)) s << INDENT << "qRegisterMetaType< ::" << metaEnum->typeEntry()->qualifiedCppName() << " >(\"" << name << "::" << metaEnum->name() << "\");" << endl; if (metaEnum->typeEntry()->flags()) { @@ -4965,8 +5060,8 @@ void CppGenerator::writeTypeDiscoveryFunction(QTextStream& s, const AbstractMeta s << INDENT << "return cptr;" << endl; } } else if (metaClass->isPolymorphic()) { - AbstractMetaClassList ancestors = getAllAncestors(metaClass); - foreach (AbstractMetaClass* ancestor, ancestors) { + const AbstractMetaClassList &ancestors = getAllAncestors(metaClass); + for (AbstractMetaClass *ancestor : ancestors) { if (ancestor->baseClass()) continue; if (ancestor->isPolymorphic()) { @@ -5077,7 +5172,8 @@ void CppGenerator::writeGetattroFunction(QTextStream& s, GeneratorContext &conte } s << INDENT << '}' << endl; - foreach (const AbstractMetaFunction* func, getMethodsWithBothStaticAndNonStaticMethods(metaClass)) { + const AbstractMetaFunctionList &funcs = getMethodsWithBothStaticAndNonStaticMethods(metaClass); + for (const AbstractMetaFunction *func : funcs) { QString defName = cpythonMethodDefinitionName(func); s << INDENT << "static PyMethodDef non_static_" << defName << " = {" << endl; { @@ -5172,7 +5268,7 @@ bool CppGenerator::finishGeneration() const FunctionGroupMap &functionGroups = getFunctionGroups(); for (FunctionGroupMapIt it = functionGroups.cbegin(), end = functionGroups.cend(); it != end; ++it) { AbstractMetaFunctionList overloads; - foreach (AbstractMetaFunction* func, it.value()) { + for (AbstractMetaFunction *func : it.value()) { if (!func->isModifiedRemoved()) { overloads.append(func); if (func->typeEntry()) @@ -5203,7 +5299,7 @@ bool CppGenerator::finishGeneration() } const AbstractMetaClassList lst = classesTopologicalSorted(additionalDependencies); - foreach (const AbstractMetaClass* cls, lst) { + for (const AbstractMetaClass *cls : lst){ if (!shouldGenerate(cls)) continue; @@ -5219,7 +5315,8 @@ bool CppGenerator::finishGeneration() } // Initialize smart pointer types. - foreach (const AbstractMetaType *metaType, instantiatedSmartPointers()) { + const QVector<const AbstractMetaType *> &smartPtrs = instantiatedSmartPointers(); + for (const AbstractMetaType *metaType : smartPtrs) { GeneratorContext context(0, metaType, true); QString initFunctionName = getInitFunctionName(context); s_classInitDecl << "void init_" << initFunctionName << "(PyObject* module);" << endl; @@ -5255,13 +5352,14 @@ bool CppGenerator::finishGeneration() } s << "#include \"" << getModuleHeaderFileName() << '"' << endl << endl; - foreach (const Include& include, includes) + for (const Include &include : qAsConst(includes)) s << include; s << endl; // Global enums AbstractMetaEnumList globalEnums = this->globalEnums(); - foreach (const AbstractMetaClass* metaClass, classes()) { + const AbstractMetaClassList &classList = classes(); + for (const AbstractMetaClass *metaClass : classList) { const AbstractMetaClass* encClass = metaClass->enclosingClass(); if (encClass && encClass->typeEntry()->codeGeneration() != TypeEntry::GenerateForSubclass) continue; @@ -5273,13 +5371,13 @@ bool CppGenerator::finishGeneration() //Extra includes s << endl << "// Extra includes" << endl; - QList<Include> extraIncludes; + QVector<Include> extraIncludes; if (moduleEntry) extraIncludes = moduleEntry->extraIncludes(); - foreach (AbstractMetaEnum* cppEnum, globalEnums) + for (AbstractMetaEnum *cppEnum : qAsConst(globalEnums)) extraIncludes.append(cppEnum->typeEntry()->extraIncludes()); qSort(extraIncludes.begin(), extraIncludes.end()); - foreach (const Include& inc, extraIncludes) + for (const Include &inc : qAsConst(extraIncludes)) s << inc; s << endl; @@ -5334,7 +5432,7 @@ bool CppGenerator::finishGeneration() s << "// Enum definitions "; s << "------------------------------------------------------------" << endl; - foreach (const AbstractMetaEnum* cppEnum, globalEnums) { + for (const AbstractMetaEnum *cppEnum : qAsConst(globalEnums)) { if (cppEnum->isAnonymous() || cppEnum->isPrivate()) continue; writeEnumConverterFunctions(s, cppEnum); @@ -5350,10 +5448,10 @@ bool CppGenerator::finishGeneration() } } - QStringList requiredModules = typeDb->requiredTargetImports(); + const QStringList &requiredModules = typeDb->requiredTargetImports(); if (!requiredModules.isEmpty()) s << "// Required modules' type and converter arrays." << endl; - foreach (const QString& requiredModule, requiredModules) { + for (const QString &requiredModule : requiredModules) { s << "PyTypeObject** " << cppApiVariableName(requiredModule) << ';' << endl; s << "SbkConverter** " << convertersVariableName(requiredModule) << ';' << endl; } @@ -5367,7 +5465,7 @@ bool CppGenerator::finishGeneration() for (ExtendedConverterData::const_iterator it = extendedConverters.cbegin(), end = extendedConverters.cend(); it != end; ++it) { const TypeEntry *externalType = it.key(); s << "// Extended implicit conversions for " << externalType->qualifiedTargetLangName() << '.' << endl; - foreach (const AbstractMetaClass* sourceClass, extendedConverters[externalType]) { + for (const AbstractMetaClass *sourceClass : it.value()) { AbstractMetaType* sourceType = buildAbstractMetaTypeFromAbstractMetaClass(sourceClass); AbstractMetaType* targetType = buildAbstractMetaTypeFromTypeEntry(externalType); writePythonToCppConversionFunctions(s, sourceType, targetType); @@ -5375,10 +5473,10 @@ bool CppGenerator::finishGeneration() } } - QList<const CustomConversion*> typeConversions = getPrimitiveCustomConversions(); + const QVector<const CustomConversion *> &typeConversions = getPrimitiveCustomConversions(); if (!typeConversions.isEmpty()) { s << endl << "// Primitive Type converters." << endl << endl; - foreach (const CustomConversion* conversion, typeConversions) { + for (const CustomConversion *conversion : typeConversions) { s << "// C++ to Python conversion for type '" << conversion->ownerType()->qualifiedCppName() << "'." << endl; writeCppToPythonFunction(s, conversion); writeCustomConverterFunctions(s, conversion); @@ -5386,10 +5484,10 @@ bool CppGenerator::finishGeneration() s << endl; } - QList<const AbstractMetaType*> containers = instantiatedContainers(); + const QVector<const AbstractMetaType *> &containers = instantiatedContainers(); if (!containers.isEmpty()) { s << "// Container Type converters." << endl << endl; - foreach (const AbstractMetaType* container, containers) { + for (const AbstractMetaType *container : containers) { s << "// C++ to Python conversion for type '" << container->cppSignature() << "'." << endl; writeContainerConverterFunctions(s, container); } @@ -5426,7 +5524,7 @@ bool CppGenerator::finishGeneration() s << endl; } - foreach (const QString& requiredModule, typeDb->requiredTargetImports()) { + for (const QString& requiredModule : requiredModules) { s << INDENT << "{" << endl; { Indentation indentation(INDENT); @@ -5468,7 +5566,7 @@ bool CppGenerator::finishGeneration() if (!typeConversions.isEmpty()) { s << endl; - foreach (const CustomConversion* conversion, typeConversions) { + for (const CustomConversion *conversion : typeConversions) { writePrimitiveConverterInitialization(s, conversion); s << endl; } @@ -5476,7 +5574,7 @@ bool CppGenerator::finishGeneration() if (!containers.isEmpty()) { s << endl; - foreach (const AbstractMetaType* container, containers) { + for (const AbstractMetaType *container : containers) { writeContainerConverterInitialization(s, container); s << endl; } @@ -5493,7 +5591,8 @@ bool CppGenerator::finishGeneration() writeEnumsInitialization(s, globalEnums); s << INDENT << "// Register primitive types converters." << endl; - foreach(const PrimitiveTypeEntry* pte, primitiveTypes()) { + const PrimitiveTypeEntryList &primitiveTypeList = primitiveTypes(); + for (const PrimitiveTypeEntry *pte : primitiveTypeList) { if (!pte->generateCode() || !pte->isCppPrimitive()) continue; const TypeEntry *referencedType = pte->basicReferencedTypeEntry(); @@ -5534,7 +5633,7 @@ bool CppGenerator::finishGeneration() } if (usePySideExtensions()) { - foreach (AbstractMetaEnum* metaEnum, globalEnums) + for (AbstractMetaEnum *metaEnum : qAsConst(globalEnums)) if (!metaEnum->isAnonymous()) { s << INDENT << "qRegisterMetaType< ::" << metaEnum->typeEntry()->qualifiedCppName() << " >(\"" << metaEnum->name() << "\");" << endl; } @@ -5547,9 +5646,8 @@ bool CppGenerator::finishGeneration() s << "// Multiple signatures have their index \"n:\" in front." << endl; s << "const char " << moduleName() << "_SignaturesString[] = \"\"" << endl; QString line; - while (signatureStream.readLineInto(&line)) { + while (signatureStream.readLineInto(&line)) s << INDENT << '"' << line << "\\n\"" << endl; - } s << ';' << endl; // finish the rest of __signature__ initialization. s << INDENT << "FinishSignatureInitialization(module, " << moduleName() @@ -5693,7 +5791,7 @@ void CppGenerator::writeStdListWrapperMethods(QTextStream &s, GeneratorContext & s << INDENT << metaClass->qualifiedCppName() << "::iterator _item = " CPP_SELF_VAR "->begin();" << endl; s << INDENT << "for (Py_ssize_t pos = 0; pos < _i; pos++) _item++;" << endl; - const AbstractMetaType* itemType = metaClass->templateBaseClassInstantiations().first(); + const AbstractMetaType* itemType = metaClass->templateBaseClassInstantiations().constFirst(); s << INDENT << "return "; writeToPythonConversion(s, itemType, metaClass, QLatin1String("*_item")); diff --git a/sources/shiboken2/generator/shiboken2/cppgenerator.h b/sources/shiboken2/generator/shiboken2/cppgenerator.h index 4877a1694..cce1842ab 100644 --- a/sources/shiboken2/generator/shiboken2/cppgenerator.h +++ b/sources/shiboken2/generator/shiboken2/cppgenerator.h @@ -39,12 +39,12 @@ class CppGenerator : public ShibokenGenerator public: CppGenerator(); protected: - QString fileNamePrefix() const; - QString fileNameForContext(GeneratorContext &context) const; - QList<AbstractMetaFunctionList> filterGroupedOperatorFunctions(const AbstractMetaClass* metaClass, - uint query); - void generateClass(QTextStream& s, GeneratorContext &classContext); - bool finishGeneration(); + QString fileNamePrefix() const override; + QString fileNameForContext(GeneratorContext &context) const override; + QVector<AbstractMetaFunctionList> filterGroupedOperatorFunctions(const AbstractMetaClass* metaClass, + uint query); + void generateClass(QTextStream& s, GeneratorContext &classContext) override; + bool finishGeneration() override; private: void writeConstructorNative(QTextStream& s, const AbstractMetaFunction* func); @@ -291,7 +291,7 @@ private: void writeEnumConverterInitialization(QTextStream& s, const TypeEntry* enumType); void writeEnumConverterInitialization(QTextStream& s, const AbstractMetaEnum* metaEnum); void writeContainerConverterInitialization(QTextStream& s, const AbstractMetaType* type); - void writeExtendedConverterInitialization(QTextStream& s, const TypeEntry* externalType, const QList<const AbstractMetaClass*>& conversions); + void writeExtendedConverterInitialization(QTextStream& s, const TypeEntry* externalType, const QVector<const AbstractMetaClass*>& conversions); void writeParentChildManagement(QTextStream& s, const AbstractMetaFunction* func, bool userHeuristicForReturn); bool writeParentChildManagement(QTextStream& s, const AbstractMetaFunction* func, int argIndex, bool userHeuristicPolicy); diff --git a/sources/shiboken2/generator/shiboken2/headergenerator.cpp b/sources/shiboken2/generator/shiboken2/headergenerator.cpp index 7158c370b..a033cb69a 100644 --- a/sources/shiboken2/generator/shiboken2/headergenerator.cpp +++ b/sources/shiboken2/generator/shiboken2/headergenerator.cpp @@ -35,7 +35,6 @@ #include <QtCore/QDir> #include <QtCore/QTextStream> #include <QtCore/QVariant> -#include <QtCore/QRegExp> #include <QtCore/QDebug> QString HeaderGenerator::fileNamePrefix() const @@ -139,15 +138,15 @@ void HeaderGenerator::generateClass(QTextStream &s, GeneratorContext &classConte s << endl << '{' << endl << "public:" << endl; - bool hasVirtualFunction = false; - foreach (AbstractMetaFunction *func, filterFunctions(metaClass)) { - if (func->isVirtual()) - hasVirtualFunction = true; - writeFunction(s, func); + const AbstractMetaFunctionList &funcs = filterFunctions(metaClass); + for (AbstractMetaFunction *func : funcs) { + if ((func->attributes() & AbstractMetaAttributes::FinalCppMethod) == 0) + writeFunction(s, func); } if (avoidProtectedHack() && metaClass->hasProtectedFields()) { - foreach (AbstractMetaField* field, metaClass->fields()) { + const AbstractMetaFieldList &fields = metaClass->fields(); + for (AbstractMetaField *field : fields) { if (!field->isProtected()) continue; writeProtectedFieldAccessors(s, field); @@ -162,8 +161,6 @@ void HeaderGenerator::generateClass(QTextStream &s, GeneratorContext &classConte if (avoidProtectedHack() && metaClass->hasPrivateDestructor()) s << "// C++11: need to declare (unimplemented) destructor because " "the base class destructor is private." << endl; - if (metaClass->hasVirtualDestructor() || hasVirtualFunction) - s << "virtual "; s << '~' << wrapperName << "();" << endl; } @@ -172,8 +169,8 @@ void HeaderGenerator::generateClass(QTextStream &s, GeneratorContext &classConte if ((!avoidProtectedHack() || !metaClass->hasPrivateDestructor()) && usePySideExtensions() && metaClass->isQObject()) { s << "public:\n"; - s << INDENT << "virtual int qt_metacall(QMetaObject::Call call, int id, void** args);" << endl; - s << INDENT << "virtual void* qt_metacast(const char* _clname);" << endl; + s << INDENT << "int qt_metacall(QMetaObject::Call call, int id, void** args) override;" << endl; + s << INDENT << "void* qt_metacast(const char* _clname) override;" << endl; } if (m_inheritedOverloads.size()) { @@ -228,7 +225,8 @@ void HeaderGenerator::writeFunction(QTextStream& s, const AbstractMetaFunction* s << func->ownerClass()->qualifiedCppName() << "::"; s << func->originalName() << '('; QStringList args; - foreach (const AbstractMetaArgument* arg, func->arguments()) { + const AbstractMetaArgumentList &arguments = func->arguments(); + for (const AbstractMetaArgument *arg : arguments) { QString argName = arg->name(); const TypeEntry* enumTypeEntry = 0; if (arg->type()->isFlags()) @@ -244,8 +242,9 @@ void HeaderGenerator::writeFunction(QTextStream& s, const AbstractMetaFunction* } // pure virtual functions need a default implementation - if ((func->isPrivate() && !visibilityModifiedToPrivate(func)) - || (func->isModifiedRemoved() && !func->isAbstract())) + const bool notAbstract = !func->isAbstract(); + if ((func->isPrivate() && notAbstract && !visibilityModifiedToPrivate(func)) + || (func->isModifiedRemoved() && notAbstract)) return; if (avoidProtectedHack() && func->ownerClass()->hasPrivateDestructor() @@ -256,15 +255,18 @@ void HeaderGenerator::writeFunction(QTextStream& s, const AbstractMetaFunction* s << INDENT; Options virtualOption = Generator::OriginalTypeDescription; - if (func->isVirtual() || func->isAbstract()) - s << "virtual "; - else if (!func->hasSignatureModifications()) + const bool virtualFunc = func->isVirtual() || func->isAbstract(); + if (!virtualFunc && !func->hasSignatureModifications()) virtualOption = Generator::NoOption; - s << functionSignature(func, QString(), QString(), virtualOption) << ';' << endl; + s << functionSignature(func, QString(), QString(), virtualOption); + if (virtualFunc) + s << " override"; + s << ';' << endl; // Check if this method hide other methods in base classes - foreach (const AbstractMetaFunction* f, func->ownerClass()->functions()) { + const AbstractMetaFunctionList &ownerFuncs = func->ownerClass()->functions(); + for (const AbstractMetaFunction *f : ownerFuncs) { if (f != func && !f->isConstructor() && !f->isPrivate() @@ -317,7 +319,8 @@ void HeaderGenerator::writeTypeIndexDefine(QTextStream& s, const AbstractMetaCla if (!metaClass->typeEntry()->generateCode()) return; writeTypeIndexDefineLine(s, metaClass->typeEntry()); - foreach (const AbstractMetaEnum* metaEnum, metaClass->enums()) { + const AbstractMetaEnumList &enums = metaClass->enums(); + for (const AbstractMetaEnum *metaEnum : enums) { if (metaEnum->isPrivate()) continue; writeTypeIndexDefineLine(s, metaEnum->typeEntry()); @@ -341,18 +344,20 @@ bool HeaderGenerator::finishGeneration() macrosStream << "// Type indices" << endl; AbstractMetaEnumList globalEnums = this->globalEnums(); - foreach (const AbstractMetaClass* metaClass, classes()) { + const AbstractMetaClassList &classList = classes(); + for (const AbstractMetaClass *metaClass : classList) { writeTypeIndexDefine(macrosStream, metaClass); lookForEnumsInClassesNotToBeGenerated(globalEnums, metaClass); } - foreach (const AbstractMetaEnum* metaEnum, globalEnums) + for (const AbstractMetaEnum *metaEnum : qAsConst(globalEnums)) writeTypeIndexDefineLine(macrosStream, metaEnum->typeEntry()); // Write the smart pointer define indexes. int smartPointerCountIndex = getMaxTypeIndex(); int smartPointerCount = 0; - foreach (const AbstractMetaType *metaType, instantiatedSmartPointers()) { + const QVector<const AbstractMetaType *> &instantiatedSmartPtrs = instantiatedSmartPointers(); + for (const AbstractMetaType *metaType : instantiatedSmartPtrs) { QString variableName = getTypeIndexVariableName(metaType); macrosStream << "#define "; macrosStream.setFieldWidth(60); @@ -378,9 +383,9 @@ bool HeaderGenerator::finishGeneration() // TODO-CONVERTER ------------------------------------------------------------------------------ // Using a counter would not do, a fix must be made to APIExtractor's getTypeIndex(). macrosStream << "// Converter indices" << endl; - QList<const PrimitiveTypeEntry*> primitives = primitiveTypes(); + const PrimitiveTypeEntryList &primitives = primitiveTypes(); int pCount = 0; - foreach (const PrimitiveTypeEntry* ptype, primitives) { + for (const PrimitiveTypeEntry *ptype : primitives) { /* Note: do not generate indices for typedef'd primitive types * as they'll use the primitive type converters instead, so we * don't need to create any other. @@ -391,7 +396,8 @@ bool HeaderGenerator::finishGeneration() _writeTypeIndexDefineLine(macrosStream, getTypeIndexVariableName(ptype), pCount++); } - foreach (const AbstractMetaType* container, instantiatedContainers()) { + const QVector<const AbstractMetaType *> &containers = instantiatedContainers(); + for (const AbstractMetaType *container : containers) { //_writeTypeIndexDefineLine(macrosStream, getTypeIndexVariableName(container), pCount); // DEBUG QString variableName = getTypeIndexVariableName(container); @@ -412,7 +418,7 @@ bool HeaderGenerator::finishGeneration() // TODO-CONVERTER ------------------------------------------------------------------------------ macrosStream << "// Macros for type check" << endl; - foreach (const AbstractMetaEnum* cppEnum, globalEnums) { + for (const AbstractMetaEnum *cppEnum : qAsConst(globalEnums)) { if (cppEnum->isAnonymous() || cppEnum->isPrivate()) continue; includes << cppEnum->typeEntry()->include(); @@ -420,7 +426,7 @@ bool HeaderGenerator::finishGeneration() writeSbkTypeFunction(typeFunctions, cppEnum); } - foreach (AbstractMetaClass* metaClass, classes()) { + for (AbstractMetaClass *metaClass : classList) { if (!shouldGenerate(metaClass)) continue; @@ -428,7 +434,8 @@ bool HeaderGenerator::finishGeneration() const TypeEntry* classType = metaClass->typeEntry(); includes << classType->include(); - foreach (const AbstractMetaEnum* cppEnum, metaClass->enums()) { + const AbstractMetaEnumList &enums = metaClass->enums(); + for (const AbstractMetaEnum *cppEnum : enums) { if (cppEnum->isAnonymous() || cppEnum->isPrivate()) continue; EnumTypeEntry* enumType = cppEnum->typeEntry(); @@ -441,7 +448,7 @@ bool HeaderGenerator::finishGeneration() writeSbkTypeFunction(typeFunctions, metaClass); } - foreach (const AbstractMetaType *metaType, instantiatedSmartPointers()) { + for (const AbstractMetaType *metaType : instantiatedSmartPtrs) { const TypeEntry *classType = metaType->typeEntry(); includes << classType->include(); writeSbkTypeFunction(typeFunctions, metaType); @@ -477,25 +484,27 @@ bool HeaderGenerator::finishGeneration() QStringList requiredTargetImports = TypeDatabase::instance()->requiredTargetImports(); if (!requiredTargetImports.isEmpty()) { s << "// Module Includes" << endl; - foreach (const QString& requiredModule, requiredTargetImports) + for (const QString &requiredModule : qAsConst(requiredTargetImports)) s << "#include <" << getModuleHeaderFileName(requiredModule) << ">" << endl; s << endl; } s << "// Binded library includes" << endl; - foreach (const Include& include, includes) + for (const Include &include : qAsConst(includes)) s << include; if (!primitiveTypes().isEmpty()) { s << "// Conversion Includes - Primitive Types" << endl; - foreach (const PrimitiveTypeEntry* ptype, primitiveTypes()) + const PrimitiveTypeEntryList &primitiveTypeList = primitiveTypes(); + for (const PrimitiveTypeEntry *ptype : primitiveTypeList) s << ptype->include(); s << endl; } if (!containerTypes().isEmpty()) { s << "// Conversion Includes - Container Types" << endl; - foreach (const ContainerTypeEntry* ctype, containerTypes()) + const ContainerTypeEntryList &containerTypeList = containerTypes(); + for (const ContainerTypeEntry *ctype : containerTypeList) s << ctype->include(); s << endl; } @@ -560,13 +569,14 @@ void HeaderGenerator::writeSbkTypeFunction(QTextStream &s, const AbstractMetaTyp void HeaderGenerator::writeInheritedOverloads(QTextStream& s) { - foreach (const AbstractMetaFunction* func, m_inheritedOverloads) { + for (const AbstractMetaFunction *func : qAsConst(m_inheritedOverloads)) { s << INDENT << "inline "; s << functionSignature(func, QString(), QString(), Generator::EnumAsInts|Generator::OriginalTypeDescription) << " { "; s << (func->type() ? "return " : ""); s << func->ownerClass()->qualifiedCppName() << "::" << func->originalName() << '('; QStringList args; - foreach (const AbstractMetaArgument* arg, func->arguments()) { + const AbstractMetaArgumentList &arguments = func->arguments(); + for (const AbstractMetaArgument *arg : arguments) { QString argName = arg->name(); const TypeEntry* enumTypeEntry = 0; if (arg->type()->isFlags()) diff --git a/sources/shiboken2/generator/shiboken2/headergenerator.h b/sources/shiboken2/generator/shiboken2/headergenerator.h index 72dcbf69f..d9dc8ffe8 100644 --- a/sources/shiboken2/generator/shiboken2/headergenerator.h +++ b/sources/shiboken2/generator/shiboken2/headergenerator.h @@ -41,12 +41,12 @@ class AbstractMetaFunction; class HeaderGenerator : public ShibokenGenerator { public: - QMap<QString, QString> options() const { return QMap<QString, QString>(); } + OptionDescriptions options() const override { return OptionDescriptions(); } protected: - QString fileNamePrefix() const; - QString fileNameForContext(GeneratorContext &context) const; - void generateClass(QTextStream& s, GeneratorContext &classContext); - bool finishGeneration(); + QString fileNamePrefix() const override; + QString fileNameForContext(GeneratorContext &context) const override; + void generateClass(QTextStream& s, GeneratorContext &classContext) override; + bool finishGeneration() override; private: void writeCopyCtor(QTextStream &s, const AbstractMetaClass* metaClass) const; diff --git a/sources/shiboken2/generator/shiboken2/overloaddata.cpp b/sources/shiboken2/generator/shiboken2/overloaddata.cpp index 8731fe911..3340ee957 100644 --- a/sources/shiboken2/generator/shiboken2/overloaddata.cpp +++ b/sources/shiboken2/generator/shiboken2/overloaddata.cpp @@ -53,7 +53,8 @@ static QString getTypeName(const AbstractMetaType* type) QString typeName = typeEntry->name(); if (typeEntry->isContainer()) { QStringList types; - foreach (const AbstractMetaType* cType, type->instantiations()) { + const AbstractMetaTypeList &instantiations = type->instantiations(); + for (const AbstractMetaType *cType : instantiations) { const TypeEntry *typeEntry = getReferencedTypeEntry(cType->typeEntry()); types << typeEntry->name(); } @@ -93,7 +94,7 @@ static bool typesAreEqual(const AbstractMetaType* typeA, const AbstractMetaType* */ struct OverloadSortData { - OverloadSortData() : counter(0) {}; + OverloadSortData() : counter(0) {} /** * Adds a typeName into the type map without associating it with @@ -141,10 +142,11 @@ static QString getImplicitConversionTypeName(const AbstractMetaType* containerTy else if (function->isConversionOperator()) impConv = function->ownerClass()->typeEntry()->name(); else - impConv = getTypeName(function->arguments().first()->type()); + impConv = getTypeName(function->arguments().constFirst()->type()); QStringList types; - foreach (const AbstractMetaType* otherType, containerType->instantiations()) + const AbstractMetaTypeList &instantiations = containerType->instantiations(); + for (const AbstractMetaType *otherType : instantiations) types << (otherType == instantiation ? impConv : getTypeName(otherType)); const ContainerTypeEntry* containerTypeEntry = dynamic_cast<const ContainerTypeEntry*>(containerType->typeEntry()); @@ -153,7 +155,7 @@ static QString getImplicitConversionTypeName(const AbstractMetaType* containerTy } static QString msgCyclicDependency(const QString &funcName, const QString &graphName, - const QList<const AbstractMetaFunction *> &involvedConversions) + const OverloadData::MetaFunctionList &involvedConversions) { QString result; QTextStream str(&result); @@ -209,7 +211,7 @@ void OverloadData::sortNextOverloads() << QLatin1String("long"); // sort the children overloads - foreach(OverloadData *ov, m_nextOverloadData) + for (OverloadData *ov : qAsConst(m_nextOverloadData)) ov->sortNextOverloads(); if (m_nextOverloadData.size() <= 1) @@ -218,7 +220,7 @@ void OverloadData::sortNextOverloads() // Populates the OverloadSortData object containing map and reverseMap, to map type names to ids, // these ids will be used by the topological sort algorithm, because is easier and faster to work // with graph sorting using integers. - foreach(OverloadData* ov, m_nextOverloadData) { + for (OverloadData *ov : qAsConst(m_nextOverloadData)) { sortData.mapType(ov); const QString typeName(getTypeName(ov)); @@ -240,7 +242,8 @@ void OverloadData::sortNextOverloads() qstringIndex = sortData.lastProcessedItemId(); } - foreach (const AbstractMetaType* instantiation, ov->argType()->instantiations()) { + const AbstractMetaTypeList &instantiations = ov->argType()->instantiations(); + for (const AbstractMetaType *instantiation : instantiations) { // Add dependencies for type instantiation of container. QString typeName = getTypeName(instantiation); sortData.mapType(typeName); @@ -251,10 +254,11 @@ void OverloadData::sortNextOverloads() // as Point must come before the PointF instantiation, or else list<Point> will never // be called. In the case of primitive types, list<double> must come before list<int>. if (instantiation->isPrimitive() && (signedIntegerPrimitives.contains(instantiation->name()))) { - foreach (const QString& primitive, nonIntegerPrimitives) + for (const QString &primitive : qAsConst(nonIntegerPrimitives)) sortData.mapType(getImplicitConversionTypeName(ov->argType(), instantiation, 0, primitive)); } else { - foreach (const AbstractMetaFunction* function, m_generator->implicitConversions(instantiation)) + const AbstractMetaFunctionList &funcs = m_generator->implicitConversions(instantiation); + for (const AbstractMetaFunction *function : funcs) sortData.mapType(getImplicitConversionTypeName(ov->argType(), instantiation, function)); } } @@ -287,20 +291,21 @@ void OverloadData::sortNextOverloads() QStringList classesWithIntegerImplicitConversion; - QList<const AbstractMetaFunction *> involvedConversions; + MetaFunctionList involvedConversions; - foreach(OverloadData* ov, m_nextOverloadData) { + for (OverloadData *ov : qAsConst(m_nextOverloadData)) { const AbstractMetaType* targetType = ov->argType(); const QString targetTypeEntryName(getTypeName(ov)); int targetTypeId = sortData.map[targetTypeEntryName]; // Process implicit conversions - foreach(AbstractMetaFunction* function, m_generator->implicitConversions(targetType)) { + const AbstractMetaFunctionList &functions = m_generator->implicitConversions(targetType); + for (AbstractMetaFunction *function : functions) { QString convertibleType; if (function->isConversionOperator()) convertibleType = function->ownerClass()->typeEntry()->name(); else - convertibleType = getTypeName(function->arguments().first()->type()); + convertibleType = getTypeName(function->arguments().constFirst()->type()); if (convertibleType == QLatin1String("int") || convertibleType == QLatin1String("unsigned int")) classesWithIntegerImplicitConversion << targetTypeEntryName; @@ -318,9 +323,10 @@ void OverloadData::sortNextOverloads() } // Process inheritance relationships - if (targetType->isValue() || targetType->isObject()) { + if (targetType->isValue() || targetType->isObject() || targetType->isQObject()) { const AbstractMetaClass *metaClass = AbstractMetaClass::findClass(m_generator->classes(), targetType->typeEntry()); - foreach (const AbstractMetaClass* ancestor, m_generator->getAllAncestors(metaClass)) { + const AbstractMetaClassList &ancestors = m_generator->getAllAncestors(metaClass); + for (const AbstractMetaClass *ancestor : ancestors) { QString ancestorTypeName = ancestor->typeEntry()->name(); if (!sortData.map.contains(ancestorTypeName)) continue; @@ -331,7 +337,8 @@ void OverloadData::sortNextOverloads() } // Process template instantiations - foreach (const AbstractMetaType* instantiation, targetType->instantiations()) { + const AbstractMetaTypeList &instantiations = targetType->instantiations(); + for (const AbstractMetaType *instantiation : instantiations) { if (sortData.map.contains(getTypeName(instantiation))) { int convertible = sortData.map[getTypeName(instantiation)]; @@ -339,14 +346,15 @@ void OverloadData::sortNextOverloads() graph.addEdge(convertible, targetTypeId); if (instantiation->isPrimitive() && (signedIntegerPrimitives.contains(instantiation->name()))) { - foreach (const QString& primitive, nonIntegerPrimitives) { + for (const QString &primitive : qAsConst(nonIntegerPrimitives)) { QString convertibleTypeName = getImplicitConversionTypeName(ov->argType(), instantiation, 0, primitive); if (!graph.containsEdge(targetTypeId, sortData.map[convertibleTypeName])) // Avoid cyclic dependency. graph.addEdge(sortData.map[convertibleTypeName], targetTypeId); } } else { - foreach (const AbstractMetaFunction* function, m_generator->implicitConversions(instantiation)) { + const AbstractMetaFunctionList &funcs = m_generator->implicitConversions(instantiation); + for (const AbstractMetaFunction *function : funcs) { QString convertibleTypeName = getImplicitConversionTypeName(ov->argType(), instantiation, function); if (!graph.containsEdge(targetTypeId, sortData.map[convertibleTypeName])) { // Avoid cyclic dependency. graph.addEdge(sortData.map[convertibleTypeName], targetTypeId); @@ -396,22 +404,22 @@ void OverloadData::sortNextOverloads() if (sortData.map.contains(QLatin1String("QString")) && sortData.map.contains(QLatin1String("QByteArray"))) graph.addEdge(sortData.map[QLatin1String("QString")], sortData.map[QLatin1String("QByteArray")]); - foreach(OverloadData* ov, m_nextOverloadData) { + for (OverloadData *ov : qAsConst(m_nextOverloadData)) { const AbstractMetaType* targetType = ov->argType(); if (!targetType->isEnum()) continue; QString targetTypeEntryName = getTypeName(targetType); // Enum values must precede types implicitly convertible from "int" or "unsigned int". - foreach (const QString& implicitFromInt, classesWithIntegerImplicitConversion) + for (const QString &implicitFromInt : qAsConst(classesWithIntegerImplicitConversion)) graph.addEdge(sortData.map[targetTypeEntryName], sortData.map[implicitFromInt]); } // Special case for double(int i) (not tracked by m_generator->implicitConversions - foreach (const QString& signedIntegerName, signedIntegerPrimitives) { + for (const QString &signedIntegerName : qAsConst(signedIntegerPrimitives)) { if (sortData.map.contains(signedIntegerName)) { - foreach (const QString& nonIntegerName, nonIntegerPrimitives) { + for (const QString &nonIntegerName : qAsConst(nonIntegerPrimitives)) { if (sortData.map.contains(nonIntegerName)) graph.addEdge(sortData.map[nonIntegerName], sortData.map[signedIntegerName]); } @@ -419,7 +427,7 @@ void OverloadData::sortNextOverloads() } // sort the overloads topologically based on the dependency graph. - QLinkedList<int> unmappedResult = graph.topologicalSort(); + const QLinkedList<int> unmappedResult = graph.topologicalSort(); if (unmappedResult.isEmpty()) { QString funcName = referenceFunction()->name(); if (referenceFunction()->ownerClass()) @@ -427,16 +435,15 @@ void OverloadData::sortNextOverloads() // Dump overload graph QString graphName = QDir::tempPath() + QLatin1Char('/') + funcName + QLatin1String(".dot"); - QHash<QString, int>::const_iterator it = sortData.map.begin(); QHash<int, QString> nodeNames; - for (; it != sortData.map.end(); ++it) + for (auto it = sortData.map.cbegin(), end = sortData.map.cend(); it != end; ++it) nodeNames.insert(it.value(), it.key()); graph.dumpDot(nodeNames, graphName); qCWarning(lcShiboken).noquote() << qPrintable(msgCyclicDependency(funcName, graphName, involvedConversions)); } m_nextOverloadData.clear(); - foreach(int i, unmappedResult) { + for (int i : unmappedResult) { if (!sortData.reverseMap[i]) continue; m_nextOverloadData << sortData.reverseMap[i]; @@ -464,7 +471,7 @@ OverloadData::OverloadData(const AbstractMetaFunctionList& overloads, const Shib : m_minArgs(256), m_maxArgs(0), m_argPos(-1), m_argType(0), m_headOverloadData(this), m_previousOverloadData(0), m_generator(generator) { - foreach (const AbstractMetaFunction* func, overloads) { + for (const AbstractMetaFunction *func : overloads) { m_overloads.append(func); int argSize = func->arguments().size() - numberOfRemovedArguments(func); if (m_minArgs > argSize) @@ -472,7 +479,8 @@ OverloadData::OverloadData(const AbstractMetaFunctionList& overloads, const Shib else if (m_maxArgs < argSize) m_maxArgs = argSize; OverloadData* currentOverloadData = this; - foreach (const AbstractMetaArgument* arg, func->arguments()) { + const AbstractMetaArgumentList &arguments = func->arguments(); + for (const AbstractMetaArgument *arg : arguments) { if (func->argumentRemoved(arg->argumentIndex() + 1)) continue; currentOverloadData = currentOverloadData->addOverloadData(func, arg); @@ -512,7 +520,7 @@ void OverloadData::addOverload(const AbstractMetaFunction* func) for (int i = 0; m_headOverloadData->m_minArgs > 0 && i < origNumArgs; i++) { if (func->argumentRemoved(i + 1)) continue; - if (!ShibokenGenerator::getDefaultValue(func, func->arguments()[i]).isEmpty()) { + if (!ShibokenGenerator::getDefaultValue(func, func->arguments().at(i)).isEmpty()) { int fixedArgIndex = i - removed; if (fixedArgIndex < m_headOverloadData->m_minArgs) m_headOverloadData->m_minArgs = fixedArgIndex; @@ -528,7 +536,7 @@ OverloadData* OverloadData::addOverloadData(const AbstractMetaFunction* func, const AbstractMetaType* argType = arg->type(); OverloadData* overloadData = 0; if (!func->isOperatorOverload()) { - foreach (OverloadData* tmp, m_nextOverloadData) { + for (OverloadData *tmp : qAsConst(m_nextOverloadData)) { // TODO: 'const char *', 'char *' and 'char' will have the same TypeEntry? // If an argument have a type replacement, then we should create a new overloaddata @@ -560,7 +568,7 @@ OverloadData* OverloadData::addOverloadData(const AbstractMetaFunction* func, QStringList OverloadData::returnTypes() const { QSet<QString> retTypes; - foreach (const AbstractMetaFunction* func, m_overloads) { + for (const AbstractMetaFunction *func : m_overloads) { if (!func->typeReplaced(0).isEmpty()) retTypes << func->typeReplaced(0); else if (func->type() && !func->argumentRemoved(0)) @@ -579,9 +587,9 @@ bool OverloadData::hasNonVoidReturnType() const bool OverloadData::hasVarargs() const { - foreach (const AbstractMetaFunction* func, m_overloads) { + for (const AbstractMetaFunction *func : m_overloads) { AbstractMetaArgumentList args = func->arguments(); - if (args.size() > 1 && args.last()->type()->isVarargs()) + if (args.size() > 1 && args.constLast()->type()->isVarargs()) return true; } return false; @@ -589,7 +597,7 @@ bool OverloadData::hasVarargs() const bool OverloadData::hasAllowThread() const { - foreach (const AbstractMetaFunction* func, m_overloads) { + for (const AbstractMetaFunction *func : m_overloads) { if (func->allowThread()) return true; } @@ -598,7 +606,7 @@ bool OverloadData::hasAllowThread() const bool OverloadData::hasStaticFunction(const AbstractMetaFunctionList& overloads) { - foreach (const AbstractMetaFunction* func, overloads) { + for (const AbstractMetaFunction *func : qAsConst(overloads)) { if (func->isStatic()) return true; } @@ -607,7 +615,7 @@ bool OverloadData::hasStaticFunction(const AbstractMetaFunctionList& overloads) bool OverloadData::hasStaticFunction() const { - foreach (const AbstractMetaFunction* func, m_overloads) { + for (const AbstractMetaFunction *func : m_overloads) { if (func->isStatic()) return true; } @@ -616,7 +624,7 @@ bool OverloadData::hasStaticFunction() const bool OverloadData::hasInstanceFunction(const AbstractMetaFunctionList& overloads) { - foreach (const AbstractMetaFunction* func, overloads) { + for (const AbstractMetaFunction *func : qAsConst(overloads)) { if (!func->isStatic()) return true; } @@ -625,7 +633,7 @@ bool OverloadData::hasInstanceFunction(const AbstractMetaFunctionList& overloads bool OverloadData::hasInstanceFunction() const { - foreach (const AbstractMetaFunction* func, m_overloads) { + for (const AbstractMetaFunction *func : m_overloads) { if (!func->isStatic()) return true; } @@ -644,7 +652,7 @@ bool OverloadData::hasStaticAndInstanceFunctions() const const AbstractMetaFunction* OverloadData::referenceFunction() const { - return m_overloads.first(); + return m_overloads.constFirst(); } const AbstractMetaArgument* OverloadData::argument(const AbstractMetaFunction* func) const @@ -661,7 +669,7 @@ const AbstractMetaArgument* OverloadData::argument(const AbstractMetaFunction* f argPos++; } - return func->arguments()[m_argPos + removed]; + return func->arguments().at(m_argPos + removed); } OverloadDataList OverloadData::overloadDataOnPosition(OverloadData* overloadData, int argPos) const @@ -670,7 +678,8 @@ OverloadDataList OverloadData::overloadDataOnPosition(OverloadData* overloadData if (overloadData->argPos() == argPos) { overloadDataList.append(overloadData); } else if (overloadData->argPos() < argPos) { - foreach (OverloadData* pd, overloadData->nextOverloadData()) + const OverloadDataList &data = overloadData->nextOverloadData(); + for (OverloadData *pd : data) overloadDataList += overloadDataOnPosition(pd, argPos); } return overloadDataList; @@ -685,7 +694,7 @@ OverloadDataList OverloadData::overloadDataOnPosition(int argPos) const bool OverloadData::nextArgumentHasDefaultValue() const { - foreach (OverloadData* overloadData, m_nextOverloadData) { + for (OverloadData *overloadData : m_nextOverloadData) { if (overloadData->getFunctionWithDefaultValue()) return true; } @@ -698,7 +707,8 @@ static OverloadData* _findNextArgWithDefault(OverloadData* overloadData) return overloadData; OverloadData* result = 0; - foreach (OverloadData* odata, overloadData->nextOverloadData()) { + const OverloadDataList &data = overloadData->nextOverloadData(); + for (OverloadData *odata : data) { OverloadData* tmp = _findNextArgWithDefault(odata); if (!result || (tmp && result->argPos() > tmp->argPos())) result = tmp; @@ -713,20 +723,20 @@ OverloadData* OverloadData::findNextArgWithDefault() bool OverloadData::isFinalOccurrence(const AbstractMetaFunction* func) const { - foreach (const OverloadData* pd, m_nextOverloadData) { + for (const OverloadData *pd : m_nextOverloadData) { if (pd->overloads().contains(func)) return false; } return true; } -QList<const AbstractMetaFunction*> OverloadData::overloadsWithoutRepetition() const +OverloadData::MetaFunctionList OverloadData::overloadsWithoutRepetition() const { - QList<const AbstractMetaFunction*> overloads = m_overloads; - foreach (const AbstractMetaFunction* func, m_overloads) { + MetaFunctionList overloads = m_overloads; + for (const AbstractMetaFunction *func : m_overloads) { if (func->minimalSignature().endsWith(QLatin1String("const"))) continue; - foreach (const AbstractMetaFunction* f, overloads) { + for (const AbstractMetaFunction *f : qAsConst(overloads)) { if ((func->minimalSignature() + QLatin1String("const")) == f->minimalSignature()) { overloads.removeOne(f); break; @@ -738,23 +748,23 @@ QList<const AbstractMetaFunction*> OverloadData::overloadsWithoutRepetition() co const AbstractMetaFunction* OverloadData::getFunctionWithDefaultValue() const { - foreach (const AbstractMetaFunction* func, m_overloads) { + for (const AbstractMetaFunction *func : m_overloads) { int removedArgs = 0; for (int i = 0; i <= m_argPos + removedArgs; i++) { if (func->argumentRemoved(i + 1)) removedArgs++; } - if (!ShibokenGenerator::getDefaultValue(func, func->arguments()[m_argPos + removedArgs]).isEmpty()) + if (!ShibokenGenerator::getDefaultValue(func, func->arguments().at(m_argPos + removedArgs)).isEmpty()) return func; } return 0; } -QList<int> OverloadData::invalidArgumentLengths() const +QVector<int> OverloadData::invalidArgumentLengths() const { QSet<int> validArgLengths; - foreach (const AbstractMetaFunction* func, m_headOverloadData->m_overloads) { + for (const AbstractMetaFunction *func : qAsConst(m_headOverloadData->m_overloads)) { const AbstractMetaArgumentList args = func->arguments(); int offset = 0; for (int i = 0; i < args.size(); ++i) { @@ -768,7 +778,7 @@ QList<int> OverloadData::invalidArgumentLengths() const validArgLengths << args.size() - offset; } - QList<int> invalidArgLengths; + QVector<int> invalidArgLengths; for (int i = minArgs() + 1; i < maxArgs(); i++) { if (!validArgLengths.contains(i)) invalidArgLengths.append(i); @@ -811,7 +821,7 @@ QPair<int, int> OverloadData::getMinMaxArguments(const AbstractMetaFunctionList& if (func->argumentRemoved(j + 1)) continue; int fixedArgIndex = j - removed; - if (fixedArgIndex < minArgs && !ShibokenGenerator::getDefaultValue(func, func->arguments()[j]).isEmpty()) + if (fixedArgIndex < minArgs && !ShibokenGenerator::getDefaultValue(func, func->arguments().at(j)).isEmpty()) minArgs = fixedArgIndex; } } @@ -821,7 +831,7 @@ QPair<int, int> OverloadData::getMinMaxArguments(const AbstractMetaFunctionList& bool OverloadData::isSingleArgument(const AbstractMetaFunctionList& overloads) { bool singleArgument = true; - foreach (const AbstractMetaFunction* func, overloads) { + for (const AbstractMetaFunction *func : overloads) { if (func->arguments().size() - numberOfRemovedArguments(func) != 1) { singleArgument = false; break; @@ -859,7 +869,7 @@ QString OverloadData::dumpGraph() const // Shows all function signatures s << "legend [fontsize=9 fontname=freemono shape=rect label=\""; - foreach (const AbstractMetaFunction* func, overloads()) { + for (const AbstractMetaFunction *func : m_overloads) { s << "f" << functionNumber(func) << " : "; if (func->type()) s << toHtml(func->type()->cppSignature()); @@ -893,7 +903,7 @@ QString OverloadData::dumpGraph() const s << "</td></tr>"; // Shows type changes for all function signatures - foreach (const AbstractMetaFunction* func, overloads()) { + for (const AbstractMetaFunction *func : m_overloads) { if (func->typeReplaced(0).isEmpty()) continue; s << "<tr><td bgcolor=\"gray\" align=\"right\">f" << functionNumber(func); @@ -916,13 +926,13 @@ QString OverloadData::dumpGraph() const // Overloads for the signature to present point s << "<tr><td bgcolor=\"gray\" align=\"right\">overloads</td><td bgcolor=\"gray\" align=\"left\">"; - foreach (const AbstractMetaFunction* func, overloads()) + for (const AbstractMetaFunction *func : m_overloads) s << 'f' << functionNumber(func) << ' '; s << "</td></tr>"; s << "</table>> ];" << endl; - foreach (const OverloadData* pd, nextOverloadData()) + for (const OverloadData *pd : m_nextOverloadData) s << indent << '"' << rfunc->name() << "\" -> " << pd->dumpGraph(); s << "}" << endl; @@ -948,12 +958,12 @@ QString OverloadData::dumpGraph() const // Overloads for the signature to present point s << "<tr><td bgcolor=\"gray\" align=\"right\">overloads</td><td bgcolor=\"gray\" align=\"left\">"; - foreach (const AbstractMetaFunction* func, overloads()) + for (const AbstractMetaFunction *func : m_overloads) s << 'f' << functionNumber(func) << ' '; s << "</td></tr>"; // Show default values (original and modified) for various functions - foreach (const AbstractMetaFunction* func, overloads()) { + for (const AbstractMetaFunction *func : m_overloads) { const AbstractMetaArgument* arg = argument(func); if (!arg) continue; @@ -973,7 +983,7 @@ QString OverloadData::dumpGraph() const s << "</table>>];" << endl; - foreach (const OverloadData* pd, nextOverloadData()) + for (const OverloadData *pd : m_nextOverloadData) s << indent << argId << " -> " << pd->dumpGraph(); } return result; @@ -1004,7 +1014,7 @@ bool OverloadData::hasArgumentWithDefaultValue(const AbstractMetaFunctionList& o { if (OverloadData::getMinMaxArguments(overloads).second == 0) return false; - foreach (const AbstractMetaFunction* func, overloads) { + for (const AbstractMetaFunction *func : overloads) { if (hasArgumentWithDefaultValue(func)) return true; } @@ -1015,7 +1025,7 @@ bool OverloadData::hasArgumentWithDefaultValue() const { if (maxArgs() == 0) return false; - foreach (const AbstractMetaFunction* func, overloads()) { + for (const AbstractMetaFunction *func : m_overloads) { if (hasArgumentWithDefaultValue(func)) return true; } @@ -1024,7 +1034,8 @@ bool OverloadData::hasArgumentWithDefaultValue() const bool OverloadData::hasArgumentWithDefaultValue(const AbstractMetaFunction* func) { - foreach (const AbstractMetaArgument* arg, func->arguments()) { + const AbstractMetaArgumentList &arguments = func->arguments(); + for (const AbstractMetaArgument *arg : arguments) { if (func->argumentRemoved(arg->argumentIndex() + 1)) continue; if (!ShibokenGenerator::getDefaultValue(func, arg).isEmpty()) @@ -1036,7 +1047,8 @@ bool OverloadData::hasArgumentWithDefaultValue(const AbstractMetaFunction* func) AbstractMetaArgumentList OverloadData::getArgumentsWithDefaultValues(const AbstractMetaFunction* func) { AbstractMetaArgumentList args; - foreach (AbstractMetaArgument* arg, func->arguments()) { + const AbstractMetaArgumentList &arguments = func->arguments(); + for (AbstractMetaArgument *arg : arguments) { if (ShibokenGenerator::getDefaultValue(func, arg).isEmpty() || func->argumentRemoved(arg->argumentIndex() + 1)) continue; diff --git a/sources/shiboken2/generator/shiboken2/overloaddata.h b/sources/shiboken2/generator/shiboken2/overloaddata.h index 959b96d0b..2d815f6bb 100644 --- a/sources/shiboken2/generator/shiboken2/overloaddata.h +++ b/sources/shiboken2/generator/shiboken2/overloaddata.h @@ -30,19 +30,21 @@ #define OVERLOADDATA_H #include <abstractmetalang_typedefs.h> -#include <QtCore/QList> #include <QtCore/QBitArray> +#include <QtCore/QVector> QT_FORWARD_DECLARE_CLASS(QDebug) class ShibokenGenerator; class OverloadData; -typedef QList<OverloadData*> OverloadDataList; +typedef QVector<OverloadData *> OverloadDataList; class OverloadData { public: + typedef QVector<const AbstractMetaFunction *> MetaFunctionList; + OverloadData(const AbstractMetaFunctionList& overloads, const ShibokenGenerator* generator); ~OverloadData(); @@ -100,12 +102,12 @@ public: bool isFinalOccurrence(const AbstractMetaFunction* func) const; /// Returns the list of overloads removing repeated constant functions (ex.: "foo()" and "foo()const", the second is removed). - QList<const AbstractMetaFunction*> overloadsWithoutRepetition() const; - const QList<const AbstractMetaFunction*>& overloads() const { return m_overloads; } + MetaFunctionList overloadsWithoutRepetition() const; + const MetaFunctionList& overloads() const { return m_overloads; } OverloadDataList nextOverloadData() const { return m_nextOverloadData; } OverloadData* previousOverloadData() const { return m_previousOverloadData; } - QList<int> invalidArgumentLengths() const; + QVector<int> invalidArgumentLengths() const; static int numberOfRemovedArguments(const AbstractMetaFunction* func, int finalArgPos = -1); static QPair<int, int> getMinMaxArguments(const AbstractMetaFunctionList& overloads); @@ -146,7 +148,7 @@ private: int m_argPos; const AbstractMetaType* m_argType; QString m_argTypeReplaced; - QList<const AbstractMetaFunction*> m_overloads; + MetaFunctionList m_overloads; OverloadData* m_headOverloadData; OverloadDataList m_nextOverloadData; diff --git a/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp b/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp index 670659854..d64719bb8 100644 --- a/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp +++ b/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp @@ -35,6 +35,7 @@ #include <QtCore/QDir> #include <QtCore/QDebug> +#include <QtCore/QRegularExpression> #include <limits> #include <memory> @@ -54,22 +55,51 @@ QHash<QString, QString> ShibokenGenerator::m_formatUnits = QHash<QString, QStrin QHash<QString, QString> ShibokenGenerator::m_tpFuncs = QHash<QString, QString>(); QStringList ShibokenGenerator::m_knownPythonTypes = QStringList(); -static QString resolveScopePrefix(const AbstractMetaClass* scope, const QString& value) +static QRegularExpression placeHolderRegex(int index) { - if (!scope) - return QString(); + return QRegularExpression(QLatin1Char('%') + QString::number(index) + QStringLiteral("\\b")); +} +// Return a prefix to fully qualify value, eg: +// resolveScopePrefix("Class::NestedClass::Enum::Value1", "Enum::Value1") +// -> "Class::NestedClass::") +static QString resolveScopePrefix(const QStringList &scopeList, const QString &value) +{ QString name; - QStringList parts = scope->qualifiedCppName().split(QLatin1String("::"), QString::SkipEmptyParts); - for(int i = (parts.size() - 1) ; i >= 0; i--) { - if (!value.startsWith(parts[i] + QLatin1String("::"))) - name = parts[i] + QLatin1String("::") + name; - else + for (int i = scopeList.size() - 1 ; i >= 0; --i) { + const QString prefix = scopeList.at(i) + QLatin1String("::"); + if (value.startsWith(prefix)) name.clear(); + else + name.prepend(prefix); } - return name; } + +static inline QStringList splitClassScope(const AbstractMetaClass *scope) +{ + return scope->qualifiedCppName().split(QLatin1String("::"), QString::SkipEmptyParts); +} + +static QString resolveScopePrefix(const AbstractMetaClass *scope, const QString &value) +{ + return scope + ? resolveScopePrefix(splitClassScope(scope), value) + : QString(); +} + +static QString resolveScopePrefix(const AbstractMetaEnum *metaEnum, + const QString &value) +{ + QStringList parts; + if (const AbstractMetaClass *scope = metaEnum->enclosingClass()) + parts.append(splitClassScope(scope)); + // Fully qualify the value which is required for C++ 11 enum classes. + if (!metaEnum->isAnonymous()) + parts.append(metaEnum->name()); + return resolveScopePrefix(parts, value); +} + ShibokenGenerator::ShibokenGenerator() : Generator() { if (m_pythonPrimitiveTypeName.isEmpty()) @@ -87,10 +117,10 @@ ShibokenGenerator::ShibokenGenerator() : Generator() m_typeSystemConvName[TypeSystemIsConvertibleFunction] = QLatin1String("isConvertible"); m_typeSystemConvName[TypeSystemToCppFunction] = QLatin1String("toCpp"); m_typeSystemConvName[TypeSystemToPythonFunction] = QLatin1String("toPython"); - m_typeSystemConvRegEx[TypeSystemCheckFunction] = QRegExp(QLatin1String(CHECKTYPE_REGEX)); - m_typeSystemConvRegEx[TypeSystemIsConvertibleFunction] = QRegExp(QLatin1String(ISCONVERTIBLE_REGEX)); - m_typeSystemConvRegEx[TypeSystemToPythonFunction] = QRegExp(QLatin1String(CONVERTTOPYTHON_REGEX)); - m_typeSystemConvRegEx[TypeSystemToCppFunction] = QRegExp(QLatin1String(CONVERTTOCPP_REGEX)); + m_typeSystemConvRegEx[TypeSystemCheckFunction] = QRegularExpression(QLatin1String(CHECKTYPE_REGEX)); + m_typeSystemConvRegEx[TypeSystemIsConvertibleFunction] = QRegularExpression(QLatin1String(ISCONVERTIBLE_REGEX)); + m_typeSystemConvRegEx[TypeSystemToPythonFunction] = QRegularExpression(QLatin1String(CONVERTTOPYTHON_REGEX)); + m_typeSystemConvRegEx[TypeSystemToCppFunction] = QRegularExpression(QLatin1String(CONVERTTOCPP_REGEX)); } ShibokenGenerator::~ShibokenGenerator() @@ -115,36 +145,34 @@ void ShibokenGenerator::initPrimitiveTypesCorrespondences() // PyBool m_pythonPrimitiveTypeName.insert(QLatin1String("bool"), QLatin1String("PyBool")); + const char *charTypes[] = { + "char", "signed char", "unsigned char" + }; + for (const char *charType : charTypes) + m_pythonPrimitiveTypeName.insert(QLatin1String(charType), QStringLiteral("SbkChar")); + // PyInt - m_pythonPrimitiveTypeName.insert(QLatin1String("char"), QLatin1String("SbkChar")); - m_pythonPrimitiveTypeName.insert(QLatin1String("signed char"), QLatin1String("SbkChar")); - m_pythonPrimitiveTypeName.insert(QLatin1String("unsigned char"), QLatin1String("SbkChar")); - m_pythonPrimitiveTypeName.insert(QLatin1String("int"), QLatin1String("PyInt")); - m_pythonPrimitiveTypeName.insert(QLatin1String("signed int"), QLatin1String("PyInt")); - m_pythonPrimitiveTypeName.insert(QLatin1String("uint"), QLatin1String("PyInt")); - m_pythonPrimitiveTypeName.insert(QLatin1String("unsigned int"), QLatin1String("PyInt")); - m_pythonPrimitiveTypeName.insert(QLatin1String("short"), QLatin1String("PyInt")); - m_pythonPrimitiveTypeName.insert(QLatin1String("ushort"), QLatin1String("PyInt")); - m_pythonPrimitiveTypeName.insert(QLatin1String("signed short"), QLatin1String("PyInt")); - m_pythonPrimitiveTypeName.insert(QLatin1String("signed short int"), QLatin1String("PyInt")); - m_pythonPrimitiveTypeName.insert(QLatin1String("unsigned short"), QLatin1String("PyInt")); - m_pythonPrimitiveTypeName.insert(QLatin1String("unsigned short int"), QLatin1String("PyInt")); - m_pythonPrimitiveTypeName.insert(QLatin1String("long"), QLatin1String("PyInt")); + const char *intTypes[] = { + "int", "signed int", "uint", "unsigned int", + "short", "ushort", "signed short", "signed short int", + "unsigned short", "unsigned short", "unsigned short int", + "long" + }; + for (const char *intType : intTypes) + m_pythonPrimitiveTypeName.insert(QLatin1String(intType), QStringLiteral("PyInt")); // PyFloat m_pythonPrimitiveTypeName.insert(QLatin1String("double"), QLatin1String("PyFloat")); m_pythonPrimitiveTypeName.insert(QLatin1String("float"), QLatin1String("PyFloat")); // PyLong - m_pythonPrimitiveTypeName.insert(QLatin1String("unsigned long"), QLatin1String("PyLong")); - m_pythonPrimitiveTypeName.insert(QLatin1String("signed long"), QLatin1String("PyLong")); - m_pythonPrimitiveTypeName.insert(QLatin1String("ulong"), QLatin1String("PyLong")); - m_pythonPrimitiveTypeName.insert(QLatin1String("unsigned long int"), QLatin1String("PyLong")); - m_pythonPrimitiveTypeName.insert(QLatin1String("long long"), QLatin1String("PyLong")); - m_pythonPrimitiveTypeName.insert(QLatin1String("__int64"), QLatin1String("PyLong")); - m_pythonPrimitiveTypeName.insert(QLatin1String("unsigned long long"), QLatin1String("PyLong")); - m_pythonPrimitiveTypeName.insert(QLatin1String("unsigned __int64"), QLatin1String("PyLong")); - m_pythonPrimitiveTypeName.insert(QLatin1String("size_t"), QLatin1String("PyLong")); + const char *longTypes[] = { + "unsigned long", "signed long", "ulong", "unsigned long int", + "long long", "__int64", + "unsigned long long", "unsigned __int64", "size_t" + }; + for (const char *longType : longTypes) + m_pythonPrimitiveTypeName.insert(QLatin1String(longType), QStringLiteral("PyLong")); // Python operators m_pythonOperators.clear(); @@ -237,13 +265,16 @@ QString ShibokenGenerator::translateTypeForWrapperMethod(const AbstractMetaType* bool ShibokenGenerator::shouldGenerateCppWrapper(const AbstractMetaClass* metaClass) const { + if (metaClass->isNamespace() || (metaClass->attributes() & AbstractMetaAttributes::FinalCppClass)) + return false; bool result = metaClass->isPolymorphic() || metaClass->hasVirtualDestructor(); if (avoidProtectedHack()) { result = result || metaClass->hasProtectedFields() || metaClass->hasProtectedDestructor(); if (!result && metaClass->hasProtectedFunctions()) { int protectedFunctions = 0; int protectedOperators = 0; - foreach (const AbstractMetaFunction* func, metaClass->functions()) { + const AbstractMetaFunctionList &funcs = metaClass->functions(); + for (const AbstractMetaFunction *func : funcs) { if (!func->isProtected() || func->isSignal() || func->isModifiedRemoved()) continue; else if (func->isOperatorOverload()) @@ -256,7 +287,7 @@ bool ShibokenGenerator::shouldGenerateCppWrapper(const AbstractMetaClass* metaCl } else { result = result && !metaClass->hasPrivateDestructor(); } - return result && !metaClass->isNamespace(); + return result; } void ShibokenGenerator::lookForEnumsInClassesNotToBeGenerated(AbstractMetaEnumList& enumList, const AbstractMetaClass* metaClass) @@ -265,7 +296,8 @@ void ShibokenGenerator::lookForEnumsInClassesNotToBeGenerated(AbstractMetaEnumLi return; if (metaClass->typeEntry()->codeGeneration() == TypeEntry::GenerateForSubclass) { - foreach (const AbstractMetaEnum* metaEnum, metaClass->enums()) { + const AbstractMetaEnumList &enums = metaClass->enums(); + for (const AbstractMetaEnum *metaEnum : enums) { if (metaEnum->isPrivate() || metaEnum->typeEntry()->codeGeneration() == TypeEntry::GenerateForSubclass) continue; if (!enumList.contains(const_cast<AbstractMetaEnum*>(metaEnum))) @@ -409,32 +441,91 @@ static QString cpythonEnumFlagsName(QString moduleName, QString qualifiedCppName return result; } +// Return the scope for fully qualifying the enumeration including trailing "::". static QString searchForEnumScope(const AbstractMetaClass* metaClass, const QString& value) { - QString enumValueName = value.trimmed(); - if (!metaClass) return QString(); - - foreach (const AbstractMetaEnum* metaEnum, metaClass->enums()) { - foreach (const AbstractMetaEnumValue* enumValue, metaEnum->values()) { - if (enumValueName == enumValue->name()) - return metaClass->qualifiedCppName(); - } + const AbstractMetaEnumList &enums = metaClass->enums(); + for (const AbstractMetaEnum *metaEnum : enums) { + if (metaEnum->findEnumValue(value)) + return resolveScopePrefix(metaEnum, value); } // PYSIDE-331: We need to also search the base classes. - QString ret = searchForEnumScope(metaClass->enclosingClass(), enumValueName); + QString ret = searchForEnumScope(metaClass->enclosingClass(), value); if (ret.isEmpty()) - ret = searchForEnumScope(metaClass->baseClass(), enumValueName); + ret = searchForEnumScope(metaClass->baseClass(), value); return ret; } +// Handle QFlags<> for guessScopeForDefaultValue() +QString ShibokenGenerator::guessScopeForDefaultFlagsValue(const AbstractMetaFunction *func, + const AbstractMetaArgument *arg, + const QString &value) const +{ + // Numeric values -> "Options(42)" + static const QRegularExpression numberRegEx(QStringLiteral("^\\d+$")); // Numbers to flags + Q_ASSERT(numberRegEx.isValid()); + if (numberRegEx.match(value).hasMatch()) { + QString typeName = translateTypeForWrapperMethod(arg->type(), func->implementingClass()); + if (arg->type()->isConstant()) + typeName.remove(0, sizeof("const ") / sizeof(char) - 1); + switch (arg->type()->referenceType()) { + case NoReference: + break; + case LValueReference: + typeName.chop(1); + break; + case RValueReference: + typeName.chop(2); + break; + } + return typeName + QLatin1Char('(') + value + QLatin1Char(')'); + } + + // "Options(Option1 | Option2)" -> "Options(Class::Enum::Option1 | Class::Enum::Option2)" + static const QRegularExpression enumCombinationRegEx(QStringLiteral("^([A-Za-z_][\\w:]*)\\(([^,\\(\\)]*)\\)$")); // FlagName(EnumItem|EnumItem|...) + Q_ASSERT(enumCombinationRegEx.isValid()); + const QRegularExpressionMatch match = enumCombinationRegEx.match(value); + if (match.hasMatch()) { + const QString expression = match.captured(2).trimmed(); + if (expression.isEmpty()) + return value; + const QStringList enumItems = expression.split(QLatin1Char('|')); + const QString scope = searchForEnumScope(func->implementingClass(), + enumItems.constFirst().trimmed()); + if (scope.isEmpty()) + return value; + QString result; + QTextStream str(&result); + str << match.captured(1) << '('; // Flag name + for (int i = 0, size = enumItems.size(); i < size; ++i) { + if (i) + str << '|'; + str << scope << enumItems.at(i).trimmed(); + } + str << ')'; + return result; + } + // A single flag "Option1" -> "Class::Enum::Option1" + return searchForEnumScope(func->implementingClass(), value) + value; +} + /* * This function uses some heuristics to find out the scope for a given - * argument default value. New situations may arise in the future and + * argument default value since they must be fully qualified when used outside the class: + * class A { + * enum Enum { e1, e1 }; + * void foo(Enum e = e1); + * } + * should be qualified to: + * A::Enum cppArg0 = A::Enum::e1; + * + * New situations may arise in the future and * this method should be updated, do it with care. */ -QString ShibokenGenerator::guessScopeForDefaultValue(const AbstractMetaFunction* func, const AbstractMetaArgument* arg) +QString ShibokenGenerator::guessScopeForDefaultValue(const AbstractMetaFunction *func, + const AbstractMetaArgument *arg) const { QString value = getDefaultValue(func, arg); @@ -444,64 +535,35 @@ QString ShibokenGenerator::guessScopeForDefaultValue(const AbstractMetaFunction* if (isPointer(arg->type())) return value; - static QRegExp enumValueRegEx(QLatin1String("^([A-Za-z_]\\w*)?$")); - QString prefix; - QString suffix; + static const QRegularExpression enumValueRegEx(QStringLiteral("^([A-Za-z_]\\w*)?$")); + Q_ASSERT(enumValueRegEx.isValid()); + // Do not qualify macros by class name, eg QSGGeometry(..., int t = GL_UNSIGNED_SHORT); + static const QRegularExpression macroRegEx(QStringLiteral("^[A-Z_][A-Z0-9_]*$")); + Q_ASSERT(macroRegEx.isValid()); + if (arg->type()->isPrimitive() && macroRegEx.match(value).hasMatch()) + return value; + QString prefix; if (arg->type()->isEnum()) { - const AbstractMetaEnum* metaEnum = findAbstractMetaEnum(arg->type()); - if (metaEnum) - prefix = resolveScopePrefix(metaEnum->enclosingClass(), value); + if (const AbstractMetaEnum* metaEnum = findAbstractMetaEnum(arg->type())) + prefix = resolveScopePrefix(metaEnum, value); } else if (arg->type()->isFlags()) { - static QRegExp numberRegEx(QLatin1String("^\\d+$")); // Numbers to flags - if (numberRegEx.exactMatch(value)) { - QString typeName = translateTypeForWrapperMethod(arg->type(), func->implementingClass()); - if (arg->type()->isConstant()) - typeName.remove(0, sizeof("const ") / sizeof(char) - 1); - switch (arg->type()->referenceType()) { - case NoReference: - break; - case LValueReference: - typeName.chop(1); - break; - case RValueReference: - typeName.chop(2); - break; - } - prefix = typeName + QLatin1Char('('); - suffix = QLatin1Char(')'); - } - - static QRegExp enumCombinationRegEx(QLatin1String("^([A-Za-z_][\\w:]*)\\(([^,\\(\\)]*)\\)$")); // FlagName(EnumItem|EnumItem|...) - if (prefix.isEmpty() && enumCombinationRegEx.indexIn(value) != -1) { - QString flagName = enumCombinationRegEx.cap(1); - QStringList enumItems = enumCombinationRegEx.cap(2).split(QLatin1Char('|')); - QString scope = searchForEnumScope(func->implementingClass(), enumItems.first()); - if (!scope.isEmpty()) - scope.append(QLatin1String("::")); - - QStringList fixedEnumItems; - foreach (const QString& enumItem, enumItems) - fixedEnumItems << QString(scope + enumItem); - - if (!fixedEnumItems.isEmpty()) { - prefix = flagName + QLatin1Char('('); - value = fixedEnumItems.join(QLatin1Char('|')); - suffix = QLatin1Char(')'); - } - } + value = guessScopeForDefaultFlagsValue(func, arg, value); } else if (arg->type()->typeEntry()->isValue()) { const AbstractMetaClass *metaClass = AbstractMetaClass::findClass(classes(), arg->type()->typeEntry()); - if (enumValueRegEx.exactMatch(value)&& value != QLatin1String("NULL")) + if (enumValueRegEx.match(value).hasMatch() && value != QLatin1String("NULL")) prefix = resolveScopePrefix(metaClass, value); } else if (arg->type()->isPrimitive() && arg->type()->name() == QLatin1String("int")) { - if (enumValueRegEx.exactMatch(value) && func->implementingClass()) + if (enumValueRegEx.match(value).hasMatch() && func->implementingClass()) prefix = resolveScopePrefix(func->implementingClass(), value); } else if(arg->type()->isPrimitive()) { - static QRegExp unknowArgumentRegEx(QLatin1String("^(?:[A-Za-z_][\\w:]*\\()?([A-Za-z_]\\w*)(?:\\))?$")); // [PrimitiveType(] DESIREDNAME [)] - if (unknowArgumentRegEx.indexIn(value) != -1 && func->implementingClass()) { - foreach (const AbstractMetaField* field, func->implementingClass()->fields()) { - if (unknowArgumentRegEx.cap(1).trimmed() == field->name()) { + static const QRegularExpression unknowArgumentRegEx(QStringLiteral("^(?:[A-Za-z_][\\w:]*\\()?([A-Za-z_]\\w*)(?:\\))?$")); // [PrimitiveType(] DESIREDNAME [)] + Q_ASSERT(unknowArgumentRegEx.isValid()); + const QRegularExpressionMatch match = unknowArgumentRegEx.match(value); + if (match.hasMatch() && func->implementingClass()) { + const AbstractMetaFieldList &fields = func->implementingClass()->fields(); + for (const AbstractMetaField *field : fields) { + if (match.captured(1).trimmed() == field->name()) { QString fieldName = field->name(); if (field->isStatic()) { prefix = resolveScopePrefix(func->implementingClass(), value); @@ -510,7 +572,7 @@ QString ShibokenGenerator::guessScopeForDefaultValue(const AbstractMetaFunction* } else { fieldName.prepend(QLatin1String(CPP_SELF_VAR "->")); } - value.replace(unknowArgumentRegEx.cap(1), fieldName); + value.replace(match.captured(1), fieldName); break; } } @@ -519,9 +581,6 @@ QString ShibokenGenerator::guessScopeForDefaultValue(const AbstractMetaFunction* if (!prefix.isEmpty()) value.prepend(prefix); - if (!suffix.isEmpty()) - value.append(suffix); - return value; } @@ -622,8 +681,9 @@ bool ShibokenGenerator::shouldRejectNullPointerArgument(const AbstractMetaFuncti return false; if (func->argumentRemoved(argIndex + 1)) return false; - foreach (const FunctionModification &funcMod, func->modifications()) { - foreach (const ArgumentModification &argMod, funcMod.argument_mods) { + const FunctionModificationList &mods = func->modifications(); + for (const FunctionModification &funcMod : mods) { + for (const ArgumentModification &argMod : funcMod.argument_mods) { if (argMod.index == argIndex + 1 && argMod.noNullPointers) return true; } @@ -635,7 +695,8 @@ QString ShibokenGenerator::getFormatUnitString(const AbstractMetaFunction* func, { QString result; const char objType = (incRef ? 'O' : 'N'); - foreach (const AbstractMetaArgument* arg, func->arguments()) { + const AbstractMetaArgumentList &arguments = func->arguments(); + for (const AbstractMetaArgument *arg : arguments) { if (func->argumentRemoved(arg->argumentIndex() + 1)) continue; @@ -758,6 +819,13 @@ QString ShibokenGenerator::converterObject(const AbstractMetaType* type) return QLatin1String("Shiboken::Conversions::PrimitiveTypeConverter<const char*>()"); if (isVoidPointer(type)) return QLatin1String("Shiboken::Conversions::PrimitiveTypeConverter<void*>()"); + const AbstractMetaTypeCList nestedArrayTypes = type->nestedArrayTypes(); + if (!nestedArrayTypes.isEmpty() && nestedArrayTypes.constLast()->isCppPrimitive()) { + return QStringLiteral("Shiboken::Conversions::ArrayTypeConverter<") + + nestedArrayTypes.constLast()->minimalSignature() + + QLatin1String(">(") + QString::number(nestedArrayTypes.size()) + + QLatin1Char(')'); + } if (type->typeEntry()->isContainer()) { return convertersVariableName(type->typeEntry()->targetLangPackage()) + QLatin1Char('[') + getTypeIndexVariableName(type) + QLatin1Char(']'); @@ -983,10 +1051,12 @@ bool ShibokenGenerator::isValueTypeWithCopyConstructorOnly(const AbstractMetaCla { if (!metaClass || !metaClass->typeEntry()->isValue()) return false; + if ((metaClass->attributes() & AbstractMetaAttributes::HasRejectedConstructor) != 0) + return false; AbstractMetaFunctionList ctors = metaClass->queryFunctions(AbstractMetaClass::Constructors); if (ctors.count() != 1) return false; - return ctors.first()->functionType() == AbstractMetaFunction::CopyConstructorFunction; + return ctors.constFirst()->functionType() == AbstractMetaFunction::CopyConstructorFunction; } bool ShibokenGenerator::isValueTypeWithCopyConstructorOnly(const TypeEntry* type) const @@ -1054,7 +1124,8 @@ bool ShibokenGenerator::shouldDereferenceAbstractMetaTypePointer(const AbstractM bool ShibokenGenerator::visibilityModifiedToPrivate(const AbstractMetaFunction* func) { - foreach (const FunctionModification &mod, func->modifications()) { + const FunctionModificationList &mods = func->modifications(); + for (const FunctionModification &mod : mods) { if (mod.modifiers & Modification::Private) return true; } @@ -1089,7 +1160,7 @@ QString ShibokenGenerator::cpythonCheckFunction(const AbstractMetaType* metaType || type == ContainerTypeEntry::StackContainer || type == ContainerTypeEntry::SetContainer || type == ContainerTypeEntry::QueueContainer) { - const AbstractMetaType* type = metaType->instantiations().first(); + const AbstractMetaType* type = metaType->instantiations().constFirst(); if (isPointerToWrapperType(type)) { typeCheck += QString::fromLatin1("checkSequenceTypes(%1, ").arg(cpythonTypeNameExt(type)); } else if (isWrapperType(type)) { @@ -1105,8 +1176,8 @@ QString ShibokenGenerator::cpythonCheckFunction(const AbstractMetaType* metaType || type == ContainerTypeEntry::MultiHashContainer || type == ContainerTypeEntry::PairContainer) { QString pyType = (type == ContainerTypeEntry::PairContainer) ? QLatin1String("Pair") : QLatin1String("Dict"); - const AbstractMetaType* firstType = metaType->instantiations().first(); - const AbstractMetaType* secondType = metaType->instantiations().last(); + const AbstractMetaType* firstType = metaType->instantiations().constFirst(); + const AbstractMetaType* secondType = metaType->instantiations().constLast(); if (isPointerToWrapperType(firstType) && isPointerToWrapperType(secondType)) { typeCheck += QString::fromLatin1("check%1Types(%2, %3, ").arg(pyType) .arg(cpythonTypeNameExt(firstType), cpythonTypeNameExt(secondType)); @@ -1208,8 +1279,8 @@ QString ShibokenGenerator::cpythonIsConvertibleFunction(const AbstractMetaType* return customCheck; } + QString result = QLatin1String("Shiboken::Conversions::"); if (isWrapperType(metaType)) { - QString result = QLatin1String("Shiboken::Conversions::"); if (isPointer(metaType) || isValueTypeWithCopyConstructorOnly(metaType)) result += QLatin1String("isPythonToCppPointerConvertible"); else if (metaType->referenceType() == LValueReference) @@ -1220,8 +1291,18 @@ QString ShibokenGenerator::cpythonIsConvertibleFunction(const AbstractMetaType* + cpythonTypeNameExt(metaType) + QLatin1String("), "); return result; } - return QStringLiteral("Shiboken::Conversions::isPythonToCppConvertible(%1, ") - .arg(converterObject(metaType)); + result += QLatin1String("isPythonToCppConvertible(") + converterObject(metaType); + // Write out array sizes if known + const AbstractMetaTypeCList nestedArrayTypes = metaType->nestedArrayTypes(); + if (!nestedArrayTypes.isEmpty() && nestedArrayTypes.constLast()->isCppPrimitive()) { + const int dim1 = metaType->arrayElementCount(); + const int dim2 = nestedArrayTypes.constFirst()->isArray() + ? nestedArrayTypes.constFirst()->arrayElementCount() : -1; + result += QLatin1String(", ") + QString::number(dim1) + + QLatin1String(", ") + QString::number(dim2); + } + result += QLatin1String(", "); + return result; } QString ShibokenGenerator::cpythonIsConvertibleFunction(const AbstractMetaArgument *metaArg, bool genericNumberType) @@ -1306,12 +1387,14 @@ QString ShibokenGenerator::argumentString(const AbstractMetaFunction *func, arg = modified_type.replace(QLatin1Char('$'), QLatin1Char('.')); if (!(options & Generator::SkipName)) { - arg += QLatin1Char(' '); - arg += argument->name(); + // "int a", "int a[]" + const int arrayPos = arg.indexOf(QLatin1Char('[')); + if (arrayPos != -1) + arg.insert(arrayPos, QLatin1Char(' ') + argument->name()); + else + arg.append(QLatin1Char(' ') + argument->name()); } - QList<ReferenceCount> referenceCounts; - referenceCounts = func->referenceCounts(func->implementingClass(), argument->argumentIndex() + 1); if ((options & Generator::SkipDefaultValues) != Generator::SkipDefaultValues && !argument->originalDefaultValueExpression().isEmpty()) { @@ -1445,7 +1528,8 @@ void ShibokenGenerator::writeUnusedVariableCast(QTextStream& s, const QString& v AbstractMetaFunctionList ShibokenGenerator::filterFunctions(const AbstractMetaClass* metaClass) { AbstractMetaFunctionList result; - foreach (AbstractMetaFunction *func, metaClass->functions()) { + const AbstractMetaFunctionList &funcs = metaClass->functions(); + for (AbstractMetaFunction *func : funcs) { if (func->isSignal() || func->isDestructor() || func->usesRValueReferences() || (func->isModifiedRemoved() && !func->isAbstract() && (!avoidProtectedHack() || !func->isProtected()))) @@ -1458,11 +1542,13 @@ AbstractMetaFunctionList ShibokenGenerator::filterFunctions(const AbstractMetaCl ShibokenGenerator::ExtendedConverterData ShibokenGenerator::getExtendedConverters() const { ExtendedConverterData extConvs; - foreach (const AbstractMetaClass* metaClass, classes()) { + const AbstractMetaClassList &classList = classes(); + for (const AbstractMetaClass *metaClass : classList) { // Use only the classes for the current module. if (!shouldGenerate(metaClass)) continue; - foreach (AbstractMetaFunction* convOp, metaClass->operatorOverloads(AbstractMetaClass::ConversionOp)) { + const AbstractMetaFunctionList &overloads = metaClass->operatorOverloads(AbstractMetaClass::ConversionOp); + for (AbstractMetaFunction *convOp : overloads) { // Get only the conversion operators that return a type from another module, // that are value-types and were not removed in the type system. const TypeEntry* convType = convOp->type()->typeEntry(); @@ -1476,10 +1562,11 @@ ShibokenGenerator::ExtendedConverterData ShibokenGenerator::getExtendedConverter return extConvs; } -QList<const CustomConversion*> ShibokenGenerator::getPrimitiveCustomConversions() +QVector<const CustomConversion *> ShibokenGenerator::getPrimitiveCustomConversions() { - QList<const CustomConversion*> conversions; - foreach (const PrimitiveTypeEntry* type, primitiveTypes()) { + QVector<const CustomConversion*> conversions; + const PrimitiveTypeEntryList &primitiveTypeList = primitiveTypes(); + for (const PrimitiveTypeEntry *type : primitiveTypeList) { if (!shouldGenerateTypeEntry(type) || !isUserPrimitive(type) || !type->customConversion()) continue; @@ -1522,7 +1609,7 @@ QString ShibokenGenerator::getCodeSnippets(const CodeSnipList& codeSnips, { QString code; QTextStream c(&code); - foreach (const CodeSnip &snip, codeSnips) { + for (const CodeSnip &snip : codeSnips) { if ((position != TypeSystem::CodeSnipPositionAny && snip.position != position) || !(snip.language & language)) continue; QString snipCode; @@ -1623,6 +1710,17 @@ void ShibokenGenerator::writeCodeSnips(QTextStream& s, s << INDENT << "// End of code injection" << endl; } +static QString msgWrongIndex(const char *varName, const QString &capture, const AbstractMetaFunction *func) +{ + QString result; + QTextStream str(&result); + str << "Wrong index for " << varName << " variable (" << capture << ") on "; + if (const AbstractMetaClass *c = func->implementingClass()) + str << c->name() << "::"; + str << func->signature(); + return result; +} + void ShibokenGenerator::writeCodeSnips(QTextStream& s, const CodeSnipList& codeSnips, TypeSystem::CodeSnipPosition position, @@ -1647,15 +1745,18 @@ void ShibokenGenerator::writeCodeSnips(QTextStream& s, // Replace %PYARG_# variables. code.replace(QLatin1String("%PYARG_0"), QLatin1String(PYTHON_RETURN_VAR)); - static QRegExp pyArgsRegex(QLatin1String("%PYARG_(\\d+)")); + static const QRegularExpression pyArgsRegex(QStringLiteral("%PYARG_(\\d+)")); + Q_ASSERT(pyArgsRegex.isValid()); if (language == TypeSystem::TargetLangCode) { if (usePyArgs) { code.replace(pyArgsRegex, QLatin1String(PYTHON_ARGS"[\\1-1]")); } else { - static QRegExp pyArgsRegexCheck(QLatin1String("%PYARG_([2-9]+)")); - if (pyArgsRegexCheck.indexIn(code) != -1) { + static const QRegularExpression pyArgsRegexCheck(QStringLiteral("%PYARG_([2-9]+)")); + Q_ASSERT(pyArgsRegexCheck.isValid()); + const QRegularExpressionMatch match = pyArgsRegexCheck.match(code); + if (match.hasMatch()) { qCWarning(lcShiboken).noquote().nospace() - << "Wrong index for %PYARG variable (" << pyArgsRegexCheck.cap(1) << ") on " << func->signature(); + << msgWrongIndex("%PYARG", match.captured(1), func); return; } code.replace(QLatin1String("%PYARG_1"), QLatin1String(PYTHON_ARG)); @@ -1663,25 +1764,27 @@ void ShibokenGenerator::writeCodeSnips(QTextStream& s, } else { // Replaces the simplest case of attribution to a // Python argument on the binding virtual method. - static QRegExp pyArgsAttributionRegex(QLatin1String("%PYARG_(\\d+)\\s*=[^=]\\s*([^;]+)")); + static const QRegularExpression pyArgsAttributionRegex(QStringLiteral("%PYARG_(\\d+)\\s*=[^=]\\s*([^;]+)")); + Q_ASSERT(pyArgsAttributionRegex.isValid()); code.replace(pyArgsAttributionRegex, QLatin1String("PyTuple_SET_ITEM(" PYTHON_ARGS ", \\1-1, \\2)")); code.replace(pyArgsRegex, QLatin1String("PyTuple_GET_ITEM(" PYTHON_ARGS ", \\1-1)")); } // Replace %ARG#_TYPE variables. - foreach (const AbstractMetaArgument* arg, func->arguments()) { + const AbstractMetaArgumentList &arguments = func->arguments(); + for (const AbstractMetaArgument *arg : arguments) { QString argTypeVar = QStringLiteral("%ARG%1_TYPE").arg(arg->argumentIndex() + 1); QString argTypeVal = arg->type()->cppSignature(); code.replace(argTypeVar, argTypeVal); } - int pos = 0; - static QRegExp cppArgTypeRegexCheck(QLatin1String("%ARG(\\d+)_TYPE")); - while ((pos = cppArgTypeRegexCheck.indexIn(code, pos)) != -1) { + static const QRegularExpression cppArgTypeRegexCheck(QStringLiteral("%ARG(\\d+)_TYPE")); + Q_ASSERT(cppArgTypeRegexCheck.isValid()); + QRegularExpressionMatchIterator rit = cppArgTypeRegexCheck.globalMatch(code); + while (rit.hasNext()) { + QRegularExpressionMatch match = rit.next(); qCWarning(lcShiboken).noquote().nospace() - << "Wrong index for %ARG#_TYPE variable (" << cppArgTypeRegexCheck.cap(1) - << ") on " << func->signature(); - pos += cppArgTypeRegexCheck.matchedLength(); + << msgWrongIndex("%ARG#_TYPE", match.captured(1), func); } // Replace template variable for return variable name. @@ -1762,17 +1865,17 @@ void ShibokenGenerator::writeCodeSnips(QTextStream& s, // Replaces template %ARGUMENT_NAMES and %# variables by argument variables and values. // Replaces template variables %# for individual arguments. - ArgumentVarReplacementList argReplacements = getArgumentReplacement(func, usePyArgs, language, lastArg); + const ArgumentVarReplacementList &argReplacements = getArgumentReplacement(func, usePyArgs, language, lastArg); QStringList args; - foreach (const ArgumentVarReplacementPair &pair, argReplacements) { + for (const ArgumentVarReplacementPair &pair : argReplacements) { if (pair.second.startsWith(QLatin1String(CPP_ARG_REMOVED))) continue; args << pair.second; } code.replace(QLatin1String("%ARGUMENT_NAMES"), args.join(QLatin1String(", "))); - foreach (const ArgumentVarReplacementPair &pair, argReplacements) { + for (const ArgumentVarReplacementPair &pair : argReplacements) { const AbstractMetaArgument* arg = pair.first; int idx = arg->argumentIndex() + 1; AbstractMetaType* type = arg->type(); @@ -1789,7 +1892,7 @@ void ShibokenGenerator::writeCodeSnips(QTextStream& s, if (type->referenceType() == LValueReference || isPointer(type)) code.replace(QString::fromLatin1("%%1.").arg(idx), replacement + QLatin1String("->")); } - code.replace(QRegExp(QString::fromLatin1("%%1\\b").arg(idx)), pair.second); + code.replace(placeHolderRegex(idx), pair.second); } if (language == TypeSystem::NativeCode) { @@ -1811,7 +1914,8 @@ void ShibokenGenerator::writeCodeSnips(QTextStream& s, // dispatcher. bool hasProtectedOverload = false; if (func->isUserAdded()) { - foreach (const AbstractMetaFunction* f, getFunctionOverloads(func->ownerClass(), func->name())) + const AbstractMetaFunctionList &funcs = getFunctionOverloads(func->ownerClass(), func->name()); + for (const AbstractMetaFunction *f : funcs) hasProtectedOverload |= f->isProtected(); } @@ -1842,8 +1946,9 @@ void ShibokenGenerator::writeCodeSnips(QTextStream& s, // and false if it is a variable. static bool isVariable(const QString& code) { - static QRegExp expr(QLatin1String("\\s*\\*?\\s*[A-Za-z_][A-Za-z_0-9.]*\\s*(?:\\[[^\\[]+\\])*")); - return expr.exactMatch(code.trimmed()); + static const QRegularExpression expr(QStringLiteral("^\\s*\\*?\\s*[A-Za-z_][A-Za-z_0-9.]*\\s*(?:\\[[^\\[]+\\])*$")); + Q_ASSERT(expr.isValid()); + return expr.match(code.trimmed()).hasMatch(); } // A miniature normalizer that puts a type string into a format @@ -1893,14 +1998,13 @@ static QString getConverterTypeSystemVariableArgument(const QString& code, int p typedef QPair<QString, QString> StringPair; void ShibokenGenerator::replaceConverterTypeSystemVariable(TypeSystemConverterVariable converterVariable, QString& code) { - QRegExp& regex = m_typeSystemConvRegEx[converterVariable]; - int pos = 0; - QList<StringPair> replacements; - while ((pos = regex.indexIn(code, pos)) != -1) { - pos += regex.matchedLength(); - QStringList list = regex.capturedTexts(); - QString conversionString = list.first(); - QString conversionTypeName = list.last(); + QVector<StringPair> replacements; + QRegularExpressionMatchIterator rit = m_typeSystemConvRegEx[converterVariable].globalMatch(code); + while (rit.hasNext()) { + const QRegularExpressionMatch match = rit.next(); + const QStringList list = match.capturedTexts(); + QString conversionString = list.constFirst(); + QString conversionTypeName = list.constLast(); const AbstractMetaType* conversionType = buildAbstractMetaTypeFromString(conversionTypeName); if (!conversionType) { qFatal(qPrintable(QString::fromLatin1("Could not find type '%1' for use in '%2' conversion. " @@ -1912,14 +2016,14 @@ void ShibokenGenerator::replaceConverterTypeSystemVariable(TypeSystemConverterVa QTextStream c(&conversion); switch (converterVariable) { case TypeSystemToCppFunction: { - int end = pos - list.first().count(); + int end = match.capturedStart(); int start = end; while (start > 0 && code.at(start) != QLatin1Char('\n')) --start; while (code.at(start).isSpace()) ++start; QString varType = code.mid(start, end - start); - conversionString = varType + list.first(); + conversionString = varType + list.constFirst(); varType = miniNormalizer(varType); QString varName = list.at(1).trimmed(); if (!varType.isEmpty()) { @@ -1941,7 +2045,7 @@ void ShibokenGenerator::replaceConverterTypeSystemVariable(TypeSystemConverterVa } else { prefix = QLatin1Char('&'); } - QString arg = getConverterTypeSystemVariableArgument(code, pos); + QString arg = getConverterTypeSystemVariableArgument(code, match.capturedEnd()); conversionString += arg; c << arg << ", " << prefix << '(' << varName << ')'; break; @@ -1961,7 +2065,7 @@ void ShibokenGenerator::replaceConverterTypeSystemVariable(TypeSystemConverterVa if (conversion.isEmpty()) conversion = cpythonToPythonConversionFunction(conversionType); default: { - QString arg = getConverterTypeSystemVariableArgument(code, pos); + QString arg = getConverterTypeSystemVariableArgument(code, match.capturedEnd()); conversionString += arg; if (converterVariable == TypeSystemToPythonFunction && !isVariable(arg)) { qFatal(qPrintable(QString::fromLatin1("Only variables are acceptable as argument to %%CONVERTTOPYTHON type system variable on code snippet: '%1'") @@ -1977,14 +2081,14 @@ void ShibokenGenerator::replaceConverterTypeSystemVariable(TypeSystemConverterVa } replacements.append(qMakePair(conversionString, conversion)); } - foreach (const StringPair &rep, replacements) + for (const StringPair &rep : qAsConst(replacements)) code.replace(rep.first, rep.second); } bool ShibokenGenerator::injectedCodeUsesCppSelf(const AbstractMetaFunction* func) { CodeSnipList snips = func->injectedCodeSnips(TypeSystem::CodeSnipPositionAny, TypeSystem::TargetLangCode); - foreach (const CodeSnip &snip, snips) { + for (const CodeSnip &snip : qAsConst(snips)) { if (snip.code().contains(QLatin1String("%CPPSELF"))) return true; } @@ -1994,7 +2098,7 @@ bool ShibokenGenerator::injectedCodeUsesCppSelf(const AbstractMetaFunction* func bool ShibokenGenerator::injectedCodeUsesPySelf(const AbstractMetaFunction* func) { CodeSnipList snips = func->injectedCodeSnips(TypeSystem::CodeSnipPositionAny, TypeSystem::NativeCode); - foreach (const CodeSnip &snip, snips) { + for (const CodeSnip &snip : qAsConst(snips)) { if (snip.code().contains(QLatin1String("%PYSELF"))) return true; } @@ -2010,7 +2114,7 @@ bool ShibokenGenerator::injectedCodeCallsCppFunction(const AbstractMetaFunction* wrappedCtorCall = QStringLiteral("new %1(").arg(wrapperName(func->ownerClass())); } CodeSnipList snips = func->injectedCodeSnips(TypeSystem::CodeSnipPositionAny, TypeSystem::TargetLangCode); - foreach (const CodeSnip &snip, snips) { + for (const CodeSnip &snip : qAsConst(snips)) { if (snip.code().contains(QLatin1String("%FUNCTION_NAME(")) || snip.code().contains(funcCall) || (func->isConstructor() && ((func->ownerClass()->isPolymorphic() && snip.code().contains(wrappedCtorCall)) @@ -2023,10 +2127,11 @@ bool ShibokenGenerator::injectedCodeCallsCppFunction(const AbstractMetaFunction* bool ShibokenGenerator::injectedCodeCallsPythonOverride(const AbstractMetaFunction* func) { - static QRegExp overrideCallRegexCheck(QLatin1String("PyObject_Call\\s*\\(\\s*%PYTHON_METHOD_OVERRIDE\\s*,")); + static const QRegularExpression overrideCallRegexCheck(QStringLiteral("PyObject_Call\\s*\\(\\s*%PYTHON_METHOD_OVERRIDE\\s*,")); + Q_ASSERT(overrideCallRegexCheck.isValid()); CodeSnipList snips = func->injectedCodeSnips(TypeSystem::CodeSnipPositionAny, TypeSystem::NativeCode); - foreach (const CodeSnip &snip, snips) { - if (overrideCallRegexCheck.indexIn(snip.code()) != -1) + for (const CodeSnip &snip : qAsConst(snips)) { + if (snip.code().contains(overrideCallRegexCheck)) return true; } return false; @@ -2034,15 +2139,17 @@ bool ShibokenGenerator::injectedCodeCallsPythonOverride(const AbstractMetaFuncti bool ShibokenGenerator::injectedCodeHasReturnValueAttribution(const AbstractMetaFunction* func, TypeSystem::Language language) { - static QRegExp retValAttributionRegexCheck_native(QLatin1String("%0\\s*=[^=]\\s*.+")); - static QRegExp retValAttributionRegexCheck_target(QLatin1String("%PYARG_0\\s*=[^=]\\s*.+")); + static const QRegularExpression retValAttributionRegexCheck_native(QStringLiteral("%0\\s*=[^=]\\s*.+")); + Q_ASSERT(retValAttributionRegexCheck_native.isValid()); + static const QRegularExpression retValAttributionRegexCheck_target(QStringLiteral("%PYARG_0\\s*=[^=]\\s*.+")); + Q_ASSERT(retValAttributionRegexCheck_target.isValid()); CodeSnipList snips = func->injectedCodeSnips(TypeSystem::CodeSnipPositionAny, language); - foreach (const CodeSnip &snip, snips) { + for (const CodeSnip &snip : qAsConst(snips)) { if (language == TypeSystem::TargetLangCode) { - if (retValAttributionRegexCheck_target.indexIn(snip.code()) != -1) + if (snip.code().contains(retValAttributionRegexCheck_target)) return true; } else { - if (retValAttributionRegexCheck_native.indexIn(snip.code()) != -1) + if (snip.code().contains(retValAttributionRegexCheck_native)) return true; } } @@ -2052,11 +2159,10 @@ bool ShibokenGenerator::injectedCodeHasReturnValueAttribution(const AbstractMeta bool ShibokenGenerator::injectedCodeUsesArgument(const AbstractMetaFunction* func, int argumentIndex) { CodeSnipList snips = func->injectedCodeSnips(TypeSystem::CodeSnipPositionAny); - foreach (const CodeSnip &snip, snips) { + const QRegularExpression argRegEx = placeHolderRegex(argumentIndex + 1); + for (const CodeSnip &snip : qAsConst(snips)) { QString code = snip.code(); - if (code.contains(QLatin1String("%ARGUMENT_NAMES"))) - return true; - if (code.contains(QRegExp(QStringLiteral("%%1\\b").arg(argumentIndex + 1)))) + if (code.contains(QLatin1String("%ARGUMENT_NAMES")) || code.contains(argRegEx)) return true; } return false; @@ -2083,7 +2189,7 @@ bool ShibokenGenerator::classNeedsGetattroFunction(const AbstractMetaClass* meta const FunctionGroupMap &functionGroup = getFunctionGroups(metaClass); for (FunctionGroupMapIt it = functionGroup.cbegin(), end = functionGroup.cend(); it != end; ++it) { AbstractMetaFunctionList overloads; - foreach (AbstractMetaFunction* func, it.value()) { + for (AbstractMetaFunction *func : qAsConst(it.value())) { if (func->isAssignmentOperator() || func->isCastOperator() || func->isModifiedRemoved() || func->isPrivate() || func->ownerClass() != func->implementingClass() || func->isConstructor() || func->isOperatorOverload()) @@ -2114,7 +2220,7 @@ AbstractMetaFunctionList ShibokenGenerator::getMethodsWithBothStaticAndNonStatic const FunctionGroupMap &functionGroups = getFunctionGroups(metaClass); for (FunctionGroupMapIt it = functionGroups.cbegin(), end = functionGroups.cend(); it != end; ++it) { AbstractMetaFunctionList overloads; - foreach (AbstractMetaFunction* func, it.value()) { + for (AbstractMetaFunction *func : qAsConst(it.value())) { if (func->isAssignmentOperator() || func->isCastOperator() || func->isModifiedRemoved() || func->isPrivate() || func->ownerClass() != func->implementingClass() || func->isConstructor() || func->isOperatorOverload()) @@ -2124,7 +2230,7 @@ AbstractMetaFunctionList ShibokenGenerator::getMethodsWithBothStaticAndNonStatic if (overloads.isEmpty()) continue; if (OverloadData::hasStaticAndInstanceFunctions(overloads)) - methods.append(overloads.first()); + methods.append(overloads.constFirst()); } } return methods; @@ -2134,7 +2240,8 @@ AbstractMetaClassList ShibokenGenerator::getBaseClasses(const AbstractMetaClass* { AbstractMetaClassList baseClasses; if (metaClass) { - foreach (const QString &parent, metaClass->baseClassNames()) { + const QStringList &baseClassNames = metaClass->baseClassNames(); + for (const QString &parent : baseClassNames) { AbstractMetaClass *clazz = AbstractMetaClass::findClass(classes(), parent); if (clazz) baseClasses << clazz; @@ -2157,7 +2264,7 @@ AbstractMetaClassList ShibokenGenerator::getAllAncestors(const AbstractMetaClass AbstractMetaClassList result; if (metaClass) { AbstractMetaClassList baseClasses = getBaseClasses(metaClass); - foreach (AbstractMetaClass* base, baseClasses) { + for (AbstractMetaClass *base : qAsConst(baseClasses)) { result.append(base); result.append(getAllAncestors(base)); } @@ -2268,7 +2375,7 @@ AbstractMetaType* ShibokenGenerator::buildAbstractMetaTypeFromString(QString typ metaType->setReferenceType(refType); metaType->setConstant(isConst); metaType->setTypeUsagePattern(AbstractMetaType::ContainerPattern); - foreach (const QString& instantiation, instantiatedTypes) { + for (const QString &instantiation : qAsConst(instantiatedTypes)) { AbstractMetaType* tmplArgType = buildAbstractMetaTypeFromString(instantiation); metaType->addInstantiation(tmplArgType); } @@ -2303,7 +2410,7 @@ AbstractMetaType* ShibokenGenerator::buildAbstractMetaTypeFromAbstractMetaClass( static void dumpFunction(AbstractMetaFunctionList lst) { qDebug() << "DUMP FUNCTIONS: "; - foreach (AbstractMetaFunction *func, lst) + for (AbstractMetaFunction *func : qAsConst(lst)) qDebug() << "*" << func->ownerClass()->name() << func->signature() << "Private: " << func->isPrivate() @@ -2331,7 +2438,7 @@ QMap< QString, AbstractMetaFunctionList > ShibokenGenerator::getFunctionGroups(c AbstractMetaFunctionList lst = scope ? scope->functions() : globalFunctions(); QMap<QString, AbstractMetaFunctionList> results; - foreach (AbstractMetaFunction* func, lst) { + for (AbstractMetaFunction *func : qAsConst(lst)) { if (isGroupable(func)) results[func->name()].append(func); } @@ -2370,7 +2477,7 @@ AbstractMetaFunctionList ShibokenGenerator::getFunctionOverloads(const AbstractM AbstractMetaFunctionList results; QSet<QString> seenSignatures; - foreach (AbstractMetaFunction* func, lst) { + for (AbstractMetaFunction *func : qAsConst(lst)) { if (func->name() != functionName) continue; if (isGroupable(func)) { @@ -2387,9 +2494,10 @@ QPair< int, int > ShibokenGenerator::getMinMaxArguments(const AbstractMetaFuncti int minArgs = std::numeric_limits<int>::max(); int maxArgs = 0; - foreach (const AbstractMetaFunction* func, overloads) { + for (const AbstractMetaFunction* func : qAsConst(overloads)) { int numArgs = 0; - foreach (const AbstractMetaArgument* arg, func->arguments()) { + const AbstractMetaArgumentList &arguments = func->arguments(); + for (const AbstractMetaArgument *arg : arguments) { if (!func->argumentRemoved(arg->argumentIndex() + 1)) numArgs++; } @@ -2399,27 +2507,26 @@ QPair< int, int > ShibokenGenerator::getMinMaxArguments(const AbstractMetaFuncti return qMakePair(minArgs, maxArgs); } -QMap<QString, QString> ShibokenGenerator::options() const +Generator::OptionDescriptions ShibokenGenerator::options() const { - QMap<QString, QString> opts(Generator::options()); - opts.insert(QLatin1String(AVOID_PROTECTED_HACK), - QLatin1String("Avoid the use of the '#define protected public' hack.")); - opts.insert(QLatin1String(PARENT_CTOR_HEURISTIC), - QLatin1String("Enable heuristics to detect parent relationship on constructors.")); - opts.insert(QLatin1String(RETURN_VALUE_HEURISTIC), - QLatin1String("Enable heuristics to detect parent relationship on return values (USE WITH CAUTION!)")); - opts.insert(QLatin1String(ENABLE_PYSIDE_EXTENSIONS), - QLatin1String("Enable PySide extensions, such as support for signal/slots, use this if you are creating a binding for a Qt-based library.")); - opts.insert(QLatin1String(DISABLE_VERBOSE_ERROR_MESSAGES), - QLatin1String("Disable verbose error messages. Turn the python code hard to debug but safe few kB on the generated bindings.")); - opts.insert(QLatin1String(USE_ISNULL_AS_NB_NONZERO), - QLatin1String("If a class have an isNull()const method, it will be used to compute the value of boolean casts")); - return opts; + return OptionDescriptions() + << qMakePair(QLatin1String(AVOID_PROTECTED_HACK), + QLatin1String("Avoid the use of the '#define protected public' hack.")) + << qMakePair(QLatin1String(DISABLE_VERBOSE_ERROR_MESSAGES), + QLatin1String("Disable verbose error messages. Turn the python code hard to debug but safe few kB on the generated bindings.")) + << qMakePair(QLatin1String(PARENT_CTOR_HEURISTIC), + QLatin1String("Enable heuristics to detect parent relationship on constructors.")) + << qMakePair(QLatin1String(ENABLE_PYSIDE_EXTENSIONS), + QLatin1String("Enable PySide extensions, such as support for signal/slots, use this if you are creating a binding for a Qt-based library.")) + << qMakePair(QLatin1String(RETURN_VALUE_HEURISTIC), + QLatin1String("Enable heuristics to detect parent relationship on return values (USE WITH CAUTION!)")) + << qMakePair(QLatin1String(USE_ISNULL_AS_NB_NONZERO), + QLatin1String("If a class have an isNull()const method, it will be used to compute the value of boolean casts")); } static void getCode(QStringList& code, const CodeSnipList& codeSnips) { - foreach (const CodeSnip& snip, codeSnips) + for (const CodeSnip &snip : qAsConst(codeSnips)) code.append(snip.code()); } @@ -2438,7 +2545,7 @@ static void getCode(QStringList& code, const TypeEntry* type) if (toCppConversions.isEmpty()) return; - foreach (CustomConversion::TargetToNativeConversion* toNative, toCppConversions) + for (CustomConversion::TargetToNativeConversion *toNative : qAsConst(toCppConversions)) code.append(toNative->conversion()); } @@ -2453,20 +2560,23 @@ bool ShibokenGenerator::doSetup(const QMap<QString, QString>& args) TypeDatabase* td = TypeDatabase::instance(); QStringList snips; - foreach (const PrimitiveTypeEntry* type, primitiveTypes()) + const PrimitiveTypeEntryList &primitiveTypeList = primitiveTypes(); + for (const PrimitiveTypeEntry *type : primitiveTypeList) getCode(snips, type); - foreach (const ContainerTypeEntry* type, containerTypes()) + const ContainerTypeEntryList &containerTypeList = containerTypes(); + for (const ContainerTypeEntry *type : containerTypeList) getCode(snips, type); - foreach (const AbstractMetaClass* metaClass, classes()) + const AbstractMetaClassList &classList = classes(); + for (const AbstractMetaClass *metaClass : classList) getCode(snips, metaClass->typeEntry()); getCode(snips, td->findType(packageName())); const FunctionGroupMap &functionGroups = getFunctionGroups(); for (FunctionGroupMapIt it = functionGroups.cbegin(), end = functionGroups.cend(); it != end; ++it) { - foreach (AbstractMetaFunction* func, it.value()) + for (AbstractMetaFunction *func : it.value()) getCode(snips, func->injectedCodeSnips()); } - foreach (const QString& code, snips) { + for (const QString &code : qAsConst(snips)) { collectContainerTypesFromConverterMacros(code, true); collectContainerTypesFromConverterMacros(code, false); } @@ -2536,7 +2646,8 @@ QString ShibokenGenerator::convertersVariableName(const QString& moduleName) con static QString processInstantiationsVariableName(const AbstractMetaType* type) { QString res = QLatin1Char('_') + _fixedCppTypeName(type->typeEntry()->qualifiedCppName()).toUpper(); - foreach (const AbstractMetaType* instantiation, type->instantiations()) { + const AbstractMetaTypeList &instantiations = type->instantiations(); + for (const AbstractMetaType *instantiation : instantiations) { res += instantiation->isContainer() ? processInstantiationsVariableName(instantiation) : QLatin1Char('_') + _fixedCppTypeName(instantiation->cppSignature()).toUpper(); @@ -2551,7 +2662,8 @@ QString ShibokenGenerator::getTypeIndexVariableName(const AbstractMetaClass* met return QString(); QString base = _fixedCppTypeName(templateBaseClass->typeEntry()->qualifiedCppName()).toUpper(); QString instantiations; - foreach (const AbstractMetaType* instantiation, metaClass->templateBaseClassInstantiations()) + const AbstractMetaTypeList &templateBaseClassInstantiations = metaClass->templateBaseClassInstantiations(); + for (const AbstractMetaType *instantiation : templateBaseClassInstantiations) instantiations += processInstantiationsVariableName(instantiation); return QString::fromLatin1("SBK_%1%2_IDX").arg(base, instantiations); } @@ -2615,8 +2727,9 @@ QString ShibokenGenerator::getDefaultValue(const AbstractMetaFunction* func, co return arg->defaultValueExpression(); //Check modifications - foreach(FunctionModification m, func->modifications()) { - foreach(ArgumentModification am, m.argument_mods) { + const FunctionModificationList &mods = func->modifications(); + for (const FunctionModification &m : mods) { + for (const ArgumentModification &am : m.argument_mods) { if (am.index == (arg->argumentIndex() + 1)) return am.replacedDefaultExpression; } diff --git a/sources/shiboken2/generator/shiboken2/shibokengenerator.h b/sources/shiboken2/generator/shiboken2/shibokengenerator.h index d36962cf1..5ed7f79f6 100644 --- a/sources/shiboken2/generator/shiboken2/shibokengenerator.h +++ b/sources/shiboken2/generator/shiboken2/shibokengenerator.h @@ -56,6 +56,8 @@ #include "typesystem.h" +#include <QtCore/QRegularExpression> + class DocParser; class CodeSnip; class OverloadData; @@ -132,7 +134,7 @@ public: void writeArgumentNames(QTextStream &s, const AbstractMetaFunction* func, - Options options = NoOption) const; + Options options = NoOption) const override; /** * Function used to write the fucntion arguments on the class buffer. @@ -143,32 +145,32 @@ public: */ void writeFunctionArguments(QTextStream &s, const AbstractMetaFunction* func, - Options options = NoOption) const; + Options options = NoOption) const override; QString functionReturnType(const AbstractMetaFunction* func, Options options = NoOption) const; /// Utility function for writeCodeSnips. typedef QPair<const AbstractMetaArgument*, QString> ArgumentVarReplacementPair; - typedef QList<ArgumentVarReplacementPair> ArgumentVarReplacementList; + typedef QVector<ArgumentVarReplacementPair> ArgumentVarReplacementList; ArgumentVarReplacementList getArgumentReplacement(const AbstractMetaFunction* func, bool usePyArgs, TypeSystem::Language language, const AbstractMetaArgument* lastArg); /// Write user's custom code snippets at class or module level. void writeCodeSnips(QTextStream& s, - const QList<CodeSnip>& codeSnips, + const QVector<CodeSnip> & codeSnips, TypeSystem::CodeSnipPosition position, TypeSystem::Language language, const AbstractMetaClass* context = 0); /// Write user's custom code snippets at function level. void writeCodeSnips(QTextStream& s, - const QList<CodeSnip>& codeSnips, + const QVector<CodeSnip> & codeSnips, TypeSystem::CodeSnipPosition position, TypeSystem::Language language, const AbstractMetaFunction* func, const AbstractMetaArgument* lastArg = 0); /// Returns a string with the user's custom code snippets that comply with \p position and \p language. - QString getCodeSnippets(const QList<CodeSnip>& codeSnips, TypeSystem::CodeSnipPosition position, TypeSystem::Language language); + QString getCodeSnippets(const QVector<CodeSnip> & codeSnips, TypeSystem::CodeSnipPosition position, TypeSystem::Language language); /// Replaces variables for the user's custom code at global or class level. void processCodeSnip(QString& code, const AbstractMetaClass* context = 0); @@ -409,7 +411,11 @@ public: QString cpythonWrapperCPtr(const TypeEntry* type, QString argName); /// Guesses the scope to where belongs an argument's default value. - QString guessScopeForDefaultValue(const AbstractMetaFunction* func, const AbstractMetaArgument* arg); + QString guessScopeForDefaultValue(const AbstractMetaFunction *func, + const AbstractMetaArgument *arg) const; + QString guessScopeForDefaultFlagsValue(const AbstractMetaFunction *func, + const AbstractMetaArgument *arg, + const QString &value) const; QString cpythonEnumName(const EnumTypeEntry* enumEntry); QString cpythonEnumName(const AbstractMetaEnum* metaEnum); @@ -428,7 +434,7 @@ public: QString extendedIsConvertibleFunctionName(const TypeEntry* targetType) const; QString extendedToCppFunctionName(const TypeEntry* targetType) const; - QMap< QString, QString > options() const; + OptionDescriptions options() const override; /// Returns true if the user enabled the so called "parent constructor heuristic". bool useCtorHeuristic() const; @@ -513,12 +519,12 @@ protected: // All data about extended converters: the type entries of the target type, and a // list of AbstractMetaClasses accepted as argument for the conversion. - typedef QHash<const TypeEntry*, QList<const AbstractMetaClass*> > ExtendedConverterData; + typedef QHash<const TypeEntry *, QVector<const AbstractMetaClass *> > ExtendedConverterData; /// Returns all extended conversions for the current module. ExtendedConverterData getExtendedConverters() const; /// Returns a list of converters for the non wrapper types of the current module. - QList<const CustomConversion*> getPrimitiveCustomConversions(); + QVector<const CustomConversion *> getPrimitiveCustomConversions(); /// Returns true if the Python wrapper for the received OverloadData must accept a list of arguments. static bool pythonFunctionWrapperUsesListOfArguments(const OverloadData& overloadData); @@ -549,7 +555,7 @@ private: /// Type system converter variable replacement names and regular expressions. QString m_typeSystemConvName[TypeSystemConverterVariables]; - QRegExp m_typeSystemConvRegEx[TypeSystemConverterVariables]; + QRegularExpression m_typeSystemConvRegEx[TypeSystemConverterVariables]; }; #endif // SHIBOKENGENERATOR_H diff --git a/sources/shiboken2/header.COMM b/sources/shiboken2/header.COMM deleted file mode 100644 index 1c8cb00e7..000000000 --- a/sources/shiboken2/header.COMM +++ /dev/null @@ -1,20 +0,0 @@ -/****************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the <Fill> module. -** -** $QT_BEGIN_LICENSE:COMM$ -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** $QT_END_LICENSE$ -** -******************************************************************************/ diff --git a/sources/shiboken2/header.LGPL-ONLY b/sources/shiboken2/header.LGPL-ONLY deleted file mode 100644 index 9a676032e..000000000 --- a/sources/shiboken2/header.LGPL-ONLY +++ /dev/null @@ -1,22 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the FOO module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL-ONLY$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** If you have questions regarding the use of this file, please contact -** us via http://www.qt.io/contact-us/. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ diff --git a/sources/shiboken2/header.LGPL21 b/sources/shiboken2/header.LGPL21 deleted file mode 100644 index 533390b07..000000000 --- a/sources/shiboken2/header.LGPL21 +++ /dev/null @@ -1,33 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the FOO module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - diff --git a/sources/shiboken2/header.LGPL3 b/sources/shiboken2/header.LGPL3 deleted file mode 100644 index d9a65c2e4..000000000 --- a/sources/shiboken2/header.LGPL3 +++ /dev/null @@ -1,36 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the FOO module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL3$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPLv3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or later as published by the Free -** Software Foundation and appearing in the file LICENSE.GPL included in -** the packaging of this file. Please review the following information to -** ensure the GNU General Public License version 2.0 requirements will be -** met: http://www.gnu.org/licenses/gpl-2.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - diff --git a/sources/shiboken2/header.LGPL3-COMM b/sources/shiboken2/header.LGPL3-COMM deleted file mode 100644 index b5dc15d38..000000000 --- a/sources/shiboken2/header.LGPL3-COMM +++ /dev/null @@ -1,28 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the FOO module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL3-COMM$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPLv3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - diff --git a/sources/shiboken2/libshiboken/CMakeLists.txt b/sources/shiboken2/libshiboken/CMakeLists.txt index 6e725e6af..e87cf07fd 100644 --- a/sources/shiboken2/libshiboken/CMakeLists.txt +++ b/sources/shiboken2/libshiboken/CMakeLists.txt @@ -1,5 +1,22 @@ project(libshiboken) +macro(get_numpy_location) + execute_process( + COMMAND ${PYTHON_EXECUTABLE} -c "if True: + import sys + import os + numpy = '' + for p in sys.path: + if 'site-' in p: + numpy = os.path.join(p, 'numpy') + if os.path.exists(numpy): + print(os.path.realpath(numpy)) + break" + OUTPUT_VARIABLE PYTHON_NUMPY_LOCATION + OUTPUT_STRIP_TRAILING_WHITESPACE) + message("PYTHON_NUMPY_LOCATION: " ${PYTHON_NUMPY_LOCATION}) +endmacro() + option(ENABLE_VERSION_SUFFIX "Used to use current version in suffix to generated files. This is used to allow multiples versions installed simultaneous." FALSE) if(ENABLE_VERSION_SUFFIX) set(shiboken2_SUFFIX "-${shiboken_MAJOR_VERSION}.${shiboken_MINOR_VERSION}") @@ -10,14 +27,6 @@ endif() configure_file("${CMAKE_CURRENT_SOURCE_DIR}/sbkversion.h.in" "${CMAKE_CURRENT_BINARY_DIR}/sbkversion.h" @ONLY) -#Find installed sparsehash -find_path(SPARSEHASH_INCLUDE_PATH sparseconfig.h PATH_SUFFIXES "/google/sparsehash") -if(SPARSEHASH_INCLUDE_PATH) - message(STATUS "Using system hash found in: ${SPARSEHASH_INCLUDE_PATH}") -else() - set(SPARSEHASH_INCLUDE_PATH ${CMAKE_SOURCE_DIR}/ext/sparsehash) -endif() - set(libshiboken_MAJOR_VERSION ${shiboken_MAJOR_VERSION}) set(libshiboken_MINOR_VERSION ${shiboken_MINOR_VERSION}) set(libshiboken_MICRO_VERSION ${shiboken_MICRO_VERSION}) @@ -29,6 +38,7 @@ basewrapper.cpp debugfreehook.cpp gilstate.cpp helper.cpp +sbkarrayconverter.cpp sbkconverter.cpp sbkenum.cpp sbkmodule.cpp @@ -41,10 +51,19 @@ qapp_macro.cpp voidptr.cpp ) -include_directories(${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_CURRENT_BINARY_DIR} - ${SBK_PYTHON_INCLUDE_DIR} - ${SPARSEHASH_INCLUDE_PATH}) +get_numpy_location() + +set(libshiboken_INCLUDES ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ${SBK_PYTHON_INCLUDE_DIR}) + +if (NOT "${PYTHON_NUMPY_LOCATION}" STREQUAL "") + set(libshiboken_INCLUDES ${libshiboken_INCLUDES} ${PYTHON_NUMPY_LOCATION}/core/include) + set(libshiboken_SRC ${libshiboken_SRC} sbknumpyarrayconverter.cpp) + add_definitions(-DHAVE_NUMPY -DNPY_NO_DEPRECATED_API=NPY_1_7_API_VERSION) +endif() + +set(APIEXTRACTOR_EXTRA_INCLUDES ${APIEXTRACTOR_EXTRA_INCLUDES} ${LIBXSLT_INCLUDE_DIR} ${LIBXML2_INCLUDE_DIR}) + +include_directories(${libshiboken_INCLUDES}) add_library(libshiboken SHARED ${libshiboken_SRC}) target_link_libraries(libshiboken ${SBK_PYTHON_LIBRARIES}) set_target_properties(libshiboken PROPERTIES OUTPUT_NAME "shiboken2${shiboken2_SUFFIX}${PYTHON_SHARED_LIBRARY_SUFFIX}" @@ -58,6 +77,7 @@ install(FILES bindingmanager.h gilstate.h helper.h + sbkarrayconverter.h sbkconverter.h sbkenum.h sbkmodule.h diff --git a/sources/shiboken2/libshiboken/basewrapper.cpp b/sources/shiboken2/libshiboken/basewrapper.cpp index 270a5df94..d7d37971c 100644 --- a/sources/shiboken2/libshiboken/basewrapper.cpp +++ b/sources/shiboken2/libshiboken/basewrapper.cpp @@ -542,7 +542,6 @@ void DeallocVisitor::done() DtorCallerVisitor::done(); } -namespace Module { void init(); } namespace Conversions { void init(); } void init() @@ -551,7 +550,6 @@ void init() if (shibokenAlreadInitialised) return; - Module::init(); Conversions::init(); PyEval_InitThreads(); @@ -681,14 +679,6 @@ bool canCallConstructor(PyTypeObject* myType, PyTypeObject* ctorType) return true; } - -bool hasExternalCppConversions(SbkObjectType*) { return false; } // DEPRECATED. -bool isExternalConvertible(SbkObjectType *, PyObject *) { return false; } // DEPRECATED. -void setExternalCppConversionFunction(SbkObjectType*, ExtendedToCppFunc) {} // DEPRECATED. -void setExternalIsConvertibleFunction(SbkObjectType*, ExtendedIsConvertibleFunc) {} // DEPRECATED. -void* callExternalCppConversion(SbkObjectType*, PyObject*) { return 0; } // DEPRECATED. - - bool hasCast(SbkObjectType* type) { return type->d->mi_specialcast != 0; @@ -721,18 +711,6 @@ void setTypeDiscoveryFunctionV2(SbkObjectType* self, TypeDiscoveryFuncV2 func) self->d->type_discovery = func; } -void setTypeDiscoveryFunction(SbkObjectType* self, TypeDiscoveryFunc func) -{ - self->d->type_discovery = (TypeDiscoveryFuncV2)func; -} - -TypeDiscoveryFunc getTypeDiscoveryFunction(SbkObjectType* self) -{ - // This is an illegal cast because the return value is different, - // but nobody ever used this function, so... =] - return (TypeDiscoveryFunc)self->d->type_discovery; -} - void copyMultimpleheritance(SbkObjectType* self, SbkObjectType* other) { self->d->mi_init = other->d->mi_init; @@ -840,13 +818,15 @@ Py_hash_t hash(PyObject* pyObj) static void setSequenceOwnership(PyObject* pyObj, bool owner) { if (PySequence_Check(pyObj)) { - std::list<SbkObject*> objs = splitPyObject(pyObj); - std::list<SbkObject*>::const_iterator it = objs.begin(); - for(; it != objs.end(); ++it) { - if (owner) - getOwnership(*it); - else - releaseOwnership(*it); + Py_ssize_t size = PySequence_Size(pyObj); + if (size > 0) { + std::list<SbkObject*> objs = splitPyObject(pyObj); + for (auto it = objs.begin(), end = objs.end(); it != end; ++it) { + if (owner) + getOwnership(*it); + else + releaseOwnership(*it); + } } } else if (Object::checkType(pyObj)) { if (owner) @@ -1053,11 +1033,6 @@ void makeValid(SbkObject* self) } } -bool hasParentInfo(SbkObject* pyObj) -{ - return pyObj->d->parentInfo != 0; -} - void* cppPointer(SbkObject* pyObj, PyTypeObject* desiredType) { PyTypeObject* type = Py_TYPE(pyObj); diff --git a/sources/shiboken2/libshiboken/basewrapper.h b/sources/shiboken2/libshiboken/basewrapper.h index bd2d6820f..f6a7352f7 100644 --- a/sources/shiboken2/libshiboken/basewrapper.h +++ b/sources/shiboken2/libshiboken/basewrapper.h @@ -151,14 +151,6 @@ LIBSHIBOKEN_API bool isUserType(PyTypeObject* pyObj); */ LIBSHIBOKEN_API bool canCallConstructor(PyTypeObject* myType, PyTypeObject* ctorType); - -LIBSHIBOKEN_API bool hasExternalCppConversions(SbkObjectType*); // DEPRECATED. -LIBSHIBOKEN_API bool isExternalConvertible(SbkObjectType*, PyObject*); // DEPRECATED. -LIBSHIBOKEN_API void setExternalCppConversionFunction(SbkObjectType*, ExtendedToCppFunc); // DEPRECATED. -LIBSHIBOKEN_API void setExternalIsConvertibleFunction(SbkObjectType*, ExtendedIsConvertibleFunc); // DEPRECATED. -LIBSHIBOKEN_API void* callExternalCppConversion(SbkObjectType*, PyObject*); // DEPRECATED. - - /** * Tells if the \p type represents an object of a class with multiple inheritance in C++. * When this occurs, the C++ pointer held by the Python wrapper will need to be cast when @@ -180,9 +172,6 @@ LIBSHIBOKEN_API void setOriginalName(SbkObjectType* self, const char* nam LIBSHIBOKEN_API const char* getOriginalName(SbkObjectType* self); LIBSHIBOKEN_API void setTypeDiscoveryFunctionV2(SbkObjectType* self, TypeDiscoveryFuncV2 func); -LIBSHIBOKEN_API SBK_DEPRECATED(void setTypeDiscoveryFunction(SbkObjectType* self, TypeDiscoveryFunc func)); -LIBSHIBOKEN_API SBK_DEPRECATED(TypeDiscoveryFunc getTypeDiscoveryFunction(SbkObjectType* self)); - LIBSHIBOKEN_API void copyMultimpleheritance(SbkObjectType* self, SbkObjectType* other); LIBSHIBOKEN_API void setMultipleIheritanceFunction(SbkObjectType* self, MultipleInheritanceInitFunction func); LIBSHIBOKEN_API MultipleInheritanceInitFunction getMultipleIheritanceFunction(SbkObjectType* self); @@ -333,11 +322,6 @@ LIBSHIBOKEN_API void releaseOwnership(PyObject* pyObj); LIBSHIBOKEN_API void releaseOwnership(SbkObject* pyObj); /** - * Returns true if the pyObj holds information about their parents. - */ -LIBSHIBOKEN_API bool hasParentInfo(SbkObject* pyObj); - -/** * Get the C++ pointer of type \p desiredType from a Python object. */ LIBSHIBOKEN_API void* cppPointer(SbkObject* pyObj, PyTypeObject* desiredType); @@ -387,12 +371,6 @@ LIBSHIBOKEN_API void setParent(PyObject* parent, PyObject* child); LIBSHIBOKEN_API void removeParent(SbkObject* child, bool giveOwnershipBack = true, bool keepReferenc = false); /** -* \internal This is an internal function called by tp_dealloc, it's exported just for technical reasons. -* \note Do not call this function inside your bindings. -*/ -LIBSHIBOKEN_API void destroyParentInfo(SbkObject* obj, bool removeFromParent = true); - -/** * Mark the object as invalid */ LIBSHIBOKEN_API void invalidate(SbkObject* self); diff --git a/sources/shiboken2/libshiboken/bindingmanager.cpp b/sources/shiboken2/libshiboken/bindingmanager.cpp index d7e122cd7..3308ef972 100644 --- a/sources/shiboken2/libshiboken/bindingmanager.cpp +++ b/sources/shiboken2/libshiboken/bindingmanager.cpp @@ -40,7 +40,6 @@ #include "basewrapper.h" #include "basewrapper_p.h" #include "bindingmanager.h" -#include "google/dense_hash_map" #include "sbkdbg.h" #include "gilstate.h" #include "sbkstring.h" @@ -48,23 +47,23 @@ #include <cstddef> #include <fstream> +#include <unordered_map> namespace Shiboken { -typedef google::dense_hash_map<const void*, SbkObject*> WrapperMap; +typedef std::unordered_map<const void *, SbkObject *> WrapperMap; class Graph { public: typedef std::list<SbkObjectType*> NodeList; - typedef google::dense_hash_map<SbkObjectType*, NodeList> Edges; + typedef std::unordered_map<SbkObjectType *, NodeList> Edges; Edges m_edges; Graph() { - m_edges.set_empty_key(0); } void addEdge(SbkObjectType* from, SbkObjectType* to) @@ -172,8 +171,6 @@ void BindingManager::BindingManagerPrivate::assignWrapper(SbkObject* wrapper, co BindingManager::BindingManager() { m_d = new BindingManager::BindingManagerPrivate; - m_d->wrapperMapper.set_empty_key((WrapperMap::key_type)0); - m_d->wrapperMapper.set_deleted_key((WrapperMap::key_type)1); #ifdef SHIBOKEN_INSTALL_FREE_DEBUG_HOOK debugInstallFreeHook(); diff --git a/sources/shiboken2/libshiboken/sbkarrayconverter.cpp b/sources/shiboken2/libshiboken/sbkarrayconverter.cpp new file mode 100644 index 000000000..c22015709 --- /dev/null +++ b/sources/shiboken2/libshiboken/sbkarrayconverter.cpp @@ -0,0 +1,289 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "sbkarrayconverter.h" +#include "sbkarrayconverter_p.h" +#include "helper.h" +#include "sbkconverter.h" +#include "sbkconverter_p.h" + +#include <longobject.h> +#include <floatobject.h> + +#include <algorithm> + +static SbkArrayConverter *ArrayTypeConverters[Shiboken::Conversions::SBK_ARRAY_IDX_SIZE] [2] = {}; + +namespace Shiboken { +namespace Conversions { + +// Check whether Predicate is true for all elements of a sequence +template <class Predicate> +static bool sequenceAllOf(PyObject *pyIn, Predicate p) +{ + const Py_ssize_t size = PySequence_Size(pyIn); + for (Py_ssize_t i = 0; i < size; ++i) { + PyObject *item = PySequence_GetItem(pyIn, i); + const bool ok = p(item); + Py_XDECREF(item); + if (!ok) + return false; + } + return true; +} + +// Convert a sequence to output iterator +template <class T, class Converter> +inline void convertPySequence(PyObject *pyIn, Converter c, T *out) +{ + const Py_ssize_t size = PySequence_Size(pyIn); + for (Py_ssize_t i = 0; i < size; ++i) { + PyObject *item = PySequence_GetItem(pyIn, i); + *out++ = c(item); + Py_XDECREF(item); + } +} + +// Internal, for usage by numpy +SbkArrayConverter *createArrayConverter(IsArrayConvertibleToCppFunc toCppCheckFunc) +{ + SbkArrayConverter *result = new SbkArrayConverter; + result->toCppConversions.push_back(toCppCheckFunc); + return result; +} + +static PythonToCppFunc unimplementedArrayCheck(PyObject *, int, int) +{ + warning(PyExc_RuntimeWarning, 0, "SbkConverter: Unimplemented C++ array type."); + return nullptr; +} + +SbkArrayConverter *unimplementedArrayConverter() +{ + static SbkArrayConverter *result = createArrayConverter(unimplementedArrayCheck); + return result; +} + +// Integers + +static inline bool intCheck(PyObject *pyIn) +{ +#ifdef IS_PY3K + return PyLong_Check(pyIn); +#else + return PyInt_Check(pyIn); +#endif +} + +static short toShort(PyObject *pyIn) { return short(PyLong_AsLong(pyIn)); } + +static void sequenceToCppShortArray(PyObject *pyIn, void *cppOut) +{ + ArrayHandle<short> *handle = reinterpret_cast<ArrayHandle<short> *>(cppOut); + handle->allocate(PySequence_Size(pyIn)); + convertPySequence(pyIn, toShort, handle->data()); +} + +static inline bool sequenceSizeCheck(PyObject *pyIn, int expectedSize = -1) +{ + if (expectedSize >= 0) { + const int size = int(PySequence_Size(pyIn)); + if (size < expectedSize) { + warning(PyExc_RuntimeWarning, 0, "A sequence of size %d was passed to a function that expects %d.", + size, expectedSize); + return false; + } + } + return true; +} + +static inline bool intArrayCheck(PyObject *pyIn, int expectedSize = -1) +{ + return PySequence_Check(pyIn) && sequenceAllOf(pyIn, intCheck) + && sequenceSizeCheck(pyIn, expectedSize); +} + +static PythonToCppFunc sequenceToCppShortArrayCheck(PyObject *pyIn, int dim1, int /* dim2 */) +{ + return intArrayCheck(pyIn, dim1) ? sequenceToCppShortArray : nullptr; +} + +static short toUnsignedShort(PyObject *pyIn) { return static_cast<unsigned short>(PyLong_AsUnsignedLong(pyIn)); } + +static void sequenceToCppUnsignedShortArray(PyObject *pyIn, void *cppOut) +{ + ArrayHandle<unsigned short> *handle = reinterpret_cast<ArrayHandle<unsigned short> *>(cppOut); + handle->allocate(PySequence_Size(pyIn)); + convertPySequence(pyIn, toUnsignedShort, handle->data()); +} + +static PythonToCppFunc sequenceToCppUnsignedShortArrayCheck(PyObject *pyIn, int dim1, int /* dim2 */) +{ + return intArrayCheck(pyIn, dim1) ? sequenceToCppUnsignedShortArray : nullptr; +} + +static void sequenceToCppIntArray(PyObject *pyIn, void *cppOut) +{ + ArrayHandle<int> *handle = reinterpret_cast<ArrayHandle<int> *>(cppOut); + handle->allocate(PySequence_Size(pyIn)); + convertPySequence(pyIn, _PyLong_AsInt, handle->data()); +} + +static PythonToCppFunc sequenceToCppIntArrayCheck(PyObject *pyIn, int dim1, int /* dim2 */) +{ + return intArrayCheck(pyIn, dim1) ? sequenceToCppIntArray : nullptr; +} + +static void sequenceToCppUnsignedArray(PyObject *pyIn, void *cppOut) +{ + ArrayHandle<unsigned> *handle = reinterpret_cast<ArrayHandle<unsigned> *>(cppOut); + handle->allocate(PySequence_Size(pyIn)); + convertPySequence(pyIn, PyLong_AsUnsignedLong, handle->data()); +} + +static PythonToCppFunc sequenceToCppUnsignedArrayCheck(PyObject *pyIn, int dim1, int /* dim2 */) +{ + return intArrayCheck(pyIn, dim1) ? sequenceToCppUnsignedArray : nullptr; +} + +static void sequenceToCppLongLongArray(PyObject *pyIn, void *cppOut) +{ + ArrayHandle<long long> *handle = reinterpret_cast<ArrayHandle<long long> *>(cppOut); + handle->allocate(PySequence_Size(pyIn)); + convertPySequence(pyIn, PyLong_AsLongLong, handle->data()); +} + +static PythonToCppFunc sequenceToCppLongLongArrayCheck(PyObject *pyIn, int dim1, int /* dim2 */) +{ + return intArrayCheck(pyIn, dim1) ? sequenceToCppLongLongArray : nullptr; +} + +static void sequenceToCppUnsignedLongLongArray(PyObject *pyIn, void *cppOut) +{ + ArrayHandle<unsigned long long> *handle = reinterpret_cast<ArrayHandle<unsigned long long> *>(cppOut); + handle->allocate(PySequence_Size(pyIn)); + convertPySequence(pyIn, PyLong_AsUnsignedLongLong, handle->data()); +} + +static PythonToCppFunc sequenceToCppUnsignedLongLongArrayCheck(PyObject *pyIn, int dim1, int /* dim2 */) +{ + return intArrayCheck(pyIn, dim1) ? sequenceToCppUnsignedLongLongArray : nullptr; +} + +// Float + +static inline bool floatCheck(PyObject *pyIn) { return PyFloat_Check(pyIn); } + +static inline bool floatArrayCheck(PyObject *pyIn, int expectedSize = -1) +{ + return PySequence_Check(pyIn) && sequenceAllOf(pyIn, floatCheck) + && sequenceSizeCheck(pyIn, expectedSize); +} + +static void sequenceToCppDoubleArray(PyObject *pyIn, void *cppOut) +{ + ArrayHandle<double> *handle = reinterpret_cast<ArrayHandle<double> *>(cppOut); + handle->allocate(PySequence_Size(pyIn)); + convertPySequence(pyIn, PyFloat_AsDouble, handle->data()); +} + +static inline float pyToFloat(PyObject *pyIn) { return float(PyFloat_AsDouble(pyIn)); } + +static void sequenceToCppFloatArray(PyObject *pyIn, void *cppOut) +{ + ArrayHandle<float> *handle = reinterpret_cast<ArrayHandle<float> *>(cppOut); + handle->allocate(PySequence_Size(pyIn)); + convertPySequence(pyIn, pyToFloat, handle->data()); +} + +static PythonToCppFunc sequenceToCppFloatArrayCheck(PyObject *pyIn, int dim1, int /* dim2 */) +{ + return floatArrayCheck(pyIn, dim1) ? sequenceToCppFloatArray : nullptr; +} + +static PythonToCppFunc sequenceToCppDoubleArrayCheck(PyObject *pyIn, int dim1, int /* dim2 */) +{ + return floatArrayCheck(pyIn, dim1) ? sequenceToCppDoubleArray : nullptr; +} + +#ifdef HAVE_NUMPY +void initNumPyArrayConverters(); +#endif + +void initArrayConverters() +{ + SbkArrayConverter **start = &ArrayTypeConverters[0][0]; + std::fill(start, start + sizeof(ArrayTypeConverters) / sizeof(ArrayTypeConverters[0][0]), nullptr); + // Populate 1-dimensional sequence converters + ArrayTypeConverters[SBK_DOUBLE_ARRAY_IDX][0] = + createArrayConverter(sequenceToCppDoubleArrayCheck); + ArrayTypeConverters[SBK_FLOAT_ARRAY_IDX][0] = + createArrayConverter(sequenceToCppFloatArrayCheck); + ArrayTypeConverters[SBK_SHORT_ARRAY_IDX][0] = + createArrayConverter(sequenceToCppShortArrayCheck); + ArrayTypeConverters[SBK_UNSIGNEDSHORT_ARRAY_IDX][0] = + createArrayConverter(sequenceToCppUnsignedShortArrayCheck); + ArrayTypeConverters[SBK_INT_ARRAY_IDX][0] = + createArrayConverter(sequenceToCppIntArrayCheck); + ArrayTypeConverters[SBK_UNSIGNEDINT_ARRAY_IDX][0] = + createArrayConverter(sequenceToCppUnsignedArrayCheck); + ArrayTypeConverters[SBK_LONGLONG_ARRAY_IDX][0] = + createArrayConverter(sequenceToCppLongLongArrayCheck); + ArrayTypeConverters[SBK_UNSIGNEDLONGLONG_ARRAY_IDX][0] = + createArrayConverter(sequenceToCppUnsignedLongLongArrayCheck); + +#ifdef HAVE_NUMPY + initNumPyArrayConverters(); +#endif +} + +SbkArrayConverter *arrayTypeConverter(int index, int dimension) +{ + SbkArrayConverter *c = ArrayTypeConverters[index][dimension - 1]; + return c ? c : unimplementedArrayConverter(); +} + +// Internal, for usage by numpy +void setArrayTypeConverter(int index, int dimension, SbkArrayConverter *c) +{ + ArrayTypeConverters[index][dimension - 1] = c; +} + +} // namespace Conversions +} // namespace Shiboken diff --git a/sources/shiboken2/libshiboken/sbkarrayconverter.h b/sources/shiboken2/libshiboken/sbkarrayconverter.h new file mode 100644 index 000000000..f3d3e5f98 --- /dev/null +++ b/sources/shiboken2/libshiboken/sbkarrayconverter.h @@ -0,0 +1,171 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef SBKARRAYCONVERTERS_H +#define SBKARRAYCONVERTERS_H + +#include "sbkpython.h" +#include "shibokenmacros.h" + +extern "C" { +struct SbkArrayConverter; +} + +namespace Shiboken { +namespace Conversions { + +enum : int { + SBK_UNIMPLEMENTED_ARRAY_IDX, + SBK_DOUBLE_ARRAY_IDX, + SBK_FLOAT_ARRAY_IDX, + SBK_SHORT_ARRAY_IDX, + SBK_UNSIGNEDSHORT_ARRAY_IDX, + SBK_INT_ARRAY_IDX, + SBK_UNSIGNEDINT_ARRAY_IDX, + SBK_LONGLONG_ARRAY_IDX, + SBK_UNSIGNEDLONGLONG_ARRAY_IDX, + SBK_ARRAY_IDX_SIZE +}; + +/** + * ArrayHandle is the type expected by shiboken2's array converter + * functions. It provides access to array data which it may own + * (in the case of conversions from PySequence) or a flat pointer + * to internal data (in the case of array modules like numpy). + */ + +template <class T> +class ArrayHandle +{ + ArrayHandle(const ArrayHandle &) = delete; + ArrayHandle& operator=(const ArrayHandle &) = delete; +public: + ArrayHandle() {} + ~ArrayHandle() { destroy(); } + + void allocate(Py_ssize_t size); + void setData(T *d, size_t size); + + size_t size() const { return m_size; } + T *data() const { return m_data; } + operator T*() const { return m_data; } + +private: + void destroy(); + + T *m_data = nullptr; + Py_ssize_t m_size = 0; + bool m_owned = false; +}; + +/** + * Similar to ArrayHandle for fixed size 2 dimensional arrays. + * columns is the size of the last dimension + * It only has a setData() methods since it will be used for numpy only. + */ + +template <class T, int columns> +class Array2Handle +{ +public: + typedef T RowType[columns]; + + Array2Handle() {} + + operator RowType*() const { return m_rows; } + + void setData(RowType *d) { m_rows = d; } + +private: + RowType *m_rows = nullptr; +}; + +/// Returns the converter for an array type. +LIBSHIBOKEN_API SbkArrayConverter *arrayTypeConverter(int index, int dimension = 1); + +template <class T> +struct ArrayTypeIndex{ + enum : int { index = SBK_UNIMPLEMENTED_ARRAY_IDX }; +}; + +template <> struct ArrayTypeIndex<double> { enum : int { index = SBK_DOUBLE_ARRAY_IDX }; }; +template <> struct ArrayTypeIndex<float> { enum : int { index = SBK_FLOAT_ARRAY_IDX };}; +template <> struct ArrayTypeIndex<short> { enum : int { index = SBK_SHORT_ARRAY_IDX };}; +template <> struct ArrayTypeIndex<unsigned short> { enum : int { index = SBK_UNSIGNEDSHORT_ARRAY_IDX };}; +template <> struct ArrayTypeIndex<int> { enum : int { index = SBK_INT_ARRAY_IDX };}; +template <> struct ArrayTypeIndex<unsigned> { enum : int { index = SBK_UNSIGNEDINT_ARRAY_IDX };}; +template <> struct ArrayTypeIndex<long long> { enum : int { index = SBK_LONGLONG_ARRAY_IDX };}; +template <> struct ArrayTypeIndex<unsigned long long> { enum : int { index = SBK_UNSIGNEDLONGLONG_ARRAY_IDX };}; + +template<typename T> SbkArrayConverter *ArrayTypeConverter(int dimension) +{ return arrayTypeConverter(ArrayTypeIndex<T>::index, dimension); } + +// ArrayHandle methods +template<class T> +void ArrayHandle<T>::allocate(Py_ssize_t size) +{ + destroy(); + m_data = new T[size]; + m_size = size; + m_owned = true; +} + +template<class T> +void ArrayHandle<T>::setData(T *d, size_t size) +{ + destroy(); + m_data = d; + m_size = size; + m_owned = false; +} + +template<class T> +void ArrayHandle<T>::destroy() +{ + if (m_owned) + delete [] m_data; + m_data = nullptr; + m_size = 0; + m_owned = false; +} + +} // namespace Conversions +} // namespace Shiboken + +#endif // SBKARRAYCONVERTERS_H diff --git a/sources/shiboken2/libshiboken/sbkarrayconverter_p.h b/sources/shiboken2/libshiboken/sbkarrayconverter_p.h new file mode 100644 index 000000000..9384fbcf5 --- /dev/null +++ b/sources/shiboken2/libshiboken/sbkarrayconverter_p.h @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef SBKARRAYCONVERTER_P_H +#define SBKARRAYCONVERTER_P_H + +#include "sbkconverter_p.h" +#include <vector> + +extern "C" +{ + +typedef PythonToCppFunc (*IsArrayConvertibleToCppFunc)(PyObject*, int dim1, int dim2); +/** + * \internal + * Private structure of SbkArrayConverter. + */ + +struct SbkArrayConverter +{ + std::vector<IsArrayConvertibleToCppFunc> toCppConversions; +}; + +} // extern "C" + +#endif // SBKARRAYCONVERTER_P_H diff --git a/sources/shiboken2/libshiboken/sbkconverter.cpp b/sources/shiboken2/libshiboken/sbkconverter.cpp index 0949d803d..0e154da39 100644 --- a/sources/shiboken2/libshiboken/sbkconverter.cpp +++ b/sources/shiboken2/libshiboken/sbkconverter.cpp @@ -39,22 +39,26 @@ #include "sbkconverter.h" #include "sbkconverter_p.h" +#include "sbkarrayconverter_p.h" #include "basewrapper_p.h" #include "bindingmanager.h" -#include "google/dense_hash_map" #include "autodecref.h" #include "sbkdbg.h" #include "helper.h" #include "voidptr.h" +#include <unordered_map> + static SbkConverter** PrimitiveTypeConverters; -typedef google::dense_hash_map<std::string, SbkConverter*> ConvertersMap; +typedef std::unordered_map<std::string, SbkConverter *> ConvertersMap; static ConvertersMap converters; namespace Shiboken { namespace Conversions { +void initArrayConverters(); + void init() { static SbkConverter* primitiveTypeConverters[] = { @@ -79,8 +83,6 @@ void init() PrimitiveTypeConverters = primitiveTypeConverters; assert(converters.empty()); - converters.set_empty_key(""); - converters.set_deleted_key("?"); converters["PY_LONG_LONG"] = primitiveTypeConverters[SBK_PY_LONG_LONG_IDX]; converters["bool"] = primitiveTypeConverters[SBK_BOOL_IDX_1]; converters["char"] = primitiveTypeConverters[SBK_CHAR_IDX]; @@ -98,9 +100,11 @@ void init() converters["unsigned long"] = primitiveTypeConverters[SBK_UNSIGNEDLONG_IDX]; converters["unsigned short"] = primitiveTypeConverters[SBK_UNSIGNEDSHORT_IDX]; converters["void*"] = primitiveTypeConverters[SBK_VOIDPTR_IDX]; + + initArrayConverters(); } -static SbkConverter* createConverterObject(PyTypeObject* type, +SbkConverter *createConverterObject(PyTypeObject *type, PythonToCppFunc toCppPointerConvFunc, IsConvertibleToCppFunc toCppPointerCheckFunc, CppToPythonFunc pointerToPythonFunc, @@ -257,6 +261,17 @@ PythonToCppFunc isPythonToCppConvertible(const SbkConverter *converter, PyObject return IsPythonToCppConvertible(converter, pyIn); } +PythonToCppFunc isPythonToCppConvertible(const SbkArrayConverter *converter, + int dim1, int dim2, PyObject *pyIn) +{ + assert(pyIn); + for (IsArrayConvertibleToCppFunc f : converter->toCppConversions) { + if (PythonToCppFunc c = f(pyIn, dim1, dim2)) + return c; + } + return nullptr; +} + PythonToCppFunc isPythonToCppReferenceConvertible(const SbkObjectType *type, PyObject *pyIn) { if (pyIn != Py_None) { diff --git a/sources/shiboken2/libshiboken/sbkconverter.h b/sources/shiboken2/libshiboken/sbkconverter.h index 7eb666b25..6d40f85cc 100644 --- a/sources/shiboken2/libshiboken/sbkconverter.h +++ b/sources/shiboken2/libshiboken/sbkconverter.h @@ -67,6 +67,7 @@ extern "C" * using the functions provided by the converter API. */ struct SbkConverter; +struct SbkArrayConverter; /** * Given a void pointer to a C++ object, this function must return @@ -241,6 +242,8 @@ LIBSHIBOKEN_API PythonToCppFunc isPythonToCppReferenceConvertible(const SbkObjec /// This is the same as isPythonToCppValueConvertible function. LIBSHIBOKEN_API PythonToCppFunc isPythonToCppConvertible(const SbkConverter *converter, PyObject *pyIn); +LIBSHIBOKEN_API PythonToCppFunc isPythonToCppConvertible(const SbkArrayConverter *converter, + int dim1, int dim2, PyObject *pyIn); /** * Returns the C++ pointer for the \p pyIn object cast to the type passed via \p desiredType. diff --git a/sources/shiboken2/libshiboken/sbkconverter_p.h b/sources/shiboken2/libshiboken/sbkconverter_p.h index 110358273..cfe3d7e98 100644 --- a/sources/shiboken2/libshiboken/sbkconverter_p.h +++ b/sources/shiboken2/libshiboken/sbkconverter_p.h @@ -533,4 +533,13 @@ struct Primitive<std::string> : TwoPrimitive<std::string> } }; +namespace Shiboken { +namespace Conversions { +SbkConverter *createConverterObject(PyTypeObject *type, + PythonToCppFunc toCppPointerConvFunc, + IsConvertibleToCppFunc toCppPointerCheckFunc, + CppToPythonFunc pointerToPythonFunc, + CppToPythonFunc copyToPythonFunc); +} // namespace Conversions +} // namespace Shiboken #endif // SBK_CONVERTER_P_H diff --git a/sources/shiboken2/libshiboken/sbkenum.cpp b/sources/shiboken2/libshiboken/sbkenum.cpp index a62448aa6..c817a21de 100644 --- a/sources/shiboken2/libshiboken/sbkenum.cpp +++ b/sources/shiboken2/libshiboken/sbkenum.cpp @@ -492,11 +492,11 @@ bool createGlobalEnumItem(PyTypeObject* enumType, PyObject* module, const char* return false; } -bool createScopedEnumItem(PyTypeObject* enumType, SbkObjectType* scope, const char* itemName, long itemValue) +bool createScopedEnumItem(PyTypeObject *enumType, PyTypeObject *scope, + const char *itemName, long itemValue) { - PyObject* enumItem = createEnumItem(enumType, itemName, itemValue); - if (enumItem) { - if (PyDict_SetItemString(scope->super.ht_type.tp_dict, itemName, enumItem) < 0) + if (PyObject *enumItem = createEnumItem(enumType, itemName, itemValue)) { + if (PyDict_SetItemString(scope->tp_dict, itemName, enumItem) < 0) return false; Py_DECREF(enumItem); return true; @@ -504,6 +504,11 @@ bool createScopedEnumItem(PyTypeObject* enumType, SbkObjectType* scope, const ch return false; } +bool createScopedEnumItem(PyTypeObject* enumType, SbkObjectType* scope, const char* itemName, long itemValue) +{ + return createScopedEnumItem(enumType, &scope->super.ht_type, itemName, itemValue); +} + PyObject* newItem(PyTypeObject* enumType, long itemValue, const char* itemName) { bool newValue = true; diff --git a/sources/shiboken2/libshiboken/sbkenum.h b/sources/shiboken2/libshiboken/sbkenum.h index 4b572dbcc..b01114ba6 100644 --- a/sources/shiboken2/libshiboken/sbkenum.h +++ b/sources/shiboken2/libshiboken/sbkenum.h @@ -95,6 +95,8 @@ namespace Enum */ LIBSHIBOKEN_API bool createGlobalEnumItem(PyTypeObject* enumType, PyObject* module, const char* itemName, long itemValue); /// This function does the same as createGlobalEnumItem, but adds the enum to a Shiboken type or namespace. + LIBSHIBOKEN_API bool createScopedEnumItem(PyTypeObject *enumType, PyTypeObject *scope, + const char *itemName, long itemValue); LIBSHIBOKEN_API bool createScopedEnumItem(PyTypeObject* enumType, SbkObjectType* scope, const char* itemName, long itemValue); LIBSHIBOKEN_API PyObject* newItem(PyTypeObject* enumType, long itemValue, const char* itemName = 0); diff --git a/sources/shiboken2/libshiboken/sbkmodule.cpp b/sources/shiboken2/libshiboken/sbkmodule.cpp index 084e23efa..2ea9d56ac 100644 --- a/sources/shiboken2/libshiboken/sbkmodule.cpp +++ b/sources/shiboken2/libshiboken/sbkmodule.cpp @@ -40,17 +40,13 @@ #include "sbkmodule.h" #include "basewrapper.h" #include "bindingmanager.h" - -// TODO: for performance reasons this should be a sparse_hash_map, -// because there'll be very few modules as keys. The sparse_hash_map -// is missing from the code added in ../ext/sparsehash/google directory. -#include "google/dense_hash_map" +#include <unordered_map> /// This hash maps module objects to arrays of Python types. -typedef google::dense_hash_map<PyObject*, PyTypeObject**> ModuleTypesMap; +typedef std::unordered_map<PyObject *, PyTypeObject **> ModuleTypesMap; /// This hash maps module objects to arrays of converters. -typedef google::dense_hash_map<PyObject*, SbkConverter**> ModuleConvertersMap; +typedef std::unordered_map<PyObject *, SbkConverter **> ModuleConvertersMap; /// All types produced in imported modules are mapped here. static ModuleTypesMap moduleTypes; @@ -61,15 +57,6 @@ namespace Shiboken namespace Module { -void init() -{ - // Initializes type registry for modules. - moduleTypes.set_empty_key((ModuleTypesMap::key_type)0); - moduleTypes.set_deleted_key((ModuleTypesMap::key_type)1); - moduleConverters.set_empty_key((ModuleConvertersMap::key_type)0); - moduleConverters.set_deleted_key((ModuleConvertersMap::key_type)1); -} - PyObject* import(const char* moduleName) { PyObject* sysModules = PyImport_GetModuleDict(); diff --git a/sources/shiboken2/libshiboken/sbknumpyarrayconverter.cpp b/sources/shiboken2/libshiboken/sbknumpyarrayconverter.cpp new file mode 100644 index 000000000..97eab2205 --- /dev/null +++ b/sources/shiboken2/libshiboken/sbknumpyarrayconverter.cpp @@ -0,0 +1,308 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "sbkarrayconverter.h" +#include "helper.h" +#include "sbkconverter.h" +#include "sbkconverter_p.h" +#include "sbkarrayconverter_p.h" + +#include <numpy/arrayobject.h> + +#include <algorithm> +#include <iostream> +#include <cstdint> + +enum { debugNumPy = 0 }; + +struct TypeCharMapping +{ + NPY_TYPES type; + const char *name; +}; + +static const TypeCharMapping typeCharMappings[] = { +{NPY_BYTE, "NPY_BYTE"}, +{NPY_UBYTE, "NPY_UBYTE"}, +{NPY_SHORT, "NPY_SHORT"}, +{NPY_USHORT, "NPY_USHORT"}, +{NPY_INT, "NPY_INT"}, +{NPY_UINT, "NPY_UINT"}, +{NPY_LONG, "NPY_LONG"}, +{NPY_ULONG, "NPY_ULONG"}, +{NPY_LONGLONG, "NPY_LONGLONG"}, +{NPY_ULONGLONG, "NPY_ULONGLONG"}, +{NPY_FLOAT, "NPY_FLOAT"}, +{NPY_DOUBLE, "NPY_DOUBLE"} +}; + +const char *npTypeName(npy_intp t) +{ + const TypeCharMapping *end = typeCharMappings + sizeof(typeCharMappings) / sizeof(typeCharMappings[0]); + const TypeCharMapping *result = + std::find_if(typeCharMappings, end, + [t] (const TypeCharMapping &m) { return m.type == t; }); + return result != end ? result->name : nullptr; +} + +std::ostream &operator<<(std::ostream &str, PyArrayObject *o) +{ + str << "PyArrayObject("; + if (o) { + const npy_intp npType = PyArray_TYPE(o); + if (const char *name = npTypeName(npType)) + str << name; + else + str << "type=" << npType; + const int nDim = PyArray_NDIM(o); + const npy_intp *dims = PyArray_DIMS(o); + for (int d = 0; d < nDim; ++d) + str << '[' << dims[d] << ']'; + str << ", "; + const int flags = PyArray_FLAGS(o); + if ((flags & NPY_ARRAY_C_CONTIGUOUS) != 0) + str << " NPY_ARRAY_C_CONTIGUOUS"; + if ((flags & NPY_ARRAY_F_CONTIGUOUS) != 0) + str << " NPY_ARRAY_F_CONTIGUOUS"; + if ((flags & NPY_ARRAY_OWNDATA) != 0) + str << " NPY_ARRAY_OWNDATA"; + if ((flags & NPY_ARRAY_FORCECAST) != 0) + str << " NPY_ARRAY_FORCECAST"; + if ((flags & NPY_ARRAY_ENSURECOPY) != 0) + str << " NPY_ARRAY_ENSURECOPY"; + if ((flags & NPY_ARRAY_ENSUREARRAY) != 0) + str << " NPY_ARRAY_ENSUREARRAY"; + if ((flags & NPY_ARRAY_ELEMENTSTRIDES) != 0) + str << " NPY_ARRAY_ELEMENTSTRIDES"; + if ((flags & NPY_ARRAY_ALIGNED) != 0) + str << " NPY_ARRAY_ALIGNED"; + if ((flags & NPY_ARRAY_NOTSWAPPED) != 0) + str << " NPY_ARRAY_NOTSWAPPED"; + if ((flags & NPY_ARRAY_WRITEABLE) != 0) + str << " NPY_ARRAY_WRITEABLE"; + if ((flags & NPY_ARRAY_UPDATEIFCOPY) != 0) + str << " NPY_ARRAY_UPDATEIFCOPY"; + } else { + str << '0'; + } + str << ')'; + return str; +} + +namespace Shiboken { +namespace Conversions { + +// Internals from sbkarrayconverter.cpp +SbkArrayConverter *createArrayConverter(IsArrayConvertibleToCppFunc toCppCheckFunc); +void setArrayTypeConverter(int index, int dimension, SbkArrayConverter *c); +SbkArrayConverter *unimplementedArrayConverter(); + +template <int dimension> +static bool isPrimitiveArray(PyObject *pyIn, int expectedNpType) +{ + if (!PyArray_Check(pyIn)) + return false; + PyArrayObject *pya = reinterpret_cast<PyArrayObject *>(pyIn); + if (debugNumPy) { + std::cerr << __FUNCTION__ << "(expectedNpType=" << expectedNpType; + if (const char *name = npTypeName(expectedNpType)) + std::cerr << " (" << name << ')'; + std::cerr << ' ' << pya << '\n'; + } + + const int dim = PyArray_NDIM(pya); + if (dim != dimension) { + warning(PyExc_RuntimeWarning, 0, + "%d dimensional numpy array passed to a function expecting a %d dimensional array.", + dim, dimension); + return false; + } + if ((PyArray_FLAGS(pya) & NPY_ARRAY_C_CONTIGUOUS) == 0) { + warning(PyExc_RuntimeWarning, 0, + "Cannot handle numpy arrays that do not have NPY_ARRAY_C_CONTIGUOUS set."); + return false; + } + const int actualNpType = PyArray_TYPE(pya); + if (actualNpType != expectedNpType) { + const char *actualName = npTypeName(actualNpType); + const char *expectedName = npTypeName(expectedNpType); + warning(PyExc_RuntimeWarning, 0, + "A numpy array of type %d (%s) was passed to a function expecting type %d (%s).", + actualNpType, actualName ? actualName : "", + expectedNpType, expectedName ? expectedName : ""); + return false; + } + return true; +} + +static inline bool primitiveArrayCheck1(PyObject *pyIn, int expectedNpType, int expectedSize) +{ + if (!isPrimitiveArray<1>(pyIn, expectedNpType)) + return false; + if (expectedSize >= 0) { + PyArrayObject *pya = reinterpret_cast<PyArrayObject *>(pyIn); + const int size = int(PyArray_DIMS(pya)[0]); + if (size < expectedSize) { + warning(PyExc_RuntimeWarning, 0, "A numpy array of size %d was passed to a function expects %d.", + size, expectedSize); + return false; + } + } + return true; +} + +// Convert one-dimensional array +template <class T> +static void convertArray1(PyObject *pyIn, void *cppOut) +{ + ArrayHandle<T> *handle = reinterpret_cast<ArrayHandle<T> *>(cppOut); + PyArrayObject *pya = reinterpret_cast<PyArrayObject *>(pyIn); + const npy_intp size = PyArray_DIMS(pya)[0]; + if (debugNumPy) + std::cerr << __FUNCTION__ << ' ' << size << '\n'; + handle->setData(reinterpret_cast<T *>(PyArray_DATA(pya)), size_t(size)); +} + +// Convert 2 dimensional array +template <class T> +static void convertArray2(PyObject *pyIn, void *cppOut) +{ + typedef typename Array2Handle<T, 1>::RowType RowType; + Array2Handle<T, 1> *handle = reinterpret_cast<Array2Handle<T, 1> *>(cppOut); + PyArrayObject *pya = reinterpret_cast<PyArrayObject *>(pyIn); + handle->setData(reinterpret_cast<RowType *>(PyArray_DATA(pya))); +} + +template <class T, int NumPyType> +static PythonToCppFunc checkArray1(PyObject *pyIn, int dim1, int /* dim2 */) +{ + return primitiveArrayCheck1(pyIn, NumPyType, dim1) ? convertArray1<T> : nullptr; +} + +static inline bool primitiveArrayCheck2(PyObject *pyIn, int expectedNpType, int expectedDim1, int expectedDim2) +{ + if (!isPrimitiveArray<2>(pyIn, expectedNpType)) + return false; + if (expectedDim2 >= 0) { + PyArrayObject *pya = reinterpret_cast<PyArrayObject *>(pyIn); + const int dim1 = int(PyArray_DIMS(pya)[0]); + const int dim2 = int(PyArray_DIMS(pya)[1]); + if (dim1 != expectedDim1 || dim2 != expectedDim2) { + warning(PyExc_RuntimeWarning, 0, "A numpy array of size %dx%d was passed to a function that expects %dx%d.", + dim1, dim2, expectedDim1, expectedDim2); + return false; + } + } + return true; +} + +template <class T, int NumPyType> +static PythonToCppFunc checkArray2(PyObject *pyIn, int dim1, int dim2) +{ + return primitiveArrayCheck2(pyIn, NumPyType, dim1, dim2) ? convertArray2<T> : nullptr; +} + +template <class T> +static void setOrExtendArrayConverter(int dimension, IsArrayConvertibleToCppFunc toCppCheckFunc) +{ + SbkArrayConverter *arrayConverter = ArrayTypeConverter<T>(dimension); + if (arrayConverter == unimplementedArrayConverter()) { + arrayConverter = createArrayConverter(toCppCheckFunc); + setArrayTypeConverter(ArrayTypeIndex<T>::index, dimension, arrayConverter); + } else { + arrayConverter->toCppConversions.push_back(toCppCheckFunc); + } +} + +// Extend the converters for primitive type one-dimensional arrays by NumPy ones. +template <class T, int NumPyType> +static inline void extendArrayConverter1() +{ + setOrExtendArrayConverter<T>(1, checkArray1<T, NumPyType>); +} + +// Extend the converters for primitive type one-dimensional arrays by NumPy ones. +template <class T, int NumPyType> +static inline void extendArrayConverter2() +{ + setOrExtendArrayConverter<T>(2, checkArray2<T, NumPyType>); +} + +void initNumPyArrayConverters() +{ + // Expanded from macro "import_array" in __multiarray_api.h + // Make sure to read about the magic defines PY_ARRAY_UNIQUE_SYMBOL etc., + // when changing this or spreading the code over several source files. + if (_import_array() < 0) { + if (debugNumPy) + PyErr_Print(); + PyErr_Clear(); + return; + } + // Extend the converters for primitive types by NumPy ones. + extendArrayConverter1<short, NPY_SHORT>(); + extendArrayConverter2<short, NPY_SHORT>(); + extendArrayConverter1<unsigned short, NPY_SHORT>(); + extendArrayConverter2<unsigned short, NPY_SHORT>(); + extendArrayConverter1<int, NPY_INT>(); + extendArrayConverter2<int, NPY_INT>(); + extendArrayConverter1<unsigned int, NPY_UINT>(); + extendArrayConverter2<unsigned int, NPY_UINT>(); + extendArrayConverter1<long long, NPY_LONGLONG>(); + extendArrayConverter2<long long, NPY_LONGLONG>(); + extendArrayConverter1<unsigned long long, NPY_ULONGLONG>(); + if (sizeof(long) == 8) { // UNIX/LP64: ints typically come as long + extendArrayConverter1<long long, NPY_LONG>(); + extendArrayConverter2<long long, NPY_LONG>(); + extendArrayConverter1<unsigned long long, NPY_ULONG>(); + extendArrayConverter2<unsigned long long, NPY_ULONG>(); + } else if (sizeof(long) == sizeof(int)) { + extendArrayConverter1<int, NPY_LONG>(); + extendArrayConverter1<unsigned, NPY_ULONG>(); + extendArrayConverter2<int, NPY_LONG>(); + extendArrayConverter2<unsigned, NPY_ULONG>(); + } + extendArrayConverter1<float, NPY_FLOAT>(); + extendArrayConverter2<float, NPY_FLOAT>(); + extendArrayConverter1<double, NPY_DOUBLE>(); + extendArrayConverter2<double, NPY_DOUBLE>(); +} + +} // namespace Conversions +} // namespace Shiboken diff --git a/sources/shiboken2/libshiboken/shiboken.h b/sources/shiboken2/libshiboken/shiboken.h index 9f4b8a560..6cdfe65bd 100644 --- a/sources/shiboken2/libshiboken/shiboken.h +++ b/sources/shiboken2/libshiboken/shiboken.h @@ -47,6 +47,7 @@ #include "gilstate.h" #include "threadstatesaver.h" #include "helper.h" +#include "sbkarrayconverter.h" #include "sbkconverter.h" #include "sbkenum.h" #include "sbkmodule.h" diff --git a/sources/shiboken2/shiboken_version.py b/sources/shiboken2/shiboken_version.py index b207d6b9c..aacb7e0d9 100644 --- a/sources/shiboken2/shiboken_version.py +++ b/sources/shiboken2/shiboken_version.py @@ -1,5 +1,44 @@ +############################################################################# +## +## Copyright (C) 2018 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of PySide2. +## +## $QT_BEGIN_LICENSE:LGPL$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU Lesser General Public License Usage +## Alternatively, this file may be used under the terms of the GNU Lesser +## General Public License version 3 as published by the Free Software +## Foundation and appearing in the file LICENSE.LGPL3 included in the +## packaging of this file. Please review the following information to +## ensure the GNU Lesser General Public License version 3 requirements +## will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 2.0 or (at your option) the GNU General +## Public license version 3 or any later version approved by the KDE Free +## Qt Foundation. The licenses are as published by the Free Software +## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-2.0.html and +## https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + major_version = "5" -minor_version = "6" +minor_version = "9" patch_version = "0" pre_release_version_type = "a" # e.g. "a", "b", "rc". pre_release_version = "1" # e.g "1", "2", (which means "beta1", "beta2", if type is "b") diff --git a/sources/shiboken2/tests/dumpcodemodel/main.cpp b/sources/shiboken2/tests/dumpcodemodel/main.cpp index 9e62faa16..13dab6e8a 100644 --- a/sources/shiboken2/tests/dumpcodemodel/main.cpp +++ b/sources/shiboken2/tests/dumpcodemodel/main.cpp @@ -37,6 +37,8 @@ #include <QtCore/QFile> #include <iostream> +#include <algorithm> +#include <iterator> int main(int argc, char **argv) { @@ -53,22 +55,19 @@ int main(int argc, char **argv) parser.addPositionalArgument(QStringLiteral("file"), QStringLiteral("C++ source file")); parser.process(app); - if (parser.positionalArguments().isEmpty()) + const QStringList &positionalArguments = parser.positionalArguments(); + if (positionalArguments.isEmpty()) parser.showHelp(1); - const QString sourceFileName = parser.positionalArguments().at(0); - QFile sourceFile(sourceFileName); - if (!sourceFile.open(QIODevice::ReadOnly | QIODevice::Text)) { - QString message = QLatin1String("Cannot open \"") + QDir::toNativeSeparators(sourceFileName) - + QLatin1String("\": ") + sourceFile.errorString(); + QByteArrayList arguments; + std::transform(positionalArguments.cbegin(), positionalArguments.cend(), + std::back_inserter(arguments), QFile::encodeName); + const FileModelItem dom = AbstractMetaBuilderPrivate::buildDom(arguments, 0); + if (dom.isNull()) { + QString message = QLatin1String("Unable to parse ") + positionalArguments.join(QLatin1Char(' ')); std::cerr << qPrintable(message) << '\n'; - return -1; - } - - const FileModelItem dom = AbstractMetaBuilderPrivate::buildDom(&sourceFile); - sourceFile.close(); - if (dom.isNull()) return -2; + } QString output; { diff --git a/sources/shiboken2/tests/libother/otherderived.cpp b/sources/shiboken2/tests/libother/otherderived.cpp index 4128d73ff..de16b0ab4 100644 --- a/sources/shiboken2/tests/libother/otherderived.cpp +++ b/sources/shiboken2/tests/libother/otherderived.cpp @@ -59,3 +59,6 @@ OtherDerived::unpureVirtual() { } +void OtherDerived::pureVirtualPrivate() +{ +} diff --git a/sources/shiboken2/tests/libother/otherderived.h b/sources/shiboken2/tests/libother/otherderived.h index 792b7c408..592e9e023 100644 --- a/sources/shiboken2/tests/libother/otherderived.h +++ b/sources/shiboken2/tests/libother/otherderived.h @@ -41,11 +41,11 @@ class LIBOTHER_API OtherDerived : public Abstract { public: OtherDerived(int id = -1); - virtual ~OtherDerived(); - virtual void pureVirtual(); - virtual void* pureVirtualReturningVoidPtr(); - virtual void unpureVirtual(); - virtual PrintFormat returnAnEnum() { return Short; } + ~OtherDerived() override; + void pureVirtual() override; + void* pureVirtualReturningVoidPtr() override; + void unpureVirtual() override; + PrintFormat returnAnEnum() override { return Short; } inline void useObjectTypeFromOtherModule(ObjectType*) {} inline Event useValueTypeFromOtherModule(const Event& e) { return e; } @@ -59,7 +59,10 @@ public: protected: inline const char* getClassName() { return className(); } - virtual const char* className() { return "OtherDerived"; } + virtual const char* className() override { return "OtherDerived"; } + +private: + void pureVirtualPrivate() override; }; #endif // OTHERDERIVED_H diff --git a/sources/shiboken2/tests/libsample/abstract.h b/sources/shiboken2/tests/libsample/abstract.h index 77a43f3d1..f31870522 100644 --- a/sources/shiboken2/tests/libsample/abstract.h +++ b/sources/shiboken2/tests/libsample/abstract.h @@ -102,6 +102,7 @@ protected: unsigned int bitField: 1; private: + virtual void pureVirtualPrivate() = 0; int m_id; }; #endif // ABSTRACT_H diff --git a/sources/shiboken2/tests/libsample/derived.cpp b/sources/shiboken2/tests/libsample/derived.cpp index 00ac8ebe5..9552a2a8c 100644 --- a/sources/shiboken2/tests/libsample/derived.cpp +++ b/sources/shiboken2/tests/libsample/derived.cpp @@ -103,6 +103,8 @@ struct SecretClass : public Abstract { virtual void* pureVirtualReturningVoidPtr() { return 0; } virtual PrintFormat returnAnEnum() { return Short; } void hideFunction(HideType*){}; +private: + virtual void pureVirtualPrivate() {} }; Abstract* Derived::triggerImpossibleTypeDiscovery() @@ -117,3 +119,7 @@ Abstract* Derived::triggerAnotherImpossibleTypeDiscovery() { return new AnotherSecretClass; } + +void Derived::pureVirtualPrivate() +{ +} diff --git a/sources/shiboken2/tests/libsample/derived.h b/sources/shiboken2/tests/libsample/derived.h index 5c57e4691..84c502566 100644 --- a/sources/shiboken2/tests/libsample/derived.h +++ b/sources/shiboken2/tests/libsample/derived.h @@ -53,13 +53,13 @@ public: }; Derived(int id = -1); - virtual ~Derived(); - virtual void pureVirtual(); - virtual void* pureVirtualReturningVoidPtr(); - virtual void unpureVirtual(); + ~Derived() override; + void pureVirtual() override; + void* pureVirtualReturningVoidPtr() override; + void unpureVirtual() override; - virtual PrintFormat returnAnEnum() { return Short; } - virtual Type type() const { return TpDerived; } + PrintFormat returnAnEnum() override { return Short; } + Type type() const override { return TpDerived; } // factory method static Abstract* createObject(); @@ -83,10 +83,13 @@ public: static Abstract* triggerImpossibleTypeDiscovery(); static Abstract* triggerAnotherImpossibleTypeDiscovery(); - void hideFunction(HideType*) {} + void hideFunction(HideType*) override {} protected: const char* getClassName() { return className(); } - virtual const char* className() { return "Derived"; } + virtual const char* className() override { return "Derived"; } + +private: + void pureVirtualPrivate() override; }; #endif // DERIVED_H diff --git a/sources/shiboken2/tests/libsample/functions.cpp b/sources/shiboken2/tests/libsample/functions.cpp index 4a15cdae8..bf73d5ed7 100644 --- a/sources/shiboken2/tests/libsample/functions.cpp +++ b/sources/shiboken2/tests/libsample/functions.cpp @@ -28,7 +28,9 @@ #include "functions.h" #include <string.h> +#include <algorithm> #include <iostream> +#include <numeric> using namespace std; @@ -197,6 +199,45 @@ acceptOddBoolReference(OddBool& x) return x; } +int sumIntArray(int array[4]) +{ + return std::accumulate(array, array + 4, 0); +} + +double sumDoubleArray(double array[4]) +{ + return std::accumulate(array, array + 4, double(0)); +} + +int sumIntMatrix(int m[2][3]) +{ + int result = 0; + for (int r = 0; r < 2; ++r) { + for (int c = 0; c < 3; ++c) + result += m[r][c]; + } + return result; +} + +double sumDoubleMatrix(double m[2][3]) +{ + double result = 0; + for (int r = 0; r < 2; ++r) { + for (int c = 0; c < 3; ++c) + result += m[r][c]; + } + return result; +} + +ArrayModifyTest::ArrayModifyTest() +{ +} + +int ArrayModifyTest::sumIntArray(int n, int *array) +{ + return std::accumulate(array, array + n, 0); +} + ClassWithFunctionPointer::ClassWithFunctionPointer() { callFunctionPointer(0, &ClassWithFunctionPointer::doNothing); diff --git a/sources/shiboken2/tests/libsample/functions.h b/sources/shiboken2/tests/libsample/functions.h index 89a175bc4..a53f97c6e 100644 --- a/sources/shiboken2/tests/libsample/functions.h +++ b/sources/shiboken2/tests/libsample/functions.h @@ -81,6 +81,17 @@ LIBSAMPLE_API double acceptDouble(double x); LIBSAMPLE_API int acceptIntReference(int& x); LIBSAMPLE_API OddBool acceptOddBoolReference(OddBool& x); +LIBSAMPLE_API int sumIntArray(int array[4]); +LIBSAMPLE_API double sumDoubleArray(double array[4]); +LIBSAMPLE_API int sumIntMatrix(int m[2][3]); +LIBSAMPLE_API double sumDoubleMatrix(double m[2][3]); + +class LIBSAMPLE_API ArrayModifyTest +{ +public: + ArrayModifyTest(); + int sumIntArray(int n, int *array); +}; class LIBSAMPLE_API ClassWithFunctionPointer { diff --git a/sources/shiboken2/tests/libsample/multiple_derived.h b/sources/shiboken2/tests/libsample/multiple_derived.h index 5825e59b4..7a130c6b5 100644 --- a/sources/shiboken2/tests/libsample/multiple_derived.h +++ b/sources/shiboken2/tests/libsample/multiple_derived.h @@ -58,11 +58,11 @@ class LIBSAMPLE_API MDerived1 : public Base1, public Base2 { public: MDerived1(); - virtual ~MDerived1() {} + ~MDerived1() override {} - virtual int mderived1Method() { return m_value; } - virtual int base1Method() { return Base1::base1Method() * 10; } - virtual int base2Method() { return Base2::base2Method() * 10; } + int mderived1Method() { return m_value; } + int base1Method () override { return Base1::base1Method() * 10; } + int base2Method() override { return Base2::base2Method() * 10; } inline Base1* castToBase1() { return (Base1*) this; } inline Base2* castToBase2() { return (Base2*) this; } @@ -71,7 +71,7 @@ public: static MDerived1* transformFromBase2(Base2 *self); private: - virtual void publicMethod() {} + void publicMethod() override {} int m_value; }; diff --git a/sources/shiboken2/tests/libsample/objecttype.h b/sources/shiboken2/tests/libsample/objecttype.h index 487472b0f..91fb45515 100644 --- a/sources/shiboken2/tests/libsample/objecttype.h +++ b/sources/shiboken2/tests/libsample/objecttype.h @@ -45,6 +45,12 @@ struct Event SOME_EVENT, ANY_EVENT }; + + enum class EventTypeClass { + Value1, + Value2 + }; + Event(EventType eventType) : m_eventType(eventType) {} EventType eventType() { return m_eventType; } private: @@ -167,8 +173,8 @@ class LIBSAMPLE_API ObjectTypeDerived: public ObjectType, public OtherBase { public: ObjectTypeDerived(): ObjectType(), OtherBase() {}; - virtual bool event(Event* event); - virtual ~ObjectTypeDerived(); + bool event(Event* event) override; + ~ObjectTypeDerived() override; }; #endif // OBJECTTYPE_H diff --git a/sources/shiboken2/tests/libsample/objecttypelayout.h b/sources/shiboken2/tests/libsample/objecttypelayout.h index 3fa8b9dbf..8524c1989 100644 --- a/sources/shiboken2/tests/libsample/objecttypelayout.h +++ b/sources/shiboken2/tests/libsample/objecttypelayout.h @@ -41,10 +41,10 @@ public: void addObject(ObjectType* obj); std::list<ObjectType*> objects() const; - virtual bool isLayoutType() { return true; } + bool isLayoutType() override { return true; } inline static ObjectTypeLayout* create() { return new ObjectTypeLayout(); } - virtual ObjectType* takeChild(const Str& name) { return ObjectType::takeChild(name); } + ObjectType* takeChild(const Str& name) override { return ObjectType::takeChild(name); } private: std::list<ObjectType*> m_objects; diff --git a/sources/shiboken2/tests/libsample/photon.h b/sources/shiboken2/tests/libsample/photon.h index d8b1be423..437ec1d9b 100644 --- a/sources/shiboken2/tests/libsample/photon.h +++ b/sources/shiboken2/tests/libsample/photon.h @@ -84,7 +84,7 @@ public: static inline TemplateBase<CLASS_TYPE>* passPointerThrough(TemplateBase<CLASS_TYPE>* obj) { return obj; } - virtual ClassType type() const { return CLASS_TYPE; } + ClassType type() const override { return CLASS_TYPE; } static const ClassType staticType = CLASS_TYPE; }; diff --git a/sources/shiboken2/tests/libsample/samplenamespace.h b/sources/shiboken2/tests/libsample/samplenamespace.h index 3ce410941..93cafa29c 100644 --- a/sources/shiboken2/tests/libsample/samplenamespace.h +++ b/sources/shiboken2/tests/libsample/samplenamespace.h @@ -110,6 +110,10 @@ public: NiceValue1, NiceValue2 }; + enum class NiceEnumClass { + NiceClassValue1, NiceClassValue2 + }; + inline int someMethod(SomeInnerClass*) { return 0; } virtual OkThisIsRecursiveEnough* someVirtualMethod(OkThisIsRecursiveEnough* arg) { return arg; } }; diff --git a/sources/shiboken2/tests/libsample/virtualmethods.cpp b/sources/shiboken2/tests/libsample/virtualmethods.cpp index 05b854e08..e0cba3a47 100644 --- a/sources/shiboken2/tests/libsample/virtualmethods.cpp +++ b/sources/shiboken2/tests/libsample/virtualmethods.cpp @@ -57,3 +57,22 @@ VirtualMethods::getMargins(int* left, int* top, int* right, int* bottom) const *bottom = m_bottom; } +double VirtualDaughter2::virtualMethod0(Point pt, int val, Complex cpx, bool b) +{ + return 42 + VirtualMethods::virtualMethod0(pt, val, cpx, b); +} + +int VirtualDaughter2::sum0(int a0, int a1, int a2) +{ + return 42 + VirtualMethods::sum0(a0, a1, a2); +} + +double VirtualFinalDaughter::virtualMethod0(Point pt, int val, Complex cpx, bool b) +{ + return 42 + VirtualMethods::virtualMethod0(pt, val, cpx, b); +} + +int VirtualFinalDaughter::sum0(int a0, int a1, int a2) +{ + return 42 + VirtualMethods::sum0(a0, a1, a2); +} diff --git a/sources/shiboken2/tests/libsample/virtualmethods.h b/sources/shiboken2/tests/libsample/virtualmethods.h index 5754d0d5d..4ba3ad338 100644 --- a/sources/shiboken2/tests/libsample/virtualmethods.h +++ b/sources/shiboken2/tests/libsample/virtualmethods.h @@ -121,6 +121,24 @@ public: VirtualDaughter(Str name) : VirtualMethods(name) {} }; +class LIBSAMPLE_API VirtualDaughter2 : public VirtualMethods +{ +public: + VirtualDaughter2() : VirtualMethods("VirtualDaughter2") {} + + double virtualMethod0(Point pt, int val, Complex cpx, bool b) override; + int sum0(int a0, int a1, int a2) final; +}; + +class LIBSAMPLE_API VirtualFinalDaughter final : public VirtualMethods +{ +public: + VirtualFinalDaughter() : VirtualMethods("VirtualFinalDaughter") {} + + double virtualMethod0(Point pt, int val, Complex cpx, bool b) override; + int sum0(int a0, int a1, int a2) override; +}; + class LIBSAMPLE_API VirtualDtor { public: diff --git a/sources/shiboken2/tests/samplebinding/CMakeLists.txt b/sources/shiboken2/tests/samplebinding/CMakeLists.txt index 1b97bd0e8..78ddfca0a 100644 --- a/sources/shiboken2/tests/samplebinding/CMakeLists.txt +++ b/sources/shiboken2/tests/samplebinding/CMakeLists.txt @@ -7,6 +7,7 @@ ${CMAKE_CURRENT_SOURCE_DIR}/typesystem_sample.xml set(sample_SRC ${CMAKE_CURRENT_BINARY_DIR}/sample/abstractmodifications_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/abstract_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/arraymodifytest_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/base1_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/base2_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/base3_wrapper.cpp @@ -109,6 +110,8 @@ ${CMAKE_CURRENT_BINARY_DIR}/sample/time_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/templateptr_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/unremovednamespace_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/virtualdaughter_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/virtualdaughter2_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/virtualfinaldaughter_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/virtualdtor_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/virtualmethods_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/voidholder_wrapper.cpp diff --git a/sources/shiboken2/tests/samplebinding/array_numpy_test.py b/sources/shiboken2/tests/samplebinding/array_numpy_test.py new file mode 100644 index 000000000..bde46f2e3 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/array_numpy_test.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python + +############################################################################# +## +## Copyright (C) 2017 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Test case for NumPy Array types.''' + +import unittest +import sample + +hasNumPy = False + +try: + import numpy + hasNumPy = True +except ImportError: + pass + +class ArrayTester(unittest.TestCase): + '''Test case for NumPy arrays.''' + + def testIntArray(self): + intList = numpy.array([1, 2, 3, 4], dtype = 'int32') + self.assertEqual(sample.sumIntArray(intList), 10) + + def testDoubleArray(self): + doubleList = numpy.array([1, 2, 3, 4], dtype = 'double') + self.assertEqual(sample.sumDoubleArray(doubleList), 10) + + def testIntMatrix(self): + intMatrix = numpy.array([[1, 2, 3], [4, 5, 6]], dtype = 'int32') + self.assertEqual(sample.sumIntMatrix(intMatrix), 21) + + def testDoubleMatrix(self): + doubleMatrix = numpy.array([[1, 2, 3], [4, 5, 6]], dtype = 'double') + self.assertEqual(sample.sumDoubleMatrix(doubleMatrix), 21) + +if __name__ == '__main__' and hasNumPy: + unittest.main() diff --git a/sources/shiboken2/tests/samplebinding/array_sequence_test.py b/sources/shiboken2/tests/samplebinding/array_sequence_test.py new file mode 100644 index 000000000..0fd2ec636 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/array_sequence_test.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python + +############################################################################# +## +## Copyright (C) 2017 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Test case for Array types (PySequence).''' + +import unittest +import sample + +class ArrayTester(unittest.TestCase): + '''Test case for arrays.''' + + def testIntArray(self): + intList = [1, 2, 3, 4] + self.assertEqual(sample.sumIntArray(intList), 10) + + def testIntArrayModified(self): + intList = [1, 2, 3, 4] + tester = sample.ArrayModifyTest() + self.assertEqual(tester.sumIntArray(4, intList), 10) + + def testDoubleArray(self): + doubleList = [1.2, 2.3, 3.4, 4.5] + self.assertEqual(sample.sumDoubleArray(doubleList), 11.4) + +if __name__ == '__main__': + unittest.main() diff --git a/sources/shiboken2/tests/samplebinding/enum_test.py b/sources/shiboken2/tests/samplebinding/enum_test.py index 6468d3cc4..711215c35 100644 --- a/sources/shiboken2/tests/samplebinding/enum_test.py +++ b/sources/shiboken2/tests/samplebinding/enum_test.py @@ -110,6 +110,11 @@ class EnumTest(unittest.TestCase): self.assertEqual(SampleNamespace.AnonymousClassEnum_Value0, 0) self.assertEqual(SampleNamespace.AnonymousClassEnum_Value1, 1) + def testEnumClasses(self): + # C++ 11: values of enum classes need to be fully qualified to match C++ + sum = Event.EventTypeClass.Value1 + Event.EventTypeClass.Value2 + self.assertEqual(sum, 1) + def testEnumTpPrintImplementation(self): '''Without SbkEnum.tp_print 'print' returns the enum represented as an int.''' tmpfile = createTempFile() diff --git a/sources/shiboken2/tests/samplebinding/typesystem_sample.xml b/sources/shiboken2/tests/samplebinding/typesystem_sample.xml index e4e8f7e22..5a12eeccd 100644 --- a/sources/shiboken2/tests/samplebinding/typesystem_sample.xml +++ b/sources/shiboken2/tests/samplebinding/typesystem_sample.xml @@ -501,11 +501,21 @@ <function signature="gimmeInt()" /> <function signature="gimmeDouble()" /> <function signature="makeCString()" /> + <function signature="sumIntArray(int[4])"/> + <function signature="sumDoubleArray(double[4])"/> + <function signature="sumIntMatrix(int[2][3])"/> + <function signature="sumDoubleMatrix(double[2][3])"/> <function signature="multiplyPair(std::pair<double, double>)" /> <function signature="returnCString()" /> <function signature="overloadedFunc(double)" /> <function signature="overloadedFunc(int)" /> + <value-type name="ArrayModifyTest"> + <modify-function signature="sumIntArray(int, int*)"> + <modify-argument index="2"><array/></modify-argument> + </modify-function> + </value-type> + <value-type name="ClassWithFunctionPointer"> <suppress-warning text="skipping function 'ClassWithFunctionPointer::callFunctionPointer', unmatched parameter type 'void (*)(void*)'" /> </value-type> @@ -538,6 +548,7 @@ <value-type name="SomeInnerClass"> <object-type name="OkThisIsRecursiveEnough"> <enum-type name="NiceEnum" /> + <enum-type name="NiceEnumClass" /> </object-type> <enum-type name="ProtectedEnum"/> </value-type> @@ -787,6 +798,7 @@ <value-type name="Event"> <enum-type name="EventType"/> + <enum-type name="EventTypeClass" class="yes"/> </value-type> <value-type name="BlackBox"> @@ -1159,7 +1171,7 @@ <!-- change the name of this virtual method --> <modify-function signature="className()" rename="name"/> - <modify-function signature="sumPointArray(int, const Point*)"> + <modify-function signature="sumPointArray(int, const Point[])"> <modify-argument index="1"> <remove-argument/> <conversion-rule class="native"> @@ -1477,6 +1489,8 @@ </modify-function> </value-type> <value-type name="VirtualDaughter" /> + <object-type name="VirtualDaughter2" /> + <object-type name="VirtualFinalDaughter" /> <value-type name="VirtualDtor"> <modify-function signature="create()"> @@ -1950,7 +1964,7 @@ <define-ownership owner="c++"/> </modify-argument> </modify-function> - <modify-function signature="acceptSequence(const char**)"> + <modify-function signature="acceptSequence(const char*[])"> <modify-argument index="1"> <replace-type modified-type="PySequence" /> <conversion-rule class="native"> diff --git a/sources/shiboken2/tests/test_generator/dummygenerator.cpp b/sources/shiboken2/tests/test_generator/dummygenerator.cpp index 51d2b33da..40d9fb771 100644 --- a/sources/shiboken2/tests/test_generator/dummygenerator.cpp +++ b/sources/shiboken2/tests/test_generator/dummygenerator.cpp @@ -52,7 +52,8 @@ DummyGenerator::doSetup(const QMap<QString, QString>& args) QFile logFile(args["dump-arguments"]); logFile.open(QIODevice::WriteOnly | QIODevice::Text); QTextStream out(&logFile); - foreach (const QString& key, args.keys()) { + for (QMap<QString, QString>::const_iterator it = args.cbegin(), end = args.cend(); it != end; ++it) { + const QString& key = it.key(); if (key == "arg-1") out << "header-file"; else if (key == "arg-2") |