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();
652QQmlJSRegisterContent QQmlJSTypeResolver::merge(
653 QQmlJSRegisterContent a, QQmlJSRegisterContent b)
const
659 QSet<QQmlJSRegisterContent> origins;
661 QQmlJSRegisterContent aResultScope;
662 if (a.isConversion()) {
663 const auto aOrigins = a.conversionOrigins();
664 for (
const auto &aOrigin : aOrigins)
665 origins.insert(aOrigin);
666 aResultScope = a.conversionResultScope();
669 aResultScope = a.scope();
672 QQmlJSRegisterContent bResultScope;
673 if (b.isConversion()) {
674 const auto bOrigins = b.conversionOrigins();
675 for (
const auto &bOrigin : bOrigins)
676 origins.insert(bOrigin);
677 bResultScope = b.conversionResultScope();
680 bResultScope = b.scope();
683 const auto mergeScopes = [&](QQmlJSRegisterContent a, QQmlJSRegisterContent b) {
686 return (a == b) ? a : merge(a, b);
689 return m_pool->createConversion(
691 merge(a.containedType(), b.containedType()),
692 mergeScopes(aResultScope, bResultScope),
693 mergeVariants(a.variant(), b.variant()),
694 mergeScopes(a.scope(), b.scope()));
697QQmlJSScope::ConstPtr QQmlJSTypeResolver::merge(
const QQmlJSScope::ConstPtr &a,
698 const QQmlJSScope::ConstPtr &b)
const
706 const auto baseOrExtension
707 = [](
const QQmlJSScope::ConstPtr &a,
const QQmlJSScope::ConstPtr &b) {
708 QQmlJSScope::ConstPtr found;
709 QQmlJSUtils::searchBaseAndExtensionTypes(
710 a, [&](
const QQmlJSScope::ConstPtr &scope, QQmlJSScope::ExtensionKind kind) {
712 case QQmlJSScope::NotExtension:
714 if (b->inherits(scope)) {
719 case QQmlJSScope::ExtensionJavaScript:
728 case QQmlJSScope::ExtensionType:
729 case QQmlJSScope::ExtensionNamespace:
740 if (a == jsValueType() || a == varType())
742 if (b == jsValueType() || b == varType())
745 const auto isInt32Compatible = [&](
const QQmlJSScope::ConstPtr &type) {
746 return (isIntegral(type)
747 && type != uint32Type()
748 && type != int64Type()
749 && type != uint64Type())
750 || type == boolType();
753 if (isInt32Compatible(a) && isInt32Compatible(b))
756 const auto isUInt32Compatible = [&](
const QQmlJSScope::ConstPtr &type) {
757 return (isUnsignedInteger(type) && type != uint64Type()) || type == boolType();
760 if (isUInt32Compatible(a) && isUInt32Compatible(b))
763 if (isNumeric(a) && isNumeric(b))
766 if (isPrimitive(a) && isPrimitive(b))
767 return jsPrimitiveType();
769 if (
const auto base = baseOrExtension(a, b))
772 if (
const auto base = baseOrExtension(b, a))
775 if ((a == nullType() || a == boolType()) && b->isReferenceType())
778 if ((b == nullType() || b == boolType()) && a->isReferenceType())
881QQmlJSScope::ConstPtr QQmlJSTypeResolver::genericType(
882 const QQmlJSScope::ConstPtr &type,
883 ComponentIsGeneric allowComponent)
const
885 if (type->isScript())
886 return m_jsValueType;
888 if (type == m_metaObjectType)
889 return m_metaObjectType;
891 if (type->accessSemantics() == QQmlJSScope::AccessSemantics::Reference) {
892 QString unresolvedBaseTypeName;
893 for (
auto base = type; base;) {
899 if (base->internalName() == u"QObject"_s) {
901 }
else if (allowComponent == ComponentIsGeneric::Yes
902 && base->internalName() == u"QQmlComponent"_s) {
906 if (
auto baseBase = base->baseType()) {
909 unresolvedBaseTypeName = base->baseTypeName();
916 if (type->filePath().isEmpty())
917 return m_jsValueType;
919 m_logger->log(u"Object type %1 is not derived from QObject or QQmlComponent. "
920 "You may need to fully qualify all names in C++ so that moc can see them. "
921 "You may also need to add qt_extract_metatypes(<target containing %2>)."_s
922 .arg(type->internalName(), unresolvedBaseTypeName),
923 qmlCompiler, type->sourceLocation());
926 return m_jsValueType;
929 if (type->isListProperty())
930 return m_listPropertyType;
932 if (type->scopeType() == QQmlSA::ScopeType::EnumScope)
933 return type->baseType();
935 if (isPrimitive(type)) {
937 if (!type->filePath().isEmpty())
947 return m_jsPrimitiveType;
950 for (
const QQmlJSScope::ConstPtr &builtin : {
951 m_realType, m_floatType, m_int8Type, m_uint8Type, m_int16Type, m_uint16Type,
952 m_int32Type, m_uint32Type, m_int64Type, m_uint64Type, m_boolType, m_stringType,
953 m_stringListType, m_byteArrayType, m_urlType, m_dateTimeType, m_dateType,
954 m_timeType, m_variantListType, m_variantMapType, m_varType, m_jsValueType,
955 m_jsPrimitiveType, m_listPropertyType, m_qObjectType, m_qObjectListType,
956 m_metaObjectType, m_forInIteratorPtr, m_forOfIteratorPtr }) {
957 if (type == builtin || type == builtin->listType())
1088QQmlJSScope::ConstPtr QQmlJSTypeResolver::scopedType(
1089 const QQmlJSScope::ConstPtr &scope,
const QString &name,
1090 QQmlJSScopesByIdOptions options)
const
1092 QQmlJSScopesById::CertainCallback<QQmlJSScope::ConstPtr> identified;
1093 if (m_objectsById.possibleScopes(name, scope, options, identified)
1094 != QQmlJSScopesById::Success::Yes) {
1099 if (identified.result) {
1101 return identified.result;
1104 if (QQmlJSScope::ConstPtr base = QQmlJSScope::findCurrentQMLScope(scope)) {
1105 QQmlJSScope::ConstPtr result;
1106 if (QQmlJSUtils::searchBaseAndExtensionTypes(
1107 base, [&](
const QQmlJSScope::ConstPtr &found, QQmlJSScope::ExtensionKind mode) {
1108 if (mode == QQmlJSScope::ExtensionNamespace)
1111 if (found->hasOwnProperty(name)) {
1112 const QQmlJSMetaProperty prop = found->ownProperty(name);
1113 if (!isRevisionAllowed(prop.revision(), scope))
1116 result = resolveParentProperty(name, base, prop.type());
1120 if (found->hasOwnMethod(name)) {
1121 const auto methods = found->ownMethods(name);
1122 for (
const auto &method : methods) {
1123 if (isRevisionAllowed(method.revision(), scope)) {
1124 result = jsValueType();
1136 if (QQmlJSScope::ConstPtr result = containedTypeForName(name))
1139 if (m_jsGlobalObject->hasProperty(name))
1140 return m_jsGlobalObject->property(name).type();
1142 if (m_jsGlobalObject->hasMethod(name))
1143 return jsValueType();
1155QQmlJSRegisterContent QQmlJSTypeResolver::scopedType(QQmlJSRegisterContent scope,
1156 const QString &name,
int lookupIndex,
1157 QQmlJSScopesByIdOptions options)
const
1159 const QQmlJSScope::ConstPtr contained = scope.containedType();
1161 QQmlJSScopesById::CertainCallback<QQmlJSScope::ConstPtr> identified;
1162 if (m_objectsById.possibleScopes(name, contained, options, identified)
1163 != QQmlJSScopesById::Success::Yes) {
1168 if (identified.result) {
1170 return m_pool->createType(
1171 identified.result, lookupIndex, QQmlJSRegisterContent::ObjectById, scope);
1174 if (QQmlJSScope::ConstPtr base = QQmlJSScope::findCurrentQMLScope(contained)) {
1175 QQmlJSRegisterContent result;
1176 if (QQmlJSUtils::searchBaseAndExtensionTypes(
1177 base, [&](
const QQmlJSScope::ConstPtr &found, QQmlJSScope::ExtensionKind mode) {
1178 if (mode == QQmlJSScope::ExtensionNamespace)
1181 const QQmlJSRegisterContent resultScope = mode == QQmlJSScope::NotExtension
1183 : extensionType(found, scope);
1185 if (found->hasOwnProperty(name)) {
1186 QQmlJSMetaProperty prop = found->ownProperty(name);
1187 if (!isRevisionAllowed(prop.revision(), contained))
1190 prop.setType(resolveParentProperty(name, base, prop.type()));
1191 result = m_pool->createProperty(
1192 prop, QQmlJSRegisterContent::InvalidLookupIndex, lookupIndex,
1193 scopeContentVariant(mode,
false), resultScope);
1197 if (found->hasOwnMethod(name)) {
1198 auto methods = found->ownMethods(name);
1199 for (
auto it = methods.begin(); it != methods.end();) {
1200 if (!isRevisionAllowed(it->revision(), contained))
1201 it = methods.erase(it);
1205 if (methods.isEmpty())
1207 result = m_pool->createMethod(
1208 methods, jsValueType(), scopeContentVariant(mode,
true), resultScope);
1219 QQmlJSRegisterContent result = registerContentForName(name, scope);
1221 if (result.isValid())
1224 if (m_jsGlobalObject->hasProperty(name)) {
1225 return m_pool->createProperty(
1226 m_jsGlobalObject->property(name), QQmlJSRegisterContent::InvalidLookupIndex,
1227 lookupIndex, QQmlJSRegisterContent::Property, m_jsGlobalObjectContent);
1228 }
else if (m_jsGlobalObject->hasMethod(name)) {
1229 return m_pool->createMethod(
1230 m_jsGlobalObject->methods(name), jsValueType(),
1231 QQmlJSRegisterContent::Property, m_jsGlobalObjectContent);
1302QQmlJSMetaMethod QQmlJSTypeResolver::selectConstructor(
1303 const QQmlJSScope::ConstPtr &type,
const QQmlJSScope::ConstPtr &passedArgumentType,
1304 bool *isExtension)
const
1309 || canHold(passedArgumentType, type)
1310 || type->accessSemantics() != QQmlJSScope::AccessSemantics::Value
1311 || !type->isCreatable()) {
1312 return QQmlJSMetaMethod();
1315 auto doSelectConstructor = [&](
const QQmlJSScope::ConstPtr &ctorProvider) {
1316 QQmlJSMetaMethod candidate;
1318 const auto ownMethods = ctorProvider->ownMethods();
1319 for (
const QQmlJSMetaMethod &method : ownMethods) {
1320 if (!method.isConstructor())
1323 const auto index = method.constructorIndex();
1324 Q_ASSERT(index != QQmlJSMetaMethod::RelativeFunctionIndex::Invalid);
1326 const auto methodArguments = method.parameters();
1327 if (methodArguments.size() != 1)
1330 const QQmlJSScope::ConstPtr methodArgumentType = methodArguments[0].type();
1333 if (methodArgumentType == type)
1336 if (passedArgumentType == methodArgumentType)
1341 if (!candidate.isValid()
1342 && canPrimitivelyConvertFromTo(passedArgumentType, methodArgumentType)) {
1350 if (QQmlJSScope::ConstPtr extension = type->extensionType().scope) {
1351 const QQmlJSMetaMethod ctor = doSelectConstructor(extension);
1352 if (ctor.isValid()) {
1354 *isExtension =
true;
1360 *isExtension =
false;
1362 return doSelectConstructor(type);
1422bool QQmlJSTypeResolver::canPrimitivelyConvertFromTo(
1423 const QQmlJSScope::ConstPtr &from,
const QQmlJSScope::ConstPtr &to)
const
1427 if (from == m_varType || to == m_varType)
1429 if (from == m_jsValueType || to == m_jsValueType)
1431 if (to == m_qQmlScriptStringType)
1433 if (isNumeric(from) && isNumeric(to))
1436 if (to == m_boolType)
1439 if (from->accessSemantics() == QQmlJSScope::AccessSemantics::Reference
1440 && to == m_stringType) {
1445 if (isNumeric(from) && to == m_stringType)
1449 if (from == m_stringType && isNumeric(to))
1450 return to->scopeType() != QQmlJSScope::ScopeType::EnumScope;
1453 if ((from == m_stringType && to == m_urlType)
1454 || (from == m_urlType && to == m_stringType)) {
1459 if ((from == m_stringType && to == m_byteArrayType)
1460 || (from == m_byteArrayType && to == m_stringType)) {
1464 if (to == m_voidType)
1468 return from == m_voidType;
1470 const auto types = { m_dateTimeType, m_dateType, m_timeType, m_stringType };
1471 for (
const auto &originType : types) {
1472 if (from != originType)
1475 for (
const auto &targetType : types) {
1476 if (to == targetType)
1480 if (to == m_realType)
1486 if (from == m_nullType && to->accessSemantics() == QQmlJSScope::AccessSemantics::Reference)
1489 if (from == m_jsPrimitiveType) {
1491 return isPrimitive(to) || to->accessSemantics() == QQmlJSScope::AccessSemantics::Reference;
1494 if (to == m_jsPrimitiveType)
1495 return isPrimitive(from);
1497 const bool matchByName = !to->isComposite();
1498 Q_ASSERT(!matchByName || !to->internalName().isEmpty());
1499 if (QQmlJSUtils::searchBaseAndExtensionTypes(
1500 from, [&](
const QQmlJSScope::ConstPtr &scope, QQmlJSScope::ExtensionKind kind) {
1502 case QQmlJSScope::NotExtension:
1503 case QQmlJSScope::ExtensionJavaScript:
1509 || (matchByName && scope->internalName() == to->internalName());
1510 case QQmlJSScope::ExtensionType:
1511 case QQmlJSScope::ExtensionNamespace:
1519 if (from == m_variantListType)
1520 return to->accessSemantics() == QQmlJSScope::AccessSemantics::Sequence;
1523 if (canPrimitivelyConvertFromTo(from, m_jsPrimitiveType)
1524 && canPrimitivelyConvertFromTo(m_jsPrimitiveType, to)) {
1528 if (areEquivalentLists(from, to))
1531 if (from->isListProperty()
1532 && to->accessSemantics() == QQmlJSScope::AccessSemantics::Sequence
1533 && canConvertFromTo(from->elementType(), to->elementType())) {
1538 if (to->accessSemantics() == QQmlJSScope::AccessSemantics::Sequence
1539 && from->accessSemantics() == QQmlJSScope::AccessSemantics::Reference
1540 && from->inherits(to->elementType())) {
1544 if (to == m_stringType && from->accessSemantics() == QQmlJSScope::AccessSemantics::Sequence)
1545 return canConvertFromTo(from->elementType(), m_stringType);
1563QQmlJSRegisterContent QQmlJSTypeResolver::memberType(
1564 QQmlJSRegisterContent type,
const QString &name,
int baseLookupIndex,
1565 int resultLookupIndex)
const
1567 QQmlJSRegisterContent result;
1568 const QQmlJSScope::ConstPtr contained = type.containedType();
1571 if (contained == metaObjectType())
1572 return memberEnumType(type.scope(), name);
1574 if (contained == variantMapType() || contained->inherits(qmlPropertyMapType())) {
1575 QQmlJSMetaProperty prop;
1576 prop.setPropertyName(name);
1577 prop.setTypeName(u"QVariant"_s);
1578 prop.setType(varType());
1579 prop.setIsWritable(
true);
1580 return m_pool->createProperty(
1581 prop, baseLookupIndex, resultLookupIndex,
1582 QQmlJSRegisterContent::Property, type);
1585 if (contained == jsValueType()) {
1586 QQmlJSMetaProperty prop;
1587 prop.setPropertyName(name);
1588 prop.setTypeName(u"QJSValue"_s);
1589 prop.setType(jsValueType());
1590 prop.setIsWritable(
true);
1591 return m_pool->createProperty(
1592 prop, baseLookupIndex, resultLookupIndex,
1593 QQmlJSRegisterContent::Property, type);
1596 if ((contained == stringType()
1597 || contained->accessSemantics() == QQmlJSScope::AccessSemantics::Sequence)
1598 && name == u"length"_s) {
1599 return lengthProperty(contained != stringType(), type);
1602 const auto check = [&](
const QQmlJSScope::ConstPtr &scope, QQmlJSScope::ExtensionKind mode) {
1603 const QQmlJSRegisterContent resultScope = mode == QQmlJSScope::NotExtension
1604 ? baseType(scope, type)
1605 : extensionType(scope, type);
1607 if (mode != QQmlJSScope::ExtensionNamespace) {
1608 if (scope->hasOwnProperty(name)) {
1609 const auto prop = scope->ownProperty(name);
1610 result = m_pool->createProperty(
1611 prop, baseLookupIndex, resultLookupIndex,
1612 QQmlJSRegisterContent::Property, resultScope);
1616 if (scope->hasOwnMethod(name)) {
1617 const auto methods = scope->ownMethods(name);
1618 result = m_pool->createMethod(
1619 methods, jsValueType(), QQmlJSRegisterContent::Method, resultScope);
1624 if (type.variant() == QQmlJSRegisterContent::ObjectById)
1626 return checkEnums(resultScope, name, &result);
1629 if (QQmlJSUtils::searchBaseAndExtensionTypes(type.containedType(), check))
1632 for (
auto scope = contained;
1633 scope && (QQmlSA::isFunctionScope(scope->scopeType())
1634 || scope->scopeType() == QQmlSA::ScopeType::JSLexicalScope);
1635 scope = scope->parentScope()) {
1636 if (
auto ownIdentifier = scope->ownJSIdentifier(name)) {
1637 QQmlJSMetaProperty prop;
1638 prop.setPropertyName(name);
1639 prop.setTypeName(u"QJSValue"_s);
1640 prop.setType(jsValueType());
1641 prop.setIsWritable(!(ownIdentifier.value().isConst));
1643 return m_pool->createProperty(
1644 prop, baseLookupIndex, resultLookupIndex,
1645 QQmlJSRegisterContent::Property,
1646 parentScope(scope, type));
1651 if (type.isType()) {
1652 if (
auto result = memberEnumType(type.scope(), name); result.isValid())
1656 if (QQmlJSScope::ConstPtr attachedBase = typeForName(name)) {
1657 if (QQmlJSScope::ConstPtr attached = attachedBase->attachedType()) {
1658 if (!genericType(attached)) {
1659 m_logger->log(u"Cannot resolve generic base of attached %1"_s.arg(
1660 attached->internalName()),
1661 qmlCompiler, attached->sourceLocation());
1663 }
else if (contained->accessSemantics() != QQmlJSScope::AccessSemantics::Reference) {
1664 m_logger->log(u"Cannot retrieve attached object for non-reference type %1"_s.arg(
1665 contained->internalName()),
1666 qmlCompiler, contained->sourceLocation());
1669 const QQmlJSRegisterContent namedType = m_pool->createType(
1670 attachedBase, QQmlJSRegisterContent::InvalidLookupIndex,
1671 QQmlJSRegisterContent::TypeByName, type);
1673 return m_pool->createType(
1674 attached, resultLookupIndex, QQmlJSRegisterContent::Attachment,
1702QQmlJSRegisterContent QQmlJSTypeResolver::memberType(
1703 QQmlJSRegisterContent type,
const QString &name,
int lookupIndex)
const
1706 return memberType(type, name, type.resultLookupIndex(), lookupIndex);
1707 if (type.isProperty() || type.isMethodCall())
1708 return memberType(type, name, type.resultLookupIndex(), lookupIndex);
1709 if (type.isEnumeration()) {
1710 const auto enumeration = type.enumeration();
1711 if (!type.enumMember().isEmpty() || !enumeration.hasKey(name))
1713 return m_pool->createEnumeration(
1714 enumeration, name, QQmlJSRegisterContent::Enum, type.scope());
1716 if (type.isMethod()) {
1717 QQmlJSMetaProperty prop;
1718 prop.setTypeName(u"QJSValue"_s);
1719 prop.setPropertyName(name);
1720 prop.setType(jsValueType());
1721 prop.setIsWritable(
true);
1722 return m_pool->createProperty(
1723 prop, QQmlJSRegisterContent::InvalidLookupIndex, lookupIndex,
1724 QQmlJSRegisterContent::Property, type);
1726 if (type.isImportNamespace()) {
1727 Q_ASSERT(type.scopeType()->isReferenceType());
1728 return registerContentForName(name, type);
1730 if (type.isConversion()) {
1731 if (
const auto result = memberType(
1732 type, name, type.resultLookupIndex(), lookupIndex);
1737 if (
const auto result = memberEnumType(type.scope(), name); result.isValid())
1744 const auto nonVoid = extractNonVoidFromOptionalType(type);
1747 return (!nonVoid.isNull() && canHold(type.conversionResultType(), nonVoid.containedType()))
1748 ? memberType(nonVoid, name, type.resultLookupIndex(), lookupIndex)
1749 : QQmlJSRegisterContent();
1752 Q_UNREACHABLE_RETURN({});