Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,12 @@
package org.spongepowered.asm.mixin.transformer;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

import org.objectweb.asm.tree.InnerClassNode;
import org.spongepowered.asm.logging.ILogger;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.ClassVisitor;
Expand Down Expand Up @@ -57,7 +59,7 @@ final class InnerClassGenerator implements IClassGenerator {
* Information about an inner class instance. Implements {@link Remapper} so
* that it can participate in the remapping process.
*/
static class InnerClassInfo extends Remapper implements ISyntheticClassInfo {
class InnerClassInfo extends Remapper implements ISyntheticClassInfo {

/**
* Mixin which provides this class
Expand Down Expand Up @@ -155,10 +157,21 @@ String getNestHostName() {

void accept(final ClassVisitor classVisitor) throws ClassNotFoundException, IOException {
ClassNode classNode = MixinService.getService().getBytecodeProvider().getClassNode(this.originalName);
this.readInnerClasses(classNode);
classNode.accept(classVisitor);
this.loadCounter++;
}

private void readInnerClasses(ClassNode classNode) {
// Read possibly nested inner classes
for (InnerClassNode inner : classNode.innerClasses) {
if ((inner.outerName != null && this.findRemappedName(inner.outerName) != null)
|| inner.name.startsWith(this.mixin.getClassRef() + "$")) {
InnerClassGenerator.this.registerInnerClass(this.owner, this.targetClassInfo, inner.name);
}
}
}

/**
* Used to remap fields which have been renamed while being applied to
* the target class or by an implementation of IRemapper.
Expand Down Expand Up @@ -198,10 +211,9 @@ public String mapMethodName(String owner, String name, String desc) {
*/
@Override
public String map(String key) {
if (this.originalName.equals(key)) {
return this.name;
} else if (this.ownerName.equals(key)) {
return this.targetClassInfo.getName();
String remappedName = this.findRemappedName(key);
if (remappedName != null) {
return remappedName;
}
return key;
}
Expand All @@ -213,6 +225,15 @@ public String map(String key) {
public String toString() {
return this.name;
}

private String findRemappedName(String originalName) {
if (this.ownerName.equals(originalName)) {
return this.targetClassInfo.getName();
}
return InnerClassGenerator.this.innerClassNames.get(
InnerClassGenerator.innerClassCoordinate(this.owner, this.targetClassInfo, originalName)
);
}

}

Expand Down Expand Up @@ -252,21 +273,6 @@ public void visitSource(String source, String debug) {
av.visitEnd();
}

/* (non-Javadoc)
* @see org.objectweb.asm.commons.RemappingClassAdapter
* #visitInnerClass(java.lang.String, java.lang.String,
* java.lang.String, int)
*/
@Override
public void visitInnerClass(String name, String outerName, String innerName, int access) {
if (name.startsWith(this.info.getOriginalName() + "$")) {
throw new InvalidMixinException(this.info.getOwner(), "Found unsupported nested inner class " + name + " in "
+ this.info.getOriginalName());
}

super.visitInnerClass(name, outerName, innerName, access);
}

}

/**
Expand Down Expand Up @@ -338,7 +344,7 @@ public String getName() {
* @param innerClassName Original inner class name
*/
void registerInnerClass(MixinInfo owner, ClassInfo targetClass, String innerClassName) {
String coordinate = String.format("%s:%s:%s", owner, innerClassName, targetClass.getName());
String coordinate = InnerClassGenerator.innerClassCoordinate(owner, targetClass, innerClassName);
String uniqueName = this.innerClassNames.get(coordinate);
if (uniqueName != null) {
return;
Expand Down Expand Up @@ -421,7 +427,8 @@ private static String getUniqueReference(String originalName, ClassInfo targetCl
if (name.matches("^[0-9]+$")) {
name = "Anonymous";
}
return String.format("%s$%s$%s", targetClass, name, UUID.randomUUID().toString().replace("-", ""));
UUID uuid = UUID.nameUUIDFromBytes(originalName.getBytes(StandardCharsets.UTF_8));
return String.format("%s$%s$%s", targetClass, name, uuid.toString().replace("-", ""));
}

/**
Expand Down Expand Up @@ -457,4 +464,8 @@ private static ClassVisitor createRemappingAdapter(ClassVisitor cv, Remapper rem
return InnerClassGenerator.clRemapper.getConstructor(ClassVisitor.class, Remapper.class).newInstance(cv, remapper);
}

private static String innerClassCoordinate(MixinInfo owner, ClassInfo targetClass, String innerClassName) {
return String.format("%s:%s:%s", owner.getClassRef(), innerClassName, targetClass.getName());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,10 @@
* mixins.
*
* <p>Such tasks as {@link MixinCoprocessorAccessor making accessor mixins
* loadable (and transforming the accessors therein)}, {@link
* MixinCoprocessorSyntheticInner exposing synthetic inner classes to all
* consumers} and {@link MixinCoprocessorNestHost applying nest member
* attributes to nest hosts which may themselves not be mixin targets} are
* handled by different coprocessors.</p>
* loadable (and transforming the accessors therein)}, and {@link
* MixinCoprocessorNestHost applying nest member attributes to nest hosts
* which may themselves not be mixin targets} are handled by different
* coprocessors.</p>
*
* <p>These classes were previously encapsulated in a single companion class
* called <tt>MixinPostProcessor</tt>, but the mixture of responsibilities of
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -224,14 +224,9 @@ class State {
* Interfaces soft-implemented using {@link Implements}
*/
protected final List<InterfaceInfo> softImplements = new ArrayList<InterfaceInfo>();

/**
* Synthetic inner classes
*/
protected final Set<String> syntheticInnerClasses = new HashSet<String>();

/**
* Non-synthetic inner classes
* Inner classes
*/
protected final Set<String> innerClasses = new HashSet<String>();

Expand Down Expand Up @@ -286,10 +281,6 @@ List<? extends InterfaceInfo> getSoftImplements() {
return this.softImplements;
}

Set<String> getSyntheticInnerClasses() {
return this.syntheticInnerClasses;
}

Set<String> getInnerClasses() {
return this.innerClasses;
}
Expand Down Expand Up @@ -420,20 +411,13 @@ void readImplementations(SubType type) {
}

/**
* Read inner class definitions for the class and locate any synthetic
* inner classes so that we can add them to the passthrough set in our
* parent config.
* Read inner class definitions for the class and locate any of our inner classes.
*/
void readInnerClasses() {
for (InnerClassNode inner : this.validationClassNode.innerClasses) {
if ((inner.outerName != null && inner.outerName.equals(this.classInfo.getName()))
|| inner.name.startsWith(this.validationClassNode.name + "$")) {
boolean isStatic = (inner.access & Opcodes.ACC_STATIC) != 0;
boolean isSynthetic = (inner.access & Opcodes.ACC_SYNTHETIC) != 0;

if (isStatic && isSynthetic) {
this.syntheticInnerClasses.add(inner.name);
} else if (!ClassInfo.isMixin(inner.name)) {
if (!ClassInfo.isMixin(inner.name)) {
this.innerClasses.add(inner.name);
}
}
Expand Down Expand Up @@ -466,7 +450,7 @@ class Reloaded extends State {
*/
@Override
protected void validateChanges(SubType type, List<ClassInfo> targetClasses) {
if (!this.syntheticInnerClasses.equals(this.previous.syntheticInnerClasses)) {
if (!this.innerClasses.equals(this.previous.innerClasses)) {
throw new MixinReloadException(MixinInfo.this, "Cannot change inner classes");
}
if (!this.interfaces.equals(this.previous.interfaces)) {
Expand Down Expand Up @@ -1237,16 +1221,9 @@ public List<String> getTargetClasses() {
List<InterfaceInfo> getSoftImplements() {
return Collections.<InterfaceInfo>unmodifiableList(this.getState().getSoftImplements());
}

/**
* Get the synthetic inner classes for this mixin
*/
Set<String> getSyntheticInnerClasses() {
return Collections.<String>unmodifiableSet(this.getState().getSyntheticInnerClasses());
}

/**
* Get the user-defined inner classes for this mixin
* Get the inner classes for this mixin
*/
Set<String> getInnerClasses() {
return Collections.<String>unmodifiableSet(this.getState().getInnerClasses());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,6 @@ public String getErrorMessage(IMixinInfo mixin, IMixinConfig config, Phase phase
this.hotSwapper = hotSwapper;

this.coprocessors.add(new MixinCoprocessorPassthrough());
this.coprocessors.add(new MixinCoprocessorSyntheticInner());
this.coprocessors.add(new MixinCoprocessorAccessor(this.sessionId));
this.coprocessors.add(nestHostCoprocessor);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -637,6 +637,8 @@ private void transformFieldRef(MethodNode method, Iterator<AbstractInsnNode> ite
if (field != null && field.isRenamed() && field.getOriginalName().equals(fieldRef.getName()) && field.isStatic()) {
fieldRef.setName(field.getName());
}
} else if (this.innerClasses.containsKey(fieldRef.getOwner())) {
fieldRef.setOwner(this.innerClasses.get(fieldRef.getOwner()));
} else {
if (ClassInfo.isMixin(fieldRef.getOwner())) {
ClassInfo fieldOwner = ClassInfo.forName(fieldRef.getOwner());
Expand Down