mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
do not warn about effectively final vars used in inner classes in java 8 (IDEA-91372)
This commit is contained in:
+36
-27
@@ -23,6 +23,7 @@ import com.intellij.codeInsight.intention.IntentionAction;
|
||||
import com.intellij.codeInsight.intention.QuickFixFactory;
|
||||
import com.intellij.openapi.project.IndexNotReadyException;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.controlFlow.*;
|
||||
import com.intellij.psi.search.LocalSearchScope;
|
||||
@@ -698,7 +699,11 @@ public class HighlightControlFlowUtil {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
String description = JavaErrorMessages.message("variable.must.be.final", context.getText());
|
||||
if (PsiUtil.getLanguageLevel(variable).isAtLeast(LanguageLevel.JDK_1_8) &&
|
||||
isEffectivelyFinal(variable, innerClass, context)) {
|
||||
return null;
|
||||
}
|
||||
final String description = JavaErrorMessages.message("variable.must.be.final", context.getText());
|
||||
|
||||
final HighlightInfo highlightInfo = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, context, description);
|
||||
QuickFixAction.registerQuickFixAction(highlightInfo, new VariableAccessFromInnerClassFix(variable, innerClass));
|
||||
@@ -706,33 +711,11 @@ public class HighlightControlFlowUtil {
|
||||
} else {
|
||||
final PsiLambdaExpression lambdaExpression = PsiTreeUtil.getParentOfType(context, PsiLambdaExpression.class);
|
||||
if (lambdaExpression != null && !PsiTreeUtil.isAncestor(lambdaExpression, variable, true)) {
|
||||
boolean effectivelyFinal;
|
||||
if (variable instanceof PsiParameter) {
|
||||
final PsiElement parent = variable.getParent();
|
||||
if (parent instanceof PsiParameterList && parent.getParent() == lambdaExpression) {
|
||||
return null;
|
||||
}
|
||||
effectivelyFinal = notAccessedForWriting(variable, new LocalSearchScope(((PsiParameter)variable).getDeclarationScope()));
|
||||
} else {
|
||||
final ControlFlow controlFlow;
|
||||
try {
|
||||
controlFlow = getControlFlow(PsiUtil.getVariableCodeBlock(variable, context));
|
||||
}
|
||||
catch (AnalysisCanceledException e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (ControlFlowUtil.isVariableDefinitelyAssigned(variable, controlFlow)) {
|
||||
final Collection<ControlFlowUtil.VariableInfo> initializedTwice = ControlFlowUtil.getInitializedTwice(controlFlow);
|
||||
effectivelyFinal = !initializedTwice.contains(new ControlFlowUtil.VariableInfo(variable, null));
|
||||
if (effectivelyFinal) {
|
||||
effectivelyFinal = notAccessedForWriting(variable, new LocalSearchScope(lambdaExpression));
|
||||
}
|
||||
} else {
|
||||
effectivelyFinal = false;
|
||||
}
|
||||
final PsiElement parent = variable.getParent();
|
||||
if (parent instanceof PsiParameterList && parent.getParent() == lambdaExpression) {
|
||||
return null;
|
||||
}
|
||||
if (!effectivelyFinal ) {
|
||||
if (!isEffectivelyFinal(variable, lambdaExpression, context)) {
|
||||
return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, context, "Variable used in lambda expression should be effectively final");
|
||||
}
|
||||
}
|
||||
@@ -740,6 +723,32 @@ public class HighlightControlFlowUtil {
|
||||
return null;
|
||||
}
|
||||
|
||||
private static boolean isEffectivelyFinal(PsiVariable variable, PsiElement scope, PsiJavaCodeReferenceElement context) {
|
||||
boolean effectivelyFinal;
|
||||
if (variable instanceof PsiParameter) {
|
||||
effectivelyFinal = notAccessedForWriting(variable, new LocalSearchScope(((PsiParameter)variable).getDeclarationScope()));
|
||||
} else {
|
||||
final ControlFlow controlFlow;
|
||||
try {
|
||||
controlFlow = getControlFlow(PsiUtil.getVariableCodeBlock(variable, context));
|
||||
}
|
||||
catch (AnalysisCanceledException e) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (ControlFlowUtil.isVariableDefinitelyAssigned(variable, controlFlow)) {
|
||||
final Collection<ControlFlowUtil.VariableInfo> initializedTwice = ControlFlowUtil.getInitializedTwice(controlFlow);
|
||||
effectivelyFinal = !initializedTwice.contains(new ControlFlowUtil.VariableInfo(variable, null));
|
||||
if (effectivelyFinal) {
|
||||
effectivelyFinal = notAccessedForWriting(variable, new LocalSearchScope(scope));
|
||||
}
|
||||
} else {
|
||||
effectivelyFinal = false;
|
||||
}
|
||||
}
|
||||
return effectivelyFinal;
|
||||
}
|
||||
|
||||
private static boolean notAccessedForWriting(PsiVariable variable, final LocalSearchScope searchScope) {
|
||||
for (PsiReference reference : ReferencesSearch.search(variable, searchScope)) {
|
||||
final PsiElement element = reference.getElement();
|
||||
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
// "Make 'i' final" "false"
|
||||
import java.io.*;
|
||||
|
||||
class a {
|
||||
void f() {
|
||||
int i = 0;
|
||||
new Runnable() {
|
||||
public void run() {
|
||||
int ii = <caret>i;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.codeInsight.daemon.quickFix;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
|
||||
/**
|
||||
* User: anna
|
||||
*/
|
||||
public class VariableAccessFromInnerClass18Test extends LightQuickFixTestCase {
|
||||
public void test() throws Exception {
|
||||
doAllTests();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getBasePath() {
|
||||
return "/codeInsight/daemonCodeAnalyzer/quickFix/mustBeFinal18";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void beforeActionStarted(String testName, String contents) {
|
||||
for (int i=0;i<10;i++) {
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
myEditor.getDocument().insertString(myEditor.getCaretModel().getOffset(), "//");
|
||||
}
|
||||
});
|
||||
|
||||
doHighlighting();
|
||||
delete();
|
||||
delete();
|
||||
doHighlighting();
|
||||
}
|
||||
}
|
||||
}
|
||||
+7
-22
@@ -1,33 +1,18 @@
|
||||
|
||||
package com.intellij.codeInsight.daemon.quickFix;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
|
||||
public class VariableAccessFromInnerClassTest extends LightQuickFixTestCase {
|
||||
public void test() throws Exception {
|
||||
doAllTests();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void beforeActionStarted(String testName, String contents) {
|
||||
for (int i=0;i<10;i++) {
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
myEditor.getDocument().insertString(myEditor.getCaretModel().getOffset(), "//");
|
||||
}
|
||||
});
|
||||
|
||||
doHighlighting();
|
||||
delete();
|
||||
delete();
|
||||
doHighlighting();
|
||||
}
|
||||
}
|
||||
public class VariableAccessFromInnerClassTest extends VariableAccessFromInnerClass18Test {
|
||||
|
||||
@Override
|
||||
protected String getBasePath() {
|
||||
return "/codeInsight/daemonCodeAnalyzer/quickFix/mustBeFinal";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected LanguageLevel getLanguageLevel() {
|
||||
return LanguageLevel.JDK_1_7;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user