//===--- 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->getLocStart(),
                                         NextNode->getLocStart());

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

  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(TranslationUnitDecl *Top) { TraverseDecl(Top); }

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

  // 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
