// 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 'dart:collection';

import 'package:collection/collection.dart';
import 'package:kernel/core_types.dart';
import 'package:kernel/kernel.dart' hide Pattern;
import 'package:path/path.dart' as p;

import 'constants.dart';

Never throwUnsupportedInvalidType(InvalidType type) => throw UnsupportedError(
  'Unsupported invalid type $type (${type.runtimeType}).',
);

Never throwUnsupportedAuxiliaryType(AuxiliaryType type) =>
    throw UnsupportedError(
      'Unsupported auxiliary type $type (${type.runtimeType}).',
    );

Never throwUnsupportedExperimentalType(ExperimentalType type) =>
    throw UnsupportedError(
      'Unsupported experimental type $type (${type.runtimeType}).',
    );

Constructor? unnamedConstructor(Class c) =>
    c.constructors.firstWhereOrNull((c) => c.name.text == '');

/// Returns `true` when a class is eligible to be used as a mixin without
/// having the mixin class modifier in Dart language versions < 3.0.
extension ClassExtension on Class {
  bool isLegacyMixinEligible(CoreTypes coreTypes) =>
      !isMixinDeclaration && superclass == coreTypes.objectClass;
}

/// Returns the enclosing library for reference [node].
Library getLibrary(NamedNode node) {
  for (TreeNode? n = node; n != null; n = n.parent) {
    if (n is Library) return n;
  }
  throw UnsupportedError('Could not find a containing library for $node');
}

final Pattern _syntheticTypeCharacters = RegExp('[&^#.|]');

String escapeIdentifier(String identifier) {
  // Remove the special characters used to encode mixin application class names
  // and extension method / parameter names which are legal in Kernel, but not
  // in JavaScript.
  //
  // Note, there is an implicit assumption here that we won't have
  // collisions since everything is mapped to \$.  That may work out fine given
  // how these are synthesized, but may need to revisit.
  return identifier.replaceAll(_syntheticTypeCharacters, r'$');
}

/// Returns the escaped name for class [node].
///
/// The caller of this function has to make sure that this name is unique in
/// the current scope.
String getLocalClassName(Class node) => escapeIdentifier(node.name);

/// Returns the escaped name for the type parameter [node].
String getTypeParameterName(
  /* TypeParameter | StructuralParameter */ Object node,
) {
  assert(node is TypeParameter || node is StructuralParameter);
  if (node is TypeParameter) {
    return escapeIdentifier(node.name!);
  } else {
    node as StructuralParameter;
    return escapeIdentifier(node.name!);
  }
}

String getTopLevelName(NamedNode n) {
  if (n is Procedure) return n.name.text;
  if (n is Class) return n.name;
  if (n is Typedef) return n.name;
  if (n is Field) return n.name.text;
  return n.reference.canonicalName!.name;
}

/// Given an annotated [node] and a [test] function, returns the first matching
/// constant valued annotation.
///
/// For example if we had the ClassDeclaration node for `FontElement`:
///
///    @js.JS('HTMLFontElement')
///    @deprecated
///    class FontElement { ... }
///
/// We could match `@deprecated` with a test function like:
///
///    (v) => v.type.name == 'Deprecated' && v.type.element.library.isDartCore
///
Expression? findAnnotation(TreeNode node, bool Function(Expression) test) {
  List<Expression> annotations;
  if (node is Class) {
    annotations = node.annotations;
  } else if (node is Typedef) {
    annotations = node.annotations;
  } else if (node is Procedure) {
    annotations = node.annotations;
  } else if (node is Member) {
    annotations = node.annotations;
  } else if (node is Library) {
    annotations = node.annotations;
  } else {
    return null;
  }
  return annotations.firstWhereOrNull(test);
}

/// Returns true if [value] represents an annotation for class [className] in
/// "dart:" library [libraryName].
bool isBuiltinAnnotation(
  Expression value,
  String libraryName,
  String className,
) {
  var c = getAnnotationClass(value);
  if (c != null && c.name == className) {
    var uri = c.enclosingLibrary.importUri;
    return uri.isScheme('dart') && uri.path == libraryName;
  }
  return false;
}

