[cfe] Create constructors through fragments

Change-Id: If2a7095c09dcf2d73d326b6ba6d796acfa882c55
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/408780
Reviewed-by: Chloe Stefantsova <cstefantsova@google.com>
Commit-Queue: Johnni Winther <johnniwinther@google.com>
This commit is contained in:
Johnni Winther
2025-02-10 07:09:07 -08:00
committed by Commit Queue
parent 3b750c5545
commit a78235cf01
24 changed files with 1957 additions and 1348 deletions
@@ -225,7 +225,7 @@ class FormalParameterBuilder extends BuilderImpl
void finalizeInitializingFormal(
DeclarationBuilder declarationBuilder,
ConstructorDeclaration constructorDeclaration,
ConstructorDeclarationBuilder constructorDeclaration,
ClassHierarchyBase hierarchy) {
String fieldName = isWildcardLoweredFormalParameter(name) ? '_' : name;
Builder? fieldBuilder = declarationBuilder.lookupLocalMember(fieldName);
@@ -22,7 +22,7 @@ class ConstructorFragment implements Fragment, FunctionFragment {
final bool forAbstractClassOrMixin;
Token? _beginInitializers;
AbstractSourceConstructorBuilder? _builder;
SourceConstructorBuilderImpl? _builder;
ConstructorFragment(
{required this.constructorName,
@@ -55,12 +55,12 @@ class ConstructorFragment implements Fragment, FunctionFragment {
}
@override
AbstractSourceConstructorBuilder get builder {
SourceConstructorBuilderImpl get builder {
assert(_builder != null, "Builder has not been computed for $this.");
return _builder!;
}
void set builder(AbstractSourceConstructorBuilder value) {
void set builder(SourceConstructorBuilderImpl value) {
assert(_builder == null, "Builder has already been computed for $this.");
_builder = value;
}
@@ -91,8 +91,7 @@ class _ConstructorBodyBuildingContext implements FunctionBodyBuildingContext {
// constructor body. An error is reported by the parser but we skip
// the body here to avoid overwriting the already lowering const
// constructor.
!(_fragment.builder is SourceExtensionTypeConstructorBuilder &&
_fragment.modifiers.isConst);
!(_fragment.builder.isExtensionTypeMember && _fragment.modifiers.isConst);
@override
LocalScope computeFormalParameterScope(LookupScope typeParameterScope) {
@@ -0,0 +1,677 @@
// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'package:kernel/ast.dart';
import 'package:kernel/type_algebra.dart';
import '../../builder/declaration_builders.dart';
import '../../builder/formal_parameter_builder.dart';
import '../../builder/metadata_builder.dart';
import '../../builder/type_builder.dart';
import '../../kernel/internal_ast.dart';
import '../../kernel/kernel_helper.dart';
import '../../source/name_scheme.dart';
import '../../source/source_class_builder.dart';
import '../../source/source_constructor_builder.dart';
import '../../source/source_extension_type_declaration_builder.dart';
import '../../source/source_library_builder.dart';
import '../../source/source_member_builder.dart';
import '../fragment.dart';
import 'encoding.dart';
abstract class ConstructorDeclaration {
List<MetadataBuilder>? get metadata;
OmittedTypeBuilder get returnType;
List<NominalParameterBuilder>? get typeParameters;
List<FormalParameterBuilder>? get formals;
Member get constructor;
Procedure? get tearOff;
FunctionNode get function;
Member get readTarget;
Reference get readTargetReference;
Member get invokeTarget;
Reference get invokeTargetReference;
void registerFunctionBody(Statement value);
void registerNoBodyConstructor();
VariableDeclaration? get thisVariable;
List<TypeParameter>? get thisTypeParameters;
List<Initializer> get initializers;
void createNode(
{required String name,
required SourceLibraryBuilder libraryBuilder,
required NameScheme nameScheme,
required Reference? constructorReference,
required Reference? tearOffReference});
void buildOutlineNodes(
BuildNodesCallback f, {
required SourceConstructorBuilder constructorBuilder,
required SourceLibraryBuilder libraryBuilder,
required Member declarationConstructor,
required List<DelayedDefaultValueCloner> delayedDefaultValueCloners,
});
void prepareInitializers();
void prependInitializer(Initializer initializer);
void becomeNative();
VariableDeclaration? getTearOffParameter(int index);
void finishAugmentation(SourceConstructorBuilder origin);
Substitution computeFieldTypeSubstitution(
DeclarationBuilder declarationBuilder);
void buildBody();
bool get isRedirecting;
bool get hasSuperInitializingFormals;
void addSuperParameterDefaultValueCloners(
{required List<DelayedDefaultValueCloner> delayedDefaultValueCloners,
required Member superTarget,
required List<int?>? positionalSuperParameters,
required List<String>? namedSuperParameters,
required SourceLibraryBuilder libraryBuilder});
}
mixin RegularConstructorDeclarationMixin implements ConstructorDeclaration {
RegularConstructorEncoding get _encoding;
@override
// Coverage-ignore(suite): Not run.
Member get constructor => _encoding.constructor;
@override
// Coverage-ignore(suite): Not run.
Procedure? get tearOff => _encoding.constructorTearOff;
@override
FunctionNode get function => _encoding.function;
@override
Member get readTarget => _encoding.readTarget;
@override
// Coverage-ignore(suite): Not run.
Reference get readTargetReference => _encoding.readTargetReference;
@override
Member get invokeTarget => _encoding.invokeTarget;
@override
// Coverage-ignore(suite): Not run.
Reference get invokeTargetReference => _encoding.invokeTargetReference;
@override
void registerFunctionBody(Statement value) {
_encoding.registerFunctionBody(value);
}
@override
void registerNoBodyConstructor() {
_encoding.registerNoBodyConstructor();
}
@override
VariableDeclaration? get thisVariable => null;
@override
List<TypeParameter>? get thisTypeParameters => null;
@override
List<Initializer> get initializers => _encoding.initializers;
@override
void prepareInitializers() {
_encoding.prepareInitializers();
}
@override
void prependInitializer(Initializer initializer) {
_encoding.prependInitializer(initializer);
}
@override
void becomeNative() {
_encoding.becomeNative();
}
@override
VariableDeclaration? getTearOffParameter(int index) {
return _encoding.getTearOffParameter(index);
}
@override
void finishAugmentation(SourceConstructorBuilder origin) {
_encoding.finishAugmentation(origin);
}
@override
Substitution computeFieldTypeSubstitution(
DeclarationBuilder declarationBuilder) {
// Nothing to substitute. Regular generative constructors don't have their
// own type parameters.
return Substitution.empty;
}
@override
void buildBody() {}
@override
bool get isRedirecting {
for (Initializer initializer in initializers) {
if (initializer is RedirectingInitializer) {
return true;
}
}
return false;
}
@override
late final bool hasSuperInitializingFormals =
formals?.any((formal) => formal.isSuperInitializingFormal) ?? false;
@override
void addSuperParameterDefaultValueCloners(
{required List<DelayedDefaultValueCloner> delayedDefaultValueCloners,
required Member superTarget,
required List<int?>? positionalSuperParameters,
required List<String>? namedSuperParameters,
required SourceLibraryBuilder libraryBuilder}) {
_encoding.addSuperParameterDefaultValueCloners(
delayedDefaultValueCloners: delayedDefaultValueCloners,
superTarget: superTarget,
positionalSuperParameters: positionalSuperParameters,
namedSuperParameters: namedSuperParameters,
libraryBuilder: libraryBuilder);
}
}
class RegularConstructorDeclaration
with RegularConstructorDeclarationMixin
implements ConstructorDeclaration {
final ConstructorFragment _fragment;
final List<FormalParameterBuilder>? _syntheticFormals;
@override
final RegularConstructorEncoding _encoding;
@override
final List<NominalParameterBuilder>? typeParameters;
RegularConstructorDeclaration(this._fragment,
{required List<FormalParameterBuilder>? syntheticFormals,
required this.typeParameters})
: _syntheticFormals = syntheticFormals,
_encoding = new RegularConstructorEncoding(
isExternal: _fragment.modifiers.isExternal);
@override
List<MetadataBuilder>? get metadata => _fragment.metadata;
@override
OmittedTypeBuilder get returnType => _fragment.returnType;
@override
late final List<FormalParameterBuilder>? formals = _syntheticFormals != null
? [..._syntheticFormals, ...?_fragment.formals]
: _fragment.formals;
@override
void createNode(
{required String name,
required SourceLibraryBuilder libraryBuilder,
required NameScheme nameScheme,
required Reference? constructorReference,
required Reference? tearOffReference}) {
_encoding.createNode(
name: name,
libraryBuilder: libraryBuilder,
nameScheme: nameScheme,
constructorReference: constructorReference,
tearOffReference: tearOffReference,
fileUri: _fragment.fileUri,
startOffset: _fragment.startOffset,
fileOffset: _fragment.fullNameOffset,
endOffset: _fragment.endOffset,
isSynthetic: false,
forAbstractClassOrEnumOrMixin: _fragment.forAbstractClassOrMixin);
}
@override
void buildOutlineNodes(BuildNodesCallback f,
{required SourceConstructorBuilder constructorBuilder,
required SourceLibraryBuilder libraryBuilder,
required Member declarationConstructor,
required List<DelayedDefaultValueCloner> delayedDefaultValueCloners}) {
_encoding.buildOutlineNodes(f,
constructorBuilder: constructorBuilder,
libraryBuilder: libraryBuilder,
declarationBuilder:
constructorBuilder.declarationBuilder as SourceClassBuilder,
declarationConstructor: declarationConstructor,
formalsOffset: _fragment.formalsOffset,
isConst: _fragment.modifiers.isConst,
returnType: returnType,
typeParameters: typeParameters,
formals: formals,
delayedDefaultValueCloners: delayedDefaultValueCloners);
}
}
// Coverage-ignore(suite): Not run.
class PrimaryConstructorDeclaration
with RegularConstructorDeclarationMixin
implements ConstructorDeclaration {
final PrimaryConstructorFragment _fragment;
@override
final RegularConstructorEncoding _encoding;
PrimaryConstructorDeclaration(this._fragment)
: _encoding = new RegularConstructorEncoding(
isExternal: _fragment.modifiers.isExternal);
@override
OmittedTypeBuilder get returnType => _fragment.returnType;
@override
List<MetadataBuilder>? get metadata => null;
@override
List<FormalParameterBuilder>? get formals => _fragment.formals;
@override
List<NominalParameterBuilder>? get typeParameters => null;
@override
void createNode(
{required String name,
required SourceLibraryBuilder libraryBuilder,
required NameScheme nameScheme,
required Reference? constructorReference,
required Reference? tearOffReference}) {
_encoding.createNode(
name: name,
libraryBuilder: libraryBuilder,
nameScheme: nameScheme,
constructorReference: constructorReference,
tearOffReference: tearOffReference,
fileUri: _fragment.fileUri,
startOffset: _fragment.startOffset,
fileOffset: _fragment.fileOffset,
// TODO(johnniwinther): Provide `endOffset`.
endOffset: _fragment.formalsOffset,
isSynthetic: false,
forAbstractClassOrEnumOrMixin: _fragment.forAbstractClassOrMixin);
}
@override
void buildOutlineNodes(BuildNodesCallback f,
{required SourceConstructorBuilder constructorBuilder,
required SourceLibraryBuilder libraryBuilder,
required Member declarationConstructor,
required List<DelayedDefaultValueCloner> delayedDefaultValueCloners}) {
_encoding.buildOutlineNodes(f,
constructorBuilder: constructorBuilder,
libraryBuilder: libraryBuilder,
declarationBuilder:
constructorBuilder.declarationBuilder as SourceClassBuilder,
declarationConstructor: declarationConstructor,
formalsOffset: _fragment.formalsOffset,
isConst: _fragment.modifiers.isConst,
returnType: returnType,
typeParameters: typeParameters,
formals: formals,
delayedDefaultValueCloners: delayedDefaultValueCloners);
}
}
class DefaultEnumConstructorDeclaration
with RegularConstructorDeclarationMixin
implements ConstructorDeclaration {
final Uri _fileUri;
final int _fileOffset;
@override
final OmittedTypeBuilder returnType;
@override
final List<FormalParameterBuilder> formals;
@override
final RegularConstructorEncoding _encoding =
new RegularConstructorEncoding(isExternal: false);
DefaultEnumConstructorDeclaration(
{required this.returnType,
required this.formals,
required Uri fileUri,
required int fileOffset})
: _fileUri = fileUri,
_fileOffset = fileOffset;
@override
List<MetadataBuilder>? get metadata => null;
@override
List<NominalParameterBuilder>? get typeParameters => null;
@override
void createNode(
{required String name,
required SourceLibraryBuilder libraryBuilder,
required NameScheme nameScheme,
required Reference? constructorReference,
required Reference? tearOffReference}) {
_encoding.createNode(
name: name,
libraryBuilder: libraryBuilder,
nameScheme: nameScheme,
constructorReference: constructorReference,
tearOffReference: tearOffReference,
fileUri: _fileUri,
startOffset: _fileOffset,
fileOffset: _fileOffset,
endOffset: _fileOffset,
isSynthetic: true,
forAbstractClassOrEnumOrMixin: true);
}
@override
void buildOutlineNodes(BuildNodesCallback f,
{required SourceConstructorBuilder constructorBuilder,
required SourceLibraryBuilder libraryBuilder,
required Member declarationConstructor,
required List<DelayedDefaultValueCloner> delayedDefaultValueCloners}) {
_encoding.buildOutlineNodes(f,
constructorBuilder: constructorBuilder,
libraryBuilder: libraryBuilder,
declarationBuilder:
constructorBuilder.declarationBuilder as SourceClassBuilder,
declarationConstructor: declarationConstructor,
formalsOffset: _fileOffset,
isConst: true,
returnType: returnType,
typeParameters: typeParameters,
formals: formals,
delayedDefaultValueCloners: delayedDefaultValueCloners);
}
}
mixin ExtensionTypeConstructorDeclarationMixin
implements ConstructorDeclaration {
ExtensionTypeConstructorEncoding get _encoding;
@override
// Coverage-ignore(suite): Not run.
Member get constructor => _encoding.constructor;
@override
// Coverage-ignore(suite): Not run.
Procedure? get tearOff => _encoding.constructorTearOff;
@override
FunctionNode get function => _encoding.function;
@override
Member get readTarget => _encoding.readTarget;
@override
// Coverage-ignore(suite): Not run.
Reference get readTargetReference => _encoding.readTargetReference;
@override
Member get invokeTarget => _encoding.invokeTarget;
@override
// Coverage-ignore(suite): Not run.
Reference get invokeTargetReference => _encoding.invokeTargetReference;
@override
void registerFunctionBody(Statement value) {
_encoding.registerFunctionBody(value);
}
@override
void registerNoBodyConstructor() {
_encoding.registerNoBodyConstructor();
}
@override
VariableDeclaration? get thisVariable => _encoding.thisVariable;
@override
List<TypeParameter>? get thisTypeParameters => _encoding.thisTypeParameters;
@override
List<Initializer> get initializers => _encoding.initializers;
@override
void prepareInitializers() {
_encoding.prepareInitializers();
}
@override
void prependInitializer(Initializer initializer) {
_encoding.prependInitializer(initializer);
}
@override
void becomeNative() {
throw new UnsupportedError("$runtimeType.becomeNative()");
}
@override
VariableDeclaration? getTearOffParameter(int index) {
return _encoding.getTearOffParameter(index);
}
@override
void finishAugmentation(SourceConstructorBuilder origin) {
throw new UnsupportedError('$runtimeType.finishAugmentation');
}
@override
Substitution computeFieldTypeSubstitution(
DeclarationBuilder declarationBuilder) {
if (typeParameters != null) {
assert(
declarationBuilder.typeParameters!.length == typeParameters?.length);
return Substitution.fromPairs(
(declarationBuilder as SourceExtensionTypeDeclarationBuilder)
.extensionTypeDeclaration
.typeParameters,
new List<DartType>.generate(
declarationBuilder.typeParameters!.length,
(int index) => new TypeParameterType.withDefaultNullability(
function.typeParameters[index])));
} else {
return Substitution.empty;
}
}
@override
void buildBody() {
_encoding.buildBody();
}
@override
bool get isRedirecting {
for (Initializer initializer in initializers) {
if (initializer is ExtensionTypeRedirectingInitializer) {
return true;
}
}
return false;
}
@override
late final bool hasSuperInitializingFormals =
formals?.any((formal) => formal.isSuperInitializingFormal) ?? false;
@override
void addSuperParameterDefaultValueCloners(
{required List<DelayedDefaultValueCloner> delayedDefaultValueCloners,
required Member superTarget,
required List<int?>? positionalSuperParameters,
required List<String>? namedSuperParameters,
required SourceLibraryBuilder libraryBuilder}) {
throw new UnsupportedError(
'$runtimeType.addSuperParameterDefaultValueCloners');
}
}
class ExtensionTypeConstructorDeclaration
with ExtensionTypeConstructorDeclarationMixin
implements ConstructorDeclaration {
final ConstructorFragment _fragment;
@override
final List<NominalParameterBuilder>? typeParameters;
@override
final ExtensionTypeConstructorEncoding _encoding;
ExtensionTypeConstructorDeclaration(this._fragment,
{required this.typeParameters})
: _encoding = new ExtensionTypeConstructorEncoding(
isExternal: _fragment.modifiers.isExternal);
@override
List<MetadataBuilder>? get metadata => _fragment.metadata;
@override
OmittedTypeBuilder get returnType => _fragment.returnType;
@override
List<FormalParameterBuilder>? get formals => _fragment.formals;
@override
void createNode(
{required String name,
required SourceLibraryBuilder libraryBuilder,
required NameScheme nameScheme,
required Reference? constructorReference,
required Reference? tearOffReference}) {
_encoding.createNode(
name: name,
libraryBuilder: libraryBuilder,
nameScheme: nameScheme,
constructorReference: constructorReference,
tearOffReference: tearOffReference,
fileUri: _fragment.fileUri,
fileOffset: _fragment.fullNameOffset,
endOffset: _fragment.endOffset,
forAbstractClassOrEnumOrMixin: _fragment.forAbstractClassOrMixin);
}
@override
void buildOutlineNodes(BuildNodesCallback f,
{required SourceConstructorBuilder constructorBuilder,
required SourceLibraryBuilder libraryBuilder,
required Member declarationConstructor,
required List<DelayedDefaultValueCloner> delayedDefaultValueCloners}) {
_encoding.buildOutlineNodes(f,
constructorBuilder: constructorBuilder,
libraryBuilder: libraryBuilder,
declarationBuilder: constructorBuilder.declarationBuilder
as SourceExtensionTypeDeclarationBuilder,
declarationConstructor: declarationConstructor,
fileOffset: _fragment.fullNameOffset,
formalsOffset: _fragment.formalsOffset,
isConst: _fragment.modifiers.isConst,
returnType: returnType,
typeParameters: typeParameters,
formals: formals,
delayedDefaultValueCloners: delayedDefaultValueCloners);
}
}
class ExtensionTypePrimaryConstructorDeclaration
with ExtensionTypeConstructorDeclarationMixin
implements ConstructorDeclaration {
final PrimaryConstructorFragment _fragment;
@override
final List<NominalParameterBuilder>? typeParameters;
@override
final ExtensionTypeConstructorEncoding _encoding;
ExtensionTypePrimaryConstructorDeclaration(this._fragment,
{required this.typeParameters})
: _encoding = new ExtensionTypeConstructorEncoding(
isExternal: _fragment.modifiers.isExternal);
@override
List<MetadataBuilder>? get metadata => null;
@override
OmittedTypeBuilder get returnType => _fragment.returnType;
@override
List<FormalParameterBuilder>? get formals => _fragment.formals;
@override
void createNode(
{required String name,
required SourceLibraryBuilder libraryBuilder,
required NameScheme nameScheme,
required Reference? constructorReference,
required Reference? tearOffReference}) {
_encoding.createNode(
name: name,
libraryBuilder: libraryBuilder,
nameScheme: nameScheme,
constructorReference: constructorReference,
tearOffReference: tearOffReference,
fileUri: _fragment.fileUri,
fileOffset: _fragment.fileOffset,
// TODO(johnniwinther): Provide `endOffset`.
endOffset: _fragment.formalsOffset,
forAbstractClassOrEnumOrMixin: _fragment.forAbstractClassOrMixin);
}
@override
void buildOutlineNodes(BuildNodesCallback f,
{required SourceConstructorBuilder constructorBuilder,
required SourceLibraryBuilder libraryBuilder,
required Member declarationConstructor,
required List<DelayedDefaultValueCloner> delayedDefaultValueCloners}) {
_encoding.buildOutlineNodes(f,
constructorBuilder: constructorBuilder,
libraryBuilder: libraryBuilder,
declarationBuilder: constructorBuilder.declarationBuilder
as SourceExtensionTypeDeclarationBuilder,
declarationConstructor: declarationConstructor,
fileOffset: _fragment.fileOffset,
formalsOffset: _fragment.formalsOffset,
isConst: _fragment.modifiers.isConst,
returnType: returnType,
typeParameters: typeParameters,
formals: formals,
delayedDefaultValueCloners: delayedDefaultValueCloners);
}
}
@@ -0,0 +1,564 @@
// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'package:kernel/ast.dart';
import '../../api_prototype/lowering_predicates.dart';
import '../../builder/declaration_builders.dart';
import '../../builder/formal_parameter_builder.dart';
import '../../builder/omitted_type_builder.dart';
import '../../builder/type_builder.dart';
import '../../kernel/constructor_tearoff_lowering.dart';
import '../../kernel/internal_ast.dart';
import '../../kernel/kernel_helper.dart';
import '../../source/name_scheme.dart';
import '../../source/source_class_builder.dart';
import '../../source/source_constructor_builder.dart';
import '../../source/source_extension_type_declaration_builder.dart';
import '../../source/source_function_builder.dart';
import '../../source/source_library_builder.dart';
import '../../source/source_member_builder.dart';
import '../../type_inference/type_schema.dart';
class RegularConstructorEncoding {
late final Constructor _constructor;
late final Procedure? _constructorTearOff;
final bool _isExternal;
Statement? bodyInternal;
RegularConstructorEncoding({required bool isExternal})
: _isExternal = isExternal;
Member get readTarget =>
_constructorTearOff ??
// The case is need to ensure that the upper bound is [Member] and not
// [GenericFunction].
_constructor as Member;
// Coverage-ignore(suite): Not run.
Reference get readTargetReference =>
(_constructorTearOff ?? _constructor).reference;
Member get invokeTarget => _constructor;
// Coverage-ignore(suite): Not run.
Reference get invokeTargetReference => _constructor.reference;
void registerFunctionBody(Statement value) {
function.body = value..parent = function;
}
void registerNoBodyConstructor() {
if (!_isExternal) {
registerFunctionBody(new EmptyStatement());
}
}
FunctionNode get function => _constructor.function;
void createNode(
{required String name,
required SourceLibraryBuilder libraryBuilder,
required NameScheme nameScheme,
required Reference? constructorReference,
required Reference? tearOffReference,
required Uri fileUri,
required int startOffset,
required int fileOffset,
required int endOffset,
required bool isSynthetic,
required bool forAbstractClassOrEnumOrMixin}) {
_constructor = new Constructor(
new FunctionNode(_isExternal ? null : new EmptyStatement()),
name: dummyName,
fileUri: fileUri,
reference: constructorReference,
isSynthetic: isSynthetic)
..startFileOffset = startOffset
..fileOffset = fileOffset
..fileEndOffset = endOffset;
nameScheme
.getConstructorMemberName(name, isTearOff: false)
.attachMember(_constructor);
_constructorTearOff = createConstructorTearOffProcedure(
nameScheme.getConstructorMemberName(name, isTearOff: true),
libraryBuilder,
fileUri,
fileOffset,
tearOffReference,
forAbstractClassOrEnumOrMixin: forAbstractClassOrEnumOrMixin);
}
// Coverage-ignore(suite): Not run.
Member get constructor => _constructor;
// Coverage-ignore(suite): Not run.
Procedure? get constructorTearOff => _constructorTearOff;
List<Initializer> get initializers => _constructor.initializers;
void buildOutlineNodes(
BuildNodesCallback f, {
required SourceConstructorBuilder constructorBuilder,
required SourceLibraryBuilder libraryBuilder,
required SourceClassBuilder declarationBuilder,
required Member declarationConstructor,
required int formalsOffset,
required bool isConst,
required TypeBuilder returnType,
required List<NominalParameterBuilder>? typeParameters,
required List<FormalParameterBuilder>? formals,
required List<DelayedDefaultValueCloner> delayedDefaultValueCloners,
}) {
_build(
constructorBuilder: constructorBuilder,
libraryBuilder: libraryBuilder,
classBuilder: declarationBuilder,
declarationConstructor: declarationConstructor,
formalsOffset: formalsOffset,
isConst: isConst,
returnType: returnType,
typeParameters: typeParameters,
formals: formals,
delayedDefaultValueCloners: delayedDefaultValueCloners);
f(
member: _constructor,
tearOff: _constructorTearOff,
kind: BuiltMemberKind.Constructor);
}
bool _hasBeenBuilt = false;
void _build({
required SourceConstructorBuilder constructorBuilder,
required SourceLibraryBuilder libraryBuilder,
required SourceClassBuilder classBuilder,
required Member declarationConstructor,
required int formalsOffset,
required bool isConst,
required TypeBuilder returnType,
required List<NominalParameterBuilder>? typeParameters,
required List<FormalParameterBuilder>? formals,
required List<DelayedDefaultValueCloner> delayedDefaultValueCloners,
}) {
if (!_hasBeenBuilt) {
// According to the specification §9.3 the return type of a constructor
// function is its enclosing class.
function.asyncMarker = AsyncMarker.Sync;
buildTypeParametersAndFormals(
libraryBuilder, function, typeParameters, formals,
classTypeParameters: null, supportsTypeParameters: false);
Class enclosingClass = classBuilder.cls;
List<DartType> typeParameterTypes = <DartType>[];
for (int i = 0; i < enclosingClass.typeParameters.length; i++) {
TypeParameter typeParameter = enclosingClass.typeParameters[i];
typeParameterTypes
.add(new TypeParameterType.withDefaultNullability(typeParameter));
}
InterfaceType type = new InterfaceType(
enclosingClass, Nullability.nonNullable, typeParameterTypes);
returnType.registerInferredType(type);
_constructor.function.fileOffset = formalsOffset;
_constructor.function.fileEndOffset = _constructor.fileEndOffset;
_constructor.function.typeParameters = const <TypeParameter>[];
_constructor.isConst = isConst;
_constructor.isExternal = _isExternal;
if (_constructorTearOff != null) {
DelayedDefaultValueCloner delayedDefaultValueCloner =
buildConstructorTearOffProcedure(
tearOff: _constructorTearOff,
declarationConstructor: declarationConstructor,
implementationConstructor: _constructor,
enclosingDeclarationTypeParameters:
classBuilder.cls.typeParameters,
libraryBuilder: libraryBuilder);
delayedDefaultValueCloners.add(delayedDefaultValueCloner);
}
_hasBeenBuilt = true;
}
if (formals != null) {
bool needsInference = false;
for (FormalParameterBuilder formal in formals) {
if (formal.type is InferableTypeBuilder &&
(formal.isInitializingFormal || formal.isSuperInitializingFormal)) {
formal.variable!.type = const UnknownType();
needsInference = true;
} else if (!formal.hasDeclaredInitializer &&
formal.isSuperInitializingFormal) {
needsInference = true;
}
}
if (needsInference) {
libraryBuilder.loader
.registerConstructorToBeInferred(_constructor, constructorBuilder);
}
}
}
void prepareInitializers() {
// For const constructors we parse initializers already at the outlining
// stage, there is no easy way to make body building stage skip initializer
// parsing, so we simply clear parsed initializers and rebuild them
// again.
// For when doing an experimental incremental compilation they are also
// potentially done more than once (because it rebuilds the bodies of an old
// compile), and so we also clear them.
// Note: this method clears both initializers from the target Kernel node
// and internal state associated with parsing initializers.
_constructor.initializers = [];
//redirectingInitializer = null;
//superInitializer = null;
}
void prependInitializer(Initializer initializer) {
initializer.parent = _constructor;
_constructor.initializers.insert(0, initializer);
}
void becomeNative() {
_constructor.isExternal = true;
}
VariableDeclaration? getTearOffParameter(int index) {
Procedure? constructorTearOff = _constructorTearOff;
if (constructorTearOff != null) {
if (index < constructorTearOff.function.positionalParameters.length) {
return constructorTearOff.function.positionalParameters[index];
} else {
index -= constructorTearOff.function.positionalParameters.length;
if (index < constructorTearOff.function.namedParameters.length) {
return constructorTearOff.function.namedParameters[index];
}
}
}
return null;
}
void finishAugmentation(SourceConstructorBuilder origin) {
finishConstructorAugmentation(
origin.invokeTarget as Constructor, _constructor);
if (_constructorTearOff != null) {
finishProcedureAugmentation(
origin.readTarget as Procedure, _constructorTearOff);
}
}
bool _hasAddedDefaultValueCloners = false;
void addSuperParameterDefaultValueCloners(
{required List<DelayedDefaultValueCloner> delayedDefaultValueCloners,
required Member superTarget,
required List<int?>? positionalSuperParameters,
required List<String>? namedSuperParameters,
required SourceLibraryBuilder libraryBuilder}) {
if (!_hasAddedDefaultValueCloners) {
// If this constructor formals are part of a cyclic dependency this
// might be called more than once.
delayedDefaultValueCloners.add(new DelayedDefaultValueCloner(
superTarget, invokeTarget,
positionalSuperParameters: positionalSuperParameters ?? const <int>[],
namedSuperParameters: namedSuperParameters ?? const <String>[],
isOutlineNode: true,
libraryBuilder: libraryBuilder));
if (_constructorTearOff != null) {
delayedDefaultValueCloners.add(new DelayedDefaultValueCloner(
superTarget, _constructorTearOff,
positionalSuperParameters:
positionalSuperParameters ?? const <int>[],
namedSuperParameters: namedSuperParameters ?? const <String>[],
isOutlineNode: true,
libraryBuilder: libraryBuilder));
}
_hasAddedDefaultValueCloners = true;
}
}
}
class ExtensionTypeConstructorEncoding {
late final Procedure _constructor;
late final Procedure? _constructorTearOff;
final bool _isExternal;
Statement? bodyInternal;
/// If this procedure is an extension instance member or extension type
/// instance member, [_thisVariable] holds the synthetically added `this`
/// parameter.
VariableDeclaration? _thisVariable;
/// If this procedure is an extension instance member or extension type
/// instance member, [_thisTypeParameters] holds the type parameters copied
/// from the extension/extension type declaration.
List<TypeParameter>? _thisTypeParameters;
List<Initializer> initializers = [];
ExtensionTypeConstructorEncoding({required bool isExternal})
: _isExternal = isExternal;
Member get readTarget =>
_constructorTearOff ?? // Coverage-ignore(suite): Not run.
_constructor;
// Coverage-ignore(suite): Not run.
Reference get readTargetReference =>
(_constructorTearOff ?? _constructor).reference;
Member get invokeTarget => _constructor;
// Coverage-ignore(suite): Not run.
Reference get invokeTargetReference => _constructor.reference;
void registerFunctionBody(Statement value) {
function.body = value..parent = function;
}
void registerNoBodyConstructor() {
if (!_hasBuiltBody && !_isExternal) {
registerFunctionBody(new EmptyStatement());
}
}
FunctionNode get function => _constructor.function;
void createNode(
{required String name,
required SourceLibraryBuilder libraryBuilder,
required NameScheme nameScheme,
required Reference? constructorReference,
required Reference? tearOffReference,
required Uri fileUri,
required int fileOffset,
required int endOffset,
required bool forAbstractClassOrEnumOrMixin}) {
_constructor = new Procedure(dummyName, ProcedureKind.Method,
new FunctionNode(_isExternal ? null : new EmptyStatement()),
fileUri: fileUri, reference: constructorReference)
..fileOffset = fileOffset
..fileEndOffset = endOffset;
nameScheme
.getConstructorMemberName(name, isTearOff: false)
.attachMember(_constructor);
_constructorTearOff = createConstructorTearOffProcedure(
nameScheme.getConstructorMemberName(name, isTearOff: true),
libraryBuilder,
fileUri,
fileOffset,
tearOffReference,
forAbstractClassOrEnumOrMixin: forAbstractClassOrEnumOrMixin,
forceCreateLowering: true)
?..isExtensionTypeMember = true;
}
// Coverage-ignore(suite): Not run.
Member get constructor => _constructor;
// Coverage-ignore(suite): Not run.
Procedure? get constructorTearOff => _constructorTearOff;
void buildOutlineNodes(
BuildNodesCallback f, {
required SourceConstructorBuilder constructorBuilder,
required SourceLibraryBuilder libraryBuilder,
required SourceExtensionTypeDeclarationBuilder declarationBuilder,
required Member declarationConstructor,
required int fileOffset,
required int formalsOffset,
required bool isConst,
required TypeBuilder returnType,
required List<NominalParameterBuilder>? typeParameters,
required List<FormalParameterBuilder>? formals,
required List<DelayedDefaultValueCloner> delayedDefaultValueCloners,
}) {
_build(
constructorBuilder: constructorBuilder,
libraryBuilder: libraryBuilder,
declarationBuilder: declarationBuilder,
declarationConstructor: declarationConstructor,
fileOffset: fileOffset,
formalsOffset: formalsOffset,
isConst: isConst,
returnType: returnType,
typeParameters: typeParameters,
formals: formals,
delayedDefaultValueCloners: delayedDefaultValueCloners);
f(
member: _constructor,
tearOff: _constructorTearOff,
kind: BuiltMemberKind.ExtensionTypeConstructor);
}
bool _hasBeenBuilt = false;
void _build({
required SourceConstructorBuilder constructorBuilder,
required SourceLibraryBuilder libraryBuilder,
required SourceExtensionTypeDeclarationBuilder declarationBuilder,
required Member declarationConstructor,
required int fileOffset,
required int formalsOffset,
required bool isConst,
required TypeBuilder returnType,
required List<NominalParameterBuilder>? typeParameters,
required List<FormalParameterBuilder>? formals,
required List<DelayedDefaultValueCloner> delayedDefaultValueCloners,
}) {
if (!_hasBeenBuilt) {
// According to the specification §9.3 the return type of a constructor
// function is its enclosing class.
function.asyncMarker = AsyncMarker.Sync;
buildTypeParametersAndFormals(
libraryBuilder, function, typeParameters, formals,
classTypeParameters: null, supportsTypeParameters: true);
if (declarationBuilder.typeParameters != null) {
int count = declarationBuilder.typeParameters!.length;
_thisTypeParameters = new List<TypeParameter>.generate(
count, (int index) => function.typeParameters[index],
growable: false);
}
List<DartType> typeArguments;
if (_thisTypeParameters != null) {
typeArguments = [
for (TypeParameter parameter in _thisTypeParameters!)
new TypeParameterType.withDefaultNullability(parameter)
];
} else {
typeArguments = [];
}
ExtensionTypeDeclaration extensionTypeDeclaration =
declarationBuilder.extensionTypeDeclaration;
_thisVariable = new VariableDeclarationImpl(syntheticThisName,
isFinal: true,
type: new ExtensionType(
extensionTypeDeclaration, Nullability.nonNullable, typeArguments))
..fileOffset = fileOffset
..isLowered = true;
List<DartType> typeParameterTypes = <DartType>[];
for (int i = 0; i < function.typeParameters.length; i++) {
TypeParameter typeParameter = function.typeParameters[i];
typeParameterTypes
.add(new TypeParameterType.withDefaultNullability(typeParameter));
}
ExtensionType type = new ExtensionType(extensionTypeDeclaration,
Nullability.nonNullable, typeParameterTypes);
returnType.registerInferredType(type);
_constructor.function.fileOffset = formalsOffset;
_constructor.function.fileEndOffset = _constructor.fileEndOffset;
_constructor.isConst = isConst;
_constructor.isExternal = _isExternal;
_constructor.isStatic = true;
_constructor.isExtensionTypeMember = true;
if (_constructorTearOff != null) {
delayedDefaultValueCloners.add(buildConstructorTearOffProcedure(
tearOff: _constructorTearOff,
declarationConstructor: declarationConstructor,
implementationConstructor: _constructor,
libraryBuilder: libraryBuilder));
}
_hasBeenBuilt = true;
}
if (formals != null) {
bool needsInference = false;
for (FormalParameterBuilder formal in formals) {
if (formal.type is InferableTypeBuilder &&
(formal.isInitializingFormal || formal.isSuperInitializingFormal)) {
formal.variable!.type = const UnknownType();
needsInference = true;
} else if (!formal.hasDeclaredInitializer &&
formal.isSuperInitializingFormal) {
needsInference = true;
}
}
if (needsInference) {
libraryBuilder.loader
.registerConstructorToBeInferred(_constructor, constructorBuilder);
}
}
}
VariableDeclaration? get thisVariable {
assert(_thisVariable != null,
"ProcedureBuilder.thisVariable has not been set.");
return _thisVariable;
}
List<TypeParameter>? get thisTypeParameters {
// Use [_thisVariable] as marker for whether this type parameters have
// been computed.
assert(_thisVariable != null,
"ProcedureBuilder.thisTypeParameters has not been set.");
return _thisTypeParameters;
}
void prepareInitializers() {
// For const constructors we parse initializers already at the outlining
// stage, there is no easy way to make body building stage skip initializer
// parsing, so we simply clear parsed initializers and rebuild them
// again.
// For when doing an experimental incremental compilation they are also
// potentially done more than once (because it rebuilds the bodies of an old
// compile), and so we also clear them.
// Note: this method clears both initializers from the target Kernel node
// and internal state associated with parsing initializers.
initializers = [];
//redirectingInitializer = null;
//superInitializer = null;
}
void prependInitializer(Initializer initializer) {
initializers.insert(0, initializer);
}
VariableDeclaration? getTearOffParameter(int index) {
Procedure? constructorTearOff = _constructorTearOff;
if (constructorTearOff != null) {
if (index < constructorTearOff.function.positionalParameters.length) {
return constructorTearOff.function.positionalParameters[index];
} else {
index -= constructorTearOff.function.positionalParameters.length;
if (index < constructorTearOff.function.namedParameters.length) {
return constructorTearOff.function.namedParameters[index];
}
}
}
return null;
}
bool _hasBuiltBody = false;
void buildBody() {
if (_hasBuiltBody) {
return;
}
if (!_isExternal) {
VariableDeclaration thisVariable = this.thisVariable!;
List<Statement> statements = [thisVariable];
ExtensionTypeInitializerToStatementConverter visitor =
new ExtensionTypeInitializerToStatementConverter(
statements, thisVariable);
for (Initializer initializer in initializers) {
initializer.accept(visitor);
}
if (function.body != null && function.body is! EmptyStatement) {
statements.add(function.body!);
}
statements.add(new ReturnStatement(new VariableGet(thisVariable)));
registerFunctionBody(new Block(statements));
}
_hasBuiltBody = true;
}
}
+1 -1
View File
@@ -898,7 +898,7 @@ class _GetterFragmentBodyBuilderContext extends BodyBuilderContext {
TypeBuilder get returnType => _fragment.returnType;
@override
void setBody(Statement body) {
void registerFunctionBody(Statement body) {
function.body = body..parent = function;
}
+1 -1
View File
@@ -1276,7 +1276,7 @@ class _MethodFragmentBodyBuilderContext extends BodyBuilderContext {
TypeBuilder get returnType => _fragment.returnType;
@override
void setBody(Statement body) {
void registerFunctionBody(Statement body) {
function.body = body..parent = function;
}
@@ -18,7 +18,7 @@ class PrimaryConstructorFragment implements Fragment, FunctionFragment {
final bool forAbstractClassOrMixin;
Token? _beginInitializers;
AbstractSourceConstructorBuilder? _builder;
SourceConstructorBuilderImpl? _builder;
PrimaryConstructorFragment(
{required this.constructorName,
@@ -47,12 +47,12 @@ class PrimaryConstructorFragment implements Fragment, FunctionFragment {
}
@override
AbstractSourceConstructorBuilder get builder {
SourceConstructorBuilderImpl get builder {
assert(_builder != null, "Builder has not been computed for $this.");
return _builder!;
}
void set builder(AbstractSourceConstructorBuilder value) {
void set builder(SourceConstructorBuilderImpl value) {
assert(_builder == null, "Builder has already been computed for $this.");
_builder = value;
}
+1 -1
View File
@@ -919,7 +919,7 @@ class _SetterFragmentBodyBuilderContext extends BodyBuilderContext {
TypeBuilder get returnType => _fragment.returnType;
@override
void setBody(Statement body) {
void registerFunctionBody(Statement body) {
function.body = body..parent = function;
}
@@ -1340,7 +1340,7 @@ class BodyBuilder extends StackListenerImpl
])
..fileOffset = body.fileOffset;
}
_context.setBody(body);
_context.registerFunctionBody(body);
}
performBacklogComputations();
@@ -2114,7 +2114,7 @@ class BodyBuilder extends StackListenerImpl
/// >If a generative constructor c is not a redirecting constructor
/// >and no body is provided, then c implicitly has an empty body {}.
/// We use an empty statement instead.
function.body = new EmptyStatement()..parent = function;
_context.registerNoBodyConstructor();
} else if (body != null && _context.isMixinClass && !_context.isFactory) {
// Report an error if a mixin class has a non-factory constructor with a
// body.
@@ -368,8 +368,13 @@ abstract class BodyBuilderContext {
}
/// Registers [body] as the result of the body building.
void setBody(Statement body) {
throw new UnsupportedError("${runtimeType}.setBody");
void registerFunctionBody(Statement body) {
throw new UnsupportedError("${runtimeType}.registerFunctionBody");
}
/// Registers that the constructor has no body.
void registerNoBodyConstructor() {
throw new UnsupportedError("${runtimeType}.registerNoBodyConstructor");
}
/// Returns the type of `this` in the body being built.
@@ -793,8 +798,8 @@ mixin _FunctionBodyBuilderContextMixin<T extends SourceFunctionBuilder>
}
}
mixin _ConstructorBodyBuilderContextMixin<T extends ConstructorDeclaration>
implements BodyBuilderContext {
mixin _ConstructorBodyBuilderContextMixin<
T extends ConstructorDeclarationBuilder> implements BodyBuilderContext {
T get _member;
TreeNode get _initializerParent;
@@ -853,11 +858,11 @@ mixin _ConstructorBodyBuilderContextMixin<T extends ConstructorDeclaration>
class ConstructorBodyBuilderContext extends BodyBuilderContext
with
_FunctionBodyBuilderContextMixin<DeclaredSourceConstructorBuilder>,
_ConstructorBodyBuilderContextMixin<DeclaredSourceConstructorBuilder>,
_MemberBodyBuilderContext<DeclaredSourceConstructorBuilder> {
_FunctionBodyBuilderContextMixin<SourceConstructorBuilderImpl>,
_ConstructorBodyBuilderContextMixin<SourceConstructorBuilderImpl>,
_MemberBodyBuilderContext<SourceConstructorBuilderImpl> {
@override
final DeclaredSourceConstructorBuilder _member;
final SourceConstructorBuilderImpl _member;
@override
final Member _builtMember;
@@ -872,8 +877,13 @@ class ConstructorBodyBuilderContext extends BodyBuilderContext
}
@override
void setBody(Statement body) {
_member.body = body;
void registerFunctionBody(Statement body) {
_member.registerFunctionBody(body);
}
@override
void registerNoBodyConstructor() {
_member.registerNoBodyConstructor();
}
@override
@@ -883,7 +893,8 @@ class ConstructorBodyBuilderContext extends BodyBuilderContext
@override
bool needsImplicitSuperInitializer(CoreTypes coreTypes) {
return !_declarationContext.isObjectClass(coreTypes) &&
return _member.isClassMember &&
!_declarationContext.isObjectClass(coreTypes) &&
!isExternalConstructor;
}
@@ -891,40 +902,6 @@ class ConstructorBodyBuilderContext extends BodyBuilderContext
TreeNode get _initializerParent => _member.invokeTarget;
}
class ExtensionTypeConstructorBodyBuilderContext extends BodyBuilderContext
with
_FunctionBodyBuilderContextMixin<SourceExtensionTypeConstructorBuilder>,
_ConstructorBodyBuilderContextMixin<
SourceExtensionTypeConstructorBuilder>,
_MemberBodyBuilderContext<SourceExtensionTypeConstructorBuilder> {
@override
final SourceExtensionTypeConstructorBuilder _member;
@override
final Member _builtMember;
ExtensionTypeConstructorBodyBuilderContext(this._member, this._builtMember)
: super(_member.libraryBuilder, _member.declarationBuilder,
isDeclarationInstanceMember: _member.isDeclarationInstanceMember);
@override
LocalScope computeFormalParameterInitializerScope(LocalScope parent) {
return _member.computeFormalParameterInitializerScope(parent);
}
@override
void setBody(Statement body) {
_member.body = body;
}
@override
bool isConstructorCyclic(String name) {
return _declarationContext.isConstructorCyclic(_member.name, name);
}
@override
TreeNode get _initializerParent => _member.invokeTarget;
}
class ParameterBodyBuilderContext extends BodyBuilderContext {
factory ParameterBodyBuilderContext(
LibraryBuilder libraryBuilder,
+34 -29
View File
@@ -102,6 +102,14 @@ class KernelTarget {
const PredefinedTypeName("dynamic"), const NullabilityBuilder.inherent(),
instanceTypeParameterAccess: InstanceTypeParameterAccessState.Unexpected);
final NamedTypeBuilder intType = new NamedTypeBuilderImpl(
const PredefinedTypeName("int"), const NullabilityBuilder.omitted(),
instanceTypeParameterAccess: InstanceTypeParameterAccessState.Unexpected);
final NamedTypeBuilder stringType = new NamedTypeBuilderImpl(
const PredefinedTypeName("String"), const NullabilityBuilder.omitted(),
instanceTypeParameterAccess: InstanceTypeParameterAccessState.Unexpected);
final NamedTypeBuilder objectType = new NamedTypeBuilderImpl(
const PredefinedTypeName("Object"), const NullabilityBuilder.omitted(),
instanceTypeParameterAccess: InstanceTypeParameterAccessState.Unexpected);
@@ -1232,30 +1240,25 @@ class KernelTarget {
enclosingClass.enclosingLibrary.nonNullable, typeParameterTypes);
}
void _bindCoreType(NamedTypeBuilder typeBuilder, {bool isNullClass = false}) {
TypeDeclarationBuilder typeDeclarationBuilder = loader.coreLibrary
.lookupLocalMember(typeBuilder.typeName.name, required: true)
as TypeDeclarationBuilder;
typeBuilder.bind(loader.coreLibrary, typeDeclarationBuilder);
if (isNullClass) {
(typeDeclarationBuilder as ClassBuilder).isNullClass = true;
}
}
void setupTopAndBottomTypes() {
objectType.bind(
loader.coreLibrary,
loader.coreLibrary.lookupLocalMember("Object", required: true)
as TypeDeclarationBuilder);
dynamicType.bind(
loader.coreLibrary,
loader.coreLibrary.lookupLocalMember("dynamic", required: true)
as TypeDeclarationBuilder);
ClassBuilder nullClassBuilder = loader.coreLibrary
.lookupLocalMember("Null", required: true) as ClassBuilder;
nullType.bind(loader.coreLibrary, nullClassBuilder..isNullClass = true);
bottomType.bind(
loader.coreLibrary,
loader.coreLibrary.lookupLocalMember("Never", required: true)
as TypeDeclarationBuilder);
enumType.bind(
loader.coreLibrary,
loader.coreLibrary.lookupLocalMember("Enum", required: true)
as TypeDeclarationBuilder);
underscoreEnumType.bind(
loader.coreLibrary,
loader.coreLibrary.lookupLocalMember("_Enum", required: true)
as TypeDeclarationBuilder);
_bindCoreType(objectType);
_bindCoreType(stringType);
_bindCoreType(intType);
_bindCoreType(dynamicType);
_bindCoreType(nullType, isNullClass: true);
_bindCoreType(bottomType);
_bindCoreType(enumType);
_bindCoreType(underscoreEnumType);
}
void computeCoreTypes() {
@@ -1421,15 +1424,16 @@ class KernelTarget {
}
}
Map<ConstructorDeclaration, Set<SourcePropertyBuilder>>
Map<ConstructorDeclarationBuilder, Set<SourcePropertyBuilder>>
constructorInitializedFields = new Map.identity();
Set<SourcePropertyBuilder>? initializedFieldBuilders = null;
Set<SourcePropertyBuilder>? uninitializedInstanceFields;
Iterator<ConstructorDeclaration> constructorIterator =
classDeclaration.fullConstructorIterator<ConstructorDeclaration>();
Iterator<ConstructorDeclarationBuilder> constructorIterator =
classDeclaration
.fullConstructorIterator<ConstructorDeclarationBuilder>();
while (constructorIterator.moveNext()) {
ConstructorDeclaration constructor = constructorIterator.current;
ConstructorDeclarationBuilder constructor = constructorIterator.current;
if (constructor.isEffectivelyRedirecting) continue;
if (constructor.isConst && nonFinalFields.isNotEmpty) {
classDeclaration.addProblem(messageConstConstructorNonFinalField,
@@ -1514,9 +1518,10 @@ class KernelTarget {
// Run through all fields that are initialized by some constructor, and
// make sure that all other constructors also initialize them.
for (MapEntry<ConstructorDeclaration, Set<SourcePropertyBuilder>> entry
for (MapEntry<ConstructorDeclarationBuilder,
Set<SourcePropertyBuilder>> entry
in constructorInitializedFields.entries) {
ConstructorDeclaration constructorBuilder = entry.key;
ConstructorDeclarationBuilder constructorBuilder = entry.key;
Set<SourcePropertyBuilder> fieldBuilders = entry.value;
for (SourcePropertyBuilder fieldBuilder
in initializedFieldBuilders!.difference(fieldBuilders)) {
@@ -12,7 +12,7 @@ import 'source_property_builder.dart';
/// Common interface for builders for generative constructor declarations in
/// source code, such as a generative constructor in a regular class or a
/// generative constructor in an extension type declaration.
abstract class ConstructorDeclaration implements SourceFunctionBuilder {
abstract class ConstructorDeclarationBuilder implements SourceFunctionBuilder {
/// Returns `true` if this constructor, including its augmentations, is
/// external.
///
@@ -940,7 +940,7 @@ class SourceClassBuilder extends ClassBuilderImpl
SourceMemberBuilder constructor = constructorIterator.current;
// Assumes the constructor isn't synthetic since
// [installSyntheticConstructors] hasn't been called yet.
if (constructor is DeclaredSourceConstructorBuilder) {
if (constructor is SourceConstructorBuilderImpl) {
// Report an error if a mixin class has a constructor with parameters,
// is external, or is a redirecting constructor.
if (constructor.isRedirecting ||
File diff suppressed because it is too large Load Diff
@@ -33,6 +33,7 @@ import '../codes/cfe_codes.dart'
messageNoUnnamedConstructorInObject,
noLength,
templateEnumContainsRestrictedInstanceDeclaration;
import '../fragment/constructor/declaration.dart';
import '../fragment/fragment.dart';
import '../kernel/body_builder_context.dart';
import '../kernel/constructor_tearoff_lowering.dart';
@@ -58,17 +59,13 @@ class SourceEnumBuilder extends SourceClassBuilder {
final TypeBuilder _underscoreEnumTypeBuilder;
late final NamedTypeBuilder intType;
late final NamedTypeBuilder stringType;
late final NamedTypeBuilder objectType;
late final NamedTypeBuilder listType;
late final NamedTypeBuilder selfType;
DeclaredSourceConstructorBuilder? synthesizedDefaultConstructorBuilder;
SourceConstructorBuilderImpl? synthesizedDefaultConstructorBuilder;
late final _EnumValuesFieldDeclaration _enumValuesFieldDeclaration;
@@ -141,30 +138,6 @@ class SourceEnumBuilder extends SourceClassBuilder {
super.buildScopes(coreLibrary);
_createSynthesizedMembers(coreLibrary);
// Include duplicates to install the formals on all constructors to avoid a
// crash later.
Iterator<MemberBuilder> iterator =
nameSpace.filteredConstructorNameIterator(
includeDuplicates: true, includeAugmentations: true);
while (iterator.moveNext()) {
MemberBuilder member = iterator.current;
if (member is DeclaredSourceConstructorBuilder) {
member.ensureGrowableFormals();
FormalParameterBuilder nameFormalParameterBuilder =
new FormalParameterBuilder(FormalParameterKind.requiredPositional,
Modifiers.empty, stringType, "#name", fileOffset,
fileUri: fileUri, hasImmediatelyDeclaredInitializer: false);
member.formals!.insert(0, nameFormalParameterBuilder);
FormalParameterBuilder indexFormalParameterBuilder =
new FormalParameterBuilder(FormalParameterKind.requiredPositional,
Modifiers.empty, intType, "#index", fileOffset,
fileUri: fileUri, hasImmediatelyDeclaredInitializer: false);
member.formals!.insert(0, indexFormalParameterBuilder);
}
}
Iterator<MemberBuilder> constructorIterator =
nameSpace.filteredConstructorIterator(
includeDuplicates: false, includeAugmentations: true);
@@ -180,23 +153,6 @@ class SourceEnumBuilder extends SourceClassBuilder {
void _createSynthesizedMembers(LibraryBuilder coreLibrary) {
// TODO(ahe): These types shouldn't be looked up in scope, they come
// directly from dart:core.
intType = new NamedTypeBuilderImpl(
const PredefinedTypeName("int"), const NullabilityBuilder.omitted(),
instanceTypeParameterAccess:
// If "int" resolves to an instance type parameter then that we
// would allowed (the types that we are adding are in instance
// context after all) but it would be unexpected and we would like
// an assertion failure, since "int" was meant to be `int` from
// `dart:core`.
// TODO(johnniwinther): Add a more robust way of creating named
// typed builders for dart:core types. This might be needed for the
// enhanced enums feature where enums can actually declare type
// variables.
InstanceTypeParameterAccessState.Unexpected);
stringType = new NamedTypeBuilderImpl(
const PredefinedTypeName("String"), const NullabilityBuilder.omitted(),
instanceTypeParameterAccess:
InstanceTypeParameterAccessState.Unexpected);
objectType = new NamedTypeBuilderImpl(
const PredefinedTypeName("Object"), const NullabilityBuilder.omitted(),
instanceTypeParameterAccess:
@@ -326,35 +282,55 @@ class SourceEnumBuilder extends SourceClassBuilder {
}
}
if (needsSynthesizedDefaultConstructor) {
synthesizedDefaultConstructorBuilder =
new DeclaredSourceConstructorBuilder(
metadata: null,
modifiers: Modifiers.Const,
FormalParameterBuilder nameFormalParameterBuilder =
new FormalParameterBuilder(
FormalParameterKind.requiredPositional,
Modifiers.empty,
libraryBuilder.loader.target.stringType,
"#name",
fileOffset,
fileUri: fileUri,
hasImmediatelyDeclaredInitializer: false);
FormalParameterBuilder indexFormalParameterBuilder =
new FormalParameterBuilder(
FormalParameterKind.requiredPositional,
Modifiers.empty,
libraryBuilder.loader.target.intType,
"#index",
fileOffset,
fileUri: fileUri,
hasImmediatelyDeclaredInitializer: false);
ConstructorDeclaration constructorDeclaration =
new DefaultEnumConstructorDeclaration(
returnType:
libraryBuilder.loader.inferableTypes.addInferableType(),
name: "",
typeParameters: null,
formals: [],
libraryBuilder: libraryBuilder,
declarationBuilder: this,
formals: [
indexFormalParameterBuilder,
nameFormalParameterBuilder
],
fileUri: fileUri,
startOffset: fileOffset,
fileOffset: fileOffset,
formalsOffset: fileOffset,
endOffset: endOffset,
constructorReference: constructorReference,
tearOffReference: tearOffReference,
nameScheme: new NameScheme(
isInstanceMember: false,
containerName: new ClassName(name),
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.
beginInitializers: new Token.eof(-1));
fileOffset: fileOffset);
synthesizedDefaultConstructorBuilder = new SourceConstructorBuilderImpl(
modifiers: Modifiers.Const,
name: "",
libraryBuilder: libraryBuilder,
declarationBuilder: this,
fileUri: fileUri,
fileOffset: fileOffset,
constructorReference: constructorReference,
tearOffReference: tearOffReference,
nameScheme: new NameScheme(
isInstanceMember: false,
containerName: new ClassName(name),
containerType: ContainerType.Class,
libraryName: libraryName),
// 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),
constructorDeclaration: constructorDeclaration);
synthesizedDefaultConstructorBuilder!
.registerInitializedField(valuesBuilder);
nameSpace.addConstructor("", synthesizedDefaultConstructorBuilder!);
@@ -379,7 +355,9 @@ class SourceEnumBuilder extends SourceClassBuilder {
isAbstract: false,
reference: toStringReference,
creator: new _EnumToStringCreator(
this, stringType, _underscoreEnumTypeBuilder));
this,
libraryBuilder.loader.target.stringType,
_underscoreEnumTypeBuilder));
nameSpace.addLocalMember(toStringBuilder.name, toStringBuilder,
setter: false);
nameSpaceBuilder.checkTypeParameterConflict(libraryBuilder,
@@ -410,9 +388,6 @@ class SourceEnumBuilder extends SourceClassBuilder {
}
}
intType.resolveIn(coreLibrary.scope, fileOffset, fileUri, libraryBuilder);
stringType.resolveIn(
coreLibrary.scope, fileOffset, fileUri, libraryBuilder);
objectType.resolveIn(
coreLibrary.scope, fileOffset, fileUri, libraryBuilder);
listType.resolveIn(coreLibrary.scope, fileOffset, fileUri, libraryBuilder);
@@ -429,7 +404,7 @@ class SourceEnumBuilder extends SourceClassBuilder {
if (identical(this.supertypeBuilder, _underscoreEnumTypeBuilder)) {
if (synthesizedDefaultConstructorBuilder != null) {
Constructor constructor =
synthesizedDefaultConstructorBuilder!.constructor;
synthesizedDefaultConstructorBuilder!.invokeTarget as Constructor;
ClassBuilder objectClass = objectType.declaration as ClassBuilder;
ClassBuilder enumClass =
_underscoreEnumTypeBuilder.declaration as ClassBuilder;
@@ -860,14 +860,14 @@ class SourceExtensionTypeDeclarationBuilder
/// Looks up the constructor by [name] on the class built by this class
/// builder.
SourceExtensionTypeConstructorBuilder? lookupConstructor(Name name) {
SourceConstructorBuilderImpl? lookupConstructor(Name name) {
if (name.text == "new") {
// Coverage-ignore-block(suite): Not run.
name = new Name("", name.library);
}
Builder? builder = nameSpace.lookupConstructor(name.text);
if (builder is SourceExtensionTypeConstructorBuilder) {
if (builder is SourceConstructorBuilderImpl) {
return builder;
}
return null;
@@ -515,7 +515,7 @@ class FactoryBodyBuilderContext extends BodyBuilderContext {
}
@override
void setBody(Statement body) {
void registerFunctionBody(Statement body) {
_member.setBody(body);
}
@@ -2,6 +2,7 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'package:_fe_analyzer_shared/src/parser/formal_parameter_kind.dart';
import 'package:kernel/ast.dart';
import 'package:kernel/reference_from_index.dart';
@@ -12,12 +13,14 @@ import '../base/problems.dart';
import '../base/scope.dart';
import '../builder/builder.dart';
import '../builder/declaration_builders.dart';
import '../builder/formal_parameter_builder.dart';
import '../builder/function_builder.dart';
import '../builder/member_builder.dart';
import '../builder/named_type_builder.dart';
import '../builder/nullability_builder.dart';
import '../builder/prefix_builder.dart';
import '../builder/type_builder.dart';
import '../fragment/constructor/declaration.dart';
import '../fragment/fragment.dart';
import 'builder_factory.dart';
import 'name_scheme.dart';
@@ -1583,11 +1586,32 @@ void _computeBuildersFromFragments(String name, List<Fragment> fragments,
methodBuilder;
}
case ConstructorFragment():
List<NominalParameterBuilder>? typeParameters =
fragment.typeParameters?.builders;
String name = fragment.name;
NameScheme nameScheme = new NameScheme(
isInstanceMember: false,
containerName: containerName,
containerType: containerType,
libraryName: indexedLibrary != null
? new LibraryName(indexedLibrary.library.reference)
: enclosingLibraryBuilder.libraryName);
Reference? constructorReference;
Reference? tearOffReference;
if (indexedContainer != null) {
constructorReference = indexedContainer!.lookupConstructorReference(
nameScheme.getConstructorMemberName(name, isTearOff: false).name);
tearOffReference = indexedContainer!.lookupGetterReference(
nameScheme.getConstructorMemberName(name, isTearOff: true).name);
}
SourceConstructorBuilderImpl constructorBuilder;
switch (declarationBuilder!) {
case ExtensionBuilder():
case ExtensionTypeDeclarationBuilder():
List<NominalParameterBuilder>? typeParameters = fragment
.typeParameters
// Coverage-ignore(suite): Not run.
?.builders;
NominalParameterCopy? nominalVariableCopy =
NominalParameterCopy.copyTypeParameters(
unboundNominalParameters, declarationBuilder.typeParameters,
@@ -1603,74 +1627,109 @@ void _computeBuildersFromFragments(String name, List<Fragment> fragments,
typeParameters = nominalVariableCopy.newParameterBuilders;
}
}
fragment.typeParameterNameSpace.addTypeParameters(
problemReporting, typeParameters,
ownerName: fragment.name, allowNameConflict: true);
ConstructorDeclaration constructorDeclaration =
new ExtensionTypeConstructorDeclaration(fragment,
typeParameters: typeParameters);
constructorBuilder = new SourceConstructorBuilderImpl(
modifiers: fragment.modifiers,
name: name,
libraryBuilder: enclosingLibraryBuilder,
declarationBuilder:
declarationBuilder as SourceExtensionTypeDeclarationBuilder,
fileUri: fragment.fileUri,
fileOffset: fragment.fullNameOffset,
constructorReference: constructorReference,
tearOffReference: tearOffReference,
nameScheme: nameScheme,
nativeMethodName: fragment.nativeMethodName,
beginInitializers: fragment.beginInitializers,
constructorDeclaration: constructorDeclaration);
case ClassBuilder():
}
fragment.typeParameterNameSpace.addTypeParameters(
problemReporting, typeParameters,
ownerName: fragment.name, allowNameConflict: true);
String name = fragment.name;
NameScheme nameScheme = new NameScheme(
isInstanceMember: false,
containerName: containerName,
containerType: containerType,
libraryName: indexedLibrary != null
? new LibraryName(indexedLibrary.library.reference)
: enclosingLibraryBuilder.libraryName);
Reference? constructorReference;
Reference? tearOffReference;
if (indexedContainer != null) {
constructorReference = indexedContainer!.lookupConstructorReference(
nameScheme.getConstructorMemberName(name, isTearOff: false).name);
tearOffReference = indexedContainer!.lookupGetterReference(
nameScheme.getConstructorMemberName(name, isTearOff: true).name);
}
AbstractSourceConstructorBuilder constructorBuilder;
if (declarationBuilder is SourceExtensionTypeDeclarationBuilder) {
constructorBuilder = new SourceExtensionTypeConstructorBuilder(
metadata: fragment.metadata,
modifiers: fragment.modifiers,
returnType: fragment.returnType,
name: name,
typeParameters: typeParameters,
formals: fragment.formals,
libraryBuilder: enclosingLibraryBuilder,
declarationBuilder: declarationBuilder,
fileUri: fragment.fileUri,
startOffset: fragment.startOffset,
fileOffset: fragment.fullNameOffset,
formalsOffset: fragment.formalsOffset,
endOffset: fragment.endOffset,
constructorReference: constructorReference,
tearOffReference: tearOffReference,
nameScheme: nameScheme,
nativeMethodName: fragment.nativeMethodName,
forAbstractClassOrEnumOrMixin: fragment.forAbstractClassOrMixin,
beginInitializers: fragment.beginInitializers);
} else {
constructorBuilder = new DeclaredSourceConstructorBuilder(
metadata: fragment.metadata,
modifiers: fragment.modifiers,
returnType: fragment.returnType,
name: fragment.name,
typeParameters: typeParameters,
formals: fragment.formals,
libraryBuilder: enclosingLibraryBuilder,
declarationBuilder: declarationBuilder,
fileUri: fragment.fileUri,
startOffset: fragment.startOffset,
fileOffset: fragment.fullNameOffset,
formalsOffset: fragment.formalsOffset,
endOffset: fragment.endOffset,
constructorReference: constructorReference,
tearOffReference: tearOffReference,
nameScheme: nameScheme,
nativeMethodName: fragment.nativeMethodName,
forAbstractClassOrEnumOrMixin: fragment.forAbstractClassOrMixin,
beginInitializers: fragment.beginInitializers);
List<FormalParameterBuilder>? syntheticFormals;
if (declarationBuilder.isEnum) {
syntheticFormals = [
new FormalParameterBuilder(
FormalParameterKind.requiredPositional,
Modifiers.empty,
loader.target.intType,
"#index",
fragment.fullNameOffset,
fileUri: fragment.fileUri,
hasImmediatelyDeclaredInitializer: false),
new FormalParameterBuilder(
FormalParameterKind.requiredPositional,
Modifiers.empty,
loader.target.stringType,
"#name",
fragment.fullNameOffset,
fileUri: fragment.fileUri,
hasImmediatelyDeclaredInitializer: false),
];
}
List<NominalParameterBuilder>? typeParameters =
fragment.typeParameters?.builders;
fragment.typeParameterNameSpace.addTypeParameters(
problemReporting, typeParameters,
ownerName: fragment.name, allowNameConflict: true);
ConstructorDeclaration constructorDeclaration =
new RegularConstructorDeclaration(fragment,
typeParameters: typeParameters,
syntheticFormals: syntheticFormals);
constructorBuilder = new SourceConstructorBuilderImpl(
modifiers: fragment.modifiers,
name: fragment.name,
libraryBuilder: enclosingLibraryBuilder,
declarationBuilder: declarationBuilder,
fileUri: fragment.fileUri,
fileOffset: fragment.fullNameOffset,
constructorReference: constructorReference,
tearOffReference: tearOffReference,
nameScheme: nameScheme,
nativeMethodName: fragment.nativeMethodName,
beginInitializers: fragment.beginInitializers,
constructorDeclaration: constructorDeclaration);
case ExtensionBuilder():
List<NominalParameterBuilder>? typeParameters = fragment
.typeParameters
// Coverage-ignore(suite): Not run.
?.builders;
NominalParameterCopy? nominalVariableCopy =
NominalParameterCopy.copyTypeParameters(
unboundNominalParameters, declarationBuilder.typeParameters,
kind: TypeParameterKind.extensionSynthesized,
instanceTypeParameterAccess:
InstanceTypeParameterAccessState.Allowed);
if (nominalVariableCopy != null) {
if (typeParameters != null) {
// Coverage-ignore-block(suite): Not run.
typeParameters = nominalVariableCopy.newParameterBuilders
..addAll(typeParameters);
} else {
typeParameters = nominalVariableCopy.newParameterBuilders;
}
}
fragment.typeParameterNameSpace.addTypeParameters(
problemReporting, typeParameters,
ownerName: fragment.name, allowNameConflict: true);
ConstructorDeclaration constructorDeclaration =
new RegularConstructorDeclaration(fragment,
typeParameters: typeParameters, syntheticFormals: null);
constructorBuilder = new SourceConstructorBuilderImpl(
modifiers: fragment.modifiers,
name: fragment.name,
libraryBuilder: enclosingLibraryBuilder,
declarationBuilder: declarationBuilder,
fileUri: fragment.fileUri,
fileOffset: fragment.fullNameOffset,
constructorReference: constructorReference,
tearOffReference: tearOffReference,
nameScheme: nameScheme,
nativeMethodName: fragment.nativeMethodName,
beginInitializers: fragment.beginInitializers,
constructorDeclaration: constructorDeclaration);
}
fragment.builder = constructorBuilder;
builders.add(new _AddBuilder(fragment.name, constructorBuilder,
@@ -1685,19 +1744,6 @@ void _computeBuildersFromFragments(String name, List<Fragment> fragments,
case PrimaryConstructorFragment():
String name = fragment.name;
NominalParameterCopy? nominalVariableCopy =
NominalParameterCopy.copyTypeParameters(
unboundNominalParameters, declarationBuilder!.typeParameters,
kind: TypeParameterKind.extensionSynthesized,
instanceTypeParameterAccess:
InstanceTypeParameterAccessState.Allowed);
List<NominalParameterBuilder>? typeParameters =
nominalVariableCopy?.newParameterBuilders;
fragment.typeParameterNameSpace.addTypeParameters(
problemReporting, typeParameters,
ownerName: fragment.name, allowNameConflict: true);
NameScheme nameScheme = new NameScheme(
isInstanceMember: false,
containerName: containerName,
@@ -1716,50 +1762,57 @@ void _computeBuildersFromFragments(String name, List<Fragment> fragments,
nameScheme.getConstructorMemberName(name, isTearOff: true).name);
}
AbstractSourceConstructorBuilder constructorBuilder;
if (declarationBuilder is SourceExtensionTypeDeclarationBuilder) {
constructorBuilder = new SourceExtensionTypeConstructorBuilder(
metadata: null,
modifiers: fragment.modifiers,
returnType: fragment.returnType,
name: name,
typeParameters: typeParameters,
formals: fragment.formals,
libraryBuilder: enclosingLibraryBuilder,
declarationBuilder: declarationBuilder,
fileUri: fragment.fileUri,
startOffset: fragment.startOffset,
fileOffset: fragment.fileOffset,
formalsOffset: fragment.formalsOffset,
// TODO(johnniwinther): Provide `endOffset`.
endOffset: fragment.formalsOffset,
constructorReference: constructorReference,
tearOffReference: tearOffReference,
nameScheme: nameScheme,
forAbstractClassOrEnumOrMixin: fragment.forAbstractClassOrMixin,
beginInitializers: fragment.beginInitializers);
} else {
// Coverage-ignore-block(suite): Not run.
constructorBuilder = new DeclaredSourceConstructorBuilder(
metadata: null,
modifiers: fragment.modifiers,
returnType: fragment.returnType,
name: fragment.name,
typeParameters: typeParameters,
formals: fragment.formals,
libraryBuilder: enclosingLibraryBuilder,
declarationBuilder: declarationBuilder,
fileUri: fragment.fileUri,
startOffset: fragment.startOffset,
fileOffset: fragment.fileOffset,
formalsOffset: fragment.formalsOffset,
// TODO(johnniwinther): Provide `endOffset`.
endOffset: fragment.formalsOffset,
constructorReference: constructorReference,
tearOffReference: tearOffReference,
nameScheme: nameScheme,
forAbstractClassOrEnumOrMixin: fragment.forAbstractClassOrMixin,
beginInitializers: fragment.beginInitializers);
SourceConstructorBuilderImpl constructorBuilder;
switch (declarationBuilder!) {
case ExtensionTypeDeclarationBuilder():
NominalParameterCopy? nominalVariableCopy =
NominalParameterCopy.copyTypeParameters(
unboundNominalParameters, declarationBuilder.typeParameters,
kind: TypeParameterKind.extensionSynthesized,
instanceTypeParameterAccess:
InstanceTypeParameterAccessState.Allowed);
List<NominalParameterBuilder>? typeParameters =
nominalVariableCopy?.newParameterBuilders;
fragment.typeParameterNameSpace.addTypeParameters(
problemReporting, typeParameters,
ownerName: fragment.name, allowNameConflict: true);
ConstructorDeclaration constructorDeclaration =
new ExtensionTypePrimaryConstructorDeclaration(fragment,
typeParameters: typeParameters);
constructorBuilder = new SourceConstructorBuilderImpl(
modifiers: fragment.modifiers,
name: name,
libraryBuilder: enclosingLibraryBuilder,
declarationBuilder:
declarationBuilder as SourceExtensionTypeDeclarationBuilder,
fileUri: fragment.fileUri,
fileOffset: fragment.fileOffset,
constructorReference: constructorReference,
tearOffReference: tearOffReference,
nameScheme: nameScheme,
beginInitializers: fragment.beginInitializers,
constructorDeclaration: constructorDeclaration);
// Coverage-ignore(suite): Not run.
case ClassBuilder():
ConstructorDeclaration constructorDeclaration =
new PrimaryConstructorDeclaration(fragment);
constructorBuilder = new SourceConstructorBuilderImpl(
modifiers: fragment.modifiers,
name: fragment.name,
libraryBuilder: enclosingLibraryBuilder,
declarationBuilder: declarationBuilder,
fileUri: fragment.fileUri,
fileOffset: fragment.fileOffset,
constructorReference: constructorReference,
tearOffReference: tearOffReference,
nameScheme: nameScheme,
beginInitializers: fragment.beginInitializers,
constructorDeclaration: constructorDeclaration);
// Coverage-ignore(suite): Not run.
case ExtensionBuilder():
throw new UnsupportedError(
'Unexpected extension primary constructor $fragment');
}
fragment.builder = constructorBuilder;
builders.add(new _AddBuilder(fragment.name, constructorBuilder,
@@ -151,7 +151,7 @@ class InferenceVisitorImpl extends InferenceVisitorBase
@override
final TypeAnalyzerOptions options;
final ConstructorDeclaration? constructorDeclaration;
final ConstructorDeclarationBuilder? constructorDeclaration;
@override
late final SharedTypeAnalyzerErrors errors = new SharedTypeAnalyzerErrors(
@@ -52,8 +52,10 @@ abstract class TypeInferrer {
DartType returnType, AsyncMarker asyncMarker, Statement body);
/// Performs type inference on the given constructor initializer.
InitializerInferenceResult inferInitializer(InferenceHelper helper,
ConstructorDeclaration constructorDeclaration, Initializer initializer);
InitializerInferenceResult inferInitializer(
InferenceHelper helper,
ConstructorDeclarationBuilder constructorDeclaration,
Initializer initializer);
/// Performs type inference on the given metadata annotations.
void inferMetadata(
@@ -141,7 +143,7 @@ class TypeInferrerImpl implements TypeInferrer {
typeCacheLegacy: engine.typeCacheLegacy);
InferenceVisitorBase _createInferenceVisitor(InferenceHelper helper,
[ConstructorDeclaration? constructorDeclaration]) {
[ConstructorDeclarationBuilder? constructorDeclaration]) {
// For full (non-top level) inference, we need access to the
// InferenceHelper so that we can perform error reporting.
return new InferenceVisitorImpl(
@@ -246,8 +248,10 @@ class TypeInferrerImpl implements TypeInferrer {
}
@override
InitializerInferenceResult inferInitializer(InferenceHelper helper,
ConstructorDeclaration constructorDeclaration, Initializer initializer) {
InitializerInferenceResult inferInitializer(
InferenceHelper helper,
ConstructorDeclarationBuilder constructorDeclaration,
Initializer initializer) {
// Use polymorphic dispatch on [KernelInitializer] to perform whatever
// kind of type inference is correct for this kind of initializer.
// TODO(paulberry): experiment to see if dynamic dispatch would be better,
@@ -349,8 +353,10 @@ class TypeInferrerImplBenchmarked implements TypeInferrer {
}
@override
InitializerInferenceResult inferInitializer(InferenceHelper helper,
ConstructorDeclaration constructorDeclaration, Initializer initializer) {
InitializerInferenceResult inferInitializer(
InferenceHelper helper,
ConstructorDeclarationBuilder constructorDeclaration,
Initializer initializer) {
benchmarker.beginSubdivide(BenchmarkSubdivides.inferInitializer);
InitializerInferenceResult result =
impl.inferInitializer(helper, constructorDeclaration, initializer);
@@ -479,6 +479,16 @@ const Map<String, ({int hitCount, int missCount})> _expect = {
missCount: 0,
),
// 100.0%.
"package:front_end/src/fragment/constructor/declaration.dart": (
hitCount: 248,
missCount: 0,
),
// 100.0%.
"package:front_end/src/fragment/constructor/encoding.dart": (
hitCount: 318,
missCount: 0,
),
// 100.0%.
"package:front_end/src/fragment/enum.dart": (
hitCount: 13,
missCount: 0,
@@ -580,12 +590,12 @@ const Map<String, ({int hitCount, int missCount})> _expect = {
),
// 100.0%.
"package:front_end/src/kernel/body_builder.dart": (
hitCount: 7181,
hitCount: 7180,
missCount: 0,
),
// 100.0%.
"package:front_end/src/kernel/body_builder_context.dart": (
hitCount: 303,
hitCount: 289,
missCount: 0,
),
// 100.0%.
@@ -730,7 +740,7 @@ const Map<String, ({int hitCount, int missCount})> _expect = {
),
// 100.0%.
"package:front_end/src/kernel/kernel_target.dart": (
hitCount: 1068,
hitCount: 1051,
missCount: 0,
),
// 100.0%.
@@ -860,12 +870,12 @@ const Map<String, ({int hitCount, int missCount})> _expect = {
),
// 100.0%.
"package:front_end/src/source/source_constructor_builder.dart": (
hitCount: 1084,
hitCount: 722,
missCount: 0,
),
// 100.0%.
"package:front_end/src/source/source_enum_builder.dart": (
hitCount: 420,
hitCount: 403,
missCount: 0,
),
// 100.0%.
@@ -931,7 +941,7 @@ const Map<String, ({int hitCount, int missCount})> _expect = {
),
// 100.0%.
"package:front_end/src/source/type_parameter_scope_builder.dart": (
hitCount: 1395,
hitCount: 1408,
missCount: 0,
),
// 100.0%.
@@ -169,7 +169,7 @@ class PatchingDataExtractor extends CfeDataExtractor<Features> {
if (memberBuilder is SourcePropertyBuilder) {
patchMembers = memberBuilder.augmentationsForTesting;
}
if (memberBuilder is DeclaredSourceConstructorBuilder) {
if (memberBuilder is SourceConstructorBuilderImpl) {
patchMembers = memberBuilder.augmentationsForTesting;
}
if (memberBuilder is SourceFactoryBuilder) {
@@ -55,27 +55,35 @@ static extension-type-member method E1|constructor#(core::int foo) → self::E1%
;
static extension-type-member method E1|constructor#_#new#tearOff(core::int foo) → self::E1% /* erasure=core::int, declared=! */
return self::E1|constructor#(foo);
static extension-type-member method E1|constructor#named(core::int foo, invalid-type bar) → self::E1% /* erasure=core::int, declared=! */
;
static extension-type-member method E1|constructor#named(core::int foo, invalid-type bar) → self::E1% /* erasure=core::int, declared=! */ {
lowered final self::E1% /* erasure=core::int, declared=! */ #this = foo;
return #this;
}
static extension-type-member method E1|constructor#_#named#tearOff(core::int foo, invalid-type bar) → self::E1% /* erasure=core::int, declared=! */
return self::E1|constructor#named(foo, bar);
static extension-type-member method E2|constructor#(core::int foo) → self::E2% /* erasure=core::int, declared=! */
;
static extension-type-member method E2|constructor#_#new#tearOff(core::int foo) → self::E2% /* erasure=core::int, declared=! */
return self::E2|constructor#(foo);
static extension-type-member method E2|constructor#named(core::int foo, {required invalid-type bar}) → self::E2% /* erasure=core::int, declared=! */
;
static extension-type-member method E2|constructor#named(core::int foo, {required invalid-type bar}) → self::E2% /* erasure=core::int, declared=! */ {
lowered final self::E2% /* erasure=core::int, declared=! */ #this = foo;
return #this;
}
static extension-type-member method E2|constructor#_#named#tearOff(core::int foo, {required invalid-type bar}) → self::E2% /* erasure=core::int, declared=! */
return self::E2|constructor#named(foo, bar: bar);
static extension-type-member method E3|constructor#(core::int foo) → self::E3% /* erasure=core::int, declared=! */
;
static extension-type-member method E3|constructor#_#new#tearOff(core::int foo) → self::E3% /* erasure=core::int, declared=! */
return self::E3|constructor#(foo);
static extension-type-member method E3|constructor#named(core::int foo, [has-declared-initializer invalid-type bar = null]) → self::E3% /* erasure=core::int, declared=! */
;
static extension-type-member method E3|constructor#named(core::int foo, [has-declared-initializer invalid-type bar = null]) → self::E3% /* erasure=core::int, declared=! */ {
lowered final self::E3% /* erasure=core::int, declared=! */ #this = foo;
return #this;
}
static extension-type-member method E3|constructor#_#named#tearOff(core::int foo, [has-declared-initializer invalid-type bar]) → self::E3% /* erasure=core::int, declared=! */
return self::E3|constructor#named(foo, bar);
static extension-type-member method E4|constructor#(invalid-type foo) → self::E4% /* erasure=invalid-type, declared=! */
;
static extension-type-member method E4|constructor#(invalid-type foo) → self::E4% /* erasure=invalid-type, declared=! */ {
lowered final self::E4% /* erasure=invalid-type, declared=! */ #this = foo;
return #this;
}
static extension-type-member method E4|constructor#_#new#tearOff(invalid-type foo) → self::E4% /* erasure=invalid-type, declared=! */
return self::E4|constructor#(foo);
@@ -38,8 +38,10 @@ static extension-type-member method E07|constructor#(core::int x) → self::E07%
;
static extension-type-member method E07|constructor#_#new#tearOff(core::int x) → self::E07% /* erasure=core::int, declared=! */
return self::E07|constructor#(x);
static extension-type-member method E08|constructor#(core::int x) → self::E08% /* erasure=core::int, declared=! */
;
static extension-type-member method E08|constructor#(core::int x) → self::E08% /* erasure=core::int, declared=! */ {
lowered final self::E08% /* erasure=core::int, declared=! */ #this = x;
return #this;
}
static extension-type-member method E08|constructor#_#new#tearOff(core::int x) → self::E08% /* erasure=core::int, declared=! */
return self::E08|constructor#(x);
static extension-type-member method E11|constructor#(() → core::int x) → self::E11% /* erasure=() → core::int, declared=! */