1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-09-10 03:53:21 +02:00

Bug 423126 - Extract Function refactoring misses additional occurrences

of the extracted code
This commit is contained in:
Sergey Prigogin 2013-12-03 18:16:43 -08:00
parent 090345f405
commit 772f6c1643
5 changed files with 133 additions and 51 deletions

View file

@ -37,7 +37,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
* Scope of a function, containing labels. * Scope of a function, containing labels.
*/ */
public class CPPFunctionScope extends CPPScope implements ICPPFunctionScope { public class CPPFunctionScope extends CPPScope implements ICPPFunctionScope {
private CharArrayObjectMap<IBinding> labels = CharArrayObjectMap.emptyMap(); private CharArrayObjectMap<ILabel> labels = CharArrayObjectMap.emptyMap();
/** /**
* @param physicalNode * @param physicalNode
@ -58,13 +58,9 @@ public class CPPFunctionScope extends CPPScope implements ICPPFunctionScope {
return; return;
if (labels == CharArrayObjectMap.EMPTY_MAP) if (labels == CharArrayObjectMap.EMPTY_MAP)
labels = new CharArrayObjectMap<IBinding>(2); labels = new CharArrayObjectMap<ILabel>(2);
labels.put(binding.getNameCharArray(), binding); labels.put(binding.getNameCharArray(), (ILabel) binding);
}
public IBinding getBinding(IASTName name) {
return labels.get(name.getLookupKey());
} }
@Override @Override

View file

@ -23,11 +23,11 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
import org.eclipse.core.runtime.PlatformObject; import org.eclipse.core.runtime.PlatformObject;
public class CPPLabel extends PlatformObject implements ILabel, ICPPInternalBinding { public class CPPLabel extends PlatformObject implements ILabel, ICPPInternalBinding {
private IASTName statement; private IASTName name;
public CPPLabel(IASTName statement) { public CPPLabel(IASTName name) {
this.statement = statement; this.name = name;
statement.setBinding(this); name.setBinding(this);
} }
@Override @Override
@ -37,11 +37,12 @@ public class CPPLabel extends PlatformObject implements ILabel, ICPPInternalBind
@Override @Override
public IASTNode getDefinition() { public IASTNode getDefinition() {
return statement; return name;
} }
@Override @Override
public IASTLabelStatement getLabelStatement() { public IASTLabelStatement getLabelStatement() {
IASTNode statement = name.getParent();
if (statement instanceof IASTLabelStatement) if (statement instanceof IASTLabelStatement)
return (IASTLabelStatement) statement; return (IASTLabelStatement) statement;
@ -56,20 +57,20 @@ public class CPPLabel extends PlatformObject implements ILabel, ICPPInternalBind
@Override @Override
public char[] getNameCharArray() { public char[] getNameCharArray() {
return statement.getSimpleID(); return name.getSimpleID();
} }
@Override @Override
public IScope getScope() { public IScope getScope() {
return CPPVisitor.getContainingScope(statement); return CPPVisitor.getContainingScope(name);
} }
public IASTNode getPhysicalNode() { public IASTNode getPhysicalNode() {
return statement; return name;
} }
public void setLabelStatement(IASTName labelStatement) { public void setLabelStatement(IASTName labelStatement) {
statement = labelStatement; name = labelStatement;
} }
@Override @Override
@ -102,7 +103,7 @@ public class CPPLabel extends PlatformObject implements ILabel, ICPPInternalBind
@Override @Override
public IBinding getOwner() { public IBinding getOwner() {
return CPPVisitor.findEnclosingFunction(statement); return CPPVisitor.findEnclosingFunction(name);
} }
@Override @Override

View file

@ -2919,6 +2919,7 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase {
public void testDuplicates() throws Exception { public void testDuplicates() throws Exception {
assertRefactoringSuccess(); assertRefactoringSuccess();
} }
//A.h //A.h
//#ifndef A_H_ //#ifndef A_H_
//#define A_H_ //#define A_H_
@ -4192,6 +4193,78 @@ public class ExtractFunctionRefactoringTest extends RefactoringTestBase {
assertRefactoringSuccess(); assertRefactoringSuccess();
} }
//test.cpp
//template<typename T>
//void p(T p) {}
//
//#define TRACE(var) p(__LINE__), p(": "), p(#var), p("="), p(var)
//
//void test(int x, int y) {
// /*$*/TRACE(x);/*$$*/
// TRACE(y);
// TRACE(x);
//}
//====================
//template<typename T>
//void p(T p) {}
//
//#define TRACE(var) p(__LINE__), p(": "), p(#var), p("="), p(var)
//
//void extracted(int x) {
// TRACE(x);
//}
//
//void test(int x, int y) {
// extracted(x);
// TRACE(y);
// extracted(x);
//}
public void testLiteralFromMacro() throws Exception {
assertRefactoringSuccess();
}
//test.cpp
//#define LABEL(a, b) a ## b
//#define MACRO1(cond1, cond2, var, n) \
//if (cond1) { \
// if (cond2) { \
// var++; \
// goto LABEL(label, n); \
// } \
//} else LABEL(label, n): \
// var--
//#define MACRO(var) MACRO1(true, false, var, __COUNTER__)
//
//void test1(int x, int y) {
// MACRO(x);
// MACRO(y);
// /*$*/MACRO(x);/*$$*/
//}
//====================
//#define LABEL(a, b) a ## b
//#define MACRO1(cond1, cond2, var, n) \
//if (cond1) { \
// if (cond2) { \
// var++; \
// goto LABEL(label, n); \
// } \
//} else LABEL(label, n): \
// var--
//#define MACRO(var) MACRO1(true, false, var, __COUNTER__)
//
//void extracted(int x) {
// MACRO(x);
//}
//
//void test1(int x, int y) {
// extracted(x);
// MACRO(y);
// extracted(x);
//}
public void testLabelFromMacro() throws Exception {
assertRefactoringSuccess();
}
//A.h //A.h
//#ifndef A_H_ //#ifndef A_H_
//#define A_H_ //#define A_H_

View file

@ -703,8 +703,9 @@ public class ExtractFunctionRefactoring extends CRefactoring {
boolean theRetName = false; boolean theRetName = false;
for (NameInformation nameInfo : info.getParameters()) { for (NameInformation nameInfo : info.getParameters()) {
Integer trailSeqNumber = trailNameTable.get(nameInfo.getDeclarationName().getRawSignature());
String origName = null; String origName = null;
Integer trailSeqNumber = trailNameTable.get(nameInfo.getDeclarationName().getRawSignature());
if (trailSeqNumber != null) {
for (Entry<String, Integer> entry : similarNameTable.entrySet()) { for (Entry<String, Integer> entry : similarNameTable.entrySet()) {
if (entry.getValue().equals(trailSeqNumber)) { if (entry.getValue().equals(trailSeqNumber)) {
origName = entry.getKey(); origName = entry.getKey();
@ -713,6 +714,9 @@ public class ExtractFunctionRefactoring extends CRefactoring {
} }
} }
} }
} else {
origName = String.valueOf(nameInfo.getDeclarationName().getSimpleID());
}
if (origName != null) { if (origName != null) {
boolean found = false; boolean found = false;
@ -773,7 +777,9 @@ public class ExtractFunctionRefactoring extends CRefactoring {
private IASTNode getReturnAssignment(IASTExpressionStatement stmt, private IASTNode getReturnAssignment(IASTExpressionStatement stmt,
IASTFunctionCallExpression callExpression, IASTName retname) { IASTFunctionCallExpression callExpression, IASTName retname) {
if (info.getReturnVariable().equals(info.getMandatoryReturnVariable())) { if (info.getReturnVariable().equals(info.getMandatoryReturnVariable())) {
IASTSimpleDeclaration orgDecl = CPPVisitor.findAncestorWithType(info.getReturnVariable().getDeclarationName(), IASTSimpleDeclaration.class); IASTSimpleDeclaration orgDecl =
CPPVisitor.findAncestorWithType(info.getReturnVariable().getDeclarationName(),
IASTSimpleDeclaration.class);
IASTSimpleDeclaration decl = new CPPASTSimpleDeclaration(); IASTSimpleDeclaration decl = new CPPASTSimpleDeclaration();
decl.setDeclSpecifier(orgDecl.getDeclSpecifier().copy(CopyStyle.withLocations)); decl.setDeclSpecifier(orgDecl.getDeclSpecifier().copy(CopyStyle.withLocations));
@ -804,8 +810,7 @@ public class ExtractFunctionRefactoring extends CRefactoring {
return getReturnAssignment(stmt, binaryExpression); return getReturnAssignment(stmt, binaryExpression);
} }
private IASTNode getReturnAssignment(IASTExpressionStatement stmt, private IASTNode getReturnAssignment(IASTExpressionStatement stmt, IASTExpression callExpression) {
IASTExpression callExpression) {
IASTNode node = container.getNodesToWrite().get(0); IASTNode node = container.getNodesToWrite().get(0);
return extractor.createReturnAssignment(node, stmt, callExpression); return extractor.createReturnAssignment(node, stmt, callExpression);
} }

View file

@ -41,6 +41,7 @@ import org.eclipse.cdt.core.dom.ast.IASTStatement;
import org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression; import org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression;
import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression; import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression;
import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.ILabel;
import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.c.ICASTDeclSpecifier; import org.eclipse.cdt.core.dom.ast.c.ICASTDeclSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCatchHandler; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCatchHandler;
@ -121,7 +122,7 @@ public class TrailNodeEqualityChecker implements EqualityChecker<IASTNode> {
return trailName.equals(name); return trailName.equals(name);
} else if (trailNode instanceof TrailName && node instanceof IASTName) { } else if (trailNode instanceof TrailName && node instanceof IASTName) {
TrailName trailName = (TrailName) trailNode; TrailName trailName = (TrailName) trailNode;
IASTName name = (IASTName)node; IASTName name = (IASTName) node;
return isNameEqual(trailName, name); return isNameEqual(trailName, name);
} else { } else {
return true; return true;
@ -275,7 +276,7 @@ public class TrailNodeEqualityChecker implements EqualityChecker<IASTNode> {
} else if (trailNode instanceof IASTLiteralExpression) { } else if (trailNode instanceof IASTLiteralExpression) {
IASTLiteralExpression trailLiteral = (IASTLiteralExpression) trailNode; IASTLiteralExpression trailLiteral = (IASTLiteralExpression) trailNode;
IASTLiteralExpression literal = (IASTLiteralExpression) node; IASTLiteralExpression literal = (IASTLiteralExpression) node;
return trailLiteral.getKind() == literal.getKind() && trailLiteral.toString().equals(literal.toString()); return trailLiteral.getKind() == literal.getKind() && trailLiteral.getRawSignature().equals(literal.getRawSignature());
} else if (trailNode instanceof IASTUnaryExpression) { } else if (trailNode instanceof IASTUnaryExpression) {
IASTUnaryExpression trailExpr = (IASTUnaryExpression) trailNode; IASTUnaryExpression trailExpr = (IASTUnaryExpression) trailNode;
IASTUnaryExpression expr = (IASTUnaryExpression) node; IASTUnaryExpression expr = (IASTUnaryExpression) node;
@ -359,9 +360,10 @@ public class TrailNodeEqualityChecker implements EqualityChecker<IASTNode> {
return false; return false;
} }
if (trailName.isGloballyQualified()) { IASTName realName = trailName.getRealName();
IBinding realBind = trailName.getRealName().resolveBinding(); IBinding realBind = realName.resolveBinding();
IBinding nameBind = name.resolveBinding(); IBinding nameBind = name.resolveBinding();
if (trailName.isGloballyQualified()) {
IIndexName[] realDecs; IIndexName[] realDecs;
IIndexName[] nameDecs; IIndexName[] nameDecs;
try { try {
@ -371,7 +373,9 @@ public class TrailNodeEqualityChecker implements EqualityChecker<IASTNode> {
CUIPlugin.log(e); CUIPlugin.log(e);
return false; return false;
} }
if (realDecs.length == nameDecs.length) {
if (realDecs.length != nameDecs.length)
return false;
for (int i = 0; i < realDecs.length; ++i) { for (int i = 0; i < realDecs.length; ++i) {
IASTFileLocation rfl = realDecs[i].getFileLocation(); IASTFileLocation rfl = realDecs[i].getFileLocation();
IASTFileLocation nfl = nameDecs[i].getFileLocation(); IASTFileLocation nfl = nameDecs[i].getFileLocation();
@ -380,17 +384,20 @@ public class TrailNodeEqualityChecker implements EqualityChecker<IASTNode> {
} }
return true; return true;
} else { } else {
return false; if (realBind instanceof ILabel && nameBind instanceof ILabel) {
if (realName.getRawSignature().equals(name.getRawSignature())) {
return true;
} }
} else { } else {
IType oType = getType(trailName.getRealName().resolveBinding()); IType oType = getType(realBind);
IType nType = getType(name.resolveBinding()); IType nType = getType(nameBind);
if (oType == null || nType == null) if (oType == null || nType == null)
return false; return false;
if (oType.isSameType(nType)) if (oType.isSameType(nType))
return true; return true;
} }
}
return false; return false;
} }