Move DOM delta comparison to its own file, enhance inverting moves
Signed-off-by: Nicholas Van Sickle <nvsickle@amazon.com>
This commit is contained in:
@@ -0,0 +1,178 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzCore/DOM/DomComparison.h>
|
||||
#include <AzCore/std/containers/queue.h>
|
||||
#include <AzCore/std/containers/unordered_set.h>
|
||||
|
||||
namespace AZ::Dom
|
||||
{
|
||||
PatchUndoRedoInfo GenerateHierarchicalDeltaPatch(
|
||||
const Value& beforeState, const Value& afterState, const DeltaPatchGenerationParameters& params)
|
||||
{
|
||||
PatchUndoRedoInfo patches;
|
||||
|
||||
auto AddPatch = [&patches](PatchOperation op, PatchOperation inverse)
|
||||
{
|
||||
patches.m_forwardPatches.PushBack(AZStd::move(op));
|
||||
patches.m_inversePatches.PushFront(AZStd::move(inverse));
|
||||
};
|
||||
|
||||
AZStd::function<void(const Path&, const Value&, const Value&)> compareValues;
|
||||
|
||||
struct PendingComparison
|
||||
{
|
||||
Path m_path;
|
||||
const Value& m_before;
|
||||
const Value& m_after;
|
||||
|
||||
PendingComparison(Path path, const Value& before, const Value& after)
|
||||
: m_path(AZStd::move(path))
|
||||
, m_before(before)
|
||||
, m_after(after)
|
||||
{
|
||||
}
|
||||
};
|
||||
AZStd::queue<PendingComparison> entriesToCompare;
|
||||
|
||||
AZStd::unordered_set<AZ::Name::Hash> desiredKeys;
|
||||
auto compareObjects = [&](const Path& path, const Value& before, const Value& after)
|
||||
{
|
||||
desiredKeys.clear();
|
||||
Path subPath = path;
|
||||
for (auto it = after.MemberBegin(); it != after.MemberEnd(); ++it)
|
||||
{
|
||||
desiredKeys.insert(it->first.GetHash());
|
||||
subPath.Push(it->first);
|
||||
auto beforeIt = before.FindMember(it->first);
|
||||
if (beforeIt == before.MemberEnd())
|
||||
{
|
||||
AddPatch(PatchOperation::AddOperation(subPath, it->second), PatchOperation::RemoveOperation(subPath));
|
||||
}
|
||||
else
|
||||
{
|
||||
entriesToCompare.emplace(subPath, beforeIt->second, it->second);
|
||||
}
|
||||
subPath.Pop();
|
||||
}
|
||||
|
||||
for (auto it = before.MemberBegin(); it != before.MemberEnd(); ++it)
|
||||
{
|
||||
if (!desiredKeys.contains(it->first.GetHash()))
|
||||
{
|
||||
subPath.Push(it->first);
|
||||
AddPatch(PatchOperation::RemoveOperation(subPath), PatchOperation::AddOperation(subPath, it->second));
|
||||
subPath.Pop();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
auto compareArrays = [&](const Path& path, const Value& before, const Value& after)
|
||||
{
|
||||
const size_t beforeSize = before.ArraySize();
|
||||
const size_t afterSize = after.ArraySize();
|
||||
|
||||
// If more than replaceThreshold values differ, do a replace operation instead
|
||||
if (params.m_replaceThreshold != DeltaPatchGenerationParameters::NoReplace)
|
||||
{
|
||||
size_t changedValueCount = 0;
|
||||
const size_t entriesToEnumerate = AZStd::min(beforeSize, afterSize);
|
||||
for (size_t i = 0; i < entriesToEnumerate; ++i)
|
||||
{
|
||||
if (before[i] != after[i])
|
||||
{
|
||||
++changedValueCount;
|
||||
if (changedValueCount >= params.m_replaceThreshold)
|
||||
{
|
||||
AddPatch(PatchOperation::ReplaceOperation(path, after), PatchOperation::ReplaceOperation(path, before));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Path subPath = path;
|
||||
for (size_t i = 0; i < afterSize; ++i)
|
||||
{
|
||||
if (i >= beforeSize)
|
||||
{
|
||||
subPath.Push(PathEntry(PathEntry::EndOfArrayIndex));
|
||||
AddPatch(PatchOperation::AddOperation(subPath, after[i]), PatchOperation::RemoveOperation(subPath));
|
||||
subPath.Pop();
|
||||
}
|
||||
else
|
||||
{
|
||||
subPath.Push(PathEntry(i));
|
||||
entriesToCompare.emplace(subPath, before[i], after[i]);
|
||||
subPath.Pop();
|
||||
}
|
||||
}
|
||||
|
||||
if (beforeSize > afterSize)
|
||||
{
|
||||
subPath.Push(PathEntry(PathEntry::EndOfArrayIndex));
|
||||
for (size_t i = beforeSize; i > afterSize; --i)
|
||||
{
|
||||
AddPatch(PatchOperation::RemoveOperation(subPath), PatchOperation::AddOperation(subPath, before[i - 1]));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
auto compareNodes = [&](const Path& path, const Value& before, const Value& after)
|
||||
{
|
||||
if (before.GetNodeName() != after.GetNodeName())
|
||||
{
|
||||
AddPatch(PatchOperation::ReplaceOperation(path, after), PatchOperation::ReplaceOperation(path, before));
|
||||
}
|
||||
else
|
||||
{
|
||||
compareObjects(path, before, after);
|
||||
compareArrays(path, before, after);
|
||||
}
|
||||
};
|
||||
|
||||
compareValues = [&](const Path& path, const Value& before, const Value& after)
|
||||
{
|
||||
if (before.GetType() != after.GetType())
|
||||
{
|
||||
AddPatch(PatchOperation::ReplaceOperation(path, after), PatchOperation::ReplaceOperation(path, before));
|
||||
}
|
||||
else if (before == after)
|
||||
{
|
||||
// If a shallow comparison succeeds we're pointing to an identical value or container
|
||||
// and don't need to drill down.
|
||||
return;
|
||||
}
|
||||
else if (before.IsObject())
|
||||
{
|
||||
compareObjects(path, before, after);
|
||||
}
|
||||
else if (before.IsArray())
|
||||
{
|
||||
compareArrays(path, before, after);
|
||||
}
|
||||
else if (before.IsNode())
|
||||
{
|
||||
compareNodes(path, before, after);
|
||||
}
|
||||
else
|
||||
{
|
||||
AddPatch(PatchOperation::ReplaceOperation(path, after), PatchOperation::ReplaceOperation(path, before));
|
||||
}
|
||||
};
|
||||
|
||||
entriesToCompare.emplace(Path(), beforeState, afterState);
|
||||
while (!entriesToCompare.empty())
|
||||
{
|
||||
PendingComparison& comparison = entriesToCompare.front();
|
||||
compareValues(comparison.m_path, comparison.m_before, comparison.m_after);
|
||||
entriesToCompare.pop();
|
||||
}
|
||||
return patches;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/DOM/DomPatch.h>
|
||||
|
||||
namespace AZ::Dom
|
||||
{
|
||||
//! A set of patches for applying a change and doing the inverse operation.
|
||||
struct PatchUndoRedoInfo
|
||||
{
|
||||
Patch m_forwardPatches;
|
||||
Patch m_inversePatches;
|
||||
};
|
||||
|
||||
//! Parameters for GenerateHierarchicalDeltaPatch.
|
||||
struct DeltaPatchGenerationParameters
|
||||
{
|
||||
static constexpr size_t NoReplace = AZStd::numeric_limits<size_t>::max();
|
||||
static constexpr size_t AlwaysFullReplace = 0;
|
||||
|
||||
//! The threshold of changed values in a node or array which, if exceeded, will cause the generation to create an
|
||||
//! entire "replace" oepration instead. If set to NoReplace, no replacement will occur.
|
||||
size_t m_replaceThreshold = 3;
|
||||
};
|
||||
|
||||
//! Generates a set of patches such that m_forwardPatches.Apply(beforeState) shall produce a document equivalent to afterState, and
|
||||
//! a subsequent m_inversePatches.Apply(beforeState) shall produce the original document. This patch generation strategy does a
|
||||
//! hierarchical comparison and is not guaranteed to create the minimal set of patches required to transform between the two states.
|
||||
PatchUndoRedoInfo GenerateHierarchicalDeltaPatch(const Value& beforeState, const Value& afterState, const DeltaPatchGenerationParameters& params = {});
|
||||
} // namespace AZ::Dom
|
||||
@@ -8,8 +8,6 @@
|
||||
|
||||
#include <AzCore/DOM/DomPatch.h>
|
||||
#include <AzCore/DOM/DomUtils.h>
|
||||
#include <AzCore/std/containers/queue.h>
|
||||
#include <AzCore/std/containers/unordered_set.h>
|
||||
|
||||
namespace AZ::Dom
|
||||
{
|
||||
@@ -297,7 +295,7 @@ namespace AZ::Dom
|
||||
}
|
||||
}
|
||||
|
||||
AZ::Outcome<PatchOperation, AZStd::string> PatchOperation::GetInverse(Value stateBeforeApplication) const
|
||||
AZ::Outcome<AZStd::fixed_vector<PatchOperation, 2>, AZStd::string> PatchOperation::GetInverse(Value stateBeforeApplication) const
|
||||
{
|
||||
switch (m_type)
|
||||
{
|
||||
@@ -310,10 +308,10 @@ namespace AZ::Dom
|
||||
const Value* existingValue = stateBeforeApplication.FindChild(m_domPath);
|
||||
if (existingValue != nullptr)
|
||||
{
|
||||
return AZ::Success(PatchOperation::ReplaceOperation(m_domPath, *existingValue));
|
||||
return AZ::Success<InversePatches>({PatchOperation::ReplaceOperation(m_domPath, *existingValue)});
|
||||
}
|
||||
}
|
||||
return AZ::Success(PatchOperation::RemoveOperation(m_domPath));
|
||||
return AZ::Success<InversePatches>({PatchOperation::RemoveOperation(m_domPath)});
|
||||
}
|
||||
case Type::Remove:
|
||||
{
|
||||
@@ -325,7 +323,7 @@ namespace AZ::Dom
|
||||
m_domPath.AppendToString(errorMessage);
|
||||
return AZ::Failure(AZStd::move(errorMessage));
|
||||
}
|
||||
return AZ::Success(PatchOperation::AddOperation(m_domPath, *existingValue));
|
||||
return AZ::Success<InversePatches>({PatchOperation::AddOperation(m_domPath, *existingValue)});
|
||||
}
|
||||
case Type::Replace:
|
||||
{
|
||||
@@ -337,7 +335,7 @@ namespace AZ::Dom
|
||||
m_domPath.AppendToString(errorMessage);
|
||||
return AZ::Failure(AZStd::move(errorMessage));
|
||||
}
|
||||
return AZ::Success(PatchOperation::ReplaceOperation(m_domPath, *existingValue));
|
||||
return AZ::Success<InversePatches>({PatchOperation::ReplaceOperation(m_domPath, *existingValue)});
|
||||
}
|
||||
case Type::Copy:
|
||||
{
|
||||
@@ -349,40 +347,37 @@ namespace AZ::Dom
|
||||
m_domPath.AppendToString(errorMessage);
|
||||
return AZ::Failure(AZStd::move(errorMessage));
|
||||
}
|
||||
return AZ::Success(PatchOperation::ReplaceOperation(m_domPath, *existingValue));
|
||||
return AZ::Success<InversePatches>({PatchOperation::ReplaceOperation(m_domPath, *existingValue)});
|
||||
}
|
||||
case Type::Move:
|
||||
{
|
||||
// Move -> Replace, using the common ancestor of the two paths as the replacement
|
||||
// This is not a minimal inverse, which would be two replace operations at each path
|
||||
const Path& destPath = m_domPath;
|
||||
const Path& sourcePath = GetSourcePath();
|
||||
|
||||
Path commonAncestor;
|
||||
for (size_t i = 0; i < destPath.Size() && i < sourcePath.Size(); ++i)
|
||||
const Value* sourceValue = stateBeforeApplication.FindChild(GetSourcePath());
|
||||
if (sourceValue == nullptr)
|
||||
{
|
||||
if (destPath[i] != sourcePath[i])
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
commonAncestor.Push(destPath[i]);
|
||||
}
|
||||
|
||||
const Value* existingValue = stateBeforeApplication.FindChild(commonAncestor);
|
||||
if (existingValue == nullptr)
|
||||
{
|
||||
AZStd::string errorMessage = "Unable to invert DOM copy patch, common ancestor path not found: ";
|
||||
commonAncestor.AppendToString(errorMessage);
|
||||
AZStd::string errorMessage = "Unable to invert DOM copy patch, source path not found: ";
|
||||
m_domPath.AppendToString(errorMessage);
|
||||
return AZ::Failure(AZStd::move(errorMessage));
|
||||
}
|
||||
return AZ::Success(PatchOperation::ReplaceOperation(commonAncestor, *existingValue));
|
||||
|
||||
// If there was a value at the destination path, invert with an add / replace
|
||||
const Value* destinationValue = stateBeforeApplication.FindChild(GetDestinationPath());
|
||||
if (destinationValue != nullptr)
|
||||
{
|
||||
InversePatches result({PatchOperation::AddOperation(GetSourcePath(), *sourceValue)});
|
||||
result.push_back(PatchOperation::ReplaceOperation(GetDestinationPath(), *destinationValue));
|
||||
return AZ::Success<InversePatches>({
|
||||
PatchOperation::AddOperation(GetSourcePath(), *sourceValue),
|
||||
PatchOperation::ReplaceOperation(GetDestinationPath(), *destinationValue),
|
||||
});
|
||||
}
|
||||
// Otherwise, just do a move
|
||||
return AZ::Success<InversePatches>({PatchOperation::MoveOperation(GetDestinationPath(), GetSourcePath())});
|
||||
}
|
||||
case Type::Test:
|
||||
{
|
||||
// Test -> Test (no change)
|
||||
// When inverting a sequence of patches, applying them in reverse order should allow the test to continue to succeed
|
||||
return AZ::Success(*this);
|
||||
return AZ::Success<InversePatches>({*this});
|
||||
}
|
||||
}
|
||||
return AZ::Failure<AZStd::string>("Unable to invert DOM patch, unknown type specified");
|
||||
@@ -801,168 +796,4 @@ namespace AZ::Dom
|
||||
{
|
||||
return PatchOperation(AZStd::move(testPath), PatchOperation::Type::Test, AZStd::move(value));
|
||||
}
|
||||
|
||||
PatchInfo GenerateHierarchicalDeltaPatch(
|
||||
const Value& beforeState, const Value& afterState, const DeltaPatchGenerationParameters& params)
|
||||
{
|
||||
PatchInfo patches;
|
||||
|
||||
auto AddPatch = [&patches](PatchOperation op, PatchOperation inverse)
|
||||
{
|
||||
patches.m_forwardPatches.PushBack(AZStd::move(op));
|
||||
patches.m_inversePatches.PushFront(AZStd::move(inverse));
|
||||
};
|
||||
|
||||
AZStd::function<void(const Path&, const Value&, const Value&)> compareValues;
|
||||
|
||||
struct PendingComparison
|
||||
{
|
||||
Path m_path;
|
||||
const Value& m_before;
|
||||
const Value& m_after;
|
||||
|
||||
PendingComparison(Path path, const Value& before, const Value& after)
|
||||
: m_path(AZStd::move(path))
|
||||
, m_before(before)
|
||||
, m_after(after)
|
||||
{
|
||||
}
|
||||
};
|
||||
AZStd::queue<PendingComparison> entriesToCompare;
|
||||
|
||||
AZStd::unordered_set<AZ::Name::Hash> desiredKeys;
|
||||
auto compareObjects = [&](const Path& path, const Value& before, const Value& after)
|
||||
{
|
||||
desiredKeys.clear();
|
||||
Path subPath = path;
|
||||
for (auto it = after.MemberBegin(); it != after.MemberEnd(); ++it)
|
||||
{
|
||||
desiredKeys.insert(it->first.GetHash());
|
||||
subPath.Push(it->first);
|
||||
auto beforeIt = before.FindMember(it->first);
|
||||
if (beforeIt == before.MemberEnd())
|
||||
{
|
||||
AddPatch(PatchOperation::AddOperation(subPath, it->second), PatchOperation::RemoveOperation(subPath));
|
||||
}
|
||||
else
|
||||
{
|
||||
entriesToCompare.emplace(subPath, beforeIt->second, it->second);
|
||||
}
|
||||
subPath.Pop();
|
||||
}
|
||||
|
||||
for (auto it = before.MemberBegin(); it != before.MemberEnd(); ++it)
|
||||
{
|
||||
if (!desiredKeys.contains(it->first.GetHash()))
|
||||
{
|
||||
subPath.Push(it->first);
|
||||
AddPatch(PatchOperation::RemoveOperation(subPath), PatchOperation::AddOperation(subPath, it->second));
|
||||
subPath.Pop();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
auto compareArrays = [&](const Path& path, const Value& before, const Value& after)
|
||||
{
|
||||
const size_t beforeSize = before.ArraySize();
|
||||
const size_t afterSize = after.ArraySize();
|
||||
|
||||
// If more than replaceThreshold values differ, do a replace operation instead
|
||||
if (params.m_replaceThreshold != DeltaPatchGenerationParameters::NoReplace)
|
||||
{
|
||||
size_t changedValueCount = 0;
|
||||
const size_t entriesToEnumerate = AZStd::min(beforeSize, afterSize);
|
||||
for (size_t i = 0; i < entriesToEnumerate; ++i)
|
||||
{
|
||||
if (before[i] != after[i])
|
||||
{
|
||||
++changedValueCount;
|
||||
if (changedValueCount >= params.m_replaceThreshold)
|
||||
{
|
||||
AddPatch(PatchOperation::ReplaceOperation(path, after), PatchOperation::ReplaceOperation(path, before));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Path subPath = path;
|
||||
for (size_t i = 0; i < afterSize; ++i)
|
||||
{
|
||||
if (i >= beforeSize)
|
||||
{
|
||||
subPath.Push(PathEntry(PathEntry::EndOfArrayIndex));
|
||||
AddPatch(PatchOperation::AddOperation(subPath, after[i]), PatchOperation::RemoveOperation(subPath));
|
||||
subPath.Pop();
|
||||
}
|
||||
else
|
||||
{
|
||||
subPath.Push(PathEntry(i));
|
||||
entriesToCompare.emplace(subPath, before[i], after[i]);
|
||||
subPath.Pop();
|
||||
}
|
||||
}
|
||||
|
||||
if (beforeSize > afterSize)
|
||||
{
|
||||
subPath.Push(PathEntry(PathEntry::EndOfArrayIndex));
|
||||
for (size_t i = beforeSize; i > afterSize; --i)
|
||||
{
|
||||
AddPatch(PatchOperation::RemoveOperation(subPath), PatchOperation::AddOperation(subPath, before[i - 1]));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
auto compareNodes = [&](const Path& path, const Value& before, const Value& after)
|
||||
{
|
||||
if (before.GetNodeName() != after.GetNodeName())
|
||||
{
|
||||
AddPatch(PatchOperation::ReplaceOperation(path, after), PatchOperation::ReplaceOperation(path, before));
|
||||
}
|
||||
else
|
||||
{
|
||||
compareObjects(path, before, after);
|
||||
compareArrays(path, before, after);
|
||||
}
|
||||
};
|
||||
|
||||
compareValues = [&](const Path& path, const Value& before, const Value& after)
|
||||
{
|
||||
if (before.GetType() != after.GetType())
|
||||
{
|
||||
AddPatch(PatchOperation::ReplaceOperation(path, after), PatchOperation::ReplaceOperation(path, before));
|
||||
}
|
||||
else if (before == after)
|
||||
{
|
||||
// If a shallow comparison succeeds we're pointing to an identical value or container
|
||||
// and don't need to drill down.
|
||||
return;
|
||||
}
|
||||
else if (before.IsObject())
|
||||
{
|
||||
compareObjects(path, before, after);
|
||||
}
|
||||
else if (before.IsArray())
|
||||
{
|
||||
compareArrays(path, before, after);
|
||||
}
|
||||
else if (before.IsNode())
|
||||
{
|
||||
compareNodes(path, before, after);
|
||||
}
|
||||
else
|
||||
{
|
||||
AddPatch(PatchOperation::ReplaceOperation(path, after), PatchOperation::ReplaceOperation(path, before));
|
||||
}
|
||||
};
|
||||
|
||||
entriesToCompare.emplace(Path(), beforeState, afterState);
|
||||
while (!entriesToCompare.empty())
|
||||
{
|
||||
PendingComparison& comparison = entriesToCompare.front();
|
||||
compareValues(comparison.m_path, comparison.m_before, comparison.m_after);
|
||||
entriesToCompare.pop();
|
||||
}
|
||||
return patches;
|
||||
}
|
||||
} // namespace AZ::Dom
|
||||
|
||||
@@ -71,7 +71,8 @@ namespace AZ::Dom
|
||||
Value GetDomRepresentation() const;
|
||||
static AZ::Outcome<PatchOperation, AZStd::string> CreateFromDomRepresentation(Value domValue);
|
||||
|
||||
AZ::Outcome<PatchOperation, AZStd::string> GetInverse(Value stateBeforeApplication) const;
|
||||
using InversePatches = AZStd::fixed_vector<PatchOperation, 2>;
|
||||
AZ::Outcome<AZStd::fixed_vector<PatchOperation, 2>, AZStd::string> GetInverse(Value stateBeforeApplication) const;
|
||||
|
||||
enum class ExistenceCheckFlags : AZ::u8
|
||||
{
|
||||
@@ -182,27 +183,4 @@ namespace AZ::Dom
|
||||
private:
|
||||
OperationsContainer m_operations;
|
||||
};
|
||||
|
||||
//! A set of patches for applying a change and doing the inverse operation (i.e. undoing it).
|
||||
struct PatchInfo
|
||||
{
|
||||
Patch m_forwardPatches;
|
||||
Patch m_inversePatches;
|
||||
};
|
||||
|
||||
//! Parameters for GenerateHierarchicalDeltaPatch.
|
||||
struct DeltaPatchGenerationParameters
|
||||
{
|
||||
static constexpr size_t NoReplace = AZStd::numeric_limits<size_t>::max();
|
||||
static constexpr size_t AlwaysFullReplace = 0;
|
||||
|
||||
//! The threshold of changed values in a node or array which, if exceeded, will cause the generation to create an
|
||||
//! entire "replace" oepration instead. If set to NoReplace, no replacement will occur.
|
||||
size_t m_replaceThreshold = 3;
|
||||
};
|
||||
|
||||
//! Generates a set of patches such that m_forwardPatches.Apply(beforeState) shall produce a document equivalent to afterState, and
|
||||
//! a subsequent m_inversePatches.Apply(beforeState) shall produce the original document. This patch generation strategy does a
|
||||
//! hierarchical comparison and is not guaranteed to create the minimal set of patches required to transform between the two states.
|
||||
PatchInfo GenerateHierarchicalDeltaPatch(const Value& beforeState, const Value& afterState, const DeltaPatchGenerationParameters& params = {});
|
||||
} // namespace AZ::Dom
|
||||
|
||||
@@ -128,6 +128,8 @@ set(FILES
|
||||
DOM/DomValueWriter.h
|
||||
DOM/DomVisitor.cpp
|
||||
DOM/DomVisitor.h
|
||||
DOM/DomComparison.cpp
|
||||
DOM/DomComparison.h
|
||||
DOM/Backends/JSON/JsonBackend.h
|
||||
DOM/Backends/JSON/JsonSerializationUtils.cpp
|
||||
DOM/Backends/JSON/JsonSerializationUtils.h
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
*/
|
||||
|
||||
#include <AzCore/DOM/DomPatch.h>
|
||||
#include <AzCore/DOM/DomComparison.h>
|
||||
#include <Tests/DOM/DomFixtures.h>
|
||||
|
||||
namespace AZ::Dom::Tests
|
||||
@@ -45,9 +46,9 @@ namespace AZ::Dom::Tests
|
||||
DomTestFixture::TearDown();
|
||||
}
|
||||
|
||||
PatchInfo GenerateAndVerifyDelta()
|
||||
PatchUndoRedoInfo GenerateAndVerifyDelta()
|
||||
{
|
||||
PatchInfo info = GenerateHierarchicalDeltaPatch(m_dataset, m_deltaDataset);
|
||||
PatchUndoRedoInfo info = GenerateHierarchicalDeltaPatch(m_dataset, m_deltaDataset);
|
||||
|
||||
auto result = info.m_forwardPatches.Apply(m_dataset);
|
||||
EXPECT_TRUE(result.IsSuccess());
|
||||
|
||||
Reference in New Issue
Block a user