Skip to content

Commit 2206c9b

Browse files
scheglovCommit Queue
authored andcommitted
Fine. Record and check allDeclaredConstructors for InterfaceElement(s).
Change-Id: Ia1a8dec38b7df4689b5aee716117afee7b550d02 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/444383 Commit-Queue: Konstantin Shcheglov <[email protected]> Reviewed-by: Paul Berry <[email protected]>
1 parent 9b2d1b7 commit 2206c9b

File tree

5 files changed

+896
-36
lines changed

5 files changed

+896
-36
lines changed

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

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4739,6 +4739,9 @@ abstract class InterfaceElementImpl extends InstanceElementImpl
47394739

47404740
@override
47414741
List<ConstructorElementImpl> get constructors {
4742+
globalResultRequirements?.record_instanceElement_constructors(
4743+
element: this,
4744+
);
47424745
ensureReadMembers();
47434746
if (!identical(_constructors, _Sentinel.constructorElement)) {
47444747
return _constructors;
@@ -4877,7 +4880,16 @@ abstract class InterfaceElementImpl extends InstanceElementImpl
48774880
element: this,
48784881
name: name,
48794882
);
4880-
return constructors.firstWhereOrNull((e) => e.name == name);
4883+
4884+
return globalResultRequirements.withoutRecording(
4885+
reason: r'''
4886+
The result depends only on the requested constructor, which we have already
4887+
recorded above.
4888+
''',
4889+
operation: () {
4890+
return constructors.firstWhereOrNull((e) => e.name == name);
4891+
},
4892+
);
48814893
}
48824894

48834895
@Deprecated('Use getNamedConstructor instead')

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

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,30 @@ class InstanceMethodIdMismatch extends RequirementFailure {
138138
}
139139
}
140140

141+
class InterfaceChildrenIdsMismatch extends RequirementFailure {
142+
final Uri libraryUri;
143+
final LookupName interfaceName;
144+
final String childrenPropertyName;
145+
final ManifestItemIdList expectedIds;
146+
final ManifestItemIdList actualIds;
147+
148+
InterfaceChildrenIdsMismatch({
149+
required this.libraryUri,
150+
required this.interfaceName,
151+
required this.childrenPropertyName,
152+
required this.expectedIds,
153+
required this.actualIds,
154+
});
155+
156+
@override
157+
String toString() {
158+
return 'InterfaceChildrenIdsMismatch(libraryUri: $libraryUri, '
159+
'interfaceName: ${interfaceName.asString}, '
160+
'childrenPropertyName: $childrenPropertyName, '
161+
'expectedIds: $expectedIds, actualIds: $actualIds)';
162+
}
163+
}
164+
141165
class InterfaceConstructorIdMismatch extends RequirementFailure {
142166
final Uri libraryUri;
143167
final LookupName interfaceName;

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

Lines changed: 52 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -260,36 +260,44 @@ class InterfaceItemRequirements {
260260
/// If the element was asked for its full interface.
261261
ManifestItemId? interfaceId;
262262

263-
final Map<LookupName, ManifestItemId?> constructors;
263+
/// Set if [InstanceElementImpl.constructors] is invoked.
264+
ManifestItemIdList? allDeclaredConstructors;
265+
266+
/// Requested with [InstanceElementImpl.getNamedConstructor].
267+
final Map<LookupName, ManifestItemId?> requestedConstructors;
264268

265269
/// These are "methods" in wide meaning: methods, getters, setters.
266270
final Map<LookupName, ManifestItemId?> methods;
267271

268272
InterfaceItemRequirements({
269273
required this.interfaceId,
270-
required this.constructors,
274+
required this.allDeclaredConstructors,
275+
required this.requestedConstructors,
271276
required this.methods,
272277
});
273278

274279
factory InterfaceItemRequirements.empty() {
275280
return InterfaceItemRequirements(
276281
interfaceId: null,
277-
constructors: {},
282+
allDeclaredConstructors: null,
283+
requestedConstructors: {},
278284
methods: {},
279285
);
280286
}
281287

282288
factory InterfaceItemRequirements.read(SummaryDataReader reader) {
283289
return InterfaceItemRequirements(
284290
interfaceId: ManifestItemId.readOptional(reader),
285-
constructors: reader.readNameToIdMap(),
291+
allDeclaredConstructors: ManifestItemIdList.readOptional(reader),
292+
requestedConstructors: reader.readNameToIdMap(),
286293
methods: reader.readNameToIdMap(),
287294
);
288295
}
289296

290297
void write(BufferedSink sink) {
291298
interfaceId.writeOptional(sink);
292-
sink.writeNameToIdMap(constructors);
299+
allDeclaredConstructors.writeOptional(sink);
300+
sink.writeNameToIdMap(requestedConstructors);
293301
sink.writeNameToIdMap(methods);
294302
}
295303
}
@@ -601,8 +609,8 @@ class RequirementsManifest {
601609
);
602610
}
603611

