Version 2.16.0-143.0.dev
Merge commit 'b8e5842a2c2313453d31c5f35c04a7e4274f0b10' into 'dev'
diff --git a/pkg/front_end/lib/src/fasta/builder/class_builder.dart b/pkg/front_end/lib/src/fasta/builder/class_builder.dart
index 70eeca3..69e68ff 100644
--- a/pkg/front_end/lib/src/fasta/builder/class_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/class_builder.dart
@@ -22,47 +22,31 @@
TreeNode,
TypeParameter,
getAsTypeArguments;
-
import 'package:kernel/class_hierarchy.dart'
show ClassHierarchy, ClassHierarchyMembers;
-
import 'package:kernel/core_types.dart' show CoreTypes;
-
+import 'package:kernel/src/legacy_erasure.dart';
import 'package:kernel/text/text_serialization_verifier.dart';
-
import 'package:kernel/type_algebra.dart' show Substitution, substitute;
-
import 'package:kernel/type_environment.dart'
show SubtypeCheckMode, TypeEnvironment;
-import 'package:kernel/src/legacy_erasure.dart';
-
import '../dill/dill_member_builder.dart';
-
import '../fasta_codes.dart';
-
import '../kernel/kernel_helper.dart';
-
import '../kernel/redirecting_factory_body.dart' show RedirectingFactoryBody;
-
import '../loader.dart';
-
import '../modifier.dart';
-
import '../names.dart' show noSuchMethodName;
-
import '../problems.dart' show internalProblem, unhandled;
-
import '../scope.dart';
-
+import '../source/source_constructor_builder.dart';
+import '../source/source_factory_builder.dart';
import '../source/source_library_builder.dart' show SourceLibraryBuilder;
-
import '../source/source_loader.dart';
-
+import '../source/source_member_builder.dart';
import '../type_inference/type_schema.dart' show UnknownType;
-
import '../util/helpers.dart' show DelayedActionPerformer;
-
import 'builder.dart';
import 'constructor_builder.dart';
import 'constructor_reference_builder.dart';
@@ -75,7 +59,6 @@
import 'named_type_builder.dart';
import 'never_type_declaration_builder.dart';
import 'nullability_builder.dart';
-import 'factory_builder.dart';
import 'type_alias_builder.dart';
import 'type_builder.dart';
import 'type_declaration_builder.dart';
diff --git a/pkg/front_end/lib/src/fasta/builder/constructor_builder.dart b/pkg/front_end/lib/src/fasta/builder/constructor_builder.dart
index c2e155b..960410b 100644
--- a/pkg/front_end/lib/src/fasta/builder/constructor_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/constructor_builder.dart
@@ -2,757 +2,11 @@
// 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/scanner/token.dart' show Token;
-
import 'package:kernel/ast.dart';
-import 'package:kernel/class_hierarchy.dart';
-import 'package:kernel/type_algebra.dart';
-import '../builder/library_builder.dart';
-
-import '../constant_context.dart' show ConstantContext;
-
-import '../dill/dill_member_builder.dart';
-
-import '../kernel/body_builder.dart' show BodyBuilder;
-import '../kernel/constructor_tearoff_lowering.dart';
-import '../kernel/expression_generator_helper.dart'
- show ExpressionGeneratorHelper;
-import '../kernel/hierarchy/class_member.dart' show ClassMember;
-import '../kernel/utils.dart'
- show isRedirectingGenerativeConstructorImplementation;
-import '../kernel/kernel_helper.dart' show SynthesizedFunctionNode;
-
-import '../source/source_loader.dart' show SourceLoader;
-
-import '../messages.dart'
- show
- Message,
- messageMoreThanOneSuperInitializer,
- messageRedirectingConstructorWithAnotherInitializer,
- messageRedirectingConstructorWithMultipleRedirectInitializers,
- messageRedirectingConstructorWithSuperInitializer,
- messageSuperInitializerNotLast,
- noLength;
-
-import '../source/source_class_builder.dart';
-import '../source/source_library_builder.dart' show SourceLibraryBuilder;
-import '../type_inference/type_schema.dart';
-import '../type_inference/type_inferrer.dart';
-import '../util/helpers.dart' show DelayedActionPerformer;
-
-import 'builder.dart';
-import 'class_builder.dart';
-import 'field_builder.dart';
-import 'formal_parameter_builder.dart';
import 'function_builder.dart';
-import 'member_builder.dart';
-import 'metadata_builder.dart';
-import 'named_type_builder.dart';
-import 'type_alias_builder.dart';
-import 'type_builder.dart';
-import 'type_declaration_builder.dart';
-import 'type_variable_builder.dart';
abstract class ConstructorBuilder implements FunctionBuilder {
/// The [Constructor] built by this builder.
Constructor get constructor;
}
-
-class SourceConstructorBuilder extends FunctionBuilderImpl
- implements ConstructorBuilder {
- final Constructor _constructor;
- final Procedure? _constructorTearOff;
-
- Set<FieldBuilder>? _initializedFields;
-
- final int charOpenParenOffset;
-
- bool hasMovedSuperInitializer = false;
-
- SuperInitializer? superInitializer;
-
- RedirectingInitializer? redirectingInitializer;
-
- Token? beginInitializers;
-
- SourceConstructorBuilder? actualOrigin;
-
- Constructor get actualConstructor => _constructor;
-
- bool _hasFormalsInferred = false;
-
- final bool _hasSuperInitializingFormals;
-
- final List<SynthesizedFunctionNode> _superParameterDefaultValueCloners =
- <SynthesizedFunctionNode>[];
-
- SourceConstructorBuilder(
- List<MetadataBuilder>? metadata,
- int modifiers,
- TypeBuilder? returnType,
- String name,
- List<TypeVariableBuilder>? typeVariables,
- List<FormalParameterBuilder>? formals,
- SourceLibraryBuilder compilationUnit,
- int startCharOffset,
- int charOffset,
- this.charOpenParenOffset,
- int charEndOffset,
- Reference? constructorReference,
- Reference? tearOffReference,
- {String? nativeMethodName,
- required bool forAbstractClassOrEnum})
- : _constructor = new Constructor(new FunctionNode(null),
- name: new Name(name, compilationUnit.library),
- fileUri: compilationUnit.fileUri,
- reference: constructorReference)
- ..startFileOffset = startCharOffset
- ..fileOffset = charOffset
- ..fileEndOffset = charEndOffset
- ..isNonNullableByDefault = compilationUnit.isNonNullableByDefault,
- _constructorTearOff = createConstructorTearOffProcedure(
- name,
- compilationUnit,
- compilationUnit.fileUri,
- charOffset,
- tearOffReference,
- forAbstractClassOrEnum: forAbstractClassOrEnum),
- _hasSuperInitializingFormals =
- formals?.any((formal) => formal.isSuperInitializingFormal) ?? false,
- super(metadata, modifiers, returnType, name, typeVariables, formals,
- compilationUnit, charOffset, nativeMethodName);
-
- @override
- SourceLibraryBuilder get library => super.library as SourceLibraryBuilder;
-
- @override
- SourceClassBuilder get classBuilder =>
- super.classBuilder as SourceClassBuilder;
-
- @override
- Member? get readTarget => _constructorTearOff ?? _constructor;
-
- @override
- Member? get writeTarget => null;
-
- @override
- Member get invokeTarget => constructor;
-
- @override
- FunctionNode get function => _constructor.function;
-
- @override
- Iterable<Member> get exportedMembers => [constructor];
-
- @override
- SourceConstructorBuilder get origin => actualOrigin ?? this;
-
- ConstructorBuilder? get patchForTesting =>
- dataForTesting?.patchForTesting as ConstructorBuilder?;
-
- @override
- bool get isDeclarationInstanceMember => false;
-
- @override
- bool get isClassInstanceMember => false;
-
- @override
- bool get isConstructor => true;
-
- @override
- AsyncMarker get asyncModifier => AsyncMarker.Sync;
-
- @override
- ProcedureKind? get kind => null;
-
- @override
- bool get isRedirectingGenerativeConstructor {
- return isRedirectingGenerativeConstructorImplementation(_constructor);
- }
-
- @override
- void buildMembers(
- SourceLibraryBuilder library, void Function(Member, BuiltMemberKind) f) {
- Member member = build(library);
- f(member, BuiltMemberKind.Constructor);
- if (_constructorTearOff != null) {
- f(_constructorTearOff!, BuiltMemberKind.Method);
- }
- }
-
- bool _hasBeenBuilt = false;
-
- @override
- Constructor build(SourceLibraryBuilder libraryBuilder) {
- if (!_hasBeenBuilt) {
- buildFunction(libraryBuilder);
- _constructor.function.fileOffset = charOpenParenOffset;
- _constructor.function.fileEndOffset = _constructor.fileEndOffset;
- _constructor.function.typeParameters = const <TypeParameter>[];
- _constructor.isConst = isConst;
- _constructor.isExternal = isExternal;
- updatePrivateMemberName(_constructor, libraryBuilder);
-
- if (_constructorTearOff != null) {
- buildConstructorTearOffProcedure(_constructorTearOff!, _constructor,
- classBuilder.cls, libraryBuilder);
- }
-
- _hasBeenBuilt = true;
- }
- if (formals != null) {
- bool needsInference = false;
- for (FormalParameterBuilder formal in formals!) {
- if (formal.type == null &&
- (formal.isInitializingFormal || formal.isSuperInitializingFormal)) {
- formal.variable!.type = const UnknownType();
- needsInference = true;
- }
- }
- if (needsInference) {
- assert(
- library == libraryBuilder,
- "Unexpected library builder ${libraryBuilder} for"
- " constructor $this in ${library}.");
- libraryBuilder.loader
- .registerConstructorToBeInferred(_constructor, this);
- }
- }
- return _constructor;
- }
-
- /// Infers the types of any untyped initializing formals.
- void inferFormalTypes(ClassHierarchy classHierarchy) {
- if (_hasFormalsInferred) return;
- if (formals != null) {
- for (FormalParameterBuilder formal in formals!) {
- if (formal.type == null) {
- if (formal.isInitializingFormal) {
- formal.finalizeInitializingFormal(classBuilder);
- }
- }
- }
-
- if (_hasSuperInitializingFormals) {
- if (beginInitializers != null) {
- BodyBuilder bodyBuilder = library.loader
- .createBodyBuilderForOutlineExpression(
- library, classBuilder, this, classBuilder.scope, fileUri);
- bodyBuilder.constantContext = ConstantContext.required;
- bodyBuilder.parseInitializers(beginInitializers!,
- doFinishConstructor: false);
- }
- finalizeSuperInitializingFormals(
- classHierarchy, _superParameterDefaultValueCloners);
- }
- }
- _hasFormalsInferred = true;
- }
-
- /* ConstructorBuilder | DillConstructorBuilder */
- Object? _computeSuperTargetBuilder() {
- Constructor superTarget;
- ClassBuilder superclassBuilder;
-
- TypeBuilder? supertype = classBuilder.supertypeBuilder;
- if (supertype is NamedTypeBuilder) {
- TypeDeclarationBuilder? declaration = supertype.declaration;
- if (declaration is ClassBuilder) {
- superclassBuilder = declaration;
- } else if (declaration is TypeAliasBuilder) {
- declaration = declaration.unaliasDeclaration(supertype.arguments);
- if (declaration is ClassBuilder) {
- superclassBuilder = declaration;
- } else {
- // The error in this case should be reported elsewhere.
- return null;
- }
- } else {
- // The error in this case should be reported elsewhere.
- return null;
- }
- } else {
- // The error in this case should be reported elsewhere.
- return null;
- }
-
- if (constructor.initializers.isNotEmpty &&
- constructor.initializers.last is SuperInitializer) {
- superTarget = (constructor.initializers.last as SuperInitializer).target;
- } else {
- MemberBuilder? memberBuilder = superclassBuilder.constructors
- .lookup("", charOffset, library.fileUri);
- if (memberBuilder is ConstructorBuilder) {
- superTarget = memberBuilder.constructor;
- } else if (memberBuilder is DillConstructorBuilder) {
- superTarget = memberBuilder.constructor;
- } else {
- // The error in this case should be reported elsewhere.
- return null;
- }
- }
-
- MemberBuilder? constructorBuilder =
- superclassBuilder.findConstructorOrFactory(
- superTarget.name.text, charOffset, library.fileUri, library);
- return constructorBuilder is ConstructorBuilder ||
- constructorBuilder is DillConstructorBuilder
- ? constructorBuilder
- : null;
- }
-
- void finalizeSuperInitializingFormals(ClassHierarchy classHierarchy,
- List<SynthesizedFunctionNode> synthesizedFunctionNodes) {
- if (formals == null) return;
- if (!_hasSuperInitializingFormals) return;
-
- void performRecoveryForErroneousCase() {
- for (FormalParameterBuilder formal in formals!) {
- if (formal.isSuperInitializingFormal) {
- formal.variable!.type = const DynamicType();
- }
- }
- }
-
- Object? superTargetBuilder = _computeSuperTargetBuilder();
- Constructor superTarget;
- List<FormalParameterBuilder>? superFormals;
- if (superTargetBuilder is SourceConstructorBuilder) {
- superTarget = superTargetBuilder.constructor;
- superFormals = superTargetBuilder.formals!;
- } else if (superTargetBuilder is DillConstructorBuilder) {
- superTarget = superTargetBuilder.constructor;
- if (superTargetBuilder is SyntheticConstructorBuilder) {
- superFormals = superTargetBuilder.formals;
- } else {
- // The error in this case should be reported elsewhere. Here we perform
- // a simple recovery.
- return performRecoveryForErroneousCase();
- }
- } else {
- // The error in this case should be reported elsewhere. Here we perform a
- // simple recovery.
- return performRecoveryForErroneousCase();
- }
-
- if (superFormals == null) {
- // The error in this case should be reported elsewhere. Here we perform a
- // simple recovery.
- return performRecoveryForErroneousCase();
- }
-
- if (superTargetBuilder is SourceConstructorBuilder) {
- superTargetBuilder.inferFormalTypes(classHierarchy);
- } else if (superTargetBuilder is SyntheticConstructorBuilder) {
- MemberBuilder? superTargetOriginBuilder = superTargetBuilder.actualOrigin;
- if (superTargetOriginBuilder is SourceConstructorBuilder) {
- superTargetOriginBuilder.inferFormalTypes(classHierarchy);
- }
- }
-
- int superInitializingFormalIndex = -1;
- List<int>? positionalSuperParameters;
- List<String>? namedSuperParameters;
-
- Supertype? supertype = classHierarchy.getClassAsInstanceOf(
- classBuilder.cls, superTarget.enclosingClass);
- assert(supertype != null);
- Map<TypeParameter, DartType> substitution =
- new Map<TypeParameter, DartType>.fromIterables(
- supertype!.classNode.typeParameters, supertype.typeArguments);
-
- for (int formalIndex = 0; formalIndex < formals!.length; formalIndex++) {
- FormalParameterBuilder formal = formals![formalIndex];
- if (formal.isSuperInitializingFormal) {
- superInitializingFormalIndex++;
- bool hasImmediatelyDeclaredInitializer = formal.hasDeclaredInitializer;
- if (formal.type == null) {
- DartType? type;
-
- if (formal.isPositional) {
- if (superInitializingFormalIndex < superFormals.length) {
- FormalParameterBuilder correspondingSuperFormal =
- superFormals[superInitializingFormalIndex];
- formal.hasDeclaredInitializer =
- hasImmediatelyDeclaredInitializer ||
- correspondingSuperFormal.hasDeclaredInitializer;
- if (!hasImmediatelyDeclaredInitializer) {
- (positionalSuperParameters ??= <int>[]).add(formalIndex);
- }
- type = correspondingSuperFormal.variable!.type;
- } else {
- // TODO(cstefantsova): Report an error.
- }
- } else {
- FormalParameterBuilder? correspondingSuperFormal;
- for (FormalParameterBuilder superFormal in superFormals) {
- if (superFormal.isNamed && superFormal.name == formal.name) {
- correspondingSuperFormal = superFormal;
- break;
- }
- }
-
- if (correspondingSuperFormal != null) {
- formal.hasDeclaredInitializer =
- hasImmediatelyDeclaredInitializer ||
- correspondingSuperFormal.hasDeclaredInitializer;
- if (!hasImmediatelyDeclaredInitializer) {
- (namedSuperParameters ??= <String>[]).add(formal.name);
- }
- type = correspondingSuperFormal.variable!.type;
- } else {
- // TODO(cstefantsova): Report an error.
- }
- }
-
- if (substitution.isNotEmpty && type != null) {
- type = substitute(type, substitution);
- }
- formal.variable!.type = type ?? const DynamicType();
- } else {
- formal.variable!.type = const DynamicType();
- }
- }
- }
-
- if (positionalSuperParameters != null || namedSuperParameters != null) {
- synthesizedFunctionNodes.add(new SynthesizedFunctionNode(
- substitution, superTarget.function, constructor.function,
- positionalSuperParameters: positionalSuperParameters ?? const <int>[],
- namedSuperParameters: namedSuperParameters ?? const <String>[],
- isOutlineNode: true));
- }
- }
-
- bool _hasBuiltOutlines = false;
-
- @override
- void buildOutlineExpressions(
- SourceLibraryBuilder library,
- ClassHierarchy classHierarchy,
- List<DelayedActionPerformer> delayedActionPerformers,
- List<SynthesizedFunctionNode> synthesizedFunctionNodes) {
- if (_hasBuiltOutlines) return;
- if (isConst && isPatch) {
- origin.buildOutlineExpressions(library, classHierarchy,
- delayedActionPerformers, synthesizedFunctionNodes);
- }
- super.buildOutlineExpressions(library, classHierarchy,
- delayedActionPerformers, synthesizedFunctionNodes);
-
- // For modular compilation purposes we need to include initializers
- // for const constructors into the outline. We also need to parse
- // initializers to infer types of the super-initializing parameters.
- if ((isConst || _hasSuperInitializingFormals) &&
- beginInitializers != null) {
- BodyBuilder bodyBuilder = library.loader
- .createBodyBuilderForOutlineExpression(
- library, classBuilder, this, classBuilder.scope, fileUri);
- bodyBuilder.constantContext = ConstantContext.required;
- bodyBuilder.parseInitializers(beginInitializers!,
- doFinishConstructor: isConst);
- bodyBuilder.performBacklogComputations(delayedActionPerformers);
- }
- beginInitializers = null;
- addSuperParameterDefaultValueCloners(synthesizedFunctionNodes);
- if (isConst && isPatch) {
- _finishPatch();
- }
- _hasBuiltOutlines = true;
- }
-
- void addSuperParameterDefaultValueCloners(
- List<SynthesizedFunctionNode> synthesizedFunctionNodes) {
- Object? superTargetBuilder = _computeSuperTargetBuilder();
- if (superTargetBuilder is SourceConstructorBuilder) {
- superTargetBuilder
- .addSuperParameterDefaultValueCloners(synthesizedFunctionNodes);
- } else if (superTargetBuilder is SyntheticConstructorBuilder) {
- superTargetBuilder
- .addSuperParameterDefaultValueCloners(synthesizedFunctionNodes);
- }
- synthesizedFunctionNodes.addAll(_superParameterDefaultValueCloners);
- _superParameterDefaultValueCloners.clear();
- }
-
- @override
- void buildFunction(SourceLibraryBuilder library) {
- // According to the specification §9.3 the return type of a constructor
- // function is its enclosing class.
- super.buildFunction(library);
- 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.withDefaultNullabilityForLibrary(
- typeParameter, library.library));
- }
- function.returnType = new InterfaceType(
- enclosingClass, library.nonNullable, typeParameterTypes);
- }
-
- @override
- Constructor get constructor => isPatch ? origin.constructor : _constructor;
-
- @override
- Member get member => constructor;
-
- void injectInvalidInitializer(Message message, int charOffset, int length,
- ExpressionGeneratorHelper helper) {
- List<Initializer> initializers = _constructor.initializers;
- Initializer lastInitializer = initializers.removeLast();
- assert(lastInitializer == superInitializer ||
- lastInitializer == redirectingInitializer);
- Initializer error = helper.buildInvalidInitializer(
- helper.buildProblem(message, charOffset, length));
- initializers.add(error..parent = _constructor);
- initializers.add(lastInitializer);
- }
-
- void addInitializer(Initializer initializer, ExpressionGeneratorHelper helper,
- {required InitializerInferenceResult? inferenceResult}) {
- List<Initializer> initializers = _constructor.initializers;
- if (initializer is SuperInitializer) {
- if (superInitializer != null) {
- injectInvalidInitializer(messageMoreThanOneSuperInitializer,
- initializer.fileOffset, "super".length, helper);
- } else if (redirectingInitializer != null) {
- injectInvalidInitializer(
- messageRedirectingConstructorWithSuperInitializer,
- initializer.fileOffset,
- "super".length,
- helper);
- } else {
- inferenceResult?.applyResult(initializers, _constructor);
- initializers.add(initializer..parent = _constructor);
- superInitializer = initializer;
- }
- } else if (initializer is RedirectingInitializer) {
- if (superInitializer != null) {
- // Point to the existing super initializer.
- injectInvalidInitializer(
- messageRedirectingConstructorWithSuperInitializer,
- superInitializer!.fileOffset,
- "super".length,
- helper);
- } else if (redirectingInitializer != null) {
- injectInvalidInitializer(
- messageRedirectingConstructorWithMultipleRedirectInitializers,
- initializer.fileOffset,
- noLength,
- helper);
- } else if (initializers.isNotEmpty) {
- // Error on all previous ones.
- for (int i = 0; i < initializers.length; i++) {
- Initializer initializer = initializers[i];
- int length = noLength;
- if (initializer is AssertInitializer) length = "assert".length;
- Initializer error = helper.buildInvalidInitializer(
- helper.buildProblem(
- messageRedirectingConstructorWithAnotherInitializer,
- initializer.fileOffset,
- length));
- error.parent = _constructor;
- initializers[i] = error;
- }
- inferenceResult?.applyResult(initializers, _constructor);
- initializers.add(initializer..parent = _constructor);
- redirectingInitializer = initializer;
- } else {
- inferenceResult?.applyResult(initializers, _constructor);
- initializers.add(initializer..parent = _constructor);
- redirectingInitializer = initializer;
- }
- } else if (redirectingInitializer != null) {
- int length = noLength;
- if (initializer is AssertInitializer) length = "assert".length;
- injectInvalidInitializer(
- messageRedirectingConstructorWithAnotherInitializer,
- initializer.fileOffset,
- length,
- helper);
- } else if (superInitializer != null) {
- injectInvalidInitializer(messageSuperInitializerNotLast,
- initializer.fileOffset, noLength, helper);
- } else {
- inferenceResult?.applyResult(initializers, _constructor);
- initializers.add(initializer..parent = _constructor);
- }
- }
-
- @override
- VariableDeclaration? getTearOffParameter(int index) {
- 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 _finishPatch() {
- // TODO(ahe): restore file-offset once we track both origin and patch file
- // URIs. See https://github.com/dart-lang/sdk/issues/31579
- origin.constructor.fileUri = fileUri;
- origin.constructor.startFileOffset = _constructor.startFileOffset;
- origin.constructor.fileOffset = _constructor.fileOffset;
- origin.constructor.fileEndOffset = _constructor.fileEndOffset;
- origin.constructor.annotations
- .forEach((m) => m.fileOffset = _constructor.fileOffset);
-
- origin.constructor.isExternal = _constructor.isExternal;
- origin.constructor.function = _constructor.function;
- origin.constructor.function.parent = origin.constructor;
- origin.constructor.initializers = _constructor.initializers;
- setParents(origin.constructor.initializers, origin.constructor);
- }
-
- @override
- int finishPatch() {
- if (!isPatch) return 0;
- _finishPatch();
- return 1;
- }
-
- @override
- void becomeNative(SourceLoader loader) {
- _constructor.isExternal = true;
- super.becomeNative(loader);
- }
-
- @override
- void applyPatch(Builder patch) {
- if (patch is SourceConstructorBuilder) {
- if (checkPatch(patch)) {
- patch.actualOrigin = this;
- dataForTesting?.patchForTesting = patch;
- }
- } else {
- reportPatchMismatch(patch);
- }
- }
-
- 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;
- hasMovedSuperInitializer = false;
- }
-
- @override
- List<ClassMember> get localMembers =>
- throw new UnsupportedError('${runtimeType}.localMembers');
-
- @override
- List<ClassMember> get localSetters =>
- throw new UnsupportedError('${runtimeType}.localSetters');
-
- /// Registers field as being initialized by this constructor.
- ///
- /// The field can be initialized either via an initializing formal or via an
- /// entry in the constructor initializer list.
- void registerInitializedField(FieldBuilder fieldBuilder) {
- (_initializedFields ??= {}).add(fieldBuilder);
- }
-
- /// Returns the fields registered as initialized by this constructor.
- ///
- /// Returns the set of fields previously registered via
- /// [registerInitializedField] and passes on the ownership of the collection
- /// to the caller.
- Set<FieldBuilder>? takeInitializedFields() {
- Set<FieldBuilder>? result = _initializedFields;
- _initializedFields = null;
- return result;
- }
-}
-
-class SyntheticConstructorBuilder extends DillConstructorBuilder
- with SourceMemberBuilderMixin {
- // TODO(johnniwinther,cstefantsova): Rename [_origin] to avoid the confusion
- // with patches.
- // TODO(johnniwinther): Change the type of [_origin] to SourceMemberBuilder
- // when it's the supertype for both old SourceMemberBuilder and
- // SyntheticConstructorBuilder.
- MemberBuilder? _origin;
- SynthesizedFunctionNode? _synthesizedFunctionNode;
-
- SyntheticConstructorBuilder(SourceClassBuilder parent,
- Constructor constructor, Procedure? constructorTearOff,
- {MemberBuilder? origin, SynthesizedFunctionNode? synthesizedFunctionNode})
- : _origin = origin,
- _synthesizedFunctionNode = synthesizedFunctionNode,
- super(constructor, constructorTearOff, parent);
-
- // TODO(johnniwinther,cstefantsova): Rename [actualOrigin] to avoid the
- // confusion with patches.
- MemberBuilder? get actualOrigin {
- MemberBuilder? origin = _origin;
- while (origin is SyntheticConstructorBuilder) {
- origin = origin._origin;
- }
- return origin;
- }
-
- List<FormalParameterBuilder>? get formals {
- MemberBuilder? origin = actualOrigin;
- return origin is SourceConstructorBuilder ? origin.formals : null;
- }
-
- @override
- void buildOutlineExpressions(
- SourceLibraryBuilder libraryBuilder,
- ClassHierarchy classHierarchy,
- List<DelayedActionPerformer> delayedActionPerformers,
- List<SynthesizedFunctionNode> synthesizedFunctionNodes) {
- if (_origin != null) {
- // Ensure that default value expressions have been created for [_origin].
- LibraryBuilder originLibraryBuilder = _origin!.library;
- if (originLibraryBuilder is SourceLibraryBuilder) {
- // If [_origin] is from a source library, we need to build the default
- // values and initializers first.
- MemberBuilder origin = _origin!;
- if (origin is SourceConstructorBuilder) {
- origin.buildOutlineExpressions(originLibraryBuilder, classHierarchy,
- delayedActionPerformers, synthesizedFunctionNodes);
- } else if (origin is SyntheticConstructorBuilder) {
- origin.buildOutlineExpressions(originLibraryBuilder, classHierarchy,
- delayedActionPerformers, synthesizedFunctionNodes);
- }
- }
- addSuperParameterDefaultValueCloners(synthesizedFunctionNodes);
- _origin = null;
- }
- }
-
- void addSuperParameterDefaultValueCloners(
- List<SynthesizedFunctionNode> synthesizedFunctionNodes) {
- MemberBuilder? origin = _origin;
- if (origin is SourceConstructorBuilder) {
- origin.addSuperParameterDefaultValueCloners(synthesizedFunctionNodes);
- } else if (origin is SyntheticConstructorBuilder) {
- origin.addSuperParameterDefaultValueCloners(synthesizedFunctionNodes);
- }
- if (_synthesizedFunctionNode != null) {
- synthesizedFunctionNodes
- .add(_synthesizedFunctionNode!..isOutlineNode = true);
- _synthesizedFunctionNode = null;
- }
- }
-}
diff --git a/pkg/front_end/lib/src/fasta/builder/field_builder.dart b/pkg/front_end/lib/src/fasta/builder/field_builder.dart
index 251ad96..725b34c 100644
--- a/pkg/front_end/lib/src/fasta/builder/field_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/field_builder.dart
@@ -4,43 +4,9 @@
library fasta.field_builder;
-import 'package:_fe_analyzer_shared/src/scanner/scanner.dart' show Token;
-
import 'package:kernel/ast.dart';
-import 'package:kernel/class_hierarchy.dart';
import 'package:kernel/core_types.dart';
-import 'package:kernel/src/legacy_erasure.dart';
-import 'package:kernel/type_algebra.dart';
-import '../constant_context.dart' show ConstantContext;
-
-import '../fasta_codes.dart' show messageInternalProblemAlreadyInitialized;
-
-import '../kernel/body_builder.dart' show BodyBuilder;
-import '../kernel/hierarchy/class_member.dart';
-import '../kernel/hierarchy/members_builder.dart';
-import '../kernel/implicit_field_type.dart';
-import '../kernel/kernel_helper.dart';
-import '../kernel/late_lowering.dart' as late_lowering;
-import '../kernel/member_covariance.dart';
-
-import '../modifier.dart' show covariantMask, hasInitializerMask, lateMask;
-
-import '../problems.dart' show internalProblem;
-
-import '../scope.dart' show Scope;
-
-import '../source/name_scheme.dart';
-import '../source/source_extension_builder.dart';
-import '../source/source_library_builder.dart' show SourceLibraryBuilder;
-import '../source/source_loader.dart' show SourceLoader;
-
-import '../type_inference/type_inference_engine.dart'
- show IncludesTypeParametersNonCovariantly;
-
-import '../util/helpers.dart' show DelayedActionPerformer;
-
-import 'class_builder.dart';
import 'member_builder.dart';
import 'metadata_builder.dart';
import 'type_builder.dart';
@@ -82,1776 +48,3 @@
DartType get fieldType;
}
-
-class SourceFieldBuilder extends SourceMemberBuilderImpl
- implements FieldBuilder {
- @override
- final String name;
-
- @override
- final int modifiers;
-
- late FieldEncoding _fieldEncoding;
-
- @override
- final List<MetadataBuilder>? metadata;
-
- @override
- final TypeBuilder? type;
-
- Token? _constInitializerToken;
-
- bool hadTypesInferred = false;
-
- @override
- bool hasBodyBeenBuilt = false;
-
- // TODO(johnniwinther): [parent] is not trust-worthy for determining
- // properties since it is changed after the creation of the builder. For now
- // we require it has an argument here. A follow-up should clean up the
- // misuse of parent.
- @override
- final bool isTopLevel;
-
- SourceFieldBuilder(
- this.metadata,
- this.type,
- this.name,
- this.modifiers,
- this.isTopLevel,
- SourceLibraryBuilder libraryBuilder,
- int charOffset,
- int charEndOffset,
- NameScheme fieldNameScheme,
- {Reference? fieldReference,
- Reference? fieldGetterReference,
- Reference? fieldSetterReference,
- Reference? lateIsSetFieldReference,
- Reference? lateIsSetGetterReference,
- Reference? lateIsSetSetterReference,
- Reference? lateGetterReference,
- Reference? lateSetterReference,
- Token? constInitializerToken})
- : _constInitializerToken = constInitializerToken,
- super(libraryBuilder, charOffset) {
- bool isInstanceMember = fieldNameScheme.isInstanceMember;
-
- Uri fileUri = libraryBuilder.fileUri;
- // If in mixed mode, late lowerings cannot use `null` as a sentinel on
- // non-nullable fields since they can be assigned from legacy code.
- late_lowering.IsSetStrategy isSetStrategy =
- late_lowering.computeIsSetStrategy(libraryBuilder);
-
- if (isAbstract || isExternal) {
- assert(fieldReference == null);
- assert(lateIsSetFieldReference == null);
- assert(lateIsSetGetterReference == null);
- assert(lateIsSetSetterReference == null);
- assert(lateGetterReference == null);
- assert(lateSetterReference == null);
- _fieldEncoding = new AbstractOrExternalFieldEncoding(
- this,
- name,
- fieldNameScheme,
- fileUri,
- charOffset,
- charEndOffset,
- fieldGetterReference,
- fieldSetterReference,
- isAbstract: isAbstract,
- isExternal: isExternal,
- isFinal: isFinal,
- isCovariantByDeclaration: isCovariantByDeclaration,
- isNonNullableByDefault: library.isNonNullableByDefault);
- } else if (isLate &&
- libraryBuilder.loader.target.backendTarget.isLateFieldLoweringEnabled(
- hasInitializer: hasInitializer,
- isFinal: isFinal,
- isStatic: !isInstanceMember)) {
- if (hasInitializer) {
- if (isFinal) {
- _fieldEncoding = new LateFinalFieldWithInitializerEncoding(
- name,
- fieldNameScheme,
- fileUri,
- charOffset,
- charEndOffset,
- fieldReference,
- fieldGetterReference,
- fieldSetterReference,
- lateIsSetFieldReference,
- lateIsSetGetterReference,
- lateIsSetSetterReference,
- lateGetterReference,
- lateSetterReference,
- isCovariantByDeclaration,
- isSetStrategy);
- } else {
- _fieldEncoding = new LateFieldWithInitializerEncoding(
- name,
- fieldNameScheme,
- fileUri,
- charOffset,
- charEndOffset,
- fieldReference,
- fieldGetterReference,
- fieldSetterReference,
- lateIsSetFieldReference,
- lateIsSetGetterReference,
- lateIsSetSetterReference,
- lateGetterReference,
- lateSetterReference,
- isCovariantByDeclaration,
- isSetStrategy);
- }
- } else {
- if (isFinal) {
- _fieldEncoding = new LateFinalFieldWithoutInitializerEncoding(
- name,
- fieldNameScheme,
- fileUri,
- charOffset,
- charEndOffset,
- fieldReference,
- fieldGetterReference,
- fieldSetterReference,
- lateIsSetFieldReference,
- lateIsSetGetterReference,
- lateIsSetSetterReference,
- lateGetterReference,
- lateSetterReference,
- isCovariantByDeclaration,
- isSetStrategy);
- } else {
- _fieldEncoding = new LateFieldWithoutInitializerEncoding(
- name,
- fieldNameScheme,
- fileUri,
- charOffset,
- charEndOffset,
- fieldReference,
- fieldGetterReference,
- fieldSetterReference,
- lateIsSetFieldReference,
- lateIsSetGetterReference,
- lateIsSetSetterReference,
- lateGetterReference,
- lateSetterReference,
- isCovariantByDeclaration,
- isSetStrategy);
- }
- }
- } else if (libraryBuilder.isNonNullableByDefault &&
- libraryBuilder.loader.target.backendTarget.useStaticFieldLowering &&
- !isInstanceMember &&
- !isConst &&
- hasInitializer) {
- if (isFinal) {
- _fieldEncoding = new LateFinalFieldWithInitializerEncoding(
- name,
- fieldNameScheme,
- fileUri,
- charOffset,
- charEndOffset,
- fieldReference,
- fieldGetterReference,
- fieldSetterReference,
- lateIsSetFieldReference,
- lateIsSetGetterReference,
- lateIsSetSetterReference,
- lateGetterReference,
- lateSetterReference,
- isCovariantByDeclaration,
- isSetStrategy);
- } else {
- _fieldEncoding = new LateFieldWithInitializerEncoding(
- name,
- fieldNameScheme,
- fileUri,
- charOffset,
- charEndOffset,
- fieldReference,
- fieldGetterReference,
- fieldSetterReference,
- lateIsSetFieldReference,
- lateIsSetGetterReference,
- lateIsSetSetterReference,
- lateGetterReference,
- lateSetterReference,
- isCovariantByDeclaration,
- isSetStrategy);
- }
- } else {
- assert(lateIsSetFieldReference == null);
- assert(lateIsSetGetterReference == null);
- assert(lateIsSetSetterReference == null);
- assert(lateGetterReference == null);
- assert(lateSetterReference == null);
- _fieldEncoding = new RegularFieldEncoding(
- name, fieldNameScheme, fileUri, charOffset, charEndOffset,
- isFinal: isFinal,
- isConst: isConst,
- isLate: isLate,
- hasInitializer: hasInitializer,
- isNonNullableByDefault: library.isNonNullableByDefault,
- fieldReference: fieldReference,
- getterReference: fieldGetterReference,
- setterReference: fieldSetterReference);
- }
- }
-
- bool get isLateLowered => _fieldEncoding.isLateLowering;
-
- bool _typeEnsured = false;
- Set<ClassMember>? _overrideDependencies;
-
- void registerOverrideDependency(Set<ClassMember> overriddenMembers) {
- assert(
- overriddenMembers.every((overriddenMember) =>
- overriddenMember.classBuilder != classBuilder),
- "Unexpected override dependencies for $this: $overriddenMembers");
- _overrideDependencies ??= {};
- _overrideDependencies!.addAll(overriddenMembers);
- }
-
- void _ensureType(ClassMembersBuilder membersBuilder) {
- if (_typeEnsured) return;
- if (_overrideDependencies != null) {
- membersBuilder.inferFieldType(this, _overrideDependencies!);
- _overrideDependencies = null;
- } else {
- inferType();
- }
- _typeEnsured = true;
- }
-
- @override
- SourceLibraryBuilder get library => super.library as SourceLibraryBuilder;
-
- @override
- Member get member => _fieldEncoding.field;
-
- @override
- String get debugName => "FieldBuilder";
-
- @override
- bool get isField => true;
-
- @override
- bool get isLate => (modifiers & lateMask) != 0;
-
- @override
- bool get isCovariantByDeclaration => (modifiers & covariantMask) != 0;
-
- @override
- bool get hasInitializer => (modifiers & hasInitializerMask) != 0;
-
- @override
- void buildBody(CoreTypes coreTypes, Expression? initializer) {
- assert(!hasBodyBeenBuilt);
- hasBodyBeenBuilt = true;
- if (!hasInitializer &&
- initializer != null &&
- initializer is! NullLiteral &&
- !isConst &&
- !isFinal) {
- internalProblem(
- messageInternalProblemAlreadyInitialized, charOffset, fileUri);
- }
- _fieldEncoding.createBodies(coreTypes, initializer);
- }
-
- @override
- List<Initializer> buildInitializer(int fileOffset, Expression value,
- {required bool isSynthetic}) {
- return _fieldEncoding.createInitializer(fileOffset, value,
- isSynthetic: isSynthetic);
- }
-
- @override
- bool get isEligibleForInference {
- return type == null && (hasInitializer || isClassInstanceMember);
- }
-
- @override
- bool get isAssignable {
- if (isConst) return false;
- if (isFinal) {
- if (isLate) {
- return !hasInitializer;
- }
- return false;
- }
- return true;
- }
-
- @override
- Field get field => _fieldEncoding.field;
-
- @override
- Member get readTarget => _fieldEncoding.readTarget;
-
- @override
- Member? get writeTarget {
- return isAssignable ? _fieldEncoding.writeTarget : null;
- }
-
- @override
- Member get invokeTarget => readTarget;
-
- @override
- Iterable<Member> get exportedMembers => _fieldEncoding.exportedMembers;
-
- @override
- void buildMembers(
- SourceLibraryBuilder library, void Function(Member, BuiltMemberKind) f) {
- build(library);
- _fieldEncoding.registerMembers(library, this, f);
- }
-
- /// Builds the core AST structures for this field as needed for the outline.
- void build(SourceLibraryBuilder libraryBuilder) {
- if (type != null) {
- fieldType = type!.build(libraryBuilder);
- }
- _fieldEncoding.build(libraryBuilder, this);
- }
-
- @override
- void buildOutlineExpressions(
- SourceLibraryBuilder library,
- ClassHierarchy classHierarchy,
- List<DelayedActionPerformer> delayedActionPerformers,
- List<SynthesizedFunctionNode> synthesizedFunctionNodes) {
- _fieldEncoding.completeSignature(classHierarchy.coreTypes);
-
- for (Annotatable annotatable in _fieldEncoding.annotatables) {
- MetadataBuilder.buildAnnotations(
- annotatable,
- metadata,
- library,
- declarationBuilder,
- this,
- fileUri,
- declarationBuilder?.scope ?? library.scope);
- }
-
- // For modular compilation we need to include initializers of all const
- // fields and all non-static final fields in classes with const constructors
- // into the outline.
- if ((isConst ||
- (isFinal &&
- !isStatic &&
- isClassMember &&
- classBuilder!.declaresConstConstructor)) &&
- _constInitializerToken != null) {
- Scope scope = declarationBuilder?.scope ?? library.scope;
- BodyBuilder bodyBuilder = library.loader
- .createBodyBuilderForOutlineExpression(
- library, declarationBuilder, this, scope, fileUri);
- bodyBuilder.constantContext =
- isConst ? ConstantContext.inferred : ConstantContext.required;
- Expression initializer = bodyBuilder.typeInferrer.inferFieldInitializer(
- bodyBuilder,
- fieldType,
- bodyBuilder.parseFieldInitializer(_constInitializerToken!));
- if (bodyBuilder.transformSetLiterals ||
- bodyBuilder.transformCollections) {
- // Wrap the initializer in a temporary parent expression; the
- // transformations need a parent relation.
- Not wrapper = new Not(initializer);
- SourceLoader loader = library.loader;
- loader.transformPostInference(wrapper, bodyBuilder.transformSetLiterals,
- bodyBuilder.transformCollections, library.library);
- initializer = wrapper.operand;
- }
- buildBody(classHierarchy.coreTypes, initializer);
- bodyBuilder.performBacklogComputations(delayedActionPerformers);
- }
- _constInitializerToken = null;
- }
-
- @override
- DartType get fieldType => _fieldEncoding.type;
-
- void set fieldType(DartType value) {
- _fieldEncoding.type = value;
- if (!isFinal && !isConst && parent is ClassBuilder) {
- Class enclosingClass = classBuilder!.cls;
- if (enclosingClass.typeParameters.isNotEmpty) {
- IncludesTypeParametersNonCovariantly needsCheckVisitor =
- new IncludesTypeParametersNonCovariantly(
- enclosingClass.typeParameters,
- // We are checking the field type as if it is the type of the
- // parameter of the implicit setter and this is a contravariant
- // position.
- initialVariance: Variance.contravariant);
- if (value.accept(needsCheckVisitor)) {
- _fieldEncoding.setGenericCovariantImpl();
- }
- }
- }
- }
-
- @override
- DartType inferType() {
- SourceLibraryBuilder library = this.library;
- if (fieldType is! ImplicitFieldType) {
- // We have already inferred a type.
- return fieldType;
- }
-
- ImplicitFieldType implicitFieldType = fieldType as ImplicitFieldType;
- DartType inferredType = implicitFieldType.computeType();
- if (fieldType is ImplicitFieldType) {
- // `fieldType` may have changed if a circularity was detected when
- // [inferredType] was computed.
- if (!library.isNonNullableByDefault) {
- inferredType = legacyErasure(inferredType);
- }
- fieldType = implicitFieldType.checkInferred(inferredType);
-
- IncludesTypeParametersNonCovariantly? needsCheckVisitor;
- if (parent is ClassBuilder) {
- Class enclosingClass = classBuilder!.cls;
- if (enclosingClass.typeParameters.isNotEmpty) {
- needsCheckVisitor = new IncludesTypeParametersNonCovariantly(
- enclosingClass.typeParameters,
- // We are checking the field type as if it is the type of the
- // parameter of the implicit setter and this is a contravariant
- // position.
- initialVariance: Variance.contravariant);
- }
- }
- if (needsCheckVisitor != null) {
- if (fieldType.accept(needsCheckVisitor)) {
- _fieldEncoding.setGenericCovariantImpl();
- }
- }
- }
- return fieldType;
- }
-
- @override
- DartType get builtType => fieldType;
-
- List<ClassMember>? _localMembers;
- List<ClassMember>? _localSetters;
-
- @override
- List<ClassMember> get localMembers =>
- _localMembers ??= _fieldEncoding.getLocalMembers(this);
-
- @override
- List<ClassMember> get localSetters =>
- _localSetters ??= _fieldEncoding.getLocalSetters(this);
-}
-
-/// Strategy pattern for creating different encodings of a declared field.
-///
-/// This is used to provide lowerings for late fields using synthesized getters
-/// and setters.
-abstract class FieldEncoding {
- /// The type of the declared field.
- abstract DartType type;
-
- /// Creates the bodies needed for the field encoding using [initializer] as
- /// the declared initializer expression.
- ///
- /// This method is not called for fields in outlines unless their are constant
- /// or part of a const constructor.
- void createBodies(CoreTypes coreTypes, Expression? initializer);
-
- List<Initializer> createInitializer(int fileOffset, Expression value,
- {required bool isSynthetic});
-
- /// Registers that the (implicit) setter associated with this field needs to
- /// contain a runtime type check to deal with generic covariance.
- void setGenericCovariantImpl();
-
- /// Returns the field that holds the field value at runtime.
- Field get field;
-
- /// Returns the members that holds the field annotations.
- Iterable<Annotatable> get annotatables;
-
- /// Returns the member used to read the field value.
- Member get readTarget;
-
- /// Returns the member used to write to the field.
- Member? get writeTarget;
-
- /// Returns the generated members that are visible through exports.
- Iterable<Member> get exportedMembers;
-
- /// Creates the members necessary for this field encoding.
- ///
- /// This method is called for both outline and full compilation so the created
- /// members should be without body. The member bodies are created through
- /// [createBodies].
- void build(
- SourceLibraryBuilder libraryBuilder, SourceFieldBuilder fieldBuilder);
-
- /// Calls [f] for each member needed for this field encoding.
- void registerMembers(
- SourceLibraryBuilder library,
- SourceFieldBuilder fieldBuilder,
- void Function(Member, BuiltMemberKind) f);
-
- /// Returns a list of the field, getters and methods created by this field
- /// encoding.
- List<ClassMember> getLocalMembers(SourceFieldBuilder fieldBuilder);
-
- /// Returns a list of the setters created by this field encoding.
- List<ClassMember> getLocalSetters(SourceFieldBuilder fieldBuilder);
-
- /// Ensures that the signatures all members created by this field encoding
- /// are fully typed.
- void completeSignature(CoreTypes coreTypes);
-
- /// Returns `true` if this encoding is a late lowering.
- bool get isLateLowering;
-}
-
-class RegularFieldEncoding implements FieldEncoding {
- late final Field _field;
-
- RegularFieldEncoding(String name, NameScheme nameScheme, Uri fileUri,
- int charOffset, int charEndOffset,
- {required bool isFinal,
- required bool isConst,
- required bool isLate,
- required bool hasInitializer,
- required bool isNonNullableByDefault,
- required Reference? fieldReference,
- required Reference? getterReference,
- required Reference? setterReference}) {
- // ignore: unnecessary_null_comparison
- assert(isFinal != null);
- // ignore: unnecessary_null_comparison
- assert(isConst != null);
- // ignore: unnecessary_null_comparison
- assert(isLate != null);
- // ignore: unnecessary_null_comparison
- assert(hasInitializer != null);
- bool isImmutable =
- isLate ? (isFinal && hasInitializer) : (isFinal || isConst);
- _field = isImmutable
- ? new Field.immutable(
- nameScheme.getFieldName(FieldNameType.Field, name,
- isSynthesized: false),
- isFinal: isFinal,
- isConst: isConst,
- isLate: isLate,
- fileUri: fileUri,
- fieldReference: fieldReference,
- getterReference: getterReference)
- : new Field.mutable(
- nameScheme.getFieldName(FieldNameType.Field, name,
- isSynthesized: false),
- isFinal: isFinal,
- isLate: isLate,
- fileUri: fileUri,
- fieldReference: fieldReference,
- getterReference: getterReference,
- setterReference: setterReference);
- _field
- ..fileOffset = charOffset
- ..fileEndOffset = charEndOffset
- ..isNonNullableByDefault = isNonNullableByDefault;
- }
-
- @override
- DartType get type => _field.type;
-
- @override
- void set type(DartType value) {
- _field.type = value;
- }
-
- @override
- void completeSignature(CoreTypes coreTypes) {}
-
- @override
- void createBodies(CoreTypes coreTypes, Expression? initializer) {
- if (initializer != null) {
- _field.initializer = initializer..parent = _field;
- }
- }
-
- @override
- List<Initializer> createInitializer(int fileOffset, Expression value,
- {required bool isSynthetic}) {
- return <Initializer>[
- new FieldInitializer(_field, value)
- ..fileOffset = fileOffset
- ..isSynthetic = isSynthetic
- ];
- }
-
- @override
- void build(
- SourceLibraryBuilder libraryBuilder, SourceFieldBuilder fieldBuilder) {
- _field..isCovariantByDeclaration = fieldBuilder.isCovariantByDeclaration;
- if (fieldBuilder.isExtensionMember) {
- _field
- ..isStatic = true
- ..isExtensionMember = true;
- } else {
- bool isInstanceMember =
- !fieldBuilder.isStatic && !fieldBuilder.isTopLevel;
- _field
- ..isStatic = !isInstanceMember
- ..isExtensionMember = false;
- }
- _field.isLate = fieldBuilder.isLate;
- updatePrivateMemberName(_field, libraryBuilder);
- }
-
- @override
- void registerMembers(
- SourceLibraryBuilder library,
- SourceFieldBuilder fieldBuilder,
- void Function(Member, BuiltMemberKind) f) {
- f(
- _field,
- fieldBuilder.isExtensionMember
- ? BuiltMemberKind.ExtensionField
- : BuiltMemberKind.Field);
- }
-
- @override
- void setGenericCovariantImpl() {
- _field.isCovariantByClass = true;
- }
-
- @override
- Field get field => _field;
-
- @override
- Iterable<Annotatable> get annotatables => [_field];
-
- @override
- Member get readTarget => _field;
-
- @override
- Member get writeTarget => _field;
-
- @override
- Iterable<Member> get exportedMembers => [_field];
-
- @override
- List<ClassMember> getLocalMembers(SourceFieldBuilder fieldBuilder) =>
- <ClassMember>[new SourceFieldMember(fieldBuilder, forSetter: false)];
-
- @override
- List<ClassMember> getLocalSetters(SourceFieldBuilder fieldBuilder) =>
- fieldBuilder.isAssignable
- ? <ClassMember>[new SourceFieldMember(fieldBuilder, forSetter: true)]
- : const <ClassMember>[];
-
- @override
- bool get isLateLowering => false;
-}
-
-class SourceFieldMember extends BuilderClassMember {
- @override
- final SourceFieldBuilder memberBuilder;
-
- Covariance? _covariance;
-
- @override
- final bool forSetter;
-
- SourceFieldMember(this.memberBuilder, {required this.forSetter})
- // ignore: unnecessary_null_comparison
- : assert(forSetter != null);
-
- @override
- void inferType(ClassMembersBuilder membersBuilder) {
- memberBuilder._ensureType(membersBuilder);
- }
-
- @override
- void registerOverrideDependency(Set<ClassMember> overriddenMembers) {
- memberBuilder.registerOverrideDependency(overriddenMembers);
- }
-
- @override
- Member getMember(ClassMembersBuilder membersBuilder) {
- memberBuilder._ensureType(membersBuilder);
- return memberBuilder.field;
- }
-
- @override
- Covariance getCovariance(ClassMembersBuilder membersBuilder) {
- return _covariance ??= forSetter
- ? new Covariance.fromMember(getMember(membersBuilder),
- forSetter: forSetter)
- : const Covariance.empty();
- }
-
- @override
- bool get isSourceDeclaration => true;
-
- @override
- bool get isProperty => true;
-
- @override
- bool isSameDeclaration(ClassMember other) {
- return other is SourceFieldMember && memberBuilder == other.memberBuilder;
- }
-}
-
-abstract class AbstractLateFieldEncoding implements FieldEncoding {
- final String name;
- final int fileOffset;
- final int fileEndOffset;
- DartType? _type;
- late final Field _field;
- Field? _lateIsSetField;
- late Procedure _lateGetter;
- Procedure? _lateSetter;
-
- // If `true`, an isSet field is used even when the type of the field is
- // not potentially nullable.
- //
- // This is used to force use isSet fields in mixed mode encoding since
- // we cannot trust non-nullable fields to be initialized with non-null values.
- final late_lowering.IsSetStrategy _isSetStrategy;
- late_lowering.IsSetEncoding? _isSetEncoding;
-
- // If `true`, the is-set field was register before the type was known to be
- // nullable or non-nullable. In this case we do not try to remove it from
- // the generated AST to avoid inconsistency between the class hierarchy used
- // during and after inference.
- //
- // This is also used to force use isSet fields in mixed mode encoding since
- // we cannot trust non-nullable fields to be initialized with non-null values.
- bool _forceIncludeIsSetField;
-
- AbstractLateFieldEncoding(
- this.name,
- NameScheme nameScheme,
- Uri fileUri,
- int charOffset,
- int charEndOffset,
- Reference? fieldReference,
- Reference? fieldGetterReference,
- Reference? fieldSetterReference,
- Reference? lateIsSetFieldReference,
- Reference? lateIsSetGetterReference,
- Reference? lateIsSetSetterReference,
- Reference? lateGetterReference,
- Reference? lateSetterReference,
- bool isCovariantByDeclaration,
- late_lowering.IsSetStrategy isSetStrategy)
- : fileOffset = charOffset,
- fileEndOffset = charEndOffset,
- _isSetStrategy = isSetStrategy,
- _forceIncludeIsSetField =
- isSetStrategy == late_lowering.IsSetStrategy.forceUseIsSetField {
- _field = new Field.mutable(
- nameScheme.getFieldName(FieldNameType.Field, name, isSynthesized: true),
- fileUri: fileUri,
- fieldReference: fieldReference,
- getterReference: fieldGetterReference,
- setterReference: fieldSetterReference)
- ..fileOffset = charOffset
- ..fileEndOffset = charEndOffset
- ..isNonNullableByDefault = true
- ..isInternalImplementation = true;
- switch (_isSetStrategy) {
- case late_lowering.IsSetStrategy.useSentinelOrNull:
- case late_lowering.IsSetStrategy.forceUseSentinel:
- // [_lateIsSetField] is never needed.
- break;
- case late_lowering.IsSetStrategy.forceUseIsSetField:
- case late_lowering.IsSetStrategy.useIsSetFieldOrNull:
- _lateIsSetField = new Field.mutable(
- nameScheme.getFieldName(FieldNameType.IsSetField, name,
- isSynthesized: true),
- fileUri: fileUri,
- fieldReference: lateIsSetFieldReference,
- getterReference: lateIsSetGetterReference,
- setterReference: lateIsSetSetterReference)
- ..fileOffset = charOffset
- ..fileEndOffset = charEndOffset
- ..isNonNullableByDefault = true
- ..isInternalImplementation = true;
- break;
- }
- _lateGetter = new Procedure(
- nameScheme.getFieldName(FieldNameType.Getter, name,
- isSynthesized: true),
- ProcedureKind.Getter,
- new FunctionNode(null)
- ..fileOffset = charOffset
- ..fileEndOffset = charEndOffset,
- fileUri: fileUri,
- reference: lateGetterReference)
- ..fileOffset = charOffset
- ..fileEndOffset = charEndOffset
- ..isNonNullableByDefault = true;
- _lateSetter = _createSetter(
- nameScheme.getFieldName(FieldNameType.Setter, name,
- isSynthesized: true),
- fileUri,
- charOffset,
- lateSetterReference,
- isCovariantByDeclaration: isCovariantByDeclaration);
- }
-
- late_lowering.IsSetEncoding get isSetEncoding {
- assert(_type != null, "Type has not been computed for field $name.");
- return _isSetEncoding ??=
- late_lowering.computeIsSetEncoding(_type!, _isSetStrategy);
- }
-
- @override
- void completeSignature(CoreTypes coreTypes) {
- _lateIsSetField?.type = coreTypes.boolRawType(Nullability.nonNullable);
- }
-
- @override
- void createBodies(CoreTypes coreTypes, Expression? initializer) {
- assert(_type != null, "Type has not been computed for field $name.");
- if (isSetEncoding == late_lowering.IsSetEncoding.useSentinel) {
- _field.initializer = new StaticInvocation(coreTypes.createSentinelMethod,
- new Arguments([], types: [_type!])..fileOffset = fileOffset)
- ..fileOffset = fileOffset
- ..parent = _field;
- } else {
- _field.initializer = new NullLiteral()
- ..fileOffset = fileOffset
- ..parent = _field;
- }
- if (_lateIsSetField != null) {
- _lateIsSetField!.initializer = new BoolLiteral(false)
- ..fileOffset = fileOffset
- ..parent = _lateIsSetField;
- }
- _lateGetter.function.body = _createGetterBody(coreTypes, name, initializer)
- ..parent = _lateGetter.function;
- if (_lateSetter != null) {
- _lateSetter!.function.body = _createSetterBody(
- coreTypes, name, _lateSetter!.function.positionalParameters.first)
- ..parent = _lateSetter!.function;
- }
- }
-
- @override
- List<Initializer> createInitializer(int fileOffset, Expression value,
- {required bool isSynthetic}) {
- List<Initializer> initializers = <Initializer>[];
- if (_lateIsSetField != null) {
- initializers.add(new FieldInitializer(
- _lateIsSetField!, new BoolLiteral(true)..fileOffset = fileOffset)
- ..fileOffset = fileOffset
- ..isSynthetic = isSynthetic);
- }
- initializers.add(new FieldInitializer(_field, value)
- ..fileOffset = fileOffset
- ..isSynthetic = isSynthetic);
- return initializers;
- }
-
- /// Creates an [Expression] that reads [_field].
- ///
- /// If [needsPromotion] is `true`, the field will be read through a `let`
- /// expression that promotes the expression to [_type]. This is needed for a
- /// sound encoding of fields with type variable type of undetermined
- /// nullability.
- Expression _createFieldRead({bool needsPromotion: false}) {
- assert(_type != null, "Type has not been computed for field $name.");
- if (needsPromotion) {
- VariableDeclaration variable = new VariableDeclaration.forValue(
- _createFieldGet(_field),
- type: _type!.withDeclaredNullability(Nullability.nullable))
- ..fileOffset = fileOffset;
- return new Let(
- variable, new VariableGet(variable, _type)..fileOffset = fileOffset);
- } else {
- return _createFieldGet(_field);
- }
- }
-
- /// Creates an [Expression] that reads [field].
- Expression _createFieldGet(Field field) {
- if (field.isStatic) {
- return new StaticGet(field)..fileOffset = fileOffset;
- } else {
- // No substitution needed for the result type, since any type variables
- // in there are also in scope at the access site.
- return new InstanceGet(InstanceAccessKind.Instance,
- new ThisExpression()..fileOffset = fileOffset, field.name,
- interfaceTarget: field, resultType: field.type)
- ..fileOffset = fileOffset;
- }
- }
-
- /// Creates an [Expression] that writes [value] to [field].
- Expression _createFieldSet(Field field, Expression value) {
- if (field.isStatic) {
- return new StaticSet(field, value)..fileOffset = fileOffset;
- } else {
- return new InstanceSet(InstanceAccessKind.Instance,
- new ThisExpression()..fileOffset = fileOffset, field.name, value,
- interfaceTarget: field)
- ..fileOffset = fileOffset;
- }
- }
-
- Statement _createGetterBody(
- CoreTypes coreTypes, String name, Expression? initializer);
-
- Procedure? _createSetter(
- Name name, Uri fileUri, int charOffset, Reference? reference,
- {required bool isCovariantByDeclaration}) {
- // ignore: unnecessary_null_comparison
- assert(isCovariantByDeclaration != null);
- VariableDeclaration parameter = new VariableDeclaration(null)
- ..isCovariantByDeclaration = isCovariantByDeclaration
- ..fileOffset = fileOffset;
- return new Procedure(
- name,
- ProcedureKind.Setter,
- new FunctionNode(null,
- positionalParameters: [parameter], returnType: const VoidType())
- ..fileOffset = charOffset
- ..fileEndOffset = fileEndOffset,
- fileUri: fileUri,
- reference: reference)
- ..fileOffset = charOffset
- ..fileEndOffset = fileEndOffset
- ..isNonNullableByDefault = true;
- }
-
- Statement _createSetterBody(
- CoreTypes coreTypes, String name, VariableDeclaration parameter);
-
- @override
- DartType get type {
- assert(_type != null, "Type has not been computed for field $name.");
- return _type!;
- }
-
- @override
- void set type(DartType value) {
- assert(_type == null || _type is ImplicitFieldType,
- "Type has already been computed for field $name.");
- _type = value;
- if (value is! ImplicitFieldType) {
- _field.type = value.withDeclaredNullability(Nullability.nullable);
- _lateGetter.function.returnType = value;
- if (_lateSetter != null) {
- _lateSetter!.function.positionalParameters.single.type = value;
- }
- if (!_type!.isPotentiallyNullable && !_forceIncludeIsSetField) {
- // We only need the is-set field if the field is potentially nullable.
- // Otherwise we use `null` to signal that the field is uninitialized.
- _lateIsSetField = null;
- }
- }
- }
-
- @override
- void setGenericCovariantImpl() {
- _field.isCovariantByClass = true;
- _lateSetter?.function.positionalParameters.single.isCovariantByClass = true;
- }
-
- @override
- Field get field => _field;
-
- @override
- Iterable<Annotatable> get annotatables {
- List<Annotatable> list = [_lateGetter];
- if (_lateSetter != null) {
- list.add(_lateSetter!);
- }
- return list;
- }
-
- @override
- Member get readTarget => _lateGetter;
-
- @override
- Member? get writeTarget => _lateSetter;
-
- @override
- Iterable<Member> get exportedMembers {
- if (_lateSetter != null) {
- return [_lateGetter, _lateSetter!];
- }
- return [_lateGetter];
- }
-
- @override
- void build(
- SourceLibraryBuilder libraryBuilder, SourceFieldBuilder fieldBuilder) {
- bool isInstanceMember;
- bool isExtensionMember = fieldBuilder.isExtensionMember;
- if (isExtensionMember) {
- _field
- ..isStatic = true
- ..isExtensionMember = isExtensionMember;
- isInstanceMember = false;
- } else {
- isInstanceMember = !fieldBuilder.isStatic && !fieldBuilder.isTopLevel;
- _field
- ..isStatic = !isInstanceMember
- ..isExtensionMember = false;
- }
- updatePrivateMemberName(_field, libraryBuilder);
- if (_lateIsSetField != null) {
- _lateIsSetField!
- ..isStatic = !isInstanceMember
- ..isStatic = _field.isStatic
- ..isExtensionMember = isExtensionMember;
- updatePrivateMemberName(_lateIsSetField!, libraryBuilder);
- }
- _lateGetter
- ..isStatic = !isInstanceMember
- ..isExtensionMember = isExtensionMember;
- updatePrivateMemberName(_lateGetter, libraryBuilder);
- if (_lateSetter != null) {
- _lateSetter!
- ..isStatic = !isInstanceMember
- ..isExtensionMember = isExtensionMember;
- updatePrivateMemberName(_lateSetter!, libraryBuilder);
- }
- }
-
- @override
- void registerMembers(
- SourceLibraryBuilder library,
- SourceFieldBuilder fieldBuilder,
- void Function(Member, BuiltMemberKind) f) {
- f(
- _field,
- fieldBuilder.isExtensionMember
- ? BuiltMemberKind.ExtensionField
- : BuiltMemberKind.Field);
- if (_lateIsSetField != null) {
- _forceIncludeIsSetField = true;
- f(_lateIsSetField!, BuiltMemberKind.LateIsSetField);
- }
- f(_lateGetter, BuiltMemberKind.LateGetter);
- if (_lateSetter != null) {
- f(_lateSetter!, BuiltMemberKind.LateSetter);
- }
- }
-
- @override
- List<ClassMember> getLocalMembers(SourceFieldBuilder fieldBuilder) {
- List<ClassMember> list = <ClassMember>[
- new _SynthesizedFieldClassMember(
- fieldBuilder, field, _SynthesizedFieldMemberKind.LateField,
- isInternalImplementation: true),
- new _SynthesizedFieldClassMember(fieldBuilder, _lateGetter,
- _SynthesizedFieldMemberKind.LateGetterSetter,
- isInternalImplementation: false)
- ];
- if (_lateIsSetField != null) {
- list.add(new _SynthesizedFieldClassMember(
- fieldBuilder, _lateIsSetField!, _SynthesizedFieldMemberKind.LateIsSet,
- isInternalImplementation: true));
- }
- return list;
- }
-
- @override
- List<ClassMember> getLocalSetters(SourceFieldBuilder fieldBuilder) {
- List<ClassMember> list = <ClassMember>[
- new _SynthesizedFieldClassMember(
- fieldBuilder, field, _SynthesizedFieldMemberKind.LateField,
- forSetter: true, isInternalImplementation: true),
- ];
- if (_lateIsSetField != null) {
- list.add(new _SynthesizedFieldClassMember(
- fieldBuilder, _lateIsSetField!, _SynthesizedFieldMemberKind.LateIsSet,
- forSetter: true, isInternalImplementation: true));
- }
- if (_lateSetter != null) {
- list.add(new _SynthesizedFieldClassMember(fieldBuilder, _lateSetter!,
- _SynthesizedFieldMemberKind.LateGetterSetter,
- forSetter: true, isInternalImplementation: false));
- }
- return list;
- }
-
- @override
- bool get isLateLowering => true;
-}
-
-mixin NonFinalLate on AbstractLateFieldEncoding {
- @override
- Statement _createSetterBody(
- CoreTypes coreTypes, String name, VariableDeclaration parameter) {
- assert(_type != null, "Type has not been computed for field $name.");
- return late_lowering.createSetterBody(
- coreTypes, fileOffset, name, parameter, _type!,
- shouldReturnValue: false,
- createVariableWrite: (Expression value) =>
- _createFieldSet(_field, value),
- createIsSetWrite: (Expression value) =>
- _createFieldSet(_lateIsSetField!, value),
- isSetEncoding: isSetEncoding);
- }
-}
-
-mixin LateWithoutInitializer on AbstractLateFieldEncoding {
- @override
- Statement _createGetterBody(
- CoreTypes coreTypes, String name, Expression? initializer) {
- assert(_type != null, "Type has not been computed for field $name.");
- return late_lowering.createGetterBodyWithoutInitializer(
- coreTypes, fileOffset, name, type,
- createVariableRead: _createFieldRead,
- createIsSetRead: () => _createFieldGet(_lateIsSetField!),
- isSetEncoding: isSetEncoding,
- forField: true);
- }
-}
-
-class LateFieldWithoutInitializerEncoding extends AbstractLateFieldEncoding
- with NonFinalLate, LateWithoutInitializer {
- LateFieldWithoutInitializerEncoding(
- String name,
- NameScheme nameScheme,
- Uri fileUri,
- int charOffset,
- int charEndOffset,
- Reference? fieldReference,
- Reference? fieldGetterReference,
- Reference? fieldSetterReference,
- Reference? lateIsSetFieldReference,
- Reference? lateIsSetGetterReference,
- Reference? lateIsSetSetterReference,
- Reference? lateGetterReference,
- Reference? lateSetterReference,
- bool isCovariantByDeclaration,
- late_lowering.IsSetStrategy isSetStrategy)
- : super(
- name,
- nameScheme,
- fileUri,
- charOffset,
- charEndOffset,
- fieldReference,
- fieldGetterReference,
- fieldSetterReference,
- lateIsSetFieldReference,
- lateIsSetGetterReference,
- lateIsSetSetterReference,
- lateGetterReference,
- lateSetterReference,
- isCovariantByDeclaration,
- isSetStrategy);
-}
-
-class LateFieldWithInitializerEncoding extends AbstractLateFieldEncoding
- with NonFinalLate {
- LateFieldWithInitializerEncoding(
- String name,
- NameScheme nameScheme,
- Uri fileUri,
- int charOffset,
- int charEndOffset,
- Reference? fieldReference,
- Reference? fieldGetterReference,
- Reference? fieldSetterReference,
- Reference? lateIsSetFieldReference,
- Reference? lateIsSetGetterReference,
- Reference? lateIsSetSetterReference,
- Reference? lateGetterReference,
- Reference? lateSetterReference,
- bool isCovariantByDeclaration,
- late_lowering.IsSetStrategy isSetStrategy)
- : super(
- name,
- nameScheme,
- fileUri,
- charOffset,
- charEndOffset,
- fieldReference,
- fieldGetterReference,
- fieldSetterReference,
- lateIsSetFieldReference,
- lateIsSetGetterReference,
- lateIsSetSetterReference,
- lateGetterReference,
- lateSetterReference,
- isCovariantByDeclaration,
- isSetStrategy);
-
- @override
- Statement _createGetterBody(
- CoreTypes coreTypes, String name, Expression? initializer) {
- assert(_type != null, "Type has not been computed for field $name.");
- return late_lowering.createGetterWithInitializer(
- coreTypes, fileOffset, name, _type!, initializer!,
- createVariableRead: _createFieldRead,
- createVariableWrite: (Expression value) =>
- _createFieldSet(_field, value),
- createIsSetRead: () => _createFieldGet(_lateIsSetField!),
- createIsSetWrite: (Expression value) =>
- _createFieldSet(_lateIsSetField!, value),
- isSetEncoding: isSetEncoding);
- }
-}
-
-class LateFinalFieldWithoutInitializerEncoding extends AbstractLateFieldEncoding
- with LateWithoutInitializer {
- LateFinalFieldWithoutInitializerEncoding(
- String name,
- NameScheme nameScheme,
- Uri fileUri,
- int charOffset,
- int charEndOffset,
- Reference? fieldReference,
- Reference? fieldGetterReference,
- Reference? fieldSetterReference,
- Reference? lateIsSetFieldReference,
- Reference? lateIsSetGetterReference,
- Reference? lateIsSetSetterReference,
- Reference? lateGetterReference,
- Reference? lateSetterReference,
- bool isCovariantByDeclaration,
- late_lowering.IsSetStrategy isSetStrategy)
- : super(
- name,
- nameScheme,
- fileUri,
- charOffset,
- charEndOffset,
- fieldReference,
- fieldGetterReference,
- fieldSetterReference,
- lateIsSetFieldReference,
- lateIsSetGetterReference,
- lateIsSetSetterReference,
- lateGetterReference,
- lateSetterReference,
- isCovariantByDeclaration,
- isSetStrategy);
-
- @override
- Statement _createSetterBody(
- CoreTypes coreTypes, String name, VariableDeclaration parameter) {
- assert(_type != null, "Type has not been computed for field $name.");
- return late_lowering.createSetterBodyFinal(
- coreTypes, fileOffset, name, parameter, type,
- shouldReturnValue: false,
- createVariableRead: () => _createFieldGet(_field),
- createVariableWrite: (Expression value) =>
- _createFieldSet(_field, value),
- createIsSetRead: () => _createFieldGet(_lateIsSetField!),
- createIsSetWrite: (Expression value) =>
- _createFieldSet(_lateIsSetField!, value),
- isSetEncoding: isSetEncoding,
- forField: true);
- }
-}
-
-class LateFinalFieldWithInitializerEncoding extends AbstractLateFieldEncoding {
- LateFinalFieldWithInitializerEncoding(
- String name,
- NameScheme nameScheme,
- Uri fileUri,
- int charOffset,
- int charEndOffset,
- Reference? fieldReference,
- Reference? fieldGetterReference,
- Reference? fieldSetterReference,
- Reference? lateIsSetFieldReference,
- Reference? lateIsSetGetterReference,
- Reference? lateIsSetSetterReference,
- Reference? lateGetterReference,
- Reference? lateSetterReference,
- bool isCovariantByDeclaration,
- late_lowering.IsSetStrategy isSetStrategy)
- : super(
- name,
- nameScheme,
- fileUri,
- charOffset,
- charEndOffset,
- fieldReference,
- fieldGetterReference,
- fieldSetterReference,
- lateIsSetFieldReference,
- lateIsSetGetterReference,
- lateIsSetSetterReference,
- lateGetterReference,
- lateSetterReference,
- isCovariantByDeclaration,
- isSetStrategy);
- @override
- Statement _createGetterBody(
- CoreTypes coreTypes, String name, Expression? initializer) {
- assert(_type != null, "Type has not been computed for field $name.");
- return late_lowering.createGetterWithInitializerWithRecheck(
- coreTypes, fileOffset, name, _type!, initializer!,
- createVariableRead: _createFieldRead,
- createVariableWrite: (Expression value) =>
- _createFieldSet(_field, value),
- createIsSetRead: () => _createFieldGet(_lateIsSetField!),
- createIsSetWrite: (Expression value) =>
- _createFieldSet(_lateIsSetField!, value),
- isSetEncoding: isSetEncoding,
- forField: true);
- }
-
- @override
- Procedure? _createSetter(
- Name name, Uri fileUri, int charOffset, Reference? reference,
- {required bool isCovariantByDeclaration}) =>
- null;
-
- @override
- Statement _createSetterBody(
- CoreTypes coreTypes, String name, VariableDeclaration parameter) =>
- throw new UnsupportedError(
- '$runtimeType._createSetterBody is not supported.');
-}
-
-class _SynthesizedFieldClassMember implements ClassMember {
- final SourceFieldBuilder fieldBuilder;
- final _SynthesizedFieldMemberKind _kind;
-
- final Member _member;
-
- Covariance? _covariance;
-
- @override
- final bool forSetter;
-
- @override
- final bool isInternalImplementation;
-
- _SynthesizedFieldClassMember(this.fieldBuilder, this._member, this._kind,
- {this.forSetter: false, required this.isInternalImplementation})
- // ignore: unnecessary_null_comparison
- : assert(isInternalImplementation != null);
-
- @override
- Member getMember(ClassMembersBuilder membersBuilder) {
- fieldBuilder._ensureType(membersBuilder);
- return _member;
- }
-
- @override
- Covariance getCovariance(ClassMembersBuilder membersBuilder) {
- return _covariance ??= new Covariance.fromMember(getMember(membersBuilder),
- forSetter: forSetter);
- }
-
- @override
- void inferType(ClassMembersBuilder membersBuilder) {
- fieldBuilder._ensureType(membersBuilder);
- }
-
- @override
- void registerOverrideDependency(Set<ClassMember> overriddenMembers) {
- fieldBuilder.registerOverrideDependency(overriddenMembers);
- }
-
- @override
- bool get isSourceDeclaration => true;
-
- @override
- bool get isProperty => isField || isGetter || isSetter;
-
- @override
- ClassBuilder get classBuilder => fieldBuilder.classBuilder!;
-
- @override
- bool isObjectMember(ClassBuilder objectClass) {
- return classBuilder == objectClass;
- }
-
- @override
- bool get isDuplicate => fieldBuilder.isDuplicate;
-
- @override
- bool get isStatic => fieldBuilder.isStatic;
-
- @override
- bool get isField => _member is Field;
-
- @override
- bool get isAssignable {
- Member field = _member;
- return field is Field && field.hasSetter;
- }
-
- @override
- bool get isSetter {
- Member procedure = _member;
- return procedure is Procedure && procedure.kind == ProcedureKind.Setter;
- }
-
- @override
- bool get isGetter {
- Member procedure = _member;
- return procedure is Procedure && procedure.kind == ProcedureKind.Getter;
- }
-
- @override
- bool get isFinal {
- Member field = _member;
- return field is Field && field.isFinal;
- }
-
- @override
- bool get isConst {
- Member field = _member;
- return field is Field && field.isConst;
- }
-
- @override
- Name get name => _member.name;
-
- @override
- String get fullName {
- String suffix = isSetter ? "=" : "";
- String className = classBuilder.fullNameForErrors;
- // ignore: unnecessary_null_comparison
- return className == null
- ? "${fullNameForErrors}$suffix"
- : "${className}.${fullNameForErrors}$suffix";
- }
-
- @override
- String get fullNameForErrors => fieldBuilder.fullNameForErrors;
-
- @override
- Uri get fileUri => fieldBuilder.fileUri;
-
- @override
- int get charOffset => fieldBuilder.charOffset;
-
- @override
- bool get isAbstract => _member.isAbstract;
-
- @override
- bool get isSynthesized => false;
-
- @override
- bool get hasDeclarations => false;
-
- @override
- List<ClassMember> get declarations =>
- throw new UnsupportedError("$runtimeType.declarations");
-
- @override
- ClassMember get interfaceMember => this;
-
- @override
- bool isSameDeclaration(ClassMember other) {
- if (identical(this, other)) return true;
- return other is _SynthesizedFieldClassMember &&
- fieldBuilder == other.fieldBuilder &&
- _kind == other._kind;
- }
-
- @override
- String toString() => '_SynthesizedFieldClassMember('
- '$fieldBuilder,$_member,$_kind,forSetter=${forSetter})';
-}
-
-class AbstractOrExternalFieldEncoding implements FieldEncoding {
- final SourceFieldBuilder _fieldBuilder;
- final bool isAbstract;
- final bool isExternal;
- final bool _isExtensionInstanceMember;
-
- late Procedure _getter;
- Procedure? _setter;
- DartType? _type;
-
- AbstractOrExternalFieldEncoding(
- this._fieldBuilder,
- String name,
- NameScheme nameScheme,
- Uri fileUri,
- int charOffset,
- int charEndOffset,
- Reference? getterReference,
- Reference? setterReference,
- {required this.isAbstract,
- required this.isExternal,
- required bool isFinal,
- required bool isCovariantByDeclaration,
- required bool isNonNullableByDefault})
- // ignore: unnecessary_null_comparison
- : assert(isAbstract != null),
- // ignore: unnecessary_null_comparison
- assert(isExternal != null),
- // ignore: unnecessary_null_comparison
- assert(isFinal != null),
- // ignore: unnecessary_null_comparison
- assert(isCovariantByDeclaration != null),
- // ignore: unnecessary_null_comparison
- assert(isNonNullableByDefault != null),
- _isExtensionInstanceMember = isExternal &&
- nameScheme.isExtensionMember &&
- nameScheme.isInstanceMember {
- if (_isExtensionInstanceMember) {
- _getter = new Procedure(
- nameScheme.getProcedureName(ProcedureKind.Getter, name),
- ProcedureKind.Method,
- new FunctionNode(null, positionalParameters: [
- new VariableDeclaration(extensionThisName)..fileOffset
- ]),
- fileUri: fileUri,
- reference: getterReference)
- ..fileOffset = charOffset
- ..fileEndOffset = charEndOffset
- ..isNonNullableByDefault = isNonNullableByDefault;
- if (!isFinal) {
- VariableDeclaration parameter =
- new VariableDeclaration("#externalFieldValue")
- ..isCovariantByDeclaration = isCovariantByDeclaration
- ..fileOffset = charOffset;
- _setter = new Procedure(
- nameScheme.getProcedureName(ProcedureKind.Setter, name),
- ProcedureKind.Method,
- new FunctionNode(null,
- positionalParameters: [
- new VariableDeclaration(extensionThisName)..fileOffset,
- parameter
- ],
- returnType: const VoidType())
- ..fileOffset = charOffset
- ..fileEndOffset = charEndOffset,
- fileUri: fileUri,
- reference: setterReference)
- ..fileOffset = charOffset
- ..fileEndOffset = charEndOffset
- ..isNonNullableByDefault = isNonNullableByDefault;
- }
- } else {
- _getter = new Procedure(
- nameScheme.getFieldName(FieldNameType.Getter, name,
- isSynthesized: true),
- ProcedureKind.Getter,
- new FunctionNode(null),
- fileUri: fileUri,
- reference: getterReference)
- ..fileOffset = charOffset
- ..fileEndOffset = charEndOffset
- ..isNonNullableByDefault = isNonNullableByDefault;
- if (!isFinal) {
- VariableDeclaration parameter =
- new VariableDeclaration("#externalFieldValue")
- ..isCovariantByDeclaration = isCovariantByDeclaration
- ..fileOffset = charOffset;
- _setter = new Procedure(
- nameScheme.getFieldName(FieldNameType.Setter, name,
- isSynthesized: true),
- ProcedureKind.Setter,
- new FunctionNode(null,
- positionalParameters: [parameter], returnType: const VoidType())
- ..fileOffset = charOffset
- ..fileEndOffset = charEndOffset,
- fileUri: fileUri,
- reference: setterReference)
- ..fileOffset = charOffset
- ..fileEndOffset = charEndOffset
- ..isNonNullableByDefault = isNonNullableByDefault;
- }
- }
- }
-
- @override
- DartType get type {
- assert(_type != null,
- "Type has not been computed for field ${_fieldBuilder.name}.");
- return _type!;
- }
-
- @override
- void set type(DartType value) {
- assert(_type == null || _type is ImplicitFieldType,
- "Type has already been computed for field ${_fieldBuilder.name}.");
- _type = value;
- if (value is! ImplicitFieldType) {
- if (_isExtensionInstanceMember) {
- SourceExtensionBuilder extensionBuilder =
- _fieldBuilder.parent as SourceExtensionBuilder;
- DartType onType = extensionBuilder.extension.onType;
- List<TypeParameter> typeParameters =
- extensionBuilder.extension.typeParameters;
- if (typeParameters.isNotEmpty) {
- FreshTypeParameters getterTypeParameters =
- getFreshTypeParameters(typeParameters);
- _getter.function.positionalParameters.first.type =
- getterTypeParameters.substitute(onType);
- _getter.function.returnType = getterTypeParameters.substitute(value);
- _getter.function.typeParameters =
- getterTypeParameters.freshTypeParameters;
- setParents(
- getterTypeParameters.freshTypeParameters, _getter.function);
-
- Procedure? setter = _setter;
- if (setter != null) {
- FreshTypeParameters setterTypeParameters =
- getFreshTypeParameters(typeParameters);
- setter.function.positionalParameters.first.type =
- setterTypeParameters.substitute(onType);
- setter.function.positionalParameters[1].type =
- setterTypeParameters.substitute(value);
- setter.function.typeParameters =
- setterTypeParameters.freshTypeParameters;
- setParents(
- setterTypeParameters.freshTypeParameters, setter.function);
- }
- } else {
- _getter.function.returnType = value;
- _setter?.function.positionalParameters[1].type = value;
- _getter.function.positionalParameters.first.type = onType;
- _setter?.function.positionalParameters.first.type = onType;
- }
- } else {
- _getter.function.returnType = value;
- Procedure? setter = _setter;
- if (setter != null) {
- if (setter.kind == ProcedureKind.Method) {
- setter.function.positionalParameters[1].type = value;
- } else {
- setter.function.positionalParameters.first.type = value;
- }
- }
- }
- }
- }
-
- @override
- void completeSignature(CoreTypes coreTypes) {}
-
- @override
- void createBodies(CoreTypes coreTypes, Expression? initializer) {
- //assert(initializer != null);
- }
-
- @override
- List<Initializer> createInitializer(int fileOffset, Expression value,
- {required bool isSynthetic}) {
- throw new UnsupportedError('ExternalFieldEncoding.createInitializer');
- }
-
- @override
- void build(
- SourceLibraryBuilder libraryBuilder, SourceFieldBuilder fieldBuilder) {
- bool isExtensionMember = fieldBuilder.isExtensionMember;
- bool isInstanceMember = !fieldBuilder.isExtensionMember &&
- !fieldBuilder.isStatic &&
- !fieldBuilder.isTopLevel;
- _getter..isConst = fieldBuilder.isConst;
- _getter
- ..isStatic = !isInstanceMember
- ..isExtensionMember = isExtensionMember
- ..isAbstract = isAbstract && !isExternal
- ..isExternal = isExternal;
- updatePrivateMemberName(_getter, libraryBuilder);
-
- if (_setter != null) {
- _setter!
- ..isStatic = !isInstanceMember
- ..isExtensionMember = isExtensionMember
- ..isAbstract = isAbstract && !isExternal
- ..isExternal = isExternal;
- updatePrivateMemberName(_setter!, libraryBuilder);
- }
- }
-
- @override
- void registerMembers(
- SourceLibraryBuilder library,
- SourceFieldBuilder fieldBuilder,
- void Function(Member, BuiltMemberKind) f) {
- f(
- _getter,
- fieldBuilder.isExtensionMember
- ? BuiltMemberKind.ExtensionGetter
- : BuiltMemberKind.Method);
- if (_setter != null) {
- f(
- _setter!,
- fieldBuilder.isExtensionMember
- ? BuiltMemberKind.ExtensionSetter
- : BuiltMemberKind.Method);
- }
- }
-
- @override
- void setGenericCovariantImpl() {
- _setter!.function.positionalParameters.first.isCovariantByClass = true;
- }
-
- @override
- Field get field {
- throw new UnsupportedError("ExternalFieldEncoding.field");
- }
-
- @override
- Iterable<Annotatable> get annotatables {
- List<Annotatable> list = [_getter];
- if (_setter != null) {
- list.add(_setter!);
- }
- return list;
- }
-
- @override
- Member get readTarget => _getter;
-
- @override
- Member? get writeTarget => _setter;
-
- @override
- Iterable<Member> get exportedMembers {
- if (_setter != null) {
- return [_getter, _setter!];
- }
- return [_getter];
- }
-
- @override
- List<ClassMember> getLocalMembers(SourceFieldBuilder fieldBuilder) =>
- <ClassMember>[
- new _SynthesizedFieldClassMember(fieldBuilder, _getter,
- _SynthesizedFieldMemberKind.AbstractExternalGetterSetter,
- forSetter: false, isInternalImplementation: false)
- ];
-
- @override
- List<ClassMember> getLocalSetters(SourceFieldBuilder fieldBuilder) =>
- _setter != null
- ? <ClassMember>[
- new _SynthesizedFieldClassMember(fieldBuilder, _setter!,
- _SynthesizedFieldMemberKind.AbstractExternalGetterSetter,
- forSetter: true, isInternalImplementation: false)
- ]
- : const <ClassMember>[];
-
- @override
- bool get isLateLowering => false;
-}
-
-enum _SynthesizedFieldMemberKind {
- /// A `isSet` field used for late lowering.
- LateIsSet,
-
- /// A field used for the value of a late lowered field.
- LateField,
-
- /// A getter or setter used for late lowering.
- LateGetterSetter,
-
- /// A getter or setter used for abstract or external fields.
- AbstractExternalGetterSetter,
-}
diff --git a/pkg/front_end/lib/src/fasta/builder/formal_parameter_builder.dart b/pkg/front_end/lib/src/fasta/builder/formal_parameter_builder.dart
index 5c954d0..1503956 100644
--- a/pkg/front_end/lib/src/fasta/builder/formal_parameter_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/formal_parameter_builder.dart
@@ -9,35 +9,24 @@
isMandatoryFormalParameterKind,
isOptionalNamedFormalParameterKind,
isOptionalPositionalFormalParameterKind;
-
import 'package:_fe_analyzer_shared/src/parser/parser.dart'
show FormalParameterKind;
-
import 'package:_fe_analyzer_shared/src/scanner/scanner.dart' show Token;
-
import 'package:kernel/ast.dart'
show DartType, DynamicType, Expression, VariableDeclaration;
-
import 'package:kernel/src/legacy_erasure.dart';
import '../constant_context.dart' show ConstantContext;
-
-import '../modifier.dart';
-
-import '../scope.dart' show Scope;
-
-import '../source/source_library_builder.dart';
-
import '../kernel/body_builder.dart' show BodyBuilder;
-
import '../kernel/internal_ast.dart' show VariableDeclarationImpl;
-
+import '../modifier.dart';
+import '../scope.dart' show Scope;
+import '../source/source_factory_builder.dart';
+import '../source/source_library_builder.dart';
import '../util/helpers.dart' show DelayedActionPerformer;
-
import 'builder.dart';
import 'class_builder.dart';
import 'constructor_builder.dart';
-import 'factory_builder.dart';
import 'field_builder.dart';
import 'library_builder.dart';
import 'metadata_builder.dart';
diff --git a/pkg/front_end/lib/src/fasta/builder/function_builder.dart b/pkg/front_end/lib/src/fasta/builder/function_builder.dart
index 1390968..820d4bb 100644
--- a/pkg/front_end/lib/src/fasta/builder/function_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/function_builder.dart
@@ -5,522 +5,10 @@
library fasta.procedure_builder;
import 'package:kernel/ast.dart';
-import 'package:kernel/class_hierarchy.dart';
-import '../identifiers.dart';
-import '../scope.dart';
-
-import '../kernel/internal_ast.dart' show VariableDeclarationImpl;
-import '../kernel/kernel_helper.dart';
-
-import '../source/source_loader.dart' show SourceLoader;
-
-import '../messages.dart'
- show
- messagePatchDeclarationMismatch,
- messagePatchDeclarationOrigin,
- messagePatchNonExternal,
- noLength,
- templateRequiredNamedParameterHasDefaultValueError;
-
-import '../modifier.dart';
-
-import '../source/source_library_builder.dart' show SourceLibraryBuilder;
-
-import '../type_inference/type_inference_engine.dart'
- show IncludesTypeParametersNonCovariantly;
-
-import '../util/helpers.dart' show DelayedActionPerformer;
-
-import 'builder.dart';
-import 'class_builder.dart';
-import 'declaration_builder.dart';
-import 'extension_builder.dart';
-import 'formal_parameter_builder.dart';
-import 'library_builder.dart';
import 'member_builder.dart';
-import 'metadata_builder.dart';
-import 'type_builder.dart';
-import 'type_variable_builder.dart';
/// Common base class for constructor and procedure builders.
abstract class FunctionBuilder implements MemberBuilder {
FunctionNode get function;
}
-
-abstract class SourceFunctionBuilder
- implements FunctionBuilder, SourceMemberBuilder {
- List<MetadataBuilder>? get metadata;
-
- TypeBuilder? get returnType;
-
- List<TypeVariableBuilder>? get typeVariables;
-
- List<FormalParameterBuilder>? get formals;
-
- AsyncMarker get asyncModifier;
-
- @override
- ProcedureKind? get kind;
-
- @override
- bool get isAbstract;
-
- @override
- bool get isConstructor;
-
- @override
- bool get isRegularMethod;
-
- @override
- bool get isGetter;
-
- @override
- bool get isSetter;
-
- @override
- bool get isOperator;
-
- @override
- bool get isFactory;
-
- /// This is the formal parameter scope as specified in the Dart Programming
- /// Language Specification, 4th ed, section 9.2.
- Scope computeFormalParameterScope(Scope parent);
-
- Scope computeFormalParameterInitializerScope(Scope parent);
-
- /// This scope doesn't correspond to any scope specified in the Dart
- /// Programming Language Specification, 4th ed. It's an unspecified extension
- /// to support generic methods.
- Scope computeTypeParameterScope(Scope parent);
-
- FormalParameterBuilder? getFormal(Identifier identifier);
-
- String? get nativeMethodName;
-
- Statement? get body;
-
- void set body(Statement? newBody);
-
- @override
- bool get isNative;
-
- /// Returns the [index]th parameter of this function.
- ///
- /// The index is the syntactical index, including both positional and named
- /// parameter in the order they are declared, and excluding the synthesized
- /// this parameter on extension instance members.
- VariableDeclaration getFormalParameter(int index);
-
- /// If this is an extension instance method or constructor with lowering
- /// enabled, the tear off parameter corresponding to the [index]th parameter
- /// on the instance method or constructor is returned.
- ///
- /// This is used to update the default value for the closure parameter when
- /// it has been computed for the original parameter.
- VariableDeclaration? getTearOffParameter(int index);
-
- /// Returns the parameter for 'this' synthetically added to extension
- /// instance members.
- VariableDeclaration? get extensionThis;
-
- /// Returns a list of synthetic type parameters added to extension instance
- /// members.
- List<TypeParameter>? get extensionTypeParameters;
-
- void becomeNative(SourceLoader loader);
-
- bool checkPatch(FunctionBuilder patch);
-
- void reportPatchMismatch(Builder patch);
-}
-
-/// Common base class for constructor and procedure builders.
-abstract class FunctionBuilderImpl extends SourceMemberBuilderImpl
- implements SourceFunctionBuilder {
- @override
- final List<MetadataBuilder>? metadata;
-
- @override
- final int modifiers;
-
- @override
- final TypeBuilder? returnType;
-
- @override
- final String name;
-
- @override
- final List<TypeVariableBuilder>? typeVariables;
-
- @override
- final List<FormalParameterBuilder>? formals;
-
- /// If this procedure is an extension instance member, [_extensionThis] holds
- /// the synthetically added `this` parameter.
- VariableDeclaration? _extensionThis;
-
- /// If this procedure is an extension instance member,
- /// [_extensionTypeParameters] holds the type parameters copied from the
- /// extension declaration.
- List<TypeParameter>? _extensionTypeParameters;
-
- FunctionBuilderImpl(
- this.metadata,
- this.modifiers,
- this.returnType,
- this.name,
- this.typeVariables,
- this.formals,
- LibraryBuilder compilationUnit,
- int charOffset,
- this.nativeMethodName)
- : super(compilationUnit, charOffset) {
- if (formals != null) {
- for (int i = 0; i < formals!.length; i++) {
- formals![i].parent = this;
- }
- }
- }
-
- @override
- String get debugName => "FunctionBuilder";
-
- @override
- AsyncMarker get asyncModifier;
-
- @override
- bool get isConstructor => false;
-
- @override
- bool get isAbstract => (modifiers & abstractMask) != 0;
-
- @override
- bool get isRegularMethod => identical(ProcedureKind.Method, kind);
-
- @override
- bool get isGetter => identical(ProcedureKind.Getter, kind);
-
- @override
- bool get isSetter => identical(ProcedureKind.Setter, kind);
-
- @override
- bool get isOperator => identical(ProcedureKind.Operator, kind);
-
- @override
- bool get isFactory => identical(ProcedureKind.Factory, kind);
-
- @override
- bool get isExternal => (modifiers & externalMask) != 0;
-
- @override
- bool get isAssignable => false;
-
- @override
- Scope computeFormalParameterScope(Scope parent) {
- if (formals == null) return parent;
- Map<String, Builder> local = <String, Builder>{};
- for (FormalParameterBuilder formal in formals!) {
- if (!isConstructor ||
- !formal.isInitializingFormal && !formal.isSuperInitializingFormal) {
- local[formal.name] = formal;
- }
- }
- return new Scope(
- local: local,
- parent: parent,
- debugName: "formal parameter",
- isModifiable: false);
- }
-
- @override
- Scope computeFormalParameterInitializerScope(Scope parent) {
- // From
- // [dartLangSpec.tex](../../../../../../docs/language/dartLangSpec.tex) at
- // revision 94b23d3b125e9d246e07a2b43b61740759a0dace:
- //
- // When the formal parameter list of a non-redirecting generative
- // constructor contains any initializing formals, a new scope is
- // introduced, the _formal parameter initializer scope_, which is the
- // current scope of the initializer list of the constructor, and which is
- // enclosed in the scope where the constructor is declared. Each
- // initializing formal in the formal parameter list introduces a final
- // local variable into the formal parameter initializer scope, but not into
- // the formal parameter scope; every other formal parameter introduces a
- // local variable into both the formal parameter scope and the formal
- // parameter initializer scope.
-
- if (formals == null) return parent;
- Map<String, Builder> local = <String, Builder>{};
- for (FormalParameterBuilder formal in formals!) {
- local[formal.name] = formal.forFormalParameterInitializerScope();
- }
- return new Scope(
- local: local,
- parent: parent,
- debugName: "formal parameter initializer",
- isModifiable: false);
- }
-
- @override
- Scope computeTypeParameterScope(Scope parent) {
- if (typeVariables == null) return parent;
- Map<String, Builder> local = <String, Builder>{};
- for (TypeVariableBuilder variable in typeVariables!) {
- local[variable.name] = variable;
- }
- return new Scope(
- local: local,
- parent: parent,
- debugName: "type parameter",
- isModifiable: false);
- }
-
- @override
- FormalParameterBuilder? getFormal(Identifier identifier) {
- if (formals != null) {
- for (FormalParameterBuilder formal in formals!) {
- if (formal.name == identifier.name &&
- formal.charOffset == identifier.charOffset) {
- return formal;
- }
- }
- // If we have any formals we should find the one we're looking for.
- assert(false, "$identifier not found in $formals");
- }
- return null;
- }
-
- @override
- final String? nativeMethodName;
-
- Statement? bodyInternal;
-
- @override
- void set body(Statement? newBody) {
-// if (newBody != null) {
-// if (isAbstract) {
-// // TODO(danrubel): Is this check needed?
-// return internalProblem(messageInternalProblemBodyOnAbstractMethod,
-// newBody.fileOffset, fileUri);
-// }
-// }
- bodyInternal = newBody;
- // A forwarding semi-stub is a method that is abstract in the source code,
- // but which needs to have a forwarding stub body in order to ensure that
- // covariance checks occur. We don't want to replace the forwarding stub
- // body with null.
- TreeNode? parent = function.parent;
- if (!(newBody == null &&
- parent is Procedure &&
- parent.isForwardingSemiStub)) {
- function.body = newBody;
- newBody?.parent = function;
- }
- }
-
- @override
- Statement? get body => bodyInternal ??= new EmptyStatement();
-
- @override
- bool get isNative => nativeMethodName != null;
-
- void buildFunction(SourceLibraryBuilder library) {
- function.asyncMarker = asyncModifier;
- function.body = body;
- body?.parent = function;
- IncludesTypeParametersNonCovariantly? needsCheckVisitor;
- if (!isConstructor && !isFactory && parent is ClassBuilder) {
- Class enclosingClass = classBuilder!.cls;
- if (enclosingClass.typeParameters.isNotEmpty) {
- needsCheckVisitor = new IncludesTypeParametersNonCovariantly(
- enclosingClass.typeParameters,
- // We are checking the parameter types which are in a
- // contravariant position.
- initialVariance: Variance.contravariant);
- }
- }
- if (typeVariables != null) {
- for (TypeVariableBuilder t in typeVariables!) {
- TypeParameter parameter = t.parameter;
- function.typeParameters.add(parameter);
- if (needsCheckVisitor != null) {
- if (parameter.bound.accept(needsCheckVisitor)) {
- parameter.isCovariantByClass = true;
- }
- }
- }
- setParents(function.typeParameters, function);
- }
- if (formals != null) {
- for (FormalParameterBuilder formal in formals!) {
- VariableDeclaration parameter = formal.build(library, 0);
- if (needsCheckVisitor != null) {
- if (parameter.type.accept(needsCheckVisitor)) {
- parameter.isCovariantByClass = true;
- }
- }
- if (formal.isNamed) {
- function.namedParameters.add(parameter);
- } else {
- function.positionalParameters.add(parameter);
- }
- parameter.parent = function;
- if (formal.isRequired) {
- function.requiredParameterCount++;
- }
-
- if (library.isNonNullableByDefault) {
- // Required named parameters can't have default values.
- if (formal.isNamedRequired && formal.initializerToken != null) {
- library.addProblem(
- templateRequiredNamedParameterHasDefaultValueError
- .withArguments(formal.name),
- formal.charOffset,
- formal.name.length,
- formal.fileUri);
- }
- }
- }
- }
- if (!isExtensionInstanceMember &&
- isSetter &&
- (formals?.length != 1 || formals![0].isOptional)) {
- // Replace illegal parameters by single dummy parameter.
- // Do this after building the parameters, since the diet listener
- // assumes that parameters are built, even if illegal in number.
- VariableDeclaration parameter =
- new VariableDeclarationImpl("#synthetic", 0);
- function.positionalParameters.clear();
- function.positionalParameters.add(parameter);
- parameter.parent = function;
- function.namedParameters.clear();
- function.requiredParameterCount = 1;
- }
- if (returnType != null) {
- function.returnType = returnType!.build(library);
- }
- if (isExtensionInstanceMember) {
- ExtensionBuilder extensionBuilder = parent as ExtensionBuilder;
- _extensionThis = function.positionalParameters.first;
- if (extensionBuilder.typeParameters != null) {
- int count = extensionBuilder.typeParameters!.length;
- _extensionTypeParameters = new List<TypeParameter>.generate(
- count, (int index) => function.typeParameters[index],
- growable: false);
- }
- }
- }
-
- @override
- VariableDeclaration getFormalParameter(int index) {
- if (isExtensionInstanceMember) {
- return formals![index + 1].variable!;
- } else {
- return formals![index].variable!;
- }
- }
-
- @override
- VariableDeclaration? getTearOffParameter(int index) => null;
-
- @override
- VariableDeclaration? get extensionThis {
- assert(_extensionThis != null || !isExtensionInstanceMember,
- "ProcedureBuilder.extensionThis has not been set.");
- return _extensionThis;
- }
-
- @override
- List<TypeParameter>? get extensionTypeParameters {
- // Use [_extensionThis] as marker for whether extension type parameters have
- // been computed.
- assert(_extensionThis != null || !isExtensionInstanceMember,
- "ProcedureBuilder.extensionTypeParameters has not been set.");
- return _extensionTypeParameters;
- }
-
- bool _hasBuiltOutlineExpressions = false;
-
- @override
- void buildOutlineExpressions(
- SourceLibraryBuilder library,
- ClassHierarchy classHierarchy,
- List<DelayedActionPerformer> delayedActionPerformers,
- List<SynthesizedFunctionNode> synthesizedFunctionNodes) {
- if (!_hasBuiltOutlineExpressions) {
- DeclarationBuilder? classOrExtensionBuilder =
- isClassMember || isExtensionMember
- ? parent as DeclarationBuilder
- : null;
- Scope parentScope = classOrExtensionBuilder?.scope ?? library.scope;
- MetadataBuilder.buildAnnotations(member, metadata, library,
- classOrExtensionBuilder, this, fileUri, parentScope);
- if (typeVariables != null) {
- for (int i = 0; i < typeVariables!.length; i++) {
- typeVariables![i].buildOutlineExpressions(
- library,
- classOrExtensionBuilder,
- this,
- classHierarchy,
- delayedActionPerformers,
- computeTypeParameterScope(parentScope));
- }
- }
-
- if (formals != null) {
- // For const constructors we need to include default parameter values
- // into the outline. For all other formals we need to call
- // buildOutlineExpressions to clear initializerToken to prevent
- // consuming too much memory.
- for (FormalParameterBuilder formal in formals!) {
- formal.buildOutlineExpressions(library, delayedActionPerformers);
- }
- }
- _hasBuiltOutlineExpressions = true;
- }
- }
-
- Member build(SourceLibraryBuilder library);
-
- @override
- void becomeNative(SourceLoader loader) {
- MemberBuilder constructor = loader.getNativeAnnotation();
- Arguments arguments =
- new Arguments(<Expression>[new StringLiteral(nativeMethodName!)]);
- Expression annotation;
- if (constructor.isConstructor) {
- annotation = new ConstructorInvocation(
- constructor.member as Constructor, arguments)
- ..isConst = true;
- } else {
- annotation =
- new StaticInvocation(constructor.member as Procedure, arguments)
- ..isConst = true;
- }
- member.addAnnotation(annotation);
- }
-
- @override
- bool checkPatch(FunctionBuilder patch) {
- if (!isExternal) {
- patch.library.addProblem(
- messagePatchNonExternal, patch.charOffset, noLength, patch.fileUri!,
- context: [
- messagePatchDeclarationOrigin.withLocation(
- fileUri, charOffset, noLength)
- ]);
- return false;
- }
- return true;
- }
-
- @override
- void reportPatchMismatch(Builder patch) {
- library.addProblem(messagePatchDeclarationMismatch, patch.charOffset,
- noLength, patch.fileUri!, context: [
- messagePatchDeclarationOrigin.withLocation(fileUri, charOffset, noLength)
- ]);
- }
-}
diff --git a/pkg/front_end/lib/src/fasta/builder/member_builder.dart b/pkg/front_end/lib/src/fasta/builder/member_builder.dart
index 954097a..719b64d 100644
--- a/pkg/front_end/lib/src/fasta/builder/member_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/member_builder.dart
@@ -5,19 +5,9 @@
library fasta.member_builder;
import 'package:kernel/ast.dart';
-import 'package:kernel/class_hierarchy.dart';
-
-import '../../base/common.dart';
import '../kernel/hierarchy/class_member.dart';
-import '../kernel/kernel_helper.dart';
import '../modifier.dart';
-import '../problems.dart' show unsupported;
-import '../source/source_library_builder.dart';
-import '../type_inference/type_inference_engine.dart'
- show InferenceDataForTesting;
-import '../util/helpers.dart' show DelayedActionPerformer;
-
import 'builder.dart';
import 'class_builder.dart';
import 'declaration_builder.dart';
@@ -165,105 +155,6 @@
String get fullNameForErrors => name;
}
-abstract class SourceMemberBuilder implements MemberBuilder {
- MemberDataForTesting? get dataForTesting;
-
- /// Builds the core AST structures for this member as needed for the outline.
- void buildMembers(
- SourceLibraryBuilder library, void Function(Member, BuiltMemberKind) f);
-
- void buildOutlineExpressions(
- SourceLibraryBuilder library,
- ClassHierarchy classHierarchy,
- List<DelayedActionPerformer> delayedActionPerformers,
- List<SynthesizedFunctionNode> synthesizedFunctionNodes);
-}
-
-mixin SourceMemberBuilderMixin implements SourceMemberBuilder {
- @override
- MemberDataForTesting? dataForTesting =
- retainDataForTesting ? new MemberDataForTesting() : null;
-
- @override
- void buildMembers(
- SourceLibraryBuilder library, void Function(Member, BuiltMemberKind) f) {
- assert(false, "Unexpected call to $runtimeType.buildMembers.");
- }
-}
-
-abstract class SourceMemberBuilderImpl extends MemberBuilderImpl
- implements SourceMemberBuilder {
- @override
- MemberDataForTesting? dataForTesting;
-
- SourceMemberBuilderImpl(Builder parent, int charOffset, [Uri? fileUri])
- : dataForTesting =
- retainDataForTesting ? new MemberDataForTesting() : null,
- super(parent, charOffset, fileUri);
-
- bool get isRedirectingGenerativeConstructor => false;
-
- bool? _isConflictingSetter;
-
- @override
- bool get isConflictingSetter {
- return _isConflictingSetter ??= false;
- }
-
- void set isConflictingSetter(bool value) {
- assert(_isConflictingSetter == null,
- '$this.isConflictingSetter has already been fixed.');
- _isConflictingSetter = value;
- }
-
- // TODO(johnniwinther): Remove this and create a [ProcedureBuilder] interface.
- @override
- ProcedureKind? get kind => unsupported("kind", charOffset, fileUri);
-
- @override
- void buildOutlineExpressions(
- SourceLibraryBuilder library,
- ClassHierarchy classHierarchy,
- List<DelayedActionPerformer> delayedActionPerformers,
- List<SynthesizedFunctionNode> synthesizedFunctionNodes) {}
-
- @override
- StringBuffer printOn(StringBuffer buffer) {
- if (isClassMember) {
- buffer.write(classBuilder!.name);
- buffer.write('.');
- }
- buffer.write(name);
- return buffer;
- }
-
- /// The builder for the enclosing class or extension, if any.
- DeclarationBuilder? get declarationBuilder =>
- parent is DeclarationBuilder ? parent as DeclarationBuilder : null;
-}
-
-enum BuiltMemberKind {
- Constructor,
- RedirectingFactory,
- Field,
- Method,
- ExtensionField,
- ExtensionMethod,
- ExtensionGetter,
- ExtensionSetter,
- ExtensionOperator,
- ExtensionTearOff,
- LateIsSetField,
- LateGetter,
- LateSetter,
-}
-
-class MemberDataForTesting {
- final InferenceDataForTesting inferenceData = new InferenceDataForTesting();
-
- MemberBuilder? patchForTesting;
-}
-
/// Base class for implementing [ClassMember] for a [MemberBuilder].
abstract class BuilderClassMember implements ClassMember {
MemberBuilderImpl get memberBuilder;
@@ -344,13 +235,3 @@
@override
String toString() => '$runtimeType($fullName,forSetter=${forSetter})';
}
-
-/// If the name of [member] is private, update it to use the library reference
-/// of [libraryBuilder].
-// TODO(johnniwinther): Avoid having to update private names by setting
-// the correct library reference when creating parts.
-void updatePrivateMemberName(Member member, LibraryBuilder libraryBuilder) {
- if (member.name.isPrivate) {
- member.name = new Name(member.name.text, libraryBuilder.library);
- }
-}
diff --git a/pkg/front_end/lib/src/fasta/builder/procedure_builder.dart b/pkg/front_end/lib/src/fasta/builder/procedure_builder.dart
index f09dc0d..71ca0c2 100644
--- a/pkg/front_end/lib/src/fasta/builder/procedure_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/procedure_builder.dart
@@ -3,24 +3,8 @@
// BSD-style license that can be found in the LICENSE file.
import 'package:kernel/ast.dart';
-import 'package:kernel/type_algebra.dart';
-import '../kernel/hierarchy/class_member.dart';
-import '../kernel/hierarchy/members_builder.dart';
-import '../kernel/member_covariance.dart';
-
-import '../source/name_scheme.dart';
-import '../source/source_loader.dart' show SourceLoader;
-import '../source/source_library_builder.dart' show SourceLibraryBuilder;
-
-import 'builder.dart';
-import 'extension_builder.dart';
-import 'formal_parameter_builder.dart';
import 'function_builder.dart';
-import 'member_builder.dart';
-import 'metadata_builder.dart';
-import 'type_builder.dart';
-import 'type_variable_builder.dart';
abstract class ProcedureBuilder implements FunctionBuilder {
int get charOpenParenOffset;
@@ -46,521 +30,3 @@
/// Returns `true` if this procedure is declared in an extension declaration.
bool get isExtensionMethod;
}
-
-class SourceProcedureBuilder extends FunctionBuilderImpl
- implements ProcedureBuilder {
- @override
- final int charOpenParenOffset;
-
- @override
- AsyncMarker actualAsyncModifier = AsyncMarker.Sync;
-
- @override
- final bool isExtensionInstanceMember;
-
- late Procedure _procedure;
-
- final Reference? _tearOffReference;
-
- /// If this is an extension instance method then [_extensionTearOff] holds
- /// the synthetically created tear off function.
- Procedure? _extensionTearOff;
-
- /// If this is an extension instance method then
- /// [_extensionTearOffParameterMap] holds a map from the parameters of
- /// the methods to the parameter of the closure returned in the tear-off.
- ///
- /// This map is used to set the default values on the closure parameters when
- /// these have been built.
- Map<VariableDeclaration, VariableDeclaration>? _extensionTearOffParameterMap;
-
- @override
- final ProcedureKind kind;
-
- SourceProcedureBuilder? actualOrigin;
-
- SourceProcedureBuilder(
- List<MetadataBuilder>? metadata,
- int modifiers,
- TypeBuilder? returnType,
- String name,
- List<TypeVariableBuilder>? typeVariables,
- List<FormalParameterBuilder>? formals,
- this.kind,
- SourceLibraryBuilder libraryBuilder,
- int startCharOffset,
- int charOffset,
- this.charOpenParenOffset,
- int charEndOffset,
- Reference? procedureReference,
- this._tearOffReference,
- AsyncMarker asyncModifier,
- NameScheme nameScheme,
- {required bool isExtensionMember,
- required bool isInstanceMember,
- String? nativeMethodName})
- // ignore: unnecessary_null_comparison
- : assert(isExtensionMember != null),
- // ignore: unnecessary_null_comparison
- assert(isInstanceMember != null),
- assert(kind != ProcedureKind.Factory),
- this.isExtensionInstanceMember = isInstanceMember && isExtensionMember,
- super(metadata, modifiers, returnType, name, typeVariables, formals,
- libraryBuilder, charOffset, nativeMethodName) {
- _procedure = new Procedure(
- nameScheme.getProcedureName(kind, name),
- isExtensionInstanceMember ? ProcedureKind.Method : kind,
- new FunctionNode(null),
- fileUri: libraryBuilder.fileUri,
- reference: procedureReference)
- ..startFileOffset = startCharOffset
- ..fileOffset = charOffset
- ..fileEndOffset = charEndOffset
- ..isNonNullableByDefault = libraryBuilder.isNonNullableByDefault;
- this.asyncModifier = asyncModifier;
- if (isExtensionMember && isInstanceMember && kind == ProcedureKind.Method) {
- _extensionTearOff ??= new Procedure(
- nameScheme.getProcedureName(ProcedureKind.Getter, name),
- ProcedureKind.Method,
- new FunctionNode(null),
- isStatic: true,
- isExtensionMember: true,
- reference: _tearOffReference,
- fileUri: fileUri)
- ..isNonNullableByDefault = library.isNonNullableByDefault;
- }
- }
-
- @override
- ProcedureBuilder? get patchForTesting =>
- dataForTesting?.patchForTesting as ProcedureBuilder?;
-
- @override
- AsyncMarker get asyncModifier => actualAsyncModifier;
-
- @override
- Statement? get body {
- if (bodyInternal == null && !isAbstract && !isExternal) {
- bodyInternal = new EmptyStatement();
- }
- return bodyInternal;
- }
-
- @override
- void set asyncModifier(AsyncMarker newModifier) {
- actualAsyncModifier = newModifier;
- function.asyncMarker = actualAsyncModifier;
- function.dartAsyncMarker = actualAsyncModifier;
- }
-
- @override
- bool get isEligibleForTopLevelInference {
- if (isDeclarationInstanceMember) {
- if (returnType == null) return true;
- if (formals != null) {
- for (FormalParameterBuilder formal in formals!) {
- if (formal.type == null) return true;
- }
- }
- }
- return false;
- }
-
- @override
- bool get isExtensionMethod {
- return parent is ExtensionBuilder;
- }
-
- @override
- Member get member => procedure;
-
- @override
- SourceProcedureBuilder get origin => actualOrigin ?? this;
-
- @override
- Procedure get procedure => isPatch ? origin.procedure : _procedure;
-
- @override
- Procedure get actualProcedure => _procedure;
-
- @override
- FunctionNode get function => _procedure.function;
-
- bool _typeEnsured = false;
- Set<ClassMember>? _overrideDependencies;
-
- void registerOverrideDependency(Set<ClassMember> overriddenMembers) {
- assert(
- overriddenMembers.every((overriddenMember) =>
- overriddenMember.classBuilder != classBuilder),
- "Unexpected override dependencies for $this: $overriddenMembers");
- _overrideDependencies ??= {};
- _overrideDependencies!.addAll(overriddenMembers);
- }
-
- void _ensureTypes(ClassMembersBuilder membersBuilder) {
- if (_typeEnsured) return;
- if (_overrideDependencies != null) {
- if (isGetter) {
- membersBuilder.inferGetterType(this, _overrideDependencies!);
- } else if (isSetter) {
- membersBuilder.inferSetterType(this, _overrideDependencies!);
- } else {
- membersBuilder.inferMethodType(this, _overrideDependencies!);
- }
- _overrideDependencies = null;
- }
- _typeEnsured = true;
- }
-
- @override
- Member? get readTarget {
- switch (kind) {
- case ProcedureKind.Method:
- return extensionTearOff ?? procedure;
- case ProcedureKind.Getter:
- return procedure;
- case ProcedureKind.Factory:
- return procedure;
- case ProcedureKind.Operator:
- case ProcedureKind.Setter:
- return null;
- }
- }
-
- @override
- Member? get writeTarget {
- switch (kind) {
- case ProcedureKind.Setter:
- return procedure;
- case ProcedureKind.Method:
- case ProcedureKind.Getter:
- case ProcedureKind.Operator:
- case ProcedureKind.Factory:
- return null;
- }
- }
-
- @override
- Member? get invokeTarget {
- switch (kind) {
- case ProcedureKind.Method:
- case ProcedureKind.Getter:
- case ProcedureKind.Operator:
- case ProcedureKind.Factory:
- return procedure;
- case ProcedureKind.Setter:
- return null;
- }
- }
-
- @override
- Iterable<Member> get exportedMembers => [procedure];
-
- @override
- void buildMembers(
- SourceLibraryBuilder library, void Function(Member, BuiltMemberKind) f) {
- Member member = build(library);
- if (isExtensionMethod) {
- switch (kind) {
- case ProcedureKind.Method:
- f(member, BuiltMemberKind.ExtensionMethod);
- break;
- case ProcedureKind.Getter:
- f(member, BuiltMemberKind.ExtensionGetter);
- break;
- case ProcedureKind.Setter:
- f(member, BuiltMemberKind.ExtensionSetter);
- break;
- case ProcedureKind.Operator:
- f(member, BuiltMemberKind.ExtensionOperator);
- break;
- case ProcedureKind.Factory:
- throw new UnsupportedError(
- 'Unexpected extension method kind ${kind}');
- }
- if (extensionTearOff != null) {
- f(extensionTearOff!, BuiltMemberKind.ExtensionTearOff);
- }
- } else {
- f(member, BuiltMemberKind.Method);
- }
- }
-
- @override
- Procedure build(SourceLibraryBuilder libraryBuilder) {
- buildFunction(libraryBuilder);
- _procedure.function.fileOffset = charOpenParenOffset;
- _procedure.function.fileEndOffset = _procedure.fileEndOffset;
- _procedure.isAbstract = isAbstract;
- _procedure.isExternal = isExternal;
- _procedure.isConst = isConst;
- updatePrivateMemberName(_procedure, libraryBuilder);
- if (isExtensionMethod) {
- _procedure.isExtensionMember = true;
- _procedure.isStatic = true;
- if (isExtensionInstanceMember) {
- assert(_procedure.kind == ProcedureKind.Method);
- }
- } else {
- _procedure.isStatic = isStatic;
- }
- if (extensionTearOff != null) {
- _buildExtensionTearOff(libraryBuilder, parent as ExtensionBuilder);
- updatePrivateMemberName(extensionTearOff!, libraryBuilder);
- }
- return _procedure;
- }
-
- /// Creates a top level function that creates a tear off of an extension
- /// instance method.
- ///
- /// For this declaration
- ///
- /// extension E<T> on A<T> {
- /// X method<S>(S s, Y y) {}
- /// }
- ///
- /// we create the top level function
- ///
- /// X E|method<T, S>(A<T> #this, S s, Y y) {}
- ///
- /// and the tear off function
- ///
- /// X Function<S>(S, Y) E|get#method<T>(A<T> #this) {
- /// return (S s, Y y) => E|method<T, S>(#this, s, y);
- /// }
- ///
- void _buildExtensionTearOff(
- SourceLibraryBuilder libraryBuilder, ExtensionBuilder extensionBuilder) {
- assert(
- _extensionTearOff != null, "No extension tear off created for $this.");
-
- _extensionTearOffParameterMap = {};
-
- int fileOffset = _procedure.fileOffset;
- int fileEndOffset = _procedure.fileEndOffset;
-
- int extensionTypeParameterCount =
- extensionBuilder.typeParameters?.length ?? 0;
-
- List<TypeParameter> typeParameters = <TypeParameter>[];
-
- Map<TypeParameter, DartType> substitutionMap = {};
- List<DartType> typeArguments = <DartType>[];
- for (TypeParameter typeParameter in function.typeParameters) {
- TypeParameter newTypeParameter = new TypeParameter(typeParameter.name);
- typeParameters.add(newTypeParameter);
- typeArguments.add(substitutionMap[typeParameter] =
- new TypeParameterType.forAlphaRenaming(
- typeParameter, newTypeParameter));
- }
-
- List<TypeParameter> tearOffTypeParameters = <TypeParameter>[];
- List<TypeParameter> closureTypeParameters = <TypeParameter>[];
- Substitution substitution = Substitution.fromMap(substitutionMap);
- for (int index = 0; index < typeParameters.length; index++) {
- TypeParameter newTypeParameter = typeParameters[index];
- newTypeParameter.bound =
- substitution.substituteType(function.typeParameters[index].bound);
- newTypeParameter.defaultType = function.typeParameters[index].defaultType;
- if (index < extensionTypeParameterCount) {
- tearOffTypeParameters.add(newTypeParameter);
- } else {
- closureTypeParameters.add(newTypeParameter);
- }
- }
-
- VariableDeclaration copyParameter(
- VariableDeclaration parameter, DartType type,
- {required bool isOptional}) {
- VariableDeclaration newParameter = new VariableDeclaration(parameter.name,
- type: type,
- isFinal: parameter.isFinal,
- isLowered: parameter.isLowered)
- ..fileOffset = parameter.fileOffset;
- _extensionTearOffParameterMap![parameter] = newParameter;
- return newParameter;
- }
-
- VariableDeclaration extensionThis = copyParameter(
- function.positionalParameters.first,
- substitution.substituteType(function.positionalParameters.first.type),
- isOptional: false);
-
- DartType closureReturnType =
- substitution.substituteType(function.returnType);
- List<VariableDeclaration> closurePositionalParameters = [];
- List<Expression> closurePositionalArguments = [];
-
- for (int position = 0;
- position < function.positionalParameters.length;
- position++) {
- VariableDeclaration parameter = function.positionalParameters[position];
- if (position == 0) {
- /// Pass `this` as a captured variable.
- closurePositionalArguments
- .add(new VariableGet(extensionThis)..fileOffset = fileOffset);
- } else {
- DartType type = substitution.substituteType(parameter.type);
- VariableDeclaration newParameter = copyParameter(parameter, type,
- isOptional: position >= function.requiredParameterCount);
- closurePositionalParameters.add(newParameter);
- closurePositionalArguments
- .add(new VariableGet(newParameter)..fileOffset = fileOffset);
- }
- }
- List<VariableDeclaration> closureNamedParameters = [];
- List<NamedExpression> closureNamedArguments = [];
- for (VariableDeclaration parameter in function.namedParameters) {
- DartType type = substitution.substituteType(parameter.type);
- VariableDeclaration newParameter =
- copyParameter(parameter, type, isOptional: true);
- closureNamedParameters.add(newParameter);
- closureNamedArguments.add(new NamedExpression(parameter.name!,
- new VariableGet(newParameter)..fileOffset = fileOffset));
- }
-
- Statement closureBody = new ReturnStatement(
- new StaticInvocation(
- _procedure,
- new Arguments(closurePositionalArguments,
- types: typeArguments, named: closureNamedArguments))
- ..fileOffset = fileOffset)
- ..fileOffset = fileOffset;
-
- FunctionExpression closure = new FunctionExpression(
- new FunctionNode(closureBody,
- typeParameters: closureTypeParameters,
- positionalParameters: closurePositionalParameters,
- namedParameters: closureNamedParameters,
- requiredParameterCount:
- _procedure.function.requiredParameterCount - 1,
- returnType: closureReturnType)
- ..fileOffset = fileOffset
- ..fileEndOffset = fileEndOffset)
- ..fileOffset = fileOffset;
-
- _extensionTearOff!
- ..function = (new FunctionNode(
- new ReturnStatement(closure)..fileOffset = fileOffset,
- typeParameters: tearOffTypeParameters,
- positionalParameters: [extensionThis],
- requiredParameterCount: 1,
- returnType: closure.function.computeFunctionType(library.nonNullable))
- ..fileOffset = fileOffset
- ..fileEndOffset = fileEndOffset)
- ..fileUri = fileUri
- ..fileOffset = fileOffset
- ..fileEndOffset = fileEndOffset;
- _extensionTearOff!.function.parent = _extensionTearOff;
- }
-
- Procedure? get extensionTearOff => _extensionTearOff;
-
- @override
- VariableDeclaration? getTearOffParameter(int index) {
- return _extensionTearOffParameterMap?[getFormalParameter(index)];
- }
-
- List<ClassMember>? _localMembers;
- List<ClassMember>? _localSetters;
-
- @override
- List<ClassMember> get localMembers => _localMembers ??= isSetter
- ? const <ClassMember>[]
- : <ClassMember>[new SourceProcedureMember(this)];
-
- @override
- List<ClassMember> get localSetters =>
- _localSetters ??= isSetter && !isConflictingSetter
- ? <ClassMember>[new SourceProcedureMember(this)]
- : const <ClassMember>[];
-
- @override
- void becomeNative(SourceLoader loader) {
- _procedure.isExternal = true;
- super.becomeNative(loader);
- }
-
- @override
- void applyPatch(Builder patch) {
- if (patch is SourceProcedureBuilder) {
- if (checkPatch(patch)) {
- patch.actualOrigin = this;
- dataForTesting?.patchForTesting = patch;
- }
- } else {
- reportPatchMismatch(patch);
- }
- }
-
- @override
- int finishPatch() {
- if (!isPatch) return 0;
-
- // TODO(ahe): restore file-offset once we track both origin and patch file
- // URIs. See https://github.com/dart-lang/sdk/issues/31579
- origin.procedure.fileUri = fileUri;
- origin.procedure.startFileOffset = _procedure.startFileOffset;
- origin.procedure.fileOffset = _procedure.fileOffset;
- origin.procedure.fileEndOffset = _procedure.fileEndOffset;
- origin.procedure.annotations
- .forEach((m) => m.fileOffset = _procedure.fileOffset);
-
- origin.procedure.isAbstract = _procedure.isAbstract;
- origin.procedure.isExternal = _procedure.isExternal;
- origin.procedure.function = _procedure.function;
- origin.procedure.function.parent = origin.procedure;
- origin.procedure.isRedirectingFactory = _procedure.isRedirectingFactory;
- return 1;
- }
-}
-
-class SourceProcedureMember extends BuilderClassMember {
- @override
- final SourceProcedureBuilder memberBuilder;
-
- Covariance? _covariance;
-
- SourceProcedureMember(this.memberBuilder);
-
- @override
- bool get isSourceDeclaration => true;
-
- @override
- void inferType(ClassMembersBuilder membersBuilder) {
- memberBuilder._ensureTypes(membersBuilder);
- }
-
- @override
- void registerOverrideDependency(Set<ClassMember> overriddenMembers) {
- memberBuilder.registerOverrideDependency(overriddenMembers);
- }
-
- @override
- Member getMember(ClassMembersBuilder membersBuilder) {
- memberBuilder._ensureTypes(membersBuilder);
- return memberBuilder.member;
- }
-
- @override
- Covariance getCovariance(ClassMembersBuilder membersBuilder) {
- return _covariance ??= new Covariance.fromMember(getMember(membersBuilder),
- forSetter: forSetter);
- }
-
- @override
- bool get forSetter => isSetter;
-
- @override
- bool get isProperty =>
- memberBuilder.kind == ProcedureKind.Getter ||
- memberBuilder.kind == ProcedureKind.Setter;
-
- @override
- bool isSameDeclaration(ClassMember other) {
- return other is SourceProcedureMember &&
- memberBuilder == other.memberBuilder;
- }
-}
diff --git a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
index 3c7b280..847a435 100644
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
@@ -5,9 +5,7 @@
library fasta.body_builder;
import 'package:_fe_analyzer_shared/src/flow_analysis/flow_analysis.dart';
-
import 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;
-
import 'package:_fe_analyzer_shared/src/parser/parser.dart'
show
Assert,
@@ -20,7 +18,6 @@
lengthForToken,
lengthOfSpan,
optional;
-
import 'package:_fe_analyzer_shared/src/parser/quote.dart'
show
Quote,
@@ -32,13 +29,10 @@
import 'package:_fe_analyzer_shared/src/parser/stack_listener.dart'
show FixedNullableList, GrowableList, NullValue, ParserRecovery;
import 'package:_fe_analyzer_shared/src/parser/value_kind.dart';
-
import 'package:_fe_analyzer_shared/src/scanner/scanner.dart' show Token;
import 'package:_fe_analyzer_shared/src/scanner/token_impl.dart'
show isBinaryOperator, isMinusOperator, isUserDefinableOperator;
-
import 'package:_fe_analyzer_shared/src/util/link.dart';
-
import 'package:kernel/ast.dart';
import 'package:kernel/class_hierarchy.dart';
import 'package:kernel/clone.dart';
@@ -52,12 +46,9 @@
import '../builder/class_builder.dart';
import '../builder/constructor_builder.dart';
import '../builder/declaration_builder.dart';
-import '../builder/enum_builder.dart';
import '../builder/extension_builder.dart';
-import '../builder/factory_builder.dart';
import '../builder/field_builder.dart';
import '../builder/formal_parameter_builder.dart';
-import '../builder/function_builder.dart';
import '../builder/function_type_builder.dart';
import '../builder/invalid_type_declaration_builder.dart';
import '../builder/library_builder.dart';
@@ -66,20 +57,15 @@
import '../builder/named_type_builder.dart';
import '../builder/nullability_builder.dart';
import '../builder/prefix_builder.dart';
-import '../builder/procedure_builder.dart';
import '../builder/type_alias_builder.dart';
import '../builder/type_builder.dart';
import '../builder/type_declaration_builder.dart';
import '../builder/type_variable_builder.dart';
import '../builder/variable_builder.dart';
import '../builder/void_type_declaration_builder.dart';
-
import '../constant_context.dart' show ConstantContext;
-
import '../dill/dill_library_builder.dart' show DillLibraryBuilder;
-
import '../fasta_codes.dart' as fasta;
-
import '../fasta_codes.dart'
show
LocatedMessage,
@@ -87,36 +73,30 @@
Template,
noLength,
templateExperimentNotEnabled;
-
import '../identifiers.dart'
show Identifier, InitializedIdentifier, QualifiedName, flattenName;
-
import '../kernel/utils.dart';
-
import '../messages.dart' as messages show getLocationFromUri;
-
import '../modifier.dart'
show Modifier, constMask, covariantMask, finalMask, lateMask, requiredMask;
-
import '../names.dart' show emptyName, minusName, plusName;
-
import '../problems.dart'
show internalProblem, unexpected, unhandled, unsupported;
-
import '../scope.dart';
-
import '../source/diet_parser.dart';
import '../source/scope_listener.dart' show JumpTargetKind, ScopeListener;
+import '../source/source_constructor_builder.dart';
+import '../source/source_enum_builder.dart';
+import '../source/source_factory_builder.dart';
+import '../source/source_function_builder.dart';
import '../source/source_library_builder.dart' show SourceLibraryBuilder;
+import '../source/source_procedure_builder.dart';
import '../source/stack_listener_impl.dart' show offsetForToken;
import '../source/value_kinds.dart';
-
import '../type_inference/type_inferrer.dart'
show TypeInferrer, InferredFunctionBody, InitializerInferenceResult;
import '../type_inference/type_schema.dart' show UnknownType;
-
import '../util/helpers.dart' show DelayedActionPerformer;
-
import 'collections.dart';
import 'constness.dart' show Constness;
import 'constructor_tearoff_lowering.dart';
diff --git a/pkg/front_end/lib/src/fasta/kernel/constructor_tearoff_lowering.dart b/pkg/front_end/lib/src/fasta/kernel/constructor_tearoff_lowering.dart
index 244a71d..0cbb45a 100644
--- a/pkg/front_end/lib/src/fasta/kernel/constructor_tearoff_lowering.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/constructor_tearoff_lowering.dart
@@ -4,8 +4,9 @@
import 'package:kernel/ast.dart';
import 'package:kernel/type_algebra.dart';
-import '../builder/member_builder.dart';
+
import '../source/source_library_builder.dart';
+import '../source/source_member_builder.dart';
import 'kernel_helper.dart';
const String _tearOffNamePrefix = '_#';
diff --git a/pkg/front_end/lib/src/fasta/kernel/hierarchy/members_builder.dart b/pkg/front_end/lib/src/fasta/kernel/hierarchy/members_builder.dart
index f50343a..6a0c047 100644
--- a/pkg/front_end/lib/src/fasta/kernel/hierarchy/members_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/hierarchy/members_builder.dart
@@ -8,10 +8,10 @@
import 'package:kernel/class_hierarchy.dart' show ClassHierarchyMembers;
import '../../builder/class_builder.dart';
-import '../../builder/field_builder.dart';
-import '../../builder/procedure_builder.dart';
import '../../builder/type_builder.dart';
import '../../source/source_class_builder.dart';
+import '../../source/source_field_builder.dart';
+import '../../source/source_procedure_builder.dart';
import 'class_member.dart';
import 'delayed.dart';
import 'hierarchy_builder.dart';
diff --git a/pkg/front_end/lib/src/fasta/kernel/hierarchy/members_node.dart b/pkg/front_end/lib/src/fasta/kernel/hierarchy/members_node.dart
index b2fc124..81fd945 100644
--- a/pkg/front_end/lib/src/fasta/kernel/hierarchy/members_node.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/hierarchy/members_node.dart
@@ -14,12 +14,10 @@
import '../../../base/common.dart';
import '../../builder/builder.dart';
import '../../builder/class_builder.dart';
-import '../../builder/field_builder.dart';
import '../../builder/formal_parameter_builder.dart';
import '../../builder/library_builder.dart';
import '../../builder/member_builder.dart';
import '../../builder/named_type_builder.dart';
-import '../../builder/procedure_builder.dart';
import '../../builder/type_alias_builder.dart';
import '../../builder/type_builder.dart';
import '../../builder/type_declaration_builder.dart';
@@ -44,6 +42,8 @@
import '../../names.dart' show noSuchMethodName;
import '../../scope.dart' show Scope;
import '../../source/source_class_builder.dart';
+import '../../source/source_field_builder.dart';
+import '../../source/source_procedure_builder.dart';
import '../combined_member_signature.dart';
import '../member_covariance.dart';
import 'class_member.dart';
diff --git a/pkg/front_end/lib/src/fasta/kernel/implicit_field_type.dart b/pkg/front_end/lib/src/fasta/kernel/implicit_field_type.dart
index c4f1db7..792c92f 100644
--- a/pkg/front_end/lib/src/fasta/kernel/implicit_field_type.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/implicit_field_type.dart
@@ -5,17 +5,15 @@
library fasta.implicit_type;
import 'package:_fe_analyzer_shared/src/scanner/token.dart' show Token;
-
import 'package:kernel/ast.dart';
-
import 'package:kernel/src/assumptions.dart';
import 'package:kernel/src/legacy_erasure.dart';
import 'package:kernel/src/printer.dart';
-import '../builder/field_builder.dart';
import '../constant_context.dart';
import '../fasta_codes.dart';
import '../problems.dart' show unsupported;
+import '../source/source_field_builder.dart';
import '../type_inference/type_inferrer.dart';
import '../type_inference/type_schema.dart';
import 'body_builder.dart';
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
index 4167fe9..ad571bc 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
@@ -66,6 +66,8 @@
import '../scope.dart' show AmbiguousBuilder;
import '../source/name_scheme.dart';
import '../source/source_class_builder.dart' show SourceClassBuilder;
+import '../source/source_constructor_builder.dart';
+import '../source/source_field_builder.dart';
import '../source/source_library_builder.dart' show SourceLibraryBuilder;
import '../source/source_loader.dart' show SourceLoader;
import '../target_implementation.dart' show TargetImplementation;
diff --git a/pkg/front_end/lib/src/fasta/scope.dart b/pkg/front_end/lib/src/fasta/scope.dart
index 840e400..cc9eb28 100644
--- a/pkg/front_end/lib/src/fasta/scope.dart
+++ b/pkg/front_end/lib/src/fasta/scope.dart
@@ -13,12 +13,6 @@
import 'builder/member_builder.dart';
import 'builder/name_iterator.dart';
import 'builder/type_variable_builder.dart';
-import 'kernel/body_builder.dart' show JumpTarget;
-import 'kernel/hierarchy/class_member.dart' show ClassMember;
-import 'kernel/kernel_helper.dart';
-import 'source/source_library_builder.dart';
-import 'util/helpers.dart' show DelayedActionPerformer;
-
import 'fasta_codes.dart'
show
LocatedMessage,
@@ -27,8 +21,13 @@
templateAccessError,
templateDuplicatedDeclarationUse,
templateDuplicatedNamePreviouslyUsedCause;
-
+import 'kernel/body_builder.dart' show JumpTarget;
+import 'kernel/hierarchy/class_member.dart' show ClassMember;
+import 'kernel/kernel_helper.dart';
import 'problems.dart' show internalProblem, unsupported;
+import 'source/source_library_builder.dart';
+import 'source/source_member_builder.dart';
+import 'util/helpers.dart' show DelayedActionPerformer;
class MutableScope {
/// Names declared in this scope.
diff --git a/pkg/front_end/lib/src/fasta/source/diet_listener.dart b/pkg/front_end/lib/src/fasta/source/diet_listener.dart
index ae3196c..ab8d175 100644
--- a/pkg/front_end/lib/src/fasta/source/diet_listener.dart
+++ b/pkg/front_end/lib/src/fasta/source/diet_listener.dart
@@ -12,40 +12,26 @@
MemberKind,
Parser,
optional;
-
import 'package:_fe_analyzer_shared/src/parser/quote.dart' show unescapeString;
-
import 'package:_fe_analyzer_shared/src/parser/stack_listener.dart'
show FixedNullableList, NullValue, ParserRecovery;
-
import 'package:_fe_analyzer_shared/src/parser/value_kind.dart';
-
import 'package:_fe_analyzer_shared/src/scanner/token.dart' show Token;
-
import 'package:kernel/ast.dart';
-
import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
-
import 'package:kernel/core_types.dart' show CoreTypes;
import '../builder/builder.dart';
import '../builder/class_builder.dart';
import '../builder/declaration_builder.dart';
-import '../builder/field_builder.dart';
import '../builder/formal_parameter_builder.dart';
-import '../builder/function_builder.dart';
import '../builder/function_type_builder.dart';
import '../builder/metadata_builder.dart';
import '../builder/modifier_builder.dart';
import '../builder/type_alias_builder.dart';
import '../builder/type_builder.dart';
-
-import '../identifiers.dart' show QualifiedName;
-
import '../constant_context.dart' show ConstantContext;
-
import '../crash.dart' show Crash;
-
import '../fasta_codes.dart'
show
Code,
@@ -53,27 +39,20 @@
Message,
messageExpectedBlockToSkip,
templateInternalProblemNotFound;
-
+import '../identifiers.dart' show QualifiedName;
import '../ignored_parser_errors.dart' show isIgnoredParserError;
-
import '../kernel/body_builder.dart' show BodyBuilder, FormalParameters;
-
import '../problems.dart'
show DebugAbort, internalProblem, unexpected, unhandled;
-
import '../scope.dart';
-
import '../source/value_kinds.dart';
-
import '../type_inference/type_inference_engine.dart'
show InferenceDataForTesting, TypeInferenceEngine;
-
import '../type_inference/type_inferrer.dart' show TypeInferrer;
-
import 'diet_parser.dart';
-
+import 'source_field_builder.dart';
+import 'source_function_builder.dart';
import 'source_library_builder.dart' show SourceLibraryBuilder;
-
import 'stack_listener_impl.dart';
class DietListener extends StackListenerImpl {
diff --git a/pkg/front_end/lib/src/fasta/source/outline_builder.dart b/pkg/front_end/lib/src/fasta/source/outline_builder.dart
index c4e44e2..7f34cfd 100644
--- a/pkg/front_end/lib/src/fasta/source/outline_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/outline_builder.dart
@@ -14,23 +14,16 @@
lengthOfSpan,
MemberKind,
optional;
-
import 'package:_fe_analyzer_shared/src/parser/quote.dart' show unescapeString;
-
import 'package:_fe_analyzer_shared/src/parser/stack_listener.dart'
show FixedNullableList, NullValue, ParserRecovery;
-
import 'package:_fe_analyzer_shared/src/parser/value_kind.dart';
-
import 'package:_fe_analyzer_shared/src/scanner/scanner.dart' show Token;
-
import 'package:_fe_analyzer_shared/src/util/link.dart';
-
import 'package:kernel/ast.dart'
show AsyncMarker, InvalidType, Nullability, ProcedureKind, Variance;
import '../builder/constructor_reference_builder.dart';
-import '../builder/enum_builder.dart';
import '../builder/fixed_type_builder.dart';
import '../builder/formal_parameter_builder.dart';
import '../builder/function_type_builder.dart';
@@ -41,20 +34,13 @@
import '../builder/nullability_builder.dart';
import '../builder/type_builder.dart';
import '../builder/type_variable_builder.dart';
-
import '../combinator.dart' show CombinatorBuilder;
-
import '../configuration.dart' show Configuration;
-
import '../fasta_codes.dart';
-
import '../identifiers.dart' show QualifiedName, flattenName;
-
import '../ignored_parser_errors.dart' show isIgnoredParserError;
-
import '../kernel/type_algorithms.dart';
import '../kernel/utils.dart';
-
import '../modifier.dart'
show
Const,
@@ -73,27 +59,22 @@
mixinDeclarationMask,
requiredMask,
staticMask;
-
import '../operator.dart'
show
Operator,
operatorFromString,
operatorToString,
operatorRequiredArgumentCount;
-
import '../problems.dart' show unhandled;
-
+import 'source_enum_builder.dart';
import 'source_extension_builder.dart';
-
import 'source_library_builder.dart'
show
TypeParameterScopeBuilder,
TypeParameterScopeKind,
FieldInfo,
SourceLibraryBuilder;
-
import 'stack_listener_impl.dart';
-
import 'value_kinds.dart';
enum MethodBody {
diff --git a/pkg/front_end/lib/src/fasta/source/source_class_builder.dart b/pkg/front_end/lib/src/fasta/source/source_class_builder.dart
index f60505d..b623395 100644
--- a/pkg/front_end/lib/src/fasta/source/source_class_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_class_builder.dart
@@ -21,10 +21,7 @@
import '../builder/builder.dart';
import '../builder/class_builder.dart';
-import '../builder/constructor_builder.dart';
import '../builder/constructor_reference_builder.dart';
-import '../builder/factory_builder.dart';
-import '../builder/field_builder.dart';
import '../builder/function_builder.dart';
import '../builder/invalid_type_declaration_builder.dart';
import '../builder/library_builder.dart';
@@ -32,34 +29,29 @@
import '../builder/metadata_builder.dart';
import '../builder/named_type_builder.dart';
import '../builder/nullability_builder.dart';
-import '../builder/procedure_builder.dart';
import '../builder/type_alias_builder.dart';
import '../builder/type_builder.dart';
import '../builder/type_declaration_builder.dart';
import '../builder/type_variable_builder.dart';
-
import '../dill/dill_member_builder.dart';
-
import '../fasta_codes.dart';
-
import '../kernel/combined_member_signature.dart';
import '../kernel/kernel_helper.dart';
import '../kernel/kernel_target.dart' show KernelTarget;
import '../kernel/redirecting_factory_body.dart' show redirectingName;
import '../kernel/type_algorithms.dart' show computeTypeVariableBuilderVariance;
import '../kernel/utils.dart' show compareProcedures;
-
import '../names.dart' show equalsName, noSuchMethodName;
-
import '../problems.dart' show unexpected, unhandled, unimplemented;
-
import '../scope.dart';
-
import '../type_inference/type_schema.dart';
-
import '../util/helpers.dart';
-
+import 'source_constructor_builder.dart';
+import 'source_factory_builder.dart';
+import 'source_field_builder.dart';
import 'source_library_builder.dart' show SourceLibraryBuilder;
+import 'source_member_builder.dart';
+import 'source_procedure_builder.dart';
Class initializeClass(
Class? cls,
diff --git a/pkg/front_end/lib/src/fasta/source/source_constructor_builder.dart b/pkg/front_end/lib/src/fasta/source/source_constructor_builder.dart
new file mode 100644
index 0000000..ed633a7
--- /dev/null
+++ b/pkg/front_end/lib/src/fasta/source/source_constructor_builder.dart
@@ -0,0 +1,747 @@
+// Copyright (c) 2019, 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:_fe_analyzer_shared/src/scanner/token.dart' show Token;
+import 'package:kernel/ast.dart';
+import 'package:kernel/class_hierarchy.dart';
+import 'package:kernel/type_algebra.dart';
+
+import '../builder/builder.dart';
+import '../builder/class_builder.dart';
+import '../builder/constructor_builder.dart';
+import '../builder/field_builder.dart';
+import '../builder/formal_parameter_builder.dart';
+import '../builder/library_builder.dart';
+import '../builder/member_builder.dart';
+import '../builder/metadata_builder.dart';
+import '../builder/named_type_builder.dart';
+import '../builder/type_alias_builder.dart';
+import '../builder/type_builder.dart';
+import '../builder/type_declaration_builder.dart';
+import '../builder/type_variable_builder.dart';
+import '../constant_context.dart' show ConstantContext;
+import '../dill/dill_member_builder.dart';
+import '../kernel/body_builder.dart' show BodyBuilder;
+import '../kernel/constructor_tearoff_lowering.dart';
+import '../kernel/expression_generator_helper.dart'
+ show ExpressionGeneratorHelper;
+import '../kernel/hierarchy/class_member.dart' show ClassMember;
+import '../kernel/kernel_helper.dart' show SynthesizedFunctionNode;
+import '../kernel/utils.dart'
+ show isRedirectingGenerativeConstructorImplementation;
+import '../messages.dart'
+ show
+ Message,
+ messageMoreThanOneSuperInitializer,
+ messageRedirectingConstructorWithAnotherInitializer,
+ messageRedirectingConstructorWithMultipleRedirectInitializers,
+ messageRedirectingConstructorWithSuperInitializer,
+ messageSuperInitializerNotLast,
+ noLength;
+import '../source/source_class_builder.dart';
+import '../source/source_library_builder.dart' show SourceLibraryBuilder;
+import '../source/source_loader.dart' show SourceLoader;
+import '../source/source_member_builder.dart';
+import '../type_inference/type_inferrer.dart';
+import '../type_inference/type_schema.dart';
+import '../util/helpers.dart' show DelayedActionPerformer;
+import 'source_function_builder.dart';
+
+class SourceConstructorBuilder extends FunctionBuilderImpl
+ implements ConstructorBuilder {
+ final Constructor _constructor;
+ final Procedure? _constructorTearOff;
+
+ Set<FieldBuilder>? _initializedFields;
+
+ final int charOpenParenOffset;
+
+ bool hasMovedSuperInitializer = false;
+
+ SuperInitializer? superInitializer;
+
+ RedirectingInitializer? redirectingInitializer;
+
+ Token? beginInitializers;
+
+ SourceConstructorBuilder? actualOrigin;
+
+ Constructor get actualConstructor => _constructor;
+
+ bool _hasFormalsInferred = false;
+
+ final bool _hasSuperInitializingFormals;
+
+ final List<SynthesizedFunctionNode> _superParameterDefaultValueCloners =
+ <SynthesizedFunctionNode>[];
+
+ SourceConstructorBuilder(
+ List<MetadataBuilder>? metadata,
+ int modifiers,
+ TypeBuilder? returnType,
+ String name,
+ List<TypeVariableBuilder>? typeVariables,
+ List<FormalParameterBuilder>? formals,
+ SourceLibraryBuilder compilationUnit,
+ int startCharOffset,
+ int charOffset,
+ this.charOpenParenOffset,
+ int charEndOffset,
+ Reference? constructorReference,
+ Reference? tearOffReference,
+ {String? nativeMethodName,
+ required bool forAbstractClassOrEnum})
+ : _constructor = new Constructor(new FunctionNode(null),
+ name: new Name(name, compilationUnit.library),
+ fileUri: compilationUnit.fileUri,
+ reference: constructorReference)
+ ..startFileOffset = startCharOffset
+ ..fileOffset = charOffset
+ ..fileEndOffset = charEndOffset
+ ..isNonNullableByDefault = compilationUnit.isNonNullableByDefault,
+ _constructorTearOff = createConstructorTearOffProcedure(
+ name,
+ compilationUnit,
+ compilationUnit.fileUri,
+ charOffset,
+ tearOffReference,
+ forAbstractClassOrEnum: forAbstractClassOrEnum),
+ _hasSuperInitializingFormals =
+ formals?.any((formal) => formal.isSuperInitializingFormal) ?? false,
+ super(metadata, modifiers, returnType, name, typeVariables, formals,
+ compilationUnit, charOffset, nativeMethodName);
+
+ @override
+ SourceLibraryBuilder get library => super.library as SourceLibraryBuilder;
+
+ @override
+ SourceClassBuilder get classBuilder =>
+ super.classBuilder as SourceClassBuilder;
+
+ @override
+ Member? get readTarget => _constructorTearOff ?? _constructor;
+
+ @override
+ Member? get writeTarget => null;
+
+ @override
+ Member get invokeTarget => constructor;
+
+ @override
+ FunctionNode get function => _constructor.function;
+
+ @override
+ Iterable<Member> get exportedMembers => [constructor];
+
+ @override
+ SourceConstructorBuilder get origin => actualOrigin ?? this;
+
+ ConstructorBuilder? get patchForTesting =>
+ dataForTesting?.patchForTesting as ConstructorBuilder?;
+
+ @override
+ bool get isDeclarationInstanceMember => false;
+
+ @override
+ bool get isClassInstanceMember => false;
+
+ @override
+ bool get isConstructor => true;
+
+ @override
+ AsyncMarker get asyncModifier => AsyncMarker.Sync;
+
+ @override
+ ProcedureKind? get kind => null;
+
+ @override
+ bool get isRedirectingGenerativeConstructor {
+ return isRedirectingGenerativeConstructorImplementation(_constructor);
+ }
+
+ @override
+ void buildMembers(
+ SourceLibraryBuilder library, void Function(Member, BuiltMemberKind) f) {
+ Member member = build(library);
+ f(member, BuiltMemberKind.Constructor);
+ if (_constructorTearOff != null) {
+ f(_constructorTearOff!, BuiltMemberKind.Method);
+ }
+ }
+
+ bool _hasBeenBuilt = false;
+
+ @override
+ Constructor build(SourceLibraryBuilder libraryBuilder) {
+ if (!_hasBeenBuilt) {
+ buildFunction(libraryBuilder);
+ _constructor.function.fileOffset = charOpenParenOffset;
+ _constructor.function.fileEndOffset = _constructor.fileEndOffset;
+ _constructor.function.typeParameters = const <TypeParameter>[];
+ _constructor.isConst = isConst;
+ _constructor.isExternal = isExternal;
+ updatePrivateMemberName(_constructor, libraryBuilder);
+
+ if (_constructorTearOff != null) {
+ buildConstructorTearOffProcedure(_constructorTearOff!, _constructor,
+ classBuilder.cls, libraryBuilder);
+ }
+
+ _hasBeenBuilt = true;
+ }
+ if (formals != null) {
+ bool needsInference = false;
+ for (FormalParameterBuilder formal in formals!) {
+ if (formal.type == null &&
+ (formal.isInitializingFormal || formal.isSuperInitializingFormal)) {
+ formal.variable!.type = const UnknownType();
+ needsInference = true;
+ }
+ }
+ if (needsInference) {
+ assert(
+ library == libraryBuilder,
+ "Unexpected library builder ${libraryBuilder} for"
+ " constructor $this in ${library}.");
+ libraryBuilder.loader
+ .registerConstructorToBeInferred(_constructor, this);
+ }
+ }
+ return _constructor;
+ }
+
+ /// Infers the types of any untyped initializing formals.
+ void inferFormalTypes(ClassHierarchy classHierarchy) {
+ if (_hasFormalsInferred) return;
+ if (formals != null) {
+ for (FormalParameterBuilder formal in formals!) {
+ if (formal.type == null) {
+ if (formal.isInitializingFormal) {
+ formal.finalizeInitializingFormal(classBuilder);
+ }
+ }
+ }
+
+ if (_hasSuperInitializingFormals) {
+ if (beginInitializers != null) {
+ BodyBuilder bodyBuilder = library.loader
+ .createBodyBuilderForOutlineExpression(
+ library, classBuilder, this, classBuilder.scope, fileUri);
+ bodyBuilder.constantContext = ConstantContext.required;
+ bodyBuilder.parseInitializers(beginInitializers!,
+ doFinishConstructor: false);
+ }
+ finalizeSuperInitializingFormals(
+ classHierarchy, _superParameterDefaultValueCloners);
+ }
+ }
+ _hasFormalsInferred = true;
+ }
+
+ /* ConstructorBuilder | DillConstructorBuilder */
+ Object? _computeSuperTargetBuilder() {
+ Constructor superTarget;
+ ClassBuilder superclassBuilder;
+
+ TypeBuilder? supertype = classBuilder.supertypeBuilder;
+ if (supertype is NamedTypeBuilder) {
+ TypeDeclarationBuilder? declaration = supertype.declaration;
+ if (declaration is ClassBuilder) {
+ superclassBuilder = declaration;
+ } else if (declaration is TypeAliasBuilder) {
+ declaration = declaration.unaliasDeclaration(supertype.arguments);
+ if (declaration is ClassBuilder) {
+ superclassBuilder = declaration;
+ } else {
+ // The error in this case should be reported elsewhere.
+ return null;
+ }
+ } else {
+ // The error in this case should be reported elsewhere.
+ return null;
+ }
+ } else {
+ // The error in this case should be reported elsewhere.
+ return null;
+ }
+
+ if (constructor.initializers.isNotEmpty &&
+ constructor.initializers.last is SuperInitializer) {
+ superTarget = (constructor.initializers.last as SuperInitializer).target;
+ } else {
+ MemberBuilder? memberBuilder = superclassBuilder.constructors
+ .lookup("", charOffset, library.fileUri);
+ if (memberBuilder is ConstructorBuilder) {
+ superTarget = memberBuilder.constructor;
+ } else if (memberBuilder is DillConstructorBuilder) {
+ superTarget = memberBuilder.constructor;
+ } else {
+ // The error in this case should be reported elsewhere.
+ return null;
+ }
+ }
+
+ MemberBuilder? constructorBuilder =
+ superclassBuilder.findConstructorOrFactory(
+ superTarget.name.text, charOffset, library.fileUri, library);
+ return constructorBuilder is ConstructorBuilder ||
+ constructorBuilder is DillConstructorBuilder
+ ? constructorBuilder
+ : null;
+ }
+
+ void finalizeSuperInitializingFormals(ClassHierarchy classHierarchy,
+ List<SynthesizedFunctionNode> synthesizedFunctionNodes) {
+ if (formals == null) return;
+ if (!_hasSuperInitializingFormals) return;
+
+ void performRecoveryForErroneousCase() {
+ for (FormalParameterBuilder formal in formals!) {
+ if (formal.isSuperInitializingFormal) {
+ formal.variable!.type = const DynamicType();
+ }
+ }
+ }
+
+ Object? superTargetBuilder = _computeSuperTargetBuilder();
+ Constructor superTarget;
+ List<FormalParameterBuilder>? superFormals;
+ if (superTargetBuilder is SourceConstructorBuilder) {
+ superTarget = superTargetBuilder.constructor;
+ superFormals = superTargetBuilder.formals!;
+ } else if (superTargetBuilder is DillConstructorBuilder) {
+ superTarget = superTargetBuilder.constructor;
+ if (superTargetBuilder is SyntheticConstructorBuilder) {
+ superFormals = superTargetBuilder.formals;
+ } else {
+ // The error in this case should be reported elsewhere. Here we perform
+ // a simple recovery.
+ return performRecoveryForErroneousCase();
+ }
+ } else {
+ // The error in this case should be reported elsewhere. Here we perform a
+ // simple recovery.
+ return performRecoveryForErroneousCase();
+ }
+
+ if (superFormals == null) {
+ // The error in this case should be reported elsewhere. Here we perform a
+ // simple recovery.
+ return performRecoveryForErroneousCase();
+ }
+
+ if (superTargetBuilder is SourceConstructorBuilder) {
+ superTargetBuilder.inferFormalTypes(classHierarchy);
+ } else if (superTargetBuilder is SyntheticConstructorBuilder) {
+ MemberBuilder? superTargetOriginBuilder = superTargetBuilder.actualOrigin;
+ if (superTargetOriginBuilder is SourceConstructorBuilder) {
+ superTargetOriginBuilder.inferFormalTypes(classHierarchy);
+ }
+ }
+
+ int superInitializingFormalIndex = -1;
+ List<int>? positionalSuperParameters;
+ List<String>? namedSuperParameters;
+
+ Supertype? supertype = classHierarchy.getClassAsInstanceOf(
+ classBuilder.cls, superTarget.enclosingClass);
+ assert(supertype != null);
+ Map<TypeParameter, DartType> substitution =
+ new Map<TypeParameter, DartType>.fromIterables(
+ supertype!.classNode.typeParameters, supertype.typeArguments);
+
+ for (int formalIndex = 0; formalIndex < formals!.length; formalIndex++) {
+ FormalParameterBuilder formal = formals![formalIndex];
+ if (formal.isSuperInitializingFormal) {
+ superInitializingFormalIndex++;
+ bool hasImmediatelyDeclaredInitializer = formal.hasDeclaredInitializer;
+ if (formal.type == null) {
+ DartType? type;
+
+ if (formal.isPositional) {
+ if (superInitializingFormalIndex < superFormals.length) {
+ FormalParameterBuilder correspondingSuperFormal =
+ superFormals[superInitializingFormalIndex];
+ formal.hasDeclaredInitializer =
+ hasImmediatelyDeclaredInitializer ||
+ correspondingSuperFormal.hasDeclaredInitializer;
+ if (!hasImmediatelyDeclaredInitializer) {
+ (positionalSuperParameters ??= <int>[]).add(formalIndex);
+ }
+ type = correspondingSuperFormal.variable!.type;
+ } else {
+ // TODO(cstefantsova): Report an error.
+ }
+ } else {
+ FormalParameterBuilder? correspondingSuperFormal;
+ for (FormalParameterBuilder superFormal in superFormals) {
+ if (superFormal.isNamed && superFormal.name == formal.name) {
+ correspondingSuperFormal = superFormal;
+ break;
+ }
+ }
+
+ if (correspondingSuperFormal != null) {
+ formal.hasDeclaredInitializer =
+ hasImmediatelyDeclaredInitializer ||
+ correspondingSuperFormal.hasDeclaredInitializer;
+ if (!hasImmediatelyDeclaredInitializer) {
+ (namedSuperParameters ??= <String>[]).add(formal.name);
+ }
+ type = correspondingSuperFormal.variable!.type;
+ } else {
+ // TODO(cstefantsova): Report an error.
+ }
+ }
+
+ if (substitution.isNotEmpty && type != null) {
+ type = substitute(type, substitution);
+ }
+ formal.variable!.type = type ?? const DynamicType();
+ } else {
+ formal.variable!.type = const DynamicType();
+ }
+ }
+ }
+
+ if (positionalSuperParameters != null || namedSuperParameters != null) {
+ synthesizedFunctionNodes.add(new SynthesizedFunctionNode(
+ substitution, superTarget.function, constructor.function,
+ positionalSuperParameters: positionalSuperParameters ?? const <int>[],
+ namedSuperParameters: namedSuperParameters ?? const <String>[],
+ isOutlineNode: true));
+ }
+ }
+
+ bool _hasBuiltOutlines = false;
+
+ @override
+ void buildOutlineExpressions(
+ SourceLibraryBuilder library,
+ ClassHierarchy classHierarchy,
+ List<DelayedActionPerformer> delayedActionPerformers,
+ List<SynthesizedFunctionNode> synthesizedFunctionNodes) {
+ if (_hasBuiltOutlines) return;
+ if (isConst && isPatch) {
+ origin.buildOutlineExpressions(library, classHierarchy,
+ delayedActionPerformers, synthesizedFunctionNodes);
+ }
+ super.buildOutlineExpressions(library, classHierarchy,
+ delayedActionPerformers, synthesizedFunctionNodes);
+
+ // For modular compilation purposes we need to include initializers
+ // for const constructors into the outline. We also need to parse
+ // initializers to infer types of the super-initializing parameters.
+ if ((isConst || _hasSuperInitializingFormals) &&
+ beginInitializers != null) {
+ BodyBuilder bodyBuilder = library.loader
+ .createBodyBuilderForOutlineExpression(
+ library, classBuilder, this, classBuilder.scope, fileUri);
+ bodyBuilder.constantContext = ConstantContext.required;
+ bodyBuilder.parseInitializers(beginInitializers!,
+ doFinishConstructor: isConst);
+ bodyBuilder.performBacklogComputations(delayedActionPerformers);
+ }
+ beginInitializers = null;
+ addSuperParameterDefaultValueCloners(synthesizedFunctionNodes);
+ if (isConst && isPatch) {
+ _finishPatch();
+ }
+ _hasBuiltOutlines = true;
+ }
+
+ void addSuperParameterDefaultValueCloners(
+ List<SynthesizedFunctionNode> synthesizedFunctionNodes) {
+ Object? superTargetBuilder = _computeSuperTargetBuilder();
+ if (superTargetBuilder is SourceConstructorBuilder) {
+ superTargetBuilder
+ .addSuperParameterDefaultValueCloners(synthesizedFunctionNodes);
+ } else if (superTargetBuilder is SyntheticConstructorBuilder) {
+ superTargetBuilder
+ .addSuperParameterDefaultValueCloners(synthesizedFunctionNodes);
+ }
+ synthesizedFunctionNodes.addAll(_superParameterDefaultValueCloners);
+ _superParameterDefaultValueCloners.clear();
+ }
+
+ @override
+ void buildFunction(SourceLibraryBuilder library) {
+ // According to the specification §9.3 the return type of a constructor
+ // function is its enclosing class.
+ super.buildFunction(library);
+ 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.withDefaultNullabilityForLibrary(
+ typeParameter, library.library));
+ }
+ function.returnType = new InterfaceType(
+ enclosingClass, library.nonNullable, typeParameterTypes);
+ }
+
+ @override
+ Constructor get constructor => isPatch ? origin.constructor : _constructor;
+
+ @override
+ Member get member => constructor;
+
+ void injectInvalidInitializer(Message message, int charOffset, int length,
+ ExpressionGeneratorHelper helper) {
+ List<Initializer> initializers = _constructor.initializers;
+ Initializer lastInitializer = initializers.removeLast();
+ assert(lastInitializer == superInitializer ||
+ lastInitializer == redirectingInitializer);
+ Initializer error = helper.buildInvalidInitializer(
+ helper.buildProblem(message, charOffset, length));
+ initializers.add(error..parent = _constructor);
+ initializers.add(lastInitializer);
+ }
+
+ void addInitializer(Initializer initializer, ExpressionGeneratorHelper helper,
+ {required InitializerInferenceResult? inferenceResult}) {
+ List<Initializer> initializers = _constructor.initializers;
+ if (initializer is SuperInitializer) {
+ if (superInitializer != null) {
+ injectInvalidInitializer(messageMoreThanOneSuperInitializer,
+ initializer.fileOffset, "super".length, helper);
+ } else if (redirectingInitializer != null) {
+ injectInvalidInitializer(
+ messageRedirectingConstructorWithSuperInitializer,
+ initializer.fileOffset,
+ "super".length,
+ helper);
+ } else {
+ inferenceResult?.applyResult(initializers, _constructor);
+ initializers.add(initializer..parent = _constructor);
+ superInitializer = initializer;
+ }
+ } else if (initializer is RedirectingInitializer) {
+ if (superInitializer != null) {
+ // Point to the existing super initializer.
+ injectInvalidInitializer(
+ messageRedirectingConstructorWithSuperInitializer,
+ superInitializer!.fileOffset,
+ "super".length,
+ helper);
+ } else if (redirectingInitializer != null) {
+ injectInvalidInitializer(
+ messageRedirectingConstructorWithMultipleRedirectInitializers,
+ initializer.fileOffset,
+ noLength,
+ helper);
+ } else if (initializers.isNotEmpty) {
+ // Error on all previous ones.
+ for (int i = 0; i < initializers.length; i++) {
+ Initializer initializer = initializers[i];
+ int length = noLength;
+ if (initializer is AssertInitializer) length = "assert".length;
+ Initializer error = helper.buildInvalidInitializer(
+ helper.buildProblem(
+ messageRedirectingConstructorWithAnotherInitializer,
+ initializer.fileOffset,
+ length));
+ error.parent = _constructor;
+ initializers[i] = error;
+ }
+ inferenceResult?.applyResult(initializers, _constructor);
+ initializers.add(initializer..parent = _constructor);
+ redirectingInitializer = initializer;
+ } else {
+ inferenceResult?.applyResult(initializers, _constructor);
+ initializers.add(initializer..parent = _constructor);
+ redirectingInitializer = initializer;
+ }
+ } else if (redirectingInitializer != null) {
+ int length = noLength;
+ if (initializer is AssertInitializer) length = "assert".length;
+ injectInvalidInitializer(
+ messageRedirectingConstructorWithAnotherInitializer,
+ initializer.fileOffset,
+ length,
+ helper);
+ } else if (superInitializer != null) {
+ injectInvalidInitializer(messageSuperInitializerNotLast,
+ initializer.fileOffset, noLength, helper);
+ } else {
+ inferenceResult?.applyResult(initializers, _constructor);
+ initializers.add(initializer..parent = _constructor);
+ }
+ }
+
+ @override
+ VariableDeclaration? getTearOffParameter(int index) {
+ 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 _finishPatch() {
+ // TODO(ahe): restore file-offset once we track both origin and patch file
+ // URIs. See https://github.com/dart-lang/sdk/issues/31579
+ origin.constructor.fileUri = fileUri;
+ origin.constructor.startFileOffset = _constructor.startFileOffset;
+ origin.constructor.fileOffset = _constructor.fileOffset;
+ origin.constructor.fileEndOffset = _constructor.fileEndOffset;
+ origin.constructor.annotations
+ .forEach((m) => m.fileOffset = _constructor.fileOffset);
+
+ origin.constructor.isExternal = _constructor.isExternal;
+ origin.constructor.function = _constructor.function;
+ origin.constructor.function.parent = origin.constructor;
+ origin.constructor.initializers = _constructor.initializers;
+ setParents(origin.constructor.initializers, origin.constructor);
+ }
+
+ @override
+ int finishPatch() {
+ if (!isPatch) return 0;
+ _finishPatch();
+ return 1;
+ }
+
+ @override
+ void becomeNative(SourceLoader loader) {
+ _constructor.isExternal = true;
+ super.becomeNative(loader);
+ }
+
+ @override
+ void applyPatch(Builder patch) {
+ if (patch is SourceConstructorBuilder) {
+ if (checkPatch(patch)) {
+ patch.actualOrigin = this;
+ dataForTesting?.patchForTesting = patch;
+ }
+ } else {
+ reportPatchMismatch(patch);
+ }
+ }
+
+ 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;
+ hasMovedSuperInitializer = false;
+ }
+
+ @override
+ List<ClassMember> get localMembers =>
+ throw new UnsupportedError('${runtimeType}.localMembers');
+
+ @override
+ List<ClassMember> get localSetters =>
+ throw new UnsupportedError('${runtimeType}.localSetters');
+
+ /// Registers field as being initialized by this constructor.
+ ///
+ /// The field can be initialized either via an initializing formal or via an
+ /// entry in the constructor initializer list.
+ void registerInitializedField(FieldBuilder fieldBuilder) {
+ (_initializedFields ??= {}).add(fieldBuilder);
+ }
+
+ /// Returns the fields registered as initialized by this constructor.
+ ///
+ /// Returns the set of fields previously registered via
+ /// [registerInitializedField] and passes on the ownership of the collection
+ /// to the caller.
+ Set<FieldBuilder>? takeInitializedFields() {
+ Set<FieldBuilder>? result = _initializedFields;
+ _initializedFields = null;
+ return result;
+ }
+}
+
+class SyntheticConstructorBuilder extends DillConstructorBuilder
+ with SourceMemberBuilderMixin {
+ // TODO(johnniwinther,cstefantsova): Rename [_origin] to avoid the confusion
+ // with patches.
+ // TODO(johnniwinther): Change the type of [_origin] to SourceMemberBuilder
+ // when it's the supertype for both old SourceMemberBuilder and
+ // SyntheticConstructorBuilder.
+ MemberBuilder? _origin;
+ SynthesizedFunctionNode? _synthesizedFunctionNode;
+
+ SyntheticConstructorBuilder(SourceClassBuilder parent,
+ Constructor constructor, Procedure? constructorTearOff,
+ {MemberBuilder? origin, SynthesizedFunctionNode? synthesizedFunctionNode})
+ : _origin = origin,
+ _synthesizedFunctionNode = synthesizedFunctionNode,
+ super(constructor, constructorTearOff, parent);
+
+ // TODO(johnniwinther,cstefantsova): Rename [actualOrigin] to avoid the
+ // confusion with patches.
+ MemberBuilder? get actualOrigin {
+ MemberBuilder? origin = _origin;
+ while (origin is SyntheticConstructorBuilder) {
+ origin = origin._origin;
+ }
+ return origin;
+ }
+
+ List<FormalParameterBuilder>? get formals {
+ MemberBuilder? origin = actualOrigin;
+ return origin is SourceConstructorBuilder ? origin.formals : null;
+ }
+
+ @override
+ void buildOutlineExpressions(
+ SourceLibraryBuilder libraryBuilder,
+ ClassHierarchy classHierarchy,
+ List<DelayedActionPerformer> delayedActionPerformers,
+ List<SynthesizedFunctionNode> synthesizedFunctionNodes) {
+ if (_origin != null) {
+ // Ensure that default value expressions have been created for [_origin].
+ LibraryBuilder originLibraryBuilder = _origin!.library;
+ if (originLibraryBuilder is SourceLibraryBuilder) {
+ // If [_origin] is from a source library, we need to build the default
+ // values and initializers first.
+ MemberBuilder origin = _origin!;
+ if (origin is SourceConstructorBuilder) {
+ origin.buildOutlineExpressions(originLibraryBuilder, classHierarchy,
+ delayedActionPerformers, synthesizedFunctionNodes);
+ } else if (origin is SyntheticConstructorBuilder) {
+ origin.buildOutlineExpressions(originLibraryBuilder, classHierarchy,
+ delayedActionPerformers, synthesizedFunctionNodes);
+ }
+ }
+ addSuperParameterDefaultValueCloners(synthesizedFunctionNodes);
+ _origin = null;
+ }
+ }
+
+ void addSuperParameterDefaultValueCloners(
+ List<SynthesizedFunctionNode> synthesizedFunctionNodes) {
+ MemberBuilder? origin = _origin;
+ if (origin is SourceConstructorBuilder) {
+ origin.addSuperParameterDefaultValueCloners(synthesizedFunctionNodes);
+ } else if (origin is SyntheticConstructorBuilder) {
+ origin.addSuperParameterDefaultValueCloners(synthesizedFunctionNodes);
+ }
+ if (_synthesizedFunctionNode != null) {
+ synthesizedFunctionNodes
+ .add(_synthesizedFunctionNode!..isOutlineNode = true);
+ _synthesizedFunctionNode = null;
+ }
+ }
+}
diff --git a/pkg/front_end/lib/src/fasta/builder/enum_builder.dart b/pkg/front_end/lib/src/fasta/source/source_enum_builder.dart
similarity index 95%
rename from pkg/front_end/lib/src/fasta/builder/enum_builder.dart
rename to pkg/front_end/lib/src/fasta/source/source_enum_builder.dart
index 1253322..112e190 100644
--- a/pkg/front_end/lib/src/fasta/builder/enum_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_enum_builder.dart
@@ -28,9 +28,19 @@
SuperInitializer,
ThisExpression;
import 'package:kernel/class_hierarchy.dart';
-
import 'package:kernel/reference_from_index.dart' show IndexedClass;
+import '../builder/builder.dart';
+import '../builder/class_builder.dart';
+import '../builder/field_builder.dart';
+import '../builder/formal_parameter_builder.dart';
+import '../builder/library_builder.dart';
+import '../builder/member_builder.dart';
+import '../builder/metadata_builder.dart';
+import '../builder/named_type_builder.dart';
+import '../builder/nullability_builder.dart';
+import '../builder/procedure_builder.dart';
+import '../builder/type_builder.dart';
import '../fasta_codes.dart'
show
LocatedMessage,
@@ -39,32 +49,17 @@
templateDuplicatedDeclarationCause,
templateDuplicatedDeclarationSyntheticCause,
templateEnumConstantSameNameAsEnclosing;
-
import '../kernel/constructor_tearoff_lowering.dart';
import '../kernel/kernel_helper.dart';
-
-import '../util/helpers.dart';
-
import '../modifier.dart' show constMask, hasInitializerMask, staticMask;
-
import '../scope.dart';
-
-import '../source/name_scheme.dart';
-import '../source/source_class_builder.dart' show SourceClassBuilder;
-import '../source/source_library_builder.dart' show SourceLibraryBuilder;
-
-import 'builder.dart';
-import 'class_builder.dart';
-import 'constructor_builder.dart';
-import 'field_builder.dart';
-import 'formal_parameter_builder.dart';
-import 'library_builder.dart';
-import 'member_builder.dart';
-import 'metadata_builder.dart';
-import 'named_type_builder.dart';
-import 'nullability_builder.dart';
-import 'procedure_builder.dart';
-import 'type_builder.dart';
+import '../util/helpers.dart';
+import 'name_scheme.dart';
+import 'source_class_builder.dart' show SourceClassBuilder;
+import 'source_constructor_builder.dart';
+import 'source_field_builder.dart';
+import 'source_library_builder.dart' show SourceLibraryBuilder;
+import 'source_procedure_builder.dart';
class EnumBuilder extends SourceClassBuilder {
final List<EnumConstantInfo?>? enumConstantInfos;
diff --git a/pkg/front_end/lib/src/fasta/source/source_extension_builder.dart b/pkg/front_end/lib/src/fasta/source/source_extension_builder.dart
index e17ec41..6a8924b 100644
--- a/pkg/front_end/lib/src/fasta/source/source_extension_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_extension_builder.dart
@@ -7,36 +7,29 @@
import 'package:kernel/type_environment.dart';
import '../../base/common.dart';
-
import '../builder/builder.dart';
import '../builder/class_builder.dart';
import '../builder/extension_builder.dart';
-import '../builder/field_builder.dart';
import '../builder/library_builder.dart';
-import '../builder/member_builder.dart';
import '../builder/metadata_builder.dart';
import '../builder/procedure_builder.dart';
import '../builder/type_builder.dart';
import '../builder/type_variable_builder.dart';
-
import '../fasta_codes.dart'
show
messagePatchDeclarationMismatch,
messagePatchDeclarationOrigin,
noLength,
templateExtensionMemberConflictsWithObjectMember;
-
import '../kernel/kernel_helper.dart';
-
import '../operator.dart';
-
import '../problems.dart';
-
import '../scope.dart';
-
import '../util/helpers.dart';
-
+import 'source_field_builder.dart';
import 'source_library_builder.dart';
+import 'source_member_builder.dart';
+import 'source_procedure_builder.dart';
const String extensionThisName = '#this';
diff --git a/pkg/front_end/lib/src/fasta/builder/factory_builder.dart b/pkg/front_end/lib/src/fasta/source/source_factory_builder.dart
similarity index 96%
rename from pkg/front_end/lib/src/fasta/builder/factory_builder.dart
rename to pkg/front_end/lib/src/fasta/source/source_factory_builder.dart
index 9d3f52d..56e6800 100644
--- a/pkg/front_end/lib/src/fasta/builder/factory_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_factory_builder.dart
@@ -6,8 +6,14 @@
import 'package:kernel/class_hierarchy.dart';
import 'package:kernel/type_algebra.dart';
+import '../builder/builder.dart';
+import '../builder/constructor_reference_builder.dart';
+import '../builder/formal_parameter_builder.dart';
+import '../builder/function_builder.dart';
+import '../builder/metadata_builder.dart';
+import '../builder/type_builder.dart';
+import '../builder/type_variable_builder.dart';
import '../dill/dill_member_builder.dart';
-
import '../kernel/constructor_tearoff_lowering.dart';
import '../kernel/forest.dart';
import '../kernel/hierarchy/class_member.dart';
@@ -15,30 +21,17 @@
import '../kernel/kernel_helper.dart';
import '../kernel/redirecting_factory_body.dart'
show getRedirectingFactoryBody, RedirectingFactoryBody;
-
-import '../source/source_loader.dart' show SourceLoader;
-
import '../messages.dart'
show messageConstFactoryRedirectionToNonConst, noLength;
-
import '../problems.dart' show unexpected, unhandled;
-
-import '../source/name_scheme.dart';
-import '../source/source_library_builder.dart' show SourceLibraryBuilder;
-
import '../type_inference/type_inferrer.dart';
import '../type_inference/type_schema.dart';
-
import '../util/helpers.dart';
-
-import 'builder.dart';
-import 'constructor_reference_builder.dart';
-import 'formal_parameter_builder.dart';
-import 'function_builder.dart';
-import 'member_builder.dart';
-import 'metadata_builder.dart';
-import 'type_builder.dart';
-import 'type_variable_builder.dart';
+import 'name_scheme.dart';
+import 'source_function_builder.dart';
+import 'source_library_builder.dart' show SourceLibraryBuilder;
+import 'source_loader.dart' show SourceLoader;
+import 'source_member_builder.dart';
class SourceFactoryBuilder extends FunctionBuilderImpl {
final int charOpenParenOffset;
diff --git a/pkg/front_end/lib/src/fasta/source/source_field_builder.dart b/pkg/front_end/lib/src/fasta/source/source_field_builder.dart
new file mode 100644
index 0000000..634ffab
--- /dev/null
+++ b/pkg/front_end/lib/src/fasta/source/source_field_builder.dart
@@ -0,0 +1,1812 @@
+// Copyright (c) 2016, 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.
+
+library fasta.field_builder;
+
+import 'package:_fe_analyzer_shared/src/scanner/scanner.dart' show Token;
+import 'package:kernel/ast.dart';
+import 'package:kernel/class_hierarchy.dart';
+import 'package:kernel/core_types.dart';
+import 'package:kernel/src/legacy_erasure.dart';
+import 'package:kernel/type_algebra.dart';
+
+import '../builder/class_builder.dart';
+import '../builder/field_builder.dart';
+import '../builder/member_builder.dart';
+import '../builder/metadata_builder.dart';
+import '../builder/type_builder.dart';
+import '../constant_context.dart' show ConstantContext;
+import '../fasta_codes.dart' show messageInternalProblemAlreadyInitialized;
+import '../kernel/body_builder.dart' show BodyBuilder;
+import '../kernel/hierarchy/class_member.dart';
+import '../kernel/hierarchy/members_builder.dart';
+import '../kernel/implicit_field_type.dart';
+import '../kernel/kernel_helper.dart';
+import '../kernel/late_lowering.dart' as late_lowering;
+import '../kernel/member_covariance.dart';
+import '../modifier.dart' show covariantMask, hasInitializerMask, lateMask;
+import '../problems.dart' show internalProblem;
+import '../scope.dart' show Scope;
+import '../source/name_scheme.dart';
+import '../source/source_extension_builder.dart';
+import '../source/source_library_builder.dart' show SourceLibraryBuilder;
+import '../source/source_loader.dart' show SourceLoader;
+import '../type_inference/type_inference_engine.dart'
+ show IncludesTypeParametersNonCovariantly;
+import '../util/helpers.dart' show DelayedActionPerformer;
+import 'source_member_builder.dart';
+
+class SourceFieldBuilder extends SourceMemberBuilderImpl
+ implements FieldBuilder {
+ @override
+ final String name;
+
+ @override
+ final int modifiers;
+
+ late FieldEncoding _fieldEncoding;
+
+ @override
+ final List<MetadataBuilder>? metadata;
+
+ @override
+ final TypeBuilder? type;
+
+ Token? _constInitializerToken;
+
+ bool hadTypesInferred = false;
+
+ @override
+ bool hasBodyBeenBuilt = false;
+
+ // TODO(johnniwinther): [parent] is not trust-worthy for determining
+ // properties since it is changed after the creation of the builder. For now
+ // we require it has an argument here. A follow-up should clean up the
+ // misuse of parent.
+ @override
+ final bool isTopLevel;
+
+ SourceFieldBuilder(
+ this.metadata,
+ this.type,
+ this.name,
+ this.modifiers,
+ this.isTopLevel,
+ SourceLibraryBuilder libraryBuilder,
+ int charOffset,
+ int charEndOffset,
+ NameScheme fieldNameScheme,
+ {Reference? fieldReference,
+ Reference? fieldGetterReference,
+ Reference? fieldSetterReference,
+ Reference? lateIsSetFieldReference,
+ Reference? lateIsSetGetterReference,
+ Reference? lateIsSetSetterReference,
+ Reference? lateGetterReference,
+ Reference? lateSetterReference,
+ Token? constInitializerToken})
+ : _constInitializerToken = constInitializerToken,
+ super(libraryBuilder, charOffset) {
+ bool isInstanceMember = fieldNameScheme.isInstanceMember;
+
+ Uri fileUri = libraryBuilder.fileUri;
+ // If in mixed mode, late lowerings cannot use `null` as a sentinel on
+ // non-nullable fields since they can be assigned from legacy code.
+ late_lowering.IsSetStrategy isSetStrategy =
+ late_lowering.computeIsSetStrategy(libraryBuilder);
+
+ if (isAbstract || isExternal) {
+ assert(fieldReference == null);
+ assert(lateIsSetFieldReference == null);
+ assert(lateIsSetGetterReference == null);
+ assert(lateIsSetSetterReference == null);
+ assert(lateGetterReference == null);
+ assert(lateSetterReference == null);
+ _fieldEncoding = new AbstractOrExternalFieldEncoding(
+ this,
+ name,
+ fieldNameScheme,
+ fileUri,
+ charOffset,
+ charEndOffset,
+ fieldGetterReference,
+ fieldSetterReference,
+ isAbstract: isAbstract,
+ isExternal: isExternal,
+ isFinal: isFinal,
+ isCovariantByDeclaration: isCovariantByDeclaration,
+ isNonNullableByDefault: library.isNonNullableByDefault);
+ } else if (isLate &&
+ libraryBuilder.loader.target.backendTarget.isLateFieldLoweringEnabled(
+ hasInitializer: hasInitializer,
+ isFinal: isFinal,
+ isStatic: !isInstanceMember)) {
+ if (hasInitializer) {
+ if (isFinal) {
+ _fieldEncoding = new LateFinalFieldWithInitializerEncoding(
+ name,
+ fieldNameScheme,
+ fileUri,
+ charOffset,
+ charEndOffset,
+ fieldReference,
+ fieldGetterReference,
+ fieldSetterReference,
+ lateIsSetFieldReference,
+ lateIsSetGetterReference,
+ lateIsSetSetterReference,
+ lateGetterReference,
+ lateSetterReference,
+ isCovariantByDeclaration,
+ isSetStrategy);
+ } else {
+ _fieldEncoding = new LateFieldWithInitializerEncoding(
+ name,
+ fieldNameScheme,
+ fileUri,
+ charOffset,
+ charEndOffset,
+ fieldReference,
+ fieldGetterReference,
+ fieldSetterReference,
+ lateIsSetFieldReference,
+ lateIsSetGetterReference,
+ lateIsSetSetterReference,
+ lateGetterReference,
+ lateSetterReference,
+ isCovariantByDeclaration,
+ isSetStrategy);
+ }
+ } else {
+ if (isFinal) {
+ _fieldEncoding = new LateFinalFieldWithoutInitializerEncoding(
+ name,
+ fieldNameScheme,
+ fileUri,
+ charOffset,
+ charEndOffset,
+ fieldReference,
+ fieldGetterReference,
+ fieldSetterReference,
+ lateIsSetFieldReference,
+ lateIsSetGetterReference,
+ lateIsSetSetterReference,
+ lateGetterReference,
+ lateSetterReference,
+ isCovariantByDeclaration,
+ isSetStrategy);
+ } else {
+ _fieldEncoding = new LateFieldWithoutInitializerEncoding(
+ name,
+ fieldNameScheme,
+ fileUri,
+ charOffset,
+ charEndOffset,
+ fieldReference,
+ fieldGetterReference,
+ fieldSetterReference,
+ lateIsSetFieldReference,
+ lateIsSetGetterReference,
+ lateIsSetSetterReference,
+ lateGetterReference,
+ lateSetterReference,
+ isCovariantByDeclaration,
+ isSetStrategy);
+ }
+ }
+ } else if (libraryBuilder.isNonNullableByDefault &&
+ libraryBuilder.loader.target.backendTarget.useStaticFieldLowering &&
+ !isInstanceMember &&
+ !isConst &&
+ hasInitializer) {
+ if (isFinal) {
+ _fieldEncoding = new LateFinalFieldWithInitializerEncoding(
+ name,
+ fieldNameScheme,
+ fileUri,
+ charOffset,
+ charEndOffset,
+ fieldReference,
+ fieldGetterReference,
+ fieldSetterReference,
+ lateIsSetFieldReference,
+ lateIsSetGetterReference,
+ lateIsSetSetterReference,
+ lateGetterReference,
+ lateSetterReference,
+ isCovariantByDeclaration,
+ isSetStrategy);
+ } else {
+ _fieldEncoding = new LateFieldWithInitializerEncoding(
+ name,
+ fieldNameScheme,
+ fileUri,
+ charOffset,
+ charEndOffset,
+ fieldReference,
+ fieldGetterReference,
+ fieldSetterReference,
+ lateIsSetFieldReference,
+ lateIsSetGetterReference,
+ lateIsSetSetterReference,
+ lateGetterReference,
+ lateSetterReference,
+ isCovariantByDeclaration,
+ isSetStrategy);
+ }
+ } else {
+ assert(lateIsSetFieldReference == null);
+ assert(lateIsSetGetterReference == null);
+ assert(lateIsSetSetterReference == null);
+ assert(lateGetterReference == null);
+ assert(lateSetterReference == null);
+ _fieldEncoding = new RegularFieldEncoding(
+ name, fieldNameScheme, fileUri, charOffset, charEndOffset,
+ isFinal: isFinal,
+ isConst: isConst,
+ isLate: isLate,
+ hasInitializer: hasInitializer,
+ isNonNullableByDefault: library.isNonNullableByDefault,
+ fieldReference: fieldReference,
+ getterReference: fieldGetterReference,
+ setterReference: fieldSetterReference);
+ }
+ }
+
+ bool get isLateLowered => _fieldEncoding.isLateLowering;
+
+ bool _typeEnsured = false;
+ Set<ClassMember>? _overrideDependencies;
+
+ void registerOverrideDependency(Set<ClassMember> overriddenMembers) {
+ assert(
+ overriddenMembers.every((overriddenMember) =>
+ overriddenMember.classBuilder != classBuilder),
+ "Unexpected override dependencies for $this: $overriddenMembers");
+ _overrideDependencies ??= {};
+ _overrideDependencies!.addAll(overriddenMembers);
+ }
+
+ void _ensureType(ClassMembersBuilder membersBuilder) {
+ if (_typeEnsured) return;
+ if (_overrideDependencies != null) {
+ membersBuilder.inferFieldType(this, _overrideDependencies!);
+ _overrideDependencies = null;
+ } else {
+ inferType();
+ }
+ _typeEnsured = true;
+ }
+
+ @override
+ SourceLibraryBuilder get library => super.library as SourceLibraryBuilder;
+
+ @override
+ Member get member => _fieldEncoding.field;
+
+ @override
+ String get debugName => "FieldBuilder";
+
+ @override
+ bool get isField => true;
+
+ @override
+ bool get isLate => (modifiers & lateMask) != 0;
+
+ @override
+ bool get isCovariantByDeclaration => (modifiers & covariantMask) != 0;
+
+ @override
+ bool get hasInitializer => (modifiers & hasInitializerMask) != 0;
+
+ @override
+ void buildBody(CoreTypes coreTypes, Expression? initializer) {
+ assert(!hasBodyBeenBuilt);
+ hasBodyBeenBuilt = true;
+ if (!hasInitializer &&
+ initializer != null &&
+ initializer is! NullLiteral &&
+ !isConst &&
+ !isFinal) {
+ internalProblem(
+ messageInternalProblemAlreadyInitialized, charOffset, fileUri);
+ }
+ _fieldEncoding.createBodies(coreTypes, initializer);
+ }
+
+ @override
+ List<Initializer> buildInitializer(int fileOffset, Expression value,
+ {required bool isSynthetic}) {
+ return _fieldEncoding.createInitializer(fileOffset, value,
+ isSynthetic: isSynthetic);
+ }
+
+ @override
+ bool get isEligibleForInference {
+ return type == null && (hasInitializer || isClassInstanceMember);
+ }
+
+ @override
+ bool get isAssignable {
+ if (isConst) return false;
+ if (isFinal) {
+ if (isLate) {
+ return !hasInitializer;
+ }
+ return false;
+ }
+ return true;
+ }
+
+ @override
+ Field get field => _fieldEncoding.field;
+
+ @override
+ Member get readTarget => _fieldEncoding.readTarget;
+
+ @override
+ Member? get writeTarget {
+ return isAssignable ? _fieldEncoding.writeTarget : null;
+ }
+
+ @override
+ Member get invokeTarget => readTarget;
+
+ @override
+ Iterable<Member> get exportedMembers => _fieldEncoding.exportedMembers;
+
+ @override
+ void buildMembers(
+ SourceLibraryBuilder library, void Function(Member, BuiltMemberKind) f) {
+ build(library);
+ _fieldEncoding.registerMembers(library, this, f);
+ }
+
+ /// Builds the core AST structures for this field as needed for the outline.
+ void build(SourceLibraryBuilder libraryBuilder) {
+ if (type != null) {
+ fieldType = type!.build(libraryBuilder);
+ }
+ _fieldEncoding.build(libraryBuilder, this);
+ }
+
+ @override
+ void buildOutlineExpressions(
+ SourceLibraryBuilder library,
+ ClassHierarchy classHierarchy,
+ List<DelayedActionPerformer> delayedActionPerformers,
+ List<SynthesizedFunctionNode> synthesizedFunctionNodes) {
+ _fieldEncoding.completeSignature(classHierarchy.coreTypes);
+
+ for (Annotatable annotatable in _fieldEncoding.annotatables) {
+ MetadataBuilder.buildAnnotations(
+ annotatable,
+ metadata,
+ library,
+ declarationBuilder,
+ this,
+ fileUri,
+ declarationBuilder?.scope ?? library.scope);
+ }
+
+ // For modular compilation we need to include initializers of all const
+ // fields and all non-static final fields in classes with const constructors
+ // into the outline.
+ if ((isConst ||
+ (isFinal &&
+ !isStatic &&
+ isClassMember &&
+ classBuilder!.declaresConstConstructor)) &&
+ _constInitializerToken != null) {
+ Scope scope = declarationBuilder?.scope ?? library.scope;
+ BodyBuilder bodyBuilder = library.loader
+ .createBodyBuilderForOutlineExpression(
+ library, declarationBuilder, this, scope, fileUri);
+ bodyBuilder.constantContext =
+ isConst ? ConstantContext.inferred : ConstantContext.required;
+ Expression initializer = bodyBuilder.typeInferrer.inferFieldInitializer(
+ bodyBuilder,
+ fieldType,
+ bodyBuilder.parseFieldInitializer(_constInitializerToken!));
+ if (bodyBuilder.transformSetLiterals ||
+ bodyBuilder.transformCollections) {
+ // Wrap the initializer in a temporary parent expression; the
+ // transformations need a parent relation.
+ Not wrapper = new Not(initializer);
+ SourceLoader loader = library.loader;
+ loader.transformPostInference(wrapper, bodyBuilder.transformSetLiterals,
+ bodyBuilder.transformCollections, library.library);
+ initializer = wrapper.operand;
+ }
+ buildBody(classHierarchy.coreTypes, initializer);
+ bodyBuilder.performBacklogComputations(delayedActionPerformers);
+ }
+ _constInitializerToken = null;
+ }
+
+ @override
+ DartType get fieldType => _fieldEncoding.type;
+
+ void set fieldType(DartType value) {
+ _fieldEncoding.type = value;
+ if (!isFinal && !isConst && parent is ClassBuilder) {
+ Class enclosingClass = classBuilder!.cls;
+ if (enclosingClass.typeParameters.isNotEmpty) {
+ IncludesTypeParametersNonCovariantly needsCheckVisitor =
+ new IncludesTypeParametersNonCovariantly(
+ enclosingClass.typeParameters,
+ // We are checking the field type as if it is the type of the
+ // parameter of the implicit setter and this is a contravariant
+ // position.
+ initialVariance: Variance.contravariant);
+ if (value.accept(needsCheckVisitor)) {
+ _fieldEncoding.setGenericCovariantImpl();
+ }
+ }
+ }
+ }
+
+ @override
+ DartType inferType() {
+ SourceLibraryBuilder library = this.library;
+ if (fieldType is! ImplicitFieldType) {
+ // We have already inferred a type.
+ return fieldType;
+ }
+
+ ImplicitFieldType implicitFieldType = fieldType as ImplicitFieldType;
+ DartType inferredType = implicitFieldType.computeType();
+ if (fieldType is ImplicitFieldType) {
+ // `fieldType` may have changed if a circularity was detected when
+ // [inferredType] was computed.
+ if (!library.isNonNullableByDefault) {
+ inferredType = legacyErasure(inferredType);
+ }
+ fieldType = implicitFieldType.checkInferred(inferredType);
+
+ IncludesTypeParametersNonCovariantly? needsCheckVisitor;
+ if (parent is ClassBuilder) {
+ Class enclosingClass = classBuilder!.cls;
+ if (enclosingClass.typeParameters.isNotEmpty) {
+ needsCheckVisitor = new IncludesTypeParametersNonCovariantly(
+ enclosingClass.typeParameters,
+ // We are checking the field type as if it is the type of the
+ // parameter of the implicit setter and this is a contravariant
+ // position.
+ initialVariance: Variance.contravariant);
+ }
+ }
+ if (needsCheckVisitor != null) {
+ if (fieldType.accept(needsCheckVisitor)) {
+ _fieldEncoding.setGenericCovariantImpl();
+ }
+ }
+ }
+ return fieldType;
+ }
+
+ @override
+ DartType get builtType => fieldType;
+
+ List<ClassMember>? _localMembers;
+ List<ClassMember>? _localSetters;
+
+ @override
+ List<ClassMember> get localMembers =>
+ _localMembers ??= _fieldEncoding.getLocalMembers(this);
+
+ @override
+ List<ClassMember> get localSetters =>
+ _localSetters ??= _fieldEncoding.getLocalSetters(this);
+}
+
+/// Strategy pattern for creating different encodings of a declared field.
+///
+/// This is used to provide lowerings for late fields using synthesized getters
+/// and setters.
+abstract class FieldEncoding {
+ /// The type of the declared field.
+ abstract DartType type;
+
+ /// Creates the bodies needed for the field encoding using [initializer] as
+ /// the declared initializer expression.
+ ///
+ /// This method is not called for fields in outlines unless their are constant
+ /// or part of a const constructor.
+ void createBodies(CoreTypes coreTypes, Expression? initializer);
+
+ List<Initializer> createInitializer(int fileOffset, Expression value,
+ {required bool isSynthetic});
+
+ /// Registers that the (implicit) setter associated with this field needs to
+ /// contain a runtime type check to deal with generic covariance.
+ void setGenericCovariantImpl();
+
+ /// Returns the field that holds the field value at runtime.
+ Field get field;
+
+ /// Returns the members that holds the field annotations.
+ Iterable<Annotatable> get annotatables;
+
+ /// Returns the member used to read the field value.
+ Member get readTarget;
+
+ /// Returns the member used to write to the field.
+ Member? get writeTarget;
+
+ /// Returns the generated members that are visible through exports.
+ Iterable<Member> get exportedMembers;
+
+ /// Creates the members necessary for this field encoding.
+ ///
+ /// This method is called for both outline and full compilation so the created
+ /// members should be without body. The member bodies are created through
+ /// [createBodies].
+ void build(
+ SourceLibraryBuilder libraryBuilder, SourceFieldBuilder fieldBuilder);
+
+ /// Calls [f] for each member needed for this field encoding.
+ void registerMembers(
+ SourceLibraryBuilder library,
+ SourceFieldBuilder fieldBuilder,
+ void Function(Member, BuiltMemberKind) f);
+
+ /// Returns a list of the field, getters and methods created by this field
+ /// encoding.
+ List<ClassMember> getLocalMembers(SourceFieldBuilder fieldBuilder);
+
+ /// Returns a list of the setters created by this field encoding.
+ List<ClassMember> getLocalSetters(SourceFieldBuilder fieldBuilder);
+
+ /// Ensures that the signatures all members created by this field encoding
+ /// are fully typed.
+ void completeSignature(CoreTypes coreTypes);
+
+ /// Returns `true` if this encoding is a late lowering.
+ bool get isLateLowering;
+}
+
+class RegularFieldEncoding implements FieldEncoding {
+ late final Field _field;
+
+ RegularFieldEncoding(String name, NameScheme nameScheme, Uri fileUri,
+ int charOffset, int charEndOffset,
+ {required bool isFinal,
+ required bool isConst,
+ required bool isLate,
+ required bool hasInitializer,
+ required bool isNonNullableByDefault,
+ required Reference? fieldReference,
+ required Reference? getterReference,
+ required Reference? setterReference}) {
+ // ignore: unnecessary_null_comparison
+ assert(isFinal != null);
+ // ignore: unnecessary_null_comparison
+ assert(isConst != null);
+ // ignore: unnecessary_null_comparison
+ assert(isLate != null);
+ // ignore: unnecessary_null_comparison
+ assert(hasInitializer != null);
+ bool isImmutable =
+ isLate ? (isFinal && hasInitializer) : (isFinal || isConst);
+ _field = isImmutable
+ ? new Field.immutable(
+ nameScheme.getFieldName(FieldNameType.Field, name,
+ isSynthesized: false),
+ isFinal: isFinal,
+ isConst: isConst,
+ isLate: isLate,
+ fileUri: fileUri,
+ fieldReference: fieldReference,
+ getterReference: getterReference)
+ : new Field.mutable(
+ nameScheme.getFieldName(FieldNameType.Field, name,
+ isSynthesized: false),
+ isFinal: isFinal,
+ isLate: isLate,
+ fileUri: fileUri,
+ fieldReference: fieldReference,
+ getterReference: getterReference,
+ setterReference: setterReference);
+ _field
+ ..fileOffset = charOffset
+ ..fileEndOffset = charEndOffset
+ ..isNonNullableByDefault = isNonNullableByDefault;
+ }
+
+ @override
+ DartType get type => _field.type;
+
+ @override
+ void set type(DartType value) {
+ _field.type = value;
+ }
+
+ @override
+ void completeSignature(CoreTypes coreTypes) {}
+
+ @override
+ void createBodies(CoreTypes coreTypes, Expression? initializer) {
+ if (initializer != null) {
+ _field.initializer = initializer..parent = _field;
+ }
+ }
+
+ @override
+ List<Initializer> createInitializer(int fileOffset, Expression value,
+ {required bool isSynthetic}) {
+ return <Initializer>[
+ new FieldInitializer(_field, value)
+ ..fileOffset = fileOffset
+ ..isSynthetic = isSynthetic
+ ];
+ }
+
+ @override
+ void build(
+ SourceLibraryBuilder libraryBuilder, SourceFieldBuilder fieldBuilder) {
+ _field..isCovariantByDeclaration = fieldBuilder.isCovariantByDeclaration;
+ if (fieldBuilder.isExtensionMember) {
+ _field
+ ..isStatic = true
+ ..isExtensionMember = true;
+ } else {
+ bool isInstanceMember =
+ !fieldBuilder.isStatic && !fieldBuilder.isTopLevel;
+ _field
+ ..isStatic = !isInstanceMember
+ ..isExtensionMember = false;
+ }
+ _field.isLate = fieldBuilder.isLate;
+ updatePrivateMemberName(_field, libraryBuilder);
+ }
+
+ @override
+ void registerMembers(
+ SourceLibraryBuilder library,
+ SourceFieldBuilder fieldBuilder,
+ void Function(Member, BuiltMemberKind) f) {
+ f(
+ _field,
+ fieldBuilder.isExtensionMember
+ ? BuiltMemberKind.ExtensionField
+ : BuiltMemberKind.Field);
+ }
+
+ @override
+ void setGenericCovariantImpl() {
+ _field.isCovariantByClass = true;
+ }
+
+ @override
+ Field get field => _field;
+
+ @override
+ Iterable<Annotatable> get annotatables => [_field];
+
+ @override
+ Member get readTarget => _field;
+
+ @override
+ Member get writeTarget => _field;
+
+ @override
+ Iterable<Member> get exportedMembers => [_field];
+
+ @override
+ List<ClassMember> getLocalMembers(SourceFieldBuilder fieldBuilder) =>
+ <ClassMember>[new SourceFieldMember(fieldBuilder, forSetter: false)];
+
+ @override
+ List<ClassMember> getLocalSetters(SourceFieldBuilder fieldBuilder) =>
+ fieldBuilder.isAssignable
+ ? <ClassMember>[new SourceFieldMember(fieldBuilder, forSetter: true)]
+ : const <ClassMember>[];
+
+ @override
+ bool get isLateLowering => false;
+}
+
+class SourceFieldMember extends BuilderClassMember {
+ @override
+ final SourceFieldBuilder memberBuilder;
+
+ Covariance? _covariance;
+
+ @override
+ final bool forSetter;
+
+ SourceFieldMember(this.memberBuilder, {required this.forSetter})
+ // ignore: unnecessary_null_comparison
+ : assert(forSetter != null);
+
+ @override
+ void inferType(ClassMembersBuilder membersBuilder) {
+ memberBuilder._ensureType(membersBuilder);
+ }
+
+ @override
+ void registerOverrideDependency(Set<ClassMember> overriddenMembers) {
+ memberBuilder.registerOverrideDependency(overriddenMembers);
+ }
+
+ @override
+ Member getMember(ClassMembersBuilder membersBuilder) {
+ memberBuilder._ensureType(membersBuilder);
+ return memberBuilder.field;
+ }
+
+ @override
+ Covariance getCovariance(ClassMembersBuilder membersBuilder) {
+ return _covariance ??= forSetter
+ ? new Covariance.fromMember(getMember(membersBuilder),
+ forSetter: forSetter)
+ : const Covariance.empty();
+ }
+
+ @override
+ bool get isSourceDeclaration => true;
+
+ @override
+ bool get isProperty => true;
+
+ @override
+ bool isSameDeclaration(ClassMember other) {
+ return other is SourceFieldMember && memberBuilder == other.memberBuilder;
+ }
+}
+
+abstract class AbstractLateFieldEncoding implements FieldEncoding {
+ final String name;
+ final int fileOffset;
+ final int fileEndOffset;
+ DartType? _type;
+ late final Field _field;
+ Field? _lateIsSetField;
+ late Procedure _lateGetter;
+ Procedure? _lateSetter;
+
+ // If `true`, an isSet field is used even when the type of the field is
+ // not potentially nullable.
+ //
+ // This is used to force use isSet fields in mixed mode encoding since
+ // we cannot trust non-nullable fields to be initialized with non-null values.
+ final late_lowering.IsSetStrategy _isSetStrategy;
+ late_lowering.IsSetEncoding? _isSetEncoding;
+
+ // If `true`, the is-set field was register before the type was known to be
+ // nullable or non-nullable. In this case we do not try to remove it from
+ // the generated AST to avoid inconsistency between the class hierarchy used
+ // during and after inference.
+ //
+ // This is also used to force use isSet fields in mixed mode encoding since
+ // we cannot trust non-nullable fields to be initialized with non-null values.
+ bool _forceIncludeIsSetField;
+
+ AbstractLateFieldEncoding(
+ this.name,
+ NameScheme nameScheme,
+ Uri fileUri,
+ int charOffset,
+ int charEndOffset,
+ Reference? fieldReference,
+ Reference? fieldGetterReference,
+ Reference? fieldSetterReference,
+ Reference? lateIsSetFieldReference,
+ Reference? lateIsSetGetterReference,
+ Reference? lateIsSetSetterReference,
+ Reference? lateGetterReference,
+ Reference? lateSetterReference,
+ bool isCovariantByDeclaration,
+ late_lowering.IsSetStrategy isSetStrategy)
+ : fileOffset = charOffset,
+ fileEndOffset = charEndOffset,
+ _isSetStrategy = isSetStrategy,
+ _forceIncludeIsSetField =
+ isSetStrategy == late_lowering.IsSetStrategy.forceUseIsSetField {
+ _field = new Field.mutable(
+ nameScheme.getFieldName(FieldNameType.Field, name, isSynthesized: true),
+ fileUri: fileUri,
+ fieldReference: fieldReference,
+ getterReference: fieldGetterReference,
+ setterReference: fieldSetterReference)
+ ..fileOffset = charOffset
+ ..fileEndOffset = charEndOffset
+ ..isNonNullableByDefault = true
+ ..isInternalImplementation = true;
+ switch (_isSetStrategy) {
+ case late_lowering.IsSetStrategy.useSentinelOrNull:
+ case late_lowering.IsSetStrategy.forceUseSentinel:
+ // [_lateIsSetField] is never needed.
+ break;
+ case late_lowering.IsSetStrategy.forceUseIsSetField:
+ case late_lowering.IsSetStrategy.useIsSetFieldOrNull:
+ _lateIsSetField = new Field.mutable(
+ nameScheme.getFieldName(FieldNameType.IsSetField, name,
+ isSynthesized: true),
+ fileUri: fileUri,
+ fieldReference: lateIsSetFieldReference,
+ getterReference: lateIsSetGetterReference,
+ setterReference: lateIsSetSetterReference)
+ ..fileOffset = charOffset
+ ..fileEndOffset = charEndOffset
+ ..isNonNullableByDefault = true
+ ..isInternalImplementation = true;
+ break;
+ }
+ _lateGetter = new Procedure(
+ nameScheme.getFieldName(FieldNameType.Getter, name,
+ isSynthesized: true),
+ ProcedureKind.Getter,
+ new FunctionNode(null)
+ ..fileOffset = charOffset
+ ..fileEndOffset = charEndOffset,
+ fileUri: fileUri,
+ reference: lateGetterReference)
+ ..fileOffset = charOffset
+ ..fileEndOffset = charEndOffset
+ ..isNonNullableByDefault = true;
+ _lateSetter = _createSetter(
+ nameScheme.getFieldName(FieldNameType.Setter, name,
+ isSynthesized: true),
+ fileUri,
+ charOffset,
+ lateSetterReference,
+ isCovariantByDeclaration: isCovariantByDeclaration);
+ }
+
+ late_lowering.IsSetEncoding get isSetEncoding {
+ assert(_type != null, "Type has not been computed for field $name.");
+ return _isSetEncoding ??=
+ late_lowering.computeIsSetEncoding(_type!, _isSetStrategy);
+ }
+
+ @override
+ void completeSignature(CoreTypes coreTypes) {
+ _lateIsSetField?.type = coreTypes.boolRawType(Nullability.nonNullable);
+ }
+
+ @override
+ void createBodies(CoreTypes coreTypes, Expression? initializer) {
+ assert(_type != null, "Type has not been computed for field $name.");
+ if (isSetEncoding == late_lowering.IsSetEncoding.useSentinel) {
+ _field.initializer = new StaticInvocation(coreTypes.createSentinelMethod,
+ new Arguments([], types: [_type!])..fileOffset = fileOffset)
+ ..fileOffset = fileOffset
+ ..parent = _field;
+ } else {
+ _field.initializer = new NullLiteral()
+ ..fileOffset = fileOffset
+ ..parent = _field;
+ }
+ if (_lateIsSetField != null) {
+ _lateIsSetField!.initializer = new BoolLiteral(false)
+ ..fileOffset = fileOffset
+ ..parent = _lateIsSetField;
+ }
+ _lateGetter.function.body = _createGetterBody(coreTypes, name, initializer)
+ ..parent = _lateGetter.function;
+ if (_lateSetter != null) {
+ _lateSetter!.function.body = _createSetterBody(
+ coreTypes, name, _lateSetter!.function.positionalParameters.first)
+ ..parent = _lateSetter!.function;
+ }
+ }
+
+ @override
+ List<Initializer> createInitializer(int fileOffset, Expression value,
+ {required bool isSynthetic}) {
+ List<Initializer> initializers = <Initializer>[];
+ if (_lateIsSetField != null) {
+ initializers.add(new FieldInitializer(
+ _lateIsSetField!, new BoolLiteral(true)..fileOffset = fileOffset)
+ ..fileOffset = fileOffset
+ ..isSynthetic = isSynthetic);
+ }
+ initializers.add(new FieldInitializer(_field, value)
+ ..fileOffset = fileOffset
+ ..isSynthetic = isSynthetic);
+ return initializers;
+ }
+
+ /// Creates an [Expression] that reads [_field].
+ ///
+ /// If [needsPromotion] is `true`, the field will be read through a `let`
+ /// expression that promotes the expression to [_type]. This is needed for a
+ /// sound encoding of fields with type variable type of undetermined
+ /// nullability.
+ Expression _createFieldRead({bool needsPromotion: false}) {
+ assert(_type != null, "Type has not been computed for field $name.");
+ if (needsPromotion) {
+ VariableDeclaration variable = new VariableDeclaration.forValue(
+ _createFieldGet(_field),
+ type: _type!.withDeclaredNullability(Nullability.nullable))
+ ..fileOffset = fileOffset;
+ return new Let(
+ variable, new VariableGet(variable, _type)..fileOffset = fileOffset);
+ } else {
+ return _createFieldGet(_field);
+ }
+ }
+
+ /// Creates an [Expression] that reads [field].
+ Expression _createFieldGet(Field field) {
+ if (field.isStatic) {
+ return new StaticGet(field)..fileOffset = fileOffset;
+ } else {
+ // No substitution needed for the result type, since any type variables
+ // in there are also in scope at the access site.
+ return new InstanceGet(InstanceAccessKind.Instance,
+ new ThisExpression()..fileOffset = fileOffset, field.name,
+ interfaceTarget: field, resultType: field.type)
+ ..fileOffset = fileOffset;
+ }
+ }
+
+ /// Creates an [Expression] that writes [value] to [field].
+ Expression _createFieldSet(Field field, Expression value) {
+ if (field.isStatic) {
+ return new StaticSet(field, value)..fileOffset = fileOffset;
+ } else {
+ return new InstanceSet(InstanceAccessKind.Instance,
+ new ThisExpression()..fileOffset = fileOffset, field.name, value,
+ interfaceTarget: field)
+ ..fileOffset = fileOffset;
+ }
+ }
+
+ Statement _createGetterBody(
+ CoreTypes coreTypes, String name, Expression? initializer);
+
+ Procedure? _createSetter(
+ Name name, Uri fileUri, int charOffset, Reference? reference,
+ {required bool isCovariantByDeclaration}) {
+ // ignore: unnecessary_null_comparison
+ assert(isCovariantByDeclaration != null);
+ VariableDeclaration parameter = new VariableDeclaration(null)
+ ..isCovariantByDeclaration = isCovariantByDeclaration
+ ..fileOffset = fileOffset;
+ return new Procedure(
+ name,
+ ProcedureKind.Setter,
+ new FunctionNode(null,
+ positionalParameters: [parameter], returnType: const VoidType())
+ ..fileOffset = charOffset
+ ..fileEndOffset = fileEndOffset,
+ fileUri: fileUri,
+ reference: reference)
+ ..fileOffset = charOffset
+ ..fileEndOffset = fileEndOffset
+ ..isNonNullableByDefault = true;
+ }
+
+ Statement _createSetterBody(
+ CoreTypes coreTypes, String name, VariableDeclaration parameter);
+
+ @override
+ DartType get type {
+ assert(_type != null, "Type has not been computed for field $name.");
+ return _type!;
+ }
+
+ @override
+ void set type(DartType value) {
+ assert(_type == null || _type is ImplicitFieldType,
+ "Type has already been computed for field $name.");
+ _type = value;
+ if (value is! ImplicitFieldType) {
+ _field.type = value.withDeclaredNullability(Nullability.nullable);
+ _lateGetter.function.returnType = value;
+ if (_lateSetter != null) {
+ _lateSetter!.function.positionalParameters.single.type = value;
+ }
+ if (!_type!.isPotentiallyNullable && !_forceIncludeIsSetField) {
+ // We only need the is-set field if the field is potentially nullable.
+ // Otherwise we use `null` to signal that the field is uninitialized.
+ _lateIsSetField = null;
+ }
+ }
+ }
+
+ @override
+ void setGenericCovariantImpl() {
+ _field.isCovariantByClass = true;
+ _lateSetter?.function.positionalParameters.single.isCovariantByClass = true;
+ }
+
+ @override
+ Field get field => _field;
+
+ @override
+ Iterable<Annotatable> get annotatables {
+ List<Annotatable> list = [_lateGetter];
+ if (_lateSetter != null) {
+ list.add(_lateSetter!);
+ }
+ return list;
+ }
+
+ @override
+ Member get readTarget => _lateGetter;
+
+ @override
+ Member? get writeTarget => _lateSetter;
+
+ @override
+ Iterable<Member> get exportedMembers {
+ if (_lateSetter != null) {
+ return [_lateGetter, _lateSetter!];
+ }
+ return [_lateGetter];
+ }
+
+ @override
+ void build(
+ SourceLibraryBuilder libraryBuilder, SourceFieldBuilder fieldBuilder) {
+ bool isInstanceMember;
+ bool isExtensionMember = fieldBuilder.isExtensionMember;
+ if (isExtensionMember) {
+ _field
+ ..isStatic = true
+ ..isExtensionMember = isExtensionMember;
+ isInstanceMember = false;
+ } else {
+ isInstanceMember = !fieldBuilder.isStatic && !fieldBuilder.isTopLevel;
+ _field
+ ..isStatic = !isInstanceMember
+ ..isExtensionMember = false;
+ }
+ updatePrivateMemberName(_field, libraryBuilder);
+ if (_lateIsSetField != null) {
+ _lateIsSetField!
+ ..isStatic = !isInstanceMember
+ ..isStatic = _field.isStatic
+ ..isExtensionMember = isExtensionMember;
+ updatePrivateMemberName(_lateIsSetField!, libraryBuilder);
+ }
+ _lateGetter
+ ..isStatic = !isInstanceMember
+ ..isExtensionMember = isExtensionMember;
+ updatePrivateMemberName(_lateGetter, libraryBuilder);
+ if (_lateSetter != null) {
+ _lateSetter!
+ ..isStatic = !isInstanceMember
+ ..isExtensionMember = isExtensionMember;
+ updatePrivateMemberName(_lateSetter!, libraryBuilder);
+ }
+ }
+
+ @override
+ void registerMembers(
+ SourceLibraryBuilder library,
+ SourceFieldBuilder fieldBuilder,
+ void Function(Member, BuiltMemberKind) f) {
+ f(
+ _field,
+ fieldBuilder.isExtensionMember
+ ? BuiltMemberKind.ExtensionField
+ : BuiltMemberKind.Field);
+ if (_lateIsSetField != null) {
+ _forceIncludeIsSetField = true;
+ f(_lateIsSetField!, BuiltMemberKind.LateIsSetField);
+ }
+ f(_lateGetter, BuiltMemberKind.LateGetter);
+ if (_lateSetter != null) {
+ f(_lateSetter!, BuiltMemberKind.LateSetter);
+ }
+ }
+
+ @override
+ List<ClassMember> getLocalMembers(SourceFieldBuilder fieldBuilder) {
+ List<ClassMember> list = <ClassMember>[
+ new _SynthesizedFieldClassMember(
+ fieldBuilder, field, _SynthesizedFieldMemberKind.LateField,
+ isInternalImplementation: true),
+ new _SynthesizedFieldClassMember(fieldBuilder, _lateGetter,
+ _SynthesizedFieldMemberKind.LateGetterSetter,
+ isInternalImplementation: false)
+ ];
+ if (_lateIsSetField != null) {
+ list.add(new _SynthesizedFieldClassMember(
+ fieldBuilder, _lateIsSetField!, _SynthesizedFieldMemberKind.LateIsSet,
+ isInternalImplementation: true));
+ }
+ return list;
+ }
+
+ @override
+ List<ClassMember> getLocalSetters(SourceFieldBuilder fieldBuilder) {
+ List<ClassMember> list = <ClassMember>[
+ new _SynthesizedFieldClassMember(
+ fieldBuilder, field, _SynthesizedFieldMemberKind.LateField,
+ forSetter: true, isInternalImplementation: true),
+ ];
+ if (_lateIsSetField != null) {
+ list.add(new _SynthesizedFieldClassMember(
+ fieldBuilder, _lateIsSetField!, _SynthesizedFieldMemberKind.LateIsSet,
+ forSetter: true, isInternalImplementation: true));
+ }
+ if (_lateSetter != null) {
+ list.add(new _SynthesizedFieldClassMember(fieldBuilder, _lateSetter!,
+ _SynthesizedFieldMemberKind.LateGetterSetter,
+ forSetter: true, isInternalImplementation: false));
+ }
+ return list;
+ }
+
+ @override
+ bool get isLateLowering => true;
+}
+
+mixin NonFinalLate on AbstractLateFieldEncoding {
+ @override
+ Statement _createSetterBody(
+ CoreTypes coreTypes, String name, VariableDeclaration parameter) {
+ assert(_type != null, "Type has not been computed for field $name.");
+ return late_lowering.createSetterBody(
+ coreTypes, fileOffset, name, parameter, _type!,
+ shouldReturnValue: false,
+ createVariableWrite: (Expression value) =>
+ _createFieldSet(_field, value),
+ createIsSetWrite: (Expression value) =>
+ _createFieldSet(_lateIsSetField!, value),
+ isSetEncoding: isSetEncoding);
+ }
+}
+
+mixin LateWithoutInitializer on AbstractLateFieldEncoding {
+ @override
+ Statement _createGetterBody(
+ CoreTypes coreTypes, String name, Expression? initializer) {
+ assert(_type != null, "Type has not been computed for field $name.");
+ return late_lowering.createGetterBodyWithoutInitializer(
+ coreTypes, fileOffset, name, type,
+ createVariableRead: _createFieldRead,
+ createIsSetRead: () => _createFieldGet(_lateIsSetField!),
+ isSetEncoding: isSetEncoding,
+ forField: true);
+ }
+}
+
+class LateFieldWithoutInitializerEncoding extends AbstractLateFieldEncoding
+ with NonFinalLate, LateWithoutInitializer {
+ LateFieldWithoutInitializerEncoding(
+ String name,
+ NameScheme nameScheme,
+ Uri fileUri,
+ int charOffset,
+ int charEndOffset,
+ Reference? fieldReference,
+ Reference? fieldGetterReference,
+ Reference? fieldSetterReference,
+ Reference? lateIsSetFieldReference,
+ Reference? lateIsSetGetterReference,
+ Reference? lateIsSetSetterReference,
+ Reference? lateGetterReference,
+ Reference? lateSetterReference,
+ bool isCovariantByDeclaration,
+ late_lowering.IsSetStrategy isSetStrategy)
+ : super(
+ name,
+ nameScheme,
+ fileUri,
+ charOffset,
+ charEndOffset,
+ fieldReference,
+ fieldGetterReference,
+ fieldSetterReference,
+ lateIsSetFieldReference,
+ lateIsSetGetterReference,
+ lateIsSetSetterReference,
+ lateGetterReference,
+ lateSetterReference,
+ isCovariantByDeclaration,
+ isSetStrategy);
+}
+
+class LateFieldWithInitializerEncoding extends AbstractLateFieldEncoding
+ with NonFinalLate {
+ LateFieldWithInitializerEncoding(
+ String name,
+ NameScheme nameScheme,
+ Uri fileUri,
+ int charOffset,
+ int charEndOffset,
+ Reference? fieldReference,
+ Reference? fieldGetterReference,
+ Reference? fieldSetterReference,
+ Reference? lateIsSetFieldReference,
+ Reference? lateIsSetGetterReference,
+ Reference? lateIsSetSetterReference,
+ Reference? lateGetterReference,
+ Reference? lateSetterReference,
+ bool isCovariantByDeclaration,
+ late_lowering.IsSetStrategy isSetStrategy)
+ : super(
+ name,
+ nameScheme,
+ fileUri,
+ charOffset,
+ charEndOffset,
+ fieldReference,
+ fieldGetterReference,
+ fieldSetterReference,
+ lateIsSetFieldReference,
+ lateIsSetGetterReference,
+ lateIsSetSetterReference,
+ lateGetterReference,
+ lateSetterReference,
+ isCovariantByDeclaration,
+ isSetStrategy);
+
+ @override
+ Statement _createGetterBody(
+ CoreTypes coreTypes, String name, Expression? initializer) {
+ assert(_type != null, "Type has not been computed for field $name.");
+ return late_lowering.createGetterWithInitializer(
+ coreTypes, fileOffset, name, _type!, initializer!,
+ createVariableRead: _createFieldRead,
+ createVariableWrite: (Expression value) =>
+ _createFieldSet(_field, value),
+ createIsSetRead: () => _createFieldGet(_lateIsSetField!),
+ createIsSetWrite: (Expression value) =>
+ _createFieldSet(_lateIsSetField!, value),
+ isSetEncoding: isSetEncoding);
+ }
+}
+
+class LateFinalFieldWithoutInitializerEncoding extends AbstractLateFieldEncoding
+ with LateWithoutInitializer {
+ LateFinalFieldWithoutInitializerEncoding(
+ String name,
+ NameScheme nameScheme,
+ Uri fileUri,
+ int charOffset,
+ int charEndOffset,
+ Reference? fieldReference,
+ Reference? fieldGetterReference,
+ Reference? fieldSetterReference,
+ Reference? lateIsSetFieldReference,
+ Reference? lateIsSetGetterReference,
+ Reference? lateIsSetSetterReference,
+ Reference? lateGetterReference,
+ Reference? lateSetterReference,
+ bool isCovariantByDeclaration,
+ late_lowering.IsSetStrategy isSetStrategy)
+ : super(
+ name,
+ nameScheme,
+ fileUri,
+ charOffset,
+ charEndOffset,
+ fieldReference,
+ fieldGetterReference,
+ fieldSetterReference,
+ lateIsSetFieldReference,
+ lateIsSetGetterReference,
+ lateIsSetSetterReference,
+ lateGetterReference,
+ lateSetterReference,
+ isCovariantByDeclaration,
+ isSetStrategy);
+
+ @override
+ Statement _createSetterBody(
+ CoreTypes coreTypes, String name, VariableDeclaration parameter) {
+ assert(_type != null, "Type has not been computed for field $name.");
+ return late_lowering.createSetterBodyFinal(
+ coreTypes, fileOffset, name, parameter, type,
+ shouldReturnValue: false,
+ createVariableRead: () => _createFieldGet(_field),
+ createVariableWrite: (Expression value) =>
+ _createFieldSet(_field, value),
+ createIsSetRead: () => _createFieldGet(_lateIsSetField!),
+ createIsSetWrite: (Expression value) =>
+ _createFieldSet(_lateIsSetField!, value),
+ isSetEncoding: isSetEncoding,
+ forField: true);
+ }
+}
+
+class LateFinalFieldWithInitializerEncoding extends AbstractLateFieldEncoding {
+ LateFinalFieldWithInitializerEncoding(
+ String name,
+ NameScheme nameScheme,
+ Uri fileUri,
+ int charOffset,
+ int charEndOffset,
+ Reference? fieldReference,
+ Reference? fieldGetterReference,
+ Reference? fieldSetterReference,
+ Reference? lateIsSetFieldReference,
+ Reference? lateIsSetGetterReference,
+ Reference? lateIsSetSetterReference,
+ Reference? lateGetterReference,
+ Reference? lateSetterReference,
+ bool isCovariantByDeclaration,
+ late_lowering.IsSetStrategy isSetStrategy)
+ : super(
+ name,
+ nameScheme,
+ fileUri,
+ charOffset,
+ charEndOffset,
+ fieldReference,
+ fieldGetterReference,
+ fieldSetterReference,
+ lateIsSetFieldReference,
+ lateIsSetGetterReference,
+ lateIsSetSetterReference,
+ lateGetterReference,
+ lateSetterReference,
+ isCovariantByDeclaration,
+ isSetStrategy);
+
+ @override
+ Statement _createGetterBody(
+ CoreTypes coreTypes, String name, Expression? initializer) {
+ assert(_type != null, "Type has not been computed for field $name.");
+ return late_lowering.createGetterWithInitializerWithRecheck(
+ coreTypes, fileOffset, name, _type!, initializer!,
+ createVariableRead: _createFieldRead,
+ createVariableWrite: (Expression value) =>
+ _createFieldSet(_field, value),
+ createIsSetRead: () => _createFieldGet(_lateIsSetField!),
+ createIsSetWrite: (Expression value) =>
+ _createFieldSet(_lateIsSetField!, value),
+ isSetEncoding: isSetEncoding,
+ forField: true);
+ }
+
+ @override
+ Procedure? _createSetter(
+ Name name, Uri fileUri, int charOffset, Reference? reference,
+ {required bool isCovariantByDeclaration}) =>
+ null;
+
+ @override
+ Statement _createSetterBody(
+ CoreTypes coreTypes, String name, VariableDeclaration parameter) =>
+ throw new UnsupportedError(
+ '$runtimeType._createSetterBody is not supported.');
+}
+
+class _SynthesizedFieldClassMember implements ClassMember {
+ final SourceFieldBuilder fieldBuilder;
+ final _SynthesizedFieldMemberKind _kind;
+
+ final Member _member;
+
+ Covariance? _covariance;
+
+ @override
+ final bool forSetter;
+
+ @override
+ final bool isInternalImplementation;
+
+ _SynthesizedFieldClassMember(this.fieldBuilder, this._member, this._kind,
+ {this.forSetter: false, required this.isInternalImplementation})
+ // ignore: unnecessary_null_comparison
+ : assert(isInternalImplementation != null);
+
+ @override
+ Member getMember(ClassMembersBuilder membersBuilder) {
+ fieldBuilder._ensureType(membersBuilder);
+ return _member;
+ }
+
+ @override
+ Covariance getCovariance(ClassMembersBuilder membersBuilder) {
+ return _covariance ??= new Covariance.fromMember(getMember(membersBuilder),
+ forSetter: forSetter);
+ }
+
+ @override
+ void inferType(ClassMembersBuilder membersBuilder) {
+ fieldBuilder._ensureType(membersBuilder);
+ }
+
+ @override
+ void registerOverrideDependency(Set<ClassMember> overriddenMembers) {
+ fieldBuilder.registerOverrideDependency(overriddenMembers);
+ }
+
+ @override
+ bool get isSourceDeclaration => true;
+
+ @override
+ bool get isProperty => isField || isGetter || isSetter;
+
+ @override
+ ClassBuilder get classBuilder => fieldBuilder.classBuilder!;
+
+ @override
+ bool isObjectMember(ClassBuilder objectClass) {
+ return classBuilder == objectClass;
+ }
+
+ @override
+ bool get isDuplicate => fieldBuilder.isDuplicate;
+
+ @override
+ bool get isStatic => fieldBuilder.isStatic;
+
+ @override
+ bool get isField => _member is Field;
+
+ @override
+ bool get isAssignable {
+ Member field = _member;
+ return field is Field && field.hasSetter;
+ }
+
+ @override
+ bool get isSetter {
+ Member procedure = _member;
+ return procedure is Procedure && procedure.kind == ProcedureKind.Setter;
+ }
+
+ @override
+ bool get isGetter {
+ Member procedure = _member;
+ return procedure is Procedure && procedure.kind == ProcedureKind.Getter;
+ }
+
+ @override
+ bool get isFinal {
+ Member field = _member;
+ return field is Field && field.isFinal;
+ }
+
+ @override
+ bool get isConst {
+ Member field = _member;
+ return field is Field && field.isConst;
+ }
+
+ @override
+ Name get name => _member.name;
+
+ @override
+ String get fullName {
+ String suffix = isSetter ? "=" : "";
+ String className = classBuilder.fullNameForErrors;
+ // ignore: unnecessary_null_comparison
+ return className == null
+ ? "${fullNameForErrors}$suffix"
+ : "${className}.${fullNameForErrors}$suffix";
+ }
+
+ @override
+ String get fullNameForErrors => fieldBuilder.fullNameForErrors;
+
+ @override
+ Uri get fileUri => fieldBuilder.fileUri;
+
+ @override
+ int get charOffset => fieldBuilder.charOffset;
+
+ @override
+ bool get isAbstract => _member.isAbstract;
+
+ @override
+ bool get isSynthesized => false;
+
+ @override
+ bool get hasDeclarations => false;
+
+ @override
+ List<ClassMember> get declarations =>
+ throw new UnsupportedError("$runtimeType.declarations");
+
+ @override
+ ClassMember get interfaceMember => this;
+
+ @override
+ bool isSameDeclaration(ClassMember other) {
+ if (identical(this, other)) return true;
+ return other is _SynthesizedFieldClassMember &&
+ fieldBuilder == other.fieldBuilder &&
+ _kind == other._kind;
+ }
+
+ @override
+ String toString() => '_SynthesizedFieldClassMember('
+ '$fieldBuilder,$_member,$_kind,forSetter=${forSetter})';
+}
+
+class AbstractOrExternalFieldEncoding implements FieldEncoding {
+ final SourceFieldBuilder _fieldBuilder;
+ final bool isAbstract;
+ final bool isExternal;
+ final bool _isExtensionInstanceMember;
+
+ late Procedure _getter;
+ Procedure? _setter;
+ DartType? _type;
+
+ AbstractOrExternalFieldEncoding(
+ this._fieldBuilder,
+ String name,
+ NameScheme nameScheme,
+ Uri fileUri,
+ int charOffset,
+ int charEndOffset,
+ Reference? getterReference,
+ Reference? setterReference,
+ {required this.isAbstract,
+ required this.isExternal,
+ required bool isFinal,
+ required bool isCovariantByDeclaration,
+ required bool isNonNullableByDefault})
+ // ignore: unnecessary_null_comparison
+ : assert(isAbstract != null),
+ // ignore: unnecessary_null_comparison
+ assert(isExternal != null),
+ // ignore: unnecessary_null_comparison
+ assert(isFinal != null),
+ // ignore: unnecessary_null_comparison
+ assert(isCovariantByDeclaration != null),
+ // ignore: unnecessary_null_comparison
+ assert(isNonNullableByDefault != null),
+ _isExtensionInstanceMember = isExternal &&
+ nameScheme.isExtensionMember &&
+ nameScheme.isInstanceMember {
+ if (_isExtensionInstanceMember) {
+ _getter = new Procedure(
+ nameScheme.getProcedureName(ProcedureKind.Getter, name),
+ ProcedureKind.Method,
+ new FunctionNode(null, positionalParameters: [
+ new VariableDeclaration(extensionThisName)..fileOffset
+ ]),
+ fileUri: fileUri,
+ reference: getterReference)
+ ..fileOffset = charOffset
+ ..fileEndOffset = charEndOffset
+ ..isNonNullableByDefault = isNonNullableByDefault;
+ if (!isFinal) {
+ VariableDeclaration parameter =
+ new VariableDeclaration("#externalFieldValue")
+ ..isCovariantByDeclaration = isCovariantByDeclaration
+ ..fileOffset = charOffset;
+ _setter = new Procedure(
+ nameScheme.getProcedureName(ProcedureKind.Setter, name),
+ ProcedureKind.Method,
+ new FunctionNode(null,
+ positionalParameters: [
+ new VariableDeclaration(extensionThisName)..fileOffset,
+ parameter
+ ],
+ returnType: const VoidType())
+ ..fileOffset = charOffset
+ ..fileEndOffset = charEndOffset,
+ fileUri: fileUri,
+ reference: setterReference)
+ ..fileOffset = charOffset
+ ..fileEndOffset = charEndOffset
+ ..isNonNullableByDefault = isNonNullableByDefault;
+ }
+ } else {
+ _getter = new Procedure(
+ nameScheme.getFieldName(FieldNameType.Getter, name,
+ isSynthesized: true),
+ ProcedureKind.Getter,
+ new FunctionNode(null),
+ fileUri: fileUri,
+ reference: getterReference)
+ ..fileOffset = charOffset
+ ..fileEndOffset = charEndOffset
+ ..isNonNullableByDefault = isNonNullableByDefault;
+ if (!isFinal) {
+ VariableDeclaration parameter =
+ new VariableDeclaration("#externalFieldValue")
+ ..isCovariantByDeclaration = isCovariantByDeclaration
+ ..fileOffset = charOffset;
+ _setter = new Procedure(
+ nameScheme.getFieldName(FieldNameType.Setter, name,
+ isSynthesized: true),
+ ProcedureKind.Setter,
+ new FunctionNode(null,
+ positionalParameters: [parameter], returnType: const VoidType())
+ ..fileOffset = charOffset
+ ..fileEndOffset = charEndOffset,
+ fileUri: fileUri,
+ reference: setterReference)
+ ..fileOffset = charOffset
+ ..fileEndOffset = charEndOffset
+ ..isNonNullableByDefault = isNonNullableByDefault;
+ }
+ }
+ }
+
+ @override
+ DartType get type {
+ assert(_type != null,
+ "Type has not been computed for field ${_fieldBuilder.name}.");
+ return _type!;
+ }
+
+ @override
+ void set type(DartType value) {
+ assert(_type == null || _type is ImplicitFieldType,
+ "Type has already been computed for field ${_fieldBuilder.name}.");
+ _type = value;
+ if (value is! ImplicitFieldType) {
+ if (_isExtensionInstanceMember) {
+ SourceExtensionBuilder extensionBuilder =
+ _fieldBuilder.parent as SourceExtensionBuilder;
+ DartType onType = extensionBuilder.extension.onType;
+ List<TypeParameter> typeParameters =
+ extensionBuilder.extension.typeParameters;
+ if (typeParameters.isNotEmpty) {
+ FreshTypeParameters getterTypeParameters =
+ getFreshTypeParameters(typeParameters);
+ _getter.function.positionalParameters.first.type =
+ getterTypeParameters.substitute(onType);
+ _getter.function.returnType = getterTypeParameters.substitute(value);
+ _getter.function.typeParameters =
+ getterTypeParameters.freshTypeParameters;
+ setParents(
+ getterTypeParameters.freshTypeParameters, _getter.function);
+
+ Procedure? setter = _setter;
+ if (setter != null) {
+ FreshTypeParameters setterTypeParameters =
+ getFreshTypeParameters(typeParameters);
+ setter.function.positionalParameters.first.type =
+ setterTypeParameters.substitute(onType);
+ setter.function.positionalParameters[1].type =
+ setterTypeParameters.substitute(value);
+ setter.function.typeParameters =
+ setterTypeParameters.freshTypeParameters;
+ setParents(
+ setterTypeParameters.freshTypeParameters, setter.function);
+ }
+ } else {
+ _getter.function.returnType = value;
+ _setter?.function.positionalParameters[1].type = value;
+ _getter.function.positionalParameters.first.type = onType;
+ _setter?.function.positionalParameters.first.type = onType;
+ }
+ } else {
+ _getter.function.returnType = value;
+ Procedure? setter = _setter;
+ if (setter != null) {
+ if (setter.kind == ProcedureKind.Method) {
+ setter.function.positionalParameters[1].type = value;
+ } else {
+ setter.function.positionalParameters.first.type = value;
+ }
+ }
+ }
+ }
+ }
+
+ @override
+ void completeSignature(CoreTypes coreTypes) {}
+
+ @override
+ void createBodies(CoreTypes coreTypes, Expression? initializer) {
+ //assert(initializer != null);
+ }
+
+ @override
+ List<Initializer> createInitializer(int fileOffset, Expression value,
+ {required bool isSynthetic}) {
+ throw new UnsupportedError('ExternalFieldEncoding.createInitializer');
+ }
+
+ @override
+ void build(
+ SourceLibraryBuilder libraryBuilder, SourceFieldBuilder fieldBuilder) {
+ bool isExtensionMember = fieldBuilder.isExtensionMember;
+ bool isInstanceMember = !fieldBuilder.isExtensionMember &&
+ !fieldBuilder.isStatic &&
+ !fieldBuilder.isTopLevel;
+ _getter..isConst = fieldBuilder.isConst;
+ _getter
+ ..isStatic = !isInstanceMember
+ ..isExtensionMember = isExtensionMember
+ ..isAbstract = isAbstract && !isExternal
+ ..isExternal = isExternal;
+ updatePrivateMemberName(_getter, libraryBuilder);
+
+ if (_setter != null) {
+ _setter!
+ ..isStatic = !isInstanceMember
+ ..isExtensionMember = isExtensionMember
+ ..isAbstract = isAbstract && !isExternal
+ ..isExternal = isExternal;
+ updatePrivateMemberName(_setter!, libraryBuilder);
+ }
+ }
+
+ @override
+ void registerMembers(
+ SourceLibraryBuilder library,
+ SourceFieldBuilder fieldBuilder,
+ void Function(Member, BuiltMemberKind) f) {
+ f(
+ _getter,
+ fieldBuilder.isExtensionMember
+ ? BuiltMemberKind.ExtensionGetter
+ : BuiltMemberKind.Method);
+ if (_setter != null) {
+ f(
+ _setter!,
+ fieldBuilder.isExtensionMember
+ ? BuiltMemberKind.ExtensionSetter
+ : BuiltMemberKind.Method);
+ }
+ }
+
+ @override
+ void setGenericCovariantImpl() {
+ _setter!.function.positionalParameters.first.isCovariantByClass = true;
+ }
+
+ @override
+ Field get field {
+ throw new UnsupportedError("ExternalFieldEncoding.field");
+ }
+
+ @override
+ Iterable<Annotatable> get annotatables {
+ List<Annotatable> list = [_getter];
+ if (_setter != null) {
+ list.add(_setter!);
+ }
+ return list;
+ }
+
+ @override
+ Member get readTarget => _getter;
+
+ @override
+ Member? get writeTarget => _setter;
+
+ @override
+ Iterable<Member> get exportedMembers {
+ if (_setter != null) {
+ return [_getter, _setter!];
+ }
+ return [_getter];
+ }
+
+ @override
+ List<ClassMember> getLocalMembers(SourceFieldBuilder fieldBuilder) =>
+ <ClassMember>[
+ new _SynthesizedFieldClassMember(fieldBuilder, _getter,
+ _SynthesizedFieldMemberKind.AbstractExternalGetterSetter,
+ forSetter: false, isInternalImplementation: false)
+ ];
+
+ @override
+ List<ClassMember> getLocalSetters(SourceFieldBuilder fieldBuilder) =>
+ _setter != null
+ ? <ClassMember>[
+ new _SynthesizedFieldClassMember(fieldBuilder, _setter!,
+ _SynthesizedFieldMemberKind.AbstractExternalGetterSetter,
+ forSetter: true, isInternalImplementation: false)
+ ]
+ : const <ClassMember>[];
+
+ @override
+ bool get isLateLowering => false;
+}
+
+enum _SynthesizedFieldMemberKind {
+ /// A `isSet` field used for late lowering.
+ LateIsSet,
+
+ /// A field used for the value of a late lowered field.
+ LateField,
+
+ /// A getter or setter used for late lowering.
+ LateGetterSetter,
+
+ /// A getter or setter used for abstract or external fields.
+ AbstractExternalGetterSetter,
+}
diff --git a/pkg/front_end/lib/src/fasta/source/source_function_builder.dart b/pkg/front_end/lib/src/fasta/source/source_function_builder.dart
new file mode 100644
index 0000000..c29ad33
--- /dev/null
+++ b/pkg/front_end/lib/src/fasta/source/source_function_builder.dart
@@ -0,0 +1,515 @@
+// Copyright (c) 2016, 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.
+
+library fasta.procedure_builder;
+
+import 'package:kernel/ast.dart';
+import 'package:kernel/class_hierarchy.dart';
+
+import '../builder/builder.dart';
+import '../builder/class_builder.dart';
+import '../builder/declaration_builder.dart';
+import '../builder/extension_builder.dart';
+import '../builder/formal_parameter_builder.dart';
+import '../builder/function_builder.dart';
+import '../builder/library_builder.dart';
+import '../builder/member_builder.dart';
+import '../builder/metadata_builder.dart';
+import '../builder/type_builder.dart';
+import '../builder/type_variable_builder.dart';
+import '../identifiers.dart';
+import '../kernel/internal_ast.dart' show VariableDeclarationImpl;
+import '../kernel/kernel_helper.dart';
+import '../messages.dart'
+ show
+ messagePatchDeclarationMismatch,
+ messagePatchDeclarationOrigin,
+ messagePatchNonExternal,
+ noLength,
+ templateRequiredNamedParameterHasDefaultValueError;
+import '../modifier.dart';
+import '../scope.dart';
+import '../source/source_loader.dart' show SourceLoader;
+import '../type_inference/type_inference_engine.dart'
+ show IncludesTypeParametersNonCovariantly;
+import '../util/helpers.dart' show DelayedActionPerformer;
+import 'source_library_builder.dart' show SourceLibraryBuilder;
+import 'source_member_builder.dart';
+
+abstract class SourceFunctionBuilder
+ implements FunctionBuilder, SourceMemberBuilder {
+ List<MetadataBuilder>? get metadata;
+
+ TypeBuilder? get returnType;
+
+ List<TypeVariableBuilder>? get typeVariables;
+
+ List<FormalParameterBuilder>? get formals;
+
+ AsyncMarker get asyncModifier;
+
+ @override
+ ProcedureKind? get kind;
+
+ @override
+ bool get isAbstract;
+
+ @override
+ bool get isConstructor;
+
+ @override
+ bool get isRegularMethod;
+
+ @override
+ bool get isGetter;
+
+ @override
+ bool get isSetter;
+
+ @override
+ bool get isOperator;
+
+ @override
+ bool get isFactory;
+
+ /// This is the formal parameter scope as specified in the Dart Programming
+ /// Language Specification, 4th ed, section 9.2.
+ Scope computeFormalParameterScope(Scope parent);
+
+ Scope computeFormalParameterInitializerScope(Scope parent);
+
+ /// This scope doesn't correspond to any scope specified in the Dart
+ /// Programming Language Specification, 4th ed. It's an unspecified extension
+ /// to support generic methods.
+ Scope computeTypeParameterScope(Scope parent);
+
+ FormalParameterBuilder? getFormal(Identifier identifier);
+
+ String? get nativeMethodName;
+
+ Statement? get body;
+
+ void set body(Statement? newBody);
+
+ @override
+ bool get isNative;
+
+ /// Returns the [index]th parameter of this function.
+ ///
+ /// The index is the syntactical index, including both positional and named
+ /// parameter in the order they are declared, and excluding the synthesized
+ /// this parameter on extension instance members.
+ VariableDeclaration getFormalParameter(int index);
+
+ /// If this is an extension instance method or constructor with lowering
+ /// enabled, the tear off parameter corresponding to the [index]th parameter
+ /// on the instance method or constructor is returned.
+ ///
+ /// This is used to update the default value for the closure parameter when
+ /// it has been computed for the original parameter.
+ VariableDeclaration? getTearOffParameter(int index);
+
+ /// Returns the parameter for 'this' synthetically added to extension
+ /// instance members.
+ VariableDeclaration? get extensionThis;
+
+ /// Returns a list of synthetic type parameters added to extension instance
+ /// members.
+ List<TypeParameter>? get extensionTypeParameters;
+
+ void becomeNative(SourceLoader loader);
+
+ bool checkPatch(FunctionBuilder patch);
+
+ void reportPatchMismatch(Builder patch);
+}
+
+/// Common base class for constructor and procedure builders.
+abstract class FunctionBuilderImpl extends SourceMemberBuilderImpl
+ implements SourceFunctionBuilder {
+ @override
+ final List<MetadataBuilder>? metadata;
+
+ @override
+ final int modifiers;
+
+ @override
+ final TypeBuilder? returnType;
+
+ @override
+ final String name;
+
+ @override
+ final List<TypeVariableBuilder>? typeVariables;
+
+ @override
+ final List<FormalParameterBuilder>? formals;
+
+ /// If this procedure is an extension instance member, [_extensionThis] holds
+ /// the synthetically added `this` parameter.
+ VariableDeclaration? _extensionThis;
+
+ /// If this procedure is an extension instance member,
+ /// [_extensionTypeParameters] holds the type parameters copied from the
+ /// extension declaration.
+ List<TypeParameter>? _extensionTypeParameters;
+
+ FunctionBuilderImpl(
+ this.metadata,
+ this.modifiers,
+ this.returnType,
+ this.name,
+ this.typeVariables,
+ this.formals,
+ LibraryBuilder compilationUnit,
+ int charOffset,
+ this.nativeMethodName)
+ : super(compilationUnit, charOffset) {
+ if (formals != null) {
+ for (int i = 0; i < formals!.length; i++) {
+ formals![i].parent = this;
+ }
+ }
+ }
+
+ @override
+ String get debugName => "FunctionBuilder";
+
+ @override
+ AsyncMarker get asyncModifier;
+
+ @override
+ bool get isConstructor => false;
+
+ @override
+ bool get isAbstract => (modifiers & abstractMask) != 0;
+
+ @override
+ bool get isRegularMethod => identical(ProcedureKind.Method, kind);
+
+ @override
+ bool get isGetter => identical(ProcedureKind.Getter, kind);
+
+ @override
+ bool get isSetter => identical(ProcedureKind.Setter, kind);
+
+ @override
+ bool get isOperator => identical(ProcedureKind.Operator, kind);
+
+ @override
+ bool get isFactory => identical(ProcedureKind.Factory, kind);
+
+ @override
+ bool get isExternal => (modifiers & externalMask) != 0;
+
+ @override
+ bool get isAssignable => false;
+
+ @override
+ Scope computeFormalParameterScope(Scope parent) {
+ if (formals == null) return parent;
+ Map<String, Builder> local = <String, Builder>{};
+ for (FormalParameterBuilder formal in formals!) {
+ if (!isConstructor ||
+ !formal.isInitializingFormal && !formal.isSuperInitializingFormal) {
+ local[formal.name] = formal;
+ }
+ }
+ return new Scope(
+ local: local,
+ parent: parent,
+ debugName: "formal parameter",
+ isModifiable: false);
+ }
+
+ @override
+ Scope computeFormalParameterInitializerScope(Scope parent) {
+ // From
+ // [dartLangSpec.tex](../../../../../../docs/language/dartLangSpec.tex) at
+ // revision 94b23d3b125e9d246e07a2b43b61740759a0dace:
+ //
+ // When the formal parameter list of a non-redirecting generative
+ // constructor contains any initializing formals, a new scope is
+ // introduced, the _formal parameter initializer scope_, which is the
+ // current scope of the initializer list of the constructor, and which is
+ // enclosed in the scope where the constructor is declared. Each
+ // initializing formal in the formal parameter list introduces a final
+ // local variable into the formal parameter initializer scope, but not into
+ // the formal parameter scope; every other formal parameter introduces a
+ // local variable into both the formal parameter scope and the formal
+ // parameter initializer scope.
+
+ if (formals == null) return parent;
+ Map<String, Builder> local = <String, Builder>{};
+ for (FormalParameterBuilder formal in formals!) {
+ local[formal.name] = formal.forFormalParameterInitializerScope();
+ }
+ return new Scope(
+ local: local,
+ parent: parent,
+ debugName: "formal parameter initializer",
+ isModifiable: false);
+ }
+
+ @override
+ Scope computeTypeParameterScope(Scope parent) {
+ if (typeVariables == null) return parent;
+ Map<String, Builder> local = <String, Builder>{};
+ for (TypeVariableBuilder variable in typeVariables!) {
+ local[variable.name] = variable;
+ }
+ return new Scope(
+ local: local,
+ parent: parent,
+ debugName: "type parameter",
+ isModifiable: false);
+ }
+
+ @override
+ FormalParameterBuilder? getFormal(Identifier identifier) {
+ if (formals != null) {
+ for (FormalParameterBuilder formal in formals!) {
+ if (formal.name == identifier.name &&
+ formal.charOffset == identifier.charOffset) {
+ return formal;
+ }
+ }
+ // If we have any formals we should find the one we're looking for.
+ assert(false, "$identifier not found in $formals");
+ }
+ return null;
+ }
+
+ @override
+ final String? nativeMethodName;
+
+ Statement? bodyInternal;
+
+ @override
+ void set body(Statement? newBody) {
+// if (newBody != null) {
+// if (isAbstract) {
+// // TODO(danrubel): Is this check needed?
+// return internalProblem(messageInternalProblemBodyOnAbstractMethod,
+// newBody.fileOffset, fileUri);
+// }
+// }
+ bodyInternal = newBody;
+ // A forwarding semi-stub is a method that is abstract in the source code,
+ // but which needs to have a forwarding stub body in order to ensure that
+ // covariance checks occur. We don't want to replace the forwarding stub
+ // body with null.
+ TreeNode? parent = function.parent;
+ if (!(newBody == null &&
+ parent is Procedure &&
+ parent.isForwardingSemiStub)) {
+ function.body = newBody;
+ newBody?.parent = function;
+ }
+ }
+
+ @override
+ Statement? get body => bodyInternal ??= new EmptyStatement();
+
+ @override
+ bool get isNative => nativeMethodName != null;
+
+ void buildFunction(SourceLibraryBuilder library) {
+ function.asyncMarker = asyncModifier;
+ function.body = body;
+ body?.parent = function;
+ IncludesTypeParametersNonCovariantly? needsCheckVisitor;
+ if (!isConstructor && !isFactory && parent is ClassBuilder) {
+ Class enclosingClass = classBuilder!.cls;
+ if (enclosingClass.typeParameters.isNotEmpty) {
+ needsCheckVisitor = new IncludesTypeParametersNonCovariantly(
+ enclosingClass.typeParameters,
+ // We are checking the parameter types which are in a
+ // contravariant position.
+ initialVariance: Variance.contravariant);
+ }
+ }
+ if (typeVariables != null) {
+ for (TypeVariableBuilder t in typeVariables!) {
+ TypeParameter parameter = t.parameter;
+ function.typeParameters.add(parameter);
+ if (needsCheckVisitor != null) {
+ if (parameter.bound.accept(needsCheckVisitor)) {
+ parameter.isCovariantByClass = true;
+ }
+ }
+ }
+ setParents(function.typeParameters, function);
+ }
+ if (formals != null) {
+ for (FormalParameterBuilder formal in formals!) {
+ VariableDeclaration parameter = formal.build(library, 0);
+ if (needsCheckVisitor != null) {
+ if (parameter.type.accept(needsCheckVisitor)) {
+ parameter.isCovariantByClass = true;
+ }
+ }
+ if (formal.isNamed) {
+ function.namedParameters.add(parameter);
+ } else {
+ function.positionalParameters.add(parameter);
+ }
+ parameter.parent = function;
+ if (formal.isRequired) {
+ function.requiredParameterCount++;
+ }
+
+ if (library.isNonNullableByDefault) {
+ // Required named parameters can't have default values.
+ if (formal.isNamedRequired && formal.initializerToken != null) {
+ library.addProblem(
+ templateRequiredNamedParameterHasDefaultValueError
+ .withArguments(formal.name),
+ formal.charOffset,
+ formal.name.length,
+ formal.fileUri);
+ }
+ }
+ }
+ }
+ if (!isExtensionInstanceMember &&
+ isSetter &&
+ (formals?.length != 1 || formals![0].isOptional)) {
+ // Replace illegal parameters by single dummy parameter.
+ // Do this after building the parameters, since the diet listener
+ // assumes that parameters are built, even if illegal in number.
+ VariableDeclaration parameter =
+ new VariableDeclarationImpl("#synthetic", 0);
+ function.positionalParameters.clear();
+ function.positionalParameters.add(parameter);
+ parameter.parent = function;
+ function.namedParameters.clear();
+ function.requiredParameterCount = 1;
+ }
+ if (returnType != null) {
+ function.returnType = returnType!.build(library);
+ }
+ if (isExtensionInstanceMember) {
+ ExtensionBuilder extensionBuilder = parent as ExtensionBuilder;
+ _extensionThis = function.positionalParameters.first;
+ if (extensionBuilder.typeParameters != null) {
+ int count = extensionBuilder.typeParameters!.length;
+ _extensionTypeParameters = new List<TypeParameter>.generate(
+ count, (int index) => function.typeParameters[index],
+ growable: false);
+ }
+ }
+ }
+
+ @override
+ VariableDeclaration getFormalParameter(int index) {
+ if (isExtensionInstanceMember) {
+ return formals![index + 1].variable!;
+ } else {
+ return formals![index].variable!;
+ }
+ }
+
+ @override
+ VariableDeclaration? getTearOffParameter(int index) => null;
+
+ @override
+ VariableDeclaration? get extensionThis {
+ assert(_extensionThis != null || !isExtensionInstanceMember,
+ "ProcedureBuilder.extensionThis has not been set.");
+ return _extensionThis;
+ }
+
+ @override
+ List<TypeParameter>? get extensionTypeParameters {
+ // Use [_extensionThis] as marker for whether extension type parameters have
+ // been computed.
+ assert(_extensionThis != null || !isExtensionInstanceMember,
+ "ProcedureBuilder.extensionTypeParameters has not been set.");
+ return _extensionTypeParameters;
+ }
+
+ bool _hasBuiltOutlineExpressions = false;
+
+ @override
+ void buildOutlineExpressions(
+ SourceLibraryBuilder library,
+ ClassHierarchy classHierarchy,
+ List<DelayedActionPerformer> delayedActionPerformers,
+ List<SynthesizedFunctionNode> synthesizedFunctionNodes) {
+ if (!_hasBuiltOutlineExpressions) {
+ DeclarationBuilder? classOrExtensionBuilder =
+ isClassMember || isExtensionMember
+ ? parent as DeclarationBuilder
+ : null;
+ Scope parentScope = classOrExtensionBuilder?.scope ?? library.scope;
+ MetadataBuilder.buildAnnotations(member, metadata, library,
+ classOrExtensionBuilder, this, fileUri, parentScope);
+ if (typeVariables != null) {
+ for (int i = 0; i < typeVariables!.length; i++) {
+ typeVariables![i].buildOutlineExpressions(
+ library,
+ classOrExtensionBuilder,
+ this,
+ classHierarchy,
+ delayedActionPerformers,
+ computeTypeParameterScope(parentScope));
+ }
+ }
+
+ if (formals != null) {
+ // For const constructors we need to include default parameter values
+ // into the outline. For all other formals we need to call
+ // buildOutlineExpressions to clear initializerToken to prevent
+ // consuming too much memory.
+ for (FormalParameterBuilder formal in formals!) {
+ formal.buildOutlineExpressions(library, delayedActionPerformers);
+ }
+ }
+ _hasBuiltOutlineExpressions = true;
+ }
+ }
+
+ Member build(SourceLibraryBuilder library);
+
+ @override
+ void becomeNative(SourceLoader loader) {
+ MemberBuilder constructor = loader.getNativeAnnotation();
+ Arguments arguments =
+ new Arguments(<Expression>[new StringLiteral(nativeMethodName!)]);
+ Expression annotation;
+ if (constructor.isConstructor) {
+ annotation = new ConstructorInvocation(
+ constructor.member as Constructor, arguments)
+ ..isConst = true;
+ } else {
+ annotation =
+ new StaticInvocation(constructor.member as Procedure, arguments)
+ ..isConst = true;
+ }
+ member.addAnnotation(annotation);
+ }
+
+ @override
+ bool checkPatch(FunctionBuilder patch) {
+ if (!isExternal) {
+ patch.library.addProblem(
+ messagePatchNonExternal, patch.charOffset, noLength, patch.fileUri!,
+ context: [
+ messagePatchDeclarationOrigin.withLocation(
+ fileUri, charOffset, noLength)
+ ]);
+ return false;
+ }
+ return true;
+ }
+
+ @override
+ void reportPatchMismatch(Builder patch) {
+ library.addProblem(messagePatchDeclarationMismatch, patch.charOffset,
+ noLength, patch.fileUri!, context: [
+ messagePatchDeclarationOrigin.withLocation(fileUri, charOffset, noLength)
+ ]);
+ }
+}
diff --git a/pkg/front_end/lib/src/fasta/source/source_library_builder.dart b/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
index b7551de..4b3cd4c 100644
--- a/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
@@ -8,43 +8,31 @@
import 'dart:convert' show jsonEncode;
import 'package:_fe_analyzer_shared/src/scanner/token.dart' show Token;
-
import 'package:_fe_analyzer_shared/src/util/resolve_relative_uri.dart'
show resolveRelativeUri;
-
import 'package:kernel/ast.dart' hide Combinator, MapLiteralEntry;
-
import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
-
import 'package:kernel/clone.dart' show CloneVisitorNotMembers;
-
import 'package:kernel/reference_from_index.dart'
show IndexedClass, IndexedContainer, IndexedLibrary;
-
import 'package:kernel/src/bounds_checks.dart'
show
TypeArgumentIssue,
findTypeArgumentIssues,
findTypeArgumentIssuesForInvocation,
getGenericTypeName;
-
import 'package:kernel/type_algebra.dart' show Substitution, substitute;
-
import 'package:kernel/type_environment.dart'
show SubtypeCheckMode, TypeEnvironment;
import '../../api_prototype/experimental_flags.dart';
import '../../base/nnbd_mode.dart';
-
import '../builder/builder.dart';
import '../builder/builtin_type_declaration_builder.dart';
import '../builder/class_builder.dart';
-import '../builder/constructor_builder.dart';
import '../builder/constructor_reference_builder.dart';
import '../builder/dynamic_type_declaration_builder.dart';
-import '../builder/enum_builder.dart';
import '../builder/extension_builder.dart';
-import '../builder/factory_builder.dart';
import '../builder/field_builder.dart';
import '../builder/formal_parameter_builder.dart';
import '../builder/function_builder.dart';
@@ -65,23 +53,15 @@
import '../builder/type_declaration_builder.dart';
import '../builder/type_variable_builder.dart';
import '../builder/void_type_declaration_builder.dart';
-
import '../combinator.dart' show CombinatorBuilder;
-
import '../configuration.dart' show Configuration;
-
import '../dill/dill_library_builder.dart' show DillLibraryBuilder;
-
import '../export.dart' show Export;
-
import '../fasta_codes.dart';
-
import '../identifiers.dart' show QualifiedName, flattenName;
-
import '../import.dart' show Import;
-
-import '../kernel/hierarchy/members_builder.dart';
import '../kernel/constructor_tearoff_lowering.dart';
+import '../kernel/hierarchy/members_builder.dart';
import '../kernel/implicit_field_type.dart';
import '../kernel/internal_ast.dart';
import '../kernel/kernel_helper.dart';
@@ -97,7 +77,6 @@
getNonSimplicityIssuesForTypeVariables,
pendingVariance;
import '../kernel/utils.dart' show compareProcedures, toKernelCombinators;
-
import '../modifier.dart'
show
abstractMask,
@@ -112,22 +91,23 @@
mixinDeclarationMask,
namedMixinApplicationMask,
staticMask;
-
import '../names.dart' show indexSetName;
-
import '../operator.dart';
-
import '../problems.dart' show unexpected, unhandled;
-
import '../scope.dart';
-
import '../type_inference/type_inferrer.dart' show TypeInferrerImpl;
-
import '../util/helpers.dart';
import 'name_scheme.dart';
import 'source_class_builder.dart' show SourceClassBuilder;
+import 'source_constructor_builder.dart';
+import 'source_enum_builder.dart';
import 'source_extension_builder.dart';
+import 'source_factory_builder.dart';
+import 'source_field_builder.dart';
+import 'source_function_builder.dart';
import 'source_loader.dart' show SourceLoader;
+import 'source_member_builder.dart';
+import 'source_procedure_builder.dart';
import 'source_type_alias_builder.dart';
class SourceLibraryBuilder extends LibraryBuilderImpl {
diff --git a/pkg/front_end/lib/src/fasta/source/source_loader.dart b/pkg/front_end/lib/src/fasta/source/source_loader.dart
index b7bcf7a..4d9a9f9 100644
--- a/pkg/front_end/lib/src/fasta/source/source_loader.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_loader.dart
@@ -35,28 +35,26 @@
import '../../base/common.dart';
import '../../base/instrumentation.dart' show Instrumentation;
import '../../base/nnbd_mode.dart';
-import '../builder/metadata_builder.dart';
-import '../dill/dill_library_builder.dart';
-import '../builder_graph.dart';
import '../builder/builder.dart';
import '../builder/class_builder.dart';
-import '../builder/constructor_builder.dart';
import '../builder/declaration_builder.dart';
-import '../builder/enum_builder.dart';
import '../builder/extension_builder.dart';
import '../builder/field_builder.dart';
import '../builder/invalid_type_declaration_builder.dart';
import '../builder/library_builder.dart';
import '../builder/member_builder.dart';
+import '../builder/metadata_builder.dart';
import '../builder/modifier_builder.dart';
import '../builder/named_type_builder.dart';
import '../builder/procedure_builder.dart';
import '../builder/type_alias_builder.dart';
import '../builder/type_builder.dart';
import '../builder/type_declaration_builder.dart';
+import '../builder_graph.dart';
import '../crash.dart' show firstSourceUri;
import '../denylisted_classes.dart'
show denylistedCoreClasses, denylistedTypedDataClasses;
+import '../dill/dill_library_builder.dart';
import '../export.dart' show Export;
import '../fasta_codes.dart';
import '../kernel/body_builder.dart' show BodyBuilder;
@@ -84,12 +82,16 @@
import 'name_scheme.dart';
import 'outline_builder.dart' show OutlineBuilder;
import 'source_class_builder.dart' show SourceClassBuilder;
+import 'source_constructor_builder.dart';
+import 'source_enum_builder.dart';
+import 'source_field_builder.dart';
import 'source_library_builder.dart'
show
ImplicitLanguageVersion,
InvalidLanguageVersion,
LanguageVersion,
SourceLibraryBuilder;
+import 'source_procedure_builder.dart';
import 'stack_listener_impl.dart' show offsetForToken;
class SourceLoader extends Loader {
diff --git a/pkg/front_end/lib/src/fasta/source/source_member_builder.dart b/pkg/front_end/lib/src/fasta/source/source_member_builder.dart
new file mode 100644
index 0000000..edfb1a1
--- /dev/null
+++ b/pkg/front_end/lib/src/fasta/source/source_member_builder.dart
@@ -0,0 +1,129 @@
+// Copyright (c) 2016, 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.
+
+library fasta.member_builder;
+
+import 'package:kernel/ast.dart';
+import 'package:kernel/class_hierarchy.dart';
+
+import '../../base/common.dart';
+import '../builder/builder.dart';
+import '../builder/declaration_builder.dart';
+import '../builder/library_builder.dart';
+import '../builder/member_builder.dart';
+import '../kernel/kernel_helper.dart';
+import '../problems.dart' show unsupported;
+import '../source/source_library_builder.dart';
+import '../type_inference/type_inference_engine.dart'
+ show InferenceDataForTesting;
+import '../util/helpers.dart' show DelayedActionPerformer;
+
+abstract class SourceMemberBuilder implements MemberBuilder {
+ MemberDataForTesting? get dataForTesting;
+
+ /// Builds the core AST structures for this member as needed for the outline.
+ void buildMembers(
+ SourceLibraryBuilder library, void Function(Member, BuiltMemberKind) f);
+
+ void buildOutlineExpressions(
+ SourceLibraryBuilder library,
+ ClassHierarchy classHierarchy,
+ List<DelayedActionPerformer> delayedActionPerformers,
+ List<SynthesizedFunctionNode> synthesizedFunctionNodes);
+}
+
+mixin SourceMemberBuilderMixin implements SourceMemberBuilder {
+ @override
+ MemberDataForTesting? dataForTesting =
+ retainDataForTesting ? new MemberDataForTesting() : null;
+
+ @override
+ void buildMembers(
+ SourceLibraryBuilder library, void Function(Member, BuiltMemberKind) f) {
+ assert(false, "Unexpected call to $runtimeType.buildMembers.");
+ }
+}
+
+abstract class SourceMemberBuilderImpl extends MemberBuilderImpl
+ implements SourceMemberBuilder {
+ @override
+ MemberDataForTesting? dataForTesting;
+
+ SourceMemberBuilderImpl(Builder parent, int charOffset, [Uri? fileUri])
+ : dataForTesting =
+ retainDataForTesting ? new MemberDataForTesting() : null,
+ super(parent, charOffset, fileUri);
+
+ bool get isRedirectingGenerativeConstructor => false;
+
+ bool? _isConflictingSetter;
+
+ @override
+ bool get isConflictingSetter {
+ return _isConflictingSetter ??= false;
+ }
+
+ void set isConflictingSetter(bool value) {
+ assert(_isConflictingSetter == null,
+ '$this.isConflictingSetter has already been fixed.');
+ _isConflictingSetter = value;
+ }
+
+ // TODO(johnniwinther): Remove this and create a [ProcedureBuilder] interface.
+ @override
+ ProcedureKind? get kind => unsupported("kind", charOffset, fileUri);
+
+ @override
+ void buildOutlineExpressions(
+ SourceLibraryBuilder library,
+ ClassHierarchy classHierarchy,
+ List<DelayedActionPerformer> delayedActionPerformers,
+ List<SynthesizedFunctionNode> synthesizedFunctionNodes) {}
+
+ @override
+ StringBuffer printOn(StringBuffer buffer) {
+ if (isClassMember) {
+ buffer.write(classBuilder!.name);
+ buffer.write('.');
+ }
+ buffer.write(name);
+ return buffer;
+ }
+
+ /// The builder for the enclosing class or extension, if any.
+ DeclarationBuilder? get declarationBuilder =>
+ parent is DeclarationBuilder ? parent as DeclarationBuilder : null;
+}
+
+enum BuiltMemberKind {
+ Constructor,
+ RedirectingFactory,
+ Field,
+ Method,
+ ExtensionField,
+ ExtensionMethod,
+ ExtensionGetter,
+ ExtensionSetter,
+ ExtensionOperator,
+ ExtensionTearOff,
+ LateIsSetField,
+ LateGetter,
+ LateSetter,
+}
+
+class MemberDataForTesting {
+ final InferenceDataForTesting inferenceData = new InferenceDataForTesting();
+
+ MemberBuilder? patchForTesting;
+}
+
+/// If the name of [member] is private, update it to use the library reference
+/// of [libraryBuilder].
+// TODO(johnniwinther): Avoid having to update private names by setting
+// the correct library reference when creating parts.
+void updatePrivateMemberName(Member member, LibraryBuilder libraryBuilder) {
+ if (member.name.isPrivate) {
+ member.name = new Name(member.name.text, libraryBuilder.library);
+ }
+}
diff --git a/pkg/front_end/lib/src/fasta/source/source_procedure_builder.dart b/pkg/front_end/lib/src/fasta/source/source_procedure_builder.dart
new file mode 100644
index 0000000..a679d67
--- /dev/null
+++ b/pkg/front_end/lib/src/fasta/source/source_procedure_builder.dart
@@ -0,0 +1,541 @@
+// Copyright (c) 2019, 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/builder.dart';
+import '../builder/extension_builder.dart';
+import '../builder/formal_parameter_builder.dart';
+import '../builder/member_builder.dart';
+import '../builder/metadata_builder.dart';
+import '../builder/procedure_builder.dart';
+import '../builder/type_builder.dart';
+import '../builder/type_variable_builder.dart';
+import '../kernel/hierarchy/class_member.dart';
+import '../kernel/hierarchy/members_builder.dart';
+import '../kernel/member_covariance.dart';
+import '../source/name_scheme.dart';
+import '../source/source_library_builder.dart' show SourceLibraryBuilder;
+import '../source/source_loader.dart' show SourceLoader;
+import 'source_function_builder.dart';
+import 'source_member_builder.dart';
+
+class SourceProcedureBuilder extends FunctionBuilderImpl
+ implements ProcedureBuilder {
+ @override
+ final int charOpenParenOffset;
+
+ @override
+ AsyncMarker actualAsyncModifier = AsyncMarker.Sync;
+
+ @override
+ final bool isExtensionInstanceMember;
+
+ late Procedure _procedure;
+
+ final Reference? _tearOffReference;
+
+ /// If this is an extension instance method then [_extensionTearOff] holds
+ /// the synthetically created tear off function.
+ Procedure? _extensionTearOff;
+
+ /// If this is an extension instance method then
+ /// [_extensionTearOffParameterMap] holds a map from the parameters of
+ /// the methods to the parameter of the closure returned in the tear-off.
+ ///
+ /// This map is used to set the default values on the closure parameters when
+ /// these have been built.
+ Map<VariableDeclaration, VariableDeclaration>? _extensionTearOffParameterMap;
+
+ @override
+ final ProcedureKind kind;
+
+ SourceProcedureBuilder? actualOrigin;
+
+ SourceProcedureBuilder(
+ List<MetadataBuilder>? metadata,
+ int modifiers,
+ TypeBuilder? returnType,
+ String name,
+ List<TypeVariableBuilder>? typeVariables,
+ List<FormalParameterBuilder>? formals,
+ this.kind,
+ SourceLibraryBuilder libraryBuilder,
+ int startCharOffset,
+ int charOffset,
+ this.charOpenParenOffset,
+ int charEndOffset,
+ Reference? procedureReference,
+ this._tearOffReference,
+ AsyncMarker asyncModifier,
+ NameScheme nameScheme,
+ {required bool isExtensionMember,
+ required bool isInstanceMember,
+ String? nativeMethodName})
+ // ignore: unnecessary_null_comparison
+ : assert(isExtensionMember != null),
+ // ignore: unnecessary_null_comparison
+ assert(isInstanceMember != null),
+ assert(kind != ProcedureKind.Factory),
+ this.isExtensionInstanceMember = isInstanceMember && isExtensionMember,
+ super(metadata, modifiers, returnType, name, typeVariables, formals,
+ libraryBuilder, charOffset, nativeMethodName) {
+ _procedure = new Procedure(
+ nameScheme.getProcedureName(kind, name),
+ isExtensionInstanceMember ? ProcedureKind.Method : kind,
+ new FunctionNode(null),
+ fileUri: libraryBuilder.fileUri,
+ reference: procedureReference)
+ ..startFileOffset = startCharOffset
+ ..fileOffset = charOffset
+ ..fileEndOffset = charEndOffset
+ ..isNonNullableByDefault = libraryBuilder.isNonNullableByDefault;
+ this.asyncModifier = asyncModifier;
+ if (isExtensionMember && isInstanceMember && kind == ProcedureKind.Method) {
+ _extensionTearOff ??= new Procedure(
+ nameScheme.getProcedureName(ProcedureKind.Getter, name),
+ ProcedureKind.Method,
+ new FunctionNode(null),
+ isStatic: true,
+ isExtensionMember: true,
+ reference: _tearOffReference,
+ fileUri: fileUri)
+ ..isNonNullableByDefault = library.isNonNullableByDefault;
+ }
+ }
+
+ @override
+ ProcedureBuilder? get patchForTesting =>
+ dataForTesting?.patchForTesting as ProcedureBuilder?;
+
+ @override
+ AsyncMarker get asyncModifier => actualAsyncModifier;
+
+ @override
+ Statement? get body {
+ if (bodyInternal == null && !isAbstract && !isExternal) {
+ bodyInternal = new EmptyStatement();
+ }
+ return bodyInternal;
+ }
+
+ @override
+ void set asyncModifier(AsyncMarker newModifier) {
+ actualAsyncModifier = newModifier;
+ function.asyncMarker = actualAsyncModifier;
+ function.dartAsyncMarker = actualAsyncModifier;
+ }
+
+ @override
+ bool get isEligibleForTopLevelInference {
+ if (isDeclarationInstanceMember) {
+ if (returnType == null) return true;
+ if (formals != null) {
+ for (FormalParameterBuilder formal in formals!) {
+ if (formal.type == null) return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ @override
+ bool get isExtensionMethod {
+ return parent is ExtensionBuilder;
+ }
+
+ @override
+ Member get member => procedure;
+
+ @override
+ SourceProcedureBuilder get origin => actualOrigin ?? this;
+
+ @override
+ Procedure get procedure => isPatch ? origin.procedure : _procedure;
+
+ @override
+ Procedure get actualProcedure => _procedure;
+
+ @override
+ FunctionNode get function => _procedure.function;
+
+ bool _typeEnsured = false;
+ Set<ClassMember>? _overrideDependencies;
+
+ void registerOverrideDependency(Set<ClassMember> overriddenMembers) {
+ assert(
+ overriddenMembers.every((overriddenMember) =>
+ overriddenMember.classBuilder != classBuilder),
+ "Unexpected override dependencies for $this: $overriddenMembers");
+ _overrideDependencies ??= {};
+ _overrideDependencies!.addAll(overriddenMembers);
+ }
+
+ void _ensureTypes(ClassMembersBuilder membersBuilder) {
+ if (_typeEnsured) return;
+ if (_overrideDependencies != null) {
+ if (isGetter) {
+ membersBuilder.inferGetterType(this, _overrideDependencies!);
+ } else if (isSetter) {
+ membersBuilder.inferSetterType(this, _overrideDependencies!);
+ } else {
+ membersBuilder.inferMethodType(this, _overrideDependencies!);
+ }
+ _overrideDependencies = null;
+ }
+ _typeEnsured = true;
+ }
+
+ @override
+ Member? get readTarget {
+ switch (kind) {
+ case ProcedureKind.Method:
+ return extensionTearOff ?? procedure;
+ case ProcedureKind.Getter:
+ return procedure;
+ case ProcedureKind.Factory:
+ return procedure;
+ case ProcedureKind.Operator:
+ case ProcedureKind.Setter:
+ return null;
+ }
+ }
+
+ @override
+ Member? get writeTarget {
+ switch (kind) {
+ case ProcedureKind.Setter:
+ return procedure;
+ case ProcedureKind.Method:
+ case ProcedureKind.Getter:
+ case ProcedureKind.Operator:
+ case ProcedureKind.Factory:
+ return null;
+ }
+ }
+
+ @override
+ Member? get invokeTarget {
+ switch (kind) {
+ case ProcedureKind.Method:
+ case ProcedureKind.Getter:
+ case ProcedureKind.Operator:
+ case ProcedureKind.Factory:
+ return procedure;
+ case ProcedureKind.Setter:
+ return null;
+ }
+ }
+
+ @override
+ Iterable<Member> get exportedMembers => [procedure];
+
+ @override
+ void buildMembers(
+ SourceLibraryBuilder library, void Function(Member, BuiltMemberKind) f) {
+ Member member = build(library);
+ if (isExtensionMethod) {
+ switch (kind) {
+ case ProcedureKind.Method:
+ f(member, BuiltMemberKind.ExtensionMethod);
+ break;
+ case ProcedureKind.Getter:
+ f(member, BuiltMemberKind.ExtensionGetter);
+ break;
+ case ProcedureKind.Setter:
+ f(member, BuiltMemberKind.ExtensionSetter);
+ break;
+ case ProcedureKind.Operator:
+ f(member, BuiltMemberKind.ExtensionOperator);
+ break;
+ case ProcedureKind.Factory:
+ throw new UnsupportedError(
+ 'Unexpected extension method kind ${kind}');
+ }
+ if (extensionTearOff != null) {
+ f(extensionTearOff!, BuiltMemberKind.ExtensionTearOff);
+ }
+ } else {
+ f(member, BuiltMemberKind.Method);
+ }
+ }
+
+ @override
+ Procedure build(SourceLibraryBuilder libraryBuilder) {
+ buildFunction(libraryBuilder);
+ _procedure.function.fileOffset = charOpenParenOffset;
+ _procedure.function.fileEndOffset = _procedure.fileEndOffset;
+ _procedure.isAbstract = isAbstract;
+ _procedure.isExternal = isExternal;
+ _procedure.isConst = isConst;
+ updatePrivateMemberName(_procedure, libraryBuilder);
+ if (isExtensionMethod) {
+ _procedure.isExtensionMember = true;
+ _procedure.isStatic = true;
+ if (isExtensionInstanceMember) {
+ assert(_procedure.kind == ProcedureKind.Method);
+ }
+ } else {
+ _procedure.isStatic = isStatic;
+ }
+ if (extensionTearOff != null) {
+ _buildExtensionTearOff(libraryBuilder, parent as ExtensionBuilder);
+ updatePrivateMemberName(extensionTearOff!, libraryBuilder);
+ }
+ return _procedure;
+ }
+
+ /// Creates a top level function that creates a tear off of an extension
+ /// instance method.
+ ///
+ /// For this declaration
+ ///
+ /// extension E<T> on A<T> {
+ /// X method<S>(S s, Y y) {}
+ /// }
+ ///
+ /// we create the top level function
+ ///
+ /// X E|method<T, S>(A<T> #this, S s, Y y) {}
+ ///
+ /// and the tear off function
+ ///
+ /// X Function<S>(S, Y) E|get#method<T>(A<T> #this) {
+ /// return (S s, Y y) => E|method<T, S>(#this, s, y);
+ /// }
+ ///
+ void _buildExtensionTearOff(
+ SourceLibraryBuilder libraryBuilder, ExtensionBuilder extensionBuilder) {
+ assert(
+ _extensionTearOff != null, "No extension tear off created for $this.");
+
+ _extensionTearOffParameterMap = {};
+
+ int fileOffset = _procedure.fileOffset;
+ int fileEndOffset = _procedure.fileEndOffset;
+
+ int extensionTypeParameterCount =
+ extensionBuilder.typeParameters?.length ?? 0;
+
+ List<TypeParameter> typeParameters = <TypeParameter>[];
+
+ Map<TypeParameter, DartType> substitutionMap = {};
+ List<DartType> typeArguments = <DartType>[];
+ for (TypeParameter typeParameter in function.typeParameters) {
+ TypeParameter newTypeParameter = new TypeParameter(typeParameter.name);
+ typeParameters.add(newTypeParameter);
+ typeArguments.add(substitutionMap[typeParameter] =
+ new TypeParameterType.forAlphaRenaming(
+ typeParameter, newTypeParameter));
+ }
+
+ List<TypeParameter> tearOffTypeParameters = <TypeParameter>[];
+ List<TypeParameter> closureTypeParameters = <TypeParameter>[];
+ Substitution substitution = Substitution.fromMap(substitutionMap);
+ for (int index = 0; index < typeParameters.length; index++) {
+ TypeParameter newTypeParameter = typeParameters[index];
+ newTypeParameter.bound =
+ substitution.substituteType(function.typeParameters[index].bound);
+ newTypeParameter.defaultType = function.typeParameters[index].defaultType;
+ if (index < extensionTypeParameterCount) {
+ tearOffTypeParameters.add(newTypeParameter);
+ } else {
+ closureTypeParameters.add(newTypeParameter);
+ }
+ }
+
+ VariableDeclaration copyParameter(
+ VariableDeclaration parameter, DartType type,
+ {required bool isOptional}) {
+ VariableDeclaration newParameter = new VariableDeclaration(parameter.name,
+ type: type,
+ isFinal: parameter.isFinal,
+ isLowered: parameter.isLowered)
+ ..fileOffset = parameter.fileOffset;
+ _extensionTearOffParameterMap![parameter] = newParameter;
+ return newParameter;
+ }
+
+ VariableDeclaration extensionThis = copyParameter(
+ function.positionalParameters.first,
+ substitution.substituteType(function.positionalParameters.first.type),
+ isOptional: false);
+
+ DartType closureReturnType =
+ substitution.substituteType(function.returnType);
+ List<VariableDeclaration> closurePositionalParameters = [];
+ List<Expression> closurePositionalArguments = [];
+
+ for (int position = 0;
+ position < function.positionalParameters.length;
+ position++) {
+ VariableDeclaration parameter = function.positionalParameters[position];
+ if (position == 0) {
+ /// Pass `this` as a captured variable.
+ closurePositionalArguments
+ .add(new VariableGet(extensionThis)..fileOffset = fileOffset);
+ } else {
+ DartType type = substitution.substituteType(parameter.type);
+ VariableDeclaration newParameter = copyParameter(parameter, type,
+ isOptional: position >= function.requiredParameterCount);
+ closurePositionalParameters.add(newParameter);
+ closurePositionalArguments
+ .add(new VariableGet(newParameter)..fileOffset = fileOffset);
+ }
+ }
+ List<VariableDeclaration> closureNamedParameters = [];
+ List<NamedExpression> closureNamedArguments = [];
+ for (VariableDeclaration parameter in function.namedParameters) {
+ DartType type = substitution.substituteType(parameter.type);
+ VariableDeclaration newParameter =
+ copyParameter(parameter, type, isOptional: true);
+ closureNamedParameters.add(newParameter);
+ closureNamedArguments.add(new NamedExpression(parameter.name!,
+ new VariableGet(newParameter)..fileOffset = fileOffset));
+ }
+
+ Statement closureBody = new ReturnStatement(
+ new StaticInvocation(
+ _procedure,
+ new Arguments(closurePositionalArguments,
+ types: typeArguments, named: closureNamedArguments))
+ ..fileOffset = fileOffset)
+ ..fileOffset = fileOffset;
+
+ FunctionExpression closure = new FunctionExpression(
+ new FunctionNode(closureBody,
+ typeParameters: closureTypeParameters,
+ positionalParameters: closurePositionalParameters,
+ namedParameters: closureNamedParameters,
+ requiredParameterCount:
+ _procedure.function.requiredParameterCount - 1,
+ returnType: closureReturnType)
+ ..fileOffset = fileOffset
+ ..fileEndOffset = fileEndOffset)
+ ..fileOffset = fileOffset;
+
+ _extensionTearOff!
+ ..function = (new FunctionNode(
+ new ReturnStatement(closure)..fileOffset = fileOffset,
+ typeParameters: tearOffTypeParameters,
+ positionalParameters: [extensionThis],
+ requiredParameterCount: 1,
+ returnType: closure.function.computeFunctionType(library.nonNullable))
+ ..fileOffset = fileOffset
+ ..fileEndOffset = fileEndOffset)
+ ..fileUri = fileUri
+ ..fileOffset = fileOffset
+ ..fileEndOffset = fileEndOffset;
+ _extensionTearOff!.function.parent = _extensionTearOff;
+ }
+
+ Procedure? get extensionTearOff => _extensionTearOff;
+
+ @override
+ VariableDeclaration? getTearOffParameter(int index) {
+ return _extensionTearOffParameterMap?[getFormalParameter(index)];
+ }
+
+ List<ClassMember>? _localMembers;
+ List<ClassMember>? _localSetters;
+
+ @override
+ List<ClassMember> get localMembers => _localMembers ??= isSetter
+ ? const <ClassMember>[]
+ : <ClassMember>[new SourceProcedureMember(this)];
+
+ @override
+ List<ClassMember> get localSetters =>
+ _localSetters ??= isSetter && !isConflictingSetter
+ ? <ClassMember>[new SourceProcedureMember(this)]
+ : const <ClassMember>[];
+
+ @override
+ void becomeNative(SourceLoader loader) {
+ _procedure.isExternal = true;
+ super.becomeNative(loader);
+ }
+
+ @override
+ void applyPatch(Builder patch) {
+ if (patch is SourceProcedureBuilder) {
+ if (checkPatch(patch)) {
+ patch.actualOrigin = this;
+ dataForTesting?.patchForTesting = patch;
+ }
+ } else {
+ reportPatchMismatch(patch);
+ }
+ }
+
+ @override
+ int finishPatch() {
+ if (!isPatch) return 0;
+
+ // TODO(ahe): restore file-offset once we track both origin and patch file
+ // URIs. See https://github.com/dart-lang/sdk/issues/31579
+ origin.procedure.fileUri = fileUri;
+ origin.procedure.startFileOffset = _procedure.startFileOffset;
+ origin.procedure.fileOffset = _procedure.fileOffset;
+ origin.procedure.fileEndOffset = _procedure.fileEndOffset;
+ origin.procedure.annotations
+ .forEach((m) => m.fileOffset = _procedure.fileOffset);
+
+ origin.procedure.isAbstract = _procedure.isAbstract;
+ origin.procedure.isExternal = _procedure.isExternal;
+ origin.procedure.function = _procedure.function;
+ origin.procedure.function.parent = origin.procedure;
+ origin.procedure.isRedirectingFactory = _procedure.isRedirectingFactory;
+ return 1;
+ }
+}
+
+class SourceProcedureMember extends BuilderClassMember {
+ @override
+ final SourceProcedureBuilder memberBuilder;
+
+ Covariance? _covariance;
+
+ SourceProcedureMember(this.memberBuilder);
+
+ @override
+ bool get isSourceDeclaration => true;
+
+ @override
+ void inferType(ClassMembersBuilder membersBuilder) {
+ memberBuilder._ensureTypes(membersBuilder);
+ }
+
+ @override
+ void registerOverrideDependency(Set<ClassMember> overriddenMembers) {
+ memberBuilder.registerOverrideDependency(overriddenMembers);
+ }
+
+ @override
+ Member getMember(ClassMembersBuilder membersBuilder) {
+ memberBuilder._ensureTypes(membersBuilder);
+ return memberBuilder.member;
+ }
+
+ @override
+ Covariance getCovariance(ClassMembersBuilder membersBuilder) {
+ return _covariance ??= new Covariance.fromMember(getMember(membersBuilder),
+ forSetter: forSetter);
+ }
+
+ @override
+ bool get forSetter => isSetter;
+
+ @override
+ bool get isProperty =>
+ memberBuilder.kind == ProcedureKind.Getter ||
+ memberBuilder.kind == ProcedureKind.Setter;
+
+ @override
+ bool isSameDeclaration(ClassMember other) {
+ return other is SourceProcedureMember &&
+ memberBuilder == other.memberBuilder;
+ }
+}
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart b/pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart
index 407f747..639f6b7 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart
@@ -3,32 +3,22 @@
// BSD-style license that can be found in the LICENSE.md file.
import 'package:_fe_analyzer_shared/src/flow_analysis/flow_analysis.dart';
-
import 'package:kernel/ast.dart';
-
import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
-
import 'package:kernel/core_types.dart' show CoreTypes;
-
import 'package:kernel/type_environment.dart';
import '../../base/instrumentation.dart' show Instrumentation;
-
-import '../builder/constructor_builder.dart';
-
import '../kernel/forest.dart';
-import '../kernel/implicit_field_type.dart';
-import '../kernel/internal_ast.dart';
import '../kernel/hierarchy/hierarchy_builder.dart' show ClassHierarchyBuilder;
import '../kernel/hierarchy/members_builder.dart' show ClassMembersBuilder;
+import '../kernel/implicit_field_type.dart';
+import '../kernel/internal_ast.dart';
import '../kernel/kernel_helper.dart';
-
+import '../source/source_constructor_builder.dart';
import '../source/source_library_builder.dart' show SourceLibraryBuilder;
-
import 'factor_type.dart';
-
import 'type_inferrer.dart';
-
import 'type_schema_environment.dart' show TypeSchemaEnvironment;
/// Visitor to check whether a given type mentions any of a class's type
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
index 1107037..78618cb 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
@@ -3,19 +3,17 @@
// BSD-style license that can be found in the LICENSE.md file.
import 'package:_fe_analyzer_shared/src/flow_analysis/flow_analysis.dart';
-
import 'package:_fe_analyzer_shared/src/testing/id.dart';
import 'package:_fe_analyzer_shared/src/util/link.dart';
-
import 'package:kernel/ast.dart';
import 'package:kernel/canonical_name.dart' as kernel;
import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
import 'package:kernel/core_types.dart' show CoreTypes;
-import 'package:kernel/type_algebra.dart';
-import 'package:kernel/type_environment.dart';
import 'package:kernel/src/bounds_checks.dart' show calculateBounds;
import 'package:kernel/src/future_value_type.dart';
import 'package:kernel/src/legacy_erasure.dart';
+import 'package:kernel/type_algebra.dart';
+import 'package:kernel/type_environment.dart';
import '../../base/instrumentation.dart'
show
@@ -23,32 +21,23 @@
InstrumentationValueForMember,
InstrumentationValueForType,
InstrumentationValueForTypeArgs;
-
import '../../base/nnbd_mode.dart';
-
import '../../testing/id_extractor.dart';
import '../../testing/id_testing_utils.dart';
-
-import '../builder/constructor_builder.dart';
import '../builder/extension_builder.dart';
import '../builder/member_builder.dart';
-
import '../fasta_codes.dart';
-
-import '../kernel/hierarchy/class_member.dart' show ClassMember;
import '../kernel/constructor_tearoff_lowering.dart';
-import '../kernel/kernel_helper.dart';
+import '../kernel/hierarchy/class_member.dart' show ClassMember;
import '../kernel/inference_visitor.dart';
import '../kernel/internal_ast.dart';
import '../kernel/invalid_type.dart';
+import '../kernel/kernel_helper.dart';
import '../kernel/type_algorithms.dart' show hasAnyTypeVariables;
-
import '../names.dart';
-
import '../problems.dart' show internalProblem, unexpected, unhandled;
-
+import '../source/source_constructor_builder.dart';
import '../source/source_library_builder.dart' show SourceLibraryBuilder;
-
import 'inference_helper.dart' show InferenceHelper;
import 'type_constraint_gatherer.dart' show TypeConstraintGatherer;
import 'type_demotion.dart';
diff --git a/pkg/front_end/test/extensions/extensions_test.dart b/pkg/front_end/test/extensions/extensions_test.dart
index 82e937b..83e5bbf 100644
--- a/pkg/front_end/test/extensions/extensions_test.dart
+++ b/pkg/front_end/test/extensions/extensions_test.dart
@@ -3,20 +3,20 @@
// BSD-style license that can be found in the LICENSE file.
import 'dart:io' show Directory, Platform;
+
+import 'package:_fe_analyzer_shared/src/testing/features.dart';
import 'package:_fe_analyzer_shared/src/testing/id.dart';
import 'package:_fe_analyzer_shared/src/testing/id_testing.dart';
import 'package:front_end/src/api_prototype/experimental_flags.dart';
-
import 'package:front_end/src/fasta/builder/class_builder.dart';
import 'package:front_end/src/fasta/builder/extension_builder.dart';
import 'package:front_end/src/fasta/builder/formal_parameter_builder.dart';
-import 'package:front_end/src/fasta/builder/function_builder.dart';
import 'package:front_end/src/fasta/builder/library_builder.dart';
import 'package:front_end/src/fasta/builder/member_builder.dart';
import 'package:front_end/src/fasta/builder/type_builder.dart';
import 'package:front_end/src/fasta/builder/type_variable_builder.dart';
+import 'package:front_end/src/fasta/source/source_function_builder.dart';
import 'package:front_end/src/fasta/source/source_library_builder.dart';
-import 'package:_fe_analyzer_shared/src/testing/features.dart';
import 'package:front_end/src/testing/id_testing_helper.dart';
import 'package:front_end/src/testing/id_testing_utils.dart';
import 'package:kernel/ast.dart';
diff --git a/pkg/front_end/test/id_tests/assigned_variables_test.dart b/pkg/front_end/test/id_tests/assigned_variables_test.dart
index 4b1516b..1741638 100644
--- a/pkg/front_end/test/id_tests/assigned_variables_test.dart
+++ b/pkg/front_end/test/id_tests/assigned_variables_test.dart
@@ -9,9 +9,8 @@
show ActualData, Id, IdKind;
import 'package:_fe_analyzer_shared/src/testing/id_testing.dart'
show DataInterpreter, runTests;
-import 'package:front_end/src/fasta/builder/member_builder.dart';
import 'package:front_end/src/fasta/source/source_loader.dart';
-
+import 'package:front_end/src/fasta/source/source_member_builder.dart';
import 'package:front_end/src/testing/id_testing_helper.dart';
import 'package:front_end/src/testing/id_testing_utils.dart';
import 'package:kernel/ast.dart' hide Variance;
diff --git a/pkg/front_end/test/id_tests/definite_assignment_test.dart b/pkg/front_end/test/id_tests/definite_assignment_test.dart
index f51a939..b4112f5 100644
--- a/pkg/front_end/test/id_tests/definite_assignment_test.dart
+++ b/pkg/front_end/test/id_tests/definite_assignment_test.dart
@@ -3,12 +3,13 @@
// BSD-style license that can be found in the LICENSE file.
import 'dart:io' show Directory, Platform;
+
import 'package:_fe_analyzer_shared/src/testing/id.dart' show ActualData, Id;
import 'package:_fe_analyzer_shared/src/testing/id_testing.dart';
-import 'package:front_end/src/testing/id_testing_helper.dart';
-import 'package:front_end/src/fasta/builder/member_builder.dart';
import 'package:front_end/src/fasta/source/source_loader.dart';
+import 'package:front_end/src/fasta/source/source_member_builder.dart';
import 'package:front_end/src/fasta/type_inference/type_inference_engine.dart';
+import 'package:front_end/src/testing/id_testing_helper.dart';
import 'package:front_end/src/testing/id_testing_utils.dart';
import 'package:kernel/ast.dart' hide Variance;
diff --git a/pkg/front_end/test/id_tests/definite_unassignment_test.dart b/pkg/front_end/test/id_tests/definite_unassignment_test.dart
index 7aeba6f..d51a02e 100644
--- a/pkg/front_end/test/id_tests/definite_unassignment_test.dart
+++ b/pkg/front_end/test/id_tests/definite_unassignment_test.dart
@@ -3,12 +3,13 @@
// BSD-style license that can be found in the LICENSE file.
import 'dart:io' show Directory, Platform;
+
import 'package:_fe_analyzer_shared/src/testing/id.dart' show ActualData, Id;
import 'package:_fe_analyzer_shared/src/testing/id_testing.dart';
-import 'package:front_end/src/testing/id_testing_helper.dart';
-import 'package:front_end/src/fasta/builder/member_builder.dart';
import 'package:front_end/src/fasta/source/source_loader.dart';
+import 'package:front_end/src/fasta/source/source_member_builder.dart';
import 'package:front_end/src/fasta/type_inference/type_inference_engine.dart';
+import 'package:front_end/src/testing/id_testing_helper.dart';
import 'package:front_end/src/testing/id_testing_utils.dart';
import 'package:kernel/ast.dart' hide Variance;
diff --git a/pkg/front_end/test/id_tests/inferred_type_arguments_test.dart b/pkg/front_end/test/id_tests/inferred_type_arguments_test.dart
index 12ea3ed..ef7a1ca 100644
--- a/pkg/front_end/test/id_tests/inferred_type_arguments_test.dart
+++ b/pkg/front_end/test/id_tests/inferred_type_arguments_test.dart
@@ -3,10 +3,11 @@
// BSD-style license that can be found in the LICENSE file.
import 'dart:io' show Directory, Platform;
+
import 'package:_fe_analyzer_shared/src/testing/id.dart' show ActualData, Id;
import 'package:_fe_analyzer_shared/src/testing/id_testing.dart'
show DataInterpreter, runTests;
-import 'package:front_end/src/fasta/builder/member_builder.dart';
+import 'package:front_end/src/fasta/source/source_member_builder.dart';
import 'package:front_end/src/fasta/type_inference/type_inference_engine.dart';
import 'package:front_end/src/testing/id_testing_helper.dart';
import 'package:front_end/src/testing/id_testing_utils.dart';
diff --git a/pkg/front_end/test/id_tests/inferred_variable_types_test.dart b/pkg/front_end/test/id_tests/inferred_variable_types_test.dart
index a7bc0cb..02c50fa 100644
--- a/pkg/front_end/test/id_tests/inferred_variable_types_test.dart
+++ b/pkg/front_end/test/id_tests/inferred_variable_types_test.dart
@@ -3,10 +3,11 @@
// BSD-style license that can be found in the LICENSE file.
import 'dart:io' show Directory, Platform;
+
import 'package:_fe_analyzer_shared/src/testing/id.dart' show ActualData, Id;
import 'package:_fe_analyzer_shared/src/testing/id_testing.dart'
show DataInterpreter, runTests;
-import 'package:front_end/src/fasta/builder/member_builder.dart';
+import 'package:front_end/src/fasta/source/source_member_builder.dart';
import 'package:front_end/src/fasta/type_inference/type_inference_engine.dart';
import 'package:front_end/src/testing/id_testing_helper.dart';
import 'package:front_end/src/testing/id_testing_utils.dart';
diff --git a/pkg/front_end/test/id_tests/reachability_test.dart b/pkg/front_end/test/id_tests/reachability_test.dart
index 8ea7394..a2e6a1a 100644
--- a/pkg/front_end/test/id_tests/reachability_test.dart
+++ b/pkg/front_end/test/id_tests/reachability_test.dart
@@ -3,13 +3,14 @@
// BSD-style license that can be found in the LICENSE file.
import 'dart:io' show Directory, Platform;
+
import 'package:_fe_analyzer_shared/src/testing/id.dart' show ActualData, Id;
import 'package:_fe_analyzer_shared/src/testing/id_testing.dart'
show DataInterpreter, runTests;
-import 'package:front_end/src/testing/id_testing_helper.dart';
-import 'package:front_end/src/fasta/builder/member_builder.dart';
import 'package:front_end/src/fasta/source/source_loader.dart';
+import 'package:front_end/src/fasta/source/source_member_builder.dart';
import 'package:front_end/src/fasta/type_inference/type_inference_engine.dart';
+import 'package:front_end/src/testing/id_testing_helper.dart';
import 'package:front_end/src/testing/id_testing_utils.dart';
import 'package:kernel/ast.dart' hide Variance;
diff --git a/pkg/front_end/test/id_tests/why_not_promoted_test.dart b/pkg/front_end/test/id_tests/why_not_promoted_test.dart
index 5899c55..4362bf9 100644
--- a/pkg/front_end/test/id_tests/why_not_promoted_test.dart
+++ b/pkg/front_end/test/id_tests/why_not_promoted_test.dart
@@ -7,7 +7,7 @@
import 'package:_fe_analyzer_shared/src/testing/id.dart' show ActualData, Id;
import 'package:_fe_analyzer_shared/src/testing/id_testing.dart'
show DataInterpreter, runTests;
-import 'package:front_end/src/fasta/builder/member_builder.dart';
+import 'package:front_end/src/fasta/source/source_member_builder.dart';
import 'package:front_end/src/fasta/type_inference/type_inference_engine.dart';
import 'package:front_end/src/testing/id_testing_helper.dart';
import 'package:front_end/src/testing/id_testing_utils.dart';
diff --git a/pkg/front_end/test/patching/patching_test.dart b/pkg/front_end/test/patching/patching_test.dart
index 2dc83ee..6f237db 100644
--- a/pkg/front_end/test/patching/patching_test.dart
+++ b/pkg/front_end/test/patching/patching_test.dart
@@ -4,6 +4,7 @@
import 'dart:io' show Directory, Platform;
+import 'package:_fe_analyzer_shared/src/testing/features.dart';
import 'package:_fe_analyzer_shared/src/testing/id.dart' show ActualData, Id;
import 'package:_fe_analyzer_shared/src/testing/id_testing.dart';
import 'package:front_end/src/api_prototype/compiler_options.dart';
@@ -11,8 +12,7 @@
import 'package:front_end/src/fasta/builder/builder.dart';
import 'package:front_end/src/fasta/builder/class_builder.dart';
import 'package:front_end/src/fasta/builder/member_builder.dart';
-
-import 'package:_fe_analyzer_shared/src/testing/features.dart';
+import 'package:front_end/src/fasta/source/source_member_builder.dart';
import 'package:front_end/src/testing/id_testing_helper.dart';
import 'package:front_end/src/testing/id_testing_utils.dart';
import 'package:kernel/ast.dart';
diff --git a/tools/VERSION b/tools/VERSION
index 0557489..393bdb2 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 16
PATCH 0
-PRERELEASE 142
+PRERELEASE 143
PRERELEASE_PATCH 0
\ No newline at end of file