diff options
-rw-r--r-- | src/imports/builtins/builtins.qmltypes | 101 | ||||
-rw-r--r-- | src/labs/sharedimage/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/qml/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/qml/Qt6QmlBuildInternals.cmake | 2 | ||||
-rw-r--r-- | src/qml/Qt6QmlMacros.cmake | 17 | ||||
-rw-r--r-- | src/qml/qml/qqmlcomponent.h | 1 | ||||
-rw-r--r-- | src/qml/qml/qqmlengine_p.h | 2 | ||||
-rw-r--r-- | src/qml/qmldirparser/qqmldirparser.cpp | 10 | ||||
-rw-r--r-- | src/qml/qmldirparser/qqmldirparser_p.h | 4 | ||||
-rw-r--r-- | src/qmlcompiler/qqmljsimporter.cpp | 32 | ||||
-rw-r--r-- | src/qmlcompiler/qqmljsimporter_p.h | 16 | ||||
-rw-r--r-- | src/qmlcompiler/qqmljsimportvisitor.cpp | 18 | ||||
-rw-r--r-- | src/qmlcompiler/qqmljsimportvisitor_p.h | 2 | ||||
-rw-r--r-- | src/qmltyperegistrar/qmltypesclassdescription.cpp | 5 | ||||
-rw-r--r-- | src/qmltyperegistrar/qmltypesclassdescription.h | 2 | ||||
-rw-r--r-- | src/qmltyperegistrar/qmltypescreator.cpp | 83 | ||||
-rw-r--r-- | tests/auto/qml/qmllint/data/qobjectHasOwnProperty.qml | 7 | ||||
-rw-r--r-- | tests/auto/qml/qmllint/data/unused_static.qml | 4 | ||||
-rw-r--r-- | tests/auto/qml/qmllint/tst_qmllint.cpp | 2 |
19 files changed, 202 insertions, 108 deletions
diff --git a/src/imports/builtins/builtins.qmltypes b/src/imports/builtins/builtins.qmltypes index 23defaa55b..0bc89d8c9c 100644 --- a/src/imports/builtins/builtins.qmltypes +++ b/src/imports/builtins/builtins.qmltypes @@ -23,61 +23,118 @@ Module { } Component { + file: "private/qqmlengine_p.h" name: "QObject" + extension: "Object" accessSemantics: "reference" exports: ["QML/QtObject 1.0"] exportMetaObjectRevisions: [256] - - Method { - name: "toString" + Property { + name: "objectName" type: "QString" + bindable: "bindableObjectName" + read: "objectName" + write: "setObjectName" + notify: "objectNameChanged" + index: 0 + } + Signal { + name: "objectNameChanged" + Parameter { name: "objectName"; type: "QString" } } - Method { - name: "destroy" + name: "_q_reregisterTimers" + Parameter { type: "void"; isPointer: true } } - + Method { name: "toString"; type: "string" } + Method { name: "destroy" } Method { name: "destroy" - - Parameter { - name: "delay" - type: "int" - } + Parameter { name: "delay"; type: "int" } } } Component { + file: "qqmlcomponent.h" name: "QQmlComponent" accessSemantics: "reference" prototype: "QObject" exports: ["QML/Component 1.0"] exportMetaObjectRevisions: [256] - + attachedType: "QQmlComponentAttached" + Enum { + name: "CompilationMode" + values: ["PreferSynchronous", "Asynchronous"] + } Enum { name: "Status" values: ["Null", "Ready", "Loading", "Error"] } - + Property { + name: "progress" + type: "double" + read: "progress" + notify: "progressChanged" + index: 0 + isReadonly: true + } Property { name: "status" type: "Status" + read: "status" + notify: "statusChanged" + index: 1 isReadonly: true } - + Property { name: "url"; type: "QUrl"; read: "url"; index: 2; isReadonly: true } Signal { name: "statusChanged" - - Parameter { - type: "QQmlComponent::Status" - } - + Parameter { type: "QQmlComponent::Status" } + } + Signal { + name: "progressChanged" + Parameter { type: "double" } } - Method { - name: "errorString" - type: "QString" + name: "loadUrl" + Parameter { name: "url"; type: "QUrl" } + } + Method { + name: "loadUrl" + Parameter { name: "url"; type: "QUrl" } + Parameter { name: "mode"; type: "CompilationMode" } + } + Method { + name: "setData" + Parameter { type: "QByteArray" } + Parameter { name: "baseUrl"; type: "QUrl" } } + Method { name: "errorString"; type: "QString" } + Method { name: "createObject"; isJavaScriptFunction: true } + Method { + name: "createObject" + type: "QObject" + isPointer: true + Parameter { name: "parent"; type: "QObject"; isPointer: true } + Parameter { name: "properties"; type: "QVariantMap" } + } + Method { + name: "createObject" + type: "QObject" + isPointer: true + Parameter { name: "parent"; type: "QObject"; isPointer: true } + } + Method { name: "createObject"; type: "QObject"; isPointer: true } + Method { name: "incubateObject"; isJavaScriptFunction: true } + } + + Component { + file: "private/qqmlcomponentattached_p.h" + name: "QQmlComponentAttached" + accessSemantics: "reference" + prototype: "QObject" + Signal { name: "completed" } + Signal { name: "destruction" } } Component { diff --git a/src/labs/sharedimage/CMakeLists.txt b/src/labs/sharedimage/CMakeLists.txt index 0dec607ac2..5acfb3dddf 100644 --- a/src/labs/sharedimage/CMakeLists.txt +++ b/src/labs/sharedimage/CMakeLists.txt @@ -1,6 +1,7 @@ qt_internal_add_qml_module(LabsSharedImage URI "Qt.labs.sharedimage" VERSION "${PROJECT_VERSION}" + __QT_INTERNAL_STATIC_MODULE PLUGIN_TARGET sharedimageplugin NO_PLUGIN_OPTIONAL NO_GENERATE_PLUGIN_SOURCE diff --git a/src/qml/CMakeLists.txt b/src/qml/CMakeLists.txt index 046e29fdcd..3c08c6f9c5 100644 --- a/src/qml/CMakeLists.txt +++ b/src/qml/CMakeLists.txt @@ -32,6 +32,7 @@ qt_internal_add_qml_module(Qml URI "QtQml" VERSION "${PROJECT_VERSION}" DESIGNER_SUPPORTED + __QT_INTERNAL_SYSTEM_MODULE PLUGIN_TARGET qmlplugin CLASS_NAME QtQmlPlugin IMPORTS ${module_dynamic_qml_imports} diff --git a/src/qml/Qt6QmlBuildInternals.cmake b/src/qml/Qt6QmlBuildInternals.cmake index 4b6a144b0e..13cc64cad7 100644 --- a/src/qml/Qt6QmlBuildInternals.cmake +++ b/src/qml/Qt6QmlBuildInternals.cmake @@ -18,6 +18,8 @@ macro(qt_internal_get_internal_add_qml_module_keywords NO_GENERATE_QMLDIR NO_LINT NO_CACHEGEN + __QT_INTERNAL_STATIC_MODULE + __QT_INTERNAL_SYSTEM_MODULE ) set(${single_args} URI diff --git a/src/qml/Qt6QmlMacros.cmake b/src/qml/Qt6QmlMacros.cmake index e2bef207d3..d3e9ac0e03 100644 --- a/src/qml/Qt6QmlMacros.cmake +++ b/src/qml/Qt6QmlMacros.cmake @@ -32,6 +32,11 @@ function(qt6_add_qml_module target) # Used only by _qt_internal_qml_type_registration() # TODO: Remove this once qt6_extract_metatypes does not install by default. __QT_INTERNAL_INSTALL_METATYPES_JSON + + # Used to mark modules as having static side effects (i.e. if they install an image provider) + __QT_INTERNAL_STATIC_MODULE + # Used to mark modules as being a system module that provides all builtins + __QT_INTERNAL_SYSTEM_MODULE ) set(args_single @@ -453,6 +458,8 @@ function(qt6_add_qml_module target) _qt_qml_module_installed_plugin_target "${arg_INSTALLED_PLUGIN_TARGET}" QT_QML_MODULE_DESIGNER_SUPPORTED "${arg_DESIGNER_SUPPORTED}" + QT_QML_MODULE_IS_STATIC "${arg___QT_INTERNAL_STATIC_MODULE}" + QT_QML_MODULE_IS_SYSTEM "${arg___QT_INTERNAL_SYSTEM_MODULE}" QT_QML_MODULE_OUTPUT_DIRECTORY "${arg_OUTPUT_DIRECTORY}" QT_QML_MODULE_RESOURCE_PREFIX "${qt_qml_module_resource_prefix}" QT_QML_MODULE_PAST_MAJOR_VERSIONS "${arg_PAST_MAJOR_VERSIONS}" @@ -954,6 +961,16 @@ function(_qt_internal_target_generate_qmldir target) string(APPEND content "designersupported\n") endif() + get_target_property(static_module ${target} QT_QML_MODULE_IS_STATIC) + if (static_module) + string(APPEND content "static\n") + endif() + + get_target_property(system_module ${target} QT_QML_MODULE_IS_SYSTEM) + if (system_module) + string(APPEND content "system\n") + endif() + _qt_internal_qmldir_item(typeinfo QT_QML_MODULE_TYPEINFO) _qt_internal_qmldir_item_list(import QT_QML_MODULE_IMPORTS) diff --git a/src/qml/qml/qqmlcomponent.h b/src/qml/qml/qqmlcomponent.h index d60c2cdc9f..e70dae5de8 100644 --- a/src/qml/qml/qqmlcomponent.h +++ b/src/qml/qml/qqmlcomponent.h @@ -73,6 +73,7 @@ class Q_QML_EXPORT QQmlComponent : public QObject QML_NAMED_ELEMENT(Component) QML_ADDED_IN_VERSION(2, 0) QML_ATTACHED(QQmlComponentAttached) + Q_CLASSINFO("QML.OmitFromQmlTypes", "true") public: enum CompilationMode { PreferSynchronous, Asynchronous }; diff --git a/src/qml/qml/qqmlengine_p.h b/src/qml/qml/qqmlengine_p.h index 630d32736b..58bc61dcf0 100644 --- a/src/qml/qml/qqmlengine_p.h +++ b/src/qml/qml/qqmlengine_p.h @@ -96,7 +96,7 @@ struct QObjectForeign { QML_FOREIGN(QObject) QML_NAMED_ELEMENT(QtObject) QML_ADDED_IN_VERSION(2, 0) - Q_CLASSINFO("QML.Root", "QML") + Q_CLASSINFO("QML.OmitFromQmlTypes", "true") }; // This needs to be declared here so that the pool for it can live in QQmlEnginePrivate. diff --git a/src/qml/qmldirparser/qqmldirparser.cpp b/src/qml/qmldirparser/qqmldirparser.cpp index 183fa918d2..bb9036582e 100644 --- a/src/qml/qmldirparser/qqmldirparser.cpp +++ b/src/qml/qmldirparser/qqmldirparser.cpp @@ -296,6 +296,16 @@ bool QQmlDirParser::parse(const QString &source) reportError(lineNumber, 0, QStringLiteral("designersupported does not expect any argument")); else _designerSupported = true; + } else if (sections[0] == QLatin1String("static")) { + if (sectionCount != 1) + reportError(lineNumber, 0, QStringLiteral("static does not expect any argument")); + else + _isStaticModule = true; + } else if (sections[0] == QLatin1String("system")) { + if (sectionCount != 1) + reportError(lineNumber, 0, QStringLiteral("system does not expect any argument")); + else + _isSystemModule = true; } else if (sections[0] == QLatin1String("import") || sections[0] == QLatin1String("depends")) { if (!readImport(sections, sectionCount, Import::Default)) diff --git a/src/qml/qmldirparser/qqmldirparser_p.h b/src/qml/qmldirparser/qqmldirparser_p.h index fe371e6b4f..51d4d75323 100644 --- a/src/qml/qmldirparser/qqmldirparser_p.h +++ b/src/qml/qmldirparser/qqmldirparser_p.h @@ -157,6 +157,8 @@ public: QList<Script> scripts() const { return _scripts; } QList<Plugin> plugins() const { return _plugins; } bool designerSupported() const { return _designerSupported; } + bool isStaticModule() const { return _isStaticModule; } + bool isSystemModule() const { return _isSystemModule; } QStringList typeInfos() const { return _typeInfos; } QStringList classNames() const { return _classNames; } @@ -177,6 +179,8 @@ private: QList<Script> _scripts; QList<Plugin> _plugins; bool _designerSupported = false; + bool _isStaticModule = false; + bool _isSystemModule = false; QStringList _typeInfos; QStringList _classNames; QString _linkTarget; diff --git a/src/qmlcompiler/qqmljsimporter.cpp b/src/qmlcompiler/qqmljsimporter.cpp index e14fa7a52d..757830448e 100644 --- a/src/qmlcompiler/qqmljsimporter.cpp +++ b/src/qmlcompiler/qqmljsimporter.cpp @@ -146,6 +146,9 @@ QQmlJSImporter::Import QQmlJSImporter::readQmldir(const QString &path) { Import result; auto reader = createQmldirParserForFile(path + SlashQmldir); + result.name = reader.typeNamespace(); + result.isStaticModule = reader.isStaticModule(); + result.isSystemModule = reader.isSystemModule(); result.imports.append(reader.imports()); result.dependencies.append(reader.dependencies()); @@ -354,6 +357,14 @@ void QQmlJSImporter::processImport(const QQmlJSScope::Import &importDescription, if (!importDescription.prefix().isEmpty()) types->qmlNames.insert(importDescription.prefix(), {}); // Empty type means "this is the prefix" + if (!importDescription.isDependency()) { + if (import.isStaticModule) + types->staticModules << import.name; + + if (import.isSystemModule) + types->hasSystemModule = true; + } + for (auto it = import.scripts.begin(); it != import.scripts.end(); ++it) { types->cppNames.insert(prefixedName(anonPrefix, internalName(it->scope)), it->scope); // You cannot have a script without an export @@ -520,10 +531,13 @@ void QQmlJSImporter::importQmldirs(const QStringList &qmldirFiles) } } -QQmlJSImporter::ImportedTypes QQmlJSImporter::importModule( - const QString &module, const QString &prefix, QTypeRevision version) +QQmlJSImporter::ImportedTypes QQmlJSImporter::importModule(const QString &module, + const QString &prefix, + QTypeRevision version, + QStringList *staticModuleList) { - AvailableTypes result(builtinImportHelper().cppNames); + const AvailableTypes builtins = builtinImportHelper(); + AvailableTypes result(builtins.cppNames); if (!importHelper(module, &result, prefix, version)) { m_warnings.append({ QStringLiteral("Failed to import %1. Are your include paths set up properly?").arg(module), @@ -531,6 +545,16 @@ QQmlJSImporter::ImportedTypes QQmlJSImporter::importModule( QQmlJS::SourceLocation() }); } + + // If we imported a system module add all builtin QML types + if (result.hasSystemModule) { + for (const QString &name : builtins.qmlNames.keys()) + result.qmlNames.insert(prefixedName(prefix, name), builtins.qmlNames[name]); + } + + if (staticModuleList) + *staticModuleList << result.staticModules; + return result.qmlNames; } @@ -558,6 +582,8 @@ bool QQmlJSImporter::importHelper(const QString &module, AvailableTypes *types, const auto &cacheEntry = m_cachedImportTypes[cacheKey]; types->cppNames.insert(cacheEntry->cppNames); + types->staticModules << cacheEntry->staticModules; + types->hasSystemModule = cacheEntry->hasSystemModule; // No need to import qml names for dependencies if (!isDependency) diff --git a/src/qmlcompiler/qqmljsimporter_p.h b/src/qmlcompiler/qqmljsimporter_p.h index fdadcf6c3b..4cc22f4cfe 100644 --- a/src/qmlcompiler/qqmljsimporter_p.h +++ b/src/qmlcompiler/qqmljsimporter_p.h @@ -65,9 +65,9 @@ public: QQmlJSScope::Ptr importFile(const QString &file); ImportedTypes importDirectory(const QString &directory, const QString &prefix = QString()); - ImportedTypes importModule( - const QString &module, const QString &prefix = QString(), - QTypeRevision version = QTypeRevision()); + ImportedTypes importModule(const QString &module, const QString &prefix = QString(), + QTypeRevision version = QTypeRevision(), + QStringList *staticModuleList = nullptr); ImportedTypes builtinInternalNames(); @@ -97,9 +97,19 @@ private: // Names the importing component sees, including any prefixes QHash<QString, QQmlJSScope::ConstPtr> qmlNames; + + // Static modules included here + QStringList staticModules; + + // Whether a system module has been imported + bool hasSystemModule = false; }; struct Import { + QString name; + bool isStaticModule; + bool isSystemModule; + QHash<QString, QQmlJSExportedScope> objects; QHash<QString, QQmlJSExportedScope> scripts; QList<QQmlDirParser::Import> imports; diff --git a/src/qmlcompiler/qqmljsimportvisitor.cpp b/src/qmlcompiler/qqmljsimportvisitor.cpp index 6d7fe4807c..4efc722d5e 100644 --- a/src/qmlcompiler/qqmljsimportvisitor.cpp +++ b/src/qmlcompiler/qqmljsimportvisitor.cpp @@ -398,6 +398,9 @@ void QQmlJSImportVisitor::endVisit(UiProgram *) break; } + for (const QQmlJS::SourceLocation &import : m_importStaticModuleLocationMap.values()) + unusedImports.remove(import); + for (const auto &import : unusedImports) { m_logger->logInfo(QString::fromLatin1("Unused import at %1:%2:%3") .arg(m_logger->fileName()) @@ -1715,13 +1718,26 @@ bool QQmlJSImportVisitor::visit(QQmlJS::AST::UiImport *import) } path.chop(1); + QStringList staticModulesProvided; + const auto imported = m_importer->importModule( - path, prefix, import->version ? import->version->version : QTypeRevision()); + path, prefix, import->version ? import->version->version : QTypeRevision(), + &staticModulesProvided); m_rootScopeImports.insert(imported); for (const QString &key : imported.keys()) addImportLocation(key); + if (prefix.isEmpty()) { + for (const QString &staticModule : staticModulesProvided) { + // Always prefer a direct import of static module to it being imported as a dependency + if (path != staticModule && m_importStaticModuleLocationMap.contains(staticModule)) + continue; + + m_importStaticModuleLocationMap[staticModule] = import->firstSourceLocation(); + } + } + processImportWarnings(QStringLiteral("module \"%1\"").arg(path), import->firstSourceLocation()); return true; } diff --git a/src/qmlcompiler/qqmljsimportvisitor_p.h b/src/qmlcompiler/qqmljsimportvisitor_p.h index c5175fac2a..5a5256a98c 100644 --- a/src/qmlcompiler/qqmljsimportvisitor_p.h +++ b/src/qmlcompiler/qqmljsimportvisitor_p.h @@ -167,6 +167,8 @@ protected: // Maps all qmlNames to the source location of their import QMultiHash<QString, QQmlJS::SourceLocation> m_importTypeLocationMap; + // Maps all static modules to the source location of their import + QMultiHash<QString, QQmlJS::SourceLocation> m_importStaticModuleLocationMap; // Contains all import source locations (could be extracted from above but that is expensive) QSet<QQmlJS::SourceLocation> m_importLocations; // A set of all types that have been used during type resolution diff --git a/src/qmltyperegistrar/qmltypesclassdescription.cpp b/src/qmltyperegistrar/qmltypesclassdescription.cpp index 369b42fbd9..fb01a48013 100644 --- a/src/qmltyperegistrar/qmltypesclassdescription.cpp +++ b/src/qmltyperegistrar/qmltypesclassdescription.cpp @@ -180,8 +180,9 @@ void QmlTypesClassDescription::collect( isSingleton = true; } else if (name == QLatin1String("QML.Foreign")) { foreignTypeName = value; - } else if (name == QLatin1String("QML.Root")) { - isRootClass = true; + } else if (name == QLatin1String("QML.OmitFromQmlTypes")) { + if (value == QLatin1String("true")) + omitFromQmlTypes = true; } else if (name == QLatin1String("QML.HasCustomParser")) { if (value == QLatin1String("true")) hasCustomParser = true; diff --git a/src/qmltyperegistrar/qmltypesclassdescription.h b/src/qmltyperegistrar/qmltypesclassdescription.h index 10470a1644..000ff2b0da 100644 --- a/src/qmltyperegistrar/qmltypesclassdescription.h +++ b/src/qmltyperegistrar/qmltypesclassdescription.h @@ -53,8 +53,8 @@ struct QmlTypesClassDescription QTypeRevision removedInRevision; bool isCreatable = true; bool isSingleton = false; - bool isRootClass = false; bool hasCustomParser = false; + bool omitFromQmlTypes = false; QStringList implementsInterfaces; QStringList deferredNames; QStringList immediateNames; diff --git a/src/qmltyperegistrar/qmltypescreator.cpp b/src/qmltyperegistrar/qmltypescreator.cpp index d7eef3421c..bf74fa9ca2 100644 --- a/src/qmltyperegistrar/qmltypescreator.cpp +++ b/src/qmltyperegistrar/qmltypescreator.cpp @@ -336,89 +336,26 @@ static QJsonArray members(const QJsonObject *classDef, void QmlTypesCreator::writeComponents() { - const QLatin1String nameKey("name"); const QLatin1String signalsKey("signals"); const QLatin1String enumsKey("enums"); const QLatin1String propertiesKey("properties"); const QLatin1String slotsKey("slots"); const QLatin1String methodsKey("methods"); - const QLatin1String accessKey("access"); - const QLatin1String typeKey("type"); - const QLatin1String returnTypeKey("returnType"); - const QLatin1String argumentsKey("arguments"); - - const QLatin1String destroyedName("destroyed"); - const QLatin1String deleteLaterName("deleteLater"); - const QLatin1String toStringName("toString"); - const QLatin1String destroyName("destroy"); - const QLatin1String delayName("delay"); const QLatin1String signalElement("Signal"); const QLatin1String componentElement("Component"); const QLatin1String methodElement("Method"); - const QLatin1String publicAccess("public"); - const QLatin1String intType("int"); - const QLatin1String stringType("string"); - - auto writeRootClass = [&](const QJsonObject *classDef) { - // Hide destroyed() signals - QJsonArray componentSignals = members(classDef, signalsKey, m_version); - for (auto it = componentSignals.begin(); it != componentSignals.end();) { - if (it->toObject().value(nameKey).toString() == destroyedName) - it = componentSignals.erase(it); - else - ++it; - } - writeMethods(componentSignals, signalElement); - - // Hide deleteLater() methods - QJsonArray componentMethods = members(classDef, methodsKey, m_version); - const QJsonArray componentSlots = members(classDef, slotsKey, m_version); - for (const QJsonValue componentSlot : componentSlots) - componentMethods.append(componentSlot); - for (auto it = componentMethods.begin(); it != componentMethods.end();) { - if (it->toObject().value(nameKey).toString() == deleteLaterName) - it = componentMethods.erase(it); - else - ++it; - } - - // Add toString() - QJsonObject toStringMethod; - toStringMethod.insert(nameKey, toStringName); - toStringMethod.insert(accessKey, publicAccess); - toStringMethod.insert(returnTypeKey, stringType); - componentMethods.append(toStringMethod); - - // Add destroy() - QJsonObject destroyMethod; - destroyMethod.insert(nameKey, destroyName); - destroyMethod.insert(accessKey, publicAccess); - componentMethods.append(destroyMethod); - - // Add destroy(int) - QJsonObject destroyMethodWithArgument; - destroyMethodWithArgument.insert(nameKey, destroyName); - destroyMethodWithArgument.insert(accessKey, publicAccess); - QJsonObject delayArgument; - delayArgument.insert(nameKey, delayName); - delayArgument.insert(typeKey, intType); - QJsonArray destroyArguments; - destroyArguments.append(delayArgument); - destroyMethodWithArgument.insert(argumentsKey, destroyArguments); - componentMethods.append(destroyMethodWithArgument); - - writeMethods(componentMethods, methodElement); - }; - for (const QJsonObject &component : m_ownTypes) { - m_qml.writeStartObject(componentElement); - QmlTypesClassDescription collector; collector.collect(&component, m_ownTypes, m_foreignTypes, QmlTypesClassDescription::TopLevel, m_version); + if (collector.omitFromQmlTypes) + continue; + + m_qml.writeStartObject(componentElement); + writeClassProperties(collector); if (const QJsonObject *classDef = collector.resolvedClass) { @@ -426,13 +363,9 @@ void QmlTypesCreator::writeComponents() writeProperties(members(classDef, propertiesKey, m_version)); - if (collector.isRootClass) { - writeRootClass(classDef); - } else { - writeMethods(members(classDef, signalsKey, m_version), signalElement); - writeMethods(members(classDef, slotsKey, m_version), methodElement); - writeMethods(members(classDef, methodsKey, m_version), methodElement); - } + writeMethods(members(classDef, signalsKey, m_version), signalElement); + writeMethods(members(classDef, slotsKey, m_version), methodElement); + writeMethods(members(classDef, methodsKey, m_version), methodElement); } m_qml.writeEndObject(); diff --git a/tests/auto/qml/qmllint/data/qobjectHasOwnProperty.qml b/tests/auto/qml/qmllint/data/qobjectHasOwnProperty.qml new file mode 100644 index 0000000000..b985c1354f --- /dev/null +++ b/tests/auto/qml/qmllint/data/qobjectHasOwnProperty.qml @@ -0,0 +1,7 @@ +import QtQml + +QtObject { + id: root + + property bool hasFooProperty: root.hasOwnProperty('foo') +} diff --git a/tests/auto/qml/qmllint/data/unused_static.qml b/tests/auto/qml/qmllint/data/unused_static.qml new file mode 100644 index 0000000000..57c4bcba2e --- /dev/null +++ b/tests/auto/qml/qmllint/data/unused_static.qml @@ -0,0 +1,4 @@ +import QtQuick +import Qt.labs.sharedimage + +Item {} diff --git a/tests/auto/qml/qmllint/tst_qmllint.cpp b/tests/auto/qml/qmllint/tst_qmllint.cpp index 0e166b81f3..8963f3a5f1 100644 --- a/tests/auto/qml/qmllint/tst_qmllint.cpp +++ b/tests/auto/qml/qmllint/tst_qmllint.cpp @@ -895,6 +895,7 @@ void TestQmllint::cleanQmlCode_data() QTest::newRow("duplicateQmldirImport") << QStringLiteral("qmldirImport/duplicate.qml"); QTest::newRow("Used imports") << QStringLiteral("used.qml"); QTest::newRow("Unused imports (multi)") << QStringLiteral("unused_multi.qml"); + QTest::newRow("Unused static module") << QStringLiteral("unused_static.qml"); QTest::newRow("compositeSingleton") << QStringLiteral("compositesingleton.qml"); QTest::newRow("stringLength") << QStringLiteral("stringLength.qml"); QTest::newRow("stringLength2") << QStringLiteral("stringLength2.qml"); @@ -947,6 +948,7 @@ void TestQmllint::cleanQmlCode_data() QTest::newRow("declared property of JS object") << QStringLiteral("bareQt.qml"); QTest::newRow("ID overrides property") << QStringLiteral("accessibleId.qml"); QTest::newRow("matchByName") << QStringLiteral("matchByName.qml"); + QTest::newRow("QObject.hasOwnProperty") << QStringLiteral("qobjectHasOwnProperty.qml"); } void TestQmllint::cleanQmlCode() |