//===--- RedundantStrcatCallsCheck.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 "RedundantStrcatCallsCheck.h"
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"

using namespace clang::ast_matchers;

namespace clang {
namespace tidy {
namespace abseil {

// TODO: Features to add to the check:
//  - Make it work if num_args > 26.
//  - Remove empty literal string arguments.
//  - Collapse consecutive literal string arguments into one (remove the ,).
//  - Replace StrCat(a + b)  ->  StrCat(a, b)  if a or b are strings.
//  - Make it work in macros if the outer and inner StrCats are both in the
//    argument.

void RedundantStrcatCallsCheck::registerMatchers(MatchFinder* Finder) {
  if (!getLangOpts().CPlusPlus) 
  	return;
  const auto CallToStrcat =
      callExpr(callee(functionDecl(hasName("::absl::StrCat"))));
  const auto CallToStrappend =
      callExpr(callee(functionDecl(hasName("::absl::StrAppend"))));
  // Do not match StrCat() calls that are descendants of other StrCat calls.
  // Those are handled on the ancestor call.
  const auto CallToEither = callExpr(
      callee(functionDecl(hasAnyName("::absl::StrCat", "::absl::StrAppend"))));
  Finder->addMatcher(
      callExpr(CallToStrcat, unless(hasAncestor(CallToEither))).bind("StrCat"),
      this);
  Finder->addMatcher(CallToStrappend.bind("StrAppend"), this);
}

namespace {

struct StrCatCheckResult {
  int NumCalls = 0;
  std::vector<FixItHint> Hints;
};

void RemoveCallLeaveArgs(const CallExpr* Call, StrCatCheckResult* CheckResult) {
  // Remove 'Foo('
  CheckResult->Hints.push_back(
      FixItHint::CreateRemoval(CharSourceRange::getCharRange(
          Call->getBeginLoc(), Call->getArg(0)->getBeginLoc())));
  // Remove the ')'
  CheckResult->Hints.push_back(
      FixItHint::CreateRemoval(CharSourceRange::getCharRange(
          Call->getRParenLoc(), Call->getEndLoc().getLocWithOffset(1))));
}

const clang::CallExpr* ProcessArgument(const Expr* Arg,
                                       const MatchFinder::MatchResult& Result,
                                       StrCatCheckResult* CheckResult) {
  const auto IsAlphanum = hasDeclaration(cxxMethodDecl(hasName("AlphaNum")));
  static const auto* const Strcat = new auto(hasName("::absl::StrCat"));
  const auto IsStrcat = cxxBindTemporaryExpr(
      has(callExpr(callee(functionDecl(*Strcat))).bind("StrCat")));
  if (const auto* SubStrcatCall = selectFirst<const CallExpr>(
          "StrCat",
          match(stmt(anyOf(
                    cxxConstructExpr(IsAlphanum, hasArgument(0, IsStrcat)),
                    IsStrcat)),
                *Arg->IgnoreParenImpCasts(), *Result.Context))) {
    RemoveCallLeaveArgs(SubStrcatCall, CheckResult);
    return SubStrcatCall;
  }
  return nullptr;
}

StrCatCheckResult ProcessCall(const CallExpr* RootCall, bool IsAppend,
                              const MatchFinder::MatchResult& Result) {
  StrCatCheckResult CheckResult;
  std::deque<const CallExpr*> CallsToProcess = {RootCall};

  while (!CallsToProcess.empty()) {
    ++CheckResult.NumCalls;

    const CallExpr* CallExpr = CallsToProcess.front();
    CallsToProcess.pop_front();

    int StartArg = CallExpr == RootCall && IsAppend;
    for (const auto *Arg : CallExpr->arguments()) {
      if (StartArg-- > 0) 
      	continue;
      if (const clang::CallExpr* Sub =
              ProcessArgument(Arg, Result, &CheckResult)) {
        CallsToProcess.push_back(Sub);
      }
    }
  }
  return CheckResult;
}
}  // namespace

void RedundantStrcatCallsCheck::check(const MatchFinder::MatchResult& Result) {
  bool IsAppend;

  const CallExpr* RootCall;
  if ((RootCall = Result.Nodes.getNodeAs<CallExpr>("StrCat"))) 
  	IsAppend = false;
  else if ((RootCall = Result.Nodes.getNodeAs<CallExpr>("StrAppend"))) 
  	IsAppend = true;
  else 
  	return;

  if (RootCall->getBeginLoc().isMacroID()) {
    // Ignore calls within macros.
    // In many cases the outer StrCat part of the macro and the inner StrCat is
    // a macro argument. Removing the inner StrCat() converts one macro
    // argument into many.
    return;
  }

  const StrCatCheckResult CheckResult =
      ProcessCall(RootCall, IsAppend, Result);
  if (CheckResult.NumCalls == 1) {
    // Just one call, so nothing to fix.
    return;
  }

  diag(RootCall->getBeginLoc(), 
  	   "multiple calls to 'absl::StrCat' can be flattened into a single call")
      << CheckResult.Hints;
}

}  // namespace abseil
}  // namespace tidy
}  // namespace clang
