// Copyright (c) 2017, 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 dart2js.resolution_strategy;

import 'package:front_end/src/fasta/scanner.dart' show Token;

import '../../compiler_new.dart' as api;
import '../common.dart';
import '../common/backend_api.dart';
import '../common/names.dart';
import '../common/resolution.dart';
import '../common/tasks.dart';
import '../common/work.dart';
import '../common_elements.dart';
import '../compiler.dart';
import '../constants/expressions.dart' show ConstantExpression;
import '../constants/values.dart';
import '../deferred_load.dart' show DeferredLoadTask;
import '../elements/elements.dart';
import '../elements/entities.dart';
import '../elements/modelx.dart';
import '../elements/resolution_types.dart';
import '../elements/types.dart';
import '../enqueue.dart';
import '../environment.dart';
import '../frontend_strategy.dart';
import '../js_backend/backend.dart';
import '../js_backend/backend_usage.dart';
import '../js_backend/interceptor_data.dart';
import '../js_backend/mirrors_analysis.dart';
import '../js_backend/mirrors_data.dart';
import '../js_backend/native_data.dart';
import '../js_backend/no_such_method_registry.dart';
import '../js_backend/runtime_types.dart';
import '../library_loader.dart';
import '../native/enqueue.dart' show NativeResolutionEnqueuer;
import '../native/resolver.dart';
import '../patch_parser.dart';
import '../resolved_uri_translator.dart';
import '../tree/tree.dart' show Node;
import '../universe/call_structure.dart';
import '../universe/class_hierarchy_builder.dart';
import '../universe/use.dart';
import '../universe/world_builder.dart';
import '../universe/world_impact.dart';

import 'deferred_load.dart';
import 'no_such_method_resolver.dart';

