|
From: <net...@us...> - 2002-12-28 10:44:43
|
Update of /cvsroot/cpptool/rfta/src/rfta
In directory sc8-pr-cvs1:/tmp/cvs-serv25280/src/rfta
Added Files:
InlineTempRefactoringTest.h InlineTempRefactoringTest.cpp
InlineTempRefactoring.h InlineTempRefactoring.cpp
Log Message:
-- inlinetemprefactoring implementation & test
--- NEW FILE: InlineTempRefactoringTest.h ---
// //////////////////////////////////////////////////////////////////////////
// (c)Copyright 2002, Baptiste Lepilleur.
// Created: 2002/12/25
// //////////////////////////////////////////////////////////////////////////
#ifndef RFTA_INLINETEMPREFACTORINGTEST_H
#define RFTA_INLINETEMPREFACTORINGTEST_H
#include "SourceBasedTestBase.h"
#include <rfta/refactoring/RefactoringError.h>
namespace Refactoring
{
class PlainTextDocument;
/// Unit tests for InlineTempRefactoringTest
class InlineTempRefactoringTest : public SourceBasedTestBase
{
CPPUNIT_TEST_SUITE( InlineTempRefactoringTest );
CPPUNIT_TEST( testEasiestCase );
CPPUNIT_TEST( testThrowNoInitializer );
CPPUNIT_TEST( testThrowInitializerNotSupported );
CPPUNIT_TEST( testThrowVariableAssigned );
CPPUNIT_TEST( testDetectComplexVariableAssignments );
CPPUNIT_TEST( testMultipleDeclarationInitLast );
CPPUNIT_TEST( testMultipleDeclarationInitFirst );
CPPUNIT_TEST( testMultipleDeclarationInitMiddle );
CPPUNIT_TEST( testInitExpression );
CPPUNIT_TEST_SUITE_END();
public:
/*! Constructs a InlineTempRefactoringTest object.
*/
InlineTempRefactoringTest();
/// Destructor.
virtual ~InlineTempRefactoringTest();
void setUp();
void tearDown();
void testEasiestCase();
void testThrowNoInitializer();
void testThrowInitializerNotSupported();
void testThrowVariableAssigned();
void testDetectComplexVariableAssignments();
void testMultipleDeclarationInitLast();
void testMultipleDeclarationInitFirst();
void testMultipleDeclarationInitMiddle();
void testInitExpression();
private:
/// Prevents the use of the copy constructor.
InlineTempRefactoringTest( const InlineTempRefactoringTest &other );
/// Prevents the use of the copy operator.
void operator =( const InlineTempRefactoringTest &other );
private:
void applyRefactoring( const std::string &LocaleVariableName );
void applyRefactoringExpectThrow( const std::string &LocaleVariableName , RefactoringError::Cause _cause ,const CppUnit::SourceLine &sourceLine );
void applyRefactoringExpectThrow( const std::string &assigment , const std::string &LocaleVariableName , RefactoringError::Cause _cause ,const CppUnit::SourceLine &sourceLine );
void applyRefactoringNoThrow ( const std::string &assignment , const std::string &LocaleVariableName , const CppUnit::SourceLine &sourceLine );
boost::shared_ptr<PlainTextDocument> document_;
};
// Inlines methods for InlineTempRefactoringTest:
// ----------------------------------------------
} // namespace Refactoring
#endif // RFTA_INLINETEMPREFACTORINGTEST_H
--- NEW FILE: InlineTempRefactoringTest.cpp ---
// //////////////////////////////////////////////////////////////////////////
// (c)Copyright 2002, Baptiste Lepilleur.
// Created: 2002/12/25
// //////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "InlineTempRefactoringTest.h"
#include "InlineTempRefactoring.h"
#include <rfta/refactoring/PlainTextDocument.h>
namespace Refactoring
{
RFTA_TEST_SUITE_REGISTRATION( InlineTempRefactoringTest );
InlineTempRefactoringTest::InlineTempRefactoringTest()
{
}
InlineTempRefactoringTest::~InlineTempRefactoringTest()
{
}
void
InlineTempRefactoringTest::setUp()
{
SourceBasedTestBase::setUp();
}
void
InlineTempRefactoringTest::tearDown()
{
document_.reset();
SourceBasedTestBase::tearDown();
}
/**
* Help function used for applying refactoring algorithm to one example.
*/
void
InlineTempRefactoringTest::applyRefactoring( const std::string &LocaleVariableName )
{
document_.reset( new PlainTextDocument( source_ ) );
int selectionIndex = builder_->getStartIndex( "selection" );
InlineTempRefactoring refactoring( *document_,
selectionIndex );
refactoring.apply( );
CPPUNIT_ASSERT_EQUAL( LocaleVariableName, refactoring.getVariableName() );
}
/**
* Help function to test if refactoring implementation throws the expected exception,
* with the correct 'exception-reason'
*/
void
InlineTempRefactoringTest::applyRefactoringExpectThrow( const std::string &LocaleVariableName ,
RefactoringError::Cause _cause,
const CppUnit::SourceLine &sourceLine )
{
bool failed = true;
RefactoringError expected(_cause);
document_.reset( new PlainTextDocument( source_ ) );
int selectionIndex = builder_->getStartIndex( "selection" );
try {
InlineTempRefactoring refactoring( *document_,
selectionIndex );
refactoring.apply( );
std::string failure = std::string("Test fails since it expects the refactoring error '") + expected.what() + "'.";
CppUnit::Asserter::fail( CppUnit::Message( failure ), sourceLine );
}
catch (RefactoringError& err)
{
// todo@: compare the 'cause'
if ( err.getCause() != expected.getCause() )
{
std::string failure = std::string("Test fails since it throws Exception'")+err.what()+"' instead of expected '" + expected.what() + "'.";
CppUnit::Asserter::fail( CppUnit::Message( failure ), sourceLine );
}
}
}
void
InlineTempRefactoringTest::applyRefactoringExpectThrow( const std::string &assignment , const std::string &LocaleVariableName , RefactoringError::Cause _cause ,const CppUnit::SourceLine &sourceLine )
{
SourceBasedTestBase::setUp();
builder_->add( "{ double y = 2;" );
builder_->addKeyingMid( " double ", LocaleVariableName ,"= 5;", "selection" );
builder_->add( assignment );
builder_->add( "}" );
applyRefactoringExpectThrow( LocaleVariableName , RefactoringError::variableIsAssigned , sourceLine );
SourceBasedTestBase::tearDown();
}
void
InlineTempRefactoringTest::applyRefactoringNoThrow( const std::string &assignment , const std::string &LocaleVariableName , const CppUnit::SourceLine &sourceLine )
{
SourceBasedTestBase::setUp();
builder_->add( "{ double y = 2;" );
builder_->addKeyingMid( " double ", LocaleVariableName ,"= 5;", "selection" );
builder_->add( assignment );
builder_->add( "}" );
try {
applyRefactoring( LocaleVariableName );
}
catch (RefactoringError& err)
{
std::string failure = std::string("Test fails since it throws Exception '")+err.what()+"'. This was not expected.";
CppUnit::Asserter::fail( CppUnit::Message( failure ), sourceLine );
}
SourceBasedTestBase::tearDown();
}
void
InlineTempRefactoringTest::testEasiestCase()
{
builder_->add(
"{"
" double y;" );
builder_->addKeyingMid( " double ", "x"," = 4;", "selection" );
builder_->add( "y += y * x;");
builder_->add(
" return x * getQuantity();"
"}" );
applyRefactoring( "x" );
std::string expectedSource(
"{"
" double y;"
" y += y * 4;"
" return 4 * getQuantity();"
"}" );
std::string actualSource( document_->getAllText() );
RFTA_ASSERT_EQUAL( expectedSource, actualSource );
}
void
InlineTempRefactoringTest::testThrowNoInitializer()
{
builder_->add(
"{"
" double y;" );
builder_->addKeyingMid( " double ", "x",";", "selection" );
builder_->add( "y += y * x;");
builder_->add(
" return x * getQuantity();"
"}" );
applyRefactoringExpectThrow( "x" , RefactoringError::identifierIsNotInitialized , CPPUNIT_SOURCELINE() );
}
void
InlineTempRefactoringTest::testThrowInitializerNotSupported()
{
builder_->add(
"{"
" double y = 2;" );
builder_->addKeyingMid( " double ", "x","= 5 * y;", "selection" );
builder_->add( "y += y * x;");
builder_->add(
" return x * getQuantity();"
"}" );
applyRefactoringExpectThrow( "x" , RefactoringError::initializerValueNotSupported , CPPUNIT_SOURCELINE() );
}
void
InlineTempRefactoringTest::testThrowVariableAssigned()
{
applyRefactoringExpectThrow( "x = 2;", "x" , RefactoringError::variableIsAssigned , CPPUNIT_SOURCELINE() );
}
void
InlineTempRefactoringTest::testDetectComplexVariableAssignments()
{
applyRefactoringExpectThrow( "*c += x = 1;" , "x" , RefactoringError::variableIsAssigned , CPPUNIT_SOURCELINE() );
applyRefactoringExpectThrow( "if (x=1) ;" , "x" , RefactoringError::variableIsAssigned , CPPUNIT_SOURCELINE() );
applyRefactoringNoThrow ( "if (x==1) ;" , "x" , CPPUNIT_SOURCELINE() );
applyRefactoringExpectThrow( "y=2,x=1;" , "x" , RefactoringError::variableIsAssigned , CPPUNIT_SOURCELINE() );
applyRefactoringNoThrow ( "y=2,x==1;" , "x" , CPPUNIT_SOURCELINE() );
applyRefactoringExpectThrow( "int j = x = 2;", "x" , RefactoringError::variableIsAssigned , CPPUNIT_SOURCELINE() );
// the following will fail because of incomplete expression parser:
/*
applyRefactoringExpectThrow( "*c += ( x += 1 );" , "x" , RefactoringError::variableIsAssigned , CPPUNIT_SOURCELINE() );
applyRefactoringExpectThrow( "fct(x = 1);" , "x" , RefactoringError::variableIsAssigned , CPPUNIT_SOURCELINE() );
applyRefactoringExpectThrow( "x++;" , "x" , RefactoringError::variableIsAssigned , CPPUNIT_SOURCELINE() );
*/
}
void
InlineTempRefactoringTest::testMultipleDeclarationInitLast()
{
builder_->add(
"{"
" double y;" );
builder_->addKeyingMid( " double z , ", "x"," = 4;" , "selection" );
builder_->add( " y += y * x;");
builder_->add(
" return x * getQuantity();"
"}" );
applyRefactoring( "x" );
std::string expectedSource(
"{"
" double y; double z;"
" y += y * 4;"
" return 4 * getQuantity();"
"}" );
std::string actualSource( document_->getAllText() );
RFTA_ASSERT_EQUAL( expectedSource, actualSource );
}
void
InlineTempRefactoringTest::testMultipleDeclarationInitFirst()
{
builder_->add(
"{"
" double y;" );
builder_->addKeyingMid( " double ", "x"," = 4, z;", "selection" );
builder_->add( " y += y * x;");
builder_->add(
" return x * getQuantity();"
"}" );
applyRefactoring( "x" );
std::string expectedSource(
"{"
" double y; double z;"
" y += y * 4;"
" return 4 * getQuantity();"
"}" );
std::string actualSource( document_->getAllText() );
RFTA_ASSERT_EQUAL( expectedSource, actualSource );
}
void
InlineTempRefactoringTest::testMultipleDeclarationInitMiddle()
{
builder_->add(
"{"
" double y;" );
builder_->addKeyingMid( " double v , ", "x"," = 4, z;", "selection" );
builder_->add( " y += y * x;");
builder_->add(
" return x * getQuantity();"
"}" );
applyRefactoring( "x" );
std::string expectedSource(
"{"
" double y; double v , z;"
" y += y * 4;"
" return 4 * getQuantity();"
"}" );
std::string actualSource( document_->getAllText() );
RFTA_ASSERT_EQUAL( expectedSource, actualSource );
}
void
InlineTempRefactoringTest::testInitExpression()
{
builder_->add(
"{"
" double y;" );
builder_->addKeyingMid( " double ", "x"," = 4 + 3;", "selection" );
builder_->add( "y += y * x;");
builder_->add(
" return x * getQuantity();"
"}" );
applyRefactoring( "x" );
std::string expectedSource(
"{"
" double y;"
" y += y * ( 4 + 3 );"
" return ( 4 + 3 ) * getQuantity();"
"}" );
std::string actualSource( document_->getAllText() );
RFTA_ASSERT_EQUAL( expectedSource, actualSource );
}
} // namespace Refactoring
--- NEW FILE: InlineTempRefactoring.h ---
// //////////////////////////////////////////////////////////////////////////
// (c)Copyright 2002, Andre Baresel
// Created: 2002/12/25
// //////////////////////////////////////////////////////////////////////////
#ifndef RFTA_RFTA_INLINETEMPREFACTORING_H
#define RFTA_RFTA_INLINETEMPREFACTORING_H
#include <rfta/parser/ASTNode.h>
#include <rfta/refactoring/RefactoringBase.h>
#include <rfta/refactoring/ToolsBox.h>
namespace Refactoring
{
/// This class implements the algorithm for InlineTemp refactoring.
class RFTA_API InlineTempRefactoring : public RefactoringBase
{
public:
/**
* constructs on object and prepares the inlining
*/
InlineTempRefactoring(TextDocument &document,int temporaryLocation);
/**
* destroys object data.
*/
virtual ~InlineTempRefactoring();
/**
* function executes the inlining.
*/
void apply( );
/**
* function returns the name of the temporary which is about to be inlined
*/
const std::string getVariableName() const;
/**
* returns the number of occurences of the variable.
*/
int getVariableOccurrenceCount() const;
private:
void prepare(); //< does prepare the inlining (check if it's possible and find the locations for inlining)
void findLocaleVariableOccurrences(); //< find the locations of variable uses
void calculateTempDeclRange(); //< finds the source range of the temporary declaration
bool isInitializerAtomic(); //< does check the initializer for being an atomic value or not
void checkForVariableAssignments();
int temporaryLocation_; //< location where refactoring was asked for
SourceASTNodePtr sourceNode_; //< parsed source of the location
ToolsBox::ASTNodes occurrences_; //< occurences of the temporary variable
ASTNodePtr localeVariableNode_; //< ast node of the identifier at selection
ASTNodePtr temporaryDecl; //< ast node of the declaration of the selected identifier
ASTNodePtr initValue_; //< ast node of the initializer that initializes the selected variable
SourceRange rangeOfTempDeclaration; //< Range of temporary declaration that is inlined (this range can be erased after inlining)
bool tempDeclaredInMiddle; //< true if the temporary is declared between other variables.
};
// Inlines methods for InlineTempRefactoring:
// ------------------------------------------
} // namespace Refactoring
#endif // RFTA_RFTA_INLINETEMPREFACTORING_H
--- NEW FILE: InlineTempRefactoring.cpp ---
// //////////////////////////////////////////////////////////////////////////
// (c)Copyright 2002, Baptiste Lepilleur.
// Created: 2002/12/25
// //////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "InlineTempRefactoring.h"
#include <rfta/refactoring/RefactoringError.h>
#include <rfta/refactoring/TextDocument.h>
#include <rfta/parser/NonSemanticBlanker.h>
#include <rfta/parser/ParseContext.h>
#include <rfta/parser/StatementParser.h>
#include <rfta/parser/MaxLODMutator.h>
#include <rfta/parser/ExpressionOperationMutator.h>
#include <rfta/parser/ASTNodes.h>
#include "IdentifierResolverContext.h"
#include "IdentifierResolver.h"
#include "ReplaceTextTransform.h"
#include "TransformList.h"
namespace Refactoring
{
InlineTempRefactoring::InlineTempRefactoring( TextDocument &document,
int temporaryLocation )
: RefactoringBase( document )
, temporaryLocation_( temporaryLocation )
{
prepare();
}
InlineTempRefactoring::~InlineTempRefactoring()
{
}
/**
* this might not work anymore after inlining has been done.
*/
const std::string
InlineTempRefactoring::getVariableName() const
{
if ( !localeVariableNode_ )
throw RefactoringError( RefactoringError::identifierIsNotLocalVariable );
return localeVariableNode_->getBlankedText();
}
int
InlineTempRefactoring::getVariableOccurrenceCount() const
{
if ( !localeVariableNode_ )
throw RefactoringError( RefactoringError::identifierIsNotLocalVariable );
return occurrences_.size();
}
void
InlineTempRefactoring::prepare()
{
// get the source code:
std::string source( getDocument().getAllText() );
if ( temporaryLocation_ >= source.length() )
throw RefactoringError( RefactoringError::selectionNotInSource );
// blank the source code
NullPPDirectiveListener nullListener;
std::string blankedSource;
NonSemanticBlanker blanker( source, blankedSource, nullListener );
blanker.blank();
// find the compound statement where the temporary is located:
int compoundStartIndex =
ToolsBox::findCompoundBefore( blankedSource, temporaryLocation_ );
if ( compoundStartIndex < 0 )
throw RefactoringError( RefactoringError::temporaryNotInFunctionBody );
// 'lazy' parse the source
sourceNode_ = SourceASTNode::create( blankedSource, source );
ParseContext context( sourceNode_ );
StatementParser parser( context,
sourceNode_->getBlankedSourceStart() +
compoundStartIndex,
sourceNode_->getBlankedSourceEnd() );
parser.parse();
// do mutate to highest level until we know how to do it 'lazy'
MaxLODMutator mutator;
mutator.mutate( sourceNode_, sourceNode_ );
// find all occurrences of the temporary.
findLocaleVariableOccurrences();
// check for initializer property and throw exception if not found
if (!temporaryDecl->hasProperty(ASTNodeProperties::variableInitializerProperty))
throw RefactoringError( RefactoringError::identifierIsNotInitialized );
ASTNodePtr initializerNode_;
initializerNode_ = temporaryDecl->getProperty(ASTNodeProperties::variableInitializerProperty);
// check for value expression:
if (!initializerNode_->hasProperty(ASTNodeProperties::valueProperty))
throw RefactoringError( RefactoringError::initializerValueNotSupported );
initValue_ = initializerNode_->getProperty(ASTNodeProperties::valueProperty);
// @todo: EXTEND THIS BY CHECKING IF local-scope-identifiers can be inlined
int numberOfChilds = initValue_->getChildCount();
if (numberOfChilds > 0)
{
for (int idx = 0; idx < numberOfChilds; idx++ )
{
ASTNodePtr child = initValue_->getChildAt(idx);
if ( child->getType() == ASTNodeTypes::localScopeIdentifier )
throw RefactoringError( RefactoringError::initializerValueNotSupported );
}
}
checkForVariableAssignments();
}
/**
* check all occurences for:
* not being assignments to the identifier
*
* function throws an exception in case of a detected assignment.
*/
void
InlineTempRefactoring::checkForVariableAssignments()
{
for ( ToolsBox::ASTNodes::const_iterator it = occurrences_.begin();
it != occurrences_.end();
++it )
{
if ( *it != localeVariableNode_)
{
// get the expression this variable belongs to:
ASTNodePtr parentExpr = boost::make_shared((*it)->getParentNode());
bool go_deeper = false;
do {
go_deeper = false;
if (!parentExpr->hasProperty(ASTNodeProperties::expressionTypeProperty))
{
// call mutator on this expression:
SourceASTNodePtr sourceNode = boost::make_shared(parentExpr->getSourceNode());
ParseContext context( sourceNode );
ExpressionOperationMutator mutator( context, parentExpr, sourceNode );
mutator.mutate();
// check if no expression type was added:
if (!parentExpr->hasProperty(ASTNodeProperties::expressionTypeProperty))
break;
}
// check if the expression is an assignment:
ASTNodePtr exprType = parentExpr->getProperty(ASTNodeProperties::expressionTypeProperty);
if (exprType->getType() == ASTNodeTypes::assignmentExpression)
{
// find the first child that is <expression>
int idx;
for (idx=0;idx<parentExpr->getChildCount();idx++)
if (parentExpr->getChildAt(idx)->getType()==ASTNodeTypes::expression)
break;
// check if localVariable is on the left hand side:
ASTNodePtr left = parentExpr->getChildAt(idx);
SourceRange varRange = (*it)->getRange();
SourceRange leftRange = left->getRange();
if (leftRange.contains(varRange))
throw RefactoringError( RefactoringError::variableIsAssigned );
else
{
parentExpr = parentExpr->getChildAt(idx+1);
go_deeper = true;
}
}
} while (go_deeper);
}
}
}
void
InlineTempRefactoring::findLocaleVariableOccurrences()
{
SourceRange temporaryRange( temporaryLocation_, 1 );
localeVariableNode_ = ToolsBox::findIdentifierNodeAt( temporaryRange,
sourceNode_ );
if ( !localeVariableNode_ )
throw RefactoringError( RefactoringError::selectionIsNotAnIdentifier );
IdentifierResolverContext context( sourceNode_ );
IdentifierResolver resolver( context );
resolver.visitNode( sourceNode_ );
try
{
temporaryDecl =
context.getLocalVariableIdentifierDeclaration( localeVariableNode_ );
ASTNodePtr compoundNode = sourceNode_->getChildAt(0);
ToolsBox::getLocalVariableOccurrences( compoundNode,
temporaryDecl,
sourceNode_,
context,
occurrences_ );
}
catch ( NotLocalVariableIdentifierError & )
{
throw RefactoringError( RefactoringError::identifierIsNotLocalVariable );
}
}
/**
* function does check if the temporary is declared in its own declaration expression
* or if it's part of a declaration for more than one variable.
*/
void InlineTempRefactoring::calculateTempDeclRange()
{
tempDeclaredInMiddle = false;
// remove the declaration of the temporary:
ASTNodePtr decl_expr = boost::make_shared(temporaryDecl->getParentNode());
int countVarDecl = 0;
for (int j = 0; j < decl_expr->getChildCount(); j++ )
{
if (decl_expr->getChildAt(j)->getType() == ASTNodeTypes::variableDeclExpression )
countVarDecl++;
}
// check number of variables declared in this declaration:
if ( countVarDecl == 1)
// Temp is declared in its own declaration expression, range is the full expression
rangeOfTempDeclaration = decl_expr->getRange();
else
{ // Temp is declared together with other variables, we need to calculate the range
ASTNodePtr tempVarNameNode = temporaryDecl->getProperty(ASTNodeProperties::variableNameProperty);
// find out the declaration just before the temporary is declared:
int tempVarBegin = tempVarNameNode->getRange().getStartIndex();
int tempVarEnd = initValue_->getRange().getEndIndex();
int lastChildEndBefore = 0;
int firstChildStartAfter = decl_expr->getRange().getEndIndex() - 1; // ends just before the semicolon
bool childDeclaredAfterTemp = false;
for (int j = 0; j < decl_expr->getChildCount(); j++ )
{
ASTNodePtr child = decl_expr->getChildAt(j);
if ( temporaryDecl == child ) continue;
ASTNodePtr childNameNode = child->getProperty(ASTNodeProperties::variableNameProperty);
int childEndIndex = child->getRange().getEndIndex();
int childStartIndex = childNameNode->getRange().getStartIndex();
// check if the current child is the last before the temporary:
if ( childEndIndex < tempVarBegin && childEndIndex > lastChildEndBefore )
lastChildEndBefore = childEndIndex;
// check if the current child is declared after the temporary:
if ( childStartIndex > tempVarEnd && firstChildStartAfter > childStartIndex )
{
childDeclaredAfterTemp = true;
firstChildStartAfter = childStartIndex;
}
}
// temp is declared between other in case:
// there're declaration after its declaration && it is not the first
tempDeclaredInMiddle = childDeclaredAfterTemp && ( lastChildEndBefore != 0 );
// check if temporary is declared as first:
if ( lastChildEndBefore==0 )
lastChildEndBefore = tempVarBegin; // in this case delete range beginning at the temp-var-name
// calculate the range:
SourceRange merged ( lastChildEndBefore , firstChildStartAfter - lastChildEndBefore );
rangeOfTempDeclaration = merged;
}
}
bool InlineTempRefactoring::isInitializerAtomic()
{
SourceRange range = initValue_->getRange();
const char * start = &sourceNode_->getBlankedSourceStart()[range.getStartIndex()];
const char * end = &sourceNode_->getBlankedSourceStart()[range.getEndIndex()];
const char * c = start;
while (c != end)
{
switch (*c)
{
case '+': case '-': case '*': case '/': case '%': case '&':
case '|': case ',': case '~': case '^': return false;
}
c++;
}
return true;
}
void
InlineTempRefactoring::apply()
{
TransformList transforms;
calculateTempDeclRange();
if (tempDeclaredInMiddle)
transforms.add( *new ReplaceTextTransform( rangeOfTempDeclaration , " , " ) );
else
transforms.add( *new ReplaceTextTransform( rangeOfTempDeclaration , "" ) );
std::string newtext;
if (isInitializerAtomic())
{
newtext = initValue_->getOriginalText();
while (isspace(newtext[0])) newtext.erase(0,1);
while (isspace(newtext[newtext.length()-1])) newtext.erase(newtext.length()-1,1);
}
else
newtext = std::string("(") + initValue_->getOriginalText() + " )";
for ( ToolsBox::ASTNodes::const_iterator it = occurrences_.begin();
it != occurrences_.end();
++it )
{
if ( *it != localeVariableNode_)
{
SourceRange range = (*it)->getRange();
transforms.add( *new ReplaceTextTransform( range,
newtext ) );
}
}
transforms.apply( getDocument() );
}
} // namespace Refactoring
|