1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-24 09:25:31 +02:00

Extract local variable refactoring by Tom Ball. Bug 136713.

This commit is contained in:
Sergey Prigogin 2008-11-24 05:53:17 +00:00
parent cab9222e5d
commit 536750e72b
19 changed files with 1088 additions and 1 deletions

View file

@ -0,0 +1,252 @@
//!ExtractLocalVariableRefactoringTest int
//#org.eclipse.cdt.ui.tests.refactoring.extractlocalvariable.ExtractLocalVariableRefactoringTest
//@A.h
#ifndef A_H_
#define A_H_
class A
{
public:
A();
virtual ~A();
int foo();
};
#endif /*A_H_*/
//=
#ifndef A_H_
#define A_H_
class A
{
public:
A();
virtual ~A();
int foo();
};
#endif /*A_H_*/
//@A.cpp
#include "A.h"
A::A()
{
}
A::~A()
{
}
int A::foo()
{
return /*$*/42/*$$*/;
}
//=
#include "A.h"
A::A()
{
}
A::~A()
{
}
int A::foo()
{
int i = 42;
return i;
}
//!ExtractLocalVariableRefactoringTest char
//#org.eclipse.cdt.ui.tests.refactoring.extractlocalvariable.ExtractLocalVariableRefactoringTest
//@A.h
#ifndef A_H_
#define A_H_
class A
{
public:
A();
virtual ~A();
int foo();
};
#endif /*A_H_*/
//=
#ifndef A_H_
#define A_H_
class A
{
public:
A();
virtual ~A();
int foo();
};
#endif /*A_H_*/
//@A.cpp
#include "A.h"
A::A()
{
}
A::~A()
{
}
int A::foo()
{
return /*$*/'c'/*$$*/;
}
//=
#include "A.h"
A::A()
{
}
A::~A()
{
}
int A::foo()
{
char temp = 'c';
return temp;
}
//!ExtractLocalVariableRefactoringTest float
//#org.eclipse.cdt.ui.tests.refactoring.extractlocalvariable.ExtractLocalVariableRefactoringTest
//@A.h
#ifndef A_H_
#define A_H_
class A
{
public:
A();
virtual ~A();
float foo();
};
#endif /*A_H_*/
//=
#ifndef A_H_
#define A_H_
class A
{
public:
A();
virtual ~A();
float foo();
};
#endif /*A_H_*/
//@A.cpp
#include "A.h"
A::A()
{
}
A::~A()
{
}
float A::foo()
{
return /*$*/42.0/*$$*/;
}
//=
#include "A.h"
A::A()
{
}
A::~A()
{
}
float A::foo()
{
float f = 42.0;
return f;
}
//!ExtractLocalVariableRefactoringTest parentheses
//#org.eclipse.cdt.ui.tests.refactoring.extractlocalvariable.ExtractLocalVariableRefactoringTest
//@A.h
#ifndef A_H_
#define A_H_
class A
{
public:
A();
virtual ~A();
int foo();
};
#endif /*A_H_*/
//=
#ifndef A_H_
#define A_H_
class A
{
public:
A();
virtual ~A();
int foo();
};
#endif /*A_H_*/
//@A.cpp
#include "A.h"
A::A()
{
}
A::~A()
{
}
int A::foo()
{
return /*$*/(42)/*$$*/;
}
//=
#include "A.h"
A::A()
{
}
A::~A()
{
}
int A::foo()
{
int i = 42;
return i;
}

View file

@ -15,6 +15,7 @@ import junit.framework.Test;
import junit.framework.TestSuite;
import org.eclipse.cdt.ui.tests.refactoring.extractfunction.ExtractFunctionTestSuite;
import org.eclipse.cdt.ui.tests.refactoring.extractlocalvariable.ExtractLocalVariableTestSuite;
import org.eclipse.cdt.ui.tests.refactoring.rename.RenameRegressionTests;
import org.eclipse.cdt.ui.tests.refactoring.utils.UtilTestSuite;
@ -33,6 +34,7 @@ public class RefactoringTestSuite extends TestSuite {
suite.addTest(RefactoringTester.suite("HideMethodRefactoringTests", "resources/refactoring/HideMethod.rts"));
suite.addTest(RefactoringTester.suite("GettersAndSettersTests", "resources/refactoring/GenerateGettersAndSetters.rts"));
suite.addTest(RefactoringTester.suite("ImplementMethodRefactoringTests", "resources/refactoring/ImplementMethod.rts"));
suite.addTest(ExtractLocalVariableTestSuite.suite());
return suite;
}
}

View file

