Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qqmltypecompiler.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
5
6#include <private/qqmlobjectcreator_p.h>
7#include <private/qqmlcustomparser_p.h>
8#include <private/qqmlvmemetaobject_p.h>
9#include <private/qqmlcomponent_p.h>
10#include <private/qqmlpropertyresolver_p.h>
11#include <private/qqmlcomponentandaliasresolver_p.h>
12
13#define COMPILE_EXCEPTION(token, desc) \
14 { \
15 recordError((token)->location, desc); \
16 return false; \
17 }
18
20
22 disableInternalDeferredProperties, QML_DISABLE_INTERNAL_DEFERRED_PROPERTIES);
23
24Q_LOGGING_CATEGORY(lcQmlTypeCompiler, "qt.qml.typecompiler");
25
27 QmlIR::Document *parsedQML, const QQmlRefPointer<QQmlTypeNameCache> &typeNameCache,
28 QV4::ResolvedTypeReferenceMap *resolvedTypeCache, const QV4::CompiledData::DependentTypesHasher &dependencyHasher)
29 : resolvedTypes(resolvedTypeCache)
30 , engine(engine)
31 , dependencyHasher(dependencyHasher)
32 , document(parsedQML)
33 , typeNameCache(typeNameCache)
34 , typeData(typeData)
35{
36}
37
39{
40 // Build property caches and VME meta object data
41
43 it != end; ++it) {
44 QQmlCustomParser *customParser = (*it)->type().customParser();
45 if (customParser)
46 customParsers.insert(it.key(), customParser);
47 }
48
49 QQmlPendingGroupPropertyBindings pendingGroupPropertyBindings;
50
51
52 {
53 QQmlPropertyCacheCreator<QQmlTypeCompiler> propertyCacheBuilder(&m_propertyCaches, &pendingGroupPropertyBindings,
54 engine, this, imports(), typeData->typeClassName());
55 QQmlError cycleError = propertyCacheBuilder.verifyNoICCycle();
56 if (cycleError.isValid()) {
57 recordError(cycleError);
58 return nullptr;
59 }
61 do {
62 result = propertyCacheBuilder.buildMetaObjectsIncrementally();
63 const QQmlError &error = result.error;
64 if (error.isValid()) {
66 return nullptr;
67 } else {
68 // Resolve component boundaries and aliases
69
70 QQmlComponentAndAliasResolver resolver(this, enginePrivate(), &m_propertyCaches);
71 if (QQmlError error = resolver.resolve(result.processedRoot); error.isValid()) {
73 return nullptr;
74 }
75 pendingGroupPropertyBindings.resolveMissingPropertyCaches(&m_propertyCaches);
76 pendingGroupPropertyBindings.clear(); // anything that can be processed is now processed
77 }
78 } while (result.canResume);
79 }
80
81 {
82 QQmlDefaultPropertyMerger merger(this);
84 }
85
86 {
87 SignalHandlerResolver converter(this);
88 if (!converter.resolveSignalHandlerExpressions())
89 return nullptr;
90 }
91
92 {
93 QQmlEnumTypeResolver enumResolver(this);
94 if (!enumResolver.resolveEnumBindings())
95 return nullptr;
96 }
97
98 {
101 }
102
103 {
104 QQmlAliasAnnotator annotator(this);
105 annotator.annotateBindingsToAliases();
106 }
107
108 {
109 QQmlDeferredAndCustomParserBindingScanner deferredAndCustomParserBindingScanner(this);
110 if (!deferredAndCustomParserBindingScanner.scanObject())
111 return nullptr;
112 }
113
114 if (!document->javaScriptCompilationUnit.unitData()) {
115 // Compile JS binding expressions and signal handlers if necessary
116 {
117 // We can compile script strings ahead of time, but they must be compiled
118 // without type optimizations as their scope is always entirely dynamic.
119 QQmlScriptStringScanner sss(this);
120 sss.scan();
121 }
122
123 document->jsModule.fileName = typeData->urlString();
124 document->jsModule.finalUrl = typeData->finalUrlString();
125 QmlIR::JSCodeGen v4CodeGenerator(document, engine->v4engine()->illegalNames());
126 for (QmlIR::Object *object : std::as_const(document->objects)) {
127 if (!v4CodeGenerator.generateRuntimeFunctions(object)) {
128 Q_ASSERT(v4CodeGenerator.hasError());
129 recordError(v4CodeGenerator.error());
130 return nullptr;
131 }
132 }
133 document->javaScriptCompilationUnit = v4CodeGenerator.generateCompilationUnit(/*generated unit data*/false);
134 }
135
136 // Generate QML compiled type data structures
137
138 QmlIR::QmlUnitGenerator qmlGenerator;
139 qmlGenerator.generate(*document, dependencyHasher);
140
141 if (!errors.isEmpty())
142 return nullptr;
143
146 document->javaScriptCompilationUnit));
147 compilationUnit->typeNameCache = typeNameCache;
148 compilationUnit->resolvedTypes = *resolvedTypes;
149 compilationUnit->propertyCaches = std::move(m_propertyCaches);
150 Q_ASSERT(compilationUnit->propertyCaches.count() == static_cast<int>(compilationUnit->objectCount()));
151 return compilationUnit;
152}
153
155{
159 error.setDescription(description);
160 error.setUrl(url());
161 errors << error;
162}
163
165{
167 error.setDescription(message.message);
169 error.setColumn(qmlConvertSourceCoordinate<quint32, int>(message.loc.startColumn));
170 error.setUrl(url());
171 errors << error;
172}
173
175{
176 QQmlError error = e;
177 error.setUrl(url());
178 errors << error;
179}
180
182{
183 return document->stringAt(idx);
184}
185
187{
188 return document->jsGenerator.registerString(str);
189}
190
192{
193 return document->jsGenerator.registerConstant(v);
194}
195
197{
198 return document->javaScriptCompilationUnit.unitData();
199}
200
202{
203 return typeData->imports();
204}
205
207{
208 return &document->objects;
209}
210
212{
213 return &m_propertyCaches;
214}
215
217{
218 return &m_propertyCaches;
219}
220
222{
223 return document->jsParserEngine.pool();
224}
225
227{
228 return document->jsParserEngine.newStringRef(string);
229}
230
232{
233 return &document->jsGenerator.stringTable;
234}
235
236QString QQmlTypeCompiler::bindingAsString(const QmlIR::Object *object, int scriptIndex) const
237{
238 return object->bindingAsString(document, scriptIndex);
239}
240
241void QQmlTypeCompiler::addImport(const QString &module, const QString &qualifier, QTypeRevision version)
242{
243 const quint32 moduleIdx = registerString(module);
244 const quint32 qualifierIdx = registerString(qualifier);
245
246 for (int i = 0, count = document->imports.size(); i < count; ++i) {
247 const QV4::CompiledData::Import *existingImport = document->imports.at(i);
249 && existingImport->uriIndex == moduleIdx
250 && existingImport->qualifierIndex == qualifierIdx)
251 return;
252 }
253 auto pool = memoryPool();
256 import->version = version;
257 import->uriIndex = moduleIdx;
258 import->qualifierIndex = qualifierIdx;
259 document->imports.append(import);
260}
261
263{
264 return typeData->qmlType(inlineComponentName);
265}
266
268 : compiler(typeCompiler)
269{
270}
271
273 : QQmlCompilePass(typeCompiler)
274 , enginePrivate(typeCompiler->enginePrivate())
275 , qmlObjects(*typeCompiler->qmlObjects())
276 , imports(typeCompiler->imports())
277 , customParsers(typeCompiler->customParserCache())
278 , illegalNames(typeCompiler->enginePrivate()->v4engine()->illegalNames())
279 , propertyCaches(typeCompiler->propertyCaches())
280{
281}
282
284{
285 for (int objectIndex = 0; objectIndex < qmlObjects.size(); ++objectIndex) {
286 const QmlIR::Object * const obj = qmlObjects.at(objectIndex);
287 QQmlPropertyCache::ConstPtr cache = propertyCaches->at(objectIndex);
288 if (!cache)
289 continue;
290 if (QQmlCustomParser *customParser = customParsers.value(obj->inheritedTypeNameIndex)) {
291 if (!(customParser->flags() & QQmlCustomParser::AcceptsSignalHandlers))
292 continue;
293 }
294 const QString elementName = stringAt(obj->inheritedTypeNameIndex);
295 if (!resolveSignalHandlerExpressions(obj, elementName, cache))
296 return false;
297 }
298 return true;
299}
300
302 const QmlIR::Object *obj, const QString &typeName,
303 const QQmlPropertyCache::ConstPtr &propertyCache)
304{
305 // map from signal name defined in qml itself to list of parameters
306 QHash<QString, QStringList> customSignals;
307
308 for (QmlIR::Binding *binding = obj->firstBinding(); binding; binding = binding->next) {
309 const QString bindingPropertyName = stringAt(binding->propertyNameIndex);
310 // Attached property?
311 const QV4::CompiledData::Binding::Type bindingType = binding->type();
313 const QmlIR::Object *attachedObj = qmlObjects.at(binding->value.objectIndex);
314 auto *typeRef = resolvedType(binding->propertyNameIndex);
315 QQmlType type = typeRef ? typeRef->type() : QQmlType();
316 if (!type.isValid())
317 imports->resolveType(bindingPropertyName, &type, nullptr, nullptr, nullptr);
318
319 const QMetaObject *attachedType = type.attachedPropertiesType(enginePrivate);
320 if (!attachedType)
321 COMPILE_EXCEPTION(binding, tr("Non-existent attached object"));
323 if (!resolveSignalHandlerExpressions(attachedObj, bindingPropertyName, cache))
324 return false;
325 continue;
326 }
327
328 if (!QmlIR::IRBuilder::isSignalPropertyName(bindingPropertyName))
329 continue;
330
331 QQmlPropertyResolver resolver(propertyCache);
332
334 bindingPropertyName);
335
336 QString qPropertyName;
337 if (signalName.endsWith(QLatin1String("Changed")))
338 qPropertyName = signalName.mid(0, signalName.size() - static_cast<int>(strlen("Changed")));
339
340 bool notInRevision = false;
341 const QQmlPropertyData * const signal = resolver.signal(signalName, &notInRevision);
342 const QQmlPropertyData * const signalPropertyData = resolver.property(signalName, /*notInRevision ptr*/nullptr);
343 const QQmlPropertyData * const qPropertyData = !qPropertyName.isEmpty() ? resolver.property(qPropertyName) : nullptr;
344 QString finalSignalHandlerPropertyName = signalName;
347
348 const bool isPropertyObserver = !signalPropertyData && qPropertyData && qPropertyData->isBindable();
349 if (signal && !(qPropertyData && qPropertyData->isAlias() && isPropertyObserver)) {
350 int sigIndex = propertyCache->methodIndexToSignalIndex(signal->coreIndex());
351 sigIndex = propertyCache->originalClone(sigIndex);
352
353 bool unnamedParameter = false;
354
355 QList<QByteArray> parameterNames = propertyCache->signalParameterNames(sigIndex);
356 for (int i = 0; i < parameterNames.size(); ++i) {
357 const QString param = QString::fromUtf8(parameterNames.at(i));
358 if (param.isEmpty())
359 unnamedParameter = true;
360 else if (unnamedParameter) {
361 COMPILE_EXCEPTION(binding, tr("Signal uses unnamed parameter followed by named parameter."));
362 } else if (illegalNames.contains(param)) {
363 COMPILE_EXCEPTION(binding, tr("Signal parameter \"%1\" hides global variable.").arg(param));
364 }
365 }
366 } else if (isPropertyObserver) {
367 finalSignalHandlerPropertyName = qPropertyName;
369 } else {
370 if (notInRevision) {
371 // Try assinging it as a property later
372 if (signalPropertyData)
373 continue;
374
375 const QString &originalPropertyName = stringAt(binding->propertyNameIndex);
376
377 auto *typeRef = resolvedType(obj->inheritedTypeNameIndex);
378 const QQmlType type = typeRef ? typeRef->type() : QQmlType();
379 if (type.isValid()) {
380 COMPILE_EXCEPTION(binding, tr("\"%1.%2\" is not available in %3 %4.%5.")
381 .arg(typeName).arg(originalPropertyName).arg(type.module())
382 .arg(type.version().majorVersion())
383 .arg(type.version().minorVersion()));
384 } else {
385 COMPILE_EXCEPTION(binding, tr("\"%1.%2\" is not available due to component versioning.").arg(typeName).arg(originalPropertyName));
386 }
387 }
388
389 // Try to look up the signal parameter names in the object itself
390
391 // build cache if necessary
392 if (customSignals.isEmpty()) {
393 for (const QmlIR::Signal *signal = obj->firstSignal(); signal; signal = signal->next) {
394 const QString &signalName = stringAt(signal->nameIndex);
395 customSignals.insert(signalName, signal->parameterStringList(compiler->stringPool()));
396 }
397
398 for (const QmlIR::Property *property = obj->firstProperty(); property; property = property->next) {
399 const QString propName = stringAt(property->nameIndex);
400 customSignals.insert(propName, QStringList());
401 }
402 }
403
405 if (entry == customSignals.constEnd() && !qPropertyName.isEmpty())
406 entry = customSignals.constFind(qPropertyName);
407
408 if (entry == customSignals.constEnd()) {
409 // Can't find even a custom signal, then just don't do anything and try
410 // keeping the binding as a regular property assignment.
411 continue;
412 }
413 }
414
415 // Binding object to signal means connect the signal to the object's default method.
416 if (bindingType == QV4::CompiledData::Binding::Type_Object) {
418 continue;
419 }
420
421 if (bindingType != QV4::CompiledData::Binding::Type_Script) {
422 if (bindingType < QV4::CompiledData::Binding::Type_Script) {
423 COMPILE_EXCEPTION(binding, tr("Cannot assign a value to a signal (expecting a script to be run)"));
424 } else {
425 COMPILE_EXCEPTION(binding, tr("Incorrectly specified signal assignment"));
426 }
427 }
428
429 binding->propertyNameIndex = compiler->registerString(finalSignalHandlerPropertyName);
430 binding->setFlag(flag);
431 }
432 return true;
433}
434
436 : QQmlCompilePass(typeCompiler)
437 , qmlObjects(*typeCompiler->qmlObjects())
438 , propertyCaches(typeCompiler->propertyCaches())
439 , imports(typeCompiler->imports())
440{
441}
442
444{
445 for (int i = 0; i < qmlObjects.size(); ++i) {
446 QQmlPropertyCache::ConstPtr propertyCache = propertyCaches->at(i);
447 if (!propertyCache)
448 continue;
449 const QmlIR::Object *obj = qmlObjects.at(i);
450
451 QQmlPropertyResolver resolver(propertyCache);
452
453 for (QmlIR::Binding *binding = obj->firstBinding(); binding; binding = binding->next) {
454 const QV4::CompiledData::Binding::Flags bindingFlags = binding->flags();
458 continue;
459
460 if (binding->type() != QV4::CompiledData::Binding::Type_Script)
461 continue;
462
463 const QString propertyName = stringAt(binding->propertyNameIndex);
464 bool notInRevision = false;
465 const QQmlPropertyData *pd = resolver.property(propertyName, &notInRevision);
466 if (!pd || pd->isQList())
467 continue;
468
469 if (!pd->isEnum() && pd->propType().id() != QMetaType::Int)
470 continue;
471
472 if (!tryQualifiedEnumAssignment(obj, propertyCache, pd, binding))
473 return false;
474 }
475 }
476
477 return true;
478}
479
480bool QQmlEnumTypeResolver::assignEnumToBinding(QmlIR::Binding *binding, QStringView, int enumValue, bool)
481{
483 binding->value.constantValueIndex = compiler->registerConstant(QV4::Encode((double)enumValue));
484// binding->setNumberValueInternal((double)enumValue);
486 return true;
487}
488
489bool QQmlEnumTypeResolver::tryQualifiedEnumAssignment(
490 const QmlIR::Object *obj, const QQmlPropertyCache::ConstPtr &propertyCache,
491 const QQmlPropertyData *prop, QmlIR::Binding *binding)
492{
493 bool isIntProp = (prop->propType().id() == QMetaType::Int) && !prop->isEnum();
494 if (!prop->isEnum() && !isIntProp)
495 return true;
496
497 if (!prop->isWritable()
499 COMPILE_EXCEPTION(binding, tr("Invalid property assignment: \"%1\" is a read-only property")
500 .arg(stringAt(binding->propertyNameIndex)));
501 }
502
504 const QString string = compiler->bindingAsString(obj, binding->value.compiledScriptIndex);
505 if (!string.constData()->isUpper())
506 return true;
507
508 // reject any "complex" expression (even simple arithmetic)
509 // we do this by excluding everything that is not part of a
510 // valid identifier or a dot
511 for (const QChar &c : string)
512 if (!(c.isLetterOrNumber() || c == u'.' || c == u'_' || c.isSpace()))
513 return true;
514
515 // we support one or two '.' in the enum phrase:
516 // * <TypeName>.<EnumValue>
517 // * <TypeName>.<ScopedEnumName>.<EnumValue>
518
519 int dot = string.indexOf(QLatin1Char('.'));
520 if (dot == -1 || dot == string.size()-1)
521 return true;
522
523 int dot2 = string.indexOf(QLatin1Char('.'), dot+1);
524 if (dot2 != -1 && dot2 != string.size()-1) {
525 if (!string.at(dot+1).isUpper())
526 return true;
527 if (string.indexOf(QLatin1Char('.'), dot2+1) != -1)
528 return true;
529 }
530
531 QHashedStringRef typeName(string.constData(), dot);
532 const bool isQtObject = (typeName == QLatin1String("Qt"));
533 const QStringView scopedEnumName = (dot2 != -1 ? QStringView{string}.mid(dot + 1, dot2 - dot - 1) : QStringView());
534 // ### consider supporting scoped enums in Qt namespace
535 const QStringView enumValue = QStringView{string}.mid(!isQtObject && dot2 != -1 ? dot2 + 1 : dot + 1);
536
537 if (isIntProp) { // ### C++11 allows enums to be other integral types. Should we support other integral types here?
538 // Allow enum assignment to ints.
539 bool ok;
540 int enumval = evaluateEnum(typeName.toString(), scopedEnumName, enumValue, &ok);
541 if (ok) {
542 if (!assignEnumToBinding(binding, enumValue, enumval, isQtObject))
543 return false;
544 }
545 return true;
546 }
548 imports->resolveType(typeName, &type, nullptr, nullptr, nullptr);
549
550 if (!type.isValid() && !isQtObject)
551 return true;
552
553 int value = 0;
554 bool ok = false;
555
556 auto *tr = resolvedType(obj->inheritedTypeNameIndex);
557
558 // When these two match, we can short cut the search, unless...
559 bool useFastPath = type.isValid() && tr && tr->type() == type;
560 QMetaProperty mprop;
561 QMetaEnum menum;
562 if (useFastPath) {
563 mprop = propertyCache->firstCppMetaObject()->property(prop->coreIndex());
564 menum = mprop.enumerator();
565 // ...the enumerator merely comes from a related metaobject, but the enum scope does not match
566 // the typename we resolved
567 if (!menum.isScoped() && scopedEnumName.isEmpty() && typeName != QString::fromUtf8(menum.scope()))
568 useFastPath = false;;
569 }
570 if (useFastPath) {
571 QByteArray enumName = enumValue.toUtf8();
572 if (menum.isScoped() && !scopedEnumName.isEmpty() && enumName != scopedEnumName.toUtf8())
573 return true;
574
575 if (mprop.isFlagType()) {
576 value = menum.keysToValue(enumName.constData(), &ok);
577 } else {
578 value = menum.keyToValue(enumName.constData(), &ok);
579 }
580 } else {
581 // Otherwise we have to search the whole type
582 if (type.isValid()) {
583 if (!scopedEnumName.isEmpty())
584 value = type.scopedEnumValue(compiler->enginePrivate(), scopedEnumName, enumValue, &ok);
585 else
586 value = type.enumValue(compiler->enginePrivate(), QHashedStringRef(enumValue), &ok);
587 } else {
588 QByteArray enumName = enumValue.toUtf8();
589 const QMetaObject *metaObject = &Qt::staticMetaObject;
590 for (int ii = metaObject->enumeratorCount() - 1; !ok && ii >= 0; --ii) {
591 QMetaEnum e = metaObject->enumerator(ii);
592 value = e.keyToValue(enumName.constData(), &ok);
593 }
594 }
595 }
596
597 if (!ok)
598 return true;
599
600 return assignEnumToBinding(binding, enumValue, value, isQtObject);
601}
602
603int QQmlEnumTypeResolver::evaluateEnum(const QString &scope, QStringView enumName, QStringView enumValue, bool *ok) const
604{
605 Q_ASSERT_X(ok, "QQmlEnumTypeResolver::evaluateEnum", "ok must not be a null pointer");
606 *ok = false;
607
608 if (scope != QLatin1String("Qt")) {
610 imports->resolveType(scope, &type, nullptr, nullptr, nullptr);
611 if (!type.isValid())
612 return -1;
613 if (!enumName.isEmpty())
614 return type.scopedEnumValue(compiler->enginePrivate(), enumName, enumValue, ok);
616 }
617
618 const QMetaObject *mo = &Qt::staticMetaObject;
619 int i = mo->enumeratorCount();
620 const QByteArray ba = enumValue.toUtf8();
621 while (i--) {
622 int v = mo->enumerator(i).keyToValue(ba.constData(), ok);
623 if (*ok)
624 return v;
625 }
626 return -1;
627}
628
630 : QQmlCompilePass(typeCompiler)
631 , qmlObjects(*typeCompiler->qmlObjects())
632 , customParsers(typeCompiler->customParserCache())
633{
634}
635
637{
638 scanObjectRecursively(/*root object*/0);
639 for (int i = 0; i < qmlObjects.size(); ++i)
640 if (qmlObjects.at(i)->flags & QV4::CompiledData::Object::IsInlineComponentRoot)
641 scanObjectRecursively(i);
642}
643
644void QQmlCustomParserScriptIndexer::scanObjectRecursively(int objectIndex, bool annotateScriptBindings)
645{
646 const QmlIR::Object * const obj = qmlObjects.at(objectIndex);
647 if (!annotateScriptBindings)
648 annotateScriptBindings = customParsers.contains(obj->inheritedTypeNameIndex);
649 for (QmlIR::Binding *binding = obj->firstBinding(); binding; binding = binding->next) {
650 switch (binding->type()) {
652 if (annotateScriptBindings) {
655 }
656 break;
660 scanObjectRecursively(binding->value.objectIndex, annotateScriptBindings);
661 break;
662 default:
663 break;
664 }
665 }
666}
667
669 : QQmlCompilePass(typeCompiler)
670 , qmlObjects(*typeCompiler->qmlObjects())
671 , propertyCaches(typeCompiler->propertyCaches())
672{
673}
674
676{
677 for (int i = 0; i < qmlObjects.size(); ++i) {
678 QQmlPropertyCache::ConstPtr propertyCache = propertyCaches->at(i);
679 if (!propertyCache)
680 continue;
681
682 const QmlIR::Object *obj = qmlObjects.at(i);
683
684 QQmlPropertyResolver resolver(propertyCache);
685 const QQmlPropertyData *defaultProperty = obj->indexOfDefaultPropertyOrAlias != -1 ? propertyCache->parent()->defaultProperty() : propertyCache->defaultProperty();
686
687 for (QmlIR::Binding *binding = obj->firstBinding(); binding; binding = binding->next) {
688 if (!binding->isValueBinding())
689 continue;
690 bool notInRevision = false;
691 const QQmlPropertyData *pd = binding->propertyNameIndex != quint32(0) ? resolver.property(stringAt(binding->propertyNameIndex), &notInRevision) : defaultProperty;
692 if (pd && pd->isAlias())
694 }
695 }
696}
697
699 : QQmlCompilePass(typeCompiler)
700 , qmlObjects(*typeCompiler->qmlObjects())
701 , propertyCaches(typeCompiler->propertyCaches())
702{
703
704}
705
707{
708 const QMetaType scriptStringMetaType = QMetaType::fromType<QQmlScriptString>();
709 for (int i = 0; i < qmlObjects.size(); ++i) {
710 QQmlPropertyCache::ConstPtr propertyCache = propertyCaches->at(i);
711 if (!propertyCache)
712 continue;
713
714 const QmlIR::Object *obj = qmlObjects.at(i);
715
716 QQmlPropertyResolver resolver(propertyCache);
717 const QQmlPropertyData *defaultProperty = obj->indexOfDefaultPropertyOrAlias != -1 ? propertyCache->parent()->defaultProperty() : propertyCache->defaultProperty();
718
719 for (QmlIR::Binding *binding = obj->firstBinding(); binding; binding = binding->next) {
721 continue;
722 bool notInRevision = false;
723 const QQmlPropertyData *pd = binding->propertyNameIndex != quint32(0) ? resolver.property(stringAt(binding->propertyNameIndex), &notInRevision) : defaultProperty;
724 if (!pd || pd->propType() != scriptStringMetaType)
725 continue;
726
728 binding->stringIndex = compiler->registerString(script);
729 }
730 }
731}
732
733template<>
735 QmlIR::Object *object) const
736{
737 object->namedObjectsInComponent.allocate(m_compiler->memoryPool(), m_idToObjectIndex);
738}
739
740template<>
742{
743 m_compiler->qmlObjects()->at(index)->flags |= QV4::CompiledData::Object::IsComponent;
744 return true;
745}
746
747template<>
749{
750 m_compiler->qmlObjects()->at(index)->id = m_idToObjectIndex.size();
751}
752
753template<>
755{
756 QQmlJS::MemoryPool *pool = m_compiler->memoryPool();
757 QVector<QmlIR::Object *> *qmlObjects = m_compiler->qmlObjects();
758
759 // emulate "import QML 1.0" and then wrap the component in "QML.Component {}"
760 QQmlType componentType = QQmlMetaType::qmlType(
761 &QQmlComponent::staticMetaObject, QStringLiteral("QML"),
763 Q_ASSERT(componentType.isValid());
764 const QString qualifier = QStringLiteral("QML");
765
766 m_compiler->addImport(componentType.module(), qualifier, componentType.version());
767
768 QmlIR::Object *syntheticComponent = pool->New<QmlIR::Object>();
769 syntheticComponent->init(
770 pool,
771 m_compiler->registerString(
772 qualifier + QLatin1Char('.') + componentType.elementName()),
773 m_compiler->registerString(QString()), binding->valueLocation);
774 syntheticComponent->flags |= QV4::CompiledData::Object::IsComponent;
775
776 if (!m_compiler->resolvedTypes->contains(syntheticComponent->inheritedTypeNameIndex)) {
777 auto typeRef = new QV4::ResolvedTypeReference;
778 typeRef->setType(componentType);
779 typeRef->setVersion(componentType.version());
780 m_compiler->resolvedTypes->insert(syntheticComponent->inheritedTypeNameIndex, typeRef);
781 }
782
783 qmlObjects->append(syntheticComponent);
784 const int componentIndex = qmlObjects->size() - 1;
785 // Keep property caches symmetric
786 QQmlPropertyCache::ConstPtr componentCache
787 = QQmlMetaType::propertyCache(&QQmlComponent::staticMetaObject);
788 m_propertyCaches->append(componentCache);
789
790 QmlIR::Binding *syntheticBinding = pool->New<QmlIR::Binding>();
791 *syntheticBinding = *binding;
792
793 // The synthetic binding inside Component has no name. It's just "Component { Foo {} }".
794 syntheticBinding->propertyNameIndex = 0;
795
797 QString error = syntheticComponent->appendBinding(syntheticBinding, /*isListBinding*/false);
798 Q_ASSERT(error.isEmpty());
800
801 binding->value.objectIndex = componentIndex;
802
803 m_componentRoots.append(componentIndex);
804 return true;
805}
806
807template<>
808typename QQmlComponentAndAliasResolver<QQmlTypeCompiler>::AliasResolutionResult
810 int objectIndex, QQmlError *error)
811{
812 const QmlIR::Object * const obj = m_compiler->objectAt(objectIndex);
813 if (!obj->aliasCount())
814 return AllAliasesResolved;
815
816 int numResolvedAliases = 0;
817 bool seenUnresolvedAlias = false;
818
819 for (QmlIR::Alias *alias = obj->firstAlias(); alias; alias = alias->next) {
820 if (alias->hasFlag(QV4::CompiledData::Alias::Resolved))
821 continue;
822
823 seenUnresolvedAlias = true;
824
825 const int idIndex = alias->idIndex();
826 const int targetObjectIndex = m_idToObjectIndex.value(idIndex, -1);
827 if (targetObjectIndex == -1) {
829 alias->referenceLocation,
830 tr("Invalid alias reference. Unable to find id \"%1\"").arg(stringAt(idIndex)));
831 break;
832 }
833
834 const QmlIR::Object *targetObject = m_compiler->objectAt(targetObjectIndex);
835 Q_ASSERT(targetObject->id >= 0);
836 alias->setTargetObjectId(targetObject->id);
837 alias->setIsAliasToLocalAlias(false);
838
839 const QString aliasPropertyValue = stringAt(alias->propertyNameIndex);
840
842 QStringView subProperty;
843
844 const int propertySeparator = aliasPropertyValue.indexOf(QLatin1Char('.'));
845 if (propertySeparator != -1) {
846 property = QStringView{aliasPropertyValue}.left(propertySeparator);
847 subProperty = QStringView{aliasPropertyValue}.mid(propertySeparator + 1);
848 } else
849 property = QStringView(aliasPropertyValue);
850
851 QQmlPropertyIndex propIdx;
852
853 if (property.isEmpty()) {
855 } else {
856 QQmlPropertyCache::ConstPtr targetCache = m_propertyCaches->at(targetObjectIndex);
857 if (!targetCache) {
859 alias->referenceLocation,
860 tr("Invalid alias target location: %1").arg(property.toString()));
861 break;
862 }
863
864 QQmlPropertyResolver resolver(targetCache);
865
866 const QQmlPropertyData *targetProperty = resolver.property(property.toString());
867
868 // If it's an alias that we haven't resolved yet, try again later.
869 if (!targetProperty) {
870 bool aliasPointsToOtherAlias = false;
871 int localAliasIndex = 0;
872 for (auto targetAlias = targetObject->aliasesBegin(), end = targetObject->aliasesEnd(); targetAlias != end; ++targetAlias, ++localAliasIndex) {
873 if (stringAt(targetAlias->nameIndex()) == property) {
874 aliasPointsToOtherAlias = true;
875 break;
876 }
877 }
878 if (aliasPointsToOtherAlias) {
879 if (targetObjectIndex == objectIndex) {
880 alias->localAliasIndex = localAliasIndex;
881 alias->setIsAliasToLocalAlias(true);
883 ++numResolvedAliases;
884 continue;
885 }
886
887 // restore
888 alias->setIdIndex(idIndex);
889 // Try again later and resolve the target alias first.
890 break;
891 }
892 }
893
894 if (!targetProperty || targetProperty->coreIndex() > 0x0000FFFF) {
896 alias->referenceLocation,
897 tr("Invalid alias target location: %1").arg(property.toString()));
898 break;
899 }
900
901 propIdx = QQmlPropertyIndex(targetProperty->coreIndex());
902
903 if (!subProperty.isEmpty()) {
904 const QMetaObject *valueTypeMetaObject = QQmlMetaType::metaObjectForValueType(targetProperty->propType());
905 if (!valueTypeMetaObject) {
906 // could be a deep alias
907 bool isDeepAlias = subProperty.at(0).isLower();
908 if (isDeepAlias) {
909 isDeepAlias = false;
910 for (auto it = targetObject->bindingsBegin(); it != targetObject->bindingsEnd(); ++it) {
911 auto binding = *it;
912 if (m_compiler->stringAt(binding.propertyNameIndex) == property) {
913 resolver = QQmlPropertyResolver(m_propertyCaches->at(binding.value.objectIndex));
914 const QQmlPropertyData *actualProperty = resolver.property(subProperty.toString());
915 if (actualProperty) {
916 propIdx = QQmlPropertyIndex(propIdx.coreIndex(), actualProperty->coreIndex());
917 isDeepAlias = true;
918 }
919 }
920 }
921 }
922 if (!isDeepAlias) {
924 alias->referenceLocation,
925 tr("Invalid alias target location: %1").arg(subProperty.toString()));
926 break;
927 }
928 } else {
929
930 int valueTypeIndex =
931 valueTypeMetaObject->indexOfProperty(subProperty.toString().toUtf8().constData());
932 if (valueTypeIndex == -1) {
934 alias->referenceLocation,
935 tr("Invalid alias target location: %1").arg(subProperty.toString()));
936 break;
937 }
938 Q_ASSERT(valueTypeIndex <= 0x0000FFFF);
939
940 propIdx = QQmlPropertyIndex(propIdx.coreIndex(), valueTypeIndex);
941 }
942 } else {
943 if (targetProperty->isQObject())
945 }
946 }
947
948 alias->encodedMetaPropertyIndex = propIdx.toEncoded();
950 numResolvedAliases++;
951 }
952
953 if (numResolvedAliases == 0)
954 return seenUnresolvedAlias ? NoAliasResolved : AllAliasesResolved;
955
956 return SomeAliasesResolved;
957}
958
960 : QQmlCompilePass(typeCompiler)
961 , qmlObjects(typeCompiler->qmlObjects())
962 , propertyCaches(typeCompiler->propertyCaches())
963 , customParsers(typeCompiler->customParserCache())
964 , _seenObjectWithId(false)
965{
966}
967
969{
970 for (int i = 0; i < qmlObjects->size(); ++i) {
971 if ((qmlObjects->at(i)->flags & QV4::CompiledData::Object::IsInlineComponentRoot)
972 && !scanObject(i, ScopeDeferred::False)) {
973 return false;
974 }
975 }
976 return scanObject(/*root object*/0, ScopeDeferred::False);
977}
978
980 int objectIndex, ScopeDeferred scopeDeferred)
981{
982 using namespace QV4::CompiledData;
983
984 QmlIR::Object *obj = qmlObjects->at(objectIndex);
985 if (obj->idNameIndex != 0)
986 _seenObjectWithId = true;
987
988 if (obj->flags & Object::IsComponent) {
989 Q_ASSERT(obj->bindingCount() == 1);
990 const Binding *componentBinding = obj->firstBinding();
991 Q_ASSERT(componentBinding->type() == Binding::Type_Object);
992 // Components are separate from their surrounding scope. They cannot be deferred.
993 return scanObject(componentBinding->value.objectIndex, ScopeDeferred::False);
994 }
995
996 QQmlPropertyCache::ConstPtr propertyCache = propertyCaches->at(objectIndex);
997 if (!propertyCache)
998 return true;
999
1000 QString defaultPropertyName;
1001 const QQmlPropertyData *defaultProperty = nullptr;
1002 if (obj->indexOfDefaultPropertyOrAlias != -1) {
1003 const QQmlPropertyCache *cache = propertyCache->parent().data();
1004 defaultPropertyName = cache->defaultPropertyName();
1005 defaultProperty = cache->defaultProperty();
1006 } else {
1007 defaultPropertyName = propertyCache->defaultPropertyName();
1008 defaultProperty = propertyCache->defaultProperty();
1009 }
1010
1011 QQmlCustomParser *customParser = customParsers.value(obj->inheritedTypeNameIndex);
1012
1013 QQmlPropertyResolver propertyResolver(propertyCache);
1014
1015 QStringList deferredPropertyNames;
1016 QStringList immediatePropertyNames;
1017 {
1018 const QMetaObject *mo = propertyCache->firstCppMetaObject();
1019 const int deferredNamesIndex = mo->indexOfClassInfo("DeferredPropertyNames");
1020 const int immediateNamesIndex = mo->indexOfClassInfo("ImmediatePropertyNames");
1021 if (deferredNamesIndex != -1) {
1022 if (immediateNamesIndex != -1) {
1023 COMPILE_EXCEPTION(obj, tr("You cannot define both DeferredPropertyNames and "
1024 "ImmediatePropertyNames on the same type."));
1025 }
1026 const QMetaClassInfo classInfo = mo->classInfo(deferredNamesIndex);
1027 deferredPropertyNames = QString::fromUtf8(classInfo.value()).split(u',');
1028 } else if (immediateNamesIndex != -1) {
1029 const QMetaClassInfo classInfo = mo->classInfo(immediateNamesIndex);
1030 immediatePropertyNames = QString::fromUtf8(classInfo.value()).split(u',');
1031
1032 // If the property contains an empty string, all properties shall be deferred.
1033 if (immediatePropertyNames.isEmpty())
1034 immediatePropertyNames.append(QString());
1035 }
1036 }
1037
1038 for (QmlIR::Binding *binding = obj->firstBinding(); binding; binding = binding->next) {
1040
1041 if (customParser) {
1042 if (binding->type() == Binding::Type_AttachedProperty) {
1043 if (customParser->flags() & QQmlCustomParser::AcceptsAttachedProperties) {
1044 binding->setFlag(Binding::IsCustomParserBinding);
1045 obj->flags |= Object::HasCustomParserBindings;
1046 continue;
1047 }
1049 && !(customParser->flags() & QQmlCustomParser::AcceptsSignalHandlers)) {
1050 obj->flags |= Object::HasCustomParserBindings;
1051 binding->setFlag(Binding::IsCustomParserBinding);
1052 continue;
1053 }
1054 }
1055
1056 const bool hasPropertyData = [&]() {
1057 if (name.isEmpty()) {
1058 name = defaultPropertyName;
1059 if (defaultProperty)
1060 return true;
1061 } else if (name.constData()->isUpper()) {
1062 // Upper case names cannot be custom-parsed unless they are attached properties
1063 // and the custom parser explicitly accepts them. See above for that case.
1064 return false;
1065 } else {
1066 bool notInRevision = false;
1067 if (propertyResolver.property(
1068 name, &notInRevision, QQmlPropertyResolver::CheckRevision)) {
1069 return true;
1070 }
1071 }
1072
1073 if (!customParser)
1074 return false;
1075
1076 const Binding::Flags bindingFlags = binding->flags();
1077 if (bindingFlags & Binding::IsSignalHandlerExpression
1078 || bindingFlags & Binding::IsSignalHandlerObject
1079 || bindingFlags & Binding::IsPropertyObserver) {
1080 // These signal handlers cannot be custom-parsed. We have already established
1081 // that the signal exists.
1082 return false;
1083 }
1084
1085 // If the property isn't found, we may want to custom-parse the binding.
1086 obj->flags |= Object::HasCustomParserBindings;
1087 binding->setFlag(Binding::IsCustomParserBinding);
1088 return false;
1089 }();
1090
1091 bool seenSubObjectWithId = false;
1092 bool isExternal = false;
1093 if (binding->type() >= Binding::Type_Object) {
1094 const bool isOwnProperty = hasPropertyData || binding->isAttachedProperty();
1095 isExternal = !isOwnProperty && binding->isGroupProperty();
1096 if (isOwnProperty || isExternal) {
1097 qSwap(_seenObjectWithId, seenSubObjectWithId);
1098 const bool subObjectValid = scanObject(
1099 binding->value.objectIndex,
1100 (isExternal || scopeDeferred == ScopeDeferred::True)
1101 ? ScopeDeferred::True
1102 : ScopeDeferred::False);
1103 qSwap(_seenObjectWithId, seenSubObjectWithId);
1104 if (!subObjectValid)
1105 return false;
1106 _seenObjectWithId |= seenSubObjectWithId;
1107 }
1108 }
1109
1110 bool isDeferred = false;
1111 if (!immediatePropertyNames.isEmpty() && !immediatePropertyNames.contains(name)) {
1112 if (seenSubObjectWithId) {
1113 COMPILE_EXCEPTION(binding, tr("You cannot assign an id to an object assigned "
1114 "to a deferred property."));
1115 }
1116 if (isExternal || !disableInternalDeferredProperties())
1117 isDeferred = true;
1118 } else if (!deferredPropertyNames.isEmpty() && deferredPropertyNames.contains(name)) {
1119 if (!seenSubObjectWithId && binding->type() != Binding::Type_GroupProperty) {
1120 if (isExternal || !disableInternalDeferredProperties())
1121 isDeferred = true;
1122 }
1123 }
1124
1125 if (binding->type() >= Binding::Type_Object) {
1126 if (isExternal && !isDeferred && !customParser) {
1128 binding, tr("Cannot assign to non-existent property \"%1\"").arg(name));
1129 }
1130 }
1131
1132 if (isDeferred) {
1133 binding->setFlag(Binding::IsDeferredBinding);
1134 obj->flags |= Object::HasDeferredBindings;
1135 }
1136 }
1137
1138 return true;
1139}
1140
1142 : QQmlCompilePass(typeCompiler)
1143 , qmlObjects(*typeCompiler->qmlObjects())
1144 , propertyCaches(typeCompiler->propertyCaches())
1145{
1146
1147}
1148
1150{
1151 for (int i = 0; i < qmlObjects.size(); ++i)
1153}
1154
1156{
1157 QQmlPropertyCache::ConstPtr propertyCache = propertyCaches->at(objectIndex);
1158 if (!propertyCache)
1159 return;
1160
1161 QmlIR::Object *object = qmlObjects.at(objectIndex);
1162
1163 QString defaultProperty = object->indexOfDefaultPropertyOrAlias != -1 ? propertyCache->parent()->defaultPropertyName() : propertyCache->defaultPropertyName();
1164 QmlIR::Binding *bindingsToReinsert = nullptr;
1165 QmlIR::Binding *tail = nullptr;
1166
1167 QmlIR::Binding *previousBinding = nullptr;
1168 QmlIR::Binding *binding = object->firstBinding();
1169 while (binding) {
1170 if (binding->propertyNameIndex == quint32(0) || stringAt(binding->propertyNameIndex) != defaultProperty) {
1171 previousBinding = binding;
1172 binding = binding->next;
1173 continue;
1174 }
1175
1176 QmlIR::Binding *toReinsert = binding;
1177 binding = object->unlinkBinding(previousBinding, binding);
1178
1179 if (!tail) {
1180 bindingsToReinsert = toReinsert;
1181 tail = toReinsert;
1182 } else {
1183 tail->next = toReinsert;
1184 tail = tail->next;
1185 }
1186 tail->next = nullptr;
1187 }
1188
1189 binding = bindingsToReinsert;
1190 while (binding) {
1191 QmlIR::Binding *toReinsert = binding;
1192 binding = binding->next;
1193 object->insertSorted(toReinsert);
1194 }
1195}
1196
\inmodule QtCore
Definition qbytearray.h:57
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
Definition qbytearray.h:122
\inmodule QtCore
Definition qchar.h:48
constexpr bool isLower() const noexcept
Returns true if the character is a lowercase letter, for example category() is Letter_Lowercase.
Definition qchar.h:474
\inmodule QtCore
Definition qhash.h:1135
\inmodule QtCore
Definition qhash.h:818
const_iterator constFind(const Key &key) const noexcept
Definition qhash.h:1279
const_iterator constEnd() const noexcept
Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary item after the ...
Definition qhash.h:1209
const_iterator constBegin() const noexcept
Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first item in the hash.
Definition qhash.h:1205
bool contains(const Key &key) const noexcept
Returns true if the hash contains an item with the key; otherwise returns false.
Definition qhash.h:991
T value(const Key &key) const noexcept
Definition qhash.h:1044
bool isEmpty() const noexcept
Returns true if the hash contains no items; otherwise returns false.
Definition qhash.h:926
iterator insert(const Key &key, const T &value)
Inserts a new item with the key and a value of value.
Definition qhash.h:1283
Definition qlist.h:74
qsizetype size() const noexcept
Definition qlist.h:386
bool isEmpty() const noexcept
Definition qlist.h:390
const_reference at(qsizetype i) const noexcept
Definition qlist.h:429
void append(parameter_type t)
Definition qlist.h:441
void clear()
Definition qlist.h:417
\inmodule QtCore
\inmodule QtCore
int keysToValue(const char *keys, bool *ok=nullptr) const
Returns the value derived from combining together the values of the keys using the OR operator,...
bool isScoped() const
int keyToValue(const char *key, bool *ok=nullptr) const
Returns the integer value of the given enumeration key, or -1 if key is not defined.
const char * scope() const
Returns the scope this enumerator was declared in.
\inmodule QtCore
QMetaEnum enumerator() const
Returns the enumerator if this property's type is an enumerator type; otherwise the returned value is...
bool isFlagType() const
Returns true if the property's type is an enumeration value that is used as a flag; otherwise returns...
\inmodule QtCore
Definition qmetatype.h:320
int id(int=0) const
Definition qmetatype.h:454
QQmlAliasAnnotator(QQmlTypeCompiler *typeCompiler)
QQmlCustomParserScriptIndexer(QQmlTypeCompiler *typeCompiler)
The QQmlCustomParser class allows you to add new arbitrary types to QML.
QString finalUrlString() const
Returns the finalUrl() as a string.
QString urlString() const
QQmlDefaultPropertyMerger(QQmlTypeCompiler *typeCompiler)
QQmlDeferredAndCustomParserBindingScanner(QQmlTypeCompiler *typeCompiler)
QV4::ExecutionEngine * v4engine() const
QQmlEnumTypeResolver(QQmlTypeCompiler *typeCompiler)
The QQmlError class encapsulates a QML error.
Definition qqmlerror.h:18
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
MemoryPool * pool()
QStringView newStringRef(const QString &text)
static const QMetaObject * metaObjectForValueType(QMetaType type)
static QQmlPropertyCache::ConstPtr propertyCache(QObject *object, QTypeRevision version=QTypeRevision())
Returns a QQmlPropertyCache for obj if one is available.
static QQmlType qmlType(const QString &qualifiedName, QTypeRevision version)
Returns the type (if any) of URI-qualified named qualifiedName and version specified by version_major...
IncrementalResult buildMetaObjectsIncrementally()
QQmlPropertyCache::ConstPtr at(int index) const
QMetaType propType() const
qint32 toEncoded() const
T * data() const
QQmlScriptStringScanner(QQmlTypeCompiler *typeCompiler)
QQmlType qmlType(const QString &inlineComponentName=QString()) const
QByteArray typeClassName() const
const QQmlImports * imports() const
QTypeRevision version() const
Definition qqmltype.cpp:112
QHashedString module() const
Definition qqmltype.cpp:105
bool isValid() const
Definition qqmltype_p.h:58
QString elementName() const
Definition qqmltype.cpp:442
bool contains(const T &value) const
Definition qset.h:71
\inmodule QtCore
\inmodule QtCore
Definition qstringview.h:76
constexpr bool isEmpty() const noexcept
Returns whether this string view is empty - that is, whether {size() == 0}.
QByteArray toUtf8() const
Returns a UTF-8 representation of the string view as a QByteArray.
QString toString() const
Returns a deep copy of this string view's data as a QString.
Definition qstring.h:1014
constexpr QChar at(qsizetype n) const noexcept
Returns the character at position n in this string view.
constexpr QStringView mid(qsizetype pos, qsizetype n=-1) const noexcept
Returns the substring of length length starting at position start in this object.
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
QStringList split(const QString &sep, Qt::SplitBehavior behavior=Qt::KeepEmptyParts, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Splits the string into substrings wherever sep occurs, and returns the list of those strings.
Definition qstring.cpp:7956
const QChar * constData() const
Returns a pointer to the data stored in the QString.
Definition qstring.h:1101
qsizetype size() const
Returns the number of characters in this string.
Definition qstring.h:182
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5857
QString mid(qsizetype position, qsizetype n=-1) const
Returns a string that contains n characters of this string, starting at the specified position index.
Definition qstring.cpp:5204
bool endsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string ends with s; otherwise returns false.
Definition qstring.cpp:5350
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:1083
QString left(qsizetype n) const
Returns a substring that contains the n leftmost characters of the string.
Definition qstring.cpp:5161
static QString static QString qsizetype indexOf(QChar c, qsizetype from=0, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Definition qstring.cpp:4420
QByteArray toUtf8() const &
Definition qstring.h:563
\inmodule QtCore
static constexpr QTypeRevision fromVersion(Major majorVersion, Minor minorVersion)
Produces a QTypeRevision from the given majorVersion and minorVersion, both of which need to be a val...
QQmlJS::DiagnosticMessage error() const
QV4::CompiledData::CompilationUnit generateCompilationUnit(bool generateUnitData=true)
static QQmlRefPointer< ExecutableCompilationUnit > create()
QString str
[2]
qSwap(pi, e)
double e
QCache< int, Employee > cache
[0]
QSet< QString >::iterator it
auto signal
auto mo
[7]
const char * classInfo(const QMetaObject *metaObject, const char *key)
Combined button and popup list for selecting options.
std::function< QByteArray()> DependentTypesHasher
quint64 ReturnedValue
QString enumValue(const QString &value)
Definition language.cpp:469
QString qualifier
Definition language.cpp:56
DBusConnection const char DBusError * error
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
#define Q_LOGGING_CATEGORY(name,...)
const char * typeName
GLint location
GLsizei const GLfloat * v
[13]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLuint index
[2]
GLuint GLuint end
GLenum GLenum GLsizei count
GLenum type
GLuint GLsizei const GLchar * message
GLenum const GLint * param
GLuint name
GLhandleARB obj
[2]
const GLubyte * c
GLhandleARB attachedObj
GLuint entry
GLuint64EXT * result
[6]
GLsizei const GLchar *const * string
[0]
Definition qopenglext.h:694
static qreal dot(const QPointF &a, const QPointF &b)
#define DEFINE_BOOL_CONFIG_OPTION(name, var)
#define COMPILE_EXCEPTION(location, desc)
QT_BEGIN_NAMESPACE QQmlError qQmlCompileError(const QV4::CompiledData::Location &location, const QString &description)
int qmlConvertSourceCoordinate< quint32, int >(quint32 n)
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define Q_ASSERT_X(cond, x, msg)
Definition qrandom.cpp:48
SSL_CTX int(*) void arg)
QLatin1StringView QLatin1String
Definition qstringfwd.h:31
#define QStringLiteral(str)
#define tr(X)
#define Q_UNUSED(x)
unsigned int quint32
Definition qtypes.h:45
const char property[13]
Definition qwizard.cpp:101
if(qFloatDistance(a, b)<(1<< 7))
[0]
QByteArray ba
[0]
obj metaObject() -> className()
list indexOf("B")
QAction * at
QJSEngine engine
[0]
\inmodule QtCore \reentrant
Definition qchar.h:17
\inmodule QtCore
int indexOfProperty(const char *name) const
Finds property name and returns its index; otherwise returns -1.
QQmlCompilePass(QQmlTypeCompiler *typeCompiler)
QV4::ResolvedTypeReference * resolvedType(int id) const
QQmlTypeCompiler * compiler
QString stringAt(int idx) const
void resolveMissingPropertyCaches(QQmlPropertyCacheVector *propertyCaches) const
const QQmlPropertyData * property(int index) const
QQmlEnginePrivate * enginePrivate() const
int registerConstant(QV4::ReturnedValue v)
const QV4::CompiledData::Unit * qmlUnit() const
QQmlType qmlTypeForComponent(const QString &inlineComponentName=QString()) const
QQmlPropertyCacheVector * propertyCaches()
QQmlJS::MemoryPool * memoryPool()
QV4::ResolvedTypeReferenceMap * resolvedTypes
QString bindingAsString(const QmlIR::Object *object, int scriptIndex) const
QQmlTypeCompiler(QQmlEnginePrivate *engine, QQmlTypeData *typeData, QmlIR::Document *document, const QQmlRefPointer< QQmlTypeNameCache > &typeNameCache, QV4::ResolvedTypeReferenceMap *resolvedTypeCache, const QV4::CompiledData::DependentTypesHasher &dependencyHasher)
QQmlRefPointer< QV4::ExecutableCompilationUnit > compile()
int registerString(const QString &str)
const QV4::Compiler::StringTableGenerator * stringPool() const
void recordError(const QV4::CompiledData::Location &location, const QString &description)
QStringView newStringRef(const QString &string)
void addImport(const QString &module, const QString &qualifier, QTypeRevision version)
QVector< QmlIR::Object * > * qmlObjects() const
QString stringAt(int idx) const
const QQmlImports * imports() const
union QV4::CompiledData::Binding::@543 value
bool hasFlag(Flag flag) const
StringTableGenerator stringTable
int registerConstant(ReturnedValue v)
int registerString(const QString &str)
const QSet< QString > & illegalNames() const
QVector< Object * > objects
QString stringAt(int index) const
QV4::Compiler::Module jsModule
QV4::CompiledData::CompilationUnit javaScriptCompilationUnit
QV4::Compiler::JSUnitGenerator jsGenerator
QList< const QV4::CompiledData::Import * > imports
QQmlJS::Engine jsParserEngine
static QString signalNameFromSignalPropertyName(const QString &signalPropertyName)
static bool isSignalPropertyName(const QString &name)
bool generateRuntimeFunctions(QmlIR::Object *object)
PoolList< Binding >::Iterator bindingsEnd() const
QString appendBinding(Binding *b, bool isListBinding)
PoolList< Alias >::Iterator aliasesBegin() const
void init(QQmlJS::MemoryPool *pool, int typeNameIndex, int idIndex, const QV4::CompiledData::Location &location)
quint32 inheritedTypeNameIndex
PoolList< Binding >::Iterator bindingsBegin() const
PoolList< Alias >::Iterator aliasesEnd() const
void generate(Document &output, const QV4::CompiledData::DependentTypesHasher &dependencyHasher=QV4::CompiledData::DependentTypesHasher())
SignalHandlerResolver(QQmlTypeCompiler *typeCompiler)