Skip to content

Commit f3a4e5b

Browse files
scheglovCommit Queue
authored andcommitted
Fine. Record InstanceElement.methods access.
Change-Id: I6451b6d3f1bed1624f3d9e3c8e0549615b716678 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/430940 Reviewed-by: Paul Berry <[email protected]> Commit-Queue: Konstantin Shcheglov <[email protected]>
1 parent 03515b4 commit f3a4e5b

File tree

6 files changed

+309
-3
lines changed

6 files changed

+309
-3
lines changed

pkg/analyzer/lib/src/dart/element/element.dart

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4535,7 +4535,10 @@ abstract class InstanceElementImpl2 extends ElementImpl2
45354535
MetadataImpl get metadata2 => firstFragment.metadata2;
45364536

45374537
@override
4538+
@trackedDirectlyExpensive
45384539
List<MethodElementImpl2> get methods {
4540+
globalResultRequirements?.record_instanceElement_methods(element: this);
4541+
45394542
return firstFragment.methods.map((e) => e.asElement2).toList();
45404543
}
45414544

@@ -4613,7 +4616,15 @@ abstract class InstanceElementImpl2 extends ElementImpl2
46134616
name: name,
46144617
);
46154618

4616-
return methods.firstWhereOrNull((e) => e.lookupName == name);
4619+
return globalResultRequirements.withoutRecording(
4620+
reason: r'''
4621+
The result depends only on the requested method, which we have already
4622+
recorded above.
4623+
''',
4624+
operation: () {
4625+
return methods.firstWhereOrNull((e) => e.lookupName == name);
4626+
},
4627+
);
46174628
}
46184629

46194630
@Deprecated('Use getMethod instead')

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

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,10 @@ class ManifestItemIdList {
8282
const ListEquality<ManifestItemId>().equals(other.ids, ids);
8383
}
8484

