Smart completion: offer class instantiating choice

This commit is contained in:
Valentin Kipyatkov
2013-11-12 16:16:59 +04:00
parent 80ab043d21
commit 2d3b0ffc0b
33 changed files with 404 additions and 119 deletions
@@ -7,6 +7,14 @@
name='com.intellij.codeInsight.completion.CompletionSorter com.intellij.codeInsight.completion.CompletionSorter weighBefore(java.lang.String, com.intellij.codeInsight.lookup.LookupElementWeigher...)'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
<item
name='com.intellij.codeInsight.completion.InsertHandler void handleInsert(com.intellij.codeInsight.completion.InsertionContext, T) 0'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
<item
name='com.intellij.codeInsight.completion.InsertHandler void handleInsert(com.intellij.codeInsight.completion.InsertionContext, T) 1'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
<item name='com.intellij.codeInsight.completion.InsertionContext com.intellij.openapi.project.Project getProject()'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
@@ -6,4 +6,24 @@
<item name='com.intellij.codeInsight.lookup.Lookup com.intellij.openapi.editor.Editor getEditor()'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
<item
name='com.intellij.codeInsight.lookup.LookupElementBuilder com.intellij.codeInsight.lookup.LookupElementBuilder withInsertHandler(com.intellij.codeInsight.completion.InsertHandler&lt;com.intellij.codeInsight.lookup.LookupElement&gt;)'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
<item
name='com.intellij.codeInsight.lookup.LookupElementBuilder com.intellij.codeInsight.lookup.LookupElementBuilder withPresentableText(java.lang.String)'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
<item
name='com.intellij.codeInsight.lookup.LookupElementBuilder com.intellij.codeInsight.lookup.LookupElementBuilder withTailText(java.lang.String)'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
<item
name='com.intellij.codeInsight.lookup.MutableLookupElement com.intellij.codeInsight.lookup.MutableLookupElement&lt;T&gt; setInsertHandler(com.intellij.codeInsight.completion.InsertHandler&lt;? extends com.intellij.codeInsight.lookup.LookupElement&gt;)'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
<item
name='com.intellij.codeInsight.lookup.MutableLookupElement com.intellij.codeInsight.lookup.MutableLookupElement&lt;T&gt; setInsertHandler(com.intellij.codeInsight.completion.InsertHandler&lt;? extends com.intellij.codeInsight.lookup.LookupElement&gt;) 0'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
</root>
@@ -1,4 +1,7 @@
<root>
<item name='com.intellij.psi.PsiDocumentManager com.intellij.psi.PsiDocumentManager getInstance(com.intellij.openapi.project.Project)'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
<item
name='com.intellij.psi.PsiReferenceService java.util.List&lt;com.intellij.psi.PsiReference&gt; getReferences(com.intellij.psi.PsiElement, com.intellij.psi.PsiReferenceService.Hints)'>
<annotation name='org.jetbrains.annotations.NotNull'/>
@@ -22,6 +22,7 @@ import com.intellij.codeInsight.completion.CompletionParameters;
import com.intellij.codeInsight.completion.CompletionResultSet;
import com.intellij.codeInsight.completion.CompletionType;
import com.intellij.codeInsight.completion.JavaCompletionContributor;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.Conditions;
@@ -133,14 +134,17 @@ class CompletionSession {
assert parameters.getCompletionType() == CompletionType.SMART;
//noinspection StaticMethodReferencedViaSubclass
final SmartCompletionFilter filter = CompletionPackage.buildSmartCompletionFilter(jetReference.getExpression(), getResolveSession());
if (filter != null) {
final SmartCompletionData data = CompletionPackage.buildSmartCompletionData(jetReference.getExpression(), getResolveSession());
if (data != null) {
addReferenceVariants(new Condition<DeclarationDescriptor>() {
@Override
public boolean value(DeclarationDescriptor descriptor) {
return filter.accepts(descriptor);
return data.accepts(descriptor);
}
});
for (LookupElement element : data.getAdditionalElements()) {
jetResult.addElement(element);
}
}
}
@@ -1,29 +1,74 @@
package org.jetbrains.jet.plugin.completion
import com.intellij.codeInsight.completion.*
import com.intellij.util.*
import org.jetbrains.jet.lang.descriptors.*
import org.jetbrains.jet.lang.resolve.*
import org.jetbrains.jet.lang.psi.*
import org.jetbrains.jet.lexer.JetToken
import org.jetbrains.jet.lexer.JetTokens
import org.jetbrains.jet.plugin.project.CancelableResolveSession
import org.jetbrains.jet.lang.types.JetType
import org.jetbrains.jet.lang.types.*
import org.jetbrains.jet.lang.types.checker.JetTypeChecker
import com.intellij.codeInsight.lookup.*
import java.util.ArrayList
import org.jetbrains.jet.renderer.DescriptorRenderer
import com.intellij.codeInsight.completion.InsertionContext
import com.intellij.codeInsight.completion.InsertHandler
import org.jetbrains.jet.plugin.completion.handlers.*
import com.intellij.codeInsight.completion.JavaPsiClassReferenceElement
trait SmartCompletionFilter{
trait SmartCompletionData{
fun accepts(descriptor: DeclarationDescriptor): Boolean
val additionalElements: Iterable<LookupElement>
}
fun buildSmartCompletionFilter(expression: JetSimpleNameExpression, resolveSession: CancelableResolveSession): SmartCompletionFilter? {
fun buildSmartCompletionData(expression: JetSimpleNameExpression, resolveSession: CancelableResolveSession): SmartCompletionData? {
val parent = expression.getParent()
val expressionWithType = if (parent is JetQualifiedExpression) parent else expression
val expectedType: JetType? = resolveSession.resolveToElement(expressionWithType).get(BindingContext.EXPECTED_EXPRESSION_TYPE, expressionWithType)
val bindingContext = resolveSession.resolveToElement(expressionWithType)
val expectedType: JetType? = bindingContext.get(BindingContext.EXPECTED_EXPRESSION_TYPE, expressionWithType)
if (expectedType == null) return null
val itemsToSkip = calcItemsToSkip(expressionWithType, resolveSession)
return object: SmartCompletionFilter{
val additionalElements = ArrayList<LookupElement>()
if (expression == expressionWithType) { // no qualifier
val typeConstructor: TypeConstructor = expectedType.getConstructor()
val classifier: ClassifierDescriptor? = typeConstructor.getDeclarationDescriptor()
if (classifier is ClassDescriptor) {
if (classifier.getModality() != Modality.ABSTRACT){
val lookupElement = DescriptorLookupConverter.createLookupElement(resolveSession, bindingContext, classifier)
val typeArgs = expectedType.getArguments()
//TODO: shouldn't be method in DescriptorRenderer to render type arguments?
val typeArgsText =
if (typeArgs.isEmpty())
""
else
typeArgs.map { DescriptorRenderer.TEXT.renderType(it.getType()) }.makeString(", ", "<", ">")
val presentableText = lookupElement.getLookupString() + typeArgsText + "()"
val constructors: Collection<ConstructorDescriptor> = classifier.getConstructors()
val caretPosition =
if (constructors.size == 0)
CaretPosition.AFTER_BRACKETS
else if (constructors.size == 1)
if (constructors.first().getValueParameters().isEmpty()) CaretPosition.AFTER_BRACKETS else CaretPosition.IN_BRACKETS
else
CaretPosition.IN_BRACKETS
val insertHandler = JetFunctionInsertHandler(caretPosition, BracketType.PARENTHESIS)
//TODO: very bad code
if (lookupElement is LookupElementBuilder) {
additionalElements.add(lookupElement.withPresentableText(presentableText).withInsertHandler(insertHandler))
}
else if (lookupElement is JavaPsiClassReferenceElement) {
additionalElements.add(lookupElement.setPresentableText(presentableText).setInsertHandler(insertHandler))
}
}
}
}
return object: SmartCompletionData{
override fun accepts(descriptor: DeclarationDescriptor): Boolean {
if (itemsToSkip.contains(descriptor)) return false
@@ -35,6 +80,8 @@ fun buildSmartCompletionFilter(expression: JetSimpleNameExpression, resolveSessi
return false
}
}
override val additionalElements: Iterable<LookupElement> = additionalElements
}
}
@@ -45,18 +45,16 @@ public enum class BracketType {
BRACES
}
public class JetFunctionInsertHandler(val caretPosition : CaretPosition, val bracketType : BracketType) : InsertHandler<LookupElement?> {
public class JetFunctionInsertHandler(val caretPosition : CaretPosition, val bracketType : BracketType) : InsertHandler<LookupElement> {
{
if (caretPosition == CaretPosition.AFTER_BRACKETS && bracketType == BracketType.BRACES) {
throw IllegalArgumentException("CaretPosition.AFTER_BRACKETS with bracketType == BracketType.BRACES combination is not supported")
}
}
public override fun handleInsert(context: InsertionContext?, item: LookupElement?) {
if (context == null || item == null) return
PsiDocumentManager.getInstance(context.getProject())?.commitAllDocuments()
if ((context.getCompletionChar()) == '(') {
public override fun handleInsert(context: InsertionContext, item: LookupElement) {
PsiDocumentManager.getInstance(context.getProject()).commitAllDocuments()
if (context.getCompletionChar() == '(') {
context.setAddCompletionChar(false)
}
@@ -105,7 +103,7 @@ public class JetFunctionInsertHandler(val caretPosition : CaretPosition, val bra
else {
document.insertString(offset, "()")
}
PsiDocumentManager.getInstance(context.getProject())?.commitDocument(document)
PsiDocumentManager.getInstance(context.getProject()).commitDocument(document)
documentText = document.getText()
}
@@ -125,7 +123,7 @@ public class JetFunctionInsertHandler(val caretPosition : CaretPosition, val bra
editor.getCaretModel().moveToOffset(closeBracketIndex + 1)
}
PsiDocumentManager.getInstance(context.getProject())?.commitDocument(context.getDocument())
PsiDocumentManager.getInstance(context.getProject()).commitDocument(context.getDocument())
}
class object {
@@ -0,0 +1,3 @@
class Foo
var a : Foo = <caret>
@@ -0,0 +1,3 @@
class Foo
var a : Foo = Foo()<caret>
@@ -0,0 +1,3 @@
import java.util.Date
var a : Date = <caret>
@@ -0,0 +1,3 @@
import java.util.Date
var a : Date = Date(<caret>)
@@ -0,0 +1,5 @@
class Foo
fun foo(p : Object){
var a : Foo? = <caret>
}
@@ -0,0 +1,5 @@
class Foo
fun foo(p : Object){
var a : Foo? = Foo()<caret>
}
@@ -0,0 +1,5 @@
fun foo(p: java.util.BitSet){}
fun f(){
foo(<caret>)
}
@@ -0,0 +1,7 @@
import java.util.BitSet
fun foo(p: java.util.BitSet){}
fun f(){
foo(BitSet(<caret>))
}
@@ -0,0 +1,3 @@
class Foo(p : Int)
var a : Foo = <caret>
@@ -0,0 +1,3 @@
class Foo(p : Int)
var a : Foo = Foo(<caret>)
@@ -0,0 +1,5 @@
class Foo
var a : Foo = <caret>
// EXIST: Foo@Foo()
@@ -0,0 +1,5 @@
import java.util.ArrayList
var a : ArrayList<String> = <caret>
// EXIST: ArrayList@ArrayList<String>()
@@ -0,0 +1,7 @@
class Foo<T>
fun foo(p : Object){
var a : Foo<String> = <caret>
}
// EXIST: Foo@Foo<jet.String>()
@@ -0,0 +1,5 @@
import java.util.Date
var a : Date = <caret>
// EXIST: Date@Date()
@@ -0,0 +1,7 @@
class Foo
fun foo(p : Object){
var a : Foo? = <caret>
}
// EXIST: Foo@Foo()
@@ -1,5 +1,5 @@
class Foo
class Bar : Foo
open class Foo
class Bar : Foo()
val foo = Foo()
val bar = Bar()
@@ -24,3 +24,4 @@ fun f3() : String{}
// EXIST: f1
// EXIST: f2
// ABSENT: f3
// EXIST: Foo@Foo()
@@ -1,5 +1,5 @@
class Foo
class Bar : Foo
open class Foo
class Bar : Foo()
val xfoo = Foo()
val xbar = Bar()
@@ -0,0 +1,7 @@
abstract class Foo
fun foo(p : Object){
var a : Foo = <caret>
}
// ABSENT: Foo
@@ -0,0 +1,3 @@
var a : Appendable = <caret>
// ABSENT: Appendable
@@ -0,0 +1,7 @@
trait Foo
fun foo(p : Object){
var a : Foo = <caret>
}
// ABSENT: Foo
@@ -0,0 +1,7 @@
class Foo
fun foo(p : Object){
var a : Foo = p.<caret>
}
// ABSENT: Foo
+2 -2
View File
@@ -1,5 +1,5 @@
class Foo
class Bar : Foo
open class Foo
class Bar : Foo()
val xfoo = Foo()
val xbar = Bar()
@@ -30,17 +30,30 @@ public abstract class JetFixtureCompletionBaseTestCase extends LightCodeInsightF
protected void setUp() throws Exception {
super.setUp();
autocompleteSetting = CodeInsightSettings.getInstance().AUTOCOMPLETE_ON_CODE_COMPLETION;
CodeInsightSettings.getInstance().AUTOCOMPLETE_ON_CODE_COMPLETION = false;
autocompleteSetting = setAutocompleteSetting(false);
}
@Override
protected void tearDown() throws Exception {
CodeInsightSettings.getInstance().AUTOCOMPLETE_ON_CODE_COMPLETION = autocompleteSetting;
setAutocompleteSetting(autocompleteSetting);
super.tearDown();
}
private boolean setAutocompleteSetting(boolean value){
CodeInsightSettings settings = CodeInsightSettings.getInstance();
boolean oldValue;
if (completionType() == CompletionType.SMART){
oldValue = settings.AUTOCOMPLETE_ON_SMART_TYPE_COMPLETION;
settings.AUTOCOMPLETE_ON_SMART_TYPE_COMPLETION = value;
}
else{
oldValue = settings.AUTOCOMPLETE_COMMON_PREFIX;
settings.AUTOCOMPLETE_ON_CODE_COMPLETION = value;
}
return oldValue;
}
public abstract TargetPlatform getPlatform();
@NotNull
@@ -41,6 +41,21 @@ public class JetSmartCompletionTestGenerated extends AbstractJvmSmartCompletionT
doTest("idea/testData/completion/smart/ChainedCall.kt");
}
@TestMetadata("Constructor.kt")
public void testConstructor() throws Exception {
doTest("idea/testData/completion/smart/Constructor.kt");
}
@TestMetadata("ConstructorForGenericType.kt")
public void testConstructorForGenericType() throws Exception {
doTest("idea/testData/completion/smart/ConstructorForGenericType.kt");
}
@TestMetadata("ConstructorForNullable.kt")
public void testConstructorForNullable() throws Exception {
doTest("idea/testData/completion/smart/ConstructorForNullable.kt");
}
@TestMetadata("EmptyPrefix.kt")
public void testEmptyPrefix() throws Exception {
doTest("idea/testData/completion/smart/EmptyPrefix.kt");
@@ -56,6 +71,26 @@ public class JetSmartCompletionTestGenerated extends AbstractJvmSmartCompletionT
doTest("idea/testData/completion/smart/MethodCallArgument.kt");
}
@TestMetadata("NoConstructorForAbstract.kt")
public void testNoConstructorForAbstract() throws Exception {
doTest("idea/testData/completion/smart/NoConstructorForAbstract.kt");
}
@TestMetadata("NoConstructorForJavaInterface.kt")
public void testNoConstructorForJavaInterface() throws Exception {
doTest("idea/testData/completion/smart/NoConstructorForJavaInterface.kt");
}
@TestMetadata("NoConstructorForTrait.kt")
public void testNoConstructorForTrait() throws Exception {
doTest("idea/testData/completion/smart/NoConstructorForTrait.kt");
}
@TestMetadata("NoConstructorWithQualifier.kt")
public void testNoConstructorWithQualifier() throws Exception {
doTest("idea/testData/completion/smart/NoConstructorWithQualifier.kt");
}
@TestMetadata("NoSillyAssignment.kt")
public void testNoSillyAssignment() throws Exception {
doTest("idea/testData/completion/smart/NoSillyAssignment.kt");
@@ -0,0 +1,93 @@
package org.jetbrains.jet.completion.handlers
import com.intellij.codeInsight.completion.CompletionType
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"
fun testClassCompletionImport() = doTest(2, "SortedSet", null, '\n')
fun testDoNotInsertImportForAlreadyImported() = doTest()
fun testDoNotInsertDefaultJsImports() = doTest()
fun testDoNotInsertImportIfResolvedIntoJavaConstructor() = doTest()
fun testNonStandardArray() = doTest(2, "Array", "java.lang.reflect", '\n')
fun testNoParamsFunction() = doTest()
fun testParamsFunction() = doTest()
fun testInsertJavaClassImport() = doTest()
fun testInsertVoidJavaMethod() = doTest()
fun testPropertiesSetter() = doTest()
fun testExistingSingleBrackets() = doTest()
fun testExtFunction() = doTest()
fun testFunctionLiteralInsertOnSpace() = doTest(2, null, null, ' ')
fun testInsertImportOnTab() = doTest(2, "ArrayList", null, '\t')
fun testHigherOrderFunction() = doTest()
fun testInsertFqnForJavaClass() = doTest(2, "SortedSet", "java.util", '\n')
fun testHigherOrderFunctionWithArg() = doTest(2, "filterNot", null, '\n')
fun testForceParenthesisForTabChar() = doTest(0, "some", null, '\t')
fun testTabInsertAtTheFileEnd() = doTest(0, "vvvvv", null, '\t')
fun testTabInsertBeforeBraces() = doTest(0, "vvvvv", null, '\t')
fun testTabInsertBeforeBrackets() = doTest(0, "vvvvv", null, '\t')
fun testTabInsertBeforeOperator() = doTest(0, "vvvvv", null, '\t')
fun testTabInsertBeforeParentheses() = doTest(0, "vvvvv", null, '\t')
fun testTabInsertInsideBraces() = doTest(0, "vvvvv", null, '\t')
fun testTabInsertInsideBrackets() = doTest(0, "vvvvv", null, '\t')
fun testTabInsertInsideEmptyParentheses() = doTest(0, "vvvvv", null, '\t')
fun testTabInsertInsideParentheses() = doTest(0, "vvvvv", null, '\t')
fun testTabInsertInSimpleName() = doTest(0, "vvvvv", null, '\t')
fun testInsertFunctionWithSingleParameterWithBrace() = doTest(0, "some", null, '{')
fun testSingleBrackets() {
fixture.configureByFile(fileName())
fixture.`type`('(')
checkResult()
}
fun testInsertFunctionWithBothParentheses() {
fixture.configureByFile(fileName())
fixture.`type`("test()")
checkResult()
}
fun testFunctionLiteralInsertWhenNoSpacesForBraces() {
val settings = CodeStyleSettingsManager.getSettings(getProject())
val jetSettings = settings.getCustomSettings(javaClass<JetCodeStyleSettings>())!!
try {
jetSettings.INSERT_WHITESPACES_IN_SIMPLE_ONE_LINE_METHOD = false
doTest()
}
finally {
jetSettings.INSERT_WHITESPACES_IN_SIMPLE_ONE_LINE_METHOD = true
}
}
}
@@ -32,112 +32,37 @@ import org.junit.Assert
import com.intellij.openapi.application.Result
import com.intellij.testFramework.fixtures.JavaCodeInsightTestFixture
import kotlin.properties.Delegates
import com.intellij.openapi.util.io.FileUtil
public class CompletionHandlerTest() : JetLightCodeInsightFixtureTestCase() {
fun testClassCompletionImport() = doTest(CompletionType.BASIC, 2, "SortedSet", null, '\n')
public abstract class CompletionHandlerTestBase() : JetLightCodeInsightFixtureTestCase() {
protected abstract val completionType : CompletionType
protected abstract val testDataRelativePath: String
fun testDoNotInsertImportForAlreadyImported() = doTest()
fun testDoNotInsertDefaultJsImports() = doTest()
fun testDoNotInsertImportIfResolvedIntoJavaConstructor() = doTest()
fun testNonStandardArray() = doTest(CompletionType.BASIC, 2, "Array", "java.lang.reflect", '\n')
fun testNoParamsFunction() = doTest()
fun testParamsFunction() = doTest()
fun testInsertJavaClassImport() = doTest()
fun testInsertVoidJavaMethod() = doTest()
fun testPropertiesSetter() = doTest()
fun testExistingSingleBrackets() = doTest()
fun testExtFunction() = doTest()
fun testFunctionLiteralInsertOnSpace() = doTest(CompletionType.BASIC, 2, null, null, ' ')
fun testInsertImportOnTab() = doTest(CompletionType.BASIC, 2, "ArrayList", null, '\t')
fun testHigherOrderFunction() = doTest()
fun testInsertFqnForJavaClass() = doTest(CompletionType.BASIC, 2, "SortedSet", "java.util", '\n')
fun testHigherOrderFunctionWithArg() = doTest(CompletionType.BASIC, 2, "filterNot", null, '\n')
fun testForceParenthesisForTabChar() = doTest(CompletionType.BASIC, 0, "some", null, '\t')
fun testTabInsertAtTheFileEnd() = doTest(CompletionType.BASIC, 0, "vvvvv", null, '\t')
fun testTabInsertBeforeBraces() = doTest(CompletionType.BASIC, 0, "vvvvv", null, '\t')
fun testTabInsertBeforeBrackets() = doTest(CompletionType.BASIC, 0, "vvvvv", null, '\t')
fun testTabInsertBeforeOperator() = doTest(CompletionType.BASIC, 0, "vvvvv", null, '\t')
fun testTabInsertBeforeParentheses() = doTest(CompletionType.BASIC, 0, "vvvvv", null, '\t')
fun testTabInsertInsideBraces() = doTest(CompletionType.BASIC, 0, "vvvvv", null, '\t')
fun testTabInsertInsideBrackets() = doTest(CompletionType.BASIC, 0, "vvvvv", null, '\t')
fun testTabInsertInsideEmptyParentheses() = doTest(CompletionType.BASIC, 0, "vvvvv", null, '\t')
fun testTabInsertInsideParentheses() = doTest(CompletionType.BASIC, 0, "vvvvv", null, '\t')
fun testTabInsertInSimpleName() = doTest(CompletionType.BASIC, 0, "vvvvv", null, '\t')
fun testInsertFunctionWithSingleParameterWithBrace() = doTest(CompletionType.BASIC, 0, "some", null, '{')
var fixture by Delegates.notNull<JavaCodeInsightTestFixture>()
protected var fixture: JavaCodeInsightTestFixture by Delegates.notNull<JavaCodeInsightTestFixture>()
protected override fun setUp() {
super.setUp()
fixture = myFixture!!
}
fun testSingleBrackets() {
fixture.configureByFile(fileName())
fixture.`type`('(')
fixture.checkResultByFile(afterFileName())
}
protected fun doTest() : Unit = doTest(2, null, null, '\n')
fun testInsertFunctionWithBothParentheses() {
fixture.configureByFile(fileName())
fixture.`type`("test()")
fixture.checkResultByFile(afterFileName())
}
fun testFunctionLiteralInsertWhenNoSpacesForBraces() {
val settings = CodeStyleSettingsManager.getSettings(getProject())
val jetSettings = settings.getCustomSettings(javaClass<JetCodeStyleSettings>())!!
try {
jetSettings.INSERT_WHITESPACES_IN_SIMPLE_ONE_LINE_METHOD = false
doTest()
}
finally {
jetSettings.INSERT_WHITESPACES_IN_SIMPLE_ONE_LINE_METHOD = true
}
}
fun doTest() = doTest(CompletionType.BASIC, 2, null, null, '\n')
private fun doTest(`type` : CompletionType, time : Int, lookupString : String?, tailText : String?, completionChar : Char) : Unit {
protected fun doTest(time : Int, lookupString : String?, tailText : String?, completionChar : Char) : Unit {
fixture.configureByFile(fileName())
if (lookupString != null || tailText != null) {
fixture.complete(`type`, time)
fixture.complete(completionType, time)
val item = getExistentLookupElement(lookupString, tailText)
if (item != null) {
selectItem(item, completionChar)
}
}
else {
forceCompleteFirst(`type`, time)
forceCompleteFirst(completionType, time)
}
checkResult()
}
protected fun checkResult(){
fixture.checkResultByFile(afterFileName())
}
@@ -180,9 +105,9 @@ public class CompletionHandlerTest() : JetLightCodeInsightFixtureTestCase() {
return foundElement
}
fun afterFileName() = getTestName(false) + ".kt.after"
protected fun afterFileName(): String = getTestName(false) + ".kt.after"
fun forceCompleteFirst(`type` : CompletionType, time : Int) {
private fun forceCompleteFirst(`type` : CompletionType, time : Int) {
fixture.complete(`type`, time)
val items : Array<LookupElement>? = fixture.getLookupElements()
if (items != null && items.isNotEmpty()) {
@@ -190,7 +115,7 @@ public class CompletionHandlerTest() : JetLightCodeInsightFixtureTestCase() {
}
}
protected override fun getTestDataPath() : String = File(PluginTestCaseBase.getTestDataPathBase(), "/completion/handlers/").getPath() + File.separator
protected override fun getTestDataPath() : String = File(PluginTestCaseBase.getTestDataPathBase(), testDataRelativePath).getPath() + File.separator
protected fun selectItem(item : LookupElement?) {
selectItem(item, 0.toChar())
@@ -0,0 +1,45 @@
/*
* Copyright 2010-2013 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 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
public class SmartCompletionHandlerTest() : CompletionHandlerTestBase() {
override val completionType: CompletionType = CompletionType.SMART
override val testDataRelativePath: String = "/completion/handlers/smart"
fun testConstructor() = doTest()
fun testConstructorWithParameters() = doTest()
fun testConstructorForNullable() = doTest()
fun testConstructorForJavaClass() = doTest()
//fun testConstructorInsertsImport() = doTest() //TODO
}