/// [FrontendStrategy] that loads '.dart' files and creates a resolved element
/// model using the resolver.
class ResolutionFrontEndStrategy extends FrontendStrategyBase
    with ComputeSpannableMixin {
  final Compiler _compiler;
  final _CompilerElementEnvironment _elementEnvironment;
  final CommonElements commonElements;
  RuntimeTypesNeedBuilder _runtimeTypesNeedBuilder;

  AnnotationProcessor _annotationProcessor;

  factory ResolutionFrontEndStrategy(Compiler compiler) {
    ElementEnvironment elementEnvironment =
        new _CompilerElementEnvironment(compiler);
    CommonElements commonElements = new CommonElements(elementEnvironment);
    return new ResolutionFrontEndStrategy.internal(
        compiler, elementEnvironment, commonElements);
  }

  ResolutionFrontEndStrategy.internal(
      this._compiler, this._elementEnvironment, this.commonElements);

  ElementEnvironment get elementEnvironment => _elementEnvironment;

  DartTypes get dartTypes => _compiler.resolution.types;

  LibraryLoaderTask createLibraryLoader(
      ResolvedUriTranslator uriTranslator,
      ScriptLoader scriptLoader,
      api.CompilerInput compilerInput,
      ElementScanner scriptScanner,
      PatchResolverFunction patchResolverFunc,
      PatchParserTask patchParser,
      Environment environment,
      DiagnosticReporter reporter,
      Measurer measurer) {
    return new ResolutionLibraryLoaderTask(
        uriTranslator,
        scriptLoader,
        scriptScanner,
        patchResolverFunc,
        patchParser,
        environment,
        reporter,
        measurer);
  }

  AnnotationProcessor get annotationProcesser => _annotationProcessor ??=
      new _ElementAnnotationProcessor(_compiler, nativeBasicDataBuilder);

  DeferredLoadTask createDeferredLoadTask(Compiler compiler) =>
      new AstDeferredLoadTask(_compiler);

  @override
  NativeClassFinder createNativeClassFinder(NativeBasicData nativeBasicData) {
    return new ResolutionNativeClassFinder(
        _compiler.resolution,
        _compiler.reporter,
        elementEnvironment,
        commonElements,
        nativeBasicData);
  }

  NoSuchMethodResolver createNoSuchMethodResolver() =>
      new ResolutionNoSuchMethodResolver();

  MirrorsDataBuilder createMirrorsDataBuilder() {
    return new ResolutionMirrorsData(
        _compiler, elementEnvironment, commonElements);
  }

  MirrorsResolutionAnalysis createMirrorsResolutionAnalysis(
          JavaScriptBackend backend) =>
      new MirrorsResolutionAnalysisImpl(backend, _compiler.resolution);

  RuntimeTypesNeedBuilder createRuntimeTypesNeedBuilder() {
    return _runtimeTypesNeedBuilder ??= _compiler.options.disableRtiOptimization
        ? const TrivialRuntimeTypesNeedBuilder()
        : new ResolutionRuntimeTypesNeedBuilderImpl(
            elementEnvironment, dartTypes);
  }

  RuntimeTypesNeedBuilder get runtimeTypesNeedBuilderForTesting =>
      _runtimeTypesNeedBuilder;

  ResolutionWorldBuilder createResolutionWorldBuilder(
      NativeBasicData nativeBasicData,
      NativeDataBuilder nativeDataBuilder,
      InterceptorDataBuilder interceptorDataBuilder,
      BackendUsageBuilder backendUsageBuilder,
      RuntimeTypesNeedBuilder rtiNeedBuilder,
      NativeResolutionEnqueuer nativeResolutionEnqueuer,
      NoSuchMethodRegistry noSuchMethodRegistry,
      SelectorConstraintsStrategy selectorConstraintsStrategy,
      ClassHierarchyBuilder classHierarchyBuilder,
      ClassQueries classQueries) {
    return new ElementResolutionWorldBuilder(
        _compiler.backend,
        _compiler.resolution,
        nativeBasicData,
        nativeDataBuilder,
        interceptorDataBuilder,
        backendUsageBuilder,
        rtiNeedBuilder,
        nativeResolutionEnqueuer,
        noSuchMethodRegistry,
        selectorConstraintsStrategy,
        classHierarchyBuilder,
        classQueries);
  }

  WorkItemBuilder createResolutionWorkItemBuilder(
      NativeBasicData nativeBasicData,
      NativeDataBuilder nativeDataBuilder,
      ImpactTransformer impactTransformer,
      Map<Entity, WorldImpact> impactCache) {
    return new ResolutionWorkItemBuilder(_compiler.resolution);
  }

  ClassQueries createClassQueries() {
    return new ElementClassQueries(commonElements);
  }

  FunctionEntity computeMain(
      covariant LibraryElement mainApp, WorldImpactBuilder impactBuilder) {
    _elementEnvironment._mainLibrary = mainApp;
    if (mainApp == null) return null;
    MethodElement mainFunction;
    Element main = mainApp.findExported(Identifiers.main);
    ErroneousElement errorElement = null;
    if (main == null) {
      if (_compiler.options.analyzeOnly) {
        if (!_compiler.analyzeAll) {
          errorElement = new ErroneousElementX(MessageKind.CONSIDER_ANALYZE_ALL,
              {'main': Identifiers.main}, Identifiers.main, mainApp);
        }
      } else {
        // Compilation requires a main method.
        errorElement = new ErroneousElementX(MessageKind.MISSING_MAIN,
            {'main': Identifiers.main}, Identifiers.main, mainApp);
      }
      mainFunction = commonElements.missingMain;
    } else if (main.isError && main.isSynthesized) {
      if (main is ErroneousElement) {
        errorElement = main;
      } else {
        _compiler.reporter
            .internalError(main, 'Problem with ${Identifiers.main}.');
      }
      mainFunction = commonElements.badMain;
    } else if (!main.isFunction) {
      errorElement = new ErroneousElementX(MessageKind.MAIN_NOT_A_FUNCTION,
          {'main': Identifiers.main}, Identifiers.main, main);
      mainFunction = commonElements.badMain;
    } else {
      mainFunction = main;
      mainFunction.computeType(_compiler.resolution);
      FunctionSignature parameters = mainFunction.functionSignature;
      if (parameters.requiredParameterCount > 2) {
        int index = 0;
        parameters.orderedForEachParameter((Element parameter) {
          if (index++ < 2) return;
          errorElement = new ErroneousElementX(
              MessageKind.MAIN_WITH_EXTRA_PARAMETER,
              {'main': Identifiers.main},
              Identifiers.main,
              parameter);
          // Don't warn about main not being used:
          impactBuilder.registerStaticUse(
              new StaticUse.staticInvoke(mainFunction, CallStructure.NO_ARGS));

          mainFunction = commonElements.mainHasTooManyParameters;
        });
      }
    }
    if (mainFunction == null) {
      if (errorElement == null &&
          !_compiler.options.analyzeOnly &&
          !_compiler.analyzeAll) {
        _compiler.reporter
            .internalError(mainApp, "Problem with '${Identifiers.main}'.");
      } else {
        mainFunction = errorElement;
      }
    }
    if (errorElement != null &&
        errorElement.isSynthesized &&
        !mainApp.isSynthesized) {
      _compiler.reporter.reportWarningMessage(errorElement,
          errorElement.messageKind, errorElement.messageArguments);
    }
    MethodElement mainMethod;
    if (mainFunction != null && !mainFunction.isMalformed) {
      mainFunction.computeType(_compiler.resolution);
      mainMethod = mainFunction;
    }
    _elementEnvironment._mainFunction = mainMethod;
    return mainMethod;
  }
}