@ -0,0 +1,66 @@
/*******************************************************************************
* Copyright (c) 2008 Institute for Software, HSR Hochschule fuer Technik
* Rapperswil, University of applied sciences and others
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Institute for Software - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.ui.tests.refactoring.extractlocalvariable;
import java.util.Properties;
import java.util.Vector;
import org.eclipse.core.resources.IFile;
import org.eclipse.ltk.core.refactoring.Change;
import org.eclipse.ltk.core.refactoring.RefactoringStatus;
import org.eclipse.cdt.ui.tests.refactoring.RefactoringTest;
import org.eclipse.cdt.ui.tests.refactoring.TestSourceFile;
import org.eclipse.cdt.internal.ui.refactoring.CRefactoring;
import org.eclipse.cdt.internal.ui.refactoring.NameNVisibilityInformation;
import org.eclipse.cdt.internal.ui.refactoring.extractlocalvariable.ExtractLocalVariableRefactoring;
/**
* Test harness for Extract Local Variable refactoring tests.
*
* @author Tom Ball
*/
public class ExtractLocalVariableRefactoringTest extends RefactoringTest {
protected String variableName;
protected boolean fatalError;
public ExtractLocalVariableRefactoringTest(String name, Vector<TestSourceFile> files) {
super(name, files);
}
@Override
protected void runTest() throws Throwable {
IFile refFile = project.getFile(fileName);
NameNVisibilityInformation info = new NameNVisibilityInformation();
info.setName(variableName);
CRefactoring refactoring = new ExtractLocalVariableRefactoring( refFile, selection, info);
RefactoringStatus checkInitialConditions = refactoring.checkInitialConditions(NULL_PROGRESS_MONITOR);
if(fatalError){
assertConditionsFatalError(checkInitialConditions);
return;
}
assertConditionsOk(checkInitialConditions);
Change createChange = refactoring.createChange(NULL_PROGRESS_MONITOR);
RefactoringStatus finalConditions = refactoring.checkFinalConditions(NULL_PROGRESS_MONITOR);
assertConditionsOk(finalConditions);
createChange.perform(NULL_PROGRESS_MONITOR);
compareFiles(fileMap);
}
@Override
protected void configureRefactoring(Properties refactoringProperties) {
variableName = refactoringProperties.getProperty("variablename", "temp"); //$NON-NLS-1$ //$NON-NLS-2$
}
}

View file

@ -0,0 +1,33 @@
/*******************************************************************************
* Copyright (c) 2008 Institute for Software, HSR Hochschule fuer Technik
* Rapperswil, University of applied sciences and others
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Institute for Software - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.ui.tests.refactoring.extractlocalvariable;
import junit.framework.Test;
import junit.framework.TestSuite;
import org.eclipse.cdt.ui.tests.refactoring.RefactoringTester;
/**
* Test suite to run just the Extract Local Variable unit tests.
*
* @author Tom Ball
*/
public class ExtractLocalVariableTestSuite extends TestSuite {
@SuppressWarnings("nls")
public static Test suite() throws Exception {
TestSuite suite = new ExtractLocalVariableTestSuite();
suite.addTest(RefactoringTester.suite("ExtractLocalVariableRefactoringTests",
"resources/refactoring/ExtractLocalVariable.rts"));
return suite;
}
}

View file

@ -31,6 +31,7 @@ Export-Package: org.eclipse.cdt.internal.corext;x-internal:=true,
org.eclipse.cdt.internal.ui.refactoring;x-friends:="org.eclipse.cdt.ui.tests",
org.eclipse.cdt.internal.ui.refactoring.dialogs;x-internal:=true,
org.eclipse.cdt.internal.ui.refactoring.extractconstant;x-friends:="org.eclipse.cdt.ui.tests",
org.eclipse.cdt.internal.ui.refactoring.extractlocalvariable;x-friends:="org.eclipse.cdt.ui.tests",
org.eclipse.cdt.internal.ui.refactoring.extractfunction;x-friends:="org.eclipse.cdt.ui.tests",
org.eclipse.cdt.internal.ui.refactoring.gettersandsetters;x-friends:="org.eclipse.cdt.ui.tests",
org.eclipse.cdt.internal.ui.refactoring.hidemethod;x-friends:="org.eclipse.cdt.ui.tests",

View file

@ -137,6 +137,7 @@ ActionDefinition.showMacroExplorer.description= Opens a quick view for macro exp
category.refactoring.description= C/C++ Refactorings
category.refactoring.name = Refactor - C++
refactoringExtractConstant.label = Extract Constant...
refactoringExtractLocalVariable.label = Extract Local Variable...
refactoringHideMethod.label = Hide Memeber Function...
@ -144,6 +145,8 @@ ActionDefinition.renameElement.name= Rename - Refactoring
ActionDefinition.renameElement.description= Rename the selected element
ActionDefinition.extractConstant.name= Extract Constant - Refactoring
ActionDefinition.extractConstant.description= Extract a constant for the selected expression
ActionDefinition.extractLocalVariable.name= Extract Local Variable - Refactoring
ActionDefinition.extractLocalVariable.description= Extract a local variable for the selected expression
ActionDefinition.extractFunction.name= Extract Function - Refactoring
ActionDefinition.extractFunction.description= Extract a function for the selected list of expressions or statements
ActionDefinition.implementMethod.name= Implement Method - Source Generation
@ -158,6 +161,7 @@ CodingActionSet.description= Action set containing coding related C/C++ actions
Refactoring.menu.label= Refac&tor
Refactoring.renameAction.label=Re&name...
Refactoring.extractConstant.label=Extr&act Constant...
Refactoring.extractLocalVariable.label=Extract &Local Variable
Refactoring.extractFunction.label=Extract &Function...
Refactoring.hideMethod.label=Hide Method...
Refactoring.implementMethod.label=Impl&ement Method...

View file

@ -1,4 +1,3 @@
<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.0"?>
<plugin>
@ -1255,6 +1254,13 @@
id="org.eclipse.cdt.ui.actions.ExtractConstant"
retarget="true">
</action>
<action
definitionId="org.eclipse.cdt.ui.refactor.extract.local.variable"
label="%Refactoring.extractLocalVariable.label"
menubarPath="org.eclipse.jdt.ui.refactoring.menu/codingGroup"
id="org.eclipse.cdt.ui.actions.ExtractLocalVariable"
retarget="true">
</action>
<action
definitionId="org.eclipse.cdt.ui.refactor.getters.and.setters"
label="%Refactoring.gettersAndSetters.label"
@ -1740,6 +1746,11 @@
schemeId="org.eclipse.ui.defaultAcceleratorConfiguration"
contextId="org.eclipse.cdt.ui.cEditorScope"
commandId="org.eclipse.cdt.ui.refactor.extract.constant"/>
<key
sequence="M2+M3+L"
schemeId="org.eclipse.ui.defaultAcceleratorConfiguration"
contextId="org.eclipse.cdt.ui.cEditorScope"
commandId="org.eclipse.cdt.ui.refactor.extract.local.variable"/>
<scheme
id="org.eclipse.cdt.ui.visualstudio"
@ -2090,6 +2101,10 @@
categoryId="org.eclipse.cdt.ui.category.refactoring"
id="org.eclipse.cdt.ui.refactoring.command.ExtractConstant"
name="%refactoringExtractConstant.label"/>
<command
categoryId="org.eclipse.cdt.ui.category.refactoring"
id="org.eclipse.cdt.ui.refactoring.command.ExtractLocalVariable"
name="%refactoringExtractLocalVariable.label"/>
<command
categoryId="org.eclipse.cdt.ui.category.refactoring"
id="org.eclipse.cdt.ui.refactor.hide.method"
@ -2104,6 +2119,11 @@
description="%ActionDefinition.extractConstant.description"
categoryId="org.eclipse.cdt.ui.category.refactoring"
id="org.eclipse.cdt.ui.refactor.extract.constant"/>
<command
name="%ActionDefinition.extractLocalVariable.name"
description="%ActionDefinition.extractLocalVariable.description"
categoryId="org.eclipse.cdt.ui.category.refactoring"
id="org.eclipse.cdt.ui.refactor.extract.local.variable"/>
<command
name="%ActionDefinition.extractFunction.name"
description="%ActionDefinition.extractFunction.description"

View file

@ -97,6 +97,12 @@ public interface ICEditorActionDefinitionIds extends ITextEditorActionDefinition
* (value <code>"org.eclipse.cdt.ui.refactor.extract.constant"</code>).
*/
public static final String EXTRACT_CONSTANT= "org.eclipse.cdt.ui.refactor.extract.constant"; //$NON-NLS-1$
/**
* Action definition ID of the refactor -> extract local variable action
* (value <code>"org.eclipse.cdt.ui.refactor.extract.local.variable"</code>).
*/
public static final String EXTRACT_LOCAL_VARIABLE= "org.eclipse.cdt.ui.refactor.extract.local.variable"; //$NON-NLS-1$
/**
* Action definition ID of the refactor -> extract function action (value

View file

@ -0,0 +1,378 @@
/*******************************************************************************
* Copyright (c) 2008 Google 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:
* Google - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.ui.refactoring.extractlocalvariable;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.jface.text.Region;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.ltk.core.refactoring.RefactoringStatus;
import org.eclipse.text.edits.TextEditGroup;
import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTDeclarationStatement;
import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTExpression;
import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
import org.eclipse.cdt.core.dom.ast.IASTInitializerExpression;
import org.eclipse.cdt.core.dom.ast.IASTLiteralExpression;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTStatement;
import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.cpp.CPPASTVisitor;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier;
import org.eclipse.cdt.core.dom.rewrite.ASTRewrite;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTDeclarationStatement;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTDeclarator;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTIdExpression;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTInitializerExpression;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTLiteralExpression;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTName;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTSimpleDeclaration;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPMethod;
import org.eclipse.cdt.internal.ui.refactoring.CRefactoring;
import org.eclipse.cdt.internal.ui.refactoring.ModificationCollector;
import org.eclipse.cdt.internal.ui.refactoring.NameNVisibilityInformation;
import org.eclipse.cdt.internal.ui.refactoring.NodeContainer;
import org.eclipse.cdt.internal.ui.refactoring.extractfunction.ExtractExpression;
import org.eclipse.cdt.internal.ui.refactoring.utils.NodeHelper;
import org.eclipse.cdt.internal.ui.refactoring.utils.SelectionHelper;
/**
* The main class for the Extract Local Variable refactoring. This refactoring
* differs from the Extract Constant refactoring in that any valid expression
* which can be used to initialize a local variable can be extracted.
*
* @author Tom Ball
*/
public class ExtractLocalVariableRefactoring extends CRefactoring {
private IASTExpression target = null;
private final NameNVisibilityInformation info;
private NodeContainer container;
public ExtractLocalVariableRefactoring(IFile file, ISelection selection,
NameNVisibilityInformation info) {
super(file, selection, null);
this.info = info;
name = Messages.ExtractLocalVariable;
}
@Override
public RefactoringStatus checkInitialConditions(IProgressMonitor pm)
throws CoreException, OperationCanceledException {
SubMonitor sm = SubMonitor.convert(pm, 9);
super.checkInitialConditions(sm.newChild(6));
container = findAllExpressions();
if (container.size() < 1) {
initStatus.addFatalError(Messages.ExpressionMustBeSelected);
return initStatus;
}
sm.worked(1);
if (isProgressMonitorCanceld(sm, initStatus))
return initStatus;
boolean oneMarked = region != null
&& isOneMarked(container.getNodesToWrite(), region);
if (!oneMarked) {
if (target == null) {
initStatus.addFatalError(Messages.NoExpressionSelected);
} else {
initStatus.addFatalError(Messages.TooManyExpressionsSelected);
}
return initStatus;
}
sm.worked(1);
if (isProgressMonitorCanceld(sm, initStatus))
return initStatus;
container.findAllNames();
sm.worked(1);
container.getAllAfterUsedNames();
info.addNamesToUsedNames(findAllDeclaredNames());
sm.worked(1);
NodeHelper.findMethodContext(container.getNodesToWrite().get(0),
getIndex());
sm.worked(1);
info.setName(guessTempName());
sm.done();
return initStatus;
}
private ArrayList<String> findAllDeclaredNames() {
ArrayList<String> names = new ArrayList<String>();
IASTFunctionDefinition funcDef = NodeHelper
.findFunctionDefinitionInAncestors(target);
ICPPASTCompositeTypeSpecifier comTypeSpec =
getCompositeTypeSpecifier(funcDef);
if (comTypeSpec != null) {
for (IASTDeclaration dec : comTypeSpec.getMembers()) {
if (dec instanceof IASTSimpleDeclaration) {
IASTSimpleDeclaration simpDec = (IASTSimpleDeclaration) dec;
for (IASTDeclarator decor : simpDec.getDeclarators()) {
names.add(decor.getName().getRawSignature());
}
}
}
}
return names;
}
private ICPPASTCompositeTypeSpecifier getCompositeTypeSpecifier(
IASTFunctionDefinition funcDef) {
if (funcDef != null) {
IBinding binding = funcDef.getDeclarator().getName()
.resolveBinding();
if (binding instanceof CPPMethod) {
CPPMethod method = (CPPMethod) binding;
IASTNode decl = method.getDeclarations()[0];
IASTNode spec = decl.getParent().getParent();
if (spec instanceof ICPPASTCompositeTypeSpecifier) {
ICPPASTCompositeTypeSpecifier compTypeSpec =
(ICPPASTCompositeTypeSpecifier) spec;
return compTypeSpec;
}
}
}
return null;
}
private boolean isOneMarked(List<IASTNode> selectedNodes,
Region textSelection) {
boolean oneMarked = false;
for (IASTNode node : selectedNodes) {
if (node instanceof IASTExpression) {
IASTExpression expression = (IASTExpression) node;
boolean isInSameFileSelection = SelectionHelper
.isInSameFileSelection(textSelection, expression, file);
if (isInSameFileSelection
&& isExpressionInSelection(expression, textSelection)) {
if (target == null) {
target = expression;
oneMarked = true;
} else if (!isTargetChild(expression)) {
oneMarked = false;
}
}
}
}
return oneMarked;
}
private boolean isExpressionInSelection(IASTExpression expression,
Region selection) {
IASTFileLocation location = expression.getFileLocation();
int e1 = location.getNodeOffset();
int e2 = location.getNodeOffset() + location.getNodeLength();
int s1 = selection.getOffset();
int s2 = selection.getOffset() + selection.getLength();
return e1 >= s1 && e2 <= s2;
}
private boolean isTargetChild(IASTExpression child) {
if (target == null) {
return false;
}
IASTNode node = child;
while (node != null) {
if (node.getParent() == target)
return true;
node = node.getParent();
}
return false;
}
private NodeContainer findAllExpressions() {
final NodeContainer container = new NodeContainer();
unit.accept(new CPPASTVisitor() {
{
shouldVisitExpressions = true;
}
@Override
public int visit(IASTExpression expression) {
if (SelectionHelper.isSelectedFile(region, expression, file)) {
container.add(expression);
return PROCESS_SKIP;
}
return super.visit(expression);
}
});
return container;
}
@Override
protected void collectModifications(IProgressMonitor pm,
ModificationCollector collector) throws CoreException,
OperationCanceledException {
String variableName = info.getName();
TextEditGroup editGroup = new TextEditGroup(
Messages.CreateLocalVariable);
// Define temporary variable declaration and insert it
IASTStatement declInsertPoint = getParentStatement(target);
IASTDeclarationStatement declaration = getVariableNodes(variableName);
declaration.setParent(declInsertPoint.getParent());
ASTRewrite rewriter = collector.rewriterForTranslationUnit(unit);
rewriter.insertBefore(declInsertPoint.getParent(), declInsertPoint,
declaration, editGroup);
// Replace target with reference to temporary variable
CPPASTIdExpression idExpression = new CPPASTIdExpression(
new CPPASTName(variableName.toCharArray()));
rewriter.replace(target, idExpression, editGroup);
}
private IASTStatement getParentStatement(IASTNode node) {
while (node != null) {
if (node instanceof IASTStatement)
return (IASTStatement) node;
node = node.getParent();
}
return null;
}
private IASTDeclarationStatement getVariableNodes(String newName) {
IASTSimpleDeclaration simple = new CPPASTSimpleDeclaration();
IASTDeclSpecifier declSpec = new ExtractExpression()
.determineReturnType(deblock(target), null);
declSpec.setStorageClass(IASTDeclSpecifier.sc_unspecified);
simple.setDeclSpecifier(declSpec);
IASTDeclarator decl = new CPPASTDeclarator();
IASTName name = new CPPASTName(newName.toCharArray());
decl.setName(name);
IASTInitializerExpression init = new CPPASTInitializerExpression();
init.setExpression(deblock(target));
decl.setInitializer(init);
simple.addDeclarator(decl);
return new CPPASTDeclarationStatement(simple);
}
/**
* Removes surrounding parentheses from an expression. If the expression
* does not have surrounding parentheses, the original expression is returned.
*/
private static IASTExpression deblock(IASTExpression expression) {
if (expression instanceof IASTUnaryExpression) {
IASTUnaryExpression unary = (IASTUnaryExpression)expression;
if (unary.getOperator() == IASTUnaryExpression.op_bracketedPrimary) {
return deblock(unary.getOperand());
}
}
return expression;
}
public String guessTempName() {
String[] proposals= guessTempNames();
if (proposals.length == 0)
return info.getName();
else
return proposals[0];
}
/**
* @return proposed variable names (may be empty, but not null). The first
* proposal should be used as "best guess" (if it exists).
*/
public String[] guessTempNames() {
final List<String> guessedTempNames = new ArrayList<String>();
if (target != null) {
target.accept(new CPPASTVisitor() {
{
shouldVisitNames = true;
shouldVisitExpressions = true;
}
@Override
public int visit(IASTName name) {
addTempName(name.getLastName().toString());
return super.visit(name);
}
@Override
public int visit(IASTExpression expression) {
if (expression instanceof CPPASTLiteralExpression) {
CPPASTLiteralExpression literal = (CPPASTLiteralExpression)expression;
String name = null;
char[] value = literal.getValue();
switch (literal.getKind()) {
case IASTLiteralExpression.lk_char_constant:
name = Character.toString(value[0]);
break;
case IASTLiteralExpression.lk_float_constant:
name = "f"; //$NON-NLS-1$
break;
case IASTLiteralExpression.lk_integer_constant:
name = "i"; //$NON-NLS-1$
break;
case IASTLiteralExpression.lk_string_literal:
name = literal.toString();
break;
case IASTLiteralExpression.lk_false:
case IASTLiteralExpression.lk_true:
name = "b"; //$NON-NLS-1$
break;
}
if (name != null) {
addTempName(name);
}
}
return super.visit(expression);
}
private void addTempName(String name) {
char[] tmpName = new char[name.length()];
int len = 0;
for (int i = 0; i < name.length(); i++) {
char c = name.charAt(i);
if (len == 0 && Character.isJavaIdentifierStart(c)) {
tmpName[len++] = Character.toLowerCase(c);
} else if (Character.isJavaIdentifierPart(c)) {
tmpName[len++] = c;
}
}
name = new String(tmpName, 0, len);
if (name.length() > 0 && !guessedTempNames.contains(name) &&
!info.getUsedNames().contains(name)) {
guessedTempNames.add(name);
}
}
});
}
return guessedTempNames.toArray(new String[0]);
}
}

View file

@ -0,0 +1,50 @@
/*******************************************************************************
* Copyright (c) 2008 Institute for Software, HSR Hochschule fuer Technik
* Rapperswil, University of applied sciences and others
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Institute for Software - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.ui.refactoring.extractlocalvariable;
import org.eclipse.core.resources.IFile;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.window.IShellProvider;
import org.eclipse.ltk.ui.refactoring.RefactoringWizardOpenOperation;
import org.eclipse.cdt.internal.ui.refactoring.CRefactoring;
import org.eclipse.cdt.internal.ui.refactoring.NameNVisibilityInformation;
import org.eclipse.cdt.internal.ui.refactoring.RefactoringRunner;
/**
* Extract Local Variable refactoring runner.
*
* @author Tom Ball
*/
public class ExtractLocalVariableRefactoringRunner extends RefactoringRunner {
public ExtractLocalVariableRefactoringRunner(IFile file,
ISelection selection, IShellProvider shellProvider) {
super(file, selection, null, shellProvider);
}
@Override
public void run() {
NameNVisibilityInformation info = new NameNVisibilityInformation();
CRefactoring refactoring = new ExtractLocalVariableRefactoring(file,
selection, info);
ExtractLocalVariableRefactoringWizard wizard = new ExtractLocalVariableRefactoringWizard(
refactoring, info);
RefactoringWizardOpenOperation operator = new RefactoringWizardOpenOperation(wizard);
try {
operator.run(shellProvider.getShell(), refactoring.getName());
} catch (InterruptedException e) {
// initial condition checking got canceled by the user.
}
}
}