/// Gets the class of the instance referred to by metadata annotation [node].
///
/// For example:
///
/// - `@JS()` would return the "JS" class in "dart:_js_annotations".
/// - `@anonymous` would return the "_Anonymous" class in
/// "dart:_js_annotations".
///
/// This function works regardless of whether the CFE is evaluating constants,
/// or whether the constant is a field reference (such as "anonymous" above).
Class? getAnnotationClass(Expression node) {
  if (node is ConstantExpression) {
    var constant = node.constant;
    if (constant is InstanceConstant) return constant.classNode;
  } else if (node is ConstructorInvocation) {
    return node.target.enclosingClass;
  } else if (node is StaticGet) {
    var type = node.target.getterType;
    if (type is InterfaceType) return type.classNode;
  }
  return null;
}

bool isFromEnvironmentInvocation(CoreTypes coreTypes, StaticInvocation node) {
  var target = node.target;
  return node.isConst &&
      target.name.text == 'fromEnvironment' &&
      target.enclosingLibrary == coreTypes.coreLibrary;
}

List<Class> getSuperclasses(Class? c) {
  var result = <Class>[];
  var visited = HashSet<Class>();
  while (c != null && visited.add(c)) {
    for (var m = c.mixedInClass; m != null; m = m.mixedInClass) {
      result.add(m);
    }
    var superclass = c.superclass;
    if (superclass == null) break;
    result.add(superclass);
    c = superclass;
  }
  return result;
}

List<Class> getImmediateSuperclasses(Class c) {
  var result = <Class>[];
  var m = c.mixedInClass;
  if (m != null) result.add(m);
  var s = c.superclass;
  if (s != null) result.add(s);
  return result;
}

Expression? getInvocationReceiver(InvocationExpression node) {
  if (node is InstanceInvocation) {
    return node.receiver;
  } else if (node is DynamicInvocation) {
    return node.receiver;
  } else if (node is FunctionInvocation) {
    return node.receiver;
  } else if (node is LocalFunctionInvocation) {
    return VariableGet(node.variable);
  }
  return null;
}

bool isInlineJS(Member e) =>
    e is Procedure && _isProcedureFromForeignHelper('JS', e);

/// Returns `true` if [p] is the procedure named [name] from the
/// 'dart:_foreign_helper' library.
bool _isProcedureFromForeignHelper(String name, Procedure p) =>
    p.name.text == name &&
    p.enclosingLibrary.importUri.toString() == 'dart:_foreign_helper';

/// Whether the parameter [p] is covariant (either explicitly `covariant` or
/// implicitly due to generics) and needs a check for soundness.
bool isCovariantParameter(VariableDeclaration p) {
  return p.isCovariantByDeclaration || p.isCovariantByClass;
}

/// Whether the field [p] is covariant (either explicitly `covariant` or
/// implicitly due to generics) and needs a check for soundness.
bool isCovariantField(Field f) {
  return f.isCovariantByDeclaration || f.isCovariantByClass;
}

/// Returns true iff this factory constructor just throws [UnsupportedError]/
///
/// `dart:html` has many of these.
bool isUnsupportedFactoryConstructor(Procedure node) {
  if (node.name.isPrivate && node.enclosingLibrary.importUri.isScheme('dart')) {
    var body = node.function.body;
    if (body is Block) {
      var statements = body.statements;
      if (statements.length == 1) {
        var statement = statements[0];
        if (statement is ExpressionStatement) {
          var expr = statement.expression;
          if (expr is Throw) {
            var error = expr.expression;

            // HTML adds a lot of private constructors that are unreachable.
            // Skip these.
            return isBuiltinAnnotation(error, 'core', 'UnsupportedError');
          }
        }
      }
    }
  }
  return false;
}

bool hasPragma(Annotatable node, String name, CoreTypes coreTypes) {
  for (var a in node.annotations) {
    if (a is! ConstantExpression) continue;
    final value = a.constant;
    if (value is! InstanceConstant) continue;
    if (value.classReference != coreTypes.pragmaClass.reference) {
      continue;
    }
    final nameValue = value.fieldValues[coreTypes.pragmaName.fieldReference];
    if (nameValue is StringConstant && nameValue.value == name) {
      return true;
    }
  }
  return false;
}

