[LL API] Get designation correctly for enum value members (KTIJ-23458)

Although being a 'KtClass' in the PSI, 'KtEnumEntry' is a callable in
Analysis API, and its direct members should also be treated as local.
This commit is contained in:
Yan Zhulanow
2022-11-01 23:15:23 +09:00
committed by teamcity
parent 4d41ac09df
commit b770e5d02f
4 changed files with 26 additions and 15 deletions
@@ -37,26 +37,21 @@ import org.jetbrains.kotlin.fir.scopes.kotlinScopeProvider
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
import org.jetbrains.kotlin.psi.psiUtil.isAncestor
import org.jetbrains.kotlin.analysis.utils.errors.buildErrorWithAttachment
import org.jetbrains.kotlin.analysis.utils.errors.*
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf
object LowLevelFirApiFacadeForResolveOnAir {
private fun KtDeclaration.canBeEnclosingDeclaration(): Boolean = when (this) {
is KtNamedFunction -> isTopLevel || containingClassOrObject?.isLocal == false
is KtProperty -> isTopLevel || containingClassOrObject?.isLocal == false
is KtClassOrObject -> !isLocal
is KtTypeAlias -> isTopLevel() || containingClassOrObject?.isLocal == false
else -> false
private fun findNonLocalParentMaybeSelf(position: KtElement): KtNamedDeclaration? {
return position.parentsWithSelf
.filterIsInstance<KtNamedDeclaration>()
.filter { it is KtNamedFunction || it is KtProperty || (it is KtClassOrObject && it !is KtEnumEntry) || it is KtTypeAlias }
.filter { !KtPsiUtil.isLocal(it) && it.containingClassOrObject !is KtEnumEntry }
.firstOrNull()
}
private fun findEnclosingNonLocalDeclaration(position: KtElement): KtNamedDeclaration? =
position.parentsOfType<KtNamedDeclaration>().firstOrNull { ktDeclaration ->
ktDeclaration.canBeEnclosingDeclaration()
}
private fun recordOriginalDeclaration(targetDeclaration: KtNamedDeclaration, originalDeclaration: KtNamedDeclaration) {
require(originalDeclaration.containingKtFile !== targetDeclaration.containingKtFile)
val originalDeclarationParents = originalDeclaration.parentsOfType<KtDeclaration>().toList()
@@ -150,7 +145,7 @@ object LowLevelFirApiFacadeForResolveOnAir {
require(originalFirResolveSession is LLFirResolvableResolveSession)
require(elementToAnalyze !is KtFile) { "KtFile for dependency element not supported" }
val dependencyNonLocalDeclaration = findEnclosingNonLocalDeclaration(elementToAnalyze)
val dependencyNonLocalDeclaration = findNonLocalParentMaybeSelf(elementToAnalyze)
?: return LLFirResolveSessionDepended(
originalFirResolveSession,
FileTowerProvider(elementToAnalyze.containingKtFile, onAirGetTowerContextForFile(originalFirResolveSession, originalKtFile)),
@@ -216,7 +211,7 @@ object LowLevelFirApiFacadeForResolveOnAir {
onAirCreatedDeclaration: Boolean,
collector: FirTowerDataContextCollector? = null,
): FirElement {
val nonLocalDeclaration = findEnclosingNonLocalDeclaration(replacement.from)
val nonLocalDeclaration = findNonLocalParentMaybeSelf(replacement.from)
val originalFirFile = firResolveSession.getOrBuildFirFile(replacement.from.containingKtFile)
if (nonLocalDeclaration == null) {
@@ -0,0 +1,7 @@
enum class Foo {
VALUE {
/*PLACE*/fun run() = 1
}
}
/*ONAIR*/fun box(): Int = 0
@@ -0,0 +1,3 @@
public final [BODY_RESOLVE] fun box(): R|kotlin/Int| {
^box Int(0)
}
@@ -30,6 +30,12 @@ public class FirOnAirResolveTestGenerated extends AbstractFirOnAirResolveTest {
runTest("analysis/low-level-api-fir/testdata/onAirResolve/classInClass.kt");
}
@Test
@TestMetadata("enumValueMember.kt")
public void testEnumValueMember() throws Exception {
runTest("analysis/low-level-api-fir/testdata/onAirResolve/enumValueMember.kt");
}
@Test
@TestMetadata("fileAnnotation.kt")
public void testFileAnnotation() throws Exception {