// Copyright 2019 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "missing_deps.h"

#include <string.h>

#include <iostream>

#include "depfile_parser.h"
#include "deps_log.h"
#include "disk_interface.h"
#include "graph.h"
#include "state.h"
#include "util.h"

namespace {

/// ImplicitDepLoader variant that stores dep nodes into the given output
/// without updating graph deps like the base loader does.
struct NodeStoringImplicitDepLoader : public ImplicitDepLoader {
  NodeStoringImplicitDepLoader(
      State* state, DepsLog* deps_log, DiskInterface* disk_interface,
      DepfileParserOptions const* depfile_parser_options,
      std::vector<Node*>* dep_nodes_output)
      : ImplicitDepLoader(state, deps_log, disk_interface,
                          depfile_parser_options),
        dep_nodes_output_(dep_nodes_output) {}

 protected:
  virtual bool ProcessDepfileDeps(Edge* edge,
                                  std::vector<StringPiece>* depfile_ins,
                                  std::string* err);

 private:
  std::vector<Node*>* dep_nodes_output_;
};

bool NodeStoringImplicitDepLoader::ProcessDepfileDeps(
    Edge* edge, std::vector<StringPiece>* depfile_ins, std::string* err) {
  for (std::vector<StringPiece>::iterator i = depfile_ins->begin();
       i != depfile_ins->end(); ++i) {
    uint64_t slash_bits;
    CanonicalizePath(const_cast<char*>(i->str_), &i->len_, &slash_bits);
    Node* node = state_->GetNode(*i, slash_bits);
    dep_nodes_output_->push_back(node);
  }
  return true;
}

}  // namespace

MissingDependencyScannerDelegate::~MissingDependencyScannerDelegate() {}

void MissingDependencyPrinter::OnMissingDep(Node* node, const std::string& path,
                                            const Rule& generator) {
  std::cout << "Missing dep: " << node->path() << " uses " << path
            << " (generated by " << generator.name() << ")\n";
}

MissingDependencyScanner::MissingDependencyScanner(
    MissingDependencyScannerDelegate* delegate, DepsLog* deps_log, State* state,
    DiskInterface* disk_interface)
    : delegate_(delegate), deps_log_(deps_log), state_(state),
      disk_interface_(disk_interface), missing_dep_path_count_(0) {}

void MissingDependencyScanner::ProcessNode(Node* node) {
  if (!node)
    return;
  Edge* edge = node->in_edge();
  if (!edge)
    return;
  if (!seen_.insert(node).second)
    return;

  for (std::vector<Node*>::iterator in = edge->inputs_.begin();
       in != edge->inputs_.end(); ++in) {
    ProcessNode(*in);
  }

  std::string deps_type = edge->GetBinding("deps");
  if (!deps_type.empty()) {
    DepsLog::Deps* deps = deps_log_->GetDeps(node);
    if (deps)
      ProcessNodeDeps(node, deps->nodes, deps->node_count);
  } else {
    DepfileParserOptions parser_opts;
    std::vector<Node*> depfile_deps;
    NodeStoringImplicitDepLoader dep_loader(state_, deps_log_, disk_interface_,
                                            &parser_opts, &depfile_deps);
    std::string err;
    dep_loader.LoadDeps(edge, &err);
    if (!depfile_deps.empty())
      ProcessNodeDeps(node, &depfile_deps[0], depfile_deps.size());
  }
}

void MissingDependencyScanner::ProcessNodeDeps(Node* node, Node** dep_nodes,
                                               int dep_nodes_count) {
  Edge* edge = node->in_edge();
  std::set<Edge*> deplog_edges;
  for (int i = 0; i < dep_nodes_count; ++i) {
    Node* deplog_node = dep_nodes[i];
    // Special exception: A dep on build.ninja can be used to mean "always
    // rebuild this target when the build is reconfigured", but build.ninja is
    // often generated by a configuration tool like cmake or gn. The rest of
    // the build "implicitly" depends on the entire build being reconfigured,
    // so a missing dep path to build.ninja is not an actual missing dependency
    // problem.
    if (deplog_node->path() == "build.ninja")
      return;
    Edge* deplog_edge = deplog_node->in_edge();
    if (deplog_edge) {
      deplog_edges.insert(deplog_edge);
    }
  }
  std::vector<Edge*> missing_deps;
  for (std::set<Edge*>::iterator de = deplog_edges.begin();
       de != deplog_edges.end(); ++de) {
    if (!PathExistsBetween(*de, edge)) {
      missing_deps.push_back(*de);
    }
  }

  if (!missing_deps.empty()) {
    std::set<std::string> missing_deps_rule_names;
    for (std::vector<Edge*>::iterator ne = missing_deps.begin();
         ne != missing_deps.end(); ++ne) {
      for (int i = 0; i < dep_nodes_count; ++i) {
        if (dep_nodes[i]->in_edge() == *ne) {
          generated_nodes_.insert(dep_nodes[i]);
          generator_rules_.insert(&(*ne)->rule());
          missing_deps_rule_names.insert((*ne)->rule().name());
          delegate_->OnMissingDep(node, dep_nodes[i]->path(), (*ne)->rule());
        }
      }
    }
    missing_dep_path_count_ += missing_deps_rule_names.size();
    nodes_missing_deps_.insert(node);
  }
}

void MissingDependencyScanner::PrintStats() {
  std::cout << "Processed " << seen_.size() << " nodes.\n";
  if (HadMissingDeps()) {
    std::cout << "Error: There are " << missing_dep_path_count_
              << " missing dependency paths.\n";
    std::cout << nodes_missing_deps_.size()
              << " targets had depfile dependencies on "
              << generated_nodes_.size() << " distinct generated inputs "
              << "(from " << generator_rules_.size() << " rules) "
              << " without a non-depfile dep path to the generator.\n";
    std::cout << "There might be build flakiness if any of the targets listed "
                 "above are built alone, or not late enough, in a clean output "
                 "directory.\n";
  } else {
    std::cout << "No missing dependencies on generated files found.\n";
  }
}

bool MissingDependencyScanner::PathExistsBetween(Edge* from, Edge* to) {
  AdjacencyMap::iterator it = adjacency_map_.find(from);
  if (it != adjacency_map_.end()) {
    InnerAdjacencyMap::iterator inner_it = it->second.find(to);
    if (inner_it != it->second.end()) {
      return inner_it->second;
    }
  } else {
    it = adjacency_map_.insert(std::make_pair(from, InnerAdjacencyMap())).first;
  }
  bool found = false;
  for (size_t i = 0; i < to->inputs_.size(); ++i) {
    Edge* e = to->inputs_[i]->in_edge();
    if (e && (e == from || PathExistsBetween(from, e))) {
      found = true;
      break;
    }
  }
  it->second.insert(std::make_pair(to, found));
  return found;
}
