aboutsummaryrefslogtreecommitdiffstats
path: root/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp')
-rw-r--r--sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp2083
1 files changed, 1284 insertions, 799 deletions
diff --git a/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp b/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp
index 4ef6132e1..29566a272 100644
--- a/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp
+++ b/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp
@@ -1,43 +1,34 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt for Python.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "abstractmetabuilder_p.h"
+#include "abstractmetaargument.h"
#include "abstractmetaenum.h"
#include "abstractmetafield.h"
#include "abstractmetafunction.h"
+#include "abstractmetatype.h"
+#include "addedfunction.h"
#include "graph.h"
+#include "debughelpers_p.h"
#include "exception.h"
#include "messages.h"
#include "propertyspec.h"
#include "reporthandler.h"
#include "sourcelocation.h"
#include "typedatabase.h"
-#include "typesystem.h"
+#include "enumtypeentry.h"
+#include "enumvaluetypeentry.h"
+#include "arraytypeentry.h"
+#include "constantvaluetypeentry.h"
+#include "containertypeentry.h"
+#include "flagstypeentry.h"
+#include "functiontypeentry.h"
+#include "namespacetypeentry.h"
+#include "primitivetypeentry.h"
+#include "smartpointertypeentry.h"
+#include "templateargumententry.h"
+#include "typedefentry.h"
+#include "typesystemtypeentry.h"
#include "usingmember.h"
#include "parser/codemodel.h"
@@ -46,10 +37,13 @@
#include <clangparser/clangutils.h>
#include <clangparser/compilersupport.h>
+#include "qtcompat.h"
+
#include <QtCore/QDebug>
#include <QtCore/QDir>
#include <QtCore/QFile>
#include <QtCore/QFileInfo>
+#include <QtCore/QMetaObject>
#include <QtCore/QQueue>
#include <QtCore/QRegularExpression>
#include <QtCore/QTemporaryFile>
@@ -59,11 +53,11 @@
#include <algorithm>
#include <memory>
-static inline QString colonColon() { return QStringLiteral("::"); }
+using namespace Qt::StringLiterals;
static QString stripTemplateArgs(const QString &name)
{
- int pos = name.indexOf(QLatin1Char('<'));
+ const auto pos = name.indexOf(u'<');
return pos < 0 ? name : name.left(pos);
}
@@ -73,18 +67,37 @@ static void fixArgumentIndexes(AbstractMetaArgumentList *list)
(*list)[i].setArgumentIndex(i);
}
-bool AbstractMetaBuilderPrivate::m_useGlobalHeader = false;
+bool operator<(const RejectEntry &re1, const RejectEntry &re2)
+{
+ return re1.reason != re2.reason
+ ? (re1.reason < re2.reason) : (re1.sortkey < re2.sortkey);
+}
-AbstractMetaBuilderPrivate::AbstractMetaBuilderPrivate() :
- m_logDirectory(QLatin1String(".") + QDir::separator())
+QTextStream &operator<<(QTextStream &str, const RejectEntry &re)
{
+ str << re.signature;
+ if (!re.message.isEmpty())
+ str << ": " << re.message;
+ return str;
}
-AbstractMetaBuilderPrivate::~AbstractMetaBuilderPrivate()
+static void applyCachedFunctionModifications(AbstractMetaFunction *metaFunction,
+ const FunctionModificationList &functionMods)
+{
+ for (const FunctionModification &mod : functionMods) {
+ if (mod.exceptionHandling() != TypeSystem::ExceptionHandling::Unspecified)
+ metaFunction->setExceptionHandlingModification(mod.exceptionHandling());
+ if (mod.allowThread() != TypeSystem::AllowThread::Unspecified)
+ metaFunction->setAllowThreadModification(mod.allowThread());
+ }
+}
+
+bool AbstractMetaBuilderPrivate::m_useGlobalHeader = false;
+bool AbstractMetaBuilderPrivate::m_codeModelTestMode = false;
+
+AbstractMetaBuilderPrivate::AbstractMetaBuilderPrivate() :
+ m_logDirectory(u"."_s + QDir::separator())
{
- qDeleteAll(m_templates);
- qDeleteAll(m_smartPointers);
- qDeleteAll(m_metaClasses);
}
AbstractMetaBuilder::AbstractMetaBuilder() : d(new AbstractMetaBuilderPrivate)
@@ -102,16 +115,37 @@ const AbstractMetaClassList &AbstractMetaBuilder::classes() const
return d->m_metaClasses;
}
+AbstractMetaClassList AbstractMetaBuilder::takeClasses()
+{
+ AbstractMetaClassList result;
+ qSwap(result, d->m_metaClasses);
+ return result;
+}
+
const AbstractMetaClassList &AbstractMetaBuilder::templates() const
{
return d->m_templates;
}
+AbstractMetaClassList AbstractMetaBuilder::takeTemplates()
+{
+ AbstractMetaClassList result;
+ qSwap(result, d->m_templates);
+ return result;
+}
+
const AbstractMetaClassList &AbstractMetaBuilder::smartPointers() const
{
return d->m_smartPointers;
}
+AbstractMetaClassList AbstractMetaBuilder::takeSmartPointers()
+{
+ AbstractMetaClassList result;
+ qSwap(result, d->m_smartPointers);
+ return result;
+}
+
const AbstractMetaFunctionCList &AbstractMetaBuilder::globalFunctions() const
{
return d->m_globalFunctions;
@@ -122,36 +156,41 @@ const AbstractMetaEnumList &AbstractMetaBuilder::globalEnums() const
return d->m_globalEnums;
}
-const QHash<const TypeEntry *, AbstractMetaEnum> &AbstractMetaBuilder::typeEntryToEnumsHash() const
+const QHash<TypeEntryCPtr, AbstractMetaEnum> &AbstractMetaBuilder::typeEntryToEnumsHash() const
{
return d->m_enums;
}
-void AbstractMetaBuilderPrivate::checkFunctionModifications()
+const QMultiHash<QString, QString> &AbstractMetaBuilder::typedefTargetToName() const
+{
+ return d->m_typedefTargetToName;
+}
+
+void AbstractMetaBuilderPrivate::checkFunctionModifications() const
{
const auto &entries = TypeDatabase::instance()->entries();
for (auto it = entries.cbegin(), end = entries.cend(); it != end; ++it) {
- const TypeEntry *entry = it.value();
+ TypeEntryCPtr entry = it.value();
if (!entry)
continue;
if (!entry->isComplex() || !entry->generateCode())
continue;
- auto centry = static_cast<const ComplexTypeEntry *>(entry);
+ auto centry = std::static_pointer_cast<const ComplexTypeEntry>(entry);
if (!centry->generateCode())
continue;
FunctionModificationList modifications = centry->functionModifications();
- for (const FunctionModification &modification : qAsConst(modifications)) {
+ for (const FunctionModification &modification : std::as_const(modifications)) {
QString signature = modification.signature();
QString name = signature.trimmed();
- name.truncate(name.indexOf(QLatin1Char('(')));
+ name.truncate(name.indexOf(u'('));
- AbstractMetaClass *clazz = AbstractMetaClass::findClass(m_metaClasses, centry);
+ const auto clazz = AbstractMetaClass::findClass(m_metaClasses, centry);
if (!clazz)
continue;
@@ -159,13 +198,14 @@ void AbstractMetaBuilderPrivate::checkFunctionModifications()
QStringList possibleSignatures;
for (const auto &function : clazz->functions()) {
if (function->implementingClass() == clazz
- && modification.matches(function->minimalSignature())) {
+ && modification.matches(function->modificationSignatures())) {
found = true;
break;
}
if (function->originalName() == name) {
- possibleSignatures.append(function->minimalSignature() + QLatin1String(" in ")
+ const QString signatures = function->modificationSignatures().join(u'/');
+ possibleSignatures.append(signatures + u" in "_s
+ function->implementingClass()->name());
}
}
@@ -180,14 +220,14 @@ void AbstractMetaBuilderPrivate::checkFunctionModifications()
}
}
-AbstractMetaClass *AbstractMetaBuilderPrivate::argumentToClass(const ArgumentModelItem &argument,
- const AbstractMetaClass *currentClass)
+AbstractMetaClassPtr AbstractMetaBuilderPrivate::argumentToClass(const ArgumentModelItem &argument,
+ const AbstractMetaClassCPtr &currentClass)
{
- AbstractMetaClass *returned = nullptr;
+ AbstractMetaClassPtr returned;
auto type = translateType(argument->type(), currentClass);
if (!type.has_value())
return returned;
- const TypeEntry *entry = type->typeEntry();
+ TypeEntryCPtr entry = type->typeEntry();
if (entry && entry->isComplex())
returned = AbstractMetaClass::findClass(m_metaClasses, entry);
return returned;
@@ -197,18 +237,20 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::argumentToClass(const ArgumentMod
* Checks the argument of a hash function and flags the type if it is a complex type
*/
void AbstractMetaBuilderPrivate::registerHashFunction(const FunctionModelItem &function_item,
- AbstractMetaClass *currentClass)
+ const AbstractMetaClassPtr &currentClass)
{
+ if (function_item->isDeleted())
+ return;
ArgumentList arguments = function_item->arguments();
- if (arguments.size() == 1) {
- if (AbstractMetaClass *cls = argumentToClass(arguments.at(0), currentClass))
- cls->setHasHashFunction(true);
+ if (arguments.size() >= 1) { // (Class, Hash seed).
+ if (AbstractMetaClassPtr cls = argumentToClass(arguments.at(0), currentClass))
+ cls->setHashFunction(function_item->name());
}
}
void AbstractMetaBuilderPrivate::registerToStringCapabilityIn(const NamespaceModelItem &nsItem)
{
- const FunctionList &streamOps = nsItem->findFunctions(QLatin1String("operator<<"));
+ const FunctionList &streamOps = nsItem->findFunctions("operator<<");
for (const FunctionModelItem &item : streamOps)
registerToStringCapability(item, nullptr);
for (const NamespaceModelItem &ni : nsItem->namespaces())
@@ -220,13 +262,13 @@ void AbstractMetaBuilderPrivate::registerToStringCapabilityIn(const NamespaceMod
*/
void AbstractMetaBuilderPrivate::registerToStringCapability(const FunctionModelItem &function_item,
- AbstractMetaClass *currentClass)
+ const AbstractMetaClassPtr &currentClass)
{
ArgumentList arguments = function_item->arguments();
if (arguments.size() == 2) {
- if (arguments.at(0)->type().toString() == QLatin1String("QDebug")) {
+ if (arguments.at(0)->type().toString() == u"QDebug") {
const ArgumentModelItem &arg = arguments.at(1);
- if (AbstractMetaClass *cls = argumentToClass(arg, currentClass)) {
+ if (AbstractMetaClassPtr cls = argumentToClass(arg, currentClass)) {
if (arg->type().indirections() < 2)
cls->setToStringCapability(true, int(arg->type().indirections()));
}
@@ -235,27 +277,27 @@ void AbstractMetaBuilderPrivate::registerToStringCapability(const FunctionModelI
}
void AbstractMetaBuilderPrivate::traverseOperatorFunction(const FunctionModelItem &item,
- AbstractMetaClass *currentClass)
+ const AbstractMetaClassPtr &currentClass)
{
if (item->accessPolicy() != Access::Public)
return;
- ArgumentList arguments = item->arguments();
+ const ArgumentList &itemArguments = item->arguments();
bool firstArgumentIsSelf = true;
bool unaryOperator = false;
- auto baseoperandClass = argumentToClass(arguments.at(0), currentClass);
+ auto baseoperandClass = argumentToClass(itemArguments.at(0), currentClass);
- if (arguments.size() == 1) {
+ if (itemArguments.size() == 1) {
unaryOperator = true;
} else if (!baseoperandClass
|| !baseoperandClass->typeEntry()->generateCode()) {
- baseoperandClass = argumentToClass(arguments.at(1), currentClass);
+ baseoperandClass = argumentToClass(itemArguments.at(1), currentClass);
firstArgumentIsSelf = false;
} else {
auto type = translateType(item->type(), currentClass);
- const TypeEntry *retType = type.has_value() ? type->typeEntry() : nullptr;
- AbstractMetaClass *otherArgClass = argumentToClass(arguments.at(1), currentClass);
+ const auto retType = type.has_value() ? type->typeEntry() : TypeEntryCPtr{};
+ const auto otherArgClass = argumentToClass(itemArguments.at(1), currentClass);
if (otherArgClass && retType
&& (retType->isValue() || retType->isObject())
&& retType != baseoperandClass->typeEntry()
@@ -264,43 +306,60 @@ void AbstractMetaBuilderPrivate::traverseOperatorFunction(const FunctionModelIte
firstArgumentIsSelf = false;
}
}
+ if (!baseoperandClass) {
+ rejectFunction(item, currentClass, AbstractMetaBuilder::UnmatchedOperator,
+ u"base operand class not found."_s);
+ return;
+ }
- if (baseoperandClass) {
- AbstractMetaFunction *metaFunction = traverseFunction(item, baseoperandClass);
- if (metaFunction) {
- // Strip away first argument, since that is the containing object
- AbstractMetaArgumentList arguments = metaFunction->arguments();
- if (firstArgumentIsSelf || unaryOperator) {
- AbstractMetaArgument first = arguments.takeFirst();
- fixArgumentIndexes(&arguments);
- if (!unaryOperator && first.type().indirections())
- metaFunction->setPointerOperator(true);
- metaFunction->setArguments(arguments);
- } else {
- // If the operator method is not unary and the first operator is
- // not of the same type of its owning class we suppose that it
- // must be an reverse operator (e.g. CLASS::operator(TYPE, CLASS)).
- // All operator overloads that operate over a class are already
- // being added as member functions of that class by the API Extractor.
- AbstractMetaArgument last = arguments.takeLast();
- if (last.type().indirections())
- metaFunction->setPointerOperator(true);
-
- metaFunction->setArguments(arguments);
- metaFunction->setReverseOperator(true);
- }
- metaFunction->setAccess(Access::Public);
- setupFunctionDefaults(metaFunction, baseoperandClass);
- baseoperandClass->addFunction(AbstractMetaFunctionCPtr(metaFunction));
- Q_ASSERT(!metaFunction->wasPrivate());
- } else {
- delete metaFunction;
- }
+ if (item->isSpaceshipOperator() && !item->isDeleted()) {
+ AbstractMetaClass::addSynthesizedComparisonOperators(baseoperandClass);
+ return;
}
+
+ AbstractMetaFunction *metaFunction = traverseFunction(item, baseoperandClass);
+ if (metaFunction == nullptr)
+ return;
+
+ auto flags = metaFunction->flags();
+ // Strip away first argument, since that is the containing object
+ AbstractMetaArgumentList arguments = metaFunction->arguments();
+ if (firstArgumentIsSelf || unaryOperator) {
+ AbstractMetaArgument first = arguments.takeFirst();
+ fixArgumentIndexes(&arguments);
+ if (!unaryOperator && first.type().indirections())
+ metaFunction->setPointerOperator(true);
+ metaFunction->setArguments(arguments);
+ flags.setFlag(AbstractMetaFunction::Flag::OperatorLeadingClassArgumentRemoved);
+ if (first.type().passByValue())
+ flags.setFlag(AbstractMetaFunction::Flag::OperatorClassArgumentByValue);
+ } else {
+ // If the operator method is not unary and the first operator is
+ // not of the same type of its owning class we suppose that it
+ // must be an reverse operator (e.g. CLASS::operator(TYPE, CLASS)).
+ // All operator overloads that operate over a class are already
+ // being added as member functions of that class by the API Extractor.
+ AbstractMetaArgument last = arguments.takeLast();
+ if (last.type().indirections())
+ metaFunction->setPointerOperator(true);
+ metaFunction->setArguments(arguments);
+ metaFunction->setReverseOperator(true);
+ flags.setFlag(AbstractMetaFunction::Flag::OperatorTrailingClassArgumentRemoved);
+ if (last.type().passByValue())
+ flags.setFlag(AbstractMetaFunction::Flag::OperatorClassArgumentByValue);
+ }
+ metaFunction->setFlags(flags);
+ metaFunction->setAccess(Access::Public);
+ AbstractMetaClass::addFunction(baseoperandClass, AbstractMetaFunctionCPtr(metaFunction));
+ if (!metaFunction->arguments().isEmpty()) {
+ const auto include = metaFunction->arguments().constFirst().type().typeEntry()->include();
+ baseoperandClass->typeEntry()->addArgumentInclude(include);
+ }
+ Q_ASSERT(!metaFunction->wasPrivate());
}
bool AbstractMetaBuilderPrivate::traverseStreamOperator(const FunctionModelItem &item,
- AbstractMetaClass *currentClass)
+ const AbstractMetaClassPtr &currentClass)
{
ArgumentList itemArguments = item->arguments();
if (itemArguments.size() != 2 || item->accessPolicy() != Access::Public)
@@ -327,10 +386,9 @@ bool AbstractMetaBuilderPrivate::traverseStreamOperator(const FunctionModelItem
streamFunction->setArguments(arguments);
- *streamFunction += AbstractMetaFunction::FinalInTargetLang;
streamFunction->setAccess(Access::Public);
- AbstractMetaClass *funcClass;
+ AbstractMetaClassPtr funcClass;
if (!streamClass->typeEntry()->generateCode()) {
AbstractMetaArgumentList reverseArgs = streamFunction->arguments();
@@ -343,19 +401,19 @@ bool AbstractMetaBuilderPrivate::traverseStreamOperator(const FunctionModelItem
funcClass = streamClass;
}
- setupFunctionDefaults(streamFunction, funcClass);
- funcClass->addFunction(AbstractMetaFunctionCPtr(streamFunction));
+ AbstractMetaClass::addFunction(funcClass, AbstractMetaFunctionCPtr(streamFunction));
+ auto funcTe = funcClass->typeEntry();
if (funcClass == streamClass)
- funcClass->typeEntry()->addExtraInclude(streamedClass->typeEntry()->include());
+ funcTe->addArgumentInclude(streamedClass->typeEntry()->include());
else
- funcClass->typeEntry()->addExtraInclude(streamClass->typeEntry()->include());
+ funcTe->addArgumentInclude(streamClass->typeEntry()->include());
return true;
}
static bool metaEnumLessThan(const AbstractMetaEnum &e1, const AbstractMetaEnum &e2)
{ return e1.fullName() < e2.fullName(); }
-static bool metaClassLessThan(const AbstractMetaClass *c1, const AbstractMetaClass *c2)
+static bool metaClassLessThan(const AbstractMetaClassCPtr &c1, const AbstractMetaClassCPtr &c2)
{ return c1->fullName() < c2->fullName(); }
static bool metaFunctionLessThan(const AbstractMetaFunctionCPtr &f1, const AbstractMetaFunctionCPtr &f2)
@@ -368,8 +426,8 @@ void AbstractMetaBuilderPrivate::sortLists()
// this is a temporary solution before new type revision implementation
// We need move QMetaObject register before QObject.
Dependencies additionalDependencies;
- if (auto qObjectClass = AbstractMetaClass::findClass(m_metaClasses, QStringLiteral("QObject"))) {
- if (auto qMetaObjectClass = AbstractMetaClass::findClass(m_metaClasses, QStringLiteral("QMetaObject"))) {
+ if (auto qObjectClass = AbstractMetaClass::findClass(m_metaClasses, "QObject")) {
+ if (auto qMetaObjectClass = AbstractMetaClass::findClass(m_metaClasses, "QMetaObject")) {
Dependency dependency;
dependency.parent = qMetaObjectClass;
dependency.child = qObjectClass;
@@ -378,7 +436,7 @@ void AbstractMetaBuilderPrivate::sortLists()
}
m_metaClasses = classesTopologicalSorted(m_metaClasses, additionalDependencies);
- for (AbstractMetaClass *cls : qAsConst(m_metaClasses))
+ for (const auto &cls : std::as_const(m_metaClasses))
cls->sortFunctions();
// Ensure that indexes are in alphabetical order, roughly, except
@@ -395,7 +453,7 @@ FileModelItem AbstractMetaBuilderPrivate::buildDom(QByteArrayList arguments,
unsigned clangFlags)
{
clang::Builder builder;
- builder.setSystemIncludes(TypeDatabase::instance()->systemIncludes());
+ builder.setForceProcessSystemIncludes(TypeDatabase::instance()->forceProcessSystemIncludes());
if (addCompilerSupportArguments) {
if (level == LanguageLevel::Default)
level = clang::emulatedCompilerLanguageLevel();
@@ -406,18 +464,35 @@ FileModelItem AbstractMetaBuilderPrivate::buildDom(QByteArrayList arguments,
clangFlags, builder)
? builder.dom() : FileModelItem();
const clang::BaseVisitor::Diagnostics &diagnostics = builder.diagnostics();
- if (const int diagnosticsCount = diagnostics.size()) {
+ if (const auto diagnosticsCount = diagnostics.size()) {
QDebug d = qWarning();
d.nospace();
d.noquote();
d << "Clang: " << diagnosticsCount << " diagnostic messages:\n";
- for (int i = 0; i < diagnosticsCount; ++i)
+ for (qsizetype i = 0; i < diagnosticsCount; ++i)
d << " " << diagnostics.at(i) << '\n';
}
return result;
}
-void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom)
+// List of candidates for a mismatched added global function.
+static QStringList functionCandidates(const AbstractMetaFunctionCList &list,
+ const QString &signature)
+{
+ QString name = signature;
+ const auto parenPos = name.indexOf(u'(');
+ if (parenPos > 0)
+ name.truncate(parenPos);
+ QStringList result;
+ for (const auto &func : list) {
+ if (name == func->name())
+ result += func->minimalSignature();
+ }
+ return result;
+}
+
+void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom,
+ ApiExtractorFlags flags)
{
const TypeDatabase *types = TypeDatabase::instance();
@@ -426,18 +501,18 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom)
// Start the generation...
const ClassList &typeValues = dom->classes();
- ReportHandler::startProgress("Generating class model ("
- + QByteArray::number(typeValues.size()) + ")...");
+ ReportHandler::startProgress("Generated class model ("
+ + QByteArray::number(typeValues.size()) + ").");
for (const ClassModelItem &item : typeValues) {
- if (AbstractMetaClass *cls = traverseClass(dom, item, nullptr))
- addAbstractMetaClass(cls, item.data());
+ if (const auto cls = traverseClass(dom, item, nullptr))
+ addAbstractMetaClass(cls, item.get());
}
// We need to know all global enums
const EnumList &enums = dom->enums();
- ReportHandler::startProgress("Generating enum model ("
- + QByteArray::number(enums.size()) + ")...");
+ ReportHandler::startProgress("Generated enum model ("
+ + QByteArray::number(enums.size()) + ").");
for (const EnumModelItem &item : enums) {
auto metaEnum = traverseEnum(item, nullptr, QSet<QString>());
if (metaEnum.has_value()) {
@@ -447,19 +522,19 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom)
}
const auto &namespaceTypeValues = dom->namespaces();
- ReportHandler::startProgress("Generating namespace model ("
- + QByteArray::number(namespaceTypeValues.size()) + ")...");
+ ReportHandler::startProgress("Generated namespace model ("
+ + QByteArray::number(namespaceTypeValues.size()) + ").");
for (const NamespaceModelItem &item : namespaceTypeValues)
traverseNamespace(dom, item);
// Go through all typedefs to see if we have defined any
// specific typedefs to be used as classes.
const TypeDefList typeDefs = dom->typeDefs();
- ReportHandler::startProgress("Resolving typedefs ("
- + QByteArray::number(typeDefs.size()) + ")...");
+ ReportHandler::startProgress("Resolved typedefs ("
+ + QByteArray::number(typeDefs.size()) + ").");
for (const TypeDefModelItem &typeDef : typeDefs) {
- if (AbstractMetaClass *cls = traverseTypeDef(dom, typeDef, nullptr))
- addAbstractMetaClass(cls, typeDef.data());
+ if (const auto cls = traverseTypeDef(dom, typeDef, nullptr))
+ addAbstractMetaClass(cls, typeDef.get());
}
traverseTypesystemTypedefs();
@@ -473,10 +548,10 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom)
// Global functions
const FunctionList &functions = dom->functions();
for (const FunctionModelItem &func : functions) {
- if (func->accessPolicy() != Access::Public || func->name().startsWith(QLatin1String("operator")))
+ if (func->accessPolicy() != Access::Public || func->name().startsWith(u"operator"))
continue;
- FunctionTypeEntry *funcEntry = types->findFunctionType(func->name());
+ FunctionTypeEntryPtr funcEntry = types->findFunctionType(func->name());
if (!funcEntry || !funcEntry->generateCode())
continue;
@@ -490,14 +565,15 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom)
metaFunc->setTypeEntry(funcEntry);
applyFunctionModifications(metaFunc);
+ metaFunc->applyTypeModifications();
setInclude(funcEntry, func->fileName());
m_globalFunctions << metaFuncPtr;
}
- ReportHandler::startProgress("Fixing class inheritance...");
- for (AbstractMetaClass *cls : qAsConst(m_metaClasses)) {
+ ReportHandler::startProgress("Fixed class inheritance.");
+ for (const auto &cls : std::as_const(m_metaClasses)) {
if (cls->needsInheritanceSetup()) {
setupInheritance(cls);
traverseUsingMembers(cls);
@@ -509,26 +585,28 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom)
}
}
- ReportHandler::startProgress("Detecting inconsistencies in class model...");
- for (AbstractMetaClass *cls : qAsConst(m_metaClasses)) {
- cls->fixFunctions();
+ ReportHandler::startProgress("Checked for inconsistencies in class model.");
+ for (const auto &cls : std::as_const(m_metaClasses)) {
+ AbstractMetaClass::fixFunctions(cls);
if (cls->canAddDefaultConstructor())
- cls->addDefaultConstructor();
+ AbstractMetaClass::addDefaultConstructor(cls);
if (cls->canAddDefaultCopyConstructor())
- cls->addDefaultCopyConstructor();
+ AbstractMetaClass::addDefaultCopyConstructor(cls);
- const bool vco = AbstractMetaClass::determineValueTypeWithCopyConstructorOnly(cls);
+ const bool avoidProtectedHack = flags.testFlag(ApiExtractorFlag::AvoidProtectedHack);
+ const bool vco =
+ AbstractMetaClass::determineValueTypeWithCopyConstructorOnly(cls, avoidProtectedHack);
cls->setValueTypeWithCopyConstructorOnly(vco);
cls->typeEntry()->setValueTypeWithCopyConstructorOnly(vco);
}
const auto &allEntries = types->entries();
- ReportHandler::startProgress("Detecting inconsistencies in typesystem ("
- + QByteArray::number(allEntries.size()) + ")...");
+ ReportHandler::startProgress("Checked for inconsistencies in typesystem ("
+ + QByteArray::number(allEntries.size()) + ").");
for (auto it = allEntries.cbegin(), end = allEntries.cend(); it != end; ++it) {
- TypeEntry *entry = it.value();
+ const TypeEntryPtr &entry = it.value();
if (!entry->isPrimitive()) {
if ((entry->isValue() || entry->isObject())
&& !types->shouldDropTypeEntry(entry->qualifiedCppName())
@@ -538,25 +616,27 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom)
&& !AbstractMetaClass::findClass(m_metaClasses, entry)) {
qCWarning(lcShiboken, "%s", qPrintable(msgTypeNotDefined(entry)));
} else if (entry->generateCode() && entry->type() == TypeEntry::FunctionType) {
- auto fte = static_cast<const FunctionTypeEntry *>(entry);
+ auto fte = std::static_pointer_cast<const FunctionTypeEntry>(entry);
const QStringList &signatures = fte->signatures();
for (const QString &signature : signatures) {
bool ok = false;
- for (const auto &func : qAsConst(m_globalFunctions)) {
+ for (const auto &func : std::as_const(m_globalFunctions)) {
if (signature == func->minimalSignature()) {
ok = true;
break;
}
}
if (!ok) {
+ const QStringList candidates = functionCandidates(m_globalFunctions,
+ signatures.constFirst());
qCWarning(lcShiboken, "%s",
- qPrintable(msgGlobalFunctionNotDefined(fte, signature)));
+ qPrintable(msgGlobalFunctionNotDefined(fte, signature, candidates)));
}
}
} else if (entry->isEnum() && entry->generateCode()) {
- auto enumEntry = static_cast<const EnumTypeEntry *>(entry);
- AbstractMetaClass *cls = AbstractMetaClass::findClass(m_metaClasses,
- enumEntry->parent());
+ const auto enumEntry = std::static_pointer_cast<const EnumTypeEntry>(entry);
+ const auto cls = AbstractMetaClass::findClass(m_metaClasses,
+ enumEntry->parent());
const bool enumFound = cls
? cls->findEnum(entry->targetLangEntryName()).has_value()
@@ -573,7 +653,7 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom)
}
{
- const FunctionList &hashFunctions = dom->findFunctions(QLatin1String("qHash"));
+ const FunctionList &hashFunctions = dom->findFunctions("qHash");
for (const FunctionModelItem &item : hashFunctions)
registerHashFunction(item, nullptr);
}
@@ -596,16 +676,15 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom)
}
}
- ReportHandler::startProgress("Checking inconsistencies in function modifications...");
+ ReportHandler::startProgress("Checked for inconsistencies in function modifications.");
checkFunctionModifications();
- ReportHandler::startProgress("Writing log files...");
+ ReportHandler::startProgress("Wrote log files.");
- for (AbstractMetaClass *cls : qAsConst(m_metaClasses)) {
+ for (const auto &cls : std::as_const(m_metaClasses)) {
// setupEquals(cls);
// setupComparable(cls);
- setupClonable(cls);
setupExternalConversion(cls);
// sort all inner classes topologically
@@ -615,6 +694,8 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom)
cls->setInnerClasses(classesTopologicalSorted(cls->innerClasses()));
}
+ fixSmartPointers();
+
dumpLog();
sortLists();
@@ -627,25 +708,29 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom)
throw Exception(errorMessage);
}
- m_itemToClass.clear();
- m_classToItem.clear();
- m_typeSystemTypeDefs.clear();
+ if (!m_codeModelTestMode) {
+ m_itemToClass.clear();
+ m_classToItem.clear();
+ m_typeSystemTypeDefs.clear();
+ m_scopes.clear();
+ }
ReportHandler::endProgress();
}
bool AbstractMetaBuilder::build(const QByteArrayList &arguments,
+ ApiExtractorFlags apiExtractorFlags,
bool addCompilerSupportArguments,
LanguageLevel level,
unsigned clangFlags)
{
const FileModelItem dom = d->buildDom(arguments, addCompilerSupportArguments,
level, clangFlags);
- if (dom.isNull())
+ if (!dom)
return false;
if (ReportHandler::isDebug(ReportHandler::MediumDebug))
- qCDebug(lcShiboken) << dom.data();
- d->traverseDom(dom);
+ qCDebug(lcShiboken) << dom.get();
+ d->traverseDom(dom, apiExtractorFlags);
return true;
}
@@ -657,7 +742,7 @@ void AbstractMetaBuilder::setLogDirectory(const QString &logDir)
d->m_logDirectory.append(QDir::separator());
}
-void AbstractMetaBuilderPrivate::addAbstractMetaClass(AbstractMetaClass *cls,
+void AbstractMetaBuilderPrivate::addAbstractMetaClass(const AbstractMetaClassPtr &cls,
const _CodeModelItem *item)
{
m_itemToClass.insert(item, cls);
@@ -671,23 +756,27 @@ void AbstractMetaBuilderPrivate::addAbstractMetaClass(AbstractMetaClass *cls,
}
}
-AbstractMetaClass *AbstractMetaBuilderPrivate::traverseNamespace(const FileModelItem &dom,
- const NamespaceModelItem &namespaceItem)
+AbstractMetaClassPtr
+ AbstractMetaBuilderPrivate::traverseNamespace(const FileModelItem &dom,
+ const NamespaceModelItem &namespaceItem)
{
- QString namespaceName = currentScope()->qualifiedName().join(colonColon());
+ QString namespaceName = currentScope()->qualifiedName().join(u"::"_s);
if (!namespaceName.isEmpty())
- namespaceName.append(colonColon());
+ namespaceName.append(u"::"_s);
namespaceName.append(namespaceItem->name());
if (TypeDatabase::instance()->isClassRejected(namespaceName)) {
- m_rejectedClasses.insert(namespaceName, AbstractMetaBuilder::GenerationDisabled);
- return nullptr;
+ m_rejectedClasses.insert({AbstractMetaBuilder::GenerationDisabled,
+ namespaceName, namespaceName, QString{}});
+ return {};
}
auto type = TypeDatabase::instance()->findNamespaceType(namespaceName, namespaceItem->fileName());
if (!type) {
- qCWarning(lcShiboken, "%s",
- qPrintable(msgNamespaceNoTypeEntry(namespaceItem, namespaceName)));
+ const QString rejectReason = msgNamespaceNoTypeEntry(namespaceItem, namespaceName);
+ qCWarning(lcShiboken, "%s", qPrintable(rejectReason));
+ m_rejectedClasses.insert({AbstractMetaBuilder::GenerationDisabled,
+ namespaceName, namespaceName, rejectReason});
return nullptr;
}
@@ -697,22 +786,22 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseNamespace(const FileModel
}
// Continue populating namespace?
- AbstractMetaClass *metaClass = AbstractMetaClass::findClass(m_metaClasses, type);
+ AbstractMetaClassPtr metaClass = AbstractMetaClass::findClass(m_metaClasses, type);
if (!metaClass) {
- metaClass = new AbstractMetaClass;
+ metaClass.reset(new AbstractMetaClass);
metaClass->setTypeEntry(type);
- addAbstractMetaClass(metaClass, namespaceItem.data());
+ addAbstractMetaClass(metaClass, namespaceItem.get());
if (auto extendsType = type->extends()) {
- AbstractMetaClass *extended = AbstractMetaClass::findClass(m_metaClasses, extendsType);
+ const auto extended = AbstractMetaClass::findClass(m_metaClasses, extendsType);
if (!extended) {
qCWarning(lcShiboken, "%s",
qPrintable(msgNamespaceToBeExtendedNotFound(extendsType->name(), extendsType->targetLangPackage())));
- return nullptr;
+ return {};
}
metaClass->setExtendedNamespace(extended);
}
} else {
- m_itemToClass.insert(namespaceItem.data(), metaClass);
+ m_itemToClass.insert(namespaceItem.get(), metaClass);
}
traverseEnums(namespaceItem, metaClass, namespaceItem->enumsDeclarations());
@@ -721,11 +810,11 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseNamespace(const FileModel
const ClassList &classes = namespaceItem->classes();
for (const ClassModelItem &cls : classes) {
- AbstractMetaClass *mjc = traverseClass(dom, cls, metaClass);
+ const auto mjc = traverseClass(dom, cls, metaClass);
if (mjc) {
metaClass->addInnerClass(mjc);
mjc->setEnclosingClass(metaClass);
- addAbstractMetaClass(mjc, cls.data());
+ addAbstractMetaClass(mjc, cls.get());
}
}
@@ -733,20 +822,22 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseNamespace(const FileModel
// specific typedefs to be used as classes.
const TypeDefList typeDefs = namespaceItem->typeDefs();
for (const TypeDefModelItem &typeDef : typeDefs) {
- AbstractMetaClass *cls = traverseTypeDef(dom, typeDef, metaClass);
+ const auto cls = traverseTypeDef(dom, typeDef, metaClass);
if (cls) {
metaClass->addInnerClass(cls);
cls->setEnclosingClass(metaClass);
- addAbstractMetaClass(cls, typeDef.data());
+ addAbstractMetaClass(cls, typeDef.get());
}
}
// Traverse namespaces recursively
for (const NamespaceModelItem &ni : namespaceItem->namespaces()) {
- AbstractMetaClass *mjc = traverseNamespace(dom, ni);
+ const auto mjc = traverseNamespace(dom, ni);
if (mjc) {
metaClass->addInnerClass(mjc);
mjc->setEnclosingClass(metaClass);
+ m_classToItem.insert(mjc, ni.get()); // Add for enum lookup.
+ m_itemToClass.insert(ni.get(), mjc);
}
}
@@ -760,16 +851,16 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseNamespace(const FileModel
std::optional<AbstractMetaEnum>
AbstractMetaBuilderPrivate::traverseEnum(const EnumModelItem &enumItem,
- AbstractMetaClass *enclosing,
+ const AbstractMetaClassPtr &enclosing,
const QSet<QString> &enumsDeclarations)
{
- QString qualifiedName = enumItem->qualifiedName().join(colonColon());
+ QString qualifiedName = enumItem->qualifiedName().join(u"::"_s);
- TypeEntry *typeEntry = nullptr;
- const TypeEntry *enclosingTypeEntry = enclosing ? enclosing->typeEntry() : nullptr;
+ TypeEntryPtr typeEntry;
+ const auto enclosingTypeEntry = enclosing ? enclosing->typeEntry() : TypeEntryCPtr{};
if (enumItem->accessPolicy() == Access::Private) {
- typeEntry = new EnumTypeEntry(enumItem->qualifiedName().constLast(),
- QVersionNumber(0, 0), enclosingTypeEntry);
+ typeEntry.reset(new EnumTypeEntry(enumItem->qualifiedName().constLast(),
+ QVersionNumber(0, 0), enclosingTypeEntry));
TypeDatabase::instance()->addType(typeEntry);
} else if (enumItem->enumKind() != AnonymousEnum) {
typeEntry = TypeDatabase::instance()->findType(qualifiedName);
@@ -779,7 +870,7 @@ std::optional<AbstractMetaEnum>
for (const EnumeratorModelItem &enumValue : enums) {
tmpQualifiedName.removeLast();
tmpQualifiedName << enumValue->name();
- qualifiedName = tmpQualifiedName.join(colonColon());
+ qualifiedName = tmpQualifiedName.join(u"::"_s);
typeEntry = TypeDatabase::instance()->findType(qualifiedName);
if (typeEntry)
break;
@@ -796,65 +887,75 @@ std::optional<AbstractMetaEnum>
if (TypeDatabase::instance()->isEnumRejected(className, enumName, &rejectReason)) {
if (typeEntry)
typeEntry->setCodeGeneration(TypeEntry::GenerateNothing);
- m_rejectedEnums.insert(qualifiedName + rejectReason, AbstractMetaBuilder::GenerationDisabled);
+ m_rejectedEnums.insert({AbstractMetaBuilder::GenerationDisabled, qualifiedName,
+ qualifiedName, rejectReason});
return {};
}
const bool rejectionWarning = !enclosing || enclosing->typeEntry()->generateCode();
if (!typeEntry) {
+ const QString rejectReason = msgNoEnumTypeEntry(enumItem, className);
if (rejectionWarning)
- qCWarning(lcShiboken, "%s", qPrintable(msgNoEnumTypeEntry(enumItem, className)));
- m_rejectedEnums.insert(qualifiedName, AbstractMetaBuilder::NotInTypeSystem);
+ qCWarning(lcShiboken, "%s", qPrintable(rejectReason));
+ m_rejectedEnums.insert({AbstractMetaBuilder::NotInTypeSystem, qualifiedName,
+ qualifiedName, rejectReason});
return {};
}
if (!typeEntry->isEnum()) {
- if (rejectionWarning) {
- qCWarning(lcShiboken, "%s",
- qPrintable(msgNoEnumTypeConflict(enumItem, className, typeEntry)));
- }
- m_rejectedEnums.insert(qualifiedName, AbstractMetaBuilder::NotInTypeSystem);
+ const QString rejectReason = msgNoEnumTypeConflict(enumItem, className, typeEntry);
+ if (rejectionWarning)
+ qCWarning(lcShiboken, "%s", qPrintable(rejectReason));
+ m_rejectedEnums.insert({AbstractMetaBuilder::NotInTypeSystem, qualifiedName,
+ qualifiedName, rejectReason});
return {};
}
AbstractMetaEnum metaEnum;
metaEnum.setEnumKind(enumItem->enumKind());
+ metaEnum.setDeprecated(enumItem->isDeprecated());
+ metaEnum.setUnderlyingType(enumItem->underlyingType());
metaEnum.setSigned(enumItem->isSigned());
if (enumsDeclarations.contains(qualifiedName)
|| enumsDeclarations.contains(enumName)) {
metaEnum.setHasQEnumsDeclaration(true);
}
- auto *enumTypeEntry = static_cast<EnumTypeEntry *>(typeEntry);
+ auto enumTypeEntry = std::static_pointer_cast<EnumTypeEntry>(typeEntry);
metaEnum.setTypeEntry(enumTypeEntry);
metaEnum.setAccess(enumItem->accessPolicy());
if (metaEnum.access() == Access::Private)
typeEntry->setCodeGeneration(TypeEntry::GenerateNothing);
-
+ // PYSIDE-2088, MSVC signedness issue in Qt
+ const bool castToUnsigned = enumItem->isSigned()
+ && enumTypeEntry->cppType().contains(u"unsigned"_s);
const EnumeratorList &enums = enumItem->enumerators();
- for (const EnumeratorModelItem &value : enums) {
+ for (const EnumeratorModelItem &valueItem : enums) {
AbstractMetaEnumValue metaEnumValue;
- metaEnumValue.setName(value->name());
+ metaEnumValue.setName(valueItem->name());
// Deciding the enum value...
- metaEnumValue.setStringValue(value->stringValue());
- metaEnumValue.setValue(value->value());
+ metaEnumValue.setStringValue(valueItem->stringValue());
+ const auto value = valueItem->value();
+ metaEnumValue.setValue(castToUnsigned ? value.toUnsigned() : value);
+ metaEnumValue.setDeprecated(valueItem->isDeprecated());
metaEnum.addEnumValue(metaEnumValue);
}
- if (!metaEnum.typeEntry()->include().isValid())
- setInclude(metaEnum.typeEntry(), enumItem->fileName());
+ if (!metaEnum.typeEntry()->include().isValid()) {
+ auto te = std::const_pointer_cast<EnumTypeEntry>(metaEnum.typeEntry());
+ setInclude(te, enumItem->fileName());
+ }
// Register all enum values on Type database
const bool isScopedEnum = enumItem->enumKind() == EnumClass;
const EnumeratorList &enumerators = enumItem->enumerators();
for (const EnumeratorModelItem &e : enumerators) {
- auto enumValue =
- new EnumValueTypeEntry(e->name(), e->stringValue(),
- enumTypeEntry, isScopedEnum,
- enumTypeEntry->version());
+ auto enumValue = std::make_shared<EnumValueTypeEntry>(e->name(), e->stringValue(),
+ enumTypeEntry, isScopedEnum,
+ enumTypeEntry->version());
TypeDatabase::instance()->addType(enumValue);
if (e->value().isNullValue())
enumTypeEntry->setNullValue(enumValue);
@@ -866,9 +967,31 @@ std::optional<AbstractMetaEnum>
return metaEnum;
}
-AbstractMetaClass *AbstractMetaBuilderPrivate::traverseTypeDef(const FileModelItem &,
- const TypeDefModelItem &typeDef,
- AbstractMetaClass *currentClass)
+AbstractMetaClassPtr
+ AbstractMetaBuilderPrivate::traverseTypeDef(const FileModelItem &dom,
+ const TypeDefModelItem &typeDef,
+ const AbstractMetaClassPtr &currentClass)
+{
+ auto result = traverseTypeDefHelper(dom, typeDef, currentClass);
+ if (!result && typeDef->type().isPlain()) {
+ const auto &type = typeDef->type();
+ QString fullName;
+ if (currentClass)
+ fullName += currentClass->qualifiedCppName() + "::"_L1;
+ fullName += typeDef->name();
+ QString targetName = typeDef->type().toString();
+ m_typedefTargetToName.insert(targetName, fullName);
+ const QByteArray normalized = QMetaObject::normalizedType(targetName.toUtf8().constData());
+ if (targetName != QLatin1StringView(normalized))
+ m_typedefTargetToName.insert(QString::fromUtf8(normalized), fullName);
+ }
+ return result;
+}
+
+AbstractMetaClassPtr
+ AbstractMetaBuilderPrivate::traverseTypeDefHelper(const FileModelItem &,
+ const TypeDefModelItem &typeDef,
+ const AbstractMetaClassPtr &currentClass)
{
TypeDatabase *types = TypeDatabase::instance();
QString className = stripTemplateArgs(typeDef->name());
@@ -877,26 +1000,39 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseTypeDef(const FileModelIt
// we have an inner class
if (currentClass) {
fullClassName = stripTemplateArgs(currentClass->typeEntry()->qualifiedCppName())
- + colonColon() + fullClassName;
+ + u"::"_s + fullClassName;
}
// If this is the alias for a primitive type
// we store the aliased type on the alias
// TypeEntry
- PrimitiveTypeEntry *ptype = types->findPrimitiveType(className);
+ const auto ptype = types->findPrimitiveType(className);
+ const auto &targetNames = typeDef->type().qualifiedName();
+ const auto pTarget = targetNames.size() == 1
+ ? types->findPrimitiveType(targetNames.constFirst()) : PrimitiveTypeEntryPtr{};
if (ptype) {
- QString typeDefName = typeDef->type().qualifiedName()[0];
- ptype->setReferencedTypeEntry(types->findPrimitiveType(typeDefName));
+ ptype->setReferencedTypeEntry(pTarget);
return nullptr;
}
+ // It is a (nested?) global typedef to a primitive type
+ // (like size_t = unsigned)? Add it to the type DB.
+ if (pTarget && isCppPrimitive(basicReferencedNonBuiltinTypeEntry(pTarget))
+ && currentClass == nullptr) {
+ auto pte = std::make_shared<PrimitiveTypeEntry>(className, QVersionNumber{},
+ TypeEntryCPtr{});
+ pte->setReferencedTypeEntry(pTarget);
+ pte->setBuiltIn(true);
+ types->addType(pte);
+ return nullptr;
+ }
// If we haven't specified anything for the typedef, then we don't care
- ComplexTypeEntry *type = types->findComplexType(fullClassName);
+ auto type = types->findComplexType(fullClassName);
if (!type)
return nullptr;
- auto *metaClass = new AbstractMetaClass;
+ auto metaClass = std::make_shared<AbstractMetaClass>();
metaClass->setTypeDef(true);
metaClass->setTypeEntry(type);
metaClass->setBaseClassNames(QStringList(typeDef->type().toString()));
@@ -915,8 +1051,8 @@ void AbstractMetaBuilderPrivate::traverseTypesystemTypedefs()
{
const auto &entries = TypeDatabase::instance()->typedefEntries();
for (auto it = entries.begin(), end = entries.end(); it != end; ++it) {
- TypedefEntry *te = it.value();
- auto *metaClass = new AbstractMetaClass;
+ const TypedefEntryPtr &te = it.value();
+ auto metaClass = std::make_shared<AbstractMetaClass>();
metaClass->setTypeDef(true);
metaClass->setTypeEntry(te->target());
metaClass->setBaseClassNames(QStringList(te->sourceType()));
@@ -942,9 +1078,9 @@ void AbstractMetaBuilderPrivate::traverseTypesystemTypedefs()
}
}
-AbstractMetaClass *AbstractMetaBuilderPrivate::traverseClass(const FileModelItem &dom,
+AbstractMetaClassPtr AbstractMetaBuilderPrivate::traverseClass(const FileModelItem &dom,
const ClassModelItem &classItem,
- AbstractMetaClass *currentClass)
+ const AbstractMetaClassPtr &currentClass)
{
QString className = stripTemplateArgs(classItem->name());
QString fullClassName = className;
@@ -952,20 +1088,24 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseClass(const FileModelItem
// we have inner an class
if (currentClass) {
fullClassName = stripTemplateArgs(currentClass->typeEntry()->qualifiedCppName())
- + colonColon() + fullClassName;
+ + u"::"_s + fullClassName;
}
- ComplexTypeEntry *type = TypeDatabase::instance()->findComplexType(fullClassName);
+ const auto type = TypeDatabase::instance()->findComplexType(fullClassName);
AbstractMetaBuilder::RejectReason reason = AbstractMetaBuilder::NoReason;
if (TypeDatabase::instance()->isClassRejected(fullClassName)) {
reason = AbstractMetaBuilder::GenerationDisabled;
} else if (!type) {
- TypeEntry *te = TypeDatabase::instance()->findType(fullClassName);
- if (te && !te->isComplex())
+ TypeEntryPtr te = TypeDatabase::instance()->findType(fullClassName);
+ if (te && !te->isComplex()) {
reason = AbstractMetaBuilder::RedefinedToNotClass;
- else
+ // Set the default include file name
+ if (!te->include().isValid())
+ setInclude(te, classItem->fileName());
+ } else {
reason = AbstractMetaBuilder::NotInTypeSystem;
+ }
} else if (type->codeGeneration() == TypeEntry::GenerateNothing) {
reason = AbstractMetaBuilder::GenerationDisabled;
}
@@ -974,11 +1114,11 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseClass(const FileModelItem
QTextStream(&fullClassName) << "anonymous struct at " << classItem->fileName()
<< ':' << classItem->startLine();
}
- m_rejectedClasses.insert(fullClassName, reason);
+ m_rejectedClasses.insert({reason, fullClassName, fullClassName, QString{}});
return nullptr;
}
- auto *metaClass = new AbstractMetaClass;
+ auto metaClass = std::make_shared<AbstractMetaClass>();
metaClass->setSourceLocation(classItem->sourceLocation());
metaClass->setTypeEntry(type);
if ((type->typeFlags() & ComplexTypeEntry::ForceAbstract) != 0)
@@ -987,6 +1127,9 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseClass(const FileModelItem
if (classItem->isFinal())
*metaClass += AbstractMetaClass::FinalCppClass;
+ if (classItem->classType() == CodeModel::Struct)
+ *metaClass += AbstractMetaClass::Struct;
+
QStringList baseClassNames;
const QList<_ClassModelItem::BaseClass> &baseClasses = classItem->baseClasses();
for (const _ClassModelItem::BaseClass &baseClass : baseClasses) {
@@ -1000,21 +1143,22 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseClass(const FileModelItem
if (ReportHandler::isDebug(ReportHandler::MediumDebug)) {
const QString message = type->isContainer()
- ? u"container: '"_qs + fullClassName + u'\''
- : u"class: '"_qs + metaClass->fullName() + u'\'';
+ ? u"container: '"_s + fullClassName + u'\''
+ : u"class: '"_s + metaClass->fullName() + u'\'';
qCInfo(lcShiboken, "%s", qPrintable(message));
}
TemplateParameterList template_parameters = classItem->templateParameters();
- TypeEntries template_args;
+ TypeEntryCList template_args;
template_args.clear();
- auto argumentParent = metaClass->typeEntry()->typeSystemTypeEntry();
- for (int i = 0; i < template_parameters.size(); ++i) {
+ auto argumentParent = typeSystemTypeEntry(metaClass->typeEntry());
+ for (qsizetype i = 0; i < template_parameters.size(); ++i) {
const TemplateParameterModelItem &param = template_parameters.at(i);
- auto param_type = new TemplateArgumentEntry(param->name(), type->version(),
+ auto param_type =
+ std::make_shared<TemplateArgumentEntry>(param->name(), type->version(),
argumentParent);
param_type->setOrdinal(i);
- template_args.append(param_type);
+ template_args.append(TypeEntryCPtr(param_type));
}
metaClass->setTemplateArguments(template_args);
@@ -1026,11 +1170,11 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseClass(const FileModelItem
{
const ClassList &innerClasses = classItem->classes();
for (const ClassModelItem &ci : innerClasses) {
- AbstractMetaClass *cl = traverseClass(dom, ci, metaClass);
+ const auto cl = traverseClass(dom, ci, metaClass);
if (cl) {
cl->setEnclosingClass(metaClass);
metaClass->addInnerClass(cl);
- addAbstractMetaClass(cl, ci.data());
+ addAbstractMetaClass(cl, ci.get());
}
}
@@ -1040,10 +1184,10 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseClass(const FileModelItem
// specific typedefs to be used as classes.
const TypeDefList typeDefs = classItem->typeDefs();
for (const TypeDefModelItem &typeDef : typeDefs) {
- AbstractMetaClass *cls = traverseTypeDef(dom, typeDef, metaClass);
+ const auto cls = traverseTypeDef(dom, typeDef, metaClass);
if (cls) {
cls->setEnclosingClass(metaClass);
- addAbstractMetaClass(cls, typeDef.data());
+ addAbstractMetaClass(cls, typeDef.get());
}
}
@@ -1055,7 +1199,7 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseClass(const FileModelItem
}
void AbstractMetaBuilderPrivate::traverseScopeMembers(const ScopeModelItem &item,
- AbstractMetaClass *metaClass)
+ const AbstractMetaClassPtr &metaClass)
{
// Classes/Namespace members
traverseFields(item, metaClass);
@@ -1069,28 +1213,25 @@ void AbstractMetaBuilderPrivate::traverseScopeMembers(const ScopeModelItem &item
void AbstractMetaBuilderPrivate::traverseClassMembers(const ClassModelItem &item)
{
- AbstractMetaClass *metaClass = m_itemToClass.value(item.data());
- if (!metaClass)
- return;
-
- // Class members
- traverseScopeMembers(item, metaClass);
+ const auto metaClass = m_itemToClass.value(item.get());
+ if (metaClass) // Class members
+ traverseScopeMembers(item, metaClass);
}
-void AbstractMetaBuilderPrivate::traverseUsingMembers(AbstractMetaClass *metaClass)
+void AbstractMetaBuilderPrivate::traverseUsingMembers(const AbstractMetaClassPtr &metaClass) const
{
const _CodeModelItem *item = m_classToItem.value(metaClass);
if (item == nullptr || item->kind() != _CodeModelItem::Kind_Class)
return;
- auto classItem = static_cast<const _ClassModelItem *>(item);
+ const auto *classItem = static_cast<const _ClassModelItem *>(item);
for (const auto &um : classItem->usingMembers()) {
QString className = um.className;
- int pos = className.indexOf(u'<'); // strip "QList<value>"
+ auto pos = className.indexOf(u'<'); // strip "QList<value>"
if (pos != -1)
className.truncate(pos);
- if (auto baseClass = metaClass->AbstractMetaClass::findBaseClass(className)) {
+ if (auto baseClass = findBaseClass(metaClass, className)) {
QString name = um.memberName;
- const int lastQualPos = name.lastIndexOf(colonColon());
+ const auto lastQualPos = name.lastIndexOf(u"::"_s);
if (lastQualPos != -1)
name.remove(0, lastQualPos + 2);
metaClass->addUsingMember({name, baseClass, um.access});
@@ -1104,7 +1245,7 @@ void AbstractMetaBuilderPrivate::traverseUsingMembers(AbstractMetaClass *metaCla
void AbstractMetaBuilderPrivate::traverseNamespaceMembers(const NamespaceModelItem &item)
{
- AbstractMetaClass *metaClass = m_itemToClass.value(item.data());
+ const auto metaClass = m_itemToClass.value(item.get());
if (!metaClass)
return;
@@ -1119,18 +1260,18 @@ void AbstractMetaBuilderPrivate::traverseNamespaceMembers(const NamespaceModelIt
static inline QString fieldSignatureWithType(const VariableModelItem &field)
{
- return field->name() + QStringLiteral(" -> ") + field->type().toString();
+ return field->name() + " -> "_L1 + field->type().toString();
}
static inline QString qualifiedFieldSignatureWithType(const QString &className,
const VariableModelItem &field)
{
- return className + colonColon() + fieldSignatureWithType(field);
+ return className + u"::"_s + fieldSignatureWithType(field);
}
std::optional<AbstractMetaField>
AbstractMetaBuilderPrivate::traverseField(const VariableModelItem &field,
- const AbstractMetaClass *cls)
+ const AbstractMetaClassCPtr &cls)
{
QString fieldName = field->name();
QString className = cls->typeEntry()->qualifiedCppName();
@@ -1144,8 +1285,9 @@ std::optional<AbstractMetaField>
QString rejectReason;
if (TypeDatabase::instance()->isFieldRejected(className, fieldName, &rejectReason)) {
- m_rejectedFields.insert(qualifiedFieldSignatureWithType(className, field) + rejectReason,
- AbstractMetaBuilder::GenerationDisabled);
+ const QString signature = qualifiedFieldSignatureWithType(className, field);
+ m_rejectedFields.insert({AbstractMetaBuilder::GenerationDisabled,
+ signature, signature, rejectReason});
return {};
}
@@ -1158,7 +1300,7 @@ std::optional<AbstractMetaField>
auto metaType = translateType(fieldType, cls);
if (!metaType.has_value()) {
- const QString type = TypeInfo::resolveType(fieldType, currentScope()).qualifiedName().join(colonColon());
+ const QString type = TypeInfo::resolveType(fieldType, currentScope()).qualifiedName().join(u"::"_s);
if (cls->typeEntry()->generateCode()) {
qCWarning(lcShiboken, "%s",
qPrintable(msgSkippingField(field, cls->name(), type)));
@@ -1193,7 +1335,7 @@ static bool applyFieldModifications(AbstractMetaField *f)
}
void AbstractMetaBuilderPrivate::traverseFields(const ScopeModelItem &scope_item,
- AbstractMetaClass *metaClass)
+ const AbstractMetaClassPtr &metaClass)
{
const VariableList &variables = scope_item->variables();
for (const VariableModelItem &field : variables) {
@@ -1206,37 +1348,22 @@ void AbstractMetaBuilderPrivate::traverseFields(const ScopeModelItem &scope_item
}
}
-void AbstractMetaBuilderPrivate::setupFunctionDefaults(AbstractMetaFunction *metaFunction,
- AbstractMetaClass *metaClass)
-{
- // Set the default value of the declaring class. This may be changed
- // in fixFunctions later on
- metaFunction->setDeclaringClass(metaClass);
-
- // Some of the queries below depend on the implementing class being set
- // to function properly. Such as function modifications
- metaFunction->setImplementingClass(metaClass);
-
- if (metaFunction->name() == QLatin1String("operator_equal"))
- metaClass->setHasEqualsOperator(true);
-}
-
void AbstractMetaBuilderPrivate::fixReturnTypeOfConversionOperator(AbstractMetaFunction *metaFunction)
{
if (!metaFunction->isConversionOperator())
return;
TypeDatabase *types = TypeDatabase::instance();
- static const QRegularExpression operatorRegExp(QStringLiteral("^operator "));
+ static const QRegularExpression operatorRegExp("^operator "_L1);
Q_ASSERT(operatorRegExp.isValid());
QString castTo = metaFunction->name().remove(operatorRegExp).trimmed();
- if (castTo.endsWith(QLatin1Char('&')))
+ if (castTo.endsWith(u'&'))
castTo.chop(1);
- if (castTo.startsWith(QLatin1String("const ")))
+ if (castTo.startsWith(u"const "))
castTo.remove(0, 6);
- TypeEntry *retType = types->findType(castTo);
+ TypeEntryPtr retType = types->findType(castTo);
if (!retType)
return;
@@ -1248,16 +1375,22 @@ void AbstractMetaBuilderPrivate::fixReturnTypeOfConversionOperator(AbstractMetaF
AbstractMetaFunctionRawPtrList
AbstractMetaBuilderPrivate::classFunctionList(const ScopeModelItem &scopeItem,
AbstractMetaClass::Attributes *constructorAttributes,
- AbstractMetaClass *currentClass)
+ const AbstractMetaClassPtr &currentClass)
{
*constructorAttributes = {};
AbstractMetaFunctionRawPtrList result;
const FunctionList &scopeFunctionList = scopeItem->functions();
result.reserve(scopeFunctionList.size());
+ const bool isNamespace = currentClass->isNamespace();
for (const FunctionModelItem &function : scopeFunctionList) {
- if (AbstractMetaFunction *metaFunction = traverseFunction(function, currentClass)) {
+ if (isNamespace && function->isOperator()) {
+ traverseOperatorFunction(function, currentClass);
+ } else if (function->isSpaceshipOperator() && !function->isDeleted()) {
+ if (currentClass)
+ AbstractMetaClass::addSynthesizedComparisonOperators(currentClass);
+ } else if (auto *metaFunction = traverseFunction(function, currentClass)) {
result.append(metaFunction);
- } else if (function->functionType() == CodeModel::Constructor) {
+ } else if (!function->isDeleted() && function->functionType() == CodeModel::Constructor) {
auto arguments = function->arguments();
*constructorAttributes |= AbstractMetaClass::HasRejectedConstructor;
if (arguments.isEmpty() || arguments.constFirst()->defaultValue())
@@ -1267,8 +1400,8 @@ AbstractMetaFunctionRawPtrList
return result;
}
-void AbstractMetaBuilderPrivate::traverseFunctions(ScopeModelItem scopeItem,
- AbstractMetaClass *metaClass)
+void AbstractMetaBuilderPrivate::traverseFunctions(const ScopeModelItem& scopeItem,
+ const AbstractMetaClassPtr &metaClass)
{
AbstractMetaClass::Attributes constructorAttributes;
const AbstractMetaFunctionRawPtrList functions =
@@ -1277,7 +1410,7 @@ void AbstractMetaBuilderPrivate::traverseFunctions(ScopeModelItem scopeItem,
for (AbstractMetaFunction *metaFunction : functions) {
if (metaClass->isNamespace())
- *metaFunction += AbstractMetaFunction::Static;
+ metaFunction->setCppAttribute(FunctionAttribute::Static);
const auto propertyFunction = metaClass->searchPropertyFunction(metaFunction->name());
if (propertyFunction.index >= 0) {
@@ -1310,34 +1443,31 @@ void AbstractMetaBuilderPrivate::traverseFunctions(ScopeModelItem scopeItem,
metaFunction->setPropertySpecIndex(propertyFunction.index);
}
break;
+ case AbstractMetaClass::PropertyFunction::Notify:
+ if (metaFunction->isSignal()) {
+ *metaFunction += AbstractMetaFunction::PropertyNotify;
+ metaFunction->setPropertySpecIndex(propertyFunction.index);
+ }
}
}
- const bool isInvalidDestructor = metaFunction->isDestructor() && metaFunction->isPrivate();
- const bool isInvalidConstructor = metaFunction->functionType() == AbstractMetaFunction::ConstructorFunction
- && metaFunction->isPrivate();
- if (isInvalidConstructor)
+ if (metaFunction->functionType() == AbstractMetaFunction::ConstructorFunction
+ && metaFunction->isPrivate()) {
metaClass->setHasPrivateConstructor(true);
- if ((isInvalidDestructor || isInvalidConstructor)
- && !metaClass->hasNonPrivateConstructor()) {
- *metaClass += AbstractMetaClass::FinalInTargetLang;
- } else if (metaFunction->isConstructor() && !metaFunction->isPrivate()) {
- *metaClass -= AbstractMetaClass::FinalInTargetLang;
- metaClass->setHasNonPrivateConstructor(true);
}
+ if (metaFunction->isConstructor() && !metaFunction->isPrivate()) // Including Copy CT
+ metaClass->setHasNonPrivateConstructor(true);
if (!metaFunction->isDestructor()
&& !(metaFunction->isPrivate() && metaFunction->functionType() == AbstractMetaFunction::ConstructorFunction)) {
- setupFunctionDefaults(metaFunction, metaClass);
-
if (metaFunction->isSignal() && metaClass->hasSignal(metaFunction))
qCWarning(lcShiboken, "%s", qPrintable(msgSignalOverloaded(metaClass, metaFunction)));
if (metaFunction->isConversionOperator())
fixReturnTypeOfConversionOperator(metaFunction);
- metaClass->addFunction(AbstractMetaFunctionCPtr(metaFunction));
+ AbstractMetaClass::addFunction(metaClass, AbstractMetaFunctionCPtr(metaFunction));
applyFunctionModifications(metaFunction);
} else if (metaFunction->isDestructor()) {
metaClass->setHasPrivateDestructor(metaFunction->isPrivate());
@@ -1353,7 +1483,7 @@ void AbstractMetaBuilderPrivate::traverseFunctions(ScopeModelItem scopeItem,
fillAddedFunctions(metaClass);
}
-void AbstractMetaBuilderPrivate::fillAddedFunctions(AbstractMetaClass *metaClass)
+void AbstractMetaBuilderPrivate::fillAddedFunctions(const AbstractMetaClassPtr &metaClass)
{
// Add the functions added by the typesystem
QString errorMessage;
@@ -1366,12 +1496,12 @@ void AbstractMetaBuilderPrivate::fillAddedFunctions(AbstractMetaClass *metaClass
QString AbstractMetaBuilder::getSnakeCaseName(const QString &name)
{
- const int size = name.size();
+ const auto size = name.size();
if (size < 3)
return name;
QString result;
result.reserve(size + 4);
- for (int i = 0; i < size; ++i) {
+ for (qsizetype i = 0; i < size; ++i) {
const QChar c = name.at(i);
if (c.isUpper()) {
if (i > 0) {
@@ -1417,26 +1547,17 @@ void AbstractMetaBuilderPrivate::applyFunctionModifications(AbstractMetaFunction
func->setOriginalName(func->name());
func->setName(mod.renamedToName());
} else if (mod.isAccessModifier()) {
- funcRef -= AbstractMetaFunction::Friendly;
-
if (mod.isPublic())
funcRef.modifyAccess(Access::Public);
else if (mod.isProtected())
funcRef.modifyAccess(Access::Protected);
else if (mod.isPrivate())
funcRef.modifyAccess(Access::Private);
- else if (mod.isFriendly())
- funcRef += AbstractMetaFunction::Friendly;
}
-
- if (mod.isFinal())
- funcRef += AbstractMetaFunction::FinalInTargetLang;
- else if (mod.isNonFinal())
- funcRef -= AbstractMetaFunction::FinalInTargetLang;
}
}
-bool AbstractMetaBuilderPrivate::setupInheritance(AbstractMetaClass *metaClass)
+bool AbstractMetaBuilderPrivate::setupInheritance(const AbstractMetaClassPtr &metaClass)
{
if (metaClass->inheritanceDone())
return true;
@@ -1446,13 +1567,15 @@ 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.constFirst().contains(QLatin1Char('<'))) {
+ if (baseClasses.size() == 1 && baseClasses.constFirst().contains(u'<')) {
TypeInfo info;
- ComplexTypeEntry* baseContainerType;
- AbstractMetaClass* templ = findTemplateClass(baseClasses.constFirst(), metaClass, &info, &baseContainerType);
+ ComplexTypeEntryPtr baseContainerType;
+ const auto templ = findTemplateClass(baseClasses.constFirst(), metaClass,
+ &info, &baseContainerType);
if (templ) {
setupInheritance(templ);
- inheritTemplate(metaClass, templ, info);
+ if (!inheritTemplate(metaClass, templ, info))
+ return false;
metaClass->typeEntry()->setBaseContainerType(templ->typeEntry());
return true;
}
@@ -1469,15 +1592,15 @@ bool AbstractMetaBuilderPrivate::setupInheritance(AbstractMetaClass *metaClass)
return true;
}
- qCWarning(lcShiboken).noquote().nospace()
- << QStringLiteral("template baseclass '%1' of '%2' is not known")
- .arg(baseClasses.constFirst(), metaClass->name());
+ qCWarning(lcShiboken, "template baseclass '%s' of '%s' is not known",
+ qPrintable(baseClasses.constFirst()),
+ qPrintable(metaClass->name()));
return false;
}
- TypeDatabase* types = TypeDatabase::instance();
+ auto *types = TypeDatabase::instance();
- for (const auto &baseClassName : baseClasses) {
+ for (const auto &baseClassName : baseClasses) {
if (!types->isClassRejected(baseClassName)) {
auto typeEntry = types->findType(baseClassName);
if (typeEntry == nullptr || !typeEntry->isComplex()) {
@@ -1506,7 +1629,7 @@ bool AbstractMetaBuilderPrivate::setupInheritance(AbstractMetaClass *metaClass)
} else {
QString message;
QTextStream(&message) << "Class \"" << defaultSuperclassName
- << "\" specified as \"default-superclass\" of \"" << metaClass->name()
+ << R"(" specified as "default-superclass" of ")" << metaClass->name()
<< "\" could not be found in the code model.";
qCWarning(lcShiboken, "%s", qPrintable(message));
}
@@ -1516,7 +1639,7 @@ bool AbstractMetaBuilderPrivate::setupInheritance(AbstractMetaClass *metaClass)
}
void AbstractMetaBuilderPrivate::traverseEnums(const ScopeModelItem &scopeItem,
- AbstractMetaClass *metaClass,
+ const AbstractMetaClassPtr &metaClass,
const QStringList &enumsDeclarations)
{
const EnumList &enums = scopeItem->enums();
@@ -1564,7 +1687,7 @@ bool AbstractMetaBuilderPrivate::traverseAddedGlobalFunction(const AddedFunction
AbstractMetaFunction *
AbstractMetaBuilderPrivate::traverseAddedFunctionHelper(const AddedFunctionPtr &addedFunc,
- AbstractMetaClass *metaClass /* = nullptr */,
+ const AbstractMetaClassPtr &metaClass /* = {} */,
QString *errorMessage)
{
auto returnType = translateType(addedFunc->returnType(), metaClass, {}, errorMessage);
@@ -1576,13 +1699,13 @@ AbstractMetaFunction *
return nullptr;
}
- auto metaFunction = new AbstractMetaFunction(addedFunc);
+ auto *metaFunction = new AbstractMetaFunction(addedFunc);
metaFunction->setType(returnType.value());
metaFunction->setFunctionType(functionTypeFromName(addedFunc->name()));
const auto &args = addedFunc->arguments();
- qsizetype argCount = args.count();
+ qsizetype argCount = args.size();
// Check "foo(void)"
if (argCount == 1 && args.constFirst().typeInfo.isVoid())
argCount = 0;
@@ -1633,7 +1756,8 @@ AbstractMetaFunction *
// Find the correct default values
const FunctionModificationList functionMods = metaFunction->modifications(metaClass);
- for (int i = 0; i < metaArguments.size(); ++i) {
+ applyCachedFunctionModifications(metaFunction, functionMods);
+ for (qsizetype i = 0; i < metaArguments.size(); ++i) {
AbstractMetaArgument &metaArg = metaArguments[i];
// use replace-default-expression for set default value
@@ -1648,7 +1772,7 @@ AbstractMetaFunction *
}
bool AbstractMetaBuilderPrivate::traverseAddedMemberFunction(const AddedFunctionPtr &addedFunc,
- AbstractMetaClass *metaClass,
+ const AbstractMetaClassPtr &metaClass,
QString *errorMessage)
{
AbstractMetaFunction *metaFunction =
@@ -1658,11 +1782,11 @@ bool AbstractMetaBuilderPrivate::traverseAddedMemberFunction(const AddedFunction
const AbstractMetaArgumentList fargs = metaFunction->arguments();
if (metaClass->isNamespace())
- *metaFunction += AbstractMetaFunction::Static;
+ metaFunction->setCppAttribute(FunctionAttribute::Static);
if (metaFunction->name() == metaClass->name()) {
metaFunction->setFunctionType(AbstractMetaFunction::ConstructorFunction);
if (fargs.size() == 1) {
- const TypeEntry *te = fargs.constFirst().type().typeEntry();
+ const auto te = fargs.constFirst().type().typeEntry();
if (te->isCustom())
metaFunction->setExplicit(true);
if (te->name() == metaFunction->name())
@@ -1672,7 +1796,7 @@ bool AbstractMetaBuilderPrivate::traverseAddedMemberFunction(const AddedFunction
metaFunction->setDeclaringClass(metaClass);
metaFunction->setImplementingClass(metaClass);
- metaClass->addFunction(AbstractMetaFunctionCPtr(metaFunction));
+ AbstractMetaClass::addFunction(metaClass, AbstractMetaFunctionCPtr(metaFunction));
metaClass->setHasNonPrivateConstructor(true);
return true;
}
@@ -1688,9 +1812,9 @@ void AbstractMetaBuilderPrivate::fixArgumentNames(AbstractMetaFunction *func, co
}
}
- for (int i = 0, size = arguments.size(); i < size; ++i) {
+ for (qsizetype i = 0, size = arguments.size(); i < size; ++i) {
if (arguments.at(i).name().isEmpty())
- arguments[i].setName(QLatin1String("arg__") + QString::number(i + 1), false);
+ arguments[i].setName(u"arg__"_s + QString::number(i + 1), false);
}
}
@@ -1700,15 +1824,15 @@ static QString functionSignature(const FunctionModelItem &functionItem)
const ArgumentList &arguments = functionItem->arguments();
for (const ArgumentModelItem &arg : arguments)
args << arg->type().toString();
- return functionItem->name() + QLatin1Char('(') + args.join(QLatin1Char(',')) + QLatin1Char(')');
+ return functionItem->name() + u'(' + args.join(u',') + u')';
}
static inline QString qualifiedFunctionSignatureWithType(const FunctionModelItem &functionItem,
const QString &className = QString())
{
- QString result = functionItem->type().toString() + QLatin1Char(' ');
+ QString result = functionItem->type().toString() + u' ';
if (!className.isEmpty())
- result += className + colonColon();
+ result += className + u"::"_s;
result += functionSignature(functionItem);
return result;
}
@@ -1805,7 +1929,7 @@ static bool applyArrayArgumentModifications(const FunctionModificationList &func
const int i = argMod.index() - 1;
if (i < 0 || i >= func->arguments().size()) {
*errorMessage = msgCannotSetArrayUsage(func->minimalSignature(), i,
- QLatin1String("Index out of range."));
+ u"Index out of range."_s);
return false;
}
auto t = func->arguments().at(i).type();
@@ -1820,9 +1944,48 @@ static bool applyArrayArgumentModifications(const FunctionModificationList &func
return true;
}
+// Create the meta type for a view (std::string_view -> std::string)
+static AbstractMetaType createViewOnType(const AbstractMetaType &metaType,
+ const TypeEntryCPtr &viewOnTypeEntry)
+{
+ auto result = metaType;
+ result.setTypeEntry(viewOnTypeEntry);
+ if (!metaType.isContainer() || !viewOnTypeEntry->isContainer())
+ return result;
+ // For containers, when sth with several template parameters
+ // (std::span<T, int N>) is mapped onto a std::vector<T>,
+ // remove the superfluous template parameters and strip 'const'.
+ const auto vcte = std::static_pointer_cast<const ContainerTypeEntry>(viewOnTypeEntry);
+ const auto &instantiations = metaType.instantiations();
+ AbstractMetaTypeList viewInstantiations;
+ const auto size = std::min(vcte->templateParameterCount(), instantiations.size());
+ for (qsizetype i = 0; i < size; ++i) {
+ auto ins = instantiations.at(i);
+ ins.setConstant(false);
+ viewInstantiations.append(ins);
+ }
+ result.setInstantiations(viewInstantiations);
+ return result;
+}
+
+void AbstractMetaBuilderPrivate::rejectFunction(const FunctionModelItem &functionItem,
+ const AbstractMetaClassPtr &currentClass,
+ AbstractMetaBuilder::RejectReason reason,
+ const QString &rejectReason)
+{
+ QString sortKey;
+ if (currentClass)
+ sortKey += currentClass->typeEntry()->qualifiedCppName() + u"::"_s;
+ sortKey += functionSignature(functionItem); // Sort without return type
+ const QString signatureWithType = functionItem->type().toString() + u' ' + sortKey;
+ m_rejectedFunctions.insert({reason, signatureWithType, sortKey, rejectReason});
+}
+
AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(const FunctionModelItem &functionItem,
- AbstractMetaClass *currentClass)
+ const AbstractMetaClassPtr &currentClass)
{
+ const auto *tdb = TypeDatabase::instance();
+
if (!functionItem->templateParameters().isEmpty())
return nullptr;
@@ -1840,34 +2003,40 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(const Functio
}
return nullptr;
}
- QString functionName = functionItem->name();
- QString className;
- if (currentClass) {
+ const QString &functionName = functionItem->name();
+ const QString className = currentClass != nullptr ?
+ currentClass->typeEntry()->qualifiedCppName() : QString{};
+
+ if (m_apiExtractorFlags.testFlag(ApiExtractorFlag::UsePySideExtensions)) {
+ // Skip enum helpers generated by Q_ENUM
+ if ((currentClass == nullptr || currentClass->isNamespace())
+ && (functionName == u"qt_getEnumMetaObject" || functionName == u"qt_getEnumName")) {
+ return nullptr;
+ }
+
// 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;
+ if (currentClass != nullptr) {
+ if (functionName == u"qt_check_for_QGADGET_macro"
+ || functionName.startsWith(u"qt_meta")) {
+ return nullptr;
+ }
+ if (functionName == u"metaObject" && className != u"QObject")
+ return nullptr;
}
- className = 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);
+ } // PySide extensions
QString rejectReason;
- if (TypeDatabase::instance()->isFunctionRejected(className, functionName, &rejectReason)) {
- m_rejectedFunctions.insert(originalQualifiedSignatureWithReturn + rejectReason, AbstractMetaBuilder::GenerationDisabled);
+ if (tdb->isFunctionRejected(className, functionName, &rejectReason)) {
+ rejectFunction(functionItem, currentClass,
+ AbstractMetaBuilder::GenerationDisabled, rejectReason);
return nullptr;
}
- const QString &signature = functionSignature(functionItem);
- const bool rejected =
- TypeDatabase::instance()->isFunctionRejected(className, signature, &rejectReason);
- if (rejected) {
+ const QString &signature = functionSignature(functionItem);
+ if (tdb->isFunctionRejected(className, signature, &rejectReason)) {
+ rejectFunction(functionItem, currentClass,
+ AbstractMetaBuilder::GenerationDisabled, rejectReason);
if (ReportHandler::isDebug(ReportHandler::MediumDebug)) {
qCInfo(lcShiboken, "%s::%s was rejected by the type database (%s).",
qPrintable(className), qPrintable(signature), qPrintable(rejectReason));
@@ -1878,47 +2047,30 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(const Functio
if (functionItem->isFriend())
return nullptr;
- const bool deprecated = functionItem->isDeprecated();
+ const auto cppAttributes = functionItem->attributes();
+ const bool deprecated = cppAttributes.testFlag(FunctionAttribute::Deprecated);
if (deprecated && m_skipDeprecated) {
- m_rejectedFunctions.insert(originalQualifiedSignatureWithReturn + QLatin1String(" is deprecated."),
- AbstractMetaBuilder::GenerationDisabled);
+ rejectFunction(functionItem, currentClass,
+ AbstractMetaBuilder::GenerationDisabled, u" is deprecated."_s);
return nullptr;
}
- auto *metaFunction = new AbstractMetaFunction;
+ AbstractMetaFunction::Flags flags;
+ auto *metaFunction = new AbstractMetaFunction(functionName);
+ metaFunction->setCppAttributes(cppAttributes);
+ const QByteArray cSignature = signature.toUtf8();
+ const QString unresolvedSignature =
+ QString::fromUtf8(QMetaObject::normalizedSignature(cSignature.constData()));
+ metaFunction->setUnresolvedSignature(unresolvedSignature);
+ if (functionItem->isHiddenFriend())
+ flags.setFlag(AbstractMetaFunction::Flag::HiddenFriend);
metaFunction->setSourceLocation(functionItem->sourceLocation());
- if (deprecated)
- *metaFunction += AbstractMetaFunction::Deprecated;
// Additional check for assignment/move assignment down below
metaFunction->setFunctionType(functionTypeFromCodeModel(functionItem->functionType()));
metaFunction->setConstant(functionItem->isConstant());
metaFunction->setExceptionSpecification(functionItem->exceptionSpecification());
- metaFunction->setName(functionName);
- metaFunction->setOriginalName(functionItem->name());
-
- if (functionItem->isAbstract())
- *metaFunction += AbstractMetaFunction::Abstract;
-
- if (functionItem->isVirtual()) {
- *metaFunction += AbstractMetaFunction::VirtualCppMethod;
- if (functionItem->isOverride())
- *metaFunction += AbstractMetaFunction::OverriddenCppMethod;
- if (functionItem->isFinal())
- *metaFunction += AbstractMetaFunction::FinalCppMethod;
- } else {
- *metaFunction += AbstractMetaFunction::FinalInTargetLang;
- }
-
- if (functionItem->isInvokable())
- *metaFunction += AbstractMetaFunction::Invokable;
-
- if (functionItem->isStatic()) {
- *metaFunction += AbstractMetaFunction::Static;
- *metaFunction += AbstractMetaFunction::FinalInTargetLang;
- }
-
// Access rights
metaFunction->setAccess(functionItem->accessPolicy());
@@ -1928,25 +2080,30 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(const Functio
metaFunction->setType(AbstractMetaType::createVoid());
break;
case AbstractMetaFunction::ConstructorFunction:
- metaFunction->setExplicit(functionItem->isExplicit());
metaFunction->setName(currentClass->name());
metaFunction->setType(AbstractMetaType::createVoid());
break;
default: {
TypeInfo returnType = functionItem->type();
- if (TypeDatabase::instance()->isReturnTypeRejected(className, returnType.toString(), &rejectReason)) {
- m_rejectedFunctions.insert(originalQualifiedSignatureWithReturn + rejectReason, AbstractMetaBuilder::GenerationDisabled);
+ if (tdb->isReturnTypeRejected(className, returnType.toString(), &rejectReason)) {
+ rejectFunction(functionItem, currentClass,
+ AbstractMetaBuilder::GenerationDisabled, rejectReason);
delete metaFunction;
return nullptr;
}
- auto type = translateType(returnType, currentClass, {}, &errorMessage);
+ TranslateTypeFlags flags;
+ if (functionItem->scopeResolution())
+ flags.setFlag(AbstractMetaBuilder::NoClassScopeLookup);
+ auto type = translateType(returnType, currentClass, flags, &errorMessage);
if (!type.has_value()) {
const QString reason = msgUnmatchedReturnType(functionItem, errorMessage);
+ const QString signature = qualifiedFunctionSignatureWithType(functionItem, className);
qCWarning(lcShiboken, "%s",
- qPrintable(msgSkippingFunction(functionItem, originalQualifiedSignatureWithReturn, reason)));
- m_rejectedFunctions.insert(originalQualifiedSignatureWithReturn, AbstractMetaBuilder::UnmatchedReturnType);
+ qPrintable(msgSkippingFunction(functionItem, signature, reason)));
+ rejectFunction(functionItem, currentClass,
+ AbstractMetaBuilder::UnmatchedReturnType, reason);
delete metaFunction;
return nullptr;
}
@@ -1957,41 +2114,56 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(const Functio
}
ArgumentList arguments = functionItem->arguments();
+ // Add private signals for documentation purposes
+ if (!arguments.isEmpty()
+ && m_apiExtractorFlags.testFlag(ApiExtractorFlag::UsePySideExtensions)
+ && functionItem->functionType() == CodeModel::Signal
+ && arguments.constLast()->type().qualifiedName().constLast() == u"QPrivateSignal") {
+ flags.setFlag(AbstractMetaFunction::Flag::PrivateSignal);
+ arguments.removeLast();
+ }
if (arguments.size() == 1) {
ArgumentModelItem arg = arguments.at(0);
TypeInfo type = arg->type();
- if (type.qualifiedName().constFirst() == QLatin1String("void") && type.indirections() == 0)
+ if (type.qualifiedName().constFirst() == u"void" && type.indirections() == 0)
arguments.pop_front();
}
- for (int i = 0; i < arguments.size(); ++i) {
+ for (qsizetype i = 0; i < arguments.size(); ++i) {
const ArgumentModelItem &arg = arguments.at(i);
- if (TypeDatabase::instance()->isArgumentTypeRejected(className, arg->type().toString(), &rejectReason)) {
- m_rejectedFunctions.insert(originalQualifiedSignatureWithReturn + rejectReason, AbstractMetaBuilder::GenerationDisabled);
+ if (tdb->isArgumentTypeRejected(className, arg->type().toString(), &rejectReason)) {
+ rejectFunction(functionItem, currentClass,
+ AbstractMetaBuilder::GenerationDisabled, rejectReason);
delete metaFunction;
return nullptr;
}
- auto metaTypeO = translateType(arg->type(), currentClass, {}, &errorMessage);
+ TranslateTypeFlags flags;
+ if (arg->scopeResolution())
+ flags.setFlag(AbstractMetaBuilder::NoClassScopeLookup);
+ auto metaTypeO = translateType(arg->type(), currentClass, flags, &errorMessage);
if (!metaTypeO.has_value()) {
// If an invalid argument has a default value, simply remove it
// unless the function is virtual (since the override in the
// wrapper can then not correctly be generated).
- if (arg->defaultValue() && !functionItem->isVirtual()) {
+ if (arg->defaultValue()
+ && !functionItem->attributes().testFlag(FunctionAttribute::Virtual)) {
if (!currentClass || currentClass->typeEntry()->generateCode()) {
+ const QString signature = qualifiedFunctionSignatureWithType(functionItem, className);
qCWarning(lcShiboken, "%s",
- qPrintable(msgStrippingArgument(functionItem, i, originalQualifiedSignatureWithReturn, arg)));
+ qPrintable(msgStrippingArgument(functionItem, i, signature,
+ arg, errorMessage)));
}
break;
}
const QString reason = msgUnmatchedParameterType(arg, i, errorMessage);
+ const QString signature = qualifiedFunctionSignatureWithType(functionItem, className);
qCWarning(lcShiboken, "%s",
- qPrintable(msgSkippingFunction(functionItem, originalQualifiedSignatureWithReturn, reason)));
- const QString rejectedFunctionSignature = originalQualifiedSignatureWithReturn
- + QLatin1String(": ") + reason;
- m_rejectedFunctions.insert(rejectedFunctionSignature, AbstractMetaBuilder::UnmatchedArgumentType);
+ qPrintable(msgSkippingFunction(functionItem, signature, reason)));
+ rejectFunction(functionItem, currentClass,
+ AbstractMetaBuilder::UnmatchedArgumentType, reason);
delete metaFunction;
return nullptr;
}
@@ -2002,10 +2174,8 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(const Functio
auto viewOnTypeEntry = metaType.typeEntry()->viewOn();
if (viewOnTypeEntry != nullptr && metaType.indirections() == 0
&& metaType.arrayElementType() == nullptr
- && !metaType.hasInstantiations()) {
- auto viewOn = metaType;
- viewOn.setTypeEntry(viewOnTypeEntry);
- metaType.setViewOn(viewOn);
+ && (!metaType.hasInstantiations() || metaType.isContainer())) {
+ metaType.setViewOn(createViewOnType(metaType, viewOnTypeEntry));
}
AbstractMetaArgument metaArgument;
@@ -2021,20 +2191,15 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(const Functio
? AbstractMetaFunction::findClassModifications(metaFunction, currentClass)
: AbstractMetaFunction::findGlobalModifications(metaFunction);
- for (const FunctionModification &mod : functionMods) {
- if (mod.exceptionHandling() != TypeSystem::ExceptionHandling::Unspecified)
- metaFunction->setExceptionHandlingModification(mod.exceptionHandling());
- else if (mod.allowThread() != TypeSystem::AllowThread::Unspecified)
- metaFunction->setAllowThreadModification(mod.allowThread());
- }
+ applyCachedFunctionModifications(metaFunction, functionMods);
// Find the correct default values
- for (int i = 0, size = metaArguments.size(); i < size; ++i) {
+ for (qsizetype i = 0, size = metaArguments.size(); i < size; ++i) {
const ArgumentModelItem &arg = arguments.at(i);
AbstractMetaArgument &metaArg = metaArguments[i];
const QString originalDefaultExpression =
- fixDefaultValue(arg, metaArg.type(), currentClass, i);
+ fixDefaultValue(arg->defaultValueExpression(), metaArg.type(), currentClass);
metaArg.setOriginalDefaultValueExpression(originalDefaultExpression);
metaArg.setDefaultValueExpression(originalDefaultExpression);
@@ -2067,7 +2232,7 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(const Functio
if (currentClass && metaFunction->arguments().size() == 1) {
const AbstractMetaType &argType = metaFunction->arguments().constFirst().type();
if (argType.typeEntry() == currentClass->typeEntry() && argType.indirections() == 0) {
- if (metaFunction->name() == QLatin1String("operator=")) {
+ if (metaFunction->name() == u"operator=") {
switch (argType.referenceType()) {
case NoReference:
metaFunction->setFunctionType(AbstractMetaFunction::AssignmentOperatorFunction);
@@ -2083,35 +2248,39 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(const Functio
}
}
}
+ metaFunction->setFlags(flags);
return metaFunction;
}
-static const TypeEntry* findTypeEntryUsingContext(const AbstractMetaClass* metaClass, const QString& qualifiedName)
+static TypeEntryCPtr findTypeEntryUsingContext(const AbstractMetaClassCPtr &metaClass,
+ const QString& qualifiedName)
{
- const TypeEntry* type = nullptr;
- QStringList context = metaClass->qualifiedCppName().split(colonColon());
+ TypeEntryCPtr type;
+ QStringList context = metaClass->qualifiedCppName().split(u"::"_s);
while (!type && !context.isEmpty()) {
- type = TypeDatabase::instance()->findType(context.join(colonColon()) + colonColon() + qualifiedName);
+ type = TypeDatabase::instance()->findType(context.join(u"::"_s) + u"::"_s + qualifiedName);
context.removeLast();
}
return type;
}
// Helper for findTypeEntries/translateTypeStatic()
-TypeEntries AbstractMetaBuilderPrivate::findTypeEntriesHelper(const QString &qualifiedName,
- const QString &name,
- const AbstractMetaClass *currentClass,
- AbstractMetaBuilderPrivate *d)
+TypeEntryCList AbstractMetaBuilderPrivate::findTypeEntriesHelper(const QString &qualifiedName,
+ const QString &name,
+ TranslateTypeFlags flags,
+ const AbstractMetaClassCPtr &currentClass,
+ AbstractMetaBuilderPrivate *d)
{
// 5.1 - Try first using the current scope
- if (currentClass) {
+ if (currentClass != nullptr
+ && !flags.testFlag(AbstractMetaBuilder::NoClassScopeLookup)) {
if (auto type = findTypeEntryUsingContext(currentClass, qualifiedName))
return {type};
// 5.1.1 - Try using the class parents' scopes
if (d && !currentClass->baseClassNames().isEmpty()) {
- const AbstractMetaClassList &baseClasses = d->getBaseClasses(currentClass);
- for (const AbstractMetaClass *cls : baseClasses) {
+ const auto &baseClasses = d->getBaseClasses(currentClass);
+ for (const auto &cls : baseClasses) {
if (auto type = findTypeEntryUsingContext(cls, qualifiedName))
return {type};
}
@@ -2135,7 +2304,7 @@ TypeEntries AbstractMetaBuilderPrivate::findTypeEntriesHelper(const QString &qua
// of the parameters.
if (currentClass) {
const auto &template_args = currentClass->templateArguments();
- for (const TypeEntry *te : template_args) {
+ for (const auto &te : template_args) {
if (te->name() == qualifiedName)
return {te};
}
@@ -2145,25 +2314,37 @@ TypeEntries AbstractMetaBuilderPrivate::findTypeEntriesHelper(const QString &qua
// Helper for translateTypeStatic() that calls findTypeEntriesHelper()
// and does some error checking.
-TypeEntries AbstractMetaBuilderPrivate::findTypeEntries(const QString &qualifiedName,
- const QString &name,
- const AbstractMetaClass *currentClass,
- AbstractMetaBuilderPrivate *d,
- QString *errorMessage)
-{
- const TypeEntries types = findTypeEntriesHelper(qualifiedName, name, currentClass, d);
+TypeEntryCList AbstractMetaBuilderPrivate::findTypeEntries(const QString &qualifiedName,
+ const QString &name,
+ TranslateTypeFlags flags,
+ const AbstractMetaClassCPtr &currentClass,
+ AbstractMetaBuilderPrivate *d,
+ QString *errorMessage)
+{
+ TypeEntryCList types = findTypeEntriesHelper(qualifiedName, name, flags,
+ currentClass, d);
if (types.isEmpty()) {
if (errorMessage != nullptr)
*errorMessage = msgCannotFindTypeEntry(qualifiedName);
return {};
}
+ // Resolve entries added by metabuilder (for example, "GLenum") to match
+ // the signatures for modifications.
+ for (qsizetype i = 0, size = types.size(); i < size; ++i) {
+ const auto &e = types.at(i);
+ if (e->isPrimitive()) {
+ const auto pte = std::static_pointer_cast<const PrimitiveTypeEntry>(e);
+ types[i] = basicReferencedNonBuiltinTypeEntry(pte);
+ }
+ }
+
if (types.size() == 1)
return types;
const auto typeEntryType = types.constFirst()->type();
const bool sameType = std::all_of(types.cbegin() + 1, types.cend(),
- [typeEntryType](const TypeEntry *e) {
+ [typeEntryType](const TypeEntryCPtr &e) {
return e->type() == typeEntryType;
});
@@ -2186,10 +2367,10 @@ TypeEntries AbstractMetaBuilderPrivate::findTypeEntries(const QString &qualified
// Reverse lookup of AbstractMetaType representing a template specialization
// found during traversing function arguments to its type system typedef'ed
// class.
-const AbstractMetaClass *AbstractMetaBuilderPrivate::resolveTypeSystemTypeDef(const AbstractMetaType &t) const
+AbstractMetaClassCPtr AbstractMetaBuilderPrivate::resolveTypeSystemTypeDef(const AbstractMetaType &t) const
{
if (t.hasInstantiations()) {
- auto pred = [t](const TypeClassEntry &e) { return e.type.equals(t); };
+ auto pred = [t](const TypeClassEntry &e) { return e.type == t; };
auto it = std::find_if(m_typeSystemTypeDefs.cbegin(), m_typeSystemTypeDefs.cend(), pred);
if (it != m_typeSystemTypeDefs.cend())
return it->klass;
@@ -2197,9 +2378,194 @@ const AbstractMetaClass *AbstractMetaBuilderPrivate::resolveTypeSystemTypeDef(co
return nullptr;
}
+// The below helpers and AbstractMetaBuilderPrivate::fixSmartPointers()
+// synthesize missing smart pointer functions and classes. For example for
+// std::shared_ptr, the full class declaration or base classes from
+// internal, compiler-dependent STL implementation headers might not be exposed
+// to the parser unless those headers are specified as <system-include>.
+
+static void synthesizeWarning(const AbstractMetaFunctionCPtr &f)
+{
+ qCWarning(lcShiboken, "Synthesizing \"%s\"...",
+ qPrintable(f->classQualifiedSignature()));
+}
+
+static AbstractMetaFunctionPtr
+ addMethod(const AbstractMetaClassPtr &s, const AbstractMetaType &returnType,
+ const QString &name, bool isConst = true)
+{
+ auto function = std::make_shared<AbstractMetaFunction>(name);
+ function->setType(returnType);
+ AbstractMetaClass::addFunction(s, function);
+ function->setConstant(isConst);
+ synthesizeWarning(function);
+ return function;
+}
+
+static AbstractMetaFunctionPtr
+ addMethod(const AbstractMetaClassPtr &s, const QString &returnTypeName,
+ const QString &name, bool isConst = true)
+{
+ auto typeEntry = TypeDatabase::instance()->findPrimitiveType(returnTypeName);
+ Q_ASSERT(typeEntry);
+ AbstractMetaType returnType(typeEntry);
+ returnType.decideUsagePattern();
+ return addMethod(s, returnType, name, isConst);
+}
+
+// Create the instantiation type of a smart pointer
+static AbstractMetaType instantiationType(const AbstractMetaClassCPtr &s,
+ const SmartPointerTypeEntryCPtr &ste)
+{
+ AbstractMetaType type(s->templateArguments().constFirst());
+ if (ste->smartPointerType() != TypeSystem::SmartPointerType::ValueHandle)
+ type.addIndirection();
+ type.decideUsagePattern();
+ return type;
+}
+
+// Create the pointee argument of a smart pointer constructor or reset()
+static AbstractMetaArgument pointeeArgument(const AbstractMetaClassCPtr &s,
+ const SmartPointerTypeEntryCPtr &ste)
+{
+ AbstractMetaArgument pointee;
+ pointee.setType(instantiationType(s, ste));
+ pointee.setName(u"pointee"_s);
+ return pointee;
+}
+
+// Add the smart pointer constructors. For MSVC, (when not specifying
+// <system-header>), clang only sees the default constructor.
+static void fixSmartPointerConstructors(const AbstractMetaClassPtr &s,
+ const SmartPointerTypeEntryCPtr &ste)
+{
+ const auto ctors = s->queryFunctions(FunctionQueryOption::Constructors);
+ bool seenDefaultConstructor = false;
+ bool seenParameter = false;
+ for (const auto &ctor : ctors) {
+ if (ctor->arguments().isEmpty())
+ seenDefaultConstructor = true;
+ else
+ seenParameter = true;
+ }
+
+ if (!seenParameter) {
+ auto constructor = std::make_shared<AbstractMetaFunction>(s->name());
+ constructor->setFunctionType(AbstractMetaFunction::ConstructorFunction);
+ constructor->addArgument(pointeeArgument(s, ste));
+ AbstractMetaClass::addFunction(s, constructor);
+ synthesizeWarning(constructor);
+ }
+
+ if (!seenDefaultConstructor) {
+ auto constructor = std::make_shared<AbstractMetaFunction>(s->name());
+ constructor->setFunctionType(AbstractMetaFunction::ConstructorFunction);
+ AbstractMetaClass::addFunction(s, constructor);
+ synthesizeWarning(constructor);
+ }
+}
+
+// Similarly, add the smart pointer reset() functions
+static void fixSmartPointerReset(const AbstractMetaClassPtr &s,
+ const SmartPointerTypeEntryCPtr &ste)
+{
+ const QString resetMethodName = ste->resetMethod();
+ const auto functions = s->findFunctions(resetMethodName);
+ bool seenParameterLess = false;
+ bool seenParameter = false;
+ for (const auto &function : functions) {
+ if (function->arguments().isEmpty())
+ seenParameterLess = true;
+ else
+ seenParameter = true;
+ }
+
+ if (!seenParameter) {
+ auto f = std::make_shared<AbstractMetaFunction>(resetMethodName);
+ f->addArgument(pointeeArgument(s, ste));
+ AbstractMetaClass::addFunction(s, f);
+ synthesizeWarning(f);
+ }
+
+ if (!seenParameterLess) {
+ auto f = std::make_shared<AbstractMetaFunction>(resetMethodName);
+ AbstractMetaClass::addFunction(s, f);
+ synthesizeWarning(f);
+ }
+}
+
+// Add the relevant missing smart pointer functions.
+static void fixSmartPointerClass(const AbstractMetaClassPtr &s,
+ const SmartPointerTypeEntryCPtr &ste)
+{
+ fixSmartPointerConstructors(s, ste);
+
+ if (!ste->resetMethod().isEmpty())
+ fixSmartPointerReset(s, ste);
+
+ const QString getterName = ste->getter();
+ if (!s->findFunction(getterName))
+ addMethod(s, instantiationType(s, ste), getterName);
+
+ const QString refCountName = ste->refCountMethodName();
+ if (!refCountName.isEmpty() && !s->findFunction(refCountName))
+ addMethod(s, u"int"_s, refCountName);
+
+ const QString valueCheckMethod = ste->valueCheckMethod();
+ if (!valueCheckMethod.isEmpty() && !s->findFunction(valueCheckMethod)) {
+ auto f = addMethod(s, u"bool"_s, valueCheckMethod);
+ if (valueCheckMethod == u"operator bool")
+ f->setFunctionType(AbstractMetaFunction::ConversionOperator);
+ }
+
+ const QString nullCheckMethod = ste->nullCheckMethod();
+ if (!nullCheckMethod.isEmpty() && !s->findFunction(nullCheckMethod))
+ addMethod(s, u"bool"_s, nullCheckMethod);
+}
+
+// Create a missing smart pointer class
+static AbstractMetaClassPtr createSmartPointerClass(const SmartPointerTypeEntryCPtr &ste,
+ const AbstractMetaClassList &allClasses)
+{
+ auto result = std::make_shared<AbstractMetaClass>();
+ result->setTypeEntry(std::const_pointer_cast<SmartPointerTypeEntry>(ste));
+ auto templateArg = std::make_shared<TemplateArgumentEntry>(u"T"_s, ste->version(),
+ typeSystemTypeEntry(ste));
+ result->setTemplateArguments({templateArg});
+ fixSmartPointerClass(result, ste);
+ auto enclosingTe = ste->parent();
+ if (!enclosingTe->isTypeSystem()) {
+ const auto enclosing = AbstractMetaClass::findClass(allClasses, enclosingTe);
+ if (!enclosing)
+ throw Exception(msgEnclosingClassNotFound(ste));
+ result->setEnclosingClass(enclosing);
+ auto inner = enclosing->innerClasses();
+ inner.append(std::const_pointer_cast<const AbstractMetaClass>(result));
+ enclosing->setInnerClasses(inner);
+ }
+ return result;
+}
+
+void AbstractMetaBuilderPrivate::fixSmartPointers()
+{
+ const auto smartPointerTypes = TypeDatabase::instance()->smartPointerTypes();
+ for (const auto &ste : smartPointerTypes) {
+ const auto smartPointerClass =
+ AbstractMetaClass::findClass(m_smartPointers, ste);
+ if (smartPointerClass) {
+ fixSmartPointerClass(std::const_pointer_cast<AbstractMetaClass>(smartPointerClass),
+ ste);
+ } else {
+ qCWarning(lcShiboken, "Synthesizing smart pointer \"%s\"...",
+ qPrintable(ste->qualifiedCppName()));
+ m_smartPointers.append(createSmartPointerClass(ste, m_metaClasses));
+ }
+ }
+}
+
std::optional<AbstractMetaType>
AbstractMetaBuilderPrivate::translateType(const TypeInfo &_typei,
- const AbstractMetaClass *currentClass,
+ const AbstractMetaClassCPtr &currentClass,
TranslateTypeFlags flags,
QString *errorMessage)
{
@@ -2212,9 +2578,16 @@ static bool isNumber(const QString &s)
[](QChar c) { return c.isDigit(); });
}
+// A type entry relevant only for non type template "X<5>"
+static bool isNonTypeTemplateArgument(const TypeEntryCPtr &te)
+{
+ const auto type = te->type();
+ return type == TypeEntry::EnumValue || type == TypeEntry::ConstantValueType;
+}
+
std::optional<AbstractMetaType>
AbstractMetaBuilderPrivate::translateTypeStatic(const TypeInfo &_typei,
- const AbstractMetaClass *currentClass,
+ const AbstractMetaClassCPtr &currentClass,
AbstractMetaBuilderPrivate *d,
TranslateTypeFlags flags,
QString *errorMessageIn)
@@ -2241,10 +2614,10 @@ std::optional<AbstractMetaType>
// the global scope when they are referenced from inside a namespace.
// This is a work around to fix this bug since fixing it in resolveType
// seemed non-trivial
- int i = d ? d->m_scopes.size() - 1 : -1;
+ qsizetype i = d ? d->m_scopes.size() - 1 : -1;
while (i >= 0) {
typeInfo = TypeInfo::resolveType(_typei, d->m_scopes.at(i--));
- if (typeInfo.qualifiedName().join(colonColon()) != _typei.qualifiedName().join(colonColon()))
+ if (typeInfo.qualifiedName().join(u"::"_s) != _typei.qualifiedName().join(u"::"_s))
break;
}
@@ -2252,7 +2625,7 @@ std::optional<AbstractMetaType>
if (typeInfo.isFunctionPointer()) {
if (errorMessageIn)
- *errorMessageIn = msgUnableToTranslateType(_typei, QLatin1String("Unsupported function pointer."));
+ *errorMessageIn = msgUnableToTranslateType(_typei, u"Unsupported function pointer."_s);
return {};
}
@@ -2268,7 +2641,7 @@ std::optional<AbstractMetaType>
bool isConstCharStarCase =
oneDimensionalArrayOfUnspecifiedSize
&& typeInfo.qualifiedName().size() == 1
- && typeInfo.qualifiedName().at(0) == QStringLiteral("char")
+ && typeInfo.qualifiedName().at(0) == "char"_L1
&& typeInfo.indirections() == 0
&& typeInfo.isConstant()
&& typeInfo.referenceType() == NoReference
@@ -2292,13 +2665,13 @@ std::optional<AbstractMetaType>
auto elementType = translateTypeStatic(newInfo, currentClass, d, flags, &errorMessage);
if (!elementType.has_value()) {
if (errorMessageIn) {
- errorMessage.prepend(QLatin1String("Unable to translate array element: "));
+ errorMessage.prepend(u"Unable to translate array element: "_s);
*errorMessageIn = msgUnableToTranslateType(_typei, errorMessage);
}
return {};
}
- for (int i = typeInfo.arrayElements().size() - 1; i >= 0; --i) {
+ for (auto i = typeInfo.arrayElements().size() - 1; i >= 0; --i) {
AbstractMetaType arrayType;
arrayType.setArrayElementType(elementType.value());
const QString &arrayElement = typeInfo.arrayElements().at(i);
@@ -2311,8 +2684,9 @@ std::optional<AbstractMetaType>
arrayType.setArrayElementCount(int(elems));
}
auto elementTypeEntry = elementType->typeEntry();
- arrayType.setTypeEntry(new ArrayTypeEntry(elementTypeEntry, elementTypeEntry->version(),
- elementTypeEntry->parent()));
+ auto at = std::make_shared<ArrayTypeEntry>(elementTypeEntry, elementTypeEntry->version(),
+ elementTypeEntry->parent());
+ arrayType.setTypeEntry(at);
arrayType.decideUsagePattern();
elementType = arrayType;
@@ -2323,7 +2697,7 @@ std::optional<AbstractMetaType>
QStringList qualifierList = typeInfo.qualifiedName();
if (qualifierList.isEmpty()) {
- errorMessage = msgUnableToTranslateType(_typei, QLatin1String("horribly broken type"));
+ errorMessage = msgUnableToTranslateType(_typei, u"horribly broken type"_s);
if (errorMessageIn)
*errorMessageIn = errorMessage;
else
@@ -2331,23 +2705,32 @@ std::optional<AbstractMetaType>
return {};
}
- QString qualifiedName = qualifierList.join(colonColon());
+ QString qualifiedName = qualifierList.join(u"::"_s);
QString name = qualifierList.takeLast();
// 4. Special case QFlags (include instantiation in name)
- if (qualifiedName == QLatin1String("QFlags")) {
+ if (qualifiedName == u"QFlags") {
qualifiedName = typeInfo.toString();
typeInfo.clearInstantiations();
}
- const TypeEntries types = findTypeEntries(qualifiedName, name, currentClass, d, errorMessageIn);
+ TypeEntryCList types = findTypeEntries(qualifiedName, name, flags,
+ currentClass, d, errorMessageIn);
+ if (!flags.testFlag(AbstractMetaBuilder::TemplateArgument)) {
+ // Avoid clashes between QByteArray and enum value QMetaType::QByteArray
+ // unless we are looking for template arguments.
+ auto end = std::remove_if(types.begin(), types.end(),
+ isNonTypeTemplateArgument);
+ types.erase(end, types.end());
+ }
+
if (types.isEmpty()) {
if (errorMessageIn != nullptr)
*errorMessageIn = msgUnableToTranslateType(_typei, *errorMessageIn);
return {};
}
- const TypeEntry *type = types.constFirst();
+ TypeEntryCPtr type = types.constFirst();
const TypeEntry::Type typeEntryType = type->type();
AbstractMetaType metaType;
@@ -2358,15 +2741,18 @@ std::optional<AbstractMetaType>
metaType.setOriginalTypeDescription(_typei.toString());
const auto &templateArguments = typeInfo.instantiations();
- for (int t = 0, size = templateArguments.size(); t < size; ++t) {
+ for (qsizetype t = 0, size = templateArguments.size(); t < size; ++t) {
const TypeInfo &ti = templateArguments.at(t);
- auto targType = translateTypeStatic(ti, currentClass, d, flags, &errorMessage);
+ auto targType = translateTypeStatic(ti, currentClass, d,
+ flags | AbstractMetaBuilder::TemplateArgument,
+ &errorMessage);
// For non-type template parameters, create a dummy type entry on the fly
// as is done for classes.
if (!targType.has_value()) {
- const QString value = ti.qualifiedName().join(colonColon());
+ const QString value = ti.qualifiedName().join(u"::"_s);
if (isNumber(value)) {
- TypeDatabase::instance()->addConstantValueTypeEntry(value, type->typeSystemTypeEntry());
+ auto module = typeSystemTypeEntry(type);
+ TypeDatabase::instance()->addConstantValueTypeEntry(value, module);
targType = translateTypeStatic(ti, currentClass, d, flags, &errorMessage);
}
}
@@ -2392,8 +2778,8 @@ std::optional<AbstractMetaType>
type = instantiationType;
} else {
auto it = std::find_if(types.cbegin(), types.cend(),
- [instantiationType](const TypeEntry *e) {
- auto smartPtr = static_cast<const SmartPointerTypeEntry *>(e);
+ [instantiationType](const TypeEntryCPtr &e) {
+ auto smartPtr = std::static_pointer_cast<const SmartPointerTypeEntry>(e);
return smartPtr->matchesInstantiation(instantiationType);
});
if (it == types.cend()) {
@@ -2427,7 +2813,7 @@ std::optional<AbstractMetaType>
std::optional<AbstractMetaType>
AbstractMetaBuilder::translateType(const TypeInfo &_typei,
- AbstractMetaClass *currentClass,
+ const AbstractMetaClassPtr &currentClass,
TranslateTypeFlags flags,
QString *errorMessage)
{
@@ -2438,7 +2824,7 @@ std::optional<AbstractMetaType>
std::optional<AbstractMetaType>
AbstractMetaBuilder::translateType(const QString &t,
- AbstractMetaClass *currentClass,
+ const AbstractMetaClassPtr &currentClass,
TranslateTypeFlags flags,
QString *errorMessageIn)
{
@@ -2461,14 +2847,14 @@ qint64 AbstractMetaBuilderPrivate::findOutValueFromString(const QString &stringV
if (ok)
return value;
- if (stringValue == QLatin1String("true") || stringValue == QLatin1String("false")) {
+ if (stringValue == u"true" || stringValue == u"false") {
ok = true;
- return (stringValue == QLatin1String("true"));
+ return (stringValue == u"true");
}
// This is a very lame way to handle expression evaluation,
// but it is not critical and will do for the time being.
- static const QRegularExpression variableNameRegExp(QStringLiteral("^[a-zA-Z_][a-zA-Z0-9_]*$"));
+ static const QRegularExpression variableNameRegExp("^[a-zA-Z_][a-zA-Z0-9_]*$"_L1);
Q_ASSERT(variableNameRegExp.isValid());
if (!variableNameRegExp.match(stringValue).hasMatch()) {
ok = true;
@@ -2481,7 +2867,7 @@ qint64 AbstractMetaBuilderPrivate::findOutValueFromString(const QString &stringV
return enumValue->value().value();
}
- for (const AbstractMetaEnum &metaEnum : qAsConst(m_globalEnums)) {
+ for (const AbstractMetaEnum &metaEnum : std::as_const(m_globalEnums)) {
auto ev = metaEnum.findEnumValue(stringValue);
if (ev.has_value()) {
ok = true;
@@ -2493,115 +2879,163 @@ qint64 AbstractMetaBuilderPrivate::findOutValueFromString(const QString &stringV
return 0;
}
-QString AbstractMetaBuilderPrivate::fixDefaultValue(const ArgumentModelItem &item,
- const AbstractMetaType &type,
- const AbstractMetaClass *implementingClass,
- int /* argumentIndex */)
+// Return whether candidate is some underqualified specification of qualifiedType
+// ("B::C" should be qualified to "A::B::C")
+static bool isUnderQualifiedSpec(QStringView qualifiedType, QStringView candidate)
{
- QString expr = item->defaultValueExpression();
- if (expr.isEmpty() || expr == u"{}")
- return expr;
+ const auto candidateSize = candidate.size();
+ const auto qualifiedTypeSize = qualifiedType.size();
+ return candidateSize < qualifiedTypeSize
+ && qualifiedType.endsWith(candidate)
+ && qualifiedType.at(qualifiedTypeSize - candidateSize - 1) == u':';
+}
+
+QString AbstractMetaBuilder::fixEnumDefault(const AbstractMetaType &type,
+ const QString &expr,
+ const AbstractMetaClassCPtr &klass) const
+{
+ return d->fixEnumDefault(type, expr, klass);
+}
+
+void AbstractMetaBuilder::setCodeModelTestMode(bool b)
+{
+ AbstractMetaBuilderPrivate::m_codeModelTestMode = b;
+}
+
+// Helper to fix a simple default value (field or enum reference) in a
+// class context.
+QString AbstractMetaBuilderPrivate::fixSimpleDefaultValue(QStringView expr,
+ const AbstractMetaClassCPtr &klass) const
+{
+ const QString field = qualifyStaticField(klass, expr);
+
+ if (!field.isEmpty())
+ return field;
+ const auto cit = m_classToItem.constFind(klass);
+ if (cit == m_classToItem.cend())
+ return {};
+ auto *scope = dynamic_cast<const _ScopeModelItem *>(cit.value());
+ if (!scope)
+ return {};
+ if (auto enumValue = scope->findEnumByValue(expr))
+ return enumValue.qualifiedName;
+ return {};
+}
+// see TestResolveType::testFixDefaultArguments()
+QString AbstractMetaBuilderPrivate::fixDefaultValue(QString expr, const AbstractMetaType &type,
+ const AbstractMetaClassCPtr &implementingClass) const
+{
expr.replace(u'\n', u' '); // breaks signature parser
- if (type.isPrimitive()) {
- if (type.name() == QLatin1String("boolean")) {
- if (expr != QLatin1String("false") && expr != QLatin1String("true")) {
- bool ok = false;
- int number = expr.toInt(&ok);
- if (ok && number)
- expr = QLatin1String("true");
- else
- expr = QLatin1String("false");
- }
- } else {
- // This can be an enum or flag so I need to delay the
- // translation until all namespaces are completely
- // processed. This is done in figureOutEnumValues()
- }
- } else if (type.isFlags() || type.isEnum()) {
- bool isNumber;
- expr.toInt(&isNumber);
- 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
- 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('<'))) {
- 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);
+ if (AbstractMetaBuilder::dontFixDefaultValue(expr))
+ return expr;
+
+ if (type.isFlags() || type.isEnum()) {
+ expr = fixEnumDefault(type, expr, implementingClass);
+ } else if (type.isContainer() && expr.contains(u'<')) {
+ // Expand a container of a nested class, fex
+ // "QList<FormatRange>()" -> "QList<QTextLayout::FormatRange>()"
+ if (type.instantiations().size() != 1)
+ return expr; // Only simple types are handled, not QMap<int, int>.
+ auto innerTypeEntry = type.instantiations().constFirst().typeEntry();
+ if (!innerTypeEntry->isComplex())
+ return expr;
+ const QString &qualifiedInnerTypeName = innerTypeEntry->qualifiedCppName();
+ if (!qualifiedInnerTypeName.contains(u"::")) // Nothing to qualify here
+ return expr;
+ const auto openPos = expr.indexOf(u'<');
+ const auto closingPos = expr.lastIndexOf(u'>');
+ if (openPos == -1 || closingPos == -1)
+ return expr;
+ const auto innerPos = openPos + 1;
+ const auto innerLen = closingPos - innerPos;
+ const auto innerType = QStringView{expr}.mid(innerPos, innerLen).trimmed();
+ if (isUnderQualifiedSpec(qualifiedInnerTypeName, innerType))
+ expr.replace(innerPos, innerLen, qualifiedInnerTypeName);
} else {
- // Here the default value is supposed to be a constructor,
- // a class field, or a constructor receiving a class field
- 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);
-
- // Fix the scope for constructor using the already resolved argument
- // type as a reference. The following regular expression extracts any
- // use of namespaces/scopes from the type string.
- static const QRegularExpression
- typeRegEx(QLatin1String(R"(^(?:const[\s]+|)([\w:]*::|)([A-Za-z_]\w*)\s*[&\*]?$)"));
- Q_ASSERT(typeRegEx.isValid());
- const QRegularExpressionMatch typeMatch = typeRegEx.match(type.minimalSignature());
-
- 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) {
- 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;
- }
+ // Here the default value is supposed to be a constructor, a class field,
+ // a constructor receiving a static class field or an enum. Consider
+ // class QSqlDatabase { ...
+ // static const char *defaultConnection;
+ // QSqlDatabase(const QString &connection = QLatin1String(defaultConnection))
+ // -> = QLatin1String(QSqlDatabase::defaultConnection)
+ // static void foo(QSqlDatabase db = QSqlDatabase(defaultConnection));
+ // -> = QSqlDatabase(QSqlDatabase::defaultConnection)
+ //
+ // Enum values from the class as defaults of int and others types (via
+ // implicit conversion) are handled here as well:
+ // class QStyleOption { ...
+ // enum StyleOptionType { Type = SO_Default };
+ // QStyleOption(..., int type = SO_Default);
+ // -> = QStyleOption::StyleOptionType::SO_Default
+
+ // Is this a single field or an enum?
+ if (isQualifiedCppIdentifier(expr)) {
+ const QString fixed = fixSimpleDefaultValue(expr, implementingClass);
+ return fixed.isEmpty() ? expr : fixed;
+ }
+
+ // Is this sth like "QLatin1String(field)", "Class(Field)", "Class()"?
+ const auto parenPos = expr.indexOf(u'(');
+ if (parenPos == -1 || !expr.endsWith(u')'))
+ return expr;
+ // Is the term within parentheses a class field or enum?
+ const auto innerLength = expr.size() - parenPos - 2;
+ if (innerLength > 0) { // Not some function call "defaultFunc()"
+ const auto inner = QStringView{expr}.mid(parenPos + 1, innerLength);
+ if (isQualifiedCppIdentifier(inner)
+ && !AbstractMetaBuilder::dontFixDefaultValue(inner)) {
+ const QString replacement = fixSimpleDefaultValue(inner, implementingClass);
+ if (!replacement.isEmpty() && replacement != inner)
+ expr.replace(parenPos + 1, innerLength, replacement);
}
}
+ // Is this a class constructor "Class(Field)"? Expand it.
+ const auto te = type.typeEntry();
+ if (!te->isComplex())
+ return expr;
+ const QString &qualifiedTypeName = te->qualifiedCppName();
+ if (!qualifiedTypeName.contains(u"::")) // Nothing to qualify here
+ return expr;
+ const auto className = QStringView{expr}.left(parenPos);
+ if (isUnderQualifiedSpec(qualifiedTypeName, className))
+ expr.replace(0, className.size(), qualifiedTypeName);
}
return expr;
}
+QString AbstractMetaBuilder::fixDefaultValue(const QString &expr, const AbstractMetaType &type,
+ const AbstractMetaClassCPtr &c) const
+{
+ return d->fixDefaultValue(expr, type, c);
+}
+
bool AbstractMetaBuilderPrivate::isEnum(const FileModelItem &dom, const QStringList& qualified_name)
{
CodeModelItem item = dom->model()->findItem(qualified_name, dom);
return item && item->kind() == _EnumModelItem::__node_kind;
}
-AbstractMetaClass* AbstractMetaBuilderPrivate::findTemplateClass(const QString &name,
- const AbstractMetaClass *context,
- TypeInfo *info,
- ComplexTypeEntry **baseContainerType) const
+AbstractMetaClassPtr
+ AbstractMetaBuilderPrivate::findTemplateClass(const QString &name,
+ const AbstractMetaClassCPtr &context,
+ TypeInfo *info,
+ ComplexTypeEntryPtr *baseContainerType) const
{
if (baseContainerType)
- *baseContainerType = nullptr;
- TypeDatabase* types = TypeDatabase::instance();
+ baseContainerType->reset();
+ auto *types = TypeDatabase::instance();
- QStringList scope = context->typeEntry()->qualifiedCppName().split(colonColon());
+ QStringList scope = context->typeEntry()->qualifiedCppName().split(u"::"_s);
QString errorMessage;
scope.removeLast();
- for (int i = scope.size(); i >= 0; --i) {
- QString prefix = i > 0 ? QStringList(scope.mid(0, i)).join(colonColon()) + colonColon() : QString();
+ for (auto i = scope.size(); i >= 0; --i) {
+ QString prefix = i > 0 ? QStringList(scope.mid(0, i)).join(u"::"_s) + u"::"_s : QString();
QString completeName = prefix + name;
const TypeInfo parsed = TypeParser::parse(completeName, &errorMessage);
- QString qualifiedName = parsed.qualifiedName().join(colonColon());
+ QString qualifiedName = parsed.qualifiedName().join(u"::"_s);
if (qualifiedName.isEmpty()) {
qWarning().noquote().nospace() << "Unable to parse type \"" << completeName
<< "\" while looking for template \"" << name << "\": " << errorMessage;
@@ -2610,8 +3044,8 @@ AbstractMetaClass* AbstractMetaBuilderPrivate::findTemplateClass(const QString &
if (info)
*info = parsed;
- AbstractMetaClass *templ = nullptr;
- for (AbstractMetaClass *c : qAsConst(m_templates)) {
+ AbstractMetaClassPtr templ;
+ for (const auto &c : std::as_const(m_templates)) {
if (c->typeEntry()->name() == qualifiedName) {
templ = c;
break;
@@ -2631,19 +3065,18 @@ AbstractMetaClass* AbstractMetaBuilderPrivate::findTemplateClass(const QString &
return nullptr;
}
-AbstractMetaClassList AbstractMetaBuilderPrivate::getBaseClasses(const AbstractMetaClass *metaClass) const
+AbstractMetaClassCList
+ AbstractMetaBuilderPrivate::getBaseClasses(const AbstractMetaClassCPtr &metaClass) const
{
// Shortcut if inheritance has already been set up
if (metaClass->inheritanceDone() || !metaClass->needsInheritanceSetup())
return metaClass->baseClasses();
- AbstractMetaClassList baseClasses;
+ AbstractMetaClassCList baseClasses;
const QStringList &baseClassNames = metaClass->baseClassNames();
for (const QString& parent : baseClassNames) {
- AbstractMetaClass *cls = nullptr;
- if (parent.contains(QLatin1Char('<')))
- cls = findTemplateClass(parent, metaClass);
- else
- cls = AbstractMetaClass::findClass(m_metaClasses, parent);
+ const auto cls = parent.contains(u'<')
+ ? findTemplateClass(parent, metaClass)
+ : AbstractMetaClass::findClass(m_metaClasses, parent);
if (cls)
baseClasses << cls;
@@ -2663,7 +3096,7 @@ std::optional<AbstractMetaType>
returned.setOriginalTemplateType(metaType);
if (returned.typeEntry()->isTemplateArgument()) {
- const auto *tae = static_cast<const TemplateArgumentEntry*>(returned.typeEntry());
+ const auto tae = std::static_pointer_cast<const TemplateArgumentEntry>(returned.typeEntry());
// If the template is intantiated with void we special case this as rejecting the functions that use this
// parameter from the instantiation.
@@ -2681,7 +3114,7 @@ std::optional<AbstractMetaType>
if (returned.hasInstantiations()) {
AbstractMetaTypeList instantiations = returned.instantiations();
- for (int i = 0; i < instantiations.count(); ++i) {
+ for (qsizetype i = 0; i < instantiations.size(); ++i) {
auto ins = inheritTemplateType(templateTypes, instantiations.at(i));
if (!ins.has_value())
return {};
@@ -2693,84 +3126,240 @@ std::optional<AbstractMetaType>
return returned;
}
-bool AbstractMetaBuilderPrivate::inheritTemplate(AbstractMetaClass *subclass,
- const AbstractMetaClass *templateClass,
+AbstractMetaClassPtr
+ AbstractMetaBuilder::inheritTemplateClass(const ComplexTypeEntryPtr &te,
+ const AbstractMetaClassCPtr &templateClass,
+ const AbstractMetaTypeList &templateTypes,
+ InheritTemplateFlags flags)
+{
+ auto result = std::make_shared<AbstractMetaClass>();
+ result->setTypeDef(true);
+
+ result->setTypeEntry(te);
+ if (!AbstractMetaBuilderPrivate::inheritTemplate(result, templateClass,
+ templateTypes, flags)) {
+ return {};
+ }
+ AbstractMetaBuilderPrivate::inheritTemplateFunctions(result);
+ return result;
+}
+
+
+static std::optional<AbstractMetaType>
+ inheritTemplateParameter(const AbstractMetaClassPtr &subclass,
+ const AbstractMetaClassCPtr &templateClass,
+ const TypeInfo &info, QString *errorMessage)
+{
+ QString typeName = info.qualifiedName().join("::"_L1);
+ TypeDatabase *typeDb = TypeDatabase::instance();
+ TypeEntryPtr t;
+ // Check for a non-type template integer parameter, that is, for a base
+ // "template <int R, int C> Matrix<R, C>" and subclass
+ // "typedef Matrix<2,3> Matrix2x3;". If so, create dummy entries of
+ // EnumValueTypeEntry for the integer values encountered on the fly.
+ if (isNumber(typeName)) {
+ t = typeDb->findType(typeName);
+ if (!t) {
+ auto parent = typeSystemTypeEntry(subclass->typeEntry());
+ t = TypeDatabase::instance()->addConstantValueTypeEntry(typeName, parent);
+ }
+ } else {
+ QStringList possibleNames;
+ possibleNames << subclass->qualifiedCppName() + "::"_L1 + typeName;
+ possibleNames << templateClass->qualifiedCppName() + "::"_L1 + typeName;
+ if (subclass->enclosingClass())
+ possibleNames << subclass->enclosingClass()->qualifiedCppName() + "::"_L1 + typeName;
+ possibleNames << typeName;
+
+ for (const QString &possibleName : std::as_const(possibleNames)) {
+ t = typeDb->findType(possibleName);
+ if (t)
+ break;
+ }
+ }
+
+ if (!t) {
+ *errorMessage = msgIgnoringTemplateParameter(typeName,
+ "The corresponding type was not found in the typesystem.");
+ return std::nullopt;
+ }
+
+ if (t->isContainer()) {
+ *errorMessage = msgIgnoringTemplateParameter(typeName,
+ "Template inheritance from nested containers is not supported");
+ return std::nullopt;
+ }
+ AbstractMetaType result(t);
+ result.setConstant(info.isConstant());
+ result.setReferenceType(info.referenceType());
+ result.setIndirectionsV(info.indirectionsV());
+ result.decideUsagePattern();
+ return result;
+}
+
+bool AbstractMetaBuilderPrivate::inheritTemplate(const AbstractMetaClassPtr &subclass,
+ const AbstractMetaClassCPtr &templateClass,
const TypeInfo &info)
{
AbstractMetaTypeList templateTypes;
+ QString errorMessage;
for (const TypeInfo &i : info.instantiations()) {
- QString typeName = i.qualifiedName().join(colonColon());
- TypeDatabase *typeDb = TypeDatabase::instance();
- TypeEntry *t = nullptr;
- // Check for a non-type template integer parameter, that is, for a base
- // "template <int R, int C> Matrix<R, C>" and subclass
- // "typedef Matrix<2,3> Matrix2x3;". If so, create dummy entries of
- // EnumValueTypeEntry for the integer values encountered on the fly.
- if (isNumber(typeName)) {
- t = typeDb->findType(typeName);
- if (!t) {
- auto parent = subclass->typeEntry()->typeSystemTypeEntry();
- t = TypeDatabase::instance()->addConstantValueTypeEntry(typeName, parent);
- }
+ const auto typeO = inheritTemplateParameter(subclass, templateClass, i, &errorMessage);
+ if (typeO.has_value()) {
+ templateTypes.append(typeO.value());
} else {
- QStringList possibleNames;
- possibleNames << subclass->qualifiedCppName() + colonColon() + typeName;
- possibleNames << templateClass->qualifiedCppName() + colonColon() + typeName;
- if (subclass->enclosingClass())
- possibleNames << subclass->enclosingClass()->qualifiedCppName() + colonColon() + typeName;
- possibleNames << typeName;
-
- for (const QString &possibleName : qAsConst(possibleNames)) {
- t = typeDb->findType(possibleName);
- if (t)
- break;
- }
- }
-
- if (t) {
- AbstractMetaType temporaryType(t);
- temporaryType.setConstant(i.isConstant());
- temporaryType.setReferenceType(i.referenceType());
- temporaryType.setIndirectionsV(i.indirectionsV());
- temporaryType.decideUsagePattern();
- templateTypes << temporaryType;
- } else {
- qCWarning(lcShiboken).noquote().nospace()
- << "Ignoring template parameter " << typeName << " from "
- << info.toString() << ". The corresponding type was not found in the typesystem.";
+ errorMessage = msgInheritTemplateIssue(subclass, info, errorMessage);
+ qCWarning(lcShiboken, "%s", qPrintable(errorMessage));
}
}
+ if (templateTypes.isEmpty()) {
+ errorMessage = msgInheritTemplateIssue(subclass, info,
+ "No template parameters could be inherited"_L1);
+ qCWarning(lcShiboken, "%s", qPrintable(errorMessage));
+ return false;
+ }
+ return inheritTemplate(subclass, templateClass, templateTypes);
+}
+bool AbstractMetaBuilderPrivate::inheritTemplate(const AbstractMetaClassPtr &subclass,
+ const AbstractMetaClassCPtr &templateClass,
+ const AbstractMetaTypeList &templateTypes,
+ InheritTemplateFlags flags)
+{
subclass->setTemplateBaseClass(templateClass);
+ if (flags.testFlag(InheritTemplateFlag::SetEnclosingClass))
+ subclass->setEnclosingClass(templateClass->enclosingClass());
subclass->setTemplateBaseClassInstantiations(templateTypes);
subclass->setBaseClass(templateClass->baseClass());
return true;
}
-static bool inheritTemplateFunction(const AbstractMetaFunctionCPtr &function,
- const AbstractMetaFunctionCList &existingSubclassFuncs,
- const AbstractMetaClass *subclass,
- const AbstractMetaClass *templateBaseClass)
+AbstractMetaFunctionPtr
+ AbstractMetaBuilderPrivate::inheritTemplateFunction(const AbstractMetaFunctionCPtr &function,
+ const AbstractMetaTypeList &templateTypes)
+{
+ AbstractMetaFunctionPtr f(function->copy());
+ f->setArguments(AbstractMetaArgumentList());
+ f->setFlags(f->flags() | AbstractMetaFunction::Flag::InheritedFromTemplate);
+
+ if (!function->isVoid()) {
+ auto returnType = inheritTemplateType(templateTypes, function->type());
+ if (!returnType.has_value())
+ return {};
+ f->setType(returnType.value());
+ }
+
+ const AbstractMetaArgumentList &arguments = function->arguments();
+ for (const AbstractMetaArgument &argument : arguments) {
+ auto argType = inheritTemplateType(templateTypes, argument.type());
+ if (!argType.has_value())
+ return {};
+ AbstractMetaArgument arg = argument;
+ arg.setType(argType.value());
+ f->addArgument(arg);
+ }
+
+ return f;
+}
+
+AbstractMetaFunctionPtr
+ AbstractMetaBuilder::inheritTemplateFunction(const AbstractMetaFunctionCPtr &function,
+ const AbstractMetaTypeList &templateTypes)
+{
+ return AbstractMetaBuilderPrivate::inheritTemplateFunction(function, templateTypes);
+}
+
+AbstractMetaFunctionPtr
+ AbstractMetaBuilderPrivate::inheritTemplateMember(const AbstractMetaFunctionCPtr &function,
+ const AbstractMetaTypeList &templateTypes,
+ const AbstractMetaClassCPtr &templateClass,
+ const AbstractMetaClassPtr &subclass)
+{
+ AbstractMetaFunctionPtr f = inheritTemplateFunction(function, templateTypes);
+ if (!f)
+ return {};
+
+ // There is no base class in the target language to inherit from here, so
+ // the template instantiation is the class that implements the function.
+ f->setImplementingClass(subclass);
+
+ // We also set it as the declaring class, since the superclass is
+ // supposed to disappear. This allows us to make certain function modifications
+ // on the inherited functions.
+ f->setDeclaringClass(subclass);
+
+ if (f->isConstructor()) {
+ f->setName(subclass->name());
+ f->setOriginalName(subclass->name());
+ }
+
+ ComplexTypeEntryPtr te = subclass->typeEntry();
+ const FunctionModificationList mods = function->modifications(templateClass);
+
+ for (auto mod : mods) {
+ mod.setSignature(f->minimalSignature());
+
+// If we ever need it... Below is the code to do
+// substitution of the template instantation type inside
+// injected code..
+#if 0
+ if (mod.modifiers & Modification::CodeInjection) {
+ for (int j = 0; j < template_types.size(); ++j) {
+ CodeSnip &snip = mod.snips.last();
+ QString code = snip.code();
+ code.replace(QString::fromLatin1("$$QT_TEMPLATE_%1$$").arg(j),
+ template_types.at(j)->typeEntry()->qualifiedCppName());
+ snip.codeList.clear();
+ snip.addCode(code);
+ }
+ }
+#endif
+ te->addFunctionModification(mod);
+ }
+
+ QString errorMessage;
+ if (!applyArrayArgumentModifications(f->modifications(subclass), f.get(),
+ &errorMessage)) {
+ qCWarning(lcShiboken, "While specializing %s (%s): %s",
+ qPrintable(subclass->name()), qPrintable(templateClass->name()),
+ qPrintable(errorMessage));
+ }
+ return f;
+}
+
+AbstractMetaFunctionPtr
+ AbstractMetaBuilder::inheritTemplateMember(const AbstractMetaFunctionCPtr &function,
+ const AbstractMetaTypeList &templateTypes,
+ const AbstractMetaClassCPtr &templateClass,
+ const AbstractMetaClassPtr &subclass)
+{
+ return AbstractMetaBuilderPrivate::inheritTemplateMember(function, templateTypes,
+ templateClass, subclass);
+}
+
+static bool doInheritTemplateFunction(const AbstractMetaFunctionCPtr &function,
+ const AbstractMetaFunctionCList &existingSubclassFuncs,
+ const AbstractMetaClassCPtr &templateBaseClass,
+ const AbstractMetaClassCPtr &subclass)
{
// If the function is modified or the instantiation has an equally named
// function we are shadowing, so we need to skip it (unless the subclass
// declares it via "using").
if (function->isModifiedRemoved())
return false;
+ if (function->isConstructor() && !subclass->isTypeDef())
+ return false;
return AbstractMetaFunction::find(existingSubclassFuncs, function->name()) == nullptr
|| subclass->isUsingMember(templateBaseClass, function->name(), Access::Protected);
}
-void AbstractMetaBuilderPrivate::inheritTemplateFunctions(AbstractMetaClass *subclass)
+void AbstractMetaBuilderPrivate::inheritTemplateFunctions(const AbstractMetaClassPtr &subclass)
{
- QString errorMessage;
auto templateClass = subclass->templateBaseClass();
if (subclass->isTypeDef()) {
- subclass->setHasCloneOperator(templateClass->hasCloneOperator());
- subclass->setHasEqualsOperator(templateClass->hasEqualsOperator());
- subclass->setHasHashFunction(templateClass->hasHashFunction());
+ subclass->setHashFunction(templateClass->hashFunction());
subclass->setHasNonPrivateConstructor(templateClass->hasNonPrivateConstructor());
subclass->setHasPrivateDestructor(templateClass->hasPrivateDestructor());
subclass->setHasProtectedDestructor(templateClass->hasProtectedDestructor());
@@ -2782,82 +3371,13 @@ void AbstractMetaBuilderPrivate::inheritTemplateFunctions(AbstractMetaClass *sub
subclass->functions(); // Take copy
const auto &templateClassFunctions = templateClass->functions();
for (const auto &function : templateClassFunctions) {
- if (!inheritTemplateFunction(function, existingSubclassFuncs,
- subclass, templateClass)) {
- continue;
- }
-
- std::unique_ptr<AbstractMetaFunction> f(function->copy());
- f->setArguments(AbstractMetaArgumentList());
-
- if (!function->isVoid()) {
- auto returnType = inheritTemplateType(templateTypes, function->type());
- if (!returnType.has_value())
- continue;
- f->setType(returnType.value());
- }
-
- const AbstractMetaArgumentList &arguments = function->arguments();
- for (const AbstractMetaArgument &argument : arguments) {
- auto argType = inheritTemplateType(templateTypes, argument.type());
- if (!argType.has_value())
- break;
- AbstractMetaArgument arg = argument;
- arg.setType(argType.value());
- f->addArgument(arg);
- }
-
- if (f->arguments().size() < function->arguments().size())
- continue;
-
- // There is no base class in the target language to inherit from here, so
- // the template instantiation is the class that implements the function.
- f->setImplementingClass(subclass);
-
- // We also set it as the declaring class, since the superclass is
- // supposed to disappear. This allows us to make certain function modifications
- // on the inherited functions.
- f->setDeclaringClass(subclass);
-
- if (f->isConstructor()) {
- if (!subclass->isTypeDef())
- continue;
- f->setName(subclass->name());
- f->setOriginalName(subclass->name());
+ if (doInheritTemplateFunction(function, existingSubclassFuncs,
+ templateClass, subclass)) {
+ AbstractMetaFunctionCPtr f = inheritTemplateMember(function, templateTypes,
+ templateClass, subclass);
+ if (f)
+ AbstractMetaClass::addFunction(subclass, f);
}
-
- ComplexTypeEntry* te = subclass->typeEntry();
- FunctionModificationList mods = function->modifications(templateClass);
- for (int i = 0; i < mods.size(); ++i) {
- FunctionModification mod = mods.at(i);
- mod.setSignature(f->minimalSignature());
-
- // If we ever need it... Below is the code to do
- // substitution of the template instantation type inside
- // injected code..
-#if 0
- if (mod.modifiers & Modification::CodeInjection) {
- for (int j = 0; j < template_types.size(); ++j) {
- CodeSnip &snip = mod.snips.last();
- QString code = snip.code();
- code.replace(QString::fromLatin1("$$QT_TEMPLATE_%1$$").arg(j),
- template_types.at(j)->typeEntry()->qualifiedCppName());
- snip.codeList.clear();
- snip.addCode(code);
- }
- }
-#endif
- te->addFunctionModification(mod);
- }
-
-
- if (!applyArrayArgumentModifications(f->modifications(subclass), f.get(),
- &errorMessage)) {
- qCWarning(lcShiboken, "While specializing %s (%s): %s",
- qPrintable(subclass->name()), qPrintable(templateClass->name()),
- qPrintable(errorMessage));
- }
- subclass->addFunction(AbstractMetaFunctionCPtr(f.release()));
}
// Take copy
@@ -2866,8 +3386,7 @@ void AbstractMetaBuilderPrivate::inheritTemplateFunctions(AbstractMetaClass *sub
for (const AbstractMetaField &field : templateClassFields) {
// If the field is modified or the instantiation has a field named
// the same as an existing field we have shadowing, so we need to skip it.
- if (field.isModifiedRemoved(TypeSystem::All)
- || field.isStatic()
+ if (field.isModifiedRemoved() || field.isStatic()
|| AbstractMetaField::find(existingSubclassFields, field.name()).has_value()) {
continue;
}
@@ -2882,7 +3401,7 @@ void AbstractMetaBuilderPrivate::inheritTemplateFunctions(AbstractMetaClass *sub
}
}
-void AbstractMetaBuilderPrivate::parseQ_Properties(AbstractMetaClass *metaClass,
+void AbstractMetaBuilderPrivate::parseQ_Properties(const AbstractMetaClassPtr &metaClass,
const QStringList &declarations)
{
const QStringList scopes = currentScope()->qualifiedName();
@@ -2893,7 +3412,7 @@ void AbstractMetaBuilderPrivate::parseQ_Properties(AbstractMetaClass *metaClass,
if (spec.has_value()) {
spec->setIndex(i);
metaClass->addPropertySpec(spec.value());
- } else {
+ } else if (!errorMessage.isEmpty()) {
QString message;
QTextStream str(&message);
str << metaClass->sourceLocation() << errorMessage;
@@ -2922,63 +3441,35 @@ void AbstractMetaBuilderPrivate::parseQ_Properties(AbstractMetaClass *metaClass,
}
}
-static AbstractMetaFunctionCPtr findCopyCtor(AbstractMetaClass* cls)
-{
- for (const auto &f : cls->functions()) {
- const AbstractMetaFunction::FunctionType t = f->functionType();
- if (t == AbstractMetaFunction::CopyConstructorFunction || t == AbstractMetaFunction::AssignmentOperatorFunction)
- return f;
- }
- return {};
-}
-
-void AbstractMetaBuilderPrivate::setupClonable(AbstractMetaClass *cls)
-{
- bool result = true;
-
- // find copy ctor for the current class
- auto copyCtor = findCopyCtor(cls);
- if (!copyCtor.isNull()) { // if exists a copy ctor in this class
- result = copyCtor->isPublic();
- } else { // else... lets find one in the parent class
- QQueue<AbstractMetaClass*> baseClasses;
- if (cls->baseClass())
- baseClasses.enqueue(cls->baseClass());
-
- while (!baseClasses.isEmpty()) {
- AbstractMetaClass* currentClass = baseClasses.dequeue();
- if (currentClass->baseClass())
- baseClasses.enqueue(currentClass->baseClass());
-
- copyCtor = findCopyCtor(currentClass);
- if (copyCtor) {
- result = copyCtor->isPublic();
- break;
- }
- }
- }
- cls->setHasCloneOperator(result);
-}
-
-void AbstractMetaBuilderPrivate::setupExternalConversion(AbstractMetaClass *cls)
+void AbstractMetaBuilderPrivate::setupExternalConversion(const AbstractMetaClassCPtr &cls)
{
const auto &convOps = cls->operatorOverloads(OperatorQueryOption::ConversionOp);
for (const auto &func : convOps) {
if (func->isModifiedRemoved())
continue;
- AbstractMetaClass *metaClass = AbstractMetaClass::findClass(m_metaClasses, func->type().typeEntry());
+ const auto metaClass =
+ AbstractMetaClass::findClass(m_metaClasses, func->type().typeEntry());
if (!metaClass)
continue;
metaClass->addExternalConversionOperator(func);
}
- const AbstractMetaClassList &innerClasses = cls->innerClasses();
- for (AbstractMetaClass *innerClass : innerClasses)
+ for (const auto &innerClass : cls->innerClasses())
setupExternalConversion(innerClass);
}
static void writeRejectLogFile(const QString &name,
- const QMap<QString, AbstractMetaBuilder::RejectReason> &rejects)
-{
+ const AbstractMetaBuilderPrivate::RejectSet &rejects)
+{
+ static const QHash<AbstractMetaBuilder::RejectReason, QByteArray> descriptions ={
+ {AbstractMetaBuilder::NotInTypeSystem, "Not in type system"_ba},
+ {AbstractMetaBuilder::GenerationDisabled, "Generation disabled by type system"_ba},
+ {AbstractMetaBuilder::RedefinedToNotClass, "Type redefined to not be a class"_ba},
+ {AbstractMetaBuilder::UnmatchedReturnType, "Unmatched return type"_ba},
+ {AbstractMetaBuilder::UnmatchedArgumentType, "Unmatched argument type"_ba},
+ {AbstractMetaBuilder::UnmatchedOperator, "Unmatched operator"_ba},
+ {AbstractMetaBuilder::Deprecated, "Deprecated"_ba}
+ };
+
QFile f(name);
if (!f.open(QIODevice::WriteOnly | QIODevice::Text)) {
qCWarning(lcShiboken, "%s", qPrintable(msgCannotOpenForWriting(f)));
@@ -2987,70 +3478,37 @@ static void writeRejectLogFile(const QString &name,
QTextStream s(&f);
-
- for (int reason = 0; reason < AbstractMetaBuilder::NoReason; ++reason) {
- s << QString(72, QLatin1Char('*')) << Qt::endl;
- switch (reason) {
- case AbstractMetaBuilder::NotInTypeSystem:
- s << "Not in type system";
- break;
- case AbstractMetaBuilder::GenerationDisabled:
- s << "Generation disabled by type system";
- break;
- case AbstractMetaBuilder::RedefinedToNotClass:
- s << "Type redefined to not be a class";
- break;
-
- case AbstractMetaBuilder::UnmatchedReturnType:
- s << "Unmatched return type";
- break;
-
- case AbstractMetaBuilder::UnmatchedArgumentType:
- s << "Unmatched argument type";
- break;
-
- case AbstractMetaBuilder::ApiIncompatible:
- s << "Incompatible API";
- break;
-
- case AbstractMetaBuilder::Deprecated:
- s << "Deprecated";
- break;
-
- default:
- s << "unknown reason";
- break;
+ int lastReason = -1;
+ for (const auto &e : rejects) {
+ if (e.reason != lastReason) {
+ const QByteArray description = descriptions.value(e.reason, "Unknown reason"_ba);
+ const QByteArray underline(description.size(), '*');
+ if (lastReason != -1)
+ s << '\n';
+ s << underline << '\n' << description << '\n' << underline << "\n\n";
+ lastReason = e.reason;
}
- s << Qt::endl;
-
- for (QMap<QString, AbstractMetaBuilder::RejectReason>::const_iterator it = rejects.constBegin();
- it != rejects.constEnd(); ++it) {
- if (it.value() != reason)
- continue;
- s << " - " << it.key() << Qt::endl;
- }
-
- s << QString(72, QLatin1Char('*')) << Qt::endl << Qt::endl;
+ s << " - " << e << '\n';
}
-
}
void AbstractMetaBuilderPrivate::dumpLog() const
{
- writeRejectLogFile(m_logDirectory + QLatin1String("mjb_rejected_classes.log"), m_rejectedClasses);
- writeRejectLogFile(m_logDirectory + QLatin1String("mjb_rejected_enums.log"), m_rejectedEnums);
- writeRejectLogFile(m_logDirectory + QLatin1String("mjb_rejected_functions.log"), m_rejectedFunctions);
- writeRejectLogFile(m_logDirectory + QLatin1String("mjb_rejected_fields.log"), m_rejectedFields);
+ writeRejectLogFile(m_logDirectory + u"mjb_rejected_classes.log"_s, m_rejectedClasses);
+ writeRejectLogFile(m_logDirectory + u"mjb_rejected_enums.log"_s, m_rejectedEnums);
+ writeRejectLogFile(m_logDirectory + u"mjb_rejected_functions.log"_s, m_rejectedFunctions);
+ writeRejectLogFile(m_logDirectory + u"mjb_rejected_fields.log"_s, m_rejectedFields);
}
-using ClassGraph = Graph<AbstractMetaClass *>;
-
-// Add a dependency of the class associated with typeEntry on clazz
-static bool addClassDependency(const AbstractMetaClassList &classList,
- const TypeEntry *typeEntry,
- AbstractMetaClass *clazz,
- ClassGraph *graph)
+// Topological sorting of classes. Templates for use with
+// AbstractMetaClassList/AbstractMetaClassCList.
+// Add a dependency of the class associated with typeEntry on clazz.
+template <class MetaClass>
+static bool addClassDependency(const QList<std::shared_ptr<MetaClass> > &classList,
+ const TypeEntryCPtr &typeEntry,
+ std::shared_ptr<MetaClass> clazz,
+ Graph<std::shared_ptr<MetaClass> > *graph)
{
if (!typeEntry->isComplex() || typeEntry == clazz->typeEntry())
return false;
@@ -3060,10 +3518,12 @@ static bool addClassDependency(const AbstractMetaClassList &classList,
return graph->addEdge(c, clazz);
}
-AbstractMetaClassList AbstractMetaBuilderPrivate::classesTopologicalSorted(const AbstractMetaClassList &classList,
- const Dependencies &additionalDependencies)
+template <class MetaClass>
+static QList<std::shared_ptr<MetaClass> >
+ topologicalSortHelper(const QList<std::shared_ptr<MetaClass> > &classList,
+ const Dependencies &additionalDependencies)
{
- ClassGraph graph(classList.cbegin(), classList.cend());
+ Graph<std::shared_ptr<MetaClass> > graph(classList.cbegin(), classList.cend());
for (const auto &dep : additionalDependencies) {
if (!graph.addEdge(dep.parent, dep.child)) {
@@ -3073,14 +3533,14 @@ AbstractMetaClassList AbstractMetaBuilderPrivate::classesTopologicalSorted(const
}
}
- for (AbstractMetaClass *clazz : classList) {
+ for (const auto &clazz : classList) {
if (auto enclosingC = clazz->enclosingClass()) {
- auto enclosing = const_cast<AbstractMetaClass *>(enclosingC);
+ const auto enclosing = std::const_pointer_cast<MetaClass>(enclosingC);
graph.addEdge(enclosing, clazz);
}
- for (auto baseClass : clazz->baseClasses())
- graph.addEdge(baseClass, clazz);
+ for (const auto &baseClass : clazz->baseClasses())
+ graph.addEdge(std::const_pointer_cast<MetaClass>(baseClass), clazz);
for (const auto &func : clazz->functions()) {
const AbstractMetaArgumentList &arguments = func->arguments();
@@ -3106,24 +3566,44 @@ AbstractMetaClassList AbstractMetaBuilderPrivate::classesTopologicalSorted(const
const auto result = graph.topologicalSort();
if (!result.isValid() && graph.nodeCount()) {
- QTemporaryFile tempFile(QDir::tempPath() + QLatin1String("/cyclic_depXXXXXX.dot"));
+ QTemporaryFile tempFile(QDir::tempPath() + u"/cyclic_depXXXXXX.dot"_s);
tempFile.setAutoRemove(false);
- tempFile.open();
- graph.dumpDot(tempFile.fileName(),
- [] (const AbstractMetaClass *c) { return c->name(); });
+ const bool ok = tempFile.open();
+ if (ok) {
+ graph.dumpDot(tempFile.fileName(),
+ [] (const AbstractMetaClassCPtr &c) { return c->name(); });
+ }
QString message;
QTextStream str(&message);
str << "Cyclic dependency of classes found:";
- for (auto c : result.cyclic)
+ for (const auto &c : result.cyclic)
str << ' ' << c->name();
- str << ". Graph can be found at \"" << QDir::toNativeSeparators(tempFile.fileName()) << '"';
+ str << '.';
+ if (ok) {
+ str << " Graph can be found at \""
+ << QDir::toNativeSeparators(tempFile.fileName()) << '"';
+ }
qCWarning(lcShiboken, "%s", qPrintable(message));
}
return result.result;
}
+AbstractMetaClassList
+ AbstractMetaBuilderPrivate::classesTopologicalSorted(const AbstractMetaClassList &classList,
+ const Dependencies &additionalDependencies)
+{
+ return topologicalSortHelper(classList, additionalDependencies);
+}
+
+AbstractMetaClassCList
+ AbstractMetaBuilderPrivate::classesTopologicalSorted(const AbstractMetaClassCList &classList,
+ const Dependencies &additionalDependencies)
+{
+ return topologicalSortHelper(classList, additionalDependencies);
+}
+
void AbstractMetaBuilderPrivate::pushScope(const NamespaceModelItem &item)
{
// For purposes of type lookup, join all namespaces of the same name
@@ -3137,8 +3617,8 @@ void AbstractMetaBuilderPrivate::pushScope(const NamespaceModelItem &item)
}
}
if (candidates.size() > 1) {
- NamespaceModelItem joined(new _NamespaceModelItem(m_scopes.constLast()->model(),
- name, _CodeModelItem::Kind_Namespace));
+ auto joined = std::make_shared<_NamespaceModelItem>(m_scopes.constLast()->model(),
+ name, _CodeModelItem::Kind_Namespace);
joined->setScope(item->scope());
for (const auto &n : candidates)
joined->appendNamespace(*n);
@@ -3171,13 +3651,18 @@ void AbstractMetaBuilder::setSkipDeprecated(bool value)
d->m_skipDeprecated = value;
}
+void AbstractMetaBuilder::setApiExtractorFlags(ApiExtractorFlags flags)
+{
+ d->m_apiExtractorFlags = flags;
+}
+
// PYSIDE-975: When receiving an absolute path name from the code model, try
// to resolve it against the include paths set on shiboken in order to recreate
// relative paths like #include <foo/bar.h>.
static inline bool isFileSystemSlash(QChar c)
{
- return c == QLatin1Char('/') || c == QLatin1Char('\\');
+ return c == u'/' || c == u'\\';
}
static bool matchHeader(const QString &headerPath, const QString &fileName)
@@ -3187,13 +3672,13 @@ static bool matchHeader(const QString &headerPath, const QString &fileName)
#else
static const Qt::CaseSensitivity caseSensitivity = Qt::CaseSensitive;
#endif
- const int pathSize = headerPath.size();
+ const auto pathSize = headerPath.size();
return fileName.size() > pathSize
&& isFileSystemSlash(fileName.at(pathSize))
&& fileName.startsWith(headerPath, caseSensitivity);
}
-void AbstractMetaBuilderPrivate::setInclude(TypeEntry *te, const QString &path) const
+void AbstractMetaBuilderPrivate::setInclude(const TypeEntryPtr &te, const QString &path) const
{
auto it = m_resolveIncludeHash.find(path);
if (it == m_resolveIncludeHash.end()) {
@@ -3241,9 +3726,9 @@ void AbstractMetaBuilder::formatDebug(QDebug &debug) const
debug << "m_globalHeader=" << d->m_globalHeaders;
debugFormatSequence(debug, "globalEnums", d->m_globalEnums, "\n");
debugFormatSequence(debug, "globalFunctions", d->m_globalFunctions, "\n");
- if (const int scopeCount = d->m_scopes.size()) {
+ if (const auto scopeCount = d->m_scopes.size()) {
debug << "\n scopes[" << scopeCount << "]=(";
- for (int i = 0; i < scopeCount; ++i) {
+ for (qsizetype i = 0; i < scopeCount; ++i) {
if (i)
debug << ", ";
_CodeModelItem::formatKind(debug, d->m_scopes.at(i)->kind());