java call completion: remove untouched argument placeholders when template is broken off

This commit is contained in:
peter
2016-09-28 17:51:51 +02:00
parent 808087b883
commit 148d76cbb1
3 changed files with 50 additions and 3 deletions
@@ -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<PsiMethod> 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<PsiMethod> 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;
}
@@ -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);
@@ -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);
}
}