class ComputeSpannableMixin {
  SourceSpan spanFromToken(Element currentElement, Token token) =>
      _spanFromTokens(currentElement, token, token);

  SourceSpan _spanFromTokens(Element currentElement, Token begin, Token end,
      [Uri uri]) {
    if (begin == null || end == null) {
      // TODO(ahe): We can almost always do better. Often it is only
      // end that is null. Otherwise, we probably know the current
      // URI.
      throw 'Cannot find tokens to produce error message.';
    }
    if (uri == null && currentElement != null) {
      if (currentElement is! Element) {
        throw 'Can only find tokens from an Element.';
      }
      Element element = currentElement;
      uri = element.compilationUnit.script.resourceUri;
      String message;
      assert(() {
        bool sameToken(Token token, Token sought) {
          if (token == sought) return true;
          if (token.stringValue == '[') {
            // `[` is converted to `[]` in the parser when needed.
            return sought.stringValue == '[]' &&
                token.charOffset <= sought.charOffset &&
                sought.charOffset < token.charEnd;
          }
          if (token.stringValue == '>>') {
            // `>>` is converted to `>` in the parser when needed.
            return sought.stringValue == '>' &&
                token.charOffset <= sought.charOffset &&
                sought.charOffset < token.charEnd;
          }
          return false;
        }

        /// Check that [begin] and [end] can be found between [from] and [to].
        validateToken(Token from, Token to) {
          if (from == null || to == null) return true;
          bool foundBegin = false;
          bool foundEnd = false;
          Token token = from;
          while (true) {
            if (sameToken(token, begin)) {
              foundBegin = true;
            }
            if (sameToken(token, end)) {
              foundEnd = true;
            }
            if (foundBegin && foundEnd) {
              return true;
            }
            if (token == to || token == token.next || token.next == null) {
              break;
            }
            token = token.next;
          }

          // Create a good message for when the tokens were not found.
          StringBuffer sb = new StringBuffer();
          sb.write('Invalid current element: $element. ');
          sb.write('Looking for ');
          sb.write('[${begin} (${begin.hashCode}),');
          sb.write('${end} (${end.hashCode})] in');

          token = from;
          while (true) {
            sb.write('\n ${token} (${token.hashCode})');
            if (token == to || token == token.next || token.next == null) {
              break;
            }
            token = token.next;
          }
          message = sb.toString();
          return false;
        }

        if (element.enclosingClass != null &&
            element.enclosingClass.isEnumClass) {
          // Enums ASTs are synthesized (and give messed up messages).
          return true;
        }

        if (element is AstElement) {
          AstElement astElement = element;
          if (astElement.hasNode) {
            Token from = astElement.node.getBeginToken();
            Token to = astElement.node.getEndToken();
            if (astElement.metadata.isNotEmpty) {
              if (!astElement.metadata.first.hasNode) {
                // We might try to report an error while parsing the metadata
                // itself.
                return true;
              }
              from = astElement.metadata.first.node.getBeginToken();
            }
            return validateToken(from, to);
          }
        }
        return true;
      }(), failedAt(currentElement, message));
    }
    return new SourceSpan.fromTokens(uri, begin, end);
  }

  SourceSpan _spanFromNode(Element currentElement, Node node) {
    return _spanFromTokens(
        currentElement, node.getBeginToken(), node.getPrefixEndToken());
  }

  SourceSpan _spanFromElement(Element currentElement, Element element) {
    if (element != null && element.sourcePosition != null) {
      return element.sourcePosition;
    }
    while (element != null && element.isSynthesized) {
      element = element.enclosingElement;
    }
    if (element != null &&
        element.sourcePosition == null &&
        !element.isLibrary &&
        !element.isCompilationUnit) {
      // Sometimes, the backend fakes up elements that have no
      // position. So we use the enclosing element instead. It is
      // not a good error location, but cancel really is "internal
      // error" or "not implemented yet", so the vicinity is good
      // enough for now.
      element = element.enclosingElement;
      // TODO(ahe): I plan to overhaul this infrastructure anyways.
    }
    if (element == null) {
      element = currentElement;
    }
    if (element == null) {
      return null;
    }

    if (element.sourcePosition != null) {
      return element.sourcePosition;
    }
    Token position = element.position;
    Uri uri = element.compilationUnit.script.resourceUri;
    return (position == null)
        ? new SourceSpan(uri, 0, 0)
        : _spanFromTokens(currentElement, position, position, uri);
  }

  SourceSpan spanFromSpannable(Spannable spannable, Entity currentElement) {
    if (spannable is Node) {
      return _spanFromNode(currentElement, spannable);
    } else if (spannable is Element) {
      return _spanFromElement(currentElement, spannable);
    } else if (spannable is MetadataAnnotation) {
      return spannable.sourcePosition;
    } else if (spannable is LocalVariable) {
      return spanFromSpannable(spannable.executableContext, currentElement);
    }
    return null;
  }
}

/// An element environment base on a [Compiler].
class _CompilerElementEnvironment extends ElementEnvironment {
  final Compiler _compiler;

  LibraryEntity _mainLibrary;
  FunctionEntity _mainFunction;

  _CompilerElementEnvironment(this._compiler);

  LibraryProvider get _libraryProvider => _compiler.libraryLoader;
  Resolution get _resolution => _compiler.resolution;

  ResolutionDynamicType get dynamicType => const ResolutionDynamicType();

  @override
  LibraryEntity get mainLibrary => _mainLibrary;

  @override
  FunctionEntity get mainFunction => _mainFunction;

  @override
  Iterable<LibraryEntity> get libraries => _compiler.libraryLoader.libraries;

  @override
  String getLibraryName(covariant LibraryElement library) =>
      library.libraryName;

  @override
  ResolutionInterfaceType getThisType(covariant ClassElement cls) {
    cls.ensureResolved(_resolution);
    return cls.thisType;
  }

  @override
  ResolutionInterfaceType getRawType(covariant ClassElement cls) {
    cls.ensureResolved(_resolution);
    return cls.rawType;
  }

  @override
  bool isGenericClass(ClassEntity cls) {
    return getThisType(cls).typeArguments.isNotEmpty;
  }

  @override
  bool isMixinApplication(covariant ClassElement cls) {
    return cls.isMixinApplication;
  }

  @override
  bool isUnnamedMixinApplication(covariant ClassElement cls) {
    return cls.isUnnamedMixinApplication;
  }

  @override
  ClassEntity getEffectiveMixinClass(covariant ClassElement cls) {
    if (!cls.isMixinApplication) return null;
    do {
      MixinApplicationElement mixinApplication = cls;
      cls = mixinApplication.mixin;
    } while (cls.isMixinApplication);
    return cls;
  }

  @override
  ResolutionDartType getTypeVariableBound(
      covariant TypeVariableElement typeVariable) {
    return typeVariable.bound;
  }

  @override
  ResolutionInterfaceType createInterfaceType(covariant ClassElement cls,
      covariant List<ResolutionDartType> typeArguments) {
    cls.ensureResolved(_resolution);
    return cls.thisType.createInstantiation(typeArguments);
  }

  @override
  MemberElement lookupLocalClassMember(covariant ClassElement cls, String name,
      {bool setter: false, bool required: false}) {
    cls.ensureResolved(_resolution);
    Element member = cls.implementation.lookupLocalMember(name);
    if (member != null && member.isAbstractField) {
      AbstractFieldElement abstractField = member;
      if (setter) {
        member = abstractField.setter;
      } else {
        member = abstractField.getter;
      }
      if (member == null && required) {
        failedAt(
            cls,
            "The class '${cls.name}' does not contain required "
            "${setter ? 'setter' : 'getter'}: '$name'.");
      }
    }
    if (member == null && required) {
      throw new SpannableAssertionFailure(
          cls,
          "The class '${cls.name}' does not "
          "contain required member: '$name'.");
    }
    return member?.declaration;
  }

