Experimental feature to show properties in completion after prefix with "get" or "set"
This commit is contained in:
@@ -42,14 +42,17 @@ import org.jetbrains.kotlin.idea.references.mainReference
|
||||
import org.jetbrains.kotlin.idea.util.CallType
|
||||
import org.jetbrains.kotlin.idea.util.ShadowedDeclarationsFilter
|
||||
import org.jetbrains.kotlin.lexer.JetTokens
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf
|
||||
import org.jetbrains.kotlin.psi.psiUtil.prevLeaf
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.bindingContextUtil.getDataFlowInfo
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.SmartCastUtils
|
||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
||||
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
|
||||
import org.jetbrains.kotlin.util.capitalizeDecapitalize.decapitalizeSmart
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance
|
||||
|
||||
class CompletionSessionConfiguration(
|
||||
@@ -120,6 +123,18 @@ abstract class CompletionSession(protected val configuration: CompletionSessionC
|
||||
|
||||
protected val prefixMatcher: PrefixMatcher = CamelHumpMatcher(prefix)
|
||||
|
||||
protected val descriptorNameFilter: (Name) -> Boolean = run {
|
||||
val nameFilter = prefixMatcher.asNameFilter()
|
||||
val getOrSetPrefix = listOf("get", "set").firstOrNull { prefix.startsWith(it) }
|
||||
if (getOrSetPrefix != null)
|
||||
nameFilter or prefixMatcher.cloneWithPrefix(prefix.removePrefix(getOrSetPrefix).decapitalizeSmart()).asNameFilter()
|
||||
else
|
||||
nameFilter
|
||||
}
|
||||
|
||||
private fun ((Name) -> Boolean).or(otherFilter: (Name) -> Boolean): (Name) -> Boolean
|
||||
= { this(it) || otherFilter(it) }
|
||||
|
||||
protected val isVisibleFilter: (DeclarationDescriptor) -> Boolean = { isVisibleDescriptor(it) }
|
||||
|
||||
protected val referenceVariantsHelper: ReferenceVariantsHelper = ReferenceVariantsHelper(bindingContext, moduleDescriptor, project, isVisibleFilter)
|
||||
@@ -207,7 +222,7 @@ abstract class CompletionSession(protected val configuration: CompletionSessionC
|
||||
referenceVariantsHelper.getReferenceVariants(
|
||||
nameExpression!!,
|
||||
descriptorKindFilter!!,
|
||||
prefixMatcher.asNameFilter(),
|
||||
descriptorNameFilter,
|
||||
filterOutJavaGettersAndSetters = configuration.filterOutJavaGettersAndSetters
|
||||
).excludeNonInitializedVariable(nameExpression)
|
||||
}
|
||||
@@ -231,7 +246,7 @@ abstract class CompletionSession(protected val configuration: CompletionSessionC
|
||||
|
||||
protected fun getRuntimeReceiverTypeReferenceVariants(): Collection<DeclarationDescriptor> {
|
||||
val restrictedKindFilter = descriptorKindFilter!!.restrictedToKinds(DescriptorKindFilter.FUNCTIONS_MASK or DescriptorKindFilter.VARIABLES_MASK) // optimization
|
||||
val descriptors = referenceVariantsHelper.getReferenceVariants(nameExpression!!, restrictedKindFilter, prefixMatcher.asNameFilter(), useRuntimeReceiverType = true)
|
||||
val descriptors = referenceVariantsHelper.getReferenceVariants(nameExpression!!, restrictedKindFilter, descriptorNameFilter, useRuntimeReceiverType = true)
|
||||
return descriptors.filter { descriptor ->
|
||||
referenceVariants.none { comparePossiblyOverridingDescriptors(project, it, descriptor) }
|
||||
}
|
||||
|
||||
+1
-1
@@ -86,7 +86,7 @@ class KDocNameCompletionSession(parameters: CompletionParameters,
|
||||
|
||||
private fun addLinkCompletions(declarationDescriptor: DeclarationDescriptor) {
|
||||
val scope = getResolutionScope(resolutionFacade, declarationDescriptor)
|
||||
scope.getDescriptors(nameFilter = prefixMatcher.asNameFilter()).forEach {
|
||||
scope.getDescriptors(nameFilter = descriptorNameFilter).forEach {
|
||||
val element = lookupElementFactory.createLookupElement(it, false)
|
||||
collector.addElement(object: LookupElementDecorator<LookupElement>(element) {
|
||||
override fun handleInsert(context: InsertionContext?) {
|
||||
|
||||
+16
-6
@@ -29,8 +29,7 @@ import org.jetbrains.kotlin.idea.JetDescriptorIconProvider
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.ResolutionFacade
|
||||
import org.jetbrains.kotlin.idea.completion.handlers.*
|
||||
import org.jetbrains.kotlin.idea.core.completion.DeclarationLookupObject
|
||||
import org.jetbrains.kotlin.types.typeUtil.TypeNullability
|
||||
import org.jetbrains.kotlin.types.typeUtil.nullability
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.psiUtil.parents
|
||||
@@ -40,7 +39,8 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor
|
||||
import org.jetbrains.kotlin.types.JetType
|
||||
import org.jetbrains.kotlin.types.TypeUtils
|
||||
import javax.swing.Icon
|
||||
import org.jetbrains.kotlin.types.typeUtil.TypeNullability
|
||||
import org.jetbrains.kotlin.types.typeUtil.nullability
|
||||
|
||||
public data class PackageLookupObject(val fqName: FqName) : DeclarationLookupObject {
|
||||
override val psiElement: PsiElement? get() = null
|
||||
@@ -255,6 +255,7 @@ public class LookupElementFactory(
|
||||
|
||||
if (descriptor is CallableDescriptor) {
|
||||
val original = descriptor.original
|
||||
val extensionReceiver = original.extensionReceiverParameter
|
||||
when {
|
||||
original is SyntheticJavaPropertyDescriptor -> {
|
||||
var from = original.getMethod.getName().asString() + "()"
|
||||
@@ -262,9 +263,8 @@ public class LookupElementFactory(
|
||||
element = element.appendTailText(" (from $from)", true)
|
||||
}
|
||||
|
||||
descriptor.getExtensionReceiverParameter() != null -> {
|
||||
val originalReceiver = descriptor.getOriginal().getExtensionReceiverParameter()!!
|
||||
val receiverPresentation = DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(originalReceiver.getType())
|
||||
extensionReceiver != null -> {
|
||||
val receiverPresentation = DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(extensionReceiver.type)
|
||||
element = element.appendTailText(" for $receiverPresentation", true)
|
||||
|
||||
val container = descriptor.getContainingDeclaration()
|
||||
@@ -289,6 +289,16 @@ public class LookupElementFactory(
|
||||
}
|
||||
}
|
||||
|
||||
if (descriptor is PropertyDescriptor) {
|
||||
val getterName = JvmAbi.getterName(name)
|
||||
if (getterName != name) {
|
||||
element = element.withLookupString(getterName)
|
||||
}
|
||||
if (descriptor.isVar) {
|
||||
element = element.withLookupString(JvmAbi.setterName(name))
|
||||
}
|
||||
}
|
||||
|
||||
if (lookupObject.isDeprecated) {
|
||||
element = element.withStrikeoutness(true)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
class C : Thread() {
|
||||
val property1: Int = 0
|
||||
var property2: Int = 0
|
||||
var xxx: Int = 0
|
||||
|
||||
fun getPPP() = 1
|
||||
}
|
||||
|
||||
fun foo(c: C) {
|
||||
c.getP<caret>
|
||||
}
|
||||
|
||||
// EXIST: property1
|
||||
// EXIST: property2
|
||||
// EXIST: getPPP
|
||||
// EXIST_JAVA_ONLY: priority
|
||||
// ABSENT: getPriority
|
||||
// ABSENT: xxx
|
||||
@@ -0,0 +1,16 @@
|
||||
class C {
|
||||
val property1: Int = 0
|
||||
var property2: Int = 0
|
||||
var xxx: Int = 0
|
||||
|
||||
fun setPPP(){}
|
||||
}
|
||||
|
||||
fun foo(c: C) {
|
||||
c.setP<caret>
|
||||
}
|
||||
|
||||
// ABSENT: property1
|
||||
// EXIST: property2
|
||||
// EXIST: setPPP
|
||||
// ABSENT: xxx
|
||||
-5
@@ -1,5 +0,0 @@
|
||||
fun foo(thread: Thread) {
|
||||
thread.get<caret>
|
||||
}
|
||||
|
||||
// EXIST_JAVA_ONLY: getPriority
|
||||
+12
-6
@@ -253,6 +253,12 @@ public class JSBasicCompletionTestGenerated extends AbstractJSBasicCompletionTes
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("GetPrefixForProperties.kt")
|
||||
public void testGetPrefixForProperties() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/GetPrefixForProperties.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("HigherOrderFunction1.kt")
|
||||
public void testHigherOrderFunction1() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/HigherOrderFunction1.kt");
|
||||
@@ -769,6 +775,12 @@ public class JSBasicCompletionTestGenerated extends AbstractJSBasicCompletionTes
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("SetPrefixForProperties.kt")
|
||||
public void testSetPrefixForProperties() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/SetPrefixForProperties.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("ShortClassNamesInTypePosition.kt")
|
||||
public void testShortClassNamesInTypePosition() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/ShortClassNamesInTypePosition.kt");
|
||||
@@ -1227,12 +1239,6 @@ public class JSBasicCompletionTestGenerated extends AbstractJSBasicCompletionTes
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("ShowGetMethodWhenNothingElseMatch.kt")
|
||||
public void testShowGetMethodWhenNothingElseMatch() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/extensions/ShowGetMethodWhenNothingElseMatch.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("ShowGetSetOnSecondCompletion.kt")
|
||||
public void testShowGetSetOnSecondCompletion() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/extensions/ShowGetSetOnSecondCompletion.kt");
|
||||
|
||||
+12
-6
@@ -253,6 +253,12 @@ public class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCompletionT
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("GetPrefixForProperties.kt")
|
||||
public void testGetPrefixForProperties() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/GetPrefixForProperties.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("HigherOrderFunction1.kt")
|
||||
public void testHigherOrderFunction1() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/HigherOrderFunction1.kt");
|
||||
@@ -769,6 +775,12 @@ public class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCompletionT
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("SetPrefixForProperties.kt")
|
||||
public void testSetPrefixForProperties() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/SetPrefixForProperties.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("ShortClassNamesInTypePosition.kt")
|
||||
public void testShortClassNamesInTypePosition() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/ShortClassNamesInTypePosition.kt");
|
||||
@@ -1227,12 +1239,6 @@ public class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCompletionT
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("ShowGetMethodWhenNothingElseMatch.kt")
|
||||
public void testShowGetMethodWhenNothingElseMatch() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/extensions/ShowGetMethodWhenNothingElseMatch.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("ShowGetSetOnSecondCompletion.kt")
|
||||
public void testShowGetSetOnSecondCompletion() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/extensions/ShowGetSetOnSecondCompletion.kt");
|
||||
|
||||
Reference in New Issue
Block a user