// Copyright (c) 2015, 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.

/// Implementation of the element model used for deserialiation.
///
/// These classes are created by [ElementDeserializer] triggered by the
/// [Deserializer].

library dart2js.serialization.modelz;

import 'serialization.dart';
import 'keys.dart';
import '../compiler.dart'
    show Compiler;
import '../constants/constructors.dart';
import '../constants/expressions.dart';
import '../diagnostics/source_span.dart'
    show SourceSpan;
import '../dart_types.dart';
import '../diagnostics/diagnostic_listener.dart';
import '../elements/elements.dart';
import '../elements/modelx.dart' show
    FunctionSignatureX;
import '../elements/common.dart';
import '../elements/visitor.dart';
import '../io/source_file.dart';
import '../ordered_typeset.dart';
import '../resolution/class_members.dart' as class_members;
import '../resolution/tree_elements.dart' show
    TreeElements;
import '../resolution/scope.dart' show
    Scope;
import '../script.dart';
import '../serialization/constant_serialization.dart';
import '../tokens/token.dart' show
    Token;
import '../tree/tree.dart';
import '../util/util.dart' show
    Link,
    LinkBuilder;

/// Compute a [Link] from an [Iterable].
Link toLink(Iterable iterable) {
  LinkBuilder builder = new LinkBuilder();
  for (var element in iterable) {
    builder.addLast(element);
  }
  return builder.toLink();
}

abstract class ElementZ extends Element with ElementCommon {
  @override
  bool get isFactoryConstructor => false;

  String toString() {
    if (enclosingElement == null || isTopLevel) return 'Z$kind($name)';
    return 'Z$kind(${enclosingElement.name}#$name)';
  }

  _unsupported(text) => throw new UnsupportedError('${this}.$text');

  @override
  AnalyzableElement get analyzableElement {
    Element element = this;
    if (element is AnalyzableElement) {
      return element;
    } else if (enclosingElement != null) {
      return enclosingElement.analyzableElement;
    }
    return null;
  }

  @override
  FunctionElement asFunctionElement() => null;

  @override
  Scope buildScope() => _unsupported('analyzableElement');

  @override
  CompilationUnitElement get compilationUnit {
    return _unsupported('compilationUnit');
  }

  @override
  ClassElement get contextClass => _unsupported('contextClass');

  @override
  ClassElement get enclosingClass => null;

  @override
  Element get enclosingClassOrCompilationUnit {
    return _unsupported('enclosingClassOrCompilationUnit');
  }

  @override
  String get fixedBackendName => _unsupported('fixedBackendName');

  @override
  bool get hasFixedBackendName => _unsupported('hasFixedBackendName');

  @override
  LibraryElement get implementationLibrary => library;

  @override
  bool get isAbstract => false;

  @override
  bool get isAssignable => _unsupported('isAssignable');

  @override
  bool get isClassMember => false;

  @override
  bool get isClosure => _unsupported('isClosure');

  @override
  bool get isConst => _unsupported('isConst');

  @override
  bool get isDeferredLoaderGetter => false;

  @override
  bool get isFinal => _unsupported('isFinal');

  @override
  bool get isInstanceMember => false;

  @override
  bool get isLocal => false;

  @override
  bool get isMixinApplication => false;

  @override
  bool get isNative => false;

  @override
  bool get isOperator => false;

  @override
  bool get isStatic => false;

  // TODO(johnniwinther): Find a more precise semantics for this.
  @override
  bool get isSynthesized => true;

  @override
  bool get isTopLevel => false;

  // TODO(johnniwinther): Support metadata.
  @override
  Iterable<MetadataAnnotation> get metadata => const <MetadataAnnotation>[];

  @override
  Element get outermostEnclosingMemberOrTopLevel {
    return _unsupported('outermostEnclosingMemberOrTopLevel');
  }

  @override
  Token get position => _unsupported('position');
}

abstract class DeserializedElementZ extends ElementZ {
  ObjectDecoder _decoder;

  DeserializedElementZ(this._decoder);

  @override
  String get name => _decoder.getString(Key.NAME);

  @override
  SourceSpan get sourcePosition {
    // TODO(johnniwinther): Should this be cached?
    int offset = _decoder.getInt(Key.OFFSET, isOptional: true);
    if (offset == null) return null;
    Uri uri = _decoder.getUri(Key.URI, isOptional: true);
    if (uri == null) {
      uri = compilationUnit.script.readableUri;
    }
    int length = _decoder.getInt(Key.LENGTH, isOptional: true);
    if (length == null) {
      length = name.length;
    }
    return new SourceSpan(uri, offset, offset + length);
  }
}

/// Deserializer for a collection of member elements serialized as a map from
/// names to element declarations.
///
/// The serialized data contains the declared getters and setters but lookup
/// into the map returns an [AbstractFieldElement] for pairs of corresponding
/// getters and setters.
///
/// The underlying map encoding allows for lazy computation of the members upon
/// query.
class MappedContainer {
  Map<String, Element> _lookupCache = {};

  Element lookup(String name, MapDecoder members) {
    if (_lookupCache.containsKey(name)) {
      Element element = _lookupCache[name];
      if (element != null) {
        return element;
      }
    }
    if (members == null) {
      return null;
    }
    bool hasId = members.containsKey(name);
    String setterName = '$name,=';
    bool hasSetterId = members.containsKey(setterName);
    Element element;
    Element setterElement;
    if (!hasId && !hasSetterId) {
      _lookupCache[name] = null;
      return null;
    }
    bool isAccessor = false;
    if (hasId) {
      element = members.getElement(name);
      isAccessor = element.isGetter;
    }
    if (hasSetterId) {
      setterElement = members.getElement(setterName);
      isAccessor = true;
    }
    if (isAccessor) {
      element = new AbstractFieldElementZ(name, element, setterElement);
    }
    _lookupCache[name] = element;
    return element;
  }
}

/// Deserializer for a collection of member elements serialized as a list of
/// element declarations.
///
/// The serialized data contains the declared getters and setters but lookup
/// into the map returns an [AbstractFieldElement] for pairs of corresponding
/// getters and setters.
///
/// The underlying list encoding requires the complete lookup map to be computed
/// before query.
class ListedContainer {
  final Map<String, Element> _lookupMap = <String, Element>{};

  ListedContainer(List<Element> elements) {
    Set<String> accessorNames = new Set<String>();
    Map<String, Element> getters = <String, Element>{};
    Map<String, Element> setters = <String, Element>{};
    for (Element element in elements) {
      String name = element.name;
      if (element.isGetter) {
        accessorNames.add(name);
        getters[name] = element;
        // Inserting [element] here to ensure insert order of [name].
        _lookupMap[name] = element;
      } else if (element.isSetter) {
        accessorNames.add(name);
        setters[name] = element;
        // Inserting [element] here to ensure insert order of [name].
        _lookupMap[name] = element;
      } else {
        _lookupMap[name] = element;
      }
    }
    for (String name in accessorNames) {
      _lookupMap[name] =
          new AbstractFieldElementZ(name, getters[name], setters[name]);
    }
  }

  Element lookup(String name) => _lookupMap[name];

  void forEach(f(Element element)) => _lookupMap.values.forEach(f);

  Iterable<Element> get values => _lookupMap.values;
}


abstract class AnalyzableElementMixin implements AnalyzableElement, ElementZ {
  @override
  bool get hasTreeElements => _unsupported('hasTreeElements');

  @override
  TreeElements get treeElements => _unsupported('treeElements');
}


abstract class AstElementMixin implements AstElement, ElementZ {
  @override
  bool get hasNode => _unsupported('hasNode');

  @override
  bool get hasResolvedAst => _unsupported('hasResolvedAst');

  @override
  get node => _unsupported('node');

  @override
  ResolvedAst get resolvedAst => _unsupported('resolvedAst');
}

abstract class ContainerMixin
    implements DeserializedElementZ, ScopeContainerElement {
  MappedContainer _membersMap = new MappedContainer();

  @override
  Element localLookup(String name) {
    return _membersMap.lookup(
        name, _decoder.getMap(Key.MEMBERS, isOptional: true));
  }

  @override
  void forEachLocalMember(f(Element element)) {
    MapDecoder members =
        _decoder.getMap(Key.MEMBERS, isOptional: true);
    if (members == null) return;
    members.forEachKey((String key) {
      Element member = members.getElement(key);
      if (member != null) {
        f(member);
      }
    });
  }
}

class AbstractFieldElementZ extends ElementZ implements AbstractFieldElement {
  final String name;
  final FunctionElement getter;
  final FunctionElement setter;

  AbstractFieldElementZ(this.name, this.getter, this.setter);

  @override
  ElementKind get kind => ElementKind.ABSTRACT_FIELD;

  @override
  accept(ElementVisitor visitor, arg) {
    return visitor.visitAbstractFieldElement(this, arg);
  }

  @override
  LibraryElement get library {
    return getter != null ? getter.library : setter.library;
  }

  @override
  Element get enclosingElement {
    return getter != null ? getter.enclosingElement : setter.enclosingElement;
  }

  @override
  SourceSpan get sourcePosition {
    return getter != null ? getter.sourcePosition : setter.sourcePosition;
  }
}

class LibraryElementZ extends DeserializedElementZ
    with AnalyzableElementMixin,
         ContainerMixin,
         LibraryElementCommon
    implements LibraryElement {
  Uri _canonicalUri;
  CompilationUnitElement _entryCompilationUnit;
  Link<CompilationUnitElement> _compilationUnits;
  List<ImportElement> _imports;
  List<ExportElement> _exports;
  ListedContainer _exportsMap;
  ListedContainer _importsMap;
  Map<LibraryTag, LibraryElement> _libraryDependencies;

  LibraryElementZ(ObjectDecoder decoder)
      : super(decoder);

  @override
  ElementKind get kind => ElementKind.LIBRARY;

  @override
  Element get enclosingElement => null;

  @override
  String get name => entryCompilationUnit.name;

  @override
  accept(ElementVisitor visitor, arg) {
    return visitor.visitLibraryElement(this, arg);
  }

  @override
  LibraryElement get library => this;

  @override
  Uri get canonicalUri {
    if (_canonicalUri == null) {
      _canonicalUri = _decoder.getUri(Key.CANONICAL_URI);
    }
    return _canonicalUri;
  }

  @override
  CompilationUnitElement get entryCompilationUnit {
    if (_entryCompilationUnit == null) {
      _entryCompilationUnit = _decoder.getElement(Key.COMPILATION_UNIT);
    }
    return _entryCompilationUnit;
  }

  @override
  Link<CompilationUnitElement> get compilationUnits {
    if (_compilationUnits == null) {
      _compilationUnits =
          toLink(_decoder.getElements(Key.COMPILATION_UNITS));
    }
    return _compilationUnits;
  }

  @override
  bool get hasLibraryName {
    return libraryName != '';
  }

  @override
  String get libraryName {
    return _decoder.getString(Key.LIBRARY_NAME);
  }

  @override
  bool get exportsHandled => true;

  void _ensureExports() {
    if (_exportsMap == null) {
      _exportsMap = new ListedContainer(_decoder.getElements(Key.EXPORT_SCOPE));
    }
  }

  @override
  void forEachExport(f(Element element)) {
    _ensureExports();
    _exportsMap.forEach(f);
  }

  @override
  Element find(String elementName) {
    Element element = localLookup(elementName);
    if (element == null) {
      _ensureImports();
      element = _importsMap.lookup(elementName);
    }
    return element;
  }

  @override
  Element findLocal(String elementName) {
    return localLookup(elementName);
  }

  @override
  bool get canUseNative => false;

  @override
  Element findExported(String elementName) => _unsupported('findExported');

  void _ensureImports() {
    if (_importsMap == null) {
      _importsMap = new ListedContainer(_decoder.getElements(Key.IMPORT_SCOPE));
    }
  }

  @override
  void forEachImport(f(Element element)) {
    _ensureImports();
    _importsMap.forEach(f);
  }

  @override
  Iterable<ImportElement> getImportsFor(Element element) {
    return _unsupported('getImportsFor');
  }

  String toString() {
    return 'Zlibrary(${canonicalUri})';
  }

  @override
  Iterable<ExportElement> get exports {
    if (_exports == null) {
      _exports = _decoder.getElements(Key.EXPORTS, isOptional: true);
    }
    return _exports;
  }

  @override
  Iterable<ImportElement> get imports {
    if (_imports == null) {
      _imports = _decoder.getElements(Key.IMPORTS, isOptional: true);
    }
    return _imports;
  }
}

class ScriptZ implements Script {
  final Uri resourceUri;

  ScriptZ(this.resourceUri);

  @override
  Script copyWithFile(SourceFile file) {
    throw new UnsupportedError('ScriptZ.copyWithFile');
  }

  @override
  SourceFile get file => throw new UnsupportedError('ScriptZ.file');

  @override
  bool get isSynthesized => throw new UnsupportedError('ScriptZ.isSynthesized');

  @override
  String get name => resourceUri.toString();

  // TODO(johnniwinther): Support the distinction between [readableUri] and
  // [resourceUri]; needed for platform libraries.
  @override
  Uri get readableUri => resourceUri;

  @override
  String get text => throw new UnsupportedError('ScriptZ.text');
}

class CompilationUnitElementZ extends DeserializedElementZ
    with LibraryMemberMixin,
         CompilationUnitElementCommon
    implements CompilationUnitElement {
  List<Element> _members;
  Script _script;

  CompilationUnitElementZ(ObjectDecoder decoder)
      : super(decoder);

  @override
  ElementKind get kind => ElementKind.COMPILATION_UNIT;

  @override
  CompilationUnitElement get compilationUnit => this;

  @override
  accept(ElementVisitor visitor, arg) {
    return visitor.visitCompilationUnitElement(this, arg);
  }

  @override
  void forEachLocalMember(f(Element element)) {
    if (_members == null) {
      _members =
          _decoder.getElements(Key.ELEMENTS, isOptional: true);
    }
    _members.forEach(f);
  }

  @override
  Script get script {
    if (_script == null) {
      Uri resolvedUri = _decoder.getUri(Key.URI);
      _script = new ScriptZ(resolvedUri);
    }
    return _script;
  }

  @override
  String get name => script.name;
}


abstract class LibraryMemberMixin implements DeserializedElementZ {
  LibraryElement _library;
  CompilationUnitElement _compilationUnit;

  @override
  LibraryElement get library {
    if (_library == null) {
      _library = _decoder.getElement(Key.LIBRARY);
    }
    return _library;
  }

  @override
  CompilationUnitElement get compilationUnit {
    if (_compilationUnit == null) {
      _compilationUnit = _decoder.getElement(Key.COMPILATION_UNIT);
    }
    return _compilationUnit;
  }

  @override
  Element get enclosingElement => compilationUnit;

  @override
  ClassElement get enclosingClass => null;

  @override
  bool get isTopLevel => true;

  @override
  bool get isStatic => false;
}

abstract class ClassMemberMixin implements DeserializedElementZ {
  ClassElement _class;

