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 |