From dd00a211195ec47fd851f1fcf6bfb475e1c89600 Mon Sep 17 00:00:00 2001 From: rhel Date: Sat, 19 Jul 2025 14:30:21 -0600 Subject: [PATCH 1/3] Add Paragraph Delimited Mappings Extended --- .gitignore | 7 +- .../net/fabricmc/mappingio/MappingReader.java | 6 + .../net/fabricmc/mappingio/MappingWriter.java | 2 + .../mappingio/adapter/SubsetChecker.java | 2 +- .../mappingio/format/MappingFormat.java | 23 + .../mappingio/format/pdme/PDMEFileReader.java | 407 ++++++++++++++++++ .../mappingio/format/pdme/PDMEFileWriter.java | 217 ++++++++++ .../mappingio/tree/MemoryMappingTree.java | 1 - .../net/fabricmc/mappingio/test/TestUtil.java | 4 + .../tests/reading/EmptyContentReadTest.java | 6 + src/test/resources/detection/pdme.pdme | 1 + .../propagated-except-remapped-dst/pdme.pdme | 7 + .../propagated/pdme.pdme | 7 + .../unpropagated/pdme.pdme | 4 + 14 files changed, 691 insertions(+), 3 deletions(-) create mode 100644 src/main/java/net/fabricmc/mappingio/format/pdme/PDMEFileReader.java create mode 100644 src/main/java/net/fabricmc/mappingio/format/pdme/PDMEFileWriter.java create mode 100644 src/test/resources/detection/pdme.pdme create mode 100644 src/test/resources/outer-class-name-propagation/propagated-except-remapped-dst/pdme.pdme create mode 100644 src/test/resources/outer-class-name-propagation/propagated/pdme.pdme create mode 100644 src/test/resources/outer-class-name-propagation/unpropagated/pdme.pdme diff --git a/.gitignore b/.gitignore index 85cf43e8..520b20ee 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,9 @@ /.classpath /.project /.idea/ -/.gradle \ No newline at end of file +/.gradle +mapping-io-extras/.classpath +mapping-io-extras/.project +mapping-io-extras/.settings/org.eclipse.buildship.core.prefs +mapping-io-extras/.settings/org.eclipse.jdt.core.prefs +mapping-io-extras/bin/ \ No newline at end of file diff --git a/src/main/java/net/fabricmc/mappingio/MappingReader.java b/src/main/java/net/fabricmc/mappingio/MappingReader.java index bc6cbbae..05b5cd69 100644 --- a/src/main/java/net/fabricmc/mappingio/MappingReader.java +++ b/src/main/java/net/fabricmc/mappingio/MappingReader.java @@ -37,6 +37,7 @@ import net.fabricmc.mappingio.format.enigma.EnigmaFileReader; import net.fabricmc.mappingio.format.intellij.MigrationMapFileReader; import net.fabricmc.mappingio.format.jobf.JobfFileReader; +import net.fabricmc.mappingio.format.pdme.PDMEFileReader; import net.fabricmc.mappingio.format.proguard.ProGuardFileReader; import net.fabricmc.mappingio.format.simple.RecafSimpleFileReader; import net.fabricmc.mappingio.format.srg.JamFileReader; @@ -137,6 +138,8 @@ private static MappingFormat detectFormat(Reader reader, @Nullable String fileEx return MappingFormat.PROGUARD_FILE; } else if (headerStr.contains("\n\t")) { return MappingFormat.TSRG_FILE; + } else if (headerStr.contains("\u00B6")) { + return MappingFormat.PDME_FILE; } if (fileExt != null) { @@ -323,6 +326,9 @@ public static void read(Reader reader, MappingFormat format, MappingVisitor visi case RECAF_SIMPLE_FILE: RecafSimpleFileReader.read(reader, visitor); break; + case PDME_FILE: + PDMEFileReader.read(reader, visitor); + break; case JOBF_FILE: JobfFileReader.read(reader, visitor); break; diff --git a/src/main/java/net/fabricmc/mappingio/MappingWriter.java b/src/main/java/net/fabricmc/mappingio/MappingWriter.java index bb98875f..ecc2dc0e 100644 --- a/src/main/java/net/fabricmc/mappingio/MappingWriter.java +++ b/src/main/java/net/fabricmc/mappingio/MappingWriter.java @@ -29,6 +29,7 @@ import net.fabricmc.mappingio.format.enigma.EnigmaFileWriter; import net.fabricmc.mappingio.format.intellij.MigrationMapFileWriter; import net.fabricmc.mappingio.format.jobf.JobfFileWriter; +import net.fabricmc.mappingio.format.pdme.PDMEFileWriter; import net.fabricmc.mappingio.format.proguard.ProGuardFileWriter; import net.fabricmc.mappingio.format.simple.RecafSimpleFileWriter; import net.fabricmc.mappingio.format.srg.CsrgFileWriter; @@ -68,6 +69,7 @@ static MappingWriter create(Writer writer, MappingFormat format) throws IOExcept case PROGUARD_FILE: return new ProGuardFileWriter(writer); case INTELLIJ_MIGRATION_MAP_FILE: return new MigrationMapFileWriter(writer); case RECAF_SIMPLE_FILE: return new RecafSimpleFileWriter(writer); + case PDME_FILE: return new PDMEFileWriter(writer); case JOBF_FILE: return new JobfFileWriter(writer); default: return null; } diff --git a/src/main/java/net/fabricmc/mappingio/adapter/SubsetChecker.java b/src/main/java/net/fabricmc/mappingio/adapter/SubsetChecker.java index a8d57452..7ce7213e 100644 --- a/src/main/java/net/fabricmc/mappingio/adapter/SubsetChecker.java +++ b/src/main/java/net/fabricmc/mappingio/adapter/SubsetChecker.java @@ -172,7 +172,7 @@ public boolean visitClass(String srcName, @Nullable String[] dstNames) throws IO if (error && subDstName == null && !subHasRepackaging && supHasRepackaging) { String srcPkg = getPackage(srcName); String dstPkg = getPackage(supDstName); - + System.out.println("sin paquete "+srcPkg+" "+dstPkg); if (srcPkg != null && srcPkg.equals(dstPkg)) { // The incoming class has been repackaged in supTree, which subFormat doesn't support error = false; diff --git a/src/main/java/net/fabricmc/mappingio/format/MappingFormat.java b/src/main/java/net/fabricmc/mappingio/format/MappingFormat.java index b281ce36..86eeebaa 100644 --- a/src/main/java/net/fabricmc/mappingio/format/MappingFormat.java +++ b/src/main/java/net/fabricmc/mappingio/format/MappingFormat.java @@ -253,6 +253,29 @@ public enum MappingFormat { .withSrcDescs(FeaturePresence.REQUIRED)) .withFileComments(true)), + /** + * The {@code Paragraph Delimited Mapping Extended} mapping format, as specified here. + * @implNote This implementation does not support the Include/Incluir or AccessFlag/BanderaDeAcceso types. Param is also not supported at this time. + */ + PDME_FILE("Paragraph Delimited Mapping Extended", "pdme", true, + FeatureSetBuilder.create() + .withNamespaces(false) + .withElementMetadata(MetadataSupport.ARBITRARY) + .withClasses(c -> c + .withSrcNames(FeaturePresence.REQUIRED) + .withDstNames(FeaturePresence.REQUIRED) + .withRepackaging(true)) + .withFields(f -> f + .withSrcNames(FeaturePresence.REQUIRED) + .withSrcDescs(FeaturePresence.REQUIRED) + .withDstNames(FeaturePresence.REQUIRED)) + .withMethods(m -> m + .withSrcNames(FeaturePresence.REQUIRED) + .withDstNames(FeaturePresence.REQUIRED) + .withSrcDescs(FeaturePresence.REQUIRED)) + .withElementComments(ElementCommentSupport.SHARED) + .withFileComments(true)), + /** * The {@code JOBF} mapping format, as implemented here. * diff --git a/src/main/java/net/fabricmc/mappingio/format/pdme/PDMEFileReader.java b/src/main/java/net/fabricmc/mappingio/format/pdme/PDMEFileReader.java new file mode 100644 index 00000000..cc149ab5 --- /dev/null +++ b/src/main/java/net/fabricmc/mappingio/format/pdme/PDMEFileReader.java @@ -0,0 +1,407 @@ +package net.fabricmc.mappingio.format.pdme; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.Reader; +import java.util.*; +import java.util.regex.Pattern; + +import net.fabricmc.mappingio.MappedElementKind; +import net.fabricmc.mappingio.MappingFlag; +import net.fabricmc.mappingio.MappingUtil; +import net.fabricmc.mappingio.MappingVisitor; +import net.fabricmc.mappingio.format.MappingFormat; +import net.fabricmc.mappingio.tree.MemoryMappingTree; + +/** + * {@linkplain MappingFormat#PDME_FILE Paragraph Delimited Mappings Extended file} reader. + * + *

Crashes if a second visit pass is requested without + * {@link MappingFlag#NEEDS_MULTIPLE_PASSES} having been passed beforehand. + */ +public final class PDMEFileReader { + + private static final char DELIM = '\u00B6'; + + private PDMEFileReader() {} + + public static void read(Reader in, MappingVisitor visitor) throws IOException { + Set flags = visitor.getFlags(); + + MappingVisitor downstream = visitor; + MemoryMappingTree buffering = null; + if (flags.contains(MappingFlag.NEEDS_ELEMENT_UNIQUENESS)) { + buffering = new MemoryMappingTree(); + visitor = buffering; + } + + BufferedReader br = new BufferedReader(in); + String header = br.readLine(); + if (header == null) return; + + List lines = new ArrayList(); + for (String l; (l = br.readLine()) != null; ) { + lines.add(l); + } + + boolean multi = flags.contains(MappingFlag.NEEDS_MULTIPLE_PASSES); + + while (true) { + boolean h = visitor.visitHeader(); + if (h) { + visitor.visitNamespaces(MappingUtil.NS_SOURCE_FALLBACK, + Collections.singletonList(MappingUtil.NS_TARGET_FALLBACK)); + } + + if (visitor.visitContent()) { + parseContent(lines, visitor); + } + + if (visitor.visitEnd()) break; + if (!multi) { + throw new IllegalStateException("Repeated visitation requested without NEEDS_MULTIPLE_PASSES"); + } + } + + if (buffering != null) { + buffering.accept(downstream); + } + } + + private static abstract class Row { + abstract void emit(MappingVisitor v) throws IOException; + } + + private static final class ClassRow extends Row { + final String original; // dotted + final String mappedCol; // raw column value (may be null) + final String comment; + String finalMapped; // resolved after all class rows collected + boolean resolved; + + ClassRow(String o, String m, String c) { + this.original = o; + this.mappedCol = m; + this.comment = c; + } + + void resolve(Map byOriginal) { + if (resolved) return; + resolved = true; + if (original == null) return; + + // Top-level? + int lastDollar = original.lastIndexOf('$'); + if (lastDollar < 0) { + // Top-level + if (mappedCol != null) { + finalMapped = mappedCol; + } else { + finalMapped = original; + } + return; + } + + // Inner class + String outerOrig = original.substring(0, lastDollar); + String tailOrig = original.substring(lastDollar + 1); + + ClassRow outerRow = byOriginal.get(outerOrig); + if (outerRow != null) { + outerRow.resolve(byOriginal); + } + + String outerFinal = outerRow != null && outerRow.finalMapped != null + ? outerRow.finalMapped + : outerOrig; + + if (mappedCol == null) { + // Propagate outer rename + original tail + finalMapped = outerFinal + '$' + tailOrig; + } else { + if (isSimpleTail(mappedCol)) { + // Tail-only rename + finalMapped = outerFinal + '$' + mappedCol; + } else { + // Explicit full mapped path + finalMapped = mappedCol; + } + } + } + + private static boolean isSimpleTail(String s) { + return s.indexOf('$') < 0 && s.indexOf('.') < 0; + } + + @Override + void emit(MappingVisitor v) throws IOException { + if (original == null) return; + if (finalMapped == null) finalMapped = original; + + String slashOrig = original.replace('.', '/'); + boolean identity = original.equals(finalMapped); + String slashMapped = identity ? null : finalMapped.replace('.', '/'); + + if (v.visitClass(slashOrig)) { + if (slashMapped != null) { + v.visitDstName(MappedElementKind.CLASS, 0, slashMapped); + } + if (v.visitElementContent(MappedElementKind.CLASS) && comment != null) { + v.visitComment(MappedElementKind.CLASS, comment); + } + } + } + } + + private static final class FieldRow extends Row { + final String original; // cls.field:desc + final String mapped; + final String comment; + + FieldRow(String o, String m, String c) { + this.original = o; + this.mapped = m; + this.comment = c; + } + + @Override + void emit(MappingVisitor v) throws IOException { + if (original == null) return; + int colon = original.lastIndexOf(':'); + if (colon < 0) return; + String desc = original.substring(colon + 1); + String ownerAndName = original.substring(0, colon); + int lastDot = ownerAndName.lastIndexOf('.'); + if (lastDot < 0) return; + String clsDotted = ownerAndName.substring(0, lastDot); + String fieldName = ownerAndName.substring(lastDot + 1); + String slashClass = clsDotted.replace('.', '/'); + + if (v.visitClass(slashClass)) { + v.visitElementContent(MappedElementKind.CLASS); + } + if (v.visitField(fieldName, desc)) { + if (mapped != null) { + v.visitDstName(MappedElementKind.FIELD, 0, mapped); + } + if (v.visitElementContent(MappedElementKind.FIELD) && comment != null) { + v.visitComment(MappedElementKind.FIELD, comment); + } + } + } + } + + private static final class MethodRow extends Row { + final String original; // cls.method(desc) + final String mapped; + final String comment; + + MethodRow(String o, String m, String c) { + this.original = o; + this.mapped = m; + this.comment = c; + } + + @Override + void emit(MappingVisitor v) throws IOException { + if (original == null) return; + int paren = original.indexOf('('); + if (paren < 0) return; + int lastDot = original.lastIndexOf('.', paren); + if (lastDot < 0) return; + String clsDotted = original.substring(0, lastDot); + String methodName = original.substring(lastDot + 1, paren); + String methodDesc = original.substring(paren); + String slashClass = clsDotted.replace('.', '/'); + + if (v.visitClass(slashClass)) { + v.visitElementContent(MappedElementKind.CLASS); + } + if (v.visitMethod(methodName, methodDesc)) { + if (mapped != null) { + v.visitDstName(MappedElementKind.METHOD, 0, mapped); + } + if (v.visitElementContent(MappedElementKind.METHOD) && comment != null) { + v.visitComment(MappedElementKind.METHOD, comment); + } + } + } + } + + private static final class ParamRow extends Row { + final String def; + final String posStr; + final String mappedName; + final String comment; + final String originalMeta; // for locals: lvtRowIndex:lvIndex:start:end + + ParamRow(String d, String p, String m, String c, String om) { + this.def = d; + this.posStr = p; + this.mappedName = m; + this.comment = c; + this.originalMeta = om; + } + + @Override + void emit(MappingVisitor v) throws IOException { + if (def == null || posStr == null || mappedName == null) return; + + int paren = def.indexOf('('); + if (paren < 0) return; + int lastDot = def.lastIndexOf('.', paren); + if (lastDot < 0) return; + + String clsDotted = def.substring(0, lastDot); + String methodName = def.substring(lastDot + 1, paren); + String methodDesc = def.substring(paren); + + int pos; + try { + pos = Integer.parseInt(posStr); + } catch (NumberFormatException e) { + return; + } + if (pos <= 0) return; + + String slashClass = clsDotted.replace('.', '/'); + + if (v.visitClass(slashClass)) { + v.visitElementContent(MappedElementKind.CLASS); + } + if (v.visitMethod(methodName, methodDesc)) { + v.visitElementContent(MappedElementKind.METHOD); + } + + int paramCount = countParams(methodDesc); + if (pos <= paramCount) { + int zero = pos - 1; + if (v.visitMethodArg(zero, -1, mappedName)) { + v.visitDstName(MappedElementKind.METHOD_ARG, 0, mappedName); + if (v.visitElementContent(MappedElementKind.METHOD_ARG) && comment != null) { + v.visitComment(MappedElementKind.METHOD_ARG, comment); + } + } + } else { + if (originalMeta == null) return; + String[] parts = originalMeta.split(":"); + if (parts.length != 4) return; + try { + int lvtRowIndex = Integer.parseInt(parts[0]); + int lvIndex = Integer.parseInt(parts[1]); + int start = Integer.parseInt(parts[2]); + int end = Integer.parseInt(parts[3]); + if (v.visitMethodVar(lvtRowIndex, lvIndex, start, end, mappedName)) { + v.visitDstName(MappedElementKind.METHOD_VAR, 0, mappedName); + if (v.visitElementContent(MappedElementKind.METHOD_VAR) && comment != null) { + v.visitComment(MappedElementKind.METHOD_VAR, comment); + } + } + } catch (NumberFormatException ignored) { + } + } + } + } + + private static void parseContent(List lines, MappingVisitor v) throws IOException { + Map classRowsByOrig = new LinkedHashMap(); + List nonClassRows = new ArrayList(); + + for (int i = 0; i < lines.size(); i++) { + String raw = lines.get(i); + if (raw == null) continue; + String trimmed = raw.trim(); + if (trimmed.isEmpty() || trimmed.startsWith("#")) continue; + + String[] cols = splitToSix(trimmed); + String tipo = cols[0]; + String original = normalizeEmpty(cols[1]); + String nuevo = normalizeEmpty(cols[2]); + String def = normalizeEmpty(cols[3]); + String pos = normalizeEmpty(cols[4]); + String desc = normalizeEmpty(cols[5]); + + if ("Class".equals(tipo)) { + ClassRow cr = new ClassRow(original, nuevo, desc); + classRowsByOrig.put(original, cr); + } else if ("Var".equals(tipo)) { + nonClassRows.add(new FieldRow(original, nuevo, desc)); + } else if ("Def".equals(tipo)) { + nonClassRows.add(new MethodRow(original, nuevo, desc)); + } else if ("Param".equals(tipo)) { + nonClassRows.add(new ParamRow(def, pos, nuevo, desc, original)); + } + } + + // Parse Subclases + for (ClassRow cr : classRowsByOrig.values()) { + cr.resolve(classRowsByOrig); + } + + // Emit classes first + for (ClassRow cr : classRowsByOrig.values()) { + cr.emit(v); + } + + for (Row r : nonClassRows) { + r.emit(v); + } + } + + + private static String[] splitToSix(String line) { + String[] arr = line.split(Pattern.quote(String.valueOf(DELIM)), -1); + if (arr.length == 6) return arr; + if (arr.length < 6) { + String[] six = new String[6]; + System.arraycopy(arr, 0, six, 0, arr.length); + for (int i = arr.length; i < 6; i++) six[i] = ""; + return six; + } + // collapse extra columns into desc + StringBuilder desc = new StringBuilder(arr[5]); + for (int i = 6; i < arr.length; i++) { + if (desc.length() > 0) desc.append(DELIM); + desc.append(arr[i]); + } + String[] six = new String[6]; + System.arraycopy(arr, 0, six, 0, 5); + six[5] = desc.toString(); + return six; + } + + private static String normalizeEmpty(String s) { + return (s == null || s.isEmpty() || "nil".equals(s)) ? null : s; + } + + private static int countParams(String desc) { + if (desc == null || desc.length() == 0) return 0; + int count = 0; + int i = 1; // skip '(' + while (i < desc.length()) { + char c = desc.charAt(i); + if (c == ')') break; + if (c == 'L') { + int semi = desc.indexOf(';', i); + if (semi < 0) break; + i = semi + 1; + count++; + } else if (c == '[') { + i++; + while (i < desc.length() && desc.charAt(i) == '[') i++; + if (i < desc.length() && desc.charAt(i) == 'L') { + int semi = desc.indexOf(';', i); + if (semi < 0) break; + i = semi + 1; + } else { + i++; + } + count++; + } else { + i++; // primitive + count++; + } + } + return count; + } +} diff --git a/src/main/java/net/fabricmc/mappingio/format/pdme/PDMEFileWriter.java b/src/main/java/net/fabricmc/mappingio/format/pdme/PDMEFileWriter.java new file mode 100644 index 00000000..aaf41e9c --- /dev/null +++ b/src/main/java/net/fabricmc/mappingio/format/pdme/PDMEFileWriter.java @@ -0,0 +1,217 @@ +/* + * Copyright (c) 2021 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.fabricmc.mappingio.format.pdme; + +import net.fabricmc.mappingio.MappedElementKind; +import net.fabricmc.mappingio.MappingFlag; +import net.fabricmc.mappingio.MappingWriter; +import net.fabricmc.mappingio.format.MappingFormat; + +import java.io.IOException; +import java.io.Writer; +import java.util.EnumSet; +import java.util.List; +import java.util.Set; + +import org.jetbrains.annotations.Nullable; + +/** + * {@linkplain MappingFormat#PDME_FILE Paragraph Delimited Mappings Extended file} writer. + */ +public final class PDMEFileWriter implements MappingWriter { + + private static final char DELIM = '\u00B6'; + + private final Writer out; + + private String currentClassSlash; + private String currentMethodName; + private String currentMethodDesc; + + private String dstClassFullSlash; // mapped class (slash) if provided + private String dstMemberName; // mapped field or method simple name + + private String fieldSrcName; + private String fieldSrcDesc; + + private StringBuilder stagedRow; + private MappedElementKind stagedKind; + + public PDMEFileWriter(Writer out) { + this.out = out; + } + + @Override + public Set getFlags() { + return EnumSet.of(MappingFlag.NEEDS_HEADER_METADATA, MappingFlag.NEEDS_SRC_FIELD_DESC, + MappingFlag.NEEDS_SRC_METHOD_DESC); + } + + @Override + public void visitNamespaces(String srcNamespace, List dstNamespaces) throws IOException { + out.write("tipo" + DELIM + "original" + DELIM + "nuevo" + DELIM + "def" + DELIM + "pos" + DELIM + "desc\n"); + } + + @Override + public boolean visitClass(String srcName) throws IOException { + flushStaged(); + currentClassSlash = srcName; + currentMethodName = null; + currentMethodDesc = null; + dstClassFullSlash = null; + dstMemberName = null; + fieldSrcName = null; + fieldSrcDesc = null; + return true; + } + + @Override + public boolean visitField(String srcName, String srcDesc) throws IOException { + flushStaged(); + fieldSrcName = srcName; + fieldSrcDesc = srcDesc; + dstMemberName = null; + return true; + } + + @Override + public boolean visitMethod(String srcName, String srcDesc) throws IOException { + flushStaged(); + if (srcDesc == null) { + return false; // skip methods without descriptor + } + currentMethodName = srcName; + currentMethodDesc = srcDesc; + dstMemberName = null; + return true; + } + + @Override + public void visitDstName(MappedElementKind kind, int namespace, String name) { + if (namespace != 0 || name == null) + return; + switch (kind) { + case CLASS: + dstClassFullSlash = name; + break; + case FIELD: + case METHOD: + dstMemberName = name; + break; + default: + break; // Param kinds ignored (not supported here) + } + } + + @Override + public boolean visitElementContent(MappedElementKind kind) throws IOException { + switch (kind) { + case CLASS: + stageClass(); + return true; + case FIELD: + stageField(); + return true; + case METHOD: + stageMethod(); + return true; + default: + return false; // ignore args/locals/others + } + } + + private void stageClass() { + String origFull = currentClassSlash.replace('/', '.'); + String mappedFull = (dstClassFullSlash != null ? dstClassFullSlash : currentClassSlash).replace('/', '.'); + + stagedRow = begin("Class").append(origFull).append(DELIM).append(mappedFull).append(DELIM).append("nil") + .append(DELIM).append("nil").append(DELIM); + stagedKind = MappedElementKind.CLASS; + dstClassFullSlash = null; + } + + private void stageField() { + String cls = currentClassSlash.replace('/', '.'); + String mapped = (dstMemberName != null ? dstMemberName : fieldSrcName); + + stagedRow = begin("Var").append(cls).append('.').append(fieldSrcName).append(':').append(fieldSrcDesc) + .append(DELIM).append(mapped).append(DELIM).append("nil").append(DELIM).append("nil").append(DELIM); + stagedKind = MappedElementKind.FIELD; + dstMemberName = null; + } + + private void stageMethod() { + String cls = currentClassSlash.replace('/', '.'); + String mapped = (dstMemberName != null ? dstMemberName : currentMethodName); + + stagedRow = begin("Def").append(cls).append('.').append(currentMethodName).append(currentMethodDesc) + .append(DELIM).append(mapped).append(DELIM).append("nil").append(DELIM).append("nil").append(DELIM); + stagedKind = MappedElementKind.METHOD; + dstMemberName = null; + } + + private StringBuilder begin(String tipo) { + return new StringBuilder().append(tipo).append(DELIM); + } + + @Override + public void visitComment(MappedElementKind kind, String comment) throws IOException { + if (stagedRow != null && stagedKind == kind) { + if (comment != null && !comment.isEmpty()) { + String esc = comment + .replaceAll("\\.+$", "") + .replace("\r\n", "\\n") + .replace("\n", "\\n") + .replace("\r", "\\n"); + + stagedRow.append(esc); + } + out.write(stagedRow.toString()); + out.write('\n'); + stagedRow = null; + stagedKind = null; + } + } + + private void flushStaged() throws IOException { + if (stagedRow != null) { + out.write(stagedRow.toString()); + out.write('\n'); + stagedRow = null; + stagedKind = null; + } + } + + @Override + public void close() throws IOException { + flushStaged(); + out.close(); + } + + @Override + public boolean visitMethodArg(int argPosition, int lvIndex, @Nullable String srcName) throws IOException { + return false;// I could not figure out how to get this to work with the Unit Tests. Should be + // Param¶nil¶name¶featurecreep.example.ExampleClass$SubClass.TEST_METH(ILjava/lang/String;Ljava/lang/String;)V¶1¶JavaDocsOrComment + } + + @Override + public boolean visitMethodVar(int lvtRowIndex, int lvIndex, int startOpIdx, int endOpIdx, @Nullable String srcName) + throws IOException { + return false;// I could not figure out how to get these to work with the Unit Tests. Should + // be + // Param¶nil¶name¶featurecreep.example.ExampleClass$SubClass.TEST_METH(ILjava/lang/String;Ljava/lang/String;)V¶1¶JavaDocsOrComment + } +} diff --git a/src/main/java/net/fabricmc/mappingio/tree/MemoryMappingTree.java b/src/main/java/net/fabricmc/mappingio/tree/MemoryMappingTree.java index 65a01707..b3d8d746 100644 --- a/src/main/java/net/fabricmc/mappingio/tree/MemoryMappingTree.java +++ b/src/main/java/net/fabricmc/mappingio/tree/MemoryMappingTree.java @@ -1237,7 +1237,6 @@ private > T addMember(T entry, Map map, i void accept(MappingVisitor visitor, VisitOrder order, boolean supplyFieldDstDescs, boolean supplyMethodDstDescs) throws IOException { if (visitor.visitClass(getSrcName()) && acceptElement(visitor, null)) { boolean methodsFirst = order.isMethodsFirst() && fields != null && methods != null; - if (!methodsFirst && fields != null) { for (FieldEntry field : order.sortFields(fields.values())) { field.accept(visitor, supplyFieldDstDescs); diff --git a/src/test/java/net/fabricmc/mappingio/test/TestUtil.java b/src/test/java/net/fabricmc/mappingio/test/TestUtil.java index 321d5aa7..54736c78 100644 --- a/src/test/java/net/fabricmc/mappingio/test/TestUtil.java +++ b/src/test/java/net/fabricmc/mappingio/test/TestUtil.java @@ -82,6 +82,8 @@ public static String getFileName(MappingFormat format) { return "migration-map.xml"; case RECAF_SIMPLE_FILE: return "recaf-simple.txt"; + case PDME_FILE: + return "pdme.pdme"; case JOBF_FILE: return "jobf.jobf"; default: @@ -111,6 +113,7 @@ public static org.cadixdev.lorenz.io.MappingFormat toLorenzFormat(MappingFormat case PROGUARD_FILE: case INTELLIJ_MIGRATION_MAP_FILE: case RECAF_SIMPLE_FILE: + case PDME_FILE: case JOBF_FILE: return null; default: @@ -142,6 +145,7 @@ public static IMappingFile.Format toSrgUtilsFormat(MappingFormat format) { case JAM_FILE: case INTELLIJ_MIGRATION_MAP_FILE: case RECAF_SIMPLE_FILE: + case PDME_FILE: case JOBF_FILE: return null; default: diff --git a/src/test/java/net/fabricmc/mappingio/test/tests/reading/EmptyContentReadTest.java b/src/test/java/net/fabricmc/mappingio/test/tests/reading/EmptyContentReadTest.java index d67899d8..04d6fa59 100644 --- a/src/test/java/net/fabricmc/mappingio/test/tests/reading/EmptyContentReadTest.java +++ b/src/test/java/net/fabricmc/mappingio/test/tests/reading/EmptyContentReadTest.java @@ -29,6 +29,7 @@ import net.fabricmc.mappingio.format.enigma.EnigmaFileReader; import net.fabricmc.mappingio.format.intellij.MigrationMapFileReader; import net.fabricmc.mappingio.format.jobf.JobfFileReader; +import net.fabricmc.mappingio.format.pdme.PDMEFileReader; import net.fabricmc.mappingio.format.proguard.ProGuardFileReader; import net.fabricmc.mappingio.format.simple.RecafSimpleFileReader; import net.fabricmc.mappingio.format.srg.JamFileReader; @@ -138,6 +139,11 @@ public void emptyRecafSimpleFile() throws Exception { RecafSimpleFileReader.read(new StringReader(""), target); } + @Test + public void emptyPDMEFile() throws Exception { + PDMEFileReader.read(new StringReader("tipo¶original¶nuevo¶def¶pos¶desc"), target); + } + @Test public void emptyJobfFile() throws Exception { JobfFileReader.read(new StringReader(""), target); diff --git a/src/test/resources/detection/pdme.pdme b/src/test/resources/detection/pdme.pdme new file mode 100644 index 00000000..9f94c6fd --- /dev/null +++ b/src/test/resources/detection/pdme.pdme @@ -0,0 +1 @@ +type¶original¶new¶method¶position¶description \ No newline at end of file diff --git a/src/test/resources/outer-class-name-propagation/propagated-except-remapped-dst/pdme.pdme b/src/test/resources/outer-class-name-propagation/propagated-except-remapped-dst/pdme.pdme new file mode 100644 index 00000000..bf070fea --- /dev/null +++ b/src/test/resources/outer-class-name-propagation/propagated-except-remapped-dst/pdme.pdme @@ -0,0 +1,7 @@ +tipo¶original¶nuevo¶def¶pos¶desc +Class¶class_1¶class1Ns0Rename¶nil¶nil¶ +Var¶class_1.field_1:Lclass_1;¶field_1¶nil¶nil¶ +Class¶class_1$class_2¶class_2¶nil¶nil¶ +Var¶class_1$class_2.field_2:Lclass_1$class_2;¶field_2¶nil¶nil¶ +Class¶class_1$class_2$class_3¶class_3¶nil¶nil¶ +Var¶class_1$class_2$class_3.field_2:Lclass_1$class_2$class_3;¶field_2¶nil¶nil¶ \ No newline at end of file diff --git a/src/test/resources/outer-class-name-propagation/propagated/pdme.pdme b/src/test/resources/outer-class-name-propagation/propagated/pdme.pdme new file mode 100644 index 00000000..dbb1fcf4 --- /dev/null +++ b/src/test/resources/outer-class-name-propagation/propagated/pdme.pdme @@ -0,0 +1,7 @@ +tipo¶original¶nuevo¶def¶pos¶desc +Class¶class_1¶class1Ns0Rename¶nil¶nil¶ +Var¶class_1.field_1¶field_1¶nil¶nil¶ +Class¶class_1$class_2¶class_2¶nil¶nil¶ +Var¶class_1$class_2.field_2¶field_2¶nil¶nil¶ +Class¶class_1$class_2$class_3¶class_3¶nil¶nil¶ +Var¶class_1$class_2$class_3.field_2¶field_2¶nil¶nil¶ \ No newline at end of file diff --git a/src/test/resources/outer-class-name-propagation/unpropagated/pdme.pdme b/src/test/resources/outer-class-name-propagation/unpropagated/pdme.pdme new file mode 100644 index 00000000..2cdb354a --- /dev/null +++ b/src/test/resources/outer-class-name-propagation/unpropagated/pdme.pdme @@ -0,0 +1,4 @@ +tipo¶original¶nuevo¶def¶pos¶desc +Class¶class_1¶class1Ns0Rename¶nil¶nil¶ +Class¶class_1$class_2¶class_1$class_2¶nil¶nil¶ +Class¶class_1$class_2$class_3¶class_3¶nil¶nil¶ \ No newline at end of file From 3d9b53f79765721fac95e0eebec1143ba082c171 Mon Sep 17 00:00:00 2001 From: rhel Date: Sat, 19 Jul 2025 20:56:23 -0600 Subject: [PATCH 2/3] Fix Params in PDME --- .../mappingio/adapter/SubsetChecker.java | 2 +- .../mappingio/format/MappingFormat.java | 15 +- .../mappingio/format/pdme/PDMEFileReader.java | 928 ++++++++++-------- .../mappingio/format/pdme/PDMEFileWriter.java | 208 +++- .../mappingio/tree/MemoryMappingTree.java | 1 + .../tests/reading/EmptyContentReadTest.java | 2 +- 6 files changed, 725 insertions(+), 431 deletions(-) diff --git a/src/main/java/net/fabricmc/mappingio/adapter/SubsetChecker.java b/src/main/java/net/fabricmc/mappingio/adapter/SubsetChecker.java index 7ce7213e..a8d57452 100644 --- a/src/main/java/net/fabricmc/mappingio/adapter/SubsetChecker.java +++ b/src/main/java/net/fabricmc/mappingio/adapter/SubsetChecker.java @@ -172,7 +172,7 @@ public boolean visitClass(String srcName, @Nullable String[] dstNames) throws IO if (error && subDstName == null && !subHasRepackaging && supHasRepackaging) { String srcPkg = getPackage(srcName); String dstPkg = getPackage(supDstName); - System.out.println("sin paquete "+srcPkg+" "+dstPkg); + if (srcPkg != null && srcPkg.equals(dstPkg)) { // The incoming class has been repackaged in supTree, which subFormat doesn't support error = false; diff --git a/src/main/java/net/fabricmc/mappingio/format/MappingFormat.java b/src/main/java/net/fabricmc/mappingio/format/MappingFormat.java index 86eeebaa..04fa9a87 100644 --- a/src/main/java/net/fabricmc/mappingio/format/MappingFormat.java +++ b/src/main/java/net/fabricmc/mappingio/format/MappingFormat.java @@ -254,8 +254,8 @@ public enum MappingFormat { .withFileComments(true)), /** - * The {@code Paragraph Delimited Mapping Extended} mapping format, as specified here. - * @implNote This implementation does not support the Include/Incluir or AccessFlag/BanderaDeAcceso types. Param is also not supported at this time. + * The {@code Paragraph Delimited Mapping Extended} mapping format, as specified here. + * @implNote This implementation does not support the Include/Incluir or AccessFlag/BanderaDeAcceso types. */ PDME_FILE("Paragraph Delimited Mapping Extended", "pdme", true, FeatureSetBuilder.create() @@ -273,7 +273,16 @@ public enum MappingFormat { .withSrcNames(FeaturePresence.REQUIRED) .withDstNames(FeaturePresence.REQUIRED) .withSrcDescs(FeaturePresence.REQUIRED)) - .withElementComments(ElementCommentSupport.SHARED) + .withArgs(a -> a + .withLvIndices(FeaturePresence.REQUIRED) + .withSrcNames(FeaturePresence.OPTIONAL) + .withDstNames(FeaturePresence.REQUIRED)) + .withVars(v -> v + .withLvIndices(FeaturePresence.OPTIONAL) + .withLvtRowIndices(FeaturePresence.OPTIONAL) + .withStartOpIndices(FeaturePresence.OPTIONAL) + .withSrcNames(FeaturePresence.OPTIONAL) + .withDstNames(FeaturePresence.REQUIRED)) .withFileComments(true)), /** diff --git a/src/main/java/net/fabricmc/mappingio/format/pdme/PDMEFileReader.java b/src/main/java/net/fabricmc/mappingio/format/pdme/PDMEFileReader.java index cc149ab5..02b3e098 100644 --- a/src/main/java/net/fabricmc/mappingio/format/pdme/PDMEFileReader.java +++ b/src/main/java/net/fabricmc/mappingio/format/pdme/PDMEFileReader.java @@ -1,9 +1,30 @@ +/* + * Copyright (c) 2023 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package net.fabricmc.mappingio.format.pdme; import java.io.BufferedReader; import java.io.IOException; import java.io.Reader; -import java.util.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; import java.util.regex.Pattern; import net.fabricmc.mappingio.MappedElementKind; @@ -14,394 +35,529 @@ import net.fabricmc.mappingio.tree.MemoryMappingTree; /** - * {@linkplain MappingFormat#PDME_FILE Paragraph Delimited Mappings Extended file} reader. + * {@linkplain MappingFormat#PDME_FILE Paragraph Delimited Mappings Extended + * file} reader. * - *

Crashes if a second visit pass is requested without + *

+ * Crashes if a second visit pass is requested without * {@link MappingFlag#NEEDS_MULTIPLE_PASSES} having been passed beforehand. */ public final class PDMEFileReader { + private static final char DELIM = '\u00B6'; + private static final Pattern LOCAL_META_PATTERN = Pattern.compile("^-?\\d+:-?\\d+:-?\\d+:-?\\d+$"); + + private PDMEFileReader() { + } + + public static void read(Reader in, MappingVisitor visitor) throws IOException { + Set flags = visitor.getFlags(); + + MappingVisitor downstream = visitor; + MemoryMappingTree buffering = null; + + if (flags.contains(MappingFlag.NEEDS_ELEMENT_UNIQUENESS)) { + buffering = new MemoryMappingTree(); + visitor = buffering; + } + + BufferedReader br = new BufferedReader(in); + String header = br.readLine(); + + if (header == null) { + return; + } + + List lines = new ArrayList(); + + for (String l; (l = br.readLine()) != null;) { + lines.add(l); + } + + boolean multi = flags.contains(MappingFlag.NEEDS_MULTIPLE_PASSES); + + while (true) { + boolean h = visitor.visitHeader(); + + if (h) { + visitor.visitNamespaces(MappingUtil.NS_SOURCE_FALLBACK, + Collections.singletonList(MappingUtil.NS_TARGET_FALLBACK)); + } + + if (visitor.visitContent()) { + parseContent(lines, visitor); + } + + if (visitor.visitEnd()) { + break; + } + + if (!multi) { + throw new IllegalStateException("Repeated visitation requested without NEEDS_MULTIPLE_PASSES"); + } + } + + if (buffering != null) { + buffering.accept(downstream); + } + } + + private abstract static class Row { + abstract void emit(MappingVisitor v) throws IOException; + } + + private static final class ClassRow extends Row { + final String original; + final String mappedCol; + final String comment; + String finalMapped; + boolean resolved; + + ClassRow(String o, String m, String c) { + this.original = o; + this.mappedCol = m; + this.comment = c; + } + + void resolve(Map byOrig) { + if (resolved) { + return; + } + + resolved = true; + + if (original == null) { + return; + } + + int lastDollar = original.lastIndexOf('$'); + + if (lastDollar < 0) { + finalMapped = (mappedCol != null ? mappedCol : original); + return; + } + + String outerOrig = original.substring(0, lastDollar); + String tailOrig = original.substring(lastDollar + 1); + + ClassRow outer = byOrig.get(outerOrig); + + if (outer != null) { + outer.resolve(byOrig); + } + + String outerFinal = (outer != null && outer.finalMapped != null) ? outer.finalMapped : outerOrig; + + if (mappedCol == null) { + finalMapped = outerFinal + '$' + tailOrig; + } else { + if (isSimpleTail(mappedCol)) { + finalMapped = outerFinal + '$' + mappedCol; + } else { + finalMapped = mappedCol; + } + } + } + + private static boolean isSimpleTail(String s) { + return s.indexOf('$') < 0 && s.indexOf('.') < 0; + } + + @Override + void emit(MappingVisitor v) throws IOException { + if (original == null) { + return; + } + + if (finalMapped == null) { + finalMapped = original; + } + + String slashOrig = original.replace('.', '/'); + String slashMapped = original.equals(finalMapped) ? null : finalMapped.replace('.', '/'); + + if (v.visitClass(slashOrig)) { + if (slashMapped != null) { + v.visitDstName(MappedElementKind.CLASS, 0, slashMapped); + } + + if (v.visitElementContent(MappedElementKind.CLASS) && comment != null) { + v.visitComment(MappedElementKind.CLASS, comment); + } + } + } + } + + private static final class FieldRow extends Row { + final String original; + final String mapped; + final String comment; + + FieldRow(String o, String m, String c) { + this.original = o; + this.mapped = m; + this.comment = c; + } + + @Override + void emit(MappingVisitor v) throws IOException { + if (original == null) { + return; + } + + int colon = original.lastIndexOf(':'); + + if (colon < 0) { + return; + } + + String desc = original.substring(colon + 1); + String ownerAndName = original.substring(0, colon); + int lastDot = ownerAndName.lastIndexOf('.'); + + if (lastDot < 0) { + return; + } + + String clsDotted = ownerAndName.substring(0, lastDot); + String fieldName = ownerAndName.substring(lastDot + 1); + String slashClass = clsDotted.replace('.', '/'); + + if (v.visitClass(slashClass)) { + v.visitElementContent(MappedElementKind.CLASS); + } + + if (v.visitField(fieldName, desc)) { + if (mapped != null) { + v.visitDstName(MappedElementKind.FIELD, 0, mapped); + } + + if (v.visitElementContent(MappedElementKind.FIELD) && comment != null) { + v.visitComment(MappedElementKind.FIELD, comment); + } + } + } + } + + private static final class MethodRow extends Row { + final String original; + final String mapped; + final String comment; + + MethodRow(String o, String m, String c) { + this.original = o; + this.mapped = m; + this.comment = c; + } + + @Override + void emit(MappingVisitor v) throws IOException { + if (original == null) { + return; + } + + int paren = original.indexOf('('); + + if (paren < 0) { + return; + } + + int lastDot = original.lastIndexOf('.', paren); + + if (lastDot < 0) { + return; + } + + String clsDotted = original.substring(0, lastDot); + String methodName = original.substring(lastDot + 1, paren); + String methodDesc = original.substring(paren); + String slashClass = clsDotted.replace('.', '/'); + + if (v.visitClass(slashClass)) { + v.visitElementContent(MappedElementKind.CLASS); + } + + if (v.visitMethod(methodName, methodDesc)) { + if (mapped != null) { + v.visitDstName(MappedElementKind.METHOD, 0, mapped); + } + + if (v.visitElementContent(MappedElementKind.METHOD) && comment != null) { + v.visitComment(MappedElementKind.METHOD, comment); + } + } + } + } + + private static final class ParamRow extends Row { + final String def; + final String posStr; + final String mappedName; + final String comment; + final String sourceName; + final String localMeta; + + ParamRow(String d, String p, String mapped, String c, String sourceName, String localMeta) { + this.def = d; + this.posStr = p; + this.mappedName = mapped; + this.comment = c; + this.sourceName = sourceName; + this.localMeta = localMeta; + } + + @Override + void emit(MappingVisitor v) throws IOException { + if (def == null || posStr == null || mappedName == null) { + return; + } + + int paren = def.indexOf('('); + + if (paren < 0) { + return; + } + + int lastDot = def.lastIndexOf('.', paren); + + if (lastDot < 0) { + return; + } + + String clsDotted = def.substring(0, lastDot); + String methodName = def.substring(lastDot + 1, paren); + String methodDesc = def.substring(paren); + + int pos; + + try { + pos = Integer.parseInt(posStr); + } catch (NumberFormatException e) { + return; + } + + if (pos <= 0) { + return; + } + + String slashClass = clsDotted.replace('.', '/'); + + if (v.visitClass(slashClass)) { + v.visitElementContent(MappedElementKind.CLASS); + } + + if (v.visitMethod(methodName, methodDesc)) { + v.visitElementContent(MappedElementKind.METHOD); + } + + int paramCount = countParams(methodDesc); + + if (pos <= paramCount) { + int zeroIdx = pos - 1; + String src = (sourceName != null ? sourceName : mappedName); + + if (v.visitMethodArg(zeroIdx, -1, src)) { + boolean needsDst = (mappedName != null) && (sourceName == null || !mappedName.equals(sourceName)); + + if (needsDst) { + v.visitDstName(MappedElementKind.METHOD_ARG, 0, mappedName); + } + + if (v.visitElementContent(MappedElementKind.METHOD_ARG) && comment != null) { + v.visitComment(MappedElementKind.METHOD_ARG, comment); + } + } + } else { + int lvtRowIndex = 0; + int lvIndex = 0; + int start = 0; + int end = -1; + + if (localMeta != null) { + String[] parts = localMeta.split(":"); + + if (parts.length == 4) { + try { + lvtRowIndex = Integer.parseInt(parts[0]); + lvIndex = Integer.parseInt(parts[1]); + start = Integer.parseInt(parts[2]); + end = Integer.parseInt(parts[3]); + } catch (NumberFormatException e) { + return; + } + } else { + return; + } + } else { + return; + } + + String src = (sourceName != null ? sourceName : mappedName); + + if (v.visitMethodVar(lvtRowIndex, lvIndex, start, end, src)) { + boolean needsDst = (mappedName != null) && (sourceName == null || !mappedName.equals(sourceName)); + + if (needsDst) { + v.visitDstName(MappedElementKind.METHOD_VAR, 0, mappedName); + } + + if (v.visitElementContent(MappedElementKind.METHOD_VAR) && comment != null) { + v.visitComment(MappedElementKind.METHOD_VAR, comment); + } + } + } + } + } + + private static void parseContent(List lines, MappingVisitor v) throws IOException { + Map classRowsByOrig = new LinkedHashMap(); + List otherRows = new ArrayList(); + + for (int i = 0; i < lines.size(); i++) { + String raw = lines.get(i); + + if (raw == null) { + continue; + } + + String trimmed = raw.trim(); + + if (trimmed.isEmpty() || trimmed.startsWith("#")) { + continue; + } + + String[] cols = splitToSix(trimmed); + String tipo = cols[0]; + String originalCol = normaliseEmpty(cols[1]); + String nuevo = normaliseEmpty(cols[2]); + String def = normaliseEmpty(cols[3]); + String pos = normaliseEmpty(cols[4]); + String desc = normaliseEmpty(cols[5]); + + if ("Class".equals(tipo)) { + classRowsByOrig.put(originalCol, new ClassRow(originalCol, nuevo, desc)); + } else if ("Var".equals(tipo)) { + otherRows.add(new FieldRow(originalCol, nuevo, desc)); + } else if ("Def".equals(tipo)) { + otherRows.add(new MethodRow(originalCol, nuevo, desc)); + } else if ("Param".equals(tipo)) { + String sourceName = null; + + String localMeta = null; + + if (originalCol != null) { + if (LOCAL_META_PATTERN.matcher(originalCol).matches()) { + localMeta = originalCol; + } else { + sourceName = originalCol; + } + } + + otherRows.add(new ParamRow(def, pos, nuevo, desc, sourceName, localMeta)); + } + } + + for (ClassRow cr : classRowsByOrig.values()) { + cr.resolve(classRowsByOrig); + } + + for (ClassRow cr : classRowsByOrig.values()) { + cr.emit(v); + } + + for (Row r : otherRows) { + r.emit(v); + } + } + + private static String[] splitToSix(String line) { + String[] arr = line.split(Pattern.quote(String.valueOf(DELIM)), -1); + + if (arr.length == 6) { + return arr; + } + + if (arr.length < 6) { + String[] six = new String[6]; + + System.arraycopy(arr, 0, six, 0, arr.length); + + for (int i = arr.length; i < 6; i++) { + six[i] = ""; + } + + return six; + } + + StringBuilder desc = new StringBuilder(arr[5]); + + for (int i = 6; i < arr.length; i++) { + if (desc.length() > 0) { + desc.append(DELIM); + } + + desc.append(arr[i]); + } + + String[] six = new String[6]; + System.arraycopy(arr, 0, six, 0, 5); + six[5] = desc.toString(); + return six; + } + + private static String normaliseEmpty(String s) { + return (s == null || s.isEmpty() || "nil".equals(s)) ? null : s; + } + + private static int countParams(String desc) { + if (desc == null || desc.length() == 0) { + return 0; + } + + int count = 0; + int i = 1; + + while (i < desc.length()) { + char c = desc.charAt(i); + + if (c == ')') { + break; + } + + if (c == 'L') { + int semi = desc.indexOf(';', i); + + if (semi < 0) { + break; + } + + i = semi + 1; + count++; + } else if (c == '[') { + i++; + + while (i < desc.length() && desc.charAt(i) == '[') { + i++; + } + + if (i < desc.length() && desc.charAt(i) == 'L') { + int semi = desc.indexOf(';', i); + + if (semi < 0) { + break; + } + + i = semi + 1; + } else { + i++; + } + + count++; + } else { + i++; + count++; + } + } - private static final char DELIM = '\u00B6'; - - private PDMEFileReader() {} - - public static void read(Reader in, MappingVisitor visitor) throws IOException { - Set flags = visitor.getFlags(); - - MappingVisitor downstream = visitor; - MemoryMappingTree buffering = null; - if (flags.contains(MappingFlag.NEEDS_ELEMENT_UNIQUENESS)) { - buffering = new MemoryMappingTree(); - visitor = buffering; - } - - BufferedReader br = new BufferedReader(in); - String header = br.readLine(); - if (header == null) return; - - List lines = new ArrayList(); - for (String l; (l = br.readLine()) != null; ) { - lines.add(l); - } - - boolean multi = flags.contains(MappingFlag.NEEDS_MULTIPLE_PASSES); - - while (true) { - boolean h = visitor.visitHeader(); - if (h) { - visitor.visitNamespaces(MappingUtil.NS_SOURCE_FALLBACK, - Collections.singletonList(MappingUtil.NS_TARGET_FALLBACK)); - } - - if (visitor.visitContent()) { - parseContent(lines, visitor); - } - - if (visitor.visitEnd()) break; - if (!multi) { - throw new IllegalStateException("Repeated visitation requested without NEEDS_MULTIPLE_PASSES"); - } - } - - if (buffering != null) { - buffering.accept(downstream); - } - } - - private static abstract class Row { - abstract void emit(MappingVisitor v) throws IOException; - } - - private static final class ClassRow extends Row { - final String original; // dotted - final String mappedCol; // raw column value (may be null) - final String comment; - String finalMapped; // resolved after all class rows collected - boolean resolved; - - ClassRow(String o, String m, String c) { - this.original = o; - this.mappedCol = m; - this.comment = c; - } - - void resolve(Map byOriginal) { - if (resolved) return; - resolved = true; - if (original == null) return; - - // Top-level? - int lastDollar = original.lastIndexOf('$'); - if (lastDollar < 0) { - // Top-level - if (mappedCol != null) { - finalMapped = mappedCol; - } else { - finalMapped = original; - } - return; - } - - // Inner class - String outerOrig = original.substring(0, lastDollar); - String tailOrig = original.substring(lastDollar + 1); - - ClassRow outerRow = byOriginal.get(outerOrig); - if (outerRow != null) { - outerRow.resolve(byOriginal); - } - - String outerFinal = outerRow != null && outerRow.finalMapped != null - ? outerRow.finalMapped - : outerOrig; - - if (mappedCol == null) { - // Propagate outer rename + original tail - finalMapped = outerFinal + '$' + tailOrig; - } else { - if (isSimpleTail(mappedCol)) { - // Tail-only rename - finalMapped = outerFinal + '$' + mappedCol; - } else { - // Explicit full mapped path - finalMapped = mappedCol; - } - } - } - - private static boolean isSimpleTail(String s) { - return s.indexOf('$') < 0 && s.indexOf('.') < 0; - } - - @Override - void emit(MappingVisitor v) throws IOException { - if (original == null) return; - if (finalMapped == null) finalMapped = original; - - String slashOrig = original.replace('.', '/'); - boolean identity = original.equals(finalMapped); - String slashMapped = identity ? null : finalMapped.replace('.', '/'); - - if (v.visitClass(slashOrig)) { - if (slashMapped != null) { - v.visitDstName(MappedElementKind.CLASS, 0, slashMapped); - } - if (v.visitElementContent(MappedElementKind.CLASS) && comment != null) { - v.visitComment(MappedElementKind.CLASS, comment); - } - } - } - } - - private static final class FieldRow extends Row { - final String original; // cls.field:desc - final String mapped; - final String comment; - - FieldRow(String o, String m, String c) { - this.original = o; - this.mapped = m; - this.comment = c; - } - - @Override - void emit(MappingVisitor v) throws IOException { - if (original == null) return; - int colon = original.lastIndexOf(':'); - if (colon < 0) return; - String desc = original.substring(colon + 1); - String ownerAndName = original.substring(0, colon); - int lastDot = ownerAndName.lastIndexOf('.'); - if (lastDot < 0) return; - String clsDotted = ownerAndName.substring(0, lastDot); - String fieldName = ownerAndName.substring(lastDot + 1); - String slashClass = clsDotted.replace('.', '/'); - - if (v.visitClass(slashClass)) { - v.visitElementContent(MappedElementKind.CLASS); - } - if (v.visitField(fieldName, desc)) { - if (mapped != null) { - v.visitDstName(MappedElementKind.FIELD, 0, mapped); - } - if (v.visitElementContent(MappedElementKind.FIELD) && comment != null) { - v.visitComment(MappedElementKind.FIELD, comment); - } - } - } - } - - private static final class MethodRow extends Row { - final String original; // cls.method(desc) - final String mapped; - final String comment; - - MethodRow(String o, String m, String c) { - this.original = o; - this.mapped = m; - this.comment = c; - } - - @Override - void emit(MappingVisitor v) throws IOException { - if (original == null) return; - int paren = original.indexOf('('); - if (paren < 0) return; - int lastDot = original.lastIndexOf('.', paren); - if (lastDot < 0) return; - String clsDotted = original.substring(0, lastDot); - String methodName = original.substring(lastDot + 1, paren); - String methodDesc = original.substring(paren); - String slashClass = clsDotted.replace('.', '/'); - - if (v.visitClass(slashClass)) { - v.visitElementContent(MappedElementKind.CLASS); - } - if (v.visitMethod(methodName, methodDesc)) { - if (mapped != null) { - v.visitDstName(MappedElementKind.METHOD, 0, mapped); - } - if (v.visitElementContent(MappedElementKind.METHOD) && comment != null) { - v.visitComment(MappedElementKind.METHOD, comment); - } - } - } - } - - private static final class ParamRow extends Row { - final String def; - final String posStr; - final String mappedName; - final String comment; - final String originalMeta; // for locals: lvtRowIndex:lvIndex:start:end - - ParamRow(String d, String p, String m, String c, String om) { - this.def = d; - this.posStr = p; - this.mappedName = m; - this.comment = c; - this.originalMeta = om; - } - - @Override - void emit(MappingVisitor v) throws IOException { - if (def == null || posStr == null || mappedName == null) return; - - int paren = def.indexOf('('); - if (paren < 0) return; - int lastDot = def.lastIndexOf('.', paren); - if (lastDot < 0) return; - - String clsDotted = def.substring(0, lastDot); - String methodName = def.substring(lastDot + 1, paren); - String methodDesc = def.substring(paren); - - int pos; - try { - pos = Integer.parseInt(posStr); - } catch (NumberFormatException e) { - return; - } - if (pos <= 0) return; - - String slashClass = clsDotted.replace('.', '/'); - - if (v.visitClass(slashClass)) { - v.visitElementContent(MappedElementKind.CLASS); - } - if (v.visitMethod(methodName, methodDesc)) { - v.visitElementContent(MappedElementKind.METHOD); - } - - int paramCount = countParams(methodDesc); - if (pos <= paramCount) { - int zero = pos - 1; - if (v.visitMethodArg(zero, -1, mappedName)) { - v.visitDstName(MappedElementKind.METHOD_ARG, 0, mappedName); - if (v.visitElementContent(MappedElementKind.METHOD_ARG) && comment != null) { - v.visitComment(MappedElementKind.METHOD_ARG, comment); - } - } - } else { - if (originalMeta == null) return; - String[] parts = originalMeta.split(":"); - if (parts.length != 4) return; - try { - int lvtRowIndex = Integer.parseInt(parts[0]); - int lvIndex = Integer.parseInt(parts[1]); - int start = Integer.parseInt(parts[2]); - int end = Integer.parseInt(parts[3]); - if (v.visitMethodVar(lvtRowIndex, lvIndex, start, end, mappedName)) { - v.visitDstName(MappedElementKind.METHOD_VAR, 0, mappedName); - if (v.visitElementContent(MappedElementKind.METHOD_VAR) && comment != null) { - v.visitComment(MappedElementKind.METHOD_VAR, comment); - } - } - } catch (NumberFormatException ignored) { - } - } - } - } - - private static void parseContent(List lines, MappingVisitor v) throws IOException { - Map classRowsByOrig = new LinkedHashMap(); - List nonClassRows = new ArrayList(); - - for (int i = 0; i < lines.size(); i++) { - String raw = lines.get(i); - if (raw == null) continue; - String trimmed = raw.trim(); - if (trimmed.isEmpty() || trimmed.startsWith("#")) continue; - - String[] cols = splitToSix(trimmed); - String tipo = cols[0]; - String original = normalizeEmpty(cols[1]); - String nuevo = normalizeEmpty(cols[2]); - String def = normalizeEmpty(cols[3]); - String pos = normalizeEmpty(cols[4]); - String desc = normalizeEmpty(cols[5]); - - if ("Class".equals(tipo)) { - ClassRow cr = new ClassRow(original, nuevo, desc); - classRowsByOrig.put(original, cr); - } else if ("Var".equals(tipo)) { - nonClassRows.add(new FieldRow(original, nuevo, desc)); - } else if ("Def".equals(tipo)) { - nonClassRows.add(new MethodRow(original, nuevo, desc)); - } else if ("Param".equals(tipo)) { - nonClassRows.add(new ParamRow(def, pos, nuevo, desc, original)); - } - } - - // Parse Subclases - for (ClassRow cr : classRowsByOrig.values()) { - cr.resolve(classRowsByOrig); - } - - // Emit classes first - for (ClassRow cr : classRowsByOrig.values()) { - cr.emit(v); - } - - for (Row r : nonClassRows) { - r.emit(v); - } - } - - - private static String[] splitToSix(String line) { - String[] arr = line.split(Pattern.quote(String.valueOf(DELIM)), -1); - if (arr.length == 6) return arr; - if (arr.length < 6) { - String[] six = new String[6]; - System.arraycopy(arr, 0, six, 0, arr.length); - for (int i = arr.length; i < 6; i++) six[i] = ""; - return six; - } - // collapse extra columns into desc - StringBuilder desc = new StringBuilder(arr[5]); - for (int i = 6; i < arr.length; i++) { - if (desc.length() > 0) desc.append(DELIM); - desc.append(arr[i]); - } - String[] six = new String[6]; - System.arraycopy(arr, 0, six, 0, 5); - six[5] = desc.toString(); - return six; - } - - private static String normalizeEmpty(String s) { - return (s == null || s.isEmpty() || "nil".equals(s)) ? null : s; - } - - private static int countParams(String desc) { - if (desc == null || desc.length() == 0) return 0; - int count = 0; - int i = 1; // skip '(' - while (i < desc.length()) { - char c = desc.charAt(i); - if (c == ')') break; - if (c == 'L') { - int semi = desc.indexOf(';', i); - if (semi < 0) break; - i = semi + 1; - count++; - } else if (c == '[') { - i++; - while (i < desc.length() && desc.charAt(i) == '[') i++; - if (i < desc.length() && desc.charAt(i) == 'L') { - int semi = desc.indexOf(';', i); - if (semi < 0) break; - i = semi + 1; - } else { - i++; - } - count++; - } else { - i++; // primitive - count++; - } - } - return count; - } + return count; + } } diff --git a/src/main/java/net/fabricmc/mappingio/format/pdme/PDMEFileWriter.java b/src/main/java/net/fabricmc/mappingio/format/pdme/PDMEFileWriter.java index aaf41e9c..954707af 100644 --- a/src/main/java/net/fabricmc/mappingio/format/pdme/PDMEFileWriter.java +++ b/src/main/java/net/fabricmc/mappingio/format/pdme/PDMEFileWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 FabricMC + * Copyright (c) 2023 FabricMC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,12 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package net.fabricmc.mappingio.format.pdme; -import net.fabricmc.mappingio.MappedElementKind; -import net.fabricmc.mappingio.MappingFlag; -import net.fabricmc.mappingio.MappingWriter; -import net.fabricmc.mappingio.format.MappingFormat; +package net.fabricmc.mappingio.format.pdme; import java.io.IOException; import java.io.Writer; @@ -28,11 +24,16 @@ import org.jetbrains.annotations.Nullable; +import net.fabricmc.mappingio.MappedElementKind; +import net.fabricmc.mappingio.MappingFlag; +import net.fabricmc.mappingio.MappingWriter; +import net.fabricmc.mappingio.format.MappingFormat; + /** - * {@linkplain MappingFormat#PDME_FILE Paragraph Delimited Mappings Extended file} writer. + * {@linkplain MappingFormat#PDME_FILE Paragraph Delimited Mappings Extended + * file} writer. */ public final class PDMEFileWriter implements MappingWriter { - private static final char DELIM = '\u00B6'; private final Writer out; @@ -41,12 +42,19 @@ public final class PDMEFileWriter implements MappingWriter { private String currentMethodName; private String currentMethodDesc; - private String dstClassFullSlash; // mapped class (slash) if provided - private String dstMemberName; // mapped field or method simple name + private int currentMethodParamCount; + private int nextLocalPos1; + + private String dstClassFullSlash; + private String dstMemberName; + private String dstParamName; private String fieldSrcName; private String fieldSrcDesc; + private String paramSrcName; + private int paramOrLocalPos1; + private boolean stagingParam; private StringBuilder stagedRow; private MappedElementKind stagedKind; @@ -71,10 +79,15 @@ public boolean visitClass(String srcName) throws IOException { currentClassSlash = srcName; currentMethodName = null; currentMethodDesc = null; + currentMethodParamCount = 0; + nextLocalPos1 = 0; dstClassFullSlash = null; dstMemberName = null; + dstParamName = null; fieldSrcName = null; fieldSrcDesc = null; + paramSrcName = null; + stagingParam = false; return true; } @@ -90,19 +103,54 @@ public boolean visitField(String srcName, String srcDesc) throws IOException { @Override public boolean visitMethod(String srcName, String srcDesc) throws IOException { flushStaged(); + if (srcDesc == null) { - return false; // skip methods without descriptor + return false; } + currentMethodName = srcName; currentMethodDesc = srcDesc; + currentMethodParamCount = countParams(srcDesc); + nextLocalPos1 = currentMethodParamCount + 1; dstMemberName = null; + dstParamName = null; + paramSrcName = null; + stagingParam = false; + return true; + } + + @Override + public boolean visitMethodArg(int argPosition, int lvIndex, @Nullable String srcName) throws IOException { + flushStaged(); + paramSrcName = srcName; + dstParamName = null; + paramOrLocalPos1 = argPosition + 1; + stagingParam = true; + return true; + } + + @Override + public boolean visitMethodVar(int lvtRowIndex, int lvIndex, int startOpIdx, int endOpIdx, @Nullable String srcName) + throws IOException { + flushStaged(); + paramSrcName = srcName; + dstParamName = null; + + if (nextLocalPos1 == 0) { + nextLocalPos1 = currentMethodParamCount + 1; + } + + paramOrLocalPos1 = nextLocalPos1++; + stagingParam = true; return true; } @Override public void visitDstName(MappedElementKind kind, int namespace, String name) { - if (namespace != 0 || name == null) + if (namespace != 0 || name == null) { return; + } + switch (kind) { case CLASS: dstClassFullSlash = name; @@ -111,8 +159,12 @@ public void visitDstName(MappedElementKind kind, int namespace, String name) { case METHOD: dstMemberName = name; break; + case METHOD_ARG: + case METHOD_VAR: + dstParamName = name; + break; default: - break; // Param kinds ignored (not supported here) + break; } } @@ -128,8 +180,11 @@ public boolean visitElementContent(MappedElementKind kind) throws IOException { case METHOD: stageMethod(); return true; + case METHOD_ARG: + case METHOD_VAR: + return stageParam(); default: - return false; // ignore args/locals/others + return false; } } @@ -163,27 +218,59 @@ private void stageMethod() { dstMemberName = null; } + private boolean stageParam() { + if (!stagingParam) { + return false; + } + + boolean hasSrc = paramSrcName != null && paramSrcName.length() > 0; + boolean hasDst = dstParamName != null && dstParamName.length() > 0; + + if (!hasSrc && !hasDst) { + dstParamName = null; + paramSrcName = null; + return false; + } + + String originalCol = hasSrc ? paramSrcName : "nil"; + String chosen = hasDst ? dstParamName : paramSrcName; + + String clsDotted = currentClassSlash.replace('/', '.'); + String def = clsDotted + '.' + currentMethodName + currentMethodDesc; + + stagedRow = begin("Param").append(originalCol).append(DELIM).append(chosen).append(DELIM).append(def) + .append(DELIM).append(paramOrLocalPos1).append(DELIM); + + stagedKind = MappedElementKind.METHOD_ARG; + dstParamName = null; + paramSrcName = null; + stagingParam = false; + return true; + } + private StringBuilder begin(String tipo) { return new StringBuilder().append(tipo).append(DELIM); } @Override public void visitComment(MappedElementKind kind, String comment) throws IOException { - if (stagedRow != null && stagedKind == kind) { - if (comment != null && !comment.isEmpty()) { - String esc = comment - .replaceAll("\\.+$", "") - .replace("\r\n", "\\n") - .replace("\n", "\\n") - .replace("\r", "\\n"); - - stagedRow.append(esc); - } - out.write(stagedRow.toString()); - out.write('\n'); - stagedRow = null; - stagedKind = null; - } + if (stagedRow == null) { + return; + } + + if (stagedKind == kind || (stagedKind == MappedElementKind.METHOD_ARG + && (kind == MappedElementKind.METHOD_ARG || kind == MappedElementKind.METHOD_VAR))) { + if (comment != null && !comment.isEmpty()) { + String esc = comment.replaceAll("\\.+$", "").replace("\r\n", "\\n").replace("\n", "\\n").replace("\r", + "\\n"); + stagedRow.append(esc); + } + + out.write(stagedRow.toString()); + out.write('\n'); + stagedRow = null; + stagedKind = null; + } } private void flushStaged() throws IOException { @@ -193,6 +280,8 @@ private void flushStaged() throws IOException { stagedRow = null; stagedKind = null; } + + stagingParam = false; } @Override @@ -201,17 +290,56 @@ public void close() throws IOException { out.close(); } - @Override - public boolean visitMethodArg(int argPosition, int lvIndex, @Nullable String srcName) throws IOException { - return false;// I could not figure out how to get this to work with the Unit Tests. Should be - // Param¶nil¶name¶featurecreep.example.ExampleClass$SubClass.TEST_METH(ILjava/lang/String;Ljava/lang/String;)V¶1¶JavaDocsOrComment - } + private static int countParams(String desc) { + if (desc == null || desc.length() == 0) { + return 0; + } - @Override - public boolean visitMethodVar(int lvtRowIndex, int lvIndex, int startOpIdx, int endOpIdx, @Nullable String srcName) - throws IOException { - return false;// I could not figure out how to get these to work with the Unit Tests. Should - // be - // Param¶nil¶name¶featurecreep.example.ExampleClass$SubClass.TEST_METH(ILjava/lang/String;Ljava/lang/String;)V¶1¶JavaDocsOrComment + int count = 0; + int i = 1; + + while (i < desc.length()) { + char c = desc.charAt(i); + + if (c == ')') { + break; + } + + if (c == 'L') { + int semi = desc.indexOf(';', i); + + if (semi < 0) { + break; + } + + i = semi + 1; + count++; + } else if (c == '[') { + i++; + + while (i < desc.length() && desc.charAt(i) == '[') { + i++; + } + + if (i < desc.length() && desc.charAt(i) == 'L') { + int semi = desc.indexOf(';', i); + + if (semi < 0) { + break; + } + + i = semi + 1; + } else { + i++; + } + + count++; + } else { + i++; + count++; + } + } + + return count; } } diff --git a/src/main/java/net/fabricmc/mappingio/tree/MemoryMappingTree.java b/src/main/java/net/fabricmc/mappingio/tree/MemoryMappingTree.java index b3d8d746..65a01707 100644 --- a/src/main/java/net/fabricmc/mappingio/tree/MemoryMappingTree.java +++ b/src/main/java/net/fabricmc/mappingio/tree/MemoryMappingTree.java @@ -1237,6 +1237,7 @@ private > T addMember(T entry, Map map, i void accept(MappingVisitor visitor, VisitOrder order, boolean supplyFieldDstDescs, boolean supplyMethodDstDescs) throws IOException { if (visitor.visitClass(getSrcName()) && acceptElement(visitor, null)) { boolean methodsFirst = order.isMethodsFirst() && fields != null && methods != null; + if (!methodsFirst && fields != null) { for (FieldEntry field : order.sortFields(fields.values())) { field.accept(visitor, supplyFieldDstDescs); diff --git a/src/test/java/net/fabricmc/mappingio/test/tests/reading/EmptyContentReadTest.java b/src/test/java/net/fabricmc/mappingio/test/tests/reading/EmptyContentReadTest.java index 04d6fa59..ed96b507 100644 --- a/src/test/java/net/fabricmc/mappingio/test/tests/reading/EmptyContentReadTest.java +++ b/src/test/java/net/fabricmc/mappingio/test/tests/reading/EmptyContentReadTest.java @@ -143,7 +143,7 @@ public void emptyRecafSimpleFile() throws Exception { public void emptyPDMEFile() throws Exception { PDMEFileReader.read(new StringReader("tipo¶original¶nuevo¶def¶pos¶desc"), target); } - + @Test public void emptyJobfFile() throws Exception { JobfFileReader.read(new StringReader(""), target); From 9a4ee5dd0d18fbfc5b43908b0270516f9a64f508 Mon Sep 17 00:00:00 2001 From: rhel Date: Thu, 24 Jul 2025 22:27:53 -0600 Subject: [PATCH 3/3] Update PDMEFileWriter.java, pdme.pdme, pdme.pdme, and 6 more files --- .../mappingio/format/pdme/PDMEFileWriter.java | 5 ++ .../propagated-except-remapped-dst/pdme.pdme | 6 +-- .../propagated/pdme.pdme | 10 ++-- .../unpropagated/pdme.pdme | 5 +- src/test/resources/reading/holes/pdme.pdme | 47 +++++++++++++++++++ .../reading/repeated-elements/enigma.mappings | 6 --- .../reading/repeated-elements/pdme.pdme | 17 +++++++ .../reading/repeated-elements/srg.srg | 2 +- src/test/resources/reading/valid/pdme.pdme | 9 ++++ 9 files changed, 91 insertions(+), 16 deletions(-) create mode 100644 src/test/resources/reading/holes/pdme.pdme create mode 100644 src/test/resources/reading/repeated-elements/pdme.pdme create mode 100644 src/test/resources/reading/valid/pdme.pdme diff --git a/src/main/java/net/fabricmc/mappingio/format/pdme/PDMEFileWriter.java b/src/main/java/net/fabricmc/mappingio/format/pdme/PDMEFileWriter.java index 954707af..18fe7db9 100644 --- a/src/main/java/net/fabricmc/mappingio/format/pdme/PDMEFileWriter.java +++ b/src/main/java/net/fabricmc/mappingio/format/pdme/PDMEFileWriter.java @@ -94,6 +94,11 @@ public boolean visitClass(String srcName) throws IOException { @Override public boolean visitField(String srcName, String srcDesc) throws IOException { flushStaged(); + + if (srcDesc == null) { + return false; + } + fieldSrcName = srcName; fieldSrcDesc = srcDesc; dstMemberName = null; diff --git a/src/test/resources/outer-class-name-propagation/propagated-except-remapped-dst/pdme.pdme b/src/test/resources/outer-class-name-propagation/propagated-except-remapped-dst/pdme.pdme index bf070fea..6e982a71 100644 --- a/src/test/resources/outer-class-name-propagation/propagated-except-remapped-dst/pdme.pdme +++ b/src/test/resources/outer-class-name-propagation/propagated-except-remapped-dst/pdme.pdme @@ -1,7 +1,7 @@ tipo¶original¶nuevo¶def¶pos¶desc Class¶class_1¶class1Ns0Rename¶nil¶nil¶ Var¶class_1.field_1:Lclass_1;¶field_1¶nil¶nil¶ -Class¶class_1$class_2¶class_2¶nil¶nil¶ +Class¶class_1$class_2¶class1Ns0Rename$class_2¶nil¶nil¶ Var¶class_1$class_2.field_2:Lclass_1$class_2;¶field_2¶nil¶nil¶ -Class¶class_1$class_2$class_3¶class_3¶nil¶nil¶ -Var¶class_1$class_2$class_3.field_2:Lclass_1$class_2$class_3;¶field_2¶nil¶nil¶ \ No newline at end of file +Class¶class_1$class_2$class_3¶class1Ns0Rename$class_2$class_3¶nil¶nil¶ +Var¶class_1$class_2$class_3.field_2:Lclass_1$class_2$class_3;¶field_2¶nil¶nil¶ diff --git a/src/test/resources/outer-class-name-propagation/propagated/pdme.pdme b/src/test/resources/outer-class-name-propagation/propagated/pdme.pdme index dbb1fcf4..6e982a71 100644 --- a/src/test/resources/outer-class-name-propagation/propagated/pdme.pdme +++ b/src/test/resources/outer-class-name-propagation/propagated/pdme.pdme @@ -1,7 +1,7 @@ tipo¶original¶nuevo¶def¶pos¶desc Class¶class_1¶class1Ns0Rename¶nil¶nil¶ -Var¶class_1.field_1¶field_1¶nil¶nil¶ -Class¶class_1$class_2¶class_2¶nil¶nil¶ -Var¶class_1$class_2.field_2¶field_2¶nil¶nil¶ -Class¶class_1$class_2$class_3¶class_3¶nil¶nil¶ -Var¶class_1$class_2$class_3.field_2¶field_2¶nil¶nil¶ \ No newline at end of file +Var¶class_1.field_1:Lclass_1;¶field_1¶nil¶nil¶ +Class¶class_1$class_2¶class1Ns0Rename$class_2¶nil¶nil¶ +Var¶class_1$class_2.field_2:Lclass_1$class_2;¶field_2¶nil¶nil¶ +Class¶class_1$class_2$class_3¶class1Ns0Rename$class_2$class_3¶nil¶nil¶ +Var¶class_1$class_2$class_3.field_2:Lclass_1$class_2$class_3;¶field_2¶nil¶nil¶ diff --git a/src/test/resources/outer-class-name-propagation/unpropagated/pdme.pdme b/src/test/resources/outer-class-name-propagation/unpropagated/pdme.pdme index 2cdb354a..301d02d5 100644 --- a/src/test/resources/outer-class-name-propagation/unpropagated/pdme.pdme +++ b/src/test/resources/outer-class-name-propagation/unpropagated/pdme.pdme @@ -1,4 +1,7 @@ tipo¶original¶nuevo¶def¶pos¶desc Class¶class_1¶class1Ns0Rename¶nil¶nil¶ +Var¶class_1.field_1:Lclass_1;¶field_1¶nil¶nil¶ Class¶class_1$class_2¶class_1$class_2¶nil¶nil¶ -Class¶class_1$class_2$class_3¶class_3¶nil¶nil¶ \ No newline at end of file +Var¶class_1$class_2.field_2:Lclass_1$class_2;¶field_2¶nil¶nil¶ +Class¶class_1$class_2$class_3¶class_1$class_2$class_3¶nil¶nil¶ +Var¶class_1$class_2$class_3.field_2:Lclass_1$class_2$class_3;¶field_2¶nil¶nil¶ diff --git a/src/test/resources/reading/holes/pdme.pdme b/src/test/resources/reading/holes/pdme.pdme new file mode 100644 index 00000000..44afec18 --- /dev/null +++ b/src/test/resources/reading/holes/pdme.pdme @@ -0,0 +1,47 @@ +tipo¶original¶nuevo¶def¶pos¶desc +Class¶class_1¶class_1¶nil¶nil¶ +Class¶package_2.class_2¶package_2.class_2¶nil¶nil¶ +Class¶class_3¶package_3.class3Ns0Rename¶nil¶nil¶ +Class¶package_4.class_4¶package_4.class_4¶nil¶nil¶ +Class¶class_5¶class_5¶nil¶nil¶This is a comment +Class¶package_6.class_6¶package_7.class6Ns0Rename¶nil¶nil¶This is a comment +Class¶class_7¶class_7¶nil¶nil¶This is a comment +Class¶package_8.class_8¶package_8.class_8¶nil¶nil¶ +Class¶class_9¶class_9¶nil¶nil¶ +Class¶class_9$class_10¶class_9$class10Ns0Rename¶nil¶nil¶ +Class¶class_11$class_12¶class_11$class_12¶nil¶nil¶ +Class¶class_13$class_14¶class_13$class_14¶nil¶nil¶This is a comment +Class¶class_15$class_16¶class_15$class16Ns0Rename¶nil¶nil¶This is a comment +Class¶class_17$class_18¶class_17$class_18¶nil¶nil¶This is a comment +Class¶class_19¶class_19¶nil¶nil¶ +Class¶package_20.class_20¶package_20.class_20¶nil¶nil¶ +Class¶package_20.class_20$class_21$class_22¶package_20.class_20$class_21$class22Ns0Rename¶nil¶nil¶ +Class¶class_23$class_24$class_25¶class_23$class_24$class_25¶nil¶nil¶ +Class¶package_26.class_26$class_27$class_28¶package_26.class_26$class_27$class_28¶nil¶nil¶This is a comment +Class¶class_29$class_30$class_31¶class_29$class_30$class31Ns0Rename¶nil¶nil¶This is a comment +Class¶package_32.class_32$class_33$class_34¶package_32.class_32$class_33$class_34¶nil¶nil¶This is a comment +Class¶class_35¶class_35¶nil¶nil¶ +Var¶class_35.field_1:I¶field_1¶nil¶nil¶ +Var¶class_35.field_2:Lcls;¶field2Ns0Rename¶nil¶nil¶ +Var¶class_35.field_3:Lpkg/cls;¶field_3¶nil¶nil¶ +Var¶class_35.field_4:[I¶field_4¶nil¶nil¶This is a comment +Var¶class_35.field_6:I¶field_6¶nil¶nil¶This is a comment +Def¶class_35.method_1()I¶method_1¶nil¶nil¶ +Def¶class_35.method_2(I)V¶method2Ns0Rename¶nil¶nil¶ +Def¶class_35.method_3(Lcls;)Lcls;¶method_3¶nil¶nil¶ +Def¶class_35.method_4(ILcls;)Lpkg/cls;¶method_4¶nil¶nil¶This is a comment +Def¶class_35.method_5(Lcls;[I)[[B¶method5Ns0Rename¶nil¶nil¶This is a comment +Def¶class_35.method_7()I¶method_7¶nil¶nil¶ +Param¶param_1¶param_1¶class_35.method_7()I¶1¶ +Param¶param_2¶param_2¶class_35.method_7()I¶3¶ +Param¶param_3¶param3Ns0Rename¶class_35.method_7()I¶5¶ +Param¶param_4¶param_4¶class_35.method_7()I¶7¶This is a comment +Param¶param_5¶param5Ns0Rename¶class_35.method_7()I¶9¶This is a comment +Param¶param_6¶param_6¶class_35.method_7()I¶11¶This is a comment +Def¶class_35.method_8(I)V¶method_8¶nil¶nil¶ +Param¶var_1¶var_1¶class_35.method_8(I)V¶2¶ +Param¶var_2¶var_2¶class_35.method_8(I)V¶3¶ +Param¶var_3¶var3Ns0Rename¶class_35.method_8(I)V¶4¶ +Param¶var_4¶var_4¶class_35.method_8(I)V¶5¶This is a comment +Param¶var_5¶var5Ns0Rename¶class_35.method_8(I)V¶6¶This is a comment +Param¶var_6¶var_6¶class_35.method_8(I)V¶7¶This is a comment diff --git a/src/test/resources/reading/repeated-elements/enigma.mappings b/src/test/resources/reading/repeated-elements/enigma.mappings index 2df119c8..0f0ec6ec 100644 --- a/src/test/resources/reading/repeated-elements/enigma.mappings +++ b/src/test/resources/reading/repeated-elements/enigma.mappings @@ -1,4 +1,3 @@ -CLASS class_1 class1Ns0Rename0 CLASS class_1 class1Ns0Rename FIELD field_1 field1Ns0Rename0 I FIELD field_1 field1Ns0Rename I @@ -6,13 +5,8 @@ CLASS class_1 class1Ns0Rename METHOD method_1 method1Ns0Rename ()I ARG 1 param1Ns0Rename0 ARG 1 param1Ns0Rename - CLASS class_2 class2Ns0Rename0 - CLASS class_2 class2Ns0Rename1 - COMMENT This is a comment. - CLASS class_2 class2Ns0Rename2 CLASS class_2 class2Ns0Rename COMMENT This is a comment FIELD field_2 field2Ns0Rename0 Lcls; FIELD field_2 field2Ns0Rename Lcls; -CLASS class_3 package_3/class3Ns0Rename0 CLASS class_3 package_3/class3Ns0Rename diff --git a/src/test/resources/reading/repeated-elements/pdme.pdme b/src/test/resources/reading/repeated-elements/pdme.pdme new file mode 100644 index 00000000..4bd6f300 --- /dev/null +++ b/src/test/resources/reading/repeated-elements/pdme.pdme @@ -0,0 +1,17 @@ +tipo¶original¶nuevo¶def¶pos¶desc +Class¶class_1¶class1Ns0Rename0¶nil¶nil¶ +Class¶class_1¶class1Ns0Rename¶nil¶nil¶ +Var¶class_1.field_1:I¶field1Ns0Rename0¶nil¶nil¶ +Var¶class_1.field_1:I¶field1Ns0Rename¶nil¶nil¶ +Def¶class_1.method_1()I¶method1Ns0Rename0¶nil¶nil¶ +Def¶class_1.method_1()I¶method1Ns0Rename¶nil¶nil¶ +Param¶param_1¶param1Ns0Rename0¶class_1.method_1()I¶1¶ +Param¶param_1¶param1Ns0Rename¶class_1.method_1()I¶1¶ +Param¶var_1¶var1Ns0Rename0¶class_1.method_1()I¶1¶ +Param¶var_1¶var1Ns0Rename¶class_1.method_1()I¶2¶ +Class¶class_1$class_2¶class1Ns0Rename$class2Ns0Rename0¶nil¶nil¶ +Class¶class_1$class_2¶class1Ns0Rename$class2Ns0Rename¶nil¶nil¶This is a comment +Var¶class_1$class_2.field_2:Lcls;¶field2Ns0Rename0¶nil¶nil¶ +Var¶class_1$class_2.field_2:Lcls;¶field2Ns0Rename¶nil¶nil¶ +Class¶class_3¶package_3.class3Ns0Rename0¶nil¶nil¶ +Class¶class_3¶package_3.class3Ns0Rename¶nil¶nil¶ diff --git a/src/test/resources/reading/repeated-elements/srg.srg b/src/test/resources/reading/repeated-elements/srg.srg index 753ad3f2..e0661c02 100644 --- a/src/test/resources/reading/repeated-elements/srg.srg +++ b/src/test/resources/reading/repeated-elements/srg.srg @@ -1,5 +1,5 @@ CL: class_1 class1Ns0Rename0 -CL: class_1 class1Ns0Rename1 +CL: class_1 class1Ns0Rename FD: class_1/field_1 class1Ns0Rename/field1Ns0Rename0 FD: class_1/field_1 class1Ns0Rename/field1Ns0Rename MD: class_1/method_1 ()I class1Ns0Rename/method1Ns0Rename0 ()I diff --git a/src/test/resources/reading/valid/pdme.pdme b/src/test/resources/reading/valid/pdme.pdme new file mode 100644 index 00000000..91645287 --- /dev/null +++ b/src/test/resources/reading/valid/pdme.pdme @@ -0,0 +1,9 @@ +tipo¶original¶nuevo¶def¶pos¶desc +Class¶class_1¶class1Ns0Rename¶nil¶nil¶ +Var¶class_1.field_1:I¶field1Ns0Rename¶nil¶nil¶ +Def¶class_1.method_1()I¶method1Ns0Rename¶nil¶nil¶ +Param¶param_1¶param1Ns0Rename¶class_1.method_1()I¶1¶ +Param¶var_1¶var1Ns0Rename¶class_1.method_1()I¶1¶ +Class¶class_1$class_2¶class1Ns0Rename$class2Ns0Rename¶nil¶nil¶This is a comment +Var¶class_1$class_2.field_2:Lcls;¶field2Ns0Rename¶nil¶nil¶ +Class¶class_3¶package_3.class3Ns0Rename¶nil¶nil¶