  @override
  Element get enclosingElement => enclosingClass;

  @override
  ClassElement get enclosingClass {
    if (_class == null) {
      _class = _decoder.getElement(Key.CLASS);
    }
    return _class;
  }

  @override
  bool get isClassMember => true;

  @override
  LibraryElement get library => enclosingClass.library;

  @override
  CompilationUnitElement get compilationUnit => enclosingClass.compilationUnit;
}

abstract class InstanceMemberMixin implements DeserializedElementZ {
  @override
  bool get isTopLevel => false;

  @override
  bool get isStatic => false;

  @override
  bool get isInstanceMember => true;
}

abstract class StaticMemberMixin implements DeserializedElementZ {
  @override
  bool get isTopLevel => false;

  @override
  bool get isStatic => true;
}

abstract class TypedElementMixin
    implements DeserializedElementZ, TypedElement {
  DartType _type;

  @override
  DartType get type {
    if (_type == null) {
      _type = _decoder.getType(Key.TYPE);
    }
    return _type;
  }

  @override
  DartType computeType(Compiler compiler) => type;
}

abstract class ParametersMixin
    implements DeserializedElementZ, FunctionTypedElement {
  FunctionSignature _functionSignature;
  List<ParameterElement> _parameters;

  bool get hasFunctionSignature => true;

  @override
  FunctionSignature get functionSignature {
    if (_functionSignature == null) {
      List<Element> requiredParameters = [];
      List<Element> optionalParameters = [];
      List orderedOptionalParameters = [];
      int requiredParameterCount = 0;
      int optionalParameterCount = 0;
      bool optionalParametersAreNamed = false;
      List<DartType> parameterTypes = <DartType>[];
      List<DartType> optionalParameterTypes = <DartType>[];
      List<String> namedParameters = <String>[];
      List<DartType> namedParameterTypes = <DartType>[];
      for (ParameterElement parameter in parameters) {
        if (parameter.isOptional) {
          optionalParameterCount++;
          requiredParameters.add(parameter);
          orderedOptionalParameters.add(parameter);
          if (parameter.isNamed) {
            optionalParametersAreNamed = true;
            namedParameters.add(parameter.name);
            namedParameterTypes.add(parameter.type);
          } else {
            optionalParameterTypes.add(parameter.type);
          }
        } else {
          requiredParameterCount++;
          optionalParameters.add(parameter);
          parameterTypes.add(parameter.type);
        }
      }
      if (optionalParametersAreNamed) {
        orderedOptionalParameters.sort((Element a, Element b) {
            return a.name.compareTo(b.name);
        });
      }

      FunctionType type = new FunctionType(
          this,
          _decoder.getType(Key.RETURN_TYPE),
          parameterTypes,
          optionalParameterTypes,
          namedParameters,
          namedParameterTypes);
      _functionSignature = new FunctionSignatureX(
          requiredParameters: requiredParameters,
          requiredParameterCount: requiredParameterCount,
          optionalParameters: optionalParameters,
          optionalParameterCount: optionalParameterCount,
          optionalParametersAreNamed: optionalParametersAreNamed,
          orderedOptionalParameters: orderedOptionalParameters,
          type: type);
    }
    return _functionSignature;
  }

  List<ParameterElement> get parameters {
    if (_parameters == null) {
      _parameters = _decoder.getElements(Key.PARAMETERS, isOptional: true);
    }
    return _parameters;
  }
}

abstract class FunctionTypedElementMixin
    implements FunctionElement, DeserializedElementZ {
  @override
  AsyncMarker get asyncMarker => _unsupported('');

  @override
  bool get isExternal => _unsupported('');

  @override
  FunctionElement asFunctionElement() => this;
}

