From f2ca8e1eff974b5b3ad7102e002c60f1210ac498 Mon Sep 17 00:00:00 2001 From: Him188 Date: Sat, 19 Jun 2021 23:58:27 +0800 Subject: [PATCH] Revert "Fix kt compiler errors (#1159)" This reverts commit b227f719 --- .github/workflows/build.yml | 8 +- .github/workflows/doc.yml | 10 +- .github/workflows/release.yml | 4 +- .../mirai-core-api-compileKotlinAndroid.txt | 5 - .../mirai-core-api-compileKotlinJvm.txt | 5 - build.gradle.kts | 1 - buildSrc/build.gradle.kts | 1 - buildSrc/src/main/kotlin/analyzes/AsmUtil.kt | 61 ++-------- .../kotlin/analyzes/NoSuchMethodAnalyzer.kt | 21 +++- .../kotlin/postktcompile/PostKotlinCompile.kt | 109 ------------------ .../commonMain/kotlin/utils/RemoteFileImpl.kt | 35 ++++++ 11 files changed, 70 insertions(+), 190 deletions(-) delete mode 100644 binary-compatibility-validator/kt-compile-edit/mirai-core-api-compileKotlinAndroid.txt delete mode 100644 binary-compatibility-validator/kt-compile-edit/mirai-core-api-compileKotlinJvm.txt delete mode 100644 buildSrc/src/main/kotlin/postktcompile/PostKotlinCompile.kt diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8755548f8..5a20c43ce 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -22,11 +22,11 @@ jobs: run: ./gradlew clean --scan - name: Build mirai-core series - run: ./gradlew assemble -Pmirai.pkc.check.enable --scan + run: ./gradlew assemble --scan - name: mirai-core Tests run: > - ./gradlew check -Pmirai.pkc.check.enable --scan + ./gradlew check --scan -Dmirai.debug.network.show.all.components=true -Dkotlinx.coroutines.debug=on -Dmirai.debug.network.show.packet.details=true @@ -51,11 +51,11 @@ jobs: run: ./gradlew clean --scan - name: Build all - run: ./gradlew assemble -Pmirai.pkc.check.enable --scan + run: ./gradlew assemble --scan - name: All Tests run: > - ./gradlew check -Pmirai.pkc.check.enable --scan + ./gradlew check --scan -Dmirai.debug.network.show.all.components=true -Dkotlinx.coroutines.debug=on -Dmirai.debug.network.show.packet.details=true \ No newline at end of file diff --git a/.github/workflows/doc.yml b/.github/workflows/doc.yml index db0a20ed2..c1b30efb5 100644 --- a/.github/workflows/doc.yml +++ b/.github/workflows/doc.yml @@ -23,10 +23,10 @@ jobs: - name: chmod -R 777 * run: chmod -R 777 * - - name: Gradle build -Pmirai.pkc.check.enable - run: ./gradlew clean build -Pmirai.pkc.check.enable # if test's failed, don't publish + - name: Gradle build + run: ./gradlew clean build # if test's failed, don't publish - name: Dokka - run: ./gradlew :mirai-core-api:dokkaHtml -Pmirai.pkc.check.enable + run: ./gradlew :mirai-core-api:dokkaHtml - name: GitHub Pages Deploy uses: peaceiris/actions-gh-pages@v3 with: @@ -55,9 +55,9 @@ jobs: - name: chmod -R 777 * run: chmod -R 777 * - name: Gradle build - run: ./gradlew clean build -Pmirai.pkc.check.enable # if test's failed, don't publish + run: ./gradlew clean build # if test's failed, don't publish - name: Dokka - run: ./gradlew :mirai-console:dokkaHtml -Pmirai.pkc.check.enable + run: ./gradlew :mirai-console:dokkaHtml - name: GitHub Pages Deploy uses: peaceiris/actions-gh-pages@v3 with: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 976e69016..9f2a204af 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -58,11 +58,11 @@ jobs: fillBuildConstants --scan - name: Assemble - run: ./gradlew assemble -Pmirai.pkc.check.enable --scan + run: ./gradlew assemble --scan - name: Check run: > - ./gradlew check -Pmirai.pkc.check.enable --scan + ./gradlew check --scan -Dmirai.debug.network.show.all.components=true -Dkotlinx.coroutines.debug=on -Dmirai.debug.network.show.packet.details=true diff --git a/binary-compatibility-validator/kt-compile-edit/mirai-core-api-compileKotlinAndroid.txt b/binary-compatibility-validator/kt-compile-edit/mirai-core-api-compileKotlinAndroid.txt deleted file mode 100644 index 0deec4f7a..000000000 --- a/binary-compatibility-validator/kt-compile-edit/mirai-core-api-compileKotlinAndroid.txt +++ /dev/null @@ -1,5 +0,0 @@ -[net/mamoe/mirai/utils/RemoteFile$isDirectory$1] [invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;] - Change opcode of net/mamoe/mirai/utils/RemoteFile.isDirectory(Lkotlin/coroutines/Continuation;)Ljava/lang/Object; from 183 to 185 -[net/mamoe/mirai/utils/RemoteFile$listFilesCollection$1] [invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;] - Change opcode of net/mamoe/mirai/utils/RemoteFile.listFilesCollection(Lkotlin/coroutines/Continuation;)Ljava/lang/Object; from 183 to 185 -[net/mamoe/mirai/utils/RemoteFile$upload$3] [invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;] - Change opcode of net/mamoe/mirai/utils/RemoteFile.upload(Ljava/io/File;Lnet/mamoe/mirai/utils/RemoteFile$ProgressionCallback;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; from 183 to 185 -[net/mamoe/mirai/utils/RemoteFile$upload$5] [invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;] - Change opcode of net/mamoe/mirai/utils/RemoteFile.upload(Ljava/io/File;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; from 183 to 185 -[net/mamoe/mirai/utils/RemoteFile$uploadAndSend$2] [invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;] - Change opcode of net/mamoe/mirai/utils/RemoteFile.uploadAndSend(Ljava/io/File;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; from 183 to 185 diff --git a/binary-compatibility-validator/kt-compile-edit/mirai-core-api-compileKotlinJvm.txt b/binary-compatibility-validator/kt-compile-edit/mirai-core-api-compileKotlinJvm.txt deleted file mode 100644 index 0deec4f7a..000000000 --- a/binary-compatibility-validator/kt-compile-edit/mirai-core-api-compileKotlinJvm.txt +++ /dev/null @@ -1,5 +0,0 @@ -[net/mamoe/mirai/utils/RemoteFile$isDirectory$1] [invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;] - Change opcode of net/mamoe/mirai/utils/RemoteFile.isDirectory(Lkotlin/coroutines/Continuation;)Ljava/lang/Object; from 183 to 185 -[net/mamoe/mirai/utils/RemoteFile$listFilesCollection$1] [invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;] - Change opcode of net/mamoe/mirai/utils/RemoteFile.listFilesCollection(Lkotlin/coroutines/Continuation;)Ljava/lang/Object; from 183 to 185 -[net/mamoe/mirai/utils/RemoteFile$upload$3] [invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;] - Change opcode of net/mamoe/mirai/utils/RemoteFile.upload(Ljava/io/File;Lnet/mamoe/mirai/utils/RemoteFile$ProgressionCallback;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; from 183 to 185 -[net/mamoe/mirai/utils/RemoteFile$upload$5] [invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;] - Change opcode of net/mamoe/mirai/utils/RemoteFile.upload(Ljava/io/File;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; from 183 to 185 -[net/mamoe/mirai/utils/RemoteFile$uploadAndSend$2] [invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;] - Change opcode of net/mamoe/mirai/utils/RemoteFile.uploadAndSend(Ljava/io/File;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; from 183 to 185 diff --git a/build.gradle.kts b/build.gradle.kts index be00a3231..353827937 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -70,7 +70,6 @@ tasks.register("publishMiraiCoreArtifactsToMavenLocal") { } analyzes.CompiledCodeVerify.run { registerAllVerifyTasks() } -postktcompile.PostKotlinCompile.run { registerForAll(rootProject) } allprojects { group = "net.mamoe" diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 14b06406a..6172a2ab0 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -58,5 +58,4 @@ dependencies { api(asm("commons")) api(gradleApi()) - api("com.googlecode.java-diff-utils:diffutils:" + version("difflib")) } \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/analyzes/AsmUtil.kt b/buildSrc/src/main/kotlin/analyzes/AsmUtil.kt index 628d1dea6..80e7883cb 100644 --- a/buildSrc/src/main/kotlin/analyzes/AsmUtil.kt +++ b/buildSrc/src/main/kotlin/analyzes/AsmUtil.kt @@ -14,60 +14,13 @@ import org.objectweb.asm.Opcodes import org.objectweb.asm.tree.ClassNode import org.objectweb.asm.tree.FieldNode import org.objectweb.asm.tree.MethodNode -import java.io.Closeable import java.io.File import java.io.InputStream -import java.util.zip.ZipFile -@Suppress("DELEGATED_MEMBER_HIDES_SUPERTYPE_OVERRIDE") -class AsmClassesM( - var res: List?, - val map: MutableMap> -) : AbstractMap>(), - MutableMap> by map, - Closeable { - operator fun plusAssign(map: AsmClassesM) { - this.map.putAll(map.map) - val r = res - if (r is MutableList) { - r.addAll(map.res ?: emptyList()) - return - } - res = (res ?: emptyList()) + (map.res ?: emptyList()) - } - - override fun close() { - res?.forEach { it.close() } - res = null - map.clear() - } -} - -typealias AsmClasses = AsmClassesM +typealias AsmClasses = Map +typealias AsmClassesM = MutableMap object AsmUtil { - var cc = 0 - fun File.readLib(): AsmClassesM { - val rs = mutableListOf() - val result: AsmClassesM = AsmClassesM(rs, HashMap()) - if (this.name.endsWith(".jar")) { - val zip = ZipFile(this) - rs.add(zip) - zip.entries().iterator().forEach l@{ entry -> - if (entry.isDirectory) return@l - if (!entry.name.endsWith(".class")) return@l - result[entry.name.removePrefix("/").removeSuffix(".class")] = lazy { - zip.getInputStream(entry).use { it.readClass() } - } - } - } else if (this.isDirectory) { - this.walk().filter { it.isFile && it.extension == "class" }.forEach { f -> - f.readClass().let { result[it.name] = lazyOf(it) } - } - } - return result - } - fun ClassNode.getMethod(name: String, desc: String, isStatic: Boolean): MethodNode? { return methods?.firstOrNull { it.name == name && it.desc == desc && ((it.access and Opcodes.ACC_STATIC) != 0) == isStatic @@ -80,7 +33,7 @@ object AsmUtil { } } - fun File.readClass(): ClassNode = inputStream().buffered().use { it.readClass() } + fun File.readClass(): ClassNode = inputStream().use { it.readClass() } fun InputStream.readClass(): ClassNode { val cnode = ClassNode() @@ -93,7 +46,7 @@ object AsmUtil { if (!this.containsKey(owner)) { ClassLoader.getSystemClassLoader().getResourceAsStream("$owner.class")?.use { val c = it.readClass() - this[c.name] = lazyOf(c) + this[c.name] = c } } } @@ -106,7 +59,7 @@ object AsmUtil { opcode: Int ): Boolean { patchJvmClass(owner) - val c = this[owner]?.value ?: return false + val c = this[owner] ?: return false val isStatic = opcode == Opcodes.GETSTATIC || opcode == Opcodes.PUTSTATIC if (c.getField(name, desc, isStatic) != null) { return true @@ -124,7 +77,7 @@ object AsmUtil { patchJvmClass(owner) when (opcode) { Opcodes.INVOKESTATIC -> { - val c = this[owner]?.value ?: return false + val c = this[owner] ?: return false return c.getMethod(name, desc, true) != null } Opcodes.INVOKEINTERFACE, @@ -132,7 +85,7 @@ object AsmUtil { Opcodes.INVOKEVIRTUAL -> { fun loopFind(current: String): Boolean { patchJvmClass(current) - val c = this[current]?.value ?: return false + val c = this[current] ?: return false if (c.getMethod(name, desc, false) != null) return true c.superName?.let { if (loopFind(it)) { diff --git a/buildSrc/src/main/kotlin/analyzes/NoSuchMethodAnalyzer.kt b/buildSrc/src/main/kotlin/analyzes/NoSuchMethodAnalyzer.kt index 68c696830..e7f5db256 100644 --- a/buildSrc/src/main/kotlin/analyzes/NoSuchMethodAnalyzer.kt +++ b/buildSrc/src/main/kotlin/analyzes/NoSuchMethodAnalyzer.kt @@ -54,22 +54,35 @@ object NoSuchMethodAnalyzer { fun check(classes: Sequence, libs: Sequence) = AsmUtil.run { val analyzer = AndroidApiLevelCheck.Analyzer(emptyMap()) - val asmClasses: AsmClassesM = AsmClassesM(mutableListOf(), HashMap()) + val asmClasses: AsmClassesM = mutableMapOf() libs.forEach { lib -> - asmClasses += lib.readLib() + if (lib.name.endsWith(".jar")) { + ZipFile(lib).use { zip -> + zip.entries().iterator().forEach l@{ entry -> + if (entry.isDirectory) return@l + if (!entry.name.endsWith(".class")) return@l + zip.getInputStream(entry).use { it.readClass() }.let { + asmClasses[it.name] = it + } + } + } + } else if (lib.isDirectory) { + lib.walk().filter { it.isFile && it.extension == "class" }.forEach { f -> + f.readClass().let { asmClasses[it.name] = it } + } + } } classes.map { it.walk() }.flatten().filter { it.isFile } .filter { it.extension == "class" } .map { it.readClass() to it } .onEach { (c, _) -> - asmClasses[c.name] = lazyOf(c) + asmClasses[c.name] = c }.toList().forEach { (classNode, file) -> analyzer.file = file classNode.methods?.forEach { method -> analyzeMethod(analyzer, method, asmClasses) } } - asmClasses.close() if (analyzer.reported) { error("Verify failed") } diff --git a/buildSrc/src/main/kotlin/postktcompile/PostKotlinCompile.kt b/buildSrc/src/main/kotlin/postktcompile/PostKotlinCompile.kt deleted file mode 100644 index e5915b9ec..000000000 --- a/buildSrc/src/main/kotlin/postktcompile/PostKotlinCompile.kt +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright 2019-2021 Mamoe Technologies and contributors. - * - * 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证. - * Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link. - * - * https://github.com/mamoe/mirai/blob/master/LICENSE - */ - -package postktcompile - -import analyzes.* -import difflib.DiffUtils -import org.gradle.api.Project -import org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompileTool -import org.objectweb.asm.ClassWriter -import org.objectweb.asm.Opcodes -import org.objectweb.asm.tree.ClassNode -import org.objectweb.asm.tree.MethodInsnNode -import java.io.File - -object PostKotlinCompile { - private fun AsmClasses.canAccessInterface(from: ClassNode, to: String): Boolean { - fun scan(current: ClassNode): Boolean { - if (current.name == to) return true - if (current.superName == to) return true - current.interfaces?.forEach { itf -> - if (scan(get(itf)?.value ?: return@forEach)) return true - } - return false - } - return scan(from) - } - - fun fixKtClass(dir: File, libs: Set, logs: MutableList) = AsmUtil.run { - val asmClasses: AsmClassesM = AsmClassesM(mutableListOf(), HashMap()) - dir.walk().filter { - it.isFile && it.extension == "class" - }.forEach { f -> - f.readClass().let { asmClasses[it.name] = lazyOf(it) } - } - val classes = asmClasses.values.toList() - libs.forEach { asmClasses += it.readLib() } - - classes.forEach { klassLazy -> - val klass = klassLazy.value - var edited = false - klass.methods?.forEach { method -> - method.instructions?.forEach { insn -> - if (insn is MethodInsnNode) { - if (insn.itf && insn.opcode != Opcodes.INVOKEINTERFACE && insn.opcode != Opcodes.INVOKESTATIC) { - if (!asmClasses.canAccessInterface(klass, insn.owner)) { - // println("${klass.name} . ${method.name}${method.desc}, ${insn.owner}.${insn.name}${insn.desc} (${insn.opcode})") - edited = true - logs.add( - "[${klass.name}] [${method.name}${method.desc}] - Change opcode of ${insn.owner}.${insn.name}${insn.desc} from ${insn.opcode} to ${Opcodes.INVOKEINTERFACE}" - ) - insn.opcode = Opcodes.INVOKEINTERFACE - } - } - } - } - } - if (edited) { - dir.resolve("${klass.name}.class").writeBytes( - ClassWriter(0).also { klass.accept(it) }.toByteArray() - ) - } - } - asmClasses.close() - } - - fun registerForAll(rootProject: Project) { - val checkEnabled = rootProject.hasProperty("mirai.pkc.check.enable") - val validator = rootProject.file("binary-compatibility-validator/kt-compile-edit") - rootProject.subprojects { - val subp: Project = this@subprojects - subp.tasks.withType(AbstractKotlinCompileTool::class.java) { - val task: AbstractKotlinCompileTool<*> = this@withType - task.doLast { - val logFile = validator.resolve("${subp.name.replace(":", "_")}-${task.name}.txt") - val logs = mutableListOf() - println("$task: Pre classes patching......") - task.outputs.files.toList().forEach { f -> - println("$task: Patching $f") - fixKtClass(f, task.classpath.files, logs) - } - println("$task: Kotlin compiled classes fix completed.") - val oldLog = if (logFile.isFile) logFile.readText().trim().lines() else emptyList() - val newLog = logs.sorted() - if (newLog == oldLog) return@doLast - val patch = DiffUtils.diff(oldLog, newLog) - - val diff = DiffUtils.generateUnifiedDiff(logFile.name, logFile.name + ".rebuild", oldLog, patch, 3) - logFile.parentFile.mkdirs() - if (checkEnabled || newLog.isNotEmpty()) { // Kotlin classes not recompiled. - logFile.writeText(newLog.joinToString("\n", postfix = "\n")) - } - val diffMsg = diff.joinToString("\n") - if (checkEnabled) { - error(diffMsg) - } else { - println(diffMsg) - } - } - } - } - } -} diff --git a/mirai-core/src/commonMain/kotlin/utils/RemoteFileImpl.kt b/mirai-core/src/commonMain/kotlin/utils/RemoteFileImpl.kt index eaad18b4c..284cb5e33 100644 --- a/mirai-core/src/commonMain/kotlin/utils/RemoteFileImpl.kt +++ b/mirai-core/src/commonMain/kotlin/utils/RemoteFileImpl.kt @@ -29,7 +29,9 @@ import net.mamoe.mirai.message.MessageReceipt import net.mamoe.mirai.message.data.FileMessage import net.mamoe.mirai.message.data.sendTo import net.mamoe.mirai.utils.* +import net.mamoe.mirai.utils.ExternalResource.Companion.toExternalResource import net.mamoe.mirai.utils.RemoteFile.Companion.ROOT_PATH +import java.io.File import java.util.* import kotlin.contracts.contract @@ -188,6 +190,9 @@ internal class RemoteFileImpl( } override suspend fun isFile(): Boolean = this.getFileFolderInfo().checkExists(this.path).isFile + + // compiler bug + override suspend fun isDirectory(): Boolean = !isFile() override suspend fun length(): Long = this.getFileFolderInfo().checkExists(this.path).size override suspend fun exists(): Boolean = this.getFileFolderInfo() != null override suspend fun getInfo(): RemoteFile.FileInfo? { @@ -250,6 +255,9 @@ internal class RemoteFileImpl( } } + // compiler bug + override suspend fun listFilesCollection(): List = listFiles().toList() + @Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") @OptIn(JavaFriendlyAPI::class) override suspend fun listFilesIterator(lazy: Boolean): Iterator { @@ -316,6 +324,9 @@ internal class RemoteFileImpl( return null } + // compiler bug + override suspend fun resolveById(id: String): RemoteFile? = resolveById(id, deep = true) + override fun resolveSibling(relative: String): RemoteFileImpl { val parent = this.parent if (parent == null) { @@ -523,11 +534,35 @@ internal class RemoteFileImpl( ) } + // compiler bug + override suspend fun upload(resource: ExternalResource): FileMessage { + return upload(resource, null) + } + + // compiler bug + override suspend fun upload(file: File, callback: RemoteFile.ProgressionCallback?): FileMessage = + file.toExternalResource().use { upload(it, callback) } + + //compiler bug + override suspend fun upload(file: File): FileMessage { + // Dear compiler: + // + // Please generate invokeinterface. + // + // Yours Sincerely + // Him188 + return file.toExternalResource().use { upload(it) } + } + override suspend fun uploadAndSend(resource: ExternalResource): MessageReceipt { @Suppress("DEPRECATION") return upload(resource).sendTo(contact) } + // compiler bug + override suspend fun uploadAndSend(file: File): MessageReceipt = + file.toExternalResource().use { uploadAndSend(it) } + // override suspend fun writeSession(resource: ExternalResource): FileUploadSession { // }