blob: 90bf3291909d89cad04f42c43dc68f9e253e4840 [file] [log] [blame]
// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:collection' show Queue;
import 'algorithm_state.dart';
import 'entity_data.dart';
import 'import_set.dart';
import '../elements/entities.dart';
/// The entity_data_state work queue.
class WorkQueue {
/// The actual queue of work that needs to be done.
final Queue<WorkItem> queue = Queue();
/// An index to find work items in the queue corresponding to a given
/// [EntityData].
final Map<EntityData, WorkItem> pendingWorkItems = {};
/// Lattice used to compute unions of [ImportSet]s.
final ImportSetLattice _importSets;
/// Registry used to create [EntityData].
final EntityDataRegistry _registry;
WorkQueue(this._importSets, this._registry);
/// Whether there are no more work items in the queue.
bool get isNotEmpty => queue.isNotEmpty;
/// Pop the next element in the queue.
WorkItem nextItem() {
assert(isNotEmpty);
return queue.removeFirst();
}
/// Add to the queue that [element] should be updated to include all imports
/// in [importSet]. If there is already a work item in the queue for
/// [element], this makes sure that the work item now includes the union of
/// [importSet] and the existing work item's import set.
void addEntityData(EntityData entityData, ImportSet importSet) {
var item = pendingWorkItems[entityData];
if (item == null) {
item = WorkItem(entityData, importSet);
pendingWorkItems[entityData] = item;
queue.add(item);
} else {
item.importsToAdd = _importSets.union(item.importsToAdd, importSet);
}
}
void addMember(MemberEntity member, ImportSet importSet) {
addEntityData(_registry.createMemberEntityData(member), importSet);
}
void addClass(ClassEntity cls, ImportSet importSet) {
addEntityData(_registry.createClassEntityData(cls), importSet);
}
/// Processes the next item in the queue.
void processNextItem(AlgorithmState state) {
var item = nextItem();
var entityData = item.entityData;
pendingWorkItems.remove(entityData);
ImportSet oldSet = state.entityToSet[entityData];
ImportSet newSet = _importSets.union(oldSet, item.importsToAdd);
state.update(entityData, oldSet, newSet);
}
}
/// Summary of the work that needs to be done on a class, member, or constant.
class WorkItem {
final EntityData entityData;
/// Additional imports that use [element] or [value] and need to be added by
/// the algorithm.
///
/// This is non-final in case we add more deferred imports to the set before
/// the work item is applied (see [WorkQueue.addElement] and
/// [WorkQueue.addConstant]).
ImportSet importsToAdd;
WorkItem(this.entityData, this.importsToAdd);
}