// 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_algebra.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.fileUri.resolve(kernel.parts[i].partUri);
        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) {
      return _getFunctionType(context, kernelType);
    }

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

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

    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);
    GenericFunctionTypeElementImpl functionElement = typedefElement.function;

    kernel.FunctionType typedefType = typedef.type;
    var kernelTypeParameters = typedef.typeParameters.toList();
    kernelTypeParameters.addAll(typedefType.typeParameters);

    // If no type parameters, the raw type of the element will do.
    FunctionTypeImpl rawType = functionElement.type;
    if (kernelTypeParameters.isEmpty) {
      return rawType;
    }

    // Compute type arguments for kernel type parameters.
    var kernelMap = kernel.unifyTypes(typedefType.withoutTypeParameters,
        kernelType.withoutTypeParameters, kernelTypeParameters.toSet());

    // Prepare Analyzer type parameters, in the same order as kernel ones.
    var astTypeParameters = typedefElement.typeParameters.toList();
    astTypeParameters.addAll(functionElement.typeParameters);

    // Convert kernel type arguments into Analyzer types.
    int length = astTypeParameters.length;
    var usedTypeParameters = <TypeParameterElement>[];
    var usedTypeArguments = <DartType>[];
    for (var i = 0; i < length; i++) {
      var kernelParameter = kernelTypeParameters[i];
      var kernelArgument = kernelMap[kernelParameter];
      if (kernelArgument == null ||
          kernelArgument is kernel.TypeParameterType &&
              kernelArgument.parameter.parent == null) {
        continue;
      }
      TypeParameterElement astParameter = astTypeParameters[i];
      DartType astArgument = getType(context, kernelArgument);
      usedTypeParameters.add(astParameter);
      usedTypeArguments.add(astArgument);
    }

    if (usedTypeParameters.isEmpty) {
      return rawType;
    }

    // Replace Analyzer type parameters with type arguments.
    throw new UnimplementedError(
        'TODO(paulberry): resynthesize generic typedef');
  }

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

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

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

    if (k is kernel.ShadowInvalidInitializer) {
      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 = _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);
    }

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

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

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

    // 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) {
    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<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 _isStaticError(kernel.Expression expr) {
    return expr is kernel.InvalidExpression;
  }
}

/**
 * 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) {
      String absoluteUriStr;
      if (fileUri.startsWith('file://')) {
        // 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));
        absoluteUriStr = absoluteUri.toString();
      } else {
        // File URIs must have the "file" scheme.
        // But for invalid URIs, which cannot be even parsed, FrontEnd returns
        // URIs with the "org-dartlang-malformed-uri" scheme, and does not
        // resolve them to file URIs.
        // We don't have anything better than to use these URIs as is.
        absoluteUriStr = fileUri;
      }
      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 ("${context.libraryContext.library.fileUri.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 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) {
    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
  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;
  }
}
