diff options
author | Andrei Golubev <andrei.golubev@qt.io> | 2021-06-04 15:59:26 +0200 |
---|---|---|
committer | Andrei Golubev <andrei.golubev@qt.io> | 2021-06-07 13:53:08 +0200 |
commit | 9a706f9715d2af914539656d507d149e4cab5c55 (patch) | |
tree | 7c47b9f0ed9871008810027597f503f34c664e60 /src | |
parent | 4b6655bf98467775f117e3b0edab4731551dbae5 (diff) |
QQmlJSScope: add method to query the owner of the property
When calculating absolute property index from the relative
QQmlJSMetaProperty::index() value, we need to know the QQmlJSScope
that owns the property (to start the value calculation from).
The logic of finding the property is non-trivial (due to extension
types), so custom QQmlJSScope traversal should really be discouraged
While adding a new method, revise existing QQmlJSScope traversal
method and make it more generic, so that we could return
both (const) QQmlJSScope * and QQmlJSScope::{Ptr, ConstPtr} depending
on the use case
Change-Id: I84ce038a6a40cdcab3f33ba6a448baa672d62826
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
Diffstat (limited to 'src')
-rw-r--r-- | src/qmlcompiler/qqmljsscope.cpp | 58 | ||||
-rw-r--r-- | src/qmlcompiler/qqmljsscope_p.h | 3 |
2 files changed, 56 insertions, 5 deletions
diff --git a/src/qmlcompiler/qqmljsscope.cpp b/src/qmlcompiler/qqmljsscope.cpp index 7d5e26bad9..2276c10814 100644 --- a/src/qmlcompiler/qqmljsscope.cpp +++ b/src/qmlcompiler/qqmljsscope.cpp @@ -35,16 +35,50 @@ #include <QtCore/qfileinfo.h> #include <algorithm> +#include <type_traits> QT_BEGIN_NAMESPACE -template<typename Action> -static bool searchBaseAndExtensionTypes(const QQmlJSScope *type, const Action &check) +/*! \internal + + Utility method that returns proper value according to the type To. This + version returns From. +*/ +template<typename To, typename From, typename std::enable_if_t<!std::is_pointer_v<To>, int> = 0> +static auto getQQmlJSScopeFromSmartPtr(const From &p) -> From +{ + static_assert(!std::is_pointer_v<From>, "From has to be a smart pointer holding QQmlJSScope"); + return p; +} + +/*! \internal + + Utility method that returns proper value according to the type To. This + version returns From::get(), which is a raw pointer. The returned type is + not necessary equal to To (e.g. To might be `QQmlJSScope *` while returned + is `const QQmlJSScope *`). +*/ +template<typename To, typename From, typename std::enable_if_t<std::is_pointer_v<To>, int> = 0> +static auto getQQmlJSScopeFromSmartPtr(const From &p) -> decltype(p.get()) +{ + static_assert(!std::is_pointer_v<From>, "From has to be a smart pointer holding QQmlJSScope"); + return p.get(); +} + +template<typename QQmlJSScopePtr, typename Action> +static bool searchBaseAndExtensionTypes(QQmlJSScopePtr type, const Action &check) { - for (const QQmlJSScope *scope = type; scope; scope = scope->baseType().data()) { + // NB: among other things, getQQmlJSScopeFromSmartPtr() also resolves const + // vs non-const pointer issue, so use it's return value as the type + using T = decltype( + getQQmlJSScopeFromSmartPtr<QQmlJSScopePtr>(std::declval<QQmlJSScope::ConstPtr>())); + + for (T scope = type; scope; + scope = getQQmlJSScopeFromSmartPtr<QQmlJSScopePtr>(scope->baseType())) { // Extensions override their base types - for (const QQmlJSScope *extension = scope->extensionType().data(); extension; - extension = extension->baseType().data()) { + for (T extension = getQQmlJSScopeFromSmartPtr<QQmlJSScopePtr>(scope->extensionType()); + extension; + extension = getQQmlJSScopeFromSmartPtr<QQmlJSScopePtr>(extension->baseType())) { if (check(extension)) return true; } @@ -343,6 +377,20 @@ QQmlJSMetaProperty QQmlJSScope::property(const QString &name) const return prop; } +QQmlJSScope::ConstPtr QQmlJSScope::ownerOfProperty(const QQmlJSScope::ConstPtr &self, + const QString &name) +{ + QQmlJSScope::ConstPtr owner; + searchBaseAndExtensionTypes(self, [&](const QQmlJSScope::ConstPtr &scope) { + if (scope->hasOwnProperty(name)) { + owner = scope; + return true; + } + return false; + }); + return owner; +} + void QQmlJSScope::setPropertyLocallyRequired(const QString &name, bool isRequired) { if (!isRequired) diff --git a/src/qmlcompiler/qqmljsscope_p.h b/src/qmlcompiler/qqmljsscope_p.h index fade4d84be..3822cd9c32 100644 --- a/src/qmlcompiler/qqmljsscope_p.h +++ b/src/qmlcompiler/qqmljsscope_p.h @@ -248,6 +248,9 @@ public: bool hasPropertyBinding(const QString &name) const; QQmlJSMetaPropertyBinding propertyBinding(const QString &name) const; + static QQmlJSScope::ConstPtr ownerOfProperty(const QQmlJSScope::ConstPtr &self, + const QString &name); + bool isResolved() const; bool isFullyResolved() const; |