// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
library kernel.checks;

import 'ast.dart';
import 'transformations/flags.dart';

void verifyComponent(Component component) {
  VerifyingVisitor.check(component);
}

class VerificationError {
  final TreeNode context;

  final TreeNode node;

  final String details;

  VerificationError(this.context, this.node, this.details);

  toString() {
    Location location;
    try {
      location = node?.location ?? context?.location;
    } catch (_) {
      // TODO(ahe): Fix the compiler instead.
    }
    if (location != null) {
      String file = location.file?.toString() ?? "";
      return "$file:${location.line}:${location.column}: Verification error:"
          " $details";
    } else {
      return "Verification error: $details\n"
          "Context: '$context'.\n"
          "Node: '$node'.";
    }
  }
}

enum TypedefState { Done, BeingChecked }

/// Checks that a kernel component is well-formed.
///
/// This does not include any kind of type checking.
class VerifyingVisitor extends RecursiveVisitor {
  final Set<Class> classes = new Set<Class>();
  final Set<Typedef> typedefs = new Set<Typedef>();
  Set<TypeParameter> typeParametersInScope = new Set<TypeParameter>();
  final List<VariableDeclaration> variableStack = <VariableDeclaration>[];
  final Map<Typedef, TypedefState> typedefState = <Typedef, TypedefState>{};
  bool classTypeParametersAreInScope = false;

  /// If true, relax certain checks for *outline* mode. For example, don't
  /// attempt to validate constructor initializers.
  bool isOutline = false;

  bool inCatchBlock = false;

  Library currentLibrary;

  Member currentMember;

  Class currentClass;

  TreeNode currentParent;

  TreeNode get context => currentMember ?? currentClass;

  static void check(Component component) {
    component.accept(new VerifyingVisitor());
  }

  defaultTreeNode(TreeNode node) {
    visitChildren(node);
  }

  problem(TreeNode node, String details, {TreeNode context}) {
    context ??= this.context;
    throw new VerificationError(context, node, details);
  }

  TreeNode enterParent(TreeNode node) {
    if (!identical(node.parent, currentParent)) {
      problem(
          node,
          "Incorrect parent pointer on ${node.runtimeType}:"
          " expected '${currentParent.runtimeType}',"
          " but found: '${node.parent.runtimeType}'.",
          context: currentParent);
    }
    var oldParent = currentParent;
    currentParent = node;
    return oldParent;
  }

  void exitParent(TreeNode oldParent) {
    currentParent = oldParent;
  }

  int enterLocalScope() => variableStack.length;

  void exitLocalScope(int stackHeight) {
    for (int i = stackHeight; i < variableStack.length; ++i) {
      undeclareVariable(variableStack[i]);
    }
    variableStack.length = stackHeight;
  }

  void visitChildren(TreeNode node) {
    var oldParent = enterParent(node);
    node.visitChildren(this);
    exitParent(oldParent);
  }

  void visitWithLocalScope(TreeNode node) {
    int stackHeight = enterLocalScope();
    visitChildren(node);
    exitLocalScope(stackHeight);
  }

  void declareMember(Member member) {
    if (member.transformerFlags & TransformerFlag.seenByVerifier != 0) {
      problem(member.function,
          "Member '$member' has been declared more than once.");
    }
    member.transformerFlags |= TransformerFlag.seenByVerifier;
  }

  void undeclareMember(Member member) {
    member.transformerFlags &= ~TransformerFlag.seenByVerifier;
  }

  void declareVariable(VariableDeclaration variable) {
    if (variable.flags & VariableDeclaration.FlagInScope != 0) {
      problem(variable, "Variable '$variable' declared more than once.");
    }
    variable.flags |= VariableDeclaration.FlagInScope;
    variableStack.add(variable);
  }

  void undeclareVariable(VariableDeclaration variable) {
    variable.flags &= ~VariableDeclaration.FlagInScope;
  }

  void declareTypeParameters(List<TypeParameter> parameters) {
    for (int i = 0; i < parameters.length; ++i) {
      var parameter = parameters[i];
      if (parameter.bound == null) {
        problem(
            currentParent, "Missing bound for type parameter '$parameter'.");
      }
      if (!typeParametersInScope.add(parameter)) {
        problem(parameter, "Type parameter '$parameter' redeclared.");
      }
    }
  }

  void undeclareTypeParameters(List<TypeParameter> parameters) {
    typeParametersInScope.removeAll(parameters);
  }

  void checkVariableInScope(VariableDeclaration variable, TreeNode where) {
    if (variable.flags & VariableDeclaration.FlagInScope == 0) {
      problem(where, "Variable '$variable' used out of scope.");
    }
  }

