diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt index 47fc37beef0..f018144c21b 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt @@ -24,6 +24,7 @@ import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutorByMap import org.jetbrains.kotlin.fir.resolve.toSymbol import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.approximateDeclarationType +import org.jetbrains.kotlin.fir.scopes.getDeclaredConstructors import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol import org.jetbrains.kotlin.fir.symbols.impl.* @@ -43,7 +44,6 @@ import org.jetbrains.kotlin.ir.util.isMethodOfAny import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.calls.NewCommonSuperTypeCalculator.commonSuperType import org.jetbrains.kotlin.util.OperatorNameConventions -import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull class CallAndReferenceGenerator( private val components: Fir2IrComponents, @@ -691,7 +691,11 @@ class CallAndReferenceGenerator( useSiteTarget = this@toAnnotationCall.useSiteTarget annotationTypeRef = this@toAnnotationCall.annotationTypeRef val symbol = annotationTypeRef.coneType.fullyExpandedType(session).toSymbol(session) as? FirRegularClassSymbol ?: return null - val constructorSymbol = symbol.declarationSymbols.firstIsInstanceOrNull() ?: return null + + val constructorSymbol = + symbol.unsubstitutedScope(session, scopeSession, withForcedTypeCalculator = false) + .getDeclaredConstructors().firstOrNull() ?: return null + val argumentToParameterToMapping = constructorSymbol.valueParameterSymbols.mapNotNull { val parameter = it.fir val argument = this@toAnnotationCall.argumentMapping.mapping[parameter.name] ?: return@mapNotNull null diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/deserializedAnnotationReferencesJava/libraryAnnotation/Nls.java b/compiler/testData/compileKotlinAgainstCustomBinaries/deserializedAnnotationReferencesJava/libraryAnnotation/Nls.java new file mode 100644 index 00000000000..76e13371e53 --- /dev/null +++ b/compiler/testData/compileKotlinAgainstCustomBinaries/deserializedAnnotationReferencesJava/libraryAnnotation/Nls.java @@ -0,0 +1,25 @@ +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Documented +@Retention(RetentionPolicy.CLASS) +@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE, ElementType.TYPE_USE, ElementType.TYPE, ElementType.PACKAGE}) +public @interface Nls { + enum Capitalization { + + NotSpecified, + /** + * e.g. This Is a Title + */ + Title, + /** + * e.g. This is a sentence + */ + Sentence + } + + Capitalization capitalization() default Capitalization.NotSpecified; +} diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/deserializedAnnotationReferencesJava/libraryUsingAnnotation/MyClass.kt b/compiler/testData/compileKotlinAgainstCustomBinaries/deserializedAnnotationReferencesJava/libraryUsingAnnotation/MyClass.kt new file mode 100644 index 00000000000..0a1677ae483 --- /dev/null +++ b/compiler/testData/compileKotlinAgainstCustomBinaries/deserializedAnnotationReferencesJava/libraryUsingAnnotation/MyClass.kt @@ -0,0 +1 @@ +class MyClass(val name: @Nls(capitalization = Nls.Capitalization.Title) String) diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/deserializedAnnotationReferencesJava/output.txt b/compiler/testData/compileKotlinAgainstCustomBinaries/deserializedAnnotationReferencesJava/output.txt new file mode 100644 index 00000000000..d86bac9de59 --- /dev/null +++ b/compiler/testData/compileKotlinAgainstCustomBinaries/deserializedAnnotationReferencesJava/output.txt @@ -0,0 +1 @@ +OK diff --git a/compiler/testData/compileKotlinAgainstCustomBinaries/deserializedAnnotationReferencesJava/usage.kt b/compiler/testData/compileKotlinAgainstCustomBinaries/deserializedAnnotationReferencesJava/usage.kt new file mode 100644 index 00000000000..04f26e98637 --- /dev/null +++ b/compiler/testData/compileKotlinAgainstCustomBinaries/deserializedAnnotationReferencesJava/usage.kt @@ -0,0 +1,6 @@ +fun box(): String { + // This class is only needed to force resolution of `@Nls` scope, so its types would be converted to resolved + class LocalClassToUseAnnotation(val name: @Nls(capitalization = Nls.Capitalization.Title) String) + + return MyClass("OK").name +} diff --git a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstCustomBinariesTest.kt b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstCustomBinariesTest.kt index 4b4543fda27..155b023679a 100644 --- a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstCustomBinariesTest.kt +++ b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/CompileKotlinAgainstCustomBinariesTest.kt @@ -795,6 +795,25 @@ class CompileKotlinAgainstCustomBinariesTest : AbstractKotlinCompilerIntegration ) } + fun testDeserializedAnnotationReferencesJava() { + // Only Java + val libraryAnnotation = compileLibrary("libraryAnnotation") + // Specifically, use K1 + // Remove "-Xuse-k2=false" argument once it becomes forbidden + val libraryUsingAnnotation = compileLibrary( + "libraryUsingAnnotation", + additionalOptions = listOf("-language-version", "1.8", "-Xuse-k2=false"), + extraClassPath = listOf(libraryAnnotation) + ) + + compileKotlin( + "usage.kt", + output = tmpdir, + classpath = listOf(libraryAnnotation, libraryUsingAnnotation), + additionalOptions = listOf("-language-version", "2.0") + ) + } + private fun loadClassFile(className: String, dir: File, library: File) { val classLoader = URLClassLoader(arrayOf(dir.toURI().toURL(), library.toURI().toURL())) val mainClass = classLoader.loadClass(className)