| // 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); |
| } |