FIR IDE: implement basic classifier name contributor
This commit is contained in:
committed by
TeamCityServer
parent
58d5907041
commit
1e1ce3067f
@@ -7,7 +7,7 @@ package org.jetbrains.kotlin.psi
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
|
|
||||||
interface KtClassLikeDeclaration : KtDeclaration {
|
interface KtClassLikeDeclaration : KtNamedDeclaration {
|
||||||
/**
|
/**
|
||||||
* Return [ClassId], if the class is not local (E.e, if a class can be accessed by that [ClassId] from another context)
|
* Return [ClassId], if the class is not local (E.e, if a class can be accessed by that [ClassId] from another context)
|
||||||
*
|
*
|
||||||
|
|||||||
-2
@@ -4,6 +4,4 @@ fun Strange(){}
|
|||||||
fun Annotations<S<caret>
|
fun Annotations<S<caret>
|
||||||
|
|
||||||
// INVOCATION_COUNT: 0
|
// INVOCATION_COUNT: 0
|
||||||
// EXIST: String
|
|
||||||
// EXIST: Set
|
|
||||||
// ABSENT: Strange
|
// ABSENT: Strange
|
||||||
|
|||||||
+5
@@ -70,6 +70,7 @@ private object KotlinFirCompletionProvider : CompletionProvider<CompletionParame
|
|||||||
val packageCompletionContributor = FirPackageCompletionContributor(basicContext)
|
val packageCompletionContributor = FirPackageCompletionContributor(basicContext)
|
||||||
val importDirectivePackageMembersCompletionContributor = FirImportDirectivePackageMembersCompletionContributor(basicContext)
|
val importDirectivePackageMembersCompletionContributor = FirImportDirectivePackageMembersCompletionContributor(basicContext)
|
||||||
val typeParameterConstraintNameInWhereClauseContributor = FirTypeParameterConstraintNameInWhereClauseCompletionContributor(basicContext)
|
val typeParameterConstraintNameInWhereClauseContributor = FirTypeParameterConstraintNameInWhereClauseCompletionContributor(basicContext)
|
||||||
|
val classifierNameContributor = FirSameAsFileClassifierNameCompletionContributor(basicContext)
|
||||||
|
|
||||||
when (positionContext) {
|
when (positionContext) {
|
||||||
is FirExpressionNameReferencePositionContext -> {
|
is FirExpressionNameReferencePositionContext -> {
|
||||||
@@ -112,6 +113,10 @@ private object KotlinFirCompletionProvider : CompletionProvider<CompletionParame
|
|||||||
complete(keywordContributor, positionContext)
|
complete(keywordContributor, positionContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
is FirClassifierNamePositionContext -> {
|
||||||
|
complete(classifierNameContributor, 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
|
||||||
}
|
}
|
||||||
|
|||||||
+27
-4
@@ -20,9 +20,15 @@ internal sealed class FirRawPositionCompletionContext {
|
|||||||
abstract val position: PsiElement
|
abstract val position: PsiElement
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal class FirClassifierNamePositionContext(
|
||||||
|
override val position: PsiElement,
|
||||||
|
val classLikeDeclaration: KtClassLikeDeclaration,
|
||||||
|
) : FirRawPositionCompletionContext()
|
||||||
|
|
||||||
|
|
||||||
internal class FirIncorrectPositionContext(
|
internal class FirIncorrectPositionContext(
|
||||||
override val position: PsiElement
|
override val position: PsiElement
|
||||||
): FirRawPositionCompletionContext()
|
) : FirRawPositionCompletionContext()
|
||||||
|
|
||||||
internal class FirTypeConstraintNameInWhereClausePositionContext(
|
internal class FirTypeConstraintNameInWhereClausePositionContext(
|
||||||
override val position: PsiElement,
|
override val position: PsiElement,
|
||||||
@@ -89,10 +95,26 @@ internal class FirUnknownPositionContext(
|
|||||||
internal object FirPositionCompletionContextDetector {
|
internal object FirPositionCompletionContextDetector {
|
||||||
fun detect(basicContext: FirBasicCompletionContext): FirRawPositionCompletionContext {
|
fun detect(basicContext: FirBasicCompletionContext): FirRawPositionCompletionContext {
|
||||||
val position = basicContext.parameters.position
|
val position = basicContext.parameters.position
|
||||||
|
return detectForPositionWithReference(position)
|
||||||
|
?: detectForPositionWithoutReference(position)
|
||||||
|
?: FirUnknownPositionContext(position)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun detectForPositionWithoutReference(position: PsiElement): FirRawPositionCompletionContext? {
|
||||||
|
val parent = position.parent
|
||||||
|
return when {
|
||||||
|
parent is KtClassLikeDeclaration && parent.nameIdentifier == position -> {
|
||||||
|
FirClassifierNamePositionContext(position, parent)
|
||||||
|
}
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun detectForPositionWithReference(position: PsiElement): FirRawPositionCompletionContext? {
|
||||||
val reference = (position.parent as? KtSimpleNameExpression)?.mainReference
|
val reference = (position.parent as? KtSimpleNameExpression)?.mainReference
|
||||||
?: return FirUnknownPositionContext(position)
|
?: return null
|
||||||
val nameExpression = reference.expression.takeIf { it !is KtLabelReferenceExpression }
|
val nameExpression = reference.expression.takeIf { it !is KtLabelReferenceExpression }
|
||||||
?: return FirUnknownPositionContext(position)
|
?: return null
|
||||||
val explicitReceiver = nameExpression.getReceiverExpression()
|
val explicitReceiver = nameExpression.getReceiverExpression()
|
||||||
val parent = nameExpression.parent
|
val parent = nameExpression.parent
|
||||||
|
|
||||||
@@ -190,7 +212,8 @@ internal object FirPositionCompletionContextDetector {
|
|||||||
is FirImportDirectivePositionContext,
|
is FirImportDirectivePositionContext,
|
||||||
is FirPackageDirectivePositionContext,
|
is FirPackageDirectivePositionContext,
|
||||||
is FirTypeConstraintNameInWhereClausePositionContext,
|
is FirTypeConstraintNameInWhereClausePositionContext,
|
||||||
is FirIncorrectPositionContext -> {
|
is FirIncorrectPositionContext,
|
||||||
|
is FirClassifierNamePositionContext -> {
|
||||||
analyse(basicContext.originalKtFile, action)
|
analyse(basicContext.originalKtFile, action)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -46,7 +46,7 @@ internal class FirKeywordCompletionContributor(basicContext: FirBasicCompletionC
|
|||||||
else -> reference.expression
|
else -> reference.expression
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is FirTypeConstraintNameInWhereClausePositionContext, is FirIncorrectPositionContext -> {
|
is FirTypeConstraintNameInWhereClausePositionContext, is FirIncorrectPositionContext, is FirClassifierNamePositionContext -> {
|
||||||
error("keyword completion should not be called for ${positionContext::class.simpleName}")
|
error("keyword completion should not be called for ${positionContext::class.simpleName}")
|
||||||
}
|
}
|
||||||
is FirUnknownPositionContext -> null
|
is FirUnknownPositionContext -> null
|
||||||
|
|||||||
+36
@@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* 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.contributors
|
||||||
|
|
||||||
|
import com.intellij.codeInsight.lookup.LookupElementBuilder
|
||||||
|
import org.jetbrains.kotlin.idea.completion.context.FirBasicCompletionContext
|
||||||
|
import org.jetbrains.kotlin.idea.completion.context.FirClassifierNamePositionContext
|
||||||
|
import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||||
|
import org.jetbrains.kotlin.renderer.render
|
||||||
|
|
||||||
|
internal class FirSameAsFileClassifierNameCompletionContributor(
|
||||||
|
basicContext: FirBasicCompletionContext
|
||||||
|
) : FirCompletionContributorBase<FirClassifierNamePositionContext>(basicContext) {
|
||||||
|
|
||||||
|
override fun KtAnalysisSession.complete(positionContext: FirClassifierNamePositionContext) {
|
||||||
|
if (positionContext.classLikeDeclaration is KtClassOrObject) {
|
||||||
|
completeTopLevelClassName(positionContext.classLikeDeclaration)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun completeTopLevelClassName(classOrObject: KtClassOrObject) {
|
||||||
|
if (!classOrObject.isTopLevel()) return
|
||||||
|
val name = originalKtFile.virtualFile.nameWithoutExtension
|
||||||
|
if (!isValidUpperCapitalizedClassName(name)) return
|
||||||
|
if (originalKtFile.declarations.any { it is KtClassOrObject && it.name == name }) return
|
||||||
|
result.addElement(LookupElementBuilder.create(name))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isValidUpperCapitalizedClassName(name: String) =
|
||||||
|
Name.isValidIdentifier(name) && Name.identifier(name).render() == name && name[0].isUpperCase()
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user