//===--- SuspiciousCallArgumentCheck.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 "SuspiciousCallArgumentCheck.h"
#include "../utils/OptionsUtils.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Type.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include <sstream>

using namespace clang::ast_matchers;
namespace optutils = clang::tidy::utils::options;

namespace clang {
namespace tidy {
namespace readability {

namespace {
struct DefaultHeuristicConfiguration {
  /// Whether the heuristic is to be enabled by default.
  const bool Enabled;

  /// The upper bound of % of similarity the two strings might have to be
  /// considered dissimilar.
  /// (For purposes of configuration, -1 if the heuristic is not configurable
  /// with bounds.)
  const int8_t DissimilarBelow;

  /// The lower bound of % of similarity the two string must have to be
  /// considered similar.
  /// (For purposes of configuration, -1 if the heuristic is not configurable
  /// with bounds.)
  const int8_t SimilarAbove;

  /// Can the heuristic be configured with bounds?
  bool hasBounds() const { return DissimilarBelow > -1 && SimilarAbove > -1; }
};
} // namespace

static constexpr std::size_t DefaultMinimumIdentifierNameLength = 3;

static constexpr StringRef HeuristicToString[] = {
    "Equality",  "Abbreviation", "Prefix",      "Suffix",
    "Substring", "Levenshtein",  "JaroWinkler", "Dice"};

static constexpr DefaultHeuristicConfiguration Defaults[] = {
    {true, -1, -1}, // Equality.
    {true, -1, -1}, // Abbreviation.
    {true, 25, 30}, // Prefix.
    {true, 25, 30}, // Suffix.
    {true, 40, 50}, // Substring.
    {true, 50, 66}, // Levenshtein.
    {true, 75, 85}, // Jaro-Winkler.
    {true, 60, 70}, // Dice.
};

static_assert(
    sizeof(HeuristicToString) / sizeof(HeuristicToString[0]) ==
        SuspiciousCallArgumentCheck::HeuristicCount,
    "Ensure that every heuristic has a corresponding stringified name");
static_assert(sizeof(Defaults) / sizeof(Defaults[0]) ==
                  SuspiciousCallArgumentCheck::HeuristicCount,
              "Ensure that every heuristic has a default configuration.");

namespace {
template <std::size_t I> struct HasWellConfiguredBounds {
  static constexpr bool Value =
      !((Defaults[I].DissimilarBelow == -1) ^ (Defaults[I].SimilarAbove == -1));
  static_assert(Value, "A heuristic must either have a dissimilarity and "
                       "similarity bound, or neither!");
};

template <std::size_t I> struct HasWellConfiguredBoundsFold {
  static constexpr bool Value = HasWellConfiguredBounds<I>::Value &&
                                HasWellConfiguredBoundsFold<I - 1>::Value;
};

template <> struct HasWellConfiguredBoundsFold<0> {
  static constexpr bool Value = HasWellConfiguredBounds<0>::Value;
};

struct AllHeuristicsBoundsWellConfigured {
  static constexpr bool Value =
      HasWellConfiguredBoundsFold<SuspiciousCallArgumentCheck::HeuristicCount -
                                  1>::Value;
};

static_assert(AllHeuristicsBoundsWellConfigured::Value, "");
} // namespace

static constexpr llvm::StringLiteral DefaultAbbreviations = "addr=address;"
                                                            "arr=array;"
                                                            "attr=attribute;"
                                                            "buf=buffer;"
                                                            "cl=client;"
                                                            "cnt=count;"
                                                            "col=column;"
                                                            "cpy=copy;"
                                                            "dest=destination;"
                                                            "dist=distance"
                                                            "dst=distance;"
                                                            "elem=element;"
                                                            "hght=height;"
                                                            "i=index;"
                                                            "idx=index;"
                                                            "len=length;"
                                                            "ln=line;"
                                                            "lst=list;"
                                                            "nr=number;"
                                                            "num=number;"
                                                            "pos=position;"
                                                            "ptr=pointer;"
                                                            "ref=reference;"
                                                            "src=source;"
                                                            "srv=server;"
                                                            "stmt=statement;"
                                                            "str=string;"
                                                            "val=value;"
                                                            "var=variable;"
                                                            "vec=vector;"
                                                            "wdth=width";

static constexpr std::size_t SmallVectorSize =
    SuspiciousCallArgumentCheck::SmallVectorSize;

/// Returns how many % X is of Y.
static inline double percentage(double X, double Y) { return X / Y * 100.0; }

static bool applyEqualityHeuristic(StringRef Arg, StringRef Param) {
  return Arg.equals_insensitive(Param);
}

static bool applyAbbreviationHeuristic(
    const llvm::StringMap<std::string> &AbbreviationDictionary, StringRef Arg,
    StringRef Param) {
  if (AbbreviationDictionary.find(Arg) != AbbreviationDictionary.end() &&
      Param.equals(AbbreviationDictionary.lookup(Arg)))
    return true;

  if (AbbreviationDictionary.find(Param) != AbbreviationDictionary.end() &&
      Arg.equals(AbbreviationDictionary.lookup(Param)))
    return true;

  return false;
}

/// Check whether the shorter String is a prefix of the longer String.
static bool applyPrefixHeuristic(StringRef Arg, StringRef Param,
                                 int8_t Threshold) {
  StringRef Shorter = Arg.size() < Param.size() ? Arg : Param;
  StringRef Longer = Arg.size() >= Param.size() ? Arg : Param;

  if (Longer.startswith_insensitive(Shorter))
    return percentage(Shorter.size(), Longer.size()) > Threshold;

  return false;
}

/// Check whether the shorter String is a suffix of the longer String.
static bool applySuffixHeuristic(StringRef Arg, StringRef Param,
                                 int8_t Threshold) {
  StringRef Shorter = Arg.size() < Param.size() ? Arg : Param;
  StringRef Longer = Arg.size() >= Param.size() ? Arg : Param;

  if (Longer.endswith_insensitive(Shorter))
    return percentage(Shorter.size(), Longer.size()) > Threshold;

  return false;
}

static bool applySubstringHeuristic(StringRef Arg, StringRef Param,
                                    int8_t Threshold) {

  std::size_t MaxLength = 0;
  SmallVector<std::size_t, SmallVectorSize> Current(Param.size());
  SmallVector<std::size_t, SmallVectorSize> Previous(Param.size());
  std::string ArgLower = Arg.lower();
  std::string ParamLower = Param.lower();

  for (std::size_t I = 0; I < Arg.size(); ++I) {
    for (std::size_t J = 0; J < Param.size(); ++J) {
      if (ArgLower[I] == ParamLower[J]) {
        if (I == 0 || J == 0)
          Current[J] = 1;
        else
          Current[J] = 1 + Previous[J - 1];

        MaxLength = std::max(MaxLength, Current[J]);
      } else
        Current[J] = 0;
    }

    Current.swap(Previous);
  }

  size_t LongerLength = std::max(Arg.size(), Param.size());
  return percentage(MaxLength, LongerLength) > Threshold;
}

static bool applyLevenshteinHeuristic(StringRef Arg, StringRef Param,
                                      int8_t Threshold) {
  std::size_t LongerLength = std::max(Arg.size(), Param.size());
  double Dist = Arg.edit_distance(Param);
  Dist = (1.0 - Dist / LongerLength) * 100.0;
  return Dist > Threshold;
}

// Based on http://en.wikipedia.org/wiki/Jaro–Winkler_distance.
static bool applyJaroWinklerHeuristic(StringRef Arg, StringRef Param,
                                      int8_t Threshold) {
  std::size_t Match = 0, Transpos = 0;
  std::ptrdiff_t ArgLen = Arg.size();
  std::ptrdiff_t ParamLen = Param.size();
  SmallVector<int, SmallVectorSize> ArgFlags(ArgLen);
  SmallVector<int, SmallVectorSize> ParamFlags(ParamLen);
  std::ptrdiff_t Range =
      std::max(std::ptrdiff_t{0}, std::max(ArgLen, ParamLen) / 2 - 1);

  // Calculate matching characters.
  for (std::ptrdiff_t I = 0; I < ParamLen; ++I)
    for (std::ptrdiff_t J = std::max(I - Range, std::ptrdiff_t{0}),
                        L = std::min(I + Range + 1, ArgLen);
         J < L; ++J)
      if (tolower(Param[I]) == tolower(Arg[J]) && !ArgFlags[J]) {
        ArgFlags[J] = 1;
        ParamFlags[I] = 1;
        ++Match;
        break;
      }

  if (!Match)
    return false;

  // Calculate character transpositions.
  std::ptrdiff_t L = 0;
  for (std::ptrdiff_t I = 0; I < ParamLen; ++I) {
    if (ParamFlags[I] == 1) {
      std::ptrdiff_t J;
      for (J = L; J < ArgLen; ++J)
        if (ArgFlags[J] == 1) {
          L = J + 1;
          break;
        }

      if (tolower(Param[I]) != tolower(Arg[J]))
        ++Transpos;
    }
  }
  Transpos /= 2;

  // Jaro distance.
  double MatchD = Match;
  double Dist = ((MatchD / ArgLen) + (MatchD / ParamLen) +
                 ((MatchD - Transpos) / Match)) /
                3.0;

  // Calculate common string prefix up to 4 chars.
  L = 0;
  for (std::ptrdiff_t I = 0;
       I < std::min(std::min(ArgLen, ParamLen), std::ptrdiff_t{4}); ++I)
    if (tolower(Arg[I]) == tolower(Param[I]))
      ++L;

  // Jaro-Winkler distance.
  Dist = (Dist + (L * 0.1 * (1.0 - Dist))) * 100.0;
  return Dist > Threshold;
}

// Based on http://en.wikipedia.org/wiki/Sørensen–Dice_coefficient
static bool applyDiceHeuristic(StringRef Arg, StringRef Param,
                               int8_t Threshold) {
  llvm::StringSet<> ArgBigrams;
  llvm::StringSet<> ParamBigrams;

  // Extract character bigrams from Arg.
  for (std::ptrdiff_t I = 0; I < static_cast<std::ptrdiff_t>(Arg.size()) - 1;
       ++I)
    ArgBigrams.insert(Arg.substr(I, 2).lower());

  // Extract character bigrams from Param.
  for (std::ptrdiff_t I = 0; I < static_cast<std::ptrdiff_t>(Param.size()) - 1;
       ++I)
    ParamBigrams.insert(Param.substr(I, 2).lower());

  std::size_t Intersection = 0;

  // Find the intersection between the two sets.
  for (auto IT = ParamBigrams.begin(); IT != ParamBigrams.end(); ++IT)
    Intersection += ArgBigrams.count((IT->getKey()));

  // Calculate Dice coefficient.
  return percentage(Intersection * 2.0,
                    ArgBigrams.size() + ParamBigrams.size()) > Threshold;
}

/// Checks if ArgType binds to ParamType regarding reference-ness and
/// cv-qualifiers.
static bool areRefAndQualCompatible(QualType ArgType, QualType ParamType) {
  return !ParamType->isReferenceType() ||
         ParamType.getNonReferenceType().isAtLeastAsQualifiedAs(
             ArgType.getNonReferenceType());
}

static bool isPointerOrArray(QualType TypeToCheck) {
  return TypeToCheck->isPointerType() || TypeToCheck->isArrayType();
}

/// Checks whether ArgType is an array type identical to ParamType's array type.
/// Enforces array elements' qualifier compatibility as well.
static bool isCompatibleWithArrayReference(QualType ArgType,
                                           QualType ParamType) {
  if (!ArgType->isArrayType())
    return false;
  // Here, qualifiers belong to the elements of the arrays.
  if (!ParamType.isAtLeastAsQualifiedAs(ArgType))
    return false;

  return ParamType.getUnqualifiedType() == ArgType.getUnqualifiedType();
}

static QualType convertToPointeeOrArrayElementQualType(QualType TypeToConvert) {
  unsigned CVRqualifiers = 0;
  // Save array element qualifiers, since getElementType() removes qualifiers
  // from array elements.
  if (TypeToConvert->isArrayType())
    CVRqualifiers = TypeToConvert.getLocalQualifiers().getCVRQualifiers();
  TypeToConvert = TypeToConvert->isPointerType()
                      ? TypeToConvert->getPointeeType()
                      : TypeToConvert->getAsArrayTypeUnsafe()->getElementType();
  TypeToConvert = TypeToConvert.withCVRQualifiers(CVRqualifiers);
  return TypeToConvert;
}

/// Checks if multilevel pointers' qualifiers compatibility continues on the
/// current pointer level. For multilevel pointers, C++ permits conversion, if
/// every cv-qualifier in ArgType also appears in the corresponding position in
/// ParamType, and if PramType has a cv-qualifier that's not in ArgType, then
/// every * in ParamType to the right of that cv-qualifier, except the last
/// one, must also be const-qualified.
static bool arePointersStillQualCompatible(QualType ArgType, QualType ParamType,
                                           bool &IsParamContinuouslyConst) {
  // The types are compatible, if the parameter is at least as qualified as the
  // argument, and if it is more qualified, it has to be const on upper pointer
  // levels.
  bool AreTypesQualCompatible =
      ParamType.isAtLeastAsQualifiedAs(ArgType) &&
      (!ParamType.hasQualifiers() || IsParamContinuouslyConst);
  // Check whether the parameter's constness continues at the current pointer
  // level.
  IsParamContinuouslyConst &= ParamType.isConstQualified();

  return AreTypesQualCompatible;
}

/// Checks whether multilevel pointers are compatible in terms of levels,
/// qualifiers and pointee type.
static bool arePointerTypesCompatible(QualType ArgType, QualType ParamType,
                                      bool IsParamContinuouslyConst) {
  if (!arePointersStillQualCompatible(ArgType, ParamType,
                                      IsParamContinuouslyConst))
    return false;

  do {
    // Step down one pointer level.
    ArgType = convertToPointeeOrArrayElementQualType(ArgType);
    ParamType = convertToPointeeOrArrayElementQualType(ParamType);

    // Check whether cv-qualifiers permit compatibility on
    // current level.
    if (!arePointersStillQualCompatible(ArgType, ParamType,
                                        IsParamContinuouslyConst))
      return false;

    if (ParamType.getUnqualifiedType() == ArgType.getUnqualifiedType())
      return true;

  } while (ParamType->isPointerType() && ArgType->isPointerType());
  // The final type does not match, or pointer levels differ.
  return false;
}

/// Checks whether ArgType converts implicitly to ParamType.
static bool areTypesCompatible(QualType ArgType, QualType ParamType,
                               const ASTContext &Ctx) {
  if (ArgType.isNull() || ParamType.isNull())
    return false;

  ArgType = ArgType.getCanonicalType();
  ParamType = ParamType.getCanonicalType();

  if (ArgType == ParamType)
    return true;

  // Check for constness and reference compatibility.
  if (!areRefAndQualCompatible(ArgType, ParamType))
    return false;

  bool IsParamReference = ParamType->isReferenceType();

  // Reference-ness has already been checked and should be removed
  // before further checking.
  ArgType = ArgType.getNonReferenceType();
  ParamType = ParamType.getNonReferenceType();

  if (ParamType.getUnqualifiedType() == ArgType.getUnqualifiedType())
    return true;

  // Arithmetic types are interconvertible, except scoped enums.
  if (ParamType->isArithmeticType() && ArgType->isArithmeticType()) {
    if ((ParamType->isEnumeralType() &&
         ParamType->castAs<EnumType>()->getDecl()->isScoped()) ||
        (ArgType->isEnumeralType() &&
         ArgType->castAs<EnumType>()->getDecl()->isScoped()))
      return false;

    return true;
  }

  // Check if the argument and the param are both function types (the parameter
  // decayed to a function pointer).
  if (ArgType->isFunctionType() && ParamType->isFunctionPointerType()) {
    ParamType = ParamType->getPointeeType();
    return ArgType == ParamType;
  }

  // Arrays or pointer arguments convert to array or pointer parameters.
  if (!(isPointerOrArray(ArgType) && isPointerOrArray(ParamType)))
    return false;

  // When ParamType is an array reference, ArgType has to be of the same-sized
  // array-type with cv-compatible element type.
  if (IsParamReference && ParamType->isArrayType())
    return isCompatibleWithArrayReference(ArgType, ParamType);

  bool IsParamContinuouslyConst =
      !IsParamReference || ParamType.getNonReferenceType().isConstQualified();

  // Remove the first level of indirection.
  ArgType = convertToPointeeOrArrayElementQualType(ArgType);
  ParamType = convertToPointeeOrArrayElementQualType(ParamType);

  // Check qualifier compatibility on the next level.
  if (!ParamType.isAtLeastAsQualifiedAs(ArgType))
    return false;

  if (ParamType.getUnqualifiedType() == ArgType.getUnqualifiedType())
    return true;

  // At this point, all possible C language implicit conversion were checked.
  if (!Ctx.getLangOpts().CPlusPlus)
    return false;

  // Check whether ParamType and ArgType were both pointers to a class or a
  // struct, and check for inheritance.
  if (ParamType->isStructureOrClassType() &&
      ArgType->isStructureOrClassType()) {
    const auto *ArgDecl = ArgType->getAsCXXRecordDecl();
    const auto *ParamDecl = ParamType->getAsCXXRecordDecl();
    if (!ArgDecl || !ArgDecl->hasDefinition() || !ParamDecl ||
        !ParamDecl->hasDefinition())
      return false;

    return ArgDecl->isDerivedFrom(ParamDecl);
  }

  // Unless argument and param are both multilevel pointers, the types are not
  // convertible.
  if (!(ParamType->isAnyPointerType() && ArgType->isAnyPointerType()))
    return false;

  return arePointerTypesCompatible(ArgType, ParamType,
                                   IsParamContinuouslyConst);
}

static bool isOverloadedUnaryOrBinarySymbolOperator(const FunctionDecl *FD) {
  switch (FD->getOverloadedOperator()) {
  case OO_None:
  case OO_Call:
  case OO_Subscript:
  case OO_New:
  case OO_Delete:
  case OO_Array_New:
  case OO_Array_Delete:
  case OO_Conditional:
  case OO_Coawait:
    return false;

  default:
    return FD->getNumParams() <= 2;
  }
}

SuspiciousCallArgumentCheck::SuspiciousCallArgumentCheck(
    StringRef Name, ClangTidyContext *Context)
    : ClangTidyCheck(Name, Context),
      MinimumIdentifierNameLength(Options.get(
          "MinimumIdentifierNameLength", DefaultMinimumIdentifierNameLength)) {
  auto GetToggleOpt = [this](Heuristic H) -> bool {
    auto Idx = static_cast<std::size_t>(H);
    assert(Idx < HeuristicCount);
    return Options.get(HeuristicToString[Idx], Defaults[Idx].Enabled);
  };
  auto GetBoundOpt = [this](Heuristic H, BoundKind BK) -> int8_t {
    auto Idx = static_cast<std::size_t>(H);
    assert(Idx < HeuristicCount);

    SmallString<32> Key = HeuristicToString[Idx];
    Key.append(BK == BoundKind::DissimilarBelow ? "DissimilarBelow"
                                                : "SimilarAbove");
    int8_t Default = BK == BoundKind::DissimilarBelow
                         ? Defaults[Idx].DissimilarBelow
                         : Defaults[Idx].SimilarAbove;
    return Options.get(Key, Default);
  };
  for (std::size_t Idx = 0; Idx < HeuristicCount; ++Idx) {
    auto H = static_cast<Heuristic>(Idx);
    if (GetToggleOpt(H))
      AppliedHeuristics.emplace_back(H);
    ConfiguredBounds.emplace_back(
        std::make_pair(GetBoundOpt(H, BoundKind::DissimilarBelow),
                       GetBoundOpt(H, BoundKind::SimilarAbove)));
  }

  for (StringRef Abbreviation : optutils::parseStringList(
           Options.get("Abbreviations", DefaultAbbreviations))) {
    auto KeyAndValue = Abbreviation.split("=");
    assert(!KeyAndValue.first.empty() && !KeyAndValue.second.empty());
    AbbreviationDictionary.insert(
        std::make_pair(KeyAndValue.first, KeyAndValue.second.str()));
  }
}

void SuspiciousCallArgumentCheck::storeOptions(
    ClangTidyOptions::OptionMap &Opts) {
  Options.store(Opts, "MinimumIdentifierNameLength",
                MinimumIdentifierNameLength);
  const auto &SetToggleOpt = [this, &Opts](Heuristic H) -> void {
    auto Idx = static_cast<std::size_t>(H);
    Options.store(Opts, HeuristicToString[Idx], isHeuristicEnabled(H));
  };
  const auto &SetBoundOpt = [this, &Opts](Heuristic H, BoundKind BK) -> void {
    auto Idx = static_cast<std::size_t>(H);
    assert(Idx < HeuristicCount);
    if (!Defaults[Idx].hasBounds())
      return;

    SmallString<32> Key = HeuristicToString[Idx];
    Key.append(BK == BoundKind::DissimilarBelow ? "DissimilarBelow"
                                                : "SimilarAbove");
    Options.store(Opts, Key, *getBound(H, BK));
  };

  for (std::size_t Idx = 0; Idx < HeuristicCount; ++Idx) {
    auto H = static_cast<Heuristic>(Idx);
    SetToggleOpt(H);
    SetBoundOpt(H, BoundKind::DissimilarBelow);
    SetBoundOpt(H, BoundKind::SimilarAbove);
  }

  SmallVector<std::string, 32> Abbreviations;
  for (const auto &Abbreviation : AbbreviationDictionary) {
    SmallString<32> EqualSignJoined;
    EqualSignJoined.append(Abbreviation.first());
    EqualSignJoined.append("=");
    EqualSignJoined.append(Abbreviation.second);

    if (!Abbreviation.second.empty())
      Abbreviations.emplace_back(EqualSignJoined.str());
  }
  Options.store(Opts, "Abbreviations",
                optutils::serializeStringList(std::vector<StringRef>(
                    Abbreviations.begin(), Abbreviations.end())));
}

bool SuspiciousCallArgumentCheck::isHeuristicEnabled(Heuristic H) const {
  return llvm::is_contained(AppliedHeuristics, H);
}

Optional<int8_t> SuspiciousCallArgumentCheck::getBound(Heuristic H,
                                                       BoundKind BK) const {
  auto Idx = static_cast<std::size_t>(H);
  assert(Idx < HeuristicCount);

  if (!Defaults[Idx].hasBounds())
    return None;

  switch (BK) {
  case BoundKind::DissimilarBelow:
    return ConfiguredBounds[Idx].first;
  case BoundKind::SimilarAbove:
    return ConfiguredBounds[Idx].second;
  }
  llvm_unreachable("Unhandled Bound kind.");
}

void SuspiciousCallArgumentCheck::registerMatchers(MatchFinder *Finder) {
  // Only match calls with at least 2 arguments.
  Finder->addMatcher(
      functionDecl(forEachDescendant(callExpr(unless(anyOf(argumentCountIs(0),
                                                           argumentCountIs(1))))
                                         .bind("functionCall")))
          .bind("callingFunc"),
      this);
}

void SuspiciousCallArgumentCheck::check(
    const MatchFinder::MatchResult &Result) {
  const auto *MatchedCallExpr =
      Result.Nodes.getNodeAs<CallExpr>("functionCall");
  const auto *Caller = Result.Nodes.getNodeAs<FunctionDecl>("callingFunc");
  assert(MatchedCallExpr && Caller);

  const Decl *CalleeDecl = MatchedCallExpr->getCalleeDecl();
  if (!CalleeDecl)
    return;

  const FunctionDecl *CalleeFuncDecl = CalleeDecl->getAsFunction();
  if (!CalleeFuncDecl)
    return;
  if (CalleeFuncDecl == Caller)
    // Ignore recursive calls.
    return;
  if (isOverloadedUnaryOrBinarySymbolOperator(CalleeFuncDecl))
    return;

  // Get param attributes.
  setParamNamesAndTypes(CalleeFuncDecl);

  if (ParamNames.empty())
    return;

  // Get Arg attributes.
  std::size_t InitialArgIndex = 0;

  if (const auto *MethodDecl = dyn_cast<CXXMethodDecl>(CalleeFuncDecl)) {
    if (MethodDecl->getParent()->isLambda())
      // Lambda functions' first Arg are the lambda object.
      InitialArgIndex = 1;
    else if (MethodDecl->getOverloadedOperator() == OO_Call)
      // For custom operator()s, the first Arg is the called object.
      InitialArgIndex = 1;
  }

  setArgNamesAndTypes(MatchedCallExpr, InitialArgIndex);

  if (ArgNames.empty())
    return;

  std::size_t ParamCount = ParamNames.size();

  // Check similarity.
  for (std::size_t I = 0; I < ParamCount; ++I) {
    for (std::size_t J = I + 1; J < ParamCount; ++J) {
      // Do not check if param or arg names are short, or not convertible.
      if (!areParamAndArgComparable(I, J, *Result.Context))
        continue;
      if (!areArgsSwapped(I, J))
        continue;

      // Warning at the call itself.
      diag(MatchedCallExpr->getExprLoc(),
           "%ordinal0 argument '%1' (passed to '%2') looks like it might be "
           "swapped with the %ordinal3, '%4' (passed to '%5')")
          << static_cast<unsigned>(I + 1) << ArgNames[I] << ParamNames[I]
          << static_cast<unsigned>(J + 1) << ArgNames[J] << ParamNames[J]
          << MatchedCallExpr->getArg(I)->getSourceRange()
          << MatchedCallExpr->getArg(J)->getSourceRange();

      // Note at the functions declaration.
      SourceLocation IParNameLoc =
          CalleeFuncDecl->getParamDecl(I)->getLocation();
      SourceLocation JParNameLoc =
          CalleeFuncDecl->getParamDecl(J)->getLocation();

      diag(CalleeFuncDecl->getLocation(), "in the call to %0, declared here",
           DiagnosticIDs::Note)
          << CalleeFuncDecl
          << CharSourceRange::getTokenRange(IParNameLoc, IParNameLoc)
          << CharSourceRange::getTokenRange(JParNameLoc, JParNameLoc);
    }
  }
}

void SuspiciousCallArgumentCheck::setParamNamesAndTypes(
    const FunctionDecl *CalleeFuncDecl) {
  // Reset vectors, and fill them with the currently checked function's
  // parameters' data.
  ParamNames.clear();
  ParamTypes.clear();

  for (const ParmVarDecl *Param : CalleeFuncDecl->parameters()) {
    ParamTypes.push_back(Param->getType());

    if (IdentifierInfo *II = Param->getIdentifier())
      ParamNames.push_back(II->getName());
    else
      ParamNames.push_back(StringRef());
  }
}

void SuspiciousCallArgumentCheck::setArgNamesAndTypes(
    const CallExpr *MatchedCallExpr, std::size_t InitialArgIndex) {
  // Reset vectors, and fill them with the currently checked function's
  // arguments' data.
  ArgNames.clear();
  ArgTypes.clear();

  for (std::size_t I = InitialArgIndex, J = MatchedCallExpr->getNumArgs();
       I < J; ++I) {
    assert(ArgTypes.size() == I - InitialArgIndex &&
           ArgNames.size() == ArgTypes.size() &&
           "Every iteration must put an element into the vectors!");

    if (const auto *ArgExpr = dyn_cast<DeclRefExpr>(
            MatchedCallExpr->getArg(I)->IgnoreUnlessSpelledInSource())) {
      if (const auto *Var = dyn_cast<VarDecl>(ArgExpr->getDecl())) {
        ArgTypes.push_back(Var->getType());
        ArgNames.push_back(Var->getName());
        continue;
      }
      if (const auto *FCall = dyn_cast<FunctionDecl>(ArgExpr->getDecl())) {
        if (FCall->getNameInfo().getName().isIdentifier()) {
          ArgTypes.push_back(FCall->getType());
          ArgNames.push_back(FCall->getName());
          continue;
        }
      }
    }

    ArgTypes.push_back(QualType());
    ArgNames.push_back(StringRef());
  }
}

bool SuspiciousCallArgumentCheck::areParamAndArgComparable(
    std::size_t Position1, std::size_t Position2, const ASTContext &Ctx) const {
  if (Position1 >= ArgNames.size() || Position2 >= ArgNames.size())
    return false;

  // Do not report for too short strings.
  if (ArgNames[Position1].size() < MinimumIdentifierNameLength ||
      ArgNames[Position2].size() < MinimumIdentifierNameLength ||
      ParamNames[Position1].size() < MinimumIdentifierNameLength ||
      ParamNames[Position2].size() < MinimumIdentifierNameLength)
    return false;

  if (!areTypesCompatible(ArgTypes[Position1], ParamTypes[Position2], Ctx) ||
      !areTypesCompatible(ArgTypes[Position2], ParamTypes[Position1], Ctx))
    return false;

  return true;
}

bool SuspiciousCallArgumentCheck::areArgsSwapped(std::size_t Position1,
                                                 std::size_t Position2) const {
  for (Heuristic H : AppliedHeuristics) {
    bool A1ToP2Similar = areNamesSimilar(
        ArgNames[Position2], ParamNames[Position1], H, BoundKind::SimilarAbove);
    bool A2ToP1Similar = areNamesSimilar(
        ArgNames[Position1], ParamNames[Position2], H, BoundKind::SimilarAbove);

    bool A1ToP1Dissimilar =
        !areNamesSimilar(ArgNames[Position1], ParamNames[Position1], H,
                         BoundKind::DissimilarBelow);
    bool A2ToP2Dissimilar =
        !areNamesSimilar(ArgNames[Position2], ParamNames[Position2], H,
                         BoundKind::DissimilarBelow);

    if ((A1ToP2Similar || A2ToP1Similar) && A1ToP1Dissimilar &&
        A2ToP2Dissimilar)
      return true;
  }
  return false;
}

bool SuspiciousCallArgumentCheck::areNamesSimilar(StringRef Arg,
                                                  StringRef Param, Heuristic H,
                                                  BoundKind BK) const {
  int8_t Threshold = -1;
  if (Optional<int8_t> GotBound = getBound(H, BK))
    Threshold = *GotBound;

  switch (H) {
  case Heuristic::Equality:
    return applyEqualityHeuristic(Arg, Param);
  case Heuristic::Abbreviation:
    return applyAbbreviationHeuristic(AbbreviationDictionary, Arg, Param);
  case Heuristic::Prefix:
    return applyPrefixHeuristic(Arg, Param, Threshold);
  case Heuristic::Suffix:
    return applySuffixHeuristic(Arg, Param, Threshold);
  case Heuristic::Substring:
    return applySubstringHeuristic(Arg, Param, Threshold);
  case Heuristic::Levenshtein:
    return applyLevenshteinHeuristic(Arg, Param, Threshold);
  case Heuristic::JaroWinkler:
    return applyJaroWinklerHeuristic(Arg, Param, Threshold);
  case Heuristic::Dice:
    return applyDiceHeuristic(Arg, Param, Threshold);
  }
  llvm_unreachable("Unhandled heuristic kind");
}

} // namespace readability
} // namespace tidy
} // namespace clang
