From ffff6226b0eec5ab2a575dcade838abeb57fb82c Mon Sep 17 00:00:00 2001 From: Valentin Kipyatkov Date: Tue, 3 Mar 2015 19:04:13 +0300 Subject: [PATCH] KT-6608 Code completion does not work after $ in string literals KT-5070 Add braces when complete function in string templates #KT-6608 Fixed #KT-5070 Fixed --- .../idea/completion/CompletionSession.kt | 68 ++++++++++--------- .../kotlin/idea/completion/CompletionUtils.kt | 14 ++++ .../completion/LookupElementsCollector.kt | 22 ++++-- .../basic/common/StringTemplate1.kt | 6 ++ .../basic/common/StringTemplate2.kt | 6 ++ .../handlers/basic/stringTemplate/1.kt | 5 ++ .../handlers/basic/stringTemplate/1.kt.after | 5 ++ .../handlers/basic/stringTemplate/2.kt | 5 ++ .../handlers/basic/stringTemplate/2.kt.after | 5 ++ .../handlers/basic/stringTemplate/3.kt | 5 ++ .../handlers/basic/stringTemplate/3.kt.after | 5 ++ .../handlers/basic/stringTemplate/4.kt | 5 ++ .../handlers/basic/stringTemplate/4.kt.after | 5 ++ .../basic/stringTemplate/NotEmptyPrefix.kt | 7 ++ .../stringTemplate/NotEmptyPrefix.kt.after | 7 ++ .../handlers/basic/stringTemplate/Replace.kt | 6 ++ .../basic/stringTemplate/Replace.kt.after | 6 ++ .../JSBasicCompletionTestGenerated.java | 12 ++++ .../JvmBasicCompletionTestGenerated.java | 12 ++++ .../AbstractCompletionHandlerTests.kt | 29 +++----- .../handlers/BasicCompletionHandlerTest.kt | 12 +++- .../BasicCompletionHandlerTestGenerated.java | 48 +++++++++++++ .../handlers/CompletionHandlerTestBase.kt | 34 +++------- ...AbstractEditorForEvaluateExpressionTest.kt | 5 +- 24 files changed, 249 insertions(+), 85 deletions(-) create mode 100644 idea/testData/completion/basic/common/StringTemplate1.kt create mode 100644 idea/testData/completion/basic/common/StringTemplate2.kt create mode 100644 idea/testData/completion/handlers/basic/stringTemplate/1.kt create mode 100644 idea/testData/completion/handlers/basic/stringTemplate/1.kt.after create mode 100644 idea/testData/completion/handlers/basic/stringTemplate/2.kt create mode 100644 idea/testData/completion/handlers/basic/stringTemplate/2.kt.after create mode 100644 idea/testData/completion/handlers/basic/stringTemplate/3.kt create mode 100644 idea/testData/completion/handlers/basic/stringTemplate/3.kt.after create mode 100644 idea/testData/completion/handlers/basic/stringTemplate/4.kt create mode 100644 idea/testData/completion/handlers/basic/stringTemplate/4.kt.after create mode 100644 idea/testData/completion/handlers/basic/stringTemplate/NotEmptyPrefix.kt create mode 100644 idea/testData/completion/handlers/basic/stringTemplate/NotEmptyPrefix.kt.after create mode 100644 idea/testData/completion/handlers/basic/stringTemplate/Replace.kt create mode 100644 idea/testData/completion/handlers/basic/stringTemplate/Replace.kt.after diff --git a/idea/src/org/jetbrains/kotlin/idea/completion/CompletionSession.kt b/idea/src/org/jetbrains/kotlin/idea/completion/CompletionSession.kt index 49f480b2552..100d51b94dc 100644 --- a/idea/src/org/jetbrains/kotlin/idea/completion/CompletionSession.kt +++ b/idea/src/org/jetbrains/kotlin/idea/completion/CompletionSession.kt @@ -17,36 +17,38 @@ package org.jetbrains.kotlin.idea.completion import com.intellij.codeInsight.completion.* +import com.intellij.openapi.project.Project +import com.intellij.openapi.vfs.VirtualFile +import com.intellij.patterns.CharPattern +import com.intellij.patterns.PatternCondition +import com.intellij.patterns.StandardPatterns import com.intellij.psi.PsiElement +import com.intellij.psi.search.DelegatingGlobalSearchScope import com.intellij.psi.search.GlobalSearchScope import com.intellij.psi.util.PsiTreeUtil +import com.intellij.util.ProcessingContext import org.jetbrains.kotlin.descriptors.* -import org.jetbrains.kotlin.psi.* -import org.jetbrains.kotlin.resolve.BindingContext -import org.jetbrains.kotlin.idea.caches.resolve.* +import org.jetbrains.kotlin.idea.caches.KotlinIndicesHelper +import org.jetbrains.kotlin.idea.caches.resolve.ResolutionFacade +import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade import org.jetbrains.kotlin.idea.codeInsight.ReferenceVariantsHelper import org.jetbrains.kotlin.idea.completion.smart.SmartCompletion -import org.jetbrains.kotlin.idea.references.JetSimpleNameReference -import org.jetbrains.kotlin.idea.caches.KotlinIndicesHelper -import com.intellij.openapi.project.Project -import com.intellij.psi.search.DelegatingGlobalSearchScope -import com.intellij.openapi.vfs.VirtualFile -import org.jetbrains.kotlin.load.java.descriptors.SamConstructorDescriptorKindExclude -import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter -import org.jetbrains.kotlin.resolve.calls.smartcasts.SmartCastUtils -import org.jetbrains.kotlin.resolve.bindingContextUtil.getDataFlowInfo -import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull import org.jetbrains.kotlin.idea.refactoring.comparePossiblyOverridingDescriptors -import kotlin.properties.Delegates -import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType -import org.jetbrains.kotlin.idea.util.makeNotNullable +import org.jetbrains.kotlin.idea.references.JetSimpleNameReference import org.jetbrains.kotlin.idea.util.CallType -import org.jetbrains.kotlin.resolve.scopes.DescriptorKindExclude -import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode -import com.intellij.patterns.StandardPatterns -import com.intellij.util.ProcessingContext -import com.intellij.patterns.PatternCondition +import org.jetbrains.kotlin.idea.util.makeNotNullable +import org.jetbrains.kotlin.load.java.descriptors.SamConstructorDescriptorKindExclude +import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType import org.jetbrains.kotlin.psi.psiUtil.isAncestor +import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.resolve.bindingContextUtil.getDataFlowInfo +import org.jetbrains.kotlin.resolve.calls.smartcasts.SmartCastUtils +import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode +import org.jetbrains.kotlin.resolve.scopes.DescriptorKindExclude +import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter +import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull +import kotlin.properties.Delegates class CompletionSessionConfiguration( val completeNonImportedDeclarations: Boolean, @@ -88,18 +90,21 @@ abstract class CompletionSessionBase(protected val configuration: CompletionSess protected val bindingContext: BindingContext? = expression?.let { resolutionFacade.analyze(it, BodyResolveMode.PARTIAL_FOR_COMPLETION) } protected val inDescriptor: DeclarationDescriptor? = expression?.let { bindingContext!!.get(BindingContext.RESOLUTION_SCOPE, it)?.getContainingDeclaration() } + private fun singleCharPattern(char: Char): CharPattern { + return StandardPatterns.character().with( + object : PatternCondition(char.toString()) { + override fun accepts(c: Char, context: ProcessingContext) = c == char + }) + } + + private val kotlinIdentifierStartPattern = StandardPatterns.and(StandardPatterns.character().javaIdentifierStart(), StandardPatterns.not(singleCharPattern('$'))) + private val kotlinIdentifierPartPattern = StandardPatterns.and(StandardPatterns.character().javaIdentifierPart(), StandardPatterns.not(singleCharPattern('$'))) + protected val prefix: String = CompletionUtil.findIdentifierPrefix( parameters.getPosition().getContainingFile(), parameters.getOffset(), - StandardPatterns.or(StandardPatterns.character().javaIdentifierPart(), - StandardPatterns.character().with( - object : PatternCondition("@") { - override fun accepts(c: Char?, context: ProcessingContext?): Boolean { - return c == '@' - } - }) - ), - StandardPatterns.character().javaIdentifierStart()) + StandardPatterns.or(kotlinIdentifierPartPattern, singleCharPattern('@')), + kotlinIdentifierStartPattern) protected val resultSet: CompletionResultSet = resultSet .withPrefixMatcher(prefix) @@ -129,7 +134,8 @@ abstract class CompletionSessionBase(protected val configuration: CompletionSess LookupElementFactory(receiverTypes) } - protected val collector: LookupElementsCollector = LookupElementsCollector(prefixMatcher, parameters, resolutionFacade, lookupElementFactory) + protected val collector: LookupElementsCollector = LookupElementsCollector( + prefixMatcher, parameters, resolutionFacade, lookupElementFactory, expression?.getParent() is JetSimpleNameStringTemplateEntry) protected val project: Project = position.getProject() diff --git a/idea/src/org/jetbrains/kotlin/idea/completion/CompletionUtils.kt b/idea/src/org/jetbrains/kotlin/idea/completion/CompletionUtils.kt index 4c1ee730cce..95108b0abd9 100644 --- a/idea/src/org/jetbrains/kotlin/idea/completion/CompletionUtils.kt +++ b/idea/src/org/jetbrains/kotlin/idea/completion/CompletionUtils.kt @@ -89,6 +89,20 @@ fun LookupElement.withReceiverCast(): LookupElement { } } +fun LookupElement.withBracesSurrounding(): LookupElement { + return object: LookupElementDecorator(this) { + override fun handleInsert(context: InsertionContext) { + context.getDocument().insertString(context.getStartOffset(), "{") + + val tailOffset = context.getTailOffset() + context.getDocument().insertString(tailOffset, "}") + context.setTailOffset(tailOffset) + + super.handleInsert(context) + } + } +} + val KEEP_OLD_ARGUMENT_LIST_ON_TAB_KEY = Key("KEEP_OLD_ARGUMENT_LIST_ON_TAB_KEY") fun LookupElement.keepOldArgumentListOnTab(): LookupElement { diff --git a/idea/src/org/jetbrains/kotlin/idea/completion/LookupElementsCollector.kt b/idea/src/org/jetbrains/kotlin/idea/completion/LookupElementsCollector.kt index c6b601ce68f..2dec49e7cef 100644 --- a/idea/src/org/jetbrains/kotlin/idea/completion/LookupElementsCollector.kt +++ b/idea/src/org/jetbrains/kotlin/idea/completion/LookupElementsCollector.kt @@ -35,7 +35,8 @@ class LookupElementsCollector( private val prefixMatcher: PrefixMatcher, private val completionParameters: CompletionParameters, private val resolutionFacade: ResolutionFacade, - private val lookupElementFactory: LookupElementFactory + private val lookupElementFactory: LookupElementFactory, + private val surroundCallsWithBraces: Boolean ) { private val elements = ArrayList() @@ -62,9 +63,15 @@ class LookupElementsCollector( public fun addDescriptorElements(descriptor: DeclarationDescriptor, suppressAutoInsertion: Boolean, withReceiverCast: Boolean) { run { var lookupElement = lookupElementFactory.createLookupElement(resolutionFacade, descriptor, true) + if (withReceiverCast) { lookupElement = lookupElement.withReceiverCast() } + + if (surroundCallsWithBraces && descriptor is FunctionDescriptor) { + lookupElement = lookupElement.withBracesSurrounding() + } + if (suppressAutoInsertion) { addElementWithAutoInsertionSuppressed(lookupElement) } @@ -81,8 +88,9 @@ class LookupElementsCollector( if (KotlinBuiltIns.isFunctionOrExtensionFunctionType(parameterType)) { val parameterCount = KotlinBuiltIns.getParameterTypeProjectionsFromFunctionType(parameterType).size() if (parameterCount > 1) { - val lookupElement = lookupElementFactory.createLookupElement(resolutionFacade, descriptor, true) - addElement(object : LookupElementDecorator(lookupElement) { + var lookupElement = lookupElementFactory.createLookupElement(resolutionFacade, descriptor, true) + + lookupElement = object : LookupElementDecorator(lookupElement) { override fun renderElement(presentation: LookupElementPresentation) { super.renderElement(presentation) @@ -95,7 +103,13 @@ class LookupElementsCollector( override fun handleInsert(context: InsertionContext) { KotlinFunctionInsertHandler(CaretPosition.IN_BRACKETS, GenerateLambdaInfo(parameterType, true)).handleInsert(context, this) } - }) + } + + if (surroundCallsWithBraces) { + lookupElement = lookupElement.withBracesSurrounding() + } + + addElement(lookupElement) } } } diff --git a/idea/testData/completion/basic/common/StringTemplate1.kt b/idea/testData/completion/basic/common/StringTemplate1.kt new file mode 100644 index 00000000000..7d5854b7f04 --- /dev/null +++ b/idea/testData/completion/basic/common/StringTemplate1.kt @@ -0,0 +1,6 @@ +fun foo(param: String) { + val s = "$" +} + +// EXIST: foo +// EXIST: param diff --git a/idea/testData/completion/basic/common/StringTemplate2.kt b/idea/testData/completion/basic/common/StringTemplate2.kt new file mode 100644 index 00000000000..83bd658fedf --- /dev/null +++ b/idea/testData/completion/basic/common/StringTemplate2.kt @@ -0,0 +1,6 @@ +fun foo(param: String) { + val s = "${}" +} + +// EXIST: foo +// EXIST: param diff --git a/idea/testData/completion/handlers/basic/stringTemplate/1.kt b/idea/testData/completion/handlers/basic/stringTemplate/1.kt new file mode 100644 index 00000000000..f6397761c3c --- /dev/null +++ b/idea/testData/completion/handlers/basic/stringTemplate/1.kt @@ -0,0 +1,5 @@ +fun foo(): String { + val s = "$" +} + +// ELEMENT: foo diff --git a/idea/testData/completion/handlers/basic/stringTemplate/1.kt.after b/idea/testData/completion/handlers/basic/stringTemplate/1.kt.after new file mode 100644 index 00000000000..c87bad00ce5 --- /dev/null +++ b/idea/testData/completion/handlers/basic/stringTemplate/1.kt.after @@ -0,0 +1,5 @@ +fun foo(): String { + val s = "${foo()}" +} + +// ELEMENT: foo diff --git a/idea/testData/completion/handlers/basic/stringTemplate/2.kt b/idea/testData/completion/handlers/basic/stringTemplate/2.kt new file mode 100644 index 00000000000..dbfc3161278 --- /dev/null +++ b/idea/testData/completion/handlers/basic/stringTemplate/2.kt @@ -0,0 +1,5 @@ +fun foo(p: String): String { + val s = "$" +} + +// ELEMENT: foo diff --git a/idea/testData/completion/handlers/basic/stringTemplate/2.kt.after b/idea/testData/completion/handlers/basic/stringTemplate/2.kt.after new file mode 100644 index 00000000000..dd9ab98a12d --- /dev/null +++ b/idea/testData/completion/handlers/basic/stringTemplate/2.kt.after @@ -0,0 +1,5 @@ +fun foo(p: String): String { + val s = "${foo()}" +} + +// ELEMENT: foo diff --git a/idea/testData/completion/handlers/basic/stringTemplate/3.kt b/idea/testData/completion/handlers/basic/stringTemplate/3.kt new file mode 100644 index 00000000000..6a4db6e2599 --- /dev/null +++ b/idea/testData/completion/handlers/basic/stringTemplate/3.kt @@ -0,0 +1,5 @@ +fun foo(): String { + val s = "${}" +} + +// ELEMENT: foo diff --git a/idea/testData/completion/handlers/basic/stringTemplate/3.kt.after b/idea/testData/completion/handlers/basic/stringTemplate/3.kt.after new file mode 100644 index 00000000000..c87bad00ce5 --- /dev/null +++ b/idea/testData/completion/handlers/basic/stringTemplate/3.kt.after @@ -0,0 +1,5 @@ +fun foo(): String { + val s = "${foo()}" +} + +// ELEMENT: foo diff --git a/idea/testData/completion/handlers/basic/stringTemplate/4.kt b/idea/testData/completion/handlers/basic/stringTemplate/4.kt new file mode 100644 index 00000000000..fa7ae139387 --- /dev/null +++ b/idea/testData/completion/handlers/basic/stringTemplate/4.kt @@ -0,0 +1,5 @@ +fun foo(param: Any): String { + val s = "${}" +} + +// ELEMENT: param diff --git a/idea/testData/completion/handlers/basic/stringTemplate/4.kt.after b/idea/testData/completion/handlers/basic/stringTemplate/4.kt.after new file mode 100644 index 00000000000..5595753fa10 --- /dev/null +++ b/idea/testData/completion/handlers/basic/stringTemplate/4.kt.after @@ -0,0 +1,5 @@ +fun foo(param: Any): String { + val s = "${param}" +} + +// ELEMENT: param diff --git a/idea/testData/completion/handlers/basic/stringTemplate/NotEmptyPrefix.kt b/idea/testData/completion/handlers/basic/stringTemplate/NotEmptyPrefix.kt new file mode 100644 index 00000000000..f68380e7fd6 --- /dev/null +++ b/idea/testData/completion/handlers/basic/stringTemplate/NotEmptyPrefix.kt @@ -0,0 +1,7 @@ +fun bar() {} + +fun test(){ + "$b" +} + +// ELEMENT: bar diff --git a/idea/testData/completion/handlers/basic/stringTemplate/NotEmptyPrefix.kt.after b/idea/testData/completion/handlers/basic/stringTemplate/NotEmptyPrefix.kt.after new file mode 100644 index 00000000000..b546ad5d4c2 --- /dev/null +++ b/idea/testData/completion/handlers/basic/stringTemplate/NotEmptyPrefix.kt.after @@ -0,0 +1,7 @@ +fun bar() {} + +fun test(){ + "${bar()}" +} + +// ELEMENT: bar diff --git a/idea/testData/completion/handlers/basic/stringTemplate/Replace.kt b/idea/testData/completion/handlers/basic/stringTemplate/Replace.kt new file mode 100644 index 00000000000..59cee4df8d8 --- /dev/null +++ b/idea/testData/completion/handlers/basic/stringTemplate/Replace.kt @@ -0,0 +1,6 @@ +fun foo(): String { + val s = "$xxx" +} + +// ELEMENT: foo +// CHAR: \t diff --git a/idea/testData/completion/handlers/basic/stringTemplate/Replace.kt.after b/idea/testData/completion/handlers/basic/stringTemplate/Replace.kt.after new file mode 100644 index 00000000000..2358c2ba92d --- /dev/null +++ b/idea/testData/completion/handlers/basic/stringTemplate/Replace.kt.after @@ -0,0 +1,6 @@ +fun foo(): String { + val s = "${foo()}" +} + +// ELEMENT: foo +// CHAR: \t diff --git a/idea/tests/org/jetbrains/kotlin/completion/JSBasicCompletionTestGenerated.java b/idea/tests/org/jetbrains/kotlin/completion/JSBasicCompletionTestGenerated.java index 5bdc27de284..78383b9f8ba 100644 --- a/idea/tests/org/jetbrains/kotlin/completion/JSBasicCompletionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/completion/JSBasicCompletionTestGenerated.java @@ -883,6 +883,18 @@ public class JSBasicCompletionTestGenerated extends AbstractJSBasicCompletionTes doTest(fileName); } + @TestMetadata("StringTemplate1.kt") + public void testStringTemplate1() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/basic/common/StringTemplate1.kt"); + doTest(fileName); + } + + @TestMetadata("StringTemplate2.kt") + public void testStringTemplate2() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/basic/common/StringTemplate2.kt"); + doTest(fileName); + } + @TestMetadata("SubpackageInFun.kt") public void testSubpackageInFun() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/basic/common/SubpackageInFun.kt"); diff --git a/idea/tests/org/jetbrains/kotlin/completion/JvmBasicCompletionTestGenerated.java b/idea/tests/org/jetbrains/kotlin/completion/JvmBasicCompletionTestGenerated.java index 83031eab4a7..4c359b29cf2 100644 --- a/idea/tests/org/jetbrains/kotlin/completion/JvmBasicCompletionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/completion/JvmBasicCompletionTestGenerated.java @@ -883,6 +883,18 @@ public class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCompletionT doTest(fileName); } + @TestMetadata("StringTemplate1.kt") + public void testStringTemplate1() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/basic/common/StringTemplate1.kt"); + doTest(fileName); + } + + @TestMetadata("StringTemplate2.kt") + public void testStringTemplate2() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/basic/common/StringTemplate2.kt"); + doTest(fileName); + } + @TestMetadata("SubpackageInFun.kt") public void testSubpackageInFun() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/basic/common/SubpackageInFun.kt"); diff --git a/idea/tests/org/jetbrains/kotlin/completion/handlers/AbstractCompletionHandlerTests.kt b/idea/tests/org/jetbrains/kotlin/completion/handlers/AbstractCompletionHandlerTests.kt index 0ea11ca0237..cfcd1b0a2ad 100644 --- a/idea/tests/org/jetbrains/kotlin/completion/handlers/AbstractCompletionHandlerTests.kt +++ b/idea/tests/org/jetbrains/kotlin/completion/handlers/AbstractCompletionHandlerTests.kt @@ -17,11 +17,12 @@ package org.jetbrains.kotlin.completion.handlers import com.intellij.codeInsight.completion.CompletionType -import org.jetbrains.kotlin.test.InTextDirectivesUtils import com.intellij.openapi.util.io.FileUtil +import org.jetbrains.kotlin.idea.JetLightProjectDescriptor +import org.jetbrains.kotlin.test.InTextDirectivesUtils import java.io.File -public abstract class AbstractCompletionHandlerTest : CompletionHandlerTestBase() { +public abstract class AbstractCompletionHandlerTest(private val defaultCompletionType: CompletionType) : CompletionHandlerTestBase() { private val INVOCATION_COUNT_PREFIX = "INVOCATION_COUNT:" private val LOOKUP_STRING_PREFIX = "ELEMENT:" private val ELEMENT_TEXT_PREFIX = "ELEMENT_TEXT:" @@ -53,32 +54,20 @@ public abstract class AbstractCompletionHandlerTest : CompletionHandlerTestBase( else -> error("Unknown completion type: $completionTypeString") } - doTestWithTextLoaded(completionType, invocationCount, lookupString, itemText, tailText, completionChar) + doTestWithTextLoaded(completionType, invocationCount, lookupString, itemText, tailText, completionChar, testPath + ".after") } protected open fun setUpFixture(testPath: String) { fixture.configureByFile(testPath) } - protected abstract val defaultCompletionType: CompletionType + override fun getProjectDescriptor() = JetLightProjectDescriptor.INSTANCE } -public abstract class AbstractBasicCompletionHandlerTest() : AbstractCompletionHandlerTest() { - override val defaultCompletionType: CompletionType = CompletionType.BASIC - override val testDataRelativePath: String = "/completion/handlers/basic" -} +public abstract class AbstractBasicCompletionHandlerTest() : AbstractCompletionHandlerTest(CompletionType.BASIC) -public abstract class AbstractSmartCompletionHandlerTest() : AbstractCompletionHandlerTest() { - override val defaultCompletionType: CompletionType = CompletionType.SMART - override val testDataRelativePath: String = "/completion/handlers/smart" -} +public abstract class AbstractSmartCompletionHandlerTest() : AbstractCompletionHandlerTest(CompletionType.SMART) -public abstract class AbstractCompletionCharFilterTest() : AbstractCompletionHandlerTest() { - override val defaultCompletionType: CompletionType = CompletionType.BASIC - override val testDataRelativePath: String = "/completion/handlers/charFilter" -} +public abstract class AbstractCompletionCharFilterTest() : AbstractCompletionHandlerTest(CompletionType.BASIC) -public abstract class AbstractKeywordCompletionHandlerTest() : AbstractCompletionHandlerTest() { - override val defaultCompletionType: CompletionType = CompletionType.BASIC - override val testDataRelativePath: String = "/completion/handlers/keywords" -} +public abstract class AbstractKeywordCompletionHandlerTest() : AbstractCompletionHandlerTest(CompletionType.BASIC) diff --git a/idea/tests/org/jetbrains/kotlin/completion/handlers/BasicCompletionHandlerTest.kt b/idea/tests/org/jetbrains/kotlin/completion/handlers/BasicCompletionHandlerTest.kt index ccd3d32655b..353617b5370 100644 --- a/idea/tests/org/jetbrains/kotlin/completion/handlers/BasicCompletionHandlerTest.kt +++ b/idea/tests/org/jetbrains/kotlin/completion/handlers/BasicCompletionHandlerTest.kt @@ -17,12 +17,18 @@ package org.jetbrains.kotlin.completion.handlers import com.intellij.codeInsight.completion.CompletionType -import org.jetbrains.kotlin.idea.formatter.JetCodeStyleSettings import com.intellij.psi.codeStyle.CodeStyleSettingsManager +import org.jetbrains.kotlin.idea.PluginTestCaseBase +import org.jetbrains.kotlin.idea.formatter.JetCodeStyleSettings +import java.io.File deprecated("All tests from here to be moved to the generated test") public class BasicCompletionHandlerTest : CompletionHandlerTestBase(){ - override val testDataRelativePath: String = "/completion/handlers" + private fun checkResult(){ + fixture.checkResultByFile(getTestName(false) + ".kt.after") + } + + override fun getTestDataPath() = File(PluginTestCaseBase.getTestDataPathBase(), "/completion/handlers").getPath() + File.separator private fun doTest() { doTest(2, "*", null, null, '\n') @@ -34,7 +40,7 @@ public class BasicCompletionHandlerTest : CompletionHandlerTestBase(){ private fun doTest(time: Int, lookupString: String?, itemText: String?, tailText: String?, completionChar: Char) { fixture.configureByFile(fileName()) - doTestWithTextLoaded(CompletionType.BASIC, time, lookupString, itemText, tailText, completionChar) + doTestWithTextLoaded(CompletionType.BASIC, time, lookupString, itemText, tailText, completionChar, fileName() + ".after") } fun testClassCompletionImport() = doTest(2, "SortedSet", null, '\n') diff --git a/idea/tests/org/jetbrains/kotlin/completion/handlers/BasicCompletionHandlerTestGenerated.java b/idea/tests/org/jetbrains/kotlin/completion/handlers/BasicCompletionHandlerTestGenerated.java index 74dd11a39ee..010ec4ebf70 100644 --- a/idea/tests/org/jetbrains/kotlin/completion/handlers/BasicCompletionHandlerTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/completion/handlers/BasicCompletionHandlerTestGenerated.java @@ -30,6 +30,9 @@ import java.util.regex.Pattern; @SuppressWarnings("all") @TestMetadata("idea/testData/completion/handlers/basic") @TestDataPath("$PROJECT_ROOT") +@InnerTestClasses({ + BasicCompletionHandlerTestGenerated.StringTemplate.class, +}) @RunWith(JUnit3RunnerWithInners.class) public class BasicCompletionHandlerTestGenerated extends AbstractBasicCompletionHandlerTest { public void testAllFilesPresentInBasic() throws Exception { @@ -77,4 +80,49 @@ public class BasicCompletionHandlerTestGenerated extends AbstractBasicCompletion String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/handlers/basic/SuperTypeArg.kt"); doTest(fileName); } + + @TestMetadata("idea/testData/completion/handlers/basic/stringTemplate") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class StringTemplate extends AbstractBasicCompletionHandlerTest { + @TestMetadata("1.kt") + public void test1() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/handlers/basic/stringTemplate/1.kt"); + doTest(fileName); + } + + @TestMetadata("2.kt") + public void test2() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/handlers/basic/stringTemplate/2.kt"); + doTest(fileName); + } + + @TestMetadata("3.kt") + public void test3() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/handlers/basic/stringTemplate/3.kt"); + doTest(fileName); + } + + @TestMetadata("4.kt") + public void test4() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/handlers/basic/stringTemplate/4.kt"); + doTest(fileName); + } + + public void testAllFilesPresentInStringTemplate() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/completion/handlers/basic/stringTemplate"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("NotEmptyPrefix.kt") + public void testNotEmptyPrefix() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/handlers/basic/stringTemplate/NotEmptyPrefix.kt"); + doTest(fileName); + } + + @TestMetadata("Replace.kt") + public void testReplace() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/handlers/basic/stringTemplate/Replace.kt"); + doTest(fileName); + } + } } diff --git a/idea/tests/org/jetbrains/kotlin/completion/handlers/CompletionHandlerTestBase.kt b/idea/tests/org/jetbrains/kotlin/completion/handlers/CompletionHandlerTestBase.kt index 1a34f4a8b84..bf6d1417a81 100644 --- a/idea/tests/org/jetbrains/kotlin/completion/handlers/CompletionHandlerTestBase.kt +++ b/idea/tests/org/jetbrains/kotlin/completion/handlers/CompletionHandlerTestBase.kt @@ -16,23 +16,20 @@ package org.jetbrains.kotlin.completion.handlers -import org.jetbrains.kotlin.idea.JetLightCodeInsightFixtureTestCase import com.intellij.codeInsight.completion.CompletionType import com.intellij.codeInsight.lookup.LookupElement -import java.io.File -import org.jetbrains.kotlin.idea.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.codeInsight.lookup.LookupEvent +import com.intellij.codeInsight.lookup.LookupManager +import com.intellij.codeInsight.lookup.impl.LookupImpl import com.intellij.openapi.application.Result +import com.intellij.openapi.command.WriteCommandAction import com.intellij.testFramework.fixtures.JavaCodeInsightTestFixture +import org.jetbrains.kotlin.idea.JetLightCodeInsightFixtureTestCase +import org.jetbrains.kotlin.test.JetTestUtils +import org.junit.Assert public abstract class CompletionHandlerTestBase() : JetLightCodeInsightFixtureTestCase() { - protected abstract val testDataRelativePath: String - protected val fixture: JavaCodeInsightTestFixture get() = myFixture @@ -42,7 +39,8 @@ public abstract class CompletionHandlerTestBase() : JetLightCodeInsightFixtureTe lookupString: String?, itemText: String?, tailText: String?, - completionChar: Char + completionChar: Char, + afterFilePath: String ) { fixture.complete(completionType, time) @@ -53,11 +51,7 @@ public abstract class CompletionHandlerTestBase() : JetLightCodeInsightFixtureTe } } - checkResult() - } - - protected fun checkResult(){ - fixture.checkResultByFile(afterFileName()) + fixture.checkResultByFile(afterFilePath) } private fun getExistentLookupElement(lookupString: String?, itemText: String?, tailText: String?): LookupElement? { @@ -111,13 +105,7 @@ public abstract class CompletionHandlerTestBase() : JetLightCodeInsightFixtureTe return foundElement } - protected fun afterFileName(): String = getTestName(false) + ".kt.after" - - protected override fun getTestDataPath() : String = File(PluginTestCaseBase.getTestDataPathBase(), testDataRelativePath).getPath() + File.separator - - protected fun selectItem(item: LookupElement?) { - selectItem(item, 0.toChar()) - } + override fun getTestDataPath() = JetTestUtils.getHomeDirectory() protected fun selectItem(item: LookupElement?, completionChar: Char) { val lookup = (fixture.getLookup() as LookupImpl) diff --git a/idea/tests/org/jetbrains/kotlin/idea/debugger/evaluate/AbstractEditorForEvaluateExpressionTest.kt b/idea/tests/org/jetbrains/kotlin/idea/debugger/evaluate/AbstractEditorForEvaluateExpressionTest.kt index 5310b0d3047..a74a63778ea 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/debugger/evaluate/AbstractEditorForEvaluateExpressionTest.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/debugger/evaluate/AbstractEditorForEvaluateExpressionTest.kt @@ -78,13 +78,10 @@ public abstract class AbstractCodeFragmentCompletionTest : AbstractJvmBasicCompl } } -public abstract class AbstractCodeFragmentCompletionHandlerTest : AbstractCompletionHandlerTest() { +public abstract class AbstractCodeFragmentCompletionHandlerTest : AbstractCompletionHandlerTest(CompletionType.BASIC) { override fun setUpFixture(testPath: String) { myFixture.configureByCodeFragment(testPath) } - - override val testDataRelativePath: String = "/completion/handlers/runtimeCast/" - override val defaultCompletionType: CompletionType = CompletionType.BASIC } private fun JavaCodeInsightTestFixture.configureByCodeFragment(filePath: String) {