FIR IDE: implement completion for callable references
This commit is contained in:
committed by
teamcityserver
parent
a42e9c236a
commit
2ffc7ad0a0
+1
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_COMPARISON
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
val v = File::<caret>
|
val v = File::<caret>
|
||||||
|
|||||||
+1
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_COMPARISON
|
||||||
val v = "a"::<caret>
|
val v = "a"::<caret>
|
||||||
|
|
||||||
// EXIST: extFun
|
// EXIST: extFun
|
||||||
|
|||||||
+1
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_COMPARISON
|
||||||
package ppp
|
package ppp
|
||||||
|
|
||||||
class X(p: Int)
|
class X(p: Int)
|
||||||
|
|||||||
+1
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_COMPARISON
|
||||||
package ppp
|
package ppp
|
||||||
|
|
||||||
class X(p: Int)
|
class X(p: Int)
|
||||||
|
|||||||
+1
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_COMPARISON
|
||||||
fun globalFun(p: Int) {}
|
fun globalFun(p: Int) {}
|
||||||
|
|
||||||
class C {
|
class C {
|
||||||
|
|||||||
+1
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_COMPARISON
|
||||||
fun globalFun(p: Int) {}
|
fun globalFun(p: Int) {}
|
||||||
|
|
||||||
class C {
|
class C {
|
||||||
|
|||||||
+1
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_COMPARISON
|
||||||
class C {
|
class C {
|
||||||
fun foo() {
|
fun foo() {
|
||||||
val v = D::<caret>
|
val v = D::<caret>
|
||||||
|
|||||||
+1
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_COMPARISON
|
||||||
class C {
|
class C {
|
||||||
fun foo() {
|
fun foo() {
|
||||||
val v = D::memberFun<caret>
|
val v = D::memberFun<caret>
|
||||||
|
|||||||
+7
@@ -79,7 +79,9 @@ private object KotlinFirCompletionProvider : CompletionProvider<CompletionParame
|
|||||||
) {
|
) {
|
||||||
val keywordContributor = FirKeywordCompletionContributor(basicContext)
|
val keywordContributor = FirKeywordCompletionContributor(basicContext)
|
||||||
val callableContributor = FirCallableCompletionContributor(basicContext)
|
val callableContributor = FirCallableCompletionContributor(basicContext)
|
||||||
|
val callableReferenceContributor = FirCallableReferenceCompletionContributor(basicContext)
|
||||||
val classifierContributor = FirClassifierCompletionContributor(basicContext)
|
val classifierContributor = FirClassifierCompletionContributor(basicContext)
|
||||||
|
val classifierReferenceContributor = FirClassifierReferenceCompletionContributor(basicContext)
|
||||||
val annotationsContributor = FirAnnotationCompletionContributor(basicContext)
|
val annotationsContributor = FirAnnotationCompletionContributor(basicContext)
|
||||||
val packageCompletionContributor = FirPackageCompletionContributor(basicContext)
|
val packageCompletionContributor = FirPackageCompletionContributor(basicContext)
|
||||||
val importDirectivePackageMembersCompletionContributor = FirImportDirectivePackageMembersCompletionContributor(basicContext)
|
val importDirectivePackageMembersCompletionContributor = FirImportDirectivePackageMembersCompletionContributor(basicContext)
|
||||||
@@ -137,6 +139,11 @@ private object KotlinFirCompletionProvider : CompletionProvider<CompletionParame
|
|||||||
complete(whenWithSubjecConditionContributor, positionContext)
|
complete(whenWithSubjecConditionContributor, positionContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
is FirCallableReferencePositionContext -> {
|
||||||
|
complete(callableReferenceContributor, positionContext)
|
||||||
|
complete(classifierReferenceContributor, positionContext)
|
||||||
|
}
|
||||||
|
|
||||||
is FirIncorrectPositionContext -> {
|
is FirIncorrectPositionContext -> {
|
||||||
// do nothing, completion is not suposed to be called here
|
// do nothing, completion is not suposed to be called here
|
||||||
}
|
}
|
||||||
|
|||||||
+12
@@ -96,6 +96,13 @@ internal class FirWithSubjectEntryPositionContext(
|
|||||||
val whenCondition: KtWhenCondition,
|
val whenCondition: KtWhenCondition,
|
||||||
) : FirNameReferencePositionContext()
|
) : FirNameReferencePositionContext()
|
||||||
|
|
||||||
|
internal class FirCallableReferencePositionContext(
|
||||||
|
override val position: PsiElement,
|
||||||
|
override val reference: KtSimpleNameReference,
|
||||||
|
override val nameExpression: KtSimpleNameExpression,
|
||||||
|
override val explicitReceiver: KtExpression?
|
||||||
|
) : FirNameReferencePositionContext()
|
||||||
|
|
||||||
internal class FirUnknownPositionContext(
|
internal class FirUnknownPositionContext(
|
||||||
override val position: PsiElement
|
override val position: PsiElement
|
||||||
) : FirRawPositionCompletionContext()
|
) : FirRawPositionCompletionContext()
|
||||||
@@ -130,6 +137,11 @@ internal object FirPositionCompletionContextDetector {
|
|||||||
parent is KtUserType -> {
|
parent is KtUserType -> {
|
||||||
detectForTypeContext(parent, position, reference, nameExpression, explicitReceiver)
|
detectForTypeContext(parent, position, reference, nameExpression, explicitReceiver)
|
||||||
}
|
}
|
||||||
|
parent is KtCallableReferenceExpression -> {
|
||||||
|
FirCallableReferencePositionContext(
|
||||||
|
position, reference, nameExpression, parent.receiverExpression
|
||||||
|
)
|
||||||
|
}
|
||||||
parent is KtWhenCondition && parent.isConditionOnWhenWithSubject() -> {
|
parent is KtWhenCondition && parent.isConditionOnWhenWithSubject() -> {
|
||||||
FirWithSubjectEntryPositionContext(
|
FirWithSubjectEntryPositionContext(
|
||||||
position,
|
position,
|
||||||
|
|||||||
+46
-11
@@ -9,22 +9,27 @@ import org.jetbrains.kotlin.idea.completion.checkers.CompletionVisibilityChecker
|
|||||||
import org.jetbrains.kotlin.idea.completion.checkers.ExtensionApplicabilityChecker
|
import org.jetbrains.kotlin.idea.completion.checkers.ExtensionApplicabilityChecker
|
||||||
import org.jetbrains.kotlin.idea.completion.context.FirBasicCompletionContext
|
import org.jetbrains.kotlin.idea.completion.context.FirBasicCompletionContext
|
||||||
import org.jetbrains.kotlin.idea.completion.context.FirNameReferencePositionContext
|
import org.jetbrains.kotlin.idea.completion.context.FirNameReferencePositionContext
|
||||||
|
import org.jetbrains.kotlin.idea.completion.lookups.CallableInsertionStrategy
|
||||||
|
import org.jetbrains.kotlin.idea.completion.lookups.ImportStrategy
|
||||||
import org.jetbrains.kotlin.idea.fir.HLIndexHelper
|
import org.jetbrains.kotlin.idea.fir.HLIndexHelper
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession
|
import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.components.KtScopeContext
|
import org.jetbrains.kotlin.idea.frontend.api.components.KtScopeContext
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.scopes.KtCompositeScope
|
import org.jetbrains.kotlin.idea.frontend.api.scopes.KtCompositeScope
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.scopes.KtScope
|
import org.jetbrains.kotlin.idea.frontend.api.scopes.KtScope
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.*
|
import org.jetbrains.kotlin.idea.frontend.api.symbols.*
|
||||||
|
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSymbolWithVisibility
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.types.KtClassType
|
import org.jetbrains.kotlin.idea.frontend.api.types.KtClassType
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.types.KtNonErrorClassType
|
import org.jetbrains.kotlin.idea.frontend.api.types.KtNonErrorClassType
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.types.KtType
|
import org.jetbrains.kotlin.idea.frontend.api.types.KtType
|
||||||
import org.jetbrains.kotlin.psi.KtExpression
|
import org.jetbrains.kotlin.psi.KtExpression
|
||||||
|
|
||||||
internal class FirCallableCompletionContributor(
|
internal open class FirCallableCompletionContributor(
|
||||||
basicContext: FirBasicCompletionContext,
|
basicContext: FirBasicCompletionContext,
|
||||||
) : FirContextCompletionContributorBase<FirNameReferencePositionContext>(basicContext) {
|
) : FirContextCompletionContributorBase<FirNameReferencePositionContext>(basicContext) {
|
||||||
private val typeNamesProvider = TypeNamesProvider(indexHelper)
|
private val typeNamesProvider = TypeNamesProvider(indexHelper)
|
||||||
|
|
||||||
|
protected open val insertionStrategy: CallableInsertionStrategy = CallableInsertionStrategy.AS_CALL
|
||||||
|
|
||||||
private val shouldCompleteTopLevelCallablesFromIndex: Boolean
|
private val shouldCompleteTopLevelCallablesFromIndex: Boolean
|
||||||
get() = prefixMatcher.prefix.isNotEmpty()
|
get() = prefixMatcher.prefix.isNotEmpty()
|
||||||
|
|
||||||
@@ -67,22 +72,22 @@ internal class FirCallableCompletionContributor(
|
|||||||
val availableNonExtensions = collectNonExtensions(implicitScopes, visibilityChecker)
|
val availableNonExtensions = collectNonExtensions(implicitScopes, visibilityChecker)
|
||||||
val extensionsWhichCanBeCalled = collectSuitableExtensions(implicitScopes, extensionChecker, visibilityChecker)
|
val extensionsWhichCanBeCalled = collectSuitableExtensions(implicitScopes, extensionChecker, visibilityChecker)
|
||||||
|
|
||||||
availableNonExtensions.forEach { addSymbolToCompletion(expectedType, it) }
|
availableNonExtensions.forEach { addCallableSymbolToCompletion(expectedType, it, insertionStrategy = insertionStrategy) }
|
||||||
extensionsWhichCanBeCalled.forEach { addSymbolToCompletion(expectedType, it) }
|
extensionsWhichCanBeCalled.forEach { addCallableSymbolToCompletion(expectedType, it, insertionStrategy = insertionStrategy) }
|
||||||
|
|
||||||
if (shouldCompleteTopLevelCallablesFromIndex) {
|
if (shouldCompleteTopLevelCallablesFromIndex) {
|
||||||
val topLevelCallables = indexHelper.getTopLevelCallables(scopeNameFilter)
|
val topLevelCallables = indexHelper.getTopLevelCallables(scopeNameFilter)
|
||||||
topLevelCallables.asSequence()
|
topLevelCallables.asSequence()
|
||||||
.map { it.getSymbol() as KtCallableSymbol }
|
.map { it.getSymbol() as KtCallableSymbol }
|
||||||
.filter { with(visibilityChecker) { isVisible(it) } }
|
.filter { with(visibilityChecker) { isVisible(it) } }
|
||||||
.forEach { addSymbolToCompletion(expectedType, it) }
|
.forEach { addCallableSymbolToCompletion(expectedType, it, insertionStrategy = insertionStrategy) }
|
||||||
}
|
}
|
||||||
|
|
||||||
collectTopLevelExtensionsFromIndices(implicitReceiversTypes, extensionChecker, visibilityChecker)
|
collectTopLevelExtensionsFromIndices(implicitReceiversTypes, extensionChecker, visibilityChecker)
|
||||||
.forEach { addSymbolToCompletion(expectedType, it) }
|
.forEach { addCallableSymbolToCompletion(expectedType, it, insertionStrategy = insertionStrategy) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun KtAnalysisSession.collectDotCompletion(
|
protected open fun KtAnalysisSession.collectDotCompletion(
|
||||||
implicitScopes: KtCompositeScope,
|
implicitScopes: KtCompositeScope,
|
||||||
explicitReceiver: KtExpression,
|
explicitReceiver: KtExpression,
|
||||||
expectedType: KtType?,
|
expectedType: KtType?,
|
||||||
@@ -111,11 +116,11 @@ internal class FirCallableCompletionContributor(
|
|||||||
.filterNot { it.isExtension }
|
.filterNot { it.isExtension }
|
||||||
.filter { with(visibilityChecker) { isVisible(it) } }
|
.filter { with(visibilityChecker) { isVisible(it) } }
|
||||||
.forEach { callable ->
|
.forEach { callable ->
|
||||||
addSymbolToCompletion(expectedType, callable)
|
addCallableSymbolToCompletion(expectedType, callable, insertionStrategy = insertionStrategy)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun KtAnalysisSession.collectDotCompletionForCallableReceiver(
|
protected fun KtAnalysisSession.collectDotCompletionForCallableReceiver(
|
||||||
implicitScopes: KtCompositeScope,
|
implicitScopes: KtCompositeScope,
|
||||||
explicitReceiver: KtExpression,
|
explicitReceiver: KtExpression,
|
||||||
expectedType: KtType?,
|
expectedType: KtType?,
|
||||||
@@ -128,11 +133,11 @@ internal class FirCallableCompletionContributor(
|
|||||||
val nonExtensionMembers = collectNonExtensions(possibleReceiverScope, visibilityChecker)
|
val nonExtensionMembers = collectNonExtensions(possibleReceiverScope, visibilityChecker)
|
||||||
val extensionNonMembers = collectSuitableExtensions(implicitScopes, extensionChecker, visibilityChecker)
|
val extensionNonMembers = collectSuitableExtensions(implicitScopes, extensionChecker, visibilityChecker)
|
||||||
|
|
||||||
nonExtensionMembers.forEach { addSymbolToCompletion(expectedType, it) }
|
nonExtensionMembers.forEach { addCallableSymbolToCompletion(expectedType, it, insertionStrategy = insertionStrategy) }
|
||||||
extensionNonMembers.forEach { addSymbolToCompletion(expectedType, it) }
|
extensionNonMembers.forEach { addCallableSymbolToCompletion(expectedType, it, insertionStrategy = insertionStrategy) }
|
||||||
|
|
||||||
collectTopLevelExtensionsFromIndices(listOf(typeOfPossibleReceiver), extensionChecker, visibilityChecker)
|
collectTopLevelExtensionsFromIndices(listOf(typeOfPossibleReceiver), extensionChecker, visibilityChecker)
|
||||||
.forEach { addSymbolToCompletion(expectedType, it) }
|
.forEach { addCallableSymbolToCompletion(expectedType, it, insertionStrategy = insertionStrategy) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun KtAnalysisSession.collectTopLevelExtensionsFromIndices(
|
private fun KtAnalysisSession.collectTopLevelExtensionsFromIndices(
|
||||||
@@ -168,6 +173,36 @@ internal class FirCallableCompletionContributor(
|
|||||||
implicitReceiversTypes.flatMapTo(hashSetOf()) { with(typeNamesProvider) { findAllNames(it) } }
|
implicitReceiversTypes.flatMapTo(hashSetOf()) { with(typeNamesProvider) { findAllNames(it) } }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal class FirCallableReferenceCompletionContributor(
|
||||||
|
basicContext: FirBasicCompletionContext
|
||||||
|
) : FirCallableCompletionContributor(basicContext) {
|
||||||
|
override val insertionStrategy: CallableInsertionStrategy = CallableInsertionStrategy.AS_IDENTIFIER
|
||||||
|
|
||||||
|
override fun KtAnalysisSession.collectDotCompletion(
|
||||||
|
implicitScopes: KtCompositeScope,
|
||||||
|
explicitReceiver: KtExpression,
|
||||||
|
expectedType: KtType?,
|
||||||
|
extensionChecker: ExtensionApplicabilityChecker,
|
||||||
|
visibilityChecker: CompletionVisibilityChecker
|
||||||
|
) {
|
||||||
|
when (val resolved = explicitReceiver.reference()?.resolveToSymbol()) {
|
||||||
|
is KtPackageSymbol -> return
|
||||||
|
is KtNamedClassOrObjectSymbol -> {
|
||||||
|
resolved.getMemberScope()
|
||||||
|
.getCallableSymbols(scopeNameFilter)
|
||||||
|
.filter { with(visibilityChecker) { isVisible(it) } }
|
||||||
|
.forEach { symbol ->
|
||||||
|
addCallableSymbolToCompletion(expectedType = null, symbol, insertionStrategy = insertionStrategy)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
collectDotCompletionForCallableReceiver(implicitScopes, explicitReceiver, expectedType, extensionChecker, visibilityChecker)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private class TypeNamesProvider(private val indexHelper: HLIndexHelper) {
|
private class TypeNamesProvider(private val indexHelper: HLIndexHelper) {
|
||||||
fun KtAnalysisSession.findAllNames(type: KtType): Set<String> {
|
fun KtAnalysisSession.findAllNames(type: KtType): Set<String> {
|
||||||
if (type !is KtNonErrorClassType) return emptySet()
|
if (type !is KtNonErrorClassType) return emptySet()
|
||||||
|
|||||||
+18
-3
@@ -14,6 +14,8 @@ import org.jetbrains.kotlin.idea.frontend.api.symbols.*
|
|||||||
import org.jetbrains.kotlin.idea.frontend.api.types.KtClassType
|
import org.jetbrains.kotlin.idea.frontend.api.types.KtClassType
|
||||||
import org.jetbrains.kotlin.psi.KtExpression
|
import org.jetbrains.kotlin.psi.KtExpression
|
||||||
import org.jetbrains.kotlin.idea.completion.contributors.helpers.FirClassifierProvider.getAvailableClassifiersCurrentScope
|
import org.jetbrains.kotlin.idea.completion.contributors.helpers.FirClassifierProvider.getAvailableClassifiersCurrentScope
|
||||||
|
import org.jetbrains.kotlin.idea.completion.lookups.ImportStrategy
|
||||||
|
import org.jetbrains.kotlin.idea.completion.lookups.detectImportStrategy
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.types.KtNonErrorClassType
|
import org.jetbrains.kotlin.idea.frontend.api.types.KtNonErrorClassType
|
||||||
|
|
||||||
internal open class FirClassifierCompletionContributor(
|
internal open class FirClassifierCompletionContributor(
|
||||||
@@ -22,6 +24,9 @@ internal open class FirClassifierCompletionContributor(
|
|||||||
|
|
||||||
protected open fun KtAnalysisSession.filterClassifiers(classifierSymbol: KtClassifierSymbol): Boolean = true
|
protected open fun KtAnalysisSession.filterClassifiers(classifierSymbol: KtClassifierSymbol): Boolean = true
|
||||||
|
|
||||||
|
protected open fun KtAnalysisSession.getImportingStrategy(classifierSymbol: KtClassifierSymbol): ImportStrategy =
|
||||||
|
detectImportStrategy(classifierSymbol)
|
||||||
|
|
||||||
override fun KtAnalysisSession.complete(positionContext: FirNameReferencePositionContext) {
|
override fun KtAnalysisSession.complete(positionContext: FirNameReferencePositionContext) {
|
||||||
val visibilityChecker = CompletionVisibilityChecker.create(basicContext, positionContext)
|
val visibilityChecker = CompletionVisibilityChecker.create(basicContext, positionContext)
|
||||||
|
|
||||||
@@ -45,7 +50,7 @@ internal open class FirClassifierCompletionContributor(
|
|||||||
.getClassifierSymbols(scopeNameFilter)
|
.getClassifierSymbols(scopeNameFilter)
|
||||||
.filter { filterClassifiers(it) }
|
.filter { filterClassifiers(it) }
|
||||||
.filter { with(visibilityChecker) { isVisible(it) } }
|
.filter { with(visibilityChecker) { isVisible(it) } }
|
||||||
.forEach { addClassifierSymbolToCompletion(it, insertFqName = false) }
|
.forEach { addClassifierSymbolToCompletion(it, ImportStrategy.DoNothing) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun KtAnalysisSession.completeWithoutReceiver(
|
private fun KtAnalysisSession.completeWithoutReceiver(
|
||||||
@@ -60,7 +65,9 @@ internal open class FirClassifierCompletionContributor(
|
|||||||
visibilityChecker
|
visibilityChecker
|
||||||
)
|
)
|
||||||
.filter { filterClassifiers(it) }
|
.filter { filterClassifiers(it) }
|
||||||
.forEach { addClassifierSymbolToCompletion(it, insertFqName = true) }
|
.forEach { classifierSymbol ->
|
||||||
|
addClassifierSymbolToCompletion(classifierSymbol, getImportingStrategy(classifierSymbol))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,4 +94,12 @@ internal class FirAnnotationCompletionContributor(
|
|||||||
expendedClass?.let { filterClassifiers(it) } == true
|
expendedClass?.let { filterClassifiers(it) } == true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal class FirClassifierReferenceCompletionContributor(
|
||||||
|
basicContext: FirBasicCompletionContext
|
||||||
|
) : FirClassifierCompletionContributor(basicContext) {
|
||||||
|
|
||||||
|
override fun KtAnalysisSession.getImportingStrategy(classifierSymbol: KtClassifierSymbol): ImportStrategy =
|
||||||
|
ImportStrategy.DoNothing
|
||||||
|
}
|
||||||
|
|||||||
+11
-7
@@ -6,15 +6,15 @@
|
|||||||
package org.jetbrains.kotlin.idea.completion.contributors
|
package org.jetbrains.kotlin.idea.completion.contributors
|
||||||
|
|
||||||
import com.intellij.codeInsight.completion.CompletionParameters
|
import com.intellij.codeInsight.completion.CompletionParameters
|
||||||
import com.intellij.codeInsight.completion.CompletionResultSet
|
|
||||||
import com.intellij.codeInsight.completion.PrefixMatcher
|
import com.intellij.codeInsight.completion.PrefixMatcher
|
||||||
import com.intellij.codeInsight.lookup.LookupElement
|
import com.intellij.codeInsight.lookup.LookupElement
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import org.jetbrains.kotlin.idea.completion.LookupElementSink
|
import org.jetbrains.kotlin.idea.completion.LookupElementSink
|
||||||
import org.jetbrains.kotlin.idea.completion.context.FirBasicCompletionContext
|
import org.jetbrains.kotlin.idea.completion.context.FirBasicCompletionContext
|
||||||
import org.jetbrains.kotlin.idea.completion.context.FirRawPositionCompletionContext
|
import org.jetbrains.kotlin.idea.completion.context.FirRawPositionCompletionContext
|
||||||
import org.jetbrains.kotlin.idea.completion.lookups.CallableImportStrategy
|
import org.jetbrains.kotlin.idea.completion.lookups.ImportStrategy
|
||||||
import org.jetbrains.kotlin.idea.completion.lookups.CallableInsertionStrategy
|
import org.jetbrains.kotlin.idea.completion.lookups.CallableInsertionStrategy
|
||||||
|
import org.jetbrains.kotlin.idea.completion.lookups.detectImportStrategy
|
||||||
import org.jetbrains.kotlin.idea.completion.lookups.factories.KotlinFirLookupElementFactory
|
import org.jetbrains.kotlin.idea.completion.lookups.factories.KotlinFirLookupElementFactory
|
||||||
import org.jetbrains.kotlin.idea.completion.weighers.Weighers
|
import org.jetbrains.kotlin.idea.completion.weighers.Weighers
|
||||||
import org.jetbrains.kotlin.idea.fir.HLIndexHelper
|
import org.jetbrains.kotlin.idea.fir.HLIndexHelper
|
||||||
@@ -50,16 +50,18 @@ internal abstract class FirCompletionContributorBase<C : FirRawPositionCompletio
|
|||||||
if (symbol !is KtNamedSymbol) return
|
if (symbol !is KtNamedSymbol) return
|
||||||
with(lookupElementFactory) {
|
with(lookupElementFactory) {
|
||||||
createLookupElement(symbol)
|
createLookupElement(symbol)
|
||||||
.let { applyWeighers(it, symbol, expectedType) }
|
|
||||||
.let(sink::addElement)
|
.let(sink::addElement)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun KtAnalysisSession.addClassifierSymbolToCompletion(symbol: KtClassifierSymbol, insertFqName: Boolean) {
|
protected fun KtAnalysisSession.addClassifierSymbolToCompletion(
|
||||||
|
symbol: KtClassifierSymbol,
|
||||||
|
importingStrategy: ImportStrategy = detectImportStrategy(symbol)
|
||||||
|
) {
|
||||||
if (symbol !is KtNamedSymbol) return
|
if (symbol !is KtNamedSymbol) return
|
||||||
val lookup = with(lookupElementFactory) {
|
val lookup = with(lookupElementFactory) {
|
||||||
when (symbol) {
|
when (symbol) {
|
||||||
is KtClassLikeSymbol -> createLookupElementForClassLikeSymbol(symbol, insertFqName)
|
is KtClassLikeSymbol -> createLookupElementForClassLikeSymbol(symbol, importingStrategy)
|
||||||
is KtTypeParameterSymbol -> createLookupElement(symbol)
|
is KtTypeParameterSymbol -> createLookupElement(symbol)
|
||||||
}
|
}
|
||||||
} ?: return
|
} ?: return
|
||||||
@@ -67,14 +69,16 @@ internal abstract class FirCompletionContributorBase<C : FirRawPositionCompletio
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected fun KtAnalysisSession.addCallableSymbolToCompletion(
|
protected fun KtAnalysisSession.addCallableSymbolToCompletion(
|
||||||
|
expectedType: KtType?,
|
||||||
symbol: KtCallableSymbol,
|
symbol: KtCallableSymbol,
|
||||||
importingStrategy: CallableImportStrategy,
|
importingStrategy: ImportStrategy = detectImportStrategy(symbol),
|
||||||
insertionStrategy: CallableInsertionStrategy,
|
insertionStrategy: CallableInsertionStrategy,
|
||||||
) {
|
) {
|
||||||
if (symbol !is KtNamedSymbol) return
|
if (symbol !is KtNamedSymbol) return
|
||||||
val lookup = with(lookupElementFactory) {
|
val lookup = with(lookupElementFactory) {
|
||||||
createCallableLookupElement(symbol, importingStrategy, insertionStrategy)
|
createCallableLookupElement(symbol, importingStrategy, insertionStrategy)
|
||||||
} ?: return
|
}
|
||||||
|
applyWeighers(lookup, symbol, expectedType)
|
||||||
sink.addElement(lookup)
|
sink.addElement(lookup)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+4
-3
@@ -9,7 +9,7 @@ import org.jetbrains.kotlin.idea.completion.checkers.CompletionVisibilityChecker
|
|||||||
import org.jetbrains.kotlin.idea.completion.context.FirBasicCompletionContext
|
import org.jetbrains.kotlin.idea.completion.context.FirBasicCompletionContext
|
||||||
import org.jetbrains.kotlin.idea.completion.context.FirImportDirectivePositionContext
|
import org.jetbrains.kotlin.idea.completion.context.FirImportDirectivePositionContext
|
||||||
import org.jetbrains.kotlin.idea.completion.contributors.helpers.getStaticScope
|
import org.jetbrains.kotlin.idea.completion.contributors.helpers.getStaticScope
|
||||||
import org.jetbrains.kotlin.idea.completion.lookups.CallableImportStrategy
|
import org.jetbrains.kotlin.idea.completion.lookups.ImportStrategy
|
||||||
import org.jetbrains.kotlin.idea.completion.lookups.CallableInsertionStrategy
|
import org.jetbrains.kotlin.idea.completion.lookups.CallableInsertionStrategy
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession
|
import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession
|
||||||
|
|
||||||
@@ -23,14 +23,15 @@ internal class FirImportDirectivePackageMembersCompletionContributor(
|
|||||||
|
|
||||||
scope.getClassifierSymbols(scopeNameFilter)
|
scope.getClassifierSymbols(scopeNameFilter)
|
||||||
.filter { with(visibilityChecker) { isVisible(it) } }
|
.filter { with(visibilityChecker) { isVisible(it) } }
|
||||||
.forEach { addClassifierSymbolToCompletion(it, insertFqName = false) }
|
.forEach { addClassifierSymbolToCompletion(it, ImportStrategy.DoNothing) }
|
||||||
|
|
||||||
scope.getCallableSymbols(scopeNameFilter)
|
scope.getCallableSymbols(scopeNameFilter)
|
||||||
.filter { with(visibilityChecker) { isVisible(it) } }
|
.filter { with(visibilityChecker) { isVisible(it) } }
|
||||||
.forEach {
|
.forEach {
|
||||||
addCallableSymbolToCompletion(
|
addCallableSymbolToCompletion(
|
||||||
|
expectedType = null,
|
||||||
it,
|
it,
|
||||||
importingStrategy = CallableImportStrategy.DoNothing,
|
importingStrategy = ImportStrategy.DoNothing,
|
||||||
insertionStrategy = CallableInsertionStrategy.AS_IDENTIFIER
|
insertionStrategy = CallableInsertionStrategy.AS_IDENTIFIER
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
-57
@@ -1,57 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.jetbrains.kotlin.idea.completion.lookups
|
|
||||||
|
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.analyse
|
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.addImportToFile
|
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtCallableSymbol
|
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtFunctionSymbol
|
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtKotlinPropertySymbol
|
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtPossibleMemberSymbol
|
|
||||||
import org.jetbrains.kotlin.name.CallableId
|
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
|
||||||
|
|
||||||
internal sealed class CallableImportStrategy {
|
|
||||||
object DoNothing : CallableImportStrategy()
|
|
||||||
data class AddImport(val nameToImport: CallableId) : CallableImportStrategy()
|
|
||||||
data class InsertFqNameAndShorten(val callableId: CallableId) : CallableImportStrategy()
|
|
||||||
}
|
|
||||||
|
|
||||||
internal fun detectImportStrategy(symbol: KtCallableSymbol): CallableImportStrategy {
|
|
||||||
if (symbol !is KtPossibleMemberSymbol || symbol.dispatchType != null) return CallableImportStrategy.DoNothing
|
|
||||||
|
|
||||||
val propertyId = symbol.callableIdIfNonLocal ?: return CallableImportStrategy.DoNothing
|
|
||||||
|
|
||||||
return if (symbol.isExtension) {
|
|
||||||
CallableImportStrategy.AddImport(propertyId)
|
|
||||||
} else {
|
|
||||||
CallableImportStrategy.InsertFqNameAndShorten(propertyId)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal fun addCallableImportIfRequired(targetFile: KtFile, nameToImport: CallableId) {
|
|
||||||
if (!alreadyHasImport(targetFile, nameToImport)) {
|
|
||||||
addImportToFile(targetFile.project, targetFile, nameToImport)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun alreadyHasImport(file: KtFile, nameToImport: CallableId): Boolean {
|
|
||||||
if (file.importDirectives.any { it.importPath?.fqName == nameToImport.asSingleFqName() }) return true
|
|
||||||
|
|
||||||
withAllowedResolve {
|
|
||||||
analyse(file) {
|
|
||||||
val scopes = file.getScopeContextForFile().scopes
|
|
||||||
if (!scopes.mayContainName(nameToImport.callableName)) return false
|
|
||||||
|
|
||||||
return scopes
|
|
||||||
.getCallableSymbols { it == nameToImport.callableName }
|
|
||||||
.any {
|
|
||||||
it is KtKotlinPropertySymbol && it.callableIdIfNonLocal == nameToImport ||
|
|
||||||
it is KtFunctionSymbol && it.callableIdIfNonLocal == nameToImport
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.idea.completion.lookups
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession
|
||||||
|
import org.jetbrains.kotlin.idea.frontend.api.analyse
|
||||||
|
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.addImportToFile
|
||||||
|
import org.jetbrains.kotlin.idea.frontend.api.symbols.*
|
||||||
|
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtPossibleMemberSymbol
|
||||||
|
import org.jetbrains.kotlin.name.CallableId
|
||||||
|
import org.jetbrains.kotlin.name.FqName
|
||||||
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
|
|
||||||
|
internal sealed class ImportStrategy {
|
||||||
|
object DoNothing : ImportStrategy()
|
||||||
|
data class AddImport(val nameToImport: FqName) : ImportStrategy()
|
||||||
|
data class InsertFqNameAndShorten(val fqName: FqName) : ImportStrategy()
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun KtAnalysisSession.detectImportStrategy(symbol: KtSymbol): ImportStrategy = when (symbol) {
|
||||||
|
is KtCallableSymbol -> detectImportStrategyForCallableSymbol(symbol)
|
||||||
|
is KtClassLikeSymbol -> detectImportStrategyForClassLikeSymbol(symbol)
|
||||||
|
else -> ImportStrategy.DoNothing
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun KtAnalysisSession.detectImportStrategyForCallableSymbol(symbol: KtCallableSymbol): ImportStrategy {
|
||||||
|
if (symbol !is KtPossibleMemberSymbol || symbol.dispatchType != null) return ImportStrategy.DoNothing
|
||||||
|
|
||||||
|
val propertyId = symbol.callableIdIfNonLocal?.asSingleFqName() ?: return ImportStrategy.DoNothing
|
||||||
|
|
||||||
|
return if (symbol.isExtension) {
|
||||||
|
ImportStrategy.AddImport(propertyId)
|
||||||
|
} else {
|
||||||
|
ImportStrategy.InsertFqNameAndShorten(propertyId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun KtAnalysisSession.detectImportStrategyForClassLikeSymbol(symbol: KtClassLikeSymbol): ImportStrategy {
|
||||||
|
val classId = symbol.classIdIfNonLocal ?: return ImportStrategy.DoNothing
|
||||||
|
return ImportStrategy.InsertFqNameAndShorten(classId.asSingleFqName())
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun addCallableImportIfRequired(targetFile: KtFile, nameToImport: FqName) {
|
||||||
|
if (!alreadyHasImport(targetFile, nameToImport)) {
|
||||||
|
addImportToFile(targetFile.project, targetFile, nameToImport)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun alreadyHasImport(file: KtFile, nameToImport: FqName): Boolean {
|
||||||
|
if (file.importDirectives.any { it.importPath?.fqName == nameToImport }) return true
|
||||||
|
|
||||||
|
withAllowedResolve {
|
||||||
|
analyse(file) {
|
||||||
|
val scopes = file.getScopeContextForFile().scopes
|
||||||
|
if (!scopes.mayContainName(nameToImport.shortName())) return false
|
||||||
|
|
||||||
|
val anyCallableSymbolMatches = scopes
|
||||||
|
.getCallableSymbols { it == nameToImport.shortName() }
|
||||||
|
.any { callable ->
|
||||||
|
val callableFqName = callable.callableIdIfNonLocal?.asSingleFqName()
|
||||||
|
callable is KtKotlinPropertySymbol && callableFqName == nameToImport ||
|
||||||
|
callable is KtFunctionSymbol && callableFqName == nameToImport
|
||||||
|
}
|
||||||
|
if (anyCallableSymbolMatches) return true
|
||||||
|
|
||||||
|
return scopes.getClassifierSymbols { it == nameToImport.shortName() }.any { classifier ->
|
||||||
|
val classId = (classifier as? KtClassLikeSymbol)?.classIdIfNonLocal
|
||||||
|
classId?.asSingleFqName() == nameToImport
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+12
-8
@@ -10,6 +10,8 @@ import com.intellij.codeInsight.completion.InsertionContext
|
|||||||
import com.intellij.codeInsight.lookup.LookupElement
|
import com.intellij.codeInsight.lookup.LookupElement
|
||||||
import com.intellij.codeInsight.lookup.LookupElementBuilder
|
import com.intellij.codeInsight.lookup.LookupElementBuilder
|
||||||
import com.intellij.openapi.util.TextRange
|
import com.intellij.openapi.util.TextRange
|
||||||
|
import org.jetbrains.kotlin.idea.completion.lookups.*
|
||||||
|
import org.jetbrains.kotlin.idea.completion.lookups.ImportStrategy
|
||||||
import org.jetbrains.kotlin.idea.completion.lookups.KotlinLookupObject
|
import org.jetbrains.kotlin.idea.completion.lookups.KotlinLookupObject
|
||||||
import org.jetbrains.kotlin.idea.completion.lookups.shortenReferencesForFirCompletion
|
import org.jetbrains.kotlin.idea.completion.lookups.shortenReferencesForFirCompletion
|
||||||
import org.jetbrains.kotlin.idea.completion.lookups.withSymbolInfo
|
import org.jetbrains.kotlin.idea.completion.lookups.withSymbolInfo
|
||||||
@@ -21,10 +23,13 @@ import org.jetbrains.kotlin.name.Name
|
|||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.renderer.render
|
import org.jetbrains.kotlin.renderer.render
|
||||||
|
|
||||||
class ClassLookupElementFactory {
|
internal class ClassLookupElementFactory {
|
||||||
fun KtAnalysisSession.createLookup(symbol: KtClassLikeSymbol, insertFqName: Boolean = true): LookupElementBuilder {
|
fun KtAnalysisSession.createLookup(
|
||||||
|
symbol: KtClassLikeSymbol,
|
||||||
|
importingStrategy: ImportStrategy = detectImportStrategy(symbol)
|
||||||
|
): LookupElementBuilder {
|
||||||
val name = symbol.nameOrAnonymous
|
val name = symbol.nameOrAnonymous
|
||||||
return LookupElementBuilder.create(ClassifierLookupObject(name, symbol.classIdIfNonLocal, insertFqName), name.asString())
|
return LookupElementBuilder.create(ClassifierLookupObject(name, importingStrategy), name.asString())
|
||||||
.withInsertHandler(ClassifierInsertionHandler)
|
.withInsertHandler(ClassifierInsertionHandler)
|
||||||
.let { withSymbolInfo(symbol, it) }
|
.let { withSymbolInfo(symbol, it) }
|
||||||
}
|
}
|
||||||
@@ -33,9 +38,8 @@ class ClassLookupElementFactory {
|
|||||||
|
|
||||||
private data class ClassifierLookupObject(
|
private data class ClassifierLookupObject(
|
||||||
override val shortName: Name,
|
override val shortName: Name,
|
||||||
val classId: ClassId?,
|
val importingStrategy: ImportStrategy
|
||||||
val insertFqName: Boolean
|
) : KotlinLookupObject
|
||||||
) : KotlinLookupObject {}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The simplest implementation of the insertion handler for a classifiers.
|
* The simplest implementation of the insertion handler for a classifiers.
|
||||||
@@ -45,8 +49,8 @@ private object ClassifierInsertionHandler : InsertHandler<LookupElement> {
|
|||||||
val targetFile = context.file as? KtFile ?: return
|
val targetFile = context.file as? KtFile ?: return
|
||||||
val lookupObject = item.`object` as ClassifierLookupObject
|
val lookupObject = item.`object` as ClassifierLookupObject
|
||||||
|
|
||||||
if (lookupObject.classId != null && lookupObject.insertFqName) {
|
if (lookupObject.importingStrategy is ImportStrategy.InsertFqNameAndShorten) {
|
||||||
val fqName = lookupObject.classId.asSingleFqName()
|
val fqName = lookupObject.importingStrategy.fqName
|
||||||
|
|
||||||
context.document.replaceString(context.startOffset, context.tailOffset, fqName.render())
|
context.document.replaceString(context.startOffset, context.tailOffset, fqName.render())
|
||||||
context.commitDocument()
|
context.commitDocument()
|
||||||
|
|||||||
+7
-9
@@ -10,18 +10,15 @@ import com.intellij.codeInsight.completion.InsertionContext
|
|||||||
import com.intellij.codeInsight.lookup.Lookup
|
import com.intellij.codeInsight.lookup.Lookup
|
||||||
import com.intellij.codeInsight.lookup.LookupElement
|
import com.intellij.codeInsight.lookup.LookupElement
|
||||||
import com.intellij.codeInsight.lookup.LookupElementBuilder
|
import com.intellij.codeInsight.lookup.LookupElementBuilder
|
||||||
import com.intellij.openapi.diagnostic.ControlFlowException
|
|
||||||
import com.intellij.openapi.diagnostic.logger
|
|
||||||
import com.intellij.openapi.util.TextRange
|
import com.intellij.openapi.util.TextRange
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import org.jetbrains.kotlin.idea.completion.lookups.*
|
import org.jetbrains.kotlin.idea.completion.lookups.*
|
||||||
import org.jetbrains.kotlin.idea.completion.lookups.CallableImportStrategy
|
import org.jetbrains.kotlin.idea.completion.lookups.ImportStrategy
|
||||||
import org.jetbrains.kotlin.idea.completion.lookups.CallableInsertionStrategy
|
import org.jetbrains.kotlin.idea.completion.lookups.CallableInsertionStrategy
|
||||||
import org.jetbrains.kotlin.idea.completion.lookups.CompletionShortNamesRenderer
|
import org.jetbrains.kotlin.idea.completion.lookups.CompletionShortNamesRenderer
|
||||||
import org.jetbrains.kotlin.idea.completion.lookups.QuotedNamesAwareInsertionHandler
|
import org.jetbrains.kotlin.idea.completion.lookups.QuotedNamesAwareInsertionHandler
|
||||||
import org.jetbrains.kotlin.idea.completion.lookups.addCallableImportIfRequired
|
import org.jetbrains.kotlin.idea.completion.lookups.addCallableImportIfRequired
|
||||||
import org.jetbrains.kotlin.idea.completion.lookups.shortenReferencesForFirCompletion
|
import org.jetbrains.kotlin.idea.completion.lookups.shortenReferencesForFirCompletion
|
||||||
import org.jetbrains.kotlin.idea.core.asFqNameWithRootPrefixIfNeeded
|
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession
|
import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.*
|
import org.jetbrains.kotlin.idea.frontend.api.symbols.*
|
||||||
import org.jetbrains.kotlin.lexer.KtTokens
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
@@ -34,11 +31,12 @@ import org.jetbrains.kotlin.idea.completion.lookups.TailTextProvider.getTailText
|
|||||||
import org.jetbrains.kotlin.idea.completion.lookups.TailTextProvider.insertLambdaBraces
|
import org.jetbrains.kotlin.idea.completion.lookups.TailTextProvider.insertLambdaBraces
|
||||||
import org.jetbrains.kotlin.idea.completion.lookups.CompletionShortNamesRenderer.renderFunctionParameters
|
import org.jetbrains.kotlin.idea.completion.lookups.CompletionShortNamesRenderer.renderFunctionParameters
|
||||||
import org.jetbrains.kotlin.idea.completion.lookups.CompletionShortNamesRenderer.TYPE_RENDERING_OPTIONS
|
import org.jetbrains.kotlin.idea.completion.lookups.CompletionShortNamesRenderer.TYPE_RENDERING_OPTIONS
|
||||||
|
import org.jetbrains.kotlin.idea.core.withRootPrefixIfNeeded
|
||||||
|
|
||||||
internal class FunctionLookupElementFactory {
|
internal class FunctionLookupElementFactory {
|
||||||
fun KtAnalysisSession.createLookup(
|
fun KtAnalysisSession.createLookup(
|
||||||
symbol: KtFunctionSymbol,
|
symbol: KtFunctionSymbol,
|
||||||
importStrategy: CallableImportStrategy,
|
importStrategy: ImportStrategy,
|
||||||
insertionStrategy: CallableInsertionStrategy
|
insertionStrategy: CallableInsertionStrategy
|
||||||
): LookupElementBuilder {
|
): LookupElementBuilder {
|
||||||
val lookupObject = FunctionLookupObject(
|
val lookupObject = FunctionLookupObject(
|
||||||
@@ -68,7 +66,7 @@ internal class FunctionLookupElementFactory {
|
|||||||
*/
|
*/
|
||||||
private data class FunctionLookupObject(
|
private data class FunctionLookupObject(
|
||||||
override val shortName: Name,
|
override val shortName: Name,
|
||||||
val importStrategy: CallableImportStrategy,
|
val importStrategy: ImportStrategy,
|
||||||
val inputValueArguments: Boolean,
|
val inputValueArguments: Boolean,
|
||||||
val insertEmptyLambda: Boolean,
|
val insertEmptyLambda: Boolean,
|
||||||
// for distinction between different overloads
|
// for distinction between different overloads
|
||||||
@@ -167,11 +165,11 @@ private object FunctionInsertionHandler : QuotedNamesAwareInsertionHandler() {
|
|||||||
val element = context.file.findElementAt(startOffset) ?: return
|
val element = context.file.findElementAt(startOffset) ?: return
|
||||||
|
|
||||||
val importStrategy = lookupObject.importStrategy
|
val importStrategy = lookupObject.importStrategy
|
||||||
if (importStrategy is CallableImportStrategy.InsertFqNameAndShorten) {
|
if (importStrategy is ImportStrategy.InsertFqNameAndShorten) {
|
||||||
context.document.replaceString(
|
context.document.replaceString(
|
||||||
context.startOffset,
|
context.startOffset,
|
||||||
context.tailOffset,
|
context.tailOffset,
|
||||||
importStrategy.callableId.asFqNameWithRootPrefixIfNeeded().render()
|
importStrategy.fqName.withRootPrefixIfNeeded().render()
|
||||||
)
|
)
|
||||||
context.commitDocument()
|
context.commitDocument()
|
||||||
|
|
||||||
@@ -183,7 +181,7 @@ private object FunctionInsertionHandler : QuotedNamesAwareInsertionHandler() {
|
|||||||
addArguments(context, element, lookupObject)
|
addArguments(context, element, lookupObject)
|
||||||
context.commitDocument()
|
context.commitDocument()
|
||||||
|
|
||||||
if (importStrategy is CallableImportStrategy.AddImport) {
|
if (importStrategy is ImportStrategy.AddImport) {
|
||||||
addCallableImportIfRequired(targetFile, importStrategy.nameToImport)
|
addCallableImportIfRequired(targetFile, importStrategy.nameToImport)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-4
@@ -7,7 +7,7 @@ package org.jetbrains.kotlin.idea.completion.lookups.factories
|
|||||||
|
|
||||||
import com.intellij.codeInsight.lookup.LookupElement
|
import com.intellij.codeInsight.lookup.LookupElement
|
||||||
import com.intellij.codeInsight.lookup.LookupElementBuilder
|
import com.intellij.codeInsight.lookup.LookupElementBuilder
|
||||||
import org.jetbrains.kotlin.idea.completion.lookups.CallableImportStrategy
|
import org.jetbrains.kotlin.idea.completion.lookups.ImportStrategy
|
||||||
import org.jetbrains.kotlin.idea.completion.lookups.CallableInsertionStrategy
|
import org.jetbrains.kotlin.idea.completion.lookups.CallableInsertionStrategy
|
||||||
import org.jetbrains.kotlin.idea.completion.lookups.detectImportStrategy
|
import org.jetbrains.kotlin.idea.completion.lookups.detectImportStrategy
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession
|
import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession
|
||||||
@@ -37,7 +37,7 @@ internal class KotlinFirLookupElementFactory {
|
|||||||
|
|
||||||
fun KtAnalysisSession.createCallableLookupElement(
|
fun KtAnalysisSession.createCallableLookupElement(
|
||||||
symbol: KtCallableSymbol,
|
symbol: KtCallableSymbol,
|
||||||
importingStrategy: CallableImportStrategy,
|
importingStrategy: ImportStrategy,
|
||||||
insertionStrategy: CallableInsertionStrategy,
|
insertionStrategy: CallableInsertionStrategy,
|
||||||
): LookupElementBuilder {
|
): LookupElementBuilder {
|
||||||
return when (symbol) {
|
return when (symbol) {
|
||||||
@@ -50,9 +50,12 @@ internal class KotlinFirLookupElementFactory {
|
|||||||
fun createPackagePartLookupElement(packagePartFqName: FqName): LookupElement =
|
fun createPackagePartLookupElement(packagePartFqName: FqName): LookupElement =
|
||||||
packagePartLookupElementFactory.createPackagePartLookupElement(packagePartFqName)
|
packagePartLookupElementFactory.createPackagePartLookupElement(packagePartFqName)
|
||||||
|
|
||||||
fun KtAnalysisSession.createLookupElementForClassLikeSymbol(symbol: KtClassLikeSymbol, insertFqName: Boolean = true): LookupElement? {
|
fun KtAnalysisSession.createLookupElementForClassLikeSymbol(
|
||||||
|
symbol: KtClassLikeSymbol,
|
||||||
|
importingStrategy: ImportStrategy = detectImportStrategy(symbol)
|
||||||
|
): LookupElement? {
|
||||||
if (symbol !is KtNamedSymbol) return null
|
if (symbol !is KtNamedSymbol) return null
|
||||||
return with(classLookupElementFactory) { createLookup(symbol, insertFqName) }
|
return with(classLookupElementFactory) { createLookup(symbol, importingStrategy) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+8
-8
@@ -11,12 +11,12 @@ import com.intellij.codeInsight.lookup.LookupElement
|
|||||||
import com.intellij.codeInsight.lookup.LookupElementBuilder
|
import com.intellij.codeInsight.lookup.LookupElementBuilder
|
||||||
import com.intellij.openapi.util.TextRange
|
import com.intellij.openapi.util.TextRange
|
||||||
import org.jetbrains.kotlin.idea.completion.lookups.*
|
import org.jetbrains.kotlin.idea.completion.lookups.*
|
||||||
import org.jetbrains.kotlin.idea.completion.lookups.CallableImportStrategy
|
import org.jetbrains.kotlin.idea.completion.lookups.ImportStrategy
|
||||||
import org.jetbrains.kotlin.idea.completion.lookups.TailTextProvider.getTailText
|
import org.jetbrains.kotlin.idea.completion.lookups.TailTextProvider.getTailText
|
||||||
import org.jetbrains.kotlin.idea.completion.lookups.addCallableImportIfRequired
|
import org.jetbrains.kotlin.idea.completion.lookups.addCallableImportIfRequired
|
||||||
import org.jetbrains.kotlin.idea.completion.lookups.detectImportStrategy
|
import org.jetbrains.kotlin.idea.completion.lookups.detectImportStrategy
|
||||||
import org.jetbrains.kotlin.idea.completion.lookups.shortenReferencesForFirCompletion
|
import org.jetbrains.kotlin.idea.completion.lookups.shortenReferencesForFirCompletion
|
||||||
import org.jetbrains.kotlin.idea.core.asFqNameWithRootPrefixIfNeeded
|
import org.jetbrains.kotlin.idea.core.withRootPrefixIfNeeded
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession
|
import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.components.KtTypeRendererOptions
|
import org.jetbrains.kotlin.idea.frontend.api.components.KtTypeRendererOptions
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSyntheticJavaPropertySymbol
|
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSyntheticJavaPropertySymbol
|
||||||
@@ -28,7 +28,7 @@ import org.jetbrains.kotlin.renderer.render
|
|||||||
internal class VariableLookupElementFactory {
|
internal class VariableLookupElementFactory {
|
||||||
fun KtAnalysisSession.createLookup(
|
fun KtAnalysisSession.createLookup(
|
||||||
symbol: KtVariableLikeSymbol,
|
symbol: KtVariableLikeSymbol,
|
||||||
importStrategy: CallableImportStrategy = detectImportStrategy(symbol)
|
importStrategy: ImportStrategy = detectImportStrategy(symbol)
|
||||||
): LookupElementBuilder {
|
): LookupElementBuilder {
|
||||||
val lookupObject = VariableLookupObject(
|
val lookupObject = VariableLookupObject(
|
||||||
symbol.name,
|
symbol.name,
|
||||||
@@ -63,7 +63,7 @@ internal class VariableLookupElementFactory {
|
|||||||
*/
|
*/
|
||||||
private data class VariableLookupObject(
|
private data class VariableLookupObject(
|
||||||
override val shortName: Name,
|
override val shortName: Name,
|
||||||
val importStrategy: CallableImportStrategy,
|
val importStrategy: ImportStrategy,
|
||||||
override val renderedReceiverType: String?,
|
override val renderedReceiverType: String?,
|
||||||
) : KotlinCallableLookupObject()
|
) : KotlinCallableLookupObject()
|
||||||
|
|
||||||
@@ -74,22 +74,22 @@ private object VariableInsertionHandler : InsertHandler<LookupElement> {
|
|||||||
val lookupObject = item.`object` as VariableLookupObject
|
val lookupObject = item.`object` as VariableLookupObject
|
||||||
|
|
||||||
when (val importStrategy = lookupObject.importStrategy) {
|
when (val importStrategy = lookupObject.importStrategy) {
|
||||||
is CallableImportStrategy.AddImport -> {
|
is ImportStrategy.AddImport -> {
|
||||||
addCallableImportIfRequired(targetFile, importStrategy.nameToImport)
|
addCallableImportIfRequired(targetFile, importStrategy.nameToImport)
|
||||||
}
|
}
|
||||||
|
|
||||||
is CallableImportStrategy.InsertFqNameAndShorten -> {
|
is ImportStrategy.InsertFqNameAndShorten -> {
|
||||||
context.document.replaceString(
|
context.document.replaceString(
|
||||||
context.startOffset,
|
context.startOffset,
|
||||||
context.tailOffset,
|
context.tailOffset,
|
||||||
importStrategy.callableId.asFqNameWithRootPrefixIfNeeded().render()
|
importStrategy.fqName.withRootPrefixIfNeeded().render()
|
||||||
)
|
)
|
||||||
|
|
||||||
context.commitDocument()
|
context.commitDocument()
|
||||||
shortenReferencesForFirCompletion(targetFile, TextRange(context.startOffset, context.tailOffset))
|
shortenReferencesForFirCompletion(targetFile, TextRange(context.startOffset, context.tailOffset))
|
||||||
}
|
}
|
||||||
|
|
||||||
is CallableImportStrategy.DoNothing -> {
|
is ImportStrategy.DoNothing -> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,6 +47,17 @@ interface KtScope : ValidityTokenOwner {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a sequence of all [KtSymbol] which current scope contain if declaration name matches [nameFilter]
|
||||||
|
* Constructors are not included here as they have no name
|
||||||
|
*/
|
||||||
|
fun getAllNamedSymbols(nameFilter: KtScopeNameFilter = { true }): Sequence<KtSymbol> = withValidityAssertion {
|
||||||
|
sequence {
|
||||||
|
yieldAll(getCallableSymbols(nameFilter))
|
||||||
|
yieldAll(getClassifierSymbols(nameFilter))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a sequence of [KtCallableSymbol] which current scope contain if declaration name matches [nameFilter]
|
* Return a sequence of [KtCallableSymbol] which current scope contain if declaration name matches [nameFilter]
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user