Kaydet (Commit) a7c3adb7 authored tarafından Luboš Luňák's avatar Luboš Luňák

avoid having to manuall modify sources when adding a new clang plugin

Now each one registers in its .cxx file.

Change-Id: I811c0d4400c2bdccc1c287269378d7e8ad8743ce
üst b8f932b6
......@@ -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())
{
bodyNotInBlock.run();
salLogAreas.run();
unusedVariableCheck.run();
}
else
for( int i = 0;
i < pluginCount;
++i )
{
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 );
};
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment