From db3ef0bebeab3753c75c93712e9cccf511661fb2 Mon Sep 17 00:00:00 2001 From: Emanuel Graf Date: Tue, 11 Nov 2008 15:20:14 +0000 Subject: [PATCH] FIXED - bug 248622: Extract function fails to extract several expressions https://bugs.eclipse.org/bugs/show_bug.cgi?id=248622 --- .../resources/refactoring/ExtractMethod.rts | 224 ++++++++++ .../refactoring/utils/ExpressionCopyTest.java | 398 ++++++++++++++++++ .../refactoring/utils/UtilTestSuite.java | 1 + .../extractfunction/ExtractExpression.java | 19 +- .../ExtractFunctionRefactoring.java | 40 +- .../refactoring/utils/ExpressionCopier.java | 302 +++++++++++++ 6 files changed, 977 insertions(+), 7 deletions(-) create mode 100644 core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/utils/ExpressionCopyTest.java create mode 100644 core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/utils/ExpressionCopier.java diff --git a/core/org.eclipse.cdt.ui.tests/resources/refactoring/ExtractMethod.rts b/core/org.eclipse.cdt.ui.tests/resources/refactoring/ExtractMethod.rts index eb6165cb785..cbabba76867 100644 --- a/core/org.eclipse.cdt.ui.tests/resources/refactoring/ExtractMethod.rts +++ b/core/org.eclipse.cdt.ui.tests/resources/refactoring/ExtractMethod.rts @@ -2340,3 +2340,227 @@ int main() { return 0; } +//!Bug 248622: Extract function fails to extract several expressions; Selection at the end +//#org.eclipse.cdt.ui.tests.refactoring.extractfunction.ExtractFunctionRefactoringTest +//@.config +filename=Test.cpp +methodname=endTag +//@testString.h + +namespace test{ + + class string{ + public: + + friend string operator+(const string& lhs, const string& rhs) + { + return rhs; + } + + + string operator+(const string& rhs){return rhs;} + string(char* cp){} + string(){}; + + }; +} + +//@Test.cpp +#include "testString.h" + +test::string toXML() { + test::string name; + name = "hello"; + return "<" + name + ">" + /*$*/""/*$$*/; +} + +int main() { + return 0; +} + +//= +#include "testString.h" + +wchar_t endTag(test::string name) +{ + return ""; +} + +test::string toXML() { + test::string name; + name = "hello"; + return "<" + name + ">" + endTag(name); +} + +int main() { + return 0; +} + +//!Bug 248622: Extract function fails to extract several expressions; Selection in the middle +//#org.eclipse.cdt.ui.tests.refactoring.extractfunction.ExtractFunctionRefactoringTest +//@.config +filename=Test.cpp +methodname=exp +//@testString.h + +namespace test{ + + class string{ + public: + + friend string operator+(const string& lhs, const string& rhs) + { + return rhs; + } + + + string operator+(const string& rhs){return rhs;} + string(char* cp){} + string(){}; + + }; +} + +//@Test.cpp +#include "testString.h" + +test::string toXML() { + test::string name; + name = "hello"; + return "<" + name + /*$*/">" + ""; +} + +int main() { + return 0; +} + +//= +#include "testString.h" + +wchar_t exp() +{ + return ">" + ""; +} + +int main() { + return 0; +} + +//!Bug 248622: Extract function fails to extract several expressions; Selection at the end +//#org.eclipse.cdt.ui.tests.refactoring.extractfunction.ExtractFunctionRefactoringTest +//@.config +filename=Test.cpp +methodname=endTag +//@testString.h + +namespace test{ + + class string{ + public: + + friend string operator+(const string& lhs, const string& rhs) + { + return rhs; + } + + + string operator+(const string& rhs){return rhs;} + string(char* cp){} + string(){}; + + }; +} + +//@Test.cpp +#include "testString.h" + +test::string toXML() { + test::string name; + name = "hello"; + return "<" + name + ">" + /*$*/""/*$$*/; +} + +int main() { + return 0; +} + +//= +#include "testString.h" + +wchar_t endTag(test::string name) +{ + return ""; +} + +test::string toXML() { + test::string name; + name = "hello"; + return "<" + name + ">" + endTag(name); +} + +int main() { + return 0; +} + +//!Bug 248622: Extract function fails to extract several expressions; Selection in the middle +//#org.eclipse.cdt.ui.tests.refactoring.extractfunction.ExtractFunctionRefactoringTest +//@.config +filename=Test.cpp +methodname=exp +//@testString.h + +namespace test{ + + class string{ + public: + + friend string operator+(const string& lhs, const string& rhs) + { + return rhs; + } + + + string operator+(const string& rhs){return rhs;} + string(char* cp){} + string(){}; + + }; +} + +//@Test.cpp +#include "testString.h" + +test::string toXML() { + test::string name; + name = "hello"; + return "<" + name + /*$*/">" + ""; +} + +int main() { + return 0; +} + +//= +#include "testString.h" + +wchar_t exp() +{ + return ">" + ""; +} + +int main() { + return 0; +} + diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/utils/ExpressionCopyTest.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/utils/ExpressionCopyTest.java new file mode 100644 index 00000000000..c8d0bbabec9 --- /dev/null +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/utils/ExpressionCopyTest.java @@ -0,0 +1,398 @@ +/******************************************************************************* + * Copyright (c) 2008 Institute for Software, HSR Hochschule fuer Technik + * Rapperswil, University of applied sciences and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Institute for Software (IFS)- initial API and implementation + ******************************************************************************/ +package org.eclipse.cdt.ui.tests.refactoring.utils; + +import junit.framework.TestCase; + +import org.eclipse.cdt.core.dom.ast.IASTArraySubscriptExpression; +import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression; +import org.eclipse.cdt.core.dom.ast.IASTConditionalExpression; +import org.eclipse.cdt.core.dom.ast.IASTExpression; +import org.eclipse.cdt.core.dom.ast.IASTExpressionList; +import org.eclipse.cdt.core.dom.ast.IASTFieldReference; +import org.eclipse.cdt.core.dom.ast.IASTFunctionCallExpression; +import org.eclipse.cdt.core.dom.ast.IASTIdExpression; +import org.eclipse.cdt.core.dom.ast.IASTLiteralExpression; +import org.eclipse.cdt.core.dom.ast.IASTName; +import org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression; +import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeleteExpression; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFieldReference; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNewExpression; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTSimpleTypeConstructorExpression; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTypenameExpression; +import org.eclipse.cdt.core.parser.ParserLanguage; + +import org.eclipse.cdt.internal.core.dom.parser.c.CASTArraySubscriptExpression; +import org.eclipse.cdt.internal.core.dom.parser.c.CASTBinaryExpression; +import org.eclipse.cdt.internal.core.dom.parser.c.CASTConditionalExpression; +import org.eclipse.cdt.internal.core.dom.parser.c.CASTExpressionList; +import org.eclipse.cdt.internal.core.dom.parser.c.CASTFieldReference; +import org.eclipse.cdt.internal.core.dom.parser.c.CASTFunctionCallExpression; +import org.eclipse.cdt.internal.core.dom.parser.c.CASTIdExpression; +import org.eclipse.cdt.internal.core.dom.parser.c.CASTLiteralExpression; +import org.eclipse.cdt.internal.core.dom.parser.c.CASTName; +import org.eclipse.cdt.internal.core.dom.parser.c.CASTTypeIdExpression; +import org.eclipse.cdt.internal.core.dom.parser.c.CASTUnaryExpression; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTArraySubscriptExpression; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTBinaryExpression; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTConditionalExpression; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTDeleteExpression; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTIdExpression; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTLiteralExpression; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTName; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTNewExpression; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTSimpleTypeConstructorExpression; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTTypenameExpression; + +import org.eclipse.cdt.internal.ui.refactoring.utils.ExpressionCopier; + +/** + * @author Emanuel Graf IFS + * + */ +public class ExpressionCopyTest extends TestCase { + + private ExpressionCopier copier = new ExpressionCopier(); + + + /** + * Test method for {@link org.eclipse.cdt.internal.ui.refactoring.utils.ExpressionCopier#copy(org.eclipse.cdt.core.dom.ast.IASTIdExpression)}. + */ + public void testCopyIASTIdExpression() { + IASTIdExpression castIdExp = new CASTIdExpression(); + + castIdExp.setName(getTestName(ParserLanguage.C)); + IASTIdExpression copy = (IASTIdExpression) copier.createCopy(castIdExp); + assertTrue(copy instanceof CASTIdExpression); + assertEquals(castIdExp, copy); + + IASTIdExpression cppAstIdExp = new CPPASTIdExpression(getTestName(ParserLanguage.CPP)); + copy = (IASTIdExpression) copier.createCopy(cppAstIdExp); + assertTrue(copy instanceof CPPASTIdExpression); + assertEquals(cppAstIdExp, copy); + + } + + + + /** + * Test method for {@link org.eclipse.cdt.internal.ui.refactoring.utils.ExpressionCopier#copy(org.eclipse.cdt.core.dom.ast.IASTLiteralExpression)}. + */ + public void testCopyIASTLiteralExpression() { + IASTLiteralExpression litExp = getTestLiteralExp(ParserLanguage.C); + IASTLiteralExpression copy = (IASTLiteralExpression) copier.createCopy(litExp); + + assertTrue(copy instanceof CASTLiteralExpression); + assertEquals(litExp, copy); + + + litExp = getTestLiteralExp(ParserLanguage.CPP); + copy = (IASTLiteralExpression) copier.createCopy(litExp); + assertTrue(copy instanceof CPPASTLiteralExpression); + assertEquals(litExp, copy); + + } + + + /** + * Test method for {@link org.eclipse.cdt.internal.ui.refactoring.utils.ExpressionCopier#copy(IASTArraySubscriptExpression)}. + */ + public void testCopyIASTArraySubscriptExpression() { + IASTIdExpression idExp = new CASTIdExpression(getTestName(ParserLanguage.C)); + IASTLiteralExpression litExp =getTestLiteralExp(ParserLanguage.C); + + IASTArraySubscriptExpression arrSubExp = new CASTArraySubscriptExpression(idExp, litExp); + IASTArraySubscriptExpression copy = (IASTArraySubscriptExpression) copier.createCopy(arrSubExp); + assertFalse(arrSubExp == copy); + assertTrue(copy instanceof CASTArraySubscriptExpression); + assertFalse(arrSubExp.getArrayExpression() == copy.getArrayExpression()); + assertEquals(idExp, (IASTIdExpression)copy.getArrayExpression()); + assertEquals(litExp, (IASTLiteralExpression)copy.getSubscriptExpression()); + + idExp = new CPPASTIdExpression(getTestName(ParserLanguage.CPP)); + litExp = getTestLiteralExp(ParserLanguage.CPP); + arrSubExp = new CPPASTArraySubscriptExpression(idExp, litExp); + copy = (IASTArraySubscriptExpression) copier.createCopy(arrSubExp); + assertFalse(arrSubExp == copy); + assertTrue(copy instanceof CPPASTArraySubscriptExpression); + assertFalse(arrSubExp.getArrayExpression() == copy.getArrayExpression()); + assertEquals(idExp, (IASTIdExpression)copy.getArrayExpression()); + assertEquals(litExp, (IASTLiteralExpression)copy.getSubscriptExpression()); + } + + public void testCopyASTBinaryExpression() { + IASTExpression op1 = getTestLiteralExp(ParserLanguage.C); + IASTExpression op2 = getTestLiteralExp(ParserLanguage.C); + + IASTBinaryExpression binExp = new CASTBinaryExpression(IASTBinaryExpression.op_plus, op1, op2); + IASTBinaryExpression copy = (IASTBinaryExpression) copier.createCopy(binExp); + assertTrue(copy instanceof CASTBinaryExpression); + assertEquals(binExp, copy); + + op1 = getTestLiteralExp(ParserLanguage.CPP); + op2 = getTestLiteralExp(ParserLanguage.CPP); + binExp = new CPPASTBinaryExpression(IASTBinaryExpression.op_plus, op1, op2); + copy = (IASTBinaryExpression) copier.createCopy(binExp); + assertTrue(copy instanceof CPPASTBinaryExpression); + assertEquals(binExp, copy); + } + + public void testCopyCastExpression() { + IASTExpression op1 = getTestLiteralExp(ParserLanguage.C); + + //TODO + } + + public void testCopyConditionalExpression() { + IASTExpression pos = getTestLiteralExp(ParserLanguage.C); + IASTExpression neg = getTestLiteralExp(ParserLanguage.C); + IASTExpression cond = getTestLiteralExp(ParserLanguage.C); + + IASTConditionalExpression condExp = new CASTConditionalExpression(cond, pos, neg); + IASTConditionalExpression copy = (IASTConditionalExpression) copier.createCopy(condExp); + assertTrue(copy instanceof CASTConditionalExpression); + assertEquals(condExp, copy); + + pos = getTestLiteralExp(ParserLanguage.CPP); + neg = getTestLiteralExp(ParserLanguage.CPP); + cond = getTestLiteralExp(ParserLanguage.CPP); + + condExp = new CPPASTConditionalExpression(cond, pos, neg); + copy = (IASTConditionalExpression) copier.createCopy(condExp); + assertTrue(copy instanceof CPPASTConditionalExpression); + assertEquals(condExp, copy); + } + + public void testCopyExpressionList() { + IASTLiteralExpression lit1 = getTestLiteralExp(ParserLanguage.C); + IASTLiteralExpression lit2 = getTestLiteralExp(ParserLanguage.C); + + IASTExpressionList list = new CASTExpressionList(); + list.addExpression(lit1); + list.addExpression(lit2); + IASTExpressionList copy = (IASTExpressionList) copier.createCopy(list); + + assertFalse(list == copy); + IASTExpression[] orgList = list.getExpressions(); + IASTExpression[] copyList = copy.getExpressions(); + assertEquals(orgList.length, copyList.length); + for(int i = 0; i < orgList.length; ++i ) { + assertEquals((IASTLiteralExpression)orgList[i], (IASTLiteralExpression)copyList[i]); + } + } + + public void testCopyFieldExpression() { + IASTName name = getTestName(ParserLanguage.C); + IASTIdExpression id = new CASTIdExpression(); + id.setName(getTestName(ParserLanguage.C)); + + IASTFieldReference exp = new CASTFieldReference(name, id, true); + IASTFieldReference copy = (IASTFieldReference) copier.createCopy(exp); + + assertEquals(exp, copy); + } + + public void testCopyFunctionCallExpression() { + IASTIdExpression funcName = new CASTIdExpression(getTestName(ParserLanguage.C)); + IASTLiteralExpression parameter = getTestLiteralExp(ParserLanguage.C); + IASTFunctionCallExpression funcCall = new CASTFunctionCallExpression(); + funcCall.setFunctionNameExpression(funcName); + funcCall.setParameterExpression(parameter); + + IASTFunctionCallExpression copy = (IASTFunctionCallExpression) copier.createCopy(funcCall); + assertEquals(funcCall, copy); + } + + public void testCopyTypeIdExpression() { + IASTTypeIdExpression type = new CASTTypeIdExpression(); + type.setOperator(IASTTypeIdExpression.op_sizeof); + + IASTTypeIdExpression copy = (IASTTypeIdExpression) copier.createCopy(type); + assertEquals(type, copy); + } + + public void testCopyUnaryExpression() { + IASTUnaryExpression exp = new CASTUnaryExpression(); + exp.setOperand(new CASTIdExpression(getTestName(ParserLanguage.C))); + exp.setOperator(IASTUnaryExpression.op_postFixDecr); + + IASTUnaryExpression copy = (IASTUnaryExpression) copier.createCopy(exp); + + assertEquals(exp,copy); + } + + public void testCopyDeleteExp() { + ICPPASTDeleteExpression exp = new CPPASTDeleteExpression(); + exp.setIsVectored(true); + exp.setOperand(new CASTIdExpression(getTestName(ParserLanguage.CPP))); + + ICPPASTDeleteExpression copy = (ICPPASTDeleteExpression) copier.createCopy(exp); + + assertEquals(exp, copy); + + } + + public void testCopyNewExp() { + ICPPASTNewExpression exp = new CPPASTNewExpression(); + + IASTIdExpression placement = new CPPASTIdExpression(getTestName(ParserLanguage.CPP)); + IASTLiteralExpression init = getTestLiteralExp(ParserLanguage.CPP); + + exp.setNewPlacement(placement); + exp.setNewInitializer(init); + + ICPPASTNewExpression copy = (ICPPASTNewExpression) copier.createCopy(exp); + + assertEquals(exp, copy); + } + + public void testCopySimpleTypeConstructor() { + ICPPASTSimpleTypeConstructorExpression exp = new CPPASTSimpleTypeConstructorExpression(); + exp.setSimpleType(ICPPASTSimpleTypeConstructorExpression.t_int); + exp.setInitialValue(getTestLiteralExp(ParserLanguage.CPP)); + + ICPPASTSimpleTypeConstructorExpression copy = (ICPPASTSimpleTypeConstructorExpression) copier.createCopy(exp); + + assertEquals(exp, copy); + } + + public void testCopyTypeIdInitExp() { + //TODO + } + + public void testCopyTypenameExp() { + ICPPASTTypenameExpression exp = new CPPASTTypenameExpression(); + exp.setName(getTestName(ParserLanguage.CPP)); + exp.setIsTemplate(true); + exp.setInitialValue(getTestLiteralExp(ParserLanguage.CPP)); + + ICPPASTTypenameExpression copy = (ICPPASTTypenameExpression) copier.createCopy(exp); + + assertEquals(exp, copy); + } + + private void assertEquals(ICPPASTTypenameExpression exp, ICPPASTTypenameExpression copy) { + assertFalse(exp == copy); + + assertFalse(exp.getName() == copy.getName()); + assertFalse(exp.getInitialValue() == copy.getInitialValue()); + + assertEquals(exp.getName().toCharArray(), copy.getName().toCharArray()); + assertEquals(exp.isTemplate(), copy.isTemplate()); + } + + private void assertEquals(ICPPASTSimpleTypeConstructorExpression exp, ICPPASTSimpleTypeConstructorExpression copy) { + assertFalse(exp == copy); + assertEquals(exp.getSimpleType(), copy.getSimpleType()); + assertFalse(exp.getInitialValue() == copy.getInitialValue()); + assertEquals((IASTLiteralExpression)exp.getInitialValue(), (IASTLiteralExpression)copy.getInitialValue()); + } + + private void assertEquals(ICPPASTNewExpression exp, ICPPASTNewExpression copy) { + assertFalse(exp == copy); + assertEquals(exp.isGlobal(), copy.isGlobal()); + assertEquals(exp.isNewTypeId(), copy.isNewTypeId()); + + assertFalse(exp.getNewInitializer() == copy.getNewInitializer()); + assertFalse(exp.getNewPlacement() == copy.getNewPlacement()); + } + + private void assertEquals(ICPPASTDeleteExpression exp, ICPPASTDeleteExpression copy) { + assertFalse(exp == copy); + assertEquals(exp.isGlobal(), copy.isGlobal()); + assertEquals(exp.isVectored(), copy.isVectored()); + assertFalse(exp.getOperand() == copy.getOperand()); + assertEquals((IASTIdExpression)exp.getOperand(), (IASTIdExpression)copy.getOperand()); + } + + private void assertEquals(IASTUnaryExpression exp, IASTUnaryExpression copy) { + assertFalse(exp == copy); + assertEquals(exp.getOperator(), copy.getOperator()); + assertEquals((IASTIdExpression)exp.getOperand(),(IASTIdExpression)copy.getOperand()); + } + + private void assertEquals(IASTTypeIdExpression exp, IASTTypeIdExpression copy) { + assertFalse(exp == copy); + assertEquals(exp.getOperator(), copy.getOperator()); + } + + private void assertEquals(IASTFunctionCallExpression exp, IASTFunctionCallExpression copy) { + assertFalse(exp == copy); + assertFalse(exp.getFunctionNameExpression() == copy.getFunctionNameExpression()); + assertFalse(exp.getParameterExpression() == copy.getParameterExpression()); + + assertEquals((IASTIdExpression)exp.getFunctionNameExpression(), (IASTIdExpression)copy.getFunctionNameExpression()); + assertEquals((IASTLiteralExpression)exp.getParameterExpression(),(IASTLiteralExpression)copy.getParameterExpression()); + } + + private void assertEquals(IASTFieldReference exp, IASTFieldReference copy) { + assertFalse(exp == copy); + + assertEquals(exp.getFieldName().toString(), copy.getFieldName().toString()); + assertEquals((IASTIdExpression) exp.getFieldOwner(), (IASTIdExpression) copy.getFieldOwner()); + assertEquals(exp.isPointerDereference(), copy.isPointerDereference()); + if (exp instanceof ICPPASTFieldReference) { + assertEquals(((ICPPASTFieldReference)exp.getFieldOwner()).isTemplate(),((ICPPASTFieldReference)copy.getFieldOwner()).isTemplate()); + } + } + + private void assertEquals(IASTConditionalExpression condExp, IASTConditionalExpression copy) { + assertFalse(condExp == copy); + assertEquals((IASTLiteralExpression) condExp.getLogicalConditionExpression(), + (IASTLiteralExpression) copy.getLogicalConditionExpression()); + assertEquals((IASTLiteralExpression) condExp.getPositiveResultExpression(), + (IASTLiteralExpression) copy.getPositiveResultExpression()); + assertEquals((IASTLiteralExpression) condExp.getNegativeResultExpression(), + (IASTLiteralExpression) copy.getNegativeResultExpression()); + } + + private void assertEquals(IASTBinaryExpression binExp, + IASTBinaryExpression copy) { + assertFalse(binExp == copy); + assertEquals((IASTLiteralExpression)binExp.getOperand1(), (IASTLiteralExpression)copy.getOperand1()); + assertEquals((IASTLiteralExpression)binExp.getOperand2(), (IASTLiteralExpression)copy.getOperand2()); + assertEquals(binExp.getOperator(), copy.getOperator()); + } + + + private void assertEquals(IASTLiteralExpression org, + IASTLiteralExpression copy) { + assertFalse(org == copy); + assertEquals(org.getKind(), copy.getKind()); + assertEquals(org.toString(), copy.toString()); + } + + + private void assertEquals(IASTIdExpression castIdExp, IASTIdExpression copy) { + assertFalse(castIdExp == copy); + assertEquals(castIdExp.getName().toString(), copy.getName().toString()); + } + + + private IASTLiteralExpression getTestLiteralExp(ParserLanguage lang) { + if(lang.isCPP()) { + return new CPPASTLiteralExpression(IASTLiteralExpression.lk_integer_constant, new char[]{'0'}); + }else { + return new CASTLiteralExpression(IASTLiteralExpression.lk_integer_constant, new char[]{'0'}); + } + } + + private IASTName getTestName(ParserLanguage lang) { + if(lang.isCPP()) { + return new CPPASTName(new char[] {'t', 'e', 's', 't'}); + }else { + return new CASTName(new char[] {'t', 'e', 's', 't'}); + } + } + +} diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/utils/UtilTestSuite.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/utils/UtilTestSuite.java index bdeca35b3f5..950850975fe 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/utils/UtilTestSuite.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/utils/UtilTestSuite.java @@ -27,6 +27,7 @@ public class UtilTestSuite extends TestSuite { suite.addTest(IdentifierHelperTest.suite()); suite.addTest(RefactoringTester.suite("TranslationUnitHelperTest", "resources/refactoring/TranslationunitHelper.rts")); //$NON-NLS-1$ //$NON-NLS-2$ suite.addTestSuite(PseudoNameGeneratorTest.class); + suite.addTestSuite(ExpressionCopyTest.class); return suite; } } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/ExtractExpression.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/ExtractExpression.java index 225bbab8f0a..cb16948a251 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/ExtractExpression.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/ExtractExpression.java @@ -52,6 +52,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPNamespace; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTypedef; import org.eclipse.cdt.internal.ui.refactoring.NodeContainer.NameInformation; +import org.eclipse.cdt.internal.ui.refactoring.utils.ExpressionCopier; /** * Handles the extraction of expression nodes, like return type determination. @@ -60,6 +61,8 @@ import org.eclipse.cdt.internal.ui.refactoring.NodeContainer.NameInformation; * */ public class ExtractExpression extends ExtractedFunctionConstructionHelper { + + ExpressionCopier expCopier = new ExpressionCopier(); final static char[] ZERO= {'0'}; @Override @@ -71,7 +74,21 @@ public class ExtractExpression extends ExtractedFunctionConstructionHelper { statement.setReturnValue(nullReturnExp); ASTRewrite nestedRewrite = rewrite.insertBefore(compound, null, statement, group); - nestedRewrite.replace(nullReturnExp, list.get(0), group); + nestedRewrite.replace(nullReturnExp, getExpression(list), group); + + } + + private IASTExpression getExpression(List list) { + if(list.size()> 1 ) { + CPPASTBinaryExpression bExp = new CPPASTBinaryExpression(); + bExp.setParent(list.get(0).getParent()); + bExp.setOperand1(expCopier.createCopy((IASTExpression) list.get(0))); + bExp.setOperator(((IASTBinaryExpression)list.get(1).getParent()).getOperator()); + bExp.setOperand2(getExpression(list.subList(1, list.size()))); + return bExp; + }else { + return expCopier.createCopy((IASTExpression) list.get(0)); + } } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/ExtractFunctionRefactoring.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/ExtractFunctionRefactoring.java index 0cec143ee8b..46bd6d3e469 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/ExtractFunctionRefactoring.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/ExtractFunctionRefactoring.java @@ -12,6 +12,7 @@ package org.eclipse.cdt.internal.ui.refactoring.extractfunction; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.Vector; import java.util.Map.Entry; @@ -45,6 +46,7 @@ import org.eclipse.cdt.core.dom.ast.IASTFunctionDeclarator; import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition; import org.eclipse.cdt.core.dom.ast.IASTIdExpression; import org.eclipse.cdt.core.dom.ast.IASTInitializerExpression; +import org.eclipse.cdt.core.dom.ast.IASTLiteralExpression; import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration; @@ -70,6 +72,7 @@ import org.eclipse.cdt.core.dom.rewrite.ASTRewrite; import org.eclipse.cdt.ui.CUIPlugin; import org.eclipse.cdt.internal.core.dom.parser.c.CASTBinaryExpression; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTBinaryExpression; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTCompoundStatement; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTDeclarationStatement; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTDeclarator; @@ -79,6 +82,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTFunctionCallExpression import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTFunctionDefinition; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTIdExpression; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTInitializerExpression; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTLiteralExpression; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTName; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTQualifiedName; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTReturnStatement; @@ -174,11 +178,6 @@ public class ExtractFunctionRefactoring extends CRefactoring { boolean isExtractExpression = container.getNodesToWrite().get(0) instanceof IASTExpression; info.setExtractExpression(isExtractExpression); - if (isExtractExpression && container.getNodesToWrite().size() > 1) { - status - .addFatalError(Messages.ExtractFunctionRefactoring_TooManySelected); - } - info.setDeclarator(getDeclaration(container.getNodesToWrite().get(0))); MethodContext context = NodeHelper.findMethodContext(container.getNodesToWrite().get(0), getIndex()); info.setMethodContext(context); @@ -307,7 +306,7 @@ public class ExtractFunctionRefactoring extends CRefactoring { CPPASTDeclarationStatement declarationStatement = new CPPASTDeclarationStatement((IASTDeclaration) methodCall); methodCall = declarationStatement; } - rewriter.replace(firstNodeToWrite, methodCall, editGroup); + insertCallintoTree(methodCall, container.getNodesToWrite(), rewriter, editGroup); for (IASTNode node : container.getNodesToWrite()) { if (node != firstNodeToWrite) { rewriter.remove(node, editGroup); @@ -315,6 +314,35 @@ public class ExtractFunctionRefactoring extends CRefactoring { } } + private void insertCallintoTree(IASTNode methodCall, List list, + ASTRewrite rewriter, TextEditGroup editGroup) { + IASTNode firstNode = list.get(0); + if(list.size() > 1 && firstNode.getParent() instanceof IASTBinaryExpression && + firstNode.getParent().getParent() instanceof IASTBinaryExpression) { + IASTBinaryExpression parent = (IASTBinaryExpression) firstNode.getParent(); + IASTExpression leftSubTree = parent.getOperand1(); + int op = parent.getOperator(); + IASTBinaryExpression newParentNode = new CPPASTBinaryExpression(); + CPPASTLiteralExpression placeholder = new CPPASTLiteralExpression(IASTLiteralExpression.lk_integer_constant, "0"); //$NON-NLS-1$ + IASTBinaryExpression rootBinExp = getRootBinExp(parent, list); + newParentNode.setParent(rootBinExp.getParent()); + newParentNode.setOperand1(placeholder); + newParentNode.setOperator(op); + newParentNode.setOperand2((IASTExpression) methodCall); // TODO check + ASTRewrite callRewrite = rewriter.replace(rootBinExp, newParentNode, editGroup); + callRewrite.replace(placeholder, leftSubTree, editGroup); + }else { + rewriter.replace(firstNode, methodCall, editGroup); + } + } + + private IASTBinaryExpression getRootBinExp(IASTBinaryExpression binExp, List nodeList) { + while(binExp.getParent() instanceof IASTBinaryExpression && nodeList.contains(((IASTBinaryExpression) binExp.getParent()).getOperand2())) { + binExp = (IASTBinaryExpression) binExp.getParent(); + } + return binExp; + } + private void createMethodDefinition(final IASTName astMethodName, MethodContext context, IASTNode firstNode, final IFile implementationFile, ModificationCollector collector) { diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/utils/ExpressionCopier.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/utils/ExpressionCopier.java new file mode 100644 index 00000000000..7f9ec908f99 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/utils/ExpressionCopier.java @@ -0,0 +1,302 @@ +/******************************************************************************* + * Copyright (c) 2008 Institute for Software, HSR Hochschule fuer Technik + * Rapperswil, University of applied sciences and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Institute for Software (IFS)- initial API and implementation + ******************************************************************************/ +package org.eclipse.cdt.internal.ui.refactoring.utils; + +import org.eclipse.cdt.core.dom.ast.IASTArraySubscriptExpression; +import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression; +import org.eclipse.cdt.core.dom.ast.IASTCastExpression; +import org.eclipse.cdt.core.dom.ast.IASTConditionalExpression; +import org.eclipse.cdt.core.dom.ast.IASTExpression; +import org.eclipse.cdt.core.dom.ast.IASTExpressionList; +import org.eclipse.cdt.core.dom.ast.IASTFieldReference; +import org.eclipse.cdt.core.dom.ast.IASTFunctionCallExpression; +import org.eclipse.cdt.core.dom.ast.IASTIdExpression; +import org.eclipse.cdt.core.dom.ast.IASTLiteralExpression; +import org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression; +import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCastExpression; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeleteExpression; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFieldReference; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTLiteralExpression; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNewExpression; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTSimpleTypeConstructorExpression; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTypenameExpression; + +import org.eclipse.cdt.internal.core.dom.parser.c.CASTArraySubscriptExpression; +import org.eclipse.cdt.internal.core.dom.parser.c.CASTBinaryExpression; +import org.eclipse.cdt.internal.core.dom.parser.c.CASTCastExpression; +import org.eclipse.cdt.internal.core.dom.parser.c.CASTConditionalExpression; +import org.eclipse.cdt.internal.core.dom.parser.c.CASTExpressionList; +import org.eclipse.cdt.internal.core.dom.parser.c.CASTFieldReference; +import org.eclipse.cdt.internal.core.dom.parser.c.CASTFunctionCallExpression; +import org.eclipse.cdt.internal.core.dom.parser.c.CASTIdExpression; +import org.eclipse.cdt.internal.core.dom.parser.c.CASTLiteralExpression; +import org.eclipse.cdt.internal.core.dom.parser.c.CASTTypeIdExpression; +import org.eclipse.cdt.internal.core.dom.parser.c.CASTUnaryExpression; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTArraySubscriptExpression; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTBinaryExpression; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTCastExpression; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTConditionalExpression; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTDeleteExpression; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTExpressionList; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTFieldReference; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTFunctionCallExpression; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTIdExpression; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTLiteralExpression; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTName; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTNewExpression; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTSimpleTypeConstructorExpression; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTTypeIdExpression; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTTypenameExpression; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTUnaryExpression; + +/** + * + * Creates a copy of an {@link IASTExpression}. + * + * @author Emanuel Graf IFS + * + */ +public class ExpressionCopier { + + + public IASTExpression createCopy(IASTExpression exp) { + if (exp instanceof IASTLiteralExpression) { + return copy((IASTLiteralExpression) exp); + } + if(exp instanceof IASTIdExpression) { + return copy((IASTIdExpression)exp); + } + if(exp instanceof IASTArraySubscriptExpression) { + return copy((IASTArraySubscriptExpression)exp); + } + if(exp instanceof IASTBinaryExpression) { + return copy((IASTBinaryExpression)exp); + } + if(exp instanceof IASTCastExpression) { + return copy((IASTCastExpression)exp); + } + if(exp instanceof IASTConditionalExpression) { + return copy((IASTConditionalExpression)exp); + } + if(exp instanceof IASTExpressionList) { + return copy((IASTExpressionList)exp); + } + if(exp instanceof IASTFieldReference) { + return copy((IASTFieldReference)exp); + } + if(exp instanceof IASTFunctionCallExpression) { + return copy((IASTFunctionCallExpression)exp); + } + if(exp instanceof IASTTypeIdExpression) { + return copy((IASTTypeIdExpression)exp); + } + if(exp instanceof IASTUnaryExpression) { + return copy((IASTUnaryExpression)exp); + } + if(exp instanceof ICPPASTDeleteExpression) { + return copy((ICPPASTDeleteExpression)exp); + } + if(exp instanceof ICPPASTNewExpression) { + return copy((ICPPASTNewExpression)exp); + } + if(exp instanceof ICPPASTSimpleTypeConstructorExpression) { + return copy((ICPPASTSimpleTypeConstructorExpression)exp); + } + if(exp instanceof ICPPASTTypenameExpression) { + return copy((ICPPASTTypenameExpression)exp); + } + + return exp; + } + + private IASTExpression copy(ICPPASTTypenameExpression exp) { + ICPPASTTypenameExpression copy = new CPPASTTypenameExpression(); + copy.setIsTemplate(exp.isTemplate()); + copy.setName(new CPPASTName(exp.getName().toCharArray())); + copy.setInitialValue(createCopy(exp.getInitialValue())); + return copy; + } + + private IASTExpression copy(ICPPASTSimpleTypeConstructorExpression exp) { + ICPPASTSimpleTypeConstructorExpression copy = new CPPASTSimpleTypeConstructorExpression(); + copy.setSimpleType(exp.getSimpleType()); + copy.setInitialValue(createCopy(exp.getInitialValue())); + return copy; + } + + private IASTExpression copy(ICPPASTNewExpression exp) { + ICPPASTNewExpression copy = new CPPASTNewExpression(); + + copy.setIsGlobal(exp.isGlobal()); + copy.setIsNewTypeId(exp.isNewTypeId()); + copy.setNewInitializer(createCopy(exp.getNewInitializer())); + copy.setNewPlacement(createCopy(exp.getNewPlacement())); + copy.setTypeId(exp.getTypeId()); + + return copy; + } + + private IASTExpression copy(ICPPASTDeleteExpression exp) { + ICPPASTDeleteExpression copy = new CPPASTDeleteExpression(); + + copy.setIsGlobal(exp.isGlobal()); + copy.setIsVectored(exp.isVectored()); + copy.setOperand(createCopy(exp.getOperand())); + + return copy; + } + + private IASTExpression copy(IASTUnaryExpression exp) { + IASTUnaryExpression copy; + if(exp instanceof CPPASTUnaryExpression) { + copy = new CPPASTUnaryExpression(); + }else { + copy = new CASTUnaryExpression(); + } + copy.setOperator(exp.getOperator()); + copy.setOperand(createCopy(exp.getOperand())); + return copy; + } + + private IASTTypeIdExpression copy(IASTTypeIdExpression exp) { + IASTTypeIdExpression copy; + if(exp instanceof CPPASTTypeIdExpression) { + copy = new CPPASTTypeIdExpression(); + }else { + copy = new CASTTypeIdExpression(); + } + + copy.setOperator(exp.getOperator()); + copy.setTypeId(exp.getTypeId()); + return copy; + } + + private IASTExpression copy(IASTFunctionCallExpression exp) { + IASTFunctionCallExpression copy; + if(exp instanceof CPPASTFunctionCallExpression) { + copy = new CPPASTFunctionCallExpression(); + }else { + copy = new CASTFunctionCallExpression(); + } + copy.setFunctionNameExpression(createCopy(exp.getFunctionNameExpression())); + copy.setParameterExpression(createCopy(exp.getParameterExpression())); + + return copy; + } + + private IASTBinaryExpression copy(IASTBinaryExpression exp) { + IASTBinaryExpression copy; + if(exp instanceof CPPASTBinaryExpression) { + copy = new CPPASTBinaryExpression(); + }else { + copy = new CASTBinaryExpression(); + } + + copy.setOperand1(createCopy(exp.getOperand1())); + copy.setOperand2(createCopy(exp.getOperand2())); + copy.setOperator(exp.getOperator()); + + return copy; + } + + private IASTArraySubscriptExpression copy(IASTArraySubscriptExpression exp) { + IASTArraySubscriptExpression copy; + if(exp instanceof CPPASTArraySubscriptExpression) { + copy = new CPPASTArraySubscriptExpression(); + }else { + copy = new CASTArraySubscriptExpression(); + } + + copy.setArrayExpression(createCopy(exp.getArrayExpression())); + copy.setSubscriptExpression(createCopy(exp.getSubscriptExpression())); + return copy; + } + + private IASTIdExpression copy(IASTIdExpression exp) { + IASTIdExpression copy; + if (exp instanceof CPPASTIdExpression) { + copy = new CPPASTIdExpression(); + }else { + copy = new CASTIdExpression(); + } + copy.setName(exp.getName()); + return copy; + + } + + private IASTLiteralExpression copy(IASTLiteralExpression exp) { + IASTLiteralExpression copy; + if (exp instanceof ICPPASTLiteralExpression) { + copy = new CPPASTLiteralExpression(); + }else { + copy = new CASTLiteralExpression(); + } + copy.setKind(exp.getKind()); + copy.setValue(exp.toString()); + return copy; + } + + private IASTCastExpression copy(IASTCastExpression exp) { + IASTCastExpression copy; + if(exp instanceof ICPPASTCastExpression) { + copy = new CPPASTCastExpression(); + }else { + copy = new CASTCastExpression(); + } + copy.setOperator(exp.getOperator()); + copy.setOperand(createCopy(exp.getOperand())); + copy.setTypeId(exp.getTypeId()); + return copy; + } + + private IASTConditionalExpression copy(IASTConditionalExpression exp) { + IASTConditionalExpression copy; + if(exp instanceof CASTConditionalExpression) { + copy = new CASTConditionalExpression(); + }else { + copy = new CPPASTConditionalExpression(); + } + copy.setLogicalConditionExpression(createCopy(exp.getLogicalConditionExpression())); + copy.setPositiveResultExpression(createCopy(exp.getPositiveResultExpression())); + copy.setNegativeResultExpression(createCopy(exp.getNegativeResultExpression())); + return copy; + } + + private IASTExpressionList copy(IASTExpressionList exp) { + IASTExpressionList copy; + if(exp instanceof CASTExpressionList) { + copy = new CASTExpressionList(); + }else { + copy = new CPPASTExpressionList(); + } + for (IASTExpression expression : exp.getExpressions()) { + copy.addExpression(createCopy(expression)); + } + return copy; + } + + private IASTFieldReference copy(IASTFieldReference exp) { + IASTFieldReference copy; + if (exp instanceof ICPPASTFieldReference) { + copy = new CPPASTFieldReference(); + ((ICPPASTFieldReference)copy).setIsTemplate(((ICPPASTFieldReference)exp).isTemplate()); + }else { + copy = new CASTFieldReference(); + } + + copy.setFieldName(exp.getFieldName()); + copy.setFieldOwner(createCopy(exp.getFieldOwner())); + copy.setIsPointerDereference(exp.isPointerDereference()); + return copy; + } +}