libreoffice/compilerplugins/clang/cppunitassertequals.cxx
Miklos Vajna 839e53b933 compilerplugins: enable loplugin:cppunitassertequals by default
This forces writing a comparision of two variables in the
CPPUNIT_ASSERT_EQUALS(expected, actual) form, rather than
CPPUNIT_ASSERT(actual == expected). The benefit is when the test fail,
it's more clear what are these two values, rather than just seeing that
they are not equal.

In the relatively rare case when the types are not streamable, the
plugin can be silenced using CPPUNIT_ASSERT(bool(it == foo.end())). But
please always first consider making the type streamable instead. See
commit 0e1b831b93048c68735f2e2dbdcee587db4862ef
(CppunitTest_vcl_complextext: fix loplugin:cppunitassertequals warnings,
2016-12-16) for an example.

Change-Id: I564fb0724836b6dbbea9262b53ad646e285a339c
2017-02-03 12:20:03 +01:00

107 lines
2.8 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include <cassert>
#include <string>
#include <iostream>
#include <fstream>
#include <set>
#include "plugin.hxx"
#include "check.hxx"
/**
Check for calls to CPPUNIT_ASSERT when it should be using CPPUNIT_ASSERT_EQUALS
*/
namespace {
class CppunitAssertEquals:
public RecursiveASTVisitor<CppunitAssertEquals>, public loplugin::Plugin
{
public:
explicit CppunitAssertEquals(InstantiationData const & data): Plugin(data) {}
virtual void run() override
{
TraverseDecl(compiler.getASTContext().getTranslationUnitDecl());
}
bool VisitCallExpr(const CallExpr*);
bool VisitBinaryOperator(const BinaryOperator*);
private:
void checkExpr(const Stmt* stmt);
};
bool CppunitAssertEquals::VisitCallExpr(const CallExpr* callExpr)
{
if (ignoreLocation(callExpr)) {
return true;
}
if (callExpr->getDirectCallee() == nullptr) {
return true;
}
const FunctionDecl* functionDecl = callExpr->getDirectCallee()->getCanonicalDecl();
if (functionDecl->getOverloadedOperator() != OO_EqualEqual) {
return true;
}
checkExpr(callExpr);
return true;
}
bool CppunitAssertEquals::VisitBinaryOperator(const BinaryOperator* binaryOp)
{
if (ignoreLocation(binaryOp)) {
return true;
}
if (binaryOp->getOpcode() != BO_EQ) {
return true;
}
checkExpr(binaryOp);
return true;
}
/*
* check that we are not a compound expression
*/
void CppunitAssertEquals::checkExpr(const Stmt* stmt)
{
const Stmt* parent = parentStmt(stmt);
if (!parent || !isa<ParenExpr>(parent)) {
return;
}
parent = parentStmt(parent);
if (!parent || !isa<UnaryOperator>(parent)) {
return;
}
parent = parentStmt(parent);
if (!parent || !isa<CallExpr>(parent)) {
return;
}
const CallExpr* callExpr = dyn_cast<CallExpr>(parent);
if (!callExpr || callExpr->getDirectCallee() == nullptr) {
return;
}
const FunctionDecl* functionDecl = callExpr->getDirectCallee()->getCanonicalDecl();
if (!functionDecl ||
!loplugin::DeclCheck(functionDecl).Function("failIf").Namespace("Asserter").Namespace("CppUnit").GlobalNamespace())
{
return;
}
report(
DiagnosticsEngine::Warning, "rather call CPPUNIT_ASSERT_EQUALS",
stmt->getSourceRange().getBegin())
<< stmt->getSourceRange();
}
loplugin::Plugin::Registration< CppunitAssertEquals > X("cppunitassertequals");
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */