summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Gegy2018-12-15 22:29:41 +0200
committerGravatar Adrian Siekierka2018-12-15 21:29:41 +0100
commit4ff89cb1d48cb6916220ee308bf40810cfd868e2 (patch)
tree1145080fde3ea6d727848d15994a3b71478ee22f /src
parentFix #78 (#85) (diff)
downloadenigma-4ff89cb1d48cb6916220ee308bf40810cfd868e2.tar.gz
enigma-4ff89cb1d48cb6916220ee308bf40810cfd868e2.tar.xz
enigma-4ff89cb1d48cb6916220ee308bf40810cfd868e2.zip
Tweak variable name generation (#86)
* Don't apply offset to all methods in abstract class * Tweak local variable naming
Diffstat (limited to 'src')
-rw-r--r--src/main/java/cuchaz/enigma/bytecode/translators/TranslationMethodVisitor.java70
-rw-r--r--src/main/java/cuchaz/enigma/mapping/NameValidator.java4
-rw-r--r--src/main/java/cuchaz/enigma/mapping/TypeDescriptor.java16
-rw-r--r--src/main/java/cuchaz/enigma/mapping/entry/MethodDefEntry.java16
-rw-r--r--src/test/java/cuchaz/enigma/TestTypeDescriptor.java14
5 files changed, 78 insertions, 42 deletions
diff --git a/src/main/java/cuchaz/enigma/bytecode/translators/TranslationMethodVisitor.java b/src/main/java/cuchaz/enigma/bytecode/translators/TranslationMethodVisitor.java
index 52b40b05..6d0d550b 100644
--- a/src/main/java/cuchaz/enigma/bytecode/translators/TranslationMethodVisitor.java
+++ b/src/main/java/cuchaz/enigma/bytecode/translators/TranslationMethodVisitor.java
@@ -1,14 +1,13 @@
1package cuchaz.enigma.bytecode.translators; 1package cuchaz.enigma.bytecode.translators;
2 2
3import cuchaz.enigma.mapping.MethodDescriptor; 3import cuchaz.enigma.mapping.*;
4import cuchaz.enigma.mapping.Signature;
5import cuchaz.enigma.mapping.Translator;
6import cuchaz.enigma.mapping.TypeDescriptor;
7import cuchaz.enigma.mapping.entry.*; 4import cuchaz.enigma.mapping.entry.*;
8import org.objectweb.asm.*; 5import org.objectweb.asm.*;
9 6
7import java.util.Collection;
10import java.util.List; 8import java.util.List;
11import java.util.Locale; 9import java.util.Locale;
10import java.util.stream.Collectors;
12 11
13public class TranslationMethodVisitor extends MethodVisitor { 12public class TranslationMethodVisitor extends MethodVisitor {
14 private final ClassDefEntry ownerEntry; 13 private final ClassDefEntry ownerEntry;
@@ -85,17 +84,26 @@ public class TranslationMethodVisitor extends MethodVisitor {
85 hasParameterMeta = true; 84 hasParameterMeta = true;
86 85
87 String translatedSignature = translator.getTranslatedSignature(Signature.createTypedSignature(signature)).toString(); 86 String translatedSignature = translator.getTranslatedSignature(Signature.createTypedSignature(signature)).toString();
88 int offsetIndex = index; 87 int argumentIndex = methodEntry.getArgumentIndex(ownerEntry, index);
89 88
90 if (offsetIndex >= 0) { 89 if (argumentIndex >= 0) {
91 LocalVariableDefEntry entry = new LocalVariableDefEntry(methodEntry, offsetIndex, name, new TypeDescriptor(desc)); 90 LocalVariableDefEntry entry = new LocalVariableDefEntry(methodEntry, index, name, new TypeDescriptor(desc));
92 LocalVariableDefEntry translatedEntry = translator.getTranslatedVariableDef(entry); 91 LocalVariableDefEntry translatedEntry = translator.getTranslatedVariableDef(entry);
93 String translatedName = translatedEntry.getName(); 92 String translatedName = translatedEntry.getName();
94 93
95 // TODO: Better name inference 94 // TODO: Better name inference
96 if (translatedName.equals(entry.getName())) { 95 if (translatedName.equals(entry.getName())) {
97 boolean argument = offsetIndex < methodEntry.getDesc().getArgumentDescs().size(); 96 List<TypeDescriptor> arguments = methodEntry.getDesc().getArgumentDescs();
98 translatedName = inferName(argument, offsetIndex, translatedEntry.getDesc()); 97 List<TypeDescriptor> translatedArguments = arguments.stream()
98 .map(translator::getTranslatedTypeDesc)
99 .collect(Collectors.toList());
100
101 boolean argument = argumentIndex < arguments.size();
102 if (argument) {
103 translatedName = inferArgumentName(argumentIndex, translatedEntry.getDesc(), translatedArguments);
104 } else {
105 translatedName = inferLocalVariableName(argumentIndex, translatedEntry.getDesc());
106 }
99 } 107 }
100 108
101 super.visitLocalVariable(translatedName, translatedEntry.getDesc().toString(), translatedSignature, start, end, index); 109 super.visitLocalVariable(translatedName, translatedEntry.getDesc().toString(), translatedSignature, start, end, index);
@@ -147,48 +155,56 @@ public class TranslationMethodVisitor extends MethodVisitor {
147 // If we didn't receive any parameter metadata, generate it 155 // If we didn't receive any parameter metadata, generate it
148 if (!hasParameterMeta) { 156 if (!hasParameterMeta) {
149 List<TypeDescriptor> arguments = methodEntry.getDesc().getArgumentDescs(); 157 List<TypeDescriptor> arguments = methodEntry.getDesc().getArgumentDescs();
150 int flags = ownerEntry.getAccess().getFlags(); 158 int offset = ((methodEntry.getAccess().getFlags() & Opcodes.ACC_ABSTRACT) != 0) ? 1 : 0;
151 int offset = ((flags & Opcodes.ACC_INTERFACE) != 0 || (flags & Opcodes.ACC_ABSTRACT) != 0) ? 1 : 0;
152 159
153 for (int index = 0; index < arguments.size(); index++) { 160 for (int argumentIndex = 0; argumentIndex < arguments.size(); argumentIndex++) {
154 LocalVariableEntry entry = new LocalVariableEntry(methodEntry, offset, "", true); 161 LocalVariableEntry entry = new LocalVariableEntry(methodEntry, offset, "", true);
155 LocalVariableEntry translatedEntry = translator.getTranslatedVariable(entry); 162 LocalVariableEntry translatedEntry = translator.getTranslatedVariable(entry);
156 String translatedName = translatedEntry.getName(); 163 String translatedName = translatedEntry.getName();
157 if (translatedName.equals(entry.getName())) { 164 if (translatedName.equals(entry.getName())) {
158 super.visitParameter(inferName(true, index, arguments.get(index)), 0); 165 super.visitParameter(inferArgumentName(argumentIndex, arguments.get(argumentIndex), arguments), 0);
159 } else { 166 } else {
160 super.visitParameter(translatedName, 0); 167 super.visitParameter(translatedName, 0);
161 } 168 }
162 169
163 offset += arguments.get(index).getSize(); 170 offset += arguments.get(argumentIndex).getSize();
164 } 171 }
165 } 172 }
166 super.visitEnd(); 173 super.visitEnd();
167 } 174 }
168 175
169 private String inferName(boolean argument, int argumentIndex, TypeDescriptor desc) { 176 private String inferArgumentName(int index, TypeDescriptor desc, Collection<TypeDescriptor> arguments) {
177 boolean uniqueType = arguments.stream().filter(desc::equals).count() <= 1;
170 String translatedName; 178 String translatedName;
171 int nameIndex = argumentIndex + 1; 179 int nameIndex = index + 1;
172 StringBuilder nameBuilder = new StringBuilder(argument ? "a" : "v"); 180 StringBuilder nameBuilder = new StringBuilder(getTypeName(desc));
181 if (!uniqueType || NameValidator.isReserved(nameBuilder.toString())) {
182 nameBuilder.append(nameIndex);
183 }
184 translatedName = nameBuilder.toString();
185 return translatedName;
186 }
187
188 private String inferLocalVariableName(int index, TypeDescriptor desc) {
189 int nameIndex = index + 1;
190 return getTypeName(desc) + nameIndex;
191 }
192
193 private String getTypeName(TypeDescriptor desc) {
173 // Unfortunately each of these have different name getters, so they have different code paths 194 // Unfortunately each of these have different name getters, so they have different code paths
174 if (desc.isPrimitive()) { 195 if (desc.isPrimitive()) {
175 TypeDescriptor.Primitive argCls = desc.getPrimitive(); 196 TypeDescriptor.Primitive argCls = desc.getPrimitive();
176 nameBuilder.append(argCls.name()); 197 return argCls.name().toLowerCase(Locale.ROOT);
177 } else if (desc.isArray()) { 198 } else if (desc.isArray()) {
178 // List types would require this whole block again, so just go with aListx 199 // List types would require this whole block again, so just go with aListx
179 nameBuilder.append("Arr"); 200 return "arr";
180 } else if (desc.isType()) { 201 } else if (desc.isType()) {
181 String typeName = desc.getTypeEntry().getSimpleName().replace("$", ""); 202 String typeName = desc.getTypeEntry().getSimpleName().replace("$", "");
182 typeName = typeName.substring(0, 1).toUpperCase(Locale.ROOT) + typeName.substring(1); 203 typeName = typeName.substring(0, 1).toLowerCase(Locale.ROOT) + typeName.substring(1);
183 nameBuilder.append(typeName); 204 return typeName;
184 } else { 205 } else {
185 System.err.println("Encountered invalid argument type descriptor " + desc.toString()); 206 System.err.println("Encountered invalid argument type descriptor " + desc.toString());
186 nameBuilder.append("Unk"); 207 return "var";
187 } 208 }
188 if (!argument || methodEntry.getDesc().getArgumentDescs().size() > 1) {
189 nameBuilder.append(nameIndex);
190 }
191 translatedName = nameBuilder.toString();
192 return translatedName;
193 } 209 }
194} 210}
diff --git a/src/main/java/cuchaz/enigma/mapping/NameValidator.java b/src/main/java/cuchaz/enigma/mapping/NameValidator.java
index 9273c9bc..fca8cfcb 100644
--- a/src/main/java/cuchaz/enigma/mapping/NameValidator.java
+++ b/src/main/java/cuchaz/enigma/mapping/NameValidator.java
@@ -66,4 +66,8 @@ public class NameValidator {
66 public static String validateArgumentName(String name) { 66 public static String validateArgumentName(String name) {
67 return validateFieldName(name); 67 return validateFieldName(name);
68 } 68 }
69
70 public static boolean isReserved(String name) {
71 return ReservedWords.contains(name);
72 }
69} 73}
diff --git a/src/main/java/cuchaz/enigma/mapping/TypeDescriptor.java b/src/main/java/cuchaz/enigma/mapping/TypeDescriptor.java
index 3c8cc746..6e58aa0f 100644
--- a/src/main/java/cuchaz/enigma/mapping/TypeDescriptor.java
+++ b/src/main/java/cuchaz/enigma/mapping/TypeDescriptor.java
@@ -223,14 +223,14 @@ public class TypeDescriptor {
223 } 223 }
224 224
225 public enum Primitive { 225 public enum Primitive {
226 Byte('B'), 226 BYTE('B'),
227 Character('C'), 227 CHARACTER('C'),
228 Short('S'), 228 SHORT('S'),
229 Integer('I'), 229 INTEGER('I'),
230 Long('J'), 230 LONG('J'),
231 Float('F'), 231 FLOAT('F'),
232 Double('D'), 232 DOUBLE('D'),
233 Boolean('Z'); 233 BOOLEAN('Z');
234 234
235 private static final Map<Character, Primitive> lookup; 235 private static final Map<Character, Primitive> lookup;
236 236
diff --git a/src/main/java/cuchaz/enigma/mapping/entry/MethodDefEntry.java b/src/main/java/cuchaz/enigma/mapping/entry/MethodDefEntry.java
index 960b08d1..fa9e6685 100644
--- a/src/main/java/cuchaz/enigma/mapping/entry/MethodDefEntry.java
+++ b/src/main/java/cuchaz/enigma/mapping/entry/MethodDefEntry.java
@@ -42,4 +42,20 @@ public class MethodDefEntry extends MethodEntry implements DefEntry {
42 public MethodDefEntry updateOwnership(ClassEntry classEntry) { 42 public MethodDefEntry updateOwnership(ClassEntry classEntry) {
43 return new MethodDefEntry(new ClassEntry(classEntry.getName()), name, descriptor, signature, access); 43 return new MethodDefEntry(new ClassEntry(classEntry.getName()), name, descriptor, signature, access);
44 } 44 }
45
46 public int getArgumentIndex(ClassDefEntry ownerEntry, int localVariableIndex) {
47 int argumentIndex = localVariableIndex;
48
49 // Enum constructors have an implicit "name" and "ordinal" parameter as well as "this"
50 if (ownerEntry.getAccess().isEnum() && getName().startsWith("<")) {
51 argumentIndex -= 2;
52 }
53
54 // If we're not static, "this" is bound to index 0
55 if (!getAccess().isStatic()) {
56 argumentIndex -= 1;
57 }
58
59 return argumentIndex;
60 }
45} 61}
diff --git a/src/test/java/cuchaz/enigma/TestTypeDescriptor.java b/src/test/java/cuchaz/enigma/TestTypeDescriptor.java
index 90fd6351..8172848c 100644
--- a/src/test/java/cuchaz/enigma/TestTypeDescriptor.java
+++ b/src/test/java/cuchaz/enigma/TestTypeDescriptor.java
@@ -51,13 +51,13 @@ public class TestTypeDescriptor {
51 51
52 @Test 52 @Test
53 public void getPrimitive() { 53 public void getPrimitive() {
54 assertThat(new TypeDescriptor("Z").getPrimitive(), is(TypeDescriptor.Primitive.Boolean)); 54 assertThat(new TypeDescriptor("Z").getPrimitive(), is(TypeDescriptor.Primitive.BOOLEAN));
55 assertThat(new TypeDescriptor("B").getPrimitive(), is(TypeDescriptor.Primitive.Byte)); 55 assertThat(new TypeDescriptor("B").getPrimitive(), is(TypeDescriptor.Primitive.BYTE));
56 assertThat(new TypeDescriptor("C").getPrimitive(), is(TypeDescriptor.Primitive.Character)); 56 assertThat(new TypeDescriptor("C").getPrimitive(), is(TypeDescriptor.Primitive.CHARACTER));
57 assertThat(new TypeDescriptor("I").getPrimitive(), is(TypeDescriptor.Primitive.Integer)); 57 assertThat(new TypeDescriptor("I").getPrimitive(), is(TypeDescriptor.Primitive.INTEGER));
58 assertThat(new TypeDescriptor("J").getPrimitive(), is(TypeDescriptor.Primitive.Long)); 58 assertThat(new TypeDescriptor("J").getPrimitive(), is(TypeDescriptor.Primitive.LONG));
59 assertThat(new TypeDescriptor("F").getPrimitive(), is(TypeDescriptor.Primitive.Float)); 59 assertThat(new TypeDescriptor("F").getPrimitive(), is(TypeDescriptor.Primitive.FLOAT));
60 assertThat(new TypeDescriptor("D").getPrimitive(), is(TypeDescriptor.Primitive.Double)); 60 assertThat(new TypeDescriptor("D").getPrimitive(), is(TypeDescriptor.Primitive.DOUBLE));
61 } 61 }
62 62
63 @Test 63 @Test