30QQmlJSTypeResolver::QQmlJSTypeResolver(QQmlJSImporter *importer)
31 : m_pool(std::make_unique<QQmlJSRegisterContentPool>())
32 , m_imports(importer->builtinInternalNames())
34 const QQmlJSImporter::ImportedTypes &builtinTypes = m_imports;
36 m_voidType = builtinTypes.type(u"void"_s).scope;
37 assertExtension(m_voidType,
"undefined"_L1);
39 m_nullType = builtinTypes.type(u"std::nullptr_t"_s).scope;
42 m_realType = builtinTypes.type(u"double"_s).scope;
43 assertExtension(m_realType,
"Number"_L1);
45 m_floatType = builtinTypes.type(u"float"_s).scope;
46 assertExtension(m_floatType,
"Number"_L1);
48 m_int8Type = builtinTypes.type(u"qint8"_s).scope;
49 assertExtension(m_int8Type,
"Number"_L1);
51 m_uint8Type = builtinTypes.type(u"quint8"_s).scope;
52 assertExtension(m_uint8Type,
"Number"_L1);
54 m_int16Type = builtinTypes.type(u"short"_s).scope;
55 assertExtension(m_int16Type,
"Number"_L1);
57 m_uint16Type = builtinTypes.type(u"ushort"_s).scope;
58 assertExtension(m_uint16Type,
"Number"_L1);
60 m_int32Type = builtinTypes.type(u"int"_s).scope;
61 assertExtension(m_int32Type,
"Number"_L1);
63 m_uint32Type = builtinTypes.type(u"uint"_s).scope;
64 assertExtension(m_uint32Type,
"Number"_L1);
66 m_int64Type = builtinTypes.type(u"qlonglong"_s).scope;
67 Q_ASSERT(m_int64Type);
69 m_uint64Type = builtinTypes.type(u"qulonglong"_s).scope;
70 Q_ASSERT(m_uint64Type);
72 m_sizeType = builtinTypes.type(u"qsizetype"_s).scope;
73 assertExtension(m_sizeType,
"Number"_L1);
76 Q_ASSERT(m_sizeType == m_int32Type || m_sizeType == m_int64Type);
78 m_boolType = builtinTypes.type(u"bool"_s).scope;
79 assertExtension(m_boolType,
"Boolean"_L1);
81 m_stringType = builtinTypes.type(u"QString"_s).scope;
82 assertExtension(m_stringType,
"String"_L1);
84 m_stringListType = builtinTypes.type(u"QStringList"_s).scope;
85 assertExtension(m_stringListType,
"Array"_L1);
87 m_byteArrayType = builtinTypes.type(u"QByteArray"_s).scope;
88 assertExtension(m_byteArrayType,
"ArrayBuffer"_L1);
90 m_urlType = builtinTypes.type(u"QUrl"_s).scope;
91 assertExtension(m_urlType,
"URL"_L1);
93 m_dateTimeType = builtinTypes.type(u"QDateTime"_s).scope;
94 assertExtension(m_dateTimeType,
"Date"_L1);
96 m_dateType = builtinTypes.type(u"QDate"_s).scope;
99 m_timeType = builtinTypes.type(u"QTime"_s).scope;
100 Q_ASSERT(m_timeType);
102 m_regexpType = builtinTypes.type(u"QRegularExpression"_s).scope;
103 Q_ASSERT(m_regexpType);
105 m_variantListType = builtinTypes.type(u"QVariantList"_s).scope;
106 assertExtension(m_variantListType,
"Array"_L1);
108 m_variantMapType = builtinTypes.type(u"QVariantMap"_s).scope;
109 Q_ASSERT(m_variantMapType);
110 m_varType = builtinTypes.type(u"QVariant"_s).scope;
113 m_qmlPropertyMapType = builtinTypes.type(u"QQmlPropertyMap"_s).scope;
114 Q_ASSERT(m_qmlPropertyMapType);
116 m_jsValueType = builtinTypes.type(u"QJSValue"_s).scope;
117 Q_ASSERT(m_jsValueType);
119 m_qObjectType = builtinTypes.type(u"QObject"_s).scope;
120 assertExtension(m_qObjectType,
"Object"_L1);
122 m_qObjectListType = builtinTypes.type(u"QObjectList"_s).scope;
123 assertExtension(m_qObjectListType,
"Array"_L1);
125 m_qQmlScriptStringType = builtinTypes.type(u"QQmlScriptString"_s).scope;
126 Q_ASSERT(m_qQmlScriptStringType);
128 m_functionType = builtinTypes.type(u"function"_s).scope;
129 Q_ASSERT(m_functionType);
131 m_numberPrototype = builtinTypes.type(u"NumberPrototype"_s).scope;
132 Q_ASSERT(m_numberPrototype);
134 m_arrayPrototype = builtinTypes.type(u"ArrayPrototype"_s).scope;
135 Q_ASSERT(m_arrayPrototype);
137 m_listPropertyType = m_qObjectType->listType();
138 Q_ASSERT(m_listPropertyType->internalName() == u"QQmlListProperty<QObject>"_s);
139 Q_ASSERT(m_listPropertyType->accessSemantics() == QQmlJSScope::AccessSemantics::Sequence);
140 Q_ASSERT(m_listPropertyType->elementTypeName() == u"QObject"_s);
141 assertExtension(m_listPropertyType,
"Array"_L1);
143 QQmlJSScope::Ptr emptyType = QQmlJSScope::create();
144 emptyType->setAccessSemantics(QQmlJSScope::AccessSemantics::None);
145 m_emptyType = emptyType;
147 QQmlJSScope::Ptr jsPrimitiveType = QQmlJSScope::create();
148 jsPrimitiveType->setInternalName(u"QJSPrimitiveValue"_s);
149 jsPrimitiveType->setFilePath(u"qjsprimitivevalue.h"_s);
150 jsPrimitiveType->setAccessSemantics(QQmlJSScope::AccessSemantics::Value);
151 m_jsPrimitiveType = jsPrimitiveType;
153 QQmlJSScope::Ptr metaObjectType = QQmlJSScope::create();
154 metaObjectType->setInternalName(u"const QMetaObject"_s);
155 metaObjectType->setFilePath(u"qmetaobject.h"_s);
156 metaObjectType->setAccessSemantics(QQmlJSScope::AccessSemantics::Reference);
157 m_metaObjectType = metaObjectType;
159 m_jsGlobalObject = importer->jsGlobalObject();
161 QQmlJSScope::Ptr forInIteratorPtr = QQmlJSScope::create();
162 forInIteratorPtr->setAccessSemantics(QQmlJSScope::AccessSemantics::Value);
163 forInIteratorPtr->setFilePath(u"qjslist.h"_s);
164 forInIteratorPtr->setInternalName(u"QJSListForInIterator::Ptr"_s);
165 m_forInIteratorPtr = forInIteratorPtr;
167 QQmlJSScope::Ptr forOfIteratorPtr = QQmlJSScope::create();
168 forOfIteratorPtr->setAccessSemantics(QQmlJSScope::AccessSemantics::Value);
169 forOfIteratorPtr->setFilePath(u"qjslist.h"_s);
170 forOfIteratorPtr->setInternalName(u"QJSListForOfIterator::Ptr"_s);
171 m_forOfIteratorPtr = forOfIteratorPtr;
174 m_jsGlobalObjectContent = m_pool->createType(
175 m_jsGlobalObject, QQmlJSRegisterContent::InvalidLookupIndex,
176 QQmlJSRegisterContent::ScopeObject);
260QQmlJSTypeResolver::typeForBinaryOperation(QSOperator::Op oper, QQmlJSRegisterContent left,
261 QQmlJSRegisterContent right)
const
263 Q_ASSERT(left.isValid());
264 Q_ASSERT(right.isValid());
267 case QSOperator::Op::Equal:
268 case QSOperator::Op::NotEqual:
269 case QSOperator::Op::StrictEqual:
270 case QSOperator::Op::StrictNotEqual:
271 case QSOperator::Op::Lt:
272 case QSOperator::Op::Gt:
273 case QSOperator::Op::Ge:
274 case QSOperator::Op::In:
275 case QSOperator::Op::Le:
276 return operationType(boolType());
277 case QSOperator::Op::BitAnd:
278 case QSOperator::Op::BitOr:
279 case QSOperator::Op::BitXor:
280 case QSOperator::Op::LShift:
281 case QSOperator::Op::RShift:
282 return operationType(int32Type());
283 case QSOperator::Op::URShift:
284 return operationType(uint32Type());
285 case QSOperator::Op::Add: {
286 const auto leftContents = left.containedType();
287 const auto rightContents = right.containedType();
288 if (leftContents == stringType() || rightContents == stringType())
289 return operationType(stringType());
291 const QQmlJSScope::ConstPtr result = merge(leftContents, rightContents);
292 if (result == boolType())
293 return operationType(int32Type());
294 if (isNumeric(result))
295 return operationType(realType());
297 return operationType(jsPrimitiveType());
299 case QSOperator::Op::Sub:
300 case QSOperator::Op::Mul:
301 case QSOperator::Op::Exp: {
302 const QQmlJSScope::ConstPtr result = merge(left.containedType(), right.containedType());
303 return operationType(result == boolType() ? int32Type() : realType());
305 case QSOperator::Op::Div:
306 case QSOperator::Op::Mod:
307 return operationType(realType());
308 case QSOperator::Op::As:
309 return operationType(right.containedType());
314 return operationType(merge(left.containedType(), right.containedType()));
452QQmlJSRegisterContent QQmlJSTypeResolver::registerContentForName(
453 const QString &name, QQmlJSRegisterContent scopeType)
const
455 QQmlJSScope::ConstPtr type = typeForName(name);
457 return QQmlJSRegisterContent();
459 if (type->isSingleton()) {
460 return m_pool->createType(
461 type, QQmlJSRegisterContent::InvalidLookupIndex,
462 QQmlJSRegisterContent::Singleton, scopeType);
465 if (type->isScript()) {
466 return m_pool->createType(
467 type, QQmlJSRegisterContent::InvalidLookupIndex,
468 QQmlJSRegisterContent::Script, scopeType);
471 const QQmlJSRegisterContent namedType = m_pool->createType(
472 type, QQmlJSRegisterContent::InvalidLookupIndex, QQmlJSRegisterContent::TypeByName,
475 if (
const auto attached = type->attachedType()) {
476 if (!genericType(attached)) {
477 m_logger->log(u"Cannot resolve generic base of attached %1"_s.arg(
478 attached->internalName()),
479 qmlCompiler, attached->sourceLocation());
481 }
else if (type->accessSemantics() != QQmlJSScope::AccessSemantics::Reference) {
482 m_logger->log(u"Cannot retrieve attached object for non-reference type %1"_s.arg(
483 type->internalName()),
484 qmlCompiler, type->sourceLocation());
490 return m_pool->createType(
491 attached, QQmlJSRegisterContent::InvalidLookupIndex,
492 QQmlJSRegisterContent::Attachment, namedType);
496 switch (type->accessSemantics()) {
497 case QQmlJSScope::AccessSemantics::None:
498 case QQmlJSScope::AccessSemantics::Reference:
503 return m_pool->createType(
504 metaObjectType(), QQmlJSRegisterContent::InvalidLookupIndex,
505 QQmlJSRegisterContent::MetaType, namedType);
506 case QQmlJSScope::AccessSemantics::Sequence:
507 case QQmlJSScope::AccessSemantics::Value:
508 if (scopeType.isImportNamespace() || canAddressValueTypes()) {
509 return m_pool->createType(
510 metaObjectType(), QQmlJSRegisterContent::InvalidLookupIndex,
511 QQmlJSRegisterContent::MetaType, namedType);
518 return QQmlJSRegisterContent();
645QQmlJSRegisterContent QQmlJSTypeResolver::merge(
646 QQmlJSRegisterContent a, QQmlJSRegisterContent b)
const
652 QSet<QQmlJSRegisterContent> origins;
654 QQmlJSRegisterContent aResultScope;
655 if (a.isConversion()) {
656 const auto aOrigins = a.conversionOrigins();
657 for (
const auto &aOrigin : aOrigins)
658 origins.insert(aOrigin);
659 aResultScope = a.conversionResultScope();
662 aResultScope = a.scope();
665 QQmlJSRegisterContent bResultScope;
666 if (b.isConversion()) {
667 const auto bOrigins = b.conversionOrigins();
668 for (
const auto &bOrigin : bOrigins)
669 origins.insert(bOrigin);
670 bResultScope = b.conversionResultScope();
673 bResultScope = b.scope();
676 const auto mergeScopes = [&](QQmlJSRegisterContent a, QQmlJSRegisterContent b) {
679 return (a == b) ? a : merge(a, b);
682 return m_pool->createConversion(
684 merge(a.containedType(), b.containedType()),
685 mergeScopes(aResultScope, bResultScope),
686 mergeVariants(a.variant(), b.variant()),
687 mergeScopes(a.scope(), b.scope()));
690QQmlJSScope::ConstPtr QQmlJSTypeResolver::merge(
const QQmlJSScope::ConstPtr &a,
691 const QQmlJSScope::ConstPtr &b)
const
699 const auto baseOrExtension
700 = [](
const QQmlJSScope::ConstPtr &a,
const QQmlJSScope::ConstPtr &b) {
701 QQmlJSScope::ConstPtr found;
702 QQmlJSUtils::searchBaseAndExtensionTypes(
703 a, [&](
const QQmlJSScope::ConstPtr &scope, QQmlJSScope::ExtensionKind kind) {
705 case QQmlJSScope::NotExtension:
707 if (b->inherits(scope)) {
712 case QQmlJSScope::ExtensionJavaScript:
721 case QQmlJSScope::ExtensionType:
722 case QQmlJSScope::ExtensionNamespace:
733 if (a == jsValueType() || a == varType())
735 if (b == jsValueType() || b == varType())
738 const auto isInt32Compatible = [&](
const QQmlJSScope::ConstPtr &type) {
739 return (isIntegral(type)
740 && type != uint32Type()
741 && type != int64Type()
742 && type != uint64Type())
743 || type == boolType();
746 if (isInt32Compatible(a) && isInt32Compatible(b))
749 const auto isUInt32Compatible = [&](
const QQmlJSScope::ConstPtr &type) {
750 return (isUnsignedInteger(type) && type != uint64Type()) || type == boolType();
753 if (isUInt32Compatible(a) && isUInt32Compatible(b))
756 if (isNumeric(a) && isNumeric(b))
759 if (isPrimitive(a) && isPrimitive(b))
760 return jsPrimitiveType();
762 if (
const auto base = baseOrExtension(a, b))
765 if (
const auto base = baseOrExtension(b, a))
768 if ((a == nullType() || a == boolType()) && b->isReferenceType())
771 if ((b == nullType() || b == boolType()) && a->isReferenceType())
874QQmlJSScope::ConstPtr QQmlJSTypeResolver::genericType(
875 const QQmlJSScope::ConstPtr &type,
876 ComponentIsGeneric allowComponent)
const
878 if (type->isScript())
879 return m_jsValueType;
881 if (type == m_metaObjectType)
882 return m_metaObjectType;
884 if (type->accessSemantics() == QQmlJSScope::AccessSemantics::Reference) {
885 QString unresolvedBaseTypeName;
886 for (
auto base = type; base;) {
892 if (base->internalName() == u"QObject"_s) {
894 }
else if (allowComponent == ComponentIsGeneric::Yes
895 && base->internalName() == u"QQmlComponent"_s) {
899 if (
auto baseBase = base->baseType()) {
902 unresolvedBaseTypeName = base->baseTypeName();
909 if (type->filePath().isEmpty())
910 return m_jsValueType;
912 m_logger->log(u"Object type %1 is not derived from QObject or QQmlComponent. "
913 "You may need to fully qualify all names in C++ so that moc can see them. "
914 "You may also need to add qt_extract_metatypes(<target containing %2>)."_s
915 .arg(type->internalName(), unresolvedBaseTypeName),
916 qmlCompiler, type->sourceLocation());
919 return m_jsValueType;
922 if (type->isListProperty())
923 return m_listPropertyType;
925 if (type->scopeType() == QQmlSA::ScopeType::EnumScope)
926 return type->baseType();
928 if (isPrimitive(type)) {
930 if (!type->filePath().isEmpty())
940 return m_jsPrimitiveType;
943 for (
const QQmlJSScope::ConstPtr &builtin : {
944 m_realType, m_floatType, m_int8Type, m_uint8Type, m_int16Type, m_uint16Type,
945 m_int32Type, m_uint32Type, m_int64Type, m_uint64Type, m_boolType, m_stringType,
946 m_stringListType, m_byteArrayType, m_urlType, m_dateTimeType, m_dateType,
947 m_timeType, m_variantListType, m_variantMapType, m_varType, m_jsValueType,
948 m_jsPrimitiveType, m_listPropertyType, m_qObjectType, m_qObjectListType,
949 m_metaObjectType, m_forInIteratorPtr, m_forOfIteratorPtr }) {
950 if (type == builtin || type == builtin->listType())
1081QQmlJSScope::ConstPtr QQmlJSTypeResolver::scopedType(
1082 const QQmlJSScope::ConstPtr &scope,
const QString &name,
1083 QQmlJSScopesByIdOptions options)
const
1085 QQmlJSScopesById::CertainCallback<QQmlJSScope::ConstPtr> identified;
1086 if (m_objectsById.possibleScopes(name, scope, options, identified)
1087 != QQmlJSScopesById::Success::Yes) {
1092 if (identified.result) {
1094 return identified.result;
1097 if (QQmlJSScope::ConstPtr base = QQmlJSScope::findCurrentQMLScope(scope)) {
1098 QQmlJSScope::ConstPtr result;
1099 if (QQmlJSUtils::searchBaseAndExtensionTypes(
1100 base, [&](
const QQmlJSScope::ConstPtr &found, QQmlJSScope::ExtensionKind mode) {
1101 if (mode == QQmlJSScope::ExtensionNamespace)
1104 if (found->hasOwnProperty(name)) {
1105 const QQmlJSMetaProperty prop = found->ownProperty(name);
1106 if (!isRevisionAllowed(prop.revision(), scope))
1109 result = resolveParentProperty(name, base, prop.type());
1113 if (found->hasOwnMethod(name)) {
1114 const auto methods = found->ownMethods(name);
1115 for (
const auto &method : methods) {
1116 if (isRevisionAllowed(method.revision(), scope)) {
1117 result = jsValueType();
1129 if (QQmlJSScope::ConstPtr result = containedTypeForName(name))
1132 if (m_jsGlobalObject->hasProperty(name))
1133 return m_jsGlobalObject->property(name).type();
1135 if (m_jsGlobalObject->hasMethod(name))
1136 return jsValueType();
1148QQmlJSRegisterContent QQmlJSTypeResolver::scopedType(QQmlJSRegisterContent scope,
1149 const QString &name,
int lookupIndex,
1150 QQmlJSScopesByIdOptions options)
const
1152 const QQmlJSScope::ConstPtr contained = scope.containedType();
1154 QQmlJSScopesById::CertainCallback<QQmlJSScope::ConstPtr> identified;
1155 if (m_objectsById.possibleScopes(name, contained, options, identified)
1156 != QQmlJSScopesById::Success::Yes) {
1161 if (identified.result) {
1163 return m_pool->createType(
1164 identified.result, lookupIndex, QQmlJSRegisterContent::ObjectById, scope);
1167 if (QQmlJSScope::ConstPtr base = QQmlJSScope::findCurrentQMLScope(contained)) {
1168 QQmlJSRegisterContent result;
1169 if (QQmlJSUtils::searchBaseAndExtensionTypes(
1170 base, [&](
const QQmlJSScope::ConstPtr &found, QQmlJSScope::ExtensionKind mode) {
1171 if (mode == QQmlJSScope::ExtensionNamespace)
1174 const QQmlJSRegisterContent resultScope = mode == QQmlJSScope::NotExtension
1176 : extensionType(found, scope);
1178 if (found->hasOwnProperty(name)) {
1179 QQmlJSMetaProperty prop = found->ownProperty(name);
1180 if (!isRevisionAllowed(prop.revision(), contained))
1183 prop.setType(resolveParentProperty(name, base, prop.type()));
1184 result = m_pool->createProperty(
1185 prop, QQmlJSRegisterContent::InvalidLookupIndex, lookupIndex,
1186 scopeContentVariant(mode,
false), resultScope);
1190 if (found->hasOwnMethod(name)) {
1191 auto methods = found->ownMethods(name);
1192 for (
auto it = methods.begin(); it != methods.end();) {
1193 if (!isRevisionAllowed(it->revision(), contained))
1194 it = methods.erase(it);
1198 if (methods.isEmpty())
1200 result = m_pool->createMethod(
1201 methods, jsValueType(), scopeContentVariant(mode,
true), resultScope);
1212 QQmlJSRegisterContent result = registerContentForName(name, scope);
1214 if (result.isValid())
1217 if (m_jsGlobalObject->hasProperty(name)) {
1218 return m_pool->createProperty(
1219 m_jsGlobalObject->property(name), QQmlJSRegisterContent::InvalidLookupIndex,
1220 lookupIndex, QQmlJSRegisterContent::Property, m_jsGlobalObjectContent);
1221 }
else if (m_jsGlobalObject->hasMethod(name)) {
1222 return m_pool->createMethod(
1223 m_jsGlobalObject->methods(name), jsValueType(),
1224 QQmlJSRegisterContent::Property, m_jsGlobalObjectContent);
1295QQmlJSMetaMethod QQmlJSTypeResolver::selectConstructor(
1296 const QQmlJSScope::ConstPtr &type,
const QQmlJSScope::ConstPtr &passedArgumentType,
1297 bool *isExtension)
const
1302 || canHold(passedArgumentType, type)
1303 || type->accessSemantics() != QQmlJSScope::AccessSemantics::Value
1304 || !type->isCreatable()) {
1305 return QQmlJSMetaMethod();
1308 auto doSelectConstructor = [&](
const QQmlJSScope::ConstPtr &type) {
1309 QQmlJSMetaMethod candidate;
1311 const auto ownMethods = type->ownMethods();
1312 for (
const QQmlJSMetaMethod &method : ownMethods) {
1313 if (!method.isConstructor())
1316 const auto index = method.constructorIndex();
1317 Q_ASSERT(index != QQmlJSMetaMethod::RelativeFunctionIndex::Invalid);
1319 const auto methodArguments = method.parameters();
1320 if (methodArguments.size() != 1)
1323 const QQmlJSScope::ConstPtr methodArgumentType = methodArguments[0].type();
1325 if (passedArgumentType == methodArgumentType)
1330 if (!candidate.isValid()
1331 && canPrimitivelyConvertFromTo(passedArgumentType, methodArgumentType)) {
1339 if (QQmlJSScope::ConstPtr extension = type->extensionType().scope) {
1340 const QQmlJSMetaMethod ctor = doSelectConstructor(extension);
1341 if (ctor.isValid()) {
1343 *isExtension =
true;
1349 *isExtension =
false;
1351 return doSelectConstructor(type);
1411bool QQmlJSTypeResolver::canPrimitivelyConvertFromTo(
1412 const QQmlJSScope::ConstPtr &from,
const QQmlJSScope::ConstPtr &to)
const
1416 if (from == m_varType || to == m_varType)
1418 if (from == m_jsValueType || to == m_jsValueType)
1420 if (to == m_qQmlScriptStringType)
1422 if (isNumeric(from) && isNumeric(to))
1425 if (to == m_boolType)
1428 if (from->accessSemantics() == QQmlJSScope::AccessSemantics::Reference
1429 && to == m_stringType) {
1434 if (isNumeric(from) && to == m_stringType)
1438 if (from == m_stringType && isNumeric(to))
1439 return to->scopeType() != QQmlJSScope::ScopeType::EnumScope;
1442 if ((from == m_stringType && to == m_urlType)
1443 || (from == m_urlType && to == m_stringType)) {
1448 if ((from == m_stringType && to == m_byteArrayType)
1449 || (from == m_byteArrayType && to == m_stringType)) {
1453 if (to == m_voidType)
1457 return from == m_voidType;
1459 const auto types = { m_dateTimeType, m_dateType, m_timeType, m_stringType };
1460 for (
const auto &originType : types) {
1461 if (from != originType)
1464 for (
const auto &targetType : types) {
1465 if (to == targetType)
1469 if (to == m_realType)
1475 if (from == m_nullType && to->accessSemantics() == QQmlJSScope::AccessSemantics::Reference)
1478 if (from == m_jsPrimitiveType) {
1480 return isPrimitive(to) || to->accessSemantics() == QQmlJSScope::AccessSemantics::Reference;
1483 if (to == m_jsPrimitiveType)
1484 return isPrimitive(from);
1486 const bool matchByName = !to->isComposite();
1487 Q_ASSERT(!matchByName || !to->internalName().isEmpty());
1488 if (QQmlJSUtils::searchBaseAndExtensionTypes(
1489 from, [&](
const QQmlJSScope::ConstPtr &scope, QQmlJSScope::ExtensionKind kind) {
1491 case QQmlJSScope::NotExtension:
1492 case QQmlJSScope::ExtensionJavaScript:
1498 || (matchByName && scope->internalName() == to->internalName());
1499 case QQmlJSScope::ExtensionType:
1500 case QQmlJSScope::ExtensionNamespace:
1508 if (from == m_variantListType)
1509 return to->accessSemantics() == QQmlJSScope::AccessSemantics::Sequence;
1512 if (canConvertFromTo(from, m_jsPrimitiveType) && canConvertFromTo(m_jsPrimitiveType, to))
1515 if (areEquivalentLists(from, to))
1518 if (from->isListProperty()
1519 && to->accessSemantics() == QQmlJSScope::AccessSemantics::Sequence
1520 && canConvertFromTo(from->elementType(), to->elementType())) {
1525 if (to->accessSemantics() == QQmlJSScope::AccessSemantics::Sequence
1526 && from->accessSemantics() == QQmlJSScope::AccessSemantics::Reference
1527 && from->inherits(to->elementType())) {
1531 if (to == m_stringType && from->accessSemantics() == QQmlJSScope::AccessSemantics::Sequence)
1532 return canConvertFromTo(from->elementType(), m_stringType);
1550QQmlJSRegisterContent QQmlJSTypeResolver::memberType(
1551 QQmlJSRegisterContent type,
const QString &name,
int baseLookupIndex,
1552 int resultLookupIndex)
const
1554 QQmlJSRegisterContent result;
1555 const QQmlJSScope::ConstPtr contained = type.containedType();
1558 if (contained == metaObjectType())
1561 if (contained == variantMapType() || contained->inherits(qmlPropertyMapType())) {
1562 QQmlJSMetaProperty prop;
1563 prop.setPropertyName(name);
1564 prop.setTypeName(u"QVariant"_s);
1565 prop.setType(varType());
1566 prop.setIsWritable(
true);
1567 return m_pool->createProperty(
1568 prop, baseLookupIndex, resultLookupIndex,
1569 QQmlJSRegisterContent::Property, type);
1572 if (contained == jsValueType()) {
1573 QQmlJSMetaProperty prop;
1574 prop.setPropertyName(name);
1575 prop.setTypeName(u"QJSValue"_s);
1576 prop.setType(jsValueType());
1577 prop.setIsWritable(
true);
1578 return m_pool->createProperty(
1579 prop, baseLookupIndex, resultLookupIndex,
1580 QQmlJSRegisterContent::Property, type);
1583 if ((contained == stringType()
1584 || contained->accessSemantics() == QQmlJSScope::AccessSemantics::Sequence)
1585 && name == u"length"_s) {
1586 return lengthProperty(contained != stringType(), type);
1589 const auto check = [&](
const QQmlJSScope::ConstPtr &scope, QQmlJSScope::ExtensionKind mode) {
1590 const QQmlJSRegisterContent resultScope = mode == QQmlJSScope::NotExtension
1591 ? baseType(scope, type)
1592 : extensionType(scope, type);
1594 if (mode != QQmlJSScope::ExtensionNamespace) {
1595 if (scope->hasOwnProperty(name)) {
1596 const auto prop = scope->ownProperty(name);
1597 result = m_pool->createProperty(
1598 prop, baseLookupIndex, resultLookupIndex,
1599 QQmlJSRegisterContent::Property, resultScope);
1603 if (scope->hasOwnMethod(name)) {
1604 const auto methods = scope->ownMethods(name);
1605 result = m_pool->createMethod(
1606 methods, jsValueType(), QQmlJSRegisterContent::Method, resultScope);
1611 return checkEnums(resultScope, name, &result);
1614 if (QQmlJSUtils::searchBaseAndExtensionTypes(type.containedType(), check))
1617 for (
auto scope = contained;
1618 scope && (QQmlSA::isFunctionScope(scope->scopeType())
1619 || scope->scopeType() == QQmlSA::ScopeType::JSLexicalScope);
1620 scope = scope->parentScope()) {
1621 if (
auto ownIdentifier = scope->ownJSIdentifier(name)) {
1622 QQmlJSMetaProperty prop;
1623 prop.setPropertyName(name);
1624 prop.setTypeName(u"QJSValue"_s);
1625 prop.setType(jsValueType());
1626 prop.setIsWritable(!(ownIdentifier.value().isConst));
1628 return m_pool->createProperty(
1629 prop, baseLookupIndex, resultLookupIndex,
1630 QQmlJSRegisterContent::Property,
1631 parentScope(scope, type));
1635 if (QQmlJSScope::ConstPtr attachedBase = typeForName(name)) {
1636 if (QQmlJSScope::ConstPtr attached = attachedBase->attachedType()) {
1637 if (!genericType(attached)) {
1638 m_logger->log(u"Cannot resolve generic base of attached %1"_s.arg(
1639 attached->internalName()),
1640 qmlCompiler, attached->sourceLocation());
1642 }
else if (contained->accessSemantics() != QQmlJSScope::AccessSemantics::Reference) {
1643 m_logger->log(u"Cannot retrieve attached object for non-reference type %1"_s.arg(
1644 contained->internalName()),
1645 qmlCompiler, contained->sourceLocation());
1648 const QQmlJSRegisterContent namedType = m_pool->createType(
1649 attachedBase, QQmlJSRegisterContent::InvalidLookupIndex,
1650 QQmlJSRegisterContent::TypeByName, type);
1652 return m_pool->createType(
1653 attached, resultLookupIndex, QQmlJSRegisterContent::Attachment,
1681QQmlJSRegisterContent QQmlJSTypeResolver::memberType(
1682 QQmlJSRegisterContent type,
const QString &name,
int lookupIndex)
const
1684 if (type.isType()) {
1685 const auto result = memberType(type, name, type.resultLookupIndex(), lookupIndex);
1686 if (result.isValid())
1691 return memberEnumType(type.scope(), name);
1693 if (type.isProperty() || type.isMethodCall())
1694 return memberType(type, name, type.resultLookupIndex(), lookupIndex);
1695 if (type.isEnumeration()) {
1696 const auto enumeration = type.enumeration();
1697 if (!type.enumMember().isEmpty() || !enumeration.hasKey(name))
1699 return m_pool->createEnumeration(
1700 enumeration, name, QQmlJSRegisterContent::Enum, type.scope());
1702 if (type.isMethod()) {
1703 QQmlJSMetaProperty prop;
1704 prop.setTypeName(u"QJSValue"_s);
1705 prop.setPropertyName(name);
1706 prop.setType(jsValueType());
1707 prop.setIsWritable(
true);
1708 return m_pool->createProperty(
1709 prop, QQmlJSRegisterContent::InvalidLookupIndex, lookupIndex,
1710 QQmlJSRegisterContent::Property, type);
1712 if (type.isImportNamespace()) {
1713 Q_ASSERT(type.scopeType()->isReferenceType());
1714 return registerContentForName(name, type);
1716 if (type.isConversion()) {
1717 if (
const auto result = memberType(
1718 type, name, type.resultLookupIndex(), lookupIndex);
1723 if (
const auto result = memberEnumType(type.scope(), name); result.isValid())
1730 const auto nonVoid = extractNonVoidFromOptionalType(type);
1733 return (!nonVoid.isNull() && canHold(type.conversionResultType(), nonVoid.containedType()))
1734 ? memberType(nonVoid, name, type.resultLookupIndex(), lookupIndex)
1735 : QQmlJSRegisterContent();
1738 Q_UNREACHABLE_RETURN({});