[java-inspections] IDEA-287325 Redundant assignment false-positive when used in catch

GitOrigin-RevId: d55ad9f7e81367d6ae8b362f21ca250edb084e42
This commit is contained in:
Tagir Valeev
2022-02-14 10:51:34 +00:00
committed by intellij-monorepo-bot
parent 14f58cbce4
commit 86e7c0d17a
7 changed files with 152 additions and 120 deletions
@@ -244,13 +244,21 @@ final class ControlFlowAnalyzer extends JavaElementVisitor {
}
}
// optimization: reduce number of instructions
boolean isGeneratingStatement = element instanceof PsiStatement && !(element instanceof PsiSwitchLabelStatement);
boolean isGeneratingCodeBlock = element instanceof PsiCodeBlock && !(element.getParent() instanceof PsiSwitchStatement);
if (isGeneratingStatement || isGeneratingCodeBlock) {
boolean isGeneratingStatement = element instanceof PsiStatement && !(element instanceof PsiSwitchLabelStatement) &&
!isAbruptStatement(element);
PsiElement parent = element.getParent();
boolean isGeneratingCodeBlock = element instanceof PsiCodeBlock && !(parent instanceof PsiSwitchStatement);
boolean isGeneratingExpression = element instanceof PsiExpression && !(element instanceof PsiSwitchExpression) &&
isAbruptStatement(parent);
if (isGeneratingStatement || isGeneratingCodeBlock || isGeneratingExpression) {
generateUncheckedExceptionJumps(element, atStart);
}
}
private static boolean isAbruptStatement(@NotNull PsiElement element) {
return element instanceof PsiReturnStatement || element instanceof PsiYieldStatement || element instanceof PsiThrowStatement;
}
private void finishElement(@NotNull PsiElement element) {
generateUncheckedExceptionJumpsIfNeeded(element, false);
@@ -877,7 +885,7 @@ final class ControlFlowAnalyzer extends JavaElementVisitor {
@Override
public void visitSwitchLabelStatement(PsiSwitchLabelStatement statement) {
startElement(statement);
generateCaseValueInstructions(statement.getCaseValues());
generateCaseValueInstructions(statement.getCaseLabelElementList());
finishElement(statement);
}
@@ -885,7 +893,7 @@ final class ControlFlowAnalyzer extends JavaElementVisitor {
public void visitSwitchLabeledRuleStatement(PsiSwitchLabeledRuleStatement statement) {
startElement(statement);
generateCaseValueInstructions(statement.getCaseValues());
generateCaseValueInstructions(statement.getCaseLabelElementList());
PsiStatement body = statement.getBody();
if (body != null) {
@@ -903,11 +911,13 @@ final class ControlFlowAnalyzer extends JavaElementVisitor {
finishElement(statement);
}
private void generateCaseValueInstructions(@Nullable PsiExpressionList values) {
private void generateCaseValueInstructions(@Nullable PsiCaseLabelElementList values) {
if (values != null) {
for (PsiExpression caseValue : values.getExpressions()) {
for (PsiCaseLabelElement caseValue : values.getElements()) {
ProgressManager.checkCanceled();
generateExpressionInstructions(caseValue);
if (caseValue instanceof PsiExpression) {
generateExpressionInstructions((PsiExpression)caseValue);
}
}
}
}
@@ -0,0 +1,16 @@
class Main {
static int test() {
String msg = "ERR1";
try {
msg = "ERR2"; // HERE
return throwsNFE();
} catch (NumberFormatException e) {
System.err.println(msg);
}
return 0;
}
static int throwsNFE() throws NumberFormatException {
throw new NumberFormatException("NFE");
}
}
@@ -1,30 +1,31 @@
0: COND_THROW_TO 9
1: GOTO [END] 7 RETURN
2: COND_THROW_TO 9
3: COND_THROW_TO 9
4: GOTO [END] 5
5: CALL 11
6: GOTO [END] 30
7: CALL 11
8: GOTO [END] 30 RETURN
9: CALL 11
10: GOTO [END] 29
11: COND_THROW_TO 19
12: EMPTY
13: COND_THROW_TO 19
14: GOTO [END] 15
15: CALL 21
16: GOTO [END] 26
17: CALL 21
18: GOTO [END] 27 RETURN
19: CALL 21
20: GOTO [END] 25
21: GOTO [END] 23 RETURN
22: RETURN FROM 21
23: RETURN FROM 21 TO 18
24: RETURN FROM 21 TO 20
25: THROW_TO 30
26: RETURN FROM 11
27: RETURN FROM 11 TO 8
28: RETURN FROM 11 TO 10
29: THROW_TO 30
0: COND_THROW_TO 10
1: COND_THROW_TO 10
2: COND_THROW_TO 10
3: GOTO [END] 8 RETURN
4: COND_THROW_TO 10
5: GOTO [END] 6
6: CALL 12
7: GOTO [END] 31
8: CALL 12
9: GOTO [END] 31 RETURN
10: CALL 12
11: GOTO [END] 30
12: COND_THROW_TO 20
13: EMPTY
14: COND_THROW_TO 20
15: GOTO [END] 16
16: CALL 22
17: GOTO [END] 27
18: CALL 22
19: GOTO [END] 28 RETURN
20: CALL 22
21: GOTO [END] 26
22: GOTO [END] 24 RETURN
23: RETURN FROM 22
24: RETURN FROM 22 TO 19
25: RETURN FROM 22 TO 21
26: THROW_TO 31
27: RETURN FROM 12
28: RETURN FROM 12 TO 9
29: RETURN FROM 12 TO 11
30: THROW_TO 31
@@ -1,27 +1,28 @@
0: READ obj
1: COND_GOTO [END] 27
2: COND_THROW_TO 9
3: COND_THROW_TO 20
4: EMPTY
5: THROW_TO 9
6: COND_THROW_TO 20
7: COND_THROW_TO 20
8: GOTO [END] 16
9: WRITE re
10: COND_THROW_TO 20
11: READ re
12: EMPTY
13: COND_THROW_TO 20
14: COND_THROW_TO 20
15: GOTO [END] 16
16: CALL 22
17: GOTO [END] 27
18: CALL 22
19: GOTO [END] 27 RETURN
20: CALL 22
21: GOTO [END] 26
22: WRITE obj
23: RETURN FROM 22
24: RETURN FROM 22 TO 19
25: RETURN FROM 22 TO 21
26: THROW_TO 27
1: COND_GOTO [END] 28
2: COND_THROW_TO 10
3: COND_THROW_TO 21
4: COND_THROW_TO 21
5: EMPTY
6: COND_THROW_TO 21
7: THROW_TO 10
8: COND_THROW_TO 21
9: GOTO [END] 17
10: WRITE re
11: COND_THROW_TO 21
12: READ re
13: EMPTY
14: COND_THROW_TO 21
15: COND_THROW_TO 21
16: GOTO [END] 17
17: CALL 23
18: GOTO [END] 28
19: CALL 23
20: GOTO [END] 28 RETURN
21: CALL 23
22: GOTO [END] 27
23: WRITE obj
24: RETURN FROM 23
25: RETURN FROM 23 TO 20
26: RETURN FROM 23 TO 22
27: THROW_TO 28
@@ -1,28 +1,30 @@
0: COND_THROW_TO 8
1: COND_THROW_TO 19
2: EMPTY
3: COND_THROW_TO 8
4: GOTO [END] 17 RETURN
5: COND_THROW_TO 19
6: COND_THROW_TO 19
7: GOTO [END] 15
8: WRITE e
9: COND_THROW_TO 19
10: EMPTY
11: THROW_TO 19
12: COND_THROW_TO 19
13: COND_THROW_TO 19
14: GOTO [END] 15
15: CALL 21
16: GOTO [END] 28
17: CALL 21
18: GOTO [END] 28 RETURN
19: CALL 21
20: GOTO [END] 27
21: EMPTY
22: COND_THROW_TO 26
23: RETURN FROM 21
24: RETURN FROM 21 TO 18
25: RETURN FROM 21 TO 20
26: RETURN FROM 21 TO 20
27: THROW_TO 28
0: COND_THROW_TO 9
1: COND_THROW_TO 21
2: COND_THROW_TO 21
3: EMPTY
4: COND_THROW_TO 9
5: COND_THROW_TO 21
6: GOTO [END] 19 RETURN
7: COND_THROW_TO 21
8: GOTO [END] 17
9: WRITE e
10: COND_THROW_TO 21
11: COND_THROW_TO 21
12: EMPTY
13: COND_THROW_TO 21
14: THROW_TO 21
15: COND_THROW_TO 21
16: GOTO [END] 17
17: CALL 23
18: GOTO [END] 30
19: CALL 23
20: GOTO [END] 30 RETURN
21: CALL 23
22: GOTO [END] 29
23: EMPTY
24: COND_THROW_TO 28
25: RETURN FROM 23
26: RETURN FROM 23 TO 20
27: RETURN FROM 23 TO 22
28: RETURN FROM 23 TO 22
29: THROW_TO 30
@@ -1,28 +1,29 @@
0: COND_THROW_TO 24
1: COND_THROW_TO 24
2: COND_THROW_TO 12
3: EMPTY
4: THROW_TO 24
5: COND_THROW_TO 12
6: COND_THROW_TO 12
7: GOTO [END] 8
8: CALL 14
9: GOTO [END] 23
10: CALL 14
11: GOTO [END] 28 RETURN
12: CALL 14
13: GOTO [END] 22
14: READ writer
15: EMPTY
16: COND_THROW_TO 21
17: COND_THROW_TO 21
18: RETURN FROM 14
19: RETURN FROM 14 TO 11
20: RETURN FROM 14 TO 13
21: RETURN FROM 14 TO 24
22: THROW_TO 28
23: GOTO [END] 28
24: WRITE e
25: READ e
26: EMPTY
27: GOTO [END] 28
0: COND_THROW_TO 25
1: COND_THROW_TO 25
2: COND_THROW_TO 13
3: COND_THROW_TO 13
4: EMPTY
5: COND_THROW_TO 13
6: THROW_TO 25
7: COND_THROW_TO 13
8: GOTO [END] 9
9: CALL 15
10: GOTO [END] 24
11: CALL 15
12: GOTO [END] 29 RETURN
13: CALL 15
14: GOTO [END] 23
15: READ writer
16: EMPTY
17: COND_THROW_TO 22
18: COND_THROW_TO 22
19: RETURN FROM 15
20: RETURN FROM 15 TO 12
21: RETURN FROM 15 TO 14
22: RETURN FROM 15 TO 25
23: THROW_TO 29
24: GOTO [END] 29
25: WRITE e
26: READ e
27: EMPTY
28: GOTO [END] 29
@@ -74,6 +74,7 @@ public class DefUseTest extends LightJavaCodeInsightFixtureTestCase {
public void testLastInTry() { doTest(); }
public void testFieldOverwrite() { doTest(); }
public void testFieldOverwriteAfterQualifierUpdate() { doTest(); }
public void testAssignmentInCatch() { doTest(); }
@NotNull
@Override