  visitComponent(Component component) {
    try {
      for (var library in component.libraries) {
        for (var class_ in library.classes) {
          if (!classes.add(class_)) {
            problem(class_, "Class '$class_' declared more than once.");
          }
        }
        for (var typedef_ in library.typedefs) {
          if (!typedefs.add(typedef_)) {
            problem(typedef_, "Typedef '$typedef_' declared more than once.");
          }
        }
        library.members.forEach(declareMember);
        for (var class_ in library.classes) {
          class_.members.forEach(declareMember);
        }
      }
      visitChildren(component);
    } finally {
      for (var library in component.libraries) {
        library.members.forEach(undeclareMember);
        for (var class_ in library.classes) {
          class_.members.forEach(undeclareMember);
        }
      }
      variableStack.forEach(undeclareVariable);
    }
  }

  void visitLibrary(Library node) {
    currentLibrary = node;
    super.visitLibrary(node);
    currentLibrary = null;
  }

  void checkTypedef(Typedef node) {
    var state = typedefState[node];
    if (state == TypedefState.Done) return;
    if (state == TypedefState.BeingChecked) {
      problem(node, "The typedef '$node' refers to itself", context: node);
    }
    assert(state == null);
    typedefState[node] = TypedefState.BeingChecked;
    var savedTypeParameters = typeParametersInScope;
    typeParametersInScope = node.typeParameters.toSet();
    var savedParent = currentParent;
    currentParent = node;
    // Visit children without checking the parent pointer on the typedef itself
    // since this can be called from a context other than its true parent.
    node.visitChildren(this);
    currentParent = savedParent;
    typeParametersInScope = savedTypeParameters;
    typedefState[node] = TypedefState.Done;
  }

  visitTypedef(Typedef node) {
    checkTypedef(node);
    // Enter and exit the node to check the parent pointer on the typedef node.
    exitParent(enterParent(node));
  }

  visitField(Field node) {
    currentMember = node;
    var oldParent = enterParent(node);
    bool isTopLevel = node.parent == currentLibrary;
    if (isTopLevel && !node.isStatic) {
      problem(node, "The top-level field '${node.name.name}' should be static",
          context: node);
    }
    if (node.isConst && !node.isStatic) {
      problem(node, "The const field '${node.name.name}' should be static",
          context: node);
    }
    classTypeParametersAreInScope = !node.isStatic;
    node.initializer?.accept(this);
    node.type.accept(this);
    classTypeParametersAreInScope = false;
    visitList(node.annotations, this);
    exitParent(oldParent);
    currentMember = null;
  }

  visitProcedure(Procedure node) {
    currentMember = node;
    var oldParent = enterParent(node);
    classTypeParametersAreInScope = !node.isStatic;
    node.function.accept(this);
    classTypeParametersAreInScope = false;
    visitList(node.annotations, this);
    exitParent(oldParent);
    currentMember = null;
  }

  visitConstructor(Constructor node) {
    currentMember = node;
    classTypeParametersAreInScope = true;
    // The constructor member needs special treatment due to parameters being
    // in scope in the initializer list.
    var oldParent = enterParent(node);
    int stackHeight = enterLocalScope();
    visitChildren(node.function);
    visitList(node.initializers, this);
    if (!isOutline) {
      checkInitializers(node);
    }
    exitLocalScope(stackHeight);
    classTypeParametersAreInScope = false;
    visitList(node.annotations, this);
    exitParent(oldParent);
    classTypeParametersAreInScope = false;
    currentMember = null;
  }

  visitClass(Class node) {
    currentClass = node;
    declareTypeParameters(node.typeParameters);
    var oldParent = enterParent(node);
    classTypeParametersAreInScope = false;
    visitList(node.annotations, this);
    classTypeParametersAreInScope = true;
    visitList(node.typeParameters, this);
    visitList(node.fields, this);
    visitList(node.constructors, this);
    visitList(node.procedures, this);
    exitParent(oldParent);
    undeclareTypeParameters(node.typeParameters);
    currentClass = null;
  }

  visitFunctionNode(FunctionNode node) {
    declareTypeParameters(node.typeParameters);
    bool savedInCatchBlock = inCatchBlock;
    inCatchBlock = false;
    visitWithLocalScope(node);
    inCatchBlock = savedInCatchBlock;
    undeclareTypeParameters(node.typeParameters);
  }

  visitFunctionType(FunctionType node) {
    for (int i = 1; i < node.namedParameters.length; ++i) {
      if (node.namedParameters[i - 1].compareTo(node.namedParameters[i]) >= 0) {
        problem(currentParent,
            "Named parameters are not sorted on function type ($node).");
      }
    }
    declareTypeParameters(node.typeParameters);
    for (var typeParameter in node.typeParameters) {
      typeParameter.bound?.accept(this);
    }
    visitList(node.positionalParameters, this);
    visitList(node.namedParameters, this);
    node.returnType.accept(this);
    undeclareTypeParameters(node.typeParameters);
  }

