diff --git a/annotations/com/intellij/codeInsight/lookup/annotations.xml b/annotations/com/intellij/codeInsight/lookup/annotations.xml
index 2c3b30ff6ac..8ad65130b35 100644
--- a/annotations/com/intellij/codeInsight/lookup/annotations.xml
+++ b/annotations/com/intellij/codeInsight/lookup/annotations.xml
@@ -6,6 +6,17 @@
-
+ -
+
+
+ -
+
+
+ -
+
+
-
@@ -42,6 +53,10 @@
name='com.intellij.codeInsight.lookup.LookupElementBuilder com.intellij.codeInsight.lookup.LookupElementBuilder withPresentableText(java.lang.String)'>
+ -
+
+
-
@@ -50,6 +65,10 @@
name='com.intellij.codeInsight.lookup.LookupElementBuilder com.intellij.codeInsight.lookup.LookupElementBuilder withTailText(java.lang.String)'>
+ -
+
+
-
@@ -58,6 +77,20 @@
name='com.intellij.codeInsight.lookup.LookupElementBuilder com.intellij.codeInsight.lookup.LookupElementBuilder withTypeText(java.lang.String, boolean)'>
+ -
+
+
+ -
+
+
+
+
+ -
+
+
-
diff --git a/idea/src/org/jetbrains/jet/plugin/completion/SmartCompletion.kt b/idea/src/org/jetbrains/jet/plugin/completion/SmartCompletion.kt
index 96ef59ea5ce..aeff3a5e59a 100644
--- a/idea/src/org/jetbrains/jet/plugin/completion/SmartCompletion.kt
+++ b/idea/src/org/jetbrains/jet/plugin/completion/SmartCompletion.kt
@@ -26,6 +26,9 @@ import com.intellij.psi.PsiElement
import com.intellij.psi.PsiClass
import com.intellij.psi.PsiModifier
import com.intellij.psi.util.PsiTreeUtil
+import com.intellij.openapi.editor.EditorModificationUtil
+import org.jetbrains.jet.plugin.codeInsight.ImplementMethodsHandler
+import com.intellij.psi.PsiDocumentManager
trait SmartCompletionData{
fun accepts(descriptor: DeclarationDescriptor): Boolean
@@ -122,12 +125,13 @@ private fun typeInstantiationItems(expectedType: JetType, resolveSession: Cancel
val typeConstructor: TypeConstructor = expectedType.getConstructor()
val classifier: ClassifierDescriptor? = typeConstructor.getDeclarationDescriptor()
if (!(classifier is ClassDescriptor)) return listOf()
- if (classifier.getModality() == Modality.ABSTRACT) return listOf()
//TODO: check for constructor's visibility
val lookupElement = DescriptorLookupConverter.createLookupElement(resolveSession, bindingContext, classifier)
+ var lookupString = lookupElement.getLookupString()
+
val typeArgs = expectedType.getArguments()
//TODO: shouldn't be method in DescriptorRenderer to render type arguments?
val typeArgsText =
@@ -135,27 +139,59 @@ private fun typeInstantiationItems(expectedType: JetType, resolveSession: Cancel
""
else
typeArgs.map { DescriptorRenderer.TEXT.renderType(it.getType()) }.makeString(", ", "<", ">")
- val presentableText = lookupElement.getLookupString() + typeArgsText + "()"
+ var itemText = 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) {
- return listOf(lookupElement.withPresentableText(presentableText).withInsertHandler(insertHandler))
+ val insertHandler: InsertHandler
+ var suppressAutoInsertion: Boolean = false
+ 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)
+ }
+ }
+ suppressAutoInsertion = true
}
- else if (lookupElement is JavaPsiClassReferenceElement) {
- return listOf(lookupElement.setPresentableText(presentableText).setInsertHandler(insertHandler))
+ else {
+ itemText += "()"
+ 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
+ insertHandler = JetFunctionInsertHandler(caretPosition, BracketType.PARENTHESIS)
}
- return listOf()
+ val lookupElementDecorated = object: LookupElementDecorator(lookupElement){
+ override fun getLookupString() = lookupString
+
+ override fun renderElement(presentation: LookupElementPresentation) {
+ lookupElement.renderElement(presentation)
+ presentation.setItemText(itemText)
+ }
+
+ override fun handleInsert(context: InsertionContext) {
+ insertHandler.handleInsert(context, lookupElement)
+ }
+ }
+
+ if (suppressAutoInsertion) {
+ return listOf(AutoCompletionPolicy.NEVER_AUTOCOMPLETE.applyPolicy(lookupElementDecorated))
+ }
+ else{
+ return listOf(lookupElementDecorated)
+ }
}
private fun thisItems(context: JetExpression, expectedType: JetType, bindingContext: BindingContext): Iterable {
@@ -273,27 +309,45 @@ private fun staticMembers(context: JetExpression, expectedType: JetType, resolve
.filterTo(descriptors) { it is ClassDescriptor && it.getKind() == ClassKind.ENUM_ENTRY }
}
- return descriptors
- .filter { !(it is DeclarationDescriptorWithVisibility) || Visibilities.isVisible(it, scope.getContainingDeclaration()) }
- .map {
- val lookupElement = DescriptorLookupConverter.createLookupElement(resolveSession, bindingContext, it)
- val presentation = LookupElementPresentation()
- lookupElement.renderElement(presentation)
- var builder = LookupElementBuilder.create(lookupElement.getObject(), classDescriptor.getName().asString() + "." + lookupElement.getLookupString())
- .withIcon(presentation.getIcon())
- .withStrikeoutness(presentation.isStrikeout())
- .withTailText(" (" + DescriptorUtils.getFqName(classDescriptor.getContainingDeclaration()) + ")")
- .withTypeText(if (!presentation.getTypeText().isNullOrEmpty())
- presentation.getTypeText()
- else
- DescriptorRenderer.TEXT.renderType(classDescriptor.getDefaultType()))
- if (it is FunctionDescriptor) {
- builder = builder.withPresentableText(builder.getLookupString() + "()")
- val caretPosition = if (it.getValueParameters().empty) CaretPosition.AFTER_BRACKETS else CaretPosition.IN_BRACKETS
- builder = builder.withInsertHandler(JetFunctionInsertHandler(caretPosition, BracketType.PARENTHESIS))
- }
- builder
+ 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?
+ if (descriptor is FunctionDescriptor) {
+ itemText += "()"
+ val caretPosition = if (descriptor.getValueParameters().empty) CaretPosition.AFTER_BRACKETS else CaretPosition.IN_BRACKETS
+ insertHandler = JetFunctionInsertHandler(caretPosition, BracketType.PARENTHESIS)
+ }
+ else {
+ insertHandler = null
+ }
+ 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()) + ")")
+ 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)
+ }
+ }
+ }
+ }
+
+ return descriptors
+ .filter { !(it is DeclarationDescriptorWithVisibility) || Visibilities.isVisible(it, scope.getContainingDeclaration()) }
+ .map({toLookupElement(it)}) //TODO: use ::toLookupElement but it causes compiler to crash
}
private fun isSubtypeOf(t: JetType, expectedType: JetType): Boolean{
diff --git a/idea/testData/completion/handlers/smart/AnonymousObject1.kt b/idea/testData/completion/handlers/smart/AnonymousObject1.kt
new file mode 100644
index 00000000000..e7b59ef3ae0
--- /dev/null
+++ b/idea/testData/completion/handlers/smart/AnonymousObject1.kt
@@ -0,0 +1,3 @@
+trait Foo
+
+var a : Foo =
diff --git a/idea/testData/completion/handlers/smart/AnonymousObject1.kt.after b/idea/testData/completion/handlers/smart/AnonymousObject1.kt.after
new file mode 100644
index 00000000000..e16a0ad3ec7
--- /dev/null
+++ b/idea/testData/completion/handlers/smart/AnonymousObject1.kt.after
@@ -0,0 +1,3 @@
+trait Foo
+
+var a : Foo = object: Foo {}
diff --git a/idea/testData/completion/handlers/smart/AnonymousObject2.kt b/idea/testData/completion/handlers/smart/AnonymousObject2.kt
new file mode 100644
index 00000000000..824e20a25de
--- /dev/null
+++ b/idea/testData/completion/handlers/smart/AnonymousObject2.kt
@@ -0,0 +1,3 @@
+abstract class Foo
+
+var a : Foo =
diff --git a/idea/testData/completion/handlers/smart/AnonymousObject2.kt.after b/idea/testData/completion/handlers/smart/AnonymousObject2.kt.after
new file mode 100644
index 00000000000..3add17a6704
--- /dev/null
+++ b/idea/testData/completion/handlers/smart/AnonymousObject2.kt.after
@@ -0,0 +1,3 @@
+abstract class Foo
+
+var a : Foo = object: Foo() {}
diff --git a/idea/testData/completion/handlers/smart/AnonymousObject3.kt b/idea/testData/completion/handlers/smart/AnonymousObject3.kt
new file mode 100644
index 00000000000..8fcf46277a5
--- /dev/null
+++ b/idea/testData/completion/handlers/smart/AnonymousObject3.kt
@@ -0,0 +1 @@
+var r : Runnable =
diff --git a/idea/testData/completion/handlers/smart/AnonymousObject3.kt.after b/idea/testData/completion/handlers/smart/AnonymousObject3.kt.after
new file mode 100644
index 00000000000..0598254f494
--- /dev/null
+++ b/idea/testData/completion/handlers/smart/AnonymousObject3.kt.after
@@ -0,0 +1,5 @@
+var r : Runnable = object: Runnable {
+ override fun run() {
+ throw UnsupportedOperationException()
+ }
+}
diff --git a/idea/testData/completion/smart/AnonymousObject1.kt b/idea/testData/completion/smart/AnonymousObject1.kt
new file mode 100644
index 00000000000..fc0486b0cb4
--- /dev/null
+++ b/idea/testData/completion/smart/AnonymousObject1.kt
@@ -0,0 +1,6 @@
+trait Foo
+
+var a : Foo =
+
+// ABSENT: Foo
+// EXIST: { lookupString:"object", itemText:"object: Foo{...}" }
diff --git a/idea/testData/completion/smart/AnonymousObject2.kt b/idea/testData/completion/smart/AnonymousObject2.kt
new file mode 100644
index 00000000000..74ee08a1b9c
--- /dev/null
+++ b/idea/testData/completion/smart/AnonymousObject2.kt
@@ -0,0 +1,6 @@
+abstract class Foo
+
+var a : Foo =
+
+// ABSENT: Foo
+// EXIST: { lookupString:"object", itemText:"object: Foo(){...}" }
diff --git a/idea/testData/completion/smart/AnonymousObjectForJavaInterface.kt b/idea/testData/completion/smart/AnonymousObjectForJavaInterface.kt
new file mode 100644
index 00000000000..326935a2fe6
--- /dev/null
+++ b/idea/testData/completion/smart/AnonymousObjectForJavaInterface.kt
@@ -0,0 +1,4 @@
+var a : Appendable =
+
+// ABSENT: Appendable
+// EXIST: { lookupString:"object", itemText:"object: Appendable{...}" }
\ No newline at end of file
diff --git a/idea/testData/completion/smart/NoConstructorForAbstract.kt b/idea/testData/completion/smart/NoConstructorForAbstract.kt
deleted file mode 100644
index 0b18a4584ca..00000000000
--- a/idea/testData/completion/smart/NoConstructorForAbstract.kt
+++ /dev/null
@@ -1,7 +0,0 @@
-abstract class Foo
-
-fun foo(p : Any){
- var a : Foo =
-}
-
-// ABSENT: Foo
diff --git a/idea/testData/completion/smart/NoConstructorForJavaInterface.kt b/idea/testData/completion/smart/NoConstructorForJavaInterface.kt
deleted file mode 100644
index 7dfd234c1c9..00000000000
--- a/idea/testData/completion/smart/NoConstructorForJavaInterface.kt
+++ /dev/null
@@ -1,3 +0,0 @@
-var a : Appendable =
-
-// ABSENT: Appendable
diff --git a/idea/testData/completion/smart/NoConstructorForTrait.kt b/idea/testData/completion/smart/NoConstructorForTrait.kt
deleted file mode 100644
index 26d16b3d75a..00000000000
--- a/idea/testData/completion/smart/NoConstructorForTrait.kt
+++ /dev/null
@@ -1,7 +0,0 @@
-trait Foo
-
-fun foo(p : Any){
- var a : Foo =
-}
-
-// ABSENT: Foo
diff --git a/idea/tests/org/jetbrains/jet/completion/JvmSmartCompletionTestGenerated.java b/idea/tests/org/jetbrains/jet/completion/JvmSmartCompletionTestGenerated.java
index 0adda257811..a1e85016c9a 100644
--- a/idea/tests/org/jetbrains/jet/completion/JvmSmartCompletionTestGenerated.java
+++ b/idea/tests/org/jetbrains/jet/completion/JvmSmartCompletionTestGenerated.java
@@ -36,6 +36,21 @@ public class JvmSmartCompletionTestGenerated extends AbstractJvmSmartCompletionT
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("idea/testData/completion/smart"), Pattern.compile("^(.+)\\.kt$"), true);
}
+ @TestMetadata("AnonymousObject1.kt")
+ public void testAnonymousObject1() throws Exception {
+ doTest("idea/testData/completion/smart/AnonymousObject1.kt");
+ }
+
+ @TestMetadata("AnonymousObject2.kt")
+ public void testAnonymousObject2() throws Exception {
+ doTest("idea/testData/completion/smart/AnonymousObject2.kt");
+ }
+
+ @TestMetadata("AnonymousObjectForJavaInterface.kt")
+ public void testAnonymousObjectForJavaInterface() throws Exception {
+ doTest("idea/testData/completion/smart/AnonymousObjectForJavaInterface.kt");
+ }
+
@TestMetadata("AutoCastedType.kt")
public void testAutoCastedType() throws Exception {
doTest("idea/testData/completion/smart/AutoCastedType.kt");
@@ -151,21 +166,6 @@ public class JvmSmartCompletionTestGenerated 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");
diff --git a/idea/tests/org/jetbrains/jet/completion/handlers/SmartCompletionHandlerTest.kt b/idea/tests/org/jetbrains/jet/completion/handlers/SmartCompletionHandlerTest.kt
index 5e05779187d..5faa45822fb 100644
--- a/idea/tests/org/jetbrains/jet/completion/handlers/SmartCompletionHandlerTest.kt
+++ b/idea/tests/org/jetbrains/jet/completion/handlers/SmartCompletionHandlerTest.kt
@@ -51,4 +51,7 @@ public class SmartCompletionHandlerTest() : CompletionHandlerTestBase() {
fun testTabReplaceExpression2() = doTest(1, "sss", null, '\t')
fun testTabReplaceExpression3() = doTest(1, "sss", null, '\t')
fun testTabReplaceOperand() = doTest(1, "b3", null, '\t')
+ fun testAnonymousObject1() = doTest(1, "object", null, '\t')
+ fun testAnonymousObject2() = doTest(1, "object", null, '\t')
+ fun testAnonymousObject3() = doTest(1, "object", null, '\t')
}