// 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/source/line_info.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/member.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/resolver.dart' show TypeProvider;
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_algebra.dart' as kernel;
import 'package:kernel/type_environment.dart' as kernel;
import 'package:path/path.dart' as pathos;

/// Information about a single file - a library or part.
class KernelFileInfo {
  final bool exists;
  final int contentLength;
  final LineInfo lineInfo;
  final kernel.Library library;

  KernelFileInfo(this.exists, this.contentLength, this.lineInfo, this.library);
}

/**
 * Object that can resynthesize analyzer [LibraryElement] from Kernel.
 */
class KernelResynthesizer implements ElementResynthesizer {
  final AnalysisContextImpl _analysisContext;
  final Map<String, KernelFileInfo> _fileInfoMap;
  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._fileInfoMap) {
    _buildTypeProvider();
    _analysisContext.typeProvider = _typeProvider;
  }

  @override
  AnalysisContext get context => _analysisContext;

  /**
   * TODO(brianwilkerson) Remove this getter.
   */
  bool get strongMode => true;

  /**
   * 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];
    LibraryElementImpl library = getLibrary(libraryUri);
    if (library == null) return null;

    if (componentPtr == 0) {
      return library;
    }

    String topKindOrClassName = components[--componentPtr];

    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 = _fileInfoMap[uriStr].library;
      if (kernel == null) return null;

      if (_fileInfoMap[uriStr]?.exists != 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(uriStr, kernel.fileUri).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 relativeUriStr = kernel.parts[i].partUri;
        var importUriStr =
            resolveRelativeUri(kernel.importUri, Uri.parse(relativeUriStr))
                .toString();
        var fileUri = kernel.fileUri.resolve(relativeUriStr);
        var unitContext = libraryContext._buildUnit(importUriStr, fileUri);
        var partUnit = unitContext.unit;
        parts[i] = partUnit;
      }
      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) {
      return _getFunctionType(context, kernelType);
    }

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

  /// 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');
  }

  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);
  }

  /// Return the [FunctionType] that corresponds to the given [kernelType].
  FunctionType _getFunctionType(
      ElementImpl context, kernel.FunctionType kernelType) {
    if (kernelType.typedef != null) {
      var translatedType = _getTypedefType(context, kernelType);
      if (translatedType != null) return translatedType;
    }

    var element = new FunctionElementImpl('', -1);
    context.encloseElement(element);

    // Set type parameters.
    {
      List<kernel.TypeParameter> typeParameters = kernelType.typeParameters;
      int count = typeParameters.length;
      var astTypeParameters = new List<TypeParameterElement>(count);
      for (int i = 0; i < count; i++) {
        astTypeParameters[i] =
            new TypeParameterElementImpl.forKernel(element, typeParameters[i]);
      }
      element.typeParameters = astTypeParameters;
    }

    // Set formal parameters.
    var parameters = _getFunctionTypeParameters(kernelType);
    var positionalParameters = parameters[0];
    var namedParameters = parameters[1];
    var astParameters = ParameterElementImpl.forKernelParameters(
        element,
        kernelType.requiredParameterCount,
        positionalParameters,
        namedParameters);
    element.parameters = astParameters;

    element.returnType = getType(element, kernelType.returnType);

    return new FunctionTypeImpl(element);
  }

  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 [FunctionType] for the given typedef based [kernelType].
  FunctionType _getTypedefType(
      ElementImpl context, kernel.FunctionType kernelType) {
    kernel.Typedef typedef = kernelType.typedef;

    GenericTypeAliasElementImpl typedefElement =
        getElementFromCanonicalName(typedef.canonicalName);

    kernel.FunctionType typedefType = typedef.type;

    if (kernelType.typeParameters.length != typedefType.typeParameters.length) {
      // Type parameters don't match; just resynthesize as a synthetic function
      // type.
      return null;
    }

    // In the general case imagine the typedef is:
    //     typedef F<T, U> = ... Function<V, W>(...);
    // And kernelType is:
    //     ... Function<X, Y>(...);
    // So the outer type parameters of the typedef have been instantiated (or
    // there were none); the inner type parameters have not been instantiated
    // (or there were none).
    //
    // Now we have to figure out what substitution was used to instantiate
    // the typedef, since the kernel doesn't track that information.
    var substitution = kernel.unifyTypes(
        typedefType, kernelType, typedef.typeParameters.toSet());

    // Convert kernel type arguments into Analyzer types.
    var typeArguments = typedef.typeParameters
        .map((t) => substitution.containsKey(t)
            ? getType(context, substitution[t])
            : _typeProvider.nullType)
        .toList();
    return typedefElement.instantiate(typeArguments);
  }

  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;
  }

  /// Return the list with exactly two elements - positional and named
  /// parameter lists.
  static List<List<kernel.VariableDeclaration>> _getFunctionTypeParameters(
      kernel.FunctionType type) {
    int positionalCount = type.positionalParameters.length;
    var positionalParameters =
        new List<kernel.VariableDeclaration>(positionalCount);
    var knownPositionalParameters = const <kernel.VariableDeclaration>[];
    if (type.typedefReference != null) {
      knownPositionalParameters =
          type.typedefReference.asTypedef.positionalParameters;
    }
    for (int i = 0; i < positionalCount; i++) {
      String name = i < knownPositionalParameters.length
          ? (knownPositionalParameters[i].name ?? '')
          : '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];
  }
}

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

  _ExprBuilder(this._context, this._contextElement);

  TypeProvider get typeProvider =>
      _context.libraryContext.resynthesizer._typeProvider;

  Expression build(kernel.Expression expr) {
    if (_hasInvalidExpression(expr)) {
      return AstTestFactory.identifier3('#invalidConst');
    }
    return _build(expr);
  }

  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;
    }

    if (k is kernel.ShadowInvalidFieldInitializer ||
        k is kernel.ShadowInvalidInitializer ||
        k is kernel.InvalidSuperInitializerJudgment) {
      return null;
    }

    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 = _getTypes([expr.typeArgument]);
      var typeArgumentNodes = _buildTypeArgumentList(typeArguments);
      var elements = expr.expressions.map(_build).toList();
      return AstTestFactory.listLiteral2(keyword, typeArgumentNodes, elements)
        ..staticType = typeProvider.listType.instantiate(typeArguments);
    }

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

      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, typeArgumentNodes, 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.AsExpression && expr.isTypeError) {
      return _build(expr.operand);
    }

    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) {
      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) {
      ConstructorElementImpl element = _getElement(expr.targetReference);

      // It's safe to pass null for the TypeEnvironment because it isn't
      // needed to compute the type of a constructor invocation.
      var kernelType = expr.getStaticType(null);
      var type = _getType(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);
      var creation = AstTestFactory.instanceCreationExpression(
          keyword, constructorName, arguments);
      creation.staticElement = ConstructorMember.from(element, type);
      creation.staticType = type;
      return creation;
    }

    if (expr is kernel.Instantiation) {
      return _build(expr.expression);
    }

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

    // 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) {
    String name = reference.canonicalName.name;
    SimpleIdentifier identifier = AstTestFactory.identifier3(name);
    Element element = _getElement(reference);
    identifier.staticElement = element;
    return identifier;
  }

  TypeAnnotation _buildType(DartType type) {
    List<TypeAnnotation> argumentNodes;
    if (type is ParameterizedType) {
      argumentNodes = _buildTypeArguments(type.typeArguments);
    }
    TypeName node = AstTestFactory.typeName4(type.name, argumentNodes);
    node.type = type;
    (node.name as SimpleIdentifier).staticElement = type.element;
    return node;
  }

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

  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);
  }

  DartType _getType(kernel.DartType kernel) {
    return _context.getType(_contextElement, kernel);
  }

  List<DartType> _getTypes(List<kernel.DartType> kernels) {
    int length = kernels.length;
    var types = new List<DartType>(length);
    for (int i = 0; i < length; i++) {
      DartType type = _getType(kernels[i]);
      types[i] = type;
    }
    return types;
  }

  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);
  }

  static bool _hasInvalidExpression(kernel.Expression expr) {
    var visitor = new _HasInvalidExpressionVisitor();
    expr.accept(visitor);
    return visitor.result;
  }
}

class _HasInvalidExpressionVisitor extends kernel.RecursiveVisitor<void> {
  bool result = false;

  @override
  void visitInvalidExpression(kernel.InvalidExpression node) {
    result = true;
  }
}

/**
 * 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 {
    return resynthesizer._fileInfoMap['dart:core'].library;
  }

  @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 uriStr, Uri fileUri) {
    var unitContext = new _KernelUnitResynthesizerContextImpl(this, fileUri);

    var unitElement = new CompilationUnitElementImpl.forKernel(
        libraryElement, unitContext, '<no name>');
    unitContext.unit = unitElement;
    unitElement.librarySource = librarySource;
    if (!fileUri.isScheme('org-dartlang-malformed-uri')) {
      var fileInfo = resynthesizer._fileInfoMap[uriStr];
      unitElement.setCodeRange(0, fileInfo.contentLength);
      unitElement.lineInfo = fileInfo.lineInfo;
      unitElement.source = resynthesizer._getSource(uriStr);
    }

    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) {
      var libraryFileUri = context.libraryContext.library.fileUri;
      for (var part in context.libraryContext.library.parts) {
        if (libraryFileUri.resolve(part.partUri) == 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 Uri 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) {
    return KernelResynthesizer._getFunctionTypeParameters(type);
  }

  @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
  ConstructorElement getRedirectedConstructor(ElementImpl context,
      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) {
          ConstructorElementImpl constructorElement = libraryContext
              .resynthesizer
              .getElementFromCanonicalName(target.reference.canonicalName);
          var typeArguments = body.typeArguments;
          if (typeArguments != null) {
            var classElement = constructorElement.enclosingElement;

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

            return ConstructorMember.from(constructorElement, instantiatedType);
          } else {
            return constructorElement;
          }
        }
      }
    }
    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;
  }
}
