@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.descriptors.java.JavaVisibilities
14
14
import org.jetbrains.kotlin.ir.IrElement
15
15
import org.jetbrains.kotlin.ir.IrStatement
16
16
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
17
+ import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
17
18
import org.jetbrains.kotlin.ir.backend.js.utils.realOverrideTarget
18
19
import org.jetbrains.kotlin.ir.builders.declarations.*
19
20
import org.jetbrains.kotlin.ir.declarations.*
@@ -44,15 +45,21 @@ import org.jetbrains.kotlin.ir.util.parentClassOrNull
44
45
import org.jetbrains.kotlin.ir.util.primaryConstructor
45
46
import org.jetbrains.kotlin.ir.util.render
46
47
import 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
47
51
import org.jetbrains.kotlin.load.java.sources.JavaSourceElement
52
+ import org.jetbrains.kotlin.load.java.structure.JavaAnnotation
48
53
import org.jetbrains.kotlin.load.java.structure.JavaClass
54
+ import org.jetbrains.kotlin.load.java.structure.JavaConstructor
49
55
import org.jetbrains.kotlin.load.java.structure.JavaMethod
50
56
import org.jetbrains.kotlin.load.java.structure.JavaTypeParameter
51
57
import org.jetbrains.kotlin.load.java.structure.JavaTypeParameterListOwner
52
58
import org.jetbrains.kotlin.load.java.structure.impl.classFiles.BinaryJavaClass
53
59
import org.jetbrains.kotlin.name.FqName
54
60
import org.jetbrains.kotlin.types.Variance
55
61
import org.jetbrains.kotlin.util.OperatorNameConventions
62
+ import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
56
63
import java.io.Closeable
57
64
import java.util.*
58
65
import kotlin.collections.ArrayList
@@ -887,7 +894,13 @@ open class KotlinFileExtractor(
887
894
extractTypeAccessRecursive(substitutedType, location, id, - 1 )
888
895
}
889
896
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)
891
904
return extractValueParameter(id, substitutedType, vp.name.asString(), location, parent, idx, useValueParameter(vp, parentSourceDeclaration), syntheticParameterNames, vp.isVararg, vp.isNoinline, vp.isCrossinline)
892
905
}
893
906
}
@@ -1337,6 +1350,32 @@ open class KotlinFileExtractor(
1337
1350
logger.warn(" Needed a signature for a type that doesn't have one" )
1338
1351
}
1339
1352
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
+
1340
1379
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 > {
1341
1380
with (" function" , f) {
1342
1381
DeclarationStackAdjuster (f, overriddenAttributes).use {
@@ -1427,8 +1466,10 @@ open class KotlinFileExtractor(
1427
1466
1428
1467
linesOfCode?.linesOfCodeInDeclaration(f, id)
1429
1468
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
+ }
1432
1473
1433
1474
return id
1434
1475
}
0 commit comments