/// Gets the real supertype of [c] and the list of [mixins] in reverse
/// application order (mixins will appear before ones they override).
///
/// This is used to ignore synthetic mixin application classes.
///
// TODO(jmesserly): consider replacing this with Kernel's mixin unrolling
Class getSuperclassAndMixins(Class c, List<Class> mixins) {
  assert(mixins.isEmpty);
  assert(c.superclass != null);

  var mixedInClass = c.mixedInClass;
  if (mixedInClass != null) mixins.add(mixedInClass);

  var sc = c.superclass!;
  for (; sc.isAnonymousMixin; sc = sc.superclass!) {
    mixedInClass = sc.mixedInClass;
    if (mixedInClass != null) mixins.add(sc.mixedInClass!);
  }
  return sc;
}

/// Returns true if a switch statement contains any continues with a label.
bool hasLabeledContinue(SwitchStatement node) {
  var visitor = LabelContinueFinder();
  node.accept(visitor);
  return visitor.found;
}

class LabelContinueFinder extends RecursiveVisitor {
  var found = false;

  void visit(Statement? s) {
    if (!found && s != null) s.accept(this);
  }

  @override
  void visitContinueSwitchStatement(ContinueSwitchStatement node) =>
      found = true;
}

/// Returns true if a class contains any 'super' calls.
bool hasSuper(Class node) {
  var visitor = SuperFinder();
  node.accept(visitor);
  return visitor.found;
}

class SuperFinder extends RecursiveVisitor {
  var found = false;

  void visit(Statement? s) {
    if (!found && s != null) s.accept(this);
  }

  @override
  void visitAbstractSuperPropertyGet(AbstractSuperPropertyGet node) =>
      found = true;

  @override
  void visitAbstractSuperPropertySet(AbstractSuperPropertySet node) =>
      found = true;

  @override
  void visitSuperPropertyGet(SuperPropertyGet node) => found = true;

  @override
  void visitSuperPropertySet(SuperPropertySet node) => found = true;

  @override
  void visitAbstractSuperMethodInvocation(AbstractSuperMethodInvocation node) =>
      found = true;

  @override
  void visitSuperMethodInvocation(SuperMethodInvocation node) => found = true;
}

/// Returns `true` if any of [n]s children are a [FunctionExpression] node.
bool containsFunctionExpression(Node n) {
  var visitor = _FunctionExpressionFinder.instance;
  visitor.found = false;
  n.accept(visitor);
  return visitor.found;
}

class _FunctionExpressionFinder extends RecursiveVisitor {
  var found = false;

  static final instance = _FunctionExpressionFinder();

  @override
  void visitFunctionExpression(FunctionExpression node) => found = true;
}

/// Whether [member] is declared native, as in:
///
///    void foo() native;
///
/// This syntax is only allowed in sdk libraries and native tests.
bool isNative(Member member) =>
    // The CFE represents `native` members with the `external` bit and with an
    // internal @ExternalName annotation as a marker.
    member.isExternal && member.annotations.any(_isNativeMarkerAnnotation);

bool _isNativeMarkerAnnotation(Expression annotation) {
  if (annotation is ConstantExpression) {
    var constant = annotation.constant;
    if (constant is InstanceConstant &&
        constant.classNode.name == 'ExternalName' &&
        _isDartInternal(constant.classNode.enclosingLibrary.importUri)) {
      return true;
    }
  }
  return false;
}

bool _isDartInternal(Uri uri) =>
    uri.isScheme('dart') && uri.path == '_internal';

/// Collects all `TypeParameter`s from the `TypeParameterType`s present in the
/// visited `DartType`.
class TypeParameterFinder extends RecursiveVisitor {
  final _found = <TypeParameter>{};
  static TypeParameterFinder? _instance;

  TypeParameterFinder._();
  factory TypeParameterFinder.instance() {
    if (_instance != null) return _instance!;
    return TypeParameterFinder._();
  }

  Set<TypeParameter> find(DartType type) {
    _found.clear();
    type.accept(this);
    return _found;
  }

  @override
  void visitTypeParameterType(TypeParameterType node) =>
      _found.add(node.parameter);
}

/// Collects [InterfaceType] nodes that appear in in a DartType.
class InterfaceTypeExtractor extends RecursiveVisitor {
  final Set<InterfaceType> _found = {};

  @override
  void visitInterfaceType(InterfaceType node) {
    _found.add(node);
    node.visitChildren(this);
  }

  /// Returns all [InterfaceType]s that appear in [type].
  Iterable<InterfaceType> extract(DartType type) {
    type.accept(this);
    return _found;
  }
}

/// Replaces [VariableGet] nodes with a different expression defined by a
/// replacement map.
class VariableGetReplacer extends Transformer {
  final Map<VariableDeclaration, Expression> _replacements;

  VariableGetReplacer(this._replacements);

  @override
  TreeNode visitVariableGet(VariableGet node) {
    var replacement = _replacements[node.variable];
    return replacement ?? node;
  }
}

/// Tests a [StaticInvocation] node to determine if it would be safe to inline.
///
/// Each static invocation should be inspected individually as this class only
/// inspects the body of a given invocation target, and does not recurse
/// transitively into the bodies of other invocations it finds.
///
/// The determination of what is safe to inline is specifically targeting simple
/// methods in the dart:_rti library and has not been validated to use as an
/// inliner for static methods from any other libraries. Instead of inlining by
/// introducing let variables that preserve the evaluation order of the call,
/// only code where it is safe to replace the argument of the call at the
/// place where it used is considered suitable.
///
/// The body of the target method may only contain simple expressions known to
/// have no side-effects like null, bool or string literals, constants, enum
/// values, and variable accesses. Additionally some static invocations from the
/// runtime libraries are permitted in the body when they have been manually
/// inspected for side effects and annotated as safe with
/// `@pragma('ddc:trust-inline`). After the last method argument has been used,
/// this restriction is weakened to allow any static invocations to appear.
class BasicInlineTester extends TreeVisitorDefault<bool> {
  /// The constants used to access constant evaluation for annotations.
  final DevCompilerConstants _constants;

  /// The order that the arguments are expected to used in the body of the
  /// function for it to be considered safe for inlining.
  ///
  /// This is essential to preserve the execution order of the expressions
  /// passed as arguments.
  List<VariableDeclaration>? _expectedArgumentOrder;

  /// The position in [_expectedArgumentOrder] to begin looking for the next
  /// used argument.
  int _nextArgIndex = 0;

  /// Returns `true` if uses of all the expected arguments have already been
  /// seen by the visitor.
  bool get _allArgumentsUsed => _nextArgIndex >= _expectedArgumentOrder!.length;

  BasicInlineTester(this._constants);

  /// Returns `true` when [possibleInline] is considered simple enough to
  /// be safe to inline.
  ///
  /// The considerations for inlining are designed specifically to target select
  /// invocations in the dart:_rti library.
  bool canInline(FunctionNode possibleInline) {
    if (possibleInline.namedParameters.isNotEmpty ||
        possibleInline.typeParameters.isNotEmpty ||
        possibleInline.positionalParameters.length !=
            possibleInline.requiredParameterCount) {
      // Only consider functions with required positional arguments.
      return false;
    }
    final body = possibleInline.body;
    // No code available here to inline.
    if (body == null) return false;

    _expectedArgumentOrder = possibleInline.positionalParameters;
    _nextArgIndex = 0;
    // Important to note that the static invocation being considered for inline
    // is not visited. Instead the body of the target function being invoked is
    // visited to determine if inlining is feasible. Any other static
    // invocations appearing within that body *will* be visited.
    final result = body.accept(this);
    // Avoid retaining any of the arguments after returning.
    _expectedArgumentOrder = null;
    return result;
  }

  /// Returns `true` when [node] is annotated with
  /// `@pragma('ddc:trust-inline`)`.
  bool _hasTrustInlinePragma(NamedNode node) {
    var annotation = findAnnotation(node, (e) {
      if (!isBuiltinAnnotation(e, 'core', 'pragma')) return false;
      var name = _constants.getFieldValueFromAnnotation(e, 'name') as String?;
      return name == 'ddc:trust-inline';
    });
    return annotation != null;
  }