  @override
  ConstructorElement lookupConstructor(covariant ClassElement cls, String name,
      {bool required: false}) {
    cls.ensureResolved(_resolution);
    ConstructorElement constructor = cls.implementation.lookupConstructor(name);
    // TODO(johnniwinther): Skip redirecting factories.
    if (constructor == null && required) {
      throw new SpannableAssertionFailure(
          cls,
          "The class '${cls.name}' does not contain "
          "required constructor: '$name'.");
    }
    return constructor?.declaration;
  }

  @override
  void forEachLocalClassMember(
      covariant ClassElement cls, void f(MemberElement member)) {
    cls.ensureResolved(_resolution);

    void handleMember(_member) {
      MemberElement member = _member;
      if (member.isSynthesized) return;
      if (member.isMalformed) return;
      if (member.isConstructor) return;
      if (!member.isDeclaration) return;
      f(member);
    }

    cls.forEachLocalMember(handleMember);
    if (cls.isPatched) {
      cls.implementation.forEachLocalMember(handleMember);
    }
  }

  @override
  void forEachInjectedClassMember(
      covariant ClassElement cls, void f(MemberElement member)) {}

  @override
  void forEachClassMember(covariant ClassElement cls,
      void f(ClassElement declarer, MemberElement member)) {
    cls.ensureResolved(_resolution);
    cls.forEachMember((ClassElement declarer, _member) {
      MemberElement member = _member;
      if (member.isSynthesized) return;
      if (member.isMalformed) return;
      if (member.isConstructor) return;
      f(declarer, member);
    }, includeSuperAndInjectedMembers: true);
  }

  @override
  void forEachConstructor(
      covariant ClassElement cls, void f(ConstructorEntity constructor),
      {bool ensureResolved: true}) {
    if (ensureResolved) cls.ensureResolved(_resolution);
    for (ConstructorElement constructor in cls.implementation.constructors) {
      if (ensureResolved) _resolution.ensureResolved(constructor.declaration);
      if (constructor.isRedirectingFactory) continue;
      f(constructor);
    }
  }

  @override
  void forEachConstructorBody(
      covariant ClassElement cls, void f(ConstructorBodyEntity constructor)) {
    cls.forEachConstructorBody(f);
  }

  @override
  void forEachNestedClosure(
      covariant MemberElement member, void f(FunctionEntity closure)) {
    for (var closure in member.nestedClosures) {
      f(closure);
    }
  }

  @override
  ClassEntity getSuperClass(covariant ClassElement cls,
      {bool skipUnnamedMixinApplications: false}) {
    cls.ensureResolved(_resolution);
    ClassElement superclass = cls.superclass;
    if (skipUnnamedMixinApplications) {
      while (superclass != null && superclass.isUnnamedMixinApplication) {
        superclass = superclass.superclass;
      }
    }
    return superclass;
  }

  @override
  void forEachSupertype(
      covariant ClassElement cls, void f(ResolutionInterfaceType supertype)) {
    cls.allSupertypes.forEach((InterfaceType supertype) => f(supertype));
  }

  @override
  void forEachMixin(covariant ClassElement cls, void f(ClassElement mixin)) {
    for (; cls != null; cls = cls.superclass) {
      if (cls.isMixinApplication) {
        MixinApplicationElement mixinApplication = cls;
        f(mixinApplication.mixin);
      }
    }
  }

  @override
  MemberElement lookupLibraryMember(
      covariant LibraryElement library, String name,
      {bool setter: false, bool required: false}) {
    Element member = library.implementation.findLocal(name);
    if (member != null && member.isAbstractField) {
      AbstractFieldElement abstractField = member;
      if (setter) {
        member = abstractField.setter;
      } else {
        member = abstractField.getter;
      }
      if (member == null && required) {
        failedAt(
            library,
            "The library '${library.canonicalUri}' does not contain required "
            "${setter ? 'setter' : 'getter'}: '$name'.");
      }
    }
    if (member is! MemberElement) {
      member = null;
    }
    if (member == null && required) {
      failedAt(
          library,
          "The library '${library.canonicalUri}' does not "
          "contain required member: '$name'.");
    }
    return member?.declaration;
  }

  @override
  void forEachLibraryMember(
      covariant LibraryElement library, void f(MemberEntity member)) {
    library.implementation.forEachLocalMember((Element element) {
      if (!element.isClass && !element.isTypedef) {
        MemberElement member = element;
        f(member);
      }
    });
  }

