cascading conditional operators, give a hint on complexity

Change-Id: Ie9d0b07a32cc17705db735ea18f70f28d57badd4
Reviewed-on: https://gerrit.libreoffice.org/12990
Reviewed-by: Björn Michaelsen <bjoern.michaelsen@canonical.com>
Tested-by: Björn Michaelsen <bjoern.michaelsen@canonical.com>
This commit is contained in:
Bjoern Michaelsen
2014-11-19 17:46:01 +01:00
committed by Björn Michaelsen
parent 2851ce5afd
commit 395d6a96aa
3 changed files with 39 additions and 8 deletions

View File

@@ -14,8 +14,8 @@
/*
This is a compile check.
It checks for conditional operators in conditional operators, which are
errorprone, e.g.
It checks for complex statements with conditional operators in conditional
operators, which are errorprone, e.g.
Thing foo = IsBar() ? ( IsBaz() ? b1 : b2 ) : b3;
However, it finds 556 cases in sw/source alone, thus likely needs some more
@@ -24,9 +24,19 @@ a certain length in characters (but that needs the Context/SourceManager, which
I havent played with yet).
*/
// the value is rather arbitrary, but code above this number of stmts begins to
// be smelly
static const int stmtlimit = 50;
namespace loplugin
{
struct WalkCounter
{
int stmtcount;
bool cascading;
};
// Ctor, nothing special, pass the argument(s).
CascadingCondOp::CascadingCondOp( const InstantiationData& data )
: Plugin( data )
@@ -41,20 +51,30 @@ void CascadingCondOp::run()
TraverseDecl( compiler.getASTContext().getTranslationUnitDecl());
}
void CascadingCondOp::Walk( const Stmt* stmt )
void CascadingCondOp::Walk( const Stmt* stmt, WalkCounter& c )
{
for(Stmt::const_child_iterator it = stmt->child_begin(); it != stmt->child_end(); ++it)
{
if ( const ConditionalOperator* condop = dyn_cast< ConditionalOperator >( *it ))
report( DiagnosticsEngine::Warning, "cascading conditional operator", condop->getLocStart());
Walk(*it);
++c.stmtcount;
if ( dyn_cast< ConditionalOperator >( *it ))
c.cascading = true;
Walk(*it, c);
}
}
bool CascadingCondOp::VisitStmt( const Stmt* stmt )
{
if ( const ConditionalOperator* condop = dyn_cast< ConditionalOperator >( stmt ))
Walk(condop);
{
WalkCounter c = { 0, false };
Walk(condop, c);
if(c.cascading && c.stmtcount >= stmtlimit)
{
std::string msg("cascading conditional operator, complexity: ");
msg.append(std::to_string(c.stmtcount));
report( DiagnosticsEngine::Warning, msg, condop->getLocStart());
}
}
return true;
}

View File

@@ -17,6 +17,8 @@
namespace loplugin
{
struct WalkCounter;
// The class implementing the plugin action.
class CascadingCondOp
// Inherits from the Clang class that will allow examing the Clang AST tree (i.e. syntax tree).
@@ -27,7 +29,7 @@ class CascadingCondOp
public:
CascadingCondOp( const InstantiationData& data );
virtual void run() override;
void Walk( const Stmt* stmt );
void Walk( const Stmt* stmt, WalkCounter& c );
bool VisitStmt( const Stmt* stmt );
};

View File

@@ -358,4 +358,13 @@ SwEditShell* SwDoc::GetEditShell()
return GetEditShell();
}
//bool foo()
//{
// bool b1 = true ? true : false;
// bool b2 = (true ? true : false) ? true : false;
// bool b3 = true ? (true ? true : false) : false;
// bool b4 = true ? true : (true ? true : false);
// return false;
//}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */