qmllint: Resolve aliases in nested objects

So far we've just ignored them.

Change-Id: I2ca522ef825a341a3f4bf1c2a42fb0376180cdda
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
This commit is contained in:
Ulf Hermann 2020-10-21 14:11:10 +02:00
parent ec9d125f55
commit 826b7c3b18
5 changed files with 59 additions and 25 deletions

View File

@ -30,6 +30,7 @@
#include <QtCore/qfileinfo.h>
#include <QtCore/qdir.h>
#include <QtCore/qqueue.h>
QT_BEGIN_NAMESPACE
@ -60,32 +61,33 @@ void QQmlJSImportVisitor::leaveEnvironment()
m_currentScope = m_currentScope->parentScope();
}
void QQmlJSImportVisitor::resolveAliases()
{
QQueue<QQmlJSScope::Ptr> objects;
objects.enqueue(m_qmlRootScope);
while (!objects.isEmpty()) {
const QQmlJSScope::Ptr object = objects.dequeue();
const auto properties = object->properties();
for (auto property : properties) {
if (!property.isAlias())
continue;
const auto it = m_scopesById.find(property.typeName());
if (it != m_scopesById.end()) {
property.setType(QQmlJSScope::ConstPtr(*it));
object->addProperty(property);
}
}
const auto childScopes = object->childScopes();
for (const auto &childScope : childScopes)
objects.enqueue(childScope);
}
}
QQmlJSScope::Ptr QQmlJSImportVisitor::result() const
{
QQmlJSScope::Ptr result = QQmlJSScope::create();
result->setIsComposite(true);
result->setBaseTypeName(m_qmlRootScope->baseTypeName());
const auto properties = m_qmlRootScope->properties();
for (auto property : properties) {
if (property.isAlias()) {
const auto it = m_scopesById.find(property.typeName());
if (it != m_scopesById.end())
property.setType(QQmlJSScope::ConstPtr(*it));
result->addProperty(property);
} else {
result->addProperty(property);
}
}
for (const auto &method : m_qmlRootScope->methods())
result->addMethod(method);
for (const auto &enumerator : m_qmlRootScope->enums())
result->addEnum(enumerator);
result->resolveTypes(m_rootScopeImports);
result->setSourceLocation(m_qmlRootScope->sourceLocation());
return result;
return m_qmlRootScope;
}
void QQmlJSImportVisitor::importExportedNames(QQmlJSScope::ConstPtr scope)
@ -126,6 +128,11 @@ bool QQmlJSImportVisitor::visit(QQmlJS::AST::UiProgram *)
return true;
}
void QQmlJSImportVisitor::endVisit(UiProgram *)
{
resolveAliases();
}
bool QQmlJSImportVisitor::visit(UiObjectDefinition *definition)
{
QString superType;

View File

@ -59,6 +59,7 @@ public:
protected:
bool visit(QQmlJS::AST::UiProgram *) override;
void endVisit(QQmlJS::AST::UiProgram *) override;
bool visit(QQmlJS::AST::UiObjectDefinition *) override;
void endVisit(QQmlJS::AST::UiObjectDefinition *) override;
bool visit(QQmlJS::AST::UiPublicMember *) override;
@ -97,7 +98,7 @@ protected:
QString m_implicitImportDirectory;
QStringList m_qmltypesFiles;
QQmlJSScope::Ptr m_currentScope;
QQmlJSScope::ConstPtr m_qmlRootScope;
QQmlJSScope::Ptr m_qmlRootScope;
QQmlJSScope::ConstPtr m_globalScope;
QHash<QString, QQmlJSScope::ConstPtr> m_scopesById;
QHash<QString, QQmlJSScope::ConstPtr> m_rootScopeImports;
@ -110,6 +111,7 @@ protected:
void leaveEnvironment();
private:
void resolveAliases();
void visitFunctionExpressionHelper(QQmlJS::AST::FunctionExpression *fexpr);
void importExportedNames(QQmlJSScope::ConstPtr scope);
};

View File

@ -0,0 +1,10 @@
import QtQuick
Item {
Item {
QtObject { id: inner }
property alias innerObj: inner
property string name: innerObj.wrongwrongwrong
}
}

View File

@ -0,0 +1,10 @@
import QtQuick
Item {
Item {
QtObject { id: inner }
property alias innerObj: inner
property string name: innerObj.objectName
}
}

View File

@ -228,6 +228,10 @@ void TestQmllint::dirtyQmlCode_data()
<< QStringLiteral("nanchors3.qml")
<< QString()
<< QString();
QTest::newRow("badAliasObject")
<< QStringLiteral("badAliasObject.qml")
<< QString("Warning: Property \"wrongwrongwrong\" not found on type \"QtObject\"")
<< QString();
}
void TestQmllint::dirtyQmlCode()
@ -287,6 +291,7 @@ void TestQmllint::cleanQmlCode_data()
QTest::newRow("anchors1") << QStringLiteral("anchors1.qml");
QTest::newRow("anchors2") << QStringLiteral("anchors2.qml");
QTest::newRow("optionalImport") << QStringLiteral("optionalImport.qml");
QTest::newRow("goodAliasObject") << QStringLiteral("goodAliasObject.qml");
}
void TestQmllint::cleanQmlCode()