class ClassElementZ extends DeserializedElementZ
    with AnalyzableElementMixin,
         AstElementMixin,
         ClassElementCommon,
         class_members.ClassMemberMixin,
         ContainerMixin,
         LibraryMemberMixin,
         TypeDeclarationMixin<InterfaceType>
    implements ClassElement {
  bool _isObject;
  DartType _supertype;
  OrderedTypeSet _allSupertypesAndSelf;
  Link<DartType> _interfaces;

  ClassElementZ(ObjectDecoder decoder)
      : super(decoder);

  InterfaceType _createType(List<DartType> typeArguments) {
    return new InterfaceType(this, typeArguments);
  }

  @override
  ElementKind get kind => ElementKind.CLASS;

  @override
  accept(ElementVisitor visitor, arg) {
    return visitor.visitClassElement(this, arg);
  }

  @override
  DartType get supertype {
    if (_isObject == null) {
      _supertype = _decoder.getType(Key.SUPERTYPE, isOptional: true);
      _isObject = _supertype == null;
    }
    return _supertype;
  }

  @override
  bool get isAbstract => _decoder.getBool(Key.IS_ABSTRACT);

  @override
  bool get isObject {
    return supertype == null;
  }

  @override
  void addBackendMember(Element element) => _unsupported('addBackendMember');

  @override
  OrderedTypeSet get allSupertypesAndSelf {
    if (_allSupertypesAndSelf == null) {
      ObjectDecoder supertypesDeserializer =
          _decoder.getObject(Key.SUPERTYPES);
      List<int> offsets = supertypesDeserializer.getInts(Key.OFFSETS);
      List<Link<DartType>> levels = new List<Link<DartType>>(offsets.length);
      LinkBuilder<DartType> typesBuilder = new LinkBuilder<DartType>();
      int offset = 0;
      int depth = offsets.length - 1;
      for (DartType type in supertypesDeserializer.getTypes(Key.TYPES)) {
        Link<DartType> link = typesBuilder.addLast(type);
        if (offsets[depth] == offset) {
          levels[depth] = link;
          depth--;
        }
        offset++;
      }
      LinkBuilder<DartType> supertypesBuilder = new LinkBuilder<DartType>();
      for (DartType supertype in
          supertypesDeserializer.getTypes(Key.SUPERTYPES, isOptional: true)) {
        supertypesBuilder.addLast(supertype);
      }
      Link<DartType> types = typesBuilder.toLink();
      Link<DartType> supertypes = supertypesBuilder.toLink();
      _allSupertypesAndSelf = new OrderedTypeSet.internal(
          levels, types, supertypes);
    }
    return _allSupertypesAndSelf;
  }

  @override
  void forEachBackendMember(void f(Element member)) {
    _unsupported('forEachBackendMember');
  }

  @override
  bool get hasBackendMembers => _unsupported('hasBackendMembers');

  @override
  bool get hasConstructor => _unsupported('hasConstructor');

  @override
  bool hasFieldShadowedBy(Element fieldMember) => _unsupported('');

  @override
  bool get hasIncompleteHierarchy => _unsupported('hasIncompleteHierarchy');

  @override
  bool get hasLocalScopeMembers => _unsupported('hasLocalScopeMembers');

  @override
  bool implementsFunction(Compiler compiler) {
    return _unsupported('implementsFunction');
  }

  @override
  Link<DartType> get interfaces {
    if (_interfaces == null) {
      _interfaces = toLink(
          _decoder.getTypes(Key.INTERFACES, isOptional: true));
    }
    return _interfaces;
  }

  @override
  bool get isEnumClass => false;

  @override
  bool get isProxy => _unsupported('isProxy');

  @override
  bool get isUnnamedMixinApplication {
    return _unsupported('isUnnamedMixinApplication');
  }

  @override
  Element lookupBackendMember(String memberName) {
    return _unsupported('lookupBackendMember');
  }

  @override
  ConstructorElement lookupDefaultConstructor() {
    ConstructorElement constructor = lookupConstructor("");
    if (constructor != null && constructor.parameters.isEmpty) {
      return constructor;
    }
    return null;
  }

  @override
  String get nativeTagInfo => _unsupported('nativeTagInfo');

  @override
  void reverseBackendMembers() => _unsupported('reverseBackendMembers');

  @override
  ClassElement get superclass => supertype != null ? supertype.element : null;

  @override
  void ensureResolved(Compiler compiler) {
    compiler.world.registerClass(this);
  }
}

abstract class ConstructorElementZ extends DeserializedElementZ
    with AnalyzableElementMixin,
         AstElementMixin,
         ClassMemberMixin,
         FunctionTypedElementMixin,
         ParametersMixin,
         TypedElementMixin,
         MemberElementMixin
    implements ConstructorElement {
  ConstantConstructor _constantConstructor;

  ConstructorElementZ(ObjectDecoder decoder)
      : super(decoder);

  accept(ElementVisitor visitor, arg) {
    return visitor.visitConstructorElement(this, arg);
  }

  @override
  bool get isConst => _decoder.getBool(Key.IS_CONST);

  @override
  bool get isExternal => _decoder.getBool(Key.IS_EXTERNAL);

  bool get isFromEnvironmentConstructor {
    return name == 'fromEnvironment' &&
           library.isDartCore &&
           (enclosingClass.name == 'bool' ||
            enclosingClass.name == 'int' ||
            enclosingClass.name == 'String');
  }

  ConstantConstructor get constantConstructor {
    if (isConst && _constantConstructor == null) {
      ObjectDecoder data =
          _decoder.getObject(Key.CONSTRUCTOR, isOptional: true);
      if (data == null) {
        assert(isFromEnvironmentConstructor || isExternal);
        return null;
      }
      _constantConstructor = ConstantConstructorDeserializer.deserialize(data);
    }
    return _constantConstructor;
  }

  @override
  AsyncMarker get asyncMarker => _unsupported('asyncMarker');

  @override
  InterfaceType computeEffectiveTargetType(InterfaceType newType) {
    return _unsupported('computeEffectiveTargetType');
  }

  @override
  ConstructorElement get definingConstructor  {
    return _unsupported('definingConstructor');
  }

  @override
  ConstructorElement get effectiveTarget  {
    return _unsupported('effectiveTarget');
  }

  @override
  ConstructorElement get immediateRedirectionTarget  {
    return _unsupported('immediateRedirectionTarget');
  }

  @override
  bool get isRedirectingFactory => _unsupported('isRedirectingFactory');

  @override
  bool get isRedirectingGenerative => _unsupported('isRedirectingGenerative');

  @override
  bool get isCyclicRedirection => _unsupported('isCyclicRedirection');

  @override
  PrefixElement get redirectionDeferredPrefix  {
    return _unsupported('redirectionDeferredPrefix');
  }
}

