345 static_assert(
sizeof(Object) == 84,
"Update objectContentEqual when Object layout changes");
346 if (oldObj.nNamedObjectsInComponent != newObj.nNamedObjectsInComponent)
349 const quint32_le *oldNamed = oldObj.namedObjectsInComponentTable();
350 const quint32_le *newNamed = newObj.namedObjectsInComponentTable();
351 for (quint32 i = 0; i < oldObj.nNamedObjectsInComponent; ++i) {
352 if (oldNamed[i] != newNamed[i])
356 if (oldObj.nFunctions != newObj.nFunctions)
359 const quint32_le *oldFuncs = oldObj.functionOffsetTable();
360 const quint32_le *newFuncs = newObj.functionOffsetTable();
361 for (quint32 i = 0; i < oldObj.nFunctions; ++i) {
362 if (oldFuncs[i] != newFuncs[i])
366 return stringsEqual(oldObj.inheritedTypeNameIndex, newObj.inheritedTypeNameIndex)
367 && stringsEqual(oldObj.idNameIndex, newObj.idNameIndex)
368 && oldObj.flags() == newObj.flags()
369 && oldObj.hasAliasAsDefaultProperty() == newObj.hasAliasAsDefaultProperty()
370 && oldObj.objectId() == newObj.objectId()
371 && oldObj.indexOfDefaultPropertyOrAlias == newObj.indexOfDefaultPropertyOrAlias;
449 static_assert(
sizeof(Binding) == 24,
"Update bindingContentEqual when Binding layout changes");
450 static_assert(
sizeof(TranslationData) == 16,
"Update bindingContentEqual when TranslationData layout changes");
451 if (oldBinding.type() != newBinding.type() || oldBinding.flags() != newBinding.flags())
454 if (!stringsEqual(oldBinding.propertyNameIndex, newBinding.propertyNameIndex))
457 switch (oldBinding.type()) {
458 case Binding::Type_Invalid:
460 case Binding::Type_Boolean:
461 return oldBinding.valueAsBoolean() == newBinding.valueAsBoolean();
462 case Binding::Type_Number: {
463 if (oldBinding.hasFlag(CompiledData::Binding::IsResolvedEnum))
464 return oldBinding.value.resolvedEnumValue == newBinding.value.resolvedEnumValue;
465 const uint oldIdx = oldBinding.value.constantValueIndex;
466 const uint newIdx = newBinding.value.constantValueIndex;
467 Q_ASSERT(oldIdx < oldUnit->constantTableSize);
468 Q_ASSERT(newIdx < newUnit->constantTableSize);
469 return oldIdx == newIdx && oldUnit->constants()[oldIdx] == newUnit->constants()[newIdx];
471 case Binding::Type_String:
472 return stringsEqual(oldBinding.stringIndex, newBinding.stringIndex);
473 case Binding::Type_Null:
475 case Binding::Type_Translation:
476 case Binding::Type_TranslationById: {
477 const auto &oldTrans = oldUnit->translations()[oldBinding.value.translationDataIndex];
478 const auto &newTrans = newUnit->translations()[newBinding.value.translationDataIndex];
482 const bool oldHasCtx = oldTrans.contextIndex != TranslationData::NoContextIndex;
483 const bool newHasCtx = newTrans.contextIndex != TranslationData::NoContextIndex;
485 if (oldHasCtx != newHasCtx)
488 if (oldHasCtx && !stringsEqual(oldTrans.contextIndex, newTrans.contextIndex))
491 return stringsEqual(oldBinding.stringIndex, newBinding.stringIndex)
492 && stringsEqual(oldTrans.stringIndex, newTrans.stringIndex)
493 && stringsEqual(oldTrans.commentIndex, newTrans.commentIndex)
494 && oldTrans.number == newTrans.number;
496 case Binding::Type_Script:
497 return oldBinding.value.compiledScriptIndex == newBinding.value.compiledScriptIndex;
498 case Binding::Type_Object:
499 case Binding::Type_AttachedProperty:
500 case Binding::Type_GroupProperty:
501 return oldBinding.value.objectIndex == newBinding.value.objectIndex
502 && objectContentEqual(
503 *oldUnit->qmlUnit()->objectAt(oldBinding.value.objectIndex),
504 *newUnit->qmlUnit()->objectAt(newBinding.value.objectIndex));
729 const QmlUnit *oldQml = oldUnit->qmlUnit();
730 const QmlUnit *newQml = newUnit->qmlUnit();
732 if (!oldQml || !newQml)
739 change.data = extractData(*newUnit);
740 changes.append(change);
743 compareIndexedElements<Object>(
745 [oldQml](quint32 i) ->
const Object & {
return *oldQml->objectAt(i); },
748 [newQml](quint32 i) ->
const Object & {
return *newQml->objectAt(i); },
750 [
this](
const Object &a,
const Object &b) {
return objectContentEqual(a, b); });
753 const quint32 commonCount = std::min(oldQml->nObjects, newQml->nObjects);
754 for (quint32 objectIndex = 0; objectIndex < commonCount; ++objectIndex) {
756 const Object *oldObj = oldQml->objectAt(objectIndex);
757 const Object *newObj = newQml->objectAt(objectIndex);
759 compareObjectProperties(oldObj, newObj);
760 compareObjectAliases(oldObj, newObj);
761 compareObjectEnums(oldObj, newObj);
762 compareObjectSignals(oldObj, newObj);
763 compareObjectInlineComponents(oldObj, newObj);
764 compareObjectRequiredPropertyExtraData(oldObj, newObj);
765 compareObjectBindings(oldObj, newObj);
768 compareIndexedElements<quint64_le>(
769 IndexedElements{ [
this](quint32 i) {
return oldUnit->constants()[i]; },
770 oldUnit->constantTableSize },
771 IndexedElements{ [
this](quint32 i) {
return newUnit->constants()[i]; },
772 newUnit->constantTableSize },
773 [](
const quint64_le &a,
const quint64_le &b) {
return a == b; });
775 compareIndexedElements<QString>(
776 IndexedElements{ [
this](quint32 i) {
return oldUnit->stringAtInternal(i); },
777 oldUnit->stringTableSize },
778 IndexedElements{ [
this](quint32 i) {
return newUnit->stringAtInternal(i); },
779 newUnit->stringTableSize },
780 [](
const QString &a,
const QString &b) {
return a == b; });
782 compareIndexedElements<Lookup>(
783 IndexedElements{ [
this](quint32 i) {
return oldUnit->lookupTable()[i]; },
784 oldUnit->lookupTableSize },
785 IndexedElements{ [
this](quint32 i) {
return newUnit->lookupTable()[i]; },
786 newUnit->lookupTableSize },
787 [
this](
const Lookup &a,
const Lookup &b) {
788 return a.type() == b.type() && a.mode() == b.mode()
789 && stringsEqual(a.nameIndex(), b.nameIndex());
792 compareIndexedElements<Import>(
793 IndexedElements{ [oldQml](quint32 i) {
return *oldQml->importAt(i); },
795 IndexedElements{ [newQml](quint32 i) {
return *newQml->importAt(i); },
797 [
this](
const Import &a,
const Import &b) {
798 return a.type == b.type && stringsEqual(a.uriIndex, b.uriIndex)
799 && stringsEqual(a.qualifierIndex, b.qualifierIndex)
800 && a.version == b.version;
803 compareIndexedElements<Function>(IndexedElements{ [
this](quint32 i) ->
const Function & {
804 return *oldUnit->functionAt(i);
806 oldUnit->functionTableSize },
807 IndexedElements{ [
this](quint32 i) ->
const Function & {
808 return *newUnit->functionAt(i);
810 newUnit->functionTableSize },
811 [
this](
const Function &a,
const Function &b) {
812 return functionContentEqual(a, b);
815 compareIndexedElements<TranslationData>(
816 IndexedElements{ [
this](quint32 i) {
return oldUnit->translations()[i]; },
817 oldUnit->translationTableSize },
818 IndexedElements{ [
this](quint32 i) {
return newUnit->translations()[i]; },
819 newUnit->translationTableSize },
820 [
this](
const TranslationData &a,
const TranslationData &b) {
821 return translationContentEqual(a, b);
824 compareIndexedElements<RegExp>(
826 [
this](quint32 i) ->
const RegExp & {
return *oldUnit->regexpAt(i); },
827 oldUnit->regexpTableSize },
829 [
this](quint32 i) ->
const RegExp & {
return *newUnit->regexpAt(i); },
830 newUnit->regexpTableSize },
831 [
this](
const RegExp &a,
const RegExp &b) {
832 return a.flags() == b.flags() && stringsEqual(a.stringIndex(), b.stringIndex());
835 compareIndexedElements<Class>(
837 [
this](quint32 i) ->
const Class & {
return *oldUnit->classAt(i); },
838 oldUnit->classTableSize },
840 [
this](quint32 i) ->
const Class & {
return *newUnit->classAt(i); },
841 newUnit->classTableSize },
842 [
this](
const Class &a,
const Class &b) {
return classContentEqual(a, b); });
844 compareIndexedElements<TemplateObject>(
845 IndexedElements{ [
this](quint32 i) ->
const TemplateObject & {
846 return *oldUnit->templateObjectAt(i);
848 oldUnit->templateObjectTableSize },
849 IndexedElements{ [
this](quint32 i) ->
const TemplateObject & {
850 return *newUnit->templateObjectAt(i);
852 newUnit->templateObjectTableSize },
853 [
this](
const TemplateObject &a,
const TemplateObject &b) {
854 return templateObjectContentEqual(a, b);
858 auto jsClassFromUnit = [](
const Unit *unit, quint32 idx) ->
const JSClass & {
859 const quint32_le *offsetTable =
reinterpret_cast<
const quint32_le *>(
860 reinterpret_cast<
const char *>(unit) + unit->offsetToJSClassTable);
861 return *
reinterpret_cast<
const JSClass *>(
reinterpret_cast<
const char *>(unit)
864 compareIndexedElements<JSClass>(
865 IndexedElements{ [
this, jsClassFromUnit](quint32 i) ->
const JSClass & {
866 return jsClassFromUnit(oldUnit, i);
868 oldUnit->jsClassTableSize },
869 IndexedElements{ [
this, jsClassFromUnit](quint32 i) ->
const JSClass & {
870 return jsClassFromUnit(newUnit, i);
872 newUnit->jsClassTableSize },
873 [
this](
const JSClass &a,
const JSClass &b) {
874 return jsClassContentEqual(a, b);
878 compareIndexedElements<Block>(
880 [
this](quint32 i) ->
const Block & {
return *oldUnit->blockAt(i); },
881 oldUnit->blockTableSize },
883 [
this](quint32 i) ->
const Block & {
return *newUnit->blockAt(i); },
884 newUnit->blockTableSize },
885 [
this](
const Block &a,
const Block &b) {
return blockContentEqual(a, b); });
887 return CompilationUnitDiff{ std::move(changes),
true };