mirror of
https://github.com/rojo-rbx/rojo.git
synced 2026-10-23 05:51:39 +00:00
Enhance matching module with reference identity and caching improvements
- Introduced a new `RefIdentity` type to store reference details (name and className) in the matching process. - Updated `VCache` and `SCache` structures to include references, improving the handling of reference comparisons during matching. - Modified `cacheVirtual` and `cacheStudio` functions to support reference caching, enhancing performance and accuracy in matching. - Improved `countOwnDiffs` function to account for reference mismatches, ensuring more precise cost calculations. - Added comprehensive tests to validate the new reference handling and caching mechanisms. These changes significantly enhance the efficiency and accuracy of the matching process in the application.
This commit is contained in:
parent
bf4aef6e94
commit
b687c8862d
12 changed files with 1401 additions and 61 deletions
|
|
@ -47,11 +47,17 @@ type MatchingSession = {
|
|||
costCache: { [string]: { [Instance]: number } },
|
||||
}
|
||||
|
||||
type RefIdentity = {
|
||||
name: string,
|
||||
className: string,
|
||||
}
|
||||
|
||||
type VCache = {
|
||||
props: { [string]: any },
|
||||
extraProps: { string },
|
||||
tags: { [string]: boolean },
|
||||
attrs: { [string]: any },
|
||||
refs: { [string]: RefIdentity },
|
||||
childCount: number,
|
||||
}
|
||||
|
||||
|
|
@ -60,6 +66,7 @@ type SCache = {
|
|||
props: { [string]: any },
|
||||
tags: { [string]: boolean },
|
||||
attrs: { [string]: any },
|
||||
refs: { [string]: RefIdentity },
|
||||
children: { Instance },
|
||||
childCount: number,
|
||||
}
|
||||
|
|
@ -73,6 +80,12 @@ type VirtualInstance = {
|
|||
|
||||
type VirtualInstances = { [string]: VirtualInstance }
|
||||
|
||||
type ClassComparisonKeys = {
|
||||
propNames: { string },
|
||||
propNameSet: { [string]: boolean },
|
||||
defaults: { [string]: any },
|
||||
}
|
||||
|
||||
type ScoredPair = {
|
||||
vi: number,
|
||||
si: number,
|
||||
|
|
@ -107,9 +120,10 @@ end
|
|||
-- Pre-computation helpers (called once per instance per group)
|
||||
-- ================================================================
|
||||
|
||||
local function cacheVirtual(vInst: VirtualInstance, classKeys: any): VCache
|
||||
local function cacheVirtual(vInst: VirtualInstance, classKeys: ClassComparisonKeys, virtualInstances: VirtualInstances): VCache
|
||||
local decoded: { [string]: any } = {}
|
||||
local extraProps: { string } = {}
|
||||
local refs: { [string]: RefIdentity } = {}
|
||||
local vProps = vInst.Properties
|
||||
|
||||
if vProps then
|
||||
|
|
@ -120,6 +134,13 @@ local function cacheVirtual(vInst: VirtualInstance, classKeys: any): VCache
|
|||
|
||||
local ty = next(encodedValue)
|
||||
if ty == "Ref" then
|
||||
local targetId = encodedValue.Ref
|
||||
if targetId then
|
||||
local target = virtualInstances[targetId]
|
||||
if target then
|
||||
refs[propName] = { name = target.Name, className = target.ClassName }
|
||||
end
|
||||
end
|
||||
continue
|
||||
end
|
||||
|
||||
|
|
@ -156,11 +177,12 @@ local function cacheVirtual(vInst: VirtualInstance, classKeys: any): VCache
|
|||
extraProps = extraProps,
|
||||
tags = decodedTags,
|
||||
attrs = decodedAttrs,
|
||||
refs = refs,
|
||||
childCount = if vInst.Children then #vInst.Children else 0,
|
||||
}
|
||||
end
|
||||
|
||||
local function cacheStudio(studioInstance: Instance, classKeys: any, extraPropNames: { string }): SCache
|
||||
local function cacheStudio(studioInstance: Instance, classKeys: ClassComparisonKeys, extraPropNames: { string }, refPropNames: { string }): SCache
|
||||
local props: { [string]: any } = {}
|
||||
|
||||
for _, propName in ipairs(classKeys.propNames) do
|
||||
|
|
@ -180,6 +202,14 @@ local function cacheStudio(studioInstance: Instance, classKeys: any, extraPropNa
|
|||
end
|
||||
end
|
||||
|
||||
local refs: { [string]: RefIdentity } = {}
|
||||
for _, propName in ipairs(refPropNames) do
|
||||
local ok, value = safeGet(studioInstance, propName)
|
||||
if ok and typeof(value) == "Instance" then
|
||||
refs[propName] = { name = (value :: Instance).Name, className = (value :: Instance).ClassName }
|
||||
end
|
||||
end
|
||||
|
||||
local tags: { [string]: boolean } = {}
|
||||
for _, tag in ipairs(studioInstance:GetTags()) do
|
||||
tags[tag] = true
|
||||
|
|
@ -192,6 +222,7 @@ local function cacheStudio(studioInstance: Instance, classKeys: any, extraPropNa
|
|||
props = props,
|
||||
tags = tags,
|
||||
attrs = studioInstance:GetAttributes(),
|
||||
refs = refs,
|
||||
children = children,
|
||||
childCount = #children,
|
||||
}
|
||||
|
|
@ -201,7 +232,7 @@ end
|
|||
-- Hot-path scoring (ZERO decode, ZERO reflection lookup)
|
||||
-- ================================================================
|
||||
|
||||
local function countOwnDiffs(vCache: VCache, sCache: SCache, classKeys: any): number
|
||||
local function countOwnDiffs(vCache: VCache, sCache: SCache, classKeys: ClassComparisonKeys): number
|
||||
local cost = 0
|
||||
local vProps = vCache.props
|
||||
local sProps = sCache.props
|
||||
|
|
@ -250,6 +281,24 @@ local function countOwnDiffs(vCache: VCache, sCache: SCache, classKeys: any): nu
|
|||
end
|
||||
end
|
||||
|
||||
local vRefs = vCache.refs
|
||||
local sRefs = sCache.refs
|
||||
for propName, vRef in pairs(vRefs) do
|
||||
local sRef = sRefs[propName]
|
||||
if sRef then
|
||||
if vRef.name ~= sRef.name or vRef.className ~= sRef.className then
|
||||
cost += UNMATCHED_PENALTY
|
||||
end
|
||||
else
|
||||
cost += UNMATCHED_PENALTY
|
||||
end
|
||||
end
|
||||
for propName, _ in pairs(sRefs) do
|
||||
if not vRefs[propName] then
|
||||
cost += UNMATCHED_PENALTY
|
||||
end
|
||||
end
|
||||
|
||||
if vCache.childCount ~= sCache.childCount then
|
||||
cost += 1
|
||||
end
|
||||
|
|
@ -301,8 +350,12 @@ local function computePairCost(
|
|||
end
|
||||
|
||||
local classKeys = RbxDom.getClassComparisonKeys(vInst.ClassName)
|
||||
local vCache = cacheVirtual(vInst, classKeys)
|
||||
local sCache = cacheStudio(studioInstance, classKeys, vCache.extraProps)
|
||||
local vCache = cacheVirtual(vInst, classKeys, virtualInstances)
|
||||
local refPropNames: { string } = {}
|
||||
for propName, _ in pairs(vCache.refs) do
|
||||
table.insert(refPropNames, propName)
|
||||
end
|
||||
local sCache = cacheStudio(studioInstance, classKeys, vCache.extraProps, refPropNames)
|
||||
|
||||
local cost = countOwnDiffs(vCache, sCache, classKeys)
|
||||
if cost >= bestSoFar then
|
||||
|
|
@ -312,29 +365,29 @@ local function computePairCost(
|
|||
local vChildren = vInst.Children
|
||||
local studioKids = sCache.children
|
||||
|
||||
if (not vChildren or #vChildren == 0) and #studioKids == 0 then
|
||||
-- leaf
|
||||
elseif not vChildren or #vChildren == 0 then
|
||||
cost += #studioKids * UNMATCHED_PENALTY
|
||||
elseif #studioKids == 0 then
|
||||
for _, childId in ipairs(vChildren) do
|
||||
if virtualInstances[childId] then
|
||||
cost += UNMATCHED_PENALTY
|
||||
end
|
||||
end
|
||||
else
|
||||
local validVChildren: { string } = {}
|
||||
for _, childId in ipairs(vChildren) do
|
||||
if virtualInstances[childId] then
|
||||
table.insert(validVChildren, childId)
|
||||
end
|
||||
end
|
||||
if #validVChildren > 0 then
|
||||
local childResult =
|
||||
matchChildren(session, validVChildren, studioKids, virtualInstances, virtualId, studioInstance)
|
||||
cost += childResult.totalCost
|
||||
else
|
||||
if (vChildren and #vChildren > 0) or #studioKids > 0 then
|
||||
if not vChildren or #vChildren == 0 then
|
||||
cost += #studioKids * UNMATCHED_PENALTY
|
||||
elseif #studioKids == 0 then
|
||||
for _, childId in ipairs(vChildren) do
|
||||
if virtualInstances[childId] then
|
||||
cost += UNMATCHED_PENALTY
|
||||
end
|
||||
end
|
||||
else
|
||||
local validVChildren: { string } = {}
|
||||
for _, childId in ipairs(vChildren) do
|
||||
if virtualInstances[childId] then
|
||||
table.insert(validVChildren, childId)
|
||||
end
|
||||
end
|
||||
if #validVChildren > 0 then
|
||||
local childResult =
|
||||
matchChildren(session, validVChildren, studioKids, virtualInstances, virtualId, studioInstance)
|
||||
cost += childResult.totalCost
|
||||
else
|
||||
cost += #studioKids * UNMATCHED_PENALTY
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -469,6 +522,7 @@ matchChildren = function(
|
|||
|
||||
local vCaches: { [number]: VCache } = {}
|
||||
local allExtraProps: { [string]: boolean } = {}
|
||||
local allRefProps: { [string]: boolean } = {}
|
||||
for _, vi in ipairs(vIndices) do
|
||||
if matchedV2[vi] then
|
||||
continue
|
||||
|
|
@ -477,11 +531,14 @@ matchChildren = function(
|
|||
if not vInst then
|
||||
continue
|
||||
end
|
||||
local vCache = cacheVirtual(vInst, classKeys)
|
||||
local vCache = cacheVirtual(vInst, classKeys, virtualInstances)
|
||||
vCaches[vi] = vCache
|
||||
for _, propName in ipairs(vCache.extraProps) do
|
||||
allExtraProps[propName] = true
|
||||
end
|
||||
for propName, _ in pairs(vCache.refs) do
|
||||
allRefProps[propName] = true
|
||||
end
|
||||
end
|
||||
|
||||
local extraPropNamesArray: { string } = {}
|
||||
|
|
@ -489,10 +546,15 @@ matchChildren = function(
|
|||
table.insert(extraPropNamesArray, propName)
|
||||
end
|
||||
|
||||
local refPropNamesArray: { string } = {}
|
||||
for propName, _ in pairs(allRefProps) do
|
||||
table.insert(refPropNamesArray, propName)
|
||||
end
|
||||
|
||||
local sCaches: { [number]: SCache } = {}
|
||||
for _, si in ipairs(sIndices) do
|
||||
if not matchedS2[si] then
|
||||
sCaches[si] = cacheStudio(remainingStudio[si], classKeys, extraPropNamesArray)
|
||||
sCaches[si] = cacheStudio(remainingStudio[si], classKeys, extraPropNamesArray, refPropNamesArray)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -529,35 +591,35 @@ matchChildren = function(
|
|||
local vChildren = vInst.Children
|
||||
local studioKids = sCache.children
|
||||
|
||||
if (not vChildren or #vChildren == 0) and #studioKids == 0 then
|
||||
-- leaf
|
||||
elseif not vChildren or #vChildren == 0 then
|
||||
cost += #studioKids * UNMATCHED_PENALTY
|
||||
elseif #studioKids == 0 then
|
||||
for _, childId in ipairs(vChildren) do
|
||||
if virtualInstances[childId] then
|
||||
cost += UNMATCHED_PENALTY
|
||||
end
|
||||
end
|
||||
else
|
||||
local validVChildren: { string } = {}
|
||||
for _, childId in ipairs(vChildren) do
|
||||
if virtualInstances[childId] then
|
||||
table.insert(validVChildren, childId)
|
||||
end
|
||||
end
|
||||
if #validVChildren > 0 then
|
||||
local childResult = matchChildren(
|
||||
session,
|
||||
validVChildren,
|
||||
studioKids,
|
||||
virtualInstances,
|
||||
remainingVirtual[vi],
|
||||
sCache.instance
|
||||
)
|
||||
cost += childResult.totalCost
|
||||
else
|
||||
if (vChildren and #vChildren > 0) or #studioKids > 0 then
|
||||
if not vChildren or #vChildren == 0 then
|
||||
cost += #studioKids * UNMATCHED_PENALTY
|
||||
elseif #studioKids == 0 then
|
||||
for _, childId in ipairs(vChildren) do
|
||||
if virtualInstances[childId] then
|
||||
cost += UNMATCHED_PENALTY
|
||||
end
|
||||
end
|
||||
else
|
||||
local validVChildren: { string } = {}
|
||||
for _, childId in ipairs(vChildren) do
|
||||
if virtualInstances[childId] then
|
||||
table.insert(validVChildren, childId)
|
||||
end
|
||||
end
|
||||
if #validVChildren > 0 then
|
||||
local childResult = matchChildren(
|
||||
session,
|
||||
validVChildren,
|
||||
studioKids,
|
||||
virtualInstances,
|
||||
remainingVirtual[vi],
|
||||
sCache.instance
|
||||
)
|
||||
cost += childResult.totalCost
|
||||
else
|
||||
cost += #studioKids * UNMATCHED_PENALTY
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue