diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/ConstructorInsertHandler.java b/java/java-impl/src/com/intellij/codeInsight/completion/ConstructorInsertHandler.java index 2b3ef76b6957..5c30b77f7e08 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/ConstructorInsertHandler.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/ConstructorInsertHandler.java @@ -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 candidatesToImplement = OverrideImplementUtil.getMethodsToOverrideImplement(aClass, true); - for (Iterator 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 methods = OverrideImplementUtil.overrideOrImplementMethodCandidates(aClass, candidatesToImplement, false); - List> prototypes = OverrideImplementUtil.convert2GenerationInfos(methods); - List> 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 candidatesToImplement = OverrideImplementExploreUtil.getMethodsToOverrideImplement(aClass, true); + for (Iterator 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 methods = OverrideImplementUtil.overrideOrImplementMethodCandidates(aClass, candidatesToImplement, false); + List> prototypes = OverrideImplementUtil.convert2GenerationInfos(methods); + List> 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"); + } }