Skip to content

Commit

Permalink
Fix move refactor to recognize super class name collision (#1704)
Browse files Browse the repository at this point in the history
- fix MoveInstanceMethodProcessor to recognize when a member being
  moved has same name as a member of a super class of the target
  and change existing references to use super qualifier
- add new test to MoveInstanceMethodTests
- fixes #1676
  • Loading branch information
jjohnstn authored Oct 7, 2024
1 parent 8f8fafd commit 0d7e5c5
Show file tree
Hide file tree
Showing 4 changed files with 133 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2238,6 +2238,7 @@ protected TextChangeManager createChangeManager(final RefactoringStatus status,
adjustor.rewriteVisibility(Progress.subMonitor(monitor, 1));
sourceRewrite.rewriteAST(document, fMethod.getCompilationUnit().getOptions(true));
createMethodSignature(document, declaration, sourceRewrite, rewrites);
modifyInheritedMethodCalls(document, declaration, sourceRewrite, rewrites);
ICompilationUnit unit= null;
CompilationUnitRewrite rewrite= null;
for (final Iterator<ICompilationUnit> iterator= rewrites.keySet().iterator(); iterator.hasNext();) {
Expand Down Expand Up @@ -3035,6 +3036,89 @@ protected void createMethodSignature(final IDocument document, final MethodDecla
}
}

private class SuperMethodChecker extends ASTVisitor {
private final CompilationUnitRewrite fRewriter;

public SuperMethodChecker(final CompilationUnitRewrite rewriter) {
fRewriter= rewriter;
}

@Override
public boolean visit(MethodInvocation node) {
if (node.getName().getFullyQualifiedName().equals(fMethodName)) {
IMethodBinding methodBinding= node.resolveMethodBinding();
if (methodBinding != null) {
ITypeBinding typeBinding= methodBinding.getDeclaringClass();
if (typeBinding != null) {
ITypeBinding targetTypeBinding= fTarget.getType();
if (!typeBinding.isEqualTo(targetTypeBinding) && findInHierarchy(typeBinding, targetTypeBinding)) {
ASTRewrite astRewrite= fRewriter.getASTRewrite();
AST ast= node.getAST();
SuperMethodInvocation superMethod= ast.newSuperMethodInvocation();
superMethod.setName(ast.newSimpleName(node.getName().getFullyQualifiedName()));
ListRewrite typeArgs= astRewrite.getListRewrite(node, MethodInvocation.TYPE_ARGUMENTS_PROPERTY);
List<Type> originalTypeList= typeArgs.getOriginalList();
if (originalTypeList.size() > 0) {
ASTNode typeArgsCopy= typeArgs.createCopyTarget(originalTypeList.get(0), originalTypeList.get(originalTypeList.size() - 1));
superMethod.typeArguments().add(typeArgsCopy);
}
ListRewrite args= astRewrite.getListRewrite(node, MethodInvocation.ARGUMENTS_PROPERTY);
List<Type> originalArgsList= args.getOriginalList();
if (originalArgsList.size() > 0) {
ASTNode argsCopy= typeArgs.createCopyTarget(originalArgsList.get(0), originalArgsList.get(originalTypeList.size() - 1));
superMethod.arguments().add(argsCopy);
}
astRewrite.replace(node, superMethod, null);
}
}
}
}
return true;
}

private boolean findInHierarchy(ITypeBinding toFind, ITypeBinding binding) {
if (binding == null) {
return false;
}
if (toFind.isEqualTo(binding)) {
return true;
}
if (findInHierarchy(toFind, binding.getSuperclass())) {
return true;
}
ITypeBinding[] bindingInterfaces= binding.getInterfaces();
for (ITypeBinding bindingInterface : bindingInterfaces) {
if (findInHierarchy(toFind, bindingInterface)) {
return true;
}
}
return false;
}
}

/**
* @param document
* the buffer containing the source of the source compilation
* unit
* @param declaration
* the method declaration to use as source
* @param rewrite
* the ast rewrite to use for the copy of the method body
* @param rewrites
* the compilation unit rewrites
* @throws JavaModelException
* if the insertion point cannot be found
*/
protected void modifyInheritedMethodCalls(final IDocument document, final MethodDeclaration declaration, final ASTRewrite rewrite, final Map<ICompilationUnit, CompilationUnitRewrite> rewrites) throws JavaModelException {
Assert.isNotNull(document);
Assert.isNotNull(declaration);
Assert.isNotNull(rewrite);
Assert.isNotNull(rewrites);
final CompilationUnitRewrite rewriter= getCompilationUnitRewrite(rewrites, getTargetType().getCompilationUnit());
final AbstractTypeDeclaration type= ASTNodeSearchUtil.getAbstractTypeDeclarationNode(getTargetType(), rewriter.getRoot());
type.accept(new SuperMethodChecker(rewriter));
}

/**
* Creates the necessary changes to remove method type parameters if they
* match with enclosing type parameters.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package p1;

class A {
B b;

void method() {
System.out.println("A class method");
}
}

class ParentClass {
void method() {
System.out.println("ParentClass method");
}
}

class B extends ParentClass {
void test() {
method();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package p1;

class A {
B b;
}

class ParentClass {
void method() {
System.out.println("ParentClass method");
}
}

class B extends ParentClass {
void test() {
super.method();
}

void method() {
System.out.println("A class method");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -708,6 +708,13 @@ public void test78() throws Exception {
public void test79() throws Exception {
helper1(new String[] { "A" }, "A", 11, 17, 11, 18, FIELD, "b", true, true);
}

@Test
public void test80() throws Exception {
helper1(new String[] { "A" }, "A", 6, 10, 6, 16, FIELD, "b", true, true);
}


// Move mA1 to field fB, do not inline delegator
@Test
public void test3() throws Exception {
Expand Down

0 comments on commit 0d7e5c5

Please sign in to comment.