aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
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;