mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[intention-preview] ExtendSealedClassFix and improvements to ImplementOrExtendFix
GitOrigin-RevId: 6e68f66952d5a995a260f4c235fb48cd1217cdf3
This commit is contained in:
committed by
intellij-monorepo-bot
parent
9dd69ca785
commit
5c444185a3
@@ -427,12 +427,11 @@ remove.unreachable.branches=Remove unreachable branches
|
||||
simplify.boolean.expression.extracting.side.effects=\ extracting side effects
|
||||
intention.move.parenthesis.name=Fix closing parenthesis placement
|
||||
|
||||
extend.sealed.title=Extend sealed class and mark as
|
||||
implement.sealed.title=Implement sealed interface and mark as
|
||||
extend.sealed.title=Make ''{0}'' {1, choice, 1#extend|2#implement} ''{2}'' and
|
||||
|
||||
implement.or.extend.fix.family=Implement/Extend required base class
|
||||
implement.or.extend.fix.implement.text=Implement ''{0}''
|
||||
implement.or.extend.fix.extend.text=Extend ''{0}''
|
||||
implement.or.extend.fix.implement.text=Make ''{0}'' implement ''{1}''
|
||||
implement.or.extend.fix.extend.text=Make ''{0}'' extend ''{1}''
|
||||
|
||||
seal.class.from.permits.list.fix=Seal inheritor
|
||||
|
||||
|
||||
+52
-44
@@ -1,7 +1,8 @@
|
||||
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.codeInsight.daemon.impl.quickfix;
|
||||
|
||||
import com.intellij.codeInsight.daemon.QuickFixBundle;
|
||||
import com.intellij.codeInsight.intention.FileModifier;
|
||||
import com.intellij.codeInsight.intention.choice.ChoiceTitleIntentionAction;
|
||||
import com.intellij.codeInsight.intention.choice.ChoiceVariantIntentionAction;
|
||||
import com.intellij.codeInsight.intention.choice.DefaultIntentionActionWithChoice;
|
||||
@@ -16,7 +17,6 @@ import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.searches.DirectClassInheritorsSearch;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.Query;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -25,61 +25,51 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import static com.intellij.util.ObjectUtils.tryCast;
|
||||
|
||||
public class ExtendSealedClassFix implements DefaultIntentionActionWithChoice {
|
||||
@FileModifier.SafeFieldForPreview private final SmartPsiElementPointer<PsiClass> myParentClassPointer;
|
||||
@FileModifier.SafeFieldForPreview private final SmartPsiElementPointer<PsiClass> mySubclassPointer;
|
||||
private final @Nls String myName;
|
||||
|
||||
private static final String[] SUBCLASS_MODIFIERS = {PsiModifier.FINAL, PsiModifier.NON_SEALED, PsiModifier.SEALED};
|
||||
|
||||
private final boolean myParentIsInterface;
|
||||
private final boolean myChildIsInterface;
|
||||
private final SmartPsiElementPointer<PsiJavaCodeReferenceElement> mySubclassReferencePointer;
|
||||
|
||||
private ExtendSealedClassFix(PsiJavaCodeReferenceElement reference, boolean parentIsInterface, boolean childIsInterface) {
|
||||
mySubclassReferencePointer = SmartPointerManager.createPointer(reference);
|
||||
myParentIsInterface = parentIsInterface;
|
||||
myChildIsInterface = childIsInterface;
|
||||
private ExtendSealedClassFix(PsiClass parentClass, PsiClass subclass) {
|
||||
myParentClassPointer = SmartPointerManager.createPointer(parentClass);
|
||||
mySubclassPointer = SmartPointerManager.createPointer(subclass);
|
||||
int extendsImplements = subclass.isInterface() || !parentClass.isInterface() ? 1 : 2;
|
||||
myName = QuickFixBundle.message("extend.sealed.title", subclass.getName(), extendsImplements, parentClass.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ChoiceTitleIntentionAction getTitle() {
|
||||
String fixName = getName();
|
||||
return new ChoiceTitleIntentionAction(fixName, fixName);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Nls
|
||||
private String getName() {
|
||||
return QuickFixBundle.message(myParentIsInterface ? "implement.sealed.title" : "extend.sealed.title");
|
||||
return new ChoiceTitleIntentionAction(QuickFixBundle.message("implement.or.extend.fix.family"), myName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull List<ChoiceVariantIntentionAction> getVariants() {
|
||||
if (!myParentIsInterface && myChildIsInterface) return Collections.emptyList();
|
||||
if (myChildIsInterface) {
|
||||
return Arrays.asList(new ExtendSealedClassVariantAction(0, PsiModifier.SEALED),
|
||||
new ExtendSealedClassVariantAction(1, PsiModifier.NON_SEALED));
|
||||
PsiClass subclass = mySubclassPointer.getElement();
|
||||
PsiClass parentClass = myParentClassPointer.getElement();
|
||||
if (subclass == null || parentClass == null) return Collections.emptyList();
|
||||
boolean parentIsInterface = parentClass.isInterface();
|
||||
boolean subclassIsInterface = subclass.isInterface();
|
||||
if (!parentIsInterface && subclassIsInterface) return Collections.emptyList();
|
||||
if (subclassIsInterface) {
|
||||
return Arrays.asList(new ExtendSealedClassVariantAction(0, PsiModifier.SEALED, myParentClassPointer, mySubclassPointer),
|
||||
new ExtendSealedClassVariantAction(1, PsiModifier.NON_SEALED, myParentClassPointer, mySubclassPointer));
|
||||
}
|
||||
return IntStream.range(0, SUBCLASS_MODIFIERS.length)
|
||||
.mapToObj(i -> new ExtendSealedClassVariantAction(i, SUBCLASS_MODIFIERS[i]))
|
||||
.collect(Collectors.toList());
|
||||
return Arrays.asList(new ExtendSealedClassVariantAction(0, PsiModifier.FINAL, myParentClassPointer, mySubclassPointer),
|
||||
new ExtendSealedClassVariantAction(1, PsiModifier.SEALED, myParentClassPointer, mySubclassPointer),
|
||||
new ExtendSealedClassVariantAction(2, PsiModifier.NON_SEALED, myParentClassPointer, mySubclassPointer));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return fixes or null if given case is not supported (but probably valid)
|
||||
*/
|
||||
static LocalQuickFix @Nullable [] createFixes(@NotNull PsiJavaCodeReferenceElement subclassReference,
|
||||
@NotNull PsiClass parentClass,
|
||||
@NotNull PsiClass subclass) {
|
||||
static LocalQuickFix @Nullable [] createFixes(@NotNull PsiClass parentClass, @NotNull PsiClass subclass) {
|
||||
if (!parentClass.hasModifierProperty(PsiModifier.SEALED) || !parentClass.getManager().isInProject(parentClass)) return null;
|
||||
boolean parentIsInterface = parentClass.isInterface();
|
||||
if (parentIsInterface && (subclass.isRecord() || subclass.isEnum())) return null;
|
||||
PsiModifierList modifiers = subclass.getModifierList();
|
||||
if (modifiers == null || hasSealedClassSubclassModifier(modifiers)) return null;
|
||||
ExtendSealedClassFix extendSealedClassFix = new ExtendSealedClassFix(subclassReference, parentIsInterface, subclass.isInterface());
|
||||
ExtendSealedClassFix extendSealedClassFix = new ExtendSealedClassFix(parentClass, subclass);
|
||||
List<LocalQuickFix> actions = new ArrayList<>();
|
||||
actions.add(extendSealedClassFix.getTitle());
|
||||
actions.addAll(extendSealedClassFix.getVariants());
|
||||
@@ -93,17 +83,25 @@ public class ExtendSealedClassFix implements DefaultIntentionActionWithChoice {
|
||||
}
|
||||
|
||||
private static boolean hasSealedClassSubclassModifier(@NotNull PsiModifierList modifiers) {
|
||||
return ContainerUtil.exists(SUBCLASS_MODIFIERS, m -> modifiers.hasExplicitModifier(m));
|
||||
return modifiers.hasExplicitModifier(PsiModifier.FINAL) ||
|
||||
modifiers.hasExplicitModifier(PsiModifier.SEALED) ||
|
||||
modifiers.hasExplicitModifier(PsiModifier.NON_SEALED);
|
||||
}
|
||||
|
||||
private class ExtendSealedClassVariantAction extends ChoiceVariantIntentionAction {
|
||||
private static class ExtendSealedClassVariantAction extends ChoiceVariantIntentionAction {
|
||||
|
||||
private final int myIndex;
|
||||
private final @NlsSafe String myModifier;
|
||||
private final SmartPsiElementPointer<PsiClass> myParentClassPointer;
|
||||
private final SmartPsiElementPointer<PsiClass> mySubclassPointer;
|
||||
|
||||
private ExtendSealedClassVariantAction(int index, @NotNull String modifier) {
|
||||
private ExtendSealedClassVariantAction(int index, @NotNull String modifier,
|
||||
SmartPsiElementPointer<PsiClass> parentClassPointer,
|
||||
SmartPsiElementPointer<PsiClass> subclassPointer) {
|
||||
myIndex = index;
|
||||
myModifier = modifier;
|
||||
myParentClassPointer = parentClassPointer;
|
||||
mySubclassPointer = subclassPointer;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -118,7 +116,7 @@ public class ExtendSealedClassFix implements DefaultIntentionActionWithChoice {
|
||||
|
||||
@Override
|
||||
public @IntentionFamilyName @NotNull String getFamilyName() {
|
||||
return ExtendSealedClassFix.this.getName();
|
||||
return QuickFixBundle.message("implement.or.extend.fix.family");
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -126,14 +124,16 @@ public class ExtendSealedClassFix implements DefaultIntentionActionWithChoice {
|
||||
return getFamilyName() + " " + myModifier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable PsiElement getElementToMakeWritable(@NotNull PsiFile currentFile) {
|
||||
return mySubclassPointer.getContainingFile();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyFix(@NotNull Project project, PsiFile file, @Nullable Editor editor) {
|
||||
if (editor == null) return;
|
||||
PsiJavaCodeReferenceElement referenceElement = mySubclassReferencePointer.getElement();
|
||||
if (referenceElement == null) return;
|
||||
PsiClass parentClass = PsiTreeUtil.getParentOfType(referenceElement, PsiClass.class);
|
||||
PsiClass parentClass = myParentClassPointer.getElement();
|
||||
if (parentClass == null || !parentClass.hasModifierProperty(PsiModifier.SEALED)) return;
|
||||
PsiClass subclass = tryCast(referenceElement.resolve(), PsiClass.class);
|
||||
PsiClass subclass = mySubclassPointer.getElement();
|
||||
if (subclass == null) return;
|
||||
if (ImplementOrExtendFix.implementOrExtend(parentClass, subclass) == null) return;
|
||||
PsiModifierList modifiers = subclass.getModifierList();
|
||||
@@ -146,5 +146,13 @@ public class ExtendSealedClassFix implements DefaultIntentionActionWithChoice {
|
||||
subclass.navigate(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable FileModifier getFileModifierForPreview(@NotNull PsiFile target) {
|
||||
PsiClass subclass = mySubclassPointer.getElement();
|
||||
PsiClass copy = PsiTreeUtil.findSameElementInCopy(subclass, target);
|
||||
if (copy == null) return null;
|
||||
return new ExtendSealedClassVariantAction(myIndex, myModifier, myParentClassPointer, SmartPointerManager.createPointer(copy));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+27
-94
@@ -1,102 +1,38 @@
|
||||
// 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.
|
||||
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.codeInsight.daemon.impl.quickfix;
|
||||
|
||||
import com.intellij.CommonBundle;
|
||||
import com.intellij.codeInsight.FileModificationService;
|
||||
import com.intellij.codeInsight.daemon.QuickFixBundle;
|
||||
import com.intellij.codeInsight.intention.FileModifier;
|
||||
import com.intellij.codeInsight.intention.IntentionAction;
|
||||
import com.intellij.codeInsight.intention.preview.IntentionPreviewInfo;
|
||||
import com.intellij.codeInspection.LocalQuickFix;
|
||||
import com.intellij.codeInspection.LocalQuickFixAndIntentionActionOnPsiElement;
|
||||
import com.intellij.codeInspection.util.IntentionFamilyName;
|
||||
import com.intellij.codeInspection.util.IntentionName;
|
||||
import com.intellij.ide.highlighter.JavaFileType;
|
||||
import com.intellij.openapi.application.WriteAction;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.pom.Navigatable;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.refactoring.RefactoringBundle;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.siyeh.ig.psiutils.TypeUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import static com.intellij.util.ObjectUtils.tryCast;
|
||||
|
||||
public final class ImplementOrExtendFix extends LocalQuickFixAndIntentionActionOnPsiElement {
|
||||
|
||||
private final SmartPsiElementPointer<PsiClass> mySubclassPointer;
|
||||
private final SmartPsiElementPointer<PsiClass> myParentClassPointer;
|
||||
@SafeFieldForPreview private final SmartPsiElementPointer<PsiClass> mySubclassPointer;
|
||||
@SafeFieldForPreview private final SmartPsiElementPointer<PsiClass> myParentClassPointer;
|
||||
private final boolean myOnTheFly;
|
||||
private final @IntentionName String myName;
|
||||
|
||||
private ImplementOrExtendFix(@NotNull PsiElement place, @NotNull PsiClass subclass, @NotNull PsiClass parentClass, boolean onTheFly) {
|
||||
super(place);
|
||||
mySubclassPointer = SmartPointerManager.createPointer(subclass);
|
||||
myParentClassPointer = SmartPointerManager.createPointer(parentClass);
|
||||
myOnTheFly = onTheFly;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull IntentionPreviewInfo generatePreview(@NotNull Project project, @NotNull Editor editor, @NotNull PsiFile file) {
|
||||
PsiClass subclass = mySubclassPointer.getElement();
|
||||
PsiClass parent = myParentClassPointer.getElement();
|
||||
if (subclass == null || !subclass.isValid() || parent == null || !parent.isValid()) return IntentionPreviewInfo.EMPTY;
|
||||
PsiFile subclassFile = subclass.getContainingFile();
|
||||
|
||||
if (!subclassFile.isWritable() || subclass.getImplementsList() == null || subclass.getExtendsList() == null) {
|
||||
return IntentionPreviewInfo.EMPTY;
|
||||
}
|
||||
|
||||
String before = createClassDescription(subclass, null, null);
|
||||
String after = createClassDescription(subclass, parent.isInterface() ? null : parent, parent.isInterface() ? parent : null);
|
||||
if (before == null || after == null) {
|
||||
return IntentionPreviewInfo.EMPTY;
|
||||
}
|
||||
return new IntentionPreviewInfo.CustomDiff(JavaFileType.INSTANCE, subclassFile.getName(), before, after);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static String createClassDescription(@Nullable PsiClass psiClass,
|
||||
@Nullable PsiClass addToExtends,
|
||||
@Nullable PsiClass addToImplement) {
|
||||
if (psiClass == null) {
|
||||
return null;
|
||||
}
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
PsiElement brace = psiClass.getLBrace();
|
||||
for (PsiElement child : psiClass.getChildren()) {
|
||||
if (child == brace) {
|
||||
break;
|
||||
}
|
||||
if (child == psiClass.getImplementsList() && addToImplement!=null){
|
||||
String text = child.getText();
|
||||
PsiElementFactory elementFactory = JavaPsiFacade.getInstance(child.getProject()).getElementFactory();
|
||||
PsiClassType type = elementFactory.createType(addToImplement);
|
||||
text = StringUtil.isNotEmpty(text) ? text + ", " + type.getName() : "implements " + type.getName();
|
||||
if (!(child.getPrevSibling() instanceof PsiWhiteSpace)) {
|
||||
text = " " + text;
|
||||
}
|
||||
stringBuilder.append(text);
|
||||
continue;
|
||||
}
|
||||
if (child == psiClass.getExtendsList() && addToExtends!=null) {
|
||||
PsiElementFactory elementFactory = JavaPsiFacade.getInstance(child.getProject()).getElementFactory();
|
||||
PsiClassType type = elementFactory.createType(addToExtends);
|
||||
String text = "extends " + type.getName();
|
||||
if (!(child.getPrevSibling() instanceof PsiWhiteSpace)) {
|
||||
text = " " + text;
|
||||
}
|
||||
stringBuilder.append(text);
|
||||
continue;
|
||||
}
|
||||
stringBuilder.append(child.getText());
|
||||
}
|
||||
return stringBuilder.toString();
|
||||
myName = parentClass.isInterface() && !subclass.isInterface()
|
||||
? QuickFixBundle.message("implement.or.extend.fix.implement.text", subclass.getName(), parentClass.getName())
|
||||
: QuickFixBundle.message("implement.or.extend.fix.extend.text", subclass.getName(), parentClass.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -109,34 +45,32 @@ public final class ImplementOrExtendFix extends LocalQuickFixAndIntentionActionO
|
||||
// to plugin.xml or java class
|
||||
PsiClass subclass = mySubclassPointer.getElement();
|
||||
if (subclass == null || !subclass.isValid()) return;
|
||||
PsiFile subclassFile = subclass.getContainingFile();
|
||||
boolean external = file != subclassFile;
|
||||
if (external && !subclassFile.isWritable()) {
|
||||
String className = subclass.getQualifiedName();
|
||||
Messages.showErrorDialog(project, RefactoringBundle.message("0.is.read.only", className), CommonBundle.getErrorTitle());
|
||||
return;
|
||||
}
|
||||
PsiClass parentClass = myParentClassPointer.getElement();
|
||||
if (parentClass == null) return;
|
||||
if (!FileModificationService.getInstance().prepareFileForWrite(subclassFile)) return;
|
||||
boolean external = file != subclass.getContainingFile();
|
||||
|
||||
WriteAction.run(() -> {
|
||||
PsiElement e = implementOrExtend(parentClass, subclass);
|
||||
if (myOnTheFly && external && e instanceof Navigatable) ((Navigatable)e).navigate(true);
|
||||
});
|
||||
PsiElement e = implementOrExtend(parentClass, subclass);
|
||||
if (myOnTheFly && external && e instanceof Navigatable) ((Navigatable)e).navigate(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean startInWriteAction() {
|
||||
return false;
|
||||
public @Nullable PsiElement getElementToMakeWritable(@NotNull PsiFile currentFile) {
|
||||
return mySubclassPointer.getElement();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable FileModifier getFileModifierForPreview(@NotNull PsiFile target) {
|
||||
PsiClass subclass = mySubclassPointer.getElement();
|
||||
PsiClass copy = PsiTreeUtil.findSameElementInCopy(subclass, target);
|
||||
PsiElement place = myStartElement.getElement();
|
||||
PsiClass parentClass = myParentClassPointer.getElement();
|
||||
if (copy == null || place == null || parentClass == null) return null;
|
||||
return new ImplementOrExtendFix(place, copy, parentClass, myOnTheFly);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @IntentionName @NotNull String getText() {
|
||||
PsiClass parentClass = Objects.requireNonNull(myParentClassPointer.getElement());
|
||||
return parentClass.isInterface()
|
||||
? QuickFixBundle.message("implement.or.extend.fix.implement.text", parentClass.getQualifiedName())
|
||||
: QuickFixBundle.message("implement.or.extend.fix.extend.text", parentClass.getQualifiedName());
|
||||
return myName;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -165,10 +99,9 @@ public final class ImplementOrExtendFix extends LocalQuickFixAndIntentionActionO
|
||||
return LocalQuickFix.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
PsiJavaCodeReferenceElement subclassRef = tryCast(place, PsiJavaCodeReferenceElement.class);
|
||||
LocalQuickFix[] fixes = subclassRef == null ? null : ExtendSealedClassFix.createFixes(subclassRef, parentClass, subclass);
|
||||
LocalQuickFix[] fixes = ExtendSealedClassFix.createFixes(parentClass, subclass);
|
||||
if (fixes != null) return fixes;
|
||||
return new LocalQuickFix[]{new ImplementOrExtendFix(place, subclass, parentClass, onTheFly)};
|
||||
return new LocalQuickFix[]{ new ImplementOrExtendFix(place, subclass, parentClass, onTheFly) };
|
||||
}
|
||||
|
||||
static boolean hasNonObjectParent(@NotNull PsiClass psiClass) {
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// "Implement 'Parent'" "true"
|
||||
// "Make 'MyEnum' implement 'Parent'" "true-preview"
|
||||
sealed interface Parent permits MyEnum {}
|
||||
|
||||
enum MyEnum implements Parent {}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// "Extend 'Parent'" "true"
|
||||
// "Make 'Child' extend 'Parent'" "true-preview"
|
||||
sealed class Parent permits Child {}
|
||||
|
||||
final class Child extends Parent {}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// "Implement 'Parent'" "true"
|
||||
// "Make 'User' implement 'Parent'" "true-preview"
|
||||
sealed interface Parent permits User {}
|
||||
|
||||
record User(int age) implements Parent {}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// "final" "true"
|
||||
// "final" "true-preview"
|
||||
sealed class Parent permits Child {}
|
||||
|
||||
final class Child extends Parent {}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// "non-sealed" "true"
|
||||
// "non-sealed" "true-preview"
|
||||
sealed interface Parent permits Child, Foo {}
|
||||
|
||||
interface OtherParent {}
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// "final" "true"
|
||||
// "final" "true-preview"
|
||||
sealed class Parent permits Child {}
|
||||
|
||||
final class Child extends Parent {}
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
// "Make 'Child' extend 'Parent'" "true-preview"
|
||||
sealed interface Parent permits Child {}
|
||||
|
||||
non-sealed interface Child extends Parent {}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// "Implement 'Parent'" "true"
|
||||
// "Make 'MyEnum' implement 'Parent'" "true-preview"
|
||||
sealed interface Parent permits MyEnum<caret> {}
|
||||
|
||||
enum MyEnum {}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// "Extend 'Parent'" "true"
|
||||
// "Make 'Child' extend 'Parent'" "true-preview"
|
||||
sealed class Parent permits C<caret>hild {}
|
||||
|
||||
final class Child {}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// "Implement 'Parent'" "true"
|
||||
// "Make 'User' implement 'Parent'" "true-preview"
|
||||
sealed interface Parent permits User<caret> {}
|
||||
|
||||
record User(int age) {}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// "final" "true"
|
||||
// "final" "true-preview"
|
||||
sealed class Parent permits C<caret>hild {}
|
||||
|
||||
class Child {}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// "non-sealed" "true"
|
||||
// "non-sealed" "true-preview"
|
||||
sealed interface Parent permits Child<caret>, Foo {}
|
||||
|
||||
interface OtherParent {}
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// "final" "true"
|
||||
// "final" "true-preview"
|
||||
sealed class Parent permits C<caret>hild {}
|
||||
|
||||
class Child extends Object {}
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
// "Make 'Child' extend 'Parent'" "true-preview"
|
||||
sealed interface Parent permits C<caret>hild {}
|
||||
|
||||
non-sealed interface Child {}
|
||||
Reference in New Issue
Block a user