[java-highlighting] IDEA-339935 JEP 463

- rename unnamed classes to implicitly declared classes

GitOrigin-RevId: 2c6d7f16a1dc6d2371b8f8b5f5675246c9bc99f9
This commit is contained in:
Mikhail Pyltsin
2023-12-06 18:22:42 +01:00
committed by intellij-monorepo-bot
parent 9e479dc1a2
commit 3f86cf9292
108 changed files with 333 additions and 335 deletions

View File

@@ -1350,19 +1350,19 @@ public final class HighlightClassUtil {
return null;
}
static HighlightInfo.Builder checkUnnamedClassMember(@NotNull PsiMember member, @NotNull LanguageLevel languageLevel,
@NotNull PsiFile psiFile) {
if (!(member.getContainingClass() instanceof PsiUnnamedClass unnamedClass)) {
static HighlightInfo.Builder checkImplicitClassMember(@NotNull PsiMember member, @NotNull LanguageLevel languageLevel,
@NotNull PsiFile psiFile) {
if (!(member.getContainingClass() instanceof PsiImplicitClass implicitClass)) {
return null;
}
HighlightInfo.Builder builder = HighlightUtil.checkFeature(member, HighlightingFeature.UNNAMED_CLASSES, languageLevel, psiFile);
HighlightInfo.Builder builder = HighlightUtil.checkFeature(member, HighlightingFeature.IMPLICIT_CLASSES, languageLevel, psiFile);
if (builder == null) return null;
if (!(member instanceof PsiClass) && !HighlightingFeature.UNNAMED_CLASSES.isAvailable(member)) {
boolean hasClassToRelocate = PsiTreeUtil.findChildOfType(unnamedClass, PsiClass.class) != null;
if (!(member instanceof PsiClass) && !HighlightingFeature.IMPLICIT_CLASSES.isAvailable(member)) {
boolean hasClassToRelocate = PsiTreeUtil.findChildOfType(implicitClass, PsiClass.class) != null;
if (hasClassToRelocate) {
MoveMembersIntoClassFix fix = new MoveMembersIntoClassFix(unnamedClass);
MoveMembersIntoClassFix fix = new MoveMembersIntoClassFix(implicitClass);
builder.registerFix(fix, null, null, null, null);
}
}

View File

@@ -7,60 +7,60 @@ import com.intellij.codeInsight.daemon.impl.HighlightInfoType;
import com.intellij.codeInsight.intention.QuickFixFactory;
import com.intellij.psi.*;
import com.intellij.psi.util.ClassUtil;
import com.intellij.psi.util.JavaUnnamedClassUtil;
import com.intellij.psi.util.JavaImplicitClassUtil;
import com.intellij.psi.util.PsiMethodUtil;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Checks and reports errors for unnamed classes {@link PsiUnnamedClass}.
* Checks and reports errors for implicitly declared classes {@link PsiImplicitClass}.
*/
public final class HighlightUnnamedClassUtil {
public final class HighlightImplicitClassUtil {
static HighlightInfo.@Nullable Builder checkUnnamedClassHasMainMethod(@NotNull PsiJavaFile file) {
if (!HighlightingFeature.UNNAMED_CLASSES.isAvailable(file)) return null;
PsiUnnamedClass unnamedClass = JavaUnnamedClassUtil.getUnnamedClassFor(file);
if (unnamedClass == null) return null;
PsiMethod[] methods = unnamedClass.getMethods();
static HighlightInfo.@Nullable Builder checkImplicitClassHasMainMethod(@NotNull PsiJavaFile file) {
if (!HighlightingFeature.IMPLICIT_CLASSES.isAvailable(file)) return null;
PsiImplicitClass implicitClass = JavaImplicitClassUtil.getImplicitClassFor(file);
if (implicitClass == null) return null;
PsiMethod[] methods = implicitClass.getMethods();
boolean hasMainMethod = ContainerUtil.exists(methods, method -> "main".equals(method.getName()) && PsiMethodUtil.isMainMethod(method));
if (!hasMainMethod) {
return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR)
.range(file)
.fileLevelAnnotation()
.registerFix(QuickFixFactory.getInstance().createAddMainMethodFix(unnamedClass), null, null, null, null)
.description(JavaErrorBundle.message("error.unnamed.class.contains.no.main.method"));
.registerFix(QuickFixFactory.getInstance().createAddMainMethodFix(implicitClass), null, null, null, null)
.description(JavaErrorBundle.message("error.implicit.class.contains.no.main.method"));
}
return null;
}
static HighlightInfo.@Nullable Builder checkUnnamedClassFileIsValidIdentifier(@NotNull PsiJavaFile file) {
if (!HighlightingFeature.UNNAMED_CLASSES.isAvailable(file)) return null;
PsiUnnamedClass unnamedClass = JavaUnnamedClassUtil.getUnnamedClassFor(file);
if (unnamedClass == null) return null;
String name = ClassUtil.getJVMClassName(unnamedClass);
static HighlightInfo.@Nullable Builder checkImplicitClassFileIsValidIdentifier(@NotNull PsiJavaFile file) {
if (!HighlightingFeature.IMPLICIT_CLASSES.isAvailable(file)) return null;
PsiImplicitClass implicitClass = JavaImplicitClassUtil.getImplicitClassFor(file);
if (implicitClass == null) return null;
String name = ClassUtil.getJVMClassName(implicitClass);
if (!PsiNameHelper.getInstance(file.getProject()).isQualifiedName(name)) {
return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR)
.range(file)
.fileLevelAnnotation()
.description(JavaErrorBundle.message("error.unnamed.class.has.invalid.file.name"));
.description(JavaErrorBundle.message("error.implicit.class.has.invalid.file.name"));
}
return null;
}
static HighlightInfo.@Nullable Builder checkInitializersInUnnamedClass(@NotNull PsiClassInitializer initializer) {
if (initializer.getContainingClass() instanceof PsiUnnamedClass && HighlightingFeature.UNNAMED_CLASSES.isAvailable(initializer)) {
static HighlightInfo.@Nullable Builder checkInitializersInImplicitClass(@NotNull PsiClassInitializer initializer) {
if (initializer.getContainingClass() instanceof PsiImplicitClass && HighlightingFeature.IMPLICIT_CLASSES.isAvailable(initializer)) {
return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(initializer).descriptionAndTooltip(
JavaErrorBundle.message("error.initializers.are.not.allowed.in.unnamed.classes"));
JavaErrorBundle.message("error.initializers.are.not.allowed.in.implicit.classes"));
}
return null;
}
static HighlightInfo.@Nullable Builder checkPackageNotAllowedInUnnamedClass(@NotNull PsiPackageStatement statement,
@NotNull PsiFile file) {
if (HighlightingFeature.UNNAMED_CLASSES.isAvailable(file) && JavaUnnamedClassUtil.isFileWithUnnamedClass(file)) {
static HighlightInfo.@Nullable Builder checkPackageNotAllowedInImplicitClass(@NotNull PsiPackageStatement statement,
@NotNull PsiFile file) {
if (HighlightingFeature.IMPLICIT_CLASSES.isAvailable(file) && JavaImplicitClassUtil.isFileWithImplicitClass(file)) {
return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(statement).descriptionAndTooltip(
JavaErrorBundle.message("error.package.statement.not.allowed.for.unnamed.class"));
JavaErrorBundle.message("error.package.statement.not.allowed.for.implicit.class"));
}
return null;
}

View File

@@ -373,8 +373,8 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
@Override
public void visitJavaFile(@NotNull PsiJavaFile file) {
super.visitJavaFile(file);
if (!hasErrorResults()) add(HighlightUnnamedClassUtil.checkUnnamedClassHasMainMethod(file));
if (!hasErrorResults()) add(HighlightUnnamedClassUtil.checkUnnamedClassFileIsValidIdentifier(file));
if (!hasErrorResults()) add(HighlightImplicitClassUtil.checkImplicitClassHasMainMethod(file));
if (!hasErrorResults()) add(HighlightImplicitClassUtil.checkImplicitClassFileIsValidIdentifier(file));
}
@Override
@@ -553,14 +553,14 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
@Override
public void visitClassInitializer(@NotNull PsiClassInitializer initializer) {
super.visitClassInitializer(initializer);
if (!hasErrorResults()) add(HighlightClassUtil.checkUnnamedClassMember(initializer, myLanguageLevel, myFile));
if (!hasErrorResults()) add(HighlightClassUtil.checkImplicitClassMember(initializer, myLanguageLevel, myFile));
if (!hasErrorResults()) add(HighlightClassUtil.checkIllegalInstanceMemberInRecord(initializer));
if (!hasErrorResults()) add(HighlightControlFlowUtil.checkInitializerCompleteNormally(initializer));
if (!hasErrorResults()) add(HighlightControlFlowUtil.checkUnreachableStatement(initializer.getBody()));
if (!hasErrorResults()) {
add(HighlightClassUtil.checkThingNotAllowedInInterface(initializer, initializer.getContainingClass()));
}
if (!hasErrorResults()) add(HighlightUnnamedClassUtil.checkInitializersInUnnamedClass(initializer));
if (!hasErrorResults()) add(HighlightImplicitClassUtil.checkInitializersInImplicitClass(initializer));
}
@Override
@@ -724,7 +724,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
@Override
public void visitField(@NotNull PsiField field) {
super.visitField(field);
if (!hasErrorResults()) add(HighlightClassUtil.checkUnnamedClassMember(field, myLanguageLevel, myFile));
if (!hasErrorResults()) add(HighlightClassUtil.checkImplicitClassMember(field, myLanguageLevel, myFile));
if (!hasErrorResults()) add(HighlightClassUtil.checkIllegalInstanceMemberInRecord(field));
if (!hasErrorResults()) add(HighlightControlFlowUtil.checkFinalFieldInitialized(field));
}
@@ -989,7 +989,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
@Override
public void visitMethod(@NotNull PsiMethod method) {
super.visitMethod(method);
if (!hasErrorResults()) add(HighlightClassUtil.checkUnnamedClassMember(method, myLanguageLevel, myFile));
if (!hasErrorResults()) add(HighlightClassUtil.checkImplicitClassMember(method, myLanguageLevel, myFile));
if (!hasErrorResults()) add(HighlightControlFlowUtil.checkUnreachableStatement(method.getBody()));
if (!hasErrorResults()) add(HighlightMethodUtil.checkConstructorHandleSuperClassExceptions(method));
if (!hasErrorResults()) add(HighlightMethodUtil.checkRecursiveConstructorInvocation(method));
@@ -1147,7 +1147,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
if (myLanguageLevel.isAtLeast(LanguageLevel.JDK_1_9)) {
if (!hasErrorResults()) add(ModuleHighlightUtil.checkPackageStatement(statement, myFile, myJavaModule));
}
if (!hasErrorResults()) add(HighlightUnnamedClassUtil.checkPackageNotAllowedInUnnamedClass(statement, myFile));
if (!hasErrorResults()) add(HighlightImplicitClassUtil.checkPackageNotAllowedInImplicitClass(statement, myFile));
}
@Override

View File

@@ -95,7 +95,7 @@ public enum HighlightingFeature {
return super.isSufficient(useSiteLevel) || LanguageLevel.JDK_21_PREVIEW == useSiteLevel;
}
},
UNNAMED_CLASSES(LanguageLevel.JDK_21_PREVIEW, "feature.unnamed.classes");
IMPLICIT_CLASSES(LanguageLevel.JDK_21_PREVIEW, "feature.implicit.classes");
public static final @NonNls String JDK_INTERNAL_PREVIEW_FEATURE = "jdk.internal.PreviewFeature";
public static final @NonNls String JDK_INTERNAL_JAVAC_PREVIEW_FEATURE = "jdk.internal.javac.PreviewFeature";

View File

@@ -13,10 +13,10 @@ import java.util.Arrays;
import java.util.List;
public class MoveMembersIntoClassFix implements ModCommandAction {
private final SmartPsiElementPointer<PsiUnnamedClass> myUnnamedClass;
private final SmartPsiElementPointer<PsiImplicitClass> myImplicitClass;
public MoveMembersIntoClassFix(PsiUnnamedClass unnamedClass) {
myUnnamedClass = SmartPointerManager.createPointer(unnamedClass);
public MoveMembersIntoClassFix(PsiImplicitClass implicitClass) {
myImplicitClass = SmartPointerManager.createPointer(implicitClass);
}
@Override
@@ -31,9 +31,9 @@ public class MoveMembersIntoClassFix implements ModCommandAction {
@Override
public @NotNull ModCommand perform(@NotNull ActionContext context) {
PsiUnnamedClass unnamedClass = myUnnamedClass.getElement();
if (unnamedClass == null) return ModCommand.nop();
PsiClass[] innerClasses = unnamedClass.getInnerClasses();
PsiImplicitClass implicitClass = myImplicitClass.getElement();
if (implicitClass == null) return ModCommand.nop();
PsiClass[] innerClasses = implicitClass.getInnerClasses();
List<? extends ModCommandAction> actionsPerClass = Arrays.stream(innerClasses).map(MoveAllMembersToParticularClassAction::new).toList();
@@ -50,7 +50,7 @@ public class MoveMembersIntoClassFix implements ModCommandAction {
@Override
protected void invoke(@NotNull ActionContext context, @NotNull PsiClass element, @NotNull ModPsiUpdater updater) {
if (!(element.getContainingClass() instanceof PsiUnnamedClass unn)) return;
if (!(element.getContainingClass() instanceof PsiImplicitClass unn)) return;
PsiMember[] members = PsiTreeUtil.getChildrenOfType(unn, PsiMember.class);
if (members == null) return;
List<PsiMember> membersWithoutClasses = Arrays.stream(members).filter(member -> !(member instanceof PsiClass)).toList();

View File

@@ -325,7 +325,7 @@ public abstract class CodeBlockSurrounder {
return null;
}
if (parent instanceof PsiField) {
if (parent.getParent() instanceof PsiUnnamedClass) {
if (parent.getParent() instanceof PsiImplicitClass) {
return null;
}
return new ExtractFieldInitializerSurrounder(expression, (PsiField)parent);