Completion: moved signatures from "item text" to tail
#KT-5652 Fixed
This commit is contained in:
@@ -30,6 +30,7 @@ import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.jet.plugin.util.IdeDescriptorRenderers
|
||||
import com.intellij.codeInsight.completion.PrefixMatcher
|
||||
import org.jetbrains.jet.lang.resolve.name.Name
|
||||
import com.intellij.codeInsight.lookup.LookupElementPresentation
|
||||
|
||||
enum class ItemPriority {
|
||||
MULTIPLE_ARGUMENTS_ITEM
|
||||
@@ -79,4 +80,11 @@ private fun qualifierName(descriptor: DeclarationDescriptor): String? = when (de
|
||||
else -> null
|
||||
}
|
||||
|
||||
fun PrefixMatcher.asNameFilter() = { (name: Name) -> !name.isSpecial() && prefixMatches(name.getIdentifier()) }
|
||||
fun PrefixMatcher.asNameFilter() = { (name: Name) -> !name.isSpecial() && prefixMatches(name.getIdentifier()) }
|
||||
|
||||
fun LookupElementPresentation.prependTailText(text: String, grayed: Boolean) {
|
||||
val tails = getTailFragments()
|
||||
clearTail()
|
||||
appendTailText(text, grayed)
|
||||
tails.forEach { appendTailText(it.text, it.isGrayed()) }
|
||||
}
|
||||
@@ -58,40 +58,43 @@ public object KotlinLookupElementFactory {
|
||||
return createLookupElementForJavaClass(declaration)
|
||||
}
|
||||
|
||||
val name = descriptor.getName().asString()
|
||||
var element = LookupElementBuilder.create(DeclarationDescriptorLookupObject(descriptor, analyzer, declaration), name)
|
||||
|
||||
var presentableText = name
|
||||
var typeText = ""
|
||||
var tailText = ""
|
||||
var element = LookupElementBuilder.create(DeclarationDescriptorLookupObject(descriptor, analyzer, declaration), descriptor.getName().asString())
|
||||
.withIcon(JetDescriptorIconProvider.getIcon(descriptor, declaration, Iconable.ICON_FLAG_VISIBILITY))
|
||||
|
||||
if (descriptor is FunctionDescriptor) {
|
||||
val returnType = descriptor.getReturnType()
|
||||
typeText = if (returnType != null) DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(returnType) else ""
|
||||
presentableText += DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderFunctionParameters(descriptor)
|
||||
when (descriptor) {
|
||||
is FunctionDescriptor -> {
|
||||
val returnType = descriptor.getReturnType()
|
||||
element = element.withTypeText(if (returnType != null) DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(returnType) else "")
|
||||
element = element.appendTailText(DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderFunctionParameters(descriptor), false)
|
||||
|
||||
if (descriptor.getExtensionReceiverParameter() != null) {
|
||||
tailText += " for " + DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(descriptor.getExtensionReceiverParameter()!!.getType())
|
||||
tailText += " in " + DescriptorUtils.getFqName(descriptor.getContainingDeclaration())
|
||||
if (descriptor.getExtensionReceiverParameter() != null) {
|
||||
val tail = " for " + DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(descriptor.getExtensionReceiverParameter()!!.getType()) +
|
||||
" in " + DescriptorUtils.getFqName(descriptor.getContainingDeclaration())
|
||||
element = element.appendTailText(tail, true)
|
||||
}
|
||||
}
|
||||
|
||||
is VariableDescriptor -> {
|
||||
element = element.withTypeText(DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(descriptor.getType()))
|
||||
}
|
||||
|
||||
is ClassDescriptor -> {
|
||||
element = element.appendTailText(" (" + DescriptorUtils.getFqName(descriptor.getContainingDeclaration()) + ")", true)
|
||||
}
|
||||
|
||||
else -> {
|
||||
element = element.withTypeText(DescriptorRenderer.SHORT_NAMES_IN_TYPES.render(descriptor))
|
||||
}
|
||||
}
|
||||
else if (descriptor is VariableDescriptor) {
|
||||
typeText = DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(descriptor.getType())
|
||||
}
|
||||
else if (descriptor is ClassDescriptor) {
|
||||
tailText = " (" + DescriptorUtils.getFqName(descriptor.getContainingDeclaration()) + ")"
|
||||
}
|
||||
else {
|
||||
typeText = DescriptorRenderer.SHORT_NAMES_IN_TYPES.render(descriptor)
|
||||
|
||||
if (KotlinBuiltIns.getInstance().isDeprecated(descriptor)) {
|
||||
element = element.withStrikeoutness(true)
|
||||
}
|
||||
|
||||
val insertHandler = getDefaultInsertHandler(descriptor)
|
||||
element = element.withInsertHandler(insertHandler)
|
||||
|
||||
element = element.withTailText(tailText, true).withTypeText(typeText).withPresentableText(presentableText)
|
||||
element = element.withIcon(JetDescriptorIconProvider.getIcon(descriptor, declaration, Iconable.ICON_FLAG_VISIBILITY))
|
||||
element = element.withStrikeoutness(KotlinBuiltIns.getInstance().isDeprecated(descriptor))
|
||||
|
||||
if (insertHandler is KotlinFunctionInsertHandler && insertHandler.lambdaInfo != null) {
|
||||
element.putUserData<Boolean>(KotlinCompletionCharFilter.ACCEPT_OPENING_BRACE, true)
|
||||
}
|
||||
|
||||
@@ -80,7 +80,11 @@ class LookupElementsCollector(
|
||||
addElement(object : LookupElementDecorator<LookupElement>(lookupElement) {
|
||||
override fun renderElement(presentation: LookupElementPresentation) {
|
||||
super.renderElement(presentation)
|
||||
presentation.setItemText(getLookupString() + " " + buildLambdaPresentation(parameterType))
|
||||
|
||||
val tails = presentation.getTailFragments()
|
||||
presentation.clearTail()
|
||||
presentation.appendTailText(" " + buildLambdaPresentation(parameterType), false)
|
||||
tails.drop(1)/*drop old function signature*/.forEach { presentation.appendTailText(it.text, it.isGrayed()) }
|
||||
}
|
||||
|
||||
override fun handleInsert(context: InsertionContext) {
|
||||
|
||||
@@ -246,7 +246,8 @@ class SmartCompletion(val expression: JetSimpleNameExpression,
|
||||
override fun renderElement(presentation: LookupElementPresentation) {
|
||||
super.renderElement(presentation)
|
||||
presentation.setItemText(text)
|
||||
presentation.setTypeText("")
|
||||
presentation.clearTail()
|
||||
presentation.setTypeText(null)
|
||||
}
|
||||
|
||||
override fun handleInsert(context: InsertionContext) {
|
||||
|
||||
@@ -74,6 +74,7 @@ class TypeInstantiationItems(val resolveSession: ResolveSessionForBodies, val bi
|
||||
|
||||
val typeArgs = jetType.getArguments()
|
||||
var itemText = lookupString + DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderTypeArguments(typeArgs)
|
||||
var signatureText: String? = null
|
||||
|
||||
val insertHandler: InsertHandler<LookupElement>
|
||||
val typeText = qualifiedNameForSourceCode(classifier) + IdeDescriptorRenderers.SOURCE_CODE.renderTypeArguments(typeArgs)
|
||||
@@ -99,7 +100,7 @@ class TypeInstantiationItems(val resolveSession: ResolveSessionForBodies, val bi
|
||||
}
|
||||
else {
|
||||
//TODO: when constructor has one parameter of lambda type with more than one parameter, generate special additional item
|
||||
itemText += when (visibleConstructors.size) {
|
||||
signatureText = when (visibleConstructors.size) {
|
||||
0 -> "()"
|
||||
1 -> DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderFunctionParameters(visibleConstructors.single())
|
||||
else -> "(...)"
|
||||
@@ -138,6 +139,10 @@ class TypeInstantiationItems(val resolveSession: ResolveSessionForBodies, val bi
|
||||
override fun renderElement(presentation: LookupElementPresentation) {
|
||||
getDelegate().renderElement(presentation)
|
||||
presentation.setItemText(itemText)
|
||||
|
||||
if (signatureText != null) {
|
||||
presentation.prependTailText(signatureText!!, false)
|
||||
}
|
||||
}
|
||||
|
||||
override fun handleInsert(context: InsertionContext) {
|
||||
|
||||
@@ -4,4 +4,4 @@ fun some() {
|
||||
tes<caret>
|
||||
}
|
||||
|
||||
// EXIST: { lookupString:"test", itemText:"test(a: Int)" }
|
||||
// EXIST: { lookupString:"test", itemText:"test", tailText:"(a: Int)" }
|
||||
@@ -4,5 +4,5 @@ fun test() {
|
||||
fo<caret>
|
||||
}
|
||||
|
||||
// EXIST: { lookupString:"foo", itemText: "foo(p: (String, Char) -> Unit)", typeText:"Unit" }
|
||||
// EXIST: { lookupString:"foo", itemText: "foo { (String, Char) -> ... }", typeText:"Unit" }
|
||||
// EXIST: { lookupString:"foo", itemText: "foo", tailText: "(p: (String, Char) -> Unit)", typeText:"Unit" }
|
||||
// EXIST: { lookupString:"foo", itemText: "foo", tailText: " { (String, Char) -> ... }", typeText:"Unit" }
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
fun String.foo(p: (String, Char) -> Unit){}
|
||||
|
||||
fun test() {
|
||||
"".fo<caret>
|
||||
}
|
||||
|
||||
// EXIST: { lookupString:"foo", itemText: "foo", tailText: "(p: (String, Char) -> Unit) for String in <root>", typeText:"Unit" }
|
||||
// EXIST: { lookupString:"foo", itemText: "foo", tailText: " { (String, Char) -> ... } for String in <root>", typeText:"Unit" }
|
||||
@@ -8,5 +8,5 @@ fun firstFun() {
|
||||
}
|
||||
|
||||
// INVOCATION_COUNT: 1
|
||||
// EXIST: { lookupString:"toLinkedList", itemText:"toLinkedList()", tailText:" for Iterable<T> in kotlin" }
|
||||
// EXIST: { lookupString:"toLinkedList", itemText:"toLinkedList", tailText:"() for Iterable<T> in kotlin" }
|
||||
// NUMBER: 1
|
||||
|
||||
@@ -2,4 +2,5 @@ fun foo(){
|
||||
val l : java.util.Calendar = <caret>
|
||||
}
|
||||
|
||||
// ELEMENT_TEXT: Calendar.getInstance(TimeZone!)
|
||||
// ELEMENT_TEXT: Calendar.getInstance
|
||||
// TAIL_TEXT: (TimeZone!)
|
||||
|
||||
@@ -4,4 +4,5 @@ fun foo(){
|
||||
val l : java.util.Calendar = Calendar.getInstance(<caret>)
|
||||
}
|
||||
|
||||
// ELEMENT_TEXT: Calendar.getInstance(TimeZone!)
|
||||
// ELEMENT_TEXT: Calendar.getInstance
|
||||
// TAIL_TEXT: (TimeZone!)
|
||||
|
||||
@@ -6,4 +6,5 @@ fun bar() {
|
||||
foo(<caret>)
|
||||
}
|
||||
|
||||
// ELEMENT_TEXT: "?: getString(i: Int)"
|
||||
// ELEMENT_TEXT: "?: getString"
|
||||
// TAIL_TEXT: "(i: Int)"
|
||||
|
||||
@@ -6,4 +6,5 @@ fun bar() {
|
||||
foo(getString(<caret>) ?: )
|
||||
}
|
||||
|
||||
// ELEMENT_TEXT: "?: getString(i: Int)"
|
||||
// ELEMENT_TEXT: "?: getString"
|
||||
// TAIL_TEXT: "(i: Int)"
|
||||
|
||||
@@ -8,4 +8,5 @@ fun foo(){
|
||||
val k : K = <caret>
|
||||
}
|
||||
|
||||
// ELEMENT_TEXT: "!! K.bar()"
|
||||
// ELEMENT_TEXT: "!! K.bar"
|
||||
// TAIL_TEXT: "()"
|
||||
|
||||
@@ -8,4 +8,5 @@ fun foo(){
|
||||
val k : K = K.bar()!!<caret>
|
||||
}
|
||||
|
||||
// ELEMENT_TEXT: "!! K.bar()"
|
||||
// ELEMENT_TEXT: "!! K.bar"
|
||||
// TAIL_TEXT: "()"
|
||||
|
||||
@@ -15,7 +15,7 @@ fun foo(){
|
||||
}
|
||||
|
||||
// EXIST: { lookupString:"foo", itemText:"K.foo", tailText:" (sample)", typeText:"K" }
|
||||
// EXIST: { lookupString:"bar", itemText:"K.bar()", tailText:" (sample)", typeText:"K" }
|
||||
// EXIST: { lookupString:"bar", itemText:"K.bar", tailText:"() (sample)", typeText:"K" }
|
||||
// ABSENT: { itemText: "K.x" }
|
||||
// ABSENT: { itemText:"K.kk" }
|
||||
// EXIST: { lookupString:"kk", itemText:"!! K.kk", tailText:" (sample)", typeText:"K?" }
|
||||
|
||||
@@ -14,6 +14,6 @@ fun foo(){
|
||||
}
|
||||
|
||||
// EXIST: { lookupString:"foo", itemText:"K.foo", tailText:" (sample)", typeText:"K" }
|
||||
// EXIST: { lookupString:"bar", itemText:"K.bar()", tailText:" (sample)", typeText:"K" }
|
||||
// EXIST: { lookupString:"bar", itemText:"K.bar", tailText:"() (sample)", typeText:"K" }
|
||||
// ABSENT: { itemText: "K.x" }
|
||||
// EXIST: { lookupString:"kk", itemText:"K.kk", tailText:" (sample)", typeText:"K?" }
|
||||
|
||||
@@ -2,4 +2,4 @@ class Foo
|
||||
|
||||
var a : Foo = <caret>
|
||||
|
||||
// EXIST: { lookupString:"Foo", itemText:"Foo()" }
|
||||
// EXIST: { lookupString:"Foo", itemText:"Foo", tailText: "() (<root>)" }
|
||||
|
||||
@@ -4,4 +4,4 @@ fun foo(p : Any){
|
||||
var a : Foo<String> = <caret>
|
||||
}
|
||||
|
||||
// EXIST: { lookupString:"Foo", itemText:"Foo<String>()" }
|
||||
// EXIST: { lookupString:"Foo", itemText:"Foo<String>", tailText:"() (<root>)" }
|
||||
|
||||
@@ -2,4 +2,4 @@ import java.util.Date
|
||||
|
||||
var a : Date = <caret>
|
||||
|
||||
// EXIST: { lookupString:"Date", itemText:"Date(...)" }
|
||||
// EXIST: { lookupString:"Date", itemText:"Date", tailText:"(...) (java.util)" }
|
||||
|
||||
@@ -4,4 +4,4 @@ fun foo(p : Any){
|
||||
var a : Foo? = <caret>
|
||||
}
|
||||
|
||||
// EXIST: { lookupString:"Foo", itemText:"Foo()" }
|
||||
// EXIST: { lookupString:"Foo", itemText:"Foo", tailText: "() (<root>)" }
|
||||
|
||||
@@ -2,4 +2,4 @@ class Foo(val p1: String, val p2: Any?)
|
||||
|
||||
var a : Foo = <caret>
|
||||
|
||||
// EXIST: { lookupString:"Foo", itemText:"Foo(p1: String, p2: Any?)" }
|
||||
// EXIST: { lookupString:"Foo", itemText:"Foo", tailText:"(p1: String, p2: Any?) (<root>)" }
|
||||
|
||||
@@ -26,4 +26,4 @@ fun f3() : String{}
|
||||
// EXIST: f1
|
||||
// EXIST: f2
|
||||
// ABSENT: f3
|
||||
// EXIST: { lookupString:"Foo", itemText:"Foo()" }
|
||||
// EXIST: { lookupString:"Foo", itemText:"Foo", tailText: "() (<root>)" }
|
||||
|
||||
@@ -7,7 +7,7 @@ fun bar() {
|
||||
fun f1(){}
|
||||
fun f2(i: Int){}
|
||||
|
||||
// EXIST: { lookupString:"::f1", itemText:"::f1", tailText:"", typeText:"" }
|
||||
// EXIST: { lookupString:"::f1", itemText:"::f1", tailText:null, typeText:null }
|
||||
// ABSENT: ::f2
|
||||
// ABSENT: ::Unit
|
||||
// ABSENT: ::Nothing
|
||||
|
||||
@@ -6,7 +6,7 @@ fun bar() {
|
||||
foo1() ?: <caret>
|
||||
}
|
||||
|
||||
// EXIST: { itemText:"foo3()" }
|
||||
// ABSENT: { itemText:"foo2()" }
|
||||
// EXIST: { itemText:"!! foo2()" }
|
||||
// EXIST: { itemText:"?: foo2()" }
|
||||
// EXIST: { itemText:"foo3" }
|
||||
// ABSENT: { itemText:"foo2" }
|
||||
// EXIST: { itemText:"!! foo2" }
|
||||
// EXIST: { itemText:"?: foo2" }
|
||||
|
||||
@@ -2,6 +2,6 @@ fun foo(){
|
||||
val l : java.util.Calendar = <caret>
|
||||
}
|
||||
|
||||
// EXIST: { lookupString:"getInstance", itemText:"Calendar.getInstance()", tailText:" (java.util)", typeText:"Calendar!" }
|
||||
// EXIST: { lookupString:"getInstance", itemText:"Calendar.getInstance(TimeZone!)", tailText:" (java.util)", typeText:"Calendar!" }
|
||||
// EXIST: { lookupString:"getInstance", itemText:"Calendar.getInstance(TimeZone!, Locale!)", tailText:" (java.util)", typeText:"Calendar!" }
|
||||
// EXIST: { lookupString:"getInstance", itemText:"Calendar.getInstance", tailText:"() (java.util)", typeText:"Calendar!" }
|
||||
// EXIST: { lookupString:"getInstance", itemText:"Calendar.getInstance", tailText:"(TimeZone!) (java.util)", typeText:"Calendar!" }
|
||||
// EXIST: { lookupString:"getInstance", itemText:"Calendar.getInstance", tailText:"(TimeZone!, Locale!) (java.util)", typeText:"Calendar!" }
|
||||
|
||||
@@ -10,4 +10,4 @@ fun foo(): X {
|
||||
}
|
||||
|
||||
// ABSENT: f
|
||||
// EXIST: { lookupString:"g", itemText:"X.g()" }
|
||||
// EXIST: { lookupString:"g", itemText:"X.g", tailText:"() (<root>)" }
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
var a : Runnable = <caret>
|
||||
|
||||
// EXIST: {"lookupString":"Runnable", "tailText":"", "typeText":"Runnable", "itemText":"Runnable(function: () -> Unit)"}
|
||||
// EXIST: {"lookupString":"Runnable", "itemText":"Runnable", "tailText":"(function: () -> Unit)", "typeText":"Runnable"}
|
||||
|
||||
@@ -20,6 +20,7 @@ import com.google.common.base.Function;
|
||||
import com.google.common.collect.Collections2;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonNull;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import com.intellij.codeInsight.lookup.LookupElement;
|
||||
@@ -75,7 +76,10 @@ public class ExpectedCompletionUtils {
|
||||
if (!validKeys.contains(key)) {
|
||||
throw new RuntimeException("Invalid json property '" + key + "'");
|
||||
}
|
||||
map.put(key, entry.getValue().getAsString());
|
||||
JsonElement value = entry.getValue();
|
||||
if (!(value instanceof JsonNull)) {
|
||||
map.put(key, value.getAsString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -298,6 +298,12 @@ public class JSBasicCompletionTestGenerated extends AbstractJSBasicCompletionTes
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("HigherOrderFunction2.kt")
|
||||
public void testHigherOrderFunction2() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/basic/common/HigherOrderFunction2.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("ImportedEnumMembers.kt")
|
||||
public void testImportedEnumMembers() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/basic/common/ImportedEnumMembers.kt");
|
||||
|
||||
@@ -298,6 +298,12 @@ public class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCompletionT
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("HigherOrderFunction2.kt")
|
||||
public void testHigherOrderFunction2() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/basic/common/HigherOrderFunction2.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("ImportedEnumMembers.kt")
|
||||
public void testImportedEnumMembers() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/basic/common/ImportedEnumMembers.kt");
|
||||
|
||||
@@ -84,11 +84,11 @@ public class BasicCompletionHandlerTest : CompletionHandlerTestBase(){
|
||||
|
||||
fun testHigherOrderFunctionWithArg() = doTest(2, "filterNot", null, '\n')
|
||||
|
||||
fun testHigherOrderFunctionWithArgs1() = doTest(1, "foo", "foo { (String, Char) -> ... }", null, '\n')
|
||||
fun testHigherOrderFunctionWithArgs1() = doTest(1, "foo", "foo", " { (String, Char) -> ... }", '\n')
|
||||
|
||||
fun testHigherOrderFunctionWithArgs2() = doTest(1, "foo", "foo(p: (String, Char) -> Boolean)", null, '\n')
|
||||
fun testHigherOrderFunctionWithArgs2() = doTest(1, "foo", "foo", "(p: (String, Char) -> Boolean)", '\n')
|
||||
|
||||
fun testHigherOrderFunctionWithArgs3() = doTest(1, "foo", "foo { (String, Char) -> ... }", null, '\n')
|
||||
fun testHigherOrderFunctionWithArgs3() = doTest(1, "foo", "foo", " { (String, Char) -> ... }", '\n')
|
||||
|
||||
fun testForceParenthesisForTabChar() = doTest(0, "some", null, '\t')
|
||||
|
||||
@@ -161,7 +161,7 @@ public class BasicCompletionHandlerTest : CompletionHandlerTestBase(){
|
||||
fun testTypeArgOfSuper() = doTest(1, "X", null, '\n')
|
||||
|
||||
fun testKeywordClassName() = doTest(1, "class", null, '\n')
|
||||
fun testKeywordFunctionName() = doTest(1, "fun", "fun()", null, '\n')
|
||||
fun testKeywordFunctionName() = doTest(1, "fun", "fun", "()", '\n')
|
||||
|
||||
fun testInfixCall() = doTest(1, "to", null, null, '\n')
|
||||
fun testInfixCallOnSpace() = doTest(1, "to", null, null, ' ')
|
||||
|
||||
Reference in New Issue
Block a user