From 4bc45f31f023d5aae691f413541e77421fa0006e Mon Sep 17 00:00:00 2001 From: Tagir Valeev Date: Thu, 19 Dec 2019 12:39:28 +0700 Subject: [PATCH] Records extend the Record class (IDEA-228460) GitOrigin-RevId: f99f9cfbe07cec22bc34596366c97d62d024e4b2 --- .../impl/analysis/GenericsHighlightUtil.java | 10 -------- .../impl/analysis/HighlightClassUtil.java | 23 ++++++++++++++++++- .../daemon/impl/analysis/HighlightUtil.java | 2 +- .../impl/analysis/HighlightVisitorImpl.java | 1 + .../intellij/psi/impl/PsiClassImplUtil.java | 11 +++++++++ .../src/messages/JavaErrorMessages.properties | 2 +- .../advHighlightingRecords/RecordBasics.java | 8 +++++++ .../genericsHighlighting/Enum.java | 2 ++ .../daemon/LightRecordsHighlightingTest.java | 5 ++++ .../com/intellij/psi/CommonClassNames.java | 1 + 10 files changed, 52 insertions(+), 13 deletions(-) diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java index b2a30e0c972b..025775d7b42b 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java @@ -1206,16 +1206,6 @@ public class GenericsHighlightUtil { return null; } - static HighlightInfo checkCannotInheritFromEnum(@NotNull PsiClass superClass, @NotNull PsiElement elementToHighlight) { - HighlightInfo errorResult = null; - if (Comparing.strEqual("java.lang.Enum", superClass.getQualifiedName())) { - String message = JavaErrorMessages.message("classes.extends.enum"); - errorResult = - HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(elementToHighlight).descriptionAndTooltip(message).create(); - } - return errorResult; - } - static HighlightInfo checkGenericCannotExtendException(@NotNull PsiReferenceList list) { PsiElement parent = list.getParent(); if (parent instanceof PsiClass) { diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightClassUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightClassUtil.java index 3b1eec453821..53d53f1ebe02 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightClassUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightClassUtil.java @@ -105,7 +105,7 @@ public class HighlightClassUtil { if (aClass.isEnum()) { if (hasEnumConstantsWithInitializer(aClass)) return null; } - else if (aClass.hasModifierProperty(PsiModifier.ABSTRACT) || aClass.getRBrace() == null ) { + else if (aClass.hasModifierProperty(PsiModifier.ABSTRACT) || aClass.getRBrace() == null || aClass.isRecord()) { return null; } return checkClassWithAbstractMethods(aClass, textRange); @@ -910,4 +910,25 @@ public class HighlightClassUtil { } return null; } + + static HighlightInfo checkExtendsProhibitedClass(@NotNull PsiClass superClass, @NotNull PsiElement elementToHighlight) { + String qualifiedName = superClass.getQualifiedName(); + if (CommonClassNames.JAVA_LANG_ENUM.equals(qualifiedName) || CommonClassNames.JAVA_LANG_RECORD.equals(qualifiedName)) { + String message = JavaErrorMessages.message("classes.extends.prohibited.super", qualifiedName); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(elementToHighlight).descriptionAndTooltip(message).create(); + } + return null; + } + + public static HighlightInfo checkAnonymousInheritProhibited(PsiNewExpression expression) { + PsiAnonymousClass aClass = expression.getAnonymousClass(); + if (aClass != null) { + PsiClass superClass = aClass.getSuperClass(); + PsiJavaCodeReferenceElement reference = expression.getClassOrAnonymousClassReference(); + if (superClass != null && reference != null) { + return checkExtendsProhibitedClass(superClass, reference); + } + } + return null; + } } diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java index 462d053f0a1f..36eb5f0512ea 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java @@ -3033,7 +3033,7 @@ public class HighlightUtil extends HighlightUtilBase { highlightInfo = HighlightClassUtil.checkCannotInheritFromFinal(aClass, ref); } if (highlightInfo == null) { - highlightInfo = GenericsHighlightUtil.checkCannotInheritFromEnum(aClass, ref); + highlightInfo = HighlightClassUtil.checkExtendsProhibitedClass(aClass, ref); } if (highlightInfo == null) { highlightInfo = GenericsHighlightUtil.checkCannotInheritFromTypeParameter(aClass, ref); diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java index 59e39eabcfb4..a535a7511618 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java @@ -1042,6 +1042,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh PsiJavaCodeReferenceElement classReference = expression.getClassReference(); myHolder.add(HighlightUtil.checkUnhandledExceptions(expression, classReference != null ? classReference.getTextRange() : null)); if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkAnonymousInheritFinal(expression)); + if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkAnonymousInheritProhibited(expression)); if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkQualifiedNew(expression, type, aClass)); if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkCreateInnerClassFromStaticContext(expression, type, aClass)); if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkTypeParameterInstantiation(expression)); diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/PsiClassImplUtil.java b/java/java-psi-impl/src/com/intellij/psi/impl/PsiClassImplUtil.java index 8aeedaf1931a..04bede0cdecf 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/PsiClassImplUtil.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/PsiClassImplUtil.java @@ -704,6 +704,9 @@ public class PsiClassImplUtil { if (psiClass.isEnum()) { return findSpecialSuperClass(psiClass, CommonClassNames.JAVA_LANG_ENUM); } + if (psiClass.isRecord()) { + return findSpecialSuperClass(psiClass, CommonClassNames.JAVA_LANG_RECORD); + } if (psiClass instanceof PsiAnonymousClass) { PsiClassType baseClassReference = ((PsiAnonymousClass)psiClass).getBaseClassType(); @@ -941,6 +944,14 @@ public class PsiClassImplUtil { PsiClassType enumSuperType = getEnumSuperType(psiClass, JavaPsiFacade.getElementFactory(psiClass.getProject())); return enumSuperType == null ? PsiClassType.EMPTY_ARRAY : new PsiClassType[]{enumSuperType}; } + if (psiClass.isRecord()) { + final PsiClass recordClass = findSpecialSuperClass(psiClass, CommonClassNames.JAVA_LANG_RECORD); + if (recordClass != null) { + return new PsiClassType[]{new PsiImmediateClassType(recordClass, PsiSubstitutor.EMPTY)}; + } + PsiElementFactory factory = JavaPsiFacade.getElementFactory(psiClass.getProject()); + return new PsiClassType[]{factory.createTypeByFQClassName(CommonClassNames.JAVA_LANG_RECORD, psiClass.getResolveScope())}; + } if (psiClass.isAnnotationType()) { return new PsiClassType[]{getAnnotationSuperType(psiClass, JavaPsiFacade.getElementFactory(psiClass.getProject()))}; } diff --git a/java/java-psi-impl/src/messages/JavaErrorMessages.properties b/java/java-psi-impl/src/messages/JavaErrorMessages.properties index 2c82c5bc8ded..b63a07a7e3db 100644 --- a/java/java-psi-impl/src/messages/JavaErrorMessages.properties +++ b/java/java-psi-impl/src/messages/JavaErrorMessages.properties @@ -110,7 +110,7 @@ vararg.not.last.parameter=Vararg parameter must be the last in the list modifiers.for.enum.constants=No modifiers allowed for enum constants generics.type.arguments.on.raw.type=Type arguments given on a raw type generics.type.arguments.on.raw.method=Type arguments given on a raw method -classes.extends.enum=Classes cannot directly extend 'java.lang.Enum' +classes.extends.prohibited.super=Classes cannot directly extend ''{0}'' unchecked.overriding.incompatible.return.type=Unchecked overriding: return type requires unchecked conversion. Found ''{0}'', required ''{1}'' local.enum=Enum must not be local diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlightingRecords/RecordBasics.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlightingRecords/RecordBasics.java index adb7396318c0..f26f22c42ed7 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlightingRecords/RecordBasics.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlightingRecords/RecordBasics.java @@ -7,6 +7,14 @@ class ClassWithComponents2( abstract record AbstractRecord() {} record ExtendsObject() extends Object {} class ExtendsRecord extends NoComponents {} +abstract class ExtendsJLR extends Record {} +class AnonymousExtendsJLR { + Record r = new Record() { + public boolean equals(Object other) {return this == other;} + public int hashCode() {return 0;} + public String toString() {return "";} + }; +} record ComponentModifiers( public int x, diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/Enum.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/Enum.java index f3b2950ee837..69995a2667fc 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/Enum.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/Enum.java @@ -123,6 +123,8 @@ class X extends E public X(String name, int ordinal) { super(name, ordinal); } + + Enum e = new Enum("", 0) {}; } enum StaticInEnumConstantInitializer { diff --git a/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/LightRecordsHighlightingTest.java b/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/LightRecordsHighlightingTest.java index b20979eaac18..84b49cd803ca 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/LightRecordsHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/LightRecordsHighlightingTest.java @@ -32,6 +32,11 @@ public class LightRecordsHighlightingTest extends LightJavaCodeInsightFixtureTes } private void doTest() { + myFixture.addClass("package java.lang; public abstract class Record {" + + "public abstract boolean equals(Object obj);" + + "public abstract int hashCode();" + + "public abstract String toString();" + + "}"); myFixture.configureByFile(getTestName(false) + ".java"); myFixture.checkHighlighting(); } diff --git a/platform/core-api/src/com/intellij/psi/CommonClassNames.java b/platform/core-api/src/com/intellij/psi/CommonClassNames.java index f7c5b5f2688e..c1dd821e01cd 100644 --- a/platform/core-api/src/com/intellij/psi/CommonClassNames.java +++ b/platform/core-api/src/com/intellij/psi/CommonClassNames.java @@ -12,6 +12,7 @@ public interface CommonClassNames { String JAVA_LANG_CLASS = "java.lang.Class"; String JAVA_LANG_OVERRIDE = "java.lang.Override"; String JAVA_LANG_ENUM = "java.lang.Enum"; + String JAVA_LANG_RECORD = "java.lang.Record"; String JAVA_LANG_VOID = "java.lang.Void"; String JAVA_UTIL_OBJECTS = "java.util.Objects";