IDEA-121698 Automatically make variables accessed from outer scopes final

This commit is contained in:
peter
2014-03-05 19:11:43 +01:00
parent 6166a0e4fb
commit 2c6cea692a
4 changed files with 35 additions and 2 deletions

View File

@@ -3,16 +3,23 @@ package com.intellij.codeInsight.lookup;
import com.intellij.codeInsight.AutoPopupController;
import com.intellij.codeInsight.TailType;
import com.intellij.codeInsight.completion.*;
import com.intellij.codeInsight.daemon.impl.analysis.HighlightControlFlowUtil;
import com.intellij.featureStatistics.FeatureUsageTracker;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.RangeMarker;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.controlFlow.ControlFlowUtil;
import com.intellij.psi.impl.source.PostprocessReformattingAspect;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.containers.HashMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
/**
* @author peter
*/
@@ -115,6 +122,9 @@ public class VariableLookupItem extends LookupItem<PsiVariable> implements Typed
JavaCodeStyleManager.getInstance(context.getProject()).shortenClassReferences(ref);
}
ref = PsiTreeUtil.findElementOfClassAtOffset(context.getFile(), context.getTailOffset() - 1, PsiReferenceExpression.class, false);
makeVariableFinalIfNeeded(context, ref);
final char completionChar = context.getCompletionChar();
if (completionChar == '=') {
context.setAddCompletionChar(false);
@@ -141,6 +151,25 @@ public class VariableLookupItem extends LookupItem<PsiVariable> implements Typed
}
}
private static void makeVariableFinalIfNeeded(InsertionContext context, @Nullable PsiReferenceExpression ref) {
if (!Registry.is("java.completion.make.outer.variables.final") ||
ref == null || PsiUtil.isLanguageLevel8OrHigher(ref) || JspPsiUtil.isInJspFile(ref)) {
return;
}
PsiElement target = ref.resolve();
if (target instanceof PsiLocalVariable || target instanceof PsiParameter) {
PsiClass placeClass = PsiTreeUtil.findElementOfClassAtOffset(context.getFile(), context.getTailOffset() - 1, PsiClass.class, false);
if (placeClass != null && !PsiTreeUtil.isAncestor(placeClass, target, true) &&
!HighlightControlFlowUtil.isReassigned((PsiVariable)target, new HashMap<PsiElement, Collection<ControlFlowUtil.VariableInfo>>())) {
PsiModifierList modifierList = ((PsiVariable)target).getModifierList();
if (modifierList != null) {
modifierList.setModifierProperty(PsiModifier.FINAL, true);
}
}
}
}
private boolean shouldQualify(PsiField field, InsertionContext context) {
if (myHelper != null && !myHelper.willBeImported()) {
return true;

View File

@@ -1,6 +1,6 @@
class C{
{
Object o;
final Object o;
if (o instanceof Foo) {
new Runnable() {
public void run() {

View File

@@ -10,7 +10,7 @@ package codeInsight.completion.variables.locals;
public class TestSource4 {
int aaa = 0;
public static void foo(){
int abc = 0;
final int abc = 0;
class Inner1{
int sbe=abc<caret>
}

View File

@@ -227,6 +227,10 @@ projectView.hide.dot.idea=true
show.live.templates.in.completion=true
ide.completion.autopopup.select.live.templates=true
ide.completion.autopopup.choose.by.enter=true
java.completion.make.outer.variables.final=true
java.completion.make.outer.variables.final.description=Make variables accessed from inner class final automatically
documentation.component.editor.font=false
ide.completion.show.better.matching.classes=true