Proper checks for missing implementation of abstract method in records (IDEA-228460, IDEA-CR-56772)

GitOrigin-RevId: 1be11a80e1721116959dc24cb79c9feb4065f4ef
This commit is contained in:
Tagir Valeev
2019-12-19 13:26:15 +07:00
committed by intellij-monorepo-bot
parent b2fe378c9f
commit 39a9039c38
6 changed files with 16 additions and 8 deletions

View File

@@ -467,7 +467,8 @@ public class GenericsHighlightUtil {
defaultMethod.getSignature(PsiSubstitutor.EMPTY))) {
continue;
}
final String key = aClass instanceof PsiEnumConstantInitializer ? "enum.constant.should.implement.method" : "class.must.be.abstract";
final String key = aClass instanceof PsiEnumConstantInitializer || aClass.isRecord() ?
"class.must.implement.method" : "class.must.be.abstract";
final String message = JavaErrorMessages.message(key, HighlightUtil.formatClass(aClass, false), JavaHighlightUtil.formatMethod(abstracts.get(0)),
HighlightUtil.formatClass(unrelatedMethodContainingClass, false));
final HighlightInfo info = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(classIdentifier).descriptionAndTooltip(message).create();

View File

@@ -74,10 +74,9 @@ public class HighlightClassUtil {
String baseClassName = HighlightUtil.formatClass(aClass, false);
String methodName = JavaHighlightUtil.formatMethod(abstractMethod);
String message = JavaErrorMessages.message(aClass instanceof PsiEnumConstantInitializer || implementsFixElement instanceof PsiEnumConstant ? "enum.constant.should.implement.method" : "class.must.be.abstract",
baseClassName,
methodName,
HighlightUtil.formatClass(superClass, false));
String messageKey = aClass instanceof PsiEnumConstantInitializer || aClass.isRecord() || implementsFixElement instanceof PsiEnumConstant ?
"class.must.implement.method" : "class.must.be.abstract";
String message = JavaErrorMessages.message(messageKey, baseClassName, methodName, HighlightUtil.formatClass(superClass, false));
HighlightInfo errorResult = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(range).descriptionAndTooltip(message).create();
final PsiMethod anyMethodToImplement = ClassUtil.getAnyMethodToImplement(aClass);
@@ -105,7 +104,7 @@ public class HighlightClassUtil {
if (aClass.isEnum()) {
if (hasEnumConstantsWithInitializer(aClass)) return null;
}
else if (aClass.hasModifierProperty(PsiModifier.ABSTRACT) || aClass.getRBrace() == null || aClass.isRecord()) {
else if (aClass.hasModifierProperty(PsiModifier.ABSTRACT) || aClass.getRBrace() == null) {
return null;
}
return checkClassWithAbstractMethods(aClass, textRange);

View File

@@ -59,7 +59,8 @@ public class ClassUtil {
for (HierarchicalMethodSignature signatureHierarchical : aClass.getVisibleSignatures()) {
PsiMethod method = signatureHierarchical.getMethod();
PsiClass containingClass = method.getContainingClass();
if (containingClass == null) {
// TODO: remove record check when we provide synthetic equals/hashCode/toString for Record classes
if (containingClass == null || CommonClassNames.JAVA_LANG_RECORD.equals(containingClass.getQualifiedName())) {
continue;
}
if (!aClass.equals(containingClass)

View File

@@ -121,7 +121,7 @@ implements.after.interface=No implements clause allowed for interface
extends.after.enum=No extends clause allowed for enum
static.declaration.in.inner.class=Inner classes cannot have static declarations
class.must.be.abstract=Class ''{0}'' must either be declared abstract or implement abstract method ''{1}'' in ''{2}''
enum.constant.should.implement.method=Class ''{0}'' must implement abstract method ''{1}'' in ''{2}''
class.must.implement.method=Class ''{0}'' must implement abstract method ''{1}'' in ''{2}''
abstract.cannot.be.instantiated=''{0}'' is abstract; cannot be instantiated
duplicate.class.in.other.file=Duplicate class found in the file ''{0}''
duplicate.class=Duplicate class: ''{0}''

View File

@@ -15,6 +15,10 @@ class AnonymousExtendsJLR {
public String toString() {return "";}
};
}
<error descr="Class 'SuperInterface' must implement abstract method 'run()' in 'Runnable'">record SuperInterface() implements Runnable</error> {}
interface I1 { default void run() {}}
interface I2 { void run();}
record <error descr="Class 'UnrelatedDefaults' must implement abstract method 'run()' in 'I2'">UnrelatedDefaults</error>() implements I1, I2 {}
record ComponentModifiers(
<error descr="Modifier 'public' not allowed here">public</error> int x,

View File

@@ -0,0 +1,3 @@
// "Make 'Rec' abstract" "false"
record R<caret>ec() implements Runnable {
}