  @override
  ClassElement lookupClass(covariant LibraryElement library, String name,
      {bool required: false}) {
    Element cls = library.implementation.findLocal(name);
    if (cls is! ClassElement) {
      cls = null;
    }
    if (cls == null && required) {
      failedAt(
          library,
          "The library '${library.libraryName}' does not "
          "contain required class: '$name'.");
    }
    return cls?.declaration;
  }

  @override
  void forEachClass(covariant LibraryElement library, void f(ClassEntity cls)) {
    library.implementation.forEachLocalMember((dynamic member) {
      if (member.isClass) {
        ClassElement cls = member;
        f(cls);
      }
    });
  }

  @override
  LibraryElement lookupLibrary(Uri uri, {bool required: false}) {
    LibraryElement library = _libraryProvider.lookupLibrary(uri);
    // If the script of the library is synthesized, the library does not exist
    // and we do not try to load the helpers.
    //
    // This could for example happen if dart:async is disabled, then loading it
    // should not try to find the given element.
    if (library != null && library.isSynthesized) {
      return null;
    }
    if (library == null && required) {
      failedAt(NO_LOCATION_SPANNABLE, "The library '${uri}' was not found.");
    }
    return library;
  }

  @override
  bool isDeferredLoadLibraryGetter(covariant MemberElement member) {
    return member.isDeferredLoaderGetter;
  }

  @override
  ResolutionFunctionType getFunctionType(covariant MethodElement method) {
    if (method is ConstructorBodyElement) {
      return method.constructor.type;
    }
    method.computeType(_resolution);
    ResolutionFunctionType type = method.type;
    if (method.isConstructor) {
      ConstructorElement constructor = method;
      if (constructor.definingConstructor != null) {
        // The type of a defining constructor doesn't use the right type
        // variables. Substitute the type variable of the defining class by the
        // type variables of the enclosing class.
        ClassElement definingClass =
            constructor.definingConstructor.enclosingClass;
        type = type.substByContext(
            method.enclosingClass.thisType.asInstanceOf(definingClass));
      }
    }
    return type;
  }

  @override
  List<TypeVariableType> getFunctionTypeVariables(FunctionEntity function) {
    return const <TypeVariableType>[];
  }

  @override
  DartType getFunctionAsyncOrSyncStarElementType(FunctionEntity function) {
    return dynamicType;
  }

  @override
  DartType getAsyncOrSyncStarElementType(AsyncMarker marker, DartType type) {
    return dynamicType;
  }

  @override
  DartType getFieldType(covariant FieldElement field) {
    field.computeType(_resolution);
    return field.type;
  }

  @override
  ResolutionFunctionType getLocalFunctionType(
      covariant LocalFunctionElement function) {
    return function.type;
  }

  @override
  ConstantExpression getFieldConstant(covariant FieldElement field) {
    return field.constant;
  }

  @override
  ResolutionDartType getUnaliasedType(covariant ResolutionDartType type) {
    type.computeUnaliased(_resolution);
    return type.unaliased;
  }

  @override
  Iterable<ConstantValue> getMemberMetadata(covariant MemberElement element,
      {bool includeParameterMetadata: false}) {
    List<ConstantValue> values = <ConstantValue>[];
    values.addAll(_getMetadataOf(element));
    if (includeParameterMetadata) {
      if (element.isFunction || element.isConstructor || element.isSetter) {
        MethodElement function = element.implementation;
        function.functionSignature.forEachParameter(
            (parameter) => values.addAll(_getMetadataOf(parameter)));
      }
    }
    return values;
  }

  @override
  Iterable<ConstantValue> getLibraryMetadata(covariant LibraryElement element) {
    return _getMetadataOf(element);
  }

  @override
  Iterable<ImportEntity> getImports(covariant LibraryElement library) {
    return library.imports;
  }

  @override
  Iterable<ConstantValue> getClassMetadata(covariant ClassElement element) {
    return _getMetadataOf(element);
  }

  @override
  Iterable<ConstantValue> getTypedefMetadata(covariant TypedefElement element) {
    return _getMetadataOf(element);
  }

  Iterable<ConstantValue> _getMetadataOf(Element element) {
    List<ConstantValue> constants = <ConstantValue>[];
    _compiler.reporter.withCurrentElement(element, () {
      for (MetadataAnnotation metadata in element.implementation.metadata) {
        metadata.ensureResolved(_compiler.resolution);
        assert(metadata.constant != null,
            failedAt(metadata, "Unevaluated metadata constant."));
        constants.add(
            _compiler.backend.constants.getConstantValue(metadata.constant));
      }
    });
    return constants;
  }

