aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2021-01-20 12:17:42 +0100
committerUlf Hermann <ulf.hermann@qt.io>2021-01-20 13:33:52 +0100
commit3ae2a6a47c960d159e1110b434795fc69ecf3d80 (patch)
treebb703e7dc88eaedb2ac064a345008295eec20fd2 /src
parentbf573ad295fbc1eee9379bfaafcded293c4b81f4 (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.cpp65
-rw-r--r--src/qmlcompiler/qqmljsscope_p.h7
-rw-r--r--src/qmlcompiler/qqmljstypedescriptionreader.cpp2
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, "