[ULC] Add constant evaluation to light classes service
This commit is contained in:
@@ -18,6 +18,8 @@ package org.jetbrains.kotlin.asJava
|
||||
|
||||
import com.intellij.openapi.components.ServiceManager
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiConstantEvaluationHelper
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiManager
|
||||
import com.intellij.psi.util.CachedValue
|
||||
import org.jetbrains.kotlin.asJava.builder.LightClassBuilderResult
|
||||
|
||||
@@ -9,12 +9,10 @@ import org.jetbrains.annotations.TestOnly
|
||||
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
|
||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator
|
||||
import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver
|
||||
import java.util.concurrent.ConcurrentMap
|
||||
|
||||
interface KtUltraLightSupport {
|
||||
val moduleName: String
|
||||
@@ -23,6 +21,7 @@ interface KtUltraLightSupport {
|
||||
val moduleDescriptor: ModuleDescriptor
|
||||
val isReleasedCoroutine: Boolean
|
||||
fun hasAlias(file: KtFile, shortName: Name?): Boolean = false
|
||||
fun getConstantEvaluator(expression: KtExpression): ConstantExpressionEvaluator
|
||||
|
||||
companion object {
|
||||
// This property may be removed once IntelliJ versions earlier than 2018.3 become unsupported
|
||||
@@ -52,4 +51,7 @@ class UltraLightSupportViaService(private val ktElement: KtElement) : KtUltraLig
|
||||
|
||||
override val isReleasedCoroutine: Boolean
|
||||
get() = serviceProvidedSupport.isReleasedCoroutine
|
||||
|
||||
override fun getConstantEvaluator(expression: KtExpression): ConstantExpressionEvaluator =
|
||||
serviceProvidedSupport.getConstantEvaluator(expression)
|
||||
}
|
||||
|
||||
+2
-2
@@ -13,6 +13,7 @@ import com.intellij.psi.impl.light.LightTypeElement
|
||||
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
|
||||
import org.jetbrains.kotlin.asJava.classes.cannotModify
|
||||
import org.jetbrains.kotlin.asJava.classes.lazyPub
|
||||
import org.jetbrains.kotlin.asJava.computeExpression
|
||||
import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap
|
||||
import org.jetbrains.kotlin.name.FqNameUnsafe
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
@@ -39,8 +40,7 @@ open class KtLightPsiLiteral(
|
||||
private val lightParent: PsiElement
|
||||
) : KtLightElementBase(lightParent), PsiLiteralExpression {
|
||||
|
||||
override fun getValue(): Any? =
|
||||
LanguageConstantExpressionEvaluator.INSTANCE.forLanguage(kotlinOrigin.language)?.computeConstantExpression(this, false)
|
||||
override fun getValue(): Any? = computeExpression(this)
|
||||
|
||||
override fun getType(): PsiType? {
|
||||
val bindingContext = LightClassGenerationSupport.getInstance(this.project).analyze(kotlinOrigin)
|
||||
|
||||
@@ -21,6 +21,7 @@ import com.intellij.psi.search.GlobalSearchScope
|
||||
import org.jetbrains.kotlin.asJava.classes.KtLightClass
|
||||
import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade
|
||||
import org.jetbrains.kotlin.asJava.classes.KtUltraLightElementWithNullabilityAnnotation
|
||||
import org.jetbrains.kotlin.asJava.classes.runReadAction
|
||||
import org.jetbrains.kotlin.asJava.elements.PsiElementWithOrigin
|
||||
import org.jetbrains.kotlin.asJava.elements.*
|
||||
import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap
|
||||
@@ -32,6 +33,10 @@ import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.*
|
||||
import org.jetbrains.kotlin.resolve.DelegatingBindingTrace
|
||||
import org.jetbrains.kotlin.resolve.constants.ArrayValue
|
||||
import org.jetbrains.kotlin.resolve.constants.ConstantValue
|
||||
import org.jetbrains.kotlin.types.TypeUtils
|
||||
|
||||
/**
|
||||
* Can be null in scripts and for elements from non-jvm modules.
|
||||
@@ -248,4 +253,31 @@ fun fastCheckIsNullabilityApplied(lightElement: KtLightElement<*, PsiModifierLis
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
fun computeExpression(expression: PsiElement): Any? {
|
||||
fun evalConstantValue(constantValue: ConstantValue<*>): Any? {
|
||||
return if (constantValue is ArrayValue) {
|
||||
val items = constantValue.value.map { evalConstantValue(it) }
|
||||
items.singleOrNull() ?: items
|
||||
} else constantValue.value
|
||||
}
|
||||
|
||||
val expressionToCompute = when (expression) {
|
||||
is KtLightElementBase -> expression.kotlinOrigin as? KtExpression ?: return null
|
||||
else -> return null
|
||||
}
|
||||
|
||||
val generationSupport = LightClassGenerationSupport.getInstance(expressionToCompute.project)
|
||||
val evaluator = generationSupport
|
||||
.getUltraLightClassSupport(expressionToCompute)
|
||||
.getConstantEvaluator(expressionToCompute)
|
||||
|
||||
val constant = runReadAction {
|
||||
val evaluatorTrace = DelegatingBindingTrace(generationSupport.analyze(expressionToCompute), "Evaluating annotation argument")
|
||||
evaluator.evaluateExpression(expressionToCompute, evaluatorTrace)
|
||||
} ?: return null
|
||||
|
||||
if (constant.isError) return null
|
||||
return evalConstantValue(constant.toConstantValue(TypeUtils.NO_EXPECTED_TYPE))
|
||||
}
|
||||
Reference in New Issue
Block a user