SSR: copy implements, extends and type parameters correctly when replacing classes with inner classes

This commit is contained in:
Bas Leijdekkers
2016-09-26 15:03:19 +02:00
parent d36dd6587f
commit db546f6911
2 changed files with 48 additions and 21 deletions
@@ -1,3 +1,18 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.structuralsearch;
import com.intellij.openapi.fileTypes.StdFileTypes;
@@ -130,7 +145,6 @@ public class JavaReplaceHandler extends StructuralReplaceHandler {
* that are present in matched nodes but not present in searched & replaced nodes
*/
private void copyUnmatchedElements(final PsiElement original, final PsiElement replacement) {
Map<String, String> newNameToSearchPatternNameMap = myContext.getNewName2PatternNameMap();
Map<String, PsiNamedElement> originalNamedElements = Collector.collectNamedElements(original);
@@ -197,6 +211,18 @@ public class JavaReplaceHandler extends StructuralReplaceHandler {
replacementNamedElement instanceof PsiMethod) {
copyMethodBodyIfNotReplaced((PsiMethod)originalNamedElement, (PsiMethod)searchedNamedElement, (PsiMethod)replacementNamedElement);
}
if (originalNamedElement instanceof PsiClass &&
searchedNamedElement instanceof PsiClass &&
replacementNamedElement instanceof PsiClass) {
final PsiClass originalClass = (PsiClass)originalNamedElement;
final PsiClass queryClass = (PsiClass)searchedNamedElement;
final PsiClass replacementClass = (PsiClass)replacementNamedElement;
copyExtendsListIfNotReplaced(originalClass, queryClass, replacementClass);
copyImplementsListIfNotReplaced(originalClass, queryClass, replacementClass);
copyTypeParameterListIfNotReplaced(originalClass, queryClass, replacementClass);
}
}
}
@@ -361,26 +387,9 @@ public class JavaReplaceHandler extends StructuralReplaceHandler {
elementToReplace.getNode().getTreeParent().removeChild(elementToReplace.getNode());
}
else {
// preserve comments
copyUnmatchedElements(elementToReplace, replacement);
if (replacement instanceof PsiClass) {
final PsiStatement[] searchStatements = getCodeBlock().getStatements();
if (searchStatements.length > 0 &&
searchStatements[0] instanceof PsiDeclarationStatement &&
((PsiDeclarationStatement)searchStatements[0]).getDeclaredElements()[0] instanceof PsiClass) {
final PsiClass replaceClazz = (PsiClass)replacement;
final PsiClass queryClazz = (PsiClass)((PsiDeclarationStatement)searchStatements[0]).getDeclaredElements()[0];
final PsiClass clazz = (PsiClass)elementToReplace;
copyExtendsListIfNotReplaced(clazz, queryClazz, replaceClazz);
copyImplementsListIfNotReplaced(clazz, queryClazz, replaceClazz);
copyTypeParameterListIfNotReplaced(clazz, queryClazz, replaceClazz);
}
}
replacement = handleSymbolReplacement(replacement, elementToReplace);
elementToReplace.replace(replacement);
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -2455,7 +2455,8 @@ public class StructuralReplaceTest extends StructuralReplaceTestCase {
final String by = "void $a$(int i);";
assertEquals("abstract class A {\n" +
" abstract void a(int i);\n" +
"}", replacer.testReplace(in, what, by, options));
"}",
replacer.testReplace(in, what, by, options));
}
public void testReplaceParameterWithComment() {
@@ -2466,6 +2467,23 @@ public class StructuralReplaceTest extends StructuralReplaceTestCase {
final String by = "final long /*!*/ $a$ = $b$;";
assertEquals("class A {\n" +
" void a(final long /*!*/ b) {}\n" +
"}", replacer.testReplace(in, what, by, options));
"}",
replacer.testReplace(in, what, by, options));
}
public void testReplaceInnerClass() {
String in = "public class A {" +
" public class B<T> extends A implements Serializable {}" +
"}";
String what = "class '_A {" +
" class '_B {}" +
"}";
String by = "class $A$ {" +
" private class $B$ {}" +
"}";
assertEquals("public class A {" +
" private class B<T> extends A implements Serializable {}" +
"}",
replacer.testReplace(in, what, by, options));
}
}