From 886ef1a4b460de3ceef9aa08f82dd7674eb8d8ac Mon Sep 17 00:00:00 2001 From: Ivan Kylchik Date: Mon, 4 Sep 2023 16:18:27 +0200 Subject: [PATCH] [FIR] Support the simple case of java field interpretation #KT-57802 --- .../kotlin/fir/backend/Fir2IrConverter.kt | 36 ++++++++++++++--- ...LightTreeBlackBoxCodegenTestGenerated.java | 6 +++ ...hIrFakeOverrideGeneratorTestGenerated.java | 6 +++ .../FirPsiBlackBoxCodegenTestGenerated.java | 6 +++ .../kotlin/fir/java/FirJavaElementFinder.kt | 18 +++++++++ .../transformer/IrConstTransformer.kt | 20 +++++++++- .../box/involvesIrInterpreter/kt57802.kt | 39 +++++++++++++++++++ .../codegen/BlackBoxCodegenTestGenerated.java | 6 +++ .../IrBlackBoxCodegenTestGenerated.java | 6 +++ ...kBoxCodegenWithIrInlinerTestGenerated.java | 6 +++ .../LightAnalysisModeTestGenerated.java | 5 +++ 11 files changed, 148 insertions(+), 6 deletions(-) create mode 100644 compiler/testData/codegen/box/involvesIrInterpreter/kt57802.kt diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrConverter.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrConverter.kt index 2f871db8b2e..f191ca16e5f 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrConverter.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrConverter.kt @@ -14,7 +14,6 @@ import org.jetbrains.kotlin.backend.common.actualizer.FakeOverrideRebuilder import org.jetbrains.kotlin.backend.common.sourceElement import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.config.LanguageFeature -import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.DescriptorVisibilities import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.fir.* @@ -31,28 +30,32 @@ import org.jetbrains.kotlin.fir.extensions.declarationGenerators import org.jetbrains.kotlin.fir.extensions.extensionService import org.jetbrains.kotlin.fir.extensions.generatedMembers import org.jetbrains.kotlin.fir.extensions.generatedNestedClassifiers +import org.jetbrains.kotlin.fir.java.javaElementFinder import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.symbols.lazyDeclarationResolver import org.jetbrains.kotlin.fir.types.resolvedType -import org.jetbrains.kotlin.ir.PsiIrFileEntry import org.jetbrains.kotlin.ir.IrBuiltIns +import org.jetbrains.kotlin.ir.PsiIrFileEntry import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.impl.IrFileImpl import org.jetbrains.kotlin.ir.declarations.impl.IrModuleFragmentImpl +import org.jetbrains.kotlin.ir.expressions.IrConst import org.jetbrains.kotlin.ir.expressions.impl.IrDelegatingConstructorCallImpl import org.jetbrains.kotlin.ir.interpreter.IrInterpreter import org.jetbrains.kotlin.ir.interpreter.IrInterpreterConfiguration import org.jetbrains.kotlin.ir.interpreter.IrInterpreterEnvironment import org.jetbrains.kotlin.ir.interpreter.checker.EvaluationMode +import org.jetbrains.kotlin.ir.interpreter.transformer.evaluate import org.jetbrains.kotlin.ir.interpreter.transformer.transformConst import org.jetbrains.kotlin.ir.overrides.IrFakeOverrideBuilder -import org.jetbrains.kotlin.ir.types.IrTypeSystemContext import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorPublicSymbolImpl import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionPublicSymbolImpl +import org.jetbrains.kotlin.ir.types.IrTypeSystemContext import org.jetbrains.kotlin.ir.util.KotlinMangler import org.jetbrains.kotlin.ir.util.NaiveSourceBasedFileEntryImpl import org.jetbrains.kotlin.ir.util.defaultType +import org.jetbrains.kotlin.ir.util.fileOrNull import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.KtFile @@ -107,7 +110,7 @@ class Fir2IrConverter( } } - evaluateConstants(irModuleFragment, configuration) + evaluateConstants(irModuleFragment, components) } fun bindFakeOverridesOrPostpone(declarations: List) { @@ -528,7 +531,8 @@ class Fir2IrConverter( } companion object { - private fun evaluateConstants(irModuleFragment: IrModuleFragment, fir2IrConfiguration: Fir2IrConfiguration) { + private fun evaluateConstants(irModuleFragment: IrModuleFragment, components: Fir2IrComponents) { + val fir2IrConfiguration = components.configuration val firModuleDescriptor = irModuleFragment.descriptor as? FirModuleDescriptor val targetPlatform = firModuleDescriptor?.platform val languageVersionSettings = firModuleDescriptor?.session?.languageVersionSettings ?: return @@ -538,8 +542,30 @@ class Fir2IrConverter( platform = targetPlatform, printOnlyExceptionMessage = true, ) + val interpreter = IrInterpreter(IrInterpreterEnvironment(irModuleFragment.irBuiltins, configuration)) val mode = if (intrinsicConstEvaluation) EvaluationMode.ONLY_INTRINSIC_CONST else EvaluationMode.ONLY_BUILTINS + + components.session.javaElementFinder?.propertyEvaluator = eval@{ firProperty -> + val irProperty = components.declarationStorage.getCachedIrProperty(firProperty, fakeOverrideOwnerLookupTag = null) ?: return@eval null + + fun IrProperty.tryToGetConst(): IrConst<*>? { + return (backingField?.initializer?.expression as? IrConst<*>) + } + + irProperty.tryToGetConst()?.let { return@eval it.value.toString() } + val irFile = irProperty.fileOrNull ?: return@eval null + // Note: can't evaluate all expressions in given file, because we can accidentally get recursive processing and + // second call of `Fir2IrLazyField.initializer` will return null + val evaluated = irProperty.evaluate( + irFile, interpreter, mode, + evaluatedConstTracker = fir2IrConfiguration.evaluatedConstTracker, + inlineConstTracker = fir2IrConfiguration.inlineConstTracker, + ) + + return@eval evaluated?.tryToGetConst()?.value?.toString() + } + val ktDiagnosticReporter = KtDiagnosticReporterWithImplicitIrBasedContext(fir2IrConfiguration.diagnosticReporter, languageVersionSettings) irModuleFragment.files.forEach { it.transformConst( diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirLightTreeBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirLightTreeBlackBoxCodegenTestGenerated.java index 0e7d16f0332..b4ef4e12166 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirLightTreeBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirLightTreeBlackBoxCodegenTestGenerated.java @@ -29167,6 +29167,12 @@ public class FirLightTreeBlackBoxCodegenTestGenerated extends AbstractFirLightTr runTest("compiler/testData/codegen/box/involvesIrInterpreter/kt57313.kt"); } + @Test + @TestMetadata("kt57802.kt") + public void testKt57802() throws Exception { + runTest("compiler/testData/codegen/box/involvesIrInterpreter/kt57802.kt"); + } + @Test @TestMetadata("kt58005.kt") public void testKt58005() throws Exception { diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirLightTreeBlackBoxCodegenWithIrFakeOverrideGeneratorTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirLightTreeBlackBoxCodegenWithIrFakeOverrideGeneratorTestGenerated.java index c3b5485110f..a259fac15a8 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirLightTreeBlackBoxCodegenWithIrFakeOverrideGeneratorTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirLightTreeBlackBoxCodegenWithIrFakeOverrideGeneratorTestGenerated.java @@ -29167,6 +29167,12 @@ public class FirLightTreeBlackBoxCodegenWithIrFakeOverrideGeneratorTestGenerated runTest("compiler/testData/codegen/box/involvesIrInterpreter/kt57313.kt"); } + @Test + @TestMetadata("kt57802.kt") + public void testKt57802() throws Exception { + runTest("compiler/testData/codegen/box/involvesIrInterpreter/kt57802.kt"); + } + @Test @TestMetadata("kt58005.kt") public void testKt58005() throws Exception { diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirPsiBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirPsiBlackBoxCodegenTestGenerated.java index f1686aa3213..3a829287a5a 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirPsiBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirPsiBlackBoxCodegenTestGenerated.java @@ -29167,6 +29167,12 @@ public class FirPsiBlackBoxCodegenTestGenerated extends AbstractFirPsiBlackBoxCo runTest("compiler/testData/codegen/box/involvesIrInterpreter/kt57313.kt"); } + @Test + @TestMetadata("kt57802.kt") + public void testKt57802() throws Exception { + runTest("compiler/testData/codegen/box/involvesIrInterpreter/kt57802.kt"); + } + @Test @TestMetadata("kt58005.kt") public void testKt58005() throws Exception { diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/FirJavaElementFinder.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/FirJavaElementFinder.kt index 5580202eb4b..69d20689dfb 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/FirJavaElementFinder.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/FirJavaElementFinder.kt @@ -9,6 +9,7 @@ import com.intellij.openapi.project.Project import com.intellij.openapi.util.Pair import com.intellij.psi.* import com.intellij.psi.impl.cache.ModifierFlags +import com.intellij.psi.impl.cache.TypeInfo import com.intellij.psi.impl.compiled.ClsClassImpl import com.intellij.psi.impl.compiled.ClsFileImpl import com.intellij.psi.impl.file.PsiPackageImpl @@ -24,12 +25,14 @@ import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.fir.FirModuleData import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.FirSessionComponent +import org.jetbrains.kotlin.fir.declarations.FirProperty import org.jetbrains.kotlin.fir.declarations.FirRegularClass import org.jetbrains.kotlin.fir.declarations.FirTypeParameter import org.jetbrains.kotlin.fir.declarations.utils.classId import org.jetbrains.kotlin.fir.declarations.utils.isInner import org.jetbrains.kotlin.fir.declarations.utils.modality import org.jetbrains.kotlin.fir.declarations.utils.visibility +import org.jetbrains.kotlin.fir.expressions.FirConstExpression import org.jetbrains.kotlin.fir.moduleData import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.resolve.fullyExpandedType @@ -48,11 +51,14 @@ import org.jetbrains.kotlin.utils.exceptions.errorWithAttachment val FirSession.javaElementFinder: FirJavaElementFinder? by FirSession.nullableSessionComponentAccessor() +private typealias PropertyEvaluator = (FirProperty) -> String? + class FirJavaElementFinder( private val session: FirSession, project: Project ) : PsiElementFinder(), KotlinFinderMarker, FirSessionComponent { private val psiManager = PsiManager.getInstance(project) + var propertyEvaluator: PropertyEvaluator? = null private val firProviders: List = buildList { add(session.firProvider) @@ -111,6 +117,18 @@ class FirJavaElementFinder( ) ) + val classProperties = firClass.declarations.filterIsInstance() + // Note: we must store companion properties in outer clas because java resolver will not find it other way. + val companionProperties = firClass.companionObjectSymbol?.declarationSymbols?.map { it.fir }?.filterIsInstance() ?: emptyList() + (classProperties + companionProperties).forEach { + // TODO correct type info + val psiField = PsiFieldStubImpl( + stub, it.name.identifier, TypeInfo.fromString("int"), propertyEvaluator?.invoke(it), + PsiFieldStubImpl.packFlags(false, false, false, false) + ) + PsiModifierListStubImpl(psiField, ModifierFlags.PUBLIC_MASK + ModifierFlags.FINAL_MASK + ModifierFlags.STATIC_MASK) + } + PsiModifierListStubImpl(stub, firClass.packFlags()) newTypeParameterList( diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/transformer/IrConstTransformer.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/transformer/IrConstTransformer.kt index 113e978f097..2d21b8cba5a 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/transformer/IrConstTransformer.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/transformer/IrConstTransformer.kt @@ -75,6 +75,24 @@ fun IrFile.runConstOptimizations( preprocessedFile.transform(irConstExpressionTransformer, IrConstTransformer.Data()) } +// TODO simplify +fun IrProperty.evaluate( + irFile: IrFile, + interpreter: IrInterpreter, + mode: EvaluationMode, + evaluatedConstTracker: EvaluatedConstTracker? = null, + inlineConstTracker: InlineConstTracker? = null, + onWarning: (IrFile, IrElement, IrErrorExpression) -> Unit = { _, _, _ -> }, + onError: (IrFile, IrElement, IrErrorExpression) -> Unit = { _, _, _ -> }, + suppressExceptions: Boolean = false, +): IrProperty? { + val checker = IrInterpreterCommonChecker() + val irConstExpressionTransformer = IrConstAllTransformer( + interpreter, irFile, mode, checker, evaluatedConstTracker, inlineConstTracker, onWarning, onError, suppressExceptions + ) + return this.transform(irConstExpressionTransformer, IrConstTransformer.Data()) as? IrProperty +} + private fun IrFile.preprocessForConstTransformer( interpreter: IrInterpreter, mode: EvaluationMode, @@ -88,7 +106,7 @@ private fun IrFile.preprocessForConstTransformer( // Note: We are using `IrElementTransformer` here instead of `IrElementTransformerVoid` to avoid conflicts with `IrTypeVisitorVoid` // that is used later in `IrConstTypeAnnotationTransformer`. -internal abstract class IrConstTransformer( +abstract class IrConstTransformer( protected val interpreter: IrInterpreter, private val irFile: IrFile, private val mode: EvaluationMode, diff --git a/compiler/testData/codegen/box/involvesIrInterpreter/kt57802.kt b/compiler/testData/codegen/box/involvesIrInterpreter/kt57802.kt new file mode 100644 index 00000000000..a4873ce2c04 --- /dev/null +++ b/compiler/testData/codegen/box/involvesIrInterpreter/kt57802.kt @@ -0,0 +1,39 @@ +// TARGET_BACKEND: JVM +// FILE: Bar.java +package one.two; + +public class Bar { + public static final int BAR = Doo.DOO + 1; +} + +// FILE: Boo.java +package one.two; + +public class Boo { + public static final int BOO = Baz.BAZ + 1; +} + +// FILE: Main.kt +package one.two + +class Foo { + companion object { + const val FOO = Boo.BOO + 1 + } +} + +class Baz { + companion object { + const val BAZ = Bar.BAR + 1 + } +} + +class Doo { + companion object { + const val DOO = 1 + } +} + +fun box(): String { + return "OK" +} diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java index bf2db239de3..08a1a5c848e 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java @@ -27823,6 +27823,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/involvesIrInterpreter/kt57028.kt"); } + @Test + @TestMetadata("kt57802.kt") + public void testKt57802() throws Exception { + runTest("compiler/testData/codegen/box/involvesIrInterpreter/kt57802.kt"); + } + @Test @TestMetadata("kt58005.kt") public void testKt58005() throws Exception { diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java index 51e7d99357c..17466a31193 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java @@ -29167,6 +29167,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/involvesIrInterpreter/kt57313.kt"); } + @Test + @TestMetadata("kt57802.kt") + public void testKt57802() throws Exception { + runTest("compiler/testData/codegen/box/involvesIrInterpreter/kt57802.kt"); + } + @Test @TestMetadata("kt58005.kt") public void testKt58005() throws Exception { diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenWithIrInlinerTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenWithIrInlinerTestGenerated.java index de20884f227..f89e1ef3be4 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenWithIrInlinerTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenWithIrInlinerTestGenerated.java @@ -29167,6 +29167,12 @@ public class IrBlackBoxCodegenWithIrInlinerTestGenerated extends AbstractIrBlack runTest("compiler/testData/codegen/box/involvesIrInterpreter/kt57313.kt"); } + @Test + @TestMetadata("kt57802.kt") + public void testKt57802() throws Exception { + runTest("compiler/testData/codegen/box/involvesIrInterpreter/kt57802.kt"); + } + @Test @TestMetadata("kt58005.kt") public void testKt58005() throws Exception { diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index 0ff20c2f57b..ef327b0b026 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -24625,6 +24625,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/involvesIrInterpreter/kt57313.kt"); } + @TestMetadata("kt57802.kt") + public void testKt57802() throws Exception { + runTest("compiler/testData/codegen/box/involvesIrInterpreter/kt57802.kt"); + } + @TestMetadata("kt58005.kt") public void testKt58005() throws Exception { runTest("compiler/testData/codegen/box/involvesIrInterpreter/kt58005.kt");