Skip to content

Commit 717257b

Browse files
scheglovCommit Queue
authored andcommitted
Fine. Store inherited items separately.
We store only IDs of inherited members, without type substitution, because any code that sees substitution also depends on the type arguments provided to the class that declares these members. Change-Id: I7f04555cec9998d0d4ac3eea166ff5f02848b326 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/421585 Commit-Queue: Konstantin Shcheglov <[email protected]> Reviewed-by: Paul Berry <[email protected]>
1 parent 9334e8b commit 717257b

File tree

6 files changed

+1799
-590
lines changed

6 files changed

+1799
-590
lines changed

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

Lines changed: 85 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ class LibraryManifestBuilder {
8686
///
8787
/// It is filled initially during matching element structures.
8888
/// Then we remove those that affected by changed elements.
89-
final Map<Element2, ManifestItem> itemMap = Map.identity();
89+
final Map<Element2, ManifestItem> declaredItems = Map.identity();
9090

9191
/// The new manifests for libraries.
9292
final Map<Uri, LibraryManifest> newManifests = {};
@@ -136,7 +136,8 @@ class LibraryManifestBuilder {
136136
encodingContext.withTypeParameters(
137137
element.typeParameters2,
138138
(typeParameters) {
139-
classItem.members.clear();
139+
classItem.declaredMembers.clear();
140+
classItem.inheritedMembers.clear();
140141
_addInterfaceElementStaticExecutables(
141142
encodingContext: encodingContext,
142143
instanceElement: element,
@@ -151,6 +152,44 @@ class LibraryManifestBuilder {
151152
);
152153
}
153154

155+
void _addInheritedInterfaceElementExecutables(InterfaceElementImpl2 element) {
156+
// We don't create items for elements without name.
157+
if (element.lookupName == null) {
158+
return;
159+
}
160+
161+
// Must be created already.
162+
var item = declaredItems[element] as InterfaceItem;
163+
164+
var map = element.inheritanceManager.getInterface2(element).map2;
165+
for (var entry in map.entries) {
166+
var executable = entry.value.baseElement;
167+
168+
// Add only inherited.
169+
if (executable.enclosingElement2 == element) {
170+
continue;
171+
}
172+
173+
var lookupName = executable.lookupName?.asLookupName;
174+
if (lookupName == null) {
175+
continue;
176+
}
177+
178+
var id = _getInterfaceElementMemberId(executable);
179+
item.inheritedMembers[lookupName] = id;
180+
}
181+
}
182+
183+
void _addInheritedInterfaceElementsExecutables() {
184+
for (var libraryElement in libraryElements) {
185+
for (var element in libraryElement.children2) {
186+
if (element is InterfaceElementImpl2) {
187+
_addInheritedInterfaceElementExecutables(element);
188+
}
189+
}
190+
}
191+
}
192+
154193
void _addInstanceElementGetter({
155194
required EncodeContext encodingContext,
156195
required InstanceItem instanceItem,
@@ -168,7 +207,7 @@ class LibraryManifestBuilder {
168207
element: element,
169208
);
170209
});
171-
instanceItem.members[lookupName] = item;
210+
instanceItem.declaredMembers[lookupName] = item;
172211
}
173212

174213
void _addInstanceElementInstanceExecutable({
@@ -210,7 +249,7 @@ class LibraryManifestBuilder {
210249
element: element,
211250
);
212251
});
213-
instanceItem.members[lookupName] = item;
252+
instanceItem.declaredMembers[lookupName] = item;
214253
}
215254

216255
void _addInstanceElementStaticExecutables({
@@ -256,7 +295,7 @@ class LibraryManifestBuilder {
256295
element: element,
257296
);
258297
});
259-
interfaceItem.members[lookupName] = item;
298+
interfaceItem.declaredMembers[lookupName] = item;
260299
}
261300

262301
void _addInterfaceElementInstanceExecutables({
@@ -267,11 +306,16 @@ class LibraryManifestBuilder {
267306
var inheritance = interfaceElement.inheritanceManager;
268307
var map = inheritance.getInterface2(interfaceElement).map2;
269308
for (var entry in map.entries) {
270-
_addInstanceElementInstanceExecutable(
271-
encodingContext: encodingContext,
272-
instanceItem: interfaceItem,
273-
element: entry.value,
274-
);
309+
var executable = entry.value;
310+
if (executable.enclosingElement2 == interfaceElement) {
311+
// SAFETY: declared in the element are always impl.
312+
executable as ExecutableElementImpl2;
313+
_addInstanceElementInstanceExecutable(
314+
encodingContext: encodingContext,
315+
instanceItem: interfaceItem,
316+
element: executable,
317+
);
318+
}
275319
}
276320
}
277321

@@ -473,6 +517,8 @@ class LibraryManifestBuilder {
473517
newManifests[libraryUri] = newManifest;
474518
}
475519

520+
_addInheritedInterfaceElementsExecutables();
521+
476522
return newManifests;
477523
}
478524

@@ -491,15 +537,15 @@ class LibraryManifestBuilder {
491537
_LibraryMatch(
492538
manifest: manifest,
493539
library: libraryElement,
494-
itemMap: itemMap,
540+
itemMap: declaredItems,
495541
structureMismatched: affectedElements,
496542
refElementsMap: refElementsMap,
497543
refExternalIds: refExternalIds,
498544
).compareStructures();
499545
}
500546

501547
performance
502-
..getDataInt('structureMatchedCount').add(itemMap.length)
548+
..getDataInt('structureMatchedCount').add(declaredItems.length)
503549
..getDataInt('structureMismatchedCount').add(affectedElements.length);
504550

505551
// Propagate invalidation from referenced elements.
@@ -514,7 +560,7 @@ class LibraryManifestBuilder {
514560
// Move the element to affected.
515561
// Its dependencies are not interesting anymore.
516562
affectedElements.add(element);
517-
itemMap.remove(element);
563+
declaredItems.remove(element);
518564
refElementsMap.remove(element);
519565
break;
520566
}
@@ -526,7 +572,7 @@ class LibraryManifestBuilder {
526572
// Move the element to affected.
527573
// Its dependencies are not interesting anymore.
528574
affectedElements.add(element);
529-
itemMap.remove(element);
575+
declaredItems.remove(element);
530576
refElementsMap.remove(element);
531577
break;
532578
}
@@ -536,7 +582,7 @@ class LibraryManifestBuilder {
536582
}
537583

538584
performance
539-
..getDataInt('transitiveMatchedCount').add(itemMap.length)
585+
..getDataInt('transitiveMatchedCount').add(declaredItems.length)
540586
..getDataInt('transitiveAffectedCount').add(affectedElements.length);
541587
}
542588

@@ -545,7 +591,14 @@ class LibraryManifestBuilder {
545591
return inputManifests[uri] ?? LibraryManifest(reExportMap: {}, items: {});
546592
}
547593

548-
/// Returns either the existing item from [itemMap], or builds a new one.
594+
ManifestItemId _getInterfaceElementMemberId(ExecutableElementImpl2 element) {
595+
if (declaredItems[element] case var declaredItem?) {
596+
return declaredItem.id;
597+
}
598+
return elementFactory.getElementId(element)!;
599+
}
600+
601+
/// Returns either the existing item from [declaredItems], or builds a new one.
549602
Item _getOrBuildElementItem<Element extends Element2,
550603
Item extends ManifestItem>(
551604
Element element,
@@ -554,11 +607,11 @@ class LibraryManifestBuilder {
554607
// We assume that when matching elements against the structure of
555608
// the item, we put into [itemMap] only the type of the item that
556609
// corresponds the type of the element.
557-
var item = itemMap[element] as Item?;
610+
var item = declaredItems[element] as Item?;
558611
if (item == null) {
559612
item = build();
560613
// To reuse items for inherited members.
561-
itemMap[element] = item;
614+
declaredItems[element] = item;
562615
}
563616
return item;
564617
}
@@ -726,13 +779,17 @@ class _LibraryMatch {
726779
for (var entry in map.entries) {
727780
var nameObj = entry.key;
728781
var executable = entry.value;
729-
if (!_matchInstanceExecutable(
730-
interfaceMatchContext: matchContext,
731-
members: item.members,
732-
lookupName: nameObj.name.asLookupName,
733-
executable: executable,
734-
)) {
735-
structureMismatched.add(executable);
782+
if (executable.enclosingElement2 == element) {
783+
// SAFETY: declared in the element are always impl.
784+
executable as ExecutableElementImpl2;
785+
if (!_matchInstanceExecutable(
786+
interfaceMatchContext: matchContext,
787+
members: item.declaredMembers,
788+
lookupName: nameObj.name.asLookupName,
789+
executable: executable,
790+
)) {
791+
structureMismatched.add(executable);
792+
}
736793
}
737794
}
738795
}
@@ -771,7 +828,7 @@ class _LibraryMatch {
771828
for (var constructor in interfaceElement.constructors2) {
772829
if (!_matchInterfaceConstructor(
773830
interfaceMatchContext: matchContext,
774-
members: item.members,
831+
members: item.declaredMembers,
775832
element: constructor,
776833
)) {
777834
structureMismatched.add(constructor);
@@ -792,7 +849,7 @@ class _LibraryMatch {
792849
if (lookupName != null) {
793850
if (!_matchInstanceExecutable(
794851
interfaceMatchContext: matchContext,
795-
members: item.members,
852+
members: item.declaredMembers,
796853
lookupName: lookupName,
797854
executable: getters,
798855
)) {
@@ -808,7 +865,7 @@ class _LibraryMatch {
808865
if (lookupName != null) {
809866
if (!_matchInstanceExecutable(
810867
interfaceMatchContext: matchContext,
811-
members: item.members,
868+
members: item.declaredMembers,
812869
lookupName: lookupName,
813870
executable: method,
814871
)) {

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

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -226,14 +226,14 @@ class MatchContext {
226226

227227
extension LinkedElementFactoryExtension on LinkedElementFactory {
228228
/// Returns the id of [element], or `null` if from this bundle.
229-
ManifestItemId? getElementId(Element2 element2) {
229+
ManifestItemId? getElementId(Element2 element) {
230230
Element2 topLevelElement;
231231
Element2? memberElement;
232-
if (element2.enclosingElement2 is LibraryElement2) {
233-
topLevelElement = element2;
232+
if (element.enclosingElement2 is LibraryElement2) {
233+
topLevelElement = element;
234234
} else {
235-
topLevelElement = element2.enclosingElement2!;
236-
memberElement = element2;
235+
topLevelElement = element.enclosingElement2!;
236+
memberElement = element;
237237
}
238238

239239
// SAFETY: if we can reference the element, it is in a library.
@@ -261,9 +261,9 @@ extension LinkedElementFactoryExtension on LinkedElementFactory {
261261
// TODO(scheglov): When implementation is complete, cast unconditionally.
262262
if (topLevelItem is InstanceItem) {
263263
var memberName = memberElement.lookupName!.asLookupName;
264-
var memberItem = topLevelItem.members[memberName];
264+
var memberId = topLevelItem.getMemberId(memberName);
265265
// TODO(scheglov): When implementation is complete, null assert.
266-
return memberItem?.id;
266+
return memberId;
267267
}
268268

269269
return null;

0 commit comments

Comments
 (0)