diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaMethodCallElement.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaMethodCallElement.java index cb9265c6a86b..09b57555cd23 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaMethodCallElement.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaMethodCallElement.java @@ -21,11 +21,14 @@ import com.intellij.codeInsight.lookup.*; import com.intellij.codeInsight.lookup.impl.JavaElementLookupRenderer; import com.intellij.codeInsight.template.*; import com.intellij.codeInsight.template.impl.ConstantNode; +import com.intellij.codeInsight.template.impl.TemplateImpl; import com.intellij.codeInsight.template.impl.TemplateManagerImpl; import com.intellij.codeInsight.template.impl.TemplateState; import com.intellij.featureStatistics.FeatureUsageTracker; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.event.DocumentAdapter; +import com.intellij.openapi.editor.event.DocumentEvent; import com.intellij.openapi.util.ClassConditionKey; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.Key; @@ -40,6 +43,8 @@ import com.intellij.psi.util.TypeConversionUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.concurrent.atomic.AtomicInteger; + /** * @author peter */ @@ -243,6 +248,8 @@ public class JavaMethodCallElement extends LookupItem implements Type TemplateState templateState = TemplateManagerImpl.getTemplateState(editor); if (templateState == null) return; + setupNonFilledArgumentRemoving(editor, templateState); + editor.putUserData(ARGUMENT_TEMPLATE_ACTIVE, this); Disposer.register(templateState, () -> { if (editor.getUserData(ARGUMENT_TEMPLATE_ACTIVE) == this) { @@ -251,6 +258,41 @@ public class JavaMethodCallElement extends LookupItem implements Type }); } + private static void setupNonFilledArgumentRemoving(final Editor editor, final TemplateState templateState) { + AtomicInteger maxEditedVariable = new AtomicInteger(-1); + editor.getDocument().addDocumentListener(new DocumentAdapter() { + @Override + public void documentChanged(DocumentEvent e) { + maxEditedVariable.set(Math.max(maxEditedVariable.get(), templateState.getCurrentVariableNumber())); + } + }, templateState); + + templateState.addTemplateStateListener(new TemplateEditingAdapter() { + @Override + public void currentVariableChanged(TemplateState templateState, Template template, int oldIndex, int newIndex) { + maxEditedVariable.set(Math.max(maxEditedVariable.get(), oldIndex)); + } + + @Override + public void beforeTemplateFinished(TemplateState state, Template template, boolean brokenOff) { + if (brokenOff) { + removeUntouchedArguments((TemplateImpl)template); + } + } + + private void removeUntouchedArguments(TemplateImpl template) { + int firstUnchangedVar = maxEditedVariable.get() + 1; + if (firstUnchangedVar >= template.getVariableCount()) return; + + TextRange startRange = templateState.getVariableRange(template.getVariableNameAt(firstUnchangedVar)); + TextRange endRange = templateState.getVariableRange(template.getVariableNameAt(template.getVariableCount() - 1)); + if (startRange == null || endRange == null) return; + + editor.getDocument().deleteString(startRange.getStartOffset(), endRange.getEndOffset()); + } + }); + } + private boolean shouldInsertTypeParameters() { return myMayNeedExplicitTypeParameters && !getInferenceSubstitutor().equals(PsiSubstitutor.EMPTY) && myMethod.getParameterList().getParametersCount() == 0; } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/TemplateEditingListener.java b/platform/lang-impl/src/com/intellij/codeInsight/template/TemplateEditingListener.java index 59ff3be18f90..5145043cee67 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/template/TemplateEditingListener.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/TemplateEditingListener.java @@ -23,6 +23,11 @@ import com.intellij.codeInsight.template.impl.TemplateState; */ public interface TemplateEditingListener { void beforeTemplateFinished(TemplateState state, Template template); + + default void beforeTemplateFinished(TemplateState state, Template template, boolean brokenOff) { + beforeTemplateFinished(state, template); + } + void templateFinished(Template template, boolean brokenOff); void templateCancelled(Template template); void currentVariableChanged(TemplateState templateState, Template template, int oldIndex, int newIndex); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateState.java b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateState.java index 2e9f250f12be..bcd4b755470e 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateState.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateState.java @@ -1090,7 +1090,7 @@ public class TemplateState implements Disposable { private void cleanupTemplateState(boolean brokenOff) { final Editor editor = myEditor; - fireBeforeTemplateFinished(); + fireBeforeTemplateFinished(brokenOff); if (!isDisposed()) { int oldVar = myCurrentVariableNumber; setCurrentVariableNumber(-1); @@ -1398,9 +1398,9 @@ public class TemplateState implements Disposable { } } - private void fireBeforeTemplateFinished() { + private void fireBeforeTemplateFinished(boolean brokenOff) { for (TemplateEditingListener listener : myListeners) { - listener.beforeTemplateFinished(this, myTemplate); + listener.beforeTemplateFinished(this, myTemplate, brokenOff); } }