Skip to content

Commit efa2870

Browse files
scheglovCommit Queue
authored andcommitted
Fine. Fix for checking requirements of re-exports.
Change-Id: I1a2e8302e5534fe8d77d3f8d7964d0626835e727 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/430124 Reviewed-by: Brian Wilkerson <[email protected]> Commit-Queue: Konstantin Shcheglov <[email protected]>
1 parent f16cd98 commit efa2870

File tree

6 files changed

+638
-102
lines changed

6 files changed

+638
-102
lines changed

pkg/analyzer/lib/src/fine/library_manifest.dart

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import 'package:analyzer/src/summary2/data_reader.dart';
1515
import 'package:analyzer/src/summary2/data_writer.dart';
1616
import 'package:analyzer/src/summary2/linked_element_factory.dart';
1717
import 'package:analyzer/src/util/performance/operation_performance.dart';
18+
import 'package:analyzer/src/utilities/extensions/collection.dart';
1819
import 'package:collection/collection.dart';
1920

2021
/// The manifest of a single library.
@@ -69,6 +70,23 @@ class LibraryManifest {
6970
);
7071
}
7172

73+
Map<LookupName, ManifestItemId> get exportedIds {
74+
return Map.fromEntries([
75+
...reExportMap.entries,
76+
...<Map<LookupName, TopLevelItem>>[
77+
declaredClasses,
78+
declaredEnums,
79+
declaredMixins,
80+
declaredGetters,
81+
declaredSetters,
82+
declaredFunctions,
83+
]
84+
.expand((map) => map.entries)
85+
.whereNot((entry) => entry.key.isPrivate)
86+
.mapValue((item) => item.id),
87+
]);
88+
}
89+
7290
/// Returns the ID of a top-level element either declared or re-exported,
7391
/// or `null` if there is no such element.
7492
ManifestItemId? getExportedId(LookupName name) {

pkg/analyzer/lib/src/fine/lookup_name.dart

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,12 @@ extension IterableOfStringExtension on Iterable<String> {
136136
}
137137
}
138138

139+
extension LookupNameIterableExtension on Iterable<LookupName> {
140+
void write(BufferedSink sink) {
141+
sink.writeIterable(this, (name) => name.write(sink));
142+
}
143+
}
144+
139145
extension StringExtension on String {
140146
BaseName get asBaseName {
141147
return BaseName(this);
@@ -156,4 +162,14 @@ extension SummaryDataReaderExtension on SummaryDataReader {
156162
}
157163
return result;
158164
}
165+
166+
Set<LookupName> readLookupNameSet() {
167+
var length = readUInt30();
168+
var result = <LookupName>{};
169+
for (var i = 0; i < length; i++) {
170+
var lookupName = LookupName.read(this);
171+
result.add(lookupName);
172+
}
173+
return result;
174+
}
159175
}

pkg/analyzer/lib/src/fine/requirements.dart

Lines changed: 90 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ RequirementsManifest? globalResultRequirements;
2525
/// This cannot be `const` because we change it in tests.
2626
bool withFineDependencies = false;
2727

28+
/// Requirements for a single `export`.
2829
@visibleForTesting
2930
class ExportRequirement {
3031
final Uri fragmentUri;
@@ -53,41 +54,40 @@ class ExportRequirement {
5354
);
5455
}
5556

