// 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.

import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/standard_ast_factory.dart';
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/context/context.dart' show AnalysisContextImpl;
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/handle.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/dart/resolver/scope.dart';
import 'package:analyzer/src/generated/engine.dart' show AnalysisContext;
import 'package:analyzer/src/generated/testing/ast_test_factory.dart';
import 'package:analyzer/src/summary/summary_sdk.dart';
import 'package:front_end/src/base/resolve_relative_uri.dart';
import 'package:front_end/src/base/source.dart';
import 'package:front_end/src/fasta/kernel/kernel_shadow_ast.dart' as kernel;
import 'package:front_end/src/fasta/kernel/redirecting_factory_body.dart';
import 'package:kernel/kernel.dart' as kernel;
import 'package:kernel/type_environment.dart' as kernel;
import 'package:path/path.dart' as pathos;

/**
 * Object that can resynthesize analyzer [LibraryElement] from Kernel.
 */
class KernelResynthesizer implements ElementResynthesizer {
  final AnalysisContextImpl _analysisContext;
  final kernel.TypeEnvironment _types;
  final Map<String, kernel.Library> _kernelMap;
  final Map<String, bool> _libraryExistMap;
  final Map<String, LibraryElementImpl> _libraryMap = {};

  /**
   * Cache of [Source] objects that have already been converted from URIs.
   */
  final Map<String, Source> _sources = <String, Source>{};

  /// The type provider for this resynthesizer.
  SummaryTypeProvider _typeProvider;

  KernelResynthesizer(this._analysisContext, this._types, this._kernelMap,
      this._libraryExistMap) {
    _buildTypeProvider();
    _analysisContext.typeProvider = _typeProvider;
  }

  @override
  AnalysisContext get context => _analysisContext;

  /**
   * Return `true` if strong mode analysis should be used.
   */
  bool get strongMode => _analysisContext.analysisOptions.strongMode;

  /**
   * Return the `Type` type.
   */
  DartType get typeType => getLibrary('dart:core').getType('Type').type;

  @override
  Element getElement(ElementLocation location) {
    List<String> components = location.components;

    LibraryElementImpl library = getLibrary(components[0]);
    if (components.length == 1) {
      return library;
    }

    CompilationUnitElement unit;
    for (var libraryUnit in library.units) {
      if (libraryUnit.source.uri.toString() == components[1]) {
        unit = libraryUnit;
        break;
      }
    }
    if (unit == null) {
      throw new ArgumentError('Unable to find unit: $location');
    }
    if (components.length == 2) {
      return unit;
    }

    ElementImpl element = unit as ElementImpl;
    for (int i = 2; i < components.length; i++) {
      if (element == null) {
        throw new ArgumentError('Unable to find element: $location');
      }
      element = element.getChild(components[i]);
    }
    return element;
  }

  /**
   * Return the [ElementImpl] that corresponds to the given [name], or `null`
   * if the corresponding element cannot be found.
   */
  ElementImpl getElementFromCanonicalName(kernel.CanonicalName name) {
    if (name == null) return null;

    var components = new List<String>(5);
    var componentPtr = 0;
    for (var namePart = name;
        namePart != null && !namePart.isRoot;
        namePart = namePart.parent) {
      components[componentPtr++] = namePart.name;
    }

    String libraryUri = components[--componentPtr];
    String topKindOrClassName = components[--componentPtr];

    LibraryElementImpl library = getLibrary(libraryUri);
    if (library == null) return null;

    String takeElementName() {
      String publicNameOrLibraryUri = components[--componentPtr];
      if (publicNameOrLibraryUri == libraryUri) {
        return components[--componentPtr];
      } else {
        return publicNameOrLibraryUri;
      }
    }

    // Top-level element other than class.
    if (topKindOrClassName == '@fields' ||
        topKindOrClassName == '@methods' ||
        topKindOrClassName == '@getters' ||
        topKindOrClassName == '@setters' ||
        topKindOrClassName == '@typedefs') {
      String elementName = takeElementName();
      for (CompilationUnitElement unit in library.units) {
        CompilationUnitElementImpl unitImpl = unit;
        ElementImpl child = unitImpl.getChild(elementName);
        if (child != null) {
          return child;
        }
      }
      return null;
    }

    AbstractClassElementImpl classElement;
    for (CompilationUnitElement unit in library.units) {
      CompilationUnitElementImpl unitImpl = unit;
      classElement = unitImpl.getChild(topKindOrClassName);
      if (classElement != null) {
        break;
      }
    }
    if (classElement == null) return null;

    // If no more component, the class is the element.
    if (componentPtr == 0) return classElement;

    String kind = components[--componentPtr];
    String elementName = takeElementName();
    if (kind == '@methods') {
      return classElement.getMethod(elementName) as ElementImpl;
    } else if (kind == '@getters') {
      return classElement.getGetter(elementName) as ElementImpl;
    } else if (kind == '@setters') {
      return classElement.getSetter(elementName) as ElementImpl;
    } else if (kind == '@fields') {
      return classElement.getField(elementName) as ElementImpl;
    } else if (kind == '@constructors' || kind == '@factories') {
      if (elementName.isEmpty) {
        return classElement.unnamedConstructor as ElementImpl;
      }
      return classElement.getNamedConstructor(elementName) as ElementImpl;
    } else {
      throw new UnimplementedError('Internal error: $kind unexpected.');
    }
  }

  /**
   * Return the [LibraryElementImpl] for the given [uriStr], or `null` if
   * the library is not part of the Kernel libraries bundle.
   */
  LibraryElementImpl getLibrary(String uriStr) {
    return _libraryMap.putIfAbsent(uriStr, () {
      var kernel = _kernelMap[uriStr];
      if (kernel == null) return null;

      if (_libraryExistMap[uriStr] != true) {
        return _newSyntheticLibrary(uriStr);
      }

      var libraryContext =
          new _KernelLibraryResynthesizerContextImpl(this, kernel);

      // Build the library.
      LibraryElementImpl libraryElement = libraryContext._buildLibrary(uriStr);
      if (libraryElement == null) return null;

      // Build the defining unit.
      var definingUnit = libraryContext._buildUnit(null).unit;
      libraryElement.definingCompilationUnit = definingUnit;

      // Build units for parts.
      var parts = new List<CompilationUnitElementImpl>(kernel.parts.length);
      for (int i = 0; i < kernel.parts.length; i++) {
        var fileUri = kernel.parts[i].fileUri;
        var unitContext = libraryContext._buildUnit("$fileUri");
        parts[i] = unitContext.unit;
      }
      libraryElement.parts = parts;

      // Create the required `loadLibrary` function.
      if (uriStr != 'dart:core' && uriStr != 'dart:async') {
        libraryElement.createLoadLibraryFunction(_typeProvider);
      }

      return libraryElement;
    });
  }

  DartType getType(ElementImpl context, kernel.DartType kernelType) {
    if (kernelType is kernel.DynamicType) return DynamicTypeImpl.instance;
    if (kernelType is kernel.InvalidType) return UndefinedTypeImpl.instance;
    if (kernelType is kernel.BottomType) return BottomTypeImpl.instance;
    if (kernelType is kernel.VoidType) return VoidTypeImpl.instance;

    if (kernelType is kernel.InterfaceType) {
      var name = kernelType.className.canonicalName;
      if (!strongMode &&
          name.name == 'FutureOr' &&
          name.parent.name == 'dart:async') {
        return DynamicTypeImpl.instance;
      }
      return _getInterfaceType(context, name, kernelType.typeArguments);
    }

    if (kernelType is kernel.TypeParameterType) {
      kernel.TypeParameter kTypeParameter = kernelType.parameter;
      return _getTypeParameter(context, kTypeParameter).type;
    }

    if (kernelType is kernel.FunctionType) {
      var typeElement =
          new GenericFunctionTypeElementImpl.forKernel(context, kernelType);
      return typeElement.type;
    }

    // TODO(scheglov) Support other kernel types.
    throw new UnimplementedError('For ${kernelType.runtimeType}');
  }

  void _buildTypeProvider() {
    var coreLibrary = getLibrary('dart:core');
    var asyncLibrary = getLibrary('dart:async');
    _typeProvider = new SummaryTypeProvider();
    _typeProvider.initializeCore(coreLibrary);
    _typeProvider.initializeAsync(asyncLibrary);
    // Now, when TypeProvider is ready, we can finalize core/async.
    coreLibrary.createLoadLibraryFunction(_typeProvider);
    asyncLibrary.createLoadLibraryFunction(_typeProvider);
  }

  InterfaceType _getInterfaceType(ElementImpl context,
      kernel.CanonicalName className, List<kernel.DartType> kernelArguments) {
    var libraryName = className.parent;
    var libraryElement = getLibrary(libraryName.name);
    ClassElement classElement = libraryElement.getType(className.name);
    classElement ??= libraryElement.getEnum(className.name);

    if (kernelArguments.isEmpty) {
      return classElement.type;
    }

    return new InterfaceTypeImpl.elementWithNameAndArgs(
        classElement, classElement.name, () {
      List<DartType> arguments = kernelArguments
          .map((kernel.DartType k) => getType(context, k))
          .toList(growable: false);
      return arguments;
    });
  }

  /**
   * Get the [Source] object for the given [uri].
   */
  Source _getSource(String uri) {
    return _sources.putIfAbsent(
        uri, () => _analysisContext.sourceFactory.forUri(uri));
  }

