Add simple completion of class-like symbols

This commit is contained in:
Roman Golyshev
2020-07-13 12:02:22 +03:00
committed by Ilya Kirillov
parent 20c627ea47
commit 1b3a1a662f
4 changed files with 34 additions and 10 deletions
@@ -0,0 +1,18 @@
class DefaultConstructor
class TwoConstructors(s: String) {
constructor(l: Int): this(l.toString()) {}
}
data class DataClass(val a: Int)
abstract class AbstractClass
fun usage() {
<caret>
}
// EXIST: DefaultConstructor
// EXIST: TwoConstructors
// EXIST: DataClass
// EXIST: AbstractClass
@@ -2322,6 +2322,11 @@ public class JSBasicCompletionTestGenerated extends AbstractJSBasicCompletionTes
runTest("idea/idea-completion/testData/basic/common/primitiveCompletion/stringCompletion.kt");
}
@TestMetadata("topLevelClasses.kt")
public void testTopLevelClasses() throws Exception {
runTest("idea/idea-completion/testData/basic/common/primitiveCompletion/topLevelClasses.kt");
}
@TestMetadata("topLevelVariablesAndFunctions.kt")
public void testTopLevelVariablesAndFunctions() throws Exception {
runTest("idea/idea-completion/testData/basic/common/primitiveCompletion/topLevelVariablesAndFunctions.kt");
@@ -2322,6 +2322,11 @@ public class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCompletionT
runTest("idea/idea-completion/testData/basic/common/primitiveCompletion/stringCompletion.kt");
}
@TestMetadata("topLevelClasses.kt")
public void testTopLevelClasses() throws Exception {
runTest("idea/idea-completion/testData/basic/common/primitiveCompletion/topLevelClasses.kt");
}
@TestMetadata("topLevelVariablesAndFunctions.kt")
public void testTopLevelVariablesAndFunctions() throws Exception {
runTest("idea/idea-completion/testData/basic/common/primitiveCompletion/topLevelVariablesAndFunctions.kt");
@@ -10,10 +10,7 @@ import com.intellij.codeInsight.lookup.LookupElementBuilder
import com.intellij.patterns.PlatformPatterns
import com.intellij.util.ProcessingContext
import org.jetbrains.kotlin.idea.frontend.api.getAnalysisSessionFor
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtCallableSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtNamedSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtPossibleExtensionSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.isExtension
import org.jetbrains.kotlin.idea.frontend.api.symbols.*
import org.jetbrains.kotlin.idea.frontend.api.types.KtType
import org.jetbrains.kotlin.idea.references.mainReference
import org.jetbrains.kotlin.psi.KtFile
@@ -45,7 +42,7 @@ private object KotlinHighLevelApiContributor : CompletionProvider<CompletionPara
val typeOfPossibleReceiver = possibleReceiver?.let { sessionForCompletion.getKtExpressionType(it) }
val possibleReceiverScope = typeOfPossibleReceiver?.let { sessionForCompletion.scopeProvider.getScopeForType(it) }
fun addToCompletion(symbol: KtCallableSymbol) {
fun addToCompletion(symbol: KtSymbol) {
if (symbol !is KtNamedSymbol) return
result.addElement(LookupElementBuilder.create(symbol.name.asString()))
}
@@ -54,12 +51,10 @@ private object KotlinHighLevelApiContributor : CompletionProvider<CompletionPara
val nonExtensionMembers = possibleReceiverScope
.getCallableSymbols()
.filterNot { it.isExtension }
.toList()
val extensionNonMembers = implicitScopes
.getCallableSymbols()
.filter { it.isExtension && it.canBeCalledWith(listOf(typeOfPossibleReceiver)) }
.toList()
nonExtensionMembers.forEach(::addToCompletion)
extensionNonMembers.forEach(::addToCompletion)
@@ -69,15 +64,16 @@ private object KotlinHighLevelApiContributor : CompletionProvider<CompletionPara
.filter { !it.isExtension || it.canBeCalledWith(implicitReceivers) }
extensionNonMembers.forEach(::addToCompletion)
}
return
val availableClasses = implicitScopes.getClassClassLikeSymbols()
availableClasses.forEach(::addToCompletion)
}
}
}
private fun KtCallableSymbol.canBeCalledWith(implicitReceivers: List<KtType>): Boolean {
val requiredReceiverType = (this as? KtPossibleExtensionSymbol)?.receiverType
?: error("Extension receiver type should be present on ${this}")
?: error("Extension receiver type should be present on $this")
return implicitReceivers.any { it.isSubTypeOf(requiredReceiverType) }
}