class GenerativeConstructorElementZ extends ConstructorElementZ {
  GenerativeConstructorElementZ(ObjectDecoder decoder)
      : super(decoder);

  @override
  ElementKind get kind => ElementKind.GENERATIVE_CONSTRUCTOR;
}

class FactoryConstructorElementZ extends ConstructorElementZ {

  FactoryConstructorElementZ(ObjectDecoder decoder)
      : super(decoder);

  @override
  ElementKind get kind => ElementKind.FUNCTION;

  @override
  bool get isFactoryConstructor => true;
}

abstract class MemberElementMixin
    implements DeserializedElementZ, MemberElement {

  @override
  MemberElement get memberContext => this;

  @override
  Name get memberName => new Name(name, library);

  @override
  List<FunctionElement> get nestedClosures => const <FunctionElement>[];

}

abstract class FieldElementZ extends DeserializedElementZ
    with AnalyzableElementMixin,
         AstElementMixin,
         TypedElementMixin,
         MemberElementMixin
    implements FieldElement {
  ConstantExpression _constant;

  FieldElementZ(ObjectDecoder decoder)
      : super(decoder);

  @override
  ElementKind get kind => ElementKind.FIELD;

  @override
  accept(ElementVisitor visitor, arg) {
    return visitor.visitFieldElement(this, arg);
  }

  @override
  bool get isFinal => _decoder.getBool(Key.IS_FINAL);

  @override
  bool get isConst => _decoder.getBool(Key.IS_CONST);

  @override
  ConstantExpression get constant {
    if (isConst && _constant == null) {
      _constant = _decoder.getConstant(Key.CONSTANT);
    }
    return _constant;
  }

  @override
  Expression get initializer => _unsupported('initializer');
}


class TopLevelFieldElementZ extends FieldElementZ with LibraryMemberMixin {
  TopLevelFieldElementZ(ObjectDecoder decoder)
      : super(decoder);
}

class StaticFieldElementZ extends FieldElementZ
    with ClassMemberMixin, StaticMemberMixin {
  StaticFieldElementZ(ObjectDecoder decoder)
      : super(decoder);
}

class InstanceFieldElementZ extends FieldElementZ
    with ClassMemberMixin, InstanceMemberMixin {
  InstanceFieldElementZ(ObjectDecoder decoder)
      : super(decoder);
}

abstract class FunctionElementZ extends DeserializedElementZ
    with AnalyzableElementMixin,
         AstElementMixin,
         ParametersMixin,
         FunctionTypedElementMixin,
         TypedElementMixin,
         MemberElementMixin
    implements MethodElement {
  FunctionElementZ(ObjectDecoder decoder)
      : super(decoder);

  @override
  ElementKind get kind => ElementKind.FUNCTION;

  @override
  accept(ElementVisitor visitor, arg) {
    return visitor.visitFunctionElement(this, arg);
  }

  @override
  bool get isOperator => _decoder.getBool(Key.IS_OPERATOR);
}

class TopLevelFunctionElementZ extends FunctionElementZ
    with LibraryMemberMixin {
  TopLevelFunctionElementZ(ObjectDecoder decoder)
      : super(decoder);
}

class StaticFunctionElementZ extends FunctionElementZ
    with ClassMemberMixin, StaticMemberMixin {
  StaticFunctionElementZ(ObjectDecoder decoder)
      : super(decoder);
}

class InstanceFunctionElementZ extends FunctionElementZ
    with ClassMemberMixin, InstanceMemberMixin {
  InstanceFunctionElementZ(ObjectDecoder decoder)
      : super(decoder);
}

abstract class GetterElementZ extends DeserializedElementZ
    with AnalyzableElementMixin,
         AstElementMixin,
         FunctionTypedElementMixin,
         ParametersMixin,
         TypedElementMixin,
         MemberElementMixin
    implements FunctionElement {

  GetterElementZ(ObjectDecoder decoder)
      : super(decoder);

  @override
  ElementKind get kind => ElementKind.GETTER;

  @override
  accept(ElementVisitor visitor, arg) {
    return visitor.visitFunctionElement(this, arg);
  }
}

class TopLevelGetterElementZ extends GetterElementZ with LibraryMemberMixin {
  TopLevelGetterElementZ(ObjectDecoder decoder)
      : super(decoder);
}

class StaticGetterElementZ extends GetterElementZ
    with ClassMemberMixin, StaticMemberMixin {
  StaticGetterElementZ(ObjectDecoder decoder)
      : super(decoder);
}

class InstanceGetterElementZ extends GetterElementZ
    with ClassMemberMixin, InstanceMemberMixin {
  InstanceGetterElementZ(ObjectDecoder decoder)
      : super(decoder);
}

