From 16508aff77569c683baaaf42d32cf482b6a8a386 Mon Sep 17 00:00:00 2001 From: zaaarf Date: Wed, 24 Jan 2024 17:35:09 +0100 Subject: chore: version bump + internal reorganisation --- build.gradle | 2 +- src/main/java/ftbsc/lll/mapper/IMappingFormat.java | 2 +- src/main/java/ftbsc/lll/mapper/data/ClassData.java | 144 +++++++++++++++++++++ src/main/java/ftbsc/lll/mapper/data/FieldData.java | 55 ++++++++ .../java/ftbsc/lll/mapper/data/MethodData.java | 35 +++++ .../ftbsc/lll/mapper/data/MethodSignature.java | 51 ++++++++ .../java/ftbsc/lll/mapper/impl/MultiMapper.java | 6 +- src/main/java/ftbsc/lll/mapper/impl/SRGMapper.java | 6 +- .../java/ftbsc/lll/mapper/impl/TSRGMapper.java | 4 +- .../java/ftbsc/lll/mapper/impl/TinyV2Mapper.java | 4 +- src/main/java/ftbsc/lll/mapper/tools/Mapper.java | 78 ----------- .../java/ftbsc/lll/mapper/tools/MappingUtils.java | 64 --------- .../ftbsc/lll/mapper/tools/data/ClassData.java | 144 --------------------- .../ftbsc/lll/mapper/tools/data/FieldData.java | 56 -------- .../ftbsc/lll/mapper/tools/data/MethodData.java | 35 ----- .../lll/mapper/tools/data/MethodSignature.java | 51 -------- src/main/java/ftbsc/lll/mapper/utils/Mapper.java | 78 +++++++++++ .../java/ftbsc/lll/mapper/utils/MappingUtils.java | 64 +++++++++ 18 files changed, 439 insertions(+), 440 deletions(-) create mode 100644 src/main/java/ftbsc/lll/mapper/data/ClassData.java create mode 100644 src/main/java/ftbsc/lll/mapper/data/FieldData.java create mode 100644 src/main/java/ftbsc/lll/mapper/data/MethodData.java create mode 100644 src/main/java/ftbsc/lll/mapper/data/MethodSignature.java delete mode 100644 src/main/java/ftbsc/lll/mapper/tools/Mapper.java delete mode 100644 src/main/java/ftbsc/lll/mapper/tools/MappingUtils.java delete mode 100644 src/main/java/ftbsc/lll/mapper/tools/data/ClassData.java delete mode 100644 src/main/java/ftbsc/lll/mapper/tools/data/FieldData.java delete mode 100644 src/main/java/ftbsc/lll/mapper/tools/data/MethodData.java delete mode 100644 src/main/java/ftbsc/lll/mapper/tools/data/MethodSignature.java create mode 100644 src/main/java/ftbsc/lll/mapper/utils/Mapper.java create mode 100644 src/main/java/ftbsc/lll/mapper/utils/MappingUtils.java diff --git a/build.gradle b/build.gradle index 2437aab..5ddaa88 100644 --- a/build.gradle +++ b/build.gradle @@ -24,7 +24,7 @@ repositories { } dependencies { - implementation 'ftbsc:lll:0.4.2' + implementation 'ftbsc:lll:0.5.0' implementation 'com.google.auto.service:auto-service-annotations:1.1.0' annotationProcessor 'com.google.auto.service:auto-service:1.1.0' } diff --git a/src/main/java/ftbsc/lll/mapper/IMappingFormat.java b/src/main/java/ftbsc/lll/mapper/IMappingFormat.java index f691bfe..f5d2bcc 100644 --- a/src/main/java/ftbsc/lll/mapper/IMappingFormat.java +++ b/src/main/java/ftbsc/lll/mapper/IMappingFormat.java @@ -1,7 +1,7 @@ package ftbsc.lll.mapper; import ftbsc.lll.exceptions.MalformedMappingsException; -import ftbsc.lll.mapper.tools.Mapper; +import ftbsc.lll.mapper.utils.Mapper; import java.util.List; diff --git a/src/main/java/ftbsc/lll/mapper/data/ClassData.java b/src/main/java/ftbsc/lll/mapper/data/ClassData.java new file mode 100644 index 0000000..04592fd --- /dev/null +++ b/src/main/java/ftbsc/lll/mapper/data/ClassData.java @@ -0,0 +1,144 @@ +package ftbsc.lll.mapper.data; + +import ftbsc.lll.exceptions.MappingNotFoundException; +import ftbsc.lll.mapper.utils.Mapper; +import ftbsc.lll.mapper.utils.MappingUtils; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * Container class used to store information about classes. + */ +public class ClassData { + + /** + * The internal (like the fully-qualified name, but with '/' instead + * of '.') of the class. + */ + public final String name; + + /** + * The mapped internal (like the fully-qualified name, but with '/' + * instead of '.') of the class. + */ + public final String nameMapped; + + /** + * A {@link Map} tying each method's signature to its data class. + */ + private final Map methods; + + /** + * A {@link Map} tying each field's name to its data class. + */ + private final Map fields; + + /** + * The constructor. It takes in the names (plain and mapped) of a class. + * @param name the plain name + * @param nameMapped the mapped name + */ + public ClassData(String name, String nameMapped) { + this.name = name; + this.nameMapped = nameMapped; + this.methods = new HashMap<>(); + this.fields = new HashMap<>(); + } + + /** + * Adds a method to the target class. + * @param name the method name + * @param nameMapped the mapped method name + * @param descriptor the descriptor of the method + */ + public void addMethod(String name, String nameMapped, String descriptor) { + MethodData data = new MethodData(this, name, nameMapped, descriptor); + this.methods.put(data.signature, data); + } + + /** + * Adds a field to the target class. + * @param plain the name of the field + * @param mapped the mapped name of the field + */ + public void addField(String plain, String mapped) { + this.fields.put(plain, new FieldData(this, plain, mapped)); + } + + /** + * Adds a field to the target class. + * @param plain the name of the field + * @param mapped the mapped name of the field + * @param descriptor the plain type descriptor of the field + */ + public void addField(String plain, String mapped, String descriptor) { + this.fields.put(plain, new FieldData(this, plain, mapped, descriptor)); + } + + /** + * Generates the reverse mappings for this class. + * Should always be called only after the given mapper has finished + * processing all classes. + * @param mapper the mapper that generated this data + * @return a ClassData representing the inverted mappings + */ + public ClassData generateReverseMappings(Mapper mapper) { + ClassData reverse = new ClassData(this.nameMapped, this.name); + this.methods.forEach((signature, data) -> reverse.addMethod(nameMapped, signature.name, + MappingUtils.mapMethodDescriptor(signature.descriptor, mapper, false))); + this.fields.forEach((name, data) -> reverse.addField(data.nameMapped, name, data.descriptor)); + return reverse; + } + + /** + * Gets the {@link MethodData} from its name and descriptor, which may be partial + * (i.e. not include the return type). + * @param methodName the method name + * @param methodDescriptor the method descriptor, which may be partial + * @return the requested {@link MethodData} + * @throws MappingNotFoundException if the mapping wasn't found + */ + public MethodData mapMethod(String methodName, String methodDescriptor) { + List signatures = this.methods.keySet().stream().filter( + s -> s.name.equals(methodName) && s.descriptor.startsWith(methodDescriptor) + ).collect(Collectors.toList()); + if(signatures.size() > 1) + throw new RuntimeException(); //should never happen unless something goes horribly wrong + else if(signatures.isEmpty()) + throw new MappingNotFoundException("method", + String.format("%s::%s%s", this.name, methodName, methodDescriptor)); + return this.methods.get(signatures.get(0)); + } + + /** + * Gets the {@link FieldData} its name. + * @param fieldName the field name + * @return the requested {@link FieldData} + * @throws MappingNotFoundException if the mapping wasn't found + */ + public FieldData mapField(String fieldName) { + FieldData data = this.fields.get(fieldName); + if(data == null) + throw new MappingNotFoundException("field", String.format("%s.%s", this.name, fieldName)); + else return data; + } + + /** + * Gets the underlying {@link Map} for {@link MethodData}. + * @return a {@link Map} tying each {@link MethodSignature} to its {@link MethodData} + */ + public Map getMethods() { + return this.methods; + } + + /** + * Gets the underlying {@link Map} for {@link FieldData}. + * @return a {@link Map} tying each field name to its {@link FieldData} + */ + public Map getFields() { + return this.fields; + } +} diff --git a/src/main/java/ftbsc/lll/mapper/data/FieldData.java b/src/main/java/ftbsc/lll/mapper/data/FieldData.java new file mode 100644 index 0000000..3e6cf6c --- /dev/null +++ b/src/main/java/ftbsc/lll/mapper/data/FieldData.java @@ -0,0 +1,55 @@ +package ftbsc.lll.mapper.data; + +/** + * Container class for method data. + */ +public class FieldData { + /** + * The internal name of the parent class. + */ + public final ClassData parentClass; + + /** + * The name of the method. + */ + public final String name; + + /** + * The name mapped. + */ + public final String nameMapped; + + /** + * The field's type descriptor. + * Some formats may not specify it; if this was created in one such format, + * this is going to be null. + */ + public final String descriptor; + + /** + * Constructs a new {@link FieldData} with unspecified descriptor. + * @param parentClass the {@link ClassData} representation of the parent class + * @param name the field name + * @param nameMapped the mapped field name + */ + public FieldData(ClassData parentClass, String name, String nameMapped) { + this.parentClass = parentClass; + this.name = name; + this.nameMapped = nameMapped; + this.descriptor = null; + } + + /** + * Constructs a new {@link FieldData} with descriptor. + * @param parentClass the {@link ClassData} representation of the parent class + * @param name the field name + * @param nameMapped the mapped field name + * @param descriptor the field's type descriptor + */ + public FieldData(ClassData parentClass, String name, String nameMapped, String descriptor) { + this.parentClass = parentClass; + this.name = name; + this.nameMapped = nameMapped; + this.descriptor = descriptor; + } +} diff --git a/src/main/java/ftbsc/lll/mapper/data/MethodData.java b/src/main/java/ftbsc/lll/mapper/data/MethodData.java new file mode 100644 index 0000000..670ecd2 --- /dev/null +++ b/src/main/java/ftbsc/lll/mapper/data/MethodData.java @@ -0,0 +1,35 @@ +package ftbsc.lll.mapper.data; + +/** + * Container class for method data. + */ +public class MethodData { + + /** + * The internal name of the parent class. + */ + public final ClassData parentClass; + + /** + * The signature of the method. + */ + public final MethodSignature signature; + + /** + * The mapped name of the method. + */ + public final String nameMapped; + + /** + * Constructs a new {@link MethodData}. + * @param parentClass the {@link ClassData} representation of the parent class + * @param name the method name + * @param nameMapped the mapped method name + * @param descriptor the method's descriptor + */ + public MethodData(ClassData parentClass, String name, String nameMapped, String descriptor) { + this.parentClass = parentClass; + this.signature = new MethodSignature(name, descriptor); + this.nameMapped = nameMapped; + } +} diff --git a/src/main/java/ftbsc/lll/mapper/data/MethodSignature.java b/src/main/java/ftbsc/lll/mapper/data/MethodSignature.java new file mode 100644 index 0000000..d7515a8 --- /dev/null +++ b/src/main/java/ftbsc/lll/mapper/data/MethodSignature.java @@ -0,0 +1,51 @@ +package ftbsc.lll.mapper.data; + +import java.util.Objects; + +/** + * Container class for method signature data. + */ +public class MethodSignature { + /** + * The name of the method. + */ + public final String name; + + /** + * The descriptor of the method. + */ + public final String descriptor; + + /** + * Constructs a new {@link MethodSignature}. The parameters should be + * either plain or obfuscated in the same way; + * @param name the method name + * @param descriptor the method descriptor + */ + public MethodSignature(String name, String descriptor) { + this.name = name; + this.descriptor = descriptor; + } + + /** + * Checks if two {@link MethodSignature}s represent the same method. + * @param o the other signature + * @return whether they represent the same method + */ + @Override + public boolean equals(Object o) { + if(this == o) return true; + if(o == null || getClass() != o.getClass()) return false; + MethodSignature signature = (MethodSignature) o; + return Objects.equals(name, signature.name) && Objects.equals(descriptor, signature.descriptor); + } + + /** + * Calculates a hash based on name and descriptor. + * @return the hash code + */ + @Override + public int hashCode() { + return Objects.hash(name, descriptor); + } +} diff --git a/src/main/java/ftbsc/lll/mapper/impl/MultiMapper.java b/src/main/java/ftbsc/lll/mapper/impl/MultiMapper.java index 1ff1459..d7e1eba 100644 --- a/src/main/java/ftbsc/lll/mapper/impl/MultiMapper.java +++ b/src/main/java/ftbsc/lll/mapper/impl/MultiMapper.java @@ -4,9 +4,9 @@ import com.google.auto.service.AutoService; import ftbsc.lll.exceptions.MalformedMappingsException; import ftbsc.lll.mapper.IMappingFormat; import ftbsc.lll.mapper.MapperProvider; -import ftbsc.lll.mapper.tools.Mapper; -import ftbsc.lll.mapper.tools.MappingUtils; -import ftbsc.lll.mapper.tools.data.ClassData; +import ftbsc.lll.mapper.utils.Mapper; +import ftbsc.lll.mapper.utils.MappingUtils; +import ftbsc.lll.mapper.data.ClassData; import java.util.ArrayList; import java.util.List; diff --git a/src/main/java/ftbsc/lll/mapper/impl/SRGMapper.java b/src/main/java/ftbsc/lll/mapper/impl/SRGMapper.java index c92dba7..b4d51af 100644 --- a/src/main/java/ftbsc/lll/mapper/impl/SRGMapper.java +++ b/src/main/java/ftbsc/lll/mapper/impl/SRGMapper.java @@ -3,8 +3,8 @@ package ftbsc.lll.mapper.impl; import com.google.auto.service.AutoService; import ftbsc.lll.exceptions.MalformedMappingsException; import ftbsc.lll.mapper.IMappingFormat; -import ftbsc.lll.mapper.tools.Mapper; -import ftbsc.lll.mapper.tools.data.ClassData; +import ftbsc.lll.mapper.utils.Mapper; +import ftbsc.lll.mapper.data.ClassData; import java.util.List; @@ -138,4 +138,4 @@ public class SRGMapper implements IMappingFormat { public Mapper getInvertedMapper(List lines, boolean ignoreErrors) { return this.buildMapper(lines, ignoreErrors, true); } -} \ No newline at end of file +} diff --git a/src/main/java/ftbsc/lll/mapper/impl/TSRGMapper.java b/src/main/java/ftbsc/lll/mapper/impl/TSRGMapper.java index 222fafc..c15bfa6 100644 --- a/src/main/java/ftbsc/lll/mapper/impl/TSRGMapper.java +++ b/src/main/java/ftbsc/lll/mapper/impl/TSRGMapper.java @@ -3,8 +3,8 @@ package ftbsc.lll.mapper.impl; import com.google.auto.service.AutoService; import ftbsc.lll.exceptions.MalformedMappingsException; import ftbsc.lll.mapper.IMappingFormat; -import ftbsc.lll.mapper.tools.Mapper; -import ftbsc.lll.mapper.tools.data.ClassData; +import ftbsc.lll.mapper.utils.Mapper; +import ftbsc.lll.mapper.data.ClassData; import java.util.List; import java.util.regex.Pattern; diff --git a/src/main/java/ftbsc/lll/mapper/impl/TinyV2Mapper.java b/src/main/java/ftbsc/lll/mapper/impl/TinyV2Mapper.java index 1810b84..e60b7ed 100644 --- a/src/main/java/ftbsc/lll/mapper/impl/TinyV2Mapper.java +++ b/src/main/java/ftbsc/lll/mapper/impl/TinyV2Mapper.java @@ -3,8 +3,8 @@ package ftbsc.lll.mapper.impl; import com.google.auto.service.AutoService; import ftbsc.lll.exceptions.MalformedMappingsException; import ftbsc.lll.mapper.IMappingFormat; -import ftbsc.lll.mapper.tools.Mapper; -import ftbsc.lll.mapper.tools.data.ClassData; +import ftbsc.lll.mapper.utils.Mapper; +import ftbsc.lll.mapper.data.ClassData; import java.util.List; import java.util.regex.Pattern; diff --git a/src/main/java/ftbsc/lll/mapper/tools/Mapper.java b/src/main/java/ftbsc/lll/mapper/tools/Mapper.java deleted file mode 100644 index 2b59d17..0000000 --- a/src/main/java/ftbsc/lll/mapper/tools/Mapper.java +++ /dev/null @@ -1,78 +0,0 @@ -package ftbsc.lll.mapper.tools; - -import ftbsc.lll.exceptions.MappingNotFoundException; -import ftbsc.lll.mapper.tools.data.ClassData; -import ftbsc.lll.mapper.tools.data.FieldData; -import ftbsc.lll.mapper.tools.data.MethodData; - -import java.util.HashMap; -import java.util.Map; - -/** - * An object containing parsed mapping data, which can - * apply a conversion as requested. - */ -public class Mapper { - /** - * A {@link Map} tying each plain class name to its class data. - */ - protected final Map mappings = new HashMap<>(); - - /** - * Gets the {@link ClassData} given the plain name. - * @param name the plain internal name of the desired class - * @return the mapped name of the class - * @throws MappingNotFoundException if no mapping is found - */ - public ClassData getClassData(String name) throws MappingNotFoundException { - ClassData data = this.mappings.get(name.replace('.', '/')); - if(data == null) - throw new MappingNotFoundException("class", name); - else return data; - } - - /** - * Gets the mapped name of a method - * @param parent the plain internal name of the parent class - * @param name the plain method name - * @param descriptor the descriptor of the method - * @return the mapped name of the given member - * @throws MappingNotFoundException if no mapping is found - */ - public MethodData getMethodData(String parent, String name, String descriptor) throws MappingNotFoundException { - return this.getClassData(parent).mapMethod(name, descriptor); - } - - /** - * Gets the mapped name of a field. - * @param parent the plain internal name of the parent class - * @param name the field's plain name - * @return the mapped name of the requested field - * @throws MappingNotFoundException if no mapping is found - */ - public FieldData getFieldData(String parent, String name) throws MappingNotFoundException { - return this.getClassData(parent).mapField(name); - } - - /** - * Gets the "raw mappings". - * @return a {@link Map} tying each {@link ClassData} to the class' plain name - */ - public Map getRawMappings() { - return this.mappings; - } - - /** - * Builds a new {@link Mapper} that functions in reverse to this one (i.e. one that - * considers as "mapped" what this one considers plain, and vice versa). - * @return the inverted mapper - */ - public Mapper getInverted() { - Mapper inverted = new Mapper(); - this.mappings.forEach((name, data) -> { - ClassData reverse = data.generateReverseMappings(this); - inverted.mappings.put(data.nameMapped, reverse); - }); - return inverted; - } -} diff --git a/src/main/java/ftbsc/lll/mapper/tools/MappingUtils.java b/src/main/java/ftbsc/lll/mapper/tools/MappingUtils.java deleted file mode 100644 index fc121dd..0000000 --- a/src/main/java/ftbsc/lll/mapper/tools/MappingUtils.java +++ /dev/null @@ -1,64 +0,0 @@ -package ftbsc.lll.mapper.tools; - -import ftbsc.lll.exceptions.MappingNotFoundException; -import ftbsc.lll.tools.DescriptorBuilder; -import org.objectweb.asm.Type; - -/** - * A collection of static utility methods correlated to - * mappers. - */ -public class MappingUtils { - - /** - * Maps a method descriptor, replacing its class references with their mapped counterparts. - * @param descriptor a {@link String} containing the descriptor - * @param mapper the {@link Mapper} to use for the process - * @param reverse if true it uses the inverted mapper rather than the normal one - * @return the mapped descriptor - */ - public static String mapMethodDescriptor(String descriptor, Mapper mapper, boolean reverse) { - Type method = Type.getMethodType(descriptor); - Type[] arguments = method.getArgumentTypes(); - Type returnType = method.getReturnType(); - - Type[] mappedArguents = new Type[arguments.length]; - for(int i = 0; i < mappedArguents.length; i++) - mappedArguents[i] = mapType(arguments[i], mapper, reverse); - - return Type.getMethodDescriptor(mapType(returnType, mapper, reverse), mappedArguents); - } - - /** - * Given a {@link Type} and a valid {@link Mapper} it returns its mapped counterpart. - * @param type the type in question - * @param mapper the {@link Mapper} to use for the process - * @param reverse if true it uses the inverted mapper rather than the normal one - * @return the mapped type - */ - public static Type mapType(Type type, Mapper mapper, boolean reverse) { - //unwrap arrays - Type unwrapped = type; - int arrayLevel = 0; - while(unwrapped.getSort() == Type.ARRAY) { - unwrapped = unwrapped.getElementType(); - arrayLevel++; - } - - //if it's a primitive no operation is needed - if(type.getSort() < Type.ARRAY) - return type; - - String internalName = type.getInternalName(); - - String internalNameMapped; - try { - internalNameMapped = reverse - ? mapper.getInverted().getClassData(internalName).nameMapped - : mapper.getClassData(internalName).nameMapped; - return Type.getType(DescriptorBuilder.nameToDescriptor(internalNameMapped, arrayLevel)); - } catch(MappingNotFoundException e) { - return type; - } - } -} diff --git a/src/main/java/ftbsc/lll/mapper/tools/data/ClassData.java b/src/main/java/ftbsc/lll/mapper/tools/data/ClassData.java deleted file mode 100644 index 4b4f58e..0000000 --- a/src/main/java/ftbsc/lll/mapper/tools/data/ClassData.java +++ /dev/null @@ -1,144 +0,0 @@ -package ftbsc.lll.mapper.tools.data; - -import ftbsc.lll.exceptions.MappingNotFoundException; -import ftbsc.lll.mapper.tools.Mapper; -import ftbsc.lll.mapper.tools.MappingUtils; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -/** - * Container class used to store information about classes. - */ -public class ClassData { - - /** - * The internal (like the fully-qualified name, but with '/' instead - * of '.') of the class. - */ - public final String name; - - /** - * The mapped internal (like the fully-qualified name, but with '/' - * instead of '.') of the class. - */ - public final String nameMapped; - - /** - * A {@link Map} tying each method's signature to its data class. - */ - private final Map methods; - - /** - * A {@link Map} tying each field's name to its data class. - */ - private final Map fields; - - /** - * The constructor. It takes in the names (plain and mapped) of a class. - * @param name the plain name - * @param nameMapped the mapped name - */ - public ClassData(String name, String nameMapped) { - this.name = name; - this.nameMapped = nameMapped; - this.methods = new HashMap<>(); - this.fields = new HashMap<>(); - } - - /** - * Adds a method to the target class. - * @param name the method name - * @param nameMapped the mapped method name - * @param descriptor the descriptor of the method - */ - public void addMethod(String name, String nameMapped, String descriptor) { - MethodData data = new MethodData(this, name, nameMapped, descriptor); - this.methods.put(data.signature, data); - } - - /** - * Adds a field to the target class. - * @param plain the name of the field - * @param mapped the mapped name of the field - */ - public void addField(String plain, String mapped) { - this.fields.put(plain, new FieldData(this, plain, mapped)); - } - - /** - * Adds a field to the target class. - * @param plain the name of the field - * @param mapped the mapped name of the field - * @param descriptor the plain type descriptor of the field - */ - public void addField(String plain, String mapped, String descriptor) { - this.fields.put(plain, new FieldData(this, plain, mapped, descriptor)); - } - - /** - * Generates the reverse mappings for this class. - * Should always be called only after the given mapper has finished - * processing all classes. - * @param mapper the mapper that generated this data - * @return a ClassData representing the inverted mappings - */ - public ClassData generateReverseMappings(Mapper mapper) { - ClassData reverse = new ClassData(this.nameMapped, this.name); - this.methods.forEach((signature, data) -> reverse.addMethod(nameMapped, signature.name, - MappingUtils.mapMethodDescriptor(signature.descriptor, mapper, false))); - this.fields.forEach((name, data) -> reverse.addField(data.nameMapped, name, data.descriptor)); - return reverse; - } - - /** - * Gets the {@link MethodData} from its name and descriptor, which may be partial - * (i.e. not include the return type). - * @param methodName the method name - * @param methodDescriptor the method descriptor, which may be partial - * @return the requested {@link MethodData} - * @throws MappingNotFoundException if the mapping wasn't found - */ - public MethodData mapMethod(String methodName, String methodDescriptor) { - List signatures = this.methods.keySet().stream().filter( - s -> s.name.equals(methodName) && s.descriptor.startsWith(methodDescriptor) - ).collect(Collectors.toList()); - if(signatures.size() > 1) - throw new RuntimeException(); //should never happen unless something goes horribly wrong - else if(signatures.isEmpty()) - throw new MappingNotFoundException("method", - String.format("%s::%s%s", this.name, methodName, methodDescriptor)); - return this.methods.get(signatures.get(0)); - } - - /** - * Gets the {@link FieldData} its name. - * @param fieldName the field name - * @return the requested {@link FieldData} - * @throws MappingNotFoundException if the mapping wasn't found - */ - public FieldData mapField(String fieldName) { - FieldData data = this.fields.get(fieldName); - if(data == null) - throw new MappingNotFoundException("field", String.format("%s.%s", this.name, fieldName)); - else return data; - } - - /** - * Gets the underlying {@link Map} for {@link MethodData}. - * @return a {@link Map} tying each {@link MethodSignature} to its {@link MethodData} - */ - public Map getMethods() { - return this.methods; - } - - /** - * Gets the underlying {@link Map} for {@link FieldData}. - * @return a {@link Map} tying each field name to its {@link FieldData} - */ - public Map getFields() { - return this.fields; - } -} \ No newline at end of file diff --git a/src/main/java/ftbsc/lll/mapper/tools/data/FieldData.java b/src/main/java/ftbsc/lll/mapper/tools/data/FieldData.java deleted file mode 100644 index e239d66..0000000 --- a/src/main/java/ftbsc/lll/mapper/tools/data/FieldData.java +++ /dev/null @@ -1,56 +0,0 @@ - -package ftbsc.lll.mapper.tools.data; - -/** - * Container class for method data. - */ -public class FieldData { - /** - * The internal name of the parent class. - */ - public final ClassData parentClass; - - /** - * The name of the method. - */ - public final String name; - - /** - * The name mapped. - */ - public final String nameMapped; - - /** - * The field's type descriptor. - * Some formats may not specify it; if this was created in one such format, - * this is going to be null. - */ - public final String descriptor; - - /** - * Constructs a new {@link FieldData} with unspecified descriptor. - * @param parentClass the {@link ClassData} representation of the parent class - * @param name the field name - * @param nameMapped the mapped field name - */ - public FieldData(ClassData parentClass, String name, String nameMapped) { - this.parentClass = parentClass; - this.name = name; - this.nameMapped = nameMapped; - this.descriptor = null; - } - - /** - * Constructs a new {@link FieldData} with descriptor. - * @param parentClass the {@link ClassData} representation of the parent class - * @param name the field name - * @param nameMapped the mapped field name - * @param descriptor the field's type descriptor - */ - public FieldData(ClassData parentClass, String name, String nameMapped, String descriptor) { - this.parentClass = parentClass; - this.name = name; - this.nameMapped = nameMapped; - this.descriptor = descriptor; - } -} diff --git a/src/main/java/ftbsc/lll/mapper/tools/data/MethodData.java b/src/main/java/ftbsc/lll/mapper/tools/data/MethodData.java deleted file mode 100644 index 699b0b0..0000000 --- a/src/main/java/ftbsc/lll/mapper/tools/data/MethodData.java +++ /dev/null @@ -1,35 +0,0 @@ -package ftbsc.lll.mapper.tools.data; - -/** - * Container class for method data. - */ -public class MethodData { - - /** - * The internal name of the parent class. - */ - public final ClassData parentClass; - - /** - * The signature of the method. - */ - public final MethodSignature signature; - - /** - * The mapped name of the method. - */ - public final String nameMapped; - - /** - * Constructs a new {@link MethodData}. - * @param parentClass the {@link ClassData} representation of the parent class - * @param name the method name - * @param nameMapped the mapped method name - * @param descriptor the method's descriptor - */ - public MethodData(ClassData parentClass, String name, String nameMapped, String descriptor) { - this.parentClass = parentClass; - this.signature = new MethodSignature(name, descriptor); - this.nameMapped = nameMapped; - } -} diff --git a/src/main/java/ftbsc/lll/mapper/tools/data/MethodSignature.java b/src/main/java/ftbsc/lll/mapper/tools/data/MethodSignature.java deleted file mode 100644 index 08770be..0000000 --- a/src/main/java/ftbsc/lll/mapper/tools/data/MethodSignature.java +++ /dev/null @@ -1,51 +0,0 @@ -package ftbsc.lll.mapper.tools.data; - -import java.util.Objects; - -/** - * Container class for method signature data. - */ -public class MethodSignature { - /** - * The name of the method. - */ - public final String name; - - /** - * The descriptor of the method. - */ - public final String descriptor; - - /** - * Constructs a new {@link MethodSignature}. The parameters should be - * either plain or obfuscated in the same way; - * @param name the method name - * @param descriptor the method descriptor - */ - public MethodSignature(String name, String descriptor) { - this.name = name; - this.descriptor = descriptor; - } - - /** - * Checks if two {@link MethodSignature}s represent the same method. - * @param o the other signature - * @return whether they represent the same method - */ - @Override - public boolean equals(Object o) { - if(this == o) return true; - if(o == null || getClass() != o.getClass()) return false; - MethodSignature signature = (MethodSignature) o; - return Objects.equals(name, signature.name) && Objects.equals(descriptor, signature.descriptor); - } - - /** - * Calculates a hash based on name and descriptor. - * @return the hash code - */ - @Override - public int hashCode() { - return Objects.hash(name, descriptor); - } -} diff --git a/src/main/java/ftbsc/lll/mapper/utils/Mapper.java b/src/main/java/ftbsc/lll/mapper/utils/Mapper.java new file mode 100644 index 0000000..b6e0722 --- /dev/null +++ b/src/main/java/ftbsc/lll/mapper/utils/Mapper.java @@ -0,0 +1,78 @@ +package ftbsc.lll.mapper.utils; + +import ftbsc.lll.exceptions.MappingNotFoundException; +import ftbsc.lll.mapper.data.ClassData; +import ftbsc.lll.mapper.data.FieldData; +import ftbsc.lll.mapper.data.MethodData; + +import java.util.HashMap; +import java.util.Map; + +/** + * An object containing parsed mapping data, which can + * apply a conversion as requested. + */ +public class Mapper { + /** + * A {@link Map} tying each plain class name to its class data. + */ + protected final Map mappings = new HashMap<>(); + + /** + * Gets the {@link ClassData} given the plain name. + * @param name the plain internal name of the desired class + * @return the mapped name of the class + * @throws MappingNotFoundException if no mapping is found + */ + public ClassData getClassData(String name) throws MappingNotFoundException { + ClassData data = this.mappings.get(name.replace('.', '/')); + if(data == null) + throw new MappingNotFoundException("class", name); + else return data; + } + + /** + * Gets the mapped name of a method + * @param parent the plain internal name of the parent class + * @param name the plain method name + * @param descriptor the descriptor of the method + * @return the mapped name of the given member + * @throws MappingNotFoundException if no mapping is found + */ + public MethodData getMethodData(String parent, String name, String descriptor) throws MappingNotFoundException { + return this.getClassData(parent).mapMethod(name, descriptor); + } + + /** + * Gets the mapped name of a field. + * @param parent the plain internal name of the parent class + * @param name the field's plain name + * @return the mapped name of the requested field + * @throws MappingNotFoundException if no mapping is found + */ + public FieldData getFieldData(String parent, String name) throws MappingNotFoundException { + return this.getClassData(parent).mapField(name); + } + + /** + * Gets the "raw mappings". + * @return a {@link Map} tying each {@link ClassData} to the class' plain name + */ + public Map getRawMappings() { + return this.mappings; + } + + /** + * Builds a new {@link Mapper} that functions in reverse to this one (i.e. one that + * considers as "mapped" what this one considers plain, and vice versa). + * @return the inverted mapper + */ + public Mapper getInverted() { + Mapper inverted = new Mapper(); + this.mappings.forEach((name, data) -> { + ClassData reverse = data.generateReverseMappings(this); + inverted.mappings.put(data.nameMapped, reverse); + }); + return inverted; + } +} diff --git a/src/main/java/ftbsc/lll/mapper/utils/MappingUtils.java b/src/main/java/ftbsc/lll/mapper/utils/MappingUtils.java new file mode 100644 index 0000000..ff7327c --- /dev/null +++ b/src/main/java/ftbsc/lll/mapper/utils/MappingUtils.java @@ -0,0 +1,64 @@ +package ftbsc.lll.mapper.utils; + +import ftbsc.lll.exceptions.MappingNotFoundException; +import ftbsc.lll.utils.DescriptorBuilder; +import org.objectweb.asm.Type; + +/** + * A collection of static utility methods correlated to + * mappers. + */ +public class MappingUtils { + + /** + * Maps a method descriptor, replacing its class references with their mapped counterparts. + * @param descriptor a {@link String} containing the descriptor + * @param mapper the {@link Mapper} to use for the process + * @param reverse if true it uses the inverted mapper rather than the normal one + * @return the mapped descriptor + */ + public static String mapMethodDescriptor(String descriptor, Mapper mapper, boolean reverse) { + Type method = Type.getMethodType(descriptor); + Type[] arguments = method.getArgumentTypes(); + Type returnType = method.getReturnType(); + + Type[] mappedArguents = new Type[arguments.length]; + for(int i = 0; i < mappedArguents.length; i++) + mappedArguents[i] = mapType(arguments[i], mapper, reverse); + + return Type.getMethodDescriptor(mapType(returnType, mapper, reverse), mappedArguents); + } + + /** + * Given a {@link Type} and a valid {@link Mapper} it returns its mapped counterpart. + * @param type the type in question + * @param mapper the {@link Mapper} to use for the process + * @param reverse if true it uses the inverted mapper rather than the normal one + * @return the mapped type + */ + public static Type mapType(Type type, Mapper mapper, boolean reverse) { + //unwrap arrays + Type unwrapped = type; + int arrayLevel = 0; + while(unwrapped.getSort() == Type.ARRAY) { + unwrapped = unwrapped.getElementType(); + arrayLevel++; + } + + //if it's a primitive no operation is needed + if(type.getSort() < Type.ARRAY) + return type; + + String internalName = type.getInternalName(); + + String internalNameMapped; + try { + internalNameMapped = reverse + ? mapper.getInverted().getClassData(internalName).nameMapped + : mapper.getClassData(internalName).nameMapped; + return Type.getType(DescriptorBuilder.nameToDescriptor(internalNameMapped, arrayLevel)); + } catch(MappingNotFoundException e) { + return type; + } + } +} -- cgit v1.2.3-56-ga3b1