diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/DelegatedPropertyGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/DelegatedPropertyGenerator.kt index 4c2e3cb0736..26174c8bdc8 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/DelegatedPropertyGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/DelegatedPropertyGenerator.kt @@ -43,6 +43,8 @@ import org.jetbrains.kotlin.psi.psiUtil.startOffsetSkippingComments import org.jetbrains.kotlin.psi2ir.intermediate.* import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.types.error.ErrorTypeKind +import org.jetbrains.kotlin.types.error.ErrorUtils.createErrorType import org.jetbrains.kotlin.types.typeUtil.replaceArgumentsWithStarProjections internal class DelegatedPropertyGenerator( @@ -323,8 +325,11 @@ internal class DelegatedPropertyGenerator( val provideDelegateResolvedCall = get(BindingContext.PROVIDE_DELEGATE_RESOLVED_CALL, delegatedPropertyDescriptor) val delegateType = if (provideDelegateResolvedCall != null) { provideDelegateResolvedCall.resultingDescriptor.returnType!! - } else { + } else if (context.configuration.generateBodies) { getTypeInferredByFrontendOrFail(ktDelegate.expression!!) + } else { + getTypeInferredByFrontend(ktDelegate.expression!!) + ?: createErrorType(ErrorTypeKind.UNRESOLVED_TYPE, ktDelegate.expression!!.text) } // For KAPT stub generation, we approximate the type of the delegate. // Since we are not generating bodies, we could end up with unbound diff --git a/compiler/testData/codegen/kapt/dataClass.ir.txt b/compiler/testData/codegen/kapt/dataClass.ir.txt new file mode 100644 index 00000000000..5ecf4cd85d8 --- /dev/null +++ b/compiler/testData/codegen/kapt/dataClass.ir.txt @@ -0,0 +1,15 @@ +@kotlin.Metadata +public final class User { + // source: 'dataClass.kt' + private final field age: int + private final @org.jetbrains.annotations.NotNull field name: java.lang.String + public method (@org.jetbrains.annotations.NotNull p0: java.lang.String, p1: int): void + public final @org.jetbrains.annotations.NotNull method component1(): java.lang.String + public final method component2(): int + public final @org.jetbrains.annotations.NotNull method copy(@org.jetbrains.annotations.NotNull p0: java.lang.String, p1: int): User + public method equals(@org.jetbrains.annotations.Nullable p0: java.lang.Object): boolean + public final method getAge(): int + public final @org.jetbrains.annotations.NotNull method getName(): java.lang.String + public method hashCode(): int + public @org.jetbrains.annotations.NotNull method toString(): java.lang.String +} diff --git a/compiler/testData/codegen/kapt/errorTypes.ir.txt b/compiler/testData/codegen/kapt/errorTypes.ir.txt new file mode 100644 index 00000000000..8f20cd630cd --- /dev/null +++ b/compiler/testData/codegen/kapt/errorTypes.ir.txt @@ -0,0 +1,30 @@ +@kotlin.Metadata +@kotlin.Suppress(names=["UNRESOLVED_REFERENCE"]) +public final class A { + // source: 'errorTypes.kt' + private final @org.jetbrains.annotations.NotNull field a: error.NonExistentClass + public method (): void + public final @org.jetbrains.annotations.NotNull method getA(): error.NonExistentClass +} + +@kotlin.Metadata +@kotlin.Suppress(names=["UNRESOLVED_REFERENCE"]) +public final class B { + // source: 'errorTypes.kt' + private final @org.jetbrains.annotations.NotNull field a$delegate: error.NonExistentClass + public method (): void + public synthetic deprecated static @kotlin.Suppress(names=["UNRESOLVED_REFERENCE_WRONG_RECEIVER"]) method getA$annotations(): void + public final @org.jetbrains.annotations.NotNull method getA(): java.lang.String +} + +@kotlin.Metadata +public class C { + // source: 'errorTypes.kt' + public method (): void +} + +@kotlin.Metadata +public final class ErrorTypesKt { + // source: 'errorTypes.kt' + public final static @org.jetbrains.annotations.NotNull method flaf(@org.jetbrains.annotations.NotNull p0: C): java.lang.String +} diff --git a/compiler/testData/codegen/kapt/errorTypes.kt b/compiler/testData/codegen/kapt/errorTypes.kt index 4cdc751f02b..0915929e3d7 100644 --- a/compiler/testData/codegen/kapt/errorTypes.kt +++ b/compiler/testData/codegen/kapt/errorTypes.kt @@ -1,4 +1,14 @@ @Suppress("UNRESOLVED_REFERENCE") class A { val a: ABC = null -} \ No newline at end of file +} + +open class C + +@Suppress("UNRESOLVED_REFERENCE") +class B : NonExisting { + @Suppress("UNRESOLVED_REFERENCE_WRONG_RECEIVER") + val a: String by flaf() +} + +fun C.flaf() = "OK" diff --git a/compiler/testData/codegen/kapt/errorTypes.txt b/compiler/testData/codegen/kapt/errorTypes.txt index eff3db2cf68..2948b13d78a 100644 --- a/compiler/testData/codegen/kapt/errorTypes.txt +++ b/compiler/testData/codegen/kapt/errorTypes.txt @@ -6,3 +6,26 @@ public final class A { public method (): void public final @org.jetbrains.annotations.NotNull method getA(): error.NonExistentClass } + +@kotlin.Metadata +@kotlin.Suppress(names=["UNRESOLVED_REFERENCE"]) +public final class B { + // source: 'errorTypes.kt' + synthetic final static field $$delegatedProperties: kotlin.reflect.KProperty[] + private final @org.jetbrains.annotations.NotNull field a$delegate: error.NonExistentClass + public method (): void + public synthetic deprecated static @kotlin.Suppress(names=["UNRESOLVED_REFERENCE_WRONG_RECEIVER"]) method getA$annotations(): void + public final @org.jetbrains.annotations.NotNull method getA(): java.lang.String +} + +@kotlin.Metadata +public class C { + // source: 'errorTypes.kt' + public method (): void +} + +@kotlin.Metadata +public final class ErrorTypesKt { + // source: 'errorTypes.kt' + public final static @org.jetbrains.annotations.NotNull method flaf(@org.jetbrains.annotations.NotNull p0: C): java.lang.String +} diff --git a/compiler/testData/codegen/kapt/innerClasses.ir.txt b/compiler/testData/codegen/kapt/innerClasses.ir.txt new file mode 100644 index 00000000000..36d8629bbb1 --- /dev/null +++ b/compiler/testData/codegen/kapt/innerClasses.ir.txt @@ -0,0 +1,61 @@ +@kotlin.Metadata +public final class test/TopLevel$Companion { + // source: 'innerClasses.kt' + private method (): void + public synthetic method (p0: kotlin.jvm.internal.DefaultConstructorMarker): void + public final method a(): void + public synthetic deprecated static @kotlin.jvm.JvmStatic method getQ$annotations(): void + public final @org.jetbrains.annotations.NotNull method getQ(): java.lang.String + public final inner class test/TopLevel$Companion +} + +@kotlin.Metadata +public interface test/TopLevel$InnerInterface { + // source: 'innerClasses.kt' + public inner class test/TopLevel$InnerInterface +} + +@kotlin.Metadata +public final class test/TopLevel$InnerObject { + // source: 'innerClasses.kt' + public final static @org.jetbrains.annotations.NotNull field INSTANCE: test.TopLevel$InnerObject + static method (): void + private method (): void + public final inner class test/TopLevel$InnerObject +} + +@kotlin.Metadata +public final class test/TopLevel$NestedClass$NestedInnerClass { + // source: 'innerClasses.kt' + synthetic final field this$0: test.TopLevel$NestedClass + public method (p0: test.TopLevel$NestedClass): void + public final inner class test/TopLevel$NestedClass + public final inner class test/TopLevel$NestedClass$NestedInnerClass +} + +@kotlin.Metadata +public final class test/TopLevel$NestedClass { + // source: 'innerClasses.kt' + public method (): void + public final inner class test/TopLevel$NestedClass + public final inner class test/TopLevel$NestedClass$NestedInnerClass +} + +@kotlin.Metadata +public final class test/TopLevel { + // source: 'innerClasses.kt' + public final static @org.jetbrains.annotations.NotNull field Companion: test.TopLevel$Companion + private final static @org.jetbrains.annotations.NotNull field q: java.lang.String + private final @org.jetbrains.annotations.NotNull field x: java.lang.String + private final field y: int + static method (): void + public method (): void + public final method b(): void + public final static @org.jetbrains.annotations.NotNull method getQ(): java.lang.String + public final @org.jetbrains.annotations.NotNull method getX(): java.lang.String + public final method getY(): int + public final inner class test/TopLevel$Companion + public final inner class test/TopLevel$InnerObject + public final inner class test/TopLevel$NestedClass + public inner class test/TopLevel$InnerInterface +} diff --git a/compiler/testData/codegen/kapt/jvmOverloads.ir.txt b/compiler/testData/codegen/kapt/jvmOverloads.ir.txt new file mode 100644 index 00000000000..f82b15bc7c4 --- /dev/null +++ b/compiler/testData/codegen/kapt/jvmOverloads.ir.txt @@ -0,0 +1,10 @@ +@kotlin.Metadata +public final class Test { + // source: 'jvmOverloads.kt' + public method (): void + public synthetic static method b$default(p0: Test, p1: java.lang.String, p2: int, p3: char, p4: int, p5: java.lang.Object): void + public final @kotlin.jvm.JvmOverloads method b(): void + public final @kotlin.jvm.JvmOverloads method b(@org.jetbrains.annotations.NotNull p0: java.lang.String): void + public final @kotlin.jvm.JvmOverloads method b(@org.jetbrains.annotations.NotNull p0: java.lang.String, p1: int): void + public final @kotlin.jvm.JvmOverloads method b(@org.jetbrains.annotations.NotNull p0: java.lang.String, p1: int, p2: char): void +} diff --git a/compiler/tests-common/tests/org/jetbrains/kotlin/codegen/AbstractIrKapt3BuilderModeBytecodeShapeTest.kt b/compiler/tests-common/tests/org/jetbrains/kotlin/codegen/AbstractIrKapt3BuilderModeBytecodeShapeTest.kt new file mode 100644 index 00000000000..7d879cb0a4e --- /dev/null +++ b/compiler/tests-common/tests/org/jetbrains/kotlin/codegen/AbstractIrKapt3BuilderModeBytecodeShapeTest.kt @@ -0,0 +1,28 @@ +/* + * Copyright 2010-2023 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.codegen + +import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment +import org.jetbrains.kotlin.resolve.jvm.extensions.AnalysisHandlerExtension +import org.jetbrains.kotlin.resolve.jvm.extensions.PartialAnalysisHandlerExtension +import org.jetbrains.kotlin.test.KotlinTestUtils +import org.jetbrains.kotlin.test.TargetBackend +import java.io.File + +abstract class AbstractIrKapt3BuilderModeBytecodeShapeTest : AbstractKapt3BuilderModeBytecodeShapeTest() { + override val backend: TargetBackend = TargetBackend.JVM_IR +} diff --git a/compiler/tests-common/tests/org/jetbrains/kotlin/codegen/AbstractKapt3BuilderModeBytecodeShapeTest.kt b/compiler/tests-common/tests/org/jetbrains/kotlin/codegen/AbstractKapt3BuilderModeBytecodeShapeTest.kt index 0a81e531467..0c63d521860 100644 --- a/compiler/tests-common/tests/org/jetbrains/kotlin/codegen/AbstractKapt3BuilderModeBytecodeShapeTest.kt +++ b/compiler/tests-common/tests/org/jetbrains/kotlin/codegen/AbstractKapt3BuilderModeBytecodeShapeTest.kt @@ -20,6 +20,7 @@ import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment import org.jetbrains.kotlin.resolve.jvm.extensions.AnalysisHandlerExtension import org.jetbrains.kotlin.resolve.jvm.extensions.PartialAnalysisHandlerExtension import org.jetbrains.kotlin.test.KotlinTestUtils +import org.jetbrains.kotlin.test.TargetBackend import java.io.File abstract class AbstractKapt3BuilderModeBytecodeShapeTest : CodegenTestCase() { @@ -31,7 +32,9 @@ abstract class AbstractKapt3BuilderModeBytecodeShapeTest : CodegenTestCase() { override fun doMultiFileTest(wholeFile: File, files: List) { compile(files) - val txtFile = File(wholeFile.parentFile, wholeFile.nameWithoutExtension + ".txt") + val irFile = File(wholeFile.parentFile, wholeFile.nameWithoutExtension + ".ir.txt") + val nonIrFile = File(wholeFile.parentFile, wholeFile.nameWithoutExtension + ".txt") + val txtFile = if (backend == TargetBackend.JVM_IR && irFile.exists()) irFile else nonIrFile KotlinTestUtils.assertEqualsToFile(txtFile, BytecodeListingTextCollectingVisitor.getText(classFileFactory)) } diff --git a/compiler/tests-for-compiler-generator/tests/org/jetbrains/kotlin/test/generators/GenerateJUnit3CompilerTests.kt b/compiler/tests-for-compiler-generator/tests/org/jetbrains/kotlin/test/generators/GenerateJUnit3CompilerTests.kt index 55c2c94c152..5835798045e 100644 --- a/compiler/tests-for-compiler-generator/tests/org/jetbrains/kotlin/test/generators/GenerateJUnit3CompilerTests.kt +++ b/compiler/tests-for-compiler-generator/tests/org/jetbrains/kotlin/test/generators/GenerateJUnit3CompilerTests.kt @@ -100,6 +100,10 @@ fun generateJUnit3CompilerTests(args: Array) { model("codegen/kapt", targetBackend = TargetBackend.JVM) } + testClass { + model("codegen/kapt", targetBackend = TargetBackend.JVM_IR) + } + testClass { model("codegen/script", extension = "kts", targetBackend = TargetBackend.JVM) } diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/IrKapt3BuilderModeBytecodeShapeTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/IrKapt3BuilderModeBytecodeShapeTestGenerated.java new file mode 100644 index 00000000000..de29d85517e --- /dev/null +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/IrKapt3BuilderModeBytecodeShapeTestGenerated.java @@ -0,0 +1,67 @@ +/* + * 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.codegen; + +import com.intellij.testFramework.TestDataPath; +import org.jetbrains.kotlin.test.JUnit3RunnerWithInners; +import org.jetbrains.kotlin.test.KotlinTestUtils; +import org.jetbrains.kotlin.test.util.KtTestUtil; +import org.jetbrains.kotlin.test.TargetBackend; +import org.jetbrains.kotlin.test.TestMetadata; +import org.junit.runner.RunWith; + +import java.io.File; +import java.util.regex.Pattern; + +/** This class is generated by {@link org.jetbrains.kotlin.test.generators.GenerateCompilerTestsKt}. DO NOT MODIFY MANUALLY */ +@SuppressWarnings("all") +@TestMetadata("compiler/testData/codegen/kapt") +@TestDataPath("$PROJECT_ROOT") +@RunWith(JUnit3RunnerWithInners.class) +public class IrKapt3BuilderModeBytecodeShapeTestGenerated extends AbstractIrKapt3BuilderModeBytecodeShapeTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM_IR, testDataFilePath); + } + + public void testAllFilesPresentInKapt() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/kapt"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); + } + + @TestMetadata("dataClass.kt") + public void testDataClass() throws Exception { + runTest("compiler/testData/codegen/kapt/dataClass.kt"); + } + + @TestMetadata("errorTypes.kt") + public void testErrorTypes() throws Exception { + runTest("compiler/testData/codegen/kapt/errorTypes.kt"); + } + + @TestMetadata("innerClasses.kt") + public void testInnerClasses() throws Exception { + runTest("compiler/testData/codegen/kapt/innerClasses.kt"); + } + + @TestMetadata("interfaceImpls.kt") + public void testInterfaceImpls() throws Exception { + runTest("compiler/testData/codegen/kapt/interfaceImpls.kt"); + } + + @TestMetadata("jvmOverloads.kt") + public void testJvmOverloads() throws Exception { + runTest("compiler/testData/codegen/kapt/jvmOverloads.kt"); + } + + @TestMetadata("lambdas.kt") + public void testLambdas() throws Exception { + runTest("compiler/testData/codegen/kapt/lambdas.kt"); + } + + @TestMetadata("simple.kt") + public void testSimple() throws Exception { + runTest("compiler/testData/codegen/kapt/simple.kt"); + } +}