  @override
  ResolutionFunctionType getFunctionTypeOfTypedef(
      covariant TypedefElement typedef) {
    var result = typedef.alias;
    if (result.isMalformed) return null;
    return result;
  }

  @override
  ResolutionTypedefType getTypedefTypeOfTypedef(
          covariant TypedefElement typedef) =>
      typedef.thisType;

  @override
  bool isEnumClass(covariant ClassElement cls) => cls.isEnumClass;
}

/// AST-based logic for processing annotations. These annotations are processed
/// very early in the compilation pipeline, typically this is before resolution
/// is complete. Because of that this processor does a lightweight parse of the
/// annotation (which is restricted to a limited subset of the annotation
/// syntax), and, once resolution completes, it validates that the parsed
/// annotations correspond to the correct element.
class _ElementAnnotationProcessor implements AnnotationProcessor {
  final Compiler _compiler;
  final NativeBasicDataBuilder _nativeBasicDataBuilder;

  _ElementAnnotationProcessor(this._compiler, this._nativeBasicDataBuilder);

  CommonElements get _commonElements => _compiler.resolution.commonElements;

  /// Check whether [cls] has a `@Native(...)` annotation, and if so, set its
  /// native name from the annotation.
  void extractNativeAnnotations(covariant LibraryElement library) {
    library.forEachLocalMember((Element element) {
      if (element.isClass) {
        EagerAnnotationHandler.checkAnnotation(_compiler, element,
            new NativeAnnotationHandler(_nativeBasicDataBuilder));
      }
    });
  }

  void extractJsInteropAnnotations(covariant LibraryElement library) {
    bool checkJsInteropAnnotation(Element element) {
      return EagerAnnotationHandler.checkAnnotation(
          _compiler, element, const JsInteropAnnotationHandler());
    }

    if (checkJsInteropAnnotation(library)) {
      _nativeBasicDataBuilder.markAsJsInteropLibrary(library);
    }
    library.forEachLocalMember((Element element) {
      if (element.isClass) {
        ClassElement cls = element;
        if (checkJsInteropAnnotation(element)) {
          _nativeBasicDataBuilder.markAsJsInteropClass(cls);
        }
      }
    });
  }

