From 00fcd0550fcdda621c2e4662f6ddd55ce673b931 Mon Sep 17 00:00:00 2001 From: Gegy Date: Thu, 24 Jan 2019 14:48:32 +0200 Subject: [WIP] Mapping rework (#91) * Move packages * Mapping & entry refactor: first pass * Fix deobf -> obf tree remapping * Resolve various issues * Give all entries the potential for parents and treat inner classes as children * Deobf UI tree elements * Tests pass * Sort mapping output * Fix delta tracking * Index separation and first pass for #97 * Keep track of remapped jar index * Fix child entries not being remapped * Drop non-root entries * Track dropped mappings * Fix enigma mapping ordering * EntryTreeNode interface * Small tweaks * Naive full index remap on rename * Entries can resolve to more than one root entry * Support alternative resolution strategies * Bridge method resolution * Tests pass * Fix mappings being used where there are none * Fix methods with different descriptors being considered unique. closes #89 --- .../java/cuchaz/enigma/mapping/ClassMapping.java | 627 --------------------- .../enigma/mapping/DirectionalTranslator.java | 371 ------------ .../java/cuchaz/enigma/mapping/FieldMapping.java | 100 ---- .../enigma/mapping/LocalVariableMapping.java | 58 -- src/main/java/cuchaz/enigma/mapping/Mappings.java | 268 --------- .../cuchaz/enigma/mapping/MappingsChecker.java | 101 ---- .../enigma/mapping/MappingsEnigmaReader.java | 186 ------ .../enigma/mapping/MappingsEnigmaWriter.java | 160 ------ .../cuchaz/enigma/mapping/MappingsRenamer.java | 365 ------------ .../cuchaz/enigma/mapping/MappingsSRGWriter.java | 80 --- .../cuchaz/enigma/mapping/MappingsTinyReader.java | 130 ----- .../java/cuchaz/enigma/mapping/MemberMapping.java | 21 - .../cuchaz/enigma/mapping/MethodDescriptor.java | 114 ---- .../java/cuchaz/enigma/mapping/MethodMapping.java | 210 ------- .../java/cuchaz/enigma/mapping/NameValidator.java | 73 --- src/main/java/cuchaz/enigma/mapping/Signature.java | 82 --- .../cuchaz/enigma/mapping/SignatureUpdater.java | 92 --- .../enigma/mapping/TranslationDirection.java | 36 -- .../java/cuchaz/enigma/mapping/Translator.java | 109 ---- .../java/cuchaz/enigma/mapping/TypeDescriptor.java | 258 --------- .../cuchaz/enigma/mapping/entry/ClassDefEntry.java | 38 -- .../cuchaz/enigma/mapping/entry/ClassEntry.java | 175 ------ .../java/cuchaz/enigma/mapping/entry/DefEntry.java | 7 - .../java/cuchaz/enigma/mapping/entry/Entry.java | 22 - .../cuchaz/enigma/mapping/entry/EntryFactory.java | 49 -- .../cuchaz/enigma/mapping/entry/FieldDefEntry.java | 44 -- .../cuchaz/enigma/mapping/entry/FieldEntry.java | 77 --- .../mapping/entry/LocalVariableDefEntry.java | 61 -- .../enigma/mapping/entry/LocalVariableEntry.java | 93 --- .../enigma/mapping/entry/MethodDefEntry.java | 61 -- .../cuchaz/enigma/mapping/entry/MethodEntry.java | 80 --- .../enigma/mapping/entry/ProcyonEntryFactory.java | 48 -- .../enigma/mapping/entry/ReferencedEntryPool.java | 59 -- 33 files changed, 4255 deletions(-) delete mode 100644 src/main/java/cuchaz/enigma/mapping/ClassMapping.java delete mode 100644 src/main/java/cuchaz/enigma/mapping/DirectionalTranslator.java delete mode 100644 src/main/java/cuchaz/enigma/mapping/FieldMapping.java delete mode 100644 src/main/java/cuchaz/enigma/mapping/LocalVariableMapping.java delete mode 100644 src/main/java/cuchaz/enigma/mapping/Mappings.java delete mode 100644 src/main/java/cuchaz/enigma/mapping/MappingsChecker.java delete mode 100644 src/main/java/cuchaz/enigma/mapping/MappingsEnigmaReader.java delete mode 100644 src/main/java/cuchaz/enigma/mapping/MappingsEnigmaWriter.java delete mode 100644 src/main/java/cuchaz/enigma/mapping/MappingsRenamer.java delete mode 100644 src/main/java/cuchaz/enigma/mapping/MappingsSRGWriter.java delete mode 100644 src/main/java/cuchaz/enigma/mapping/MappingsTinyReader.java delete mode 100644 src/main/java/cuchaz/enigma/mapping/MemberMapping.java delete mode 100644 src/main/java/cuchaz/enigma/mapping/MethodDescriptor.java delete mode 100644 src/main/java/cuchaz/enigma/mapping/MethodMapping.java delete mode 100644 src/main/java/cuchaz/enigma/mapping/NameValidator.java delete mode 100644 src/main/java/cuchaz/enigma/mapping/Signature.java delete mode 100644 src/main/java/cuchaz/enigma/mapping/SignatureUpdater.java delete mode 100644 src/main/java/cuchaz/enigma/mapping/TranslationDirection.java delete mode 100644 src/main/java/cuchaz/enigma/mapping/Translator.java delete mode 100644 src/main/java/cuchaz/enigma/mapping/TypeDescriptor.java delete mode 100644 src/main/java/cuchaz/enigma/mapping/entry/ClassDefEntry.java delete mode 100644 src/main/java/cuchaz/enigma/mapping/entry/ClassEntry.java delete mode 100644 src/main/java/cuchaz/enigma/mapping/entry/DefEntry.java delete mode 100644 src/main/java/cuchaz/enigma/mapping/entry/Entry.java delete mode 100644 src/main/java/cuchaz/enigma/mapping/entry/EntryFactory.java delete mode 100644 src/main/java/cuchaz/enigma/mapping/entry/FieldDefEntry.java delete mode 100644 src/main/java/cuchaz/enigma/mapping/entry/FieldEntry.java delete mode 100644 src/main/java/cuchaz/enigma/mapping/entry/LocalVariableDefEntry.java delete mode 100644 src/main/java/cuchaz/enigma/mapping/entry/LocalVariableEntry.java delete mode 100644 src/main/java/cuchaz/enigma/mapping/entry/MethodDefEntry.java delete mode 100644 src/main/java/cuchaz/enigma/mapping/entry/MethodEntry.java delete mode 100644 src/main/java/cuchaz/enigma/mapping/entry/ProcyonEntryFactory.java delete mode 100644 src/main/java/cuchaz/enigma/mapping/entry/ReferencedEntryPool.java (limited to 'src/main/java/cuchaz/enigma/mapping') diff --git a/src/main/java/cuchaz/enigma/mapping/ClassMapping.java b/src/main/java/cuchaz/enigma/mapping/ClassMapping.java deleted file mode 100644 index 9c193ef..0000000 --- a/src/main/java/cuchaz/enigma/mapping/ClassMapping.java +++ /dev/null @@ -1,627 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.mapping; - -import com.google.common.collect.Maps; -import cuchaz.enigma.mapping.entry.ClassEntry; -import cuchaz.enigma.mapping.entry.FieldEntry; -import cuchaz.enigma.mapping.entry.MethodEntry; -import cuchaz.enigma.throwables.MappingConflict; - -import java.util.ArrayList; -import java.util.Map; - -// FIXME: Enigma doesn't support inner classes of inner class????! -public class ClassMapping implements Comparable { - - private String obfFullName; - private String obfSimpleName; - private String deobfName; - private String deobfFullName; - private String previousDeobfName; - private Map innerClassesByObfSimple; - private Map innerClassesByObfFull; - private Map innerClassesByDeobf; - private Map fieldsByObf; - private Map fieldsByDeobf; - private Map methodsByObf; - private Map methodsByDeobf; - private boolean isDirty; - private Mappings.EntryModifier modifier; - - public ClassMapping(String obfFullName) { - this(obfFullName, null, Mappings.EntryModifier.UNCHANGED); - } - - public ClassMapping(String obfFullName, String deobfName) { - this(obfFullName, deobfName, Mappings.EntryModifier.UNCHANGED); - } - - public ClassMapping(String obfFullName, String deobfName, Mappings.EntryModifier modifier) { - this.obfFullName = obfFullName; - ClassEntry classEntry = new ClassEntry(obfFullName); - obfSimpleName = classEntry.isInnerClass() ? classEntry.getInnermostClassName() : classEntry.getSimpleName(); - previousDeobfName = null; - this.deobfName = NameValidator.validateClassName(deobfName, false); - innerClassesByObfSimple = Maps.newHashMap(); - innerClassesByObfFull = Maps.newHashMap(); - innerClassesByDeobf = Maps.newHashMap(); - fieldsByObf = Maps.newHashMap(); - fieldsByDeobf = Maps.newHashMap(); - methodsByObf = Maps.newHashMap(); - methodsByDeobf = Maps.newHashMap(); - isDirty = true; - this.modifier = modifier; - } - - public static boolean isSimpleClassName(String name) { - return name.indexOf('/') < 0 && name.indexOf('$') < 0; - } - - public String getObfFullName() { - return obfFullName; - } - - public String getObfSimpleName() { - return obfSimpleName; - } - - public String getPreviousDeobfName() { - return previousDeobfName; - } - - public String getDeobfName() { - return deobfName; - } - - public String getTranslatedName(TranslationDirection direction) { - return direction.choose(deobfName, obfFullName); - } - - //// INNER CLASSES //////// - - public void setDeobfName(String val) { - previousDeobfName = deobfName; - deobfName = NameValidator.validateClassName(val, false); - this.isDirty = true; - } - - public Iterable innerClasses() { - assert (innerClassesByObfSimple.size() >= innerClassesByDeobf.size()); - return innerClassesByObfSimple.values(); - } - - public void addInnerClassMapping(ClassMapping classMapping) throws MappingConflict { - // FIXME: dirty hack, that can get into issues, but it's a temp fix! - if (this.innerClassesByObfFull.containsKey(classMapping.getObfSimpleName())) { - throw new MappingConflict("classes", classMapping.getObfSimpleName(), this.innerClassesByObfSimple.get(classMapping.getObfSimpleName()).getObfSimpleName()); - } - innerClassesByObfFull.put(classMapping.getObfFullName(), classMapping); - innerClassesByObfSimple.put(classMapping.getObfSimpleName(), classMapping); - - if (classMapping.getDeobfName() != null) { - if (this.innerClassesByDeobf.containsKey(classMapping.getDeobfName())) { - throw new MappingConflict("classes", classMapping.getDeobfName(), this.innerClassesByDeobf.get(classMapping.getDeobfName()).getDeobfName()); - } - innerClassesByDeobf.put(classMapping.getDeobfName(), classMapping); - } - this.isDirty = true; - } - - public void removeInnerClassMapping(ClassMapping classMapping) { - innerClassesByObfFull.remove(classMapping.getObfFullName()); - boolean obfWasRemoved = innerClassesByObfSimple.remove(classMapping.getObfSimpleName()) != null; - assert (obfWasRemoved); - if (classMapping.getDeobfName() != null) { - boolean deobfWasRemoved = innerClassesByDeobf.remove(classMapping.getDeobfName()) != null; - assert (deobfWasRemoved); - } - this.isDirty = true; - } - - public ClassMapping getOrCreateInnerClass(ClassEntry obfInnerClass) { - ClassMapping classMapping = innerClassesByObfSimple.get(obfInnerClass.getInnermostClassName()); - if (classMapping == null) { - classMapping = new ClassMapping(obfInnerClass.getName()); - innerClassesByObfFull.put(classMapping.getObfFullName(), classMapping); - boolean wasAdded = innerClassesByObfSimple.put(classMapping.getObfSimpleName(), classMapping) == null; - assert (wasAdded); - this.isDirty = true; - } - return classMapping; - } - - public ClassMapping getInnerClassByObfSimple(String obfSimpleName) { - assert (isSimpleClassName(obfSimpleName)); - return innerClassesByObfSimple.get(obfSimpleName); - } - - public ClassMapping getInnerClassByDeobf(String deobfName) { - assert (isSimpleClassName(deobfName)); - return innerClassesByDeobf.get(deobfName); - } - - public ClassMapping getInnerClassByDeobfThenObfSimple(String name) { - ClassMapping classMapping = getInnerClassByDeobf(name); - if (classMapping == null) { - classMapping = getInnerClassByObfSimple(name); - } - return classMapping; - } - - public String getDeobfInnerClassName(String obfSimpleName) { - assert (isSimpleClassName(obfSimpleName)); - ClassMapping classMapping = innerClassesByObfSimple.get(obfSimpleName); - if (classMapping != null) { - return classMapping.getDeobfName(); - } - return null; - } - - public void setInnerClassName(ClassEntry obfInnerClass, String deobfName) { - ClassMapping classMapping = getOrCreateInnerClass(obfInnerClass); - if (classMapping.getDeobfName() != null) { - boolean wasRemoved = innerClassesByDeobf.remove(classMapping.getDeobfName()) != null; - assert (wasRemoved); - } - classMapping.setDeobfName(deobfName); - if (deobfName != null) { - assert (isSimpleClassName(deobfName)); - boolean wasAdded = innerClassesByDeobf.put(deobfName, classMapping) == null; - assert (wasAdded); - } - this.isDirty = true; - } - - public boolean hasInnerClassByObfSimple(String obfSimpleName) { - return innerClassesByObfSimple.containsKey(obfSimpleName); - } - - //// FIELDS //////// - - public boolean hasInnerClassByDeobf(String deobfName) { - return innerClassesByDeobf.containsKey(deobfName); - } - - public Iterable fields() { - assert (fieldsByObf.size() == fieldsByDeobf.size()); - return fieldsByObf.values(); - } - - public boolean containsObfField(String obfName, TypeDescriptor obfDesc) { - return fieldsByObf.containsKey(getFieldKey(obfName, obfDesc)); - } - - public boolean containsDeobfField(String deobfName, TypeDescriptor deobfDesc) { - return fieldsByDeobf.containsKey(getFieldKey(deobfName, deobfDesc)); - } - - public void addFieldMapping(FieldMapping fieldMapping) { - String obfKey = getFieldKey(fieldMapping.getObfName(), fieldMapping.getObfDesc()); - if (fieldsByObf.containsKey(obfKey)) { - throw new Error("Already have mapping for " + obfFullName + "." + obfKey); - } - if (fieldMapping.getDeobfName() != null) { - String deobfKey = getFieldKey(fieldMapping.getDeobfName(), fieldMapping.getObfDesc()); - if (fieldsByDeobf.containsKey(deobfKey)) { - throw new Error("Already have mapping for " + deobfName + "." + deobfKey); - } - boolean deobfWasAdded = fieldsByDeobf.put(deobfKey, fieldMapping) == null; - assert (deobfWasAdded); - } - boolean obfWasAdded = fieldsByObf.put(obfKey, fieldMapping) == null; - assert (obfWasAdded); - this.isDirty = true; - } - - public void removeFieldMapping(FieldMapping fieldMapping) { - boolean obfWasRemoved = fieldsByObf.remove(getFieldKey(fieldMapping.getObfName(), fieldMapping.getObfDesc())) != null; - assert (obfWasRemoved); - if (fieldMapping.getDeobfName() != null) { - boolean deobfWasRemoved = fieldsByDeobf.remove(getFieldKey(fieldMapping.getDeobfName(), fieldMapping.getObfDesc())) != null; - assert (deobfWasRemoved); - } - this.isDirty = true; - } - - public FieldMapping getFieldByObf(String obfName, TypeDescriptor obfDesc) { - return fieldsByObf.get(getFieldKey(obfName, obfDesc)); - } - - public FieldMapping getFieldByObf(FieldEntry field) { - return getFieldByObf(field.getName(), field.getDesc()); - } - - public FieldMapping getFieldByDeobf(String deobfName, TypeDescriptor obfDesc) { - return fieldsByDeobf.get(getFieldKey(deobfName, obfDesc)); - } - - public String getObfFieldName(String deobfName, TypeDescriptor obfDesc) { - FieldMapping fieldMapping = fieldsByDeobf.get(getFieldKey(deobfName, obfDesc)); - if (fieldMapping != null) { - return fieldMapping.getObfName(); - } - return null; - } - - public String getDeobfFieldName(String obfName, TypeDescriptor obfDesc) { - FieldMapping fieldMapping = fieldsByObf.get(getFieldKey(obfName, obfDesc)); - if (fieldMapping != null) { - return fieldMapping.getDeobfName(); - } - return null; - } - - private String getFieldKey(String name, TypeDescriptor desc) { - if (name == null) { - throw new IllegalArgumentException("name cannot be null!"); - } - if (desc == null) { - throw new IllegalArgumentException("desc cannot be null!"); - } - return name + ":" + desc; - } - - public void setFieldName(String obfName, TypeDescriptor obfDesc, String deobfName) { - assert (deobfName != null); - FieldMapping fieldMapping = fieldsByObf.get(getFieldKey(obfName, obfDesc)); - if (fieldMapping == null) { - fieldMapping = new FieldMapping(obfName, obfDesc, deobfName, Mappings.EntryModifier.UNCHANGED); - boolean obfWasAdded = fieldsByObf.put(getFieldKey(obfName, obfDesc), fieldMapping) == null; - assert (obfWasAdded); - } else { - boolean wasRemoved = fieldsByDeobf.remove(getFieldKey(fieldMapping.getDeobfName(), obfDesc)) != null; - assert (wasRemoved); - } - fieldMapping.setDeobfName(deobfName); - if (deobfName != null) { - boolean wasAdded = fieldsByDeobf.put(getFieldKey(deobfName, obfDesc), fieldMapping) == null; - assert (wasAdded); - } - this.isDirty = true; - } - - //// METHODS //////// - - public void setFieldObfNameAndType(String oldObfName, TypeDescriptor obfDesc, String newObfName, TypeDescriptor newObfDesc) { - assert (newObfName != null); - FieldMapping fieldMapping = fieldsByObf.remove(getFieldKey(oldObfName, obfDesc)); - assert (fieldMapping != null); - fieldMapping.setObfName(newObfName); - fieldMapping.setObfDesc(newObfDesc); - boolean obfWasAdded = fieldsByObf.put(getFieldKey(newObfName, newObfDesc), fieldMapping) == null; - assert (obfWasAdded); - this.isDirty = true; - } - - public Iterable methods() { - assert (methodsByObf.size() >= methodsByDeobf.size()); - return methodsByObf.values(); - } - - public boolean containsObfMethod(String obfName, MethodDescriptor obfDescriptor) { - return methodsByObf.containsKey(getMethodKey(obfName, obfDescriptor)); - } - - public boolean containsDeobfMethod(String deobfName, MethodDescriptor obfDescriptor) { - return methodsByDeobf.containsKey(getMethodKey(deobfName, obfDescriptor)); - } - - public void addMethodMapping(MethodMapping methodMapping) { - String obfKey = getMethodKey(methodMapping.getObfName(), methodMapping.getObfDesc()); - if (methodsByObf.containsKey(obfKey)) { - throw new Error("Already have mapping for " + obfFullName + "." + obfKey); - } - boolean wasAdded = methodsByObf.put(obfKey, methodMapping) == null; - assert (wasAdded); - if (!methodMapping.isObfuscated()) { - String deobfKey = getMethodKey(methodMapping.getDeobfName(), methodMapping.getObfDesc()); - if (methodsByDeobf.containsKey(deobfKey)) { - throw new Error("Already have mapping for " + deobfName + "." + deobfKey); - } - boolean deobfWasAdded = methodsByDeobf.put(deobfKey, methodMapping) == null; - assert (deobfWasAdded); - } - this.isDirty = true; - assert (methodsByObf.size() >= methodsByDeobf.size()); - } - - public void removeMethodMapping(MethodMapping methodMapping) { - boolean obfWasRemoved = methodsByObf.remove(getMethodKey(methodMapping.getObfName(), methodMapping.getObfDesc())) != null; - assert (obfWasRemoved); - if (!methodMapping.isObfuscated()) { - boolean deobfWasRemoved = methodsByDeobf.remove(getMethodKey(methodMapping.getDeobfName(), methodMapping.getObfDesc())) != null; - assert (deobfWasRemoved); - } - this.isDirty = true; - } - - public MethodMapping getMethodByObf(String obfName, MethodDescriptor obfDescriptor) { - return methodsByObf.get(getMethodKey(obfName, obfDescriptor)); - } - - public MethodMapping getMethodByObf(MethodEntry method) { - return getMethodByObf(method.getName(), method.getDesc()); - } - - public MethodMapping getMethodByDeobf(String deobfName, MethodDescriptor obfDescriptor) { - return methodsByDeobf.get(getMethodKey(deobfName, obfDescriptor)); - } - - private String getMethodKey(String name, MethodDescriptor descriptor) { - if (name == null) { - throw new IllegalArgumentException("name cannot be null!"); - } - if (descriptor == null) { - throw new IllegalArgumentException("descriptor cannot be null!"); - } - return name + descriptor; - } - - public void setMethodName(String obfName, MethodDescriptor obfDescriptor, String deobfName) { - MethodMapping methodMapping = methodsByObf.get(getMethodKey(obfName, obfDescriptor)); - if (methodMapping == null) { - methodMapping = createMethodMapping(obfName, obfDescriptor); - } else if (!methodMapping.isObfuscated()) { - boolean wasRemoved = methodsByDeobf.remove(getMethodKey(methodMapping.getDeobfName(), methodMapping.getObfDesc())) != null; - assert (wasRemoved); - } - methodMapping.setDeobfName(deobfName); - if (deobfName != null) { - boolean wasAdded = methodsByDeobf.put(getMethodKey(deobfName, obfDescriptor), methodMapping) == null; - assert (wasAdded); - } - this.isDirty = true; - } - - //// ARGUMENTS //////// - - public void setMethodObfNameAndSignature(String oldObfName, MethodDescriptor obfDescriptor, String newObfName, MethodDescriptor newObfDescriptor) { - assert (newObfName != null); - MethodMapping methodMapping = methodsByObf.remove(getMethodKey(oldObfName, obfDescriptor)); - assert (methodMapping != null); - methodMapping.setObfName(newObfName); - methodMapping.setObfDescriptor(newObfDescriptor); - boolean obfWasAdded = methodsByObf.put(getMethodKey(newObfName, newObfDescriptor), methodMapping) == null; - assert (obfWasAdded); - this.isDirty = true; - } - - public void setArgumentName(String obfMethodName, MethodDescriptor obfMethodDescriptor, int argumentIndex, String argumentName) { - assert (argumentName != null); - MethodMapping methodMapping = methodsByObf.get(getMethodKey(obfMethodName, obfMethodDescriptor)); - if (methodMapping == null) { - methodMapping = createMethodMapping(obfMethodName, obfMethodDescriptor); - } - methodMapping.setLocalVariableName(argumentIndex, argumentName); - this.isDirty = true; - } - - public void removeArgumentName(String obfMethodName, MethodDescriptor obfMethodDescriptor, int argumentIndex) { - methodsByObf.get(getMethodKey(obfMethodName, obfMethodDescriptor)).removeLocalVariableName(argumentIndex); - this.isDirty = true; - } - - private MethodMapping createMethodMapping(String obfName, MethodDescriptor obfDescriptor) { - MethodMapping methodMapping = new MethodMapping(obfName, obfDescriptor); - boolean wasAdded = methodsByObf.put(getMethodKey(obfName, obfDescriptor), methodMapping) == null; - assert (wasAdded); - this.isDirty = true; - return methodMapping; - } - - @Override - public String toString() { - StringBuilder buf = new StringBuilder(); - buf.append(obfFullName); - buf.append(" <-> "); - buf.append(deobfName); - buf.append("\n"); - buf.append("Fields:\n"); - for (FieldMapping fieldMapping : fields()) { - buf.append("\t"); - buf.append(fieldMapping.getObfName()); - buf.append(" <-> "); - buf.append(fieldMapping.getDeobfName()); - buf.append("\n"); - } - buf.append("Methods:\n"); - for (MethodMapping methodMapping : methodsByObf.values()) { - buf.append(methodMapping); - buf.append("\n"); - } - buf.append("Inner Classes:\n"); - for (ClassMapping classMapping : innerClassesByObfSimple.values()) { - buf.append("\t"); - buf.append(classMapping.getObfSimpleName()); - buf.append(" <-> "); - buf.append(classMapping.getDeobfName()); - buf.append("\n"); - } - return buf.toString(); - } - - @Override - public int compareTo(ClassMapping other) { - // sort by a, b, c, ... aa, ab, etc - if (obfFullName.length() != other.obfFullName.length()) { - return obfFullName.length() - other.obfFullName.length(); - } - return obfFullName.compareTo(other.obfFullName); - } - - public boolean renameObfClass(String oldObfClassName, String newObfClassName) { - - // rename inner classes - for (ClassMapping innerClassMapping : new ArrayList<>(innerClassesByObfSimple.values())) { - if (innerClassMapping.renameObfClass(oldObfClassName, newObfClassName)) { - boolean wasRemoved = innerClassesByObfSimple.remove(oldObfClassName) != null; - assert (wasRemoved); - boolean wasAdded = innerClassesByObfSimple.put(newObfClassName, innerClassMapping) == null; - assert (wasAdded); - } - } - - // rename field types - for (FieldMapping fieldMapping : new ArrayList<>(fieldsByObf.values())) { - String oldFieldKey = getFieldKey(fieldMapping.getObfName(), fieldMapping.getObfDesc()); - if (fieldMapping.renameObfClass(oldObfClassName, newObfClassName)) { - boolean wasRemoved = fieldsByObf.remove(oldFieldKey) != null; - assert (wasRemoved); - boolean wasAdded = fieldsByObf - .put(getFieldKey(fieldMapping.getObfName(), fieldMapping.getObfDesc()), fieldMapping) == null; - assert (wasAdded); - } - } - - // rename method signatures - for (MethodMapping methodMapping : new ArrayList<>(methodsByObf.values())) { - String oldMethodKey = getMethodKey(methodMapping.getObfName(), methodMapping.getObfDesc()); - if (methodMapping.renameObfClass(oldObfClassName, newObfClassName)) { - boolean wasRemoved = methodsByObf.remove(oldMethodKey) != null; - assert (wasRemoved); - boolean wasAdded = methodsByObf - .put(getMethodKey(methodMapping.getObfName(), methodMapping.getObfDesc()), methodMapping) == null; - assert (wasAdded); - } - } - - if (obfFullName.equals(oldObfClassName)) { - // rename this class - obfFullName = newObfClassName; - return true; - } - this.isDirty = true; - return false; - } - - public boolean containsArgument(MethodEntry obfMethodEntry, String name) { - MethodMapping methodMapping = methodsByObf.get(getMethodKey(obfMethodEntry.getName(), obfMethodEntry.getDesc())); - return methodMapping != null && methodMapping.containsLocalVariable(name); - } - - public ClassEntry getObfEntry() { - return new ClassEntry(obfFullName); - } - - public ClassEntry getDeObfEntry() { - return deobfFullName != null ? new ClassEntry(deobfFullName) : null; - } - - public boolean isObfuscated() { - return this.deobfName == null || this.deobfName.equals(this.obfFullName); - } - - public String getSaveName() { - return this.isObfuscated() ? this.obfFullName : this.deobfName; - } - - public boolean isDirty() { - return isDirty || areInnersDirty(); - } - - private boolean areInnersDirty(){ - for (ClassMapping c : this.innerClasses()){ - if (c.isDirty()){ - return true; - } - } - return false; - } - - public void resetDirty() { - this.isDirty = false; - } - - public void markDirty() { - this.isDirty = true; - } - - public Mappings.EntryModifier getModifier() { - return modifier; - } - - public void setModifier(Mappings.EntryModifier modifier) { - if (this.modifier != modifier) - this.isDirty = true; - this.modifier = modifier; - } - - public void setFieldModifier(String obfName, TypeDescriptor obfDesc, Mappings.EntryModifier modifier) { - FieldMapping fieldMapping = fieldsByObf.computeIfAbsent(getFieldKey(obfName, obfDesc), - k -> new FieldMapping(obfName, obfDesc, null, Mappings.EntryModifier.UNCHANGED)); - - if (fieldMapping.getModifier() != modifier) { - fieldMapping.setModifier(modifier); - this.isDirty = true; - } - } - - public void setMethodModifier(String obfName, MethodDescriptor sig, Mappings.EntryModifier modifier) { - MethodMapping methodMapping = methodsByObf.computeIfAbsent(getMethodKey(obfName, sig), - k -> new MethodMapping(obfName, sig, null, Mappings.EntryModifier.UNCHANGED)); - - if (methodMapping.getModifier() != modifier) { - methodMapping.setModifier(modifier); - this.isDirty = true; - } - } - - // Used for tiny parsing to keep track of deobfuscate inner classes - public ClassMapping setDeobfInner(String deobName) { - this.deobfFullName = deobName; - return this; - } - - public ClassMapping copy() { - ClassMapping copied = new ClassMapping(this.obfFullName); - copied.obfSimpleName= this.obfSimpleName; - copied.modifier = this.modifier; - copied.deobfFullName = this.deobfFullName; - copied.deobfName = this.deobfName; - copied.innerClassesByDeobf = this.innerClassesByDeobf; - copied.innerClassesByObfFull = this.innerClassesByObfFull; - copied.innerClassesByObfSimple = this.innerClassesByObfSimple; - copied.fieldsByObf = this.fieldsByObf; - copied.fieldsByDeobf = this.fieldsByDeobf; - copied.methodsByObf = this.methodsByObf; - copied.methodsByDeobf = this.methodsByDeobf; - return copied; - } - - @Override - public int hashCode() { - return this.obfFullName.hashCode(); - } - - @Override - public boolean equals(Object obj) { - return obj instanceof ClassMapping && ((ClassMapping) obj).obfFullName.equals(this.obfFullName); - } - - public boolean isEmpty() { - if (fieldsByDeobf.isEmpty() && methodsByDeobf.isEmpty() && deobfFullName == null && deobfName == null - && innerClassesByObfSimple.values().stream().allMatch(ClassMapping::isEmpty)) { - - // check args - for (MethodMapping mapping : methodsByObf.values()) { - if (mapping.arguments().iterator().hasNext()) { - return false; - } - } - - return true; - } - - return false; - } -} diff --git a/src/main/java/cuchaz/enigma/mapping/DirectionalTranslator.java b/src/main/java/cuchaz/enigma/mapping/DirectionalTranslator.java deleted file mode 100644 index 388e7ac..0000000 --- a/src/main/java/cuchaz/enigma/mapping/DirectionalTranslator.java +++ /dev/null @@ -1,371 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.mapping; - -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import cuchaz.enigma.analysis.TranslationIndex; -import cuchaz.enigma.bytecode.AccessFlags; -import cuchaz.enigma.mapping.entry.*; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.ServiceLoader; - -public class DirectionalTranslator implements Translator { - private final TranslationDirection direction; - private final Map classes; - private final TranslationIndex index; - - public DirectionalTranslator(ReferencedEntryPool entryPool) { - this.direction = null; - this.classes = Maps.newHashMap(); - this.index = new TranslationIndex(entryPool); - } - - public DirectionalTranslator(TranslationDirection direction, Map classes, TranslationIndex index) { - this.direction = direction; - this.classes = classes; - this.index = index; - } - - public TranslationDirection getDirection() { - return direction; - } - - public TranslationIndex getTranslationIndex() { - return index; - } - - @Override - public ClassEntry getTranslatedClass(ClassEntry entry) { - String className; - if (entry.isArray()) { - className = this.getTranslatedTypeDesc(new TypeDescriptor(entry.getName())).toString(); - } else { - className = entry.isInnerClass() ? translateInnerClassName(entry) : translateClassName(entry); - } - return new ClassEntry(className); - } - - @Override - public ClassDefEntry getTranslatedClassDef(ClassDefEntry entry) { - String className; - if (entry.isArray()) { - className = this.getTranslatedTypeDesc(new TypeDescriptor(entry.getName())).toString(); - } else { - className = entry.isInnerClass() ? translateInnerClassName(entry) : translateClassName(entry); - } - Signature translatedSignature = this.getTranslatedSignature(entry.getSignature()); - return new ClassDefEntry(className, translatedSignature, getClassModifier(entry).transform(entry.getAccess())); - } - - private String translateClassName(ClassEntry entry) { - // normal classes are easy - ClassMapping classMapping = this.classes.get(entry.getName()); - if (classMapping == null) { - return entry.getName(); - } - return classMapping.getTranslatedName(direction); - } - - private String translateInnerClassName(ClassEntry entry) { - // translate as much of the class chain as we can - List mappingsChain = getClassMappingChain(entry); - String[] obfClassNames = entry.getName().split("\\$"); - StringBuilder buf = new StringBuilder(); - for (int i = 0; i < obfClassNames.length; i++) { - boolean isFirstClass = buf.length() == 0; - String className = null; - ClassMapping classMapping = mappingsChain.get(i); - if (classMapping != null) { - className = this.direction.choose( - classMapping.getDeobfName(), - isFirstClass ? classMapping.getObfFullName() : classMapping.getObfSimpleName() - ); - } - if (className == null) { - className = obfClassNames[i]; - } - if (!isFirstClass) { - buf.append("$"); - } - buf.append(className); - } - return buf.toString(); - } - - @Override - public FieldDefEntry getTranslatedFieldDef(FieldDefEntry entry) { - String translatedName = translateFieldName(entry); - if (translatedName == null) { - translatedName = entry.getName(); - } - ClassEntry translatedOwner = getTranslatedClass(entry.getOwnerClassEntry()); - TypeDescriptor translatedDesc = getTranslatedTypeDesc(entry.getDesc()); - Signature translatedSignature = getTranslatedSignature(entry.getSignature()); - AccessFlags translatedAccess = getFieldModifier(entry).transform(entry.getAccess()); - return new FieldDefEntry(translatedOwner, translatedName, translatedDesc, translatedSignature, translatedAccess); - } - - @Override - public FieldEntry getTranslatedField(FieldEntry entry) { - String translatedName = translateFieldName(entry); - if (translatedName == null) { - translatedName = entry.getName(); - } - ClassEntry translatedOwner = getTranslatedClass(entry.getOwnerClassEntry()); - TypeDescriptor translatedDesc = getTranslatedTypeDesc(entry.getDesc()); - return new FieldEntry(translatedOwner, translatedName, translatedDesc); - } - - private String translateFieldName(FieldEntry entry) { - // resolve the class entry - ClassEntry resolvedClassEntry = this.index.resolveEntryOwner(entry); - if (resolvedClassEntry != null) { - // look for the class - ClassMapping classMapping = findClassMapping(resolvedClassEntry); - if (classMapping != null) { - // look for the field - FieldMapping mapping = this.direction.choose( - classMapping.getFieldByObf(entry.getName(), entry.getDesc()), - classMapping.getFieldByDeobf(entry.getName(), getTranslatedTypeDesc(entry.getDesc())) - ); - if (mapping != null) { - return this.direction.choose(mapping.getDeobfName(), mapping.getObfName()); - } - } - } - return null; - } - - @Override - public MethodDefEntry getTranslatedMethodDef(MethodDefEntry entry) { - String translatedName = translateMethodName(entry); - if (translatedName == null) { - translatedName = entry.getName(); - } - ClassEntry translatedOwner = getTranslatedClass(entry.getOwnerClassEntry()); - MethodDescriptor translatedDesc = getTranslatedMethodDesc(entry.getDesc()); - Signature translatedSignature = getTranslatedSignature(entry.getSignature()); - AccessFlags access = getMethodModifier(entry).transform(entry.getAccess()); - return new MethodDefEntry(translatedOwner, translatedName, translatedDesc, translatedSignature, access); - } - - @Override - public MethodEntry getTranslatedMethod(MethodEntry entry) { - String translatedName = translateMethodName(entry); - if (translatedName == null) { - translatedName = entry.getName(); - } - ClassEntry translatedOwner = getTranslatedClass(entry.getOwnerClassEntry()); - MethodDescriptor translatedDesc = getTranslatedMethodDesc(entry.getDesc()); - return new MethodEntry(translatedOwner, translatedName, translatedDesc); - } - - private String translateMethodName(MethodEntry entry) { - // resolve the class entry - ClassEntry resolvedOwner = this.index.resolveEntryOwner(entry); - if (resolvedOwner != null) { - // look for class - ClassMapping classMapping = findClassMapping(resolvedOwner); - if (classMapping != null) { - // look for the method - MethodMapping mapping = this.direction.choose( - classMapping.getMethodByObf(entry.getName(), entry.getDesc()), - classMapping.getMethodByDeobf(entry.getName(), getTranslatedMethodDesc(entry.getDesc())) - ); - if (mapping != null) { - return this.direction.choose(mapping.getDeobfName(), mapping.getObfName()); - } - } - } - return null; - } - - @Override - public LocalVariableEntry getTranslatedVariable(LocalVariableEntry entry) { - String translatedArgumentName = translateLocalVariableName(entry); - if (translatedArgumentName == null) { - translatedArgumentName = inheritLocalVariableName(entry); - } - if (translatedArgumentName == null) { - translatedArgumentName = entry.getName(); - } - // TODO: Translating arguments calls method translation.. Can we refactor the code in such a way that we don't need this? - MethodEntry translatedOwner = getTranslatedMethod(entry.getOwnerEntry()); - return new LocalVariableEntry(translatedOwner, entry.getIndex(), translatedArgumentName, entry.isParameter()); - } - - @Override - public LocalVariableDefEntry getTranslatedVariableDef(LocalVariableDefEntry entry) { - String translatedArgumentName = translateLocalVariableName(entry); - if (translatedArgumentName == null) { - translatedArgumentName = inheritLocalVariableName(entry); - } - // TODO: Translating arguments calls method translation.. Can we refactor the code in such a way that we don't need this? - MethodDefEntry translatedOwner = getTranslatedMethodDef(entry.getOwnerEntry()); - TypeDescriptor translatedTypeDesc = getTranslatedTypeDesc(entry.getDesc()); - return new LocalVariableDefEntry(translatedOwner, entry.getIndex(), translatedArgumentName != null ? translatedArgumentName : entry.getName(), entry.isParameter(), translatedTypeDesc); - } - - @Override - public boolean hasClassMapping(ClassEntry entry) { - return classes.containsKey(entry.getName()); - } - - @Override - public boolean hasFieldMapping(FieldEntry entry) { - return translateFieldName(entry) != null; - } - - @Override - public boolean hasMethodMapping(MethodEntry entry) { - return translateMethodName(entry) != null; - } - - @Override - public boolean hasLocalVariableMapping(LocalVariableEntry entry) { - return translateLocalVariableName(entry) != null || inheritLocalVariableName(entry) != null; - } - - // TODO: support not identical behavior (specific to constructor) - private String translateLocalVariableName(LocalVariableEntry entry) { - // look for identical behavior in superclasses - ClassEntry ownerEntry = entry.getOwnerClassEntry(); - if (ownerEntry != null) { - // look for the class - ClassMapping classMapping = findClassMapping(ownerEntry); - if (classMapping != null) { - // look for the method - MethodMapping methodMapping = this.direction.choose( - classMapping.getMethodByObf(entry.getMethodName(), entry.getMethodDesc()), - classMapping.getMethodByDeobf(entry.getMethodName(), getTranslatedMethodDesc(entry.getMethodDesc())) - ); - if (methodMapping != null) { - int index = entry.getIndex(); - return this.direction.choose( - methodMapping.getDeobfLocalVariableName(index), - methodMapping.getObfLocalVariableName(index) - ); - } - } - } - return null; - } - - private String inheritLocalVariableName(LocalVariableEntry entry) { - List ancestry = this.index.getAncestry(entry.getOwnerClassEntry()); - // Check in mother class for the arg - for (ClassEntry ancestorEntry : ancestry) { - LocalVariableEntry motherArg = entry.updateOwnership(ancestorEntry); - if (this.index.entryExists(motherArg)) { - String result = translateLocalVariableName(motherArg); - if (result != null) { - return result; - } - } - } - return null; - } - - @Override - public TypeDescriptor getTranslatedTypeDesc(TypeDescriptor desc) { - return desc.remap(this::remapClass); - } - - @Override - public MethodDescriptor getTranslatedMethodDesc(MethodDescriptor descriptor) { - List arguments = descriptor.getArgumentDescs(); - List translatedArguments = new ArrayList<>(arguments.size()); - for (TypeDescriptor argument : arguments) { - translatedArguments.add(getTranslatedTypeDesc(argument)); - } - return new MethodDescriptor(translatedArguments, getTranslatedTypeDesc(descriptor.getReturnDesc())); - } - - @Override - public Signature getTranslatedSignature(Signature signature) { - if (signature == null) { - return null; - } - return signature.remap(this::remapClass); - } - - private ClassMapping findClassMapping(ClassEntry entry) { - List mappingChain = getClassMappingChain(entry); - return mappingChain.get(mappingChain.size() - 1); - } - - private List getClassMappingChain(ClassEntry entry) { - - // get a list of all the classes in the hierarchy - String[] parts = entry.getName().split("\\$"); - List mappingsChain = Lists.newArrayList(); - - // get mappings for the outer class - ClassMapping outerClassMapping = this.classes.get(parts[0]); - mappingsChain.add(outerClassMapping); - - for (int i = 1; i < parts.length; i++) { - - // get mappings for the inner class - ClassMapping innerClassMapping = null; - if (outerClassMapping != null) { - innerClassMapping = this.direction.choose( - outerClassMapping.getInnerClassByObfSimple(parts[i]), - outerClassMapping.getInnerClassByDeobfThenObfSimple(parts[i]) - ); - } - mappingsChain.add(innerClassMapping); - outerClassMapping = innerClassMapping; - } - - assert (mappingsChain.size() == parts.length); - return mappingsChain; - } - - private Mappings.EntryModifier getClassModifier(ClassEntry entry) { - ClassMapping classMapping = findClassMapping(entry); - if (classMapping != null) { - return classMapping.getModifier(); - } - return Mappings.EntryModifier.UNCHANGED; - } - - private Mappings.EntryModifier getFieldModifier(FieldEntry entry) { - ClassMapping classMapping = findClassMapping(entry.getOwnerClassEntry()); - if (classMapping != null) { - FieldMapping fieldMapping = classMapping.getFieldByObf(entry); - if (fieldMapping != null) { - return fieldMapping.getModifier(); - } - } - return Mappings.EntryModifier.UNCHANGED; - } - - private Mappings.EntryModifier getMethodModifier(MethodEntry entry) { - ClassMapping classMapping = findClassMapping(entry.getOwnerClassEntry()); - if (classMapping != null) { - MethodMapping methodMapping = classMapping.getMethodByObf(entry); - if (methodMapping != null) { - return methodMapping.getModifier(); - } - } - return Mappings.EntryModifier.UNCHANGED; - } - - private String remapClass(String name) { - return getTranslatedClass(new ClassEntry(name)).getName(); - } -} diff --git a/src/main/java/cuchaz/enigma/mapping/FieldMapping.java b/src/main/java/cuchaz/enigma/mapping/FieldMapping.java deleted file mode 100644 index 8fbe095..0000000 --- a/src/main/java/cuchaz/enigma/mapping/FieldMapping.java +++ /dev/null @@ -1,100 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.mapping; - -import cuchaz.enigma.mapping.entry.ClassEntry; -import cuchaz.enigma.mapping.entry.FieldEntry; -import cuchaz.enigma.throwables.IllegalNameException; - -public class FieldMapping implements Comparable, MemberMapping { - - private String obfName; - private String deobfName; - private TypeDescriptor obfDesc; - private Mappings.EntryModifier modifier; - - public FieldMapping(String obfName, TypeDescriptor obfDesc, String deobfName, Mappings.EntryModifier modifier) { - this.obfName = obfName; - this.deobfName = NameValidator.validateFieldName(deobfName); - this.obfDesc = obfDesc; - this.modifier = modifier; - } - - @Override - public FieldEntry getObfEntry(ClassEntry classEntry) { - return new FieldEntry(classEntry, this.obfName, this.obfDesc); - } - - @Override - public String getObfName() { - return this.obfName; - } - - public void setObfName(String name) { - try { - NameValidator.validateMethodName(name); - } catch (IllegalNameException ex) { - // Invalid name, damn obfuscation! Map to a deob name with another name to avoid issues - if (this.deobfName == null) { - System.err.println("WARNING: " + name + " is conflicting, auto deobfuscate to " + (name + "_auto_deob")); - setDeobfName(name + "_auto_deob"); - } - } - this.obfName = name; - } - - public String getDeobfName() { - return this.deobfName; - } - - public void setDeobfName(String val) { - this.deobfName = NameValidator.validateFieldName(val); - } - - public TypeDescriptor getObfDesc() { - return this.obfDesc; - } - - public void setObfDesc(TypeDescriptor val) { - this.obfDesc = val; - } - - public Mappings.EntryModifier getModifier() { - return modifier; - } - - public void setModifier(Mappings.EntryModifier modifier) { - this.modifier = modifier; - } - - @Override - public int compareTo(FieldMapping other) { - return (this.obfName + this.obfDesc).compareTo(other.obfName + other.obfDesc); - } - - public boolean renameObfClass(final String oldObfClassName, final String newObfClassName) { - // rename obf classes in the desc - TypeDescriptor newDesc = this.obfDesc.remap(className -> { - if (className.equals(oldObfClassName)) { - return newObfClassName; - } - return className; - }); - - if (!newDesc.equals(this.obfDesc)) { - this.obfDesc = newDesc; - return true; - } - return false; - } - -} diff --git a/src/main/java/cuchaz/enigma/mapping/LocalVariableMapping.java b/src/main/java/cuchaz/enigma/mapping/LocalVariableMapping.java deleted file mode 100644 index bfe66b2..0000000 --- a/src/main/java/cuchaz/enigma/mapping/LocalVariableMapping.java +++ /dev/null @@ -1,58 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.mapping; - -import cuchaz.enigma.mapping.entry.LocalVariableEntry; -import cuchaz.enigma.mapping.entry.MethodEntry; - -public class LocalVariableMapping implements Comparable { - - private int index; - private String name; - - // NOTE: this argument order is important for the MethodReader/MethodWriter - public LocalVariableMapping(int index, String name) { - this.index = index; - this.name = NameValidator.validateArgumentName(name); - } - - public LocalVariableMapping(LocalVariableMapping other) { - this.index = other.index; - this.name = other.name; - } - - public int getIndex() { - return this.index; - } - - public String getName() { - return this.name; - } - - public void setName(String val) { - this.name = NameValidator.validateArgumentName(val); - } - - @Deprecated - public LocalVariableEntry getObfEntry(MethodEntry methodEntry) { - return new LocalVariableEntry(methodEntry, index, name); - } - - public LocalVariableEntry getObfEntry(MethodEntry methodEntry, boolean parameter) { - return new LocalVariableEntry(methodEntry, index, name, parameter); - } - - @Override - public int compareTo(LocalVariableMapping other) { - return Integer.compare(this.index, other.index); - } -} diff --git a/src/main/java/cuchaz/enigma/mapping/Mappings.java b/src/main/java/cuchaz/enigma/mapping/Mappings.java deleted file mode 100644 index c865079..0000000 --- a/src/main/java/cuchaz/enigma/mapping/Mappings.java +++ /dev/null @@ -1,268 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.mapping; - -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import com.google.common.collect.Sets; -import cuchaz.enigma.analysis.TranslationIndex; -import cuchaz.enigma.api.EnigmaPlugin; -import cuchaz.enigma.bytecode.AccessFlags; -import cuchaz.enigma.mapping.entry.ClassEntry; -import cuchaz.enigma.mapping.entry.MethodEntry; -import cuchaz.enigma.throwables.MappingConflict; - -import java.io.File; -import java.io.IOException; -import java.util.*; -import java.util.stream.Collectors; - -public class Mappings { - - private final FormatType originMapping; - protected Map classesByObf; - protected Map classesByDeobf; - private Mappings previousState; - - public Mappings() { - this(FormatType.ENIGMA_DIRECTORY); - } - - public Mappings(FormatType originMapping) { - this.originMapping = originMapping; - this.classesByObf = Maps.newHashMap(); - this.classesByDeobf = Maps.newHashMap(); - } - - public Collection classes() { - assert (this.classesByObf.size() >= this.classesByDeobf.size()); - return this.classesByObf.values(); - } - - public void addClassMapping(ClassMapping classMapping) throws MappingConflict { - if (this.classesByObf.containsKey(classMapping.getObfFullName())) { - throw new MappingConflict("class", classMapping.getObfFullName(), this.classesByObf.get(classMapping.getObfFullName()).getObfFullName()); - } - this.classesByObf.put(classMapping.getObfFullName(), classMapping); - - if (classMapping.getDeobfName() != null) { - if (this.classesByDeobf.containsKey(classMapping.getDeobfName())) { - throw new MappingConflict("class", classMapping.getDeobfName(), this.classesByDeobf.get(classMapping.getDeobfName()).getDeobfName()); - } - this.classesByDeobf.put(classMapping.getDeobfName(), classMapping); - } - } - - public void removeClassMapping(ClassMapping classMapping) { - boolean obfWasRemoved = this.classesByObf.remove(classMapping.getObfFullName()) != null; - assert (obfWasRemoved); - if (classMapping.getDeobfName() != null) { - boolean deobfWasRemoved = this.classesByDeobf.remove(classMapping.getDeobfName()) != null; - assert (deobfWasRemoved); - } - } - - public ClassMapping getClassByObf(ClassEntry entry) { - return getClassByObf(entry.getName()); - } - - public ClassMapping getClassByObf(String obfName) { - return this.classesByObf.get(obfName); - } - - public ClassMapping getClassByDeobf(ClassEntry entry) { - return getClassByDeobf(entry.getName()); - } - - public ClassMapping getClassByDeobf(String deobfName) { - return this.classesByDeobf.get(deobfName); - } - - public void setClassDeobfName(ClassMapping classMapping, String deobfName) { - if (classMapping.getDeobfName() != null) { - boolean wasRemoved = this.classesByDeobf.remove(classMapping.getDeobfName()) != null; - assert (wasRemoved); - } - classMapping.setDeobfName(deobfName); - if (deobfName != null) { - boolean wasAdded = this.classesByDeobf.put(deobfName, classMapping) == null; - assert (wasAdded); - } - } - - public Translator getTranslator(TranslationDirection direction, TranslationIndex index) { - switch (direction) { - case DEOBFUSCATING: - - return new DirectionalTranslator(direction, this.classesByObf, index); - - case OBFUSCATING: - - // fill in the missing deobf class entries with obf entries - Map classes = Maps.newHashMap(); - for (ClassMapping classMapping : classes()) { - if (classMapping.getDeobfName() != null) { - classes.put(classMapping.getDeobfName(), classMapping); - } else { - classes.put(classMapping.getObfFullName(), classMapping); - } - } - - // translate the translation index - // NOTE: this isn't actually recursive - TranslationIndex deobfIndex = new TranslationIndex(index, getTranslator(TranslationDirection.DEOBFUSCATING, index)); - - return new DirectionalTranslator(direction, classes, deobfIndex); - - default: - throw new Error("Invalid translation direction!"); - } - } - - @Override - public String toString() { - StringBuilder buf = new StringBuilder(); - for (ClassMapping classMapping : this.classesByObf.values()) { - buf.append(classMapping); - buf.append("\n"); - } - return buf.toString(); - } - - public void renameObfClass(String oldObfName, String newObfName) { - new ArrayList<>(classes()).stream().filter(classMapping -> classMapping.renameObfClass(oldObfName, newObfName)).forEach(classMapping -> { - boolean wasRemoved = this.classesByObf.remove(oldObfName) != null; - assert (wasRemoved); - boolean wasAdded = this.classesByObf.put(newObfName, classMapping) == null; - assert (wasAdded); - }); - } - - public Set getAllObfClassNames() { - final Set classNames = Sets.newHashSet(); - for (ClassMapping classMapping : classes()) { - - // add the class name - classNames.add(classMapping.getObfFullName()); - - // add classes from method signatures - for (MethodMapping methodMapping : classMapping.methods()) { - for (TypeDescriptor desc : methodMapping.getObfDesc().types()) { - if (desc.containsType()) { - classNames.add(desc.getTypeEntry().getClassName()); - } - } - } - } - return classNames; - } - - public boolean containsDeobfClass(String deobfName) { - return this.classesByDeobf.containsKey(deobfName); - } - - public boolean containsDeobfField(ClassEntry obfClassEntry, String deobfName, TypeDescriptor obfDesc) { - ClassMapping classMapping = this.classesByObf.get(obfClassEntry.getName()); - return classMapping != null && classMapping.containsDeobfField(deobfName, obfDesc); - } - - public boolean containsDeobfField(ClassEntry obfClassEntry, String deobfName) { - ClassMapping classMapping = this.classesByObf.get(obfClassEntry.getName()); - if (classMapping != null) - for (FieldMapping fieldMapping : classMapping.fields()) - if (deobfName.equals(fieldMapping.getDeobfName()) || deobfName.equals(fieldMapping.getObfName())) - return true; - - return false; - } - - public boolean containsDeobfMethod(ClassEntry obfClassEntry, String deobfName, MethodDescriptor obfDescriptor) { - ClassMapping classMapping = this.classesByObf.get(obfClassEntry.getName()); - return classMapping != null && classMapping.containsDeobfMethod(deobfName, obfDescriptor); - } - - public boolean containsArgument(MethodEntry obfMethodEntry, String name) { - ClassMapping classMapping = this.classesByObf.get(obfMethodEntry.getClassName()); - return classMapping != null && classMapping.containsArgument(obfMethodEntry, name); - } - - public List getClassMappingChain(ClassEntry obfClass) { - List mappingChain = Lists.newArrayList(); - ClassMapping classMapping = null; - for (ClassEntry obfClassEntry : obfClass.getClassChain()) { - if (mappingChain.isEmpty()) { - classMapping = this.classesByObf.get(obfClassEntry.getName()); - } else if (classMapping != null) { - classMapping = classMapping.getInnerClassByObfSimple(obfClassEntry.getInnermostClassName()); - } - mappingChain.add(classMapping); - } - return mappingChain; - } - - public FormatType getOriginMappingFormat() { - return originMapping; - } - - public void savePreviousState() { - this.previousState = new Mappings(this.originMapping); - this.previousState.classesByDeobf = new HashMap<>(); - for (Map.Entry entry : this.classesByDeobf.entrySet()) { - this.previousState.classesByDeobf.put(entry.getKey(), entry.getValue().copy()); - } - this.previousState.classesByObf = new HashMap<>(); - for (Map.Entry entry : this.classesByObf.entrySet()) { - this.previousState.classesByObf.put(entry.getKey(), entry.getValue().copy()); - } - classesByDeobf.values().forEach(ClassMapping::resetDirty); - classesByObf.values().forEach(ClassMapping::resetDirty); - } - - public void saveEnigmaMappings(File file, boolean isDirectoryFormat) throws IOException { - new MappingsEnigmaWriter().write(file, this, isDirectoryFormat); - this.savePreviousState(); - } - - public void saveSRGMappings(File file) throws IOException { - new MappingsSRGWriter().write(file, this); - } - - public Mappings getPreviousState() { - return previousState; - } - - public enum FormatType { - ENIGMA_FILE, ENIGMA_DIRECTORY, TINY_FILE, SRG_FILE - } - - public enum EntryModifier { - UNCHANGED, PUBLIC, PROTECTED, PRIVATE; - - public String getFormattedName() { - return " ACC:" + super.toString(); - } - - public AccessFlags transform(AccessFlags access) { - switch (this) { - case PUBLIC: - return access.setPublic(); - case PROTECTED: - return access.setProtected(); - case PRIVATE: - return access.setPrivate(); - case UNCHANGED: - default: - return access; - } - } - } -} diff --git a/src/main/java/cuchaz/enigma/mapping/MappingsChecker.java b/src/main/java/cuchaz/enigma/mapping/MappingsChecker.java deleted file mode 100644 index a42f255..0000000 --- a/src/main/java/cuchaz/enigma/mapping/MappingsChecker.java +++ /dev/null @@ -1,101 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.mapping; - -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import cuchaz.enigma.analysis.JarIndex; -import cuchaz.enigma.mapping.entry.ClassEntry; -import cuchaz.enigma.mapping.entry.EntryFactory; -import cuchaz.enigma.mapping.entry.FieldEntry; -import cuchaz.enigma.mapping.entry.MethodEntry; - -import java.util.Map; - -public class MappingsChecker { - - private JarIndex index; - private Map droppedClassMappings; - private Map droppedInnerClassMappings; - private Map droppedFieldMappings; - private Map droppedMethodMappings; - - public MappingsChecker(JarIndex index) { - this.index = index; - this.droppedClassMappings = Maps.newHashMap(); - this.droppedInnerClassMappings = Maps.newHashMap(); - this.droppedFieldMappings = Maps.newHashMap(); - this.droppedMethodMappings = Maps.newHashMap(); - } - - public Map getDroppedClassMappings() { - return this.droppedClassMappings; - } - - public Map getDroppedInnerClassMappings() { - return this.droppedInnerClassMappings; - } - - public Map getDroppedFieldMappings() { - return this.droppedFieldMappings; - } - - public Map getDroppedMethodMappings() { - return this.droppedMethodMappings; - } - - public void dropBrokenMappings(Mappings mappings) { - for (ClassMapping classMapping : Lists.newArrayList(mappings.classes())) { - if (!checkClassMapping(classMapping)) { - mappings.removeClassMapping(classMapping); - this.droppedClassMappings.put(EntryFactory.getObfClassEntry(this.index, classMapping), classMapping); - } - } - } - - private boolean checkClassMapping(ClassMapping classMapping) { - - // check the class - ClassEntry classEntry = EntryFactory.getObfClassEntry(this.index, classMapping); - if (!this.index.getObfClassEntries().contains(classEntry)) { - return false; - } - - // check the fields - for (FieldMapping fieldMapping : Lists.newArrayList(classMapping.fields())) { - FieldEntry obfFieldEntry = EntryFactory.getObfFieldEntry(classMapping, fieldMapping); - if (!this.index.containsObfField(obfFieldEntry)) { - classMapping.removeFieldMapping(fieldMapping); - this.droppedFieldMappings.put(obfFieldEntry, fieldMapping); - } - } - - // check methods - for (MethodMapping methodMapping : Lists.newArrayList(classMapping.methods())) { - MethodEntry obfMethodEntry = EntryFactory.getObfMethodEntry(classEntry, methodMapping); - if (!this.index.containsObfMethod(obfMethodEntry)) { - classMapping.removeMethodMapping(methodMapping); - this.droppedMethodMappings.put(obfMethodEntry, methodMapping); - } - } - - // check inner classes - for (ClassMapping innerClassMapping : Lists.newArrayList(classMapping.innerClasses())) { - if (!checkClassMapping(innerClassMapping)) { - classMapping.removeInnerClassMapping(innerClassMapping); - this.droppedInnerClassMappings.put(EntryFactory.getObfClassEntry(this.index, innerClassMapping), innerClassMapping); - } - } - - return true; - } -} diff --git a/src/main/java/cuchaz/enigma/mapping/MappingsEnigmaReader.java b/src/main/java/cuchaz/enigma/mapping/MappingsEnigmaReader.java deleted file mode 100644 index ddbee76..0000000 --- a/src/main/java/cuchaz/enigma/mapping/MappingsEnigmaReader.java +++ /dev/null @@ -1,186 +0,0 @@ -package cuchaz.enigma.mapping; - -import com.google.common.base.Charsets; -import com.google.common.collect.Queues; -import cuchaz.enigma.throwables.MappingConflict; -import cuchaz.enigma.throwables.MappingParseException; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.util.Deque; -import java.util.function.Supplier; - -public class MappingsEnigmaReader { - - public Mappings read(File file) throws IOException, MappingParseException { - Mappings mappings; - - // Multiple file - if (file.isDirectory()) { - mappings = new Mappings(Mappings.FormatType.ENIGMA_DIRECTORY); - readDirectory(mappings, file); - } else { - mappings = new Mappings(); - readFile(mappings, file); - } - return mappings; - } - - public void readDirectory(Mappings mappings, File directory) throws IOException, MappingParseException { - File[] files = directory.listFiles(); - if (files != null) { - for (File file : files) { - if (file.isFile() && !file.getName().startsWith(".") && file.getName().endsWith(".mapping")) - readFile(mappings, file); - else if (file.isDirectory()) - readDirectory(mappings, file.getAbsoluteFile()); - } - mappings.savePreviousState(); - } else - throw new IOException("Cannot access directory" + directory.getAbsolutePath()); - } - - public Mappings readFile(Mappings mappings, File file) throws IOException, MappingParseException { - return readFileStream(mappings, new FileInputStream(file), file::getAbsolutePath); - } - - public Mappings readFileStream(Mappings mappings, InputStream stream, Supplier filenameSupplier) throws IOException, MappingParseException { - try (BufferedReader in = new BufferedReader(new InputStreamReader(stream, Charsets.UTF_8))) { - Deque mappingStack = Queues.newArrayDeque(); - - int lineNumber = 0; - String line; - while ((line = in.readLine()) != null) { - lineNumber++; - - // strip comments - int commentPos = line.indexOf('#'); - if (commentPos >= 0) { - line = line.substring(0, commentPos); - } - - // skip blank lines - if (line.trim().length() <= 0) { - continue; - } - - // get the indent of this line - int indent = 0; - for (int i = 0; i < line.length(); i++) { - if (line.charAt(i) != '\t') { - break; - } - indent++; - } - - // handle stack pops - while (indent < mappingStack.size()) { - mappingStack.pop(); - } - - String[] parts = line.trim().split("\\s"); - try { - // read the first token - String token = parts[0]; - - if (token.equalsIgnoreCase("CLASS")) { - ClassMapping classMapping; - if (indent <= 0) { - // outer class - classMapping = readClass(parts, false); - mappings.addClassMapping(classMapping); - } else { - - // inner class - if (!(mappingStack.peek() instanceof ClassMapping)) { - throw new MappingParseException(filenameSupplier, lineNumber, "Unexpected CLASS entry here!"); - } - - classMapping = readClass(parts, true); - ((ClassMapping) mappingStack.peek()).addInnerClassMapping(classMapping); - } - mappingStack.push(classMapping); - } else if (token.equalsIgnoreCase("FIELD")) { - if (mappingStack.isEmpty() || !(mappingStack.peek() instanceof ClassMapping)) { - throw new MappingParseException(filenameSupplier, lineNumber, "Unexpected FIELD entry here!"); - } - ((ClassMapping) mappingStack.peek()).addFieldMapping(readField(parts)); - } else if (token.equalsIgnoreCase("METHOD")) { - if (mappingStack.isEmpty() || !(mappingStack.peek() instanceof ClassMapping)) { - throw new MappingParseException(filenameSupplier, lineNumber, "Unexpected METHOD entry here!"); - } - MethodMapping methodMapping = readMethod(parts); - ((ClassMapping) mappingStack.peek()).addMethodMapping(methodMapping); - mappingStack.push(methodMapping); - } else if (token.equalsIgnoreCase("ARG")) { - if (mappingStack.isEmpty() || !(mappingStack.peek() instanceof MethodMapping)) { - throw new MappingParseException(filenameSupplier, lineNumber, "Unexpected ARG entry here!"); - } - ((MethodMapping) mappingStack.peek()).addArgumentMapping(readArgument(parts)); - } - } catch (ArrayIndexOutOfBoundsException | IllegalArgumentException ex) { - throw new MappingParseException(filenameSupplier, lineNumber, "Malformed line:\n" + line); - } catch (MappingConflict e) { - throw new MappingParseException(filenameSupplier, lineNumber, e.getMessage()); - } - } - return mappings; - } - } - - private LocalVariableMapping readArgument(String[] parts) { - return new LocalVariableMapping(Integer.parseInt(parts[1]), parts[2]); - } - - private ClassMapping readClass(String[] parts, boolean makeSimple) { - if (parts.length == 2) { - return new ClassMapping(parts[1]); - } else if (parts.length == 3) { - boolean access = parts[2].startsWith("ACC:"); - ClassMapping mapping; - if (access) - mapping = new ClassMapping(parts[1], null, Mappings.EntryModifier.valueOf(parts[2].substring(4))); - else - mapping = new ClassMapping(parts[1], parts[2]); - - return mapping; - } else if (parts.length == 4) - return new ClassMapping(parts[1], parts[2], Mappings.EntryModifier.valueOf(parts[3].substring(4))); - return null; - } - - /* TEMP */ - protected FieldMapping readField(String[] parts) { - FieldMapping mapping = null; - if (parts.length == 4) { - boolean access = parts[3].startsWith("ACC:"); - if (access) - mapping = new FieldMapping(parts[1], new TypeDescriptor(parts[2]), null, - Mappings.EntryModifier.valueOf(parts[3].substring(4))); - else - mapping = new FieldMapping(parts[1], new TypeDescriptor(parts[3]), parts[2], Mappings.EntryModifier.UNCHANGED); - } else if (parts.length == 5) - mapping = new FieldMapping(parts[1], new TypeDescriptor(parts[3]), parts[2], Mappings.EntryModifier.valueOf(parts[4].substring(4))); - return mapping; - } - - private MethodMapping readMethod(String[] parts) { - MethodMapping mapping = null; - if (parts.length == 3) - mapping = new MethodMapping(parts[1], new MethodDescriptor(parts[2])); - else if (parts.length == 4) { - boolean access = parts[3].startsWith("ACC:"); - if (access) - mapping = new MethodMapping(parts[1], new MethodDescriptor(parts[2]), null, Mappings.EntryModifier.valueOf(parts[3].substring(4))); - else - mapping = new MethodMapping(parts[1], new MethodDescriptor(parts[3]), parts[2]); - } else if (parts.length == 5) - mapping = new MethodMapping(parts[1], new MethodDescriptor(parts[3]), parts[2], - Mappings.EntryModifier.valueOf(parts[4].substring(4))); - return mapping; - } -} diff --git a/src/main/java/cuchaz/enigma/mapping/MappingsEnigmaWriter.java b/src/main/java/cuchaz/enigma/mapping/MappingsEnigmaWriter.java deleted file mode 100644 index e3302b1..0000000 --- a/src/main/java/cuchaz/enigma/mapping/MappingsEnigmaWriter.java +++ /dev/null @@ -1,160 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - * - * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.mapping; - -import com.google.common.base.Charsets; - -import java.io.*; -import java.util.*; - -public class MappingsEnigmaWriter { - - public void write(File out, Mappings mappings, boolean isDirectoryFormat) throws IOException { - if (!isDirectoryFormat) { - PrintWriter outputWriter = new PrintWriter(new OutputStreamWriter(new FileOutputStream(out), Charsets.UTF_8)); - write(outputWriter, mappings); - outputWriter.close(); - } else - writeAsDirectory(out, mappings); - } - - public void writeAsDirectory(File target, Mappings mappings) throws IOException { - if (!target.exists() && !target.mkdirs()) - throw new IOException("Cannot create mapping directory!"); - - Mappings previousState = mappings.getPreviousState(); - for (ClassMapping classMapping : sorted(mappings.classes())) { - File result = new File(target, classMapping.getSaveName() + ".mapping"); - - if (!classMapping.isDirty()) { - continue; - } - - if (classMapping.isEmpty()) { - if (result.exists()) { - result.delete(); - } - continue; - } - - if (previousState != null) { - ClassMapping previousClass = previousState.classesByObf.get(classMapping.getObfFullName()); - File previousFile; - if (previousClass != null) { - previousFile = new File(target, previousClass.getSaveName() + ".mapping"); - } else { - previousFile = new File(target, classMapping.getObfFullName() + ".mapping"); - } - if (previousFile.exists() && !previousFile.delete()) { - System.err.println("Failed to delete old class mapping " + previousFile.getName()); - } - } - - File packageFile = result.getParentFile(); - if (!packageFile.exists()) { - packageFile.mkdirs(); - } - result.createNewFile(); - - try (PrintWriter outputWriter = new PrintWriter(new BufferedWriter(new FileWriter(result)))) { - write(outputWriter, classMapping, 0); - } - } - - // Remove dropped mappings - if (previousState != null) { - Set droppedClassMappings = new HashSet<>(previousState.classes()); - droppedClassMappings.removeAll(mappings.classes()); - for (ClassMapping droppedMapping : droppedClassMappings) { - File result = new File(target, droppedMapping.getSaveName() + ".mapping"); - if (!result.exists()) { - continue; - } - if (!result.delete()) { - System.err.println("Failed to delete dropped class mapping " + result.getName()); - } - } - } - } - - public void write(PrintWriter out, Mappings mappings) throws IOException { - for (ClassMapping classMapping : sorted(mappings.classes())) { - write(out, classMapping, 0); - } - } - - protected void write(PrintWriter out, ClassMapping classMapping, int depth) throws IOException { - if (classMapping.getDeobfName() == null) { - out.format("%sCLASS %s%s\n", getIndent(depth), classMapping.getObfFullName(), - classMapping.getModifier() == Mappings.EntryModifier.UNCHANGED ? "" : classMapping.getModifier().getFormattedName()); - } else { - out.format("%sCLASS %s %s%s\n", getIndent(depth), classMapping.getObfFullName(), classMapping.getDeobfName(), - classMapping.getModifier() == Mappings.EntryModifier.UNCHANGED ? "" : classMapping.getModifier().getFormattedName()); - } - - for (ClassMapping innerClassMapping : sorted(classMapping.innerClasses())) { - write(out, innerClassMapping, depth + 1); - } - - for (FieldMapping fieldMapping : sorted(classMapping.fields())) { - write(out, fieldMapping, depth + 1); - } - - for (MethodMapping methodMapping : sorted(classMapping.methods())) { - write(out, methodMapping, depth + 1); - } - } - - private void write(PrintWriter out, FieldMapping fieldMapping, int depth) { - if (fieldMapping.getDeobfName() == null) - out.format("%sFIELD %s %s%s\n", getIndent(depth), fieldMapping.getObfName(), fieldMapping.getObfDesc().toString(), - fieldMapping.getModifier() == Mappings.EntryModifier.UNCHANGED ? "" : fieldMapping.getModifier().getFormattedName()); - else - out.format("%sFIELD %s %s %s%s\n", getIndent(depth), fieldMapping.getObfName(), fieldMapping.getDeobfName(), fieldMapping.getObfDesc().toString(), - fieldMapping.getModifier() == Mappings.EntryModifier.UNCHANGED ? "" : fieldMapping.getModifier().getFormattedName()); - } - - private void write(PrintWriter out, MethodMapping methodMapping, int depth) throws IOException { - if (methodMapping.isObfuscated()) { - out.format("%sMETHOD %s %s%s\n", getIndent(depth), methodMapping.getObfName(), methodMapping.getObfDesc(), - methodMapping.getModifier() == Mappings.EntryModifier.UNCHANGED ? "" : methodMapping.getModifier().getFormattedName()); - } else { - out.format("%sMETHOD %s %s %s%s\n", getIndent(depth), methodMapping.getObfName(), methodMapping.getDeobfName(), methodMapping.getObfDesc(), - methodMapping.getModifier() == Mappings.EntryModifier.UNCHANGED ? "" : methodMapping.getModifier().getFormattedName()); - } - - for (LocalVariableMapping localVariableMapping : sorted(methodMapping.arguments())) { - write(out, localVariableMapping, depth + 1); - } - } - - private void write(PrintWriter out, LocalVariableMapping localVariableMapping, int depth) { - out.format("%sARG %d %s\n", getIndent(depth), localVariableMapping.getIndex(), localVariableMapping.getName()); - } - - protected > List sorted(Iterable classes) { - List out = new ArrayList<>(); - for (T t : classes) { - out.add(t); - } - Collections.sort(out); - return out; - } - - private String getIndent(int depth) { - StringBuilder buf = new StringBuilder(); - for (int i = 0; i < depth; i++) { - buf.append("\t"); - } - return buf.toString(); - } -} diff --git a/src/main/java/cuchaz/enigma/mapping/MappingsRenamer.java b/src/main/java/cuchaz/enigma/mapping/MappingsRenamer.java deleted file mode 100644 index 8ef4f12..0000000 --- a/src/main/java/cuchaz/enigma/mapping/MappingsRenamer.java +++ /dev/null @@ -1,365 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.mapping; - -import com.google.common.collect.Lists; -import cuchaz.enigma.analysis.JarIndex; -import cuchaz.enigma.mapping.entry.*; -import cuchaz.enigma.throwables.IllegalNameException; -import cuchaz.enigma.throwables.MappingConflict; - -import java.io.IOException; -import java.io.ObjectOutputStream; -import java.io.OutputStream; -import java.util.List; -import java.util.Set; -import java.util.zip.GZIPOutputStream; - -public class MappingsRenamer { - - private final JarIndex index; - private final ReferencedEntryPool entryPool; - private Mappings mappings; - - public MappingsRenamer(JarIndex index, Mappings mappings, ReferencedEntryPool entryPool) { - this.index = index; - this.mappings = mappings; - this.entryPool = entryPool; - } - - public void setMappings(Mappings mappings) { - this.mappings = mappings; - } - - public void setClassName(ClassEntry obf, String deobfName) { - - deobfName = NameValidator.validateClassName(deobfName, !obf.isInnerClass()); - - List mappingChain = getOrCreateClassMappingChain(obf); - if (mappingChain.size() == 1) { - - if (deobfName != null) { - // make sure we don't rename to an existing obf or deobf class - if (mappings.containsDeobfClass(deobfName) || index.containsObfClass(entryPool.getClass(deobfName))) { - throw new IllegalNameException(deobfName, "There is already a class with that name"); - } - } - - ClassMapping classMapping = mappingChain.get(0); - mappings.setClassDeobfName(classMapping, deobfName); - - } else { - - ClassMapping outerClassMapping = mappingChain.get(mappingChain.size() - 2); - - if (deobfName != null) { - // make sure we don't rename to an existing obf or deobf inner class - if (outerClassMapping.hasInnerClassByDeobf(deobfName) || outerClassMapping.hasInnerClassByObfSimple(deobfName)) { - throw new IllegalNameException(deobfName, "There is already a class with that name"); - } - } - - outerClassMapping.setInnerClassName(obf, deobfName); - } - } - - public void removeClassMapping(ClassEntry obf) { - setClassName(obf, null); - } - - public void markClassAsDeobfuscated(ClassEntry obf) { - String deobfName = obf.isInnerClass() ? obf.getInnermostClassName() : obf.getName(); - List mappingChain = getOrCreateClassMappingChain(obf); - if (mappingChain.size() == 1) { - ClassMapping classMapping = mappingChain.get(0); - mappings.setClassDeobfName(classMapping, deobfName); - } else { - ClassMapping outerClassMapping = mappingChain.get(mappingChain.size() - 2); - outerClassMapping.setInnerClassName(obf, deobfName); - } - } - - public void setFieldName(FieldEntry obf, String deobfName) { - deobfName = NameValidator.validateFieldName(deobfName); - FieldEntry targetEntry = entryPool.getField(obf.getOwnerClassEntry(), deobfName, obf.getDesc()); - ClassEntry definedClass = null; - if (mappings.containsDeobfField(obf.getOwnerClassEntry(), deobfName) || index.containsEntryWithSameName(targetEntry)) { - definedClass = obf.getOwnerClassEntry(); - } else { - for (ClassEntry ancestorEntry : this.index.getTranslationIndex().getAncestry(obf.getOwnerClassEntry())) { - if (mappings.containsDeobfField(ancestorEntry, deobfName) || index.containsEntryWithSameName(targetEntry.updateOwnership(ancestorEntry))) { - definedClass = ancestorEntry; - break; - } - } - } - - if (definedClass != null) { - Translator translator = mappings.getTranslator(TranslationDirection.DEOBFUSCATING, index.getTranslationIndex()); - String className = translator.getTranslatedClass(entryPool.getClass(definedClass.getClassName())).getName(); - if (className == null) - className = definedClass.getClassName(); - throw new IllegalNameException(deobfName, "There is already a field with that name in " + className); - } - - ClassMapping classMapping = getOrCreateClassMapping(obf.getOwnerClassEntry()); - classMapping.setFieldName(obf.getName(), obf.getDesc(), deobfName); - } - - public void removeFieldMapping(FieldEntry obf) { - ClassMapping classMapping = getOrCreateClassMapping(obf.getOwnerClassEntry()); - classMapping.removeFieldMapping(classMapping.getFieldByObf(obf.getName(), obf.getDesc())); - } - - public void markFieldAsDeobfuscated(FieldEntry obf) { - ClassMapping classMapping = getOrCreateClassMapping(obf.getOwnerClassEntry()); - classMapping.setFieldName(obf.getName(), obf.getDesc(), obf.getName()); - } - - private void validateMethodTreeName(MethodEntry entry, String deobfName) { - MethodEntry targetEntry = entryPool.getMethod(entry.getOwnerClassEntry(), deobfName, entry.getDesc()); - - // TODO: Verify if I don't break things - ClassMapping classMapping = mappings.getClassByObf(entry.getOwnerClassEntry()); - if ((classMapping != null && classMapping.containsDeobfMethod(deobfName, entry.getDesc()) && classMapping.getMethodByObf(entry.getName(), entry.getDesc()) != classMapping.getMethodByDeobf(deobfName, entry.getDesc())) - || index.containsObfMethod(targetEntry)) { - Translator translator = mappings.getTranslator(TranslationDirection.DEOBFUSCATING, index.getTranslationIndex()); - String deobfClassName = translator.getTranslatedClass(entryPool.getClass(entry.getClassName())).getClassName(); - if (deobfClassName == null) { - deobfClassName = entry.getClassName(); - } - throw new IllegalNameException(deobfName, "There is already a method with that name and signature in class " + deobfClassName); - } - - for (ClassEntry child : index.getTranslationIndex().getSubclass(entry.getOwnerClassEntry())) { - validateMethodTreeName(entry.updateOwnership(child), deobfName); - } - } - - public void setMethodTreeName(MethodEntry obf, String deobfName) { - Set implementations = index.getRelatedMethodImplementations(obf); - - deobfName = NameValidator.validateMethodName(deobfName); - for (MethodEntry entry : implementations) { - validateMethodTreeName(entry, deobfName); - } - - for (MethodEntry entry : implementations) { - setMethodName(entry, deobfName); - } - } - - public void setMethodName(MethodEntry obf, String deobfName) { - deobfName = NameValidator.validateMethodName(deobfName); - MethodEntry targetEntry = entryPool.getMethod(obf.getOwnerClassEntry(), deobfName, obf.getDesc()); - ClassMapping classMapping = getOrCreateClassMapping(obf.getOwnerClassEntry()); - - // TODO: Verify if I don't break things - if ((mappings.containsDeobfMethod(obf.getOwnerClassEntry(), deobfName, obf.getDesc()) && classMapping.getMethodByObf(obf.getName(), obf.getDesc()) != classMapping.getMethodByDeobf(deobfName, obf.getDesc())) - || index.containsObfMethod(targetEntry)) { - Translator translator = mappings.getTranslator(TranslationDirection.DEOBFUSCATING, index.getTranslationIndex()); - String deobfClassName = translator.getTranslatedClass(entryPool.getClass(obf.getClassName())).getClassName(); - if (deobfClassName == null) { - deobfClassName = obf.getClassName(); - } - throw new IllegalNameException(deobfName, "There is already a method with that name and signature in class " + deobfClassName); - } - - classMapping.setMethodName(obf.getName(), obf.getDesc(), deobfName); - } - - public void removeMethodTreeMapping(MethodEntry obf) { - index.getRelatedMethodImplementations(obf).forEach(this::removeMethodMapping); - } - - public void removeMethodMapping(MethodEntry obf) { - ClassMapping classMapping = getOrCreateClassMapping(obf.getOwnerClassEntry()); - classMapping.setMethodName(obf.getName(), obf.getDesc(), null); - } - - public void markMethodTreeAsDeobfuscated(MethodEntry obf) { - index.getRelatedMethodImplementations(obf).forEach(this::markMethodAsDeobfuscated); - } - - public void markMethodAsDeobfuscated(MethodEntry obf) { - ClassMapping classMapping = getOrCreateClassMapping(obf.getOwnerClassEntry()); - classMapping.setMethodName(obf.getName(), obf.getDesc(), obf.getName()); - } - - public void setLocalVariableTreeName(LocalVariableEntry obf, String deobfName) { - MethodEntry obfMethod = obf.getOwnerEntry(); - if (!obf.isParameter()) { - setLocalVariableName(obf, deobfName); - return; - } - - Set implementations = index.getRelatedMethodImplementations(obfMethod); - for (MethodEntry entry : implementations) { - ClassMapping classMapping = mappings.getClassByObf(entry.getOwnerClassEntry()); - if (classMapping != null) { - MethodMapping mapping = classMapping.getMethodByObf(entry.getName(), entry.getDesc()); - // NOTE: don't need to check arguments for name collisions with names determined by Procyon - // TODO: Verify if I don't break things - if (mapping != null) { - for (LocalVariableMapping localVariableMapping : Lists.newArrayList(mapping.arguments())) { - if (localVariableMapping.getIndex() != obf.getIndex()) { - if (mapping.getDeobfLocalVariableName(localVariableMapping.getIndex()).equals(deobfName) - || localVariableMapping.getName().equals(deobfName)) { - throw new IllegalNameException(deobfName, "There is already an argument with that name"); - } - } - } - } - } - } - - for (MethodEntry entry : implementations) { - setLocalVariableName(new LocalVariableEntry(entry, obf.getIndex(), obf.getName(), obf.isParameter()), deobfName); - } - } - - public void setLocalVariableName(LocalVariableEntry obf, String deobfName) { - deobfName = NameValidator.validateArgumentName(deobfName); - ClassMapping classMapping = getOrCreateClassMapping(obf.getOwnerClassEntry()); - MethodMapping mapping = classMapping.getMethodByObf(obf.getMethodName(), obf.getMethodDesc()); - // NOTE: don't need to check arguments for name collisions with names determined by Procyon - // TODO: Verify if I don't break things - if (mapping != null) { - for (LocalVariableMapping localVariableMapping : Lists.newArrayList(mapping.arguments())) { - if (localVariableMapping.getIndex() != obf.getIndex()) { - if (mapping.getDeobfLocalVariableName(localVariableMapping.getIndex()).equals(deobfName) - || localVariableMapping.getName().equals(deobfName)) { - throw new IllegalNameException(deobfName, "There is already an argument with that name"); - } - } - } - } - - classMapping.setArgumentName(obf.getMethodName(), obf.getMethodDesc(), obf.getIndex(), deobfName); - } - - public void removeLocalVariableMapping(LocalVariableEntry obf) { - ClassMapping classMapping = getOrCreateClassMapping(obf.getOwnerClassEntry()); - classMapping.removeArgumentName(obf.getMethodName(), obf.getMethodDesc(), obf.getIndex()); - } - - public void markArgumentAsDeobfuscated(LocalVariableEntry obf) { - ClassMapping classMapping = getOrCreateClassMapping(obf.getOwnerClassEntry()); - classMapping.setArgumentName(obf.getMethodName(), obf.getMethodDesc(), obf.getIndex(), obf.getName()); - } - - public boolean moveFieldToObfClass(ClassMapping classMapping, FieldMapping fieldMapping, ClassEntry obfClass) { - classMapping.removeFieldMapping(fieldMapping); - ClassMapping targetClassMapping = getOrCreateClassMapping(obfClass); - if (!targetClassMapping.containsObfField(fieldMapping.getObfName(), fieldMapping.getObfDesc())) { - if (!targetClassMapping.containsDeobfField(fieldMapping.getDeobfName(), fieldMapping.getObfDesc())) { - targetClassMapping.addFieldMapping(fieldMapping); - return true; - } else { - System.err.println("WARNING: deobf field was already there: " + obfClass + "." + fieldMapping.getDeobfName()); - } - } - return false; - } - - public boolean moveMethodToObfClass(ClassMapping classMapping, MethodMapping methodMapping, ClassEntry obfClass) { - classMapping.removeMethodMapping(methodMapping); - ClassMapping targetClassMapping = getOrCreateClassMapping(obfClass); - if (!targetClassMapping.containsObfMethod(methodMapping.getObfName(), methodMapping.getObfDesc())) { - if (!targetClassMapping.containsDeobfMethod(methodMapping.getDeobfName(), methodMapping.getObfDesc())) { - targetClassMapping.addMethodMapping(methodMapping); - return true; - } else { - System.err.println("WARNING: deobf method was already there: " + obfClass + "." + methodMapping.getDeobfName() + methodMapping.getObfDesc()); - } - } - return false; - } - - public void write(OutputStream out) throws IOException { - // TEMP: just use the object output for now. We can find a more efficient storage format later - GZIPOutputStream gzipout = new GZIPOutputStream(out); - ObjectOutputStream oout = new ObjectOutputStream(gzipout); - oout.writeObject(this); - gzipout.finish(); - } - - private ClassMapping getOrCreateClassMapping(ClassEntry obfClassEntry) { - List mappingChain = getOrCreateClassMappingChain(obfClassEntry); - return mappingChain.get(mappingChain.size() - 1); - } - - private List getOrCreateClassMappingChain(ClassEntry obfClassEntry) { - List classChain = obfClassEntry.getClassChain(); - List mappingChain = mappings.getClassMappingChain(obfClassEntry); - for (int i = 0; i < classChain.size(); i++) { - ClassEntry classEntry = classChain.get(i); - ClassMapping classMapping = mappingChain.get(i); - if (classMapping == null) { - - // create it - classMapping = new ClassMapping(classEntry.getName()); - mappingChain.set(i, classMapping); - - // add it to the right parent - try { - if (i == 0) { - mappings.addClassMapping(classMapping); - } else { - mappingChain.get(i - 1).addInnerClassMapping(classMapping); - } - } catch (MappingConflict mappingConflict) { - mappingConflict.printStackTrace(); - } - } - } - return mappingChain; - } - - public void setClassModifier(ClassEntry obEntry, Mappings.EntryModifier modifier) { - ClassMapping classMapping = getOrCreateClassMapping(obEntry); - classMapping.setModifier(modifier); - } - - public void setFieldModifier(FieldEntry obEntry, Mappings.EntryModifier modifier) { - ClassMapping classMapping = getOrCreateClassMapping(obEntry.getOwnerClassEntry()); - classMapping.setFieldModifier(obEntry.getName(), obEntry.getDesc(), modifier); - } - - public void setMethodModifier(MethodEntry obEntry, Mappings.EntryModifier modifier) { - ClassMapping classMapping = getOrCreateClassMapping(obEntry.getOwnerClassEntry()); - classMapping.setMethodModifier(obEntry.getName(), obEntry.getDesc(), modifier); - } - - public Mappings.EntryModifier getClassModifier(ClassEntry obfEntry) { - ClassMapping classMapping = getOrCreateClassMapping(obfEntry); - return classMapping.getModifier(); - } - - public Mappings.EntryModifier getFieldModifier(FieldEntry obfEntry) { - ClassMapping classMapping = getOrCreateClassMapping(obfEntry.getOwnerClassEntry()); - FieldMapping fieldMapping = classMapping.getFieldByObf(obfEntry); - if (fieldMapping == null) { - return Mappings.EntryModifier.UNCHANGED; - } - return fieldMapping.getModifier(); - } - - public Mappings.EntryModifier getMethodModfifier(MethodEntry obfEntry) { - ClassMapping classMapping = getOrCreateClassMapping(obfEntry.getOwnerClassEntry()); - MethodMapping methodMapping = classMapping.getMethodByObf(obfEntry); - if (methodMapping == null) { - return Mappings.EntryModifier.UNCHANGED; - } - return methodMapping.getModifier(); - } -} diff --git a/src/main/java/cuchaz/enigma/mapping/MappingsSRGWriter.java b/src/main/java/cuchaz/enigma/mapping/MappingsSRGWriter.java deleted file mode 100644 index 32f0ee9..0000000 --- a/src/main/java/cuchaz/enigma/mapping/MappingsSRGWriter.java +++ /dev/null @@ -1,80 +0,0 @@ -package cuchaz.enigma.mapping; - -import com.google.common.base.Charsets; -import cuchaz.enigma.analysis.TranslationIndex; -import cuchaz.enigma.mapping.entry.ReferencedEntryPool; - -import java.io.*; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -/** - * Created by Mark on 11/08/2016. - */ -public class MappingsSRGWriter { - - public void write(File file, Mappings mappings) throws IOException { - if (file.exists()) { - file.delete(); - } - file.createNewFile(); - - TranslationIndex index = new TranslationIndex(new ReferencedEntryPool()); - - PrintWriter writer = new PrintWriter(new OutputStreamWriter(new FileOutputStream(file), Charsets.UTF_8)); - List fieldMappings = new ArrayList<>(); - List methodMappings = new ArrayList<>(); - for (ClassMapping classMapping : sorted(mappings.classes())) { - if (classMapping.getDeobfName() == null || classMapping.getObfSimpleName() == null || classMapping.getDeobfName() == null) { - continue; - } - writer.write("CL: " + classMapping.getObfSimpleName() + " " + classMapping.getDeobfName()); - writer.write(System.lineSeparator()); - for (ClassMapping innerClassMapping : sorted(classMapping.innerClasses())) { - if (innerClassMapping.getDeobfName() == null || innerClassMapping.getObfSimpleName() == null || innerClassMapping.getDeobfName() == null) { - continue; - } - String innerClassName = classMapping.getObfSimpleName() + "$" + innerClassMapping.getObfSimpleName(); - String innerDeobfClassName = classMapping.getDeobfName() + "$" + innerClassMapping.getDeobfName(); - writer.write("CL: " + innerClassName + " " + classMapping.getDeobfName() + "$" + innerClassMapping.getDeobfName()); - writer.write(System.lineSeparator()); - for (FieldMapping fieldMapping : sorted(innerClassMapping.fields())) { - fieldMappings.add("FD: " + innerClassName + "/" + fieldMapping.getObfName() + " " + innerDeobfClassName + "/" + fieldMapping.getDeobfName()); - } - - for (MethodMapping methodMapping : sorted(innerClassMapping.methods())) { - methodMappings.add("MD: " + innerClassName + "/" + methodMapping.getObfName() + " " + methodMapping.getObfDesc() + " " + innerDeobfClassName + "/" + methodMapping.getDeobfName() + " " + mappings.getTranslator(TranslationDirection.DEOBFUSCATING, index).getTranslatedMethodDesc(methodMapping.getObfDesc())); - } - } - - for (FieldMapping fieldMapping : sorted(classMapping.fields())) { - fieldMappings.add("FD: " + classMapping.getObfFullName() + "/" + fieldMapping.getObfName() + " " + classMapping.getDeobfName() + "/" + fieldMapping.getDeobfName()); - } - - for (MethodMapping methodMapping : sorted(classMapping.methods())) { - methodMappings.add("MD: " + classMapping.getObfFullName() + "/" + methodMapping.getObfName() + " " + methodMapping.getObfDesc() + " " + classMapping.getDeobfName() + "/" + methodMapping.getDeobfName() + " " + mappings.getTranslator(TranslationDirection.DEOBFUSCATING, index).getTranslatedMethodDesc(methodMapping.getObfDesc())); - } - } - for (String fd : fieldMappings) { - writer.write(fd); - writer.write(System.lineSeparator()); - } - - for (String md : methodMappings) { - writer.write(md); - writer.write(System.lineSeparator()); - } - - writer.close(); - } - - private > List sorted(Iterable classes) { - List out = new ArrayList<>(); - for (T t : classes) { - out.add(t); - } - Collections.sort(out); - return out; - } -} diff --git a/src/main/java/cuchaz/enigma/mapping/MappingsTinyReader.java b/src/main/java/cuchaz/enigma/mapping/MappingsTinyReader.java deleted file mode 100644 index 756ac43..0000000 --- a/src/main/java/cuchaz/enigma/mapping/MappingsTinyReader.java +++ /dev/null @@ -1,130 +0,0 @@ -package cuchaz.enigma.mapping; - -import com.google.common.base.Charsets; -import com.google.common.collect.Maps; -import cuchaz.enigma.mapping.entry.ClassEntry; -import cuchaz.enigma.throwables.MappingConflict; -import cuchaz.enigma.throwables.MappingParseException; - -import java.io.File; -import java.io.IOException; -import java.nio.file.Files; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -public class MappingsTinyReader { - public ClassMapping readClass(String[] parts) { - // Extract the inner naming of the deob form if it have one - String deobName = parts[2].contains("$") ? parts[2].substring(parts[2].lastIndexOf('$') + 1) : parts[2]; - return new ClassMapping(parts[1], deobName).setDeobfInner(parts[2]); - } - - public FieldMapping readField(String[] parts) { - return new FieldMapping(parts[3], new TypeDescriptor(parts[2]), parts[4], Mappings.EntryModifier.UNCHANGED); - } - - public MethodMapping readMethod(String[] parts) { - return new MethodMapping(parts[3], new MethodDescriptor(parts[2]), parts[4]); - } - - public Mappings read(File file) throws IOException, MappingParseException { - Mappings mappings = new Mappings(Mappings.FormatType.TINY_FILE); - List lines = Files.readAllLines(file.toPath(), Charsets.UTF_8); - Map classMappingMap = Maps.newHashMap(); - lines.remove(0); // TODO: use the header - for (int lineNumber = 0; lineNumber < lines.size(); lineNumber++) { - String line = lines.get(lineNumber); - String[] parts = line.split("\t"); - try { - String token = parts[0]; - ClassMapping classMapping; - switch (token) { - case "CLASS": - - // Check for orphan created by field or method entries. It shouldn't be possible but I prefer to handle this case - if (classMappingMap.containsKey(parts[1])) { - classMapping = classMappingMap.get(parts[1]); - - // We have the full deob name, Enigma only support simple class name so we extract it. - String deobName = parts[2].contains("$") ? - parts[2].substring(parts[2].lastIndexOf('$') + 1) : - parts[2]; - - // Add full deob name to the class mapping to handle inner class after this loop - classMappingMap.put(parts[2], classMapping.setDeobfInner(parts[2])); - classMapping.setDeobfName(deobName); - - // Avoid to make the mapping dirty directly at the startup - classMapping.resetDirty(); - } else - classMapping = readClass(parts); - classMappingMap.put(parts[1], classMapping); - break; - case "FIELD": - // We can have missing classes mappings because they don't have a ob name, so we create it and use it - classMapping = classMappingMap.computeIfAbsent(parts[1], k -> new ClassMapping(parts[1])); - classMapping.addFieldMapping(readField(parts)); - break; - case "METHOD": - // We can have missing classes mappings because they don't have a ob name, so we create it and use it - classMapping = classMappingMap.computeIfAbsent(parts[1], k -> new ClassMapping(parts[1])); - classMapping.addMethodMapping(readMethod(parts)); - break; - case "MTH-ARG": - classMapping = classMappingMap.computeIfAbsent(parts[1], k -> new ClassMapping(parts[1])); - classMapping.setArgumentName(parts[3], new MethodDescriptor(parts[2]), Integer.parseInt(parts[4]), parts[5]); - break; - default: - throw new MappingParseException(file, lineNumber, "Unknown token '" + token + "' !"); - } - } catch (ArrayIndexOutOfBoundsException | IllegalArgumentException ex) { - ex.printStackTrace(); - throw new MappingParseException(file, lineNumber, "Malformed line:\n" + line); - } - } - - List toRegister = new ArrayList<>(classMappingMap.values()); - - // After having completely parsed the file, we need to register it to the real mapping - for (ClassMapping classMapping : toRegister) { - ClassEntry obEntry = classMapping.getObfEntry(); - ClassEntry deobEntry = classMapping.getDeObfEntry(); - try { - if (obEntry.isInnerClass()) { - ClassMapping parent = classMappingMap.get(obEntry.getOuterClassName()); - // Inner class can miss their parent... So we create it and add it to the mappings - if (parent == null) { - parent = new ClassMapping(obEntry.getOuterClassName()); // FIXME: WE ACTUALLY DON'T MANAGE INNER CLASS OF INNER CLASS - classMappingMap.put(obEntry.getOuterClassName(), parent); - mappings.addClassMapping(parent); - } - // Add the inner class to the parent - parent.addInnerClassMapping(classMapping); - } - // obf class can become deobf inner classs, manage this case. - else if (deobEntry != null && deobEntry.isInnerClass()) { - String outerClassName = deobEntry.getOuterClassName(); - ClassMapping parent = classMappingMap.get(outerClassName); - - // Only the inner is deob??? Okay - if (parent == null) { - parent = classMappingMap.get(outerClassName); - if (parent == null) { - parent = new ClassMapping(outerClassName); // FIXME: WE ACTUALLY DON'T MANAGE INNER CLASS OF INNER CLASS - classMappingMap.put(outerClassName, parent); - mappings.addClassMapping(parent); - } - } - parent.addInnerClassMapping(classMapping); - } else - mappings.addClassMapping(classMapping); - } catch (MappingConflict e) { - throw new MappingParseException(file, -1, e.getMessage()); - } - } - lines.clear(); - classMappingMap.clear(); - return mappings; - } -} diff --git a/src/main/java/cuchaz/enigma/mapping/MemberMapping.java b/src/main/java/cuchaz/enigma/mapping/MemberMapping.java deleted file mode 100644 index 6effb91..0000000 --- a/src/main/java/cuchaz/enigma/mapping/MemberMapping.java +++ /dev/null @@ -1,21 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.mapping; - -import cuchaz.enigma.mapping.entry.ClassEntry; -import cuchaz.enigma.mapping.entry.Entry; - -public interface MemberMapping { - T getObfEntry(ClassEntry classEntry); - - String getObfName(); -} diff --git a/src/main/java/cuchaz/enigma/mapping/MethodDescriptor.java b/src/main/java/cuchaz/enigma/mapping/MethodDescriptor.java deleted file mode 100644 index 0fc0351..0000000 --- a/src/main/java/cuchaz/enigma/mapping/MethodDescriptor.java +++ /dev/null @@ -1,114 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.mapping; - -import com.google.common.collect.Lists; -import cuchaz.enigma.mapping.entry.ClassEntry; -import cuchaz.enigma.utils.Utils; - -import java.util.ArrayList; -import java.util.List; -import java.util.function.Function; - -public class MethodDescriptor { - - private List argumentDescs; - private TypeDescriptor returnDesc; - - public MethodDescriptor(String desc) { - try { - this.argumentDescs = Lists.newArrayList(); - int i = 0; - while (i < desc.length()) { - char c = desc.charAt(i); - if (c == '(') { - assert (this.argumentDescs.isEmpty()); - assert (this.returnDesc == null); - i++; - } else if (c == ')') { - i++; - break; - } else { - String type = TypeDescriptor.parseFirst(desc.substring(i)); - this.argumentDescs.add(new TypeDescriptor(type)); - i += type.length(); - } - } - this.returnDesc = new TypeDescriptor(TypeDescriptor.parseFirst(desc.substring(i))); - } catch (Exception ex) { - throw new IllegalArgumentException("Unable to parse method descriptor: " + desc, ex); - } - } - - public MethodDescriptor(List argumentDescs, TypeDescriptor returnDesc) { - this.argumentDescs = argumentDescs; - this.returnDesc = returnDesc; - } - - public List getArgumentDescs() { - return this.argumentDescs; - } - - public TypeDescriptor getReturnDesc() { - return this.returnDesc; - } - - @Override - public String toString() { - StringBuilder buf = new StringBuilder(); - buf.append("("); - for (TypeDescriptor desc : this.argumentDescs) { - buf.append(desc); - } - buf.append(")"); - buf.append(this.returnDesc); - return buf.toString(); - } - - public Iterable types() { - List descs = Lists.newArrayList(); - descs.addAll(this.argumentDescs); - descs.add(this.returnDesc); - return descs; - } - - @Override - public boolean equals(Object other) { - return other instanceof MethodDescriptor && equals((MethodDescriptor) other); - } - - public boolean equals(MethodDescriptor other) { - return this.argumentDescs.equals(other.argumentDescs) && this.returnDesc.equals(other.returnDesc); - } - - @Override - public int hashCode() { - return Utils.combineHashesOrdered(this.argumentDescs.hashCode(), this.returnDesc.hashCode()); - } - - public boolean hasClass(ClassEntry classEntry) { - for (TypeDescriptor desc : types()) { - if (desc.containsType() && desc.getTypeEntry().equals(classEntry)) { - return true; - } - } - return false; - } - - public MethodDescriptor remap(Function remapper) { - List argumentDescs = new ArrayList<>(this.argumentDescs.size()); - for (TypeDescriptor desc : this.argumentDescs) { - argumentDescs.add(desc.remap(remapper)); - } - return new MethodDescriptor(argumentDescs, returnDesc.remap(remapper)); - } -} diff --git a/src/main/java/cuchaz/enigma/mapping/MethodMapping.java b/src/main/java/cuchaz/enigma/mapping/MethodMapping.java deleted file mode 100644 index 2f10144..0000000 --- a/src/main/java/cuchaz/enigma/mapping/MethodMapping.java +++ /dev/null @@ -1,210 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.mapping; - -import com.google.common.base.Preconditions; -import com.google.common.collect.Maps; -import cuchaz.enigma.mapping.entry.ClassEntry; -import cuchaz.enigma.mapping.entry.MethodEntry; -import cuchaz.enigma.throwables.IllegalNameException; -import cuchaz.enigma.throwables.MappingConflict; - -import java.util.Map; - -public class MethodMapping implements Comparable, MemberMapping { - - private String obfName; - private String deobfName; - private MethodDescriptor obfDescriptor; - private Map localVariables; - private Mappings.EntryModifier modifier; - - public MethodMapping(String obfName, MethodDescriptor obfDescriptor) { - this(obfName, obfDescriptor, null, Mappings.EntryModifier.UNCHANGED); - } - - public MethodMapping(String obfName, MethodDescriptor obfDescriptor, String deobfName) { - this(obfName, obfDescriptor, deobfName, Mappings.EntryModifier.UNCHANGED); - } - - public MethodMapping(String obfName, MethodDescriptor obfDescriptor, String deobfName, Mappings.EntryModifier modifier) { - Preconditions.checkNotNull(obfName, "Method obf name cannot be null"); - Preconditions.checkNotNull(obfDescriptor, "Method obf desc cannot be null"); - this.obfName = obfName; - this.deobfName = NameValidator.validateMethodName(deobfName); - this.obfDescriptor = obfDescriptor; - this.localVariables = Maps.newTreeMap(); - this.modifier = modifier; - } - - public MethodMapping(MethodMapping other, Translator translator) { - this.obfName = other.obfName; - this.deobfName = other.deobfName; - this.modifier = other.modifier; - this.obfDescriptor = translator.getTranslatedMethodDesc(other.obfDescriptor); - this.localVariables = Maps.newTreeMap(); - for (Map.Entry entry : other.localVariables.entrySet()) { - this.localVariables.put(entry.getKey(), new LocalVariableMapping(entry.getValue())); - } - } - - @Override - public String getObfName() { - return this.obfName; - } - - public void setObfName(String name) { - try { - NameValidator.validateMethodName(name); - } catch (IllegalNameException ex) { - // Invalid name, damn obfuscation! Map to a deob name with another name to avoid issues - if (this.deobfName == null) { - System.err.println("WARNING: " + name + " is conflicting, auto deobfuscate to " + (name + "_auto_deob")); - setDeobfName(name + "_auto_deob"); - } - } - this.obfName = name; - } - - public String getDeobfName() { - if (deobfName == null) { - return obfName; - } - return this.deobfName; - } - - public void setDeobfName(String val) { - this.deobfName = NameValidator.validateMethodName(val); - } - - public MethodDescriptor getObfDesc() { - return this.obfDescriptor; - } - - public void setObfDescriptor(MethodDescriptor val) { - this.obfDescriptor = val; - } - - public Iterable arguments() { - return this.localVariables.values(); - } - - public void addArgumentMapping(LocalVariableMapping localVariableMapping) throws MappingConflict { - if (this.localVariables.containsKey(localVariableMapping.getIndex())) { - throw new MappingConflict("argument", localVariableMapping.getName(), this.localVariables.get(localVariableMapping.getIndex()).getName()); - } - this.localVariables.put(localVariableMapping.getIndex(), localVariableMapping); - } - - public String getObfLocalVariableName(int index) { - LocalVariableMapping localVariableMapping = this.localVariables.get(index); - if (localVariableMapping != null) { - return localVariableMapping.getName(); - } - - return null; - } - - public String getDeobfLocalVariableName(int index) { - LocalVariableMapping localVariableMapping = this.localVariables.get(index); - if (localVariableMapping != null) { - return localVariableMapping.getName(); - } - - return null; - } - - public void setLocalVariableName(int index, String name) { - LocalVariableMapping localVariableMapping = this.localVariables.get(index); - if (localVariableMapping == null) { - localVariableMapping = new LocalVariableMapping(index, name); - boolean wasAdded = this.localVariables.put(index, localVariableMapping) == null; - assert (wasAdded); - } else { - localVariableMapping.setName(name); - } - } - - public void removeLocalVariableName(int index) { - boolean wasRemoved = this.localVariables.remove(index) != null; - assert (wasRemoved); - } - - @Override - public String toString() { - StringBuilder buf = new StringBuilder(); - buf.append("\t"); - buf.append(this.obfName); - buf.append(" <-> "); - buf.append(this.deobfName); - buf.append("\n"); - buf.append("\t"); - buf.append(this.obfDescriptor); - buf.append("\n"); - buf.append("\tLocal Variables:\n"); - for (LocalVariableMapping localVariableMapping : this.localVariables.values()) { - buf.append("\t\t"); - buf.append(localVariableMapping.getIndex()); - buf.append(" -> "); - buf.append(localVariableMapping.getName()); - buf.append("\n"); - } - return buf.toString(); - } - - @Override - public int compareTo(MethodMapping other) { - return (this.obfName + this.obfDescriptor).compareTo(other.obfName + other.obfDescriptor); - } - - public boolean containsLocalVariable(String name) { - for (LocalVariableMapping localVariableMapping : this.localVariables.values()) { - if (localVariableMapping.getName().equals(name)) { - return true; - } - } - return false; - } - - public boolean renameObfClass(final String oldObfClassName, final String newObfClassName) { - // rename obf classes in the signature - MethodDescriptor newDescriptor = obfDescriptor.remap(className -> { - if (className.equals(oldObfClassName)) { - return newObfClassName; - } - return className; - }); - - if (!newDescriptor.equals(this.obfDescriptor)) { - this.obfDescriptor = newDescriptor; - return true; - } - return false; - } - - @Override - public MethodEntry getObfEntry(ClassEntry classEntry) { - return new MethodEntry(classEntry, this.obfName, this.obfDescriptor); - } - - public Mappings.EntryModifier getModifier() { - return modifier; - } - - public void setModifier(Mappings.EntryModifier modifier) { - this.modifier = modifier; - } - - public boolean isObfuscated() { - return deobfName == null || deobfName.equals(obfName); - } -} diff --git a/src/main/java/cuchaz/enigma/mapping/NameValidator.java b/src/main/java/cuchaz/enigma/mapping/NameValidator.java deleted file mode 100644 index fca8cfc..0000000 --- a/src/main/java/cuchaz/enigma/mapping/NameValidator.java +++ /dev/null @@ -1,73 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.mapping; - -import cuchaz.enigma.mapping.entry.ClassEntry; -import cuchaz.enigma.throwables.IllegalNameException; - -import java.util.Arrays; -import java.util.List; -import java.util.regex.Pattern; - -public class NameValidator { - - private static final Pattern IdentifierPattern; - private static final Pattern ClassPattern; - private static final List ReservedWords = Arrays.asList( - "abstract", "continue", "for", "new", "switch", "assert", "default", "goto", "package", "synchronized", - "boolean", "do", "if", "private", "this", "break", "double", "implements", "protected", "throw", "byte", - "else", "import", "public", "throws", "case", "enum", "instanceof", "return", "transient", "catch", - "extends", "int", "short", "try", "char", "final", "interface", "static", "void", "class", "finally", - "long", "strictfp", "volatile", "const", "float", "native", "super", "while" - ); - - static { - String identifierRegex = "[A-Za-z_<][A-Za-z0-9_>]*"; - IdentifierPattern = Pattern.compile(identifierRegex); - ClassPattern = Pattern.compile(String.format("^(%s(\\.|/))*(%s)$", identifierRegex, identifierRegex)); - } - - public static String validateClassName(String name, boolean packageRequired) { - if (name == null) { - return null; - } - if (!ClassPattern.matcher(name).matches() || ReservedWords.contains(name)) { - throw new IllegalNameException(name, "This doesn't look like a legal class name"); - } - if (packageRequired && ClassEntry.getPackageName(name) == null) { - throw new IllegalNameException(name, "Class must be in a package"); - } - return name; - } - - public static String validateFieldName(String name) { - if (name == null) { - return null; - } - if (!IdentifierPattern.matcher(name).matches() || ReservedWords.contains(name)) { - throw new IllegalNameException(name, "This doesn't look like a legal identifier"); - } - return name; - } - - public static String validateMethodName(String name) { - return validateFieldName(name); - } - - public static String validateArgumentName(String name) { - return validateFieldName(name); - } - - public static boolean isReserved(String name) { - return ReservedWords.contains(name); - } -} diff --git a/src/main/java/cuchaz/enigma/mapping/Signature.java b/src/main/java/cuchaz/enigma/mapping/Signature.java deleted file mode 100644 index 071e4af..0000000 --- a/src/main/java/cuchaz/enigma/mapping/Signature.java +++ /dev/null @@ -1,82 +0,0 @@ -package cuchaz.enigma.mapping; - -import cuchaz.enigma.bytecode.translators.TranslationSignatureVisitor; -import org.objectweb.asm.signature.SignatureReader; -import org.objectweb.asm.signature.SignatureVisitor; -import org.objectweb.asm.signature.SignatureWriter; - -import java.util.function.Function; -import java.util.regex.Pattern; - -public class Signature { - private static final Pattern OBJECT_PATTERN = Pattern.compile(".*:Ljava/lang/Object;:.*"); - - private final String signature; - private final boolean isType; - - private Signature(String signature, boolean isType) { - if (signature != null && OBJECT_PATTERN.matcher(signature).matches()) { - signature = signature.replaceAll(":Ljava/lang/Object;:", "::"); - } - - this.signature = signature; - this.isType = isType; - } - - public static Signature createTypedSignature(String signature) { - if (signature != null && !signature.isEmpty()) { - return new Signature(signature, true); - } - return new Signature(null, true); - } - - public static Signature createSignature(String signature) { - if (signature != null && !signature.isEmpty()) { - return new Signature(signature, false); - } - return new Signature(null, false); - } - - public String getSignature() { - return signature; - } - - public boolean isType() { - return isType; - } - - public Signature remap(Function remapper) { - if (signature == null) { - return this; - } - SignatureWriter writer = new SignatureWriter(); - SignatureVisitor visitor = new TranslationSignatureVisitor(remapper, writer); - if (isType) { - new SignatureReader(signature).acceptType(visitor); - } else { - new SignatureReader(signature).accept(visitor); - } - return new Signature(writer.toString(), isType); - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof Signature) { - Signature other = (Signature) obj; - return (other.signature == null && signature == null || other.signature != null - && signature != null && other.signature.equals(signature)) - && other.isType == this.isType; - } - return false; - } - - @Override - public int hashCode() { - return signature.hashCode() | (isType ? 1 : 0) << 16; - } - - @Override - public String toString() { - return signature; - } -} diff --git a/src/main/java/cuchaz/enigma/mapping/SignatureUpdater.java b/src/main/java/cuchaz/enigma/mapping/SignatureUpdater.java deleted file mode 100644 index ddc5af4..0000000 --- a/src/main/java/cuchaz/enigma/mapping/SignatureUpdater.java +++ /dev/null @@ -1,92 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.mapping; - -import com.google.common.collect.Lists; - -import java.io.IOException; -import java.io.StringReader; -import java.util.List; - -public class SignatureUpdater { - - public static String update(String signature, ClassNameUpdater updater) { - try { - StringBuilder buf = new StringBuilder(); - - // read the signature character-by-character - StringReader reader = new StringReader(signature); - int i; - while ((i = reader.read()) != -1) { - char c = (char) i; - - // does this character start a class name? - if (c == 'L') { - // update the class name and add it to the buffer - buf.append('L'); - String className = readClass(reader); - if (className == null) { - throw new IllegalArgumentException("Malformed signature: " + signature); - } - buf.append(updater.update(className)); - buf.append(';'); - } else { - // copy the character into the buffer - buf.append(c); - } - } - - return buf.toString(); - } catch (IOException ex) { - // I'm pretty sure a StringReader will never throw one of these - throw new Error(ex); - } - } - - private static String readClass(StringReader reader) throws IOException { - // read all the characters in the buffer until we hit a ';' - // remember to treat generics correctly - StringBuilder buf = new StringBuilder(); - int depth = 0; - int i; - while ((i = reader.read()) != -1) { - char c = (char) i; - - if (c == '<') { - depth++; - } else if (c == '>') { - depth--; - } else if (depth == 0) { - if (c == ';') { - return buf.toString(); - } else { - buf.append(c); - } - } - } - - return null; - } - - public static List getClasses(String signature) { - final List classNames = Lists.newArrayList(); - update(signature, className -> { - classNames.add(className); - return className; - }); - return classNames; - } - - public interface ClassNameUpdater { - String update(String className); - } -} diff --git a/src/main/java/cuchaz/enigma/mapping/TranslationDirection.java b/src/main/java/cuchaz/enigma/mapping/TranslationDirection.java deleted file mode 100644 index 4bbde54..0000000 --- a/src/main/java/cuchaz/enigma/mapping/TranslationDirection.java +++ /dev/null @@ -1,36 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.mapping; - -public enum TranslationDirection { - - DEOBFUSCATING { - @Override - public T choose(T deobfChoice, T obfChoice) { - if (deobfChoice == null) { - return obfChoice; - } - return deobfChoice; - } - }, - OBFUSCATING { - @Override - public T choose(T deobfChoice, T obfChoice) { - if (obfChoice == null) { - return deobfChoice; - } - return obfChoice; - } - }; - - public abstract T choose(T deobfChoice, T obfChoice); -} diff --git a/src/main/java/cuchaz/enigma/mapping/Translator.java b/src/main/java/cuchaz/enigma/mapping/Translator.java deleted file mode 100644 index a9ff1cb..0000000 --- a/src/main/java/cuchaz/enigma/mapping/Translator.java +++ /dev/null @@ -1,109 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.mapping; - -import cuchaz.enigma.mapping.entry.*; -import org.objectweb.asm.Handle; -import org.objectweb.asm.Type; - -public interface Translator { - ClassEntry getTranslatedClass(ClassEntry entry); - - ClassDefEntry getTranslatedClassDef(ClassDefEntry entry); - - FieldEntry getTranslatedField(FieldEntry entry); - - FieldDefEntry getTranslatedFieldDef(FieldDefEntry entry); - - MethodEntry getTranslatedMethod(MethodEntry entry); - - MethodDefEntry getTranslatedMethodDef(MethodDefEntry entry); - - LocalVariableEntry getTranslatedVariable(LocalVariableEntry entry); - - LocalVariableDefEntry getTranslatedVariableDef(LocalVariableDefEntry entry); - - boolean hasClassMapping(ClassEntry entry); - - boolean hasFieldMapping(FieldEntry entry); - - boolean hasMethodMapping(MethodEntry entry); - - boolean hasLocalVariableMapping(LocalVariableEntry entry); - - TypeDescriptor getTranslatedTypeDesc(TypeDescriptor desc); - - MethodDescriptor getTranslatedMethodDesc(MethodDescriptor descriptor); - - Signature getTranslatedSignature(Signature signature); - - default Type getTranslatedType(Type type) { - String descString = type.getDescriptor(); - switch (type.getSort()) { - case Type.OBJECT: { - ClassEntry classEntry = new ClassEntry(type.getInternalName()); - return Type.getObjectType(getTranslatedClass(classEntry).getName()); - } - case Type.ARRAY: { - TypeDescriptor descriptor = new TypeDescriptor(descString); - return Type.getType(getTranslatedTypeDesc(descriptor).toString()); - } - case Type.METHOD: { - MethodDescriptor descriptor = new MethodDescriptor(descString); - return Type.getMethodType(getTranslatedMethodDesc(descriptor).toString()); - } - } - return type; - } - - default Handle getTranslatedHandle(Handle handle) { - MethodEntry entry = new MethodEntry(new ClassEntry(handle.getOwner()), handle.getName(), new MethodDescriptor(handle.getDesc())); - MethodEntry translatedMethod = getTranslatedMethod(entry); - ClassEntry ownerClass = translatedMethod.getOwnerClassEntry(); - return new Handle(handle.getTag(), ownerClass.getName(), translatedMethod.getName(), translatedMethod.getDesc().toString(), handle.isInterface()); - } - - default Object getTranslatedValue(Object value) { - if (value instanceof Type) { - return this.getTranslatedType((Type) value); - } else if (value instanceof Handle) { - return getTranslatedHandle((Handle) value); - } - return value; - } - - @SuppressWarnings("unchecked") - default T getTranslatedEntry(T entry) { - if (entry instanceof ClassDefEntry) { - return (T) getTranslatedClassDef((ClassDefEntry) entry); - } else if (entry instanceof ClassEntry) { - return (T) getTranslatedClass((ClassEntry) entry); - } else if (entry instanceof FieldDefEntry) { - return (T) getTranslatedFieldDef((FieldDefEntry) entry); - } else if (entry instanceof MethodDefEntry) { - return (T) getTranslatedMethodDef((MethodDefEntry) entry); - } else if (entry instanceof FieldEntry) { - return (T) getTranslatedField((FieldEntry) entry); - } else if (entry instanceof MethodEntry) { - return (T) getTranslatedMethod((MethodEntry) entry); - } else if (entry instanceof LocalVariableDefEntry) { - return (T) getTranslatedVariableDef((LocalVariableDefEntry) entry); - } else if (entry instanceof LocalVariableEntry) { - return (T) getTranslatedVariable((LocalVariableEntry) entry); - } else if (entry instanceof TypeDescriptor) { - return (T) getTranslatedTypeDesc((TypeDescriptor) entry); - } else if (entry instanceof MethodDescriptor) { - return (T) getTranslatedMethodDesc((MethodDescriptor) entry); - } - throw new IllegalArgumentException("Cannot translate unknown entry type"); - } -} diff --git a/src/main/java/cuchaz/enigma/mapping/TypeDescriptor.java b/src/main/java/cuchaz/enigma/mapping/TypeDescriptor.java deleted file mode 100644 index 6e58aa0..0000000 --- a/src/main/java/cuchaz/enigma/mapping/TypeDescriptor.java +++ /dev/null @@ -1,258 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.mapping; - -import com.google.common.base.Preconditions; -import com.google.common.collect.Maps; -import cuchaz.enigma.mapping.entry.ClassEntry; - -import java.util.Map; -import java.util.function.Function; - -public class TypeDescriptor { - - protected final String desc; - - public TypeDescriptor(String desc) { - Preconditions.checkNotNull(desc, "Desc cannot be null"); - - // don't deal with generics - // this is just for raw jvm types - if (desc.charAt(0) == 'T' || desc.indexOf('<') >= 0 || desc.indexOf('>') >= 0) { - throw new IllegalArgumentException("don't use with generic types or templates: " + desc); - } - - this.desc = desc; - } - - public static String parseFirst(String in) { - - if (in == null || in.length() <= 0) { - throw new IllegalArgumentException("No desc to parse, input is empty!"); - } - - // read one desc from the input - - char c = in.charAt(0); - - // first check for void - if (c == 'V') { - return "V"; - } - - // then check for primitives - Primitive primitive = Primitive.get(c); - if (primitive != null) { - return in.substring(0, 1); - } - - // then check for classes - if (c == 'L') { - return readClass(in); - } - - // then check for templates - if (c == 'T') { - return readClass(in); - } - - // then check for arrays - int dim = countArrayDimension(in); - if (dim > 0) { - String arrayType = TypeDescriptor.parseFirst(in.substring(dim)); - return in.substring(0, dim + arrayType.length()); - } - - throw new IllegalArgumentException("don't know how to parse: " + in); - } - - private static int countArrayDimension(String in) { - int i = 0; - while (i < in.length() && in.charAt(i) == '[') - i++; - return i; - } - - private static String readClass(String in) { - // read all the characters in the buffer until we hit a ';' - // include the parameters too - StringBuilder buf = new StringBuilder(); - int depth = 0; - for (int i = 0; i < in.length(); i++) { - char c = in.charAt(i); - buf.append(c); - - if (c == '<') { - depth++; - } else if (c == '>') { - depth--; - } else if (depth == 0 && c == ';') { - return buf.toString(); - } - } - return null; - } - - public static TypeDescriptor of(String name) { - return new TypeDescriptor("L" + name + ";"); - } - - @Override - public String toString() { - return this.desc; - } - - public boolean isVoid() { - return this.desc.length() == 1 && this.desc.charAt(0) == 'V'; - } - - public boolean isPrimitive() { - return this.desc.length() == 1 && Primitive.get(this.desc.charAt(0)) != null; - } - - public Primitive getPrimitive() { - if (!isPrimitive()) { - throw new IllegalStateException("not a primitive"); - } - return Primitive.get(this.desc.charAt(0)); - } - - public boolean isType() { - return this.desc.charAt(0) == 'L' && this.desc.charAt(this.desc.length() - 1) == ';'; - } - - public ClassEntry getTypeEntry() { - if (isType()) { - String name = this.desc.substring(1, this.desc.length() - 1); - - int pos = name.indexOf('<'); - if (pos >= 0) { - // remove the parameters from the class name - name = name.substring(0, pos); - } - - return new ClassEntry(name); - - } else if (isArray() && getArrayType().isType()) { - return getArrayType().getTypeEntry(); - } else { - throw new IllegalStateException("desc doesn't have a class"); - } - } - - public boolean isArray() { - return this.desc.charAt(0) == '['; - } - - public int getArrayDimension() { - if (!isArray()) { - throw new IllegalStateException("not an array"); - } - return countArrayDimension(this.desc); - } - - public TypeDescriptor getArrayType() { - if (!isArray()) { - throw new IllegalStateException("not an array"); - } - return new TypeDescriptor(this.desc.substring(getArrayDimension(), this.desc.length())); - } - - public boolean containsType() { - return isType() || (isArray() && getArrayType().containsType()); - } - - @Override - public boolean equals(Object other) { - return other instanceof TypeDescriptor && equals((TypeDescriptor) other); - } - - public boolean equals(TypeDescriptor other) { - return this.desc.equals(other.desc); - } - - @Override - public int hashCode() { - return this.desc.hashCode(); - } - - public TypeDescriptor remap(Function remapper) { - String desc = this.desc; - if (isType() || (isArray() && containsType())) { - String replacedName = remapper.apply(this.getTypeEntry().getName()); - if (replacedName != null) { - if (this.isType()) { - desc = "L" + replacedName + ";"; - } else { - desc = getArrayPrefix(this.getArrayDimension()) + "L" + replacedName + ";"; - } - } - } - return new TypeDescriptor(desc); - } - - private static String getArrayPrefix(int dimension) { - StringBuilder buf = new StringBuilder(); - for (int i = 0; i < dimension; i++) { - buf.append("["); - } - return buf.toString(); - } - - public int getSize() { - switch (desc.charAt(0)) { - case 'J': - case 'D': - if (desc.length() == 1) { - return 2; - } else { - return 1; - } - default: - return 1; - } - } - - public enum Primitive { - BYTE('B'), - CHARACTER('C'), - SHORT('S'), - INTEGER('I'), - LONG('J'), - FLOAT('F'), - DOUBLE('D'), - BOOLEAN('Z'); - - private static final Map lookup; - - static { - lookup = Maps.newTreeMap(); - for (Primitive val : values()) { - lookup.put(val.getCode(), val); - } - } - - private char code; - - Primitive(char code) { - this.code = code; - } - - public static Primitive get(char code) { - return lookup.get(code); - } - - public char getCode() { - return this.code; - } - } -} diff --git a/src/main/java/cuchaz/enigma/mapping/entry/ClassDefEntry.java b/src/main/java/cuchaz/enigma/mapping/entry/ClassDefEntry.java deleted file mode 100644 index df72e7e..0000000 --- a/src/main/java/cuchaz/enigma/mapping/entry/ClassDefEntry.java +++ /dev/null @@ -1,38 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.mapping.entry; - -import com.google.common.base.Preconditions; -import cuchaz.enigma.bytecode.AccessFlags; -import cuchaz.enigma.mapping.Signature; - -public class ClassDefEntry extends ClassEntry implements DefEntry { - private final AccessFlags access; - private final Signature signature; - - public ClassDefEntry(String className, Signature signature, AccessFlags access) { - super(className); - Preconditions.checkNotNull(signature, "Class signature cannot be null"); - Preconditions.checkNotNull(access, "Class access cannot be null"); - this.signature = signature; - this.access = access; - } - - public Signature getSignature() { - return signature; - } - - @Override - public AccessFlags getAccess() { - return access; - } -} diff --git a/src/main/java/cuchaz/enigma/mapping/entry/ClassEntry.java b/src/main/java/cuchaz/enigma/mapping/entry/ClassEntry.java deleted file mode 100644 index c795825..0000000 --- a/src/main/java/cuchaz/enigma/mapping/entry/ClassEntry.java +++ /dev/null @@ -1,175 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.mapping.entry; - -import com.google.common.base.Preconditions; -import com.google.common.collect.Lists; - -import java.util.List; - -public class ClassEntry implements Entry { - - private final String name; - - public ClassEntry(String className) { - Preconditions.checkNotNull(className, "Class name cannot be null"); - - if (className.indexOf('.') >= 0) { - throw new IllegalArgumentException("Class name must be in JVM format. ie, path/to/package/class$inner : " + className); - } - - this.name = className; - - if (isInnerClass() && getInnermostClassName().indexOf('/') >= 0) { - throw new IllegalArgumentException("Inner class must not have a package: " + className); - } - } - - public ClassEntry(ClassEntry other) { - this.name = other.name; - } - - @Override - public String getName() { - return this.name; - } - - @Override - public String getClassName() { - return this.name; - } - - @Override - public ClassEntry getOwnerClassEntry() { - return this; - } - - @Override - public ClassEntry updateOwnership(ClassEntry classEntry) { - return classEntry; - } - - @Override - public int hashCode() { - return this.name.hashCode(); - } - - @Override - public boolean equals(Object other) { - return other instanceof ClassEntry && equals((ClassEntry) other); - } - - public boolean equals(ClassEntry other) { - return other != null && this.name.equals(other.name); - } - - @Override - public String toString() { - return this.name; - } - - public boolean isArray() { - return this.name.lastIndexOf('[') >= 0; - } - - public boolean isInnerClass() { - return this.name.lastIndexOf('$') >= 0; - } - - public List getClassChainNames() { - return Lists.newArrayList(this.name.split("\\$")); - } - - public List getClassChain() { - List entries = Lists.newArrayList(); - StringBuilder buf = new StringBuilder(); - for (String name : getClassChainNames()) { - if (buf.length() > 0) { - buf.append("$"); - } - buf.append(name); - entries.add(new ClassEntry(buf.toString())); - } - return entries; - } - - public String getOutermostClassName() { - if (isInnerClass()) { - return this.name.substring(0, this.name.indexOf('$')); - } - return this.name; - } - - public ClassEntry getOutermostClassEntry() { - return new ClassEntry(getOutermostClassName()); - } - - public String getOuterClassName() { - if (!isInnerClass()) { - throw new Error("This is not an inner class!"); - } - return this.name.substring(0, this.name.lastIndexOf('$')); - } - - public ClassEntry getOuterClassEntry() { - return new ClassEntry(getOuterClassName()); - } - - public String getInnermostClassName() { - if (!isInnerClass()) { - throw new Error("This is not an inner class!"); - } - return this.name.substring(this.name.lastIndexOf('$') + 1); - } - - public boolean isInDefaultPackage() { - return this.name.indexOf('/') < 0; - } - - public String getPackageName() { - return getPackageName(this.name); - } - - public String getSimpleName() { - int pos = this.name.lastIndexOf('/'); - if (pos > 0) { - return this.name.substring(pos + 1); - } - return this.name; - } - - public static String getPackageName(String name) { - int pos = name.lastIndexOf('/'); - if (pos > 0) { - return name.substring(0, pos); - } - return null; - } - - public ClassEntry buildClassEntry(List classChain) { - assert (classChain.contains(this)); - StringBuilder buf = new StringBuilder(); - for (ClassEntry chainEntry : classChain) { - if (buf.length() == 0) { - buf.append(chainEntry.getName()); - } else { - buf.append("$"); - buf.append(chainEntry.isInnerClass() ? chainEntry.getInnermostClassName() : chainEntry.getSimpleName()); - } - - if (chainEntry == this) { - break; - } - } - return new ClassEntry(buf.toString()); - } -} diff --git a/src/main/java/cuchaz/enigma/mapping/entry/DefEntry.java b/src/main/java/cuchaz/enigma/mapping/entry/DefEntry.java deleted file mode 100644 index 43ad027..0000000 --- a/src/main/java/cuchaz/enigma/mapping/entry/DefEntry.java +++ /dev/null @@ -1,7 +0,0 @@ -package cuchaz.enigma.mapping.entry; - -import cuchaz.enigma.bytecode.AccessFlags; - -public interface DefEntry extends Entry { - AccessFlags getAccess(); -} diff --git a/src/main/java/cuchaz/enigma/mapping/entry/Entry.java b/src/main/java/cuchaz/enigma/mapping/entry/Entry.java deleted file mode 100644 index b612140..0000000 --- a/src/main/java/cuchaz/enigma/mapping/entry/Entry.java +++ /dev/null @@ -1,22 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.mapping.entry; - -public interface Entry { - String getName(); - - String getClassName(); - - ClassEntry getOwnerClassEntry(); - - Entry updateOwnership(ClassEntry classEntry); -} diff --git a/src/main/java/cuchaz/enigma/mapping/entry/EntryFactory.java b/src/main/java/cuchaz/enigma/mapping/entry/EntryFactory.java deleted file mode 100644 index 5bd159f..0000000 --- a/src/main/java/cuchaz/enigma/mapping/entry/EntryFactory.java +++ /dev/null @@ -1,49 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.mapping.entry; - -import cuchaz.enigma.analysis.JarIndex; -import cuchaz.enigma.mapping.ClassMapping; -import cuchaz.enigma.mapping.FieldMapping; -import cuchaz.enigma.mapping.MethodDescriptor; -import cuchaz.enigma.mapping.MethodMapping; - -public class EntryFactory { - public static ClassEntry getObfClassEntry(JarIndex jarIndex, ClassMapping classMapping) { - ClassEntry obfClassEntry = new ClassEntry(classMapping.getObfFullName()); - return obfClassEntry.buildClassEntry(jarIndex.getObfClassChain(obfClassEntry)); - } - - private static ClassEntry getObfClassEntry(ClassMapping classMapping) { - return new ClassEntry(classMapping.getObfFullName()); - } - - public static ClassEntry getDeobfClassEntry(ClassMapping classMapping) { - return new ClassEntry(classMapping.getDeobfName()); - } - - public static FieldEntry getObfFieldEntry(ClassMapping classMapping, FieldMapping fieldMapping) { - return new FieldEntry(getObfClassEntry(classMapping), fieldMapping.getObfName(), fieldMapping.getObfDesc()); - } - - public static MethodEntry getMethodEntry(ClassEntry classEntry, String name, MethodDescriptor desc) { - return new MethodEntry(classEntry, name, desc); - } - - public static MethodEntry getObfMethodEntry(ClassEntry classEntry, MethodMapping methodMapping) { - return getMethodEntry(classEntry, methodMapping.getObfName(), methodMapping.getObfDesc()); - } - - public static MethodEntry getObfMethodEntry(ClassMapping classMapping, MethodMapping methodMapping) { - return getObfMethodEntry(getObfClassEntry(classMapping), methodMapping); - } -} diff --git a/src/main/java/cuchaz/enigma/mapping/entry/FieldDefEntry.java b/src/main/java/cuchaz/enigma/mapping/entry/FieldDefEntry.java deleted file mode 100644 index 223410f..0000000 --- a/src/main/java/cuchaz/enigma/mapping/entry/FieldDefEntry.java +++ /dev/null @@ -1,44 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.mapping.entry; - -import com.google.common.base.Preconditions; -import cuchaz.enigma.bytecode.AccessFlags; -import cuchaz.enigma.mapping.Signature; -import cuchaz.enigma.mapping.TypeDescriptor; - -public class FieldDefEntry extends FieldEntry implements DefEntry { - private final AccessFlags access; - private final Signature signature; - - public FieldDefEntry(ClassEntry ownerEntry, String name, TypeDescriptor desc, Signature signature, AccessFlags access) { - super(ownerEntry, name, desc); - Preconditions.checkNotNull(access, "Field access cannot be null"); - Preconditions.checkNotNull(signature, "Field signature cannot be null"); - this.access = access; - this.signature = signature; - } - - @Override - public AccessFlags getAccess() { - return access; - } - - public Signature getSignature() { - return signature; - } - - @Override - public FieldDefEntry updateOwnership(ClassEntry owner) { - return new FieldDefEntry(owner, this.name, this.desc, signature, access); - } -} diff --git a/src/main/java/cuchaz/enigma/mapping/entry/FieldEntry.java b/src/main/java/cuchaz/enigma/mapping/entry/FieldEntry.java deleted file mode 100644 index b6e1554..0000000 --- a/src/main/java/cuchaz/enigma/mapping/entry/FieldEntry.java +++ /dev/null @@ -1,77 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.mapping.entry; - -import com.google.common.base.Preconditions; -import cuchaz.enigma.mapping.TypeDescriptor; -import cuchaz.enigma.utils.Utils; - -public class FieldEntry implements Entry { - - protected final ClassEntry ownerEntry; - protected final String name; - protected final TypeDescriptor desc; - - // NOTE: this argument order is important for the MethodReader/MethodWriter - public FieldEntry(ClassEntry ownerEntry, String name, TypeDescriptor desc) { - Preconditions.checkNotNull(ownerEntry, "Owner cannot be null"); - Preconditions.checkNotNull(name, "Field name cannot be null"); - Preconditions.checkNotNull(desc, "Field descriptor cannot be null"); - - this.ownerEntry = ownerEntry; - this.name = name; - this.desc = desc; - } - - @Override - public ClassEntry getOwnerClassEntry() { - return this.ownerEntry; - } - - @Override - public String getName() { - return this.name; - } - - @Override - public String getClassName() { - return this.ownerEntry.getName(); - } - - public TypeDescriptor getDesc() { - return this.desc; - } - - @Override - public FieldEntry updateOwnership(ClassEntry owner) { - return new FieldEntry(owner, this.name, this.desc); - } - - @Override - public int hashCode() { - return Utils.combineHashesOrdered(this.ownerEntry, this.name, this.desc); - } - - @Override - public boolean equals(Object other) { - return other instanceof FieldEntry && equals((FieldEntry) other); - } - - public boolean equals(FieldEntry other) { - return this.ownerEntry.equals(other.ownerEntry) && this.name.equals(other.name) && this.desc.equals(other.desc); - } - - @Override - public String toString() { - return this.ownerEntry.getName() + "." + this.name + ":" + this.desc; - } -} diff --git a/src/main/java/cuchaz/enigma/mapping/entry/LocalVariableDefEntry.java b/src/main/java/cuchaz/enigma/mapping/entry/LocalVariableDefEntry.java deleted file mode 100644 index d186664..0000000 --- a/src/main/java/cuchaz/enigma/mapping/entry/LocalVariableDefEntry.java +++ /dev/null @@ -1,61 +0,0 @@ -package cuchaz.enigma.mapping.entry; - -import com.google.common.base.Preconditions; -import cuchaz.enigma.mapping.TypeDescriptor; -import cuchaz.enigma.utils.Utils; - -/** - * TypeDescriptor... - * Created by Thog - * 19/10/2016 - */ -public class LocalVariableDefEntry extends LocalVariableEntry { - - protected final MethodDefEntry ownerEntry; - protected final TypeDescriptor desc; - - public LocalVariableDefEntry(MethodDefEntry ownerEntry, int index, String name, TypeDescriptor desc) { - this(ownerEntry, index, name, true, desc); - } - - public LocalVariableDefEntry(MethodDefEntry ownerEntry, int index, String name, boolean parameter, TypeDescriptor desc) { - super(ownerEntry, index, name, parameter); - Preconditions.checkNotNull(desc, "Variable desc cannot be null"); - - this.ownerEntry = ownerEntry; - this.desc = desc; - } - - @Override - public MethodDefEntry getOwnerEntry() { - return this.ownerEntry; - } - - public TypeDescriptor getDesc() { - return desc; - } - - @Override - public LocalVariableDefEntry updateOwnership(ClassEntry classEntry) { - return new LocalVariableDefEntry(ownerEntry.updateOwnership(classEntry), index, name, parameter, desc); - } - - @Override - public int hashCode() { - return Utils.combineHashesOrdered(this.ownerEntry, this.desc.hashCode(), this.name.hashCode(), Integer.hashCode(this.index)); - } - - @Override - public boolean equals(Object other) { - return other instanceof LocalVariableDefEntry && equals((LocalVariableDefEntry) other); - } - - public boolean equals(LocalVariableDefEntry other) { - return this.ownerEntry.equals(other.ownerEntry) && this.desc.equals(other.desc) && this.name.equals(other.name) && this.index == other.index; - } - - @Override - public String toString() { - return this.ownerEntry + "(" + this.index + ":" + this.name + ":" + this.desc + ")"; - } -} diff --git a/src/main/java/cuchaz/enigma/mapping/entry/LocalVariableEntry.java b/src/main/java/cuchaz/enigma/mapping/entry/LocalVariableEntry.java deleted file mode 100644 index 3507b25..0000000 --- a/src/main/java/cuchaz/enigma/mapping/entry/LocalVariableEntry.java +++ /dev/null @@ -1,93 +0,0 @@ -package cuchaz.enigma.mapping.entry; - -import com.google.common.base.Preconditions; -import cuchaz.enigma.mapping.MethodDescriptor; -import cuchaz.enigma.utils.Utils; - -/** - * TypeDescriptor... - * Created by Thog - * 19/10/2016 - */ -public class LocalVariableEntry implements Entry { - - protected final MethodEntry ownerEntry; - protected final String name; - protected final int index; - protected final boolean parameter; - - @Deprecated - public LocalVariableEntry(MethodEntry ownerEntry, int index, String name) { - this(ownerEntry, index, name, true); - } - - public LocalVariableEntry(MethodEntry ownerEntry, int index, String name, boolean parameter) { - Preconditions.checkNotNull(ownerEntry, "Variable owner cannot be null"); - Preconditions.checkNotNull(name, "Variable name cannot be null"); - Preconditions.checkArgument(index >= 0, "Index must be positive"); - - this.ownerEntry = ownerEntry; - this.name = name; - this.index = index; - this.parameter = parameter; - } - - public boolean isParameter() { - return this.parameter; - } - - public MethodEntry getOwnerEntry() { - return this.ownerEntry; - } - - public int getIndex() { - return index; - } - - @Override - public String getName() { - return this.name; - } - - @Override - public ClassEntry getOwnerClassEntry() { - return this.ownerEntry.getOwnerClassEntry(); - } - - @Override - public String getClassName() { - return this.ownerEntry.getClassName(); - } - - @Override - public LocalVariableEntry updateOwnership(ClassEntry classEntry) { - return new LocalVariableEntry(ownerEntry.updateOwnership(classEntry), index, name, parameter); - } - - public String getMethodName() { - return this.ownerEntry.getName(); - } - - public MethodDescriptor getMethodDesc() { - return this.ownerEntry.getDesc(); - } - - @Override - public int hashCode() { - return Utils.combineHashesOrdered(this.ownerEntry, this.name.hashCode(), Integer.hashCode(this.index)); - } - - @Override - public boolean equals(Object other) { - return other instanceof LocalVariableEntry && equals((LocalVariableEntry) other); - } - - public boolean equals(LocalVariableEntry other) { - return this.ownerEntry.equals(other.ownerEntry) && this.name.equals(other.name) && this.index == other.index; - } - - @Override - public String toString() { - return this.ownerEntry + "(" + this.index + ":" + this.name + ")"; - } -} diff --git a/src/main/java/cuchaz/enigma/mapping/entry/MethodDefEntry.java b/src/main/java/cuchaz/enigma/mapping/entry/MethodDefEntry.java deleted file mode 100644 index fa9e668..0000000 --- a/src/main/java/cuchaz/enigma/mapping/entry/MethodDefEntry.java +++ /dev/null @@ -1,61 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.mapping.entry; - -import com.google.common.base.Preconditions; -import cuchaz.enigma.bytecode.AccessFlags; -import cuchaz.enigma.mapping.MethodDescriptor; -import cuchaz.enigma.mapping.Signature; - -public class MethodDefEntry extends MethodEntry implements DefEntry { - - private final AccessFlags access; - private final Signature signature; - - public MethodDefEntry(ClassEntry classEntry, String name, MethodDescriptor descriptor, Signature signature, AccessFlags access) { - super(classEntry, name, descriptor); - Preconditions.checkNotNull(access, "Method access cannot be null"); - Preconditions.checkNotNull(signature, "Method signature cannot be null"); - this.access = access; - this.signature = signature; - } - - @Override - public AccessFlags getAccess() { - return access; - } - - public Signature getSignature() { - return signature; - } - - @Override - public MethodDefEntry updateOwnership(ClassEntry classEntry) { - return new MethodDefEntry(new ClassEntry(classEntry.getName()), name, descriptor, signature, access); - } - - public int getArgumentIndex(ClassDefEntry ownerEntry, int localVariableIndex) { - int argumentIndex = localVariableIndex; - - // Enum constructors have an implicit "name" and "ordinal" parameter as well as "this" - if (ownerEntry.getAccess().isEnum() && getName().startsWith("<")) { - argumentIndex -= 2; - } - - // If we're not static, "this" is bound to index 0 - if (!getAccess().isStatic()) { - argumentIndex -= 1; - } - - return argumentIndex; - } -} diff --git a/src/main/java/cuchaz/enigma/mapping/entry/MethodEntry.java b/src/main/java/cuchaz/enigma/mapping/entry/MethodEntry.java deleted file mode 100644 index 1abc5b1..0000000 --- a/src/main/java/cuchaz/enigma/mapping/entry/MethodEntry.java +++ /dev/null @@ -1,80 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.mapping.entry; - -import com.google.common.base.Preconditions; -import cuchaz.enigma.mapping.MethodDescriptor; -import cuchaz.enigma.utils.Utils; - -public class MethodEntry implements Entry { - - protected final ClassEntry classEntry; - protected final String name; - protected final MethodDescriptor descriptor; - - public MethodEntry(ClassEntry classEntry, String name, MethodDescriptor descriptor) { - Preconditions.checkNotNull(classEntry, "Class cannot be null"); - Preconditions.checkNotNull(name, "Method name cannot be null"); - Preconditions.checkNotNull(descriptor, "Method descriptor cannot be null"); - - this.classEntry = classEntry; - this.name = name; - this.descriptor = descriptor; - } - - @Override - public ClassEntry getOwnerClassEntry() { - return this.classEntry; - } - - @Override - public String getName() { - return this.name; - } - - public MethodDescriptor getDesc() { - return this.descriptor; - } - - public boolean isConstructor() { - return name.equals("") || name.equals(""); - } - - @Override - public String getClassName() { - return this.classEntry.getName(); - } - - @Override - public MethodEntry updateOwnership(ClassEntry classEntry) { - return new MethodEntry(new ClassEntry(classEntry.getName()), name, descriptor); - } - - @Override - public int hashCode() { - return Utils.combineHashesOrdered(this.classEntry, this.name, this.descriptor); - } - - @Override - public boolean equals(Object other) { - return other instanceof MethodEntry && equals((MethodEntry) other); - } - - public boolean equals(MethodEntry other) { - return this.classEntry.equals(other.getOwnerClassEntry()) && this.name.equals(other.getName()) && this.descriptor.equals(other.getDesc()); - } - - @Override - public String toString() { - return this.classEntry.getName() + "." + this.name + this.descriptor; - } -} diff --git a/src/main/java/cuchaz/enigma/mapping/entry/ProcyonEntryFactory.java b/src/main/java/cuchaz/enigma/mapping/entry/ProcyonEntryFactory.java deleted file mode 100644 index 73770c5..0000000 --- a/src/main/java/cuchaz/enigma/mapping/entry/ProcyonEntryFactory.java +++ /dev/null @@ -1,48 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.mapping.entry; - -import com.strobel.assembler.metadata.FieldDefinition; -import com.strobel.assembler.metadata.MemberReference; -import com.strobel.assembler.metadata.MethodDefinition; -import cuchaz.enigma.bytecode.AccessFlags; -import cuchaz.enigma.mapping.MethodDescriptor; -import cuchaz.enigma.mapping.Signature; -import cuchaz.enigma.mapping.TypeDescriptor; - -public class ProcyonEntryFactory { - private final ReferencedEntryPool entryPool; - - public ProcyonEntryFactory(ReferencedEntryPool entryPool) { - this.entryPool = entryPool; - } - - public FieldEntry getFieldEntry(MemberReference def) { - ClassEntry classEntry = entryPool.getClass(def.getDeclaringType().getInternalName()); - return entryPool.getField(classEntry, def.getName(), def.getErasedSignature()); - } - - public FieldDefEntry getFieldDefEntry(FieldDefinition def) { - ClassEntry classEntry = entryPool.getClass(def.getDeclaringType().getInternalName()); - return new FieldDefEntry(classEntry, def.getName(), new TypeDescriptor(def.getErasedSignature()), Signature.createTypedSignature(def.getSignature()), new AccessFlags(def.getModifiers())); - } - - public MethodEntry getMethodEntry(MemberReference def) { - ClassEntry classEntry = entryPool.getClass(def.getDeclaringType().getInternalName()); - return entryPool.getMethod(classEntry, def.getName(), def.getErasedSignature()); - } - - public MethodDefEntry getMethodDefEntry(MethodDefinition def) { - ClassEntry classEntry = entryPool.getClass(def.getDeclaringType().getInternalName()); - return new MethodDefEntry(classEntry, def.getName(), new MethodDescriptor(def.getErasedSignature()), Signature.createSignature(def.getSignature()), new AccessFlags(def.getModifiers())); - } -} diff --git a/src/main/java/cuchaz/enigma/mapping/entry/ReferencedEntryPool.java b/src/main/java/cuchaz/enigma/mapping/entry/ReferencedEntryPool.java deleted file mode 100644 index 12b3955..0000000 --- a/src/main/java/cuchaz/enigma/mapping/entry/ReferencedEntryPool.java +++ /dev/null @@ -1,59 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.mapping.entry; - -import cuchaz.enigma.mapping.MethodDescriptor; -import cuchaz.enigma.mapping.TypeDescriptor; - -import java.util.HashMap; -import java.util.Map; - -public class ReferencedEntryPool { - private final Map classEntries = new HashMap<>(); - private final Map> methodEntries = new HashMap<>(); - private final Map> fieldEntries = new HashMap<>(); - - public ClassEntry getClass(String name) { - // TODO: FIXME - I'm a hack! - if ("[T".equals(name) || "[[T".equals(name) || "[[[T".equals(name)) { - name = name.replaceAll("T", "Ljava/lang/Object;"); - } - - final String computeName = name; - return this.classEntries.computeIfAbsent(name, s -> new ClassEntry(computeName)); - } - - public MethodEntry getMethod(ClassEntry ownerEntry, String name, String desc) { - return getMethod(ownerEntry, name, new MethodDescriptor(desc)); - } - - public MethodEntry getMethod(ClassEntry ownerEntry, String name, MethodDescriptor desc) { - String key = name + desc.toString(); - return getClassMethods(ownerEntry.getName()).computeIfAbsent(key, s -> new MethodEntry(ownerEntry, name, desc)); - } - - public FieldEntry getField(ClassEntry ownerEntry, String name, String desc) { - return getField(ownerEntry, name, new TypeDescriptor(desc)); - } - - public FieldEntry getField(ClassEntry ownerEntry, String name, TypeDescriptor desc) { - return getClassFields(ownerEntry.getName()).computeIfAbsent(name, s -> new FieldEntry(ownerEntry, name, desc)); - } - - private Map getClassMethods(String name) { - return methodEntries.computeIfAbsent(name, s -> new HashMap<>()); - } - - private Map getClassFields(String name) { - return fieldEntries.computeIfAbsent(name, s -> new HashMap<>()); - } -} -- cgit v1.2.3