aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMaximilian Goldstein <max.goldstein@qt.io>2022-05-20 11:53:40 +0200
committerMaximilian Goldstein <max.goldstein@qt.io>2022-06-02 10:07:40 +0200
commit15efc5c32369f5852c7f83696fe0d21f6d338972 (patch)
tree7c2eaa7631f79f0a4f9b78d28b9204e3198d67b6 /src
parent80f0bf64e49f07a73712998ddc8a0eebd1b660b6 (diff)
qqmlsa: Make property pass check base and extension types as well
In many cases we need to also check base an extension types since we don't always have direct inheritance (i.e. very common with QtQuick.Controls) Change-Id: I66307b7d0081d49611a9e61847e4363d5819bf82 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'src')
-rw-r--r--src/qmlcompiler/qqmljstypepropagator.cpp12
-rw-r--r--src/qmlcompiler/qqmlsa.cpp52
-rw-r--r--src/qmlcompiler/qqmlsa_p.h17
3 files changed, 55 insertions, 26 deletions
diff --git a/src/qmlcompiler/qqmljstypepropagator.cpp b/src/qmlcompiler/qqmljstypepropagator.cpp
index 27e120a832..44822371b5 100644
--- a/src/qmlcompiler/qqmljstypepropagator.cpp
+++ b/src/qmlcompiler/qqmljstypepropagator.cpp
@@ -97,6 +97,12 @@ QQmlJSCompilePass::InstructionAnnotations QQmlJSTypePropagator::run(
void QQmlJSTypePropagator::generate_Ret()
{
+ if (m_passManager != nullptr && m_function->isProperty) {
+ m_passManager->analyzeBinding(m_function->qmlScope,
+ m_typeResolver->containedType(m_state.accumulatorIn()),
+ getCurrentBindingSourceLocation());
+ }
+
if (m_function->isSignalHandler) {
// Signal handlers cannot return anything.
} else if (!m_returnType.isValid() && m_state.accumulatorIn().isValid()
@@ -125,12 +131,6 @@ void QQmlJSTypePropagator::generate_Ret()
addReadAccumulator(m_returnType);
}
- if (m_passManager != nullptr && m_function->isProperty) {
- m_passManager->analyzeBinding(m_function->qmlScope,
- m_typeResolver->containedType(m_state.accumulatorIn()),
- getCurrentBindingSourceLocation());
- }
-
m_state.setHasSideEffects(true);
m_state.skipInstructionsUntilNextJumpTarget = true;
}
diff --git a/src/qmlcompiler/qqmlsa.cpp b/src/qmlcompiler/qqmlsa.cpp
index 184ac79ee0..31fedc9ff4 100644
--- a/src/qmlcompiler/qqmlsa.cpp
+++ b/src/qmlcompiler/qqmlsa.cpp
@@ -32,6 +32,7 @@
#include "qqmljslogger_p.h"
#include "qqmljstyperesolver_p.h"
#include "qqmljsimportvisitor_p.h"
+#include "qqmljsutils_p.h"
#include <memory>
@@ -101,7 +102,7 @@ static QString lookupName(const QQmlSA::Element &element, LookupMode mode = Look
bool PassManager::registerPropertyPass(std::shared_ptr<PropertyPass> pass,
QAnyStringView moduleName, QAnyStringView typeName,
- QAnyStringView propertyName)
+ QAnyStringView propertyName, bool allowInheritance)
{
QString name;
if (!moduleName.isEmpty() && !typeName.isEmpty()) {
@@ -114,7 +115,11 @@ bool PassManager::registerPropertyPass(std::shared_ptr<PropertyPass> pass,
name = lookupName(element, Register);
}
- m_propertyPasses.insert({ std::make_pair<>(name, propertyName.toString()), std::move(pass) });
+ const PassManager::PropertyPassInfo passInfo {
+ propertyName.isEmpty() ? QStringList {} : QStringList { propertyName.toString() },
+ std::move(pass), allowInheritance
+ };
+ m_propertyPasses.insert({ name, passInfo });
return true;
}
@@ -195,7 +200,7 @@ void PassManager::analyzeBinding(const Element &element, const QQmlSA::Element &
for (PropertyPass *pass : findPropertyUsePasses(element, propertyName))
pass->onBinding(element, propertyName, binding, bindingScope, value);
- if (!info->second.isAttached)
+ if (!info->second.isAttached || bindingScope->baseType().isNull())
return;
for (PropertyPass *pass : findPropertyUsePasses(bindingScope->baseType(), propertyName))
@@ -207,20 +212,35 @@ bool PassManager::hasImportedModule(QAnyStringView module) const
return m_visitor->imports().contains(u"$module$." + module.toString());
}
-std::vector<PropertyPass *> PassManager::findPropertyUsePasses(const QQmlSA::Element &element,
- const QString &propertyName)
+QSet<PropertyPass *> PassManager::findPropertyUsePasses(const QQmlSA::Element &element,
+ const QString &propertyName)
{
- const QString typeName = lookupName(element);
- std::vector<PropertyPass *> passes;
- for (const auto &key :
- { std::make_pair<>(typeName, propertyName), std::make_pair<>(QString(), propertyName),
- std::make_pair<>(typeName, QString()) }) {
- auto pass = m_propertyPasses.equal_range(key);
- if (pass.first == pass.second)
- continue;
-
- for (auto it = pass.first; it != pass.second; it++)
- passes.push_back(it->second.get());
+ QStringList typeNames { lookupName(element) };
+
+ QQmlJSUtils::searchBaseAndExtensionTypes(
+ element, [&](const QQmlJSScope::ConstPtr &scope, QQmlJSScope::ExtensionKind mode) {
+ Q_UNUSED(mode);
+ typeNames.append(lookupName(scope));
+ return false;
+ });
+
+ QSet<PropertyPass *> passes;
+
+ for (const QString &typeName : typeNames) {
+ for (auto &pass :
+ { m_propertyPasses.equal_range(u""_s), m_propertyPasses.equal_range(typeName) }) {
+ if (pass.first == pass.second)
+ continue;
+
+ for (auto it = pass.first; it != pass.second; it++) {
+ if (typeName != typeNames.constFirst() && !it->second.allowInheritance)
+ continue;
+ if (it->second.properties.isEmpty()
+ || it->second.properties.contains(propertyName)) {
+ passes.insert(it->second.pass.get());
+ }
+ }
+ }
}
return passes;
}
diff --git a/src/qmlcompiler/qqmlsa_p.h b/src/qmlcompiler/qqmlsa_p.h
index 5f2ebcd91a..7e1eeb1c27 100644
--- a/src/qmlcompiler/qqmlsa_p.h
+++ b/src/qmlcompiler/qqmlsa_p.h
@@ -42,6 +42,7 @@
#include <qtqmlcompilerexports.h>
#include <private/qqmljsscope_p.h>
+#include <QtCore/qset.h>
#include <map>
#include <unordered_map>
@@ -126,7 +127,8 @@ public:
void registerElementPass(std::unique_ptr<ElementPass> pass);
bool registerPropertyPass(std::shared_ptr<PropertyPass> pass, QAnyStringView moduleName,
QAnyStringView typeName,
- QAnyStringView propertyName = QAnyStringView());
+ QAnyStringView propertyName = QAnyStringView(),
+ bool allowInheritance = true);
void analyze(const Element &root);
bool hasImportedModule(QAnyStringView name) const;
@@ -134,8 +136,8 @@ public:
private:
friend struct ::QQmlJSTypePropagator;
- std::vector<PropertyPass *> findPropertyUsePasses(const QQmlSA::Element &element,
- const QString &propertyName);
+ QSet<PropertyPass *> findPropertyUsePasses(const QQmlSA::Element &element,
+ const QString &propertyName);
void analyzeWrite(const QQmlSA::Element &element, QString propertyName,
const QQmlSA::Element &value, const QQmlSA::Element &writeScope,
@@ -153,12 +155,19 @@ private:
bool isAttached;
};
+ struct PropertyPassInfo
+ {
+ QStringList properties;
+ std::shared_ptr<PropertyPass> pass;
+ bool allowInheritance = true;
+ };
+
void addBindingSourceLocations(const QQmlSA::Element &element,
const QQmlSA::Element &scope = QQmlSA::Element(),
const QString prefix = QString(), bool isAttached = false);
std::vector<std::unique_ptr<ElementPass>> m_elementPasses;
- std::multimap<std::pair<QString, QString>, std::shared_ptr<PropertyPass>> m_propertyPasses;
+ std::multimap<QString, PropertyPassInfo> m_propertyPasses;
std::unordered_map<quint32, BindingInfo> m_bindingsByLocation;
QQmlJSImportVisitor *m_visitor;
QQmlJSTypeResolver *m_typeResolver;