[cfe] Add PrimaryConstructoFieldFragment

This creates a PrimaryConstructorFieldFragment instead of a FieldFragment for primary constructor fields (currently only occurring in extension types).

Change-Id: Iec58112a0a0ef64dba248f1ce93625e297b10705
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/426460
Reviewed-by: Chloe Stefantsova <cstefantsova@google.com>
Commit-Queue: Johnni Winther <johnniwinther@google.com>
This commit is contained in:
Johnni Winther
2025-05-05 03:45:17 -07:00
committed by Commit Queue
parent df9e0f9729
commit 918899974a
10 changed files with 610 additions and 77 deletions
@@ -18,7 +18,7 @@ class ExtensionTypeFragment extends DeclarationFragmentImpl
late final int startOffset;
late final int endOffset;
final List<FieldFragment> primaryConstructorFields = [];
final List<PrimaryConstructorFieldFragment> primaryConstructorFields = [];
SourceExtensionTypeDeclarationBuilder? _builder;
@@ -54,7 +54,7 @@ class ExtensionTypeFragment extends DeclarationFragmentImpl
modifiers.isAugment;
@override
void addPrimaryConstructorField(FieldFragment fragment) {
void addPrimaryConstructorField(PrimaryConstructorFieldFragment fragment) {
primaryConstructorFields.add(fragment);
}
@@ -23,9 +23,6 @@ class FieldFragment implements Fragment {
final bool isTopLevel;
final Modifiers modifiers;
// TODO(johnniwinther): Create separate fragment for primary constructor
// fields.
final bool isPrimaryConstructorField;
final LookupScope enclosingScope;
@@ -46,7 +43,6 @@ class FieldFragment implements Fragment {
required this.type,
required this.isTopLevel,
required this.modifiers,
required this.isPrimaryConstructorField,
required this.enclosingScope,
required this.enclosingDeclaration,
required this.enclosingCompilationUnit,
@@ -5,17 +5,36 @@
part of '../fragment.dart';
class FieldFragmentBodyBuilderContext extends BodyBuilderContext {
final SourcePropertyBuilder _builder;
final FieldFragmentDeclaration _declaration;
final FieldFragment _fragment;
FieldFragmentBodyBuilderContext(
this._declaration,
this._fragment,
SourceLibraryBuilder libraryBuilder,
DeclarationBuilder? declarationBuilder,
{required bool isDeclarationInstanceMember})
: super(libraryBuilder, declarationBuilder,
isDeclarationInstanceMember: isDeclarationInstanceMember);
@override
final bool isLateField;
@override
final bool isAbstractField;
@override
final bool isExternalField;
final int _nameOffset;
final int _nameLength;
final bool _isConst;
FieldFragmentBodyBuilderContext(this._builder, this._declaration,
{required this.isLateField,
required this.isAbstractField,
required this.isExternalField,
required int nameOffset,
required int nameLength,
required bool isConst})
: this._nameOffset = nameOffset,
this._nameLength = nameLength,
this._isConst = isConst,
super(_builder.libraryBuilder, _builder.declarationBuilder,
isDeclarationInstanceMember: _builder.isDeclarationInstanceMember);
@override
// Coverage-ignore(suite): Not run.
@@ -26,25 +45,16 @@ class FieldFragmentBodyBuilderContext extends BodyBuilderContext {
}
@override
bool get isLateField => _fragment.modifiers.isLate;
@override
bool get isAbstractField => _fragment.modifiers.isAbstract;
@override
bool get isExternalField => _fragment.modifiers.isExternal;
// Coverage-ignore(suite): Not run.
int get memberNameOffset => _nameOffset;
@override
// Coverage-ignore(suite): Not run.
int get memberNameOffset => _fragment.nameOffset;
@override
// Coverage-ignore(suite): Not run.
int get memberNameLength => _fragment.name.length;
int get memberNameLength => _nameLength;
@override
InstanceTypeParameterAccessState get instanceTypeParameterAccessState {
if (_fragment.builder.isExtensionMember && !isExternalField) {
if (_builder.isExtensionMember && !isExternalField) {
return InstanceTypeParameterAccessState.Invalid;
} else {
return super.instanceTypeParameterAccessState;
@@ -59,15 +69,15 @@ class FieldFragmentBodyBuilderContext extends BodyBuilderContext {
@override
// Coverage-ignore(suite): Not run.
AugmentSuperTarget? get augmentSuperTarget {
if (_fragment.builder.isAugmentation) {
return _fragment.builder.augmentSuperTarget;
if (_builder.isAugmentation) {
return _builder.augmentSuperTarget;
}
return null;
}
@override
ConstantContext get constantContext {
return _fragment.modifiers.isConst
return _isConst
? ConstantContext.inferred
: !_declaration.isStatic && declarationDeclaresConstConstructor
? ConstantContext.required
@@ -128,7 +128,7 @@ abstract class FieldDeclaration {
shared.Expression? get initializerExpression;
}
class FieldDeclarationImpl
class RegularFieldDeclaration
with FieldDeclarationMixin
implements
FieldDeclaration,
@@ -149,7 +149,7 @@ class FieldDeclarationImpl
/// building them twice as part of the non-outline build.
bool hasBodyBeenBuilt = false;
FieldDeclarationImpl(this._fragment) {
RegularFieldDeclaration(this._fragment) {
_fragment.declaration = this;
}
@@ -194,8 +194,7 @@ class FieldDeclarationImpl
@override
bool get isExtensionTypeDeclaredInstanceField =>
builder.isExtensionTypeInstanceMember &&
!_fragment.isPrimaryConstructorField;
builder.isExtensionTypeInstanceMember;
@override
bool get isFinal => _fragment.modifiers.isFinal;
@@ -404,9 +403,13 @@ class FieldDeclarationImpl
@override
BodyBuilderContext createBodyBuilderContext() {
return new FieldFragmentBodyBuilderContext(
this, _fragment, builder.libraryBuilder, builder.declarationBuilder,
isDeclarationInstanceMember: builder.isDeclarationInstanceMember);
return new FieldFragmentBodyBuilderContext(builder, this,
isLateField: _fragment.modifiers.isLate,
isAbstractField: _fragment.modifiers.isAbstract,
isExternalField: _fragment.modifiers.isExternal,
nameOffset: _fragment.nameOffset,
nameLength: _fragment.name.length,
isConst: _fragment.modifiers.isConst);
}
void createEncoding(SourcePropertyBuilder builder) {
@@ -430,20 +433,16 @@ class FieldDeclarationImpl
isAbstract: isAbstract,
isExternal: isExternal);
} else if (isExtensionTypeMember && isInstanceMember) {
if (_fragment.isPrimaryConstructorField) {
_encoding = new RepresentationFieldEncoding(_fragment);
} else {
// Field on a extension type. Encode as abstract.
// TODO(johnniwinther): Should we have an erroneous flag on such
// members?
_encoding = new AbstractOrExternalFieldEncoding(_fragment,
isExtensionInstanceMember: isExtensionMember && isInstanceMember,
isExtensionTypeInstanceMember:
isExtensionTypeMember && isInstanceMember,
isAbstract: true,
isExternal: false,
isForcedExtension: true);
}
// Field on a extension type. Encode as abstract.
// TODO(johnniwinther): Should we have an erroneous flag on such
// members?
_encoding = new AbstractOrExternalFieldEncoding(_fragment,
isExtensionInstanceMember: isExtensionMember && isInstanceMember,
isExtensionTypeInstanceMember:
isExtensionTypeMember && isInstanceMember,
isAbstract: true,
isExternal: false,
isForcedExtension: true);
} else if (isLate &&
libraryBuilder.loader.target.backendTarget.isLateFieldLoweringEnabled(
hasInitializer: hasInitializer,
@@ -1167,7 +1167,7 @@ class AbstractOrExternalFieldEncoding implements FieldEncoding {
/// The encoding of an extension type declaration representation field.
class RepresentationFieldEncoding implements FieldEncoding {
final FieldFragment _fragment;
final PrimaryConstructorFieldFragment _fragment;
late Procedure _getter;
DartType? _type;
@@ -1219,12 +1219,12 @@ class RepresentationFieldEncoding implements FieldEncoding {
fileUri: _fragment.fileUri, reference: references.fieldGetterReference)
..stubKind = ProcedureStubKind.RepresentationField
..fileOffset = _fragment.nameOffset
..fileEndOffset = _fragment.endOffset;
..fileEndOffset = _fragment.nameOffset;
nameScheme
.getFieldMemberName(FieldNameType.RepresentationField, _fragment.name,
isSynthesized: true)
.attachMember(_getter);
_getter..isConst = _fragment.modifiers.isConst;
_getter..isConst = false;
_getter
..isStatic = false
..isExtensionMember = false
@@ -56,8 +56,10 @@ import '../source/source_property_builder.dart';
import '../source/source_type_alias_builder.dart';
import '../source/source_type_parameter_builder.dart';
import '../source/type_parameter_scope_builder.dart';
import '../type_inference/inference_helper.dart';
import '../type_inference/inference_results.dart';
import '../type_inference/type_inference_engine.dart';
import '../type_inference/type_inferrer.dart';
import '../type_inference/type_schema.dart';
import 'constructor/declaration.dart';
import 'factory/declaration.dart';
@@ -86,6 +88,7 @@ part 'method.dart';
part 'mixin.dart';
part 'named_mixin_application.dart';
part 'primary_constructor.dart';
part 'primary_constructor_field.dart';
part 'setter.dart';
part 'type_parameter.dart';
part 'typedef.dart';
@@ -0,0 +1,428 @@
// 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 PrimaryConstructorFieldFragment implements Fragment {
@override
final String name;
final Uri fileUri;
final int nameOffset;
final List<MetadataBuilder>? metadata;
final TypeBuilder type;
final LookupScope enclosingScope;
final DeclarationFragment enclosingDeclaration;
final LibraryFragment enclosingCompilationUnit;
SourcePropertyBuilder? _builder;
PrimaryConstructorFieldDeclaration? _declaration;
PrimaryConstructorFieldFragment({
required this.name,
required this.fileUri,
required this.nameOffset,
required this.metadata,
required this.type,
required this.enclosingScope,
required this.enclosingDeclaration,
required this.enclosingCompilationUnit,
});
@override
SourcePropertyBuilder get builder {
assert(_builder != null, "Builder has not been computed for $this.");
return _builder!;
}
void set builder(SourcePropertyBuilder value) {
assert(_builder == null, "Builder has already been computed for $this.");
_builder = value;
}
PrimaryConstructorFieldDeclaration get declaration {
assert(
_declaration != null, "Declaration has not been computed for $this.");
return _declaration!;
}
void set declaration(PrimaryConstructorFieldDeclaration value) {
assert(_declaration == null,
"Declaration has already been computed for $this.");
_declaration = value;
}
}
class PrimaryConstructorFieldDeclaration
with FieldDeclarationMixin
implements
FieldDeclaration,
FieldFragmentDeclaration,
GetterDeclaration,
Inferable,
InferredTypeListener {
final PrimaryConstructorFieldFragment _fragment;
late final FieldEncoding _encoding;
/// 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;
PrimaryConstructorFieldDeclaration(this._fragment) {
_fragment.declaration = this;
}
@override
SourcePropertyBuilder get builder => _fragment.builder;
@override
FieldQuality get fieldQuality => FieldQuality.Concrete;
@override
DartType get fieldType => _encoding.type;
@override
Uri get fileUri => _fragment.fileUri;
@override
GetterQuality get getterQuality => GetterQuality.Implicit;
@override
bool get hasInitializer => false;
@override
bool get hasSetter => false;
@override
// Coverage-ignore(suite): Not run.
shared.Expression? get initializerExpression => null;
@override
bool get isConst => false;
@override
bool get isEnumElement => false;
@override
bool get isExtensionTypeDeclaredInstanceField => false;
@override
bool get isFinal => true;
@override
bool get isLate => false;
@override
bool get isStatic => false;
@override
List<ClassMember> get localMembers => _encoding.localMembers;
@override
List<MetadataBuilder>? get metadata => _fragment.metadata;
@override
int get nameOffset => _fragment.nameOffset;
@override
Member get readTarget => _encoding.readTarget;
@override
TypeBuilder get type => _fragment.type;
@override
// Coverage-ignore(suite): Not run.
DartType get fieldTypeInternal => _encoding.type;
@override
void set fieldTypeInternal(DartType value) {
_encoding.type = value;
}
/// 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;
_encoding.createBodies(coreTypes, initializer);
}
@override
Initializer buildErroneousInitializer(Expression effect, Expression value,
{required int fileOffset}) {
return _encoding.buildErroneousInitializer(effect, value,
fileOffset: fileOffset);
}
@override
void buildFieldInitializer(InferenceHelper helper, TypeInferrer typeInferrer,
CoreTypes coreTypes, Expression? initializer) {
if (initializer != null) {
if (!hasBodyBeenBuilt) {
initializer = typeInferrer
.inferFieldInitializer(helper, fieldType, initializer)
.expression;
buildBody(coreTypes, initializer);
}
} else if (!hasBodyBeenBuilt) {
buildBody(coreTypes, null);
}
}
@override
void buildImplicitDefaultValue() {
_encoding.buildImplicitDefaultValue();
}
@override
Initializer buildImplicitInitializer() {
return _encoding.buildImplicitInitializer();
}
@override
List<Initializer> buildInitializer(int fileOffset, Expression value,
{required bool isSynthetic}) {
return _encoding.createInitializer(fileOffset, value,
isSynthetic: isSynthetic);
}
@override
void buildFieldOutlineExpressions(
{required ClassHierarchy classHierarchy,
required SourceLibraryBuilder libraryBuilder,
required DeclarationBuilder? declarationBuilder,
required List<Annotatable> annotatables,
required Uri annotatablesFileUri,
required bool isClassInstanceMember}) {
BodyBuilderContext bodyBuilderContext = createBodyBuilderContext();
for (Annotatable annotatable in annotatables) {
buildMetadataForOutlineExpressions(
libraryBuilder: libraryBuilder,
scope: _fragment.enclosingScope,
bodyBuilderContext: bodyBuilderContext,
annotatable: annotatable,
annotatableFileUri: annotatablesFileUri,
metadata: metadata);
}
}
@override
void buildFieldOutlineNode(SourceLibraryBuilder libraryBuilder,
NameScheme nameScheme, BuildNodesCallback f, FieldReference references,
{required List<TypeParameter>? classTypeParameters}) {
_encoding.buildOutlineNode(libraryBuilder, nameScheme, references,
isAbstractOrExternal: false, classTypeParameters: classTypeParameters);
if (type is! InferableTypeBuilder) {
fieldType = type.build(libraryBuilder, TypeUse.fieldType);
}
_encoding.registerMembers(f);
}
@override
void checkFieldTypes(SourceLibraryBuilder libraryBuilder,
TypeEnvironment typeEnvironment, SourcePropertyBuilder? setterBuilder) {
libraryBuilder.checkTypesInField(typeEnvironment,
isInstanceMember: builder.isDeclarationInstanceMember,
isLate: isLate,
isExternal: false,
hasInitializer: hasInitializer,
fieldType: fieldType,
name: _fragment.name,
nameLength: _fragment.name.length,
nameOffset: nameOffset,
fileUri: fileUri);
}
@override
void checkFieldVariance(
SourceClassBuilder sourceClassBuilder, TypeEnvironment typeEnvironment) {
sourceClassBuilder.checkVarianceInField(typeEnvironment,
fieldType: fieldType,
isInstanceMember: !isStatic,
hasSetter: hasSetter,
isCovariantByDeclaration: false,
fileUri: fileUri,
fileOffset: nameOffset);
}
@override
int computeFieldDefaultTypes(ComputeDefaultTypeContext context) {
if (type is! OmittedTypeBuilder) {
context.reportInboundReferenceIssuesForType(type);
context.recursivelyReportGenericFunctionTypesAsBoundsForType(type);
}
return 0;
}
@override
BodyBuilderContext createBodyBuilderContext() {
return new FieldFragmentBodyBuilderContext(builder, this,
isLateField: false,
isAbstractField: false,
isExternalField: false,
nameOffset: _fragment.nameOffset,
nameLength: _fragment.name.length,
isConst: false);
}
void createEncoding(SourcePropertyBuilder builder) {
SourceLibraryBuilder libraryBuilder = builder.libraryBuilder;
bool isInstanceMember = builder.isDeclarationInstanceMember;
bool isExtensionTypeMember = builder.isExtensionTypeMember;
// TODO(johnniwinther): Add support for regular fields for the primary
// constructors feature.
assert(isExtensionTypeMember && isInstanceMember);
_encoding = new RepresentationFieldEncoding(_fragment);
type.registerInferredTypeListener(this);
if (type is InferableTypeBuilder) {
// 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(
libraryBuilder: libraryBuilder,
typeBuilder: type,
inferType: inferType,
computeType: _computeInferredType,
fileUri: fileUri,
name: _fragment.name,
nameOffset: nameOffset,
nameLength: _fragment.name.length,
token: null);
type.registerInferable(this);
}
}
@override
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: _fragment.name,
fileUri: fileUri,
nameOffset: nameOffset,
nameLength: _fragment.name.length,
isAssignable: hasSetter);
} else {
// Coverage-ignore-block(suite): Not run.
type.build(builder.libraryBuilder, TypeUse.fieldType,
hierarchy: membersBuilder.hierarchyBuilder);
}
}
@override
void registerSuperCall() {
_encoding.registerSuperCall();
}
DartType _computeInferredType(
ClassHierarchyBase classHierarchy, Token? token) {
DartType? inferredType;
SourceLibraryBuilder libraryBuilder = builder.libraryBuilder;
DeclarationBuilder? declarationBuilder = builder.declarationBuilder;
if (token != null) {
InterfaceType? enclosingClassThisType = declarationBuilder
is SourceClassBuilder
? libraryBuilder.loader.typeInferenceEngine.coreTypes
.thisInterfaceType(
declarationBuilder.cls, libraryBuilder.library.nonNullable)
: null;
LookupScope scope = _fragment.enclosingScope;
TypeInferrer typeInferrer =
libraryBuilder.loader.typeInferenceEngine.createTopLevelTypeInferrer(
fileUri,
enclosingClassThisType,
libraryBuilder,
scope,
builder
.dataForTesting
// Coverage-ignore(suite): Not run.
?.inferenceData);
BodyBuilderContext bodyBuilderContext = createBodyBuilderContext();
BodyBuilder bodyBuilder = libraryBuilder.loader.createBodyBuilderForField(
libraryBuilder, bodyBuilderContext, scope, typeInferrer, fileUri);
bodyBuilder.constantContext = ConstantContext.none;
bodyBuilder.inFieldInitializer = true;
bodyBuilder.inLateFieldInitializer = false;
Expression initializer = bodyBuilder.parseFieldInitializer(token);
inferredType =
typeInferrer.inferImplicitFieldType(bodyBuilder, initializer);
} else {
inferredType = const DynamicType();
}
return inferredType;
}
@override
void setCovariantByClassInternal() {
_encoding.setCovariantByClass();
}
@override
void buildGetterOutlineExpressions(
{required ClassHierarchy classHierarchy,
required SourceLibraryBuilder libraryBuilder,
required DeclarationBuilder? declarationBuilder,
required SourcePropertyBuilder propertyBuilder,
required Annotatable annotatable,
required Uri annotatableFileUri,
required bool isClassInstanceMember}) {}
@override
void buildGetterOutlineNode(
{required SourceLibraryBuilder libraryBuilder,
required NameScheme nameScheme,
required BuildNodesCallback f,
required PropertyReferences? references,
required List<TypeParameter>? classTypeParameters}) {}
@override
void checkGetterTypes(SourceLibraryBuilder libraryBuilder,
TypeEnvironment typeEnvironment, SourcePropertyBuilder? setterBuilder) {}
@override
void checkGetterVariance(
SourceClassBuilder sourceClassBuilder, TypeEnvironment typeEnvironment) {}
@override
int computeGetterDefaultTypes(ComputeDefaultTypeContext context) {
return 0;
}
@override
void createGetterEncoding(
ProblemReporting problemReporting,
SourcePropertyBuilder builder,
PropertyEncodingStrategy encodingStrategy,
List<NominalParameterBuilder> unboundNominalParameters) {}
@override
void ensureGetterTypes(
{required SourceLibraryBuilder libraryBuilder,
required DeclarationBuilder? declarationBuilder,
required ClassMembersBuilder membersBuilder,
required Set<ClassMember>? getterOverrideDependencies}) {}
@override
Iterable<Reference> getExportedGetterReferences(
PropertyReferences references) {
return [references.getterReference!];
}
}
@@ -1347,17 +1347,12 @@ class BuilderFactoryImpl implements BuilderFactory, BuilderFactoryResult {
required TypeBuilder type,
required String name,
required int nameOffset}) {
_declarationFragments.current.addPrimaryConstructorField(_addField(
metadata: metadata,
modifiers: Modifiers.Final,
isTopLevel: false,
type: type,
name: name,
nameOffset: nameOffset,
endOffset: nameOffset,
initializerToken: null,
hasInitializer: false,
isPrimaryConstructorField: true));
_declarationFragments.current.addPrimaryConstructorField(
_addPrimaryConstructorField(
metadata: metadata,
type: type,
name: name,
nameOffset: nameOffset));
}
@override
@@ -1819,8 +1814,7 @@ class BuilderFactoryImpl implements BuilderFactory, BuilderFactoryResult {
initializerToken: startToken,
hasInitializer: hasInitializer,
constInitializerToken:
potentiallyNeedInitializerInOutline ? startToken : null,
isPrimaryConstructorField: false));
potentiallyNeedInitializerInOutline ? startToken : null));
}
}
@@ -1834,8 +1828,7 @@ class BuilderFactoryImpl implements BuilderFactory, BuilderFactoryResult {
required int endOffset,
required Token? initializerToken,
required bool hasInitializer,
Token? constInitializerToken,
required bool isPrimaryConstructorField}) {
Token? constInitializerToken}) {
DeclarationFragmentImpl? enclosingDeclaration =
_declarationFragments.currentOrNull;
if (hasInitializer) {
@@ -1852,7 +1845,6 @@ class BuilderFactoryImpl implements BuilderFactory, BuilderFactoryResult {
type: type,
isTopLevel: isTopLevel,
modifiers: modifiers,
isPrimaryConstructorField: isPrimaryConstructorField,
enclosingScope:
enclosingDeclaration?.bodyScope ?? _compilationUnitScope,
enclosingDeclaration: enclosingDeclaration,
@@ -1861,6 +1853,27 @@ class BuilderFactoryImpl implements BuilderFactory, BuilderFactoryResult {
return fragment;
}
PrimaryConstructorFieldFragment _addPrimaryConstructorField(
{required List<MetadataBuilder>? metadata,
required TypeBuilder type,
required String name,
required int nameOffset}) {
DeclarationFragmentImpl enclosingDeclaration =
_declarationFragments.current;
PrimaryConstructorFieldFragment fragment =
new PrimaryConstructorFieldFragment(
name: name,
fileUri: _compilationUnit.fileUri,
nameOffset: nameOffset,
metadata: metadata,
type: type,
enclosingScope: enclosingDeclaration.bodyScope,
enclosingDeclaration: enclosingDeclaration,
enclosingCompilationUnit: _compilationUnit);
_addFragment(fragment);
return fragment;
}
@override
FormalParameterBuilder addFormalParameter(
List<MetadataBuilder>? metadata,
@@ -76,7 +76,7 @@ class SourceExtensionTypeDeclarationBuilder
final ExtensionTypeFragment _introductory;
FieldFragment? _representationFieldFragment;
PrimaryConstructorFieldFragment? _representationFieldFragment;
final IndexedContainer? indexedContainer;
@@ -92,7 +92,7 @@ class SourceExtensionTypeDeclarationBuilder
required int endOffset,
required ExtensionTypeFragment fragment,
required this.indexedContainer,
required FieldFragment? representationFieldFragment})
required PrimaryConstructorFieldFragment? representationFieldFragment})
: parent = enclosingLibraryBuilder,
fileOffset = nameOffset,
_modifiers = fragment.modifiers,
@@ -1045,6 +1045,7 @@ void _checkAugmentation(
case MethodFragment():
case PrimaryConstructorFragment():
case SetterFragment():
case PrimaryConstructorFieldFragment():
if (fragmentName.inLibrary) {
message = fragmentName.inPatch
? templateUnmatchedPatchLibraryMember
@@ -1102,6 +1103,7 @@ _PreBuilder _createPreBuilder(_FragmentName fragmentName) {
case PrimaryConstructorFragment():
return new _ConstructorPreBuilder(fragmentName);
case FieldFragment():
case PrimaryConstructorFieldFragment():
return new _PropertyPreBuilder.forField(fragmentName);
case GetterFragment():
return new _PropertyPreBuilder.forGetter(fragmentName);
@@ -1328,6 +1330,21 @@ void _computeBuildersFromFragments(String name, List<Fragment> fragments,
inLibrary: declarationBuilder == null,
);
addFragment(fragmentName);
case PrimaryConstructorFieldFragment():
_FragmentName fragmentName = new _FragmentName(
_FragmentKind.Property,
fragment,
fileUri: fragment.fileUri,
name: fragment.name,
nameOffset: fragment.nameOffset,
nameLength: fragment.name.length,
isAugment: false,
propertyKind: _PropertyKind.FinalField,
isStatic: false,
inPatch: fragment.enclosingDeclaration.isPatch,
inLibrary: false,
);
addFragment(fragmentName);
case GetterFragment():
_FragmentName fragmentName = new _FragmentName(
_FragmentKind.Property,
@@ -1442,6 +1459,17 @@ void _computeBuildersFromFragments(String name, List<Fragment> fragments,
containerType: containerType,
indexedContainer: indexedContainer,
containerName: containerName));
case PrimaryConstructorFieldFragment():
builders.add(_createPrimaryConstructorFieldBuilder(fragment,
problemReporting: problemReporting,
loader: loader,
enclosingLibraryBuilder: enclosingLibraryBuilder,
declarationBuilder: declarationBuilder!,
unboundNominalParameters: unboundNominalParameters,
indexedLibrary: indexedLibrary,
containerType: containerType,
indexedContainer: indexedContainer,
containerName: containerName));
case GetterFragment():
builders.add(_createGetterBuilder(fragment, augmentations,
problemReporting: problemReporting,
@@ -1768,7 +1796,7 @@ abstract class DeclarationFragmentImpl implements DeclarationFragment {
DeclarationBuilder get builder;
void addPrimaryConstructorField(FieldFragment fragment) {
void addPrimaryConstructorField(PrimaryConstructorFieldFragment fragment) {
throw new UnsupportedError(
"Unexpected primary constructor field in $this.");
}
@@ -2398,9 +2426,9 @@ _AddBuilder _createExtensionTypeBuilder(ExtensionTypeFragment fragment,
required IndexedLibrary? indexedLibrary}) {
IndexedContainer? indexedContainer =
indexedLibrary?.lookupIndexedExtensionTypeDeclaration(fragment.name);
List<FieldFragment> primaryConstructorFields =
List<PrimaryConstructorFieldFragment> primaryConstructorFields =
fragment.primaryConstructorFields;
FieldFragment? representationFieldFragment;
PrimaryConstructorFieldFragment? representationFieldFragment;
if (primaryConstructorFields.isNotEmpty) {
representationFieldFragment = primaryConstructorFields.first;
}
@@ -2468,7 +2496,7 @@ _AddBuilder _createFieldBuilder(FieldFragment fragment,
fieldIsLateWithLowering: fieldIsLateWithLowering,
isExternal: fragment.modifiers.isExternal);
FieldDeclarationImpl declaration = new FieldDeclarationImpl(fragment);
RegularFieldDeclaration declaration = new RegularFieldDeclaration(fragment);
SourcePropertyBuilder propertyBuilder = new SourcePropertyBuilder.forField(
fileUri: fragment.fileUri,
fileOffset: fragment.nameOffset,
@@ -2496,6 +2524,62 @@ _AddBuilder _createFieldBuilder(FieldFragment fragment,
fragment.enclosingCompilationUnit.isPatch);
}
_AddBuilder _createPrimaryConstructorFieldBuilder(
PrimaryConstructorFieldFragment fragment,
{required ProblemReporting problemReporting,
required SourceLoader loader,
required SourceLibraryBuilder enclosingLibraryBuilder,
required DeclarationBuilder declarationBuilder,
required List<NominalParameterBuilder> unboundNominalParameters,
required IndexedLibrary? indexedLibrary,
required ContainerType containerType,
required IndexedContainer? indexedContainer,
required ContainerName? containerName}) {
String name = fragment.name;
final bool isInstanceMember = true;
PropertyEncodingStrategy propertyEncodingStrategy =
new PropertyEncodingStrategy(declarationBuilder,
isInstanceMember: isInstanceMember);
NameScheme nameScheme = new NameScheme(
isInstanceMember: isInstanceMember,
containerName: containerName,
containerType: containerType,
libraryName: indexedLibrary != null
? new LibraryName(indexedLibrary.reference)
: enclosingLibraryBuilder.libraryName);
indexedContainer ??= indexedLibrary;
FieldReference references = new FieldReference(
name, nameScheme, indexedContainer,
fieldIsLateWithLowering: false, isExternal: false);
PrimaryConstructorFieldDeclaration declaration =
new PrimaryConstructorFieldDeclaration(fragment);
SourcePropertyBuilder propertyBuilder = new SourcePropertyBuilder.forField(
fileUri: fragment.fileUri,
fileOffset: fragment.nameOffset,
name: name,
libraryBuilder: enclosingLibraryBuilder,
declarationBuilder: declarationBuilder,
nameScheme: nameScheme,
fieldDeclaration: declaration,
getterDeclaration: declaration,
setterDeclaration: null,
modifiers: Modifiers.Final,
references: references);
fragment.builder = propertyBuilder;
declaration.createEncoding(propertyBuilder);
declaration.createGetterEncoding(problemReporting, propertyBuilder,
propertyEncodingStrategy, unboundNominalParameters);
references.registerReference(loader, propertyBuilder);
return new _AddBuilder(
fragment.name, propertyBuilder, fragment.fileUri, fragment.nameOffset,
inPatch: fragment.enclosingDeclaration.isPatch);
}
_AddBuilder _createGetterBuilder(
GetterFragment fragment, List<Fragment>? augmentations,
{required ProblemReporting problemReporting,