  /// Return the [TypeParameterElement] for the given [kernelTypeParameter].
  TypeParameterElement _getTypeParameter(
      ElementImpl context, kernel.TypeParameter kernelTypeParameter) {
    String name = kernelTypeParameter.name;
    for (var ctx = context; ctx != null; ctx = ctx.enclosingElement) {
      if (ctx is TypeParameterizedElementMixin) {
        for (var typeParameter in ctx.typeParameters) {
          if (typeParameter.name == name) {
            return typeParameter;
          }
        }
      }
    }
    throw new StateError('Not found $kernelTypeParameter in $context');
  }

  LibraryElementImpl _newSyntheticLibrary(String uriStr) {
    Source librarySource = _getSource(uriStr);
    if (librarySource == null) return null;

    LibraryElementImpl libraryElement =
        new LibraryElementImpl(context, '', -1, 0);
    libraryElement.isSynthetic = true;
    CompilationUnitElementImpl unitElement =
        new CompilationUnitElementImpl(librarySource.shortName);
    libraryElement.definingCompilationUnit = unitElement;
    unitElement.source = librarySource;
    unitElement.librarySource = librarySource;
    libraryElement.createLoadLibraryFunction(_typeProvider);
    libraryElement.publicNamespace = new Namespace({});
    libraryElement.exportNamespace = new Namespace({});
    return libraryElement;
  }
}

/**
 * This exception is thrown when we detect that the Kernel has a compilation
 * error, so we cannot resynthesize the constant expression.
 */
class _CompilationErrorFound {
  const _CompilationErrorFound();
}

/**
 * Builder of [Expression]s from [kernel.Expression]s.
 */
class _ExprBuilder {
  final _KernelUnitResynthesizerContextImpl _context;
  final ElementImpl _contextElement;

  _ExprBuilder(this._context, this._contextElement);

  Expression build(kernel.Expression expr) {
    try {
      return _build(expr);
    } on _CompilationErrorFound {
      return AstTestFactory.identifier3('#invalidConst');
    }
  }

  ConstructorInitializer buildInitializer(kernel.Initializer k) {
    if (k is kernel.FieldInitializer) {
      Expression value = build(k.value);
      ConstructorFieldInitializer initializer = AstTestFactory
          .constructorFieldInitializer(false, k.field.name.name, value);
      initializer.fieldName.staticElement = _getElement(k.fieldReference);
      return initializer;
    }

    if (k is kernel.AssertInitializer) {
      var body = k.statement;
      var condition = build(body.condition);
      var message = body.message != null ? build(body.message) : null;
      return AstTestFactory.assertInitializer(condition, message);
    }

    if (k is kernel.RedirectingInitializer) {
      ConstructorElementImpl redirect = _getElement(k.targetReference);
      var arguments = _toArguments(k.arguments);

      RedirectingConstructorInvocation invocation =
          AstTestFactory.redirectingConstructorInvocation(arguments);
      invocation.staticElement = redirect;

      String name = k.target.name.name;
      if (name.isNotEmpty) {
        invocation.constructorName = AstTestFactory.identifier3(name)
          ..staticElement = redirect;
      }

      return invocation;
    }

    if (k is kernel.SuperInitializer) {
      ConstructorElementImpl redirect = _getElement(k.targetReference);
      var arguments = _toArguments(k.arguments);

      SuperConstructorInvocation invocation =
          AstTestFactory.superConstructorInvocation(arguments);
      invocation.staticElement = redirect;

      String name = k.target.name.name;
      if (name.isNotEmpty) {
        invocation.constructorName = AstTestFactory.identifier3(name)
          ..staticElement = redirect;
      }

      return invocation;
    }

    // TODO(scheglov) Support other kernel initializer types.
    throw new UnimplementedError('For ${k.runtimeType}');
  }

