mirror of
https://github.com/rojo-rbx/rojo.git
synced 2026-04-21 13:15:50 +00:00
Break apart plugin reconciler (#332)
* Start splitting apart reconciler, with tests * Reify children in reify * Baseline hydrate implementation * Remove debug print * Scaffold out diff implementation, just supporting name changes * invariant -> error in decodeValue * Flesh out diff and add getProperty * Clear out top-level reconciler interface, start updating code that touches it * Address review feedback * Add (experimental) Selene configuration * Add emptiness checks to PatchSet, remove unimplement invert method * Improve descendant destruction behavior in InstanceMap * Track instanceId on all reify errors * Base implementation of applyPatch, returning partial patches on failure * Change reify to accept InstanceMap and insert instances into it * Start testing applyPatch for removals * Add test for applyPatch adding instances successfully and not * Add , which is just error with formatting * Correctly use new diff and applyPatch APIs * Improve applyPatch logging and fix field name typo * Better debug output when reify fails * Print out unapplied patch in debug mode * Don't write properties if their values are not different. This was exposed trying to sync the Rojo plugin, which has a gigantic ModuleScript in it with the reflection database. This workaround was present in some form in many versions of Rojo, and I guess we still need it. This time, I actually documented why it's here so that I don't forget for the umpteenth time... * Add placeholder test that needs to happen still * Introduce easier plugin testing, write applyPatch properties test * Delete legacy get/setCanonicalProperty files * Fix trying to remove numbers instead of instances * Change applyPatch to return partial patches instead of binary success * Work towards being able to decode and apply refs * Add helpers for PatchSet assertions * Apply refs in reify, test all cases * Improve diagnostics when patches fail to apply * Stop logging when destroying untracked instances, it's ok * Remove read before setting property in applyPatch * Fix diff thinking all properties are changed
This commit is contained in:
committed by
GitHub
parent
50f0a2bd2e
commit
f66860bdfe
@@ -16,10 +16,169 @@ PatchSet.validate = t.interface({
|
||||
})
|
||||
|
||||
--[[
|
||||
Invert the given PatchSet using the given instance map.
|
||||
Create a new, empty PatchSet.
|
||||
]]
|
||||
function PatchSet.invert(patchSet, instanceMap)
|
||||
error("not yet implemented", 2)
|
||||
function PatchSet.newEmpty()
|
||||
return {
|
||||
removed = {},
|
||||
added = {},
|
||||
updated = {},
|
||||
}
|
||||
end
|
||||
|
||||
--[[
|
||||
Tells whether the given PatchSet is empty.
|
||||
]]
|
||||
function PatchSet.isEmpty(patchSet)
|
||||
return next(patchSet.removed) == nil and
|
||||
next(patchSet.added) == nil and
|
||||
next(patchSet.updated) == nil
|
||||
end
|
||||
|
||||
--[[
|
||||
Tells whether the given PatchSet has any remove operations.
|
||||
]]
|
||||
function PatchSet.hasRemoves(patchSet)
|
||||
return next(patchSet.removed) ~= nil
|
||||
end
|
||||
|
||||
--[[
|
||||
Tells whether the given PatchSet has any add operations.
|
||||
]]
|
||||
function PatchSet.hasAdditions(patchSet)
|
||||
return next(patchSet.added) ~= nil
|
||||
end
|
||||
|
||||
--[[
|
||||
Tells whether the given PatchSet has any update operations.
|
||||
]]
|
||||
function PatchSet.hasUpdates(patchSet)
|
||||
return next(patchSet.updated) ~= nil
|
||||
end
|
||||
|
||||
--[[
|
||||
Merge multiple PatchSet objects into the given PatchSet.
|
||||
]]
|
||||
function PatchSet.assign(target, ...)
|
||||
for i = 1, select("#", ...) do
|
||||
local sourcePatch = select(i, ...)
|
||||
|
||||
for _, removed in ipairs(sourcePatch.removed) do
|
||||
table.insert(target.removed, removed)
|
||||
end
|
||||
|
||||
for id, added in pairs(sourcePatch.added) do
|
||||
target.added[id] = added
|
||||
end
|
||||
|
||||
for _, update in ipairs(sourcePatch.updated) do
|
||||
table.insert(target.updated, update)
|
||||
end
|
||||
end
|
||||
|
||||
return target
|
||||
end
|
||||
|
||||
--[[
|
||||
Create a list of human-readable statements summarizing the contents of this
|
||||
patch, intended to be displayed to users.
|
||||
]]
|
||||
function PatchSet.humanSummary(instanceMap, patchSet)
|
||||
local statements = {}
|
||||
|
||||
for _, idOrInstance in ipairs(patchSet.removed) do
|
||||
local instance, id
|
||||
|
||||
if type(idOrInstance) == "string" then
|
||||
id = idOrInstance
|
||||
instance = instanceMap.fromIds[id]
|
||||
else
|
||||
instance = idOrInstance
|
||||
id = instanceMap.fromInstances[instance]
|
||||
end
|
||||
|
||||
if instance ~= nil then
|
||||
table.insert(statements, string.format("- Delete instance %s", instance:GetFullName()))
|
||||
else
|
||||
table.insert(statements, string.format("- Delete instance with ID %s", id))
|
||||
end
|
||||
end
|
||||
|
||||
local additionsMentioned = {}
|
||||
|
||||
local function addAllDescendents(virtualInstance)
|
||||
additionsMentioned[virtualInstance.Id] = true
|
||||
|
||||
for _, childId in ipairs(virtualInstance.Children) do
|
||||
addAllDescendents(patchSet.added[childId])
|
||||
end
|
||||
end
|
||||
|
||||
for id, addition in pairs(patchSet.added) do
|
||||
if additionsMentioned[id] then
|
||||
continue
|
||||
end
|
||||
|
||||
local virtualInstance = addition
|
||||
while true do
|
||||
if virtualInstance.Parent == nil then
|
||||
break
|
||||
end
|
||||
|
||||
local virtualParent = patchSet.added[virtualInstance.Parent]
|
||||
if virtualParent == nil then
|
||||
break
|
||||
end
|
||||
|
||||
virtualInstance = virtualParent
|
||||
end
|
||||
|
||||
local parentDisplayName = "nil (how strange!)"
|
||||
if virtualInstance.Parent ~= nil then
|
||||
local parent = instanceMap.fromIds[virtualInstance.Parent]
|
||||
if parent ~= nil then
|
||||
parentDisplayName = parent:GetFullName()
|
||||
end
|
||||
end
|
||||
|
||||
table.insert(statements, string.format(
|
||||
"- Add instance %q (ClassName %q) to %s",
|
||||
virtualInstance.Name, virtualInstance.ClassName, parentDisplayName))
|
||||
end
|
||||
|
||||
for _, update in ipairs(patchSet.updated) do
|
||||
local updatedProperties = {}
|
||||
|
||||
if update.changedMetadata ~= nil then
|
||||
table.insert(updatedProperties, "Rojo's Metadata")
|
||||
end
|
||||
|
||||
if update.changedName ~= nil then
|
||||
table.insert(updatedProperties, "Name")
|
||||
end
|
||||
|
||||
if update.changedClassName ~= nil then
|
||||
table.insert(updatedProperties, "ClassName")
|
||||
end
|
||||
|
||||
for name in pairs(update.changedProperties) do
|
||||
table.insert(updatedProperties, name)
|
||||
end
|
||||
|
||||
local instance = instanceMap.fromIds[update.id]
|
||||
local displayName
|
||||
if instance ~= nil then
|
||||
displayName = instance:GetFullName()
|
||||
else
|
||||
displayName = "[unknown instance]"
|
||||
end
|
||||
|
||||
table.insert(statements, string.format(
|
||||
"- Update properties on %s: %s",
|
||||
displayName, table.concat(updatedProperties, ",")))
|
||||
end
|
||||
|
||||
return table.concat(statements, "\n")
|
||||
end
|
||||
|
||||
return PatchSet
|
||||
Reference in New Issue
Block a user