mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-01-04 17:20:55 +07:00
pull up: erasure type parameters or try to substitute (IDEA-53490)
This commit is contained in:
@@ -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<PsiMember> movedMembers = new HashSet<PsiMember>();
|
||||
myMembersAfterMove = new HashSet<PsiMember>();
|
||||
|
||||
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<PsiTypeParameter, PsiType> 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) {
|
||||
|
||||
@@ -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<PsiReference> refsToRebind = new ArrayList<PsiReference>();
|
||||
|
||||
@@ -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<PsiTypeParameter> 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);
|
||||
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
public class Parent<S> {}
|
||||
|
||||
class Child extends Parent<String> {
|
||||
String <caret>f;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
public class Parent<S> {
|
||||
String f;
|
||||
}
|
||||
|
||||
class Child extends Parent<String> {
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
public class Parent {}
|
||||
|
||||
class Child<T> extends Parent {
|
||||
T <caret>f;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
public class Parent {
|
||||
Object f;
|
||||
}
|
||||
|
||||
class Child<T> extends Parent {
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
public class Parent<S> {}
|
||||
|
||||
class Child<T> extends Parent<T> {
|
||||
T <caret>f;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
public class Parent<S> {
|
||||
S f;
|
||||
}
|
||||
|
||||
class Child<T> extends Parent<T> {
|
||||
}
|
||||
@@ -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());
|
||||
|
||||
Reference in New Issue
Block a user