6#include <private/qqmlcustomparser_p.h>
7#include <private/qqmlglobal_p.h>
8#include <private/qqmlirbuilder_p.h>
9#include <private/qqmlpropertycachecreator_p.h>
10#include <private/qqmlpropertyresolver_p.h>
11#include <private/qqmlstringconverters_p.h>
13#include <QtCore/qdatetime.h>
19 switch (metaType.
id()) {
20#define HANDLE_PRIMITIVE(Type, id, T) \
23#undef HANDLE_PRIMITIVE
33 : enginePrivate(enginePrivate)
34 , compilationUnit(compilationUnit)
36 , qmlUnit(compilationUnit->unitData())
37 , propertyCaches(compilationUnit->propertyCaches)
38 , bindingPropertyDataPerObject(&compilationUnit->bindingPropertyDataPerObject)
40 bindingPropertyDataPerObject->resize(compilationUnit->objectCount());
45 return validateObject(0,
nullptr);
70 for (
auto it =
obj->inlineComponentsBegin();
it !=
obj->inlineComponentsEnd(); ++
it) {
71 const auto errors = validateObject(
it->objectIndex,
nullptr);
72 if (!errors.isEmpty())
81 return validateObject(componentBinding->
value.
objectIndex, componentBinding);
89 if (
auto typeRef = resolvedType(
obj->inheritedTypeNameIndex)) {
90 const auto type = typeRef->type();
92 customParser =
type.customParser();
108 if (populatingValueTypeGroupProperty) {
109 return recordError(binding->
location,
tr(
"Property assignment expected"));
120 if (
obj->indexOfDefaultPropertyOrAlias != -1) {
122 defaultPropertyName =
cache->defaultPropertyName();
123 defaultProperty =
cache->defaultProperty();
125 defaultPropertyName = propertyCache->defaultPropertyName();
126 defaultProperty = propertyCache->defaultProperty();
131 binding =
obj->bindingTable();
135 const QV4::CompiledData::Binding::Flags bindingFlags = binding->
flags();
140 customBindings << binding;
145 customBindings << binding;
150 bool bindingToDefaultProperty =
false;
151 bool isGroupProperty = instantiatingBinding
154 bool notInRevision =
false;
156 if (!
name.isEmpty()) {
159 pd = propertyResolver.signal(
name, ¬InRevision);
161 pd = propertyResolver.property(
name, ¬InRevision,
167 if (
auto *objectType = resolvedType(
obj->inheritedTypeNameIndex)) {
168 const auto type = objectType->type();
169 if (
type.isValid()) {
170 const auto version = objectType->version();
171 return recordError(binding->
location,
172 tr(
"\"%1.%2\" is not available in %3 %4.%5.")
174 .arg(version.majorVersion())
175 .arg(version.minorVersion()));
183 return recordError(binding->
location,
tr(
"Cannot assign a value directly to a grouped property"));
185 pd = defaultProperty;
186 name = defaultPropertyName;
187 bindingToDefaultProperty =
true;
191 collectedBindingPropertyData[
i] = pd;
199 return recordError(binding->
location,
tr(
"Invalid use of namespace"));
200 return recordError(binding->
location,
tr(
"Invalid attached object assignment"));
205 const bool populatingValueTypeGroupProperty
211 populatingValueTypeGroupProperty);
212 if (!subObjectValidatorErrors.
isEmpty())
213 return subObjectValidatorErrors;
228 binding->
location,
tr(
"%1 properties cannot be used here")
240 const bool assigningToGroupProperty = assignedGroupProperty != groupProperties.
constEnd() && !(binding->
propertyNameIndex < (*assignedGroupProperty)->propertyNameIndex);
249 return recordError(binding->
valueLocation,
tr(
"Cannot assign a value directly to a grouped property"));
250 return recordError(binding->
valueLocation,
tr(
"Invalid property assignment: \"%1\" is a read-only property").
arg(
name));
255 if (pd->
propType() == QMetaType::fromType<QQmlScriptString>())
256 error =
tr(
"Cannot assign multiple values to a script property");
258 error =
tr(
"Cannot assign multiple values to a singular property");
262 if (!bindingToDefaultProperty
265 && assigningToGroupProperty) {
267 if (loc < (*assignedGroupProperty)->valueLocation)
268 loc = (*assignedGroupProperty)->valueLocation;
271 return recordError(loc,
tr(
"Property has already been assigned a value"));
272 return recordError(loc,
tr(
"Cannot assign a value directly to a grouped property"));
276 QQmlError bindingError = validateLiteralBinding(propertyCache, pd, binding);
278 return recordError(bindingError);
280 QQmlError bindingError = validateObjectBinding(pd,
name, binding);
282 return recordError(bindingError);
287 return recordError(binding->
location,
tr(
"Invalid property assignment: \"%1\" is a read-only property").
arg(
name));
290 return recordError(binding->
location,
tr(
"Invalid grouped property access"));
297 tr(
"Invalid grouped property access: Property \"%1\" with primitive type \"%2\".")
304 return recordError(binding->
location,
305 tr(
"Invalid grouped property access: Property \"%1\" with type \"%2\", which is not a value type")
314 customBindings << binding;
317 if (bindingToDefaultProperty) {
318 return recordError(binding->
location,
tr(
"Cannot assign to non-existent default property"));
320 return recordError(binding->
location,
tr(
"Cannot assign to non-existent property \"%1\"").
arg(
name));
325 if (
obj->idNameIndex) {
326 if (populatingValueTypeGroupProperty)
327 return recordError(
obj->locationOfIdProperty,
tr(
"Invalid use of id property with a value type"));
329 bool notInRevision =
false;
330 collectedBindingPropertyData << propertyResolver.property(
QStringLiteral(
"id"), ¬InRevision);
333 if (customParser && !customBindings.
isEmpty()) {
335 customParser->validator =
this;
336 customParser->engine = enginePrivate;
337 customParser->imports = imports;
339 customParser->validator =
nullptr;
340 customParser->engine =
nullptr;
347 (*bindingPropertyDataPerObject)[objectIndex] = collectedBindingPropertyData;
353QQmlError QQmlPropertyValidator::validateLiteralBinding(
370 if (
p.isFlagType()) {
371 p.enumerator().keysToValue(
value.toUtf8().constData(), &
ok);
373 p.enumerator().keyToValue(
value.toUtf8().constData(), &
ok);
386 const auto isStringBinding = [&]() ->
bool {
392 switch (
property->propType().id()) {
395 case QMetaType::QString: {
397 return warnOrError(
tr(
"Invalid property assignment: string expected"));
401 case QMetaType::QStringList: {
403 return warnOrError(
tr(
"Invalid property assignment: string or string list expected"));
407 case QMetaType::QByteArray: {
409 return warnOrError(
tr(
"Invalid property assignment: byte array expected"));
412 case QMetaType::QUrl: {
414 return warnOrError(
tr(
"Invalid property assignment: url expected"));
417 case QMetaType::UInt: {
423 return warnOrError(
tr(
"Invalid property assignment: unsigned int expected"));
426 case QMetaType::Int: {
429 if (
double(
int(
d)) ==
d)
432 return warnOrError(
tr(
"Invalid property assignment: int expected"));
435 case QMetaType::Float: {
437 return warnOrError(
tr(
"Invalid property assignment: number expected"));
441 case QMetaType::Double: {
443 return warnOrError(
tr(
"Invalid property assignment: number expected"));
447 case QMetaType::QColor: {
449 if (isStringBinding())
452 return warnOrError(
tr(
"Invalid property assignment: color expected"));
456#if QT_CONFIG(datestring)
457 case QMetaType::QDate: {
459 if (isStringBinding())
462 return warnOrError(
tr(
"Invalid property assignment: date expected"));
466 case QMetaType::QTime: {
468 if (isStringBinding())
471 return warnOrError(
tr(
"Invalid property assignment: time expected"));
475 case QMetaType::QDateTime: {
477 if (isStringBinding())
480 return warnOrError(
tr(
"Invalid property assignment: datetime expected"));
485 case QMetaType::QPoint: {
487 if (isStringBinding())
490 return warnOrError(
tr(
"Invalid property assignment: point expected"));
494 case QMetaType::QPointF: {
496 if (isStringBinding())
499 return warnOrError(
tr(
"Invalid property assignment: point expected"));
503 case QMetaType::QSize: {
505 if (isStringBinding())
508 return warnOrError(
tr(
"Invalid property assignment: size expected"));
512 case QMetaType::QSizeF: {
514 if (isStringBinding())
517 return warnOrError(
tr(
"Invalid property assignment: size expected"));
521 case QMetaType::QRect: {
523 if (isStringBinding())
526 return warnOrError(
tr(
"Invalid property assignment: rect expected"));
530 case QMetaType::QRectF: {
532 if (isStringBinding())
535 return warnOrError(
tr(
"Invalid property assignment: point expected"));
539 case QMetaType::Bool: {
541 return warnOrError(
tr(
"Invalid property assignment: boolean expected"));
545 case QMetaType::QVector2D:
546 case QMetaType::QVector3D:
547 case QMetaType::QVector4D:
548 case QMetaType::QQuaternion: {
550 switch (
property->propType().id()) {
562 return warnOrError(
tr(
"Invalid property assignment: %1 expected")
567 case QMetaType::QRegularExpression:
568 return warnOrError(
tr(
"Invalid property assignment: regular expression expected; use /pattern/ syntax"));
573 return warnOrError(
tr(
"Invalid property assignment: number or array of numbers expected"));
580 if (
double(
int(
n)) !=
n)
584 return warnOrError(
tr(
"Invalid property assignment: int or array of ints expected"));
588 return warnOrError(
tr(
"Invalid property assignment: bool or array of bools expected"));
593 return warnOrError(
tr(
"Invalid property assignment: url or array of urls expected"));
598 return warnOrError(
tr(
"Invalid property assignment: string or array of strings expected"));
601 }
else if (
property->propType() == QMetaType::fromType<QJSValue>()) {
603 }
else if (
property->propType() == QMetaType::fromType<QQmlScriptString>()) {
632 for (
const auto& icDatum : compilationUnit->inlineComponentData) {
633 if (icDatum.qmlType.typeId() == to) {
643 fromMo = fromMo->parent();
669 bool isValueSource =
false;
670 bool isPropertyInterceptor =
false;
679 mo =
mo->superClass();
686 if (!isValueSource && !isPropertyInterceptor) {
693 const QMetaType propType =
property->propType();
694 const auto rhsType = [&]() {
703 }
else if (propType == QMetaType::fromType<QVariant>()
704 || propType == QMetaType::fromType<QJSValue>()) {
711 if (!canCoerce(listType,
source)) {
725 }
else if (propType == QMetaType::fromType<QQmlScriptString>()) {
729 .
arg(rhsType()).
arg(propertyName));
737 if (!propertyMetaObject) {
742 for (
const auto& icDatum: compilationUnit->inlineComponentData) {
743 if (icDatum.qmlType.typeId() ==
property->propType()) {
744 propertyMetaObject = compilationUnit->
propertyCaches.
at(icDatum.objectIndex);
750 if (propertyMetaObject) {
753 bool isAssignable =
false;
755 while (
c && !isAssignable) {
756 isAssignable |=
c == propertyMetaObject;
761 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.")
bool isEmpty() const noexcept
void append(parameter_type t)
The QQmlCustomParser class allows you to add new arbitrary types to QML.
@ AcceptsAttachedProperties
QVector< QQmlError > errors() const
virtual void verifyBindings(const QQmlRefPointer< QV4::ExecutableCompilationUnit > &, const QList< const QV4::CompiledData::Binding * > &)=0
The QQmlError class encapsulates a QML error.
bool isValid() const
Returns true if this error is valid, otherwise false.
The QQmlImports class encapsulates one QML document's import statements.
bool resolveType(const QHashedStringRef &type, QQmlType *type_return, QTypeRevision *version_return, QQmlImportNamespace **ns_return, QList< QQmlError > *errors=nullptr, QQmlType::RegistrationType registrationType=QQmlType::AnyRegistrationType, bool *typeRecursionDetected=nullptr) const
QQmlPropertyCache::ConstPtr at(int index) const
QMetaType propType() const
QVector< QQmlError > validate()
QQmlPropertyValidator(QQmlEnginePrivate *enginePrivate, const QQmlImports *imports, const QQmlRefPointer< QV4::ExecutableCompilationUnit > &compilationUnit)
int propertyValueSourceCast() const
int propertyValueInterceptorCast() const
bool canConstructValueType() const
static QVariant createValueType(const QJSValue &, QMetaType)
\macro QT_RESTRICTED_CAST_FROM_ASCII
static QString fromLatin1(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
const CompiledObject * objectAt(int index) const
QQmlPropertyCacheVector propertyCaches
QString bindingValueAsString(const CompiledData::Binding *binding) const
void insert(qsizetype i, T &&t)
typename Base::const_iterator const_iterator
const_iterator constEnd() const
auto constBegin() const -> const_iterator
QCache< int, Employee > cache
[0]
QSet< QString >::iterator it
Q_QML_PRIVATE_EXPORT QPointF pointFFromString(const QString &, bool *ok=nullptr)
Q_QML_PRIVATE_EXPORT unsigned rgbaFromString(const QString &, bool *ok=nullptr)
Q_QML_PRIVATE_EXPORT QSizeF sizeFFromString(const QString &, bool *ok=nullptr)
Q_QML_PRIVATE_EXPORT QRectF rectFFromString(const QString &, bool *ok=nullptr)
Combined button and popup list for selecting options.
DBusConnection const char DBusError * error
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
GLsizei GLsizei GLchar * source
QT_BEGIN_NAMESPACE QQmlError qQmlCompileError(const QV4::CompiledData::Location &location, const QString &description)
QVarLengthArray< const QV4::CompiledData::Binding *, 8 > GroupPropertyVector
static QT_BEGIN_NAMESPACE bool isPrimitiveType(QMetaType metaType)
#define HANDLE_PRIMITIVE(Type, id, T)
QLatin1StringView QLatin1String
#define QStringLiteral(str)
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
quint32_le propertyNameIndex
bool evaluatesToString() const
bool isAttachedProperty() const
union QV4::CompiledData::Binding::@543 value
bool hasFlag(Flag flag) const
bool isGroupProperty() const
@ InitializerForReadOnlyDeclaration
@ IsSignalHandlerExpression
double bindingValueAsNumber(const CompiledData::Binding *binding) const
quint32_le inheritedTypeNameIndex
static bool isSignalPropertyName(const QString &name)