31QQmlJSTypeResolver::QQmlJSTypeResolver(QQmlJSImporter *importer)
32 : m_pool(std::make_unique<QQmlJSRegisterContentPool>())
33 , m_imports(importer->builtinInternalNames())
34 , m_importer(importer)
36 const QQmlJSImporter::ImportedTypes &builtinTypes = m_imports;
38 m_voidType = builtinTypes.type(u"void"_s).scope;
39 assertExtension(m_voidType,
"undefined"_L1);
41 m_nullType = builtinTypes.type(u"std::nullptr_t"_s).scope;
44 m_realType = builtinTypes.type(u"double"_s).scope;
45 assertExtension(m_realType,
"Number"_L1);
47 m_floatType = builtinTypes.type(u"float"_s).scope;
48 assertExtension(m_floatType,
"Number"_L1);
50 m_int8Type = builtinTypes.type(u"qint8"_s).scope;
51 assertExtension(m_int8Type,
"Number"_L1);
53 m_uint8Type = builtinTypes.type(u"quint8"_s).scope;
54 assertExtension(m_uint8Type,
"Number"_L1);
56 m_int16Type = builtinTypes.type(u"short"_s).scope;
57 assertExtension(m_int16Type,
"Number"_L1);
59 m_uint16Type = builtinTypes.type(u"ushort"_s).scope;
60 assertExtension(m_uint16Type,
"Number"_L1);
62 m_int32Type = builtinTypes.type(u"int"_s).scope;
63 assertExtension(m_int32Type,
"Number"_L1);
65 m_uint32Type = builtinTypes.type(u"uint"_s).scope;
66 assertExtension(m_uint32Type,
"Number"_L1);
68 m_int64Type = builtinTypes.type(u"qlonglong"_s).scope;
69 Q_ASSERT(m_int64Type);
71 m_uint64Type = builtinTypes.type(u"qulonglong"_s).scope;
72 Q_ASSERT(m_uint64Type);
74 m_sizeType = builtinTypes.type(u"qsizetype"_s).scope;
75 assertExtension(m_sizeType,
"Number"_L1);
78 Q_ASSERT(m_sizeType == m_int32Type || m_sizeType == m_int64Type);
80 m_boolType = builtinTypes.type(u"bool"_s).scope;
81 assertExtension(m_boolType,
"Boolean"_L1);
83 m_stringType = builtinTypes.type(u"QString"_s).scope;
84 assertExtension(m_stringType,
"String"_L1);
86 m_stringListType = builtinTypes.type(u"QStringList"_s).scope;
87 assertExtension(m_stringListType,
"Array"_L1);
89 m_byteArrayType = builtinTypes.type(u"QByteArray"_s).scope;
90 assertExtension(m_byteArrayType,
"ArrayBuffer"_L1);
92 m_urlType = builtinTypes.type(u"QUrl"_s).scope;
93 assertExtension(m_urlType,
"URL"_L1);
95 m_dateTimeType = builtinTypes.type(u"QDateTime"_s).scope;
96 assertExtension(m_dateTimeType,
"Date"_L1);
98 m_dateType = builtinTypes.type(u"QDate"_s).scope;
101 m_timeType = builtinTypes.type(u"QTime"_s).scope;
102 Q_ASSERT(m_timeType);
104 m_regexpType = builtinTypes.type(u"QRegularExpression"_s).scope;
105 Q_ASSERT(m_regexpType);
107 m_variantListType = builtinTypes.type(u"QVariantList"_s).scope;
108 assertExtension(m_variantListType,
"Array"_L1);
110 m_variantMapType = builtinTypes.type(u"QVariantMap"_s).scope;
111 Q_ASSERT(m_variantMapType);
112 m_varType = builtinTypes.type(u"QVariant"_s).scope;
115 m_qmlPropertyMapType = builtinTypes.type(u"QQmlPropertyMap"_s).scope;
116 Q_ASSERT(m_qmlPropertyMapType);
118 m_jsValueType = builtinTypes.type(u"QJSValue"_s).scope;
119 Q_ASSERT(m_jsValueType);
121 m_qObjectType = builtinTypes.type(u"QObject"_s).scope;
122 assertExtension(m_qObjectType,
"Object"_L1);
124 m_qObjectListType = builtinTypes.type(u"QObjectList"_s).scope;
125 assertExtension(m_qObjectListType,
"Array"_L1);
127 m_qQmlScriptStringType = builtinTypes.type(u"QQmlScriptString"_s).scope;
128 Q_ASSERT(m_qQmlScriptStringType);
130 m_functionType = builtinTypes.type(u"function"_s).scope;
131 Q_ASSERT(m_functionType);
133 m_numberPrototype = builtinTypes.type(u"NumberPrototype"_s).scope;
134 Q_ASSERT(m_numberPrototype);
136 m_arrayPrototype = builtinTypes.type(u"ArrayPrototype"_s).scope;
137 Q_ASSERT(m_arrayPrototype);
139 m_listPropertyType = m_qObjectType->listType();
140 Q_ASSERT(m_listPropertyType->internalName() == u"QQmlListProperty<QObject>"_s);
141 Q_ASSERT(m_listPropertyType->accessSemantics() == QQmlJSScope::AccessSemantics::Sequence);
142 Q_ASSERT(m_listPropertyType->elementTypeName() == u"QObject"_s);
143 assertExtension(m_listPropertyType,
"Array"_L1);
145 QQmlJSScope::Ptr emptyType = QQmlJSScope::create();
146 emptyType->setAccessSemantics(QQmlJSScope::AccessSemantics::None);
147 m_emptyType = emptyType;
149 QQmlJSScope::Ptr jsPrimitiveType = QQmlJSScope::create();
150 jsPrimitiveType->setInternalName(u"QJSPrimitiveValue"_s);
151 jsPrimitiveType->setFilePath(u"qjsprimitivevalue.h"_s);
152 jsPrimitiveType->setAccessSemantics(QQmlJSScope::AccessSemantics::Value);
153 m_jsPrimitiveType = jsPrimitiveType;
155 QQmlJSScope::Ptr metaObjectType = QQmlJSScope::create();
156 metaObjectType->setInternalName(u"const QMetaObject"_s);
157 metaObjectType->setFilePath(u"qmetaobject.h"_s);
158 metaObjectType->setAccessSemantics(QQmlJSScope::AccessSemantics::Reference);
159 m_metaObjectType = metaObjectType;
161 m_jsGlobalObject = importer->jsGlobalObject();
163 QQmlJSScope::Ptr forInIteratorPtr = QQmlJSScope::create();
164 forInIteratorPtr->setAccessSemantics(QQmlJSScope::AccessSemantics::Value);
165 forInIteratorPtr->setFilePath(u"qjslist.h"_s);
166 forInIteratorPtr->setInternalName(u"QJSListForInIterator::Ptr"_s);
167 m_forInIteratorPtr = forInIteratorPtr;
169 QQmlJSScope::Ptr forOfIteratorPtr = QQmlJSScope::create();
170 forOfIteratorPtr->setAccessSemantics(QQmlJSScope::AccessSemantics::Value);
171 forOfIteratorPtr->setFilePath(u"qjslist.h"_s);
172 forOfIteratorPtr->setInternalName(u"QJSListForOfIterator::Ptr"_s);
173 m_forOfIteratorPtr = forOfIteratorPtr;
176 m_jsGlobalObjectContent = m_pool->createType(
177 m_jsGlobalObject, QQmlJSRegisterContent::InvalidLookupIndex,
178 QQmlJSRegisterContent::ScopeObject);
263QQmlJSTypeResolver::typeForBinaryOperation(QSOperator::Op oper, QQmlJSRegisterContent left,
264 QQmlJSRegisterContent right)
const
266 Q_ASSERT(left.isValid());
267 Q_ASSERT(right.isValid());
270 case QSOperator::Op::Equal:
271 case QSOperator::Op::NotEqual:
272 case QSOperator::Op::StrictEqual:
273 case QSOperator::Op::StrictNotEqual:
274 case QSOperator::Op::Lt:
275 case QSOperator::Op::Gt:
276 case QSOperator::Op::Ge:
277 case QSOperator::Op::In:
278 case QSOperator::Op::Le:
279 return operationType(boolType());
280 case QSOperator::Op::BitAnd:
281 case QSOperator::Op::BitOr:
282 case QSOperator::Op::BitXor:
283 case QSOperator::Op::LShift:
284 case QSOperator::Op::RShift:
285 return operationType(int32Type());
286 case QSOperator::Op::URShift:
287 return operationType(uint32Type());
288 case QSOperator::Op::Add: {
289 const auto leftContents = left.containedType();
290 const auto rightContents = right.containedType();
291 if (leftContents == stringType() || rightContents == stringType())
292 return operationType(stringType());
294 const QQmlJSScope::ConstPtr result = merge(leftContents, rightContents);
295 if (result == boolType())
296 return operationType(int32Type());
297 if (isNumeric(result))
298 return operationType(realType());
300 return operationType(jsPrimitiveType());
302 case QSOperator::Op::Sub:
303 case QSOperator::Op::Mul:
304 case QSOperator::Op::Exp: {
305 const QQmlJSScope::ConstPtr result = merge(left.containedType(), right.containedType());
306 return operationType(result == boolType() ? int32Type() : realType());
308 case QSOperator::Op::Div:
309 case QSOperator::Op::Mod:
310 return operationType(realType());
311 case QSOperator::Op::As:
312 return operationType(right.containedType());
317 return operationType(merge(left.containedType(), right.containedType()));
455QQmlJSRegisterContent QQmlJSTypeResolver::registerContentForName(
456 const QString &name, QQmlJSRegisterContent scopeType)
const
458 QQmlJSScope::ConstPtr type = typeForName(name);
460 return QQmlJSRegisterContent();
462 if (type->isSingleton()) {
463 return m_pool->createType(
464 type, QQmlJSRegisterContent::InvalidLookupIndex,
465 QQmlJSRegisterContent::Singleton, scopeType);
468 if (type->isScript()) {
469 return m_pool->createType(
470 type, QQmlJSRegisterContent::InvalidLookupIndex,
471 QQmlJSRegisterContent::Script, scopeType);
474 const QQmlJSRegisterContent namedType = m_pool->createType(
475 type, QQmlJSRegisterContent::InvalidLookupIndex, QQmlJSRegisterContent::TypeByName,
478 if (
const auto attached = type->attachedType()) {
479 if (!genericType(attached)) {
480 m_logger->log(u"Cannot resolve generic base of attached %1"_s.arg(
481 attached->internalName()),
482 qmlCompiler, attached->sourceLocation());
484 }
else if (type->accessSemantics() != QQmlJSScope::AccessSemantics::Reference) {
485 m_logger->log(u"Cannot retrieve attached object for non-reference type %1"_s.arg(
486 type->internalName()),
487 qmlCompiler, type->sourceLocation());
493 return m_pool->createType(
494 attached, QQmlJSRegisterContent::InvalidLookupIndex,
495 QQmlJSRegisterContent::Attachment, namedType);
499 switch (type->accessSemantics()) {
500 case QQmlJSScope::AccessSemantics::None:
501 case QQmlJSScope::AccessSemantics::Reference:
506 return m_pool->createType(
507 metaObjectType(), QQmlJSRegisterContent::InvalidLookupIndex,
508 QQmlJSRegisterContent::MetaType, namedType);
509 case QQmlJSScope::AccessSemantics::Sequence:
510 case QQmlJSScope::AccessSemantics::Value:
511 if (scopeType.isImportNamespace() || canAddressValueTypes()) {
512 return m_pool->createType(
513 metaObjectType(), QQmlJSRegisterContent::InvalidLookupIndex,
514 QQmlJSRegisterContent::MetaType, namedType);
521 return QQmlJSRegisterContent();
654QQmlJSRegisterContent QQmlJSTypeResolver::merge(
655 QQmlJSRegisterContent a, QQmlJSRegisterContent b)
const
660 const RegisterPair key(a, b);
661 if (
const auto it = m_mergeCache.constFind(key); it != m_mergeCache.constEnd())
662 return m_pool->clone(*it);
666 QSet<QQmlJSRegisterContent> origins;
668 QQmlJSRegisterContent aResultScope;
669 if (a.isConversion()) {
670 const auto &aOrigins = a.conversionOrigins();
671 for (
const auto &aOrigin : aOrigins)
672 origins.insert(aOrigin);
673 aResultScope = a.conversionResultScope();
676 aResultScope = a.scope();
679 QQmlJSRegisterContent bResultScope;
680 if (b.isConversion()) {
681 const auto &bOrigins = b.conversionOrigins();
682 for (
const auto &bOrigin : bOrigins)
683 origins.insert(bOrigin);
684 bResultScope = b.conversionResultScope();
687 bResultScope = b.scope();
690 const auto mergeScopes = [&](QQmlJSRegisterContent a, QQmlJSRegisterContent b) {
693 return (a == b) ? a : merge(a, b);
696 const QQmlJSRegisterContent merged = m_pool->createConversion(
698 merge(a.containedType(), b.containedType()),
699 mergeScopes(aResultScope, bResultScope),
700 mergeVariants(a.variant(), b.variant()),
701 mergeScopes(a.scope(), b.scope()));
703 m_mergeCache.insert(key, m_pool->clone(merged));
707QQmlJSScope::ConstPtr QQmlJSTypeResolver::merge(
const QQmlJSScope::ConstPtr &a,
708 const QQmlJSScope::ConstPtr &b)
const
716 const auto baseOrExtension
717 = [](
const QQmlJSScope::ConstPtr &a,
const QQmlJSScope::ConstPtr &b) {
718 QQmlJSScope::ConstPtr found;
719 QQmlJSUtils::searchBaseAndExtensionTypes(
720 a, [&](
const QQmlJSScope::ConstPtr &scope, QQmlJSScope::ExtensionKind kind) {
722 case QQmlJSScope::NotExtension:
724 if (b->inherits(scope)) {
729 case QQmlJSScope::ExtensionJavaScript:
738 case QQmlJSScope::ExtensionType:
739 case QQmlJSScope::ExtensionNamespace:
750 if (a == jsValueType() || a == varType())
752 if (b == jsValueType() || b == varType())
755 const auto isInt32Compatible = [&](
const QQmlJSScope::ConstPtr &type) {
756 return (isIntegral(type)
757 && type != uint32Type()
758 && type != int64Type()
759 && type != uint64Type())
760 || type == boolType();
763 if (isInt32Compatible(a) && isInt32Compatible(b))
766 const auto isUInt32Compatible = [&](
const QQmlJSScope::ConstPtr &type) {
767 return (isUnsignedInteger(type) && type != uint64Type()) || type == boolType();
770 if (isUInt32Compatible(a) && isUInt32Compatible(b))
773 if (isNumeric(a) && isNumeric(b))
776 if (isPrimitive(a) && isPrimitive(b))
777 return jsPrimitiveType();
779 if (
const auto base = baseOrExtension(a, b))
782 if (
const auto base = baseOrExtension(b, a))
785 if ((a == nullType() || a == boolType()) && b->isReferenceType())
788 if ((b == nullType() || b == boolType()) && a->isReferenceType())
892QQmlJSScope::ConstPtr QQmlJSTypeResolver::genericType(
893 const QQmlJSScope::ConstPtr &type,
894 ComponentIsGeneric allowComponent)
const
896 if (type->isScript())
897 return m_jsValueType;
899 if (type == m_metaObjectType)
900 return m_metaObjectType;
902 if (type->accessSemantics() == QQmlJSScope::AccessSemantics::Reference) {
903 QString unresolvedBaseTypeName;
904 for (
auto base = type; base;) {
910 if (base->internalName() == u"QObject"_s) {
912 }
else if (allowComponent == ComponentIsGeneric::Yes
913 && base->internalName() == u"QQmlComponent"_s) {
917 if (
auto baseBase = base->baseType()) {
920 unresolvedBaseTypeName = base->baseTypeName();
927 if (type->filePath().isEmpty())
928 return m_jsValueType;
930 m_logger->log(u"Object type %1 is not derived from QObject or QQmlComponent. "
931 "You may need to fully qualify all names in C++ so that moc can see them. "
932 "You may also need to add qt_extract_metatypes(<target containing %2>)."_s
933 .arg(type->internalName(), unresolvedBaseTypeName),
934 qmlCompiler, type->sourceLocation());
937 return m_jsValueType;
940 if (type->isListProperty())
941 return m_listPropertyType;
943 if (type->scopeType() == QQmlSA::ScopeType::EnumScope)
944 return type->baseType();
946 if (isPrimitive(type)) {
948 if (!type->filePath().isEmpty())
958 return m_jsPrimitiveType;
961 for (
const QQmlJSScope::ConstPtr &builtin : {
962 m_realType, m_floatType, m_int8Type, m_uint8Type, m_int16Type, m_uint16Type,
963 m_int32Type, m_uint32Type, m_int64Type, m_uint64Type, m_boolType, m_stringType,
964 m_stringListType, m_byteArrayType, m_urlType, m_dateTimeType, m_dateType,
965 m_timeType, m_variantListType, m_variantMapType, m_varType, m_jsValueType,
966 m_jsPrimitiveType, m_listPropertyType, m_qObjectType, m_qObjectListType,
967 m_metaObjectType, m_forInIteratorPtr, m_forOfIteratorPtr }) {
968 if (type == builtin || type == builtin->listType())
1099QQmlJSScope::ConstPtr QQmlJSTypeResolver::scopedType(
1100 const QQmlJSScope::ConstPtr &scope,
const QString &name,
1101 QQmlJSScopesByIdOptions options)
const
1103 QQmlJSScopesById::CertainCallback<QQmlJSScope::ConstPtr> identified;
1104 if (m_objectsById.possibleScopes(name, scope, options, identified)
1105 != QQmlJSScopesById::Success::Yes) {
1110 if (identified.result) {
1112 return identified.result;
1115 if (QQmlJSScope::ConstPtr base = QQmlJSScope::findCurrentQMLScope(scope)) {
1116 QQmlJSScope::ConstPtr result;
1117 if (QQmlJSUtils::searchBaseAndExtensionTypes(
1118 base, [&](
const QQmlJSScope::ConstPtr &found, QQmlJSScope::ExtensionKind mode) {
1119 if (mode == QQmlJSScope::ExtensionNamespace)
1122 if (found->hasOwnProperty(name)) {
1123 const QQmlJSMetaProperty prop = found->ownProperty(name);
1124 if (!isRevisionAllowed(prop.revision(), scope))
1127 result = resolveParentProperty(name, base, prop.type());
1131 if (found->hasOwnMethod(name)) {
1132 const auto methods = found->ownMethods(name);
1133 for (
const auto &method : methods) {
1134 if (isRevisionAllowed(method.revision(), scope)) {
1135 result = jsValueType();
1147 if (QQmlJSScope::ConstPtr result = containedTypeForName(name))
1150 if (m_jsGlobalObject->hasProperty(name))
1151 return m_jsGlobalObject->property(name).type();
1153 if (m_jsGlobalObject->hasMethod(name))
1154 return jsValueType();
1166QQmlJSRegisterContent QQmlJSTypeResolver::scopedType(QQmlJSRegisterContent scope,
1167 const QString &name,
int lookupIndex,
1168 QQmlJSScopesByIdOptions options)
const
1170 const QQmlJSScope::ConstPtr contained = scope.containedType();
1172 QQmlJSScopesById::CertainCallback<QQmlJSScope::ConstPtr> identified;
1173 if (m_objectsById.possibleScopes(name, contained, options, identified)
1174 != QQmlJSScopesById::Success::Yes) {
1179 if (identified.result) {
1181 return m_pool->createType(
1182 identified.result, lookupIndex, QQmlJSRegisterContent::ObjectById, scope);
1185 if (QQmlJSScope::ConstPtr base = QQmlJSScope::findCurrentQMLScope(contained)) {
1186 QQmlJSRegisterContent result;
1187 if (QQmlJSUtils::searchBaseAndExtensionTypes(
1188 base, [&](
const QQmlJSScope::ConstPtr &found, QQmlJSScope::ExtensionKind mode) {
1189 if (mode == QQmlJSScope::ExtensionNamespace)
1192 const QQmlJSRegisterContent resultScope = mode == QQmlJSScope::NotExtension
1194 : extensionType(found, scope);
1196 if (found->hasOwnProperty(name)) {
1197 QQmlJSMetaProperty prop = found->ownProperty(name);
1198 if (!isRevisionAllowed(prop.revision(), contained))
1201 prop.setType(resolveParentProperty(name, base, prop.type()));
1202 result = m_pool->createProperty(
1203 prop, QQmlJSRegisterContent::InvalidLookupIndex, lookupIndex,
1204 scopeContentVariant(mode,
false), resultScope);
1208 if (found->hasOwnMethod(name)) {
1209 auto methods = found->ownMethods(name);
1210 for (
auto it = methods.begin(); it != methods.end();) {
1211 if (!isRevisionAllowed(it->revision(), contained))
1212 it = methods.erase(it);
1216 if (methods.isEmpty())
1218 result = m_pool->createMethod(
1219 methods, jsValueType(), scopeContentVariant(mode,
true), resultScope);
1230 QQmlJSRegisterContent result = registerContentForName(name, scope);
1232 if (result.isValid())
1235 if (m_jsGlobalObject->hasProperty(name)) {
1236 return m_pool->createProperty(
1237 m_jsGlobalObject->property(name), QQmlJSRegisterContent::InvalidLookupIndex,
1238 lookupIndex, QQmlJSRegisterContent::Property, m_jsGlobalObjectContent);
1239 }
else if (m_jsGlobalObject->hasMethod(name)) {
1240 return m_pool->createMethod(
1241 m_jsGlobalObject->methods(name), jsValueType(),
1242 QQmlJSRegisterContent::Property, m_jsGlobalObjectContent);
1313QQmlJSMetaMethod QQmlJSTypeResolver::selectConstructor(
1314 const QQmlJSScope::ConstPtr &type,
const QQmlJSScope::ConstPtr &passedArgumentType,
1315 bool *isExtension)
const
1320 || canHold(passedArgumentType, type)
1321 || type->accessSemantics() != QQmlJSScope::AccessSemantics::Value
1322 || !type->isCreatable()) {
1323 return QQmlJSMetaMethod();
1326 auto doSelectConstructor = [&](
const QQmlJSScope::ConstPtr &ctorProvider) {
1327 QQmlJSMetaMethod candidate;
1329 const auto ownMethods = ctorProvider->ownMethods();
1330 for (
const QQmlJSMetaMethod &method : ownMethods) {
1331 if (!method.isConstructor())
1334 const auto index = method.constructorIndex();
1335 Q_ASSERT(index != QQmlJSMetaMethod::RelativeFunctionIndex::Invalid);
1337 const auto methodArguments = method.parameters();
1338 if (methodArguments.size() != 1)
1341 const QQmlJSScope::ConstPtr methodArgumentType = methodArguments[0].type();
1344 if (methodArgumentType == type)
1347 if (passedArgumentType == methodArgumentType)
1352 if (!candidate.isValid()
1353 && canPrimitivelyConvertFromTo(passedArgumentType, methodArgumentType)) {
1361 if (QQmlJSScope::ConstPtr extension = type->extensionType().scope) {
1362 const QQmlJSMetaMethod ctor = doSelectConstructor(extension);
1363 if (ctor.isValid()) {
1365 *isExtension =
true;
1371 *isExtension =
false;
1373 return doSelectConstructor(type);
1433bool QQmlJSTypeResolver::canPrimitivelyConvertFromTo(
1434 const QQmlJSScope::ConstPtr &from,
const QQmlJSScope::ConstPtr &to)
const
1438 if (from == m_varType || to == m_varType)
1440 if (from == m_jsValueType || to == m_jsValueType)
1442 if (to == m_qQmlScriptStringType)
1444 if (isNumeric(from) && isNumeric(to))
1447 if (to == m_boolType)
1450 if (from->accessSemantics() == QQmlJSScope::AccessSemantics::Reference
1451 && to == m_stringType) {
1456 if (isNumeric(from) && to == m_stringType)
1460 if (from == m_stringType && isNumeric(to))
1461 return to->scopeType() != QQmlJSScope::ScopeType::EnumScope;
1464 if ((from == m_stringType && to == m_urlType)
1465 || (from == m_urlType && to == m_stringType)) {
1470 if ((from == m_stringType && to == m_byteArrayType)
1471 || (from == m_byteArrayType && to == m_stringType)) {
1475 if (to == m_voidType)
1479 return from == m_voidType;
1481 const auto types = { m_dateTimeType, m_dateType, m_timeType, m_stringType };
1482 for (
const auto &originType : types) {
1483 if (from != originType)
1486 for (
const auto &targetType : types) {
1487 if (to == targetType)
1491 if (to == m_realType)
1497 if (from == m_nullType && to->accessSemantics() == QQmlJSScope::AccessSemantics::Reference)
1500 if (from == m_jsPrimitiveType) {
1502 return isPrimitive(to) || to->accessSemantics() == QQmlJSScope::AccessSemantics::Reference;
1505 if (to == m_jsPrimitiveType)
1506 return isPrimitive(from);
1508 const bool matchByName = !to->isComposite();
1509 Q_ASSERT(!matchByName || !to->internalName().isEmpty());
1510 if (QQmlJSUtils::searchBaseAndExtensionTypes(
1511 from, [&](
const QQmlJSScope::ConstPtr &scope, QQmlJSScope::ExtensionKind kind) {
1513 case QQmlJSScope::NotExtension:
1514 case QQmlJSScope::ExtensionJavaScript:
1520 || (matchByName && scope->internalName() == to->internalName());
1521 case QQmlJSScope::ExtensionType:
1522 case QQmlJSScope::ExtensionNamespace:
1530 if (from == m_variantListType)
1531 return to->accessSemantics() == QQmlJSScope::AccessSemantics::Sequence;
1534 if (canPrimitivelyConvertFromTo(from, m_jsPrimitiveType)
1535 && canPrimitivelyConvertFromTo(m_jsPrimitiveType, to)) {
1539 if (areEquivalentLists(from, to))
1542 if (from->isListProperty()
1543 && to->accessSemantics() == QQmlJSScope::AccessSemantics::Sequence
1544 && canConvertFromTo(from->elementType(), to->elementType())) {
1549 if (to->accessSemantics() == QQmlJSScope::AccessSemantics::Sequence
1550 && from->accessSemantics() == QQmlJSScope::AccessSemantics::Reference
1551 && from->inherits(to->elementType())) {
1555 if (to == m_stringType && from->accessSemantics() == QQmlJSScope::AccessSemantics::Sequence)
1556 return canConvertFromTo(from->elementType(), m_stringType);
1574QQmlJSRegisterContent QQmlJSTypeResolver::memberType(
1575 QQmlJSRegisterContent type,
const QString &name,
int baseLookupIndex,
1576 int resultLookupIndex)
const
1578 QQmlJSRegisterContent result;
1579 const QQmlJSScope::ConstPtr contained = type.containedType();
1582 if (contained == metaObjectType())
1583 return memberEnumType(type.scope(), name);
1585 if (contained == variantMapType() || contained->inherits(qmlPropertyMapType())) {
1586 QQmlJSMetaProperty prop;
1587 prop.setPropertyName(name);
1588 prop.setTypeName(u"QVariant"_s);
1589 prop.setType(varType());
1590 prop.setIsWritable(
true);
1591 return m_pool->createProperty(
1592 prop, baseLookupIndex, resultLookupIndex,
1593 QQmlJSRegisterContent::Property, type);
1596 if (contained == jsValueType()) {
1597 QQmlJSMetaProperty prop;
1598 prop.setPropertyName(name);
1599 prop.setTypeName(u"QJSValue"_s);
1600 prop.setType(jsValueType());
1601 prop.setIsWritable(
true);
1602 return m_pool->createProperty(
1603 prop, baseLookupIndex, resultLookupIndex,
1604 QQmlJSRegisterContent::Property, type);
1607 if ((contained == stringType()
1608 || contained->accessSemantics() == QQmlJSScope::AccessSemantics::Sequence)
1609 && name == u"length"_s) {
1610 return lengthProperty(contained != stringType(), type);
1613 const auto check = [&](
const QQmlJSScope::ConstPtr &scope, QQmlJSScope::ExtensionKind mode) {
1614 const QQmlJSRegisterContent resultScope = mode == QQmlJSScope::NotExtension
1615 ? baseType(scope, type)
1616 : extensionType(scope, type);
1618 if (mode != QQmlJSScope::ExtensionNamespace) {
1619 if (scope->hasOwnProperty(name)) {
1620 const auto prop = scope->ownProperty(name);
1621 result = m_pool->createProperty(
1622 prop, baseLookupIndex, resultLookupIndex,
1623 QQmlJSRegisterContent::Property, resultScope);
1627 if (scope->hasOwnMethod(name)) {
1628 const auto methods = scope->ownMethods(name);
1629 result = m_pool->createMethod(
1630 methods, jsValueType(), QQmlJSRegisterContent::Method, resultScope);
1635 if (type.variant() == QQmlJSRegisterContent::ObjectById)
1637 return checkEnums(resultScope, name, &result);
1640 if (QQmlJSUtils::searchBaseAndExtensionTypes(type.containedType(), check))
1643 for (
auto scope = contained;
1644 scope && (QQmlSA::isFunctionScope(scope->scopeType())
1645 || scope->scopeType() == QQmlSA::ScopeType::JSLexicalScope);
1646 scope = scope->parentScope()) {
1647 if (
auto ownIdentifier = scope->ownJSIdentifier(name)) {
1648 QQmlJSMetaProperty prop;
1649 prop.setPropertyName(name);
1650 prop.setTypeName(u"QJSValue"_s);
1651 prop.setType(jsValueType());
1652 prop.setIsWritable(!(ownIdentifier.value().isConst));
1654 return m_pool->createProperty(
1655 prop, baseLookupIndex, resultLookupIndex,
1656 QQmlJSRegisterContent::Property,
1657 parentScope(scope, type));
1662 if (type.isType()) {
1663 if (
auto result = memberEnumType(type.scope(), name); result.isValid())
1667 if (QQmlJSScope::ConstPtr attachedBase = typeForName(name)) {
1668 if (QQmlJSScope::ConstPtr attached = attachedBase->attachedType()) {
1669 if (!genericType(attached)) {
1670 m_logger->log(u"Cannot resolve generic base of attached %1"_s.arg(
1671 attached->internalName()),
1672 qmlCompiler, attached->sourceLocation());
1674 }
else if (contained->accessSemantics() != QQmlJSScope::AccessSemantics::Reference) {
1675 m_logger->log(u"Cannot retrieve attached object for non-reference type %1"_s.arg(
1676 contained->internalName()),
1677 qmlCompiler, contained->sourceLocation());
1680 const QQmlJSRegisterContent namedType = m_pool->createType(
1681 attachedBase, QQmlJSRegisterContent::InvalidLookupIndex,
1682 QQmlJSRegisterContent::TypeByName, type);
1684 return m_pool->createType(
1685 attached, resultLookupIndex, QQmlJSRegisterContent::Attachment,
1713QQmlJSRegisterContent QQmlJSTypeResolver::memberType(
1714 QQmlJSRegisterContent type,
const QString &name,
int lookupIndex)
const
1717 return memberType(type, name, type.resultLookupIndex(), lookupIndex);
1718 if (type.isProperty() || type.isMethodCall())
1719 return memberType(type, name, type.resultLookupIndex(), lookupIndex);
1720 if (type.isEnumeration()) {
1721 const auto enumeration = type.enumeration();
1722 if (!type.enumMember().isEmpty() || !enumeration.hasKey(name))
1724 return m_pool->createEnumeration(
1725 enumeration, name, QQmlJSRegisterContent::Enum, type.scope());
1727 if (type.isMethod()) {
1728 QQmlJSMetaProperty prop;
1729 prop.setTypeName(u"QJSValue"_s);
1730 prop.setPropertyName(name);
1731 prop.setType(jsValueType());
1732 prop.setIsWritable(
true);
1733 return m_pool->createProperty(
1734 prop, QQmlJSRegisterContent::InvalidLookupIndex, lookupIndex,
1735 QQmlJSRegisterContent::Property, type);
1737 if (type.isImportNamespace()) {
1738 Q_ASSERT(type.scopeType()->isReferenceType());
1739 return registerContentForName(name, type);
1741 if (type.isConversion()) {
1742 if (
const auto result = memberType(
1743 type, name, type.resultLookupIndex(), lookupIndex);
1748 if (
const auto result = memberEnumType(type.scope(), name); result.isValid())
1755 const auto nonVoid = extractNonVoidFromOptionalType(type);
1758 return (!nonVoid.isNull() && canHold(type.conversionResultType(), nonVoid.containedType()))
1759 ? memberType(nonVoid, name, type.resultLookupIndex(), lookupIndex)
1760 : QQmlJSRegisterContent();
1763 Q_UNREACHABLE_RETURN({});