Skip to content

Commit 3b5b121

Browse files
authored
Merge pull request github#11553 from smowton/smowton/fix/kotlin-synthetic-noarg-constructor
Kotlin: Extract a no-arg constuctor whenever a Kotlin class has default values for all parameters
2 parents f0ac59b + 407e4cd commit 3b5b121

File tree

4 files changed

+33
-3
lines changed

4 files changed

+33
-3
lines changed

java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1049,8 +1049,6 @@ open class KotlinFileExtractor(
10491049
private val jvmOverloadsFqName = FqName("kotlin.jvm.JvmOverloads")
10501050

10511051
private fun extractGeneratedOverloads(f: IrFunction, parentId: Label<out DbReftype>, maybeSourceParentId: Label<out DbReftype>?, extractBody: Boolean, extractMethodAndParameterTypeAccesses: Boolean, typeSubstitution: TypeSubstitution?, classTypeArgsIncludingOuterClasses: List<IrTypeArgument>?) {
1052-
if (!f.hasAnnotation(jvmOverloadsFqName))
1053-
return
10541052

10551053
fun extractGeneratedOverload(paramList: List<IrValueParameter?>) {
10561054
val overloadParameters = paramList.filterNotNull()
@@ -1096,6 +1094,22 @@ open class KotlinFileExtractor(
10961094
}
10971095
}
10981096

1097+
if (!f.hasAnnotation(jvmOverloadsFqName)) {
1098+
if (f is IrConstructor &&
1099+
f.valueParameters.isNotEmpty() &&
1100+
f.valueParameters.all { it.defaultValue != null } &&
1101+
f.parentClassOrNull?.let {
1102+
// Don't create a default constructor for an annotation class, or a class that explicitly declares a no-arg constructor.
1103+
!it.isAnnotationClass &&
1104+
it.declarations.none { d -> d is IrConstructor && d.valueParameters.isEmpty() }
1105+
} == true) {
1106+
// Per https://kotlinlang.org/docs/classes.html#creating-instances-of-classes, a single default overload gets created specifically
1107+
// when we have all default parameters, regardless of `@JvmOverloads`.
1108+
extractGeneratedOverload(f.valueParameters.map { _ -> null })
1109+
}
1110+
return
1111+
}
1112+
10991113
val paramList: MutableList<IrValueParameter?> = f.valueParameters.toMutableList()
11001114
for (n in (f.valueParameters.size - 1) downTo 0) {
11011115
if (f.valueParameters[n].defaultValue != null) {
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
@AllDefaultsAnnotation
2+
public class User {
3+
4+
public static void test() { new AllDefaultsConstructor(); new AllDefaultsExplicitNoargConstructor(); }
5+
6+
}

java/ql/integration-tests/all-platforms/kotlin/jvmoverloads-external-class/test.kt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,13 @@ public class Test {
33
@JvmOverloads fun f(x: Int = 0, y: Int) { }
44

55
}
6+
7+
public class AllDefaultsConstructor(val x: Int = 1, val y: Int = 2) { }
8+
9+
public annotation class AllDefaultsAnnotation(val x: Int = 1, val y: Int = 2) { }
10+
11+
public class AllDefaultsExplicitNoargConstructor(val x: Int = 1, val y: Int = 2) {
12+
13+
constructor() : this(3, 4) { }
14+
15+
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
from create_database_utils import *
22

33
os.mkdir('bin')
4-
run_codeql_database_create(["kotlinc test.kt -d bin", "kotlinc user.kt -cp bin"], lang="java")
4+
run_codeql_database_create(["kotlinc test.kt -d bin", "kotlinc user.kt -cp bin", "javac User.java -cp bin"], lang="java")

0 commit comments

Comments
 (0)