Skip to content

Commit 4683a0c

Browse files
scheglovCommit Queue
authored andcommitted
Fine. Support for mixins.
Change-Id: I0f264d3e96cb78641f17290d5875bf014f69bc08 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/421966 Reviewed-by: Paul Berry <[email protected]> Commit-Queue: Konstantin Shcheglov <[email protected]>
1 parent d85ab6d commit 4683a0c

File tree

4 files changed

+2372
-68
lines changed

4 files changed

+2372
-68
lines changed

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

Lines changed: 113 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -376,6 +376,40 @@ class LibraryManifestBuilder {
376376
);
377377
}
378378

379+
void _addMixin({
380+
required EncodeContext encodingContext,
381+
required Map<LookupName, TopLevelItem> newItems,
382+
required MixinElementImpl2 element,
383+
required LookupName lookupName,
384+
}) {
385+
var mixinItem = _getOrBuildElementItem(element, () {
386+
return MixinItem.fromElement(
387+
id: ManifestItemId.generate(),
388+
context: encodingContext,
389+
element: element,
390+
);
391+
});
392+
newItems[lookupName] = mixinItem;
393+
394+
encodingContext.withTypeParameters(
395+
element.typeParameters2,
396+
(typeParameters) {
397+
mixinItem.declaredMembers.clear();
398+
mixinItem.inheritedMembers.clear();
399+
_addInterfaceElementStaticExecutables(
400+
encodingContext: encodingContext,
401+
instanceElement: element,
402+
interfaceItem: mixinItem,
403+
);
404+
_addInterfaceElementInstanceExecutables(
405+
encodingContext: encodingContext,
406+
interfaceElement: element,
407+
interfaceItem: mixinItem,
408+
);
409+
},
410+
);
411+
}
412+
379413
void _addReExports() {
380414
for (var libraryElement in libraryElements) {
381415
var libraryUri = libraryElement.uri;
@@ -528,6 +562,13 @@ class LibraryManifestBuilder {
528562
element: element,
529563
lookupName: lookupName,
530564
);
565+
case MixinElementImpl2():
566+
_addMixin(
567+
encodingContext: encodingContext,
568+
newItems: newItems,
569+
element: element,
570+
lookupName: lookupName,
571+
);
531572
case SetterElementImpl():
532573
_addTopLevelSetter(
533574
encodingContext: encodingContext,
@@ -711,6 +752,10 @@ class _LibraryMatch {
711752
if (!_matchTopGetter(name: name, element: element)) {
712753
structureMismatched.add(element);
713754
}
755+
case MixinElementImpl2():
756+
if (!_matchMixin(name: name, element: element)) {
757+
structureMismatched.add(element);
758+
}
714759
case SetterElementImpl():
715760
if (!_matchTopSetter(name: name, element: element)) {
716761
structureMismatched.add(element);
@@ -752,19 +797,19 @@ class _LibraryMatch {
752797

753798
_addMatchingElementItem(element, item, matchContext);
754799

755-
_matchInterfaceConstructors(
800+
_matchInterfaceElementConstructors(
756801
matchContext: matchContext,
757802
interfaceElement: element,
758803
item: item,
759804
);
760805

761-
_matchStaticExecutables(
806+
_matchInstanceElementStaticExecutables(
762807
matchContext: matchContext,
763808
element: element,
764809
item: item,
765810
);
766811

767-
_matchInstanceExecutables(
812+
_matchInterfaceElementInstanceExecutables(
768813
matchContext: matchContext,
769814
element: element,
770815
item: item,
@@ -773,12 +818,16 @@ class _LibraryMatch {
773818
return true;
774819
}
775820

776-
bool _matchInstanceExecutable({
821+
bool _matchInstanceElementExecutable({
777822
required MatchContext interfaceMatchContext,
778823
required Map<LookupName, InstanceItemMemberItem> members,
779-
required LookupName lookupName,
780824
required ExecutableElementImpl2 executable,
781825
}) {
826+
var lookupName = executable.lookupName?.asLookupName;
827+
if (lookupName == null) {
828+
return true;
829+
}
830+
782831
var item = members[lookupName];
783832

784833
switch (executable) {
@@ -824,22 +873,22 @@ class _LibraryMatch {
824873
}
825874
}
826875

827-
void _matchInstanceExecutables({
876+
void _matchInstanceElementStaticExecutables({
828877
required MatchContext matchContext,
829-
required ClassElementImpl2 element,
830-
required ClassItem item,
878+
required InstanceElementImpl2 element,
879+
required InstanceItem item,
831880
}) {
832-
var map = element.inheritanceManager.getInterface2(element).map2;
833-
for (var entry in map.entries) {
834-
var nameObj = entry.key;
835-
var executable = entry.value;
836-
if (executable.enclosingElement2 == element) {
837-
// SAFETY: declared in the element are always impl.
838-
executable as ExecutableElementImpl2;
839-
if (!_matchInstanceExecutable(
881+
var executables = [
882+
...element.getters2,
883+
...element.methods2,
884+
...element.setters2,
885+
];
886+
887+
for (var executable in executables) {
888+
if (executable.isStatic) {
889+
if (!_matchInstanceElementExecutable(
840890
interfaceMatchContext: matchContext,
841891
members: item.declaredMembers,
842-
lookupName: nameObj.name.asLookupName,
843892
executable: executable,
844893
)) {
845894
structureMismatched.add(executable);
@@ -848,12 +897,12 @@ class _LibraryMatch {
848897
}
849898
}
850899

851-
bool _matchInterfaceConstructor({
900+
bool _matchInterfaceElementConstructor({
852901
required MatchContext interfaceMatchContext,
853902
required Map<LookupName, InstanceItemMemberItem> members,
854903
required ConstructorElementImpl2 element,
855904
}) {
856-
var lookupName = element.name3?.asLookupName;
905+
var lookupName = element.lookupName?.asLookupName;
857906
if (lookupName == null) {
858907
return false;
859908
}
@@ -872,13 +921,13 @@ class _LibraryMatch {
872921
return true;
873922
}
874923

875-
void _matchInterfaceConstructors({
924+
void _matchInterfaceElementConstructors({
876925
required MatchContext matchContext,
877-
required ClassElementImpl2 interfaceElement,
878-
required ClassItem item,
926+
required InterfaceElementImpl2 interfaceElement,
927+
required InterfaceItem item,
879928
}) {
880929
for (var constructor in interfaceElement.constructors2) {
881-
if (!_matchInterfaceConstructor(
930+
if (!_matchInterfaceElementConstructor(
882931
interfaceMatchContext: matchContext,
883932
members: item.declaredMembers,
884933
element: constructor,
@@ -888,60 +937,56 @@ class _LibraryMatch {
888937
}
889938
}
890939

891-
void _matchStaticExecutables({
940+
void _matchInterfaceElementInstanceExecutables({
892941
required MatchContext matchContext,
893-
required ClassElementImpl2 element,
894-
required ClassItem item,
942+
required InterfaceElementImpl2 element,
943+
required InterfaceItem item,
895944
}) {
896-
// TODO(scheglov): it looks that we repeat iterations
897-
// We do it for structural matching, and then for adding.
898-
for (var getter in element.getters2) {
899-
if (getter.isStatic) {
900-
var lookupName = getter.lookupName?.asLookupName;
901-
if (lookupName != null) {
902-
if (!_matchInstanceExecutable(
903-
interfaceMatchContext: matchContext,
904-
members: item.declaredMembers,
905-
lookupName: lookupName,
906-
executable: getter,
907-
)) {
908-
structureMismatched.add(getter);
909-
}
945+
var map = element.inheritanceManager.getInterface2(element).map2;
946+
for (var executable in map.values) {
947+
if (executable.enclosingElement2 == element) {
948+
// SAFETY: declared in the element are always impl.
949+
executable as ExecutableElementImpl2;
950+
if (!_matchInstanceElementExecutable(
951+
interfaceMatchContext: matchContext,
952+
members: item.declaredMembers,
953+
executable: executable,
954+
)) {
955+
structureMismatched.add(executable);
910956
}
911957
}
912958
}
959+
}
913960

914-
for (var method in element.methods2) {
915-
if (method.isStatic) {
916-
var lookupName = method.lookupName?.asLookupName;
917-
if (lookupName != null) {
918-
if (!_matchInstanceExecutable(
919-
interfaceMatchContext: matchContext,
920-
members: item.declaredMembers,
921-
lookupName: lookupName,
922-
executable: method,
923-
)) {
924-
structureMismatched.add(method);
925-
}
926-
}
927-
}
961+
bool _matchMixin({
962+
required LookupName? name,
963+
required MixinElementImpl2 element,
964+
}) {
965+
var item = manifest.items[name];
966+
if (item is! MixinItem) {
967+
return false;
928968
}
929969

930-
for (var setter in element.setters2) {
931-
if (setter.isStatic) {
932-
var lookupName = setter.lookupName?.asLookupName;
933-
if (lookupName != null) {
934-
if (!_matchInstanceExecutable(
935-
interfaceMatchContext: matchContext,
936-
members: item.declaredMembers,
937-
lookupName: lookupName,
938-
executable: setter,
939-
)) {
940-
structureMismatched.add(setter);
941-
}
942-
}
943-
}
970+
var matchContext = MatchContext(parent: null);
971+
if (!item.match(matchContext, element)) {
972+
return false;
944973
}
974+
975+
_addMatchingElementItem(element, item, matchContext);
976+
977+
_matchInstanceElementStaticExecutables(
978+
matchContext: matchContext,
979+
element: element,
980+
item: item,
981+
);
982+
983+
_matchInterfaceElementInstanceExecutables(
984+
matchContext: matchContext,
985+
element: element,
986+
item: item,
987+
);
988+
989+
return true;
945990
}
946991

947992
bool _matchTopFunction({

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

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -526,6 +526,72 @@ class ManifestMetadata {
526526
}
527527
}
528528

529+
class MixinItem extends InterfaceItem {
530+
final List<ManifestType> superclassConstraints;
531+
532+
MixinItem({
533+
required super.id,
534+
required super.metadata,
535+
required super.typeParameters,
536+
required super.supertype,
537+
required super.interfaces,
538+
required super.mixins,
539+
required super.declaredMembers,
540+
required super.inheritedMembers,
541+
required this.superclassConstraints,
542+
});
543+
544+
factory MixinItem.fromElement({
545+
required ManifestItemId id,
546+
required EncodeContext context,
547+
required MixinElementImpl2 element,
548+
}) {
549+
return context.withTypeParameters(
550+
element.typeParameters2,
551+
(typeParameters) {
552+
return MixinItem(
553+
id: id,
554+
metadata: ManifestMetadata.encode(context, element.metadata2),
555+
typeParameters: typeParameters,
556+
supertype: element.supertype?.encode(context),
557+
mixins: element.mixins.encode(context),
558+
interfaces: element.interfaces.encode(context),
559+
declaredMembers: {},
560+
inheritedMembers: {},
561+
superclassConstraints: element.superclassConstraints.encode(context),
562+
);
563+
},
564+
);
565+
}
566+
567+
factory MixinItem.read(SummaryDataReader reader) {
568+
return MixinItem(
569+
id: ManifestItemId.read(reader),
570+
metadata: ManifestMetadata.read(reader),
571+
typeParameters: ManifestTypeParameter.readList(reader),
572+
declaredMembers: InstanceItem._readDeclaredMembers(reader),
573+
supertype: ManifestType.readOptional(reader),
574+
mixins: ManifestType.readList(reader),
575+
interfaces: ManifestType.readList(reader),
576+
inheritedMembers: InterfaceItem._readInheritedMembers(reader),
577+
superclassConstraints: ManifestType.readList(reader),
578+
);
579+
}
580+
581+
@override
582+
bool match(MatchContext context, covariant MixinElementImpl2 element) {
583+
return super.match(context, element) &&
584+
superclassConstraints.match(context, element.superclassConstraints);
585+
}
586+
587+
@override
588+
void write(BufferedSink sink) {
589+
sink.writeEnum(_ManifestItemKind.mixin_);
590+
super.write(sink);
591+
superclassConstraints.writeList(sink);
592+
}
593+
}
594+
529595
class TopLevelFunctionItem extends TopLevelItem {
530596
final ManifestFunctionType functionType;
531597

@@ -638,6 +704,8 @@ sealed class TopLevelItem extends ManifestItem {
638704
switch (kind) {
639705
case _ManifestItemKind.class_:
640706
return ClassItem.read(reader);
707+
case _ManifestItemKind.mixin_:
708+
return MixinItem.read(reader);
641709
case _ManifestItemKind.topLevelFunction:
642710
return TopLevelFunctionItem.read(reader);
643711
case _ManifestItemKind.topLevelGetter:
@@ -699,6 +767,7 @@ class TopLevelSetterItem extends TopLevelItem {
699767

700768
enum _ManifestItemKind {
701769
class_,
770+
mixin_,
702771
topLevelFunction,
703772
topLevelGetter,
704773
topLevelSetter,

0 commit comments

Comments
 (0)