frequently used super class inspection: fix npe when classes has the same method not defined in base class

This commit is contained in:
Dmitry Batkovich
2017-05-11 17:59:56 +03:00
parent 21db96b0e9
commit 2fd794b883
@@ -26,7 +26,6 @@ import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.util.Pair;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.impl.source.PsiExtensibleClass;
import com.intellij.refactoring.ui.MemberSelectionPanel;
import com.intellij.refactoring.util.classMembers.MemberInfo;
import com.intellij.util.ArrayUtil;
@@ -38,6 +37,7 @@ import org.jetbrains.annotations.TestOnly;
import javax.swing.*;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -116,15 +116,15 @@ public class ChangeSuperClassFix implements LocalQuickFix, HighPriorityAction {
private static void changeSuperClass(@NotNull final PsiClass aClass,
@NotNull final PsiClass oldSuperClass,
@NotNull final PsiClass newSuperClass) {
List<PsiMethod> ownMethods = ((PsiExtensibleClass)aClass).getOwnMethods();
PsiMethod[] ownMethods = aClass.getMethods();
// first is own method, second is parent
List<Pair<PsiMethod, Set<PsiMethod>>> oldOverridenMethods =
ownMethods.stream().map(m -> {
Stream.of(ownMethods).map(m -> {
if (m.isConstructor()) return null;
PsiMethod[] supers = m.findSuperMethods(oldSuperClass);
if (supers.length == 0) return null;
return Pair.create(m, ContainerUtil.set(supers));
}).collect(Collectors.toList());
}).filter(Objects::nonNull).collect(Collectors.toList());
JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(aClass.getProject());
PsiElementFactory factory = psiFacade.getElementFactory();
@@ -160,21 +160,28 @@ public class ChangeSuperClassFix implements LocalQuickFix, HighPriorityAction {
JavaCodeStyleManager.getInstance(aClass.getProject()).shortenClassReferences(ref);
});
if (ownMethods.isEmpty()) {
// should not override methods from a new super class
return;
}
Stream<PsiMethod> memberInfos = oldOverridenMethods.stream().filter(m -> {
List<MemberInfo> memberInfos = oldOverridenMethods.stream().filter(m -> {
Set<PsiMethod> newSupers = ContainerUtil.set(m.getFirst().findSuperMethods(newSuperClass));
return !newSupers.equals(m.getSecond());
}).map(m -> m.getFirst());
}).map(m -> m.getFirst())
.map(m -> {
MemberInfo info = new MemberInfo(m);
info.setChecked(true);
return info;
}).collect(Collectors.toList());
if (memberInfos.isEmpty()) {
return;
}
List<PsiMethod> toDelete = getOverridenMethodsToDelete(memberInfos, newSuperClass.getName(), aClass.getProject());
WriteAction.run(() -> {
for (PsiMethod method : toDelete) {
method.delete();
}
});
if (!toDelete.isEmpty()) {
WriteAction.run(() -> {
for (PsiMethod method : toDelete) {
method.delete();
}
});
}
}
@NotNull
@@ -183,26 +190,23 @@ public class ChangeSuperClassFix implements LocalQuickFix, HighPriorityAction {
}
@NotNull
private static List<PsiMethod> getOverridenMethodsToDelete(Stream<PsiMethod> candidates,
private static List<PsiMethod> getOverridenMethodsToDelete(List<MemberInfo> candidates,
String newClassName,
Project project) {
MemberSelectionPanel panel =
new MemberSelectionPanel("<html>Choose members to delete since they are already defined in <b>" + newClassName + "</b>",
candidates.map(m -> {
MemberInfo info = new MemberInfo(m);
info.setChecked(true);
return info;
}).collect(Collectors.toList()), null);
candidates,
null);
DialogWrapper dlg = new DialogWrapper(project, false) {
{
setOKButtonText("Remove");
setTitle("Choose Members");
init();
}
@NotNull
@Override
protected JComponent createCenterPanel() {
return panel;
}
};