IDEA-173444 Parameter hints in completion: incorrect behavior on value inserting before hint

This commit is contained in:
Dmitry Batrak
2017-05-25 17:48:09 +03:00
parent bdfe213c40
commit b2f3dd449b
3 changed files with 48 additions and 23 deletions
@@ -359,6 +359,11 @@ public class JavaMethodCallElement extends LookupItem<PsiMethod> implements Type
}
}
public static boolean hasCompletionHints(@NotNull PsiCallExpression expression) {
PsiExpressionList argumentList = expression.getArgumentList();
return argumentList != null && !ContainerUtil.isEmpty(argumentList.getUserData(COMPLETION_HINTS));
}
private static void setupNonFilledArgumentRemoving(final Editor editor, final TemplateState templateState) {
AtomicInteger maxEditedVariable = new AtomicInteger(-1);
editor.getDocument().addDocumentListener(new DocumentListener() {
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
* Copyright 2000-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,6 +16,7 @@
package com.intellij.codeInsight.hints
import com.intellij.codeInsight.completion.CompletionMemory
import com.intellij.codeInsight.completion.JavaMethodCallElement
import com.intellij.psi.*
import com.intellij.psi.impl.source.resolve.graphInference.PsiPolyExpressionUtil
import com.intellij.psi.impl.source.tree.java.PsiMethodCallExpressionImpl
@@ -26,6 +27,8 @@ import com.intellij.psi.util.TypeConversionUtil
object JavaInlayHintsProvider {
fun hints(callExpression: PsiCallExpression): Set<InlayInfo> {
if (JavaMethodCallElement.hasCompletionHints(callExpression)) return emptySet()
val resolveResult = callExpression.resolveMethodGenerics()
val hints = methodHints(callExpression, resolveResult)
if (hints.isNotEmpty()) return hints
@@ -30,6 +30,7 @@ import com.intellij.openapi.util.registry.RegistryValue;
import com.intellij.util.ui.UIUtil;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.locks.LockSupport;
import java.util.stream.Stream;
@@ -61,7 +62,7 @@ public class CompletionHintsTest extends LightFixtureCompletionTestCase {
myFixture.checkResultWithInlays("class C { void m() { System.setProperty(<hint text=\"key:\"/>, <hint text=\"value:\"/>) } }");
// check that hints don't disappear after daemon highlighting passes
runHintsPass();
waitForAllAsyncStuff();
myFixture.checkResultWithInlays("class C { void m() { System.setProperty(<hint text=\"key:\"/>, <hint text=\"value:\"/>) } }");
// test Tab/Shift+Tab navigation
@@ -78,15 +79,14 @@ public class CompletionHintsTest extends LightFixtureCompletionTestCase {
myFixture.type("\"a");
myFixture.performEditorAction("NextParameter");
myFixture.type("\"b");
runHintsPass();
waitForAllAsyncStuff();
myFixture.checkResultWithInlays("class C { void m() { System.setProperty(<hint text=\"key:\"/>\"a\", <hint text=\"value:\"/>\"b\") } }");
// test hints disappearance when caret moves out of parameter list
myFixture.performEditorAction("EditorRight");
myFixture.performEditorAction("EditorRight");
ParameterInfoController.waitForDelayedActions(getEditor(), 10, TimeUnit.SECONDS);
myFixture.performEditorAction(IdeActions.ACTION_EDITOR_MOVE_CARET_RIGHT);
myFixture.performEditorAction(IdeActions.ACTION_EDITOR_MOVE_CARET_RIGHT);
runHintsPass();
waitForAllAsyncStuff();
myFixture.checkResultWithInlays("class C { void m() { System.setProperty(\"a\", \"b\") } }");
}
@@ -97,7 +97,7 @@ public class CompletionHintsTest extends LightFixtureCompletionTestCase {
myFixture.checkResultWithInlays("class C { void m() { Character.forDigit(<hint text=\"digit:\"/>, <hint text=\"radix:\"/>) } }");
// check that hints don't disappear after daemon highlighting passes
runHintsPass();
waitForAllAsyncStuff();
myFixture.checkResultWithInlays("class C { void m() { Character.forDigit(<hint text=\"digit:\"/>, <hint text=\"radix:\"/>) } }");
// test Tab/Shift+Tab navigation
@@ -114,15 +114,14 @@ public class CompletionHintsTest extends LightFixtureCompletionTestCase {
myFixture.type("1");
myFixture.performEditorAction("NextParameter");
myFixture.type("2");
runHintsPass();
waitForAllAsyncStuff();
myFixture.checkResultWithInlays("class C { void m() { Character.forDigit(<hint text=\"digit:\"/>1, <hint text=\"radix:\"/>2) } }");
// test hints don't disappear when caret moves out of parameter list
myFixture.performEditorAction("EditorRight");
myFixture.performEditorAction("EditorRight");
ParameterInfoController.waitForDelayedActions(getEditor(), 10, TimeUnit.SECONDS);
myFixture.performEditorAction(IdeActions.ACTION_EDITOR_MOVE_CARET_RIGHT);
myFixture.performEditorAction(IdeActions.ACTION_EDITOR_MOVE_CARET_RIGHT);
runHintsPass();
waitForAllAsyncStuff();
myFixture.checkResultWithInlays("class C { void m() { Character.forDigit(<hint text=\"digit:\"/>1, <hint text=\"radix:\"/>2) } }");
}
@@ -136,7 +135,7 @@ public class CompletionHintsTest extends LightFixtureCompletionTestCase {
complete("forDigit");
myFixture.checkResultWithInlays("class C { void m() { Character.forDigit(<hint text=\"digit:\"/>, <hint text=\"radix:\"/>) } }");
runHintsPass();
waitForAllAsyncStuff();
myFixture.checkResultWithInlays("class C { void m() { Character.forDigit(<hint text=\"digit:\"/>, <hint text=\"radix:\"/>) } }");
}
finally {
@@ -180,25 +179,25 @@ public class CompletionHintsTest extends LightFixtureCompletionTestCase {
"}");
}
public void testNestedCompletion() {
public void testNestedCompletion() throws Exception {
myFixture.configureByText(JavaFileType.INSTANCE, "class C { void m() { System.setPro<caret> } }");
complete("setProperty");
runHintsPass();
waitForAllAsyncStuff();
myFixture.checkResultWithInlays("class C { void m() { System.setProperty(<hint text=\"key:\"/>, <hint text=\"value:\"/>) } }");
myFixture.type("System.getPro");
complete("getProperty(String key, String def)");
runHintsPass();
waitForAllAsyncStuff();
myFixture.checkResultWithInlays("class C { void m() { System.setProperty(<hint text=\"key:\"/>System.getProperty(<hint text=\"key:\"/>, <hint text=\"def:\"/>), <hint text=\"value:\"/>) } }");
myFixture.checkResult("class C { void m() { System.setProperty(System.getProperty(<caret>, ), ) } }");
}
public void testTabWithNestedCompletion() {
public void testTabWithNestedCompletion() throws Exception {
myFixture.configureByText(JavaFileType.INSTANCE, "class C { void m() { System.setPro<caret> } }");
complete("setProperty");
runHintsPass();
waitForAllAsyncStuff();
myFixture.type("System.getPro");
complete("getProperty(String key, String def)");
runHintsPass();
waitForAllAsyncStuff();
myFixture.checkResult("class C { void m() { System.setProperty(System.getProperty(<caret>, ), ) } }");
myFixture.performEditorAction("NextParameter");
myFixture.checkResult("class C { void m() { System.setProperty(System.getProperty(, <caret>), ) } }");
@@ -221,8 +220,7 @@ public class CompletionHintsTest extends LightFixtureCompletionTestCase {
complete("getProperty(String key, String def)");
myFixture.checkResultWithInlays("class C { void m() { System.getProperty(<hint text=\"key:\"/>, <hint text=\"def:\"/>) } }");
myFixture.performEditorAction(IdeActions.ACTION_EDITOR_DELETE);
ParameterInfoController.waitForDelayedActions(getEditor(), 1, TimeUnit.MINUTES);
runHintsPass();
waitForAllAsyncStuff();
myFixture.checkResultWithInlays("class C { void m() { System.getProperty( ) } }");
}
@@ -237,6 +235,24 @@ public class CompletionHintsTest extends LightFixtureCompletionTestCase {
getEditor().getCaretModel().getVisualPosition());
}
public void testNoHintsDuplicationWhenTypingToTheLeftOfHint() throws Exception {
myFixture.configureByText(JavaFileType.INSTANCE, "class C { void m() { Character.for<caret> } }");
complete("forDigit");
waitForAllAsyncStuff();
type("1");
myFixture.performEditorAction(IdeActions.ACTION_EDITOR_MOVE_CARET_RIGHT);
type("2");
waitForAllAsyncStuff();
myFixture.checkResultWithInlays("class C { void m() { Character.forDigit(<hint text=\"digit:\"/>1,2 <hint text=\"radix:\"/>) } }");
myFixture.performEditorAction(IdeActions.ACTION_EDITOR_MOVE_LINE_END);
waitForAllAsyncStuff();
myFixture.checkResultWithInlays("class C { void m() { Character.forDigit(<hint text=\"digit:\"/>1,<hint text=\"radix:\"/>2 ) } }");
}
private void waitForParameterInfoUpdate() throws TimeoutException {
ParameterInfoController.waitForDelayedActions(getEditor(), 1, TimeUnit.MINUTES);
}
private void showParameterInfo() {
myFixture.performEditorAction("ParameterInfo");
UIUtil.dispatchAllInvocationEvents();
@@ -261,7 +277,8 @@ public class CompletionHintsTest extends LightFixtureCompletionTestCase {
}
}
private void runHintsPass() {
private void waitForAllAsyncStuff() throws TimeoutException {
waitForParameterInfoUpdate();
myFixture.doHighlighting();
waitTillAnimationCompletes();
}