  Expression _build(kernel.Expression expr) {
    if (expr is kernel.NullLiteral) {
      return AstTestFactory.nullLiteral();
    }
    if (expr is kernel.BoolLiteral) {
      return AstTestFactory.booleanLiteral(expr.value);
    }
    if (expr is kernel.IntLiteral) {
      return AstTestFactory.integer(expr.value);
    }
    if (expr is kernel.DoubleLiteral) {
      return AstTestFactory.doubleLiteral(expr.value);
    }
    if (expr is kernel.StringLiteral) {
      return AstTestFactory.string2(expr.value);
    }
    if (expr is kernel.StringConcatenation) {
      List<InterpolationElement> elements = expr.expressions
          .map(_build)
          .map(_newInterpolationElement)
          .toList(growable: false);
      return AstTestFactory.string(elements);
    }
    if (expr is kernel.SymbolLiteral) {
      List<String> components = expr.value.split('.').toList();
      return AstTestFactory.symbolLiteral(components);
    }

    if (expr is kernel.ListLiteral) {
      Keyword keyword = expr.isConst ? Keyword.CONST : null;
      var typeArguments = _buildTypeArgumentList([expr.typeArgument]);
      var elements = expr.expressions.map(_build).toList();
      return AstTestFactory.listLiteral2(keyword, typeArguments, elements);
    }

    if (expr is kernel.MapLiteral) {
      Keyword keyword = expr.isConst ? Keyword.CONST : null;
      var typeArguments =
          _buildTypeArgumentList([expr.keyType, expr.valueType]);

      int numberOfEntries = expr.entries.length;
      var entries = new List<MapLiteralEntry>(numberOfEntries);
      for (int i = 0; i < numberOfEntries; i++) {
        var entry = expr.entries[i];
        Expression key = _build(entry.key);
        Expression value = _build(entry.value);
        entries[i] = AstTestFactory.mapLiteralEntry2(key, value);
      }

      return AstTestFactory.mapLiteral(keyword, typeArguments, entries);
    }

    if (expr is kernel.StaticGet) {
      return _buildIdentifier(expr.targetReference, isGet: true);
    }

    if (expr is kernel.ThisExpression) {
      return AstTestFactory.thisExpression();
    }

    if (expr is kernel.PropertyGet) {
      Expression target = _build(expr.receiver);
      kernel.Reference reference = expr.interfaceTargetReference;
      SimpleIdentifier identifier = _buildSimpleIdentifier(reference);
      return AstTestFactory.propertyAccess(target, identifier);
    }

    if (expr is kernel.VariableGet) {
      String name = expr.variable.name;
      Element contextConstructor = _contextElement;
      if (contextConstructor is ConstructorElement) {
        SimpleIdentifier identifier = AstTestFactory.identifier3(name);
        ParameterElement parameter = contextConstructor.parameters.firstWhere(
            (parameter) => parameter.name == name,
            orElse: () => null);
        identifier.staticElement = parameter;
        return identifier;
      }
    }

    if (expr is kernel.ConditionalExpression) {
      var condition = _build(expr.condition);
      var then = _build(expr.then);
      var otherwise = _build(expr.otherwise);
      return AstTestFactory.conditionalExpression(condition, then, otherwise);
    }

    if (expr is kernel.Not) {
      kernel.Expression kernelOperand = expr.operand;
      var operand = _build(kernelOperand);
      return AstTestFactory.prefixExpression(TokenType.BANG, operand);
    }

    if (expr is kernel.LogicalExpression) {
      var operator = _toBinaryOperatorTokenType(expr.operator);
      var left = _build(expr.left);
      var right = _build(expr.right);
      return AstTestFactory.binaryExpression(left, operator, right);
    }

    if (expr is kernel.Let) {
      var body = expr.body;
      if (body is kernel.ConditionalExpression) {
        var condition = body.condition;
        var otherwiseExpr = body.otherwise;
        if (condition is kernel.MethodInvocation) {
          var equalsReceiver = condition.receiver;
          if (equalsReceiver is kernel.VariableGet &&
              condition.name.name == '==' &&
              condition.arguments.positional.length == 1 &&
              condition.arguments.positional[0] is kernel.NullLiteral &&
              otherwiseExpr is kernel.VariableGet &&
              otherwiseExpr.variable == equalsReceiver.variable) {
            var left = _build(expr.variable.initializer);
            var right = _build(body.then);
            return AstTestFactory.binaryExpression(
                left, TokenType.QUESTION_QUESTION, right);
          }
        }
      }
    }

    if (expr is kernel.MethodInvocation) {
      kernel.Member member = expr.interfaceTarget;
      if (member is kernel.Procedure) {
        if (member.kind == kernel.ProcedureKind.Operator) {
          var left = _build(expr.receiver);
          String operatorName = expr.name.name;
          List<kernel.Expression> args = expr.arguments.positional;
          if (args.isEmpty) {
            if (operatorName == 'unary-') {
              return AstTestFactory.prefixExpression(TokenType.MINUS, left);
            }
            if (operatorName == '~') {
              return AstTestFactory.prefixExpression(TokenType.TILDE, left);
            }
          } else if (args.length == 1) {
            var operator = _toBinaryOperatorTokenType(operatorName);
            var right = _build(args.single);
            return AstTestFactory.binaryExpression(left, operator, right);
          }
        }
      }
    }

    if (expr is kernel.StaticInvocation) {
      kernel.Procedure target = expr.target;
      String name = target.name.name;
      List<Expression> arguments = _toArguments(expr.arguments);
      MethodInvocation invocation =
          AstTestFactory.methodInvocation3(null, name, null, arguments);
      invocation.methodName.staticElement = _getElement(target.reference);
      return invocation;
    }

    if (expr is kernel.ConstructorInvocation) {
      var element = _getElement(expr.targetReference);

      var kernelType =
          expr.getStaticType(_context.libraryContext.resynthesizer._types);
      var type = _context.getType(_contextElement, kernelType);
      TypeName typeName = _buildType(type);

      var constructorName = AstTestFactory.constructorName(
          typeName, element.name.isNotEmpty ? element.name : null);
      constructorName?.name?.staticElement = element;

      var keyword = expr.isConst ? Keyword.CONST : Keyword.NEW;
      var arguments = _toArguments(expr.arguments);
      return AstTestFactory.instanceCreationExpression(
          keyword, constructorName, arguments);
    }

    if (expr is kernel.TypeLiteral) {
      ElementImpl element;
      var kernelType = expr.type;
      if (kernelType is kernel.FunctionType) {
        element = _getElement(kernelType.typedefReference);
      } else {
        var type = _context.getType(_contextElement, kernelType);
        element = type.element;
      }
      var identifier = AstTestFactory.identifier3(element.name);
      identifier.staticElement = element;
      identifier.staticType = _context.libraryContext.resynthesizer.typeType;
      return identifier;
    }

    // Invalid annotations are represented as Let.
    if (expr is kernel.Let) {
      kernel.Let let = expr;
      if (_isConstantExpressionErrorThrow(let.variable.initializer) ||
          _isConstantExpressionErrorThrow(let.body)) {
        throw const _CompilationErrorFound();
      }
    }

    // Stop if there is an error.
    if (_isConstantExpressionErrorThrow(expr)) {
      throw const _CompilationErrorFound();
    }

    // TODO(scheglov): complete getExpression
    throw new UnimplementedError('kernel: (${expr.runtimeType}) $expr');
  }