View file

@ -0,0 +1,39 @@
/*******************************************************************************
* Copyright (c) 2008 Institute for Software, HSR Hochschule fuer Technik
* Rapperswil, University of applied sciences and others
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Institute for Software - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.ui.refactoring.extractlocalvariable;
import org.eclipse.ltk.core.refactoring.Refactoring;
import org.eclipse.ltk.ui.refactoring.RefactoringWizard;
import org.eclipse.cdt.internal.ui.refactoring.NameNVisibilityInformation;
/**
* The wizard page for Extract Local Variable Refactoring, creates the UI page.
*
* @author Tom Ball
*/
public class ExtractLocalVariableRefactoringWizard extends RefactoringWizard {
private InputPage page;
private final NameNVisibilityInformation info;
public ExtractLocalVariableRefactoringWizard(Refactoring refactoring,
NameNVisibilityInformation info) {
super(refactoring, WIZARD_BASED_USER_INTERFACE);
this.info = info;
}
@Override
protected void addUserInputPages() {
page = new InputPage(Messages.ExtractLocalVariable, info);
addPage(page);
}
}

View file

@ -0,0 +1,108 @@
/*******************************************************************************
* Copyright (c) 2008 Institute for Software, HSR Hochschule fuer Technik
* Rapperswil, University of applied sciences and others
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Institute for Software - initial API and implementation
* Google
*******************************************************************************/
package org.eclipse.cdt.internal.ui.refactoring.extractlocalvariable;
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.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Text;
import org.eclipse.cdt.internal.ui.refactoring.NameNVisibilityInformation;
import org.eclipse.cdt.internal.ui.refactoring.dialogs.LabeledTextField;
import org.eclipse.cdt.internal.ui.refactoring.utils.IdentifierHelper;
import org.eclipse.cdt.internal.ui.refactoring.utils.IdentifierResult;
/**
* Input verification page for the ExtractLocalVariable refactoring, cloned
* from org.eclipse.cdt.internal.ui.refactoring.extractconstant.InputPage.
*
* @author Tom Ball
*/
public class InputPage extends UserInputWizardPage {
private String label = Messages.VariableName;
private final NameNVisibilityInformation info;
private InputForm control;
public InputPage(String name, NameNVisibilityInformation info) {
super(name);
this.info = info;
}
public String getVariableName() {
return info.getName();
}
public void createControl(Composite parent) {
control = new InputForm(parent, label);
setTitle(getName());
setMessage(Messages.EnterVariableName);
setPageComplete(false);
Text nameText = control.getVariableNameText();
nameText.setText(info.getName());
nameText.addModifyListener(new ModifyListener() {
public void modifyText(ModifyEvent e) {
info.setName(control.getVariableNameText().getText());
checkName();
}
});
checkName();
setControl(control);
}
private void verifyName(String name) {
if (info.getUsedNames().contains(name)) {
setErrorMessage(NLS.bind(Messages.NameAlreadyDefined, name));
setPageComplete(false);
}
}
private void checkName() {
String methodName = control.getVariableNameText().getText();
IdentifierResult result = IdentifierHelper
.checkIdentifierName(methodName);
if (result.isCorrect()) {
setErrorMessage(null);
setPageComplete(true);
verifyName(methodName);
} else {
setErrorMessage(NLS.bind(Messages.CheckName, result.getMessage()));
setPageComplete(false);
}
}
private static class InputForm extends Composite {
LabeledTextField variableName;
InputForm(Composite parent, String label) {
super(parent, SWT.NONE);
FillLayout layout = new FillLayout(SWT.HORIZONTAL);
GridData gridData = new GridData(SWT.FILL, SWT.BEGINNING, true,
false);
gridData.horizontalAlignment = GridData.FILL;
setLayoutData(gridData);
setLayout(layout);
variableName = new LabeledTextField(this, label, ""); //$NON-NLS-1$
}
Text getVariableNameText() {
return variableName.getText();
}
}
}

