blob: 972b493f409cb2058b5d1d38e98ef8a5802369dc [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.
part of 'fragment.dart';
class ConstructorName {
/// The name of the constructor itself.
///
/// For an unnamed constructor, this is ''.
final String name;
/// The offset of the name of the constructor, if the constructor is not
/// unnamed.
final int? nameOffset;
/// The name of the constructor including the enclosing declaration name.
///
/// For unnamed constructors the full name is normalized to be the class name,
/// regardless of whether the constructor was declared with 'new'.
///
/// For invalid constructor names, the full name is normalized to use the
/// class name as prefix, regardless of whether the declaration did so.
///
/// This means that not in all cases is the text pointed to by
/// [fullNameOffset] and [fullNameLength] the same as the [fullName].
final String fullName;
/// The offset at which the full name occurs.
///
/// This is used in messages to put the `^` at the start of the [fullName].
final int fullNameOffset;
/// The number of characters of full name that occurs at [fullNameOffset].
///
/// This is used in messages to put the right amount of `^` under the name.
final int fullNameLength;
ConstructorName(
{required this.name,
required this.nameOffset,
required this.fullName,
required this.fullNameOffset,
required this.fullNameLength})
: assert(name != 'new');
}
void _buildMetadataForOutlineExpressions(
SourceLibraryBuilder libraryBuilder,
LookupScope parentScope,
BodyBuilderContext bodyBuilderContext,
Annotatable annotatable,
List<MetadataBuilder>? metadata,
{required Uri fileUri,
required bool createFileUriExpression}) {
MetadataBuilder.buildAnnotations(annotatable, metadata, bodyBuilderContext,
libraryBuilder, fileUri, parentScope,
createFileUriExpression: createFileUriExpression);
}
void _buildTypeParametersForOutlineExpressions(
ClassHierarchy classHierarchy,
SourceLibraryBuilder libraryBuilder,
BodyBuilderContext bodyBuilderContext,
LookupScope typeParameterScope,
List<NominalParameterBuilder>? typeParameters) {
if (typeParameters != null) {
for (int i = 0; i < typeParameters.length; i++) {
typeParameters[i].buildOutlineExpressions(libraryBuilder,
bodyBuilderContext, classHierarchy, typeParameterScope);
}
}
}
void _buildFormalsForOutlineExpressions(
SourceLibraryBuilder libraryBuilder,
DeclarationBuilder? declarationBuilder,
List<FormalParameterBuilder>? formals,
{required bool isClassInstanceMember}) {
if (formals != null) {
for (FormalParameterBuilder formal in formals) {
_buildFormalForOutlineExpressions(
libraryBuilder, declarationBuilder, formal,
isClassInstanceMember: isClassInstanceMember);
}
}
}
void _buildFormalForOutlineExpressions(SourceLibraryBuilder libraryBuilder,
DeclarationBuilder? declarationBuilder, FormalParameterBuilder formal,
{required bool isClassInstanceMember}) {
// For const constructors we need to include default parameter values
// into the outline. For all other formals we need to call
// buildOutlineExpressions to clear initializerToken to prevent
// consuming too much memory.
formal.buildOutlineExpressions(libraryBuilder, declarationBuilder,
buildDefaultValue: isClassInstanceMember);
}
/// Common interface for fragments that can declare a field.
abstract class FieldDeclaration {
/// The metadata declared on this fragment.
List<MetadataBuilder>? get metadata;
/// Builds the core AST structures for this field declaration as needed for
/// the outline.
void buildOutlineNode(SourceLibraryBuilder libraryBuilder,
NameScheme nameScheme, BuildNodesCallback f, FieldReference references,
{required List<TypeParameter>? classTypeParameters});
void buildOutlineExpressions(
ClassHierarchy classHierarchy,
SourceLibraryBuilder libraryBuilder,
DeclarationBuilder? declarationBuilder,
LookupScope parentScope,
List<Annotatable> annotatables,
{required bool isClassInstanceMember,
required bool createFileUriExpression});
int computeDefaultTypes(ComputeDefaultTypeContext context);
void checkTypes(SourceLibraryBuilder libraryBuilder,
TypeEnvironment typeEnvironment, SourcePropertyBuilder? setterBuilder,
{required bool isAbstract, required bool isExternal});
/// Checks the variance of type parameters [sourceClassBuilder] used in the
/// type of this field declaration.
void checkVariance(
SourceClassBuilder sourceClassBuilder, TypeEnvironment typeEnvironment);
/// The references to the members from this field declaration that are
/// accessible in exports through the name of the builder.
Iterable<Reference> getExportedMemberReferences(FieldReference references);
/// Return `true` if the declaration introduces a setter.
bool get hasSetter;
/// Return `true` if the declaration has an initializer.
bool get hasInitializer;
/// Return `true` if the declaration is final.
bool get isFinal;
/// Return `true` if the declaration is late.
bool get isLate;
/// Return `true` if the declaration is in instance field declared in an
/// extension type.
bool get isExtensionTypeDeclaredInstanceField;
/// Returns `true` if this field is declared by an enum element.
bool get isEnumElement;
/// The [ClassMember]s for the getter introduced by this field declaration.
List<ClassMember> get localMembers;
/// The [ClassMember]s for the setter introduced by this field declaration,
/// if any.
List<ClassMember> get localSetters;
/// The [Member] uses as the target for reading from this field declaration.
Member get readTarget;
/// The [Member] uses as the target for writing to this field declaration, or
/// `null` if this field declaration has no setter.
Member? get writeTarget;
/// The [TypeBuilder] for the declared type of this field declaration.
TypeBuilder get type;
/// The [DartType] of this field declaration.
abstract DartType fieldType;
Initializer buildErroneousInitializer(Expression effect, Expression value,
{required int fileOffset});
/// 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();
/// 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});
/// Ensures that the type of this field declaration has been computed.
void ensureTypes(
ClassMembersBuilder membersBuilder,
Set<ClassMember>? getterOverrideDependencies,
Set<ClassMember>? setterOverrideDependencies);
/// Infers the type of this field declaration.
DartType inferType(ClassHierarchyBase hierarchy);
shared.Expression? get initializerExpression;
}
mixin FieldDeclarationMixin
implements FieldDeclaration, Inferable, InferredTypeListener {
Uri get fileUri;
int get nameOffset;
SourcePropertyBuilder get builder;
bool get isConst;
void _setCovariantByClassInternal();
abstract DartType _fieldTypeInternal;
@override
void onInferredType(DartType type) {
fieldType = type;
}
@override
void inferTypes(ClassHierarchyBase hierarchy) {
inferType(hierarchy);
}
@override
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)) {
_setCovariantByClassInternal();
}
}
}
return fieldType;
});
}
@override
// Coverage-ignore(suite): Not run.
DartType get fieldType => _fieldTypeInternal;
@override
void set fieldType(DartType value) {
_fieldTypeInternal = value;
DeclarationBuilder? declarationBuilder = builder.declarationBuilder;
// TODO(johnniwinther): Should this be `hasSetter`?
if (!isFinal && !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)) {
_setCovariantByClassInternal();
}
}
}
}
}