  Identifier _buildIdentifier(kernel.Reference reference, {bool isGet: false}) {
    Element element = _getElement(reference);
    if (isGet && element is PropertyInducingElement) {
      element = (element as PropertyInducingElement).getter;
    }
    SimpleIdentifier property = AstTestFactory.identifier3(element.displayName)
      ..staticElement = element;
    Element enclosingElement = element.enclosingElement;
    if (enclosingElement is ClassElement) {
      SimpleIdentifier classRef = AstTestFactory
          .identifier3(enclosingElement.name)
            ..staticElement = enclosingElement;
      return AstTestFactory.identifier(classRef, property);
    } else {
      return property;
    }
  }

  SimpleIdentifier _buildSimpleIdentifier(kernel.Reference reference) {
    if (reference == null) {
      throw const _CompilationErrorFound();
    }
    String name = reference.canonicalName.name;
    SimpleIdentifier identifier = AstTestFactory.identifier3(name);
    Element element = _getElement(reference);
    identifier.staticElement = element;
    return identifier;
  }

  TypeAnnotation _buildType(DartType type) {
    if (type is InterfaceType) {
      var name = AstTestFactory.identifier3(type.element.name)
        ..staticElement = type.element
        ..staticType = type;
      List<TypeAnnotation> arguments = _buildTypeArguments(type.typeArguments);
      return AstTestFactory.typeName3(name, arguments)..type = type;
    }
    if (type is DynamicTypeImpl || type is TypeParameterType) {
      var identifier = AstTestFactory.identifier3(type.name)
        ..staticElement = type.element
        ..staticType = type;
      return AstTestFactory.typeName3(identifier)..type = type;
    }
    // TODO(scheglov) Implement for other types.
    throw new UnimplementedError('type: (${type.runtimeType}) $type');
  }

  TypeArgumentList _buildTypeArgumentList(List<kernel.DartType> kernels) {
    int length = kernels.length;
    var types = new List<TypeAnnotation>(length);
    for (int i = 0; i < length; i++) {
      DartType type = _context.getType(_contextElement, kernels[i]);
      TypeAnnotation typeAnnotation = _buildType(type);
      types[i] = typeAnnotation;
    }
    return AstTestFactory.typeArgumentList(types);
  }

  List<TypeAnnotation> _buildTypeArguments(List<DartType> types) {
    if (types.every((t) => t.isDynamic)) return null;
    return types.map(_buildType).toList();
  }

  ElementImpl _getElement(kernel.Reference reference) {
    return _context.libraryContext.resynthesizer
        .getElementFromCanonicalName(reference?.canonicalName);
  }

  InterpolationElement _newInterpolationElement(Expression expr) {
    if (expr is SimpleStringLiteral) {
      return astFactory.interpolationString(expr.literal, expr.value);
    } else {
      return AstTestFactory.interpolationExpression(expr);
    }
  }

  /// Return [Expression]s for the given [kernelArguments].
  List<Expression> _toArguments(kernel.Arguments kernelArguments) {
    int numPositional = kernelArguments.positional.length;
    int numNamed = kernelArguments.named.length;
    var arguments = new List<Expression>(numPositional + numNamed);

    int i = 0;
    for (kernel.Expression k in kernelArguments.positional) {
      arguments[i++] = _build(k);
    }

    for (kernel.NamedExpression k in kernelArguments.named) {
      var value = _build(k.value);
      arguments[i++] = AstTestFactory.namedExpression2(k.name, value);
    }

    return arguments;
  }

