1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-06-08 18:26:01 +02:00

New UI and other improvements for Extract Function refactoring .

This commit is contained in:
Sergey Prigogin 2012-02-03 18:32:59 -08:00
parent 0d4d66ec6e
commit fa13b42c51
64 changed files with 4139 additions and 1592 deletions

View file

@ -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);
}
}
}

View file

@ -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;
}
}

View file

@ -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);
}

View file

@ -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.

View file

@ -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);

View file

@ -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

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -1502,8 +1502,8 @@ public:
return mClass;
}
void setClass(int _class) {
mClass = _class;
void setClass(int clazz) {
mClass = clazz;
}
private:

View file

@ -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"));
}
}

View file

@ -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;

View file

@ -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;

View file

@ -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;
/**

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

View file

@ -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);
}
}
}

View file

@ -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$

View file

@ -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$

View file

@ -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;
}
}

View file

@ -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();
}
}

View file

@ -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;
}
}
}
}

View file

@ -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);
}

View file

@ -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;

View file

@ -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

View file

@ -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;
}

View file

@ -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);

View file

@ -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;
}
}

View file

@ -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();
}

View file

@ -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 {

View file

@ -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}

View file

@ -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;
}
}

View file

@ -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.

View file

@ -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);
}
}

View file

@ -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;
}
}

View file

@ -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);
}
}

View file

@ -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.

View file

@ -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();
}
}

View file

@ -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;
}
}

View file

@ -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$
public ExtractFunctionInputPage(String name, ExtractFunctionInformation info) {
super(name);
this.info = info;
private ExtractFunctionRefactoring refactoring;
private ExtractFunctionInformation info;
private Text textField;
private boolean firstTime;
private CSourceViewer signaturePreview;
private Document signaturePreviewDocument;
private IDialogSettings settings;
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() {
@Override
public void widgetDefaultSelected(SelectionEvent e) {
info.setReplaceDuplicates(comp.getReplaceSimilarButton().isEnabled());
}
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 widgetSelected(SelectionEvent e) {
widgetDefaultSelected(e);
info.setReplaceDuplicates(((Button) e.widget).getSelection());
}
});
setControl(comp);
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);
}
protected void visibilityChange(String text) {
info.setVisibility(VisibilityEnum.getEnumForStringRepresentation(text));
private Text createTextInputField(Composite parent, int style) {
Text result = new Text(parent, style);
result.addModifyListener(new ModifyListener() {
@Override
public void modifyText(ModifyEvent e) {
textModified(getText());
}
});
TextFieldNavigationHandler.install(result);
return result;
}
private void checkName() {
String methodName = comp.getMethodName();
IdentifierResult result = IdentifierHelper.checkIdentifierName(methodName);
if (result.isCorrect()) {
setErrorMessage(null);
setPageComplete(true);
} else {
setErrorMessage(Messages.ExtractFunctionInputPage_CheckFunctionName + " " + result.getMessage()); //$NON-NLS-1$
setPageComplete(false);
private String getText() {
if (textField == null)
return null;
return textField.getText();
}
private String getLabelText(){
return Messages.ExtractFunctionInputPage_label_text;
}
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 {
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;
}
}

View file

@ -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,19 +185,33 @@ public class ExtractFunctionRefactoring extends CRefactoring {
if (isProgressMonitorCanceld(sm, initStatus))
return initStatus;
info.setParameterCandidates(container.getParameterCandidates());
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;
List<NameInformation> returnValueCandidates = container.getReturnValueCandidates();
if (returnValueCandidates.size() > 1) {
initStatus.addFatalError(Messages.ExtractFunctionRefactoring_TooManySelected);
} else if (returnValueCandidates.size() == 1) {
info.setMandatoryReturnVariable(returnValueCandidates.get(0));
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>();
for (IASTNode node : container.getNodesToWrite()) {
if (!(node instanceof IASTComment)) {
nodesToRewriteWithoutComments.add(node);
}
}
final List<IASTNode> nodesToRewriteWithoutComments = getNodesWithoutComments(container.getNodesToWrite());
final List<IASTNode> initTrail = getTrail(nodesToRewriteWithoutComments);
final String title;
if (contextType == MethodContext.ContextType.METHOD) {
title = Messages.ExtractFunctionRefactoring_CreateMethodCall;
} else {
title = Messages.ExtractFunctionRefactoring_CreateFunctionCall;
}
if (!hasNameResolvingForSimilarError) {
ast.accept(new SimilarFinderVisitor(this, collector, initTrail, implementationFile,
astMethodName, nodesToRewriteWithoutComments, title));
}
ast.accept(new SimilarReplacerVisitor(this, container, collector, initTrail, astMethodName,
nodesToRewriteWithoutComments));
}
protected List<IASTNode> getTrail(List<IASTNode> stmts) {
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];
}
private List<IASTNode> getNodesWithoutComments(List<IASTNode> nodes) {
final List<IASTNode> nodesWithoutComments = new ArrayList<IASTNode>(nodes.size());
for (IASTNode node : nodes) {
if (!(node instanceof IASTComment)) {
nodesWithoutComments.add(node);
}
}
return nodesWithoutComments;
}
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();
}
}

View file

@ -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 {

View file

@ -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());
}
}

View file

@ -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();

View file

@ -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;
}

View file

@ -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;

View file

@ -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.

View file

@ -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;

View file

@ -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);
}
}
}
}

View file

@ -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();
}
}

View file

@ -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;

View file

@ -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);

View file

@ -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.

View file

@ -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;

View file

@ -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);
}
}
}

View file

@ -1661,9 +1661,43 @@ 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$