aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/qmlcompiler/qqmljsimportvisitor.cpp2
-rw-r--r--src/qmlcompiler/qqmljsscope.cpp127
-rw-r--r--src/qmlcompiler/qqmljsscope_p.h15
-rw-r--r--src/qmlcompiler/qqmljstypedescriptionreader.cpp2
-rw-r--r--tests/auto/qml/qmllint/data/ImportWithPrefix.qml2
-rw-r--r--tools/qmllint/checkidentifiers.cpp36
6 files changed, 98 insertions, 86 deletions
diff --git a/src/qmlcompiler/qqmljsimportvisitor.cpp b/src/qmlcompiler/qqmljsimportvisitor.cpp
index 96c5b3b369..d5b5acd06b 100644
--- a/src/qmlcompiler/qqmljsimportvisitor.cpp
+++ b/src/qmlcompiler/qqmljsimportvisitor.cpp
@@ -298,7 +298,7 @@ bool QQmlJSImportVisitor::visit(QQmlJS::AST::UiEnumDeclaration *uied)
qmlEnum.addKey(member->member.toString());
qmlEnum.addValue(int(member->value));
}
- m_currentScope->addEnumeration(qmlEnum);
+ m_currentScope->addOwnEnumeration(qmlEnum);
return true;
}
diff --git a/src/qmlcompiler/qqmljsscope.cpp b/src/qmlcompiler/qqmljsscope.cpp
index 5bca7ffcd4..11a2b4a619 100644
--- a/src/qmlcompiler/qqmljsscope.cpp
+++ b/src/qmlcompiler/qqmljsscope.cpp
@@ -38,6 +38,30 @@
QT_BEGIN_NAMESPACE
+template<typename Action>
+static bool searchBaseAndExtensionTypes(const QQmlJSScope *type, const Action &check)
+{
+ const QQmlJSScope *nonCompositeBase = nullptr;
+ for (const QQmlJSScope *scope = type; scope; scope = scope->baseType().data()) {
+ if (check(scope))
+ return true;
+
+ if (!nonCompositeBase && !scope->isComposite())
+ nonCompositeBase = scope;
+ }
+
+ if (!nonCompositeBase)
+ return false;
+
+ for (const QQmlJSScope *scope = nonCompositeBase->extensionType().data(); scope;
+ scope = scope->baseType().data()) {
+ if (check(scope))
+ return true;
+ }
+
+ return false;
+}
+
QQmlJSScope::QQmlJSScope(ScopeType type, const QQmlJSScope::Ptr &parentScope)
: m_parentScope(parentScope), m_scopeType(type) {}
@@ -78,39 +102,53 @@ 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;
+ return searchBaseAndExtensionTypes(this, [&](const QQmlJSScope *scope) {
+ return scope->m_methods.contains(name);
+ });
}
QList<QQmlJSMetaMethod> QQmlJSScope::methods(const QString &name) const
{
QList<QQmlJSMetaMethod> results;
- const QQmlJSScope *nonCompositeBase = isComposite() ? this : nullptr;
- for (const QQmlJSScope *scope = this; scope; scope = scope->baseType().data()) {
+ searchBaseAndExtensionTypes(this, [&](const QQmlJSScope *scope) {
results.append(scope->ownMethods(name));
- if (!nonCompositeBase && !scope->isComposite())
- nonCompositeBase = scope;
- }
+ return false;
+ });
+ return results;
+}
- if (nonCompositeBase && nonCompositeBase != this) {
- if (QQmlJSScope::ConstPtr extension = nonCompositeBase->extensionType())
- results.append(extension->methods(name));
- }
+bool QQmlJSScope::hasEnumeration(const QString &name) const
+{
+ return searchBaseAndExtensionTypes(this, [&](const QQmlJSScope *scope) {
+ return scope->m_enumerations.contains(name);
+ });
+}
- return results;
+bool QQmlJSScope::hasEnumerationKey(const QString &name) const
+{
+ return searchBaseAndExtensionTypes(this, [&](const QQmlJSScope *scope) {
+ for (const auto &e : scope->m_enumerations) {
+ if (e.keys().contains(name))
+ return true;
+ }
+ return false;
+ });
+}
+
+QQmlJSMetaEnum QQmlJSScope::enumeration(const QString &name) const
+{
+ QQmlJSMetaEnum result;
+
+ searchBaseAndExtensionTypes(this, [&](const QQmlJSScope *scope) {
+ const auto it = scope->m_enumerations.find(name);
+ if (it == scope->m_enumerations.end())
+ return false;
+ result = *it;
+ return true;
+ });
+
+ return result;
}
bool QQmlJSScope::isIdInCurrentQmlScopes(const QString &id) const
@@ -262,41 +300,22 @@ 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;
+ return searchBaseAndExtensionTypes(this, [&](const QQmlJSScope *scope) {
+ return scope->m_properties.contains(name);
+ });
}
QQmlJSMetaProperty QQmlJSScope::property(const QString &name) const
{
- const QQmlJSScope *nonCompositeBase = isComposite() ? this : nullptr;
- for (const QQmlJSScope *scope = this; scope; scope = scope->baseType().data()) {
+ QQmlJSMetaProperty prop;
+ searchBaseAndExtensionTypes(this, [&](const QQmlJSScope *scope) {
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 {};
+ if (it == scope->m_properties.end())
+ return false;
+ prop = *it;
+ return true;
+ });
+ return prop;
}
QQmlJSScope::Export::Export(QString package, QString type, const QTypeRevision &version) :
diff --git a/src/qmlcompiler/qqmljsscope_p.h b/src/qmlcompiler/qqmljsscope_p.h
index 4e16f45930..9cb08c655e 100644
--- a/src/qmlcompiler/qqmljsscope_p.h
+++ b/src/qmlcompiler/qqmljsscope_p.h
@@ -175,13 +175,14 @@ public:
bool hasMethod(const QString &name) const;
QList<QQmlJSMetaMethod> methods(const QString &name) const;
- void addEnumeration(const QQmlJSMetaEnum &enumeration)
- {
- m_enumerations.insert(enumeration.name(), enumeration);
- }
- QHash<QString, QQmlJSMetaEnum> enumerations() const { return m_enumerations; }
- QQmlJSMetaEnum enumeration(const QString &name) const { return m_enumerations.value(name); }
- bool hasEnumeration(const QString &name) const { return m_enumerations.contains(name); }
+ void addOwnEnumeration(const QQmlJSMetaEnum &enumeration) { m_enumerations.insert(enumeration.name(), enumeration); }
+ QHash<QString, QQmlJSMetaEnum> ownEnumerations() const { return m_enumerations; }
+ QQmlJSMetaEnum ownEnumeration(const QString &name) const { return m_enumerations.value(name); }
+ bool hasOwnEnumeration(const QString &name) const { return m_enumerations.contains(name); }
+
+ bool hasEnumeration(const QString &name) const;
+ bool hasEnumerationKey(const QString &name) const;
+ QQmlJSMetaEnum enumeration(const QString &name) const;
QString fileName() const { return m_fileName; }
void setFileName(const QString &file) { m_fileName = file; }
diff --git a/src/qmlcompiler/qqmljstypedescriptionreader.cpp b/src/qmlcompiler/qqmljstypedescriptionreader.cpp
index b1a1d18bfe..b3ef6092a0 100644
--- a/src/qmlcompiler/qqmljstypedescriptionreader.cpp
+++ b/src/qmlcompiler/qqmljstypedescriptionreader.cpp
@@ -390,7 +390,7 @@ void QQmlJSTypeDescriptionReader::readEnum(UiObjectDefinition *ast, const QQmlJS
}
}
- scope->addEnumeration(metaEnum);
+ scope->addOwnEnumeration(metaEnum);
}
void QQmlJSTypeDescriptionReader::readParameter(UiObjectDefinition *ast, QQmlJSMetaMethod *metaMethod)
diff --git a/tests/auto/qml/qmllint/data/ImportWithPrefix.qml b/tests/auto/qml/qmllint/data/ImportWithPrefix.qml
index 6d070da21a..e42a052187 100644
--- a/tests/auto/qml/qmllint/data/ImportWithPrefix.qml
+++ b/tests/auto/qml/qmllint/data/ImportWithPrefix.qml
@@ -1,5 +1,7 @@
+import QtQml
import "." as MyStuff
MyStuff.Simple {
property bool something: contains(Qt.point(12, 34))
+ property int other: Qt.AlignBottom
}
diff --git a/tools/qmllint/checkidentifiers.cpp b/tools/qmllint/checkidentifiers.cpp
index 90456f97aa..0517f67ed5 100644
--- a/tools/qmllint/checkidentifiers.cpp
+++ b/tools/qmllint/checkidentifiers.cpp
@@ -56,10 +56,7 @@ private:
};
static const QStringList unknownBuiltins = {
- // TODO: "string" should be added to builtins.qmltypes, and the special handling below removed
QStringLiteral("alias"), // TODO: we cannot properly resolve aliases, yet
- QStringLiteral("QRectF"), // TODO: should be added to builtins.qmltypes
- QStringLiteral("QFont"), // TODO: should be added to builtins.qmltypes
QStringLiteral("QJSValue"), // We cannot say anything intelligent about untyped JS values.
QStringLiteral("variant"), // Same for generic variants
};
@@ -208,22 +205,19 @@ bool CheckIdentifiers::checkMemberAccess(const QVector<FieldMember> &members,
return true; // Access to property of JS function
auto checkEnums = [&](const QQmlJSScope::ConstPtr &scope) {
- const auto enums = scope->enumerations();
- for (const auto &enumerator : enums) {
- if (enumerator.name() == access.m_name) {
- detectedRestrictiveKind = QLatin1String("enum");
- detectedRestrictiveName = access.m_name;
- expectedNext.append(enumerator.keys());
- return true;
- }
- for (const QString &key : enumerator.keys()) {
- if (access.m_name == key) {
- detectedRestrictiveKind = QLatin1String("enum");
- detectedRestrictiveName = access.m_name;
- return true;
- }
- }
+ if (scope->hasEnumeration(access.m_name)) {
+ detectedRestrictiveKind = QLatin1String("enum");
+ detectedRestrictiveName = access.m_name;
+ expectedNext.append(scope->enumeration(access.m_name).keys());
+ return true;
}
+
+ if (scope->hasEnumerationKey(access.m_name)) {
+ detectedRestrictiveKind = QLatin1String("enum");
+ detectedRestrictiveName = access.m_name;
+ return true;
+ }
+
return false;
};
@@ -360,10 +354,6 @@ bool CheckIdentifiers::operator()(
continue;
}
- // TODO: Lots of builtins are missing
- if (memberAccessBase.m_name == QLatin1String("Qt"))
- continue;
-
const auto typeIt = m_types.find(memberAccessBase.m_name);
if (typeIt != m_types.end()) {
if (typeIt->isNull()) {
@@ -389,7 +379,7 @@ bool CheckIdentifiers::operator()(
const auto firstElement = root->childScopes()[0];
if (firstElement->hasProperty(memberAccessBase.m_name)
|| firstElement->hasMethod(memberAccessBase.m_name)
- || firstElement->enumerations().contains(memberAccessBase.m_name)) {
+ || firstElement->hasEnumeration(memberAccessBase.m_name)) {
m_colorOut->writePrefixedMessage(
memberAccessBase.m_name
+ QLatin1String(" is a member of the root element\n")