aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2021-02-18 11:40:31 +0100
committerUlf Hermann <ulf.hermann@qt.io>2021-02-24 08:33:21 +0100
commit120eb155ef1f0da51c473b080880169a85e5ceb2 (patch)
treeb8bc85734d68f125d424b1f45f2576d20c885a43 /src
parentae68d95b8c1c56ae907cbe88122dd79bafd20b72 (diff)
qmllint: Check for existence of property types
For each binding there should be a property and that property should have a type we recognize. Enums can be property types in C++. We support this by adding child scopes for such enums. The child scopes are then referenced by the QQmlJSMetaEnums and derive from int. The test then reveals that we were missing a few properties in QtQuick.tooling. Add those. Change-Id: I1deef94393ee0e17d34c2dc5980ebfbf25417f36 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> (cherry picked from commit 08c8e8ac3ba8eb23ae5c158990f5d029ac9988ed)
Diffstat (limited to 'src')
-rw-r--r--src/imports/tooling/Component.qml1
-rw-r--r--src/imports/tooling/Parameter.qml1
-rw-r--r--src/qmlcompiler/qqmljsimporter.cpp2
-rw-r--r--src/qmlcompiler/qqmljsimportvisitor.cpp12
-rw-r--r--src/qmlcompiler/qqmljsmetatypes_p.h9
-rw-r--r--src/qmlcompiler/qqmljsscope.cpp54
-rw-r--r--src/qmlcompiler/qqmljsscope_p.h6
7 files changed, 58 insertions, 27 deletions
diff --git a/src/imports/tooling/Component.qml b/src/imports/tooling/Component.qml
index 786e4a99df..942d838900 100644
--- a/src/imports/tooling/Component.qml
+++ b/src/imports/tooling/Component.qml
@@ -55,4 +55,5 @@ QtObject {
property bool isCreatable: name.length > 0
property bool isComposite: false
property string accessSemantics: "reference"
+ property string defaultProperty
}
diff --git a/src/imports/tooling/Parameter.qml b/src/imports/tooling/Parameter.qml
index 108a80098f..a45f9d33ff 100644
--- a/src/imports/tooling/Parameter.qml
+++ b/src/imports/tooling/Parameter.qml
@@ -42,4 +42,5 @@ import QML
QtObject {
required property string name
required property string type
+ property bool isPointer: false
}
diff --git a/src/qmlcompiler/qqmljsimporter.cpp b/src/qmlcompiler/qqmljsimporter.cpp
index 823c0e6f2c..f03c32e2cf 100644
--- a/src/qmlcompiler/qqmljsimporter.cpp
+++ b/src/qmlcompiler/qqmljsimporter.cpp
@@ -235,7 +235,7 @@ void QQmlJSImporter::processImport(
for (auto it = import.objects.begin(); it != import.objects.end(); ++it) {
const auto &val = it.value();
if (val->baseType().isNull()) // Otherwise we have already done it in localFile2ScopeTree()
- val->resolveTypes(types->cppNames);
+ QQmlJSScope::resolveTypes(val, types->cppNames);
}
}
diff --git a/src/qmlcompiler/qqmljsimportvisitor.cpp b/src/qmlcompiler/qqmljsimportvisitor.cpp
index 11ab47e455..08cd9d254c 100644
--- a/src/qmlcompiler/qqmljsimportvisitor.cpp
+++ b/src/qmlcompiler/qqmljsimportvisitor.cpp
@@ -129,13 +129,13 @@ bool QQmlJSImportVisitor::visit(UiObjectDefinition *definition)
if (!m_exportedRootScope)
m_exportedRootScope = m_currentScope;
- m_currentScope->resolveTypes(m_rootScopeImports);
+ QQmlJSScope::resolveTypes(m_currentScope, m_rootScopeImports);
return true;
}
void QQmlJSImportVisitor::endVisit(UiObjectDefinition *)
{
- m_currentScope->resolveTypes(m_rootScopeImports);
+ QQmlJSScope::resolveTypes(m_currentScope, m_rootScopeImports);
leaveEnvironment();
}
@@ -494,13 +494,13 @@ bool QQmlJSImportVisitor::visit(QQmlJS::AST::UiObjectBinding *uiob)
enterEnvironment(QQmlJSScope::QMLScope, name,
uiob->qualifiedTypeNameId->identifierToken);
- m_currentScope->resolveTypes(m_rootScopeImports);
+ QQmlJSScope::resolveTypes(m_currentScope, m_rootScopeImports);
return true;
}
void QQmlJSImportVisitor::endVisit(QQmlJS::AST::UiObjectBinding *uiob)
{
- m_currentScope->resolveTypes(m_rootScopeImports);
+ QQmlJSScope::resolveTypes(m_currentScope, m_rootScopeImports);
const QQmlJSScope::ConstPtr childScope = m_currentScope;
leaveEnvironment();
@@ -541,7 +541,7 @@ bool QQmlJSImportVisitor::visit(ESModule *module)
void QQmlJSImportVisitor::endVisit(ESModule *)
{
- m_exportedRootScope->resolveTypes(m_rootScopeImports);
+ QQmlJSScope::resolveTypes(m_exportedRootScope, m_rootScopeImports);
}
bool QQmlJSImportVisitor::visit(Program *)
@@ -556,7 +556,7 @@ bool QQmlJSImportVisitor::visit(Program *)
void QQmlJSImportVisitor::endVisit(Program *)
{
- m_exportedRootScope->resolveTypes(m_rootScopeImports);
+ QQmlJSScope::resolveTypes(m_exportedRootScope, m_rootScopeImports);
}
QT_END_NAMESPACE
diff --git a/src/qmlcompiler/qqmljsmetatypes_p.h b/src/qmlcompiler/qqmljsmetatypes_p.h
index 0ab56e9503..57328af836 100644
--- a/src/qmlcompiler/qqmljsmetatypes_p.h
+++ b/src/qmlcompiler/qqmljsmetatypes_p.h
@@ -62,6 +62,7 @@ class QQmlJSMetaEnum
QList<int> m_values; // empty if values unknown.
QString m_name;
QString m_alias;
+ QSharedPointer<const QQmlJSScope> m_type;
bool m_isFlag = false;
public:
@@ -89,13 +90,17 @@ public:
int value(const QString &key) const { return m_values.value(m_keys.indexOf(key)); }
bool hasKey(const QString &key) const { return m_keys.indexOf(key) != -1; }
+ QSharedPointer<const QQmlJSScope> type() const { return m_type; }
+ void setType(const QSharedPointer<const QQmlJSScope> &type) { m_type = type; }
+
friend bool operator==(const QQmlJSMetaEnum &a, const QQmlJSMetaEnum &b)
{
return a.m_keys == b.m_keys
&& a.m_values == b.m_values
&& a.m_name == b.m_name
&& a.m_alias == b.m_alias
- && a.m_isFlag == b.m_isFlag;
+ && a.m_isFlag == b.m_isFlag
+ && a.m_type == b.m_type;
}
friend bool operator!=(const QQmlJSMetaEnum &a, const QQmlJSMetaEnum &b)
@@ -105,7 +110,7 @@ public:
friend size_t qHash(const QQmlJSMetaEnum &e, size_t seed = 0)
{
- return qHashMulti(seed, e.m_keys, e.m_values, e.m_name, e.m_alias, e.m_isFlag);
+ return qHashMulti(seed, e.m_keys, e.m_values, e.m_name, e.m_alias, e.m_isFlag, e.m_type);
}
};
diff --git a/src/qmlcompiler/qqmljsscope.cpp b/src/qmlcompiler/qqmljsscope.cpp
index 64fa44ef82..5c3ce8d139 100644
--- a/src/qmlcompiler/qqmljsscope.cpp
+++ b/src/qmlcompiler/qqmljsscope.cpp
@@ -190,7 +190,8 @@ QQmlJSScope::findJSIdentifier(const QString &id) const
return std::optional<JavaScriptIdentifier>{};
}
-void QQmlJSScope::resolveTypes(const QHash<QString, QQmlJSScope::ConstPtr> &contextualTypes)
+void QQmlJSScope::resolveTypes(const QQmlJSScope::Ptr &self,
+ const QHash<QString, QQmlJSScope::ConstPtr> &contextualTypes)
{
auto findType = [&](const QString &name) {
auto type = contextualTypes.constFind(name);
@@ -200,25 +201,46 @@ void QQmlJSScope::resolveTypes(const QHash<QString, QQmlJSScope::ConstPtr> &cont
return QQmlJSScope::ConstPtr();
};
- if (!m_baseType && !m_baseTypeName.isEmpty())
- m_baseType = findType(m_baseTypeName);
+ if (!self->m_baseType && !self->m_baseTypeName.isEmpty())
+ self->m_baseType = findType(self->m_baseTypeName);
- if (!m_attachedType && !m_attachedTypeName.isEmpty())
- m_attachedType = findType(m_attachedTypeName);
+ if (!self->m_attachedType && !self->m_attachedTypeName.isEmpty())
+ self->m_attachedType = findType(self->m_attachedTypeName);
- if (!m_valueType && !m_valueTypeName.isEmpty())
- m_valueType = findType(m_valueTypeName);
+ if (!self->m_valueType && !self->m_valueTypeName.isEmpty())
+ self->m_valueType = findType(self->m_valueTypeName);
- if (!m_extensionType && !m_extensionTypeName.isEmpty())
- m_extensionType = findType(m_extensionTypeName);
+ if (!self->m_extensionType && !self->m_extensionTypeName.isEmpty())
+ self->m_extensionType = findType(self->m_extensionTypeName);
- for (auto it = m_properties.begin(), end = m_properties.end(); it != end; ++it) {
+ const auto intType = findType(QStringLiteral("int"));
+ Q_ASSERT(intType); // There always has to be a builtin "int" type
+ for (auto it = self->m_enumerations.begin(), end = self->m_enumerations.end();
+ it != end; ++it) {
+ auto enumScope = QQmlJSScope::create(EnumScope, self);
+ enumScope->m_baseTypeName = QStringLiteral("int");
+ enumScope->m_baseType = intType;
+ enumScope->m_semantics = AccessSemantics::Value;
+ enumScope->m_internalName = self->internalName() + QStringLiteral("::") + it->name();
+ it->setType(ConstPtr(enumScope));
+ }
+
+ for (auto it = self->m_properties.begin(), end = self->m_properties.end(); it != end; ++it) {
const QString typeName = it->typeName();
- if (!it->type() && !typeName.isEmpty())
- it->setType(findType(typeName));
+ if (it->type() || typeName.isEmpty())
+ continue;
+
+ if (const auto type = findType(typeName)) {
+ it->setType(type);
+ continue;
+ }
+
+ const auto enumeration = self->m_enumerations.find(typeName);
+ if (enumeration != self->m_enumerations.end())
+ it->setType(enumeration->type());
}
- for (auto it = m_methods.begin(), end = m_methods.end(); it != end; ++it) {
+ for (auto it = self->m_methods.begin(), end = self->m_methods.end(); it != end; ++it) {
const QString returnTypeName = it->returnTypeName();
if (!it->returnType() && !returnTypeName.isEmpty())
it->setReturnType(findType(returnTypeName));
@@ -238,11 +260,11 @@ void QQmlJSScope::resolveTypes(const QHash<QString, QQmlJSScope::ConstPtr> &cont
it->setParameterTypes(paramTypes);
}
- for (auto it = m_childScopes.begin(), end = m_childScopes.end(); it != end; ++it) {
+ for (auto it = self->m_childScopes.begin(), end = self->m_childScopes.end(); it != end; ++it) {
QQmlJSScope::Ptr childScope = *it;
switch (childScope->scopeType()) {
case QQmlJSScope::GroupedPropertyScope:
- searchBaseAndExtensionTypes(this, [&](const QQmlJSScope *type) {
+ searchBaseAndExtensionTypes(self.data(), [&](const QQmlJSScope *type) {
const auto propertyIt = type->m_properties.find(childScope->internalName());
if (propertyIt != type->m_properties.end()) {
childScope->m_baseType = QQmlJSScope::ConstPtr(propertyIt->type());
@@ -261,7 +283,7 @@ void QQmlJSScope::resolveTypes(const QHash<QString, QQmlJSScope::ConstPtr> &cont
default:
break;
}
- childScope->resolveTypes(contextualTypes);
+ resolveTypes(childScope, contextualTypes);
}
}
diff --git a/src/qmlcompiler/qqmljsscope_p.h b/src/qmlcompiler/qqmljsscope_p.h
index 8f095cffbf..cbfc109154 100644
--- a/src/qmlcompiler/qqmljsscope_p.h
+++ b/src/qmlcompiler/qqmljsscope_p.h
@@ -96,7 +96,8 @@ public:
JSLexicalScope,
QMLScope,
GroupedPropertyScope,
- AttachedPropertyScope
+ AttachedPropertyScope,
+ EnumScope
};
enum class AccessSemantics {
@@ -260,7 +261,8 @@ public:
return result;
}
- void resolveTypes(const QHash<QString, ConstPtr> &contextualTypes);
+ static void resolveTypes(const QQmlJSScope::Ptr &self,
+ const QHash<QString, ConstPtr> &contextualTypes);
void setSourceLocation(const QQmlJS::SourceLocation &sourceLocation)
{