mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
SafeDelete: support sealed classes (IDEA-243902)
GitOrigin-RevId: 1b2c6f68d91e519736787f8cfbd9e8be57a7ead0
This commit is contained in:
committed by
intellij-monorepo-bot
parent
6ca02a49fc
commit
895bf1829e
@@ -572,11 +572,16 @@ public class JavaSafeDeleteProcessor extends SafeDeleteProcessorDelegateBase {
|
||||
if (parent instanceof PsiReferenceList) {
|
||||
final PsiElement pparent = parent.getParent();
|
||||
if (pparent instanceof PsiClass && element instanceof PsiJavaCodeReferenceElement) {
|
||||
PsiJavaCodeReferenceElement classRef = (PsiJavaCodeReferenceElement) element;
|
||||
final PsiClass inheritor = (PsiClass) pparent;
|
||||
if (parent.equals(inheritor.getPermitsList())) {
|
||||
usages.add(new SafeDeletePermitsClassUsageInfo(classRef, psiClass, inheritor));
|
||||
return true;
|
||||
}
|
||||
//If psiClass contains only private members, then it is safe to remove it and change inheritor's extends/implements accordingly
|
||||
if (justPrivates) {
|
||||
if (parent.equals(inheritor.getExtendsList()) || parent.equals(inheritor.getImplementsList())) {
|
||||
usages.add(new SafeDeleteExtendsClassUsageInfo((PsiJavaCodeReferenceElement)element, psiClass, inheritor));
|
||||
usages.add(new SafeDeleteExtendsClassUsageInfo(classRef, psiClass, inheritor));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.refactoring.safeDelete.usageInfo;
|
||||
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiClassType;
|
||||
import com.intellij.psi.PsiJavaCodeReferenceElement;
|
||||
import com.intellij.psi.PsiReferenceList;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.siyeh.ig.psiutils.ClassUtils;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class SafeDeletePermitsClassUsageInfo extends SafeDeleteReferenceUsageInfo {
|
||||
private final PsiClass myParentClass;
|
||||
|
||||
public SafeDeletePermitsClassUsageInfo(final PsiJavaCodeReferenceElement reference, PsiClass refClass, PsiClass parentClass) {
|
||||
super(reference, refClass, true);
|
||||
myParentClass = parentClass;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiClass getReferencedElement() {
|
||||
return (PsiClass)super.getReferencedElement();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteElement() throws IncorrectOperationException {
|
||||
final PsiClass refClass = getReferencedElement();
|
||||
ClassUtils.removeFromPermitsList(myParentClass, refClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSafeDelete() {
|
||||
if (getElement() != null) return true;
|
||||
PsiReferenceList permitsList = myParentClass.getPermitsList();
|
||||
if (permitsList == null) return false;
|
||||
PsiJavaCodeReferenceElement[] childRefs = permitsList.getReferenceElements();
|
||||
if (childRefs.length < 1) return false;
|
||||
return ContainerUtil.exists(childRefs, ref -> ref.resolve() == getReferencedElement());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
if (!super.equals(o)) return false;
|
||||
SafeDeletePermitsClassUsageInfo info = (SafeDeletePermitsClassUsageInfo)o;
|
||||
return Objects.equals(myParentClass, info.myParentClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(super.hashCode(), myParentClass);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
sealed interface GrandParent1 permits Parent, A {}
|
||||
|
||||
sealed class GrandParent2 permits Parent {}
|
||||
|
||||
sealed class <caret>Parent extends GrandParent2 implements GrandParent1 permits A, B {}
|
||||
|
||||
non-sealed class A extends Parent implements GrandParent1 {}
|
||||
|
||||
final class B extends Parent {}
|
||||
@@ -0,0 +1,7 @@
|
||||
sealed interface GrandParent1 permits A, B {}
|
||||
|
||||
sealed class GrandParent2 permits A, B {}
|
||||
|
||||
non-sealed class A extends GrandParent2 implements GrandParent1 {}
|
||||
|
||||
final class B extends GrandParent2 implements GrandParent1 {}
|
||||
@@ -276,7 +276,7 @@ public class SafeDeleteTest extends MultiFileTestCase {
|
||||
LanguageLevelProjectExtension.getInstance(getProject()).setLanguageLevel(LanguageLevel.JDK_1_7);
|
||||
doSingleFileTest();
|
||||
}
|
||||
|
||||
|
||||
public void testLastResourceVariableConflictingVar() throws Exception {
|
||||
LanguageLevelProjectExtension.getInstance(getProject()).setLanguageLevel(LanguageLevel.JDK_1_7);
|
||||
doSingleFileTest();
|
||||
@@ -388,6 +388,11 @@ public class SafeDeleteTest extends MultiFileTestCase {
|
||||
doSingleFileTest();
|
||||
}
|
||||
|
||||
public void testSealedParent() throws Exception {
|
||||
LanguageLevelProjectExtension.getInstance(getProject()).setLanguageLevel(LanguageLevel.JDK_15_PREVIEW);
|
||||
doSingleFileTest();
|
||||
}
|
||||
|
||||
private void doTest(@NonNls final String qClassName) {
|
||||
doTest((rootDir, rootAfter) -> this.performAction(qClassName));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user