View file

@ -0,0 +1,38 @@
/*******************************************************************************
* Copyright (c) 2008 Institute for Software, HSR Hochschule fuer Technik
* Rapperswil, University of applied sciences and others
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Institute for Software - initial API and implementation
* Google
*******************************************************************************/
package org.eclipse.cdt.internal.ui.refactoring.extractlocalvariable;
import org.eclipse.osgi.util.NLS;
public final class Messages extends NLS {
private static final String BUNDLE_NAME = "org.eclipse.cdt.internal.ui.refactoring.extractlocalvariable.messages"; //$NON-NLS-1$
public static String CheckName;
public static String CreateLocalVariable;
public static String EnterVariableName;
public static String ExpressionMustBeSelected;
public static String ExtractLocalVariable;
public static String NameAlreadyDefined;
public static String NoExpressionSelected;
public static String ReplaceExpression;
public static String TooManyExpressionsSelected;
public static String VariableName;
static {
NLS.initializeMessages(BUNDLE_NAME, Messages.class);
}
private Messages() {
// Do not instantiate
}
}

View file

@ -0,0 +1,23 @@
###############################################################################
# Copyright (c) 2008 Institute for Software, HSR Hochschule fuer Technik
# Rapperswil, University of applied sciences and others
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Eclipse Public License v1.0
# which accompanies this distribution, and is available at
# http://www.eclipse.org/legal/epl-v10.html
#
# Contributors:
# Institute for Software - initial API and implementation
# IBM Corporation
# Google
###############################################################################
VariableName=Variable &name:
EnterVariableName=Enter a name for the new variable
CheckName=Check Name: {0}
NameAlreadyDefined=An element named ''{0}'' is already defined in this scope.
ExtractLocalVariable=Extract Local Variable
ExpressionMustBeSelected=An expression must be selected to activate this refactoring.
NoExpressionSelected=No expression selected.
TooManyExpressionsSelected=Too many expressions selected.
CreateLocalVariable=Create Local Variable
ReplaceExpression=Replace an expression

View file

