summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar liach2019-09-04 11:56:09 -0400
committerGravatar Player2019-11-03 12:46:29 +0000
commitce52582f49e618729720a057ae5029d2a1d15da4 (patch)
treef20f266c366af4a2169a735771cbca37449de4e8 /src
parentCheck protected method/field target in visibility index (#157) (diff)
downloadenigma-fork-ce52582f49e618729720a057ae5029d2a1d15da4.tar.gz
enigma-fork-ce52582f49e618729720a057ae5029d2a1d15da4.tar.xz
enigma-fork-ce52582f49e618729720a057ae5029d2a1d15da4.zip
Add tinyv2 save/load
Diffstat (limited to 'src')
-rw-r--r--src/main/java/cuchaz/enigma/command/MappingCommandsUtil.java19
-rw-r--r--src/main/java/cuchaz/enigma/translation/mapping/serde/MappingFormat.java1
-rw-r--r--src/main/java/cuchaz/enigma/translation/mapping/serde/RawEntryMapping.java23
-rw-r--r--src/main/java/cuchaz/enigma/translation/mapping/serde/TinyV2Reader.java290
-rw-r--r--src/main/java/cuchaz/enigma/translation/mapping/serde/TinyV2Writer.java169
-rw-r--r--src/test/java/cuchaz/enigma/mapping/TestTinyV2InnerClasses.java41
-rw-r--r--src/test/java/cuchaz/enigma/mapping/TestV2Main.java24
-rw-r--r--src/test/resources/tinyV2InnerClasses/c.mapping2
-rw-r--r--src/test/resources/tinyV2InnerClasses/cuchaz/enigma/Dad.mapping5
9 files changed, 572 insertions, 2 deletions
diff --git a/src/main/java/cuchaz/enigma/command/MappingCommandsUtil.java b/src/main/java/cuchaz/enigma/command/MappingCommandsUtil.java
index bacb8ff..fc68edf 100644
--- a/src/main/java/cuchaz/enigma/command/MappingCommandsUtil.java
+++ b/src/main/java/cuchaz/enigma/command/MappingCommandsUtil.java
@@ -91,7 +91,11 @@ public final class MappingCommandsUtil {
91 MappingFormat format = null; 91 MappingFormat format = null;
92 try { 92 try {
93 format = MappingFormat.valueOf(type.toUpperCase()); 93 format = MappingFormat.valueOf(type.toUpperCase());
94 } catch (IllegalArgumentException ignored) {} 94 } catch (IllegalArgumentException ignored) {
95 if (type.equals("tinyv2")) {
96 format = MappingFormat.TINY_V2;
97 }
98 }
95 99
96 if (format != null) { 100 if (format != null) {
97 return format.getReader().read(path, ProgressListener.none(), saveParameters); 101 return format.getReader().read(path, ProgressListener.none(), saveParameters);
@@ -106,7 +110,18 @@ public final class MappingCommandsUtil {
106 return; 110 return;
107 } 111 }
108 112
109 if (type.startsWith("tiny")) { 113 if (type.startsWith("tinyv2:") || type.startsWith("tiny_v2:")) {
114 String[] split = type.split(":");
115
116 if (split.length != 3) {
117 throw new IllegalArgumentException("specify column names as 'tinyv2:from_namespace:to_namespace'");
118 }
119
120 new TinyV2Writer(split[1], split[2]).write(mappings, path, ProgressListener.none(), saveParameters);
121 return;
122 }
123
124 if (type.startsWith("tiny:")) {
110 String[] split = type.split(":"); 125 String[] split = type.split(":");
111 126
112 if (split.length != 3) { 127 if (split.length != 3) {
diff --git a/src/main/java/cuchaz/enigma/translation/mapping/serde/MappingFormat.java b/src/main/java/cuchaz/enigma/translation/mapping/serde/MappingFormat.java
index e6461b4..7eae1c0 100644
--- a/src/main/java/cuchaz/enigma/translation/mapping/serde/MappingFormat.java
+++ b/src/main/java/cuchaz/enigma/translation/mapping/serde/MappingFormat.java
@@ -14,6 +14,7 @@ import java.nio.file.Path;
14public enum MappingFormat { 14public enum MappingFormat {
15 ENIGMA_FILE(EnigmaMappingsWriter.FILE, EnigmaMappingsReader.FILE), 15 ENIGMA_FILE(EnigmaMappingsWriter.FILE, EnigmaMappingsReader.FILE),
16 ENIGMA_DIRECTORY(EnigmaMappingsWriter.DIRECTORY, EnigmaMappingsReader.DIRECTORY), 16 ENIGMA_DIRECTORY(EnigmaMappingsWriter.DIRECTORY, EnigmaMappingsReader.DIRECTORY),
17 TINY_V2(new TinyV2Writer("intermediary", "named"), new TinyV2Reader()),
17 TINY_FILE(TinyMappingsWriter.INSTANCE, TinyMappingsReader.INSTANCE), 18 TINY_FILE(TinyMappingsWriter.INSTANCE, TinyMappingsReader.INSTANCE),
18 SRG_FILE(SrgMappingsWriter.INSTANCE, null), 19 SRG_FILE(SrgMappingsWriter.INSTANCE, null),
19 PROGUARD(null, ProguardMappingsReader.INSTANCE); 20 PROGUARD(null, ProguardMappingsReader.INSTANCE);
diff --git a/src/main/java/cuchaz/enigma/translation/mapping/serde/RawEntryMapping.java b/src/main/java/cuchaz/enigma/translation/mapping/serde/RawEntryMapping.java
new file mode 100644
index 0000000..5d63f38
--- /dev/null
+++ b/src/main/java/cuchaz/enigma/translation/mapping/serde/RawEntryMapping.java
@@ -0,0 +1,23 @@
1package cuchaz.enigma.translation.mapping.serde;
2
3import com.google.common.base.Strings;
4import cuchaz.enigma.translation.mapping.AccessModifier;
5import cuchaz.enigma.translation.mapping.EntryMapping;
6
7final class RawEntryMapping {
8 private final String targetName;
9 private final AccessModifier access;
10
11 RawEntryMapping(String targetName) {
12 this(targetName, null);
13 }
14
15 RawEntryMapping(String targetName, AccessModifier access) {
16 this.access = access;
17 this.targetName = targetName;
18 }
19
20 EntryMapping bake() {
21 return Strings.isNullOrEmpty(targetName) ? null : new EntryMapping(targetName, access);
22 }
23}
diff --git a/src/main/java/cuchaz/enigma/translation/mapping/serde/TinyV2Reader.java b/src/main/java/cuchaz/enigma/translation/mapping/serde/TinyV2Reader.java
new file mode 100644
index 0000000..2621f31
--- /dev/null
+++ b/src/main/java/cuchaz/enigma/translation/mapping/serde/TinyV2Reader.java
@@ -0,0 +1,290 @@
1package cuchaz.enigma.translation.mapping.serde;
2
3import cuchaz.enigma.ProgressListener;
4import cuchaz.enigma.throwables.MappingParseException;
5import cuchaz.enigma.translation.mapping.EntryMapping;
6import cuchaz.enigma.translation.mapping.MappingPair;
7import cuchaz.enigma.translation.mapping.MappingSaveParameters;
8import cuchaz.enigma.translation.mapping.tree.EntryTree;
9import cuchaz.enigma.translation.mapping.tree.HashEntryTree;
10import cuchaz.enigma.translation.representation.MethodDescriptor;
11import cuchaz.enigma.translation.representation.TypeDescriptor;
12import cuchaz.enigma.translation.representation.entry.ClassEntry;
13import cuchaz.enigma.translation.representation.entry.Entry;
14import cuchaz.enigma.translation.representation.entry.FieldEntry;
15import cuchaz.enigma.translation.representation.entry.LocalVariableEntry;
16import cuchaz.enigma.translation.representation.entry.MethodEntry;
17
18import java.io.IOException;
19import java.nio.charset.StandardCharsets;
20import java.nio.file.Files;
21import java.nio.file.Path;
22import java.util.BitSet;
23import java.util.List;
24
25final class TinyV2Reader implements MappingsReader {
26
27 private static final String MINOR_VERSION = "0";
28 // 0 indent
29 private static final int IN_HEADER = 0;
30 private static final int IN_CLASS = IN_HEADER + 1;
31 // 1 indent
32 private static final int IN_METHOD = IN_CLASS + 1;
33 private static final int IN_FIELD = IN_METHOD + 1;
34 // 2 indent
35 private static final int IN_PARAMETER = IN_FIELD + 1;
36 // general properties
37 private static final int STATE_SIZE = IN_PARAMETER + 1;
38 private static final int[] INDENT_CLEAR_START = {IN_HEADER, IN_METHOD, IN_PARAMETER, STATE_SIZE};
39
40 @Override
41 public EntryTree<EntryMapping> read(Path path, ProgressListener progress, MappingSaveParameters saveParameters) throws IOException, MappingParseException {
42 return read(path, Files.readAllLines(path, StandardCharsets.UTF_8), progress);
43 }
44
45 private EntryTree<EntryMapping> read(Path path, List<String> lines, ProgressListener progress) throws MappingParseException {
46 EntryTree<EntryMapping> mappings = new HashEntryTree<>();
47
48 progress.init(lines.size(), "Loading mapping file");
49
50 BitSet state = new BitSet(STATE_SIZE);
51 @SuppressWarnings({"unchecked", "rawtypes"})
52 MappingPair<? extends Entry<?>, RawEntryMapping>[] holds = new MappingPair[STATE_SIZE];
53 boolean escapeNames = false;
54
55 for (int lineNumber = 0; lineNumber < lines.size(); lineNumber++) {
56 try {
57 progress.step(lineNumber, "");
58 String line = lines.get(lineNumber);
59
60 int indent = 0;
61 while (line.charAt(indent) == '\t')
62 indent++;
63
64 String[] parts = line.substring(indent).split("\t", -1);
65 if (parts.length == 0 || indent >= INDENT_CLEAR_START.length)
66 throw new IllegalArgumentException("Invalid format");
67
68 // clean and register stuff in stack
69 for (int i = INDENT_CLEAR_START[indent]; i < STATE_SIZE; i++) {
70 state.clear(i);
71 if (holds[i] != null) {
72 RawEntryMapping mapping = holds[i].getMapping();
73 if (mapping != null) {
74 EntryMapping baked = mapping.bake();
75 if (baked != null) {
76 mappings.insert(holds[i].getEntry(), baked);
77 }
78 }
79 holds[i] = null;
80 }
81 }
82
83 switch (indent) {
84 case 0:
85 switch (parts[0]) {
86 case "tiny": // header
87 if (lineNumber != 0) {
88 throw new IllegalArgumentException("Header can only be on the first line");
89 }
90 if (parts.length < 5) {
91 throw new IllegalArgumentException("Not enough header columns, needs at least 5");
92 }
93 if (!"2".equals(parts[1]) || !MINOR_VERSION.equals(parts[2])) {
94 throw new IllegalArgumentException("Unsupported TinyV2 version, requires major " + "2" + " and minor " + MINOR_VERSION + "");
95 }
96 state.set(IN_HEADER);
97 break;
98 case "c": // class
99 state.set(IN_CLASS);
100 holds[IN_CLASS] = parseClass(parts, escapeNames);
101 break;
102 default:
103 unsupportKey(parts);
104 }
105
106 break;
107 case 1:
108 if (state.get(IN_HEADER)) {
109 if (parts[0].equals("esacpe-names")) {
110 escapeNames = true;
111 }
112
113 break;
114 }
115
116 if (state.get(IN_CLASS)) {
117 switch (parts[0]) {
118 case "m": // method
119 state.set(IN_METHOD);
120 holds[IN_METHOD] = parseMethod(holds[IN_CLASS], parts, escapeNames);
121 break;
122 case "f": // field
123 state.set(IN_FIELD);
124 holds[IN_FIELD] = parseField(holds[IN_CLASS], parts, escapeNames);
125 break;
126 case "c": // class javadoc
127 addJavadoc(holds[IN_CLASS], parts);
128 break;
129 default:
130 unsupportKey(parts);
131 }
132 break;
133 }
134
135 unsupportKey(parts);
136 case 2:
137 if (state.get(IN_METHOD)) {
138 switch (parts[0]) {
139 case "p": // parameter
140 state.set(IN_PARAMETER);
141 holds[IN_PARAMETER] = parseArgument(holds[IN_METHOD], parts, escapeNames);
142 break;
143 case "v": // local variable
144 // TODO add local var mapping
145 break;
146 case "c": // method javadoc
147 addJavadoc(holds[IN_METHOD], parts);
148 break;
149 default:
150 unsupportKey(parts);
151 }
152 break;
153 }
154
155 if (state.get(IN_FIELD)) {
156 switch (parts[0]) {
157 case "c": // field javadoc
158 addJavadoc(holds[IN_FIELD], parts);
159 break;
160 default:
161 unsupportKey(parts);
162 }
163 break;
164 }
165 unsupportKey(parts);
166 case 3:
167 if (state.get(IN_PARAMETER)) {
168 switch (parts[0]) {
169 case "c":
170 addJavadoc(holds[IN_PARAMETER], parts);
171 break;
172 default:
173 unsupportKey(parts);
174 }
175 break;
176 }
177 unsupportKey(parts);
178 default:
179 unsupportKey(parts);
180 }
181
182 } catch (Throwable t) {
183 t.printStackTrace();
184 throw new MappingParseException(path::toString, lineNumber + 1, t.toString());
185 }
186 }
187
188 return mappings;
189 }
190
191 private void unsupportKey(String[] parts) {
192 throw new IllegalArgumentException("Unsupported key " + parts[0]);
193 }
194
195 private void addJavadoc(MappingPair<? extends Entry, RawEntryMapping> pair, String[] parts) {
196 if (parts.length != 2) {
197 throw new IllegalArgumentException("Invalid javadoc declaration");
198 }
199
200 addJavadoc(pair, parts[1]);
201 }
202
203 private void addJavadoc(MappingPair<? extends Entry, RawEntryMapping> pair, String javadoc) {
204 RawEntryMapping mapping = pair.getMapping();
205 if (mapping == null) {
206 throw new IllegalArgumentException("Javadoc requires a mapping in enigma!");
207 }
208// mapping.addJavadocLine(javadoc); todo javadocs
209 }
210
211 private MappingPair<ClassEntry, RawEntryMapping> parseClass(String[] tokens, boolean escapeNames) {
212 ClassEntry obfuscatedEntry = new ClassEntry(unescapeOpt(tokens[1], escapeNames));
213 if (tokens.length <= 2)
214 return new MappingPair<>(obfuscatedEntry);
215 String token2 = unescapeOpt(tokens[2], escapeNames);
216 String mapping = token2.substring(token2.lastIndexOf('$') + 1);
217 return new MappingPair<>(obfuscatedEntry, new RawEntryMapping(mapping));
218 }
219
220 private MappingPair<FieldEntry, RawEntryMapping> parseField(MappingPair<? extends Entry, RawEntryMapping> parent, String[] tokens, boolean escapeNames) {
221 ClassEntry ownerClass = (ClassEntry) parent.getEntry();
222 TypeDescriptor descriptor = new TypeDescriptor(unescapeOpt(tokens[1], escapeNames));
223
224 FieldEntry obfuscatedEntry = new FieldEntry(ownerClass, unescapeOpt(tokens[2], escapeNames), descriptor);
225 if (tokens.length <= 3)
226 return new MappingPair<>(obfuscatedEntry);
227 String mapping = unescapeOpt(tokens[3], escapeNames);
228 return new MappingPair<>(obfuscatedEntry, new RawEntryMapping(mapping));
229 }
230
231 private MappingPair<MethodEntry, RawEntryMapping> parseMethod(MappingPair<? extends Entry, RawEntryMapping> parent, String[] tokens, boolean escapeNames) {
232 ClassEntry ownerClass = (ClassEntry) parent.getEntry();
233 MethodDescriptor descriptor = new MethodDescriptor(unescapeOpt(tokens[1], escapeNames));
234
235 MethodEntry obfuscatedEntry = new MethodEntry(ownerClass, unescapeOpt(tokens[2], escapeNames), descriptor);
236 if (tokens.length <= 3)
237 return new MappingPair<>(obfuscatedEntry);
238 String mapping = unescapeOpt(tokens[3], escapeNames);
239 return new MappingPair<>(obfuscatedEntry, new RawEntryMapping(mapping));
240 }
241
242 private MappingPair<LocalVariableEntry, RawEntryMapping> parseArgument(MappingPair<? extends Entry, RawEntryMapping> parent, String[] tokens, boolean escapeNames) {
243 MethodEntry ownerMethod = (MethodEntry) parent.getEntry();
244 int variableIndex = Integer.parseInt(tokens[1]);
245
246 // tokens[2] is the useless obf name
247
248 LocalVariableEntry obfuscatedEntry = new LocalVariableEntry(ownerMethod, variableIndex, "", true);
249 if (tokens.length <= 3)
250 return new MappingPair<>(obfuscatedEntry);
251 String mapping = unescapeOpt(tokens[3], escapeNames);
252 return new MappingPair<>(obfuscatedEntry, new RawEntryMapping(mapping));
253 }
254
255 private static final String TO_ESCAPE = "\\\n\r\0\t";
256 private static final String ESCAPED = "\\nr0t";
257
258 private static String unescapeOpt(String raw, boolean escapedStrings) {
259 return escapedStrings ? unescape(raw) : raw;
260 }
261
262 private static String unescape(String str) {
263 // copied from matcher, lazy!
264 int pos = str.indexOf('\\');
265 if (pos < 0) return str;
266
267 StringBuilder ret = new StringBuilder(str.length() - 1);
268 int start = 0;
269
270 do {
271 ret.append(str, start, pos);
272 pos++;
273 int type;
274
275 if (pos >= str.length()) {
276 throw new RuntimeException("incomplete escape sequence at the end");
277 } else if ((type = ESCAPED.indexOf(str.charAt(pos))) < 0) {
278 throw new RuntimeException("invalid escape character: \\" + str.charAt(pos));
279 } else {
280 ret.append(TO_ESCAPE.charAt(type));
281 }
282
283 start = pos + 1;
284 } while ((pos = str.indexOf('\\', start)) >= 0);
285
286 ret.append(str, start, str.length());
287
288 return ret.toString();
289 }
290}
diff --git a/src/main/java/cuchaz/enigma/translation/mapping/serde/TinyV2Writer.java b/src/main/java/cuchaz/enigma/translation/mapping/serde/TinyV2Writer.java
new file mode 100644
index 0000000..a734ca2
--- /dev/null
+++ b/src/main/java/cuchaz/enigma/translation/mapping/serde/TinyV2Writer.java
@@ -0,0 +1,169 @@
1package cuchaz.enigma.translation.mapping.serde;
2
3import com.google.common.base.Strings;
4import cuchaz.enigma.ProgressListener;
5import cuchaz.enigma.translation.mapping.EntryMap;
6import cuchaz.enigma.translation.mapping.EntryMapping;
7import cuchaz.enigma.translation.mapping.MappingDelta;
8import cuchaz.enigma.translation.mapping.MappingSaveParameters;
9import cuchaz.enigma.translation.mapping.tree.EntryTree;
10import cuchaz.enigma.translation.mapping.tree.EntryTreeNode;
11import cuchaz.enigma.translation.representation.entry.ClassEntry;
12import cuchaz.enigma.translation.representation.entry.Entry;
13import cuchaz.enigma.translation.representation.entry.FieldEntry;
14import cuchaz.enigma.translation.representation.entry.LocalVariableEntry;
15import cuchaz.enigma.translation.representation.entry.MethodEntry;
16import cuchaz.enigma.utils.LFPrintWriter;
17
18import java.io.IOException;
19import java.io.PrintWriter;
20import java.nio.file.Files;
21import java.nio.file.Path;
22import java.util.Deque;
23import java.util.LinkedList;
24import java.util.List;
25import java.util.stream.Collectors;
26import java.util.stream.StreamSupport;
27
28public final class TinyV2Writer implements MappingsWriter {
29
30 private static final String MINOR_VERSION = "0";
31 private final String obfHeader;
32 private final String deobfHeader;
33
34 public TinyV2Writer(String obfHeader, String deobfHeader) {
35 this.obfHeader = obfHeader;
36 this.deobfHeader = deobfHeader;
37 }
38
39 @Override
40 public void write(EntryTree<EntryMapping> mappings, MappingDelta<EntryMapping> delta, Path path, ProgressListener progress, MappingSaveParameters parameters) {
41 List<EntryTreeNode<EntryMapping>> classes = StreamSupport.stream(mappings.spliterator(), false).filter(node -> node.getEntry() instanceof ClassEntry).collect(Collectors.toList());
42
43 try (PrintWriter writer = new LFPrintWriter(Files.newBufferedWriter(path))) {
44 writer.println("tiny\t2\t" + MINOR_VERSION + "\t" + obfHeader + "\t" + deobfHeader);
45
46 // no escape names
47
48 for (EntryTreeNode<EntryMapping> node : classes) {
49 writeClass(writer, node, mappings);
50 }
51 } catch (IOException ex) {
52 ex.printStackTrace(); // TODO add some better logging system
53 }
54 }
55
56 private void writeClass(PrintWriter writer, EntryTreeNode<EntryMapping> node, EntryMap<EntryMapping> tree) {
57 writer.print("c\t");
58 ClassEntry classEntry = (ClassEntry) node.getEntry();
59 String fullName = classEntry.getFullName();
60 writer.print(fullName);
61 Deque<String> parts = new LinkedList<>();
62 do {
63 EntryMapping mapping = tree.get(classEntry);
64 if (mapping != null) {
65 parts.addFirst(mapping.getTargetName());
66 } else {
67 parts.addFirst(classEntry.getName());
68 }
69 classEntry = classEntry.getOuterClass();
70 } while (classEntry != null);
71
72 String mappedName = String.join("$", parts);
73
74 writer.print("\t");
75
76 writer.print(mappedName); // todo escaping when we have v2 fixed later
77
78 writer.println();
79
80 writeComment(writer, node.getValue(), 1);
81
82 for (EntryTreeNode<EntryMapping> child : node.getChildNodes()) {
83 Entry entry = child.getEntry();
84 if (entry instanceof FieldEntry) {
85 writeField(writer, child);
86 } else if (entry instanceof MethodEntry) {
87 writeMethod(writer, child);
88 }
89 }
90 }
91
92 private void writeMethod(PrintWriter writer, EntryTreeNode<EntryMapping> node) {
93 writer.print(indent(1));
94 writer.print("m\t");
95 writer.print(((MethodEntry) node.getEntry()).getDesc().toString());
96 writer.print("\t");
97 writer.print(node.getEntry().getName());
98 writer.print("\t");
99 EntryMapping mapping = node.getValue();
100 if (mapping == null) {
101 writer.println(node.getEntry().getName()); // todo fix v2 name inference
102 } else {
103 writer.println(mapping.getTargetName());
104
105 writeComment(writer, mapping, 2);
106 }
107
108 for (EntryTreeNode<EntryMapping> child : node.getChildNodes()) {
109 Entry entry = child.getEntry();
110 if (entry instanceof LocalVariableEntry) {
111 writeParameter(writer, child);
112 }
113 // TODO write actual local variables
114 }
115 }
116
117 private void writeField(PrintWriter writer, EntryTreeNode<EntryMapping> node) {
118 if (node.getValue() == null)
119 return; // Shortcut
120
121 writer.print(indent(1));
122 writer.print("f\t");
123 writer.print(((FieldEntry) node.getEntry()).getDesc().toString());
124 writer.print("\t");
125 writer.print(node.getEntry().getName());
126 writer.print("\t");
127 EntryMapping mapping = node.getValue();
128 if (mapping == null) {
129 writer.println(node.getEntry().getName()); // todo fix v2 name inference
130 } else {
131 writer.println(mapping.getTargetName());
132
133 writeComment(writer, mapping, 2);
134 }
135 }
136
137 private void writeParameter(PrintWriter writer, EntryTreeNode<EntryMapping> node) {
138 if (node.getValue() == null)
139 return; // Shortcut
140
141 writer.print(indent(2));
142 writer.print("p\t");
143 writer.print(((LocalVariableEntry) node.getEntry()).getIndex());
144 writer.print("\t");
145 writer.print(node.getEntry().getName());
146 writer.print("\t");
147 EntryMapping mapping = node.getValue();
148 if (mapping == null) {
149 writer.println(); // todo ???
150 } else {
151 writer.println(mapping.getTargetName());
152
153 writeComment(writer, mapping, 3);
154 }
155 }
156
157 private void writeComment(PrintWriter writer, EntryMapping mapping, int indent) {
158// if (mapping != null && mapping.getJavadoc() != null) { todo javadocs
159// writer.print(indent(indent));
160// writer.print("c\t");
161// writer.print(MappingHelper.escape(mapping.getJavadoc()));
162// writer.println();
163// }
164 }
165
166 private String indent(int level) {
167 return Strings.repeat("\t", level);
168 }
169}
diff --git a/src/test/java/cuchaz/enigma/mapping/TestTinyV2InnerClasses.java b/src/test/java/cuchaz/enigma/mapping/TestTinyV2InnerClasses.java
new file mode 100644
index 0000000..7cfdaca
--- /dev/null
+++ b/src/test/java/cuchaz/enigma/mapping/TestTinyV2InnerClasses.java
@@ -0,0 +1,41 @@
1/*******************************************************************************
2 * Copyright (c) 2015 Jeff Martin.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the GNU Lesser General Public
5 * License v3.0 which accompanies this distribution, and is available at
6 * http://www.gnu.org/licenses/lgpl.html
7 *
8 * Contributors:
9 * Jeff Martin - initial API and implementation
10 ******************************************************************************/
11
12package cuchaz.enigma.mapping;
13
14import cuchaz.enigma.Enigma;
15import cuchaz.enigma.EnigmaProject;
16import cuchaz.enigma.ProgressListener;
17import cuchaz.enigma.translation.mapping.serde.EnigmaMappingsReader;
18import cuchaz.enigma.translation.representation.entry.ClassEntry;
19import org.junit.Test;
20
21import java.nio.file.Path;
22import java.nio.file.Paths;
23
24import static cuchaz.enigma.TestEntryFactory.newClass;
25
26public final class TestTinyV2InnerClasses {
27 private Path jar;
28 private Path mappings;
29
30 public TestTinyV2InnerClasses() throws Exception {
31 jar = Paths.get("build/test-obf/innerClasses.jar");
32 mappings = Paths.get(TestTinyV2InnerClasses.class.getResource("/tinyV2InnerClasses/").toURI());
33 }
34
35// @Test
36 public void testMappings() throws Exception {
37 EnigmaProject project = Enigma.create().openJar(jar, ProgressListener.none());
38 project.setMappings(EnigmaMappingsReader.DIRECTORY.read(mappings, ProgressListener.none(), project.getEnigma().getProfile().getMappingSaveParameters()));
39
40 }
41}
diff --git a/src/test/java/cuchaz/enigma/mapping/TestV2Main.java b/src/test/java/cuchaz/enigma/mapping/TestV2Main.java
new file mode 100644
index 0000000..021a90c
--- /dev/null
+++ b/src/test/java/cuchaz/enigma/mapping/TestV2Main.java
@@ -0,0 +1,24 @@
1package cuchaz.enigma.mapping;
2
3import cuchaz.enigma.ProgressListener;
4import cuchaz.enigma.translation.mapping.EntryMapping;
5import cuchaz.enigma.translation.mapping.MappingFileNameFormat;
6import cuchaz.enigma.translation.mapping.MappingSaveParameters;
7import cuchaz.enigma.translation.mapping.serde.EnigmaMappingsReader;
8import cuchaz.enigma.translation.mapping.serde.TinyV2Writer;
9import cuchaz.enigma.translation.mapping.tree.EntryTree;
10
11import java.nio.file.Path;
12import java.nio.file.Paths;
13
14public final class TestV2Main {
15 public static void main(String... args) throws Exception {
16 Path path = Paths.get(TestV2Main.class.getResource("/tinyV2InnerClasses/").toURI());
17
18 MappingSaveParameters parameters = new MappingSaveParameters(MappingFileNameFormat.BY_DEOBF);
19
20 EntryTree<EntryMapping> tree = EnigmaMappingsReader.DIRECTORY.read(path, ProgressListener.none(), parameters);
21
22 new TinyV2Writer("obf", "deobf").write(tree, Paths.get("currentYarn.tiny"), ProgressListener.none(), parameters);
23 }
24}
diff --git a/src/test/resources/tinyV2InnerClasses/c.mapping b/src/test/resources/tinyV2InnerClasses/c.mapping
new file mode 100644
index 0000000..f9b0442
--- /dev/null
+++ b/src/test/resources/tinyV2InnerClasses/c.mapping
@@ -0,0 +1,2 @@
1CLASS c
2 CLASS a Kid
diff --git a/src/test/resources/tinyV2InnerClasses/cuchaz/enigma/Dad.mapping b/src/test/resources/tinyV2InnerClasses/cuchaz/enigma/Dad.mapping
new file mode 100644
index 0000000..8d43ba9
--- /dev/null
+++ b/src/test/resources/tinyV2InnerClasses/cuchaz/enigma/Dad.mapping
@@ -0,0 +1,5 @@
1CLASS f cuchaz/enigma/Dad
2 CLASS a One
3 CLASS a Two
4 CLASS a
5 FIELD a value I