mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
InlineSuperClass: do not inline class with sealed parent as anonymous, fix permits list in case when sealed parent and child are both sealed (IDEA-243902)
GitOrigin-RevId: 52ac1c93c8d9091b18172ec27a95c0eccc672915
This commit is contained in:
committed by
intellij-monorepo-bot
parent
ae1f9c7d4a
commit
3ea4e3a5b5
+9
-1
@@ -39,6 +39,7 @@ import com.intellij.refactoring.util.InlineUtil;
|
||||
import com.intellij.refactoring.util.RefactoringUtil;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.Processor;
|
||||
import com.siyeh.ig.psiutils.ClassUtils;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -73,7 +74,9 @@ public class InlineToAnonymousClassHandler extends JavaInlineActionHandler {
|
||||
}
|
||||
if (!(element instanceof PsiClass)) return false;
|
||||
if (element instanceof PsiAnonymousClass) return false;
|
||||
return findClassInheritors((PsiClass)element);
|
||||
PsiClass psiClass = (PsiClass)element;
|
||||
if (!findClassInheritors(psiClass)) return false;
|
||||
return !isParentSealed(psiClass);
|
||||
}
|
||||
|
||||
private static boolean findClassInheritors(final PsiClass element) {
|
||||
@@ -92,6 +95,11 @@ public class InlineToAnonymousClassHandler extends JavaInlineActionHandler {
|
||||
return inheritors.isEmpty();
|
||||
}
|
||||
|
||||
private static boolean isParentSealed(@NotNull PsiClass psiClass) {
|
||||
if (PsiTreeUtil.findChildOfType(psiClass, PsiMember.class) == null) return false;
|
||||
return ClassUtils.hasSealedParent(psiClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canInlineElementInEditor(PsiElement element, Editor editor) {
|
||||
if (canInlineElement(element)) {
|
||||
|
||||
+10
@@ -20,11 +20,14 @@ import com.intellij.usageView.UsageInfo;
|
||||
import com.intellij.usageView.UsageViewDescriptor;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.containers.MultiMap;
|
||||
import com.siyeh.ig.psiutils.ClassUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static com.intellij.util.ObjectUtils.tryCast;
|
||||
|
||||
/**
|
||||
* @author yole
|
||||
*/
|
||||
@@ -216,6 +219,13 @@ public class InlineToAnonymousClassProcessor extends BaseRefactoringProcessor {
|
||||
else if (element != null && element.getParent() instanceof PsiNewExpression) {
|
||||
newExpressions.add((PsiNewExpression) element.getParent());
|
||||
}
|
||||
else if (element instanceof PsiJavaCodeReferenceElement && element.getParent() instanceof PsiReferenceList) {
|
||||
PsiReferenceList refList = (PsiReferenceList) element.getParent();
|
||||
PsiClass parentClass = tryCast(refList.getParent(), PsiClass.class);
|
||||
if (parentClass != null && refList == parentClass.getPermitsList()) {
|
||||
ClassUtils.removeFromPermitsList(parentClass, myClass);
|
||||
}
|
||||
}
|
||||
else {
|
||||
PsiImportStatement statement = PsiTreeUtil.getParentOfType(element, PsiImportStatement.class);
|
||||
if (statement != null && !myInlineThisOnly) {
|
||||
|
||||
+5
-1
@@ -119,9 +119,13 @@ public class InlineSuperClassRefactoringProcessor extends FixableUsagesRefactori
|
||||
if (parent instanceof PsiReferenceList) {
|
||||
final PsiElement pparent = parent.getParent();
|
||||
if (pparent instanceof PsiClass) {
|
||||
final PsiJavaCodeReferenceElement classRef = (PsiJavaCodeReferenceElement)element;
|
||||
final PsiClass inheritor = (PsiClass)pparent;
|
||||
if (parent.equals(inheritor.getExtendsList()) || parent.equals(inheritor.getImplementsList())) {
|
||||
usages.add(new ReplaceExtendsListUsageInfo((PsiJavaCodeReferenceElement)element, mySuperClass, inheritor));
|
||||
usages.add(new ReplaceExtendsListUsageInfo(classRef, mySuperClass, inheritor));
|
||||
}
|
||||
else if (parent.equals(inheritor.getPermitsList())) {
|
||||
usages.add(new RemovePermitsListUsageInfo(classRef, mySuperClass, inheritor));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
// 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.inlineSuperClass.usageInfo;
|
||||
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiJavaCodeReferenceElement;
|
||||
import com.intellij.refactoring.safeDelete.usageInfo.SafeDeletePermitsClassUsageInfo;
|
||||
import com.intellij.refactoring.util.FixableUsageInfo;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
|
||||
public class RemovePermitsListUsageInfo extends FixableUsageInfo {
|
||||
private final SafeDeletePermitsClassUsageInfo mySafeDeletePermitsClassUsageInfo;
|
||||
|
||||
public RemovePermitsListUsageInfo(PsiJavaCodeReferenceElement reference, PsiClass refClass, PsiClass parentClass) {
|
||||
super(reference);
|
||||
mySafeDeletePermitsClassUsageInfo = new SafeDeletePermitsClassUsageInfo(reference, refClass, parentClass, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fixUsage() throws IncorrectOperationException {
|
||||
if (mySafeDeletePermitsClassUsageInfo.isSafeDelete()) {
|
||||
mySafeDeletePermitsClassUsageInfo.deleteElement();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -575,7 +575,7 @@ public class JavaSafeDeleteProcessor extends SafeDeleteProcessorDelegateBase {
|
||||
PsiJavaCodeReferenceElement classRef = (PsiJavaCodeReferenceElement) element;
|
||||
final PsiClass inheritor = (PsiClass) pparent;
|
||||
if (parent.equals(inheritor.getPermitsList())) {
|
||||
usages.add(new SafeDeletePermitsClassUsageInfo(classRef, psiClass, inheritor));
|
||||
usages.add(new SafeDeletePermitsClassUsageInfo(classRef, psiClass, inheritor, true));
|
||||
return true;
|
||||
}
|
||||
//If psiClass contains only private members, then it is safe to remove it and change inheritor's extends/implements accordingly
|
||||
|
||||
+19
-7
@@ -2,21 +2,24 @@
|
||||
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 org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class SafeDeletePermitsClassUsageInfo extends SafeDeleteReferenceUsageInfo {
|
||||
private final PsiClass myParentClass;
|
||||
private final boolean myChangeParentModifier;
|
||||
|
||||
public SafeDeletePermitsClassUsageInfo(final PsiJavaCodeReferenceElement reference, PsiClass refClass, PsiClass parentClass) {
|
||||
public SafeDeletePermitsClassUsageInfo(PsiJavaCodeReferenceElement reference, PsiClass refClass,
|
||||
PsiClass parentClass, boolean changeParentModifier) {
|
||||
super(reference, refClass, true);
|
||||
myParentClass = parentClass;
|
||||
myChangeParentModifier = changeParentModifier;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -27,17 +30,26 @@ public class SafeDeletePermitsClassUsageInfo extends SafeDeleteReferenceUsageInf
|
||||
@Override
|
||||
public void deleteElement() throws IncorrectOperationException {
|
||||
final PsiClass refClass = getReferencedElement();
|
||||
ClassUtils.removeFromPermitsList(myParentClass, refClass);
|
||||
if (myChangeParentModifier) {
|
||||
ClassUtils.removeFromPermitsList(myParentClass, refClass);
|
||||
}
|
||||
else {
|
||||
PsiJavaCodeReferenceElement exChildRef = findReference();
|
||||
if (exChildRef != null) exChildRef.delete();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSafeDelete() {
|
||||
if (getElement() != null) return true;
|
||||
return getElement() != null && findReference() != null;
|
||||
}
|
||||
|
||||
private @Nullable PsiJavaCodeReferenceElement findReference() {
|
||||
PsiReferenceList permitsList = myParentClass.getPermitsList();
|
||||
if (permitsList == null) return false;
|
||||
if (permitsList == null) return null;
|
||||
PsiJavaCodeReferenceElement[] childRefs = permitsList.getReferenceElements();
|
||||
if (childRefs.length < 1) return false;
|
||||
return ContainerUtil.exists(childRefs, ref -> ref.resolve() == getReferencedElement());
|
||||
if (childRefs.length < 1) return null;
|
||||
return ContainerUtil.find(childRefs, ref -> ref.resolve() == getReferencedElement());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
sealed class Parent permits Parent.A {
|
||||
|
||||
void test() {
|
||||
Object obj = new A<caret>();
|
||||
}
|
||||
|
||||
static final class A extends Parent {}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
final class Parent {
|
||||
|
||||
void test() {
|
||||
Object obj = new Parent();
|
||||
}
|
||||
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
sealed class Parent {
|
||||
|
||||
void test() {
|
||||
Object obj = new A<caret>();
|
||||
}
|
||||
|
||||
static final class A extends Parent {
|
||||
void foo() {}
|
||||
}
|
||||
|
||||
}
|
||||
+10
@@ -271,6 +271,16 @@ public class InlineToAnonymousClassTest extends LightRefactoringTestCase {
|
||||
doTest(true, false);
|
||||
}
|
||||
|
||||
public void testSealed() {
|
||||
setLanguageLevel(LanguageLevel.JDK_15_PREVIEW);
|
||||
doTest(false, false);
|
||||
}
|
||||
|
||||
public void testSealedParentChildWithMembers() {
|
||||
setLanguageLevel(LanguageLevel.JDK_15_PREVIEW);
|
||||
doTestCanBeInvokedOnReference(false);
|
||||
}
|
||||
|
||||
public void testNoInlineAbstract() {
|
||||
doTestNoInline("Abstract classes cannot be inlined");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user