mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-08-01 05:15:43 +02:00
Extract Function: find and extract dublicated code
This commit is contained in:
parent
6a9abf764d
commit
e5fa863d5c
10 changed files with 1506 additions and 19 deletions
File diff suppressed because it is too large
Load diff
|
@ -261,3 +261,102 @@ int main(){
|
||||||
flags="4" id="org.eclipse.cdt.internal.ui.refactoring.extractfunction.ExtractFunctionRefactoring"
|
flags="4" id="org.eclipse.cdt.internal.ui.refactoring.extractfunction.ExtractFunctionRefactoring"
|
||||||
name="exp" project="RegressionTestProject" selection="23,5" visibility="private"/>
|
name="exp" project="RegressionTestProject" selection="23,5" visibility="private"/>
|
||||||
</session>
|
</session>
|
||||||
|
|
||||||
|
//!ExtractFunctionRefactoringTest duplicates with different Names History Test
|
||||||
|
//#org.eclipse.cdt.ui.tests.refactoring.RefactoringHistoryTest
|
||||||
|
//@A.h
|
||||||
|
#ifndef A_H_
|
||||||
|
#define A_H_
|
||||||
|
|
||||||
|
class A
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
A();
|
||||||
|
virtual ~A();
|
||||||
|
int foo();
|
||||||
|
|
||||||
|
private:
|
||||||
|
int help();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /*A_H_*/
|
||||||
|
|
||||||
|
//=
|
||||||
|
#ifndef A_H_
|
||||||
|
#define A_H_
|
||||||
|
|
||||||
|
class A
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
A();
|
||||||
|
virtual ~A();
|
||||||
|
int foo();
|
||||||
|
|
||||||
|
private:
|
||||||
|
int help();
|
||||||
|
void exp(int & i);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /*A_H_*/
|
||||||
|
|
||||||
|
//@A.cpp
|
||||||
|
#include "A.h"
|
||||||
|
|
||||||
|
A::A()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
A::~A()
|
||||||
|
{
|
||||||
|
int oo = 99;
|
||||||
|
++oo;
|
||||||
|
help();
|
||||||
|
}int A::foo()
|
||||||
|
{
|
||||||
|
int i = 2;
|
||||||
|
++i;
|
||||||
|
help();
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
int A::help()
|
||||||
|
{
|
||||||
|
return 42;
|
||||||
|
}
|
||||||
|
|
||||||
|
//=
|
||||||
|
#include "A.h"
|
||||||
|
|
||||||
|
A::A()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
A::~A()
|
||||||
|
{
|
||||||
|
int oo = 99;
|
||||||
|
exp(oo);
|
||||||
|
}void A::exp(int & i)
|
||||||
|
{
|
||||||
|
++i;
|
||||||
|
help();
|
||||||
|
}
|
||||||
|
|
||||||
|
int A::foo()
|
||||||
|
{
|
||||||
|
int i = 2;
|
||||||
|
exp(i);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
int A::help()
|
||||||
|
{
|
||||||
|
return 42;
|
||||||
|
}
|
||||||
|
|
||||||
|
//@refScript.xml
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<session version="1.0">
|
||||||
|
<refactoring comment="Create method exp" description="Extract Method Refactoring"
|
||||||
|
fileName="file:$$projectPath$$/A.cpp" flags="4" id="org.eclipse.cdt.internal.ui.refactoring.extractfunction.ExtractFunctionRefactoring"
|
||||||
|
name="exp" project="RegressionTestProject" replaceDuplicates="true" selection="97,13" visibility="private"/>
|
||||||
|
</session>
|
||||||
|
|
|
@ -30,6 +30,7 @@ public class ExtractFunctionTestSuite extends TestSuite {
|
||||||
suite.addTest(RefactoringTester.suite("ExtractMethodPreprocessorRefactoringTests", "resources/refactoring/ExtractMethodPreprocessor.rts"));
|
suite.addTest(RefactoringTester.suite("ExtractMethodPreprocessorRefactoringTests", "resources/refactoring/ExtractMethodPreprocessor.rts"));
|
||||||
suite.addTest(RefactoringTester.suite("Extract Function Templates Tests", "resources/refactoring/ExtractFunctionTemplates.rts"));
|
suite.addTest(RefactoringTester.suite("Extract Function Templates Tests", "resources/refactoring/ExtractFunctionTemplates.rts"));
|
||||||
suite.addTest(RefactoringTester.suite("Extract Method History Test", "resources/refactoring/ExtractMethodHistory.rts"));
|
suite.addTest(RefactoringTester.suite("Extract Method History Test", "resources/refactoring/ExtractMethodHistory.rts"));
|
||||||
|
suite.addTest(RefactoringTester.suite("Extract Function Dublicates Test", "resources/refactoring/ExtractMethodDuplicates.rts"));
|
||||||
return suite;
|
return suite;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Copyright (c) 2008 Institute for Software, HSR Hochschule fuer Technik
|
* Copyright (c) 2008, 2009 Institute for Software, HSR Hochschule fuer Technik
|
||||||
* Rapperswil, University of applied sciences and others
|
* Rapperswil, University of applied sciences and others
|
||||||
* All rights reserved. This program and the accompanying materials
|
* All rights reserved. This program and the accompanying materials
|
||||||
* are made available under the terms of the Eclipse Public License v1.0
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
@ -40,15 +40,13 @@ public class ExtractFunctionComposite extends Composite {
|
||||||
Group returnGroup = createReturnGroup(nameVisiComp);
|
Group returnGroup = createReturnGroup(nameVisiComp);
|
||||||
createReturnValueChooser(returnGroup, info, ip);
|
createReturnValueChooser(returnGroup, info, ip);
|
||||||
|
|
||||||
// Disabled for now
|
createReplaceCheckBox(nameVisiComp);
|
||||||
//createReplaceCheckBox(nameVisiComp);
|
|
||||||
|
|
||||||
if (info.getMethodContext().getType() == MethodContext.ContextType.METHOD) {
|
if (info.getMethodContext().getType() == MethodContext.ContextType.METHOD) {
|
||||||
visibilityPanelSetVisible(true);
|
visibilityPanelSetVisible(true);
|
||||||
}else {
|
}else {
|
||||||
visibilityPanelSetVisible(false);
|
visibilityPanelSetVisible(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
layout();
|
layout();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,13 +104,13 @@ public class ExtractFunctionComposite extends Composite {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// private void createReplaceCheckBox(Composite parent) {
|
private void createReplaceCheckBox(Composite parent) {
|
||||||
// replaceSimilar = new Button(parent, SWT.CHECK | SWT.LEFT);
|
replaceSimilar = new Button(parent, SWT.CHECK | SWT.LEFT);
|
||||||
// GridData buttonLayoutData = new GridData(SWT.None);
|
GridData buttonLayoutData = new GridData(SWT.None);
|
||||||
// buttonLayoutData.verticalIndent = 5;
|
buttonLayoutData.verticalIndent = 5;
|
||||||
// replaceSimilar.setLayoutData(buttonLayoutData);
|
replaceSimilar.setLayoutData(buttonLayoutData);
|
||||||
// replaceSimilar.setText(Messages.ExtractFunctionComposite_ReplaceDuplicates);
|
replaceSimilar.setText(Messages.ExtractFunctionComposite_ReplaceDuplicates);
|
||||||
// }
|
}
|
||||||
|
|
||||||
|
|
||||||
public ChooserComposite getReturnChooser() {
|
public ChooserComposite getReturnChooser() {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Copyright (c) 2008 Institute for Software, HSR Hochschule fuer Technik
|
* Copyright (c) 2008, 2009 Institute for Software, HSR Hochschule fuer Technik
|
||||||
* Rapperswil, University of applied sciences and others
|
* Rapperswil, University of applied sciences and others
|
||||||
* All rights reserved. This program and the accompanying materials
|
* All rights reserved. This program and the accompanying materials
|
||||||
* are made available under the terms of the Eclipse Public License v1.0
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
@ -17,6 +17,8 @@ import org.eclipse.swt.events.ModifyEvent;
|
||||||
import org.eclipse.swt.events.ModifyListener;
|
import org.eclipse.swt.events.ModifyListener;
|
||||||
import org.eclipse.swt.events.MouseAdapter;
|
import org.eclipse.swt.events.MouseAdapter;
|
||||||
import org.eclipse.swt.events.MouseEvent;
|
import org.eclipse.swt.events.MouseEvent;
|
||||||
|
import org.eclipse.swt.events.SelectionEvent;
|
||||||
|
import org.eclipse.swt.events.SelectionListener;
|
||||||
import org.eclipse.swt.widgets.Button;
|
import org.eclipse.swt.widgets.Button;
|
||||||
import org.eclipse.swt.widgets.Composite;
|
import org.eclipse.swt.widgets.Composite;
|
||||||
import org.eclipse.swt.widgets.Control;
|
import org.eclipse.swt.widgets.Control;
|
||||||
|
@ -65,9 +67,7 @@ public class ExtractFunctionInputPage extends UserInputWizardPage {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Disable until it works again.
|
comp.getReplaceSimilarButton().addSelectionListener(new SelectionListener(){
|
||||||
*
|
|
||||||
* comp.getReplaceSimilarButton().addSelectionListener(new SelectionListener(){
|
|
||||||
|
|
||||||
public void widgetDefaultSelected(SelectionEvent e) {
|
public void widgetDefaultSelected(SelectionEvent e) {
|
||||||
info.setReplaceDuplicates(comp.getReplaceSimilarButton().isEnabled());
|
info.setReplaceDuplicates(comp.getReplaceSimilarButton().isEnabled());
|
||||||
|
@ -77,7 +77,7 @@ public class ExtractFunctionInputPage extends UserInputWizardPage {
|
||||||
widgetDefaultSelected(e);
|
widgetDefaultSelected(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
});*/
|
});
|
||||||
|
|
||||||
setControl(comp);
|
setControl(comp);
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@ package org.eclipse.cdt.internal.ui.refactoring.extractfunction;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Vector;
|
import java.util.Vector;
|
||||||
|
@ -36,6 +37,7 @@ import org.eclipse.text.edits.TextEditGroup;
|
||||||
|
|
||||||
import org.eclipse.cdt.core.dom.ast.DOMException;
|
import org.eclipse.cdt.core.dom.ast.DOMException;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression;
|
import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTComment;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTCompoundStatement;
|
import org.eclipse.cdt.core.dom.ast.IASTCompoundStatement;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier;
|
import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
|
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
|
||||||
|
@ -49,6 +51,7 @@ import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTIdExpression;
|
import org.eclipse.cdt.core.dom.ast.IASTIdExpression;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTInitializerExpression;
|
import org.eclipse.cdt.core.dom.ast.IASTInitializerExpression;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTName;
|
import org.eclipse.cdt.core.dom.ast.IASTName;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTNamedTypeSpecifier;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration;
|
import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTPointerOperator;
|
import org.eclipse.cdt.core.dom.ast.IASTPointerOperator;
|
||||||
|
@ -63,11 +66,15 @@ import org.eclipse.cdt.core.dom.ast.INodeFactory;
|
||||||
import org.eclipse.cdt.core.dom.ast.IParameter;
|
import org.eclipse.cdt.core.dom.ast.IParameter;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.CPPASTVisitor;
|
import org.eclipse.cdt.core.dom.ast.cpp.CPPASTVisitor;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier;
|
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.ICPPASTFunctionDeclarator;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTOperatorName;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTSimpleDeclSpecifier;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTSimpleDeclSpecifier;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateDeclaration;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateDeclaration;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateParameter;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateParameter;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBinding;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
|
||||||
import org.eclipse.cdt.core.dom.rewrite.ASTRewrite;
|
import org.eclipse.cdt.core.dom.rewrite.ASTRewrite;
|
||||||
|
@ -105,6 +112,7 @@ import org.eclipse.cdt.internal.ui.refactoring.NodeContainer;
|
||||||
import org.eclipse.cdt.internal.ui.refactoring.MethodContext.ContextType;
|
import org.eclipse.cdt.internal.ui.refactoring.MethodContext.ContextType;
|
||||||
import org.eclipse.cdt.internal.ui.refactoring.NodeContainer.NameInformation;
|
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.ASTHelper;
|
||||||
|
import org.eclipse.cdt.internal.ui.refactoring.utils.CPPASTAllVisitor;
|
||||||
import org.eclipse.cdt.internal.ui.refactoring.utils.NodeHelper;
|
import org.eclipse.cdt.internal.ui.refactoring.utils.NodeHelper;
|
||||||
import org.eclipse.cdt.internal.ui.refactoring.utils.SelectionHelper;
|
import org.eclipse.cdt.internal.ui.refactoring.utils.SelectionHelper;
|
||||||
|
|
||||||
|
@ -129,7 +137,7 @@ public class ExtractFunctionRefactoring extends CRefactoring {
|
||||||
HashMap<String, Integer> nameTrail;
|
HashMap<String, Integer> nameTrail;
|
||||||
|
|
||||||
private ExtractedFunctionConstructionHelper extractedFunctionConstructionHelper;
|
private ExtractedFunctionConstructionHelper extractedFunctionConstructionHelper;
|
||||||
private INodeFactory factory = CPPNodeFactory.getDefault();
|
private final INodeFactory factory = CPPNodeFactory.getDefault();
|
||||||
|
|
||||||
public ExtractFunctionRefactoring(IFile file, ISelection selection,
|
public ExtractFunctionRefactoring(IFile file, ISelection selection,
|
||||||
ExtractFunctionInformation info, ICProject project) {
|
ExtractFunctionInformation info, ICProject project) {
|
||||||
|
@ -340,6 +348,11 @@ public class ExtractFunctionRefactoring extends CRefactoring {
|
||||||
methodCall = declarationStatement;
|
methodCall = declarationStatement;
|
||||||
}
|
}
|
||||||
insertCallintoTree(methodCall, container.getNodesToWrite(), rewriter, editGroup);
|
insertCallintoTree(methodCall, container.getNodesToWrite(), rewriter, editGroup);
|
||||||
|
|
||||||
|
if (info.isReplaceDuplicates()) {
|
||||||
|
replaceSimilar(collector, astMethodName, implementationFile, context.getType());
|
||||||
|
}
|
||||||
|
|
||||||
for (IASTNode node : container.getNodesToWrite()) {
|
for (IASTNode node : container.getNodesToWrite()) {
|
||||||
if (node != firstNodeToWrite) {
|
if (node != firstNodeToWrite) {
|
||||||
rewriter.remove(node, editGroup);
|
rewriter.remove(node, editGroup);
|
||||||
|
@ -404,6 +417,158 @@ public class ExtractFunctionRefactoring extends CRefactoring {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void replaceSimilar(ModificationCollector collector, final IASTName astMethodName,
|
||||||
|
final IFile implementationFile,
|
||||||
|
final ContextType contextType) {
|
||||||
|
// Find similar code
|
||||||
|
final List<IASTNode> nodesToRewriteWithoutComments = new LinkedList<IASTNode>();
|
||||||
|
|
||||||
|
for (IASTNode node : container.getNodesToWrite()) {
|
||||||
|
if (!(node instanceof IASTComment)) {
|
||||||
|
nodesToRewriteWithoutComments.add(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final Vector<IASTNode> initTrail = getTrail(nodesToRewriteWithoutComments);
|
||||||
|
final String title;
|
||||||
|
if (contextType == MethodContext.ContextType.METHOD) {
|
||||||
|
title = Messages.ExtractFunctionRefactoring_CreateMethodCall;
|
||||||
|
} else {
|
||||||
|
title = Messages.ExtractFunctionRefactoring_CreateFunctionCall;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hasNameResolvingForSimilarError) {
|
||||||
|
unit.accept(new SimilarFinderVisitor(this, collector, initTrail, implementationFile,
|
||||||
|
astMethodName, nodesToRewriteWithoutComments, title));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Vector<IASTNode> getTrail(List<IASTNode> stmts) {
|
||||||
|
final Vector<IASTNode> trail = new Vector<IASTNode>();
|
||||||
|
|
||||||
|
nameTrail = new HashMap<String, Integer>();
|
||||||
|
final Container<Integer> trailCounter = new Container<Integer>(NULL_INTEGER);
|
||||||
|
|
||||||
|
for (IASTNode node : stmts) {
|
||||||
|
node.accept(new CPPASTAllVisitor() {
|
||||||
|
@Override
|
||||||
|
public int visitAll(IASTNode node) {
|
||||||
|
|
||||||
|
if (node instanceof IASTComment) {
|
||||||
|
// Visit Comment, but don't add them to the trail
|
||||||
|
return super.visitAll(node);
|
||||||
|
} else if (node instanceof IASTNamedTypeSpecifier) {
|
||||||
|
// Skip if somewhere is a named Type Specifier
|
||||||
|
trail.add(node);
|
||||||
|
return PROCESS_SKIP;
|
||||||
|
} else if (node instanceof IASTName) {
|
||||||
|
if (node instanceof ICPPASTConversionName && node instanceof ICPPASTOperatorName
|
||||||
|
&& node instanceof ICPPASTTemplateId) {
|
||||||
|
trail.add(node);
|
||||||
|
return super.visitAll(node);
|
||||||
|
} else {
|
||||||
|
// Save Name Sequenz Number
|
||||||
|
IASTName name = (IASTName) node;
|
||||||
|
TrailName trailName = new TrailName();
|
||||||
|
int actCount = trailCounter.getObject().intValue();
|
||||||
|
if (nameTrail.containsKey(name.getRawSignature())) {
|
||||||
|
Integer value = nameTrail.get(name.getRawSignature());
|
||||||
|
actCount = value.intValue();
|
||||||
|
} else {
|
||||||
|
trailCounter.setObject(Integer.valueOf(++actCount));
|
||||||
|
nameTrail.put(name.getRawSignature(), trailCounter.getObject());
|
||||||
|
}
|
||||||
|
trailName.setNameNumber(actCount);
|
||||||
|
trailName.setRealName(name);
|
||||||
|
|
||||||
|
if (info.getReturnVariable() != null
|
||||||
|
&& info.getReturnVariable().getName().getRawSignature().equals(
|
||||||
|
name.getRawSignature())) {
|
||||||
|
returnNumber.setObject(Integer.valueOf(actCount));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save type informations for the name
|
||||||
|
IBinding bind = name.resolveBinding();
|
||||||
|
IASTName[] declNames = name.getTranslationUnit().getDeclarationsInAST(bind);
|
||||||
|
if (declNames.length > 0) {
|
||||||
|
IASTNode tmpNode = ASTHelper.getDeclarationForNode(declNames[0]);
|
||||||
|
|
||||||
|
IBinding declbind = declNames[0].resolveBinding();
|
||||||
|
if (declbind instanceof ICPPBinding) {
|
||||||
|
ICPPBinding cppBind = (ICPPBinding) declbind;
|
||||||
|
try {
|
||||||
|
trailName.setGloballyQualified(cppBind.isGloballyQualified());
|
||||||
|
} catch (DOMException e) {
|
||||||
|
ILog logger = CUIPlugin.getDefault().getLog();
|
||||||
|
IStatus status = new Status(IStatus.WARNING, CUIPlugin.PLUGIN_ID,
|
||||||
|
IStatus.OK, e.getMessage(), e);
|
||||||
|
|
||||||
|
logger.log(status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tmpNode != null) {
|
||||||
|
trailName.setDeclaration(tmpNode);
|
||||||
|
} else {
|
||||||
|
hasNameResolvingForSimilarError = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
trail.add(trailName);
|
||||||
|
return PROCESS_SKIP;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
trail.add(node);
|
||||||
|
return super.visitAll(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return trail;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean isStatementInTrail(IASTStatement stmt, final Vector<IASTNode> trail) {
|
||||||
|
final Container<Boolean> same = new Container<Boolean>(Boolean.TRUE);
|
||||||
|
final TrailNodeEqualityChecker equalityChecker = new TrailNodeEqualityChecker(names, namesCounter);
|
||||||
|
|
||||||
|
stmt.accept(new CPPASTAllVisitor() {
|
||||||
|
@Override
|
||||||
|
public int visitAll(IASTNode node) {
|
||||||
|
|
||||||
|
int pos = trailPos.getObject().intValue();
|
||||||
|
|
||||||
|
if (trail.size() <= 0 || pos >= trail.size()) {
|
||||||
|
same.setObject(Boolean.FALSE);
|
||||||
|
return PROCESS_ABORT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node instanceof IASTComment) {
|
||||||
|
// Visit Comment, but they are not in the trail
|
||||||
|
return super.visitAll(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
IASTNode trailNode = trail.get(pos);
|
||||||
|
trailPos.setObject(Integer.valueOf(pos + 1));
|
||||||
|
|
||||||
|
if (equalityChecker.isEquals(trailNode, node)) {
|
||||||
|
if (node instanceof ICPPASTQualifiedName || node instanceof IASTNamedTypeSpecifier) {
|
||||||
|
return PROCESS_SKIP;
|
||||||
|
} else {
|
||||||
|
return super.visitAll(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
same.setObject(new Boolean(false));
|
||||||
|
return PROCESS_ABORT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return same.getObject().booleanValue();
|
||||||
|
}
|
||||||
|
|
||||||
private boolean isMethodAllreadyDefined(
|
private boolean isMethodAllreadyDefined(
|
||||||
IASTSimpleDeclaration methodDeclaration,
|
IASTSimpleDeclaration methodDeclaration,
|
||||||
ICPPASTCompositeTypeSpecifier classDeclaration) {
|
ICPPASTCompositeTypeSpecifier classDeclaration) {
|
||||||
|
@ -777,6 +942,7 @@ public class ExtractFunctionRefactoring extends CRefactoring {
|
||||||
arguments.put(CRefactoringDescription.SELECTION, region.getOffset() + "," + region.getLength()); //$NON-NLS-1$
|
arguments.put(CRefactoringDescription.SELECTION, region.getOffset() + "," + region.getLength()); //$NON-NLS-1$
|
||||||
arguments.put(ExtractFunctionRefactoringDescription.NAME, info.getMethodName());
|
arguments.put(ExtractFunctionRefactoringDescription.NAME, info.getMethodName());
|
||||||
arguments.put(ExtractFunctionRefactoringDescription.VISIBILITY, info.getVisibility().toString());
|
arguments.put(ExtractFunctionRefactoringDescription.VISIBILITY, info.getVisibility().toString());
|
||||||
|
arguments.put(ExtractFunctionRefactoringDescription.REPLACE_DUBLICATES, Boolean.toString(info.isReplaceDuplicates()));
|
||||||
return arguments;
|
return arguments;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,7 @@ import org.eclipse.cdt.internal.ui.refactoring.utils.VisibilityEnum;
|
||||||
public class ExtractFunctionRefactoringDescription extends CRefactoringDescription {
|
public class ExtractFunctionRefactoringDescription extends CRefactoringDescription {
|
||||||
protected static final String NAME = "name"; //$NON-NLS-1$
|
protected static final String NAME = "name"; //$NON-NLS-1$
|
||||||
protected static final String VISIBILITY = "visibility"; //$NON-NLS-1$
|
protected static final String VISIBILITY = "visibility"; //$NON-NLS-1$
|
||||||
|
protected static final String REPLACE_DUBLICATES = "replaceDuplicates"; //$NON-NLS-1$
|
||||||
|
|
||||||
public ExtractFunctionRefactoringDescription(String project, String description,
|
public ExtractFunctionRefactoringDescription(String project, String description,
|
||||||
String comment, Map<String, String> arguments) {
|
String comment, Map<String, String> arguments) {
|
||||||
|
@ -46,6 +47,7 @@ public class ExtractFunctionRefactoringDescription extends CRefactoringDescripti
|
||||||
|
|
||||||
info.setMethodName(arguments.get(NAME));
|
info.setMethodName(arguments.get(NAME));
|
||||||
info.setVisibility(VisibilityEnum.getEnumForStringRepresentation(arguments.get(VISIBILITY)));
|
info.setVisibility(VisibilityEnum.getEnumForStringRepresentation(arguments.get(VISIBILITY)));
|
||||||
|
info.setReplaceDuplicates(Boolean.parseBoolean(arguments.get(REPLACE_DUBLICATES)));
|
||||||
|
|
||||||
proj = getCProject();
|
proj = getCProject();
|
||||||
file = getFile();
|
file = getFile();
|
||||||
|
|
|
@ -34,7 +34,7 @@ public final class Messages extends NLS {
|
||||||
public static String ExtractFunctionComposite_ReturnValue;
|
public static String ExtractFunctionComposite_ReturnValue;
|
||||||
public static String ExtractFunctionRefactoring_CreateMethodDef;
|
public static String ExtractFunctionRefactoring_CreateMethodDef;
|
||||||
public static String ExtractFunctionRefactoring_CreateFunctionDef;
|
public static String ExtractFunctionRefactoring_CreateFunctionDef;
|
||||||
// public static String ExtractFunctionComposite_ReplaceDuplicates;
|
public static String ExtractFunctionComposite_ReplaceDuplicates;
|
||||||
public static String ExtractFunctionRefactoring_CreateMethodCall;
|
public static String ExtractFunctionRefactoring_CreateMethodCall;
|
||||||
public static String ExtractFunctionRefactoring_CreateFunctionCall;
|
public static String ExtractFunctionRefactoring_CreateFunctionCall;
|
||||||
public static String ChooserComposite_Return;
|
public static String ChooserComposite_Return;
|
||||||
|
|
|
@ -0,0 +1,146 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 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 java.util.List;
|
||||||
|
import java.util.Vector;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
|
import org.eclipse.core.resources.IFile;
|
||||||
|
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.ast.IASTStatement;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.cpp.CPPASTVisitor;
|
||||||
|
import org.eclipse.cdt.core.dom.rewrite.ASTRewrite;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.internal.ui.refactoring.ModificationCollector;
|
||||||
|
import org.eclipse.cdt.internal.ui.refactoring.NodeContainer;
|
||||||
|
import org.eclipse.cdt.internal.ui.refactoring.NodeContainer.NameInformation;
|
||||||
|
|
||||||
|
final class SimilarFinderVisitor extends CPPASTVisitor {
|
||||||
|
|
||||||
|
private final ExtractFunctionRefactoring refactoring;
|
||||||
|
|
||||||
|
private final Vector<IASTNode> trail;
|
||||||
|
private final IASTName name;
|
||||||
|
private final List<IASTNode> stmts;
|
||||||
|
private int i = 0;
|
||||||
|
private NodeContainer similarContainer;
|
||||||
|
private final List<IASTStatement> stmtToReplace = new ArrayList<IASTStatement>();
|
||||||
|
|
||||||
|
private final ModificationCollector collector;
|
||||||
|
|
||||||
|
SimilarFinderVisitor(ExtractFunctionRefactoring refactoring,
|
||||||
|
ModificationCollector collector, Vector<IASTNode> trail, IFile file, IASTName name,
|
||||||
|
List<IASTNode> stmts, String title) {
|
||||||
|
this.refactoring = refactoring;
|
||||||
|
this.trail = trail;
|
||||||
|
this.name = name;
|
||||||
|
this.stmts = stmts;
|
||||||
|
this.collector = collector;
|
||||||
|
this.similarContainer = new NodeContainer();
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
shouldVisitStatements = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int visit(IASTStatement stmt) {
|
||||||
|
|
||||||
|
boolean isAllreadyInMainRefactoring = isInSelection(stmt);
|
||||||
|
|
||||||
|
if( (!isAllreadyInMainRefactoring)
|
||||||
|
&& this.refactoring.isStatementInTrail(stmt, trail)){
|
||||||
|
stmtToReplace.add(stmt);
|
||||||
|
similarContainer.add(stmt);
|
||||||
|
++i;
|
||||||
|
|
||||||
|
if(i==stmts.size()){
|
||||||
|
//found similar code
|
||||||
|
|
||||||
|
boolean similarOnReturnWays = true;
|
||||||
|
for (NameInformation nameInfo : similarContainer.getAllAfterUsedNames()) {
|
||||||
|
if(this.refactoring.names.containsKey(nameInfo.getDeclaration().getRawSignature())){
|
||||||
|
Integer nameOrderNumber = this.refactoring.names.get(nameInfo.getDeclaration().getRawSignature());
|
||||||
|
if(this.refactoring.nameTrail.containsValue(nameOrderNumber)){
|
||||||
|
String orgName = null;
|
||||||
|
boolean found = false;
|
||||||
|
for (Entry<String, Integer> entry : this.refactoring.nameTrail.entrySet()) {
|
||||||
|
if(entry.getValue().equals(nameOrderNumber)){
|
||||||
|
orgName = entry.getKey();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(orgName != null){
|
||||||
|
for (NameInformation orgNameInfo : this.refactoring.container.getAllAfterUsedNamesChoosenByUser()) {
|
||||||
|
if( orgName.equals(orgNameInfo.getDeclaration().getRawSignature()) ){
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!found){
|
||||||
|
similarOnReturnWays = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(similarOnReturnWays){
|
||||||
|
System.out.println(6);
|
||||||
|
IASTNode call = refactoring.getMethodCall(name,
|
||||||
|
this.refactoring.nameTrail, this.refactoring.names,
|
||||||
|
this.refactoring.container, similarContainer);
|
||||||
|
ASTRewrite rewrite = collector.rewriterForTranslationUnit(stmtToReplace.get(0)
|
||||||
|
.getTranslationUnit());
|
||||||
|
TextEditGroup editGroup = new TextEditGroup("Replace Dublicated Code");
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
return PROCESS_SKIP;
|
||||||
|
} else {
|
||||||
|
clear();
|
||||||
|
return super.visit(stmt);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isInSelection(IASTStatement stmt) {
|
||||||
|
List<IASTNode>nodes = this.refactoring.container.getNodesToWrite();
|
||||||
|
for (IASTNode node : nodes) {
|
||||||
|
if(node.equals(stmt)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void clear() {
|
||||||
|
i = 0;
|
||||||
|
this.refactoring.names.clear();
|
||||||
|
similarContainer = new NodeContainer();
|
||||||
|
this.refactoring.namesCounter.setObject(ExtractFunctionRefactoring.NULL_INTEGER);
|
||||||
|
this.refactoring.trailPos.setObject(ExtractFunctionRefactoring.NULL_INTEGER);
|
||||||
|
stmtToReplace.clear();
|
||||||
|
}
|
||||||
|
}
|
|
@ -22,7 +22,7 @@ ExtractFunctionInputPage_1=is used after the extracted block - it needs to be pa
|
||||||
ExtractFunctionComposite_ReturnValue=Return value:
|
ExtractFunctionComposite_ReturnValue=Return value:
|
||||||
ExtractFunctionRefactoring_CreateMethodDef=Create Method Definition
|
ExtractFunctionRefactoring_CreateMethodDef=Create Method Definition
|
||||||
ExtractFunctionRefactoring_CreateFunctionDef=Create Function Definition
|
ExtractFunctionRefactoring_CreateFunctionDef=Create Function Definition
|
||||||
#ExtractFunctionComposite_ReplaceDuplicates=Replace all occurrences of statements with method.
|
ExtractFunctionComposite_ReplaceDuplicates=Replace all occurrences of statements with method.
|
||||||
ExtractFunctionRefactoring_CreateMethodCall=Create Method Call
|
ExtractFunctionRefactoring_CreateMethodCall=Create Method Call
|
||||||
ExtractFunctionRefactoring_CreateFunctionCall=Create Function Call
|
ExtractFunctionRefactoring_CreateFunctionCall=Create Function Call
|
||||||
ChooserComposite_Return=Return
|
ChooserComposite_Return=Return
|
||||||
|
|
Loading…
Add table
Reference in a new issue