[cfe] Create fields through SourcePropertyBuilder
Change-Id: I20c9dd7baa705aba77d90b94ba0a46ed64eb02ec
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/403600
Commit-Queue: Johnni Winther <johnniwinther@google.com>
Reviewed-by: Chloe Stefantsova <cstefantsova@google.com>
diff --git a/pkg/front_end/lib/src/base/incremental_compiler.dart b/pkg/front_end/lib/src/base/incremental_compiler.dart
index f2ffaeb..ca404aa 100644
--- a/pkg/front_end/lib/src/base/incremental_compiler.dart
+++ b/pkg/front_end/lib/src/base/incremental_compiler.dart
@@ -73,7 +73,6 @@
import '../builder/builder.dart' show Builder;
import '../builder/declaration_builders.dart'
show ClassBuilder, ExtensionBuilder, ExtensionTypeDeclarationBuilder;
-import '../builder/field_builder.dart' show FieldBuilder;
import '../builder/library_builder.dart'
show CompilationUnit, LibraryBuilder, SourceCompilationUnit;
import '../builder/member_builder.dart' show MemberBuilder;
@@ -741,7 +740,9 @@
if (sourceBuilder == null) {
sourceBuilder = sourceLibraryBuilder.exportNameSpace
.lookupLocalMember(name, setter: false);
- if (sourceBuilder is FieldBuilder && sourceBuilder.isAssignable) {
+ if (sourceBuilder is MemberBuilder &&
+ sourceBuilder.isField &&
+ sourceBuilder.isAssignable) {
// Assignable fields can be lowered into a getter and setter.
return;
}
diff --git a/pkg/front_end/lib/src/base/scope.dart b/pkg/front_end/lib/src/base/scope.dart
index 38b029d0..45bb794 100644
--- a/pkg/front_end/lib/src/base/scope.dart
+++ b/pkg/front_end/lib/src/base/scope.dart
@@ -688,6 +688,14 @@
bool get isAbstract => false;
@override
+ // Coverage-ignore(suite): Not run.
+ bool get isFinal => false;
+
+ @override
+ // Coverage-ignore(suite): Not run.
+ bool get isSynthesized => false;
+
+ @override
bool get isConflictingSetter => false;
@override
@@ -1503,8 +1511,9 @@
return _hasPatchAnnotation(self.metadata);
} else if (self is SourceMethodBuilder) {
return _hasPatchAnnotation(self.metadata);
- } else if (self is SourceExtensionTypeDeclarationBuilder) {
- // Coverage-ignore-block(suite): Not run.
+ }
+ // Coverage-ignore(suite): Not run.
+ else if (self is SourceExtensionTypeDeclarationBuilder) {
return _hasPatchAnnotation(self.metadata);
}
return false;
diff --git a/pkg/front_end/lib/src/builder/builder_mixins.dart b/pkg/front_end/lib/src/builder/builder_mixins.dart
index 68bd1c3..2817a14 100644
--- a/pkg/front_end/lib/src/builder/builder_mixins.dart
+++ b/pkg/front_end/lib/src/builder/builder_mixins.dart
@@ -10,7 +10,6 @@
import '../base/scope.dart';
import 'builder.dart';
import 'declaration_builders.dart';
-import 'field_builder.dart';
import 'library_builder.dart';
import 'member_builder.dart';
import 'nullability_builder.dart';
@@ -96,16 +95,16 @@
if (builder == null && setter) {
// When looking up setters, we include assignable fields.
builder = lookupLocalMember(name.text, setter: false, required: required);
- if (builder is! FieldBuilder || !builder.isAssignable) {
+ if (builder is! MemberBuilder ||
+ !builder.isField ||
+ !builder.isAssignable) {
builder = null;
}
}
if (builder != null) {
if (name.isPrivate && libraryBuilder.library != name.library) {
builder = null;
- } else if (builder is FieldBuilder &&
- !builder.isStatic &&
- !builder.isExternal) {
+ } else if (builder.isField && !builder.isStatic && !builder.isExternal) {
// Non-external extension instance fields are invalid.
builder = null;
} else if (builder.isDuplicate) {
diff --git a/pkg/front_end/lib/src/builder/formal_parameter_builder.dart b/pkg/front_end/lib/src/builder/formal_parameter_builder.dart
index 774db86..1d984b3 100644
--- a/pkg/front_end/lib/src/builder/formal_parameter_builder.dart
+++ b/pkg/front_end/lib/src/builder/formal_parameter_builder.dart
@@ -19,13 +19,13 @@
import '../source/builder_factory.dart';
import '../source/constructor_declaration.dart';
import '../source/source_factory_builder.dart';
-import '../source/source_field_builder.dart';
import '../source/source_library_builder.dart';
import 'builder.dart';
import 'constructor_builder.dart';
import 'declaration_builders.dart';
import 'member_builder.dart';
import 'omitted_type_builder.dart';
+import 'property_builder.dart';
import 'type_builder.dart';
import 'variable_builder.dart';
@@ -229,7 +229,7 @@
ClassHierarchyBase hierarchy) {
String fieldName = isWildcardLoweredFormalParameter(name) ? '_' : name;
Builder? fieldBuilder = declarationBuilder.lookupLocalMember(fieldName);
- if (fieldBuilder is SourceFieldBuilder) {
+ if (fieldBuilder is PropertyBuilder && fieldBuilder.isField) {
DartType fieldType = fieldBuilder.inferType(hierarchy);
fieldType = constructorDeclaration.substituteFieldType(fieldType);
type.registerInferredType(fieldType);
diff --git a/pkg/front_end/lib/src/builder/invalid_type_declaration_builder.dart b/pkg/front_end/lib/src/builder/invalid_type_declaration_builder.dart
index b4dc83d..fb8ec6e 100644
--- a/pkg/front_end/lib/src/builder/invalid_type_declaration_builder.dart
+++ b/pkg/front_end/lib/src/builder/invalid_type_declaration_builder.dart
@@ -28,7 +28,7 @@
@override
// Coverage-ignore(suite): Not run.
- Uri? get fileUri => message.uri;
+ Uri get fileUri => message.uri!;
@override
DartType buildAliasedType(
diff --git a/pkg/front_end/lib/src/builder/member_builder.dart b/pkg/front_end/lib/src/builder/member_builder.dart
index 98af57c..0c5c795 100644
--- a/pkg/front_end/lib/src/builder/member_builder.dart
+++ b/pkg/front_end/lib/src/builder/member_builder.dart
@@ -186,6 +186,7 @@
Uri get fileUri => memberBuilder.fileUri;
@override
+ // Coverage-ignore(suite): Not run.
bool get isExtensionTypeMember => memberBuilder.isExtensionTypeMember;
@override
@@ -206,6 +207,7 @@
bool get isDuplicate => memberBuilder.isDuplicate;
@override
+ // Coverage-ignore(suite): Not run.
bool get isField => memberBuilder.isField;
@override
@@ -231,9 +233,11 @@
bool get isSynthesized => false;
@override
+ // Coverage-ignore(suite): Not run.
bool get isInternalImplementation => false;
@override
+ // Coverage-ignore(suite): Not run.
bool get isNoSuchMethodForwarder => false;
@override
diff --git a/pkg/front_end/lib/src/builder/property_builder.dart b/pkg/front_end/lib/src/builder/property_builder.dart
new file mode 100644
index 0000000..fe65c62
--- /dev/null
+++ b/pkg/front_end/lib/src/builder/property_builder.dart
@@ -0,0 +1,41 @@
+// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:kernel/ast.dart';
+import 'package:kernel/class_hierarchy.dart';
+
+import 'member_builder.dart';
+
+abstract class PropertyBuilder implements MemberBuilder {
+ bool get hasInitializer;
+
+ @override
+ Uri get fileUri;
+
+ bool get isExtensionTypeDeclaredInstanceField;
+
+ bool get isLate;
+
+ bool get isFinal;
+
+ abstract DartType fieldType;
+
+ DartType inferType(ClassHierarchyBase hierarchy);
+
+ /// Builds the field initializers for each field used to encode this field
+ /// using the [fileOffset] for the created nodes and [value] as the initial
+ /// field value.
+ List<Initializer> buildInitializer(int fileOffset, Expression value,
+ {required bool isSynthetic});
+
+ /// Creates the AST node for this field as the default initializer.
+ void buildImplicitDefaultValue();
+
+ /// Create the [Initializer] for the implicit initialization of this field
+ /// in a constructor.
+ Initializer buildImplicitInitializer();
+
+ Initializer buildErroneousInitializer(Expression effect, Expression value,
+ {required int fileOffset});
+}
diff --git a/pkg/front_end/lib/src/fragment/field.dart b/pkg/front_end/lib/src/fragment/field.dart
index 0648f15..93694e2 100644
--- a/pkg/front_end/lib/src/fragment/field.dart
+++ b/pkg/front_end/lib/src/fragment/field.dart
@@ -4,7 +4,7 @@
part of 'fragment.dart';
-class FieldFragment implements Fragment {
+class FieldFragment implements Fragment, Inferable, InferredTypeListener {
@override
final String name;
@@ -21,7 +21,9 @@
// fields.
final bool isPrimaryConstructorField;
- SourceFieldBuilder? _builder;
+ SourcePropertyBuilder? _builder;
+
+ late final _FieldEncoding _encoding;
FieldFragment(
{required this.name,
@@ -59,6 +61,7 @@
return result;
}
+ // Coverage-ignore(suite): Not run.
Token? get constInitializerToken {
Token? result = _constInitializerToken;
// Ensure that we don't hold onto the token.
@@ -67,16 +70,377 @@
}
@override
- SourceFieldBuilder get builder {
+ SourcePropertyBuilder get builder {
assert(_builder != null, "Builder has not been computed for $this.");
return _builder!;
}
- void set builder(SourceFieldBuilder value) {
+ void set builder(SourcePropertyBuilder value) {
assert(_builder == null, "Builder has already been computed for $this.");
_builder = value;
+
+ SourceLibraryBuilder libraryBuilder = builder.libraryBuilder;
+
+ bool isAbstract = modifiers.isAbstract;
+ bool isExternal = modifiers.isExternal;
+ bool isInstanceMember = builder.isDeclarationInstanceMember;
+ bool isExtensionMember = builder.isExtensionMember;
+ bool isExtensionTypeMember = builder.isExtensionTypeMember;
+
+ // 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) {
+ _encoding = new AbstractOrExternalFieldEncoding(this,
+ isExtensionInstanceMember: isExtensionMember && isInstanceMember,
+ isExtensionTypeInstanceMember:
+ isExtensionTypeMember && isInstanceMember,
+ isAbstract: isAbstract,
+ isExternal: isExternal);
+ } else if (isExtensionTypeMember && isInstanceMember) {
+ if (isPrimaryConstructorField) {
+ _encoding = new RepresentationFieldEncoding(this);
+ } else {
+ // Field on a extension type. Encode as abstract.
+ // TODO(johnniwinther): Should we have an erroneous flag on such
+ // members?
+ _encoding = new AbstractOrExternalFieldEncoding(this,
+ isExtensionInstanceMember: isExtensionMember && isInstanceMember,
+ isExtensionTypeInstanceMember:
+ isExtensionTypeMember && isInstanceMember,
+ isAbstract: true,
+ isExternal: false,
+ isForcedExtension: true);
+ }
+ } else if (isLate &&
+ libraryBuilder.loader.target.backendTarget.isLateFieldLoweringEnabled(
+ hasInitializer: hasInitializer,
+ isFinal: isFinal,
+ isStatic: !isInstanceMember)) {
+ if (hasInitializer) {
+ if (isFinal) {
+ _encoding = new LateFinalFieldWithInitializerEncoding(this,
+ isSetStrategy: isSetStrategy);
+ } else {
+ _encoding = new LateFieldWithInitializerEncoding(this,
+ isSetStrategy: isSetStrategy);
+ }
+ } else {
+ if (isFinal) {
+ _encoding = new LateFinalFieldWithoutInitializerEncoding(this,
+ isSetStrategy: isSetStrategy);
+ } else {
+ _encoding = new LateFieldWithoutInitializerEncoding(this,
+ isSetStrategy: isSetStrategy);
+ }
+ }
+ } else if (libraryBuilder
+ .loader.target.backendTarget.useStaticFieldLowering &&
+ !isInstanceMember &&
+ !modifiers.isConst &&
+ hasInitializer) {
+ if (isFinal) {
+ _encoding = new LateFinalFieldWithInitializerEncoding(this,
+ isSetStrategy: isSetStrategy);
+ } else {
+ _encoding = new LateFieldWithInitializerEncoding(this,
+ isSetStrategy: isSetStrategy);
+ }
+ } else {
+ _encoding = new RegularFieldEncoding(this, isEnumElement: false);
+ }
+
+ type.registerInferredTypeListener(this);
+ Token? token = initializerToken;
+ if (type is InferableTypeBuilder) {
+ if (!modifiers.hasInitializer && _isStatic) {
+ // A static field without type and initializer will always be inferred
+ // to have type `dynamic`.
+ type.registerInferredType(const DynamicType());
+ } else {
+ // A field with no type and initializer or an instance field without
+ // type and initializer need to have the type inferred.
+ _encoding.type =
+ new InferredType.fromFieldFragmentInitializer(this, token);
+ type.registerInferable(this);
+ }
+ }
}
+ BodyBuilderContext createBodyBuilderContext() {
+ return new _FieldFragmentBodyBuilderContext(
+ this, builder.libraryBuilder, builder.declarationBuilder,
+ isDeclarationInstanceMember: builder.isDeclarationInstanceMember);
+ }
+
+ /// Registers that a `super` call has occurred in the initializer of this
+ /// field.
+ void registerSuperCall() {
+ _encoding.registerSuperCall();
+ }
+
+ void buildOutlineNode(SourceLibraryBuilder libraryBuilder,
+ NameScheme nameScheme, BuildNodesCallback f, FieldReference references,
+ {required List<TypeParameter>? classTypeParameters}) {
+ _encoding.buildOutlineNode(libraryBuilder, nameScheme, references,
+ isAbstractOrExternal: modifiers.isAbstract || modifiers.isExternal,
+ classTypeParameters: classTypeParameters);
+ if (type is! InferableTypeBuilder) {
+ fieldType = type.build(libraryBuilder, TypeUse.fieldType);
+ }
+ _encoding.registerMembers(f);
+ }
+
+ Iterable<Reference> getExportedMemberReferences(FieldReference references) {
+ return [
+ references.getterReference!,
+ if (hasSetter) references.setterReference!
+ ];
+ }
+
+ shared.Expression? _initializerExpression;
+
+ // Coverage-ignore(suite): Not run.
+ shared.Expression? get initializerExpression => _initializerExpression;
+
+ void buildOutlineExpressions(
+ ClassHierarchy classHierarchy,
+ SourceLibraryBuilder libraryBuilder,
+ DeclarationBuilder? declarationBuilder,
+ LookupScope parentScope,
+ List<Annotatable> annotatables,
+ {required bool isClassInstanceMember,
+ required bool createFileUriExpression}) {
+ BodyBuilderContext bodyBuilderContext = createBodyBuilderContext();
+ for (Annotatable annotatable in annotatables) {
+ _buildMetadataForOutlineExpressions(libraryBuilder, parentScope,
+ bodyBuilderContext, annotatable, metadata,
+ fileUri: fileUri, createFileUriExpression: createFileUriExpression);
+ }
+ // 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 ((modifiers.isConst ||
+ (isFinal &&
+ isClassInstanceMember &&
+ (declarationBuilder as SourceClassBuilder)
+ .declaresConstConstructor)) &&
+ _constInitializerToken != null) {
+ Token initializerToken = _constInitializerToken!;
+ LookupScope scope = declarationBuilder?.scope ?? libraryBuilder.scope;
+ BodyBuilder bodyBuilder = libraryBuilder.loader
+ .createBodyBuilderForOutlineExpression(
+ libraryBuilder, createBodyBuilderContext(), scope, fileUri);
+ bodyBuilder.constantContext = modifiers.isConst
+ ? ConstantContext.inferred
+ : ConstantContext.required;
+ Expression initializer = bodyBuilder.typeInferrer
+ .inferFieldInitializer(bodyBuilder, fieldType,
+ bodyBuilder.parseFieldInitializer(initializerToken))
+ .expression;
+ buildBody(classHierarchy.coreTypes, initializer);
+ bodyBuilder.performBacklogComputations();
+ if (computeSharedExpressionForTesting) {
+ // Coverage-ignore-block(suite): Not run.
+ _initializerExpression = parseFieldInitializer(libraryBuilder.loader,
+ initializerToken, libraryBuilder.importUri, fileUri, scope);
+ }
+ }
+ _constInitializerToken = null;
+ }
+
+ void checkTypes(SourceLibraryBuilder libraryBuilder,
+ TypeEnvironment typeEnvironment, SourcePropertyBuilder? setterBuilder,
+ {required bool isAbstract, required bool isExternal}) {
+ libraryBuilder.checkTypesInField(typeEnvironment,
+ isInstanceMember: builder.isDeclarationInstanceMember,
+ isLate: isLate,
+ isExternal: isExternal,
+ hasInitializer: hasInitializer,
+ fieldType: fieldType,
+ name: name,
+ nameLength: name.length,
+ nameOffset: nameOffset,
+ fileUri: fileUri);
+ }
+
+ void ensureTypes(
+ ClassMembersBuilder membersBuilder,
+ Set<ClassMember>? getterOverrideDependencies,
+ Set<ClassMember>? setterOverrideDependencies) {
+ if (getterOverrideDependencies != null ||
+ setterOverrideDependencies != null) {
+ membersBuilder.inferFieldType(
+ builder.declarationBuilder as SourceClassBuilder,
+ type,
+ [...?getterOverrideDependencies, ...?setterOverrideDependencies],
+ name: name,
+ fileUri: fileUri,
+ nameOffset: nameOffset,
+ nameLength: name.length,
+ isAssignable: hasSetter);
+ } else {
+ type.build(builder.libraryBuilder, TypeUse.fieldType,
+ hierarchy: membersBuilder.hierarchyBuilder);
+ }
+ }
+
+ void checkVariance(
+ SourceClassBuilder sourceClassBuilder, TypeEnvironment typeEnvironment) {
+ sourceClassBuilder.checkVarianceInField(typeEnvironment,
+ fieldType: fieldType,
+ isInstanceMember: !_isStatic,
+ hasSetter: hasSetter,
+ isCovariantByDeclaration: modifiers.isCovariant,
+ fileUri: fileUri,
+ fileOffset: nameOffset);
+ }
+
+ int computeDefaultTypes(ComputeDefaultTypeContext context) {
+ if (type is! OmittedTypeBuilder) {
+ context.reportInboundReferenceIssuesForType(type);
+ context.recursivelyReportGenericFunctionTypesAsBoundsForType(type);
+ }
+ return 0;
+ }
+
+ Member get readTarget => _encoding.readTarget;
+
+ Member? get writeTarget => _encoding.writeTarget;
+
+ /// Whether the body of this field has been built.
+ ///
+ /// Constant fields have their initializer built in the outline so we avoid
+ /// building them twice as part of the non-outline build.
+ bool hasBodyBeenBuilt = false;
+
+ /// Builds the body of this field using [initializer] as the initializer
+ /// expression.
+ void buildBody(CoreTypes coreTypes, Expression? initializer) {
+ assert(!hasBodyBeenBuilt, "Body has already been built for $this.");
+ hasBodyBeenBuilt = true;
+ if (!modifiers.hasInitializer &&
+ initializer != null &&
+ initializer is! NullLiteral &&
+ // Coverage-ignore(suite): Not run.
+ !modifiers.isConst &&
+ // Coverage-ignore(suite): Not run.
+ !modifiers.isFinal) {
+ internalProblem(
+ messageInternalProblemAlreadyInitialized, nameOffset, fileUri);
+ }
+ _encoding.createBodies(coreTypes, initializer);
+ }
+
+ DartType get fieldType => _encoding.type;
+
+ @override
+ void inferTypes(ClassHierarchyBase hierarchy) {
+ inferType(hierarchy);
+ }
+
+ DartType inferType(ClassHierarchyBase hierarchy) {
+ if (fieldType is! InferredType) {
+ // We have already inferred a type.
+ return fieldType;
+ }
+
+ return builder.libraryBuilder.loader
+ .withUriForCrashReporting(fileUri, nameOffset, () {
+ InferredType implicitFieldType = fieldType as InferredType;
+ DartType inferredType = implicitFieldType.computeType(hierarchy);
+ if (fieldType is InferredType) {
+ // `fieldType` may have changed if a circularity was detected when
+ // [inferredType] was computed.
+ type.registerInferredType(inferredType);
+
+ // TODO(johnniwinther): Isn't this handled in the [fieldType] setter?
+ IncludesTypeParametersNonCovariantly? needsCheckVisitor;
+ DeclarationBuilder? declarationBuilder = builder.declarationBuilder;
+ if (declarationBuilder is ClassBuilder) {
+ Class enclosingClass = declarationBuilder.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)) {
+ _encoding.setCovariantByClass();
+ }
+ }
+ }
+ return fieldType;
+ });
+ }
+
+ void set fieldType(DartType value) {
+ _encoding.type = value;
+ DeclarationBuilder? declarationBuilder = builder.declarationBuilder;
+ // TODO(johnniwinther): Should this be `hasSetter`?
+ if (!isFinal && !modifiers.isConst && declarationBuilder is ClassBuilder) {
+ Class enclosingClass = declarationBuilder.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)) {
+ _encoding.setCovariantByClass();
+ }
+ }
+ }
+ }
+
+ Initializer buildErroneousInitializer(Expression effect, Expression value,
+ {required int fileOffset}) {
+ return _encoding.buildErroneousInitializer(effect, value,
+ fileOffset: fileOffset);
+ }
+
+ void buildImplicitDefaultValue() {
+ _encoding.buildImplicitDefaultValue();
+ }
+
+ Initializer buildImplicitInitializer() {
+ return _encoding.buildImplicitInitializer();
+ }
+
+ List<Initializer> buildInitializer(int fileOffset, Expression value,
+ {required bool isSynthetic}) {
+ return _encoding.createInitializer(fileOffset, value,
+ isSynthetic: isSynthetic);
+ }
+
+ bool get hasInitializer => modifiers.hasInitializer;
+
+ bool get isExtensionTypeDeclaredInstanceField =>
+ builder.isExtensionTypeInstanceMember && !isPrimaryConstructorField;
+
+ bool get isFinal => modifiers.isFinal;
+
+ bool get isLate => modifiers.isLate;
+
+ bool get _isStatic =>
+ modifiers.isStatic || builder.declarationBuilder == null;
+
@override
String toString() => '$runtimeType($name,$fileUri,$nameOffset)';
+
+ @override
+ void onInferredType(DartType type) {
+ fieldType = type;
+ }
+
+ List<ClassMember> get localMembers => _encoding.localMembers;
+
+ List<ClassMember> get localSetters => _encoding.localSetters;
}
diff --git a/pkg/front_end/lib/src/fragment/field/body_builder_context.dart b/pkg/front_end/lib/src/fragment/field/body_builder_context.dart
new file mode 100644
index 0000000..a79fcb5
--- /dev/null
+++ b/pkg/front_end/lib/src/fragment/field/body_builder_context.dart
@@ -0,0 +1,74 @@
+// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of '../fragment.dart';
+
+class _FieldFragmentBodyBuilderContext extends BodyBuilderContext {
+ final FieldFragment _fragment;
+
+ _FieldFragmentBodyBuilderContext(
+ this._fragment,
+ SourceLibraryBuilder libraryBuilder,
+ DeclarationBuilder? declarationBuilder,
+ {required bool isDeclarationInstanceMember})
+ : super(libraryBuilder, declarationBuilder,
+ isDeclarationInstanceMember: isDeclarationInstanceMember);
+
+ @override
+ // Coverage-ignore(suite): Not run.
+ LocalScope computeFormalParameterInitializerScope(LocalScope parent) {
+ /// Initializer formals or super parameters cannot occur in getters so
+ /// we don't need to create a new scope.
+ return parent;
+ }
+
+ @override
+ bool get isLateField => _fragment.modifiers.isLate;
+
+ @override
+ bool get isAbstractField => _fragment.modifiers.isAbstract;
+
+ @override
+ bool get isExternalField => _fragment.modifiers.isExternal;
+
+ @override
+ // Coverage-ignore(suite): Not run.
+ int get memberNameOffset => _fragment.nameOffset;
+
+ @override
+ // Coverage-ignore(suite): Not run.
+ int get memberNameLength => _fragment.name.length;
+
+ @override
+ InstanceTypeParameterAccessState get instanceTypeParameterAccessState {
+ if (_fragment.builder.isExtensionMember && !isExternalField) {
+ return InstanceTypeParameterAccessState.Invalid;
+ } else {
+ return super.instanceTypeParameterAccessState;
+ }
+ }
+
+ @override
+ void registerSuperCall() {
+ _fragment.registerSuperCall();
+ }
+
+ @override
+ // Coverage-ignore(suite): Not run.
+ AugmentSuperTarget? get augmentSuperTarget {
+ if (_fragment.builder.isAugmentation) {
+ return _fragment.builder.augmentSuperTarget;
+ }
+ return null;
+ }
+
+ @override
+ ConstantContext get constantContext {
+ return _fragment.modifiers.isConst
+ ? ConstantContext.inferred
+ : !_fragment._isStatic && declarationDeclaresConstConstructor
+ ? ConstantContext.required
+ : ConstantContext.none;
+ }
+}
diff --git a/pkg/front_end/lib/src/fragment/field/class_member.dart b/pkg/front_end/lib/src/fragment/field/class_member.dart
new file mode 100644
index 0000000..8d0daa0
--- /dev/null
+++ b/pkg/front_end/lib/src/fragment/field/class_member.dart
@@ -0,0 +1,339 @@
+// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of '../fragment.dart';
+
+class _FieldClassMember implements ClassMember {
+ final SourcePropertyBuilder _builder;
+ final FieldFragment _fragment;
+
+ @override
+ final bool forSetter;
+
+ Covariance? _covariance;
+
+ _FieldClassMember(this._builder, this._fragment, {required this.forSetter});
+
+ @override
+ int get charOffset => _fragment.nameOffset;
+
+ @override
+ DeclarationBuilder get declarationBuilder => _builder.declarationBuilder!;
+
+ @override
+ // Coverage-ignore(suite): Not run.
+ List<ClassMember> get declarations =>
+ throw new UnsupportedError('$runtimeType.declarations');
+
+ @override
+ Uri get fileUri => _fragment.fileUri;
+
+ @override
+ // Coverage-ignore(suite): Not run.
+ String get fullName {
+ String className = declarationBuilder.fullNameForErrors;
+ return "${className}.${fullNameForErrors}";
+ }
+
+ @override
+ String get fullNameForErrors => _builder.fullNameForErrors;
+
+ @override
+ Covariance getCovariance(ClassMembersBuilder membersBuilder) {
+ return _covariance ??= forSetter
+ ? new Covariance.fromMember(getMember(membersBuilder),
+ forSetter: forSetter)
+ : const Covariance.empty();
+ }
+
+ @override
+ Member getMember(ClassMembersBuilder membersBuilder) {
+ _builder.ensureTypes(membersBuilder);
+ return forSetter ? _builder.writeTarget! : _builder.readTarget!;
+ }
+
+ @override
+ // Coverage-ignore(suite): Not run.
+ MemberResult getMemberResult(ClassMembersBuilder membersBuilder) {
+ if (isStatic) {
+ return new StaticMemberResult(getMember(membersBuilder), memberKind,
+ isDeclaredAsField: true,
+ fullName: '${declarationBuilder.name}.${_builder.memberName.text}');
+ } else if (_builder.isExtensionTypeMember) {
+ ExtensionTypeDeclaration extensionTypeDeclaration =
+ (declarationBuilder as ExtensionTypeDeclarationBuilder)
+ .extensionTypeDeclaration;
+ Member member = getTearOff(membersBuilder) ?? getMember(membersBuilder);
+ return new ExtensionTypeMemberResult(
+ extensionTypeDeclaration, member, memberKind, name,
+ isDeclaredAsField: true);
+ } else {
+ return new TypeDeclarationInstanceMemberResult(
+ getMember(membersBuilder), memberKind,
+ isDeclaredAsField: true);
+ }
+ }
+
+ @override
+ // Coverage-ignore(suite): Not run.
+ Member? getTearOff(ClassMembersBuilder membersBuilder) => null;
+
+ @override
+ bool get hasDeclarations => false;
+
+ @override
+ void inferType(ClassMembersBuilder membersBuilder) {
+ _builder.ensureTypes(membersBuilder);
+ }
+
+ @override
+ ClassMember get interfaceMember => this;
+
+ @override
+ // TODO(johnniwinther): This should not be determined by the builder. A
+ // property can have a non-abstract getter and an abstract setter or the
+ // reverse. With augmentations, abstract introductory declarations might even
+ // be implemented by augmentations.
+ bool get isAbstract => _fragment.modifiers.isAbstract;
+
+ @override
+ bool get isDuplicate => _builder.isDuplicate;
+
+ @override
+ bool get isExtensionTypeMember => _builder.isExtensionTypeMember;
+
+ @override
+ bool get isField => true;
+
+ @override
+ // Coverage-ignore(suite): Not run.
+ bool get isGetter => false; //!forSetter;
+
+ @override
+ bool get isInternalImplementation => false;
+
+ @override
+ bool get isNoSuchMethodForwarder => false;
+
+ @override
+ // Coverage-ignore(suite): Not run.
+ bool isObjectMember(ClassBuilder objectClass) {
+ return declarationBuilder == objectClass;
+ }
+
+ @override
+ bool get isProperty => true;
+
+ @override
+ bool isSameDeclaration(ClassMember other) {
+ return other is _FieldClassMember && _builder == other._builder;
+ }
+
+ @override
+ bool get isSetter => false; //forSetter;
+
+ @override
+ bool get isSourceDeclaration => true;
+
+ @override
+ bool get isStatic => _fragment.modifiers.isStatic;
+
+ @override
+ bool get isSynthesized => false;
+
+ @override
+ ClassMemberKind get memberKind =>
+ forSetter ? ClassMemberKind.Setter : ClassMemberKind.Getter;
+
+ @override
+ Name get name => _builder.memberName;
+
+ @override
+ void registerOverrideDependency(Set<ClassMember> overriddenMembers) {
+ if (forSetter) {
+ _builder.registerSetterOverrideDependency(overriddenMembers);
+ } else {
+ _builder.registerGetterOverrideDependency(overriddenMembers);
+ }
+ }
+
+ @override
+ String toString() => '$runtimeType($fullName,forSetter=${forSetter})';
+}
+
+class _SynthesizedFieldClassMember implements ClassMember {
+ final SourcePropertyBuilder _builder;
+ final _SynthesizedFieldMemberKind _kind;
+
+ final Member _member;
+
+ final Name _name;
+
+ Covariance? _covariance;
+
+ @override
+ final ClassMemberKind memberKind;
+
+ _SynthesizedFieldClassMember(
+ this._builder, this._member, this._name, this._kind, this.memberKind);
+
+ @override
+ bool get isInternalImplementation => _kind.isInternalImplementation;
+
+ @override
+ Member getMember(ClassMembersBuilder membersBuilder) {
+ _builder.ensureTypes(membersBuilder);
+ return _member;
+ }
+
+ @override
+ Member? getTearOff(ClassMembersBuilder membersBuilder) {
+ // Ensure field type is computed.
+ getMember(membersBuilder);
+ return null;
+ }
+
+ @override
+ Covariance getCovariance(ClassMembersBuilder membersBuilder) {
+ return _covariance ??= new Covariance.fromMember(getMember(membersBuilder),
+ forSetter: forSetter);
+ }
+
+ @override
+ MemberResult getMemberResult(ClassMembersBuilder membersBuilder) {
+ return new TypeDeclarationInstanceMemberResult(
+ getMember(membersBuilder), memberKind,
+ isDeclaredAsField: _builder.isField);
+ }
+
+ @override
+ void inferType(ClassMembersBuilder membersBuilder) {
+ _builder.ensureTypes(membersBuilder);
+ }
+
+ @override
+ void registerOverrideDependency(Set<ClassMember> overriddenMembers) {
+ if (forSetter) {
+ _builder.registerSetterOverrideDependency(overriddenMembers);
+ } else {
+ _builder.registerGetterOverrideDependency(overriddenMembers);
+ }
+ }
+
+ @override
+ bool get isSourceDeclaration => true;
+
+ @override
+ bool get forSetter => memberKind == ClassMemberKind.Setter;
+
+ @override
+ bool get isProperty => memberKind != ClassMemberKind.Method;
+
+ @override
+ DeclarationBuilder get declarationBuilder => _builder.declarationBuilder!;
+
+ @override
+ // Coverage-ignore(suite): Not run.
+ bool isObjectMember(ClassBuilder objectClass) {
+ return declarationBuilder == objectClass;
+ }
+
+ @override
+ bool get isDuplicate => _builder.isDuplicate;
+
+ @override
+ bool get isStatic => _builder.isStatic;
+
+ @override
+ bool get isField => _member is Field;
+
+ @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
+ Name get name => _name;
+
+ @override
+ // Coverage-ignore(suite): Not run.
+ String get fullName {
+ String suffix = isSetter ? "=" : "";
+ String className = declarationBuilder.fullNameForErrors;
+ return "${className}.${fullNameForErrors}$suffix";
+ }
+
+ @override
+ String get fullNameForErrors => _builder.fullNameForErrors;
+
+ @override
+ Uri get fileUri => _builder.fileUri;
+
+ @override
+ int get charOffset => _builder.fileOffset;
+
+ @override
+ bool get isAbstract => _member.isAbstract;
+
+ @override
+ bool get isSynthesized => false;
+
+ @override
+ bool get hasDeclarations => false;
+
+ @override
+ // Coverage-ignore(suite): Not run.
+ 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 &&
+ _builder == other._builder &&
+ _kind == other._kind;
+ }
+
+ @override
+ bool get isNoSuchMethodForwarder => false;
+
+ @override
+ String toString() => '_SynthesizedFieldClassMember('
+ '$_builder,$_member,$_kind,forSetter=${forSetter})';
+
+ @override
+ bool get isExtensionTypeMember => _builder.isExtensionTypeMember;
+}
+
+enum _SynthesizedFieldMemberKind {
+ /// A `isSet` field used for late lowering.
+ LateIsSet(isInternalImplementation: true),
+
+ /// A field used for the value of a late lowered field.
+ LateField(isInternalImplementation: true),
+
+ /// A getter or setter used for late lowering.
+ LateGetterSetter(isInternalImplementation: false),
+
+ /// A getter or setter used for abstract or external fields.
+ AbstractExternalGetterSetter(isInternalImplementation: false),
+
+ /// A getter for an extension type declaration representation field.
+ RepresentationField(isInternalImplementation: false),
+ ;
+
+ final bool isInternalImplementation;
+
+ const _SynthesizedFieldMemberKind({required this.isInternalImplementation});
+}
diff --git a/pkg/front_end/lib/src/fragment/field/encoding.dart b/pkg/front_end/lib/src/fragment/field/encoding.dart
new file mode 100644
index 0000000..4aaf45d
--- /dev/null
+++ b/pkg/front_end/lib/src/fragment/field/encoding.dart
@@ -0,0 +1,1326 @@
+// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of '../fragment.dart';
+
+/// Strategy pattern for creating different encodings of a declared field.
+///
+/// This is used to provide lowerings for late fields using synthesized getters
+/// and setters.
+sealed class _FieldEncoding {
+ /// 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 buildOutlineNode(SourceLibraryBuilder libraryBuilder,
+ NameScheme nameScheme, FieldReference references,
+ {required bool isAbstractOrExternal,
+ required List<TypeParameter>? classTypeParameters});
+
+ /// Calls [f] for each member needed for this field encoding.
+ void registerMembers(BuildNodesCallback f);
+
+ /// 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);
+
+ /// The type of the declared field.
+ abstract DartType type;
+
+ List<Initializer> createInitializer(int fileOffset, Expression value,
+ {required bool isSynthetic});
+
+ /// Creates the AST node for this field as the default initializer.
+ void buildImplicitDefaultValue();
+
+ /// Create the [Initializer] for the implicit initialization of this field
+ /// in a constructor.
+ Initializer buildImplicitInitializer();
+
+ Initializer buildErroneousInitializer(Expression effect, Expression value,
+ {required int fileOffset});
+
+ /// Registers that the (implicit) setter associated with this field needs to
+ /// contain a runtime type check to deal with generic covariance.
+ void setCovariantByClass();
+
+ /// Returns the field that holds the field value at runtime.
+ Field get field;
+
+ /// The [Member] built during [SourceFieldBuilder.buildOutlineExpressions].
+ Member get builtMember;
+
+ /// 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 reference used to read the field value.
+ Reference get readTargetReference;
+
+ /// Returns the member used to write to the field.
+ Member? get writeTarget;
+
+ /// Returns the reference used to write to the field.
+ Reference? get writeTargetReference;
+
+ /// Returns the references to the generated members that are visible through
+ /// exports.
+ ///
+ /// This is the getter reference, and, if available, the setter reference.
+ Iterable<Reference> get exportedReferenceMembers;
+
+ /// Returns a list of the field, getters and methods created by this field
+ /// encoding.
+ List<ClassMember> get localMembers;
+
+ /// Returns a list of the setters created by this field encoding.
+ List<ClassMember> get localSetters;
+
+ /// Registers that a `super` call has occurred in the initializer of this
+ /// field.
+ void registerSuperCall();
+}
+
+class RegularFieldEncoding implements _FieldEncoding {
+ final FieldFragment _fragment;
+ final bool isEnumElement;
+ Field? _field;
+ DartType _type = const DynamicType();
+
+ RegularFieldEncoding(this._fragment, {required this.isEnumElement}) {}
+
+ @override
+ DartType get type => _type;
+
+ @override
+ void set type(DartType value) {
+ _type = value;
+ _field?.type = value;
+ }
+
+ @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 buildOutlineNode(SourceLibraryBuilder libraryBuilder,
+ NameScheme nameScheme, FieldReference references,
+ {required bool isAbstractOrExternal,
+ required List<TypeParameter>? classTypeParameters}) {
+ bool isImmutable = _fragment.modifiers.isLate
+ ? (_fragment.modifiers.isFinal && _fragment.hasInitializer)
+ : (_fragment.modifiers.isFinal || _fragment.modifiers.isConst);
+ _field = isImmutable
+ ? new Field.immutable(dummyName,
+ type: _type,
+ isFinal: _fragment.modifiers.isFinal,
+ isConst: _fragment.modifiers.isConst,
+ isLate: _fragment.modifiers.isLate,
+ fileUri: _fragment.fileUri,
+ fieldReference: references.fieldReference,
+ getterReference: references.fieldGetterReference,
+ isEnumElement: isEnumElement)
+ : new Field.mutable(dummyName,
+ type: _type,
+ isFinal: _fragment.modifiers.isFinal,
+ isLate: _fragment.modifiers.isLate,
+ fileUri: _fragment.fileUri,
+ fieldReference: references.fieldReference,
+ getterReference: references.fieldGetterReference,
+ setterReference: references.fieldSetterReference);
+ nameScheme
+ .getFieldMemberName(FieldNameType.Field, _fragment.name,
+ isSynthesized: false)
+ .attachMember(_field!);
+ _field!
+ ..fileOffset = _fragment.nameOffset
+ ..fileEndOffset = _fragment.endOffset;
+ _field!..isCovariantByDeclaration = _fragment.modifiers.isCovariant;
+ if (_fragment.builder.isExtensionMember) {
+ _field!
+ ..isStatic = true
+ ..isExtensionMember = true;
+ } else if (_fragment.builder.isExtensionTypeMember) {
+ _field!
+ ..isStatic = _fragment.builder.isStatic
+ ..isExtensionTypeMember = true;
+ } else {
+ bool isInstanceMember =
+ !_fragment.builder.isStatic && !_fragment.builder.isTopLevel;
+ _field!
+ ..isStatic = !isInstanceMember
+ ..isExtensionMember = false;
+ }
+ _field!.isLate = _fragment.modifiers.isLate;
+ }
+
+ @override
+ void registerMembers(BuildNodesCallback f) {
+ f(
+ member: _field!,
+ kind: _fragment.builder.isExtensionMember ||
+ _fragment.builder.isExtensionTypeMember
+ ? BuiltMemberKind.ExtensionField
+ : BuiltMemberKind.Field);
+ }
+
+ @override
+ void setCovariantByClass() {
+ if (_field!.hasSetter) {
+ _field!.isCovariantByClass = true;
+ }
+ }
+
+ @override
+ // Coverage-ignore(suite): Not run.
+ Field get field => _field!;
+
+ @override
+ // Coverage-ignore(suite): Not run.
+ Member get builtMember => _field!;
+
+ @override
+ // Coverage-ignore(suite): Not run.
+ Iterable<Annotatable> get annotatables => [_field!];
+
+ @override
+ Member get readTarget => _field!;
+
+ @override
+ // Coverage-ignore(suite): Not run.
+ Reference get readTargetReference => _field!.getterReference;
+
+ @override
+ Member get writeTarget => _field!;
+
+ @override
+ // Coverage-ignore(suite): Not run.
+ Reference? get writeTargetReference => _field!.setterReference;
+
+ @override
+ // Coverage-ignore(suite): Not run.
+ Iterable<Reference> get exportedReferenceMembers => [
+ _field!.getterReference,
+ if (_field!.hasSetter) _field!.setterReference!
+ ];
+
+ @override
+ List<ClassMember> get localMembers => <ClassMember>[
+ new _FieldClassMember(_fragment.builder, _fragment, forSetter: false)
+ ];
+
+ @override
+ List<ClassMember> get localSetters => _fragment.hasSetter
+ ? [new _FieldClassMember(_fragment.builder, _fragment, forSetter: true)]
+ : const [];
+
+ @override
+ void buildImplicitDefaultValue() {
+ _field!.initializer = new NullLiteral()..parent = _field;
+ }
+
+ @override
+ Initializer buildImplicitInitializer() {
+ return new FieldInitializer(_field!, new NullLiteral())..isSynthetic = true;
+ }
+
+ @override
+ Initializer buildErroneousInitializer(Expression effect, Expression value,
+ {required int fileOffset}) {
+ return new ShadowInvalidFieldInitializer(type, value, effect)
+ ..fileOffset = fileOffset;
+ }
+
+ @override
+ void registerSuperCall() {
+ _field!.transformerFlags |= TransformerFlag.superCalls;
+ }
+}
+
+abstract class AbstractLateFieldEncoding implements _FieldEncoding {
+ final FieldFragment _fragment;
+ DartType? _type;
+ Field? _field;
+ Field? _lateIsSetField;
+ 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._fragment,
+ {required late_lowering.IsSetStrategy isSetStrategy})
+ : _isSetStrategy = isSetStrategy,
+ _forceIncludeIsSetField =
+ isSetStrategy == late_lowering.IsSetStrategy.forceUseIsSetField {}
+
+ late_lowering.IsSetEncoding get isSetEncoding {
+ assert(_type != null,
+ "Type has not been computed for field ${_fragment.name}.");
+ return _isSetEncoding ??=
+ late_lowering.computeIsSetEncoding(_type!, _isSetStrategy);
+ }
+
+ @override
+ void createBodies(CoreTypes coreTypes, Expression? initializer) {
+ assert(_type != null,
+ "Type has not been computed for field ${_fragment.name}.");
+ if (isSetEncoding == late_lowering.IsSetEncoding.useSentinel) {
+ _field!.initializer = new StaticInvocation(coreTypes.createSentinelMethod,
+ new Arguments([], types: [_type!])..fileOffset = _fragment.nameOffset)
+ ..fileOffset = _fragment.nameOffset
+ ..parent = _field;
+ } else {
+ _field!.initializer = new NullLiteral()
+ ..fileOffset = _fragment.nameOffset
+ ..parent = _field;
+ }
+ if (_lateIsSetField != null) {
+ _lateIsSetField!.initializer = new BoolLiteral(false)
+ ..fileOffset = _fragment.nameOffset
+ ..parent = _lateIsSetField;
+ }
+ _lateGetter!.function.body =
+ _createGetterBody(coreTypes, _fragment.name, initializer)
+ ..parent = _lateGetter!.function;
+ // The initializer is copied from [_field] to [_lateGetter] so we copy the
+ // transformer flags to reflect whether the getter contains super calls.
+ _lateGetter!.transformerFlags = _field!.transformerFlags;
+
+ if (_lateSetter != null) {
+ _lateSetter!.function.body = _createSetterBody(coreTypes, _fragment.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 parameter type of undetermined
+ /// nullability.
+ Expression _createFieldRead({bool needsPromotion = false}) {
+ assert(_type != null,
+ "Type has not been computed for field ${_fragment.name}.");
+ if (needsPromotion) {
+ VariableDeclaration variable = new VariableDeclaration.forValue(
+ _createFieldGet(_field!),
+ type: _type!.withDeclaredNullability(Nullability.nullable))
+ ..fileOffset = _fragment.nameOffset;
+ return new Let(variable,
+ new VariableGet(variable, _type)..fileOffset = _fragment.nameOffset);
+ } else {
+ return _createFieldGet(_field!);
+ }
+ }
+
+ /// Creates an [Expression] that reads [field].
+ Expression _createFieldGet(Field field) {
+ if (field.isStatic) {
+ return new StaticGet(field)..fileOffset = _fragment.nameOffset;
+ } else {
+ // No substitution needed for the result type, since any type parameters
+ // in there are also in scope at the access site.
+ return new InstanceGet(InstanceAccessKind.Instance,
+ new ThisExpression()..fileOffset = _fragment.nameOffset, field.name,
+ interfaceTarget: field, resultType: field.type)
+ ..fileOffset = _fragment.nameOffset;
+ }
+ }
+
+ /// Creates an [Expression] that writes [value] to [field].
+ Expression _createFieldSet(Field field, Expression value) {
+ if (field.isStatic) {
+ return new StaticSet(field, value)..fileOffset = _fragment.nameOffset;
+ } else {
+ return new InstanceSet(
+ InstanceAccessKind.Instance,
+ new ThisExpression()..fileOffset = _fragment.nameOffset,
+ field.name,
+ value,
+ interfaceTarget: field)
+ ..fileOffset = _fragment.nameOffset;
+ }
+ }
+
+ Statement _createGetterBody(
+ CoreTypes coreTypes, String name, Expression? initializer);
+
+ Procedure? _createSetter(Uri fileUri, int charOffset, Reference? reference,
+ {required bool isCovariantByDeclaration}) {
+ VariableDeclaration parameter =
+ new VariableDeclaration("${_fragment.name}#param")
+ ..isCovariantByDeclaration = isCovariantByDeclaration
+ ..fileOffset = _fragment.nameOffset;
+ return new Procedure(
+ dummyName,
+ ProcedureKind.Setter,
+ new FunctionNode(null,
+ positionalParameters: [parameter], returnType: const VoidType())
+ ..fileOffset = charOffset
+ ..fileEndOffset = _fragment.endOffset,
+ fileUri: fileUri,
+ reference: reference)
+ ..fileOffset = charOffset
+ ..fileEndOffset = _fragment.endOffset;
+ }
+
+ Statement _createSetterBody(
+ CoreTypes coreTypes, String name, VariableDeclaration parameter);
+
+ @override
+ DartType get type {
+ assert(_type != null,
+ "Type has not been computed for field ${_fragment.name}.");
+ return _type!;
+ }
+
+ /// Updates the field/getter/setter types of [_field], [_lateGetter] and
+ /// [_lateSetter] to match the value of [_type].
+ ///
+ /// This allows for creating the members and computing the type in arbitrary
+ /// order.
+ void _updateMemberTypes() {
+ DartType? type = _type;
+ Field? field = _field;
+ if (type != null && type is! InferredType && field != null) {
+ field.type = type.withDeclaredNullability(Nullability.nullable);
+ _lateGetter!.function.returnType = type;
+ _lateSetter?.function.positionalParameters.single.type = type;
+ 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 set type(DartType value) {
+ assert(_type == null || _type is InferredType,
+ "Type has already been computed for field ${_fragment.name}.");
+ _type = value;
+ _updateMemberTypes();
+ }
+
+ @override
+ void setCovariantByClass() {
+ if (_field!.hasSetter) {
+ _field!.isCovariantByClass = true;
+ }
+ _lateSetter?.function.positionalParameters.single.isCovariantByClass = true;
+ }
+
+ @override
+ Field get field => _field!;
+
+ @override
+ // Coverage-ignore(suite): Not run.
+ Member get builtMember => _field!;
+
+ @override
+ // Coverage-ignore(suite): Not run.
+ Iterable<Annotatable> get annotatables {
+ List<Annotatable> list = [_lateGetter!];
+ if (_lateSetter != null) {
+ list.add(_lateSetter!);
+ }
+ return list;
+ }
+
+ @override
+ Member get readTarget => _lateGetter!;
+
+ @override
+ // Coverage-ignore(suite): Not run.
+ Reference get readTargetReference => _lateGetter!.reference;
+
+ @override
+ Member? get writeTarget => _lateSetter;
+
+ @override
+ // Coverage-ignore(suite): Not run.
+ Reference? get writeTargetReference => _lateSetter?.reference;
+
+ @override
+ // Coverage-ignore(suite): Not run.
+ Iterable<Reference> get exportedReferenceMembers {
+ if (_lateSetter != null) {
+ return [_lateGetter!.reference, _lateSetter!.reference];
+ }
+ return [_lateGetter!.reference];
+ }
+
+ @override
+ void buildOutlineNode(SourceLibraryBuilder libraryBuilder,
+ NameScheme nameScheme, FieldReference references,
+ {required bool isAbstractOrExternal,
+ required List<TypeParameter>? classTypeParameters}) {
+ _field = new Field.mutable(dummyName,
+ fileUri: _fragment.fileUri,
+ fieldReference: references.fieldReference,
+ getterReference: references.fieldGetterReference,
+ setterReference: references.fieldSetterReference)
+ ..fileOffset = _fragment.nameOffset
+ ..fileEndOffset = _fragment.endOffset
+ ..isInternalImplementation = true;
+ nameScheme
+ .getFieldMemberName(FieldNameType.Field, _fragment.name,
+ isSynthesized: true)
+ .attachMember(_field!);
+ 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(dummyName,
+ fileUri: _fragment.fileUri,
+ fieldReference: references.lateIsSetFieldReference,
+ getterReference: references.lateIsSetGetterReference,
+ setterReference: references.lateIsSetSetterReference)
+ ..fileOffset = _fragment.nameOffset
+ ..fileEndOffset = _fragment.endOffset
+ ..isInternalImplementation = true;
+ nameScheme
+ .getFieldMemberName(FieldNameType.IsSetField, _fragment.name,
+ isSynthesized: true)
+ .attachMember(_lateIsSetField!);
+ break;
+ }
+ _lateGetter = new Procedure(
+ dummyName,
+ ProcedureKind.Getter,
+ new FunctionNode(null)
+ ..fileOffset = _fragment.nameOffset
+ ..fileEndOffset = _fragment.endOffset,
+ fileUri: _fragment.fileUri,
+ reference: references.lateGetterReference)
+ ..fileOffset = _fragment.nameOffset
+ ..fileEndOffset = _fragment.endOffset;
+ nameScheme
+ .getFieldMemberName(FieldNameType.Getter, _fragment.name,
+ isSynthesized: true)
+ .attachMember(_lateGetter!);
+ _lateSetter = _createSetter(
+ _fragment.fileUri, _fragment.nameOffset, references.lateSetterReference,
+ isCovariantByDeclaration: _fragment.modifiers.isCovariant);
+ if (_lateSetter != null) {
+ nameScheme
+ .getFieldMemberName(FieldNameType.Setter, _fragment.name,
+ isSynthesized: true)
+ .attachMember(_lateSetter!);
+ }
+
+ bool isInstanceMember =
+ !_fragment.builder.isStatic && !_fragment.builder.isTopLevel;
+ bool isExtensionMember = _fragment.builder.isExtensionMember;
+ bool isExtensionTypeMember = _fragment.builder.isExtensionTypeMember;
+ if (isExtensionMember) {
+ _field!
+ ..isStatic = true
+ ..isExtensionMember = isExtensionMember;
+ isInstanceMember = false;
+ } else if (isExtensionTypeMember) {
+ // Coverage-ignore-block(suite): Not run.
+ _field!
+ ..isStatic = _fragment.builder.isStatic
+ ..isExtensionTypeMember = true;
+ } else {
+ _field!
+ ..isStatic = !isInstanceMember
+ ..isExtensionMember = false;
+ }
+ if (_lateIsSetField != null) {
+ _lateIsSetField!
+ ..isStatic = !isInstanceMember
+ ..isExtensionMember = isExtensionMember
+ ..isExtensionTypeMember = isExtensionTypeMember
+ ..type = libraryBuilder.loader
+ .createCoreType('bool', Nullability.nonNullable);
+ }
+ _lateGetter!
+ ..isStatic = !isInstanceMember
+ ..isExtensionMember = isExtensionMember
+ ..isExtensionTypeMember = isExtensionTypeMember;
+ if (_lateSetter != null) {
+ _lateSetter!
+ ..isStatic = !isInstanceMember
+ ..isExtensionMember = isExtensionMember
+ ..isExtensionTypeMember = isExtensionTypeMember;
+ }
+ _updateMemberTypes();
+ }
+
+ @override
+ void registerMembers(BuildNodesCallback f) {
+ f(
+ member: _field!,
+ kind: _fragment.builder.isExtensionMember ||
+ _fragment.builder.isExtensionTypeMember
+ ? BuiltMemberKind.ExtensionField
+ : BuiltMemberKind.Field);
+ if (_lateIsSetField != null) {
+ _forceIncludeIsSetField = true;
+ f(member: _lateIsSetField!, kind: BuiltMemberKind.LateIsSetField);
+ }
+ f(member: _lateGetter!, kind: BuiltMemberKind.LateGetter);
+ if (_lateSetter != null) {
+ f(member: _lateSetter!, kind: BuiltMemberKind.LateSetter);
+ }
+ }
+
+ @override
+ List<ClassMember> get localMembers {
+ List<ClassMember> list = [
+ new _SynthesizedFieldClassMember(_fragment.builder, field, field.name,
+ _SynthesizedFieldMemberKind.LateField, ClassMemberKind.Getter),
+ new _SynthesizedFieldClassMember(
+ _fragment.builder,
+ _lateGetter!,
+ _fragment.builder.memberName,
+ _SynthesizedFieldMemberKind.LateGetterSetter,
+ ClassMemberKind.Getter)
+ ];
+ if (_lateIsSetField != null) {
+ list.add(new _SynthesizedFieldClassMember(
+ _fragment.builder,
+ _lateIsSetField!,
+ _lateIsSetField!.name,
+ _SynthesizedFieldMemberKind.LateIsSet,
+ ClassMemberKind.Getter));
+ }
+ return list;
+ }
+
+ @override
+ List<ClassMember> get localSetters {
+ List<ClassMember> list = [
+ new _SynthesizedFieldClassMember(_fragment.builder, field, field.name,
+ _SynthesizedFieldMemberKind.LateField, ClassMemberKind.Setter),
+ ];
+ if (_lateIsSetField != null) {
+ list.add(new _SynthesizedFieldClassMember(
+ _fragment.builder,
+ _lateIsSetField!,
+ _lateIsSetField!.name,
+ _SynthesizedFieldMemberKind.LateIsSet,
+ ClassMemberKind.Setter));
+ }
+ if (_lateSetter != null) {
+ list.add(new _SynthesizedFieldClassMember(
+ _fragment.builder,
+ _lateSetter!,
+ _fragment.builder.memberName,
+ _SynthesizedFieldMemberKind.LateGetterSetter,
+ ClassMemberKind.Setter));
+ }
+ return list;
+ }
+
+ @override
+ void registerSuperCall() {
+ _field!.transformerFlags |= TransformerFlag.superCalls;
+ }
+}
+
+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, _fragment.nameOffset, 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, _fragment.nameOffset, name, type,
+ createVariableRead: _createFieldRead,
+ createIsSetRead: () => _createFieldGet(_lateIsSetField!),
+ isSetEncoding: isSetEncoding,
+ forField: true);
+ }
+
+ @override
+ void buildImplicitDefaultValue() {
+ throw new UnsupportedError("$runtimeType.buildImplicitDefaultValue");
+ }
+
+ @override
+ Initializer buildImplicitInitializer() {
+ throw new UnsupportedError("$runtimeType.buildImplicitInitializer");
+ }
+
+ @override
+ Initializer buildErroneousInitializer(Expression effect, Expression value,
+ {required int fileOffset}) {
+ throw new UnsupportedError("$runtimeType.buildDuplicatedInitializer");
+ }
+}
+
+class LateFieldWithoutInitializerEncoding extends AbstractLateFieldEncoding
+ with NonFinalLate, LateWithoutInitializer {
+ LateFieldWithoutInitializerEncoding(super._fragment,
+ {required super.isSetStrategy});
+}
+
+class LateFieldWithInitializerEncoding extends AbstractLateFieldEncoding
+ with NonFinalLate {
+ LateFieldWithInitializerEncoding(super._fragment,
+ {required super.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, _fragment.nameOffset, name, _type!, initializer!,
+ createVariableRead: _createFieldRead,
+ createVariableWrite: (Expression value) =>
+ _createFieldSet(_field!, value),
+ createIsSetRead: () => _createFieldGet(_lateIsSetField!),
+ createIsSetWrite: (Expression value) =>
+ _createFieldSet(_lateIsSetField!, value),
+ isSetEncoding: isSetEncoding);
+ }
+
+ @override
+ void buildImplicitDefaultValue() {
+ throw new UnsupportedError("$runtimeType.buildImplicitDefaultValue");
+ }
+
+ @override
+ Initializer buildImplicitInitializer() {
+ throw new UnsupportedError("$runtimeType.buildImplicitInitializer");
+ }
+
+ @override
+ Initializer buildErroneousInitializer(Expression effect, Expression value,
+ {required int fileOffset}) {
+ throw new UnsupportedError("$runtimeType.buildDuplicatedInitializer");
+ }
+}
+
+class LateFinalFieldWithoutInitializerEncoding extends AbstractLateFieldEncoding
+ with LateWithoutInitializer {
+ LateFinalFieldWithoutInitializerEncoding(super._fragment,
+ {required super.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, _fragment.nameOffset, 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(super._fragment,
+ {required super.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, _fragment.nameOffset, 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(Uri fileUri, int charOffset, Reference? reference,
+ {required bool isCovariantByDeclaration}) =>
+ null;
+
+ @override
+ // Coverage-ignore(suite): Not run.
+ Statement _createSetterBody(
+ CoreTypes coreTypes, String name, VariableDeclaration parameter) =>
+ throw new UnsupportedError(
+ '$runtimeType._createSetterBody is not supported.');
+
+ @override
+ void buildImplicitDefaultValue() {
+ throw new UnsupportedError("$runtimeType.buildImplicitDefaultValue");
+ }
+
+ @override
+ Initializer buildImplicitInitializer() {
+ throw new UnsupportedError("$runtimeType.buildImplicitInitializer");
+ }
+
+ @override
+ Initializer buildErroneousInitializer(Expression effect, Expression value,
+ {required int fileOffset}) {
+ throw new UnsupportedError("$runtimeType.buildDuplicatedInitializer");
+ }
+}
+
+class AbstractOrExternalFieldEncoding implements _FieldEncoding {
+ final FieldFragment _fragment;
+ final bool isAbstract;
+ final bool isExternal;
+ final bool _isExtensionInstanceMember;
+ final bool _isExtensionTypeInstanceMember;
+
+ Procedure? _getter;
+ Procedure? _setter;
+ DartType? _type;
+
+ AbstractOrExternalFieldEncoding(this._fragment,
+ {required bool isExtensionInstanceMember,
+ required bool isExtensionTypeInstanceMember,
+ required this.isAbstract,
+ required this.isExternal,
+ bool isForcedExtension = false})
+ : _isExtensionInstanceMember =
+ (isExternal || isForcedExtension) && isExtensionInstanceMember,
+ _isExtensionTypeInstanceMember =
+ (isExternal || isForcedExtension) && isExtensionTypeInstanceMember;
+
+ @override
+ DartType get type {
+ assert(_type != null,
+ "Type has not been computed for field ${_fragment.name}.");
+ return _type!;
+ }
+
+ /// Updates the getter/setter types of [_getter] and [_setter] to match the
+ /// value of [_type].
+ ///
+ /// This allows for creating the members and computing the type in arbitrary
+ /// order.
+ void _updateMemberTypes() {
+ Procedure? getter = _getter;
+ Procedure? setter = _setter;
+ DartType? type = _type;
+ if (type != null && type is! InferredType && getter != null) {
+ if (_isExtensionInstanceMember || _isExtensionTypeInstanceMember) {
+ DartType thisParameterType;
+ List<TypeParameter> typeParameters;
+ if (_isExtensionInstanceMember) {
+ SourceExtensionBuilder extensionBuilder =
+ _fragment.builder.parent as SourceExtensionBuilder;
+ thisParameterType = extensionBuilder.extension.onType;
+ typeParameters = extensionBuilder.extension.typeParameters;
+ } else {
+ SourceExtensionTypeDeclarationBuilder
+ extensionTypeDeclarationBuilder =
+ _fragment.builder.parent as SourceExtensionTypeDeclarationBuilder;
+ thisParameterType = extensionTypeDeclarationBuilder
+ .extensionTypeDeclaration.declaredRepresentationType;
+ typeParameters = extensionTypeDeclarationBuilder
+ .extensionTypeDeclaration.typeParameters;
+ }
+ if (typeParameters.isNotEmpty) {
+ FreshTypeParameters getterTypeParameters =
+ getFreshTypeParameters(typeParameters);
+ getter.function.positionalParameters.first.type =
+ getterTypeParameters.substitute(thisParameterType);
+ getter.function.returnType = getterTypeParameters.substitute(type);
+ getter.function.typeParameters =
+ getterTypeParameters.freshTypeParameters;
+ setParents(getterTypeParameters.freshTypeParameters, getter.function);
+
+ if (setter != null) {
+ FreshTypeParameters setterTypeParameters =
+ getFreshTypeParameters(typeParameters);
+ setter.function.positionalParameters.first.type =
+ setterTypeParameters.substitute(thisParameterType);
+ setter.function.positionalParameters[1].type =
+ setterTypeParameters.substitute(type);
+ setter.function.typeParameters =
+ setterTypeParameters.freshTypeParameters;
+ setParents(
+ setterTypeParameters.freshTypeParameters, setter.function);
+ }
+ } else {
+ getter.function.returnType = type;
+ setter?.function.positionalParameters[1].type = type;
+ getter.function.positionalParameters.first.type = thisParameterType;
+ setter?.function.positionalParameters.first.type = thisParameterType;
+ }
+ } else {
+ getter.function.returnType = type;
+ if (setter != null) {
+ if (setter.kind == ProcedureKind.Method) {
+ // Coverage-ignore-block(suite): Not run.
+ setter.function.positionalParameters[1].type = type;
+ } else {
+ setter.function.positionalParameters.first.type = type;
+ }
+ }
+ }
+ }
+ }
+
+ @override
+ void set type(DartType value) {
+ assert(_type == null || _type is InferredType,
+ "Type has already been computed for field ${_fragment.name}.");
+ _type = value;
+ _updateMemberTypes();
+ }
+
+ @override
+ void createBodies(CoreTypes coreTypes, Expression? initializer) {
+ // TODO(johnniwinther): Enable this assert.
+ //assert(initializer != null);
+ }
+
+ @override
+ List<Initializer> createInitializer(int fileOffset, Expression value,
+ {required bool isSynthetic}) {
+ throw new UnsupportedError('ExternalFieldEncoding.createInitializer');
+ }
+
+ @override
+ void buildOutlineNode(SourceLibraryBuilder libraryBuilder,
+ NameScheme nameScheme, FieldReference references,
+ {required bool isAbstractOrExternal,
+ required List<TypeParameter>? classTypeParameters}) {
+ if (_isExtensionInstanceMember || _isExtensionTypeInstanceMember) {
+ _getter = new Procedure(
+ dummyName,
+ ProcedureKind.Method,
+ new FunctionNode(null, positionalParameters: [
+ new VariableDeclaration(syntheticThisName)
+ ..fileOffset = _fragment.nameOffset
+ ..isLowered = true
+ ]),
+ fileUri: _fragment.fileUri,
+ reference: references.fieldGetterReference)
+ ..fileOffset = _fragment.nameOffset
+ ..fileEndOffset = _fragment.endOffset;
+ nameScheme
+ .getProcedureMemberName(ProcedureKind.Getter, _fragment.name)
+ .attachMember(_getter!);
+ if (!_fragment.modifiers.isFinal) {
+ VariableDeclaration parameter =
+ new VariableDeclaration("#externalFieldValue", isSynthesized: true)
+ ..isCovariantByDeclaration = _fragment.modifiers.isCovariant
+ ..fileOffset = _fragment.nameOffset;
+ _setter = new Procedure(
+ dummyName,
+ ProcedureKind.Method,
+ new FunctionNode(null,
+ positionalParameters: [
+ new VariableDeclaration(syntheticThisName)
+ ..fileOffset = _fragment.nameOffset
+ ..isLowered = true,
+ parameter
+ ],
+ returnType: const VoidType())
+ ..fileOffset = _fragment.nameOffset
+ ..fileEndOffset = _fragment.endOffset,
+ fileUri: _fragment.fileUri,
+ reference: references.fieldSetterReference)
+ ..fileOffset = _fragment.nameOffset
+ ..fileEndOffset = _fragment.endOffset;
+ nameScheme
+ .getProcedureMemberName(ProcedureKind.Setter, _fragment.name)
+ .attachMember(_setter!);
+ }
+ } else {
+ _getter = new Procedure(
+ dummyName, ProcedureKind.Getter, new FunctionNode(null),
+ fileUri: _fragment.fileUri,
+ reference: references.fieldGetterReference)
+ ..fileOffset = _fragment.nameOffset
+ ..fileEndOffset = _fragment.endOffset;
+ nameScheme
+ .getFieldMemberName(FieldNameType.Getter, _fragment.name,
+ isSynthesized: true)
+ .attachMember(_getter!);
+ if (!_fragment.modifiers.isFinal) {
+ VariableDeclaration parameter =
+ new VariableDeclaration("#externalFieldValue", isSynthesized: true)
+ ..isCovariantByDeclaration = _fragment.modifiers.isCovariant
+ ..fileOffset = _fragment.nameOffset;
+ _setter = new Procedure(
+ dummyName,
+ ProcedureKind.Setter,
+ new FunctionNode(null,
+ positionalParameters: [parameter], returnType: const VoidType())
+ ..fileOffset = _fragment.nameOffset
+ ..fileEndOffset = _fragment.endOffset,
+ fileUri: _fragment.fileUri,
+ reference: references.fieldSetterReference)
+ ..fileOffset = _fragment.nameOffset
+ ..fileEndOffset = _fragment.endOffset;
+ nameScheme
+ .getFieldMemberName(FieldNameType.Setter, _fragment.name,
+ isSynthesized: true)
+ .attachMember(_setter!);
+ }
+ }
+
+ bool isExtensionMember = _fragment.builder.isExtensionMember;
+ bool isExtensionTypeMember = _fragment.builder.isExtensionTypeMember;
+ bool isInstanceMember = !isExtensionMember &&
+ !isExtensionTypeMember &&
+ !_fragment.builder.isStatic &&
+ !_fragment.builder.isTopLevel;
+ _getter!
+ ..isConst = _fragment.modifiers.isConst
+ ..isStatic = !isInstanceMember
+ ..isExtensionMember = isExtensionMember
+ ..isExtensionTypeMember = isExtensionTypeMember
+ ..isAbstract = isAbstract && !isExternal
+ ..isExternal = isExternal;
+
+ _setter
+ ?..isStatic = !isInstanceMember
+ ..isExtensionMember = isExtensionMember
+ ..isExtensionTypeMember = isExtensionTypeMember
+ ..isAbstract = isAbstract && !isExternal
+ ..isExternal = isExternal;
+
+ _updateMemberTypes();
+ }
+
+ @override
+ void registerMembers(BuildNodesCallback f) {
+ BuiltMemberKind getterMemberKind;
+ if (_fragment.builder.isExtensionMember) {
+ getterMemberKind = BuiltMemberKind.ExtensionGetter;
+ } else if (_fragment.builder.isExtensionTypeMember) {
+ getterMemberKind = BuiltMemberKind.ExtensionTypeGetter;
+ } else {
+ getterMemberKind = BuiltMemberKind.Method;
+ }
+ f(member: _getter!, kind: getterMemberKind);
+ if (_setter != null) {
+ BuiltMemberKind setterMemberKind;
+ if (_fragment.builder.isExtensionMember) {
+ setterMemberKind = BuiltMemberKind.ExtensionSetter;
+ } else if (_fragment.builder.isExtensionTypeMember) {
+ setterMemberKind = BuiltMemberKind.ExtensionTypeSetter;
+ } else {
+ setterMemberKind = BuiltMemberKind.Method;
+ }
+ f(member: _setter!, kind: setterMemberKind);
+ }
+ }
+
+ @override
+ // Coverage-ignore(suite): Not run.
+ void setCovariantByClass() {
+ _setter!.function.positionalParameters.first.isCovariantByClass = true;
+ }
+
+ @override
+ Field get field {
+ throw new UnsupportedError("ExternalFieldEncoding.field");
+ }
+
+ @override
+ // Coverage-ignore(suite): Not run.
+ Member get builtMember => _getter!;
+
+ @override
+ // Coverage-ignore(suite): Not run.
+ Iterable<Annotatable> get annotatables {
+ List<Annotatable> list = [_getter!];
+ if (_setter != null) {
+ list.add(_setter!);
+ }
+ return list;
+ }
+
+ @override
+ Member get readTarget => _getter!;
+
+ @override
+ // Coverage-ignore(suite): Not run.
+ Reference get readTargetReference => _getter!.reference;
+
+ @override
+ Member? get writeTarget => _setter;
+
+ @override
+ // Coverage-ignore(suite): Not run.
+ Reference? get writeTargetReference => _setter?.reference;
+
+ @override
+ // Coverage-ignore(suite): Not run.
+ Iterable<Reference> get exportedReferenceMembers {
+ if (_setter != null) {
+ return [_getter!.reference, _setter!.reference];
+ }
+ return [_getter!.reference];
+ }
+
+ @override
+ List<ClassMember> get localMembers => <ClassMember>[
+ new _SynthesizedFieldClassMember(
+ _fragment.builder,
+ _getter!,
+ _fragment.builder.memberName,
+ _SynthesizedFieldMemberKind.AbstractExternalGetterSetter,
+ ClassMemberKind.Getter)
+ ];
+
+ @override
+ List<ClassMember> get localSetters => _setter != null
+ ? <ClassMember>[
+ new _SynthesizedFieldClassMember(
+ _fragment.builder,
+ _setter!,
+ _fragment.builder.memberName,
+ _SynthesizedFieldMemberKind.AbstractExternalGetterSetter,
+ ClassMemberKind.Setter)
+ ]
+ : const <ClassMember>[];
+
+ @override
+ void buildImplicitDefaultValue() {
+ throw new UnsupportedError("$runtimeType.buildImplicitDefaultValue");
+ }
+
+ @override
+ Initializer buildImplicitInitializer() {
+ throw new UnsupportedError("$runtimeType.buildImplicitInitializer");
+ }
+
+ @override
+ Initializer buildErroneousInitializer(Expression effect, Expression value,
+ {required int fileOffset}) {
+ return new ShadowInvalidFieldInitializer(type, value, effect)
+ ..fileOffset = fileOffset;
+ }
+
+ @override
+ void registerSuperCall() {
+ throw new UnsupportedError(
+ "Unexpected call to ${runtimeType}.registerSuperCall().");
+ }
+}
+
+/// The encoding of an extension type declaration representation field.
+class RepresentationFieldEncoding implements _FieldEncoding {
+ final FieldFragment _fragment;
+
+ late Procedure _getter;
+ DartType? _type;
+
+ RepresentationFieldEncoding(this._fragment);
+ @override
+ DartType get type {
+ assert(_type != null,
+ "Type has not been computed for field ${_fragment.name}.");
+ return _type!;
+ }
+
+ @override
+ void set type(DartType value) {
+ assert(
+ _type == null ||
+ // Coverage-ignore(suite): Not run.
+ _type is InferredType,
+ "Type has already been computed for field ${_fragment.name}.");
+ _type = value;
+ if (value is! InferredType) {
+ _getter.function.returnType = value;
+ }
+ }
+
+ @override
+ // Coverage-ignore(suite): Not run.
+ void createBodies(CoreTypes coreTypes, Expression? initializer) {
+ // TODO(johnniwinther): Enable this assert.
+ //assert(initializer != null);
+ }
+
+ @override
+ List<Initializer> createInitializer(int fileOffset, Expression value,
+ {required bool isSynthetic}) {
+ return <Initializer>[
+ new ExtensionTypeRepresentationFieldInitializer(_getter, value)
+ ];
+ }
+
+ @override
+ void buildOutlineNode(SourceLibraryBuilder libraryBuilder,
+ NameScheme nameScheme, FieldReference references,
+ {required bool isAbstractOrExternal,
+ required List<TypeParameter>? classTypeParameters}) {
+ _getter = new Procedure(
+ dummyName, ProcedureKind.Getter, new FunctionNode(null),
+ fileUri: _fragment.fileUri, reference: references.fieldGetterReference)
+ ..stubKind = ProcedureStubKind.RepresentationField
+ ..fileOffset = _fragment.nameOffset
+ ..fileEndOffset = _fragment.endOffset;
+ nameScheme
+ .getFieldMemberName(FieldNameType.RepresentationField, _fragment.name,
+ isSynthesized: true)
+ .attachMember(_getter);
+ _getter..isConst = _fragment.modifiers.isConst;
+ _getter
+ ..isStatic = false
+ ..isExtensionMember = false
+ ..isExtensionTypeMember = true
+ ..isAbstract = true
+ ..isExternal = false;
+ }
+
+ @override
+ void registerMembers(BuildNodesCallback f) {
+ f(member: _getter, kind: BuiltMemberKind.ExtensionTypeRepresentationField);
+ }
+
+ @override
+ void setCovariantByClass() {
+ throw new UnsupportedError("$runtimeType.setGenericCovariantImpl");
+ }
+
+ @override
+ Field get field {
+ throw new UnsupportedError("$runtimeType.field");
+ }
+
+ @override
+ // Coverage-ignore(suite): Not run.
+ Member get builtMember => _getter;
+
+ @override
+ // Coverage-ignore(suite): Not run.
+ Iterable<Annotatable> get annotatables => [_getter];
+
+ @override
+ Member get readTarget => _getter;
+
+ @override
+ // Coverage-ignore(suite): Not run.
+ Reference get readTargetReference => _getter.reference;
+
+ @override
+ Member? get writeTarget => null;
+
+ @override
+ // Coverage-ignore(suite): Not run.
+ Reference? get writeTargetReference => null;
+
+ @override
+ // Coverage-ignore(suite): Not run.
+ Iterable<Reference> get exportedReferenceMembers => [_getter.reference];
+
+ @override
+ List<ClassMember> get localMembers => [
+ new _SynthesizedFieldClassMember(
+ _fragment.builder,
+ _getter,
+ _fragment.builder.memberName,
+ _SynthesizedFieldMemberKind.RepresentationField,
+ ClassMemberKind.Getter)
+ ];
+
+ @override
+ List<ClassMember> get localSetters => const [];
+
+ @override
+ // Coverage-ignore(suite): Not run.
+ void buildImplicitDefaultValue() {
+ // Not needed.
+ }
+
+ @override
+ Initializer buildImplicitInitializer() {
+ return new ExtensionTypeRepresentationFieldInitializer(
+ _getter, new NullLiteral());
+ }
+
+ @override
+ Initializer buildErroneousInitializer(Expression effect, Expression value,
+ {required int fileOffset}) {
+ return new ShadowInvalidFieldInitializer(type, value, effect)
+ ..fileOffset = fileOffset;
+ }
+
+ @override
+ void registerSuperCall() {
+ throw new UnsupportedError(
+ "Unexpected call to ${runtimeType}.registerSuperCall().");
+ }
+}
diff --git a/pkg/front_end/lib/src/fragment/fragment.dart b/pkg/front_end/lib/src/fragment/fragment.dart
index 4fd060f..3b3a131 100644
--- a/pkg/front_end/lib/src/fragment/fragment.dart
+++ b/pkg/front_end/lib/src/fragment/fragment.dart
@@ -2,16 +2,22 @@
// 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/metadata/expressions.dart' as shared;
import 'package:_fe_analyzer_shared/src/parser/member_kind.dart';
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/transformations/flags.dart';
import 'package:kernel/type_algebra.dart';
import 'package:kernel/type_environment.dart';
+import '../api_prototype/codes.dart';
+import '../api_prototype/lowering_predicates.dart';
+import '../base/constant_context.dart';
import '../base/local_scope.dart';
import '../base/modifiers.dart';
+import '../base/problems.dart';
import '../base/scope.dart';
import '../builder/builder.dart';
import '../builder/constructor_reference_builder.dart';
@@ -19,27 +25,32 @@
import '../builder/formal_parameter_builder.dart';
import '../builder/metadata_builder.dart';
import '../builder/mixin_application_builder.dart';
+import '../builder/named_type_builder.dart';
import '../builder/omitted_type_builder.dart';
import '../builder/type_builder.dart';
+import '../kernel/body_builder.dart';
import '../kernel/body_builder_context.dart';
import '../kernel/hierarchy/class_member.dart';
import '../kernel/hierarchy/members_builder.dart';
+import '../kernel/implicit_field_type.dart';
import '../kernel/internal_ast.dart';
+import '../kernel/late_lowering.dart' as late_lowering;
+import '../kernel/macro/metadata.dart' hide FieldReference;
+import '../kernel/member_covariance.dart';
import '../kernel/type_algorithms.dart';
import '../source/name_scheme.dart';
-import '../source/source_property_builder.dart';
import '../source/source_class_builder.dart';
import '../source/source_constructor_builder.dart';
import '../source/source_enum_builder.dart';
import '../source/source_extension_builder.dart';
import '../source/source_extension_type_declaration_builder.dart';
import '../source/source_factory_builder.dart';
-import '../source/source_field_builder.dart';
import '../source/source_function_builder.dart';
import '../source/source_library_builder.dart';
import '../source/source_loader.dart';
import '../source/source_member_builder.dart';
import '../source/source_method_builder.dart';
+import '../source/source_property_builder.dart';
import '../source/source_type_alias_builder.dart';
import '../source/type_parameter_scope_builder.dart';
import '../type_inference/type_inference_engine.dart';
@@ -52,6 +63,9 @@
part 'extension_type.dart';
part 'factory.dart';
part 'field.dart';
+part 'field/body_builder_context.dart';
+part 'field/class_member.dart';
+part 'field/encoding.dart';
part 'function.dart';
part 'getter.dart';
part 'method.dart';
diff --git a/pkg/front_end/lib/src/fragment/getter.dart b/pkg/front_end/lib/src/fragment/getter.dart
index 5097931..96e7659 100644
--- a/pkg/front_end/lib/src/fragment/getter.dart
+++ b/pkg/front_end/lib/src/fragment/getter.dart
@@ -133,11 +133,9 @@
}
void buildOutlineNode(SourceLibraryBuilder libraryBuilder,
- NameScheme nameScheme, BuildNodesCallback f,
- {required Reference getterReference,
- required List<TypeParameter>? classTypeParameters}) {
- _encoding.buildOutlineNode(libraryBuilder, nameScheme, f,
- getterReference: getterReference,
+ NameScheme nameScheme, BuildNodesCallback f, GetterReference references,
+ {required List<TypeParameter>? classTypeParameters}) {
+ _encoding.buildOutlineNode(libraryBuilder, nameScheme, f, references,
isAbstractOrExternal: modifiers.isAbstract || modifiers.isExternal,
classTypeParameters: classTypeParameters);
}
@@ -161,6 +159,9 @@
createFileUriExpression: createFileUriExpression);
}
+ Iterable<Reference> getExportedMemberReferences(GetterReference references) =>
+ [references.getterReference];
+
BodyBuilderContext createBodyBuilderContext() {
return new _GetterFragmentBodyBuilderContext(
this, builder.libraryBuilder, builder.declarationBuilder,
@@ -175,20 +176,20 @@
return _encoding.computeDefaultTypes(context);
}
- void ensureTypes(
- ClassMembersBuilder membersBuilder,
- SourceClassBuilder enclosingClassBuilder,
+ void ensureTypes(ClassMembersBuilder membersBuilder,
Set<ClassMember>? getterOverrideDependencies) {
if (getterOverrideDependencies != null) {
membersBuilder.inferGetterType(
- enclosingClassBuilder, returnType, getterOverrideDependencies,
+ builder.declarationBuilder as SourceClassBuilder,
+ returnType,
+ getterOverrideDependencies,
name: name,
fileUri: fileUri,
nameOffset: nameOffset,
nameLength: name.length);
}
_encoding.ensureTypes(
- enclosingClassBuilder.libraryBuilder, membersBuilder.hierarchyBuilder);
+ builder.libraryBuilder, membersBuilder.hierarchyBuilder);
}
void checkTypes(SourceLibraryBuilder libraryBuilder,
@@ -269,9 +270,8 @@
Procedure get readTarget;
void buildOutlineNode(SourceLibraryBuilder libraryBuilder,
- NameScheme nameScheme, BuildNodesCallback f,
- {required Reference getterReference,
- required bool isAbstractOrExternal,
+ NameScheme nameScheme, BuildNodesCallback f, GetterReference references,
+ {required bool isAbstractOrExternal,
required List<TypeParameter>? classTypeParameters});
void buildOutlineExpressions(
@@ -328,9 +328,8 @@
@override
void buildOutlineNode(SourceLibraryBuilder libraryBuilder,
- NameScheme nameScheme, BuildNodesCallback f,
- {required Reference getterReference,
- required bool isAbstractOrExternal,
+ NameScheme nameScheme, BuildNodesCallback f, GetterReference references,
+ {required bool isAbstractOrExternal,
List<TypeParameter>? classTypeParameters}) {
FunctionNode function = new FunctionNode(
isAbstractOrExternal ? null : new EmptyStatement(),
@@ -349,7 +348,7 @@
nameScheme.getProcedureMemberName(ProcedureKind.Getter, _fragment.name);
Procedure procedure = _procedure = new Procedure(
memberName.name, ProcedureKind.Getter, function,
- reference: getterReference, fileUri: _fragment.fileUri)
+ reference: references.getterReference, fileUri: _fragment.fileUri)
..fileStartOffset = _fragment.startOffset
..fileOffset = _fragment.nameOffset
..fileEndOffset = _fragment.endOffset
@@ -556,9 +555,8 @@
@override
void buildOutlineNode(SourceLibraryBuilder libraryBuilder,
- NameScheme nameScheme, BuildNodesCallback f,
- {required Reference getterReference,
- required bool isAbstractOrExternal,
+ NameScheme nameScheme, BuildNodesCallback f, GetterReference references,
+ {required bool isAbstractOrExternal,
required List<TypeParameter>? classTypeParameters}) {
List<TypeParameter>? typeParameters;
if (_clonedDeclarationTypeParameters != null) {
@@ -589,7 +587,7 @@
nameScheme.getProcedureMemberName(ProcedureKind.Getter, _fragment.name);
Procedure procedure = _procedure = new Procedure(
memberName.name, ProcedureKind.Method, function,
- reference: getterReference, fileUri: _fragment.fileUri)
+ reference: references.getterReference, fileUri: _fragment.fileUri)
..fileStartOffset = _fragment.startOffset
..fileOffset = _fragment.nameOffset
..fileEndOffset = _fragment.endOffset
diff --git a/pkg/front_end/lib/src/fragment/setter.dart b/pkg/front_end/lib/src/fragment/setter.dart
index 952b59e..d28c135 100644
--- a/pkg/front_end/lib/src/fragment/setter.dart
+++ b/pkg/front_end/lib/src/fragment/setter.dart
@@ -125,11 +125,9 @@
}
void buildOutlineNode(SourceLibraryBuilder libraryBuilder,
- NameScheme nameScheme, BuildNodesCallback f,
- {required Reference setterReference,
- required List<TypeParameter>? classTypeParameters}) {
- _encoding.buildOutlineNode(libraryBuilder, nameScheme, f,
- setterReference: setterReference,
+ NameScheme nameScheme, BuildNodesCallback f, SetterReference references,
+ {required List<TypeParameter>? classTypeParameters}) {
+ _encoding.buildOutlineNode(libraryBuilder, nameScheme, f, references,
isAbstractOrExternal: modifiers.isAbstract || modifiers.isExternal,
classTypeParameters: classTypeParameters);
}
@@ -153,20 +151,23 @@
createFileUriExpression: createFileUriExpression);
}
- void ensureTypes(
- ClassMembersBuilder membersBuilder,
- SourceClassBuilder enclosingClassBuilder,
+ Iterable<Reference> getExportedMemberReferences(SetterReference references) =>
+ [references.setterReference];
+
+ void ensureTypes(ClassMembersBuilder membersBuilder,
Set<ClassMember>? setterOverrideDependencies) {
if (setterOverrideDependencies != null) {
membersBuilder.inferSetterType(
- enclosingClassBuilder, declaredFormals, setterOverrideDependencies,
+ builder.declarationBuilder as SourceClassBuilder,
+ declaredFormals,
+ setterOverrideDependencies,
name: name,
fileUri: fileUri,
nameOffset: nameOffset,
nameLength: name.length);
}
_encoding.ensureTypes(
- enclosingClassBuilder.libraryBuilder, membersBuilder.hierarchyBuilder);
+ builder.libraryBuilder, membersBuilder.hierarchyBuilder);
}
void checkTypes(
@@ -266,9 +267,8 @@
Procedure get writeTarget;
void buildOutlineNode(SourceLibraryBuilder libraryBuilder,
- NameScheme nameScheme, BuildNodesCallback f,
- {required Reference setterReference,
- required bool isAbstractOrExternal,
+ NameScheme nameScheme, BuildNodesCallback f, SetterReference references,
+ {required bool isAbstractOrExternal,
required List<TypeParameter>? classTypeParameters});
void buildOutlineExpressions(
@@ -353,9 +353,8 @@
@override
void buildOutlineNode(SourceLibraryBuilder libraryBuilder,
- NameScheme nameScheme, BuildNodesCallback f,
- {required Reference setterReference,
- required bool isAbstractOrExternal,
+ NameScheme nameScheme, BuildNodesCallback f, SetterReference references,
+ {required bool isAbstractOrExternal,
List<TypeParameter>? classTypeParameters}) {
FunctionNode function = new FunctionNode(
isAbstractOrExternal ? null : new EmptyStatement(),
@@ -385,7 +384,7 @@
nameScheme.getProcedureMemberName(ProcedureKind.Setter, _fragment.name);
Procedure procedure = _procedure = new Procedure(
memberName.name, ProcedureKind.Setter, function,
- reference: setterReference, fileUri: _fragment.fileUri)
+ reference: references.setterReference, fileUri: _fragment.fileUri)
..fileStartOffset = _fragment.startOffset
..fileOffset = _fragment.nameOffset
..fileEndOffset = _fragment.endOffset
@@ -580,9 +579,8 @@
@override
void buildOutlineNode(SourceLibraryBuilder libraryBuilder,
- NameScheme nameScheme, BuildNodesCallback f,
- {required Reference setterReference,
- required bool isAbstractOrExternal,
+ NameScheme nameScheme, BuildNodesCallback f, SetterReference references,
+ {required bool isAbstractOrExternal,
required List<TypeParameter>? classTypeParameters}) {
List<TypeParameter>? typeParameters;
if (_clonedDeclarationTypeParameters != null) {
@@ -630,7 +628,7 @@
nameScheme.getProcedureMemberName(ProcedureKind.Setter, _fragment.name);
Procedure procedure = _procedure = new Procedure(
memberName.name, ProcedureKind.Method, function,
- reference: setterReference, fileUri: _fragment.fileUri)
+ reference: references.setterReference, fileUri: _fragment.fileUri)
..fileStartOffset = _fragment.startOffset
..fileOffset = _fragment.nameOffset
..fileEndOffset = _fragment.endOffset
diff --git a/pkg/front_end/lib/src/kernel/body_builder.dart b/pkg/front_end/lib/src/kernel/body_builder.dart
index 920295e..8dd7677 100644
--- a/pkg/front_end/lib/src/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/kernel/body_builder.dart
@@ -73,6 +73,7 @@
import '../builder/nullability_builder.dart';
import '../builder/omitted_type_builder.dart';
import '../builder/prefix_builder.dart';
+import '../builder/property_builder.dart';
import '../builder/record_type_builder.dart';
import '../builder/type_builder.dart';
import '../builder/variable_builder.dart';
@@ -91,9 +92,9 @@
templateLocalVariableUsedBeforeDeclaredContext;
import '../codes/cfe_codes.dart' as cfe;
import '../dill/dill_library_builder.dart' show DillLibraryBuilder;
+import '../fragment/fragment.dart';
import '../source/diet_parser.dart';
import '../source/offset_map.dart';
-import '../source/source_field_builder.dart';
import '../source/source_library_builder.dart';
import '../source/source_member_builder.dart';
import '../source/stack_listener_impl.dart'
@@ -977,16 +978,16 @@
]));
Expression? initializer = pop() as Expression?;
Identifier identifier = pop() as Identifier;
- SourceFieldBuilder fieldBuilder = offsetMap.lookupField(identifier);
+ FieldFragment fieldFragment = offsetMap.lookupField(identifier);
if (initializer != null) {
- if (!fieldBuilder.hasBodyBeenBuilt) {
+ if (!fieldFragment.hasBodyBeenBuilt) {
initializer = typeInferrer
- .inferFieldInitializer(this, fieldBuilder.builtType, initializer)
+ .inferFieldInitializer(this, fieldFragment.fieldType, initializer)
.expression;
- fieldBuilder.buildBody(coreTypes, initializer);
+ fieldFragment.buildBody(coreTypes, initializer);
}
- } else if (!fieldBuilder.hasBodyBeenBuilt) {
- fieldBuilder.buildBody(coreTypes, null);
+ } else if (!fieldFragment.hasBodyBeenBuilt) {
+ fieldFragment.buildBody(coreTypes, null);
}
}
assert(checkState(
@@ -9070,7 +9071,7 @@
}
Initializer buildDuplicatedInitializer(
- SourceFieldBuilder fieldBuilder,
+ PropertyBuilder fieldBuilder,
Expression value,
String name,
int offset,
@@ -9105,7 +9106,9 @@
if (builder?.next != null) {
// Duplicated name, already reported.
while (builder != null) {
- if (builder.next == null && builder is SourceFieldBuilder) {
+ if (builder.next == null &&
+ builder is PropertyBuilder &&
+ builder.isField) {
// Assume the first field has been initialized.
_context.registerInitializedField(builder);
}
@@ -9122,7 +9125,8 @@
),
fieldNameOffset)
];
- } else if (builder is SourceFieldBuilder &&
+ } else if (builder is PropertyBuilder &&
+ builder.isField &&
builder.isDeclarationInstanceMember) {
if (builder.isExtensionTypeDeclaredInstanceField) {
// Operating on an invalid field. Don't report anything though
diff --git a/pkg/front_end/lib/src/kernel/body_builder_context.dart b/pkg/front_end/lib/src/kernel/body_builder_context.dart
index 684fe4c..511db32 100644
--- a/pkg/front_end/lib/src/kernel/body_builder_context.dart
+++ b/pkg/front_end/lib/src/kernel/body_builder_context.dart
@@ -15,6 +15,7 @@
import '../builder/formal_parameter_builder.dart';
import '../builder/library_builder.dart';
import '../builder/named_type_builder.dart';
+import '../builder/property_builder.dart';
import '../builder/type_builder.dart';
import '../dill/dill_class_builder.dart';
import '../source/constructor_declaration.dart';
@@ -50,6 +51,10 @@
_declarationContext = new BodyBuilderDeclarationContext(
libraryBuilder, declarationBuilder);
+ /// Returns `true` if the enclosing declaration declares a const constructor.
+ bool get declarationDeclaresConstConstructor =>
+ _declarationContext.declaresConstConstructor;
+
/// Returns the file offset of the name of the member whose body is being
/// built.
///
@@ -282,7 +287,7 @@
/// Registers that the field [builder] has been initialized in generative
/// constructor whose body is being built.
- void registerInitializedField(SourceFieldBuilder builder) {
+ void registerInitializedField(PropertyBuilder builder) {
throw new UnsupportedError('${runtimeType}.registerInitializedField');
}
@@ -748,15 +753,19 @@
isDeclarationInstanceMember: _member.isDeclarationInstanceMember);
@override
+ // Coverage-ignore(suite): Not run.
bool get isLateField => _member.isLate;
@override
+ // Coverage-ignore(suite): Not run.
bool get isAbstractField => _member.isAbstract;
@override
+ // Coverage-ignore(suite): Not run.
bool get isExternalField => _member.isExternal;
@override
+ // Coverage-ignore(suite): Not run.
InstanceTypeParameterAccessState get instanceTypeParameterAccessState {
if (_member.isExtensionMember && !_member.isExternal) {
return InstanceTypeParameterAccessState.Invalid;
@@ -766,6 +775,7 @@
}
@override
+ // Coverage-ignore(suite): Not run.
ConstantContext get constantContext {
return _member.isConst
? ConstantContext.inferred
@@ -852,7 +862,7 @@
}
@override
- void registerInitializedField(SourceFieldBuilder builder) {
+ void registerInitializedField(PropertyBuilder builder) {
_member.registerInitializedField(builder);
}
diff --git a/pkg/front_end/lib/src/kernel/expression_generator.dart b/pkg/front_end/lib/src/kernel/expression_generator.dart
index 48cb7cf..4e77f1b 100644
--- a/pkg/front_end/lib/src/kernel/expression_generator.dart
+++ b/pkg/front_end/lib/src/kernel/expression_generator.dart
@@ -1979,6 +1979,10 @@
} else if (getterBuilder.isField) {
assert(!getterBuilder.isStatic);
MemberBuilder memberBuilder = getterBuilder as MemberBuilder;
+ assert(
+ memberBuilder.invokeTarget is Procedure?,
+ "Unexpected invoke target ${memberBuilder.invokeTarget} "
+ "(${memberBuilder.invokeTarget.runtimeType}) on ${memberBuilder}.");
readTarget = memberBuilder.invokeTarget as Procedure?;
} else {
return unhandled(
diff --git a/pkg/front_end/lib/src/kernel/hierarchy/class_member.dart b/pkg/front_end/lib/src/kernel/hierarchy/class_member.dart
index 2c280dd..b2849dc 100644
--- a/pkg/front_end/lib/src/kernel/hierarchy/class_member.dart
+++ b/pkg/front_end/lib/src/kernel/hierarchy/class_member.dart
@@ -170,6 +170,8 @@
@override
DartType getMemberType(
ClassMembersBuilder membersBuilder, TypeDeclarationType thisType) {
+ assert(member.getterType is FunctionType,
+ "Unexpected member type for $member (${member.runtimeType}).");
FunctionType type = member.getterType as FunctionType;
if (type.typeParameters.isNotEmpty) {
// Coverage-ignore-block(suite): Not run.
diff --git a/pkg/front_end/lib/src/kernel/implicit_field_type.dart b/pkg/front_end/lib/src/kernel/implicit_field_type.dart
index 8cb4666..5a9646c 100644
--- a/pkg/front_end/lib/src/kernel/implicit_field_type.dart
+++ b/pkg/front_end/lib/src/kernel/implicit_field_type.dart
@@ -11,10 +11,14 @@
import '../base/constant_context.dart';
import '../base/problems.dart' show unsupported;
import '../builder/builder.dart';
+import '../builder/declaration_builders.dart';
import '../builder/inferable_type_builder.dart';
import '../codes/cfe_codes.dart';
+import '../fragment/fragment.dart';
+import '../source/source_class_builder.dart';
import '../source/source_enum_builder.dart';
import '../source/source_field_builder.dart';
+import '../source/source_library_builder.dart';
import '../type_inference/type_inferrer.dart';
import 'body_builder.dart';
import 'body_builder_context.dart';
@@ -29,6 +33,10 @@
SourceFieldBuilder fieldBuilder, Token? initializerToken) =
_ImplicitFieldTypeRoot;
+ factory InferredType.fromFieldFragmentInitializer(
+ FieldFragment fieldFragment, Token? initializerToken) =
+ _ImplicitFieldFragmentTypeRoot;
+
factory InferredType.fromInferableTypeUse(InferableTypeUse inferableTypeUse) =
_InferredTypeUse;
@@ -114,6 +122,7 @@
@override
DartType computeType(ClassHierarchyBase hierarchy) {
if (isStarted) {
+ // Coverage-ignore-block(suite): Not run.
fieldBuilder.libraryBuilder.addProblem(
templateCantInferTypeDueToCircularity
.withArguments(fieldBuilder.name),
@@ -131,7 +140,9 @@
parent.elementBuilders.contains(fieldBuilder)) {
inferredType = parent.buildElement(
fieldBuilder, parent.libraryBuilder.loader.coreTypes);
- } else if (initializerToken != null) {
+ }
+ // Coverage-ignore(suite): Not run.
+ else if (initializerToken != null) {
InterfaceType? enclosingClassThisType = fieldBuilder.classBuilder == null
? null
: fieldBuilder.libraryBuilder.loader.typeInferenceEngine.coreTypes
@@ -143,10 +154,7 @@
fieldBuilder.fileUri,
enclosingClassThisType,
fieldBuilder.libraryBuilder,
- fieldBuilder
- .dataForTesting
- // Coverage-ignore(suite): Not run.
- ?.inferenceData);
+ fieldBuilder.dataForTesting?.inferenceData);
BodyBuilderContext bodyBuilderContext =
fieldBuilder.createBodyBuilderContext();
BodyBuilder bodyBuilder = fieldBuilder.libraryBuilder.loader
@@ -195,6 +203,116 @@
String toString() => 'ImplicitFieldType(${toStringInternal()})';
}
+class _ImplicitFieldFragmentTypeRoot extends InferredType {
+ final FieldFragment _fieldFragment;
+
+ Token? initializerToken;
+ bool isStarted = false;
+
+ _ImplicitFieldFragmentTypeRoot(this._fieldFragment, this.initializerToken)
+ : super._();
+
+ @override
+ // Coverage-ignore(suite): Not run.
+ Uri get fileUri => _fieldFragment.fileUri;
+
+ @override
+ // Coverage-ignore(suite): Not run.
+ int get charOffset => _fieldFragment.nameOffset;
+
+ @override
+ DartType inferType(ClassHierarchyBase hierarchy) {
+ return _fieldFragment.inferType(hierarchy);
+ }
+
+ @override
+ DartType computeType(ClassHierarchyBase hierarchy) {
+ if (isStarted) {
+ _fieldFragment.builder.libraryBuilder.addProblem(
+ templateCantInferTypeDueToCircularity
+ .withArguments(_fieldFragment.name),
+ _fieldFragment.nameOffset,
+ _fieldFragment.name.length,
+ _fieldFragment.fileUri);
+ DartType type = const InvalidType();
+ _fieldFragment.type.registerInferredType(type);
+ return type;
+ }
+ isStarted = true;
+ DartType? inferredType;
+ SourceLibraryBuilder libraryBuilder = _fieldFragment.builder.libraryBuilder;
+ DeclarationBuilder? declarationBuilder =
+ _fieldFragment.builder.declarationBuilder;
+ if (declarationBuilder is SourceEnumBuilder &&
+ declarationBuilder.elementBuilders.contains(_fieldFragment.builder)) {
+ // Coverage-ignore-block(suite): Not run.
+ inferredType = declarationBuilder.buildElement(
+ // TODO(johnniwinther): Create a EnumElementFragment to avoid this.
+ _fieldFragment.builder as SourceFieldBuilder,
+ libraryBuilder.loader.coreTypes);
+ } else if (initializerToken != null) {
+ InterfaceType? enclosingClassThisType = declarationBuilder
+ is SourceClassBuilder
+ ? libraryBuilder.loader.typeInferenceEngine.coreTypes
+ .thisInterfaceType(
+ declarationBuilder.cls, libraryBuilder.library.nonNullable)
+ : null;
+ TypeInferrer typeInferrer =
+ libraryBuilder.loader.typeInferenceEngine.createTopLevelTypeInferrer(
+ _fieldFragment.fileUri,
+ enclosingClassThisType,
+ libraryBuilder,
+ _fieldFragment
+ .builder
+ .dataForTesting
+ // Coverage-ignore(suite): Not run.
+ ?.inferenceData);
+ BodyBuilderContext bodyBuilderContext =
+ _fieldFragment.createBodyBuilderContext();
+ BodyBuilder bodyBuilder = libraryBuilder.loader.createBodyBuilderForField(
+ libraryBuilder,
+ bodyBuilderContext,
+ declarationBuilder?.scope ?? libraryBuilder.scope,
+ typeInferrer,
+ _fieldFragment.fileUri);
+ bodyBuilder.constantContext = _fieldFragment.modifiers.isConst
+ ? ConstantContext.inferred
+ : ConstantContext.none;
+ bodyBuilder.inFieldInitializer = true;
+ bodyBuilder.inLateFieldInitializer = _fieldFragment.modifiers.isLate;
+ Expression initializer =
+ bodyBuilder.parseFieldInitializer(initializerToken!);
+ initializerToken = null;
+
+ inferredType =
+ typeInferrer.inferImplicitFieldType(bodyBuilder, initializer);
+ } else {
+ inferredType = const DynamicType();
+ }
+ return inferredType;
+ }
+
+ @override
+ // Coverage-ignore(suite): Not run.
+ void toTextInternal(AstPrinter printer) {
+ printer.write('<implicit-field-type:$_fieldFragment>');
+ }
+
+ @override
+ // Coverage-ignore(suite): Not run.
+ bool equals(Object other, Assumptions? assumptions) {
+ if (identical(this, other)) return true;
+ return other is _ImplicitFieldFragmentTypeRoot &&
+ _fieldFragment == other._fieldFragment;
+ }
+
+ @override
+ int get hashCode => _fieldFragment.hashCode;
+
+ @override
+ String toString() => 'ImplicitFieldType(${toStringInternal()})';
+}
+
class _InferredTypeUse extends InferredType {
final InferableTypeUse inferableTypeUse;
diff --git a/pkg/front_end/lib/src/kernel/kernel_target.dart b/pkg/front_end/lib/src/kernel/kernel_target.dart
index 05953dc..7386f7c 100644
--- a/pkg/front_end/lib/src/kernel/kernel_target.dart
+++ b/pkg/front_end/lib/src/kernel/kernel_target.dart
@@ -47,13 +47,13 @@
import '../base/uri_translator.dart' show UriTranslator;
import '../builder/builder.dart';
import '../builder/declaration_builders.dart';
-import '../builder/field_builder.dart';
import '../builder/library_builder.dart';
import '../builder/member_builder.dart';
import '../builder/name_iterator.dart';
import '../builder/named_type_builder.dart';
import '../builder/nullability_builder.dart';
import '../builder/procedure_builder.dart';
+import '../builder/property_builder.dart';
import '../builder/type_builder.dart';
import '../dill/dill_target.dart' show DillTarget;
import '../source/class_declaration.dart';
@@ -62,13 +62,13 @@
import '../source/source_class_builder.dart' show SourceClassBuilder;
import '../source/source_constructor_builder.dart';
import '../source/source_extension_type_declaration_builder.dart';
-import '../source/source_field_builder.dart';
import '../source/source_library_builder.dart' show SourceLibraryBuilder;
import '../source/source_loader.dart'
show CompilationPhaseForProblemReporting, SourceLoader;
import '../source/source_method_builder.dart';
import '../type_inference/type_schema.dart';
import 'benchmarker.dart' show BenchmarkPhases, Benchmarker;
+import 'cfe_verifier.dart' show verifyComponent, verifyGetStaticType;
import 'constant_evaluator.dart' as constants
show
EvaluationMode,
@@ -81,7 +81,6 @@
import 'kernel_constants.dart' show KernelConstantErrorReporter;
import 'kernel_helper.dart';
import 'macro/macro.dart';
-import 'cfe_verifier.dart' show verifyComponent, verifyGetStaticType;
class KernelTarget {
final Ticker ticker;
@@ -1533,14 +1532,17 @@
/// Quotes below are from [Dart Programming Language Specification, 4th
/// Edition](http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-408.pdf):
- List<SourceFieldBuilder> uninitializedFields = [];
- List<SourceFieldBuilder> nonFinalFields = [];
- List<SourceFieldBuilder> lateFinalFields = [];
+ List<PropertyBuilder> uninitializedFields = [];
+ List<PropertyBuilder> nonFinalFields = [];
+ List<PropertyBuilder> lateFinalFields = [];
- Iterator<SourceFieldBuilder> fieldIterator =
- classDeclaration.fullMemberIterator<SourceFieldBuilder>();
+ Iterator<PropertyBuilder> fieldIterator =
+ classDeclaration.fullMemberIterator<PropertyBuilder>();
while (fieldIterator.moveNext()) {
- SourceFieldBuilder fieldBuilder = fieldIterator.current;
+ PropertyBuilder fieldBuilder = fieldIterator.current;
+ if (!fieldBuilder.isField) {
+ continue;
+ }
if (fieldBuilder.isAbstract || fieldBuilder.isExternal) {
// Skip abstract and external fields. These are abstract/external
// getters/setters and have no initialization.
@@ -1559,10 +1561,10 @@
}
}
- Map<ConstructorDeclaration, Set<SourceFieldBuilder>>
+ Map<ConstructorDeclaration, Set<PropertyBuilder>>
constructorInitializedFields = new Map.identity();
- Set<SourceFieldBuilder>? initializedFieldBuilders = null;
- Set<SourceFieldBuilder>? uninitializedInstanceFields;
+ Set<PropertyBuilder>? initializedFieldBuilders = null;
+ Set<PropertyBuilder>? uninitializedInstanceFields;
Iterator<ConstructorDeclaration> constructorIterator =
classDeclaration.fullConstructorIterator<ConstructorDeclaration>();
@@ -1579,14 +1581,14 @@
nonFinalFields.clear();
}
if (constructor.isConst && lateFinalFields.isNotEmpty) {
- for (FieldBuilder field in lateFinalFields) {
+ for (PropertyBuilder field in lateFinalFields) {
classDeclaration.addProblem(
messageConstConstructorLateFinalFieldError,
field.fileOffset,
noLength,
context: [
messageConstConstructorLateFinalFieldCause.withLocation(
- constructor.fileUri!, constructor.fileOffset, noLength)
+ constructor.fileUri, constructor.fileOffset, noLength)
]);
}
lateFinalFields.clear();
@@ -1595,23 +1597,23 @@
// Assume that an external constructor initializes all uninitialized
// instance fields.
uninitializedInstanceFields ??= uninitializedFields
- .where((SourceFieldBuilder fieldBuilder) => !fieldBuilder.isStatic)
+ .where((PropertyBuilder fieldBuilder) => !fieldBuilder.isStatic)
.toSet();
constructorInitializedFields[constructor] = uninitializedInstanceFields;
- (initializedFieldBuilders ??= new Set<SourceFieldBuilder>.identity())
+ (initializedFieldBuilders ??= new Set<PropertyBuilder>.identity())
.addAll(uninitializedInstanceFields);
} else {
- Set<SourceFieldBuilder> fields =
+ Set<PropertyBuilder> fields =
constructor.takeInitializedFields() ?? const {};
constructorInitializedFields[constructor] = fields;
- (initializedFieldBuilders ??= new Set<SourceFieldBuilder>.identity())
+ (initializedFieldBuilders ??= new Set<PropertyBuilder>.identity())
.addAll(fields);
}
}
// Run through all fields that aren't initialized by any constructor, and
// set their initializer to `null`.
- for (SourceFieldBuilder fieldBuilder in uninitializedFields) {
+ for (PropertyBuilder fieldBuilder in uninitializedFields) {
if (fieldBuilder.isExtensionTypeDeclaredInstanceField) continue;
if (initializedFieldBuilders == null ||
!initializedFieldBuilders.contains(fieldBuilder)) {
@@ -1651,11 +1653,11 @@
// Run through all fields that are initialized by some constructor, and
// make sure that all other constructors also initialize them.
- for (MapEntry<ConstructorDeclaration, Set<FieldBuilder>> entry
+ for (MapEntry<ConstructorDeclaration, Set<PropertyBuilder>> entry
in constructorInitializedFields.entries) {
ConstructorDeclaration constructorBuilder = entry.key;
- Set<FieldBuilder> fieldBuilders = entry.value;
- for (SourceFieldBuilder fieldBuilder
+ Set<PropertyBuilder> fieldBuilders = entry.value;
+ for (PropertyBuilder fieldBuilder
in initializedFieldBuilders!.difference(fieldBuilders)) {
if (fieldBuilder.isExtensionTypeDeclaredInstanceField) continue;
if (!fieldBuilder.hasInitializer && !fieldBuilder.isLate) {
@@ -1674,12 +1676,12 @@
.withLocation(fieldBuilder.fileUri,
fieldBuilder.fileOffset, fieldBuilder.name.length)
]);
- } else if (fieldBuilder.field.type is! InvalidType &&
+ } else if (fieldBuilder.fieldType is! InvalidType &&
!fieldBuilder.isLate &&
- fieldBuilder.field.type.isPotentiallyNonNullable) {
+ fieldBuilder.fieldType.isPotentiallyNonNullable) {
libraryBuilder.addProblem(
templateFieldNonNullableNotInitializedByConstructorError
- .withArguments(fieldBuilder.name, fieldBuilder.field.type),
+ .withArguments(fieldBuilder.name, fieldBuilder.fieldType),
constructorBuilder.fileOffset,
noLength,
constructorBuilder.fileUri,
diff --git a/pkg/front_end/lib/src/kernel/macro/introspectors.dart b/pkg/front_end/lib/src/kernel/macro/introspectors.dart
index 29679e1..afc8a18 100644
--- a/pkg/front_end/lib/src/kernel/macro/introspectors.dart
+++ b/pkg/front_end/lib/src/kernel/macro/introspectors.dart
@@ -129,8 +129,12 @@
macro.Declaration _createMemberDeclaration(MemberBuilder memberBuilder) {
if (memberBuilder is SourceMethodBuilder) {
return _createMethodDeclaration(memberBuilder);
- } else if (memberBuilder is SourcePropertyBuilder) {
+ } else if (memberBuilder is SourcePropertyBuilder &&
+ (memberBuilder.isGetter || memberBuilder.isSetter)) {
return _createGetterDeclaration(memberBuilder);
+ } else if (memberBuilder is SourcePropertyBuilder &&
+ memberBuilder.isField) {
+ return _createFieldDeclaration(memberBuilder);
} else if (memberBuilder is SourceFieldBuilder) {
return _createVariableDeclaration(memberBuilder);
} else if (memberBuilder is SourceConstructorBuilder) {
@@ -445,10 +449,8 @@
// TODO(johnniwinther): Support typeParameters
typeParameters: const [],
);
- if (builder.fileUri != null) {
- _declarationOffsets[declaration] =
- new UriOffset(builder.fileUri!, builder.fileOffset);
- }
+ _declarationOffsets[declaration] =
+ new UriOffset(builder.fileUri, builder.fileOffset);
return declaration;
}
@@ -641,6 +643,64 @@
}
/// Creates the [macro.VariableDeclaration] corresponding to [builder].
+ macro.VariableDeclaration _createFieldDeclaration(
+ SourcePropertyBuilder builder) {
+ macro.ParameterizedTypeDeclaration? definingTypeDeclaration = null;
+ Builder? parent = builder.parent;
+ if (parent is ClassBuilder) {
+ definingTypeDeclaration = getClassDeclaration(parent);
+ } else if (parent is ExtensionTypeDeclarationBuilder) {
+ definingTypeDeclaration = getExtensionTypeDeclaration(parent);
+ }
+ final macro.LibraryImpl library = getLibrary(builder.libraryBuilder);
+ macro.VariableDeclaration declaration;
+ if (definingTypeDeclaration != null) {
+ // TODO(johnniwinther): Should static fields be field or variable
+ // declarations?
+ declaration = new macro.FieldDeclarationImpl(
+ id: macro.RemoteInstance.uniqueId,
+ identifier: new MemberBuilderIdentifier(
+ memberBuilder: builder,
+ id: macro.RemoteInstance.uniqueId,
+ name: builder.name),
+ library: library,
+ // TODO: Provide metadata annotations.
+ metadata: const [],
+ definingType:
+ definingTypeDeclaration.identifier as macro.IdentifierImpl,
+ hasAbstract: builder.isAbstract,
+ hasConst: builder.isConst,
+ hasExternal: builder.isExternal,
+ hasFinal: builder.isFinal,
+ hasInitializer: builder.hasInitializer,
+ hasLate: builder.isLate,
+ hasStatic: builder.isStatic,
+ type: types.getTypeAnnotation(
+ builder.libraryBuilder, builder.typeForTesting));
+ } else {
+ declaration = new macro.VariableDeclarationImpl(
+ id: macro.RemoteInstance.uniqueId,
+ identifier: new MemberBuilderIdentifier(
+ memberBuilder: builder,
+ id: macro.RemoteInstance.uniqueId,
+ name: builder.name),
+ library: library,
+ // TODO: Provide metadata annotations.
+ metadata: const [],
+ hasConst: builder.isConst,
+ hasExternal: builder.isExternal,
+ hasFinal: builder.isFinal,
+ hasInitializer: builder.hasInitializer,
+ hasLate: builder.isLate,
+ type: types.getTypeAnnotation(
+ builder.libraryBuilder, builder.typeForTesting));
+ }
+ _declarationOffsets[declaration] =
+ new UriOffset(builder.fileUri, builder.fileOffset);
+ return declaration;
+ }
+
+ /// Creates the [macro.VariableDeclaration] corresponding to [builder].
macro.VariableDeclaration _createVariableDeclaration(
SourceFieldBuilder builder) {
macro.ParameterizedTypeDeclaration? definingTypeDeclaration = null;
@@ -867,20 +927,26 @@
if (type is macro.ClassDeclaration || type is macro.MixinDeclaration) {
ClassBuilder classBuilder = _introspection
._getClassBuilder(type as macro.ParameterizedTypeDeclaration);
- Iterator<SourceFieldBuilder> iterator =
- classBuilder.fullMemberIterator<SourceFieldBuilder>();
+ Iterator<SourceMemberBuilder> iterator =
+ classBuilder.fullMemberIterator<SourceMemberBuilder>();
while (iterator.moveNext()) {
- result.add(_introspection.getMemberDeclaration(iterator.current)
- as macro.FieldDeclaration);
+ SourceMemberBuilder memberBuilder = iterator.current;
+ if (memberBuilder.isField) {
+ result.add(_introspection.getMemberDeclaration(memberBuilder)
+ as macro.FieldDeclaration);
+ }
}
} else if (type is macro.ExtensionTypeDeclaration) {
ExtensionTypeDeclarationBuilder extensionTypeDeclarationBuilder =
_introspection._getExtensionTypeDeclarationBuilder(type);
- Iterator<SourceFieldBuilder> iterator = extensionTypeDeclarationBuilder
- .fullMemberIterator<SourceFieldBuilder>();
+ Iterator<SourceMemberBuilder> iterator = extensionTypeDeclarationBuilder
+ .fullMemberIterator<SourceMemberBuilder>();
while (iterator.moveNext()) {
- result.add(_introspection.getMemberDeclaration(iterator.current)
- as macro.FieldDeclaration);
+ SourceMemberBuilder memberBuilder = iterator.current;
+ if (memberBuilder.isField) {
+ result.add(_introspection.getMemberDeclaration(memberBuilder)
+ as macro.FieldDeclaration);
+ }
}
} else {
throw new UnsupportedError('Only introspection on classes is supported');
@@ -899,7 +965,8 @@
while (iterator.moveNext()) {
SourceMemberBuilder memberBuilder = iterator.current;
if (memberBuilder is SourceMethodBuilder ||
- memberBuilder is SourcePropertyBuilder) {
+ (memberBuilder is SourcePropertyBuilder &&
+ (memberBuilder.isGetter || memberBuilder.isSetter))) {
result.add(_introspection.getMemberDeclaration(memberBuilder)
as macro.MethodDeclaration);
}
@@ -912,7 +979,8 @@
while (iterator.moveNext()) {
SourceMemberBuilder memberBuilder = iterator.current;
if (memberBuilder is SourceMethodBuilder ||
- memberBuilder is SourcePropertyBuilder) {
+ (memberBuilder is SourcePropertyBuilder &&
+ (memberBuilder.isGetter || memberBuilder.isSetter))) {
result.add(_introspection.getMemberDeclaration(memberBuilder)
as macro.MethodDeclaration);
}
diff --git a/pkg/front_end/lib/src/kernel/macro/metadata.dart b/pkg/front_end/lib/src/kernel/macro/metadata.dart
index f270f6e..763aa31 100644
--- a/pkg/front_end/lib/src/kernel/macro/metadata.dart
+++ b/pkg/front_end/lib/src/kernel/macro/metadata.dart
@@ -24,8 +24,10 @@
import '../../builder/null_type_declaration_builder.dart';
import '../../builder/prefix_builder.dart';
import '../../builder/procedure_builder.dart';
+import '../../builder/property_builder.dart';
import '../../source/source_field_builder.dart';
import '../../source/source_method_builder.dart';
+import '../../source/source_property_builder.dart';
// Coverage-ignore(suite): Not run.
final Uri dummyUri = Uri.parse('dummy:uri');
@@ -79,6 +81,11 @@
if (element is SourceFieldBuilder) {
return element.initializerExpression;
}
+ } else if (reference is PropertyReference) {
+ PropertyBuilder element = reference.builder;
+ if (element is SourcePropertyBuilder) {
+ return element.initializerExpression;
+ }
} else {
assert(false,
"Unexpected field reference $reference (${reference.runtimeType})");
@@ -90,6 +97,8 @@
shared.Proto builderToProto(Builder builder, String name) {
if (builder is FieldBuilder) {
return new shared.FieldProto(new FieldReference(builder));
+ } else if (builder is PropertyBuilder) {
+ return new shared.FieldProto(new PropertyReference(builder));
} else if (builder is ProcedureBuilder) {
return new shared.FunctionProto(new FunctionReference(builder));
} else if (builder is SourceMethodBuilder) {
@@ -353,6 +362,16 @@
}
// Coverage-ignore(suite): Not run.
+class PropertyReference extends shared.FieldReference {
+ final PropertyBuilder builder;
+
+ PropertyReference(this.builder);
+
+ @override
+ String get name => builder.name;
+}
+
+// Coverage-ignore(suite): Not run.
class FunctionReference extends shared.FunctionReference {
final ProcedureBuilder builder;
diff --git a/pkg/front_end/lib/src/source/constructor_declaration.dart b/pkg/front_end/lib/src/source/constructor_declaration.dart
index ef5edc3..17a90bc 100644
--- a/pkg/front_end/lib/src/source/constructor_declaration.dart
+++ b/pkg/front_end/lib/src/source/constructor_declaration.dart
@@ -4,9 +4,9 @@
import 'package:kernel/ast.dart';
+import '../builder/property_builder.dart';
import '../kernel/expression_generator_helper.dart';
import '../type_inference/inference_results.dart';
-import 'source_field_builder.dart';
import 'source_function_builder.dart';
/// Common interface for builders for generative constructor declarations in
@@ -41,14 +41,14 @@
///
/// The field can be initialized either via an initializing formal or via an
/// entry in the constructor initializer list.
- void registerInitializedField(SourceFieldBuilder fieldBuilder);
+ void registerInitializedField(PropertyBuilder 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<SourceFieldBuilder>? takeInitializedFields();
+ Set<PropertyBuilder>? takeInitializedFields();
/// Substitute [fieldType] from the context of the enclosing class or
/// extension type declaration to this constructor.
diff --git a/pkg/front_end/lib/src/source/diet_listener.dart b/pkg/front_end/lib/src/source/diet_listener.dart
index 4cb8778..50731ff 100644
--- a/pkg/front_end/lib/src/source/diet_listener.dart
+++ b/pkg/front_end/lib/src/source/diet_listener.dart
@@ -45,7 +45,6 @@
import '../type_inference/type_inferrer.dart' show TypeInferrer;
import 'diet_parser.dart';
import 'offset_map.dart';
-import 'source_field_builder.dart';
import 'source_library_builder.dart' show SourceLibraryBuilder;
import 'stack_listener_impl.dart';
@@ -932,13 +931,14 @@
if (names == null || currentClassIsParserRecovery) return;
Identifier first = names.first!;
- SourceFieldBuilder declaration = _offsetMap.lookupField(first);
+ FieldFragment fragment = _offsetMap.lookupField(first);
// TODO(paulberry): don't re-parse the field if we've already parsed it
// for type inference.
_parseFields(
_offsetMap,
- createListener(declaration.createBodyBuilderContext(), memberScope,
- inferenceDataForTesting: declaration
+ createListener(fragment.createBodyBuilderContext(), memberScope,
+ inferenceDataForTesting: fragment
+ .builder
.dataForTesting
// Coverage-ignore(suite): Not run.
?.inferenceData),
diff --git a/pkg/front_end/lib/src/source/offset_map.dart b/pkg/front_end/lib/src/source/offset_map.dart
index 8dd2b27..5ff7097 100644
--- a/pkg/front_end/lib/src/source/offset_map.dart
+++ b/pkg/front_end/lib/src/source/offset_map.dart
@@ -14,7 +14,6 @@
import '../builder/declaration_builders.dart';
import '../codes/cfe_codes.dart';
import '../fragment/fragment.dart';
-import 'source_field_builder.dart';
/// Map from offsets of directives and declarations to the objects the define.
///
@@ -99,9 +98,9 @@
_fields[identifier.nameOffset] = fragment;
}
- SourceFieldBuilder lookupField(Identifier identifier) {
- return _checkBuilder(_fields[identifier.nameOffset]?.builder,
- identifier.name, identifier.nameOffset);
+ FieldFragment lookupField(Identifier identifier) {
+ return _checkFragment(
+ _fields[identifier.nameOffset], identifier.name, identifier.nameOffset);
}
void registerPrimaryConstructor(
diff --git a/pkg/front_end/lib/src/source/source_class_builder.dart b/pkg/front_end/lib/src/source/source_class_builder.dart
index 54f06f6..ddfb129 100644
--- a/pkg/front_end/lib/src/source/source_class_builder.dart
+++ b/pkg/front_end/lib/src/source/source_class_builder.dart
@@ -48,7 +48,6 @@
import 'source_builder_mixins.dart';
import 'source_constructor_builder.dart';
import 'source_factory_builder.dart';
-import 'source_field_builder.dart';
import 'source_library_builder.dart';
import 'source_loader.dart';
import 'source_member_builder.dart';
@@ -1037,21 +1036,26 @@
return supertype;
}
- void checkVarianceInField(SourceFieldBuilder fieldBuilder,
- TypeEnvironment typeEnvironment, List<TypeParameter> typeParameters) {
- for (TypeParameter typeParameter in typeParameters) {
- Variance fieldVariance =
- computeVariance(typeParameter, fieldBuilder.fieldType);
- if (fieldBuilder.isClassInstanceMember) {
- reportVariancePositionIfInvalid(fieldVariance, typeParameter,
- fieldBuilder.fileUri, fieldBuilder.fileOffset);
- }
- if (fieldBuilder.isClassInstanceMember &&
- fieldBuilder.isAssignable &&
- !fieldBuilder.isCovariantByDeclaration) {
- fieldVariance = Variance.contravariant.combine(fieldVariance);
- reportVariancePositionIfInvalid(fieldVariance, typeParameter,
- fieldBuilder.fileUri, fieldBuilder.fileOffset);
+ void checkVarianceInField(TypeEnvironment typeEnvironment,
+ {required DartType fieldType,
+ required bool isInstanceMember,
+ required bool hasSetter,
+ required bool isCovariantByDeclaration,
+ required Uri fileUri,
+ required int fileOffset}) {
+ List<TypeParameter> typeParameters = cls.typeParameters;
+ if (typeParameters.isNotEmpty) {
+ for (TypeParameter typeParameter in typeParameters) {
+ Variance fieldVariance = computeVariance(typeParameter, fieldType);
+ if (isInstanceMember) {
+ reportVariancePositionIfInvalid(
+ fieldVariance, typeParameter, fileUri, fileOffset);
+ }
+ if (isInstanceMember && hasSetter && !isCovariantByDeclaration) {
+ fieldVariance = Variance.contravariant.combine(fieldVariance);
+ reportVariancePositionIfInvalid(
+ fieldVariance, typeParameter, fileUri, fileOffset);
+ }
}
}
}
diff --git a/pkg/front_end/lib/src/source/source_constructor_builder.dart b/pkg/front_end/lib/src/source/source_constructor_builder.dart
index 78a0e8b..f8f08fc 100644
--- a/pkg/front_end/lib/src/source/source_constructor_builder.dart
+++ b/pkg/front_end/lib/src/source/source_constructor_builder.dart
@@ -30,6 +30,7 @@
import '../builder/member_builder.dart';
import '../builder/metadata_builder.dart';
import '../builder/omitted_type_builder.dart';
+import '../builder/property_builder.dart';
import '../builder/type_builder.dart';
import '../kernel/body_builder.dart' show BodyBuilder;
import '../kernel/body_builder_context.dart';
@@ -51,7 +52,6 @@
import 'source_class_builder.dart';
import 'source_enum_builder.dart';
import 'source_extension_type_declaration_builder.dart';
-import 'source_field_builder.dart';
import 'source_function_builder.dart';
import 'source_library_builder.dart' show SourceLibraryBuilder;
import 'source_loader.dart'
@@ -396,6 +396,14 @@
@override
// Coverage-ignore(suite): Not run.
bool get isProperty => false;
+
+ @override
+ // Coverage-ignore(suite): Not run.
+ bool get isFinal => false;
+
+ @override
+ // Coverage-ignore(suite): Not run.
+ bool get isSynthesized => false;
}
class DeclaredSourceConstructorBuilder
@@ -405,7 +413,7 @@
@override
late final Procedure? _constructorTearOff;
- Set<SourceFieldBuilder>? _initializedFields;
+ Set<PropertyBuilder>? _initializedFields;
DeclaredSourceConstructorBuilder? actualOrigin;
@@ -1000,7 +1008,7 @@
}
@override
- void registerInitializedField(SourceFieldBuilder fieldBuilder) {
+ void registerInitializedField(PropertyBuilder fieldBuilder) {
if (isAugmenting) {
origin.registerInitializedField(fieldBuilder);
} else {
@@ -1009,8 +1017,8 @@
}
@override
- Set<SourceFieldBuilder>? takeInitializedFields() {
- Set<SourceFieldBuilder>? result = _initializedFields;
+ Set<PropertyBuilder>? takeInitializedFields() {
+ Set<PropertyBuilder>? result = _initializedFields;
_initializedFields = null;
return result;
}
@@ -1127,6 +1135,14 @@
@override
// Coverage-ignore(suite): Not run.
+ bool get isFinal => false;
+
+ @override
+ // Coverage-ignore(suite): Not run.
+ bool get isSynthesized => true;
+
+ @override
+ // Coverage-ignore(suite): Not run.
bool get isAbstract => false;
@override
@@ -1302,7 +1318,7 @@
@override
late final Procedure? _constructorTearOff;
- Set<SourceFieldBuilder>? _initializedFields;
+ Set<PropertyBuilder>? _initializedFields;
@override
List<Initializer> initializers = [];
@@ -1542,13 +1558,13 @@
}
@override
- void registerInitializedField(SourceFieldBuilder fieldBuilder) {
+ void registerInitializedField(PropertyBuilder fieldBuilder) {
(_initializedFields ??= {}).add(fieldBuilder);
}
@override
- Set<SourceFieldBuilder>? takeInitializedFields() {
- Set<SourceFieldBuilder>? result = _initializedFields;
+ Set<PropertyBuilder>? takeInitializedFields() {
+ Set<PropertyBuilder>? result = _initializedFields;
_initializedFields = null;
return result;
}
diff --git a/pkg/front_end/lib/src/source/source_extension_type_declaration_builder.dart b/pkg/front_end/lib/src/source/source_extension_type_declaration_builder.dart
index 020afb8..3ce7584 100644
--- a/pkg/front_end/lib/src/source/source_extension_type_declaration_builder.dart
+++ b/pkg/front_end/lib/src/source/source_extension_type_declaration_builder.dart
@@ -35,9 +35,9 @@
import 'source_builder_mixins.dart';
import 'source_constructor_builder.dart';
import 'source_factory_builder.dart';
-import 'source_field_builder.dart';
import 'source_library_builder.dart';
import 'source_member_builder.dart';
+import 'source_property_builder.dart';
import 'type_parameter_scope_builder.dart';
class SourceExtensionTypeDeclarationBuilder
@@ -90,8 +90,6 @@
FieldFragment? _representationFieldFragment;
- SourceFieldBuilder? _representationFieldBuilder;
-
final IndexedContainer? indexedContainer;
Nullability? _nullability;
@@ -155,13 +153,8 @@
@override
bool get isAugment => _modifiers.isAugment;
- SourceFieldBuilder? get representationFieldBuilder {
- if (_representationFieldBuilder == null) {
- _representationFieldBuilder = _representationFieldFragment?.builder;
- _representationFieldFragment = null;
- }
- return _representationFieldBuilder;
- }
+ SourcePropertyBuilder? get representationFieldBuilder =>
+ _representationFieldFragment?.builder;
@override
void buildScopes(LibraryBuilder coreLibrary) {
@@ -187,7 +180,7 @@
@override
TypeBuilder? get declaredRepresentationTypeBuilder =>
- representationFieldBuilder?.type;
+ _representationFieldFragment?.type;
@override
SourceExtensionTypeDeclarationBuilder get origin => _origin ?? this;
@@ -347,8 +340,8 @@
DartType representationType;
String representationName;
- if (representationFieldBuilder != null) {
- TypeBuilder typeBuilder = representationFieldBuilder!.type;
+ if (_representationFieldFragment != null) {
+ TypeBuilder typeBuilder = _representationFieldFragment!.type;
if (typeBuilder.isExplicit) {
if (_checkRepresentationDependency(typeBuilder, this, {this}, {})) {
representationType = const InvalidType();
@@ -373,16 +366,16 @@
if (isBottom(representationType)) {
libraryBuilder.addProblem(
messageExtensionTypeRepresentationTypeBottom,
- representationFieldBuilder!.fileOffset,
- representationFieldBuilder!.name.length,
- representationFieldBuilder!.fileUri);
+ _representationFieldFragment!.nameOffset,
+ _representationFieldFragment!.name.length,
+ _representationFieldFragment!.fileUri);
representationType = const InvalidType();
}
}
} else {
representationType = const DynamicType();
}
- representationName = representationFieldBuilder!.name;
+ representationName = _representationFieldFragment!.name;
} else {
representationType = const InvalidType();
representationName = '#';
@@ -436,9 +429,9 @@
}
libraryBuilder.addProblem(
messageCyclicRepresentationDependency,
- representationFieldBuilder!.type.charOffset!,
+ _representationFieldFragment!.type.charOffset!,
noLength,
- representationFieldBuilder!.type.fileUri,
+ _representationFieldFragment!.type.fileUri,
context: context);
return true;
} else {
diff --git a/pkg/front_end/lib/src/source/source_factory_builder.dart b/pkg/front_end/lib/src/source/source_factory_builder.dart
index 234e348..d7f73c8 100644
--- a/pkg/front_end/lib/src/source/source_factory_builder.dart
+++ b/pkg/front_end/lib/src/source/source_factory_builder.dart
@@ -182,6 +182,14 @@
// Coverage-ignore(suite): Not run.
bool get isProperty => false;
+ @override
+ // Coverage-ignore(suite): Not run.
+ bool get isFinal => false;
+
+ @override
+ // Coverage-ignore(suite): Not run.
+ bool get isSynthesized => false;
+
Procedure get _procedure =>
isAugmenting ? origin._procedure : _procedureInternal;
diff --git a/pkg/front_end/lib/src/source/source_field_builder.dart b/pkg/front_end/lib/src/source/source_field_builder.dart
index 342417e..9bb0e96 100644
--- a/pkg/front_end/lib/src/source/source_field_builder.dart
+++ b/pkg/front_end/lib/src/source/source_field_builder.dart
@@ -22,6 +22,7 @@
import '../builder/member_builder.dart';
import '../builder/metadata_builder.dart';
import '../builder/omitted_type_builder.dart';
+import '../builder/property_builder.dart';
import '../builder/type_builder.dart';
import '../codes/cfe_codes.dart' show messageInternalProblemAlreadyInitialized;
import '../kernel/body_builder.dart' show BodyBuilder;
@@ -45,7 +46,7 @@
import 'source_member_builder.dart';
class SourceFieldBuilder extends SourceMemberBuilderImpl
- implements FieldBuilder, InferredTypeListener, Inferable {
+ implements FieldBuilder, InferredTypeListener, Inferable, PropertyBuilder {
@override
final SourceLibraryBuilder libraryBuilder;
@@ -81,6 +82,7 @@
final bool isPrimaryConstructorField;
+ @override
final bool isSynthesized;
/// If `true`, this field builder is for the field corresponding to an enum
@@ -131,6 +133,7 @@
late_lowering.IsSetStrategy isSetStrategy =
late_lowering.computeIsSetStrategy(libraryBuilder);
if (isAbstract || isExternal) {
+ // Coverage-ignore-block(suite): Not run.
assert(fieldReference == null);
assert(lateIsSetFieldReference == null);
assert(lateIsSetGetterReference == null);
@@ -152,7 +155,9 @@
isFinal: isFinal,
isCovariantByDeclaration: isCovariantByDeclaration);
} else if (nameScheme.isExtensionTypeMember &&
+ // Coverage-ignore(suite): Not run.
nameScheme.isInstanceMember) {
+ // Coverage-ignore-block(suite): Not run.
assert(fieldReference == null);
assert(fieldSetterReference == null);
assert(lateIsSetFieldReference == null);
@@ -183,10 +188,12 @@
isForcedExtension: true);
}
} else if (isLate &&
+ // Coverage-ignore(suite): Not run.
libraryBuilder.loader.target.backendTarget.isLateFieldLoweringEnabled(
hasInitializer: hasInitializer,
isFinal: isFinal,
isStatic: !isInstanceMember)) {
+ // Coverage-ignore-block(suite): Not run.
assert(!isEnumElement, "Unexpected late enum element");
if (hasInitializer) {
if (isFinal) {
@@ -265,7 +272,9 @@
.loader.target.backendTarget.useStaticFieldLowering &&
!isInstanceMember &&
!isConst &&
+ // Coverage-ignore(suite): Not run.
hasInitializer) {
+ // Coverage-ignore-block(suite): Not run.
assert(!isEnumElement, "Unexpected non-const enum element");
if (isFinal) {
_fieldEncoding = new LateFinalFieldWithInitializerEncoding(
@@ -325,7 +334,10 @@
}
if (type is InferableTypeBuilder) {
- if (!hasInitializer && isStatic) {
+ if (!hasInitializer &&
+ // Coverage-ignore(suite): Not run.
+ isStatic) {
+ // Coverage-ignore-block(suite): Not run.
// A static field without type and initializer will always be inferred
// to have type `dynamic`.
type.registerInferredType(const DynamicType());
@@ -351,6 +363,7 @@
bool get isProperty => true;
@override
+ // Coverage-ignore(suite): Not run.
bool get isAugmentation => modifiers.isAugment;
@override
@@ -359,22 +372,28 @@
@override
bool get isAbstract => modifiers.isAbstract;
+ @override
+ // Coverage-ignore(suite): Not run.
bool get isExtensionTypeDeclaredInstanceField =>
isExtensionTypeInstanceMember && !isPrimaryConstructorField;
@override
bool get isConst => modifiers.isConst;
+ @override
bool get isFinal => modifiers.isFinal;
@override
bool get isStatic => modifiers.isStatic;
@override
+ // Coverage-ignore(suite): Not run.
bool get isAugment => modifiers.isAugment;
@override
- Builder get parent => declarationBuilder ?? libraryBuilder;
+ Builder get parent =>
+ declarationBuilder ?? // Coverage-ignore(suite): Not run.
+ libraryBuilder;
@override
Name get memberName => _memberName.name;
@@ -382,6 +401,7 @@
bool _typeEnsured = false;
Set<ClassMember>? _overrideDependencies;
+ // Coverage-ignore(suite): Not run.
void registerOverrideDependency(Set<ClassMember> overriddenMembers) {
assert(
overriddenMembers.every((overriddenMember) =>
@@ -394,6 +414,7 @@
void _ensureType(ClassMembersBuilder membersBuilder) {
if (_typeEnsured) return;
if (_overrideDependencies != null) {
+ // Coverage-ignore-block(suite): Not run.
membersBuilder.inferFieldType(declarationBuilder as SourceClassBuilder,
type, _overrideDependencies!,
name: fullNameForErrors,
@@ -412,10 +433,12 @@
@override
bool get isField => true;
+ @override
bool get isLate => modifiers.isLate;
bool get isCovariantByDeclaration => modifiers.isCovariant;
+ @override
bool get hasInitializer => modifiers.hasInitializer;
/// Builds the body of this field using [initializer] as the initializer
@@ -425,6 +448,7 @@
hasBodyBeenBuilt = true;
if (!hasInitializer &&
initializer != null &&
+ // Coverage-ignore(suite): Not run.
initializer is! NullLiteral &&
// Coverage-ignore(suite): Not run.
!isConst &&
@@ -436,26 +460,28 @@
_fieldEncoding.createBodies(coreTypes, initializer);
}
- /// Builds the field initializers for each field used to encode this field
- /// using the [fileOffset] for the created nodes and [value] as the initial
- /// field value.
+ @override
+ // Coverage-ignore(suite): Not run.
List<Initializer> buildInitializer(int fileOffset, Expression value,
{required bool isSynthetic}) {
return _fieldEncoding.createInitializer(fileOffset, value,
isSynthetic: isSynthetic);
}
- /// Creates the AST node for this field as the default initializer.
+ @override
+ // Coverage-ignore(suite): Not run.
void buildImplicitDefaultValue() {
_fieldEncoding.buildImplicitDefaultValue();
}
- /// Create the [Initializer] for the implicit initialization of this field
- /// in a constructor.
+ @override
+ // Coverage-ignore(suite): Not run.
Initializer buildImplicitInitializer() {
return _fieldEncoding.buildImplicitInitializer();
}
+ @override
+ // Coverage-ignore(suite): Not run.
Initializer buildErroneousInitializer(Expression effect, Expression value,
{required int fileOffset}) {
return _fieldEncoding.buildErroneousInitializer(effect, value,
@@ -465,6 +491,7 @@
@override
bool get isAssignable {
if (isConst) return false;
+ // Coverage-ignore(suite): Not run.
if (isFinal) {
if (isLate) {
return !hasInitializer;
@@ -485,6 +512,7 @@
Reference get readTargetReference => _fieldEncoding.readTargetReference;
@override
+ // Coverage-ignore(suite): Not run.
Member? get writeTarget {
return isAssignable ? _fieldEncoding.writeTarget : null;
}
@@ -501,6 +529,7 @@
Reference get invokeTargetReference => _fieldEncoding.readTargetReference;
@override
+ // Coverage-ignore(suite): Not run.
Iterable<Reference> get exportedMemberReferences =>
_fieldEncoding.exportedReferenceMembers;
@@ -535,18 +564,21 @@
createBodyBuilderContext(),
libraryBuilder,
fileUri,
- declarationBuilder?.scope ?? libraryBuilder.scope);
+ declarationBuilder?.scope ?? // Coverage-ignore(suite): Not run.
+ libraryBuilder.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 ||
+ // Coverage-ignore(suite): Not run.
(isFinal &&
!isStatic &&
isClassMember &&
classBuilder!.declaresConstConstructor)) &&
_constInitializerToken != null) {
+ // Coverage-ignore-block(suite): Not run.
Token initializerToken = _constInitializerToken!;
LookupScope scope = declarationBuilder?.scope ?? libraryBuilder.scope;
BodyBuilder bodyBuilder = libraryBuilder.loader
@@ -561,7 +593,6 @@
buildBody(classHierarchy.coreTypes, initializer);
bodyBuilder.performBacklogComputations();
if (computeSharedExpressionForTesting) {
- // Coverage-ignore-block(suite): Not run.
_initializerExpression = parseFieldInitializer(libraryBuilder.loader,
initializerToken, libraryBuilder.importUri, fileUri, scope);
}
@@ -575,11 +606,17 @@
// Coverage-ignore(suite): Not run.
bool get hasOutlineExpressionsBuilt => _constInitializerToken == null;
+ @override
DartType get fieldType => _fieldEncoding.type;
+ @override
void set fieldType(DartType value) {
_fieldEncoding.type = value;
- if (!isFinal && !isConst && parent is ClassBuilder) {
+ if (!isFinal &&
+ !isConst &&
+ // Coverage-ignore(suite): Not run.
+ parent is ClassBuilder) {
+ // Coverage-ignore-block(suite): Not run.
Class enclosingClass = classBuilder!.cls;
if (enclosingClass.typeParameters.isNotEmpty) {
IncludesTypeParametersNonCovariantly needsCheckVisitor =
@@ -601,8 +638,10 @@
inferType(hierarchy);
}
+ @override
DartType inferType(ClassHierarchyBase hierarchy) {
if (fieldType is! InferredType) {
+ // Coverage-ignore-block(suite): Not run.
// We have already inferred a type.
return fieldType;
}
@@ -630,6 +669,7 @@
}
if (needsCheckVisitor != null) {
if (fieldType.accept(needsCheckVisitor)) {
+ // Coverage-ignore-block(suite): Not run.
_fieldEncoding.setGenericCovariantImpl();
}
}
@@ -643,6 +683,7 @@
fieldType = type;
}
+ // Coverage-ignore(suite): Not run.
DartType get builtType => fieldType;
List<ClassMember>? _localMembers;
@@ -670,14 +711,28 @@
@override
void checkVariance(
SourceClassBuilder sourceClassBuilder, TypeEnvironment typeEnvironment) {
- sourceClassBuilder.checkVarianceInField(
- this, typeEnvironment, sourceClassBuilder.cls.typeParameters);
+ sourceClassBuilder.checkVarianceInField(typeEnvironment,
+ fieldType: fieldType,
+ isInstanceMember: isClassInstanceMember,
+ hasSetter: isAssignable,
+ isCovariantByDeclaration: isCovariantByDeclaration,
+ fileUri: fileUri,
+ fileOffset: fileOffset);
}
@override
void checkTypes(SourceLibraryBuilder library, NameSpace nameSpace,
TypeEnvironment typeEnvironment) {
- library.checkTypesInField(this, typeEnvironment);
+ library.checkTypesInField(typeEnvironment,
+ isInstanceMember: isDeclarationInstanceMember,
+ isLate: isLate,
+ isExternal: isExternal,
+ hasInitializer: hasInitializer,
+ fieldType: fieldType,
+ name: name,
+ nameLength: name.length,
+ nameOffset: fileOffset,
+ fileUri: fileUri);
}
@override
@@ -793,7 +848,9 @@
fieldReference: fieldReference,
getterReference: getterReference,
isEnumElement: isEnumElement)
- : new Field.mutable(dummyName,
+ :
+ // Coverage-ignore(suite): Not run.
+ new Field.mutable(dummyName,
isFinal: isFinal,
isLate: isLate,
fileUri: fileUri,
@@ -824,6 +881,7 @@
}
@override
+ // Coverage-ignore(suite): Not run.
List<Initializer> createInitializer(int fileOffset, Expression value,
{required bool isSynthetic}) {
return <Initializer>[
@@ -838,16 +896,19 @@
SourceLibraryBuilder libraryBuilder, SourceFieldBuilder fieldBuilder) {
_field..isCovariantByDeclaration = fieldBuilder.isCovariantByDeclaration;
if (fieldBuilder.isExtensionMember) {
+ // Coverage-ignore-block(suite): Not run.
_field
..isStatic = true
..isExtensionMember = true;
} else if (fieldBuilder.isExtensionTypeMember) {
+ // Coverage-ignore-block(suite): Not run.
_field
..isStatic = fieldBuilder.isStatic
..isExtensionTypeMember = true;
} else {
- bool isInstanceMember =
- !fieldBuilder.isStatic && !fieldBuilder.isTopLevel;
+ bool isInstanceMember = !fieldBuilder.isStatic &&
+ // Coverage-ignore(suite): Not run.
+ !fieldBuilder.isTopLevel;
_field
..isStatic = !isInstanceMember
..isExtensionMember = false;
@@ -867,6 +928,7 @@
}
@override
+ // Coverage-ignore(suite): Not run.
void setGenericCovariantImpl() {
if (_field.hasSetter) {
_field.isCovariantByClass = true;
@@ -890,6 +952,7 @@
Reference get readTargetReference => _field.getterReference;
@override
+ // Coverage-ignore(suite): Not run.
Member get writeTarget => _field;
@override
@@ -897,6 +960,7 @@
Reference? get writeTargetReference => _field.setterReference;
@override
+ // Coverage-ignore(suite): Not run.
Iterable<Reference> get exportedReferenceMembers =>
[_field.getterReference, if (_field.hasSetter) _field.setterReference!];
@@ -909,22 +973,27 @@
@override
List<ClassMember> getLocalSetters(SourceFieldBuilder fieldBuilder) =>
fieldBuilder.isAssignable
- ? <ClassMember>[
+ ?
+ // Coverage-ignore(suite): Not run.
+ <ClassMember>[
new SourceFieldMember(fieldBuilder, ClassMemberKind.Setter)
]
: const <ClassMember>[];
@override
+ // Coverage-ignore(suite): Not run.
void buildImplicitDefaultValue() {
_field.initializer = new NullLiteral()..parent = _field;
}
@override
+ // Coverage-ignore(suite): Not run.
Initializer buildImplicitInitializer() {
return new FieldInitializer(_field, new NullLiteral())..isSynthetic = true;
}
@override
+ // Coverage-ignore(suite): Not run.
Initializer buildErroneousInitializer(Expression effect, Expression value,
{required int fileOffset}) {
return new ShadowInvalidFieldInitializer(type, value, effect)
@@ -944,11 +1013,13 @@
SourceFieldMember(this.memberBuilder, this.memberKind);
@override
+ // Coverage-ignore(suite): Not run.
void inferType(ClassMembersBuilder membersBuilder) {
memberBuilder._ensureType(membersBuilder);
}
@override
+ // Coverage-ignore(suite): Not run.
void registerOverrideDependency(Set<ClassMember> overriddenMembers) {
memberBuilder.registerOverrideDependency(overriddenMembers);
}
@@ -968,6 +1039,7 @@
}
@override
+ // Coverage-ignore(suite): Not run.
Covariance getCovariance(ClassMembersBuilder membersBuilder) {
return _covariance ??= forSetter
? new Covariance.fromMember(getMember(membersBuilder),
@@ -976,6 +1048,7 @@
}
@override
+ // Coverage-ignore(suite): Not run.
bool get isSourceDeclaration => true;
@override
@@ -983,10 +1056,13 @@
@override
bool isSameDeclaration(ClassMember other) {
- return other is SourceFieldMember && memberBuilder == other.memberBuilder;
+ return other is SourceFieldMember &&
+ // Coverage-ignore(suite): Not run.
+ memberBuilder == other.memberBuilder;
}
}
+// Coverage-ignore(suite): Not run.
abstract class AbstractLateFieldEncoding implements FieldEncoding {
final String name;
final int fileOffset;
@@ -1264,14 +1340,12 @@
Member get readTarget => _lateGetter;
@override
- // Coverage-ignore(suite): Not run.
Reference get readTargetReference => _lateGetter.reference;
@override
Member? get writeTarget => _lateSetter;
@override
- // Coverage-ignore(suite): Not run.
Reference? get writeTargetReference => _lateSetter?.reference;
@override
@@ -1294,7 +1368,6 @@
..isExtensionMember = isExtensionMember;
isInstanceMember = false;
} else if (isExtensionTypeMember) {
- // Coverage-ignore-block(suite): Not run.
_field
..isStatic = fieldBuilder.isStatic
..isExtensionTypeMember = true;
@@ -1399,6 +1472,7 @@
mixin NonFinalLate on AbstractLateFieldEncoding {
@override
+ // Coverage-ignore(suite): Not run.
Statement _createSetterBody(
CoreTypes coreTypes, String name, VariableDeclaration parameter) {
assert(_type != null, "Type has not been computed for field $name.");
@@ -1415,6 +1489,7 @@
mixin LateWithoutInitializer on AbstractLateFieldEncoding {
@override
+ // Coverage-ignore(suite): Not run.
Statement _createGetterBody(
CoreTypes coreTypes, String name, Expression? initializer) {
assert(_type != null, "Type has not been computed for field $name.");
@@ -1443,6 +1518,7 @@
}
}
+// Coverage-ignore(suite): Not run.
class LateFieldWithoutInitializerEncoding extends AbstractLateFieldEncoding
with NonFinalLate, LateWithoutInitializer {
LateFieldWithoutInitializerEncoding(
@@ -1463,6 +1539,7 @@
required super.isSetStrategy});
}
+// Coverage-ignore(suite): Not run.
class LateFieldWithInitializerEncoding extends AbstractLateFieldEncoding
with NonFinalLate {
LateFieldWithInitializerEncoding(
@@ -1514,6 +1591,7 @@
}
}
+// Coverage-ignore(suite): Not run.
class LateFinalFieldWithoutInitializerEncoding extends AbstractLateFieldEncoding
with LateWithoutInitializer {
LateFinalFieldWithoutInitializerEncoding(
@@ -1551,6 +1629,7 @@
}
}
+// Coverage-ignore(suite): Not run.
class LateFinalFieldWithInitializerEncoding extends AbstractLateFieldEncoding {
LateFinalFieldWithInitializerEncoding(
{required super.name,
@@ -1591,7 +1670,6 @@
null;
@override
- // Coverage-ignore(suite): Not run.
Statement _createSetterBody(
CoreTypes coreTypes, String name, VariableDeclaration parameter) =>
throw new UnsupportedError(
@@ -1614,6 +1692,7 @@
}
}
+// Coverage-ignore(suite): Not run.
class _SynthesizedFieldClassMember implements ClassMember {
final SourceFieldBuilder fieldBuilder;
final _SynthesizedFieldMemberKind _kind;
@@ -1683,7 +1762,6 @@
DeclarationBuilder get declarationBuilder => fieldBuilder.declarationBuilder!;
@override
- // Coverage-ignore(suite): Not run.
bool isObjectMember(ClassBuilder objectClass) {
return declarationBuilder == objectClass;
}
@@ -1713,7 +1791,6 @@
Name get name => _name;
@override
- // Coverage-ignore(suite): Not run.
String get fullName {
String suffix = isSetter ? "=" : "";
String className = declarationBuilder.fullNameForErrors;
@@ -1739,7 +1816,6 @@
bool get hasDeclarations => false;
@override
- // Coverage-ignore(suite): Not run.
List<ClassMember> get declarations =>
throw new UnsupportedError("$runtimeType.declarations");
@@ -1765,6 +1841,7 @@
bool get isExtensionTypeMember => fieldBuilder.isExtensionTypeMember;
}
+// Coverage-ignore(suite): Not run.
class AbstractOrExternalFieldEncoding implements FieldEncoding {
final SourceFieldBuilder _fieldBuilder;
final bool isAbstract;
@@ -1935,7 +2012,6 @@
Procedure? setter = _setter;
if (setter != null) {
if (setter.kind == ProcedureKind.Method) {
- // Coverage-ignore-block(suite): Not run.
setter.function.positionalParameters[1].type = value;
} else {
setter.function.positionalParameters.first.type = value;
@@ -2010,7 +2086,6 @@
}
@override
- // Coverage-ignore(suite): Not run.
void setGenericCovariantImpl() {
_setter!.function.positionalParameters.first.isCovariantByClass = true;
}
@@ -2036,14 +2111,12 @@
Member get readTarget => _getter;
@override
- // Coverage-ignore(suite): Not run.
Reference get readTargetReference => _getter.reference;
@override
Member? get writeTarget => _setter;
@override
- // Coverage-ignore(suite): Not run.
Reference? get writeTargetReference => _setter?.reference;
@override
@@ -2098,6 +2171,7 @@
}
}
+// Coverage-ignore(suite): Not run.
/// The encoding of an extension type declaration representation field.
class RepresentationFieldEncoding implements FieldEncoding {
final SourceFieldBuilder _fieldBuilder;
@@ -2134,10 +2208,7 @@
@override
void set type(DartType value) {
- assert(
- _type == null ||
- // Coverage-ignore(suite): Not run.
- _type is InferredType,
+ assert(_type == null || _type is InferredType,
"Type has already been computed for field ${_fieldBuilder.name}.");
_type = value;
if (value is! InferredType) {
@@ -2146,7 +2217,6 @@
}
@override
- // Coverage-ignore(suite): Not run.
void createBodies(CoreTypes coreTypes, Expression? initializer) {
// TODO(johnniwinther): Enable this assert.
//assert(initializer != null);
@@ -2198,19 +2268,15 @@
Member get readTarget => _getter;
@override
- // Coverage-ignore(suite): Not run.
Reference get readTargetReference => _getter.reference;
@override
- // Coverage-ignore(suite): Not run.
Member? get writeTarget => null;
@override
- // Coverage-ignore(suite): Not run.
Reference? get writeTargetReference => null;
@override
- // Coverage-ignore(suite): Not run.
Iterable<Reference> get exportedReferenceMembers => [_getter.reference];
@override
@@ -2230,7 +2296,6 @@
const <ClassMember>[];
@override
- // Coverage-ignore(suite): Not run.
void buildImplicitDefaultValue() {
// Not needed.
}
diff --git a/pkg/front_end/lib/src/source/source_library_builder.dart b/pkg/front_end/lib/src/source/source_library_builder.dart
index 0b046cd..85f0fb2 100644
--- a/pkg/front_end/lib/src/source/source_library_builder.dart
+++ b/pkg/front_end/lib/src/source/source_library_builder.dart
@@ -70,7 +70,6 @@
import 'source_extension_builder.dart';
import 'source_extension_type_declaration_builder.dart';
import 'source_factory_builder.dart';
-import 'source_field_builder.dart';
import 'source_loader.dart'
show CompilationPhaseForProblemReporting, SourceLoader;
import 'source_member_builder.dart';
@@ -874,7 +873,7 @@
while (memberIterator.moveNext()) {
SourceMemberBuilder member = memberIterator.current;
if (member.isStatic) continue;
- if (member is SourceFieldBuilder) {
+ if (member.isField) {
if (member.isSynthesized) continue;
PropertyNonPromotabilityReason? reason = fieldPromotability.addField(
classInfo, member, member.name,
@@ -882,7 +881,7 @@
isAbstract: member.isAbstract,
isExternal: member.isExternal);
if (reason != null) {
- individualPropertyReasons[member.readTarget] = reason;
+ individualPropertyReasons[member.readTarget!] = reason;
}
} else if (member.isGetter) {
if (member.isSynthetic) continue;
@@ -1655,26 +1654,33 @@
addProblem(message, fileOffset, noLength, fileUri, context: context);
}
- void checkTypesInField(
- SourceFieldBuilder fieldBuilder, TypeEnvironment typeEnvironment) {
+ void checkTypesInField(TypeEnvironment typeEnvironment,
+ {required bool isInstanceMember,
+ required bool isLate,
+ required bool isExternal,
+ required bool hasInitializer,
+ required DartType fieldType,
+ required String name,
+ required int nameLength,
+ required int nameOffset,
+ required Uri fileUri}) {
// Check that the field has an initializer if its type is potentially
// non-nullable.
// Only static and top-level fields are checked here. Instance fields are
// checked elsewhere.
- DartType fieldType = fieldBuilder.fieldType;
- if (!fieldBuilder.isDeclarationInstanceMember &&
- !fieldBuilder.isLate &&
- !fieldBuilder.isExternal &&
+ if (!isInstanceMember &&
+ !isLate &&
+ !isExternal &&
fieldType is! InvalidType &&
fieldType.isPotentiallyNonNullable &&
- !fieldBuilder.hasInitializer) {
+ !hasInitializer) {
addProblem(
templateFieldNonNullableWithoutInitializerError.withArguments(
- fieldBuilder.name, fieldBuilder.fieldType),
- fieldBuilder.fileOffset,
- fieldBuilder.name.length,
- fieldBuilder.fileUri);
+ name, fieldType),
+ nameOffset,
+ nameLength,
+ fileUri);
}
}
@@ -2212,8 +2218,8 @@
/// This class examines all the [Class]es in a library and determines which
/// fields are promotable within that library.
-class _FieldPromotability
- extends FieldPromotability<Class, SourceFieldBuilder, SourceMemberBuilder> {
+class _FieldPromotability extends FieldPromotability<Class, SourceMemberBuilder,
+ SourceMemberBuilder> {
@override
Iterable<Class> getSuperclasses(Class class_,
{required bool ignoreImplements}) {
@@ -2253,7 +2259,7 @@
/// see [individualPropertyReasons].
final Map<
String,
- FieldNameNonPromotabilityInfo<Class, SourceFieldBuilder,
+ FieldNameNonPromotabilityInfo<Class, SourceMemberBuilder,
SourceMemberBuilder>> fieldNameInfo;
/// Map whose keys are the members that a property get might resolve to, and
diff --git a/pkg/front_end/lib/src/source/source_member_builder.dart b/pkg/front_end/lib/src/source/source_member_builder.dart
index 1f9ef75..43a412c 100644
--- a/pkg/front_end/lib/src/source/source_member_builder.dart
+++ b/pkg/front_end/lib/src/source/source_member_builder.dart
@@ -28,6 +28,14 @@
@override
SourceLibraryBuilder get libraryBuilder;
+ @override
+ Uri get fileUri;
+
+ bool get isFinal;
+
+ // TODO(johnniwinther): Avoid this or define a clear semantics.
+ bool get isSynthesized;
+
/// Builds the core AST structures for this member as needed for the outline.
void buildOutlineNodes(BuildNodesCallback f);
diff --git a/pkg/front_end/lib/src/source/source_method_builder.dart b/pkg/front_end/lib/src/source/source_method_builder.dart
index af9fad6..8b7ba28 100644
--- a/pkg/front_end/lib/src/source/source_method_builder.dart
+++ b/pkg/front_end/lib/src/source/source_method_builder.dart
@@ -118,6 +118,14 @@
@override
bool get isAugment => _modifiers.isAugment;
+ @override
+ // Coverage-ignore(suite): Not run.
+ bool get isFinal => false;
+
+ @override
+ // Coverage-ignore(suite): Not run.
+ bool get isSynthesized => false;
+
// TODO(johnniwinther): What is this supposed to return?
@override
// Coverage-ignore(suite): Not run.
diff --git a/pkg/front_end/lib/src/source/source_property_builder.dart b/pkg/front_end/lib/src/source/source_property_builder.dart
index 4d2482e..fef0e3c 100644
--- a/pkg/front_end/lib/src/source/source_property_builder.dart
+++ b/pkg/front_end/lib/src/source/source_property_builder.dart
@@ -2,8 +2,10 @@
// 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/metadata/expressions.dart' as shared;
import 'package:kernel/ast.dart';
import 'package:kernel/class_hierarchy.dart';
+import 'package:kernel/reference_from_index.dart';
import 'package:kernel/type_algebra.dart';
import 'package:kernel/type_environment.dart';
@@ -14,6 +16,7 @@
import '../builder/declaration_builders.dart';
import '../builder/formal_parameter_builder.dart';
import '../builder/metadata_builder.dart';
+import '../builder/property_builder.dart';
import '../builder/type_builder.dart';
import '../fragment/fragment.dart';
import '../kernel/augmentation_lowering.dart';
@@ -26,9 +29,11 @@
import 'source_class_builder.dart';
import 'source_function_builder.dart';
import 'source_library_builder.dart';
+import 'source_loader.dart';
import 'source_member_builder.dart';
-class SourcePropertyBuilder extends SourceMemberBuilderImpl {
+class SourcePropertyBuilder extends SourceMemberBuilderImpl
+ implements PropertyBuilder {
@override
final Uri fileUri;
@@ -53,13 +58,13 @@
/// same name must be augmentations.
// TODO(johnniwinther): Support setter and field declarations.
// TODO(johnniwinther): Add [_augmentations] field.
+ FieldFragment? _introductoryField;
GetterFragment? _introductoryGetable;
SetterFragment? _introductorySetable;
Modifiers _modifiers;
- final Reference? _getterReference;
- final Reference? _setterReference;
+ final PropertyReferences _references;
final MemberName _memberName;
@@ -89,12 +94,11 @@
required this.isStatic,
required NameScheme nameScheme,
required GetterFragment fragment,
- required Reference? getterReference})
+ required PropertyReferences references})
: _nameScheme = nameScheme,
_introductoryGetable = fragment,
_modifiers = fragment.modifiers,
- _getterReference = getterReference ?? new Reference(),
- _setterReference = null,
+ _references = references,
_memberName = nameScheme.getDeclaredName(name);
SourcePropertyBuilder.forSetter(
@@ -106,12 +110,27 @@
required this.isStatic,
required NameScheme nameScheme,
required SetterFragment fragment,
- required Reference? setterReference})
+ required PropertyReferences references})
: _nameScheme = nameScheme,
_introductorySetable = fragment,
_modifiers = fragment.modifiers,
- _getterReference = null,
- _setterReference = setterReference ?? new Reference(),
+ _references = references,
+ _memberName = nameScheme.getDeclaredName(name);
+
+ SourcePropertyBuilder.forField(
+ {required this.fileUri,
+ required this.fileOffset,
+ required this.name,
+ required this.libraryBuilder,
+ required this.declarationBuilder,
+ required this.isStatic,
+ required NameScheme nameScheme,
+ required FieldFragment fragment,
+ required PropertyReferences references})
+ : _nameScheme = nameScheme,
+ _introductoryField = fragment,
+ _modifiers = fragment.modifiers,
+ _references = references,
_memberName = nameScheme.getDeclaredName(name);
@override
@@ -133,20 +152,27 @@
@override
bool get isAugment => _modifiers.isAugment;
+ @override
+ bool get isSynthesized => false;
+
// TODO(johnniwinther): What is this supposed to return?
@override
// Coverage-ignore(suite): Not run.
Iterable<Annotatable> get annotatables => [
if (readTarget != null) readTarget as Annotatable,
- if (writeTarget != null) writeTarget as Annotatable
+ if (writeTarget != null && readTarget != writeTarget)
+ writeTarget as Annotatable
];
// TODO(johnniwinther): Remove this. This is only needed for detecting patches
// and macro annotations and we should use the fragment directly once
// augmentations are fragments.
List<MetadataBuilder>? get metadata =>
- _introductoryGetable?.metadata ?? // Coverage-ignore(suite): Not run.
- _introductorySetable?.metadata;
+ _introductoryGetable?.metadata ??
+ _introductorySetable
+ // Coverage-ignore(suite): Not run.
+ ?.metadata ??
+ _introductoryField?.metadata;
@override
void applyAugmentation(Builder augmentation) {
@@ -344,11 +370,14 @@
@override
void buildOutlineNodes(BuildNodesCallback f) {
- _introductoryGetable?.buildOutlineNode(libraryBuilder, _nameScheme, f,
- getterReference: _getterReference!,
+ _introductoryField?.buildOutlineNode(
+ libraryBuilder, _nameScheme, f, _references as FieldReference,
classTypeParameters: classBuilder?.cls.typeParameters);
- _introductorySetable?.buildOutlineNode(libraryBuilder, _nameScheme, f,
- setterReference: _setterReference!,
+ _introductoryGetable?.buildOutlineNode(
+ libraryBuilder, _nameScheme, f, _references as GetterReference,
+ classTypeParameters: classBuilder?.cls.typeParameters);
+ _introductorySetable?.buildOutlineNode(
+ libraryBuilder, _nameScheme, f, _references as SetterReference,
classTypeParameters: classBuilder?.cls.typeParameters);
}
@@ -360,6 +389,18 @@
if (!hasBuiltOutlineExpressions) {
LookupScope parentScope =
declarationBuilder?.scope ?? libraryBuilder.scope;
+ _introductoryField?.buildOutlineExpressions(
+ classHierarchy,
+ libraryBuilder,
+ declarationBuilder,
+ parentScope,
+ [
+ readTarget as Annotatable,
+ if (writeTarget != null && readTarget != writeTarget)
+ writeTarget as Annotatable
+ ],
+ isClassInstanceMember: isClassInstanceMember,
+ createFileUriExpression: isAugmented);
_introductoryGetable?.buildOutlineExpressions(
classHierarchy,
libraryBuilder,
@@ -390,6 +431,8 @@
setterBuilder = nameSpace.lookupLocalMember(name, setter: true)
as SourcePropertyBuilder?;
}
+ _introductoryField?.checkTypes(library, typeEnvironment, setterBuilder,
+ isExternal: isExternal, isAbstract: isAbstract);
_introductoryGetable?.checkTypes(library, typeEnvironment, setterBuilder,
isExternal: isExternal, isAbstract: isAbstract);
_introductorySetable?.checkTypes(library, typeEnvironment,
@@ -412,6 +455,7 @@
void checkVariance(
SourceClassBuilder sourceClassBuilder, TypeEnvironment typeEnvironment) {
if (!isClassInstanceMember) return;
+ _introductoryField?.checkVariance(sourceClassBuilder, typeEnvironment);
_introductoryGetable?.checkVariance(sourceClassBuilder, typeEnvironment);
_introductorySetable?.checkVariance(sourceClassBuilder, typeEnvironment);
List<SourcePropertyBuilder>? getterAugmentations = _getterAugmentations;
@@ -430,21 +474,24 @@
@override
Iterable<Reference> get exportedMemberReferences => [
- if (_getterReference != null) _getterReference,
- if (_setterReference != null) _setterReference
+ ...?_introductoryField
+ ?.getExportedMemberReferences(_references as FieldReference),
+ ...?_introductoryGetable
+ ?.getExportedMemberReferences(_references as GetterReference),
+ ...?_introductorySetable
+ ?.getExportedMemberReferences(_references as SetterReference),
];
+ // TODO(johnniwinther): Should fields and getters have an invoke target?
@override
- Member? get invokeTarget => null;
+ Member? get invokeTarget => readTarget;
@override
// Coverage-ignore(suite): Not run.
- Reference? get invokeTargetReference => null;
+ Reference? get invokeTargetReference => readTargetReference;
@override
- // Coverage-ignore(suite): Not run.
- bool get isAssignable =>
- throw new UnsupportedError('$runtimeType.isAssignable');
+ bool get isAssignable => _introductoryField?.hasSetter ?? false;
List<ClassMember>? _localMembers;
@@ -452,12 +499,14 @@
@override
List<ClassMember> get localMembers => _localMembers ??= [
+ ...?_introductoryField?.localMembers,
if (_introductoryGetable != null)
new _GetterClassMember(this, _introductoryGetable!)
];
@override
List<ClassMember> get localSetters => _localSetters ??= [
+ ...?_introductoryField?.localSetters,
if (_introductorySetable != null && !isConflictingSetter)
new _SetterClassMember(this, _introductorySetable!)
];
@@ -466,27 +515,33 @@
Name get memberName => _memberName.name;
@override
- Member? get readTarget =>
- isAugmenting ? _origin!.readTarget : _introductoryGetable?.readTarget;
+ Member? get readTarget => isAugmenting
+ ? _origin!.readTarget
+ : (_introductoryField?.readTarget ?? _introductoryGetable?.readTarget);
@override
// Coverage-ignore(suite): Not run.
Reference? get readTargetReference =>
- isAugmenting ? _origin!.readTargetReference : _getterReference;
+ isAugmenting ? _origin!.readTargetReference : _references.getterReference;
@override
- Member? get writeTarget =>
- isAugmenting ? _origin!.writeTarget : _introductorySetable?.writeTarget;
+ Member? get writeTarget => isAugmenting
+ ? _origin!.writeTarget
+ : (_introductorySetable?.writeTarget ?? _introductoryField?.writeTarget);
@override
// Coverage-ignore(suite): Not run.
- Reference? get writeTargetReference =>
- isAugmenting ? _origin!.writeTargetReference : _setterReference;
+ Reference? get writeTargetReference => isAugmenting
+ ? _origin!.writeTargetReference
+ : _references.setterReference;
@override
int computeDefaultTypes(ComputeDefaultTypeContext context,
{required bool inErrorRecovery}) {
int count = 0;
+ if (_introductoryField != null) {
+ count += _introductoryField!.computeDefaultTypes(context);
+ }
if (_introductoryGetable != null) {
count += _introductoryGetable!.computeDefaultTypes(context);
}
@@ -517,12 +572,20 @@
TypeBuilder? get returnTypeForTesting =>
_introductoryGetable?.returnType ?? _introductorySetable?.returnType;
+ // Coverage-ignore(suite): Not run.
+ TypeBuilder? get typeForTesting => _introductoryField?.type;
+
@override
bool get isAugmenting => this != origin;
@override
bool get isProperty => true;
+ // TODO(johnniwinther): Remove this. Maybe replace with `hasField`,
+ // `hasGetter` and `hasSetter`?
+ @override
+ bool get isField => _introductoryField != null;
+
// TODO(johnniwinther): Remove this. Maybe replace with `hasGetter`?
@override
bool get isGetter => _introductoryGetable != null;
@@ -534,7 +597,7 @@
bool _typeEnsured = false;
Set<ClassMember>? _getterOverrideDependencies;
- void _registerGetterOverrideDependency(Set<ClassMember> overriddenMembers) {
+ void registerGetterOverrideDependency(Set<ClassMember> overriddenMembers) {
assert(
overriddenMembers.every((overriddenMember) =>
overriddenMember.declarationBuilder != classBuilder),
@@ -545,7 +608,7 @@
Set<ClassMember>? _setterOverrideDependencies;
- void _registerSetterOverrideDependency(Set<ClassMember> overriddenMembers) {
+ void registerSetterOverrideDependency(Set<ClassMember> overriddenMembers) {
assert(
overriddenMembers.every((overriddenMember) =>
overriddenMember.declarationBuilder != classBuilder),
@@ -554,13 +617,15 @@
_setterOverrideDependencies!.addAll(overriddenMembers);
}
- void _ensureTypes(ClassMembersBuilder membersBuilder) {
+ void ensureTypes(ClassMembersBuilder membersBuilder) {
if (_typeEnsured) return;
- _introductoryGetable?.ensureTypes(membersBuilder,
- declarationBuilder as SourceClassBuilder, _getterOverrideDependencies);
+ _introductoryField?.ensureTypes(membersBuilder, _getterOverrideDependencies,
+ _setterOverrideDependencies);
+ _introductoryGetable?.ensureTypes(
+ membersBuilder, _getterOverrideDependencies);
+ _introductorySetable?.ensureTypes(
+ membersBuilder, _setterOverrideDependencies);
_getterOverrideDependencies = null;
- _introductorySetable?.ensureTypes(membersBuilder,
- declarationBuilder as SourceClassBuilder, _setterOverrideDependencies);
_setterOverrideDependencies = null;
_typeEnsured = true;
}
@@ -602,6 +667,63 @@
}
return setterType;
}
+
+ @override
+ DartType get fieldType {
+ return _introductoryField!.fieldType;
+ }
+
+ @override
+ // Coverage-ignore(suite): Not run.
+ void set fieldType(DartType value) {
+ _introductoryField!.fieldType = value;
+ }
+
+ @override
+ Initializer buildErroneousInitializer(Expression effect, Expression value,
+ {required int fileOffset}) {
+ return _introductoryField!
+ .buildErroneousInitializer(effect, value, fileOffset: fileOffset);
+ }
+
+ @override
+ void buildImplicitDefaultValue() {
+ _introductoryField!.buildImplicitDefaultValue();
+ }
+
+ @override
+ Initializer buildImplicitInitializer() {
+ return _introductoryField!.buildImplicitInitializer();
+ }
+
+ @override
+ List<Initializer> buildInitializer(int fileOffset, Expression value,
+ {required bool isSynthetic}) {
+ return _introductoryField!
+ .buildInitializer(fileOffset, value, isSynthetic: isSynthetic);
+ }
+
+ @override
+ bool get hasInitializer => _introductoryField!.hasInitializer;
+
+ @override
+ bool get isExtensionTypeDeclaredInstanceField =>
+ _introductoryField!.isExtensionTypeDeclaredInstanceField;
+
+ @override
+ bool get isFinal => _introductoryField!.isFinal;
+
+ @override
+ bool get isLate => _introductoryField!.isLate;
+
+ @override
+ DartType inferType(ClassHierarchyBase hierarchy) {
+ return _introductoryField!.inferType(hierarchy);
+ }
+
+ // Coverage-ignore(suite): Not run.
+ shared.Expression? get initializerExpression =>
+ _introductoryField?.initializerExpression;
}
class _GetterClassMember implements ClassMember {
@@ -674,7 +796,7 @@
@override
void inferType(ClassMembersBuilder membersBuilder) {
- _builder._ensureTypes(membersBuilder);
+ _builder.ensureTypes(membersBuilder);
}
@override
@@ -741,7 +863,7 @@
@override
void registerOverrideDependency(Set<ClassMember> overriddenMembers) {
- _builder._registerGetterOverrideDependency(overriddenMembers);
+ _builder.registerGetterOverrideDependency(overriddenMembers);
}
@override
@@ -820,7 +942,7 @@
@override
void inferType(ClassMembersBuilder membersBuilder) {
- _builder._ensureTypes(membersBuilder);
+ _builder.ensureTypes(membersBuilder);
}
@override
@@ -886,9 +1008,332 @@
@override
void registerOverrideDependency(Set<ClassMember> overriddenMembers) {
- _builder._registerSetterOverrideDependency(overriddenMembers);
+ _builder.registerSetterOverrideDependency(overriddenMembers);
}
@override
String toString() => '$runtimeType($fullName,forSetter=${forSetter})';
}
+
+abstract class PropertyReferences {
+ Reference? get getterReference;
+ Reference? get setterReference;
+}
+
+class GetterReference extends PropertyReferences {
+ Reference? _getterReference;
+
+ GetterReference._(this._getterReference);
+
+ factory GetterReference(
+ String name, NameScheme nameScheme, IndexedContainer? indexedContainer,
+ {required bool isAugmentation}) {
+ Reference? procedureReference;
+ ProcedureKind kind = ProcedureKind.Getter;
+ if (indexedContainer != null && !isAugmentation) {
+ Name nameToLookup = nameScheme.getProcedureMemberName(kind, name).name;
+ procedureReference = indexedContainer.lookupGetterReference(nameToLookup);
+ }
+ return new GetterReference._(procedureReference);
+ }
+
+ void registerReference(SourceLoader loader, Builder builder) {
+ if (_getterReference != null) {
+ loader.buildersCreatedWithReferences[_getterReference!] = builder;
+ }
+ }
+
+ @override
+ Reference get getterReference => _getterReference ??= new Reference();
+
+ @override
+ // Coverage-ignore(suite): Not run.
+ Reference? get setterReference => null;
+}
+
+class SetterReference extends PropertyReferences {
+ Reference? _setterReference;
+
+ SetterReference._(this._setterReference);
+
+ factory SetterReference(
+ String name, NameScheme nameScheme, IndexedContainer? indexedContainer,
+ {required bool isAugmentation}) {
+ Reference? procedureReference;
+ ProcedureKind kind = ProcedureKind.Setter;
+ if (indexedContainer != null && !isAugmentation) {
+ Name nameToLookup = nameScheme.getProcedureMemberName(kind, name).name;
+ if ((nameScheme.isExtensionMember || nameScheme.isExtensionTypeMember) &&
+ nameScheme.isInstanceMember) {
+ // Extension (type) instance setters are encoded as methods.
+ procedureReference =
+ indexedContainer.lookupGetterReference(nameToLookup);
+ } else {
+ procedureReference =
+ indexedContainer.lookupSetterReference(nameToLookup);
+ }
+ }
+ return new SetterReference._(procedureReference);
+ }
+
+ void registerReference(SourceLoader loader, Builder builder) {
+ if (_setterReference != null) {
+ loader.buildersCreatedWithReferences[_setterReference!] = builder;
+ }
+ }
+
+ @override
+ // Coverage-ignore(suite): Not run.
+ Reference? get getterReference => null;
+
+ @override
+ Reference get setterReference => _setterReference ??= new Reference();
+}
+
+abstract class FieldReference extends PropertyReferences {
+ factory FieldReference(
+ String name, NameScheme nameScheme, IndexedContainer? indexedContainer,
+ {required bool fieldIsLateWithLowering, required bool isExternal}) {
+ Reference? fieldReference;
+ Reference? fieldGetterReference;
+ Reference? fieldSetterReference;
+ Reference? lateIsSetFieldReference;
+ Reference? lateIsSetGetterReference;
+ Reference? lateIsSetSetterReference;
+ Reference? lateGetterReference;
+ Reference? lateSetterReference;
+ if (indexedContainer != null) {
+ if ((nameScheme.isExtensionMember || nameScheme.isExtensionTypeMember) &&
+ nameScheme.isInstanceMember &&
+ isExternal) {
+ /// An external extension (type) instance field is special. It is
+ /// treated as an external getter/setter pair and is therefore
+ /// encoded as a pair of top level methods using the extension
+ /// instance member naming convention.
+ fieldGetterReference = indexedContainer.lookupGetterReference(
+ nameScheme.getProcedureMemberName(ProcedureKind.Getter, name).name);
+ fieldSetterReference = indexedContainer.lookupGetterReference(
+ nameScheme.getProcedureMemberName(ProcedureKind.Setter, name).name);
+ } else if (nameScheme.isExtensionTypeMember &&
+ nameScheme.isInstanceMember) {
+ Name nameToLookup = nameScheme
+ .getFieldMemberName(FieldNameType.RepresentationField, name,
+ isSynthesized: true)
+ .name;
+ fieldGetterReference =
+ indexedContainer.lookupGetterReference(nameToLookup);
+ } else {
+ Name nameToLookup = nameScheme
+ .getFieldMemberName(FieldNameType.Field, name,
+ isSynthesized: fieldIsLateWithLowering)
+ .name;
+ fieldReference = indexedContainer.lookupFieldReference(nameToLookup);
+ fieldGetterReference =
+ indexedContainer.lookupGetterReference(nameToLookup);
+ fieldSetterReference =
+ indexedContainer.lookupSetterReference(nameToLookup);
+ }
+
+ if (fieldIsLateWithLowering) {
+ Name lateIsSetName = nameScheme
+ .getFieldMemberName(FieldNameType.IsSetField, name,
+ isSynthesized: fieldIsLateWithLowering)
+ .name;
+ lateIsSetFieldReference =
+ indexedContainer.lookupFieldReference(lateIsSetName);
+ lateIsSetGetterReference =
+ indexedContainer.lookupGetterReference(lateIsSetName);
+ lateIsSetSetterReference =
+ indexedContainer.lookupSetterReference(lateIsSetName);
+ lateGetterReference = indexedContainer.lookupGetterReference(nameScheme
+ .getFieldMemberName(FieldNameType.Getter, name,
+ isSynthesized: fieldIsLateWithLowering)
+ .name);
+ lateSetterReference = indexedContainer.lookupSetterReference(nameScheme
+ .getFieldMemberName(FieldNameType.Setter, name,
+ isSynthesized: fieldIsLateWithLowering)
+ .name);
+ }
+ }
+ if (fieldIsLateWithLowering) {
+ return new _LateFieldLoweringReference._(
+ fieldReference: fieldReference,
+ fieldGetterReference: fieldGetterReference,
+ fieldSetterReference: fieldSetterReference,
+ lateIsSetFieldReference: lateIsSetFieldReference,
+ lateIsSetGetterReference: lateIsSetGetterReference,
+ lateIsSetSetterReference: lateIsSetSetterReference,
+ lateGetterReference: lateGetterReference,
+ lateSetterReference: lateSetterReference);
+ } else {
+ return new _RegularFieldReference._(
+ fieldReference: fieldReference,
+ fieldGetterReference: fieldGetterReference,
+ fieldSetterReference: fieldSetterReference,
+ lateIsSetFieldReference: lateIsSetFieldReference,
+ lateIsSetGetterReference: lateIsSetGetterReference,
+ lateIsSetSetterReference: lateIsSetSetterReference,
+ lateGetterReference: lateGetterReference,
+ lateSetterReference: lateSetterReference);
+ }
+ }
+
+ void registerReference(SourceLoader loader, Builder builder);
+
+ Reference get fieldReference;
+ Reference get fieldGetterReference;
+ Reference get fieldSetterReference;
+ Reference get lateIsSetFieldReference;
+ Reference get lateIsSetGetterReference;
+ Reference get lateIsSetSetterReference;
+ Reference get lateGetterReference;
+ Reference get lateSetterReference;
+}
+
+class _RegularFieldReference implements FieldReference {
+ Reference? _fieldReference;
+ Reference? _fieldGetterReference;
+ Reference? _fieldSetterReference;
+ Reference? _lateIsSetFieldReference;
+ Reference? _lateIsSetGetterReference;
+ Reference? _lateIsSetSetterReference;
+ Reference? _lateGetterReference;
+ Reference? _lateSetterReference;
+
+ _RegularFieldReference._(
+ {required Reference? fieldReference,
+ required Reference? fieldGetterReference,
+ required Reference? fieldSetterReference,
+ required Reference? lateIsSetFieldReference,
+ required Reference? lateIsSetGetterReference,
+ required Reference? lateIsSetSetterReference,
+ required Reference? lateGetterReference,
+ required Reference? lateSetterReference})
+ : _fieldReference = fieldReference,
+ _fieldGetterReference = fieldGetterReference,
+ _fieldSetterReference = fieldSetterReference,
+ _lateIsSetFieldReference = lateIsSetFieldReference,
+ _lateIsSetGetterReference = lateIsSetGetterReference,
+ _lateIsSetSetterReference = lateIsSetSetterReference,
+ _lateGetterReference = lateGetterReference,
+ _lateSetterReference = lateSetterReference;
+
+ @override
+ void registerReference(SourceLoader loader, Builder builder) {
+ if (_fieldGetterReference != null) {
+ loader.buildersCreatedWithReferences[_fieldGetterReference!] = builder;
+ }
+ if (_fieldSetterReference != null) {
+ loader.buildersCreatedWithReferences[_fieldSetterReference!] = builder;
+ }
+ }
+
+ @override
+ Reference get fieldReference => _fieldReference ??= new Reference();
+
+ @override
+ Reference get fieldGetterReference =>
+ _fieldGetterReference ??= new Reference();
+
+ @override
+ Reference get fieldSetterReference =>
+ _fieldSetterReference ??= new Reference();
+
+ @override
+ Reference get lateIsSetFieldReference =>
+ _lateIsSetFieldReference ??= new Reference();
+
+ @override
+ Reference get lateIsSetGetterReference =>
+ _lateIsSetGetterReference ??= new Reference();
+
+ @override
+ Reference get lateIsSetSetterReference =>
+ _lateIsSetSetterReference ??= new Reference();
+
+ @override
+ Reference get lateGetterReference => _lateGetterReference ??= new Reference();
+
+ @override
+ Reference get lateSetterReference => _lateSetterReference ??= new Reference();
+
+ @override
+ Reference? get getterReference => fieldGetterReference;
+
+ @override
+ Reference? get setterReference => fieldSetterReference;
+}
+
+class _LateFieldLoweringReference implements FieldReference {
+ Reference? _fieldReference;
+ Reference? _fieldGetterReference;
+ Reference? _fieldSetterReference;
+ Reference? _lateIsSetFieldReference;
+ Reference? _lateIsSetGetterReference;
+ Reference? _lateIsSetSetterReference;
+ Reference? _lateGetterReference;
+ Reference? _lateSetterReference;
+
+ _LateFieldLoweringReference._(
+ {required Reference? fieldReference,
+ required Reference? fieldGetterReference,
+ required Reference? fieldSetterReference,
+ required Reference? lateIsSetFieldReference,
+ required Reference? lateIsSetGetterReference,
+ required Reference? lateIsSetSetterReference,
+ required Reference? lateGetterReference,
+ required Reference? lateSetterReference})
+ : _fieldReference = fieldReference,
+ _fieldGetterReference = fieldGetterReference,
+ _fieldSetterReference = fieldSetterReference,
+ _lateIsSetFieldReference = lateIsSetFieldReference,
+ _lateIsSetGetterReference = lateIsSetGetterReference,
+ _lateIsSetSetterReference = lateIsSetSetterReference,
+ _lateGetterReference = lateGetterReference,
+ _lateSetterReference = lateSetterReference;
+
+ @override
+ void registerReference(SourceLoader loader, Builder builder) {
+ if (_fieldGetterReference != null) {
+ loader.buildersCreatedWithReferences[_fieldGetterReference!] = builder;
+ }
+ if (_fieldSetterReference != null) {
+ loader.buildersCreatedWithReferences[_fieldSetterReference!] = builder;
+ }
+ }
+
+ @override
+ Reference get fieldReference => _fieldReference ??= new Reference();
+
+ @override
+ Reference get fieldGetterReference =>
+ _fieldGetterReference ??= new Reference();
+
+ @override
+ Reference get fieldSetterReference =>
+ _fieldSetterReference ??= new Reference();
+
+ @override
+ Reference get lateIsSetFieldReference =>
+ _lateIsSetFieldReference ??= new Reference();
+
+ @override
+ Reference get lateIsSetGetterReference =>
+ _lateIsSetGetterReference ??= new Reference();
+
+ @override
+ Reference get lateIsSetSetterReference =>
+ _lateIsSetSetterReference ??= new Reference();
+
+ @override
+ Reference get lateGetterReference => _lateGetterReference ??= new Reference();
+
+ @override
+ Reference get lateSetterReference => _lateSetterReference ??= new Reference();
+
+ @override
+ Reference? get getterReference => lateGetterReference;
+
+ @override
+ Reference? get setterReference => lateSetterReference;
+}
diff --git a/pkg/front_end/lib/src/source/synthetic_method_builder.dart b/pkg/front_end/lib/src/source/synthetic_method_builder.dart
index 3e9689c..093b352 100644
--- a/pkg/front_end/lib/src/source/synthetic_method_builder.dart
+++ b/pkg/front_end/lib/src/source/synthetic_method_builder.dart
@@ -133,6 +133,14 @@
bool get isProperty => false;
@override
+ // Coverage-ignore(suite): Not run.
+ bool get isFinal => false;
+
+ @override
+ // Coverage-ignore(suite): Not run.
+ bool get isSynthesized => true;
+
+ @override
late final List<ClassMember> localMembers = [
new _SyntheticMethodClassMember(this)
];
diff --git a/pkg/front_end/lib/src/source/type_parameter_scope_builder.dart b/pkg/front_end/lib/src/source/type_parameter_scope_builder.dart
index 6bcba25c..bc8b3d9 100644
--- a/pkg/front_end/lib/src/source/type_parameter_scope_builder.dart
+++ b/pkg/front_end/lib/src/source/type_parameter_scope_builder.dart
@@ -32,7 +32,6 @@
import 'source_extension_builder.dart';
import 'source_extension_type_declaration_builder.dart';
import 'source_factory_builder.dart';
-import 'source_field_builder.dart';
import 'source_library_builder.dart';
import 'source_loader.dart';
import 'source_method_builder.dart';
@@ -1481,9 +1480,6 @@
final bool isInstanceMember = containerType != ContainerType.Library &&
!fragment.modifiers.isStatic;
- final bool isExtensionMember = containerType == ContainerType.Extension;
- final bool isExtensionTypeMember =
- containerType == ContainerType.ExtensionType;
NameScheme nameScheme = new NameScheme(
isInstanceMember: isInstanceMember,
@@ -1494,107 +1490,26 @@
: enclosingLibraryBuilder.libraryName);
indexedContainer ??= indexedLibrary;
- Reference? fieldReference;
- Reference? fieldGetterReference;
- Reference? fieldSetterReference;
- Reference? lateIsSetFieldReference;
- Reference? lateIsSetGetterReference;
- Reference? lateIsSetSetterReference;
- Reference? lateGetterReference;
- Reference? lateSetterReference;
- if (indexedContainer != null) {
- if ((isExtensionMember || isExtensionTypeMember) &&
- isInstanceMember &&
- fragment.modifiers.isExternal) {
- /// An external extension (type) instance field is special. It is
- /// treated as an external getter/setter pair and is therefore
- /// encoded as a pair of top level methods using the extension
- /// instance member naming convention.
- fieldGetterReference = indexedContainer!.lookupGetterReference(
- nameScheme
- .getProcedureMemberName(ProcedureKind.Getter, name)
- .name);
- fieldSetterReference = indexedContainer!.lookupGetterReference(
- nameScheme
- .getProcedureMemberName(ProcedureKind.Setter, name)
- .name);
- } else if (isExtensionTypeMember && isInstanceMember) {
- Name nameToLookup = nameScheme
- .getFieldMemberName(FieldNameType.RepresentationField, name,
- isSynthesized: true)
- .name;
- fieldGetterReference =
- indexedContainer!.lookupGetterReference(nameToLookup);
- } else {
- Name nameToLookup = nameScheme
- .getFieldMemberName(FieldNameType.Field, name,
- isSynthesized: fieldIsLateWithLowering)
- .name;
- fieldReference =
- indexedContainer!.lookupFieldReference(nameToLookup);
- fieldGetterReference =
- indexedContainer!.lookupGetterReference(nameToLookup);
- fieldSetterReference =
- indexedContainer!.lookupSetterReference(nameToLookup);
- }
+ FieldReference references = new FieldReference(
+ name, nameScheme, indexedContainer,
+ fieldIsLateWithLowering: fieldIsLateWithLowering,
+ isExternal: fragment.modifiers.isExternal);
- if (fieldIsLateWithLowering) {
- Name lateIsSetName = nameScheme
- .getFieldMemberName(FieldNameType.IsSetField, name,
- isSynthesized: fieldIsLateWithLowering)
- .name;
- lateIsSetFieldReference =
- indexedContainer!.lookupFieldReference(lateIsSetName);
- lateIsSetGetterReference =
- indexedContainer!.lookupGetterReference(lateIsSetName);
- lateIsSetSetterReference =
- indexedContainer!.lookupSetterReference(lateIsSetName);
- lateGetterReference = indexedContainer!.lookupGetterReference(
- nameScheme
- .getFieldMemberName(FieldNameType.Getter, name,
- isSynthesized: fieldIsLateWithLowering)
- .name);
- lateSetterReference = indexedContainer!.lookupSetterReference(
- nameScheme
- .getFieldMemberName(FieldNameType.Setter, name,
- isSynthesized: fieldIsLateWithLowering)
- .name);
- }
- }
- SourceFieldBuilder fieldBuilder = new SourceFieldBuilder(
- metadata: fragment.metadata,
- type: fragment.type,
- name: name,
- modifiers: fragment.modifiers,
- isTopLevel: fragment.isTopLevel,
- isPrimaryConstructorField: fragment.isPrimaryConstructorField,
- libraryBuilder: enclosingLibraryBuilder,
- declarationBuilder: declarationBuilder,
- fileUri: fragment.fileUri,
- nameOffset: fragment.nameOffset,
- endOffset: fragment.endOffset,
- nameScheme: nameScheme,
- fieldReference: fieldReference,
- fieldGetterReference: fieldGetterReference,
- fieldSetterReference: fieldSetterReference,
- lateIsSetFieldReference: lateIsSetFieldReference,
- lateIsSetGetterReference: lateIsSetGetterReference,
- lateIsSetSetterReference: lateIsSetSetterReference,
- lateGetterReference: lateGetterReference,
- lateSetterReference: lateSetterReference,
- initializerToken: fragment.initializerToken,
- constInitializerToken: fragment.constInitializerToken);
- fragment.builder = fieldBuilder;
- builders.add(new _AddBuilder(fragment.name, fieldBuilder,
+ SourcePropertyBuilder propertyBuilder =
+ new SourcePropertyBuilder.forField(
+ fileUri: fragment.fileUri,
+ fileOffset: fragment.nameOffset,
+ name: name,
+ libraryBuilder: enclosingLibraryBuilder,
+ declarationBuilder: declarationBuilder,
+ isStatic: fragment.modifiers.isStatic,
+ nameScheme: nameScheme,
+ fragment: fragment,
+ references: references);
+ fragment.builder = propertyBuilder;
+ builders.add(new _AddBuilder(fragment.name, propertyBuilder,
fragment.fileUri, fragment.nameOffset));
- if (fieldGetterReference != null) {
- loader.buildersCreatedWithReferences[fieldGetterReference] =
- fieldBuilder;
- }
- if (fieldSetterReference != null) {
- loader.buildersCreatedWithReferences[fieldSetterReference] =
- fieldBuilder;
- }
+ references.registerReference(loader, propertyBuilder);
case GetterFragment():
String name = fragment.name;
final bool isInstanceMember = containerType != ContainerType.Library &&
@@ -1604,7 +1519,7 @@
List<NominalParameterBuilder>? typeParameters,
List<FormalParameterBuilder>? formals
) = _createTypeParametersAndFormals(
- declarationBuilder, null, null, unboundNominalParameters,
+ declarationBuilder, unboundNominalParameters,
isInstanceMember: isInstanceMember,
fileUri: fragment.fileUri,
nameOffset: fragment.nameOffset);
@@ -1621,19 +1536,15 @@
? new LibraryName(indexedLibrary.library.reference)
: enclosingLibraryBuilder.libraryName);
- Reference? procedureReference;
indexedContainer ??= indexedLibrary;
bool isAugmentation = enclosingLibraryBuilder.isAugmenting &&
fragment.modifiers.isAugment;
- ProcedureKind kind = ProcedureKind.Getter;
- if (indexedContainer != null && !isAugmentation) {
- Name nameToLookup =
- nameScheme.getProcedureMemberName(kind, name).name;
- procedureReference =
- indexedContainer!.lookupGetterReference(nameToLookup);
- }
+ GetterReference references = new GetterReference(
+ name, nameScheme, indexedContainer,
+ isAugmentation: isAugmentation);
+
SourcePropertyBuilder propertyBuilder =
new SourcePropertyBuilder.forGetter(
fileUri: fragment.fileUri,
@@ -1644,14 +1555,11 @@
isStatic: fragment.modifiers.isStatic,
fragment: fragment,
nameScheme: nameScheme,
- getterReference: procedureReference);
+ references: references);
fragment.setBuilder(propertyBuilder, typeParameters, formals);
builders.add(new _AddBuilder(fragment.name, propertyBuilder,
fragment.fileUri, fragment.nameOffset));
- if (procedureReference != null) {
- loader.buildersCreatedWithReferences[procedureReference] =
- propertyBuilder;
- }
+ references.registerReference(loader, propertyBuilder);
case SetterFragment():
String name = fragment.name;
final bool isInstanceMember = containerType != ContainerType.Library &&
@@ -1661,7 +1569,7 @@
List<NominalParameterBuilder>? typeParameters,
List<FormalParameterBuilder>? formals
) = _createTypeParametersAndFormals(
- declarationBuilder, null, null, unboundNominalParameters,
+ declarationBuilder, unboundNominalParameters,
isInstanceMember: isInstanceMember,
fileUri: fragment.fileUri,
nameOffset: fragment.nameOffset);
@@ -1670,10 +1578,6 @@
problemReporting, typeParameters,
ownerName: name, allowNameConflict: true);
- final bool isExtensionMember = containerType == ContainerType.Extension;
- final bool isExtensionTypeMember =
- containerType == ContainerType.ExtensionType;
-
NameScheme nameScheme = new NameScheme(
containerName: containerName,
containerType: containerType,
@@ -1682,26 +1586,15 @@
? new LibraryName(indexedLibrary.library.reference)
: enclosingLibraryBuilder.libraryName);
- Reference? procedureReference;
indexedContainer ??= indexedLibrary;
bool isAugmentation = enclosingLibraryBuilder.isAugmenting &&
fragment.modifiers.isAugment;
- ProcedureKind kind = ProcedureKind.Setter;
- if (indexedContainer != null && !isAugmentation) {
- Name nameToLookup =
- nameScheme.getProcedureMemberName(kind, name).name;
- if ((isExtensionMember || isExtensionTypeMember) &&
- isInstanceMember) {
- // Extension (type) instance setters are encoded as methods.
- procedureReference =
- indexedContainer!.lookupGetterReference(nameToLookup);
- } else {
- procedureReference =
- indexedContainer!.lookupSetterReference(nameToLookup);
- }
- }
+ SetterReference references = new SetterReference(
+ name, nameScheme, indexedContainer,
+ isAugmentation: isAugmentation);
+
SourcePropertyBuilder propertyBuilder =
new SourcePropertyBuilder.forSetter(
fileUri: fragment.fileUri,
@@ -1712,14 +1605,11 @@
isStatic: fragment.modifiers.isStatic,
fragment: fragment,
nameScheme: nameScheme,
- setterReference: procedureReference);
+ references: references);
fragment.setBuilder(propertyBuilder, typeParameters, formals);
builders.add(new _AddBuilder(fragment.name, propertyBuilder,
fragment.fileUri, fragment.nameOffset));
- if (procedureReference != null) {
- loader.buildersCreatedWithReferences[procedureReference] =
- propertyBuilder;
- }
+ references.registerReference(loader, propertyBuilder);
if (conflictingSetter) {
propertyBuilder.isConflictingSetter = true;
}
@@ -1732,7 +1622,7 @@
List<NominalParameterBuilder>? typeParameters,
List<FormalParameterBuilder>? formals
) = _createTypeParametersAndFormals(
- declarationBuilder, null, null, unboundNominalParameters,
+ declarationBuilder, unboundNominalParameters,
isInstanceMember: isInstanceMember,
fileUri: fragment.fileUri,
nameOffset: fragment.nameOffset);
@@ -2605,14 +2495,13 @@
(
List<NominalParameterBuilder>? typeParameters,
List<FormalParameterBuilder>? formals
-) _createTypeParametersAndFormals(
- DeclarationBuilder? declarationBuilder,
- List<NominalParameterBuilder>? typeParameters,
- List<FormalParameterBuilder>? formals,
+) _createTypeParametersAndFormals(DeclarationBuilder? declarationBuilder,
List<NominalParameterBuilder> _unboundNominalVariables,
{required bool isInstanceMember,
required Uri fileUri,
required int nameOffset}) {
+ List<NominalParameterBuilder>? typeParameters;
+ List<FormalParameterBuilder>? formals;
if (isInstanceMember) {
switch (declarationBuilder) {
case ExtensionBuilder():
@@ -2624,13 +2513,7 @@
InstanceTypeParameterAccessState.Allowed);
if (nominalVariableCopy != null) {
- if (typeParameters != null) {
- // Coverage-ignore-block(suite): Not run.
- typeParameters = nominalVariableCopy.newParameterBuilders
- ..addAll(typeParameters);
- } else {
- typeParameters = nominalVariableCopy.newParameterBuilders;
- }
+ typeParameters = nominalVariableCopy.newParameterBuilders;
}
TypeBuilder thisType = declarationBuilder.onType;
@@ -2647,10 +2530,6 @@
isExtensionThis: true,
hasImmediatelyDeclaredInitializer: false)
];
- if (formals != null) {
- // Coverage-ignore-block(suite): Not run.
- synthesizedFormals.addAll(formals);
- }
formals = synthesizedFormals;
case ExtensionTypeDeclarationBuilder():
NominalParameterCopy? nominalVariableCopy =
@@ -2661,13 +2540,7 @@
InstanceTypeParameterAccessState.Allowed);
if (nominalVariableCopy != null) {
- if (typeParameters != null) {
- // Coverage-ignore-block(suite): Not run.
- typeParameters = nominalVariableCopy.newParameterBuilders
- ..addAll(typeParameters);
- } else {
- typeParameters = nominalVariableCopy.newParameterBuilders;
- }
+ typeParameters = nominalVariableCopy.newParameterBuilders;
}
TypeBuilder thisType =
@@ -2699,10 +2572,6 @@
isExtensionThis: true,
hasImmediatelyDeclaredInitializer: false)
];
- if (formals != null) {
- // Coverage-ignore-block(suite): Not run.
- synthesizedFormals.addAll(formals);
- }
formals = synthesizedFormals;
case ClassFragment():
case MixinFragment():
diff --git a/pkg/front_end/lib/src/type_inference/inference_visitor_base.dart b/pkg/front_end/lib/src/type_inference/inference_visitor_base.dart
index 2927ddd..6c87506 100644
--- a/pkg/front_end/lib/src/type_inference/inference_visitor_base.dart
+++ b/pkg/front_end/lib/src/type_inference/inference_visitor_base.dart
@@ -38,7 +38,6 @@
import '../kernel/kernel_helper.dart';
import '../kernel/type_algorithms.dart' show hasAnyTypeParameters;
import '../source/source_constructor_builder.dart';
-import '../source/source_field_builder.dart';
import '../source/source_library_builder.dart'
show FieldNonPromotabilityInfo, SourceLibraryBuilder;
import '../source/source_member_builder.dart';
@@ -4416,16 +4415,16 @@
// libraries, so just don't generate a context message.
return const [];
}
- FieldNameNonPromotabilityInfo<Class, SourceFieldBuilder,
+ FieldNameNonPromotabilityInfo<Class, SourceMemberBuilder,
SourceMemberBuilder>? fieldNameInfo =
fieldNonPromotabilityInfo.fieldNameInfo[reason.propertyName];
List<LocatedMessage> messages = [];
if (fieldNameInfo != null) {
- for (SourceFieldBuilder field in fieldNameInfo.conflictingFields) {
+ for (SourceMemberBuilder field in fieldNameInfo.conflictingFields) {
messages.add(templateFieldNotPromotedBecauseConflictingField
.withArguments(
reason.propertyName,
- field.readTarget.enclosingClass!.name,
+ field.readTarget!.enclosingClass!.name,
NonPromotionDocumentationLink.conflictingNonPromotableField.url)
.withLocation(field.fileUri, field.fileOffset, noLength));
}
@@ -4435,7 +4434,7 @@
reason.propertyName,
getter.readTarget!.enclosingClass!.name,
NonPromotionDocumentationLink.conflictingGetter.url)
- .withLocation(getter.fileUri!, getter.fileOffset, noLength));
+ .withLocation(getter.fileUri, getter.fileOffset, noLength));
}
for (Class nsmClass in fieldNameInfo.conflictingNsmClasses) {
messages.add(templateFieldNotPromotedBecauseConflictingNsmForwarder
diff --git a/pkg/front_end/test/coverage_suite_expected.dart b/pkg/front_end/test/coverage_suite_expected.dart
index aea19d9..6f7e123 100644
--- a/pkg/front_end/test/coverage_suite_expected.dart
+++ b/pkg/front_end/test/coverage_suite_expected.dart
@@ -208,9 +208,9 @@
hitCount: 260,
missCount: 0,
),
- // 99.38931297709924%.
+ // 99.38837920489296%.
"package:front_end/src/base/scope.dart": (
- hitCount: 651,
+ hitCount: 650,
missCount: 4,
),
// 100.0%.
@@ -245,7 +245,7 @@
),
// 100.0%.
"package:front_end/src/builder/builder_mixins.dart": (
- hitCount: 44,
+ hitCount: 45,
missCount: 0,
),
// 100.0%.
@@ -290,7 +290,7 @@
),
// 100.0%.
"package:front_end/src/builder/formal_parameter_builder.dart": (
- hitCount: 169,
+ hitCount: 170,
missCount: 0,
),
// 100.0%.
@@ -325,7 +325,7 @@
),
// 100.0%.
"package:front_end/src/builder/member_builder.dart": (
- hitCount: 97,
+ hitCount: 89,
missCount: 0,
),
// 100.0%.
@@ -505,12 +505,27 @@
),
// 100.0%.
"package:front_end/src/fragment/field.dart": (
- hitCount: 22,
+ hitCount: 300,
+ missCount: 0,
+ ),
+ // 100.0%.
+ "package:front_end/src/fragment/field/body_builder_context.dart": (
+ hitCount: 30,
+ missCount: 0,
+ ),
+ // 100.0%.
+ "package:front_end/src/fragment/field/class_member.dart": (
+ hitCount: 157,
+ missCount: 0,
+ ),
+ // 100.0%.
+ "package:front_end/src/fragment/field/encoding.dart": (
+ hitCount: 995,
missCount: 0,
),
// 100.0%.
"package:front_end/src/fragment/getter.dart": (
- hitCount: 533,
+ hitCount: 541,
missCount: 0,
),
// 100.0%.
@@ -535,7 +550,7 @@
),
// 100.0%.
"package:front_end/src/fragment/setter.dart": (
- hitCount: 553,
+ hitCount: 561,
missCount: 0,
),
// 100.0%.
@@ -560,12 +575,12 @@
),
// 100.0%.
"package:front_end/src/kernel/body_builder.dart": (
- hitCount: 7180,
+ hitCount: 7182,
missCount: 0,
),
// 100.0%.
"package:front_end/src/kernel/body_builder_context.dart": (
- hitCount: 343,
+ hitCount: 324,
missCount: 0,
),
// 100.0%.
@@ -620,7 +635,7 @@
),
// 100.0%.
"package:front_end/src/kernel/expression_generator.dart": (
- hitCount: 2519,
+ hitCount: 2522,
missCount: 0,
),
// 100.0%.
@@ -640,7 +655,7 @@
),
// 100.0%.
"package:front_end/src/kernel/hierarchy/class_member.dart": (
- hitCount: 386,
+ hitCount: 389,
missCount: 0,
),
// 100.0%.
@@ -680,7 +695,7 @@
),
// 100.0%.
"package:front_end/src/kernel/implicit_field_type.dart": (
- hitCount: 93,
+ hitCount: 97,
missCount: 0,
),
// 100.0%.
@@ -710,7 +725,7 @@
),
// 100.0%.
"package:front_end/src/kernel/kernel_target.dart": (
- hitCount: 1078,
+ hitCount: 1076,
missCount: 0,
),
// 100.0%.
@@ -850,7 +865,7 @@
),
// 100.0%.
"package:front_end/src/source/diet_listener.dart": (
- hitCount: 659,
+ hitCount: 660,
missCount: 0,
),
// 100.0%.
@@ -865,7 +880,7 @@
),
// 100.0%.
"package:front_end/src/source/offset_map.dart": (
- hitCount: 151,
+ hitCount: 150,
missCount: 0,
),
// 100.0%.
@@ -890,7 +905,7 @@
),
// 100.0%.
"package:front_end/src/source/source_class_builder.dart": (
- hitCount: 1282,
+ hitCount: 1276,
missCount: 0,
),
// 100.0%.
@@ -916,7 +931,7 @@
// 100.0%.
"package:front_end/src/source/source_extension_type_declaration_builder.dart":
(
- hitCount: 508,
+ hitCount: 504,
missCount: 0,
),
// 100.0%.
@@ -926,7 +941,7 @@
),
// 100.0%.
"package:front_end/src/source/source_field_builder.dart": (
- hitCount: 1269,
+ hitCount: 268,
missCount: 0,
),
// 100.0%.
@@ -936,7 +951,7 @@
),
// 100.0%.
"package:front_end/src/source/source_library_builder.dart": (
- hitCount: 1265,
+ hitCount: 1254,
missCount: 0,
),
// 100.0%.
@@ -956,7 +971,7 @@
),
// 100.0%.
"package:front_end/src/source/source_property_builder.dart": (
- hitCount: 540,
+ hitCount: 769,
missCount: 0,
),
// 100.0%.
@@ -976,7 +991,7 @@
),
// 100.0%.
"package:front_end/src/source/type_parameter_scope_builder.dart": (
- hitCount: 1533,
+ hitCount: 1489,
missCount: 0,
),
// 100.0%.
diff --git a/pkg/front_end/test/macros/application/macro_application_test.dart b/pkg/front_end/test/macros/application/macro_application_test.dart
index 4c297b9..16dd38a 100644
--- a/pkg/front_end/test/macros/application/macro_application_test.dart
+++ b/pkg/front_end/test/macros/application/macro_application_test.dart
@@ -11,6 +11,7 @@
import 'package:front_end/src/api_prototype/experimental_flags.dart';
import 'package:front_end/src/builder/field_builder.dart';
import 'package:front_end/src/builder/member_builder.dart';
+import 'package:front_end/src/builder/property_builder.dart';
import 'package:front_end/src/kernel/macro/macro.dart';
import 'package:front_end/src/kernel/macro/offset_checker.dart';
import 'package:front_end/src/macros/macro_serializer.dart';
@@ -125,6 +126,9 @@
if (memberBuilder is FieldBuilder) {
// Only show annotations for the field or getter.
return memberBuilder.readTarget == member;
+ } else if (memberBuilder is PropertyBuilder && memberBuilder.isField) {
+ // Only show annotations for the field or getter.
+ return memberBuilder.readTarget == member;
} else if (member is Procedure && member.isSetter) {
return memberBuilder.writeTarget == member;
} else if (member is Procedure && member.isGetter) {
diff --git a/pkg/front_end/test/testing/suite.dart b/pkg/front_end/test/testing/suite.dart
index 861e58c..891f3f0 100644
--- a/pkg/front_end/test/testing/suite.dart
+++ b/pkg/front_end/test/testing/suite.dart
@@ -1128,7 +1128,8 @@
a.libraries[i], b.libraries[i],
strategy: const Strategy());
if (!result.isEquivalent) {
- print(result.toString());
+ print('Original component and new component are not equivalent:\n'
+ '$result');
return false;
}
}