avoid having to manuall modify sources when adding a new clang plugin
Now each one registers in its .cxx file. Change-Id: I811c0d4400c2bdccc1c287269378d7e8ad8743ce
This commit is contained in:
@@ -139,4 +139,6 @@ void BodyNotInBlock::checkBody( const Stmt* body, SourceLocation stmtLocation, c
|
||||
}
|
||||
}
|
||||
|
||||
static Plugin::Registration< BodyNotInBlock > X( "bodynotinblock" );
|
||||
|
||||
} // namespace
|
||||
|
@@ -22,7 +22,7 @@ class BodyNotInBlock
|
||||
{
|
||||
public:
|
||||
explicit BodyNotInBlock( ASTContext& context );
|
||||
void run();
|
||||
virtual void run();
|
||||
bool VisitFunctionDecl( FunctionDecl* declaration );
|
||||
private:
|
||||
typedef vector< const Stmt* > StmtParents;
|
||||
|
@@ -49,4 +49,6 @@ bool LclStaticFix::VisitFunctionDecl( FunctionDecl* declaration )
|
||||
return true;
|
||||
}
|
||||
|
||||
static Plugin::Registration< LclStaticFix > X( "lclstaticfix" );
|
||||
|
||||
} // namespace
|
||||
|
@@ -22,7 +22,7 @@ class LclStaticFix
|
||||
{
|
||||
public:
|
||||
explicit LclStaticFix( ASTContext& context, Rewriter& rewriter );
|
||||
void run();
|
||||
virtual void run();
|
||||
bool VisitFunctionDecl( FunctionDecl* declaration );
|
||||
};
|
||||
|
||||
|
@@ -55,6 +55,12 @@ bool Plugin::ignoreLocation( SourceLocation loc )
|
||||
return true;
|
||||
}
|
||||
|
||||
void Plugin::registerPlugin( Plugin* (*create)( ASTContext&, Rewriter& ), const char* optionName, bool isRewriter )
|
||||
{
|
||||
PluginHandler::registerPlugin( create, optionName, isRewriter );
|
||||
}
|
||||
|
||||
/////
|
||||
|
||||
RewritePlugin::RewritePlugin( ASTContext& context, Rewriter& rewriter )
|
||||
: Plugin( context )
|
||||
|
@@ -28,18 +28,36 @@ using namespace std;
|
||||
namespace loplugin
|
||||
{
|
||||
|
||||
/**
|
||||
Base class for plugins.
|
||||
|
||||
If you want to create a non-rewriter action, inherit from this class. Remember to also
|
||||
use Plugin::Registration.
|
||||
*/
|
||||
class Plugin
|
||||
{
|
||||
public:
|
||||
explicit Plugin( ASTContext& context );
|
||||
virtual ~Plugin();
|
||||
virtual void run() = 0;
|
||||
template< typename T > class Registration;
|
||||
protected:
|
||||
DiagnosticBuilder report( DiagnosticsEngine::Level level, StringRef message, SourceLocation loc = SourceLocation());
|
||||
bool ignoreLocation( SourceLocation loc );
|
||||
bool ignoreLocation( const Decl* decl );
|
||||
bool ignoreLocation( const Stmt* stmt );
|
||||
ASTContext& context;
|
||||
private:
|
||||
static void registerPlugin( Plugin* (*create)( ASTContext&, Rewriter& ), const char* optionName, bool isRewriter );
|
||||
template< typename T > static Plugin* createHelper( ASTContext& context, Rewriter& rewriter );
|
||||
enum { isRewriter = false };
|
||||
};
|
||||
|
||||
/**
|
||||
Base class for rewriter plugins.
|
||||
|
||||
Remember to also use Plugin::Registration.
|
||||
*/
|
||||
class RewritePlugin
|
||||
: public Plugin
|
||||
{
|
||||
@@ -85,10 +103,44 @@ class RewritePlugin
|
||||
bool replaceText( SourceRange range, SourceRange replacementRange );
|
||||
Rewriter& rewriter;
|
||||
private:
|
||||
template< typename T > friend class Plugin::Registration;
|
||||
template< typename T > static Plugin* createHelper( ASTContext& context, Rewriter& rewriter );
|
||||
enum { isRewriter = true };
|
||||
bool reportEditFailure( SourceLocation loc );
|
||||
bool adjustForWholeStatement( SourceRange* range );
|
||||
};
|
||||
|
||||
/**
|
||||
Plugin registration helper.
|
||||
|
||||
If you create a new helper class, create also an instance of this class to automatically register it.
|
||||
The passed argument is name of the plugin, used for explicitly invoking rewriter plugins
|
||||
(it is ignored for non-rewriter plugins).
|
||||
|
||||
@code
|
||||
static Plugin::Registration< NameOfClass > X( "nameofclass" );
|
||||
@endcode
|
||||
*/
|
||||
template< typename T >
|
||||
class Plugin::Registration
|
||||
{
|
||||
public:
|
||||
Registration( const char* optionName );
|
||||
};
|
||||
|
||||
class RegistrationCreate
|
||||
{
|
||||
public:
|
||||
template< typename T, bool > static T* create( ASTContext& context, Rewriter& rewriter );
|
||||
};
|
||||
|
||||
/////
|
||||
|
||||
inline
|
||||
Plugin::~Plugin()
|
||||
{
|
||||
}
|
||||
|
||||
inline
|
||||
bool Plugin::ignoreLocation( const Decl* decl )
|
||||
{
|
||||
@@ -101,6 +153,25 @@ bool Plugin::ignoreLocation( const Stmt* stmt )
|
||||
return ignoreLocation( stmt->getLocStart());
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
Plugin* Plugin::createHelper( ASTContext& context, Rewriter& )
|
||||
{
|
||||
return new T( context );
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
Plugin* RewritePlugin::createHelper( ASTContext& context, Rewriter& rewriter )
|
||||
{
|
||||
return new T( context, rewriter );
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
inline
|
||||
Plugin::Registration< T >::Registration( const char* optionName )
|
||||
{
|
||||
registerPlugin( &T::template createHelper< T >, optionName, T::isRewriter );
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif // COMPILEPLUGIN_H
|
||||
|
@@ -19,39 +19,80 @@
|
||||
namespace loplugin
|
||||
{
|
||||
|
||||
struct PluginData
|
||||
{
|
||||
Plugin* (*create)( ASTContext&, Rewriter& );
|
||||
Plugin* object;
|
||||
const char* optionName;
|
||||
bool isRewriter;
|
||||
};
|
||||
|
||||
const int MAX_PLUGINS = 100;
|
||||
static PluginData plugins[ MAX_PLUGINS ];
|
||||
static int pluginCount = 0;
|
||||
static bool pluginObjectsCreated = false;
|
||||
|
||||
PluginHandler::PluginHandler( ASTContext& context, const vector< string >& args )
|
||||
: rewriter( context.getSourceManager(), context.getLangOpts())
|
||||
, args( args )
|
||||
, bodyNotInBlock( context )
|
||||
, lclStaticFix( context, rewriter )
|
||||
, postfixIncrementFix( context, rewriter )
|
||||
, removeForwardStringDecl( context, rewriter )
|
||||
, salLogAreas( context )
|
||||
, unusedVariableCheck( context )
|
||||
{
|
||||
bool wasCreated = false;
|
||||
for( int i = 0;
|
||||
i < pluginCount;
|
||||
++i )
|
||||
{
|
||||
bool create = false;
|
||||
if( args.empty()) // no args -> create non-writer plugins
|
||||
create = !plugins[ i ].isRewriter;
|
||||
else // create only the given plugin(s)
|
||||
{
|
||||
if( find( args.begin(), args.end(), plugins[ i ].optionName ) != args.end())
|
||||
create = true;
|
||||
}
|
||||
if( create )
|
||||
{
|
||||
plugins[ i ].object = plugins[ i ].create( context, rewriter );
|
||||
wasCreated = true;
|
||||
}
|
||||
}
|
||||
pluginObjectsCreated = true;
|
||||
if( !args.empty() && !wasCreated )
|
||||
{
|
||||
DiagnosticsEngine& diag = context.getDiagnostics();
|
||||
diag.Report( diag.getCustomDiagID( DiagnosticsEngine::Fatal,
|
||||
"unknown plugin tool %0 [loplugin]" )) << args.front();
|
||||
}
|
||||
}
|
||||
|
||||
PluginHandler::~PluginHandler()
|
||||
{
|
||||
for( int i = 0;
|
||||
i < pluginCount;
|
||||
++i )
|
||||
if( plugins[ i ].object != NULL )
|
||||
delete plugins[ i ].object;
|
||||
}
|
||||
|
||||
void PluginHandler::registerPlugin( Plugin* (*create)( ASTContext&, Rewriter& ), const char* optionName, bool isRewriter )
|
||||
{
|
||||
assert( !pluginObjectsCreated );
|
||||
assert( pluginCount < MAX_PLUGINS );
|
||||
plugins[ pluginCount ].create = create;
|
||||
plugins[ pluginCount ].object = NULL;
|
||||
plugins[ pluginCount ].optionName = optionName;
|
||||
plugins[ pluginCount ].isRewriter = isRewriter;
|
||||
++pluginCount;
|
||||
}
|
||||
|
||||
void PluginHandler::HandleTranslationUnit( ASTContext& context )
|
||||
{
|
||||
if( context.getDiagnostics().hasErrorOccurred())
|
||||
return;
|
||||
if( isArg( "lclstaticfix" ))
|
||||
lclStaticFix.run();
|
||||
else if( isArg( "postfixincrementfix" ))
|
||||
postfixIncrementFix.run();
|
||||
else if( isArg( "removeforwardstringdecl" ))
|
||||
removeForwardStringDecl.run();
|
||||
else if( args.empty())
|
||||
for( int i = 0;
|
||||
i < pluginCount;
|
||||
++i )
|
||||
{
|
||||
bodyNotInBlock.run();
|
||||
salLogAreas.run();
|
||||
unusedVariableCheck.run();
|
||||
}
|
||||
else
|
||||
{
|
||||
DiagnosticsEngine& diag = context.getDiagnostics();
|
||||
diag.Report( diag.getCustomDiagID( DiagnosticsEngine::Fatal,
|
||||
"unknown plugin tool %0 [loplugin]" )) << args.front();
|
||||
if( plugins[ i ].object != NULL )
|
||||
plugins[ i ].object->run();
|
||||
}
|
||||
for( Rewriter::buffer_iterator it = rewriter.buffer_begin();
|
||||
it != rewriter.buffer_end();
|
||||
|
@@ -16,13 +16,6 @@
|
||||
#include <clang/AST/ASTConsumer.h>
|
||||
#include <clang/Frontend/FrontendAction.h>
|
||||
|
||||
#include "bodynotinblock.hxx"
|
||||
#include "lclstaticfix.hxx"
|
||||
#include "postfixincrementfix.hxx"
|
||||
#include "removeforwardstringdecl.hxx"
|
||||
#include "sallogareas.hxx"
|
||||
#include "unusedvariablecheck.hxx"
|
||||
|
||||
namespace loplugin
|
||||
{
|
||||
|
||||
@@ -34,17 +27,11 @@ class PluginHandler
|
||||
{
|
||||
public:
|
||||
PluginHandler( ASTContext& context, const vector< string >& args );
|
||||
virtual ~PluginHandler();
|
||||
virtual void HandleTranslationUnit( ASTContext& context );
|
||||
static void registerPlugin( Plugin* (*create)( ASTContext&, Rewriter& ), const char* optionName, bool isRewriter );
|
||||
private:
|
||||
bool isArg( const char* arg ) const;
|
||||
Rewriter rewriter;
|
||||
vector< string > args;
|
||||
BodyNotInBlock bodyNotInBlock;
|
||||
LclStaticFix lclStaticFix;
|
||||
PostfixIncrementFix postfixIncrementFix;
|
||||
RemoveForwardStringDecl removeForwardStringDecl;
|
||||
SalLogAreas salLogAreas;
|
||||
UnusedVariableCheck unusedVariableCheck;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -60,14 +47,6 @@ class LibreOfficeAction
|
||||
vector< string > _args;
|
||||
};
|
||||
|
||||
/////
|
||||
|
||||
inline
|
||||
bool PluginHandler::isArg( const char* arg ) const
|
||||
{
|
||||
return find( args.begin(), args.end(), arg ) != args.end();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif // COMPILEPLUGIN_H
|
||||
|
@@ -162,4 +162,6 @@ bool PostfixIncrementFix::shouldDoChange( const Expr* operand )
|
||||
}
|
||||
}
|
||||
|
||||
static Plugin::Registration< PostfixIncrementFix > X( "postfixincrementfix" );
|
||||
|
||||
} // namespace
|
||||
|
@@ -22,7 +22,7 @@ class PostfixIncrementFix
|
||||
{
|
||||
public:
|
||||
explicit PostfixIncrementFix( ASTContext& context, Rewriter& rewriter );
|
||||
void run();
|
||||
virtual void run();
|
||||
bool VisitFunctionDecl( FunctionDecl* declaration );
|
||||
private:
|
||||
typedef std::vector< const Stmt* > StmtParents;
|
||||
|
@@ -73,4 +73,6 @@ bool RemoveForwardStringDecl::tryRemoveStringForwardDecl( const Decl* decl )
|
||||
return false;
|
||||
}
|
||||
|
||||
static Plugin::Registration< RemoveForwardStringDecl > X( "removeforwardstringdecl" );
|
||||
|
||||
} // namespace
|
||||
|
@@ -22,7 +22,7 @@ class RemoveForwardStringDecl
|
||||
{
|
||||
public:
|
||||
explicit RemoveForwardStringDecl( ASTContext& context, Rewriter& rewriter );
|
||||
void run();
|
||||
virtual void run();
|
||||
bool VisitNamespaceDecl( NamespaceDecl* declaration );
|
||||
private:
|
||||
bool tryRemoveStringForwardDecl( const Decl* decl );
|
||||
|
@@ -131,4 +131,6 @@ void SalLogAreas::readLogAreas()
|
||||
report( DiagnosticsEngine::Warning, "error reading log areas [loplugin]" );
|
||||
}
|
||||
|
||||
static Plugin::Registration< SalLogAreas > X( "sallogareas" );
|
||||
|
||||
} // namespace
|
||||
|
@@ -24,7 +24,7 @@ class SalLogAreas
|
||||
{
|
||||
public:
|
||||
explicit SalLogAreas( ASTContext& context );
|
||||
void run();
|
||||
virtual void run();
|
||||
bool VisitFunctionDecl( FunctionDecl* function );
|
||||
bool VisitCallExpr( CallExpr* call );
|
||||
private:
|
||||
|
@@ -100,4 +100,6 @@ bool UnusedVariableCheck::VisitVarDecl( VarDecl* var )
|
||||
return true;
|
||||
}
|
||||
|
||||
static Plugin::Registration< UnusedVariableCheck > X( "unusedvariablecheck" );
|
||||
|
||||
} // namespace
|
||||
|
@@ -22,7 +22,7 @@ class UnusedVariableCheck
|
||||
{
|
||||
public:
|
||||
explicit UnusedVariableCheck( ASTContext& context );
|
||||
void run();
|
||||
virtual void run();
|
||||
bool VisitVarDecl( VarDecl* var );
|
||||
};
|
||||
|
||||
|
Reference in New Issue
Block a user