aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2021-02-01 15:03:19 +0100
committerUlf Hermann <ulf.hermann@qt.io>2021-02-01 16:51:51 +0100
commitf6fc35b45b449fe7aaca3237f29393a12fc3f90c (patch)
treebd808ac4fd916f49417f08e0e32105e614c7f0fd /tools
parent24ec3b3e7fa09900d791dcaedb0820a0b1890336 (diff)
QmlCompiler: Allow for multiple extensions per object
Previously, the assumption was that each object could only have a single extension object. As proven by the new qqmllanguage test this is not the case. Each registered object in the type hierarchy can have its own extension. Therefore, adjust the algorithms that generate qmltypes and iterate the extension objects when analyzing them. This leads us to the realization that anonymous types can in fact meaningfully carry extensions and implement interfaces. Adapt qmltyperegistrar accordingly. For the test to compile, however, we need to realize that the class declaring interfaces needs to befriend all potential subclass's QmlInterface structs. Fix that, too. The rabbit hole went deep. Change-Id: Ia451897e927e03b95c3062e829edf1dfcd216613 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'tools')
-rw-r--r--tools/qmllint/checkidentifiers.cpp27
1 files changed, 11 insertions, 16 deletions
diff --git a/tools/qmllint/checkidentifiers.cpp b/tools/qmllint/checkidentifiers.cpp
index 32a47891d5..6400e5db77 100644
--- a/tools/qmllint/checkidentifiers.cpp
+++ b/tools/qmllint/checkidentifiers.cpp
@@ -76,19 +76,14 @@ void CheckIdentifiers::printContext(
+ QLatin1Char('\n'), Normal);
}
-static bool walkViaParentAndAttachedScopes(QQmlJSScope::ConstPtr rootType,
- std::function<bool(QQmlJSScope::ConstPtr)> visit)
+template<typename Visitor>
+static bool walkRelatedScopes(QQmlJSScope::ConstPtr rootType, const Visitor &visit)
{
if (rootType.isNull())
return false;
std::stack<QQmlJSScope::ConstPtr> stack;
stack.push(rootType);
- if (!rootType->isComposite()) {
- if (auto extension = rootType->extensionType())
- stack.push(extension);
- }
-
while (!stack.empty()) {
const auto type = stack.top();
stack.pop();
@@ -96,17 +91,17 @@ static bool walkViaParentAndAttachedScopes(QQmlJSScope::ConstPtr rootType,
if (visit(type))
return true;
- if (auto superType = type->baseType()) {
- stack.push(superType);
- if (type->isComposite() && !superType->isComposite()) {
- if (auto extension = superType->extensionType())
- stack.push(extension);
- }
- }
-
if (auto attachedType = type->attachedType())
stack.push(attachedType);
+
+ if (auto baseType = type->baseType())
+ stack.push(baseType);
+
+ // Push extension type last. It overrides the base type.
+ if (auto extensionType = type->extensionType())
+ stack.push(extensionType);
}
+
return false;
}
@@ -233,7 +228,7 @@ bool CheckIdentifiers::checkMemberAccess(const QVector<FieldMember> &members,
rootType = scope;
bool typeFound =
- walkViaParentAndAttachedScopes(rootType, [&](QQmlJSScope::ConstPtr type) {
+ walkRelatedScopes(rootType, [&](QQmlJSScope::ConstPtr type) {
const auto typeProperties = type->ownProperties();
const auto typeIt = typeProperties.find(access.m_name);
if (typeIt != typeProperties.end()) {