push down/pull up: ensure raw substitutor correctly erase types in the target class (IDEA-155581)

This commit is contained in:
Anna.Kozlova
2016-05-04 20:18:45 +02:00
parent da211b4083
commit 5965c21f44
4 changed files with 52 additions and 7 deletions
@@ -803,17 +803,39 @@ public class RefactoringUtil {
final PsiElementFactory factory) {
final Map<PsiElement, PsiElement> replacement = new LinkedHashMap<PsiElement, PsiElement>();
for (PsiTypeParameter parameter : parametersIterable) {
PsiType substitutedType = substitutor.substitute(parameter);
if (substitutedType == null) {
substitutedType = TypeConversionUtil.erasure(factory.createType(parameter));
}
final PsiType substitutedType = substitutor.substitute(parameter);
final PsiType erasedType = substitutedType == null ? TypeConversionUtil.erasure(factory.createType(parameter))
: substitutedType;
for (PsiReference reference : ReferencesSearch.search(parameter, new LocalSearchScope(member))) {
final PsiElement element = reference.getElement();
final PsiElement parent = element.getParent();
if (parent instanceof PsiTypeElement) {
replacement.put(parent, factory.createTypeElement(substitutedType));
} else if (element instanceof PsiJavaCodeReferenceElement && substitutedType instanceof PsiClassType) {
replacement.put(element, factory.createReferenceElementByType((PsiClassType)substitutedType));
if (substitutedType == null) {
//extends/implements list of type parameters: S extends List<T>
final PsiJavaCodeReferenceElement codeReferenceElement = PsiTreeUtil.getTopmostParentOfType(parent, PsiJavaCodeReferenceElement.class);
if (codeReferenceElement != null) {
final PsiJavaCodeReferenceElement copy = (PsiJavaCodeReferenceElement)codeReferenceElement.copy();
final PsiReferenceParameterList parameterList = copy.getParameterList();
if (parameterList != null) {
parameterList.delete();
}
replacement.put(codeReferenceElement, copy);
}
else {
//nested types List<List<T> listOfLists;
PsiTypeElement topPsiTypeElement = PsiTreeUtil.getTopmostParentOfType(parent, PsiTypeElement.class);
if (topPsiTypeElement == null) {
topPsiTypeElement = (PsiTypeElement)parent;
}
replacement.put(topPsiTypeElement, factory.createTypeElement(TypeConversionUtil.erasure(topPsiTypeElement.getType())));
}
}
else {
replacement.put(parent, factory.createTypeElement(substitutedType));
}
}
else if (element instanceof PsiJavaCodeReferenceElement && erasedType instanceof PsiClassType) {
replacement.put(element, factory.createReferenceElementByType((PsiClassType)erasedType));
}
}
}
@@ -0,0 +1,9 @@
import java.util.*;
class A<T> {
<S extends T, K extends List<List<T>>> <caret>foo(List<? extends T> l1, List<? extends S> l2, List<? extends K> l3, S s, K k, T t) {
Collections.<T>emptyList();
}
}
class B extends A {}
@@ -0,0 +1,10 @@
import java.util.*;
class A<T> {
}
class B extends A {
<S extends Object, K extends List> B(List l1, List<? extends S> l2, List<? extends K> l3, S s, K k, Object t) {
Collections.emptyList();
}
}
@@ -79,6 +79,10 @@ public class PushDownTest extends LightRefactoringTestCase {
doTestImplements(true);
}
public void testErasureIfInheritsWithRawSubstitution() throws Exception {
doTest();
}
private void doTest() {
doTest(false);
}