Refactor keyword completion handlers
- Separate completion keyword handlers stuff into files - Introduce CompletionKeywordHandlerProvider as a common way to provide handlers - Move CompletionKeywordHandler factory out of companion object
This commit is contained in:
committed by
TeamCityServer
parent
8983bde73e
commit
e5202f44d7
+3
-1
@@ -24,6 +24,8 @@ import org.jetbrains.kotlin.descriptors.*
|
|||||||
import org.jetbrains.kotlin.idea.analysis.analyzeInContext
|
import org.jetbrains.kotlin.idea.analysis.analyzeInContext
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.util.resolveToDescriptor
|
import org.jetbrains.kotlin.idea.caches.resolve.util.resolveToDescriptor
|
||||||
import org.jetbrains.kotlin.idea.codeInsight.ReferenceVariantsHelper
|
import org.jetbrains.kotlin.idea.codeInsight.ReferenceVariantsHelper
|
||||||
|
import org.jetbrains.kotlin.idea.completion.keywords.DefaultCompletionKeywordHandlerProvider
|
||||||
|
import org.jetbrains.kotlin.idea.completion.keywords.createLookups
|
||||||
import org.jetbrains.kotlin.idea.completion.smart.ExpectedInfoMatch
|
import org.jetbrains.kotlin.idea.completion.smart.ExpectedInfoMatch
|
||||||
import org.jetbrains.kotlin.idea.completion.smart.SMART_COMPLETION_ITEM_PRIORITY_KEY
|
import org.jetbrains.kotlin.idea.completion.smart.SMART_COMPLETION_ITEM_PRIORITY_KEY
|
||||||
import org.jetbrains.kotlin.idea.completion.smart.SmartCompletion
|
import org.jetbrains.kotlin.idea.completion.smart.SmartCompletion
|
||||||
@@ -583,7 +585,7 @@ class BasicCompletionSession(
|
|||||||
val keyword = lookupElement.lookupString
|
val keyword = lookupElement.lookupString
|
||||||
if (keyword in keywordsToSkip) return@complete
|
if (keyword in keywordsToSkip) return@complete
|
||||||
|
|
||||||
val completionKeywordHandler = DefaultCompletionKeywordHandlers.defaultHandlers.getHandlerForKeyword(keyword)
|
val completionKeywordHandler = DefaultCompletionKeywordHandlerProvider.getHandlerForKeyword(keyword)
|
||||||
if (completionKeywordHandler != null) {
|
if (completionKeywordHandler != null) {
|
||||||
val lookups = completionKeywordHandler.createLookups(parameters, expression, lookupElement, project)
|
val lookups = completionKeywordHandler.createLookups(parameters, expression, lookupElement, project)
|
||||||
collector.addElements(lookups)
|
collector.addElements(lookups)
|
||||||
|
|||||||
+12
-5
@@ -16,6 +16,11 @@ import org.jetbrains.kotlin.idea.completion.context.FirPositionCompletionContext
|
|||||||
import org.jetbrains.kotlin.idea.completion.context.FirUnknownPositionContext
|
import org.jetbrains.kotlin.idea.completion.context.FirUnknownPositionContext
|
||||||
import org.jetbrains.kotlin.idea.completion.contributors.keywords.OverrideKeywordHandler
|
import org.jetbrains.kotlin.idea.completion.contributors.keywords.OverrideKeywordHandler
|
||||||
import org.jetbrains.kotlin.idea.completion.contributors.keywords.ReturnKeywordHandler
|
import org.jetbrains.kotlin.idea.completion.contributors.keywords.ReturnKeywordHandler
|
||||||
|
import org.jetbrains.kotlin.idea.completion.contributors.keywords.ReturnKeywordHandler.createLookups
|
||||||
|
import org.jetbrains.kotlin.idea.completion.keywords.CompletionKeywordHandlerProvider
|
||||||
|
import org.jetbrains.kotlin.idea.completion.keywords.CompletionKeywordHandlers
|
||||||
|
import org.jetbrains.kotlin.idea.completion.keywords.DefaultCompletionKeywordHandlerProvider
|
||||||
|
import org.jetbrains.kotlin.idea.completion.keywords.createLookups
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession
|
import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession
|
||||||
import org.jetbrains.kotlin.platform.jvm.isJvm
|
import org.jetbrains.kotlin.platform.jvm.isJvm
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
@@ -26,7 +31,7 @@ internal class FirKeywordCompletionContributor(basicContext: FirBasicCompletionC
|
|||||||
override fun getLanguageVersionSetting(module: Module) = LanguageVersionSettingsImpl.DEFAULT // TODO
|
override fun getLanguageVersionSetting(module: Module) = LanguageVersionSettingsImpl.DEFAULT // TODO
|
||||||
})
|
})
|
||||||
|
|
||||||
private val resolveDependentCompletionKeywordHandlers = ResolveDependentCompletionKeywordHandlers(basicContext)
|
private val resolveDependentCompletionKeywordHandlers = ResolveDependentCompletionKeywordHandlerProvider(basicContext)
|
||||||
|
|
||||||
fun KtAnalysisSession.completeKeywords(
|
fun KtAnalysisSession.completeKeywords(
|
||||||
positionContext: FirPositionCompletionContext
|
positionContext: FirPositionCompletionContext
|
||||||
@@ -46,9 +51,9 @@ internal class FirKeywordCompletionContributor(basicContext: FirBasicCompletionC
|
|||||||
|
|
||||||
fun KtAnalysisSession.completeWithResolve(position: PsiElement, expression: KtExpression?) {
|
fun KtAnalysisSession.completeWithResolve(position: PsiElement, expression: KtExpression?) {
|
||||||
complete(position) { lookupElement, keyword ->
|
complete(position) { lookupElement, keyword ->
|
||||||
val lookups = DefaultCompletionKeywordHandlers.defaultHandlers.getHandlerForKeyword(keyword)
|
val lookups = DefaultCompletionKeywordHandlerProvider.getHandlerForKeyword(keyword)
|
||||||
?.createLookups(parameters, expression, lookupElement, project)
|
?.createLookups(parameters, expression, lookupElement, project)
|
||||||
?: resolveDependentCompletionKeywordHandlers.handlers.getHandlerForKeyword(keyword)?.run {
|
?: resolveDependentCompletionKeywordHandlers.getHandlerForKeyword(keyword)?.run {
|
||||||
createLookups(parameters, expression, lookupElement, project)
|
createLookups(parameters, expression, lookupElement, project)
|
||||||
}
|
}
|
||||||
?: listOf(lookupElement)
|
?: listOf(lookupElement)
|
||||||
@@ -64,8 +69,10 @@ internal class FirKeywordCompletionContributor(basicContext: FirBasicCompletionC
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ResolveDependentCompletionKeywordHandlers(basicContext: FirBasicCompletionContext) {
|
private class ResolveDependentCompletionKeywordHandlerProvider(
|
||||||
val handlers = CompletionKeywordHandlers(
|
basicContext: FirBasicCompletionContext
|
||||||
|
) : CompletionKeywordHandlerProvider<KtAnalysisSession>() {
|
||||||
|
override val handlers = CompletionKeywordHandlers(
|
||||||
ReturnKeywordHandler,
|
ReturnKeywordHandler,
|
||||||
OverrideKeywordHandler(basicContext),
|
OverrideKeywordHandler(basicContext),
|
||||||
)
|
)
|
||||||
|
|||||||
+1
@@ -13,6 +13,7 @@ import com.intellij.ui.RowIcon
|
|||||||
import org.jetbrains.kotlin.descriptors.Modality
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
import org.jetbrains.kotlin.idea.completion.*
|
import org.jetbrains.kotlin.idea.completion.*
|
||||||
import org.jetbrains.kotlin.idea.completion.context.FirBasicCompletionContext
|
import org.jetbrains.kotlin.idea.completion.context.FirBasicCompletionContext
|
||||||
|
import org.jetbrains.kotlin.idea.completion.keywords.CompletionKeywordHandler
|
||||||
import org.jetbrains.kotlin.idea.core.overrideImplement.*
|
import org.jetbrains.kotlin.idea.core.overrideImplement.*
|
||||||
import org.jetbrains.kotlin.idea.core.overrideImplement.KtClassMember
|
import org.jetbrains.kotlin.idea.core.overrideImplement.KtClassMember
|
||||||
import org.jetbrains.kotlin.idea.core.overrideImplement.KtGenerateMembersHandler
|
import org.jetbrains.kotlin.idea.core.overrideImplement.KtGenerateMembersHandler
|
||||||
|
|||||||
+1
-1
@@ -8,9 +8,9 @@ package org.jetbrains.kotlin.idea.completion.contributors.keywords
|
|||||||
import com.intellij.codeInsight.completion.CompletionParameters
|
import com.intellij.codeInsight.completion.CompletionParameters
|
||||||
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.CompletionKeywordHandler
|
|
||||||
import org.jetbrains.kotlin.idea.completion.createKeywordElement
|
import org.jetbrains.kotlin.idea.completion.createKeywordElement
|
||||||
import org.jetbrains.kotlin.idea.completion.createKeywordElementWithSpace
|
import org.jetbrains.kotlin.idea.completion.createKeywordElementWithSpace
|
||||||
|
import org.jetbrains.kotlin.idea.completion.keywords.CompletionKeywordHandler
|
||||||
import org.jetbrains.kotlin.idea.completion.labelNameToTail
|
import org.jetbrains.kotlin.idea.completion.labelNameToTail
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession
|
import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession
|
||||||
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtFunctionSymbol
|
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtFunctionSymbol
|
||||||
|
|||||||
+54
@@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* 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.keywords
|
||||||
|
|
||||||
|
import com.intellij.codeInsight.completion.CompletionParameters
|
||||||
|
import com.intellij.codeInsight.lookup.LookupElement
|
||||||
|
import com.intellij.openapi.project.Project
|
||||||
|
import org.jetbrains.kotlin.lexer.KtKeywordToken
|
||||||
|
import org.jetbrains.kotlin.psi.KtExpression
|
||||||
|
|
||||||
|
abstract class CompletionKeywordHandler<CONTEXT>(
|
||||||
|
val keyword: KtKeywordToken
|
||||||
|
) {
|
||||||
|
object NO_CONTEXT
|
||||||
|
|
||||||
|
abstract fun CONTEXT.createLookups(
|
||||||
|
parameters: CompletionParameters,
|
||||||
|
expression: KtExpression?,
|
||||||
|
lookup: LookupElement,
|
||||||
|
project: Project
|
||||||
|
): Collection<LookupElement>
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun <CONTEXT> completionKeywordHandler(
|
||||||
|
keyword: KtKeywordToken,
|
||||||
|
crossinline create: CONTEXT.(
|
||||||
|
parameters: CompletionParameters,
|
||||||
|
expression: KtExpression?,
|
||||||
|
lookup: LookupElement,
|
||||||
|
project: Project
|
||||||
|
) -> Collection<LookupElement>
|
||||||
|
) = object : CompletionKeywordHandler<CONTEXT>(keyword) {
|
||||||
|
override fun CONTEXT.createLookups(
|
||||||
|
parameters: CompletionParameters,
|
||||||
|
expression: KtExpression?,
|
||||||
|
lookup: LookupElement,
|
||||||
|
project: Project
|
||||||
|
): Collection<LookupElement> = create(parameters, expression, lookup, project)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a list of [LookupElement] for [CompletionKeywordHandler] which has no context
|
||||||
|
*
|
||||||
|
* This function is needed to avoid writing `with(CompletionKeywordHandler.NO_CONTEXT) { ... }` to create such lookups
|
||||||
|
*/
|
||||||
|
fun CompletionKeywordHandler<CompletionKeywordHandler.NO_CONTEXT>.createLookups(
|
||||||
|
parameters: CompletionParameters,
|
||||||
|
expression: KtExpression?,
|
||||||
|
lookup: LookupElement,
|
||||||
|
project: Project
|
||||||
|
): Collection<LookupElement> = with(CompletionKeywordHandler.NO_CONTEXT) { createLookups(parameters, expression, lookup, project) }
|
||||||
+21
@@ -0,0 +1,21 @@
|
|||||||
|
/*
|
||||||
|
* 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.keywords
|
||||||
|
|
||||||
|
abstract class CompletionKeywordHandlerProvider<CONTEXT> {
|
||||||
|
protected abstract val handlers: CompletionKeywordHandlers<CONTEXT>
|
||||||
|
|
||||||
|
fun getHandlerForKeyword(keyword: String): CompletionKeywordHandler<CONTEXT>? =
|
||||||
|
handlers.getHandlerForKeyword(keyword)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class CompletionKeywordHandlers<CONTEXT>(vararg handlers: CompletionKeywordHandler<CONTEXT>) {
|
||||||
|
private val handlerByKeyword = handlers.associateBy { it.keyword.value }
|
||||||
|
|
||||||
|
internal fun getHandlerForKeyword(keyword: String): CompletionKeywordHandler<CONTEXT>? =
|
||||||
|
handlerByKeyword[keyword]
|
||||||
|
}
|
||||||
+9
-60
@@ -3,48 +3,36 @@
|
|||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* 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
|
package org.jetbrains.kotlin.idea.completion.keywords
|
||||||
|
|
||||||
import com.intellij.codeInsight.completion.CompletionParameters
|
import com.intellij.codeInsight.completion.CompletionParameters
|
||||||
import com.intellij.codeInsight.lookup.LookupElement
|
import org.jetbrains.kotlin.idea.completion.breakOrContinueExpressionItems
|
||||||
import com.intellij.openapi.project.Project
|
|
||||||
import org.jetbrains.kotlin.idea.completion.handlers.createKeywordConstructLookupElement
|
import org.jetbrains.kotlin.idea.completion.handlers.createKeywordConstructLookupElement
|
||||||
import org.jetbrains.kotlin.lexer.KtKeywordToken
|
|
||||||
import org.jetbrains.kotlin.lexer.KtTokens
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
import org.jetbrains.kotlin.psi.KtExpression
|
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.prevLeaf
|
import org.jetbrains.kotlin.psi.psiUtil.prevLeaf
|
||||||
|
|
||||||
class CompletionKeywordHandlers<CONTEXT>(handlers: List<CompletionKeywordHandler<CONTEXT>>) {
|
|
||||||
constructor(vararg handlers: CompletionKeywordHandler<CONTEXT>) : this(handlers.toList())
|
|
||||||
|
|
||||||
private val handlerByKeyword = handlers.associateBy { it.keyword.value }
|
|
||||||
|
|
||||||
fun getHandlerForKeyword(keyword: String): CompletionKeywordHandler<CONTEXT>? =
|
|
||||||
handlerByKeyword[keyword]
|
|
||||||
}
|
|
||||||
|
|
||||||
@OptIn(ExperimentalStdlibApi::class)
|
@OptIn(ExperimentalStdlibApi::class)
|
||||||
object DefaultCompletionKeywordHandlers {
|
object DefaultCompletionKeywordHandlerProvider : CompletionKeywordHandlerProvider<CompletionKeywordHandler.NO_CONTEXT>() {
|
||||||
private val BREAK_HANDLER =
|
private val BREAK_HANDLER =
|
||||||
CompletionKeywordHandler<CompletionKeywordHandler.NO_CONTEXT>(KtTokens.BREAK_KEYWORD) { _, expression, _, _ ->
|
completionKeywordHandler<CompletionKeywordHandler.NO_CONTEXT>(KtTokens.BREAK_KEYWORD) { _, expression, _, _ ->
|
||||||
if (expression != null) {
|
if (expression != null) {
|
||||||
breakOrContinueExpressionItems(expression, KtTokens.BREAK_KEYWORD.value)
|
breakOrContinueExpressionItems(expression, KtTokens.BREAK_KEYWORD.value)
|
||||||
} else emptyList()
|
} else emptyList()
|
||||||
}
|
}
|
||||||
|
|
||||||
private val CONTINUE_HANDLER =
|
private val CONTINUE_HANDLER =
|
||||||
CompletionKeywordHandler<CompletionKeywordHandler.NO_CONTEXT>(KtTokens.CONTINUE_KEYWORD) { _, expression, _, _ ->
|
completionKeywordHandler<CompletionKeywordHandler.NO_CONTEXT>(KtTokens.CONTINUE_KEYWORD) { _, expression, _, _ ->
|
||||||
if (expression != null) {
|
if (expression != null) {
|
||||||
breakOrContinueExpressionItems(expression, KtTokens.CONTINUE_KEYWORD.value)
|
breakOrContinueExpressionItems(expression, KtTokens.CONTINUE_KEYWORD.value)
|
||||||
} else emptyList()
|
} else emptyList()
|
||||||
}
|
}
|
||||||
|
|
||||||
private val CONTRACT_HANDLER = CompletionKeywordHandler<CompletionKeywordHandler.NO_CONTEXT>(KtTokens.CONTRACT_KEYWORD) { _, _, _, _ ->
|
private val CONTRACT_HANDLER = completionKeywordHandler<CompletionKeywordHandler.NO_CONTEXT>(KtTokens.CONTRACT_KEYWORD) { _, _, _, _ ->
|
||||||
emptyList()
|
emptyList()
|
||||||
}
|
}
|
||||||
|
|
||||||
private val GETTER_HANDLER =
|
private val GETTER_HANDLER =
|
||||||
CompletionKeywordHandler<CompletionKeywordHandler.NO_CONTEXT>(KtTokens.GET_KEYWORD) { parameters, _, lookupElement, project ->
|
completionKeywordHandler<CompletionKeywordHandler.NO_CONTEXT>(KtTokens.GET_KEYWORD) { parameters, _, lookupElement, project ->
|
||||||
buildList {
|
buildList {
|
||||||
add(lookupElement)
|
add(lookupElement)
|
||||||
if (!parameters.isUseSiteAnnotationTarget) {
|
if (!parameters.isUseSiteAnnotationTarget) {
|
||||||
@@ -62,7 +50,7 @@ object DefaultCompletionKeywordHandlers {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private val SETTER_HANDLER =
|
private val SETTER_HANDLER =
|
||||||
CompletionKeywordHandler<CompletionKeywordHandler.NO_CONTEXT>(KtTokens.SET_KEYWORD) { parameters, _, lookupElement, project ->
|
completionKeywordHandler<CompletionKeywordHandler.NO_CONTEXT>(KtTokens.SET_KEYWORD) { parameters, _, lookupElement, project ->
|
||||||
buildList {
|
buildList {
|
||||||
add(lookupElement)
|
add(lookupElement)
|
||||||
if (!parameters.isUseSiteAnnotationTarget) {
|
if (!parameters.isUseSiteAnnotationTarget) {
|
||||||
@@ -79,52 +67,13 @@ object DefaultCompletionKeywordHandlers {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val defaultHandlers = CompletionKeywordHandlers(
|
override val handlers = CompletionKeywordHandlers(
|
||||||
BREAK_HANDLER, CONTINUE_HANDLER,
|
BREAK_HANDLER, CONTINUE_HANDLER,
|
||||||
GETTER_HANDLER, SETTER_HANDLER,
|
GETTER_HANDLER, SETTER_HANDLER,
|
||||||
CONTRACT_HANDLER,
|
CONTRACT_HANDLER,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun CompletionKeywordHandler<CompletionKeywordHandler.NO_CONTEXT>.createLookups(
|
|
||||||
parameters: CompletionParameters,
|
|
||||||
expression: KtExpression?,
|
|
||||||
lookup: LookupElement,
|
|
||||||
project: Project
|
|
||||||
): Collection<LookupElement> = with(CompletionKeywordHandler.NO_CONTEXT) { createLookups(parameters, expression, lookup, project) }
|
|
||||||
|
|
||||||
private val CompletionParameters.isUseSiteAnnotationTarget
|
private val CompletionParameters.isUseSiteAnnotationTarget
|
||||||
get() = position.prevLeaf()?.node?.elementType == KtTokens.AT
|
get() = position.prevLeaf()?.node?.elementType == KtTokens.AT
|
||||||
|
|
||||||
|
|
||||||
abstract class CompletionKeywordHandler<CONTEXT>(
|
|
||||||
val keyword: KtKeywordToken
|
|
||||||
) {
|
|
||||||
object NO_CONTEXT
|
|
||||||
|
|
||||||
abstract fun CONTEXT.createLookups(
|
|
||||||
parameters: CompletionParameters,
|
|
||||||
expression: KtExpression?,
|
|
||||||
lookup: LookupElement,
|
|
||||||
project: Project
|
|
||||||
): Collection<LookupElement>
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
inline operator fun <CONTEXT> invoke(
|
|
||||||
keyword: KtKeywordToken,
|
|
||||||
crossinline create: CONTEXT.(
|
|
||||||
parameters: CompletionParameters,
|
|
||||||
expression: KtExpression?,
|
|
||||||
lookup: LookupElement,
|
|
||||||
project: Project
|
|
||||||
) -> Collection<LookupElement>
|
|
||||||
) = object : CompletionKeywordHandler<CONTEXT>(keyword) {
|
|
||||||
override fun CONTEXT.createLookups(
|
|
||||||
parameters: CompletionParameters,
|
|
||||||
expression: KtExpression?,
|
|
||||||
lookup: LookupElement,
|
|
||||||
project: Project
|
|
||||||
): Collection<LookupElement> = create(parameters, expression, lookup, project)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user