| // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| import 'package:_fe_analyzer_shared/src/metadata/expressions.dart' as shared; |
| import 'package:_fe_analyzer_shared/src/parser/formal_parameter_kind.dart'; |
| import 'package:front_end/src/base/messages.dart'; |
| import 'package:front_end/src/builder/property_builder.dart'; |
| import 'package:front_end/src/fragment/method/encoding.dart'; |
| import 'package:front_end/src/source/source_method_builder.dart'; |
| import 'package:kernel/ast.dart'; |
| import 'package:kernel/class_hierarchy.dart'; |
| import 'package:kernel/reference_from_index.dart' show IndexedClass; |
| import 'package:kernel/src/bounds_checks.dart'; |
| import 'package:kernel/transformations/flags.dart'; |
| import 'package:kernel/type_environment.dart'; |
| |
| import '../base/modifiers.dart' show Modifiers; |
| import '../base/scope.dart'; |
| import '../base/uri_offset.dart'; |
| import '../builder/builder.dart'; |
| import '../builder/constructor_builder.dart'; |
| import '../builder/declaration_builders.dart'; |
| import '../builder/factory_builder.dart'; |
| import '../builder/formal_parameter_builder.dart'; |
| import '../builder/library_builder.dart'; |
| import '../builder/member_builder.dart'; |
| import '../builder/metadata_builder.dart'; |
| import '../builder/method_builder.dart'; |
| import '../builder/named_type_builder.dart'; |
| import '../builder/nullability_builder.dart'; |
| import '../builder/type_builder.dart'; |
| import '../fragment/constructor/declaration.dart'; |
| import '../fragment/field/declaration.dart'; |
| import '../fragment/fragment.dart'; |
| import '../fragment/getter/declaration.dart'; |
| import '../fragment/method/declaration.dart'; |
| import '../kernel/body_builder_context.dart'; |
| import '../kernel/constructor_tearoff_lowering.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 '../kernel/utils.dart'; |
| import 'name_scheme.dart'; |
| import 'source_class_builder.dart' show SourceClassBuilder; |
| import 'source_constructor_builder.dart'; |
| import 'source_library_builder.dart' show SourceLibraryBuilder; |
| import 'source_member_builder.dart'; |
| import 'source_property_builder.dart'; |
| import 'source_type_parameter_builder.dart'; |
| import 'type_parameter_scope_builder.dart'; |
| |
| class SourceEnumBuilder extends SourceClassBuilder { |
| final int startOffset; |
| final int endOffset; |
| |
| final ClassDeclaration _introductory; |
| |
| final List<EnumElementFragment> _enumElements; |
| |
| final TypeBuilder _underscoreEnumTypeBuilder; |
| |
| late final NamedTypeBuilder objectType; |
| |
| late final NamedTypeBuilder listType; |
| |
| late final NamedTypeBuilder selfType; |
| |
| SourceConstructorBuilderImpl? _synthesizedDefaultConstructorBuilder; |
| |
| late final _EnumValuesFieldDeclaration _enumValuesFieldDeclaration; |
| |
| SourceEnumBuilder.internal( |
| {required String name, |
| required List<SourceNominalParameterBuilder>? typeParameters, |
| required TypeBuilder underscoreEnumTypeBuilder, |
| required LookupScope typeParameterScope, |
| required DeclarationNameSpaceBuilder nameSpaceBuilder, |
| required List<EnumElementFragment> enumElements, |
| required SourceLibraryBuilder libraryBuilder, |
| required Uri fileUri, |
| required this.startOffset, |
| required int nameOffset, |
| required this.endOffset, |
| required IndexedClass? indexedClass, |
| required ClassDeclaration classDeclaration}) |
| : _underscoreEnumTypeBuilder = underscoreEnumTypeBuilder, |
| _introductory = classDeclaration, |
| _enumElements = enumElements, |
| super( |
| modifiers: Modifiers.empty, |
| name: name, |
| typeParameters: typeParameters, |
| typeParameterScope: typeParameterScope, |
| nameSpaceBuilder: nameSpaceBuilder, |
| libraryBuilder: libraryBuilder, |
| fileUri: fileUri, |
| nameOffset: nameOffset, |
| indexedClass: indexedClass, |
| introductory: classDeclaration); |
| |
| factory SourceEnumBuilder( |
| {required String name, |
| required List<SourceNominalParameterBuilder>? typeParameters, |
| required TypeBuilder underscoreEnumTypeBuilder, |
| required List<TypeBuilder>? interfaceBuilders, |
| required List<EnumElementFragment> enumElements, |
| required SourceLibraryBuilder libraryBuilder, |
| required Uri fileUri, |
| required int startOffset, |
| required int nameOffset, |
| required int endOffset, |
| required IndexedClass? indexedClass, |
| required LookupScope typeParameterScope, |
| required DeclarationNameSpaceBuilder nameSpaceBuilder, |
| required ClassDeclaration classDeclaration}) { |
| SourceEnumBuilder enumBuilder = new SourceEnumBuilder.internal( |
| name: name, |
| typeParameters: typeParameters, |
| underscoreEnumTypeBuilder: underscoreEnumTypeBuilder, |
| typeParameterScope: typeParameterScope, |
| nameSpaceBuilder: nameSpaceBuilder, |
| enumElements: enumElements, |
| libraryBuilder: libraryBuilder, |
| fileUri: fileUri, |
| startOffset: startOffset, |
| nameOffset: nameOffset, |
| endOffset: endOffset, |
| indexedClass: indexedClass, |
| classDeclaration: classDeclaration); |
| return enumBuilder; |
| } |
| |
| @override |
| void buildScopes(LibraryBuilder coreLibrary) { |
| super.buildScopes(coreLibrary); |
| _createSynthesizedMembers(coreLibrary); |
| |
| Iterator<ConstructorBuilder> constructorIterator = |
| filteredConstructorsIterator(includeDuplicates: false); |
| while (constructorIterator.moveNext()) { |
| ConstructorBuilder constructorBuilder = constructorIterator.current; |
| if (!constructorBuilder.isConst) { |
| libraryBuilder.addProblem(messageEnumNonConstConstructor, |
| constructorBuilder.fileOffset, noLength, fileUri); |
| } |
| } |
| } |
| |
| void _createSynthesizedMembers(LibraryBuilder coreLibrary) { |
| // TODO(ahe): These types shouldn't be looked up in scope, they come |
| // directly from dart:core. |
| objectType = new NamedTypeBuilderImpl( |
| const PredefinedTypeName("Object"), const NullabilityBuilder.omitted(), |
| instanceTypeParameterAccess: |
| InstanceTypeParameterAccessState.Unexpected); |
| selfType = new NamedTypeBuilderImpl(new SyntheticTypeName(name, fileOffset), |
| const NullabilityBuilder.omitted(), |
| instanceTypeParameterAccess: |
| InstanceTypeParameterAccessState.Unexpected, |
| fileUri: fileUri, |
| charOffset: fileOffset); |
| listType = new NamedTypeBuilderImpl( |
| const PredefinedTypeName("List"), const NullabilityBuilder.omitted(), |
| arguments: <TypeBuilder>[selfType], |
| instanceTypeParameterAccess: |
| InstanceTypeParameterAccessState.Unexpected); |
| |
| // metadata class E extends _Enum { |
| // const E(int index, String name) : super(index, name); |
| // static const E id0 = const E(0, 'id0'); |
| // ... |
| // static const E id${n-1} = const E(n - 1, 'idn-1'); |
| // static const List<E> values = const <E>[id0, ..., id${n-1}]; |
| // String _enumToString() { |
| // return "E.${_Enum::_name}"; |
| // } |
| // } |
| |
| LibraryName libraryName = indexedClass != null |
| ? new LibraryName(indexedClass!.library.reference) |
| : libraryBuilder.libraryName; |
| |
| NameScheme staticFieldNameScheme = new NameScheme( |
| isInstanceMember: false, |
| containerName: new ClassName(name), |
| containerType: ContainerType.Class, |
| libraryName: libraryName); |
| |
| Reference? constructorReference; |
| Reference? tearOffReference; |
| Reference? toStringReference; |
| if (indexedClass != null) { |
| constructorReference = |
| indexedClass!.lookupConstructorReference(new Name("")); |
| tearOffReference = indexedClass!.lookupGetterReference( |
| new Name(constructorTearOffName(""), indexedClass!.library)); |
| toStringReference = indexedClass!.lookupGetterReference( |
| new Name("_enumToString", coreLibrary.library)); |
| } |
| |
| PropertyReferences valuesReferences = new PropertyReferences( |
| "values", staticFieldNameScheme, indexedClass, |
| fieldIsLateWithLowering: false); |
| |
| NamedBuilder? customValuesDeclaration = |
| nameSpace.lookupLocalMember("values")?.getable; |
| if (customValuesDeclaration != null) { |
| // Retrieve the earliest declaration for error reporting. |
| while (customValuesDeclaration?.next != null) { |
| customValuesDeclaration = customValuesDeclaration?.next; |
| } |
| libraryBuilder.addProblem( |
| messageEnumContainsValuesDeclaration, |
| customValuesDeclaration!.fileOffset, |
| customValuesDeclaration.fullNameForErrors.length, |
| fileUri); |
| } |
| |
| for (String restrictedInstanceMemberName in const [ |
| "index", |
| "hashCode", |
| "==" |
| ]) { |
| NamedBuilder? customIndexDeclaration = |
| nameSpace.lookupLocalMember(restrictedInstanceMemberName)?.getable; |
| NamedBuilder? invalidDeclaration; |
| if (customIndexDeclaration is PropertyBuilder && |
| !customIndexDeclaration.hasAbstractGetter && |
| !customIndexDeclaration.isEnumElement) { |
| invalidDeclaration = customIndexDeclaration; |
| } else if (customIndexDeclaration is MethodBuilder && |
| !customIndexDeclaration.isAbstract) { |
| invalidDeclaration = customIndexDeclaration; |
| } |
| if (invalidDeclaration != null) { |
| // Retrieve the earliest declaration for error reporting. |
| while (customIndexDeclaration?.next != null) { |
| // Coverage-ignore-block(suite): Not run. |
| customIndexDeclaration = customIndexDeclaration?.next; |
| } |
| libraryBuilder.addProblem( |
| templateEnumContainsRestrictedInstanceDeclaration |
| .withArguments(restrictedInstanceMemberName), |
| customIndexDeclaration!.fileOffset, |
| customIndexDeclaration.fullNameForErrors.length, |
| fileUri); |
| } |
| } |
| |
| _enumValuesFieldDeclaration = |
| new _EnumValuesFieldDeclaration(this, listType); |
| |
| SourcePropertyBuilder valuesBuilder = new SourcePropertyBuilder( |
| fileUri: fileUri, |
| fileOffset: fileOffset, |
| name: "values", |
| libraryBuilder: libraryBuilder, |
| declarationBuilder: this, |
| nameScheme: staticFieldNameScheme, |
| fieldDeclaration: _enumValuesFieldDeclaration, |
| getterDeclaration: _enumValuesFieldDeclaration, |
| getterAugmentations: const [], |
| setterDeclaration: null, |
| setterAugmentations: const [], |
| references: valuesReferences, |
| isStatic: true); |
| _enumValuesFieldDeclaration.builder = valuesBuilder; |
| |
| if (customValuesDeclaration != null) { |
| customValuesDeclaration.next = valuesBuilder; |
| nameSpaceBuilder.checkTypeParameterConflict(libraryBuilder, |
| valuesBuilder.name, valuesBuilder, valuesBuilder.fileUri); |
| addMemberInternal(valuesBuilder, addToNameSpace: false); |
| } else { |
| addMemberInternal(valuesBuilder, addToNameSpace: true); |
| nameSpaceBuilder.checkTypeParameterConflict(libraryBuilder, |
| valuesBuilder.name, valuesBuilder, valuesBuilder.fileUri); |
| } |
| |
| // The default constructor is added if no generative or unnamed factory |
| // constructors are declared. |
| bool needsSynthesizedDefaultConstructor = true; |
| Iterator<MemberBuilder> iterator = unfilteredConstructorsIterator; |
| while (iterator.moveNext()) { |
| MemberBuilder constructorBuilder = iterator.current; |
| if (constructorBuilder is! FactoryBuilder || |
| constructorBuilder.name == "") { |
| needsSynthesizedDefaultConstructor = false; |
| break; |
| } |
| } |
| if (needsSynthesizedDefaultConstructor) { |
| FormalParameterBuilder nameFormalParameterBuilder = |
| new FormalParameterBuilder( |
| FormalParameterKind.requiredPositional, |
| Modifiers.empty, |
| libraryBuilder.loader.target.stringType, |
| "#name", |
| fileOffset, |
| fileUri: fileUri, |
| hasImmediatelyDeclaredInitializer: false); |
| |
| FormalParameterBuilder indexFormalParameterBuilder = |
| new FormalParameterBuilder( |
| FormalParameterKind.requiredPositional, |
| Modifiers.empty, |
| libraryBuilder.loader.target.intType, |
| "#index", |
| fileOffset, |
| fileUri: fileUri, |
| hasImmediatelyDeclaredInitializer: false); |
| |
| ConstructorDeclaration constructorDeclaration = |
| new DefaultEnumConstructorDeclaration( |
| returnType: |
| libraryBuilder.loader.inferableTypes.addInferableType(), |
| formals: [ |
| indexFormalParameterBuilder, |
| nameFormalParameterBuilder |
| ], |
| fileUri: fileUri, |
| fileOffset: fileOffset, |
| lookupScope: _introductory.compilationUnitScope); |
| SourceConstructorBuilderImpl constructorBuilder = |
| _synthesizedDefaultConstructorBuilder = |
| new SourceConstructorBuilderImpl( |
| modifiers: Modifiers.Const, |
| name: "", |
| libraryBuilder: libraryBuilder, |
| declarationBuilder: this, |
| fileUri: fileUri, |
| fileOffset: fileOffset, |
| constructorReference: constructorReference, |
| tearOffReference: tearOffReference, |
| nameScheme: new NameScheme( |
| isInstanceMember: false, |
| containerName: new ClassName(name), |
| containerType: ContainerType.Class, |
| libraryName: libraryName), |
| introductory: constructorDeclaration); |
| constructorBuilder.registerInitializedField(valuesBuilder); |
| addConstructorInternal(constructorBuilder, addToNameSpace: true); |
| nameSpaceBuilder.checkTypeParameterConflict( |
| libraryBuilder, |
| _synthesizedDefaultConstructorBuilder!.name, |
| _synthesizedDefaultConstructorBuilder!, |
| _synthesizedDefaultConstructorBuilder!.fileUri); |
| } |
| |
| SourceMethodBuilder toStringBuilder = new SourceMethodBuilder( |
| name: "_enumToString", |
| fileUri: fileUri, |
| fileOffset: fileOffset, |
| libraryBuilder: libraryBuilder, |
| declarationBuilder: this, |
| nameScheme: new NameScheme( |
| isInstanceMember: true, |
| containerName: new ClassName(name), |
| containerType: ContainerType.Class, |
| libraryName: new LibraryName(coreLibrary.library.reference)), |
| introductory: new _EnumToStringMethodDeclaration(this, |
| libraryBuilder.loader.target.stringType, _underscoreEnumTypeBuilder, |
| fileUri: fileUri, fileOffset: fileOffset), |
| augmentations: const [], |
| isStatic: false, |
| modifiers: Modifiers.empty, |
| reference: toStringReference, |
| tearOffReference: null); |
| addMemberInternal(toStringBuilder, addToNameSpace: true); |
| nameSpaceBuilder.checkTypeParameterConflict(libraryBuilder, |
| toStringBuilder.name, toStringBuilder, toStringBuilder.fileUri); |
| |
| selfType.bind(libraryBuilder, this); |
| |
| if (name == "values") { |
| libraryBuilder.addProblem( |
| messageEnumWithNameValues, this.fileOffset, name.length, fileUri); |
| } |
| } |
| |
| @override |
| bool get isEnum => true; |
| |
| @override |
| TypeBuilder? get mixedInTypeBuilder => null; |
| |
| @override |
| Class build(LibraryBuilder coreLibrary) { |
| int elementIndex = 0; |
| for (EnumElementFragment enumElement in _enumElements) { |
| if (!enumElement.builder.isDuplicate) { |
| enumElement.declaration.elementIndex = elementIndex++; |
| } else { |
| enumElement.declaration.elementIndex = -1; |
| } |
| } |
| |
| bindCoreType(coreLibrary, objectType); |
| bindCoreType(coreLibrary, listType); |
| |
| Class cls = super.build(coreLibrary); |
| cls.isEnum = true; |
| |
| // The super initializer for the synthesized default constructor is |
| // inserted here if the enum's supertype is _Enum to preserve the legacy |
| // behavior or having the old-style enum constants built in the outlines. |
| // Other constructors are handled in [BodyBuilder.finishConstructor] as |
| // they are processed via the pipeline for constructor parsing and |
| // building. |
| if (identical(this.supertypeBuilder, _underscoreEnumTypeBuilder)) { |
| if (_synthesizedDefaultConstructorBuilder != null) { |
| Constructor constructor = |
| _synthesizedDefaultConstructorBuilder!.invokeTarget as Constructor; |
| ClassBuilder objectClass = objectType.declaration as ClassBuilder; |
| ClassBuilder enumClass = |
| _underscoreEnumTypeBuilder.declaration as ClassBuilder; |
| MemberBuilder? superConstructor = enumClass.findConstructorOrFactory( |
| "", fileOffset, fileUri, libraryBuilder); |
| if (superConstructor == null || |
| superConstructor is! ConstructorBuilder) { |
| // Coverage-ignore-block(suite): Not run. |
| // TODO(ahe): Ideally, we would also want to check that [Object]'s |
| // unnamed constructor requires no arguments. But that information |
| // isn't always available at this point, and it's not really a |
| // situation that can happen unless you start modifying the SDK |
| // sources. (We should add a correct message. We no longer depend on |
| // Object here.) |
| libraryBuilder.addProblem( |
| messageNoUnnamedConstructorInObject, |
| objectClass.fileOffset, |
| objectClass.name.length, |
| objectClass.fileUri); |
| } else { |
| constructor.initializers.add(new SuperInitializer( |
| superConstructor.invokeTarget as Constructor, |
| new Arguments.forwarded( |
| constructor.function, libraryBuilder.library)) |
| ..parent = constructor); |
| } |
| _synthesizedDefaultConstructorBuilder = null; |
| } |
| } |
| |
| return cls; |
| } |
| |
| @override |
| BodyBuilderContext createBodyBuilderContext() { |
| return new EnumBodyBuilderContext(this); |
| } |
| |
| @override |
| void buildOutlineExpressions(ClassHierarchy classHierarchy, |
| List<DelayedDefaultValueCloner> delayedDefaultValueCloners) { |
| for (EnumElementFragment enumElement in _enumElements) { |
| enumElement.declaration.inferType(classHierarchy); |
| } |
| _enumValuesFieldDeclaration.inferType(classHierarchy); |
| |
| super.buildOutlineExpressions(classHierarchy, delayedDefaultValueCloners); |
| } |
| } |
| |
| class _EnumToStringMethodDeclaration implements MethodDeclaration { |
| static const String _enumToStringName = "_enumToString"; |
| |
| final SourceEnumBuilder _enumBuilder; |
| final TypeBuilder _stringTypeBuilder; |
| final TypeBuilder _underscoreEnumTypeBuilder; |
| |
| final Uri _fileUri; |
| final int _fileOffset; |
| late final Procedure _procedure; |
| |
| _EnumToStringMethodDeclaration(this._enumBuilder, this._stringTypeBuilder, |
| this._underscoreEnumTypeBuilder, |
| {required Uri fileUri, required int fileOffset}) |
| : _fileUri = fileUri, |
| _fileOffset = fileOffset; |
| |
| @override |
| UriOffsetLength get uriOffset => new UriOffset(_fileUri, _fileOffset); |
| |
| @override |
| void buildOutlineExpressions( |
| {required ClassHierarchy classHierarchy, |
| required SourceLibraryBuilder libraryBuilder, |
| required DeclarationBuilder? declarationBuilder, |
| required SourceMethodBuilder methodBuilder, |
| required Annotatable annotatable, |
| required Uri annotatableFileUri, |
| required bool isClassInstanceMember}) { |
| Name toStringName = |
| new Name(_enumToStringName, classHierarchy.coreTypes.coreLibrary); |
| Member? superToString = _enumBuilder.cls.superclass != null |
| ? classHierarchy.getDispatchTarget( |
| _enumBuilder.cls.superclass!, toStringName) |
| : null; |
| Procedure? toStringSuperTarget = superToString is Procedure && |
| // Coverage-ignore(suite): Not run. |
| superToString.enclosingClass != classHierarchy.coreTypes.objectClass |
| ? superToString |
| : null; |
| |
| if (toStringSuperTarget != null) { |
| // Coverage-ignore-block(suite): Not run. |
| _procedure.transformerFlags |= TransformerFlag.superCalls; |
| _procedure.function.body = new ReturnStatement(new SuperMethodInvocation( |
| toStringName, new Arguments([]), toStringSuperTarget)) |
| ..parent = _procedure.function; |
| } else { |
| ClassBuilder enumClass = |
| _underscoreEnumTypeBuilder.declaration as ClassBuilder; |
| MemberBuilder? nameFieldBuilder = |
| enumClass.lookupLocalMember("_name") as MemberBuilder?; |
| assert(nameFieldBuilder != null); |
| Field nameField = nameFieldBuilder!.readTarget as Field; |
| |
| _procedure.function.body = new ReturnStatement(new StringConcatenation([ |
| new StringLiteral("${_enumBuilder.cls.demangledName}."), |
| new InstanceGet.byReference( |
| InstanceAccessKind.Instance, new ThisExpression(), nameField.name, |
| interfaceTargetReference: nameField.getterReference, |
| resultType: nameField.getterType), |
| ])) |
| ..parent = _procedure.function; |
| } |
| } |
| |
| @override |
| void buildOutlineNode(SourceLibraryBuilder libraryBuilder, |
| NameScheme nameScheme, BuildNodesCallback f, |
| {required Reference reference, |
| required Reference? tearOffReference, |
| required List<TypeParameter>? classTypeParameters}) { |
| FunctionNode function = new FunctionNode( |
| new EmptyStatement()..fileOffset = _fileOffset, |
| returnType: |
| _stringTypeBuilder.build(libraryBuilder, TypeUse.returnType)) |
| ..fileOffset = _fileOffset |
| ..fileEndOffset = _fileOffset; |
| _procedure = new Procedure( |
| nameScheme.getDeclaredName(_enumToStringName).name, |
| ProcedureKind.Method, |
| function, |
| fileUri: fileUri, |
| reference: reference) |
| ..fileOffset = _fileOffset |
| ..fileEndOffset = _fileOffset |
| ..transformerFlags |= TransformerFlag.superCalls; |
| f(kind: BuiltMemberKind.Method, member: _procedure); |
| } |
| |
| @override |
| void checkTypes( |
| SourceLibraryBuilder libraryBuilder, TypeEnvironment typeEnvironment) {} |
| |
| @override |
| void checkVariance( |
| SourceClassBuilder sourceClassBuilder, TypeEnvironment typeEnvironment) {} |
| |
| @override |
| int computeDefaultTypes(ComputeDefaultTypeContext context) { |
| return 0; |
| } |
| |
| @override |
| void createEncoding( |
| ProblemReporting problemReporting, |
| SourceMethodBuilder builder, |
| MethodEncodingStrategy encodingStrategy, |
| List<NominalParameterBuilder> unboundNominalParameters) { |
| throw new UnsupportedError("$runtimeType.createEncoding"); |
| } |
| |
| @override |
| void ensureTypes( |
| ClassMembersBuilder membersBuilder, |
| SourceClassBuilder enclosingClassBuilder, |
| Set<ClassMember>? overrideDependencies) {} |
| |
| @override |
| Uri get fileUri => _fileUri; |
| |
| @override |
| Procedure get invokeTarget => _procedure; |
| |
| @override |
| bool get isOperator => false; |
| |
| @override |
| // Coverage-ignore(suite): Not run. |
| List<MetadataBuilder>? get metadata => null; |
| |
| @override |
| Procedure? get readTarget => null; |
| } |
| |
| class _EnumValuesFieldDeclaration |
| implements FieldDeclaration, GetterDeclaration { |
| static const String name = "values"; |
| |
| final SourceEnumBuilder _sourceEnumBuilder; |
| |
| SourcePropertyBuilder? _builder; |
| |
| DartType _type = const DynamicType(); |
| |
| Field? _field; |
| |
| final TypeBuilder _typeBuilder; |
| |
| _EnumValuesFieldDeclaration(this._sourceEnumBuilder, this._typeBuilder); |
| |
| @override |
| UriOffsetLength get uriOffset => |
| new UriOffset(_sourceEnumBuilder.fileUri, _sourceEnumBuilder.fileOffset); |
| |
| 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; |
| } |
| |
| @override |
| // Coverage-ignore(suite): Not run. |
| void createFieldEncoding(SourcePropertyBuilder builder) {} |
| |
| @override |
| Initializer buildErroneousInitializer(Expression effect, Expression value, |
| {required int fileOffset}) { |
| throw new UnsupportedError('${runtimeType}.buildErroneousInitializer'); |
| } |
| |
| @override |
| void buildImplicitDefaultValue() { |
| throw new UnsupportedError('${runtimeType}.buildImplicitDefaultValue'); |
| } |
| |
| @override |
| Initializer buildImplicitInitializer() { |
| throw new UnsupportedError('${runtimeType}.buildImplicitInitializer'); |
| } |
| |
| @override |
| List<Initializer> buildInitializer(int fileOffset, Expression value, |
| {required bool isSynthetic}) { |
| throw new UnsupportedError('${runtimeType}.buildInitializer'); |
| } |
| |
| @override |
| void buildFieldOutlineExpressions( |
| {required ClassHierarchy classHierarchy, |
| required SourceLibraryBuilder libraryBuilder, |
| required DeclarationBuilder? declarationBuilder, |
| required List<Annotatable> annotatables, |
| required Uri annotatablesFileUri, |
| required bool isClassInstanceMember}) { |
| List<Expression> values = <Expression>[]; |
| for (EnumElementFragment enumElement in _sourceEnumBuilder._enumElements) { |
| enumElement.declaration.inferType(classHierarchy); |
| if (!enumElement.builder.isDuplicate) { |
| values.add(new StaticGet(enumElement.declaration.readTarget)); |
| } |
| } |
| |
| _field!.initializer = new ListLiteral(values, |
| typeArgument: instantiateToBounds( |
| _sourceEnumBuilder.rawType(Nullability.nonNullable), |
| classHierarchy.coreTypes.objectClass), |
| isConst: true) |
| ..parent = _field; |
| } |
| |
| @override |
| void buildFieldOutlineNode( |
| SourceLibraryBuilder libraryBuilder, |
| NameScheme nameScheme, |
| BuildNodesCallback f, |
| PropertyReferences references, |
| {required List<TypeParameter>? classTypeParameters}) { |
| fieldType = _typeBuilder.build(libraryBuilder, TypeUse.fieldType); |
| _field = new Field.immutable(dummyName, |
| type: _type, |
| isFinal: false, |
| isConst: true, |
| isStatic: true, |
| fileUri: builder.fileUri, |
| fieldReference: references.fieldReference, |
| getterReference: references.getterReference, |
| isEnumElement: false) |
| ..fileOffset = builder.fileOffset |
| ..fileEndOffset = builder.fileOffset; |
| nameScheme |
| .getFieldMemberName(FieldNameType.Field, name, isSynthesized: false) |
| .attachMember(_field!); |
| f(member: _field!, kind: BuiltMemberKind.Field); |
| } |
| |
| @override |
| void checkFieldTypes(SourceLibraryBuilder libraryBuilder, |
| TypeEnvironment typeEnvironment, SourcePropertyBuilder? setterBuilder) {} |
| |
| @override |
| // Coverage-ignore(suite): Not run. |
| void checkFieldVariance( |
| SourceClassBuilder sourceClassBuilder, TypeEnvironment typeEnvironment) {} |
| |
| @override |
| int computeFieldDefaultTypes(ComputeDefaultTypeContext context) { |
| return 0; |
| } |
| |
| @override |
| // Coverage-ignore(suite): Not run. |
| void ensureTypes( |
| ClassMembersBuilder membersBuilder, |
| Set<ClassMember>? getterOverrideDependencies, |
| Set<ClassMember>? setterOverrideDependencies) { |
| inferType(membersBuilder.hierarchyBuilder); |
| } |
| |
| @override |
| bool get hasInitializer => true; |
| |
| @override |
| // Coverage-ignore(suite): Not run. |
| bool get hasSetter => false; |
| |
| @override |
| // Coverage-ignore(suite): Not run. |
| shared.Expression? get initializerExpression => null; |
| |
| @override |
| // Coverage-ignore(suite): Not run. |
| bool get isEnumElement => false; |
| |
| @override |
| // Coverage-ignore(suite): Not run. |
| bool get isExtensionTypeDeclaredInstanceField => false; |
| |
| @override |
| // Coverage-ignore(suite): Not run. |
| bool get isFinal => false; |
| |
| @override |
| // Coverage-ignore(suite): Not run. |
| bool get isLate => false; |
| |
| @override |
| // Coverage-ignore(suite): Not run. |
| bool get isConst => true; |
| |
| @override |
| List<ClassMember> get localMembers => |
| [new _EnumValuesClassMember(builder, uriOffset)]; |
| |
| @override |
| // Coverage-ignore(suite): Not run. |
| List<MetadataBuilder>? get metadata => null; |
| |
| @override |
| Member get readTarget => _field!; |
| |
| @override |
| // Coverage-ignore(suite): Not run. |
| DartType get fieldType => _type; |
| |
| @override |
| void set fieldType(DartType value) { |
| _type = value; |
| _field |
| // Coverage-ignore(suite): Not run. |
| ?.type = value; |
| } |
| |
| @override |
| DartType inferType(ClassHierarchyBase hierarchy) { |
| return _type; |
| } |
| |
| @override |
| FieldQuality get fieldQuality => FieldQuality.Concrete; |
| |
| @override |
| GetterQuality get getterQuality => GetterQuality.Implicit; |
| |
| @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 |
| // Coverage-ignore(suite): Not run. |
| void checkGetterVariance( |
| SourceClassBuilder sourceClassBuilder, TypeEnvironment typeEnvironment) {} |
| |
| @override |
| int computeGetterDefaultTypes(ComputeDefaultTypeContext context) { |
| return 0; |
| } |
| |
| @override |
| // Coverage-ignore(suite): Not run. |
| void createGetterEncoding( |
| ProblemReporting problemReporting, |
| SourcePropertyBuilder builder, |
| PropertyEncodingStrategy encodingStrategy, |
| List<NominalParameterBuilder> unboundNominalParameters) {} |
| |
| @override |
| // Coverage-ignore(suite): Not run. |
| void ensureGetterTypes( |
| {required SourceLibraryBuilder libraryBuilder, |
| required DeclarationBuilder? declarationBuilder, |
| required ClassMembersBuilder membersBuilder, |
| required Set<ClassMember>? getterOverrideDependencies}) {} |
| |
| @override |
| // Coverage-ignore(suite): Not run. |
| Uri get fileUri => _sourceEnumBuilder.fileUri; |
| |
| @override |
| // Coverage-ignore(suite): Not run. |
| Iterable<Reference> getExportedGetterReferences( |
| PropertyReferences references) { |
| return [references.getterReference!]; |
| } |
| } |
| |
| class _EnumValuesClassMember implements ClassMember { |
| final SourcePropertyBuilder _builder; |
| |
| @override |
| final UriOffsetLength uriOffset; |
| |
| Covariance? _covariance; |
| |
| _EnumValuesClassMember(this._builder, this.uriOffset); |
| |
| @override |
| bool get forSetter => false; |
| |
| @override |
| DeclarationBuilder get declarationBuilder => _builder.declarationBuilder!; |
| |
| @override |
| // Coverage-ignore(suite): Not run. |
| List<ClassMember> get declarations => |
| throw new UnsupportedError('$runtimeType.declarations'); |
| |
| @override |
| // Coverage-ignore(suite): Not run. |
| String get fullName { |
| String className = declarationBuilder.fullNameForErrors; |
| return "${className}.${fullNameForErrors}"; |
| } |
| |
| @override |
| // Coverage-ignore(suite): Not run. |
| String get fullNameForErrors => _builder.fullNameForErrors; |
| |
| @override |
| // Coverage-ignore(suite): Not run. |
| Covariance getCovariance(ClassMembersBuilder membersBuilder) { |
| return _covariance ??= forSetter |
| ? new Covariance.fromMember(getMember(membersBuilder), |
| forSetter: forSetter) |
| : const Covariance.empty(); |
| } |
| |
| @override |
| Member getMember(ClassMembersBuilder membersBuilder) { |
| inferType(membersBuilder); |
| return forSetter |
| ? |
| // Coverage-ignore(suite): Not run. |
| _builder.writeTarget! |
| : _builder.readTarget!; |
| } |
| |
| @override |
| // Coverage-ignore(suite): Not run. |
| MemberResult getMemberResult(ClassMembersBuilder membersBuilder) { |
| return new StaticMemberResult(getMember(membersBuilder), memberKind, |
| isDeclaredAsField: true, |
| fullName: '${declarationBuilder.name}.${_builder.memberName.text}'); |
| } |
| |
| @override |
| // Coverage-ignore(suite): Not run. |
| Member? getTearOff(ClassMembersBuilder membersBuilder) => null; |
| |
| @override |
| bool get hasDeclarations => false; |
| |
| @override |
| void inferType(ClassMembersBuilder membersBuilder) { |
| _builder.inferFieldType(membersBuilder.hierarchyBuilder); |
| } |
| |
| @override |
| ClassMember get interfaceMember => this; |
| |
| @override |
| bool get isAbstract => false; |
| |
| @override |
| bool get isDuplicate => _builder.isDuplicate; |
| |
| @override |
| // Coverage-ignore(suite): Not run. |
| bool get isExtensionTypeMember => _builder.isExtensionTypeMember; |
| |
| @override |
| // Coverage-ignore(suite): Not run. |
| 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 _EnumValuesClassMember && |
| // Coverage-ignore(suite): Not run. |
| _builder == other._builder; |
| } |
| |
| @override |
| // Coverage-ignore(suite): Not run. |
| bool get isSetter => false; |
| |
| @override |
| // Coverage-ignore(suite): Not run. |
| bool get isSourceDeclaration => true; |
| |
| @override |
| bool get isStatic => true; |
| |
| @override |
| bool get isSynthesized => true; |
| |
| @override |
| // Coverage-ignore(suite): Not run. |
| ClassMemberKind get memberKind => ClassMemberKind.Getter; |
| |
| @override |
| Name get name => _builder.memberName; |
| |
| @override |
| // Coverage-ignore(suite): Not run. |
| void registerOverrideDependency( |
| ClassMembersBuilder membersBuilder, Set<ClassMember> overriddenMembers) { |
| _builder.registerGetterOverrideDependency( |
| membersBuilder, overriddenMembers); |
| } |
| |
| @override |
| String toString() => '$runtimeType($fullName)'; |
| } |