From 8d7f95a137b93e3fe6cf369528fd4616f82fb125 Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Wed, 11 Sep 2013 16:17:02 +0200 Subject: [PATCH] IDEA-26350 (Bad Java code is green: variable might not have been initialized) --- .../analysis/HighlightControlFlowUtil.java | 18 +++++++++++++++--- .../psi/controlFlow/ControlFlowAnalyzer.java | 4 ++-- .../advHighlighting/AssignToFinal.java | 12 ++++++++++++ 3 files changed, 29 insertions(+), 5 deletions(-) diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightControlFlowUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightControlFlowUtil.java index fffd2cad3273..78d2dc6ea12e 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightControlFlowUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightControlFlowUtil.java @@ -380,6 +380,10 @@ public class HighlightControlFlowUtil { HighlightInfo highlightInfo = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(description).create(); QuickFixAction.registerQuickFixAction(highlightInfo, QUICK_FIX_FACTORY.createAddVariableInitializerFix(variable)); + if (variable instanceof PsiField) { + QuickFixAction.registerQuickFixAction(highlightInfo, + QUICK_FIX_FACTORY.createModifierListFix(variable, PsiModifier.FINAL, false, false)); + } return highlightInfo; } @@ -546,11 +550,14 @@ public class HighlightControlFlowUtil { @Nullable public static HighlightInfo checkCannotWriteToFinal(PsiExpression expression, @NotNull PsiFile containingFile) { PsiReferenceExpression reference = null; + boolean readBeforeWrite = false; if (expression instanceof PsiAssignmentExpression) { - final PsiExpression left = PsiUtil.skipParenthesizedExprDown(((PsiAssignmentExpression)expression).getLExpression()); + final PsiAssignmentExpression assignmentExpression = (PsiAssignmentExpression)expression; + final PsiExpression left = PsiUtil.skipParenthesizedExprDown(assignmentExpression.getLExpression()); if (left instanceof PsiReferenceExpression) { reference = (PsiReferenceExpression)left; } + readBeforeWrite = assignmentExpression.getOperationTokenType() != JavaTokenType.EQ; } else if (expression instanceof PsiPostfixExpression) { final PsiExpression operand = PsiUtil.skipParenthesizedExprDown(((PsiPostfixExpression)expression).getOperand()); @@ -558,6 +565,7 @@ public class HighlightControlFlowUtil { if (operand instanceof PsiReferenceExpression && (sign == JavaTokenType.PLUSPLUS || sign == JavaTokenType.MINUSMINUS)) { reference = (PsiReferenceExpression)operand; } + readBeforeWrite = true; } else if (expression instanceof PsiPrefixExpression) { final PsiExpression operand = PsiUtil.skipParenthesizedExprDown(((PsiPrefixExpression)expression).getOperand()); @@ -565,13 +573,17 @@ public class HighlightControlFlowUtil { if (operand instanceof PsiReferenceExpression && (sign == JavaTokenType.PLUSPLUS || sign == JavaTokenType.MINUSMINUS)) { reference = (PsiReferenceExpression)operand; } + readBeforeWrite = true; } final PsiElement resolved = reference == null ? null : reference.resolve(); PsiVariable variable = resolved instanceof PsiVariable ? (PsiVariable)resolved : null; if (variable == null || !variable.hasModifierProperty(PsiModifier.FINAL)) return null; - if (!canWriteToFinal(variable, expression, reference, containingFile)) { + final boolean canWrite = canWriteToFinal(variable, expression, reference, containingFile); + if (readBeforeWrite || !canWrite) { final String name = variable.getName(); - String description = JavaErrorMessages.message("assignment.to.final.variable", name); + String description = canWrite ? + JavaErrorMessages.message("variable.not.initialized", name) : + JavaErrorMessages.message("assignment.to.final.variable", name); final HighlightInfo highlightInfo = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(reference.getTextRange()).descriptionAndTooltip(description).create(); final PsiClass innerClass = getInnerClassVariableReferencedFrom(variable, expression); diff --git a/java/java-psi-impl/src/com/intellij/psi/controlFlow/ControlFlowAnalyzer.java b/java/java-psi-impl/src/com/intellij/psi/controlFlow/ControlFlowAnalyzer.java index c2675894986d..da3411af8ed6 100644 --- a/java/java-psi-impl/src/com/intellij/psi/controlFlow/ControlFlowAnalyzer.java +++ b/java/java-psi-impl/src/com/intellij/psi/controlFlow/ControlFlowAnalyzer.java @@ -1504,7 +1504,7 @@ class ControlFlowAnalyzer extends JavaElementVisitor { startElement(expression); IElementType op = expression.getOperationTokenType(); - PsiExpression operand = expression.getOperand(); + PsiExpression operand = PsiUtil.skipParenthesizedExprDown(expression.getOperand()); operand.accept(this); if (op == JavaTokenType.PLUSPLUS || op == JavaTokenType.MINUSMINUS) { if (operand instanceof PsiReferenceExpression) { @@ -1521,7 +1521,7 @@ class ControlFlowAnalyzer extends JavaElementVisitor { @Override public void visitPrefixExpression(PsiPrefixExpression expression) { startElement(expression); - PsiExpression operand = expression.getOperand(); + PsiExpression operand = PsiUtil.skipParenthesizedExprDown(expression.getOperand()); if (operand != null) { IElementType operationSign = expression.getOperationTokenType(); if (operationSign == JavaTokenType.EXCL) { diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/AssignToFinal.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/AssignToFinal.java index 1c3342a46009..171b63a8f06f 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/AssignToFinal.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/AssignToFinal.java @@ -80,3 +80,15 @@ class Foo { } } } +class T1 { + private final int i1; + private final int i2; + private final int i3; + private final int i4; + { + (i1)++; + ++(i2); + i3 += 1; + (i4) = 1; + } +} \ No newline at end of file