Skip to content

Commit

Permalink
Overriding methods can return a superclass of the method they override
Browse files Browse the repository at this point in the history
  • Loading branch information
Runemoro committed Jun 20, 2018
1 parent 69e27a0 commit 7719039
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 38 deletions.
31 changes: 1 addition & 30 deletions src/main/java/org/dimdev/javaremapper/GeneratingMapping.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package org.dimdev.javaremapper;

import org.objectweb.asm.Type;

import java.util.Set;

public class GeneratingMapping extends Mapping {
Expand Down Expand Up @@ -61,7 +59,7 @@ public String getMethod(String className, String methodName, String methodDescri
// Don't remap inherited methods, their name is inherited from the parent's mapping
for (String superclass : inheritanceProvider.getAllSuperclasses(className)) {
for (MemberRef ref : inheritanceProvider.getInheritableMethods(superclass)) {
if (methodName.equals(ref.name) && methodDescriptorOverrides(methodDescriptor, ref.descriptor)) {
if (methodName.equals(ref.name) && TypeUtil.methodDescriptorOverrides(inheritanceProvider, methodDescriptor, ref.descriptor)) {
return null;
}
}
Expand All @@ -74,31 +72,4 @@ public String getMethod(String className, String methodName, String methodDescri
}
return result;
}

private boolean methodDescriptorOverrides(String descriptor1, String descriptor2) {
// Check return types
Type ret1 = Type.getReturnType(descriptor1);
Type ret2 = Type.getReturnType(descriptor2);
if (!ret1.equals(ret2) && !inheritanceProvider.getAllSuperclasses(ret1.getClassName()).contains(ret2.getClassName())) {
return false;
}

// Check argument types
Type[] args1 = Type.getArgumentTypes(descriptor1);
Type[] args2 = Type.getArgumentTypes(descriptor2);

if (args1.length != args2.length) return false;

for (int i = 0; i < args1.length; i++) {
String class1 = args1[i].getClassName();
String class2 = args2[i].getClassName();

// Arguments must be the identical in Java, not supertypes
if (!class1.equals(class2)) {
return false;
}
}

return true;
}
}
18 changes: 10 additions & 8 deletions src/main/java/org/dimdev/javaremapper/SimpleRemapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,17 @@ public String mapMethodName(String owner, String name, String desc) {
String newName = mapping.getMethod(owner, name, desc);

for (String superclass : inheritanceProvider.getAllSuperclasses(owner)) {
if (inheritanceProvider.getInheritableMethods(superclass).contains(new MemberRef(name, desc))) {
String inheritedNewName = mapping.getMethod(superclass, name, desc);
if (inheritedNewName != null) {
if (newName != null && !inheritedNewName.equals(newName)) {
System.err.println("Method inheritance problem: " + owner + "." + name + desc +
" inherits " + superclass + "." + name + desc +
" but " + newName + " != " + inheritedNewName);
for (MemberRef ref : inheritanceProvider.getInheritableMethods(superclass)) {
if (name.equals(ref.name) && TypeUtil.methodDescriptorOverrides(inheritanceProvider, desc, ref.descriptor)) {
String inheritedNewName = mapping.getMethod(superclass, name, desc);
if (inheritedNewName != null) {
if (newName != null && !inheritedNewName.equals(newName)) {
System.err.println("Method inheritance problem: " + owner + "." + name + desc +
" inherits " + superclass + "." + name + desc +
" but " + newName + " != " + inheritedNewName);
}
return inheritedNewName;
}
return inheritedNewName;
}
}
}
Expand Down
32 changes: 32 additions & 0 deletions src/main/java/org/dimdev/javaremapper/TypeUtil.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package org.dimdev.javaremapper;

import org.objectweb.asm.Type;

public final class TypeUtil {
public static boolean methodDescriptorOverrides(InheritanceProvider inheritanceProvider, String descriptor1, String descriptor2) {
// Check return types
Type ret1 = Type.getReturnType(descriptor1);
Type ret2 = Type.getReturnType(descriptor2);
if (!ret1.equals(ret2) && !inheritanceProvider.getAllSuperclasses(ret1.getClassName()).contains(ret2.getClassName())) {
return false;
}

// Check argument types
Type[] args1 = Type.getArgumentTypes(descriptor1);
Type[] args2 = Type.getArgumentTypes(descriptor2);

if (args1.length != args2.length) return false;

for (int i = 0; i < args1.length; i++) {
String class1 = args1[i].getClassName();
String class2 = args2[i].getClassName();

// Arguments must be the identical in Java, not supertypes
if (!class1.equals(class2)) {
return false;
}
}

return true;
}
}

0 comments on commit 7719039

Please sign in to comment.