604-
var interfaceRequirements = interfaceEntry.value;
605-
if (interfaceRequirements.interfaceId case var expectedId?) {
612+
var requirements = interfaceEntry.value;
613+
if (requirements.interfaceId case var expectedId?) {
606614
var actualId = interfaceItem.interface.id;
607615
if (expectedId != actualId) {
608616
return InterfaceIdMismatch(
@@ -614,7 +622,21 @@ class RequirementsManifest {
614622
}
615623
}
616624

617-
var constructors = interfaceRequirements.constructors;
625+
if (requirements.allDeclaredConstructors case var required?) {
626+
var actualItems = interfaceItem.declaredConstructors.values;
627+
var actualIds = actualItems.map((item) => item.id);
628+
if (!required.equalToIterable(actualIds)) {
629+
return InterfaceChildrenIdsMismatch(
630+
libraryUri: libraryUri,
631+
interfaceName: interfaceName,
632+
childrenPropertyName: 'constructors',
633+
expectedIds: required,
634+
actualIds: ManifestItemIdList(actualIds.toList()),
635+
);
636+
}
637+
}
638+
639+
var constructors = requirements.requestedConstructors;
618640
for (var constructorEntry in constructors.entries) {
619641
var constructorName = constructorEntry.key;
620642
var constructorId = interfaceItem.getConstructorId(constructorName);
@@ -630,7 +652,7 @@ class RequirementsManifest {
630652
}
631653
}
632654

633-
var methods = interfaceRequirements.methods;
655+
var methods = requirements.methods;
634656
for (var methodEntry in methods.entries) {
635657
var methodName = methodEntry.key;
636658
var methodId = interfaceItem.getInterfaceMethodId(methodName);
@@ -694,6 +716,26 @@ class RequirementsManifest {
694716
}
695717
}
696718

719+
void record_instanceElement_constructors({
720+
required InterfaceElementImpl element,
721+
}) {
722+
if (_recordingLockLevel != 0) {
723+
return;
724+
}
725+
726+
var itemRequirements = _getInterfaceItem(element);
727+
if (itemRequirements == null) {
728+
return;
729+
}
730+
731+
var item = itemRequirements.item;
732+
var requirements = itemRequirements.requirements;
733+
734+
requirements.allDeclaredConstructors ??= ManifestItemIdList(
735+
item.declaredConstructors.values.map((item) => item.id).toList(),
736+
);
737+
}
738+
697739
void record_instanceElement_fields({required InstanceElementImpl element}) {
698740
if (_recordingLockLevel != 0) {
699741
return;
@@ -897,7 +939,7 @@ class RequirementsManifest {
897939

898940
var constructorName = name.asLookupName;
899941
var constructorId = item.getConstructorId(constructorName);
900-
requirements.constructors[constructorName] = constructorId;
942+
requirements.requestedConstructors[constructorName] = constructorId;
901943
}
902944

903945
void record_propertyAccessorElement_variable({

0 commit comments

Comments
 (0)