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);
262QQmlJSTypeResolver::typeForBinaryOperation(QSOperator::Op oper, QQmlJSRegisterContent left,
263 QQmlJSRegisterContent right)
const
265 Q_ASSERT(left.isValid());
266 Q_ASSERT(right.isValid());
269 case QSOperator::Op::Equal:
270 case QSOperator::Op::NotEqual:
271 case QSOperator::Op::StrictEqual:
272 case QSOperator::Op::StrictNotEqual:
273 case QSOperator::Op::Lt:
274 case QSOperator::Op::Gt:
275 case QSOperator::Op::Ge:
276 case QSOperator::Op::In:
277 case QSOperator::Op::Le:
278 return operationType(boolType());
279 case QSOperator::Op::BitAnd:
280 case QSOperator::Op::BitOr:
281 case QSOperator::Op::BitXor:
282 case QSOperator::Op::LShift:
283 case QSOperator::Op::RShift:
284 return operationType(int32Type());
285 case QSOperator::Op::URShift:
286 return operationType(uint32Type());
287 case QSOperator::Op::Add: {
288 const auto leftContents = left.containedType();
289 const auto rightContents = right.containedType();
290 if (leftContents == stringType() || rightContents == stringType())
291 return operationType(stringType());
293 const QQmlJSScope::ConstPtr result = merge(leftContents, rightContents);
294 if (result == boolType())
295 return operationType(int32Type());
296 if (isNumeric(result))
297 return operationType(realType());
299 return operationType(jsPrimitiveType());
301 case QSOperator::Op::Sub:
302 case QSOperator::Op::Mul:
303 case QSOperator::Op::Exp: {
304 const QQmlJSScope::ConstPtr result = merge(left.containedType(), right.containedType());
305 return operationType(result == boolType() ? int32Type() : realType());
307 case QSOperator::Op::Div:
308 case QSOperator::Op::Mod:
309 return operationType(realType());
310 case QSOperator::Op::As:
311 return operationType(right.containedType());
316 return operationType(merge(left.containedType(), right.containedType()));
454QQmlJSRegisterContent QQmlJSTypeResolver::registerContentForName(
455 const QString &name, QQmlJSRegisterContent scopeType)
const
457 QQmlJSScope::ConstPtr type = typeForName(name);
459 return QQmlJSRegisterContent();
461 if (type->isSingleton()) {
462 return m_pool->createType(
463 type, QQmlJSRegisterContent::InvalidLookupIndex,
464 QQmlJSRegisterContent::Singleton, scopeType);
467 if (type->isScript()) {
468 return m_pool->createType(
469 type, QQmlJSRegisterContent::InvalidLookupIndex,
470 QQmlJSRegisterContent::Script, scopeType);
473 const QQmlJSRegisterContent namedType = m_pool->createType(
474 type, QQmlJSRegisterContent::InvalidLookupIndex, QQmlJSRegisterContent::TypeByName,
477 if (
const auto attached = type->attachedType()) {
478 if (!genericType(attached)) {
479 m_logger->log(u"Cannot resolve generic base of attached %1"_s.arg(
480 attached->internalName()),
481 qmlCompiler, attached->sourceLocation());
483 }
else if (type->accessSemantics() != QQmlJSScope::AccessSemantics::Reference) {
484 m_logger->log(u"Cannot retrieve attached object for non-reference type %1"_s.arg(
485 type->internalName()),
486 qmlCompiler, type->sourceLocation());
492 return m_pool->createType(
493 attached, QQmlJSRegisterContent::InvalidLookupIndex,
494 QQmlJSRegisterContent::Attachment, namedType);
498 switch (type->accessSemantics()) {
499 case QQmlJSScope::AccessSemantics::None:
500 case QQmlJSScope::AccessSemantics::Reference:
505 return m_pool->createType(
506 metaObjectType(), QQmlJSRegisterContent::InvalidLookupIndex,
507 QQmlJSRegisterContent::MetaType, namedType);
508 case QQmlJSScope::AccessSemantics::Sequence:
509 case QQmlJSScope::AccessSemantics::Value:
510 if (scopeType.isImportNamespace() || canAddressValueTypes()) {
511 return m_pool->createType(
512 metaObjectType(), QQmlJSRegisterContent::InvalidLookupIndex,
513 QQmlJSRegisterContent::MetaType, namedType);
520 return QQmlJSRegisterContent();
653QQmlJSRegisterContent QQmlJSTypeResolver::merge(
654 QQmlJSRegisterContent a, QQmlJSRegisterContent b)
const
659 const RegisterPair key(a, b);
660 if (
const auto it = m_mergeCache.constFind(key); it != m_mergeCache.constEnd())
661 return m_pool->clone(*it);
665 QSet<QQmlJSRegisterContent> origins;
667 QQmlJSRegisterContent aResultScope;
668 if (a.isConversion()) {
669 const auto &aOrigins = a.conversionOrigins();
670 for (
const auto &aOrigin : aOrigins)
671 origins.insert(aOrigin);
672 aResultScope = a.conversionResultScope();
675 aResultScope = a.scope();
678 QQmlJSRegisterContent bResultScope;
679 if (b.isConversion()) {
680 const auto &bOrigins = b.conversionOrigins();
681 for (
const auto &bOrigin : bOrigins)
682 origins.insert(bOrigin);
683 bResultScope = b.conversionResultScope();
686 bResultScope = b.scope();
689 const auto mergeScopes = [&](QQmlJSRegisterContent a, QQmlJSRegisterContent b) {
692 return (a == b) ? a : merge(a, b);
695 const QQmlJSRegisterContent merged = m_pool->createConversion(
697 merge(a.containedType(), b.containedType()),
698 mergeScopes(aResultScope, bResultScope),
699 mergeVariants(a.variant(), b.variant()),
700 mergeScopes(a.scope(), b.scope()));
702 m_mergeCache.insert(key, m_pool->clone(merged));
706QQmlJSScope::ConstPtr QQmlJSTypeResolver::merge(
const QQmlJSScope::ConstPtr &a,
707 const QQmlJSScope::ConstPtr &b)
const
715 const auto baseOrExtension
716 = [](
const QQmlJSScope::ConstPtr &a,
const QQmlJSScope::ConstPtr &b) {
717 QQmlJSScope::ConstPtr found;
718 QQmlJSUtils::searchBaseAndExtensionTypes(
719 a, [&](
const QQmlJSScope::ConstPtr &scope, QQmlJSScope::ExtensionKind kind) {
721 case QQmlJSScope::NotExtension:
723 if (b->inherits(scope)) {
728 case QQmlJSScope::ExtensionJavaScript:
737 case QQmlJSScope::ExtensionType:
738 case QQmlJSScope::ExtensionNamespace:
749 if (a == jsValueType() || a == varType())
751 if (b == jsValueType() || b == varType())
754 const auto isInt32Compatible = [&](
const QQmlJSScope::ConstPtr &type) {
755 return (isIntegral(type)
756 && type != uint32Type()
757 && type != int64Type()
758 && type != uint64Type())
759 || type == boolType();
762 if (isInt32Compatible(a) && isInt32Compatible(b))
765 const auto isUInt32Compatible = [&](
const QQmlJSScope::ConstPtr &type) {
766 return (isUnsignedInteger(type) && type != uint64Type()) || type == boolType();
769 if (isUInt32Compatible(a) && isUInt32Compatible(b))
772 if (isNumeric(a) && isNumeric(b))
775 if (isPrimitive(a) && isPrimitive(b))
776 return jsPrimitiveType();
778 if (
const auto base = baseOrExtension(a, b))
781 if (
const auto base = baseOrExtension(b, a))
784 if ((a == nullType() || a == boolType()) && b->isReferenceType())
787 if ((b == nullType() || b == boolType()) && a->isReferenceType())
891QQmlJSScope::ConstPtr QQmlJSTypeResolver::genericType(
892 const QQmlJSScope::ConstPtr &type,
893 ComponentIsGeneric allowComponent)
const
895 if (type->isScript())
896 return m_jsValueType;
898 if (type == m_metaObjectType)
899 return m_metaObjectType;
901 if (type->accessSemantics() == QQmlJSScope::AccessSemantics::Reference) {
902 QString unresolvedBaseTypeName;
903 for (
auto base = type; base;) {
909 if (base->internalName() == u"QObject"_s) {
911 }
else if (allowComponent == ComponentIsGeneric::Yes
912 && base->internalName() == u"QQmlComponent"_s) {
916 if (
auto baseBase = base->baseType()) {
919 unresolvedBaseTypeName = base->baseTypeName();
926 if (type->filePath().isEmpty())
927 return m_jsValueType;
929 m_logger->log(u"Object type %1 is not derived from QObject or QQmlComponent. "
930 "You may need to fully qualify all names in C++ so that moc can see them. "
931 "You may also need to add qt_extract_metatypes(<target containing %2>)."_s
932 .arg(type->internalName(), unresolvedBaseTypeName),
933 qmlCompiler, type->sourceLocation());
936 return m_jsValueType;
939 if (type->isListProperty())
940 return m_listPropertyType;
942 if (type->scopeType() == QQmlSA::ScopeType::EnumScope)
943 return type->baseType();
945 if (isPrimitive(type)) {
947 if (!type->filePath().isEmpty())
957 return m_jsPrimitiveType;
960 for (
const QQmlJSScope::ConstPtr &builtin : {
961 m_realType, m_floatType, m_int8Type, m_uint8Type, m_int16Type, m_uint16Type,
962 m_int32Type, m_uint32Type, m_int64Type, m_uint64Type, m_boolType, m_stringType,
963 m_stringListType, m_byteArrayType, m_urlType, m_dateTimeType, m_dateType,
964 m_timeType, m_variantListType, m_variantMapType, m_varType, m_jsValueType,
965 m_jsPrimitiveType, m_listPropertyType, m_qObjectType, m_qObjectListType,
966 m_metaObjectType, m_forInIteratorPtr, m_forOfIteratorPtr }) {
967 if (type == builtin || type == builtin->listType())
1098QQmlJSScope::ConstPtr QQmlJSTypeResolver::scopedType(
1099 const QQmlJSScope::ConstPtr &scope,
const QString &name,
1100 QQmlJSScopesByIdOptions options)
const
1102 QQmlJSScopesById::CertainCallback<QQmlJSScope::ConstPtr> identified;
1103 if (m_objectsById.possibleScopes(name, scope, options, identified)
1104 != QQmlJSScopesById::Success::Yes) {
1109 if (identified.result) {
1111 return identified.result;
1114 if (QQmlJSScope::ConstPtr base = QQmlJSScope::findCurrentQMLScope(scope)) {
1115 QQmlJSScope::ConstPtr result;
1116 if (QQmlJSUtils::searchBaseAndExtensionTypes(
1117 base, [&](
const QQmlJSScope::ConstPtr &found, QQmlJSScope::ExtensionKind mode) {
1118 if (mode == QQmlJSScope::ExtensionNamespace)
1121 if (found->hasOwnProperty(name)) {
1122 const QQmlJSMetaProperty prop = found->ownProperty(name);
1123 if (!isRevisionAllowed(prop.revision(), scope))
1126 result = resolveParentProperty(name, base, prop.type());
1130 if (found->hasOwnMethod(name)) {
1131 const auto methods = found->ownMethods(name);
1132 for (
const auto &method : methods) {
1133 if (isRevisionAllowed(method.revision(), scope)) {
1134 result = jsValueType();
1146 if (QQmlJSScope::ConstPtr result = containedTypeForName(name))
1149 if (m_jsGlobalObject->hasProperty(name))
1150 return m_jsGlobalObject->property(name).type();
1152 if (m_jsGlobalObject->hasMethod(name))
1153 return jsValueType();
1165QQmlJSRegisterContent QQmlJSTypeResolver::scopedType(QQmlJSRegisterContent scope,
1166 const QString &name,
int lookupIndex,
1167 QQmlJSScopesByIdOptions options)
const
1169 const QQmlJSScope::ConstPtr contained = scope.containedType();
1171 QQmlJSScopesById::CertainCallback<QQmlJSScope::ConstPtr> identified;
1172 if (m_objectsById.possibleScopes(name, contained, options, identified)
1173 != QQmlJSScopesById::Success::Yes) {
1178 if (identified.result) {
1180 return m_pool->createType(
1181 identified.result, lookupIndex, QQmlJSRegisterContent::ObjectById, scope);
1184 if (QQmlJSScope::ConstPtr base = QQmlJSScope::findCurrentQMLScope(contained)) {
1185 QQmlJSRegisterContent result;
1186 if (QQmlJSUtils::searchBaseAndExtensionTypes(
1187 base, [&](
const QQmlJSScope::ConstPtr &found, QQmlJSScope::ExtensionKind mode) {
1188 if (mode == QQmlJSScope::ExtensionNamespace)
1191 const QQmlJSRegisterContent resultScope = mode == QQmlJSScope::NotExtension
1193 : extensionType(found, scope);
1195 if (found->hasOwnProperty(name)) {
1196 QQmlJSMetaProperty prop = found->ownProperty(name);
1197 if (!isRevisionAllowed(prop.revision(), contained))
1200 prop.setType(resolveParentProperty(name, base, prop.type()));
1201 result = m_pool->createProperty(
1202 prop, QQmlJSRegisterContent::InvalidLookupIndex, lookupIndex,
1203 scopeContentVariant(mode,
false), resultScope);
1207 if (found->hasOwnMethod(name)) {
1208 auto methods = found->ownMethods(name);
1209 for (
auto it = methods.begin(); it != methods.end();) {
1210 if (!isRevisionAllowed(it->revision(), contained))
1211 it = methods.erase(it);
1215 if (methods.isEmpty())
1217 result = m_pool->createMethod(
1218 methods, jsValueType(), scopeContentVariant(mode,
true), resultScope);
1229 QQmlJSRegisterContent result = registerContentForName(name, scope);
1231 if (result.isValid())
1234 if (m_jsGlobalObject->hasProperty(name)) {
1235 return m_pool->createProperty(
1236 m_jsGlobalObject->property(name), QQmlJSRegisterContent::InvalidLookupIndex,
1237 lookupIndex, QQmlJSRegisterContent::Property, m_jsGlobalObjectContent);
1238 }
else if (m_jsGlobalObject->hasMethod(name)) {
1239 return m_pool->createMethod(
1240 m_jsGlobalObject->methods(name), jsValueType(),
1241 QQmlJSRegisterContent::Property, m_jsGlobalObjectContent);
1312QQmlJSMetaMethod QQmlJSTypeResolver::selectConstructor(
1313 const QQmlJSScope::ConstPtr &type,
const QQmlJSScope::ConstPtr &passedArgumentType,
1314 bool *isExtension)
const
1319 || canHold(passedArgumentType, type)
1320 || type->accessSemantics() != QQmlJSScope::AccessSemantics::Value
1321 || !type->isCreatable()) {
1322 return QQmlJSMetaMethod();
1325 auto doSelectConstructor = [&](
const QQmlJSScope::ConstPtr &ctorProvider) {
1326 QQmlJSMetaMethod candidate;
1328 const auto ownMethods = ctorProvider->ownMethods();
1329 for (
const QQmlJSMetaMethod &method : ownMethods) {
1330 if (!method.isConstructor())
1333 const auto index = method.constructorIndex();
1334 Q_ASSERT(index != QQmlJSMetaMethod::RelativeFunctionIndex::Invalid);
1336 const auto methodArguments = method.parameters();
1337 if (methodArguments.size() != 1)
1340 const QQmlJSScope::ConstPtr methodArgumentType = methodArguments[0].type();
1343 if (methodArgumentType == type)
1346 if (passedArgumentType == methodArgumentType)
1351 if (!candidate.isValid()
1352 && canPrimitivelyConvertFromTo(passedArgumentType, methodArgumentType)) {
1360 if (QQmlJSScope::ConstPtr extension = type->extensionType().scope) {
1361 const QQmlJSMetaMethod ctor = doSelectConstructor(extension);
1362 if (ctor.isValid()) {
1364 *isExtension =
true;
1370 *isExtension =
false;
1372 return doSelectConstructor(type);
1432bool QQmlJSTypeResolver::canPrimitivelyConvertFromTo(
1433 const QQmlJSScope::ConstPtr &from,
const QQmlJSScope::ConstPtr &to)
const
1437 if (from == m_varType || to == m_varType)
1439 if (from == m_jsValueType || to == m_jsValueType)
1441 if (to == m_qQmlScriptStringType)
1443 if (isNumeric(from) && isNumeric(to))
1446 if (to == m_boolType)
1449 if (from->accessSemantics() == QQmlJSScope::AccessSemantics::Reference
1450 && to == m_stringType) {
1455 if (isNumeric(from) && to == m_stringType)
1459 if (from == m_stringType && isNumeric(to))
1460 return to->scopeType() != QQmlJSScope::ScopeType::EnumScope;
1463 if ((from == m_stringType && to == m_urlType)
1464 || (from == m_urlType && to == m_stringType)) {
1469 if ((from == m_stringType && to == m_byteArrayType)
1470 || (from == m_byteArrayType && to == m_stringType)) {
1474 if (to == m_voidType)
1478 return from == m_voidType;
1480 const auto types = { m_dateTimeType, m_dateType, m_timeType, m_stringType };
1481 for (
const auto &originType : types) {
1482 if (from != originType)
1485 for (
const auto &targetType : types) {
1486 if (to == targetType)
1490 if (to == m_realType)
1496 if (from == m_nullType && to->accessSemantics() == QQmlJSScope::AccessSemantics::Reference)
1499 if (from == m_jsPrimitiveType) {
1501 return isPrimitive(to) || to->accessSemantics() == QQmlJSScope::AccessSemantics::Reference;
1504 if (to == m_jsPrimitiveType)
1505 return isPrimitive(from);
1507 const bool matchByName = !to->isComposite();
1508 Q_ASSERT(!matchByName || !to->internalName().isEmpty());
1509 if (QQmlJSUtils::searchBaseAndExtensionTypes(
1510 from, [&](
const QQmlJSScope::ConstPtr &scope, QQmlJSScope::ExtensionKind kind) {
1512 case QQmlJSScope::NotExtension:
1513 case QQmlJSScope::ExtensionJavaScript:
1519 || (matchByName && scope->internalName() == to->internalName());
1520 case QQmlJSScope::ExtensionType:
1521 case QQmlJSScope::ExtensionNamespace:
1529 if (from == m_variantListType)
1530 return to->accessSemantics() == QQmlJSScope::AccessSemantics::Sequence;
1533 if (canPrimitivelyConvertFromTo(from, m_jsPrimitiveType)
1534 && canPrimitivelyConvertFromTo(m_jsPrimitiveType, to)) {
1538 if (areEquivalentLists(from, to))
1541 if (from->isListProperty()
1542 && to->accessSemantics() == QQmlJSScope::AccessSemantics::Sequence
1543 && canConvertFromTo(from->elementType(), to->elementType())) {
1548 if (to->accessSemantics() == QQmlJSScope::AccessSemantics::Sequence
1549 && from->accessSemantics() == QQmlJSScope::AccessSemantics::Reference
1550 && from->inherits(to->elementType())) {
1554 if (to == m_stringType && from->accessSemantics() == QQmlJSScope::AccessSemantics::Sequence)
1555 return canConvertFromTo(from->elementType(), m_stringType);
1573QQmlJSRegisterContent QQmlJSTypeResolver::memberType(
1574 QQmlJSRegisterContent type,
const QString &name,
int baseLookupIndex,
1575 int resultLookupIndex)
const
1577 QQmlJSRegisterContent result;
1578 const QQmlJSScope::ConstPtr contained = type.containedType();
1581 if (contained == metaObjectType())
1582 return memberEnumType(type.scope(), name);
1584 if (contained == variantMapType() || contained->inherits(qmlPropertyMapType())) {
1585 QQmlJSMetaProperty prop;
1586 prop.setPropertyName(name);
1587 prop.setTypeName(u"QVariant"_s);
1588 prop.setType(varType());
1589 prop.setIsWritable(
true);
1590 return m_pool->createProperty(
1591 prop, baseLookupIndex, resultLookupIndex,
1592 QQmlJSRegisterContent::Property, type);
1595 if (contained == jsValueType()) {
1596 QQmlJSMetaProperty prop;
1597 prop.setPropertyName(name);
1598 prop.setTypeName(u"QJSValue"_s);
1599 prop.setType(jsValueType());
1600 prop.setIsWritable(
true);
1601 return m_pool->createProperty(
1602 prop, baseLookupIndex, resultLookupIndex,
1603 QQmlJSRegisterContent::Property, type);
1606 if ((contained == stringType()
1607 || contained->accessSemantics() == QQmlJSScope::AccessSemantics::Sequence)
1608 && name == u"length"_s) {
1609 return lengthProperty(contained != stringType(), type);
1612 const auto check = [&](
const QQmlJSScope::ConstPtr &scope, QQmlJSScope::ExtensionKind mode) {
1613 const QQmlJSRegisterContent resultScope = mode == QQmlJSScope::NotExtension
1614 ? baseType(scope, type)
1615 : extensionType(scope, type);
1617 if (mode != QQmlJSScope::ExtensionNamespace) {
1618 if (scope->hasOwnProperty(name)) {
1619 const auto prop = scope->ownProperty(name);
1620 result = m_pool->createProperty(
1621 prop, baseLookupIndex, resultLookupIndex,
1622 QQmlJSRegisterContent::Property, resultScope);
1626 if (scope->hasOwnMethod(name)) {
1627 const auto methods = scope->ownMethods(name);
1628 result = m_pool->createMethod(
1629 methods, jsValueType(), QQmlJSRegisterContent::Method, resultScope);
1634 if (type.variant() == QQmlJSRegisterContent::ObjectById)
1636 return checkEnums(resultScope, name, &result);
1639 if (QQmlJSUtils::searchBaseAndExtensionTypes(type.containedType(), check))
1642 for (
auto scope = contained;
1643 scope && (QQmlSA::isFunctionScope(scope->scopeType())
1644 || scope->scopeType() == QQmlSA::ScopeType::JSLexicalScope);
1645 scope = scope->parentScope()) {
1646 if (
auto ownIdentifier = scope->ownJSIdentifier(name)) {
1647 QQmlJSMetaProperty prop;
1648 prop.setPropertyName(name);
1649 prop.setTypeName(u"QJSValue"_s);
1650 prop.setType(jsValueType());
1651 prop.setIsWritable(!(ownIdentifier.value().isConst));
1653 return m_pool->createProperty(
1654 prop, baseLookupIndex, resultLookupIndex,
1655 QQmlJSRegisterContent::Property,
1656 parentScope(scope, type));
1661 if (type.isType()) {
1662 if (
auto result = memberEnumType(type.scope(), name); result.isValid())
1666 if (QQmlJSScope::ConstPtr attachedBase = typeForName(name)) {
1667 if (QQmlJSScope::ConstPtr attached = attachedBase->attachedType()) {
1668 if (!genericType(attached)) {
1669 m_logger->log(u"Cannot resolve generic base of attached %1"_s.arg(
1670 attached->internalName()),
1671 qmlCompiler, attached->sourceLocation());
1673 }
else if (contained->accessSemantics() != QQmlJSScope::AccessSemantics::Reference) {
1674 m_logger->log(u"Cannot retrieve attached object for non-reference type %1"_s.arg(
1675 contained->internalName()),
1676 qmlCompiler, contained->sourceLocation());
1679 const QQmlJSRegisterContent namedType = m_pool->createType(
1680 attachedBase, QQmlJSRegisterContent::InvalidLookupIndex,
1681 QQmlJSRegisterContent::TypeByName, type);
1683 return m_pool->createType(
1684 attached, resultLookupIndex, QQmlJSRegisterContent::Attachment,
1712QQmlJSRegisterContent QQmlJSTypeResolver::memberType(
1713 QQmlJSRegisterContent type,
const QString &name,
int lookupIndex)
const
1716 return memberType(type, name, type.resultLookupIndex(), lookupIndex);
1717 if (type.isProperty() || type.isMethodCall())
1718 return memberType(type, name, type.resultLookupIndex(), lookupIndex);
1719 if (type.isEnumeration()) {
1720 const auto enumeration = type.enumeration();
1721 if (!type.enumMember().isEmpty() || !enumeration.hasKey(name))
1723 return m_pool->createEnumeration(
1724 enumeration, name, QQmlJSRegisterContent::Enum, type.scope());
1726 if (type.isMethod()) {
1727 QQmlJSMetaProperty prop;
1728 prop.setTypeName(u"QJSValue"_s);
1729 prop.setPropertyName(name);
1730 prop.setType(jsValueType());
1731 prop.setIsWritable(
true);
1732 return m_pool->createProperty(
1733 prop, QQmlJSRegisterContent::InvalidLookupIndex, lookupIndex,
1734 QQmlJSRegisterContent::Property, type);
1736 if (type.isImportNamespace()) {
1737 Q_ASSERT(type.scopeType()->isReferenceType());
1738 return registerContentForName(name, type);
1740 if (type.isConversion()) {
1741 if (
const auto result = memberType(
1742 type, name, type.resultLookupIndex(), lookupIndex);
1747 if (
const auto result = memberEnumType(type.scope(), name); result.isValid())
1754 const auto nonVoid = extractNonVoidFromOptionalType(type);
1757 return (!nonVoid.isNull() && canHold(type.conversionResultType(), nonVoid.containedType()))
1758 ? memberType(nonVoid, name, type.resultLookupIndex(), lookupIndex)
1759 : QQmlJSRegisterContent();
1762 Q_UNREACHABLE_RETURN({});