mirror of
https://gitflic.ru/project/openide/openide.git
synced 2025-12-16 14:23:28 +07:00
extract superclass: do not extract class type parameter if method one is used
This commit is contained in:
@@ -18,6 +18,7 @@ package com.intellij.refactoring.extractSuperclass;
|
||||
import com.intellij.codeInsight.generation.OverrideImplementUtil;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.CodeStyleManager;
|
||||
import com.intellij.psi.util.MethodSignature;
|
||||
@@ -30,6 +31,7 @@ import com.intellij.refactoring.util.classMembers.MemberInfo;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@@ -162,27 +164,34 @@ public class ExtractSuperClassUtil {
|
||||
for (final MemberInfo info : selectedMembers) {
|
||||
movedElements.add(info.getMember());
|
||||
}
|
||||
final PsiTypeParameterList typeParameterList = RefactoringUtil.createTypeParameterListWithUsedTypeParameters(
|
||||
movedElements.toArray(new PsiElement[movedElements.size()]));
|
||||
final PsiTypeParameterList typeParameterList = RefactoringUtil.createTypeParameterListWithUsedTypeParameters(null, new Condition<PsiTypeParameter>() {
|
||||
@Override
|
||||
public boolean value(PsiTypeParameter parameter) {
|
||||
return findTypeParameterInDerived(derivedClass, parameter.getName()) != null;
|
||||
}
|
||||
}, movedElements.toArray(new PsiElement[movedElements.size()]));
|
||||
final PsiTypeParameterList originalTypeParameterList = superClass.getTypeParameterList();
|
||||
assert originalTypeParameterList != null;
|
||||
final PsiTypeParameterList newList = typeParameterList != null ? (PsiTypeParameterList)originalTypeParameterList.replace(typeParameterList) : originalTypeParameterList;
|
||||
final PsiElementFactory factory = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory();
|
||||
Map<PsiTypeParameter, PsiType> substitutionMap = new HashMap<PsiTypeParameter, PsiType>();
|
||||
for (final PsiTypeParameter parameter : newList.getTypeParameters()) {
|
||||
substitutionMap.put(parameter, factory.createType(findTypeParameterInDerived(derivedClass, parameter.getName())));
|
||||
final PsiTypeParameter parameterInDerived = findTypeParameterInDerived(derivedClass, parameter.getName());
|
||||
if (parameterInDerived != null) {
|
||||
substitutionMap.put(parameter, factory.createType(parameterInDerived));
|
||||
}
|
||||
}
|
||||
|
||||
final PsiClassType type = factory.createType(superClass, factory.createSubstitutor(substitutionMap));
|
||||
return factory.createReferenceElementByType(type);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiTypeParameter findTypeParameterInDerived(final PsiClass aClass, final String name) {
|
||||
for (PsiTypeParameter typeParameter : PsiUtil.typeParametersIterable(aClass)) {
|
||||
if (name.equals(typeParameter.getName())) return typeParameter;
|
||||
}
|
||||
|
||||
LOG.error("Cannot find type parameter");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1196,12 +1196,20 @@ public class RefactoringUtil {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiTypeParameterList createTypeParameterListWithUsedTypeParameters(final PsiTypeParameterList fromList, @NotNull final PsiElement... elements) {
|
||||
public static PsiTypeParameterList createTypeParameterListWithUsedTypeParameters(final PsiTypeParameterList fromList,
|
||||
@NotNull final PsiElement... elements) {
|
||||
return createTypeParameterListWithUsedTypeParameters(fromList, Condition.TRUE, elements);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiTypeParameterList createTypeParameterListWithUsedTypeParameters(final PsiTypeParameterList fromList,
|
||||
Condition<PsiTypeParameter> filter,
|
||||
@NotNull final PsiElement... elements) {
|
||||
if (elements.length == 0) return null;
|
||||
final Set<PsiTypeParameter> used = new HashSet<PsiTypeParameter>();
|
||||
for (final PsiElement element : elements) {
|
||||
if (element == null) continue;
|
||||
collectTypeParameters(used, element); //pull up extends cls class with type params
|
||||
collectTypeParameters(used, element, filter); //pull up extends cls class with type params
|
||||
|
||||
}
|
||||
|
||||
@@ -1235,6 +1243,10 @@ public class RefactoringUtil {
|
||||
}
|
||||
|
||||
public static void collectTypeParameters(final Set<PsiTypeParameter> used, final PsiElement element) {
|
||||
collectTypeParameters(used, element, Condition.TRUE);
|
||||
}
|
||||
public static void collectTypeParameters(final Set<PsiTypeParameter> used, final PsiElement element,
|
||||
final Condition<PsiTypeParameter> filter) {
|
||||
element.accept(new JavaRecursiveElementVisitor() {
|
||||
@Override public void visitReferenceElement(PsiJavaCodeReferenceElement reference) {
|
||||
super.visitReferenceElement(reference);
|
||||
@@ -1242,7 +1254,7 @@ public class RefactoringUtil {
|
||||
final PsiElement resolved = reference.resolve();
|
||||
if (resolved instanceof PsiTypeParameter) {
|
||||
final PsiTypeParameter typeParameter = (PsiTypeParameter)resolved;
|
||||
if (PsiTreeUtil.isAncestor(typeParameter.getOwner(), element, false)) {
|
||||
if (PsiTreeUtil.isAncestor(typeParameter.getOwner(), element, false) && filter.value(typeParameter)) {
|
||||
used.add(typeParameter);
|
||||
}
|
||||
}
|
||||
@@ -1254,7 +1266,8 @@ public class RefactoringUtil {
|
||||
super.visitExpression(expression);
|
||||
final PsiType type = expression.getType();
|
||||
final PsiClass resolved = PsiUtil.resolveClassInType(type);
|
||||
if (resolved instanceof PsiTypeParameter && PsiTreeUtil.isAncestor(((PsiTypeParameter)resolved).getOwner(), element, false)){
|
||||
if (resolved instanceof PsiTypeParameter && PsiTreeUtil.isAncestor(((PsiTypeParameter)resolved).getOwner(), element, false) && filter.value(
|
||||
(PsiTypeParameter)resolved)){
|
||||
used.add((PsiTypeParameter)resolved);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
public class Test {
|
||||
public <T> T m(){return null;}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
public class TestSubclass extends Test {
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
public class Test {
|
||||
public <T> T m(){return null;}
|
||||
}
|
||||
@@ -41,6 +41,10 @@ public class ExtractSuperClassTest extends CodeInsightTestCase {
|
||||
doTest("Test", "TestSubclass", new RefactoringTestUtil.MemberDescriptor("x", PsiField.class));
|
||||
}
|
||||
|
||||
public void testMethodTypeParameter() throws Exception {
|
||||
doTest("Test", "TestSubclass", new RefactoringTestUtil.MemberDescriptor("m", PsiMethod.class));
|
||||
}
|
||||
|
||||
public void testConflictUsingPrivateMethod() throws Exception {
|
||||
doTest("Test", "TestSubclass",
|
||||
new String[] {"Method <b><code>Test.foo()</code></b> is private and will not be accessible from method <b><code>x()</code></b>."},
|
||||
|
||||
Reference in New Issue
Block a user