//===- RedundantVoidArgCheck.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 "RedundantVoidArgCheck.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Lex/Lexer.h"

using namespace clang::ast_matchers;

namespace clang::tidy::modernize {

namespace {

// Determine if the given QualType is a nullary function or pointer to same.
bool protoTypeHasNoParms(QualType QT) {
  if (const auto *PT = QT->getAs<PointerType>())
    QT = PT->getPointeeType();
  if (auto *MPT = QT->getAs<MemberPointerType>())
    QT = MPT->getPointeeType();
  if (const auto *FP = QT->getAs<FunctionProtoType>())
    return FP->getNumParams() == 0;
  return false;
}

const char FunctionId[] = "function";
const char TypedefId[] = "typedef";
const char FieldId[] = "field";
const char VarId[] = "var";
const char NamedCastId[] = "named-cast";
const char CStyleCastId[] = "c-style-cast";
const char ExplicitCastId[] = "explicit-cast";
const char LambdaId[] = "lambda";

} // namespace

void RedundantVoidArgCheck::registerMatchers(MatchFinder *Finder) {
  Finder->addMatcher(functionDecl(parameterCountIs(0), unless(isImplicit()),
                                  unless(isInstantiated()), unless(isExternC()))
                         .bind(FunctionId),
                     this);
  Finder->addMatcher(typedefNameDecl(unless(isImplicit())).bind(TypedefId),
                     this);
  auto ParenFunctionType = parenType(innerType(functionType()));
  auto PointerToFunctionType = pointee(ParenFunctionType);
  auto FunctionOrMemberPointer =
      anyOf(hasType(pointerType(PointerToFunctionType)),
            hasType(memberPointerType(PointerToFunctionType)));
  Finder->addMatcher(fieldDecl(FunctionOrMemberPointer).bind(FieldId), this);
  Finder->addMatcher(varDecl(FunctionOrMemberPointer).bind(VarId), this);
  auto CastDestinationIsFunction =
      hasDestinationType(pointsTo(ParenFunctionType));
  Finder->addMatcher(
      cStyleCastExpr(CastDestinationIsFunction).bind(CStyleCastId), this);
  Finder->addMatcher(
      cxxStaticCastExpr(CastDestinationIsFunction).bind(NamedCastId), this);
  Finder->addMatcher(
      cxxReinterpretCastExpr(CastDestinationIsFunction).bind(NamedCastId),
      this);
  Finder->addMatcher(
      cxxConstCastExpr(CastDestinationIsFunction).bind(NamedCastId), this);
  Finder->addMatcher(lambdaExpr().bind(LambdaId), this);
}

void RedundantVoidArgCheck::check(const MatchFinder::MatchResult &Result) {
  const BoundNodes &Nodes = Result.Nodes;
  if (const auto *Function = Nodes.getNodeAs<FunctionDecl>(FunctionId))
    processFunctionDecl(Result, Function);
  else if (const auto *TypedefName =
               Nodes.getNodeAs<TypedefNameDecl>(TypedefId))
    processTypedefNameDecl(Result, TypedefName);
  else if (const auto *Member = Nodes.getNodeAs<FieldDecl>(FieldId))
    processFieldDecl(Result, Member);
  else if (const auto *Var = Nodes.getNodeAs<VarDecl>(VarId))
    processVarDecl(Result, Var);
  else if (const auto *NamedCast =
               Nodes.getNodeAs<CXXNamedCastExpr>(NamedCastId))
    processNamedCastExpr(Result, NamedCast);
  else if (const auto *CStyleCast =
               Nodes.getNodeAs<CStyleCastExpr>(CStyleCastId))
    processExplicitCastExpr(Result, CStyleCast);
  else if (const auto *ExplicitCast =
               Nodes.getNodeAs<ExplicitCastExpr>(ExplicitCastId))
    processExplicitCastExpr(Result, ExplicitCast);
  else if (const auto *Lambda = Nodes.getNodeAs<LambdaExpr>(LambdaId))
    processLambdaExpr(Result, Lambda);
}

void RedundantVoidArgCheck::processFunctionDecl(
    const MatchFinder::MatchResult &Result, const FunctionDecl *Function) {
  const auto *Method = dyn_cast<CXXMethodDecl>(Function);
  SourceLocation Start = Method && Method->getParent()->isLambda()
                             ? Method->getBeginLoc()
                             : Function->getLocation();
  SourceLocation End = Function->getEndLoc();
  if (Function->isThisDeclarationADefinition()) {
    if (const Stmt *Body = Function->getBody()) {
      End = Body->getBeginLoc();
      if (End.isMacroID() &&
          Result.SourceManager->isAtStartOfImmediateMacroExpansion(End))
        End = Result.SourceManager->getExpansionLoc(End);
      End = End.getLocWithOffset(-1);
    }
    removeVoidArgumentTokens(Result, SourceRange(Start, End),
                             "function definition");
  } else
    removeVoidArgumentTokens(Result, SourceRange(Start, End),
                             "function declaration");
}

bool isMacroIdentifier(const IdentifierTable &Idents, const Token &ProtoToken) {
  if (!ProtoToken.is(tok::TokenKind::raw_identifier))
    return false;

  IdentifierTable::iterator It = Idents.find(ProtoToken.getRawIdentifier());
  if (It == Idents.end())
    return false;

  return It->second->hadMacroDefinition();
}

void RedundantVoidArgCheck::removeVoidArgumentTokens(
    const ast_matchers::MatchFinder::MatchResult &Result, SourceRange Range,
    StringRef GrammarLocation) {
  CharSourceRange CharRange =
      Lexer::makeFileCharRange(CharSourceRange::getTokenRange(Range),
                               *Result.SourceManager, getLangOpts());

  std::string DeclText =
      Lexer::getSourceText(CharRange, *Result.SourceManager, getLangOpts())
          .str();
  Lexer PrototypeLexer(CharRange.getBegin(), getLangOpts(), DeclText.data(),
                       DeclText.data(), DeclText.data() + DeclText.size());
  enum class TokenState {
    Start,
    MacroId,
    MacroLeftParen,
    MacroArguments,
    LeftParen,
    Void,
  };
  TokenState State = TokenState::Start;
  Token VoidToken;
  Token ProtoToken;
  const IdentifierTable &Idents = Result.Context->Idents;
  int MacroLevel = 0;
  std::string Diagnostic =
      ("redundant void argument list in " + GrammarLocation).str();

  while (!PrototypeLexer.LexFromRawLexer(ProtoToken)) {
    switch (State) {
    case TokenState::Start:
      if (ProtoToken.is(tok::TokenKind::l_paren))
        State = TokenState::LeftParen;
      else if (isMacroIdentifier(Idents, ProtoToken))
        State = TokenState::MacroId;
      break;
    case TokenState::MacroId:
      if (ProtoToken.is(tok::TokenKind::l_paren))
        State = TokenState::MacroLeftParen;
      else
        State = TokenState::Start;
      break;
    case TokenState::MacroLeftParen:
      ++MacroLevel;
      if (ProtoToken.is(tok::TokenKind::raw_identifier)) {
        if (isMacroIdentifier(Idents, ProtoToken))
          State = TokenState::MacroId;
        else
          State = TokenState::MacroArguments;
      } else if (ProtoToken.is(tok::TokenKind::r_paren)) {
        --MacroLevel;
        if (MacroLevel == 0)
          State = TokenState::Start;
        else
          State = TokenState::MacroId;
      } else
        State = TokenState::MacroArguments;
      break;
    case TokenState::MacroArguments:
      if (isMacroIdentifier(Idents, ProtoToken))
        State = TokenState::MacroLeftParen;
      else if (ProtoToken.is(tok::TokenKind::r_paren)) {
        --MacroLevel;
        if (MacroLevel == 0)
          State = TokenState::Start;
      }
      break;
    case TokenState::LeftParen:
      if (ProtoToken.is(tok::TokenKind::raw_identifier)) {
        if (isMacroIdentifier(Idents, ProtoToken))
          State = TokenState::MacroId;
        else if (ProtoToken.getRawIdentifier() == "void") {
          State = TokenState::Void;
          VoidToken = ProtoToken;
        }
      } else if (ProtoToken.is(tok::TokenKind::l_paren))
        State = TokenState::LeftParen;
      else
        State = TokenState::Start;
      break;
    case TokenState::Void:
      State = TokenState::Start;
      if (ProtoToken.is(tok::TokenKind::r_paren))
        removeVoidToken(VoidToken, Diagnostic);
      else if (ProtoToken.is(tok::TokenKind::l_paren))
        State = TokenState::LeftParen;
      break;
    }
  }

  if (State == TokenState::Void && ProtoToken.is(tok::TokenKind::r_paren))
    removeVoidToken(VoidToken, Diagnostic);
}

void RedundantVoidArgCheck::removeVoidToken(Token VoidToken,
                                            StringRef Diagnostic) {
  SourceLocation VoidLoc = VoidToken.getLocation();
  diag(VoidLoc, Diagnostic) << FixItHint::CreateRemoval(VoidLoc);
}

void RedundantVoidArgCheck::processTypedefNameDecl(
    const MatchFinder::MatchResult &Result,
    const TypedefNameDecl *TypedefName) {
  if (protoTypeHasNoParms(TypedefName->getUnderlyingType()))
    removeVoidArgumentTokens(Result, TypedefName->getSourceRange(),
                             isa<TypedefDecl>(TypedefName) ? "typedef"
                                                           : "type alias");
}

void RedundantVoidArgCheck::processFieldDecl(
    const MatchFinder::MatchResult &Result, const FieldDecl *Member) {
  if (protoTypeHasNoParms(Member->getType()))
    removeVoidArgumentTokens(Result, Member->getSourceRange(),
                             "field declaration");
}

void RedundantVoidArgCheck::processVarDecl(
    const MatchFinder::MatchResult &Result, const VarDecl *Var) {
  if (protoTypeHasNoParms(Var->getType())) {
    SourceLocation Begin = Var->getBeginLoc();
    if (Var->hasInit()) {
      SourceLocation InitStart =
          Result.SourceManager->getExpansionLoc(Var->getInit()->getBeginLoc())
              .getLocWithOffset(-1);
      removeVoidArgumentTokens(Result, SourceRange(Begin, InitStart),
                               "variable declaration with initializer");
    } else
      removeVoidArgumentTokens(Result, Var->getSourceRange(),
                               "variable declaration");
  }
}

void RedundantVoidArgCheck::processNamedCastExpr(
    const MatchFinder::MatchResult &Result, const CXXNamedCastExpr *NamedCast) {
  if (protoTypeHasNoParms(NamedCast->getTypeAsWritten()))
    removeVoidArgumentTokens(
        Result,
        NamedCast->getTypeInfoAsWritten()->getTypeLoc().getSourceRange(),
        "named cast");
}

void RedundantVoidArgCheck::processExplicitCastExpr(
    const MatchFinder::MatchResult &Result,
    const ExplicitCastExpr *ExplicitCast) {
  if (protoTypeHasNoParms(ExplicitCast->getTypeAsWritten()))
    removeVoidArgumentTokens(Result, ExplicitCast->getSourceRange(),
                             "cast expression");
}

void RedundantVoidArgCheck::processLambdaExpr(
    const MatchFinder::MatchResult &Result, const LambdaExpr *Lambda) {
  if (Lambda->getLambdaClass()->getLambdaCallOperator()->getNumParams() == 0 &&
      Lambda->hasExplicitParameters()) {
    SourceManager *SM = Result.SourceManager;
    TypeLoc TL = Lambda->getLambdaClass()->getLambdaTypeInfo()->getTypeLoc();
    removeVoidArgumentTokens(Result,
                             {SM->getSpellingLoc(TL.getBeginLoc()),
                              SM->getSpellingLoc(TL.getEndLoc())},
                             "lambda expression");
  }
}

} // namespace clang::tidy::modernize
