blob: 36f365ac8938256a13ef292ce3d2c925cc440699 [file] [log] [blame]
// Copyright (c) 2019, 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 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/summary2/combinator.dart';
import 'package:analyzer/src/summary2/library_builder.dart';
import 'package:analyzer/src/summary2/reference.dart';
class Export {
final LibraryBuilder exporter;
final ExportLocation location;
final List<Combinator> combinators;
Export({
required this.exporter,
required this.location,
required this.combinators,
});
bool addToExportScope(String name, ExportedReference exported) {
if (combinators.allows(name)) {
return exporter.exportScope.export(location, name, exported);
}
return false;
}
}
class ExportedReference {
final Reference reference;
ExportedReference({
required this.reference,
});
@override
String toString() {
return '$reference';
}
}
/// [ExportedReference] for a public element declared in the library.
class ExportedReferenceDeclared extends ExportedReference {
ExportedReferenceDeclared({
required super.reference,
});
}
/// [ExportedReference] for an element that is re-exported.
class ExportedReferenceExported extends ExportedReference {
/// The locations of `export` (at least one) that export the element.
final List<ExportLocation> locations;
ExportedReferenceExported({
required super.reference,
required this.locations,
});
void addLocation(ExportLocation location) {
if (!locations.contains(location)) {
locations.add(location);
}
}
}
class ExportLocation {
/// The index of the container with the `export` directive, `0` means the
/// library itself, a positive value means a `+1` index in the library
/// augmentations.
final int containerIndex;
/// The index in [LibraryElementImpl.libraryExports].
final int exportIndex;
ExportLocation({
required this.containerIndex,
required this.exportIndex,
});
@override
bool operator ==(Object other) {
return other is ExportLocation &&
other.containerIndex == containerIndex &&
other.exportIndex == exportIndex;
}
LibraryExportElementImpl exportOf(LibraryElementImpl library) {
final container = containerIndex == 0
? library
: library.augmentations[containerIndex - 1];
return container.libraryExports[exportIndex] as LibraryExportElementImpl;
}
@override
String toString() {
return '($containerIndex, $exportIndex)';
}
}
class ExportScope {
final Map<String, ExportedReference> map = {};
void declare(String name, Reference reference) {
map[name] = ExportedReferenceDeclared(
reference: reference,
);
}
bool export(
ExportLocation location,
String name,
ExportedReference exported,
) {
final existing = map[name];
if (existing?.reference == exported.reference) {
if (existing is ExportedReferenceExported) {
existing.addLocation(location);
}
return false;
}
// Ambiguous declaration detected.
if (existing != null) return false;
map[name] = ExportedReferenceExported(
reference: exported.reference,
locations: [location],
);
return true;
}
void forEach(void Function(String name, ExportedReference reference) f) {
map.forEach(f);
}
}