abstract class SetterElementZ extends DeserializedElementZ
    with AnalyzableElementMixin,
         AstElementMixin,
         FunctionTypedElementMixin,
         ParametersMixin,
         TypedElementMixin,
         MemberElementMixin
    implements FunctionElement {

  SetterElementZ(ObjectDecoder decoder)
      : super(decoder);

  @override
  ElementKind get kind => ElementKind.SETTER;

  @override
  accept(ElementVisitor visitor, arg) {
    return visitor.visitFunctionElement(this, arg);
  }
}

class TopLevelSetterElementZ extends SetterElementZ with LibraryMemberMixin {
  TopLevelSetterElementZ(ObjectDecoder decoder)
      : super(decoder);
}

class StaticSetterElementZ extends SetterElementZ
    with ClassMemberMixin, StaticMemberMixin {
  StaticSetterElementZ(ObjectDecoder decoder)
      : super(decoder);
}

class InstanceSetterElementZ extends SetterElementZ
    with ClassMemberMixin, InstanceMemberMixin {
  InstanceSetterElementZ(ObjectDecoder decoder)
      : super(decoder);
}

abstract class TypeDeclarationMixin<T extends GenericType>
    implements DeserializedElementZ, TypeDeclarationElement {
  List<DartType> _typeVariables;
  T _rawType;
  T _thisType;
  Name _memberName;

  Name get memberName {
    if (_memberName == null) {
      _memberName = new Name(name, library);
    }
    return _memberName;
  }

  void _ensureTypes() {
    if (_typeVariables == null) {
      _typeVariables = _decoder.getTypes(
          Key.TYPE_VARIABLES, isOptional: true);
      _rawType = _createType(new List<DartType>.filled(
          _typeVariables.length, const DynamicType()));
      _thisType = _createType(_typeVariables);
    }
  }

  T _createType(List<DartType> typeArguments);

  @override
  List<DartType> get typeVariables {
    _ensureTypes();
    return _typeVariables;
  }

  @override
  T get rawType {
    _ensureTypes();
    return _rawType;
  }

  @override
  T get thisType {
    _ensureTypes();
    return _thisType;
  }

  @override
  T computeType(Compiler compiler) => thisType;

  @override
  bool get isResolved => true;
}

class TypedefElementZ extends DeserializedElementZ
    with AnalyzableElementMixin,
         AstElementMixin,
         LibraryMemberMixin,
         ParametersMixin,
         TypeDeclarationMixin<TypedefType>
    implements TypedefElement {
  DartType _alias;

  TypedefElementZ(ObjectDecoder decoder)
      : super(decoder);

  TypedefType _createType(List<DartType> typeArguments) {
    return new TypedefType(this, typeArguments);
  }

  @override
  ElementKind get kind => ElementKind.TYPEDEF;

  @override
  accept(ElementVisitor visitor, arg) {
    return visitor.visitTypedefElement(this, arg);
  }

  @override
  DartType get alias {
    if (_alias == null) {
      _alias = _decoder.getType(Key.ALIAS);
    }
    return _alias;
  }

  @override
  void ensureResolved(Compiler compiler) {}

  @override
  void checkCyclicReference(Compiler compiler) {}
}

class TypeVariableElementZ extends DeserializedElementZ
    with AnalyzableElementMixin,
         AstElementMixin,
         TypedElementMixin
    implements TypeVariableElement {
  TypeDeclarationElement _typeDeclaration;
  TypeVariableType _type;
  DartType _bound;
  Name _memberName;

  TypeVariableElementZ(ObjectDecoder decoder)
      : super(decoder);

  Name get memberName {
    if (_memberName == null) {
      _memberName = new Name(name, library);
    }
    return _memberName;
  }

  @override
  ElementKind get kind => ElementKind.TYPE_VARIABLE;

  @override
  accept(ElementVisitor visitor, arg) {
    return visitor.visitTypeVariableElement(this, arg);
  }

  @override
  CompilationUnitElement get compilationUnit {
    return typeDeclaration.compilationUnit;
  }

  @override
  Element get enclosingElement => typeDeclaration;

  @override
  Element get enclosingClass => typeDeclaration;

  @override
  int get index => _decoder.getInt(Key.INDEX);

  @override
  TypeDeclarationElement get typeDeclaration {
    if (_typeDeclaration == null) {
      _typeDeclaration =
          _decoder.getElement(Key.TYPE_DECLARATION);
    }
    return _typeDeclaration;
  }

  DartType get bound {
    if (_bound == null) {
      _bound = _decoder.getType(Key.BOUND);
    }
    return _bound;
  }

  @override
  LibraryElement get library => typeDeclaration.library;
}

