[kernel] Add ExtensionTypeDeclaration.procedures

This adds a list of `Procedure`s to `ExtensionTypeDeclaration`. This is
meant to model representation fields and combined member signatures
computed from inherited non-extension type members.

These are not meant to be handled by the backends. The combined
member signature can be the interface target of an `InstanceInvocation`
expression but will always have a `.memberSignatureOrigin` value from
one of the original class members.

TEST=existing

Change-Id: I87768ed75a3c7126b0a30f8ccf06e46678c56db6
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/330301
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Reviewed-by: Srujan Gaddam <srujzs@google.com>
Reviewed-by: Jens Johansen <jensj@google.com>
Commit-Queue: Johnni Winther <johnniwinther@google.com>
This commit is contained in:
Johnni Winther 2023-10-13 07:42:29 +00:00 committed by Commit Queue
parent 06ab207091
commit f87142fdc2
27 changed files with 260 additions and 166 deletions

View file

@ -254,7 +254,7 @@ extension ExtensionMemberDescriptorExtension on ExtensionMemberDescriptor {
bool get isSetter => kind == ExtensionMemberKind.Setter; bool get isSetter => kind == ExtensionMemberKind.Setter;
bool get isMethod => kind == ExtensionMemberKind.Method; bool get isMethod => kind == ExtensionMemberKind.Method;
bool get isExternal => (member.asProcedure).isExternal; bool get isExternal => (memberReference.asProcedure).isExternal;
} }
extension ProcedureExtension on Procedure { extension ProcedureExtension on Procedure {

View file

@ -714,8 +714,8 @@ class ExtensionIndex {
void _indexExtensions(Library library) { void _indexExtensions(Library library) {
if (_processedExtensionLibraries.contains(library)) return; if (_processedExtensionLibraries.contains(library)) return;
for (var extension in library.extensions) { for (var extension in library.extensions) {
for (var descriptor in extension.members) { for (var descriptor in extension.memberDescriptors) {
var reference = descriptor.member; var reference = descriptor.memberReference;
var onType = extension.onType; var onType = extension.onType;
bool isInteropOnType = false; bool isInteropOnType = false;
Annotatable? cls; Annotatable? cls;
@ -738,7 +738,7 @@ class ExtensionIndex {
_extensionMemberIndex[reference] = descriptor; _extensionMemberIndex[reference] = descriptor;
_extensionAnnotatableIndex[reference] = cls!; _extensionAnnotatableIndex[reference] = cls!;
_extensionIndex[reference] = extension; _extensionIndex[reference] = extension;
final tearOffReference = descriptor.tearOff; final tearOffReference = descriptor.tearOffReference;
if (tearOffReference != null) { if (tearOffReference != null) {
_extensionMemberIndex[tearOffReference] = descriptor; _extensionMemberIndex[tearOffReference] = descriptor;
_extensionIndex[tearOffReference] = extension; _extensionIndex[tearOffReference] = extension;
@ -832,11 +832,11 @@ class ExtensionIndex {
if (_processedExtensionTypeLibraries.contains(library)) return; if (_processedExtensionTypeLibraries.contains(library)) return;
for (var extensionType in library.extensionTypeDeclarations) { for (var extensionType in library.extensionTypeDeclarations) {
if (isInteropExtensionType(extensionType)) { if (isInteropExtensionType(extensionType)) {
for (var descriptor in extensionType.members) { for (var descriptor in extensionType.memberDescriptors) {
final reference = descriptor.member; final reference = descriptor.memberReference;
_extensionTypeMemberIndex[reference] = descriptor; _extensionTypeMemberIndex[reference] = descriptor;
_extensionTypeIndex[reference] = extensionType; _extensionTypeIndex[reference] = extensionType;
final tearOffReference = descriptor.tearOff; final tearOffReference = descriptor.tearOffReference;
if (tearOffReference != null) { if (tearOffReference != null) {
_extensionTypeMemberIndex[tearOffReference] = descriptor; _extensionTypeMemberIndex[tearOffReference] = descriptor;
_extensionTypeIndex[tearOffReference] = extensionType; _extensionTypeIndex[tearOffReference] = extensionType;

View file

@ -199,7 +199,7 @@ class StaticInteropMockValidator {
// setters return their return and parameter types, respectively. // setters return their return and parameter types, respectively.
DartType _getTypeOfDescriptor(ExtensionMemberDescriptor interopDescriptor) { DartType _getTypeOfDescriptor(ExtensionMemberDescriptor interopDescriptor) {
// CFE creates static procedures for each extension member. // CFE creates static procedures for each extension member.
var interopMember = interopDescriptor.member.asProcedure; var interopMember = interopDescriptor.memberReference.asProcedure;
if (interopDescriptor.isGetter) { if (interopDescriptor.isGetter) {
return interopMember.function.returnType; return interopMember.function.returnType;
@ -325,7 +325,7 @@ class StaticInteropMockValidator {
var extensions = _staticInteropClassesWithExtensions[cls.reference]; var extensions = _staticInteropClassesWithExtensions[cls.reference];
if (extensions != null) { if (extensions != null) {
for (var extension in extensions) { for (var extension in extensions) {
for (var descriptor in extension.members) { for (var descriptor in extension.memberDescriptors) {
if (!descriptor.isExternal || descriptor.isStatic) continue; if (!descriptor.isExternal || descriptor.isStatic) continue;
// No need to handle external fields - they are transformed to // No need to handle external fields - they are transformed to
// external getters/setters by the CFE. // external getters/setters by the CFE.
@ -336,7 +336,8 @@ class StaticInteropMockValidator {
} }
_descriptorToExtensionName[descriptor] = _descriptorToExtensionName[descriptor] =
extension.isUnnamedExtension ? '<unnamed>' : extension.name; extension.isUnnamedExtension ? '<unnamed>' : extension.name;
var name = js_interop.getJSName(descriptor.member.asMember); var name =
js_interop.getJSName(descriptor.memberReference.asMember);
if (name.isEmpty) name = descriptor.name.text; if (name.isEmpty) name = descriptor.name.text;
exportNameToDescriptors! exportNameToDescriptors!
.putIfAbsent(name, () => {}) .putIfAbsent(name, () => {})

View file

@ -77,9 +77,10 @@ String? computeKernelElementNameForSourceMaps(
String _findExtensionMemberName(ir.Member member) { String _findExtensionMemberName(ir.Member member) {
assert(member.isExtensionMember); assert(member.isExtensionMember);
for (ir.Extension extension in member.enclosingLibrary.extensions) { for (ir.Extension extension in member.enclosingLibrary.extensions) {
for (ir.ExtensionMemberDescriptor descriptor in extension.members) { for (ir.ExtensionMemberDescriptor descriptor
if (descriptor.member == member.reference || in extension.memberDescriptors) {
descriptor.tearOff == member.reference) { if (descriptor.memberReference == member.reference ||
descriptor.tearOffReference == member.reference) {
String extensionName; String extensionName;
// Anonymous extensions contain a # on their synthetic name. // Anonymous extensions contain a # on their synthetic name.
if (extension.name.contains('#')) { if (extension.name.contains('#')) {

View file

@ -32,20 +32,20 @@ class DillExtensionBuilder extends ExtensionBuilderImpl {
parent: parent.scope, parent: parent.scope,
debugName: "extension ${extension.name}", debugName: "extension ${extension.name}",
isModifiable: false)) { isModifiable: false)) {
for (ExtensionMemberDescriptor descriptor in extension.members) { for (ExtensionMemberDescriptor descriptor in extension.memberDescriptors) {
Name name = descriptor.name; Name name = descriptor.name;
switch (descriptor.kind) { switch (descriptor.kind) {
case ExtensionMemberKind.Method: case ExtensionMemberKind.Method:
if (descriptor.isStatic) { if (descriptor.isStatic) {
Procedure procedure = descriptor.member.asProcedure; Procedure procedure = descriptor.memberReference.asProcedure;
scope.addLocalMember( scope.addLocalMember(
name.text, name.text,
new DillExtensionStaticMethodBuilder( new DillExtensionStaticMethodBuilder(
procedure, descriptor, this), procedure, descriptor, this),
setter: false); setter: false);
} else { } else {
Procedure procedure = descriptor.member.asProcedure; Procedure procedure = descriptor.memberReference.asProcedure;
Procedure? tearOff = descriptor.tearOff?.asProcedure; Procedure? tearOff = descriptor.tearOffReference?.asProcedure;
assert(tearOff != null, "No tear found for ${descriptor}"); assert(tearOff != null, "No tear found for ${descriptor}");
scope.addLocalMember( scope.addLocalMember(
name.text, name.text,
@ -55,25 +55,25 @@ class DillExtensionBuilder extends ExtensionBuilderImpl {
} }
break; break;
case ExtensionMemberKind.Getter: case ExtensionMemberKind.Getter:
Procedure procedure = descriptor.member.asProcedure; Procedure procedure = descriptor.memberReference.asProcedure;
scope.addLocalMember(name.text, scope.addLocalMember(name.text,
new DillExtensionGetterBuilder(procedure, descriptor, this), new DillExtensionGetterBuilder(procedure, descriptor, this),
setter: false); setter: false);
break; break;
case ExtensionMemberKind.Field: case ExtensionMemberKind.Field:
Field field = descriptor.member.asField; Field field = descriptor.memberReference.asField;
scope.addLocalMember( scope.addLocalMember(
name.text, new DillExtensionFieldBuilder(field, descriptor, this), name.text, new DillExtensionFieldBuilder(field, descriptor, this),
setter: false); setter: false);
break; break;
case ExtensionMemberKind.Setter: case ExtensionMemberKind.Setter:
Procedure procedure = descriptor.member.asProcedure; Procedure procedure = descriptor.memberReference.asProcedure;
scope.addLocalMember(name.text, scope.addLocalMember(name.text,
new DillExtensionSetterBuilder(procedure, descriptor, this), new DillExtensionSetterBuilder(procedure, descriptor, this),
setter: true); setter: true);
break; break;
case ExtensionMemberKind.Operator: case ExtensionMemberKind.Operator:
Procedure procedure = descriptor.member.asProcedure; Procedure procedure = descriptor.memberReference.asProcedure;
scope.addLocalMember(name.text, scope.addLocalMember(name.text,
new DillExtensionOperatorBuilder(procedure, descriptor, this), new DillExtensionOperatorBuilder(procedure, descriptor, this),
setter: false); setter: false);

View file

@ -43,20 +43,20 @@ class DillExtensionTypeDeclarationBuilder
new ConstructorScope( new ConstructorScope(
_extensionTypeDeclaration.name, <String, MemberBuilder>{})) { _extensionTypeDeclaration.name, <String, MemberBuilder>{})) {
for (ExtensionTypeMemberDescriptor descriptor for (ExtensionTypeMemberDescriptor descriptor
in _extensionTypeDeclaration.members) { in _extensionTypeDeclaration.memberDescriptors) {
Name name = descriptor.name; Name name = descriptor.name;
switch (descriptor.kind) { switch (descriptor.kind) {
case ExtensionTypeMemberKind.Method: case ExtensionTypeMemberKind.Method:
if (descriptor.isStatic) { if (descriptor.isStatic) {
Procedure procedure = descriptor.member.asProcedure; Procedure procedure = descriptor.memberReference.asProcedure;
scope.addLocalMember( scope.addLocalMember(
name.text, name.text,
new DillExtensionTypeStaticMethodBuilder( new DillExtensionTypeStaticMethodBuilder(
procedure, descriptor, this), procedure, descriptor, this),
setter: false); setter: false);
} else { } else {
Procedure procedure = descriptor.member.asProcedure; Procedure procedure = descriptor.memberReference.asProcedure;
Procedure? tearOff = descriptor.tearOff?.asProcedure; Procedure? tearOff = descriptor.tearOffReference?.asProcedure;
assert(tearOff != null, "No tear found for ${descriptor}"); assert(tearOff != null, "No tear found for ${descriptor}");
scope.addLocalMember( scope.addLocalMember(
name.text, name.text,
@ -66,32 +66,32 @@ class DillExtensionTypeDeclarationBuilder
} }
break; break;
case ExtensionTypeMemberKind.Getter: case ExtensionTypeMemberKind.Getter:
Procedure procedure = descriptor.member.asProcedure; Procedure procedure = descriptor.memberReference.asProcedure;
scope.addLocalMember(name.text, scope.addLocalMember(name.text,
new DillExtensionTypeGetterBuilder(procedure, descriptor, this), new DillExtensionTypeGetterBuilder(procedure, descriptor, this),
setter: false); setter: false);
break; break;
case ExtensionTypeMemberKind.Field: case ExtensionTypeMemberKind.Field:
Field field = descriptor.member.asField; Field field = descriptor.memberReference.asField;
scope.addLocalMember(name.text, scope.addLocalMember(name.text,
new DillExtensionTypeFieldBuilder(field, descriptor, this), new DillExtensionTypeFieldBuilder(field, descriptor, this),
setter: false); setter: false);
break; break;
case ExtensionTypeMemberKind.Setter: case ExtensionTypeMemberKind.Setter:
Procedure procedure = descriptor.member.asProcedure; Procedure procedure = descriptor.memberReference.asProcedure;
scope.addLocalMember(name.text, scope.addLocalMember(name.text,
new DillExtensionTypeSetterBuilder(procedure, descriptor, this), new DillExtensionTypeSetterBuilder(procedure, descriptor, this),
setter: true); setter: true);
break; break;
case ExtensionTypeMemberKind.Operator: case ExtensionTypeMemberKind.Operator:
Procedure procedure = descriptor.member.asProcedure; Procedure procedure = descriptor.memberReference.asProcedure;
scope.addLocalMember(name.text, scope.addLocalMember(name.text,
new DillExtensionTypeOperatorBuilder(procedure, descriptor, this), new DillExtensionTypeOperatorBuilder(procedure, descriptor, this),
setter: false); setter: false);
break; break;
case ExtensionTypeMemberKind.Constructor: case ExtensionTypeMemberKind.Constructor:
Procedure procedure = descriptor.member.asProcedure; Procedure procedure = descriptor.memberReference.asProcedure;
Procedure? tearOff = descriptor.tearOff?.asProcedure; Procedure? tearOff = descriptor.tearOffReference?.asProcedure;
constructorScope.addLocalMember( constructorScope.addLocalMember(
name.text, name.text,
new DillExtensionTypeConstructorBuilder( new DillExtensionTypeConstructorBuilder(
@ -99,8 +99,8 @@ class DillExtensionTypeDeclarationBuilder
break; break;
case ExtensionTypeMemberKind.Factory: case ExtensionTypeMemberKind.Factory:
case ExtensionTypeMemberKind.RedirectingFactory: case ExtensionTypeMemberKind.RedirectingFactory:
Procedure procedure = descriptor.member.asProcedure; Procedure procedure = descriptor.memberReference.asProcedure;
Procedure? tearOff = descriptor.tearOff?.asProcedure; Procedure? tearOff = descriptor.tearOffReference?.asProcedure;
constructorScope.addLocalMember( constructorScope.addLocalMember(
name.text, name.text,
new DillExtensionTypeFactoryBuilder( new DillExtensionTypeFactoryBuilder(

View file

@ -149,10 +149,10 @@ class SourceExtensionBuilder extends ExtensionBuilderImpl
kind = ExtensionMemberKind.Operator; kind = ExtensionMemberKind.Operator;
break; break;
} }
extension.members.add(new ExtensionMemberDescriptor( extension.memberDescriptors.add(new ExtensionMemberDescriptor(
name: new Name(name, libraryBuilder.library), name: new Name(name, libraryBuilder.library),
member: memberReference, memberReference: memberReference,
tearOff: tearOffReference, tearOffReference: tearOffReference,
isStatic: memberBuilder.isStatic, isStatic: memberBuilder.isStatic,
kind: kind)); kind: kind));
} }

View file

@ -503,12 +503,13 @@ class SourceExtensionTypeDeclarationBuilder
kind = ExtensionTypeMemberKind.Operator; kind = ExtensionTypeMemberKind.Operator;
break; break;
} }
extensionTypeDeclaration.members.add(new ExtensionTypeMemberDescriptor( extensionTypeDeclaration.memberDescriptors.add(
name: new Name(name, libraryBuilder.library), new ExtensionTypeMemberDescriptor(
member: memberReference, name: new Name(name, libraryBuilder.library),
tearOff: tearOffReference, memberReference: memberReference,
isStatic: memberBuilder.isStatic, tearOffReference: tearOffReference,
kind: kind)); isStatic: memberBuilder.isStatic,
kind: kind));
} }
@override @override

View file

@ -986,33 +986,33 @@ abstract class InferenceVisitorBase implements InferenceVisitor {
Member? targetTearoff; Member? targetTearoff;
ProcedureKind? targetKind; ProcedureKind? targetKind;
for (ExtensionTypeMemberDescriptor descriptor for (ExtensionTypeMemberDescriptor descriptor
in extensionType.extensionTypeDeclaration.members) { in extensionType.extensionTypeDeclaration.memberDescriptors) {
if (descriptor.name == name) { if (descriptor.name == name) {
switch (descriptor.kind) { switch (descriptor.kind) {
case ExtensionTypeMemberKind.Method: case ExtensionTypeMemberKind.Method:
if (!isSetter) { if (!isSetter) {
targetMember = descriptor.member.asMember; targetMember = descriptor.memberReference.asMember;
targetTearoff = descriptor.tearOff?.asMember; targetTearoff = descriptor.tearOffReference?.asMember;
targetKind = ProcedureKind.Method; targetKind = ProcedureKind.Method;
} }
break; break;
case ExtensionTypeMemberKind.Getter: case ExtensionTypeMemberKind.Getter:
if (!isSetter) { if (!isSetter) {
targetMember = descriptor.member.asMember; targetMember = descriptor.memberReference.asMember;
targetTearoff = null; targetTearoff = null;
targetKind = ProcedureKind.Getter; targetKind = ProcedureKind.Getter;
} }
break; break;
case ExtensionTypeMemberKind.Setter: case ExtensionTypeMemberKind.Setter:
if (isSetter) { if (isSetter) {
targetMember = descriptor.member.asMember; targetMember = descriptor.memberReference.asMember;
targetTearoff = null; targetTearoff = null;
targetKind = ProcedureKind.Setter; targetKind = ProcedureKind.Setter;
} }
break; break;
case ExtensionTypeMemberKind.Operator: case ExtensionTypeMemberKind.Operator:
if (!isSetter) { if (!isSetter) {
targetMember = descriptor.member.asMember; targetMember = descriptor.memberReference.asMember;
targetTearoff = null; targetTearoff = null;
targetKind = ProcedureKind.Operator; targetKind = ProcedureKind.Operator;
} }

View file

@ -853,9 +853,9 @@ List<String> extensionMethodDescriptorToText(
} }
return [ return [
descriptorToText(descriptor.member, forTearOff: false), descriptorToText(descriptor.memberReference, forTearOff: false),
if (descriptor.tearOff != null) if (descriptor.tearOffReference != null)
descriptorToText(descriptor.tearOff!, forTearOff: true), descriptorToText(descriptor.tearOffReference!, forTearOff: true),
]; ];
} }

View file

@ -217,7 +217,7 @@ class ExtensionsDataExtractor extends CfeDataExtractor<Features> {
features.addElement( features.addElement(
Tags.extensionTypeParameters, typeParameterToText(typeParameter)); Tags.extensionTypeParameters, typeParameterToText(typeParameter));
} }
for (ExtensionMemberDescriptor descriptor in extension.members) { for (ExtensionMemberDescriptor descriptor in extension.memberDescriptors) {
for (String text in extensionMethodDescriptorToText(descriptor)) { for (String text in extensionMethodDescriptorToText(descriptor)) {
features.addElement(Tags.extensionMembers, text); features.addElement(Tags.extensionMembers, text);
} }

View file

@ -400,6 +400,7 @@ dereferencing
deregister deregister
descent descent
descriptive descriptive
descriptors
deserializable deserializable
deserializer deserializer
deserializers deserializers

View file

@ -117,6 +117,7 @@ const Map<String?, Map<String, FieldRule?>> _fieldRuleMap = {
}, },
'ExtensionTypeDeclaration': { 'ExtensionTypeDeclaration': {
'typeParameters': FieldRule(isDeclaration: true), 'typeParameters': FieldRule(isDeclaration: true),
'_procedures': FieldRule(name: 'procedures'),
}, },
'Field': { 'Field': {
'reference': FieldRule(name: 'fieldReference'), 'reference': FieldRule(name: 'fieldReference'),

View file

@ -147,7 +147,7 @@ type CanonicalName {
type ComponentFile { type ComponentFile {
UInt32 magic = 0x90ABCDEF; UInt32 magic = 0x90ABCDEF;
UInt32 formatVersion = 111; UInt32 formatVersion = 112;
Byte[10] shortSdkHash; Byte[10] shortSdkHash;
List<String> problemsAsJson; // Described in problems.md. List<String> problemsAsJson; // Described in problems.md.
Library[] libraries; Library[] libraries;
@ -374,6 +374,7 @@ type ExtensionTypeDeclaration extends Node {
DartType declaredRepresentationType; DartType declaredRepresentationType;
StringReference representationName; StringReference representationName;
List<DartType> implements; List<DartType> implements;
List<Procedure> procedures;
List<ExtensionTypeMemberKind> members; List<ExtensionTypeMemberKind> members;
} }

View file

@ -1570,7 +1570,7 @@ class Extension extends NamedNode
/// ///
/// The members are converted into top-level members and only accessible /// The members are converted into top-level members and only accessible
/// by reference through [ExtensionMemberDescriptor]. /// by reference through [ExtensionMemberDescriptor].
List<ExtensionMemberDescriptor> members; List<ExtensionMemberDescriptor> memberDescriptors;
@override @override
List<Expression> annotations = const <Expression>[]; List<Expression> annotations = const <Expression>[];
@ -1594,11 +1594,12 @@ class Extension extends NamedNode
{required this.name, {required this.name,
List<TypeParameter>? typeParameters, List<TypeParameter>? typeParameters,
DartType? onType, DartType? onType,
List<ExtensionMemberDescriptor>? members, List<ExtensionMemberDescriptor>? memberDescriptors,
required this.fileUri, required this.fileUri,
Reference? reference}) Reference? reference})
: this.typeParameters = typeParameters ?? <TypeParameter>[], : this.typeParameters = typeParameters ?? <TypeParameter>[],
this.members = members ?? <ExtensionMemberDescriptor>[], this.memberDescriptors =
memberDescriptors ?? <ExtensionMemberDescriptor>[],
super(reference) { super(reference) {
setParents(this.typeParameters, this); setParents(this.typeParameters, this);
if (onType != null) { if (onType != null) {
@ -1722,18 +1723,18 @@ class ExtensionMemberDescriptor {
int flags = 0; int flags = 0;
/// Reference to the top-level member created for the extension method. /// Reference to the top-level member created for the extension method.
final Reference member; final Reference memberReference;
/// Reference to the top-level member created for the extension member tear /// Reference to the top-level member created for the extension member tear
/// off, if any. /// off, if any.
final Reference? tearOff; final Reference? tearOffReference;
ExtensionMemberDescriptor( ExtensionMemberDescriptor(
{required this.name, {required this.name,
required this.kind, required this.kind,
bool isStatic = false, bool isStatic = false,
required this.member, required this.memberReference,
required this.tearOff}) { required this.tearOffReference}) {
this.isStatic = isStatic; this.isStatic = isStatic;
} }
@ -1747,7 +1748,7 @@ class ExtensionMemberDescriptor {
@override @override
String toString() { String toString() {
return 'ExtensionMemberDescriptor($name,$kind,' return 'ExtensionMemberDescriptor($name,$kind,'
'${member.toStringInternal()},isStatic=${isStatic})'; '${memberReference.toStringInternal()},isStatic=${isStatic})';
} }
} }
@ -1790,11 +1791,19 @@ class ExtensionTypeDeclaration extends NamedNode
/// library of the extension type declaration. /// library of the extension type declaration.
late String representationName; late String representationName;
/// Abstract procedures that are part of the extension type declaration
/// interface.
///
/// This includes a getter for the representation field and member signatures
/// computed as the combined member signature of inherited non-extension type
/// members.
List<Procedure> _procedures;
/// The members declared by the extension type declaration. /// The members declared by the extension type declaration.
/// ///
/// The members are converted into top-level members and only accessible /// The members are converted into top-level members and only accessible
/// by reference through [ExtensionTypeMemberDescriptor]. /// by reference through [ExtensionTypeMemberDescriptor].
List<ExtensionTypeMemberDescriptor> members; List<ExtensionTypeMemberDescriptor> memberDescriptors;
@override @override
List<Expression> annotations = const <Expression>[]; List<Expression> annotations = const <Expression>[];
@ -1816,15 +1825,19 @@ class ExtensionTypeDeclaration extends NamedNode
{required this.name, {required this.name,
List<TypeParameter>? typeParameters, List<TypeParameter>? typeParameters,
DartType? declaredRepresentationType, DartType? declaredRepresentationType,
List<ExtensionTypeMemberDescriptor>? members, List<ExtensionTypeMemberDescriptor>? memberDescriptors,
List<DartType>? implements, List<DartType>? implements,
List<Procedure>? procedures,
required this.fileUri, required this.fileUri,
Reference? reference}) Reference? reference})
: this.typeParameters = typeParameters ?? <TypeParameter>[], : this.typeParameters = typeParameters ?? <TypeParameter>[],
this.members = members ?? <ExtensionTypeMemberDescriptor>[], this.memberDescriptors =
memberDescriptors ?? <ExtensionTypeMemberDescriptor>[],
this.implements = implements ?? <DartType>[], this.implements = implements ?? <DartType>[],
this._procedures = procedures ?? <Procedure>[],
super(reference) { super(reference) {
setParents(this.typeParameters, this); setParents(this.typeParameters, this);
setParents(this._procedures, this);
if (declaredRepresentationType != null) { if (declaredRepresentationType != null) {
this.declaredRepresentationType = declaredRepresentationType; this.declaredRepresentationType = declaredRepresentationType;
} }
@ -1837,6 +1850,20 @@ class ExtensionTypeDeclaration extends NamedNode
Library get enclosingLibrary => parent as Library; Library get enclosingLibrary => parent as Library;
void addProcedure(Procedure procedure) {
procedure.parent = this;
procedures.add(procedure);
}
List<Procedure> get procedures => _procedures;
/// Internal. Should *ONLY* be used from within kernel.
///
/// Used for adding procedures when reading the dill file.
void set proceduresInternal(List<Procedure> procedures) {
_procedures = procedures;
}
@override @override
R accept<R>(TreeVisitor<R> v) => v.visitExtensionTypeDeclaration(this); R accept<R>(TreeVisitor<R> v) => v.visitExtensionTypeDeclaration(this);
@ -1852,6 +1879,7 @@ class ExtensionTypeDeclaration extends NamedNode
visitList(annotations, v); visitList(annotations, v);
visitList(typeParameters, v); visitList(typeParameters, v);
declaredRepresentationType.accept(v); declaredRepresentationType.accept(v);
visitList(procedures, v);
} }
@override @override
@ -1859,6 +1887,7 @@ class ExtensionTypeDeclaration extends NamedNode
v.transformList(annotations, this); v.transformList(annotations, this);
v.transformList(typeParameters, this); v.transformList(typeParameters, this);
declaredRepresentationType = v.visitDartType(declaredRepresentationType); declaredRepresentationType = v.visitDartType(declaredRepresentationType);
v.transformList(procedures, this);
} }
@override @override
@ -1867,6 +1896,7 @@ class ExtensionTypeDeclaration extends NamedNode
v.transformTypeParameterList(typeParameters, this); v.transformTypeParameterList(typeParameters, this);
declaredRepresentationType = declaredRepresentationType =
v.visitDartType(declaredRepresentationType, cannotRemoveSentinel); v.visitDartType(declaredRepresentationType, cannotRemoveSentinel);
v.transformProcedureList(procedures, this);
} }
@override @override
@ -1933,18 +1963,18 @@ class ExtensionTypeMemberDescriptor {
/// Reference to the top-level member created for the extension type /// Reference to the top-level member created for the extension type
/// declaration member. /// declaration member.
final Reference member; final Reference memberReference;
/// Reference to the top-level member created for the extension type /// Reference to the top-level member created for the extension type
/// declaration member tear off, if any. /// declaration member tear off, if any.
final Reference? tearOff; final Reference? tearOffReference;
ExtensionTypeMemberDescriptor( ExtensionTypeMemberDescriptor(
{required this.name, {required this.name,
required this.kind, required this.kind,
bool isStatic = false, bool isStatic = false,
required this.member, required this.memberReference,
required this.tearOff}) { required this.tearOffReference}) {
this.isStatic = isStatic; this.isStatic = isStatic;
} }
@ -1959,8 +1989,8 @@ class ExtensionTypeMemberDescriptor {
@override @override
String toString() { String toString() {
return 'ExtensionTypeMemberDescriptor($name,$kind,' return 'ExtensionTypeMemberDescriptor($name,$kind,'
'${member.toStringInternal()},isStatic=${isStatic},' '${memberReference.toStringInternal()},isStatic=${isStatic},'
'${tearOff?.toStringInternal()})'; '${tearOffReference?.toStringInternal()})';
} }
} }
@ -15296,8 +15326,8 @@ final ExtensionMemberDescriptor dummyExtensionMemberDescriptor =
new ExtensionMemberDescriptor( new ExtensionMemberDescriptor(
name: dummyName, name: dummyName,
kind: ExtensionMemberKind.Getter, kind: ExtensionMemberKind.Getter,
member: dummyReference, memberReference: dummyReference,
tearOff: null); tearOffReference: null);
/// Non-nullable [ExtensionTypeDeclaration] dummy value. /// Non-nullable [ExtensionTypeDeclaration] dummy value.
/// ///
@ -15316,8 +15346,8 @@ final ExtensionTypeMemberDescriptor dummyExtensionTypeMemberDescriptor =
new ExtensionTypeMemberDescriptor( new ExtensionTypeMemberDescriptor(
name: dummyName, name: dummyName,
kind: ExtensionTypeMemberKind.Getter, kind: ExtensionTypeMemberKind.Getter,
member: dummyReference, memberReference: dummyReference,
tearOff: null); tearOffReference: null);
/// Non-nullable [ExtensionType] dummy value. /// Non-nullable [ExtensionType] dummy value.
/// ///

View file

@ -1361,6 +1361,19 @@ class BinaryBuilder {
return list; return list;
} }
List<Procedure> _readProcedureListWithoutOffsets(TreeNode parent) {
int length = readUInt30();
if (!useGrowableLists && length == 0) {
// When lists don't have to be growable anyway, we might as well use an
// almost constant one for the empty list.
return emptyListOfProcedure;
}
List<Procedure> list = new List<Procedure>.generate(length, (int index) {
return readProcedure(/* no end offset = */ -1)..parent = parent;
}, growable: useGrowableLists);
return list;
}
void _readLibraryDependencies(Library library) { void _readLibraryDependencies(Library library) {
int length = readUInt30(); int length = readUInt30();
if (!useGrowableLists && length == 0) { if (!useGrowableLists && length == 0) {
@ -1571,7 +1584,7 @@ class BinaryBuilder {
node.fileUri = fileUri; node.fileUri = fileUri;
node.onType = onType; node.onType = onType;
node.members = _readExtensionMemberDescriptorList(); node.memberDescriptors = _readExtensionMemberDescriptorList();
return node; return node;
} }
@ -1597,8 +1610,8 @@ class BinaryBuilder {
return new ExtensionMemberDescriptor( return new ExtensionMemberDescriptor(
name: name, name: name,
kind: ExtensionMemberKind.values[kind], kind: ExtensionMemberKind.values[kind],
member: memberName.reference, memberReference: memberName.reference,
tearOff: tearOffName?.reference) tearOffReference: tearOffName?.reference)
..flags = flags; ..flags = flags;
} }
@ -1639,6 +1652,8 @@ class BinaryBuilder {
DartType representationType = readDartType(); DartType representationType = readDartType();
String representationName = readStringReference(); String representationName = readStringReference();
List<DartType> implements = _readExtensionTypeDeclarationImplementsList(); List<DartType> implements = _readExtensionTypeDeclarationImplementsList();
node.proceduresInternal = _readProcedureListWithoutOffsets(node);
typeParameterStack.length = 0; typeParameterStack.length = 0;
node.name = name; node.name = name;
@ -1647,7 +1662,8 @@ class BinaryBuilder {
node.representationName = representationName; node.representationName = representationName;
node.implements = implements; node.implements = implements;
node.members = _readExtensionTypeMemberDescriptorList();
node.memberDescriptors = _readExtensionTypeMemberDescriptorList();
return node; return node;
} }
@ -1684,8 +1700,8 @@ class BinaryBuilder {
return new ExtensionTypeMemberDescriptor( return new ExtensionTypeMemberDescriptor(
name: name, name: name,
kind: ExtensionTypeMemberKind.values[kind], kind: ExtensionTypeMemberKind.values[kind],
member: memberName.reference, memberReference: memberName.reference,
tearOff: tearOffName?.reference) tearOffReference: tearOffName?.reference)
..flags = flags; ..flags = flags;
} }

View file

@ -2646,17 +2646,17 @@ class BinaryPrinter implements Visitor<void>, BinarySink {
leaveScope(typeParameters: node.typeParameters); leaveScope(typeParameters: node.typeParameters);
final int len = node.members.length; final int len = node.memberDescriptors.length;
writeUInt30(len); writeUInt30(len);
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
final ExtensionMemberDescriptor descriptor = node.members[i]; final ExtensionMemberDescriptor descriptor = node.memberDescriptors[i];
writeName(descriptor.name); writeName(descriptor.name);
writeByte(descriptor.kind.index); writeByte(descriptor.kind.index);
writeByte(descriptor.flags); writeByte(descriptor.flags);
assert(descriptor.member.canonicalName != null, assert(descriptor.memberReference.canonicalName != null,
"No canonical name for ${descriptor}."); "No canonical name for ${descriptor}.");
writeNonNullCanonicalNameReference(descriptor.member); writeNonNullCanonicalNameReference(descriptor.memberReference);
writeNullAllowedCanonicalNameReference(descriptor.tearOff); writeNullAllowedCanonicalNameReference(descriptor.tearOffReference);
} }
} }
@ -2679,23 +2679,25 @@ class BinaryPrinter implements Visitor<void>, BinarySink {
writeDartType(node.declaredRepresentationType); writeDartType(node.declaredRepresentationType);
writeStringReference(node.representationName); writeStringReference(node.representationName);
writeNodeList(node.implements); writeNodeList(node.implements);
writeProcedureNodeList(node.procedures);
leaveScope(typeParameters: node.typeParameters); leaveScope(typeParameters: node.typeParameters);
final int len = node.members.length; final int len = node.memberDescriptors.length;
writeUInt30(len); writeUInt30(len);
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
final ExtensionTypeMemberDescriptor descriptor = node.members[i]; final ExtensionTypeMemberDescriptor descriptor =
node.memberDescriptors[i];
writeName(descriptor.name); writeName(descriptor.name);
writeByte(descriptor.kind.index); writeByte(descriptor.kind.index);
writeByte(descriptor.flags); writeByte(descriptor.flags);
assert(descriptor.member.canonicalName != null, assert(descriptor.memberReference.canonicalName != null,
"No canonical name for ${descriptor}."); "No canonical name for ${descriptor}.");
writeNonNullCanonicalNameReference(descriptor.member); writeNonNullCanonicalNameReference(descriptor.memberReference);
assert( assert(
descriptor.tearOff == null || descriptor.tearOffReference == null ||
descriptor.tearOff?.canonicalName != null, descriptor.tearOffReference?.canonicalName != null,
"No canonical name for ${descriptor} tear-off."); "No canonical name for ${descriptor} tear-off.");
writeNullAllowedCanonicalNameReference(descriptor.tearOff); writeNullAllowedCanonicalNameReference(descriptor.tearOffReference);
} }
} }

View file

@ -226,7 +226,7 @@ class Tag {
/// Internal version of kernel binary format. /// Internal version of kernel binary format.
/// Bump it when making incompatible changes in kernel binaries. /// Bump it when making incompatible changes in kernel binaries.
/// Keep in sync with runtime/vm/kernel_binary.h, pkg/kernel/binary.md. /// Keep in sync with runtime/vm/kernel_binary.h, pkg/kernel/binary.md.
static const int BinaryFormatVersion = 111; static const int BinaryFormatVersion = 112;
} }
abstract class ConstantTag { abstract class ConstantTag {

View file

@ -247,7 +247,7 @@ class _MemberTable {
class_!.fields.forEach(_addMember); class_!.fields.forEach(_addMember);
class_!.constructors.forEach(_addMember); class_!.constructors.forEach(_addMember);
} else if (extension_ != null) { } else if (extension_ != null) {
extension_!.members.forEach(_addExtensionMember); extension_!.memberDescriptors.forEach(_addExtensionMember);
} else { } else {
library.procedures.forEach(_addMember); library.procedures.forEach(_addMember);
library.fields.forEach(_addMember); library.fields.forEach(_addMember);
@ -307,8 +307,8 @@ class _MemberTable {
_members![name] = replacement; _members![name] = replacement;
} }
addReference(extensionMember.member, forTearOff: false); addReference(extensionMember.memberReference, forTearOff: false);
addReference(extensionMember.tearOff, forTearOff: true); addReference(extensionMember.tearOffReference, forTearOff: true);
} }
String get containerName { String get containerName {

View file

@ -129,8 +129,9 @@ class IndexedLibrary extends IndexedContainer {
// repurposing these canonical names. // repurposing these canonical names.
for (Extension extension in unnamedExtensions) { for (Extension extension in unnamedExtensions) {
extension.reference.canonicalName?.unbind(); extension.reference.canonicalName?.unbind();
for (ExtensionMemberDescriptor descriptor in extension.members) { for (ExtensionMemberDescriptor descriptor
Reference reference = descriptor.member; in extension.memberDescriptors) {
Reference reference = descriptor.memberReference;
Member member = reference.asMember; Member member = reference.asMember;
if (member is Field) { if (member is Field) {
member.fieldReference.canonicalName?.unbind(); member.fieldReference.canonicalName?.unbind();
@ -139,7 +140,7 @@ class IndexedLibrary extends IndexedContainer {
} else { } else {
member.reference.canonicalName?.unbind(); member.reference.canonicalName?.unbind();
} }
descriptor.tearOff?.canonicalName?.unbind(); descriptor.tearOffReference?.canonicalName?.unbind();
} }
} }
} }

View file

@ -1715,10 +1715,11 @@ class EquivalenceStrategy {
if (!checkExtensionMemberDescriptor_flags(visitor, node, other)) { if (!checkExtensionMemberDescriptor_flags(visitor, node, other)) {
result = visitor.resultOnInequivalence; result = visitor.resultOnInequivalence;
} }
if (!checkExtensionMemberDescriptor_member(visitor, node, other)) { if (!checkExtensionMemberDescriptor_memberReference(visitor, node, other)) {
result = visitor.resultOnInequivalence; result = visitor.resultOnInequivalence;
} }
if (!checkExtensionMemberDescriptor_tearOff(visitor, node, other)) { if (!checkExtensionMemberDescriptor_tearOffReference(
visitor, node, other)) {
result = visitor.resultOnInequivalence; result = visitor.resultOnInequivalence;
} }
return result; return result;
@ -1746,7 +1747,7 @@ class EquivalenceStrategy {
if (!checkExtension_onType(visitor, node, other)) { if (!checkExtension_onType(visitor, node, other)) {
result = visitor.resultOnInequivalence; result = visitor.resultOnInequivalence;
} }
if (!checkExtension_members(visitor, node, other)) { if (!checkExtension_memberDescriptors(visitor, node, other)) {
result = visitor.resultOnInequivalence; result = visitor.resultOnInequivalence;
} }
if (!checkExtension_annotations(visitor, node, other)) { if (!checkExtension_annotations(visitor, node, other)) {
@ -1780,10 +1781,12 @@ class EquivalenceStrategy {
if (!checkExtensionTypeMemberDescriptor_flags(visitor, node, other)) { if (!checkExtensionTypeMemberDescriptor_flags(visitor, node, other)) {
result = visitor.resultOnInequivalence; result = visitor.resultOnInequivalence;
} }
if (!checkExtensionTypeMemberDescriptor_member(visitor, node, other)) { if (!checkExtensionTypeMemberDescriptor_memberReference(
visitor, node, other)) {
result = visitor.resultOnInequivalence; result = visitor.resultOnInequivalence;
} }
if (!checkExtensionTypeMemberDescriptor_tearOff(visitor, node, other)) { if (!checkExtensionTypeMemberDescriptor_tearOffReference(
visitor, node, other)) {
result = visitor.resultOnInequivalence; result = visitor.resultOnInequivalence;
} }
return result; return result;
@ -1816,7 +1819,11 @@ class EquivalenceStrategy {
visitor, node, other)) { visitor, node, other)) {
result = visitor.resultOnInequivalence; result = visitor.resultOnInequivalence;
} }
if (!checkExtensionTypeDeclaration_members(visitor, node, other)) { if (!checkExtensionTypeDeclaration_procedures(visitor, node, other)) {
result = visitor.resultOnInequivalence;
}
if (!checkExtensionTypeDeclaration_memberDescriptors(
visitor, node, other)) {
result = visitor.resultOnInequivalence; result = visitor.resultOnInequivalence;
} }
if (!checkExtensionTypeDeclaration_annotations(visitor, node, other)) { if (!checkExtensionTypeDeclaration_annotations(visitor, node, other)) {
@ -6022,24 +6029,31 @@ class EquivalenceStrategy {
return visitor.checkValues(node.flags, other.flags, 'flags'); return visitor.checkValues(node.flags, other.flags, 'flags');
} }
bool checkExtensionMemberDescriptor_member(EquivalenceVisitor visitor, bool checkExtensionMemberDescriptor_memberReference(
ExtensionMemberDescriptor node, ExtensionMemberDescriptor other) { EquivalenceVisitor visitor,
return visitor.checkReferences(node.member, other.member, 'member'); ExtensionMemberDescriptor node,
ExtensionMemberDescriptor other) {
return visitor.checkReferences(
node.memberReference, other.memberReference, 'memberReference');
} }
bool checkExtensionMemberDescriptor_tearOff(EquivalenceVisitor visitor, bool checkExtensionMemberDescriptor_tearOffReference(
ExtensionMemberDescriptor node, ExtensionMemberDescriptor other) { EquivalenceVisitor visitor,
return visitor.checkReferences(node.tearOff, other.tearOff, 'tearOff'); ExtensionMemberDescriptor node,
ExtensionMemberDescriptor other) {
return visitor.checkReferences(
node.tearOffReference, other.tearOffReference, 'tearOffReference');
} }
bool checkExtension_members( bool checkExtension_memberDescriptors(
EquivalenceVisitor visitor, Extension node, Extension other) { EquivalenceVisitor visitor, Extension node, Extension other) {
return visitor.checkLists(node.members, other.members, (a, b, _) { return visitor.checkLists(node.memberDescriptors, other.memberDescriptors,
(a, b, _) {
if (identical(a, b)) return true; if (identical(a, b)) return true;
if (a is! ExtensionMemberDescriptor) return false; if (a is! ExtensionMemberDescriptor) return false;
if (b is! ExtensionMemberDescriptor) return false; if (b is! ExtensionMemberDescriptor) return false;
return checkExtensionMemberDescriptor(visitor, a, b); return checkExtensionMemberDescriptor(visitor, a, b);
}, 'members'); }, 'memberDescriptors');
} }
bool checkExtension_annotations( bool checkExtension_annotations(
@ -6095,6 +6109,12 @@ class EquivalenceStrategy {
other.representationName, 'representationName'); other.representationName, 'representationName');
} }
bool checkExtensionTypeDeclaration_procedures(EquivalenceVisitor visitor,
ExtensionTypeDeclaration node, ExtensionTypeDeclaration other) {
return visitor.checkLists(
node.procedures, other.procedures, visitor.checkNodes, 'procedures');
}
bool checkExtensionTypeMemberDescriptor_name(EquivalenceVisitor visitor, bool checkExtensionTypeMemberDescriptor_name(EquivalenceVisitor visitor,
ExtensionTypeMemberDescriptor node, ExtensionTypeMemberDescriptor other) { ExtensionTypeMemberDescriptor node, ExtensionTypeMemberDescriptor other) {
return visitor.checkNodes(node.name, other.name, 'name'); return visitor.checkNodes(node.name, other.name, 'name');
@ -6110,24 +6130,33 @@ class EquivalenceStrategy {
return visitor.checkValues(node.flags, other.flags, 'flags'); return visitor.checkValues(node.flags, other.flags, 'flags');
} }
bool checkExtensionTypeMemberDescriptor_member(EquivalenceVisitor visitor, bool checkExtensionTypeMemberDescriptor_memberReference(
ExtensionTypeMemberDescriptor node, ExtensionTypeMemberDescriptor other) { EquivalenceVisitor visitor,
return visitor.checkReferences(node.member, other.member, 'member'); ExtensionTypeMemberDescriptor node,
ExtensionTypeMemberDescriptor other) {
return visitor.checkReferences(
node.memberReference, other.memberReference, 'memberReference');
} }
bool checkExtensionTypeMemberDescriptor_tearOff(EquivalenceVisitor visitor, bool checkExtensionTypeMemberDescriptor_tearOffReference(
ExtensionTypeMemberDescriptor node, ExtensionTypeMemberDescriptor other) { EquivalenceVisitor visitor,
return visitor.checkReferences(node.tearOff, other.tearOff, 'tearOff'); ExtensionTypeMemberDescriptor node,
ExtensionTypeMemberDescriptor other) {
return visitor.checkReferences(
node.tearOffReference, other.tearOffReference, 'tearOffReference');
} }
bool checkExtensionTypeDeclaration_members(EquivalenceVisitor visitor, bool checkExtensionTypeDeclaration_memberDescriptors(
ExtensionTypeDeclaration node, ExtensionTypeDeclaration other) { EquivalenceVisitor visitor,
return visitor.checkLists(node.members, other.members, (a, b, _) { ExtensionTypeDeclaration node,
ExtensionTypeDeclaration other) {
return visitor.checkLists(node.memberDescriptors, other.memberDescriptors,
(a, b, _) {
if (identical(a, b)) return true; if (identical(a, b)) return true;
if (a is! ExtensionTypeMemberDescriptor) return false; if (a is! ExtensionTypeMemberDescriptor) return false;
if (b is! ExtensionTypeMemberDescriptor) return false; if (b is! ExtensionTypeMemberDescriptor) return false;
return checkExtensionTypeMemberDescriptor(visitor, a, b); return checkExtensionTypeMemberDescriptor(visitor, a, b);
}, 'members'); }, 'memberDescriptors');
} }
bool checkExtensionTypeDeclaration_annotations(EquivalenceVisitor visitor, bool checkExtensionTypeDeclaration_annotations(EquivalenceVisitor visitor,

View file

@ -1360,7 +1360,7 @@ class Printer extends VisitorDefault<void> with VisitorVoidMixin {
endLine(endLineString); endLine(endLineString);
++indentation; ++indentation;
node.members.forEach((ExtensionMemberDescriptor descriptor) { node.memberDescriptors.forEach((ExtensionMemberDescriptor descriptor) {
void writeReference(Reference reference, {required bool isTearOff}) { void writeReference(Reference reference, {required bool isTearOff}) {
writeIndentation(); writeIndentation();
writeModifier(descriptor.isStatic, 'static'); writeModifier(descriptor.isStatic, 'static');
@ -1398,9 +1398,9 @@ class Printer extends VisitorDefault<void> with VisitorVoidMixin {
endLine(';'); endLine(';');
} }
writeReference(descriptor.member, isTearOff: false); writeReference(descriptor.memberReference, isTearOff: false);
if (descriptor.tearOff != null) { if (descriptor.tearOffReference != null) {
writeReference(descriptor.tearOff!, isTearOff: true); writeReference(descriptor.tearOffReference!, isTearOff: true);
} }
}); });
--indentation; --indentation;
@ -1430,7 +1430,8 @@ class Printer extends VisitorDefault<void> with VisitorVoidMixin {
endLine(endLineString); endLine(endLineString);
++indentation; ++indentation;
node.members.forEach((ExtensionTypeMemberDescriptor descriptor) { node.procedures.forEach(writeNode);
node.memberDescriptors.forEach((ExtensionTypeMemberDescriptor descriptor) {
void writeReference(Reference reference, {required bool isTearOff}) { void writeReference(Reference reference, {required bool isTearOff}) {
writeIndentation(); writeIndentation();
writeModifier(descriptor.isStatic, 'static'); writeModifier(descriptor.isStatic, 'static');
@ -1477,9 +1478,9 @@ class Printer extends VisitorDefault<void> with VisitorVoidMixin {
endLine(';'); endLine(';');
} }
writeReference(descriptor.member, isTearOff: false); writeReference(descriptor.memberReference, isTearOff: false);
if (descriptor.tearOff != null) { if (descriptor.tearOffReference != null) {
writeReference(descriptor.tearOff!, isTearOff: true); writeReference(descriptor.tearOffReference!, isTearOff: true);
} }
}); });
--indentation; --indentation;

View file

@ -710,13 +710,13 @@ class WidgetCreatorTracker {
return; return;
} }
for (ExtensionMemberDescriptor member in extension.members) { for (ExtensionMemberDescriptor member in extension.memberDescriptors) {
if (member.isStatic) { if (member.isStatic) {
// We could support static extension methods but it is not clear that // We could support static extension methods but it is not clear that
// there is a use case for this. // there is a use case for this.
continue; continue;
} }
final Procedure method = member.member.asProcedure; final Procedure method = member.memberReference.asProcedure;
if (_hasWidgetFactoryAnnotation(method)) { if (_hasWidgetFactoryAnnotation(method)) {
_maybeAddNamedParameter( _maybeAddNamedParameter(
method.function, method.function,
@ -730,7 +730,7 @@ class WidgetCreatorTracker {
), ),
); );
} }
final Procedure? tearOff = member.tearOff?.asProcedure; final Procedure? tearOff = member.tearOffReference?.asProcedure;
if (tearOff != null && _hasWidgetFactoryAnnotation(tearOff)) { if (tearOff != null && _hasWidgetFactoryAnnotation(tearOff)) {
_maybeAddNamedParameter( _maybeAddNamedParameter(
tearOff.function, tearOff.function,

View file

@ -403,8 +403,9 @@ class VerifyingVisitor extends RecursiveResultVisitor<void> {
if (_extensionsMembers == null) { if (_extensionsMembers == null) {
Map<Reference, ExtensionMemberDescriptor> map = _extensionsMembers = {}; Map<Reference, ExtensionMemberDescriptor> map = _extensionsMembers = {};
for (Extension extension in library.extensions) { for (Extension extension in library.extensions) {
for (ExtensionMemberDescriptor descriptor in extension.members) { for (ExtensionMemberDescriptor descriptor
Reference memberReference = descriptor.member; in extension.memberDescriptors) {
Reference memberReference = descriptor.memberReference;
map[memberReference] = descriptor; map[memberReference] = descriptor;
Member member = memberReference.asMember; Member member = memberReference.asMember;
if (!member.isExtensionMember) { if (!member.isExtensionMember) {
@ -413,7 +414,7 @@ class VerifyingVisitor extends RecursiveResultVisitor<void> {
"Member $member (${descriptor}) from $extension is not marked " "Member $member (${descriptor}) from $extension is not marked "
"as an extension member."); "as an extension member.");
} }
Reference? tearOffReference = descriptor.tearOff; Reference? tearOffReference = descriptor.tearOffReference;
if (tearOffReference != null) { if (tearOffReference != null) {
map[tearOffReference] = descriptor; map[tearOffReference] = descriptor;
Member tearOff = tearOffReference.asMember; Member tearOff = tearOffReference.asMember;
@ -438,8 +439,8 @@ class VerifyingVisitor extends RecursiveResultVisitor<void> {
for (ExtensionTypeDeclaration extensionTypeDeclaration for (ExtensionTypeDeclaration extensionTypeDeclaration
in library.extensionTypeDeclarations) { in library.extensionTypeDeclarations) {
for (ExtensionTypeMemberDescriptor descriptor for (ExtensionTypeMemberDescriptor descriptor
in extensionTypeDeclaration.members) { in extensionTypeDeclaration.memberDescriptors) {
Reference memberReference = descriptor.member; Reference memberReference = descriptor.memberReference;
map[memberReference] = descriptor; map[memberReference] = descriptor;
Member member = memberReference.asMember; Member member = memberReference.asMember;
if (!member.isExtensionTypeMember) { if (!member.isExtensionTypeMember) {
@ -448,7 +449,7 @@ class VerifyingVisitor extends RecursiveResultVisitor<void> {
"Member $member (${descriptor}) from $extensionTypeDeclaration " "Member $member (${descriptor}) from $extensionTypeDeclaration "
"is not marked as an extension type member."); "is not marked as an extension type member.");
} }
Reference? tearOffReference = descriptor.tearOff; Reference? tearOffReference = descriptor.tearOffReference;
if (tearOffReference != null) { if (tearOffReference != null) {
map[tearOffReference] = descriptor; map[tearOffReference] = descriptor;
Member tearOff = tearOffReference.asMember; Member tearOff = tearOffReference.asMember;

View file

@ -877,9 +877,9 @@ class TreeShaker {
if (m.isExtensionMember) { if (m.isExtensionMember) {
// The AST should have exactly one [Extension] for [m]. // The AST should have exactly one [Extension] for [m].
final extension = m.enclosingLibrary.extensions.firstWhere((extension) { final extension = m.enclosingLibrary.extensions.firstWhere((extension) {
return extension.members.any((descriptor) => return extension.memberDescriptors.any((descriptor) =>
descriptor.member.asMember == m || descriptor.memberReference.asMember == m ||
descriptor.tearOff?.asMember == m); descriptor.tearOffReference?.asMember == m);
}); });
// Ensure we retain the [Extension] itself (though members might be // Ensure we retain the [Extension] itself (though members might be
@ -894,9 +894,9 @@ class TreeShaker {
final extensionTypeDeclaration = m final extensionTypeDeclaration = m
.enclosingLibrary.extensionTypeDeclarations .enclosingLibrary.extensionTypeDeclarations
.firstWhere((extensionTypeDeclaration) { .firstWhere((extensionTypeDeclaration) {
return extensionTypeDeclaration.members.any((descriptor) => return extensionTypeDeclaration.memberDescriptors.any((descriptor) =>
descriptor.member.asMember == m || descriptor.memberReference.asMember == m ||
descriptor.tearOff?.asMember == m); descriptor.tearOffReference?.asMember == m);
}); });
// Ensure we retain the [ExtensionTypeDeclaration] itself (though // Ensure we retain the [ExtensionTypeDeclaration] itself (though
@ -1985,17 +1985,17 @@ class _TreeShakerPass2 extends RemovingTransformer {
TreeNode visitExtension(Extension node, TreeNode? removalSentinel) { TreeNode visitExtension(Extension node, TreeNode? removalSentinel) {
if (shaker.isExtensionUsed(node)) { if (shaker.isExtensionUsed(node)) {
int writeIndex = 0; int writeIndex = 0;
for (int i = 0; i < node.members.length; ++i) { for (int i = 0; i < node.memberDescriptors.length; ++i) {
ExtensionMemberDescriptor descriptor = node.members[i]; ExtensionMemberDescriptor descriptor = node.memberDescriptors[i];
// To avoid depending on the order in which members and extensions are // To avoid depending on the order in which members and extensions are
// visited during the transformation, we handle both cases: either the // visited during the transformation, we handle both cases: either the
// member was already removed or it will be removed later. // member was already removed or it will be removed later.
final Reference memberReference = descriptor.member; final Reference memberReference = descriptor.memberReference;
final bool memberIsBound = memberReference.node != null; final bool memberIsBound = memberReference.node != null;
final bool isMemberUsed = final bool isMemberUsed =
memberIsBound && shaker.isMemberUsed(memberReference.asMember); memberIsBound && shaker.isMemberUsed(memberReference.asMember);
final Reference? tearOffReference = descriptor.tearOff; final Reference? tearOffReference = descriptor.tearOffReference;
final bool tearOffIsBound = tearOffReference?.node != null; final bool tearOffIsBound = tearOffReference?.node != null;
final bool isTearOffUsed = final bool isTearOffUsed =
tearOffIsBound && shaker.isMemberUsed(tearOffReference!.asMember); tearOffIsBound && shaker.isMemberUsed(tearOffReference!.asMember);
@ -2008,16 +2008,16 @@ class _TreeShakerPass2 extends RemovingTransformer {
name: descriptor.name, name: descriptor.name,
kind: descriptor.kind, kind: descriptor.kind,
isStatic: descriptor.isStatic, isStatic: descriptor.isStatic,
member: descriptor.member, memberReference: descriptor.memberReference,
tearOff: null); tearOffReference: null);
} }
node.members[writeIndex++] = descriptor; node.memberDescriptors[writeIndex++] = descriptor;
} }
} }
node.members.length = writeIndex; node.memberDescriptors.length = writeIndex;
// We only retain the extension if at least one member is retained. // We only retain the extension if at least one member is retained.
assert(node.members.isNotEmpty); assert(node.memberDescriptors.isNotEmpty);
return node; return node;
} }
return removalSentinel!; return removalSentinel!;
@ -2028,18 +2028,18 @@ class _TreeShakerPass2 extends RemovingTransformer {
ExtensionTypeDeclaration node, TreeNode? removalSentinel) { ExtensionTypeDeclaration node, TreeNode? removalSentinel) {
if (shaker.isExtensionTypeDeclarationUsed(node)) { if (shaker.isExtensionTypeDeclarationUsed(node)) {
int writeIndex = 0; int writeIndex = 0;
for (int i = 0; i < node.members.length; ++i) { for (int i = 0; i < node.memberDescriptors.length; ++i) {
ExtensionTypeMemberDescriptor descriptor = node.members[i]; ExtensionTypeMemberDescriptor descriptor = node.memberDescriptors[i];
// To avoid depending on the order in which members and extension type // To avoid depending on the order in which members and extension type
// declarations are visited during the transformation, we handle both // declarations are visited during the transformation, we handle both
// cases: either the member was already removed or it will be removed // cases: either the member was already removed or it will be removed
// later. // later.
final Reference memberReference = descriptor.member; final Reference memberReference = descriptor.memberReference;
final bool memberIsBound = memberReference.node != null; final bool memberIsBound = memberReference.node != null;
final bool isMemberUsed = final bool isMemberUsed =
memberIsBound && shaker.isMemberUsed(memberReference.asMember); memberIsBound && shaker.isMemberUsed(memberReference.asMember);
final Reference? tearOffReference = descriptor.tearOff; final Reference? tearOffReference = descriptor.tearOffReference;
final bool tearOffIsBound = tearOffReference?.node != null; final bool tearOffIsBound = tearOffReference?.node != null;
final bool isTearOffUsed = final bool isTearOffUsed =
tearOffIsBound && shaker.isMemberUsed(tearOffReference!.asMember); tearOffIsBound && shaker.isMemberUsed(tearOffReference!.asMember);
@ -2052,17 +2052,17 @@ class _TreeShakerPass2 extends RemovingTransformer {
name: descriptor.name, name: descriptor.name,
kind: descriptor.kind, kind: descriptor.kind,
isStatic: descriptor.isStatic, isStatic: descriptor.isStatic,
member: descriptor.member, memberReference: descriptor.memberReference,
tearOff: null); tearOffReference: null);
} }
node.members[writeIndex++] = descriptor; node.memberDescriptors[writeIndex++] = descriptor;
} }
} }
node.members.length = writeIndex; node.memberDescriptors.length = writeIndex;
// We only retain the extension type declaration if at least one member is // We only retain the extension type declaration if at least one member is
// retained. // retained.
assert(node.members.isNotEmpty); assert(node.memberDescriptors.isNotEmpty);
return node; return node;
} }
return removalSentinel!; return removalSentinel!;

View file

@ -18,7 +18,7 @@ namespace kernel {
// package:kernel/binary.md. // package:kernel/binary.md.
static const uint32_t kMagicProgramFile = 0x90ABCDEFu; static const uint32_t kMagicProgramFile = 0x90ABCDEFu;
static const uint32_t kSupportedKernelFormatVersion = 111; static const uint32_t kSupportedKernelFormatVersion = 112;
// Keep in sync with package:kernel/lib/binary/tag.dart // Keep in sync with package:kernel/lib/binary/tag.dart
#define KERNEL_TAG_LIST(V) \ #define KERNEL_TAG_LIST(V) \

View file

@ -1002,6 +1002,14 @@ void KernelLoader::FinishTopLevelClassLoading(
helper_.SkipStringReference(); // skip representation name. helper_.SkipStringReference(); // skip representation name.
helper_.SkipListOfDartTypes(); // skip implements types. helper_.SkipListOfDartTypes(); // skip implements types.
// Skip extension type procedures.
const intptr_t extension_type_procedure_count =
helper_.ReadListLength(); // read list length.
for (intptr_t i = 0; i < extension_type_procedure_count; ++i) {
ProcedureHelper procedure_helper(&helper_);
procedure_helper.ReadUntilExcluding(ProcedureHelper::kEnd);
}
const intptr_t extension_type_member_count = helper_.ReadListLength(); const intptr_t extension_type_member_count = helper_.ReadListLength();
for (intptr_t j = 0; j < extension_type_member_count; ++j) { for (intptr_t j = 0; j < extension_type_member_count; ++j) {
helper_.SkipName(); // skip name. helper_.SkipName(); // skip name.