summaryrefslogtreecommitdiff
path: root/compilerplugins
diff options
context:
space:
mode:
authorLuboš Luňák <l.lunak@suse.cz>2012-12-20 23:08:52 +0100
committerLuboš Luňák <l.lunak@suse.cz>2013-01-04 15:27:26 +0100
commitc26e655264f03bb8bc484130ab2f539a9f831f16 (patch)
treec25225c8deab3cdfd3d3aa11b491beb7817fa33c /compilerplugins
parent217e3f2ea1e8983328364607f244daceeafca167 (diff)
support for removing a statement as a whole
Change-Id: Icb7b017a0c76a6169f0f629bb40bf97449c75837
Diffstat (limited to 'compilerplugins')
-rw-r--r--compilerplugins/clang/plugin.cxx39
-rw-r--r--compilerplugins/clang/plugin.hxx28
2 files changed, 57 insertions, 10 deletions
diff --git a/compilerplugins/clang/plugin.cxx b/compilerplugins/clang/plugin.cxx
index 6535e1a96471..22bac0cdfe8c 100644
--- a/compilerplugins/clang/plugin.cxx
+++ b/compilerplugins/clang/plugin.cxx
@@ -105,22 +105,47 @@ bool RewritePlugin::insertTextBefore( SourceLocation Loc, StringRef Str )
bool RewritePlugin::removeText( SourceLocation Start, unsigned Length, RewriteOptions opts )
{
- if( rewriter.RemoveText( Start, Length, opts ))
- return reportEditFailure( Start );
- return true;
+ return removeText( SourceRange( Start, Start.getLocWithOffset( Length )), opts );
}
-bool RewritePlugin::removeText( CharSourceRange range, RewriteOptions opts )
+bool RewritePlugin::removeText( SourceRange range, RewriteOptions opts )
{
+ if( opts.RemoveWholeStatement )
+ {
+ if( !adjustForWholeStatement( &range ))
+ return reportEditFailure( range.getBegin());
+ }
if( rewriter.RemoveText( range, opts ))
return reportEditFailure( range.getBegin());
return true;
}
-bool RewritePlugin::removeText( SourceRange range, RewriteOptions opts )
+bool RewritePlugin::adjustForWholeStatement( SourceRange* range )
{
- if( rewriter.RemoveText( range, opts ))
- return reportEditFailure( range.getBegin());
+ SourceManager& SM = rewriter.getSourceMgr();
+ SourceLocation fileStartLoc = SM.getLocForStartOfFile( SM.getFileID( range->getBegin()));
+ if( fileStartLoc.isInvalid())
+ return false;
+ bool invalid = false;
+ const char* fileBuf = SM.getCharacterData( fileStartLoc, &invalid );
+ if( invalid )
+ return false;
+ const char* startBuf = SM.getCharacterData( range->getBegin(), &invalid );
+ if( invalid )
+ return false;
+ const char* endBuf = SM.getCharacterData( range->getEnd(), &invalid );
+ if( invalid )
+ return false;
+ const char* startSpacePos = startBuf;
+ // do not skip \n here, RemoveLineIfEmpty can take care of that
+ --startSpacePos;
+ while( startSpacePos >= fileBuf && ( *startSpacePos == ' ' || *startSpacePos == '\t' ))
+ --startSpacePos;
+ const char* semiPos = strchr( endBuf, ';' );
+ if( semiPos == NULL )
+ return false;
+ *range = SourceRange( range->getBegin().getLocWithOffset( startSpacePos - startBuf + 1 ),
+ range->getEnd().getLocWithOffset( semiPos - endBuf + 1 ));
return true;
}
diff --git a/compilerplugins/clang/plugin.hxx b/compilerplugins/clang/plugin.hxx
index 2a587addcb54..b9409b2cfc1c 100644
--- a/compilerplugins/clang/plugin.hxx
+++ b/compilerplugins/clang/plugin.hxx
@@ -44,18 +44,39 @@ class RewritePlugin
public:
explicit RewritePlugin( ASTContext& context, Rewriter& rewriter );
protected:
- typedef Rewriter::RewriteOptions RewriteOptions;
+ // This enum allows passing just 'RemoveLineIfEmpty' to functions below.
+ enum RemoveLineIfEmpty_t { RemoveLineIfEmpty };
+ // Use this to remove the declaration/statement as a whole, i.e. all whitespace before the statement
+ // and the trailing semicolor (is not part of the AST element range itself).
+ // The trailing semicolon must be present.
+ enum RemoveWholeStatement_t { RemoveWholeStatement };
+ enum RemoveLineIfEmptyAndWholeStatement_t { RemoveLineIfEmptyAndWholeStatement };
+ // syntactic sugar to be able to write 'RemoveLineIfEmpty | RemoveWholeStatement'
+ friend RemoveLineIfEmptyAndWholeStatement_t operator|( RemoveLineIfEmpty_t, RemoveWholeStatement_t )
+ { return RemoveLineIfEmptyAndWholeStatement; }
+ struct RewriteOptions
+ : public Rewriter::RewriteOptions
+ {
+ RewriteOptions() : RemoveWholeStatement( false ) {} // default
+ RewriteOptions( RemoveLineIfEmpty_t ) : RemoveWholeStatement( false ) { RemoveLineIfEmpty = true; }
+ RewriteOptions( RemoveWholeStatement_t ) : RemoveWholeStatement( true ) {}
+ RewriteOptions( RemoveLineIfEmptyAndWholeStatement_t ) : RemoveWholeStatement( true ) { RemoveLineIfEmpty = true; }
+ bool RemoveWholeStatement;
+ };
// These following insert/remove/replaceText functions map to functions
- // in clang::Rewriter, with two differences:
+ // in clang::Rewriter, with these differences:
// - they (more intuitively) return false on failure rather than true
// - they report a warning when the change cannot be done
+ // - There is RemoveWholeStatement to also remove the trailing semicolon when removing (must be there)
+ // and al preceding whitespace.
bool insertText( SourceLocation Loc, StringRef Str,
bool InsertAfter = true, bool indentNewLines = false );
bool insertTextAfter( SourceLocation Loc, StringRef Str );
bool insertTextAfterToken( SourceLocation Loc, StringRef Str );
bool insertTextBefore( SourceLocation Loc, StringRef Str );
bool removeText( SourceLocation Start, unsigned Length, RewriteOptions opts = RewriteOptions());
- bool removeText( CharSourceRange range, RewriteOptions opts = RewriteOptions());
+ // CharSourceRange not supported, unless really needed, as it makes RemoveSemicolon more complicated
+ //bool removeText( CharSourceRange range, RewriteOptions opts = RewriteOptions());
bool removeText( SourceRange range, RewriteOptions opts = RewriteOptions());
bool replaceText( SourceLocation Start, unsigned OrigLength, StringRef NewStr );
bool replaceText( SourceRange range, StringRef NewStr );
@@ -63,6 +84,7 @@ class RewritePlugin
Rewriter& rewriter;
private:
bool reportEditFailure( SourceLocation loc );
+ bool adjustForWholeStatement( SourceRange* range );
};
inline