//===--- RedundantStrcatCallsCheck.cpp - clang-tidy------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#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