class ParameterElementZ extends DeserializedElementZ
    with AnalyzableElementMixin,
         AstElementMixin,
         TypedElementMixin
    implements ParameterElement {
  FunctionElement _functionDeclaration;
  ConstantExpression _constant;
  DartType _type;

  ParameterElementZ(ObjectDecoder decoder) : super(decoder);

  @override
  accept(ElementVisitor visitor, arg) {
    return visitor.visitParameterElement(this, arg);
  }

  @override
  ConstantExpression get constant {
    if (isOptional) {
      if (_constant == null) {
        _constant = _decoder.getConstant(Key.CONSTANT);
      }
      return _constant;
    }
    return null;
  }

  @override
  CompilationUnitElement get compilationUnit {
    return functionDeclaration.compilationUnit;
  }

  @override
  ExecutableElement get executableContext => functionDeclaration;

  @override
  Element get enclosingElement => functionDeclaration;

  @override
  FunctionElement get functionDeclaration {
    if (_functionDeclaration == null) {
      _functionDeclaration = _decoder.getElement(Key.FUNCTION);
    }
    return _functionDeclaration;
  }

  @override
  FunctionSignature get functionSignature => _unsupported('functionSignature');

  @override
  Expression get initializer => _unsupported('initializer');

  @override
  bool get isNamed => _decoder.getBool(Key.IS_NAMED);

  @override
  bool get isOptional => _decoder.getBool(Key.IS_OPTIONAL);

  @override
  ElementKind get kind => ElementKind.PARAMETER;

  @override
  LibraryElement get library => executableContext.library;

  @override
  MemberElement get memberContext => executableContext.memberContext;
}

class InitializingFormalElementZ extends ParameterElementZ
    implements InitializingFormalElement {
  FieldElement _fieldElement;

  InitializingFormalElementZ(ObjectDecoder decoder)
      : super(decoder);

  @override
  FieldElement get fieldElement {
    if (_fieldElement == null) {
      _fieldElement = _decoder.getElement(Key.FIELD);
    }
    return _fieldElement;
  }

  @override
  accept(ElementVisitor visitor, arg) {
    return visitor.visitFieldParameterElement(this, arg);
  }

  @override
  ElementKind get kind => ElementKind.INITIALIZING_FORMAL;
}

class ImportElementZ extends DeserializedElementZ
    with LibraryMemberMixin implements ImportElement {
  bool _isDeferred;
  PrefixElement _prefix;
  LibraryElement _importedLibrary;
  Uri _uri;

  ImportElementZ(ObjectDecoder decoder)
      : super(decoder);

  @override
  String get name => '';

  @override
  accept(ElementVisitor visitor, arg) => visitor.visitImportElement(this, arg);

  @override
  ElementKind get kind => ElementKind.IMPORT;

  @override
  LibraryElement get importedLibrary {
    if (_importedLibrary == null) {
      _importedLibrary = _decoder.getElement(Key.LIBRARY_DEPENDENCY);
    }
    return _importedLibrary;
  }

  void _ensurePrefixResolved() {
    if (_isDeferred == null) {
      _isDeferred = _decoder.getBool(Key.IS_DEFERRED);
      _prefix = _decoder.getElement(Key.PREFIX, isOptional: true);
    }
  }

  @override
  bool get isDeferred {
    _ensurePrefixResolved();
    return _isDeferred;
  }

  @override
  PrefixElement get prefix {
    _ensurePrefixResolved();
    return _prefix;
  }

  @override
  Uri get uri {
    if (_uri == null) {
      _uri = _decoder.getUri(Key.URI);
    }
    return _uri;
  }

  @override
  Import get node => _unsupported('node');

  String toString() => 'Z$kind($uri)';
}

class ExportElementZ extends DeserializedElementZ
    with LibraryMemberMixin implements ExportElement {
  LibraryElement _exportedLibrary;
  Uri _uri;

  ExportElementZ(ObjectDecoder decoder)
      : super(decoder);

  @override
  String get name => '';

  @override
  accept(ElementVisitor visitor, arg) => visitor.visitExportElement(this, arg);

  @override
  ElementKind get kind => ElementKind.EXPORT;

  @override
  LibraryElement get exportedLibrary {
    if (_exportedLibrary == null) {
      _exportedLibrary = _decoder.getElement(Key.LIBRARY_DEPENDENCY);
    }
    return _exportedLibrary;
  }

  @override
  Uri get uri {
    if (_uri == null) {
      _uri = _decoder.getUri(Key.URI);
    }
    return _uri;
  }

  @override
  Export get node => _unsupported('node');

  String toString() => 'Z$kind($uri)';
}

class PrefixElementZ extends DeserializedElementZ
    with LibraryMemberMixin implements PrefixElement {
  bool _isDeferred;
  ImportElement _deferredImport;

  PrefixElementZ(ObjectDecoder decoder)
      : super(decoder);

  @override
  accept(ElementVisitor visitor, arg) => visitor.visitPrefixElement(this, arg);

  void _ensureDeferred() {
    if (_isDeferred == null) {
      _isDeferred = _decoder.getBool(Key.IS_DEFERRED);
      _deferredImport = _decoder.getElement(Key.IMPORT, isOptional: true);
    }
  }

  @override
  ImportElement get deferredImport {
    _ensureDeferred();
    return _deferredImport;
  }

  @override
  bool get isDeferred {
    _ensureDeferred();
    return _isDeferred;
  }

  @override
  ElementKind get kind => ElementKind.PREFIX;

  @override
  Element lookupLocalMember(String memberName) {
    return _unsupported('lookupLocalMember');
  }
}