diff --git a/plugins/fir-plugin-prototype/build.gradle.kts b/plugins/fir-plugin-prototype/build.gradle.kts index 783bc9a2759..5b567f86a3d 100644 --- a/plugins/fir-plugin-prototype/build.gradle.kts +++ b/plugins/fir-plugin-prototype/build.gradle.kts @@ -17,6 +17,7 @@ dependencies { compileOnly(project(":compiler:fir:entrypoint")) compileOnly(project(":compiler:plugin-api")) compileOnly(intellijCore()) + compileOnly(commonDependency("org.jetbrains.intellij.deps:asm-all")) testApiJUnit5() testApi(projectTests(":compiler:tests-common-new")) diff --git a/plugins/fir-plugin-prototype/src/org/jetbrains/kotlin/ir/plugin/GeneratedDeclarationsIrBodyFiller.kt b/plugins/fir-plugin-prototype/src/org/jetbrains/kotlin/ir/plugin/GeneratedDeclarationsIrBodyFiller.kt index cfb57cdf55e..aa7c413f4bb 100644 --- a/plugins/fir-plugin-prototype/src/org/jetbrains/kotlin/ir/plugin/GeneratedDeclarationsIrBodyFiller.kt +++ b/plugins/fir-plugin-prototype/src/org/jetbrains/kotlin/ir/plugin/GeneratedDeclarationsIrBodyFiller.kt @@ -21,6 +21,7 @@ class GeneratedDeclarationsIrBodyFiller : IrGenerationExtension { TransformerForAddingAnnotations(pluginContext), ComposableFunctionsTransformer(pluginContext), BodyWithDefaultValueReplacer(), + SourceElementChecker(pluginContext), ) for (transformer in transformers) { diff --git a/plugins/fir-plugin-prototype/src/org/jetbrains/kotlin/ir/plugin/SourceElementChecker.kt b/plugins/fir-plugin-prototype/src/org/jetbrains/kotlin/ir/plugin/SourceElementChecker.kt new file mode 100644 index 00000000000..8c436c269a2 --- /dev/null +++ b/plugins/fir-plugin-prototype/src/org/jetbrains/kotlin/ir/plugin/SourceElementChecker.kt @@ -0,0 +1,70 @@ +/* + * Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.ir.plugin + +import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext +import org.jetbrains.kotlin.descriptors.SourceElement +import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin +import org.jetbrains.kotlin.fir.java.JavaBinarySourceElement +import org.jetbrains.kotlin.fir.lazy.Fir2IrLazyClass +import org.jetbrains.kotlin.ir.IrElement +import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET +import org.jetbrains.kotlin.ir.declarations.IrClass +import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin +import org.jetbrains.kotlin.ir.declarations.IrFunction +import org.jetbrains.kotlin.ir.symbols.IrSymbolInternals +import org.jetbrains.kotlin.ir.types.IrSimpleType +import org.jetbrains.kotlin.ir.util.fqNameForIrSerialization +import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid +import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid +import org.jetbrains.kotlin.load.java.structure.impl.VirtualFileBoundJavaClass +import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinarySourceElement +import org.jetbrains.kotlin.load.kotlin.VirtualFileKotlinClass +import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource + +@OptIn(IrSymbolInternals::class) +class SourceElementChecker(val context: IrPluginContext) : IrElementVisitorVoid { + override fun visitElement(element: IrElement) { + element.acceptChildrenVoid(this) + } + + override fun visitFunction(declaration: IrFunction) { + val type = declaration.returnType as? IrSimpleType ?: return + val klass = type.classifier.owner as? IrClass ?: return + if (klass.startOffset != UNDEFINED_OFFSET) { + return + } + if (klass.origin is IrDeclarationOrigin.GeneratedByPlugin) { + return + } + if (klass is Fir2IrLazyClass && klass.fir.origin == FirDeclarationOrigin.BuiltIns) { + return + } + when (val sourceElement = klass.source) { + is KotlinJvmBinarySourceElement -> { + val binaryClass = sourceElement.binaryClass + if (binaryClass !is VirtualFileKotlinClass) { + throw AssertionError("No virtual file found: ${binaryClass.classId}") + } + } + is JavaBinarySourceElement -> { + val javaClass = sourceElement.javaClass + (javaClass as VirtualFileBoundJavaClass).virtualFile + ?: throw AssertionError("No virtual file found: ${javaClass.fqName}") + } + is DeserializedContainerSource -> { + // Klib element is possible here in JS test + return + } + SourceElement.NO_SOURCE -> { + throw AssertionError("No source found: ${klass.fqNameForIrSerialization}") + } + else -> { + throw AssertionError("Unknown source element: ${sourceElement.javaClass}") + } + } + } +} diff --git a/plugins/fir-plugin-prototype/testData/box/builtins.fir.txt b/plugins/fir-plugin-prototype/testData/box/builtins.fir.txt new file mode 100644 index 00000000000..2c7f705178b --- /dev/null +++ b/plugins/fir-plugin-prototype/testData/box/builtins.fir.txt @@ -0,0 +1,60 @@ +FILE: builtins.kt + public final fun foo1(): R|kotlin/Unit| { + } + public final fun foo2(): R|kotlin/Int| { + ^foo2 Int(2) + } + public final fun foo3(): R|kotlin/Short| { + ^foo3 Short(3) + } + public final fun foo4(): R|kotlin/Byte| { + ^foo4 Byte(4) + } + public final fun foo5(): R|kotlin/Long| { + ^foo5 Long(5) + } + public final fun foo6(): R|kotlin/Float| { + ^foo6 Float(6.0) + } + public final fun foo7(): R|kotlin/Double| { + ^foo7 Double(7.0) + } + public final fun foo8(): R|kotlin/Char| { + ^foo8 Char(8) + } + public final fun foo9(): R|kotlin/Boolean| { + ^foo9 Boolean(true) + } + public final fun foo10(): R|kotlin/String| { + ^foo10 String(10) + } + public final fun foo11(): R|kotlin/collections/List| { + ^foo11 R|kotlin/collections/listOf|(String(11)) + } + public final fun foo12(): R|kotlin/collections/MutableList| { + ^foo12 R|kotlin/collections/mutableListOf|(vararg(String(12))) + } + public final fun foo13(): R|kotlin/Any| { + ^foo13 Int(13) + } + public final fun foo14(): R|kotlin/Nothing| { + ^foo14 R|kotlin/TODO|() + } + public final fun foo15(): R|() -> kotlin/Int| { + ^foo15 fun (): R|kotlin/Int| { + ^ Int(15) + } + + } + public final fun foo16(): R|kotlin/Array| { + ^foo16 R|kotlin/arrayOf|(vararg(String(16))) + } + public final fun foo17(): R|kotlin/Number| { + ^foo17 Int(17) + } + public final fun foo18(): R|kotlin/annotation/AnnotationTarget| { + ^foo18 Q|kotlin/annotation/AnnotationTarget|.R|kotlin/annotation/AnnotationTarget.CLASS| + } + public final fun box(): R|kotlin/String| { + ^box String(OK) + } diff --git a/plugins/fir-plugin-prototype/testData/box/builtins.kt b/plugins/fir-plugin-prototype/testData/box/builtins.kt new file mode 100644 index 00000000000..39d7006e238 --- /dev/null +++ b/plugins/fir-plugin-prototype/testData/box/builtins.kt @@ -0,0 +1,39 @@ +// WITH_STDLIB + +fun foo1() {} + +fun foo2(): Int = 2 + +fun foo3(): Short = 3 + +fun foo4(): Byte = 4 + +fun foo5(): Long = 5L + +fun foo6(): Float = 6.0f + +fun foo7(): Double = 7.0 + +fun foo8(): Char = '8' + +fun foo9(): Boolean = true + +fun foo10(): String = "10" + +fun foo11(): List = listOf("11") + +fun foo12(): MutableList = mutableListOf("12") + +fun foo13(): Any = 13 + +fun foo14(): Nothing = TODO() + +fun foo15(): () -> Int = { 15 } + +fun foo16(): Array = arrayOf("16") + +fun foo17(): Number = 17 + +fun foo18(): AnnotationTarget = AnnotationTarget.CLASS + +fun box() = "OK" diff --git a/plugins/fir-plugin-prototype/testData/box/extendsJava.fir.txt b/plugins/fir-plugin-prototype/testData/box/extendsJava.fir.txt new file mode 100644 index 00000000000..b3a76fcb337 --- /dev/null +++ b/plugins/fir-plugin-prototype/testData/box/extendsJava.fir.txt @@ -0,0 +1,13 @@ +FILE: extendsJava.kt + public final class A : R|java/io/File| { + public constructor(): R|A| { + super(String(A)) + } + + } + public final fun foo(): R|A| { + ^foo R|kotlin/TODO|() + } + public final fun box(): R|kotlin/String| { + ^box String(OK) + } diff --git a/plugins/fir-plugin-prototype/testData/box/extendsJava.kt b/plugins/fir-plugin-prototype/testData/box/extendsJava.kt new file mode 100644 index 00000000000..9316091f23f --- /dev/null +++ b/plugins/fir-plugin-prototype/testData/box/extendsJava.kt @@ -0,0 +1,8 @@ +// FULL_JDK +import java.io.File; + +class A : File("A") + +fun foo(): A = TODO() + +fun box() = "OK" diff --git a/plugins/fir-plugin-prototype/tests-gen/org/jetbrains/kotlin/fir/plugin/runners/FirLightTreePluginBlackBoxCodegenTestGenerated.java b/plugins/fir-plugin-prototype/tests-gen/org/jetbrains/kotlin/fir/plugin/runners/FirLightTreePluginBlackBoxCodegenTestGenerated.java index cd6d1dcd812..c1fd8799c27 100644 --- a/plugins/fir-plugin-prototype/tests-gen/org/jetbrains/kotlin/fir/plugin/runners/FirLightTreePluginBlackBoxCodegenTestGenerated.java +++ b/plugins/fir-plugin-prototype/tests-gen/org/jetbrains/kotlin/fir/plugin/runners/FirLightTreePluginBlackBoxCodegenTestGenerated.java @@ -25,6 +25,12 @@ public class FirLightTreePluginBlackBoxCodegenTestGenerated extends AbstractFirL KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("plugins/fir-plugin-prototype/testData/box"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); } + @Test + @TestMetadata("builtins.kt") + public void testBuiltins() throws Exception { + runTest("plugins/fir-plugin-prototype/testData/box/builtins.kt"); + } + @Test @TestMetadata("classWithAllPropertiesConstructor.kt") public void testClassWithAllPropertiesConstructor() throws Exception { @@ -55,6 +61,12 @@ public class FirLightTreePluginBlackBoxCodegenTestGenerated extends AbstractFirL runTest("plugins/fir-plugin-prototype/testData/box/expectComposableFunction.kt"); } + @Test + @TestMetadata("extendsJava.kt") + public void testExtendsJava() throws Exception { + runTest("plugins/fir-plugin-prototype/testData/box/extendsJava.kt"); + } + @Test @TestMetadata("generatedClassWithMembersAndNestedClasses.kt") public void testGeneratedClassWithMembersAndNestedClasses() throws Exception {