move plugin handling to separate source files

Change-Id: Ifa1af34121bda9ca3250d09a3b8a46ea226795ed
This commit is contained in:
Luboš Luňák
2013-02-02 16:35:47 +01:00
parent a31f465416
commit b8f932b6a5
4 changed files with 212 additions and 156 deletions

View File

@@ -10,21 +10,10 @@
#include "plugin.hxx"
#include <clang/AST/ASTConsumer.h>
#include <clang/AST/ASTContext.h>
#include <clang/Basic/FileManager.h>
#include <clang/Frontend/CompilerInstance.h>
#include <clang/Frontend/FrontendAction.h>
#include <clang/Frontend/FrontendPluginRegistry.h>
#include <stdio.h>
#include <unistd.h>
#include "bodynotinblock.hxx"
#include "lclstaticfix.hxx"
#include "postfixincrementfix.hxx"
#include "removeforwardstringdecl.hxx"
#include "sallogareas.hxx"
#include "unusedvariablecheck.hxx"
#include "pluginhandler.hxx"
namespace loplugin
{
@@ -176,148 +165,4 @@ bool RewritePlugin::reportEditFailure( SourceLocation loc )
return false;
}
/**
Class that manages all LO modules.
*/
class PluginHandler
: public ASTConsumer
{
public:
explicit 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 )
{
}
virtual void 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
{
DiagnosticsEngine& diag = context.getDiagnostics();
diag.Report( diag.getCustomDiagID( DiagnosticsEngine::Fatal,
"unknown plugin tool %0 [loplugin]" )) << args.front();
}
for( Rewriter::buffer_iterator it = rewriter.buffer_begin();
it != rewriter.buffer_end();
++it )
{
const FileEntry* e = context.getSourceManager().getFileEntryForID( it->first );
DiagnosticsEngine& diag = context.getDiagnostics();
/* Check where the file actually is, and warn about cases where modification
most probably doesn't matter (generated files in workdir).
The order here is important, as OUTDIR and WORKDIR are often in SRCDIR/BUILDDIR,
and BUILDDIR is sometimes in SRCDIR. */
string modifyFile;
if( strncmp( e->getName(), OUTDIR, strlen( OUTDIR )) == 0 )
{
/* Try to find a matching file for a file in solver/ (include files
are usually included from there rather than from the source dir) if possible. */
if( strncmp( e->getName(), OUTDIR "/inc/", strlen( OUTDIR ) + strlen( "/inc/" )) == 0 )
{
string filename( e->getName());
int modulePos = strlen( OUTDIR ) + strlen( "/inc/" );
size_t moduleEnd = filename.find( '/', modulePos );
if( moduleEnd != string::npos )
{
modifyFile = SRCDIR "/" + filename.substr( modulePos, moduleEnd - modulePos )
+ "/inc/" + filename.substr( modulePos );
}
}
if( modifyFile.empty())
diag.Report( diag.getCustomDiagID( DiagnosticsEngine::Warning,
"modified source in solver/ : %0 [loplugin]" )) << e->getName();
}
else if( strncmp( e->getName(), WORKDIR, strlen( WORKDIR )) == 0 )
diag.Report( diag.getCustomDiagID( DiagnosticsEngine::Warning,
"modified source in workdir/ : %0 [loplugin]" )) << e->getName();
else if( strcmp( SRCDIR, BUILDDIR ) != 0 && strncmp( e->getName(), BUILDDIR, strlen( BUILDDIR )) == 0 )
diag.Report( diag.getCustomDiagID( DiagnosticsEngine::Warning,
"modified source in build dir : %0 [loplugin]" )) << e->getName();
else if( strncmp( e->getName(), SRCDIR, strlen( SRCDIR )) == 0 )
; // ok
else
{
diag.Report( diag.getCustomDiagID( DiagnosticsEngine::Warning,
"modified source in unknown location, not modifying : %0 [loplugin]" )) << e->getName();
continue; // --->
}
if( modifyFile.empty())
modifyFile = e->getName();
char* filename = new char[ modifyFile.length() + 100 ];
sprintf( filename, "%s.new.%d", modifyFile.c_str(), getpid());
string error;
bool ok = false;
raw_fd_ostream ostream( filename, error );
if( error.empty())
{
it->second.write( ostream );
ostream.close();
if( !ostream.has_error() && rename( filename, modifyFile.c_str()) == 0 )
ok = true;
}
ostream.clear_error();
unlink( filename );
if( !ok )
diag.Report( diag.getCustomDiagID( DiagnosticsEngine::Error,
"cannot write modified source to %0 (%1) [loplugin]" )) << modifyFile << error;
delete[] filename;
}
}
private:
bool isArg( const char* arg ) const
{
return find( args.begin(), args.end(), arg ) != args.end();
}
Rewriter rewriter;
vector< string > args;
BodyNotInBlock bodyNotInBlock;
LclStaticFix lclStaticFix;
PostfixIncrementFix postfixIncrementFix;
RemoveForwardStringDecl removeForwardStringDecl;
SalLogAreas salLogAreas;
UnusedVariableCheck unusedVariableCheck;
};
/**
The Clang plugin class, just forwards to PluginHandler.
*/
class LibreOfficeAction
: public PluginASTAction
{
public:
virtual ASTConsumer* CreateASTConsumer( CompilerInstance& Compiler, StringRef InFile )
{
return new PluginHandler( Compiler.getASTContext(), _args );
}
virtual bool ParseArgs( const CompilerInstance& CI, const vector< string >& args )
{
_args = args;
return true;
}
private:
vector< string > _args;
};
} // namespace
static FrontendPluginRegistry::Add< loplugin::LibreOfficeAction > X( "loplugin", "LibreOffice compile check plugin" );