  @override
  bool defaultTreeNode(Node _) => false;

  @override
  bool visitReturnStatement(ReturnStatement node) {
    var returnExpression = node.expression;
    return returnExpression == null ? false : returnExpression.accept(this);
  }

  @override
  bool visitBlock(Block node) {
    if (node.statements.length != 1) return false;
    return node.statements.single.accept(this);
  }

  @override
  bool visitStaticInvocation(StaticInvocation node) {
    // Reaching this visitor means that a static invocation appears in the body
    // of the function being evaluated for inlining.
    var positionalArgs = node.arguments.positional;
    if (isInlineJS(node.target)) {
      // Ensure JS expressions do not span multiple statements. Since these are
      // inlined elsewhere we don't want to accidentally combine multiple
      // Javascript statements into a position where they don't belong. Instead
      // of inspecting if it is valid, just reject any source templates that
      // contain ';' characters.
      var codeLiteral = positionalArgs[1];
      String? code;
      if (codeLiteral is StringLiteral) {
        code = codeLiteral.value;
      } else if (codeLiteral is ConstantExpression) {
        var constant = codeLiteral.constant;
        if (constant is StringConstant) {
          code = constant.value;
        }
      }
      if (code == null || code.contains(';')) return false;
    }
    // Inspect the arguments.
    for (var argument in positionalArgs) {
      if (!argument.accept(this)) return false;
    }
    // While all of the uses of the arguments are still being discovered,
    // only allow additional static invocations explicitly annotated as
    // trusted. This prevents inlining a static invocation that could
    // change the evaluation order of the expressions passed as arguments.
    // Example:
    // ```
    // echo(s) {
    //   print(s);
    //   return s;
    // }
    //
    // dangerous(arg1, arg2) {
    //   return fn(arg1, echo('third'), arg2);
    // }
    // ```
    // Calls to `dangerous()` should not be inlined without let variables
    // because the expression evaluation order would be disrupted:
    // ```
    // dangerous(echo('first'), echo('second'));
    //    |   |
    //    V   V
    // fn(echo('first'), echo('third'), echo('second')) // INVALID!
    return _allArgumentsUsed || _hasTrustInlinePragma(node.target);
  }

  @override
  bool visitBoolLiteral(BoolLiteral _) => true;

  @override
  bool visitNullLiteral(NullLiteral _) => true;

  @override
  bool visitStringLiteral(StringLiteral _) => true;

  @override
  bool visitConstantExpression(ConstantExpression _) => true;

  @override
  bool visitVariableGet(VariableGet node) {
    // The variable is an argument of the function to be inlined. Verify it
    // appears in an order consistent with the order the arguments appeared
    // in the call.
    final location = _expectedArgumentOrder!.indexOf(
      node.variable,
      _nextArgIndex,
    );
    // Either the variable isn't one of the expected arguments at all, or it is
    // appearing out of the expected order.
    if (location == -1) return false;
    // Advance the start of the expected range past the variable just found to
    // ensure the variable can only be used once.
    _nextArgIndex = location + 1;
    return true;
  }

  @override
  bool visitField(Field node) => node.isEnumElement;

  @override
  bool visitStaticGet(StaticGet node) {
    return node.target.accept(this);
  }
}

extension MemberHelpers on Member {
  /// Returns `true` if this is the `hashCode` or `runtimeType` getter.
  bool get isCoreObjectGetter =>
      isInstanceMember &&
      (name.text == 'hashCode' || name.text == 'runtimeType');
}

extension ProcedureHelpers on Procedure {
  /// Returns `true` if [name] is an operator method that is available on
  /// primitive types (`int`, `double`, `num`, `String`, `bool`).
  ///
  /// This does not include logical operators that cannot be user-defined
  /// (`!`, `&&` and `||`).
  bool get isPrimitiveOperator {
    switch (name.text) {
      case '==':
      case '~':
      case '^':
      case '|':
      case '&':
      case '>>':
      case '<<':
      case '>>>':
      case '+':
      case 'unary-':
      case '-':
      case '*':
      case '/':
      case '~/':
      case '>':
      case '<':
      case '>=':
      case '<=':
      case '%':
        return true;
    }
    return false;
  }

