7#include <private/qqmlcustomparser_p.h>
8#include <private/qqmlglobal_p.h>
9#include <private/qqmlirbuilder_p.h>
10#include <private/qqmlpropertycachecreator_p.h>
11#include <private/qqmlpropertyresolver_p.h>
12#include <private/qqmlstringconverters_p.h>
13#include <private/qqmlsignalnames_p.h>
15#include <QtCore/qdatetime.h>
21 switch (metaType.id()) {
22#define HANDLE_PRIMITIVE(Type, id, T)
24QT_FOR_EACH_STATIC_PRIMITIVE_TYPE(HANDLE_PRIMITIVE);
25#undef HANDLE_PRIMITIVE
32QQmlPropertyValidator::QQmlPropertyValidator(
33 QQmlTypeLoader *typeLoader,
const QQmlImports *imports,
34 const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit)
35 : m_typeLoader(typeLoader)
36 , compilationUnit(compilationUnit)
38 , qmlUnit(compilationUnit->unitData())
39 , propertyCaches(compilationUnit->propertyCaches)
40 , bindingPropertyDataPerObject(&compilationUnit->bindingPropertyDataPerObject)
42 bindingPropertyDataPerObject->resize(compilationUnit->objectCount());
45QList<QQmlError> QQmlPropertyValidator::validate()
47 return validateObject(0,
nullptr);
54 bool operator()(quint32 name,
const QV4::CompiledData::Binding *binding)
const
56 return name < binding->propertyNameIndex;
58 bool operator()(
const QV4::CompiledData::Binding *binding, quint32 name)
const
60 return binding->propertyNameIndex < name;
62 bool operator()(
const QV4::CompiledData::Binding *lhs,
const QV4::CompiledData::Binding *rhs)
const
64 return lhs->propertyNameIndex < rhs->propertyNameIndex;
68QList<QQmlError> QQmlPropertyValidator::validateObject(
69 int objectIndex,
const QV4::CompiledData::Binding *instantiatingBinding,
70 bool populatingValueTypeGroupProperty,
71 QQmlPropertyResolver::RevisionCheck checkRevision)
const
75 if (objectIndex >= compilationUnit->objectCount()) {
76 return validateObject(
77 compilationUnit->resolvedIndex(objectIndex), instantiatingBinding,
78 populatingValueTypeGroupProperty, checkRevision);
81 const QV4::CompiledData::Object *obj = compilationUnit->objectAt(objectIndex);
82 for (
auto it = obj->inlineComponentsBegin(); it != obj->inlineComponentsEnd(); ++it) {
83 const auto errors = validateObject(it->objectIndex,
nullptr);
84 if (!errors.isEmpty())
88 if (obj->hasFlag(QV4::CompiledData::Object::IsComponent)
89 && !obj->hasFlag(QV4::CompiledData::Object::IsInlineComponentRoot)) {
90 Q_ASSERT(obj->nBindings == 1);
91 const QV4::CompiledData::Binding *componentBinding = obj->bindingTable();
92 Q_ASSERT(componentBinding->type() == QV4::CompiledData::Binding::Type_Object);
93 return validateObject(componentBinding->value.objectIndex, componentBinding);
96 QQmlPropertyCache::ConstPtr propertyCache = propertyCaches.at(objectIndex);
98 return QList<QQmlError>();
100 QQmlCustomParser *customParser =
nullptr;
101 if (
auto typeRef = resolvedType(obj->inheritedTypeNameIndex)) {
106 populatingValueTypeGroupProperty =
false;
108 const auto type = typeRef->type();
110 customParser = type.customParser();
113 QList<
const QV4::CompiledData::Binding*> customBindings;
118 const QV4::CompiledData::Binding *binding = obj->bindingTable();
119 for (quint32 i = 0; i < obj->nBindings; ++i, ++binding) {
120 if (!binding->isGroupProperty())
123 if (binding->hasFlag(QV4::CompiledData::Binding::IsOnAssignment))
126 if (populatingValueTypeGroupProperty) {
127 return recordError(binding->location, tr(
"Property assignment expected"));
130 GroupPropertyVector::const_iterator pos = std::lower_bound(groupProperties.constBegin(), groupProperties.constEnd(), binding->propertyNameIndex, BindingFinder());
131 groupProperties.insert(pos, binding);
134 QQmlPropertyResolver propertyResolver(propertyCache);
136 QString defaultPropertyName;
137 const QQmlPropertyData *defaultProperty =
nullptr;
138 if (obj->indexOfDefaultPropertyOrAlias != -1) {
139 const QQmlPropertyCache *cache = propertyCache->parent().data();
140 defaultPropertyName = cache->defaultPropertyName();
141 defaultProperty = cache->defaultProperty();
143 defaultPropertyName = propertyCache->defaultPropertyName();
144 defaultProperty = propertyCache->defaultProperty();
147 QV4::CompiledData::BindingPropertyData collectedBindingPropertyData(obj->nBindings);
149 binding = obj->bindingTable();
150 for (quint32 i = 0; i < obj->nBindings; ++i, ++binding) {
151 QString name = stringAt(binding->propertyNameIndex);
152 const QV4::CompiledData::Binding::Type bindingType = binding->type();
153 const QV4::CompiledData::Binding::Flags bindingFlags = binding->flags();
156 if (bindingType == QV4::CompiledData::Binding::Type_AttachedProperty) {
157 if (customParser->flags() & QQmlCustomParser::AcceptsAttachedProperties) {
158 customBindings << binding;
161 }
else if (QQmlSignalNames::isHandlerName(name)
162 && !(customParser->flags() & QQmlCustomParser::AcceptsSignalHandlers)) {
163 customBindings << binding;
168 bool bindingToDefaultProperty =
false;
169 bool isGroupProperty = instantiatingBinding
170 && instantiatingBinding->type() == QV4::CompiledData::Binding::Type_GroupProperty;
172 bool notInRevision =
false;
173 const QQmlPropertyData *pd =
nullptr;
174 if (!name.isEmpty()) {
175 if (bindingFlags & QV4::CompiledData::Binding::IsSignalHandlerExpression
176 || bindingFlags & QV4::CompiledData::Binding::IsSignalHandlerObject) {
177 pd = propertyResolver.signal(name, ¬InRevision, checkRevision);
179 pd = propertyResolver.property(name, ¬InRevision, checkRevision);
183 QString typeName = stringAt(obj->inheritedTypeNameIndex);
184 if (
auto *objectType = resolvedType(obj->inheritedTypeNameIndex)) {
185 const auto type = objectType->type();
186 if (type.isValid()) {
187 const auto version = objectType->version();
188 return recordError(binding->location,
189 tr(
"\"%1.%2\" is not available in %3 %4.%5.")
190 .arg(typeName).arg(name).arg(type.module())
191 .arg(version.majorVersion())
192 .arg(version.minorVersion()));
195 return recordError(binding->location, tr(
"\"%1.%2\" is not available due to component versioning.").arg(typeName).arg(name));
200 return recordError(binding->location, tr(
"Cannot assign a value directly to a grouped property"));
202 pd = defaultProperty;
203 name = defaultPropertyName;
204 bindingToDefaultProperty =
true;
208 collectedBindingPropertyData[i] = pd;
210 if (name.constData()->isUpper() && !binding->isAttachedProperty()) {
212 QQmlImportNamespace *typeNamespace =
nullptr;
213 imports->resolveType(
214 m_typeLoader, stringAt(binding->propertyNameIndex),
215 &type,
nullptr, &typeNamespace);
217 return recordError(binding->location, tr(
"Invalid use of namespace"));
218 return recordError(binding->location, tr(
"Invalid attached object assignment"));
221 if (bindingType >= QV4::CompiledData::Binding::Type_Object
222 && (pd || binding->isAttachedProperty() || binding->isGroupProperty())) {
223 const bool populatingValueTypeGroupProperty
225 && QQmlMetaType::metaObjectForValueType(pd->propType())
226 && !binding->hasFlag(QV4::CompiledData::Binding::IsOnAssignment);
229 const QList<QQmlError> subObjectValidatorErrors = validateObject(
230 binding->value.objectIndex, binding, populatingValueTypeGroupProperty,
231 QQmlPropertyResolver::IgnoreRevision);
233 if (!subObjectValidatorErrors.isEmpty())
234 return subObjectValidatorErrors;
238 if (binding->flags() & (QV4::CompiledData::Binding::IsSignalHandlerExpression
239 | QV4::CompiledData::Binding::IsSignalHandlerObject
240 | QV4::CompiledData::Binding::IsPropertyObserver)) {
244 if ((pd && bindingType == QV4::CompiledData::Binding::Type_AttachedProperty)
245 || (!pd && bindingType == QV4::CompiledData::Binding::Type_GroupProperty)) {
246 if (instantiatingBinding && (instantiatingBinding->isAttachedProperty()
247 || instantiatingBinding->isGroupProperty())) {
249 binding->location, tr(
"%1 properties cannot be used here")
250 .arg(bindingType == QV4::CompiledData::Binding::Type_AttachedProperty
251 ? QStringLiteral(
"Attached")
252 : QStringLiteral(
"Group")));
255 }
else if (bindingType == QV4::CompiledData::Binding::Type_AttachedProperty) {
260 GroupPropertyVector::const_iterator assignedGroupProperty = std::lower_bound(groupProperties.constBegin(), groupProperties.constEnd(), binding->propertyNameIndex, BindingFinder());
261 const bool assigningToGroupProperty = assignedGroupProperty != groupProperties.constEnd() && !(binding->propertyNameIndex < (*assignedGroupProperty)->propertyNameIndex);
263 if (!pd->isWritable()
265 && !binding->isGroupProperty()
266 && !(bindingFlags & QV4::CompiledData::Binding::InitializerForReadOnlyDeclaration)
269 if (assigningToGroupProperty && bindingType < QV4::CompiledData::Binding::Type_Object)
270 return recordError(binding->valueLocation, tr(
"Cannot assign a value directly to a grouped property"));
271 return recordError(binding->valueLocation, tr(
"Invalid property assignment: \"%1\" is a read-only property").arg(name));
274 if (!pd->isQList() && (bindingFlags & QV4::CompiledData::Binding::IsListItem)) {
276 if (pd->propType() == QMetaType::fromType<QQmlScriptString>())
277 error = tr(
"Cannot assign multiple values to a script property");
279 error = tr(
"Cannot assign multiple values to a singular property");
280 return recordError(binding->valueLocation, error);
283 if (!bindingToDefaultProperty
284 && !binding->isGroupProperty()
285 && !(bindingFlags & QV4::CompiledData::Binding::IsOnAssignment)
286 && assigningToGroupProperty) {
287 QV4::CompiledData::Location loc = binding->valueLocation;
288 if (loc < (*assignedGroupProperty)->valueLocation)
289 loc = (*assignedGroupProperty)->valueLocation;
291 if (pd && QQmlMetaType::isValueType(pd->propType()))
292 return recordError(loc, tr(
"Property has already been assigned a value"));
293 return recordError(loc, tr(
"Cannot assign a value directly to a grouped property"));
296 if (bindingType < QV4::CompiledData::Binding::Type_Script) {
297 QQmlError bindingError = validateLiteralBinding(propertyCache, pd, binding);
298 if (bindingError.isValid())
299 return recordError(bindingError);
300 }
else if (bindingType == QV4::CompiledData::Binding::Type_Object) {
301 QQmlError bindingError = validateObjectBinding(pd, name, binding);
302 if (bindingError.isValid())
303 return recordError(bindingError);
304 }
else if (binding->isGroupProperty()) {
305 if (QQmlMetaType::isValueType(pd->propType())) {
306 if (QQmlMetaType::metaObjectForValueType(pd->propType())) {
307 if (!pd->isWritable()) {
308 return recordError(binding->location, tr(
"Invalid property assignment: \"%1\" is a read-only property").arg(name));
311 return recordError(binding->location, tr(
"Invalid grouped property access"));
314 const QMetaType type = pd->propType();
315 if (isPrimitiveType(type)) {
318 tr(
"Invalid grouped property access: Property \"%1\" with primitive type \"%2\".")
319 .arg(name, QString::fromUtf8(type.name()))
323 if (!QQmlMetaType::propertyCacheForType(type)) {
324 auto mo = type.metaObject();
326 return recordError(binding->location,
327 tr(
"Invalid grouped property access: Property \"%1\" with type \"%2\", which is neither a value nor an object type")
328 .arg(name, QString::fromUtf8(type.name()))
331 if (QMetaObjectPrivate::get(mo)->flags & DynamicMetaObject) {
332 return recordError(binding->location,
333 tr(
"Unsupported grouped property access: Property \"%1\" with type \"%2\" has a dynamic meta-object.")
334 .arg(name, QString::fromUtf8(type.name()))
343 customBindings << binding;
346 if (bindingToDefaultProperty) {
347 return recordError(binding->location, tr(
"Cannot assign to non-existent default property"));
349 return recordError(binding->location, tr(
"Cannot assign to non-existent property \"%1\"").arg(name));
354 if (obj->idNameIndex) {
355 if (populatingValueTypeGroupProperty)
356 return recordError(obj->locationOfIdProperty, tr(
"Invalid use of id property with a value type"));
358 bool notInRevision =
false;
359 collectedBindingPropertyData
360 << propertyResolver.property(QStringLiteral(
"id"), ¬InRevision, checkRevision);
363 if (customParser && !customBindings.isEmpty()) {
364 customParser->clearErrors();
365 customParser->validator =
this;
366 customParser->imports = imports;
367 customParser->verifyBindings(compilationUnit, customBindings);
368 customParser->validator =
nullptr;
369 customParser->imports = (QQmlImports*)
nullptr;
370 QList<QQmlError> parserErrors = customParser->errors();
371 if (!parserErrors.isEmpty())
375 (*bindingPropertyDataPerObject)[objectIndex] = collectedBindingPropertyData;
377 QList<QQmlError> noError;
381QQmlError QQmlPropertyValidator::validateLiteralBinding(
382 const QQmlPropertyCache::ConstPtr &propertyCache,
const QQmlPropertyData *property,
383 const QV4::CompiledData::Binding *binding)
const
385 if (property->isQList()) {
386 return qQmlCompileError(binding->valueLocation, tr(
"Cannot assign primitives to lists"));
391 if (property->isEnum()) {
392 if (binding->hasFlag(QV4::CompiledData::Binding::IsResolvedEnum))
397 if (property->isAlias() && binding->isNumberBinding())
400 QString value = compilationUnit->bindingValueAsString(binding);
401 QMetaProperty p = propertyCache->firstCppMetaObject()->property(property->coreIndex());
403 if (p.isFlagType()) {
404 p.enumerator().keysToValue(value.toUtf8().constData(), &ok);
406 p.enumerator().keyToValue(value.toUtf8().constData(), &ok);
409 return qQmlCompileError(binding->valueLocation, tr(
"Invalid property assignment: unknown enumeration"));
414 auto warnOrError = [&](
const QString &error) {
415 return qQmlCompileError(binding->valueLocation, error);
418 const QV4::CompiledData::Binding::Type bindingType = binding->type();
419 const auto isStringBinding = [&]() ->
bool {
421 Q_ASSERT(bindingType != QV4::CompiledData::Binding::Type_Script);
422 return bindingType == QV4::CompiledData::Binding::Type_String;
425 switch (property->propType().id()) {
426 case QMetaType::QVariant:
428 case QMetaType::QString: {
429 if (!binding->evaluatesToString()) {
430 return warnOrError(tr(
"Invalid property assignment: string expected"));
434 case QMetaType::QStringList: {
435 if (!binding->evaluatesToString()) {
436 return warnOrError(tr(
"Invalid property assignment: string or string list expected"));
440 case QMetaType::QByteArray: {
441 if (bindingType != QV4::CompiledData::Binding::Type_String)
442 return warnOrError(tr(
"Invalid property assignment: byte array expected"));
445 case QMetaType::QUrl: {
446 if (bindingType != QV4::CompiledData::Binding::Type_String)
447 return warnOrError(tr(
"Invalid property assignment: url expected"));
450 case QMetaType::UInt: {
451 if (bindingType == QV4::CompiledData::Binding::Type_Number) {
452 double d = compilationUnit->bindingValueAsNumber(binding);
453 if (
double(uint(d)) == d)
456 return warnOrError(tr(
"Invalid property assignment: unsigned int expected"));
459 case QMetaType::Int: {
460 if (bindingType == QV4::CompiledData::Binding::Type_Number) {
461 double d = compilationUnit->bindingValueAsNumber(binding);
462 if (
double(
int(d)) == d)
465 return warnOrError(tr(
"Invalid property assignment: int expected"));
468 case QMetaType::LongLong:
469 case QMetaType::ULongLong:
470 case QMetaType::Long:
471 case QMetaType::ULong:
472 case QMetaType::Float:
473 case QMetaType::Double: {
474 if (bindingType != QV4::CompiledData::Binding::Type_Number) {
475 return warnOrError(tr(
"Invalid property assignment: number expected"));
479 case QMetaType::QColor: {
481 if (isStringBinding())
482 QQmlStringConverters::rgbaFromString(compilationUnit->bindingValueAsString(binding), &ok);
484 return warnOrError(tr(
"Invalid property assignment: color expected"));
488#if QT_CONFIG(datestring)
489 case QMetaType::QDate: {
491 if (isStringBinding())
492 QQmlStringConverters::dateFromString(compilationUnit->bindingValueAsString(binding), &ok);
494 return warnOrError(tr(
"Invalid property assignment: date expected"));
498 case QMetaType::QTime: {
500 if (isStringBinding())
501 QQmlStringConverters::timeFromString(compilationUnit->bindingValueAsString(binding), &ok);
503 return warnOrError(tr(
"Invalid property assignment: time expected"));
507 case QMetaType::QDateTime: {
509 if (isStringBinding())
510 QQmlStringConverters::dateTimeFromString(compilationUnit->bindingValueAsString(binding), &ok);
512 return warnOrError(tr(
"Invalid property assignment: datetime expected"));
517 case QMetaType::QPoint: {
519 if (isStringBinding())
520 QQmlStringConverters::pointFFromString(compilationUnit->bindingValueAsString(binding), &ok);
522 return warnOrError(tr(
"Invalid property assignment: point expected"));
526 case QMetaType::QPointF: {
528 if (isStringBinding())
529 QQmlStringConverters::pointFFromString(compilationUnit->bindingValueAsString(binding), &ok);
531 return warnOrError(tr(
"Invalid property assignment: point expected"));
535 case QMetaType::QSize: {
537 if (isStringBinding())
538 QQmlStringConverters::sizeFFromString(compilationUnit->bindingValueAsString(binding), &ok);
540 return warnOrError(tr(
"Invalid property assignment: size expected"));
544 case QMetaType::QSizeF: {
546 if (isStringBinding())
547 QQmlStringConverters::sizeFFromString(compilationUnit->bindingValueAsString(binding), &ok);
549 return warnOrError(tr(
"Invalid property assignment: size expected"));
553 case QMetaType::QRect: {
555 if (isStringBinding())
556 QQmlStringConverters::rectFFromString(compilationUnit->bindingValueAsString(binding), &ok);
558 return warnOrError(tr(
"Invalid property assignment: rect expected"));
562 case QMetaType::QRectF: {
564 if (isStringBinding())
565 QQmlStringConverters::rectFFromString(compilationUnit->bindingValueAsString(binding), &ok);
567 return warnOrError(tr(
"Invalid property assignment: point expected"));
571 case QMetaType::Bool: {
572 if (bindingType != QV4::CompiledData::Binding::Type_Boolean) {
573 return warnOrError(tr(
"Invalid property assignment: boolean expected"));
577 case QMetaType::QVector2D:
578 case QMetaType::QVector3D:
579 case QMetaType::QVector4D:
580 case QMetaType::QQuaternion: {
581 auto typeName = [&]() {
582 switch (property->propType().id()) {
583 case QMetaType::QVector2D:
return QStringLiteral(
"2D vector");
584 case QMetaType::QVector3D:
return QStringLiteral(
"3D vector");
585 case QMetaType::QVector4D:
return QStringLiteral(
"4D vector");
586 case QMetaType::QQuaternion:
return QStringLiteral(
"quaternion");
587 default:
return QString();
590 const QVariant result = QQmlValueTypeProvider::createValueType(
591 compilationUnit->bindingValueAsString(binding),
592 property->propType());
593 if (!result.isValid()) {
594 return warnOrError(tr(
"Invalid property assignment: %1 expected")
599 case QMetaType::QRegularExpression:
600 return warnOrError(tr(
"Invalid property assignment: regular expression expected; use /pattern/ syntax"));
603 if (property->propType() == QMetaType::fromType<QList<qreal> >()) {
604 if (bindingType != QV4::CompiledData::Binding::Type_Number) {
605 return warnOrError(tr(
"Invalid property assignment: number or array of numbers expected"));
608 }
else if (property->propType() == QMetaType::fromType<QList<
int> >()) {
609 bool ok = (bindingType == QV4::CompiledData::Binding::Type_Number);
611 double n = compilationUnit->bindingValueAsNumber(binding);
612 if (
double(
int(n)) != n)
616 return warnOrError(tr(
"Invalid property assignment: int or array of ints expected"));
618 }
else if (property->propType() == QMetaType::fromType<QList<
bool> >()) {
619 if (bindingType != QV4::CompiledData::Binding::Type_Boolean) {
620 return warnOrError(tr(
"Invalid property assignment: bool or array of bools expected"));
623 }
else if (property->propType() == QMetaType::fromType<QList<QUrl> >()) {
624 if (bindingType != QV4::CompiledData::Binding::Type_String) {
625 return warnOrError(tr(
"Invalid property assignment: url or array of urls expected"));
628 }
else if (property->propType() == QMetaType::fromType<QList<QString> >()) {
629 if (!binding->evaluatesToString()) {
630 return warnOrError(tr(
"Invalid property assignment: string or array of strings expected"));
633 }
else if (property->propType() == QMetaType::fromType<QJSValue>()) {
635 }
else if (property->propType() == QMetaType::fromType<QQmlScriptString>()) {
637 }
else if (property->isQObject()
638 && bindingType == QV4::CompiledData::Binding::Type_Null) {
640 }
else if (QQmlMetaType::qmlType(property->propType()).canConstructValueType()) {
644 return warnOrError(tr(
"Invalid property assignment: unsupported type \"%1\"").arg(QLatin1StringView(property->propType().name())));
652
653
654
655bool QQmlPropertyValidator::canCoerce(QMetaType to, QQmlPropertyCache::ConstPtr fromMo)
const
657 if (QQmlMetaType::canConvert(fromMo, to))
664 for (
const auto &icDatum : std::as_const(compilationUnit->inlineComponentData)) {
665 if (icDatum.qmlType.typeId() != to)
668 const auto toMo = compilationUnit->propertyCaches.at(icDatum.objectIndex);
669 for (QQmlPropertyCache::ConstPtr parent = fromMo; parent; parent = parent->parent()) {
679QList<QQmlError> QQmlPropertyValidator::recordError(
const QV4::CompiledData::Location &location,
const QString &description)
const
681 QList<QQmlError> errors;
682 errors.append(qQmlCompileError(location, description));
686QList<QQmlError> QQmlPropertyValidator::recordError(
const QQmlError &error)
const
688 QList<QQmlError> errors;
689 errors.append(error);
693QQmlError QQmlPropertyValidator::validateObjectBinding(
const QQmlPropertyData *property,
const QString &propertyName,
const QV4::CompiledData::Binding *binding)
const
697 if (binding->hasFlag(QV4::CompiledData::Binding::IsOnAssignment)) {
698 Q_ASSERT(binding->type() == QV4::CompiledData::Binding::Type_Object);
700 bool isValueSource =
false;
701 bool isPropertyInterceptor =
false;
703 const QV4::CompiledData::Object *targetObject = compilationUnit->objectAt(binding->value.objectIndex);
704 if (
auto *typeRef = resolvedType(targetObject->inheritedTypeNameIndex)) {
705 QQmlPropertyCache::ConstPtr cache = typeRef->createPropertyCache();
706 const QMetaObject *mo = cache ? cache->firstCppMetaObject() :
nullptr;
708 while (mo && !qmlType.isValid()) {
709 qmlType = QQmlMetaType::qmlType(mo);
710 mo = mo->superClass();
713 isValueSource = qmlType.propertyValueSourceCast() != -1;
714 isPropertyInterceptor = qmlType.propertyValueInterceptorCast() != -1;
717 if (!isValueSource && !isPropertyInterceptor) {
718 return qQmlCompileError(binding->valueLocation, tr(
"\"%1\" cannot operate on \"%2\"").arg(stringAt(targetObject->inheritedTypeNameIndex)).arg(propertyName));
724 const QMetaType propType = property->propType();
725 const auto rhsType = [&]() {
726 return stringAt(compilationUnit->objectAt(binding->value.objectIndex)
727 ->inheritedTypeNameIndex);
730 if (QQmlMetaType::isInterface(propType)) {
734 }
else if (propType == QMetaType::fromType<QVariant>()
735 || propType == QMetaType::fromType<QJSValue>()) {
738 }
else if (property->isQList()) {
739 const QMetaType listType = QQmlMetaType::listValueType(property->propType());
740 if (!QQmlMetaType::isInterface(listType)) {
741 QQmlPropertyCache::ConstPtr source = propertyCaches.at(binding->value.objectIndex);
743 if (
const int wrapper = compilationUnit->implicitComponentForObject(
744 binding->value.objectIndex); wrapper != -1) {
746 source = propertyCaches.at(wrapper);
749 if (!canCoerce(listType, source)) {
750 const QString expectedTypeName = QString::fromUtf8(listType.name()).remove(QLatin1Char(
'*'));
751 return qQmlCompileError(binding->valueLocation,
752 tr(
"Cannot assign object of type \"%1\" to list property \"%2\"; expected \"%3\"")
753 .arg(source->className(), propertyName, expectedTypeName));
757 }
else if (binding->hasFlag(QV4::CompiledData::Binding::IsSignalHandlerObject)
758 && property->isFunction()) {
760 }
else if (isPrimitiveType(propType)) {
761 auto typeName = QString::fromUtf8(QMetaType(propType).name());
762 return qQmlCompileError(binding->location, tr(
"Cannot assign value of type \"%1\" to property \"%2\", expecting \"%3\"")
766 }
else if (propType == QMetaType::fromType<QQmlScriptString>()) {
767 return qQmlCompileError(binding->valueLocation, tr(
"Invalid property assignment: script expected"));
768 }
else if (!QQmlMetaType::isValueType(property->propType())) {
769 QQmlPropertyCache::ConstPtr propertyMetaObject;
775 for (
const auto &icDatum: std::as_const(compilationUnit->inlineComponentData)) {
776 if (icDatum.qmlType.typeId() == property->propType()) {
777 propertyMetaObject = compilationUnit->propertyCaches.at(icDatum.objectIndex);
782 if (!propertyMetaObject) {
787 propertyMetaObject = QQmlMetaType::rawPropertyCacheForType(propType);
790 if (propertyMetaObject) {
793 bool isAssignable =
false;
794 QQmlPropertyCache::ConstPtr c = propertyCaches.at(binding->value.objectIndex);
796 if (
const int wrapper = compilationUnit->implicitComponentForObject(
797 binding->value.objectIndex); wrapper != -1) {
799 c = propertyCaches.at(wrapper);
802 while (c && !isAssignable) {
803 isAssignable |= c == propertyMetaObject;
808 return qQmlCompileError(binding->valueLocation, tr(
"Cannot assign object of type \"%1\" to property of type \"%2\" as the former is neither the same as the latter nor a sub-class of it.")
809 .arg(rhsType()).arg(QLatin1String(property->propType().name())));
812 return qQmlCompileError(binding->valueLocation, tr(
"Cannot assign to property of unknown type \"%1\".")
813 .arg(QLatin1String(property->propType().name())));
Combined button and popup list for selecting options.
QVarLengthArray< const QV4::CompiledData::Binding *, 8 > GroupPropertyVector
static QT_BEGIN_NAMESPACE bool isPrimitiveType(QMetaType metaType)
bool operator()(quint32 name, const QV4::CompiledData::Binding *binding) const
bool operator()(const QV4::CompiledData::Binding *binding, quint32 name) const
bool operator()(const QV4::CompiledData::Binding *lhs, const QV4::CompiledData::Binding *rhs) const