85+
bool equalToIterable(Iterable<ManifestItemId> other) {
86+
return const IterableEquality<ManifestItemId>().equals(ids, other);
87+
}
88+
8589
@override
8690
String toString() {
8791
return '[${ids.join(', ')}]';
@@ -90,12 +94,22 @@ class ManifestItemIdList {
9094
void write(BufferedSink sink) {
9195
sink.writeList(ids, (id) => id.write(sink));
9296
}
97+
98+
static ManifestItemIdList? readOptional(SummaryDataReader reader) {
99+
return reader.readOptionalObject(() => ManifestItemIdList.read(reader));
100+
}
93101
}
94102

95103
extension ManifestItemIdExtension on ManifestItemId? {
96104
void writeOptional(BufferedSink sink) {
97-
sink.writeOptionalObject(this, (id) {
98-
id.write(sink);
105+
sink.writeOptionalObject(this, (it) {
106+
it.write(sink);
99107
});
100108
}
101109
}
110+
111+
extension ManifestItemIdListOrNullExtension on ManifestItemIdList? {
112+
void writeOptional(BufferedSink sink) {
113+
sink.writeOptionalObject(this, (it) => it.write(sink));
114+
}
115+
}

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,20 @@ class InstanceMethodIdMismatch extends RequirementFailure {
7676
});
7777
}
7878

79+
class InstanceMethodIdsMismatch extends RequirementFailure {
80+
final Uri libraryUri;
81+
final LookupName interfaceName;
82+
final ManifestItemIdList expectedIds;
83+
final ManifestItemIdList actualIds;
84+
85+
InstanceMethodIdsMismatch({
86+
required this.libraryUri,
87+
required this.interfaceName,
88+
required this.expectedIds,
89+
required this.actualIds,
90+
});
91+
}
92+
7993
class InterfaceConstructorIdMismatch extends RequirementFailure {
8094
final Uri libraryUri;
8195
final LookupName interfaceName;

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

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,11 +202,14 @@ class InstanceItemRequirements {
202202
final Map<LookupName, ManifestItemId?> requestedSetters;
203203
final Map<LookupName, ManifestItemId?> requestedMethods;
204204

205+
ManifestItemIdList? allDeclaredMethods;
206+
205207
InstanceItemRequirements({
206208
required this.requestedFields,
207209
required this.requestedGetters,
208210
required this.requestedSetters,
209211
required this.requestedMethods,
212+
required this.allDeclaredMethods,
210213
});
211214

212215
factory InstanceItemRequirements.empty() {
@@ -215,6 +218,7 @@ class InstanceItemRequirements {
215218
requestedGetters: {},
216219
requestedSetters: {},
217220
requestedMethods: {},
221+
allDeclaredMethods: null,
218222
);
219223
}
220224

@@ -224,6 +228,7 @@ class InstanceItemRequirements {
224228
requestedGetters: reader.readNameToIdMap(),
225229
requestedSetters: reader.readNameToIdMap(),
226230
requestedMethods: reader.readNameToIdMap(),
231+
allDeclaredMethods: ManifestItemIdList.readOptional(reader),
227232
);
228233
}
229234

@@ -232,6 +237,7 @@ class InstanceItemRequirements {
232237
sink.writeNameToIdMap(requestedGetters);
233238
sink.writeNameToIdMap(requestedSetters);
234239
sink.writeNameToIdMap(requestedMethods);
240+
allDeclaredMethods.writeOptional(sink);
235241
}
236242
}
237243

@@ -321,6 +327,8 @@ class RequirementsManifest {
321327

322328
final List<LibraryExportRequirements> exportRequirements = [];
323329

330+
int _recordingLockLevel = 0;
331+
324332
RequirementsManifest();
325333

326334
factory RequirementsManifest.read(SummaryDataReader reader) {
@@ -491,6 +499,19 @@ class RequirementsManifest {
491499
);
492500
}
493501
}
502+
503+
if (requirements.allDeclaredMethods case var required?) {
504+
var actualItems = instanceItem.declaredMethods.values;
505+
var actualIds = actualItems.map((item) => item.id);
506+
if (!required.equalToIterable(actualIds)) {
507+
return InstanceMethodIdsMismatch(
508+
libraryUri: libraryUri,
509+
interfaceName: instanceName,
510+
expectedIds: required,
511+
actualIds: ManifestItemIdList(actualIds.toList()),
512+
);
513+
}
514+
}
494515
}
495516
}
496517

@@ -666,6 +687,24 @@ class RequirementsManifest {
666687
requirements.requestedSetters[methodName] = methodId;
667688
}
668689

690+
void record_instanceElement_methods({required InstanceElementImpl2 element}) {
691+
if (_recordingLockLevel != 0) {
692+
return;
693+
}
694+
695+
var itemRequirements = _getInstanceItem(element);
696+
if (itemRequirements == null) {
697+
return;
698+
}
699+
700+
var item = itemRequirements.item;
701+
var requirements = itemRequirements.requirements;
702+
703+
requirements.allDeclaredMethods ??= ManifestItemIdList(
704+
item.declaredMethods.values.map((item) => item.id).toList(),
705+
);
706+
}
707+
669708
/// Record that a member with [nameObj] was requested from the interface
670709
/// of [element]. The [methodElement] is used for consistency checking.
671710
void record_interface_getMember({
@@ -973,6 +1012,25 @@ class _InterfaceItemWithRequirements {
9731012
});
9741013
}
9751014

1015+
extension RequirementsManifestExtension on RequirementsManifest? {
1016+
T withoutRecording<T>({
1017+
required String reason,
1018+
required T Function() operation,
1019+
}) {
1020+
var self = this;
1021+
if (self == null) {
1022+
return operation();
1023+
} else {
1024+
self._recordingLockLevel++;
1025+
try {
1026+
return operation();
1027+
} finally {
1028+
self._recordingLockLevel--;
1029+
}
1030+
}
1031+
}
1032+
}
1033+
9761034
extension _BufferedSinkExtension on BufferedSink {
9771035
void writeNameToIdMap(Map<LookupName, ManifestItemId?> map) {
9781036
writeMap(

0 commit comments

Comments
 (0)