@ -247,6 +247,13 @@ public class CdtActionConstants {
* (value <code>"org.eclipse.cdt.ui.actions.ExtractConstant"</code>).
*/
public static final String EXTRACT_CONSTANT= "org.eclipse.cdt.ui.actions.ExtractConstant"; //$NON-NLS-1$
/**
* Refactor menu: name of standard Extract Local Variable global action
* (value <code>"org.eclipse.cdt.ui.actions.ExtractLocalVariable"</code>).
* @since 5.1
*/
public static final String EXTRACT_LOCAL_VARIABLE= "org.eclipse.cdt.ui.actions.ExtractLocalVariable"; //$NON-NLS-1$
/**
* Refactor menu: name of standard Hide Method global action

View file

@ -113,6 +113,7 @@ public class CRefactoringActionGroup extends ActionGroup implements ISelectionCh
private String fGroupName= IWorkbenchActionConstants.GROUP_REORGANIZE;
private CRenameAction fRenameAction;
private RefactoringAction fExtractConstantAction;
private RefactoringAction fExtractLocalVariableAction;
private RefactoringAction fExtractFunctionAction;
private RefactoringAction fHideMethodAction;
private RefactoringAction fImplementMethodAction;
@ -153,6 +154,10 @@ public class CRefactoringActionGroup extends ActionGroup implements ISelectionCh
fExtractConstantAction.setActionDefinitionId(ICEditorActionDefinitionIds.EXTRACT_CONSTANT);
fAllActions.add(fExtractConstantAction);
fExtractLocalVariableAction= new ExtractLocalVariableAction();
fExtractLocalVariableAction.setActionDefinitionId(ICEditorActionDefinitionIds.EXTRACT_LOCAL_VARIABLE);
fAllActions.add(fExtractLocalVariableAction);
fExtractFunctionAction = new ExtractFunctionAction();
fExtractFunctionAction.setActionDefinitionId(ICEditorActionDefinitionIds.EXTRACT_FUNCTION);
fAllActions.add(fExtractFunctionAction);
@ -204,6 +209,7 @@ public class CRefactoringActionGroup extends ActionGroup implements ISelectionCh
super.fillActionBars(actionBar);
setActionHandler(actionBar, CdtActionConstants.RENAME, fRenameAction);
setActionHandler(actionBar, CdtActionConstants.EXTRACT_CONSTANT, fExtractConstantAction);
setActionHandler(actionBar, CdtActionConstants.EXTRACT_LOCAL_VARIABLE, fExtractLocalVariableAction);
setActionHandler(actionBar, CdtActionConstants.EXTRACT_METHOD, fExtractFunctionAction);
setActionHandler(actionBar, CdtActionConstants.HIDE_METHOD, fHideMethodAction);
setActionHandler(actionBar, CdtActionConstants.IMPLEMENT_METHOD, fImplementMethodAction);
@ -236,6 +242,7 @@ public class CRefactoringActionGroup extends ActionGroup implements ISelectionCh
addAction(refactorSubmenu, fRenameAction);
refactorSubmenu.add(new Separator(GROUP_CODING));
addAction(refactorSubmenu, fExtractConstantAction);
addAction(refactorSubmenu, fExtractLocalVariableAction);
addAction(refactorSubmenu, fExtractFunctionAction);
addAction(refactorSubmenu, fHideMethodAction);
refactorSubmenu.add(new Separator(GROUP_REORG2));

View file

@ -0,0 +1,50 @@
/*******************************************************************************
* Copyright (c) 2005, 2006 Wind River Systems, Inc.
* 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:
* Markus Schorn - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.ui.refactoring.actions;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.jface.window.IShellProvider;
import org.eclipse.cdt.core.model.ICElement;
import org.eclipse.cdt.core.model.IWorkingCopy;
import org.eclipse.cdt.internal.ui.refactoring.extractlocalvariable.ExtractLocalVariableRefactoringRunner;
/**
* Launches a extract local variable refactoring.
*/
public class ExtractLocalVariableAction extends RefactoringAction {
public ExtractLocalVariableAction() {
super(Messages.ExtractLocalVariableAction_label);
}
@Override
public void run(IShellProvider shellProvider, ICElement elem) {
}
@Override
public void run(IShellProvider shellProvider, IWorkingCopy wc, ITextSelection selection) {
IResource res= wc.getResource();
if (res instanceof IFile) {
new ExtractLocalVariableRefactoringRunner((IFile) res, selection, shellProvider).run();
}
}
@Override
public void updateSelection(ICElement elem) {
super.updateSelection(elem);
setEnabled(false);
}
}

View file

@ -14,9 +14,11 @@ import org.eclipse.osgi.util.NLS;
public class Messages extends NLS {
private static final String BUNDLE_NAME = "org.eclipse.cdt.ui.refactoring.actions.messages"; //$NON-NLS-1$
public static String CRefactoringActionGroup_menu;
public static String CRenameAction_label;
public static String ExtractConstantAction_label;
public static String ExtractLocalVariableAction_label;
public static String ExtractFunctionAction_label;
public static String HideMethodAction_label;
public static String ImplementMethodAction_label;

View file

@ -11,6 +11,7 @@
CRefactoringActionGroup_menu=Refactor
CRenameAction_label=Rename...
ExtractConstantAction_label=Extract Constant...
ExtractLocalVariableAction_label=Extract Local Variable...
GettersAndSetters_label=Generate Getters and Setters...
ImplementMethodAction_label=Implement Method...
HideMethodAction_label=Hide Method...