31QQmlJSTypeResolver::QQmlJSTypeResolver(QQmlJSImporter *importer)
32 : m_pool(std::make_unique<QQmlJSRegisterContentPool>())
33 , m_imports(importer->builtinInternalNames())
35 const QQmlJSImporter::ImportedTypes &builtinTypes = m_imports;
37 m_voidType = builtinTypes.type(u"void"_s).scope;
38 assertExtension(m_voidType,
"undefined"_L1);
40 m_nullType = builtinTypes.type(u"std::nullptr_t"_s).scope;
43 m_realType = builtinTypes.type(u"double"_s).scope;
44 assertExtension(m_realType,
"Number"_L1);
46 m_floatType = builtinTypes.type(u"float"_s).scope;
47 assertExtension(m_floatType,
"Number"_L1);
49 m_int8Type = builtinTypes.type(u"qint8"_s).scope;
50 assertExtension(m_int8Type,
"Number"_L1);
52 m_uint8Type = builtinTypes.type(u"quint8"_s).scope;
53 assertExtension(m_uint8Type,
"Number"_L1);
55 m_int16Type = builtinTypes.type(u"short"_s).scope;
56 assertExtension(m_int16Type,
"Number"_L1);
58 m_uint16Type = builtinTypes.type(u"ushort"_s).scope;
59 assertExtension(m_uint16Type,
"Number"_L1);
61 m_int32Type = builtinTypes.type(u"int"_s).scope;
62 assertExtension(m_int32Type,
"Number"_L1);
64 m_uint32Type = builtinTypes.type(u"uint"_s).scope;
65 assertExtension(m_uint32Type,
"Number"_L1);
67 m_int64Type = builtinTypes.type(u"qlonglong"_s).scope;
68 Q_ASSERT(m_int64Type);
70 m_uint64Type = builtinTypes.type(u"qulonglong"_s).scope;
71 Q_ASSERT(m_uint64Type);
73 m_sizeType = builtinTypes.type(u"qsizetype"_s).scope;
74 assertExtension(m_sizeType,
"Number"_L1);
77 Q_ASSERT(m_sizeType == m_int32Type || m_sizeType == m_int64Type);
79 m_boolType = builtinTypes.type(u"bool"_s).scope;
80 assertExtension(m_boolType,
"Boolean"_L1);
82 m_stringType = builtinTypes.type(u"QString"_s).scope;
83 assertExtension(m_stringType,
"String"_L1);
85 m_stringListType = builtinTypes.type(u"QStringList"_s).scope;
86 assertExtension(m_stringListType,
"Array"_L1);
88 m_byteArrayType = builtinTypes.type(u"QByteArray"_s).scope;
89 assertExtension(m_byteArrayType,
"ArrayBuffer"_L1);
91 m_urlType = builtinTypes.type(u"QUrl"_s).scope;
92 assertExtension(m_urlType,
"URL"_L1);
94 m_dateTimeType = builtinTypes.type(u"QDateTime"_s).scope;
95 assertExtension(m_dateTimeType,
"Date"_L1);
97 m_dateType = builtinTypes.type(u"QDate"_s).scope;
100 m_timeType = builtinTypes.type(u"QTime"_s).scope;
101 Q_ASSERT(m_timeType);
103 m_regexpType = builtinTypes.type(u"QRegularExpression"_s).scope;
104 Q_ASSERT(m_regexpType);
106 m_variantListType = builtinTypes.type(u"QVariantList"_s).scope;
107 assertExtension(m_variantListType,
"Array"_L1);
109 m_variantMapType = builtinTypes.type(u"QVariantMap"_s).scope;
110 Q_ASSERT(m_variantMapType);
111 m_varType = builtinTypes.type(u"QVariant"_s).scope;
114 m_qmlPropertyMapType = builtinTypes.type(u"QQmlPropertyMap"_s).scope;
115 Q_ASSERT(m_qmlPropertyMapType);
117 m_jsValueType = builtinTypes.type(u"QJSValue"_s).scope;
118 Q_ASSERT(m_jsValueType);
120 m_qObjectType = builtinTypes.type(u"QObject"_s).scope;
121 assertExtension(m_qObjectType,
"Object"_L1);
123 m_qObjectListType = builtinTypes.type(u"QObjectList"_s).scope;
124 assertExtension(m_qObjectListType,
"Array"_L1);
126 m_qQmlScriptStringType = builtinTypes.type(u"QQmlScriptString"_s).scope;
127 Q_ASSERT(m_qQmlScriptStringType);
129 m_functionType = builtinTypes.type(u"function"_s).scope;
130 Q_ASSERT(m_functionType);
132 m_numberPrototype = builtinTypes.type(u"NumberPrototype"_s).scope;
133 Q_ASSERT(m_numberPrototype);
135 m_arrayPrototype = builtinTypes.type(u"ArrayPrototype"_s).scope;
136 Q_ASSERT(m_arrayPrototype);
138 m_listPropertyType = m_qObjectType->listType();
139 Q_ASSERT(m_listPropertyType->internalName() == u"QQmlListProperty<QObject>"_s);
140 Q_ASSERT(m_listPropertyType->accessSemantics() == QQmlJSScope::AccessSemantics::Sequence);
141 Q_ASSERT(m_listPropertyType->elementTypeName() == u"QObject"_s);
142 assertExtension(m_listPropertyType,
"Array"_L1);
144 QQmlJSScope::Ptr emptyType = QQmlJSScope::create();
145 emptyType->setAccessSemantics(QQmlJSScope::AccessSemantics::None);
146 m_emptyType = emptyType;
148 QQmlJSScope::Ptr jsPrimitiveType = QQmlJSScope::create();
149 jsPrimitiveType->setInternalName(u"QJSPrimitiveValue"_s);
150 jsPrimitiveType->setFilePath(u"qjsprimitivevalue.h"_s);
151 jsPrimitiveType->setAccessSemantics(QQmlJSScope::AccessSemantics::Value);
152 m_jsPrimitiveType = jsPrimitiveType;
154 QQmlJSScope::Ptr metaObjectType = QQmlJSScope::create();
155 metaObjectType->setInternalName(u"const QMetaObject"_s);
156 metaObjectType->setFilePath(u"qmetaobject.h"_s);
157 metaObjectType->setAccessSemantics(QQmlJSScope::AccessSemantics::Reference);
158 m_metaObjectType = metaObjectType;
160 m_jsGlobalObject = importer->jsGlobalObject();
162 QQmlJSScope::Ptr forInIteratorPtr = QQmlJSScope::create();
163 forInIteratorPtr->setAccessSemantics(QQmlJSScope::AccessSemantics::Value);
164 forInIteratorPtr->setFilePath(u"qjslist.h"_s);
165 forInIteratorPtr->setInternalName(u"QJSListForInIterator::Ptr"_s);
166 m_forInIteratorPtr = forInIteratorPtr;
168 QQmlJSScope::Ptr forOfIteratorPtr = QQmlJSScope::create();
169 forOfIteratorPtr->setAccessSemantics(QQmlJSScope::AccessSemantics::Value);
170 forOfIteratorPtr->setFilePath(u"qjslist.h"_s);
171 forOfIteratorPtr->setInternalName(u"QJSListForOfIterator::Ptr"_s);
172 m_forOfIteratorPtr = forOfIteratorPtr;
175 m_jsGlobalObjectContent = m_pool->createType(
176 m_jsGlobalObject, QQmlJSRegisterContent::InvalidLookupIndex,
177 QQmlJSRegisterContent::ScopeObject);
261QQmlJSTypeResolver::typeForBinaryOperation(QSOperator::Op oper, QQmlJSRegisterContent left,
262 QQmlJSRegisterContent right)
const
264 Q_ASSERT(left.isValid());
265 Q_ASSERT(right.isValid());
268 case QSOperator::Op::Equal:
269 case QSOperator::Op::NotEqual:
270 case QSOperator::Op::StrictEqual:
271 case QSOperator::Op::StrictNotEqual:
272 case QSOperator::Op::Lt:
273 case QSOperator::Op::Gt:
274 case QSOperator::Op::Ge:
275 case QSOperator::Op::In:
276 case QSOperator::Op::Le:
277 return operationType(boolType());
278 case QSOperator::Op::BitAnd:
279 case QSOperator::Op::BitOr:
280 case QSOperator::Op::BitXor:
281 case QSOperator::Op::LShift:
282 case QSOperator::Op::RShift:
283 return operationType(int32Type());
284 case QSOperator::Op::URShift:
285 return operationType(uint32Type());
286 case QSOperator::Op::Add: {
287 const auto leftContents = left.containedType();
288 const auto rightContents = right.containedType();
289 if (leftContents == stringType() || rightContents == stringType())
290 return operationType(stringType());
292 const QQmlJSScope::ConstPtr result = merge(leftContents, rightContents);
293 if (result == boolType())
294 return operationType(int32Type());
295 if (isNumeric(result))
296 return operationType(realType());
298 return operationType(jsPrimitiveType());
300 case QSOperator::Op::Sub:
301 case QSOperator::Op::Mul:
302 case QSOperator::Op::Exp: {
303 const QQmlJSScope::ConstPtr result = merge(left.containedType(), right.containedType());
304 return operationType(result == boolType() ? int32Type() : realType());
306 case QSOperator::Op::Div:
307 case QSOperator::Op::Mod:
308 return operationType(realType());
309 case QSOperator::Op::As:
310 return operationType(right.containedType());
315 return operationType(merge(left.containedType(), right.containedType()));
453QQmlJSRegisterContent QQmlJSTypeResolver::registerContentForName(
454 const QString &name, QQmlJSRegisterContent scopeType)
const
456 QQmlJSScope::ConstPtr type = typeForName(name);
458 return QQmlJSRegisterContent();
460 if (type->isSingleton()) {
461 return m_pool->createType(
462 type, QQmlJSRegisterContent::InvalidLookupIndex,
463 QQmlJSRegisterContent::Singleton, scopeType);
466 if (type->isScript()) {
467 return m_pool->createType(
468 type, QQmlJSRegisterContent::InvalidLookupIndex,
469 QQmlJSRegisterContent::Script, scopeType);
472 const QQmlJSRegisterContent namedType = m_pool->createType(
473 type, QQmlJSRegisterContent::InvalidLookupIndex, QQmlJSRegisterContent::TypeByName,
476 if (
const auto attached = type->attachedType()) {
477 if (!genericType(attached)) {
478 m_logger->log(u"Cannot resolve generic base of attached %1"_s.arg(
479 attached->internalName()),
480 qmlCompiler, attached->sourceLocation());
482 }
else if (type->accessSemantics() != QQmlJSScope::AccessSemantics::Reference) {
483 m_logger->log(u"Cannot retrieve attached object for non-reference type %1"_s.arg(
484 type->internalName()),
485 qmlCompiler, type->sourceLocation());
491 return m_pool->createType(
492 attached, QQmlJSRegisterContent::InvalidLookupIndex,
493 QQmlJSRegisterContent::Attachment, namedType);
497 switch (type->accessSemantics()) {
498 case QQmlJSScope::AccessSemantics::None:
499 case QQmlJSScope::AccessSemantics::Reference:
504 return m_pool->createType(
505 metaObjectType(), QQmlJSRegisterContent::InvalidLookupIndex,
506 QQmlJSRegisterContent::MetaType, namedType);
507 case QQmlJSScope::AccessSemantics::Sequence:
508 case QQmlJSScope::AccessSemantics::Value:
509 if (scopeType.isImportNamespace() || canAddressValueTypes()) {
510 return m_pool->createType(
511 metaObjectType(), QQmlJSRegisterContent::InvalidLookupIndex,
512 QQmlJSRegisterContent::MetaType, namedType);
519 return QQmlJSRegisterContent();
646QQmlJSRegisterContent QQmlJSTypeResolver::merge(
647 QQmlJSRegisterContent a, QQmlJSRegisterContent b)
const
653 QSet<QQmlJSRegisterContent> origins;
655 QQmlJSRegisterContent aResultScope;
656 if (a.isConversion()) {
657 const auto aOrigins = a.conversionOrigins();
658 for (
const auto &aOrigin : aOrigins)
659 origins.insert(aOrigin);
660 aResultScope = a.conversionResultScope();
663 aResultScope = a.scope();
666 QQmlJSRegisterContent bResultScope;
667 if (b.isConversion()) {
668 const auto bOrigins = b.conversionOrigins();
669 for (
const auto &bOrigin : bOrigins)
670 origins.insert(bOrigin);
671 bResultScope = b.conversionResultScope();
674 bResultScope = b.scope();
677 const auto mergeScopes = [&](QQmlJSRegisterContent a, QQmlJSRegisterContent b) {
680 return (a == b) ? a : merge(a, b);
683 return m_pool->createConversion(
685 merge(a.containedType(), b.containedType()),
686 mergeScopes(aResultScope, bResultScope),
687 mergeVariants(a.variant(), b.variant()),
688 mergeScopes(a.scope(), b.scope()));
691QQmlJSScope::ConstPtr QQmlJSTypeResolver::merge(
const QQmlJSScope::ConstPtr &a,
692 const QQmlJSScope::ConstPtr &b)
const
700 const auto baseOrExtension
701 = [](
const QQmlJSScope::ConstPtr &a,
const QQmlJSScope::ConstPtr &b) {
702 QQmlJSScope::ConstPtr found;
703 QQmlJSUtils::searchBaseAndExtensionTypes(
704 a, [&](
const QQmlJSScope::ConstPtr &scope, QQmlJSScope::ExtensionKind kind) {
706 case QQmlJSScope::NotExtension:
708 if (b->inherits(scope)) {
713 case QQmlJSScope::ExtensionJavaScript:
722 case QQmlJSScope::ExtensionType:
723 case QQmlJSScope::ExtensionNamespace:
734 if (a == jsValueType() || a == varType())
736 if (b == jsValueType() || b == varType())
739 const auto isInt32Compatible = [&](
const QQmlJSScope::ConstPtr &type) {
740 return (isIntegral(type)
741 && type != uint32Type()
742 && type != int64Type()
743 && type != uint64Type())
744 || type == boolType();
747 if (isInt32Compatible(a) && isInt32Compatible(b))
750 const auto isUInt32Compatible = [&](
const QQmlJSScope::ConstPtr &type) {
751 return (isUnsignedInteger(type) && type != uint64Type()) || type == boolType();
754 if (isUInt32Compatible(a) && isUInt32Compatible(b))
757 if (isNumeric(a) && isNumeric(b))
760 if (isPrimitive(a) && isPrimitive(b))
761 return jsPrimitiveType();
763 if (
const auto base = baseOrExtension(a, b))
766 if (
const auto base = baseOrExtension(b, a))
769 if ((a == nullType() || a == boolType()) && b->isReferenceType())
772 if ((b == nullType() || b == boolType()) && a->isReferenceType())
875QQmlJSScope::ConstPtr QQmlJSTypeResolver::genericType(
876 const QQmlJSScope::ConstPtr &type,
877 ComponentIsGeneric allowComponent)
const
879 if (type->isScript())
880 return m_jsValueType;
882 if (type == m_metaObjectType)
883 return m_metaObjectType;
885 if (type->accessSemantics() == QQmlJSScope::AccessSemantics::Reference) {
886 QString unresolvedBaseTypeName;
887 for (
auto base = type; base;) {
893 if (base->internalName() == u"QObject"_s) {
895 }
else if (allowComponent == ComponentIsGeneric::Yes
896 && base->internalName() == u"QQmlComponent"_s) {
900 if (
auto baseBase = base->baseType()) {
903 unresolvedBaseTypeName = base->baseTypeName();
910 if (type->filePath().isEmpty())
911 return m_jsValueType;
913 m_logger->log(u"Object type %1 is not derived from QObject or QQmlComponent. "
914 "You may need to fully qualify all names in C++ so that moc can see them. "
915 "You may also need to add qt_extract_metatypes(<target containing %2>)."_s
916 .arg(type->internalName(), unresolvedBaseTypeName),
917 qmlCompiler, type->sourceLocation());
920 return m_jsValueType;
923 if (type->isListProperty())
924 return m_listPropertyType;
926 if (type->scopeType() == QQmlSA::ScopeType::EnumScope)
927 return type->baseType();
929 if (isPrimitive(type)) {
931 if (!type->filePath().isEmpty())
941 return m_jsPrimitiveType;
944 for (
const QQmlJSScope::ConstPtr &builtin : {
945 m_realType, m_floatType, m_int8Type, m_uint8Type, m_int16Type, m_uint16Type,
946 m_int32Type, m_uint32Type, m_int64Type, m_uint64Type, m_boolType, m_stringType,
947 m_stringListType, m_byteArrayType, m_urlType, m_dateTimeType, m_dateType,
948 m_timeType, m_variantListType, m_variantMapType, m_varType, m_jsValueType,
949 m_jsPrimitiveType, m_listPropertyType, m_qObjectType, m_qObjectListType,
950 m_metaObjectType, m_forInIteratorPtr, m_forOfIteratorPtr }) {
951 if (type == builtin || type == builtin->listType())
1082QQmlJSScope::ConstPtr QQmlJSTypeResolver::scopedType(
1083 const QQmlJSScope::ConstPtr &scope,
const QString &name,
1084 QQmlJSScopesByIdOptions options)
const
1086 QQmlJSScopesById::CertainCallback<QQmlJSScope::ConstPtr> identified;
1087 if (m_objectsById.possibleScopes(name, scope, options, identified)
1088 != QQmlJSScopesById::Success::Yes) {
1093 if (identified.result) {
1095 return identified.result;
1098 if (QQmlJSScope::ConstPtr base = QQmlJSScope::findCurrentQMLScope(scope)) {
1099 QQmlJSScope::ConstPtr result;
1100 if (QQmlJSUtils::searchBaseAndExtensionTypes(
1101 base, [&](
const QQmlJSScope::ConstPtr &found, QQmlJSScope::ExtensionKind mode) {
1102 if (mode == QQmlJSScope::ExtensionNamespace)
1105 if (found->hasOwnProperty(name)) {
1106 const QQmlJSMetaProperty prop = found->ownProperty(name);
1107 if (!isRevisionAllowed(prop.revision(), scope))
1110 result = resolveParentProperty(name, base, prop.type());
1114 if (found->hasOwnMethod(name)) {
1115 const auto methods = found->ownMethods(name);
1116 for (
const auto &method : methods) {
1117 if (isRevisionAllowed(method.revision(), scope)) {
1118 result = jsValueType();
1130 if (QQmlJSScope::ConstPtr result = containedTypeForName(name))
1133 if (m_jsGlobalObject->hasProperty(name))
1134 return m_jsGlobalObject->property(name).type();
1136 if (m_jsGlobalObject->hasMethod(name))
1137 return jsValueType();
1149QQmlJSRegisterContent QQmlJSTypeResolver::scopedType(QQmlJSRegisterContent scope,
1150 const QString &name,
int lookupIndex,
1151 QQmlJSScopesByIdOptions options)
const
1153 const QQmlJSScope::ConstPtr contained = scope.containedType();
1155 QQmlJSScopesById::CertainCallback<QQmlJSScope::ConstPtr> identified;
1156 if (m_objectsById.possibleScopes(name, contained, options, identified)
1157 != QQmlJSScopesById::Success::Yes) {
1162 if (identified.result) {
1164 return m_pool->createType(
1165 identified.result, lookupIndex, QQmlJSRegisterContent::ObjectById, scope);
1168 if (QQmlJSScope::ConstPtr base = QQmlJSScope::findCurrentQMLScope(contained)) {
1169 QQmlJSRegisterContent result;
1170 if (QQmlJSUtils::searchBaseAndExtensionTypes(
1171 base, [&](
const QQmlJSScope::ConstPtr &found, QQmlJSScope::ExtensionKind mode) {
1172 if (mode == QQmlJSScope::ExtensionNamespace)
1175 const QQmlJSRegisterContent resultScope = mode == QQmlJSScope::NotExtension
1177 : extensionType(found, scope);
1179 if (found->hasOwnProperty(name)) {
1180 QQmlJSMetaProperty prop = found->ownProperty(name);
1181 if (!isRevisionAllowed(prop.revision(), contained))
1184 prop.setType(resolveParentProperty(name, base, prop.type()));
1185 result = m_pool->createProperty(
1186 prop, QQmlJSRegisterContent::InvalidLookupIndex, lookupIndex,
1187 scopeContentVariant(mode,
false), resultScope);
1191 if (found->hasOwnMethod(name)) {
1192 auto methods = found->ownMethods(name);
1193 for (
auto it = methods.begin(); it != methods.end();) {
1194 if (!isRevisionAllowed(it->revision(), contained))
1195 it = methods.erase(it);
1199 if (methods.isEmpty())
1201 result = m_pool->createMethod(
1202 methods, jsValueType(), scopeContentVariant(mode,
true), resultScope);
1213 QQmlJSRegisterContent result = registerContentForName(name, scope);
1215 if (result.isValid())
1218 if (m_jsGlobalObject->hasProperty(name)) {
1219 return m_pool->createProperty(
1220 m_jsGlobalObject->property(name), QQmlJSRegisterContent::InvalidLookupIndex,
1221 lookupIndex, QQmlJSRegisterContent::Property, m_jsGlobalObjectContent);
1222 }
else if (m_jsGlobalObject->hasMethod(name)) {
1223 return m_pool->createMethod(
1224 m_jsGlobalObject->methods(name), jsValueType(),
1225 QQmlJSRegisterContent::Property, m_jsGlobalObjectContent);
1296QQmlJSMetaMethod QQmlJSTypeResolver::selectConstructor(
1297 const QQmlJSScope::ConstPtr &type,
const QQmlJSScope::ConstPtr &passedArgumentType,
1298 bool *isExtension)
const
1303 || canHold(passedArgumentType, type)
1304 || type->accessSemantics() != QQmlJSScope::AccessSemantics::Value
1305 || !type->isCreatable()) {
1306 return QQmlJSMetaMethod();
1309 auto doSelectConstructor = [&](
const QQmlJSScope::ConstPtr &ctorProvider) {
1310 QQmlJSMetaMethod candidate;
1312 const auto ownMethods = ctorProvider->ownMethods();
1313 for (
const QQmlJSMetaMethod &method : ownMethods) {
1314 if (!method.isConstructor())
1317 const auto index = method.constructorIndex();
1318 Q_ASSERT(index != QQmlJSMetaMethod::RelativeFunctionIndex::Invalid);
1320 const auto methodArguments = method.parameters();
1321 if (methodArguments.size() != 1)
1324 const QQmlJSScope::ConstPtr methodArgumentType = methodArguments[0].type();
1327 if (methodArgumentType == type)
1330 if (passedArgumentType == methodArgumentType)
1335 if (!candidate.isValid()
1336 && canPrimitivelyConvertFromTo(passedArgumentType, methodArgumentType)) {
1344 if (QQmlJSScope::ConstPtr extension = type->extensionType().scope) {
1345 const QQmlJSMetaMethod ctor = doSelectConstructor(extension);
1346 if (ctor.isValid()) {
1348 *isExtension =
true;
1354 *isExtension =
false;
1356 return doSelectConstructor(type);
1416bool QQmlJSTypeResolver::canPrimitivelyConvertFromTo(
1417 const QQmlJSScope::ConstPtr &from,
const QQmlJSScope::ConstPtr &to)
const
1421 if (from == m_varType || to == m_varType)
1423 if (from == m_jsValueType || to == m_jsValueType)
1425 if (to == m_qQmlScriptStringType)
1427 if (isNumeric(from) && isNumeric(to))
1430 if (to == m_boolType)
1433 if (from->accessSemantics() == QQmlJSScope::AccessSemantics::Reference
1434 && to == m_stringType) {
1439 if (isNumeric(from) && to == m_stringType)
1443 if (from == m_stringType && isNumeric(to))
1444 return to->scopeType() != QQmlJSScope::ScopeType::EnumScope;
1447 if ((from == m_stringType && to == m_urlType)
1448 || (from == m_urlType && to == m_stringType)) {
1453 if ((from == m_stringType && to == m_byteArrayType)
1454 || (from == m_byteArrayType && to == m_stringType)) {
1458 if (to == m_voidType)
1462 return from == m_voidType;
1464 const auto types = { m_dateTimeType, m_dateType, m_timeType, m_stringType };
1465 for (
const auto &originType : types) {
1466 if (from != originType)
1469 for (
const auto &targetType : types) {
1470 if (to == targetType)
1474 if (to == m_realType)
1480 if (from == m_nullType && to->accessSemantics() == QQmlJSScope::AccessSemantics::Reference)
1483 if (from == m_jsPrimitiveType) {
1485 return isPrimitive(to) || to->accessSemantics() == QQmlJSScope::AccessSemantics::Reference;
1488 if (to == m_jsPrimitiveType)
1489 return isPrimitive(from);
1491 const bool matchByName = !to->isComposite();
1492 Q_ASSERT(!matchByName || !to->internalName().isEmpty());
1493 if (QQmlJSUtils::searchBaseAndExtensionTypes(
1494 from, [&](
const QQmlJSScope::ConstPtr &scope, QQmlJSScope::ExtensionKind kind) {
1496 case QQmlJSScope::NotExtension:
1497 case QQmlJSScope::ExtensionJavaScript:
1503 || (matchByName && scope->internalName() == to->internalName());
1504 case QQmlJSScope::ExtensionType:
1505 case QQmlJSScope::ExtensionNamespace:
1513 if (from == m_variantListType)
1514 return to->accessSemantics() == QQmlJSScope::AccessSemantics::Sequence;
1517 if (canPrimitivelyConvertFromTo(from, m_jsPrimitiveType)
1518 && canPrimitivelyConvertFromTo(m_jsPrimitiveType, to)) {
1522 if (areEquivalentLists(from, to))
1525 if (from->isListProperty()
1526 && to->accessSemantics() == QQmlJSScope::AccessSemantics::Sequence
1527 && canConvertFromTo(from->elementType(), to->elementType())) {
1532 if (to->accessSemantics() == QQmlJSScope::AccessSemantics::Sequence
1533 && from->accessSemantics() == QQmlJSScope::AccessSemantics::Reference
1534 && from->inherits(to->elementType())) {
1538 if (to == m_stringType && from->accessSemantics() == QQmlJSScope::AccessSemantics::Sequence)
1539 return canConvertFromTo(from->elementType(), m_stringType);
1557QQmlJSRegisterContent QQmlJSTypeResolver::memberType(
1558 QQmlJSRegisterContent type,
const QString &name,
int baseLookupIndex,
1559 int resultLookupIndex)
const
1561 QQmlJSRegisterContent result;
1562 const QQmlJSScope::ConstPtr contained = type.containedType();
1565 if (contained == metaObjectType())
1566 return memberEnumType(type.scope(), name);
1568 if (contained == variantMapType() || contained->inherits(qmlPropertyMapType())) {
1569 QQmlJSMetaProperty prop;
1570 prop.setPropertyName(name);
1571 prop.setTypeName(u"QVariant"_s);
1572 prop.setType(varType());
1573 prop.setIsWritable(
true);
1574 return m_pool->createProperty(
1575 prop, baseLookupIndex, resultLookupIndex,
1576 QQmlJSRegisterContent::Property, type);
1579 if (contained == jsValueType()) {
1580 QQmlJSMetaProperty prop;
1581 prop.setPropertyName(name);
1582 prop.setTypeName(u"QJSValue"_s);
1583 prop.setType(jsValueType());
1584 prop.setIsWritable(
true);
1585 return m_pool->createProperty(
1586 prop, baseLookupIndex, resultLookupIndex,
1587 QQmlJSRegisterContent::Property, type);
1590 if ((contained == stringType()
1591 || contained->accessSemantics() == QQmlJSScope::AccessSemantics::Sequence)
1592 && name == u"length"_s) {
1593 return lengthProperty(contained != stringType(), type);
1596 const auto check = [&](
const QQmlJSScope::ConstPtr &scope, QQmlJSScope::ExtensionKind mode) {
1597 const QQmlJSRegisterContent resultScope = mode == QQmlJSScope::NotExtension
1598 ? baseType(scope, type)
1599 : extensionType(scope, type);
1601 if (mode != QQmlJSScope::ExtensionNamespace) {
1602 if (scope->hasOwnProperty(name)) {
1603 const auto prop = scope->ownProperty(name);
1604 result = m_pool->createProperty(
1605 prop, baseLookupIndex, resultLookupIndex,
1606 QQmlJSRegisterContent::Property, resultScope);
1610 if (scope->hasOwnMethod(name)) {
1611 const auto methods = scope->ownMethods(name);
1612 result = m_pool->createMethod(
1613 methods, jsValueType(), QQmlJSRegisterContent::Method, resultScope);
1618 if (type.variant() == QQmlJSRegisterContent::ObjectById)
1620 return checkEnums(resultScope, name, &result);
1623 if (QQmlJSUtils::searchBaseAndExtensionTypes(type.containedType(), check))
1626 for (
auto scope = contained;
1627 scope && (QQmlSA::isFunctionScope(scope->scopeType())
1628 || scope->scopeType() == QQmlSA::ScopeType::JSLexicalScope);
1629 scope = scope->parentScope()) {
1630 if (
auto ownIdentifier = scope->ownJSIdentifier(name)) {
1631 QQmlJSMetaProperty prop;
1632 prop.setPropertyName(name);
1633 prop.setTypeName(u"QJSValue"_s);
1634 prop.setType(jsValueType());
1635 prop.setIsWritable(!(ownIdentifier.value().isConst));
1637 return m_pool->createProperty(
1638 prop, baseLookupIndex, resultLookupIndex,
1639 QQmlJSRegisterContent::Property,
1640 parentScope(scope, type));
1645 if (type.isType()) {
1646 if (
auto result = memberEnumType(type.scope(), name); result.isValid())
1650 if (QQmlJSScope::ConstPtr attachedBase = typeForName(name)) {
1651 if (QQmlJSScope::ConstPtr attached = attachedBase->attachedType()) {
1652 if (!genericType(attached)) {
1653 m_logger->log(u"Cannot resolve generic base of attached %1"_s.arg(
1654 attached->internalName()),
1655 qmlCompiler, attached->sourceLocation());
1657 }
else if (contained->accessSemantics() != QQmlJSScope::AccessSemantics::Reference) {
1658 m_logger->log(u"Cannot retrieve attached object for non-reference type %1"_s.arg(
1659 contained->internalName()),
1660 qmlCompiler, contained->sourceLocation());
1663 const QQmlJSRegisterContent namedType = m_pool->createType(
1664 attachedBase, QQmlJSRegisterContent::InvalidLookupIndex,
1665 QQmlJSRegisterContent::TypeByName, type);
1667 return m_pool->createType(
1668 attached, resultLookupIndex, QQmlJSRegisterContent::Attachment,
1696QQmlJSRegisterContent QQmlJSTypeResolver::memberType(
1697 QQmlJSRegisterContent type,
const QString &name,
int lookupIndex)
const
1700 return memberType(type, name, type.resultLookupIndex(), lookupIndex);
1701 if (type.isProperty() || type.isMethodCall())
1702 return memberType(type, name, type.resultLookupIndex(), lookupIndex);
1703 if (type.isEnumeration()) {
1704 const auto enumeration = type.enumeration();
1705 if (!type.enumMember().isEmpty() || !enumeration.hasKey(name))
1707 return m_pool->createEnumeration(
1708 enumeration, name, QQmlJSRegisterContent::Enum, type.scope());
1710 if (type.isMethod()) {
1711 QQmlJSMetaProperty prop;
1712 prop.setTypeName(u"QJSValue"_s);
1713 prop.setPropertyName(name);
1714 prop.setType(jsValueType());
1715 prop.setIsWritable(
true);
1716 return m_pool->createProperty(
1717 prop, QQmlJSRegisterContent::InvalidLookupIndex, lookupIndex,
1718 QQmlJSRegisterContent::Property, type);
1720 if (type.isImportNamespace()) {
1721 Q_ASSERT(type.scopeType()->isReferenceType());
1722 return registerContentForName(name, type);
1724 if (type.isConversion()) {
1725 if (
const auto result = memberType(
1726 type, name, type.resultLookupIndex(), lookupIndex);
1731 if (
const auto result = memberEnumType(type.scope(), name); result.isValid())
1738 const auto nonVoid = extractNonVoidFromOptionalType(type);
1741 return (!nonVoid.isNull() && canHold(type.conversionResultType(), nonVoid.containedType()))
1742 ? memberType(nonVoid, name, type.resultLookupIndex(), lookupIndex)
1743 : QQmlJSRegisterContent();
1746 Q_UNREACHABLE_RETURN({});