KT-18040: Enable auto popup when typing after $e. in string template
#KT-18040 fixed
This commit is contained in:
+36
@@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.idea.completion.confidence
|
||||||
|
|
||||||
|
import com.intellij.codeInsight.completion.CompletionConfidence
|
||||||
|
import com.intellij.openapi.util.TextRange
|
||||||
|
import com.intellij.psi.PsiElement
|
||||||
|
import com.intellij.psi.PsiFile
|
||||||
|
import com.intellij.util.ThreeState
|
||||||
|
import org.jetbrains.kotlin.psi.KtSimpleNameStringTemplateEntry
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.prevLeaf
|
||||||
|
|
||||||
|
class EnableAutopopupInStringTemplate : CompletionConfidence() {
|
||||||
|
override fun shouldSkipAutopopup(contextElement: PsiElement, psiFile: PsiFile, offset: Int): ThreeState {
|
||||||
|
val stringTemplate = contextElement.prevLeaf()?.getParentOfType<KtSimpleNameStringTemplateEntry>(strict = false) ?: return ThreeState.UNSURE
|
||||||
|
val textRange = TextRange.create(stringTemplate.endOffset, offset)
|
||||||
|
val containsWhitespaces = textRange.substring(psiFile.text).any { it.isWhitespace() }
|
||||||
|
return if (containsWhitespaces) ThreeState.UNSURE else ThreeState.NO
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
class Bar {
|
||||||
|
val aa = "Some"
|
||||||
|
}
|
||||||
|
|
||||||
|
fun foo() {
|
||||||
|
val bar = Bar()
|
||||||
|
val y = "$bar.<caret>"
|
||||||
|
}
|
||||||
|
|
||||||
|
// ELEMENT: aa
|
||||||
+11
@@ -0,0 +1,11 @@
|
|||||||
|
class Bar {
|
||||||
|
val aa = "Some"
|
||||||
|
}
|
||||||
|
|
||||||
|
fun foo() {
|
||||||
|
val bar = Bar()
|
||||||
|
val y = """$bar.
|
||||||
|
a<caret>"""
|
||||||
|
}
|
||||||
|
|
||||||
|
// NO_LOOKUP
|
||||||
@@ -2,3 +2,4 @@ fun test() {
|
|||||||
"a<caret>"
|
"a<caret>"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NO_LOOKUP
|
||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
class Bar {
|
||||||
|
val aa = "Some"
|
||||||
|
}
|
||||||
|
|
||||||
|
fun foo() {
|
||||||
|
val bar = Bar()
|
||||||
|
val y = "$bar. a<caret>"
|
||||||
|
}
|
||||||
|
|
||||||
|
// NO_LOOKUP
|
||||||
+37
-9
@@ -20,10 +20,13 @@ import com.intellij.codeInsight.CodeInsightSettings;
|
|||||||
import com.intellij.codeInsight.completion.CodeCompletionHandlerBase;
|
import com.intellij.codeInsight.completion.CodeCompletionHandlerBase;
|
||||||
import com.intellij.codeInsight.completion.CompletionType;
|
import com.intellij.codeInsight.completion.CompletionType;
|
||||||
import com.intellij.codeInsight.completion.LightCompletionTestCase;
|
import com.intellij.codeInsight.completion.LightCompletionTestCase;
|
||||||
|
import com.intellij.codeInsight.lookup.LookupElement;
|
||||||
|
import com.intellij.codeInsight.lookup.LookupManager;
|
||||||
import com.intellij.codeInsight.lookup.impl.LookupImpl;
|
import com.intellij.codeInsight.lookup.impl.LookupImpl;
|
||||||
import com.intellij.openapi.projectRoots.JavaSdk;
|
import com.intellij.openapi.projectRoots.JavaSdk;
|
||||||
import com.intellij.openapi.projectRoots.Sdk;
|
import com.intellij.openapi.projectRoots.Sdk;
|
||||||
import com.intellij.openapi.util.text.StringUtil;
|
import com.intellij.openapi.util.text.StringUtil;
|
||||||
|
import com.intellij.util.ArrayUtil;
|
||||||
import org.apache.commons.lang.SystemUtils;
|
import org.apache.commons.lang.SystemUtils;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.kotlin.idea.completion.test.CompletionTestUtilKt;
|
import org.jetbrains.kotlin.idea.completion.test.CompletionTestUtilKt;
|
||||||
@@ -32,6 +35,7 @@ import org.jetbrains.kotlin.idea.test.TestUtilsKt;
|
|||||||
import org.jetbrains.kotlin.test.InTextDirectivesUtils;
|
import org.jetbrains.kotlin.test.InTextDirectivesUtils;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class KotlinConfidenceTest extends LightCompletionTestCase {
|
public class KotlinConfidenceTest extends LightCompletionTestCase {
|
||||||
private static final String TYPE_DIRECTIVE_PREFIX = "// TYPE:";
|
private static final String TYPE_DIRECTIVE_PREFIX = "// TYPE:";
|
||||||
@@ -60,6 +64,18 @@ public class KotlinConfidenceTest extends LightCompletionTestCase {
|
|||||||
doTest();
|
doTest();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testAutoPopupInStringTemplate() {
|
||||||
|
doTest();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testNoAutoPopupInStringTemplateAfterSpace() {
|
||||||
|
doTest();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testNoAutoPopupInRawStringTemplateAfterNewLine() {
|
||||||
|
doTest();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void setUp() throws Exception {
|
protected void setUp() throws Exception {
|
||||||
super.setUp();
|
super.setUp();
|
||||||
@@ -83,23 +99,31 @@ public class KotlinConfidenceTest extends LightCompletionTestCase {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
configureByFile(getBeforeFileName());
|
configureByFile(getBeforeFileName());
|
||||||
String typeText = getTypeTextFromFile();
|
String text = getEditor().getDocument().getText();
|
||||||
if (typeText != null) {
|
String typeText = getTypeText(text);
|
||||||
type(typeText);
|
List<String> expectedElements = InTextDirectivesUtils.findLinesWithPrefixesRemoved(text, "// ELEMENT:");
|
||||||
checkResultByFile(getAfterFileName());
|
boolean noLookup = InTextDirectivesUtils.isDirectiveDefined(text, "// NO_LOOKUP");
|
||||||
|
|
||||||
|
assertFalse("Can't both expect lookup elements and no lookup", !expectedElements.isEmpty() && noLookup);
|
||||||
|
|
||||||
|
if (noLookup) {
|
||||||
|
assertNull("Expected no lookup", getLookup());
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
else {
|
else if (!expectedElements.isEmpty()) {
|
||||||
LookupImpl lookup = getLookup();
|
assertContainsItems(ArrayUtil.toStringArray(expectedElements));
|
||||||
assertNull("No completion auto-popup expected", lookup);
|
return;
|
||||||
}
|
}
|
||||||
|
assertNotNull("You must type something, use // TYPE:", typeText);
|
||||||
|
type(typeText);
|
||||||
|
checkResultByFile(getAfterFileName());
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
CodeInsightSettings.getInstance().SELECT_AUTOPOPUP_SUGGESTIONS_BY_CHARS = completeByChars;
|
CodeInsightSettings.getInstance().SELECT_AUTOPOPUP_SUGGESTIONS_BY_CHARS = completeByChars;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static String getTypeTextFromFile() {
|
protected static String getTypeText(String text) {
|
||||||
String text = getEditor().getDocument().getText();
|
|
||||||
|
|
||||||
String[] directives = InTextDirectivesUtils.findArrayWithPrefixes(text, TYPE_DIRECTIVE_PREFIX);
|
String[] directives = InTextDirectivesUtils.findArrayWithPrefixes(text, TYPE_DIRECTIVE_PREFIX);
|
||||||
if (directives.length == 0) return null;
|
if (directives.length == 0) return null;
|
||||||
@@ -131,5 +155,9 @@ public class KotlinConfidenceTest extends LightCompletionTestCase {
|
|||||||
protected void complete() {
|
protected void complete() {
|
||||||
new CodeCompletionHandlerBase(CompletionType.BASIC, false, true, true).invokeCompletion(
|
new CodeCompletionHandlerBase(CompletionType.BASIC, false, true, true).invokeCompletion(
|
||||||
getProject(), getEditor(), 0, false, false);
|
getProject(), getEditor(), 0, false, false);
|
||||||
|
|
||||||
|
LookupImpl lookup = (LookupImpl) LookupManager.getActiveLookup(myEditor);
|
||||||
|
myItems = lookup == null ? null : lookup.getItems().toArray(LookupElement.EMPTY_ARRAY);
|
||||||
|
myPrefix = lookup == null ? null : lookup.itemPattern(lookup.getItems().get(0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -491,6 +491,7 @@
|
|||||||
<completion.confidence language="kotlin"
|
<completion.confidence language="kotlin"
|
||||||
implementationClass="org.jetbrains.kotlin.idea.completion.confidence.UnfocusedPossibleFunctionParameter"/>
|
implementationClass="org.jetbrains.kotlin.idea.completion.confidence.UnfocusedPossibleFunctionParameter"/>
|
||||||
<completion.confidence language="kotlin" implementationClass="com.intellij.codeInsight.completion.AlwaysFocusLookup" order="last"/>
|
<completion.confidence language="kotlin" implementationClass="com.intellij.codeInsight.completion.AlwaysFocusLookup" order="last"/>
|
||||||
|
<completion.confidence language="kotlin" implementationClass="org.jetbrains.kotlin.idea.completion.confidence.EnableAutopopupInStringTemplate"/>
|
||||||
<completion.confidence language="kotlin" implementationClass="com.intellij.codeInsight.completion.SkipAutopopupInStrings"/>
|
<completion.confidence language="kotlin" implementationClass="com.intellij.codeInsight.completion.SkipAutopopupInStrings"/>
|
||||||
|
|
||||||
<lookup.charFilter implementation="org.jetbrains.kotlin.idea.completion.KotlinCompletionCharFilter"/>
|
<lookup.charFilter implementation="org.jetbrains.kotlin.idea.completion.KotlinCompletionCharFilter"/>
|
||||||
|
|||||||
Reference in New Issue
Block a user