|
From: <sve...@us...> - 2003-04-21 16:10:30
|
Update of /cvsroot/cpptool/rfta/src/rfta
In directory sc8-pr-cvs1:/tmp/cvs-serv20797/src/rfta
Added Files:
SplitDeclarationRefactoringTest.h
SplitDeclarationRefactoringTest.cpp
SplitDeclarationRefactoring.cpp
Log Message:
initial check-in
Takes a declaration like
int *x, &y, z=5;
and splits it into
int *x;
int &y;
int z=5;
Implemented using the code model component
--- NEW FILE: SplitDeclarationRefactoringTest.h ---
// //////////////////////////////////////////////////////////////////////////
// (c)Copyright 2003, Sven Reichard.
// Created: 2003/04/18
// //////////////////////////////////////////////////////////////////////////
#ifndef RFTA_SPLITDECLARATIONREFACTORINGTEST_H
#define RFTA_SPLITDECLARATIONREFACTORINGTEST_H
#include "SourceBasedTestBase.h"
namespace Refactoring
{
class PlainTextDocument;
/// Unit tests for SplitDeclarationRefactoringTest
class SplitDeclarationRefactoringTest : public SourceBasedTestBase
{
CPPUNIT_TEST_SUITE( SplitDeclarationRefactoringTest );
CPPUNIT_TEST( testEasiestCase );
CPPUNIT_TEST( testSeveralVariables );
CPPUNIT_TEST_FAIL( testSpaceProblem );
CPPUNIT_TEST( testSeveralDeclarations );
CPPUNIT_TEST( testInitializers );
CPPUNIT_TEST_SUITE_END();
public:
/*! Constructs a SplitDeclarationRefactoringTest object.
*/
SplitDeclarationRefactoringTest();
/// Destructor.
virtual ~SplitDeclarationRefactoringTest();
void setUp();
void tearDown();
void testEasiestCase();
void testSeveralVariables();
void testSpaceProblem();
void testSeveralDeclarations();
void testInitializers();
private:
void applyRefactoring( );
boost::shared_ptr<PlainTextDocument> document_;
};
// Inlines methods for SplitDeclarationRefactoringTest:
// ----------------------------------------------
} // namespace Refactoring
#endif // RFTA_SPLITDECLARATIONREFACTORINGTEST_H
--- NEW FILE: SplitDeclarationRefactoringTest.cpp ---
// //////////////////////////////////////////////////////////////////////////
// (c)Copyright 2003, Sven Reichard.
// Created: 2003/04/18
// //////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "SplitDeclarationRefactoringTest.h"
#include <rfta/refactoring/SplitDeclarationRefactoring.h>
#include <rfta/refactoring/PlainTextDocument.h>
namespace Refactoring
{
RFTA_TEST_SUITE_REGISTRATION( SplitDeclarationRefactoringTest );
SplitDeclarationRefactoringTest::SplitDeclarationRefactoringTest()
{
}
SplitDeclarationRefactoringTest::~SplitDeclarationRefactoringTest()
{
}
void
SplitDeclarationRefactoringTest::setUp()
{
SourceBasedTestBase::setUp();
}
void
SplitDeclarationRefactoringTest::tearDown()
{
document_.reset();
SourceBasedTestBase::tearDown();
}
void
SplitDeclarationRefactoringTest::applyRefactoring( )
{
document_.reset( new PlainTextDocument( source_ ) );
int selectionIndex = builder_->getStartIndex( "selection" );
SplitDeclarationRefactoring refactoring( *document_,
selectionIndex );
refactoring.apply( );
}
void
SplitDeclarationRefactoringTest::testEasiestCase()
{
builder_->add("{\n");
builder_->addKeyingMid(" double ", "x", ", y;\n", "selection");
builder_->add("}\n");
applyRefactoring( );
std::string expectedSource(
"{\n"
" double x;\n"
" double y;\n"
"}\n" );
std::string actualSource( document_->getAllText() );
RFTA_ASSERT_EQUAL( expectedSource, actualSource );
}
void
SplitDeclarationRefactoringTest::testSeveralVariables()
{
builder_->add("{\n");
builder_->addKeyingMid(" double *", "x", ", y[3], &z;\n", "selection");
builder_->add("}\n");
applyRefactoring( );
std::string expectedSource(
"{\n"
" double *x;\n"
" double y[3];\n"
" double &z;\n"
"}\n" );
std::string actualSource( document_->getAllText() );
RFTA_ASSERT_EQUAL( expectedSource, actualSource );
}
void
SplitDeclarationRefactoringTest::testSpaceProblem()
{
builder_->add("{\n");
builder_->addKeyingMid(" double* ", "x", ", y[3], &z;\n", "selection");
builder_->add("}\n");
applyRefactoring( );
std::string expectedSource(
"{\n"
" double* x;\n"
" double y[3];\n"
" double &z;\n"
"}\n" );
std::string actualSource( document_->getAllText() );
RFTA_ASSERT_EQUAL( expectedSource, actualSource );
}
void
SplitDeclarationRefactoringTest::testSeveralDeclarations()
{
builder_->add( "{\n");
builder_->add( " double x, y;\n");
builder_->addKeyingMid(" int ", "a", ", b;\n", "selection" );
builder_->add( " bool n, m;\n");
builder_->add( "}\n" );
applyRefactoring( );
std::string expectedSource(
"{\n"
" double x, y;\n"
" int a;\n"
" int b;\n"
" bool n, m;\n"
"}\n");
std::string actualSource( document_->getAllText() );
RFTA_ASSERT_EQUAL( expectedSource, actualSource );
}
void
SplitDeclarationRefactoringTest::testInitializers()
{
builder_->add( "{\n" );
builder_->addKeyingMid( " int x=0, ", "y(2)", ";\n", "selection");
builder_->add( "}\n");
applyRefactoring( );
std::string expectedSource (
"{\n"
" int x=0;\n"
" int y(2);\n"
"}\n");
std::string actualSource( document_->getAllText() );
RFTA_ASSERT_EQUAL( expectedSource, actualSource );
}
} // namespace Refactoring
--- NEW FILE: SplitDeclarationRefactoring.cpp ---
// //////////////////////////////////////////////////////////////////////////
// Implementation file SplitDeclarationRefactoring.cpp for class SplitDeclarationRefactoring
// (c)Copyright 2002, Sven Reichard
// Created: 2002/12/05
// //////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include <rfta/refactoring/SplitDeclarationRefactoring.h>
#include "IdentifierResolver.h"
#include "IdentifierResolverContext.h"
#include "ReplaceTextTransform.h"
#include "TransformList.h"
#include <rfta/parser/MaxLODMutator.h>
#include <rfta/parser/NonSemanticBlanker.h>
#include <rfta/parser/ParseContext.h>
#include <rfta/parser/ParserError.h>
#include <rfta/parser/ParserTools.h>
#include <rfta/parser/SourceASTNode.h>
#include <rfta/parser/StatementParser.h>
#include <rfta/parser/ASTNodes.h>
#include <rfta/refactoring/RefactoringError.h>
#include <rfta/refactoring/TextDocument.h>
# include <rfta/refactoring/CodeModel.h>
# include <rfta/refactoring/CodeModelStatements.h>
# include <rfta/refactoring/CodeModelForward.h>
# include <rfta/refactoring/CodeModelExpressions.h>
# include <CodeRewriter.h>
namespace Refactoring
{
SplitDeclarationRefactoring::
SplitDeclarationRefactoring( TextDocument &document,
int declarationLocation )
: RefactoringBase( document )
, declarationLocation_( declarationLocation )
{
prepare();
}
SplitDeclarationRefactoring::~SplitDeclarationRefactoring()
{
}
void
SplitDeclarationRefactoring::prepare()
{
std::string source( getDocument().getAllText() );
if ( declarationLocation_ >= source.length() )
throw RefactoringError( RefactoringError::selectionNotInSource );
NullPPDirectiveListener nullListener;
std::string blankedSource;
NonSemanticBlanker blanker( source, blankedSource, nullListener );
blanker.blank();
int compoundStartIndex =
ToolsBox::findCompoundBefore( blankedSource, declarationLocation_ );
if ( compoundStartIndex < 0 )
throw RefactoringError( RefactoringError::temporaryNotInFunctionBody );
sourceNode_ = SourceASTNode::create( blankedSource, source );
ParseContext context( sourceNode_ );
StatementParser parser( context,
sourceNode_->getBlankedSourceStart() +
compoundStartIndex,
sourceNode_->getBlankedSourceEnd() );
parser.parse();
// don't bother with lazy parsing for now...
MaxLODMutator mutator;
mutator.mutate( sourceNode_, sourceNode_ );
}
int
SplitDeclarationRefactoring::
findIndexOfCorrectDeclaration( CodeModel::CompoundStatementPtr compound )
{
int n;
for (n = 0; n < compound->getStatementCount(); n++)
{
CodeModel::StatementPtr statement = compound->getStatementAt(n);
CodeModel::DeclarationStatement* declaration=
dynamic_cast<CodeModel::DeclarationStatement*>(&*statement);
if (!declaration)
continue;
SourceRange range = declaration->getSourceRange();
if (range.getStartIndex() > declarationLocation_)
continue;
if (range.getEndIndex() < declarationLocation_ )
continue;
break;
}
return n;
}
CodeModel::StatementPtr
SplitDeclarationRefactoring::
makeDeclarationFromFirstDeclarator
( const CodeModel::DeclaratorExpressionPtr declaratorExpression)
{
CodeModel::DeclaratorPtr firstDeclarator =
declaratorExpression->getDeclaratorAt(0);
CodeModel::TypePartPtr type = declaratorExpression->getPrimaryType();
CodeModel::DeclaratorExpressionPtr newExpression =
CodeModel::DeclaratorExpressionPtr(new CodeModel::DeclaratorExpression(type));
newExpression->appendDeclarator( firstDeclarator );
CodeModel::StatementPtr newStatement =
CodeModel::StatementPtr( new CodeModel::DeclarationStatement( newExpression));
return newStatement;
};
void
SplitDeclarationRefactoring::apply( )
{
CodeModel::Generator generator;
CodeModel::CompoundStatementPtr compound =
generator.generateCompound(sourceNode_->getChildAt(0));
int n = findIndexOfCorrectDeclaration( compound );
CodeModel::DeclarationStatement* declaration=
dynamic_cast<CodeModel::DeclarationStatement*>
(&*compound->getStatementAt(n));
CodeModel::DeclaratorExpressionPtr declaratorExpression
= declaration->getDeclaration();
while (declaratorExpression->getDeclaratorCount() > 1)
{
CodeModel::StatementPtr newStatement =
makeDeclarationFromFirstDeclarator( declaratorExpression );
compound->insertStatementAt( n++, newStatement );
declaratorExpression->removeDeclaratorAt(0);
}
std::string source( getDocument().getAllText());
CodeModel::CodeRewriter writer(source, 2);
writer.rewrite(compound, getDocument());
}
} // namespace Refactoring
|