diff options
-rw-r--r-- | src/qmlcompiler/qqmljsimportvisitor.cpp | 2 | ||||
-rw-r--r-- | src/qmlcompiler/qqmljsscope.cpp | 127 | ||||
-rw-r--r-- | src/qmlcompiler/qqmljsscope_p.h | 15 | ||||
-rw-r--r-- | src/qmlcompiler/qqmljstypedescriptionreader.cpp | 2 | ||||
-rw-r--r-- | tests/auto/qml/qmllint/data/ImportWithPrefix.qml | 2 | ||||
-rw-r--r-- | tools/qmllint/checkidentifiers.cpp | 36 |
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") |