diff options
19 files changed, 182 insertions, 36 deletions
diff --git a/src/imports/tooling/Enum.qml b/src/imports/tooling/Enum.qml index 9fcdfb4a5e..04276fdeed 100644 --- a/src/imports/tooling/Enum.qml +++ b/src/imports/tooling/Enum.qml @@ -7,5 +7,6 @@ Member { property string alias property string type property bool isFlag: false + property bool isScoped: false property var values: [] } diff --git a/src/qmlcompiler/qqmljsimportvisitor.cpp b/src/qmlcompiler/qqmljsimportvisitor.cpp index 9c7d498b11..f2d22a4448 100644 --- a/src/qmlcompiler/qqmljsimportvisitor.cpp +++ b/src/qmlcompiler/qqmljsimportvisitor.cpp @@ -2256,6 +2256,7 @@ bool QQmlJSImportVisitor::visit(QQmlJS::AST::UiEnumDeclaration *uied) uied->firstSourceLocation()); } QQmlJSMetaEnum qmlEnum(uied->name.toString()); + qmlEnum.setIsQml(true); for (const auto *member = uied->members; member; member = member->next) { qmlEnum.addKey(member->member.toString()); qmlEnum.addValue(int(member->value)); diff --git a/src/qmlcompiler/qqmljsmetatypes_p.h b/src/qmlcompiler/qqmljsmetatypes_p.h index 22dcf2eabe..215c979f79 100644 --- a/src/qmlcompiler/qqmljsmetatypes_p.h +++ b/src/qmlcompiler/qqmljsmetatypes_p.h @@ -59,7 +59,8 @@ class QQmlJSMetaEnum QString m_typeName; QSharedPointer<const QQmlJSScope> m_type; bool m_isFlag = false; - bool m_scoped = true; + bool m_isScoped = false; + bool m_isQml = false; public: QQmlJSMetaEnum() = default; @@ -76,8 +77,11 @@ public: bool isFlag() const { return m_isFlag; } void setIsFlag(bool isFlag) { m_isFlag = isFlag; } - bool isScoped() const { return m_scoped; } - void setScoped(bool v) { m_scoped = v; } + bool isScoped() const { return m_isScoped; } + void setIsScoped(bool v) { m_isScoped = v; } + + bool isQml() const { return m_isQml; } + void setIsQml(bool v) { m_isQml = v; } void addKey(const QString &key) { m_keys.append(key); } QStringList keys() const { return m_keys; } @@ -102,7 +106,8 @@ public: && a.m_name == b.m_name && a.m_alias == b.m_alias && a.m_isFlag == b.m_isFlag - && a.m_type == b.m_type; + && a.m_type == b.m_type + && a.m_isScoped == b.m_isScoped; } friend bool operator!=(const QQmlJSMetaEnum &a, const QQmlJSMetaEnum &b) @@ -112,7 +117,8 @@ public: friend size_t qHash(const QQmlJSMetaEnum &e, size_t seed = 0) { - return qHashMulti(seed, e.m_keys, e.m_values, e.m_name, e.m_alias, e.m_isFlag, e.m_type); + return qHashMulti( + seed, e.m_keys, e.m_values, e.m_name, e.m_alias, e.m_isFlag, e.m_type, e.m_isScoped); } }; diff --git a/src/qmlcompiler/qqmljstypedescriptionreader.cpp b/src/qmlcompiler/qqmljstypedescriptionreader.cpp index 66bf8791e2..7e87a66765 100644 --- a/src/qmlcompiler/qqmljstypedescriptionreader.cpp +++ b/src/qmlcompiler/qqmljstypedescriptionreader.cpp @@ -427,13 +427,13 @@ void QQmlJSTypeDescriptionReader::readEnum(UiObjectDefinition *ast, const QQmlJS metaEnum.setIsFlag(readBoolBinding(script)); } else if (name == QLatin1String("values")) { readEnumValues(script, &metaEnum); - } else if (name == QLatin1String("scoped")) { - metaEnum.setScoped(readBoolBinding(script)); + } else if (name == QLatin1String("isScoped")) { + metaEnum.setIsScoped(readBoolBinding(script)); } else if (name == QLatin1String("type")) { metaEnum.setTypeName(readStringBinding(script)); } else { addWarning(script->firstSourceLocation(), - tr("Expected only name, alias, isFlag, values, scoped, or type.")); + tr("Expected only name, alias, isFlag, values, isScoped, or type.")); } } diff --git a/src/qmlcompiler/qqmljstypepropagator.cpp b/src/qmlcompiler/qqmljstypepropagator.cpp index 7ba6b0eba4..fa29c305bd 100644 --- a/src/qmlcompiler/qqmljstypepropagator.cpp +++ b/src/qmlcompiler/qqmljstypepropagator.cpp @@ -675,24 +675,32 @@ void QQmlJSTypePropagator::generate_StoreNameStrict(int name) } bool QQmlJSTypePropagator::checkForEnumProblems( - const QQmlJSRegisterContent &base, const QString &propertyName) const + const QQmlJSRegisterContent &base, const QString &propertyName) { if (base.isEnumeration()) { const auto metaEn = base.enumeration(); - if (!metaEn.isScoped()) { - m_logger->log(u"You cannot access unscoped enum \"%1\" from here."_s.arg(propertyName), - qmlRestrictedType, getCurrentSourceLocation()); - return true; - } else if (!metaEn.hasKey(propertyName)) { + if (!metaEn.hasKey(propertyName)) { auto fixSuggestion = QQmlJSUtils::didYouMean(propertyName, metaEn.keys(), getCurrentSourceLocation()); - m_logger->log(u"\"%1\" is not an entry of enum \"%2\"."_s.arg(propertyName) - .arg(metaEn.name()), - qmlMissingEnumEntry, getCurrentSourceLocation(), true, true, - fixSuggestion); + const QString error = u"\"%1\" is not an entry of enum \"%2\"."_s + .arg(propertyName, metaEn.name()); + setError(error); + m_logger->log( + error, qmlMissingEnumEntry, getCurrentSourceLocation(), true, true, + fixSuggestion); + return true; + } + } else if (base.variant() == QQmlJSRegisterContent::MetaType) { + const QQmlJSMetaEnum metaEn = base.scopeType()->enumeration(propertyName); + if (metaEn.isValid() && !metaEn.isScoped() && !metaEn.isQml()) { + const QString error + = u"You cannot access unscoped enum \"%1\" from here."_s.arg(propertyName); + setError(error); + m_logger->log(error, qmlRestrictedType, getCurrentSourceLocation()); return true; } } + return false; } @@ -818,10 +826,10 @@ void QQmlJSTypePropagator::propagatePropertyLookup(const QString &propertyName, } } - if (checkForEnumProblems(m_state.accumulatorIn(), propertyName)) - return; - if (!m_state.accumulatorOut().isValid()) { + if (checkForEnumProblems(m_state.accumulatorIn(), propertyName)) + return; + setError(u"Cannot load property %1 from %2."_s .arg(propertyName, m_state.accumulatorIn().descriptiveName())); diff --git a/src/qmlcompiler/qqmljstypepropagator_p.h b/src/qmlcompiler/qqmljstypepropagator_p.h index d2e1b4e8f9..b4ce021be3 100644 --- a/src/qmlcompiler/qqmljstypepropagator_p.h +++ b/src/qmlcompiler/qqmljstypepropagator_p.h @@ -168,7 +168,7 @@ struct Q_QMLCOMPILER_EXPORT QQmlJSTypePropagator : public QQmlJSCompilePass void generate_ThrowOnNullOrUndefined() override; void generate_GetTemplateObject(int index) override; - bool checkForEnumProblems(const QQmlJSRegisterContent &base, const QString &propertyName) const; + bool checkForEnumProblems(const QQmlJSRegisterContent &base, const QString &propertyName); Verdict startInstruction(QV4::Moth::Instr::Type instr) override; void endInstruction(QV4::Moth::Instr::Type instr) override; diff --git a/src/qmlcompiler/qqmljstyperesolver.cpp b/src/qmlcompiler/qqmljstyperesolver.cpp index c325208152..14f4436eac 100644 --- a/src/qmlcompiler/qqmljstyperesolver.cpp +++ b/src/qmlcompiler/qqmljstyperesolver.cpp @@ -1101,7 +1101,7 @@ bool QQmlJSTypeResolver::checkEnums(const QQmlJSScope::ConstPtr &scope, const QS const auto enums = scope->ownEnumerations(); for (const auto &enumeration : enums) { - if (enumeration.name() == name) { + if ((enumeration.isScoped() || enumeration.isQml()) && enumeration.name() == name) { *result = QQmlJSRegisterContent::create( storedType(enumeration.type()), enumeration, QString(), inExtension ? QQmlJSRegisterContent::ExtensionObjectEnum @@ -1110,7 +1110,7 @@ bool QQmlJSTypeResolver::checkEnums(const QQmlJSScope::ConstPtr &scope, const QS return true; } - if (enumeration.hasKey(name)) { + if (!enumeration.isScoped() && enumeration.hasKey(name)) { *result = QQmlJSRegisterContent::create( storedType(enumeration.type()), enumeration, name, inExtension ? QQmlJSRegisterContent::ExtensionObjectEnum diff --git a/src/qmltyperegistrar/qqmltyperegistrarconstants_p.h b/src/qmltyperegistrar/qqmltyperegistrarconstants_p.h index 7b7d12d67a..2422962248 100644 --- a/src/qmltyperegistrar/qqmltyperegistrarconstants_p.h +++ b/src/qmltyperegistrar/qqmltyperegistrarconstants_p.h @@ -53,6 +53,7 @@ static constexpr QLatin1StringView S_IS_LIST { "isList" }; static constexpr QLatin1StringView S_IS_POINTER { "isPointer" }; static constexpr QLatin1StringView S_IS_READONLY { "isReadonly" }; static constexpr QLatin1StringView S_IS_REQUIRED { "isRequired" }; +static constexpr QLatin1StringView S_IS_SCOPED { "isScoped" }; static constexpr QLatin1StringView S_IS_SINGLETON { "isSingleton" }; static constexpr QLatin1StringView S_METHOD { "Method" }; static constexpr QLatin1StringView S_MODULE { "Module" }; @@ -101,6 +102,7 @@ static constexpr QLatin1StringView S_IMMEDIATE_PROPERTY_NAMES { "ImmediatePr static constexpr QLatin1StringView S_INDEX { "index" }; static constexpr QLatin1StringView S_INPUT_FILE { "inputFile" }; static constexpr QLatin1StringView S_INTERFACES { "interfaces" }; +static constexpr QLatin1StringView S_IS_CLASS { "isClass" }; static constexpr QLatin1StringView S_IS_CLONED { "isCloned" }; static constexpr QLatin1StringView S_IS_CONSTRUCTOR { "isConstructor" }; static constexpr QLatin1StringView S_IS_FLAG { "isFlag" }; @@ -119,6 +121,11 @@ static constexpr QLatin1StringView S_PROPERTY { "property" } static constexpr QLatin1StringView S_PUBLIC { "public" }; static constexpr QLatin1StringView S_QUALIFIED_CLASS_NAME { "qualifiedClassName" }; static constexpr QLatin1StringView S_READ { "read" }; + +static constexpr QLatin1StringView S_REGISTER_ENUM_CLASSES_UNSCOPED { + "RegisterEnumClassesUnscoped" +}; + static constexpr QLatin1StringView S_REQUIRED { "required" }; static constexpr QLatin1StringView S_RESET { "reset" }; static constexpr QLatin1StringView S_RETURN_TYPE { "returnType" }; diff --git a/src/qmltyperegistrar/qqmltypesclassdescription.cpp b/src/qmltyperegistrar/qqmltypesclassdescription.cpp index 8d58647096..5d3a30483a 100644 --- a/src/qmltyperegistrar/qqmltypesclassdescription.cpp +++ b/src/qmltyperegistrar/qqmltypesclassdescription.cpp @@ -184,10 +184,13 @@ void QmlTypesClassDescription::collectLocalAnonymous( const auto classInfos = classDef.value(S_CLASS_INFOS).toArray(); for (const QCborValue &classInfo : classInfos) { const QCborMap obj = classInfo.toMap(); - if (obj[S_NAME] == S_DEFAULT_PROPERTY) + const QCborValue name = obj[S_NAME]; + if (name == S_DEFAULT_PROPERTY) defaultProp = toStringView(obj, S_VALUE); - if (obj[S_NAME] == S_PARENT_PROPERTY) + else if (name == S_PARENT_PROPERTY) parentProp = toStringView(obj, S_VALUE); + else if (name == S_REGISTER_ENUM_CLASSES_UNSCOPED && toStringView(obj, S_VALUE) == S_FALSE) + registerEnumClassesScoped = true; } collectInterfaces(classDef); @@ -225,6 +228,12 @@ void QmlTypesClassDescription::collect( continue; } + if (name == S_REGISTER_ENUM_CLASSES_UNSCOPED) { + if (mode != RelatedType && value == S_FALSE) + registerEnumClassesScoped = true; + continue; + } + if (name == S_ADDED_IN_VERSION) { const QTypeRevision revision = handleInMinorVersion( QTypeRevision::fromEncodedVersion(toInt(value)), @@ -318,10 +327,12 @@ void QmlTypesClassDescription::collect( if (const FoundType found = findType(foreign, types, foreignTypeName, namespaces)) { resolved = found.select(classDef, "Foreign"); - // Default properties are always local. + // Default properties and enum classes are always local. defaultProp = {}; + registerEnumClassesScoped = false; - // Foreign type can have a default property or an attached types + // Foreign type can have a default property or an attached type, + // or RegisterEnumClassesUnscoped classinfo. const auto classInfos = resolved.value(S_CLASS_INFOS).toArray(); for (const QCborValue &classInfo : classInfos) { const QCborMap obj = classInfo.toMap(); @@ -331,6 +342,9 @@ void QmlTypesClassDescription::collect( defaultProp = foreignValue; } else if (parentProp.isEmpty() && foreignName == S_PARENT_PROPERTY) { parentProp = foreignValue; + } else if (foreignName == S_REGISTER_ENUM_CLASSES_UNSCOPED) { + if (foreignValue == S_FALSE) + registerEnumClassesScoped = true; } else if (foreignName == S_ATTACHED) { if (const FoundType attached = collectRelated( foreignValue, types, foreign, defaultRevision, namespaces)) { diff --git a/src/qmltyperegistrar/qqmltypesclassdescription_p.h b/src/qmltyperegistrar/qqmltypesclassdescription_p.h index 7eb51be44e..ba02a135dd 100644 --- a/src/qmltyperegistrar/qqmltypesclassdescription_p.h +++ b/src/qmltyperegistrar/qqmltypesclassdescription_p.h @@ -73,6 +73,7 @@ struct QmlTypesClassDescription bool omitFromQmlTypes = false; bool extensionIsJavaScript = false; bool extensionIsNamespace = false; + bool registerEnumClassesScoped = false; QList<QAnyStringView> implementsInterfaces; QList<QAnyStringView> deferredNames; QList<QAnyStringView> immediateNames; diff --git a/src/qmltyperegistrar/qqmltypescreator.cpp b/src/qmltyperegistrar/qqmltypescreator.cpp index e2d71b4f9b..ed55d3d6d5 100644 --- a/src/qmltyperegistrar/qqmltypescreator.cpp +++ b/src/qmltyperegistrar/qqmltypescreator.cpp @@ -341,7 +341,8 @@ void QmlTypesCreator::writeMethods(const QCborArray &methods, QLatin1StringView } } -void QmlTypesCreator::writeEnums(const QCborArray &enums) +void QmlTypesCreator::writeEnums( + const QCborArray &enums, QmlTypesCreator::EnumClassesMode enumClassesMode) { for (const QCborValue &item : enums) { const QCborMap obj = item.toMap(); @@ -359,6 +360,13 @@ void QmlTypesCreator::writeEnums(const QCborArray &enums) auto isFlag = obj.find(MetatypesDotJson::S_IS_FLAG); if (isFlag != obj.end() && isFlag->toBool()) m_qml.writeBooleanBinding(S_IS_FLAG, true); + + if (enumClassesMode == EnumClassesMode::Scoped) { + const auto isClass = obj.find(MetatypesDotJson::S_IS_CLASS); + if (isClass != obj.end() && isClass->toBool()) + m_qml.writeBooleanBinding(S_IS_SCOPED, true); + } + writeType(obj, MetatypesDotJson::S_TYPE); m_qml.writeStringListBinding(S_VALUES, valueList); m_qml.writeEndObject(); @@ -425,7 +433,11 @@ void QmlTypesCreator::writeComponents() writeClassProperties(collector); if (const QCborMap &classDef = collector.resolvedClass; !classDef.isEmpty()) { - writeEnums(members(classDef, MetatypesDotJson::S_ENUMS, m_version)); + writeEnums( + members(classDef, MetatypesDotJson::S_ENUMS, m_version), + collector.registerEnumClassesScoped + ? EnumClassesMode::Scoped + : EnumClassesMode::Unscoped); writeProperties(members(classDef, MetatypesDotJson::S_PROPERTIES, m_version)); @@ -452,7 +464,11 @@ void QmlTypesCreator::writeComponents() collector.collectLocalAnonymous(component, m_ownTypes, m_foreignTypes, m_version); writeClassProperties(collector); - writeEnums(members(component, MetatypesDotJson::S_ENUMS, m_version)); + writeEnums( + members(component, MetatypesDotJson::S_ENUMS, m_version), + collector.registerEnumClassesScoped + ? EnumClassesMode::Scoped + : EnumClassesMode::Unscoped); writeProperties(members(component, MetatypesDotJson::S_PROPERTIES, m_version)); diff --git a/src/qmltyperegistrar/qqmltypescreator_p.h b/src/qmltyperegistrar/qqmltypescreator_p.h index 5d303b24a7..af2ffdf7dd 100644 --- a/src/qmltyperegistrar/qqmltypescreator_p.h +++ b/src/qmltyperegistrar/qqmltypescreator_p.h @@ -41,7 +41,10 @@ private: void writeType(const QCborMap &property, QLatin1StringView key); void writeProperties(const QCborArray &properties); void writeMethods(const QCborArray &methods, QLatin1StringView type); - void writeEnums(const QCborArray &enums); + + enum class EnumClassesMode { Scoped, Unscoped }; + void writeEnums(const QCborArray &enums, EnumClassesMode enumClassesMode); + void writeComponents(); QByteArray m_output; diff --git a/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt b/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt index 1149f4373e..69d1217544 100644 --- a/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt +++ b/tests/auto/qml/qmlcppcodegen/data/CMakeLists.txt @@ -235,6 +235,7 @@ set(qml_files revisions.qml scopeIdLookup.qml scopeVsObject.qml + scopedEnum.qml script.js script.mjs sequenceToIterable.qml diff --git a/tests/auto/qml/qmlcppcodegen/data/enumproblems.h b/tests/auto/qml/qmlcppcodegen/data/enumproblems.h index f640b1fc1c..36f97bec5a 100644 --- a/tests/auto/qml/qmlcppcodegen/data/enumproblems.h +++ b/tests/auto/qml/qmlcppcodegen/data/enumproblems.h @@ -82,4 +82,38 @@ public: Q_FLAG(Option) }; +class ScopedEnum : public QObject { + Q_OBJECT + QML_NAMED_ELEMENT(Data) + Q_CLASSINFO("RegisterEnumClassesUnscoped", "false") + +public: + enum class DType { + A = 27, B + }; + Q_ENUM(DType) + + enum EType { + C = 7, D + }; + Q_ENUM(EType) +}; + +class UnscopedEnum : public QObject { + Q_OBJECT + QML_NAMED_ELEMENT(Data2) + Q_CLASSINFO("RegisterEnumClassesUnscoped", "true") + +public: + enum class DType { + A = 26, B + }; + Q_ENUM(DType) + + enum EType { + C = 6, D + }; + Q_ENUM(EType) +}; + #endif // ENUMPROBLEMS_H diff --git a/tests/auto/qml/qmlcppcodegen/data/scopedEnum.qml b/tests/auto/qml/qmlcppcodegen/data/scopedEnum.qml new file mode 100644 index 0000000000..8b9f161b06 --- /dev/null +++ b/tests/auto/qml/qmlcppcodegen/data/scopedEnum.qml @@ -0,0 +1,19 @@ +import QtQml +import TestTypes + +QtObject { + property int good: Data.DType.A + property int bad: Data.A + + property int wrong: Data.EType.C + property int right: Data.C + + property int notgood: Data2.DType.A + property int notbad: Data2.A + + property int notwrong: Data2.EType.C + property int notright: Data2.C + + property int passable: Enums.AppState.Blue + property int wild: Enums.Green +} diff --git a/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp b/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp index 9363172a0e..da8652acf5 100644 --- a/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp +++ b/tests/auto/qml/qmlcppcodegen/tst_qmlcppcodegen.cpp @@ -203,6 +203,7 @@ private slots: void scopeIdLookup(); void scopeObjectDestruction(); void scopeVsObject(); + void scopedEnum(); void sequenceToIterable(); void setLookupConversion(); void setLookupOriginalScope(); @@ -4125,6 +4126,39 @@ void tst_QmlCppCodegen::scopeVsObject() QCOMPARE(object->property("objectName").toString(), u"foobar"_s); } +void tst_QmlCppCodegen::scopedEnum() +{ + QQmlEngine engine; + const QString url = u"qrc:/qt/qml/TestTypes/scopedEnum.qml"_s; + QQmlComponent component(&engine, QUrl(url)); + QVERIFY2(!component.isError(), component.errorString().toUtf8()); + + QTest::ignoreMessage( + QtWarningMsg, + qPrintable(url + u":6:5: Unable to assign [undefined] to int"_s)); + QTest::ignoreMessage( + QtWarningMsg, + qPrintable(url + u":8: TypeError: Cannot read property 'C' of undefined"_s)); + QTest::ignoreMessage( + QtWarningMsg, + qPrintable(url + u":14: TypeError: Cannot read property 'C' of undefined"_s)); + + QScopedPointer<QObject> object(component.create()); + QVERIFY(!object.isNull()); + QCOMPARE(object->property("good").toInt(), 27); + QCOMPARE(object->property("bad").toInt(), 0); + QCOMPARE(object->property("wrong").toInt(), 0); + QCOMPARE(object->property("right").toInt(), 7); + + QCOMPARE(object->property("notgood").toInt(), 26); + QCOMPARE(object->property("notbad").toInt(), 26); + QCOMPARE(object->property("notwrong").toInt(), 0); + QCOMPARE(object->property("notright").toInt(), 6); + + QCOMPARE(object->property("passable").toInt(), 2); + QCOMPARE(object->property("wild").toInt(), 1); +} + void tst_QmlCppCodegen::sequenceToIterable() { QQmlEngine engine; diff --git a/tests/auto/qml/qmllint/data/Things/plugins.qmltypes b/tests/auto/qml/qmllint/data/Things/plugins.qmltypes index 45a6af32ab..453e81d57a 100644 --- a/tests/auto/qml/qmllint/data/Things/plugins.qmltypes +++ b/tests/auto/qml/qmllint/data/Things/plugins.qmltypes @@ -12,6 +12,7 @@ Module { exports: ["Things/SomethingEntirelyStrange 1.0"] Enum { name: "AnEnum" + isScoped: true values: { "AAA": 0, "BBB": 1, @@ -20,7 +21,7 @@ Module { } Enum { name: "TheEnum" - scoped: false + isScoped: false values: { "V1": 0, "V2": 1 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/tst_qmllint.cpp b/tests/auto/qml/qmllint/tst_qmllint.cpp index 753a4d3af9..9929d0c850 100644 --- a/tests/auto/qml/qmllint/tst_qmllint.cpp +++ b/tests/auto/qml/qmllint/tst_qmllint.cpp @@ -1060,8 +1060,8 @@ expression: \${expr} \${expr} \\\${expr} \\\${expr}`)", QTest::newRow("NotScopedEnumCpp") << QStringLiteral("NotScopedEnumCpp.qml") << Result{ { Message{ - QStringLiteral("You cannot access unscoped enum \"V1\" from here."), 5, - 57 } } }; + QStringLiteral("You cannot access unscoped enum \"TheEnum\" from here."), 5, + 49 } } }; QTest::newRow("unresolvedArrayBinding") << QStringLiteral("unresolvedArrayBinding.qml") |