Java: Provide better error message - illegal forward reference (IDEA-337031)

GitOrigin-RevId: 789b0bca6e6b1f9d0d366cd20a011c194cf1af0d
This commit is contained in:
Bas Leijdekkers
2023-11-02 16:27:34 +01:00
committed by intellij-monorepo-bot
parent 8cbdbab21a
commit 60a6cb2a00
11 changed files with 45 additions and 40 deletions

View File

@@ -2537,7 +2537,10 @@ public final class HighlightUtil {
static HighlightInfo.Builder checkIllegalForwardReferenceToField(@NotNull PsiReferenceExpression expression, @NotNull PsiField referencedField) {
Boolean isIllegalForwardReference = isIllegalForwardReferenceToField(expression, referencedField, false);
if (isIllegalForwardReference == null) return null;
String description = JavaErrorBundle.message(isIllegalForwardReference ? "illegal.forward.reference" : "illegal.self.reference");
String key = referencedField instanceof PsiEnumConstant
? (isIllegalForwardReference ? "illegal.forward.reference.enum" : "illegal.self.reference.enum")
: (isIllegalForwardReference ? "illegal.forward.reference" : "illegal.self.reference");
String description = JavaErrorBundle.message(key, referencedField.getName());
return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(description);
}

View File

@@ -289,8 +289,10 @@ incorrect.number.of.nested.patterns=Incorrect number of nested patterns: expecte
pattern.is.not.exhaustive=Pattern ''{0}'' is not exhaustive on ''{1}''
identifier.is.not.allowed.here=Identifier is not allowed here
illegal.forward.reference=Illegal forward reference
illegal.self.reference=Illegal self reference
illegal.forward.reference=Cannot read value of field ''{0}'' before the field''s definition
illegal.self.reference=Cannot read value of field ''{0}'' from inside the fields''s definition
illegal.forward.reference.enum=Cannot refer to enum constant ''{0}'' before its definition
illegal.self.reference.enum=Cannot refer to enum constant ''{0}'' from inside its own definition
unknown.class=Unknown class: ''{0}''
illegal.type.void=Illegal type: 'void'

View File

@@ -6,22 +6,22 @@ public class a {
{
int i;
if (<error descr="Illegal forward reference">FI</error> == 4) i = 5;
if (<error descr="Cannot read value of field 'FI' before the field's definition">FI</error> == 4) i = 5;
}
final int FI = 4;
int k = 1 + <error descr="Illegal forward reference">ki</error>;
int k = 1 + <error descr="Cannot read value of field 'ki' before the field's definition">ki</error>;
int ki;
final int fi5 = <error descr="Illegal self reference">fi5</error> + 1;
final int fi5 = <error descr="Cannot read value of field 'fi5' from inside the fields's definition">fi5</error> + 1;
}
class a1 {
static int i = <error descr="Illegal forward reference">j</error> + 2;
static int i = <error descr="Cannot read value of field 'j' before the field's definition">j</error> + 2;
static int j = 4;
}
class a2 {
static { i = <error descr="Illegal forward reference">j</error> + 2; }
static { i = <error descr="Cannot read value of field 'j' before the field's definition">j</error> + 2; }
static int i, j;
static { j = 4; }
}
@@ -30,7 +30,7 @@ class a2 {
class UseBeforeDeclaration {
static {
x = 100; // ok - assignment
int y = <error descr="Illegal forward reference">x</error> + 1; // error - read before declaration
int y = <error descr="Cannot read value of field 'x' before the field's definition">x</error> + 1; // error - read before declaration
int v = x = 3; // ok - x at left hand side of assignment
int z = UseBeforeDeclaration.x * 2; // ok - not accessed via simple name
Object o = new Object(){
@@ -40,10 +40,10 @@ class UseBeforeDeclaration {
}
{
j = 200; // ok - assignment
j = <error descr="Illegal forward reference">j</error> + 1; // error - right hand side reads before declaration
int k = j = <error descr="Illegal forward reference">j</error> + 1;
j = <error descr="Cannot read value of field 'j' before the field's definition">j</error> + 1; // error - right hand side reads before declaration
int k = j = <error descr="Cannot read value of field 'j' before the field's definition">j</error> + 1;
int n = j = 300; // ok - j at left hand side of assignment
int h = <error descr="Illegal forward reference">j</error>++; // error - read before declaration
int h = <error descr="Cannot read value of field 'j' before the field's definition">j</error>++; // error - read before declaration
int l = this.j * 3; // ok - not accessed via simple name
Object o = new Object(){
void foo(){j++;} // ok - occurs in a different class
@@ -62,13 +62,13 @@ class UseBeforeDeclaration {
class a3 {
static {
<error descr="Illegal forward reference">i</error>+=1;
<error descr="Cannot read value of field 'i' before the field's definition">i</error>+=1;
}
static int j=<error descr="Illegal forward reference">i</error>+=1;
static int j=<error descr="Cannot read value of field 'i' before the field's definition">i</error>+=1;
static int i=0;
{
<error descr="Illegal forward reference">k</error>+=1;
<error descr="Cannot read value of field 'k' before the field's definition">k</error>+=1;
}
int n=<error descr="Illegal forward reference">k</error>+=1;
int n=<error descr="Cannot read value of field 'k' before the field's definition">k</error>+=1;
int k=0;
}

View File

@@ -103,7 +103,7 @@ enum OurEnum {
enum TestEnum
{
A(<error descr="Illegal forward reference">B</error>), B(A);
A(<error descr="Cannot refer to enum constant 'B' before its definition">B</error>), B(A);
TestEnum(TestEnum other) {
<error descr="Call to super is not allowed in enum constructor">super(null, 0)</error>;
}

View File

@@ -4,12 +4,12 @@ import java.util.ArrayList;
import java.util.List;
enum Enum1 {
A(<error descr="Illegal forward reference">B</error>.var),
A(<error descr="Cannot refer to enum constant 'B' before its definition">B</error>.var),
B(test.Enum1.A.var),
C(<error descr="Illegal forward reference">constant</error>),
C(<error descr="Cannot read value of field 'constant' before the field's definition">constant</error>),
D(Enum1.constant),
E(<error descr="Illegal forward reference">staticVar</error>),
F(<error descr="Illegal forward reference">Enum1.staticVar</error>)
E(<error descr="Cannot read value of field 'staticVar' before the field's definition">staticVar</error>),
F(<error descr="Cannot read value of field 'staticVar' before the field's definition">Enum1.staticVar</error>)
;
Enum1(String str) {
}
@@ -20,10 +20,10 @@ enum Enum1 {
}
enum Enum2 {
A(<error descr="Illegal forward reference">B</error>.var),
A(<error descr="Cannot refer to enum constant 'B' before its definition">B</error>.var),
B(A.var),
C(<error descr="Illegal forward reference">constant</error>),
D(<error descr="Illegal forward reference">Enum2.constant</error>)
C(<error descr="Cannot read value of field 'constant' before the field's definition">constant</error>),
D(<error descr="Cannot read value of field 'constant' before the field's definition">Enum2.constant</error>)
;
Enum2(List<String> str) {
}
@@ -33,15 +33,15 @@ enum Enum2 {
}
enum Enum3 {
A(<error descr="Illegal forward reference">B</error>),
B(<error descr="Illegal forward reference">Enum3.C</error>),
A(<error descr="Cannot refer to enum constant 'B' before its definition">B</error>),
B(<error descr="Cannot refer to enum constant 'C' before its definition">Enum3.C</error>),
C(A),
D(Enum3.B),
E(<error descr="Illegal forward reference">constant</error>),
F(<error descr="Illegal forward reference">Enum3.constant</error>),
E(<error descr="Cannot read value of field 'constant' before the field's definition">constant</error>),
F(<error descr="Cannot read value of field 'constant' before the field's definition">Enum3.constant</error>),
G(A.var),
H(<error descr="Illegal forward reference">staticVar</error>),
I(<error descr="Illegal forward reference">Enum3.staticVar</error>)
H(<error descr="Cannot read value of field 'staticVar' before the field's definition">staticVar</error>),
I(<error descr="Cannot read value of field 'staticVar' before the field's definition">Enum3.staticVar</error>)
;
Enum3(Enum3 str) {
}
@@ -54,7 +54,7 @@ enum Enum4 {
A
;
static final String C1 = Enum4.D;
static final String C2 = <error descr="Illegal forward reference">D</error>;
static final String C2 = <error descr="Cannot read value of field 'D' before the field's definition">D</error>;
static final String C3 = A.D;
static final String D = "";
}

View File

@@ -6,7 +6,7 @@ enum IDEA56239 {
System.out.println(FOO1);
System.out.println(<error descr="It is illegal to access static member 'C' from enum constructor or instance initializer">C</error>);
}
}, C(<error descr="Illegal forward reference">D</error>), D;
}, C(<error descr="Cannot refer to enum constant 'D' before its definition">D</error>), D;
public static String FOO = "";
public static final String FOO1 = "";

View File

@@ -91,7 +91,7 @@ enum OurEnum {
enum TestEnum
{
A(<error descr="Illegal forward reference">B</error>), B(A);
A(<error descr="Cannot refer to enum constant 'B' before its definition">B</error>), B(A);
TestEnum(TestEnum other) {
<error descr="Call to super is not allowed in enum constructor">super(null, 0)</error>;
}

View File

@@ -6,7 +6,7 @@ enum IDEA56239 {
System.out.println(FOO1);
System.out.println(<error descr="It is illegal to access static member 'C' from enum constructor or instance initializer">C</error>);
}
}, C(<error descr="Illegal forward reference">D</error>), D;
}, C(<error descr="Cannot refer to enum constant 'D' before its definition">D</error>), D;
public static String FOO = "";
public static final String FOO1 = "";

View File

@@ -1,5 +1,5 @@
public class LambdaTest {
Op lambda_fib = (n) -> (n < 2) ? 1 : <error descr="Illegal self reference">lambda_fib</error>.op(n - 1) + <error descr="Illegal self reference">lambda_fib</error>.op(n - 2);
Op lambda_fib = (n) -> (n < 2) ? 1 : <error descr="Cannot read value of field 'lambda_fib' from inside the fields's definition">lambda_fib</error>.op(n - 1) + <error descr="Cannot read value of field 'lambda_fib' from inside the fields's definition">lambda_fib</error>.op(n - 2);
{
Op lambda_fib = (n) -> (n < 2) ? 1 : <error descr="Variable 'lambda_fib' might not have been initialized">lambda_fib</error>.op(n - 1) + lambda_fib.op(n - 2);

View File

@@ -3,11 +3,11 @@ package test;
class Test {
void foo() {
enum Enum {
A(<error descr="Illegal forward reference">B</error>.var),
A(<error descr="Cannot refer to enum constant 'B' before its definition">B</error>.var),
B(A.var),
C(<error descr="Illegal forward reference">constant</error>),
D(<error descr="Illegal forward reference">Enum.staticVar</error>),
E(<error descr="Illegal forward reference">staticVar</error>),
C(<error descr="Cannot read value of field 'constant' before the field's definition">constant</error>),
D(<error descr="Cannot read value of field 'staticVar' before the field's definition">Enum.staticVar</error>),
E(<error descr="Cannot read value of field 'staticVar' before the field's definition">staticVar</error>),
;
Enum(String str) {
}

View File

@@ -230,7 +230,7 @@ class AdvancedArrayAccess {
System.out.println(array[0]); // <-- Value 'array[0]' was reported as always 'null'
}
private static final int[] ARR_FIRST = {<error descr="Illegal forward reference">ARR_SECOND</error>[0], 1};
private static final int[] ARR_FIRST = {<error descr="Cannot read value of field 'ARR_SECOND' before the field's definition">ARR_SECOND</error>[0], 1};
private static final int[] ARR_SECOND = {ARR_FIRST[0], 1};
void testSelfReference() {