support for removing a statement as a whole
Change-Id: Icb7b017a0c76a6169f0f629bb40bf97449c75837
This commit is contained in:
@@ -105,25 +105,50 @@ bool RewritePlugin::insertTextBefore( SourceLocation Loc, StringRef Str )
|
|||||||
|
|
||||||
bool RewritePlugin::removeText( SourceLocation Start, unsigned Length, RewriteOptions opts )
|
bool RewritePlugin::removeText( SourceLocation Start, unsigned Length, RewriteOptions opts )
|
||||||
{
|
{
|
||||||
if( rewriter.RemoveText( Start, Length, opts ))
|
return removeText( SourceRange( Start, Start.getLocWithOffset( Length )), opts );
|
||||||
return reportEditFailure( Start );
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RewritePlugin::removeText( CharSourceRange range, RewriteOptions opts )
|
|
||||||
{
|
|
||||||
if( rewriter.RemoveText( range, opts ))
|
|
||||||
return reportEditFailure( range.getBegin());
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RewritePlugin::removeText( SourceRange 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 ))
|
if( rewriter.RemoveText( range, opts ))
|
||||||
return reportEditFailure( range.getBegin());
|
return reportEditFailure( range.getBegin());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool RewritePlugin::adjustForWholeStatement( SourceRange* range )
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
bool RewritePlugin::replaceText( SourceLocation Start, unsigned OrigLength, StringRef NewStr )
|
bool RewritePlugin::replaceText( SourceLocation Start, unsigned OrigLength, StringRef NewStr )
|
||||||
{
|
{
|
||||||
if( rewriter.ReplaceText( Start, OrigLength, NewStr ))
|
if( rewriter.ReplaceText( Start, OrigLength, NewStr ))
|
||||||
|
@@ -44,18 +44,39 @@ class RewritePlugin
|
|||||||
public:
|
public:
|
||||||
explicit RewritePlugin( ASTContext& context, Rewriter& rewriter );
|
explicit RewritePlugin( ASTContext& context, Rewriter& rewriter );
|
||||||
protected:
|
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
|
// 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 (more intuitively) return false on failure rather than true
|
||||||
// - they report a warning when the change cannot be done
|
// - 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 insertText( SourceLocation Loc, StringRef Str,
|
||||||
bool InsertAfter = true, bool indentNewLines = false );
|
bool InsertAfter = true, bool indentNewLines = false );
|
||||||
bool insertTextAfter( SourceLocation Loc, StringRef Str );
|
bool insertTextAfter( SourceLocation Loc, StringRef Str );
|
||||||
bool insertTextAfterToken( SourceLocation Loc, StringRef Str );
|
bool insertTextAfterToken( SourceLocation Loc, StringRef Str );
|
||||||
bool insertTextBefore( SourceLocation Loc, StringRef Str );
|
bool insertTextBefore( SourceLocation Loc, StringRef Str );
|
||||||
bool removeText( SourceLocation Start, unsigned Length, RewriteOptions opts = RewriteOptions());
|
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 removeText( SourceRange range, RewriteOptions opts = RewriteOptions());
|
||||||
bool replaceText( SourceLocation Start, unsigned OrigLength, StringRef NewStr );
|
bool replaceText( SourceLocation Start, unsigned OrigLength, StringRef NewStr );
|
||||||
bool replaceText( SourceRange range, StringRef NewStr );
|
bool replaceText( SourceRange range, StringRef NewStr );
|
||||||
@@ -63,6 +84,7 @@ class RewritePlugin
|
|||||||
Rewriter& rewriter;
|
Rewriter& rewriter;
|
||||||
private:
|
private:
|
||||||
bool reportEditFailure( SourceLocation loc );
|
bool reportEditFailure( SourceLocation loc );
|
||||||
|
bool adjustForWholeStatement( SourceRange* range );
|
||||||
};
|
};
|
||||||
|
|
||||||
inline
|
inline
|
||||||
|
Reference in New Issue
Block a user