/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
   file LICENSE.rst or https://cmake.org/licensing for details.  */
#include "StringConcatenationUseCmstrcatCheck.h"

#include <cassert>

#include <clang/ASTMatchers/ASTMatchFinder.h>
#include <clang/Lex/Lexer.h>

namespace clang {
namespace tidy {
namespace cmake {
using namespace ast_matchers;

StringConcatenationUseCmstrcatCheck::StringConcatenationUseCmstrcatCheck(
  StringRef Name, ClangTidyContext* Context)
  : ClangTidyCheck(Name, Context)
{
}

void StringConcatenationUseCmstrcatCheck::registerMatchers(MatchFinder* Finder)
{
  auto IsString = expr(hasType(qualType(hasUnqualifiedDesugaredType(
    recordType(hasDeclaration(classTemplateSpecializationDecl(
      hasName("::std::basic_string"),
      hasTemplateArgument(
        0, templateArgument(refersToType(asString("char")))))))))));

  auto IsChar = expr(hasType(asString("char")));

  auto IsCharPtr = expr(hasType(pointerType(pointee(asString("const char")))));

  auto IsStringConcat =
    cxxOperatorCallExpr(hasOperatorName("+"),
                        anyOf(allOf(hasLHS(IsString), hasRHS(IsString)),
                              allOf(hasLHS(IsString), hasRHS(IsChar)),
                              allOf(hasLHS(IsString), hasRHS(IsCharPtr)),
                              allOf(hasLHS(IsChar), hasRHS(IsString)),
                              allOf(hasLHS(IsCharPtr), hasRHS(IsString))));

  auto IsStringAppend = cxxOperatorCallExpr(
    hasOperatorName("+="), hasLHS(IsString),
    anyOf(hasRHS(IsString), hasRHS(IsChar), hasRHS(IsCharPtr)));

  auto IsStringConcatWithLHS =
    cxxOperatorCallExpr(
      IsStringConcat,
      optionally(hasLHS(materializeTemporaryExpr(
        has(cxxBindTemporaryExpr(has(IsStringConcat.bind("lhs"))))))))
      .bind("concat");

  auto IsStringAppendWithRHS =
    cxxOperatorCallExpr(
      IsStringAppend,
      optionally(hasRHS(materializeTemporaryExpr(has(implicitCastExpr(
        has(cxxBindTemporaryExpr(has(IsStringConcat.bind("rhs"))))))))))
      .bind("append");

  Finder->addMatcher(IsStringConcatWithLHS, this);
  Finder->addMatcher(IsStringAppendWithRHS, this);
}

void StringConcatenationUseCmstrcatCheck::check(
  MatchFinder::MatchResult const& Result)
{
  CXXOperatorCallExpr const* AppendNode =
    Result.Nodes.getNodeAs<CXXOperatorCallExpr>("append");
  CXXOperatorCallExpr const* ConcatNode =
    Result.Nodes.getNodeAs<CXXOperatorCallExpr>("concat");

  if (AppendNode != nullptr) {
    if (AppendNode->getBeginLoc().isValid()) {
      assert(InProgressExprChains.find(AppendNode) ==
             InProgressExprChains.end());

      ExprChain TmpExprChain =
        std::make_pair(OperatorType::PlusEquals,
                       std::vector<CXXOperatorCallExpr const*>{ AppendNode });
      CXXOperatorCallExpr const* RHSNode =
        Result.Nodes.getNodeAs<CXXOperatorCallExpr>("rhs");

      if (RHSNode != nullptr) {
        if (RHSNode->getBeginLoc().isValid()) {
          InProgressExprChains[RHSNode] = std::move(TmpExprChain);
        }
      } else {
        issueCorrection(TmpExprChain, Result);
      }
    }
  }

  if (ConcatNode != nullptr) {
    if (ConcatNode->getBeginLoc().isValid()) {
      ExprChain TmpExprChain;

      if (!(InProgressExprChains.find(ConcatNode) ==
            InProgressExprChains.end())) {
        TmpExprChain = std::move(InProgressExprChains[ConcatNode]);
        InProgressExprChains.erase(ConcatNode);
        if (TmpExprChain.first == OperatorType::PlusEquals) {
          TmpExprChain.second.insert(TmpExprChain.second.begin() + 1,
                                     ConcatNode);
        } else {
          TmpExprChain.second.insert(TmpExprChain.second.begin(), ConcatNode);
        }
      } else {
        TmpExprChain = std::make_pair(
          OperatorType::Plus,
          std::vector<CXXOperatorCallExpr const*>{ ConcatNode });
      }

      CXXOperatorCallExpr const* LHSNode =
        Result.Nodes.getNodeAs<CXXOperatorCallExpr>("lhs");

      if (LHSNode != nullptr) {
        if (LHSNode->getBeginLoc().isValid()) {
          InProgressExprChains[LHSNode] = std::move(TmpExprChain);
        }
      } else {
        issueCorrection(TmpExprChain, Result);
      }
    }
  }
}

void StringConcatenationUseCmstrcatCheck::issueCorrection(
  ExprChain const& Chain, MatchFinder::MatchResult const& Result)
{
  std::vector<FixItHint> FixIts;
  CXXOperatorCallExpr const* ExprNode;
  std::vector<clang::CXXOperatorCallExpr const*>::const_iterator It =
    Chain.second.begin();

  if (Chain.first == OperatorType::PlusEquals) {
    ExprNode = *It;
    StringRef LHS = Lexer::getSourceText(
      CharSourceRange::getTokenRange(ExprNode->getArg(0)->getSourceRange()),
      Result.Context->getSourceManager(), Result.Context->getLangOpts());

    FixIts.push_back(FixItHint::CreateReplacement(
      ExprNode->getExprLoc(), "= cmStrCat(" + LHS.str() + ","));
    It++;
  } else {
    ExprNode = *It;
    FixIts.push_back(
      FixItHint::CreateInsertion(ExprNode->getBeginLoc(), "cmStrCat("));
  }

  while (It != std::end(Chain.second)) {
    ExprNode = *It;
    FixIts.push_back(
      FixItHint::CreateReplacement(ExprNode->getOperatorLoc(), ","));
    It++;
  }
  It--;
  ExprNode = *It;

  StringRef LastToken = Lexer::getSourceText(
    CharSourceRange::getTokenRange(
      ExprNode->getArg(1)->getSourceRange().getEnd()),
    Result.Context->getSourceManager(), Result.Context->getLangOpts());
  FixIts.push_back(FixItHint::CreateInsertion(
    ExprNode->getEndLoc().getLocWithOffset(LastToken.str().size()), ")"));

  It = Chain.second.begin();
  ExprNode = *It;

  if (Chain.first == OperatorType::PlusEquals) {
    this->diag(ExprNode->getOperatorLoc(),
               "use cmStrCat() instead of string append")
      << FixIts;
  } else {
    this->diag(ExprNode->getBeginLoc(),
               "use cmStrCat() instead of string concatenation")
      << FixIts;
  }
}
}
}
}