  /// Returns `true` if this is any `toString` or `noSuchMethod` method
  /// implementation.
  ///
  /// See [isToStringOrNoSuchMethodWithDefaultSignature] to test for a
  /// `toString` or `noSuchMethod` implementation with a default signature.
  bool get isToStringOrNoSuchMethod =>
      isInstanceMember &&
      (name.text == 'toString' || name.text == 'noSuchMethod');

  /// Returns `true` if this is any `toString` or `noSuchMethod` method
  /// implementation with the default signature.
  ///
  /// For example this will return `false` if this is an override with optional
  /// positional or named parameters.
  ///
  /// See [isToStringOrNoSuchMethod] to test for any `toString` or
  /// `noSuchMethod` implementation.
  bool get isToStringOrNoSuchMethodWithDefaultSignature {
    if (function.namedParameters.isNotEmpty ||
        function.typeParameters.isNotEmpty) {
      return false;
    }
    if (name.text == 'toString') {
      return function.positionalParameters.isEmpty;
    } else if (name.text == 'noSuchMethod') {
      return function.positionalParameters.length == 1;
    }
    return false;
  }
}

extension InstanceInvocationHelpers on InstanceInvocation {
  /// Returns `true` when this represents an invocation of `List.add()` that
  /// can be optimized.
  ///
  /// For example, a List literal that uses control flow collections to add
  /// elements can safely push directly to the backing array:
  ///
  /// ```
  /// final myList = [if (test) 1, ...otherList, 2, 3, if (otherTest) 1];
  /// ```
  ///
  /// The optimized add operation can skip checks for a growable or modifiable
  /// list and the element type is known to be invariant so it can skip the
  /// type check.
  bool isNativeListInvariantAddInvocation(Class coreListClass) {
    if (isInvariant && name.text == 'add') {
      // The call to add is marked as invariant, so the type check on the
      // parameter to add is not needed.
      var receiver_ = receiver;
      if (receiver_ is VariableGet &&
          receiver_.variable.isFinal &&
          !receiver_.variable.isLate) {
        // The receiver is a final variable, so it only contains the
        // initializer value. Also, avoid late variables in case the CFE
        // lowering of late variables is changed in the future.
        var initializer = receiver_.variable.initializer;
        if (initializer is ListLiteral) {
          // The initializer is a list literal, so we know the list can be
          // grown, modified, and is represented by a JavaScript Array.
          return true;
        }
        if (initializer is StaticInvocation &&
            initializer.target.enclosingClass == coreListClass &&
            initializer.target.name.text == 'of' &&
            initializer.arguments.named.isEmpty) {
          // The initializer is a `List.of()` call from the dart:core library
          // and the growable named argument has not been passed (it defaults
          // to true).
          return true;
        }
      }
    }
    return false;
  }
}

extension LibraryHelpers on Library {
  /// Returns the size in bytes of the Dart source code for this library.
  ///
  /// This includes the size of the library source and all part sources.
  int get dartSize {
    final uriToSource = enclosingComponent!.uriToSource;

    final libUri = fileUri;
    final source = uriToSource[libUri];
    if (source == null) {
      // Sources that only contain external declarations have nothing to add to
      // the sum.
      return 0;
    }
    var dartSize = source.source.length;
    for (final part in parts) {
      var partUri = part.partUri;
      if (partUri.startsWith(importUri.scheme)) {
        // Convert to a relative-to-library uri in order to compute a file uri.
        partUri = p.relative(partUri, from: p.dirname('$importUri'));
      }
      final fileUri = libUri.resolve(partUri);
      final partSource = uriToSource[fileUri];
      if (partSource == null) {
        // Sources that only contain external declarations have nothing to add
        // to the sum.
        continue;
      }
      dartSize += partSource.source.length;
    }

    return dartSize;
  }
}
