Revert "Fix kt compiler errors (#1159)"

This reverts commit b227f719
This commit is contained in:
Him188 2021-06-19 23:58:27 +08:00
parent 006b63e93e
commit f2ca8e1eff
11 changed files with 70 additions and 190 deletions

View File

@ -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

View File

@ -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:

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -70,7 +70,6 @@ tasks.register("publishMiraiCoreArtifactsToMavenLocal") {
}
analyzes.CompiledCodeVerify.run { registerAllVerifyTasks() }
postktcompile.PostKotlinCompile.run { registerForAll(rootProject) }
allprojects {
group = "net.mamoe"

View File

@ -58,5 +58,4 @@ dependencies {
api(asm("commons"))
api(gradleApi())
api("com.googlecode.java-diff-utils:diffutils:" + version("difflib"))
}

View File

@ -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<Closeable>?,
val map: MutableMap<String, Lazy<ClassNode>>
) : AbstractMap<String, Lazy<ClassNode>>(),
MutableMap<String, Lazy<ClassNode>> by map,
Closeable {
operator fun plusAssign(map: AsmClassesM) {
this.map.putAll(map.map)
val r = res
if (r is MutableList<Closeable>) {
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<String, ClassNode>
typealias AsmClassesM = MutableMap<String, ClassNode>
object AsmUtil {
var cc = 0
fun File.readLib(): AsmClassesM {
val rs = mutableListOf<Closeable>()
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)) {

View File

@ -54,22 +54,35 @@ object NoSuchMethodAnalyzer {
fun check(classes: Sequence<File>, libs: Sequence<File>) = 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")
}

View File

@ -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<File>, logs: MutableList<String>) = 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<String>()
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)
}
}
}
}
}
}

View File

@ -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<RemoteFile> = listFiles().toList()
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
@OptIn(JavaFriendlyAPI::class)
override suspend fun listFilesIterator(lazy: Boolean): Iterator<RemoteFile> {
@ -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<Contact> {
@Suppress("DEPRECATION")
return upload(resource).sendTo(contact)
}
// compiler bug
override suspend fun uploadAndSend(file: File): MessageReceipt<Contact> =
file.toExternalResource().use { uploadAndSend(it) }
// override suspend fun writeSession(resource: ExternalResource): FileUploadSession {
// }