//===--- UnusedParametersCheck.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 "UnusedParametersCheck.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Lex/Lexer.h"
#include "llvm/ADT/STLExtras.h"
#include <unordered_set>

using namespace clang::ast_matchers;

namespace clang {
namespace tidy {
namespace misc {

namespace {
bool isOverrideMethod(const FunctionDecl *Function) {
  if (const auto *MD = dyn_cast<CXXMethodDecl>(Function))
    return MD->size_overridden_methods() > 0 || MD->hasAttr<OverrideAttr>();
  return false;
}
} // namespace

void UnusedParametersCheck::registerMatchers(MatchFinder *Finder) {
  Finder->addMatcher(
      functionDecl(isDefinition(), hasBody(stmt()), hasAnyParameter(decl()))
          .bind("function"),
      this);
}

template <typename T>
static CharSourceRange removeNode(const MatchFinder::MatchResult &Result,
                                  const T *PrevNode, const T *Node,
                                  const T *NextNode) {
  if (NextNode)
    return CharSourceRange::getCharRange(Node->getBeginLoc(),
                                         NextNode->getBeginLoc());

  if (PrevNode)
    return CharSourceRange::getTokenRange(
        Lexer::getLocForEndOfToken(PrevNode->getEndLoc(), 0,
                                   *Result.SourceManager,
                                   Result.Context->getLangOpts()),
        Node->getEndLoc());

  return CharSourceRange::getTokenRange(Node->getSourceRange());
}

static FixItHint removeParameter(const MatchFinder::MatchResult &Result,
                                 const FunctionDecl *Function, unsigned Index) {
  return FixItHint::CreateRemoval(removeNode(
      Result, Index > 0 ? Function->getParamDecl(Index - 1) : nullptr,
      Function->getParamDecl(Index),
      Index + 1 < Function->getNumParams() ? Function->getParamDecl(Index + 1)
                                           : nullptr));
}

static FixItHint removeArgument(const MatchFinder::MatchResult &Result,
                                const CallExpr *Call, unsigned Index) {
  return FixItHint::CreateRemoval(removeNode(
      Result, Index > 0 ? Call->getArg(Index - 1) : nullptr,
      Call->getArg(Index),
      Index + 1 < Call->getNumArgs() ? Call->getArg(Index + 1) : nullptr));
}

class UnusedParametersCheck::IndexerVisitor
    : public RecursiveASTVisitor<IndexerVisitor> {
public:
  IndexerVisitor(ASTContext &Ctx) { TraverseAST(Ctx); }

  const std::unordered_set<const CallExpr *> &
  getFnCalls(const FunctionDecl *Fn) {
    return Index[Fn->getCanonicalDecl()].Calls;
  }

  const std::unordered_set<const DeclRefExpr *> &
  getOtherRefs(const FunctionDecl *Fn) {
    return Index[Fn->getCanonicalDecl()].OtherRefs;
  }

  bool shouldTraversePostOrder() const { return true; }

  bool WalkUpFromDeclRefExpr(DeclRefExpr *DeclRef) {
    if (const auto *Fn = dyn_cast<FunctionDecl>(DeclRef->getDecl())) {
      Fn = Fn->getCanonicalDecl();
      Index[Fn].OtherRefs.insert(DeclRef);
    }
    return true;
  }

  bool WalkUpFromCallExpr(CallExpr *Call) {
    if (const auto *Fn =
            dyn_cast_or_null<FunctionDecl>(Call->getCalleeDecl())) {
      Fn = Fn->getCanonicalDecl();
      if (const auto *Ref =
              dyn_cast<DeclRefExpr>(Call->getCallee()->IgnoreImplicit())) {
        Index[Fn].OtherRefs.erase(Ref);
      }
      Index[Fn].Calls.insert(Call);
    }
    return true;
  }

private:
  struct IndexEntry {
    std::unordered_set<const CallExpr *> Calls;
    std::unordered_set<const DeclRefExpr *> OtherRefs;
  };

  std::unordered_map<const FunctionDecl *, IndexEntry> Index;
};

UnusedParametersCheck::~UnusedParametersCheck() = default;

UnusedParametersCheck::UnusedParametersCheck(StringRef Name,
                                             ClangTidyContext *Context)
    : ClangTidyCheck(Name, Context),
      StrictMode(Options.getLocalOrGlobal("StrictMode", 0) != 0) {}

void UnusedParametersCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
  Options.store(Opts, "StrictMode", StrictMode);
}

void UnusedParametersCheck::warnOnUnusedParameter(
    const MatchFinder::MatchResult &Result, const FunctionDecl *Function,
    unsigned ParamIndex) {
  const auto *Param = Function->getParamDecl(ParamIndex);
  auto MyDiag = diag(Param->getLocation(), "parameter %0 is unused") << Param;

  if (!Indexer) {
    Indexer = llvm::make_unique<IndexerVisitor>(*Result.Context);
  }

  // Comment out parameter name for non-local functions.
  if (Function->isExternallyVisible() ||
      !Result.SourceManager->isInMainFile(Function->getLocation()) ||
      !Indexer->getOtherRefs(Function).empty() || isOverrideMethod(Function)) {
    SourceRange RemovalRange(Param->getLocation());
    // Note: We always add a space before the '/*' to not accidentally create a
    // '*/*' for pointer types, which doesn't start a comment. clang-format will
    // clean this up afterwards.
    MyDiag << FixItHint::CreateReplacement(
        RemovalRange, (Twine(" /*") + Param->getName() + "*/").str());
    return;
  }

  // Fix all redeclarations.
  for (const FunctionDecl *FD : Function->redecls())
    if (FD->param_size())
      MyDiag << removeParameter(Result, FD, ParamIndex);

  // Fix all call sites.
  for (const CallExpr *Call : Indexer->getFnCalls(Function))
    if (ParamIndex < Call->getNumArgs()) // See PR38055 for example.
      MyDiag << removeArgument(Result, Call, ParamIndex);
}

void UnusedParametersCheck::check(const MatchFinder::MatchResult &Result) {
  const auto *Function = Result.Nodes.getNodeAs<FunctionDecl>("function");
  if (!Function->hasWrittenPrototype() || Function->isTemplateInstantiation())
    return;
  if (const auto *Method = dyn_cast<CXXMethodDecl>(Function))
    if (Method->isLambdaStaticInvoker())
      return;
  for (unsigned i = 0, e = Function->getNumParams(); i != e; ++i) {
    const auto *Param = Function->getParamDecl(i);
    if (Param->isUsed() || Param->isReferenced() || !Param->getDeclName() ||
        Param->hasAttr<UnusedAttr>())
      continue;

    // In non-strict mode ignore function definitions with empty bodies
    // (constructor initializer counts for non-empty body).
    if (StrictMode ||
        (Function->getBody()->child_begin() !=
         Function->getBody()->child_end()) ||
        (isa<CXXConstructorDecl>(Function) &&
         cast<CXXConstructorDecl>(Function)->getNumCtorInitializers() > 0))
      warnOnUnusedParameter(Result, Function, i);
  }
}

} // namespace misc
} // namespace tidy
} // namespace clang
