mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
highlight completion hints of currently filled method call
for IDEA-180808
This commit is contained in:
+77
-42
@@ -39,13 +39,11 @@ import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.util.MethodSignatureUtil;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.text.CharArrayUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author Maxim.Mossienko
|
||||
@@ -55,8 +53,10 @@ public class MethodParameterInfoHandler implements ParameterInfoHandlerWithTabAc
|
||||
PsiMethodCallExpression.class, PsiNewExpression.class, PsiAnonymousClass.class, PsiEnumConstant.class);
|
||||
|
||||
private static final Set<? extends Class> ourStopSearch = Collections.singleton(PsiMethod.class);
|
||||
|
||||
private Inlay myHighlightedHint;
|
||||
private static final String WHITESPACE = " \t";
|
||||
|
||||
private Inlay myCurrentHint;
|
||||
private List<Inlay> myHighlightedHints;
|
||||
|
||||
@Override
|
||||
public Object[] getParametersForLookup(LookupElement item, ParameterInfoContext context) {
|
||||
@@ -337,51 +337,86 @@ public class MethodParameterInfoHandler implements ParameterInfoHandlerWithTabAc
|
||||
private void highlightHints(@NotNull Editor editor, @Nullable PsiExpressionList expressionList, int currentHintIndex) {
|
||||
if (editor.isDisposed()) return;
|
||||
ParameterHintsPresentationManager presentationManager = ParameterHintsPresentationManager.getInstance();
|
||||
Inlay hint = null;
|
||||
if (expressionList != null && expressionList.isValid() &&
|
||||
currentHintIndex >= 0 && (currentHintIndex < expressionList.getExpressions().length ||
|
||||
currentHintIndex == 0 && expressionList.getExpressions().length == 0)) {
|
||||
PsiElement prevDelimiter, nextDelimiter;
|
||||
if (currentHintIndex < expressionList.getExpressions().length) {
|
||||
PsiExpression expression = expressionList.getExpressions()[currentHintIndex];
|
||||
//noinspection StatementWithEmptyBody
|
||||
for (prevDelimiter = expression;
|
||||
prevDelimiter != null && !(prevDelimiter instanceof PsiJavaToken);
|
||||
prevDelimiter = prevDelimiter.getPrevSibling())
|
||||
;
|
||||
//noinspection StatementWithEmptyBody
|
||||
for (nextDelimiter = expression;
|
||||
nextDelimiter != null && !(nextDelimiter instanceof PsiJavaToken);
|
||||
nextDelimiter = nextDelimiter.getNextSibling())
|
||||
;
|
||||
}
|
||||
else {
|
||||
prevDelimiter = expressionList.getFirstChild(); // left parenthesis
|
||||
nextDelimiter = expressionList.getLastChild(); // right parenthesis
|
||||
}
|
||||
if (prevDelimiter != null && nextDelimiter != null) {
|
||||
Inlay currentHint = null;
|
||||
List<Inlay> highlightedHints = null;
|
||||
if (expressionList != null && expressionList.isValid()) {
|
||||
int expressionCount = expressionList.getExpressions().length;
|
||||
if (currentHintIndex == 0 || currentHintIndex > 0 && currentHintIndex < expressionCount) {
|
||||
highlightedHints = new ArrayList<>(expressionCount);
|
||||
ParameterHintsPass.syncUpdate(expressionList.getParent(), editor);
|
||||
for (Inlay inlay : editor.getInlayModel().getInlineElementsInRange(prevDelimiter.getTextRange().getEndOffset(),
|
||||
nextDelimiter.getTextRange().getStartOffset())) {
|
||||
if (presentationManager.isParameterHint(inlay)) {
|
||||
hint = inlay;
|
||||
break;
|
||||
PsiElement prevDelimiter, nextDelimiter;
|
||||
for (int i = 0; i < Math.max(expressionCount, currentHintIndex == 0 ? 1 : 0); i++) {
|
||||
if (i < expressionCount) {
|
||||
PsiExpression expression = expressionList.getExpressions()[i];
|
||||
//noinspection StatementWithEmptyBody
|
||||
for (prevDelimiter = expression;
|
||||
prevDelimiter != null && !(prevDelimiter instanceof PsiJavaToken);
|
||||
prevDelimiter = prevDelimiter.getPrevSibling())
|
||||
;
|
||||
//noinspection StatementWithEmptyBody
|
||||
for (nextDelimiter = expression;
|
||||
nextDelimiter != null && !(nextDelimiter instanceof PsiJavaToken);
|
||||
nextDelimiter = nextDelimiter.getNextSibling())
|
||||
;
|
||||
}
|
||||
else {
|
||||
prevDelimiter = expressionList.getFirstChild(); // left parenthesis
|
||||
nextDelimiter = expressionList.getLastChild(); // right parenthesis
|
||||
}
|
||||
if (prevDelimiter != null && nextDelimiter != null) {
|
||||
CharSequence text = editor.getDocument().getImmutableCharSequence();
|
||||
int firstRangeStartOffset = prevDelimiter.getTextRange().getEndOffset();
|
||||
int firstRangeEndOffset = CharArrayUtil.shiftForward(text, firstRangeStartOffset, WHITESPACE);
|
||||
for (Inlay inlay : editor.getInlayModel().getInlineElementsInRange(firstRangeStartOffset, firstRangeEndOffset)) {
|
||||
if (presentationManager.isParameterHint(inlay)) {
|
||||
highlightedHints.add(inlay);
|
||||
if (i == currentHintIndex && currentHint == null) currentHint = inlay;
|
||||
}
|
||||
}
|
||||
int secondRangeEndOffset = nextDelimiter.getTextRange().getStartOffset();
|
||||
if (secondRangeEndOffset > firstRangeEndOffset) {
|
||||
int secondRangeStartOffset = CharArrayUtil.shiftBackward(text, secondRangeEndOffset - 1, WHITESPACE) + 1;
|
||||
for (Inlay inlay : editor.getInlayModel().getInlineElementsInRange(secondRangeStartOffset, secondRangeEndOffset)) {
|
||||
if (presentationManager.isParameterHint(inlay)) {
|
||||
highlightedHints.add(inlay);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (hint == myHighlightedHint) return;
|
||||
if (myHighlightedHint != null && myHighlightedHint.isValid()) presentationManager.setHighlighted(myHighlightedHint, false);
|
||||
myHighlightedHint = hint;
|
||||
if (myHighlightedHint != null && myHighlightedHint.isValid()) presentationManager.setHighlighted(myHighlightedHint, true);
|
||||
if (currentHint == myCurrentHint && Objects.equals(highlightedHints, myHighlightedHints)) return;
|
||||
resetHints();
|
||||
if (currentHint != null) {
|
||||
presentationManager.setCurrent(currentHint, true);
|
||||
myCurrentHint = currentHint;
|
||||
}
|
||||
if (!ContainerUtil.isEmpty(highlightedHints)) {
|
||||
for (Inlay highlightedHint : highlightedHints) {
|
||||
presentationManager.setHighlighted(highlightedHint, true);
|
||||
}
|
||||
myHighlightedHints = highlightedHints;
|
||||
}
|
||||
}
|
||||
|
||||
private void resetHints() {
|
||||
ParameterHintsPresentationManager presentationManager = ParameterHintsPresentationManager.getInstance();
|
||||
if (myCurrentHint != null) {
|
||||
presentationManager.setCurrent(myCurrentHint, false);
|
||||
myCurrentHint = null;
|
||||
}
|
||||
if (myHighlightedHints != null) {
|
||||
for (Inlay hint : myHighlightedHints) {
|
||||
presentationManager.setHighlighted(hint, false);
|
||||
}
|
||||
myHighlightedHints = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
if (myHighlightedHint != null) {
|
||||
if (myHighlightedHint.isValid()) ParameterHintsPresentationManager.getInstance().setHighlighted(myHighlightedHint, false);
|
||||
myHighlightedHint = null;
|
||||
}
|
||||
resetHints();
|
||||
}
|
||||
|
||||
private static PsiSubstitutor getCandidateInfoSubstitutor(PsiElement argList, CandidateInfo candidate, boolean resolveResult) {
|
||||
|
||||
+72
-72
@@ -60,26 +60,26 @@ public class CompletionHintsTest extends LightFixtureCompletionTestCase {
|
||||
// check hints appearance on completion
|
||||
configureJava("class C { void m() { System.setPro<caret> } }");
|
||||
complete("setProperty");
|
||||
checkResultWithInlays("class C { void m() { System.setProperty(<HINT text=\"key:\"/><caret>, <hint text=\"value:\"/>) } }");
|
||||
checkResultWithInlays("class C { void m() { System.setProperty(<HINT text=\"key:\"/><caret>, <Hint text=\"value:\"/>) } }");
|
||||
|
||||
// check that hints don't disappear after daemon highlighting passes
|
||||
waitForAllAsyncStuff();
|
||||
checkResultWithInlays("class C { void m() { System.setProperty(<HINT text=\"key:\"/><caret>, <hint text=\"value:\"/>) } }");
|
||||
checkResultWithInlays("class C { void m() { System.setProperty(<HINT text=\"key:\"/><caret>, <Hint text=\"value:\"/>) } }");
|
||||
|
||||
// test Tab/Shift+Tab navigation
|
||||
next();
|
||||
waitForAllAsyncStuff();
|
||||
checkResultWithInlays("class C { void m() { System.setProperty(<hint text=\"key:\"/>, <HINT text=\"value:\"/><caret>) } }");
|
||||
checkResultWithInlays("class C { void m() { System.setProperty(<Hint text=\"key:\"/>, <HINT text=\"value:\"/><caret>) } }");
|
||||
prev();
|
||||
waitForAllAsyncStuff();
|
||||
checkResultWithInlays("class C { void m() { System.setProperty(<HINT text=\"key:\"/><caret>, <hint text=\"value:\"/>) } }");
|
||||
checkResultWithInlays("class C { void m() { System.setProperty(<HINT text=\"key:\"/><caret>, <Hint text=\"value:\"/>) } }");
|
||||
|
||||
// test hints remain shown while entering parameter values
|
||||
myFixture.type("\"a");
|
||||
next();
|
||||
myFixture.type("\"b");
|
||||
waitForAllAsyncStuff();
|
||||
checkResultWithInlays("class C { void m() { System.setProperty(<hint text=\"key:\"/>\"a\", <HINT text=\"value:\"/>\"b<caret>\") } }");
|
||||
checkResultWithInlays("class C { void m() { System.setProperty(<Hint text=\"key:\"/>\"a\", <HINT text=\"value:\"/>\"b<caret>\") } }");
|
||||
|
||||
// test hints disappearance when caret moves out of parameter list
|
||||
right();
|
||||
@@ -95,26 +95,26 @@ public class CompletionHintsTest extends LightFixtureCompletionTestCase {
|
||||
// check hints appearance on completion
|
||||
configureJava("class C { void m() { Character.for<caret> } }");
|
||||
complete("forDigit");
|
||||
checkResultWithInlays("class C { void m() { Character.forDigit(<HINT text=\"digit:\"/><caret>, <hint text=\"radix:\"/>) } }");
|
||||
checkResultWithInlays("class C { void m() { Character.forDigit(<HINT text=\"digit:\"/><caret>, <Hint text=\"radix:\"/>) } }");
|
||||
|
||||
// check that hints don't disappear after daemon highlighting passes
|
||||
waitForAllAsyncStuff();
|
||||
checkResultWithInlays("class C { void m() { Character.forDigit(<HINT text=\"digit:\"/><caret>, <hint text=\"radix:\"/>) } }");
|
||||
checkResultWithInlays("class C { void m() { Character.forDigit(<HINT text=\"digit:\"/><caret>, <Hint text=\"radix:\"/>) } }");
|
||||
|
||||
// test Tab/Shift+Tab navigation
|
||||
next();
|
||||
waitForAllAsyncStuff();
|
||||
checkResultWithInlays("class C { void m() { Character.forDigit(<hint text=\"digit:\"/>, <HINT text=\"radix:\"/><caret>) } }");
|
||||
checkResultWithInlays("class C { void m() { Character.forDigit(<Hint text=\"digit:\"/>, <HINT text=\"radix:\"/><caret>) } }");
|
||||
prev();
|
||||
waitForAllAsyncStuff();
|
||||
checkResultWithInlays("class C { void m() { Character.forDigit(<HINT text=\"digit:\"/><caret>, <hint text=\"radix:\"/>) } }");
|
||||
checkResultWithInlays("class C { void m() { Character.forDigit(<HINT text=\"digit:\"/><caret>, <Hint text=\"radix:\"/>) } }");
|
||||
|
||||
// test hints remain shown while entering parameter values
|
||||
myFixture.type("1");
|
||||
next();
|
||||
myFixture.type("2");
|
||||
waitForAllAsyncStuff();
|
||||
checkResultWithInlays("class C { void m() { Character.forDigit(<hint text=\"digit:\"/>1, <HINT text=\"radix:\"/>2<caret>) } }");
|
||||
checkResultWithInlays("class C { void m() { Character.forDigit(<Hint text=\"digit:\"/>1, <HINT text=\"radix:\"/>2<caret>) } }");
|
||||
|
||||
// test hints don't disappear when caret moves out of parameter list
|
||||
right();
|
||||
@@ -133,10 +133,10 @@ public class CompletionHintsTest extends LightFixtureCompletionTestCase {
|
||||
|
||||
configureJava("class C { void m() { Character.for<caret> } }");
|
||||
complete("forDigit");
|
||||
checkResultWithInlays("class C { void m() { Character.forDigit(<HINT text=\"digit:\"/><caret>, <hint text=\"radix:\"/>) } }");
|
||||
checkResultWithInlays("class C { void m() { Character.forDigit(<HINT text=\"digit:\"/><caret>, <Hint text=\"radix:\"/>) } }");
|
||||
|
||||
waitForAllAsyncStuff();
|
||||
checkResultWithInlays("class C { void m() { Character.forDigit(<HINT text=\"digit:\"/><caret>, <hint text=\"radix:\"/>) } }");
|
||||
checkResultWithInlays("class C { void m() { Character.forDigit(<HINT text=\"digit:\"/><caret>, <Hint text=\"radix:\"/>) } }");
|
||||
}
|
||||
finally {
|
||||
option.set(savedValue);
|
||||
@@ -150,7 +150,7 @@ public class CompletionHintsTest extends LightFixtureCompletionTestCase {
|
||||
showParameterInfo();
|
||||
methodOverloadDown();
|
||||
checkResultWithInlays(
|
||||
"class C { void m() { Character.toChars(<HINT text=\"codePoint:\"/><caret>, <hint text=\"dst:\"/>, <hint text=\"dstIndex:\"/>) } }");
|
||||
"class C { void m() { Character.toChars(<HINT text=\"codePoint:\"/><caret>, <Hint text=\"dst:\"/>, <Hint text=\"dstIndex:\"/>) } }");
|
||||
}
|
||||
|
||||
public void testSwitchingOverloadsWithParameterFilled() {
|
||||
@@ -160,7 +160,7 @@ public class CompletionHintsTest extends LightFixtureCompletionTestCase {
|
||||
checkResultWithInlays("class C { void m() { Character.toChars(<HINT text=\"codePoint:\"/>123<caret>) } }");
|
||||
showParameterInfo();
|
||||
methodOverloadDown();
|
||||
checkResultWithInlays("class C { void m() { Character.toChars(<hint text=\"codePoint:\"/>123, <HINT text=\"dst:\"/><caret>, <hint text=\"dstIndex:\"/>) } }");
|
||||
checkResultWithInlays("class C { void m() { Character.toChars(<Hint text=\"codePoint:\"/>123, <HINT text=\"dst:\"/><caret>, <Hint text=\"dstIndex:\"/>) } }");
|
||||
}
|
||||
|
||||
public void testSwitchingOverloadsForMethodWithDisabledHints() throws Exception {
|
||||
@@ -173,7 +173,7 @@ public class CompletionHintsTest extends LightFixtureCompletionTestCase {
|
||||
checkResultWithInlays("class C {\n" +
|
||||
" int some(int from, int to) { return 0; }\n" +
|
||||
" int some(int from, int to, int other) { return 0; }\n" +
|
||||
" void m() { some(<HINT text=\"from:\"/><caret>, <hint text=\"to:\"/>, <hint text=\"other:\"/>) }\n" +
|
||||
" void m() { some(<HINT text=\"from:\"/><caret>, <Hint text=\"to:\"/>, <Hint text=\"other:\"/>) }\n" +
|
||||
"}");
|
||||
showParameterInfo();
|
||||
checkHintContents("<html><b>int from</b>, int to</html>\n" +
|
||||
@@ -184,7 +184,7 @@ public class CompletionHintsTest extends LightFixtureCompletionTestCase {
|
||||
checkResultWithInlays("class C {\n" +
|
||||
" int some(int from, int to) { return 0; }\n" +
|
||||
" int some(int from, int to, int other) { return 0; }\n" +
|
||||
" void m() { some(<HINT text=\"from:\"/><caret>, <hint text=\"to:\"/>) }\n" +
|
||||
" void m() { some(<HINT text=\"from:\"/><caret>, <Hint text=\"to:\"/>) }\n" +
|
||||
"}");
|
||||
checkHintContents("[<html><b>int from</b>, int to</html>]\n" +
|
||||
"-\n" +
|
||||
@@ -211,11 +211,11 @@ public class CompletionHintsTest extends LightFixtureCompletionTestCase {
|
||||
configureJava("class C { void m() { System.setPro<caret> } }");
|
||||
complete("setProperty");
|
||||
waitForAllAsyncStuff();
|
||||
checkResultWithInlays("class C { void m() { System.setProperty(<HINT text=\"key:\"/><caret>, <hint text=\"value:\"/>) } }");
|
||||
checkResultWithInlays("class C { void m() { System.setProperty(<HINT text=\"key:\"/><caret>, <Hint text=\"value:\"/>) } }");
|
||||
myFixture.type("System.getPro");
|
||||
complete("getProperty(String key, String def)");
|
||||
waitForAllAsyncStuff();
|
||||
checkResultWithInlays("class C { void m() { System.setProperty(<hint text=\"key:\"/>System.getProperty(<HINT text=\"key:\"/><caret>, <hint text=\"def:\"/>), <hint text=\"value:\"/>) } }");
|
||||
checkResultWithInlays("class C { void m() { System.setProperty(<hint text=\"key:\"/>System.getProperty(<HINT text=\"key:\"/><caret>, <Hint text=\"def:\"/>), <hint text=\"value:\"/>) } }");
|
||||
}
|
||||
|
||||
public void testTabWithNestedCompletion() throws Exception {
|
||||
@@ -225,16 +225,16 @@ public class CompletionHintsTest extends LightFixtureCompletionTestCase {
|
||||
myFixture.type("System.getPro");
|
||||
complete("getProperty(String key, String def)");
|
||||
waitForAllAsyncStuff();
|
||||
checkResultWithInlays("class C { void m() { System.setProperty(<hint text=\"key:\"/>System.getProperty(<HINT text=\"key:\"/><caret>, <hint text=\"def:\"/>), <hint text=\"value:\"/>) } }");
|
||||
checkResultWithInlays("class C { void m() { System.setProperty(<hint text=\"key:\"/>System.getProperty(<HINT text=\"key:\"/><caret>, <Hint text=\"def:\"/>), <hint text=\"value:\"/>) } }");
|
||||
next();
|
||||
waitForAllAsyncStuff();
|
||||
checkResultWithInlays("class C { void m() { System.setProperty(<hint text=\"key:\"/>System.getProperty(<hint text=\"key:\"/>, <HINT text=\"def:\"/><caret>), <hint text=\"value:\"/>) } }");
|
||||
checkResultWithInlays("class C { void m() { System.setProperty(<hint text=\"key:\"/>System.getProperty(<Hint text=\"key:\"/>, <HINT text=\"def:\"/><caret>), <hint text=\"value:\"/>) } }");
|
||||
next();
|
||||
waitForAllAsyncStuff();
|
||||
checkResultWithInlays("class C { void m() { System.setProperty(<HINT text=\"key:\"/>System.getProperty(<hint text=\"key:\"/>, <hint text=\"def:\"/>)<caret>, <hint text=\"value:\"/>) } }");
|
||||
checkResultWithInlays("class C { void m() { System.setProperty(<HINT text=\"key:\"/>System.getProperty(<hint text=\"key:\"/>, <hint text=\"def:\"/>)<caret>, <Hint text=\"value:\"/>) } }");
|
||||
next();
|
||||
waitForAllAsyncStuff();
|
||||
checkResultWithInlays("class C { void m() { System.setProperty(<hint text=\"key:\"/>System.getProperty(<hint text=\"key:\"/>, <hint text=\"def:\"/>), <HINT text=\"value:\"/><caret>) } }");
|
||||
checkResultWithInlays("class C { void m() { System.setProperty(<Hint text=\"key:\"/>System.getProperty(<hint text=\"key:\"/>, <hint text=\"def:\"/>), <HINT text=\"value:\"/><caret>) } }");
|
||||
next();
|
||||
waitForAllAsyncStuff();
|
||||
checkResultWithInlays("class C { void m() { System.setProperty(<hint text=\"key:\"/>System.getProperty(<hint text=\"key:\"/>, <hint text=\"def:\"/>), <hint text=\"value:\"/>)<caret> } }");
|
||||
@@ -249,7 +249,7 @@ public class CompletionHintsTest extends LightFixtureCompletionTestCase {
|
||||
public void testHintsDisappearWhenNumberOfParametersIsChangedDirectly() throws Exception {
|
||||
configureJava("class C { void m() { System.getPro<caret> } }");
|
||||
complete("getProperty(String key, String def)");
|
||||
checkResultWithInlays("class C { void m() { System.getProperty(<HINT text=\"key:\"/><caret>, <hint text=\"def:\"/>) } }");
|
||||
checkResultWithInlays("class C { void m() { System.getProperty(<HINT text=\"key:\"/><caret>, <Hint text=\"def:\"/>) } }");
|
||||
delete();
|
||||
waitForAllAsyncStuff();
|
||||
checkResultWithInlays("class C { void m() { System.getProperty(<caret> ) } }");
|
||||
@@ -258,7 +258,7 @@ public class CompletionHintsTest extends LightFixtureCompletionTestCase {
|
||||
public void testHintsDisappearWhenNumberOfParametersIsChangedDirectlyWithNoOverloads() throws Exception {
|
||||
configureJava("class C { void m() { Character.for<caret> } }");
|
||||
complete("forDigit");
|
||||
checkResultWithInlays("class C { void m() { Character.forDigit(<HINT text=\"digit:\"/><caret>, <hint text=\"radix:\"/>) } }");
|
||||
checkResultWithInlays("class C { void m() { Character.forDigit(<HINT text=\"digit:\"/><caret>, <Hint text=\"radix:\"/>) } }");
|
||||
delete();
|
||||
waitForAllAsyncStuff();
|
||||
checkResultWithInlays("class C { void m() { Character.forDigit(<caret> ) } }");
|
||||
@@ -270,7 +270,7 @@ public class CompletionHintsTest extends LightFixtureCompletionTestCase {
|
||||
type("new String().trim");
|
||||
myFixture.complete(CompletionType.SMART);
|
||||
waitForAllAsyncStuff();
|
||||
checkResultWithInlays("class C { void m() { System.setProperty(<hint text=\"key:\"/>new String().trim(), <HINT text=\"value:\"/><caret>) } }");
|
||||
checkResultWithInlays("class C { void m() { System.setProperty(<Hint text=\"key:\"/>new String().trim(), <HINT text=\"value:\"/><caret>) } }");
|
||||
}
|
||||
|
||||
public void testNoHintsDuplicationWhenTypingToTheLeftOfHint() throws Exception {
|
||||
@@ -281,7 +281,7 @@ public class CompletionHintsTest extends LightFixtureCompletionTestCase {
|
||||
right();
|
||||
type("2");
|
||||
waitForAllAsyncStuff();
|
||||
checkResultWithInlays("class C { void m() { Character.forDigit(<hint text=\"digit:\"/>1,<HINT text=\"radix:\"/>2<caret> ) } }");
|
||||
checkResultWithInlays("class C { void m() { Character.forDigit(<Hint text=\"digit:\"/>1,<HINT text=\"radix:\"/>2<caret> ) } }");
|
||||
myFixture.performEditorAction(IdeActions.ACTION_EDITOR_MOVE_LINE_END);
|
||||
waitForAllAsyncStuff();
|
||||
checkResultWithInlays("class C { void m() { Character.forDigit(<hint text=\"digit:\"/>1,<hint text=\"radix:\"/>2 ) } }<caret>");
|
||||
@@ -334,7 +334,7 @@ public class CompletionHintsTest extends LightFixtureCompletionTestCase {
|
||||
next();
|
||||
prev();
|
||||
waitForAllAsyncStuff();
|
||||
checkResultWithInlays("class C { void m() { System.getProperty(<hint text=\"key:\"/>, <HINT text=\"def:\"/><caret>) } }");
|
||||
checkResultWithInlays("class C { void m() { System.getProperty(<Hint text=\"key:\"/>, <HINT text=\"def:\"/><caret>) } }");
|
||||
}
|
||||
|
||||
public void testPrevParameterFromOutsideWhenParametersAreNotEmpty() throws Exception {
|
||||
@@ -346,26 +346,26 @@ public class CompletionHintsTest extends LightFixtureCompletionTestCase {
|
||||
next();
|
||||
prev();
|
||||
waitForAllAsyncStuff();
|
||||
checkResultWithInlays("class C { void m() { System.getProperty(<hint text=\"key:\"/>\"a\", <HINT text=\"def:\"/><caret>\"b\") } }");
|
||||
checkResultWithInlays("class C { void m() { System.getProperty(<Hint text=\"key:\"/>\"a\", <HINT text=\"def:\"/><caret>\"b\") } }");
|
||||
}
|
||||
|
||||
public void testVararg() throws Exception {
|
||||
configureJava("class C { void m() { String.for<caret> } }");
|
||||
complete();
|
||||
checkResultWithInlays("class C { void m() { String.format(<HINT text=\"format:\"/><caret><hint text=\", args:\"/>) } }");
|
||||
checkResultWithInlays("class C { void m() { String.format(<HINT text=\"format:\"/><caret><Hint text=\", args:\"/>) } }");
|
||||
type("\"a");
|
||||
next();
|
||||
waitForAllAsyncStuff();
|
||||
checkResultWithInlays("class C { void m() { String.format(<hint text=\"format:\"/>\"a\", <HINT text=\"args:\"/><caret>) } }");
|
||||
checkResultWithInlays("class C { void m() { String.format(<Hint text=\"format:\"/>\"a\", <HINT text=\"args:\"/><caret>) } }");
|
||||
next();
|
||||
waitForAllAsyncStuff();
|
||||
checkResultWithInlays("class C { void m() { String.format(<hint text=\"format:\"/>\"a\"<hint text=\", args:\"/>)<caret> } }");
|
||||
prev();
|
||||
waitForAllAsyncStuff();
|
||||
checkResultWithInlays("class C { void m() { String.format(<hint text=\"format:\"/>\"a\", <HINT text=\"args:\"/><caret>) } }");
|
||||
checkResultWithInlays("class C { void m() { String.format(<Hint text=\"format:\"/>\"a\", <HINT text=\"args:\"/><caret>) } }");
|
||||
prev();
|
||||
waitForAllAsyncStuff();
|
||||
checkResultWithInlays("class C { void m() { String.format(<HINT text=\"format:\"/>\"a\"<caret><hint text=\", args:\"/>) } }");
|
||||
checkResultWithInlays("class C { void m() { String.format(<HINT text=\"format:\"/>\"a\"<caret><Hint text=\", args:\"/>) } }");
|
||||
}
|
||||
|
||||
public void testVarargWithNoMandatoryArguments() throws Exception {
|
||||
@@ -377,7 +377,7 @@ public class CompletionHintsTest extends LightFixtureCompletionTestCase {
|
||||
type("1");
|
||||
next();
|
||||
waitForAllAsyncStuff();
|
||||
checkResultWithInlays("class C { int vararg(int... args){ return 0; } void m() { vararg(<hint text=\"args:\"/>1, <caret>) } }");
|
||||
checkResultWithInlays("class C { int vararg(int... args){ return 0; } void m() { vararg(<Hint text=\"args:\"/>1, <caret>) } }");
|
||||
checkHintContents("<html><b>int...</b></html>");
|
||||
next();
|
||||
waitForAllAsyncStuff();
|
||||
@@ -385,7 +385,7 @@ public class CompletionHintsTest extends LightFixtureCompletionTestCase {
|
||||
checkHintContents(null);
|
||||
prev();
|
||||
waitForAllAsyncStuff();
|
||||
checkResultWithInlays("class C { int vararg(int... args){ return 0; } void m() { vararg(<hint text=\"args:\"/>1, <caret>) } }");
|
||||
checkResultWithInlays("class C { int vararg(int... args){ return 0; } void m() { vararg(<Hint text=\"args:\"/>1, <caret>) } }");
|
||||
checkHintContents("<html><b>int...</b></html>");
|
||||
prev();
|
||||
waitForAllAsyncStuff();
|
||||
@@ -396,45 +396,45 @@ public class CompletionHintsTest extends LightFixtureCompletionTestCase {
|
||||
public void testVarargWithTwoMandatoryArguments() throws Exception {
|
||||
configureJava("class C { int vararg(int a, int b, int... args){ return 0; } void m() { varar<caret> } }");
|
||||
complete();
|
||||
checkResultWithInlays("class C { int vararg(int a, int b, int... args){ return 0; } void m() { vararg(<HINT text=\"a:\"/><caret>, <hint text=\"b:\"/><hint text=\", args:\"/>) } }");
|
||||
checkResultWithInlays("class C { int vararg(int a, int b, int... args){ return 0; } void m() { vararg(<HINT text=\"a:\"/><caret>, <Hint text=\"b:\"/><Hint text=\", args:\"/>) } }");
|
||||
type("1");
|
||||
next();
|
||||
waitForAllAsyncStuff();
|
||||
checkResultWithInlays("class C { int vararg(int a, int b, int... args){ return 0; } void m() { vararg(<hint text=\"a:\"/>1, <HINT text=\"b:\"/><caret><hint text=\", args:\"/>) } }");
|
||||
checkResultWithInlays("class C { int vararg(int a, int b, int... args){ return 0; } void m() { vararg(<Hint text=\"a:\"/>1, <HINT text=\"b:\"/><caret><Hint text=\", args:\"/>) } }");
|
||||
type("2");
|
||||
next();
|
||||
waitForAllAsyncStuff();
|
||||
checkResultWithInlays("class C { int vararg(int a, int b, int... args){ return 0; } void m() { vararg(<hint text=\"a:\"/>1, <hint text=\"b:\"/>2, <HINT text=\"args:\"/><caret>) } }");
|
||||
checkResultWithInlays("class C { int vararg(int a, int b, int... args){ return 0; } void m() { vararg(<Hint text=\"a:\"/>1, <Hint text=\"b:\"/>2, <HINT text=\"args:\"/><caret>) } }");
|
||||
next();
|
||||
waitForAllAsyncStuff();
|
||||
checkResultWithInlays("class C { int vararg(int a, int b, int... args){ return 0; } void m() { vararg(<hint text=\"a:\"/>1, <hint text=\"b:\"/>2<hint text=\", args:\"/>)<caret> } }");
|
||||
prev();
|
||||
waitForAllAsyncStuff();
|
||||
checkResultWithInlays("class C { int vararg(int a, int b, int... args){ return 0; } void m() { vararg(<hint text=\"a:\"/>1, <hint text=\"b:\"/>2, <HINT text=\"args:\"/><caret>) } }");
|
||||
checkResultWithInlays("class C { int vararg(int a, int b, int... args){ return 0; } void m() { vararg(<Hint text=\"a:\"/>1, <Hint text=\"b:\"/>2, <HINT text=\"args:\"/><caret>) } }");
|
||||
prev();
|
||||
waitForAllAsyncStuff();
|
||||
checkResultWithInlays("class C { int vararg(int a, int b, int... args){ return 0; } void m() { vararg(<hint text=\"a:\"/>1, <HINT text=\"b:\"/>2<caret><hint text=\", args:\"/>) } }");
|
||||
checkResultWithInlays("class C { int vararg(int a, int b, int... args){ return 0; } void m() { vararg(<Hint text=\"a:\"/>1, <HINT text=\"b:\"/>2<caret><Hint text=\", args:\"/>) } }");
|
||||
}
|
||||
|
||||
public void testVarargHintsDontSwitchPlaces() throws Exception {
|
||||
configureJava("class C { void m() { java.util.Collections.add<caret> } }");
|
||||
complete();
|
||||
checkResultWithInlays("class C { void m() { java.util.Collections.addAll(<HINT text=\"c:\"/><caret><hint text=\", elements:\"/>) } }");
|
||||
checkResultWithInlays("class C { void m() { java.util.Collections.addAll(<HINT text=\"c:\"/><caret><Hint text=\", elements:\"/>) } }");
|
||||
left();
|
||||
type('s');
|
||||
waitForAllAsyncStuff();
|
||||
checkResultWithInlays("class C { void m() { java.util.Collections.addAll(<HINT text=\"c:\"/>s<caret><hint text=\", elements:\"/>) } }");
|
||||
checkResultWithInlays("class C { void m() { java.util.Collections.addAll(<HINT text=\"c:\"/>s<caret><Hint text=\", elements:\"/>) } }");
|
||||
backspace();
|
||||
checkResultWithInlays("class C { void m() { java.util.Collections.addAll(<HINT text=\"c:\"/><caret><hint text=\", elements:\"/>) } }");
|
||||
checkResultWithInlays("class C { void m() { java.util.Collections.addAll(<HINT text=\"c:\"/><caret><Hint text=\", elements:\"/>) } }");
|
||||
waitForAllAsyncStuff();
|
||||
checkResultWithInlays("class C { void m() { java.util.Collections.addAll(<HINT text=\"c:\"/><caret><hint text=\", elements:\"/>) } }");
|
||||
checkResultWithInlays("class C { void m() { java.util.Collections.addAll(<HINT text=\"c:\"/><caret><Hint text=\", elements:\"/>) } }");
|
||||
}
|
||||
|
||||
public void testHintsDontDisappearWhenNavigatingAwayFromUncompletedInvocation() throws Exception {
|
||||
configureJava("class C { void m() { System.setPro<caret> } }");
|
||||
complete("setProperty");
|
||||
waitForAllAsyncStuff();
|
||||
checkResultWithInlays("class C { void m() { System.setProperty(<HINT text=\"key:\"/><caret>, <hint text=\"value:\"/>) } }");
|
||||
checkResultWithInlays("class C { void m() { System.setProperty(<HINT text=\"key:\"/><caret>, <Hint text=\"value:\"/>) } }");
|
||||
home();
|
||||
type(' ');
|
||||
waitForAllAsyncStuff();
|
||||
@@ -465,7 +465,7 @@ public class CompletionHintsTest extends LightFixtureCompletionTestCase {
|
||||
"}\n" +
|
||||
"class C extends P {\n" +
|
||||
" void method(int a, int b) {\n" +
|
||||
" super.method(<HINT text=\"a:\"/><caret>, <hint text=\"b:\"/>);\n" +
|
||||
" super.method(<HINT text=\"a:\"/><caret>, <Hint text=\"b:\"/>);\n" +
|
||||
" }\n" +
|
||||
"}");
|
||||
complete("a, b");
|
||||
@@ -489,26 +489,26 @@ public class CompletionHintsTest extends LightFixtureCompletionTestCase {
|
||||
// check hints appearance on completion
|
||||
configureJava("class C { void m() { Character.for<caret> } }");
|
||||
complete("forDigit");
|
||||
checkResultWithInlays("class C { void m() { Character.forDigit(<HINT text=\"digit:\"/><caret>, <hint text=\"radix:\"/>) } }");
|
||||
checkResultWithInlays("class C { void m() { Character.forDigit(<HINT text=\"digit:\"/><caret>, <Hint text=\"radix:\"/>) } }");
|
||||
|
||||
// check that hints don't disappear after daemon highlighting passes
|
||||
waitForAllAsyncStuff();
|
||||
checkResultWithInlays("class C { void m() { Character.forDigit(<HINT text=\"digit:\"/><caret>, <hint text=\"radix:\"/>) } }");
|
||||
checkResultWithInlays("class C { void m() { Character.forDigit(<HINT text=\"digit:\"/><caret>, <Hint text=\"radix:\"/>) } }");
|
||||
|
||||
// test Tab/Shift+Tab navigation
|
||||
next();
|
||||
waitForAllAsyncStuff();
|
||||
checkResultWithInlays("class C { void m() { Character.forDigit(<hint text=\"digit:\"/>, <HINT text=\"radix:\"/><caret>) } }");
|
||||
checkResultWithInlays("class C { void m() { Character.forDigit(<Hint text=\"digit:\"/>, <HINT text=\"radix:\"/><caret>) } }");
|
||||
prev();
|
||||
waitForAllAsyncStuff();
|
||||
checkResultWithInlays("class C { void m() { Character.forDigit(<HINT text=\"digit:\"/><caret>, <hint text=\"radix:\"/>) } }");
|
||||
checkResultWithInlays("class C { void m() { Character.forDigit(<HINT text=\"digit:\"/><caret>, <Hint text=\"radix:\"/>) } }");
|
||||
|
||||
// test hints remain shown while entering parameter values
|
||||
myFixture.type("1");
|
||||
next();
|
||||
myFixture.type("2");
|
||||
waitForAllAsyncStuff();
|
||||
checkResultWithInlays("class C { void m() { Character.forDigit(<hint text=\"digit:\"/>1, <HINT text=\"radix:\"/>2<caret>) } }");
|
||||
checkResultWithInlays("class C { void m() { Character.forDigit(<Hint text=\"digit:\"/>1, <HINT text=\"radix:\"/>2<caret>) } }");
|
||||
|
||||
// test hints disappear when caret moves out of parameter list
|
||||
right();
|
||||
@@ -531,7 +531,7 @@ public class CompletionHintsTest extends LightFixtureCompletionTestCase {
|
||||
complete();
|
||||
checkResultWithInlays("class C {\n" +
|
||||
" void mmm(int a, int b, int c, int d, int e, int f) {}\n" +
|
||||
" void m2() { mmm(<HINT text=\"a:\"/><caret>, <hint text=\"b:\"/>, <hint text=\"c:\"/>, <hint text=\"d:\"/>, <hint text=\"e:\"/>, <hint text=\"f:\"/>); }\n" +
|
||||
" void m2() { mmm(<HINT text=\"a:\"/><caret>, <Hint text=\"b:\"/>, <Hint text=\"c:\"/>, <Hint text=\"d:\"/>, <Hint text=\"e:\"/>, <Hint text=\"f:\"/>); }\n" +
|
||||
"}");
|
||||
}
|
||||
|
||||
@@ -542,27 +542,27 @@ public class CompletionHintsTest extends LightFixtureCompletionTestCase {
|
||||
myFixture.type("System.getPro");
|
||||
complete("getProperty(String key, String def)");
|
||||
waitForAllAsyncStuff();
|
||||
checkResultWithInlays("class C { void m() { System.setProperty(<hint text=\"key:\"/>System.getProperty(<HINT text=\"key:\"/><caret>, <hint text=\"def:\"/>), <hint text=\"value:\"/>) } }");
|
||||
checkResultWithInlays("class C { void m() { System.setProperty(<hint text=\"key:\"/>System.getProperty(<HINT text=\"key:\"/><caret>, <Hint text=\"def:\"/>), <hint text=\"value:\"/>) } }");
|
||||
next();
|
||||
waitForAllAsyncStuff();
|
||||
checkResultWithInlays("class C { void m() { System.setProperty(<hint text=\"key:\"/>System.getProperty(<hint text=\"key:\"/>, <HINT text=\"def:\"/><caret>), <hint text=\"value:\"/>) } }");
|
||||
checkResultWithInlays("class C { void m() { System.setProperty(<hint text=\"key:\"/>System.getProperty(<Hint text=\"key:\"/>, <HINT text=\"def:\"/><caret>), <hint text=\"value:\"/>) } }");
|
||||
next();
|
||||
waitForAllAsyncStuff();
|
||||
checkResultWithInlays("class C { void m() { System.setProperty(<HINT text=\"key:\"/>System.getProperty(<hint text=\"key:\"/>, <hint text=\"def:\"/>)<caret>, <hint text=\"value:\"/>) } }");
|
||||
checkResultWithInlays("class C { void m() { System.setProperty(<HINT text=\"key:\"/>System.getProperty(<hint text=\"key:\"/>, <hint text=\"def:\"/>)<caret>, <Hint text=\"value:\"/>) } }");
|
||||
left();
|
||||
waitForAllAsyncStuff();
|
||||
checkResultWithInlays("class C { void m() { System.setProperty(<hint text=\"key:\"/>System.getProperty(<hint text=\"key:\"/>, <HINT text=\"def:\"/><caret>), <hint text=\"value:\"/>) } }");
|
||||
checkResultWithInlays("class C { void m() { System.setProperty(<hint text=\"key:\"/>System.getProperty(<Hint text=\"key:\"/>, <HINT text=\"def:\"/><caret>), <hint text=\"value:\"/>) } }");
|
||||
}
|
||||
|
||||
public void testHintPopupContentsForMethodWithOverloads() throws Exception {
|
||||
configureJava("class C { void m() { System.getPro<caret> } }");
|
||||
complete("getProperty(String key, String def)");
|
||||
waitForAllAsyncStuff();
|
||||
checkResultWithInlays("class C { void m() { System.getProperty(<HINT text=\"key:\"/><caret>, <hint text=\"def:\"/>) } }");
|
||||
checkResultWithInlays("class C { void m() { System.getProperty(<HINT text=\"key:\"/><caret>, <Hint text=\"def:\"/>) } }");
|
||||
checkHintContents("<html><b>@NotNull String</b> <i>the name of the system property. </i></html>");
|
||||
next();
|
||||
waitForAllAsyncStuff();
|
||||
checkResultWithInlays("class C { void m() { System.getProperty(<hint text=\"key:\"/>, <HINT text=\"def:\"/><caret>) } }");
|
||||
checkResultWithInlays("class C { void m() { System.getProperty(<Hint text=\"key:\"/>, <HINT text=\"def:\"/><caret>) } }");
|
||||
checkHintContents("<html><b>String</b> <i>a default value. </i></html>");
|
||||
showParameterInfo();
|
||||
waitForAllAsyncStuff();
|
||||
@@ -575,11 +575,11 @@ public class CompletionHintsTest extends LightFixtureCompletionTestCase {
|
||||
configureJava("class C { void m() { System.setPro<caret> } }");
|
||||
complete("setProperty");
|
||||
waitForAllAsyncStuff();
|
||||
checkResultWithInlays("class C { void m() { System.setProperty(<HINT text=\"key:\"/><caret>, <hint text=\"value:\"/>) } }");
|
||||
checkResultWithInlays("class C { void m() { System.setProperty(<HINT text=\"key:\"/><caret>, <Hint text=\"value:\"/>) } }");
|
||||
checkHintContents("<html><b>@NotNull String</b> <i>the name of the system property. </i></html>");
|
||||
next();
|
||||
waitForAllAsyncStuff();
|
||||
checkResultWithInlays("class C { void m() { System.setProperty(<hint text=\"key:\"/>, <HINT text=\"value:\"/><caret>) } }");
|
||||
checkResultWithInlays("class C { void m() { System.setProperty(<Hint text=\"key:\"/>, <HINT text=\"value:\"/><caret>) } }");
|
||||
checkHintContents("<html><b>String</b> <i>the value of the system property. </i></html>");
|
||||
showParameterInfo();
|
||||
waitForAllAsyncStuff();
|
||||
@@ -651,14 +651,14 @@ public class CompletionHintsTest extends LightFixtureCompletionTestCase {
|
||||
checkResultWithInlays("class C {\n" +
|
||||
" void a(int p, int q) {}\n" +
|
||||
" void a(int p, int q, int r) {}\n" +
|
||||
" void m() { a(<HINT text=\"p:\"/><caret>, <hint text=\"q:\"/>) }\n" +
|
||||
" void m() { a(<HINT text=\"p:\"/><caret>, <Hint text=\"q:\"/>) }\n" +
|
||||
"}");
|
||||
next();
|
||||
waitForAllAsyncStuff();
|
||||
checkResultWithInlays("class C {\n" +
|
||||
" void a(int p, int q) {}\n" +
|
||||
" void a(int p, int q, int r) {}\n" +
|
||||
" void m() { a(<hint text=\"p:\"/>, <HINT text=\"q:\"/><caret>) }\n" +
|
||||
" void m() { a(<Hint text=\"p:\"/>, <HINT text=\"q:\"/><caret>) }\n" +
|
||||
"}");
|
||||
}
|
||||
|
||||
@@ -712,7 +712,7 @@ public class CompletionHintsTest extends LightFixtureCompletionTestCase {
|
||||
assertEquals("local", myFixture.getLookupElements()[0].getLookupString());
|
||||
myFixture.performEditorAction(IdeActions.ACTION_CHOOSE_LOOKUP_ITEM_REPLACE);
|
||||
waitForAllAsyncStuff();
|
||||
checkResultWithInlays("class C { void m() { String local = \"a\"; String local2 = \"b\"; System.getProperty(<hint text=\"key:\"/>local, <HINT text=\"def:\"/><caret>) } }");
|
||||
checkResultWithInlays("class C { void m() { String local = \"a\"; String local2 = \"b\"; System.getProperty(<Hint text=\"key:\"/>local, <HINT text=\"def:\"/><caret>) } }");
|
||||
}
|
||||
|
||||
public void testGenericType() throws Exception {
|
||||
@@ -725,19 +725,19 @@ public class CompletionHintsTest extends LightFixtureCompletionTestCase {
|
||||
public void testCompletionBetweenVarargHints() {
|
||||
configureJava("class C { int myVal = 1; void vararg(int a, int... b) {} void m() { varar<caret> } }");
|
||||
complete();
|
||||
checkResultWithInlays("class C { int myVal = 1; void vararg(int a, int... b) {} void m() { vararg(<HINT text=\"a:\"/><caret><hint text=\", b:\"/>); } }");
|
||||
checkResultWithInlays("class C { int myVal = 1; void vararg(int a, int... b) {} void m() { vararg(<HINT text=\"a:\"/><caret><Hint text=\", b:\"/>); } }");
|
||||
type("myVa");
|
||||
complete();
|
||||
checkResultWithInlays("class C { int myVal = 1; void vararg(int a, int... b) {} void m() { vararg(<HINT text=\"a:\"/>myVal<caret><hint text=\", b:\"/>); } }");
|
||||
checkResultWithInlays("class C { int myVal = 1; void vararg(int a, int... b) {} void m() { vararg(<HINT text=\"a:\"/>myVal<caret><Hint text=\", b:\"/>); } }");
|
||||
}
|
||||
|
||||
public void testEnteringSpaceBetweenVarargHints() throws Exception {
|
||||
configureJava("class C { void vararg(Object a, int... b) {} void m() { varar<caret> } }");
|
||||
complete();
|
||||
checkResultWithInlays("class C { void vararg(Object a, int... b) {} void m() { vararg(<HINT text=\"a:\"/><caret><hint text=\", b:\"/>); } }");
|
||||
checkResultWithInlays("class C { void vararg(Object a, int... b) {} void m() { vararg(<HINT text=\"a:\"/><caret><Hint text=\", b:\"/>); } }");
|
||||
type("new ");
|
||||
waitForAllAsyncStuff();
|
||||
checkResultWithInlays("class C { void vararg(Object a, int... b) {} void m() { vararg(<HINT text=\"a:\"/>new <caret><hint text=\", b:\"/>); } }");
|
||||
checkResultWithInlays("class C { void vararg(Object a, int... b) {} void m() { vararg(<HINT text=\"a:\"/>new <caret><Hint text=\", b:\"/>); } }");
|
||||
}
|
||||
|
||||
public void testNoTooltipForInvalidParameter() throws Exception {
|
||||
@@ -788,7 +788,7 @@ public class CompletionHintsTest extends LightFixtureCompletionTestCase {
|
||||
public void testNoLinksInParameterJavadoc() throws Exception {
|
||||
configureJava("class C { void m() { String.for<caret> } }");
|
||||
complete();
|
||||
checkResultWithInlays("class C { void m() { String.format(<HINT text=\"format:\"/><caret><hint text=\", args:\"/>) } }");
|
||||
checkResultWithInlays("class C { void m() { String.format(<HINT text=\"format:\"/><caret><Hint text=\", args:\"/>) } }");
|
||||
waitForAllAsyncStuff();
|
||||
checkHintContents("<html><b>String</b> <i> A format string </i></html>");
|
||||
}
|
||||
@@ -799,25 +799,25 @@ public class CompletionHintsTest extends LightFixtureCompletionTestCase {
|
||||
// check hints appearance on completion
|
||||
configureJava("class C { C(int a, int b) {} void m() { new C<caret> } }");
|
||||
complete("C(int a, int b)");
|
||||
checkResultWithInlays("class C { C(int a, int b) {} void m() { new C(<HINT text=\"a:\"/><caret>, <hint text=\"b:\"/>) } }");
|
||||
checkResultWithInlays("class C { C(int a, int b) {} void m() { new C(<HINT text=\"a:\"/><caret>, <Hint text=\"b:\"/>) } }");
|
||||
// check that hints don't disappear after daemon highlighting passes
|
||||
waitForAllAsyncStuff();
|
||||
checkResultWithInlays("class C { C(int a, int b) {} void m() { new C(<HINT text=\"a:\"/><caret>, <hint text=\"b:\"/>) } }");
|
||||
checkResultWithInlays("class C { C(int a, int b) {} void m() { new C(<HINT text=\"a:\"/><caret>, <Hint text=\"b:\"/>) } }");
|
||||
|
||||
// test Tab/Shift+Tab navigation
|
||||
next();
|
||||
waitForAllAsyncStuff();
|
||||
checkResultWithInlays("class C { C(int a, int b) {} void m() { new C(<hint text=\"a:\"/>, <HINT text=\"b:\"/><caret>) } }");
|
||||
checkResultWithInlays("class C { C(int a, int b) {} void m() { new C(<Hint text=\"a:\"/>, <HINT text=\"b:\"/><caret>) } }");
|
||||
prev();
|
||||
waitForAllAsyncStuff();
|
||||
checkResultWithInlays("class C { C(int a, int b) {} void m() { new C(<HINT text=\"a:\"/><caret>, <hint text=\"b:\"/>) } }");
|
||||
checkResultWithInlays("class C { C(int a, int b) {} void m() { new C(<HINT text=\"a:\"/><caret>, <Hint text=\"b:\"/>) } }");
|
||||
|
||||
// test hints remain shown while entering parameter values
|
||||
myFixture.type("1");
|
||||
next();
|
||||
myFixture.type("2");
|
||||
waitForAllAsyncStuff();
|
||||
checkResultWithInlays("class C { C(int a, int b) {} void m() { new C(<hint text=\"a:\"/>1, <HINT text=\"b:\"/>2<caret>) } }");
|
||||
checkResultWithInlays("class C { C(int a, int b) {} void m() { new C(<Hint text=\"a:\"/>1, <HINT text=\"b:\"/>2<caret>) } }");
|
||||
|
||||
// test hints don't disappear when caret moves out of parameter list
|
||||
right();
|
||||
|
||||
+2
-13
@@ -1,17 +1,5 @@
|
||||
/*
|
||||
* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
*/
|
||||
package com.intellij.application.options.colors.highlighting;
|
||||
|
||||
@@ -58,6 +46,7 @@ public class InlineElementData extends HighlightData {
|
||||
Inlay hint = hintsPresentationManager.addHint(view, offset, false, myText, false);
|
||||
hintsPresentationManager.setHighlighted(hint,
|
||||
DefaultLanguageHighlighterColors.INLINE_PARAMETER_HINT_HIGHLIGHTED.equals(getHighlightKey()));
|
||||
hintsPresentationManager.setCurrent(hint, myText.contains("current"));
|
||||
List<Inlay> inlays = view.getInlayModel().getInlineElementsInRange(offset, offset);
|
||||
for (Inlay inlay : inlays) {
|
||||
EditorCustomElementRenderer renderer = inlay.getRenderer();
|
||||
|
||||
+25
-1
@@ -98,6 +98,22 @@ public class ParameterHintsPresentationManager implements Disposable {
|
||||
return renderer.highlighted;
|
||||
}
|
||||
|
||||
public void setCurrent(@NotNull Inlay hint, boolean current) {
|
||||
if (!isParameterHint(hint)) throw new IllegalArgumentException("Not a parameter hint");
|
||||
MyRenderer renderer = (MyRenderer)hint.getRenderer();
|
||||
boolean oldValue = renderer.current;
|
||||
if (current != oldValue) {
|
||||
renderer.current = current;
|
||||
hint.repaint();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isCurrent(@NotNull Inlay hint) {
|
||||
if (!isParameterHint(hint)) throw new IllegalArgumentException("Not a parameter hint");
|
||||
MyRenderer renderer = (MyRenderer)hint.getRenderer();
|
||||
return renderer.current;
|
||||
}
|
||||
|
||||
private void updateRenderer(@NotNull Editor editor, @NotNull Inlay hint, @Nullable String newText) {
|
||||
MyRenderer renderer = (MyRenderer)hint.getRenderer();
|
||||
renderer.update(editor, newText, true);
|
||||
@@ -186,6 +202,7 @@ public class ParameterHintsPresentationManager implements Disposable {
|
||||
private int steps;
|
||||
private int step;
|
||||
private boolean highlighted;
|
||||
private boolean current;
|
||||
|
||||
private MyRenderer(Editor editor, String text, boolean animated) {
|
||||
updateState(editor, text, animated);
|
||||
@@ -241,12 +258,12 @@ public class ParameterHintsPresentationManager implements Disposable {
|
||||
: DefaultLanguageHighlighterColors.INLINE_PARAMETER_HINT);
|
||||
if (attributes != null) {
|
||||
MyFontMetrics fontMetrics = getFontMetrics(editor);
|
||||
int gap = r.height < (fontMetrics.lineHeight + 2) ? 1 : 2;
|
||||
Color backgroundColor = attributes.getBackgroundColor();
|
||||
if (backgroundColor != null) {
|
||||
GraphicsConfig config = GraphicsUtil.setupAAPainting(g);
|
||||
GraphicsUtil.paintWithAlpha(g, BACKGROUND_ALPHA);
|
||||
g.setColor(backgroundColor);
|
||||
int gap = r.height < (fontMetrics.lineHeight + 2) ? 1 : 2;
|
||||
g.fillRoundRect(r.x + 2, r.y + gap, r.width - 4, r.height - gap * 2, 8, 8);
|
||||
config.restore();
|
||||
}
|
||||
@@ -264,6 +281,13 @@ public class ParameterHintsPresentationManager implements Disposable {
|
||||
|
||||
g.setClip(savedClip);
|
||||
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, savedHint);
|
||||
|
||||
if (current) {
|
||||
savedHint = g2d.getRenderingHint(RenderingHints.KEY_ANTIALIASING);
|
||||
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
g.drawRoundRect(r.x + 2, r.y + gap, r.width - 4, r.height - gap * 2, 8, 8);
|
||||
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, savedHint);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
-14
@@ -1,17 +1,5 @@
|
||||
/*
|
||||
* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
*/
|
||||
package com.intellij.openapi.options.colors.pages;
|
||||
|
||||
@@ -225,8 +213,9 @@ public class DefaultLanguageColorsPage implements RainbowColorSettingsPage, Disp
|
||||
"Function <func_decl>declaration</func_decl> (<param>parameter1</param> <param>parameter2</param> <param>parameter3</param> <param>parameter4</param>)\n" +
|
||||
" Local <local_var>variable1</local_var> <local_var>variable2</local_var> <local_var>variable3</local_var> <local_var>variable4</local_var>\n" +
|
||||
"Function <func_call>call</func_call>(" +
|
||||
"<parameter_hint p>0, <parameter_hint_highlighted param>1, <parameter_hint parameterName>2" +
|
||||
"<parameter_hint p:>0, <parameter_hint param:>1, <parameter_hint parameterName:>2" +
|
||||
")\n" +
|
||||
"Current function <func_call>call</func_call>(<parameter_hint_highlighted param:>0, <parameter_hint_highlighted currentParam:>1)\n" +
|
||||
"Interface <interface>Name</interface>\n" +
|
||||
"<metadata>@Metadata</metadata>\n" +
|
||||
"Class <class_name>Name</class_name>\n" +
|
||||
|
||||
+21
-24
@@ -1,17 +1,5 @@
|
||||
/*
|
||||
* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
*/
|
||||
package com.intellij.testFramework.utils.inlays
|
||||
|
||||
@@ -36,7 +24,7 @@ class InlayHintsChecker(private val myFixture: CodeInsightTestFixture) {
|
||||
private var isParamHintsEnabledBefore = false
|
||||
|
||||
companion object {
|
||||
val pattern: Pattern = Pattern.compile("(<caret>)|(<selection>)|(</selection>)|<(hint|HINT)\\s+text=\"([^\"\n\r]+)\"\\s*/>")
|
||||
val pattern: Pattern = Pattern.compile("(<caret>)|(<selection>)|(</selection>)|<(hint|HINT|Hint|hINT)\\s+text=\"([^\"\n\r]+)\"\\s*/>")
|
||||
|
||||
private val default = ParameterNameHintsSettings()
|
||||
}
|
||||
@@ -66,20 +54,27 @@ class InlayHintsChecker(private val myFixture: CodeInsightTestFixture) {
|
||||
fun verifyInlaysAndCaretInfo(expectedInlaysAndCaret: CaretAndInlaysInfo, originalText: String) {
|
||||
val file = myFixture.file
|
||||
val document = myFixture.getDocument(file)
|
||||
val actual: List<Triple<Int, String, Boolean>> = getActualInlays()
|
||||
val actual: List<ParamHintInfo> = getActualInlays()
|
||||
|
||||
val expected = expectedInlaysAndCaret.inlays
|
||||
|
||||
if (expectedInlaysAndCaret.inlays.size != actual.size || actual.zip(expected).any { it.first != it.second }) {
|
||||
val entries: MutableList<Pair<Int, String>> = mutableListOf()
|
||||
actual.forEach { entries.add(Pair(it.first, "<${if(it.third) "HINT" else "hint"} text=\"${it.second}\" />")) }
|
||||
actual.forEach { entries.add(Pair(it.offset, buildString {
|
||||
append("<")
|
||||
append((if (it.highlighted) "H" else "h"))
|
||||
append((if (it.current) "INT" else "int"))
|
||||
append(" text=\"")
|
||||
append(it.text)
|
||||
append("\"/>")
|
||||
}))}
|
||||
if (expectedInlaysAndCaret.caretOffset != null) {
|
||||
val actualCaretOffset = myFixture.editor.caretModel.offset
|
||||
val actualInlaysBeforeCaret = myFixture.editor.caretModel.visualPosition.column -
|
||||
myFixture.editor.offsetToVisualPosition(actualCaretOffset).column
|
||||
val first = entries.indexOfFirst { it.first == actualCaretOffset }
|
||||
val insertIndex = if (first == -1) -entries.binarySearch { it.first - actualCaretOffset } - 1
|
||||
else first + actualInlaysBeforeCaret;
|
||||
else first + actualInlaysBeforeCaret
|
||||
entries.add(insertIndex, Pair(actualCaretOffset, "<caret>"))
|
||||
}
|
||||
val proposedText = StringBuilder(document.text)
|
||||
@@ -104,22 +99,22 @@ class InlayHintsChecker(private val myFixture: CodeInsightTestFixture) {
|
||||
}
|
||||
}
|
||||
|
||||
private fun getActualInlays(): List<Triple<Int, String, Boolean>> {
|
||||
private fun getActualInlays(): List<ParamHintInfo> {
|
||||
val editor = myFixture.editor
|
||||
val allInlays = editor.inlayModel.getInlineElementsInRange(0, editor.document.textLength)
|
||||
|
||||
val hintManager = ParameterHintsPresentationManager.getInstance()
|
||||
return allInlays
|
||||
.filter { hintManager.isParameterHint(it) }
|
||||
.map { Triple(it.offset, hintManager.getHintText(it), hintManager.isHighlighted(it))}
|
||||
.sortedBy { it.first }
|
||||
.map { ParamHintInfo(it.offset, hintManager.getHintText(it), hintManager.isHighlighted(it), hintManager.isCurrent(it))}
|
||||
.sortedBy { it.offset }
|
||||
}
|
||||
|
||||
fun extractInlaysAndCaretInfo(document: Document): CaretAndInlaysInfo {
|
||||
val text = document.text
|
||||
val matcher = pattern.matcher(text)
|
||||
|
||||
val inlays = mutableListOf<Triple<Int, String, Boolean>>()
|
||||
val inlays = mutableListOf<ParamHintInfo>()
|
||||
var extractedLength = 0
|
||||
var caretOffset : Int? = null
|
||||
var inlaysBeforeCaret = 0
|
||||
@@ -134,7 +129,7 @@ class InlayHintsChecker(private val myFixture: CodeInsightTestFixture) {
|
||||
if (matcher.group(1) != null) {
|
||||
caretOffset = realStartOffset
|
||||
inlays.asReversed()
|
||||
.takeWhile { it.first == caretOffset }
|
||||
.takeWhile { it.offset == caretOffset }
|
||||
.forEach { inlaysBeforeCaret++ }
|
||||
}
|
||||
else if (matcher.group(2) != null) {
|
||||
@@ -144,7 +139,7 @@ class InlayHintsChecker(private val myFixture: CodeInsightTestFixture) {
|
||||
selectionEnd = realStartOffset
|
||||
}
|
||||
else {
|
||||
inlays += Triple(realStartOffset, matcher.group(5), matcher.group(4) == "HINT")
|
||||
inlays += ParamHintInfo(realStartOffset, matcher.group(5), matcher.group(4).startsWith("H"), matcher.group(4).endsWith("INT"))
|
||||
}
|
||||
|
||||
removeText(document, realStartOffset, matchedLength)
|
||||
@@ -166,4 +161,6 @@ class InlayHintsChecker(private val myFixture: CodeInsightTestFixture) {
|
||||
}
|
||||
|
||||
class CaretAndInlaysInfo (val caretOffset: Int?, val inlaysBeforeCaret: Int, val selection: TextRange?,
|
||||
val inlays: List<Triple<Int, String, Boolean>>)
|
||||
val inlays: List<ParamHintInfo>)
|
||||
|
||||
data class ParamHintInfo (val offset: Int, val text: String, val highlighted: Boolean, val current: Boolean)
|
||||
Reference in New Issue
Block a user