FIR LC: add support for inline class

This commit is contained in:
Jinseong Jeon
2021-10-27 18:13:15 -07:00
committed by Ilya Kirillov
parent 0e7d1b3945
commit 5880d80d26
5 changed files with 81 additions and 4 deletions
@@ -28,7 +28,7 @@ import org.jetbrains.kotlin.util.OperatorNameConventions.EQUALS
import org.jetbrains.kotlin.util.OperatorNameConventions.TO_STRING
import org.jetbrains.kotlin.utils.addToStdlib.applyIf
internal class FirLightClassForSymbol(
internal open class FirLightClassForSymbol(
private val classOrObjectSymbol: KtNamedClassOrObjectSymbol,
manager: PsiManager
) : FirLightClassForClassOrObjectSymbol(classOrObjectSymbol, manager) {
@@ -0,0 +1,67 @@
/*
* 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.light.classes.symbol
import com.intellij.psi.PsiManager
import com.intellij.psi.PsiMethod
import org.jetbrains.kotlin.analysis.api.symbols.KtFunctionSymbol
import org.jetbrains.kotlin.analysis.api.symbols.KtNamedClassOrObjectSymbol
import org.jetbrains.kotlin.analysis.api.symbols.KtPropertySymbol
import org.jetbrains.kotlin.asJava.classes.lazyPub
import org.jetbrains.kotlin.asJava.elements.KtLightField
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
import org.jetbrains.kotlin.light.classes.symbol.classes.createMethods
import org.jetbrains.kotlin.light.classes.symbol.classes.createPropertyAccessors
import org.jetbrains.kotlin.resolve.deprecation.DeprecationLevelValue
internal class FirLightInlineClass(
private val classOrObjectSymbol: KtNamedClassOrObjectSymbol,
manager: PsiManager
) : FirLightClassForSymbol(classOrObjectSymbol, manager) {
init {
require(classOrObjectSymbol.isInline)
}
private val _ownMethods: List<KtLightMethod> by lazyPub {
val result = mutableListOf<KtLightMethod>()
analyzeWithSymbolAsContext(classOrObjectSymbol) {
val declaredMemberScope = classOrObjectSymbol.getDeclaredMemberScope()
val applicableDeclarations = declaredMemberScope.getCallableSymbols()
.filter {
(it as? KtPropertySymbol)?.isOverride == true || (it as? KtFunctionSymbol)?.isOverride == true
}
.filterNot {
it.deprecationStatus?.deprecationLevel == DeprecationLevelValue.HIDDEN
}
createMethods(applicableDeclarations, result, suppressStaticForMethods = false)
val inlineClassParameterSymbol =
declaredMemberScope.getConstructors().singleOrNull { it.isPrimary }?.valueParameters?.singleOrNull()
if (inlineClassParameterSymbol != null) {
val propertySymbol = declaredMemberScope.getCallableSymbols { it == inlineClassParameterSymbol.name }
.singleOrNull { it is KtPropertySymbol && it.isFromPrimaryConstructor } as? KtPropertySymbol
if (propertySymbol != null) {
// (inline or) value class primary constructor must have only final read-only (val) property parameter
// Even though the property parameter is mutable (for some reasons, e.g., testing or not checked yet),
// we can enforce immutability here.
createPropertyAccessors(result, propertySymbol, isTopLevel = false, isMutable = false)
}
}
}
result
}
override fun getOwnMethods(): List<PsiMethod> = _ownMethods
override fun getOwnFields(): List<KtLightField> = emptyList()
override fun copy(): FirLightInlineClass =
FirLightInlineClass(classOrObjectSymbol, manager)
}
@@ -70,7 +70,11 @@ fun createFirLightClassNoCache(classOrObject: KtClassOrObject): KtLightClass? =
return when {
classOrObject is KtEnumEntry -> lightClassForEnumEntry(classOrObject)
classOrObject.hasModifier(KtTokens.INLINE_KEYWORD) -> return null //TODO
classOrObject.hasModifier(KtTokens.INLINE_KEYWORD) -> {
analyseForLightClasses(classOrObject) {
classOrObject.getNamedClassOrObjectSymbol()?.let { FirLightInlineClass(it, classOrObject.manager) }
}
}
else -> {
analyseForLightClasses(classOrObject) {
classOrObject.getClassOrObjectSymbol().createLightClassNoCache(classOrObject.manager)
@@ -210,6 +214,7 @@ internal fun FirLightClassBase.createPropertyAccessors(
result: MutableList<KtLightMethod>,
declaration: KtPropertySymbol,
isTopLevel: Boolean,
isMutable: Boolean = !declaration.isVal,
) {
if (declaration is KtKotlinPropertySymbol && declaration.isConst) return
@@ -258,7 +263,7 @@ internal fun FirLightClassBase.createPropertyAccessors(
!isAnnotationType && it.needToCreateAccessor(AnnotationUseSiteTarget.PROPERTY_SETTER)
}
if (setter != null) {
if (isMutable && setter != null) {
val lightMemberOrigin = originalElement?.let {
LightMemberOriginForDeclaration(
originalElement = it,
@@ -57,6 +57,9 @@ class KtUltraLightInlineClass(
if (inlineClassParameter != null) {
membersBuilder.propertyAccessors(
inlineClassParameter,
// (inline or) value class primary constructor must have only final read-only (val) property parameter
// Even though the property parameter is mutable (for some reasons, e.g., testing or not checked yet),
// we can enforce immutability here.
mutable = false,
forceStatic = false,
onlyJvmStatic = false
@@ -26,4 +26,6 @@ inline class InlineInheritance(val v: Int) : I {
override val x get() = 5
fun z() = 7
}
}
// FIR_COMPARISON