//===--- 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 const std::string DefaultAbbreviations =
    optutils::serializeStringList({"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->getAs<EnumType>()->getDecl()->isScoped()) ||
        (ArgType->isEnumeralType() &&
         ArgType->getAs<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 (const std::string &Abbreviation : optutils::parseStringList(
           Options.get("Abbreviations", DefaultAbbreviations))) {
    auto KeyAndValue = StringRef{Abbreviation}.split("=");
    assert(!KeyAndValue.first.empty() && !KeyAndValue.second.empty());
    AbbreviationDictionary.insert(
        std::make_pair(KeyAndValue.first.str(), 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).getValue());
  };

  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(Abbreviations));
}

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) {
    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());
      } else if (const auto *FCall =
                     dyn_cast<FunctionDecl>(ArgExpr->getDecl())) {
        ArgTypes.push_back(FCall->getType());
        ArgNames.push_back(FCall->getName());
      } else {
        ArgTypes.push_back(QualType());
        ArgNames.push_back(StringRef());
      }
    } else {
      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.getValue();

  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