  void processJsInteropAnnotations(
      NativeBasicData nativeBasicData, NativeDataBuilder nativeDataBuilder) {
    if (_commonElements.jsAnnotationClass == null) return;

    ClassElement cls = _commonElements.jsAnnotationClass;
    FieldElement nameField = cls.lookupMember('name');

    /// Resolves the metadata of [element] and returns the name of the `JS(...)`
    /// annotation for js interop, if found.
    String processJsInteropAnnotation(Element element) {
      for (MetadataAnnotation annotation in element.implementation.metadata) {
        // TODO(johnniwinther): Avoid processing unresolved elements.
        if (annotation.constant == null) continue;
        ConstantValue constant =
            _compiler.constants.getConstantValue(annotation.constant);
        if (constant == null || constant is! ConstructedConstantValue) continue;
        ConstructedConstantValue constructedConstant = constant;
        if (constructedConstant.type.element ==
            _commonElements.jsAnnotationClass) {
          ConstantValue value = constructedConstant.fields[nameField];
          String name;
          if (value.isString) {
            StringConstantValue stringValue = value;
            name = stringValue.stringValue;
          } else {
            // TODO(jacobr): report a warning if the value is not a String.
            name = '';
          }
          return name;
        }
      }
      return null;
    }

    void checkFunctionParameters(MethodElement fn) {
      if (fn.hasFunctionSignature &&
          fn.functionSignature.optionalParametersAreNamed) {
        _compiler.reporter.reportErrorMessage(
            fn,
            MessageKind.JS_INTEROP_METHOD_WITH_NAMED_ARGUMENTS,
            {'method': fn.name});
      }
    }

    bool hasAnonymousAnnotation(Element element) {
      if (_commonElements.jsAnonymousClass == null) return false;
      return element.metadata.any((MetadataAnnotation annotation) {
        ConstantValue constant =
            _compiler.constants.getConstantValue(annotation.constant);
        if (constant == null || constant is! ConstructedConstantValue)
          return false;
        ConstructedConstantValue constructedConstant = constant;
        return constructedConstant.type.element ==
            _commonElements.jsAnonymousClass;
      });
    }

    void processJsInteropAnnotationsInLibrary(LibraryElement library) {
      String libraryName = processJsInteropAnnotation(library);
      if (libraryName != null) {
        nativeDataBuilder.setJsInteropLibraryName(library, libraryName);
      }
      library.implementation.forEachLocalMember((Element element) {
        if (element is MemberElement) {
          String memberName = processJsInteropAnnotation(element);
          if (memberName != null) {
            nativeDataBuilder.setJsInteropMemberName(element, memberName);
            if (element is MethodElement) {
              checkFunctionParameters(element);
            }
          }
        }

        if (!element.isClass) return;

        ClassElement classElement = element;
        String className = processJsInteropAnnotation(classElement);
        if (className != null) {
          nativeDataBuilder.setJsInteropClassName(classElement, className);
        }
        if (!nativeBasicData.isJsInteropClass(classElement)) return;

        bool isAnonymous = hasAnonymousAnnotation(classElement);
        if (isAnonymous) {
          nativeDataBuilder.markJsInteropClassAsAnonymous(classElement);
        }

        // Skip classes that are completely unreachable. This should only happen
        // when all of jsinterop types are unreachable from main.
        if (!_compiler.resolutionWorldBuilder.isImplemented(classElement)) {
          return;
        }

        if (!classElement
            .implementsInterface(_commonElements.jsJavaScriptObjectClass)) {
          _compiler.reporter.reportErrorMessage(classElement,
              MessageKind.JS_INTEROP_CLASS_CANNOT_EXTEND_DART_CLASS, {
            'cls': classElement.name,
            'superclass': classElement.superclass.name
          });
        }

        classElement.forEachMember((ClassElement classElement, _member) {
          MemberElement member = _member;
          String memberName = processJsInteropAnnotation(member);
          if (memberName != null) {
            nativeDataBuilder.setJsInteropMemberName(member, memberName);
          }

          if (!member.isSynthesized &&
              nativeBasicData.isJsInteropClass(classElement) &&
              member is MethodElement) {
            MethodElement fn = member;
            if (!fn.isExternal &&
                !fn.isAbstract &&
                !fn.isConstructor &&
                !fn.isStatic) {
              _compiler.reporter.reportErrorMessage(
                  fn,
                  MessageKind.JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER,
                  {'cls': classElement.name, 'member': member.name});
            }

            if (fn.isFactoryConstructor && isAnonymous) {
              if (fn.functionSignature.requiredParameterCount > 0 ||
                  fn.functionSignature.hasOptionalParameters &&
                      !fn.functionSignature.optionalParametersAreNamed) {
                _compiler.reporter.reportErrorMessage(
                    fn,
                    MessageKind
                        .JS_OBJECT_LITERAL_CONSTRUCTOR_WITH_POSITIONAL_ARGUMENTS,
                    {'cls': classElement.name});
              }
            } else {
              checkFunctionParameters(fn);
            }
          }
        });
      });
    }

    _compiler.libraryLoader.libraries
        .forEach((LibraryEntity l) => processJsInteropAnnotationsInLibrary(l));
  }
}

/// Builder that creates work item necessary for the resolution of a
/// [MemberElement].
class ResolutionWorkItemBuilder extends WorkItemBuilder {
  final Resolution _resolution;

  ResolutionWorkItemBuilder(this._resolution);

  @override
  WorkItem createWorkItem(MemberElement element) {
    assert(element.isDeclaration, failedAt(element));
    if (element.isMalformed) return null;

    assert(element is AnalyzableElement,
        failedAt(element, 'Element $element is not analyzable.'));
    return _resolution.createWorkItem(element);
  }
}

class ResolutionMirrorsData extends MirrorsDataImpl {
  ResolutionMirrorsData(Compiler compiler,
      ElementEnvironment elementEnvironment, CommonElements commonElements)
      : super(compiler, elementEnvironment, commonElements);

  @override
  bool isClassInjected(covariant ClassElement cls) => cls.isInjected;

  @override
  bool isClassResolved(covariant ClassElement cls) => cls.isResolved;

  @override
  void forEachConstructor(
      covariant ClassElement cls, void f(ConstructorEntity constructor)) {
    cls.constructors.forEach((Element _constructor) {
      ConstructorElement constructor = _constructor;
      f(constructor);
    });
  }
}
