From 11251a93ac7370a2ca475394c0282cd5e097fb5a Mon Sep 17 00:00:00 2001 From: Ivan Gavrilovic Date: Fri, 26 Jun 2020 20:51:58 +0100 Subject: [PATCH] KAPT: Fix serialization of class structure data When serializing ClasspathEntryData, ids assigned to types were incorrect, resulting in corrupt data when deserializing files. This happened if there were dependencies between classes. Fixes KT-39876 Test: ClasspathAnalyzerTest --- .../kapt/incremental/ClasspathAnalyzer.kt | 5 +++- .../kapt/incremental/ClasspathAnalyzerTest.kt | 29 +++++++++++++++++-- 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/incremental/ClasspathAnalyzer.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/incremental/ClasspathAnalyzer.kt index 403285cba0a..6366f939195 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/incremental/ClasspathAnalyzer.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/incremental/ClasspathAnalyzer.kt @@ -108,6 +108,7 @@ class ClasspathEntryData : Serializable { @Transient var classAbiHash = mutableMapOf() + @Transient var classDependencies = mutableMapOf() @@ -118,7 +119,9 @@ class ClasspathEntryData : Serializable { val names = LinkedHashMap() sortedClassDependencies.forEach { - names[it.key] = names.size + if (it.key !in names) { + names[it.key] = names.size + } it.value.abiTypes.forEach { type -> if (type !in names) names[type] = names.size } diff --git a/libraries/tools/kotlin-gradle-plugin/src/test/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/incremental/ClasspathAnalyzerTest.kt b/libraries/tools/kotlin-gradle-plugin/src/test/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/incremental/ClasspathAnalyzerTest.kt index f9dbcf47e32..a441d5c901f 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/test/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/incremental/ClasspathAnalyzerTest.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/test/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/incremental/ClasspathAnalyzerTest.kt @@ -134,9 +134,34 @@ class ClasspathAnalyzerTest { assertTrue(data.classDependencies.isEmpty()) } - private fun emptyClass(internalName: String): ByteArray { + @Test + fun testJarsWithDependenciesWithinClasses() { + val inputJar = tmp.newFile("input.jar").also { jar -> + ZipOutputStream(jar.outputStream()).use { + it.putNextEntry(ZipEntry("test/A.class")) + it.write(emptyClass("test/A", "test/B")) + it.closeEntry() + + it.putNextEntry(ZipEntry("test/B.class")) + it.write(emptyClass("test/B")) + it.closeEntry() + + it.putNextEntry(ZipEntry("test/C.class")) + it.write(emptyClass("test/C")) + it.closeEntry() + } + } + val transform = StructureArtifactTransform().also { it.outputDirectory = tmp.newFolder() } + val outputs = transform.transform(inputJar) + + val data = ClasspathEntryData.ClasspathEntrySerializer.loadFrom(outputs.single()) + assertEquals(setOf("test/A", "test/B", "test/C"), data.classAbiHash.keys) + assertEquals(setOf("test/A", "test/B", "test/C"), data.classDependencies.keys) + } + + private fun emptyClass(internalName: String, superClass: String = "java/lang/Object"): ByteArray { val writer = ClassWriter(Opcodes.API_VERSION) - writer.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC, internalName, null, "java/lang/Object", emptyArray()) + writer.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC, internalName, null, superClass, emptyArray()) return writer.toByteArray() } }