Java: statements before super() part I (IDEA-340403)

GitOrigin-RevId: 7307a469267746ed3432acd1e73c894ccc87a254
This commit is contained in:
Bas Leijdekkers
2023-12-20 13:10:04 +01:00
committed by intellij-monorepo-bot
parent 7b6abd34f3
commit 176a8e0bec
5 changed files with 38 additions and 12 deletions

View File

@@ -143,6 +143,7 @@ feature.classfile.api=ClassFile API
feature.stream.gatherers=Stream Gatherers
feature.foreign.functions=Foreign Function & Memory API
feature.virtual.threads=Virtual Threads
feature.statements.before.super=Statements before super()
find.searching.for.references.to.class.progress=Searching for references to class {0}...
find.usages.panel.title.derived.classes.cap=Derived classes

View File

@@ -67,10 +67,11 @@ import static com.intellij.util.ObjectUtils.tryCast;
public final class HighlightMethodUtil {
private static final Logger LOG = Logger.getInstance(HighlightMethodUtil.class);
private static final MethodSignature ourValuesEnumSyntheticMethod = MethodSignatureUtil.createMethodSignature("values",
PsiType.EMPTY_ARRAY,
PsiTypeParameter.EMPTY_ARRAY,
PsiSubstitutor.EMPTY);
private static final MethodSignature ourValuesEnumSyntheticMethod =
MethodSignatureUtil.createMethodSignature("values",
PsiType.EMPTY_ARRAY,
PsiTypeParameter.EMPTY_ARRAY,
PsiSubstitutor.EMPTY);
private HighlightMethodUtil() { }
@@ -1452,6 +1453,17 @@ public final class HighlightMethodUtil {
static HighlightInfo.Builder checkConstructorCallProblems(@NotNull PsiMethodCallExpression methodCall) {
if (!JavaPsiConstructorUtil.isConstructorCall(methodCall)) return null;
PsiMethod method = PsiTreeUtil.getParentOfType(methodCall, PsiMethod.class, true, PsiClass.class, PsiLambdaExpression.class);
PsiReferenceExpression expression = methodCall.getMethodExpression();
if (method == null || !method.isConstructor()) {
String message = JavaErrorBundle.message("constructor.call.only.allowed.in.constructor", expression.getText() + "()");
return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(methodCall).descriptionAndTooltip(message);
}
PsiMethodCallExpression constructorCall = JavaPsiConstructorUtil.findThisOrSuperCallInConstructor(method);
if (constructorCall != methodCall) {
return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(methodCall).descriptionAndTooltip(
JavaErrorBundle.message("only.one.constructor.call.allowed.in.constructor", expression.getText() + "()"));
}
PsiElement codeBlock = methodCall.getParent().getParent();
if (codeBlock instanceof PsiCodeBlock) {
PsiMethod ctor = tryCast(codeBlock.getParent(), PsiMethod.class);
@@ -1469,9 +1481,13 @@ public final class HighlightMethodUtil {
}
}
}
PsiReferenceExpression expression = methodCall.getMethodExpression();
if (!(codeBlock instanceof PsiCodeBlock) || !(codeBlock.getParent() instanceof PsiMethod)) {
String message = JavaErrorBundle.message("constructor.call.must.be.top.level.statement", expression.getText() + "()");
return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(methodCall).descriptionAndTooltip(message);
}
String message = JavaErrorBundle.message("constructor.call.must.be.first.statement", expression.getText() + "()");
return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(methodCall).descriptionAndTooltip(message);
return HighlightUtil.checkFeature(methodCall, HighlightingFeature.STATEMENTS_BEFORE_SUPER, PsiUtil.getLanguageLevel(methodCall),
methodCall.getContainingFile(), message, HighlightInfoType.ERROR);
}

View File

@@ -120,6 +120,7 @@ public enum HighlightingFeature {
STRUCTURED_CONCURRENCY(LanguageLevel.JDK_21_PREVIEW, "feature.structured.concurrency"),
CLASSFILE_API(LanguageLevel.JDK_22_PREVIEW, "feature.classfile.api"),
STREAM_GATHERERS(LanguageLevel.JDK_22_PREVIEW, "feature.stream.gatherers"),
STATEMENTS_BEFORE_SUPER(LanguageLevel.JDK_22_PREVIEW, "feature.statements.before.super"),
;
public static final @NonNls String JDK_INTERNAL_PREVIEW_FEATURE = "jdk.internal.PreviewFeature";

View File

@@ -157,6 +157,9 @@ abstract.method.in.non.abstract.class=Abstract method in non-abstract class
missing.return.type=Invalid method declaration; return type required
duplicate.method=''{0}'' is already defined in ''{1}''
constructor.call.must.be.first.statement=Call to ''{0}'' must be first statement in constructor body
constructor.call.only.allowed.in.constructor=Call to ''{0}'' only allowed in constructor body
constructor.call.must.be.top.level.statement=Call to ''{0}'' must be a top level statement in constructor body
only.one.constructor.call.allowed.in.constructor=Only one explicit constructor call allowed in constructor
direct.abstract.method.access=Abstract method ''{0}'' cannot be accessed directly
unrelated.overriding.methods.return.types=methods have unrelated return types
overrides.deprecated.method=Overrides deprecated method in ''{0}''

View File

@@ -11,34 +11,39 @@ class b extends a {
}
b(int i) {
this();
<error descr="Call to 'super()' must be first statement in constructor body">super(2)</error>;
<error descr="Only one explicit constructor call allowed in constructor">super(2)</error>;
}
b(char i) {
super(4);
<error descr="Call to 'this()' must be first statement in constructor body">this()</error>;
<error descr="Only one explicit constructor call allowed in constructor">this()</error>;
}
b(String s) {
try {
<error descr="Call to 'super()' must be first statement in constructor body">super(2)</error>;
<error descr="Call to 'super()' must be a top level statement in constructor body">super(2)</error>;
}
finally {
}
}
b(String s, int i) {
{
<error descr="Call to 'super()' must be first statement in constructor body">super(2)</error>;
<error descr="Call to 'super()' must be a top level statement in constructor body">super(2)</error>;
}
}
void f() {
<error descr="Call to 'super()' must be first statement in constructor body">super()</error>;
<error descr="Call to 'super()' only allowed in constructor body">super()</error>;
}
void g() {
<error descr="Call to 'this()' must be first statement in constructor body">this()</error>;
<error descr="Call to 'this()' only allowed in constructor body">this()</error>;
}
}
class Z {
Z() {
Object x = <error descr="Call to 'super()' must be a top level statement in constructor body">super()</error>;
}
}
class O extends A.B
{
public O(A a)