433 static_assert(
sizeof(Binding) == 24,
"Update bindingContentEqual when Binding layout changes");
434 static_assert(
sizeof(TranslationData) == 16,
"Update bindingContentEqual when TranslationData layout changes");
435 if (oldBinding.type() != newBinding.type() || oldBinding.flags() != newBinding.flags())
438 if (!stringsEqual(oldBinding.propertyNameIndex, newBinding.propertyNameIndex))
441 switch (oldBinding.type()) {
442 case Binding::Type_Invalid:
444 case Binding::Type_Boolean:
445 return oldBinding.valueAsBoolean() == newBinding.valueAsBoolean();
446 case Binding::Type_Number: {
447 const uint oldIdx = oldBinding.value.constantValueIndex;
448 const uint newIdx = newBinding.value.constantValueIndex;
449 Q_ASSERT(oldIdx < oldUnit->constantTableSize);
450 Q_ASSERT(newIdx < newUnit->constantTableSize);
451 return oldIdx == newIdx && oldUnit->constants()[oldIdx] == newUnit->constants()[newIdx];
453 case Binding::Type_String:
454 return stringsEqual(oldBinding.stringIndex, newBinding.stringIndex);
455 case Binding::Type_Null:
457 case Binding::Type_Translation:
458 case Binding::Type_TranslationById: {
459 const auto &oldTrans = oldUnit->translations()[oldBinding.value.translationDataIndex];
460 const auto &newTrans = newUnit->translations()[newBinding.value.translationDataIndex];
464 const bool oldHasCtx = oldTrans.contextIndex != TranslationData::NoContextIndex;
465 const bool newHasCtx = newTrans.contextIndex != TranslationData::NoContextIndex;
467 if (oldHasCtx != newHasCtx)
470 if (oldHasCtx && !stringsEqual(oldTrans.contextIndex, newTrans.contextIndex))
473 return stringsEqual(oldBinding.stringIndex, newBinding.stringIndex)
474 && stringsEqual(oldTrans.stringIndex, newTrans.stringIndex)
475 && stringsEqual(oldTrans.commentIndex, newTrans.commentIndex)
476 && oldTrans.number == newTrans.number;
478 case Binding::Type_Script:
479 return oldBinding.value.compiledScriptIndex == newBinding.value.compiledScriptIndex;
480 case Binding::Type_Object:
481 case Binding::Type_AttachedProperty:
482 case Binding::Type_GroupedProperty:
483 return oldBinding.value.objectIndex == newBinding.value.objectIndex
484 && objectContentEqual(
485 *oldUnit->qmlUnit()->objectAt(oldBinding.value.objectIndex),
486 *newUnit->qmlUnit()->objectAt(newBinding.value.objectIndex));
711 const QmlUnit *oldQml = oldUnit->qmlUnit();
712 const QmlUnit *newQml = newUnit->qmlUnit();
714 if (!oldQml || !newQml)
721 change.data = extractData(*newUnit);
722 changes.append(change);
725 compareIndexedElements<Object>(
727 [oldQml](quint32 i) ->
const Object & {
return *oldQml->objectAt(i); },
730 [newQml](quint32 i) ->
const Object & {
return *newQml->objectAt(i); },
732 [
this](
const Object &a,
const Object &b) {
return objectContentEqual(a, b); });
735 const quint32 commonCount = std::min(oldQml->nObjects, newQml->nObjects);
736 for (quint32 objectIndex = 0; objectIndex < commonCount; ++objectIndex) {
738 const Object *oldObj = oldQml->objectAt(objectIndex);
739 const Object *newObj = newQml->objectAt(objectIndex);
741 compareObjectProperties(oldObj, newObj);
742 compareObjectAliases(oldObj, newObj);
743 compareObjectEnums(oldObj, newObj);
744 compareObjectSignals(oldObj, newObj);
745 compareObjectInlineComponents(oldObj, newObj);
746 compareObjectRequiredPropertyExtraData(oldObj, newObj);
747 compareObjectBindings(oldObj, newObj);
750 compareIndexedElements<quint64_le>(
751 IndexedElements{ [
this](quint32 i) {
return oldUnit->constants()[i]; },
752 oldUnit->constantTableSize },
753 IndexedElements{ [
this](quint32 i) {
return newUnit->constants()[i]; },
754 newUnit->constantTableSize },
755 [](
const quint64_le &a,
const quint64_le &b) {
return a == b; });
757 compareIndexedElements<QString>(
758 IndexedElements{ [
this](quint32 i) {
return oldUnit->stringAtInternal(i); },
759 oldUnit->stringTableSize },
760 IndexedElements{ [
this](quint32 i) {
return newUnit->stringAtInternal(i); },
761 newUnit->stringTableSize },
762 [](
const QString &a,
const QString &b) {
return a == b; });
764 compareIndexedElements<Lookup>(
765 IndexedElements{ [
this](quint32 i) {
return oldUnit->lookupTable()[i]; },
766 oldUnit->lookupTableSize },
767 IndexedElements{ [
this](quint32 i) {
return newUnit->lookupTable()[i]; },
768 newUnit->lookupTableSize },
769 [
this](
const Lookup &a,
const Lookup &b) {
770 return a.type() == b.type() && a.mode() == b.mode()
771 && stringsEqual(a.nameIndex(), b.nameIndex());
774 compareIndexedElements<Import>(
775 IndexedElements{ [oldQml](quint32 i) {
return *oldQml->importAt(i); },
777 IndexedElements{ [newQml](quint32 i) {
return *newQml->importAt(i); },
779 [
this](
const Import &a,
const Import &b) {
780 return a.type == b.type && stringsEqual(a.uriIndex, b.uriIndex)
781 && stringsEqual(a.qualifierIndex, b.qualifierIndex)
782 && a.version == b.version;
785 compareIndexedElements<Function>(IndexedElements{ [
this](quint32 i) ->
const Function & {
786 return *oldUnit->functionAt(i);
788 oldUnit->functionTableSize },
789 IndexedElements{ [
this](quint32 i) ->
const Function & {
790 return *newUnit->functionAt(i);
792 newUnit->functionTableSize },
793 [
this](
const Function &a,
const Function &b) {
794 return functionContentEqual(a, b);
797 compareIndexedElements<TranslationData>(
798 IndexedElements{ [
this](quint32 i) {
return oldUnit->translations()[i]; },
799 oldUnit->translationTableSize },
800 IndexedElements{ [
this](quint32 i) {
return newUnit->translations()[i]; },
801 newUnit->translationTableSize },
802 [
this](
const TranslationData &a,
const TranslationData &b) {
803 return translationContentEqual(a, b);
806 compareIndexedElements<RegExp>(
808 [
this](quint32 i) ->
const RegExp & {
return *oldUnit->regexpAt(i); },
809 oldUnit->regexpTableSize },
811 [
this](quint32 i) ->
const RegExp & {
return *newUnit->regexpAt(i); },
812 newUnit->regexpTableSize },
813 [
this](
const RegExp &a,
const RegExp &b) {
814 return a.flags() == b.flags() && stringsEqual(a.stringIndex(), b.stringIndex());
817 compareIndexedElements<Class>(
819 [
this](quint32 i) ->
const Class & {
return *oldUnit->classAt(i); },
820 oldUnit->classTableSize },
822 [
this](quint32 i) ->
const Class & {
return *newUnit->classAt(i); },
823 newUnit->classTableSize },
824 [
this](
const Class &a,
const Class &b) {
return classContentEqual(a, b); });
826 compareIndexedElements<TemplateObject>(
827 IndexedElements{ [
this](quint32 i) ->
const TemplateObject & {
828 return *oldUnit->templateObjectAt(i);
830 oldUnit->templateObjectTableSize },
831 IndexedElements{ [
this](quint32 i) ->
const TemplateObject & {
832 return *newUnit->templateObjectAt(i);
834 newUnit->templateObjectTableSize },
835 [
this](
const TemplateObject &a,
const TemplateObject &b) {
836 return templateObjectContentEqual(a, b);
840 auto jsClassFromUnit = [](
const Unit *unit, quint32 idx) ->
const JSClass & {
841 const quint32_le *offsetTable =
reinterpret_cast<
const quint32_le *>(
842 reinterpret_cast<
const char *>(unit) + unit->offsetToJSClassTable);
843 return *
reinterpret_cast<
const JSClass *>(
reinterpret_cast<
const char *>(unit)
846 compareIndexedElements<JSClass>(
847 IndexedElements{ [
this, jsClassFromUnit](quint32 i) ->
const JSClass & {
848 return jsClassFromUnit(oldUnit, i);
850 oldUnit->jsClassTableSize },
851 IndexedElements{ [
this, jsClassFromUnit](quint32 i) ->
const JSClass & {
852 return jsClassFromUnit(newUnit, i);
854 newUnit->jsClassTableSize },
855 [
this](
const JSClass &a,
const JSClass &b) {
856 return jsClassContentEqual(a, b);
860 compareIndexedElements<Block>(
862 [
this](quint32 i) ->
const Block & {
return *oldUnit->blockAt(i); },
863 oldUnit->blockTableSize },
865 [
this](quint32 i) ->
const Block & {
return *newUnit->blockAt(i); },
866 newUnit->blockTableSize },
867 [
this](
const Block &a,
const Block &b) {
return blockContentEqual(a, b); });
869 return CompilationUnitDiff{ std::move(changes),
true };