diff --git a/modules/core/validator.js b/modules/core/validator.js index 0f8a3a1c8..ac04e92a3 100644 --- a/modules/core/validator.js +++ b/modules/core/validator.js @@ -488,10 +488,10 @@ export function coreValidator(context) { _headCache.graph = currGraph; // take snapshot _completeDiff = context.history().difference().complete(); const incrementalDiff = coreDifference(prevGraph, currGraph); - const entityIDs = Object.keys(incrementalDiff.complete()); + let entityIDs = Object.keys(incrementalDiff.complete()); + entityIDs = _headCache.withAllRelatedEntities(entityIDs); // expand set - // if (!entityIDs.size) { - if (!entityIDs.length) { + if (!entityIDs.size) { dispatch.call('validated'); return Promise.resolve(); } @@ -540,8 +540,8 @@ export function coreValidator(context) { if (!_headCache.graph) _headCache.graph = baseGraph; if (!_baseCache.graph) _baseCache.graph = baseGraph; - const entityIDs = entities.map(entity => entity.id); - // entityIDs = entityIDsToValidate(entityIDs, baseGraph); // expand set + let entityIDs = entities.map(entity => entity.id); + entityIDs = _baseCache.withAllRelatedEntities(entityIDs); // expand set validateEntitiesAsync(entityIDs, _baseCache); }); @@ -629,7 +629,7 @@ export function coreValidator(context) { // - the user did something to one of the entities involved in the issue // // Arguments - // `entityIDs` - Array containing entity IDs. + // `entityIDs` - Array or Set containing entity IDs. // function updateResolvedIssues(entityIDs) { entityIDs.forEach(entityID => { @@ -656,7 +656,7 @@ export function coreValidator(context) { // Schedule validation for many entities. // // Arguments - // `entityIDs` - Array containing entity IDs. + // `entityIDs` - Array or Set containing entityIDs. // `graph` - the graph to validate that contains those entities // `cache` - the cache to store results in (_headCache or _baseCache) // @@ -666,7 +666,7 @@ export function coreValidator(context) { // function validateEntitiesAsync(entityIDs, cache) { // Enqueue the work - const jobs = entityIDs.map(entityID => { + const jobs = Array.from(entityIDs).map(entityID => { if (cache.queuedEntityIDs.has(entityID)) return null; // queued already cache.queuedEntityIDs.add(entityID); @@ -795,24 +795,20 @@ function validationCache(which) { issuesByEntityID: {} // entity.id -> Set(issue.id) }; - cache.cacheIssues = (issues) => { - issues.forEach(issue => { - const entityIDs = issue.entityIds || []; - entityIDs.forEach(entityID => { - if (!cache.issuesByEntityID[entityID]) { - cache.issuesByEntityID[entityID] = new Set(); - } - cache.issuesByEntityID[entityID].add(issue.id); - }); - cache.issuesByIssueID[issue.id] = issue; + + cache.cacheIssue = (issue) => { + (issue.entityIds || []).forEach(entityID => { + if (!cache.issuesByEntityID[entityID]) { + cache.issuesByEntityID[entityID] = new Set(); + } + cache.issuesByEntityID[entityID].add(issue.id); }); + cache.issuesByIssueID[issue.id] = issue; }; + cache.uncacheIssue = (issue) => { - // When multiple entities are involved (e.g. crossing_ways), - // remove this issue from the other entity caches too.. - const entityIDs = issue.entityIds || []; - entityIDs.forEach(entityID => { + (issue.entityIds || []).forEach(entityID => { if (cache.issuesByEntityID[entityID]) { cache.issuesByEntityID[entityID].delete(issue.id); } @@ -820,25 +816,33 @@ function validationCache(which) { delete cache.issuesByIssueID[issue.id]; }; + + cache.cacheIssues = (issues) => { + issues.forEach(cache.cacheIssue); + }; + + cache.uncacheIssues = (issues) => { issues.forEach(cache.uncacheIssue); }; + cache.uncacheIssuesOfType = (type) => { const issuesOfType = Object.values(cache.issuesByIssueID) .filter(issue => issue.type === type); cache.uncacheIssues(issuesOfType); }; + // Remove a single entity and all its related issues from the caches cache.uncacheEntityID = (entityID) => { - const issueIDs = cache.issuesByEntityID[entityID]; - if (issueIDs) { - issueIDs.forEach(issueID => { + const entityIssueIDs = cache.issuesByEntityID[entityID]; + if (entityIssueIDs) { + entityIssueIDs.forEach(issueID => { const issue = cache.issuesByIssueID[issueID]; if (issue) { cache.uncacheIssue(issue); - } else { + } else { // shouldnt happen, clean up delete cache.issuesByIssueID[issueID]; } }); @@ -849,5 +853,32 @@ function validationCache(which) { }; + // Return the expandeded set of entityIDs related to issues for the given entityIDs + // + // Arguments + // `entityIDs` - Array or Set containing entityIDs. + // + cache.withAllRelatedEntities = (entityIDs) => { + let result = new Set(); + (entityIDs || []).forEach(entityID => { + result.add(entityID); // include self + + const entityIssueIDs = cache.issuesByEntityID[entityID]; + if (entityIssueIDs) { + entityIssueIDs.forEach(issueID => { + const issue = cache.issuesByIssueID[issueID]; + if (issue) { + (issue.entityIds || []).forEach(relatedID => result.add(relatedID)) + } else { // shouldnt happen, clean up + delete cache.issuesByIssueID[issueID]; + } + }); + } + }); + + return result; + } + + return cache; }