diff options
author | zaaarf <zaaarf@proton.me> | 2023-08-26 18:09:36 +0200 |
---|---|---|
committer | zaaarf <zaaarf@proton.me> | 2023-08-26 18:09:52 +0200 |
commit | 7898882bc5811e5f06e70bc2bb6925e114869a56 (patch) | |
tree | ee2f2a4f75c72f4beaead402d7cbf2ad8d71bfe0 /src/main/java/ftbsc/lll/mapper/tools | |
parent | c3cc90d7743b18aaef0d22adb7292c63ef48603f (diff) |
feat: implemented abstraction logic
Diffstat (limited to 'src/main/java/ftbsc/lll/mapper/tools')
5 files changed, 237 insertions, 100 deletions
diff --git a/src/main/java/ftbsc/lll/mapper/tools/ClassData.java b/src/main/java/ftbsc/lll/mapper/tools/ClassData.java deleted file mode 100644 index a9fbcec..0000000 --- a/src/main/java/ftbsc/lll/mapper/tools/ClassData.java +++ /dev/null @@ -1,100 +0,0 @@ -package ftbsc.lll.mapper.tools; - -import ftbsc.lll.exceptions.AmbiguousMappingException; -import ftbsc.lll.exceptions.MappingNotFoundException; - -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 unobfuscated name (FQN with '/' instad of '.') of the class. - */ - public final String unobf; - - /** - * The obfuscated internal name (FQN with '/' instad of '.') of the class. - */ - public final String obf; - - /** - * A {@link Map} tying each member's name or signature to its - * obfuscated counterpart. - */ - public final Map<String, String> members; - - /** - * The constructor. It takes in the names (obfuscated and non-obfuscated) - * of a class. - * @param unobf the unobfuscated name - * @param obf the obfuscated name - */ - public ClassData(String unobf, String obf) { - this.unobf = unobf; - this.obf = obf; - this.members = new HashMap<>(); - } - - /** - * Adds a member to the target class. - * For fields only the names are required; for methods, - * this takes in the full signature ({@code name + " " + space}). - * @param s the String representing the declaration line - */ - public void addMember(String s) { - String[] split = s.trim().split(" "); - if(split.length == 2) //field - members.put(split[0], split[1]); - else if (split.length == 3) //method - members.put(split[0] + " " + split[1], split[2]); - } - - /** - * Gets an obfuscated member given the method name and a method descriptor, - * which may be partial (i.e. not include return type) or null if the member - * is not a method. - * @param memberName member name - * @param methodDescriptor the method descriptor, or null if it's not a method - * @return the requested obfuscated name, or null if nothing was found - * @throws AmbiguousMappingException if not enough data was given to uniquely identify a mapping - */ - public String get(String memberName, String methodDescriptor) { - - //find all keys that start with the name - List<String> candidates = members.keySet().stream().filter( - m -> m.split(" ")[0].equals(memberName) - ).collect(Collectors.toList()); - - if(methodDescriptor != null) { - String signature = String.format("%s %s", memberName, methodDescriptor); - candidates = candidates.stream().filter( - m -> m.equals(signature) - ).collect(Collectors.toList()); - } - - switch(candidates.size()) { - case 0: - throw new MappingNotFoundException(String.format( - "%s.%s%s", - this.unobf, - memberName, - methodDescriptor == null ? "" : "()" - )); - case 1: - return members.get(candidates.get(0)); - default: - throw new AmbiguousMappingException(String.format( - "Mapper could not uniquely identify member %s.%s%s, found %d!", - this.unobf, - memberName, - methodDescriptor == null ? "" : "()", - candidates.size() - )); - } - } -}
\ No newline at end of file diff --git a/src/main/java/ftbsc/lll/mapper/tools/data/ClassData.java b/src/main/java/ftbsc/lll/mapper/tools/data/ClassData.java new file mode 100644 index 0000000..5ae4124 --- /dev/null +++ b/src/main/java/ftbsc/lll/mapper/tools/data/ClassData.java @@ -0,0 +1,117 @@ +package ftbsc.lll.mapper.tools.data; + +import ftbsc.lll.exceptions.MappingNotFoundException; +import ftbsc.lll.mapper.IMapper; +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<MethodSignature, MethodData> methods; + + /** + * A {@link Map} tying each field's name to its data class. + */ + private final Map<String, FieldData> 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)); + } + + /** + * 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 + */ + public ClassData generateReverseMappings(IMapper mapper) { + ClassData reverse = new ClassData(this.nameMapped, this.name); + this.methods.forEach((signature, data) -> reverse.addMethod(nameMapped, signature.name, + MappingUtils.obfuscateMethodDescriptor(signature.descriptor, mapper))); + this.fields.forEach((name, data) -> reverse.addField(data.nameMapped, name)); + 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<MethodSignature> 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; + } +}
\ 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 new file mode 100644 index 0000000..bcc3985 --- /dev/null +++ b/src/main/java/ftbsc/lll/mapper/tools/data/FieldData.java @@ -0,0 +1,34 @@ + +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; + + /** + * Constructs a new {@link FieldData}. + * @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; + } +} diff --git a/src/main/java/ftbsc/lll/mapper/tools/data/MethodData.java b/src/main/java/ftbsc/lll/mapper/tools/data/MethodData.java new file mode 100644 index 0000000..27c418c --- /dev/null +++ b/src/main/java/ftbsc/lll/mapper/tools/data/MethodData.java @@ -0,0 +1,35 @@ +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. + */ + 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 new file mode 100644 index 0000000..08770be --- /dev/null +++ b/src/main/java/ftbsc/lll/mapper/tools/data/MethodSignature.java @@ -0,0 +1,51 @@ +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); + } +} |