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())
882QQmlJSScope::ConstPtr QQmlJSTypeResolver::genericType(
883 const QQmlJSScope::ConstPtr &type,
884 ComponentIsGeneric allowComponent)
const
886 if (type->isScript())
887 return m_jsValueType;
889 if (type == m_metaObjectType)
890 return m_metaObjectType;
892 if (type->accessSemantics() == QQmlJSScope::AccessSemantics::Reference) {
893 QString unresolvedBaseTypeName;
894 for (
auto base = type; base;) {
900 if (base->internalName() == u"QObject"_s) {
902 }
else if (allowComponent == ComponentIsGeneric::Yes
903 && base->internalName() == u"QQmlComponent"_s) {
907 if (
auto baseBase = base->baseType()) {
910 unresolvedBaseTypeName = base->baseTypeName();
917 if (type->filePath().isEmpty())
918 return m_jsValueType;
920 m_logger->log(u"Object type %1 is not derived from QObject or QQmlComponent. "
921 "You may need to fully qualify all names in C++ so that moc can see them. "
922 "You may also need to add qt_extract_metatypes(<target containing %2>)."_s
923 .arg(type->internalName(), unresolvedBaseTypeName),
924 qmlCompiler, type->sourceLocation());
927 return m_jsValueType;
930 if (type->isListProperty())
931 return m_listPropertyType;
933 if (type->scopeType() == QQmlSA::ScopeType::EnumScope)
934 return type->baseType();
936 if (isPrimitive(type)) {
938 if (!type->filePath().isEmpty())
948 return m_jsPrimitiveType;
951 for (
const QQmlJSScope::ConstPtr &builtin : {
952 m_realType, m_floatType, m_int8Type, m_uint8Type, m_int16Type, m_uint16Type,
953 m_int32Type, m_uint32Type, m_int64Type, m_uint64Type, m_boolType, m_stringType,
954 m_stringListType, m_byteArrayType, m_urlType, m_dateTimeType, m_dateType,
955 m_timeType, m_variantListType, m_variantMapType, m_varType, m_jsValueType,
956 m_jsPrimitiveType, m_listPropertyType, m_qObjectType, m_qObjectListType,
957 m_metaObjectType, m_forInIteratorPtr, m_forOfIteratorPtr }) {
958 if (type == builtin || type == builtin->listType())
1089QQmlJSScope::ConstPtr QQmlJSTypeResolver::scopedType(
1090 const QQmlJSScope::ConstPtr &scope,
const QString &name,
1091 QQmlJSScopesByIdOptions options)
const
1093 QQmlJSScopesById::CertainCallback<QQmlJSScope::ConstPtr> identified;
1094 if (m_objectsById.possibleScopes(name, scope, options, identified)
1095 != QQmlJSScopesById::Success::Yes) {
1100 if (identified.result) {
1102 return identified.result;
1105 if (QQmlJSScope::ConstPtr base = QQmlJSScope::findCurrentQMLScope(scope)) {
1106 QQmlJSScope::ConstPtr result;
1107 if (QQmlJSUtils::searchBaseAndExtensionTypes(
1108 base, [&](
const QQmlJSScope::ConstPtr &found, QQmlJSScope::ExtensionKind mode) {
1109 if (mode == QQmlJSScope::ExtensionNamespace)
1112 if (found->hasOwnProperty(name)) {
1113 const QQmlJSMetaProperty prop = found->ownProperty(name);
1114 if (!isRevisionAllowed(prop.revision(), scope))
1117 result = resolveParentProperty(name, base, prop.type());
1121 if (found->hasOwnMethod(name)) {
1122 const auto methods = found->ownMethods(name);
1123 for (
const auto &method : methods) {
1124 if (isRevisionAllowed(method.revision(), scope)) {
1125 result = jsValueType();
1137 if (QQmlJSScope::ConstPtr result = containedTypeForName(name))
1140 if (m_jsGlobalObject->hasProperty(name))
1141 return m_jsGlobalObject->property(name).type();
1143 if (m_jsGlobalObject->hasMethod(name))
1144 return jsValueType();
1156QQmlJSRegisterContent QQmlJSTypeResolver::scopedType(QQmlJSRegisterContent scope,
1157 const QString &name,
int lookupIndex,
1158 QQmlJSScopesByIdOptions options)
const
1160 const QQmlJSScope::ConstPtr contained = scope.containedType();
1162 QQmlJSScopesById::CertainCallback<QQmlJSScope::ConstPtr> identified;
1163 if (m_objectsById.possibleScopes(name, contained, options, identified)
1164 != QQmlJSScopesById::Success::Yes) {
1169 if (identified.result) {
1171 return m_pool->createType(
1172 identified.result, lookupIndex, QQmlJSRegisterContent::ObjectById, scope);
1175 if (QQmlJSScope::ConstPtr base = QQmlJSScope::findCurrentQMLScope(contained)) {
1176 QQmlJSRegisterContent result;
1177 if (QQmlJSUtils::searchBaseAndExtensionTypes(
1178 base, [&](
const QQmlJSScope::ConstPtr &found, QQmlJSScope::ExtensionKind mode) {
1179 if (mode == QQmlJSScope::ExtensionNamespace)
1182 const QQmlJSRegisterContent resultScope = mode == QQmlJSScope::NotExtension
1184 : extensionType(found, scope);
1186 if (found->hasOwnProperty(name)) {
1187 QQmlJSMetaProperty prop = found->ownProperty(name);
1188 if (!isRevisionAllowed(prop.revision(), contained))
1191 prop.setType(resolveParentProperty(name, base, prop.type()));
1192 result = m_pool->createProperty(
1193 prop, QQmlJSRegisterContent::InvalidLookupIndex, lookupIndex,
1194 scopeContentVariant(mode,
false), resultScope);
1198 if (found->hasOwnMethod(name)) {
1199 auto methods = found->ownMethods(name);
1200 for (
auto it = methods.begin(); it != methods.end();) {
1201 if (!isRevisionAllowed(it->revision(), contained))
1202 it = methods.erase(it);
1206 if (methods.isEmpty())
1208 result = m_pool->createMethod(
1209 methods, jsValueType(), scopeContentVariant(mode,
true), resultScope);
1220 QQmlJSRegisterContent result = registerContentForName(name, scope);
1222 if (result.isValid())
1225 if (m_jsGlobalObject->hasProperty(name)) {
1226 return m_pool->createProperty(
1227 m_jsGlobalObject->property(name), QQmlJSRegisterContent::InvalidLookupIndex,
1228 lookupIndex, QQmlJSRegisterContent::Property, m_jsGlobalObjectContent);
1229 }
else if (m_jsGlobalObject->hasMethod(name)) {
1230 return m_pool->createMethod(
1231 m_jsGlobalObject->methods(name), jsValueType(),
1232 QQmlJSRegisterContent::Property, m_jsGlobalObjectContent);
1303QQmlJSMetaMethod QQmlJSTypeResolver::selectConstructor(
1304 const QQmlJSScope::ConstPtr &type,
const QQmlJSScope::ConstPtr &passedArgumentType,
1305 bool *isExtension)
const
1310 || canHold(passedArgumentType, type)
1311 || type->accessSemantics() != QQmlJSScope::AccessSemantics::Value
1312 || !type->isCreatable()) {
1313 return QQmlJSMetaMethod();
1316 auto doSelectConstructor = [&](
const QQmlJSScope::ConstPtr &ctorProvider) {
1317 QQmlJSMetaMethod candidate;
1319 const auto ownMethods = ctorProvider->ownMethods();
1320 for (
const QQmlJSMetaMethod &method : ownMethods) {
1321 if (!method.isConstructor())
1324 const auto index = method.constructorIndex();
1325 Q_ASSERT(index != QQmlJSMetaMethod::RelativeFunctionIndex::Invalid);
1327 const auto methodArguments = method.parameters();
1328 if (methodArguments.size() != 1)
1331 const QQmlJSScope::ConstPtr methodArgumentType = methodArguments[0].type();
1334 if (methodArgumentType == type)
1337 if (passedArgumentType == methodArgumentType)
1342 if (!candidate.isValid()
1343 && canPrimitivelyConvertFromTo(passedArgumentType, methodArgumentType)) {
1351 if (QQmlJSScope::ConstPtr extension = type->extensionType().scope) {
1352 const QQmlJSMetaMethod ctor = doSelectConstructor(extension);
1353 if (ctor.isValid()) {
1355 *isExtension =
true;
1361 *isExtension =
false;
1363 return doSelectConstructor(type);
1423bool QQmlJSTypeResolver::canPrimitivelyConvertFromTo(
1424 const QQmlJSScope::ConstPtr &from,
const QQmlJSScope::ConstPtr &to)
const
1428 if (from == m_varType || to == m_varType)
1430 if (from == m_jsValueType || to == m_jsValueType)
1432 if (to == m_qQmlScriptStringType)
1434 if (isNumeric(from) && isNumeric(to))
1437 if (to == m_boolType)
1440 if (from->accessSemantics() == QQmlJSScope::AccessSemantics::Reference
1441 && to == m_stringType) {
1446 if (isNumeric(from) && to == m_stringType)
1450 if (from == m_stringType && isNumeric(to))
1451 return to->scopeType() != QQmlJSScope::ScopeType::EnumScope;
1454 if ((from == m_stringType && to == m_urlType)
1455 || (from == m_urlType && to == m_stringType)) {
1460 if ((from == m_stringType && to == m_byteArrayType)
1461 || (from == m_byteArrayType && to == m_stringType)) {
1465 if (to == m_voidType)
1469 return from == m_voidType;
1471 const auto types = { m_dateTimeType, m_dateType, m_timeType, m_stringType };
1472 for (
const auto &originType : types) {
1473 if (from != originType)
1476 for (
const auto &targetType : types) {
1477 if (to == targetType)
1481 if (to == m_realType)
1487 if (from == m_nullType && to->accessSemantics() == QQmlJSScope::AccessSemantics::Reference)
1490 if (from == m_jsPrimitiveType) {
1492 return isPrimitive(to) || to->accessSemantics() == QQmlJSScope::AccessSemantics::Reference;
1495 if (to == m_jsPrimitiveType)
1496 return isPrimitive(from);
1498 const bool matchByName = !to->isComposite();
1499 Q_ASSERT(!matchByName || !to->internalName().isEmpty());
1500 if (QQmlJSUtils::searchBaseAndExtensionTypes(
1501 from, [&](
const QQmlJSScope::ConstPtr &scope, QQmlJSScope::ExtensionKind kind) {
1503 case QQmlJSScope::NotExtension:
1504 case QQmlJSScope::ExtensionJavaScript:
1510 || (matchByName && scope->internalName() == to->internalName());
1511 case QQmlJSScope::ExtensionType:
1512 case QQmlJSScope::ExtensionNamespace:
1520 if (from == m_variantListType)
1521 return to->accessSemantics() == QQmlJSScope::AccessSemantics::Sequence;
1524 if (canPrimitivelyConvertFromTo(from, m_jsPrimitiveType)
1525 && canPrimitivelyConvertFromTo(m_jsPrimitiveType, to)) {
1529 if (areEquivalentLists(from, to))
1532 if (from->isListProperty()
1533 && to->accessSemantics() == QQmlJSScope::AccessSemantics::Sequence
1534 && canConvertFromTo(from->elementType(), to->elementType())) {
1539 if (to->accessSemantics() == QQmlJSScope::AccessSemantics::Sequence
1540 && from->accessSemantics() == QQmlJSScope::AccessSemantics::Reference
1541 && from->inherits(to->elementType())) {
1545 if (to == m_stringType && from->accessSemantics() == QQmlJSScope::AccessSemantics::Sequence)
1546 return canConvertFromTo(from->elementType(), m_stringType);
1564QQmlJSRegisterContent QQmlJSTypeResolver::memberType(
1565 QQmlJSRegisterContent type,
const QString &name,
int baseLookupIndex,
1566 int resultLookupIndex)
const
1568 QQmlJSRegisterContent result;
1569 const QQmlJSScope::ConstPtr contained = type.containedType();
1572 if (contained == metaObjectType())
1573 return memberEnumType(type.scope(), name);
1575 if (contained == variantMapType() || contained->inherits(qmlPropertyMapType())) {
1576 QQmlJSMetaProperty prop;
1577 prop.setPropertyName(name);
1578 prop.setTypeName(u"QVariant"_s);
1579 prop.setType(varType());
1580 prop.setIsWritable(
true);
1581 return m_pool->createProperty(
1582 prop, baseLookupIndex, resultLookupIndex,
1583 QQmlJSRegisterContent::Property, type);
1586 if (contained == jsValueType()) {
1587 QQmlJSMetaProperty prop;
1588 prop.setPropertyName(name);
1589 prop.setTypeName(u"QJSValue"_s);
1590 prop.setType(jsValueType());
1591 prop.setIsWritable(
true);
1592 return m_pool->createProperty(
1593 prop, baseLookupIndex, resultLookupIndex,
1594 QQmlJSRegisterContent::Property, type);
1597 if ((contained == stringType()
1598 || contained->accessSemantics() == QQmlJSScope::AccessSemantics::Sequence)
1599 && name == u"length"_s) {
1600 return lengthProperty(contained != stringType(), type);
1603 const auto check = [&](
const QQmlJSScope::ConstPtr &scope, QQmlJSScope::ExtensionKind mode) {
1604 const QQmlJSRegisterContent resultScope = mode == QQmlJSScope::NotExtension
1605 ? baseType(scope, type)
1606 : extensionType(scope, type);
1608 if (mode != QQmlJSScope::ExtensionNamespace) {
1609 if (scope->hasOwnProperty(name)) {
1610 const auto prop = scope->ownProperty(name);
1611 result = m_pool->createProperty(
1612 prop, baseLookupIndex, resultLookupIndex,
1613 QQmlJSRegisterContent::Property, resultScope);
1617 if (scope->hasOwnMethod(name)) {
1618 const auto methods = scope->ownMethods(name);
1619 result = m_pool->createMethod(
1620 methods, jsValueType(), QQmlJSRegisterContent::Method, resultScope);
1625 if (type.variant() == QQmlJSRegisterContent::ObjectById)
1627 return checkEnums(resultScope, name, &result);
1630 if (QQmlJSUtils::searchBaseAndExtensionTypes(type.containedType(), check))
1633 for (
auto scope = contained;
1634 scope && (QQmlSA::isFunctionScope(scope->scopeType())
1635 || scope->scopeType() == QQmlSA::ScopeType::JSLexicalScope);
1636 scope = scope->parentScope()) {
1637 if (
auto ownIdentifier = scope->ownJSIdentifier(name)) {
1638 QQmlJSMetaProperty prop;
1639 prop.setPropertyName(name);
1640 prop.setTypeName(u"QJSValue"_s);
1641 prop.setType(jsValueType());
1642 prop.setIsWritable(!(ownIdentifier.value().isConst));
1644 return m_pool->createProperty(
1645 prop, baseLookupIndex, resultLookupIndex,
1646 QQmlJSRegisterContent::Property,
1647 parentScope(scope, type));
1652 if (type.isType()) {
1653 if (
auto result = memberEnumType(type.scope(), name); result.isValid())
1657 if (QQmlJSScope::ConstPtr attachedBase = typeForName(name)) {
1658 if (QQmlJSScope::ConstPtr attached = attachedBase->attachedType()) {
1659 if (!genericType(attached)) {
1660 m_logger->log(u"Cannot resolve generic base of attached %1"_s.arg(
1661 attached->internalName()),
1662 qmlCompiler, attached->sourceLocation());
1664 }
else if (contained->accessSemantics() != QQmlJSScope::AccessSemantics::Reference) {
1665 m_logger->log(u"Cannot retrieve attached object for non-reference type %1"_s.arg(
1666 contained->internalName()),
1667 qmlCompiler, contained->sourceLocation());
1670 const QQmlJSRegisterContent namedType = m_pool->createType(
1671 attachedBase, QQmlJSRegisterContent::InvalidLookupIndex,
1672 QQmlJSRegisterContent::TypeByName, type);
1674 return m_pool->createType(
1675 attached, resultLookupIndex, QQmlJSRegisterContent::Attachment,
1703QQmlJSRegisterContent QQmlJSTypeResolver::memberType(
1704 QQmlJSRegisterContent type,
const QString &name,
int lookupIndex)
const
1707 return memberType(type, name, type.resultLookupIndex(), lookupIndex);
1708 if (type.isProperty() || type.isMethodCall())
1709 return memberType(type, name, type.resultLookupIndex(), lookupIndex);
1710 if (type.isEnumeration()) {
1711 const auto enumeration = type.enumeration();
1712 if (!type.enumMember().isEmpty() || !enumeration.hasKey(name))
1714 return m_pool->createEnumeration(
1715 enumeration, name, QQmlJSRegisterContent::Enum, type.scope());
1717 if (type.isMethod()) {
1718 QQmlJSMetaProperty prop;
1719 prop.setTypeName(u"QJSValue"_s);
1720 prop.setPropertyName(name);
1721 prop.setType(jsValueType());
1722 prop.setIsWritable(
true);
1723 return m_pool->createProperty(
1724 prop, QQmlJSRegisterContent::InvalidLookupIndex, lookupIndex,
1725 QQmlJSRegisterContent::Property, type);
1727 if (type.isImportNamespace()) {
1728 Q_ASSERT(type.scopeType()->isReferenceType());
1729 return registerContentForName(name, type);
1731 if (type.isConversion()) {
1732 if (
const auto result = memberType(
1733 type, name, type.resultLookupIndex(), lookupIndex);
1738 if (
const auto result = memberEnumType(type.scope(), name); result.isValid())
1745 const auto nonVoid = extractNonVoidFromOptionalType(type);
1748 return (!nonVoid.isNull() && canHold(type.conversionResultType(), nonVoid.containedType()))
1749 ? memberType(nonVoid, name, type.resultLookupIndex(), lookupIndex)
1750 : QQmlJSRegisterContent();
1753 Q_UNREACHABLE_RETURN({});