Smart completion: anonymous object creation + rewrote some code using LookupElementDecorator
This commit is contained in:
@@ -6,6 +6,17 @@
|
||||
<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.LookupElement void handleInsert(com.intellij.codeInsight.completion.InsertionContext) 0'>
|
||||
<annotation name='org.jetbrains.annotations.NotNull'/>
|
||||
</item>
|
||||
<item
|
||||
name='com.intellij.codeInsight.lookup.LookupElement void renderElement(com.intellij.codeInsight.lookup.LookupElementPresentation) 0'>
|
||||
<annotation name='org.jetbrains.annotations.NotNull'/>
|
||||
</item>
|
||||
<item
|
||||
name='com.intellij.codeInsight.lookup.LookupElementBuilder com.intellij.codeInsight.lookup.LookupElement withAutoCompletionPolicy(com.intellij.codeInsight.lookup.AutoCompletionPolicy)'>
|
||||
<annotation name='org.jetbrains.annotations.NotNull'/>
|
||||
</item>
|
||||
<item
|
||||
name='com.intellij.codeInsight.lookup.LookupElementBuilder com.intellij.codeInsight.lookup.LookupElementBuilder create(com.intellij.psi.PsiNamedElement)'>
|
||||
<annotation name='org.jetbrains.annotations.NotNull'/>
|
||||
@@ -42,6 +53,10 @@
|
||||
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 withRenderer(com.intellij.codeInsight.lookup.LookupElementRenderer<com.intellij.codeInsight.lookup.LookupElement>)'>
|
||||
<annotation name='org.jetbrains.annotations.NotNull'/>
|
||||
</item>
|
||||
<item
|
||||
name='com.intellij.codeInsight.lookup.LookupElementBuilder com.intellij.codeInsight.lookup.LookupElementBuilder withStrikeoutness(boolean)'>
|
||||
<annotation name='org.jetbrains.annotations.NotNull'/>
|
||||
@@ -50,6 +65,10 @@
|
||||
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.LookupElementBuilder com.intellij.codeInsight.lookup.LookupElementBuilder withTailText(java.lang.String, boolean)'>
|
||||
<annotation name='org.jetbrains.annotations.NotNull'/>
|
||||
</item>
|
||||
<item
|
||||
name='com.intellij.codeInsight.lookup.LookupElementBuilder com.intellij.codeInsight.lookup.LookupElementBuilder withTypeText(java.lang.String)'>
|
||||
<annotation name='org.jetbrains.annotations.NotNull'/>
|
||||
@@ -58,6 +77,20 @@
|
||||
name='com.intellij.codeInsight.lookup.LookupElementBuilder com.intellij.codeInsight.lookup.LookupElementBuilder withTypeText(java.lang.String, boolean)'>
|
||||
<annotation name='org.jetbrains.annotations.NotNull'/>
|
||||
</item>
|
||||
<item
|
||||
name='com.intellij.codeInsight.lookup.LookupElementDecorator void renderElement(com.intellij.codeInsight.lookup.LookupElementPresentation) 0'>
|
||||
<annotation name='org.jetbrains.annotations.NotNull'/>
|
||||
</item>
|
||||
<item
|
||||
name='com.intellij.codeInsight.lookup.LookupElementRenderer void renderElement(T, com.intellij.codeInsight.lookup.LookupElementPresentation)'>
|
||||
<annotation name='jet.runtime.typeinfo.KotlinSignature'>
|
||||
<val name="value" val=""fun renderElement(element: T?, presentation: LookupElementPresentation): Unit""/>
|
||||
</annotation>
|
||||
</item>
|
||||
<item
|
||||
name='com.intellij.codeInsight.lookup.LookupElementRenderer void renderElement(T, com.intellij.codeInsight.lookup.LookupElementPresentation) 1'>
|
||||
<annotation name='org.jetbrains.annotations.NotNull'/>
|
||||
</item>
|
||||
<item
|
||||
name='com.intellij.codeInsight.lookup.MutableLookupElement com.intellij.codeInsight.lookup.MutableLookupElement<T> setInsertHandler(com.intellij.codeInsight.completion.InsertHandler<? extends com.intellij.codeInsight.lookup.LookupElement>)'>
|
||||
<annotation name='org.jetbrains.annotations.NotNull'/>
|
||||
|
||||
@@ -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<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) {
|
||||
return listOf(lookupElement.withPresentableText(presentableText).withInsertHandler(insertHandler))
|
||||
val insertHandler: InsertHandler<LookupElement>
|
||||
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<LookupElement>{
|
||||
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<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
|
||||
insertHandler = JetFunctionInsertHandler(caretPosition, BracketType.PARENTHESIS)
|
||||
}
|
||||
|
||||
return listOf()
|
||||
val lookupElementDecorated = object: LookupElementDecorator<LookupElement>(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<LookupElement> {
|
||||
@@ -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<LookupElement>?
|
||||
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>(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{
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
trait Foo
|
||||
|
||||
var a : Foo = <caret>
|
||||
@@ -0,0 +1,3 @@
|
||||
trait Foo
|
||||
|
||||
var a : Foo = object: Foo {<caret>}
|
||||
@@ -0,0 +1,3 @@
|
||||
abstract class Foo
|
||||
|
||||
var a : Foo = <caret>
|
||||
@@ -0,0 +1,3 @@
|
||||
abstract class Foo
|
||||
|
||||
var a : Foo = object: Foo() {<caret>}
|
||||
@@ -0,0 +1 @@
|
||||
var r : Runnable = <caret>
|
||||
@@ -0,0 +1,5 @@
|
||||
var r : Runnable = object: Runnable {
|
||||
override fun run() {
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
trait Foo
|
||||
|
||||
var a : Foo = <caret>
|
||||
|
||||
// ABSENT: Foo
|
||||
// EXIST: { lookupString:"object", itemText:"object: Foo{...}" }
|
||||
@@ -0,0 +1,6 @@
|
||||
abstract class Foo
|
||||
|
||||
var a : Foo = <caret>
|
||||
|
||||
// ABSENT: Foo
|
||||
// EXIST: { lookupString:"object", itemText:"object: Foo(){...}" }
|
||||
@@ -0,0 +1,4 @@
|
||||
var a : Appendable = <caret>
|
||||
|
||||
// ABSENT: Appendable
|
||||
// EXIST: { lookupString:"object", itemText:"object: Appendable{...}" }
|
||||
@@ -1,7 +0,0 @@
|
||||
abstract class Foo
|
||||
|
||||
fun foo(p : Any){
|
||||
var a : Foo = <caret>
|
||||
}
|
||||
|
||||
// ABSENT: Foo
|
||||
@@ -1,3 +0,0 @@
|
||||
var a : Appendable = <caret>
|
||||
|
||||
// ABSENT: Appendable
|
||||
@@ -1,7 +0,0 @@
|
||||
trait Foo
|
||||
|
||||
fun foo(p : Any){
|
||||
var a : Foo = <caret>
|
||||
}
|
||||
|
||||
// ABSENT: Foo
|
||||
@@ -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");
|
||||
|
||||
@@ -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')
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user