diff options
author | Marc Mutz <marc.mutz@kdab.com> | 2015-11-09 16:38:19 +0100 |
---|---|---|
committer | Marc Mutz <marc.mutz@kdab.com> | 2016-01-26 11:20:58 +0000 |
commit | 2c26d519e2c430ec179107addfa414e172ec7ab8 (patch) | |
tree | b3bc52b940c2a95ae92909ccc970ef62384a8698 /src | |
parent | b8c32f5efc4ac2acf453fb8ecd4a72059abf678c (diff) |
moc: simplify finding required Qt containers
The old code searched for any Qt containers by looking at
- each class definition
- each property's type
- each function (signal, slot, method)
- each argument type
and matching each against "Container<", building
the pattern string each time through the loop.
It would then collect hits in a QSet to be converted
to a QList and sorted at the very end.
The new code pulls the iteration over the candidates
out of all other loops. By doing so, it can stop
looking at classes, properties, functions etc when
it finds the first hit, and it inserts every candidate
at most once.
By iterating over the statically-known list of
candidates, the result is not a sorted set of Qt
containers, as before, but it still has s fixed order
across runs, which was the purpose of the sorting in
the original code.
In the implementation, make liberal use of C++11
range-for, which is safe, as we're passing everything
around as const.
Change-Id: If76dd3f57aa1b544a9cf1de2dca94ca7999220f0
Reviewed-by: Olivier Goffart (Woboq GmbH) <ogoffart@woboq.com>
Reviewed-by: Lars Knoll <lars.knoll@theqtcompany.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/tools/moc/moc.cpp | 72 |
1 files changed, 44 insertions, 28 deletions
diff --git a/src/tools/moc/moc.cpp b/src/tools/moc/moc.cpp index 80581a6c55..54a0871bec 100644 --- a/src/tools/moc/moc.cpp +++ b/src/tools/moc/moc.cpp @@ -801,9 +801,30 @@ void Moc::parse() } } -static void findRequiredContainers(ClassDef *cdef, QSet<QByteArray> *requiredQtContainers) +static bool any_type_contains(const QList<PropertyDef> &properties, const QByteArray &pattern) { - static const QVector<QByteArray> candidates = QVector<QByteArray>() + for (const auto &p : properties) { + if (p.type.contains(pattern)) + return true; + } + return false; +} + +static bool any_arg_contains(const QList<FunctionDef> &functions, const QByteArray &pattern) +{ + for (const auto &f : functions) { + for (const auto &arg : f.arguments) { + if (arg.normalizedType.contains(pattern)) + return true; + } + } + return false; +} + +static QByteArrayList make_candidates() +{ + QByteArrayList result; + result #define STREAM_SMART_POINTER(SMART_POINTER) << #SMART_POINTER QT_FOR_EACH_AUTOMATIC_TEMPLATE_SMART_POINTER(STREAM_SMART_POINTER) #undef STREAM_SMART_POINTER @@ -811,26 +832,31 @@ static void findRequiredContainers(ClassDef *cdef, QSet<QByteArray> *requiredQtC QT_FOR_EACH_AUTOMATIC_TEMPLATE_1ARG(STREAM_1ARG_TEMPLATE) #undef STREAM_1ARG_TEMPLATE ; + return result; +} - for (int i = 0; i < cdef->propertyList.count(); ++i) { - const PropertyDef &p = cdef->propertyList.at(i); - foreach (const QByteArray &candidate, candidates) { - if (p.type.contains(candidate + "<")) - requiredQtContainers->insert(candidate); - } - } +static QByteArrayList requiredQtContainers(const QList<ClassDef> &classes) +{ + static const QByteArrayList candidates = make_candidates(); + + QByteArrayList required; + required.reserve(candidates.size()); - QList<FunctionDef> allFunctions = cdef->slotList + cdef->signalList + cdef->methodList; + for (const auto &candidate : candidates) { + const QByteArray pattern = candidate + '<'; - for (int i = 0; i < allFunctions.count(); ++i) { - const FunctionDef &f = allFunctions.at(i); - foreach (const ArgumentDef &arg, f.arguments) { - foreach (const QByteArray &candidate, candidates) { - if (arg.normalizedType.contains(candidate + "<")) - requiredQtContainers->insert(candidate); + for (const auto &c : classes) { + if (any_type_contains(c.propertyList, pattern) || + any_arg_contains(c.slotList, pattern) || + any_arg_contains(c.signalList, pattern) || + any_arg_contains(c.methodList, pattern)) { + required.push_back(candidate); + break; } } } + + return required; } void Moc::generate(FILE *out) @@ -869,19 +895,9 @@ void Moc::generate(FILE *out) if (mustIncludeQPluginH) fprintf(out, "#include <QtCore/qplugin.h>\n"); - QSet<QByteArray> requiredQtContainers; - for (i = 0; i < classList.size(); ++i) { - findRequiredContainers(&classList[i], &requiredQtContainers); - } - - // after finding the containers, we sort them into a list to avoid - // non-deterministic behavior which may cause rebuilds unnecessarily. - QList<QByteArray> requiredContainerList = requiredQtContainers.toList(); - std::sort(requiredContainerList.begin(), requiredContainerList.end()); - - foreach (const QByteArray &qtContainer, requiredContainerList) { + const auto qtContainers = requiredQtContainers(classList); + for (const QByteArray &qtContainer : qtContainers) fprintf(out, "#include <QtCore/%s>\n", qtContainer.constData()); - } fprintf(out, "#if !defined(Q_MOC_OUTPUT_REVISION)\n" |