void RedundantVoidArgCheck::processFunctionDecl(
    const MatchFinder::MatchResult &Result, const FunctionDecl *Function) {
  if (Function->isThisDeclarationADefinition()) {
    const Stmt *Body = Function->getBody();
    SourceLocation Start = Function->getLocStart();
    SourceLocation End =
        Body ? Body->getLocStart().getLocWithOffset(-1) : Function->getLocEnd();
    removeVoidArgumentTokens(Result, SourceRange(Start, End),
                             "function definition");
  } else {
    removeVoidArgumentTokens(Result, Function->getSourceRange(),
                             "function declaration");
  }
}
void RedundantVoidArgCheck::processVarDecl(
    const MatchFinder::MatchResult &Result, const VarDecl *Var) {
  if (protoTypeHasNoParms(Var->getType())) {
    SourceLocation Begin = Var->getLocStart();
    if (Var->hasInit()) {
      SourceLocation InitStart =
          Result.SourceManager->getExpansionLoc(Var->getInit()->getLocStart())
              .getLocWithOffset(-1);
      removeVoidArgumentTokens(Result, SourceRange(Begin, InitStart),
                               "variable declaration with initializer");
    } else {
      removeVoidArgumentTokens(Result, Var->getSourceRange(),
                               "variable declaration");
    }
  }
}
void RedundantVoidArgCheck::processFieldDecl(
    const MatchFinder::MatchResult &Result, const FieldDecl *Member) {
  if (protoTypeHasNoParms(Member->getType())) {
    removeVoidArgumentTokens(Result, Member->getSourceRange(),
                             "field declaration");
  }
}
void RedundantVoidArgCheck::processExplicitCastExpr(
    const MatchFinder::MatchResult &Result,
    const ExplicitCastExpr *ExplicitCast) {
  if (protoTypeHasNoParms(ExplicitCast->getTypeAsWritten())) {
    removeVoidArgumentTokens(Result, ExplicitCast->getSourceRange(),
                             "cast expression");
  }
}
void RedundantVoidArgCheck::processNamedCastExpr(
    const MatchFinder::MatchResult &Result, const CXXNamedCastExpr *NamedCast) {
  if (protoTypeHasNoParms(NamedCast->getTypeAsWritten())) {
    removeVoidArgumentTokens(
        Result,
        NamedCast->getTypeInfoAsWritten()->getTypeLoc().getSourceRange(),
        "named cast");
  }
}
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::processFunctionDecl(
    const MatchFinder::MatchResult &Result, const FunctionDecl *Function) {
  if (Function->isThisDeclarationADefinition()) {
    SourceLocation Start = Function->getBeginLoc();
    SourceLocation End = Function->getEndLoc();
    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, Function->getSourceRange(),
                             "function declaration");
  }
}
void RedundantVoidArgCheck::processLambdaExpr(
    const MatchFinder::MatchResult &Result, const LambdaExpr *Lambda) {
  if (Lambda->getLambdaClass()->getLambdaCallOperator()->getNumParams() == 0 &&
      Lambda->hasExplicitParameters()) {
    SourceLocation Begin =
        Lambda->getIntroducerRange().getEnd().getLocWithOffset(1);
    SourceLocation End = Lambda->getBody()->getLocStart().getLocWithOffset(-1);
    removeVoidArgumentTokens(Result, SourceRange(Begin, End),
                             "lambda 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");
  }
}