diff --git a/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/stubs/ClassFileToSourceStubConverter.kt b/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/stubs/ClassFileToSourceStubConverter.kt index 410b04ee362..8b5c25f2de3 100644 --- a/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/stubs/ClassFileToSourceStubConverter.kt +++ b/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/stubs/ClassFileToSourceStubConverter.kt @@ -467,36 +467,49 @@ class ClassFileToSourceStubConverter(val kaptContext: KaptContextForStubGenerati .takeIf { it.isNotEmpty() } ?: return Pair(null, emptyList()) - val resolvedSuperTypes = superTypeEntries - .map { it to kaptContext.bindingContext[BindingContext.TYPE, it.typeReference] } + val classEntries = mutableListOf() + val interfaceEntries = mutableListOf() + val otherEntries = mutableListOf() - val (resolvedAsClasses, otherSuperTypes) = resolvedSuperTypes - .partition { - it.second?.isError == false - && (it.second?.constructor?.declarationDescriptor as? ClassDescriptor)?.kind == ClassKind.CLASS + for (entry in superTypeEntries) { + val type = kaptContext.bindingContext[BindingContext.TYPE, entry.typeReference] + val classDescriptor = type?.constructor?.declarationDescriptor as? ClassDescriptor + + if (type != null && !type.isError && classDescriptor != null) { + val container = if (classDescriptor.kind == ClassKind.INTERFACE) interfaceEntries else classEntries + container += entry + continue } - if (resolvedAsClasses.size > 1) { + if (entry is KtSuperTypeCallEntry) { + classEntries += entry + continue + } + + otherEntries += entry + } + + for (entry in otherEntries) { + if (classEntries.isEmpty()) { + if (declaration is KtClass && !declaration.isInterface() && declaration.hasOnlySecondaryConstructors()) { + classEntries += entry + continue + } + } + + interfaceEntries += entry + } + + if (classEntries.size > 1) { // Error in user code, several entries were resolved to classes return null - } else if (resolvedAsClasses.size == 1) { - return Pair(resolvedAsClasses.single().first.typeReference, otherSuperTypes.mapNotNull { it.first.typeReference }) } - val (withParenthesis, withoutParenthesis) = superTypeEntries.partition { it is KtSuperTypeCallEntry } + return Pair(classEntries.firstOrNull()?.typeReference, interfaceEntries.mapNotNull { it.typeReference }) + } - if (withParenthesis.size > 1) { - // Error in user code, several entries with super constructor call - return null - } else if (withParenthesis.size == 1) { - return Pair(withParenthesis.single().typeReference, withoutParenthesis.mapNotNull { it.typeReference }) - } - - if (declaration is KtClass && declaration.primaryConstructor == null && declaration.secondaryConstructors.isNotEmpty()) { - return Pair(superTypeEntries.first().typeReference, superTypeEntries.drop(1).mapNotNull { it.typeReference }) - } - - return Pair(null, superTypeEntries.mapNotNull { it.typeReference }) + private fun KtClass.hasOnlySecondaryConstructors(): Boolean { + return primaryConstructor == null && secondaryConstructors.isNotEmpty() } private tailrec fun checkIfValidTypeName(containingClass: ClassNode, type: Type): Boolean { diff --git a/plugins/kapt3/kapt3-compiler/test/org/jetbrains/kotlin/kapt3/test/ClassFileToSourceStubConverterTestGenerated.java b/plugins/kapt3/kapt3-compiler/test/org/jetbrains/kotlin/kapt3/test/ClassFileToSourceStubConverterTestGenerated.java index 62135525f72..90dc1c4e6db 100644 --- a/plugins/kapt3/kapt3-compiler/test/org/jetbrains/kotlin/kapt3/test/ClassFileToSourceStubConverterTestGenerated.java +++ b/plugins/kapt3/kapt3-compiler/test/org/jetbrains/kotlin/kapt3/test/ClassFileToSourceStubConverterTestGenerated.java @@ -369,6 +369,11 @@ public class ClassFileToSourceStubConverterTestGenerated extends AbstractClassFi runTest("plugins/kapt3/kapt3-compiler/testData/converter/repeatableAnnotations.kt"); } + @TestMetadata("secondaryConstructor.kt") + public void testSecondaryConstructor() throws Exception { + runTest("plugins/kapt3/kapt3-compiler/testData/converter/secondaryConstructor.kt"); + } + @TestMetadata("severalPackageParts.kt") public void testSeveralPackageParts() throws Exception { runTest("plugins/kapt3/kapt3-compiler/testData/converter/severalPackageParts.kt"); diff --git a/plugins/kapt3/kapt3-compiler/testData/converter/errorSuperclassCorrectErrorTypes.txt b/plugins/kapt3/kapt3-compiler/testData/converter/errorSuperclassCorrectErrorTypes.txt index b8e5c740f46..01c641b3783 100644 --- a/plugins/kapt3/kapt3-compiler/testData/converter/errorSuperclassCorrectErrorTypes.txt +++ b/plugins/kapt3/kapt3-compiler/testData/converter/errorSuperclassCorrectErrorTypes.txt @@ -176,7 +176,7 @@ package test; import java.lang.System; @kotlin.Metadata() -public final class TFooBar extends Foo implements Bar, test.Intf { +public final class TFooBar extends Foo implements test.Intf, Bar { @org.jetbrains.annotations.NotNull() private final X a = null; @@ -310,7 +310,7 @@ package test; import java.lang.System; @kotlin.Metadata() -public final class TxFooxBarxBaz extends x.Foo implements x.Bar, x.Baz, test.Intf { +public final class TxFooxBarxBaz extends x.Foo implements test.Intf, x.Bar, x.Baz { public TxFooxBarxBaz() { super(); diff --git a/plugins/kapt3/kapt3-compiler/testData/converter/secondaryConstructor.kt b/plugins/kapt3/kapt3-compiler/testData/converter/secondaryConstructor.kt new file mode 100644 index 00000000000..b8f766b0947 --- /dev/null +++ b/plugins/kapt3/kapt3-compiler/testData/converter/secondaryConstructor.kt @@ -0,0 +1,15 @@ +// CORRECT_ERROR_TYPES + +package secondary + +interface Named { + val name: String? +} + +class Product2 : Named { + override var name: String? = null + + constructor(otherName: String) { + this.name = otherName + } +} \ No newline at end of file diff --git a/plugins/kapt3/kapt3-compiler/testData/converter/secondaryConstructor.txt b/plugins/kapt3/kapt3-compiler/testData/converter/secondaryConstructor.txt new file mode 100644 index 00000000000..b032273355c --- /dev/null +++ b/plugins/kapt3/kapt3-compiler/testData/converter/secondaryConstructor.txt @@ -0,0 +1,37 @@ +package secondary; + +import java.lang.System; + +@kotlin.Metadata() +public abstract interface Named { + + @org.jetbrains.annotations.Nullable() + public abstract java.lang.String getName(); +} + +//////////////////// + +package secondary; + +import java.lang.System; + +@kotlin.Metadata() +public final class Product2 implements secondary.Named { + @org.jetbrains.annotations.Nullable() + private java.lang.String name; + + @org.jetbrains.annotations.Nullable() + @java.lang.Override() + public java.lang.String getName() { + return null; + } + + public void setName(@org.jetbrains.annotations.Nullable() + java.lang.String p0) { + } + + public Product2(@org.jetbrains.annotations.NotNull() + java.lang.String otherName) { + super(); + } +}