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 16f2eabdbda..eb6165cb785 100644 --- a/core/org.eclipse.cdt.ui.tests/resources/refactoring/ExtractMethod.rts +++ b/core/org.eclipse.cdt.ui.tests/resources/refactoring/ExtractMethod.rts @@ -2226,3 +2226,117 @@ void Test::test() RetType v = exp(); } +//!Bug 248238: Extract Method Produces Wrong Return Type Or Just Fails Classtype +//#org.eclipse.cdt.ui.tests.refactoring.extractfunction.ExtractFunctionRefactoringTest +//@.config +filename=Test.cpp +methodname=startTag +//@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" + +test::string startTag(test::string & name) +{ + return "<" + name + ">"; +} + +test::string toXML() { + test::string name; + name = "hello"; + return startTag(name) + ""; +} + +int main() { + return 0; +} + +//!Bug 248238: Extract Method Produces Wrong Return Type Or Just Fails Typedef +//#org.eclipse.cdt.ui.tests.refactoring.extractfunction.ExtractFunctionRefactoringTest +//@.config +filename=Test.cpp +methodname=startTag +//@testString.h + +namespace test{ + +class string2{ + public: + + friend string2 operator+(const string2& lhs, const string2& rhs) + { + return rhs; + } + + + string2 operator+(const string2& rhs){return rhs;} + string2(char* cp){} + string2(){}; + + }; + + typedef string2 string; +} + +//@Test.cpp +#include "testString.h" + +test::string toXML() { + test::string name; + name = "hello"; + return /*$*/"<" + name + ">"/*$$*/ + ""; +} + +int main() { + return 0; +} + +//= +#include "testString.h" + +test::string startTag(test::string & name) +{ + return "<" + name + ">"; +} + +test::string toXML() { + test::string name; + name = "hello"; + return startTag(name) + ""; +} + +int main() { + return 0; +} + 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 f264a2cb765..64aa180231b 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 @@ -15,6 +15,7 @@ import java.util.List; import org.eclipse.text.edits.TextEditGroup; +import org.eclipse.cdt.core.dom.ast.DOMException; import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression; import org.eclipse.cdt.core.dom.ast.IASTCompoundStatement; import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier; @@ -29,21 +30,25 @@ import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTBinaryExpression; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNewExpression; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTSimpleDeclSpecifier; import org.eclipse.cdt.core.dom.rewrite.ASTRewrite; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTBinaryExpression; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTFieldReference; 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.CPPASTLiteralExpression; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTName; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTNamedTypeSpecifier; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTQualifiedName; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTReturnStatement; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTSimpleDeclSpecifier; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTSimpleDeclaration; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBasicType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPClassType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPFunction; +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; @@ -121,32 +126,99 @@ public class ExtractExpression extends ExtractedFunctionConstructionHelper { case IASTBinaryExpression.op_divide: case IASTBinaryExpression.op_divideAssign: case IASTBinaryExpression.op_assign: + - /* Assume that the expression's return type is the same as the left operand's.*/ - - if(node.getOperand1() instanceof CPPASTIdExpression) { - IType expressionType = ((CPPASTIdExpression) node.getOperand1()).getExpressionType(); - - if (expressionType instanceof CPPBasicType) { - - CPPBasicType basicType = (CPPBasicType) expressionType; - return createSimpleDeclSpecifier(basicType.getType()); - - } else if (expressionType instanceof CPPTypedef) { - - CPPTypedef typedef = (CPPTypedef) expressionType; - return new CPPASTNamedTypeSpecifier((IASTName) typedef.getDefinition(), false); - - } else if (expressionType instanceof CPPClassType) { - - CPPClassType classType = (CPPClassType) expressionType; - return new CPPASTNamedTypeSpecifier((IASTName) classType.getDefinition(), false); - } - } + return getTypeFromBinaryExp(node); } return null /* not yet handled */; } + + private IASTDeclSpecifier getTypeFromBinaryExp(ICPPASTBinaryExpression node) { + if(node.getOperand1() instanceof ICPPASTBinaryExpression) { + IASTDeclSpecifier ret = getTypeFromBinaryExp(((CPPASTBinaryExpression)node.getOperand1())); + if(ret != null) return ret; + }else { + if(node.getOperand1() instanceof CPPASTIdExpression) { + return getBinaryExpressionType(((CPPASTIdExpression) node.getOperand1()).getExpressionType()); + } + } + + if(node.getOperand2() instanceof ICPPASTBinaryExpression) { + IASTDeclSpecifier ret = getTypeFromBinaryExp(((CPPASTBinaryExpression)node.getOperand2())); + if(ret != null) return ret; + }else { + if(node.getOperand2() instanceof CPPASTIdExpression) { + return getBinaryExpressionType(((CPPASTIdExpression) node.getOperand2()).getExpressionType()); + } + } + return null; + } + + private IASTDeclSpecifier getBinaryExpressionType(IType expressionType) { + if (expressionType instanceof CPPBasicType) { + + CPPBasicType basicType = (CPPBasicType) expressionType; + return createSimpleDeclSpecifier(basicType.getType()); + + } else if (expressionType instanceof CPPTypedef) { + + return getDeclSpecForType(((CPPTypedef)expressionType)); + + } else if (expressionType instanceof CPPClassType) { + + return getDeclSpecForType((CPPClassType)expressionType); + } + return null; + } + + private CPPASTNamedTypeSpecifier getDeclSpecForType(CPPClassType classType) { + + IASTName name = null; + try { + IBinding bind = classType.getOwner(); + if (bind instanceof CPPNamespace) { + ICPPASTQualifiedName qname = getQname(classType, bind); + qname.addName((IASTName) classType.getDefinition()); + name = qname; + }else { + name = (IASTName) classType.getDefinition(); + } + } catch (DOMException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + return new CPPASTNamedTypeSpecifier(name, false); + } + + private ICPPASTQualifiedName getQname(IBinding classType, IBinding bind) { + CPPNamespace namespace = (CPPNamespace) bind; + char[][] names = namespace.getFullyQualifiedNameCharArray(); + CPPASTQualifiedName qname = new CPPASTQualifiedName(); + for (char[] string : names) { + qname.addName(new CPPASTName(string)); + } + return qname; + } + + private IASTDeclSpecifier getDeclSpecForType(CPPTypedef typedef) { + IASTName name = null; + try { + IBinding bind = typedef.getOwner(); + if (bind instanceof CPPNamespace) { + ICPPASTQualifiedName qname = getQname(typedef, bind); + qname.addName((IASTName) typedef.getDefinition()); + name = qname; + }else { + name = (IASTName) typedef.getDefinition(); + } + } catch (DOMException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return new CPPASTNamedTypeSpecifier(name, false); + } private static IASTDeclSpecifier createSimpleDeclSpecifier(int type) { IASTSimpleDeclSpecifier declSpec = new CPPASTSimpleDeclSpecifier();