blob: 05c1bc494571f8c4dd3e409f3a40a4569c52cce9 [file] [log] [blame]
// 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.
library fasta.member_builder;
import 'dart:core' hide MapEntry;
import 'package:kernel/ast.dart';
import 'package:kernel/core_types.dart';
import '../../base/common.dart';
import '../kernel/class_hierarchy_builder.dart';
import '../modifier.dart';
import '../problems.dart' show unsupported;
import '../type_inference/type_inference_engine.dart'
show InferenceDataForTesting;
import 'builder.dart';
import 'class_builder.dart';
import 'declaration_builder.dart';
import 'extension_builder.dart';
import 'library_builder.dart';
import 'modifier_builder.dart';
abstract class MemberBuilder implements ModifierBuilder {
bool get isAssignable;
void set parent(Builder value);
LibraryBuilder get library;
/// The [Member] built by this builder;
Member get member;
/// The [Member] to use when reading from this member builder.
/// For a field, a getter or a regular method this is the [member] itself.
/// For an instance extension method this is special tear-off function. For
/// a constructor, an operator, a factory or a setter this is `null`.
Member get readTarget;
/// The [Member] to use when write to this member builder.
/// For an assignable field or a setter this is the [member] itself. For
/// a constructor, a non-assignable field, a getter, an operator or a regular
/// method this is `null`.
Member get writeTarget;
/// The [Member] to use when invoking this member builder.
/// For a constructor, a field, a regular method, a getter an operator or
/// a factory this is the [member] itself. For a setter this is `null`.
Member get invokeTarget;
// TODO(johnniwinther): Remove this and create a [ProcedureBuilder] interface.
ProcedureKind get kind;
bool get isExternal;
bool get isAbstract;
void buildOutlineExpressions(LibraryBuilder library, CoreTypes coreTypes);
/// Returns the [ClassMember]s for the non-setter members created for this
/// member builder.
/// This is normally the member itself, if not a setter, but for instance for
/// lowered late fields this can be synthesized members.
List<ClassMember> get localMembers;
/// Returns the [ClassMember]s for the setters created for this member
/// builder.
/// This is normally the member itself, if a setter, but for instance
/// lowered late fields this can be synthesized setters.
List<ClassMember> get localSetters;
abstract class MemberBuilderImpl extends ModifierBuilderImpl
implements MemberBuilder {
/// For top-level members, the parent is set correctly during
/// construction. However, for class members, the parent is initially the
/// library and updated later.
Builder parent;
String get name;
MemberDataForTesting dataForTesting;
MemberBuilderImpl(this.parent, int charOffset)
: dataForTesting =
retainDataForTesting ? new MemberDataForTesting() : null,
super(parent, charOffset);
bool get isDeclarationInstanceMember => isDeclarationMember && !isStatic;
bool get isClassInstanceMember => isClassMember && !isStatic;
bool get isExtensionInstanceMember => isExtensionMember && !isStatic;
bool get isDeclarationMember => parent is DeclarationBuilder;
bool get isClassMember => parent is ClassBuilder;
bool get isExtensionMember => parent is ExtensionBuilder;
bool get isTopLevel => !isDeclarationMember;
bool get isNative => false;
bool get isRedirectingGenerativeConstructor => false;
bool get isExternal => (modifiers & externalMask) != 0;
bool get isAbstract => (modifiers & abstractMask) != 0;
LibraryBuilder get library {
if (parent is LibraryBuilder) {
LibraryBuilder library = parent;
return library.partOfLibrary ?? library;
} else if (parent is ExtensionBuilder) {
ExtensionBuilder extension = parent;
return extension.library;
} else {
ClassBuilder cls = parent;
return cls.library;
// TODO(johnniwinther): Remove this and create a [ProcedureBuilder] interface.
ProcedureKind get kind => unsupported("kind", charOffset, fileUri);
void buildOutlineExpressions(LibraryBuilder library, CoreTypes coreTypes) {}
void buildMembers(
LibraryBuilder library, void Function(Member, BuiltMemberKind) f);
String get fullNameForErrors => name;
StringBuffer printOn(StringBuffer buffer) {
if (isClassMember) {
return buffer;
ClassBuilder get classBuilder => parent is ClassBuilder ? parent : null;
enum BuiltMemberKind {
class MemberDataForTesting {
final InferenceDataForTesting inferenceData = new InferenceDataForTesting();
MemberBuilder patchForTesting;
/// Base class for implementing [ClassMember] for a [MemberBuilder].
abstract class BuilderClassMember implements ClassMember {
MemberBuilderImpl get memberBuilder;
int get charOffset => memberBuilder.charOffset;
ClassBuilder get classBuilder => memberBuilder.classBuilder;
Uri get fileUri => memberBuilder.fileUri;
Name get name =>;
String get fullName {
String suffix = isSetter ? "=" : "";
String className = classBuilder?.fullNameForErrors;
return className == null
? "${fullNameForErrors}$suffix"
: "${className}.${fullNameForErrors}$suffix";
String get fullNameForErrors => memberBuilder.fullNameForErrors;
bool get isAssignable => memberBuilder.isAssignable;
bool get isConst => memberBuilder.isConst;
bool get isDuplicate => memberBuilder.isDuplicate;
bool get isField => memberBuilder.isField;
bool get isFinal => memberBuilder.isFinal;
bool get isGetter => memberBuilder.isGetter;
bool get isSetter => memberBuilder.isSetter;
bool get isStatic => memberBuilder.isStatic;
Member getMember(ClassHierarchyBuilder hierarchy) => memberBuilder.member;
bool isObjectMember(ClassBuilder objectClass) {
return classBuilder == objectClass;
bool get isAbstract => memberBuilder.member.isAbstract;
bool get needsComputation => false;
bool get isSynthesized => false;
bool get isInternalImplementation => false;
bool get isInheritableConflict => false;
ClassMember withParent(ClassBuilder classBuilder) =>
throw new UnsupportedError("$runtimeType.withParent");
bool get hasDeclarations => false;
List<ClassMember> get declarations =>
throw new UnsupportedError("$runtimeType.declarations");
ClassMember get abstract => this;
ClassMember get concrete => this;
bool operator ==(Object other) {
if (identical(this, other)) return true;
return false;
String toString() => '$runtimeType($fullName,forSetter=${forSetter})';