Behavior on typing chars with code completion lookup is completely defined by our own handler + added tests for this handler + fixed a few bugs related to this behavior
This commit is contained in:
@@ -130,6 +130,7 @@ import org.jetbrains.jet.j2k.test.AbstractJavaToKotlinConverterMultiFileTest
|
||||
import org.jetbrains.jet.j2k.test.AbstractJavaToKotlinConverterForWebDemoTest
|
||||
import org.jetbrains.jet.plugin.decompiler.textBuilder.AbstractDecompiledTextTest
|
||||
import org.jetbrains.jet.completion.AbstractMultiFileSmartCompletionTest
|
||||
import org.jetbrains.jet.completion.handlers.AbstractCompletionCharFilterTest
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
System.setProperty("java.awt.headless", "true")
|
||||
@@ -358,6 +359,10 @@ fun main(args: Array<String>) {
|
||||
model("completion/handlers/smart")
|
||||
}
|
||||
|
||||
testClass(javaClass<AbstractCompletionCharFilterTest>()) {
|
||||
model("completion/handlers/charFilter")
|
||||
}
|
||||
|
||||
testClass(javaClass<AbstractCodeFragmentCompletionTest>()) {
|
||||
model("completion/basic/codeFragments", extension = "kt")
|
||||
}
|
||||
|
||||
@@ -25,17 +25,22 @@ import com.intellij.openapi.util.Key
|
||||
|
||||
public class KotlinCompletionCharFilter() : CharFilter() {
|
||||
class object {
|
||||
public val ACCEPT_OPENING_BRACE: Key<Boolean> = Key<Boolean>("KotlinCompletionCharFilter.ACCEPT_OPENNING_BRACE")
|
||||
public val ACCEPT_EQ: Key<Boolean> = Key<Boolean>("KotlinCompletionCharFilter.ACCEPT_EQ")
|
||||
public val ACCEPT_OPENING_BRACE: Key<Boolean> = Key("KotlinCompletionCharFilter.ACCEPT_OPENNING_BRACE")
|
||||
public val ACCEPT_EQ: Key<Boolean> = Key("KotlinCompletionCharFilter.ACCEPT_EQ")
|
||||
}
|
||||
|
||||
public override fun acceptChar(c : Char, prefixLength : Int, lookup : Lookup) : Result? {
|
||||
if (lookup.getPsiFile() !is JetFile) return null
|
||||
if (!lookup.isCompletion()) return null
|
||||
|
||||
if (Character.isJavaIdentifierPart(c) || c == ':' /* used in '::xxx'*/) return CharFilter.Result.ADD_TO_PREFIX
|
||||
if (Character.isJavaIdentifierPart(c) || c == ':' /* used in '::xxx'*/) {
|
||||
return CharFilter.Result.ADD_TO_PREFIX
|
||||
}
|
||||
|
||||
val currentItem = lookup.getCurrentItem()
|
||||
return when (c) {
|
||||
'.' -> {
|
||||
//TODO: this heuristics better to be only used for auto-popup completion but I see no way to check this
|
||||
if (prefixLength == 0 && !lookup.isSelectionTouched()) {
|
||||
val caret = lookup.getEditor().getCaretModel().getOffset()
|
||||
if (caret > 0 && lookup.getEditor().getDocument().getCharsSequence()[caret - 1] == '.') {
|
||||
@@ -45,8 +50,7 @@ public class KotlinCompletionCharFilter() : CharFilter() {
|
||||
Result.SELECT_ITEM_AND_FINISH_LOOKUP
|
||||
}
|
||||
|
||||
'(' -> {
|
||||
val currentItem = lookup.getCurrentItem()
|
||||
'{' -> {
|
||||
if (currentItem != null && currentItem.getUserData(ACCEPT_OPENING_BRACE) ?: false)
|
||||
Result.SELECT_ITEM_AND_FINISH_LOOKUP
|
||||
else
|
||||
@@ -54,14 +58,13 @@ public class KotlinCompletionCharFilter() : CharFilter() {
|
||||
}
|
||||
|
||||
'=' -> {
|
||||
val currentItem = lookup.getCurrentItem()
|
||||
if (currentItem != null && currentItem.getUserData(ACCEPT_EQ) ?: false)
|
||||
Result.SELECT_ITEM_AND_FINISH_LOOKUP
|
||||
else
|
||||
Result.HIDE_LOOKUP
|
||||
Result.HIDE_LOOKUP //TODO: why not for others?
|
||||
}
|
||||
|
||||
',', ' ' -> Result.SELECT_ITEM_AND_FINISH_LOOKUP
|
||||
',', ' ', '(' -> Result.SELECT_ITEM_AND_FINISH_LOOKUP
|
||||
|
||||
else -> return CharFilter.Result.HIDE_LOOKUP
|
||||
}
|
||||
|
||||
@@ -88,14 +88,14 @@ public object KotlinLookupElementFactory {
|
||||
val insertHandler = getDefaultInsertHandler(descriptor)
|
||||
element = element.withInsertHandler(insertHandler)
|
||||
|
||||
if (insertHandler is JetFunctionInsertHandler && insertHandler.lambdaInfo != null) {
|
||||
element.putUserData<Boolean>(KotlinCompletionCharFilter.ACCEPT_OPENING_BRACE, true)
|
||||
}
|
||||
|
||||
element = element.withTailText(tailText, true).withTypeText(typeText).withPresentableText(presentableText)
|
||||
element = element.withIcon(JetDescriptorIconProvider.getIcon(descriptor, declaration, Iconable.ICON_FLAG_VISIBILITY))
|
||||
element = element.withStrikeoutness(KotlinBuiltIns.getInstance().isDeprecated(descriptor))
|
||||
|
||||
if (insertHandler is JetFunctionInsertHandler && insertHandler.lambdaInfo != null) {
|
||||
element.putUserData<Boolean>(KotlinCompletionCharFilter.ACCEPT_OPENING_BRACE, true)
|
||||
}
|
||||
|
||||
return element
|
||||
}
|
||||
|
||||
|
||||
@@ -88,8 +88,8 @@ object NamedParametersCompletion {
|
||||
val name = parameter.getName()
|
||||
val nameString = name.asString()
|
||||
if (nameString !in usedArguments) {
|
||||
val text = "$nameString ="
|
||||
val lookupElement = LookupElementBuilder.create(text)
|
||||
val lookupElement = LookupElementBuilder.create(nameString)
|
||||
.withPresentableText("$nameString =")
|
||||
.withTailText(" ${DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(parameter.getType())}")
|
||||
.withIcon(JetIcons.PARAMETER)
|
||||
.withInsertHandler(NamedParameterInsertHandler(name))
|
||||
|
||||
+3
-3
@@ -126,13 +126,13 @@ public class JetFunctionInsertHandler(val caretPosition : CaretPosition, val lam
|
||||
}
|
||||
|
||||
private fun addBrackets(context : InsertionContext, offsetElement : PsiElement) {
|
||||
if (context.getCompletionChar() == '(') { //TODO: more correct behavior related to braces type
|
||||
val completionChar = context.getCompletionChar()
|
||||
if (completionChar == '(') { //TODO: more correct behavior related to braces type
|
||||
context.setAddCompletionChar(false)
|
||||
}
|
||||
|
||||
val offset = context.getTailOffset()
|
||||
val document = context.getDocument()
|
||||
val completionChar = context.getCompletionChar()
|
||||
|
||||
val forceParenthesis = lambdaInfo != null && completionChar == '\t' && document.getCharsSequence().charAt(offset) == '('
|
||||
val braces = lambdaInfo != null && completionChar != '(' && !forceParenthesis
|
||||
@@ -168,7 +168,7 @@ public class JetFunctionInsertHandler(val caretPosition : CaretPosition, val lam
|
||||
val closeBracketOffset = indexOfSkippingSpace(document, closingBracket, openingBracketOffset + 1)
|
||||
val editor = context.getEditor()
|
||||
|
||||
var forcePlaceCaretIntoParentheses : Boolean = completionChar == '('
|
||||
var forcePlaceCaretIntoParentheses = completionChar == '('
|
||||
|
||||
if (caretPosition == CaretPosition.IN_BRACKETS || forcePlaceCaretIntoParentheses || closeBracketOffset == -1) {
|
||||
editor.getCaretModel().moveToOffset(openingBracketOffset + 1 + inBracketsShift)
|
||||
|
||||
@@ -30,9 +30,13 @@ class WithTailInsertHandler(val tailText: String,
|
||||
val spaceAfter: Boolean,
|
||||
val overwriteText: Boolean = true) : InsertHandler<LookupElement> {
|
||||
override fun handleInsert(context: InsertionContext, item: LookupElement) {
|
||||
val document = context.getDocument()
|
||||
|
||||
item.handleInsert(context)
|
||||
|
||||
if (tailText == context.getCompletionChar().toString() && context.shouldAddCompletionChar()) {
|
||||
return
|
||||
}
|
||||
|
||||
val document = context.getDocument()
|
||||
PsiDocumentManager.getInstance(context.getProject()).doPostponedOperationsAndUnblockDocument(document)
|
||||
|
||||
var tailOffset = context.getTailOffset()
|
||||
|
||||
@@ -39,7 +39,6 @@ object LambdaItems {
|
||||
.suppressAutoInsertion()
|
||||
.assignSmartCompletionPriority(SmartCompletionItemPriority.LAMBDA_NO_PARAMS)
|
||||
.addTailAndNameSimilarity(functionExpectedInfos)
|
||||
lookupElement.putUserData(KotlinCompletionCharFilter.ACCEPT_OPENING_BRACE, true)
|
||||
collection.add(lookupElement)
|
||||
}
|
||||
|
||||
@@ -56,7 +55,6 @@ object LambdaItems {
|
||||
.suppressAutoInsertion()
|
||||
.assignSmartCompletionPriority(SmartCompletionItemPriority.LAMBDA)
|
||||
.addTailAndNameSimilarity(functionExpectedInfos.filter { it.type == functionType })
|
||||
lookupElement.putUserData(KotlinCompletionCharFilter.ACCEPT_OPENING_BRACE, true)
|
||||
collection.add(lookupElement)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,4 +3,4 @@ fun small(param: Int) {
|
||||
|
||||
fun test() = small(<caret>)
|
||||
|
||||
// EXIST: {"lookupString":"param =","tailText":" Int","itemText":"param ="}
|
||||
// EXIST: {"lookupString":"param","tailText":" Int","itemText":"param ="}
|
||||
@@ -3,5 +3,5 @@ fun small(first: Int, second: Int) {
|
||||
|
||||
fun test() = small(12, <caret>)
|
||||
|
||||
// ABSENT: "first ="
|
||||
// EXIST: "second ="
|
||||
// ABSENT: first
|
||||
// EXIST: { lookupString:"second", itemText:"second =" }
|
||||
|
||||
@@ -7,5 +7,5 @@ fun small(paramFirst: ArrayList<String>, paramSecond: Comparable<java.lang.Runti
|
||||
|
||||
fun test() = small(<caret>)
|
||||
|
||||
// EXIST: {"lookupString":"paramSecond =","tailText":" Comparable<RuntimeException>","itemText":"paramSecond ="}
|
||||
// EXIST: {"lookupString":"paramFirst =","tailText":" ArrayList<String>","itemText":"paramFirst ="}
|
||||
// EXIST: {"lookupString":"paramSecond","tailText":" Comparable<RuntimeException>","itemText":"paramSecond ="}
|
||||
// EXIST: {"lookupString":"paramFirst","tailText":" ArrayList<String>","itemText":"paramFirst ="}
|
||||
|
||||
@@ -6,6 +6,6 @@ fun small(paramFirst: Int, paramSecond: Int) {
|
||||
fun test() = small(paramFirst = param<caret>)
|
||||
|
||||
// EXIST: paramTest
|
||||
// ABSENT: {"lookupString":"paramFirst =","tailText":" Int","itemText":"paramFirst ="}
|
||||
// ABSENT: "paramSecond ="
|
||||
// ABSENT: {"lookupString":"paramFirst","tailText":" Int","itemText":"paramFirst ="}
|
||||
// ABSENT: paramSecond
|
||||
// NUMBER: 1
|
||||
+5
-5
@@ -10,11 +10,11 @@ fun other() {
|
||||
foo(n<caret>)
|
||||
}
|
||||
|
||||
// EXIST: "nFirst ="
|
||||
// EXIST: "nSecond ="
|
||||
// EXIST: "nThird ="
|
||||
// EXIST: { lookupString:"nFirst", itemText:"nFirst =" }
|
||||
// EXIST: { lookupString:"nSecond", itemText:"nSecond =" }
|
||||
// EXIST: { lookupString:"nThird", itemText:"nThird =" }
|
||||
// EXIST: nLocal
|
||||
|
||||
// todo - should exist
|
||||
// ABSENT: "nClassParam ="
|
||||
// ABSENT: "nClassField ="
|
||||
// ABSENT: nClassParam
|
||||
// ABSENT: nClassField
|
||||
@@ -6,5 +6,5 @@ fun other() {
|
||||
Foo(p<caret>)
|
||||
}
|
||||
|
||||
// EXIST: {"lookupString":"pFirst =","tailText":" String?","itemText":"pFirst ="}
|
||||
// EXIST: {"lookupString":"pSecond =","tailText":" Int","itemText":"pSecond ="}
|
||||
// EXIST: {"lookupString":"pFirst","tailText":" String?","itemText":"pFirst ="}
|
||||
// EXIST: {"lookupString":"pSecond","tailText":" Int","itemText":"pSecond ="}
|
||||
@@ -4,8 +4,8 @@ fun test() {
|
||||
foo("str", paramThird = "test", param<caret>)
|
||||
}
|
||||
|
||||
// ABSENT: "paramFirst ="
|
||||
// EXIST: "paramSecond ="
|
||||
// ABSENT: "paramThird ="
|
||||
// EXIST: "paramFourth ="
|
||||
// ABSENT: paramFirst
|
||||
// EXIST: paramSecond
|
||||
// ABSENT: paramThird
|
||||
// EXIST: paramFourth
|
||||
|
||||
|
||||
+4
-4
@@ -5,7 +5,7 @@ fun test() {
|
||||
foo(12, param<caret>)
|
||||
}
|
||||
|
||||
// ABSENT: "paramFirst ="
|
||||
// EXIST: {"lookupString":"paramSecond =","tailText":" Int","itemText":"paramSecond ="}
|
||||
// ABSENT: "paramThird ="
|
||||
// ABSENT: "paramFourth ="
|
||||
// ABSENT: paramFirst
|
||||
// EXIST: {"lookupString":"paramSecond","tailText":" Int","itemText":"paramSecond ="}
|
||||
// ABSENT: paramThird
|
||||
// ABSENT: paramFourth
|
||||
@@ -4,6 +4,6 @@ fun foo(first: Int, second: Int, third: String) {
|
||||
fun test(p: Int) = foo(12, <caret>, third = "")
|
||||
|
||||
// EXIST: p
|
||||
// ABSENT: "first ="
|
||||
// EXIST: "third ="
|
||||
// EXIST: "second ="
|
||||
// ABSENT: first
|
||||
// EXIST: third
|
||||
// EXIST: second
|
||||
|
||||
@@ -4,6 +4,6 @@ fun foo(first: Int, second: Int, third: String) {
|
||||
fun test(p: Int) = foo(<caret>second = 3)
|
||||
|
||||
// EXIST: p
|
||||
// EXIST: "first ="
|
||||
// EXIST: "second ="
|
||||
// EXIST: "third ="
|
||||
// EXIST: first
|
||||
// EXIST: second
|
||||
// EXIST: third
|
||||
|
||||
@@ -4,7 +4,7 @@ fun foo(first: Int, second: Int, third: String) {
|
||||
fun test(p: Int) = foo(12, third = "", <caret>)
|
||||
|
||||
// ABSENT: p
|
||||
// ABSENT: "first ="
|
||||
// ABSENT: "third ="
|
||||
// EXIST: "second ="
|
||||
// ABSENT: first
|
||||
// ABSENT: third
|
||||
// EXIST: second
|
||||
// NUMBER: 1
|
||||
@@ -5,8 +5,8 @@ fun small(paramFirst: Int, paramSecond: Int) {
|
||||
|
||||
fun test() = small(param<caret>First = 12)
|
||||
|
||||
// EXIST: "paramFirst ="
|
||||
// EXIST: "paramSecond ="
|
||||
// EXIST: paramFirst
|
||||
// EXIST: paramSecond
|
||||
// EXIST: paramTest
|
||||
|
||||
// NUMBER: 3
|
||||
@@ -2,5 +2,5 @@ import lib.KotlinClass
|
||||
|
||||
fun test() = KotlinClass().foo(<caret>)
|
||||
|
||||
// ABSENT: "p0 ="
|
||||
// EXIST: "paramName ="
|
||||
// ABSENT: p0
|
||||
// EXIST: { lookupString:"paramName", itemText:"paramName =" }
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
fun foo(p: () -> Unit){}
|
||||
|
||||
fun bar() {
|
||||
foo(<caret>)
|
||||
}
|
||||
|
||||
fun f(){}
|
||||
|
||||
// COMPLETION_TYPE: SMART
|
||||
// ELEMENT: *
|
||||
// CHAR: :
|
||||
@@ -0,0 +1,11 @@
|
||||
fun foo(p: () -> Unit){}
|
||||
|
||||
fun bar() {
|
||||
foo(:<caret>)
|
||||
}
|
||||
|
||||
fun f(){}
|
||||
|
||||
// COMPLETION_TYPE: SMART
|
||||
// ELEMENT: *
|
||||
// CHAR: :
|
||||
@@ -0,0 +1,9 @@
|
||||
fun foo(p1: Int) { }
|
||||
fun foo(p1: Int, p2: Int) { }
|
||||
|
||||
fun bar(ppp: Int, a: Int) {
|
||||
foo(<caret>)
|
||||
}
|
||||
|
||||
// ELEMENT: ppp
|
||||
// CHAR: ','
|
||||
@@ -0,0 +1,9 @@
|
||||
fun foo(p1: Int) { }
|
||||
fun foo(p1: Int, p2: Int) { }
|
||||
|
||||
fun bar(ppp: Int, a: Int) {
|
||||
foo(ppp,<caret>)
|
||||
}
|
||||
|
||||
// ELEMENT: ppp
|
||||
// CHAR: ','
|
||||
@@ -0,0 +1,9 @@
|
||||
fun foo(p1: Int, p2: Int) { }
|
||||
|
||||
fun bar(pp: Int, a: Int) {
|
||||
foo(<caret>)
|
||||
}
|
||||
|
||||
// COMPLETION_TYPE: SMART
|
||||
// ELEMENT: pp
|
||||
// CHAR: ','
|
||||
@@ -0,0 +1,9 @@
|
||||
fun foo(p1: Int, p2: Int) { }
|
||||
|
||||
fun bar(pp: Int, a: Int) {
|
||||
foo(pp,<caret>)
|
||||
}
|
||||
|
||||
// COMPLETION_TYPE: SMART
|
||||
// ELEMENT: pp
|
||||
// CHAR: ','
|
||||
@@ -0,0 +1,9 @@
|
||||
class C(filter: (String) -> Boolean)
|
||||
|
||||
fun foo(p: C) {
|
||||
val c: C = <caret>
|
||||
}
|
||||
|
||||
// COMPLETION_TYPE: SMART
|
||||
// ELEMENT: C
|
||||
// CHAR: {
|
||||
@@ -0,0 +1,9 @@
|
||||
class C(filter: (String) -> Boolean)
|
||||
|
||||
fun foo(p: C) {
|
||||
val c: C = C { <caret> }
|
||||
}
|
||||
|
||||
// COMPLETION_TYPE: SMART
|
||||
// ELEMENT: C
|
||||
// CHAR: {
|
||||
@@ -0,0 +1,9 @@
|
||||
class C(filter: (String) -> Boolean)
|
||||
|
||||
fun foo(p: C) {
|
||||
val c: C = <caret>
|
||||
}
|
||||
|
||||
// COMPLETION_TYPE: SMART
|
||||
// ELEMENT: C
|
||||
// CHAR: (
|
||||
@@ -0,0 +1,9 @@
|
||||
class C(filter: (String) -> Boolean)
|
||||
|
||||
fun foo(p: C) {
|
||||
val c: C = C(<caret>)
|
||||
}
|
||||
|
||||
// COMPLETION_TYPE: SMART
|
||||
// ELEMENT: C
|
||||
// CHAR: (
|
||||
@@ -0,0 +1,7 @@
|
||||
fun foo(o: Any) {
|
||||
o.<caret>
|
||||
}
|
||||
|
||||
// INVOCATION_COUNT: 0
|
||||
// ELEMENT: hashCode
|
||||
// CHAR: .
|
||||
@@ -0,0 +1,7 @@
|
||||
fun foo(o: Any) {
|
||||
o.hashCode().<caret>
|
||||
}
|
||||
|
||||
// INVOCATION_COUNT: 0
|
||||
// ELEMENT: hashCode
|
||||
// CHAR: .
|
||||
@@ -0,0 +1,8 @@
|
||||
fun foo(filter: (String) -> Boolean) {}
|
||||
|
||||
fun bar() {
|
||||
f<caret>
|
||||
}
|
||||
|
||||
// ELEMENT: foo
|
||||
// CHAR: {
|
||||
@@ -0,0 +1,8 @@
|
||||
fun foo(filter: (String) -> Boolean) {}
|
||||
|
||||
fun bar() {
|
||||
foo { <caret> }
|
||||
}
|
||||
|
||||
// ELEMENT: foo
|
||||
// CHAR: {
|
||||
@@ -0,0 +1,8 @@
|
||||
fun foo(filter: (String) -> Boolean) {}
|
||||
|
||||
fun bar() {
|
||||
f<caret>
|
||||
}
|
||||
|
||||
// ELEMENT: foo
|
||||
// CHAR: (
|
||||
@@ -0,0 +1,8 @@
|
||||
fun foo(filter: (String) -> Boolean) {}
|
||||
|
||||
fun bar() {
|
||||
foo(<caret>)
|
||||
}
|
||||
|
||||
// ELEMENT: foo
|
||||
// CHAR: (
|
||||
@@ -0,0 +1,8 @@
|
||||
fun foo() { }
|
||||
|
||||
fun bar() {
|
||||
f<caret>
|
||||
}
|
||||
|
||||
// ELEMENT: foo
|
||||
// CHAR: (
|
||||
@@ -0,0 +1,8 @@
|
||||
fun foo() { }
|
||||
|
||||
fun bar() {
|
||||
foo(<caret>)
|
||||
}
|
||||
|
||||
// ELEMENT: foo
|
||||
// CHAR: (
|
||||
@@ -0,0 +1,8 @@
|
||||
fun foo(xxx: Int, yyy: Int)
|
||||
|
||||
fun test() {
|
||||
foo(xxx = 10, <caret>)
|
||||
}
|
||||
|
||||
// ELEMENT: yyy
|
||||
// CHAR: =
|
||||
@@ -0,0 +1,8 @@
|
||||
fun foo(xxx: Int, yyy: Int)
|
||||
|
||||
fun test() {
|
||||
foo(xxx = 10, yyy = <caret>)
|
||||
}
|
||||
|
||||
// ELEMENT: yyy
|
||||
// CHAR: =
|
||||
@@ -0,0 +1,8 @@
|
||||
fun foo(xxx: Int, yyy: Int)
|
||||
|
||||
fun test() {
|
||||
foo(xxx = 10, <caret>)
|
||||
}
|
||||
|
||||
// ELEMENT: yyy
|
||||
// CHAR: ' '
|
||||
@@ -0,0 +1,8 @@
|
||||
fun foo(xxx: Int, yyy: Int)
|
||||
|
||||
fun test() {
|
||||
foo(xxx = 10, yyy = <caret>)
|
||||
}
|
||||
|
||||
// ELEMENT: yyy
|
||||
// CHAR: ' '
|
||||
@@ -0,0 +1,7 @@
|
||||
fun foo(start: Int) {
|
||||
val range = start.<caret>
|
||||
}
|
||||
|
||||
// INVOCATION_COUNT: 0
|
||||
// ELEMENT: *
|
||||
// CHAR: .
|
||||
@@ -0,0 +1,7 @@
|
||||
fun foo(start: Int) {
|
||||
val range = start..<caret>
|
||||
}
|
||||
|
||||
// INVOCATION_COUNT: 0
|
||||
// ELEMENT: *
|
||||
// CHAR: .
|
||||
@@ -0,0 +1,4 @@
|
||||
class A : A<caret>
|
||||
|
||||
// ELEMENT: Annotation
|
||||
// CHAR: ' '
|
||||
@@ -0,0 +1,4 @@
|
||||
class A : Annotation <caret>
|
||||
|
||||
// ELEMENT: Annotation
|
||||
// CHAR: ' '
|
||||
@@ -18,5 +18,5 @@ fun test(listParam: Int) {
|
||||
// ORDER: listImportedVal
|
||||
// ORDER: listThisFileFun
|
||||
// ORDER: listImportedFun
|
||||
// ORDER: "listMatch ="
|
||||
// ORDER: "listNew ="
|
||||
// ORDER: listMatch
|
||||
// ORDER: listNew
|
||||
|
||||
@@ -19,6 +19,7 @@ package org.jetbrains.jet.completion;
|
||||
import com.intellij.testFramework.TestDataPath;
|
||||
import org.jetbrains.jet.JUnit3RunnerWithInners;
|
||||
import org.jetbrains.jet.JetTestUtils;
|
||||
import org.jetbrains.jet.test.InnerTestClasses;
|
||||
import org.jetbrains.jet.test.TestMetadata;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
|
||||
+26
-21
@@ -16,33 +16,16 @@
|
||||
|
||||
package org.jetbrains.jet.completion.handlers
|
||||
|
||||
import org.jetbrains.jet.plugin.JetLightCodeInsightFixtureTestCase
|
||||
import com.intellij.codeInsight.completion.CompletionType
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettingsManager
|
||||
import org.jetbrains.jet.plugin.formatter.JetCodeStyleSettings
|
||||
import com.intellij.codeInsight.lookup.LookupElement
|
||||
import java.io.File
|
||||
import org.jetbrains.jet.plugin.PluginTestCaseBase
|
||||
import com.intellij.codeInsight.lookup.impl.LookupImpl
|
||||
import com.intellij.codeInsight.lookup.LookupEvent
|
||||
import com.intellij.openapi.command.WriteCommandAction
|
||||
import com.intellij.codeInsight.lookup.LookupManager
|
||||
import com.intellij.codeInsight.lookup.LookupElementPresentation
|
||||
import org.junit.Assert
|
||||
import com.intellij.openapi.application.Result
|
||||
import com.intellij.testFramework.fixtures.JavaCodeInsightTestFixture
|
||||
import kotlin.properties.Delegates
|
||||
import org.jetbrains.jet.InTextDirectivesUtils
|
||||
|
||||
public abstract class AbstractSmartCompletionHandlerTest() : CompletionHandlerTestBase() {
|
||||
public abstract class AbstractCompletionHandlerTest() : CompletionHandlerTestBase() {
|
||||
private val INVOCATION_COUNT_PREFIX = "INVOCATION_COUNT:"
|
||||
private val LOOKUP_STRING_PREFIX = "ELEMENT:"
|
||||
private val ELEMENT_TEXT_PREFIX = "ELEMENT_TEXT:"
|
||||
private val TAIL_TEXT_PREFIX = "TAIL_TEXT:"
|
||||
private val COMPLETION_CHAR_PREFIX = "CHAR:"
|
||||
|
||||
override val completionType: CompletionType = CompletionType.SMART
|
||||
override val testDataRelativePath: String = "/completion/handlers/smart"
|
||||
private val COMPLETION_TYPE_PREFIX = "COMPLETION_TYPE:"
|
||||
|
||||
protected fun doTest(testPath: String) {
|
||||
fixture.configureByFile(testPath)
|
||||
@@ -52,12 +35,34 @@ public abstract class AbstractSmartCompletionHandlerTest() : CompletionHandlerTe
|
||||
val lookupString = InTextDirectivesUtils.findStringWithPrefixes(fileText, LOOKUP_STRING_PREFIX)
|
||||
val itemText = InTextDirectivesUtils.findStringWithPrefixes(fileText, ELEMENT_TEXT_PREFIX)
|
||||
val tailText = InTextDirectivesUtils.findStringWithPrefixes(fileText, TAIL_TEXT_PREFIX)
|
||||
|
||||
val completionCharString = InTextDirectivesUtils.findStringWithPrefixes(fileText, COMPLETION_CHAR_PREFIX)
|
||||
val completionChar = when(completionCharString) {
|
||||
"\\n", null -> '\n'
|
||||
"\\t" -> '\t'
|
||||
else -> error("Uknown completion char")
|
||||
else -> completionCharString.singleOrNull() ?: error("Incorrect completion char: \"$completionCharString\"")
|
||||
}
|
||||
doTestWithTextLoaded(invocationCount, lookupString, itemText, tailText, completionChar)
|
||||
|
||||
val completionTypeString = InTextDirectivesUtils.findStringWithPrefixes(fileText, COMPLETION_TYPE_PREFIX)
|
||||
val completionType = when (completionTypeString) {
|
||||
"BASIC" -> CompletionType.BASIC
|
||||
"SMART" -> CompletionType.SMART
|
||||
null -> defaultCompletionType
|
||||
else -> error("Unknown completion type: $completionTypeString")
|
||||
}
|
||||
|
||||
doTestWithTextLoaded(completionType, invocationCount, lookupString, itemText, tailText, completionChar)
|
||||
}
|
||||
|
||||
protected abstract val defaultCompletionType: CompletionType
|
||||
}
|
||||
|
||||
public abstract class AbstractSmartCompletionHandlerTest() : AbstractCompletionHandlerTest() {
|
||||
override val defaultCompletionType: CompletionType = CompletionType.SMART
|
||||
override val testDataRelativePath: String = "/completion/handlers/smart"
|
||||
}
|
||||
|
||||
public abstract class AbstractCompletionCharFilterTest() : AbstractCompletionHandlerTest() {
|
||||
override val defaultCompletionType: CompletionType = CompletionType.BASIC
|
||||
override val testDataRelativePath: String = "/completion/handlers/charFilter"
|
||||
}
|
||||
|
||||
@@ -21,9 +21,21 @@ import org.jetbrains.jet.plugin.formatter.JetCodeStyleSettings
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettingsManager
|
||||
|
||||
public class BasicCompletionHandlerTest : CompletionHandlerTestBase(){
|
||||
override val completionType: CompletionType = CompletionType.BASIC
|
||||
override val testDataRelativePath: String = "/completion/handlers"
|
||||
|
||||
private fun doTest() {
|
||||
doTest(2, "*", null, null, '\n')
|
||||
}
|
||||
|
||||
private fun doTest(time: Int, lookupString: String?, tailText: String?, completionChar: Char) {
|
||||
doTest(time, lookupString, null, tailText, completionChar)
|
||||
}
|
||||
|
||||
private fun doTest(time: Int, lookupString: String?, itemText: String?, tailText: String?, completionChar: Char) {
|
||||
fixture.configureByFile(fileName())
|
||||
doTestWithTextLoaded(CompletionType.BASIC, time, lookupString, itemText, tailText, completionChar)
|
||||
}
|
||||
|
||||
fun testClassCompletionImport() = doTest(2, "SortedSet", null, '\n')
|
||||
|
||||
fun testClassCompletionInMiddle() = doTest(1, "TimeZone", " (java.util)", '\t')
|
||||
@@ -48,9 +60,9 @@ public class BasicCompletionHandlerTest : CompletionHandlerTestBase(){
|
||||
|
||||
fun testNamedParametersCompletion() = doTest()
|
||||
|
||||
fun testNamedParametersCompletionOnEqual() = doTest(0, "paramTest =", null, '=')
|
||||
fun testNamedParametersCompletionOnEqual() = doTest(0, "paramTest", "paramTest =", null, '=')
|
||||
|
||||
fun testNamedParameterKeywordName() = doTest(1, "class =", null, '\n')
|
||||
fun testNamedParameterKeywordName() = doTest(1, "class", "class =", null, '\n')
|
||||
|
||||
fun testInsertJavaClassImport() = doTest()
|
||||
|
||||
|
||||
+116
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Copyright 2010-2014 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.jet.completion.handlers;
|
||||
|
||||
import com.intellij.testFramework.TestDataPath;
|
||||
import org.jetbrains.jet.JUnit3RunnerWithInners;
|
||||
import org.jetbrains.jet.JetTestUtils;
|
||||
import org.jetbrains.jet.test.InnerTestClasses;
|
||||
import org.jetbrains.jet.test.TestMetadata;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/** This class is generated by {@link org.jetbrains.jet.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
|
||||
@SuppressWarnings("all")
|
||||
@TestMetadata("idea/testData/completion/handlers/charFilter")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public class CompletionCharFilterTestGenerated extends AbstractCompletionCharFilterTest {
|
||||
public void testAllFilesPresentInCharFilter() throws Exception {
|
||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/completion/handlers/charFilter"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("Colon.kt")
|
||||
public void testColon() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/handlers/charFilter/Colon.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("Comma1.kt")
|
||||
public void testComma1() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/handlers/charFilter/Comma1.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("Comma2.kt")
|
||||
public void testComma2() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/handlers/charFilter/Comma2.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("ConstructorWithLambdaArg1.kt")
|
||||
public void testConstructorWithLambdaArg1() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/handlers/charFilter/ConstructorWithLambdaArg1.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("ConstructorWithLambdaArg2.kt")
|
||||
public void testConstructorWithLambdaArg2() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/handlers/charFilter/ConstructorWithLambdaArg2.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("Dot.kt")
|
||||
public void testDot() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/handlers/charFilter/Dot.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("FunctionWithLambdaArg1.kt")
|
||||
public void testFunctionWithLambdaArg1() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/handlers/charFilter/FunctionWithLambdaArg1.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("FunctionWithLambdaArg2.kt")
|
||||
public void testFunctionWithLambdaArg2() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/handlers/charFilter/FunctionWithLambdaArg2.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("LParenth.kt")
|
||||
public void testLParenth() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/handlers/charFilter/LParenth.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("NamedParameter1.kt")
|
||||
public void testNamedParameter1() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/handlers/charFilter/NamedParameter1.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("NamedParameter2.kt")
|
||||
public void testNamedParameter2() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/handlers/charFilter/NamedParameter2.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("RangeTyping.kt")
|
||||
public void testRangeTyping() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/handlers/charFilter/RangeTyping.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("Space.kt")
|
||||
public void testSpace() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/handlers/charFilter/Space.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
@@ -31,24 +31,19 @@ import com.intellij.openapi.application.Result
|
||||
import com.intellij.testFramework.fixtures.JavaCodeInsightTestFixture
|
||||
|
||||
public abstract class CompletionHandlerTestBase() : JetLightCodeInsightFixtureTestCase() {
|
||||
protected abstract val completionType : CompletionType
|
||||
protected abstract val testDataRelativePath: String
|
||||
|
||||
protected val fixture: JavaCodeInsightTestFixture
|
||||
get() = myFixture
|
||||
|
||||
protected fun doTest() : Unit = doTest(2, "*", null, null, '\n')
|
||||
|
||||
protected fun doTest(time: Int, lookupString: String?, tailText: String?, completionChar: Char) {
|
||||
doTest(time, lookupString, null, tailText, completionChar)
|
||||
}
|
||||
|
||||
protected fun doTest(time: Int, lookupString: String?, itemText: String?, tailText: String?, completionChar: Char) {
|
||||
fixture.configureByFile(fileName())
|
||||
doTestWithTextLoaded(time, lookupString, itemText, tailText, completionChar)
|
||||
}
|
||||
|
||||
protected fun doTestWithTextLoaded(time: Int, lookupString: String?, itemText: String?, tailText: String?, completionChar: Char) {
|
||||
protected fun doTestWithTextLoaded(
|
||||
completionType: CompletionType,
|
||||
time: Int,
|
||||
lookupString: String?,
|
||||
itemText: String?,
|
||||
tailText: String?,
|
||||
completionChar: Char
|
||||
) {
|
||||
fixture.complete(completionType, time)
|
||||
|
||||
if (lookupString != null || itemText != null || tailText != null) {
|
||||
@@ -126,7 +121,9 @@ public abstract class CompletionHandlerTestBase() : JetLightCodeInsightFixtureTe
|
||||
|
||||
protected fun selectItem(item: LookupElement?, completionChar: Char) {
|
||||
val lookup = (fixture.getLookup() as LookupImpl)
|
||||
lookup.setCurrentItem(item)
|
||||
if (lookup.getCurrentItem() != item) { // do not touch selection if not changed - important for char filter tests
|
||||
lookup.setCurrentItem(item)
|
||||
}
|
||||
if (LookupEvent.isSpecialCompletionChar(completionChar)) {
|
||||
(object : WriteCommandAction.Simple<Any>(getProject()) {
|
||||
protected override fun run(result: Result<Any>) {
|
||||
|
||||
Reference in New Issue
Block a user