56-
ExportFailure? isSatisfied({required LinkedElementFactory elementFactory}) {
57+
ExportFailure? isSatisfied({
58+
required LinkedElementFactory elementFactory,
59+
required Set<LookupName> declaredTopNames,
60+
}) {
5761
var libraryElement = elementFactory.libraryOfUri(exportedUri);
58-
var libraryManifest = libraryElement?.manifest;
59-
if (libraryManifest == null) {
62+
if (libraryElement == null) {
6063
return ExportLibraryMissing(uri: exportedUri);
6164
}
6265

66+
// SAFETY: every library has the manifest.
67+
var libraryManifest = libraryElement.manifest!;
68+
6369
// Every now exported ID must be previously exported.
6470
var actualCount = 0;
65-
var declaredTopEntries = <MapEntry<LookupName, TopLevelItem>>[
66-
...libraryManifest.declaredClasses.entries,
67-
...libraryManifest.declaredEnums.entries,
68-
...libraryManifest.declaredMixins.entries,
69-
...libraryManifest.declaredGetters.entries,
70-
...libraryManifest.declaredSetters.entries,
71-
...libraryManifest.declaredFunctions.entries,
72-
];
73-
for (var topEntry in declaredTopEntries) {
74-
var name = topEntry.key;
75-
if (name.isPrivate) {
71+
for (var topEntry in libraryManifest.exportedIds.entries) {
72+
var lookupName = topEntry.key;
73+
74+
// If declared locally, export is no-op.
75+
if (declaredTopNames.contains(lookupName)) {
7676
continue;
7777
}
7878

79-
if (!_passCombinators(name)) {
79+
if (!_passCombinators(lookupName)) {
8080
continue;
8181
}
8282

8383
actualCount++;
84-
var actualId = topEntry.value.id;
85-
var expectedId = exportedIds[topEntry.key];
84+
var actualId = topEntry.value;
85+
var expectedId = exportedIds[lookupName];
8686
if (actualId != expectedId) {
8787
return ExportIdMismatch(
8888
fragmentUri: fragmentUri,
8989
exportedUri: exportedUri,
90-
name: name,
90+
name: lookupName,
9191
expectedId: expectedId,
9292
actualId: actualId,
9393
);
@@ -269,6 +269,47 @@ class InterfaceItemRequirements {
269269
}
270270
}
271271

272+
/// Requirements for all `export`s of a library.
273+
@visibleForTesting
274+
class LibraryExportRequirements {
275+
final Uri libraryUri;
276+
final Set<LookupName> declaredTopNames;
277+
final List<ExportRequirement> exports;
278+
279+
LibraryExportRequirements({
280+
required this.libraryUri,
281+
required this.declaredTopNames,
282+
required this.exports,
283+
});
284+
285+
factory LibraryExportRequirements.read(SummaryDataReader reader) {
286+
return LibraryExportRequirements(
287+
libraryUri: reader.readUri(),
288+
declaredTopNames: reader.readLookupNameSet(),
289+
exports: reader.readTypedList(() => ExportRequirement.read(reader)),
290+
);
291+
}
292+
293+
ExportFailure? isSatisfied({required LinkedElementFactory elementFactory}) {
294+
for (var export in exports) {
295+
var failure = export.isSatisfied(
296+
elementFactory: elementFactory,
297+
declaredTopNames: declaredTopNames,
298+
);
299+
if (failure != null) {
300+
return failure;
301+
}
302+
}
303+
return null;
304+
}
305+
306+
void write(BufferedSink sink) {
307+
sink.writeUri(libraryUri);
308+
declaredTopNames.write(sink);
309+
sink.writeList(exports, (export) => export.write(sink));
310+
}
311+
}
312+
272313
class RequirementsManifest {
273314
/// LibraryUri => TopName => ID
274315
final Map<Uri, Map<LookupName, ManifestItemId?>> topLevels = {};
@@ -279,7 +320,7 @@ class RequirementsManifest {
279320
/// LibraryUri => TopName => InterfaceItemRequirements
280321
final Map<Uri, Map<LookupName, InterfaceItemRequirements>> interfaces = {};
281322

282-
final List<ExportRequirement> exportRequirements = [];
323+
final List<LibraryExportRequirements> exportRequirements = [];
283324

284325
RequirementsManifest();
285326

@@ -318,7 +359,7 @@ class RequirementsManifest {
318359
);
319360

320361
result.exportRequirements.addAll(
321-
reader.readTypedList(() => ExportRequirement.read(reader)),
362+
reader.readTypedList(() => LibraryExportRequirements.read(reader)),
322363
);
323364

324365
return result;
@@ -700,9 +741,12 @@ class RequirementsManifest {
700741
/// libraries are interesting.
701742
void removeReqForLibs(Set<Uri> bundleLibraryUriList) {
702743
var uriSet = bundleLibraryUriList.toSet();
703-
exportRequirements.removeWhere((export) {
704-
return uriSet.contains(export.exportedUri);
705-
});
744+
745+
for (var exportRequirement in exportRequirements) {
746+
exportRequirement.exports.removeWhere((export) {
747+
return uriSet.contains(export.exportedUri);
748+
});
749+
}
706750

707751
for (var libUri in bundleLibraryUriList) {
708752
topLevels.remove(libUri);
@@ -751,6 +795,15 @@ class RequirementsManifest {
751795
}
752796

753797
void _addExports(LibraryElementImpl libraryElement) {
798+
var declaredTopNames =
799+
libraryElement.children2
800+
.map((element) => element.lookupName)
801+
.nonNulls
802+
.map((nameStr) => nameStr.asLookupName)
803+
.toSet();
804+
805+
var fragments = <ExportRequirement>[];
806+
754807
for (var fragment in libraryElement.fragments) {
755808
for (var export in fragment.libraryExports) {
756809
var exportedLibrary = export.exportedLibrary2;
@@ -783,14 +836,17 @@ class RequirementsManifest {
783836
);
784837
for (var entry in exportMap.definedNames2.entries) {
785838
var lookupName = entry.key.asLookupName;
839+
if (declaredTopNames.contains(lookupName)) {
840+
continue;
841+
}
786842
// TODO(scheglov): must always be not null.
787843
var id = manifest.getExportedId(lookupName);
788844
if (id != null) {
789845
exportedIds[lookupName] = id;
790846
}
791847
}
792848

793-
exportRequirements.add(
849+
fragments.add(
794850
ExportRequirement(
795851
fragmentUri: fragment.source.uri,
796852
exportedUri: exportedLibrary.uri,
@@ -800,6 +856,16 @@ class RequirementsManifest {
800856
);
801857
}
802858
}
859+
860+
if (fragments.isNotEmpty) {
861+
exportRequirements.add(
862+
LibraryExportRequirements(
863+
libraryUri: libraryElement.uri,
864+
declaredTopNames: declaredTopNames,
865+
exports: fragments,
866+
),
867+
);
868+
}
803869
}
804870

805871
_InstanceItemWithRequirements? _getInstanceItem(

pkg/analyzer/lib/src/utilities/extensions/collection.dart

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,17 @@ extension IterableExtension<E> on Iterable<E> {
2525
}
2626
}
2727

28-
extension IterableMapEntryExtension<K, V> on Iterable<MapEntry<K, V>> {
28+
extension IterableOfMapEntryExtension<K, V> on Iterable<MapEntry<K, V>> {
2929
Map<K, V> get mapFromEntries => Map.fromEntries(this);
30+
31+
Iterable<MapEntry<K, V2>> mapValue<V2>(V2 Function(V) convert) {
32+
return map((entry) {
33+
var key = entry.key;
34+
var value = entry.value;
35+
var value2 = convert(value);
36+
return MapEntry(key, value2);
37+
});
38+
}
3039
}
3140

3241
extension ListExtension<E> on List<E> {

0 commit comments

Comments
 (0)