Skip to content

Commit

Permalink
add seal and interface
Browse files Browse the repository at this point in the history
  • Loading branch information
wagyourtail committed Aug 13, 2024
1 parent edd57d5 commit ec9128a
Show file tree
Hide file tree
Showing 13 changed files with 312 additions and 7 deletions.
30 changes: 30 additions & 0 deletions software-engineering/unimined-mapping-format.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ created over the years.
* [access transformer / access mappings](#access)
* [constant uninlining](#constant-group)
* [exceptions](#exceptions)
* [sealed classes](#sealed)
* [interface modification](#interfaces)
2. Must be human-readable
3. Must be relatively easy to parse / write
4. all notations must be able to represent everything legal by the jvms
Expand Down Expand Up @@ -303,6 +305,34 @@ package-private is represented as `package`

Changing method access from private will change `INVOKESPECIAL` to `INVOKEVIRTUAL` for the method.

## Sealed

this can add/remove/clear the classes for sealing, if a sealed list is cleared, the class becomes unsealed.
sealed will be defined as
```
s <action> <child> <ns1 name> <ns2 name> <ns3 name> ...
s c <ns1 name> <ns2 name> <ns3 name> ...
```

where `<ns1 name>`, `<ns2 name>`, `<ns3 name>`, etc are the namespace names to operate on.
if none of the namespaces in the file are just numbers, indexes can be used instead of names.

`<action>` is either `+`, `-` or `c` for add, remove, and clear, respectively.
`<child>` is the internal name of a class to add/remove to the sealed list in `<ns1 name>`'s names.
this argument is not included on `c`

## Interfaces

this can add/remove an interface from the interfaces list for a class/interface.
interfaces will be defined as
`j <action> <ifname> <ns1 name> <ns2 name> <ns3 name> ...`

where `<ns1 name>`, `<ns2 name>`, `<ns3 name>`, etc are the namespace names to operate on.
if none of the namespaces in the file are just numbers, indexes can be used instead of names.

where `<action>` is either `+` or `-` for add and remove respectively.
`<ifname>` is the internal name of an interface in `<ns1 name>`'s names.

## Constant Group

constant uninlining targets constants used when setting the value of methods/fields.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ object UMFReader : FormatReader {
if (input.exhausted()) break
throw IllegalArgumentException("Invalid entry type ${token.second}")
}
val entryType = EntryType.byKey[token.second.first()] ?: throw IllegalArgumentException("Invalid entry type ${token.second}")
val entryType = EntryType.byKey[token.second.first().lowercaseChar()] ?: throw IllegalArgumentException("Invalid entry type ${token.second}")
while (indent <= indentStack.last()) {
visitStack.removeLast()?.visitEnd()
indentStack.removeLast()
Expand Down Expand Up @@ -295,7 +295,6 @@ object UMFReader : FormatReader {
last as SignatureParentVisitor<*>?
last?.visitSignature(sig, names.next(), names.asSequence().toSet())
}
EntryType.EXTENSION -> TODO()
}
if (next != null) {
visitStack.add(next)
Expand Down Expand Up @@ -327,8 +326,9 @@ object UMFReader : FormatReader {
CONSTANT_GROUP('u'),
CONSTANT('n'),
CONSTANT_TARGET('t'),
EXTENSION('e'),
COMMENT('#'),
INTERFACE('j'),
SEAL('s')
;

companion object {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package xyz.wagyourtail.unimined.mapping.tree.node

import xyz.wagyourtail.unimined.mapping.Namespace
import xyz.wagyourtail.unimined.mapping.jvms.four.two.one.InternalName
import xyz.wagyourtail.unimined.mapping.visitor.ClassVisitor
import xyz.wagyourtail.unimined.mapping.visitor.InterfaceVisitor
import xyz.wagyourtail.unimined.mapping.visitor.InterfacesType

class InterfaceNode(parent: BaseNode<ClassVisitor, *>?, val type: InterfacesType, val name: InternalName, val baseNs: Namespace): BaseNode<InterfaceVisitor, ClassVisitor>(parent), InterfaceVisitor {
private val _namespaces: MutableSet<Namespace> = mutableSetOf()
val namespaces: Set<Namespace> get() = _namespaces

fun addNamespaces(namespaces: Set<Namespace>) {
root.mergeNs(namespaces)
_namespaces.addAll(namespaces)
}

override fun acceptOuter(visitor: ClassVisitor, nsFilter: Collection<Namespace>): InterfaceVisitor? {
return visitor.visitInterface(type, name, baseNs, namespaces)
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package xyz.wagyourtail.unimined.mapping.tree.node

import xyz.wagyourtail.unimined.mapping.Namespace
import xyz.wagyourtail.unimined.mapping.jvms.four.two.one.InternalName
import xyz.wagyourtail.unimined.mapping.visitor.ClassVisitor
import xyz.wagyourtail.unimined.mapping.visitor.SealVisitor
import xyz.wagyourtail.unimined.mapping.visitor.SealedType

class SealNode(parent: BaseNode<ClassVisitor, *>?, val type: SealedType, val name: InternalName?, val baseNs: Namespace): BaseNode<SealVisitor, ClassVisitor>(parent), SealVisitor {
private val _namespaces: MutableSet<Namespace> = mutableSetOf()
val namespaces: Set<Namespace> get() = _namespaces

fun addNamespaces(namespaces: Set<Namespace>) {
root.mergeNs(namespaces)
_namespaces.addAll(namespaces)
}

override fun acceptOuter(visitor: ClassVisitor, nsFilter: Collection<Namespace>): SealVisitor? {
return visitor.visitSeal(type, name, baseNs, namespaces)
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ import xyz.wagyourtail.unimined.mapping.jvms.four.three.three.MethodDescriptor
import xyz.wagyourtail.unimined.mapping.jvms.four.three.two.FieldDescriptor
import xyz.wagyourtail.unimined.mapping.jvms.four.two.one.InternalName
import xyz.wagyourtail.unimined.mapping.tree.AbstractMappingTree
import xyz.wagyourtail.unimined.mapping.tree.node.InterfaceNode
import xyz.wagyourtail.unimined.mapping.tree.node.LazyResolvables
import xyz.wagyourtail.unimined.mapping.tree.node.SealNode
import xyz.wagyourtail.unimined.mapping.tree.node.SignatureNode
import xyz.wagyourtail.unimined.mapping.tree.node._class.member.FieldNode
import xyz.wagyourtail.unimined.mapping.tree.node._class.member.MemberNode
Expand All @@ -19,8 +21,11 @@ import xyz.wagyourtail.unimined.mapping.util.mapNotNullValues
import xyz.wagyourtail.unimined.mapping.visitor.*

class ClassNode(parent: AbstractMappingTree) : MemberNode<ClassVisitor, MappingVisitor>(parent), ClassVisitor {
private val _names: MutableMap<Namespace, InternalName?> = mutableMapOf()
private val _signatures: MutableSet<SignatureNode<ClassVisitor>> = mutableSetOf()
private val _names = mutableMapOf<Namespace, InternalName?>()
private val _signatures = mutableSetOf<SignatureNode<ClassVisitor>>()
private val _inners = mutableMapOf<InnerClassNode.InnerType, InnerClassNode>()
private val _interfaces = mutableSetOf<InterfaceNode>()
private val _seals = mutableSetOf<SealNode>()

val signatures: Set<SignatureNode<ClassVisitor>> get() = _signatures

Expand All @@ -36,7 +41,11 @@ class ClassNode(parent: AbstractMappingTree) : MemberNode<ClassVisitor, MappingV
MethodNode(this)
}

val inners = mutableMapOf<InnerClassNode.InnerType, InnerClassNode>()
val inners: Map<InnerClassNode.InnerType, InnerClassNode> get() = _inners

val interfaces: Set<InterfaceNode> get() = _interfaces

val seals: Set<SealNode> get() = _seals

fun getName(namespace: Namespace) = _names[namespace]

Expand Down Expand Up @@ -95,6 +104,25 @@ class ClassNode(parent: AbstractMappingTree) : MemberNode<ClassVisitor, MappingV
wildcards.addUnresolved(this)
}

override fun visitSeal(type: SealedType, name: InternalName?, baseNs: Namespace, namespaces: Set<Namespace>): SealVisitor? {
val seal = SealNode(this, type, name, baseNs)
seal.addNamespaces(namespaces)
_seals.add(seal)
return seal
}

override fun visitInterface(
type: InterfacesType,
name: InternalName,
baseNs: Namespace,
namespaces: Set<Namespace>
): InterfaceVisitor? {
val intf = InterfaceNode(this, type, name, baseNs)
intf.addNamespaces(namespaces)
_interfaces.add(intf)
return intf
}

override fun visitInnerClass(
type: InnerClassNode.InnerType,
names: Map<Namespace, Pair<String, FullyQualifiedName?>>
Expand All @@ -103,7 +131,7 @@ class ClassNode(parent: AbstractMappingTree) : MemberNode<ClassVisitor, MappingV
val inner = if (type in inners) {
inners.getValue(type)
} else {
InnerClassNode(this, type).also { inners[type] = it }
InnerClassNode(this, type).also { _inners[type] = it }
}
inner.setNames(names.mapValues { it.value.first })
inner.setTargets(names.mapNotNullValues { it.value.second })
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,17 @@ enum class ExceptionType {
REMOVE
}

enum class SealedType {
ADD,
REMOVE,
CLEAR
}

enum class InterfacesType {
ADD,
REMOVE
}

interface PackageVisitor : AnnotationParentVisitor<PackageVisitor>, JavadocParentNode<PackageVisitor>

interface ClassVisitor : MemberVisitor<ClassVisitor>, SignatureParentVisitor<ClassVisitor> {
Expand All @@ -95,6 +106,10 @@ interface ClassVisitor : MemberVisitor<ClassVisitor>, SignatureParentVisitor<Cla
fun visitInnerClass(type: InnerClassNode.InnerType, names: Map<Namespace, Pair<String, FullyQualifiedName?>>): InnerClassVisitor?

fun visitWildcard(type: WildcardNode.WildcardType, descs: Map<Namespace, FieldOrMethodDescriptor>): WildcardVisitor?

fun visitSeal(type: SealedType, name: InternalName?, baseNs: Namespace, namespaces: Set<Namespace>): SealVisitor?

fun visitInterface(type: InterfacesType, name: InternalName, baseNs: Namespace, namespaces: Set<Namespace>): InterfaceVisitor?
}

interface InvokableVisitor<T: InvokableVisitor<T>> : MemberVisitor<T>, SignatureParentVisitor<T> {
Expand Down Expand Up @@ -141,3 +156,7 @@ interface TargetVisitor : BaseVisitor<TargetVisitor>

interface InnerClassVisitor : AccessParentVisitor<InnerClassVisitor>

interface SealVisitor : BaseVisitor<SealVisitor>

interface InterfaceVisitor : BaseVisitor<InterfaceVisitor>

Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,22 @@ open class Delegator(delegator: Delegator? = null) {
visitEnd(delegate)
}

open fun visitInterface(delegate: ClassVisitor, type: InterfacesType, name: InternalName, baseNs: Namespace, namespaces: Set<Namespace>): InterfaceVisitor? {
return delegate.visitInterface(type, name, baseNs, namespaces)?.let { DelegateInterfaceVisitor(it, delegator) }
}

open fun visitInterfaceEnd(delegate: InterfaceVisitor) {
visitEnd(delegate)
}

open fun visitSeal(delegate: ClassVisitor, type: SealedType, name: InternalName?, baseNs: Namespace, namespaces: Set<Namespace>): SealVisitor? {
return delegate.visitSeal(type, name, baseNs, namespaces)?.let { DelegateSealVisitor(it, delegator) }
}

open fun visitSealEnd(delegate: SealVisitor) {
visitEnd(delegate)
}

open fun visitParameter(delegate: InvokableVisitor<*>, index: Int?, lvOrd: Int?, names: Map<Namespace, String>): ParameterVisitor? {
return delegate.visitParameter(index, lvOrd, names)?.let { DelegateParameterVisitor(it, delegator) }
}
Expand Down Expand Up @@ -372,6 +388,19 @@ open class DelegateClassVisitor(delegate: ClassVisitor, delegator: Delegator) :
return delegator.visitWildcard(delegate, type, descs)
}

override fun visitSeal(type: SealedType, name: InternalName?, baseNs: Namespace, namespaces: Set<Namespace>): SealVisitor? {
return delegator.visitSeal(delegate, type, name, baseNs, namespaces)
}

override fun visitInterface(
type: InterfacesType,
name: InternalName,
baseNs: Namespace,
namespaces: Set<Namespace>
): InterfaceVisitor? {
return delegator.visitInterface(delegate, type, name, baseNs, namespaces)
}

override fun visitJavadoc(value: String, baseNs: Namespace, namespaces: Set<Namespace>): JavadocVisitor? {
return delegator.visitClassJavadoc(delegate, value, baseNs, namespaces)
}
Expand Down Expand Up @@ -675,3 +704,19 @@ open class DelegateInnerClassVisitor(delegate: InnerClassVisitor, delegator: Del
}

}

open class DelegateSealVisitor(delegate: SealVisitor, delegator: Delegator): DelegateBaseVisitor<SealVisitor>(delegate, delegator), SealVisitor {

override fun visitEnd() {
delegator.visitSealEnd(delegate)
}

}

open class DelegateInterfaceVisitor(delegate: InterfaceVisitor, delegator: Delegator): DelegateBaseVisitor<InterfaceVisitor>(delegate, delegator), InterfaceVisitor {

override fun visitEnd() {
delegator.visitInterfaceEnd(delegate)
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,32 @@ private class MetadataCopyVisitor(val from: Namespace, val to: Set<Namespace>, v
return super.visitSignature(delegate, value, baseNs, namespaces)
}

override fun visitInterface(
delegate: ClassVisitor,
type: InterfacesType,
name: InternalName,
baseNs: Namespace,
namespaces: Set<Namespace>
): InterfaceVisitor? {
if (baseNs == from || from in namespaces) {
return super.visitInterface(delegate, type, name, baseNs, namespaces + to)
}
return super.visitInterface(delegate, type, name, baseNs, namespaces)
}

override fun visitSeal(
delegate: ClassVisitor,
type: SealedType,
name: InternalName?,
baseNs: Namespace,
namespaces: Set<Namespace>
): SealVisitor? {
if (baseNs == from || from in namespaces) {
return super.visitSeal(delegate, type, name, baseNs, namespaces + to)
}
return super.visitSeal(delegate, type, name, baseNs, namespaces)
}

override fun visitConstantGroup(
delegate: MappingVisitor,
type: ConstantGroupNode.InlineType,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,28 @@ open class MultiClassVisitor(visitors: List<ClassVisitor>) : MultiMemberVisitor<
return MultiWildcardVisitor(visitors)
}

override fun visitSeal(
type: SealedType,
name: InternalName?,
baseNs: Namespace,
namespaces: Set<Namespace>
): SealVisitor? {
val visitors = visitors.mapNotNull { it.visitSeal(type, name, baseNs, namespaces) }
if (visitors.isEmpty()) return null
return MultiSealVisitor(visitors)
}

override fun visitInterface(
type: InterfacesType,
name: InternalName,
baseNs: Namespace,
namespaces: Set<Namespace>
): InterfaceVisitor? {
val visitors = visitors.mapNotNull { it.visitInterface(type, name, baseNs, namespaces) }
if (visitors.isEmpty()) return null
return MultiInterfaceVisitor(visitors)
}

}

open class MultiMethodVisitor(visitors: List<MethodVisitor>): MultiMemberVisitor<MethodVisitor>(visitors), MethodVisitor, SignatureParentVisitor<MethodVisitor> by MultiSignatureParentVisitor(visitors) {
Expand Down Expand Up @@ -248,3 +270,6 @@ open class MultiTargetVisitor(visitors: List<TargetVisitor>): MultiBaseVisitor<T

open class MultiInnerClassVisitor(visitors: List<InnerClassVisitor>): MultiAccessParentVisitor<InnerClassVisitor>(visitors), InnerClassVisitor

open class MultiSealVisitor(visitors: List<SealVisitor>): MultiBaseVisitor<SealVisitor>(visitors), SealVisitor

open class MultiInterfaceVisitor(visitors: List<InterfaceVisitor>): MultiBaseVisitor<InterfaceVisitor>(visitors), InterfaceVisitor
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,28 @@ class NamespaceRecordingDelegate(val recorder: (Set<Namespace>) -> Unit) : Deleg
return super.visitInnerClass(delegate, type, names)
}

override fun visitSeal(
delegate: ClassVisitor,
type: SealedType,
name: InternalName?,
baseNs: Namespace,
namespaces: Set<Namespace>
): SealVisitor? {
recorder(namespaces + baseNs)
return super.visitSeal(delegate, type, name, baseNs, namespaces)
}

override fun visitInterface(
delegate: ClassVisitor,
type: InterfacesType,
name: InternalName,
baseNs: Namespace,
namespaces: Set<Namespace>
): InterfaceVisitor? {
recorder(namespaces + baseNs)
return super.visitInterface(delegate, type, name, baseNs, namespaces)
}

override fun visitParameter(
delegate: InvokableVisitor<*>,
index: Int?,
Expand Down
Loading

0 comments on commit ec9128a

Please sign in to comment.