FIR Java: support read of field constant initializers

This commit is contained in:
Mikhail Glukhikh
2020-09-29 12:31:24 +03:00
parent fafb4a7914
commit 44ebec05bb
10 changed files with 34 additions and 20 deletions
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.builder.*
import org.jetbrains.kotlin.fir.declarations.impl.FirResolvedDeclarationStatusImpl
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.builder.*
import org.jetbrains.kotlin.fir.java.declarations.*
import org.jetbrains.kotlin.fir.resolve.constructType
@@ -309,10 +310,16 @@ class JavaSymbolProvider(
isVar = !javaField.isFinal
isStatic = javaField.isStatic
addAnnotationsFrom(this@JavaSymbolProvider.session, javaField, javaTypeParameterStack)
initializer = convertJavaInitializerToFir(javaField.initializerValue)
}
}
}
private fun convertJavaInitializerToFir(value: Any?): FirExpression? {
// NB: null should be converted to null
return value?.createConstantIfAny(session)
}
private fun convertJavaMethodToFir(
javaMethod: JavaMethod,
classId: ClassId,
@@ -451,7 +451,7 @@ private fun JavaAnnotationArgument.toFirExpression(
// TODO: this.name
return when (this) {
is JavaLiteralAnnotationArgument -> {
value.createConstant(session)
value.createConstantOrError(session)
}
is JavaArrayAnnotationArgument -> buildArrayOfCall {
argumentList = buildArgumentList {
@@ -503,13 +503,19 @@ private fun <T> List<T>.createArrayOfCall(session: FirSession, @Suppress("UNUSED
return buildArrayOfCall {
argumentList = buildArgumentList {
for (element in this@createArrayOfCall) {
arguments += element.createConstant(session)
arguments += element.createConstantOrError(session)
}
}
}
}
internal fun Any?.createConstant(session: FirSession): FirExpression {
internal fun Any?.createConstantOrError(session: FirSession): FirExpression {
return createConstantIfAny(session) ?: buildErrorExpression {
diagnostic = ConeSimpleDiagnostic("Unknown value in JavaLiteralAnnotationArgument: $this", DiagnosticKind.Java)
}
}
internal fun Any?.createConstantIfAny(session: FirSession): FirExpression? {
return when (this) {
is Byte -> buildConstExpression(null, FirConstKind.Byte, this)
is Short -> buildConstExpression(null, FirConstKind.Short, this)
@@ -530,9 +536,7 @@ internal fun Any?.createConstant(session: FirSession): FirExpression {
is BooleanArray -> toList().createArrayOfCall(session, FirConstKind.Boolean)
null -> buildConstExpression(null, FirConstKind.Null, null)
else -> buildErrorExpression {
diagnostic = ConeSimpleDiagnostic("Unknown value in JavaLiteralAnnotationArgument: $this", DiagnosticKind.Java)
}
else -> null
}
}
@@ -41,6 +41,7 @@ class FirJavaField @FirImplementationDetail constructor(
override val isVar: Boolean,
override val annotations: MutableList<FirAnnotationCall>,
override val typeParameters: MutableList<FirTypeParameter>,
override var initializer: FirExpression?,
) : FirField() {
init {
symbol.bind(this)
@@ -71,6 +72,7 @@ class FirJavaField @FirImplementationDetail constructor(
override fun <D> transformOtherChildren(transformer: FirTransformer<D>, data: D): FirField {
transformAnnotations(transformer, data)
initializer = initializer?.transformSingle(transformer, data)
return this
}
@@ -86,6 +88,7 @@ class FirJavaField @FirImplementationDetail constructor(
returnTypeRef.accept(visitor, data)
annotations.forEach { it.accept(visitor, data) }
typeParameters.forEach { it.accept(visitor, data) }
initializer?.accept(visitor, data)
}
override fun <D> transformChildren(transformer: FirTransformer<D>, data: D): FirJavaField {
@@ -117,9 +120,6 @@ class FirJavaField @FirImplementationDetail constructor(
override val delegate: FirExpression?
get() = null
override val initializer: FirExpression?
get() = null
override val delegateFieldSymbol: FirDelegateFieldSymbol<FirField>?
get() = null
@@ -141,6 +141,7 @@ internal class FirJavaFieldBuilder : FirFieldBuilder() {
var modality: Modality? = null
lateinit var visibility: Visibility
var isStatic: Boolean by Delegates.notNull()
var initializer: FirExpression? = null
override var resolvePhase: FirResolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES
@@ -157,6 +158,7 @@ internal class FirJavaFieldBuilder : FirFieldBuilder() {
isVar,
annotations,
typeParameters,
initializer,
)
}
@@ -21,7 +21,7 @@ import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.builder.*
import org.jetbrains.kotlin.fir.java.JavaSymbolProvider
import org.jetbrains.kotlin.fir.java.createConstant
import org.jetbrains.kotlin.fir.java.createConstantOrError
import org.jetbrains.kotlin.fir.java.topLevelName
import org.jetbrains.kotlin.fir.references.builder.buildErrorNamedReference
import org.jetbrains.kotlin.fir.references.builder.buildResolvedNamedReference
@@ -288,7 +288,7 @@ class KotlinDeserializedJvmSymbolsProvider(
}
private fun createConstant(value: Any?): FirExpression {
return value.createConstant(session)
return value.createConstantOrError(session)
}
}
}
@@ -102,6 +102,7 @@ class FirSignatureEnhancement(
isStatic = firElement.isStatic
annotations += firElement.annotations
status = firElement.status
initializer = firElement.initializer
}
return symbol
}
@@ -1,7 +1,7 @@
public final class ClassWithConstVal : R|kotlin/Any| {
public final field f: R|kotlin/Int|
public final field f: R|kotlin/Int| = Int(1)
public final field f2: R|kotlin/Int|
public final field f2: R|kotlin/Int| = Int(1)
public constructor(): R|test/ClassWithConstVal|
@@ -1,5 +1,5 @@
public final class FinalFieldAsVal : R|kotlin/Any| {
public final field f: R|kotlin/Int|
public final field f: R|kotlin/Int| = Int(1)
public constructor(): R|test/FinalFieldAsVal|
@@ -1,7 +1,7 @@
public open class AnnotatedField : R|kotlin/Any| {
@R|test/AnnotatedField.Anno|(String(static)) public final static field x: R|kotlin/Int|
@R|test/AnnotatedField.Anno|(String(static)) public final static field x: R|kotlin/Int| = Int(0)
@R|test/AnnotatedField.Anno|(String(member)) public final field y: R|kotlin/Int|
@R|test/AnnotatedField.Anno|(String(member)) public final field y: R|kotlin/Int| = Int(0)
public constructor(): R|test/AnnotatedField|
@@ -1,4 +1,4 @@
public abstract interface StringConstantInParam : R|kotlin/Any| {
public final static field HEL: R|ft<kotlin/String, kotlin/String?>!|
public final static field HEL: R|ft<kotlin/String, kotlin/String?>!| = String(hel)
}
@@ -1,13 +1,13 @@
public open class StaticFinal : R|kotlin/Any| {
public final static field publicNonNull: R|ft<kotlin/String, kotlin/String?>!|
public final static field publicNonNull: R|ft<kotlin/String, kotlin/String?>!| = String(aaa)
public final static field publicNull: R|ft<kotlin/String, kotlin/String?>!|
public/*package*/ final static field packageNonNull: R|ft<kotlin/String, kotlin/String?>!|
public/*package*/ final static field packageNonNull: R|ft<kotlin/String, kotlin/String?>!| = String(bbb)
public/*package*/ final static field packageNull: R|ft<kotlin/String, kotlin/String?>!|
private final static field privateNonNull: R|ft<kotlin/String, kotlin/String?>!|
private final static field privateNonNull: R|ft<kotlin/String, kotlin/String?>!| = String(bbb)
private final static field privateNull: R|ft<kotlin/String, kotlin/String?>!|