  /// Return the [TokenType] for the given operator [name].
  TokenType _toBinaryOperatorTokenType(String name) {
    if (name == '==') return TokenType.EQ_EQ;
    if (name == '&&') return TokenType.AMPERSAND_AMPERSAND;
    if (name == '||') return TokenType.BAR_BAR;
    if (name == '^') return TokenType.CARET;
    if (name == '&') return TokenType.AMPERSAND;
    if (name == '|') return TokenType.BAR;
    if (name == '>>') return TokenType.GT_GT;
    if (name == '<<') return TokenType.LT_LT;
    if (name == '+') return TokenType.PLUS;
    if (name == '-') return TokenType.MINUS;
    if (name == '*') return TokenType.STAR;
    if (name == '/') return TokenType.SLASH;
    if (name == '~/') return TokenType.TILDE_SLASH;
    if (name == '%') return TokenType.PERCENT;
    if (name == '>') return TokenType.GT;
    if (name == '<') return TokenType.LT;
    if (name == '>=') return TokenType.GT_EQ;
    if (name == '<=') return TokenType.LT_EQ;
    if (name == 'unary-') return TokenType.MINUS;
    throw new ArgumentError(name);
  }

  /**
   * Return `true` if the given [expr] throws an instance of
   * `_ConstantExpressionError` defined in `dart:core`.
   */
  static bool _isConstantExpressionErrorThrow(kernel.Expression expr) {
    if (expr is kernel.MethodInvocation) {
      if (expr.name.name == '_throw') {
        var receiver = expr.receiver;
        if (receiver is kernel.ConstructorInvocation) {
          kernel.Class targetClass = receiver.target.enclosingClass;
          return targetClass.name == '_ConstantExpressionError' &&
              targetClass.enclosingLibrary.importUri.toString() == 'dart:core';
        }
      }
    }
    return false;
  }
}

/**
 * Implementation of [KernelLibraryResynthesizerContext].
 */
class _KernelLibraryResynthesizerContextImpl
    implements KernelLibraryResynthesizerContext {
  final KernelResynthesizer resynthesizer;

  @override
  final kernel.Library library;

  /**
   * The relative URI of the directory with the [library] file.
   * E.g. `sdk/lib/core` for `sdk/lib/core/core.dart`.
   */
  String libraryDirectoryUri;

  Source librarySource;
  LibraryElementImpl libraryElement;

  _KernelLibraryResynthesizerContextImpl(this.resynthesizer, this.library) {
    libraryDirectoryUri = pathos.url.dirname("${library.fileUri}");
  }

  @override
  kernel.Library get coreLibrary => resynthesizer._kernelMap['dart:core'];

  @override
  bool get hasExtUri {
    for (var dependency in library.dependencies) {
      if (dependency.isImport &&
          dependency.targetLibrary.importUri.isScheme('dart-ext')) {
        return true;
      }
    }
    return false;
  }

  @override
  Namespace buildExportNamespace() {
    Namespace publicNamespace = buildPublicNamespace();
    if (library.additionalExports.isEmpty) {
      return publicNamespace;
    }

    Map<String, Element> definedNames = publicNamespace.definedNames;
    for (kernel.Reference additionalExport in library.additionalExports) {
      var element = resynthesizer
          .getElementFromCanonicalName(additionalExport.canonicalName);
      if (element != null) {
        definedNames[element.name] = element;
      }
    }

    return new Namespace(definedNames);
  }

  @override
  Namespace buildPublicNamespace() {
    return new NamespaceBuilder()
        .createPublicNamespaceForLibrary(libraryElement);
  }

  @override
  LibraryElementImpl getLibrary(String uriStr) {
    return resynthesizer.getLibrary(uriStr);
  }

  LibraryElementImpl _buildLibrary(String uriStr) {
    librarySource = resynthesizer._getSource(uriStr);
    if (librarySource == null) return null;
    return libraryElement =
        new LibraryElementImpl.forKernel(resynthesizer._analysisContext, this);
  }

  _KernelUnitResynthesizerContextImpl _buildUnit(String fileUri) {
    var unitContext = new _KernelUnitResynthesizerContextImpl(
        this, fileUri ?? "${library.fileUri}");
    var unitElement = new CompilationUnitElementImpl.forKernel(
        libraryElement, unitContext, '<no name>');
    unitContext.unit = unitElement;
    unitElement.librarySource = librarySource;

    if (fileUri != null) {
      // Compute the URI relative to the library directory.
      // E.g. when the library directory URI is `sdk/lib/core`, and the unit
      // URI is `sdk/lib/core/bool.dart`, the result is `bool.dart`.
      var relativeUri = pathos.url.relative(fileUri, from: libraryDirectoryUri);
      // Compute the absolute URI.
      // When the absolute library URI is `dart:core`, and the relative
      // URI is `bool.dart`, the result is `dart:core/bool.dart`.
      Uri absoluteUri =
          resolveRelativeUri(librarySource.uri, Uri.parse(relativeUri));
      String absoluteUriStr = absoluteUri.toString();
      unitElement.source = resynthesizer._getSource(absoluteUriStr);
    } else {
      unitElement.source = librarySource;
    }

    unitContext.unit = unitElement;
    return unitContext;
  }
}

