Skip to content

Commit

Permalink
work on inheritance tree. fields in signature reader
Browse files Browse the repository at this point in the history
  • Loading branch information
wagyourtail committed Sep 12, 2024
1 parent 320bf93 commit d545736
Show file tree
Hide file tree
Showing 7 changed files with 171 additions and 58 deletions.
37 changes: 14 additions & 23 deletions build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi
import xyz.wagyourtail.commons.gradle.shadow.ShadowJar
import java.net.URI

plugins {
val kotlinVersion: String by System.getProperties()
kotlin("multiplatform") version kotlinVersion
kotlin("multiplatform") version libs.versions.kotlin.asProvider()
kotlin("plugin.serialization") version libs.versions.kotlin.asProvider()
id("xyz.wagyourtail.commons-gradle") version libs.versions.commons
`maven-publish`
kotlin("plugin.serialization") version kotlinVersion
id("xyz.wagyourtail.commons-gradle") version "1.0.0-SNAPSHOT"
}

allprojects {
Expand All @@ -26,9 +23,6 @@ allprojects {
}
}

val kotlinVersion: String by System.getProperties()
val javaVersion: String by System.getProperties()

kotlin {
jvmToolchain(8)
jvm {
Expand All @@ -52,29 +46,26 @@ kotlin {
sourceSets {
val commonMain by getting {
dependencies {
api("xyz.wagyourtail.commons:commons-kt:1.0.0-SNAPSHOT")
api("io.github.oshai:kotlin-logging:6.0.1")
api("com.squareup.okio:okio:3.7.0")
api("com.sschr15.annotations:jb-annotations-kmp:24.1.0")
api("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.0-RC2")
api("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.2")
api(libs.commons.kt)
api(libs.kotlin.logging)
api(libs.okio)
api(libs.jetbrains.annotations.kmp)
api(libs.kotlin.coroutines)
api(libs.kotlin.serialization.json)
}
}
val commonTest by getting {
dependencies {
implementation(kotlin("test-common"))
implementation(kotlin("test-annotations-common"))
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.8.0-RC2")
implementation(libs.kotlin.coroutines.tests)
}
}
val jvmMain by getting {
dependencies {
// apache compress
api("org.apache.commons:commons-compress:1.26.1")

// asm
api("org.ow2.asm:asm:9.6")
api("org.ow2.asm:asm-tree:9.6")
api(libs.appache.commons.compress)
api(libs.asm)
api(libs.asm.tree)
}
}
val jvmTest by getting {
Expand All @@ -85,7 +76,7 @@ kotlin {
}
val jsMain by getting {
dependencies {
implementation(npm("jszip", "3.10.1"))
implementation(npm("jszip", libs.versions.jszip.get()))
}
}
val jsTest by getting {
Expand Down
8 changes: 3 additions & 5 deletions cli/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,13 @@ plugins {
kotlin("jvm")
}

val cliktVersion: String by project.properties

dependencies {
implementation(project(":"))

implementation("com.github.ajalt.clikt:clikt:$cliktVersion")
implementation(libs.clikt)

implementation("org.slf4j:slf4j-api:2.0.12")
implementation("org.slf4j:slf4j-simple:2.0.10")
implementation(libs.slf4j.api)
implementation(libs.slf4j.simple)

}

Expand Down
5 changes: 0 additions & 5 deletions gradle.properties
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
kotlin.code.style=official

javaVersion=8
systemProp.kotlinVersion=2.0.20

group=xyz.wagyourtail.unimined.mapping
archives_base_name=unimined-mapping-library

version=1.0.0

cliktVersion=4.2.1
38 changes: 38 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
[versions]
asm = "9.7"
okio = "3.7.0"
kotlin = "2.0.20"
commons = "1.0.0-SNAPSHOT"
jb_annotations = "24.1.0"
apache_commons_compress = "1.26.2"
kotlin_serialization = "1.6.2"
kotlin_coroutines = "1.9.0-RC"
kotlin_logging = "6.0.1"
clikt = "4.3.0"
slf4j = "2.0.13"

jszip = "3.10.1"

[libraries]
asm = { module = "org.ow2.asm:asm", version.ref = "asm" }
asm_commons = { module = "org.ow2.asm:asm-commons", version.ref = "asm" }
asm_util = { module = "org.ow2.asm:asm-util", version.ref = "asm" }
asm_analysis = { module = "org.ow2.asm:asm-analysis", version.ref = "asm" }
asm_tree = { module = "org.ow2.asm:asm-tree", version.ref = "asm" }

okio = { module = "com.squareup.okio:okio", version.ref = "okio" }

commons_kt = { module = "xyz.wagyourtail.commons:commons-kt", version.ref = "commons" }

jetbrains_annotations_kmp = { module = "com.sschr15.annotations:jb-annotations-kmp", version.ref = "jb_annotations" }
appache_commons_compress = { module = "org.apache.commons:commons-compress", version.ref = "apache_commons_compress" }

kotlin_coroutines = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlin_coroutines" }
kotlin_coroutines_tests = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "kotlin_coroutines" }
kotlin_serialization_json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlin_serialization" }
kotlin_logging = { module = "io.github.oshai:kotlin-logging", version.ref = "kotlin_logging" }

clikt = { module = "com.github.ajalt.clikt:clikt", version.ref = "clikt" }

slf4j_api = { module = "org.slf4j:slf4j-api", version.ref = "slf4j" }
slf4j_simple = { module = "org.slf4j:slf4j-simple", version.ref = "slf4j" }
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import xyz.wagyourtail.commonskt.utils.translateEscapes
import xyz.wagyourtail.unimined.mapping.EnvType
import xyz.wagyourtail.unimined.mapping.Namespace
import xyz.wagyourtail.unimined.mapping.formats.FormatReader
import xyz.wagyourtail.unimined.mapping.jvms.ext.FieldOrMethodDescriptor
import xyz.wagyourtail.unimined.mapping.jvms.four.three.three.MethodDescriptor
import xyz.wagyourtail.unimined.mapping.jvms.four.two.one.InternalName
import xyz.wagyourtail.unimined.mapping.tree.AbstractMappingTree
Expand Down Expand Up @@ -52,10 +53,16 @@ object SignatureReader : FormatReader {
throw IllegalArgumentException("invalid line: $whitespace")
}
val mName = input.takeNextLiteral()!!.translateEscapes()
val desc = MethodDescriptor.read(input.takeNextLiteral()!!.translateEscapes())
val desc = FieldOrMethodDescriptor.read(input.takeNextLiteral()!!.translateEscapes())
val sig = input.takeNextLiteral()!!.translateEscapes()
cls?.visitMethod(mapOf(ns to (mName to desc)))?.use {
visitSignature(sig, ns, emptySet())
if (desc.isMethodDescriptor()) {
cls?.visitMethod(mapOf(ns to (mName to desc.getMethodDescriptor())))?.use {
visitSignature(sig, ns, emptySet())
}
} else {
cls?.visitField(mapOf(ns to (mName to desc.getFieldDescriptor())))?.use {
visitSignature(sig, ns, emptySet())
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@ import xyz.wagyourtail.unimined.mapping.jvms.four.two.one.InternalName
import xyz.wagyourtail.unimined.mapping.tree.AbstractMappingTree
import xyz.wagyourtail.commonskt.reader.CharReader
import xyz.wagyourtail.commonskt.utils.coroutines.parallelMap
import xyz.wagyourtail.unimined.mapping.tree.node._class.ClassNode

open class InheritanceTree(val tree: AbstractMappingTree, val ns: Namespace) {
open class InheritanceTree(val tree: AbstractMappingTree, val fns: Namespace, val targets: Set<Namespace>) {
val LOGGER = KotlinLogging.logger { }

private val _classes = mutableMapOf<InternalName, ClassInfo>()
Expand Down Expand Up @@ -55,15 +56,15 @@ open class InheritanceTree(val tree: AbstractMappingTree, val ns: Namespace) {
val desc = FieldOrMethodDescriptor.read(data.takeNext()!!)

if (desc.isMethodDescriptor()) {
ci!!._methods.add(
ci!!.methods.add(
MethodInfo(
name,
desc.getMethodDescriptor(),
AccessFlag.toInt(acc.toSet())
)
)
} else {
ci!!._fields.add(
ci!!.fields.add(
FieldInfo(
name,
desc.getFieldDescriptor(),
Expand All @@ -84,7 +85,7 @@ open class InheritanceTree(val tree: AbstractMappingTree, val ns: Namespace) {
append(cls.interfaces.joinToString("\t") { it.toString() })
append("\n")

for (method in cls._methods) {
for (method in cls.methods) {
append("\t")
append(AccessFlag.of(ElementType.METHOD, method.access).joinToString("|") { it.toString() })
append("\t")
Expand All @@ -102,45 +103,106 @@ open class InheritanceTree(val tree: AbstractMappingTree, val ns: Namespace) {
val superType: InternalName?,
val interfaces: List<InternalName>,
) {
val _methods = mutableListOf<MethodInfo>()
val methods: List<MethodInfo> get() = _methods
val methods = mutableListOf<MethodInfo>()

val _fields = mutableListOf<FieldInfo>()
val fields: List<FieldInfo> get() = _fields
val fields = mutableListOf<FieldInfo>()

val superClass by lazy {
this@InheritanceTree.classes[superType]
}

val interfaceClasses by lazy {
interfaces.map { this@InheritanceTree.classes[it] }
interfaces.mapNotNull { this@InheritanceTree.classes[it] }
}

val clsNode by lazy {
tree.getClass(ns, name)
tree.getClass(fns, name)
}

val propagateLock = Mutex()

lateinit var methodData: MutableMap<Pair<String, MethodDescriptor>, Map<Namespace, String>>
lateinit var methodData: MutableMap<MethodInfo, MutableMap<Namespace, String>>

suspend fun propagate(): Map<Pair<String, MethodDescriptor>, Map<Namespace, String>> = coroutineScope {
suspend fun propagate(): Unit = coroutineScope {
if (::methodData.isInitialized) methodData
propagateLock.withLock {
if (::methodData.isInitialized) methodData
methods.filter { md ->

superClass?.propagate()
interfaceClasses.parallelMap { it.propagate() }

for (method in methods) {
clsNode?.visitMethod(mapOf(fns to (method.name to method.descriptor))).visitEnd()
}

val methods = methods.filter { md ->
// modify access
val acc = AccessFlag.of(ElementType.METHOD, md.access).toMutableSet()
val methods = clsNode?.getMethods(ns, md.name, md.descriptor)
val methods = clsNode?.getMethods(fns, md.name, md.descriptor)
methods?.flatMap { it.access }?.forEach {
it.apply(acc)
}
AccessFlag.isInheritable(acc)
}.parallelMap {
}.parallelMap { md ->
val names = (clsNode?.getMethods(fns, md.name, md.descriptor)?.firstOrNull()?.names?.filterKeys { it in targets } ?: emptyMap()).toMutableMap()
// traverse parents, retrieve matching mappings
val superNames = superClass?.methodData?.get(md)
val interfaces = interfaceClasses.map { it to it.methodData[md] }
for (ns in targets) {
if (superNames != null) {
if (names[ns] != superNames[ns]) {
if (superNames[ns] == null) {
superClass!!.overwriteMethodName(md, ns, names[ns]!!)
} else {
names[ns] = superNames.getValue(ns)
}
}
}
for ((intf, intfNames) in interfaces) {
if (intfNames != null) {
if (names[ns] != intfNames[ns] && names[ns] != null) {
intf.overwriteMethodName(md, ns, names[ns]!!)
}
}
}
}
clsNode?.visitMethod(
mapOf(fns to (md.name to md.descriptor)) +
names.mapValues { it.value to null }
)?.visitEnd()
names[fns] = md.name
md to names
}.associate { it }.toMutableMap()

for (method in superClass?.methodData ?: emptyMap()) {
if (method.key !in methods) {
methods[method.key] = method.value
}
}

for (intf in interfaceClasses) {
for (method in intf.methodData) {
if (method.key !in methods) {
methods[method.key] = method.value
}
}
}

methodData = methods
}
}

private fun overwriteMethodName(md: MethodInfo, namespace: Namespace, newName: String) {
if (md in methodData) {
methodData[md]!![namespace] = newName
clsNode?.visitMethod(mapOf(
fns to (md.name to md.descriptor),
namespace to (newName to null)
))?.visitEnd()
superClass?.overwriteMethodName(md, namespace, newName)
for (interfaceClass in interfaceClasses) {
interfaceClass.overwriteMethodName(md, namespace, newName)
}
methodData
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,24 +54,46 @@ class ClassNode(parent: AbstractMappingTree) : MemberNode<ClassVisitor, MappingV
this._names.putAll(names)
}

fun getFields(namespace: Namespace, name: String, desc: FieldDescriptor?): Set<FieldNode> {
val fields = mutableSetOf<FieldNode>()
/**
* because of how resolve works, there should really be a max of 2
* the one that matches best will be first.
* ie, if desc is not-null, it'll put the match with a not-null desc first.
* or vis-versa for null descs.
*/
fun getFields(namespace: Namespace, name: String, desc: FieldDescriptor?): List<FieldNode> {
val fields = mutableListOf<FieldNode>()
for (field in this.fields.resolve()) {
if (field.getName(namespace) == name) {
if (desc == null || !field.hasDescriptor() || field.getFieldDesc(namespace) == desc) {
fields.add(field)
// ensure best match first
if ((desc == null) xor field.hasDescriptor()) {
fields.add(0, field)
} else {
fields.add(field)
}
}
}
}
return fields
}

fun getMethods(namespace: Namespace, name: String, desc: MethodDescriptor?): Set<MethodNode> {
val methods = mutableSetOf<MethodNode>()
/**
* because of how resolve works, there should really be a max of 2
* the one that matches best will be first.
* ie, if desc is not-null, it'll put the match with a not-null desc first.
* or vis-versa for null descs.
*/
fun getMethods(namespace: Namespace, name: String, desc: MethodDescriptor?): List<MethodNode> {
val methods = mutableListOf<MethodNode>()
for (method in this.methods.resolve()) {
if (method.getName(namespace) == name) {
if (desc == null || !method.hasDescriptor() || method.getMethodDesc(namespace) == desc) {
methods.add(method)
// ensure best match first
if ((desc == null) xor method.hasDescriptor()) {
methods.add(0, method)
} else {
methods.add(method)
}
}
}
}
Expand Down

0 comments on commit d545736

Please sign in to comment.