blob: a3ab2b6193216c67baddbd27208a1cfa0abb2363 [file] [log] [blame]
// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'package:_fe_analyzer_shared/src/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';
import '../base/name_space.dart';
import '../base/uri_offset.dart';
import '../builder/builder.dart';
import '../builder/declaration_builders.dart';
import '../builder/metadata_builder.dart';
import '../builder/property_builder.dart';
import '../fragment/field/declaration.dart';
import '../fragment/getter/declaration.dart';
import '../fragment/setter/declaration.dart';
import '../kernel/hierarchy/class_member.dart';
import '../kernel/hierarchy/members_builder.dart';
import '../kernel/kernel_helper.dart';
import '../kernel/member_covariance.dart';
import '../kernel/type_algorithms.dart';
import 'name_scheme.dart';
import 'source_class_builder.dart';
import 'source_library_builder.dart';
import 'source_loader.dart';
import 'source_member_builder.dart';
class SourcePropertyBuilder extends SourceMemberBuilderImpl
implements PropertyBuilder {
@override
final Uri fileUri;
@override
final int fileOffset;
@override
final String name;
@override
final SourceLibraryBuilder libraryBuilder;
@override
final DeclarationBuilder? declarationBuilder;
@override
final bool isStatic;
final NameScheme _nameScheme;
/// The declarations that introduces this property. Subsequent property of the
/// same name must be augmentations.
FieldDeclaration? _introductoryField;
GetterDeclaration? _introductoryGetable;
List<GetterDeclaration>? _getterAugmentations;
List<GetterDeclaration>? _augmentedGetables;
GetterDeclaration? _lastGetable;
SetterDeclaration? _introductorySetable;
List<SetterDeclaration>? _setterAugmentations;
List<SetterDeclaration>? _augmentedSetables;
SetterDeclaration? _lastSetable;
final PropertyReferences _references;
final MemberName _memberName;
SourcePropertyBuilder(
{required this.fileUri,
required this.fileOffset,
required this.name,
required this.libraryBuilder,
required this.declarationBuilder,
required NameScheme nameScheme,
required FieldDeclaration? fieldDeclaration,
required GetterDeclaration? getterDeclaration,
required List<GetterDeclaration> getterAugmentations,
required SetterDeclaration? setterDeclaration,
required List<SetterDeclaration> setterAugmentations,
required this.isStatic,
required PropertyReferences references})
: _nameScheme = nameScheme,
_introductoryField = fieldDeclaration,
_introductoryGetable = getterDeclaration,
_getterAugmentations = getterAugmentations,
_introductorySetable = setterDeclaration,
_setterAugmentations = setterAugmentations,
_references = references,
_memberName = nameScheme.getDeclaredName(name) {
if (getterAugmentations.isEmpty) {
_augmentedGetables = getterAugmentations;
_lastGetable = getterDeclaration;
} else if (getterDeclaration != null) {
_augmentedGetables = [getterDeclaration, ...getterAugmentations];
_lastGetable = _augmentedGetables!.removeLast();
}
if (setterAugmentations.isEmpty) {
_augmentedSetables = setterAugmentations;
_lastSetable = setterDeclaration;
} else if (setterDeclaration != null) {
_augmentedSetables = [setterDeclaration, ...setterAugmentations];
_lastSetable = _augmentedSetables!.removeLast();
}
}
@override
Builder get parent => declarationBuilder ?? libraryBuilder;
@override
bool get hasConstField => _introductoryField?.isConst ?? false;
@override
bool get isSynthesized => false;
@override
bool get isEnumElement => _introductoryField?.isEnumElement ?? false;
@override
NamedBuilder? get getable => hasGetter ? this : null;
@override
NamedBuilder? get setable => hasSetter ? this : null;
@override
int buildBodyNodes(BuildNodesCallback f) => 0;
@override
void buildOutlineNodes(BuildNodesCallback f) {
_introductoryField?.buildFieldOutlineNode(
libraryBuilder, _nameScheme, f, _references,
classTypeParameters: classBuilder?.cls.typeParameters);
List<GetterDeclaration>? augmentedGetables = _augmentedGetables;
if (augmentedGetables != null) {
for (GetterDeclaration augmented in augmentedGetables) {
augmented.buildGetterOutlineNode(
libraryBuilder: libraryBuilder,
nameScheme: _nameScheme,
f: noAddBuildNodesCallback,
// Augmented getters don't reuse references.
references: null,
classTypeParameters: classBuilder?.cls.typeParameters);
}
}
_lastGetable?.buildGetterOutlineNode(
libraryBuilder: libraryBuilder,
nameScheme: _nameScheme,
f: f,
references: _references,
classTypeParameters: classBuilder?.cls.typeParameters);
List<SetterDeclaration>? augmentedSetables = _augmentedSetables;
if (augmentedSetables != null) {
for (SetterDeclaration augmented in augmentedSetables) {
augmented.buildSetterOutlineNode(
libraryBuilder: libraryBuilder,
nameScheme: _nameScheme,
f: noAddBuildNodesCallback,
// Augmented setters don't reuse references.
references: null,
classTypeParameters: classBuilder?.cls.typeParameters);
}
}
_lastSetable?.buildSetterOutlineNode(
libraryBuilder: libraryBuilder,
nameScheme: _nameScheme,
f: f,
references: _references,
classTypeParameters: classBuilder?.cls.typeParameters);
}
bool hasBuiltOutlineExpressions = false;
@override
void buildOutlineExpressions(ClassHierarchy classHierarchy,
List<DelayedDefaultValueCloner> delayedDefaultValueCloners) {
if (!hasBuiltOutlineExpressions) {
_introductoryField?.buildFieldOutlineExpressions(
classHierarchy: classHierarchy,
libraryBuilder: libraryBuilder,
declarationBuilder: declarationBuilder,
annotatables: [
readTarget as Annotatable,
if (writeTarget != null && readTarget != writeTarget)
writeTarget as Annotatable
],
annotatablesFileUri: readTarget!.fileUri,
isClassInstanceMember: isClassInstanceMember);
_introductoryGetable?.buildGetterOutlineExpressions(
classHierarchy: classHierarchy,
libraryBuilder: libraryBuilder,
declarationBuilder: declarationBuilder,
propertyBuilder: this,
annotatable: readTarget as Annotatable,
annotatableFileUri: readTarget!.fileUri,
isClassInstanceMember: isClassInstanceMember);
List<GetterDeclaration>? getterAugmentations = _getterAugmentations;
if (getterAugmentations != null) {
for (GetterDeclaration augmentation in getterAugmentations) {
augmentation.buildGetterOutlineExpressions(
classHierarchy: classHierarchy,
libraryBuilder: libraryBuilder,
declarationBuilder: declarationBuilder,
propertyBuilder: this,
annotatable: readTarget as Annotatable,
annotatableFileUri: readTarget!.fileUri,
isClassInstanceMember: isClassInstanceMember);
}
}
_introductorySetable?.buildSetterOutlineExpressions(
classHierarchy: classHierarchy,
libraryBuilder: libraryBuilder,
declarationBuilder: declarationBuilder,
propertyBuilder: this,
annotatable: writeTarget as Annotatable,
annotatableFileUri: writeTarget!.fileUri,
isClassInstanceMember: isClassInstanceMember);
List<SetterDeclaration>? setterAugmentations = _setterAugmentations;
if (setterAugmentations != null) {
for (SetterDeclaration augmentation in setterAugmentations) {
augmentation.buildSetterOutlineExpressions(
classHierarchy: classHierarchy,
libraryBuilder: libraryBuilder,
declarationBuilder: declarationBuilder,
propertyBuilder: this,
annotatable: writeTarget as Annotatable,
annotatableFileUri: writeTarget!.fileUri,
isClassInstanceMember: isClassInstanceMember);
}
}
hasBuiltOutlineExpressions = true;
}
}
@override
void checkTypes(SourceLibraryBuilder library, NameSpace nameSpace,
TypeEnvironment typeEnvironment) {
SourcePropertyBuilder? setterBuilder;
if (!isClassMember) {
// Getter/setter type conflict for class members is handled in the class
// hierarchy builder.
setterBuilder =
nameSpace.lookupLocalMember(name)?.setable as SourcePropertyBuilder?;
}
_introductoryField?.checkFieldTypes(
library, typeEnvironment, setterBuilder);
_introductoryGetable?.checkGetterTypes(
library, typeEnvironment, setterBuilder);
List<GetterDeclaration>? getterAugmentations = _getterAugmentations;
if (getterAugmentations != null) {
for (GetterDeclaration augmentation in getterAugmentations) {
augmentation.checkGetterTypes(library, typeEnvironment, setterBuilder);
}
}
_introductorySetable?.checkSetterTypes(library, typeEnvironment);
List<SetterDeclaration>? setterAugmentations = _setterAugmentations;
if (setterAugmentations != null) {
for (SetterDeclaration augmentation in setterAugmentations) {
augmentation.checkSetterTypes(library, typeEnvironment);
}
}
}
@override
void checkVariance(
SourceClassBuilder sourceClassBuilder, TypeEnvironment typeEnvironment) {
if (!isClassInstanceMember) return;
_introductoryField?.checkFieldVariance(sourceClassBuilder, typeEnvironment);
_introductoryGetable?.checkGetterVariance(
sourceClassBuilder, typeEnvironment);
List<GetterDeclaration>? getterAugmentations = _getterAugmentations;
if (getterAugmentations != null) {
for (GetterDeclaration augmentation in getterAugmentations) {
augmentation.checkGetterVariance(sourceClassBuilder, typeEnvironment);
}
}
_introductorySetable?.checkSetterVariance(
sourceClassBuilder, typeEnvironment);
List<SetterDeclaration>? setterAugmentations = _setterAugmentations;
if (setterAugmentations != null) {
for (SetterDeclaration augmentation in setterAugmentations) {
augmentation.checkSetterVariance(sourceClassBuilder, typeEnvironment);
}
}
}
@override
Iterable<Reference> get exportedMemberReferences => [
...?_lastGetable?.getExportedGetterReferences(_references),
...?_lastSetable?.getExportedSetterReferences(_references),
];
// TODO(johnniwinther): Should fields and getters have an invoke target?
@override
Member? get invokeTarget => readTarget;
@override
// Coverage-ignore(suite): Not run.
Reference? get invokeTargetReference => readTargetReference;
List<ClassMember>? _localMembers;
List<ClassMember>? _localSetters;
@override
List<ClassMember> get localMembers =>
_localMembers ??= _introductoryGetable?.localMembers ?? const [];
@override
List<ClassMember> get localSetters =>
_localSetters ??= _introductorySetable?.localSetters ?? const [];
@override
Name get memberName => _memberName.name;
@override
Member? get readTarget => _lastGetable?.readTarget;
@override
// Coverage-ignore(suite): Not run.
Reference? get readTargetReference => _references.getterReference;
@override
Member? get writeTarget => _lastSetable?.writeTarget;
@override
// Coverage-ignore(suite): Not run.
Reference? get writeTargetReference => _references.setterReference;
@override
int computeDefaultTypes(ComputeDefaultTypeContext context,
{required bool inErrorRecovery}) {
int count = 0;
if (_introductoryField != null) {
count += _introductoryField!.computeFieldDefaultTypes(context);
}
if (_introductoryGetable != null) {
count += _introductoryGetable!.computeGetterDefaultTypes(context);
}
List<GetterDeclaration>? getterAugmentations = _getterAugmentations;
if (getterAugmentations != null) {
for (GetterDeclaration augmentation in getterAugmentations) {
count += augmentation.computeGetterDefaultTypes(context);
}
}
if (_introductorySetable != null) {
count += _introductorySetable!.computeSetterDefaultTypes(context);
}
List<SetterDeclaration>? setterAugmentations = _setterAugmentations;
if (setterAugmentations != null) {
for (SetterDeclaration augmentation in setterAugmentations) {
count += augmentation.computeSetterDefaultTypes(context);
}
}
return count;
}
@override
// Coverage-ignore(suite): Not run.
Iterable<MetadataBuilder>? get metadataForTesting =>
_introductoryGetable?.metadata ?? _introductorySetable?.metadata;
@override
bool get isProperty => true;
bool _typeEnsured = false;
ClassMembersBuilder? _classMembersBuilder;
Set<ClassMember>? _getterOverrideDependencies;
void registerGetterOverrideDependency(
ClassMembersBuilder membersBuilder, Set<ClassMember> overriddenMembers) {
assert(
overriddenMembers.every((overriddenMember) =>
overriddenMember.declarationBuilder != classBuilder),
"Unexpected override dependencies for $this: $overriddenMembers");
_classMembersBuilder ??= membersBuilder;
_getterOverrideDependencies ??= {};
_getterOverrideDependencies!.addAll(overriddenMembers);
}
Set<ClassMember>? _setterOverrideDependencies;
void registerSetterOverrideDependency(
ClassMembersBuilder membersBuilder, Set<ClassMember> overriddenMembers) {
assert(
overriddenMembers.every((overriddenMember) =>
overriddenMember.declarationBuilder != classBuilder),
"Unexpected override dependencies for $this: $overriddenMembers");
_classMembersBuilder ??= membersBuilder;
_setterOverrideDependencies ??= {};
_setterOverrideDependencies!.addAll(overriddenMembers);
}
void inferTypesFromOverrides() {
if (_typeEnsured) return;
ClassMembersBuilder? classMembersBuilder = _classMembersBuilder;
if (classMembersBuilder != null) {
Set<ClassMember>? getterOverrideDependencies =
_getterOverrideDependencies;
Set<ClassMember>? setterOverrideDependencies =
_setterOverrideDependencies;
assert(getterOverrideDependencies != null ||
setterOverrideDependencies != null);
_introductoryField?.ensureTypes(classMembersBuilder,
getterOverrideDependencies, setterOverrideDependencies);
_introductoryGetable?.ensureGetterTypes(
libraryBuilder: libraryBuilder,
declarationBuilder: declarationBuilder,
membersBuilder: classMembersBuilder,
getterOverrideDependencies: getterOverrideDependencies);
List<GetterDeclaration>? getterAugmentations = _getterAugmentations;
if (getterAugmentations != null) {
for (GetterDeclaration augmentation in getterAugmentations) {
// Coverage-ignore-block(suite): Not run.
augmentation.ensureGetterTypes(
libraryBuilder: libraryBuilder,
declarationBuilder: declarationBuilder,
membersBuilder: classMembersBuilder,
getterOverrideDependencies: getterOverrideDependencies);
}
}
_introductorySetable?.ensureSetterTypes(
libraryBuilder: libraryBuilder,
declarationBuilder: declarationBuilder,
membersBuilder: classMembersBuilder,
setterOverrideDependencies: setterOverrideDependencies);
List<SetterDeclaration>? setterAugmentations = _setterAugmentations;
if (setterAugmentations != null) {
for (SetterDeclaration augmentation in setterAugmentations) {
// Coverage-ignore-block(suite): Not run.
augmentation.ensureSetterTypes(
libraryBuilder: libraryBuilder,
declarationBuilder: declarationBuilder,
membersBuilder: classMembersBuilder,
setterOverrideDependencies: setterOverrideDependencies);
}
}
_getterOverrideDependencies = null;
_setterOverrideDependencies = null;
_classMembersBuilder = null;
}
_typeEnsured = true;
}
static DartType getSetterType(SourcePropertyBuilder setterBuilder,
{required List<TypeParameter>? getterExtensionTypeParameters}) {
DartType setterType;
Member member = setterBuilder.writeTarget!;
if (setterBuilder.isExtensionInstanceMember ||
setterBuilder.isExtensionTypeInstanceMember) {
// An extension instance setter
//
// extension E<T> on A {
// void set property(T value) { ... }
// }
//
// is encoded as a top level method
//
// void E#set#property<T#>(A #this, T# value) { ... }
//
// Similarly for extension type instance setters.
//
Procedure procedure = member as Procedure;
setterType = procedure.function.positionalParameters[1].type;
if (getterExtensionTypeParameters != null &&
getterExtensionTypeParameters.isNotEmpty) {
// We substitute the setter type parameters for the getter type
// parameters to check them below in a shared context.
List<TypeParameter> setterExtensionTypeParameters =
procedure.function.typeParameters;
assert(getterExtensionTypeParameters.length ==
setterExtensionTypeParameters.length);
setterType = Substitution.fromPairs(setterExtensionTypeParameters, [
for (TypeParameter parameter in getterExtensionTypeParameters)
new TypeParameterType.withDefaultNullability(parameter)
]).substituteType(setterType);
}
} else {
setterType = member.setterType;
}
return setterType;
}
DartType get fieldType {
return _introductoryField!.fieldType;
}
/// Creates the [Initializer] for the invalid initialization of this field.
///
/// This is only used for instance fields.
Initializer buildErroneousInitializer(Expression effect, Expression value,
{required int fileOffset}) {
return _introductoryField!
.buildErroneousInitializer(effect, value, fileOffset: fileOffset);
}
/// Creates the AST node for this field as the default initializer.
///
/// This is only used for instance fields.
void buildImplicitDefaultValue() {
_introductoryField!.buildImplicitDefaultValue();
}
/// Create the [Initializer] for the implicit initialization of this field
/// in a constructor.
///
/// This is only used for instance fields.
Initializer buildImplicitInitializer() {
return _introductoryField!.buildImplicitInitializer();
}
/// Builds the [Initializer]s for each field used to encode this field
/// using the [fileOffset] for the created nodes and [value] as the initial
/// field value.
///
/// This is only used for instance fields.
List<Initializer> buildInitializer(int fileOffset, Expression value,
{required bool isSynthetic}) {
return _introductoryField!
.buildInitializer(fileOffset, value, isSynthetic: isSynthetic);
}
bool get hasInitializer => _introductoryField!.hasInitializer;
bool get isExtensionTypeDeclaredInstanceField =>
_introductoryField!.isExtensionTypeDeclaredInstanceField;
@override
bool get isFinal => _introductoryField!.isFinal;
bool get isLate => _introductoryField!.isLate;
DartType inferFieldType(ClassHierarchyBase hierarchy) {
inferTypesFromOverrides();
return _introductoryField!.inferType(hierarchy);
}
// Coverage-ignore(suite): Not run.
shared.Expression? get initializerExpression =>
_introductoryField?.initializerExpression;
@override
FieldQuality get fieldQuality =>
_introductoryField?.fieldQuality ?? FieldQuality.Absent;
@override
GetterQuality get getterQuality =>
_lastGetable?.getterQuality ?? GetterQuality.Absent;
@override
SetterQuality get setterQuality =>
_lastSetable?.setterQuality ?? SetterQuality.Absent;
UriOffsetLength? get fieldUriOffset => _introductoryField?.uriOffset;
@override
UriOffsetLength? get getterUriOffset => _introductoryGetable?.uriOffset;
@override
UriOffsetLength? get setterUriOffset => _introductorySetable?.uriOffset;
}
class GetterClassMember implements ClassMember {
final SourcePropertyBuilder _builder;
GetterClassMember(this._builder);
@override
UriOffsetLength get uriOffset => _builder.getterUriOffset!;
@override
DeclarationBuilder get declarationBuilder => _builder.declarationBuilder!;
@override
// Coverage-ignore(suite): Not run.
List<ClassMember> get declarations =>
throw new UnsupportedError('$runtimeType.declarations');
@override
bool get forSetter => false;
@override
String get fullName {
String className = declarationBuilder.fullNameForErrors;
return "${className}.${fullNameForErrors}";
}
@override
String get fullNameForErrors => _builder.fullNameForErrors;
@override
Covariance getCovariance(ClassMembersBuilder membersBuilder) =>
const Covariance.empty();
@override
Member getMember(ClassMembersBuilder membersBuilder) {
return _builder.readTarget!;
}
@override
// Coverage-ignore(suite): Not run.
MemberResult getMemberResult(ClassMembersBuilder membersBuilder) {
if (isStatic) {
return new StaticMemberResult(getMember(membersBuilder), memberKind,
isDeclaredAsField: false,
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: false);
} else {
return new TypeDeclarationInstanceMemberResult(
getMember(membersBuilder), memberKind,
isDeclaredAsField: false);
}
}
@override
Member? getTearOff(ClassMembersBuilder membersBuilder) => null;
@override
bool get hasDeclarations => false;
@override
void inferType(ClassMembersBuilder membersBuilder) {
_builder.inferTypesFromOverrides();
}
@override
ClassMember get interfaceMember => this;
@override
bool get isAbstract => _builder.hasAbstractGetter;
@override
bool get isDuplicate => _builder.isDuplicate;
@override
bool get isExtensionTypeMember => _builder.isExtensionTypeMember;
@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 GetterClassMember &&
// Coverage-ignore(suite): Not run.
_builder == other._builder;
}
@override
bool get isSetter => false;
@override
bool get isSourceDeclaration => true;
@override
bool get isStatic => _builder.isStatic;
@override
bool get isSynthesized => false;
@override
ClassMemberKind get memberKind => ClassMemberKind.Getter;
@override
Name get name => _builder.memberName;
@override
void registerOverrideDependency(
ClassMembersBuilder membersBuilder, Set<ClassMember> overriddenMembers) {
_builder.registerGetterOverrideDependency(
membersBuilder, overriddenMembers);
}
@override
String toString() => '$runtimeType($fullName,forSetter=${forSetter})';
}
class SetterClassMember implements ClassMember {
final SourcePropertyBuilder _builder;
late final Covariance _covariance =
new Covariance.fromSetter(_builder.writeTarget as Procedure);
SetterClassMember(this._builder);
@override
UriOffsetLength get uriOffset => _builder.setterUriOffset!;
@override
DeclarationBuilder get declarationBuilder => _builder.declarationBuilder!;
@override
// Coverage-ignore(suite): Not run.
List<ClassMember> get declarations =>
throw new UnsupportedError('$runtimeType.declarations');
@override
bool get forSetter => true;
@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) => _covariance;
@override
Member getMember(ClassMembersBuilder membersBuilder) {
return _builder.writeTarget!;
}
@override
// Coverage-ignore(suite): Not run.
MemberResult getMemberResult(ClassMembersBuilder membersBuilder) {
if (isStatic) {
return new StaticMemberResult(getMember(membersBuilder), memberKind,
isDeclaredAsField: false,
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: false);
} else {
return new TypeDeclarationInstanceMemberResult(
getMember(membersBuilder), memberKind,
isDeclaredAsField: false);
}
}
@override
Member? getTearOff(ClassMembersBuilder membersBuilder) => null;
@override
bool get hasDeclarations => false;
@override
void inferType(ClassMembersBuilder membersBuilder) {
_builder.inferTypesFromOverrides();
}
@override
ClassMember get interfaceMember => this;
@override
bool get isAbstract => _builder.hasAbstractSetter;
@override
bool get isDuplicate => _builder.isDuplicate;
@override
bool get isExtensionTypeMember => _builder.isExtensionTypeMember;
@override
bool get isNoSuchMethodForwarder => false;
@override
// Coverage-ignore(suite): Not run.
bool isObjectMember(ClassBuilder objectClass) {
return declarationBuilder == objectClass;
}
@override
bool get isProperty => true;
@override
// Coverage-ignore(suite): Not run.
bool isSameDeclaration(ClassMember other) {
return other is SetterClassMember && _builder == other._builder;
}
@override
bool get isSetter => true;
@override
bool get isSourceDeclaration => true;
@override
bool get isStatic => _builder.isStatic;
@override
bool get isSynthesized => false;
@override
ClassMemberKind get memberKind => ClassMemberKind.Setter;
@override
Name get name => _builder.memberName;
@override
void registerOverrideDependency(
ClassMembersBuilder membersBuilder, Set<ClassMember> overriddenMembers) {
_builder.registerSetterOverrideDependency(
membersBuilder, overriddenMembers);
}
@override
String toString() => '$runtimeType($fullName,forSetter=${forSetter})';
}
abstract class PropertyReferences {
Reference? get fieldReference;
Reference? get getterReference;
Reference? get setterReference;
void registerReference(SourceLoader loader, SourcePropertyBuilder builder);
factory PropertyReferences(
String name, NameScheme nameScheme, IndexedContainer? indexedContainer,
{required bool fieldIsLateWithLowering}) = _PropertyReferences;
}
class _PropertyReferences implements PropertyReferences {
Reference? _fieldReference;
Reference? _getterReference;
Reference? _setterReference;
_PropertyReferences._(
this._fieldReference, this._getterReference, this._setterReference);
factory _PropertyReferences(
String name, NameScheme nameScheme, IndexedContainer? indexedContainer,
{required bool fieldIsLateWithLowering}) {
Reference? getterReference;
Reference? setterReference;
Reference? fieldReference;
if (indexedContainer != null) {
Name getterNameToLookup =
nameScheme.getProcedureMemberName(ProcedureKind.Getter, name).name;
getterReference =
indexedContainer.lookupGetterReference(getterNameToLookup);
Name setterNameToLookup =
nameScheme.getProcedureMemberName(ProcedureKind.Setter, name).name;
if ((nameScheme.isExtensionMember || nameScheme.isExtensionTypeMember) &&
nameScheme.isInstanceMember) {
// Extension (type) instance setters are encoded as methods.
setterReference =
indexedContainer.lookupGetterReference(setterNameToLookup);
} else {
setterReference =
indexedContainer.lookupSetterReference(setterNameToLookup);
}
Name fieldNameToLookup = nameScheme
.getFieldMemberName(FieldNameType.Field, name,
isSynthesized: fieldIsLateWithLowering)
.name;
fieldReference = indexedContainer.lookupFieldReference(fieldNameToLookup);
}
return new _PropertyReferences._(
fieldReference, getterReference, setterReference);
}
@override
void registerReference(SourceLoader loader, SourcePropertyBuilder builder) {
if (_fieldReference != null) {
loader.buildersCreatedWithReferences[_fieldReference!] = builder;
}
if (_getterReference != null) {
loader.buildersCreatedWithReferences[_getterReference!] = builder;
}
if (_setterReference != null) {
loader.buildersCreatedWithReferences[_setterReference!] = builder;
}
}
@override
Reference get fieldReference => _fieldReference ??= new Reference();
@override
Reference get getterReference => _getterReference ??= new Reference();
@override
Reference get setterReference => _setterReference ??= new Reference();
}