qmllint: Resolve generalized grouped properties
Change-Id: I4c407e2332823f1a4274f55b07635d50dc0186ed Reviewed-by: Maximilian Goldstein <max.goldstein@qt.io>
This commit is contained in:
parent
85b5413dc4
commit
8591568c75
|
@ -155,7 +155,12 @@ void QQmlJSImportVisitor::leaveEnvironment()
|
|||
m_currentScope = m_currentScope->parentScope();
|
||||
}
|
||||
|
||||
void QQmlJSImportVisitor::resolveAliases()
|
||||
static bool mayBeUnresolvedGeneralizedGroupedProperty(const QQmlJSScope::ConstPtr &scope)
|
||||
{
|
||||
return scope->scopeType() == QQmlJSScope::GroupedPropertyScope && !scope->baseType();
|
||||
}
|
||||
|
||||
void QQmlJSImportVisitor::resolveAliasesAndIds()
|
||||
{
|
||||
QQueue<QQmlJSScope::Ptr> objects;
|
||||
objects.enqueue(m_exportedRootScope);
|
||||
|
@ -234,8 +239,19 @@ void QQmlJSImportVisitor::resolveAliases()
|
|||
}
|
||||
|
||||
const auto childScopes = object->childScopes();
|
||||
for (const auto &childScope : childScopes)
|
||||
for (const auto &childScope : childScopes) {
|
||||
if (mayBeUnresolvedGeneralizedGroupedProperty(childScope)) {
|
||||
const QString name = childScope->internalName();
|
||||
if (object->isNameDeferred(name)) {
|
||||
auto it = m_scopesById.find(name);
|
||||
if (it != m_scopesById.end()) {
|
||||
QQmlJSScope::resolveGeneralizedGroup(
|
||||
childScope, *it, m_rootScopeImports, &m_usedTypes);
|
||||
}
|
||||
}
|
||||
}
|
||||
objects.enqueue(childScope);
|
||||
}
|
||||
|
||||
if (doRequeue)
|
||||
requeue.enqueue(object);
|
||||
|
@ -349,8 +365,6 @@ void QQmlJSImportVisitor::endVisit(UiProgram *)
|
|||
for (const auto &scope : m_objectDefinitionScopes) {
|
||||
if (checkInheritanceCycle(scope) == CycleFound)
|
||||
return;
|
||||
|
||||
checkGroupedAndAttachedScopes(scope);
|
||||
}
|
||||
|
||||
for (const auto &scope : m_pendingDefaultProperties.keys()) {
|
||||
|
@ -358,7 +372,11 @@ void QQmlJSImportVisitor::endVisit(UiProgram *)
|
|||
return;
|
||||
}
|
||||
|
||||
resolveAliases();
|
||||
resolveAliasesAndIds();
|
||||
|
||||
for (const auto &scope : m_objectDefinitionScopes)
|
||||
checkGroupedAndAttachedScopes(scope);
|
||||
|
||||
processDefaultProperties();
|
||||
processPropertyTypes();
|
||||
processPropertyBindings();
|
||||
|
|
|
@ -261,7 +261,7 @@ protected:
|
|||
|
||||
private:
|
||||
void importBaseModules();
|
||||
void resolveAliases();
|
||||
void resolveAliasesAndIds();
|
||||
void visitFunctionExpressionHelper(QQmlJS::AST::FunctionExpression *fexpr);
|
||||
void processImportWarnings(const QString &what, const QQmlJS::SourceLocation &srcLocation = QQmlJS::SourceLocation());
|
||||
void addImportWithLocation(const QString &name, const QQmlJS::SourceLocation &loc);
|
||||
|
|
|
@ -432,6 +432,14 @@ void QQmlJSScope::resolveEnums(const QQmlJSScope::Ptr &self,
|
|||
}
|
||||
}
|
||||
|
||||
void QQmlJSScope::resolveGeneralizedGroup(const Ptr &self, const ConstPtr &baseType,
|
||||
const QHash<QString, ConstPtr> &contextualTypes,
|
||||
QSet<QString> *usedTypes)
|
||||
{
|
||||
self->m_baseType = baseType;
|
||||
resolveNonEnumTypes(self, contextualTypes, usedTypes);
|
||||
}
|
||||
|
||||
QQmlJSScope::ConstPtr QQmlJSScope::findCurrentQMLScope(const QQmlJSScope::ConstPtr &scope)
|
||||
{
|
||||
auto qmlScope = scope;
|
||||
|
|
|
@ -340,6 +340,10 @@ public:
|
|||
static void resolveEnums(const QQmlJSScope::Ptr &self,
|
||||
const QHash<QString, QQmlJSScope::ConstPtr> &contextualTypes,
|
||||
QSet<QString> *usedTypes = nullptr);
|
||||
static void resolveGeneralizedGroup(const QQmlJSScope::Ptr &self,
|
||||
const QQmlJSScope::ConstPtr &baseType,
|
||||
const QHash<QString, ConstPtr> &contextualTypes,
|
||||
QSet<QString> *usedTypes = nullptr);
|
||||
|
||||
void setSourceLocation(const QQmlJS::SourceLocation &sourceLocation)
|
||||
{
|
||||
|
|
|
@ -38,6 +38,14 @@ Module {
|
|||
Property { name: "contentData"; type: "QObject"; isList: true; isReadonly: true }
|
||||
Property { name: "contentChildren"; type: "QQuickItem"; isList: true; isReadonly: true }
|
||||
}
|
||||
Component {
|
||||
name: "WithImmediate"
|
||||
prototype: "QObject"
|
||||
exports: ["Things/WithImmediate 1.0"]
|
||||
exportMetaObjectRevisions: [256]
|
||||
immediateNames: ["contentData"]
|
||||
Property { name: "contentData"; type: "double" }
|
||||
}
|
||||
Component {
|
||||
name: "MyScreen"
|
||||
prototype: "QObject"
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
import QtQuick
|
||||
import Things
|
||||
|
||||
Item {
|
||||
id: self
|
||||
WithImmediate {
|
||||
self.aaaa: 15 - 1
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
import QtQuick
|
||||
import Things
|
||||
|
||||
Item {
|
||||
id: self
|
||||
WithImmediate {
|
||||
aself.x: 15 - 1
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
import QtQuick
|
||||
import Things
|
||||
|
||||
Item {
|
||||
id: self
|
||||
WithImmediate {
|
||||
self.x: 15 - 1
|
||||
}
|
||||
}
|
|
@ -705,6 +705,15 @@ void TestQmllint::dirtyQmlCode_data()
|
|||
<< QStringLiteral("cycleHead.qml")
|
||||
<< QStringLiteral("MenuItem is part of an inheritance cycle: MenuItem -> MenuItem")
|
||||
<< QString() << false;
|
||||
QTest::newRow("badGeneralizedGroup1")
|
||||
<< QStringLiteral("badGeneralizedGroup1.qml")
|
||||
<< QStringLiteral("Binding assigned to \"aaaa\", "
|
||||
"but no property \"aaaa\" exists in the current element")
|
||||
<< QString() << false;
|
||||
QTest::newRow("badGeneralizedGroup2")
|
||||
<< QStringLiteral("badGeneralizedGroup2.qml")
|
||||
<< QStringLiteral("unknown grouped property scope aself")
|
||||
<< QString() << false;
|
||||
}
|
||||
|
||||
void TestQmllint::dirtyQmlCode()
|
||||
|
@ -859,6 +868,7 @@ void TestQmllint::cleanQmlCode_data()
|
|||
QTest::newRow("bytearray") << QStringLiteral("bytearray.qml");
|
||||
QTest::newRow("initReadonly") << QStringLiteral("initReadonly.qml");
|
||||
QTest::newRow("connectionNoParent") << QStringLiteral("connectionNoParent.qml"); // QTBUG-97600
|
||||
QTest::newRow("goodGeneralizedGroup") << QStringLiteral("goodGeneralizedGroup.qml");
|
||||
}
|
||||
|
||||
void TestQmllint::cleanQmlCode()
|
||||
|
|
Loading…
Reference in New Issue