start template when anonymous class is completed with Object params (need better heuristic)

This commit is contained in:
Anna Kozlova
2014-06-04 15:33:38 +04:00
parent f9a561c52e
commit b6b5bbdbd6
@@ -3,16 +3,21 @@ package com.intellij.codeInsight.completion;
import com.intellij.codeInsight.ExpectedTypeInfo;
import com.intellij.codeInsight.ExpectedTypesProvider;
import com.intellij.codeInsight.generation.GenerateMembersUtil;
import com.intellij.codeInsight.generation.OverrideImplementExploreUtil;
import com.intellij.codeInsight.generation.OverrideImplementUtil;
import com.intellij.codeInsight.generation.PsiGenerationInfo;
import com.intellij.codeInsight.intention.impl.TypeExpression;
import com.intellij.codeInsight.lookup.Lookup;
import com.intellij.codeInsight.lookup.LookupElementDecorator;
import com.intellij.codeInsight.lookup.LookupItem;
import com.intellij.codeInsight.lookup.PsiTypeLookupItem;
import com.intellij.codeInsight.template.*;
import com.intellij.featureStatistics.FeatureUsageTracker;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.command.UndoConfirmationPolicy;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
@@ -25,6 +30,7 @@ import com.intellij.psi.infos.CandidateInfo;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtilCore;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -243,46 +249,98 @@ public class ConstructorInsertHandler implements InsertHandler<LookupElementDeco
return new Runnable() {
@Override
public void run(){
CommandProcessor.getInstance().executeCommand(project, new Runnable() {
@Override
public void run() {
PsiDocumentManager.getInstance(project).commitDocument(editor.getDocument());
final PsiAnonymousClass aClass = PsiTreeUtil.findElementOfClassAtOffset(file, editor.getCaretModel().getOffset(), PsiAnonymousClass.class, false);
if (aClass == null) return;
final Runnable runnable = new Runnable() {
public void run() {
PsiDocumentManager.getInstance(project).commitDocument(editor.getDocument());
final PsiAnonymousClass aClass = PsiTreeUtil.findElementOfClassAtOffset(file, editor.getCaretModel().getOffset(), PsiAnonymousClass.class, false);
if (aClass == null) return;
final Collection<CandidateInfo> candidatesToImplement = OverrideImplementUtil.getMethodsToOverrideImplement(aClass, true);
for (Iterator<CandidateInfo> iterator = candidatesToImplement.iterator(); iterator.hasNext(); ) {
final CandidateInfo candidate = iterator.next();
final PsiElement element = candidate.getElement();
if (element instanceof PsiMethod && ((PsiMethod)element).hasModifierProperty(PsiModifier.DEFAULT)) {
iterator.remove();
}
}
boolean invokeOverride = candidatesToImplement.isEmpty();
if (invokeOverride){
OverrideImplementUtil.chooseAndOverrideOrImplementMethods(project, editor, aClass, false);
}
else{
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run() {
try{
List<PsiMethod> methods = OverrideImplementUtil.overrideOrImplementMethodCandidates(aClass, candidatesToImplement, false);
List<PsiGenerationInfo<PsiMethod>> prototypes = OverrideImplementUtil.convert2GenerationInfos(methods);
List<PsiGenerationInfo<PsiMethod>> resultMembers = GenerateMembersUtil.insertMembersBeforeAnchor(aClass, null, prototypes);
resultMembers.get(0).positionCaret(editor, true);
}
catch(IncorrectOperationException ioe){
LOG.error(ioe);
CommandProcessor.getInstance().executeCommand(project, new Runnable() {
@Override
public void run() {
final Collection<CandidateInfo> candidatesToImplement = OverrideImplementExploreUtil.getMethodsToOverrideImplement(aClass, true);
for (Iterator<CandidateInfo> iterator = candidatesToImplement.iterator(); iterator.hasNext(); ) {
final CandidateInfo candidate = iterator.next();
final PsiElement element = candidate.getElement();
if (element instanceof PsiMethod && ((PsiMethod)element).hasModifierProperty(PsiModifier.DEFAULT)) {
iterator.remove();
}
}
});
}
boolean invokeOverride = candidatesToImplement.isEmpty();
if (invokeOverride) {
OverrideImplementUtil.chooseAndOverrideOrImplementMethods(project, editor, aClass, false);
}
else {
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run() {
try {
List<PsiMethod> methods = OverrideImplementUtil.overrideOrImplementMethodCandidates(aClass, candidatesToImplement, false);
List<PsiGenerationInfo<PsiMethod>> prototypes = OverrideImplementUtil.convert2GenerationInfos(methods);
List<PsiGenerationInfo<PsiMethod>> resultMembers =
GenerateMembersUtil.insertMembersBeforeAnchor(aClass, null, prototypes);
resultMembers.get(0).positionCaret(editor, true);
}
catch (IncorrectOperationException ioe) {
LOG.error(ioe);
}
}
});
}
}
}, getCommandName(), getCommandName(), UndoConfirmationPolicy.DEFAULT, editor.getDocument());
}
}, CompletionBundle.message("completion.smart.type.generate.anonymous.body"), null, UndoConfirmationPolicy.DEFAULT, editor.getDocument());
};
final PsiReferenceParameterList parameterList = aClass.getBaseClassReference().getParameterList();
final PsiTypeElement[] parameters = parameterList != null ? parameterList.getTypeParameterElements() : null;
if (startTypeTemplate(parameters)) {
startTemplate(aClass, runnable, parameters);
}
else {
runnable.run();
}
}
@Contract("null -> false")
private boolean startTypeTemplate(PsiTypeElement[] parameters) {
if (parameters != null && parameters.length > 0) {
for (PsiTypeElement parameter : parameters) {
if (!parameter.getType().equalsToText(CommonClassNames.JAVA_LANG_OBJECT)) {
return false;
}
}
return true;
}
return false;
}
private void startTemplate(final PsiAnonymousClass aClass, final Runnable runnable, @NotNull final PsiTypeElement[] parameters) {
new WriteCommandAction(aClass.getProject(), getCommandName(), getCommandName()) {
@Override
protected void run(@NotNull Result result) throws Throwable {
editor.getCaretModel().moveToOffset(aClass.getTextOffset());
final TemplateBuilderImpl templateBuilder = (TemplateBuilderImpl)TemplateBuilderFactory.getInstance().createTemplateBuilder(aClass);
for (int i = 0; i < parameters.length; i++) {
PsiTypeElement parameter = parameters[i];
templateBuilder.replaceElement(parameter, "param" + i, new TypeExpression(project, new PsiType[]{parameter.getType()}), true);
}
Template template = templateBuilder.buildInlineTemplate();
TemplateManager.getInstance(project).startTemplate(editor, template, false, null, new TemplateEditingAdapter() {
@Override
public void templateFinished(Template template, boolean brokenOff) {
if (!brokenOff) {
runnable.run();
}
}
});
}
}.execute();
}
};
}
private static String getCommandName() {
return CompletionBundle.message("completion.smart.type.generate.anonymous.body");
}
}