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 ae3196c8..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