From 39f07b8354ffb162aaa8b1c6ddcbd585237480a8 Mon Sep 17 00:00:00 2001 From: Valentin Kipyatkov Date: Wed, 25 Dec 2013 22:26:48 +0400 Subject: [PATCH] Smart completion: imports insertion + fixed both behaviour and presentation of qualified members in lookup --- .../codeInsight/lookup/annotations.xml | 3 + .../jet/lang/resolve/name/FqNameUnsafe.java | 2 + .../jet/renderer/DescriptorRenderer.java | 6 + .../jet/renderer/DescriptorRendererImpl.java | 11 ++ .../jet/plugin/completion/SmartCompletion.kt | 108 +++++++++++++----- .../smart/AnonymousObjectInsertsImport.kt | 1 + .../AnonymousObjectInsertsImport.kt.after | 7 ++ .../smart/ConstructorForGenericType.kt | 8 ++ .../smart/ConstructorForGenericType.kt.after | 8 ++ .../smart/ConstructorInsertsImport.kt | 8 +- .../smart/ConstructorInsertsImport.kt.after | 11 +- .../smart/ConstructorInsertsImport2.kt | 7 ++ .../smart/ConstructorInsertsImport2.kt.after | 11 ++ .../completion/handlers/smart/EnumMember.kt | 8 ++ .../handlers/smart/EnumMember.kt.after | 8 ++ .../smart/JavaEnumMemberInsertsImport.kt | 3 + .../JavaEnumMemberInsertsImport.kt.after | 5 + .../handlers/smart/JavaStaticField.kt | 5 + .../handlers/smart/JavaStaticField.kt.after | 5 + .../JavaStaticFieldInsertImport.kt.after | 2 +- .../smart/JavaStaticMethodInsertsImport.kt | 3 + .../JavaStaticMethodInsertsImport.kt.after | 5 + .../completion/smart/JavaStaticMethods.kt | 6 +- .../handlers/CompletionHandlerTestBase.kt | 27 ++--- .../handlers/SmartCompletionHandlerTest.kt | 11 +- 25 files changed, 223 insertions(+), 56 deletions(-) create mode 100644 idea/testData/completion/handlers/smart/AnonymousObjectInsertsImport.kt create mode 100644 idea/testData/completion/handlers/smart/AnonymousObjectInsertsImport.kt.after create mode 100644 idea/testData/completion/handlers/smart/ConstructorForGenericType.kt create mode 100644 idea/testData/completion/handlers/smart/ConstructorForGenericType.kt.after create mode 100644 idea/testData/completion/handlers/smart/ConstructorInsertsImport2.kt create mode 100644 idea/testData/completion/handlers/smart/ConstructorInsertsImport2.kt.after create mode 100644 idea/testData/completion/handlers/smart/EnumMember.kt create mode 100644 idea/testData/completion/handlers/smart/EnumMember.kt.after create mode 100644 idea/testData/completion/handlers/smart/JavaEnumMemberInsertsImport.kt create mode 100644 idea/testData/completion/handlers/smart/JavaEnumMemberInsertsImport.kt.after create mode 100644 idea/testData/completion/handlers/smart/JavaStaticField.kt create mode 100644 idea/testData/completion/handlers/smart/JavaStaticField.kt.after create mode 100644 idea/testData/completion/handlers/smart/JavaStaticMethodInsertsImport.kt create mode 100644 idea/testData/completion/handlers/smart/JavaStaticMethodInsertsImport.kt.after diff --git a/annotations/com/intellij/codeInsight/lookup/annotations.xml b/annotations/com/intellij/codeInsight/lookup/annotations.xml index 200c723282b..9277180b901 100644 --- a/annotations/com/intellij/codeInsight/lookup/annotations.xml +++ b/annotations/com/intellij/codeInsight/lookup/annotations.xml @@ -6,6 +6,9 @@ + + + diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/name/FqNameUnsafe.java b/core/descriptors/src/org/jetbrains/jet/lang/resolve/name/FqNameUnsafe.java index e3ed042bc98..f6d8c1358f5 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/name/FqNameUnsafe.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/name/FqNameUnsafe.java @@ -85,6 +85,7 @@ public final class FqNameUnsafe extends FqNameBase { + @Override @NotNull public String asString() { return fqName; @@ -267,6 +268,7 @@ public final class FqNameUnsafe extends FqNameBase { @Override + @NotNull public String toString() { return isRoot() ? ROOT_NAME.asString() : fqName; } diff --git a/core/descriptors/src/org/jetbrains/jet/renderer/DescriptorRenderer.java b/core/descriptors/src/org/jetbrains/jet/renderer/DescriptorRenderer.java index efb42082105..34d41931280 100644 --- a/core/descriptors/src/org/jetbrains/jet/renderer/DescriptorRenderer.java +++ b/core/descriptors/src/org/jetbrains/jet/renderer/DescriptorRenderer.java @@ -21,6 +21,9 @@ import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor; import org.jetbrains.jet.lang.types.JetType; +import org.jetbrains.jet.lang.types.TypeProjection; + +import java.util.List; public interface DescriptorRenderer extends Renderer { DescriptorRenderer COMPACT_WITH_MODIFIERS = new DescriptorRendererBuilder().setWithDefinedIn(false).build(); @@ -61,6 +64,9 @@ public interface DescriptorRenderer extends Renderer { @NotNull String renderType(@NotNull JetType type); + @NotNull + String renderTypeArguments(@NotNull List typeArguments); + @NotNull @Override String render(@NotNull DeclarationDescriptor declarationDescriptor); diff --git a/core/descriptors/src/org/jetbrains/jet/renderer/DescriptorRendererImpl.java b/core/descriptors/src/org/jetbrains/jet/renderer/DescriptorRendererImpl.java index ca44f99c455..4741a0a6e9c 100644 --- a/core/descriptors/src/org/jetbrains/jet/renderer/DescriptorRendererImpl.java +++ b/core/descriptors/src/org/jetbrains/jet/renderer/DescriptorRendererImpl.java @@ -201,6 +201,17 @@ public class DescriptorRendererImpl implements DescriptorRenderer { return escape(renderTypeWithoutEscape(type)); } + @NotNull + @Override + public String renderTypeArguments(@NotNull List typeArguments) { + if (typeArguments.isEmpty()) return ""; + StringBuilder sb = new StringBuilder(); + sb.append("<"); + appendTypeProjections(typeArguments, sb); + sb.append(">"); + return sb.toString(); + } + private String renderTypeWithoutEscape(@NotNull JetType type) { if (type == CANT_INFER_LAMBDA_PARAM_TYPE || type == CANT_INFER_TYPE_PARAMETER) { return "???"; diff --git a/idea/src/org/jetbrains/jet/plugin/completion/SmartCompletion.kt b/idea/src/org/jetbrains/jet/plugin/completion/SmartCompletion.kt index aeff3a5e59a..427c77210b8 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/SmartCompletion.kt +++ b/idea/src/org/jetbrains/jet/plugin/completion/SmartCompletion.kt @@ -29,6 +29,9 @@ import com.intellij.psi.util.PsiTreeUtil import com.intellij.openapi.editor.EditorModificationUtil import org.jetbrains.jet.plugin.codeInsight.ImplementMethodsHandler import com.intellij.psi.PsiDocumentManager +import com.intellij.openapi.application.ApplicationManager +import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache +import org.jetbrains.jet.plugin.codeInsight.ShortenReferences trait SmartCompletionData{ fun accepts(descriptor: DeclarationDescriptor): Boolean @@ -133,30 +136,31 @@ private fun typeInstantiationItems(expectedType: JetType, resolveSession: Cancel var lookupString = lookupElement.getLookupString() 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(", ", "<", ">") - var itemText = lookupElement.getLookupString() + typeArgsText + var itemText = lookupString + DescriptorRenderer.TEXT.renderTypeArguments(typeArgs) val insertHandler: InsertHandler var suppressAutoInsertion: Boolean = false + val typeText = DescriptorUtils.getFqName(classifier).toString() + DescriptorRenderer.SOURCE_CODE.renderTypeArguments(typeArgs) if (classifier.getModality() == Modality.ABSTRACT) { val constructorParenthesis = if (classifier.getKind() != ClassKind.TRAIT) "()" else "" itemText += constructorParenthesis itemText = "object: " + itemText + "{...}" lookupString = "object" //? - insertHandler = object: InsertHandler{ - override fun handleInsert(context: InsertionContext, item: LookupElement) { - //TODO: insert import - val editor = context.getEditor() - EditorModificationUtil.insertStringAtCaret(editor, ": " + classifier.getName() + constructorParenthesis + " {}") - editor.getCaretModel().moveToOffset(editor.getCaretModel().getOffset() - 1) - PsiDocumentManager.getInstance(context.getProject()).commitAllDocuments(); - ImplementMethodsHandler().invoke(context.getProject(), editor, context.getFile(), true) + insertHandler = InsertHandler { (context, item) -> + val editor = context.getEditor() + val startOffset = context.getStartOffset() + val text = "object: $typeText$constructorParenthesis {}" + editor.getDocument().replaceString(startOffset, context.getTailOffset(), text) + editor.getCaretModel().moveToOffset(startOffset + text.length - 1) + + PsiDocumentManager.getInstance(context.getProject()).commitAllDocuments(); + val file = context.getFile() as JetFile + val element = PsiTreeUtil.findElementOfClassAtRange(file, startOffset, startOffset + text.length, javaClass()) + if (element != null) { + ShortenReferences.process(element) } + + ImplementMethodsHandler().invoke(context.getProject(), editor, context.getFile(), true) } suppressAutoInsertion = true } @@ -170,7 +174,23 @@ private fun typeInstantiationItems(expectedType: JetType, resolveSession: Cancel if (constructors.first().getValueParameters().isEmpty()) CaretPosition.AFTER_BRACKETS else CaretPosition.IN_BRACKETS else CaretPosition.IN_BRACKETS - insertHandler = JetFunctionInsertHandler(caretPosition, BracketType.PARENTHESIS) + insertHandler = InsertHandler { (context, item) -> + val editor = context.getEditor() + val startOffset = context.getStartOffset() + val text = typeText + "()" + editor.getDocument().replaceString(startOffset, context.getTailOffset(), text) + val endOffset = startOffset + text.length + editor.getCaretModel().moveToOffset(if (caretPosition == CaretPosition.IN_BRACKETS) endOffset - 1 else endOffset) + + //TODO: autopopup parameter info and other functionality from JetFunctionInsertHandler + + PsiDocumentManager.getInstance(context.getProject()).commitAllDocuments(); + val file = context.getFile() as JetFile + val element = PsiTreeUtil.findElementOfClassAtRange(file, startOffset, endOffset, javaClass()) + if (element != null) { + ShortenReferences.process(element) + } + } } val lookupElementDecorated = object: LookupElementDecorator(lookupElement){ @@ -311,36 +331,62 @@ private fun staticMembers(context: JetExpression, expectedType: JetType, resolve fun toLookupElement(descriptor: DeclarationDescriptor): LookupElement { val lookupElement = DescriptorLookupConverter.createLookupElement(resolveSession, bindingContext, descriptor) - val lookupString = classDescriptor.getName().asString() + "." + lookupElement.getLookupString() - var itemText = lookupString - val insertHandler: InsertHandler? + val qualifierPresentation = classDescriptor.getName().asString() + val lookupString = qualifierPresentation + "." + lookupElement.getLookupString() + val qualifierText = DescriptorUtils.getFqName(classDescriptor).asString() //TODO: escape keywords + + val caretPosition: CaretPosition? if (descriptor is FunctionDescriptor) { - itemText += "()" - val caretPosition = if (descriptor.getValueParameters().empty) CaretPosition.AFTER_BRACKETS else CaretPosition.IN_BRACKETS - insertHandler = JetFunctionInsertHandler(caretPosition, BracketType.PARENTHESIS) + caretPosition = if (descriptor.getValueParameters().empty) CaretPosition.AFTER_BRACKETS else CaretPosition.IN_BRACKETS } else { - insertHandler = null + caretPosition = null } + + val insertHandler = InsertHandler { (context, item) -> + val editor = context.getEditor() + val startOffset = context.getStartOffset() + var text = qualifierText + "." + descriptor.getName().asString() //TODO: escape + if (descriptor is FunctionDescriptor) { + text += "()" + //TODO: autopopup parameter info and other functionality from JetFunctionInsertHandler + } + + editor.getDocument().replaceString(startOffset, context.getTailOffset(), text) + val endOffset = startOffset + text.length + editor.getCaretModel().moveToOffset(if (caretPosition == CaretPosition.IN_BRACKETS) endOffset - 1 else endOffset) + + PsiDocumentManager.getInstance(context.getProject()).commitAllDocuments(); + val file = context.getFile() as JetFile + val element = PsiTreeUtil.findElementOfClassAtRange(file, startOffset, startOffset + qualifierText.length, javaClass()) + if (element != null) { + ShortenReferences.process(element) + } + } + return object: LookupElementDecorator(lookupElement){ override fun getLookupString() = lookupString override fun renderElement(presentation: LookupElementPresentation) { lookupElement.renderElement(presentation) - presentation.setItemText(itemText) - presentation.setTailText(" (" + DescriptorUtils.getFqName(classDescriptor.getContainingDeclaration()) + ")") + + presentation.setItemText(qualifierPresentation + "." + presentation.getItemText()) + + val tailText = " (" + DescriptorUtils.getFqName(classDescriptor.getContainingDeclaration()) + ")" + if (descriptor is FunctionDescriptor) { + presentation.appendTailText(tailText, true) + } + else{ + presentation.setTailText(tailText, true) + } + if (presentation.getTypeText().isNullOrEmpty()) { presentation.setTypeText(DescriptorRenderer.TEXT.renderType(classDescriptor.getDefaultType())) } } override fun handleInsert(context: InsertionContext) { - if (insertHandler != null) { - insertHandler.handleInsert(context, lookupElement) - } - else{ - lookupElement.handleInsert(context) - } + insertHandler.handleInsert(context, lookupElement) } } } diff --git a/idea/testData/completion/handlers/smart/AnonymousObjectInsertsImport.kt b/idea/testData/completion/handlers/smart/AnonymousObjectInsertsImport.kt new file mode 100644 index 00000000000..592c57398f3 --- /dev/null +++ b/idea/testData/completion/handlers/smart/AnonymousObjectInsertsImport.kt @@ -0,0 +1 @@ +val c: java.io.Closeable = \ No newline at end of file diff --git a/idea/testData/completion/handlers/smart/AnonymousObjectInsertsImport.kt.after b/idea/testData/completion/handlers/smart/AnonymousObjectInsertsImport.kt.after new file mode 100644 index 00000000000..05bfc0a45db --- /dev/null +++ b/idea/testData/completion/handlers/smart/AnonymousObjectInsertsImport.kt.after @@ -0,0 +1,7 @@ +import java.io.Closeable + +val c: java.io.Closeable = object: Closeable { + override fun close() { + throw UnsupportedOperationException() + } +} \ No newline at end of file diff --git a/idea/testData/completion/handlers/smart/ConstructorForGenericType.kt b/idea/testData/completion/handlers/smart/ConstructorForGenericType.kt new file mode 100644 index 00000000000..06cdebbc852 --- /dev/null +++ b/idea/testData/completion/handlers/smart/ConstructorForGenericType.kt @@ -0,0 +1,8 @@ +import java.util.HashMap +import java.util.List + +fun foo(p: HashMap>){} + +fun f(){ + foo() +} diff --git a/idea/testData/completion/handlers/smart/ConstructorForGenericType.kt.after b/idea/testData/completion/handlers/smart/ConstructorForGenericType.kt.after new file mode 100644 index 00000000000..fabcc7d4754 --- /dev/null +++ b/idea/testData/completion/handlers/smart/ConstructorForGenericType.kt.after @@ -0,0 +1,8 @@ +import java.util.HashMap +import java.util.List + +fun foo(p: HashMap>){} + +fun f(){ + foo(HashMap>()) +} diff --git a/idea/testData/completion/handlers/smart/ConstructorInsertsImport.kt b/idea/testData/completion/handlers/smart/ConstructorInsertsImport.kt index 727b60a8d90..e03b67769a0 100644 --- a/idea/testData/completion/handlers/smart/ConstructorInsertsImport.kt +++ b/idea/testData/completion/handlers/smart/ConstructorInsertsImport.kt @@ -1,5 +1,7 @@ -fun foo(p: java.util.BitSet){} +class X { + fun foo(p: java.util.HashMap){} -fun f(){ - foo() + fun f(){ + foo() + } } diff --git a/idea/testData/completion/handlers/smart/ConstructorInsertsImport.kt.after b/idea/testData/completion/handlers/smart/ConstructorInsertsImport.kt.after index ed9850c3f1e..2d0a0cb752b 100644 --- a/idea/testData/completion/handlers/smart/ConstructorInsertsImport.kt.after +++ b/idea/testData/completion/handlers/smart/ConstructorInsertsImport.kt.after @@ -1,7 +1,10 @@ -import java.util.BitSet +import java.util.HashMap +import java.io.File -fun foo(p: java.util.BitSet){} +class X { + fun foo(p: java.util.HashMap){} -fun f(){ - foo(BitSet()) + fun f(){ + foo(HashMap()) + } } diff --git a/idea/testData/completion/handlers/smart/ConstructorInsertsImport2.kt b/idea/testData/completion/handlers/smart/ConstructorInsertsImport2.kt new file mode 100644 index 00000000000..557b6f8f22c --- /dev/null +++ b/idea/testData/completion/handlers/smart/ConstructorInsertsImport2.kt @@ -0,0 +1,7 @@ +class X { + fun foo(p: java.util.HashMap>){} + + fun f(){ + foo() + } +} diff --git a/idea/testData/completion/handlers/smart/ConstructorInsertsImport2.kt.after b/idea/testData/completion/handlers/smart/ConstructorInsertsImport2.kt.after new file mode 100644 index 00000000000..6ef99fc5432 --- /dev/null +++ b/idea/testData/completion/handlers/smart/ConstructorInsertsImport2.kt.after @@ -0,0 +1,11 @@ +import java.util.HashMap +import java.util.AbstractMap +import java.io.File + +class X { + fun foo(p: java.util.HashMap>){} + + fun f(){ + foo(HashMap>()) + } +} diff --git a/idea/testData/completion/handlers/smart/EnumMember.kt b/idea/testData/completion/handlers/smart/EnumMember.kt new file mode 100644 index 00000000000..ddc21f30e05 --- /dev/null +++ b/idea/testData/completion/handlers/smart/EnumMember.kt @@ -0,0 +1,8 @@ +enum class Foo { + X + Y +} + +fun foo(){ + val f : Foo = +} diff --git a/idea/testData/completion/handlers/smart/EnumMember.kt.after b/idea/testData/completion/handlers/smart/EnumMember.kt.after new file mode 100644 index 00000000000..3cd00a17f3d --- /dev/null +++ b/idea/testData/completion/handlers/smart/EnumMember.kt.after @@ -0,0 +1,8 @@ +enum class Foo { + X + Y +} + +fun foo(){ + val f : Foo = Foo.X +} diff --git a/idea/testData/completion/handlers/smart/JavaEnumMemberInsertsImport.kt b/idea/testData/completion/handlers/smart/JavaEnumMemberInsertsImport.kt new file mode 100644 index 00000000000..3e550180e1d --- /dev/null +++ b/idea/testData/completion/handlers/smart/JavaEnumMemberInsertsImport.kt @@ -0,0 +1,3 @@ +fun foo(){ + val e : java.lang.annotation.ElementType = +} diff --git a/idea/testData/completion/handlers/smart/JavaEnumMemberInsertsImport.kt.after b/idea/testData/completion/handlers/smart/JavaEnumMemberInsertsImport.kt.after new file mode 100644 index 00000000000..75c806d086e --- /dev/null +++ b/idea/testData/completion/handlers/smart/JavaEnumMemberInsertsImport.kt.after @@ -0,0 +1,5 @@ +import java.lang.annotation.ElementType + +fun foo(){ + val e : java.lang.annotation.ElementType = ElementType.FIELD +} diff --git a/idea/testData/completion/handlers/smart/JavaStaticField.kt b/idea/testData/completion/handlers/smart/JavaStaticField.kt new file mode 100644 index 00000000000..7ffc3c7384f --- /dev/null +++ b/idea/testData/completion/handlers/smart/JavaStaticField.kt @@ -0,0 +1,5 @@ +import java.util.Locale + +fun foo(){ + var l : Locale = +} diff --git a/idea/testData/completion/handlers/smart/JavaStaticField.kt.after b/idea/testData/completion/handlers/smart/JavaStaticField.kt.after new file mode 100644 index 00000000000..9fd249c66f2 --- /dev/null +++ b/idea/testData/completion/handlers/smart/JavaStaticField.kt.after @@ -0,0 +1,5 @@ +import java.util.Locale + +fun foo(){ + var l : Locale = Locale.ENGLISH +} diff --git a/idea/testData/completion/handlers/smart/JavaStaticFieldInsertImport.kt.after b/idea/testData/completion/handlers/smart/JavaStaticFieldInsertImport.kt.after index 9b67d7c879c..fe5cbe1622b 100644 --- a/idea/testData/completion/handlers/smart/JavaStaticFieldInsertImport.kt.after +++ b/idea/testData/completion/handlers/smart/JavaStaticFieldInsertImport.kt.after @@ -1,5 +1,5 @@ import java.util.Locale fun foo(){ - var l : java.util.Locale = Locale.ENGLISH + var l : java.util.Locale = Locale.ENGLISH } diff --git a/idea/testData/completion/handlers/smart/JavaStaticMethodInsertsImport.kt b/idea/testData/completion/handlers/smart/JavaStaticMethodInsertsImport.kt new file mode 100644 index 00000000000..c99016af90e --- /dev/null +++ b/idea/testData/completion/handlers/smart/JavaStaticMethodInsertsImport.kt @@ -0,0 +1,3 @@ +fun foo(){ + val l : java.util.Calendar = +} diff --git a/idea/testData/completion/handlers/smart/JavaStaticMethodInsertsImport.kt.after b/idea/testData/completion/handlers/smart/JavaStaticMethodInsertsImport.kt.after new file mode 100644 index 00000000000..58a61d9b553 --- /dev/null +++ b/idea/testData/completion/handlers/smart/JavaStaticMethodInsertsImport.kt.after @@ -0,0 +1,5 @@ +import java.util.Calendar + +fun foo(){ + val l : java.util.Calendar = Calendar.getInstance() +} diff --git a/idea/testData/completion/smart/JavaStaticMethods.kt b/idea/testData/completion/smart/JavaStaticMethods.kt index 907d4ac16ff..974cca331b8 100644 --- a/idea/testData/completion/smart/JavaStaticMethods.kt +++ b/idea/testData/completion/smart/JavaStaticMethods.kt @@ -1,5 +1,7 @@ fun foo(){ - val l : java.lang.Thread = + val l : java.util.Calendar = } -// EXIST: { lookupString:"Thread.currentThread", itemText:"Thread.currentThread()", tailText:" (java.lang)", typeText:"Thread" } +// EXIST: { lookupString:"Calendar.getInstance", itemText:"Calendar.getInstance", tailText:"() (java.util)", typeText:"Calendar" } +// EXIST: { lookupString:"Calendar.getInstance", itemText:"Calendar.getInstance", tailText:"(TimeZone) (java.util)", typeText:"Calendar" } +// EXIST: { lookupString:"Calendar.getInstance", itemText:"Calendar.getInstance", tailText:"(TimeZone, Locale) (java.util)", typeText:"Calendar" } diff --git a/idea/tests/org/jetbrains/jet/completion/handlers/CompletionHandlerTestBase.kt b/idea/tests/org/jetbrains/jet/completion/handlers/CompletionHandlerTestBase.kt index bfdbda5c219..97d2090e32b 100644 --- a/idea/tests/org/jetbrains/jet/completion/handlers/CompletionHandlerTestBase.kt +++ b/idea/tests/org/jetbrains/jet/completion/handlers/CompletionHandlerTestBase.kt @@ -68,31 +68,31 @@ public abstract class CompletionHandlerTestBase() : JetLightCodeInsightFixtureTe private fun getExistentLookupElement(lookupString : String?, tailText : String?) : LookupElement? { val lookup = LookupManager.getInstance(getProject())?.getActiveLookup() as LookupImpl? + if (lookup == null) return null var foundElement : LookupElement? = null - if (lookup != null) { - val presentation = LookupElementPresentation() - for (lookupElement in lookup.getItems()!!) { - - val lookupOk : Boolean - if (lookupString != null) { - lookupOk = lookupElement.getLookupString().contains(lookupString) - } - else { - lookupOk = true - } + val presentation = LookupElementPresentation() + for (lookupElement in lookup.getItems()) { + val lookupOk : Boolean + if (lookupString != null) { + lookupOk = lookupElement.getLookupString().contains(lookupString) + } + else { + lookupOk = true + } + if (lookupOk) { val tailOk : Boolean if (tailText != null) { lookupElement.renderElement(presentation) val itemTailText : String? = presentation.getTailText() - tailOk = itemTailText != null && (itemTailText.contains(tailText)) + tailOk = itemTailText != null && itemTailText.contains(tailText) } else { tailOk = true } - if (lookupOk && tailOk) { + if (tailOk) { if (foundElement != null) { Assert.fail("Several elements satisfy to completion restrictions") } @@ -102,6 +102,7 @@ public abstract class CompletionHandlerTestBase() : JetLightCodeInsightFixtureTe } } + if (foundElement == null) error("No element satisfy completion restrictions") return foundElement } diff --git a/idea/tests/org/jetbrains/jet/completion/handlers/SmartCompletionHandlerTest.kt b/idea/tests/org/jetbrains/jet/completion/handlers/SmartCompletionHandlerTest.kt index 5faa45822fb..195d12a064b 100644 --- a/idea/tests/org/jetbrains/jet/completion/handlers/SmartCompletionHandlerTest.kt +++ b/idea/tests/org/jetbrains/jet/completion/handlers/SmartCompletionHandlerTest.kt @@ -41,11 +41,17 @@ public class SmartCompletionHandlerTest() : CompletionHandlerTestBase() { fun testConstructorWithParameters() = doTest() fun testConstructorForNullable() = doTest() fun testConstructorForJavaClass() = doTest() - //fun testConstructorInsertsImport() = doTest() //TODO + fun testConstructorForGenericType() = doTest() + fun testConstructorInsertsImport() = doTest() + fun testConstructorInsertsImport2() = doTest() fun testJavaStaticMethod() = doTest(1, "Thread.currentThread", null, '\n') + fun testJavaStaticMethodInsertsImport() = doTest(1, "Calendar.getInstance", "(TimeZone)", '\n') fun testClassObjectMethod1() = doTest(1, "K.bar", null, '\n') fun testClassObjectMethod2() = doTest(1, "K.bar", null, '\n') - //fun testJavaStaticFieldInsertImport() = doTest(1, "Locale.ENGLISH", null, '\n') //TODO + fun testEnumMember() = doTest(1, "Foo.X", null, '\n') + fun testJavaEnumMemberInsertsImport() = doTest(1, "ElementType.FIELD", null, '\n') + fun testJavaStaticField() = doTest(1, "Locale.ENGLISH", null, '\n') + fun testJavaStaticFieldInsertImport() = doTest(1, "Locale.ENGLISH", null, '\n') fun testTabReplaceIdentifier() = doTest(1, "ss", null, '\t') fun testTabReplaceExpression() = doTest(1, "sss", null, '\t') fun testTabReplaceExpression2() = doTest(1, "sss", null, '\t') @@ -54,4 +60,5 @@ public class SmartCompletionHandlerTest() : CompletionHandlerTestBase() { fun testAnonymousObject1() = doTest(1, "object", null, '\t') fun testAnonymousObject2() = doTest(1, "object", null, '\t') fun testAnonymousObject3() = doTest(1, "object", null, '\t') + fun testAnonymousObjectInsertsImport() = doTest(1, "object", null, '\t') }