diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2021-01-20 12:17:42 +0100 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2021-01-20 13:33:52 +0100 |
commit | 3ae2a6a47c960d159e1110b434795fc69ecf3d80 (patch) | |
tree | bb703e7dc88eaedb2ac064a345008295eec20fd2 /src | |
parent | bf573ad295fbc1eee9379bfaafcded293c4b81f4 (diff) |
qmllint: Support extended types
Fixes: QTBUG-90448
Change-Id: I5fb6b3d9223ae95ca7e039c5b9139ed086052c29
Reviewed-by: Maximilian Goldstein <max.goldstein@qt.io>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'src')
-rw-r--r-- | src/qmlcompiler/qqmljsscope.cpp | 65 | ||||
-rw-r--r-- | src/qmlcompiler/qqmljsscope_p.h | 7 | ||||
-rw-r--r-- | src/qmlcompiler/qqmljstypedescriptionreader.cpp | 2 |
3 files changed, 71 insertions, 3 deletions
diff --git a/src/qmlcompiler/qqmljsscope.cpp b/src/qmlcompiler/qqmljsscope.cpp index 202e292838..85c84420a3 100644 --- a/src/qmlcompiler/qqmljsscope.cpp +++ b/src/qmlcompiler/qqmljsscope.cpp @@ -78,18 +78,38 @@ bool QQmlJSScope::isIdInCurrentScope(const QString &id) const bool QQmlJSScope::hasMethod(const QString &name) const { + const QQmlJSScope *nonCompositeBase = isComposite() ? this : nullptr; for (const QQmlJSScope *scope = this; scope; scope = scope->baseType().data()) { if (scope->m_methods.contains(name)) return true; + if (!nonCompositeBase && !scope->isComposite()) + nonCompositeBase = scope; } + + if (nonCompositeBase && nonCompositeBase != this) { + if (QQmlJSScope::ConstPtr extension = nonCompositeBase->extensionType()) + return extension->hasMethod(name); + } + return false; } QList<QQmlJSMetaMethod> QQmlJSScope::methods(const QString &name) const { QList<QQmlJSMetaMethod> results; - for (const QQmlJSScope *scope = this; scope; scope = scope->baseType().data()) + + const QQmlJSScope *nonCompositeBase = isComposite() ? this : nullptr; + for (const QQmlJSScope *scope = this; scope; scope = scope->baseType().data()) { results.append(scope->ownMethods(name)); + if (!nonCompositeBase && !scope->isComposite()) + nonCompositeBase = scope; + } + + if (nonCompositeBase && nonCompositeBase != this) { + if (QQmlJSScope::ConstPtr extension = nonCompositeBase->extensionType()) + results.append(extension->methods(name)); + } + return results; } @@ -157,6 +177,9 @@ void QQmlJSScope::resolveTypes(const QHash<QString, QQmlJSScope::ConstPtr> &cont if (!m_valueType && !m_valueTypeName.isEmpty()) m_valueType = findType(m_valueTypeName); + if (!m_extensionType && !m_extensionTypeName.isEmpty()) + m_extensionType = findType(m_extensionTypeName); + for (auto it = m_properties.begin(), end = m_properties.end(); it != end; ++it) { const QString typeName = it->typeName(); if (!it->type() && !typeName.isEmpty()) @@ -192,12 +215,30 @@ void QQmlJSScope::resolveGroupedScopes() continue; const QString propertyName = childScope->internalName(); - for (const QQmlJSScope *type = this; type; type = type->baseType().data()) { + auto findProperty = [&](const QQmlJSScope *type) { auto propertyIt = type->m_properties.find(propertyName); if (propertyIt != type->m_properties.end()) { childScope->m_baseType = QQmlJSScope::ConstPtr(propertyIt->type()); childScope->m_baseTypeName = propertyIt->typeName(); + return true; + } + return false; + }; + + const QQmlJSScope *nonCompositeBase = isComposite() ? this : nullptr; + for (const QQmlJSScope *type = this; type; type = type->baseType().data()) { + if (findProperty(type)) break; + + if (!nonCompositeBase && !type->isComposite()) + nonCompositeBase = type; + } + + if (!childScope->m_baseType && nonCompositeBase && nonCompositeBase != this) { + for (const QQmlJSScope *type = nonCompositeBase->extensionType().data(); type; + type = type->baseType().data()) { + if (findProperty(type)) + break; } } @@ -221,20 +262,40 @@ void QQmlJSScope::addExport(const QString &name, const QString &package, bool QQmlJSScope::hasProperty(const QString &name) const { + const QQmlJSScope *nonCompositeBase = isComposite() ? this : nullptr; for (const QQmlJSScope *scope = this; scope; scope = scope->baseType().data()) { if (scope->m_properties.contains(name)) return true; + + if (!nonCompositeBase && !scope->isComposite()) + nonCompositeBase = scope; + } + + if (nonCompositeBase && nonCompositeBase != this) { + if (QQmlJSScope::ConstPtr extension = nonCompositeBase->extensionType()) + return extension->hasProperty(name); } + return false; } QQmlJSMetaProperty QQmlJSScope::property(const QString &name) const { + const QQmlJSScope *nonCompositeBase = isComposite() ? this : nullptr; for (const QQmlJSScope *scope = this; scope; scope = scope->baseType().data()) { const auto it = scope->m_properties.find(name); if (it != scope->m_properties.end()) return *it; + + if (!nonCompositeBase && !scope->isComposite()) + nonCompositeBase = scope; } + + if (nonCompositeBase && nonCompositeBase != this) { + if (QQmlJSScope::ConstPtr extension = nonCompositeBase->extensionType()) + return extension->property(name); + } + return {}; } diff --git a/src/qmlcompiler/qqmljsscope_p.h b/src/qmlcompiler/qqmljsscope_p.h index f0833a18a0..1902c46263 100644 --- a/src/qmlcompiler/qqmljsscope_p.h +++ b/src/qmlcompiler/qqmljsscope_p.h @@ -218,6 +218,10 @@ public: void setAttachedTypeName(const QString &name) { m_attachedTypeName = name; } QQmlJSScope::ConstPtr attachedType() const { return m_attachedType; } + QString extensionTypeName() const { return m_extensionTypeName; } + void setExtensionTypeName(const QString &name) { m_extensionTypeName = name; } + QQmlJSScope::ConstPtr extensionType() const { return m_extensionType; } + QString valueTypeName() const { return m_valueTypeName; } void setValueTypeName(const QString &name) { m_valueTypeName = name; } QQmlJSScope::ConstPtr valueType() const { return m_valueType; } @@ -304,6 +308,9 @@ private: QString m_valueTypeName; QQmlJSScope::WeakConstPtr m_valueType; + QString m_extensionTypeName; + QQmlJSScope::WeakConstPtr m_extensionType; + Flags m_flags; AccessSemantics m_semantics = AccessSemantics::Reference; diff --git a/src/qmlcompiler/qqmljstypedescriptionreader.cpp b/src/qmlcompiler/qqmljstypedescriptionreader.cpp index b24722b37c..b1a1d18bfe 100644 --- a/src/qmlcompiler/qqmljstypedescriptionreader.cpp +++ b/src/qmlcompiler/qqmljstypedescriptionreader.cpp @@ -249,7 +249,7 @@ void QQmlJSTypeDescriptionReader::readComponent(UiObjectDefinition *ast) tr("Unknown access semantics \"%1\".").arg(semantics)); } } else if (name == QLatin1String("extension")) { - // not implemented + scope->setExtensionTypeName(readStringBinding(script)); } else { addWarning(script->firstSourceLocation(), tr("Expected only name, prototype, defaultProperty, attachedType, " |