@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.descriptors.java.JavaVisibilities
1414import org.jetbrains.kotlin.ir.IrElement
1515import org.jetbrains.kotlin.ir.IrStatement
1616import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
17+ import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
1718import org.jetbrains.kotlin.ir.backend.js.utils.realOverrideTarget
1819import org.jetbrains.kotlin.ir.builders.declarations.*
1920import org.jetbrains.kotlin.ir.declarations.*
@@ -44,15 +45,21 @@ import org.jetbrains.kotlin.ir.util.parentClassOrNull
4445import org.jetbrains.kotlin.ir.util.primaryConstructor
4546import org.jetbrains.kotlin.ir.util.render
4647import org.jetbrains.kotlin.ir.util.target
48+ import org.jetbrains.kotlin.load.java.JvmAnnotationNames
49+ import org.jetbrains.kotlin.load.java.NOT_NULL_ANNOTATIONS
50+ import org.jetbrains.kotlin.load.java.NULLABLE_ANNOTATIONS
4751import org.jetbrains.kotlin.load.java.sources.JavaSourceElement
52+ import org.jetbrains.kotlin.load.java.structure.JavaAnnotation
4853import org.jetbrains.kotlin.load.java.structure.JavaClass
54+ import org.jetbrains.kotlin.load.java.structure.JavaConstructor
4955import org.jetbrains.kotlin.load.java.structure.JavaMethod
5056import org.jetbrains.kotlin.load.java.structure.JavaTypeParameter
5157import org.jetbrains.kotlin.load.java.structure.JavaTypeParameterListOwner
5258import org.jetbrains.kotlin.load.java.structure.impl.classFiles.BinaryJavaClass
5359import org.jetbrains.kotlin.name.FqName
5460import org.jetbrains.kotlin.types.Variance
5561import org.jetbrains.kotlin.util.OperatorNameConventions
62+ import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
5663import java.io.Closeable
5764import java.util.*
5865import kotlin.collections.ArrayList
@@ -887,7 +894,13 @@ open class KotlinFileExtractor(
887894 extractTypeAccessRecursive(substitutedType, location, id, - 1 )
888895 }
889896 val syntheticParameterNames = isUnderscoreParameter(vp) || ((vp.parent as ? IrFunction )?.let { hasSynthesizedParameterNames(it) } ? : true )
890- extractAnnotations(vp, id, extractTypeAccess)
897+ val javaParameter = when (val callable = (vp.parent as ? IrFunction )?.let { getJavaCallable(it) }) {
898+ is JavaConstructor -> callable.valueParameters.getOrNull(idx)
899+ is JavaMethod -> callable.valueParameters.getOrNull(idx)
900+ else -> null
901+ }
902+ val extraAnnotations = listOfNotNull(getNullabilityAnnotation(vp.type, vp.origin, vp.annotations, javaParameter?.annotations))
903+ extractAnnotations(vp.annotations + extraAnnotations, id, extractTypeAccess)
891904 return extractValueParameter(id, substitutedType, vp.name.asString(), location, parent, idx, useValueParameter(vp, parentSourceDeclaration), syntheticParameterNames, vp.isVararg, vp.isNoinline, vp.isCrossinline)
892905 }
893906 }
@@ -1337,6 +1350,32 @@ open class KotlinFileExtractor(
13371350 logger.warn(" Needed a signature for a type that doesn't have one" )
13381351 }
13391352
1353+ private fun getNullabilityAnnotationName (t : IrType , declOrigin : IrDeclarationOrigin , existingAnnotations : List <IrConstructorCall >, javaAnnotations : Collection <JavaAnnotation >? ): FqName ? {
1354+ if (t !is IrSimpleType )
1355+ return null
1356+
1357+ return if (declOrigin == IrDeclarationOrigin .IR_EXTERNAL_JAVA_DECLARATION_STUB ) {
1358+ // Java declaration: restore a NotNull or Nullable annotation if the original Java member had one but the Kotlin compiler removed it.
1359+ javaAnnotations?.mapNotNull { it.classId?.asSingleFqName() }
1360+ ?.singleOrNull { NOT_NULL_ANNOTATIONS .contains(it) || NULLABLE_ANNOTATIONS .contains(it) }
1361+ ?.takeUnless { existingAnnotations.any { existing -> existing.type.classFqName == it } }
1362+ } else {
1363+ // Kotlin declaration: add a NotNull annotation to a non-nullable non-primitive type.
1364+ JvmAnnotationNames .JETBRAINS_NOT_NULL_ANNOTATION .takeUnless { t.isNullable() || primitiveTypeMapping.getPrimitiveInfo(t) != null }
1365+ }
1366+ }
1367+
1368+ private fun getNullabilityAnnotation (t : IrType , declOrigin : IrDeclarationOrigin , existingAnnotations : List <IrConstructorCall >, javaAnnotations : Collection <JavaAnnotation >? ) =
1369+ getNullabilityAnnotationName(t, declOrigin, existingAnnotations, javaAnnotations)?.let {
1370+ pluginContext.referenceClass(it)?.let { annotationClass ->
1371+ annotationClass.owner.declarations.firstIsInstanceOrNull<IrConstructor >()?.let { annotationConstructor ->
1372+ IrConstructorCallImpl .fromSymbolOwner(
1373+ UNDEFINED_OFFSET , UNDEFINED_OFFSET , annotationConstructor.returnType, annotationConstructor.symbol, 0
1374+ )
1375+ }
1376+ }
1377+ }
1378+
13401379 private fun forceExtractFunction (f : IrFunction , parentId : Label <out DbReftype >, extractBody : Boolean , extractMethodAndParameterTypeAccesses : Boolean , extractAnnotations : Boolean , typeSubstitution : TypeSubstitution ? , classTypeArgsIncludingOuterClasses : List <IrTypeArgument >? , extractOrigin : Boolean = true, overriddenAttributes : OverriddenFunctionAttributes ? = null): Label <out DbCallable > {
13411380 with (" function" , f) {
13421381 DeclarationStackAdjuster (f, overriddenAttributes).use {
@@ -1427,8 +1466,10 @@ open class KotlinFileExtractor(
14271466
14281467 linesOfCode?.linesOfCodeInDeclaration(f, id)
14291468
1430- if (extractAnnotations)
1431- extractAnnotations(f, id, extractMethodAndParameterTypeAccesses)
1469+ if (extractAnnotations) {
1470+ val extraAnnotations = listOfNotNull(getNullabilityAnnotation(f.returnType, f.origin, f.annotations, getJavaCallable(f)?.annotations))
1471+ extractAnnotations(f.annotations + extraAnnotations, id, extractMethodAndParameterTypeAccesses)
1472+ }
14321473
14331474 return id
14341475 }
0 commit comments