diff --git a/annotations/com/intellij/codeInsight/completion/annotations.xml b/annotations/com/intellij/codeInsight/completion/annotations.xml index cce2e9ddb41..fc886fda0c3 100644 --- a/annotations/com/intellij/codeInsight/completion/annotations.xml +++ b/annotations/com/intellij/codeInsight/completion/annotations.xml @@ -7,6 +7,14 @@ name='com.intellij.codeInsight.completion.CompletionSorter com.intellij.codeInsight.completion.CompletionSorter weighBefore(java.lang.String, com.intellij.codeInsight.lookup.LookupElementWeigher...)'> + + + + + + diff --git a/annotations/com/intellij/codeInsight/lookup/annotations.xml b/annotations/com/intellij/codeInsight/lookup/annotations.xml index ae51da930f5..07cea5c5724 100644 --- a/annotations/com/intellij/codeInsight/lookup/annotations.xml +++ b/annotations/com/intellij/codeInsight/lookup/annotations.xml @@ -6,4 +6,24 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/annotations/com/intellij/psi/annotations.xml b/annotations/com/intellij/psi/annotations.xml index d99fc377d4e..1870def42f3 100644 --- a/annotations/com/intellij/psi/annotations.xml +++ b/annotations/com/intellij/psi/annotations.xml @@ -1,4 +1,7 @@ + + + diff --git a/idea/src/org/jetbrains/jet/plugin/completion/CompletionSession.java b/idea/src/org/jetbrains/jet/plugin/completion/CompletionSession.java index 82cd2e1b733..611ddc53254 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/CompletionSession.java +++ b/idea/src/org/jetbrains/jet/plugin/completion/CompletionSession.java @@ -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() { @Override public boolean value(DeclarationDescriptor descriptor) { - return filter.accepts(descriptor); + return data.accepts(descriptor); } }); + for (LookupElement element : data.getAdditionalElements()) { + jetResult.addElement(element); + } } } diff --git a/idea/src/org/jetbrains/jet/plugin/completion/SmartCompletion.kt b/idea/src/org/jetbrains/jet/plugin/completion/SmartCompletion.kt index 916d5fd8f4c..828d0e69a22 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/SmartCompletion.kt +++ b/idea/src/org/jetbrains/jet/plugin/completion/SmartCompletion.kt @@ -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 } -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() + + 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 = 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 = additionalElements } } diff --git a/idea/src/org/jetbrains/jet/plugin/completion/handlers/JetFunctionInsertHandler.kt b/idea/src/org/jetbrains/jet/plugin/completion/handlers/JetFunctionInsertHandler.kt index 24b5ffafbe2..b94562337e4 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/handlers/JetFunctionInsertHandler.kt +++ b/idea/src/org/jetbrains/jet/plugin/completion/handlers/JetFunctionInsertHandler.kt @@ -45,18 +45,16 @@ public enum class BracketType { BRACES } -public class JetFunctionInsertHandler(val caretPosition : CaretPosition, val bracketType : BracketType) : InsertHandler { +public class JetFunctionInsertHandler(val caretPosition : CaretPosition, val bracketType : BracketType) : InsertHandler { { 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 { diff --git a/idea/testData/completion/handlers/smart/Constructor.kt b/idea/testData/completion/handlers/smart/Constructor.kt new file mode 100644 index 00000000000..adc6bc3fe26 --- /dev/null +++ b/idea/testData/completion/handlers/smart/Constructor.kt @@ -0,0 +1,3 @@ +class Foo + +var a : Foo = diff --git a/idea/testData/completion/handlers/smart/Constructor.kt.after b/idea/testData/completion/handlers/smart/Constructor.kt.after new file mode 100644 index 00000000000..865361bf883 --- /dev/null +++ b/idea/testData/completion/handlers/smart/Constructor.kt.after @@ -0,0 +1,3 @@ +class Foo + +var a : Foo = Foo() diff --git a/idea/testData/completion/handlers/smart/ConstructorForJavaClass.kt b/idea/testData/completion/handlers/smart/ConstructorForJavaClass.kt new file mode 100644 index 00000000000..89f096e66de --- /dev/null +++ b/idea/testData/completion/handlers/smart/ConstructorForJavaClass.kt @@ -0,0 +1,3 @@ +import java.util.Date + +var a : Date = diff --git a/idea/testData/completion/handlers/smart/ConstructorForJavaClass.kt.after b/idea/testData/completion/handlers/smart/ConstructorForJavaClass.kt.after new file mode 100644 index 00000000000..930016dcc56 --- /dev/null +++ b/idea/testData/completion/handlers/smart/ConstructorForJavaClass.kt.after @@ -0,0 +1,3 @@ +import java.util.Date + +var a : Date = Date() diff --git a/idea/testData/completion/handlers/smart/ConstructorForNullable.kt b/idea/testData/completion/handlers/smart/ConstructorForNullable.kt new file mode 100644 index 00000000000..2677f0a9a7f --- /dev/null +++ b/idea/testData/completion/handlers/smart/ConstructorForNullable.kt @@ -0,0 +1,5 @@ +class Foo + +fun foo(p : Object){ + var a : Foo? = +} diff --git a/idea/testData/completion/handlers/smart/ConstructorForNullable.kt.after b/idea/testData/completion/handlers/smart/ConstructorForNullable.kt.after new file mode 100644 index 00000000000..6a2fe26b2ae --- /dev/null +++ b/idea/testData/completion/handlers/smart/ConstructorForNullable.kt.after @@ -0,0 +1,5 @@ +class Foo + +fun foo(p : Object){ + var a : Foo? = Foo() +} diff --git a/idea/testData/completion/handlers/smart/ConstructorInsertsImport.kt b/idea/testData/completion/handlers/smart/ConstructorInsertsImport.kt new file mode 100644 index 00000000000..727b60a8d90 --- /dev/null +++ b/idea/testData/completion/handlers/smart/ConstructorInsertsImport.kt @@ -0,0 +1,5 @@ +fun foo(p: java.util.BitSet){} + +fun f(){ + foo() +} diff --git a/idea/testData/completion/handlers/smart/ConstructorInsertsImport.kt.after b/idea/testData/completion/handlers/smart/ConstructorInsertsImport.kt.after new file mode 100644 index 00000000000..ed9850c3f1e --- /dev/null +++ b/idea/testData/completion/handlers/smart/ConstructorInsertsImport.kt.after @@ -0,0 +1,7 @@ +import java.util.BitSet + +fun foo(p: java.util.BitSet){} + +fun f(){ + foo(BitSet()) +} diff --git a/idea/testData/completion/handlers/smart/ConstructorWithParameters.kt b/idea/testData/completion/handlers/smart/ConstructorWithParameters.kt new file mode 100644 index 00000000000..02b0422cc97 --- /dev/null +++ b/idea/testData/completion/handlers/smart/ConstructorWithParameters.kt @@ -0,0 +1,3 @@ +class Foo(p : Int) + +var a : Foo = diff --git a/idea/testData/completion/handlers/smart/ConstructorWithParameters.kt.after b/idea/testData/completion/handlers/smart/ConstructorWithParameters.kt.after new file mode 100644 index 00000000000..a9e97a6552d --- /dev/null +++ b/idea/testData/completion/handlers/smart/ConstructorWithParameters.kt.after @@ -0,0 +1,3 @@ +class Foo(p : Int) + +var a : Foo = Foo() diff --git a/idea/testData/completion/smart/Constructor.kt b/idea/testData/completion/smart/Constructor.kt new file mode 100644 index 00000000000..3229062eb09 --- /dev/null +++ b/idea/testData/completion/smart/Constructor.kt @@ -0,0 +1,5 @@ +class Foo + +var a : Foo = + +// EXIST: Foo@Foo() diff --git a/idea/testData/completion/smart/ConstructorForGenericJavaClass.kt.todo b/idea/testData/completion/smart/ConstructorForGenericJavaClass.kt.todo new file mode 100644 index 00000000000..71eb5f66616 --- /dev/null +++ b/idea/testData/completion/smart/ConstructorForGenericJavaClass.kt.todo @@ -0,0 +1,5 @@ +import java.util.ArrayList + +var a : ArrayList = + +// EXIST: ArrayList@ArrayList() diff --git a/idea/testData/completion/smart/ConstructorForGenericType.kt b/idea/testData/completion/smart/ConstructorForGenericType.kt new file mode 100644 index 00000000000..2bb48e4a647 --- /dev/null +++ b/idea/testData/completion/smart/ConstructorForGenericType.kt @@ -0,0 +1,7 @@ +class Foo + +fun foo(p : Object){ + var a : Foo = +} + +// EXIST: Foo@Foo() diff --git a/idea/testData/completion/smart/ConstructorForJavaClass.kt.todo b/idea/testData/completion/smart/ConstructorForJavaClass.kt.todo new file mode 100644 index 00000000000..5e6b161db2e --- /dev/null +++ b/idea/testData/completion/smart/ConstructorForJavaClass.kt.todo @@ -0,0 +1,5 @@ +import java.util.Date + +var a : Date = + +// EXIST: Date@Date() diff --git a/idea/testData/completion/smart/ConstructorForNullable.kt b/idea/testData/completion/smart/ConstructorForNullable.kt new file mode 100644 index 00000000000..89acd78d191 --- /dev/null +++ b/idea/testData/completion/smart/ConstructorForNullable.kt @@ -0,0 +1,7 @@ +class Foo + +fun foo(p : Object){ + var a : Foo? = +} + +// EXIST: Foo@Foo() diff --git a/idea/testData/completion/smart/EmptyPrefix.kt b/idea/testData/completion/smart/EmptyPrefix.kt index 9c72240c671..a0c62bae5a9 100644 --- a/idea/testData/completion/smart/EmptyPrefix.kt +++ b/idea/testData/completion/smart/EmptyPrefix.kt @@ -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() diff --git a/idea/testData/completion/smart/InsideIdentifier.kt b/idea/testData/completion/smart/InsideIdentifier.kt index 87ea0eb0256..806793850ff 100644 --- a/idea/testData/completion/smart/InsideIdentifier.kt +++ b/idea/testData/completion/smart/InsideIdentifier.kt @@ -1,5 +1,5 @@ -class Foo -class Bar : Foo +open class Foo +class Bar : Foo() val xfoo = Foo() val xbar = Bar() diff --git a/idea/testData/completion/smart/NoConstructorForAbstract.kt b/idea/testData/completion/smart/NoConstructorForAbstract.kt new file mode 100644 index 00000000000..9a3342dc205 --- /dev/null +++ b/idea/testData/completion/smart/NoConstructorForAbstract.kt @@ -0,0 +1,7 @@ +abstract class Foo + +fun foo(p : Object){ + var a : Foo = +} + +// ABSENT: Foo diff --git a/idea/testData/completion/smart/NoConstructorForJavaInterface.kt b/idea/testData/completion/smart/NoConstructorForJavaInterface.kt new file mode 100644 index 00000000000..7dfd234c1c9 --- /dev/null +++ b/idea/testData/completion/smart/NoConstructorForJavaInterface.kt @@ -0,0 +1,3 @@ +var a : Appendable = + +// ABSENT: Appendable diff --git a/idea/testData/completion/smart/NoConstructorForTrait.kt b/idea/testData/completion/smart/NoConstructorForTrait.kt new file mode 100644 index 00000000000..3497dcc04de --- /dev/null +++ b/idea/testData/completion/smart/NoConstructorForTrait.kt @@ -0,0 +1,7 @@ +trait Foo + +fun foo(p : Object){ + var a : Foo = +} + +// ABSENT: Foo diff --git a/idea/testData/completion/smart/NoConstructorWithQualifier.kt b/idea/testData/completion/smart/NoConstructorWithQualifier.kt new file mode 100644 index 00000000000..4540f087ac5 --- /dev/null +++ b/idea/testData/completion/smart/NoConstructorWithQualifier.kt @@ -0,0 +1,7 @@ +class Foo + +fun foo(p : Object){ + var a : Foo = p. +} + +// ABSENT: Foo diff --git a/idea/testData/completion/smart/WithPrefix.kt b/idea/testData/completion/smart/WithPrefix.kt index e30ab5b63a9..0103355a17d 100644 --- a/idea/testData/completion/smart/WithPrefix.kt +++ b/idea/testData/completion/smart/WithPrefix.kt @@ -1,5 +1,5 @@ -class Foo -class Bar : Foo +open class Foo +class Bar : Foo() val xfoo = Foo() val xbar = Bar() diff --git a/idea/tests/org/jetbrains/jet/completion/JetFixtureCompletionBaseTestCase.java b/idea/tests/org/jetbrains/jet/completion/JetFixtureCompletionBaseTestCase.java index 6744f034f4e..76f47fb4427 100644 --- a/idea/tests/org/jetbrains/jet/completion/JetFixtureCompletionBaseTestCase.java +++ b/idea/tests/org/jetbrains/jet/completion/JetFixtureCompletionBaseTestCase.java @@ -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 diff --git a/idea/tests/org/jetbrains/jet/completion/JetSmartCompletionTestGenerated.java b/idea/tests/org/jetbrains/jet/completion/JetSmartCompletionTestGenerated.java index 318f24784ff..81a715d86fe 100644 --- a/idea/tests/org/jetbrains/jet/completion/JetSmartCompletionTestGenerated.java +++ b/idea/tests/org/jetbrains/jet/completion/JetSmartCompletionTestGenerated.java @@ -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"); diff --git a/idea/tests/org/jetbrains/jet/completion/handlers/BasicCompletionHandlerTest.kt b/idea/tests/org/jetbrains/jet/completion/handlers/BasicCompletionHandlerTest.kt new file mode 100644 index 00000000000..13b2c6e838d --- /dev/null +++ b/idea/tests/org/jetbrains/jet/completion/handlers/BasicCompletionHandlerTest.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())!! + + try { + jetSettings.INSERT_WHITESPACES_IN_SIMPLE_ONE_LINE_METHOD = false + doTest() + } + finally { + jetSettings.INSERT_WHITESPACES_IN_SIMPLE_ONE_LINE_METHOD = true + } + } +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/jet/completion/handlers/CompletionHandlerTest.kt b/idea/tests/org/jetbrains/jet/completion/handlers/CompletionHandlerTestBase.kt similarity index 53% rename from idea/tests/org/jetbrains/jet/completion/handlers/CompletionHandlerTest.kt rename to idea/tests/org/jetbrains/jet/completion/handlers/CompletionHandlerTestBase.kt index a9a69e78ae6..bfdbda5c219 100644 --- a/idea/tests/org/jetbrains/jet/completion/handlers/CompletionHandlerTest.kt +++ b/idea/tests/org/jetbrains/jet/completion/handlers/CompletionHandlerTestBase.kt @@ -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() + protected var fixture: JavaCodeInsightTestFixture by Delegates.notNull() 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())!! - - 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? = 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()) diff --git a/idea/tests/org/jetbrains/jet/completion/handlers/SmartCompletionHandlerTest.kt b/idea/tests/org/jetbrains/jet/completion/handlers/SmartCompletionHandlerTest.kt new file mode 100644 index 00000000000..9efd3d36dd7 --- /dev/null +++ b/idea/tests/org/jetbrains/jet/completion/handlers/SmartCompletionHandlerTest.kt @@ -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 +}