diff options
Diffstat (limited to 'core')
64 files changed, 3897 insertions, 1350 deletions
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/rewrite/TypeHelper.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/rewrite/TypeHelper.java index 222d970da17..254059fb287 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/rewrite/TypeHelper.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/rewrite/TypeHelper.java @@ -10,14 +10,18 @@ *******************************************************************************/ package org.eclipse.cdt.core.dom.rewrite; +import org.eclipse.cdt.core.dom.ast.IASTDeclarator; import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; import org.eclipse.cdt.core.dom.ast.ICompositeType; import org.eclipse.cdt.core.dom.ast.IType; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTranslationUnit; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; import org.eclipse.cdt.internal.core.dom.parser.ASTTranslationUnit; import org.eclipse.cdt.internal.core.dom.parser.SizeofCalculator; import org.eclipse.cdt.internal.core.dom.parser.SizeofCalculator.SizeAndAlignment; +import org.eclipse.cdt.internal.core.dom.parser.c.CVisitor; import org.eclipse.cdt.internal.core.dom.parser.cpp.ClassTypeHelper; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil; /** @@ -59,4 +63,12 @@ public class TypeHelper { } return false; } + + public static IType createType(IASTDeclarator declarator) { + if (declarator.getTranslationUnit() instanceof ICPPASTTranslationUnit) { + return CPPVisitor.createType(declarator); + } else { + return CVisitor.createType(declarator); + } + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java index fb6a0564da6..f6c3e0b65ec 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java @@ -13,7 +13,11 @@ *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics; -import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.*; +import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.ALLCVQ; +import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.CVTYPE; +import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.TDEF; +import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.getNestedType; +import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.getUltimateTypeUptoPointers; import java.util.ArrayList; import java.util.Collections; @@ -1864,6 +1868,8 @@ public class CPPVisitor extends ASTQueries { boolean isPackExpansion= false; if (parent instanceof IASTSimpleDeclaration) { declSpec = ((IASTSimpleDeclaration) parent).getDeclSpecifier(); + } else if (parent instanceof IASTParameterDeclaration) { + declSpec = ((IASTParameterDeclaration) parent).getDeclSpecifier(); } else if (parent instanceof IASTFunctionDefinition) { declSpec = ((IASTFunctionDefinition) parent).getDeclSpecifier(); } else if (parent instanceof ICPPASTTypeId) { @@ -2506,4 +2512,21 @@ public class CPPVisitor extends ASTQueries { public static ICPPASTDeclarator findInnermostDeclarator(ICPPASTDeclarator dtor) { return (ICPPASTDeclarator) ASTQueries.findInnermostDeclarator(dtor); } + + /** + * Traverses parent chain of the given node and returns the first node of the given type. + * @param node the start node + * @param type the type to look for + * @return the node itself or its closest ancestor that has the given type, or {@code null} + * if no such node is found. + */ + @SuppressWarnings("unchecked") + public static <T extends IASTNode> T findAncestorWithType(IASTNode node, Class<T> type) { + do { + if (type.isInstance(node)) { + return (T) node; + } + } while ((node = node.getParent()) != null); + return null; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/DeclarationGeneratorImpl.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/DeclarationGeneratorImpl.java index ee4c9d86257..4718e1e11ac 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/DeclarationGeneratorImpl.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/DeclarationGeneratorImpl.java @@ -105,13 +105,13 @@ public class DeclarationGeneratorImpl extends DeclarationGenerator { returnedDeclSpec = declSpec; } else if (type instanceof ICPPTemplateInstance) { returnedDeclSpec = getDeclSpecForTemplate((ICPPTemplateInstance) type); - } else if (type instanceof IBinding) { /* ITypedef, ICompositeType... */ // BTW - we need to distinguish (and fail explicitly) on literal composites like: // struct { } aSingleInstance; returnedDeclSpec = getDeclSpecForBinding((IBinding) type); } + // TODO(sprigogin): Be honest and return null instead of void. // Fallback... if (returnedDeclSpec == null) { IASTSimpleDeclSpecifier specifier = factory.newSimpleDeclSpecifier(); @@ -129,7 +129,7 @@ public class DeclarationGeneratorImpl extends DeclarationGenerator { // Addition of pointer operators has to be in reverse order, so it's deferred until the end Map<IASTDeclarator, LinkedList<IASTPointerOperator>> pointerOperatorMap = new HashMap<IASTDeclarator, LinkedList<IASTPointerOperator>>(); - IASTName newName = (name != null) ? factory.newName(name) : factory.newName(); + IASTName newName = name != null ? factory.newName(name) : factory.newName(); // If the type is an array of something, create a declaration of a pointer to something instead // (to allow assignment, etc) @@ -311,8 +311,8 @@ public class DeclarationGeneratorImpl extends DeclarationGenerator { ICPPNodeFactory cppFactory = (ICPPNodeFactory) factory; ICPPASTTemplateId tempId = cppFactory.newTemplateId(templateName.copy()); for (ICPPTemplateArgument arg : type.getTemplateArguments()) { - IASTDeclSpecifier argDeclSpec = createDeclSpecFromType(arg.isTypeValue() ? arg - .getTypeValue() : arg.getTypeOfNonTypeValue()); + IASTDeclSpecifier argDeclSpec = createDeclSpecFromType(arg.isTypeValue() ? + arg.getTypeValue() : arg.getTypeOfNonTypeValue()); IASTTypeId typeId = cppFactory.newTypeId(argDeclSpec, null); tempId.addTemplateArgument(typeId); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/astwriter/ASTWriter.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/astwriter/ASTWriter.java index 83dd18fdf43..f9992e2c681 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/astwriter/ASTWriter.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/astwriter/ASTWriter.java @@ -39,7 +39,7 @@ import org.eclipse.cdt.internal.core.dom.rewrite.commenthandler.NodeCommentMap; * @author Emanuel Graf */ public class ASTWriter { - private ASTModificationStore modificationStore = new ASTModificationStore(); + private final ASTModificationStore modificationStore = new ASTModificationStore(); /** * Creates a <code>ASTWriter</code>. @@ -63,7 +63,7 @@ public class ASTWriter { * Generates the source code representing this node including comments. * * @param rootNode Node to write. - * @param commentMap Node Comment Map <code>ASTCommenter</code> + * @param commentMap comments for the translation unit * @return A <code>String</code> representing the source code for the node. * @throws ProblemRuntimeException if the node or one of it's children is * an <code>IASTProblemNode</code>. @@ -79,10 +79,6 @@ public class ASTWriter { return writer.toString(); } - public void setModificationStore(ASTModificationStore modificationStore) { - this.modificationStore = modificationStore; - } - /** * Returns <code>true</code> if the node should be separated by a blank line from the node * before it. diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/astwriter/ASTWriterVisitor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/astwriter/ASTWriterVisitor.java index cd1e5c363d9..ef08a0ba868 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/astwriter/ASTWriterVisitor.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/astwriter/ASTWriterVisitor.java @@ -80,6 +80,13 @@ public class ASTWriterVisitor extends ASTVisitor { shouldVisitTypeIds = true; } + /** + * Creates a writer with an empty comment map. + */ + public ASTWriterVisitor() { + this(new NodeCommentMap()); + } + public ASTWriterVisitor(NodeCommentMap commentMap) { super(); init(commentMap); diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CConventions.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CConventions.java index f88b9830d4d..462cc7f39c8 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CConventions.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CConventions.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2001, 2011 IBM Corporation and others. + * Copyright (c) 2001, 2012 IBM Corporation 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 diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/formatter/DefaultCodeFormatterConstants.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/formatter/DefaultCodeFormatterConstants.java index 711786b3bb1..ea9ac377b15 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/formatter/DefaultCodeFormatterConstants.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/formatter/DefaultCodeFormatterConstants.java @@ -15,7 +15,6 @@ package org.eclipse.cdt.core.formatter; import java.util.Map; import org.eclipse.cdt.core.CCorePlugin; -import org.eclipse.cdt.internal.formatter.DefaultCodeFormatterOptions; import org.eclipse.cdt.internal.formatter.align.Alignment; diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/DefaultCodeFormatterOptions.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/formatter/DefaultCodeFormatterOptions.java index dc1e040c11e..a62816e1ee7 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/DefaultCodeFormatterOptions.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/formatter/DefaultCodeFormatterOptions.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2011 IBM Corporation and others. + * Copyright (c) 2000, 2012 IBM Corporation 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 @@ -10,15 +10,20 @@ * Sergey Prigogin (Google) * Anton Leherbauer (Wind River Systems) *******************************************************************************/ -package org.eclipse.cdt.internal.formatter; +package org.eclipse.cdt.core.formatter; import java.util.HashMap; import java.util.Map; import org.eclipse.cdt.core.CCorePlugin; -import org.eclipse.cdt.core.formatter.DefaultCodeFormatterConstants; import org.eclipse.cdt.internal.formatter.align.Alignment; +/** + * Code formatter options. + * + * @noextend This class is not intended to be subclassed by clients. + * @since 5.4 + */ public class DefaultCodeFormatterOptions { public static final int TAB = 1; public static final int SPACE = 2; diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/CCodeFormatter.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/CCodeFormatter.java index bdc678c626a..2c891e50939 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/CCodeFormatter.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/CCodeFormatter.java @@ -21,6 +21,7 @@ import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; import org.eclipse.cdt.core.dom.ast.gnu.cpp.GPPLanguage; import org.eclipse.cdt.core.formatter.CodeFormatter; import org.eclipse.cdt.core.formatter.DefaultCodeFormatterConstants; +import org.eclipse.cdt.core.formatter.DefaultCodeFormatterOptions; import org.eclipse.cdt.core.index.IIndex; import org.eclipse.cdt.core.model.CoreModel; import org.eclipse.cdt.core.model.ILanguage; diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/CodeFormatterVisitor.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/CodeFormatterVisitor.java index cf6502358f7..30430639a17 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/CodeFormatterVisitor.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/CodeFormatterVisitor.java @@ -141,6 +141,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTWhileStatement; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier; import org.eclipse.cdt.core.dom.ast.gnu.c.ICASTKnRFunctionDeclarator; import org.eclipse.cdt.core.formatter.DefaultCodeFormatterConstants; +import org.eclipse.cdt.core.formatter.DefaultCodeFormatterOptions; import org.eclipse.cdt.core.parser.IToken; import org.eclipse.cdt.internal.formatter.align.Alignment; import org.eclipse.cdt.internal.formatter.align.AlignmentException; diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/Scribe.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/Scribe.java index 85e3ff3c7c6..ffad22adcc7 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/Scribe.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/Scribe.java @@ -18,6 +18,7 @@ import java.util.Iterator; import java.util.List; import org.eclipse.cdt.core.formatter.DefaultCodeFormatterConstants; +import org.eclipse.cdt.core.formatter.DefaultCodeFormatterOptions; import org.eclipse.cdt.internal.formatter.align.Alignment; import org.eclipse.cdt.internal.formatter.align.AlignmentException; import org.eclipse.cdt.internal.formatter.scanner.Scanner; diff --git a/core/org.eclipse.cdt.ui.tests/resources/refactoring/GenerateGettersAndSetters.rts b/core/org.eclipse.cdt.ui.tests/resources/refactoring/GenerateGettersAndSetters.rts index a270920614c..ac0dfa784c4 100644 --- a/core/org.eclipse.cdt.ui.tests/resources/refactoring/GenerateGettersAndSetters.rts +++ b/core/org.eclipse.cdt.ui.tests/resources/refactoring/GenerateGettersAndSetters.rts @@ -1502,8 +1502,8 @@ public: return mClass; } - void setClass(int _class) { - mClass = _class; + void setClass(int clazz) { + mClass = clazz; } private: diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/extractfunction/ExtractFunctionRefactoringTest.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/extractfunction/ExtractFunctionRefactoringTest.java index 9e3e46baaa9..d755f2ac8a5 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/extractfunction/ExtractFunctionRefactoringTest.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/extractfunction/ExtractFunctionRefactoringTest.java @@ -18,7 +18,7 @@ import org.eclipse.ltk.core.refactoring.Refactoring; import org.eclipse.cdt.ui.tests.refactoring.RefactoringTestBase; -import org.eclipse.cdt.internal.ui.refactoring.NodeContainer.NameInformation; +import org.eclipse.cdt.internal.ui.refactoring.NameInformation; import org.eclipse.cdt.internal.ui.refactoring.extractfunction.ExtractFunctionInformation; import org.eclipse.cdt.internal.ui.refactoring.extractfunction.ExtractFunctionRefactoring; import org.eclipse.cdt.internal.ui.refactoring.utils.VisibilityEnum; @@ -27,6 +27,7 @@ import org.eclipse.cdt.internal.ui.refactoring.utils.VisibilityEnum; * Tests for Extract Function refactoring. */ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { + private static final String NO_RETURN_VALUE = ""; private ExtractFunctionInformation refactoringInfo; private String extractedFunctionName = "extracted"; private String returnValue; @@ -59,11 +60,8 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { refactoringInfo.setReplaceDuplicates(replaceDuplicates); if (refactoringInfo.getMandatoryReturnVariable() == null) { if (returnValue != null) { - for (NameInformation nameInfo : refactoringInfo.getParameterCandidates()) { - if (returnValue.equals(String.valueOf(nameInfo.getName().getSimpleID()))) { - refactoringInfo.setReturnVariable(nameInfo); - break; - } + for (NameInformation nameInfo : refactoringInfo.getParameters()) { + nameInfo.setReturnValue(returnValue.equals(String.valueOf(nameInfo.getName().getSimpleID()))); } } } @@ -146,7 +144,7 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { //int A::help() { // return 42; //} - public void testVariableDefinedInside() throws Exception { + public void testExtractedVariableDefinition() throws Exception { assertRefactoringSuccess(); } @@ -177,7 +175,7 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { // //private: // int help(); - // void extracted(int& i); + // int extracted(int i); //}; // //#endif /*A_H_*/ @@ -211,23 +209,24 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { //A::~A() { //} // - //void A::extracted(int& i) { + //int A::extracted(int i) { // //comment // ++i; // help(); + // return i; //} // //int A::foo() { // int i = 2; // //comment - // extracted(i); + // i = extracted(i); // return i; //} // //int A::help() { // return 42; //} - public void testWithComment() throws Exception { + public void testComment() throws Exception { assertRefactoringSuccess(); } @@ -239,18 +238,19 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { // return i; //} //==================== - //void extracted(int& i) { + //int extracted(int i) { // // Comment // i = 7; + // return i; //} // //int main() { // int i; // // Comment - // extracted(i); + // i = extracted(i); // return i; //} - public void testFirstExtractedStatementWithLeadingComment() throws Exception { + public void testLeadingComment() throws Exception { assertRefactoringSuccess(); } @@ -261,16 +261,17 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { // return i; //} //==================== - //void extracted(int& i) { + //int extracted(int i) { // i = 7; // Comment + // return i; //} // //int main() { // int i; - // extracted(i); + // i = extracted(i); // return i; //} - public void testLastExtractedStatementWithTraillingComment() throws Exception { + public void testTraillingComment() throws Exception { assertRefactoringSuccess(); } @@ -312,7 +313,7 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { //int A::help() { // return 42; //} - public void testWithTwoVariableDefinedInScope() throws Exception { + public void testTwoVariableDefinedInScope() throws Exception { assertRefactoringFailure(); } @@ -404,7 +405,7 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { //}; // //#endif /*B_H_*/ - public void testWithNamedTypedField() throws Exception { + public void testNamedTypedField() throws Exception { assertRefactoringSuccess(); } @@ -496,7 +497,7 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { //}; // //#endif /*B_H_*/ - public void testWithNamedTypedVariableDefinedInScope() throws Exception { + public void testNamedTypedVariableDefinedInScope() throws Exception { assertRefactoringSuccess(); } @@ -527,7 +528,7 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { // //private: // int help(); - // void extracted(int& i); + // int extracted(int i); //}; // //#endif /*A_H_*/ @@ -565,22 +566,23 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { //A::~A() { //} // - //void A::extracted(int& i) { + //int A::extracted(int i) { // ++i; // i += ZWO; // help(); + // return i; //} // //int A::foo() { // int i = 2; - // extracted(i); + // i = extracted(i); // return i; //} // //int A::help() { // return 42; //} - public void testWithObjectStyleMacro() throws Exception { + public void testObjectStyleMacro() throws Exception { assertRefactoringSuccess(); } @@ -611,7 +613,7 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { // //private: // int help(); - // void extracted(int& i); + // int extracted(int i); //}; // //#endif /*A_H_*/ @@ -649,180 +651,23 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { //A::~A() { //} // - //void A::extracted(int& i) { + //int A::extracted(int i) { // ++i; // i = ADD(i, 42); // help(); + // return i; //} // //int A::foo() { // int i = 2; - // extracted(i); + // i = extracted(i); // return i; //} // //int A::help() { // return 42; //} - public void testWithFunctionStyleMacro() throws Exception { - assertRefactoringSuccess(); - } - - //A.h - //#ifndef A_H_ - //#define A_H_ - // - //class A { - //public: - // A(); - // virtual ~A(); - // int foo(); - // - //private: - // int help(); - //}; - // - //#endif /*A_H_*/ - //==================== - //#ifndef A_H_ - //#define A_H_ - // - //class A { - //public: - // A(); - // virtual ~A(); - // int foo(); - // - //private: - // int help(); - // void extracted(int* i); - //}; - // - //#endif /*A_H_*/ - - //A.cpp - //#include "A.h" - // - //A::A() { - //} - // - //A::~A() { - //} - // - //int A::foo() { - // int* i = new int(2); - // /*$*/++*i; - // help();/*$$*/ - // return *i; - //} - // - //int A::help() { - // return 42; - //} - //==================== - //#include "A.h" - // - //A::A() { - //} - // - //A::~A() { - //} - // - //void A::extracted(int* i) { - // ++*i; - // help(); - //} - // - //int A::foo() { - // int* i = new int(2); - // extracted(i); - // return *i; - //} - // - //int A::help() { - // return 42; - //} - public void testWithPointer() throws Exception { - assertRefactoringSuccess(); - } - - //A.h - //#ifndef A_H_ - //#define A_H_ - // - //class A { - //public: - // A(); - // virtual ~A(); - // int foo(); - // - //private: - // int help(); - //}; - // - //#endif /*A_H_*/ - //==================== - //#ifndef A_H_ - //#define A_H_ - // - //class A { - //public: - // A(); - // virtual ~A(); - // int foo(); - // - //private: - // int help(); - // void extracted(int* i); - //}; - // - //#endif /*A_H_*/ - - //A.cpp - //#include "A.h" - // - //A::A() { - //} - // - //A::~A() { - //} - // - //int A::foo() { - // int* i = new int(2); - // /*$*/++*i; - // help(); - // //A end-comment/*$$*/ - // return *i; - //} - // - //int A::help() { - // return 42; - //} - //==================== - //#include "A.h" - // - //A::A() { - //} - // - //A::~A() { - //} - // - //void A::extracted(int* i) { - // ++*i; - // help(); - //} - // - //int A::foo() { - // int* i = new int(2); - // extracted(i); - // //A end-comment - // return *i; - //} - // - //int A::help() { - // return 42; - //} - public void testWithPointerAndCommentAtTheEnd() throws Exception { + public void testFunctionStyleMacro() throws Exception { assertRefactoringSuccess(); } @@ -868,7 +713,6 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { //} // //int A::foo() { - // //A beautiful comment // int* i = new int(2); // /*$*/++*i; // help();/*$$*/ @@ -893,7 +737,6 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { //} // //int A::foo() { - // //A beautiful comment // int* i = new int(2); // extracted(i); // return *i; @@ -902,7 +745,7 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { //int A::help() { // return 42; //} - public void testWithPointerAndComment() throws Exception { + public void testPointer() throws Exception { assertRefactoringSuccess(); } @@ -933,7 +776,7 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { // //private: // int help(); - // int extracted(int i); + // void extracted(int& i); //}; // //#endif /*A_H_*/ @@ -966,23 +809,22 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { //A::~A() { //} // - //int A::extracted(int i) { + //void A::extracted(int& i) { // ++i; // help(); - // return i; //} // //int A::foo() { // int i = 2; - // i = extracted(i); + // extracted(i); // return i; //} // //int A::help() { // return 42; //} - public void testWithReturnValue() throws Exception { - returnValue = "i"; + public void testWithoutReturnValue() throws Exception { + returnValue = NO_RETURN_VALUE; assertRefactoringSuccess(); } @@ -1067,8 +909,7 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { //int A::help() { // return 42; //} - public void testWithReturnValueAndRefParameter() throws Exception { - returnValue = "i"; + public void testRefParameter() throws Exception { assertRefactoringSuccess(); } @@ -1099,7 +940,7 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { // //private: // int help(); - // int extracted(int i, B* b, int y, float x); + // int extracted(int i, int y, float x, B* b); //}; // //#endif /*A_H_*/ @@ -1138,7 +979,7 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { //A::~A() { //} // - //int A::extracted(int i, B* b, int y, float x) { + //int A::extracted(int i, int y, float x, B* b) { // ++i; // b->hello(y); // i = i + x; @@ -1151,7 +992,7 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { // float x = i; // B* b = new B(); // int y = x + i; - // i = extracted(i, b, y, x); + // i = extracted(i, y, x, b); // ++x; // return i; //} @@ -1159,8 +1000,7 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { //int A::help() { // return 42; //} - public void testWithReturnValueAndRefParameterAndSomeMoreNotUsedAfterwards() throws Exception { - returnValue = "i"; + public void testRefParameterAndSomeMoreNotUsedAfterwards() throws Exception { assertRefactoringSuccess(); } @@ -1195,7 +1035,7 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { // //private: // int help(); - // float extracted(int& i, B* b, int y, float x); + // float extracted(int& i, int y, float x, B* b); //}; // //#endif /*A_H_*/ @@ -1234,7 +1074,7 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { //A::~A() { //} // - //float A::extracted(int& i, B* b, int y, float x) { + //float A::extracted(int& i, int y, float x, B* b) { // ++i; // b->hello(y); // i = i + x; @@ -1247,7 +1087,7 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { // float x = i; // B* b = new B(); // int y = x + i; - // x = extracted(i, b, y, x); + // x = extracted(i, y, x, b); // ++x; // return i; //} @@ -1268,7 +1108,7 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { //}; // //#endif /*B_H_*/ - public void testWithReturnValueTakeTheSecondAndRefParameterAndSomeMoreNotUsedAferwards() throws Exception { + public void testExplicitlyAssignedReturnValue() throws Exception { returnValue = "x"; assertRefactoringSuccess(); } @@ -1304,7 +1144,7 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { // //private: // int help(); - // int extracted(int i, B* b, int y, float x); + // bool extracted(bool y, float x, int& i, B* b); //}; // //#endif /*A_H_*/ @@ -1322,9 +1162,10 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { // int i = 2; // float x = i; // B* b = new B(); - // int y = x + i; + // bool y = false; // /*$*/++i; // b->hello(y); + // y = !y; // i = i + x; // help();/*$$*/ // b->hello(y); @@ -1344,20 +1185,21 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { //A::~A() { //} // - //int A::extracted(int i, B* b, int y, float x) { + //bool A::extracted(bool y, float x, int& i, B* b) { // ++i; // b->hello(y); + // y = !y; // i = i + x; // help(); - // return i; + // return y; //} // //int A::foo() { // int i = 2; // float x = i; // B* b = new B(); - // int y = x + i; - // i = extracted(i, b, y, x); + // bool y = false; + // y = extracted(y, x, i, b); // b->hello(y); // ++x; // return i; @@ -1375,12 +1217,11 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { //public: // B(); // virtual ~B(); - // void hello(float y); + // void hello(bool y); //}; // //#endif /*B_H_*/ - public void testWithReturnValueAndALotRefParameter() throws Exception { - returnValue = "i"; + public void testReturnValueSelection() throws Exception { assertRefactoringSuccess(); } @@ -1415,7 +1256,7 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { // //private: // int help(); - // B* extracted(int& i, B* b, int y, float x); + // B* extracted(int& i, int y, float x, B* b); //}; // //#endif /*A_H_*/ @@ -1455,7 +1296,7 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { //A::~A() { //} // - //B* A::extracted(int& i, B* b, int y, float x) { + //B* A::extracted(int& i, int y, float x, B* b) { // ++i; // b->hello(y); // i = i + x; @@ -1468,7 +1309,7 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { // float x = i; // B* b = new B(); // int y = x + i; - // b = extracted(i, b, y, x); + // b = extracted(i, y, x, b); // b->hello(y); // ++x; // return i; @@ -1490,7 +1331,7 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { //}; // //#endif /*B_H_*/ - public void testWithReturnValueTakeTheSecondAndRefParameter() throws Exception { + public void testExplicitlyAssignedReturnValueAndOutputParameter() throws Exception { returnValue = "b"; assertRefactoringSuccess(); } @@ -1521,7 +1362,7 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { // int foo(); // //protected: - // void extracted(int& i); + // int extracted(int i); // //private: // int help(); @@ -1557,21 +1398,22 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { //A::~A() { //} // - //void A::extracted(int& i) { + //int A::extracted(int i) { // ++i; // help(); + // return i; //} // //int A::foo() { // int i = 2; - // extracted(i); + // i = extracted(i); // return i; //} // //int A::help() { // return 42; //} - public void testWithProtectedVisibility() throws Exception { + public void testProtectedVisibility() throws Exception { visibility = VisibilityEnum.v_protected; assertRefactoringSuccess(); } @@ -1600,7 +1442,7 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { // A(); // virtual ~A(); // int foo(); - // void extracted(int& i); + // int extracted(int i); // //private: // int help(); @@ -1636,21 +1478,22 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { //A::~A() { //} // - //void A::extracted(int& i) { + //int A::extracted(int i) { // ++i; // help(); + // return i; //} // //int A::foo() { // int i = 2; - // extracted(i); + // i = extracted(i); // return i; //} // //int A::help() { // return 42; //} - public void testWithPublicVisibility() throws Exception { + public void testPublicVisibility() throws Exception { visibility = VisibilityEnum.v_public; assertRefactoringSuccess(); } @@ -1682,7 +1525,7 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { // //private: // int help(); - // void extracted(int& i) const; + // int extracted(int i) const; //}; // //#endif /*A_H_*/ @@ -1715,21 +1558,22 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { //A::~A() { //} // - //void A::extracted(int& i) const { + //int A::extracted(int i) const { // ++i; // help(); + // return i; //} // //int A::foo() const { // int i = 2; - // extracted(i); + // i = extracted(i); // return i; //} // //int A::help() { // return 42; //} - public void testWithConstMethod() throws Exception { + public void testConstMethod() throws Exception { assertRefactoringSuccess(); } @@ -1762,7 +1606,7 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { // return;/*$$*/ // //unreachable //} - public void testDontExtractCodeThatContainsReturn() throws Exception { + public void testDontExtractCodeContainingReturn() throws Exception { assertRefactoringFailure(); } @@ -1773,7 +1617,7 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { // continue;/*$$*/ // } //} - public void testTestIfWeDontAllowToExtractContinue() throws Exception { + public void testDontExtractCodeContainingContinue() throws Exception { assertRefactoringFailure(); } @@ -1805,7 +1649,7 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { // int i = int(); // runTest(i); //} - public void testExtractFunctionWithAMacroCallInSelectedCodeForgetsTheMacro() throws Exception { + public void testMacroCallInSelectedCodeForgetsTheMacro() throws Exception { extractedFunctionName = "runTest"; assertRefactoringSuccess(); } @@ -1834,7 +1678,7 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { // int i = int(); // runTest(i); //} - public void testWithCommentsExtractFunctionWithAMacroCallInSelectedCodeForgetsTheMacro() throws Exception { + public void testCommentsWithMacroCallInSelectedCodeForgetsTheMacro() throws Exception { extractedFunctionName = "runTest"; assertRefactoringSuccess(); } @@ -1898,7 +1742,7 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { // int foo(int& a); // //private: - // void extracted(int& a, int b, int c); + // void extracted(int b, int c, int& a); //}; // //#endif /*A_H_*/ @@ -1927,14 +1771,14 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { //A::~A() { //} // - //void A::extracted(int& a, int b, int c) { + //void A::extracted(int b, int c, int& a) { // a = b + c; //} // //int A::foo(int& a) { // int b = 7; // int c = 8; - // extracted(a, b, c); + // extracted(b, c, a); // return a; //} public void testBug239059DoubleAmpersandInSignatureOfExtractedFunctions() throws Exception { @@ -2359,17 +2203,18 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { // return 5; //} // - //void extracted(int& a) { + //int extracted(int a) { // try { // a = myFunc(); // } catch (const int&) { // a = 3; // } + // return a; //} // //int main() { // int a = 0; - // extracted(a); + // a = extracted(a); // return a; //} public void testBug281564ExtractFunctionFailsWhenCatchingAnUnnamedException() throws Exception { @@ -2403,13 +2248,14 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { // return a; //} //==================== - //void extracted(int* a, int b) { + //int extracted(int a, int b) { // a = b * 2; + // return a; //} // //int main() { // int a, b; - // extracted(a, b); + // a = extracted(a, b); // return a; //} public void testBug288268CRefactoringCreatesCPPParameters() throws Exception { @@ -2440,7 +2286,7 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { // A(); // virtual ~A(); // int foo(); - // virtual void extracted(int& i); + // virtual int extracted(int i); // //private: // int help(); @@ -2477,23 +2323,24 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { //A::~A() { //} // - //void A::extracted(int& i) { + //int A::extracted(int i) { // //comment // ++i; // help(); + // return i; //} // //int A::foo() { // int i = 2; // //comment - // extracted(i); + // i = extracted(i); // return i; //} // //int A::help() { // return 42; //} - public void testWithVirtual() throws Exception { + public void testVirtual() throws Exception { visibility = VisibilityEnum.v_public; virtual = true; assertRefactoringSuccess(); @@ -2659,7 +2506,7 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { // //private: // int help(); - // void extracted(int& i); + // int extracted(int i); //}; // //#endif /*A_H_*/ @@ -2694,24 +2541,25 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { // //A::~A() { // int i = 2; - // extracted(i); + // i = extracted(i); //} // - //void A::extracted(int& i) { + //int A::extracted(int i) { // ++i; // help(); + // return i; //} // //int A::foo() { // int i = 2; - // extracted(i); + // i = extracted(i); // return i; //} // //int A::help() { // return 42; //} - public void testWithDuplicates() throws Exception { + public void testDuplicates() throws Exception { assertRefactoringSuccess(); } @@ -2742,7 +2590,7 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { // //private: // int help(); - // void extracted(int& i); + // int extracted(int i); //}; // //#endif /*A_H_*/ @@ -2777,17 +2625,18 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { // //A::~A() { // int oo = 99; - // extracted(oo); + // oo = extracted(oo); //} // - //void A::extracted(int& i) { + //int A::extracted(int i) { // ++i; // help(); + // return i; //} // //int A::foo() { // int i = 2; - // extracted(i); + // i = extracted(i); // return i; //} // @@ -2888,7 +2737,6 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { // return 42; //} public void testDuplicateWithField() throws Exception { - returnValue = "j"; assertRefactoringSuccess(); } @@ -2988,7 +2836,6 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { // return 42; //} public void testDuplicateWithFieldInMarkedScope() throws Exception { - returnValue = "j"; assertRefactoringSuccess(); } @@ -3084,7 +2931,6 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { // return 42; //} public void testDuplicatesWithDifferentNamesAndReturnType() throws Exception { - returnValue = "i"; assertRefactoringSuccess(); } @@ -3174,7 +3020,8 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { //int A::help() { // return 42; //} - public void testDuplicatesWithALotOfDifferentNamesAnVariableNotUsedAfterwardsInTheDuplicate() throws Exception { + public void testDuplicatesWithDifferentNamesAndOutputParameter() throws Exception { + returnValue = NO_RETURN_VALUE; assertRefactoringSuccess(); } @@ -3258,7 +3105,7 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { //int A::help() { // return 42; //} - public void testWithDuplicateNameUsedAfterwardsInDuplicateButNotInOriginalSelectionThisIsNoDuplicate() throws Exception { + public void testDuplicateNameUsedAfterwardsInDuplicateButNotInOriginalSelectionThisIsNoDuplicate() throws Exception { assertRefactoringSuccess(); } @@ -3293,7 +3140,7 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { // //private: // int help(); - // int extracted(int i, B* b, int y, float x); + // int extracted(int i, int y, float x, B* b); //}; // //#endif /*A_H_*/ @@ -3346,13 +3193,13 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { // float x = i; // B* b = new B(); // int y = x + i; - // i = extracted(i, b, y, x); + // i = extracted(i, y, x, b); // b->hello(y); // ++x; // i++; //} // - //int A::extracted(int i, B* b, int y, float x) { + //int A::extracted(int i, int y, float x, B* b) { // ++i; // b->hello(y); // i = i + x; @@ -3365,7 +3212,7 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { // float x = i; // B* b = new B(); // int y = x + i; - // i = extracted(i, b, y, x); + // i = extracted(i, y, x, b); // b->hello(y); // ++x; // return i; @@ -3387,8 +3234,7 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { //}; // //#endif /*B_H_*/ - public void testWithReturnValueAndALotRefParameterAndAMethodCall() throws Exception { - returnValue = "i"; + public void testALotRefParameterAndAMethodCall() throws Exception { assertRefactoringSuccess(); } @@ -3423,7 +3269,7 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { // //private: // int help(); - // int extracted(int i, B* b, int y, float x); + // int extracted(int i, int y, float x, B* b); //}; // //#endif /*A_H_*/ @@ -3475,13 +3321,13 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { // float x = i; // B* b = new B(); // int y = x + i; - // i = extracted(i, b, y, x); + // i = extracted(i, y, x, b); // b->hello(y); // ++x; // i++; //} // - //int A::extracted(int i, B* b, int y, float x) { + //int A::extracted(int i, int y, float x, B* b) { // ++i; // b->hello(y); // i = i + x; @@ -3494,7 +3340,7 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { // float x = i; // B* b = new B(); // int y = x + i; - // i = extracted(i, b, y, x); + // i = extracted(i, y, x, b); // b->hello(y); // return i; //} @@ -3515,8 +3361,7 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { //}; // //#endif /*B_H_*/ - public void testWithReturnValueAndALotRefParameterAndAMethodCallDuplicateIsSimilar() throws Exception { - returnValue = "i"; + public void testALotRefParameterAndAMethodCallDuplicateIsSimilar() throws Exception { assertRefactoringSuccess(); } @@ -3547,7 +3392,7 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { // //private: // int help(); - // void extracted(int& i); + // int extracted(int i); //}; // //#endif /*A_H_*/ @@ -3582,24 +3427,25 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { // //A::~A() { // int i = 2; - // extracted(i); + // i = extracted(i); //} // - //void A::extracted(int& i) { + //int A::extracted(int i) { // ++i; // help(); + // return i; //} // //int A::foo() { // int i = 2; - // extracted(i); + // i = extracted(i); // return i; //} // //int A::help() { // return 42; //} - public void testWithDuplicatesAndComments() throws Exception { + public void testDuplicatesAndComments() throws Exception { assertRefactoringSuccess(); } @@ -3630,7 +3476,7 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { // //private: // int help(); - // void extracted(int& ii); + // int extracted(int ii); //}; // //#endif /*A_H_*/ @@ -3668,22 +3514,23 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { //A::~A() { //} // - //void A::extracted(int& ii) { + //int A::extracted(int ii) { // ++ii; // ii = ADD(ii, 42); // help(); + // return ii; //} // //int A::foo() { // int ii = 2; - // extracted(ii); + // ii = extracted(ii); // return ii; //} // //int A::help() { // return 42; //} - public void testExtractFunctionRefactoringTestWithFunctionStyleMacro2() throws Exception { + public void testFunctionStyleMacro2() throws Exception { assertRefactoringSuccess(); } @@ -3862,8 +3709,7 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { //int A::help() { // return 42; //} - public void testWithMultipleMacros() throws Exception { - returnValue = "bb"; + public void testMultipleMacros() throws Exception { assertRefactoringSuccess(); } @@ -3952,7 +3798,7 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { // name="extracted" project="RegressionTestProject" selection="57,25" visibility="private"/> //</session> // - public void testExtractFunctionHistoryRefactoringTestVariableDefinedInScope() throws Exception { + public void testHistoryWithVariableDefinedInScope() throws Exception { assertRefactoringSuccess(); } @@ -3983,7 +3829,7 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { // //private: // int help(); - // void extracted(int& i); + // int extracted(int i); //}; // //#endif /*A_H_*/ @@ -4017,16 +3863,17 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { //A::~A() { //} // - //void A::extracted(int& i) { + //int A::extracted(int i) { // //comment // ++i; // help(); + // return i; //} // //int A::foo() { // int i = 2; // //comment - // extracted(i); + // i = extracted(i); // return i; //} // @@ -4042,7 +3889,7 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { // flags="4" id="org.eclipse.cdt.internal.ui.refactoring.extractfunction.ExtractFunctionRefactoring" // name="extracted" project="RegressionTestProject" selection="69,24" visibility="private"/> //</session> - public void testExtractFunctionHistoryRefactoringTest() throws Exception { + public void testHistory() throws Exception { assertRefactoringSuccess(); } @@ -4054,15 +3901,16 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { // return i; //} //==================== - //void extracted(int& i) { + //int extracted(int i) { // // Comment // i = 7; + // return i; //} // //int main() { // int i; // // Comment - // extracted(i); + // i = extracted(i); // return i; //} @@ -4074,7 +3922,7 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { // flags="4" id="org.eclipse.cdt.internal.ui.refactoring.extractfunction.ExtractFunctionRefactoring" // name="extracted" project="RegressionTestProject" selection="34,6" visibility="private"/> //</session> - public void testHistoryFirstExtractedStatementWithLeadingComment() throws Exception { + public void testHistoryWithLeadingComment() throws Exception { assertRefactoringSuccess(); } @@ -4085,13 +3933,14 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { // return i; //} //==================== - //void extracted(int& i) { + //int extracted(int i) { // i = 7; // Comment + // return i; //} // //int main() { // int i; - // extracted(i); + // i = extracted(i); // return i; //} @@ -4103,7 +3952,7 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { // flags="4" id="org.eclipse.cdt.internal.ui.refactoring.extractfunction.ExtractFunctionRefactoring" // name="extracted" project="RegressionTestProject" selection="22,6" visibility="private"/> //</session> - public void testHistoryExtractedStatementWithTrailingComment() throws Exception { + public void testHistoryWithTrailingComment() throws Exception { assertRefactoringSuccess(); } @@ -4134,7 +3983,7 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { // //private: // int help(); - // void extracted(int& i); + // int extracted(int i); //}; // //#endif /*A_H_*/ @@ -4169,17 +4018,18 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { // //A::~A() { // int oo = 99; - // extracted(oo); + // oo = extracted(oo); //} // - //void A::extracted(int& i) { + //int A::extracted(int i) { // ++i; // help(); + // return i; //} // //int A::foo() { // int i = 2; - // extracted(i); + // i = extracted(i); // return i; //} // @@ -4194,7 +4044,7 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase { // fileName="file:${projectPath}/A.cpp" flags="4" id="org.eclipse.cdt.internal.ui.refactoring.extractfunction.ExtractFunctionRefactoring" // name="extracted" project="RegressionTestProject" replaceDuplicates="true" selection="99,13" visibility="private"/> //</session> - public void testExtractFunctionRefactoringTestDuplicatesWithDifferentNamesHistoryTest() throws Exception { + public void testHistoryWithDuplicatesWithDifferentNames() throws Exception { assertRefactoringSuccess(); } } diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/utils/NameComposerTest.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/utils/NameComposerTest.java index 907c6b036de..afaec7ed7b9 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/utils/NameComposerTest.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/utils/NameComposerTest.java @@ -12,6 +12,8 @@ package org.eclipse.cdt.ui.tests.refactoring.utils; import org.eclipse.cdt.ui.PreferenceConstants; +import org.eclipse.cdt.internal.corext.codemanipulation.StubUtility; + import junit.framework.TestCase; import org.eclipse.cdt.internal.ui.util.NameComposer; @@ -46,42 +48,42 @@ public class NameComposerTest extends TestCase { } public void testTrimFieldName() { - assertEquals("f", NameComposer.trimFieldName("f_")); - assertEquals("F", NameComposer.trimFieldName("F_")); - assertEquals("oo", NameComposer.trimFieldName("F_oo")); - assertEquals("o", NameComposer.trimFieldName("f_o")); + assertEquals("f", StubUtility.trimFieldName("f_")); + assertEquals("F", StubUtility.trimFieldName("F_")); + assertEquals("oo", StubUtility.trimFieldName("F_oo")); + assertEquals("o", StubUtility.trimFieldName("f_o")); - assertEquals("M", NameComposer.trimFieldName("a_M_")); - assertEquals("bs", NameComposer.trimFieldName("a_bs_")); - assertEquals("foo_bar", NameComposer.trimFieldName("foo_bar")); - assertEquals("foo_bar", NameComposer.trimFieldName("foo_bar_")); + assertEquals("M", StubUtility.trimFieldName("a_M_")); + assertEquals("bs", StubUtility.trimFieldName("a_bs_")); + assertEquals("foo_bar", StubUtility.trimFieldName("foo_bar")); + assertEquals("foo_bar", StubUtility.trimFieldName("foo_bar_")); - assertEquals("foo_b", NameComposer.trimFieldName("foo_b_")); + assertEquals("foo_b", StubUtility.trimFieldName("foo_b_")); - assertEquals("foo", NameComposer.trimFieldName("foo")); - assertEquals("foo", NameComposer.trimFieldName("_foo")); - assertEquals("bar", NameComposer.trimFieldName("_f_bar")); + assertEquals("foo", StubUtility.trimFieldName("foo")); + assertEquals("foo", StubUtility.trimFieldName("_foo")); + assertEquals("bar", StubUtility.trimFieldName("_f_bar")); - assertEquals("f", NameComposer.trimFieldName("f__")); - assertEquals("f", NameComposer.trimFieldName("__f")); - assertEquals("O__b", NameComposer.trimFieldName("fO__b")); - assertEquals("Oo", NameComposer.trimFieldName("fOo")); - assertEquals("O", NameComposer.trimFieldName("fO")); - assertEquals("MyStatic", NameComposer.trimFieldName("sMyStatic")); - assertEquals("MyMember", NameComposer.trimFieldName("mMyMember")); + assertEquals("f", StubUtility.trimFieldName("f__")); + assertEquals("f", StubUtility.trimFieldName("__f")); + assertEquals("O__b", StubUtility.trimFieldName("fO__b")); + assertEquals("Oo", StubUtility.trimFieldName("fOo")); + assertEquals("O", StubUtility.trimFieldName("fO")); + assertEquals("MyStatic", StubUtility.trimFieldName("sMyStatic")); + assertEquals("MyMember", StubUtility.trimFieldName("mMyMember")); - assertEquals("8", NameComposer.trimFieldName("_8")); + assertEquals("8", StubUtility.trimFieldName("_8")); - assertEquals("8bar", NameComposer.trimFieldName("_8bar_")); - assertEquals("8bar_8", NameComposer.trimFieldName("_8bar_8")); - assertEquals("8bAr", NameComposer.trimFieldName("_8bAr")); - assertEquals("b8Ar", NameComposer.trimFieldName("_b8Ar")); + assertEquals("8bar", StubUtility.trimFieldName("_8bar_")); + assertEquals("8bar_8", StubUtility.trimFieldName("_8bar_8")); + assertEquals("8bAr", StubUtility.trimFieldName("_8bAr")); + assertEquals("b8Ar", StubUtility.trimFieldName("_b8Ar")); - assertEquals("Id", NameComposer.trimFieldName("Id")); - assertEquals("ID", NameComposer.trimFieldName("ID")); - assertEquals("IDS", NameComposer.trimFieldName("IDS")); - assertEquals("ID", NameComposer.trimFieldName("bID")); - assertEquals("Id", NameComposer.trimFieldName("MId")); - assertEquals("IdA", NameComposer.trimFieldName("IdA")); + assertEquals("Id", StubUtility.trimFieldName("Id")); + assertEquals("ID", StubUtility.trimFieldName("ID")); + assertEquals("IDS", StubUtility.trimFieldName("IDS")); + assertEquals("ID", StubUtility.trimFieldName("bID")); + assertEquals("Id", StubUtility.trimFieldName("MId")); + assertEquals("IdA", StubUtility.trimFieldName("IdA")); } } diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/CAutoIndentTest.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/CAutoIndentTest.java index 0d0288ebac4..ae482ea7d8b 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/CAutoIndentTest.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/CAutoIndentTest.java @@ -34,12 +34,12 @@ import org.eclipse.jface.text.TabsToSpacesConverter; import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.formatter.DefaultCodeFormatterConstants; +import org.eclipse.cdt.core.formatter.DefaultCodeFormatterOptions; import org.eclipse.cdt.ui.CUIPlugin; import org.eclipse.cdt.ui.PreferenceConstants; import org.eclipse.cdt.ui.text.ICPartitions; import org.eclipse.cdt.ui.text.doctools.DefaultMultilineCommentAutoEditStrategy; -import org.eclipse.cdt.internal.formatter.DefaultCodeFormatterOptions; import org.eclipse.cdt.internal.ui.text.CAutoIndentStrategy; import org.eclipse.cdt.internal.ui.text.CTextTools; diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/CIndenterTest.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/CIndenterTest.java index 9bf315743d8..9abe5b5291f 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/CIndenterTest.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/CIndenterTest.java @@ -22,9 +22,9 @@ import org.eclipse.jface.text.source.LineRange; import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.formatter.DefaultCodeFormatterConstants; +import org.eclipse.cdt.core.formatter.DefaultCodeFormatterOptions; import org.eclipse.cdt.ui.tests.BaseUITestCase; -import org.eclipse.cdt.internal.formatter.DefaultCodeFormatterOptions; import org.eclipse.cdt.internal.ui.editor.CDocumentSetupParticipant; import org.eclipse.cdt.internal.ui.editor.IndentUtil; diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/CodeFormatterTest.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/CodeFormatterTest.java index 08d5345b1cc..190308599d8 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/CodeFormatterTest.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/CodeFormatterTest.java @@ -27,10 +27,10 @@ import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.dom.ast.gnu.c.GCCLanguage; import org.eclipse.cdt.core.formatter.CodeFormatter; import org.eclipse.cdt.core.formatter.DefaultCodeFormatterConstants; +import org.eclipse.cdt.core.formatter.DefaultCodeFormatterOptions; import org.eclipse.cdt.ui.tests.BaseUITestCase; import org.eclipse.cdt.internal.corext.util.CodeFormatterUtil; -import org.eclipse.cdt.internal.formatter.DefaultCodeFormatterOptions; import org.eclipse.cdt.internal.formatter.align.Alignment; /** diff --git a/core/org.eclipse.cdt.ui/icons/wizban/fieldrefact_wiz.gif b/core/org.eclipse.cdt.ui/icons/wizban/fieldrefact_wiz.gif Binary files differdeleted file mode 100644 index f3e9221cca9..00000000000 --- a/core/org.eclipse.cdt.ui/icons/wizban/fieldrefact_wiz.gif +++ /dev/null diff --git a/core/org.eclipse.cdt.ui/icons/wizban/methrefact_wiz.gif b/core/org.eclipse.cdt.ui/icons/wizban/methrefact_wiz.gif Binary files differdeleted file mode 100644 index ec154e963b2..00000000000 --- a/core/org.eclipse.cdt.ui/icons/wizban/methrefact_wiz.gif +++ /dev/null diff --git a/core/org.eclipse.cdt.ui/icons/wizban/refactor_field_wiz.png b/core/org.eclipse.cdt.ui/icons/wizban/refactor_field_wiz.png Binary files differnew file mode 100644 index 00000000000..ff2dae47294 --- /dev/null +++ b/core/org.eclipse.cdt.ui/icons/wizban/refactor_field_wiz.png diff --git a/core/org.eclipse.cdt.ui/icons/wizban/refactor_method_wiz.png b/core/org.eclipse.cdt.ui/icons/wizban/refactor_method_wiz.png Binary files differnew file mode 100644 index 00000000000..1114876d871 --- /dev/null +++ b/core/org.eclipse.cdt.ui/icons/wizban/refactor_method_wiz.png diff --git a/core/org.eclipse.cdt.ui/icons/wizban/refactor_tu_wiz.png b/core/org.eclipse.cdt.ui/icons/wizban/refactor_tu_wiz.png Binary files differnew file mode 100644 index 00000000000..6cd52a58946 --- /dev/null +++ b/core/org.eclipse.cdt.ui/icons/wizban/refactor_tu_wiz.png diff --git a/core/org.eclipse.cdt.ui/icons/wizban/refactor_type_wiz.png b/core/org.eclipse.cdt.ui/icons/wizban/refactor_type_wiz.png Binary files differnew file mode 100644 index 00000000000..6cd52a58946 --- /dev/null +++ b/core/org.eclipse.cdt.ui/icons/wizban/refactor_type_wiz.png diff --git a/core/org.eclipse.cdt.ui/icons/wizban/typerefact_wiz.gif b/core/org.eclipse.cdt.ui/icons/wizban/typerefact_wiz.gif Binary files differdeleted file mode 100644 index ed3b49f2565..00000000000 --- a/core/org.eclipse.cdt.ui/icons/wizban/typerefact_wiz.gif +++ /dev/null diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/codemanipulation/StubUtility.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/codemanipulation/StubUtility.java index e11f01fabd3..e116bb286ad 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/codemanipulation/StubUtility.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/corext/codemanipulation/StubUtility.java @@ -17,6 +17,7 @@ import java.io.IOException; import java.util.ArrayList; import java.util.HashSet; import java.util.List; +import java.util.Set; import java.util.UUID; import org.eclipse.core.resources.IFile; @@ -27,6 +28,7 @@ import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.preferences.IPreferencesService; import org.eclipse.core.runtime.preferences.IScopeContext; import org.eclipse.core.runtime.preferences.InstanceScope; import org.eclipse.jface.text.BadLocationException; @@ -45,13 +47,19 @@ import org.eclipse.text.edits.InsertEdit; import org.eclipse.text.edits.MalformedTreeException; import org.eclipse.text.edits.MultiTextEdit; +import com.ibm.icu.text.BreakIterator; + +import org.eclipse.cdt.core.CConventions; import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.CCorePreferenceConstants; +import org.eclipse.cdt.core.dom.ast.gnu.cpp.GPPLanguage; +import org.eclipse.cdt.core.dom.parser.AbstractCLikeLanguage; import org.eclipse.cdt.core.model.CModelException; import org.eclipse.cdt.core.model.CoreModel; import org.eclipse.cdt.core.model.IBuffer; import org.eclipse.cdt.core.model.ICElement; import org.eclipse.cdt.core.model.ICProject; +import org.eclipse.cdt.core.model.ILanguage; import org.eclipse.cdt.core.model.ISourceRoot; import org.eclipse.cdt.core.model.ITranslationUnit; import org.eclipse.cdt.ui.CUIPlugin; @@ -64,6 +72,8 @@ import org.eclipse.cdt.internal.corext.template.c.FileTemplateContext; import org.eclipse.cdt.internal.corext.template.c.FileTemplateContextType; import org.eclipse.cdt.internal.corext.util.Strings; +import org.eclipse.cdt.internal.ui.text.CBreakIterator; +import org.eclipse.cdt.internal.ui.util.NameComposer; import org.eclipse.cdt.internal.ui.viewsupport.ProjectTemplateStore; public class StubUtility { @@ -747,4 +757,205 @@ public class StubUtility { } return result.toArray(new Template[result.size()]); } + + /** + * Returns a suggested name for a getter that is guaranteed to be a valid identifier + * and not collide with a set of given names. + * + * @param baseName the name used as an inspiration + * @param bool <code>true</code> if the getter is for a boolean field + * @param excluded the set of excluded names, can be {@code null} + * @param context the translation unit for which the code is intended, can be {@code null} + * @return the suggested name, or {@code null} if all possible names are taken + */ + public static String suggestGetterName(String baseName, boolean bool, Set<String> excluded, ITranslationUnit context) { + IPreferencesService preferences = Platform.getPreferencesService(); + int capitalization = preferences.getInt(CUIPlugin.PLUGIN_ID, + PreferenceConstants.NAME_STYLE_GETTER_CAPITALIZATION, + PreferenceConstants.NAME_STYLE_CAPITALIZATION_CAMEL_CASE, null); + String wordDelimiter = preferences.getString(CUIPlugin.PLUGIN_ID, + PreferenceConstants.NAME_STYLE_GETTER_WORD_DELIMITER, "", null); //$NON-NLS-1$ + String prefix = bool ? + preferences.getString(CUIPlugin.PLUGIN_ID, + PreferenceConstants.NAME_STYLE_GETTER_PREFIX_FOR_BOOLEAN, "is", null) : //$NON-NLS-1$ + preferences.getString(CUIPlugin.PLUGIN_ID, + PreferenceConstants.NAME_STYLE_GETTER_PREFIX, "get", null); //$NON-NLS-1$ + String suffix = preferences.getString(CUIPlugin.PLUGIN_ID, + PreferenceConstants.NAME_STYLE_GETTER_SUFFIX, "", null); //$NON-NLS-1$ + NameComposer composer = new NameComposer(capitalization, wordDelimiter, prefix, suffix); + return adjustName(composer.compose(baseName), excluded, context); + } + + /** + * Returns a suggested name for a setter that is guaranteed to be a valid identifier + * and not collide with a set of given names. + * + * @param baseName the name used as an inspiration + * @param excluded the set of excluded names, can be {@code null} + * @param context the translation unit for which the code is intended, can be {@code null} + * @return the suggested name, or {@code null} if all possible names are taken + */ + public static String suggestSetterName(String baseName, Set<String> excluded, ITranslationUnit context) { + IPreferencesService preferences = Platform.getPreferencesService(); + int capitalization = preferences.getInt(CUIPlugin.PLUGIN_ID, + PreferenceConstants.NAME_STYLE_SETTER_CAPITALIZATION, + PreferenceConstants.NAME_STYLE_CAPITALIZATION_CAMEL_CASE, null); + String wordDelimiter = preferences.getString(CUIPlugin.PLUGIN_ID, + PreferenceConstants.NAME_STYLE_SETTER_WORD_DELIMITER, "", null); //$NON-NLS-1$ + String prefix = preferences.getString(CUIPlugin.PLUGIN_ID, + PreferenceConstants.NAME_STYLE_SETTER_PREFIX, "set", null); //$NON-NLS-1$ + String suffix = preferences.getString(CUIPlugin.PLUGIN_ID, + PreferenceConstants.NAME_STYLE_SETTER_SUFFIX, "", null); //$NON-NLS-1$ + NameComposer composer = new NameComposer(capitalization, wordDelimiter, prefix, suffix); + return adjustName(composer.compose(baseName), excluded, context); + } + + /** + * Returns a suggested name for a function parameter that is guaranteed to be a valid identifier + * and not collide with a set of given names. + * + * @param baseName the name used as an inspiration + * @param excluded the set of excluded names, can be {@code null} + * @param context the translation unit for which the code is intended, can be {@code null} + * @return the suggested name, or {@code null} if all possible names are taken + */ + public static String suggestParameterName(String baseName, Set<String> excluded, ITranslationUnit context) { + IPreferencesService preferences = Platform.getPreferencesService(); + int capitalization = preferences.getInt(CUIPlugin.PLUGIN_ID, + PreferenceConstants.NAME_STYLE_VARIABLE_CAPITALIZATION, + PreferenceConstants.NAME_STYLE_CAPITALIZATION_ORIGINAL, null); + String wordDelimiter = preferences.getString(CUIPlugin.PLUGIN_ID, + PreferenceConstants.NAME_STYLE_VARIABLE_WORD_DELIMITER, "", null); //$NON-NLS-1$ + String prefix = preferences.getString(CUIPlugin.PLUGIN_ID, + PreferenceConstants.NAME_STYLE_VARIABLE_PREFIX, "", null); //$NON-NLS-1$ + String suffix = preferences.getString(CUIPlugin.PLUGIN_ID, + PreferenceConstants.NAME_STYLE_VARIABLE_SUFFIX, "", null); //$NON-NLS-1$ + NameComposer composer = new NameComposer(capitalization, wordDelimiter, prefix, suffix); + return adjustName(composer.compose(baseName), excluded, context); + } + + /** + * Returns a suggested name for a method that is guaranteed to be a valid identifier + * and not collide with a set of given names. + * + * @param baseName the name used as an inspiration + * @param excluded the set of excluded names, can be {@code null} + * @param context the translation unit for which the code is intended, can be {@code null} + * @return the suggested name, or {@code null} if all possible names are taken + */ + public static String suggestMethodName(String baseName, Set<String> excluded, ITranslationUnit context) { + IPreferencesService preferences = Platform.getPreferencesService(); + int capitalization = preferences.getInt(CUIPlugin.PLUGIN_ID, + PreferenceConstants.NAME_STYLE_METHOD_CAPITALIZATION, + PreferenceConstants.NAME_STYLE_CAPITALIZATION_ORIGINAL, null); + String wordDelimiter = preferences.getString(CUIPlugin.PLUGIN_ID, + PreferenceConstants.NAME_STYLE_METHOD_WORD_DELIMITER, "", null); //$NON-NLS-1$ + String prefix = preferences.getString(CUIPlugin.PLUGIN_ID, + PreferenceConstants.NAME_STYLE_METHOD_PREFIX, "", null); //$NON-NLS-1$ + String suffix = preferences.getString(CUIPlugin.PLUGIN_ID, + PreferenceConstants.NAME_STYLE_METHOD_SUFFIX, "", null); //$NON-NLS-1$ + NameComposer composer = new NameComposer(capitalization, wordDelimiter, prefix, suffix); + return adjustName(composer.compose(baseName), excluded, context); + } + + /** + * Checks is the given name is valid and, if not, tries to adjust it by adding a numeric suffix + * to it. + * + * @param name the name to check and, possibly, adjust + * @param namesToAvoid the set of names to avoid + * @param context the translation unit, can be {@code null} + * @return the adjusted name, or <code>null</code> if a valid name could not be generated. + */ + private static String adjustName(String name, Set<String> namesToAvoid, ITranslationUnit context) { + ILanguage language = null; + try { + if (context != null) + language = context.getLanguage(); + } catch (CoreException e) { + // Ignore + } + return adjustName(name, namesToAvoid, language); + } + + /** + * Checks is the given name is valid and, if not, tries to adjust it by adding a numeric suffix + * to it. + * + * @param name the name to check and, possibly, adjust + * @param namesToAvoid the set of names to avoid + * @param language the language of the translation unit, can be {@code null} + * @return the adjusted name, or <code>null</code> if a valid name could not be generated. + */ + private static String adjustName(String name, Set<String> namesToAvoid, ILanguage language) { + if (language == null) { + language = GPPLanguage.getDefault(); + } + String originalName = name; + if (!isValidIdentifier(name, language)) { + if ("class".equals(name)) { //$NON-NLS-1$ + name = "clazz"; //$NON-NLS-1$ + } else { + name = '_' + name; + } + } + int numTries = namesToAvoid != null ? namesToAvoid.size() + 1 : 1; + for (int i = 1; i <= numTries; i++) { + if ((namesToAvoid == null || !namesToAvoid.contains(name)) && + isValidIdentifier(name, language)) { + return name; + } + name = originalName + i; + } + return null; + } + + private static boolean isValidIdentifier(String name, ILanguage language) { + if (language instanceof AbstractCLikeLanguage) { + return CConventions.validateIdentifier(name, (AbstractCLikeLanguage) language).isOK(); + } + return true; + } + + /** + * Returns the trimmed field name. Leading and trailing non-alphanumeric characters are trimmed. + * If the first word of the name consists of a single letter and the name contains more than + * one word, the first word is removed. + * + * @param fieldName a field name to trim + * @return the trimmed field name + */ + public static String trimFieldName(String fieldName) { + CBreakIterator iterator = new CBreakIterator(); + iterator.setText(fieldName); + int firstWordStart = -1; + int firstWordEnd = -1; + int secondWordStart = -1; + int lastWordEnd = -1; + int end; + for (int start = iterator.first(); (end = iterator.next()) != BreakIterator.DONE; start = end) { + if (Character.isLetterOrDigit(fieldName.charAt(start))) { + int pos = end; + while (--pos >= start && !Character.isLetterOrDigit(fieldName.charAt(pos))) { + } + lastWordEnd = pos + 1; + if (firstWordStart < 0) { + firstWordStart = start; + firstWordEnd = lastWordEnd; + } else if (secondWordStart < 0) { + secondWordStart = start; + } + } + } + // Skip the first word if it consists of a single letter and the name contains more than + // one word. + if (firstWordStart >= 0 && firstWordStart + 1 == firstWordEnd && secondWordStart >= 0) { + firstWordStart = secondWordStart; + } + if (firstWordStart < 0) { + return fieldName; + } else { + return fieldName.substring(firstWordStart, lastWordEnd); + } + } } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CPluginImages.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CPluginImages.java index c600ac5bba7..e506fbfdd7d 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CPluginImages.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CPluginImages.java @@ -417,9 +417,10 @@ public class CPluginImages { /** @deprecated as of CDT 8.0. Use {@link CDTSharedImages#getImageDescriptor(String)}. */ @Deprecated public static final ImageDescriptor DESC_REFACTORING_INFO= createManaged ( T_OBJ, IMG_OBJS_REFACTORING_INFO); - public static final ImageDescriptor DESC_WIZBAN_REFACTOR_FIELD= createUnManaged(T_WIZBAN, "fieldrefact_wiz.gif"); //$NON-NLS-1$ - public static final ImageDescriptor DESC_WIZBAN_REFACTOR_METHOD= createUnManaged(T_WIZBAN, "methrefact_wiz.gif"); //$NON-NLS-1$ - public static final ImageDescriptor DESC_WIZBAN_REFACTOR_TYPE= createUnManaged(T_WIZBAN, "typerefact_wiz.gif"); //$NON-NLS-1$ + public static final ImageDescriptor DESC_WIZBAN_REFACTOR_TU= createUnManaged(T_WIZBAN, "refactor_tu_wiz.png"); //$NON-NLS-1$ + public static final ImageDescriptor DESC_WIZBAN_REFACTOR_FIELD= createUnManaged(T_WIZBAN, "refactor_field_wiz.png"); //$NON-NLS-1$ + public static final ImageDescriptor DESC_WIZBAN_REFACTOR_METHOD= createUnManaged(T_WIZBAN, "refactor_method_wiz.png"); //$NON-NLS-1$ + public static final ImageDescriptor DESC_WIZBAN_REFACTOR_TYPE= createUnManaged(T_WIZBAN, "refactor_type_wiz.png"); //$NON-NLS-1$ public static final ImageDescriptor DESC_OBJS_DEFAULT_CHANGE= createUnManaged(T_OBJ, "change.gif"); //$NON-NLS-1$ public static final ImageDescriptor DESC_OBJS_COMPOSITE_CHANGE= createUnManaged(T_OBJ, "composite_change.gif"); //$NON-NLS-1$ diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/ICHelpContextIds.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/ICHelpContextIds.java index c883bbb98ee..fd83696f119 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/ICHelpContextIds.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/ICHelpContextIds.java @@ -120,6 +120,7 @@ public interface ICHelpContextIds { public static final String RENAME_TYPE_WIZARD_PAGE= PREFIX + "rename_type_wizard_page_context"; //$NON-NLS-1$ public static final String RENAME_FIELD_WIZARD_PAGE= PREFIX + "rename_field_wizard_page_context"; //$NON-NLS-1$ public static final String RENAME_RESOURCE_WIZARD_PAGE= PREFIX + "rename_resource_wizard_page_context"; //$NON-NLS-1$ + public static final String EXTRACT_FUNCTION_WIZARD_PAGE= PREFIX + "extract_function_wizard_page_context"; //$NON-NLS-1$ // Dialogs public static final String EDIT_TEMPLATE_DIALOG = PREFIX + "edit_template_dialog_context"; //$NON-NLS-1$ diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dialogs/TableTextCellEditor.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dialogs/TableTextCellEditor.java new file mode 100644 index 00000000000..194996302b8 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dialogs/TableTextCellEditor.java @@ -0,0 +1,452 @@ +/******************************************************************************* + * Copyright (c) 2005, 2012 IBM Corporation 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: + * IBM Corporation - initial API and implementation + * Sergey Prigogin (Google) + *******************************************************************************/ +package org.eclipse.cdt.internal.ui.dialogs; + +import org.eclipse.core.runtime.Assert; +import org.eclipse.jface.contentassist.SubjectControlContentAssistant; +import org.eclipse.jface.viewers.CellEditor; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.osgi.util.NLS; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.FocusAdapter; +import org.eclipse.swt.events.FocusEvent; +import org.eclipse.swt.events.KeyAdapter; +import org.eclipse.swt.events.KeyEvent; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.events.MouseAdapter; +import org.eclipse.swt.events.MouseEvent; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.TraverseEvent; +import org.eclipse.swt.events.TraverseListener; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Text; + +/** + * <code>TableTextCellEditor</code> is a copy of TextCellEditor, with the + * following changes: + * + * <ul> + * <li> modify events are sent out as the text is changed, and not only after + * editing is done </li> + * + * <li>a content assistant is supported</li> + * + * <li>the user can go to the next/previous row with up and down keys</li> + * </ul> + */ +public class TableTextCellEditor extends CellEditor { + public interface IActivationListener { + public void activate(); + } + + private final TableViewer fTableViewer; + private final int fColumn; + private final String fProperty; + /** + * The editor's value on activation. This value is reset to the + * cell when the editor is left via ESC key. + */ + String fOriginalValue; + SubjectControlContentAssistant fContentAssistant; + private IActivationListener fActivationListener; + + protected Text text; + + private boolean isSelection; + private boolean isDeleteable; + private boolean isSelectable; + + private static final int defaultStyle = SWT.SINGLE; + private ModifyListener fModifyListener; + + public TableTextCellEditor(TableViewer tableViewer, int column) { + super(tableViewer.getTable(), defaultStyle); + fTableViewer= tableViewer; + fColumn= column; + fProperty= (String) tableViewer.getColumnProperties()[column]; + } + + @Override + public void activate() { + super.activate(); + if (fActivationListener != null) + fActivationListener.activate(); + fOriginalValue= text.getText(); + } + + private void fireModifyEvent(Object newValue) { + fTableViewer.getCellModifier().modify( + ((IStructuredSelection) fTableViewer.getSelection()).getFirstElement(), + fProperty, newValue); + } + + @Override + protected void focusLost() { + if (fContentAssistant != null && fContentAssistant.hasProposalPopupFocus()) { + // skip focus lost if it went to the content assist popup + } else { + super.focusLost(); + } + } + + public void setContentAssistant(SubjectControlContentAssistant assistant) { + fContentAssistant= assistant; + } + + public void setActivationListener(IActivationListener listener) { + fActivationListener= listener; + } + + public Text getText() { + return text; + } + + protected void checkDeleteable() { + boolean oldIsDeleteable = isDeleteable; + isDeleteable = isDeleteEnabled(); + if (oldIsDeleteable != isDeleteable) { + fireEnablementChanged(DELETE); + } + } + + protected void checkSelectable() { + boolean oldIsSelectable = isSelectable; + isSelectable = isSelectAllEnabled(); + if (oldIsSelectable != isSelectable) { + fireEnablementChanged(SELECT_ALL); + } + } + + protected void checkSelection() { + boolean oldIsSelection = isSelection; + isSelection = text.getSelectionCount() > 0; + if (oldIsSelection != isSelection) { + fireEnablementChanged(COPY); + fireEnablementChanged(CUT); + } + } + + private ModifyListener getModifyListener() { + if (fModifyListener == null) { + fModifyListener = new ModifyListener() { + @Override + public void modifyText(ModifyEvent e) { + editOccured(e); + } + }; + } + return fModifyListener; + } + + /* (non-Javadoc) + * Method declared on CellEditor. + */ + @Override + protected Control createControl(Composite parent) { + text= new Text(parent, getStyle()); + text.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetDefaultSelected(SelectionEvent e) { + handleDefaultSelection(e); + } + }); + text.addKeyListener(new KeyAdapter() { + @Override + public void keyPressed(KeyEvent e) { + // support switching rows while editing: + if (e.stateMask == SWT.MOD1 || e.stateMask == SWT.MOD2) { + if (e.keyCode == SWT.ARROW_UP || e.keyCode == SWT.ARROW_DOWN) { + // allow starting multi-selection even if in edit mode + deactivate(); + e.doit= false; + return; + } + } + + if (e.stateMask != SWT.NONE) + return; + + switch (e.keyCode) { + case SWT.ARROW_DOWN: + e.doit= false; + int nextRow= fTableViewer.getTable().getSelectionIndex() + 1; + if (nextRow >= fTableViewer.getTable().getItemCount()) + break; + editRow(nextRow); + break; + + case SWT.ARROW_UP: + e.doit= false; + int prevRow= fTableViewer.getTable().getSelectionIndex() - 1; + if (prevRow < 0) + break; + editRow(prevRow); + break; + + case SWT.F2: + e.doit= false; + deactivate(); + break; + } + } + + private void editRow(int row) { + fTableViewer.getTable().setSelection(row); + IStructuredSelection newSelection= (IStructuredSelection) fTableViewer.getSelection(); + if (newSelection.size() == 1) + fTableViewer.editElement(newSelection.getFirstElement(), fColumn); + } + }); + text.addKeyListener(new KeyAdapter() { + // hook key pressed - see PR 14201 + @Override + public void keyPressed(KeyEvent e) { + keyReleaseOccured(e); + + // as a result of processing the above call, clients may have + // disposed this cell editor + if ((getControl() == null) || getControl().isDisposed()) + return; + checkSelection(); // see explaination below + checkDeleteable(); + checkSelectable(); + } + }); + text.addTraverseListener(new TraverseListener() { + @Override + public void keyTraversed(TraverseEvent e) { + if (e.detail == SWT.TRAVERSE_ESCAPE + || e.detail == SWT.TRAVERSE_RETURN) { + e.doit = false; + } + } + }); + // We really want a selection listener but it is not supported so we + // use a key listener and a mouse listener to know when selection changes + // may have occurred + text.addMouseListener(new MouseAdapter() { + @Override + public void mouseUp(MouseEvent e) { + checkSelection(); + checkDeleteable(); + checkSelectable(); + } + }); + text.addFocusListener(new FocusAdapter() { + @Override + public void focusLost(FocusEvent e) { + e.display.asyncExec(new Runnable() { + @Override + public void run() { + // without the asyncExec, focus has not had a chance to go to the content assist proposals + TableTextCellEditor.this.focusLost(); + } + }); + } + }); + text.setFont(parent.getFont()); + text.setBackground(parent.getBackground()); + text.setText("");//$NON-NLS-1$ + text.addModifyListener(getModifyListener()); + + return text; + } + + @Override + protected void fireCancelEditor() { + /* bug 58540: change signature refactoring interaction: validate as you type [refactoring] */ + text.setText(fOriginalValue); + super.fireApplyEditorValue(); + } + + /** + * The <code>TextCellEditor</code> implementation of + * this <code>CellEditor</code> framework method returns + * the text string. + * + * @return the text string + */ + @Override + protected Object doGetValue() { + return text.getText(); + } + + @Override + protected void doSetFocus() { + if (text != null) { + text.selectAll(); + text.setFocus(); + checkSelection(); + checkDeleteable(); + checkSelectable(); + } + } + + /** + * The <code>TextCellEditor2</code> implementation of + * this <code>CellEditor</code> framework method accepts + * a text string (type <code>String</code>). + * + * @param value a text string (type <code>String</code>) + */ + @Override + protected void doSetValue(Object value) { + Assert.isTrue(text != null && (value instanceof String)); + text.removeModifyListener(getModifyListener()); + text.setText((String) value); + text.addModifyListener(getModifyListener()); + } + + /** + * Processes a modify event that occurred in this text cell editor. + * This framework method performs validation and sets the error message + * accordingly, and then reports a change via <code>fireEditorValueChanged</code>. + * Subclasses should call this method at appropriate times. Subclasses + * may extend or reimplement. + * + * @param e the SWT modify event + */ + protected void editOccured(ModifyEvent e) { + String value = text.getText(); + boolean oldValidState = isValueValid(); + boolean newValidState = isCorrect(value); + if (!newValidState) { + // Try to insert the current value into the error message. + setErrorMessage(NLS.bind(getErrorMessage(), value)); + } + valueChanged(oldValidState, newValidState); + fireModifyEvent(text.getText()); // update model on-the-fly + } + + @Override + public LayoutData getLayoutData() { + return new LayoutData(); + } + + protected void handleDefaultSelection(SelectionEvent event) { + // same with enter-key handling code in keyReleaseOccured(e); + fireApplyEditorValue(); + deactivate(); + } + + @Override + public boolean isCopyEnabled() { + if (text == null || text.isDisposed()) + return false; + return text.getSelectionCount() > 0; + } + + @Override + public boolean isCutEnabled() { + if (text == null || text.isDisposed()) + return false; + return text.getSelectionCount() > 0; + } + + @Override + public boolean isDeleteEnabled() { + if (text == null || text.isDisposed()) + return false; + return text.getSelectionCount() > 0 + || text.getCaretPosition() < text.getCharCount(); + } + + @Override + public boolean isPasteEnabled() { + if (text == null || text.isDisposed()) + return false; + return true; + } + + @Override + public boolean isSelectAllEnabled() { + if (text == null || text.isDisposed()) + return false; + return text.getCharCount() > 0; + } + + @Override + protected void keyReleaseOccured(KeyEvent keyEvent) { + if (keyEvent.character == '\r') { // Return key + // Enter is handled in handleDefaultSelection. + // Do not apply the editor value in response to an Enter key event + // since this can be received from the IME when the intent is -not- + // to apply the value. + // See bug 39074 [CellEditors] [DBCS] canna input mode fires bogus event from Text Control + // + // An exception is made for Ctrl+Enter for multi-line texts, since + // a default selection event is not sent in this case. + if (text != null && !text.isDisposed() && (text.getStyle() & SWT.MULTI) != 0) { + if ((keyEvent.stateMask & SWT.CTRL) != 0) { + super.keyReleaseOccured(keyEvent); + } + } + return; + } + super.keyReleaseOccured(keyEvent); + } + + @Override + public void performCopy() { + text.copy(); + } + + @Override + public void performCut() { + text.cut(); + checkSelection(); + checkDeleteable(); + checkSelectable(); + } + + @Override + public void performDelete() { + if (text.getSelectionCount() > 0) { + // remove the contents of the current selection + text.insert(""); //$NON-NLS-1$ + } else { + // remove the next character + int pos = text.getCaretPosition(); + if (pos < text.getCharCount()) { + text.setSelection(pos, pos + 1); + text.insert(""); //$NON-NLS-1$ + } + } + checkSelection(); + checkDeleteable(); + checkSelectable(); + } + + @Override + public void performPaste() { + text.paste(); + checkSelection(); + checkDeleteable(); + checkSelectable(); + } + + @Override + public void performSelectAll() { + text.selectAll(); + checkSelection(); + checkDeleteable(); + } + + @Override + protected boolean dependsOnExternalFocusListener() { + return false; + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dialogs/TextFieldNavigationHandler.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dialogs/TextFieldNavigationHandler.java new file mode 100644 index 00000000000..26ddbab5c4c --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/dialogs/TextFieldNavigationHandler.java @@ -0,0 +1,527 @@ +/******************************************************************************* + * Copyright (c) 2005, 2011 IBM Corporation 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: + * IBM Corporation - initial API and implementation + * Sergey Prigogin (Google) + *******************************************************************************/ +package org.eclipse.cdt.internal.ui.dialogs; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.core.commands.Command; +import org.eclipse.core.commands.CommandManager; +import org.eclipse.core.commands.ParameterizedCommand; +import org.eclipse.core.commands.common.NotDefinedException; +import org.eclipse.core.commands.contexts.ContextManager; +import org.eclipse.jface.bindings.BindingManager; +import org.eclipse.jface.bindings.Scheme; +import org.eclipse.jface.bindings.TriggerSequence; +import org.eclipse.jface.bindings.keys.KeySequence; +import org.eclipse.jface.bindings.keys.SWTKeySupport; +import org.eclipse.jface.util.Util; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.StyledText; +import org.eclipse.swt.events.DisposeEvent; +import org.eclipse.swt.events.DisposeListener; +import org.eclipse.swt.events.FocusEvent; +import org.eclipse.swt.events.FocusListener; +import org.eclipse.swt.events.KeyAdapter; +import org.eclipse.swt.events.KeyEvent; +import org.eclipse.swt.events.MouseAdapter; +import org.eclipse.swt.events.MouseEvent; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.widgets.Combo; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.commands.ICommandService; +import org.eclipse.ui.keys.IBindingService; +import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds; + +import com.ibm.icu.text.BreakIterator; + +import org.eclipse.cdt.ui.CUIPlugin; + +import org.eclipse.cdt.internal.ui.text.CWordIterator; + +/** + * Support for camelCase-aware sub-word navigation in dialog fields. + */ +public class TextFieldNavigationHandler { + + public static void install(Text text) { + new FocusHandler(new TextNavigable(text)); + } + + public static void install(StyledText styledText) { + new FocusHandler(new StyledTextNavigable(styledText)); + } + + public static void install(Combo combo) { + new FocusHandler(new ComboNavigable(combo)); + } + + private abstract static class WorkaroundNavigable extends Navigable { + /* workarounds for: + * - bug 103630: Add API: Combo#getCaretPosition() + * - bug 106024: Text#setSelection(int, int) does not handle start > end with SWT.SINGLE + */ + Point fLastSelection; + int fCaretPosition; + + void selectionChanged() { + Point selection= getSelection(); + if (selection.equals(fLastSelection)) { + // leave caret position + } else if (selection.x == selection.y) { //empty range + fCaretPosition= selection.x; + } else if (fLastSelection.y == selection.y) { + fCaretPosition= selection.x; //same end -> assume caret at start + } else { + fCaretPosition= selection.y; + } + fLastSelection= selection; + } + } + + private abstract static class Navigable { + public abstract Control getControl(); + + public abstract String getText(); + + public abstract void setText(String text); + + public abstract Point getSelection(); + + public abstract void setSelection(int start, int end); + + public abstract int getCaretPosition(); + } + + private static class TextNavigable extends WorkaroundNavigable { + static final boolean BUG_106024_TEXT_SELECTION= + "win32".equals(SWT.getPlatform()) //$NON-NLS-1$ + // on carbon, getCaretPosition() always returns getSelection().x + || Util.isMac(); + + private final Text fText; + + public TextNavigable(Text text) { + fText= text; + // workaround for bug 106024: + if (BUG_106024_TEXT_SELECTION) { + fLastSelection= getSelection(); + fCaretPosition= fLastSelection.y; + fText.addKeyListener(new KeyAdapter() { + @Override + public void keyReleased(KeyEvent e) { + selectionChanged(); + } + }); + fText.addMouseListener(new MouseAdapter() { + @Override + public void mouseUp(MouseEvent e) { + selectionChanged(); + } + }); + } + } + + @Override + public Control getControl() { + return fText; + } + + @Override + public String getText() { + return fText.getText(); + } + + @Override + public void setText(String text) { + fText.setText(text); + } + + @Override + public Point getSelection() { + return fText.getSelection(); + } + + @Override + public int getCaretPosition() { + if (BUG_106024_TEXT_SELECTION) { + selectionChanged(); + return fCaretPosition; + } else { + return fText.getCaretPosition(); + } + } + + @Override + public void setSelection(int start, int end) { + fText.setSelection(start, end); + } + } + + private static class StyledTextNavigable extends Navigable { + private final StyledText fStyledText; + + public StyledTextNavigable(StyledText styledText) { + fStyledText= styledText; + } + + @Override + public Control getControl() { + return fStyledText; + } + + @Override + public String getText() { + return fStyledText.getText(); + } + + @Override + public void setText(String text) { + fStyledText.setText(text); + } + + @Override + public Point getSelection() { + return fStyledText.getSelection(); + } + + @Override + public int getCaretPosition() { + return fStyledText.getCaretOffset(); + } + + @Override + public void setSelection(int start, int end) { + fStyledText.setSelection(start, end); + } + } + + private static class ComboNavigable extends WorkaroundNavigable { + private final Combo fCombo; + + public ComboNavigable(Combo combo) { + fCombo= combo; + // workaround for bug 103630: + fLastSelection= getSelection(); + fCaretPosition= fLastSelection.y; + fCombo.addKeyListener(new KeyAdapter() { + @Override + public void keyReleased(KeyEvent e) { + selectionChanged(); + } + }); + fCombo.addMouseListener(new MouseAdapter() { + @Override + public void mouseUp(MouseEvent e) { + selectionChanged(); + } + }); + } + + @Override + public Control getControl() { + return fCombo; + } + + @Override + public String getText() { + return fCombo.getText(); + } + + @Override + public void setText(String text) { + fCombo.setText(text); + } + + @Override + public Point getSelection() { + return fCombo.getSelection(); + } + + @Override + public int getCaretPosition() { + selectionChanged(); + return fCaretPosition; +// return fCombo.getCaretPosition(); // not available: bug 103630 + } + + @Override + public void setSelection(int start, int end) { + fCombo.setSelection(new Point(start, end)); + } + } + + private static class FocusHandler implements FocusListener { + private static final String EMPTY_TEXT= ""; //$NON-NLS-1$ + + private final CWordIterator fIterator; + private final Navigable fNavigable; + private KeyAdapter fKeyListener; + + private FocusHandler(Navigable navigable) { + fIterator= new CWordIterator(); + fNavigable= navigable; + + Control control= navigable.getControl(); + control.addFocusListener(this); + if (control.isFocusControl()) + activate(); + control.addDisposeListener(new DisposeListener() { + @Override + public void widgetDisposed(DisposeEvent e) { + deactivate(); + } + }); + } + + @Override + public void focusGained(FocusEvent e) { + activate(); + } + + @Override + public void focusLost(FocusEvent e) { + deactivate(); + } + + private void activate() { + fNavigable.getControl().addKeyListener(getKeyListener()); + } + + private void deactivate() { + if (fKeyListener != null) { + Control control= fNavigable.getControl(); + if (! control.isDisposed()) + control.removeKeyListener(fKeyListener); + fKeyListener= null; + } + } + + private KeyAdapter getKeyListener() { + if (fKeyListener == null) { + fKeyListener= new KeyAdapter() { + private final boolean IS_WORKAROUND= (fNavigable instanceof ComboNavigable) + || (fNavigable instanceof TextNavigable && TextNavigable.BUG_106024_TEXT_SELECTION); + private List<Submission> fSubmissions; + + @Override + public void keyPressed(KeyEvent e) { + if (IS_WORKAROUND) { + if (e.keyCode == SWT.ARROW_LEFT && e.stateMask == SWT.MOD2) { + int caretPosition= fNavigable.getCaretPosition(); + if (caretPosition != 0) { + Point selection= fNavigable.getSelection(); + if (caretPosition == selection.x) + fNavigable.setSelection(selection.y, caretPosition - 1); + else + fNavigable.setSelection(selection.x, caretPosition - 1); + } + e.doit= false; + return; + + } else if (e.keyCode == SWT.ARROW_RIGHT && e.stateMask == SWT.MOD2) { + String text= fNavigable.getText(); + int caretPosition= fNavigable.getCaretPosition(); + if (caretPosition != text.length()) { + Point selection= fNavigable.getSelection(); + if (caretPosition == selection.y) + fNavigable.setSelection(selection.x, caretPosition + 1); + else + fNavigable.setSelection(selection.y, caretPosition + 1); + } + e.doit= false; + return; + } + } + int accelerator = SWTKeySupport.convertEventToUnmodifiedAccelerator(e); + KeySequence keySequence = KeySequence.getInstance(SWTKeySupport.convertAcceleratorToKeyStroke(accelerator)); + for (Submission submission : getSubmissions()) { + TriggerSequence[] triggerSequences= submission.getTriggerSequences(); + for (int i= 0; i < triggerSequences.length; i++) { + if (triggerSequences[i].equals(keySequence)) { // XXX does not work for multi-stroke bindings + e.doit= false; + submission.execute(); + return; + } + } + } + } + + private List<Submission> getSubmissions() { + if (fSubmissions != null) + return fSubmissions; + + fSubmissions= new ArrayList<Submission>(); + + ICommandService commandService= (ICommandService) PlatformUI.getWorkbench().getAdapter(ICommandService.class); + IBindingService bindingService= (IBindingService) PlatformUI.getWorkbench().getAdapter(IBindingService.class); + if (commandService == null || bindingService == null) + return fSubmissions; + + // Workaround for https://bugs.eclipse.org/bugs/show_bug.cgi?id=184502 , + // similar to CodeAssistAdvancedConfigurationBlock.getKeyboardShortcut(..): + BindingManager localBindingManager= new BindingManager(new ContextManager(), new CommandManager()); + final Scheme[] definedSchemes= bindingService.getDefinedSchemes(); + if (definedSchemes != null) { + try { + for (int i = 0; i < definedSchemes.length; i++) { + Scheme scheme= definedSchemes[i]; + Scheme localSchemeCopy= localBindingManager.getScheme(scheme.getId()); + localSchemeCopy.define(scheme.getName(), scheme.getDescription(), scheme.getParentId()); + } + } catch (final NotDefinedException e) { + CUIPlugin.log(e); + } + } + localBindingManager.setLocale(bindingService.getLocale()); + localBindingManager.setPlatform(bindingService.getPlatform()); + + localBindingManager.setBindings(bindingService.getBindings()); + try { + Scheme activeScheme= bindingService.getActiveScheme(); + if (activeScheme != null) + localBindingManager.setActiveScheme(activeScheme); + } catch (NotDefinedException e) { + CUIPlugin.log(e); + } + + fSubmissions.add(new Submission(getKeyBindings(localBindingManager, commandService, ITextEditorActionDefinitionIds.SELECT_WORD_NEXT)) { + @Override + public void execute() { + fIterator.setText(fNavigable.getText()); + int caretPosition= fNavigable.getCaretPosition(); + int newCaret= fIterator.following(caretPosition); + if (newCaret != BreakIterator.DONE) { + Point selection= fNavigable.getSelection(); + if (caretPosition == selection.y) + fNavigable.setSelection(selection.x, newCaret); + else + fNavigable.setSelection(selection.y, newCaret); + } + fIterator.setText(EMPTY_TEXT); + } + }); + fSubmissions.add(new Submission(getKeyBindings(localBindingManager, commandService, ITextEditorActionDefinitionIds.SELECT_WORD_PREVIOUS)) { + @Override + public void execute() { + fIterator.setText(fNavigable.getText()); + int caretPosition= fNavigable.getCaretPosition(); + int newCaret= fIterator.preceding(caretPosition); + if (newCaret != BreakIterator.DONE) { + Point selection= fNavigable.getSelection(); + if (caretPosition == selection.x) + fNavigable.setSelection(selection.y, newCaret); + else + fNavigable.setSelection(selection.x, newCaret); + } + fIterator.setText(EMPTY_TEXT); + } + }); + fSubmissions.add(new Submission(getKeyBindings(localBindingManager, commandService, ITextEditorActionDefinitionIds.WORD_NEXT)) { + @Override + public void execute() { + fIterator.setText(fNavigable.getText()); + int caretPosition= fNavigable.getCaretPosition(); + int newCaret= fIterator.following(caretPosition); + if (newCaret != BreakIterator.DONE) + fNavigable.setSelection(newCaret, newCaret); + fIterator.setText(EMPTY_TEXT); + } + }); + fSubmissions.add(new Submission(getKeyBindings(localBindingManager, commandService, ITextEditorActionDefinitionIds.WORD_PREVIOUS)) { + @Override + public void execute() { + fIterator.setText(fNavigable.getText()); + int caretPosition= fNavigable.getCaretPosition(); + int newCaret= fIterator.preceding(caretPosition); + if (newCaret != BreakIterator.DONE) + fNavigable.setSelection(newCaret, newCaret); + fIterator.setText(EMPTY_TEXT); + } + }); + fSubmissions.add(new Submission(getKeyBindings(localBindingManager, commandService, ITextEditorActionDefinitionIds.DELETE_NEXT_WORD)) { + @Override + public void execute() { + Point selection= fNavigable.getSelection(); + String text= fNavigable.getText(); + int start; + int end; + if (selection.x != selection.y) { + start= selection.x; + end= selection.y; + } else { + fIterator.setText(text); + start= fNavigable.getCaretPosition(); + end= fIterator.following(start); + fIterator.setText(EMPTY_TEXT); + if (end == BreakIterator.DONE) + return; + } + fNavigable.setText(text.substring(0, start) + text.substring(end)); + fNavigable.setSelection(start, start); + } + }); + fSubmissions.add(new Submission(getKeyBindings(localBindingManager, commandService, ITextEditorActionDefinitionIds.DELETE_PREVIOUS_WORD)) { + @Override + public void execute() { + Point selection= fNavigable.getSelection(); + String text= fNavigable.getText(); + int start; + int end; + if (selection.x != selection.y) { + start= selection.x; + end= selection.y; + } else { + fIterator.setText(text); + end= fNavigable.getCaretPosition(); + start= fIterator.preceding(end); + fIterator.setText(EMPTY_TEXT); + if (start == BreakIterator.DONE) + return; + } + fNavigable.setText(text.substring(0, start) + text.substring(end)); + fNavigable.setSelection(start, start); + } + }); + + return fSubmissions; + } + + private TriggerSequence[] getKeyBindings(BindingManager localBindingManager, ICommandService commandService, String commandID) { + Command command= commandService.getCommand(commandID); + ParameterizedCommand pCmd= new ParameterizedCommand(command, null); + return localBindingManager.getActiveBindingsDisregardingContextFor(pCmd); + } + + }; + } + return fKeyListener; + } + } + + private abstract static class Submission { + private TriggerSequence[] fTriggerSequences; + + public Submission(TriggerSequence[] triggerSequences) { + fTriggerSequences= triggerSequences; + } + + public TriggerSequence[] getTriggerSequences() { + return fTriggerSequences; + } + + public abstract void execute(); + } + +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CSourceViewer.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CSourceViewer.java index 022816a5f6c..956df220a00 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CSourceViewer.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CSourceViewer.java @@ -7,7 +7,7 @@ * * Contributors: * QNX Software Systems - initial API and implementation - * Sergey Prigogin, Google + * Sergey Prigogin (Google) * Anton Leherbauer (Wind River Systems) * Markus Schorn (Wind River Systems) *******************************************************************************/ @@ -43,19 +43,23 @@ import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.RGB; import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.texteditor.AbstractDecoratedTextEditorPreferenceConstants; import org.eclipse.ui.texteditor.AbstractTextEditor; +import org.eclipse.cdt.ui.CUIPlugin; import org.eclipse.cdt.ui.PreferenceConstants; import org.eclipse.cdt.ui.text.CSourceViewerConfiguration; +import org.eclipse.cdt.ui.text.ICColorConstants; +import org.eclipse.cdt.ui.text.IColorManager; +import org.eclipse.cdt.internal.ui.text.CTextTools; /** * Source viewer for C/C++ et al. */ public class CSourceViewer extends ProjectionViewer implements IPropertyChangeListener { - /** Show outline operation id. */ public static final int SHOW_OUTLINE= 101; /** Show type hierarchy operation id. */ @@ -620,4 +624,32 @@ public class CSourceViewer extends ProjectionViewer implements IPropertyChangeLi cmd.event= null; cmd.text= null; } + + /** + * Sets the viewer's background color to the given control's background color. + * The background color is <em>only</em> set if it's visibly distinct from the + * default Java source text color. + * + * @param control the control with the default background color + */ + public void adaptBackgroundColor(Control control) { + // Workaround for dark editor background color, see https://bugs.eclipse.org/330680 + Color defaultColor= control.getBackground(); + float[] defaultBgHSB= defaultColor.getRGB().getHSB(); + + CTextTools textTools= CUIPlugin.getDefault().getTextTools(); + IColorManager manager= textTools.getColorManager(); + Color cDefaultColor= manager.getColor(ICColorConstants.C_DEFAULT); + RGB cDefaultRGB= cDefaultColor != null ? + cDefaultColor.getRGB() : new RGB(255, 255, 255); + float[] javaDefaultHSB= cDefaultRGB.getHSB(); + + if (Math.abs(defaultBgHSB[2] - javaDefaultHSB[2]) >= 0.5f) { + getTextWidget().setBackground(defaultColor); + if (fBackgroundColor != null) { + fBackgroundColor.dispose(); + fBackgroundColor= null; + } + } + } } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/NameStyleBlock.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/NameStyleBlock.java index f8356f1405a..6ef9c311a3a 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/NameStyleBlock.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/NameStyleBlock.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2011 Google, Inc and others. + * Copyright (c) 2011, 2012 Google, Inc 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 @@ -34,6 +34,8 @@ import org.eclipse.ui.preferences.IWorkbenchPreferenceContainer; import org.eclipse.cdt.ui.PreferenceConstants; import org.eclipse.cdt.utils.ui.controls.ControlFactory; +import org.eclipse.cdt.internal.corext.codemanipulation.StubUtility; + import org.eclipse.cdt.internal.ui.dialogs.IStatusChangeListener; import org.eclipse.cdt.internal.ui.dialogs.StatusInfo; import org.eclipse.cdt.internal.ui.util.NameComposer; @@ -51,6 +53,7 @@ public class NameStyleBlock extends OptionsConfigurationBlock { private static final String EXAMPLE_CONSTANT_NAME = "MY_CONSTANT"; //$NON-NLS-1$ private static final String EXAMPLE_VARIABLE_NAME = "myVariable"; //$NON-NLS-1$ private static final String EXAMPLE_FIELD_NAME = "myField"; //$NON-NLS-1$ + private static final String EXAMPLE_METHOD_NAME = "myMethod"; //$NON-NLS-1$ private static final String EXAMPLE_CLASS_NAME = "MyClass"; //$NON-NLS-1$ private final String[] CAPITALIZATION_VALUES = { @@ -81,6 +84,10 @@ public class NameStyleBlock extends OptionsConfigurationBlock { private static final Key KEY_FIELD_WORD_DELIMITER = getCDTUIKey(PreferenceConstants.NAME_STYLE_FIELD_WORD_DELIMITER); private static final Key KEY_FIELD_PREFIX = getCDTUIKey(PreferenceConstants.NAME_STYLE_FIELD_PREFIX); private static final Key KEY_FIELD_SUFFIX = getCDTUIKey(PreferenceConstants.NAME_STYLE_FIELD_SUFFIX); + private static final Key KEY_METHOD_CAPITALIZATION = getCDTUIKey(PreferenceConstants.NAME_STYLE_METHOD_CAPITALIZATION); + private static final Key KEY_METHOD_WORD_DELIMITER = getCDTUIKey(PreferenceConstants.NAME_STYLE_METHOD_WORD_DELIMITER); + private static final Key KEY_METHOD_PREFIX = getCDTUIKey(PreferenceConstants.NAME_STYLE_METHOD_PREFIX); + private static final Key KEY_METHOD_SUFFIX = getCDTUIKey(PreferenceConstants.NAME_STYLE_METHOD_SUFFIX); private static final Key KEY_GETTER_CAPITALIZATION = getCDTUIKey(PreferenceConstants.NAME_STYLE_GETTER_CAPITALIZATION); private static final Key KEY_GETTER_WORD_DELIMITER = getCDTUIKey(PreferenceConstants.NAME_STYLE_GETTER_WORD_DELIMITER); private static final Key KEY_GETTER_PREFIX = getCDTUIKey(PreferenceConstants.NAME_STYLE_GETTER_PREFIX); @@ -120,6 +127,10 @@ public class NameStyleBlock extends OptionsConfigurationBlock { KEY_FIELD_WORD_DELIMITER, KEY_FIELD_PREFIX, KEY_FIELD_SUFFIX, + KEY_METHOD_CAPITALIZATION, + KEY_METHOD_WORD_DELIMITER, + KEY_METHOD_PREFIX, + KEY_METHOD_SUFFIX, KEY_GETTER_CAPITALIZATION, KEY_GETTER_WORD_DELIMITER, KEY_GETTER_PREFIX, @@ -182,6 +193,14 @@ public class NameStyleBlock extends OptionsConfigurationBlock { .setPrefixKey(KEY_FIELD_PREFIX) .setSuffixKey(KEY_FIELD_SUFFIX) .setNameValidator(IDENTIFIER_VALIDATOR); + new Category(PreferencesMessages.NameStyleBlock_method_node, + PreferencesMessages.NameStyleBlock_method_node_description, EXAMPLE_METHOD_NAME, + codeCategory) + .setCapitalizationKey(KEY_METHOD_CAPITALIZATION) + .setWordDelimiterKey(KEY_METHOD_WORD_DELIMITER) + .setPrefixKey(KEY_METHOD_PREFIX) + .setSuffixKey(KEY_METHOD_SUFFIX) + .setNameValidator(IDENTIFIER_VALIDATOR); new Category(PreferencesMessages.NameStyleBlock_getter_node, PreferencesMessages.NameStyleBlock_getter_node_description, EXAMPLE_FIELD_NAME, codeCategory) @@ -572,7 +591,7 @@ public class NameStyleBlock extends OptionsConfigurationBlock { String name = seedNameGenerator != null ? seedNameGenerator.composeExampleName(settings) : seedName; if (trimFieldName) { - name = NameComposer.trimFieldName(name); + name = StubUtility.trimFieldName(name); } return composer.compose(name); } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/PreferencesMessages.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/PreferencesMessages.java index a4d76943d35..97fa545a614 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/PreferencesMessages.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/PreferencesMessages.java @@ -367,6 +367,8 @@ public final class PreferencesMessages extends NLS { public static String NameStyleBlock_variable_node_description; public static String NameStyleBlock_field_node; public static String NameStyleBlock_field_node_description; + public static String NameStyleBlock_method_node; + public static String NameStyleBlock_method_node_description; public static String NameStyleBlock_getter_node; public static String NameStyleBlock_getter_node_description; public static String NameStyleBlock_setter_node; diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/PreferencesMessages.properties b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/PreferencesMessages.properties index aa5574d29d8..b7cf751fbfe 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/PreferencesMessages.properties +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/PreferencesMessages.properties @@ -420,8 +420,10 @@ NameStyleBlock_constant_node=Constant NameStyleBlock_constant_node_description=Constant name NameStyleBlock_variable_node=Variable NameStyleBlock_variable_node_description=Variable name -NameStyleBlock_field_node=Class field +NameStyleBlock_field_node=Class Field NameStyleBlock_field_node_description=Class field name +NameStyleBlock_method_node=Class Method +NameStyleBlock_method_node_description=Class method name NameStyleBlock_getter_node=Getter Method NameStyleBlock_getter_node_description=Getter name based on the field name NameStyleBlock_setter_node=Setter Method diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/CRefactoring.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/CRefactoring.java index eac0efc7cbb..98a5f5a1656 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/CRefactoring.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/CRefactoring.java @@ -66,6 +66,7 @@ public abstract class CRefactoring extends Refactoring { protected String name = Messages.Refactoring_name; protected IFile file; + protected final ITranslationUnit tu; protected Region region; protected RefactoringStatus initStatus; protected IASTTranslationUnit ast; @@ -76,11 +77,10 @@ public abstract class CRefactoring extends Refactoring { project = proj; if (element instanceof ISourceReference) { ISourceReference sourceRef= (ISourceReference) element; - ITranslationUnit tu = sourceRef.getTranslationUnit(); + this.tu = sourceRef.getTranslationUnit(); IResource res= tu.getResource(); if (res instanceof IFile) this.file= (IFile) res; - try { final ISourceRange sourceRange = sourceRef.getSourceRange(); this.region = new Region(sourceRange.getIdStartPos(), sourceRange.getIdLength()); @@ -89,6 +89,7 @@ public abstract class CRefactoring extends Refactoring { } } else { this.file = file; + this.tu = (ITranslationUnit) CCorePlugin.getDefault().getCoreModel().create(file); this.region = SelectionHelper.getRegion(selection); } @@ -235,10 +236,10 @@ public abstract class CRefactoring extends Refactoring { protected boolean loadTranslationUnit(RefactoringStatus status, IProgressMonitor mon) { SubMonitor subMonitor = SubMonitor.convert(mon, 10); - if (file != null) { + if (tu != null) { try { subMonitor.subTask(Messages.Refactoring_PM_ParseTU); - ast = loadTranslationUnit(file); + ast = tu.getAST(fIndex, AST_STYLE); if (ast == null) { subMonitor.done(); return false; @@ -256,7 +257,7 @@ public abstract class CRefactoring extends Refactoring { return false; } } else { - status.addFatalError(Messages.NO_FILE); + status.addFatalError(NLS.bind(Messages.CRefactoring_FileNotFound, tu.getPath().toString())); subMonitor.done(); return false; } @@ -264,15 +265,6 @@ public abstract class CRefactoring extends Refactoring { return true; } - protected IASTTranslationUnit loadTranslationUnit(IFile file) throws CoreException { - ITranslationUnit tu = (ITranslationUnit) CCorePlugin.getDefault().getCoreModel().create(file); - if (tu == null) { - initStatus.addFatalError(NLS.bind(Messages.CRefactoring_FileNotFound, file.getName())); - return null; - } - return tu.getAST(fIndex, AST_STYLE); - } - protected boolean translationUnitHasProblem() { ProblemFinder pf = new ProblemFinder(initStatus); ast.accept(pf); @@ -305,6 +297,13 @@ public abstract class CRefactoring extends Refactoring { return fIndex; } + /** + * Returns the translation unit where the refactoring started. + */ + public ITranslationUnit getTranslationUnit() { + return tu; + } + public IASTTranslationUnit getUnit() { return ast; } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/CRefactoring2.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/CRefactoring2.java index cb2d941aaa2..8ca463f7655 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/CRefactoring2.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/CRefactoring2.java @@ -239,6 +239,13 @@ public abstract class CRefactoring2 extends Refactoring { return name; } + /** + * Returns the translation unit where the refactoring started. + */ + public ITranslationUnit getTranslationUnit() { + return tu; + } + protected IASTTranslationUnit getAST(ITranslationUnit tu, IProgressMonitor pm) throws CoreException, OperationCanceledException { return astCache.getAST(tu, pm); diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/ChangeParametersControl.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/ChangeParametersControl.java new file mode 100644 index 00000000000..dd3d10f796c --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/ChangeParametersControl.java @@ -0,0 +1,815 @@ +/******************************************************************************* + * Copyright (c) 2000, 2011 IBM Corporation 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: + * IBM Corporation - initial API and implementation + * Sergey Prigogin (Google) + *******************************************************************************/ +package org.eclipse.cdt.internal.ui.refactoring; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +import org.eclipse.core.runtime.Assert; +import org.eclipse.jface.contentassist.SubjectControlContentAssistant; +import org.eclipse.jface.resource.JFaceResources; +import org.eclipse.jface.viewers.CellEditor; +import org.eclipse.jface.viewers.ColumnWeightData; +import org.eclipse.jface.viewers.ComboBoxCellEditor; +import org.eclipse.jface.viewers.ICellModifier; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.IStructuredContentProvider; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.ITableFontProvider; +import org.eclipse.jface.viewers.ITableLabelProvider; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.CCombo; +import org.eclipse.swt.events.KeyAdapter; +import org.eclipse.swt.events.KeyEvent; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.TraverseEvent; +import org.eclipse.swt.events.TraverseListener; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableColumn; +import org.eclipse.swt.widgets.TableItem; +import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.contentassist.ContentAssistHandler; + +import org.eclipse.cdt.internal.corext.codemanipulation.StubUtility; + +import org.eclipse.cdt.internal.ui.dialogs.TableTextCellEditor; +import org.eclipse.cdt.internal.ui.dialogs.TextFieldNavigationHandler; +import org.eclipse.cdt.internal.ui.util.SWTUtil; +import org.eclipse.cdt.internal.ui.util.TableLayoutComposite; + +/** + * A special control to edit and reorder method parameters. + */ +public class ChangeParametersControl extends Composite { + + public static enum Mode { + EXTRACT_METHOD, EXTRACT_METHOD_FIXED_RETURN, CHANGE_METHOD_SIGNATURE, INTRODUCE_PARAMETER; + + public boolean canChangeTypes() { + return this == CHANGE_METHOD_SIGNATURE; + } + + public boolean canAddParameters() { + return this == Mode.CHANGE_METHOD_SIGNATURE; + } + + public boolean canChangeDefault() { + return this == Mode.CHANGE_METHOD_SIGNATURE; + } + + public boolean shouldShowDirection() { + return this == Mode.EXTRACT_METHOD || this == Mode.EXTRACT_METHOD_FIXED_RETURN; + } + + public boolean canChangeReturn() { + return this == Mode.EXTRACT_METHOD; + } + } + + private static class NameInformationContentProvider implements IStructuredContentProvider { + @Override + @SuppressWarnings("unchecked") + public Object[] getElements(Object inputElement) { + return removeMarkedAsDeleted((List<NameInformation>) inputElement); + } + + private NameInformation[] removeMarkedAsDeleted(List<NameInformation> params) { + List<NameInformation> result= new ArrayList<NameInformation>(params.size()); + for (Iterator<NameInformation> iter= params.iterator(); iter.hasNext();) { + NameInformation info= iter.next(); + if (!info.isDeleted()) + result.add(info); + } + return result.toArray(new NameInformation[result.size()]); + } + + @Override + public void dispose() { + // do nothing + } + + @Override + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + // do nothing + } + } + + private class NameInformationLabelProvider extends LabelProvider + implements ITableLabelProvider, ITableFontProvider { + @Override + public Image getColumnImage(Object element, int columnIndex) { + return null; + } + + @Override + public String getColumnText(Object element, int columnIndex) { + NameInformation info= (NameInformation) element; + if (columnIndex == indexType) { + return info.getTypeName(); + } else if (columnIndex == indexDirection) { + return getDirectionLabel(info); + } else if (columnIndex == indexName) { + return info.getNewName(); + } else if (columnIndex == indexDefault) { + if (info.isAdded()) { + return info.getDefaultValue(); + } else { + return "-"; //$NON-NLS-1$ + } + } else { + throw new IllegalArgumentException(columnIndex + ": " + element); //$NON-NLS-1$ + } + } + + @Override + public Font getFont(Object element, int columnIndex) { + NameInformation info= (NameInformation) element; + if (info.isAdded()) { + return JFaceResources.getFontRegistry().getBold(JFaceResources.DIALOG_FONT); + } + return null; + } + } + + private class ParametersCellModifier implements ICellModifier { + @Override + public boolean canModify(Object element, String property) { + Assert.isTrue(element instanceof NameInformation); + if (property.equals(columnProperties[indexType])) { + return fMode.canChangeTypes(); + } else if (property.equals(columnProperties[indexDirection])) { + return fMode.canChangeReturn() && ((NameInformation) element).isOutput(); + } else if (property.equals(columnProperties[indexName])) { + return true; + } else if (property.equals(columnProperties[indexDefault])) { + return ((NameInformation) element).isAdded(); + } + Assert.isTrue(false); + return false; + } + + @Override + public Object getValue(Object element, String property) { + Assert.isTrue(element instanceof NameInformation); + if (property.equals(columnProperties[indexType])) { + return ((NameInformation) element).getTypeName(); + } else if (property.equals(columnProperties[indexDirection])) { + return ((NameInformation) element).isReturnValue() ? INDEX_RETURN : INDEX_OUTPUT; + } else if (property.equals(columnProperties[indexName])) { + return ((NameInformation) element).getNewName(); + } else if (property.equals(columnProperties[indexDefault])) { + return ((NameInformation) element).getDefaultValue(); + } + Assert.isTrue(false); + return null; + } + + @Override + public void modify(Object element, String property, Object value) { + if (element instanceof TableItem) + element= ((TableItem) element).getData(); + if (!(element instanceof NameInformation)) + return; + String[] columnsToUpdate = new String[] { property }; + boolean unchanged; + NameInformation parameterInfo= (NameInformation) element; + if (property.equals(columnProperties[indexType])) { + unchanged= parameterInfo.getTypeName().equals(value); + parameterInfo.setTypeName((String) value); + } else if (property.equals(columnProperties[indexDirection])) { + columnsToUpdate = new String[] { property, columnProperties[indexType] }; + boolean isReturn = value.equals(INDEX_RETURN); + unchanged= isReturn == parameterInfo.isReturnValue(); + if (!unchanged && isReturn) { + for (NameInformation param : fParameters) { + if (param != parameterInfo && param.isOutput()) { + param.setReturnValue(false); + ChangeParametersControl.this.fListener.parameterChanged(param); + ChangeParametersControl.this.fTableViewer.update(param, columnsToUpdate); + break; + } + } + } + parameterInfo.setReturnValue(isReturn); + } else if (property.equals(columnProperties[indexName])) { + unchanged= parameterInfo.getNewName().equals(value); + parameterInfo.setNewName((String) value); + } else if (property.equals(columnProperties[indexDefault])) { + unchanged= parameterInfo.getDefaultValue().equals(value); + parameterInfo.setDefaultValue((String) value); + } else { + throw new IllegalStateException(); + } + if (!unchanged) { + ChangeParametersControl.this.fListener.parameterChanged(parameterInfo); + ChangeParametersControl.this.fTableViewer.update(parameterInfo, columnsToUpdate); + } + } + } + + private static class DirectionCellEditor extends ComboBoxCellEditor { + DirectionCellEditor(Table table) { + super(table, + new String[] { + /* INDEX_OUTPUT */ Messages.ChangeParametersControl_output, + /* INDEX_RETURN */ Messages.ChangeParametersControl_return}, + SWT.READ_ONLY); + } + + @Override + protected Control createControl(Composite parent) { + final CCombo comboBox = (CCombo) super.createControl(parent); + comboBox.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent event) { + fireApplyEditorValue(); + } + }); + return comboBox; + } + } + + private final String[] columnProperties; + private final int indexType; + private final int indexDirection; + private final int indexName; + private final int indexDefault; + + private static final int ROW_COUNT= 7; + + static final Integer INDEX_OUTPUT = 0; + static final Integer INDEX_RETURN = 1; + + private final Mode fMode; + private final IParameterListChangeListener fListener; + private List<NameInformation> fParameters; + private final StubTypeContext fTypeContext; + private final String[] fParamNameProposals; + private ContentAssistHandler fNameContentAssistHandler; + + private TableViewer fTableViewer; + private Button fUpButton; + private Button fDownButton; + private Button fEditButton; + private Button fAddButton; + private Button fRemoveButton; + + public ChangeParametersControl(Composite parent, int style, String label, + IParameterListChangeListener listener, Mode mode, StubTypeContext typeContext) { + this(parent, style, label, listener, mode, typeContext, new String[0]); + } + + public ChangeParametersControl(Composite parent, int style, String label, + IParameterListChangeListener listener, Mode mode) { + this(parent, style, label, listener, mode, null, new String[0]); + } + + public ChangeParametersControl(Composite parent, int style, String label, + IParameterListChangeListener listener, Mode mode, String[] paramNameProposals) { + this(parent, style, label, listener, mode, null, paramNameProposals); + } + + /** + * @param label the label before the table or <code>null</code> + * @param typeContext the package in which to complete types + */ + private ChangeParametersControl(Composite parent, int style, String label, + IParameterListChangeListener listener, Mode mode, StubTypeContext typeContext, + String[] paramNameProposals) { + super(parent, style); + Assert.isNotNull(listener); + fListener= listener; + fMode= mode; + fTypeContext= typeContext; + fParamNameProposals= paramNameProposals; + + ArrayList<String> properties = new ArrayList<String>(); + indexType = properties.size(); + properties.add("type"); //$NON-NLS-1$ + + if (fMode.shouldShowDirection()) { + indexDirection = properties.size(); + properties.add("direction"); //$NON-NLS-1$ + } else { + indexDirection = -1; + } + + indexName = properties.size(); + properties.add("name"); //$NON-NLS-1$ + + if (fMode.canChangeDefault()) { + indexDefault = properties.size(); + properties.add("default"); //$NON-NLS-1$ + } else { + indexDefault = -1; + } + columnProperties = properties.toArray(new String[properties.size()]); + + GridLayout layout= new GridLayout(); + layout.numColumns= 2; + layout.marginWidth= 0; + layout.marginHeight= 0; + setLayout(layout); + + if (label != null) { + Label tableLabel= new Label(this, SWT.NONE); + GridData labelGd= new GridData(); + labelGd.horizontalSpan= 2; + tableLabel.setLayoutData(labelGd); + tableLabel.setText(label); + } + + createParameterList(this); + createButtonComposite(this); + } + + public void setInput(List<NameInformation> parameterInfos) { + Assert.isNotNull(parameterInfos); + fParameters= parameterInfos; + fTableViewer.setInput(fParameters); + if (fParameters.size() > 0) + fTableViewer.setSelection(new StructuredSelection(fParameters.get(0))); + } + + public void editParameter(NameInformation info) { + fTableViewer.getControl().setFocus(); + if (!info.isDeleted()) { + fTableViewer.setSelection(new StructuredSelection(info), true); + updateButtonsEnabledState(); + editColumnOrNextPossible(indexName); + return; + } + } + + // ---- Parameter table ----------------------------------------------------------------------------------- + + private void createParameterList(Composite parent) { + TableLayoutComposite layouter= new TableLayoutComposite(parent, SWT.NONE); + addColumnLayoutData(layouter); + + final Table table= new Table(layouter, SWT.MULTI | SWT.BORDER | SWT.FULL_SELECTION); + table.setHeaderVisible(true); + table.setLinesVisible(true); + TableColumn tc; + tc= new TableColumn(table, SWT.NONE, indexType); + tc.setResizable(true); + tc.setText(Messages.ChangeParametersControl_table_type); + + if (indexDirection >= 0) { + tc= new TableColumn(table, SWT.NONE, indexDirection); + tc.setResizable(true); + tc.setText(Messages.ChangeParametersControl_table_direction); + } + + tc= new TableColumn(table, SWT.NONE, indexName); + tc.setResizable(true); + tc.setText(Messages.ChangeParametersControl_table_name); + + if (indexDefault >= 0) { + tc= new TableColumn(table, SWT.NONE, indexDefault); + tc.setResizable(true); + tc.setText(Messages.ChangeParametersControl_table_default_value); + } + + GridData gd= new GridData(GridData.FILL_BOTH); + gd.heightHint= SWTUtil.getTableHeightHint(table, ROW_COUNT); + gd.widthHint= 40; + layouter.setLayoutData(gd); + + fTableViewer= new TableViewer(table); + fTableViewer.setUseHashlookup(true); + fTableViewer.setContentProvider(new NameInformationContentProvider()); + fTableViewer.setLabelProvider(new NameInformationLabelProvider()); + fTableViewer.addSelectionChangedListener(new ISelectionChangedListener() { + @Override + public void selectionChanged(SelectionChangedEvent event) { + updateButtonsEnabledState(); + } + }); + + table.addTraverseListener(new TraverseListener() { + @Override + public void keyTraversed(TraverseEvent e) { + if (e.detail == SWT.TRAVERSE_RETURN && e.stateMask == SWT.NONE) { + editColumnOrNextPossible(0); + e.detail= SWT.TRAVERSE_NONE; + } + } + }); + table.addKeyListener(new KeyAdapter() { + @Override + public void keyPressed(KeyEvent e) { + if (e.keyCode == SWT.F2 && e.stateMask == SWT.NONE) { + editColumnOrNextPossible(0); + e.doit= false; + } + } + }); + + addCellEditors(); + } + + private static String getDirectionLabel(NameInformation parameter) { + return parameter.isReturnValue() ? + Messages.ChangeParametersControl_return : + parameter.isOutput() ? + Messages.ChangeParametersControl_output : + Messages.ChangeParametersControl_input; + } + + private void editColumnOrNextPossible(int column) { + NameInformation[] selected= getSelectedElements(); + if (selected.length != 1) + return; + int nextColumn= column; + do { + fTableViewer.editElement(selected[0], nextColumn); + if (fTableViewer.isCellEditorActive()) + return; + nextColumn= nextColumn(nextColumn); + } while (nextColumn != column); + } + + private void editColumnOrPrevPossible(int column) { + NameInformation[] selected= getSelectedElements(); + if (selected.length != 1) + return; + int prevColumn= column; + do { + fTableViewer.editElement(selected[0], prevColumn); + if (fTableViewer.isCellEditorActive()) + return; + prevColumn= prevColumn(prevColumn); + } while (prevColumn != column); + } + + private int nextColumn(int column) { + return column >= getTable().getColumnCount() - 1 ? 0 : column + 1; + } + + private int prevColumn(int column) { + return column <= 0 ? getTable().getColumnCount() - 1 : column - 1; + } + + private void addColumnLayoutData(TableLayoutComposite layouter) { + for (int i = 0; i < columnProperties.length; i++) { + layouter.addColumnData(new ColumnWeightData(10, true)); + } + } + + private NameInformation[] getSelectedElements() { + ISelection selection= fTableViewer.getSelection(); + if (selection == null) + return new NameInformation[0]; + + if (!(selection instanceof IStructuredSelection)) + return new NameInformation[0]; + + List<?> selected= ((IStructuredSelection) selection).toList(); + return selected.toArray(new NameInformation[selected.size()]); + } + + // ---- Button bar -------------------------------------------------------------------------------------- + + private void createButtonComposite(Composite parent) { + Composite buttonComposite= new Composite(parent, SWT.NONE); + buttonComposite.setLayoutData(new GridData(GridData.FILL_VERTICAL)); + GridLayout gl= new GridLayout(); + gl.marginHeight= 0; + gl.marginWidth= 0; + buttonComposite.setLayout(gl); + + if (fMode.canAddParameters()) + fAddButton= createAddButton(buttonComposite); + + fEditButton= createEditButton(buttonComposite); + + if (fMode.canAddParameters()) + fRemoveButton= createRemoveButton(buttonComposite); + + if (buttonComposite.getChildren().length != 0) + addSpacer(buttonComposite); + + fUpButton= createButton(buttonComposite, Messages.ChangeParametersControl_buttons_move_up, true); + fDownButton= createButton(buttonComposite, Messages.ChangeParametersControl_buttons_move_down, false); + + updateButtonsEnabledState(); + } + + private void addSpacer(Composite parent) { + Label label= new Label(parent, SWT.NONE); + GridData gd= new GridData(GridData.FILL_HORIZONTAL); + gd.heightHint= 5; + label.setLayoutData(gd); + } + + private void updateButtonsEnabledState() { + fUpButton.setEnabled(canMove(true)); + fDownButton.setEnabled(canMove(false)); + if (fEditButton != null) + fEditButton.setEnabled(getTableSelectionCount() == 1); + if (fAddButton != null) + fAddButton.setEnabled(true); + if (fRemoveButton != null) + fRemoveButton.setEnabled(getTableSelectionCount() != 0); + } + + private int getTableSelectionCount() { + return getTable().getSelectionCount(); + } + + private int getTableItemCount() { + return getTable().getItemCount(); + } + + private Table getTable() { + return fTableViewer.getTable(); + } + + private Button createEditButton(Composite buttonComposite) { + Button button= new Button(buttonComposite, SWT.PUSH); + button.setText(Messages.ChangeParametersControl_buttons_edit); + button.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + SWTUtil.setButtonDimensionHint(button); + button.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + try { + NameInformation[] selected= getSelectedElements(); + Assert.isTrue(selected.length == 1); + NameInformation parameterInfo= selected[0]; + ParameterEditDialog dialog= new ParameterEditDialog(getShell(), parameterInfo, + fMode.canChangeTypes(), fMode.canChangeDefault(), + fMode.canChangeReturn() && parameterInfo.isOutput()); + dialog.open(); + fListener.parameterChanged(parameterInfo); + fTableViewer.update(parameterInfo, columnProperties); + } finally { + fTableViewer.getControl().setFocus(); + } + } + }); + return button; + } + + private Button createAddButton(Composite buttonComposite) { + Button button= new Button(buttonComposite, SWT.PUSH); + button.setText(Messages.ChangeParametersControl_buttons_add); + button.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + SWTUtil.setButtonDimensionHint(button); + button.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + Set<String> excludedParamNames= new HashSet<String>(fParameters.size()); + for (int i= 0; i < fParameters.size(); i++) { + NameInformation info= fParameters.get(i); + excludedParamNames.add(info.getNewName()); + } + String newParamName= StubUtility.suggestParameterName("newParam", excludedParamNames, //$NON-NLS-1$ + fTypeContext != null ? fTypeContext.getTranslationUnit() : null); + NameInformation newInfo= NameInformation.createInfoForAddedParameter("int", newParamName, "0"); //$NON-NLS-1$ //$NON-NLS-2$ + int insertIndex= fParameters.size(); + fParameters.add(insertIndex, newInfo); + fListener.parameterAdded(newInfo); + fTableViewer.refresh(); + fTableViewer.getControl().setFocus(); + fTableViewer.setSelection(new StructuredSelection(newInfo), true); + updateButtonsEnabledState(); + editColumnOrNextPossible(0); + } + }); + return button; + } + + private Button createRemoveButton(Composite buttonComposite) { + final Button button= new Button(buttonComposite, SWT.PUSH); + button.setText(Messages.ChangeParametersControl_buttons_remove); + button.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + SWTUtil.setButtonDimensionHint(button); + button.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + int index= getTable().getSelectionIndices()[0]; + NameInformation[] selected= getSelectedElements(); + for (int i= 0; i < selected.length; i++) { + if (selected[i].isAdded()) { + fParameters.remove(selected[i]); + } else { + selected[i].markAsDeleted(); + } + } + restoreSelection(index); + } + + private void restoreSelection(int index) { + fTableViewer.refresh(); + fTableViewer.getControl().setFocus(); + int itemCount= getTableItemCount(); + if (itemCount != 0) { + if (index >= itemCount) + index= itemCount - 1; + getTable().setSelection(index); + } + fListener.parameterListChanged(); + updateButtonsEnabledState(); + } + }); + return button; + } + + private Button createButton(Composite buttonComposite, String text, final boolean up) { + Button button= new Button(buttonComposite, SWT.PUSH); + button.setText(text); + button.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + SWTUtil.setButtonDimensionHint(button); + button.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + ISelection savedSelection= fTableViewer.getSelection(); + if (savedSelection == null) + return; + NameInformation[] selection= getSelectedElements(); + if (selection.length == 0) + return; + + if (up) { + moveUp(selection); + } else { + moveDown(selection); + } + fTableViewer.refresh(); + fTableViewer.setSelection(savedSelection); + fListener.parameterListChanged(); + fTableViewer.getControl().setFocus(); + } + }); + return button; + } + + //---- editing ----------------------------------------------------------------------------------------------- + + private void addCellEditors() { + fTableViewer.setColumnProperties(columnProperties); + + ArrayList<CellEditor> editors = new ArrayList<CellEditor>(); + TableTextCellEditor cellEditorType= new TableTextCellEditor(fTableViewer, indexType); + editors.add(cellEditorType); + if (indexDirection >= 0) { + ComboBoxCellEditor cellEditorDirection= new DirectionCellEditor(fTableViewer.getTable()); + editors.add(cellEditorDirection); + } + TableTextCellEditor cellEditorName= new TableTextCellEditor(fTableViewer, indexName); + editors.add(cellEditorName); + if (indexDefault >= 0) { + TableTextCellEditor cellEditorDefault= new TableTextCellEditor(fTableViewer, indexDefault); + editors.add(cellEditorDefault); + } + + if (fParamNameProposals.length > 0) { + SubjectControlContentAssistant assistant= installParameterNameContentAssist(cellEditorName.getText()); + cellEditorName.setContentAssistant(assistant); + } + + for (int i = 0; i < editors.size(); i++) { + final int editorColumn= i; + final CellEditor editor = editors.get(i); + // Support tabbing between columns while editing + Control control = editor.getControl(); + control.addTraverseListener(new TraverseListener() { + @Override + public void keyTraversed(TraverseEvent e) { + switch (e.detail) { + case SWT.TRAVERSE_TAB_NEXT: + editColumnOrNextPossible(nextColumn(editorColumn)); + e.detail= SWT.TRAVERSE_NONE; + break; + + case SWT.TRAVERSE_TAB_PREVIOUS: + editColumnOrPrevPossible(prevColumn(editorColumn)); + e.detail= SWT.TRAVERSE_NONE; + break; + } + } + }); + if (control instanceof Text) { + TextFieldNavigationHandler.install((Text) control); + } + } + + cellEditorName.setActivationListener(new TableTextCellEditor.IActivationListener() { + @Override + public void activate() { + NameInformation[] selected= getSelectedElements(); + if (selected.length == 1 && fNameContentAssistHandler != null) { + fNameContentAssistHandler.setEnabled(selected[0].isAdded()); + } + } + }); + + fTableViewer.setCellEditors(editors.toArray(new CellEditor[editors.size()])); + fTableViewer.setCellModifier(new ParametersCellModifier()); + } + + //---- change order ---------------------------------------------------------------------------------------- + + private void moveUp(NameInformation[] selection) { + moveUp(fParameters, Arrays.asList(selection)); + } + + private void moveDown(NameInformation[] selection) { + Collections.reverse(fParameters); + moveUp(fParameters, Arrays.asList(selection)); + Collections.reverse(fParameters); + } + + private static void moveUp(List<NameInformation> elements, List<NameInformation> move) { + List<NameInformation> res= new ArrayList<NameInformation>(elements.size()); + List<NameInformation> deleted= new ArrayList<NameInformation>(); + NameInformation floating= null; + for (Iterator<NameInformation> iter= elements.iterator(); iter.hasNext();) { + NameInformation curr= iter.next(); + if (move.contains(curr)) { + res.add(curr); + } else if (curr.isDeleted()) { + deleted.add(curr); + } else { + if (floating != null) + res.add(floating); + floating= curr; + } + } + if (floating != null) { + res.add(floating); + } + res.addAll(deleted); + elements.clear(); + for (Iterator<NameInformation> iter= res.iterator(); iter.hasNext();) { + elements.add(iter.next()); + } + } + + private boolean canMove(boolean up) { + int notDeletedInfosCount= getNotDeletedInfosCount(); + if (notDeletedInfosCount == 0) + return false; + int[] indc= getTable().getSelectionIndices(); + if (indc.length == 0) + return false; + int invalid= up ? 0 : notDeletedInfosCount - 1; + for (int i= 0; i < indc.length; i++) { + if (indc[i] == invalid) + return false; + } + return true; + } + + private int getNotDeletedInfosCount() { + if (fParameters == null) // during initialization + return 0; + int result= 0; + for (Iterator<NameInformation> iter= fParameters.iterator(); iter.hasNext();) { + NameInformation info= iter.next(); + if (!info.isDeleted()) + result++; + } + return result; + } + + private SubjectControlContentAssistant installParameterNameContentAssist(Text text) { + return null; + // TODO(sprigogin): Implement to support parameter name content assist. +// VariableNamesProcessor processor= new VariableNamesProcessor(fParamNameProposals); +// SubjectControlContentAssistant contentAssistant= ControlContentAssistHelper.createCContentAssistant(processor); +// fNameContentAssistHandler= ContentAssistHandler.createHandlerForText(text, contentAssistant); +// return contentAssistant; + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/IParameterListChangeListener.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/IParameterListChangeListener.java new file mode 100644 index 00000000000..32ead0149a9 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/IParameterListChangeListener.java @@ -0,0 +1,35 @@ +/******************************************************************************* + * Copyright (c) 2000, 2012 IBM Corporation 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: + * IBM Corporation - initial API and implementation + * Sergey Prigogin (Google) + *******************************************************************************/ +package org.eclipse.cdt.internal.ui.refactoring; + +/** + * @see ChangeParametersControl + */ +public interface IParameterListChangeListener { + /** + * Gets fired when the given parameter has changed + * @param parameter the parameter that has changed. + */ + public void parameterChanged(NameInformation parameter); + + /** + * Gets fired when the given parameter has been added + * @param parameter the parameter that has been added. + */ + public void parameterAdded(NameInformation parameter); + + /** + * Gets fired if the parameter list got modified by reordering or removing + * parameters (note that adding is handled by <code>parameterAdded</code>)) + */ + public void parameterListChanged(); +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/Messages.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/Messages.java index 93d5ca243ff..22176b2c2fc 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/Messages.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/Messages.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2008, 2011 Institute for Software, HSR Hochschule fuer Technik + * Copyright (c) 2008, 2012 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 @@ -35,7 +35,6 @@ public final class Messages extends NLS { public static String Refactoring_CantLoadTU; public static String Refactoring_Ambiguity; public static String Refactoring_ParsingError; - public static String NO_FILE; public static String RefactoringSaveHelper_unexpected_exception; public static String RefactoringSaveHelper_saving; public static String RefactoringSaveHelper_always_save; @@ -49,6 +48,28 @@ public final class Messages extends NLS { public static String ChangeExceptionHandler_undo_button; public static String ChangeExceptionHandler_undo_dialog_message; public static String ChangeExceptionHandler_undo_dialog_title; + public static String ChangeParametersControl_table_type; + public static String ChangeParametersControl_table_direction; + public static String ChangeParametersControl_table_name; + public static String ChangeParametersControl_table_default_value; + public static String ChangeParametersControl_input; + public static String ChangeParametersControl_output; + public static String ChangeParametersControl_return; + public static String ChangeParametersControl_buttons_move_up; + public static String ChangeParametersControl_buttons_move_down; + public static String ChangeParametersControl_buttons_edit; + public static String ChangeParametersControl_buttons_add; + public static String ChangeParametersControl_buttons_remove; + public static String ParameterEditDialog_title; + public static String ParameterEditDialog_message_new; + public static String ParameterEditDialog_message; + public static String ParameterEditDialog_type; + public static String ParameterEditDialog_name; + public static String ParameterEditDialog_name_error; + public static String ParameterEditDialog_default_value; + public static String ParameterEditDialog_default_value_error; + public static String ParameterEditDialog_default_value_invalid; + public static String ParameterEditDialog_use_as_return; public static String RefactoringExecutionHelper_cannot_execute; static { diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/Messages.properties b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/Messages.properties index 04adb314e15..c42894c574b 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/Messages.properties +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/Messages.properties @@ -1,5 +1,5 @@ ############################################################################### -# Copyright (c) 2008, 2009 Institute for Software, HSR Hochschule fuer Technik +# Copyright (c) 2008, 2012 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 @@ -22,7 +22,7 @@ Refactoring_CanceledByUser=Refactoring canceled by user. Refactoring_CompileErrorInTU=The translation unit contains one or several problems. This can be caused by a syntax error in the code or a parser flaw. The refactoring will possibly fail. AddDeclarationNodeToClassChange_AddDeclaration=Add Declaration to Class {0}. CreateFileChange_CreateFile=Create file: {0} -CreateFileChange_UnknownLoc=Unknown Location: {0} +CreateFileChange_UnknownLoc=Unknown location: {0} CreateFileChange_FileExists=File already exists: {0} CRefactoring_FileNotFound=The file {0} is not on the build path of a C/C++ project. CRefactoring_checking_final_conditions=Checking preconditions... @@ -30,7 +30,6 @@ Refactoring_SelectionNotValid=Selection is not valid. Refactoring_CantLoadTU=Can not load translation unit. Refactoring_Ambiguity=Translation unit is ambiguous. Refactoring_ParsingError=Unable to parse {0}. -NO_FILE=File not found. RefactoringSaveHelper_unexpected_exception=An unexpected exception occurred. See the error log for more details. RefactoringSaveHelper_saving=Saving Resources RefactoringSaveHelper_always_save=&Always save all modified resources automatically prior to refactoring @@ -44,4 +43,26 @@ ChangeExceptionHandler_status_without_detail=Exception does not provide a detail ChangeExceptionHandler_undo_dialog_title=Undo Refactoring ChangeExceptionHandler_undo_dialog_message=An unexpected exception occurred while undoing the refactoring ''{0}'' ChangeExceptionHandler_dialog_message=An exception has been caught while processing the refactoring ''{0}''. +ChangeParametersControl_table_type=Type +ChangeParametersControl_table_direction=Input/Output +ChangeParametersControl_table_name=Name +ChangeParametersControl_table_default_value=Default value +ChangeParametersControl_input=input +ChangeParametersControl_output=output +ChangeParametersControl_return=return +ChangeParametersControl_buttons_move_up=&Up +ChangeParametersControl_buttons_move_down=D&own +ChangeParametersControl_buttons_edit=&Edit... +ChangeParametersControl_buttons_add=&Add +ChangeParametersControl_buttons_remove=Re&move +ParameterEditDialog_title=Function Parameter +ParameterEditDialog_message_new=Declaration of parameter: +ParameterEditDialog_message=Declaration of parameter ''{0}'': +ParameterEditDialog_type=&Type: +ParameterEditDialog_name=&Name: +ParameterEditDialog_name_error= Parameter name must not be empty. +ParameterEditDialog_default_value=&Default value: +ParameterEditDialog_default_value_error= Default value must not be empty. +ParameterEditDialog_default_value_invalid=''{0}'' is not a valid expression. +ParameterEditDialog_use_as_return=Use as &return value RefactoringExecutionHelper_cannot_execute=The operation cannot be performed due to the following problem:\n\n{0} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/NameInformation.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/NameInformation.java new file mode 100644 index 00000000000..aba38c6b706 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/NameInformation.java @@ -0,0 +1,315 @@ +/******************************************************************************* + * Copyright (c) 2008, 2012 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 - initial API and implementation + * Sergey Prigogin (Google) + *******************************************************************************/ +package org.eclipse.cdt.internal.ui.refactoring; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.core.runtime.Assert; + +import org.eclipse.cdt.core.dom.ast.IASTArrayDeclarator; +import org.eclipse.cdt.core.dom.ast.IASTArrayModifier; +import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier; +import org.eclipse.cdt.core.dom.ast.IASTDeclarator; +import org.eclipse.cdt.core.dom.ast.IASTFileLocation; +import org.eclipse.cdt.core.dom.ast.IASTName; +import org.eclipse.cdt.core.dom.ast.IASTNode; +import org.eclipse.cdt.core.dom.ast.IASTNode.CopyStyle; +import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration; +import org.eclipse.cdt.core.dom.ast.IASTPointerOperator; +import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration; +import org.eclipse.cdt.core.dom.ast.INodeFactory; +import org.eclipse.cdt.core.dom.ast.IType; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPNodeFactory; +import org.eclipse.cdt.core.dom.rewrite.TypeHelper; +import org.eclipse.cdt.core.model.ITranslationUnit; + +import org.eclipse.cdt.internal.core.dom.rewrite.astwriter.ASTWriterVisitor; + +/** + * Additional information about an IASTName in code being refactored. + */ +public class NameInformation { + public static final int INDEX_FOR_ADDED = -1; + + private final IASTName name; + private IASTName declarationName; + private final List<IASTName> references; + private List<IASTName> referencesAfterCached; + private int lastCachedReferencesHash; + private boolean isOutput; + private boolean mustBeReturnValue; + private boolean isWriteAccess; + private boolean passOutputByPointer; + private boolean isReturnValue; + private String newName; + private int newOrder; + private boolean isDeleted; + private String defaultValue; + private String newTypeName; + + public NameInformation(IASTName name) { + this.name = name; + this.newName = String.valueOf(name.getSimpleID()); + references = new ArrayList<IASTName>(); + } + + public static NameInformation createInfoForAddedParameter(String type, String name, + String defaultValue) { + NameInformation info= new NameInformation(null); + info.setTypeName(type); + info.setNewName(name); + info.setDefaultValue(defaultValue); + info.setNewOrder(INDEX_FOR_ADDED); + return info; + } + + /** + * For debugging only. + */ + @Override + public String toString() { + return name.toString(); + } + + public int getNewOrder() { + return newOrder; + } + + public void setNewOrder(int newOrder) { + this.newOrder = newOrder; + } + + /** + * Returns <code>true</code> if the value of the variable has to propagate to the outside world. + */ + public boolean isOutput() { + return isOutput; + } + + void setOutput(boolean isOutput) { + this.isOutput = isOutput; + } + + public boolean isOutputParameter() { + return isOutput() && !isReturnValue(); + } + + public boolean mustBeReturnValue() { + return mustBeReturnValue; + } + + public void setMustBeReturnValue(boolean mustBeReturnValue) { + this.mustBeReturnValue = mustBeReturnValue; + } + + public boolean isReturnValue() { + return mustBeReturnValue || isReturnValue; + } + + public void setReturnValue(boolean isReturnValue) { + Assert.isTrue(isReturnValue || !mustBeReturnValue); + this.isReturnValue = isReturnValue; + } + + public String getNewName() { + return newName; + } + + public void setNewName(String newName) { + this.newName = newName; + } + + public boolean isWriteAccess() { + return isWriteAccess; + } + + void setWriteAccess(boolean isWriteAceess) { + this.isWriteAccess = isWriteAceess; + } + + public boolean isDeleted() { + return isDeleted; + } + + public void markAsDeleted() { + Assert.isTrue(!isAdded()); // Added parameters should be simply removed from the list + isDeleted= true; + } + + public boolean isAdded() { + // TODO(sprigogin): Adding parameters is not supported yet. + return false; + } + + public String getDefaultValue() { + return defaultValue; + } + + public void setDefaultValue(String value) { + Assert.isNotNull(value); + defaultValue= value; + } + + public IASTName getDeclarationName() { + return declarationName; + } + + public IASTDeclarator getDeclarator() { + return (IASTDeclarator) declarationName.getParent(); + } + + public IASTDeclSpecifier getDeclSpecifier() { + IASTNode parent = getDeclarator().getParent(); + if (parent instanceof IASTSimpleDeclaration) { + return ((IASTSimpleDeclaration) parent).getDeclSpecifier(); + } else if (parent instanceof IASTParameterDeclaration) { + return ((IASTParameterDeclaration) parent).getDeclSpecifier(); + } + return null; + } + + void setDeclarationName(IASTName declarationName) { + Assert.isTrue(declarationName.getParent() instanceof IASTDeclarator); + this.declarationName = declarationName; + } + + public IASTName getName() { + return name; + } + + public boolean isRenamed() { + return name == null ? newName != null : String.valueOf(name.getSimpleID()).equals(name); + } + + void addReference(IASTName name) { + references.add(name); + } + + public String getTypeName() { + if (newTypeName != null) + return newTypeName; + INodeFactory nodeFactory = name.getTranslationUnit().getASTNodeFactory(); + IASTParameterDeclaration declaration = getParameterDeclaration(nodeFactory, null); + ASTWriterVisitor writer = new ASTWriterVisitor(); + declaration.accept(writer); + return writer.toString(); + } + + public void setTypeName(String type) { + Assert.isNotNull(type); + newTypeName= type; + } + + public String getReturnType() { + if (!isReturnValue()) + return null; + INodeFactory nodeFactory = name.getTranslationUnit().getASTNodeFactory(); + IASTDeclarator sourceDeclarator = getDeclarator(); + IASTDeclSpecifier declSpec = safeCopy(getDeclSpecifier()); + IASTDeclarator declarator = createDeclarator(nodeFactory, sourceDeclarator, null); + IASTParameterDeclaration declaration = nodeFactory.newParameterDeclaration(declSpec, declarator); + ASTWriterVisitor writer = new ASTWriterVisitor(); + declaration.accept(writer); + return writer.toString(); + } + + public List<IASTName> getReferencesAfterSelection(int endOffset) { + if (referencesAfterCached == null || lastCachedReferencesHash != references.hashCode()) { + lastCachedReferencesHash = references.hashCode(); + referencesAfterCached = new ArrayList<IASTName>(); + for (IASTName ref : references) { + IASTFileLocation loc = ref.getFileLocation(); + if (loc.getNodeOffset() >= endOffset) { + referencesAfterCached.add(ref); + } + } + } + return referencesAfterCached; + } + + public boolean isReferencedAfterSelection(int endOffset) { + return !getReferencesAfterSelection(endOffset).isEmpty(); + } + + public IASTParameterDeclaration getParameterDeclaration(INodeFactory nodeFactory) { + return getParameterDeclaration(nodeFactory, newName); + } + + private IASTParameterDeclaration getParameterDeclaration(INodeFactory nodeFactory, String paramName) { + IASTDeclarator sourceDeclarator = getDeclarator(); + IASTDeclSpecifier declSpec = safeCopy(getDeclSpecifier()); + IASTDeclarator declarator = createDeclarator(nodeFactory, sourceDeclarator, paramName); + + if (isOutputParameter()) { + if (nodeFactory instanceof ICPPNodeFactory && !passOutputByPointer) { + declarator.addPointerOperator(((ICPPNodeFactory) nodeFactory).newReferenceOperator(false)); + } else { + declarator.addPointerOperator(nodeFactory.newPointer()); + } + } else if (declSpec != null && !isWriteAccess) { + IType type = TypeHelper.createType(sourceDeclarator); + if (TypeHelper.shouldBePassedByReference(type, declarationName.getTranslationUnit())) { + if (nodeFactory instanceof ICPPNodeFactory) { + declarator.addPointerOperator(((ICPPNodeFactory) nodeFactory).newReferenceOperator(false)); + } else { + declarator.addPointerOperator(nodeFactory.newPointer()); + } + declSpec.setConst(true); + } + } + + declarator.setNestedDeclarator(sourceDeclarator.getNestedDeclarator()); + + return nodeFactory.newParameterDeclaration(declSpec, declarator); + } + + private IASTDeclarator createDeclarator(INodeFactory nodeFactory, IASTDeclarator sourceDeclarator, + String name) { + IASTName astName = name != null ? + nodeFactory.newName(name.toCharArray()) : nodeFactory.newName(); + IASTDeclarator declarator; + if (sourceDeclarator instanceof IASTArrayDeclarator) { + IASTArrayDeclarator arrDeclarator = (IASTArrayDeclarator) sourceDeclarator; + IASTArrayDeclarator arrayDeclarator = nodeFactory.newArrayDeclarator(astName); + IASTArrayModifier[] arrayModifiers = arrDeclarator.getArrayModifiers(); + for (IASTArrayModifier arrayModifier : arrayModifiers) { + arrayDeclarator.addArrayModifier(arrayModifier.copy(CopyStyle.withLocations)); + } + declarator= arrayDeclarator; + } else { + declarator = nodeFactory.newDeclarator(astName); + } + for (IASTPointerOperator pointerOp : sourceDeclarator.getPointerOperators()) { + declarator.addPointerOperator(pointerOp.copy(CopyStyle.withLocations)); + } + return declarator; + } + + @SuppressWarnings("unchecked") + private static <T extends IASTNode> T safeCopy(T node) { + return node == null ? null : (T) node.copy(CopyStyle.withLocations); + } + + public ITranslationUnit getTranslationUnit() { + return name != null ? name.getTranslationUnit().getOriginatingTranslationUnit() : null; + } + + public boolean isPassOutputByPointer() { + return passOutputByPointer; + } + + public void setPassOutputByPointer(boolean passOutputByPointer) { + this.passOutputByPointer = passOutputByPointer; + } +}
\ No newline at end of file diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/NodeContainer.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/NodeContainer.java index 353000961ef..48131146709 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/NodeContainer.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/NodeContainer.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2008, 2009 Institute for Software, HSR Hochschule fuer Technik + * Copyright (c) 2008, 2012 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 @@ -18,263 +18,39 @@ import java.util.HashSet; import java.util.List; import java.util.Set; -import org.eclipse.core.runtime.Assert; +import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.ILog; import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.preferences.IPreferencesService; import org.eclipse.cdt.core.dom.ast.ASTVisitor; import org.eclipse.cdt.core.dom.ast.DOMException; -import org.eclipse.cdt.core.dom.ast.IASTArrayDeclarator; -import org.eclipse.cdt.core.dom.ast.IASTArrayModifier; -import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier; import org.eclipse.cdt.core.dom.ast.IASTDeclarator; -import org.eclipse.cdt.core.dom.ast.IASTFileLocation; import org.eclipse.cdt.core.dom.ast.IASTMacroExpansionLocation; import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.IASTNode; -import org.eclipse.cdt.core.dom.ast.IASTNode.CopyStyle; import org.eclipse.cdt.core.dom.ast.IASTNodeLocation; -import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration; import org.eclipse.cdt.core.dom.ast.IASTPointerOperator; -import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration; import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; import org.eclipse.cdt.core.dom.ast.IBinding; -import org.eclipse.cdt.core.dom.ast.INodeFactory; import org.eclipse.cdt.core.dom.ast.IVariable; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTReferenceOperator; -import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTSimpleTypeTemplateParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPBinding; -import org.eclipse.cdt.core.dom.ast.cpp.ICPPNodeFactory; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateTypeParameter; +import org.eclipse.cdt.core.model.ITranslationUnit; import org.eclipse.cdt.ui.CUIPlugin; +import org.eclipse.cdt.ui.PreferenceConstants; -import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTName; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVariableReadWriteFlags; -import org.eclipse.cdt.internal.core.dom.rewrite.astwriter.ASTWriter; import org.eclipse.cdt.internal.core.pdom.dom.PDOMName; public class NodeContainer { - public final NameInformation NULL_NAME_INFORMATION = new NameInformation(new CPPASTName()); - private final List<IASTNode> nodes; private List<NameInformation> names; private List<NameInformation> interfaceNames; - public class NameInformation { - private IASTName name; - private IASTName declaration; - private final List<IASTName> references; - private List<IASTName> referencesAfterCached; - private int lastCachedReferencesHash; - private boolean mustBeOutput; - private boolean mustBeReturnValue; - private boolean isConst; - private boolean isWriteAccess; - - private boolean isOutput; - private boolean isReturnValue; - private String userSetName; - private int userOrder; - - public int getUserOrder() { - return userOrder; - } - - public void setUserOrder(int userOrder) { - this.userOrder = userOrder; - } - - public NameInformation(IASTName name) { - super(); - this.name = name; - references = new ArrayList<IASTName>(); - } - - public IASTName getDeclaration() { - return declaration; - } - - public void setDeclaration(IASTName declaration) { - this.declaration = declaration; - } - - public IASTName getName() { - return name; - } - - public void setName(IASTName name) { - this.name = name; - } - - public void addReference(IASTName name) { - references.add(name); - } - - public List<IASTName> getReferencesAfterSelection() { - if (referencesAfterCached == null || lastCachedReferencesHash != references.hashCode()) { - lastCachedReferencesHash = references.hashCode(); - referencesAfterCached = new ArrayList<IASTName>(); - for (IASTName ref : references) { - IASTFileLocation loc = ref.getFileLocation(); - if (loc.getNodeOffset() >= getEndOffset()) { - referencesAfterCached.add(ref); - } - } - } - return referencesAfterCached; - } - - public boolean isReferencedAfterSelection() { - return !getReferencesAfterSelection().isEmpty(); - } - - public IASTParameterDeclaration getParameterDeclaration(INodeFactory nodeFactory) { - IASTDeclarator sourceDeclarator = (IASTDeclarator) getDeclaration().getParent(); - - IASTDeclSpecifier declSpec= null; - IASTDeclarator declarator= null; - - if (sourceDeclarator.getParent() instanceof IASTSimpleDeclaration) { - IASTSimpleDeclaration decl = (IASTSimpleDeclaration) sourceDeclarator.getParent(); - declSpec = decl.getDeclSpecifier().copy(CopyStyle.withLocations); - } else if (sourceDeclarator.getParent() instanceof IASTParameterDeclaration) { - IASTParameterDeclaration decl = (IASTParameterDeclaration) sourceDeclarator.getParent(); - declSpec = decl.getDeclSpecifier().copy(CopyStyle.withLocations); - } - - IASTName name= nodeFactory.newName(getDeclaration().toCharArray()); - if (sourceDeclarator instanceof IASTArrayDeclarator) { - IASTArrayDeclarator arrDeclarator = (IASTArrayDeclarator) sourceDeclarator; - IASTArrayDeclarator arrayDtor = nodeFactory.newArrayDeclarator(name); - IASTArrayModifier[] arrayModifiers = arrDeclarator.getArrayModifiers(); - for (IASTArrayModifier arrayModifier : arrayModifiers) { - arrayDtor.addArrayModifier(arrayModifier.copy(CopyStyle.withLocations)); - } - declarator= arrayDtor; - } else { - declarator = nodeFactory.newDeclarator(name); - } - for (IASTPointerOperator pointerOp : sourceDeclarator.getPointerOperators()) { - declarator.addPointerOperator(pointerOp.copy(CopyStyle.withLocations)); - } - - boolean output = isOutput() && !isReturnValue(); - if (output && !hasReferenceOperator(declarator)) { - if (nodeFactory instanceof ICPPNodeFactory) { - declarator.addPointerOperator(((ICPPNodeFactory) nodeFactory).newReferenceOperator(false)); - } else { - declarator.addPointerOperator(nodeFactory.newPointer()); - } - } - - declarator.setNestedDeclarator(sourceDeclarator.getNestedDeclarator()); - - return nodeFactory.newParameterDeclaration(declSpec, declarator); - } - - public boolean hasReferenceOperator(IASTDeclarator declarator) { - for (IASTPointerOperator pOp : declarator.getPointerOperators()) { - if (pOp instanceof ICPPASTReferenceOperator) { - return true; - } - } - return false; - } - - public String getType() { - IASTDeclSpecifier declSpec = null; - - IASTNode node = getDeclaration().getParent(); - if (node instanceof ICPPASTSimpleTypeTemplateParameter) { - ICPPASTSimpleTypeTemplateParameter parameter = (ICPPASTSimpleTypeTemplateParameter) node; - return parameter.getName().toString(); - } - IASTDeclarator sourceDeclarator = (IASTDeclarator) node; - if (sourceDeclarator.getParent() instanceof IASTSimpleDeclaration) { - IASTSimpleDeclaration decl = (IASTSimpleDeclaration) sourceDeclarator.getParent(); - declSpec = decl.getDeclSpecifier(); - } else if (sourceDeclarator.getParent() instanceof IASTParameterDeclaration) { - IASTParameterDeclaration decl = (IASTParameterDeclaration) sourceDeclarator.getParent(); - declSpec = decl.getDeclSpecifier(); - } - - ASTWriter writer = new ASTWriter(); - return writer.write(declSpec); - } - - public boolean isDeclaredInSelection() { - if (declaration != null && declaration.toCharArray().length > 0) { - int declOffset = declaration.getFileLocation().getNodeOffset(); - return declOffset >= getStartOffset() && declOffset <= getEndOffset(); - } - return true; - } - - @Override - public String toString() { - return name.toString() + (isDeclaredInSelection() ? " (declared inside)" : ""); //$NON-NLS-1$//$NON-NLS-2$ - } - - public boolean mustBeOutput() { - return mustBeOutput; - } - - public void setMustBeOutput(boolean mustBeOutput) { - this.mustBeOutput = mustBeOutput; - } - - public boolean isOutput() { - return mustBeOutput || isOutput; - } - - public void setIsOutput(boolean isOutput) { - Assert.isTrue(isOutput || !mustBeOutput); - this.isOutput = isOutput; - } - - public boolean mustBeReturnValue() { - return mustBeReturnValue; - } - - public void setMustBeReturnValue(boolean mustBeReturnValue) { - this.mustBeReturnValue = mustBeReturnValue; - } - - public boolean isReturnValue() { - return mustBeReturnValue || isReturnValue; - } - - public void setReturnValue(boolean isReturnValue) { - Assert.isTrue(isReturnValue || !mustBeReturnValue); - this.isReturnValue = isReturnValue; - } - - public String getUserSetName() { - return userSetName; - } - - public void setUserSetName(String userSetName) { - this.userSetName = userSetName; - } - - public boolean isConst() { - return isConst; - } - - public void setConst(boolean isConst) { - this.isConst = isConst; - } - - public boolean isWriteAccess() { - return isWriteAccess; - } - - public void setWriteAccess(boolean isWriteAceess) { - this.isWriteAccess = isWriteAceess; - } - } - public NodeContainer() { super(); nodes = new ArrayList<IASTNode>(); @@ -297,6 +73,12 @@ public class NodeContainer { return; } names = new ArrayList<NameInformation>(); + + IPreferencesService preferences = Platform.getPreferencesService(); + final boolean passOutputByPointer = preferences.getBoolean(CUIPlugin.PLUGIN_ID, + PreferenceConstants.FUNCTION_PASS_OUTPUT_PARAMETERS_BY_POINTER, false, + PreferenceConstants.getPreferenceScopes(getProject())); + for (IASTNode node : nodes) { node.accept(new ASTVisitor() { { @@ -305,18 +87,19 @@ public class NodeContainer { @Override public int visit(IASTName name) { - IBinding bind = name.resolveBinding(); + IBinding binding = name.resolveBinding(); - if (bind instanceof ICPPBinding && !(bind instanceof ICPPTemplateTypeParameter)) { - ICPPBinding cppBind = (ICPPBinding) bind; + if (binding instanceof ICPPBinding && !(binding instanceof ICPPTemplateTypeParameter)) { + ICPPBinding cppBinding = (ICPPBinding) binding; try { - if (!cppBind.isGloballyQualified()) { - NameInformation nameInformation = new NameInformation(name); - IASTName[] refs = name.getTranslationUnit().getReferences(bind); + if (!cppBinding.isGloballyQualified()) { + NameInformation nameInfo = new NameInformation(name); + nameInfo.setPassOutputByPointer(passOutputByPointer); + IASTName[] refs = name.getTranslationUnit().getReferences(binding); for (IASTName ref : refs) { - nameInformation.addReference(ref); + nameInfo.addReference(ref); } - names.add(nameInformation); + names.add(nameInfo); } } catch (DOMException e) { ILog logger = CUIPlugin.getDefault().getLog(); @@ -324,10 +107,10 @@ public class NodeContainer { CUIPlugin.PLUGIN_ID, IStatus.OK, e.getMessage(), e); logger.log(status); } - } else if (bind instanceof IVariable) { + } else if (binding instanceof IVariable) { NameInformation nameInformation = new NameInformation(name); - IASTName[] refs = name.getTranslationUnit().getReferences(bind); + IASTName[] refs = name.getTranslationUnit().getReferences(binding); for (IASTName ref : refs) { nameInformation.addReference(ref); } @@ -344,11 +127,21 @@ public class NodeContainer { IASTTranslationUnit unit = name.getTranslationUnit(); IASTName[] nameDeclarations = unit.getDeclarationsInAST(name.resolveBinding()); if (nameDeclarations.length != 0) { - nameInfo.setDeclaration(nameDeclarations[nameDeclarations.length - 1]); + nameInfo.setDeclarationName(nameDeclarations[nameDeclarations.length - 1]); } } } + private IProject getProject() { + IProject project = null; + if (nodes.isEmpty()) { + ITranslationUnit tu = nodes.get(0).getTranslationUnit().getOriginatingTranslationUnit(); + if (tu != null) + project = tu.getCProject().getProject(); + } + return project; + } + /** * Returns names that are either parameter or return value candidates. */ @@ -359,25 +152,30 @@ public class NodeContainer { Set<IASTName> declarations = new HashSet<IASTName>(); interfaceNames = new ArrayList<NameInformation>(); + int endOffset = getEndOffset(); for (NameInformation nameInfo : names) { - if (declarations.add(nameInfo.getDeclaration())) { - if (nameInfo.isDeclaredInSelection()) { - if (nameInfo.isReferencedAfterSelection()) { + IASTName declarationName = nameInfo.getDeclarationName(); + if (declarations.add(declarationName)) { + if (isDeclaredInSelection(nameInfo)) { + if (nameInfo.isReferencedAfterSelection(endOffset)) { nameInfo.setMustBeReturnValue(true); interfaceNames.add(nameInfo); } } else { - for (NameInformation n2 : names) { - if (n2.getDeclaration() == nameInfo.getDeclaration()) { - int flag = CPPVariableReadWriteFlags.getReadWriteFlags(n2.getName()); - if ((flag & PDOMName.WRITE_ACCESS) != 0) { - nameInfo.setWriteAccess(true); - break; + IASTDeclarator declarator = (IASTDeclarator) declarationName.getParent(); + if (!hasReferenceOperator(declarator)) { + for (NameInformation n2 : names) { + if (n2.getDeclarationName() == declarationName) { + int flag = CPPVariableReadWriteFlags.getReadWriteFlags(n2.getName()); + if ((flag & PDOMName.WRITE_ACCESS) != 0) { + nameInfo.setWriteAccess(true); + break; + } } } - } - if (nameInfo.isWriteAccess() && nameInfo.isReferencedAfterSelection()) { - nameInfo.setMustBeOutput(true); + if (nameInfo.isWriteAccess() && nameInfo.isReferencedAfterSelection(endOffset)) { + nameInfo.setOutput(true); + } } interfaceNames.add(nameInfo); } @@ -388,6 +186,20 @@ public class NodeContainer { return interfaceNames; } + public static boolean hasReferenceOperator(IASTDeclarator declarator) { + IASTPointerOperator[] operators = declarator.getPointerOperators(); + return operators.length != 0 && operators[operators.length - 1] instanceof ICPPASTReferenceOperator; + } + + public boolean isDeclaredInSelection(NameInformation nameInfo) { + IASTName declaration = nameInfo.getDeclarationName(); + if (declaration != null && declaration.toCharArray().length > 0) { + int declOffset = declaration.getFileLocation().getNodeOffset(); + return declOffset >= getStartOffset() && declOffset <= getEndOffset(); + } + return true; + } + private List<NameInformation> getInterfaceNames(boolean isReturnValue) { List<NameInformation> selectedNames = null; @@ -412,7 +224,6 @@ public class NodeContainer { return getInterfaceNames(false); } - /** * Returns names that are candidates for being used as the function return value. Multiple * return value candidates mean that the function cannot be extracted. diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/ParameterEditDialog.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/ParameterEditDialog.java new file mode 100644 index 00000000000..13b9ae916c3 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/ParameterEditDialog.java @@ -0,0 +1,219 @@ +/******************************************************************************* + * Copyright (c) 2000, 2012 IBM Corporation 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: + * IBM Corporation - initial API and implementation + * Sergey Prigogin (Google) + *******************************************************************************/ +package org.eclipse.cdt.internal.ui.refactoring; + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.jface.dialogs.StatusDialog; +import org.eclipse.osgi.util.NLS; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; + +import org.eclipse.cdt.core.CConventions; +import org.eclipse.cdt.ui.CUIPlugin; + +import org.eclipse.cdt.internal.ui.dialogs.TextFieldNavigationHandler; +import org.eclipse.cdt.internal.ui.viewsupport.BasicElementLabels; + +public class ParameterEditDialog extends StatusDialog { + private final NameInformation fParameter; + private final boolean fEditType; + private final boolean fEditDefault; + private final boolean fEditReturn; + private Text fType; + private Text fName; + private Text fDefaultValue; + private Button fReturn; + + /** + * @param parentShell + * @param parameter + * @param canEditType + * @param canEditDefault + * @param canChangeReturn + * Can be <code>null</code> if <code>canEditType</code> is <code>false</code>. + */ + public ParameterEditDialog(Shell parentShell, NameInformation parameter, boolean canEditType, + boolean canEditDefault, boolean canChangeReturn) { + super(parentShell); + fParameter= parameter; + fEditType= canEditType; + fEditDefault= canEditDefault; + fEditReturn = canChangeReturn; + } + + @Override + protected void configureShell(Shell newShell) { + super.configureShell(newShell); + newShell.setText(Messages.ParameterEditDialog_title); + } + + @Override + protected Control createDialogArea(Composite parent) { + Composite result= (Composite) super.createDialogArea(parent); + GridLayout layout= (GridLayout) result.getLayout(); + layout.numColumns= 2; + Label label; + GridData gd; + + label= new Label(result, SWT.NONE); + String newName = fParameter.getNewName(); + if (newName.isEmpty()) { + label.setText(Messages.ParameterEditDialog_message_new); + } else { + label.setText(NLS.bind(Messages.ParameterEditDialog_message, + BasicElementLabels.getCElementName(newName))); + } + gd= new GridData(GridData.FILL_HORIZONTAL); + gd.horizontalSpan= 2; + label.setLayoutData(gd); + + if (fEditType) { + label= new Label(result, SWT.NONE); + label.setText(Messages.ParameterEditDialog_type); + fType= new Text(result, SWT.BORDER); + gd= new GridData(GridData.FILL_HORIZONTAL); + fType.setLayoutData(gd); + fType.setText(fParameter.getTypeName()); + fType.addModifyListener( + new ModifyListener() { + @Override + public void modifyText(ModifyEvent e) { + validate((Text) e.widget); + } + }); + TextFieldNavigationHandler.install(fType); + } + + label= new Label(result, SWT.NONE); + fName= new Text(result, SWT.BORDER); + initializeDialogUnits(fName); + label.setText(Messages.ParameterEditDialog_name); + gd= new GridData(GridData.FILL_HORIZONTAL); + gd.widthHint= convertWidthInCharsToPixels(45); + fName.setLayoutData(gd); + fName.setText(newName); + fName.addModifyListener( + new ModifyListener() { + @Override + public void modifyText(ModifyEvent e) { + validate((Text) e.widget); + } + }); + TextFieldNavigationHandler.install(fName); + + if (fEditDefault && fParameter.isAdded()) { + label= new Label(result, SWT.NONE); + label.setText(Messages.ParameterEditDialog_default_value); + fDefaultValue= new Text(result, SWT.BORDER); + gd= new GridData(GridData.FILL_HORIZONTAL); + fDefaultValue.setLayoutData(gd); + fDefaultValue.setText(fParameter.getDefaultValue()); + fDefaultValue.addModifyListener( + new ModifyListener() { + @Override + public void modifyText(ModifyEvent e) { + validate((Text) e.widget); + } + }); + TextFieldNavigationHandler.install(fDefaultValue); + } + if (fEditReturn) { + fReturn = new Button(result, SWT.CHECK); + fReturn.setText(Messages.ParameterEditDialog_use_as_return); + fReturn.setSelection(fParameter.isReturnValue()); + fReturn.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + } + applyDialogFont(result); + return result; + } + + @Override + protected void okPressed() { + if (fType != null) { + fParameter.setTypeName(fType.getText()); + } + fParameter.setNewName(fName.getText()); + if (fDefaultValue != null) { + fParameter.setDefaultValue(fDefaultValue.getText()); + } + if (fReturn != null) { + fParameter.setReturnValue(fReturn.getSelection()); + } + super.okPressed(); + } + + private void validate(Text first) { + IStatus[] result= new IStatus[3]; + if (first == fType) { + result[0]= validateType(); + result[1]= validateName(); + result[2]= validateDefaultValue(); + } else if (first == fName) { + result[0]= validateName(); + result[1]= validateType(); + result[2]= validateDefaultValue(); + } else { + result[0]= validateDefaultValue(); + result[1]= validateName(); + result[2]= validateType(); + } + for (int i= 0; i < result.length; i++) { + IStatus status= result[i]; + if (status != null && !status.isOK()) { + updateStatus(status); + return; + } + } + updateStatus(Status.OK_STATUS); + } + + private IStatus validateType() { + // TODO(sprigogin): Implement type validation. + return Status.OK_STATUS; + } + + private IStatus validateName() { + if (fName == null) + return null; + String name= fName.getText(); + if (name.isEmpty()) + return createErrorStatus(Messages.ParameterEditDialog_name_error); + IStatus status= CConventions.validateFieldName(name); + if (status.matches(IStatus.ERROR)) + return status; + return Status.OK_STATUS; + } + + private IStatus validateDefaultValue() { + if (fDefaultValue == null) + return null; + String defaultValue= fDefaultValue.getText(); + if (defaultValue.isEmpty()) + return createErrorStatus(Messages.ParameterEditDialog_default_value_error); + // TODO(sprigogin): Implement real default value validation. + return Status.OK_STATUS; + } + + private Status createErrorStatus(String message) { + return new Status(IStatus.ERROR, CUIPlugin.getPluginId(), IStatus.ERROR, message, null); + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/StubTypeContext.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/StubTypeContext.java new file mode 100644 index 00000000000..4223a0eee31 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/StubTypeContext.java @@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright (c) 2000, 2012 IBM Corporation 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: + * IBM Corporation - initial API and implementation + * Sergey Prigogin (Googel) + *******************************************************************************/ +package org.eclipse.cdt.internal.ui.refactoring; + +import org.eclipse.cdt.core.model.ITranslationUnit; + +public class StubTypeContext { + private final ITranslationUnit tu; + + public StubTypeContext(ITranslationUnit tu) { + this.tu = tu; + } + + public ITranslationUnit getTranslationUnit() { + return tu; + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/ChooserComposite.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/ChooserComposite.java deleted file mode 100644 index 69d9d694a38..00000000000 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/ChooserComposite.java +++ /dev/null @@ -1,204 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2008, 2009 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 - initial API and implementation - *******************************************************************************/ -package org.eclipse.cdt.internal.ui.refactoring.extractfunction; - -import java.util.ArrayList; - -import org.eclipse.swt.SWT; -import org.eclipse.swt.custom.TableEditor; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.events.SelectionListener; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Button; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Event; -import org.eclipse.swt.widgets.Table; -import org.eclipse.swt.widgets.TableColumn; -import org.eclipse.swt.widgets.TableItem; - -import org.eclipse.cdt.core.dom.ast.IASTDeclarator; - -import org.eclipse.cdt.internal.ui.refactoring.NodeContainer.NameInformation; - -public class ChooserComposite extends Composite { - private static final String COLUMN_RETURN = Messages.ChooserComposite_Return; - private static final String COLUMN_REFERENCE = Messages.ChooserComposite_CallByRef; - private static final String COLUMN_NAME = Messages.ChooserComposite_Name; - private static final String COLUMN_TYPE = Messages.ChooserComposite_Type; - - private Button checkboxVoidReturn; - - public ChooserComposite(Composite parent, final ExtractFunctionInformation info, - ExtractFunctionInputPage page) { - super(parent, SWT.NONE); - - GridLayout layout = new GridLayout(); - setLayout(layout); - - final ArrayList<Button> returnButtons = new ArrayList<Button>(); - final ArrayList<Button> referenceButtons = new ArrayList<Button>(); - - final Table table = new Table(parent, SWT.BORDER | SWT.MULTI | SWT.FILL); - - GridData tableLayoutData = new GridData(SWT.FILL, SWT.FILL, true, true); - table.setLayoutData(tableLayoutData); - - table.setLinesVisible(true); - table.setHeaderVisible(true); - - addColumnToTable(table, COLUMN_TYPE); - addColumnToTable(table, COLUMN_NAME); - addColumnToTable(table, COLUMN_REFERENCE); - addColumnToTable(table, Messages.ChooserComposite_const); - if (!info.isExtractExpression()) { - addColumnToTable(table, COLUMN_RETURN); - } - addColumnToTable(table, ""); //$NON-NLS-1$ - - for (int i = 0; i < info.getParameterCandidates().size(); i++) { - if (!info.getParameterCandidates().get(i).isDeclaredInSelection()) { - TableItem item = new TableItem(table, SWT.NONE); - - TableEditor editor = new TableEditor(table); - int columnIndex = 0; - - final NameInformation name = info.getParameterCandidates().get(i); - - // Text - item.setText(columnIndex++, name.getType()); - item.setText(columnIndex++, name.getName().toString()); - - // Button - editor = new TableEditor(table); - final Button buttonOutput = new Button(table, SWT.CHECK); - if (name.hasReferenceOperator((IASTDeclarator) name.getDeclaration().getParent())) { - buttonOutput.setSelection(true); - buttonOutput.setEnabled(false); - } else { - buttonOutput.setSelection(name.isOutput() && !name.isReturnValue()); - buttonOutput.setEnabled(!name.mustBeOutput() && !name.isReturnValue()); - } - buttonOutput.setBackground(table.getBackground()); - buttonOutput.addSelectionListener(new SelectionListener() { - @Override - public void widgetDefaultSelected(SelectionEvent e) { - widgetSelected(e); - } - - @Override - public void widgetSelected(SelectionEvent e) { - if (buttonOutput.isEnabled()) { - name.setIsOutput(buttonOutput.getSelection()); - } - } - }); - buttonOutput.pack(); - editor.minimumWidth = buttonOutput.getSize().x; - editor.horizontalAlignment = SWT.CENTER; - referenceButtons.add(buttonOutput); - editor.setEditor(buttonOutput, item, columnIndex++); - - // Const button - editor = new TableEditor(table); - final Button buttonConst = new Button(table, SWT.CHECK); - - buttonConst.setSelection(name.isConst()); - buttonConst.setEnabled(!name.isWriteAccess()); - - buttonConst.setBackground(table.getBackground()); - buttonConst.addSelectionListener(new SelectionListener() { - @Override - public void widgetDefaultSelected(SelectionEvent e) { - widgetSelected(e); - } - - @Override - public void widgetSelected(SelectionEvent e) { - name.setConst(buttonConst.getSelection()); - } - }); - buttonConst.pack(); - editor.minimumWidth = buttonConst.getSize().x; - editor.horizontalAlignment = SWT.CENTER; -// referenceButtons.add(referenceButton); - editor.setEditor(buttonConst, item, columnIndex++); - - if (info.isExtractExpression()) - continue; // Skip the return radiobutton - - // Button - editor = new TableEditor(table); - final Button buttonReturn = new Button(table, SWT.RADIO); - buttonReturn.setSelection(name.mustBeReturnValue()); - buttonReturn.setEnabled(info.getMandatoryReturnVariable() == null); - buttonReturn.setBackground(table.getBackground()); - buttonReturn.addSelectionListener(new SelectionListener() { - @Override - public void widgetDefaultSelected(SelectionEvent e) { - widgetSelected(e); - } - - @Override - public void widgetSelected(SelectionEvent e) { - name.setReturnValue(buttonReturn.getSelection()); - if (buttonReturn.getSelection()) { - buttonOutput.setSelection(false); - buttonOutput.notifyListeners(SWT.Selection, new Event()); - } else if (name.mustBeOutput()) { - buttonOutput.setSelection(true); - buttonOutput.notifyListeners(SWT.Selection, new Event()); - } - } - }); - buttonReturn.pack(); - editor.minimumWidth = buttonReturn.getSize().x; - editor.horizontalAlignment = SWT.CENTER; - returnButtons.add(buttonReturn); - editor.setEditor(buttonReturn, item, columnIndex++); - } - } - - if (!info.isExtractExpression()) { - checkboxVoidReturn = new Button(parent, SWT.CHECK | SWT.LEFT); - checkboxVoidReturn.setText(Messages.ChooserComposite_NoReturnValue); - checkboxVoidReturn.setEnabled(info.getMandatoryReturnVariable() == null); - checkboxVoidReturn.addSelectionListener(new SelectionListener() { - @Override - public void widgetDefaultSelected(SelectionEvent e) { - widgetSelected(e); - } - - @Override - public void widgetSelected(SelectionEvent e) { - info.setReturnVariable(null); - - for (Button button : returnButtons) { - if (checkboxVoidReturn.getSelection()) { - button.setSelection(false); - button.notifyListeners(SWT.Selection, new Event()); - } - button.setEnabled(!checkboxVoidReturn.getSelection()); - } - } - }); - } - - layout(); - } - - private void addColumnToTable(final Table table, String string) { - TableColumn column = new TableColumn(table, SWT.NONE); - column.setText(string); - column.setWidth(100); - } -} 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 5a93af1cab0..0135b5211bb 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 @@ -50,7 +50,7 @@ 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.CPPFunction; -import org.eclipse.cdt.internal.ui.refactoring.NodeContainer.NameInformation; +import org.eclipse.cdt.internal.ui.refactoring.NameInformation; /** * Handles the extraction of expression nodes, for example, return type determination. diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/ExtractFunctionComposite.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/ExtractFunctionComposite.java deleted file mode 100644 index 81a38f6d6b4..00000000000 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/ExtractFunctionComposite.java +++ /dev/null @@ -1,130 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2008, 2009 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 - initial API and implementation - *******************************************************************************/ -package org.eclipse.cdt.internal.ui.refactoring.extractfunction; - -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.SelectionAdapter; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Button; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Group; -import org.eclipse.swt.widgets.Text; - -import org.eclipse.cdt.internal.ui.refactoring.MethodContext; -import org.eclipse.cdt.internal.ui.refactoring.dialogs.NameAndVisibilityComposite; -import org.eclipse.cdt.internal.ui.refactoring.utils.VisibilityEnum; - -public class ExtractFunctionComposite extends Composite { - private Button replaceSimilar; - private ChooserComposite comp; - private NameAndVisibilityComposite nameVisiComp; - private final ExtractFunctionInformation info; - - public ExtractFunctionComposite(Composite parent, ExtractFunctionInformation info, - ExtractFunctionInputPage page) { - super(parent, SWT.NONE); - this.info = info; - setLayout(new GridLayout()); - - createNewMethodNameComposite(this); - - Group returnGroup = createReturnGroup(nameVisiComp); - createReturnValueChooser(returnGroup, info, page); - - createReplaceCheckBox(nameVisiComp); - - if (info.getMethodContext().getType() == MethodContext.ContextType.METHOD) { - visibilityPanelSetVisible(true); - } else { - visibilityPanelSetVisible(false); - } - layout(); - } - - private Group createReturnGroup(Composite parent) { - Group returnGroup = new Group(parent,SWT.NONE); - - returnGroup.setText(Messages.ExtractFunctionComposite_ReturnValue); - returnGroup.setLayout(new GridLayout()); - GridData gridData = new GridData(); - gridData.horizontalAlignment = GridData.FILL; - gridData.grabExcessHorizontalSpace = true; - returnGroup.setLayoutData(gridData); - return returnGroup; - } - - private void createReturnValueChooser(Composite parent, ExtractFunctionInformation info, - ExtractFunctionInputPage page) { - GridData gridData = new GridData(); - gridData.horizontalAlignment = GridData.FILL; - gridData.grabExcessHorizontalSpace = true; - comp = new ChooserComposite(parent, info, page); - comp.setLayoutData(gridData); - comp.redraw(); - } - - public Text getMethodNameText() { - return nameVisiComp.getConstantNameText(); - } - - public Button getReplaceSimilarButton() { - return replaceSimilar; - } - - public void visibilityPanelSetVisible(boolean visible) { - nameVisiComp.visibilityPanelsetVisible(visible); - } - - private void createNewMethodNameComposite(Composite parent) { - String label; - if (info.getMethodContext().getType() == MethodContext.ContextType.METHOD) { - label = Messages.ExtractFunctionComposite_MethodName; - } else { - label = Messages.ExtractFunctionComposite_FunctionName; - } - nameVisiComp = new NameAndVisibilityComposite(parent, label, VisibilityEnum.v_private, ""); //$NON-NLS-1$ - GridData gridData = new GridData(); - gridData.horizontalAlignment = GridData.FILL; - gridData.grabExcessHorizontalSpace = true; - nameVisiComp.setLayoutData(gridData); - final Button virtual = new Button(nameVisiComp, SWT.CHECK); - virtual.setText(Messages.ExtractFunctionComposite_Virtual); - virtual.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - info.setVirtual(virtual.getSelection()); - } - }); - } - - private void createReplaceCheckBox(Composite parent) { - replaceSimilar = new Button(parent, SWT.CHECK | SWT.LEFT); - GridData buttonLayoutData = new GridData(SWT.None); - buttonLayoutData.verticalIndent = 5; - replaceSimilar.setLayoutData(buttonLayoutData); - replaceSimilar.setText(Messages.ExtractFunctionComposite_ReplaceDuplicates); - } - - public ChooserComposite getReturnChooser() { - return comp; - } - - public String getMethodName(){ - return nameVisiComp.getConstantNameText().getText(); - } - - public Composite getVisibiltyGroup() { - return nameVisiComp.getVisibiltyGroup(); - } -} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/ExtractFunctionInformation.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/ExtractFunctionInformation.java index bd2cdd7ce5f..d3c30fa1ca5 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/ExtractFunctionInformation.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/ExtractFunctionInformation.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2008, 2009 Institute for Software, HSR Hochschule fuer Technik + * Copyright (c) 2008, 2012 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 @@ -8,24 +8,30 @@ * * Contributors: * Institute for Software - initial API and implementation + * Sergey Prigogin (Google) *******************************************************************************/ package org.eclipse.cdt.internal.ui.refactoring.extractfunction; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; import java.util.List; +import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier; +import org.eclipse.cdt.core.dom.ast.IASTDeclarator; +import org.eclipse.cdt.core.dom.ast.IASTPointerOperator; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator; import org.eclipse.cdt.internal.ui.refactoring.MethodContext; -import org.eclipse.cdt.internal.ui.refactoring.NodeContainer.NameInformation; +import org.eclipse.cdt.internal.ui.refactoring.NameInformation; import org.eclipse.cdt.internal.ui.refactoring.utils.VisibilityEnum; public class ExtractFunctionInformation { private VisibilityEnum visibility = VisibilityEnum.v_private; private String methodName; private boolean replaceDuplicates; - private List<NameInformation> parameterCandidates; + private List<NameInformation> parameters; private NameInformation mandatoryReturnVariable; - private NameInformation returnVariable; private ICPPASTFunctionDeclarator declarator; private MethodContext context; private boolean isExtractExpression; @@ -61,14 +67,13 @@ public class ExtractFunctionInformation { } public NameInformation getReturnVariable() { - return returnVariable; - } - - public void setReturnVariable(NameInformation variable) { - if (variable != null) { - variable.setReturnValue(true); + if (mandatoryReturnVariable != null) + return mandatoryReturnVariable; + for (NameInformation param : parameters) { + if (param.isReturnValue()) + return param; } - this.returnVariable = variable; + return null; } public NameInformation getMandatoryReturnVariable() { @@ -76,19 +81,15 @@ public class ExtractFunctionInformation { } public void setMandatoryReturnVariable(NameInformation variable) { - if (variable != null) { - variable.setMustBeReturnValue(true); - } this.mandatoryReturnVariable = variable; - this.returnVariable = variable; } - public List<NameInformation> getParameterCandidates() { - return parameterCandidates; + public List<NameInformation> getParameters() { + return parameters; } - public void setParameterCandidates(List<NameInformation> names) { - this.parameterCandidates = names; + public void setParameters(List<NameInformation> parameters) { + this.parameters = new ArrayList<NameInformation>(parameters); } public VisibilityEnum getVisibility() { @@ -122,4 +123,29 @@ public class ExtractFunctionInformation { public void setVirtual(boolean isVirtual) { this.virtual = isVirtual; } + + public void sortParameters(final boolean outFirst) { + Collections.sort(parameters, new Comparator<NameInformation>() { + @Override + public int compare(NameInformation p1, NameInformation p2) { + boolean out1 = p1.isOutputParameter() || hasNonConstPointerOrReference(p1); + boolean out2 = p2.isOutputParameter() || hasNonConstPointerOrReference(p2); + return out1 == out2 ? 0 : out1 == outFirst ? -1 : 1; + } + }); +// int i = 0; +// for (NameInformation param : parameterCandidates) { +// param.setNewOrder(i++); +// } + } + + public static boolean hasNonConstPointerOrReference(NameInformation param) { + IASTDeclarator declarator = param.getDeclarator(); + IASTPointerOperator[] operators = declarator.getPointerOperators(); + if (operators.length != 0) { + IASTDeclSpecifier declSpecifier = param.getDeclSpecifier(); + return declSpecifier == null || !declSpecifier.isConst(); + } + return false; + } } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/ExtractFunctionInputPage.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/ExtractFunctionInputPage.java index a2ea4836690..0c6a25a5f50 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/ExtractFunctionInputPage.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/ExtractFunctionInputPage.java @@ -1,94 +1,343 @@ /******************************************************************************* - * Copyright (c) 2008, 2009 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 - initial API and implementation - * IBM Corporation + * Copyright (c) 2000, 2012 IBM Corporation 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: + * IBM Corporation - initial API and implementation + * Benjamin Muskalla <bmuskalla@eclipsesource.com> + * Sergey Prigogin (Google) *******************************************************************************/ package org.eclipse.cdt.internal.ui.refactoring.extractfunction; +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.dialogs.IDialogSettings; +import org.eclipse.jface.layout.PixelConverter; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.resource.JFaceResources; +import org.eclipse.jface.text.Document; +import org.eclipse.ltk.core.refactoring.RefactoringStatus; import org.eclipse.ltk.ui.refactoring.UserInputWizardPage; +import org.eclipse.osgi.util.NLS; +import org.eclipse.swt.SWT; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; -import org.eclipse.swt.events.MouseAdapter; -import org.eclipse.swt.events.MouseEvent; +import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.PlatformUI; -import org.eclipse.cdt.internal.ui.refactoring.utils.IdentifierHelper; -import org.eclipse.cdt.internal.ui.refactoring.utils.IdentifierResult; +import org.eclipse.cdt.ui.CUIPlugin; +import org.eclipse.cdt.ui.PreferenceConstants; +import org.eclipse.cdt.ui.text.CSourceViewerConfiguration; + +import org.eclipse.cdt.internal.corext.codemanipulation.StubUtility; + +import org.eclipse.cdt.internal.ui.CPluginImages; +import org.eclipse.cdt.internal.ui.ICHelpContextIds; +import org.eclipse.cdt.internal.ui.dialogs.TextFieldNavigationHandler; +import org.eclipse.cdt.internal.ui.editor.CSourceViewer; +import org.eclipse.cdt.internal.ui.refactoring.ChangeParametersControl; +import org.eclipse.cdt.internal.ui.refactoring.ChangeParametersControl.Mode; +import org.eclipse.cdt.internal.ui.refactoring.IParameterListChangeListener; +import org.eclipse.cdt.internal.ui.refactoring.NameInformation; +import org.eclipse.cdt.internal.ui.refactoring.StubTypeContext; import org.eclipse.cdt.internal.ui.refactoring.utils.VisibilityEnum; +import org.eclipse.cdt.internal.ui.util.RowLayouter; public class ExtractFunctionInputPage extends UserInputWizardPage { - private final ExtractFunctionInformation info; - private ExtractFunctionComposite comp; - protected final String NO_NAME_ERROR_LABEL = Messages.ExtractFunctionInputPage_EnterName; + public static final String PAGE_NAME = "ExtractFunctionInputPage";//$NON-NLS-1$ + static final String DIALOG_SETTING_SECTION = "ExtractFunctionWizard"; //$NON-NLS-1$ + + private ExtractFunctionRefactoring refactoring; + private ExtractFunctionInformation info; + private Text textField; + private boolean firstTime; + private CSourceViewer signaturePreview; + private Document signaturePreviewDocument; + private IDialogSettings settings; - public ExtractFunctionInputPage(String name, ExtractFunctionInformation info) { - super(name); - this.info = info; + private static final String DESCRIPTION = Messages.ExtractFunctionInputPage_description; + private static final String ACCESS_MODIFIER = "AccessModifier"; //$NON-NLS-1$ + + public ExtractFunctionInputPage() { + super(PAGE_NAME); + setImageDescriptor(CPluginImages.DESC_WIZBAN_REFACTOR_TU); + setDescription(DESCRIPTION); + firstTime = true; + signaturePreviewDocument = new Document(); } @Override - public void createControl(final Composite parent) { - comp = new ExtractFunctionComposite(parent, info, this); - - setPageComplete(false); - - comp.getMethodNameText().addModifyListener(new ModifyListener() { - @Override - public void modifyText(ModifyEvent e) { - info.setMethodName(comp.getMethodName()); - checkName(); - } - }); - - for (Control buttons : comp.getVisibiltyGroup().getChildren()) { - buttons.addMouseListener(new MouseAdapter() { + public void createControl(Composite parent) { + refactoring = (ExtractFunctionRefactoring) getRefactoring(); + info = ((ExtractFunctionRefactoring) getRefactoring()).getRefactoringInfo(); + loadSettings(); + + Composite result = new Composite(parent, SWT.NONE); + setControl(result); + GridLayout layout = new GridLayout(); + layout.numColumns = 2; + result.setLayout(layout); + RowLayouter layouter = new RowLayouter(2); + GridData gd = null; + + initializeDialogUnits(result); + + Label label = new Label(result, SWT.NONE); + label.setText(getLabelText()); + + textField = createTextInputField(result, SWT.BORDER); + textField.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + + layouter.perform(label, textField, 1); + + label = new Label(result, SWT.NONE); + label.setText(Messages.ExtractFunctionInputPage_access_modifier); + + Composite group = new Composite(result, SWT.NONE); + group.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + layout = new GridLayout(); + layout.numColumns = 4; + layout.marginWidth = 0; + group.setLayout(layout); + + String[] labels = new String[] { + Messages.ExtractFunctionInputPage_public, + Messages.ExtractFunctionInputPage_protected, + Messages.ExtractFunctionInputPage_private + }; + VisibilityEnum[] visibilityValues = new VisibilityEnum[] { + VisibilityEnum.v_public, VisibilityEnum.v_protected, VisibilityEnum.v_private + }; + VisibilityEnum visibility = info.getVisibility(); + for (int i = 0; i < labels.length; i++) { + Button radio = new Button(group, SWT.RADIO); + radio.setText(labels[i]); + radio.setData(visibilityValues[i]); + if (visibilityValues[i].equals(visibility)) + radio.setSelection(true); + radio.addSelectionListener(new SelectionAdapter() { @Override - public void mouseUp(MouseEvent e) { - String text = ((Button)e.getSource()).getText(); - visibilityChange(text); - } + public void widgetSelected(SelectionEvent event) { + final VisibilityEnum selectedModifier = (VisibilityEnum) event.widget.getData(); + settings.put(ACCESS_MODIFIER, selectedModifier.toString()); + setVisibility(selectedModifier); + } }); } - - comp.getReplaceSimilarButton().addSelectionListener(new SelectionListener() { + layouter.perform(label, group, 1); + + if (!info.getParameters().isEmpty()) { + Mode mode = info.getMandatoryReturnVariable() != null ? + Mode.EXTRACT_METHOD_FIXED_RETURN : Mode.EXTRACT_METHOD; + ChangeParametersControl paramControl = new ChangeParametersControl(result, SWT.NONE, + Messages.ExtractFunctionInputPage_parameters, + new IParameterListChangeListener() { + @Override + public void parameterChanged(NameInformation parameter) { + parameterModified(); + } + + @Override + public void parameterListChanged() { + parameterModified(); + } + + @Override + public void parameterAdded(NameInformation parameter) { + updatePreview(getText()); + } + }, + mode, + new StubTypeContext(refactoring.getTranslationUnit())); + gd = new GridData(GridData.FILL_BOTH); + gd.horizontalSpan = 2; + paramControl.setLayoutData(gd); + paramControl.setInput(info.getParameters()); + } + + int duplicates = refactoring.getNumberOfDuplicates(); + Button checkBox = new Button(result, SWT.CHECK); + if (duplicates == 0) { + checkBox.setText(Messages.ExtractFunctionInputPage_duplicates_none); + } else if (duplicates == 1) { + checkBox.setText(Messages.ExtractFunctionInputPage_duplicates_single); + } else { + checkBox.setText(NLS.bind( + Messages.ExtractFunctionInputPage_duplicates_multi, Integer.valueOf(duplicates))); + } + checkBox.setSelection(info.isReplaceDuplicates()); + checkBox.setEnabled(duplicates > 0); + checkBox.addSelectionListener(new SelectionAdapter() { @Override - public void widgetDefaultSelected(SelectionEvent e) { - info.setReplaceDuplicates(comp.getReplaceSimilarButton().isEnabled()); + public void widgetSelected(SelectionEvent e) { + info.setReplaceDuplicates(((Button) e.widget).getSelection()); } + }); + layouter.perform(checkBox); + + label = new Label(result, SWT.SEPARATOR | SWT.HORIZONTAL); + label.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + layouter.perform(label); + createSignaturePreview(result, layouter); + + Dialog.applyDialogFont(result); + PlatformUI.getWorkbench().getHelpSystem().setHelp(getControl(), + ICHelpContextIds.EXTRACT_FUNCTION_WIZARD_PAGE); + } + + private Text createTextInputField(Composite parent, int style) { + Text result = new Text(parent, style); + result.addModifyListener(new ModifyListener() { @Override - public void widgetSelected(SelectionEvent e) { - widgetDefaultSelected(e); + public void modifyText(ModifyEvent e) { + textModified(getText()); } }); - - setControl(comp); + TextFieldNavigationHandler.install(result); + return result; + } + + private String getText() { + if (textField == null) + return null; + return textField.getText(); } - protected void visibilityChange(String text) { - info.setVisibility(VisibilityEnum.getEnumForStringRepresentation(text)); + private String getLabelText(){ + return Messages.ExtractFunctionInputPage_label_text; } - private void checkName() { - String methodName = comp.getMethodName(); - IdentifierResult result = IdentifierHelper.checkIdentifierName(methodName); - if (result.isCorrect()) { - setErrorMessage(null); - setPageComplete(true); + private void setVisibility(VisibilityEnum visibility) { + info.setVisibility(visibility); + updatePreview(getText()); + } + + private void createSignaturePreview(Composite composite, RowLayouter layouter) { + Label previewLabel = new Label(composite, SWT.NONE); + previewLabel.setText(Messages.ExtractFunctionInputPage_signature_preview); + layouter.perform(previewLabel); + + IPreferenceStore store = CUIPlugin.getDefault().getCombinedPreferenceStore(); + signaturePreview = new CSourceViewer(composite, null, null, false, SWT.READ_ONLY | SWT.V_SCROLL | SWT.WRAP /*| SWT.BORDER*/, store); + signaturePreview.configure(new CSourceViewerConfiguration(CUIPlugin.getDefault().getTextTools().getColorManager(), store, null, null)); + signaturePreview.getTextWidget().setFont(JFaceResources.getFont(PreferenceConstants.EDITOR_TEXT_FONT)); + signaturePreview.adaptBackgroundColor(composite); + signaturePreview.setDocument(signaturePreviewDocument); + signaturePreview.setEditable(false); + + // Layouting problems with wrapped text: see http://bugs.eclipse.org/bugs/show_bug.cgi?id=9866 + Control signaturePreviewControl = signaturePreview.getControl(); + PixelConverter pixelConverter = new PixelConverter(signaturePreviewControl); + GridData gdata = new GridData(GridData.FILL_BOTH); + gdata.widthHint = pixelConverter.convertWidthInCharsToPixels(50); + gdata.heightHint = pixelConverter.convertHeightInCharsToPixels(3); + signaturePreviewControl.setLayoutData(gdata); + layouter.perform(signaturePreviewControl); + } + + private void updatePreview(String methodName) { + if (signaturePreview == null) + return; + + if (methodName.isEmpty()) { + methodName = StubUtility.suggestMethodName("someMethodName", null, //$NON-NLS-1$ + refactoring.getTranslationUnit()); + } + + int top = signaturePreview.getTextWidget().getTopPixel(); + String signature = refactoring.getSignature(methodName); + signaturePreviewDocument.set(signature); + signaturePreview.getTextWidget().setTopPixel(top); + } + + private void loadSettings() { + settings = getDialogSettings().getSection(DIALOG_SETTING_SECTION); + if (settings == null) { + settings = getDialogSettings().addNewSection(DIALOG_SETTING_SECTION); + settings.put(ACCESS_MODIFIER, VisibilityEnum.v_private.toString()); + } + final String accessModifier = settings.get(ACCESS_MODIFIER); + if (accessModifier != null) { + info.setVisibility(VisibilityEnum.getEnumForStringRepresentation(accessModifier)); + } + } + + //---- Input validation ------------------------------------------------------ + + @Override + public void setVisible(boolean visible) { + if (visible) { + if (firstTime) { + firstTime = false; + setPageComplete(false); + updatePreview(getText()); + textField.setFocus(); + } else { + setPageComplete(validatePage(true)); + } + } + super.setVisible(visible); + } + + private void textModified(String methodName) { + info.setMethodName(methodName); + RefactoringStatus status = validatePage(true); + if (!status.hasFatalError()) { + updatePreview(methodName); + } else { + signaturePreviewDocument.set(""); //$NON-NLS-1$ + } + setPageComplete(status); + } + + private void parameterModified() { + updatePreview(getText()); + setPageComplete(validatePage(false)); + } + + private RefactoringStatus validatePage(boolean text) { + RefactoringStatus result = new RefactoringStatus(); + if (text) { + result.merge(validateMethodName()); + result.merge(validateParameters()); } else { - setErrorMessage(Messages.ExtractFunctionInputPage_CheckFunctionName + " " + result.getMessage()); //$NON-NLS-1$ - setPageComplete(false); + result.merge(validateParameters()); + result.merge(validateMethodName()); + } + return result; + } + + private RefactoringStatus validateMethodName() { + RefactoringStatus result = new RefactoringStatus(); + String methodName = getText(); + if (methodName.isEmpty()) { + result.addFatalError(Messages.ExtractFunctionInputPage_validation_empty_function_name); + return result; + } + result.merge(refactoring.checkMethodName()); + return result; + } + + private RefactoringStatus validateParameters() { + RefactoringStatus result = new RefactoringStatus(); + for (NameInformation paramInfo : info.getParameters()) { + if (paramInfo.getNewName().isEmpty()) { + result.addFatalError(Messages.ExtractFunctionInputPage_validation_empty_parameter_name); + return result; + } } + result.merge(refactoring.checkParameterNames()); + return result; } } 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 0395770a62b..3e8b22e9dff 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 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2008, 2010 Institute for Software, HSR Hochschule fuer Technik + * Copyright (c) 2008, 2012 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 @@ -8,15 +8,17 @@ * * Contributors: * Institute for Software - initial API and implementation + * Sergey Prigogin (Google) *******************************************************************************/ package org.eclipse.cdt.internal.ui.refactoring.extractfunction; import java.util.ArrayList; import java.util.HashMap; -import java.util.LinkedList; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.Set; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.ResourcesPlugin; @@ -25,10 +27,13 @@ import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.OperationCanceledException; import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.SubMonitor; +import org.eclipse.core.runtime.preferences.IPreferencesService; import org.eclipse.jface.viewers.ISelection; import org.eclipse.ltk.core.refactoring.RefactoringDescriptor; import org.eclipse.ltk.core.refactoring.RefactoringStatus; +import org.eclipse.osgi.util.NLS; import org.eclipse.text.edits.TextEditGroup; import org.eclipse.cdt.core.dom.ast.ASTVisitor; @@ -56,10 +61,12 @@ import org.eclipse.cdt.core.dom.ast.IASTReturnStatement; import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration; import org.eclipse.cdt.core.dom.ast.IASTStandardFunctionDeclarator; import org.eclipse.cdt.core.dom.ast.IASTStatement; +import org.eclipse.cdt.core.dom.ast.IBasicType; import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IField; import org.eclipse.cdt.core.dom.ast.INodeFactory; import org.eclipse.cdt.core.dom.ast.IParameter; +import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConversionName; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeclSpecifier; @@ -72,8 +79,12 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod; import org.eclipse.cdt.core.dom.rewrite.ASTRewrite; +import org.eclipse.cdt.core.dom.rewrite.TypeHelper; +import org.eclipse.cdt.core.formatter.DefaultCodeFormatterOptions; import org.eclipse.cdt.core.index.IIndex; import org.eclipse.cdt.core.model.ICProject; +import org.eclipse.cdt.ui.CUIPlugin; +import org.eclipse.cdt.ui.PreferenceConstants; import org.eclipse.cdt.internal.core.dom.parser.c.CASTBinaryExpression; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTBinaryExpression; @@ -91,6 +102,8 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTReturnStatement; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTSimpleDeclaration; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTTemplateDeclaration; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPNodeFactory; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil; +import org.eclipse.cdt.internal.core.dom.rewrite.astwriter.ASTWriterVisitor; import org.eclipse.cdt.internal.ui.refactoring.CRefactoring; import org.eclipse.cdt.internal.ui.refactoring.CRefactoringDescription; @@ -99,12 +112,14 @@ import org.eclipse.cdt.internal.ui.refactoring.Container; import org.eclipse.cdt.internal.ui.refactoring.MethodContext; import org.eclipse.cdt.internal.ui.refactoring.MethodContext.ContextType; import org.eclipse.cdt.internal.ui.refactoring.ModificationCollector; +import org.eclipse.cdt.internal.ui.refactoring.NameInformation; import org.eclipse.cdt.internal.ui.refactoring.NodeContainer; -import org.eclipse.cdt.internal.ui.refactoring.NodeContainer.NameInformation; import org.eclipse.cdt.internal.ui.refactoring.utils.ASTHelper; import org.eclipse.cdt.internal.ui.refactoring.utils.CPPASTAllVisitor; +import org.eclipse.cdt.internal.ui.refactoring.utils.Checks; import org.eclipse.cdt.internal.ui.refactoring.utils.NodeHelper; import org.eclipse.cdt.internal.ui.refactoring.utils.SelectionHelper; +import org.eclipse.cdt.internal.ui.viewsupport.BasicElementLabels; public class ExtractFunctionRefactoring extends CRefactoring { public static final String ID = @@ -113,7 +128,7 @@ public class ExtractFunctionRefactoring extends CRefactoring { static final Integer NULL_INTEGER = Integer.valueOf(0); static final char[] ZERO= "0".toCharArray(); //$NON-NLS-1$ - NodeContainer container; + private NodeContainer container; final ExtractFunctionInformation info; final Map<String, Integer> names; @@ -121,12 +136,11 @@ public class ExtractFunctionRefactoring extends CRefactoring { final Container<Integer> trailPos; private final Container<Integer> returnNumber; - protected boolean hasNameResolvingForSimilarError; - HashMap<String, Integer> nameTrail; private ExtractedFunctionConstructionHelper extractedFunctionConstructionHelper; - private final INodeFactory factory = CPPNodeFactory.getDefault(); + private final INodeFactory nodeFactory = CPPNodeFactory.getDefault(); + DefaultCodeFormatterOptions formattingOptions; public ExtractFunctionRefactoring(IFile file, ISelection selection, ExtractFunctionInformation info, ICProject project) { @@ -137,6 +151,7 @@ public class ExtractFunctionRefactoring extends CRefactoring { namesCounter = new Container<Integer>(NULL_INTEGER); trailPos = new Container<Integer>(NULL_INTEGER); returnNumber = new Container<Integer>(NULL_INTEGER); + formattingOptions = new DefaultCodeFormatterOptions(project.getOptions(true)); } @Override @@ -170,18 +185,32 @@ public class ExtractFunctionRefactoring extends CRefactoring { if (isProgressMonitorCanceld(sm, initStatus)) return initStatus; - info.setParameterCandidates(container.getParameterCandidates()); - sm.worked(1); - - if (isProgressMonitorCanceld(sm, initStatus)) - return initStatus; - List<NameInformation> returnValueCandidates = container.getReturnValueCandidates(); if (returnValueCandidates.size() > 1) { initStatus.addFatalError(Messages.ExtractFunctionRefactoring_TooManySelected); + return initStatus; } else if (returnValueCandidates.size() == 1) { info.setMandatoryReturnVariable(returnValueCandidates.get(0)); } + sm.worked(1); + + if (isProgressMonitorCanceld(sm, initStatus)) + return initStatus; + + info.setParameters(container.getParameterCandidates()); + initStatus.merge(checkParameterAndReturnTypes()); + if (initStatus.hasFatalError()) + return initStatus; + + if (info.getMandatoryReturnVariable() == null) { + chooseReturnVariable(); + } + + IPreferencesService preferences = Platform.getPreferencesService(); + final boolean outFirst = preferences.getBoolean(CUIPlugin.PLUGIN_ID, + PreferenceConstants.FUNCTION_OUTPUT_PARAMETERS_BEFORE_INPUT, false, + PreferenceConstants.getPreferenceScopes(project.getProject())); + info.sortParameters(outFirst); extractedFunctionConstructionHelper = ExtractedFunctionConstructionHelper.createFor(container.getNodesToWrite()); @@ -204,6 +233,28 @@ public class ExtractFunctionRefactoring extends CRefactoring { return initStatus; } + private void chooseReturnVariable() { + NameInformation candidate = null; + for (NameInformation param : info.getParameters()) { + if (param.isOutput()) { + IASTDeclarator declarator = param.getDeclarator(); + IType type = TypeHelper.createType(declarator); + type = SemanticUtil.getNestedType(type, SemanticUtil.CVTYPE | SemanticUtil.TDEF); + if (type instanceof IBasicType) { + if (((IBasicType) type).getKind() == IBasicType.Kind.eBoolean) { + param.setReturnValue(true); + return; + } + } + if (candidate == null && !TypeHelper.shouldBePassedByReference(type, ast)) { + candidate = param; + } + } + } + if (candidate != null) + candidate.setReturnValue(true); + } + private void checkForNonExtractableStatements(NodeContainer cont, RefactoringStatus status) { NonExtractableStmtFinder finder = new NonExtractableStmtFinder(); for (IASTNode node : cont.getNodesToWrite()) { @@ -259,15 +310,10 @@ public class ExtractFunctionRefactoring extends CRefactoring { IASTSimpleDeclaration methodDeclaration = getDeclaration(astMethodName); if (isMethodAllreadyDefined(methodDeclaration, classDeclaration, getIndex())) { - finalConditions.addError(Messages.ExtractFunctionRefactoring_NameInUse); + finalConditions.addError(Messages.ExtractFunctionRefactoring_name_in_use); return finalConditions; } } - for (NameInformation name : info.getParameterCandidates()) { - if (name.isReturnValue()) { - info.setReturnVariable(name); - } - } } finally { unlockIndex(); } @@ -278,9 +324,8 @@ public class ExtractFunctionRefactoring extends CRefactoring { } @Override - protected void collectModifications(IProgressMonitor pm, - ModificationCollector collector) throws CoreException, - OperationCanceledException { + protected void collectModifications(IProgressMonitor pm, ModificationCollector collector) + throws CoreException, OperationCanceledException { try { lockIndex(); try { @@ -298,10 +343,9 @@ public class ExtractFunctionRefactoring extends CRefactoring { final IFile implementationFile = ResourcesPlugin.getWorkspace().getRoot().getFileForLocation(implPath); - createMethodDefinition(astMethodName, context, firstNode, implementationFile, - collector); + createMethodDefinition(astMethodName, context, firstNode, collector); - createMethodCalls(astMethodName, implementationFile, context, collector); + createMethodCalls(astMethodName, context, collector); } finally { unlockIndex(); } @@ -310,8 +354,7 @@ public class ExtractFunctionRefactoring extends CRefactoring { } } - private void createMethodCalls(final IASTName astMethodName, - final IFile implementationFile, MethodContext context, + private void createMethodCalls(final IASTName astMethodName, MethodContext context, ModificationCollector collector) throws CoreException { String title; if (context.getType() == MethodContext.ContextType.METHOD) { @@ -326,15 +369,15 @@ public class ExtractFunctionRefactoring extends CRefactoring { ASTRewrite rewriter = collector.rewriterForTranslationUnit( firstNodeToWrite.getTranslationUnit()); TextEditGroup editGroup = new TextEditGroup(title); - if (methodCall instanceof IASTDeclaration){ + if (methodCall instanceof IASTDeclaration) { CPPASTDeclarationStatement declarationStatement = new CPPASTDeclarationStatement((IASTDeclaration) methodCall); methodCall = declarationStatement; } - insertCallintoTree(methodCall, container.getNodesToWrite(), rewriter, editGroup); + insertCallIntoTree(methodCall, container.getNodesToWrite(), rewriter, editGroup); if (info.isReplaceDuplicates()) { - replaceSimilar(collector, astMethodName, implementationFile, context.getType()); + replaceSimilar(collector, astMethodName); } for (IASTNode node : container.getNodesToWrite()) { @@ -344,8 +387,8 @@ public class ExtractFunctionRefactoring extends CRefactoring { } } - private void insertCallintoTree(IASTNode methodCall, List<IASTNode> list, - ASTRewrite rewriter, TextEditGroup editGroup) { + private void insertCallIntoTree(IASTNode methodCall, List<IASTNode> list, ASTRewrite rewriter, + TextEditGroup editGroup) { IASTNode firstNode = list.get(0); if (list.size() > 1 && firstNode.getParent() instanceof IASTBinaryExpression && firstNode.getParent().getParent() instanceof IASTBinaryExpression) { @@ -372,9 +415,8 @@ public class ExtractFunctionRefactoring extends CRefactoring { return binExp; } - private void createMethodDefinition(final IASTName astMethodName, - MethodContext context, IASTNode firstNode, - final IFile implementationFile, ModificationCollector collector) { + private void createMethodDefinition(final IASTName astMethodName, MethodContext context, + IASTNode firstNode, ModificationCollector collector) { IASTFunctionDefinition node = NodeHelper.findFunctionDefinitionInAncestors(firstNode); if (node != null) { String title; @@ -400,32 +442,39 @@ public class ExtractFunctionRefactoring extends CRefactoring { methodDeclaration, false, collector); } - private void replaceSimilar(ModificationCollector collector, final IASTName astMethodName, - final IFile implementationFile, final ContextType contextType) { + private void replaceSimilar(ModificationCollector collector, IASTName astMethodName) { // Find similar code - final List<IASTNode> nodesToRewriteWithoutComments = new LinkedList<IASTNode>(); + final List<IASTNode> nodesToRewriteWithoutComments = getNodesWithoutComments(container.getNodesToWrite()); + final List<IASTNode> initTrail = getTrail(nodesToRewriteWithoutComments); + ast.accept(new SimilarReplacerVisitor(this, container, collector, initTrail, astMethodName, + nodesToRewriteWithoutComments)); + } - for (IASTNode node : container.getNodesToWrite()) { - if (!(node instanceof IASTComment)) { - nodesToRewriteWithoutComments.add(node); + public int getNumberOfDuplicates() { + final List<IASTNode> nodesToRewriteWithoutComments = getNodesWithoutComments(container.getNodesToWrite()); + final List<IASTNode> initTrail = getTrail(nodesToRewriteWithoutComments); + final int[] count = new int[1]; + ast.accept(new SimilarFinderVisitor(this, container, initTrail, nodesToRewriteWithoutComments) { + @Override + protected void foundSimilar() { + ++count[0]; } - } + }); + return count[0]; + } - final List<IASTNode> initTrail = getTrail(nodesToRewriteWithoutComments); - final String title; - if (contextType == MethodContext.ContextType.METHOD) { - title = Messages.ExtractFunctionRefactoring_CreateMethodCall; - } else { - title = Messages.ExtractFunctionRefactoring_CreateFunctionCall; - } + private List<IASTNode> getNodesWithoutComments(List<IASTNode> nodes) { + final List<IASTNode> nodesWithoutComments = new ArrayList<IASTNode>(nodes.size()); - if (!hasNameResolvingForSimilarError) { - ast.accept(new SimilarFinderVisitor(this, collector, initTrail, implementationFile, - astMethodName, nodesToRewriteWithoutComments, title)); + for (IASTNode node : nodes) { + if (!(node instanceof IASTComment)) { + nodesWithoutComments.add(node); + } } + return nodesWithoutComments; } - protected List<IASTNode> getTrail(List<IASTNode> stmts) { + private List<IASTNode> getTrail(List<IASTNode> stmts) { final List<IASTNode> trail = new ArrayList<IASTNode>(); nameTrail = new HashMap<String, Integer>(); final Container<Integer> trailCounter = new Container<Integer>(NULL_INTEGER); @@ -590,7 +639,7 @@ public class ExtractFunctionRefactoring extends CRefactoring { IASTStandardFunctionDeclarator createdFunctionDeclarator = extractedFunctionConstructionHelper.createFunctionDeclarator(qname, info.getDeclarator(), info.getReturnVariable(), container.getNodesToWrite(), - info.getParameterCandidates(), ast.getASTNodeFactory()); + info.getParameters(), ast.getASTNodeFactory()); func.setDeclarator(createdFunctionDeclarator); IASTCompoundStatement compound = new CPPASTCompoundStatement(); @@ -619,18 +668,13 @@ public class ExtractFunctionRefactoring extends CRefactoring { NameInformation returnVariable = info.getReturnVariable(); if (returnVariable != null) { IASTReturnStatement returnStmt = new CPPASTReturnStatement(); - if (returnVariable.getDeclaration().getParent() instanceof IASTExpression) { - IASTExpression returnValue = (IASTExpression) returnVariable.getDeclaration().getParent(); - returnStmt.setReturnValue(returnValue); + IASTIdExpression expr = new CPPASTIdExpression(); + if (returnVariable.getNewName() == null) { + expr.setName(newName(returnVariable.getName())); } else { - IASTIdExpression expr = new CPPASTIdExpression(); - if (returnVariable.getUserSetName() == null) { - expr.setName(newName(returnVariable.getName())); - } else { - expr.setName(new CPPASTName(returnVariable.getUserSetName().toCharArray())); - } - returnStmt.setReturnValue(expr); + expr.setName(new CPPASTName(returnVariable.getNewName().toCharArray())); } + returnStmt.setReturnValue(expr); subRW.insertBefore(compound, null, returnStmt, group); } } @@ -646,8 +690,7 @@ public class ExtractFunctionRefactoring extends CRefactoring { returnVariable); } - protected IASTNode getMethodCall(IASTName astMethodName, - Map<String, Integer> trailNameTable, + protected IASTNode getMethodCall(IASTName astMethodName, Map<String, Integer> trailNameTable, Map<String, Integer> similarNameTable, NodeContainer myContainer, NodeContainer mySimilarContainer) { IASTExpressionStatement stmt = new CPPASTExpressionStatement(); @@ -656,12 +699,12 @@ public class ExtractFunctionRefactoring extends CRefactoring { idExpression.setName(astMethodName); List<IASTInitializerClause> args = new ArrayList<IASTInitializerClause>(); - List<IASTName> declarations = new ArrayList<IASTName>(); + Set<IASTName> declarations = new HashSet<IASTName>(); IASTName retName = null; boolean theRetName = false; - for (NameInformation nameInfo : myContainer.getNames()) { - Integer trailSeqNumber = trailNameTable.get(nameInfo.getDeclaration().getRawSignature()); + for (NameInformation nameInfo : info.getParameters()) { + Integer trailSeqNumber = trailNameTable.get(nameInfo.getDeclarationName().getRawSignature()); String origName = null; for (Entry<String, Integer> entry : similarNameTable.entrySet()) { if (entry.getValue().equals(trailSeqNumber)) { @@ -676,14 +719,14 @@ public class ExtractFunctionRefactoring extends CRefactoring { if (origName != null) { boolean found = false; for (NameInformation simNameInfo : mySimilarContainer.getNames()) { - if (origName.equals(simNameInfo.getDeclaration().getRawSignature())) { + if (origName.equals(simNameInfo.getDeclarationName().getRawSignature())) { addParameterIfPossible(args, declarations, simNameInfo); found = true; if (theRetName) { theRetName = false; retName = new CPPASTName( - simNameInfo.getDeclaration().getRawSignature().toCharArray()); + simNameInfo.getDeclarationName().getRawSignature().toCharArray()); } } } @@ -733,7 +776,7 @@ public class ExtractFunctionRefactoring extends CRefactoring { IASTFunctionCallExpression callExpression, IASTName retname) { if (info.getReturnVariable().equals(info.getMandatoryReturnVariable())) { IASTSimpleDeclaration orgDecl = NodeHelper.findSimpleDeclarationInParents(info - .getReturnVariable().getDeclaration()); + .getReturnVariable().getDeclarationName()); IASTSimpleDeclaration decl = new CPPASTSimpleDeclaration(); decl.setDeclSpecifier(orgDecl.getDeclSpecifier().copy(CopyStyle.withLocations)); @@ -775,14 +818,14 @@ public class ExtractFunctionRefactoring extends CRefactoring { IASTStandardFunctionDeclarator declarator = extractedFunctionConstructionHelper.createFunctionDeclarator(name, info.getDeclarator(), info.getReturnVariable(), container.getNodesToWrite(), - info.getParameterCandidates(), ast.getASTNodeFactory()); + info.getParameters(), ast.getASTNodeFactory()); simpleDecl.addDeclarator(declarator); return simpleDecl; } private IASTSimpleDeclaration getDeclaration(ModificationCollector collector, IASTName name) { IASTDeclSpecifier declSpec = getReturnType(); - IASTSimpleDeclaration simpleDecl = factory.newSimpleDeclaration(declSpec); + IASTSimpleDeclaration simpleDecl = nodeFactory.newSimpleDeclaration(declSpec); if (info.isVirtual() && declSpec instanceof ICPPASTDeclSpecifier) { ((ICPPASTDeclSpecifier) declSpec).setVirtual(true); } @@ -790,7 +833,7 @@ public class ExtractFunctionRefactoring extends CRefactoring { IASTStandardFunctionDeclarator declarator = extractedFunctionConstructionHelper.createFunctionDeclarator(name, info.getDeclarator(), info.getReturnVariable(), container.getNodesToWrite(), - info.getParameterCandidates(), ast.getASTNodeFactory()); + info.getParameters(), ast.getASTNodeFactory()); simpleDecl.addDeclarator(declarator); return simpleDecl; } @@ -826,19 +869,18 @@ public class ExtractFunctionRefactoring extends CRefactoring { public List<IASTInitializerClause> getCallParameters() { List<IASTInitializerClause> args = new ArrayList<IASTInitializerClause>(); - List<IASTName> declarations = new ArrayList<IASTName>(); - for (NameInformation nameInfo : container.getNames()) { + Set<IASTName> declarations = new HashSet<IASTName>(); + for (NameInformation nameInfo : info.getParameters()) { addParameterIfPossible(args, declarations, nameInfo); } return args; } - private void addParameterIfPossible(List<IASTInitializerClause> args, - List<IASTName> declarations, NameInformation nameInfo) { - if (!nameInfo.isDeclaredInSelection()) { - IASTName declaration = nameInfo.getDeclaration(); - if (!declarations.contains(declaration)) { - declarations.add(declaration); + private void addParameterIfPossible(List<IASTInitializerClause> args, Set<IASTName> declarations, + NameInformation nameInfo) { + if (!container.isDeclaredInSelection(nameInfo)) { + IASTName declaration = nameInfo.getDeclarationName(); + if (declarations.add(declaration)) { IASTIdExpression expression = new CPPASTIdExpression(); expression.setName(newName(declaration)); args.add(expression); @@ -866,4 +908,119 @@ public class ExtractFunctionRefactoring extends CRefactoring { Boolean.toString(info.isReplaceDuplicates())); return arguments; } + + public ExtractFunctionInformation getRefactoringInfo() { + return info; + } + + /** + * Checks if the new method name is a valid method name. This method doesn't + * check if a method with the same name already exists in the hierarchy. + * @return validation status + */ + public RefactoringStatus checkMethodName() { + return Checks.checkIdentifier(info.getMethodName(), tu); + } + + /** + * Checks if the parameter names are valid. + * @return validation status + */ + public RefactoringStatus checkParameterNames() { + RefactoringStatus result= new RefactoringStatus(); + List<NameInformation> parameters = info.getParameters(); + Set<String> usedNames = new HashSet<String>(); + Set<IASTName> declarations = new HashSet<IASTName>(); + for (NameInformation nameInfo : container.getNames()) { + IASTName declaration = nameInfo.getDeclarationName(); + if (declarations.add(declaration) && !parameters.contains(nameInfo)) { + usedNames.add(String.valueOf(nameInfo.getName().getSimpleID())); + } + } + for (NameInformation parameter : parameters) { + result.merge(Checks.checkIdentifier(parameter.getNewName(), tu)); + for (NameInformation other : parameters) { + if (parameter != other && other.getNewName().equals(parameter.getNewName())) { + result.addError(NLS.bind(Messages.ExtractFunctionRefactoring_duplicate_parameter, + BasicElementLabels.getCElementName(other.getNewName()))); + return result; + } + } + if (parameter.isRenamed() && usedNames.contains(parameter.getNewName())) { + result.addError(NLS.bind(Messages.ExtractFunctionRefactoring_parameter_name_in_use, + BasicElementLabels.getCElementName(parameter.getNewName()))); + return result; + } + } + return result; + } + + /** + * Checks if the parameter names are valid. + * @return validation status + */ + public RefactoringStatus checkParameterAndReturnTypes() { + RefactoringStatus result= new RefactoringStatus(); + for (NameInformation parameter : info.getParameters()) { + String typeName = parameter.getTypeName(); + if (typeName == null || typeName.isEmpty()) { + result.addError(NLS.bind(Messages.ExtractFunctionRefactoring_invalid_type, + BasicElementLabels.getCElementName(parameter.getNewName()))); + return result; + } + } + return result; + } + + /** + * Returns the signature of the new method. + * + * @param methodName the method name used for the new method + * @return the signature of the extracted method + */ + public String getSignature(String methodName) { + StringBuilder buf = new StringBuilder(); + NameInformation returnVariable = info.getReturnVariable(); + if (returnVariable != null) { + String type = returnVariable.getReturnType(); + if (type != null) { + buf.append(type); + } else { + buf.append("<unknown type>"); //$NON-NLS-1$ + } + } else { + buf.append("void"); //$NON-NLS-1$ + } + buf.append(' '); + buf.append(methodName); + if (formattingOptions.insert_space_before_opening_paren_in_method_declaration) + buf.append(' '); + buf.append('('); + List<NameInformation> parameters = info.getParameters(); + if (!parameters.isEmpty()) { + if (formattingOptions.insert_space_after_opening_paren_in_method_declaration) + buf.append(' '); + boolean first = true; + for (NameInformation parameter : parameters) { + if (!first) { + if (formattingOptions.insert_space_before_comma_in_method_declaration_parameters) + buf.append(' '); + buf.append(','); + if (formattingOptions.insert_space_after_comma_in_method_declaration_parameters) + buf.append(' '); + } + IASTParameterDeclaration declaration = parameter.getParameterDeclaration(nodeFactory); + ASTWriterVisitor writer = new ASTWriterVisitor(); + declaration.accept(writer); + buf.append(writer.toString()); + first = false; + } + if (formattingOptions.insert_space_before_closing_paren_in_method_declaration) + buf.append(' '); + } else if (formattingOptions.insert_space_between_empty_parens_in_method_declaration) { + buf.append(' '); + } + buf.append(')'); + return buf.toString(); + } } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/ExtractFunctionRefactoringRunner.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/ExtractFunctionRefactoringRunner.java index c7eeb3dbc38..91efd5ab562 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/ExtractFunctionRefactoringRunner.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/ExtractFunctionRefactoringRunner.java @@ -8,6 +8,7 @@ * * Contributors: * Institute for Software - initial API and implementation + * Sergey Prigogin (Google) *******************************************************************************/ package org.eclipse.cdt.internal.ui.refactoring.extractfunction; @@ -18,7 +19,6 @@ import org.eclipse.ltk.ui.refactoring.RefactoringWizardOpenOperation; import org.eclipse.cdt.core.model.ICProject; -import org.eclipse.cdt.internal.ui.refactoring.CRefactoring; import org.eclipse.cdt.internal.ui.refactoring.RefactoringRunner; /** @@ -35,8 +35,8 @@ public class ExtractFunctionRefactoringRunner extends RefactoringRunner { public void run() { ExtractFunctionInformation info = new ExtractFunctionInformation(); - CRefactoring refactoring = new ExtractFunctionRefactoring(file,selection,info, project); - ExtractFunctionRefactoringWizard wizard = new ExtractFunctionRefactoringWizard(refactoring,info); + ExtractFunctionRefactoring refactoring = new ExtractFunctionRefactoring(file, selection, info, project); + ExtractFunctionWizard wizard = new ExtractFunctionWizard(refactoring); RefactoringWizardOpenOperation operator = new RefactoringWizardOpenOperation(wizard); try { diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/ExtractFunctionRefactoringWizard.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/ExtractFunctionWizard.java index 4a09919e84f..28581b23025 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/ExtractFunctionRefactoringWizard.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/ExtractFunctionWizard.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2008 Institute for Software, HSR Hochschule fuer Technik + * Copyright (c) 2008, 2012 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 @@ -8,27 +8,24 @@ * * Contributors: * Institute for Software - initial API and implementation + * Sergey Prigogin (Google) *******************************************************************************/ package org.eclipse.cdt.internal.ui.refactoring.extractfunction; -import org.eclipse.ltk.core.refactoring.Refactoring; import org.eclipse.ltk.ui.refactoring.RefactoringWizard; -import org.eclipse.ltk.ui.refactoring.UserInputWizardPage; -public class ExtractFunctionRefactoringWizard extends RefactoringWizard { - private final ExtractFunctionInformation info; +import org.eclipse.cdt.ui.CUIPlugin; - public ExtractFunctionRefactoringWizard(Refactoring refactoring, ExtractFunctionInformation info) { - super(refactoring, WIZARD_BASED_USER_INTERFACE); - this.info = info; +public class ExtractFunctionWizard extends RefactoringWizard { + public ExtractFunctionWizard(ExtractFunctionRefactoring refactoring) { + super(refactoring, DIALOG_BASED_USER_INTERFACE | PREVIEW_EXPAND_FIRST_NODE); + setDefaultPageTitle(Messages.ExtractFunctionWizard_extract_function); + setDialogSettings(CUIPlugin.getDefault().getDialogSettings()); } @Override protected void addUserInputPages() { - UserInputWizardPage page = new ExtractFunctionInputPage( - Messages.ExtractFunctionRefactoringWizard_FunctionName,info); - page.setTitle(Messages.ExtractFunctionRefactoringWizard_FunctionName); - addPage(page); + addPage(new ExtractFunctionInputPage()); } } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/ExtractStatement.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/ExtractStatement.java index 221b6a47bc8..4839c7379b5 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/ExtractStatement.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/ExtractStatement.java @@ -26,7 +26,7 @@ import org.eclipse.cdt.core.dom.rewrite.ASTRewrite; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTSimpleDeclSpecifier; -import org.eclipse.cdt.internal.ui.refactoring.NodeContainer.NameInformation; +import org.eclipse.cdt.internal.ui.refactoring.NameInformation; import org.eclipse.cdt.internal.ui.refactoring.utils.ASTHelper; /** @@ -45,7 +45,7 @@ public class ExtractStatement extends ExtractedFunctionConstructionHelper { public IASTDeclSpecifier determineReturnType(IASTNode extractedNode, NameInformation returnVariable) { if (returnVariable != null) { - IASTNode decl = ASTHelper.getDeclarationForNode(returnVariable.getDeclaration()); + IASTNode decl = ASTHelper.getDeclarationForNode(returnVariable.getDeclarationName()); return ASTHelper.getDeclarationSpecifier(decl).copy(CopyStyle.withLocations); } IASTDeclSpecifier declSpec = new CPPASTSimpleDeclSpecifier(); diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/ExtractedFunctionConstructionHelper.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/ExtractedFunctionConstructionHelper.java index b39f76cdda3..ab3f2637d12 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/ExtractedFunctionConstructionHelper.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/ExtractedFunctionConstructionHelper.java @@ -32,7 +32,7 @@ import org.eclipse.cdt.core.dom.ast.INodeFactory; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator; import org.eclipse.cdt.core.dom.rewrite.ASTRewrite; -import org.eclipse.cdt.internal.ui.refactoring.NodeContainer.NameInformation; +import org.eclipse.cdt.internal.ui.refactoring.NameInformation; /** * @author Mirko Stocker @@ -73,7 +73,7 @@ public abstract class ExtractedFunctionConstructionHelper { } if (returnVariable != null) { - IASTDeclarator decl = (IASTDeclarator) returnVariable.getDeclaration().getParent(); + IASTDeclarator decl = returnVariable.getDeclarator(); IASTPointerOperator[] pointers = decl.getPointerOperators(); for (IASTPointerOperator operator : pointers) { declarator.addPointerOperator(operator.copy(CopyStyle.withLocations)); @@ -94,8 +94,8 @@ public abstract class ExtractedFunctionConstructionHelper { public List<IASTParameterDeclaration> getParameterDeclarations( Collection<NameInformation> parameterNames, INodeFactory nodeFactory) { List<IASTParameterDeclaration> result = new ArrayList<IASTParameterDeclaration>(parameterNames.size()); - for (NameInformation name : parameterNames) { - result.add(name.getParameterDeclaration(nodeFactory)); + for (NameInformation param : parameterNames) { + result.add(param.getParameterDeclaration(nodeFactory)); } return result; } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/Messages.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/Messages.java index 1efab26346e..b73937cdc38 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/Messages.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/Messages.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2008, 2009 Institute for Software, HSR Hochschule fuer Technik + * Copyright (c) 2008, 2012 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 @@ -8,35 +8,40 @@ * * Contributors: * Institute for Software - initial API and implementation + * Sergey Prigogin (Google) *******************************************************************************/ package org.eclipse.cdt.internal.ui.refactoring.extractfunction; import org.eclipse.osgi.util.NLS; public final class Messages extends NLS { - public static String ExtractFunctionRefactoringWizard_FunctionName; + public static String ExtractFunctionWizard_extract_function; public static String ExtractFunctionRefactoring_ExtractFunction; public static String ExtractFunctionRefactoring_NoStmtSelected; public static String ExtractFunctionRefactoring_TooManySelected; - public static String ExtractFunctionRefactoring_NameInUse; + public static String ExtractFunctionRefactoring_name_in_use; + public static String ExtractFunctionRefactoring_parameter_name_in_use; + public static String ExtractFunctionRefactoring_duplicate_parameter; + public static String ExtractFunctionRefactoring_invalid_type; public static String ExtractFunctionComposite_MethodName; public static String ExtractFunctionComposite_FunctionName; - public static String ExtractFunctionInputPage_EnterName; - public static String ExtractFunctionInputPage_CheckFunctionName; - public static String ExtractFunctionInputPage_1; - public static String ExtractFunctionComposite_ReturnValue; + public static String ExtractFunctionInputPage_description; + public static String ExtractFunctionInputPage_access_modifier; + public static String ExtractFunctionInputPage_public; + public static String ExtractFunctionInputPage_protected; + public static String ExtractFunctionInputPage_private; + public static String ExtractFunctionInputPage_signature_preview; + public static String ExtractFunctionInputPage_label_text; + public static String ExtractFunctionInputPage_parameters; + public static String ExtractFunctionInputPage_validation_empty_function_name; + public static String ExtractFunctionInputPage_validation_empty_parameter_name; + public static String ExtractFunctionInputPage_duplicates_none; + public static String ExtractFunctionInputPage_duplicates_single; + public static String ExtractFunctionInputPage_duplicates_multi; public static String ExtractFunctionRefactoring_CreateMethodDef; public static String ExtractFunctionRefactoring_CreateFunctionDef; - public static String ExtractFunctionComposite_ReplaceDuplicates; - public static String ExtractFunctionComposite_Virtual; public static String ExtractFunctionRefactoring_CreateMethodCall; public static String ExtractFunctionRefactoring_CreateFunctionCall; - public static String ChooserComposite_Return; - public static String ChooserComposite_CallByRef; - public static String ChooserComposite_const; - public static String ChooserComposite_Name; - public static String ChooserComposite_Type; - public static String ChooserComposite_NoReturnValue; public static String ExtractFunctionRefactoring_Error_Return; public static String ExtractFunctionRefactoring_Error_Continue; public static String ExtractFunctionRefactoring_Error_Break; diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/Messages.properties b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/Messages.properties index 05eade15df2..0c6e4be892b 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/Messages.properties +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/Messages.properties @@ -1,5 +1,5 @@ ############################################################################### -# Copyright (c) 2008, 2009 Institute for Software, HSR Hochschule fuer Technik +# Copyright (c) 2008, 2012 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 @@ -7,31 +7,36 @@ # http://www.eclipse.org/legal/epl-v10.html # # Contributors: -# Institute for Software - initial API and implementation +# Institute for Software - initial API and implementation +# Sergey Prigogin (Google) ############################################################################### -ExtractFunctionRefactoringWizard_FunctionName=Function Name +ExtractFunctionWizard_extract_function=Extract Function ExtractFunctionRefactoring_ExtractFunction=Extract Function ExtractFunctionRefactoring_NoStmtSelected=No statement selected ExtractFunctionRefactoring_TooManySelected=Too many declarations in selection. -ExtractFunctionRefactoring_NameInUse=Name already in use. +ExtractFunctionRefactoring_name_in_use=Name already in use. +ExtractFunctionRefactoring_parameter_name_in_use=''{0}'' is already used as a name in the selected code +ExtractFunctionRefactoring_duplicate_parameter=A parameter ''{0}'' already exists +ExtractFunctionRefactoring_invalid_type=Unable to determine type of ''{0}'' ExtractFunctionComposite_MethodName=Method &name: ExtractFunctionComposite_FunctionName=Function &name: -ExtractFunctionInputPage_EnterName=Enter a name -ExtractFunctionInputPage_CheckFunctionName=Check Function Name: -ExtractFunctionInputPage_1=is used after the extracted block - it needs to be passed by reference or must be the return value. -ExtractFunctionComposite_ReturnValue=Return value: +ExtractFunctionInputPage_description=Enter new method name and specify the method's visibility +ExtractFunctionInputPage_access_modifier=&Access modifier: +ExtractFunctionInputPage_public=public +ExtractFunctionInputPage_protected=protected +ExtractFunctionInputPage_private=private +ExtractFunctionInputPage_signature_preview=Function signature preview: +ExtractFunctionInputPage_label_text=Function &name: +ExtractFunctionInputPage_parameters=&Parameters: +ExtractFunctionInputPage_validation_empty_function_name=Provide a method name +ExtractFunctionInputPage_validation_empty_parameter_name=Parameter names cannot be empty +ExtractFunctionInputPage_duplicates_none=&Replace additional occurrences of statements with method +ExtractFunctionInputPage_duplicates_single=&Replace 1 additional occurrence of statements with method +ExtractFunctionInputPage_duplicates_multi=&Replace {0} additional occurrences of statements with method ExtractFunctionRefactoring_CreateMethodDef=Create Method Definition ExtractFunctionRefactoring_CreateFunctionDef=Create Function Definition -ExtractFunctionComposite_ReplaceDuplicates=Replace all occurrences of statements with method. -ExtractFunctionComposite_Virtual=virtual ExtractFunctionRefactoring_CreateMethodCall=Create Method Call ExtractFunctionRefactoring_CreateFunctionCall=Create Function Call -ChooserComposite_Return=Return -ChooserComposite_CallByRef=Call by Reference -ChooserComposite_const=const -ChooserComposite_Name=Name -ChooserComposite_Type=Type -ChooserComposite_NoReturnValue=No return-value (void) ExtractFunctionRefactoring_Error_Return=Extracting return statements is not supported ExtractFunctionRefactoring_Error_Continue=Extracting cotinue statements without the surrounding loop is not possible. Please adjust your selection. ExtractFunctionRefactoring_Error_Break=Extracting break statements without the surrounding loop is not possible. Please adjust your selection. diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/SimilarFinderVisitor.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/SimilarFinderVisitor.java index 7edab6b0817..52ebaa030be 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/SimilarFinderVisitor.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/SimilarFinderVisitor.java @@ -16,39 +16,28 @@ import java.util.ArrayList; import java.util.List; import java.util.Map.Entry; -import org.eclipse.core.resources.IFile; -import org.eclipse.text.edits.TextEditGroup; - import org.eclipse.cdt.core.dom.ast.ASTVisitor; -import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IASTStatement; -import org.eclipse.cdt.core.dom.rewrite.ASTRewrite; -import org.eclipse.cdt.internal.ui.refactoring.ModificationCollector; +import org.eclipse.cdt.internal.ui.refactoring.NameInformation; import org.eclipse.cdt.internal.ui.refactoring.NodeContainer; -import org.eclipse.cdt.internal.ui.refactoring.NodeContainer.NameInformation; - -final class SimilarFinderVisitor extends ASTVisitor { - private final ExtractFunctionRefactoring refactoring; +abstract class SimilarFinderVisitor extends ASTVisitor { + protected final ExtractFunctionRefactoring refactoring; + protected final NodeContainer extractedNodes; + protected NodeContainer similarContainer; + protected final List<IASTStatement> stmtToReplace = new ArrayList<IASTStatement>(); private final List<IASTNode> trail; - private final IASTName name; private final List<IASTNode> statements; private int statementCount; - private NodeContainer similarContainer; - private final List<IASTStatement> stmtToReplace = new ArrayList<IASTStatement>(); - - private final ModificationCollector collector; - SimilarFinderVisitor(ExtractFunctionRefactoring refactoring, ModificationCollector collector, - List<IASTNode> trail, IFile file, IASTName name, List<IASTNode> statements, - String title) { + SimilarFinderVisitor(ExtractFunctionRefactoring refactoring, NodeContainer extractedNodes, + List<IASTNode> trail, List<IASTNode> statements) { this.refactoring = refactoring; + this.extractedNodes = extractedNodes; this.trail = trail; - this.name = name; this.statements = statements; - this.collector = collector; this.similarContainer = new NodeContainer(); shouldVisitStatements = true; } @@ -65,8 +54,8 @@ final class SimilarFinderVisitor extends ASTVisitor { // Found similar code boolean similarOnReturnWays = true; for (NameInformation nameInfo : similarContainer.getParameterCandidates()) { - if (refactoring.names.containsKey(nameInfo.getDeclaration().getRawSignature())) { - Integer nameOrderNumber = refactoring.names.get(nameInfo.getDeclaration().getRawSignature()); + if (refactoring.names.containsKey(nameInfo.getDeclarationName().getRawSignature())) { + Integer nameOrderNumber = refactoring.names.get(nameInfo.getDeclarationName().getRawSignature()); if (refactoring.nameTrail.containsValue(nameOrderNumber)) { String orgName = null; boolean found = false; @@ -77,9 +66,9 @@ final class SimilarFinderVisitor extends ASTVisitor { } } if (orgName != null) { - for (NameInformation orgNameInfo : refactoring.container.getParameterCandidates()) { - if (orgName.equals(orgNameInfo.getDeclaration().getRawSignature()) && - (orgNameInfo.mustBeOutput() || !nameInfo.mustBeOutput())) { + for (NameInformation orgNameInfo : extractedNodes.getParameterCandidates()) { + if (orgName.equals(orgNameInfo.getDeclarationName().getRawSignature()) && + (orgNameInfo.isOutput() || !nameInfo.isOutput())) { found = true; break; } @@ -94,17 +83,7 @@ final class SimilarFinderVisitor extends ASTVisitor { } if (similarOnReturnWays) { - IASTNode call = refactoring.getMethodCall(name, refactoring.nameTrail, - refactoring.names, refactoring.container, similarContainer); - ASTRewrite rewrite = - collector.rewriterForTranslationUnit(stmtToReplace.get(0).getTranslationUnit()); - TextEditGroup editGroup = new TextEditGroup(Messages.SimilarFinderVisitor_replaceDuplicateCode); - rewrite.replace(stmtToReplace.get(0), call, editGroup); - if (stmtToReplace.size() > 1) { - for (int i = 1; i < stmtToReplace.size(); ++i) { - rewrite.remove(stmtToReplace.get(i), editGroup); - } - } + foundSimilar(); } clear(); } @@ -115,8 +94,10 @@ final class SimilarFinderVisitor extends ASTVisitor { } } + protected abstract void foundSimilar(); + private boolean isInSelection(IASTStatement stmt) { - List<IASTNode>nodes = refactoring.container.getNodesToWrite(); + List<IASTNode>nodes = extractedNodes.getNodesToWrite(); for (IASTNode node : nodes) { if (node.equals(stmt)) { return true; diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/SimilarReplacerVisitor.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/SimilarReplacerVisitor.java new file mode 100644 index 00000000000..bb44ec06365 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/extractfunction/SimilarReplacerVisitor.java @@ -0,0 +1,50 @@ +/******************************************************************************* + * Copyright (c) 2010 Google, Inc 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: + * Sergey Prigogin (Google) - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.ui.refactoring.extractfunction; + +import java.util.List; + +import org.eclipse.text.edits.TextEditGroup; + +import org.eclipse.cdt.core.dom.ast.IASTName; +import org.eclipse.cdt.core.dom.ast.IASTNode; +import org.eclipse.cdt.core.dom.rewrite.ASTRewrite; + +import org.eclipse.cdt.internal.ui.refactoring.ModificationCollector; +import org.eclipse.cdt.internal.ui.refactoring.NodeContainer; + +final class SimilarReplacerVisitor extends SimilarFinderVisitor { + private final IASTName name; + + private final ModificationCollector collector; + + SimilarReplacerVisitor(ExtractFunctionRefactoring refactoring, NodeContainer extractedNodes, ModificationCollector collector, + List<IASTNode> trail, IASTName name, List<IASTNode> statements) { + super(refactoring, extractedNodes, trail, statements); + this.name = name; + this.collector = collector; + } + + @Override + protected void foundSimilar() { + IASTNode call = refactoring.getMethodCall(name, refactoring.nameTrail, + refactoring.names, extractedNodes, similarContainer); + ASTRewrite rewrite = + collector.rewriterForTranslationUnit(stmtToReplace.get(0).getTranslationUnit()); + TextEditGroup editGroup = new TextEditGroup(Messages.SimilarFinderVisitor_replaceDuplicateCode); + rewrite.replace(stmtToReplace.get(0), call, editGroup); + if (stmtToReplace.size() > 1) { + for (int i = 1; i < stmtToReplace.size(); ++i) { + rewrite.remove(stmtToReplace.get(i), editGroup); + } + } + } +}
\ No newline at end of file diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/gettersandsetters/GetterSetterNameGenerator.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/gettersandsetters/GetterSetterNameGenerator.java index f13586f9af9..877cc2a677e 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/gettersandsetters/GetterSetterNameGenerator.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/gettersandsetters/GetterSetterNameGenerator.java @@ -13,21 +13,17 @@ package org.eclipse.cdt.internal.ui.refactoring.gettersandsetters; import java.util.HashSet; import java.util.Set; -import org.eclipse.core.runtime.Platform; -import org.eclipse.core.runtime.preferences.IPreferencesService; - -import org.eclipse.cdt.core.CConventions; import org.eclipse.cdt.core.dom.ast.IASTDeclarator; import org.eclipse.cdt.core.dom.ast.IASTName; +import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IBasicType; import org.eclipse.cdt.core.dom.ast.IType; -import org.eclipse.cdt.core.dom.ast.gnu.cpp.GPPLanguage; -import org.eclipse.cdt.ui.CUIPlugin; +import org.eclipse.cdt.core.model.ITranslationUnit; import org.eclipse.cdt.ui.PreferenceConstants; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor; - -import org.eclipse.cdt.internal.ui.util.NameComposer; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil; +import org.eclipse.cdt.internal.corext.codemanipulation.StubUtility; public class GetterSetterNameGenerator { private static Set<String> generateGetterSettersPreferenceKeys = new HashSet<String>(); @@ -64,29 +60,16 @@ public class GetterSetterNameGenerator { * generated. */ public static String generateGetterName(IASTName fieldName, Set<String> namesToAvoid) { - IPreferencesService preferences = Platform.getPreferencesService(); - int capitalization = preferences.getInt(CUIPlugin.PLUGIN_ID, - PreferenceConstants.NAME_STYLE_GETTER_CAPITALIZATION, - PreferenceConstants.NAME_STYLE_CAPITALIZATION_CAMEL_CASE, null); - String wordDelimiter = preferences.getString(CUIPlugin.PLUGIN_ID, - PreferenceConstants.NAME_STYLE_GETTER_WORD_DELIMITER, "", null); //$NON-NLS-1$ - String prefix = isBooleanDeclaratorName(fieldName) ? - preferences.getString(CUIPlugin.PLUGIN_ID, - PreferenceConstants.NAME_STYLE_GETTER_PREFIX_FOR_BOOLEAN, "is", null) : //$NON-NLS-1$ - preferences.getString(CUIPlugin.PLUGIN_ID, - PreferenceConstants.NAME_STYLE_GETTER_PREFIX, "get", null); //$NON-NLS-1$ - String suffix = preferences.getString(CUIPlugin.PLUGIN_ID, - PreferenceConstants.NAME_STYLE_GETTER_SUFFIX, "", null); //$NON-NLS-1$ - NameComposer composer = new NameComposer(capitalization, wordDelimiter, prefix, suffix); - String name = NameComposer.trimFieldName(fieldName.toString()); - name = composer.compose(name); - return adjustName(name, namesToAvoid); + ITranslationUnit tu = getTranslationUnit(fieldName); + return StubUtility.suggestGetterName(StubUtility.trimFieldName(fieldName.toString()), + isBooleanDeclaratorName(fieldName), namesToAvoid, tu); } private static boolean isBooleanDeclaratorName(IASTName name) { if (IASTDeclarator.DECLARATOR_NAME.equals(name.getPropertyInParent())) { IASTDeclarator declarator = (IASTDeclarator) name.getParent(); IType type = CPPVisitor.createType(declarator); + type = SemanticUtil.getNestedType(type, SemanticUtil.CVTYPE | SemanticUtil.TDEF); if (type instanceof IBasicType && ((IBasicType) type).getKind() == IBasicType.Kind.eBoolean) { return true; } @@ -103,57 +86,16 @@ public class GetterSetterNameGenerator { * generated. */ public static String generateSetterName(IASTName fieldName, Set<String> namesToAvoid) { - IPreferencesService preferences = Platform.getPreferencesService(); - int capitalization = preferences.getInt(CUIPlugin.PLUGIN_ID, - PreferenceConstants.NAME_STYLE_SETTER_CAPITALIZATION, - PreferenceConstants.NAME_STYLE_CAPITALIZATION_CAMEL_CASE, null); - String wordDelimiter = preferences.getString(CUIPlugin.PLUGIN_ID, - PreferenceConstants.NAME_STYLE_SETTER_WORD_DELIMITER, "", null); //$NON-NLS-1$ - String prefix = preferences.getString(CUIPlugin.PLUGIN_ID, - PreferenceConstants.NAME_STYLE_SETTER_PREFIX, "set", null); //$NON-NLS-1$ - String suffix = preferences.getString(CUIPlugin.PLUGIN_ID, - PreferenceConstants.NAME_STYLE_SETTER_SUFFIX, "", null); //$NON-NLS-1$ - NameComposer composer = new NameComposer(capitalization, wordDelimiter, prefix, suffix); - String name = NameComposer.trimFieldName(fieldName.toString()); - name = composer.compose(name); - return adjustName(name, namesToAvoid); + ITranslationUnit tu = getTranslationUnit(fieldName); + return StubUtility.suggestSetterName(StubUtility.trimFieldName(fieldName.toString()), namesToAvoid, tu); } - public static String generateSetterParameterName(IASTName fieldName){ - IPreferencesService preferences = Platform.getPreferencesService(); - int capitalization = preferences.getInt(CUIPlugin.PLUGIN_ID, - PreferenceConstants.NAME_STYLE_VARIABLE_CAPITALIZATION, - PreferenceConstants.NAME_STYLE_CAPITALIZATION_ORIGINAL, null); - String wordDelimiter = preferences.getString(CUIPlugin.PLUGIN_ID, - PreferenceConstants.NAME_STYLE_VARIABLE_WORD_DELIMITER, "", null); //$NON-NLS-1$ - String prefix = preferences.getString(CUIPlugin.PLUGIN_ID, - PreferenceConstants.NAME_STYLE_VARIABLE_PREFIX, "", null); //$NON-NLS-1$ - String suffix = preferences.getString(CUIPlugin.PLUGIN_ID, - PreferenceConstants.NAME_STYLE_VARIABLE_SUFFIX, "", null); //$NON-NLS-1$ - NameComposer composer = new NameComposer(capitalization, wordDelimiter, prefix, suffix); - String name = NameComposer.trimFieldName(fieldName.toString()); - name = composer.compose(name); - if (!CConventions.validateIdentifier(name, GPPLanguage.getDefault()).isOK()) - name = '_' + name; - return name; + public static String generateSetterParameterName(IASTName fieldName) { + ITranslationUnit tu = getTranslationUnit(fieldName); + return StubUtility.suggestParameterName(StubUtility.trimFieldName(fieldName.toString()), null, tu); } - /** - * Checks is the given name is valid and, if not, tries to adjust it by adding a numeric suffix - * to it. - * - * @param name the name to check and, possibly, adjust - * @param namesToAvoid the set of names to avoid - * @return the adjusted name, or <code>null</code> if a valid name could not be generated. - */ - private static String adjustName(String name, Set<String> namesToAvoid) { - String originalName = name; - for (int i = 1; i < 100; i++) { - if (!namesToAvoid.contains(name) && CConventions.validateIdentifier(name, GPPLanguage.getDefault()).isOK()) { - return name; - } - name = originalName + i; - } - return null; + private static ITranslationUnit getTranslationUnit(IASTNode node) { + return node.getTranslationUnit().getOriginatingTranslationUnit(); } } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/utils/Checks.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/utils/Checks.java index 49a98e82c15..70c721300ea 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/utils/Checks.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/utils/Checks.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2011 IBM Corporation and others. + * Copyright (c) 2000, 2012 IBM Corporation 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 @@ -21,12 +21,17 @@ import org.eclipse.core.runtime.Assert; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; import org.eclipse.ltk.core.refactoring.RefactoringStatus; import org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext; import org.eclipse.ltk.core.refactoring.participants.ResourceChangeChecker; +import org.eclipse.cdt.core.CConventions; +import org.eclipse.cdt.core.dom.ast.gnu.cpp.GPPLanguage; +import org.eclipse.cdt.core.dom.parser.AbstractCLikeLanguage; import org.eclipse.cdt.core.model.CModelException; import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.core.model.ILanguage; import org.eclipse.cdt.core.model.ITranslationUnit; import org.eclipse.cdt.internal.corext.util.CModelUtil; @@ -65,6 +70,63 @@ public class Checks { } } + /** + * Checks if the given name is a valid Java identifier. + * + * @param name the java identifier. + * @param context an {@link ITranslationUnit} or <code>null</code> + * @return a refactoring status containing the error message if the + * name is not a valid java identifier. + */ + public static RefactoringStatus checkIdentifier(String name, ITranslationUnit context) { + return checkName(name, validateIdentifier(name, context)); + } + + public static IStatus validateIdentifier(String name, ITranslationUnit context) { + ILanguage language = null; + try { + if (context != null) + language = context.getLanguage(); + } catch (CoreException e) { + // Ignore + } + if (language == null) { + language = GPPLanguage.getDefault(); + } + if (language instanceof AbstractCLikeLanguage) { + return CConventions.validateIdentifier(name, (AbstractCLikeLanguage) language); + } + return Status.OK_STATUS; + } + + /** + * Returns a fatal error in case the name is empty. In all other cases, an + * error based on the given status is returned. + * + * @param name a name + * @param status a status + * @return RefactoringStatus based on the given status or the name, if empty. + */ + public static RefactoringStatus checkName(String name, IStatus status) { + RefactoringStatus result= new RefactoringStatus(); + if (name.isEmpty()) + return RefactoringStatus.createFatalErrorStatus(Messages.Checks_choose_name); + + if (status.isOK()) + return result; + + switch (status.getSeverity()){ + case IStatus.ERROR: + return RefactoringStatus.createFatalErrorStatus(status.getMessage()); + case IStatus.WARNING: + return RefactoringStatus.createWarningStatus(status.getMessage()); + case IStatus.INFO: + return RefactoringStatus.createInfoStatus(status.getMessage()); + default: // Nothing + return new RefactoringStatus(); + } + } + public static boolean resourceExists(IPath resourcePath){ return ResourcesPlugin.getWorkspace().getRoot().findMember(resourcePath) != null; } @@ -86,7 +148,7 @@ public class Checks { if (attributes != null && attributes.isReadOnly()) return true; - if (! (res instanceof IContainer)) + if (!(res instanceof IContainer)) return false; IContainer container= (IContainer)res; @@ -116,7 +178,7 @@ public class Checks { if (!status.isOK()) { result.merge(RefactoringStatus.create(status)); if (!result.hasFatalError()) { - result.addFatalError(Messages.Checks_validateEdit); + result.addFatalError(Messages.Checks_validate_edit); } } return result; @@ -143,7 +205,7 @@ public class Checks { if (!status.isOK()) { result.merge(RefactoringStatus.create(status)); if (!result.hasFatalError()) { - result.addFatalError(Messages.Checks_validateEdit); + result.addFatalError(Messages.Checks_validate_edit); } } return result; diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/utils/Messages.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/utils/Messages.java index f3aafe6403f..34754225f14 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/utils/Messages.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/utils/Messages.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2008, 2011 Institute for Software, HSR Hochschule fuer Technik + * Copyright (c) 2008, 2012 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 @@ -21,10 +21,8 @@ public final class Messages extends NLS { public static String IdentifierHelper_emptyIdentifier; public static String IdentifierHelper_illegalCharacter; public static String IdentifierHelper_unidentifiedMistake; - public static String VisibilityEnum_public; - public static String VisibilityEnum_protected; - public static String VisibilityEnum_private; - public static String Checks_validateEdit; + public static String Checks_validate_edit; + public static String Checks_choose_name; static { NLS.initializeMessages(Messages.class.getName(), Messages.class); diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/utils/Messages.properties b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/utils/Messages.properties index e57e90e9c57..a8ab5e40a1a 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/utils/Messages.properties +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/utils/Messages.properties @@ -7,8 +7,9 @@ # http://www.eclipse.org/legal/epl-v10.html # # Contributors: -# Institute for Software - initial API and implementation -# IBM Corporation +# Institute for Software - initial API and implementation +# IBM Corporation +# Sergey Prigogin (Google) ############################################################################### IdentifierHelper_isKeyword=''{0}'' is a keyword. IdentifierHelper_isValid=''{0}'' is valid. @@ -16,7 +17,5 @@ IdentifierHelper_leadingDigit=''{0}'' has a leading digit. IdentifierHelper_emptyIdentifier=Identifier must not be empty. IdentifierHelper_illegalCharacter=Illegal character found in ''{0}''. IdentifierHelper_unidentifiedMistake=''{0}'' contains an unidentified mistake. -VisibilityEnum_public=public -VisibilityEnum_protected=protected -VisibilityEnum_private=private -Checks_validateEdit=Team provider refused file modification. +Checks_validate_edit=Team provider refused file modification. +Checks_choose_name=Choose a name. diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/utils/VisibilityEnum.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/utils/VisibilityEnum.java index 19f87e09e0f..aa653695be7 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/utils/VisibilityEnum.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/refactoring/utils/VisibilityEnum.java @@ -8,11 +8,12 @@ * * Contributors: * Institute for Software - initial API and implementation + * Sergey Prigogin (Google) *******************************************************************************/ package org.eclipse.cdt.internal.ui.refactoring.utils; -import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTVisibilityLabel; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTVisibilityLabel; /** * Enum that represents C++ visibilities, with methods to convert to @@ -20,9 +21,9 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBas */ public enum VisibilityEnum { // The values are ordered by increasing visibility. - v_private(Messages.VisibilityEnum_private, ICPPASTVisibilityLabel.v_private, ICPPASTBaseSpecifier.v_private), - v_protected(Messages.VisibilityEnum_protected, ICPPASTVisibilityLabel.v_protected, ICPPASTBaseSpecifier.v_protected), - v_public(Messages.VisibilityEnum_public, ICPPASTVisibilityLabel.v_public, ICPPASTBaseSpecifier.v_public); + v_private("private", ICPPASTVisibilityLabel.v_private, ICPPASTBaseSpecifier.v_private), //$NON-NLS-1$ + v_protected("protected", ICPPASTVisibilityLabel.v_protected, ICPPASTBaseSpecifier.v_protected), //$NON-NLS-1$ + v_public("public", ICPPASTVisibilityLabel.v_public, ICPPASTBaseSpecifier.v_public); //$NON-NLS-1$ private final String stringRepresentation; private final int visibilityLabelValue; diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/util/NameComposer.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/util/NameComposer.java index 4492bcacbc0..133d216cdbe 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/util/NameComposer.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/util/NameComposer.java @@ -146,46 +146,4 @@ public class NameComposer { Character.toUpperCase(word.charAt(i)) : Character.toLowerCase(word.charAt(i))); } } - - /** - * Returns the trimmed field name. Leading and trailing non-alphanumeric characters are trimmed. - * If the first word of the name consists of a single letter and the name contains more than - * one word, the first word is removed. - * - * @param fieldName a field name to trim - * @return the trimmed field name - */ - public static String trimFieldName(String fieldName){ - CBreakIterator iterator = new CBreakIterator(); - iterator.setText(fieldName); - int firstWordStart = -1; - int firstWordEnd = -1; - int secondWordStart = -1; - int lastWordEnd = -1; - int end; - for (int start = iterator.first(); (end = iterator.next()) != BreakIterator.DONE; start = end) { - if (Character.isLetterOrDigit(fieldName.charAt(start))) { - int pos = end; - while (--pos >= start && !Character.isLetterOrDigit(fieldName.charAt(pos))) { - } - lastWordEnd = pos + 1; - if (firstWordStart < 0) { - firstWordStart = start; - firstWordEnd = lastWordEnd; - } else if (secondWordStart < 0) { - secondWordStart = start; - } - } - } - // Skip the first word if it consists of a single letter and the name contains more than - // one word. - if (firstWordStart >= 0 && firstWordStart + 1 == firstWordEnd && secondWordStart >= 0) { - firstWordStart = secondWordStart; - } - if (firstWordStart < 0) { - return fieldName; - } else { - return fieldName.substring(firstWordStart, lastWordEnd); - } - } } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/PreferenceConstants.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/PreferenceConstants.java index ac1e12fafb5..0e55409a06f 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/PreferenceConstants.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/PreferenceConstants.java @@ -1662,8 +1662,42 @@ public class PreferenceConstants { public static final String NAME_STYLE_FIELD_WORD_DELIMITER = "nameStyle.field.wordDelimiter"; //$NON-NLS-1$ /** + * A named preference that controls how capitalization of a method name. + * <p> + * Value is of type <code>Integer</code>. + * + * @since 5.4 + */ + public static final String NAME_STYLE_METHOD_CAPITALIZATION = "nameStyle.method.capitalization"; //$NON-NLS-1$ + /** + * A named preference that controls prefix of a method name. + * <p> + * Value is of type <code>String</code>. + * + * @since 5.4 + */ + public static final String NAME_STYLE_METHOD_PREFIX = "nameStyle.method.prefix"; //$NON-NLS-1$ + /** + * A named preference that controls suffix of a method name. + * <p> + * Value is of type <code>String</code>. + * + * @since 5.4 + */ + public static final String NAME_STYLE_METHOD_SUFFIX = "nameStyle.method.suffix"; //$NON-NLS-1$ + /** + * A named preference that controls delimiter that is inserted between words + * of a method name. + * <p> + * Value is of type <code>String</code>. + * + * @since 5.4 + */ + public static final String NAME_STYLE_METHOD_WORD_DELIMITER = "nameStyle.method.wordDelimiter"; //$NON-NLS-1$ + + /** * A named preference that controls how capitalization of the getter name - * depends on capitalization of the field name. + * depends on capitalization of the method name. * <p> * Value is of type <code>Integer</code>. * @@ -2101,6 +2135,10 @@ public class PreferenceConstants { store.setDefault(NAME_STYLE_FIELD_PREFIX, ""); //$NON-NLS-1$ store.setDefault(NAME_STYLE_FIELD_SUFFIX, ""); //$NON-NLS-1$ store.setDefault(NAME_STYLE_FIELD_WORD_DELIMITER, ""); //$NON-NLS-1$ + store.setDefault(NAME_STYLE_METHOD_CAPITALIZATION, NAME_STYLE_CAPITALIZATION_LOWER_CAMEL_CASE); + store.setDefault(NAME_STYLE_METHOD_PREFIX, ""); //$NON-NLS-1$ + store.setDefault(NAME_STYLE_METHOD_SUFFIX, ""); //$NON-NLS-1$ + store.setDefault(NAME_STYLE_METHOD_WORD_DELIMITER, ""); //$NON-NLS-1$ store.setDefault(NAME_STYLE_GETTER_CAPITALIZATION, NAME_STYLE_CAPITALIZATION_CAMEL_CASE); store.setDefault(NAME_STYLE_GETTER_PREFIX, "get"); //$NON-NLS-1$ store.setDefault(NAME_STYLE_GETTER_PREFIX_FOR_BOOLEAN, "is"); //$NON-NLS-1$ |