/**
 * Implementation of [KernelUnit].
 */
class _KernelUnitImpl implements KernelUnit {
  final _KernelUnitResynthesizerContextImpl context;

  List<kernel.Expression> _annotations;
  List<kernel.Class> _classes;
  List<kernel.Field> _fields;
  List<kernel.Procedure> _procedures;
  List<kernel.Typedef> _typedefs;

  _KernelUnitImpl(this.context);

  @override
  List<kernel.Expression> get annotations {
    if (_annotations == null) {
      for (var part in context.libraryContext.library.parts) {
        if ("${part.fileUri}" == context.fileUri) {
          return _annotations = part.annotations;
        }
      }
    }
    return _annotations ?? const <kernel.Expression>[];
  }

  @override
  List<kernel.Class> get classes =>
      _classes ??= context.libraryContext.library.classes
          .where((n) => "${n.fileUri}" == context.fileUri)
          .toList(growable: false);

  @override
  List<kernel.Field> get fields =>
      _fields ??= context.libraryContext.library.fields
          .where((n) => "${n.fileUri}" == context.fileUri)
          .toList(growable: false);

  @override
  List<kernel.Procedure> get procedures =>
      _procedures ??= context.libraryContext.library.procedures
          .where((n) => "${n.fileUri}" == context.fileUri)
          .toList(growable: false);

  @override
  List<kernel.Typedef> get typedefs =>
      _typedefs ??= context.libraryContext.library.typedefs
          .where((n) => "${n.fileUri}" == context.fileUri)
          .toList(growable: false);
}

/**
 * Implementation of [KernelUnitResynthesizerContext].
 */
