//===--- AvoidBindCheck.cpp - clang-tidy-----------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "AvoidBindCheck.h"
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Lex/Lexer.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Regex.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cstddef>
#include <string>

using namespace clang::ast_matchers;

namespace clang {
namespace tidy {
namespace modernize {

namespace {

enum BindArgumentKind { BK_Temporary, BK_Placeholder, BK_CallExpr, BK_Other };

struct BindArgument {
  StringRef Tokens;
  BindArgumentKind Kind = BK_Other;
  size_t PlaceHolderIndex = 0;
};

} // end namespace

static SmallVector<BindArgument, 4>
buildBindArguments(const MatchFinder::MatchResult &Result, const CallExpr *C) {
  SmallVector<BindArgument, 4> BindArguments;
  llvm::Regex MatchPlaceholder("^_([0-9]+)$");

  // Start at index 1 as first argument to bind is the function name.
  for (size_t I = 1, ArgCount = C->getNumArgs(); I < ArgCount; ++I) {
    const Expr *E = C->getArg(I);
    BindArgument B;
    if (const auto *M = dyn_cast<MaterializeTemporaryExpr>(E)) {
      const auto *TE = M->GetTemporaryExpr();
      B.Kind = isa<CallExpr>(TE) ? BK_CallExpr : BK_Temporary;
    }

    B.Tokens = Lexer::getSourceText(
        CharSourceRange::getTokenRange(E->getLocStart(), E->getLocEnd()),
        *Result.SourceManager, Result.Context->getLangOpts());

    SmallVector<StringRef, 2> Matches;
    if (B.Kind == BK_Other && MatchPlaceholder.match(B.Tokens, &Matches)) {
      B.Kind = BK_Placeholder;
      B.PlaceHolderIndex = std::stoi(Matches[1]);
    }
    BindArguments.push_back(B);
  }
  return BindArguments;
}

static void addPlaceholderArgs(const ArrayRef<BindArgument> Args,
                               llvm::raw_ostream &Stream) {
  auto MaxPlaceholderIt =
      std::max_element(Args.begin(), Args.end(),
                       [](const BindArgument &B1, const BindArgument &B2) {
                         return B1.PlaceHolderIndex < B2.PlaceHolderIndex;
                       });

  // Placeholders (if present) have index 1 or greater.
  if (MaxPlaceholderIt == Args.end() || MaxPlaceholderIt->PlaceHolderIndex == 0)
    return;

  size_t PlaceholderCount = MaxPlaceholderIt->PlaceHolderIndex;
  Stream << "(";
  StringRef Delimiter = "";
  for (size_t I = 1; I <= PlaceholderCount; ++I) {
    Stream << Delimiter << "auto && arg" << I;
    Delimiter = ", ";
  }
  Stream << ")";
}

static void addFunctionCallArgs(const ArrayRef<BindArgument> Args,
                                llvm::raw_ostream &Stream) {
  StringRef Delimiter = "";
  for (const auto &B : Args) {
    if (B.PlaceHolderIndex)
      Stream << Delimiter << "arg" << B.PlaceHolderIndex;
    else
      Stream << Delimiter << B.Tokens;
    Delimiter = ", ";
  }
}

static bool isPlaceHolderIndexRepeated(const ArrayRef<BindArgument> Args) {
  llvm::SmallSet<size_t, 4> PlaceHolderIndices;
  for (const BindArgument &B : Args) {
    if (B.PlaceHolderIndex) {
      if (!PlaceHolderIndices.insert(B.PlaceHolderIndex).second)
        return true;
    }
  }
  return false;
}

void AvoidBindCheck::registerMatchers(MatchFinder *Finder) {
  if (!getLangOpts().CPlusPlus14) // Need C++14 for generic lambdas.
    return;

  Finder->addMatcher(
      callExpr(
          callee(namedDecl(hasName("::std::bind"))),
          hasArgument(0, declRefExpr(to(functionDecl().bind("f"))).bind("ref")))
          .bind("bind"),
      this);
}

void AvoidBindCheck::check(const MatchFinder::MatchResult &Result) {
  const auto *MatchedDecl = Result.Nodes.getNodeAs<CallExpr>("bind");
  auto Diag = diag(MatchedDecl->getLocStart(), "prefer a lambda to std::bind");

  const auto Args = buildBindArguments(Result, MatchedDecl);

  // Do not attempt to create fixits for nested call expressions.
  // FIXME: Create lambda capture variables to capture output of calls.
  // NOTE: Supporting nested std::bind will be more difficult due to placeholder
  // sharing between outer and inner std:bind invocations.
  if (llvm::any_of(Args,
                   [](const BindArgument &B) { return B.Kind == BK_CallExpr; }))
    return;

  // Do not attempt to create fixits when placeholders are reused.
  // Unused placeholders are supported by requiring C++14 generic lambdas.
  // FIXME: Support this case by deducing the common type.
  if (isPlaceHolderIndexRepeated(Args))
    return;

  const auto *F = Result.Nodes.getNodeAs<FunctionDecl>("f");

  // std::bind can support argument count mismatch between its arguments and the
  // bound function's arguments. Do not attempt to generate a fixit for such
  // cases.
  // FIXME: Support this case by creating unused lambda capture variables.
  if (F->getNumParams() != Args.size())
    return;

  std::string Buffer;
  llvm::raw_string_ostream Stream(Buffer);

  bool HasCapturedArgument = llvm::any_of(
      Args, [](const BindArgument &B) { return B.Kind == BK_Other; });
  const auto *Ref = Result.Nodes.getNodeAs<DeclRefExpr>("ref");
  Stream << "[" << (HasCapturedArgument ? "=" : "") << "]";
  addPlaceholderArgs(Args, Stream);
  Stream << " { return ";
  Ref->printPretty(Stream, nullptr, Result.Context->getPrintingPolicy());
  Stream << "(";
  addFunctionCallArgs(Args, Stream);
  Stream << "); };";

  Diag << FixItHint::CreateReplacement(MatchedDecl->getSourceRange(),
                                       Stream.str());
}

} // namespace modernize
} // namespace tidy
} // namespace clang
