AddVariableInitializer updated corresponding to review IDEA-CR-6563

This commit is contained in:
Dmitry Batkovich
2015-11-13 13:18:30 +03:00
parent ed9ee21a61
commit ac943a693c
@@ -17,19 +17,23 @@ package com.intellij.codeInsight.daemon.impl.quickfix;
import com.intellij.codeInsight.CodeInsightBundle;
import com.intellij.codeInsight.FileModificationService;
import com.intellij.codeInsight.completion.*;
import com.intellij.codeInsight.completion.JavaInheritorsGetter;
import com.intellij.codeInsight.completion.PrefixMatcher;
import com.intellij.codeInsight.completion.StatisticsWeigher;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.codeInsight.lookup.*;
import com.intellij.codeInsight.lookup.ExpressionLookupItem;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.PsiTypeLookupItem;
import com.intellij.codeInsight.template.*;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.CaretModel;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.util.InheritanceUtil;
import com.intellij.psi.filters.getters.JavaMembersGetter;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiTypesUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.refactoring.util.RefactoringUtil;
import com.intellij.util.Consumer;
import com.intellij.util.Function;
import com.intellij.util.IncorrectOperationException;
@@ -38,11 +42,13 @@ import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import static com.intellij.util.containers.ContainerUtil.*;
import static com.intellij.util.containers.ContainerUtil.map;
import static com.intellij.util.containers.ContainerUtil.sorted;
public class AddVariableInitializerFix implements IntentionAction {
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.daemon.impl.quickfix.AddReturnFix");
@@ -76,11 +82,10 @@ public class AddVariableInitializerFix implements IntentionAction {
@Override
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
if (!FileModificationService.getInstance().prepareFileForWrite(myVariable.getContainingFile())) return;
final LookupElement[] suggestedInitializers = suggestInitializer(myVariable);
LOG.assertTrue(suggestedInitializers.length > 0);
LOG.assertTrue(suggestedInitializers[0] instanceof ExpressionLookupItem);
final PsiExpression initializer = (PsiExpression) suggestedInitializers[0].getObject();
final PsiExpression initializer = (PsiExpression)suggestedInitializers[0].getObject();
if (myVariable instanceof PsiLocalVariable) {
((PsiLocalVariable)myVariable).setInitializer(initializer);
}
@@ -88,7 +93,7 @@ public class AddVariableInitializerFix implements IntentionAction {
((PsiField)myVariable).setInitializer(initializer);
}
else {
LOG.error("Unknown variable type: "+myVariable);
LOG.error("Unknown variable type: " + myVariable);
}
runAssignmentTemplate(Collections.singletonList(myVariable.getInitializer()), suggestedInitializers, editor);
}
@@ -130,80 +135,20 @@ public class AddVariableInitializerFix implements IntentionAction {
public static LookupElement[] suggestInitializer(final PsiVariable variable) {
PsiType type = variable.getType();
final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(variable.getProject());
final List<LookupElement> result = new SmartList<LookupElement>();
final String defaultValue = PsiTypesUtil.getDefaultValueOfType(type);
final ExpressionLookupItem defaultExpression = new ExpressionLookupItem(elementFactory.createExpressionFromText(defaultValue, variable));
result.add(defaultExpression);
if (type instanceof PsiClassType) {
final PsiClass aClass = PsiTypesUtil.getPsiClass(type);
if (aClass != null) {
final LookupElement nullLookupItem = new ExpressionLookupItem(elementFactory.createExpressionFromText(PsiKeyword.NULL, variable));
if (InheritanceUtil.isInheritor(aClass, CommonClassNames.JAVA_LANG_ITERABLE) ||
InheritanceUtil.isInheritor(aClass, CommonClassNames.JAVA_UTIL_MAP)) {
final List<PsiType> suggestedTypes = new SmartList<PsiType>();
JavaInheritorsGetter.processInheritors(variable.getContainingFile(), variable, Collections.singleton((PsiClassType) type), PrefixMatcher.ALWAYS_TRUE, new Consumer<PsiType>() {
@Override
public void consume(PsiType type) {
LOG.assertTrue(type instanceof PsiClassType);
final PsiClass psiClass = PsiTypesUtil.getPsiClass(type);
if (psiClass != null &&
!psiClass.isInterface() &&
!psiClass.hasModifierProperty(PsiModifier.ABSTRACT) &&
psiClass.hasModifierProperty(PsiModifier.PUBLIC) &&
PsiUtil.hasDefaultConstructor(psiClass)) {
suggestedTypes.add(type);
}
}
});
List<LookupElement> sortedLookups = map(sorted(map(suggestedTypes, new Function<PsiType, LookupElement>() {
@Override
public LookupElement fun(PsiType type) {
return PsiTypeLookupItem.createLookupItem(type, variable);
}
}), new Comparator<LookupElement>() {
@Override
public int compare(LookupElement o1, LookupElement o2) {
final int count1 = StatisticsWeigher.getBaseStatisticsInfo(o1, null).getUseCount();
final int count2 = StatisticsWeigher.getBaseStatisticsInfo(o2, null).getUseCount();
return count2 - count1;
}
}), new Function<LookupElement, LookupElement>() {
@Override
public LookupElement fun(LookupElement element) {
final LookupElementDecorator<LookupElement> constructorLookupElement =
LookupElementDecorator.withInsertHandler(element, ConstructorInsertHandler.BASIC_INSTANCE);
return new LookupElementDecorator<LookupElement>(constructorLookupElement) {
@Override
public void renderElement(LookupElementPresentation presentation) {
super.renderElement(presentation);
presentation.setTailText("");
presentation.setItemText(PsiKeyword.NEW + " " + presentation.getItemText() + "()");
}
@Override
public void handleInsert(InsertionContext context) {
super.handleInsert(context);
context.getDocument().insertString(context.getStartOffset(), PsiKeyword.NEW + " ");
}
};
}
});
LookupElement[] result = new LookupElement[sortedLookups.size() + 1];
result[0] = nullLookupItem;
for (int i = 0; i < sortedLookups.size(); i++) {
LookupElement lookup = sortedLookups.get(i);
result[i + 1] = lookup;
}
return result;
} else {
if (PsiUtil.hasDefaultConstructor(aClass)) {
final PsiExpression newExpression = elementFactory
.createExpressionFromText(PsiKeyword.NEW + " " + type.getCanonicalText(false) + "()", variable);
return new LookupElement[]{nullLookupItem, new ExpressionLookupItem(newExpression)};
}
}
if (aClass != null && PsiUtil.hasDefaultConstructor(aClass)) {
final String expressionText = PsiKeyword.NEW + " " + type.getCanonicalText(false) + "()";
ExpressionLookupItem newExpression = new ExpressionLookupItem(elementFactory.createExpressionFromText(expressionText, variable));
result.add(newExpression);
}
}
final String defaultValue = PsiTypesUtil.getDefaultValueOfType(type);
final PsiExpression expression = elementFactory.createExpressionFromText(defaultValue, variable);
return new LookupElement[] {new ExpressionLookupItem(expression)};
return result.toArray(new LookupElement[result.size()]);
}
@Override