aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/qmlcompiler/qqmljsscope.cpp65
-rw-r--r--src/qmlcompiler/qqmljsscope_p.h7
-rw-r--r--src/qmlcompiler/qqmljstypedescriptionreader.cpp2
-rw-r--r--tests/auto/qml/qmllint/tst_qmllint.cpp2
-rw-r--r--tools/qmllint/checkidentifiers.cpp13
5 files changed, 83 insertions, 6 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, "
diff --git a/tests/auto/qml/qmllint/tst_qmllint.cpp b/tests/auto/qml/qmllint/tst_qmllint.cpp
index 0a2f8ed6b1..3f674fb5cc 100644
--- a/tests/auto/qml/qmllint/tst_qmllint.cpp
+++ b/tests/auto/qml/qmllint/tst_qmllint.cpp
@@ -317,7 +317,6 @@ void TestQmllint::cleanQmlCode()
{
QFETCH(QString, filename);
const QString warnings = runQmllint(filename, true);
- QEXPECT_FAIL("unknownBuiltinFont", "Broken extended support", Continue);
QVERIFY2(warnings.isEmpty(), qPrintable(warnings));
}
@@ -362,7 +361,6 @@ QString TestQmllint::runQmllint(const QString &fileToLint, bool shouldSucceed, c
return runQmllint(fileToLint, [&](QProcess &process) {
QVERIFY(process.waitForFinished());
QCOMPARE(process.exitStatus(), QProcess::NormalExit);
- QEXPECT_FAIL("unknownBuiltinFont", "Broken extended support", Continue);
if (shouldSucceed)
QCOMPARE(process.exitCode(), 0);
else
diff --git a/tools/qmllint/checkidentifiers.cpp b/tools/qmllint/checkidentifiers.cpp
index b718f0f691..90456f97aa 100644
--- a/tools/qmllint/checkidentifiers.cpp
+++ b/tools/qmllint/checkidentifiers.cpp
@@ -86,6 +86,12 @@ static bool walkViaParentAndAttachedScopes(QQmlJSScope::ConstPtr rootType,
return false;
std::stack<QQmlJSScope::ConstPtr> stack;
stack.push(rootType);
+
+ if (!rootType->isComposite()) {
+ if (auto extension = rootType->extensionType())
+ stack.push(extension);
+ }
+
while (!stack.empty()) {
const auto type = stack.top();
stack.pop();
@@ -93,8 +99,13 @@ static bool walkViaParentAndAttachedScopes(QQmlJSScope::ConstPtr rootType,
if (visit(type))
return true;
- if (auto superType = type->baseType())
+ if (auto superType = type->baseType()) {
stack.push(superType);
+ if (type->isComposite() && !superType->isComposite()) {
+ if (auto extension = superType->extensionType())
+ stack.push(extension);
+ }
+ }
if (auto attachedType = type->attachedType())
stack.push(attachedType);