blob: 2ab8fe6f5f0603ed4ae99b7b009f77f1adb340c0 [file] [log] [blame]
// Copyright (c) 2014, 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.
part of 'program_builder.dart';
class LibraryContents {
final List<ClassEntity> classes = [];
final List<MemberEntity> members = [];
final List<ClassEntity> classTypes = [];
}
/// Maps [LibraryEntity]s to their classes, members, and class types.
///
/// Fundamentally, this class nicely encapsulates a
/// `Map<LibraryEntity, Tuple<classes, members, class types>>`.
///
/// where both classes and class types are lists of [ClassEntity] and
/// members is a list of [MemberEntity].
///
/// There exists exactly one instance per [OutputUnit].
class LibrariesMap {
final Map<LibraryEntity, LibraryContents> _mapping = {};
// It is very common to access the same library multiple times in a row, so
// we cache the last access.
LibraryEntity? _lastLibrary;
late LibraryContents _lastMapping;
/// A unique name representing this instance.
final String name;
final OutputUnit outputUnit;
LibrariesMap.main(this.outputUnit) : name = "";
LibrariesMap.deferred(this.outputUnit, this.name) {
assert(name != "");
}
LibraryContents _getMapping(LibraryEntity library) {
if (_lastLibrary != library) {
_lastLibrary = library;
_lastMapping = _mapping.putIfAbsent(library, () => LibraryContents());
}
return _lastMapping;
}
void addClass(LibraryEntity library, ClassEntity element) {
_getMapping(library).classes.add(element);
}
void addClassType(LibraryEntity library, ClassEntity element) {
_getMapping(library).classTypes.add(element);
}
void addMember(LibraryEntity library, MemberEntity element) {
_getMapping(library).members.add(element);
}
int get length => _mapping.length;
Iterable<MapEntry<LibraryEntity, LibraryContents>> get entries =>
_mapping.entries;
void forEach(
void Function(
LibraryEntity library,
List<ClassEntity> classes,
List<MemberEntity> members,
List<ClassEntity> classTypeData,
)
f,
) {
_mapping.forEach((LibraryEntity library, LibraryContents mapping) {
f(library, mapping.classes, mapping.members, mapping.classTypes);
});
}
}
/// Keeps track of all elements and holders.
///
/// This class assigns each registered element to its [LibrariesMap] (which are
/// in bijection with [OutputUnit]s).
///
/// Registered holders are assigned a name.
class Registry {
final OutputUnit _mainOutputUnit;
final Sorter _sorter;
final Map<OutputUnit, LibrariesMap> _deferredLibrariesMap = {};
/// Cache for the last seen output unit.
OutputUnit? _lastOutputUnit;
late LibrariesMap _lastLibrariesMap;
Iterable<LibrariesMap> get deferredLibrariesMap =>
_deferredLibrariesMap.values;
// Add one for the main libraries map.
int get librariesMapCount => _deferredLibrariesMap.length + 1;
late final LibrariesMap mainLibrariesMap;
Registry(this._mainOutputUnit, this._sorter);
LibrariesMap _mapUnitToLibrariesMap(OutputUnit targetUnit) {
if (targetUnit == _lastOutputUnit) return _lastLibrariesMap;
final result = (targetUnit == _mainOutputUnit)
? mainLibrariesMap
: _deferredLibrariesMap[targetUnit]!;
_lastOutputUnit = targetUnit;
_lastLibrariesMap = result;
return result;
}
void registerOutputUnit(OutputUnit outputUnit) {
if (outputUnit == _mainOutputUnit) {
mainLibrariesMap = LibrariesMap.main(_mainOutputUnit);
} else {
assert(!_deferredLibrariesMap.containsKey(outputUnit));
String name = outputUnit.name;
_deferredLibrariesMap[outputUnit] = LibrariesMap.deferred(
outputUnit,
name,
);
}
}
/// Adds all elements to their respective libraries in the correct
/// libraries map.
void registerClasses(OutputUnit outputUnit, Iterable<ClassEntity> elements) {
LibrariesMap targetLibrariesMap = _mapUnitToLibrariesMap(outputUnit);
for (ClassEntity element in _sorter.sortClasses(elements)) {
targetLibrariesMap.addClass(element.library, element);
}
}
/// Adds all elements to their respective libraries in the correct
/// libraries map.
void registerClassTypes(
OutputUnit outputUnit,
Iterable<ClassEntity> elements,
) {
LibrariesMap targetLibrariesMap = _mapUnitToLibrariesMap(outputUnit);
for (ClassEntity element in _sorter.sortClasses(elements)) {
targetLibrariesMap.addClassType(element.library, element);
}
}
/// Adds all elements to their respective libraries in the correct
/// libraries map.
void registerMembers(OutputUnit outputUnit, Iterable<MemberEntity> elements) {
LibrariesMap targetLibrariesMap = _mapUnitToLibrariesMap(outputUnit);
for (MemberEntity element in _sorter.sortMembers(elements)) {
targetLibrariesMap.addMember(element.library, element);
}
}
void registerConstant(OutputUnit outputUnit, ConstantValue constantValue) {
// Ignore for now.
}
}