Add UL support for const fields initializers
Fixed #KT-34081
This commit is contained in:
+4
-28
@@ -10,16 +10,17 @@ import com.intellij.psi.*
|
||||
import com.intellij.psi.impl.PsiImplUtil
|
||||
import com.intellij.psi.impl.light.LightIdentifier
|
||||
import com.intellij.psi.meta.PsiMetaData
|
||||
import com.intellij.psi.util.TypeConversionUtil
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightAbstractAnnotation
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightElementBase
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightNullabilityAnnotation
|
||||
import org.jetbrains.kotlin.asJava.elements.psiType
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||
import org.jetbrains.kotlin.psi.KtCallElement
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.resolve.constants.*
|
||||
import org.jetbrains.kotlin.resolve.constants.AnnotationValue
|
||||
import org.jetbrains.kotlin.resolve.constants.ArrayValue
|
||||
import org.jetbrains.kotlin.resolve.constants.ConstantValue
|
||||
import org.jetbrains.kotlin.resolve.constants.ErrorValue
|
||||
|
||||
class KtUltraLightNullabilityAnnotation(
|
||||
member: KtUltraLightElementWithNullabilityAnnotation<*, *>,
|
||||
@@ -120,31 +121,6 @@ private fun ConstantValue<*>.toAnnotationMemberValue(
|
||||
else -> createPsiLiteral(parent)
|
||||
}
|
||||
|
||||
private fun ConstantValue<*>.createPsiLiteral(parent: PsiElement): PsiExpression? {
|
||||
val asString = asStringForPsiLiteral(parent)
|
||||
val instance = PsiElementFactory.SERVICE.getInstance(parent.project)
|
||||
return instance.createExpressionFromText(asString, parent)
|
||||
}
|
||||
|
||||
private fun ConstantValue<*>.asStringForPsiLiteral(parent: PsiElement): String =
|
||||
when (this) {
|
||||
is NullValue -> "null"
|
||||
is StringValue -> "\"$value\""
|
||||
is KClassValue -> {
|
||||
val value = (value as KClassValue.Value.NormalClass).value
|
||||
val arrayPart = "[]".repeat(value.arrayNestedness)
|
||||
val fqName = value.classId.asSingleFqName()
|
||||
val canonicalText = psiType(
|
||||
fqName.asString(), parent, boxPrimitiveType = value.arrayNestedness > 0
|
||||
).let(TypeConversionUtil::erasure).getCanonicalText(false)
|
||||
|
||||
"$canonicalText$arrayPart.class"
|
||||
}
|
||||
is EnumValue -> "${enumClassId.asSingleFqName().asString()}.$enumEntryName"
|
||||
else -> value.toString()
|
||||
}
|
||||
|
||||
|
||||
private class KtUltraLightPsiArrayInitializerMemberValue(
|
||||
val lightParent: PsiElement,
|
||||
private val arguments: (KtUltraLightPsiArrayInitializerMemberValue) -> List<PsiAnnotationMemberValue>
|
||||
|
||||
@@ -135,12 +135,22 @@ internal open class KtUltraLightFieldImpl protected constructor(
|
||||
override fun getContainingClass() = containingClass
|
||||
override fun getContainingFile(): PsiFile? = containingClass.containingFile
|
||||
|
||||
override fun computeConstantValue(): Any? =
|
||||
if (hasModifierProperty(PsiModifier.FINAL) &&
|
||||
(TypeConversionUtil.isPrimitiveAndNotNull(_type) || _type.equalsToText(CommonClassNames.JAVA_LANG_STRING))
|
||||
)
|
||||
(declaration.resolve() as? VariableDescriptor)?.compileTimeInitializer?.value
|
||||
else null
|
||||
private val _initializer by lazyPub {
|
||||
_constantInitializer?.createPsiLiteral(declaration)
|
||||
}
|
||||
|
||||
override fun getInitializer(): PsiExpression? = _initializer
|
||||
|
||||
override fun hasInitializer(): Boolean = initializer !== null
|
||||
|
||||
private val _constantInitializer by lazyPub {
|
||||
if ((declaration as? KtProperty)?.hasInitializer() != true) return@lazyPub null
|
||||
if (!hasModifierProperty(PsiModifier.FINAL)) return@lazyPub null
|
||||
if (!TypeConversionUtil.isPrimitiveAndNotNull(_type) && !_type.equalsToText(CommonClassNames.JAVA_LANG_STRING)) return@lazyPub null
|
||||
propertyDescriptor?.compileTimeInitializer
|
||||
}
|
||||
|
||||
override fun computeConstantValue(): Any? = _constantInitializer?.value
|
||||
|
||||
override fun computeConstantValue(visitedVars: MutableSet<PsiVariable>?): Any? = computeConstantValue()
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ import com.intellij.psi.impl.compiled.ClsTypeElementImpl
|
||||
import com.intellij.psi.impl.compiled.SignatureParsing
|
||||
import com.intellij.psi.impl.compiled.StubBuildingVisitor
|
||||
import com.intellij.psi.impl.light.*
|
||||
import com.intellij.psi.util.TypeConversionUtil
|
||||
import com.intellij.util.BitUtil.isSet
|
||||
import com.intellij.util.containers.ContainerUtil
|
||||
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
|
||||
@@ -23,6 +24,7 @@ import org.jetbrains.kotlin.asJava.UltraLightClassModifierExtension
|
||||
import org.jetbrains.kotlin.asJava.builder.LightMemberOriginForDeclaration
|
||||
import org.jetbrains.kotlin.asJava.elements.KotlinLightTypeParameterListBuilder
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
|
||||
import org.jetbrains.kotlin.asJava.elements.psiType
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap
|
||||
import org.jetbrains.kotlin.codegen.AsmUtil
|
||||
@@ -41,7 +43,7 @@ import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.annotations.JVM_STATIC_ANNOTATION_FQ_NAME
|
||||
import org.jetbrains.kotlin.resolve.annotations.argumentValue
|
||||
import org.jetbrains.kotlin.resolve.constants.EnumValue
|
||||
import org.jetbrains.kotlin.resolve.constants.*
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKind
|
||||
@@ -355,6 +357,35 @@ private fun toQualifiedName(userType: KtUserType): FqName? {
|
||||
return FqName.fromSegments(ContainerUtil.reverse(reversedNames))
|
||||
}
|
||||
|
||||
internal fun ConstantValue<*>.createPsiLiteral(parent: PsiElement): PsiExpression? {
|
||||
val asString = asStringForPsiLiteral(parent)
|
||||
val instance = PsiElementFactory.SERVICE.getInstance(parent.project)
|
||||
return instance.createExpressionFromText(asString, parent)
|
||||
}
|
||||
|
||||
private fun ConstantValue<*>.asStringForPsiLiteral(parent: PsiElement): String =
|
||||
when (this) {
|
||||
is NullValue -> "null"
|
||||
is StringValue -> "\"$value\""
|
||||
is KClassValue -> {
|
||||
val value = (value as KClassValue.Value.NormalClass).value
|
||||
val arrayPart = "[]".repeat(value.arrayNestedness)
|
||||
val fqName = value.classId.asSingleFqName()
|
||||
val canonicalText = psiType(
|
||||
fqName.asString(), parent, boxPrimitiveType = value.arrayNestedness > 0
|
||||
).let(TypeConversionUtil::erasure).getCanonicalText(false)
|
||||
|
||||
"$canonicalText$arrayPart.class"
|
||||
}
|
||||
is EnumValue -> "${enumClassId.asSingleFqName().asString()}.$enumEntryName"
|
||||
else -> when (value) {
|
||||
is Long -> "${value}L"
|
||||
is Float -> "${value}f"
|
||||
else -> value.toString()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***
|
||||
* @see org.jetbrains.kotlin.codegen.ImplementationBodyCodegen
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user