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.PsiImplUtil
|
||||||
import com.intellij.psi.impl.light.LightIdentifier
|
import com.intellij.psi.impl.light.LightIdentifier
|
||||||
import com.intellij.psi.meta.PsiMetaData
|
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.KtLightAbstractAnnotation
|
||||||
import org.jetbrains.kotlin.asJava.elements.KtLightElementBase
|
import org.jetbrains.kotlin.asJava.elements.KtLightElementBase
|
||||||
import org.jetbrains.kotlin.asJava.elements.KtLightNullabilityAnnotation
|
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.DeclarationDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||||
import org.jetbrains.kotlin.psi.KtCallElement
|
import org.jetbrains.kotlin.psi.KtCallElement
|
||||||
import org.jetbrains.kotlin.psi.KtElement
|
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(
|
class KtUltraLightNullabilityAnnotation(
|
||||||
member: KtUltraLightElementWithNullabilityAnnotation<*, *>,
|
member: KtUltraLightElementWithNullabilityAnnotation<*, *>,
|
||||||
@@ -120,31 +121,6 @@ private fun ConstantValue<*>.toAnnotationMemberValue(
|
|||||||
else -> createPsiLiteral(parent)
|
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(
|
private class KtUltraLightPsiArrayInitializerMemberValue(
|
||||||
val lightParent: PsiElement,
|
val lightParent: PsiElement,
|
||||||
private val arguments: (KtUltraLightPsiArrayInitializerMemberValue) -> List<PsiAnnotationMemberValue>
|
private val arguments: (KtUltraLightPsiArrayInitializerMemberValue) -> List<PsiAnnotationMemberValue>
|
||||||
|
|||||||
@@ -135,12 +135,22 @@ internal open class KtUltraLightFieldImpl protected constructor(
|
|||||||
override fun getContainingClass() = containingClass
|
override fun getContainingClass() = containingClass
|
||||||
override fun getContainingFile(): PsiFile? = containingClass.containingFile
|
override fun getContainingFile(): PsiFile? = containingClass.containingFile
|
||||||
|
|
||||||
override fun computeConstantValue(): Any? =
|
private val _initializer by lazyPub {
|
||||||
if (hasModifierProperty(PsiModifier.FINAL) &&
|
_constantInitializer?.createPsiLiteral(declaration)
|
||||||
(TypeConversionUtil.isPrimitiveAndNotNull(_type) || _type.equalsToText(CommonClassNames.JAVA_LANG_STRING))
|
}
|
||||||
)
|
|
||||||
(declaration.resolve() as? VariableDescriptor)?.compileTimeInitializer?.value
|
override fun getInitializer(): PsiExpression? = _initializer
|
||||||
else null
|
|
||||||
|
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()
|
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.SignatureParsing
|
||||||
import com.intellij.psi.impl.compiled.StubBuildingVisitor
|
import com.intellij.psi.impl.compiled.StubBuildingVisitor
|
||||||
import com.intellij.psi.impl.light.*
|
import com.intellij.psi.impl.light.*
|
||||||
|
import com.intellij.psi.util.TypeConversionUtil
|
||||||
import com.intellij.util.BitUtil.isSet
|
import com.intellij.util.BitUtil.isSet
|
||||||
import com.intellij.util.containers.ContainerUtil
|
import com.intellij.util.containers.ContainerUtil
|
||||||
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
|
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.builder.LightMemberOriginForDeclaration
|
||||||
import org.jetbrains.kotlin.asJava.elements.KotlinLightTypeParameterListBuilder
|
import org.jetbrains.kotlin.asJava.elements.KotlinLightTypeParameterListBuilder
|
||||||
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
|
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.KotlinBuiltIns
|
||||||
import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap
|
import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap
|
||||||
import org.jetbrains.kotlin.codegen.AsmUtil
|
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.DescriptorUtils
|
||||||
import org.jetbrains.kotlin.resolve.annotations.JVM_STATIC_ANNOTATION_FQ_NAME
|
import org.jetbrains.kotlin.resolve.annotations.JVM_STATIC_ANNOTATION_FQ_NAME
|
||||||
import org.jetbrains.kotlin.resolve.annotations.argumentValue
|
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.classId
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKind
|
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKind
|
||||||
@@ -355,6 +357,35 @@ private fun toQualifiedName(userType: KtUserType): FqName? {
|
|||||||
return FqName.fromSegments(ContainerUtil.reverse(reversedNames))
|
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
|
* @see org.jetbrains.kotlin.codegen.ImplementationBodyCodegen
|
||||||
*/
|
*/
|
||||||
|
|||||||
+2
-2
@@ -45,7 +45,7 @@ final class null /* null*/ {
|
|||||||
@null()
|
@null()
|
||||||
public static final java.lang.Object INSTANCE;
|
public static final java.lang.Object INSTANCE;
|
||||||
|
|
||||||
private static final java.lang.String fy /* constant value text */;
|
private static final java.lang.String fy = "text" /* initializer type: java.lang.String */ /* constant value text */;
|
||||||
|
|
||||||
@org.jetbrains.annotations.NotNull()
|
@org.jetbrains.annotations.NotNull()
|
||||||
public final java.lang.String getFy();
|
public final java.lang.String getFy();
|
||||||
@@ -104,7 +104,7 @@ final class null /* null*/ {
|
|||||||
@null()
|
@null()
|
||||||
public static final java.lang.Object INSTANCE;
|
public static final java.lang.Object INSTANCE;
|
||||||
|
|
||||||
private static final java.lang.String fy /* constant value text */;
|
private static final java.lang.String fy = "text" /* initializer type: java.lang.String */ /* constant value text */;
|
||||||
|
|
||||||
@org.jetbrains.annotations.NotNull()
|
@org.jetbrains.annotations.NotNull()
|
||||||
public final java.lang.String getFy();
|
public final java.lang.String getFy();
|
||||||
|
|||||||
@@ -29,3 +29,25 @@ object Obj : java.lang.Runnable {
|
|||||||
override fun run() {}
|
override fun run() {}
|
||||||
@JvmStatic fun zoo(): Int = 2
|
@JvmStatic fun zoo(): Int = 2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
object ConstContainer {
|
||||||
|
const val str = "one" // String
|
||||||
|
const val one = 1 // Int
|
||||||
|
const val oneLong = 1L // Long
|
||||||
|
const val complexLong = 1L + 1 // Long
|
||||||
|
const val e = 2.7182818284 // Double
|
||||||
|
const val eFloat = 2.7182818284f // Float
|
||||||
|
const val complexFloat = 2.7182818284f + 2.4 // Float
|
||||||
|
}
|
||||||
|
|
||||||
|
class ClassWithConstContainer {
|
||||||
|
companion object {
|
||||||
|
const val str = "one" // String
|
||||||
|
const val one = 1 // Int
|
||||||
|
const val oneLong = 1L // Long
|
||||||
|
const val complexLong = 1L + 1 // Long
|
||||||
|
const val e = 2.7182818284 // Double
|
||||||
|
const val eFloat = 2.7182818284f // Float
|
||||||
|
const val complexFloat = 2.7182818284f + 2.4 // Float
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -170,7 +170,13 @@ object UltraLightChecker {
|
|||||||
if (this is PsiParameter && this.isVarArgs) {
|
if (this is PsiParameter && this.isVarArgs) {
|
||||||
result += " /* vararg */"
|
result += " /* vararg */"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (hasInitializer()) {
|
||||||
|
result += " = ${initializer?.text} /* initializer type: ${initializer?.type?.renderType()} */"
|
||||||
|
}
|
||||||
|
|
||||||
computeConstantValue()?.let { result += " /* constant value $it */" }
|
computeConstantValue()?.let { result += " /* constant value $it */" }
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user