[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:
committed by
Commit Queue
parent
3b750c5545
commit
a78235cf01
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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=! */
|
||||
|
||||
Reference in New Issue
Block a user