diff --git a/java/java-impl/src/com/intellij/refactoring/memberPullUp/PullUpHelper.java b/java/java-impl/src/com/intellij/refactoring/memberPullUp/PullUpHelper.java index 70e9a96f3b63..09c00ac54a12 100644 --- a/java/java-impl/src/com/intellij/refactoring/memberPullUp/PullUpHelper.java +++ b/java/java-impl/src/com/intellij/refactoring/memberPullUp/PullUpHelper.java @@ -36,10 +36,7 @@ import com.intellij.psi.codeStyle.CodeStyleSettingsManager; import com.intellij.psi.search.LocalSearchScope; import com.intellij.psi.search.searches.OverridingMethodsSearch; import com.intellij.psi.search.searches.ReferencesSearch; -import com.intellij.psi.util.InheritanceUtil; -import com.intellij.psi.util.MethodSignatureUtil; -import com.intellij.psi.util.PsiTreeUtil; -import com.intellij.psi.util.PsiUtil; +import com.intellij.psi.util.*; import com.intellij.refactoring.BaseRefactoringProcessor; import com.intellij.refactoring.RefactoringBundle; import com.intellij.refactoring.listeners.JavaRefactoringListenerManager; @@ -109,6 +106,9 @@ public class PullUpHelper extends BaseRefactoringProcessor{ final HashSet movedMembers = new HashSet(); myMembersAfterMove = new HashSet(); + RefactoringUtil.replaceMovedMemberTypeParameters(myMembersToMove, PsiUtil.typeParametersIterable(mySourceClass), + upDownSuperClassSubstitutor(), + JavaPsiFacade.getElementFactory(myProject)); // build aux sets for (MemberInfo info : myMembersToMove) { movedMembers.add(info.getMember()); @@ -235,6 +235,23 @@ public class PullUpHelper extends BaseRefactoringProcessor{ } } + private PsiSubstitutor upDownSuperClassSubstitutor() { + PsiSubstitutor substitutor = PsiSubstitutor.EMPTY; + for (PsiTypeParameter parameter : PsiUtil.typeParametersIterable(mySourceClass)) { + substitutor = substitutor.put(parameter, null); + } + final Map substitutionMap = + TypeConversionUtil.getSuperClassSubstitutor(myTargetSuperClass, mySourceClass, PsiSubstitutor.EMPTY).getSubstitutionMap(); + for (PsiTypeParameter parameter : substitutionMap.keySet()) { + final PsiType type = substitutionMap.get(parameter); + final PsiClass resolvedClass = PsiUtil.resolveClassInType(type); + if (resolvedClass instanceof PsiTypeParameter) { + substitutor = substitutor.put((PsiTypeParameter)resolvedClass, JavaPsiFacade.getElementFactory(myProject).createType(parameter)); + } + } + return substitutor; + } + private static void deleteOverrideAnnotationIfFound(PsiMethod oMethod) { final PsiAnnotation annotation = AnnotationUtil.findAnnotation(oMethod, Override.class.getName()); if (annotation != null) { diff --git a/java/java-impl/src/com/intellij/refactoring/memberPushDown/PushDownProcessor.java b/java/java-impl/src/com/intellij/refactoring/memberPushDown/PushDownProcessor.java index 7e8331bdc982..7c045e40b621 100644 --- a/java/java-impl/src/com/intellij/refactoring/memberPushDown/PushDownProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/memberPushDown/PushDownProcessor.java @@ -327,24 +327,7 @@ public class PushDownProcessor extends BaseRefactoringProcessor { private void pushDownToClass(PsiClass targetClass) throws IncorrectOperationException { final PsiElementFactory factory = JavaPsiFacade.getInstance(myClass.getProject()).getElementFactory(); final PsiSubstitutor substitutor = TypeConversionUtil.getSuperClassSubstitutor(myClass, targetClass, PsiSubstitutor.EMPTY); - for (PsiTypeParameter parameter : PsiUtil.typeParametersIterable(myClass)) { - for (PsiReference reference : ReferencesSearch.search(parameter)) { - final PsiElement element = reference.getElement(); - final PsiMember member = PsiTreeUtil.getParentOfType(element, PsiMember.class); - if (member != null) { - for (MemberInfo memberInfo : myMemberInfos) { - if (PsiTreeUtil.isAncestor(memberInfo.getMember(), member, false)) { - PsiType substitutedType = substitutor.substitute(parameter); - if (substitutedType == null) { - substitutedType = TypeConversionUtil.erasure(factory.createType(parameter)); - } - element.getParent().replace(factory.createTypeElement(substitutedType)); - break; - } - } - } - } - } + RefactoringUtil.replaceMovedMemberTypeParameters(myMemberInfos, PsiUtil.typeParametersIterable(myClass), substitutor, factory); for (MemberInfo memberInfo : myMemberInfos) { final PsiMember member = memberInfo.getMember(); final List refsToRebind = new ArrayList(); diff --git a/java/java-impl/src/com/intellij/refactoring/util/RefactoringUtil.java b/java/java-impl/src/com/intellij/refactoring/util/RefactoringUtil.java index be67e1e2bdb2..e8feac848508 100644 --- a/java/java-impl/src/com/intellij/refactoring/util/RefactoringUtil.java +++ b/java/java-impl/src/com/intellij/refactoring/util/RefactoringUtil.java @@ -48,9 +48,11 @@ import com.intellij.psi.tree.IElementType; import com.intellij.psi.util.InheritanceUtil; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; +import com.intellij.psi.util.TypeConversionUtil; import com.intellij.refactoring.PackageWrapper; import com.intellij.refactoring.introduceField.ElementToWorkOn; import com.intellij.refactoring.introduceVariable.IntroduceVariableBase; +import com.intellij.refactoring.util.classMembers.MemberInfo; import com.intellij.usageView.UsageInfo; import com.intellij.util.IncorrectOperationException; import com.intellij.util.containers.HashMap; @@ -855,6 +857,27 @@ public class RefactoringUtil { return null; } + public static void replaceMovedMemberTypeParameters(final MemberInfo[] memberInfos, + final Iterable parametersIterable, + final PsiSubstitutor substitutor, + final PsiElementFactory factory) { + for (PsiTypeParameter parameter : parametersIterable) { + for (PsiReference reference : ReferencesSearch.search(parameter)) { + final PsiElement element = reference.getElement(); + for (MemberInfo memberInfo : memberInfos) { + if (PsiTreeUtil.isAncestor(memberInfo.getMember(), element, false)) { + PsiType substitutedType = substitutor.substitute(parameter); + if (substitutedType == null) { + substitutedType = TypeConversionUtil.erasure(factory.createType(parameter)); + } + element.getParent().replace(factory.createTypeElement(substitutedType)); + break; + } + } + } + } + } + public static interface ImplicitConstructorUsageVisitor { void visitConstructor(PsiMethod constructor, PsiMethod baseConstructor); diff --git a/java/java-tests/testData/refactoring/pullUp/TypeArgument.java b/java/java-tests/testData/refactoring/pullUp/TypeArgument.java new file mode 100644 index 000000000000..21140c87bb61 --- /dev/null +++ b/java/java-tests/testData/refactoring/pullUp/TypeArgument.java @@ -0,0 +1,5 @@ +public class Parent {} + +class Child extends Parent { + String f; +} diff --git a/java/java-tests/testData/refactoring/pullUp/TypeArgument_after.java b/java/java-tests/testData/refactoring/pullUp/TypeArgument_after.java new file mode 100644 index 000000000000..6530ecf73544 --- /dev/null +++ b/java/java-tests/testData/refactoring/pullUp/TypeArgument_after.java @@ -0,0 +1,6 @@ +public class Parent { + String f; +} + +class Child extends Parent { +} diff --git a/java/java-tests/testData/refactoring/pullUp/TypeParamErasure.java b/java/java-tests/testData/refactoring/pullUp/TypeParamErasure.java new file mode 100644 index 000000000000..0dbc24fce32d --- /dev/null +++ b/java/java-tests/testData/refactoring/pullUp/TypeParamErasure.java @@ -0,0 +1,5 @@ +public class Parent {} + +class Child extends Parent { + T f; +} diff --git a/java/java-tests/testData/refactoring/pullUp/TypeParamErasure_after.java b/java/java-tests/testData/refactoring/pullUp/TypeParamErasure_after.java new file mode 100644 index 000000000000..fbe98dad3bae --- /dev/null +++ b/java/java-tests/testData/refactoring/pullUp/TypeParamErasure_after.java @@ -0,0 +1,6 @@ +public class Parent { + Object f; +} + +class Child extends Parent { +} diff --git a/java/java-tests/testData/refactoring/pullUp/TypeParamSubst.java b/java/java-tests/testData/refactoring/pullUp/TypeParamSubst.java new file mode 100644 index 000000000000..f2ad0c7e8dae --- /dev/null +++ b/java/java-tests/testData/refactoring/pullUp/TypeParamSubst.java @@ -0,0 +1,5 @@ +public class Parent {} + +class Child extends Parent { + T f; +} diff --git a/java/java-tests/testData/refactoring/pullUp/TypeParamSubst_after.java b/java/java-tests/testData/refactoring/pullUp/TypeParamSubst_after.java new file mode 100644 index 000000000000..bc7474517976 --- /dev/null +++ b/java/java-tests/testData/refactoring/pullUp/TypeParamSubst_after.java @@ -0,0 +1,6 @@ +public class Parent { + S f; +} + +class Child extends Parent { +} diff --git a/java/java-tests/testSrc/com/intellij/refactoring/PullUpTest.java b/java/java-tests/testSrc/com/intellij/refactoring/PullUpTest.java index 956fd609bc99..6885618d24ee 100644 --- a/java/java-tests/testSrc/com/intellij/refactoring/PullUpTest.java +++ b/java/java-tests/testSrc/com/intellij/refactoring/PullUpTest.java @@ -67,6 +67,18 @@ public class PullUpTest extends LightCodeInsightTestCase { doTest(new MemberDescriptor ("get", PsiMethod.class)); } + public void testTypeParamErasure() throws Exception { + doTest(new MemberDescriptor("f", PsiField.class)); + } + + public void testTypeParamSubst() throws Exception { + doTest(new MemberDescriptor("f", PsiField.class)); + } + + public void testTypeArgument() throws Exception { + doTest(new MemberDescriptor("f", PsiField.class)); + } + private void doTest(MemberDescriptor... membersToFind) throws Exception { configureByFile(BASE_PATH + getTestName(false) + ".java"); PsiElement elementAt = getFile().findElementAt(getEditor().getCaretModel().getOffset());