  visitBlock(Block node) {
    visitWithLocalScope(node);
  }

  visitForStatement(ForStatement node) {
    visitWithLocalScope(node);
  }

  visitForInStatement(ForInStatement node) {
    visitWithLocalScope(node);
  }

  visitLet(Let node) {
    visitWithLocalScope(node);
  }

  visitBlockExpression(BlockExpression node) {
    visitWithLocalScope(node);
  }

  visitCatch(Catch node) {
    bool savedInCatchBlock = inCatchBlock;
    inCatchBlock = true;
    visitWithLocalScope(node);
    inCatchBlock = savedInCatchBlock;
  }

  @override
  visitRethrow(Rethrow node) {
    if (!inCatchBlock) {
      problem(node, "Rethrow must be inside a Catch block.");
    }
  }

  visitVariableDeclaration(VariableDeclaration node) {
    var parent = node.parent;
    if (parent is! Block &&
        !(parent is Catch && parent.body != node) &&
        !(parent is FunctionNode && parent.body != node) &&
        parent is! FunctionDeclaration &&
        !(parent is ForStatement && parent.body != node) &&
        !(parent is ForInStatement && parent.body != node) &&
        parent is! Let &&
        parent is! LocalInitializer) {
      problem(
          node,
          "VariableDeclaration must be a direct child of a Block, "
          "not ${parent.runtimeType}.");
    }
    visitChildren(node);
    declareVariable(node);
  }

  visitVariableGet(VariableGet node) {
    checkVariableInScope(node.variable, node);
    visitChildren(node);
  }

  visitVariableSet(VariableSet node) {
    checkVariableInScope(node.variable, node);
    visitChildren(node);
  }

  @override
  visitStaticGet(StaticGet node) {
    visitChildren(node);
    if (node.target == null) {
      problem(node, "StaticGet without target.");
    }
    // Currently Constructor.hasGetter returns `false` even though fasta uses it
    // as a getter for internal purposes:
    //
    // Fasta is letting all call site of a redirecting constructor be resolved
    // to the real target.  In order to resolve it, it seems to add a body into
    // the redirecting-factory constructor which caches the target constructor.
    // That cache is via a `StaticGet(real-constructor)` node, which we make
    // here pass the verifier.
    if (!node.target.hasGetter && node.target is! Constructor) {
      problem(node, "StaticGet of '${node.target}' without getter.");
    }
    if (node.target.isInstanceMember) {
      problem(node, "StaticGet of '${node.target}' that's an instance member.");
    }
  }

  @override
  visitStaticSet(StaticSet node) {
    visitChildren(node);
    if (node.target == null) {
      problem(node, "StaticSet without target.");
    }
    if (!node.target.hasSetter) {
      problem(node, "StaticSet to '${node.target}' without setter.");
    }
    if (node.target.isInstanceMember) {
      problem(node, "StaticSet to '${node.target}' that's an instance member.");
    }
  }

  @override
  visitStaticInvocation(StaticInvocation node) {
    checkTargetedInvocation(node.target, node);
    if (node.target.isInstanceMember) {
      problem(node,
          "StaticInvocation of '${node.target}' that's an instance member.");
    }
    if (node.isConst &&
        (!node.target.isConst ||
            !node.target.isExternal ||
            node.target.kind != ProcedureKind.Factory)) {
      problem(
          node,
          "Constant StaticInvocation of '${node.target}' that isn't"
          " a const external factory.");
    }
  }

  void checkTargetedInvocation(Member target, InvocationExpression node) {
    visitChildren(node);
    if (target == null) {
      problem(node, "${node.runtimeType} without target.");
    }
    if (target.function == null) {
      problem(node, "${node.runtimeType} without function.");
    }
    if (!areArgumentsCompatible(node.arguments, target.function)) {
      problem(node,
          "${node.runtimeType} with incompatible arguments for '${target}'.");
    }
    int expectedTypeParameters = target is Constructor
        ? target.enclosingClass.typeParameters.length
        : target.function.typeParameters.length;
    if (node.arguments.types.length != expectedTypeParameters) {
      problem(
          node,
          "${node.runtimeType} with wrong number of type arguments"
          " for '${target}'.");
    }
  }

  @override
  visitDirectPropertyGet(DirectPropertyGet node) {
    visitChildren(node);
    if (node.target == null) {
      problem(node, "DirectPropertyGet without target.");
    }
    if (!node.target.hasGetter) {
      problem(node, "DirectPropertyGet of '${node.target}' without getter.");
    }
    if (!node.target.isInstanceMember) {
      problem(
          node,
          "DirectPropertyGet of '${node.target}' that isn't an"
          " instance member.");
    }
  }

  @override
  visitDirectPropertySet(DirectPropertySet node) {
    visitChildren(node);
    if (node.target == null) {
      problem(node, "DirectPropertySet without target.");
    }
    if (!node.target.hasSetter) {
      problem(node, "DirectPropertySet of '${node.target}' without setter.");
    }
    if (!node.target.isInstanceMember) {
      problem(node, "DirectPropertySet of '${node.target}' that is static.");
    }
  }

  @override
  visitDirectMethodInvocation(DirectMethodInvocation node) {
    checkTargetedInvocation(node.target, node);
    if (node.receiver == null) {
      problem(node, "DirectMethodInvocation without receiver.");
    }
  }

  @override
  visitConstructorInvocation(ConstructorInvocation node) {
    checkTargetedInvocation(node.target, node);
    if (node.target.enclosingClass.isAbstract) {
      problem(node, "ConstructorInvocation of abstract class.");
    }
    if (node.isConst && !node.target.isConst) {
      problem(
          node,
          "Constant ConstructorInvocation fo '${node.target}' that"
          " isn't const.");
    }
  }

  bool areArgumentsCompatible(Arguments arguments, FunctionNode function) {
    if (arguments.positional.length < function.requiredParameterCount) {
      return false;
    }
    if (arguments.positional.length > function.positionalParameters.length) {
      return false;
    }
    namedLoop:
    for (int i = 0; i < arguments.named.length; ++i) {
      var argument = arguments.named[i];
      String name = argument.name;
      for (int j = 0; j < function.namedParameters.length; ++j) {
        if (function.namedParameters[j].name == name) continue namedLoop;
      }
      return false;
    }
    return true;
  }

  @override
  visitContinueSwitchStatement(ContinueSwitchStatement node) {
    if (node.target == null) {
      problem(node, "No target.");
    } else if (node.target.parent == null) {
      problem(node, "Target has no parent.");
    } else {
      SwitchStatement statement = node.target.parent;
      for (SwitchCase switchCase in statement.cases) {
        if (switchCase == node.target) return;
      }
      problem(node, "Switch case isn't child of parent.");
    }
  }

  @override
  defaultMemberReference(Member node) {
    if (node.transformerFlags & TransformerFlag.seenByVerifier == 0) {
      problem(
          node, "Dangling reference to '$node', parent is: '${node.parent}'.");
    }
  }

  @override
  visitClassReference(Class node) {
    if (!classes.contains(node)) {
      problem(
          node, "Dangling reference to '$node', parent is: '${node.parent}'.");
    }
  }

  @override
  visitTypedefReference(Typedef node) {
    if (!typedefs.contains(node)) {
      problem(
          node, "Dangling reference to '$node', parent is: '${node.parent}'");
    }
  }

  @override
  visitTypeParameterType(TypeParameterType node) {
    var parameter = node.parameter;
    if (!typeParametersInScope.contains(parameter)) {
      problem(
          currentParent,
          "Type parameter '$parameter' referenced out of"
          " scope, parent is: '${parameter.parent}'.");
    }
    if (parameter.parent is Class && !classTypeParametersAreInScope) {
      problem(
          currentParent,
          "Type parameter '$parameter' referenced from"
          " static context, parent is: '${parameter.parent}'.");
    }
  }

  @override
  visitInterfaceType(InterfaceType node) {
    node.visitChildren(this);
    if (node.typeArguments.length != node.classNode.typeParameters.length) {
      problem(
          currentParent,
          "Type $node provides ${node.typeArguments.length}"
          " type arguments but the class declares"
          " ${node.classNode.typeParameters.length} parameters.");
    }
  }

  @override
  visitTypedefType(TypedefType node) {
    checkTypedef(node.typedefNode);
    node.visitChildren(this);
    if (node.typeArguments.length != node.typedefNode.typeParameters.length) {
      problem(
          currentParent,
          "The typedef type $node provides ${node.typeArguments.length}"
          " type arguments but the typedef declares"
          " ${node.typedefNode.typeParameters.length} parameters.");
    }
  }
}

class CheckParentPointers extends Visitor {
  static void check(TreeNode node) {
    node.accept(new CheckParentPointers(node.parent));
  }

  TreeNode parent;

  CheckParentPointers([this.parent]);

  defaultTreeNode(TreeNode node) {
    if (node.parent != parent) {
      throw new VerificationError(
          parent,
          node,
          "Parent pointer on '${node.runtimeType}' "
          "is '${node.parent.runtimeType}' "
          "but should be '${parent.runtimeType}'.");
    }
    var oldParent = parent;
    parent = node;
    node.visitChildren(this);
    parent = oldParent;
  }
}

void checkInitializers(Constructor constructor) {
  // TODO(ahe): I'll add more here in other CLs.
}
