[AA] Support enum entry initializers in member scope tests

- Now that the enum entry initializer provides a member scope, not the
  enum entry, we need a way to get to the enum entry initializer in
  tests. This can only be done via the enum entry's name, because the
  initializer is anonymous.

^KT-61425
This commit is contained in:
Marco Pennekamp
2023-08-24 21:56:56 +02:00
committed by Space Team
parent 80efa34926
commit 3add7f9db5
2 changed files with 38 additions and 18 deletions
@@ -7,6 +7,8 @@ package org.jetbrains.kotlin.analysis.api.impl.base.test
import com.intellij.openapi.util.io.FileUtil
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
import org.jetbrains.kotlin.analysis.api.symbols.KtClassKind
import org.jetbrains.kotlin.analysis.api.symbols.KtNamedClassOrObjectSymbol
import org.jetbrains.kotlin.name.CallableId
import org.jetbrains.kotlin.analysis.api.symbols.KtSymbol
import org.jetbrains.kotlin.name.ClassId
@@ -83,28 +85,46 @@ sealed class SymbolData {
}
}
data class EnumEntryInitializerData(val enumEntryId: CallableId) : SymbolData() {
override fun KtAnalysisSession.toSymbols(ktFile: KtFile): List<KtSymbol> {
val classSymbol = enumEntryId.classId?.let { getClassOrObjectSymbolByClassId(it) }
?: error("Cannot find enum class `${enumEntryId.classId}`.")
require(classSymbol is KtNamedClassOrObjectSymbol) { "`${enumEntryId.classId}` must be a named class." }
require(classSymbol.classKind == KtClassKind.ENUM_CLASS) { "`${enumEntryId.classId}` must be an enum class." }
val enumEntrySymbol = classSymbol.getEnumEntries().find { it.name == enumEntryId.callableName }
?: error("Cannot find enum entry symbol `$enumEntryId`.")
val initializerSymbol = enumEntrySymbol.enumEntryInitializer ?: error("`${enumEntryId.callableName}` must have an initializer.")
return listOf(initializerSymbol)
}
}
companion object {
val identifiers: List<String> = listOf("callable:", "class:", "typealias:", "script")
val identifiers = arrayOf("callable:", "class:", "typealias:", "enum_entry_initializer:", "script")
fun create(data: String): SymbolData = when {
data == "script" -> ScriptData
data.startsWith("class:") -> ClassData(ClassId.fromString(data.removePrefix("class:").trim()))
data.startsWith("typealias:") -> TypeAliasData(ClassId.fromString(data.removePrefix("typealias:").trim()))
data.startsWith("callable:") -> {
val fullName = data.removePrefix("callable:").trim()
val name = if ('.' in fullName) fullName.substringAfterLast(".") else fullName.substringAfterLast('/')
val (packageName, className) = run {
val packageNameWithClassName = fullName.dropLast(name.length + 1)
when {
'.' in fullName ->
packageNameWithClassName.substringBeforeLast('/') to packageNameWithClassName.substringAfterLast('/')
else -> packageNameWithClassName to null
}
}
CallableData(CallableId(FqName(packageName.replace('/', '.')), className?.let { FqName(it) }, Name.identifier(name)))
}
else -> error("Invalid symbol")
data.startsWith("callable:") -> CallableData(extractCallableId(data, "callable:"))
data.startsWith("enum_entry_initializer") -> EnumEntryInitializerData(extractCallableId(data, "enum_entry_initializer:"))
else -> error("Invalid symbol kind, expected one of: $identifiers")
}
}
}
private fun extractCallableId(data: String, prefix: String): CallableId {
val fullName = data.removePrefix(prefix).trim()
val name = if ('.' in fullName) fullName.substringAfterLast(".") else fullName.substringAfterLast('/')
val (packageName, className) = run {
val packageNameWithClassName = fullName.dropLast(name.length + 1)
when {
'.' in fullName ->
packageNameWithClassName.substringBeforeLast('/') to packageNameWithClassName.substringAfterLast('/')
else -> packageNameWithClassName to null
}
}
return CallableId(FqName(packageName.replace('/', '.')), className?.let { FqName(it) }, Name.identifier(name))
}
@@ -18,8 +18,8 @@ abstract class AbstractMemberScopeByFqNameTest : AbstractSymbolByFqNameTest() {
override fun KtAnalysisSession.collectSymbols(ktFile: KtFile, testServices: TestServices): SymbolsData {
val symbolData = SymbolByFqName.getSymbolDataFromFile(testDataPath)
val symbols = with(symbolData) { toSymbols(ktFile) }
val classSymbol = symbols.singleOrNull() as? KtSymbolWithMembers
?: error("Should be a single class symbol, but $symbols found")
return SymbolsData(classSymbol.getMemberScope().getAllSymbols().toList())
val symbolWithMembers = symbols.singleOrNull() as? KtSymbolWithMembers
?: error("Should be a single `${KtSymbolWithMembers::class.simpleName}`, but $symbols found.")
return SymbolsData(symbolWithMembers.getMemberScope().getAllSymbols().toList())
}
}