[cfe] Create SourceConstructorBuilder through fragments
Change-Id: I78e40b1c5cd80e9e32a0c96f99ec9c9a172ad8e4
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/385580
Reviewed-by: Jens Johansen <jensj@google.com>
Commit-Queue: Johnni Winther <johnniwinther@google.com>
diff --git a/pkg/front_end/lib/src/fragment/fragment.dart b/pkg/front_end/lib/src/fragment/fragment.dart
index 6239b0e..3eeda4f 100644
--- a/pkg/front_end/lib/src/fragment/fragment.dart
+++ b/pkg/front_end/lib/src/fragment/fragment.dart
@@ -16,6 +16,7 @@
import '../builder/type_builder.dart';
import '../source/name_scheme.dart';
import '../source/source_class_builder.dart';
+import '../source/source_constructor_builder.dart';
import '../source/source_enum_builder.dart';
import '../source/source_extension_builder.dart';
import '../source/source_extension_type_declaration_builder.dart';
@@ -586,3 +587,70 @@
@override
String toString() => '$runtimeType($name,$fileUri,$charOffset)';
}
+
+class ConstructorFragment implements Fragment {
+ final String name;
+ final Uri fileUri;
+ final int startCharOffset;
+ final int charOffset;
+ final int charOpenParenOffset;
+ final int charEndOffset;
+ final int modifiers;
+ final List<MetadataBuilder>? metadata;
+ final OmittedTypeBuilder returnType;
+ final List<NominalVariableBuilder>? typeParameters;
+ final List<FormalParameterBuilder>? formals;
+ final Reference? constructorReference;
+ final Reference? tearOffReference;
+ final NameScheme nameScheme;
+ final String? nativeMethodName;
+ final bool forAbstractClassOrMixin;
+ Token? _beginInitializers;
+
+ AbstractSourceConstructorBuilder? _builder;
+
+ ConstructorFragment(
+ {required this.name,
+ required this.fileUri,
+ required this.startCharOffset,
+ required this.charOffset,
+ required this.charOpenParenOffset,
+ required this.charEndOffset,
+ required this.modifiers,
+ required this.metadata,
+ required this.returnType,
+ required this.typeParameters,
+ required this.formals,
+ required this.constructorReference,
+ required this.tearOffReference,
+ required this.nameScheme,
+ required this.nativeMethodName,
+ required this.forAbstractClassOrMixin,
+ required Token? beginInitializers})
+ : _beginInitializers = beginInitializers;
+
+ Token? get beginInitializers {
+ Token? result = _beginInitializers;
+ // Ensure that we don't hold onto the token.
+ _beginInitializers = null;
+ return result;
+ }
+
+ @override
+ AbstractSourceConstructorBuilder get builder {
+ assert(
+ _builder != null, // Coverage-ignore(suite): Not run.
+ "Builder has not been computed for $this.");
+ return _builder!;
+ }
+
+ void set builder(AbstractSourceConstructorBuilder value) {
+ assert(
+ _builder == null, // Coverage-ignore(suite): Not run.
+ "Builder has already been computed for $this.");
+ _builder = value;
+ }
+
+ @override
+ String toString() => '$runtimeType($name,$fileUri,$charOffset)';
+}
diff --git a/pkg/front_end/lib/src/kernel/constructor_tearoff_lowering.dart b/pkg/front_end/lib/src/kernel/constructor_tearoff_lowering.dart
index 3a45c11..4e48cf9 100644
--- a/pkg/front_end/lib/src/kernel/constructor_tearoff_lowering.dart
+++ b/pkg/front_end/lib/src/kernel/constructor_tearoff_lowering.dart
@@ -30,8 +30,7 @@
(forceCreateLowering ||
compilationUnit.loader.target.backendTarget
.isConstructorTearOffLoweringEnabled)) {
- return _createTearOffProcedure(
- compilationUnit, tearOffName, fileUri, fileOffset, reference);
+ return _createTearOffProcedure(tearOffName, fileUri, fileOffset, reference);
}
return null;
}
@@ -50,8 +49,7 @@
if (forceCreateLowering ||
compilationUnit
.loader.target.backendTarget.isFactoryTearOffLoweringEnabled) {
- return _createTearOffProcedure(
- compilationUnit, tearOffName, fileUri, fileOffset, reference);
+ return _createTearOffProcedure(tearOffName, fileUri, fileOffset, reference);
}
return null;
}
@@ -68,8 +66,7 @@
Reference? reference) {
MemberName tearOffName = new MemberName(
libraryBuilder.libraryName, typedefTearOffName(typedefName, name));
- return _createTearOffProcedure(
- libraryBuilder, tearOffName, fileUri, fileOffset, reference);
+ return _createTearOffProcedure(tearOffName, fileUri, fileOffset, reference);
}
/// Creates the parameters and body for [tearOff] based on
@@ -276,7 +273,7 @@
/// Creates the synthesized [Procedure] node for a tear off lowering by the
/// given [name].
-Procedure _createTearOffProcedure(SourceLibraryBuilder libraryBuilder,
+Procedure _createTearOffProcedure(
MemberName tearOffName, Uri fileUri, int fileOffset, Reference? reference) {
Procedure tearOff = new Procedure(
dummyName, ProcedureKind.Method, new FunctionNode(null),
diff --git a/pkg/front_end/lib/src/source/offset_map.dart b/pkg/front_end/lib/src/source/offset_map.dart
index 6c06b5e..e565841 100644
--- a/pkg/front_end/lib/src/source/offset_map.dart
+++ b/pkg/front_end/lib/src/source/offset_map.dart
@@ -26,6 +26,7 @@
final Map<int, DeclarationFragment> _declarationFragments = {};
final Map<int, FieldFragment> _fields = {};
final Map<int, SourceFunctionBuilder> _constructors = {};
+ final Map<int, ConstructorFragment> _constructorFragments = {};
final Map<int, MethodFragment> _procedures = {};
final Map<int, LibraryPart> _parts = {};
final Map<int, Import> _imports = {};
@@ -102,12 +103,12 @@
}
void registerPrimaryConstructor(
- Token beginToken, SourceFunctionBuilder builder) {
- _constructors[beginToken.charOffset] = builder;
+ Token beginToken, ConstructorFragment builder) {
+ _constructorFragments[beginToken.charOffset] = builder;
}
SourceFunctionBuilder lookupPrimaryConstructor(Token beginToken) {
- return _checkBuilder(_constructors[beginToken.charOffset],
+ return _checkBuilder(_constructorFragments[beginToken.charOffset]?.builder,
'<primary-constructor>', beginToken.charOffset);
}
@@ -116,8 +117,16 @@
_constructors[identifier.nameOffset] = builder;
}
+ void registerConstructorFragment(
+ Identifier identifier, ConstructorFragment fragment) {
+ _constructorFragments[identifier.nameOffset] = fragment;
+ }
+
SourceFunctionBuilder lookupConstructor(Identifier identifier) {
- return _checkBuilder(_constructors[identifier.nameOffset], identifier.name,
+ return _checkBuilder(
+ _constructors[identifier.nameOffset] ??
+ _constructorFragments[identifier.nameOffset]?.builder,
+ identifier.name,
identifier.nameOffset);
}
diff --git a/pkg/front_end/lib/src/source/source_builder_factory.dart b/pkg/front_end/lib/src/source/source_builder_factory.dart
index c491aa8..38e1760 100644
--- a/pkg/front_end/lib/src/source/source_builder_factory.dart
+++ b/pkg/front_end/lib/src/source/source_builder_factory.dart
@@ -57,7 +57,6 @@
import 'name_scheme.dart';
import 'offset_map.dart';
import 'source_class_builder.dart' show SourceClassBuilder;
-import 'source_constructor_builder.dart';
import 'source_enum_builder.dart';
import 'source_factory_builder.dart';
import 'source_function_builder.dart';
@@ -126,6 +125,8 @@
final List<MethodFragment> _nativeMethodFragments = [];
+ final List<ConstructorFragment> _nativeConstructorFragments = [];
+
final LibraryName libraryName;
final LookupScope _compilationUnitScope;
@@ -1693,7 +1694,7 @@
String? nativeMethodName,
{Token? beginInitializers,
required bool forAbstractClassOrMixin}) {
- SourceFunctionBuilder builder = _addConstructor(
+ ConstructorFragment fragment = _addConstructor(
metadata,
modifiers,
constructorName,
@@ -1705,8 +1706,9 @@
charEndOffset,
nativeMethodName,
beginInitializers: beginInitializers,
- forAbstractClassOrMixin: forAbstractClassOrMixin);
- offsetMap.registerConstructor(identifier, builder);
+ forAbstractClassOrMixin: forAbstractClassOrMixin,
+ isConst: modifiers & constMask != 0);
+ offsetMap.registerConstructorFragment(identifier, fragment);
}
@override
@@ -1726,7 +1728,7 @@
List<NominalVariableBuilder>? typeVariables =
nominalVariableCopy?.newVariableBuilders;
- SourceFunctionBuilder builder = _addConstructor(
+ ConstructorFragment builder = _addConstructor(
null,
isConst ? constMask : 0,
constructorName,
@@ -1741,6 +1743,7 @@
charOffset,
/* nativeMethodName = */
null,
+ isConst: isConst,
forAbstractClassOrMixin: false);
offsetMap.registerPrimaryConstructor(beginToken, builder);
}
@@ -1768,7 +1771,7 @@
false));
}
- SourceFunctionBuilder _addConstructor(
+ ConstructorFragment _addConstructor(
List<MetadataBuilder>? metadata,
int modifiers,
String constructorName,
@@ -1780,6 +1783,7 @@
int charEndOffset,
String? nativeMethodName,
{Token? beginInitializers,
+ required bool isConst,
required bool forAbstractClassOrMixin}) {
ContainerType containerType = _declarationFragments.current.containerType;
ContainerName? containerName = _declarationFragments.current.containerName;
@@ -1804,71 +1808,47 @@
.getConstructorMemberName(constructorName, isTearOff: true)
.name);
}
- AbstractSourceConstructorBuilder constructorBuilder;
- if (_declarationFragments.current.kind ==
- DeclarationFragmentKind.extensionTypeDeclaration) {
- constructorBuilder = new SourceExtensionTypeConstructorBuilder(
- metadata,
- modifiers & ~abstractMask,
- addInferableType(),
- constructorName,
- typeVariables,
- formals,
- _parent,
- _compilationUnit.fileUri,
- startCharOffset,
- charOffset,
- charOpenParenOffset,
- charEndOffset,
- constructorReference,
- tearOffReference,
- nameScheme,
- nativeMethodName: nativeMethodName,
- forAbstractClassOrEnumOrMixin: forAbstractClassOrMixin);
- } else {
- constructorBuilder = new DeclaredSourceConstructorBuilder(
- metadata,
- modifiers & ~abstractMask,
- addInferableType(),
- constructorName,
- typeVariables,
- formals,
- _parent,
- _compilationUnit.fileUri,
- startCharOffset,
- charOffset,
- charOpenParenOffset,
- charEndOffset,
- constructorReference,
- tearOffReference,
- nameScheme,
- nativeMethodName: nativeMethodName,
- forAbstractClassOrEnumOrMixin: forAbstractClassOrMixin);
- }
+ ConstructorFragment fragment = new ConstructorFragment(
+ name: constructorName,
+ fileUri: _compilationUnit.fileUri,
+ startCharOffset: startCharOffset,
+ charOffset: charOffset,
+ charOpenParenOffset: charOpenParenOffset,
+ charEndOffset: charEndOffset,
+ modifiers: modifiers & ~abstractMask,
+ metadata: metadata,
+ returnType: addInferableType(),
+ typeParameters: typeVariables,
+ formals: formals,
+ constructorReference: constructorReference,
+ tearOffReference: tearOffReference,
+ nameScheme: nameScheme,
+ nativeMethodName: nativeMethodName,
+ forAbstractClassOrMixin: forAbstractClassOrMixin,
+ beginInitializers: isConst || libraryFeatures.superParameters.isEnabled
+
+ // const constructors will have their initializers compiled and
+ // written into the outline. In case of super-parameters language
+ // feature, the super initializers are required to infer the types
+ // of super parameters.
+ // TODO(johnniwinther): Avoid using a dummy token to ensure building
+ // of constant constructors in the outline phase.
+ ? (beginInitializers ?? new Token.eof(-1))
+ : null);
+
_nominalParameterNameSpaces.pop().addTypeVariables(
_problemReporting, typeVariables,
- ownerName: constructorBuilder.name, allowNameConflict: true);
+ ownerName: constructorName, allowNameConflict: true);
// TODO(johnniwinther): There is no way to pass the tear off reference here.
- _addBuilder(constructorName, constructorBuilder, charOffset,
- getterReference: constructorReference);
+ _addFragment(fragment, getterReference: constructorReference);
if (nativeMethodName != null) {
- _addNativeMethod(constructorBuilder);
+ _addNativeConstructorFragment(fragment);
}
- if (constructorBuilder.isConst) {
+ if (isConst) {
_declarationFragments.current.declaresConstConstructor = true;
}
- if (constructorBuilder.isConst ||
- libraryFeatures.superParameters.isEnabled) {
- // const constructors will have their initializers compiled and written
- // into the outline. In case of super-parameters language feature, the
- // super initializers are required to infer the types of super parameters.
- constructorBuilder.beginInitializers =
- // TODO(johnniwinther): Avoid using a dummy token to ensure building
- // of constant constructors in the outline phase.
- beginInitializers ?? new Token.eof(-1);
- }
- return constructorBuilder;
+ return fragment;
}
@override
@@ -2129,6 +2109,10 @@
_nativeMethodFragments.add(fragment);
}
+ void _addNativeConstructorFragment(ConstructorFragment fragment) {
+ _nativeConstructorFragments.add(fragment);
+ }
+
void _addNativeMethod(SourceFunctionBuilder method) {
_nativeMethods.add(method);
}
@@ -2749,6 +2733,9 @@
for (MethodFragment fragment in _nativeMethodFragments) {
fragment.builder.becomeNative(loader);
}
+ for (ConstructorFragment fragment in _nativeConstructorFragments) {
+ fragment.builder.becomeNative(loader);
+ }
return _nativeMethods.length;
}
diff --git a/pkg/front_end/lib/src/source/source_constructor_builder.dart b/pkg/front_end/lib/src/source/source_constructor_builder.dart
index a1d980c..a46b88c 100644
--- a/pkg/front_end/lib/src/source/source_constructor_builder.dart
+++ b/pkg/front_end/lib/src/source/source_constructor_builder.dart
@@ -79,6 +79,12 @@
extends SourceFunctionBuilderImpl
implements SourceConstructorBuilder, Inferable, ConstructorDeclaration {
@override
+ final SourceLibraryBuilder libraryBuilder;
+
+ @override
+ final DeclarationBuilder declarationBuilder;
+
+ @override
final OmittedTypeBuilder returnType;
final int charOpenParenOffset;
@@ -94,13 +100,15 @@
String name,
List<NominalVariableBuilder>? typeVariables,
List<FormalParameterBuilder>? formals,
- SourceLibraryBuilder compilationUnit,
+ this.libraryBuilder,
+ this.declarationBuilder,
Uri fileUri,
int charOffset,
this.charOpenParenOffset,
- String? nativeMethodName)
+ String? nativeMethodName,
+ this.beginInitializers)
: super(metadata, modifiers, name, typeVariables, formals,
- compilationUnit, fileUri, charOffset, nativeMethodName) {
+ declarationBuilder, fileUri, charOffset, nativeMethodName) {
if (formals != null) {
for (FormalParameterBuilder formal in formals) {
if (formal.isInitializingFormal || formal.isSuperInitializingFormal) {
@@ -111,9 +119,6 @@
}
@override
- DeclarationBuilder get declarationBuilder => super.declarationBuilder!;
-
- @override
bool get isConstructor => true;
@override
@@ -405,7 +410,8 @@
String name,
List<NominalVariableBuilder>? typeVariables,
this.formals,
- SourceLibraryBuilder compilationUnit,
+ SourceLibraryBuilder libraryBuilder,
+ DeclarationBuilder declarationBuilder,
Uri fileUri,
int startCharOffset,
int charOffset,
@@ -416,6 +422,7 @@
NameScheme nameScheme,
{String? nativeMethodName,
required bool forAbstractClassOrEnumOrMixin,
+ required Token? beginInitializers,
bool isSynthetic = false})
: _hasSuperInitializingFormals =
formals?.any((formal) => formal.isSuperInitializingFormal) ?? false,
@@ -427,11 +434,13 @@
name,
typeVariables,
formals,
- compilationUnit,
+ libraryBuilder,
+ declarationBuilder,
fileUri,
charOffset,
charOpenParenOffset,
- nativeMethodName) {
+ nativeMethodName,
+ beginInitializers) {
_constructor = new Constructor(new FunctionNode(null),
name: dummyName,
fileUri: fileUri,
@@ -445,8 +454,8 @@
.attachMember(_constructor);
_constructorTearOff = createConstructorTearOffProcedure(
nameScheme.getConstructorMemberName(name, isTearOff: true),
- compilationUnit,
- compilationUnit.fileUri,
+ libraryBuilder,
+ fileUri,
charOffset,
tearOffReference,
forAbstractClassOrEnumOrMixin: forAbstractClassOrEnumOrMixin);
@@ -1149,7 +1158,8 @@
String name,
List<NominalVariableBuilder>? typeVariables,
List<FormalParameterBuilder>? formals,
- SourceLibraryBuilder compilationUnit,
+ SourceLibraryBuilder libraryBuilder,
+ SourceExtensionTypeDeclarationBuilder declarationBuilder,
Uri fileUri,
int startCharOffset,
int charOffset,
@@ -1159,7 +1169,8 @@
Reference? tearOffReference,
NameScheme nameScheme,
{String? nativeMethodName,
- required bool forAbstractClassOrEnumOrMixin})
+ required bool forAbstractClassOrEnumOrMixin,
+ required Token? beginInitializers})
: _memberName = nameScheme.getDeclaredName(name),
super(
metadata,
@@ -1168,14 +1179,16 @@
name,
typeVariables,
formals,
- compilationUnit,
+ libraryBuilder,
+ declarationBuilder,
fileUri,
charOffset,
charOpenParenOffset,
- nativeMethodName) {
+ nativeMethodName,
+ beginInitializers) {
_constructor = new Procedure(
dummyName, ProcedureKind.Method, new FunctionNode(null),
- fileUri: compilationUnit.fileUri, reference: constructorReference)
+ fileUri: fileUri, reference: constructorReference)
..fileOffset = charOffset
..fileEndOffset = charEndOffset;
nameScheme
@@ -1183,8 +1196,8 @@
.attachMember(_constructor);
_constructorTearOff = createConstructorTearOffProcedure(
nameScheme.getConstructorMemberName(name, isTearOff: true),
- compilationUnit,
- compilationUnit.fileUri,
+ libraryBuilder,
+ fileUri,
charOffset,
tearOffReference,
forAbstractClassOrEnumOrMixin: forAbstractClassOrEnumOrMixin,
diff --git a/pkg/front_end/lib/src/source/source_enum_builder.dart b/pkg/front_end/lib/src/source/source_enum_builder.dart
index 2429e3b..1345804 100644
--- a/pkg/front_end/lib/src/source/source_enum_builder.dart
+++ b/pkg/front_end/lib/src/source/source_enum_builder.dart
@@ -369,6 +369,7 @@
/* typeParameters = */ null,
/* formals = */ [],
libraryBuilder,
+ this,
fileUri,
charOffset,
charOffset,
@@ -382,12 +383,11 @@
containerType: ContainerType.Class,
libraryName: libraryName),
forAbstractClassOrEnumOrMixin: true,
- isSynthetic: true);
- // Trick the constructor to be built during the outline phase.
- // TODO(johnniwinther): Avoid relying on [beginInitializers] to ensure
- // building constructors creation during the outline phase.
- synthesizedDefaultConstructorBuilder!.beginInitializers =
- new Token.eof(-1);
+ isSynthetic: true,
+ // Trick the constructor to be built during the outline phase.
+ // TODO(johnniwinther): Avoid relying on [beginInitializers] to
+ // ensure building constructors creation during the outline phase.
+ beginInitializers: new Token.eof(-1));
synthesizedDefaultConstructorBuilder!
.registerInitializedField(valuesBuilder);
nameSpace.addConstructor("", synthesizedDefaultConstructorBuilder!);
diff --git a/pkg/front_end/lib/src/source/type_parameter_scope_builder.dart b/pkg/front_end/lib/src/source/type_parameter_scope_builder.dart
index 6b5cd46..23e0200 100644
--- a/pkg/front_end/lib/src/source/type_parameter_scope_builder.dart
+++ b/pkg/front_end/lib/src/source/type_parameter_scope_builder.dart
@@ -19,6 +19,7 @@
import 'name_scheme.dart';
import 'source_builder_factory.dart';
import 'source_class_builder.dart';
+import 'source_constructor_builder.dart';
import 'source_enum_builder.dart';
import 'source_extension_builder.dart';
import 'source_extension_type_declaration_builder.dart';
@@ -408,6 +409,54 @@
fragment.builder = procedureBuilder;
builders.add(new _AddBuilder(fragment.name, procedureBuilder,
fragment.fileUri, fragment.charOffset));
+ case ConstructorFragment():
+ AbstractSourceConstructorBuilder constructorBuilder;
+ if (declarationBuilder is SourceExtensionTypeDeclarationBuilder) {
+ constructorBuilder = new SourceExtensionTypeConstructorBuilder(
+ fragment.metadata,
+ fragment.modifiers,
+ fragment.returnType,
+ fragment.name,
+ fragment.typeParameters,
+ fragment.formals,
+ enclosingLibraryBuilder,
+ declarationBuilder,
+ fragment.fileUri,
+ fragment.startCharOffset,
+ fragment.charOffset,
+ fragment.charOpenParenOffset,
+ fragment.charEndOffset,
+ fragment.constructorReference,
+ fragment.tearOffReference,
+ fragment.nameScheme,
+ nativeMethodName: fragment.nativeMethodName,
+ forAbstractClassOrEnumOrMixin: fragment.forAbstractClassOrMixin,
+ beginInitializers: fragment.beginInitializers);
+ } else {
+ constructorBuilder = new DeclaredSourceConstructorBuilder(
+ fragment.metadata,
+ fragment.modifiers,
+ fragment.returnType,
+ fragment.name,
+ fragment.typeParameters,
+ fragment.formals,
+ enclosingLibraryBuilder,
+ declarationBuilder!,
+ fragment.fileUri,
+ fragment.startCharOffset,
+ fragment.charOffset,
+ fragment.charOpenParenOffset,
+ fragment.charEndOffset,
+ fragment.constructorReference,
+ fragment.tearOffReference,
+ fragment.nameScheme,
+ nativeMethodName: fragment.nativeMethodName,
+ forAbstractClassOrEnumOrMixin: fragment.forAbstractClassOrMixin,
+ beginInitializers: fragment.beginInitializers);
+ }
+ fragment.builder = constructorBuilder;
+ builders.add(new _AddBuilder(fragment.name, constructorBuilder,
+ fragment.fileUri, fragment.charOffset));
}
}
}