class _KernelUnitResynthesizerContextImpl
    implements KernelUnitResynthesizerContext {
  static final Uri dartInternalUri = Uri.parse('dart:_internal');

  final _KernelLibraryResynthesizerContextImpl libraryContext;
  final String fileUri;

  CompilationUnitElementImpl unit;

  _KernelUnitResynthesizerContextImpl(this.libraryContext, this.fileUri);

  @override
  KernelUnit get kernelUnit => new _KernelUnitImpl(this);

  @override
  List<ElementAnnotation> buildAnnotations(
      List<kernel.Expression> expressions) {
    int length = expressions.length;
    if (length != 0) {
      var annotations = <ElementAnnotation>[];
      for (var expression in expressions) {
        if (_isSyntheticExternalNameAnnotation(expression)) continue;
        var annotation = _buildAnnotation(unit, expression);
        annotations.add(annotation);
      }
      return annotations;
    } else {
      return const <ElementAnnotation>[];
    }
  }

  @override
  UnitExplicitTopLevelAccessors buildTopLevelAccessors() {
    var accessorsData = new UnitExplicitTopLevelAccessors();
    var implicitVariables = <String, TopLevelVariableElementImpl>{};
    // Build explicit property accessors and implicit fields.
    for (var procedure in kernelUnit.procedures) {
      bool isGetter = procedure.kind == kernel.ProcedureKind.Getter;
      bool isSetter = procedure.kind == kernel.ProcedureKind.Setter;
      if (isGetter || isSetter) {
        var accessor =
            new PropertyAccessorElementImpl.forKernel(unit, procedure);
        accessorsData.accessors.add(accessor);

        // Create or update the implicit variable.
        String name = accessor.displayName;
        TopLevelVariableElementImpl variable = implicitVariables[name];
        if (variable == null) {
          variable = new TopLevelVariableElementImpl(name, -1);
          implicitVariables[name] = variable;
          variable.enclosingElement = unit;
          variable.isSynthetic = true;
          variable.isFinal = isGetter;
        } else {
          variable.isFinal = false;
        }

        // Attach the accessor to the variable.
        accessor.variable = variable;
        if (isGetter) {
          variable.getter = accessor;
        } else {
          variable.setter = accessor;
        }
      }
    }
    accessorsData.implicitVariables.addAll(implicitVariables.values);
    return accessorsData;
  }

  @override
  UnitExplicitTopLevelVariables buildTopLevelVariables() {
    List<kernel.Field> kernelFields = kernelUnit.fields;
    int numberOfVariables = kernelFields.length;
    var variablesData = new UnitExplicitTopLevelVariables(numberOfVariables);
    for (int i = 0; i < numberOfVariables; i++) {
      kernel.Field field = kernelFields[i];

      // Add the explicit variables.
      TopLevelVariableElementImpl variable;
      if (field.isConst && field.initializer != null) {
        variable = new ConstTopLevelVariableElementImpl.forKernel(unit, field);
      } else {
        variable = new TopLevelVariableElementImpl.forKernel(unit, field);
      }
      variablesData.variables[i] = variable;

      // Add the implicit accessors.
      variablesData.implicitAccessors
          .add(new PropertyAccessorElementImpl_ImplicitGetter(variable));
      if (!(variable.isConst || variable.isFinal)) {
        variablesData.implicitAccessors
            .add(new PropertyAccessorElementImpl_ImplicitSetter(variable));
      }
    }
    return variablesData;
  }

  @override
  ConstructorInitializer getConstructorInitializer(
      ConstructorElementImpl constructor, kernel.Initializer k) {
    if (k is kernel.FieldInitializer && k.isSynthetic ||
        k is kernel.SuperInitializer && k.isSynthetic) {
      return null;
    }
    return new _ExprBuilder(this, constructor).buildInitializer(k);
  }

  @override
  Expression getExpression(ElementImpl context, kernel.Expression expression) {
    return new _ExprBuilder(this, context).build(expression);
  }

  @override
  List<List<kernel.VariableDeclaration>> getFunctionTypeParameters(
      kernel.FunctionType type) {
    int positionalCount = type.positionalParameters.length;
    var positionalParameters =
        new List<kernel.VariableDeclaration>(positionalCount);
    for (int i = 0; i < positionalCount; i++) {
      String name = i < type.positionalParameterNames.length
          ? type.positionalParameterNames[i]
          : 'arg_$i';
      positionalParameters[i] = new kernel.VariableDeclaration(name,
          type: type.positionalParameters[i]);
    }

    var namedParameters = type.namedParameters
        .map((k) => new kernel.VariableDeclaration(k.name, type: k.type))
        .toList(growable: false);

    return [positionalParameters, namedParameters];
  }

  @override
  InterfaceType getInterfaceType(
      ElementImpl context, kernel.Supertype kernelType) {
    if (kernelType.classNode.isEnum) {
      return null;
    }
    return libraryContext.resynthesizer._getInterfaceType(
        context, kernelType.className.canonicalName, kernelType.typeArguments);
  }

  @override
  List<InterfaceType> getInterfaceTypes(
      ElementImpl context, List<kernel.Supertype> types) {
    var interfaceTypes = <InterfaceType>[];
    for (kernel.Supertype kernelType in types) {
      InterfaceType interfaceType = getInterfaceType(context, kernelType);
      if (interfaceType != null) {
        interfaceTypes.add(interfaceType);
      }
    }
    return interfaceTypes;
  }

  @override
  ConstructorElementImpl getRedirectedConstructor(
      kernel.Constructor kernelConstructor, kernel.Procedure kernelFactory) {
    if (kernelConstructor != null) {
      for (var initializer in kernelConstructor.initializers) {
        if (initializer is kernel.RedirectingInitializer) {
          return libraryContext.resynthesizer.getElementFromCanonicalName(
                  initializer.targetReference.canonicalName)
              as ConstructorElementImpl;
        }
      }
    }
    if (kernelFactory != null) {
      kernel.Statement body = kernelFactory.function.body;
      if (body is RedirectingFactoryBody) {
        kernel.Member target = body.target;
        if (target != null) {
          return libraryContext.resynthesizer
                  .getElementFromCanonicalName(target.reference.canonicalName)
              as ConstructorElementImpl;
        }
      }
    }
    return null;
  }

  @override
  DartType getType(ElementImpl context, kernel.DartType type) {
    return libraryContext.resynthesizer.getType(context, type);
  }

  ElementAnnotationImpl _buildAnnotation(
      CompilationUnitElementImpl unit, kernel.Expression expression) {
    ElementAnnotationImpl elementAnnotation = new ElementAnnotationImpl(unit);
    Expression constExpr = getExpression(unit, expression);
    if (constExpr is Identifier) {
      elementAnnotation.element = constExpr.staticElement;
      elementAnnotation.annotationAst = AstTestFactory.annotation(constExpr);
    } else if (constExpr is InstanceCreationExpression) {
      elementAnnotation.element = constExpr.staticElement;
      Identifier typeName = constExpr.constructorName.type.name;
      SimpleIdentifier constructorName = constExpr.constructorName.name;
      elementAnnotation.annotationAst = AstTestFactory.annotation2(
          typeName, constructorName, constExpr.argumentList)
        ..element = constExpr.staticElement;
    } else {
      throw new StateError(
          'Unexpected annotation type: ${constExpr.runtimeType}');
    }
    return elementAnnotation;
  }

  /// Fasta converts `native 'name'` clauses to `@ExternalName('name')`
  /// annotations. But we don't actually have these annotations in code. So,
  /// we need to skip them to avoid mismatch with AST.
  static bool _isSyntheticExternalNameAnnotation(kernel.Expression expr) {
    if (expr is kernel.ConstructorInvocation) {
      kernel.Constructor target = expr.target;
      return target != null &&
          target.enclosingClass.name == 'ExternalName' &&
          target.enclosingLibrary.importUri == dartInternalUri;
    }
    return false;
  }
}
