aboutsummaryrefslogtreecommitdiffstats
path: root/tests/auto/qml/qmllint
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/qml/qmllint')
-rw-r--r--tests/auto/qml/qmllint/CMakeLists.txt39
-rw-r--r--tests/auto/qml/qmllint/data/2behavior.qml10
-rw-r--r--tests/auto/qml/qmllint/data/2interceptors.qml6
-rw-r--r--tests/auto/qml/qmllint/data/2valueSources.qml6
-rw-r--r--tests/auto/qml/qmllint/data/AliasListType.qml7
-rw-r--r--tests/auto/qml/qmllint/data/AttachedProperties/attachedProperty.qmltypes21
-rw-r--r--tests/auto/qml/qmllint/data/AttachedProperties/qmldir3
-rw-r--r--tests/auto/qml/qmllint/data/Cycle/MenuItem.qml3
-rw-r--r--tests/auto/qml/qmllint/data/Cycle/qmldir3
-rw-r--r--tests/auto/qml/qmllint/data/Cycle1.qml4
-rw-r--r--tests/auto/qml/qmllint/data/DeprProp.qml8
-rw-r--r--tests/auto/qml/qmllint/data/DeprecatedFunctions.qml9
-rw-r--r--tests/auto/qml/qmllint/data/DuplicateImport/plugins.qmltypes11
-rw-r--r--tests/auto/qml/qmllint/data/DuplicateImport/qmldir4
-rw-r--r--tests/auto/qml/qmllint/data/Elsewhere/B.qml3
-rw-r--r--tests/auto/qml/qmllint/data/Elsewhere/qmldir2
-rw-r--r--tests/auto/qml/qmllint/data/EnumAccessCpp.qml9
-rw-r--r--tests/auto/qml/qmllint/data/Fake5Compat/GraphicalEffects/private/qmldir2
-rw-r--r--tests/auto/qml/qmllint/data/Foo.qml5
-rw-r--r--tests/auto/qml/qmllint/data/Foozle.qml3
-rw-r--r--tests/auto/qml/qmllint/data/FormUser.qml2
-rw-r--r--tests/auto/qml/qmllint/data/GrdView.qml3
-rw-r--r--tests/auto/qml/qmllint/data/ImportPath/ModuleInImportPath/A.qml5
-rw-r--r--tests/auto/qml/qmllint/data/ImportPath/ModuleInImportPath/qmldir2
-rw-r--r--tests/auto/qml/qmllint/data/InfoItemTextEdit.qml12
-rw-r--r--tests/auto/qml/qmllint/data/IsNotAnEntryOfEnum.qml14
-rw-r--r--tests/auto/qml/qmllint/data/JsLibrary/HelperLibrary.js5
-rw-r--r--tests/auto/qml/qmllint/data/JsLibrary/qmldir3
-rw-r--r--tests/auto/qml/qmllint/data/LazyAndDirect/Direct.qml5
-rw-r--r--tests/auto/qml/qmllint/data/LazyAndDirect/Lazy.qml8
-rw-r--r--tests/auto/qml/qmllint/data/LazyAndDirect/qmldir4
-rw-r--r--tests/auto/qml/qmllint/data/ListProperty.qml1
-rw-r--r--tests/auto/qml/qmllint/data/LocaleTest/localeTest.qmltypes31
-rw-r--r--tests/auto/qml/qmllint/data/LocaleTest/qmldir3
-rw-r--r--tests/auto/qml/qmllint/data/MultiDefaultProperty.qml5
-rw-r--r--tests/auto/qml/qmllint/data/MultiDirectory/Outer.qml5
-rw-r--r--tests/auto/qml/qmllint/data/MultiDirectory/multi.qrc10
-rw-r--r--tests/auto/qml/qmllint/data/MultiDirectory/qml/Inner.qml5
-rw-r--r--tests/auto/qml/qmllint/data/MultiDirectory/qml/pages/Page.qml5
-rw-r--r--tests/auto/qml/qmllint/data/MultiDirectory/qml/pages/qmldir1
-rw-r--r--tests/auto/qml/qmllint/data/MultiDirectory/qml/qmldir1
-rw-r--r--tests/auto/qml/qmllint/data/MultiDirectory/qmldir5
-rw-r--r--tests/auto/qml/qmllint/data/MyStyle/MyStyle.qmltypes112
-rw-r--r--tests/auto/qml/qmllint/data/MyStyle/ToolBar.qml12
-rw-r--r--tests/auto/qml/qmllint/data/MyStyle/qmldir4
-rw-r--r--tests/auto/qml/qmllint/data/NeedImportPath.qml5
-rw-r--r--tests/auto/qml/qmllint/data/NotScopedEnumCpp.qml6
-rw-r--r--tests/auto/qml/qmllint/data/NotSoSimple.qml5
-rw-r--r--tests/auto/qml/qmllint/data/PluginQuickAnchorsBase.qml8
-rw-r--r--tests/auto/qml/qmllint/data/PropertyBase.qml5
-rw-r--r--tests/auto/qml/qmllint/data/PropertyBase2.qml5
-rw-r--r--tests/auto/qml/qmllint/data/PropertyChangeHandlers/propertychangehandlers.qmltypes65
-rw-r--r--tests/auto/qml/qmllint/data/PropertyChangeHandlers/qmldir3
-rw-r--r--tests/auto/qml/qmllint/data/QmlBench/Globals.qml10
-rw-r--r--tests/auto/qml/qmllint/data/QmlBench/Locals.qml9
-rw-r--r--tests/auto/qml/qmllint/data/QmlBench/qmldir3
-rw-r--r--tests/auto/qml/qmllint/data/RequiredWithRootLevelAlias.qml9
-rw-r--r--tests/auto/qml/qmllint/data/SharedFunctions.js5
-rw-r--r--tests/auto/qml/qmllint/data/Singletons/MissingPragma.qml2
-rw-r--r--tests/auto/qml/qmllint/data/Singletons/MissingQmldirSingleton.qml3
-rw-r--r--tests/auto/qml/qmllint/data/Singletons/qmldir3
-rw-r--r--tests/auto/qml/qmllint/data/StringToDateTime/qmldir3
-rw-r--r--tests/auto/qml/qmllint/data/StringToDateTime/stringToDateTime.qmltypes14
-rw-r--r--tests/auto/qml/qmllint/data/Switch.qml6
-rw-r--r--tests/auto/qml/qmllint/data/T/A.qml6
-rw-r--r--tests/auto/qml/qmllint/data/T/a.qrc7
-rw-r--r--tests/auto/qml/qmllint/data/T/b.qml6
-rw-r--r--tests/auto/qml/qmllint/data/T/qmldir2
-rw-r--r--tests/auto/qml/qmllint/data/TestTypes/qmldir3
-rw-r--r--tests/auto/qml/qmllint/data/TestTypes/testtypes.qmltypes201
-rw-r--r--tests/auto/qml/qmllint/data/Things/LintDirectly.qml4
-rw-r--r--tests/auto/qml/qmllint/data/Things/NotPartOfThings.qml3
-rw-r--r--tests/auto/qml/qmllint/data/Things/plugins.qmltypes50
-rw-r--r--tests/auto/qml/qmllint/data/Things/qmldir4
-rw-r--r--tests/auto/qml/qmllint/data/TypeDeprecated.qml4
-rw-r--r--tests/auto/qml/qmllint/data/TypeDeprecatedReason.qml4
-rw-r--r--tests/auto/qml/qmllint/data/TypeWithDefaultListProperty.qml4
-rw-r--r--tests/auto/qml/qmllint/data/TypeWithDefaultProperty.qml4
-rw-r--r--tests/auto/qml/qmllint/data/TypeWithDefaultStringProperty.qml4
-rw-r--r--tests/auto/qml/qmllint/data/TypeWithDefaultVarProperty.qml4
-rw-r--r--tests/auto/qml/qmllint/data/TypeWithUnknownPropertyType.qml5
-rw-r--r--tests/auto/qml/qmllint/data/UnqualifiedInStoreSloppy.qml12
-rw-r--r--tests/auto/qml/qmllint/data/UnqualifiedInStoreStrict.qml12
-rw-r--r--tests/auto/qml/qmllint/data/accessible.qml5
-rw-r--r--tests/auto/qml/qmllint/data/accessibleId.qml14
-rw-r--r--tests/auto/qml/qmllint/data/additionalImplicitImport.qml1
-rw-r--r--tests/auto/qml/qmllint/data/addressableValue.qml8
-rw-r--r--tests/auto/qml/qmllint/data/aliasCycle.qml7
-rw-r--r--tests/auto/qml/qmllint/data/aliasToList.qml6
-rw-r--r--tests/auto/qml/qmllint/data/animationEasing.qml5
-rw-r--r--tests/auto/qml/qmllint/data/assignNonExistingTypeToVarProp.qml6
-rw-r--r--tests/auto/qml/qmllint/data/assignToReadOnlyProperty.qml5
-rw-r--r--tests/auto/qml/qmllint/data/assignToReadOnlyProperty2.qml6
-rw-r--r--tests/auto/qml/qmllint/data/attachedImportUse.qml7
-rw-r--r--tests/auto/qml/qmllint/data/attachedPropEnum.qml9
-rw-r--r--tests/auto/qml/qmllint/data/attachedPropNotReused.qml8
-rw-r--r--tests/auto/qml/qmllint/data/attachedPropertyAssignments.qml5
-rw-r--r--tests/auto/qml/qmllint/data/attachedTypeIndirect.qml5
-rw-r--r--tests/auto/qml/qmllint/data/badAliasExpression.qml6
-rw-r--r--tests/auto/qml/qmllint/data/badAliasNotAnExpression.qml8
-rw-r--r--tests/auto/qml/qmllint/data/badAttachedProperty.qml8
-rw-r--r--tests/auto/qml/qmllint/data/badAttachedPropertyNested.qml15
-rw-r--r--tests/auto/qml/qmllint/data/badAttachedPropertyTypeQtObject.qml5
-rw-r--r--tests/auto/qml/qmllint/data/badAttachedPropertyTypeString.qml5
-rw-r--r--tests/auto/qml/qmllint/data/badCppPropertyChangeHandlers1.qml4
-rw-r--r--tests/auto/qml/qmllint/data/badCppPropertyChangeHandlers2.qml4
-rw-r--r--tests/auto/qml/qmllint/data/badCppPropertyChangeHandlers3.qml4
-rw-r--r--tests/auto/qml/qmllint/data/badCppPropertyChangeHandlers4.qml4
-rw-r--r--tests/auto/qml/qmllint/data/badGeneralizedGroup1.qml9
-rw-r--r--tests/auto/qml/qmllint/data/badGeneralizedGroup2.qml9
-rw-r--r--tests/auto/qml/qmllint/data/badLiteralBinding.qml4
-rw-r--r--tests/auto/qml/qmllint/data/badLiteralBindingDate.qml4
-rw-r--r--tests/auto/qml/qmllint/data/badModulePrefix.qml7
-rw-r--r--tests/auto/qml/qmllint/data/badModulePrefix2.qml7
-rw-r--r--tests/auto/qml/qmllint/data/badScript.attached.qml4
-rw-r--r--tests/auto/qml/qmllint/data/badScriptBinding.attached.qml6
-rw-r--r--tests/auto/qml/qmllint/data/badScriptBinding.attachedSignalHandler.qml7
-rw-r--r--tests/auto/qml/qmllint/data/badScriptBinding.group.qml4
-rw-r--r--tests/auto/qml/qmllint/data/badTemplateStringSimple.qml5
-rw-r--r--tests/auto/qml/qmllint/data/bad_QT_TR_NOOP.qml5
-rw-r--r--tests/auto/qml/qmllint/data/bad_builtins/builtins.qmltypes513
-rw-r--r--tests/auto/qml/qmllint/data/bad_qsTr.qml5
-rw-r--r--tests/auto/qml/qmllint/data/badlyBoundComponents.qml25
-rw-r--r--tests/auto/qml/qmllint/data/bareQt.qml5
-rw-r--r--tests/auto/qml/qmllint/data/bindingBeforeDeclaration.qml6
-rw-r--r--tests/auto/qml/qmllint/data/bindingTypeMismatch.qml5
-rw-r--r--tests/auto/qml/qmllint/data/bindingTypeMismatchFunction.qml6
-rw-r--r--tests/auto/qml/qmllint/data/boundComponents.qml23
-rw-r--r--tests/auto/qml/qmllint/data/bytearray.qml5
-rw-r--r--tests/auto/qml/qmllint/data/cachedDependency.qml23
-rw-r--r--tests/auto/qml/qmllint/data/callBase.qml7
-rw-r--r--tests/auto/qml/qmllint/data/callJSValueProp.qml6
-rw-r--r--tests/auto/qml/qmllint/data/callLater.qml5
-rw-r--r--tests/auto/qml/qmllint/data/callVarProp.qml7
-rw-r--r--tests/auto/qml/qmllint/data/coercetovoid.qml8
-rw-r--r--tests/auto/qml/qmllint/data/compositesingleton.qml8
-rw-r--r--tests/auto/qml/qmllint/data/connectionNoParent.qml5
-rw-r--r--tests/auto/qml/qmllint/data/constructorProperty.qml5
-rw-r--r--tests/auto/qml/qmllint/data/controlsWithQuick_pluginTest.qml4
-rw-r--r--tests/auto/qml/qmllint/data/controlsWithoutQuick_pluginTest.qml3
-rw-r--r--tests/auto/qml/qmllint/data/customParser.qml17
-rw-r--r--tests/auto/qml/qmllint/data/customParser.recursive.qml16
-rw-r--r--tests/auto/qml/qmllint/data/customParserUnqualifiedAccess.qml5
-rw-r--r--tests/auto/qml/qmllint/data/cycleHead.qml7
-rw-r--r--tests/auto/qml/qmllint/data/defaultImport.qml (renamed from tests/auto/qml/qmllint/data/optionalImport.qml)0
-rw-r--r--tests/auto/qml/qmllint/data/defaultProperty.qml5
-rw-r--r--tests/auto/qml/qmllint/data/defaultPropertyComponent.2.qml7
-rw-r--r--tests/auto/qml/qmllint/data/defaultPropertyComponent.qml5
-rw-r--r--tests/auto/qml/qmllint/data/defaultPropertyList.qml7
-rw-r--r--tests/auto/qml/qmllint/data/defaultPropertyListModel.qml6
-rw-r--r--tests/auto/qml/qmllint/data/defaultPropertyVar.qml5
-rw-r--r--tests/auto/qml/qmllint/data/defaultPropertyWithDoubleAssignment.qml6
-rw-r--r--tests/auto/qml/qmllint/data/defaultPropertyWithWrongType.qml6
-rw-r--r--tests/auto/qml/qmllint/data/defaultPropertyWithinTheSameType.qml6
-rw-r--r--tests/auto/qml/qmllint/data/defaultPropertyWithoutKeyword.qml6
-rw-r--r--tests/auto/qml/qmllint/data/delegateContextProperties.qml9
-rw-r--r--tests/auto/qml/qmllint/data/deprecatedFunction.qml10
-rw-r--r--tests/auto/qml/qmllint/data/deprecatedFunctionInherited.qml7
-rw-r--r--tests/auto/qml/qmllint/data/deprecatedFunctionOverride.qml8
-rw-r--r--tests/auto/qml/qmllint/data/deprecatedProperty.qml10
-rw-r--r--tests/auto/qml/qmllint/data/deprecatedPropertyBinding.qml3
-rw-r--r--tests/auto/qml/qmllint/data/deprecatedPropertyBindingReason.qml3
-rw-r--r--tests/auto/qml/qmllint/data/deprecatedPropertyReason.qml12
-rw-r--r--tests/auto/qml/qmllint/data/deprecatedType.qml3
-rw-r--r--tests/auto/qml/qmllint/data/deprecatedTypeReason.qml3
-rw-r--r--tests/auto/qml/qmllint/data/didYouMeanBinding.qml5
-rw-r--r--tests/auto/qml/qmllint/data/didYouMeanComponent.qml4
-rw-r--r--tests/auto/qml/qmllint/data/didYouMeanEnum.qml5
-rw-r--r--tests/auto/qml/qmllint/data/didYouMeanProperty.qml6
-rw-r--r--tests/auto/qml/qmllint/data/didYouMeanPropertyCall.qml7
-rw-r--r--tests/auto/qml/qmllint/data/didYouMeanUnqualified.qml5
-rw-r--r--tests/auto/qml/qmllint/data/didYouMeanUnqualifiedCall.qml6
-rw-r--r--tests/auto/qml/qmllint/data/dontCheckJSTypes.qml11
-rw-r--r--tests/auto/qml/qmllint/data/duplicateId.qml8
-rw-r--r--tests/auto/qml/qmllint/data/duplicatedPropertyName.qml9
-rw-r--r--tests/auto/qml/qmllint/data/elementpass_pluginTest.qml7
-rw-r--r--tests/auto/qml/qmllint/data/enumInvalid.qml6
-rw-r--r--tests/auto/qml/qmllint/data/enumsOfScrollBar.qml7
-rw-r--r--tests/auto/qml/qmllint/data/findMemberPrint.qml13
-rw-r--r--tests/auto/qml/qmllint/data/generalizedGroupHint.qml23
-rw-r--r--tests/auto/qml/qmllint/data/goodAttachedProperty.qml13
-rw-r--r--tests/auto/qml/qmllint/data/goodAttachedPropertyAccess.qml14
-rw-r--r--tests/auto/qml/qmllint/data/goodAttachedPropertyNested.qml20
-rw-r--r--tests/auto/qml/qmllint/data/goodBindingsOnGroupAndAttached.qml11
-rw-r--r--tests/auto/qml/qmllint/data/goodCppPropertyChangeHandlers.qml26
-rw-r--r--tests/auto/qml/qmllint/data/goodGeneralizedGroup.qml9
-rw-r--r--tests/auto/qml/qmllint/data/goodModulePrefix.qml9
-rw-r--r--tests/auto/qml/qmllint/data/groupedAttachedLayout.qml20
-rw-r--r--tests/auto/qml/qmllint/data/groupedPropertyAssignments.qml5
-rw-r--r--tests/auto/qml/qmllint/data/groupedProperty_valueSource_interceptor.qml6
-rw-r--r--tests/auto/qml/qmllint/data/here.qml3
-rw-r--r--tests/auto/qml/qmllint/data/hidden/moduleWithQrc/main.qml11
-rw-r--r--tests/auto/qml/qmllint/data/hidden/moduleWithQrc/qmldir3
-rw-r--r--tests/auto/qml/qmllint/data/hidden/moduleWithQrc_raw_qml_0.qrc6
-rw-r--r--tests/auto/qml/qmllint/data/hidden/qmake_moduleWithQrc.qrc6
-rw-r--r--tests/auto/qml/qmllint/data/ignoreWarnings.qml24
-rw-r--r--tests/auto/qml/qmllint/data/implicitImportResource.qrc6
-rw-r--r--tests/auto/qml/qmllint/data/importNonexistentFile.qml3
-rw-r--r--tests/auto/qml/qmllint/data/importNullDevice.qml3
-rw-r--r--tests/auto/qml/qmllint/data/importQMLModule.qml2
-rw-r--r--tests/auto/qml/qmllint/data/importing_js.qml2
-rw-r--r--tests/auto/qml/qmllint/data/inaccessibleId.qml12
-rw-r--r--tests/auto/qml/qmllint/data/inaccessibleId2.qml10
-rw-r--r--tests/auto/qml/qmllint/data/incompleteQmltypes2.qml6
-rw-r--r--tests/auto/qml/qmllint/data/incompleteQmltypes3.qml6
-rw-r--r--tests/auto/qml/qmllint/data/initReadonly.qml6
-rw-r--r--tests/auto/qml/qmllint/data/inlineComponent.qml15
-rw-r--r--tests/auto/qml/qmllint/data/inlineComponentNoComponent.qml5
-rw-r--r--tests/auto/qml/qmllint/data/inlineComponentWithComponents.qml11
-rw-r--r--tests/auto/qml/qmllint/data/inlineComponentsChained.qml10
-rw-r--r--tests/auto/qml/qmllint/data/interceptor.qml10
-rw-r--r--tests/auto/qml/qmllint/data/interceptor_valueSource.qml23
-rw-r--r--tests/auto/qml/qmllint/data/invalidAliasTarget.qml11
-rw-r--r--tests/auto/qml/qmllint/data/invalidId1.qml5
-rw-r--r--tests/auto/qml/qmllint/data/invalidId2.qml7
-rw-r--r--tests/auto/qml/qmllint/data/invalidIdLookup.qml10
-rw-r--r--tests/auto/qml/qmllint/data/invalidImport.qml4
-rw-r--r--tests/auto/qml/qmllint/data/invalidInterceptor.qml8
-rw-r--r--tests/auto/qml/qmllint/data/javascriptVariableArgs.qml9
-rw-r--r--tests/auto/qml/qmllint/data/jsLibrary.qml8
-rw-r--r--tests/auto/qml/qmllint/data/jsVarDeclarations.js3
-rw-r--r--tests/auto/qml/qmllint/data/jsVarDeclarations.qml9
-rw-r--r--tests/auto/qml/qmllint/data/jsVarDeclarationsWriteConst.qml7
-rw-r--r--tests/auto/qml/qmllint/data/listIndices.qml14
-rw-r--r--tests/auto/qml/qmllint/data/listPropertyMethods.qml87
-rw-r--r--tests/auto/qml/qmllint/data/locale.qml6
-rw-r--r--tests/auto/qml/qmllint/data/lowerCaseQualifiedImport.qml9
-rw-r--r--tests/auto/qml/qmllint/data/lowerCaseQualifiedImport2.qml9
-rw-r--r--tests/auto/qml/qmllint/data/matchByName.qml8
-rw-r--r--tests/auto/qml/qmllint/data/missingBuiltinsNoCrash.qml3
-rw-r--r--tests/auto/qml/qmllint/data/missingComponentBehaviorBound.qml10
-rw-r--r--tests/auto/qml/qmllint/data/missingQmltypes.qml4
-rw-r--r--tests/auto/qml/qmllint/data/missingRequiredAlias.qml5
-rw-r--r--tests/auto/qml/qmllint/data/missingSingletonPragma.qml6
-rw-r--r--tests/auto/qml/qmllint/data/missingSingletonQmldir.qml6
-rw-r--r--tests/auto/qml/qmllint/data/multiDefaultPropertyOk.qml8
-rw-r--r--tests/auto/qml/qmllint/data/multiDefaultPropertyWithWrongType.qml8
-rw-r--r--tests/auto/qml/qmllint/data/multiGrouped.qml6
-rw-r--r--tests/auto/qml/qmllint/data/multifix.fixed.qml14
-rw-r--r--tests/auto/qml/qmllint/data/multifix.qml13
-rw-r--r--tests/auto/qml/qmllint/data/multilineString.fixed.qml21
-rw-r--r--tests/auto/qml/qmllint/data/multilineString.qml21
-rw-r--r--tests/auto/qml/qmllint/data/multilineStringEscaped.qml8
-rw-r--r--tests/auto/qml/qmllint/data/nestedInlineComponents.qml7
-rw-r--r--tests/auto/qml/qmllint/data/nonExistentListProperty.qml5
-rw-r--r--tests/auto/qml/qmllint/data/nonNullStored.qml6
-rw-r--r--tests/auto/qml/qmllint/data/notQmlRootMethods.qml8
-rw-r--r--tests/auto/qml/qmllint/data/nothing_pluginTest.qml3
-rw-r--r--tests/auto/qml/qmllint/data/nullBinding.qml5
-rw-r--r--tests/auto/qml/qmllint/data/nullBindingFunction.qml5
-rw-r--r--tests/auto/qml/qmllint/data/numberToStringProperty.qml5
-rw-r--r--tests/auto/qml/qmllint/data/objectArray.qml9
-rw-r--r--tests/auto/qml/qmllint/data/objectBoundToVar.qml4
-rw-r--r--tests/auto/qml/qmllint/data/onBindingInGroupedProperty.qml10
-rw-r--r--tests/auto/qml/qmllint/data/onlyMajorVersion.qml8
-rw-r--r--tests/auto/qml/qmllint/data/optionalChainingCall.qml9
-rw-r--r--tests/auto/qml/qmllint/data/overridescript.qml1
-rw-r--r--tests/auto/qml/qmllint/data/pluginQuick_anchors.qml9
-rw-r--r--tests/auto/qml/qmllint/data/pluginQuick_anchorsUndefined.qml10
-rw-r--r--tests/auto/qml/qmllint/data/pluginQuick_attached.qml27
-rw-r--r--tests/auto/qml/qmllint/data/pluginQuick_attachedClean.qml31
-rw-r--r--tests/auto/qml/qmllint/data/pluginQuick_attachedIgnore.qml15
-rw-r--r--tests/auto/qml/qmllint/data/pluginQuick_layoutChildren.qml29
-rw-r--r--tests/auto/qml/qmllint/data/pluginQuick_noCrashOnUneresolved.qml10
-rw-r--r--tests/auto/qml/qmllint/data/pluginQuick_propertyChangesInvalidTarget.qml8
-rw-r--r--tests/auto/qml/qmllint/data/pluginQuick_propertyChangesParsed.qml19
-rw-r--r--tests/auto/qml/qmllint/data/pluginQuick_swipeDelegate.qml19
-rw-r--r--tests/auto/qml/qmllint/data/pluginQuick_varProp.qml16
-rw-r--r--tests/auto/qml/qmllint/data/pluginQuick_varPropClean.qml16
-rw-r--r--tests/auto/qml/qmllint/data/pragmaStrict.qml7
-rw-r--r--tests/auto/qml/qmllint/data/prefixedAttachedProperty.qml5
-rw-r--r--tests/auto/qml/qmllint/data/propertyBindingValue.qml3
-rw-r--r--tests/auto/qml/qmllint/data/propertyDelegate.qml5
-rw-r--r--tests/auto/qml/qmllint/data/propertyOverride.qml5
-rw-r--r--tests/auto/qml/qmllint/data/propertypass_pluginTest.qml24
-rw-r--r--tests/auto/qml/qmllint/data/qEventPoint.qml9
-rw-r--r--tests/auto/qml/qmllint/data/qjsroot.qml20
-rw-r--r--tests/auto/qml/qmllint/data/qmlRootMethods.qml12
-rw-r--r--tests/auto/qml/qmllint/data/qmldirAndQmltypes.qml2
-rw-r--r--tests/auto/qml/qmllint/data/qmldirImport/QtObjectWithDefaultProperty.qml4
-rw-r--r--tests/auto/qml/qmllint/data/qmldirImport/duplicate.qml7
-rw-r--r--tests/auto/qml/qmllint/data/qmldirImportAndDepend/QtObjectWithDefaultProperty.qml4
-rw-r--r--tests/auto/qml/qmllint/data/qmldirImportAndDepend/good.qml2
-rw-r--r--tests/auto/qml/qmllint/data/qmodelIndex.qml6
-rw-r--r--tests/auto/qml/qmllint/data/qobjectHasOwnProperty.qml7
-rw-r--r--tests/auto/qml/qmllint/data/qtquickWindow20.qml5
-rw-r--r--tests/auto/qml/qmllint/data/qtquickWindow21.qml5
-rw-r--r--tests/auto/qml/qmllint/data/qtquickdialog.qml5
-rw-r--r--tests/auto/qml/qmllint/data/qvariant.qml5
-rw-r--r--tests/auto/qml/qmllint/data/relPathQrc/Bar/Thing2.qml3
-rw-r--r--tests/auto/qml/qmllint/data/relPathQrc/Foo/Thing.qml3
-rw-r--r--tests/auto/qml/qmllint/data/relPathQrc/resources.qrc7
-rw-r--r--tests/auto/qml/qmllint/data/requiredProperty.qml11
-rw-r--r--tests/auto/qml/qmllint/data/requiredPropertyBindings.qml24
-rw-r--r--tests/auto/qml/qmllint/data/requiredPropertyBindingsLater.qml18
-rw-r--r--tests/auto/qml/qmllint/data/requiredPropertyBindingsNow.qml17
-rw-r--r--tests/auto/qml/qmllint/data/requiredPropertyInComponent.qml25
-rw-r--r--tests/auto/qml/qmllint/data/returnTypeAnnotation_component.qml9
-rw-r--r--tests/auto/qml/qmllint/data/returnTypeAnnotation_enum.qml5
-rw-r--r--tests/auto/qml/qmllint/data/returnTypeAnnotation_method.qml6
-rw-r--r--tests/auto/qml/qmllint/data/returnTypeAnnotation_property.qml7
-rw-r--r--tests/auto/qml/qmllint/data/returnTypeAnnotation_type.qml5
-rw-r--r--tests/auto/qml/qmllint/data/scriptInTemplate.qml6
-rw-r--r--tests/auto/qml/qmllint/data/scripts/Foo.js6
-rw-r--r--tests/auto/qml/qmllint/data/scripts/qmldir4
-rw-r--r--tests/auto/qml/qmllint/data/scripts/scripts.qmltypes22
-rw-r--r--tests/auto/qml/qmllint/data/scriptstring.qml73
-rw-r--r--tests/auto/qml/qmllint/data/settings/bare/.qmllint.ini2
-rw-r--r--tests/auto/qml/qmllint/data/settings/bare/bare.qml3
-rw-r--r--tests/auto/qml/qmllint/data/settings/plugin/.qmllint.ini2
-rw-r--r--tests/auto/qml/qmllint/data/settings/plugin/elemenpass_pluginSettingTest.qml7
-rw-r--r--tests/auto/qml/qmllint/data/settings/qmlimports/.qmllint.ini2
-rw-r--r--tests/auto/qml/qmllint/data/settings/qmlimports/qmlimports.qml3
-rw-r--r--tests/auto/qml/qmllint/data/settings/qmlimports/subdir/Custom/custom.qmltypes11
-rw-r--r--tests/auto/qml/qmllint/data/settings/qmlimports/subdir/Custom/qmldir2
-rw-r--r--tests/auto/qml/qmllint/data/settings/qmltypes/.qmllint.ini3
-rw-r--r--tests/auto/qml/qmllint/data/settings/qmltypes/qmltypes.qml3
-rw-r--r--tests/auto/qml/qmllint/data/settings/qmltypes/subdir/custom.qmltypes11
-rw-r--r--tests/auto/qml/qmllint/data/settings/unqualifiedSilent/.qmllint.ini2
-rw-r--r--tests/auto/qml/qmllint/data/settings/unqualifiedSilent/unqualified.qml5
-rw-r--r--tests/auto/qml/qmllint/data/settings/unusedImportWarning/.qmllint.ini2
-rw-r--r--tests/auto/qml/qmllint/data/settings/unusedImportWarning/unused.qml5
-rw-r--r--tests/auto/qml/qmllint/data/shadowable.qml6
-rw-r--r--tests/auto/qml/qmllint/data/shadowedMethod.qml8
-rw-r--r--tests/auto/qml/qmllint/data/shadowedSignal.qml6
-rw-r--r--tests/auto/qml/qmllint/data/shadowedSignalWithId.qml6
-rw-r--r--tests/auto/qml/qmllint/data/shadowedSlot.qml6
-rw-r--r--tests/auto/qml/qmllint/data/storeNameMethod.qml12
-rw-r--r--tests/auto/qml/qmllint/data/stringAsId.qml5
-rw-r--r--tests/auto/qml/qmllint/data/stringIdUsedInWarning.qml9
-rw-r--r--tests/auto/qml/qmllint/data/stringLength.qml9
-rw-r--r--tests/auto/qml/qmllint/data/stringLength2.qml10
-rw-r--r--tests/auto/qml/qmllint/data/stringLength3.qml8
-rw-r--r--tests/auto/qml/qmllint/data/stringToByteArray.qml7
-rw-r--r--tests/auto/qml/qmllint/data/stringToDateTime.qml7
-rw-r--r--tests/auto/qml/qmllint/data/switcher.qml5
-rw-r--r--tests/auto/qml/qmllint/data/templateStringSubstitution.qml6
-rw-r--r--tests/auto/qml/qmllint/data/tooFewParams.qml5
-rw-r--r--tests/auto/qml/qmllint/data/typePropertyAccess.qml6
-rw-r--r--tests/auto/qml/qmllint/data/unaryMinusToStringProperty.qml5
-rw-r--r--tests/auto/qml/qmllint/data/unboundComponents.qml22
-rw-r--r--tests/auto/qml/qmllint/data/unexportedCppBase.qml5
-rw-r--r--tests/auto/qml/qmllint/data/unknownParentDefaultPropertyCheck.qml6
-rw-r--r--tests/auto/qml/qmllint/data/unknownTypeCustomParser.qml7
-rw-r--r--tests/auto/qml/qmllint/data/unknownTypeInRegister.qml7
-rw-r--r--tests/auto/qml/qmllint/data/unresolvedArrayBinding.qml10
-rw-r--r--tests/auto/qml/qmllint/data/unresolvedAttachedType.qml5
-rw-r--r--tests/auto/qml/qmllint/data/unresolvedType.qml14
-rw-r--r--tests/auto/qml/qmllint/data/untitled/components/Foo.qml5
-rw-r--r--tests/auto/qml/qmllint/data/untitled/main.qml9
-rw-r--r--tests/auto/qml/qmllint/data/untitled/qrcUrlImport.qrc6
-rw-r--r--tests/auto/qml/qmllint/data/unused_multi.qml7
-rw-r--r--tests/auto/qml/qmllint/data/unused_prefix.qml5
-rw-r--r--tests/auto/qml/qmllint/data/unused_simple.qml5
-rw-r--r--tests/auto/qml/qmllint/data/unused_static.qml4
-rw-r--r--tests/auto/qml/qmllint/data/unversionChangedSignalSansArguments.qml5
-rw-r--r--tests/auto/qml/qmllint/data/useConstInvokable.qml5
-rw-r--r--tests/auto/qml/qmllint/data/used.qml17
-rw-r--r--tests/auto/qml/qmllint/data/v4SequenceMethods.qml87
-rw-r--r--tests/auto/qml/qmllint/data/validLiterals.qml37
-rw-r--r--tests/auto/qml/qmllint/data/valueSource.qml8
-rw-r--r--tests/auto/qml/qmllint/data/valueSourceBetween2interceptors.qml7
-rw-r--r--tests/auto/qml/qmllint/data/valueSource_Value.qml7
-rw-r--r--tests/auto/qml/qmllint/data/valueSource_listValue.qml7
-rw-r--r--tests/auto/qml/qmllint/data/valueTypesFromString.qml7
-rw-r--r--tests/auto/qml/qmllint/data/varargs.qml7
-rw-r--r--tests/auto/qml/qmllint/data/variantMapLookup.qml13
-rw-r--r--tests/auto/qml/qmllint/data/writeListProperty.qml7
-rw-r--r--tests/auto/qml/qmllint/lintplugin.cpp131
-rw-r--r--tests/auto/qml/qmllint/lintplugin.h21
-rw-r--r--tests/auto/qml/qmllint/testPlugin.json14
-rw-r--r--tests/auto/qml/qmllint/tst_qmllint.cpp2203
372 files changed, 6139 insertions, 228 deletions
diff --git a/tests/auto/qml/qmllint/CMakeLists.txt b/tests/auto/qml/qmllint/CMakeLists.txt
index 2518740101..5a3e2d9c0d 100644
--- a/tests/auto/qml/qmllint/CMakeLists.txt
+++ b/tests/auto/qml/qmllint/CMakeLists.txt
@@ -1,23 +1,37 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
# Generated from qmllint.pro.
#####################################################################
## tst_qmllint Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qmllint LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
data/*)
list(APPEND test_data ${test_data_glob})
+add_library(LintPlugin STATIC lintplugin.h lintplugin.cpp)
+target_link_libraries(LintPlugin PRIVATE Qt::QmlCompilerPrivate)
+qt_autogen_tools_initial_setup(LintPlugin)
+target_compile_definitions(LintPlugin PRIVATE QT_STATICPLUGIN)
+
qt_internal_add_test(tst_qmllint
SOURCES
- ../../shared/util.cpp ../../shared/util.h
tst_qmllint.cpp
- INCLUDE_DIRECTORIES
- ../../shared
- PUBLIC_LIBRARIES
+ LIBRARIES
Qt::Gui
+ Qt::QuickTestUtilsPrivate
+ Qt::QmlCompilerPrivate
+ LintPlugin
TESTDATA ${test_data}
)
@@ -26,10 +40,23 @@ qt_internal_add_test(tst_qmllint
qt_internal_extend_target(tst_qmllint CONDITION ANDROID OR IOS
DEFINES
- QT_QMLTEST_DATADIR=\\\":/data\\\"
+ QT_QMLTEST_DATADIR=":/data"
)
qt_internal_extend_target(tst_qmllint CONDITION NOT ANDROID AND NOT IOS
DEFINES
- QT_QMLTEST_DATADIR=\\\"${CMAKE_CURRENT_SOURCE_DIR}/data\\\"
+ QT_QMLTEST_DATADIR="${CMAKE_CURRENT_SOURCE_DIR}/data"
)
+
+if (TARGET qmllint)
+ add_dependencies(tst_qmllint Qt::qmllint)
+endif()
+
+if (TARGET qmljsrootgen)
+ qt_internal_extend_target(tst_qmllint
+ DEFINES
+ QT_QMLJSROOTGEN_PRESENT
+ )
+
+ add_dependencies(tst_qmllint Qt::qmljsrootgen)
+endif()
diff --git a/tests/auto/qml/qmllint/data/2behavior.qml b/tests/auto/qml/qmllint/data/2behavior.qml
new file mode 100644
index 0000000000..0520415155
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/2behavior.qml
@@ -0,0 +1,10 @@
+import QtQuick 2.15
+
+Item {
+ Behavior {
+ SpringAnimation{ spring: 2; damping: 0.2; modulus: 360 }
+ }
+ Behavior {
+ SpringAnimation{ spring: 2; damping: 0.2; modulus: 360 }
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/2interceptors.qml b/tests/auto/qml/qmllint/data/2interceptors.qml
new file mode 100644
index 0000000000..9db9766a8e
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/2interceptors.qml
@@ -0,0 +1,6 @@
+import QtQuick 2.0
+
+Item {
+ Behavior on x {}
+ Behavior on x {}
+}
diff --git a/tests/auto/qml/qmllint/data/2valueSources.qml b/tests/auto/qml/qmllint/data/2valueSources.qml
new file mode 100644
index 0000000000..49e4c65caf
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/2valueSources.qml
@@ -0,0 +1,6 @@
+import QtQuick 2.0
+
+Item {
+ NumberAnimation on x {}
+ NumberAnimation on x {}
+}
diff --git a/tests/auto/qml/qmllint/data/AliasListType.qml b/tests/auto/qml/qmllint/data/AliasListType.qml
new file mode 100644
index 0000000000..bdefa1d35f
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/AliasListType.qml
@@ -0,0 +1,7 @@
+import QtQuick 2.15
+
+Item {
+ Item { id: item }
+
+ default property alias content: item.children
+}
diff --git a/tests/auto/qml/qmllint/data/AttachedProperties/attachedProperty.qmltypes b/tests/auto/qml/qmllint/data/AttachedProperties/attachedProperty.qmltypes
new file mode 100644
index 0000000000..1192a53911
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/AttachedProperties/attachedProperty.qmltypes
@@ -0,0 +1,21 @@
+import QtQuick.tooling 1.2
+Module {
+ Component {
+ file: "attachedtype.h"
+ name: "TestType"
+ accessSemantics: "reference"
+ prototype: "QObject"
+ exports: ["QmlLintTestLib/TestType 1.0"]
+ exportMetaObjectRevisions: [256]
+ attachedType: "TestTypeAttached"
+ }
+ Component {
+ file: "attachedtype.h"
+ name: "TestTypeAttached"
+ accessSemantics: "reference"
+ prototype: "QObject"
+ Property { name: "count"; type: "int"; read: "getCount"; write: "setCount" }
+ Property { name: "str"; type: "QString"; read: "getStr"; write: "setStr" }
+ Property { name: "object"; type: "QObject"; isPointer: true; read: "getObject"; write: "setObject" }
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/AttachedProperties/qmldir b/tests/auto/qml/qmllint/data/AttachedProperties/qmldir
new file mode 100644
index 0000000000..965b336902
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/AttachedProperties/qmldir
@@ -0,0 +1,3 @@
+module AttachedProperties
+typeinfo attachedProperty.qmltypes
+import QtQml
diff --git a/tests/auto/qml/qmllint/data/Cycle/MenuItem.qml b/tests/auto/qml/qmllint/data/Cycle/MenuItem.qml
new file mode 100644
index 0000000000..b316a5432c
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/Cycle/MenuItem.qml
@@ -0,0 +1,3 @@
+import QtQml
+
+MenuItem {}
diff --git a/tests/auto/qml/qmllint/data/Cycle/qmldir b/tests/auto/qml/qmllint/data/Cycle/qmldir
new file mode 100644
index 0000000000..6b0ba5519a
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/Cycle/qmldir
@@ -0,0 +1,3 @@
+module Cycle
+
+MenuItem 1.0 MenuItem.qml
diff --git a/tests/auto/qml/qmllint/data/Cycle1.qml b/tests/auto/qml/qmllint/data/Cycle1.qml
index 8095e9f732..00b7c2a4ce 100644
--- a/tests/auto/qml/qmllint/data/Cycle1.qml
+++ b/tests/auto/qml/qmllint/data/Cycle1.qml
@@ -1,2 +1,4 @@
import QtQml 2.0
-Cycle2 {}
+Cycle2 {
+ QtObject {} // Having children here has caused qmllint to hang in the past (QTBUG-96343)
+}
diff --git a/tests/auto/qml/qmllint/data/DeprProp.qml b/tests/auto/qml/qmllint/data/DeprProp.qml
new file mode 100644
index 0000000000..39f271902e
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/DeprProp.qml
@@ -0,0 +1,8 @@
+import QtQml
+
+QtObject {
+ @Deprecated {}
+ property int deprecated: 500
+ @Deprecated { reason: "Test" }
+ property int deprecatedReason: 200
+}
diff --git a/tests/auto/qml/qmllint/data/DeprecatedFunctions.qml b/tests/auto/qml/qmllint/data/DeprecatedFunctions.qml
new file mode 100644
index 0000000000..139e8a6230
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/DeprecatedFunctions.qml
@@ -0,0 +1,9 @@
+import QtQuick 2.0
+
+Item {
+ @Deprecated { reason: "This deprecation should be overridden!" }
+ function deprecatedOverride(a, b) {}
+
+ @Deprecated { reason: "This deprecation should be visible!" }
+ function deprecatedInherited(c, d) {}
+}
diff --git a/tests/auto/qml/qmllint/data/DuplicateImport/plugins.qmltypes b/tests/auto/qml/qmllint/data/DuplicateImport/plugins.qmltypes
new file mode 100644
index 0000000000..b9144a673a
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/DuplicateImport/plugins.qmltypes
@@ -0,0 +1,11 @@
+import QtQuick.tooling 1.2
+Module {
+ dependencies: []
+ Component {
+ name: "ItemDerived"
+ prototype: "QQuickItem"
+ exports: [
+ "DuplicateImport/ItemDerived 1.0"
+ ]
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/DuplicateImport/qmldir b/tests/auto/qml/qmllint/data/DuplicateImport/qmldir
new file mode 100644
index 0000000000..309ab5ac11
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/DuplicateImport/qmldir
@@ -0,0 +1,4 @@
+module DuplicateImport
+typeinfo plugins.qmltypes
+depends QtQuick 2.0
+import QtQml
diff --git a/tests/auto/qml/qmllint/data/Elsewhere/B.qml b/tests/auto/qml/qmllint/data/Elsewhere/B.qml
new file mode 100644
index 0000000000..8fc36a40da
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/Elsewhere/B.qml
@@ -0,0 +1,3 @@
+import QtQml
+
+QtObject {}
diff --git a/tests/auto/qml/qmllint/data/Elsewhere/qmldir b/tests/auto/qml/qmllint/data/Elsewhere/qmldir
new file mode 100644
index 0000000000..e38f7da9ce
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/Elsewhere/qmldir
@@ -0,0 +1,2 @@
+module Things.Nested
+A 1.0 B.qml
diff --git a/tests/auto/qml/qmllint/data/EnumAccessCpp.qml b/tests/auto/qml/qmllint/data/EnumAccessCpp.qml
new file mode 100644
index 0000000000..77cdc5eb6a
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/EnumAccessCpp.qml
@@ -0,0 +1,9 @@
+import Things
+import QtQml
+
+QtObject {
+ property int foo1: SomethingEntirelyStrange.AnEnum.AAA
+ property int foo2: SomethingEntirelyStrange.AnEnum.BBB
+ property int foo3: SomethingEntirelyStrange.AnEnum.CCC
+ property int boo1: SomethingEntirelyStrange.V1
+}
diff --git a/tests/auto/qml/qmllint/data/Fake5Compat/GraphicalEffects/private/qmldir b/tests/auto/qml/qmllint/data/Fake5Compat/GraphicalEffects/private/qmldir
new file mode 100644
index 0000000000..b13cdc9c3e
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/Fake5Compat/GraphicalEffects/private/qmldir
@@ -0,0 +1,2 @@
+module Qt5Compat.GraphicalEffects.private
+typeinfo plugins.qmltypes
diff --git a/tests/auto/qml/qmllint/data/Foo.qml b/tests/auto/qml/qmllint/data/Foo.qml
new file mode 100644
index 0000000000..6e47488e95
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/Foo.qml
@@ -0,0 +1,5 @@
+import QtQml
+
+QtObject {
+ function whatSUp() : string { return "I'm crashing"; }
+}
diff --git a/tests/auto/qml/qmllint/data/Foozle.qml b/tests/auto/qml/qmllint/data/Foozle.qml
new file mode 100644
index 0000000000..f9ed238343
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/Foozle.qml
@@ -0,0 +1,3 @@
+import QtQml
+
+Barzle {}
diff --git a/tests/auto/qml/qmllint/data/FormUser.qml b/tests/auto/qml/qmllint/data/FormUser.qml
index ea3621586f..46a5c4fd6d 100644
--- a/tests/auto/qml/qmllint/data/FormUser.qml
+++ b/tests/auto/qml/qmllint/data/FormUser.qml
@@ -1,5 +1,3 @@
-import QtQuick 2.0
-
Form {
x: 12
y: 13
diff --git a/tests/auto/qml/qmllint/data/GrdView.qml b/tests/auto/qml/qmllint/data/GrdView.qml
new file mode 100644
index 0000000000..a275839849
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/GrdView.qml
@@ -0,0 +1,3 @@
+import QtQuick 2.15 as Quick
+
+Quick.GridView {}
diff --git a/tests/auto/qml/qmllint/data/ImportPath/ModuleInImportPath/A.qml b/tests/auto/qml/qmllint/data/ImportPath/ModuleInImportPath/A.qml
new file mode 100644
index 0000000000..4141884af9
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/ImportPath/ModuleInImportPath/A.qml
@@ -0,0 +1,5 @@
+import QtQuick
+
+Item {
+ property string myProperty
+}
diff --git a/tests/auto/qml/qmllint/data/ImportPath/ModuleInImportPath/qmldir b/tests/auto/qml/qmllint/data/ImportPath/ModuleInImportPath/qmldir
new file mode 100644
index 0000000000..b6e958d657
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/ImportPath/ModuleInImportPath/qmldir
@@ -0,0 +1,2 @@
+module ModuleInImportPath
+A 1.0 A.qml
diff --git a/tests/auto/qml/qmllint/data/InfoItemTextEdit.qml b/tests/auto/qml/qmllint/data/InfoItemTextEdit.qml
new file mode 100644
index 0000000000..be2d35d574
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/InfoItemTextEdit.qml
@@ -0,0 +1,12 @@
+import QtQuick 2.11
+import QtQuick.Window 2.3
+
+Rectangle {
+ property color textStrColor: "steelblue"
+ property alias valueStr: input.text
+
+ TextInput {
+ id: input
+ }
+
+}
diff --git a/tests/auto/qml/qmllint/data/IsNotAnEntryOfEnum.qml b/tests/auto/qml/qmllint/data/IsNotAnEntryOfEnum.qml
new file mode 100644
index 0000000000..8b20fe9ae9
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/IsNotAnEntryOfEnum.qml
@@ -0,0 +1,14 @@
+import QtQuick
+
+Item {
+ id: item
+ visible: true
+
+ enum Mode {
+ Hours,
+ Minutes
+ }
+
+ property int mode: item.Mode.Hours
+ property string s: item.mode === IsNotAnEntryOfEnum.Mode.Hour ? "green" : "tomato"
+}
diff --git a/tests/auto/qml/qmllint/data/JsLibrary/HelperLibrary.js b/tests/auto/qml/qmllint/data/JsLibrary/HelperLibrary.js
new file mode 100644
index 0000000000..cf75a11b72
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/JsLibrary/HelperLibrary.js
@@ -0,0 +1,5 @@
+.pragma library
+
+function foo() {
+ return "Hello World";
+}
diff --git a/tests/auto/qml/qmllint/data/JsLibrary/qmldir b/tests/auto/qml/qmllint/data/JsLibrary/qmldir
new file mode 100644
index 0000000000..d1c7011d7a
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/JsLibrary/qmldir
@@ -0,0 +1,3 @@
+module JsLibrary
+HelperLibrary 1.0 HelperLibrary.js
+
diff --git a/tests/auto/qml/qmllint/data/LazyAndDirect/Direct.qml b/tests/auto/qml/qmllint/data/LazyAndDirect/Direct.qml
new file mode 100644
index 0000000000..fcb08c1e80
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/LazyAndDirect/Direct.qml
@@ -0,0 +1,5 @@
+import QtQml
+
+QtObject {
+ Component.onCompleted: Lazy.setDirect(this)
+}
diff --git a/tests/auto/qml/qmllint/data/LazyAndDirect/Lazy.qml b/tests/auto/qml/qmllint/data/LazyAndDirect/Lazy.qml
new file mode 100644
index 0000000000..1f69d0f16a
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/LazyAndDirect/Lazy.qml
@@ -0,0 +1,8 @@
+pragma Singleton
+import QtQml
+
+QtObject {
+ property Direct direct
+
+ function setDirect(newDirect : Direct) { direct = newDirect }
+}
diff --git a/tests/auto/qml/qmllint/data/LazyAndDirect/qmldir b/tests/auto/qml/qmllint/data/LazyAndDirect/qmldir
new file mode 100644
index 0000000000..ebc7f2a157
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/LazyAndDirect/qmldir
@@ -0,0 +1,4 @@
+module LazyAndDirect
+
+Direct 1.0 Direct.qml
+singleton Lazy 1.0 Lazy.qml
diff --git a/tests/auto/qml/qmllint/data/ListProperty.qml b/tests/auto/qml/qmllint/data/ListProperty.qml
index d2bbc58cc5..0290f51ce9 100644
--- a/tests/auto/qml/qmllint/data/ListProperty.qml
+++ b/tests/auto/qml/qmllint/data/ListProperty.qml
@@ -1,4 +1,3 @@
-import QtQuick 2.12
import Things 1.0
Frame {
diff --git a/tests/auto/qml/qmllint/data/LocaleTest/localeTest.qmltypes b/tests/auto/qml/qmllint/data/LocaleTest/localeTest.qmltypes
new file mode 100644
index 0000000000..b5baa22357
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/LocaleTest/localeTest.qmltypes
@@ -0,0 +1,31 @@
+import QtQuick.tooling 1.2
+
+// This file describes the plugin-supplied types contained in the library.
+// It is used for QML tooling purposes only.
+//
+// This file was auto-generated by qmltyperegistrar.
+
+Module {
+ Component {
+ file: "AppManager.h"
+ name: "AppManager"
+ accessSemantics: "reference"
+ prototype: "QObject"
+ exports: ["LocaleTest/AppManager 1.0"]
+ isCreatable: false
+ isSingleton: true
+ exportMetaObjectRevisions: [256]
+ Property {
+ name: "primaryLocale"
+ type: "QLocale"
+ read: "getPrimaryLocale"
+ notify: "primaryLocaleChanged"
+ index: 0
+ isReadonly: true
+ }
+ Signal {
+ name: "primaryLocaleChanged"
+ Parameter { type: "QLocale" }
+ }
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/LocaleTest/qmldir b/tests/auto/qml/qmllint/data/LocaleTest/qmldir
new file mode 100644
index 0000000000..2dc0799d5b
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/LocaleTest/qmldir
@@ -0,0 +1,3 @@
+module LocaleTest
+typeinfo localeTest.qmltypes
+depends QtQml
diff --git a/tests/auto/qml/qmllint/data/MultiDefaultProperty.qml b/tests/auto/qml/qmllint/data/MultiDefaultProperty.qml
new file mode 100644
index 0000000000..a708219c96
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/MultiDefaultProperty.qml
@@ -0,0 +1,5 @@
+import QtQml
+
+QtObject {
+ default property list<Simple> xxx
+}
diff --git a/tests/auto/qml/qmllint/data/MultiDirectory/Outer.qml b/tests/auto/qml/qmllint/data/MultiDirectory/Outer.qml
new file mode 100644
index 0000000000..5dda9a4d12
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/MultiDirectory/Outer.qml
@@ -0,0 +1,5 @@
+import QtQml
+
+QtObject {
+ property int o: 12
+}
diff --git a/tests/auto/qml/qmllint/data/MultiDirectory/multi.qrc b/tests/auto/qml/qmllint/data/MultiDirectory/multi.qrc
new file mode 100644
index 0000000000..b6df21ec4c
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/MultiDirectory/multi.qrc
@@ -0,0 +1,10 @@
+<RCC>
+ <qresource prefix="/qt/qml/MultiDirectory">
+ <file>qmldir</file>
+ <file>Outer.qml</file>
+ <file>qml/qmldir</file>
+ <file>qml/Inner.qml</file>
+ <file>qml/pages/qmldir</file>
+ <file>qml/pages/Page.qml</file>
+ </qresource>
+</RCC>
diff --git a/tests/auto/qml/qmllint/data/MultiDirectory/qml/Inner.qml b/tests/auto/qml/qmllint/data/MultiDirectory/qml/Inner.qml
new file mode 100644
index 0000000000..01b7c331d9
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/MultiDirectory/qml/Inner.qml
@@ -0,0 +1,5 @@
+import QtQml
+
+Outer {
+ o: 25
+}
diff --git a/tests/auto/qml/qmllint/data/MultiDirectory/qml/pages/Page.qml b/tests/auto/qml/qmllint/data/MultiDirectory/qml/pages/Page.qml
new file mode 100644
index 0000000000..7efc889fb1
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/MultiDirectory/qml/pages/Page.qml
@@ -0,0 +1,5 @@
+import QtQml
+
+Inner {
+ o: 32
+}
diff --git a/tests/auto/qml/qmllint/data/MultiDirectory/qml/pages/qmldir b/tests/auto/qml/qmllint/data/MultiDirectory/qml/pages/qmldir
new file mode 100644
index 0000000000..56ef19d41b
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/MultiDirectory/qml/pages/qmldir
@@ -0,0 +1 @@
+prefer :/qt/qml/MultiDirectory/
diff --git a/tests/auto/qml/qmllint/data/MultiDirectory/qml/qmldir b/tests/auto/qml/qmllint/data/MultiDirectory/qml/qmldir
new file mode 100644
index 0000000000..56ef19d41b
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/MultiDirectory/qml/qmldir
@@ -0,0 +1 @@
+prefer :/qt/qml/MultiDirectory/
diff --git a/tests/auto/qml/qmllint/data/MultiDirectory/qmldir b/tests/auto/qml/qmllint/data/MultiDirectory/qmldir
new file mode 100644
index 0000000000..699132dc4f
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/MultiDirectory/qmldir
@@ -0,0 +1,5 @@
+module MultiDirectory
+prefer :/qt/qml/MultiDirectory
+Outer 1.0 Outer.qml
+Inner 1.0 qml/Inner.qml
+Page 1.0 qml/pages/Page.qml
diff --git a/tests/auto/qml/qmllint/data/MyStyle/MyStyle.qmltypes b/tests/auto/qml/qmllint/data/MyStyle/MyStyle.qmltypes
new file mode 100644
index 0000000000..92c1b0953e
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/MyStyle/MyStyle.qmltypes
@@ -0,0 +1,112 @@
+import QtQuick.tooling 1.2
+
+// This file describes the plugin-supplied types contained in the library.
+// It is used for QML tooling purposes only.
+//
+// This file was auto-generated by qmltyperegistrar.
+
+Module {
+ Component {
+ file: "mystyle.h"
+ name: "MyStyle"
+ accessSemantics: "reference"
+ prototype: "QQuickAttachedPropertyPropagator"
+ exports: ["MyStyle/MyStyle 1.0", "MyStyle/MyStyle 254.0"]
+ isCreatable: false
+ exportMetaObjectRevisions: [256, 65024]
+ attachedType: "MyStyle"
+ Enum {
+ name: "Theme"
+ values: ["Light", "Dark"]
+ }
+ Property {
+ name: "theme"
+ type: "Theme"
+ read: "theme"
+ write: "setTheme"
+ reset: "resetTheme"
+ notify: "themeChanged"
+ index: 0
+ isFinal: true
+ }
+ Property {
+ name: "windowColor"
+ type: "QColor"
+ read: "windowColor"
+ notify: "themeChanged"
+ index: 1
+ isReadonly: true
+ isFinal: true
+ }
+ Property {
+ name: "windowTextColor"
+ type: "QColor"
+ read: "windowTextColor"
+ notify: "themeChanged"
+ index: 2
+ isReadonly: true
+ isFinal: true
+ }
+ Property {
+ name: "buttonColor"
+ type: "QColor"
+ read: "buttonColor"
+ notify: "themeChanged"
+ index: 3
+ isReadonly: true
+ isFinal: true
+ }
+ Property {
+ name: "buttonTextColor"
+ type: "QColor"
+ read: "buttonTextColor"
+ notify: "themeChanged"
+ index: 4
+ isReadonly: true
+ isFinal: true
+ }
+ Property {
+ name: "toolBarColor"
+ type: "QColor"
+ read: "toolBarColor"
+ notify: "themeChanged"
+ index: 5
+ isReadonly: true
+ isFinal: true
+ }
+ Property {
+ name: "popupColor"
+ type: "QColor"
+ read: "popupColor"
+ notify: "themeChanged"
+ index: 6
+ isReadonly: true
+ isFinal: true
+ }
+ Property {
+ name: "popupBorderColor"
+ type: "QColor"
+ read: "popupBorderColor"
+ notify: "themeChanged"
+ index: 7
+ isReadonly: true
+ isFinal: true
+ }
+ Property {
+ name: "backgroundDimColor"
+ type: "QColor"
+ read: "backgroundDimColor"
+ notify: "themeChanged"
+ index: 8
+ isReadonly: true
+ isFinal: true
+ }
+ Signal { name: "themeChanged" }
+ }
+ Component {
+ file: "qquickattachedpropertypropagator.h"
+ name: "QQuickAttachedPropertyPropagator"
+ accessSemantics: "reference"
+ prototype: "QObject"
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/MyStyle/ToolBar.qml b/tests/auto/qml/qmllint/data/MyStyle/ToolBar.qml
new file mode 100644
index 0000000000..5920797d9b
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/MyStyle/ToolBar.qml
@@ -0,0 +1,12 @@
+import QtQuick
+import QtQuick.Templates as T
+import MyStyle
+
+T.ToolBar {
+ id: control
+
+ property color c: MyStyle.toolBarColor
+ background: Rectangle {
+ color: MyStyle.toolBarColor
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/MyStyle/qmldir b/tests/auto/qml/qmllint/data/MyStyle/qmldir
new file mode 100644
index 0000000000..8cc4246f7c
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/MyStyle/qmldir
@@ -0,0 +1,4 @@
+module MyStyle
+typeinfo MyStyle.qmltypes
+ToolBar 254.0 ToolBar.qml
+import QtQuick.Controls.Material
diff --git a/tests/auto/qml/qmllint/data/NeedImportPath.qml b/tests/auto/qml/qmllint/data/NeedImportPath.qml
new file mode 100644
index 0000000000..0a63b58f7c
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/NeedImportPath.qml
@@ -0,0 +1,5 @@
+import ModuleInImportPath
+
+A {
+ myProperty: "Hello World"
+}
diff --git a/tests/auto/qml/qmllint/data/NotScopedEnumCpp.qml b/tests/auto/qml/qmllint/data/NotScopedEnumCpp.qml
new file mode 100644
index 0000000000..4fbe3ec273
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/NotScopedEnumCpp.qml
@@ -0,0 +1,6 @@
+import Things
+import QtQml
+
+QtObject {
+ property int boo1: SomethingEntirelyStrange.TheEnum.V1
+}
diff --git a/tests/auto/qml/qmllint/data/NotSoSimple.qml b/tests/auto/qml/qmllint/data/NotSoSimple.qml
new file mode 100644
index 0000000000..82a0a36ef1
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/NotSoSimple.qml
@@ -0,0 +1,5 @@
+import QtQml
+
+Simple {
+ property int complicated: 433
+}
diff --git a/tests/auto/qml/qmllint/data/PluginQuickAnchorsBase.qml b/tests/auto/qml/qmllint/data/PluginQuickAnchorsBase.qml
new file mode 100644
index 0000000000..5543762bf8
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/PluginQuickAnchorsBase.qml
@@ -0,0 +1,8 @@
+import QtQuick
+
+Item {
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.top: parent.top
+ anchors.bottom: parent.bottom
+}
diff --git a/tests/auto/qml/qmllint/data/PropertyBase.qml b/tests/auto/qml/qmllint/data/PropertyBase.qml
new file mode 100644
index 0000000000..a7a3cb5bb4
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/PropertyBase.qml
@@ -0,0 +1,5 @@
+import QtQml 2.15
+
+QtObject {
+ property var foo
+}
diff --git a/tests/auto/qml/qmllint/data/PropertyBase2.qml b/tests/auto/qml/qmllint/data/PropertyBase2.qml
new file mode 100644
index 0000000000..cfb07da0f5
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/PropertyBase2.qml
@@ -0,0 +1,5 @@
+import QtQml 2.15
+
+PropertyBase {
+ foo: QtObject { property int bar: 5 }
+}
diff --git a/tests/auto/qml/qmllint/data/PropertyChangeHandlers/propertychangehandlers.qmltypes b/tests/auto/qml/qmllint/data/PropertyChangeHandlers/propertychangehandlers.qmltypes
new file mode 100644
index 0000000000..d16b97dc6c
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/PropertyChangeHandlers/propertychangehandlers.qmltypes
@@ -0,0 +1,65 @@
+import QtQuick.tooling 1.2
+Module {
+ Component {
+ file: "typewithproperties.h"
+ name: "TypeWithProperties"
+ accessSemantics: "reference"
+ prototype: "QObject"
+ exports: ["QmltcTests/TypeWithProperties 1.0"]
+ exportMetaObjectRevisions: [256]
+ Property {
+ name: "a"
+ type: "double"
+ bindable: "bindableA"
+ read: "a"
+ write: "setA"
+ index: 0
+ }
+ Property {
+ name: "b"
+ type: "QString"
+ read: "b"
+ write: "setB"
+ notify: "bChanged"
+ index: 1
+ }
+ Property {
+ name: "c"
+ type: "QVariant"
+ read: "c"
+ write: "setC"
+ notify: "cWeirdSignal"
+ index: 2
+ }
+ Property {
+ name: "d"
+ type: "QVariant"
+ bindable: "bindableD"
+ read: "d"
+ write: "setD"
+ notify: "dSignal"
+ index: 3
+ }
+ Property {
+ name: "e"
+ type: "QString"
+ bindable: "bindableE"
+ read: "e"
+ write: "setE"
+ notify: "eChanged"
+ index: 3
+ }
+ Signal { name: "bChanged" }
+ Signal {
+ name: "cWeirdSignal"
+ Parameter { type: "QVariant" }
+ }
+ Signal {
+ name: "dSignal"
+ Parameter { type: "QVariant" }
+ Parameter { type: "QString" }
+ }
+ Signal { name: "eChanged" }
+ Method { name: "wannabeSignal" }
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/PropertyChangeHandlers/qmldir b/tests/auto/qml/qmllint/data/PropertyChangeHandlers/qmldir
new file mode 100644
index 0000000000..6adb690e9c
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/PropertyChangeHandlers/qmldir
@@ -0,0 +1,3 @@
+module PropertyChangeHandlers
+typeinfo propertychangehandlers.qmltypes
+import QtQml
diff --git a/tests/auto/qml/qmllint/data/QmlBench/Globals.qml b/tests/auto/qml/qmllint/data/QmlBench/Globals.qml
new file mode 100644
index 0000000000..6531a1e7ec
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/QmlBench/Globals.qml
@@ -0,0 +1,10 @@
+pragma Singleton
+import QtQuick 2.0
+
+QtObject {
+ readonly property string stringProp: "stringValue"
+ readonly property int intProp: 10
+ readonly property real realProp: 4.5
+ readonly property color colorProp: "green"
+ readonly property bool boolProp: true
+}
diff --git a/tests/auto/qml/qmllint/data/QmlBench/Locals.qml b/tests/auto/qml/qmllint/data/QmlBench/Locals.qml
new file mode 100644
index 0000000000..3dc7d7116c
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/QmlBench/Locals.qml
@@ -0,0 +1,9 @@
+import QtQuick 2.0
+
+QtObject {
+ readonly property string stringProp: "stringValue"
+ readonly property int intProp: 10
+ readonly property real realProp: 4.5
+ readonly property color colorProp: "green"
+ readonly property bool boolProp: true
+}
diff --git a/tests/auto/qml/qmllint/data/QmlBench/qmldir b/tests/auto/qml/qmllint/data/QmlBench/qmldir
new file mode 100644
index 0000000000..a166e269e3
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/QmlBench/qmldir
@@ -0,0 +1,3 @@
+module QmlBench
+singleton Globals 1.0 Globals.qml
+Locals 1.0 Locals.qml
diff --git a/tests/auto/qml/qmllint/data/RequiredWithRootLevelAlias.qml b/tests/auto/qml/qmllint/data/RequiredWithRootLevelAlias.qml
new file mode 100644
index 0000000000..cfedd4cf01
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/RequiredWithRootLevelAlias.qml
@@ -0,0 +1,9 @@
+import QtQuick
+
+Item {
+ property alias requiredAlias: nested.foo
+ Item {
+ id: nested
+ required property string foo
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/SharedFunctions.js b/tests/auto/qml/qmllint/data/SharedFunctions.js
new file mode 100644
index 0000000000..3398d2d6d7
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/SharedFunctions.js
@@ -0,0 +1,5 @@
+.pragma library
+
+function setColorAlpha(color, alpha) {
+ return Qt.hsla(color.hslHue, color.hslSaturation, color.hslLightness, alpha)
+}
diff --git a/tests/auto/qml/qmllint/data/Singletons/MissingPragma.qml b/tests/auto/qml/qmllint/data/Singletons/MissingPragma.qml
new file mode 100644
index 0000000000..54531c4bdc
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/Singletons/MissingPragma.qml
@@ -0,0 +1,2 @@
+import QtQml
+QtObject {}
diff --git a/tests/auto/qml/qmllint/data/Singletons/MissingQmldirSingleton.qml b/tests/auto/qml/qmllint/data/Singletons/MissingQmldirSingleton.qml
new file mode 100644
index 0000000000..923966c483
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/Singletons/MissingQmldirSingleton.qml
@@ -0,0 +1,3 @@
+pragma Singleton
+import QtQml
+QtObject {}
diff --git a/tests/auto/qml/qmllint/data/Singletons/qmldir b/tests/auto/qml/qmllint/data/Singletons/qmldir
new file mode 100644
index 0000000000..84e9876b80
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/Singletons/qmldir
@@ -0,0 +1,3 @@
+module Singletons
+singleton MissingPragma 1.0 MissingPragma.qml
+MissingQmldirSingleton 1.0 MissingQmldirSingleton.qml
diff --git a/tests/auto/qml/qmllint/data/StringToDateTime/qmldir b/tests/auto/qml/qmllint/data/StringToDateTime/qmldir
new file mode 100644
index 0000000000..761f613496
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/StringToDateTime/qmldir
@@ -0,0 +1,3 @@
+module StringToDateTime
+typeinfo stringToDateTime.qmltypes
+import QtQml
diff --git a/tests/auto/qml/qmllint/data/StringToDateTime/stringToDateTime.qmltypes b/tests/auto/qml/qmllint/data/StringToDateTime/stringToDateTime.qmltypes
new file mode 100644
index 0000000000..e0f13fa2ec
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/StringToDateTime/stringToDateTime.qmltypes
@@ -0,0 +1,14 @@
+import QtQuick.tooling 1.2
+Module {
+ Component {
+ file: "stringToQDateTime.h"
+ name: "StringToDateTimeComponent"
+ exports: ["QmlLintTestLib/StringToDateTime 1.0"]
+ exportMetaObjectRevisions: [256]
+ accessSemantics: "reference"
+ prototype: "QObject"
+ Property { name: "aDate"; type: "QDate"; read: "getADate"; write: "setADate" }
+ Property { name: "aTime"; type: "QTime"; read: "getATime"; write: "setATime" }
+ Property { name: "aDateTime"; type: "QDateTime"; read: "getADateTime"; write: "setADateTime" }
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/Switch.qml b/tests/auto/qml/qmllint/data/Switch.qml
new file mode 100644
index 0000000000..e57fde4818
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/Switch.qml
@@ -0,0 +1,6 @@
+import QtQml
+
+QtObject {
+ id: control
+ property alias onLabel: control.objectName
+}
diff --git a/tests/auto/qml/qmllint/data/T/A.qml b/tests/auto/qml/qmllint/data/T/A.qml
new file mode 100644
index 0000000000..2b8d2ad52f
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/T/A.qml
@@ -0,0 +1,6 @@
+pragma Singleton
+import QtQml
+
+QtObject {
+ property int a: 10
+}
diff --git a/tests/auto/qml/qmllint/data/T/a.qrc b/tests/auto/qml/qmllint/data/T/a.qrc
new file mode 100644
index 0000000000..a419534a08
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/T/a.qrc
@@ -0,0 +1,7 @@
+<RCC>
+ <qresource prefix="/">
+ <file>qmldir</file>
+ <file>A.qml</file>
+ <file>b.qml</file>
+ </qresource>
+</RCC>
diff --git a/tests/auto/qml/qmllint/data/T/b.qml b/tests/auto/qml/qmllint/data/T/b.qml
new file mode 100644
index 0000000000..10d3c755cf
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/T/b.qml
@@ -0,0 +1,6 @@
+import QtQml
+
+QtObject {
+ property int b: A.a
+ property int e: X.a
+}
diff --git a/tests/auto/qml/qmllint/data/T/qmldir b/tests/auto/qml/qmllint/data/T/qmldir
new file mode 100644
index 0000000000..656fafd9bb
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/T/qmldir
@@ -0,0 +1,2 @@
+module T
+singleton X 1.0 A.qml
diff --git a/tests/auto/qml/qmllint/data/TestTypes/qmldir b/tests/auto/qml/qmllint/data/TestTypes/qmldir
new file mode 100644
index 0000000000..314dccb7a9
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/TestTypes/qmldir
@@ -0,0 +1,3 @@
+module TestTypes
+typeinfo testtypes.qmltypes
+
diff --git a/tests/auto/qml/qmllint/data/TestTypes/testtypes.qmltypes b/tests/auto/qml/qmllint/data/TestTypes/testtypes.qmltypes
new file mode 100644
index 0000000000..77ad6a3cef
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/TestTypes/testtypes.qmltypes
@@ -0,0 +1,201 @@
+import QtQuick.tooling 1.2
+
+// This file describes the plugin-supplied types contained in the library.
+// It is used for QML tooling purposes only.
+//
+// This file was auto-generated by qmltyperegistrar.
+
+Module {
+ Component {
+ file: "birthdayparty.h"
+ name: "BirthDayPartyExtended"
+ accessSemantics: "reference"
+ prototype: "QObject"
+ Property { name: "eee"; type: "int"; read: "eee"; write: "setEee"; notify: "eeeChanged"; index: 0 }
+ Signal { name: "eeeChanged" }
+ }
+ Component {
+ file: "birthdayparty.h"
+ name: "BirthdayParty"
+ accessSemantics: "reference"
+ prototype: "QObject"
+ extension: "BirthDayPartyExtended"
+ exports: ["TestTypes/BirthdayParty 1.0"]
+ exportMetaObjectRevisions: [256]
+ attachedType: "BirthdayPartyAttached"
+ Property {
+ name: "host"
+ type: "Person"
+ isPointer: true
+ read: "host"
+ write: "setHost"
+ notify: "hostChanged"
+ index: 0
+ isFinal: true
+ }
+ Property { name: "guests"; type: "Person"; isList: true; read: "guests"; index: 1; isReadonly: true }
+ Signal { name: "hostChanged" }
+ Method {
+ name: "invite"
+ Parameter { name: "name"; type: "QString" }
+ }
+ }
+ Component {
+ file: "birthdayparty.h"
+ name: "BirthdayPartyAttached"
+ accessSemantics: "reference"
+ prototype: "QObject"
+ Property {
+ name: "rsvp"
+ type: "QDateTime"
+ bindable: "rsvpBindable"
+ read: "rsvp"
+ write: "setRsvp"
+ index: 0
+ }
+ }
+ Component {
+ file: "cppbaseclass.h"
+ name: "CppBaseClass"
+ accessSemantics: "reference"
+ prototype: "QObject"
+ exports: ["TestTypes/CppBaseClass 1.0"]
+ exportMetaObjectRevisions: [256]
+ Property { name: "cppProp"; type: "int"; bindable: "cppPropBindable"; index: 0; isFinal: true }
+ Property { name: "cppProp2"; type: "int"; bindable: "cppProp2Bindable"; index: 1; isFinal: true }
+ Method {
+ name: "doCall"
+ Parameter { name: "foo"; type: "QObject"; isPointer: true }
+ }
+ }
+ Component {
+ file: "cppbaseclass.h"
+ name: "CppSingleton"
+ accessSemantics: "reference"
+ prototype: "QObject"
+ exports: ["TestTypes/CppSingleton 1.0"]
+ isCreatable: false
+ isSingleton: true
+ exportMetaObjectRevisions: [256]
+ }
+ Component {
+ file: "birthdayparty.h"
+ name: "Nasty"
+ accessSemantics: "reference"
+ exports: ["TestTypes/Nasty 1.0"]
+ exportMetaObjectRevisions: [256]
+ attachedType: "Nasty"
+ }
+ Component {
+ file: "objectwithmethod.h"
+ name: "ObjectWithMethod"
+ accessSemantics: "reference"
+ prototype: "QObject"
+ exports: ["TestTypes/ObjectWithMethod 1.0"]
+ exportMetaObjectRevisions: [256]
+ Property { name: "fff"; type: "int"; bindable: "theThingBindable"; index: 0; isFinal: true }
+ Method { name: "doThing"; type: "int" }
+ }
+ Component {
+ file: "person.h"
+ name: "Person"
+ accessSemantics: "reference"
+ prototype: "QObject"
+ exports: ["TestTypes/Person 1.0"]
+ exportMetaObjectRevisions: [256]
+ Property {
+ name: "name"
+ type: "QString"
+ read: "name"
+ write: "setName"
+ notify: "nameChanged"
+ index: 0
+ isFinal: true
+ }
+ Property {
+ name: "shoeSize"
+ type: "int"
+ read: "shoeSize"
+ write: "setShoeSize"
+ notify: "shoeSizeChanged"
+ index: 1
+ }
+ Signal { name: "nameChanged" }
+ Signal { name: "shoeSizeChanged" }
+ }
+ Component {
+ file: "objectwithmethod.h"
+ name: "QObject"
+ accessSemantics: "reference"
+ Property {
+ name: "objectName"
+ type: "QString"
+ bindable: "bindableObjectName"
+ read: "objectName"
+ write: "setObjectName"
+ notify: "objectNameChanged"
+ index: 0
+ }
+ Signal {
+ name: "destroyed"
+ Parameter { type: "QObject"; isPointer: true }
+ }
+ Signal { name: "destroyed" }
+ Signal {
+ name: "objectNameChanged"
+ Parameter { name: "objectName"; type: "QString" }
+ }
+ Method { name: "deleteLater" }
+ Method {
+ name: "_q_reregisterTimers"
+ Parameter { type: "void"; isPointer: true }
+ }
+ }
+ Component {
+ file: "hasbytearray.h"
+ name: "HasByteArray"
+ exports: ["TestTypes/HasByteArray 1.0"]
+ exportMetaObjectRevisions: [256]
+ accessSemantics: "reference"
+ prototype: "QObject"
+ Property {
+ name: "byteArray"
+ type: "QByteArray"
+ read: "byteArray"
+ write: "setByteArray"
+ notify: "byteArrayChanged"
+ index: 1
+ }
+ Signal { name: "byteArrayChanged" }
+ }
+
+ Component {
+ file: "somefile.h"
+ name: "someType"
+ accessSemantics: "reference"
+ prototype: "QObject"
+ exports: ["TestTypes/MyComponent 1.0"]
+ exportMetaObjectRevisions: [256]
+ Method { name: "createObject"; isJavaScriptFunction: true }
+ }
+ Component {
+ file: "variantMapLookup.h"
+ name: "VariantMapLookupFoo"
+ prototype: "QObject"
+ exports: ["TestTypes/VariantMapLookupFoo 1.0"]
+ exportMetaObjectRevisions: [256]
+ Property {
+ name: "data"
+ type: "QVariantMap"
+ read: "data"
+ index: 0
+ }
+ }
+ Component {
+ file: "foo.h"
+ name: "Foo"
+ prototype: "QObject"
+ exports: ["TestTypes/Foo 1.0"]
+ Method { name: "print" }
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/Things/LintDirectly.qml b/tests/auto/qml/qmllint/data/Things/LintDirectly.qml
new file mode 100644
index 0000000000..4384fa99f4
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/Things/LintDirectly.qml
@@ -0,0 +1,4 @@
+Pane {
+ property var thing: NotPartOfThings {}
+ property var something: Something {}
+}
diff --git a/tests/auto/qml/qmllint/data/Things/NotPartOfThings.qml b/tests/auto/qml/qmllint/data/Things/NotPartOfThings.qml
new file mode 100644
index 0000000000..16fd397d1d
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/Things/NotPartOfThings.qml
@@ -0,0 +1,3 @@
+import QtQuick
+
+Component {}
diff --git a/tests/auto/qml/qmllint/data/Things/plugins.qmltypes b/tests/auto/qml/qmllint/data/Things/plugins.qmltypes
index 9ad8c71468..47ae34cc00 100644
--- a/tests/auto/qml/qmllint/data/Things/plugins.qmltypes
+++ b/tests/auto/qml/qmllint/data/Things/plugins.qmltypes
@@ -2,18 +2,33 @@ import QtQuick.tooling 1.2
Module {
dependencies: []
Component {
+ name: "CustomPalette"
+ prototype: "QPalette"
+ }
+
+ Component {
name: "SomethingEntirelyStrange"
prototype: "QObject"
exports: ["Things/SomethingEntirelyStrange 1.0"]
Enum {
name: "AnEnum"
+ isScoped: true
values: {
"AAA": 0,
"BBB": 1,
"CCC": 2
}
}
+ Enum {
+ name: "TheEnum"
+ isScoped: false
+ values: {
+ "V1": 0,
+ "V2": 1
+ }
+ }
Property { name: "palette"; type: "QPalette" }
+ Property { name: "palette2"; type: "CustomPalette" }
}
Component {
name: "Frame"
@@ -26,12 +41,21 @@ Module {
prototype: "QObject"
exports: ["Things.Templates/Pane 1.0"]
exportMetaObjectRevisions: [256]
+ deferredNames: ["contentData"]
Property { name: "contentWidth"; type: "double" }
Property { name: "contentHeight"; type: "double" }
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"
exports: [
@@ -64,4 +88,30 @@ Module {
]
Property { name: "alignment"; type: "Qt::Alignment" }
}
+ Component {
+ name: "CustomParserThing"
+ prototype: "QQuickItem"
+ exports: [
+ "Things/CustomParserThing 1.0"
+ ]
+ Property { name: "foo"; type: "string" }
+ hasCustomParser: true
+ }
+ Component {
+ file: "mediaplayer-qml.h"
+ name: "MediaPlayerStateMachine"
+ accessSemantics: "value"
+ exports: ["Mediaplayer/MediaPlayerStateMachine 1.0"]
+ isCreatable: false
+ exportMetaObjectRevisions: [256]
+ }
+ Component {
+ file: "constinvokable.h"
+ name: "ConstInvokable"
+ accessSemantics: "reference"
+ prototype: "QObject"
+ exports: ["Things/ConstInvokable 1.0"]
+ exportMetaObjectRevisions: [256]
+ Method { name: "getObject"; type: "QObject"; isPointer: true; isConstant: true }
+ }
}
diff --git a/tests/auto/qml/qmllint/data/Things/qmldir b/tests/auto/qml/qmllint/data/Things/qmldir
index 3c48ae0648..e1d493a480 100644
--- a/tests/auto/qml/qmllint/data/Things/qmldir
+++ b/tests/auto/qml/qmllint/data/Things/qmldir
@@ -2,5 +2,5 @@ module Things
Something 1.0 SomethingElse.qml
typeinfo plugins.qmltypes
depends QtQuick 2.0
-import QtQml
-optional import QtQuick.LocalStorage auto
+import QtQml 2.0
+default import QtQuick.LocalStorage auto
diff --git a/tests/auto/qml/qmllint/data/TypeDeprecated.qml b/tests/auto/qml/qmllint/data/TypeDeprecated.qml
new file mode 100644
index 0000000000..53ae988052
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/TypeDeprecated.qml
@@ -0,0 +1,4 @@
+import QtQml
+
+@Deprecated {}
+QtObject {}
diff --git a/tests/auto/qml/qmllint/data/TypeDeprecatedReason.qml b/tests/auto/qml/qmllint/data/TypeDeprecatedReason.qml
new file mode 100644
index 0000000000..1d43c118f7
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/TypeDeprecatedReason.qml
@@ -0,0 +1,4 @@
+import QtQml
+
+@Deprecated { reason: "Test" }
+QtObject {}
diff --git a/tests/auto/qml/qmllint/data/TypeWithDefaultListProperty.qml b/tests/auto/qml/qmllint/data/TypeWithDefaultListProperty.qml
new file mode 100644
index 0000000000..e30314a825
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/TypeWithDefaultListProperty.qml
@@ -0,0 +1,4 @@
+import QtQml 2.0
+QtObject {
+ default property list<QtObject> children
+}
diff --git a/tests/auto/qml/qmllint/data/TypeWithDefaultProperty.qml b/tests/auto/qml/qmllint/data/TypeWithDefaultProperty.qml
new file mode 100644
index 0000000000..e64befb764
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/TypeWithDefaultProperty.qml
@@ -0,0 +1,4 @@
+import QtQml 2.0
+QtObject {
+ default property QtObject child
+}
diff --git a/tests/auto/qml/qmllint/data/TypeWithDefaultStringProperty.qml b/tests/auto/qml/qmllint/data/TypeWithDefaultStringProperty.qml
new file mode 100644
index 0000000000..98c446870c
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/TypeWithDefaultStringProperty.qml
@@ -0,0 +1,4 @@
+import QtQml 2.0
+QtObject {
+ default property string child
+}
diff --git a/tests/auto/qml/qmllint/data/TypeWithDefaultVarProperty.qml b/tests/auto/qml/qmllint/data/TypeWithDefaultVarProperty.qml
new file mode 100644
index 0000000000..9fa89833d5
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/TypeWithDefaultVarProperty.qml
@@ -0,0 +1,4 @@
+import QtQml 2.0
+QtObject {
+ default property var child
+}
diff --git a/tests/auto/qml/qmllint/data/TypeWithUnknownPropertyType.qml b/tests/auto/qml/qmllint/data/TypeWithUnknownPropertyType.qml
new file mode 100644
index 0000000000..dd53e414cc
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/TypeWithUnknownPropertyType.qml
@@ -0,0 +1,5 @@
+import QtQuick 2.12
+
+Item {
+ required property Something foo
+}
diff --git a/tests/auto/qml/qmllint/data/UnqualifiedInStoreSloppy.qml b/tests/auto/qml/qmllint/data/UnqualifiedInStoreSloppy.qml
new file mode 100644
index 0000000000..197b74fa60
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/UnqualifiedInStoreSloppy.qml
@@ -0,0 +1,12 @@
+import QtQuick 2.15
+import QtQuick.Window 2.15
+
+Window {
+ Rectangle {
+ property real divisor: 0
+
+ Timer {
+ onTriggered: divisor = 1
+ }
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/UnqualifiedInStoreStrict.qml b/tests/auto/qml/qmllint/data/UnqualifiedInStoreStrict.qml
new file mode 100644
index 0000000000..198e2146f5
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/UnqualifiedInStoreStrict.qml
@@ -0,0 +1,12 @@
+import QtQuick 2.15
+import QtQuick.Window 2.15
+
+Window {
+ Rectangle {
+ property real divisor: 0
+
+ Timer {
+ onTriggered: function() {"use strict"; divisor = 1 }
+ }
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/accessible.qml b/tests/auto/qml/qmllint/data/accessible.qml
new file mode 100644
index 0000000000..c68cf23648
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/accessible.qml
@@ -0,0 +1,5 @@
+import QtQuick 2.0
+
+Item {
+ Accessible.role: Accessible.EditableText
+}
diff --git a/tests/auto/qml/qmllint/data/accessibleId.qml b/tests/auto/qml/qmllint/data/accessibleId.qml
new file mode 100644
index 0000000000..904b856320
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/accessibleId.qml
@@ -0,0 +1,14 @@
+import QtQml
+
+QtObject {
+ id: a
+ property Component c: Component {
+ QtObject {
+ id: a
+ property QtObject o: QtObject {
+ property int a: 5
+ objectName: a.objectName
+ }
+ }
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/additionalImplicitImport.qml b/tests/auto/qml/qmllint/data/additionalImplicitImport.qml
new file mode 100644
index 0000000000..ef98259903
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/additionalImplicitImport.qml
@@ -0,0 +1 @@
+Pane {}
diff --git a/tests/auto/qml/qmllint/data/addressableValue.qml b/tests/auto/qml/qmllint/data/addressableValue.qml
new file mode 100644
index 0000000000..9b93728ed8
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/addressableValue.qml
@@ -0,0 +1,8 @@
+pragma ValueTypeBehavior: Addressable
+
+import QtQml
+import scripts
+
+QtObject {
+ property var v: "red" as vvv
+}
diff --git a/tests/auto/qml/qmllint/data/aliasCycle.qml b/tests/auto/qml/qmllint/data/aliasCycle.qml
new file mode 100644
index 0000000000..bdf938f1f8
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/aliasCycle.qml
@@ -0,0 +1,7 @@
+import QtQml
+
+QtObject {
+ id: self
+ property alias a: self.b
+ property alias b: self.a
+}
diff --git a/tests/auto/qml/qmllint/data/aliasToList.qml b/tests/auto/qml/qmllint/data/aliasToList.qml
new file mode 100644
index 0000000000..890bb9eeda
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/aliasToList.qml
@@ -0,0 +1,6 @@
+import QtQuick 2.15
+
+AliasListType {
+ Item {}
+ Item {}
+}
diff --git a/tests/auto/qml/qmllint/data/animationEasing.qml b/tests/auto/qml/qmllint/data/animationEasing.qml
new file mode 100644
index 0000000000..1b0c9ffea4
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/animationEasing.qml
@@ -0,0 +1,5 @@
+import QtQml
+import QtQuick
+NumberAnimation {
+ easing.type: Easing.InOutQuad
+}
diff --git a/tests/auto/qml/qmllint/data/assignNonExistingTypeToVarProp.qml b/tests/auto/qml/qmllint/data/assignNonExistingTypeToVarProp.qml
new file mode 100644
index 0000000000..dae699fae5
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/assignNonExistingTypeToVarProp.qml
@@ -0,0 +1,6 @@
+import QtQuick
+
+ListView {
+ // model is a QVariant, so we can theoretically assign anything to it
+ model: NonExistingType {}
+}
diff --git a/tests/auto/qml/qmllint/data/assignToReadOnlyProperty.qml b/tests/auto/qml/qmllint/data/assignToReadOnlyProperty.qml
new file mode 100644
index 0000000000..0f1e6f8cd7
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/assignToReadOnlyProperty.qml
@@ -0,0 +1,5 @@
+import QtQuick 2.0
+
+Item {
+ activeFocus: true
+}
diff --git a/tests/auto/qml/qmllint/data/assignToReadOnlyProperty2.qml b/tests/auto/qml/qmllint/data/assignToReadOnlyProperty2.qml
new file mode 100644
index 0000000000..5e2b8408af
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/assignToReadOnlyProperty2.qml
@@ -0,0 +1,6 @@
+import QtQuick 2.0
+
+Item {
+ id: item
+ Component.onCompleted: activeFocus = false
+}
diff --git a/tests/auto/qml/qmllint/data/attachedImportUse.qml b/tests/auto/qml/qmllint/data/attachedImportUse.qml
new file mode 100644
index 0000000000..56b4e2bf7c
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/attachedImportUse.qml
@@ -0,0 +1,7 @@
+import QtQml
+import TestTypes
+
+QtObject {
+ id: control
+ objectName: control.BirthdayParty.objectName
+}
diff --git a/tests/auto/qml/qmllint/data/attachedPropEnum.qml b/tests/auto/qml/qmllint/data/attachedPropEnum.qml
new file mode 100644
index 0000000000..3149de04a0
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/attachedPropEnum.qml
@@ -0,0 +1,9 @@
+import QtQuick
+
+Text {
+ id: root
+ text: KeyNavigation.priority == KeyNavigation.BeforeItem ? "before" : "after"
+ Text {
+ text: root.KeyNavigation.priority == KeyNavigation.BeforeItem ? "before" : "after"
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/attachedPropNotReused.qml b/tests/auto/qml/qmllint/data/attachedPropNotReused.qml
new file mode 100644
index 0000000000..456ccd3d7d
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/attachedPropNotReused.qml
@@ -0,0 +1,8 @@
+import QtQuick
+
+Text {
+ text: KeyNavigation.priority == KeyNavigation.BeforeItem ? "before" : "after"
+ Text {
+ text: KeyNavigation.priority == KeyNavigation.BeforeItem ? "before" : "after"
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/attachedPropertyAssignments.qml b/tests/auto/qml/qmllint/data/attachedPropertyAssignments.qml
new file mode 100644
index 0000000000..5ef62f8626
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/attachedPropertyAssignments.qml
@@ -0,0 +1,5 @@
+import AttachedProperties 1.0
+QtObject {
+ TestType.count: 42
+ TestType.str: "hello"
+}
diff --git a/tests/auto/qml/qmllint/data/attachedTypeIndirect.qml b/tests/auto/qml/qmllint/data/attachedTypeIndirect.qml
new file mode 100644
index 0000000000..65598a26cd
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/attachedTypeIndirect.qml
@@ -0,0 +1,5 @@
+import QtQml 2.0
+
+QtObject {
+ GrdView.delayRemove: true
+}
diff --git a/tests/auto/qml/qmllint/data/badAliasExpression.qml b/tests/auto/qml/qmllint/data/badAliasExpression.qml
new file mode 100644
index 0000000000..655509c783
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/badAliasExpression.qml
@@ -0,0 +1,6 @@
+import QtQml
+
+QtObject {
+ id: self
+ property alias name: self.objectName + 5
+}
diff --git a/tests/auto/qml/qmllint/data/badAliasNotAnExpression.qml b/tests/auto/qml/qmllint/data/badAliasNotAnExpression.qml
new file mode 100644
index 0000000000..cdc2b28c07
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/badAliasNotAnExpression.qml
@@ -0,0 +1,8 @@
+import QtQuick 2.0
+Item {
+
+ property alias innerObj: {
+ id: inner
+ }
+
+}
diff --git a/tests/auto/qml/qmllint/data/badAttachedProperty.qml b/tests/auto/qml/qmllint/data/badAttachedProperty.qml
new file mode 100644
index 0000000000..c3f81c8058
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/badAttachedProperty.qml
@@ -0,0 +1,8 @@
+import AttachedProperties 1.0
+QtObject {
+ TestType.object: Component {}
+
+ Component.onCompleted: {
+ console.log(TestType.progress) // wrong, as progress should be a property of TestType.object
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/badAttachedPropertyNested.qml b/tests/auto/qml/qmllint/data/badAttachedPropertyNested.qml
new file mode 100644
index 0000000000..4c88a263dd
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/badAttachedPropertyNested.qml
@@ -0,0 +1,15 @@
+import AttachedProperties 1.0
+QtObject {
+ TestType.object: Component {}
+
+ Component.onCompleted: {
+ console.log(TestType.object.progress);
+ }
+
+ property QtObject child: QtObject {
+ Component.onCompleted: {
+ // doesn't work: this type's TestType.object is not set
+ console.log(TestType.object.progress);
+ }
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/badAttachedPropertyTypeQtObject.qml b/tests/auto/qml/qmllint/data/badAttachedPropertyTypeQtObject.qml
new file mode 100644
index 0000000000..8aa241bb64
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/badAttachedPropertyTypeQtObject.qml
@@ -0,0 +1,5 @@
+import AttachedProperties 1.0
+QtObject {
+ // count has type int, so assigning QtObject to it is wrong
+ TestType.count: QtObject {}
+}
diff --git a/tests/auto/qml/qmllint/data/badAttachedPropertyTypeString.qml b/tests/auto/qml/qmllint/data/badAttachedPropertyTypeString.qml
new file mode 100644
index 0000000000..b06052d93f
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/badAttachedPropertyTypeString.qml
@@ -0,0 +1,5 @@
+import AttachedProperties 1.0
+QtObject {
+ // count has type int, so assigning string to it is wrong
+ TestType.count: "hello, world"
+}
diff --git a/tests/auto/qml/qmllint/data/badCppPropertyChangeHandlers1.qml b/tests/auto/qml/qmllint/data/badCppPropertyChangeHandlers1.qml
new file mode 100644
index 0000000000..a2d1c14aaa
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/badCppPropertyChangeHandlers1.qml
@@ -0,0 +1,4 @@
+import PropertyChangeHandlers 1.0
+TypeWithProperties {
+ onAChanged: function(value) { console.log("error!", value); }
+}
diff --git a/tests/auto/qml/qmllint/data/badCppPropertyChangeHandlers2.qml b/tests/auto/qml/qmllint/data/badCppPropertyChangeHandlers2.qml
new file mode 100644
index 0000000000..8e6ed938b0
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/badCppPropertyChangeHandlers2.qml
@@ -0,0 +1,4 @@
+import PropertyChangeHandlers 1.0
+TypeWithProperties {
+ onBChanged: function(value) { console.log("error!", value); }
+}
diff --git a/tests/auto/qml/qmllint/data/badCppPropertyChangeHandlers3.qml b/tests/auto/qml/qmllint/data/badCppPropertyChangeHandlers3.qml
new file mode 100644
index 0000000000..58b56128d2
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/badCppPropertyChangeHandlers3.qml
@@ -0,0 +1,4 @@
+import PropertyChangeHandlers 1.0
+TypeWithProperties {
+ onXChanged: { console.log("error!"); }
+}
diff --git a/tests/auto/qml/qmllint/data/badCppPropertyChangeHandlers4.qml b/tests/auto/qml/qmllint/data/badCppPropertyChangeHandlers4.qml
new file mode 100644
index 0000000000..6526a46a8c
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/badCppPropertyChangeHandlers4.qml
@@ -0,0 +1,4 @@
+import PropertyChangeHandlers 1.0
+TypeWithProperties {
+ onWannabeSignal: { console.log("error!"); }
+}
diff --git a/tests/auto/qml/qmllint/data/badGeneralizedGroup1.qml b/tests/auto/qml/qmllint/data/badGeneralizedGroup1.qml
new file mode 100644
index 0000000000..95d38d42de
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/badGeneralizedGroup1.qml
@@ -0,0 +1,9 @@
+import QtQuick
+import Things
+
+Item {
+ id: self
+ WithImmediate {
+ self.aaaa: 15 - 1
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/badGeneralizedGroup2.qml b/tests/auto/qml/qmllint/data/badGeneralizedGroup2.qml
new file mode 100644
index 0000000000..546aad50ab
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/badGeneralizedGroup2.qml
@@ -0,0 +1,9 @@
+import QtQuick
+import Things
+
+Item {
+ id: self
+ WithImmediate {
+ aself.x: 15 - 1
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/badLiteralBinding.qml b/tests/auto/qml/qmllint/data/badLiteralBinding.qml
new file mode 100644
index 0000000000..b3cfc8f4ee
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/badLiteralBinding.qml
@@ -0,0 +1,4 @@
+import QtQuick
+Item {
+ property int int1: "foo"
+}
diff --git a/tests/auto/qml/qmllint/data/badLiteralBindingDate.qml b/tests/auto/qml/qmllint/data/badLiteralBindingDate.qml
new file mode 100644
index 0000000000..5a62a97083
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/badLiteralBindingDate.qml
@@ -0,0 +1,4 @@
+import QtQuick
+Item {
+ property date date1: "not a valid date"
+}
diff --git a/tests/auto/qml/qmllint/data/badModulePrefix.qml b/tests/auto/qml/qmllint/data/badModulePrefix.qml
new file mode 100644
index 0000000000..e3b513d149
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/badModulePrefix.qml
@@ -0,0 +1,7 @@
+import QtQml
+import TestTypes as T
+
+QtObject {
+ id: self
+ property string baz: self.T.CppSingleton.objectName
+}
diff --git a/tests/auto/qml/qmllint/data/badModulePrefix2.qml b/tests/auto/qml/qmllint/data/badModulePrefix2.qml
new file mode 100644
index 0000000000..f7bf73e180
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/badModulePrefix2.qml
@@ -0,0 +1,7 @@
+import QtQml
+import TestTypes as T
+
+QtObject {
+ property rect rr
+ property date foo: rr.T.BirthdayParty.rsvp
+}
diff --git a/tests/auto/qml/qmllint/data/badScript.attached.qml b/tests/auto/qml/qmllint/data/badScript.attached.qml
new file mode 100644
index 0000000000..f3183430fc
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/badScript.attached.qml
@@ -0,0 +1,4 @@
+import QtQuick
+Text {
+ font.pixelSize: 10 + pointSize * 0.1 // pointSize does not exist in the scope of the binding
+}
diff --git a/tests/auto/qml/qmllint/data/badScriptBinding.attached.qml b/tests/auto/qml/qmllint/data/badScriptBinding.attached.qml
new file mode 100644
index 0000000000..a5ec7d9050
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/badScriptBinding.attached.qml
@@ -0,0 +1,6 @@
+import QtQuick.Layouts
+RowLayout {
+ function returnTrue() { return true; }
+ Layout.fillWidth: returnTrue()
+ Layout.bogusProperty: returnTrue()
+}
diff --git a/tests/auto/qml/qmllint/data/badScriptBinding.attachedSignalHandler.qml b/tests/auto/qml/qmllint/data/badScriptBinding.attachedSignalHandler.qml
new file mode 100644
index 0000000000..56d89a81da
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/badScriptBinding.attachedSignalHandler.qml
@@ -0,0 +1,7 @@
+import QtQuick
+Rectangle {
+ Keys.onBogusSignal: function(event) {
+ // the handler is good, but the signal doesn't exist
+ console.log(event);
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/badScriptBinding.group.qml b/tests/auto/qml/qmllint/data/badScriptBinding.group.qml
new file mode 100644
index 0000000000..d92feb81f0
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/badScriptBinding.group.qml
@@ -0,0 +1,4 @@
+import QtQuick
+Text {
+ font.bogusProperty: "foo" + "bar"
+}
diff --git a/tests/auto/qml/qmllint/data/badTemplateStringSimple.qml b/tests/auto/qml/qmllint/data/badTemplateStringSimple.qml
new file mode 100644
index 0000000000..21c98943f2
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/badTemplateStringSimple.qml
@@ -0,0 +1,5 @@
+import QtQml
+
+QtObject {
+ property int i: `hallo`
+}
diff --git a/tests/auto/qml/qmllint/data/bad_QT_TR_NOOP.qml b/tests/auto/qml/qmllint/data/bad_QT_TR_NOOP.qml
new file mode 100644
index 0000000000..1e7b315dc5
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/bad_QT_TR_NOOP.qml
@@ -0,0 +1,5 @@
+import QtQml
+
+QtObject {
+ property int i: QT_TR_NOOP("fail")
+}
diff --git a/tests/auto/qml/qmllint/data/bad_builtins/builtins.qmltypes b/tests/auto/qml/qmllint/data/bad_builtins/builtins.qmltypes
new file mode 100644
index 0000000000..96f98dd14e
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/bad_builtins/builtins.qmltypes
@@ -0,0 +1,513 @@
+import QtQuick.tooling 1.2
+
+// This file describes the plugin-supplied types contained in the library.
+// It is used for QML tooling purposes only.
+//
+// This file was auto-generated by:
+// 'qmlplugindump -builtins'
+
+Module {
+ dependencies: []
+ Component {
+ name: "Qt"
+ Enum {
+ name: "GlobalColor"
+ values: {
+ "color0": 0,
+ "color1": 1,
+ "black": 2,
+ "white": 3,
+ "darkGray": 4,
+ "gray": 5,
+ "lightGray": 6,
+ "red": 7,
+ "green": 8,
+ "blue": 9,
+ "cyan": 10,
+ "magenta": 11,
+ "yellow": 12,
+ "darkRed": 13,
+ "darkGreen": 14,
+ "darkBlue": 15,
+ "darkCyan": 16,
+ "darkMagenta": 17,
+ "darkYellow": 18,
+ "transparent": 19
+ }
+ }
+ Enum {
+ name: "KeyboardModifiers"
+ values: {
+ "NoModifier": 0,
+ "ShiftModifier": 33554432,
+ "ControlModifier": 67108864,
+ "AltModifier": 134217728,
+ "MetaModifier": 268435456,
+ "KeypadModifier": 536870912,
+ "GroupSwitchModifier": 1073741824,
+ "KeyboardModifierMask": -33554432
+ }
+ }
+ Enum {
+ name: "MouseButtons"
+ values: {
+ "NoButton": 0,
+ "LeftButton": 1,
+ "RightButton": 2,
+ "MidButton": 4, // For backwards compatibility
+ "MiddleButton": 4,
+ "BackButton": 8,
+ "XButton1": 8,
+ "ExtraButton1": 8,
+ "ForwardButton": 16,
+ "XButton2": 16,
+ "ExtraButton2": 16,
+ "TaskButton": 32,
+ "ExtraButton3": 32,
+ "ExtraButton4": 64,
+ "ExtraButton5": 128,
+ "ExtraButton6": 256,
+ "ExtraButton7": 512,
+ "ExtraButton8": 1024,
+ "ExtraButton9": 2048,
+ "ExtraButton10": 4096,
+ "ExtraButton11": 8192,
+ "ExtraButton12": 16384,
+ "ExtraButton13": 32768,
+ "ExtraButton14": 65536,
+ "ExtraButton15": 131072,
+ "ExtraButton16": 262144,
+ "ExtraButton17": 524288,
+ "ExtraButton18": 1048576,
+ "ExtraButton19": 2097152,
+ "ExtraButton20": 4194304,
+ "ExtraButton21": 8388608,
+ "ExtraButton22": 16777216,
+ "ExtraButton23": 33554432,
+ "ExtraButton24": 67108864,
+ "AllButtons": 134217727,
+ "MaxMouseButton": 67108864,
+ "MouseButtonMask": -1
+ }
+ }
+ Enum {
+ name: "Orientation"
+ values: {
+ "Horizontal": 1,
+ "Vertical": 2
+ }
+ }
+ Enum {
+ name: "Orientations"
+ values: {
+ "Horizontal": 1,
+ "Vertical": 2
+ }
+ }
+ Enum {
+ name: "FocusPolicy"
+ values: {
+ "NoFocus": 0,
+ "TabFocus": 1,
+ "ClickFocus": 2,
+ "StrongFocus": 11,
+ "WheelFocus": 15
+ }
+ }
+ Enum {
+ name: "TabFocusBehavior"
+ values: {
+ "NoTabFocus": 0,
+ "TabFocusTextControls": 1,
+ "TabFocusListControls": 2,
+ "TabFocusAllControls": 255
+ }
+ }
+ Enum {
+ name: "SortOrder"
+ values: {
+ "AscendingOrder": 0,
+ "DescendingOrder": 1
+ }
+ }
+ Enum {
+ name: "SplitBehavior"
+ values: {
+ "KeepEmptyParts": 0,
+ "SkipEmptyParts": 1
+ }
+ }
+ Enum {
+ name: "Alignment"
+ values: {
+ "AlignLeft": 1,
+ "AlignLeading": 1,
+ "AlignRight": 2,
+ "AlignTrailing": 2,
+ "AlignHCenter": 4,
+ "AlignJustify": 8,
+ "AlignAbsolute": 16,
+ "AlignHorizontal_Mask": 31,
+ "AlignTop": 32,
+ "AlignBottom": 64,
+ "AlignVCenter": 128,
+ "AlignBaseline": 256,
+ "AlignVertical_Mask": 480,
+ "AlignCenter": 132
+ }
+ }
+ Enum {
+ name: "TextFlag"
+ values: {
+ "TextSingleLine": 256,
+ "TextDontClip": 512,
+ "TextExpandTabs": 1024,
+ "TextShowMnemonic": 2048,
+ "TextWordWrap": 4096,
+ "TextWrapAnywhere": 8192,
+ "TextDontPrint": 16384,
+ "TextIncludeTrailingSpaces": 134217728,
+ "TextHideMnemonic": 32768,
+ "TextJustificationForced": 65536,
+ "TextForceLeftToRight": 131072,
+ "TextForceRightToLeft": 262144,
+ "TextLongestVariant": 524288,
+ "TextBypassShaping": 1048576
+ }
+ }
+ Enum {
+ name: "TextElideMode"
+ values: {
+ "ElideLeft": 0,
+ "ElideRight": 1,
+ "ElideMiddle": 2,
+ "ElideNone": 3
+ }
+ }
+ Enum {
+ name: "WindowType"
+ values: {
+ "Widget": 0,
+ "Window": 1,
+ "Dialog": 3,
+ "Sheet": 5,
+ "Drawer": 7,
+ "Popup": 9,
+ "Tool": 11,
+ "ToolTip": 13,
+ "SplashScreen": 15,
+ "Desktop": 17,
+ "SubWindow": 18,
+ "ForeignWindow": 33,
+ "CoverWindow": 65,
+ "WindowType_Mask": 255,
+ "MSWindowsFixedSizeDialogHint": 256,
+ "MSWindowsOwnDC": 512,
+ "BypassWindowManagerHint": 1024,
+ "X11BypassWindowManagerHint": 1024,
+ "FramelessWindowHint": 2048,
+ "WindowTitleHint": 4096,
+ "WindowSystemMenuHint": 8192,
+ "WindowMinimizeButtonHint": 16384,
+ "WindowMaximizeButtonHint": 32768,
+ "WindowMinMaxButtonsHint": 49152,
+ "WindowContextHelpButtonHint": 65536,
+ "WindowShadeButtonHint": 131072,
+ "WindowStaysOnTopHint": 262144,
+ "WindowTransparentForInput": 524288,
+ "WindowOverridesSystemGestures": 1048576,
+ "WindowDoesNotAcceptFocus": 2097152,
+ "MaximizeUsingFullscreenGeometryHint": 4194304,
+ "CustomizeWindowHint": 33554432,
+ "WindowStaysOnBottomHint": 67108864,
+ "WindowCloseButtonHint": 134217728,
+ "MacWindowToolBarButtonHint": 268435456,
+ "BypassGraphicsProxyWidget": 536870912,
+ "NoDropShadowWindowHint": 1073741824,
+ "WindowFullscreenButtonHint": -2147483648
+ }
+ }
+ Enum {
+ name: "WindowFlags"
+ values: {
+ "Widget": 0,
+ "Window": 1,
+ "Dialog": 3,
+ "Sheet": 5,
+ "Drawer": 7,
+ "Popup": 9,
+ "Tool": 11,
+ "ToolTip": 13,
+ "SplashScreen": 15,
+ "Desktop": 17,
+ "SubWindow": 18,
+ "ForeignWindow": 33,
+ "CoverWindow": 65,
+ "WindowType_Mask": 255,
+ "MSWindowsFixedSizeDialogHint": 256,
+ "MSWindowsOwnDC": 512,
+ "BypassWindowManagerHint": 1024,
+ "X11BypassWindowManagerHint": 1024,
+ "FramelessWindowHint": 2048,
+ "WindowTitleHint": 4096,
+ "WindowSystemMenuHint": 8192,
+ "WindowMinimizeButtonHint": 16384,
+ "WindowMaximizeButtonHint": 32768,
+ "WindowMinMaxButtonsHint": 49152,
+ "WindowContextHelpButtonHint": 65536,
+ "WindowShadeButtonHint": 131072,
+ "WindowStaysOnTopHint": 262144,
+ "WindowTransparentForInput": 524288,
+ "WindowOverridesSystemGestures": 1048576,
+ "WindowDoesNotAcceptFocus": 2097152,
+ "MaximizeUsingFullscreenGeometryHint": 4194304,
+ "CustomizeWindowHint": 33554432,
+ "WindowStaysOnBottomHint": 67108864,
+ "WindowCloseButtonHint": 134217728,
+ "MacWindowToolBarButtonHint": 268435456,
+ "BypassGraphicsProxyWidget": 536870912,
+ "NoDropShadowWindowHint": 1073741824,
+ "WindowFullscreenButtonHint": -2147483648
+ }
+ }
+ Enum {
+ name: "WindowState"
+ values: {
+ "WindowNoState": 0,
+ "WindowMinimized": 1,
+ "WindowMaximized": 2,
+ "WindowFullScreen": 4,
+ "WindowActive": 8
+ }
+ }
+ Enum {
+ name: "WindowStates"
+ values: {
+ "WindowNoState": 0,
+ "WindowMinimized": 1,
+ "WindowMaximized": 2,
+ "WindowFullScreen": 4,
+ "WindowActive": 8
+ }
+ }
+ Enum {
+ name: "ApplicationState"
+ values: {
+ "ApplicationSuspended": 0,
+ "ApplicationHidden": 1,
+ "ApplicationInactive": 2,
+ "ApplicationActive": 4
+ }
+ }
+ Enum {
+ name: "ScreenOrientation"
+ values: {
+ "PrimaryOrientation": 0,
+ "PortraitOrientation": 1,
+ "LandscapeOrientation": 2,
+ "InvertedPortraitOrientation": 4,
+ "InvertedLandscapeOrientation": 8
+ }
+ }
+ Enum {
+ name: "ScreenOrientations"
+ values: {
+ "PrimaryOrientation": 0,
+ "PortraitOrientation": 1,
+ "LandscapeOrientation": 2,
+ "InvertedPortraitOrientation": 4,
+ "InvertedLandscapeOrientation": 8
+ }
+ }
+ Enum {
+ name: "WidgetAttribute"
+ values: {
+ "WA_Disabled": 0,
+ "WA_UnderMouse": 1,
+ "WA_MouseTracking": 2,
+ "WA_ContentsPropagated": 3,
+ "WA_OpaquePaintEvent": 4,
+ "WA_NoBackground": 4,
+ "WA_StaticContents": 5,
+ "WA_LaidOut": 7,
+ "WA_PaintOnScreen": 8,
+ "WA_NoSystemBackground": 9,
+ "WA_UpdatesDisabled": 10,
+ "WA_Mapped": 11,
+ "WA_MacNoClickThrough": 12,
+ "WA_InputMethodEnabled": 14,
+ "WA_WState_Visible": 15,
+ "WA_WState_Hidden": 16,
+ "WA_ForceDisabled": 32,
+ "WA_KeyCompression": 33,
+ "WA_PendingMoveEvent": 34,
+ "WA_PendingResizeEvent": 35,
+ "WA_SetPalette": 36,
+ "WA_SetFont": 37,
+ "WA_SetCursor": 38,
+ "WA_NoChildEventsFromChildren": 39,
+ "WA_WindowModified": 41,
+ "WA_Resized": 42,
+ "WA_Moved": 43,
+ "WA_PendingUpdate": 44,
+ "WA_InvalidSize": 45,
+ "WA_MacBrushedMetal": 46,
+ "WA_MacMetalStyle": 46,
+ "WA_CustomWhatsThis": 47,
+ "WA_LayoutOnEntireRect": 48,
+ "WA_OutsideWSRange": 49,
+ "WA_GrabbedShortcut": 50,
+ "WA_TransparentForMouseEvents": 51,
+ "WA_PaintUnclipped": 52,
+ "WA_SetWindowIcon": 53,
+ "WA_NoMouseReplay": 54,
+ "WA_DeleteOnClose": 55,
+ "WA_RightToLeft": 56,
+ "WA_SetLayoutDirection": 57,
+ "WA_NoChildEventsForParent": 58,
+ "WA_ForceUpdatesDisabled": 59,
+ "WA_WState_Created": 60,
+ "WA_WState_CompressKeys": 61,
+ "WA_WState_InPaintEvent": 62,
+ "WA_WState_Reparented": 63,
+ "WA_WState_ConfigPending": 64,
+ "WA_WState_Polished": 66,
+ "WA_WState_DND": 67,
+ "WA_WState_OwnSizePolicy": 68,
+ "WA_WState_ExplicitShowHide": 69,
+ "WA_ShowModal": 70,
+ "WA_MouseNoMask": 71,
+ "WA_GroupLeader": 72,
+ "WA_NoMousePropagation": 73,
+ "WA_Hover": 74,
+ "WA_InputMethodTransparent": 75,
+ "WA_QuitOnClose": 76,
+ "WA_KeyboardFocusChange": 77,
+ "WA_AcceptDrops": 78,
+ "WA_DropSiteRegistered": 79,
+ "WA_ForceAcceptDrops": 79,
+ "WA_WindowPropagation": 80,
+ "WA_NoX11EventCompression": 81,
+ "WA_TintedBackground": 82,
+ "WA_X11OpenGLOverlay": 83,
+ "WA_AlwaysShowToolTips": 84,
+ "WA_MacOpaqueSizeGrip": 85,
+ "WA_SetStyle": 86,
+ "WA_SetLocale": 87,
+ "WA_MacShowFocusRect": 88,
+ "WA_MacNormalSize": 89,
+ "WA_MacSmallSize": 90,
+ "WA_MacMiniSize": 91,
+ "WA_LayoutUsesWidgetRect": 92,
+ "WA_StyledBackground": 93,
+ "WA_MSWindowsUseDirect3D": 94,
+ "WA_CanHostQMdiSubWindowTitleBar": 95,
+ "WA_MacAlwaysShowToolWindow": 96,
+ "WA_StyleSheet": 97,
+ "WA_ShowWithoutActivating": 98,
+ "WA_X11BypassTransientForHint": 99,
+ "WA_NativeWindow": 100,
+ "WA_DontCreateNativeAncestors": 101,
+ "WA_MacVariableSize": 102,
+ "WA_DontShowOnScreen": 103,
+ "WA_X11NetWmWindowTypeDesktop": 104,
+ "WA_X11NetWmWindowTypeDock": 105,
+ "WA_X11NetWmWindowTypeToolBar": 106,
+ "WA_X11NetWmWindowTypeMenu": 107,
+ "WA_X11NetWmWindowTypeUtility": 108,
+ "WA_X11NetWmWindowTypeSplash": 109,
+ "WA_X11NetWmWindowTypeDialog": 110,
+ "WA_X11NetWmWindowTypeDropDownMenu": 111,
+ "WA_X11NetWmWindowTypePopupMenu": 112,
+ "WA_X11NetWmWindowTypeToolTip": 113,
+ "WA_X11NetWmWindowTypeNotification": 114,
+ "WA_X11NetWmWindowTypeCombo": 115,
+ "WA_X11NetWmWindowTypeDND": 116,
+ "WA_MacFrameworkScaled": 117,
+ "WA_SetWindowModality": 118,
+ "WA_WState_WindowOpacitySet": 119,
+ "WA_TranslucentBackground": 120,
+ "WA_AcceptTouchEvents": 121,
+ "WA_WState_AcceptedTouchBeginEvent": 122,
+ "WA_TouchPadAcceptSingleTouchEvents": 123,
+ "WA_X11DoNotAcceptFocus": 126,
+ "WA_MacNoShadow": 127,
+ "WA_AlwaysStackOnTop": 128,
+ "WA_TabletTracking": 129,
+ "WA_ContentsMarginsRespectsSafeArea": 130,
+ "WA_StyleSheetTarget": 131,
+ "WA_AttributeCount": 132
+ }
+ }
+ Enum {
+ name: "ApplicationAttribute"
+ values: {
+ "AA_ImmediateWidgetCreation": 0,
+ "AA_MSWindowsUseDirect3DByDefault": 1,
+ "AA_DontShowIconsInMenus": 2,
+ "AA_NativeWindows": 3,
+ "AA_DontCreateNativeWidgetSiblings": 4,
+ "AA_PluginApplication": 5,
+ "AA_MacPluginApplication": 5,
+ "AA_DontUseNativeMenuBar": 6,
+ "AA_MacDontSwapCtrlAndMeta": 7,
+ "AA_Use96Dpi": 8,
+ "AA_X11InitThreads": 10,
+ "AA_SynthesizeTouchForUnhandledMouseEvents": 11,
+ "AA_SynthesizeMouseForUnhandledTouchEvents": 12,
+ "AA_UseHighDpiPixmaps": 13,
+ "AA_ForceRasterWidgets": 14,
+ "AA_UseDesktopOpenGL": 15,
+ "AA_UseOpenGLES": 16,
+ "AA_UseSoftwareOpenGL": 17,
+ "AA_ShareOpenGLContexts": 18,
+ "AA_SetPalette": 19,
+ "AA_EnableHighDpiScaling": 20,
+ "AA_DisableHighDpiScaling": 21,
+ "AA_UseStyleSheetPropagationInWidgetStyles": 22,
+ "AA_DontUseNativeDialogs": 23,
+ "AA_SynthesizeMouseForUnhandledTabletEvents": 24,
+ "AA_CompressHighFrequencyEvents": 25,
+ "AA_DontCheckOpenGLContextThreadAffinity": 26,
+ "AA_DisableShaderDiskCache": 27,
+ "AA_DontShowShortcutsInContextMenus": 28,
+ "AA_CompressTabletEvents": 29,
+ "AA_DisableWindowContextHelpButton": 30,
+ "AA_DisableSessionManager": 31,
+ "AA_AttributeCount": 32
+ }
+ }
+ Enum {
+ name: "ImageConversionFlags"
+ values: {
+ "ColorMode_Mask": 3,
+ "AutoColor": 0,
+ "ColorOnly": 3,
+ "MonoOnly": 2,
+ "AlphaDither_Mask": 12,
+ "ThresholdAlphaDither": 0,
+ "OrderedAlphaDither": 4,
+ "DiffuseAlphaDither": 8,
+ "NoAlpha": 12,
+ "Dither_Mask": 48,
+ "DiffuseDither": 0,
+ "OrderedDither": 16,
+ "ThresholdDither": 32,
+ "DitherMode_Mask": 192,
+ "AutoDither": 0,
+ "PreferDither": 64,
+ "AvoidDither": 128,
+ "NoOpaqueDetection": 256,
+ "NoFormatConversion": 512
+ }
+ }
+ Enum {
+ name: "BGMode"
+ values: {
+ "TransparentMode": 0,
+ "OpaqueMode": 1
+ }
+ }
+ }
+ Component { name: "QEasingCurve"; prototype: "QQmlEasingValueType" }
+}
diff --git a/tests/auto/qml/qmllint/data/bad_qsTr.qml b/tests/auto/qml/qmllint/data/bad_qsTr.qml
new file mode 100644
index 0000000000..3723324a72
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/bad_qsTr.qml
@@ -0,0 +1,5 @@
+import QtQml
+
+QtObject {
+ property int i: qsTr("fail")
+}
diff --git a/tests/auto/qml/qmllint/data/badlyBoundComponents.qml b/tests/auto/qml/qmllint/data/badlyBoundComponents.qml
new file mode 100644
index 0000000000..4f25f1d508
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/badlyBoundComponents.qml
@@ -0,0 +1,25 @@
+pragma ComponentBehavior: Bound
+
+import QtQml
+
+QtObject {
+ id: root
+ property string foo: "bar"
+ property Component c1: Component {
+ QtObject {
+ id: cc
+ objectName: root.foo
+ property int i: 12
+ }
+ }
+
+ property Component c2: Component {
+ QtObject {
+ objectName: root.foo + cc.i
+ }
+ }
+
+ property QtObject o1: c1.createObject()
+ property QtObject o2: c2.createObject()
+
+}
diff --git a/tests/auto/qml/qmllint/data/bareQt.qml b/tests/auto/qml/qmllint/data/bareQt.qml
new file mode 100644
index 0000000000..331a66345d
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/bareQt.qml
@@ -0,0 +1,5 @@
+import QML
+
+QtObject {
+ property var a: Qt.application
+}
diff --git a/tests/auto/qml/qmllint/data/bindingBeforeDeclaration.qml b/tests/auto/qml/qmllint/data/bindingBeforeDeclaration.qml
new file mode 100644
index 0000000000..7fc592d7f0
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/bindingBeforeDeclaration.qml
@@ -0,0 +1,6 @@
+import QtQuick
+
+Item {
+ binding: QtObject {}
+ property QtObject binding
+}
diff --git a/tests/auto/qml/qmllint/data/bindingTypeMismatch.qml b/tests/auto/qml/qmllint/data/bindingTypeMismatch.qml
new file mode 100644
index 0000000000..ffde545e7d
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/bindingTypeMismatch.qml
@@ -0,0 +1,5 @@
+import QtQuick
+
+Item {
+ property int number: 3 + "Hello"
+}
diff --git a/tests/auto/qml/qmllint/data/bindingTypeMismatchFunction.qml b/tests/auto/qml/qmllint/data/bindingTypeMismatchFunction.qml
new file mode 100644
index 0000000000..74d5be4edb
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/bindingTypeMismatchFunction.qml
@@ -0,0 +1,6 @@
+import QtQuick
+
+Item {
+ function returnsString() : string {}
+ property int number: returnsString()
+}
diff --git a/tests/auto/qml/qmllint/data/boundComponents.qml b/tests/auto/qml/qmllint/data/boundComponents.qml
new file mode 100644
index 0000000000..2ffa2f4124
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/boundComponents.qml
@@ -0,0 +1,23 @@
+pragma ComponentBehavior: Bound
+
+import QtQml
+
+QtObject {
+ id: root
+ property string foo: "bar"
+ property Component c1: Component {
+ QtObject {
+ id: c1
+ objectName: root.foo
+ property int i: 12
+ property Component c2: Component {
+ QtObject {
+ objectName: root.foo + c1.i
+ }
+ }
+ property QtObject o: c2.createObject()
+ }
+ }
+
+ property QtObject o: c1.createObject()
+}
diff --git a/tests/auto/qml/qmllint/data/bytearray.qml b/tests/auto/qml/qmllint/data/bytearray.qml
new file mode 100644
index 0000000000..31c41028db
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/bytearray.qml
@@ -0,0 +1,5 @@
+import TestTypes
+
+HasByteArray {
+ property int l: byteArray.byteLength
+}
diff --git a/tests/auto/qml/qmllint/data/cachedDependency.qml b/tests/auto/qml/qmllint/data/cachedDependency.qml
new file mode 100644
index 0000000000..5a15a66997
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/cachedDependency.qml
@@ -0,0 +1,23 @@
+import QtQuick.Controls.impl // Caches QtQuick as depedency, without QML names
+import QtQuick
+
+Item {
+ QtObject { id: object }
+ Item { id: item }
+ Rectangle { id: rectangle }
+
+ // Various ways to cast between types contained in QtQuick and QtQml
+ // The QML names of both have to be available for this to work
+
+ property QtObject objectAsObject: object as QtObject
+ property QtObject objectAsItem: object as Item
+ property QtObject objectAsRectangle: object as Rectangle
+
+ property QtObject itemAsObject: item as QtObject
+ property QtObject itemAsItem: item as Item
+ property QtObject itemAsRectangle: item as Rectangle
+
+ property QtObject rectangleAsObject: rectangle as QtObject
+ property QtObject rectangleAsItem: rectangle as Item
+ property QtObject rectangleAsRectangle: rectangle as Rectangle
+}
diff --git a/tests/auto/qml/qmllint/data/callBase.qml b/tests/auto/qml/qmllint/data/callBase.qml
new file mode 100644
index 0000000000..435a5f04dd
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/callBase.qml
@@ -0,0 +1,7 @@
+import QtQml
+
+QtObject {
+ function bar(foo : Foo) {
+ var state = foo.whatSUp()
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/callJSValueProp.qml b/tests/auto/qml/qmllint/data/callJSValueProp.qml
new file mode 100644
index 0000000000..57a828fec4
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/callJSValueProp.qml
@@ -0,0 +1,6 @@
+import QtQuick
+
+Rectangle {
+ // Note: gradient is not actually callable
+ Component.onCompleted: gradient(42);
+}
diff --git a/tests/auto/qml/qmllint/data/callLater.qml b/tests/auto/qml/qmllint/data/callLater.qml
new file mode 100644
index 0000000000..6f654ebdb1
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/callLater.qml
@@ -0,0 +1,5 @@
+import QtQuick
+
+Item {
+ Component.onCompleted: Qt.callLater(console.log, "hello, World")
+}
diff --git a/tests/auto/qml/qmllint/data/callVarProp.qml b/tests/auto/qml/qmllint/data/callVarProp.qml
new file mode 100644
index 0000000000..ad69e2a679
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/callVarProp.qml
@@ -0,0 +1,7 @@
+import QtQml
+
+QtObject {
+ property var foo: () => {}
+
+ Component.onCompleted: foo()
+}
diff --git a/tests/auto/qml/qmllint/data/coercetovoid.qml b/tests/auto/qml/qmllint/data/coercetovoid.qml
new file mode 100644
index 0000000000..f1b593ea3a
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/coercetovoid.qml
@@ -0,0 +1,8 @@
+pragma Strict
+import QtQml
+
+QtObject {
+ function touchThisAndReturnSomething(x: int) {
+ return x + 1;
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/compositesingleton.qml b/tests/auto/qml/qmllint/data/compositesingleton.qml
new file mode 100644
index 0000000000..42db13154e
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/compositesingleton.qml
@@ -0,0 +1,8 @@
+import QtQml
+import QmlBench
+
+QtObject {
+ property real x: Globals.realProp
+ property real y: Globals.intProp
+ property bool smooth: Globals.boolProp
+}
diff --git a/tests/auto/qml/qmllint/data/connectionNoParent.qml b/tests/auto/qml/qmllint/data/connectionNoParent.qml
new file mode 100644
index 0000000000..27f7e22cf3
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/connectionNoParent.qml
@@ -0,0 +1,5 @@
+import QtQuick
+
+Connections {
+ function onClicked() {}
+}
diff --git a/tests/auto/qml/qmllint/data/constructorProperty.qml b/tests/auto/qml/qmllint/data/constructorProperty.qml
new file mode 100644
index 0000000000..d7ef884283
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/constructorProperty.qml
@@ -0,0 +1,5 @@
+import QtQml
+
+QtObject {
+ property double f: Number.EPSILON
+}
diff --git a/tests/auto/qml/qmllint/data/controlsWithQuick_pluginTest.qml b/tests/auto/qml/qmllint/data/controlsWithQuick_pluginTest.qml
new file mode 100644
index 0000000000..2897174a54
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/controlsWithQuick_pluginTest.qml
@@ -0,0 +1,4 @@
+import QtQuick.Controls as QQC
+import QtQuick.Window
+
+QQC.Control {}
diff --git a/tests/auto/qml/qmllint/data/controlsWithoutQuick_pluginTest.qml b/tests/auto/qml/qmllint/data/controlsWithoutQuick_pluginTest.qml
new file mode 100644
index 0000000000..c84e5527ba
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/controlsWithoutQuick_pluginTest.qml
@@ -0,0 +1,3 @@
+import QtQuick.Controls
+
+Control {}
diff --git a/tests/auto/qml/qmllint/data/customParser.qml b/tests/auto/qml/qmllint/data/customParser.qml
new file mode 100644
index 0000000000..324ca20953
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/customParser.qml
@@ -0,0 +1,17 @@
+import QtQuick 2.0
+
+Rectangle {
+ id: root
+ width: 100; height: 100
+
+ states: [
+ State {
+ name: "red_color"
+ PropertyChanges { root.color: "red" }
+ },
+ State {
+ name: "blue_color"
+ PropertyChanges { root.color: "blue" }
+ }
+ ]
+}
diff --git a/tests/auto/qml/qmllint/data/customParser.recursive.qml b/tests/auto/qml/qmllint/data/customParser.recursive.qml
new file mode 100644
index 0000000000..aa15460021
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/customParser.recursive.qml
@@ -0,0 +1,16 @@
+import QtQuick 2.0
+
+ListModel {
+ id: listModel
+ ListElement { dataType: "rect"; color: "green"; font.color: "red"; ListElement {} Behavior on FooBar {} }
+ ListElement { dataType: "image"; source: "../shared/images/qt-logo.png" }
+ ListElement { dataType: "rect"; color: "green" }
+ ListElement { dataType: "image"; source: "../shared/images/qt-logo.png" }
+ ListElement { dataType: "rect"; color: "blue" }
+ ListElement { dataType: "rect"; color: "blue" }
+ ListElement { dataType: "rect"; color: "blue" }
+ ListElement { dataType: "rect"; color: "blue" }
+ ListElement { dataType: "rect"; color: "blue" }
+ ListElement { dataType: "rect"; color: "blue" }
+}
+
diff --git a/tests/auto/qml/qmllint/data/customParserUnqualifiedAccess.qml b/tests/auto/qml/qmllint/data/customParserUnqualifiedAccess.qml
new file mode 100644
index 0000000000..dc8f814c91
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/customParserUnqualifiedAccess.qml
@@ -0,0 +1,5 @@
+import Things
+
+CustomParserThing {
+ foo: does.not.exist
+}
diff --git a/tests/auto/qml/qmllint/data/cycleHead.qml b/tests/auto/qml/qmllint/data/cycleHead.qml
new file mode 100644
index 0000000000..080eab381f
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/cycleHead.qml
@@ -0,0 +1,7 @@
+import Cycle
+import QtQuick
+
+Item {
+ property MenuItem item: a
+ MenuItem { id: a }
+}
diff --git a/tests/auto/qml/qmllint/data/optionalImport.qml b/tests/auto/qml/qmllint/data/defaultImport.qml
index 2be7cd444a..2be7cd444a 100644
--- a/tests/auto/qml/qmllint/data/optionalImport.qml
+++ b/tests/auto/qml/qmllint/data/defaultImport.qml
diff --git a/tests/auto/qml/qmllint/data/defaultProperty.qml b/tests/auto/qml/qmllint/data/defaultProperty.qml
new file mode 100644
index 0000000000..be9368c7aa
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/defaultProperty.qml
@@ -0,0 +1,5 @@
+import QtQml 2.0
+
+TypeWithDefaultProperty {
+ QtObject {}
+}
diff --git a/tests/auto/qml/qmllint/data/defaultPropertyComponent.2.qml b/tests/auto/qml/qmllint/data/defaultPropertyComponent.2.qml
new file mode 100644
index 0000000000..1c3736e703
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/defaultPropertyComponent.2.qml
@@ -0,0 +1,7 @@
+import QtQuick 2.0
+
+Item {
+ Component {
+ Rectangle {}
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/defaultPropertyComponent.qml b/tests/auto/qml/qmllint/data/defaultPropertyComponent.qml
new file mode 100644
index 0000000000..b57225ff4f
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/defaultPropertyComponent.qml
@@ -0,0 +1,5 @@
+import QtQuick
+
+Repeater {
+ QtObject {}
+}
diff --git a/tests/auto/qml/qmllint/data/defaultPropertyList.qml b/tests/auto/qml/qmllint/data/defaultPropertyList.qml
new file mode 100644
index 0000000000..ebf6357c34
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/defaultPropertyList.qml
@@ -0,0 +1,7 @@
+import QtQml 2.0
+import QtQuick 2.15
+
+TypeWithDefaultListProperty {
+ QtObject {}
+ Rectangle {}
+}
diff --git a/tests/auto/qml/qmllint/data/defaultPropertyListModel.qml b/tests/auto/qml/qmllint/data/defaultPropertyListModel.qml
new file mode 100644
index 0000000000..f0bac0fdf7
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/defaultPropertyListModel.qml
@@ -0,0 +1,6 @@
+import QtQuick 2.15
+import QtQml.Models 2.15
+
+Item {
+ ListModel {}
+}
diff --git a/tests/auto/qml/qmllint/data/defaultPropertyVar.qml b/tests/auto/qml/qmllint/data/defaultPropertyVar.qml
new file mode 100644
index 0000000000..1202d5384d
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/defaultPropertyVar.qml
@@ -0,0 +1,5 @@
+import QtQml 2.0
+
+TypeWithDefaultVarProperty {
+ QtObject {}
+}
diff --git a/tests/auto/qml/qmllint/data/defaultPropertyWithDoubleAssignment.qml b/tests/auto/qml/qmllint/data/defaultPropertyWithDoubleAssignment.qml
new file mode 100644
index 0000000000..8c2d09fb97
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/defaultPropertyWithDoubleAssignment.qml
@@ -0,0 +1,6 @@
+import QtQml 2.0
+
+TypeWithDefaultProperty {
+ QtObject {}
+ QtObject {}
+}
diff --git a/tests/auto/qml/qmllint/data/defaultPropertyWithWrongType.qml b/tests/auto/qml/qmllint/data/defaultPropertyWithWrongType.qml
new file mode 100644
index 0000000000..d04fecda49
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/defaultPropertyWithWrongType.qml
@@ -0,0 +1,6 @@
+import QtQml 2.0
+
+TypeWithDefaultStringProperty {
+ // default property has type `string`, so cannot assing an object to it
+ QtObject {}
+}
diff --git a/tests/auto/qml/qmllint/data/defaultPropertyWithinTheSameType.qml b/tests/auto/qml/qmllint/data/defaultPropertyWithinTheSameType.qml
new file mode 100644
index 0000000000..6284cca15c
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/defaultPropertyWithinTheSameType.qml
@@ -0,0 +1,6 @@
+import QtQml 2.0
+
+QtObject {
+ default property QtObject child
+ QtObject {}
+}
diff --git a/tests/auto/qml/qmllint/data/defaultPropertyWithoutKeyword.qml b/tests/auto/qml/qmllint/data/defaultPropertyWithoutKeyword.qml
new file mode 100644
index 0000000000..38f7a55984
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/defaultPropertyWithoutKeyword.qml
@@ -0,0 +1,6 @@
+import QtQml 2.0
+
+QtObject {
+ property QtObject child
+ QtObject {}
+}
diff --git a/tests/auto/qml/qmllint/data/delegateContextProperties.qml b/tests/auto/qml/qmllint/data/delegateContextProperties.qml
new file mode 100644
index 0000000000..4e133a38de
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/delegateContextProperties.qml
@@ -0,0 +1,9 @@
+import QtQuick
+
+ListView {
+ model: ListModel {}
+ delegate: Text {
+ text: model.text
+ color: index % 2 ? "red" : "blue"
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/deprecatedFunction.qml b/tests/auto/qml/qmllint/data/deprecatedFunction.qml
new file mode 100644
index 0000000000..9face2edf7
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/deprecatedFunction.qml
@@ -0,0 +1,10 @@
+import QtQuick 2.0
+
+DeprecatedFunctions {
+ @Deprecated { reason: "No particular reason." }
+ function deprecated(foobar) {}
+
+ Component.onCompleted: {
+ deprecated();
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/deprecatedFunctionInherited.qml b/tests/auto/qml/qmllint/data/deprecatedFunctionInherited.qml
new file mode 100644
index 0000000000..0164530720
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/deprecatedFunctionInherited.qml
@@ -0,0 +1,7 @@
+import QtQuick 2.0
+
+DeprecatedFunctions {
+ Component.onCompleted: {
+ deprecatedInherited();
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/deprecatedFunctionOverride.qml b/tests/auto/qml/qmllint/data/deprecatedFunctionOverride.qml
new file mode 100644
index 0000000000..f5c88b763e
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/deprecatedFunctionOverride.qml
@@ -0,0 +1,8 @@
+import QtQuick 2.0
+
+DeprecatedFunctions {
+ function deprecatedOverride(x, y, z) {}
+ Component.onCompleted: {
+ deprecatedOverride();
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/deprecatedProperty.qml b/tests/auto/qml/qmllint/data/deprecatedProperty.qml
new file mode 100644
index 0000000000..539e7abb38
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/deprecatedProperty.qml
@@ -0,0 +1,10 @@
+import QtQml
+
+QtObject {
+ @Deprecated {}
+ property int deprecated: 10
+
+ Component.onCompleted: {
+ console.log(deprecated);
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/deprecatedPropertyBinding.qml b/tests/auto/qml/qmllint/data/deprecatedPropertyBinding.qml
new file mode 100644
index 0000000000..ba3fbe6024
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/deprecatedPropertyBinding.qml
@@ -0,0 +1,3 @@
+DeprProp {
+ deprecated: 200
+}
diff --git a/tests/auto/qml/qmllint/data/deprecatedPropertyBindingReason.qml b/tests/auto/qml/qmllint/data/deprecatedPropertyBindingReason.qml
new file mode 100644
index 0000000000..543afde5e3
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/deprecatedPropertyBindingReason.qml
@@ -0,0 +1,3 @@
+DeprProp {
+ deprecatedReason: 200
+}
diff --git a/tests/auto/qml/qmllint/data/deprecatedPropertyReason.qml b/tests/auto/qml/qmllint/data/deprecatedPropertyReason.qml
new file mode 100644
index 0000000000..0e1edad6d0
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/deprecatedPropertyReason.qml
@@ -0,0 +1,12 @@
+import QtQml
+
+QtObject {
+ @Deprecated {
+ reason: "Test"
+ }
+ property int deprecated: 10
+
+ Component.onCompleted: {
+ console.log(deprecated);
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/deprecatedType.qml b/tests/auto/qml/qmllint/data/deprecatedType.qml
new file mode 100644
index 0000000000..997e5d1ff2
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/deprecatedType.qml
@@ -0,0 +1,3 @@
+import QtQml
+
+TypeDeprecated {}
diff --git a/tests/auto/qml/qmllint/data/deprecatedTypeReason.qml b/tests/auto/qml/qmllint/data/deprecatedTypeReason.qml
new file mode 100644
index 0000000000..faa84a4127
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/deprecatedTypeReason.qml
@@ -0,0 +1,3 @@
+import QtQml
+
+TypeDeprecatedReason {}
diff --git a/tests/auto/qml/qmllint/data/didYouMeanBinding.qml b/tests/auto/qml/qmllint/data/didYouMeanBinding.qml
new file mode 100644
index 0000000000..b5bb9b44ea
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/didYouMeanBinding.qml
@@ -0,0 +1,5 @@
+import QtQuick
+
+Item {
+ witdh: 50
+}
diff --git a/tests/auto/qml/qmllint/data/didYouMeanComponent.qml b/tests/auto/qml/qmllint/data/didYouMeanComponent.qml
new file mode 100644
index 0000000000..42f21c4969
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/didYouMeanComponent.qml
@@ -0,0 +1,4 @@
+import QtQuick 2.0
+
+Itym {
+}
diff --git a/tests/auto/qml/qmllint/data/didYouMeanEnum.qml b/tests/auto/qml/qmllint/data/didYouMeanEnum.qml
new file mode 100644
index 0000000000..5e6bcb4c87
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/didYouMeanEnum.qml
@@ -0,0 +1,5 @@
+import QtQuick
+
+Image {
+ property bool isReady: status === Image.Readx
+}
diff --git a/tests/auto/qml/qmllint/data/didYouMeanProperty.qml b/tests/auto/qml/qmllint/data/didYouMeanProperty.qml
new file mode 100644
index 0000000000..c27f10b978
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/didYouMeanProperty.qml
@@ -0,0 +1,6 @@
+import QtQuick
+
+Item {
+ Rectangle { id: rect }
+ width: rect.hoight * 2
+}
diff --git a/tests/auto/qml/qmllint/data/didYouMeanPropertyCall.qml b/tests/auto/qml/qmllint/data/didYouMeanPropertyCall.qml
new file mode 100644
index 0000000000..2bd6f796f2
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/didYouMeanPropertyCall.qml
@@ -0,0 +1,7 @@
+import QtQuick
+
+Item {
+ Component.onCompleted: {
+ console.lgg("Hello World!");
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/didYouMeanUnqualified.qml b/tests/auto/qml/qmllint/data/didYouMeanUnqualified.qml
new file mode 100644
index 0000000000..ca92f525f3
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/didYouMeanUnqualified.qml
@@ -0,0 +1,5 @@
+import QtQuick
+
+Item {
+ width: hoight * 2
+}
diff --git a/tests/auto/qml/qmllint/data/didYouMeanUnqualifiedCall.qml b/tests/auto/qml/qmllint/data/didYouMeanUnqualifiedCall.qml
new file mode 100644
index 0000000000..6baff8f74a
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/didYouMeanUnqualifiedCall.qml
@@ -0,0 +1,6 @@
+import QtQuick
+
+Item {
+ function func() {}
+ width: funk() * 2
+}
diff --git a/tests/auto/qml/qmllint/data/dontCheckJSTypes.qml b/tests/auto/qml/qmllint/data/dontCheckJSTypes.qml
new file mode 100644
index 0000000000..dc582936b9
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/dontCheckJSTypes.qml
@@ -0,0 +1,11 @@
+import QtQuick
+
+import "SharedFunctions.js" as Functions
+
+Item {
+ Rectangle {
+ color: Functions.setColorAlpha(Qt.color("orange"), 0.15)
+ x: Functions.setColorAlpha.asdfg
+ y: Functions.asdfg
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/duplicateId.qml b/tests/auto/qml/qmllint/data/duplicateId.qml
new file mode 100644
index 0000000000..0cd822b5ef
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/duplicateId.qml
@@ -0,0 +1,8 @@
+import QtQuick
+
+Item {
+ id: root
+ Item {
+ id: root
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/duplicatedPropertyName.qml b/tests/auto/qml/qmllint/data/duplicatedPropertyName.qml
new file mode 100644
index 0000000000..18a4435f5f
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/duplicatedPropertyName.qml
@@ -0,0 +1,9 @@
+import QtQuick
+
+Item {
+ property int cat: 12
+ property string cat: "mutantx"
+
+ signal clicked()
+ signal clicked(a: int)
+} \ No newline at end of file
diff --git a/tests/auto/qml/qmllint/data/elementpass_pluginTest.qml b/tests/auto/qml/qmllint/data/elementpass_pluginTest.qml
new file mode 100644
index 0000000000..b9250a2d11
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/elementpass_pluginTest.qml
@@ -0,0 +1,7 @@
+import QtQuick
+
+Item {
+ Rectangle {
+ radius: 5
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/enumInvalid.qml b/tests/auto/qml/qmllint/data/enumInvalid.qml
new file mode 100644
index 0000000000..a14955d3e2
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/enumInvalid.qml
@@ -0,0 +1,6 @@
+import QtQml
+
+QtObject {
+ property bool c: Qt.red > 4
+ property bool d: Qt.red < 2
+}
diff --git a/tests/auto/qml/qmllint/data/enumsOfScrollBar.qml b/tests/auto/qml/qmllint/data/enumsOfScrollBar.qml
new file mode 100644
index 0000000000..d0cd5591b9
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/enumsOfScrollBar.qml
@@ -0,0 +1,7 @@
+import QtQuick
+import QtQuick.Controls
+
+Item {
+ Component.onCompleted: console.log(ScrollBar.AlwaysOn)
+}
+
diff --git a/tests/auto/qml/qmllint/data/findMemberPrint.qml b/tests/auto/qml/qmllint/data/findMemberPrint.qml
new file mode 100644
index 0000000000..69146eb06b
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/findMemberPrint.qml
@@ -0,0 +1,13 @@
+import QtQml
+
+import TestTypes
+
+QtObject {
+ property var foooooooo: Foo {
+ id: foo
+ }
+
+ function f(): void {
+ foo.print()
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/generalizedGroupHint.qml b/tests/auto/qml/qmllint/data/generalizedGroupHint.qml
new file mode 100644
index 0000000000..5fec03f7f3
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/generalizedGroupHint.qml
@@ -0,0 +1,23 @@
+import QtQuick
+
+Window {
+ width: 640
+ height: 480
+ visible: true
+ title: 'Resolve my color type'
+
+ Item {
+ id: foo
+
+ states: [
+ State {
+ PropertyChanges {
+ target: foo
+ myColor: Qt.rgba(0.5, 0.5, 0.5, 0.16)
+ }
+ }
+ ]
+
+ property color myColor: 'black'
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/goodAttachedProperty.qml b/tests/auto/qml/qmllint/data/goodAttachedProperty.qml
new file mode 100644
index 0000000000..8472aabb10
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/goodAttachedProperty.qml
@@ -0,0 +1,13 @@
+import AttachedProperties 1.0
+QtObject {
+ TestType.object: Component {}
+ TestType.count: 42 + 2
+ Component.onCompleted: {
+ TestType.count = 42;
+ // TestType here is an attached type, not this object's instance of it.
+ // This attached type has an unchanged property object of type QtObject,
+ // so accessing Component's specific property 'progress' is only
+ // possible with a cast to Component type
+ console.log((TestType.object as Component).progress);
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/goodAttachedPropertyAccess.qml b/tests/auto/qml/qmllint/data/goodAttachedPropertyAccess.qml
new file mode 100644
index 0000000000..b7f64d9acb
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/goodAttachedPropertyAccess.qml
@@ -0,0 +1,14 @@
+import AttachedProperties 1.0
+QtObject {
+ id: root
+ TestType.object: QtObject {
+ property int progress: 42
+ }
+
+ Component.onCompleted: {
+ // NB: this currently fails as TestType.object is recognized as QtObject
+ // *exactly*, ignoring the QML code above and thus there's no 'progress'
+ // property on TestType.object
+ console.log(TestType.object.progress);
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/goodAttachedPropertyNested.qml b/tests/auto/qml/qmllint/data/goodAttachedPropertyNested.qml
new file mode 100644
index 0000000000..98d7726063
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/goodAttachedPropertyNested.qml
@@ -0,0 +1,20 @@
+import AttachedProperties 1.0
+QtObject {
+ id: root
+ TestType.object: Component {}
+ TestType.count: 42 + 2
+
+ Component.onCompleted: {
+ TestType.count = 42;
+ console.log(TestType.object.progress);
+ }
+
+ QtObject {
+ TestType.count: 43
+ Component.onCompleted: {
+ console.log(TestType.count);
+ console.log(root.TestType.count);
+ console.log(root.TestType.object.progress);
+ }
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/goodBindingsOnGroupAndAttached.qml b/tests/auto/qml/qmllint/data/goodBindingsOnGroupAndAttached.qml
new file mode 100644
index 0000000000..7a89b82f6e
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/goodBindingsOnGroupAndAttached.qml
@@ -0,0 +1,11 @@
+import QtQuick
+Rectangle {
+ Text {
+ font.pixelSize: 42
+ }
+
+ Keys.enabled: false
+ Keys.onPressed: function(event) {
+ console.log(event);
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/goodCppPropertyChangeHandlers.qml b/tests/auto/qml/qmllint/data/goodCppPropertyChangeHandlers.qml
new file mode 100644
index 0000000000..1ec2284c7d
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/goodCppPropertyChangeHandlers.qml
@@ -0,0 +1,26 @@
+import PropertyChangeHandlers 1.0
+import QtQuick
+Item {
+ TypeWithProperties {
+ onAChanged: { console.log("OK"); }
+ onBChanged: { console.log("OK"); }
+ onCChanged: { console.log("OK"); }
+ onDChanged: { console.log("OK"); }
+ onEChanged: { console.log("OK"); }
+ }
+
+ TypeWithProperties {
+ onCWeirdSignal: { console.log("OK"); }
+ onDSignal: { console.log("OK"); }
+ }
+
+ TypeWithProperties {
+ onCWeirdSignal: function(value) { console.log("OK?", value); }
+ onDSignal: function(value, str) { console.log("OK?", value, str); }
+ }
+
+ TypeWithProperties {
+ onCChanged: function(value) { console.log("OK?", value); }
+ onDChanged: function(value, str) { console.log("OK?", value, str); }
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/goodGeneralizedGroup.qml b/tests/auto/qml/qmllint/data/goodGeneralizedGroup.qml
new file mode 100644
index 0000000000..97c821adb7
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/goodGeneralizedGroup.qml
@@ -0,0 +1,9 @@
+import QtQuick
+import Things
+
+Item {
+ id: self
+ WithImmediate {
+ self.x: 15 - 1
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/goodModulePrefix.qml b/tests/auto/qml/qmllint/data/goodModulePrefix.qml
new file mode 100644
index 0000000000..251bcd82c0
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/goodModulePrefix.qml
@@ -0,0 +1,9 @@
+import QtQml
+import TestTypes as T
+
+QtObject {
+ id: self
+ property date foo: self.T.BirthdayParty.rsvp
+ property date bar: T.BirthdayParty.rsvp
+ property string baz: T.CppSingleton.objectName
+}
diff --git a/tests/auto/qml/qmllint/data/groupedAttachedLayout.qml b/tests/auto/qml/qmllint/data/groupedAttachedLayout.qml
new file mode 100644
index 0000000000..7cfe98d4f8
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/groupedAttachedLayout.qml
@@ -0,0 +1,20 @@
+import QtQuick
+import QtQuick.Layouts
+
+Window {
+ id: root
+
+ Rectangle {
+ id: redRect
+ }
+
+ Item {
+ states: [
+ State {
+ PropertyChanges {
+ redRect.Layout.fillWidth: true
+ }
+ }
+ ]
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/groupedPropertyAssignments.qml b/tests/auto/qml/qmllint/data/groupedPropertyAssignments.qml
new file mode 100644
index 0000000000..8874960d63
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/groupedPropertyAssignments.qml
@@ -0,0 +1,5 @@
+import QtQuick
+Text {
+ font.pixelSize: 24
+ font.underline: true
+}
diff --git a/tests/auto/qml/qmllint/data/groupedProperty_valueSource_interceptor.qml b/tests/auto/qml/qmllint/data/groupedProperty_valueSource_interceptor.qml
new file mode 100644
index 0000000000..4150df1aa3
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/groupedProperty_valueSource_interceptor.qml
@@ -0,0 +1,6 @@
+import QtQuick 2.0
+
+Text {
+ Behavior on font.bold {}
+ NumberAnimation on font.letterSpacing {}
+}
diff --git a/tests/auto/qml/qmllint/data/here.qml b/tests/auto/qml/qmllint/data/here.qml
new file mode 100644
index 0000000000..1ead2eedd1
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/here.qml
@@ -0,0 +1,3 @@
+import Things.Nested
+
+A {}
diff --git a/tests/auto/qml/qmllint/data/hidden/moduleWithQrc/main.qml b/tests/auto/qml/qmllint/data/hidden/moduleWithQrc/main.qml
new file mode 100644
index 0000000000..d018110b86
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/hidden/moduleWithQrc/main.qml
@@ -0,0 +1,11 @@
+import QtQuick
+import QtQuick.Controls
+
+Window {
+ width: 640; height: 480
+ visible: true
+
+ Button {
+ text: "a"
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/hidden/moduleWithQrc/qmldir b/tests/auto/qml/qmllint/data/hidden/moduleWithQrc/qmldir
new file mode 100644
index 0000000000..acb456ffd9
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/hidden/moduleWithQrc/qmldir
@@ -0,0 +1,3 @@
+module moduleWithQrc
+prefer :/qt/qml/moduleWithQrc/
+
diff --git a/tests/auto/qml/qmllint/data/hidden/moduleWithQrc_raw_qml_0.qrc b/tests/auto/qml/qmllint/data/hidden/moduleWithQrc_raw_qml_0.qrc
new file mode 100644
index 0000000000..43d3ec805c
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/hidden/moduleWithQrc_raw_qml_0.qrc
@@ -0,0 +1,6 @@
+<RCC>
+ <qresource prefix="/qt/qml/qmllint65/">
+ <file alias="main.qml">moduleWithQrc/main.qml</file>
+ </qresource>
+</RCC>
+
diff --git a/tests/auto/qml/qmllint/data/hidden/qmake_moduleWithQrc.qrc b/tests/auto/qml/qmllint/data/hidden/qmake_moduleWithQrc.qrc
new file mode 100644
index 0000000000..cb362e2d55
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/hidden/qmake_moduleWithQrc.qrc
@@ -0,0 +1,6 @@
+<RCC>
+ <qresource prefix="/qt/qml/qmllint65">
+ <file alias="qmldir">moduleWithQrc/qmldir</file>
+ </qresource>
+</RCC>
+
diff --git a/tests/auto/qml/qmllint/data/ignoreWarnings.qml b/tests/auto/qml/qmllint/data/ignoreWarnings.qml
new file mode 100644
index 0000000000..90bb9a5436
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/ignoreWarnings.qml
@@ -0,0 +1,24 @@
+import QtQuick 2.0
+import QtTest 2.0 // qmllint disable unused-imports
+import QtTest 2.0 // qmllint disable
+
+Item {
+ @Deprecated {}
+ property string deprecated
+
+ property string a: root.a // qmllint disable unqualified
+ property string b: root.a // qmllint disable
+
+ // qmllint disable unqualified
+ property string c: root.a
+ property string d: root.a
+ // qmllint enable unqualified
+
+ //qmllint disable
+ property string e: root.a
+ Component.onCompleted: {
+ console.log(deprecated);
+ }
+ // qmllint enable
+
+}
diff --git a/tests/auto/qml/qmllint/data/implicitImportResource.qrc b/tests/auto/qml/qmllint/data/implicitImportResource.qrc
new file mode 100644
index 0000000000..026c8c4d4f
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/implicitImportResource.qrc
@@ -0,0 +1,6 @@
+<RCC>
+ <qresource prefix="/">
+ <file>additionalImplicitImport.qml</file>
+ <file alias="qmldir">Things/qmldir</file>
+ </qresource>
+</RCC>
diff --git a/tests/auto/qml/qmllint/data/importNonexistentFile.qml b/tests/auto/qml/qmllint/data/importNonexistentFile.qml
new file mode 100644
index 0000000000..847023936a
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/importNonexistentFile.qml
@@ -0,0 +1,3 @@
+import "¯\(ツ)/¯:/invalid/url"
+
+QtObject {}
diff --git a/tests/auto/qml/qmllint/data/importNullDevice.qml b/tests/auto/qml/qmllint/data/importNullDevice.qml
new file mode 100644
index 0000000000..5ff3090d75
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/importNullDevice.qml
@@ -0,0 +1,3 @@
+import "/dev/null"
+
+QtObject {}
diff --git a/tests/auto/qml/qmllint/data/importQMLModule.qml b/tests/auto/qml/qmllint/data/importQMLModule.qml
new file mode 100644
index 0000000000..842183ed5b
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/importQMLModule.qml
@@ -0,0 +1,2 @@
+import QML
+QtObject {}
diff --git a/tests/auto/qml/qmllint/data/importing_js.qml b/tests/auto/qml/qmllint/data/importing_js.qml
index b2d7a34fe6..3f226f1566 100644
--- a/tests/auto/qml/qmllint/data/importing_js.qml
+++ b/tests/auto/qml/qmllint/data/importing_js.qml
@@ -3,4 +3,6 @@ import QtQuick
Item {
id: root
+
+ property var foo: JSTest.foo("Test")
}
diff --git a/tests/auto/qml/qmllint/data/inaccessibleId.qml b/tests/auto/qml/qmllint/data/inaccessibleId.qml
new file mode 100644
index 0000000000..a3489f4741
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/inaccessibleId.qml
@@ -0,0 +1,12 @@
+import QtQml
+
+QtObject {
+ id: a
+
+ property Component c: Component {
+ QtObject {
+ property int a: 5
+ objectName: a.objectName
+ }
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/inaccessibleId2.qml b/tests/auto/qml/qmllint/data/inaccessibleId2.qml
new file mode 100644
index 0000000000..b8f381b0b7
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/inaccessibleId2.qml
@@ -0,0 +1,10 @@
+import QtQml
+
+QtObject {
+ id: a
+
+ component Handle: QtObject {
+ property int a: 5
+ objectName: a.objectName
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/incompleteQmltypes2.qml b/tests/auto/qml/qmllint/data/incompleteQmltypes2.qml
new file mode 100644
index 0000000000..1cbe89dadb
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/incompleteQmltypes2.qml
@@ -0,0 +1,6 @@
+import Things 1.0
+
+SomethingEntirelyStrange {
+ id: self
+ property var a: self.palette2.weDontKnowIt
+}
diff --git a/tests/auto/qml/qmllint/data/incompleteQmltypes3.qml b/tests/auto/qml/qmllint/data/incompleteQmltypes3.qml
new file mode 100644
index 0000000000..142134d49e
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/incompleteQmltypes3.qml
@@ -0,0 +1,6 @@
+import Things 1.0
+
+SomethingEntirelyStrange {
+ id: self
+ property var a: palette
+}
diff --git a/tests/auto/qml/qmllint/data/initReadonly.qml b/tests/auto/qml/qmllint/data/initReadonly.qml
new file mode 100644
index 0000000000..a9a2a0016b
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/initReadonly.qml
@@ -0,0 +1,6 @@
+import QtQml
+
+QtObject {
+ readonly property int i: 14
+ readonly property int j: i + 20
+}
diff --git a/tests/auto/qml/qmllint/data/inlineComponent.qml b/tests/auto/qml/qmllint/data/inlineComponent.qml
new file mode 100644
index 0000000000..364d5319de
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/inlineComponent.qml
@@ -0,0 +1,15 @@
+import QtQuick 2.0
+
+Item {
+ component MyIC: IC {}
+ component IC : QtObject {}
+ QtObject {
+ component IC2: QtObject {}
+
+ property IC ic: IC {}
+ property IC2 ic2: IC2 {}
+ }
+
+ property IC ic : IC {}
+ property IC2 ic2: IC2 {}
+}
diff --git a/tests/auto/qml/qmllint/data/inlineComponentNoComponent.qml b/tests/auto/qml/qmllint/data/inlineComponentNoComponent.qml
new file mode 100644
index 0000000000..f72b0a27c5
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/inlineComponentNoComponent.qml
@@ -0,0 +1,5 @@
+import QtQuick 2.0
+Item {
+ component Base : eItm { }
+}
+
diff --git a/tests/auto/qml/qmllint/data/inlineComponentWithComponents.qml b/tests/auto/qml/qmllint/data/inlineComponentWithComponents.qml
new file mode 100644
index 0000000000..431d3ee076
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/inlineComponentWithComponents.qml
@@ -0,0 +1,11 @@
+import QtQuick 2.0
+
+Item {
+ component IC : Text {
+ text: "Hello world!"
+ MouseArea {} // Previously this would overwrite the IC
+ }
+
+ property IC ic: IC {}
+ property string icText: ic.text // Check that we can access a property not contained in the component that would overwrite
+}
diff --git a/tests/auto/qml/qmllint/data/inlineComponentsChained.qml b/tests/auto/qml/qmllint/data/inlineComponentsChained.qml
new file mode 100644
index 0000000000..cc063b1bc2
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/inlineComponentsChained.qml
@@ -0,0 +1,10 @@
+import QtQuick
+
+Item {
+ component A : B { required foo }
+ component B : C { property QtObject foo }
+ component C : Item {
+ }
+ A { foo: QtObject {} }
+}
+
diff --git a/tests/auto/qml/qmllint/data/interceptor.qml b/tests/auto/qml/qmllint/data/interceptor.qml
new file mode 100644
index 0000000000..89b4c0e54a
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/interceptor.qml
@@ -0,0 +1,10 @@
+import QtQuick 2.0
+
+Image {
+ transform: Rotation {
+ angle: 6
+ Behavior on angle {
+ SpringAnimation { spring: 2; damping: 0.2; modulus: 360 }
+ }
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/interceptor_valueSource.qml b/tests/auto/qml/qmllint/data/interceptor_valueSource.qml
new file mode 100644
index 0000000000..876ef37734
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/interceptor_valueSource.qml
@@ -0,0 +1,23 @@
+import QtQuick 2.0
+
+Item {
+ Image {
+ transform: Rotation {
+ Behavior on angle {
+ SpringAnimation { spring: 2; damping: 0.2; modulus: 360 }
+ }
+ NumberAnimation on angle {
+ }
+ }
+ }
+
+ Image {
+ transform: Rotation {
+ NumberAnimation on angle {
+ }
+ Behavior on angle {
+ SpringAnimation { spring: 2; damping: 0.2; modulus: 360 }
+ }
+ }
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/invalidAliasTarget.qml b/tests/auto/qml/qmllint/data/invalidAliasTarget.qml
new file mode 100644
index 0000000000..e6ad63b518
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/invalidAliasTarget.qml
@@ -0,0 +1,11 @@
+import QtQuick
+
+Item {
+ Item {
+
+ property alias innerinner
+ property alias name: function f() {}
+
+ property alias innerObj: 1+1
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/invalidId1.qml b/tests/auto/qml/qmllint/data/invalidId1.qml
new file mode 100644
index 0000000000..61c45530f1
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/invalidId1.qml
@@ -0,0 +1,5 @@
+import QtQml
+
+QtObject {
+ id: foo.bar
+}
diff --git a/tests/auto/qml/qmllint/data/invalidId2.qml b/tests/auto/qml/qmllint/data/invalidId2.qml
new file mode 100644
index 0000000000..dc4b05be24
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/invalidId2.qml
@@ -0,0 +1,7 @@
+import QtQuick 2.0
+
+Item {
+ id: {
+ console.log("hi");
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/invalidIdLookup.qml b/tests/auto/qml/qmllint/data/invalidIdLookup.qml
new file mode 100644
index 0000000000..b351e5cfea
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/invalidIdLookup.qml
@@ -0,0 +1,10 @@
+import Things
+import QtQml
+
+QtObject {
+ property MediaPlayerStateMachine m: MediaPlayerStateMachine {
+ id: stateMachine
+ }
+
+ objectName: stateMachine.objectName
+}
diff --git a/tests/auto/qml/qmllint/data/invalidImport.qml b/tests/auto/qml/qmllint/data/invalidImport.qml
new file mode 100644
index 0000000000..f4db5d519c
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/invalidImport.qml
@@ -0,0 +1,4 @@
+import QtQml
+import FooBar
+
+QtObject {}
diff --git a/tests/auto/qml/qmllint/data/invalidInterceptor.qml b/tests/auto/qml/qmllint/data/invalidInterceptor.qml
new file mode 100644
index 0000000000..e648e9f9bb
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/invalidInterceptor.qml
@@ -0,0 +1,8 @@
+import QtQuick 2.0
+
+Image {
+ transform: Rotation {
+ angle: 6
+ Item on angle {}
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/javascriptVariableArgs.qml b/tests/auto/qml/qmllint/data/javascriptVariableArgs.qml
new file mode 100644
index 0000000000..a9dc79dbba
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/javascriptVariableArgs.qml
@@ -0,0 +1,9 @@
+import QtQml
+
+QtObject {
+ function varArgs() {}
+ Component.onCompleted: {
+ console.log("It works!");
+ varArgs("This works", 2);
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/jsLibrary.qml b/tests/auto/qml/qmllint/data/jsLibrary.qml
new file mode 100644
index 0000000000..3878b24616
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/jsLibrary.qml
@@ -0,0 +1,8 @@
+import QtQml
+import JsLibrary as JLib
+import "JsLibrary/HelperLibrary.js" as HelperLib
+
+QtObject {
+ property string text1: JLib.HelperLibrary.foo()
+ property string text2: HelperLib.foo()
+}
diff --git a/tests/auto/qml/qmllint/data/jsVarDeclarations.js b/tests/auto/qml/qmllint/data/jsVarDeclarations.js
new file mode 100644
index 0000000000..6c01b9f9a5
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/jsVarDeclarations.js
@@ -0,0 +1,3 @@
+var varProp = 5;
+let letProp = [ 1, 2, 3, 4 ];
+const constProp = "unchangable";
diff --git a/tests/auto/qml/qmllint/data/jsVarDeclarations.qml b/tests/auto/qml/qmllint/data/jsVarDeclarations.qml
new file mode 100644
index 0000000000..6297bf002c
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/jsVarDeclarations.qml
@@ -0,0 +1,9 @@
+import QtQuick
+
+import "jsVarDeclarations.js" as JSVars
+
+Item {
+ property int varProp: JSVars.varProp
+ property var letProp: JSVars.letProp
+ property string constProp: JSVars.constProp
+}
diff --git a/tests/auto/qml/qmllint/data/jsVarDeclarationsWriteConst.qml b/tests/auto/qml/qmllint/data/jsVarDeclarationsWriteConst.qml
new file mode 100644
index 0000000000..207bb55ff7
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/jsVarDeclarationsWriteConst.qml
@@ -0,0 +1,7 @@
+import QtQuick
+
+import "jsVarDeclarations.js" as JSVars
+
+Item {
+ Component.onCompleted: { JSVars.constProp = "new value"; }
+}
diff --git a/tests/auto/qml/qmllint/data/listIndices.qml b/tests/auto/qml/qmllint/data/listIndices.qml
new file mode 100644
index 0000000000..b5fda4ef0d
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/listIndices.qml
@@ -0,0 +1,14 @@
+pragma Strict
+import QtQml
+
+QtObject {
+ id: self
+ property list<QtObject> items
+ property int numItems: items.length
+
+ Component.onCompleted: {
+ items.length = 3
+ for (var i = 0; i < 3; ++i)
+ items[i] = self
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/listPropertyMethods.qml b/tests/auto/qml/qmllint/data/listPropertyMethods.qml
new file mode 100644
index 0000000000..1e203d4de0
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/listPropertyMethods.qml
@@ -0,0 +1,87 @@
+import QtQml
+
+QtObject {
+ id: self
+
+ required property real i
+ required property real j
+ required property real k
+
+ property QtObject r1: QtObject {}
+ property QtObject r2: QtObject {}
+ property QtObject r3: QtObject {}
+
+ property list<QtObject> listProperty: [r1, r2, r3]
+ property list<QtObject> listPropertySlice: listProperty.slice(i, j)
+ property int listPropertyIndexOf: listProperty.indexOf(r2, i)
+ property int listPropertyLastIndexOf: listProperty.lastIndexOf(r3, i)
+ property string listPropertyToString: listProperty.toString()
+ property string listPropertyToLocaleString: listProperty.toLocaleString()
+ property list<QtObject> listPropertyConcat: listProperty.concat(listProperty)
+ property QtObject listPropertyFind: listProperty.find(element => element.objectName === "")
+ property int listPropertyFindIndex: listProperty.findIndex(element => element === r2)
+ property bool listPropertyIncludes: listProperty.includes(r3)
+ property string listPropertyJoin: listProperty.join()
+
+ property bool entriesMatch: {
+ var iterator = listProperty.entries();
+ for (var [index, element] of listProperty.entries()) {
+ var v = iterator.next().value;
+ if (index !== v[0] || element !== v[1]) {
+ console.log(index, v[0], element, v[1]);
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ property bool keysMatch: {
+ var iterator = listProperty.keys();
+ for (var index of listProperty.keys()) {
+ var v = iterator.next().value;
+ if (index !== v) {
+ console.log(index, v);
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ property bool valuesMatch: {
+ var iterator = listProperty.values();
+ for (var obj of listProperty.values()) {
+ var v = iterator.next().value;
+ if (obj !== v) {
+ console.log(obj, v);
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ property bool listPropertyEvery: listProperty.every((element) => element != null)
+ property bool listPropertySome: listProperty.some((element) => element.objectName === "")
+
+ property list<int> listPropertyMap: listProperty.map(((element) => element.objectName.length))
+ property list<QtObject> listPropertyFilter: listProperty.filter((element) => element.objectName.length != 1)
+ property string listPropertyReduceRight: listProperty.reduceRight((element, v) => v + '-' + element.objectName + 'v', "")
+ property string listPropertyReduce: listProperty.reduce((element, v) => v + '-' + element.objectName + 'v', "")
+ property list<string> listPropertyOwnPropertyNames: Object.getOwnPropertyNames(listProperty)
+
+ Component.onCompleted: {
+ listProperty.reverse();
+ listProperty.pop();
+ listProperty.push(self);
+ listProperty.shift();
+ listProperty.unshift(self);
+ listProperty.forEach((element) => { console.log("-" + element.objectName + "-") });
+ listProperty.sort();
+ listProperty.sort((a, b) => (a.objectName.length - b.objectName.length))
+ listProperty.copyWithin(i, j, k);
+ listProperty.fill(self, i, Math.min(j, 1024));
+ listProperty.splice(i, j, self, self, self);
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/locale.qml b/tests/auto/qml/qmllint/data/locale.qml
new file mode 100644
index 0000000000..4ff9e6392c
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/locale.qml
@@ -0,0 +1,6 @@
+import QtQml
+import LocaleTest
+
+QtObject {
+ property int monday: AppManager.primaryLocale.firstDayOfWeek
+}
diff --git a/tests/auto/qml/qmllint/data/lowerCaseQualifiedImport.qml b/tests/auto/qml/qmllint/data/lowerCaseQualifiedImport.qml
new file mode 100644
index 0000000000..14c716c35d
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/lowerCaseQualifiedImport.qml
@@ -0,0 +1,9 @@
+import QtQuick as test
+
+test.Rectangle { // crashed qqmljsimportvisitor
+ id: mainRect
+ width: 100
+ height: 100
+ visible: true
+ rotation: 11
+}
diff --git a/tests/auto/qml/qmllint/data/lowerCaseQualifiedImport2.qml b/tests/auto/qml/qmllint/data/lowerCaseQualifiedImport2.qml
new file mode 100644
index 0000000000..4e03d8091d
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/lowerCaseQualifiedImport2.qml
@@ -0,0 +1,9 @@
+import QtQuick as test
+
+test.Item {
+ property test.color c
+
+ property var p: test.Grid {}
+
+ component IC: test.Rectangle {}
+}
diff --git a/tests/auto/qml/qmllint/data/matchByName.qml b/tests/auto/qml/qmllint/data/matchByName.qml
new file mode 100644
index 0000000000..92e00129d7
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/matchByName.qml
@@ -0,0 +1,8 @@
+import QtQuick
+import QtQuick.Controls.Fusion
+
+Button {
+ Image {
+ anchors.centerIn: parent
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/missingBuiltinsNoCrash.qml b/tests/auto/qml/qmllint/data/missingBuiltinsNoCrash.qml
new file mode 100644
index 0000000000..a2f7d422b3
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/missingBuiltinsNoCrash.qml
@@ -0,0 +1,3 @@
+import QtQuick // This can't be found if --bare is specified and no paths are provided
+
+Item {}
diff --git a/tests/auto/qml/qmllint/data/missingComponentBehaviorBound.qml b/tests/auto/qml/qmllint/data/missingComponentBehaviorBound.qml
new file mode 100644
index 0000000000..0a66ec140d
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/missingComponentBehaviorBound.qml
@@ -0,0 +1,10 @@
+import QtQuick
+Item {
+ id: barsty
+ property int fooInt: 42
+
+ Repeater {
+ model: 5
+ Text { text: "Foo=" + barsty.fooInt }
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/missingQmltypes.qml b/tests/auto/qml/qmllint/data/missingQmltypes.qml
new file mode 100644
index 0000000000..8605b3fddd
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/missingQmltypes.qml
@@ -0,0 +1,4 @@
+import QtQml
+import Fake5Compat.GraphicalEffects.private
+
+QtObject {}
diff --git a/tests/auto/qml/qmllint/data/missingRequiredAlias.qml b/tests/auto/qml/qmllint/data/missingRequiredAlias.qml
new file mode 100644
index 0000000000..adb0f65198
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/missingRequiredAlias.qml
@@ -0,0 +1,5 @@
+import QtQuick
+
+Item {
+ RequiredWithRootLevelAlias {}
+}
diff --git a/tests/auto/qml/qmllint/data/missingSingletonPragma.qml b/tests/auto/qml/qmllint/data/missingSingletonPragma.qml
new file mode 100644
index 0000000000..0c691baa76
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/missingSingletonPragma.qml
@@ -0,0 +1,6 @@
+import QtQml
+import Singletons
+
+QtObject {
+ Component.onCompleted: console.log(MissingPragma)
+}
diff --git a/tests/auto/qml/qmllint/data/missingSingletonQmldir.qml b/tests/auto/qml/qmllint/data/missingSingletonQmldir.qml
new file mode 100644
index 0000000000..6bbda963a8
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/missingSingletonQmldir.qml
@@ -0,0 +1,6 @@
+import QtQml
+import Singletons
+
+QtObject {
+ Component.onCompleted: console.log(MissingQmldirSingleton)
+}
diff --git a/tests/auto/qml/qmllint/data/multiDefaultPropertyOk.qml b/tests/auto/qml/qmllint/data/multiDefaultPropertyOk.qml
new file mode 100644
index 0000000000..64748a5f39
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/multiDefaultPropertyOk.qml
@@ -0,0 +1,8 @@
+import QML
+
+MultiDefaultProperty {
+ Simple {}
+ Simple {}
+ Simple {}
+ NotSoSimple {}
+}
diff --git a/tests/auto/qml/qmllint/data/multiDefaultPropertyWithWrongType.qml b/tests/auto/qml/qmllint/data/multiDefaultPropertyWithWrongType.qml
new file mode 100644
index 0000000000..f5e881d201
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/multiDefaultPropertyWithWrongType.qml
@@ -0,0 +1,8 @@
+import QtQml
+
+MultiDefaultProperty {
+ Simple {}
+ Simple {}
+ QtObject {}
+ Simple {}
+}
diff --git a/tests/auto/qml/qmllint/data/multiGrouped.qml b/tests/auto/qml/qmllint/data/multiGrouped.qml
new file mode 100644
index 0000000000..ab6bd5bd02
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/multiGrouped.qml
@@ -0,0 +1,6 @@
+import QtQuick
+
+Item {
+ anchors.verticalCenter: parent.verticalCenter
+ anchors { right: parent.left }
+}
diff --git a/tests/auto/qml/qmllint/data/multifix.fixed.qml b/tests/auto/qml/qmllint/data/multifix.fixed.qml
new file mode 100644
index 0000000000..d2188f2318
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/multifix.fixed.qml
@@ -0,0 +1,14 @@
+pragma ComponentBehavior: Bound
+import QtQml
+
+QtObject {
+ id: root
+
+ property Component cursorDelegate: QtObject {
+ objectName: root.objectName
+ }
+
+ property Component background: QtObject {
+ objectName: root.objectName
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/multifix.qml b/tests/auto/qml/qmllint/data/multifix.qml
new file mode 100644
index 0000000000..5f05ae7e62
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/multifix.qml
@@ -0,0 +1,13 @@
+import QtQml
+
+QtObject {
+ id: root
+
+ property Component cursorDelegate: QtObject {
+ objectName: root.objectName
+ }
+
+ property Component background: QtObject {
+ objectName: root.objectName
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/multilineString.fixed.qml b/tests/auto/qml/qmllint/data/multilineString.fixed.qml
new file mode 100644
index 0000000000..e1d15a926e
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/multilineString.fixed.qml
@@ -0,0 +1,21 @@
+import QtQml
+
+QtObject {
+ property string multipart: `Foo
+multiline\`
+string` + `another\`
+part
+of it`;
+
+ property string quote: `
+quote: " \\" \\\\"
+ticks: \` \` \\\` \\\`
+singleTicks: ' \' \\' \\\'
+expression: \${expr} \${expr} \\\${expr} \\\${expr}`
+
+ property string tick: `
+quote: " \" \\" \\\"
+ticks: \` \` \\\` \\\`
+singleTicks: ' \\' \\\\'
+expression: \${expr} \${expr} \\\${expr} \\\${expr}`
+}
diff --git a/tests/auto/qml/qmllint/data/multilineString.qml b/tests/auto/qml/qmllint/data/multilineString.qml
new file mode 100644
index 0000000000..758a71f868
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/multilineString.qml
@@ -0,0 +1,21 @@
+import QtQml
+
+QtObject {
+ property string multipart: "Foo
+multiline`
+string" + "another`
+part
+of it";
+
+ property string quote: "
+quote: \" \\\" \\\\\"
+ticks: ` \` \\\` \\\`
+singleTicks: ' \' \\' \\\'
+expression: \${expr} \${expr} \\\${expr} \\\${expr}"
+
+ property string tick: '
+quote: " \" \\" \\\"
+ticks: \` \` \\\` \\\`
+singleTicks: \' \\\' \\\\\'
+expression: \${expr} \${expr} \\\${expr} \\\${expr}'
+}
diff --git a/tests/auto/qml/qmllint/data/multilineStringEscaped.qml b/tests/auto/qml/qmllint/data/multilineStringEscaped.qml
new file mode 100644
index 0000000000..e155476b3d
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/multilineStringEscaped.qml
@@ -0,0 +1,8 @@
+import QtQml
+
+QtObject {
+ property string test: "Foo\nmultiline\nString"
+ property string template: `Foo
+multiline
+string`
+}
diff --git a/tests/auto/qml/qmllint/data/nestedInlineComponents.qml b/tests/auto/qml/qmllint/data/nestedInlineComponents.qml
new file mode 100644
index 0000000000..e2a32df092
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/nestedInlineComponents.qml
@@ -0,0 +1,7 @@
+import QtQml
+
+QtObject {
+ component IC: QtObject {
+ component IC2: QtObject {}
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/nonExistentListProperty.qml b/tests/auto/qml/qmllint/data/nonExistentListProperty.qml
new file mode 100644
index 0000000000..a4f549b664
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/nonExistentListProperty.qml
@@ -0,0 +1,5 @@
+import QtQuick 2.0
+
+Item {
+ objs: [ QtObject {} ]
+}
diff --git a/tests/auto/qml/qmllint/data/nonNullStored.qml b/tests/auto/qml/qmllint/data/nonNullStored.qml
new file mode 100644
index 0000000000..04388103a1
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/nonNullStored.qml
@@ -0,0 +1,6 @@
+import QtQml
+
+QtObject {
+ property Foozle foozle
+ function barzle() { return foozle.objectName }
+}
diff --git a/tests/auto/qml/qmllint/data/notQmlRootMethods.qml b/tests/auto/qml/qmllint/data/notQmlRootMethods.qml
new file mode 100644
index 0000000000..6d067d572d
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/notQmlRootMethods.qml
@@ -0,0 +1,8 @@
+import QtQml
+
+QtObject {
+ id: self
+
+ function a() { self.deleteLater(); }
+ function b() { self.destroyed(); }
+}
diff --git a/tests/auto/qml/qmllint/data/nothing_pluginTest.qml b/tests/auto/qml/qmllint/data/nothing_pluginTest.qml
new file mode 100644
index 0000000000..3052615aef
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/nothing_pluginTest.qml
@@ -0,0 +1,3 @@
+import QtQuick
+
+Item {}
diff --git a/tests/auto/qml/qmllint/data/nullBinding.qml b/tests/auto/qml/qmllint/data/nullBinding.qml
new file mode 100644
index 0000000000..f185ce9eda
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/nullBinding.qml
@@ -0,0 +1,5 @@
+import QtQuick
+
+Item {
+ x: null
+}
diff --git a/tests/auto/qml/qmllint/data/nullBindingFunction.qml b/tests/auto/qml/qmllint/data/nullBindingFunction.qml
new file mode 100644
index 0000000000..89142bd581
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/nullBindingFunction.qml
@@ -0,0 +1,5 @@
+import QtQuick
+
+Item {
+ x: { return null }
+}
diff --git a/tests/auto/qml/qmllint/data/numberToStringProperty.qml b/tests/auto/qml/qmllint/data/numberToStringProperty.qml
new file mode 100644
index 0000000000..6da8566ce3
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/numberToStringProperty.qml
@@ -0,0 +1,5 @@
+import QtQml
+
+QtObject {
+ property string i: 1
+}
diff --git a/tests/auto/qml/qmllint/data/objectArray.qml b/tests/auto/qml/qmllint/data/objectArray.qml
new file mode 100644
index 0000000000..051b20d1d1
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/objectArray.qml
@@ -0,0 +1,9 @@
+import QtQml 2.15
+
+QtObject {
+ property list<QtObject> objects
+ objects: [
+ QtObject { property string foo: "bar" },
+ QtObject { property string bar: "foo" }
+ ]
+}
diff --git a/tests/auto/qml/qmllint/data/objectBoundToVar.qml b/tests/auto/qml/qmllint/data/objectBoundToVar.qml
new file mode 100644
index 0000000000..405a06a1c4
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/objectBoundToVar.qml
@@ -0,0 +1,4 @@
+import QtQml
+QtObject {
+ property var child: QtObject { }
+}
diff --git a/tests/auto/qml/qmllint/data/onBindingInGroupedProperty.qml b/tests/auto/qml/qmllint/data/onBindingInGroupedProperty.qml
new file mode 100644
index 0000000000..186b8a557f
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/onBindingInGroupedProperty.qml
@@ -0,0 +1,10 @@
+import QtQuick
+
+Rectangle
+{
+ id: root
+ border
+ {
+ ColorAnimation on color { }
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/onlyMajorVersion.qml b/tests/auto/qml/qmllint/data/onlyMajorVersion.qml
new file mode 100644
index 0000000000..4066f8f097
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/onlyMajorVersion.qml
@@ -0,0 +1,8 @@
+import QtQuick.Controls 2 as QQC2
+
+QQC2.ApplicationWindow {
+ height: 400
+ width: 400
+ visible: true
+ QQC2.Action {} // Action because it appeared in version 2.3
+}
diff --git a/tests/auto/qml/qmllint/data/optionalChainingCall.qml b/tests/auto/qml/qmllint/data/optionalChainingCall.qml
new file mode 100644
index 0000000000..fe9716293d
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/optionalChainingCall.qml
@@ -0,0 +1,9 @@
+import QtQuick 2.0
+
+MouseArea {
+ id: ma
+ function f() {}
+ onClicked: {
+ f?.()
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/overridescript.qml b/tests/auto/qml/qmllint/data/overridescript.qml
index b85333b95f..d88f905aa7 100644
--- a/tests/auto/qml/qmllint/data/overridescript.qml
+++ b/tests/auto/qml/qmllint/data/overridescript.qml
@@ -1,5 +1,4 @@
import QtQml
-import QtTest
import "testlogger.js" as TestLogger
QtObject {
diff --git a/tests/auto/qml/qmllint/data/pluginQuick_anchors.qml b/tests/auto/qml/qmllint/data/pluginQuick_anchors.qml
new file mode 100644
index 0000000000..927b422a06
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/pluginQuick_anchors.qml
@@ -0,0 +1,9 @@
+import QtQuick
+
+Item {
+ PluginQuickAnchorsBase {
+ anchors.horizontalCenter: null
+ anchors.verticalCenter: null
+ anchors.baseline: parent.baseline
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/pluginQuick_anchorsUndefined.qml b/tests/auto/qml/qmllint/data/pluginQuick_anchorsUndefined.qml
new file mode 100644
index 0000000000..b6c0f59c7f
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/pluginQuick_anchorsUndefined.qml
@@ -0,0 +1,10 @@
+import QtQuick
+
+Item {
+ PluginQuickAnchorsBase {
+ anchors.horizontalCenter: undefined
+ anchors.verticalCenter: undefined
+ anchors.baseline: undefined
+ Component.onCompleted: anchors.bottom = undefined
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/pluginQuick_attached.qml b/tests/auto/qml/qmllint/data/pluginQuick_attached.qml
new file mode 100644
index 0000000000..c5f4e0d552
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/pluginQuick_attached.qml
@@ -0,0 +1,27 @@
+import QtQuick
+import QtQuick.Layouts
+import QtQuick.Controls
+
+Item {
+ QtObject {
+ // QtQuick
+ Accessible.name: "Foo"
+ LayoutMirroring.enabled: true
+ EnterKey.type: Qt.EnterKeyGo
+
+ // QtQuick.Layouts
+ Layout.minimumHeight: 3
+ property bool stackLayout: StackLayout.isCurrentItem // Read-only
+
+ // QtQuick.Templates
+ ScrollBar.vertical: ScrollBar {}
+ ScrollIndicator.vertical: ScrollIndicator {}
+ SplitView.fillWidth: true
+ StackView.visible: true
+ property int swipeView: SwipeView.index // Read-only
+ TextArea.flickable: TextArea {}
+ ToolTip.delay: 50
+ property bool tumbler: Tumbler.displacement // Read-only
+ property bool swipeDelegate: SwipeDelegate.pressed // Read-only
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/pluginQuick_attachedClean.qml b/tests/auto/qml/qmllint/data/pluginQuick_attachedClean.qml
new file mode 100644
index 0000000000..5114628428
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/pluginQuick_attachedClean.qml
@@ -0,0 +1,31 @@
+import QtQuick
+import QtQuick.Layouts
+import QtQuick.Controls
+
+Item {
+ // QtQuick
+ Accessible.name: "Foo"
+ LayoutMirroring.enabled: true
+ EnterKey.type: Qt.EnterKeyGo
+
+ //QtQuick.Layouts
+ Layout.minimumHeight: 3
+ property bool stackLayout: StackLayout.isCurrentItem // Read-only
+
+ // QtQuick.Templates
+ SplitView.fillWidth: true
+ StackView.visible: true
+ property int swipeView: SwipeView.index // Read only, enforceable but complicated
+ Flickable {
+ TextArea.flickable: TextArea {}
+ ScrollIndicator.vertical: ScrollIndicator {}
+ ScrollBar.vertical: ScrollBar {}
+ }
+ ToolTip.delay: 50
+ TableView {
+ delegate: Item {
+ property bool tumbler: Tumbler.displacement // Read only, enforceable but complicated
+ }
+ }
+ property bool swipeDelegate: SwipeDelegate.pressed // Read only
+}
diff --git a/tests/auto/qml/qmllint/data/pluginQuick_attachedIgnore.qml b/tests/auto/qml/qmllint/data/pluginQuick_attachedIgnore.qml
new file mode 100644
index 0000000000..28612a129a
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/pluginQuick_attachedIgnore.qml
@@ -0,0 +1,15 @@
+import QtQuick
+import QtQuick.Controls
+
+Item {
+ id: delegate
+ property bool tumbler: Tumbler.displacement // Read-only
+ QtObject {
+ property bool tumbler2: delegate.Tumbler.displacement
+ }
+ QtObject {
+ Component.onCompleted: {
+ delegate.Accessible.name = "Foo"
+ }
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/pluginQuick_layoutChildren.qml b/tests/auto/qml/qmllint/data/pluginQuick_layoutChildren.qml
new file mode 100644
index 0000000000..5a70b05d79
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/pluginQuick_layoutChildren.qml
@@ -0,0 +1,29 @@
+import QtQuick
+import QtQuick.Layouts
+
+Item {
+ RowLayout {
+ Item {
+ anchors.fill: parent
+ x: 10
+ y: 20
+ width: 100
+ height: 200
+ }
+ }
+
+ Grid {
+ Item {
+ anchors.fill: parent
+ x: 10
+ y: 20
+ }
+ }
+
+ Flow {
+ Item { anchors.fill: parent;
+ x: 10
+ y: 20
+ }
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/pluginQuick_noCrashOnUneresolved.qml b/tests/auto/qml/qmllint/data/pluginQuick_noCrashOnUneresolved.qml
new file mode 100644
index 0000000000..7e04394350
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/pluginQuick_noCrashOnUneresolved.qml
@@ -0,0 +1,10 @@
+import QtQuick.Controls
+
+Item {
+
+ Tumbler {
+
+ contentItem: Item {
+ }
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/pluginQuick_propertyChangesInvalidTarget.qml b/tests/auto/qml/qmllint/data/pluginQuick_propertyChangesInvalidTarget.qml
new file mode 100644
index 0000000000..fa7d4ef1ac
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/pluginQuick_propertyChangesInvalidTarget.qml
@@ -0,0 +1,8 @@
+import QtQuick 2.0
+
+Rectangle {
+ State {
+ name: "test"
+ PropertyChanges { target: root; color: "blue" }
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/pluginQuick_propertyChangesParsed.qml b/tests/auto/qml/qmllint/data/pluginQuick_propertyChangesParsed.qml
new file mode 100644
index 0000000000..94873463f1
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/pluginQuick_propertyChangesParsed.qml
@@ -0,0 +1,19 @@
+import QtQuick
+
+Window {
+ Item {
+ id: foo
+ property color myColor: 'black'
+
+ states: [
+ State {
+ PropertyChanges {
+ target: foo
+ myColor: Qt.rgba(0.5, 0.5, 0.5, 0.16)
+ notThere: "a"
+ }
+ }
+ ]
+
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/pluginQuick_swipeDelegate.qml b/tests/auto/qml/qmllint/data/pluginQuick_swipeDelegate.qml
new file mode 100644
index 0000000000..a6c3b2c743
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/pluginQuick_swipeDelegate.qml
@@ -0,0 +1,19 @@
+import QtQuick.Controls
+import QtQuick
+
+Item {
+ SwipeDelegate {
+ contentItem: Item { anchors.left: parent.left }
+ background: Item { anchors.right: parent.right }
+
+ swipe.left: Item {}
+ swipe.behind: Item {}
+ }
+ SwipeDelegate {
+ contentItem: Item { anchors.centerIn: parent }
+ background: Item { anchors.fill: parent }
+
+ swipe.right: Item {}
+ swipe.behind: Item {}
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/pluginQuick_varProp.qml b/tests/auto/qml/qmllint/data/pluginQuick_varProp.qml
new file mode 100644
index 0000000000..17b5d99d6b
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/pluginQuick_varProp.qml
@@ -0,0 +1,16 @@
+import QtQuick
+import QtQuick.Controls
+
+Item {
+ SpinBox {
+ textFromValue: null
+ valueFromText: { return 6; }
+ }
+ TableView {
+ columnWidthProvider: null
+ rowHeightProvider: { return 3; }
+ }
+ Tumbler {
+ contentItem: Item {}
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/pluginQuick_varPropClean.qml b/tests/auto/qml/qmllint/data/pluginQuick_varPropClean.qml
new file mode 100644
index 0000000000..b17f7e6dd7
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/pluginQuick_varPropClean.qml
@@ -0,0 +1,16 @@
+import QtQuick
+import QtQuick.Controls
+
+Item {
+ SpinBox {
+ textFromValue: function(value, locale) { return Number(value).toLocaleString(locale, 'f', 0); }
+ valueFromText: function(text, locale) { return Number.fromLocaleString(locale, text); }
+ }
+ TableView {
+ columnWidthProvider: function(column) { return column*50; }
+ rowHeightProvider: function(row) { return row*3; }
+ }
+ Tumbler {
+ contentItem: PathView {}
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/pragmaStrict.qml b/tests/auto/qml/qmllint/data/pragmaStrict.qml
new file mode 100644
index 0000000000..d50fe9b717
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/pragmaStrict.qml
@@ -0,0 +1,7 @@
+pragma Strict
+
+import QtQml
+
+QtObject {
+ function add(a, b) { return a + b; }
+}
diff --git a/tests/auto/qml/qmllint/data/prefixedAttachedProperty.qml b/tests/auto/qml/qmllint/data/prefixedAttachedProperty.qml
new file mode 100644
index 0000000000..1f9634e280
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/prefixedAttachedProperty.qml
@@ -0,0 +1,5 @@
+import QtQuick as T
+
+T.Item {
+ T.Accessible.name: "Example"
+}
diff --git a/tests/auto/qml/qmllint/data/propertyBindingValue.qml b/tests/auto/qml/qmllint/data/propertyBindingValue.qml
new file mode 100644
index 0000000000..eb461e8fdd
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/propertyBindingValue.qml
@@ -0,0 +1,3 @@
+PropertyBase2 {
+ property int bar: foo.bar
+}
diff --git a/tests/auto/qml/qmllint/data/propertyDelegate.qml b/tests/auto/qml/qmllint/data/propertyDelegate.qml
new file mode 100644
index 0000000000..aa4d2c35c8
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/propertyDelegate.qml
@@ -0,0 +1,5 @@
+import QtQuick 2.15
+
+Repeater {
+ delegate: Item {}
+}
diff --git a/tests/auto/qml/qmllint/data/propertyOverride.qml b/tests/auto/qml/qmllint/data/propertyOverride.qml
new file mode 100644
index 0000000000..04c28485bb
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/propertyOverride.qml
@@ -0,0 +1,5 @@
+import QtQuick 2.15
+
+PropertyBase2 {
+ foo: Item {}
+}
diff --git a/tests/auto/qml/qmllint/data/propertypass_pluginTest.qml b/tests/auto/qml/qmllint/data/propertypass_pluginTest.qml
new file mode 100644
index 0000000000..728b014b85
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/propertypass_pluginTest.qml
@@ -0,0 +1,24 @@
+import QtQuick 2.0
+
+Item {
+ Text {
+ id: foo
+ text: "Foo" // Specific property we're targeting in one element
+ x: 5 // Property we're targeting regardless of type
+ y: x + 5 // Property used in a binding
+ font.bold: true // Not targeted
+ }
+ x: 5 // Property we're targeting regardless of type
+
+ ListModel { id: listModel }
+
+ ListView { // Entire type covered
+ model: listModel
+ height: 50
+ }
+
+ Component.onCompleted: {
+ console.log(foo.x); // Reading property from another component
+ foo.x = 30; // Writing property from another component
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/qEventPoint.qml b/tests/auto/qml/qmllint/data/qEventPoint.qml
new file mode 100644
index 0000000000..086e710b48
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/qEventPoint.qml
@@ -0,0 +1,9 @@
+import QtQuick
+
+TapHandler {
+ acceptedButtons: Qt.LeftButton | Qt.RightButton
+ onSingleTapped: (eventPoint, button) => {
+ console.log("Single tap at", eventPoint, "with button", button)
+ }
+ onTapped: console.log("tapped")
+}
diff --git a/tests/auto/qml/qmllint/data/qjsroot.qml b/tests/auto/qml/qmllint/data/qjsroot.qml
new file mode 100644
index 0000000000..c5995b9576
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/qjsroot.qml
@@ -0,0 +1,20 @@
+import QtQuick
+
+QtObject {
+ property var locale: Qt.locale()
+ property date currentDate: new Date()
+ property RegularExpressionValidator validator: RegularExpressionValidator { regularExpression: /20([0-9]+)/ };
+ property double pi: 3.14
+
+ // Test date
+ property string dateString: currentDate.toLocaleDateString();
+
+ // Test string
+ property int dateStringDotIndex: dateString.indexOf(".")
+
+ // Test regularExpression
+ property var dateStringReplace: validator.regularExpression.exec(dateString)
+
+ // Test double
+ property string fixedPi: pi.toFixed(1)
+}
diff --git a/tests/auto/qml/qmllint/data/qmlRootMethods.qml b/tests/auto/qml/qmllint/data/qmlRootMethods.qml
new file mode 100644
index 0000000000..5541de3a32
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/qmlRootMethods.qml
@@ -0,0 +1,12 @@
+import QtQml
+
+QtObject {
+ id: self
+
+ objectName: self.toString()
+
+ Component.onCompleted: {
+ self.destroy();
+ self.destroy(25);
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/qmldirAndQmltypes.qml b/tests/auto/qml/qmllint/data/qmldirAndQmltypes.qml
index 4847fc9196..ad88f1c58c 100644
--- a/tests/auto/qml/qmllint/data/qmldirAndQmltypes.qml
+++ b/tests/auto/qml/qmllint/data/qmldirAndQmltypes.qml
@@ -2,5 +2,5 @@ import Things 1.0
Something {
property var a: SomethingEntirelyStrange {}
- property var b: SomethingEntirelyStrange.AAA
+ property var b: SomethingEntirelyStrange.AnEnum.AAA
}
diff --git a/tests/auto/qml/qmllint/data/qmldirImport/QtObjectWithDefaultProperty.qml b/tests/auto/qml/qmllint/data/qmldirImport/QtObjectWithDefaultProperty.qml
new file mode 100644
index 0000000000..d33d0b5c94
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/qmldirImport/QtObjectWithDefaultProperty.qml
@@ -0,0 +1,4 @@
+import DuplicateImport // imports QtQml
+QtObject {
+ default property QtObject child
+}
diff --git a/tests/auto/qml/qmllint/data/qmldirImport/duplicate.qml b/tests/auto/qml/qmllint/data/qmldirImport/duplicate.qml
new file mode 100644
index 0000000000..22f454ad44
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/qmldirImport/duplicate.qml
@@ -0,0 +1,7 @@
+import DuplicateImport // imports QtQml directly and indirectly via QtQuick
+
+QtObjectWithDefaultProperty { // for default property
+ ItemDerived { // item derived has compatible QtObject type
+ x: 4
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/qmldirImportAndDepend/QtObjectWithDefaultProperty.qml b/tests/auto/qml/qmllint/data/qmldirImportAndDepend/QtObjectWithDefaultProperty.qml
new file mode 100644
index 0000000000..fb856d0b29
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/qmldirImportAndDepend/QtObjectWithDefaultProperty.qml
@@ -0,0 +1,4 @@
+import Things // imports QtQml
+QtObject {
+ default property QtObject child
+}
diff --git a/tests/auto/qml/qmllint/data/qmldirImportAndDepend/good.qml b/tests/auto/qml/qmllint/data/qmldirImportAndDepend/good.qml
index 275b531845..987301ef76 100644
--- a/tests/auto/qml/qmllint/data/qmldirImportAndDepend/good.qml
+++ b/tests/auto/qml/qmllint/data/qmldirImportAndDepend/good.qml
@@ -1,6 +1,6 @@
import Things
-QtObject {
+QtObjectWithDefaultProperty { // for default property
objectName: "QtQml was imported from Things/qmldir"
ItemDerived {
diff --git a/tests/auto/qml/qmllint/data/qmodelIndex.qml b/tests/auto/qml/qmllint/data/qmodelIndex.qml
new file mode 100644
index 0000000000..e0df84b68b
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/qmodelIndex.qml
@@ -0,0 +1,6 @@
+import QtQml
+
+QtObject {
+ property ItemSelectionModel itemSelectionModel;
+ function row() { return itemSelectionModel.currentIndex.row; }
+}
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/qtquickWindow20.qml b/tests/auto/qml/qmllint/data/qtquickWindow20.qml
new file mode 100644
index 0000000000..3019e3037b
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/qtquickWindow20.qml
@@ -0,0 +1,5 @@
+import QtQuick 2.0
+
+QtObject {
+ property var win: Window.window
+}
diff --git a/tests/auto/qml/qmllint/data/qtquickWindow21.qml b/tests/auto/qml/qmllint/data/qtquickWindow21.qml
new file mode 100644
index 0000000000..7047436da2
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/qtquickWindow21.qml
@@ -0,0 +1,5 @@
+import QtQuick 2.1
+
+QtObject {
+ property var win: Window.window
+}
diff --git a/tests/auto/qml/qmllint/data/qtquickdialog.qml b/tests/auto/qml/qmllint/data/qtquickdialog.qml
new file mode 100644
index 0000000000..4579719d06
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/qtquickdialog.qml
@@ -0,0 +1,5 @@
+import QtQuick.Dialogs
+
+MessageDialog {
+ buttons:MessageDialog.Ok
+ }
diff --git a/tests/auto/qml/qmllint/data/qvariant.qml b/tests/auto/qml/qmllint/data/qvariant.qml
new file mode 100644
index 0000000000..a9a2978876
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/qvariant.qml
@@ -0,0 +1,5 @@
+import QtQml
+
+QtObject {
+ property int len: Qt.color().length
+}
diff --git a/tests/auto/qml/qmllint/data/relPathQrc/Bar/Thing2.qml b/tests/auto/qml/qmllint/data/relPathQrc/Bar/Thing2.qml
new file mode 100644
index 0000000000..3052615aef
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/relPathQrc/Bar/Thing2.qml
@@ -0,0 +1,3 @@
+import QtQuick
+
+Item {}
diff --git a/tests/auto/qml/qmllint/data/relPathQrc/Foo/Thing.qml b/tests/auto/qml/qmllint/data/relPathQrc/Foo/Thing.qml
new file mode 100644
index 0000000000..f89ee92e3e
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/relPathQrc/Foo/Thing.qml
@@ -0,0 +1,3 @@
+import "../Bar" as Bar
+
+Bar.Thing2 {}
diff --git a/tests/auto/qml/qmllint/data/relPathQrc/resources.qrc b/tests/auto/qml/qmllint/data/relPathQrc/resources.qrc
new file mode 100644
index 0000000000..42cab37c29
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/relPathQrc/resources.qrc
@@ -0,0 +1,7 @@
+<RCC>
+ <qresource prefix="/fooBar/">
+ <file alias="Foo/Thing1.qml">Foo/Thing.qml</file>
+ <file alias="Bar/Thing2.qml">Bar/Thing2.qml</file>
+ </qresource>
+</RCC>
+
diff --git a/tests/auto/qml/qmllint/data/requiredProperty.qml b/tests/auto/qml/qmllint/data/requiredProperty.qml
index b10f0f67cd..f1e82bb402 100644
--- a/tests/auto/qml/qmllint/data/requiredProperty.qml
+++ b/tests/auto/qml/qmllint/data/requiredProperty.qml
@@ -1,6 +1,9 @@
-import QtQml 2.15
+import QtQuick 2.15
-QtObject {
- property int x
- required x
+Item {
+ component Required : QtObject {
+ property int x
+ required x
+ }
+ Required { x: 5 }
}
diff --git a/tests/auto/qml/qmllint/data/requiredPropertyBindings.qml b/tests/auto/qml/qmllint/data/requiredPropertyBindings.qml
new file mode 100644
index 0000000000..3bba84f412
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/requiredPropertyBindings.qml
@@ -0,0 +1,24 @@
+import QtQuick 2.0
+
+Item {
+ component Base : Item {
+ required property string required_now_string
+ property string required_later_string
+
+ required property QtObject required_now_object
+ property QtObject required_later_object
+ }
+
+ component Derived : Base {
+ required required_later_string
+ required required_later_object
+ }
+
+ Derived {
+ required_now_string: ""
+ required_later_string: ""
+
+ required_now_object: QtObject {}
+ required_later_object: QtObject {}
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/requiredPropertyBindingsLater.qml b/tests/auto/qml/qmllint/data/requiredPropertyBindingsLater.qml
new file mode 100644
index 0000000000..65c59d7161
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/requiredPropertyBindingsLater.qml
@@ -0,0 +1,18 @@
+import QtQuick 2.0
+
+Item {
+ component Base : Item {
+ required property string required_now_string
+ property string required_later_string
+ property string required_even_later_string
+ }
+
+ component Derived : Base {
+ required required_later_string
+ }
+
+ Derived {
+ required required_even_later_string
+ required_now_string: ""
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/requiredPropertyBindingsNow.qml b/tests/auto/qml/qmllint/data/requiredPropertyBindingsNow.qml
new file mode 100644
index 0000000000..701760b4e7
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/requiredPropertyBindingsNow.qml
@@ -0,0 +1,17 @@
+import QtQuick 2.0
+
+Item {
+ component Base : Item {
+ required property string required_now_string
+ property string required_later_string
+ }
+
+ component Derived : Base {
+ required required_later_string
+ }
+
+ Derived {
+ required property string required_defined_here_string
+ required_later_string: ""
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/requiredPropertyInComponent.qml b/tests/auto/qml/qmllint/data/requiredPropertyInComponent.qml
new file mode 100644
index 0000000000..24ecf9d706
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/requiredPropertyInComponent.qml
@@ -0,0 +1,25 @@
+import QtQuick 2.0
+
+Row {
+ // explicit component
+ Component {
+ id: foo
+ Item {
+ required property int i
+ }
+ }
+
+ // implicit component, plain property
+ property Component com: Item {}
+
+ Repeater {
+ model: 3
+ // implicit component, default property
+ Text {
+ required property int index
+ height: 40
+ color: "black"
+ text: "I'm item " + index
+ }
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/returnTypeAnnotation_component.qml b/tests/auto/qml/qmllint/data/returnTypeAnnotation_component.qml
new file mode 100644
index 0000000000..de142337b4
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/returnTypeAnnotation_component.qml
@@ -0,0 +1,9 @@
+import QtQml
+import QtQuick
+
+QtObject {
+ id: root
+ component Comp : Item { }
+ property Comp c: Comp{ }
+ function comp() { return root.c }
+}
diff --git a/tests/auto/qml/qmllint/data/returnTypeAnnotation_enum.qml b/tests/auto/qml/qmllint/data/returnTypeAnnotation_enum.qml
new file mode 100644
index 0000000000..0585ceceb2
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/returnTypeAnnotation_enum.qml
@@ -0,0 +1,5 @@
+import QtQuick
+
+QtObject {
+ function enumeration() { return Text.AlignRight }
+}
diff --git a/tests/auto/qml/qmllint/data/returnTypeAnnotation_method.qml b/tests/auto/qml/qmllint/data/returnTypeAnnotation_method.qml
new file mode 100644
index 0000000000..dc03311e73
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/returnTypeAnnotation_method.qml
@@ -0,0 +1,6 @@
+import QtQml
+
+QtObject {
+ function f() { }
+ function method() { return f }
+}
diff --git a/tests/auto/qml/qmllint/data/returnTypeAnnotation_property.qml b/tests/auto/qml/qmllint/data/returnTypeAnnotation_property.qml
new file mode 100644
index 0000000000..bb79978d85
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/returnTypeAnnotation_property.qml
@@ -0,0 +1,7 @@
+import QtQml
+
+QtObject {
+ id: root
+ property int i: 1
+ function prop() { return root.i }
+}
diff --git a/tests/auto/qml/qmllint/data/returnTypeAnnotation_type.qml b/tests/auto/qml/qmllint/data/returnTypeAnnotation_type.qml
new file mode 100644
index 0000000000..78f02a8b67
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/returnTypeAnnotation_type.qml
@@ -0,0 +1,5 @@
+import QtQml
+
+QtObject {
+ function type() { return 1 + 1 }
+}
diff --git a/tests/auto/qml/qmllint/data/scriptInTemplate.qml b/tests/auto/qml/qmllint/data/scriptInTemplate.qml
new file mode 100644
index 0000000000..ba333dcd3e
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/scriptInTemplate.qml
@@ -0,0 +1,6 @@
+import QtQml
+import scripts
+
+QtObject {
+ objectName: `Result: ${Foo.getText()}`
+}
diff --git a/tests/auto/qml/qmllint/data/scripts/Foo.js b/tests/auto/qml/qmllint/data/scripts/Foo.js
new file mode 100644
index 0000000000..1d5106f733
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/scripts/Foo.js
@@ -0,0 +1,6 @@
+.pragma library
+
+function getText() {
+ return "whohoooooo"
+}
+
diff --git a/tests/auto/qml/qmllint/data/scripts/qmldir b/tests/auto/qml/qmllint/data/scripts/qmldir
new file mode 100644
index 0000000000..b4bf844348
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/scripts/qmldir
@@ -0,0 +1,4 @@
+module scripts
+typeinfo scripts.qmltypes
+Foo 1.0 Foo.js
+
diff --git a/tests/auto/qml/qmllint/data/scripts/scripts.qmltypes b/tests/auto/qml/qmllint/data/scripts/scripts.qmltypes
new file mode 100644
index 0000000000..ebbfc41eb2
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/scripts/scripts.qmltypes
@@ -0,0 +1,22 @@
+import QtQuick.tooling 1.2
+
+// This file describes the plugin-supplied types contained in the library.
+// It is used for QML tooling purposes only.
+//
+// This file was auto-generated by qmltyperegistrar.
+
+Module {
+ Component {
+ file: "value.h"
+ name: "ValueType"
+ accessSemantics: "value"
+ exports: ["scripts/vvv 1.0"]
+ exportMetaObjectRevisions: [256]
+ Method {
+ name: "ValueType"
+ isConstructor: true
+ Parameter { name: "v"; type: "QString" }
+ }
+ Method { name: "ValueType"; isCloned: true; isConstructor: true }
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/scriptstring.qml b/tests/auto/qml/qmllint/data/scriptstring.qml
new file mode 100644
index 0000000000..733434e924
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/scriptstring.qml
@@ -0,0 +1,73 @@
+import QtQuick
+
+Window {
+ id: root
+
+ Rectangle {
+ id: main
+
+ MouseArea {
+ id: mouse
+ property int clickCount: 0
+ onClicked: {
+ clickCount++
+
+ switch ( clickCount % 3 ) {
+ case 1 :
+ main.state = "middleState"
+ break
+ case 2 :
+ main.state = "rightState"
+ break
+ default :
+ main.state = "leftState"
+ }
+ }
+ }
+
+ Rectangle {
+ id: mover
+ anchors {
+ left: undefined
+ right: undefined
+ horizontalCenter: undefined
+ top: main.top
+ bottom: main.bottom
+ }
+ }
+
+ states: [
+ State {
+ name: "leftState"
+ AnchorChanges {
+ target: mover
+ anchors.left: main.left
+ anchors.right: undefined
+ anchors.horizontalCenter: undefined
+ }
+ },
+ State {
+ name: "middleState"
+ AnchorChanges {
+ target: mover
+ anchors {
+ left: undefined
+ right: undefined
+ horizontalCenter: main.horizontalCenter
+ }
+ }
+ },
+ State {
+ name: "rightState"
+ AnchorChanges {
+ target: mover
+ anchors {
+ left: undefined
+ right: main.right
+ horizontalCenter: undefined
+ }
+ }
+ }
+ ]
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/settings/bare/.qmllint.ini b/tests/auto/qml/qmllint/data/settings/bare/.qmllint.ini
new file mode 100644
index 0000000000..2dc9ff658c
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/settings/bare/.qmllint.ini
@@ -0,0 +1,2 @@
+[General]
+DisableDefaultImports=true
diff --git a/tests/auto/qml/qmllint/data/settings/bare/bare.qml b/tests/auto/qml/qmllint/data/settings/bare/bare.qml
new file mode 100644
index 0000000000..852b8339b9
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/settings/bare/bare.qml
@@ -0,0 +1,3 @@
+import QtQuick // Should fail because Bare is specified with no import
+
+Item {}
diff --git a/tests/auto/qml/qmllint/data/settings/plugin/.qmllint.ini b/tests/auto/qml/qmllint/data/settings/plugin/.qmllint.ini
new file mode 100644
index 0000000000..a72e0e29e2
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/settings/plugin/.qmllint.ini
@@ -0,0 +1,2 @@
+[Warnings]
+TestWarning=disable
diff --git a/tests/auto/qml/qmllint/data/settings/plugin/elemenpass_pluginSettingTest.qml b/tests/auto/qml/qmllint/data/settings/plugin/elemenpass_pluginSettingTest.qml
new file mode 100644
index 0000000000..b9250a2d11
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/settings/plugin/elemenpass_pluginSettingTest.qml
@@ -0,0 +1,7 @@
+import QtQuick
+
+Item {
+ Rectangle {
+ radius: 5
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/settings/qmlimports/.qmllint.ini b/tests/auto/qml/qmllint/data/settings/qmlimports/.qmllint.ini
new file mode 100644
index 0000000000..c2f9d81743
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/settings/qmlimports/.qmllint.ini
@@ -0,0 +1,2 @@
+[General]
+AdditionalQmlImportPaths=subdir
diff --git a/tests/auto/qml/qmllint/data/settings/qmlimports/qmlimports.qml b/tests/auto/qml/qmllint/data/settings/qmlimports/qmlimports.qml
new file mode 100644
index 0000000000..221ddff254
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/settings/qmlimports/qmlimports.qml
@@ -0,0 +1,3 @@
+import Custom
+
+Thing {}
diff --git a/tests/auto/qml/qmllint/data/settings/qmlimports/subdir/Custom/custom.qmltypes b/tests/auto/qml/qmllint/data/settings/qmlimports/subdir/Custom/custom.qmltypes
new file mode 100644
index 0000000000..b3839652dc
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/settings/qmlimports/subdir/Custom/custom.qmltypes
@@ -0,0 +1,11 @@
+import QtQuick.tooling 1.2
+Module {
+ dependencies: []
+ Component {
+ name: "Thing"
+ prototype: "QObject"
+ exports: [
+ "Custom/Thing 1.0",
+ ]
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/settings/qmlimports/subdir/Custom/qmldir b/tests/auto/qml/qmllint/data/settings/qmlimports/subdir/Custom/qmldir
new file mode 100644
index 0000000000..6ad407fd38
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/settings/qmlimports/subdir/Custom/qmldir
@@ -0,0 +1,2 @@
+module Custom
+typeinfo custom.qmltypes
diff --git a/tests/auto/qml/qmllint/data/settings/qmltypes/.qmllint.ini b/tests/auto/qml/qmllint/data/settings/qmltypes/.qmllint.ini
new file mode 100644
index 0000000000..3dc2c8fd1b
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/settings/qmltypes/.qmllint.ini
@@ -0,0 +1,3 @@
+[General]
+OverwriteImportTypes=subdir/custom.qmltypes
+
diff --git a/tests/auto/qml/qmllint/data/settings/qmltypes/qmltypes.qml b/tests/auto/qml/qmllint/data/settings/qmltypes/qmltypes.qml
new file mode 100644
index 0000000000..221ddff254
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/settings/qmltypes/qmltypes.qml
@@ -0,0 +1,3 @@
+import Custom
+
+Thing {}
diff --git a/tests/auto/qml/qmllint/data/settings/qmltypes/subdir/custom.qmltypes b/tests/auto/qml/qmllint/data/settings/qmltypes/subdir/custom.qmltypes
new file mode 100644
index 0000000000..b3839652dc
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/settings/qmltypes/subdir/custom.qmltypes
@@ -0,0 +1,11 @@
+import QtQuick.tooling 1.2
+Module {
+ dependencies: []
+ Component {
+ name: "Thing"
+ prototype: "QObject"
+ exports: [
+ "Custom/Thing 1.0",
+ ]
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/settings/unqualifiedSilent/.qmllint.ini b/tests/auto/qml/qmllint/data/settings/unqualifiedSilent/.qmllint.ini
new file mode 100644
index 0000000000..92c03b2490
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/settings/unqualifiedSilent/.qmllint.ini
@@ -0,0 +1,2 @@
+[Warnings]
+UnqualifiedAccess=disable
diff --git a/tests/auto/qml/qmllint/data/settings/unqualifiedSilent/unqualified.qml b/tests/auto/qml/qmllint/data/settings/unqualifiedSilent/unqualified.qml
new file mode 100644
index 0000000000..5a68b757a9
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/settings/unqualifiedSilent/unqualified.qml
@@ -0,0 +1,5 @@
+import QtQml
+
+QtObject {
+ property int foo: root.x
+}
diff --git a/tests/auto/qml/qmllint/data/settings/unusedImportWarning/.qmllint.ini b/tests/auto/qml/qmllint/data/settings/unusedImportWarning/.qmllint.ini
new file mode 100644
index 0000000000..c012a1fc28
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/settings/unusedImportWarning/.qmllint.ini
@@ -0,0 +1,2 @@
+[Warnings]
+UnusedImports=warning
diff --git a/tests/auto/qml/qmllint/data/settings/unusedImportWarning/unused.qml b/tests/auto/qml/qmllint/data/settings/unusedImportWarning/unused.qml
new file mode 100644
index 0000000000..715ebf29d7
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/settings/unusedImportWarning/unused.qml
@@ -0,0 +1,5 @@
+import QtQml
+import QtQml.Models
+
+QtObject {
+}
diff --git a/tests/auto/qml/qmllint/data/shadowable.qml b/tests/auto/qml/qmllint/data/shadowable.qml
new file mode 100644
index 0000000000..d9c5f78016
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/shadowable.qml
@@ -0,0 +1,6 @@
+import QtQml
+
+QtObject {
+ property NotSoSimple a: NotSoSimple {}
+ property int b: a.complicated
+}
diff --git a/tests/auto/qml/qmllint/data/shadowedMethod.qml b/tests/auto/qml/qmllint/data/shadowedMethod.qml
new file mode 100644
index 0000000000..72f18aaec7
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/shadowedMethod.qml
@@ -0,0 +1,8 @@
+import QtQuick
+
+QtObject {
+ function foo() {}
+ property bool foo: false
+
+ Component.onCompleted: foo()
+}
diff --git a/tests/auto/qml/qmllint/data/shadowedSignal.qml b/tests/auto/qml/qmllint/data/shadowedSignal.qml
new file mode 100644
index 0000000000..e4bb003495
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/shadowedSignal.qml
@@ -0,0 +1,6 @@
+import QtQuick
+
+MouseArea {
+ id: mouseArea
+ Component.onCompleted: pressed()
+}
diff --git a/tests/auto/qml/qmllint/data/shadowedSignalWithId.qml b/tests/auto/qml/qmllint/data/shadowedSignalWithId.qml
new file mode 100644
index 0000000000..ed7cc9f6c4
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/shadowedSignalWithId.qml
@@ -0,0 +1,6 @@
+import QtQuick
+
+MouseArea {
+ id: mouseArea
+ Component.onCompleted: mouseArea.pressed()
+}
diff --git a/tests/auto/qml/qmllint/data/shadowedSlot.qml b/tests/auto/qml/qmllint/data/shadowedSlot.qml
new file mode 100644
index 0000000000..cb09645746
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/shadowedSlot.qml
@@ -0,0 +1,6 @@
+import QtQml
+
+ObjectModel {
+ property bool move: false
+ Component.onCompleted: move()
+}
diff --git a/tests/auto/qml/qmllint/data/storeNameMethod.qml b/tests/auto/qml/qmllint/data/storeNameMethod.qml
new file mode 100644
index 0000000000..fca02b288f
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/storeNameMethod.qml
@@ -0,0 +1,12 @@
+import QtQuick 2.15
+import QtQuick.Window 2.15
+
+Window {
+ Rectangle {
+
+ Timer {
+ function foo() {}
+ onTriggered: foo = 1
+ }
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/stringAsId.qml b/tests/auto/qml/qmllint/data/stringAsId.qml
new file mode 100644
index 0000000000..58ea28cb17
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/stringAsId.qml
@@ -0,0 +1,5 @@
+import QtQml
+
+QtObject {
+ id: "aString"
+}
diff --git a/tests/auto/qml/qmllint/data/stringIdUsedInWarning.qml b/tests/auto/qml/qmllint/data/stringIdUsedInWarning.qml
new file mode 100644
index 0000000000..672c00f39b
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/stringIdUsedInWarning.qml
@@ -0,0 +1,9 @@
+import QtQml
+
+QtObject {
+ id: "stringy"
+ property int i
+ property QtObject o: QtObject {
+ Component.onCompleted: console.log(i)
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/stringLength.qml b/tests/auto/qml/qmllint/data/stringLength.qml
new file mode 100644
index 0000000000..354fed7b22
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/stringLength.qml
@@ -0,0 +1,9 @@
+import QtQuick 2.15
+
+TextInput {
+ id: textInput
+
+ Component.onCompleted: {
+ console.log("text.length", textInput.text.length);
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/stringLength2.qml b/tests/auto/qml/qmllint/data/stringLength2.qml
new file mode 100644
index 0000000000..6dc2942b37
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/stringLength2.qml
@@ -0,0 +1,10 @@
+import QtQuick 2.15
+
+Item {
+ id: foo
+
+ property string s
+ Component.onCompleted: {
+ console.log("s.length", foo.s.length);
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/stringLength3.qml b/tests/auto/qml/qmllint/data/stringLength3.qml
new file mode 100644
index 0000000000..292a163145
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/stringLength3.qml
@@ -0,0 +1,8 @@
+import QtQuick 2.11
+import QtQuick.Window 2.3
+
+Item {
+ InfoItemTextEdit {
+ textStrColor: valueStr.length === 0 ? "#f5a71e" : "#f5a715"
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/stringToByteArray.qml b/tests/auto/qml/qmllint/data/stringToByteArray.qml
new file mode 100644
index 0000000000..b36da28f0d
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/stringToByteArray.qml
@@ -0,0 +1,7 @@
+import QtQuick
+
+Item {
+ objectName: layer.samplerName
+ layer.samplerName: "source"
+}
+
diff --git a/tests/auto/qml/qmllint/data/stringToDateTime.qml b/tests/auto/qml/qmllint/data/stringToDateTime.qml
new file mode 100644
index 0000000000..dc4bd6cda5
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/stringToDateTime.qml
@@ -0,0 +1,7 @@
+import StringToDateTime
+
+StringToDateTime {
+ aDate: "2023-03-29"
+ aTime: "15:10:41"
+ aDateTime: "2023-03-29 15:10:41"
+}
diff --git a/tests/auto/qml/qmllint/data/switcher.qml b/tests/auto/qml/qmllint/data/switcher.qml
new file mode 100644
index 0000000000..260b00fb84
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/switcher.qml
@@ -0,0 +1,5 @@
+import QML
+
+Switch {
+ onLabel: qsTr("Power on")
+}
diff --git a/tests/auto/qml/qmllint/data/templateStringSubstitution.qml b/tests/auto/qml/qmllint/data/templateStringSubstitution.qml
new file mode 100644
index 0000000000..64d6e0158d
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/templateStringSubstitution.qml
@@ -0,0 +1,6 @@
+import QtQml
+
+QtObject {
+ property int i
+ property int j: `hallo ${i}`
+}
diff --git a/tests/auto/qml/qmllint/data/tooFewParams.qml b/tests/auto/qml/qmllint/data/tooFewParams.qml
new file mode 100644
index 0000000000..15e1bb0616
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/tooFewParams.qml
@@ -0,0 +1,5 @@
+import QtQml
+
+QtObject {
+ property var a: Qt.hsla(12)
+}
diff --git a/tests/auto/qml/qmllint/data/typePropertyAccess.qml b/tests/auto/qml/qmllint/data/typePropertyAccess.qml
new file mode 100644
index 0000000000..80913806f7
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/typePropertyAccess.qml
@@ -0,0 +1,6 @@
+import QtQml
+import QmlBench
+
+QtObject {
+ property real x: Locals.realProp
+}
diff --git a/tests/auto/qml/qmllint/data/unaryMinusToStringProperty.qml b/tests/auto/qml/qmllint/data/unaryMinusToStringProperty.qml
new file mode 100644
index 0000000000..c1c51fa796
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/unaryMinusToStringProperty.qml
@@ -0,0 +1,5 @@
+import QtQml
+
+QtObject {
+ property string i: -1
+}
diff --git a/tests/auto/qml/qmllint/data/unboundComponents.qml b/tests/auto/qml/qmllint/data/unboundComponents.qml
new file mode 100644
index 0000000000..f4ce8c6f5d
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/unboundComponents.qml
@@ -0,0 +1,22 @@
+pragma ComponentBehavior: Unbound
+import QtQml
+
+QtObject {
+ id: root
+ property string foo: "bar"
+ property Component c1: Component {
+ QtObject {
+ id: c1
+ objectName: root.foo
+ property int i: 12
+ property Component c2: Component {
+ QtObject {
+ objectName: root.foo + c1.i
+ }
+ }
+ property QtObject o: c2.createObject()
+ }
+ }
+
+ property QtObject o: c1.createObject()
+}
diff --git a/tests/auto/qml/qmllint/data/unexportedCppBase.qml b/tests/auto/qml/qmllint/data/unexportedCppBase.qml
new file mode 100644
index 0000000000..c8530fd865
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/unexportedCppBase.qml
@@ -0,0 +1,5 @@
+import QtQuick 2.0
+
+QtObject {
+ property QtObject i: Image {}
+}
diff --git a/tests/auto/qml/qmllint/data/unknownParentDefaultPropertyCheck.qml b/tests/auto/qml/qmllint/data/unknownParentDefaultPropertyCheck.qml
new file mode 100644
index 0000000000..45e738ceae
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/unknownParentDefaultPropertyCheck.qml
@@ -0,0 +1,6 @@
+import QtQuick
+
+Alien { // does -intentionally- not exist
+ Item {}
+ Item {}
+}
diff --git a/tests/auto/qml/qmllint/data/unknownTypeCustomParser.qml b/tests/auto/qml/qmllint/data/unknownTypeCustomParser.qml
new file mode 100644
index 0000000000..9dbb7a9835
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/unknownTypeCustomParser.qml
@@ -0,0 +1,7 @@
+import QtQuick
+
+ListModel {
+ property var x: TypeDoesNotExist {
+ property string s: DoesNotExistEither.value;
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/unknownTypeInRegister.qml b/tests/auto/qml/qmllint/data/unknownTypeInRegister.qml
new file mode 100644
index 0000000000..72902d292b
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/unknownTypeInRegister.qml
@@ -0,0 +1,7 @@
+import QtQuick
+
+ListModel {
+ function foo(index) {
+ move(index, 1, 1);
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/unresolvedArrayBinding.qml b/tests/auto/qml/qmllint/data/unresolvedArrayBinding.qml
new file mode 100644
index 0000000000..5f099f3a55
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/unresolvedArrayBinding.qml
@@ -0,0 +1,10 @@
+import QtQuick
+
+Item {
+ states : [
+ foo{},
+ bar {},
+ State {},
+ foo {}
+ ]
+} \ No newline at end of file
diff --git a/tests/auto/qml/qmllint/data/unresolvedAttachedType.qml b/tests/auto/qml/qmllint/data/unresolvedAttachedType.qml
new file mode 100644
index 0000000000..7786aff3d2
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/unresolvedAttachedType.qml
@@ -0,0 +1,5 @@
+import QtQuick 2.15
+
+Flickable {
+ UnresolvedAttachedType.property: QtObject {}
+}
diff --git a/tests/auto/qml/qmllint/data/unresolvedType.qml b/tests/auto/qml/qmllint/data/unresolvedType.qml
new file mode 100644
index 0000000000..63282bc262
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/unresolvedType.qml
@@ -0,0 +1,14 @@
+import QtQuick 2.0
+
+Item {
+ UnresolvedType {
+ unresolvedProperty: 5
+ Item {}
+ Item {}
+ }
+ Repeater {
+ model: 10
+ delegate: UnresolvedType {}
+ }
+ property UnresolvedType foo: Item {}
+}
diff --git a/tests/auto/qml/qmllint/data/untitled/components/Foo.qml b/tests/auto/qml/qmllint/data/untitled/components/Foo.qml
new file mode 100644
index 0000000000..10e5741900
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/untitled/components/Foo.qml
@@ -0,0 +1,5 @@
+import QtQuick
+
+Text {
+ text: "Here I am!"
+}
diff --git a/tests/auto/qml/qmllint/data/untitled/main.qml b/tests/auto/qml/qmllint/data/untitled/main.qml
new file mode 100644
index 0000000000..cf8980ab55
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/untitled/main.qml
@@ -0,0 +1,9 @@
+pragma Strict
+
+import QtQuick
+import 'qrc:/untitled/components' as C
+
+Window {
+ id: root
+ C.Foo {}
+}
diff --git a/tests/auto/qml/qmllint/data/untitled/qrcUrlImport.qrc b/tests/auto/qml/qmllint/data/untitled/qrcUrlImport.qrc
new file mode 100644
index 0000000000..0ad0d57fbb
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/untitled/qrcUrlImport.qrc
@@ -0,0 +1,6 @@
+<RCC>
+ <qresource prefix="/untitled/">
+ <file alias="main.qml">main.qml</file>
+ <file alias="components/Foo.qml">components/Foo.qml</file>
+ </qresource>
+</RCC>
diff --git a/tests/auto/qml/qmllint/data/unused_multi.qml b/tests/auto/qml/qmllint/data/unused_multi.qml
new file mode 100644
index 0000000000..f078eadf0c
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/unused_multi.qml
@@ -0,0 +1,7 @@
+// This is the one kind of unused import we currently do not warn about:
+// If two imports provide the same type, one of them could be considered unused.
+// We do not however warn here because there might be legitimate reasons why a user would want this.
+import QtQuick
+import QtQml
+
+QtObject {}
diff --git a/tests/auto/qml/qmllint/data/unused_prefix.qml b/tests/auto/qml/qmllint/data/unused_prefix.qml
new file mode 100644
index 0000000000..a54d74390a
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/unused_prefix.qml
@@ -0,0 +1,5 @@
+import QtQml as Qml // Unused due to being prefixed
+import QtQuick
+
+QtObject {
+}
diff --git a/tests/auto/qml/qmllint/data/unused_simple.qml b/tests/auto/qml/qmllint/data/unused_simple.qml
new file mode 100644
index 0000000000..c2a931f3ed
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/unused_simple.qml
@@ -0,0 +1,5 @@
+import QtTest // This import is not used.
+import QtQuick
+
+QtObject {
+}
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/data/unversionChangedSignalSansArguments.qml b/tests/auto/qml/qmllint/data/unversionChangedSignalSansArguments.qml
new file mode 100644
index 0000000000..c91713fa55
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/unversionChangedSignalSansArguments.qml
@@ -0,0 +1,5 @@
+import QtQuick 2.15
+
+Item {
+ onWidthChanged: () => {}
+}
diff --git a/tests/auto/qml/qmllint/data/useConstInvokable.qml b/tests/auto/qml/qmllint/data/useConstInvokable.qml
new file mode 100644
index 0000000000..4f89e89918
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/useConstInvokable.qml
@@ -0,0 +1,5 @@
+import Things
+
+ConstInvokable {
+ objectName: getObject().objectName
+}
diff --git a/tests/auto/qml/qmllint/data/used.qml b/tests/auto/qml/qmllint/data/used.qml
new file mode 100644
index 0000000000..f5c74b0352
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/used.qml
@@ -0,0 +1,17 @@
+import QtQml as Qml
+import QtQuick as Quick
+import QtQuick 2.0 as QuickLegacy
+import QtQuick
+import Things
+
+Item {
+ property var bar: Qml.QtObject {}
+ Item {
+ property var foo: Quick.Screen.pixelDensity
+ property var foo2: parent.QuickLegacy.Screen.pixelDensity
+ }
+ required property Something moo
+ property bool boolVar: false
+ property real realVar: 17.17
+ property double doubleVar: 18.18
+}
diff --git a/tests/auto/qml/qmllint/data/v4SequenceMethods.qml b/tests/auto/qml/qmllint/data/v4SequenceMethods.qml
new file mode 100644
index 0000000000..fb4b28b674
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/v4SequenceMethods.qml
@@ -0,0 +1,87 @@
+import QtQml
+
+QtObject {
+ property rect self: Qt.rect(9, 9, 9, 9)
+
+ required property real i
+ required property real j
+ required property real k
+
+ property rect r1: Qt.rect(1, 2, 3, 4)
+ property rect r2: Qt.rect(5, 6, 7, 8)
+ property rect r3: Qt.rect(9, 10, 11, 12)
+
+ property list<rect> v4Sequence: [r1, r2, r3]
+ property list<rect> v4SequenceSlice: v4Sequence.slice(i, j)
+ property int v4SequenceIndexOf: v4Sequence.indexOf(r2, i)
+ property int v4SequenceLastIndexOf: v4Sequence.lastIndexOf(r3, i)
+ property string v4SequenceToString: v4Sequence.toString()
+ property string v4SequenceToLocaleString: v4Sequence.toLocaleString()
+ property list<rect> v4SequenceConcat: v4Sequence.concat(v4Sequence)
+ property rect v4SequenceFind: v4Sequence.find(element => element.x === 1)
+ property int v4SequenceFindIndex: v4Sequence.findIndex(element => element === r2)
+ property bool v4SequenceIncludes: v4Sequence.includes(r3)
+ property string v4SequenceJoin: v4Sequence.join()
+
+ property bool entriesMatch: {
+ var iterator = v4Sequence.entries();
+ for (var [index, element] of v4Sequence.entries()) {
+ var v = iterator.next().value;
+ if (index !== v[0] || element !== v[1]) {
+ console.log(index, v[0], element, v[1]);
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ property bool keysMatch: {
+ var iterator = v4Sequence.keys();
+ for (var index of v4Sequence.keys()) {
+ var v = iterator.next().value;
+ if (index !== v) {
+ console.log(index, v);
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ property bool valuesMatch: {
+ var iterator = v4Sequence.values();
+ for (var obj of v4Sequence.values()) {
+ var v = iterator.next().value;
+ if (obj !== v) {
+ console.log(obj, v);
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ property bool v4SequenceEvery: v4Sequence.every((element) => element != null)
+ property bool v4SequenceSome: v4Sequence.some((element) => element.x === 1)
+
+ property list<int> v4SequenceMap: v4Sequence.map(((element) => element.x))
+ property list<rect> v4SequenceFilter: v4Sequence.filter((element) => element.x != 1)
+ property string v4SequenceReduceRight: v4Sequence.reduceRight((element, v) => v + '-' + element.x + 'v', "")
+ property string v4SequenceReduce: v4Sequence.reduce((element, v) => v + '-' + element.x + 'v', "")
+ property list<string> v4SequenceOwnPropertyNames: Object.getOwnPropertyNames(v4Sequence)
+
+ Component.onCompleted: {
+ v4Sequence.reverse();
+ v4Sequence.pop();
+ v4Sequence.push(self);
+ v4Sequence.shift();
+ v4Sequence.unshift(self);
+ v4Sequence.forEach((element) => { console.log("-" + element.x + "-") });
+ v4Sequence.sort();
+ v4Sequence.sort((a, b) => (a.x - b.x))
+ v4Sequence.copyWithin(i, j, k);
+ v4Sequence.fill(self, i, Math.min(j, 1024));
+ v4Sequence.splice(i, j, self, self, self);
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/validLiterals.qml b/tests/auto/qml/qmllint/data/validLiterals.qml
new file mode 100644
index 0000000000..55792eaae2
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/validLiterals.qml
@@ -0,0 +1,37 @@
+import QtQuick
+
+QtObject {
+ property string string1: "Hello"
+
+ property int int1: 3
+
+ property double double1: 1
+
+ property real real1: 5.3
+
+ property var var1: null
+ property var var2: 3
+
+ property Item item: null
+
+ property Gradient gradient: null
+
+ property bool b1: true
+ property bool b2: false
+ property bool b3
+ b3: true
+
+ property TextInput edit: TextInput { validator: RegularExpressionValidator { regularExpression: /.*/ } }
+
+ property url url1: "http://google.com"
+
+ property color color1: "red"
+
+ property date date1: "2021-08-13T14:16:21.435Z"
+
+ property point point1: ({ x: 1, y: 2 })
+
+ property size size1: ({ width: 50, height: 50 })
+
+ property rect rect1: ({ x: 10, y: 20, width: 30, height: 30 })
+}
diff --git a/tests/auto/qml/qmllint/data/valueSource.qml b/tests/auto/qml/qmllint/data/valueSource.qml
new file mode 100644
index 0000000000..3551dde74d
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/valueSource.qml
@@ -0,0 +1,8 @@
+import QtQuick 2.0
+
+Image {
+ transform: Rotation {
+ NumberAnimation on angle {
+ }
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/valueSourceBetween2interceptors.qml b/tests/auto/qml/qmllint/data/valueSourceBetween2interceptors.qml
new file mode 100644
index 0000000000..eaa24ef339
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/valueSourceBetween2interceptors.qml
@@ -0,0 +1,7 @@
+import QtQuick 2.0
+
+Item {
+ Behavior on x {}
+ SequentialAnimation on x {}
+ Behavior on x {}
+}
diff --git a/tests/auto/qml/qmllint/data/valueSource_Value.qml b/tests/auto/qml/qmllint/data/valueSource_Value.qml
new file mode 100644
index 0000000000..a2ca81b814
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/valueSource_Value.qml
@@ -0,0 +1,7 @@
+import QtQuick 2.0
+
+Item {
+ property QtObject obj: QtObject {}
+ NumberAnimation on obj {
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/valueSource_listValue.qml b/tests/auto/qml/qmllint/data/valueSource_listValue.qml
new file mode 100644
index 0000000000..5bf339e202
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/valueSource_listValue.qml
@@ -0,0 +1,7 @@
+import QtQuick 2.0
+
+Item {
+ property list<QtObject> objs: [ QtObject {} ]
+ NumberAnimation on objs { // Note: poor example but it should error anyway
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/valueTypesFromString.qml b/tests/auto/qml/qmllint/data/valueTypesFromString.qml
new file mode 100644
index 0000000000..fc013f858f
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/valueTypesFromString.qml
@@ -0,0 +1,7 @@
+import QtQuick
+
+Item {
+ property point p: "30,50"
+ property rect p3: "10, 20, 30x50"
+ property size p4: "30x50"
+}
diff --git a/tests/auto/qml/qmllint/data/varargs.qml b/tests/auto/qml/qmllint/data/varargs.qml
new file mode 100644
index 0000000000..a10bd23932
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/varargs.qml
@@ -0,0 +1,7 @@
+import QtQml
+import TestTypes
+
+MyComponent {
+ id: self
+ Component.onCompleted: createObject({a : 12}, self, 1, 2, 3)
+}
diff --git a/tests/auto/qml/qmllint/data/variantMapLookup.qml b/tests/auto/qml/qmllint/data/variantMapLookup.qml
new file mode 100644
index 0000000000..7f50879932
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/variantMapLookup.qml
@@ -0,0 +1,13 @@
+pragma Strict
+import TestTypes
+import QtQuick
+
+Item {
+ VariantMapLookupFoo {
+ id: moo
+ }
+ Component.onCompleted: {
+ moo.data.value = 5
+ moo.data["value"] = 6
+ }
+}
diff --git a/tests/auto/qml/qmllint/data/writeListProperty.qml b/tests/auto/qml/qmllint/data/writeListProperty.qml
new file mode 100644
index 0000000000..8015fdf51b
--- /dev/null
+++ b/tests/auto/qml/qmllint/data/writeListProperty.qml
@@ -0,0 +1,7 @@
+import QtQuick
+
+Item {
+ id: self
+ property Item a: Item { id: a }
+ Component.onCompleted: self.data = [ a ]
+}
diff --git a/tests/auto/qml/qmllint/lintplugin.cpp b/tests/auto/qml/qmllint/lintplugin.cpp
new file mode 100644
index 0000000000..65795c103c
--- /dev/null
+++ b/tests/auto/qml/qmllint/lintplugin.cpp
@@ -0,0 +1,131 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include "lintplugin.h"
+
+using namespace Qt::StringLiterals;
+
+static constexpr QQmlSA::LoggerWarningId plugin{ "testPlugin.test" };
+
+class ElementTest : public QQmlSA::ElementPass
+{
+public:
+ ElementTest(QQmlSA::PassManager *manager) : QQmlSA::ElementPass(manager)
+ {
+ m_rectangle = resolveType(u"QtQuick", u"Rectangle");
+ }
+
+ bool shouldRun(const QQmlSA::Element &element) override
+ {
+ return element.baseType() == m_rectangle;
+ }
+
+ void run(const QQmlSA::Element &element) override
+ {
+ auto property = element.property(u"radius"_s);
+ if (!property.isValid() || element.property(u"radius"_s).typeName() != u"qreal") {
+ emitWarning(u"Failed to verify radius property", plugin, element.sourceLocation());
+ return;
+ }
+
+ auto bindings = element.propertyBindings(u"radius"_s);
+ if (bindings.isEmpty() || bindings.constFirst().numberValue() != 5) {
+ emitWarning(u"Failed to verify radius property binding", plugin,
+ element.sourceLocation());
+ return;
+ }
+
+ emitWarning(u"ElementTest OK", plugin, element.sourceLocation());
+ }
+
+private:
+ QQmlSA::Element m_rectangle;
+};
+
+class PropertyTest : public QQmlSA::PropertyPass
+{
+public:
+ PropertyTest(QQmlSA::PassManager *manager) : QQmlSA::PropertyPass(manager) { }
+
+ void onBinding(const QQmlSA::Element &element, const QString &propertyName,
+ const QQmlSA::Binding &binding, const QQmlSA::Element &bindingScope,
+ const QQmlSA::Element &value) override
+ {
+ emitWarning(u"Saw binding on %1 property %2 with value %3 (and type %4) in scope %5"_s
+ .arg(element.baseTypeName(), propertyName,
+ value.isNull()
+ ? u"NULL"_s
+ : (value.name().isNull() ? value.baseTypeName()
+ : value.name()))
+ .arg(qToUnderlying(binding.bindingType()))
+ .arg(bindingScope.baseTypeName()),
+ plugin, bindingScope.sourceLocation());
+ }
+
+ void onRead(const QQmlSA::Element &element, const QString &propertyName,
+ const QQmlSA::Element &readScope, QQmlSA::SourceLocation location) override
+ {
+ emitWarning(u"Saw read on %1 property %2 in scope %3"_s.arg(
+ element.baseTypeName(), propertyName, readScope.baseTypeName()),
+ plugin, location);
+ }
+
+ void onWrite(const QQmlSA::Element &element, const QString &propertyName,
+ const QQmlSA::Element &value, const QQmlSA::Element &writeScope,
+ QQmlSA::SourceLocation location) override
+ {
+ emitWarning(u"Saw write on %1 property %2 with value %3 in scope %4"_s.arg(
+ element.baseTypeName(), propertyName,
+ (value.name().isNull() ? value.baseTypeName()
+ : value.name()),
+ writeScope.baseTypeName()),
+ plugin, location);
+ }
+};
+
+class HasImportedModuleTest : public QQmlSA::ElementPass
+{
+public:
+ HasImportedModuleTest(QQmlSA::PassManager *manager, QString message)
+ : QQmlSA::ElementPass(manager), m_message(message)
+ {
+ }
+
+ bool shouldRun(const QQmlSA::Element &element) override
+ {
+ Q_UNUSED(element)
+ return true;
+ }
+
+ void run(const QQmlSA::Element &element) override
+ {
+ Q_UNUSED(element)
+ emitWarning(m_message, plugin);
+ }
+
+private:
+ QString m_message;
+};
+
+void LintPlugin::registerPasses(QQmlSA::PassManager *manager, const QQmlSA::Element &rootElement)
+{
+ if (!rootElement.filePath().endsWith(u"_pluginTest.qml"))
+ return;
+
+ manager->registerElementPass(std::make_unique<ElementTest>(manager));
+ manager->registerPropertyPass(std::make_unique<PropertyTest>(manager), "QtQuick", "Text",
+ "text");
+ manager->registerPropertyPass(std::make_unique<PropertyTest>(manager), "", "", "x");
+ manager->registerPropertyPass(std::make_unique<PropertyTest>(manager), "QtQuick", "ListView");
+ if (manager->hasImportedModule("QtQuick.Controls")) {
+ if (manager->hasImportedModule("QtQuick")) {
+ if (manager->hasImportedModule("QtQuick.Window")) {
+ manager->registerElementPass(std::make_unique<HasImportedModuleTest>(
+ manager, "QtQuick.Controls, QtQuick and QtQuick.Window present"));
+ }
+ } else {
+ manager->registerElementPass(std::make_unique<HasImportedModuleTest>(
+ manager, "QtQuick.Controls and NO QtQuick present"));
+ }
+ }
+}
diff --git a/tests/auto/qml/qmllint/lintplugin.h b/tests/auto/qml/qmllint/lintplugin.h
new file mode 100644
index 0000000000..c121657456
--- /dev/null
+++ b/tests/auto/qml/qmllint/lintplugin.h
@@ -0,0 +1,21 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#ifndef LINTPLUGIN_H
+#define LINTPLUGIN_H
+
+#include <QtPlugin>
+#include <QtCore/qobject.h>
+#include <QtQmlCompiler/qqmlsa.h>
+
+class LintPlugin : public QObject, public QQmlSA::LintPlugin
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID QmlLintPluginInterface_iid FILE "testPlugin.json")
+ Q_INTERFACES(QQmlSA::LintPlugin)
+
+public:
+ void registerPasses(QQmlSA::PassManager *manager, const QQmlSA::Element &rootElement) override;
+};
+
+#endif // LINTPLUGIN_H
diff --git a/tests/auto/qml/qmllint/testPlugin.json b/tests/auto/qml/qmllint/testPlugin.json
new file mode 100644
index 0000000000..b6958fb753
--- /dev/null
+++ b/tests/auto/qml/qmllint/testPlugin.json
@@ -0,0 +1,14 @@
+{
+ "name": "testPlugin",
+ "author": "Qt",
+ "description": "A test plugin for tst_qmllint",
+ "version": "1.0",
+ "isInternal": true,
+ "loggingCategories": [
+ {
+ "name": "test",
+ "settingsName": "TestWarning",
+ "description": "A warning type used in tests"
+ }
+ ]
+}
diff --git a/tests/auto/qml/qmllint/tst_qmllint.cpp b/tests/auto/qml/qmllint/tst_qmllint.cpp
index 25776c5448..57cb7228d8 100644
--- a/tests/auto/qml/qmllint/tst_qmllint.cpp
+++ b/tests/auto/qml/qmllint/tst_qmllint.cpp
@@ -1,41 +1,53 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Sergio Martins <sergio.martins@kdab.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Sergio Martins <sergio.martins@kdab.com>
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtTest/QtTest>
#include <QProcess>
#include <QString>
+#include <QtQuickTestUtils/private/qmlutils_p.h>
+#include <QtQmlCompiler/private/qqmljslinter_p.h>
+#include <QtQmlCompiler/private/qqmlsa_p.h>
+#include <QtCore/qplugin.h>
-#include <util.h>
+Q_IMPORT_PLUGIN(LintPlugin)
+
+using namespace Qt::StringLiterals;
class TestQmllint: public QQmlDataTest
{
Q_OBJECT
+public:
+ TestQmllint();
+
+ struct Message
+ {
+ QString text = QString();
+ quint32 line = 0, column = 0;
+ QtMsgType severity = QtWarningMsg;
+ };
+
+ struct Result
+ {
+ enum Flag { ExitsNormally = 0x1, NoMessages = 0x2, AutoFixable = 0x4 };
+
+ Q_DECLARE_FLAGS(Flags, Flag)
+
+ static Result clean() { return Result { {}, {}, {}, { NoMessages, ExitsNormally } }; }
+
+ QList<Message> expectedMessages = {};
+ QList<Message> badMessages = {};
+ QList<Message> expectedReplacements = {};
+
+ Flags flags = {};
+ };
+
+ struct Environment : public QList<QPair<QString, QString>>
+ {
+ using QList<QPair<QString, QString>>::QList;
+ };
+
private Q_SLOTS:
void initTestCase() override;
@@ -48,6 +60,9 @@ private Q_SLOTS:
void dirtyQmlCode_data();
void dirtyQmlCode();
+ void compilerWarnings_data();
+ void compilerWarnings();
+
void testUnknownCausesFail();
void directoryPassedAsQmlTypesFile();
@@ -56,102 +71,255 @@ private Q_SLOTS:
void qmltypes_data();
void qmltypes();
+#ifdef QT_QMLJSROOTGEN_PRESENT
+ void verifyJsRoot();
+#endif
+
void autoqmltypes();
void resources();
+ void multiDirectory();
+
void requiredProperty();
+ void settingsFile();
+
+ void additionalImplicitImport();
+
+ void qrcUrlImport();
+
+ void incorrectImportFromHost_data();
+ void incorrectImportFromHost();
+
+ void attachedPropertyReuse();
+
+ void missingBuiltinsNoCrash();
+ void absolutePath();
+
+ void importMultipartUri();
+
+ void lintModule_data();
+ void lintModule();
+
+ void testLineEndings();
+ void valueTypesFromString();
+
+ void ignoreSettingsNotCommandLineOptions();
+
+ void environment_data();
+ void environment();
+
+#if QT_CONFIG(library)
+ void testPlugin();
+ void quickPlugin();
+#endif
private:
- QString runQmllint(const QString &fileToLint,
- std::function<void(QProcess &)> handleResult,
- const QStringList &extraArgs = QStringList());
+ enum DefaultImportOption { NoDefaultImports, UseDefaultImports };
+ enum ContainOption { StringNotContained, StringContained };
+ enum ReplacementOption {
+ NoReplacementSearch,
+ DoReplacementSearch,
+ };
+
+ enum LintType { LintFile, LintModule };
+
+ QString runQmllint(const QString &fileToLint, std::function<void(QProcess &)> handleResult,
+ const QStringList &extraArgs = QStringList(), bool ignoreSettings = true,
+ bool addImportDirs = true, bool absolutePath = true,
+ const Environment &env = {});
QString runQmllint(const QString &fileToLint, bool shouldSucceed,
- const QStringList &extraArgs = QStringList());
+ const QStringList &extraArgs = QStringList(), bool ignoreSettings = true,
+ bool addImportDirs = true, bool absolutePath = true,
+ const Environment &env = {});
+ void callQmllint(const QString &fileToLint, bool shouldSucceed, QJsonArray *warnings = nullptr,
+ QStringList importDirs = {}, QStringList qmltypesFiles = {},
+ QStringList resources = {},
+ DefaultImportOption defaultImports = UseDefaultImports,
+ QList<QQmlJS::LoggerCategory> *categories = nullptr, bool autoFixable = false,
+ LintType type = LintFile);
+
+ void searchWarnings(const QJsonArray &warnings, const QString &string,
+ QtMsgType type = QtWarningMsg, quint32 line = 0, quint32 column = 0,
+ ContainOption shouldContain = StringContained,
+ ReplacementOption searchReplacements = NoReplacementSearch);
+
+ template<typename ExpectedMessageFailureHandler, typename BadMessageFailureHandler>
+ void checkResult(const QJsonArray &warnings, const Result &result,
+ ExpectedMessageFailureHandler onExpectedMessageFailures,
+ BadMessageFailureHandler onBadMessageFailures);
+
+ void checkResult(const QJsonArray &warnings, const Result &result)
+ {
+ checkResult(
+ warnings, result, [] {}, [] {});
+ }
+
+ void runTest(const QString &testFile, const Result &result, QStringList importDirs = {},
+ QStringList qmltypesFiles = {}, QStringList resources = {},
+ DefaultImportOption defaultImports = UseDefaultImports,
+ QList<QQmlJS::LoggerCategory> *categories = nullptr);
QString m_qmllintPath;
+ QString m_qmljsrootgenPath;
+ QString m_qmltyperegistrarPath;
+
+ QStringList m_defaultImportPaths;
+ QQmlJSLinter m_linter;
};
+Q_DECLARE_METATYPE(TestQmllint::Result)
+
+TestQmllint::TestQmllint()
+ : QQmlDataTest(QT_QMLTEST_DATADIR),
+ m_defaultImportPaths({ QLibraryInfo::path(QLibraryInfo::QmlImportsPath), dataDirectory() }),
+ m_linter(m_defaultImportPaths)
+
+{
+}
+
void TestQmllint::initTestCase()
{
QQmlDataTest::initTestCase();
m_qmllintPath = QLibraryInfo::path(QLibraryInfo::BinariesPath) + QLatin1String("/qmllint");
+ m_qmljsrootgenPath = QLibraryInfo::path(QLibraryInfo::LibraryExecutablesPath)
+ + QLatin1String("/qmljsrootgen");
+ m_qmltyperegistrarPath = QLibraryInfo::path(QLibraryInfo::LibraryExecutablesPath)
+ + QLatin1String("/qmltyperegistrar");
#ifdef Q_OS_WIN
m_qmllintPath += QLatin1String(".exe");
+ m_qmljsrootgenPath += QLatin1String(".exe");
+ m_qmltyperegistrarPath += QLatin1String(".exe");
#endif
if (!QFileInfo(m_qmllintPath).exists()) {
QString message = QStringLiteral("qmllint executable not found (looked for %0)").arg(m_qmllintPath);
QFAIL(qPrintable(message));
}
+
+#ifdef QT_QMLJSROOTGEN_PRESENT
+ if (!QFileInfo(m_qmljsrootgenPath).exists()) {
+ QString message = QStringLiteral("qmljsrootgen executable not found (looked for %0)").arg(m_qmljsrootgenPath);
+ QFAIL(qPrintable(message));
+ }
+ if (!QFileInfo(m_qmltyperegistrarPath).exists()) {
+ QString message = QStringLiteral("qmltypesregistrar executable not found (looked for %0)").arg(m_qmltyperegistrarPath);
+ QFAIL(qPrintable(message));
+ }
+#endif
}
void TestQmllint::testUnqualified()
{
QFETCH(QString, filename);
- QFETCH(QString, warningMessage);
- QFETCH(int, warningLine);
- QFETCH(int, warningColumn);
+ QFETCH(Result, result);
- const QString output = runQmllint(filename, false);
- QVERIFY(output.contains(QString::asprintf("Warning: unqualified access at %s:%d:%d", testFile(filename).toUtf8().constData(), warningLine, warningColumn)));
- QVERIFY(output.contains(warningMessage));
+ runTest(filename, result);
}
void TestQmllint::testUnqualified_data()
{
QTest::addColumn<QString>("filename");
- QTest::addColumn<QString>("warningMessage");
- QTest::addColumn<int>("warningLine");
- QTest::addColumn<int>("warningColumn");
+ QTest::addColumn<Result>("result");
- // check for false positive due to and warning about with statement
- QTest::newRow("WithStatement") << QStringLiteral("WithStatement.qml") << QStringLiteral("with statements are strongly discouraged") << 10 << 25;
// id from nowhere (as with setContextProperty)
- QTest::newRow("IdFromOuterSpaceDirect") << QStringLiteral("IdFromOuterSpace.qml") << "alien.x" << 4 << 8;
- QTest::newRow("IdFromOuterSpaceAccess") << QStringLiteral("IdFromOuterSpace.qml") << "console.log(alien)" << 7 << 21;
+ QTest::newRow("IdFromOuterSpace")
+ << QStringLiteral("IdFromOuterSpace.qml")
+ << Result { { Message { QStringLiteral("Unqualified access"), 4, 8 },
+ Message { QStringLiteral("Unqualified access"), 7, 21 } } };
// access property of root object
- QTest::newRow("FromRootDirect") << QStringLiteral("FromRoot.qml") << QStringLiteral("x: root.unqualified") << 9 << 16; // new property
- QTest::newRow("FromRootAccess") << QStringLiteral("FromRoot.qml") << QStringLiteral("property int check: root.x") << 13 << 33; // builtin property
+ QTest::newRow("FromRootDirect")
+ << QStringLiteral("FromRoot.qml")
+ << Result {
+ {
+ Message { QStringLiteral("Unqualified access"), 9, 16 }, // new property
+ Message { QStringLiteral("Unqualified access"), 13,
+ 33 } // builtin property
+ },
+ {},
+ { { Message { u"root."_s, 9, 16 } }, { Message { u"root."_s, 13, 33 } } }
+ };
// access injected name from signal
- QTest::newRow("SignalHandler1") << QStringLiteral("SignalHandler.qml") << QStringLiteral("onDoubleClicked: function(mouse) {...") << 5 << 21;
- QTest::newRow("SignalHandler2") << QStringLiteral("SignalHandler.qml") << QStringLiteral("onPositionChanged: function(mouse) {...") << 10 << 21;
- QTest::newRow("SignalHandlerShort1") << QStringLiteral("SignalHandler.qml") << QStringLiteral("onClicked: (mouse) => {...") << 8 << 29;
- QTest::newRow("SignalHandlerShort2") << QStringLiteral("SignalHandler.qml") << QStringLiteral("onPressAndHold: (mouse) => {...") << 12 << 34;
+ QTest::newRow("SignalHandler")
+ << QStringLiteral("SignalHandler.qml")
+ << Result { {
+ Message { QStringLiteral("Unqualified access"), 5, 21 },
+ Message { QStringLiteral("Unqualified access"), 10, 21 },
+ Message { QStringLiteral("Unqualified access"), 8, 29 },
+ Message { QStringLiteral("Unqualified access"), 12, 34 },
+ },
+ {},
+ {
+ Message { QStringLiteral("function(mouse)"), 4, 22 },
+ Message { QStringLiteral("function(mouse)"), 9, 24 },
+ Message { QStringLiteral("(mouse) => "), 8, 16 },
+ Message { QStringLiteral("(mouse) => "), 12, 21 },
+ } };
// access catch identifier outside catch block
- QTest::newRow("CatchStatement") << QStringLiteral("CatchStatement.qml") << QStringLiteral("err") << 6 << 21;
-
- QTest::newRow("NonSpuriousParent") << QStringLiteral("nonSpuriousParentWarning.qml") << QStringLiteral("property int x: <id>.parent.x") << 6 << 25;
+ QTest::newRow("CatchStatement")
+ << QStringLiteral("CatchStatement.qml")
+ << Result { { Message { QStringLiteral("Unqualified access"), 6, 21 } } };
+ QTest::newRow("NonSpuriousParent")
+ << QStringLiteral("nonSpuriousParentWarning.qml")
+ << Result { {
+ Message { QStringLiteral("Unqualified access"), 6, 25 },
+ },
+ {},
+ { { Message { u"<id>."_s, 6, 25 } } } };
QTest::newRow("crashConnections")
- << QStringLiteral("crashConnections.qml")
- << QStringLiteral("target: FirstRunDialog") << 4 << 13;
+ << QStringLiteral("crashConnections.qml")
+ << Result { { Message { QStringLiteral("Unqualified access"), 4, 13 } } };
+
+ QTest::newRow("delegateContextProperties")
+ << QStringLiteral("delegateContextProperties.qml")
+ << Result { { Message { QStringLiteral("Unqualified access"), 6, 14 },
+ Message { QStringLiteral("Unqualified access"), 7, 15 },
+ Message { QStringLiteral("model is implicitly injected into this "
+ "delegate. Add a required property instead.") },
+ Message {
+ QStringLiteral("index is implicitly injected into this delegate. "
+ "Add a required property instead.") } } };
+ QTest::newRow("storeSloppy")
+ << QStringLiteral("UnqualifiedInStoreSloppy.qml")
+ << Result{ { Message{ QStringLiteral("Unqualified access"), 9, 26} } };
+ QTest::newRow("storeStrict")
+ << QStringLiteral("UnqualifiedInStoreStrict.qml")
+ << Result{ { Message{ QStringLiteral("Unqualified access"), 9, 52} } };
}
void TestQmllint::testUnknownCausesFail()
{
- const QString unknownNotFound = runQmllint("unknownElement.qml", false);
- QVERIFY(unknownNotFound.contains(
- QStringLiteral("Warning: Unknown was not found. Did you add all import paths?")));
+ runTest("unknownElement.qml",
+ Result { { Message {
+ QStringLiteral("Unknown was not found. Did you add all import paths?"), 4, 5,
+ QtWarningMsg } } });
+ runTest("TypeWithUnknownPropertyType.qml",
+ Result { { Message {
+ QStringLiteral("Something was not found. Did you add all import paths?"), 4, 5,
+ QtWarningMsg } } });
}
void TestQmllint::directoryPassedAsQmlTypesFile()
{
- const QStringList iArg = QStringList() << QStringLiteral("-i") << dataDirectory();
- const QString errorMessages = runQmllint("unknownElement.qml", false, iArg);
- const QString expectedError = QStringLiteral("Warning: QML types file cannot be a directory: ") + dataDirectory();
- QVERIFY2(errorMessages.contains(expectedError), qPrintable(QString::fromLatin1(
- "Expected error to contain \"%1\", but it didn't: %2").arg(expectedError, errorMessages)));
+ runTest("unknownElement.qml",
+ Result { { Message { QStringLiteral("QML types file cannot be a directory: ")
+ + dataDirectory() } } },
+ {}, { dataDirectory() });
}
void TestQmllint::oldQmltypes()
{
- const QString errors = runQmllint("oldQmltypes.qml", true);
- QVERIFY(errors.contains(QStringLiteral("Warning: typeinfo not declared in qmldir file")));
- QVERIFY(!errors.contains(QStringLiteral("Warning: QQuickItem was not found. Did you add all import paths?")));
- QVERIFY(errors.contains(QStringLiteral("Warning: Found deprecated dependency specifications")));
-
- // Checking for both lines separately so that we don't have to mess with the line endings.b
- QVERIFY(errors.contains(QStringLiteral("Meta object revision and export version differ, ignoring the revision.")));
- QVERIFY(errors.contains(QStringLiteral("Revision 0 corresponds to version 0.0; it should be 1.0.")));
+ runTest("oldQmltypes.qml",
+ Result { {
+ Message { QStringLiteral("typeinfo not declared in qmldir file") },
+ Message {
+ QStringLiteral("Found deprecated dependency specifications") },
+ Message { QStringLiteral(
+ "Meta object revision and export version differ.") },
+ Message { QStringLiteral(
+ "Revision 0 corresponds to version 0.0; it should be 1.0.") },
+ },
+ { Message { QStringLiteral(
+ "QQuickItem was not found. Did you add all import paths?") } } });
}
void TestQmllint::qmltypes_data()
@@ -162,14 +330,80 @@ void TestQmllint::qmltypes_data()
QDirIterator it(importsPath, { "*.qmltypes" },
QDir::Files, QDirIterator::Subdirectories);
while (it.hasNext())
- QTest::addRow("%s", qPrintable(it.next().mid(importsPath.length()))) << it.filePath();
+ QTest::addRow("%s", qPrintable(it.next().mid(importsPath.size()))) << it.filePath();
}
void TestQmllint::qmltypes()
{
QFETCH(QString, file);
- runQmllint(file, true);
+ // pass the warnings in, so that callQmllint() would show errors if any
+ QJsonArray warnings;
+ callQmllint(file, true, &warnings);
+}
+
+#ifdef QT_QMLJSROOTGEN_PRESENT
+void TestQmllint::verifyJsRoot()
+{
+ QProcess process;
+
+ const QString importsPath = QLibraryInfo::path(QLibraryInfo::QmlImportsPath);
+ QDirIterator it(importsPath, { "jsroot.qmltypes" },
+ QDir::Files, QDirIterator::Subdirectories);
+
+ QVERIFY(it.hasNext());
+
+ QString currentJsRootPath = it.next();
+
+ QTemporaryDir dir;
+
+ QProcess jsrootProcess;
+ connect(&jsrootProcess, &QProcess::errorOccurred, [&](QProcess::ProcessError error) {
+ qWarning() << error << jsrootProcess.errorString();
+ });
+ jsrootProcess.setWorkingDirectory(dir.path());
+ jsrootProcess.start(m_qmljsrootgenPath, {"jsroot.json"});
+
+ jsrootProcess.waitForFinished();
+
+ QCOMPARE(jsrootProcess.exitStatus(), QProcess::NormalExit);
+ QCOMPARE(jsrootProcess.exitCode(), 0);
+
+
+ QProcess typeregistrarProcess;
+ typeregistrarProcess.setWorkingDirectory(dir.path());
+ typeregistrarProcess.start(m_qmltyperegistrarPath, {"jsroot.json", "--generate-qmltypes", "jsroot.qmltypes"});
+
+ typeregistrarProcess.waitForFinished();
+
+ QCOMPARE(typeregistrarProcess.exitStatus(), QProcess::NormalExit);
+ QCOMPARE(typeregistrarProcess.exitCode(), 0);
+
+ QString currentJsRootContent, generatedJsRootContent;
+
+ QFile currentJsRoot(currentJsRootPath);
+ QVERIFY(currentJsRoot.open(QFile::ReadOnly | QIODevice::Text));
+ currentJsRootContent = QString::fromUtf8(currentJsRoot.readAll());
+ currentJsRoot.close();
+
+ QFile generatedJsRoot(dir.path() + QDir::separator() + "jsroot.qmltypes");
+ QVERIFY(generatedJsRoot.open(QFile::ReadOnly | QIODevice::Text));
+ generatedJsRootContent = QString::fromUtf8(generatedJsRoot.readAll());
+ generatedJsRoot.close();
+
+ // If any of the following asserts fail you need to update jsroot.qmltypes using the following commands:
+ //
+ // qmljsrootgen jsroot.json
+ // qmltyperegistrar jsroot.json --generate-qmltypes src/imports/builtins/jsroot.qmltypes
+ QStringList currentLines = currentJsRootContent.split(QLatin1Char('\n'));
+ QStringList generatedLines = generatedJsRootContent.split(QLatin1Char('\n'));
+
+ QCOMPARE(currentLines.size(), generatedLines.size());
+
+ for (qsizetype i = 0; i < currentLines.size(); i++) {
+ QCOMPARE(currentLines[i], generatedLines[i]);
+ }
}
+#endif
void TestQmllint::autoqmltypes()
{
@@ -180,176 +414,785 @@ void TestQmllint::autoqmltypes()
process.waitForFinished();
QCOMPARE(process.exitStatus(), QProcess::NormalExit);
- QCOMPARE(process.exitCode(), 0);
+ QVERIFY(process.exitCode() != 0);
- QVERIFY(process.readAllStandardError().isEmpty());
+ QVERIFY(process.readAllStandardError()
+ .contains("is not a qmldir file. Assuming qmltypes"));
QVERIFY(process.readAllStandardOutput().isEmpty());
+
+ {
+ QProcess bare;
+ bare.setWorkingDirectory(testFile("autoqmltypes"));
+ bare.start(m_qmllintPath, { QStringLiteral("--bare"), QStringLiteral("test.qml") });
+ bare.waitForFinished();
+
+ const QByteArray errors = bare.readAllStandardError();
+ QVERIFY(!errors.contains("is not a qmldir file. Assuming qmltypes"));
+ QVERIFY(errors.contains("Failed to import TestTest."));
+ QVERIFY(bare.readAllStandardOutput().isEmpty());
+
+ QCOMPARE(bare.exitStatus(), QProcess::NormalExit);
+ QVERIFY(bare.exitCode() != 0);
+ }
}
void TestQmllint::resources()
{
- runQmllint(testFile("resource.qml"), true,
- {QStringLiteral("--resource"), testFile("resource.qrc")});
- runQmllint(testFile("badResource.qml"), false,
- {QStringLiteral("--resource"), testFile("resource.qrc")});
- runQmllint(testFile("resource.qml"), false, {});
- runQmllint(testFile("badResource.qml"), true, {});
+ {
+ // We need to clear the import cache before we add a qrc file with different
+ // contents for the same paths.
+ const auto guard = qScopeGuard([this]() { m_linter.clearCache(); });
+
+ callQmllint(testFile("resource.qml"), true, nullptr, {}, {}, { testFile("resource.qrc") });
+ callQmllint(testFile("badResource.qml"), false, nullptr, {}, {}, { testFile("resource.qrc") });
+ }
+
+
+ callQmllint(testFile("resource.qml"), false);
+ callQmllint(testFile("badResource.qml"), true);
+
+ {
+ const auto guard = qScopeGuard([this]() { m_linter.clearCache(); });
+ callQmllint(testFile("T/b.qml"), true, nullptr, {}, {}, { testFile("T/a.qrc") });
+ }
+
+ {
+ const auto guard = qScopeGuard([this]() { m_linter.clearCache(); });
+ callQmllint(testFile("relPathQrc/Foo/Thing.qml"), true, nullptr, {}, {},
+ { testFile("relPathQrc/resources.qrc") });
+ }
+}
+
+void TestQmllint::multiDirectory()
+{
+ callQmllint(
+ testFile("MultiDirectory/qml/Inner.qml"), true, nullptr,
+ {}, {}, { testFile("MultiDirectory/multi.qrc") });
+
+ callQmllint(
+ testFile("MultiDirectory/qml/pages/Page.qml"), true, nullptr,
+ {}, {}, { testFile("MultiDirectory/multi.qrc") });
}
void TestQmllint::dirtyQmlCode_data()
{
QTest::addColumn<QString>("filename");
- QTest::addColumn<QString>("warningMessage");
- QTest::addColumn<QString>("notContained");
+ QTest::addColumn<Result>("result");
QTest::newRow("Invalid_syntax_QML")
<< QStringLiteral("failure1.qml")
- << QStringLiteral("%1:4 : Expected token `:'")
- << QString();
- QTest::newRow("Invalid_syntax_JS")
- << QStringLiteral("failure1.js")
- << QStringLiteral("%1:4 : Expected token `;'")
- << QString();
+ << Result { { Message { QStringLiteral("Expected token `:'"), 4, 8, QtCriticalMsg } } };
+ QTest::newRow("Invalid_syntax_JS") << QStringLiteral("failure1.js")
+ << Result { { Message { QStringLiteral("Expected token `;'"),
+ 4, 12, QtCriticalMsg } } };
QTest::newRow("AutomatchedSignalHandler")
<< QStringLiteral("AutomatchedSignalHandler.qml")
- << QString("Warning: unqualified access at %1:12:36")
- << QStringLiteral("no matching signal found");
+ << Result { { Message { QStringLiteral("Unqualified access"), 12, 36 } } };
+ QTest::newRow("AutomatchedSignalHandler2")
+ << QStringLiteral("AutomatchedSignalHandler.qml")
+ << Result { { Message {
+ QStringLiteral("Implicitly defining onClicked as signal handler"), 0, 0,
+ QtInfoMsg } } };
QTest::newRow("MemberNotFound")
<< QStringLiteral("memberNotFound.qml")
- << QString("Warning: Property \"foo\" not found on type \"QtObject\" at %1:6:31")
- << QString();
+ << Result { { Message {
+ QStringLiteral("Member \"foo\" not found on type \"QtObject\""), 6,
+ 31 } } };
QTest::newRow("UnknownJavascriptMethd")
<< QStringLiteral("unknownJavascriptMethod.qml")
- << QString("Warning: Property \"foo2\" not found on type \"Methods\" at %1:5:25")
- << QString();
+ << Result { { Message {
+ QStringLiteral("Member \"foo2\" not found on type \"Methods\""), 5,
+ 25 } } };
QTest::newRow("badAlias")
<< QStringLiteral("badAlias.qml")
- << QString("Warning: unqualified access at %1:4:27")
- << QString();
- QTest::newRow("badAliasProperty")
+ << Result { { Message { QStringLiteral("Cannot resolve alias \"wrong\""), 3, 1 } } };
+ QTest::newRow("badAliasProperty1")
<< QStringLiteral("badAliasProperty.qml")
- << QString("Warning: Property \"nowhere\" not found on type \"QtObject\" at %1:5:32")
- << QString();
+ << Result { { Message { QStringLiteral("Cannot resolve alias \"wrong\""), 3, 1 } } };
+ QTest::newRow("badAliasExpression")
+ << QStringLiteral("badAliasExpression.qml")
+ << Result { { Message {
+ QStringLiteral("Invalid alias expression. Only IDs and field member "
+ "expressions can be aliased"),
+ 5, 26 } } };
+ QTest::newRow("badAliasNotAnExpression")
+ << QStringLiteral("badAliasNotAnExpression.qml")
+ << Result { { Message {
+ QStringLiteral("Invalid alias expression. Only IDs and field member "
+ "expressions can be aliased"),
+ 4, 30 } } };
+ QTest::newRow("aliasCycle1") << QStringLiteral("aliasCycle.qml")
+ << Result { { Message {
+ QStringLiteral("Alias \"b\" is part of an alias cycle"),
+ 3, 1 } } };
+ QTest::newRow("aliasCycle2") << QStringLiteral("aliasCycle.qml")
+ << Result { { Message {
+ QStringLiteral("Alias \"a\" is part of an alias cycle"),
+ 3, 1 } } };
+ QTest::newRow("invalidAliasTarget1") << QStringLiteral("invalidAliasTarget.qml")
+ << Result { { Message {
+ QStringLiteral("Invalid alias expression – an initalizer is needed."),
+ 6, 18 } } };
+ QTest::newRow("invalidAliasTarget2") << QStringLiteral("invalidAliasTarget.qml")
+ << Result { { Message {
+ QStringLiteral("Invalid alias expression. Only IDs and field member expressions can be aliased"),
+ 7, 30 } } };
+ QTest::newRow("invalidAliasTarget3") << QStringLiteral("invalidAliasTarget.qml")
+ << Result { { Message {
+ QStringLiteral("Invalid alias expression. Only IDs and field member expressions can be aliased"),
+ 9, 34 } } };
QTest::newRow("badParent")
<< QStringLiteral("badParent.qml")
- << QString("Warning: Property \"rrr\" not found on type \"Item\" at %1:5:34")
- << QString();
+ << Result { { Message { QStringLiteral("Member \"rrr\" not found on type \"Item\""),
+ 5, 34 } } };
QTest::newRow("parentIsComponent")
<< QStringLiteral("parentIsComponent.qml")
- << QString("Warning: Property \"progress\" not found on type \"QQuickItem\" at %1:7:39")
- << QString();
+ << Result { { Message {
+ QStringLiteral("Member \"progress\" not found on type \"QQuickItem\""), 7,
+ 39 } } };
QTest::newRow("badTypeAssertion")
<< QStringLiteral("badTypeAssertion.qml")
- << QString("Warning: Property \"rrr\" not found on type \"Item\" at %1:5:39")
- << QString();
+ << Result { { Message {
+ QStringLiteral("Member \"rrr\" not found on type \"QQuickItem\""), 5,
+ 39 } } };
QTest::newRow("incompleteQmltypes")
<< QStringLiteral("incompleteQmltypes.qml")
- << QString("Warning: Type \"QPalette\" of base \"palette\" not found when accessing member \"weDontKnowIt\" at %1:5:34")
- << QString();
- QTest::newRow("inheritanceCylce")
+ << Result { { Message {
+ QStringLiteral("Type \"QPalette\" of property \"palette\" not found"), 5,
+ 26 } } };
+ QTest::newRow("incompleteQmltypes2")
+ << QStringLiteral("incompleteQmltypes2.qml")
+ << Result { { Message { QStringLiteral("Member \"weDontKnowIt\" "
+ "not found on type \"CustomPalette\""),
+ 5, 35 } } };
+ QTest::newRow("incompleteQmltypes3")
+ << QStringLiteral("incompleteQmltypes3.qml")
+ << Result { { Message {
+ QStringLiteral("Type \"QPalette\" of property \"palette\" not found"), 5,
+ 21 } } };
+ QTest::newRow("inheritanceCycle")
<< QStringLiteral("Cycle1.qml")
- << QString("Warning: Cycle2 is part of an inheritance cycle: Cycle2 -> Cycle3 -> Cycle1 -> Cycle2")
- << QString();
+ << Result { { Message {
+ QStringLiteral("Cycle1 is part of an inheritance cycle: Cycle2 -> Cycle3 "
+ "-> Cycle1 -> Cycle2"),
+ 2, 1 } } };
QTest::newRow("badQmldirImportAndDepend")
<< QStringLiteral("qmldirImportAndDepend/bad.qml")
- << QString("Warning: Item was not found. Did you add all import paths?")
- << QString();
+ << Result { { Message {
+ QStringLiteral("Item was not found. Did you add all import paths?"), 3,
+ 1 } } };
QTest::newRow("javascriptMethodsInModule")
<< QStringLiteral("javascriptMethodsInModuleBad.qml")
- << QString("Warning: Property \"unknownFunc\" not found on type \"Foo\"")
- << QString();
+ << Result { { Message {
+ QStringLiteral("Member \"unknownFunc\" not found on type \"Foo\""), 5,
+ 21 } } };
QTest::newRow("badEnumFromQtQml")
<< QStringLiteral("badEnumFromQtQml.qml")
- << QString("Warning: Property \"Linear123\" not found on type \"QQmlEasingEnums\"")
- << QString();
+ << Result { { Message { QStringLiteral("Member \"Linear123\" not "
+ "found on type \"QQmlEasingEnums\""),
+ 4, 30 } } };
QTest::newRow("anchors3")
<< QStringLiteral("anchors3.qml")
- << QString()
- << QString();
- QTest::newRow("nanchors1")
- << QStringLiteral("nanchors1.qml")
- << QString()
- << QString();
- QTest::newRow("nanchors2")
- << QStringLiteral("nanchors2.qml")
- << QString("unknown grouped property scope nanchors.")
- << QString();
- QTest::newRow("nanchors3")
- << QStringLiteral("nanchors3.qml")
- << QString("unknown grouped property scope nanchors.")
- << QString();
+ << Result { { Message { QStringLiteral(
+ "Cannot assign binding of type QQuickItem to QQuickAnchorLine") } } };
+ QTest::newRow("nanchors1") << QStringLiteral("nanchors1.qml")
+ << Result { { Message { QStringLiteral(
+ "unknown grouped property scope nanchors.") } } };
+ QTest::newRow("nanchors2") << QStringLiteral("nanchors2.qml")
+ << Result { { Message { QStringLiteral(
+ "unknown grouped property scope nanchors.") } } };
+ QTest::newRow("nanchors3") << QStringLiteral("nanchors3.qml")
+ << Result { { Message { QStringLiteral(
+ "unknown grouped property scope nanchors.") } } };
QTest::newRow("badAliasObject")
<< QStringLiteral("badAliasObject.qml")
- << QString("Warning: Property \"wrongwrongwrong\" not found on type \"QtObject\"")
- << QString();
- QTest::newRow("badScript")
- << QStringLiteral("badScript.qml")
- << QString("Warning: Property \"stuff\" not found on type \"Empty\"")
- << QString();
+ << Result { { Message { QStringLiteral("Member \"wrongwrongwrong\" not "
+ "found on type \"QtObject\""),
+ 8, 40 } } };
+ QTest::newRow("badScript") << QStringLiteral("badScript.qml")
+ << Result { { Message {
+ QStringLiteral(
+ "Member \"stuff\" not found on type \"Empty\""),
+ 5, 21 } } };
+ QTest::newRow("badScriptOnAttachedProperty")
+ << QStringLiteral("badScript.attached.qml")
+ << Result { { Message { QStringLiteral("Unqualified access"), 3, 26 } } };
QTest::newRow("brokenNamespace")
<< QStringLiteral("brokenNamespace.qml")
- << QString("Warning: type not found in namespace at %1:4:17")
- << QString();
- // TODO: This fails but currently for the wrong reasons, make sure to add a warning message requirement
- // once it does fail properly in order to avoid regressions.
+ << Result { { Message { QStringLiteral("Type not found in namespace"), 4, 19 } } };
QTest::newRow("segFault (bad)")
<< QStringLiteral("SegFault.bad.qml")
- << QString()
- << QString();
+ << Result { { Message { QStringLiteral(
+ "Member \"foobar\" not found on type \"QQuickScreenAttached\"") } } };
QTest::newRow("VariableUsedBeforeDeclaration")
<< QStringLiteral("useBeforeDeclaration.qml")
- << QStringLiteral("Variable \"argq\" is used before its declaration at 5:9. "
- "The declaration is at 6:13.")
- << QString();
+ << Result { { Message {
+ QStringLiteral("Variable \"argq\" is used here before its declaration. "
+ "The declaration is at 6:13."),
+ 5, 9 } } };
QTest::newRow("SignalParameterMismatch")
<< QStringLiteral("namedSignalParameters.qml")
- << QStringLiteral("Parameter 1 to signal handler for \"onSig\" is called \"argarg\". "
- "The signal has a parameter of the same name in position 2.")
- << QStringLiteral("onSig2");
+ << Result { { Message { QStringLiteral(
+ "Parameter 1 to signal handler for \"onSig\" is called \"argarg\". "
+ "The signal has a parameter of the same name in position 2.") } },
+ { Message { QStringLiteral("onSig2") } } };
QTest::newRow("TooManySignalParameters")
<< QStringLiteral("tooManySignalParameters.qml")
- << QStringLiteral("Signal handler for \"onSig\" has more formal parameters "
- "than the signal it handles.")
- << QString();
- QTest::newRow("OnAssignment")
- << QStringLiteral("onAssignment.qml")
- << QStringLiteral("Property \"loops\" not found on type \"bool\"")
- << QString();
- QTest::newRow("BadAttached")
- << QStringLiteral("badAttached.qml")
- << QStringLiteral("unknown attached property scope WrongAttached.")
- << QString();
- QTest::newRow("BadBinding")
- << QStringLiteral("badBinding.qml")
- << QStringLiteral("Binding assigned to \"doesNotExist\", but no property "
- "\"doesNotExist\" exists in the current element.")
- << QString();
+ << Result { { Message {
+ QStringLiteral("Signal handler for \"onSig\" has more formal parameters "
+ "than the signal it handles.") } } };
+ QTest::newRow("OnAssignment") << QStringLiteral("onAssignment.qml")
+ << Result { { Message { QStringLiteral(
+ "Member \"loops\" not found on type \"bool\"") } } };
+ QTest::newRow("BadAttached") << QStringLiteral("badAttached.qml")
+ << Result { { Message { QStringLiteral(
+ "unknown attached property scope WrongAttached.") } } };
+ QTest::newRow("BadBinding") << QStringLiteral("badBinding.qml")
+ << Result { { Message { QStringLiteral(
+ "Binding assigned to \"doesNotExist\", but no property "
+ "\"doesNotExist\" exists in the current element.") } } };
+ QTest::newRow("bad template literal (simple)")
+ << QStringLiteral("badTemplateStringSimple.qml")
+ << Result { { Message {
+ QStringLiteral("Cannot assign literal of type string to int") } } };
+ QTest::newRow("bad constant number to string")
+ << QStringLiteral("numberToStringProperty.qml")
+ << Result { { Message { QStringLiteral(
+ "Cannot assign literal of type double to QString") } } };
+ QTest::newRow("bad unary minus to string")
+ << QStringLiteral("unaryMinusToStringProperty.qml")
+ << Result { { Message { QStringLiteral(
+ "Cannot assign literal of type double to QString") } } };
+ QTest::newRow("bad tranlsation binding (qsTr)") << QStringLiteral("bad_qsTr.qml") << Result {};
+ QTest::newRow("bad string binding (QT_TR_NOOP)")
+ << QStringLiteral("bad_QT_TR_NOOP.qml")
+ << Result { { Message {
+ QStringLiteral("Cannot assign literal of type string to int") } } };
+ QTest::newRow("BadScriptBindingOnGroup")
+ << QStringLiteral("badScriptBinding.group.qml")
+ << Result { { Message {
+ QStringLiteral("Binding assigned to \"bogusProperty\", but no "
+ "property \"bogusProperty\" exists in the current element."),
+ 3, 10 } } };
+ QTest::newRow("BadScriptBindingOnAttachedType")
+ << QStringLiteral("badScriptBinding.attached.qml")
+ << Result { { Message {
+ QStringLiteral("Binding assigned to \"bogusProperty\", but no "
+ "property \"bogusProperty\" exists in the current element."),
+ 5, 12 } } };
+ QTest::newRow("BadScriptBindingOnAttachedSignalHandler")
+ << QStringLiteral("badScriptBinding.attachedSignalHandler.qml")
+ << Result { { Message {
+ QStringLiteral("no matching signal found for handler \"onBogusSignal\""), 3,
+ 10 } } };
QTest::newRow("BadPropertyType")
<< QStringLiteral("badPropertyType.qml")
- << QStringLiteral("No type found for property \"bad\". This may be due to a missing "
- "import statement or incomplete qmltypes files.")
- << QString();
+ << Result { { Message { QStringLiteral(
+ "No type found for property \"bad\". This may be due to a missing "
+ "import statement or incomplete qmltypes files.") } } };
+ QTest::newRow("Deprecation (Property, with reason)")
+ << QStringLiteral("deprecatedPropertyReason.qml")
+ << Result { { Message {
+ QStringLiteral("Property \"deprecated\" is deprecated (Reason: Test)") } } };
+ QTest::newRow("Deprecation (Property, no reason)")
+ << QStringLiteral("deprecatedProperty.qml")
+ << Result { { Message { QStringLiteral("Property \"deprecated\" is deprecated") } } };
+ QTest::newRow("Deprecation (Property binding, with reason)")
+ << QStringLiteral("deprecatedPropertyBindingReason.qml")
+ << Result { { Message { QStringLiteral(
+ "Binding on deprecated property \"deprecatedReason\" (Reason: Test)") } } };
+ QTest::newRow("Deprecation (Property binding, no reason)")
+ << QStringLiteral("deprecatedPropertyBinding.qml")
+ << Result { { Message {
+ QStringLiteral("Binding on deprecated property \"deprecated\"") } } };
+ QTest::newRow("Deprecation (Type, with reason)")
+ << QStringLiteral("deprecatedTypeReason.qml")
+ << Result { { Message { QStringLiteral(
+ "Type \"TypeDeprecatedReason\" is deprecated (Reason: Test)") } } };
+ QTest::newRow("Deprecation (Type, no reason)")
+ << QStringLiteral("deprecatedType.qml")
+ << Result { { Message { QStringLiteral("Type \"TypeDeprecated\" is deprecated") } } };
+ QTest::newRow("MissingDefaultProperty")
+ << QStringLiteral("defaultPropertyWithoutKeyword.qml")
+ << Result { { Message {
+ QStringLiteral("Cannot assign to non-existent default property") } } };
+ QTest::newRow("MissingDefaultPropertyDefinedInTheSameType")
+ << QStringLiteral("defaultPropertyWithinTheSameType.qml")
+ << Result { { Message {
+ QStringLiteral("Cannot assign to non-existent default property") } } };
+ QTest::newRow("DoubleAssignToDefaultProperty")
+ << QStringLiteral("defaultPropertyWithDoubleAssignment.qml")
+ << Result { { Message { QStringLiteral(
+ "Cannot assign multiple objects to a default non-list property") } } };
+ QTest::newRow("DefaultPropertyWithWrongType(string)")
+ << QStringLiteral("defaultPropertyWithWrongType.qml")
+ << Result { { Message { QStringLiteral(
+ "Cannot assign to default property of incompatible type") } },
+ { Message { QStringLiteral(
+ "Cannot assign to non-existent default property") } } };
+ QTest::newRow("MultiDefaultPropertyWithWrongType")
+ << QStringLiteral("multiDefaultPropertyWithWrongType.qml")
+ << Result { { Message { QStringLiteral(
+ "Cannot assign to default property of incompatible type") } },
+ { Message { QStringLiteral(
+ "Cannot assign to non-existent default property") } } };
+ QTest::newRow("DefaultPropertyLookupInUnknownType")
+ << QStringLiteral("unknownParentDefaultPropertyCheck.qml")
+ << Result { { Message { QStringLiteral(
+ "Alien was not found. Did you add all import paths?") } } };
+ QTest::newRow("InvalidImport")
+ << QStringLiteral("invalidImport.qml")
+ << Result { { Message { QStringLiteral(
+ "Failed to import FooBar. Are your import paths set up properly?") } } };
+ QTest::newRow("Unused Import (simple)")
+ << QStringLiteral("unused_simple.qml")
+ << Result { { Message { QStringLiteral("Unused import"), 1, 1, QtInfoMsg } },
+ {},
+ {},
+ Result::ExitsNormally };
+ QTest::newRow("Unused Import (prefix)")
+ << QStringLiteral("unused_prefix.qml")
+ << Result { { Message { QStringLiteral("Unused import"), 1, 1, QtInfoMsg } },
+ {},
+ {},
+ Result::ExitsNormally };
+ QTest::newRow("TypePropertAccess") << QStringLiteral("typePropertyAccess.qml") << Result {};
+ QTest::newRow("badAttachedProperty")
+ << QStringLiteral("badAttachedProperty.qml")
+ << Result { { Message {
+ QStringLiteral("Member \"progress\" not found on type \"TestType\"") } } };
+ QTest::newRow("badAttachedPropertyNested")
+ << QStringLiteral("badAttachedPropertyNested.qml")
+ << Result { { Message { QStringLiteral(
+ "Member \"progress\" not found on type \"QObject\""),
+ 12, 41 } },
+ { Message { QString("Member \"progress\" not found on type \"QObject\""),
+ 6, 37 } } };
+ QTest::newRow("badAttachedPropertyTypeString")
+ << QStringLiteral("badAttachedPropertyTypeString.qml")
+ << Result { { Message {
+ QStringLiteral("Cannot assign literal of type string to int") } } };
+ QTest::newRow("badAttachedPropertyTypeQtObject")
+ << QStringLiteral("badAttachedPropertyTypeQtObject.qml")
+ << Result { { Message { QStringLiteral(
+ "Property \"count\" of type \"int\" is assigned an incompatible type "
+ "\"QtObject\"") } } };
+ // should succeed, but it does not:
+ QTest::newRow("attachedPropertyAccess")
+ << QStringLiteral("goodAttachedPropertyAccess.qml") << Result::clean();
+ // should succeed, but it does not:
+ QTest::newRow("attachedPropertyNested")
+ << QStringLiteral("goodAttachedPropertyNested.qml") << Result::clean();
+ QTest::newRow("deprecatedFunction")
+ << QStringLiteral("deprecatedFunction.qml")
+ << Result { { Message { QStringLiteral(
+ "Method \"deprecated(foobar)\" is deprecated (Reason: No particular "
+ "reason.)") } } };
+ QTest::newRow("deprecatedFunctionInherited")
+ << QStringLiteral("deprecatedFunctionInherited.qml")
+ << Result { { Message { QStringLiteral(
+ "Method \"deprecatedInherited(c, d)\" is deprecated (Reason: This "
+ "deprecation should be visible!)") } } };
+
+ QTest::newRow("duplicated id")
+ << QStringLiteral("duplicateId.qml")
+ << Result { { Message {
+ QStringLiteral("Found a duplicated id. id root was first declared "), 0, 0,
+ QtCriticalMsg } } };
+
+ QTest::newRow("string as id") << QStringLiteral("stringAsId.qml")
+ << Result { { Message { QStringLiteral(
+ "ids do not need quotation marks") } } };
+ QTest::newRow("stringIdUsedInWarning")
+ << QStringLiteral("stringIdUsedInWarning.qml")
+ << Result { { Message {
+ QStringLiteral("i is a member of a parent element"),
+ } },
+ {},
+ { Message { QStringLiteral("stringy.") } } };
+ QTest::newRow("Invalid_id_expression")
+ << QStringLiteral("invalidId1.qml")
+ << Result { { Message { QStringLiteral("Failed to parse id") } } };
+ QTest::newRow("Invalid_id_blockstatement")
+ << QStringLiteral("invalidId2.qml")
+ << Result { { Message { QStringLiteral("id must be followed by an identifier") } } };
+ QTest::newRow("multilineString")
+ << QStringLiteral("multilineString.qml")
+ << Result { { Message { QStringLiteral("String contains unescaped line terminator "
+ "which is deprecated."),
+ 0, 0, QtInfoMsg } },
+ {},
+ { Message { "`Foo\nmultiline\\`\nstring`", 4, 32 },
+ Message { "`another\\`\npart\nof it`", 6, 11 },
+ Message { R"(`
+quote: " \\" \\\\"
+ticks: \` \` \\\` \\\`
+singleTicks: ' \' \\' \\\'
+expression: \${expr} \${expr} \\\${expr} \\\${expr}`)",
+ 10, 28 },
+ Message {
+ R"(`
+quote: " \" \\" \\\"
+ticks: \` \` \\\` \\\`
+singleTicks: ' \\' \\\\'
+expression: \${expr} \${expr} \\\${expr} \\\${expr}`)",
+ 16, 27 } },
+ { Result::ExitsNormally, Result::AutoFixable } };
+ QTest::addRow("multifix")
+ << QStringLiteral("multifix.qml")
+ << Result { {
+ Message { QStringLiteral("Unqualified access"), 7, 19, QtWarningMsg},
+ Message { QStringLiteral("Unqualified access"), 11, 19, QtWarningMsg},
+ }, {}, {
+ Message { QStringLiteral("pragma ComponentBehavior: Bound\n"), 1, 1 }
+ }, { Result::AutoFixable }};
+ QTest::newRow("unresolvedType")
+ << QStringLiteral("unresolvedType.qml")
+ << Result { { Message { QStringLiteral(
+ "UnresolvedType was not found. Did you add all import paths?") } },
+ { Message { QStringLiteral("incompatible type") } } };
+ QTest::newRow("invalidInterceptor")
+ << QStringLiteral("invalidInterceptor.qml")
+ << Result { { Message { QStringLiteral(
+ "On-binding for property \"angle\" has wrong type \"Item\"") } } };
+ QTest::newRow("2Interceptors")
+ << QStringLiteral("2interceptors.qml")
+ << Result { { Message { QStringLiteral("Duplicate interceptor on property \"x\"") } } };
+ QTest::newRow("ValueSource+2Interceptors")
+ << QStringLiteral("valueSourceBetween2interceptors.qml")
+ << Result { { Message { QStringLiteral("Duplicate interceptor on property \"x\"") } } };
+ QTest::newRow("2ValueSources") << QStringLiteral("2valueSources.qml")
+ << Result { { Message { QStringLiteral(
+ "Duplicate value source on property \"x\"") } } };
+ QTest::newRow("ValueSource+Value")
+ << QStringLiteral("valueSource_Value.qml")
+ << Result { { Message { QStringLiteral(
+ "Cannot combine value source and binding on property \"obj\"") } } };
+ QTest::newRow("ValueSource+ListValue")
+ << QStringLiteral("valueSource_listValue.qml")
+ << Result { { Message { QStringLiteral(
+ "Cannot combine value source and binding on property \"objs\"") } } };
+ QTest::newRow("NonExistentListProperty")
+ << QStringLiteral("nonExistentListProperty.qml")
+ << Result { { Message { QStringLiteral("Property \"objs\" does not exist") } } };
+ QTest::newRow("QtQuick.Window 2.0")
+ << QStringLiteral("qtquickWindow20.qml")
+ << Result { { Message { QStringLiteral(
+ "Member \"window\" not found on type \"QQuickWindow\"") } } };
+ QTest::newRow("unresolvedAttachedType")
+ << QStringLiteral("unresolvedAttachedType.qml")
+ << Result { { Message { QStringLiteral(
+ "unknown attached property scope UnresolvedAttachedType.") } },
+ { Message { QStringLiteral("Property \"property\" does not exist") } } };
+ QTest::newRow("nestedInlineComponents")
+ << QStringLiteral("nestedInlineComponents.qml")
+ << Result { { Message {
+ QStringLiteral("Nested inline components are not supported") } } };
+ QTest::newRow("inlineComponentNoComponent")
+ << QStringLiteral("inlineComponentNoComponent.qml")
+ << Result { { Message {
+ QStringLiteral("Inline component declaration must be followed by a typename"),
+ 3, 2 } } };
+ QTest::newRow("WithStatement") << QStringLiteral("WithStatement.qml")
+ << Result { { Message { QStringLiteral(
+ "with statements are strongly discouraged") } } };
+ QTest::newRow("BadLiteralBinding")
+ << QStringLiteral("badLiteralBinding.qml")
+ << Result { { Message {
+ QStringLiteral("Cannot assign literal of type string to int") } } };
+ QTest::newRow("BadLiteralBindingDate")
+ << QStringLiteral("badLiteralBindingDate.qml")
+ << Result { { Message {
+ QStringLiteral("Cannot assign binding of type QString to QDateTime") } } };
+ QTest::newRow("BadModulePrefix")
+ << QStringLiteral("badModulePrefix.qml")
+ << Result { { Message {
+ QStringLiteral("Cannot access singleton as a property of an object") } } };
+ QTest::newRow("BadModulePrefix2")
+ << QStringLiteral("badModulePrefix2.qml")
+ << Result { { Message { QStringLiteral(
+ "Cannot use a non-QObject type QRectF to access prefixed import") } } };
+ QTest::newRow("AssignToReadOnlyProperty")
+ << QStringLiteral("assignToReadOnlyProperty.qml")
+ << Result { { Message {
+ QStringLiteral("Cannot assign to read-only property activeFocus") } } };
+ QTest::newRow("AssignToReadOnlyProperty")
+ << QStringLiteral("assignToReadOnlyProperty2.qml")
+ << Result { { Message {
+ QStringLiteral("Cannot assign to read-only property activeFocus") } } };
+ QTest::newRow("cachedDependency")
+ << QStringLiteral("cachedDependency.qml")
+ << Result { { Message { QStringLiteral("Unused import"), 1, 1, QtInfoMsg } },
+ { Message { QStringLiteral(
+ "Cannot assign binding of type QQuickItem to QObject") } },
+ {},
+ Result::ExitsNormally };
+ QTest::newRow("cycle in import")
+ << QStringLiteral("cycleHead.qml")
+ << Result { { Message { QStringLiteral(
+ "MenuItem is part of an inheritance cycle: MenuItem -> MenuItem") } } };
+ QTest::newRow("badGeneralizedGroup1")
+ << QStringLiteral("badGeneralizedGroup1.qml")
+ << Result { { Message { QStringLiteral(
+ "Binding assigned to \"aaaa\", "
+ "but no property \"aaaa\" exists in the current element") } } };
+ QTest::newRow("badGeneralizedGroup2")
+ << QStringLiteral("badGeneralizedGroup2.qml")
+ << Result { { Message { QStringLiteral("unknown grouped property scope aself") } } };
+ QTest::newRow("missingQmltypes")
+ << QStringLiteral("missingQmltypes.qml")
+ << Result { { Message { QStringLiteral("QML types file does not exist") } } };
+ QTest::newRow("enumInvalid")
+ << QStringLiteral("enumInvalid.qml")
+ << Result { { Message {
+ QStringLiteral("Member \"red\" not found on type \"QtObject\"") } } };
+ QTest::newRow("inaccessibleId")
+ << QStringLiteral("inaccessibleId.qml")
+ << Result { { Message {
+ QStringLiteral("Member \"objectName\" not found on type \"int\"") } } };
+ QTest::newRow("inaccessibleId2")
+ << QStringLiteral("inaccessibleId2.qml")
+ << Result { { Message {
+ QStringLiteral("Member \"objectName\" not found on type \"int\"") } } };
+ QTest::newRow("unknownTypeCustomParser")
+ << QStringLiteral("unknownTypeCustomParser.qml")
+ << Result { { Message { QStringLiteral("TypeDoesNotExist was not found.") } } };
+ QTest::newRow("nonNullStored")
+ << QStringLiteral("nonNullStored.qml")
+ << Result { { Message { QStringLiteral(
+ "Member \"objectName\" not found on type \"Foozle\"") } },
+ { Message { QStringLiteral("Unqualified access") } } };
+ QTest::newRow("cppPropertyChangeHandlers-wrong-parameters-size-bindable")
+ << QStringLiteral("badCppPropertyChangeHandlers1.qml")
+ << Result { { Message { QStringLiteral(
+ "Signal handler for \"onAChanged\" has more formal parameters than "
+ "the signal it handles") } } };
+ QTest::newRow("cppPropertyChangeHandlers-wrong-parameters-size-notify")
+ << QStringLiteral("badCppPropertyChangeHandlers2.qml")
+ << Result { { Message { QStringLiteral(
+ "Signal handler for \"onBChanged\" has more formal parameters than "
+ "the signal it handles") } } };
+ QTest::newRow("cppPropertyChangeHandlers-no-property")
+ << QStringLiteral("badCppPropertyChangeHandlers3.qml")
+ << Result { { Message {
+ QStringLiteral("no matching signal found for handler \"onXChanged\"") } } };
+ QTest::newRow("cppPropertyChangeHandlers-not-a-signal")
+ << QStringLiteral("badCppPropertyChangeHandlers4.qml")
+ << Result { { Message { QStringLiteral(
+ "no matching signal found for handler \"onWannabeSignal\"") } } };
+ QTest::newRow("didYouMean(binding)")
+ << QStringLiteral("didYouMeanBinding.qml")
+ << Result {
+ { Message { QStringLiteral(
+ "Binding assigned to \"witdh\", but no property \"witdh\" exists in "
+ "the current element.") } },
+ {},
+ { Message { QStringLiteral("width") } }
+ };
+ QTest::newRow("didYouMean(unqualified)")
+ << QStringLiteral("didYouMeanUnqualified.qml")
+ << Result { { Message { QStringLiteral("Unqualified access") } },
+ {},
+ { Message { QStringLiteral("height") } } };
+ QTest::newRow("didYouMean(unqualifiedCall)")
+ << QStringLiteral("didYouMeanUnqualifiedCall.qml")
+ << Result { { Message { QStringLiteral("Unqualified access") } },
+ {},
+ { Message { QStringLiteral("func") } } };
+ QTest::newRow("didYouMean(property)")
+ << QStringLiteral("didYouMeanProperty.qml")
+ << Result { { Message { QStringLiteral(
+ "Member \"hoight\" not found on type \"Rectangle\"") },
+ {},
+ { Message { QStringLiteral("height") } } } };
+ QTest::newRow("didYouMean(propertyCall)")
+ << QStringLiteral("didYouMeanPropertyCall.qml")
+ << Result {
+ { Message { QStringLiteral("Member \"lgg\" not found on type \"Console\"") },
+ {},
+ { Message { QStringLiteral("log") } } }
+ };
+ QTest::newRow("didYouMean(component)")
+ << QStringLiteral("didYouMeanComponent.qml")
+ << Result { { Message { QStringLiteral(
+ "Itym was not found. Did you add all import paths?") },
+ {},
+ { Message { QStringLiteral("Item") } } } };
+ QTest::newRow("didYouMean(enum)")
+ << QStringLiteral("didYouMeanEnum.qml")
+ << Result { { Message { QStringLiteral(
+ "Member \"Readx\" not found on type \"QQuickImage\"") },
+ {},
+ { Message { QStringLiteral("Ready") } } } };
+ QTest::newRow("nullBinding") << QStringLiteral("nullBinding.qml")
+ << Result{ { Message{ QStringLiteral(
+ "Cannot assign literal of type null to qreal") } } };
+ QTest::newRow("missingRequiredAlias")
+ << QStringLiteral("missingRequiredAlias.qml")
+ << Result { { Message {
+ QStringLiteral("Component is missing required property requiredAlias from "
+ "RequiredWithRootLevelAlias") } } };
+ QTest::newRow("missingSingletonPragma")
+ << QStringLiteral("missingSingletonPragma.qml")
+ << Result { { Message { QStringLiteral(
+ "Type MissingPragma declared as singleton in qmldir but missing "
+ "pragma Singleton") } } };
+ QTest::newRow("missingSingletonQmldir")
+ << QStringLiteral("missingSingletonQmldir.qml")
+ << Result { { Message { QStringLiteral(
+ "Type MissingQmldirSingleton not declared as singleton in qmldir but using "
+ "pragma Singleton") } } };
+ QTest::newRow("jsVarDeclarationsWriteConst")
+ << QStringLiteral("jsVarDeclarationsWriteConst.qml")
+ << Result { { Message {
+ QStringLiteral("Cannot assign to read-only property constProp") } } };
+ QTest::newRow("shadowedSignal")
+ << QStringLiteral("shadowedSignal.qml")
+ << Result { { Message {
+ QStringLiteral("Signal \"pressed\" is shadowed by a property.") } } };
+ QTest::newRow("shadowedSignalWithId")
+ << QStringLiteral("shadowedSignalWithId.qml")
+ << Result { { Message {
+ QStringLiteral("Signal \"pressed\" is shadowed by a property") } } };
+ QTest::newRow("shadowedSlot") << QStringLiteral("shadowedSlot.qml")
+ << Result { { Message { QStringLiteral(
+ "Slot \"move\" is shadowed by a property") } } };
+ QTest::newRow("shadowedMethod") << QStringLiteral("shadowedMethod.qml")
+ << Result { { Message { QStringLiteral(
+ "Method \"foo\" is shadowed by a property.") } } };
+ QTest::newRow("callVarProp")
+ << QStringLiteral("callVarProp.qml")
+ << Result { { Message { QStringLiteral(
+ "Property \"foo\" is a variant property. It may or may not be a "
+ "method. Use a regular function instead.") } } };
+ QTest::newRow("callJSValue")
+ << QStringLiteral("callJSValueProp.qml")
+ << Result { { Message { QStringLiteral(
+ "Property \"gradient\" is a QJSValue property. It may or may not be "
+ "a method. Use a regular Q_INVOKABLE instead.") } } };
+ QTest::newRow("assignNonExistingTypeToVarProp")
+ << QStringLiteral("assignNonExistingTypeToVarProp.qml")
+ << Result { { Message { QStringLiteral(
+ "NonExistingType was not found. Did you add all import paths?") } } };
+ QTest::newRow("unboundComponents")
+ << QStringLiteral("unboundComponents.qml")
+ << Result { {
+ Message { QStringLiteral("Unqualified access"), 10, 25 },
+ Message { QStringLiteral("Unqualified access"), 14, 33 }
+ } };
+ QTest::newRow("badlyBoundComponents")
+ << QStringLiteral("badlyBoundComponents.qml")
+ << Result{ { Message{ QStringLiteral("Unqualified access"), 18, 36 } } };
+ QTest::newRow("NotScopedEnumCpp")
+ << QStringLiteral("NotScopedEnumCpp.qml")
+ << Result{ { Message{
+ QStringLiteral("You cannot access unscoped enum \"TheEnum\" from here."), 5,
+ 49 } } };
+
+ QTest::newRow("unresolvedArrayBinding")
+ << QStringLiteral("unresolvedArrayBinding.qml")
+ << Result{ { Message{ QStringLiteral(u"Declaring an object which is not an Qml object"
+ " as a list member.") } } };
+ QTest::newRow("duplicatedPropertyName")
+ << QStringLiteral("duplicatedPropertyName.qml")
+ << Result{ { Message{ QStringLiteral("Duplicated property name \"cat\"."), 5, 5 } } };
+ QTest::newRow("duplicatedSignalName")
+ << QStringLiteral("duplicatedPropertyName.qml")
+ << Result{ { Message{ QStringLiteral("Duplicated signal name \"clicked\"."), 8, 5 } } };
+ QTest::newRow("missingComponentBehaviorBound")
+ << QStringLiteral("missingComponentBehaviorBound.qml")
+ << Result {
+ { Message{ QStringLiteral("Unqualified access"), 8, 31 } },
+ {},
+ { Message{ QStringLiteral("Set \"pragma ComponentBehavior: Bound\" in "
+ "order to use IDs from outer components "
+ "in nested components."), 0, 0, QtInfoMsg } },
+ Result::AutoFixable
+ };
+ QTest::newRow("IsNotAnEntryOfEnum")
+ << QStringLiteral("IsNotAnEntryOfEnum.qml")
+ << Result{ {
+ Message {
+ QStringLiteral("Member \"Mode\" not found on type \"Item\""), 12,
+ 29, QtWarningMsg },
+ Message{
+ QStringLiteral("\"Hour\" is not an entry of enum \"Mode\"."), 13,
+ 62, QtInfoMsg }
+ },
+ {},
+ { Message{ QStringLiteral("Hours") } }
+ };
+
+ QTest::newRow("StoreNameMethod")
+ << QStringLiteral("storeNameMethod.qml")
+ << Result { { Message { QStringLiteral("Cannot assign to method foo") } } };
+
+ QTest::newRow("CoerceToVoid")
+ << QStringLiteral("coercetovoid.qml")
+ << Result { { Message {
+ QStringLiteral("Function without return type annotation returns double")
+ } } };
+
+ QTest::newRow("lowerCaseQualifiedImport")
+ << QStringLiteral("lowerCaseQualifiedImport.qml")
+ << Result{ {
+ Message{ u"Import qualifier 'test' must start with a capital letter."_s },
+ Message{
+ u"Namespace 'test' of 'test.Rectangle' must start with an upper case letter."_s },
+ } };
+ QTest::newRow("lowerCaseQualifiedImport2")
+ << QStringLiteral("lowerCaseQualifiedImport2.qml")
+ << Result{ {
+ Message{ u"Import qualifier 'test' must start with a capital letter."_s },
+ Message{
+ u"Namespace 'test' of 'test.Item' must start with an upper case letter."_s },
+ Message{
+ u"Namespace 'test' of 'test.Rectangle' must start with an upper case letter."_s },
+ Message{
+ u"Namespace 'test' of 'test.color' must start with an upper case letter."_s },
+ Message{
+ u"Namespace 'test' of 'test.Grid' must start with an upper case letter."_s },
+ } };
+ QTest::newRow("notQmlRootMethods")
+ << QStringLiteral("notQmlRootMethods.qml")
+ << Result{ {
+ Message{ u"Member \"deleteLater\" not found on type \"QtObject\""_s },
+ Message{ u"Member \"destroyed\" not found on type \"QtObject\""_s },
+ } };
}
void TestQmllint::dirtyQmlCode()
{
QFETCH(QString, filename);
- QFETCH(QString, warningMessage);
- QFETCH(QString, notContained);
- if (warningMessage.contains(QLatin1String("%1")))
- warningMessage = warningMessage.arg(testFile(filename));
-
- const QString output = runQmllint(filename, [&](QProcess &process) {
- QVERIFY(process.waitForFinished());
- QCOMPARE(process.exitStatus(), QProcess::NormalExit);
- QEXPECT_FAIL("anchors3", "We don't see that QQuickItem cannot be assigned to QQuickAnchorLine", Abort);
- QEXPECT_FAIL("nanchors1", "Invalid grouped properties are not always detected", Abort);
- QVERIFY(process.exitCode() != 0);
- });
+ QFETCH(Result, result);
- QVERIFY(output.contains(warningMessage));
- if (!notContained.isEmpty())
- QVERIFY(!output.contains(notContained));
+ QJsonArray warnings;
+
+ QEXPECT_FAIL("attachedPropertyAccess", "We cannot discern between types and instances", Abort);
+ QEXPECT_FAIL("attachedPropertyNested", "We cannot discern between types and instances", Abort);
+ QEXPECT_FAIL("BadLiteralBindingDate",
+ "We're currently not able to verify any non-trivial QString conversion that "
+ "requires QQmlStringConverters",
+ Abort);
+ QEXPECT_FAIL("bad tranlsation binding (qsTr)", "We currently do not check translation binding",
+ Abort);
+
+ callQmllint(filename, result.flags.testFlag(Result::ExitsNormally), &warnings, {}, {}, {},
+ UseDefaultImports, nullptr, result.flags.testFlag(Result::Flag::AutoFixable));
+
+ checkResult(
+ warnings, result,
+ [] {
+ QEXPECT_FAIL("BadLiteralBindingDate",
+ "We're currently not able to verify any non-trivial QString "
+ "conversion that "
+ "requires QQmlStringConverters",
+ Abort);
+ },
+ [] {
+ QEXPECT_FAIL("badAttachedPropertyNested",
+ "We cannot discern between types and instances", Abort);
+ });
}
void TestQmllint::cleanQmlCode_data()
@@ -385,7 +1228,7 @@ void TestQmllint::cleanQmlCode_data()
QTest::newRow("enumFromQtQml") << QStringLiteral("enumFromQtQml.qml");
QTest::newRow("anchors1") << QStringLiteral("anchors1.qml");
QTest::newRow("anchors2") << QStringLiteral("anchors2.qml");
- QTest::newRow("optionalImport") << QStringLiteral("optionalImport.qml");
+ QTest::newRow("defaultImport") << QStringLiteral("defaultImport.qml");
QTest::newRow("goodAliasObject") << QStringLiteral("goodAliasObject.qml");
QTest::newRow("jsmoduleimport") << QStringLiteral("jsmoduleimport.qml");
QTest::newRow("overridescript") << QStringLiteral("overridescript.qml");
@@ -398,40 +1241,288 @@ void TestQmllint::cleanQmlCode_data()
QTest::newRow("externalEnumProperty") << QStringLiteral("externalEnumProperty.qml");
QTest::newRow("shapes") << QStringLiteral("shapes.qml");
QTest::newRow("var") << QStringLiteral("var.qml");
+ QTest::newRow("defaultProperty") << QStringLiteral("defaultProperty.qml");
+ QTest::newRow("defaultPropertyList") << QStringLiteral("defaultPropertyList.qml");
+ QTest::newRow("defaultPropertyComponent") << QStringLiteral("defaultPropertyComponent.qml");
+ QTest::newRow("defaultPropertyComponent2") << QStringLiteral("defaultPropertyComponent.2.qml");
+ QTest::newRow("defaultPropertyListModel") << QStringLiteral("defaultPropertyListModel.qml");
+ QTest::newRow("defaultPropertyVar") << QStringLiteral("defaultPropertyVar.qml");
+ QTest::newRow("multiDefaultProperty") << QStringLiteral("multiDefaultPropertyOk.qml");
+ QTest::newRow("propertyDelegate") << QStringLiteral("propertyDelegate.qml");
+ 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");
+ QTest::newRow("stringLength3") << QStringLiteral("stringLength3.qml");
+ QTest::newRow("attachedPropertyAssignments")
+ << QStringLiteral("attachedPropertyAssignments.qml");
+ QTest::newRow("groupedPropertyAssignments") << QStringLiteral("groupedPropertyAssignments.qml");
+ QTest::newRow("goodAttachedProperty") << QStringLiteral("goodAttachedProperty.qml");
+ QTest::newRow("objectBindingOnVarProperty") << QStringLiteral("objectBoundToVar.qml");
+ QTest::newRow("Unversioned change signal without arguments") << QStringLiteral("unversionChangedSignalSansArguments.qml");
+ QTest::newRow("deprecatedFunctionOverride") << QStringLiteral("deprecatedFunctionOverride.qml");
+ QTest::newRow("multilineStringEscaped") << QStringLiteral("multilineStringEscaped.qml");
+ QTest::newRow("propertyOverride") << QStringLiteral("propertyOverride.qml");
+ QTest::newRow("propertyBindingValue") << QStringLiteral("propertyBindingValue.qml");
+ QTest::newRow("customParser") << QStringLiteral("customParser.qml");
+ QTest::newRow("customParser.recursive") << QStringLiteral("customParser.recursive.qml");
+ QTest::newRow("2Behavior") << QStringLiteral("2behavior.qml");
+ QTest::newRow("interceptor") << QStringLiteral("interceptor.qml");
+ QTest::newRow("valueSource") << QStringLiteral("valueSource.qml");
+ QTest::newRow("interceptor+valueSource") << QStringLiteral("interceptor_valueSource.qml");
+ QTest::newRow("groupedProperty (valueSource+interceptor)")
+ << QStringLiteral("groupedProperty_valueSource_interceptor.qml");
+ QTest::newRow("QtQuick.Window 2.1") << QStringLiteral("qtquickWindow21.qml");
+ QTest::newRow("attachedTypeIndirect") << QStringLiteral("attachedTypeIndirect.qml");
+ QTest::newRow("objectArray") << QStringLiteral("objectArray.qml");
+ QTest::newRow("aliasToList") << QStringLiteral("aliasToList.qml");
+ QTest::newRow("QVariant") << QStringLiteral("qvariant.qml");
+ QTest::newRow("Accessible") << QStringLiteral("accessible.qml");
+ QTest::newRow("qjsroot") << QStringLiteral("qjsroot.qml");
+ QTest::newRow("qmlRootMethods") << QStringLiteral("qmlRootMethods.qml");
+ QTest::newRow("InlineComponent") << QStringLiteral("inlineComponent.qml");
+ QTest::newRow("InlineComponentWithComponents") << QStringLiteral("inlineComponentWithComponents.qml");
+ QTest::newRow("InlineComponentsChained") << QStringLiteral("inlineComponentsChained.qml");
+ QTest::newRow("ignoreWarnings") << QStringLiteral("ignoreWarnings.qml");
+ QTest::newRow("BindingBeforeDeclaration") << QStringLiteral("bindingBeforeDeclaration.qml");
+ QTest::newRow("CustomParserUnqualifiedAccess")
+ << QStringLiteral("customParserUnqualifiedAccess.qml");
+ QTest::newRow("ImportQMLModule") << QStringLiteral("importQMLModule.qml");
+ QTest::newRow("ImportDirectoryQmldir") << QStringLiteral("Things/LintDirectly.qml");
+ QTest::newRow("BindingsOnGroupAndAttachedProperties")
+ << QStringLiteral("goodBindingsOnGroupAndAttached.qml");
+ QTest::newRow("QQmlEasingEnums::Type") << QStringLiteral("animationEasing.qml");
+ QTest::newRow("ValidLiterals") << QStringLiteral("validLiterals.qml");
+ QTest::newRow("GoodModulePrefix") << QStringLiteral("goodModulePrefix.qml");
+ QTest::newRow("required property in Component") << QStringLiteral("requiredPropertyInComponent.qml");
+ 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");
+ QTest::newRow("on binding in grouped property") << QStringLiteral("onBindingInGroupedProperty.qml");
+ 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");
+ QTest::newRow("cppPropertyChangeHandlers")
+ << QStringLiteral("goodCppPropertyChangeHandlers.qml");
+ QTest::newRow("unexportedCppBase") << QStringLiteral("unexportedCppBase.qml");
+ QTest::newRow("requiredWithRootLevelAlias") << QStringLiteral("RequiredWithRootLevelAlias.qml");
+ QTest::newRow("jsVarDeclarations") << QStringLiteral("jsVarDeclarations.qml");
+ QTest::newRow("qmodelIndex") << QStringLiteral("qmodelIndex.qml");
+ QTest::newRow("boundComponents") << QStringLiteral("boundComponents.qml");
+ QTest::newRow("prefixedAttachedProperty") << QStringLiteral("prefixedAttachedProperty.qml");
+ QTest::newRow("callLater") << QStringLiteral("callLater.qml");
+ QTest::newRow("listPropertyMethods") << QStringLiteral("listPropertyMethods.qml");
+ QTest::newRow("v4SequenceMethods") << QStringLiteral("v4SequenceMethods.qml");
+ QTest::newRow("stringToByteArray") << QStringLiteral("stringToByteArray.qml");
+ QTest::newRow("jsLibrary") << QStringLiteral("jsLibrary.qml");
+ QTest::newRow("nullBindingFunction") << QStringLiteral("nullBindingFunction.qml");
+ QTest::newRow("BindingTypeMismatchFunction") << QStringLiteral("bindingTypeMismatchFunction.qml");
+ QTest::newRow("BindingTypeMismatch") << QStringLiteral("bindingTypeMismatch.qml");
+ QTest::newRow("template literal (substitution)") << QStringLiteral("templateStringSubstitution.qml");
+ QTest::newRow("enumsOfScrollBar") << QStringLiteral("enumsOfScrollBar.qml");
+ QTest::newRow("optionalChainingCall") << QStringLiteral("optionalChainingCall.qml");
+ QTest::newRow("EnumAccessCpp") << QStringLiteral("EnumAccessCpp.qml");
+ QTest::newRow("qtquickdialog") << QStringLiteral("qtquickdialog.qml");
+ QTest::newRow("callBase") << QStringLiteral("callBase.qml");
+ QTest::newRow("propertyWithOn") << QStringLiteral("switcher.qml");
+ QTest::newRow("constructorProperty") << QStringLiteral("constructorProperty.qml");
+ QTest::newRow("onlyMajorVersion") << QStringLiteral("onlyMajorVersion.qml");
+ QTest::newRow("attachedImportUse") << QStringLiteral("attachedImportUse.qml");
+ QTest::newRow("VariantMapGetPropertyLookup") << QStringLiteral("variantMapLookup.qml");
+ QTest::newRow("StringToDateTime") << QStringLiteral("stringToDateTime.qml");
+ QTest::newRow("ScriptInTemplate") << QStringLiteral("scriptInTemplate.qml");
+ QTest::newRow("AddressableValue") << QStringLiteral("addressableValue.qml");
+ QTest::newRow("WriteListProperty") << QStringLiteral("writeListProperty.qml");
+ QTest::newRow("dontConfuseMemberPrintWithGlobalPrint") << QStringLiteral("findMemberPrint.qml");
+ QTest::newRow("groupedAttachedLayout") << QStringLiteral("groupedAttachedLayout.qml");
+ QTest::newRow("QQmlScriptString") << QStringLiteral("scriptstring.qml");
+ QTest::newRow("QEventPoint") << QStringLiteral("qEventPoint.qml");
+ QTest::newRow("locale") << QStringLiteral("locale.qml");
+ QTest::newRow("constInvokable") << QStringLiteral("useConstInvokable.qml");
+ QTest::newRow("dontCheckJSTypes") << QStringLiteral("dontCheckJSTypes.qml");
}
void TestQmllint::cleanQmlCode()
{
QFETCH(QString, filename);
- const QString warnings = runQmllint(filename, true);
- QEXPECT_FAIL("segFault", "This property exists and should not produce a warning", Abort);
- QVERIFY2(warnings.isEmpty(), qPrintable(warnings));
+
+ QJsonArray warnings;
+
+ runTest(filename, Result::clean());
+}
+
+void TestQmllint::compilerWarnings_data()
+{
+ QTest::addColumn<QString>("filename");
+ QTest::addColumn<Result>("result");
+ QTest::addColumn<bool>("enableCompilerWarnings");
+
+ QTest::newRow("listIndices") << QStringLiteral("listIndices.qml") << Result::clean() << true;
+ QTest::newRow("lazyAndDirect")
+ << QStringLiteral("LazyAndDirect/Lazy.qml") << Result::clean() << true;
+ QTest::newRow("qQmlV4Function") << QStringLiteral("varargs.qml") << Result::clean() << true;
+ QTest::newRow("multiGrouped") << QStringLiteral("multiGrouped.qml") << Result::clean() << true;
+
+ QTest::newRow("shadowable")
+ << QStringLiteral("shadowable.qml")
+ << Result { { Message {QStringLiteral(
+ "with type NotSoSimple (stored as QQuickItem) can be shadowed") } } }
+ << true;
+ QTest::newRow("tooFewParameters")
+ << QStringLiteral("tooFewParams.qml")
+ << Result { { Message { QStringLiteral("No matching override found") } } } << true;
+ QTest::newRow("javascriptVariableArgs")
+ << QStringLiteral("javascriptVariableArgs.qml")
+ << Result { { Message {
+ QStringLiteral("Function expects 0 arguments, but 2 were provided") } } }
+ << true;
+ QTest::newRow("unknownTypeInRegister")
+ << QStringLiteral("unknownTypeInRegister.qml")
+ << Result { { Message {
+ QStringLiteral("Functions without type annotations won't be compiled") } } }
+ << true;
+ QTest::newRow("pragmaStrict")
+ << QStringLiteral("pragmaStrict.qml")
+ << Result { { { QStringLiteral(
+ "Functions without type annotations won't be compiled") } } }
+ << true;
+ QTest::newRow("generalizedGroupHint")
+ << QStringLiteral("generalizedGroupHint.qml")
+ << Result { { { QStringLiteral(
+ "Cannot resolve property type for binding on myColor. "
+ "You may want use ID-based grouped properties here.") } } }
+ << true;
+ QTest::newRow("invalidIdLookup")
+ << QStringLiteral("invalidIdLookup.qml")
+ << Result { { {
+ QStringLiteral("Cannot retrieve a non-object type by ID: stateMachine")
+ } } }
+ << true;
+ QTest::newRow("returnTypeAnnotation-component")
+ << QStringLiteral("returnTypeAnnotation_component.qml")
+ << Result{ { { "Could not compile function comp: function without return type "
+ "annotation returns (component in" },
+ { "returnTypeAnnotation_component.qml)::c with type Comp (stored as "
+ "QQuickItem). This may prevent proper compilation to Cpp." } } }
+ << true;
+ QTest::newRow("returnTypeAnnotation-enum")
+ << QStringLiteral("returnTypeAnnotation_enum.qml")
+ << Result{ { { "Could not compile function enumeration: function without return type "
+ "annotation returns QQuickText::HAlignment::AlignRight (stored as int). "
+ "This may prevent proper compilation to Cpp." } } }
+ << true;
+ QTest::newRow("returnTypeAnnotation-method")
+ << QStringLiteral("returnTypeAnnotation_method.qml")
+ << Result{ { { "Could not compile function method: function without return type "
+ "annotation returns (component in " }, // Don't check the build folder path
+ { "returnTypeAnnotation_method.qml)::f(...) (stored as QJSValue). This may "
+ "prevent proper compilation to Cpp." } } }
+ << true;
+ QTest::newRow("returnTypeAnnotation-property")
+ << QStringLiteral("returnTypeAnnotation_property.qml")
+ << Result{ { { "Could not compile function prop: function without return type "
+ "annotation returns (component in " }, // Don't check the build folder path
+ { "returnTypeAnnotation_property.qml)::i with type int. This may prevent "
+ "proper compilation to Cpp." } } }
+ << true;
+ QTest::newRow("returnTypeAnnotation-type")
+ << QStringLiteral("returnTypeAnnotation_type.qml")
+ << Result{ { { "Could not compile function type: function without return type "
+ "annotation returns double. This may prevent proper compilation to "
+ "Cpp." } } }
+ << true;
+}
+
+void TestQmllint::compilerWarnings()
+{
+ QFETCH(QString, filename);
+ QFETCH(Result, result);
+ QFETCH(bool, enableCompilerWarnings);
+
+ QJsonArray warnings;
+
+ auto categories = QQmlJSLogger::defaultCategories();
+
+ auto category = std::find_if(categories.begin(), categories.end(), [](const QQmlJS::LoggerCategory& category) {
+ return category.id() == qmlCompiler;
+ });
+ Q_ASSERT(category != categories.end());
+
+ if (enableCompilerWarnings) {
+ category->setLevel(QtWarningMsg);
+ category->setIgnored(false);
+ }
+
+ runTest(filename, result, {}, {}, {}, UseDefaultImports, &categories);
}
QString TestQmllint::runQmllint(const QString &fileToLint,
std::function<void(QProcess &)> handleResult,
- const QStringList &extraArgs)
+ const QStringList &extraArgs, bool ignoreSettings,
+ bool addImportDirs, bool absolutePath, const Environment &env)
{
auto qmlImportDir = QLibraryInfo::path(QLibraryInfo::QmlImportsPath);
QStringList args;
- args << (QFileInfo(fileToLint).isAbsolute() ? fileToLint : testFile(fileToLint))
- << QStringLiteral("-I") << qmlImportDir
- << QStringLiteral("-I") << dataDirectory();
+ QString absoluteFilePath =
+ QFileInfo(fileToLint).isAbsolute() ? fileToLint : testFile(fileToLint);
+
+ args << QFileInfo(absoluteFilePath).fileName();
+
+ if (addImportDirs) {
+ args << QStringLiteral("-I") << qmlImportDir
+ << QStringLiteral("-I") << dataDirectory();
+ }
+
+ if (ignoreSettings)
+ args << QStringLiteral("--ignore-settings");
+
+ if (absolutePath)
+ args << QStringLiteral("--absolute-path");
+
args << extraArgs;
args << QStringLiteral("--silent");
QString errors;
auto verify = [&](bool isSilent) {
QProcess process;
+ QProcessEnvironment processEnv = QProcessEnvironment::systemEnvironment();
+ for (const auto &entry : env)
+ processEnv.insert(entry.first, entry.second);
+
+ process.setProcessEnvironment(processEnv);
+ process.setWorkingDirectory(QFileInfo(absoluteFilePath).absolutePath());
process.start(m_qmllintPath, args);
handleResult(process);
errors = process.readAllStandardError();
- if (isSilent)
- QVERIFY(errors.isEmpty());
+ QStringList lines = errors.split(u'\n', Qt::SkipEmptyParts);
+
+ auto end = std::remove_if(lines.begin(), lines.end(), [](const QString &line) {
+ return !line.startsWith("Warning: ") && !line.startsWith("Error: ");
+ });
+
+ std::sort(lines.begin(), end);
+ auto it = std::unique(lines.begin(), end);
+ if (it != end) {
+ qDebug() << "The warnings and errors were generated more than once:";
+ do {
+ qDebug() << *it;
+ } while (++it != end);
+ QTest::qFail("Duplicate warnings and errors", __FILE__, __LINE__);
+ }
+
+ if (isSilent) {
+ QTest::qVerify(errors.isEmpty(), "errors.isEmpty()", "Silent mode outputs messages",
+ __FILE__, __LINE__);
+ }
if (QTest::currentTestFailed()) {
- qDebug() << "Command:" << process.program() << args.join(u' ');
+ qDebug().noquote() << "Command:" << process.program() << args.join(u' ');
qDebug() << "Exit status:" << process.exitStatus();
qDebug() << "Exit code:" << process.exitCode();
qDebug() << "stderr:" << errors;
@@ -444,28 +1535,722 @@ QString TestQmllint::runQmllint(const QString &fileToLint,
return errors;
}
-QString TestQmllint::runQmllint(const QString &fileToLint, bool shouldSucceed, const QStringList &extraArgs)
+QString TestQmllint::runQmllint(const QString &fileToLint, bool shouldSucceed,
+ const QStringList &extraArgs, bool ignoreSettings,
+ bool addImportDirs, bool absolutePath, const Environment &env)
{
- return runQmllint(fileToLint, [&](QProcess &process) {
- QVERIFY(process.waitForFinished());
- QCOMPARE(process.exitStatus(), QProcess::NormalExit);
+ return runQmllint(
+ fileToLint,
+ [&](QProcess &process) {
+ QVERIFY(process.waitForFinished());
+ QCOMPARE(process.exitStatus(), QProcess::NormalExit);
- QEXPECT_FAIL("segFault", "This property exists and should not produce a warning", Abort);
- if (shouldSucceed)
- QCOMPARE(process.exitCode(), 0);
- else
- QVERIFY(process.exitCode() != 0);
- }, extraArgs);
+ if (shouldSucceed)
+ QCOMPARE(process.exitCode(), 0);
+ else
+ QVERIFY(process.exitCode() != 0);
+ },
+ extraArgs, ignoreSettings, addImportDirs, absolutePath, env);
+}
+
+void TestQmllint::callQmllint(const QString &fileToLint, bool shouldSucceed, QJsonArray *warnings,
+ QStringList importPaths, QStringList qmldirFiles,
+ QStringList resources, DefaultImportOption defaultImports,
+ QList<QQmlJS::LoggerCategory> *categories, bool autoFixable,
+ LintType type)
+{
+ QJsonArray jsonOutput;
+
+ const QFileInfo info = QFileInfo(fileToLint);
+ const QString lintedFile = info.isAbsolute() ? fileToLint : testFile(fileToLint);
+
+ QQmlJSLinter::LintResult lintResult;
+
+ const QStringList resolvedImportPaths = defaultImports == UseDefaultImports
+ ? m_defaultImportPaths + importPaths
+ : importPaths;
+ if (type == LintFile) {
+ const QList<QQmlJS::LoggerCategory> resolvedCategories =
+ categories != nullptr ? *categories : QQmlJSLogger::defaultCategories();
+ lintResult = m_linter.lintFile(
+ lintedFile, nullptr, true, &jsonOutput, resolvedImportPaths, qmldirFiles,
+ resources, resolvedCategories);
+ } else {
+ lintResult =
+ m_linter.lintModule(fileToLint, true, &jsonOutput, resolvedImportPaths, resources);
+ }
+
+ bool success = lintResult == QQmlJSLinter::LintSuccess;
+ QEXPECT_FAIL("qtquickdialog", "Will fail until QTBUG-104091 is implemented", Abort);
+ QVERIFY2(success == shouldSucceed, QJsonDocument(jsonOutput).toJson());
+
+ if (warnings) {
+ QVERIFY2(jsonOutput.size() == 1, QJsonDocument(jsonOutput).toJson());
+ *warnings = jsonOutput.at(0)[u"warnings"_s].toArray();
+ }
+
+ QCOMPARE(success, shouldSucceed);
+
+ if (lintResult == QQmlJSLinter::LintSuccess || lintResult == QQmlJSLinter::HasWarnings) {
+ QString fixedCode;
+ QQmlJSLinter::FixResult fixResult = m_linter.applyFixes(&fixedCode, true);
+
+ if (autoFixable) {
+ QCOMPARE(fixResult, QQmlJSLinter::FixSuccess);
+ // Check that the fixed version of the file actually passes qmllint now
+ QTemporaryDir dir;
+ QVERIFY(dir.isValid());
+ QFile file(dir.filePath("Fixed.qml"));
+ QVERIFY2(file.open(QIODevice::WriteOnly), qPrintable(file.errorString()));
+ file.write(fixedCode.toUtf8());
+ file.flush();
+ file.close();
+
+ callQmllint(QFileInfo(file).absoluteFilePath(), true, nullptr, importPaths, qmldirFiles,
+ resources, defaultImports, categories, false);
+
+ const QString fixedPath = testFile(info.baseName() + u".fixed.qml"_s);
+
+ if (QFileInfo(fixedPath).exists()) {
+ QFile fixedFile(fixedPath);
+ QVERIFY(fixedFile.open(QFile::ReadOnly));
+ QString fixedFileContents = QString::fromUtf8(fixedFile.readAll());
+#ifdef Q_OS_WIN
+ fixedCode = fixedCode.replace(u"\r\n"_s, u"\n"_s);
+ fixedFileContents = fixedFileContents.replace(u"\r\n"_s, u"\n"_s);
+#endif
+
+ QCOMPARE(fixedCode, fixedFileContents);
+ }
+ } else {
+ if (shouldSucceed)
+ QCOMPARE(fixResult, QQmlJSLinter::NothingToFix);
+ else
+ QVERIFY(fixResult == QQmlJSLinter::FixSuccess
+ || fixResult == QQmlJSLinter::NothingToFix);
+ }
+ }
+}
+
+void TestQmllint::runTest(const QString &testFile, const Result &result, QStringList importDirs,
+ QStringList qmltypesFiles, QStringList resources,
+ DefaultImportOption defaultImports,
+ QList<QQmlJS::LoggerCategory> *categories)
+{
+ QJsonArray warnings;
+ callQmllint(testFile, result.flags.testFlag(Result::Flag::ExitsNormally), &warnings, importDirs,
+ qmltypesFiles, resources, defaultImports, categories,
+ result.flags.testFlag(Result::Flag::AutoFixable));
+ checkResult(warnings, result);
+}
+
+template<typename ExpectedMessageFailureHandler, typename BadMessageFailureHandler>
+void TestQmllint::checkResult(const QJsonArray &warnings, const Result &result,
+ ExpectedMessageFailureHandler onExpectedMessageFailures,
+ BadMessageFailureHandler onBadMessageFailures)
+{
+ if (result.flags.testFlag(Result::Flag::NoMessages))
+ QVERIFY2(warnings.isEmpty(), qPrintable(QJsonDocument(warnings).toJson()));
+
+ for (const Message &msg : result.expectedMessages) {
+ // output.contains() expect fails:
+ onExpectedMessageFailures();
+
+ searchWarnings(warnings, msg.text, msg.severity, msg.line, msg.column);
+ }
+
+ for (const Message &msg : result.badMessages) {
+ // !output.contains() expect fails:
+ onBadMessageFailures();
+
+ searchWarnings(warnings, msg.text, msg.severity, msg.line, msg.column, StringNotContained);
+ }
+
+ for (const Message &replacement : result.expectedReplacements) {
+ searchWarnings(warnings, replacement.text, replacement.severity, replacement.line,
+ replacement.column, StringContained, DoReplacementSearch);
+ }
+}
+
+void TestQmllint::searchWarnings(const QJsonArray &warnings, const QString &substring,
+ QtMsgType type, quint32 line, quint32 column,
+ ContainOption shouldContain, ReplacementOption searchReplacements)
+{
+ bool contains = false;
+
+ auto typeStringToMsgType = [](const QString &type) -> QtMsgType {
+ if (type == u"debug")
+ return QtDebugMsg;
+ if (type == u"info")
+ return QtInfoMsg;
+ if (type == u"warning")
+ return QtWarningMsg;
+ if (type == u"critical")
+ return QtCriticalMsg;
+ if (type == u"fatal")
+ return QtFatalMsg;
+
+ Q_UNREACHABLE();
+ };
+
+ for (const QJsonValueConstRef warning : warnings) {
+ QString warningMessage = warning[u"message"].toString();
+ quint32 warningLine = warning[u"line"].toInt();
+ quint32 warningColumn = warning[u"column"].toInt();
+ QtMsgType warningType = typeStringToMsgType(warning[u"type"].toString());
+
+ if (warningMessage.contains(substring)) {
+ if (warningType != type) {
+ continue;
+ }
+ if (line != 0 || column != 0) {
+ if (warningLine != line || warningColumn != column) {
+ continue;
+ }
+ }
+
+ contains = true;
+ break;
+ }
+
+ for (const QJsonValueConstRef fix : warning[u"suggestions"].toArray()) {
+ const QString fixMessage = fix[u"message"].toString();
+ if (fixMessage.contains(substring)) {
+ contains = true;
+ break;
+ }
+
+ if (searchReplacements == DoReplacementSearch) {
+ QString replacement = fix[u"replacement"].toString();
+#ifdef Q_OS_WIN
+ // Replacements can contain native line endings
+ // but we need them to be uniform in order for them to conform to our test data
+ replacement = replacement.replace(u"\r\n"_s, u"\n"_s);
+#endif
+
+ if (replacement.contains(substring)) {
+ quint32 fixLine = fix[u"line"].toInt();
+ quint32 fixColumn = fix[u"column"].toInt();
+ if (line != 0 || column != 0) {
+ if (fixLine != line || fixColumn != column) {
+ continue;
+ }
+ }
+ contains = true;
+ break;
+ }
+ }
+ }
+ }
+
+ const auto toDescription = [](const QJsonArray &warnings, const QString &substring,
+ quint32 line, quint32 column, bool must = true) {
+ QString msg = QStringLiteral("qmllint output:\n%1\nIt %2 contain '%3'")
+ .arg(QString::fromUtf8(
+ QJsonDocument(warnings).toJson(QJsonDocument::Indented)),
+ must ? u"must" : u"must NOT", substring);
+ if (line != 0 || column != 0)
+ msg += u" (%1:%2)"_s.arg(line).arg(column);
+
+ return msg;
+ };
+
+ if (shouldContain == StringContained) {
+ if (!contains)
+ qWarning().noquote() << toDescription(warnings, substring, line, column);
+ QVERIFY(contains);
+ } else {
+ if (contains)
+ qWarning().noquote() << toDescription(warnings, substring, line, column, false);
+ QVERIFY(!contains);
+ }
}
void TestQmllint::requiredProperty()
{
- QVERIFY(runQmllint("requiredProperty.qml", true).isEmpty());
+ runTest("requiredProperty.qml", Result::clean());
+
+ runTest("requiredMissingProperty.qml",
+ Result { { Message { QStringLiteral(
+ "Property \"foo\" was marked as required but does not exist.") } } });
+
+ runTest("requiredPropertyBindings.qml", Result::clean());
+ runTest("requiredPropertyBindingsNow.qml",
+ Result { { Message { QStringLiteral("Component is missing required property "
+ "required_now_string from Base") },
+ Message { QStringLiteral("Component is missing required property "
+ "required_defined_here_string from here") } } });
+ runTest("requiredPropertyBindingsLater.qml",
+ Result { { Message { QStringLiteral("Component is missing required property "
+ "required_later_string from "
+ "Base") },
+ Message { QStringLiteral("Property marked as required in Derived") },
+ Message { QStringLiteral("Component is missing required property "
+ "required_even_later_string "
+ "from Base (marked as required by here)") } } });
+}
+
+void TestQmllint::settingsFile()
+{
+ QVERIFY(runQmllint("settings/unqualifiedSilent/unqualified.qml", true, QStringList(), false)
+ .isEmpty());
+ QVERIFY(runQmllint("settings/unusedImportWarning/unused.qml", false, QStringList(), false)
+ .contains(QStringLiteral("Warning: %1:2:1: Unused import")
+ .arg(testFile("settings/unusedImportWarning/unused.qml"))));
+ QVERIFY(runQmllint("settings/bare/bare.qml", false, {}, false, false)
+ .contains(QStringLiteral("Failed to find the following builtins: "
+ "builtins.qmltypes, jsroot.qmltypes")));
+ QVERIFY(runQmllint("settings/qmltypes/qmltypes.qml", false, QStringList(), false)
+ .contains(QStringLiteral("not a qmldir file. Assuming qmltypes.")));
+ QVERIFY(runQmllint("settings/qmlimports/qmlimports.qml", true, QStringList(), false).isEmpty());
+}
+
+void TestQmllint::additionalImplicitImport()
+{
+ // We're polluting the resource file system here, so let's clean up afterwards.
+ const auto guard = qScopeGuard([this]() {m_linter.clearCache(); });
+ runTest("additionalImplicitImport.qml", Result::clean(), {}, {},
+ { testFile("implicitImportResource.qrc") });
+}
+
+void TestQmllint::qrcUrlImport()
+{
+ const auto guard = qScopeGuard([this]() { m_linter.clearCache(); });
+
+ QJsonArray warnings;
+ callQmllint(testFile("untitled/main.qml"), true, &warnings, {}, {},
+ { testFile("untitled/qrcUrlImport.qrc") });
+ checkResult(warnings, Result::clean());
+}
+
+void TestQmllint::incorrectImportFromHost_data()
+{
+ QTest::addColumn<QString>("filename");
+ QTest::addColumn<Result>("result");
+
+ QTest::newRow("NonexistentFile")
+ << QStringLiteral("importNonexistentFile.qml")
+ << Result{ { Message{
+ QStringLiteral("File or directory you are trying to import does not exist"),
+ 1, 1 } } };
+#ifndef Q_OS_WIN
+ // there is no /dev/null device on Win
+ QTest::newRow("NullDevice")
+ << QStringLiteral("importNullDevice.qml")
+ << Result{ { Message{ QStringLiteral("is neither a file nor a directory. Are sure the "
+ "import path is correct?"),
+ 1, 1 } } };
+#endif
+}
+
+void TestQmllint::incorrectImportFromHost()
+{
+ QFETCH(QString, filename);
+ QFETCH(Result, result);
- const QString errors = runQmllint("requiredMissingProperty.qml", true);
- QVERIFY(errors.contains(QStringLiteral("Property \"foo\" was marked as required but does not exist.")));
+ runTest(filename, result);
}
+void TestQmllint::attachedPropertyReuse()
+{
+ auto categories = QQmlJSLogger::defaultCategories();
+ auto category = std::find_if(categories.begin(), categories.end(), [](const QQmlJS::LoggerCategory& category) {
+ return category.id() == qmlAttachedPropertyReuse;
+ });
+ Q_ASSERT(category != categories.end());
+
+ category->setLevel(QtWarningMsg);
+ category->setIgnored(false);
+ runTest("attachedPropNotReused.qml",
+ Result { { Message { QStringLiteral("Using attached type QQuickKeyNavigationAttached "
+ "already initialized in a parent "
+ "scope") } } },
+ {}, {}, {}, UseDefaultImports, &categories);
+
+ runTest("attachedPropEnum.qml", Result::clean(), {}, {}, {}, UseDefaultImports, &categories);
+ runTest("MyStyle/ToolBar.qml", Result {
+ {
+ Message {
+ "Using attached type MyStyle already initialized in a parent scope"_L1,
+ 10,
+ 16
+ }
+ },
+ {},
+ {
+ Message {
+ "Reference it by id instead"_L1,
+ 10,
+ 16
+ }
+ },
+ Result::AutoFixable
+ });
+}
+
+void TestQmllint::missingBuiltinsNoCrash()
+{
+ // We cannot use the normal linter here since the other tests might have cached the builtins
+ // alread
+ QQmlJSLinter linter(m_defaultImportPaths);
+
+ QJsonArray jsonOutput;
+ QJsonArray warnings;
+
+ bool success = linter.lintFile(testFile("missingBuiltinsNoCrash.qml"), nullptr, true,
+ &jsonOutput, {}, {}, {}, {})
+ == QQmlJSLinter::LintSuccess;
+ QVERIFY2(!success, QJsonDocument(jsonOutput).toJson());
+
+ QVERIFY2(jsonOutput.size() == 1, QJsonDocument(jsonOutput).toJson());
+ warnings = jsonOutput.at(0)[u"warnings"_s].toArray();
+
+ checkResult(warnings,
+ Result { { Message { QStringLiteral("Failed to find the following builtins: "
+ "builtins.qmltypes, jsroot.qmltypes") } } });
+}
+
+void TestQmllint::absolutePath()
+{
+ QString absPathOutput = runQmllint("memberNotFound.qml", false, {}, true, true, true);
+ QString relPathOutput = runQmllint("memberNotFound.qml", false, {}, true, true, false);
+ const QString absolutePath = QFileInfo(testFile("memberNotFound.qml")).absoluteFilePath();
+
+ QVERIFY(absPathOutput.contains(absolutePath));
+ QVERIFY(!relPathOutput.contains(absolutePath));
+}
+
+void TestQmllint::importMultipartUri()
+{
+ runTest("here.qml", Result::clean(), {}, { testFile("Elsewhere/qmldir") });
+}
+
+void TestQmllint::lintModule_data()
+{
+ QTest::addColumn<QString>("module");
+ QTest::addColumn<QStringList>("importPaths");
+ QTest::addColumn<QStringList>("resources");
+ QTest::addColumn<Result>("result");
+
+ QTest::addRow("Things")
+ << u"Things"_s
+ << QStringList()
+ << QStringList()
+ << Result {
+ { Message {
+ u"Type \"QPalette\" not found. Used in SomethingEntirelyStrange.palette"_s,
+ },
+ Message {
+ u"Type \"CustomPalette\" is not fully resolved. Used in SomethingEntirelyStrange.palette2"_s } }
+ };
+ QTest::addRow("missingQmltypes")
+ << u"Fake5Compat.GraphicalEffects.private"_s
+ << QStringList()
+ << QStringList()
+ << Result { { Message { u"QML types file does not exist"_s } } };
+
+ QTest::addRow("moduleWithQrc")
+ << u"moduleWithQrc"_s
+ << QStringList({ testFile("hidden") })
+ << QStringList({
+ testFile("hidden/qmake_moduleWithQrc.qrc"),
+ testFile("hidden/moduleWithQrc_raw_qml_0.qrc")
+ })
+ << Result::clean();
+}
+
+void TestQmllint::lintModule()
+{
+ QFETCH(QString, module);
+ QFETCH(QStringList, importPaths);
+ QFETCH(QStringList, resources);
+ QFETCH(Result, result);
+
+ QJsonArray warnings;
+ callQmllint(module, result.flags & Result::ExitsNormally, &warnings, importPaths, {}, resources,
+ UseDefaultImports, nullptr, false, LintModule);
+ checkResult(warnings, result);
+}
+
+void TestQmllint::testLineEndings()
+{
+ {
+ const auto textWithLF = QString::fromUtf16(u"import QtQuick 2.0\nimport QtTest 2.0 // qmllint disable unused-imports\n"
+ "import QtTest 2.0 // qmllint disable\n\nItem {\n @Deprecated {}\n property string deprecated\n\n "
+ "property string a: root.a // qmllint disable unqualifi77777777777777777777777777777777777777777777777777777"
+ "777777777777777777777777777777777777ed\n property string b: root.a // qmllint di000000000000000000000000"
+ "000000000000000000inyyyyyyyyg c: root.a\n property string d: root.a\n // qmllint enable unqualified\n\n "
+ "//qmllint d 4isable\n property string e: root.a\n Component.onCompleted: {\n console.log"
+ "(deprecated);\n }\n // qmllint enable\n\n}\n");
+
+ const auto lintResult = m_linter.lintFile( {}, &textWithLF, true, nullptr, {}, {}, {}, {});
+
+ QCOMPARE(lintResult, QQmlJSLinter::LintResult::HasWarnings);
+ }
+ {
+ const auto textWithCRLF = QString::fromUtf16(u"import QtQuick 2.0\nimport QtTest 2.0 // qmllint disable unused-imports\n"
+ "import QtTest 2.0 // qmllint disable\n\nItem {\n @Deprecated {}\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r"
+ "\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\n property string deprecated\n\n property string a: root.a "
+ "// qmllint disable unqualifi77777777777777777777777777777777777777777777777777777777777777777777777777777777777777777ed\n "
+ "property string b: root.a // qmllint di000000000000000000000000000000000000000000inyyyyyyyyg c: root.a\n property string d: "
+ "root.a\n // qmllint enable unqualified\n\n //qmllint d 4isable\n property string e: root.a\n Component.onCompleted: "
+ "{\n console.log(deprecated);\n }\n // qmllint enable\n\n}\n");
+
+ const auto lintResult = m_linter.lintFile( {}, &textWithCRLF, true, nullptr, {}, {}, {}, {});
+
+ QCOMPARE(lintResult, QQmlJSLinter::LintResult::HasWarnings);
+ }
+}
+
+void TestQmllint::valueTypesFromString()
+{
+ runTest("valueTypesFromString.qml",
+ Result{ {
+ Message{
+ u"Binding is not supported: Type QSizeF should be constructed using QML_STRUCTURED_VALUE's construction mechanism, instead of a string."_s },
+ Message{
+ u"Binding is not supported: Type QRectF should be constructed using QML_STRUCTURED_VALUE's construction mechanism, instead of a string."_s },
+ Message{
+ u"Binding is not supported: Type QPointF should be constructed using QML_STRUCTURED_VALUE's construction mechanism, instead of a string."_s },
+ },
+ { /*bad messages */ },
+ {
+ Message{ u"({ width: 30, height: 50 })"_s },
+ Message{ u"({ x: 10, y: 20, width: 30, height: 50 })"_s },
+ Message{ u"({ x: 30, y: 50 })"_s },
+ } });
+}
+
+#if QT_CONFIG(library)
+void TestQmllint::testPlugin()
+{
+ bool pluginFound = false;
+ for (const QQmlJSLinter::Plugin &plugin : m_linter.plugins()) {
+ if (plugin.name() == "testPlugin") {
+ pluginFound = true;
+ QCOMPARE(plugin.author(), u"Qt"_s);
+ QCOMPARE(plugin.description(), u"A test plugin for tst_qmllint"_s);
+ QCOMPARE(plugin.version(), u"1.0"_s);
+ break;
+ }
+ }
+ QVERIFY(pluginFound);
+
+ runTest("elementpass_pluginTest.qml", Result { { Message { u"ElementTest OK"_s, 4, 5 } } });
+ runTest("propertypass_pluginTest.qml",
+ Result {
+ { // Specific binding for specific property
+ Message {
+ u"Saw binding on Text property text with value NULL (and type 3) in scope Text"_s },
+
+ // Property on any type
+ Message { u"Saw read on Text property x in scope Text"_s },
+ Message {
+ u"Saw binding on Text property x with value NULL (and type 2) in scope Text"_s },
+ Message { u"Saw read on Text property x in scope Item"_s },
+ Message { u"Saw write on Text property x with value int in scope Item"_s },
+ Message {
+ u"Saw binding on Item property x with value NULL (and type 2) in scope Item"_s },
+ // ListModel
+ Message {
+ u"Saw binding on ListView property model with value ListModel (and type 8) in scope ListView"_s },
+ Message {
+ u"Saw binding on ListView property height with value NULL (and type 2) in scope ListView"_s } } });
+ runTest("controlsWithQuick_pluginTest.qml",
+ Result { { Message { u"QtQuick.Controls, QtQuick and QtQuick.Window present"_s } } });
+ runTest("controlsWithoutQuick_pluginTest.qml",
+ Result { { Message { u"QtQuick.Controls and NO QtQuick present"_s } } });
+ // Verify that none of the passes do anything when they're not supposed to
+ runTest("nothing_pluginTest.qml", Result::clean());
+
+ QVERIFY(runQmllint("settings/plugin/elemenpass_pluginSettingTest.qml", true, QStringList(), false)
+ .isEmpty());
+}
+
+// TODO: Eventually tests for (real) plugins need to be moved into a separate file
+void TestQmllint::quickPlugin()
+{
+ const auto &plugins = m_linter.plugins();
+
+ const bool pluginFound =
+ std::find_if(plugins.cbegin(), plugins.cend(),
+ [](const auto &plugin) { return plugin.name() == "Quick"; })
+ != plugins.cend();
+ QVERIFY(pluginFound);
+
+ runTest("pluginQuick_anchors.qml",
+ Result{ { Message{
+ u"Cannot specify left, right, and horizontalCenter anchors at the same time."_s },
+ Message {
+ u"Cannot specify top, bottom, and verticalCenter anchors at the same time."_s },
+ Message{
+ u"Baseline anchor cannot be used in conjunction with top, bottom, or verticalCenter anchors."_s },
+ Message { u"Cannot assign literal of type null to QQuickAnchorLine"_s, 5,
+ 35 },
+ Message { u"Cannot assign literal of type null to QQuickAnchorLine"_s, 6,
+ 33 } } });
+ runTest("pluginQuick_anchorsUndefined.qml", Result::clean());
+ runTest("pluginQuick_layoutChildren.qml",
+ Result {
+ { Message {
+ u"Detected anchors on an item that is managed by a layout. This is undefined behavior; use Layout.alignment instead."_s },
+ Message {
+ u"Detected x on an item that is managed by a layout. This is undefined behavior; use Layout.leftMargin or Layout.rightMargin instead."_s },
+ Message {
+ u"Detected y on an item that is managed by a layout. This is undefined behavior; use Layout.topMargin or Layout.bottomMargin instead."_s },
+ Message {
+ u"Detected height on an item that is managed by a layout. This is undefined behavior; use implictHeight or Layout.preferredHeight instead."_s },
+ Message {
+ u"Detected width on an item that is managed by a layout. This is undefined behavior; use implicitWidth or Layout.preferredWidth instead."_s },
+ Message {
+ u"Cannot specify anchors for items inside Grid. Grid will not function."_s },
+ Message {
+ u"Cannot specify x for items inside Grid. Grid will not function."_s },
+ Message {
+ u"Cannot specify y for items inside Grid. Grid will not function."_s },
+ Message {
+ u"Cannot specify anchors for items inside Flow. Flow will not function."_s },
+ Message {
+ u"Cannot specify x for items inside Flow. Flow will not function."_s },
+ Message {
+ u"Cannot specify y for items inside Flow. Flow will not function."_s } } });
+ runTest("pluginQuick_attached.qml",
+ Result {
+ { Message { u"ToolTip must be attached to an Item"_s },
+ Message { u"SplitView attached property only works with Items"_s },
+ Message { u"ScrollIndicator must be attached to a Flickable"_s },
+ Message { u"ScrollBar must be attached to a Flickable or ScrollView"_s },
+ Message { u"Accessible must be attached to an Item"_s },
+ Message { u"EnterKey attached property only works with Items"_s },
+ Message {
+ u"LayoutDirection attached property only works with Items and Windows"_s },
+ Message { u"Layout must be attached to Item elements"_s },
+ Message { u"StackView attached property only works with Items"_s },
+ Message { u"TextArea must be attached to a Flickable"_s },
+ Message { u"StackLayout must be attached to an Item"_s },
+ Message {
+ u"Tumbler: attached properties of Tumbler must be accessed through a delegate item"_s },
+ Message {
+ u"Attached properties of SwipeDelegate must be accessed through an Item"_s },
+ Message { u"SwipeView must be attached to an Item"_s } } });
+
+ runTest("pluginQuick_swipeDelegate.qml",
+ Result { {
+ Message {
+ u"SwipeDelegate: Cannot use horizontal anchors with contentItem; unable to layout the item."_s,
+ 6, 43 },
+ Message {
+ u"SwipeDelegate: Cannot use horizontal anchors with background; unable to layout the item."_s,
+ 7, 43 },
+ Message { u"SwipeDelegate: Cannot set both behind and left/right properties"_s,
+ 9, 9 },
+ Message {
+ u"SwipeDelegate: Cannot use horizontal anchors with contentItem; unable to layout the item."_s,
+ 13, 47 },
+ Message {
+ u"SwipeDelegate: Cannot use horizontal anchors with background; unable to layout the item."_s,
+ 14, 42 },
+ Message { u"SwipeDelegate: Cannot set both behind and left/right properties"_s,
+ 16, 9 },
+ } });
+
+ runTest("pluginQuick_varProp.qml",
+ Result {
+ { Message {
+ u"Unexpected type for property \"contentItem\" expected QQuickPathView, QQuickListView got QQuickItem"_s },
+ Message {
+ u"Unexpected type for property \"columnWidthProvider\" expected function got null"_s },
+ Message {
+ u"Unexpected type for property \"textFromValue\" expected function got null"_s },
+ Message {
+ u"Unexpected type for property \"valueFromText\" expected function got int"_s },
+ Message {
+ u"Unexpected type for property \"rowHeightProvider\" expected function got int"_s } } });
+ runTest("pluginQuick_varPropClean.qml", Result::clean());
+ runTest("pluginQuick_attachedClean.qml", Result::clean());
+ runTest("pluginQuick_attachedIgnore.qml", Result::clean());
+ runTest("pluginQuick_noCrashOnUneresolved.qml", Result {}); // we don't care about the specific warnings
+
+ runTest("pluginQuick_propertyChangesParsed.qml",
+ Result { {
+ Message {
+ u"Property \"myColor\" is custom-parsed in PropertyChanges. "
+ "You should phrase this binding as \"foo.myColor: Qt.rgba(0.5, ...\""_s,
+ 12, 30
+ },
+ Message {
+ u"You should remove any bindings on the \"target\" property and avoid "
+ "custom-parsed bindings in PropertyChanges."_s,
+ 11, 29
+ },
+ Message {
+ u"Unknown property \"notThere\" in PropertyChanges."_s,
+ 13, 31
+ }
+ } });
+ runTest("pluginQuick_propertyChangesInvalidTarget.qml", Result {}); // we don't care about the specific warnings
+}
+
+void TestQmllint::environment_data()
+{
+ QTest::addColumn<QString>("file");
+ QTest::addColumn<bool>("shouldSucceed");
+ QTest::addColumn<QStringList>("extraArgs");
+ QTest::addColumn<Environment>("env");
+ QTest::addColumn<QString>("expectedWarning");
+
+ const QString fileThatNeedsImportPath = testFile(u"NeedImportPath.qml"_s);
+ const QString importPath = testFile(u"ImportPath"_s);
+ const QString invalidImportPath = testFile(u"ImportPathThatDoesNotExist"_s);
+ const QString noWarningExpected;
+
+ QTest::addRow("missing-import-dir")
+ << fileThatNeedsImportPath << false << QStringList{}
+ << Environment{ { u"QML_IMPORT_PATH"_s, importPath } } << noWarningExpected;
+
+ QTest::addRow("import-dir-via-arg")
+ << fileThatNeedsImportPath << true << QStringList{ u"-I"_s, importPath }
+ << Environment{ { u"QML_IMPORT_PATH"_s, invalidImportPath } } << noWarningExpected;
+
+ QTest::addRow("import-dir-via-env")
+ << fileThatNeedsImportPath << true << QStringList{ u"-E"_s }
+ << Environment{ { u"QML_IMPORT_PATH"_s, importPath } }
+ << u"Using import directories passed from environment variable \"QML_IMPORT_PATH\": \"%1\"."_s
+ .arg(importPath);
+
+ QTest::addRow("import-dir-via-env2")
+ << fileThatNeedsImportPath << true << QStringList{ u"-E"_s }
+ << Environment{ { u"QML2_IMPORT_PATH"_s, importPath } }
+ << u"Using import directories passed from the deprecated environment variable \"QML2_IMPORT_PATH\": \"%1\"."_s
+ .arg(importPath);
+}
+
+void TestQmllint::environment()
+{
+ QFETCH(QString, file);
+ QFETCH(bool, shouldSucceed);
+ QFETCH(QStringList, extraArgs);
+ QFETCH(Environment, env);
+ QFETCH(QString, expectedWarning);
+
+ const QString output = runQmllint(file, shouldSucceed, extraArgs, false, true, false, env);
+ if (!expectedWarning.isEmpty()) {
+ QVERIFY(output.contains(expectedWarning));
+ }
+}
+
+#endif
+
+void TestQmllint::ignoreSettingsNotCommandLineOptions()
+{
+ const QString importPath = testFile(u"ImportPath"_s);
+ // makes sure that ignore settings only ignores settings and not command line options like
+ // "-I".
+ const QString output = runQmllint(testFile(u"NeedImportPath.qml"_s), true,
+ QStringList{ u"-I"_s, importPath }, true);
+ // should not complain about not finding the module that is in importPath
+ QCOMPARE(output, QString());
+}
-QTEST_MAIN(TestQmllint)
+QTEST_GUILESS_MAIN(TestQmllint)
#include "tst_qmllint.moc"