featureApplier) {
featureApplier.accept(packages);
return this;
}
@@ -156,7 +158,7 @@ public FeatureSet build() {
private boolean hasNamespaces;
private MetadataSupport fileMetadata;
private MetadataSupport elementMetadata;
- private NameFeatureBuilder packages;
+ private PackageSupportBuilder packages;
private ClassSupportBuilder classes;
private MemberSupportBuilder fields;
private MemberSupportBuilder methods;
@@ -165,6 +167,47 @@ public FeatureSet build() {
private ElementCommentSupport elementComments;
private boolean hasFileComments;
+ public static class PackageSupportBuilder {
+ PackageSupportBuilder() {
+ this(false);
+ }
+
+ PackageSupportBuilder(boolean initWithFullSupport) {
+ this(new NameFeatureBuilder(initWithFullSupport), initWithFullSupport);
+ }
+
+ PackageSupportBuilder(PackageSupport classFeature) {
+ this(new NameFeatureBuilder(classFeature), classFeature.hasStructureModification());
+ }
+
+ private PackageSupportBuilder(NameFeatureBuilder names, boolean hasStructureModification) {
+ this.names = names;
+ this.hasStructureModification = hasStructureModification;
+ }
+
+ public PackageSupportBuilder withSrcNames(FeaturePresence featurePresence) {
+ names.withSrcNames(featurePresence);
+ return this;
+ }
+
+ public PackageSupportBuilder withDstNames(FeaturePresence featurePresence) {
+ names.withDstNames(featurePresence);
+ return this;
+ }
+
+ public PackageSupportBuilder withStructureModification(boolean value) {
+ hasStructureModification = value;
+ return this;
+ }
+
+ public PackageSupport build() {
+ return new PackageSupportImpl(names.build(), hasStructureModification);
+ }
+
+ private NameFeatureBuilder names;
+ private boolean hasStructureModification;
+ }
+
public static class ClassSupportBuilder {
ClassSupportBuilder() {
this(false);
diff --git a/src/main/java/net/fabricmc/mappingio/format/FeatureSetImpl.java b/src/main/java/net/fabricmc/mappingio/format/FeatureSetImpl.java
index 30283a59..7e31c53c 100644
--- a/src/main/java/net/fabricmc/mappingio/format/FeatureSetImpl.java
+++ b/src/main/java/net/fabricmc/mappingio/format/FeatureSetImpl.java
@@ -17,7 +17,7 @@
package net.fabricmc.mappingio.format;
class FeatureSetImpl implements FeatureSet {
- FeatureSetImpl(boolean hasNamespaces, MetadataSupport fileMetadata, MetadataSupport elementMetadata, NameSupport packages, ClassSupport classes, MemberSupport fields, MemberSupport methods, LocalSupport args, LocalSupport vars, ElementCommentSupport elementComments, boolean hasFileComments) {
+ FeatureSetImpl(boolean hasNamespaces, MetadataSupport fileMetadata, MetadataSupport elementMetadata, PackageSupport packages, ClassSupport classes, MemberSupport fields, MemberSupport methods, LocalSupport args, LocalSupport vars, ElementCommentSupport elementComments, boolean hasFileComments) {
this.hasNamespaces = hasNamespaces;
this.fileMetadata = fileMetadata;
this.elementMetadata = elementMetadata;
@@ -47,7 +47,7 @@ public MetadataSupport elementMetadata() {
}
@Override
- public NameSupport packages() {
+ public PackageSupport packages() {
return packages;
}
@@ -89,7 +89,7 @@ public boolean hasFileComments() {
private final boolean hasNamespaces;
private final MetadataSupport fileMetadata;
private final MetadataSupport elementMetadata;
- private final NameSupport packages;
+ private final PackageSupport packages;
private final ClassSupport classes;
private final MemberSupport fields;
private final MemberSupport methods;
@@ -98,6 +98,20 @@ public boolean hasFileComments() {
private final ElementCommentSupport elementComments;
private final boolean hasFileComments;
+ static class PackageSupportImpl extends NameSupportImpl implements PackageSupport {
+ PackageSupportImpl(NameSupport names, boolean hasStructureModification) {
+ super(names.srcNames(), names.dstNames());
+ this.hasStructureModification = hasStructureModification;
+ }
+
+ @Override
+ public boolean hasStructureModification() {
+ return hasStructureModification;
+ }
+
+ private final boolean hasStructureModification;
+ }
+
static class ClassSupportImpl extends NameSupportImpl implements ClassSupport {
ClassSupportImpl(NameSupport names, boolean hasRepackaging) {
super(names.srcNames(), names.dstNames());
diff --git a/src/main/java/net/fabricmc/mappingio/format/MappingFormat.java b/src/main/java/net/fabricmc/mappingio/format/MappingFormat.java
index b281ce36..79b9e0a0 100644
--- a/src/main/java/net/fabricmc/mappingio/format/MappingFormat.java
+++ b/src/main/java/net/fabricmc/mappingio/format/MappingFormat.java
@@ -137,13 +137,12 @@ public enum MappingFormat {
/**
* The {@code SRG} ("Searge RetroGuard") mapping format, as specified here.
- *
- * @implNote Package mappings are currently not supported.
*/
SRG_FILE("SRG file", "srg", true, FeatureSetBuilder.create()
.withPackages(p -> p
.withSrcNames(FeaturePresence.REQUIRED)
- .withDstNames(FeaturePresence.REQUIRED))
+ .withDstNames(FeaturePresence.REQUIRED)
+ .withStructureModification(true))
.withClasses(c -> c
.withSrcNames(FeaturePresence.REQUIRED)
.withDstNames(FeaturePresence.REQUIRED)
@@ -162,8 +161,6 @@ public enum MappingFormat {
* The {@code XSRG} ("Extended SRG") mapping format, as specified here.
*
* Same as SRG, but with field descriptors.
- *
- * @implNote Package mappings are currently not supported.
*/
XSRG_FILE("XSRG file", "xsrg", true, FeatureSetBuilder.createFrom(SRG_FILE.features)
.withFields(f -> f
@@ -176,7 +173,8 @@ public enum MappingFormat {
JAM_FILE("JAM file", "jam", true, FeatureSetBuilder.createFrom(SRG_FILE.features)
.withPackages(p -> p
.withSrcNames(FeaturePresence.ABSENT)
- .withDstNames(FeaturePresence.ABSENT))
+ .withDstNames(FeaturePresence.ABSENT)
+ .withStructureModification(false))
.withFields(f -> f
.withSrcDescs(FeaturePresence.REQUIRED))
.withMethods(m -> m
@@ -188,8 +186,6 @@ public enum MappingFormat {
/**
* The {@code CSRG} ("Compact SRG", since it saves disk space over SRG) mapping format, as specified here.
- *
- * @implNote Package mappings are currently not supported.
*/
CSRG_FILE("CSRG file", "csrg", true, FeatureSetBuilder.createFrom(SRG_FILE.features)
.withMethods(m -> m
@@ -199,15 +195,13 @@ public enum MappingFormat {
* The {@code TSRG} ("Tiny SRG", since it saves disk space over SRG) mapping format, as specified here.
*
*
Same as CSRG, but hierarchical instead of flat.
- *
- * @implNote Package mappings are currently not supported.
*/
TSRG_FILE("TSRG file", "tsrg", true, FeatureSetBuilder.createFrom(CSRG_FILE.features)),
/**
* The {@code TSRG v2} mapping format, as specified here.
*
- * @implNote Package mappings and static markers for methods are currently not supported.
+ * @implNote Static method markers are currently not supported.
*/
TSRG_2_FILE("TSRG v2 file", "tsrg", true, FeatureSetBuilder.createFrom(TSRG_FILE.features)
.withNamespaces(true)
@@ -222,13 +216,14 @@ public enum MappingFormat {
/**
* The IntelliJ IDEA migration map format, as implemented here.
*
- * @implNote Package mappings and file metadata are currently not supported.
+ * @implNote File metadata is currently not supported.
*/
INTELLIJ_MIGRATION_MAP_FILE("IntelliJ migration map file", "xml", true, FeatureSetBuilder.create()
.withFileMetadata(MetadataSupport.FIXED) // migration map name and description
.withPackages(p -> p
.withSrcNames(FeaturePresence.REQUIRED)
- .withDstNames(FeaturePresence.REQUIRED))
+ .withDstNames(FeaturePresence.REQUIRED)
+ .withStructureModification(true))
.withClasses(c -> c
.withSrcNames(FeaturePresence.REQUIRED)
.withDstNames(FeaturePresence.REQUIRED)
@@ -255,8 +250,6 @@ public enum MappingFormat {
/**
* The {@code JOBF} mapping format, as implemented here.
- *
- * @implNote Package mappings are currently not supported.
*/
JOBF_FILE("JOBF file", "jobf", true, FeatureSetBuilder.create()
.withPackages(p -> p
diff --git a/src/main/java/net/fabricmc/mappingio/format/intellij/MigrationMapFileReader.java b/src/main/java/net/fabricmc/mappingio/format/intellij/MigrationMapFileReader.java
index 1148c177..02547d5d 100644
--- a/src/main/java/net/fabricmc/mappingio/format/intellij/MigrationMapFileReader.java
+++ b/src/main/java/net/fabricmc/mappingio/format/intellij/MigrationMapFileReader.java
@@ -122,14 +122,17 @@ private static void read0(BufferedReader reader, String sourceNs, String targetN
break;
case "entry":
String type = xmlReader.getAttributeValue(null, "type");
+ boolean isPackage;
if (type == null || type.isEmpty()) throw new IOException("missing/empty type attribute at line "+xmlReader.getLocation().getLineNumber());
- if (type.equals("package")) continue; // TODO: support packages
- if (!type.equals("class")) throw new IOException("unexpected entry type "+type+" at line "+xmlReader.getLocation().getLineNumber());
+
+ if (!(isPackage = type.equals("package")) && !type.equals("class")) {
+ throw new IOException("unexpected entry type "+type+" at line "+xmlReader.getLocation().getLineNumber());
+ }
String srcName = xmlReader.getAttributeValue(null, "oldName");
String dstName = xmlReader.getAttributeValue(null, "newName");
- // String recursive = xmlReader.getAttributeValue(null, "recursive"); // only used for packages
+ // String recursive = xmlReader.getAttributeValue(null, "recursive"); // only used for packages, indicates if subpackages should also be renamed
if (srcName == null || srcName.isEmpty()) throw new IOException("missing/empty oldName attribute at line "+xmlReader.getLocation().getLineNumber());
if (dstName == null || dstName.isEmpty()) throw new IOException("missing/empty newName attribute at line "+xmlReader.getLocation().getLineNumber());
@@ -137,7 +140,11 @@ private static void read0(BufferedReader reader, String sourceNs, String targetN
srcName = srcName.replace('.', '/');
dstName = dstName.replace('.', '/');
- if (visitor.visitClass(srcName)) {
+ if (isPackage && visitor.visitPackage(srcName)) {
+ visitor.visitDstName(MappedElementKind.PACKAGE, 0, dstName);
+ visitor.visitElementContent(MappedElementKind.PACKAGE);
+ // TODO: visit "recursive" attribute as element metadata once https://github.com/FabricMC/mapping-io/pull/41 is merged
+ } else if (!isPackage && visitor.visitClass(srcName)) {
visitor.visitDstName(MappedElementKind.CLASS, 0, dstName);
visitor.visitElementContent(MappedElementKind.CLASS);
}
diff --git a/src/main/java/net/fabricmc/mappingio/format/intellij/MigrationMapFileWriter.java b/src/main/java/net/fabricmc/mappingio/format/intellij/MigrationMapFileWriter.java
index 95c9b5e2..181ac974 100644
--- a/src/main/java/net/fabricmc/mappingio/format/intellij/MigrationMapFileWriter.java
+++ b/src/main/java/net/fabricmc/mappingio/format/intellij/MigrationMapFileWriter.java
@@ -122,10 +122,20 @@ public void visitMetadata(String key, @Nullable String value) throws IOException
}
}
+ @Override
+ public boolean visitPackage(String srcName) throws IOException {
+ this.srcName = srcName;
+ this.dstName = null;
+ this.isPackage = true;
+
+ return true;
+ }
+
@Override
public boolean visitClass(String srcName) throws IOException {
this.srcName = srcName;
this.dstName = null;
+ this.isPackage = false;
return true;
}
@@ -166,7 +176,11 @@ public boolean visitElementContent(MappedElementKind targetKind) throws IOExcept
xmlWriter.writeEmptyElement("entry");
xmlWriter.writeAttribute("oldName", srcName.replace('/', '.'));
xmlWriter.writeAttribute("newName", dstName.replace('/', '.'));
- xmlWriter.writeAttribute("type", "class");
+ xmlWriter.writeAttribute("type", isPackage ? "package" : "class");
+
+ if (isPackage) {
+ xmlWriter.writeAttribute("recursive", "false"); // TODO: true or false?
+ }
} catch (XMLStreamException e) {
throw new IOException(e);
}
@@ -185,6 +199,7 @@ public void visitComment(MappedElementKind targetKind, String comment) throws IO
private XMLStreamWriter xmlWriter;
private boolean wroteName;
private boolean wroteOrder;
+ private boolean isPackage;
private String srcName;
private String dstName;
}
diff --git a/src/main/java/net/fabricmc/mappingio/format/jobf/JobfFileReader.java b/src/main/java/net/fabricmc/mappingio/format/jobf/JobfFileReader.java
index e3a13489..b4828eb5 100644
--- a/src/main/java/net/fabricmc/mappingio/format/jobf/JobfFileReader.java
+++ b/src/main/java/net/fabricmc/mappingio/format/jobf/JobfFileReader.java
@@ -73,7 +73,21 @@ private static void read(ColumnFileReader reader, String sourceNs, String target
do {
boolean isField;
- if (reader.nextCol("c")) { // class: c . =
+ if (reader.nextCol("p")) { // package: p =
+ String srcName = reader.nextCol();
+ if (srcName == null || srcName.isEmpty()) throw new IOException("missing package-name-a in line "+reader.getLineNumber());
+ srcName = srcName.replace('.', '/');
+
+ if (visitor.visitPackage(srcName)) {
+ readSeparator(reader);
+
+ String dstName = reader.nextCol();
+ if (dstName == null || dstName.isEmpty()) throw new IOException("missing package-name-b in line "+reader.getLineNumber());
+
+ visitor.visitDstName(MappedElementKind.PACKAGE, 0, dstName.replace('.', '/'));
+ visitor.visitElementContent(MappedElementKind.PACKAGE);
+ }
+ } else if (reader.nextCol("c")) { // class: c . =
String srcName = reader.nextCol();
if (srcName == null || srcName.isEmpty()) throw new IOException("missing class-name-a in line "+reader.getLineNumber());
srcName = srcName.replace('.', '/');
@@ -128,8 +142,6 @@ private static void read(ColumnFileReader reader, String sourceNs, String target
visitor.visitElementContent(kind);
}
}
- } else if (reader.nextCol("p")) { // package: p =
- // TODO
}
} while (reader.nextLine(0));
}
diff --git a/src/main/java/net/fabricmc/mappingio/format/jobf/JobfFileWriter.java b/src/main/java/net/fabricmc/mappingio/format/jobf/JobfFileWriter.java
index 39af0dbe..c8c497b8 100644
--- a/src/main/java/net/fabricmc/mappingio/format/jobf/JobfFileWriter.java
+++ b/src/main/java/net/fabricmc/mappingio/format/jobf/JobfFileWriter.java
@@ -51,6 +51,14 @@ public Set getFlags() {
public void visitNamespaces(String srcNamespace, List dstNamespaces) throws IOException {
}
+ @Override
+ public boolean visitPackage(String srcName) throws IOException {
+ packageSrcName = srcName;
+ dstName = null;
+
+ return true;
+ }
+
@Override
public boolean visitClass(String srcName) throws IOException {
classSrcName = srcName;
@@ -104,12 +112,23 @@ public void visitDstName(MappedElementKind targetKind, int namespace, String nam
@Override
public boolean visitElementContent(MappedElementKind targetKind) throws IOException {
+ boolean isPackage = targetKind == MappedElementKind.PACKAGE;
boolean isClass = targetKind == MappedElementKind.CLASS;
boolean isField = false;
- if (dstName == null) return isClass;
+ if (dstName == null) {
+ return isPackage || isClass;
+ }
- if ((isClass)) {
+ if (isPackage) {
+ if (countOccurrences(packageSrcName, '/') != countOccurrences(dstName, '/')) {
+ return false; // JOBF doesn't allow changes to the package structure
+ }
+
+ packageSrcName = packageSrcName.replace('/', '.');
+ dstName = dstName.replace('/', '.');
+ write("p ");
+ } else if (isClass) {
int srcNameLastSep = classSrcName.lastIndexOf('/');
int dstNameLastSep = dstName.lastIndexOf('/');
String srcPkg = classSrcName.substring(0, srcNameLastSep + 1);
@@ -127,9 +146,9 @@ public boolean visitElementContent(MappedElementKind targetKind) throws IOExcept
throw new IllegalStateException("unexpected invocation for "+targetKind);
}
- write(classSrcName);
+ write(isPackage ? packageSrcName : classSrcName);
- if (!isClass) {
+ if (!isPackage && !isClass) {
write(".");
write(memberSrcName);
@@ -158,9 +177,20 @@ private void writeLn() throws IOException {
writer.write('\n');
}
+ private int countOccurrences(String str, char c) {
+ int count = 0;
+
+ for (int i = 0; i < str.length(); i++) {
+ if (str.charAt(i) == c) count++;
+ }
+
+ return count;
+ }
+
private static final Set flags = EnumSet.of(MappingFlag.NEEDS_SRC_FIELD_DESC, MappingFlag.NEEDS_SRC_METHOD_DESC);
private final Writer writer;
+ private String packageSrcName;
private String classSrcName;
private String memberSrcName;
private String memberSrcDesc;
diff --git a/src/main/java/net/fabricmc/mappingio/format/srg/CsrgFileWriter.java b/src/main/java/net/fabricmc/mappingio/format/srg/CsrgFileWriter.java
index 50ceedbb..4cb51e1b 100644
--- a/src/main/java/net/fabricmc/mappingio/format/srg/CsrgFileWriter.java
+++ b/src/main/java/net/fabricmc/mappingio/format/srg/CsrgFileWriter.java
@@ -52,6 +52,13 @@ public void visitNamespaces(String srcNamespace, List dstNamespaces) thr
// not supported, skip
}
+ @Override
+ public boolean visitPackage(String srcName) throws IOException {
+ packageSrcName = srcName + "/";
+
+ return true;
+ }
+
@Override
public boolean visitClass(String srcName) throws IOException {
classSrcName = srcName;
@@ -92,15 +99,22 @@ public boolean visitMethodVar(int lvtRowIndex, int lvIndex, int startOpIdx, int
public void visitDstName(MappedElementKind targetKind, int namespace, String name) {
if (namespace != 0) return;
+ if (targetKind == MappedElementKind.PACKAGE && name != null) {
+ name += "/";
+ }
+
dstName = name;
}
@Override
public boolean visitElementContent(MappedElementKind targetKind) throws IOException {
if (dstName != null) {
- write(classSrcName);
+ boolean isPackage = targetKind == MappedElementKind.PACKAGE;
+ boolean isClass = targetKind == MappedElementKind.CLASS;
+
+ write(isPackage ? packageSrcName : classSrcName);
- if (targetKind != MappedElementKind.CLASS) {
+ if (!isPackage && !isClass) {
writeSpace();
write(memberSrcName);
@@ -114,8 +128,8 @@ public boolean visitElementContent(MappedElementKind targetKind) throws IOExcept
writeSpace();
write(dstName);
- writeLn();
+ writeLn();
dstName = null;
}
@@ -142,6 +156,7 @@ private void writeLn() throws IOException {
private static final Set flags = EnumSet.of(MappingFlag.NEEDS_SRC_METHOD_DESC);
private final Writer writer;
+ private String packageSrcName;
private String classSrcName;
private String memberSrcName;
private String methodSrcDesc;
diff --git a/src/main/java/net/fabricmc/mappingio/format/srg/SrgFileReader.java b/src/main/java/net/fabricmc/mappingio/format/srg/SrgFileReader.java
index 7884b41a..b952e315 100644
--- a/src/main/java/net/fabricmc/mappingio/format/srg/SrgFileReader.java
+++ b/src/main/java/net/fabricmc/mappingio/format/srg/SrgFileReader.java
@@ -76,7 +76,23 @@ private static void read(ColumnFileReader reader, String sourceNs, String target
do {
boolean isMethod;
- if (reader.nextCol("CL:")) { // class: CL:
+ if (reader.nextCol("PK:")) { // package: PK: / /
+ String srcName = reader.nextCol();
+ if (srcName == null || srcName.isEmpty()) throw new IOException("missing package-name-a in line "+reader.getLineNumber());
+
+ if (classContentVisitPending) {
+ visitor.visitElementContent(MappedElementKind.CLASS);
+ classContentVisitPending = false;
+ }
+
+ if (visitor.visitPackage(srcName.substring(0, srcName.length() - 1))) {
+ String dstName = reader.nextCol();
+ if (dstName == null || dstName.isEmpty()) throw new IOException("missing package-name-b in line "+reader.getLineNumber());
+
+ visitor.visitDstName(MappedElementKind.PACKAGE, 0, dstName.substring(0, dstName.length() - 1));
+ visitor.visitElementContent(MappedElementKind.PACKAGE);
+ }
+ } else if (reader.nextCol("CL:")) { // class: CL:
String srcName = reader.nextCol();
if (srcName == null || srcName.isEmpty()) throw new IOException("missing class-name-a in line "+reader.getLineNumber());
diff --git a/src/main/java/net/fabricmc/mappingio/format/srg/SrgFileWriter.java b/src/main/java/net/fabricmc/mappingio/format/srg/SrgFileWriter.java
index 84251990..e62efc4d 100644
--- a/src/main/java/net/fabricmc/mappingio/format/srg/SrgFileWriter.java
+++ b/src/main/java/net/fabricmc/mappingio/format/srg/SrgFileWriter.java
@@ -53,6 +53,14 @@ public Set getFlags() {
public void visitNamespaces(String srcNamespace, List dstNamespaces) throws IOException {
}
+ @Override
+ public boolean visitPackage(String srcName) throws IOException {
+ packageSrcName = srcName + "/";
+ packageDstName = null;
+
+ return true;
+ }
+
@Override
public boolean visitClass(String srcName) throws IOException {
classSrcName = srcName;
@@ -104,6 +112,9 @@ public void visitDstName(MappedElementKind targetKind, int namespace, String nam
if (namespace != 0) return;
switch (targetKind) {
+ case PACKAGE:
+ packageDstName = name == null ? null : name + "/";
+ break;
case CLASS:
classDstName = name;
break;
@@ -125,9 +136,18 @@ public void visitDstDesc(MappedElementKind targetKind, int namespace, String des
@Override
public boolean visitElementContent(MappedElementKind targetKind) throws IOException {
+ boolean isPackage = false;
+ boolean isClass = false;
+
switch (targetKind) {
+ case PACKAGE:
+ if (packageDstName == null) return false;
+ isPackage = true;
+ write("PK: ");
+ break;
case CLASS:
if (classDstName == null) return true;
+ isClass = true;
write("CL: ");
break;
case FIELD:
@@ -142,9 +162,9 @@ public boolean visitElementContent(MappedElementKind targetKind) throws IOExcept
throw new IllegalStateException("unexpected invocation for "+targetKind);
}
- write(classSrcName);
+ write(isPackage ? packageSrcName : classSrcName);
- if (targetKind != MappedElementKind.CLASS) {
+ if (!isPackage && !isClass) {
write("/");
write(memberSrcName);
@@ -155,10 +175,11 @@ public boolean visitElementContent(MappedElementKind targetKind) throws IOExcept
}
write(" ");
- if (classDstName == null) classDstName = classSrcName;
- write(classDstName);
+ write(isPackage
+ ? packageDstName != null ? packageDstName : packageSrcName
+ : classDstName != null ? classDstName : classSrcName);
- if (targetKind != MappedElementKind.CLASS) {
+ if (!isPackage && !isClass) {
write("/");
write(memberDstName);
@@ -170,7 +191,7 @@ public boolean visitElementContent(MappedElementKind targetKind) throws IOExcept
writeLn();
- return targetKind == MappedElementKind.CLASS; // only members are supported, skip anything but class contents
+ return targetKind == MappedElementKind.CLASS; // skip anything but members
}
@Override
@@ -197,9 +218,11 @@ private void writeLn() throws IOException {
private final Writer writer;
private final boolean xsrg;
+ private String packageSrcName;
private String classSrcName;
private String memberSrcName;
private String memberSrcDesc;
+ private String packageDstName;
private String classDstName;
private String memberDstName;
private String memberDstDesc;
diff --git a/src/main/java/net/fabricmc/mappingio/format/srg/TsrgFileReader.java b/src/main/java/net/fabricmc/mappingio/format/srg/TsrgFileReader.java
index fdad07a9..2a59b8cd 100644
--- a/src/main/java/net/fabricmc/mappingio/format/srg/TsrgFileReader.java
+++ b/src/main/java/net/fabricmc/mappingio/format/srg/TsrgFileReader.java
@@ -128,7 +128,7 @@ private static void read(ColumnFileReader reader, String sourceNs, String target
reader.discardMark();
String[] parts = line.split("((?<= )|(?= ))"); // Split on spaces, but keep them
- if (format != MappingFormat.TSRG_2_FILE && parts.length >= 4 && !parts[3].startsWith("#")) { // CSRG
+ if (format != MappingFormat.TSRG_2_FILE && parts.length >= 4 && !parts[3].startsWith("#")) { // CSRG member
format = MappingFormat.CSRG_FILE;
String clsName = parts[0];
if (clsName.isEmpty()) throw new IOException("missing class-name-a in line "+reader.getLineNumber());
@@ -173,14 +173,19 @@ private static void read(ColumnFileReader reader, String sourceNs, String target
}
String srcName = reader.nextCol();
- if (srcName == null || srcName.endsWith("/")) continue;
- if (srcName.isEmpty()) throw new IOException("missing class-name-a in line "+reader.getLineNumber());
+ if (srcName == null || srcName.isEmpty()) throw new IOException("missing package-/class-name-a in line "+reader.getLineNumber());
- lastClass = srcName;
- visitLastClass = visitor.visitClass(srcName);
+ if (srcName.endsWith("/")) { // package
+ if (visitor.visitPackage(srcName.substring(0, srcName.length() - 1))) {
+ readElement(reader, MappedElementKind.PACKAGE, 0, dstNsCount, visitor);
+ }
+ } else { // class
+ lastClass = srcName;
+ visitLastClass = visitor.visitClass(srcName);
- if (visitLastClass) {
- visitLastClass = readClass(reader, format == MappingFormat.TSRG_2_FILE, dstNsCount, nameTmp, visitor);
+ if (visitLastClass) {
+ visitLastClass = readClass(reader, format == MappingFormat.TSRG_2_FILE, dstNsCount, nameTmp, visitor);
+ }
}
} while (reader.nextLine(0));
}
@@ -299,6 +304,10 @@ private static void readDstNames(ColumnFileReader reader, MappedElementKind subj
if (name == null) throw new IOException("missing name columns in line "+reader.getLineNumber());
if (name.isEmpty()) throw new IOException("missing destination name in line "+reader.getLineNumber());
+ if (subjectKind == MappedElementKind.PACKAGE) {
+ name = name.substring(0, name.length() - 1);
+ }
+
visitor.visitDstName(subjectKind, dstNs, name);
}
}
diff --git a/src/main/java/net/fabricmc/mappingio/format/srg/TsrgFileWriter.java b/src/main/java/net/fabricmc/mappingio/format/srg/TsrgFileWriter.java
index 1536914b..1d289cbd 100644
--- a/src/main/java/net/fabricmc/mappingio/format/srg/TsrgFileWriter.java
+++ b/src/main/java/net/fabricmc/mappingio/format/srg/TsrgFileWriter.java
@@ -72,6 +72,14 @@ public void visitMetadata(String key, @Nullable String value) throws IOException
// TODO: Support the static method marker once https://github.com/FabricMC/mapping-io/pull/41 is merged
}
+ @Override
+ public boolean visitPackage(String srcName) throws IOException {
+ pkgSrcName = srcName += "/";
+ hasAnyDstNames = false;
+
+ return true;
+ }
+
@Override
public boolean visitClass(String srcName) throws IOException {
clsSrcName = srcName;
@@ -124,6 +132,10 @@ public boolean visitMethodVar(int lvtRowIndex, int lvIndex, int startOpIdx, int
public void visitDstName(MappedElementKind targetKind, int namespace, String name) {
if (!tsrg2 && namespace != 0) return;
+ if (targetKind == MappedElementKind.PACKAGE && name != null) {
+ name += "/";
+ }
+
dstNames[namespace] = name;
hasAnyDstNames |= name != null;
}
@@ -131,11 +143,11 @@ public void visitDstName(MappedElementKind targetKind, int namespace, String nam
@Override
public boolean visitElementContent(MappedElementKind targetKind) throws IOException {
if (classContentVisitPending && targetKind != MappedElementKind.CLASS && hasAnyDstNames) {
- String[] memberOrArgDstNames = dstNames.clone();
+ String[] packageOrMemberOrArgDstNames = dstNames.clone();
Arrays.fill(dstNames, clsSrcName);
visitElementContent(MappedElementKind.CLASS);
classContentVisitPending = false;
- dstNames = memberOrArgDstNames;
+ dstNames = packageOrMemberOrArgDstNames;
}
if (methodContentVisitPending && targetKind == MappedElementKind.METHOD_ARG && hasAnyDstNames) {
@@ -149,6 +161,10 @@ public boolean visitElementContent(MappedElementKind targetKind) throws IOExcept
String srcName = null;
switch (targetKind) {
+ case PACKAGE:
+ if (!hasAnyDstNames) return false;
+ srcName = pkgSrcName;
+ break;
case CLASS:
if (!hasAnyDstNames) {
classContentVisitPending = true;
@@ -204,8 +220,7 @@ public boolean visitElementContent(MappedElementKind targetKind) throws IOExcept
Arrays.fill(dstNames, null);
- return targetKind == MappedElementKind.CLASS
- || (tsrg2 && targetKind == MappedElementKind.METHOD);
+ return targetKind == MappedElementKind.CLASS || (tsrg2 && targetKind == MappedElementKind.METHOD);
}
@Override
@@ -239,6 +254,7 @@ private void writeLn() throws IOException {
private final Writer writer;
private final boolean tsrg2;
+ private String pkgSrcName;
private String clsSrcName;
private String memberSrcName;
private String memberSrcDesc;
diff --git a/src/main/java/net/fabricmc/mappingio/tree/MappingTree.java b/src/main/java/net/fabricmc/mappingio/tree/MappingTree.java
index a24de62d..5a184b8d 100644
--- a/src/main/java/net/fabricmc/mappingio/tree/MappingTree.java
+++ b/src/main/java/net/fabricmc/mappingio/tree/MappingTree.java
@@ -84,6 +84,34 @@ public interface MappingTree extends MappingTreeView {
*/
boolean removeMetadata(String key);
+ @Override
+ Collection extends PackageMapping> getPackages();
+ @Override
+ @Nullable
+ PackageMapping getPackage(String srcName);
+
+ @Override
+ @Nullable
+ default PackageMapping getPackage(String name, int namespace) {
+ return (PackageMapping) MappingTreeView.super.getPackage(name, namespace);
+ }
+
+ /**
+ * Merges a package mapping into the tree.
+ *
+ * @return The {@link PackageMapping} instance present in the tree after the merge has occurred.
+ * May or may not be the passed instance.
+ */
+ PackageMapping addPackage(PackageMapping pkg);
+
+ /**
+ * Removes a package mapping from the tree.
+ *
+ * @return The removed package mapping, if any.
+ */
+ @Nullable
+ PackageMapping removePackage(String srcName);
+
@Override
Collection extends ClassMapping> getClasses();
@Override
@@ -227,6 +255,8 @@ interface ElementMapping extends ElementMappingView {
void setComment(String comment);
}
+ interface PackageMapping extends ElementMapping, PackageMappingView { }
+
interface ClassMapping extends ElementMapping, ClassMappingView {
@Override
Collection extends FieldMapping> getFields();
diff --git a/src/main/java/net/fabricmc/mappingio/tree/MappingTreeView.java b/src/main/java/net/fabricmc/mappingio/tree/MappingTreeView.java
index 3dacb7b1..b562f739 100644
--- a/src/main/java/net/fabricmc/mappingio/tree/MappingTreeView.java
+++ b/src/main/java/net/fabricmc/mappingio/tree/MappingTreeView.java
@@ -85,6 +85,20 @@ default String getNamespaceName(int id) {
*/
List extends MetadataEntryView> getMetadata(String key);
+ Collection extends PackageMappingView> getPackages();
+ @Nullable
+ PackageMappingView getPackage(String srcName);
+ @Nullable
+ default PackageMappingView getPackage(String name, int namespace) {
+ if (namespace < 0) return getPackage(name);
+
+ for (PackageMappingView pkg : getPackages()) {
+ if (name.equals(pkg.getDstName(namespace))) return pkg;
+ }
+
+ return null;
+ }
+
Collection extends ClassMappingView> getClasses();
@Nullable
ClassMappingView getClass(String srcName);
@@ -138,6 +152,23 @@ default void accept(MappingVisitor visitor) throws IOException {
void accept(MappingVisitor visitor, VisitOrder order) throws IOException;
+ default String mapPackageName(String name, int namespace) {
+ return mapPackageName(name, SRC_NAMESPACE_ID, namespace);
+ }
+
+ default String mapPackageName(String name, int srcNamespace, int dstNamespace) {
+ assert name.indexOf('.') < 0;
+
+ if (srcNamespace == dstNamespace) return name;
+
+ PackageMappingView pkg = getPackage(name, srcNamespace);
+ if (pkg == null) return name;
+
+ String ret = pkg.getName(dstNamespace);
+
+ return ret != null ? ret : name;
+ }
+
default String mapClassName(String name, int namespace) {
return mapClassName(name, SRC_NAMESPACE_ID, namespace);
}
@@ -247,6 +278,8 @@ default String getName(String namespace) {
String getComment();
}
+ interface PackageMappingView extends ElementMappingView { }
+
interface ClassMappingView extends ElementMappingView {
Collection extends FieldMappingView> getFields();
diff --git a/src/main/java/net/fabricmc/mappingio/tree/MemoryMappingTree.java b/src/main/java/net/fabricmc/mappingio/tree/MemoryMappingTree.java
index 67f5c03a..1dca8610 100644
--- a/src/main/java/net/fabricmc/mappingio/tree/MemoryMappingTree.java
+++ b/src/main/java/net/fabricmc/mappingio/tree/MemoryMappingTree.java
@@ -68,13 +68,17 @@ public MemoryMappingTree(MappingTree src) {
addMetadata(entry);
}
+ for (PackageMapping pkg : src.getPackages()) {
+ addPackage(pkg);
+ }
+
for (ClassMapping cls : src.getClasses()) {
addClass(cls);
}
}
/**
- * Whether to index classes by their destination names, in addition to their source names.
+ * Whether to index packages and classes by their destination names, in addition to their source names.
*
* Trades higher memory consumption for faster lookups by destination name.
*/
@@ -83,14 +87,32 @@ public void setIndexByDstNames(boolean indexByDstNames) {
if (indexByDstNames == this.indexByDstNames) return;
if (!indexByDstNames) {
+ packagesByDstNames = null;
classesByDstNames = null;
} else if (dstNamespaces != null) {
+ initPackagesByDstNames();
initClassesByDstNames();
}
this.indexByDstNames = indexByDstNames;
}
+ @SuppressWarnings("unchecked")
+ private void initPackagesByDstNames() {
+ packagesByDstNames = new Map[dstNamespaces.size()];
+
+ for (int i = 0; i < packagesByDstNames.length; i++) {
+ packagesByDstNames[i] = new HashMap(packagesBySrcName.size());
+ }
+
+ for (PackageEntry pkg : packagesBySrcName.values()) {
+ for (int i = 0; i < pkg.dstNames.length; i++) {
+ String dstName = pkg.dstNames[i];
+ if (dstName != null) packagesByDstNames[i].put(dstName, pkg);
+ }
+ }
+ }
+
@SuppressWarnings("unchecked")
private void initClassesByDstNames() {
classesByDstNames = new Map[dstNamespaces.size()];
@@ -159,7 +181,7 @@ public List getDstNamespaces() {
public List setDstNamespaces(List namespaces) {
assertNotInVisitPass();
- if (!classesBySrcName.isEmpty()) { // classes present, update existing dstNames
+ if (!packagesBySrcName.isEmpty() || !classesBySrcName.isEmpty()) { // packages or classes present, update existing dstNames
int newSize = namespaces.size();
int[] nameMap = new int[newSize];
Set processedNamespaces = new HashSet<>(newSize);
@@ -211,6 +233,7 @@ public List setDstNamespaces(List namespaces) {
dstNamespaces = namespaces;
if (indexByDstNames) {
+ initPackagesByDstNames();
initClassesByDstNames();
}
@@ -218,6 +241,10 @@ public List setDstNamespaces(List namespaces) {
}
private void resizeDstNames(int newSize) {
+ for (PackageEntry pkg : packagesBySrcName.values()) {
+ pkg.resizeDstNames(newSize);
+ }
+
for (ClassEntry cls : classesBySrcName.values()) {
cls.resizeDstNames(newSize);
@@ -240,6 +267,10 @@ private void resizeDstNames(int newSize) {
}
private void updateDstNames(int[] nameMap) {
+ for (PackageEntry pkg : packagesBySrcName.values()) {
+ pkg.updateDstNames(nameMap);
+ }
+
for (ClassEntry cls : classesBySrcName.values()) {
cls.updateDstNames(nameMap);
@@ -261,6 +292,13 @@ private void updateDstNames(int[] nameMap) {
}
}
+ private int getSrcNsEquivalent(ElementMapping mapping) {
+ int ret = mapping.getTree().getNamespaceId(srcNamespace);
+ if (ret == NULL_NAMESPACE_ID) throw new UnsupportedOperationException("can't find source namespace in referenced mapping tree");
+
+ return ret;
+ }
+
@Override
public List extends MetadataEntry> getMetadata() {
return metadata;
@@ -283,6 +321,64 @@ public boolean removeMetadata(String key) {
return metadata.removeIf(entry -> entry.getKey().equals(key));
}
+ @Override
+ public Collection extends PackageMapping> getPackages() {
+ return packagesView;
+ }
+
+ @Override
+ @Nullable
+ public PackageMapping getPackage(String srcName) {
+ return packagesBySrcName.get(srcName);
+ }
+
+ @Override
+ @Nullable
+ public PackageMapping getPackage(String name, int namespace) {
+ if (namespace < 0 || !indexByDstNames) {
+ return VisitableMappingTree.super.getPackage(name, namespace);
+ } else {
+ return packagesByDstNames[namespace].get(name);
+ }
+ }
+
+ @Override
+ public PackageMapping addPackage(PackageMapping pkg) {
+ assertNotInVisitPass();
+ PackageEntry entry = pkg instanceof PackageEntry && pkg.getTree() == this ? (PackageEntry) pkg : new PackageEntry(this, pkg, getSrcNsEquivalent(pkg));
+ PackageEntry ret = packagesBySrcName.putIfAbsent(pkg.getSrcName(), entry);
+
+ if (ret != null) {
+ ret.copyFrom(entry, true);
+ entry = ret;
+ }
+
+ if (indexByDstNames) {
+ for (int i = 0; i < entry.dstNames.length; i++) {
+ String dstName = entry.dstNames[i];
+ if (dstName != null) packagesByDstNames[i].put(dstName, entry);
+ }
+ }
+
+ return entry;
+ }
+
+ @Override
+ @Nullable
+ public PackageMapping removePackage(String srcName) {
+ assertNotInVisitPass();
+ PackageEntry ret = packagesBySrcName.remove(srcName);
+
+ if (ret != null && indexByDstNames) {
+ for (int i = 0; i < ret.dstNames.length; i++) {
+ String dstName = ret.dstNames[i];
+ if (dstName != null) packagesByDstNames[i].remove(dstName);
+ }
+ }
+
+ return ret;
+ }
+
@Override
public Collection extends ClassMapping> getClasses() {
return classesView;
@@ -325,13 +421,6 @@ public ClassMapping addClass(ClassMapping cls) {
return entry;
}
- private int getSrcNsEquivalent(ElementMapping mapping) {
- int ret = mapping.getTree().getNamespaceId(srcNamespace);
- if (ret == NULL_NAMESPACE_ID) throw new UnsupportedOperationException("can't find source namespace in referenced mapping tree");
-
- return ret;
- }
-
@Override
@Nullable
public ClassMapping removeClass(String srcName) {
@@ -381,9 +470,22 @@ public void accept(MappingVisitor visitor, VisitOrder order) throws IOException
Set flags = visitor.getFlags();
boolean supplyFieldDstDescs = flags.contains(MappingFlag.NEEDS_DST_FIELD_DESC);
boolean supplyMethodDstDescs = flags.contains(MappingFlag.NEEDS_DST_METHOD_DESC);
+ boolean classesFirst = order.isClassesFirst();
+
+ if (classesFirst) {
+ for (ClassEntry cls : order.sortClasses(classesBySrcName.values())) {
+ cls.accept(visitor, order, supplyFieldDstDescs, supplyMethodDstDescs);
+ }
+ }
+
+ for (PackageEntry pkg : order.sortPackages(packagesBySrcName.values())) {
+ pkg.accept(visitor, order);
+ }
- for (ClassEntry cls : order.sortClasses(classesBySrcName.values())) {
- cls.accept(visitor, order, supplyFieldDstDescs, supplyMethodDstDescs);
+ if (!classesFirst) {
+ for (ClassEntry cls : order.sortClasses(classesBySrcName.values())) {
+ cls.accept(visitor, order, supplyFieldDstDescs, supplyMethodDstDescs);
+ }
}
}
} while (!visitor.visitEnd());
@@ -397,6 +499,7 @@ public void reset() {
currentEntry = null;
currentClass = null;
currentMethod = null;
+ pendingPackages = null;
pendingClasses = null;
pendingMembers = null;
}
@@ -448,8 +551,13 @@ public void visitNamespaces(String srcNamespace, List dstNamespaces) {
resizeDstNames(newSize);
if (indexByDstNames) {
+ packagesByDstNames = Arrays.copyOf(packagesByDstNames, newSize);
classesByDstNames = Arrays.copyOf(classesByDstNames, newSize);
+ for (int i = newSize - newDstNamespaces; i < packagesByDstNames.length; i++) {
+ packagesByDstNames[i] = new HashMap(packagesBySrcName.size());
+ }
+
for (int i = newSize - newDstNamespaces; i < classesByDstNames.length; i++) {
classesByDstNames[i] = new HashMap<>(classesBySrcName.size());
}
@@ -469,6 +577,7 @@ public void visitNamespaces(String srcNamespace, List dstNamespaces) {
}
if (indexByDstNames) {
+ initPackagesByDstNames();
initClassesByDstNames();
}
}
@@ -480,6 +589,26 @@ public void visitMetadata(String key, @Nullable String value) {
metadata.add(entry);
}
+ @Override
+ public boolean visitPackage(String srcName) {
+ currentClass = null;
+
+ PackageEntry pkg = (PackageEntry) getPackage(srcName, srcNsMap);
+
+ if (pkg == null) {
+ if (srcNsMap >= 0) { // tree-side srcName unknown
+ pkg = queuePendingPackage(srcName);
+ } else {
+ pkg = new PackageEntry(this, srcName);
+ packagesBySrcName.put(srcName, pkg);
+ }
+ }
+
+ currentEntry = pkg;
+
+ return true;
+ }
+
@Override
public boolean visitClass(String srcName) {
currentMethod = null;
@@ -556,6 +685,21 @@ public boolean visitMethod(String srcName, @Nullable String srcDesc) {
return true;
}
+ private PackageEntry queuePendingPackage(String name) {
+ if (pendingPackages == null) pendingPackages = new HashMap<>();
+ PackageEntry pkg = pendingPackages.get(name);
+
+ if (pkg == null) {
+ pkg = new PackageEntry(this, null);
+ pendingPackages.put(name, pkg);
+ }
+
+ assert srcNsMap >= 0;
+ pkg.setDstNameInternal(name, srcNsMap);
+
+ return pkg;
+ }
+
private ClassEntry queuePendingClass(String name) {
if (pendingClasses == null) pendingClasses = new HashMap<>();
ClassEntry cls = pendingClasses.get(name);
@@ -592,6 +736,21 @@ private MemberEntry> queuePendingMember(String name, @Nullable String desc, bo
return member;
}
+ private void addPendingPackage(PackageEntry pkg) {
+ if (pkg.isSrcNameMissing()) {
+ return;
+ }
+
+ String srcName = pkg.getSrcName();
+ PackageEntry existing = packagesBySrcName.get(srcName);
+
+ if (existing == null) {
+ packagesBySrcName.put(srcName, pkg);
+ } else { // copy remaining data
+ existing.copyFrom(pkg, true);
+ }
+ }
+
private void addPendingClass(ClassEntry cls) {
if (cls.isSrcNameMissing()) {
return;
@@ -698,6 +857,15 @@ public boolean visitMethodVar(int lvtRowIndex, int lvIndex, int startOpIdx, int
@Override
public boolean visitEnd() {
// TODO: Don't discard pending elements which are still missing their tree-side src names, upcoming visit passes might provide them
+
+ if (pendingPackages != null) {
+ for (PackageEntry pkg : pendingPackages.values()) {
+ addPendingPackage(pkg);
+ }
+
+ pendingPackages = null;
+ }
+
if (pendingClasses != null) {
for (ClassEntry cls : pendingClasses.values()) {
addPendingClass(cls);
@@ -782,8 +950,8 @@ public void visitDstName(MappedElementKind targetKind, int namespace, String nam
if (name.equals(currentEntry.getSrcNameUnchecked())) return;
switch (currentEntry.getKind()) {
+ case PACKAGE:
case CLASS:
- assert currentClass == currentEntry;
case FIELD:
case METHOD:
if (currentEntry.isSrcNameMissing()) {
@@ -864,6 +1032,11 @@ protected Entry(MemoryMappingTree tree, ElementMapping src, int srcNsEquivalent)
public abstract MappedElementKind getKind();
+ @Override
+ public MappingTree getTree() {
+ return tree;
+ }
+
final boolean isSrcNameMissing() {
return srcName == null;
}
@@ -983,6 +1156,9 @@ protected void copyFrom(T o, boolean replace) {
}
}
+ @Override
+ public abstract String toString();
+
private final boolean missingSrcNameAllowed = getKind().level > MappedElementKind.METHOD.level; // args and vars
protected final MemoryMappingTree tree;
private String srcName;
@@ -990,6 +1166,52 @@ protected void copyFrom(T o, boolean replace) {
protected String comment;
}
+ static final class PackageEntry extends Entry implements PackageMapping {
+ PackageEntry(MemoryMappingTree tree, String srcName) {
+ super(tree, srcName);
+ }
+
+ PackageEntry(MemoryMappingTree tree, PackageMapping src, int srcNsEquivalent) {
+ super(tree, src, srcNsEquivalent);
+ }
+
+ @Override
+ public MappedElementKind getKind() {
+ return MappedElementKind.PACKAGE;
+ }
+
+ @Override
+ void setDstNameInternal(String name, int namespace) {
+ if (tree.indexByDstNames) {
+ String oldName = dstNames[namespace];
+
+ if (!Objects.equals(name, oldName)) {
+ Map map = tree.packagesByDstNames[namespace];
+ if (oldName != null) map.remove(oldName);
+
+ if (name != null) {
+ map.put(name, this);
+ } else {
+ map.remove(oldName);
+ }
+ }
+ }
+
+ super.setDstNameInternal(name, namespace);
+ }
+
+ void accept(MappingVisitor visitor, VisitOrder order) throws IOException {
+ if (visitor.visitPackage(getSrcName())) {
+ acceptElement(visitor, null);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return getSrcNameUnchecked();
+ }
+ }
+
static final class ClassEntry extends Entry implements ClassMapping {
ClassEntry(MemoryMappingTree tree, String srcName) {
super(tree, srcName);
@@ -1012,11 +1234,6 @@ public MappedElementKind getKind() {
return MappedElementKind.CLASS;
}
- @Override
- public MemoryMappingTree getTree() {
- return tree;
- }
-
@Override
void setDstNameInternal(String name, int namespace) {
if (tree.indexByDstNames) {
@@ -1336,11 +1553,6 @@ protected MemberEntry(ClassEntry owner, MemberMapping src, int srcNsEquivalent)
this.key = new MemberKey(getSrcName(), srcDesc);
}
- @Override
- public MappingTree getTree() {
- return owner.tree;
- }
-
@Override
public final ClassEntry getOwner() {
return owner;
@@ -1776,11 +1988,6 @@ static final class MethodArgEntry extends Entry implements Metho
this.lvIndex = src.getLvIndex();
}
- @Override
- public MappingTree getTree() {
- return method.owner.tree;
- }
-
@Override
public MappedElementKind getKind() {
return MappedElementKind.METHOD_ARG;
@@ -1875,11 +2082,6 @@ static final class MethodVarEntry extends Entry implements Metho
this.endOpIdx = src.getEndOpIdx();
}
- @Override
- public MappingTree getTree() {
- return method.owner.tree;
- }
-
@Override
public MappedElementKind getKind() {
return MappedElementKind.METHOD_VAR;
@@ -2103,8 +2305,11 @@ public String toString() {
private String srcNamespace;
private List dstNamespaces = Collections.emptyList();
private final List metadata = new ArrayList<>();
+ private final Map packagesBySrcName = new LinkedHashMap<>();
private final Map classesBySrcName = new LinkedHashMap<>();
+ private final Collection packagesView = Collections.unmodifiableCollection(packagesBySrcName.values());
private final Collection classesView = Collections.unmodifiableCollection(classesBySrcName.values());
+ private Map[] packagesByDstNames;
private Map[] classesByDstNames;
private HierarchyInfoProvider> hierarchyInfo;
@@ -2115,6 +2320,8 @@ public String toString() {
private Entry> currentEntry;
private ClassEntry currentClass;
private MethodEntry currentMethod;
+ /** originalSrcName -> pkgEntry. */
+ private Map pendingPackages;
/** originalSrcName -> clsEntry. */
private Map pendingClasses;
private Map> pendingMembers;
diff --git a/src/main/java/net/fabricmc/mappingio/tree/VisitOrder.java b/src/main/java/net/fabricmc/mappingio/tree/VisitOrder.java
index fdda2705..389172b8 100644
--- a/src/main/java/net/fabricmc/mappingio/tree/VisitOrder.java
+++ b/src/main/java/net/fabricmc/mappingio/tree/VisitOrder.java
@@ -31,6 +31,7 @@
import net.fabricmc.mappingio.tree.MappingTreeView.MethodArgMappingView;
import net.fabricmc.mappingio.tree.MappingTreeView.MethodMappingView;
import net.fabricmc.mappingio.tree.MappingTreeView.MethodVarMappingView;
+import net.fabricmc.mappingio.tree.MappingTreeView.PackageMappingView;
/**
* Visitation order configuration for {@link MappingTreeView#accept(net.fabricmc.mappingio.MappingVisitor, VisitOrder)}.
@@ -55,6 +56,7 @@ public static VisitOrder createByInputOrder() {
*/
public static VisitOrder createByName() {
return new VisitOrder()
+ .packagesBySrcName()
.classesBySrcName()
.fieldsBySrcNameDesc()
.methodsBySrcNameDesc()
@@ -64,6 +66,20 @@ public static VisitOrder createByName() {
// visit order configuration
+ public VisitOrder packageComparator(Comparator comparator) {
+ this.packageComparator = comparator;
+
+ return this;
+ }
+
+ public VisitOrder packagesBySrcName() {
+ return packageComparator(compareBySrcName());
+ }
+
+ public VisitOrder packagesBySrcNameShortFirst() {
+ return packageComparator(compareBySrcNameShortFirst());
+ }
+
public VisitOrder classComparator(Comparator comparator) {
this.classComparator = comparator;
@@ -131,6 +147,20 @@ public VisitOrder methodVarsByLvIndex() {
.thenComparingInt(MethodVarMappingView::getEndOpIdx));
}
+ public VisitOrder classesFirst(boolean classesFirst) {
+ this.classesFirst = classesFirst;
+
+ return this;
+ }
+
+ public VisitOrder packagesFirst() {
+ return classesFirst(false);
+ }
+
+ public VisitOrder classesFirst() {
+ return classesFirst(true);
+ }
+
public VisitOrder methodsFirst(boolean methodsFirst) {
this.methodsFirst = methodsFirst;
@@ -277,6 +307,10 @@ public static int compareNullLast(@Nullable String a, @Nullable String b) {
// application
+ public Collection sortPackages(Collection packages) {
+ return sort(packages, packageComparator);
+ }
+
public Collection sortClasses(Collection classes) {
return sort(classes, classComparator);
}
@@ -306,6 +340,10 @@ private static Collection sort(Collection inputs, Comparator super T
return ret;
}
+ public boolean isClassesFirst() {
+ return classesFirst;
+ }
+
public boolean isMethodsFirst() {
return methodsFirst;
}
@@ -315,11 +353,13 @@ public boolean isMethodVarsFirst() {
}
private static final AlphanumericComparator ALPHANUM = new AlphanumericComparator(Locale.ROOT);
+ private Comparator packageComparator;
private Comparator classComparator;
private Comparator fieldComparator;
private Comparator methodComparator;
private Comparator methodArgComparator;
private Comparator methodVarComparator;
+ private boolean classesFirst;
private boolean methodsFirst;
private boolean methodVarsFirst;
}
diff --git a/src/test/java/net/fabricmc/mappingio/test/NameGen.java b/src/test/java/net/fabricmc/mappingio/test/NameGen.java
index bcfa6ac4..d2727c98 100644
--- a/src/test/java/net/fabricmc/mappingio/test/NameGen.java
+++ b/src/test/java/net/fabricmc/mappingio/test/NameGen.java
@@ -26,17 +26,29 @@
import net.fabricmc.mappingio.MappingVisitor;
class NameGen {
+ boolean visitPackage(MappingVisitor target, int nestLevel, int... dstNs) throws IOException {
+ if (!target.visitPackage(nestLevel <= 0 ? srcOutermostPkgOrCls(pkgKind) : srcInnerPkgOrCls(pkgKind, nestLevel))) {
+ return false;
+ }
+
+ for (int ns : dstNs) {
+ target.visitDstName(pkgKind, ns, nestLevel <= 0 ? dstOutermostPkgOrCls(pkgKind, ns) : dstInnerPkgOrCls(pkgKind, ns));
+ }
+
+ return target.visitElementContent(pkgKind);
+ }
+
boolean visitClass(MappingVisitor target, int... dstNs) throws IOException {
return visitInnerClass(target, 0, dstNs);
}
boolean visitInnerClass(MappingVisitor target, int nestLevel, int... dstNs) throws IOException {
- if (!target.visitClass(nestLevel <= 0 ? srcOutermostClass() : srcInnerClasses(nestLevel))) {
+ if (!target.visitClass(nestLevel <= 0 ? srcOutermostPkgOrCls(clsKind) : srcInnerPkgOrCls(clsKind, nestLevel))) {
return false;
}
for (int ns : dstNs) {
- target.visitDstName(clsKind, ns, nestLevel <= 0 ? dstOutermostClass(ns) : dstInnerClasses(ns));
+ target.visitDstName(clsKind, ns, nestLevel <= 0 ? dstOutermostPkgOrCls(clsKind, ns) : dstInnerPkgOrCls(clsKind, ns));
}
return target.visitElementContent(clsKind);
@@ -109,39 +121,45 @@ private String src(MappedElementKind kind) {
nsNum = 0;
lastKind = kind;
- if (kind == clsKind) {
- classHasDst = false;
+ if (kind.level == 0) {
+ clsOrPkgHasDst = false;
}
return getPrefix(kind) + "_" + getCounter(kind).incrementAndGet();
}
- private String srcOutermostClass() {
- innerClassNestLevel = 0;
- String ret = src(clsKind);
+ private String srcOutermostPkgOrCls(MappedElementKind kind) {
+ assert kind.level == 0;
+
+ innerPkgOrClsNestLevel = 0;
+ String ret = src(kind);
+ int counter = getCounter(kind).get();
- if (clsNum.get() % 2 == 0) {
- ret = "package_" + clsNum.get() + "/" + ret;
+ if (kind == clsKind && counter % 2 == 0) {
+ ret = "package_" + counter + "/" + ret;
}
return ret;
}
- private String srcInnerClasses(/* >=1 */ int nestLevel) {
- if (innerClassNestLevel == 0) {
- clsNum.decrementAndGet(); // we need the previously generated outer class
+ private String srcInnerPkgOrCls(MappedElementKind kind, /* >=1 */ int nestLevel) {
+ assert kind.level == 0;
+
+ if (innerPkgOrClsNestLevel == 0) {
+ getCounter(kind).decrementAndGet(); // we need the previously generated outer package/class
}
- boolean hasDst = classHasDst;
- StringBuilder sb = new StringBuilder(srcOutermostClass());
+ boolean hasDst = clsOrPkgHasDst;
+ char separator = kind == clsKind ? '$' : '/';
+ StringBuilder sb = new StringBuilder(srcOutermostPkgOrCls(kind));
for (int i = 0; i < nestLevel; i++) {
- sb.append('$');
- sb.append(src(clsKind));
+ sb.append(separator);
+ sb.append(src(kind));
}
- classHasDst = hasDst;
- innerClassNestLevel = nestLevel;
+ clsOrPkgHasDst = hasDst;
+ innerPkgOrClsNestLevel = nestLevel;
return sb.toString();
}
@@ -154,51 +172,59 @@ private String dst(MappedElementKind kind, int ns) {
nsNum = ns + 1;
}
- if (kind == clsKind) {
- classHasDst = true;
+ if (kind.level == 0) {
+ clsOrPkgHasDst = true;
}
return getPrefix(kind) + getCounter(kind).get() + "Ns" + ns + "Rename";
}
- private String dstOutermostClass(int ns) {
- String ret = dst(clsKind, ns);
+ private String dstOutermostPkgOrCls(MappedElementKind kind, int ns) {
+ assert kind.level == 0;
+
+ String ret = dst(kind, ns);
+ AtomicInteger counter = getCounter(kind);
- if (clsNum.get() % 3 == 0) {
- int num = clsNum.get() % 6 == 0 && innerClassNestLevel == 0
- ? clsNum.get() + 1
- : clsNum.get();
- ret = "package_" + num + "/" + ret;
+ if (counter.get() % 3 == 0) {
+ int num = counter.get() % 6 == 0
+ ? counter.get() + 1
+ : counter.get();
+ String pkgName = kind == pkgKind ? "filler_" : "package_";
+ ret = pkgName + num + "/" + ret;
}
return ret;
}
- private String dstInnerClasses(int ns) {
- boolean hasDst = classHasDst;
- int nestLevel = innerClassNestLevel;
- StringBuilder sb = new StringBuilder(dst(clsKind, ns));
+ private String dstInnerPkgOrCls(MappedElementKind kind, int ns) {
+ assert kind.level == 0;
+
+ boolean hasDst = clsOrPkgHasDst;
+ int nestLevel = innerPkgOrClsNestLevel;
+ char separator = kind == clsKind ? '$' : '/';
+ AtomicInteger counter = getCounter(kind);
+ StringBuilder sb = new StringBuilder(dst(kind, ns));
for (int i = nestLevel - 1; i >= 0; i--) {
- sb.insert(0, '$');
- clsNum.decrementAndGet();
+ sb.insert(0, separator);
+ counter.decrementAndGet();
if (!hasDst) {
- clsNum.decrementAndGet();
+ counter.decrementAndGet();
}
sb.insert(0, hasDst
? i == 0
- ? dstOutermostClass(ns)
- : dst(clsKind, ns)
+ ? dstOutermostPkgOrCls(kind, ns)
+ : dst(kind, ns)
: i == 0
- ? srcOutermostClass()
- : src(clsKind));
+ ? srcOutermostPkgOrCls(kind)
+ : src(kind));
}
- classHasDst = hasDst;
- innerClassNestLevel = nestLevel;
- clsNum.addAndGet(nestLevel);
+ clsOrPkgHasDst = hasDst;
+ innerPkgOrClsNestLevel = nestLevel;
+ counter.addAndGet(nestLevel);
return sb.toString();
}
@@ -215,6 +241,8 @@ private String desc(MappedElementKind kind) {
private AtomicInteger getCounter(MappedElementKind kind) {
switch (kind) {
+ case PACKAGE:
+ return pkgNum;
case CLASS:
return clsNum;
case FIELD:
@@ -232,6 +260,8 @@ private AtomicInteger getCounter(MappedElementKind kind) {
private String getPrefix(MappedElementKind kind) {
switch (kind) {
+ case PACKAGE:
+ return pkgPrefix;
case CLASS:
return clsPrefix;
case FIELD:
@@ -247,6 +277,7 @@ private String getPrefix(MappedElementKind kind) {
}
}
+ private static final String pkgPrefix = "package";
private static final String clsPrefix = "class";
private static final String fldPrefix = "field";
private static final String mthPrefix = "method";
@@ -255,11 +286,13 @@ private String getPrefix(MappedElementKind kind) {
private static final String comment = "This is a comment";
private static final List fldDescs = Collections.unmodifiableList(Arrays.asList("I", "Lcls;", "Lpkg/cls;", "[I", null));
private static final List mthDescs = Collections.unmodifiableList(Arrays.asList("()I", "(I)V", "(Lcls;)Lcls;", "(ILcls;)Lpkg/cls;", "(Lcls;[I)[[B", null));
+ private static final MappedElementKind pkgKind = MappedElementKind.PACKAGE;
private static final MappedElementKind clsKind = MappedElementKind.CLASS;
private static final MappedElementKind fldKind = MappedElementKind.FIELD;
private static final MappedElementKind mthKind = MappedElementKind.METHOD;
private static final MappedElementKind argKind = MappedElementKind.METHOD_ARG;
private static final MappedElementKind varKind = MappedElementKind.METHOD_VAR;
+ private final AtomicInteger pkgNum = new AtomicInteger();
private final AtomicInteger clsNum = new AtomicInteger();
private final AtomicInteger fldNum = new AtomicInteger();
private final AtomicInteger mthNum = new AtomicInteger();
@@ -268,6 +301,6 @@ private String getPrefix(MappedElementKind kind) {
private int nsNum;
private int counter;
private MappedElementKind lastKind;
- private boolean classHasDst;
- private int innerClassNestLevel;
+ private boolean clsOrPkgHasDst;
+ private int innerPkgOrClsNestLevel;
}
diff --git a/src/test/java/net/fabricmc/mappingio/test/TestMappings.java b/src/test/java/net/fabricmc/mappingio/test/TestMappings.java
index 6060e9d3..c7303d9a 100644
--- a/src/test/java/net/fabricmc/mappingio/test/TestMappings.java
+++ b/src/test/java/net/fabricmc/mappingio/test/TestMappings.java
@@ -64,6 +64,14 @@ public static T generateValid(T target) throws IOExce
int[] dstNs = new int[] { 0, 1 };
NameGen nameGen = new NameGen();
+ if (nameGen.visitPackage(delegate, 0, dstNs)) {
+ nameGen.visitComment(delegate);
+ }
+
+ if (nameGen.visitPackage(delegate, 1, dstNs)) {
+ nameGen.visitComment(delegate);
+ }
+
if (nameGen.visitClass(delegate, dstNs)) {
nameGen.visitField(delegate, dstNs);
@@ -97,6 +105,13 @@ public void visitMetadata(String key, @Nullable String value) throws IOException
super.visitMetadata(key, key.equals("name") ? "repeated-elements" : value);
}
+ @Override
+ public boolean visitPackage(String srcName) throws IOException {
+ replayQueue.clear();
+ replayQueue.add(Unchecked.runnable(() -> super.visitPackage(srcName)));
+ return super.visitPackage(srcName);
+ }
+
@Override
public boolean visitClass(String srcName) throws IOException {
replayQueue.clear();
@@ -188,6 +203,20 @@ public static T generateHoles(T target) throws IOExce
if (delegate.visitContent()) {
NameGen nameGen = new NameGen();
+ // Packages
+ nameGen.visitPackage(delegate, 0, 0);
+ nameGen.visitPackage(delegate, 0, 0);
+ nameGen.visitPackage(delegate, 0, 0);
+
+ nameGen.visitPackage(delegate, 0, 1);
+ nameGen.visitPackage(delegate, 0, 1);
+ nameGen.visitPackage(delegate, 0, 1);
+
+ nameGen.visitPackage(delegate, 1, 0);
+ nameGen.visitPackage(delegate, 1, 0);
+ nameGen.visitPackage(delegate, 1, 0);
+ nameGen.visitPackage(delegate, 1, 0);
+
// (Inner) Classes
for (int nestLevel = 0; nestLevel <= 2; nestLevel++) {
nameGen.visitClass(delegate);
@@ -464,5 +493,10 @@ public boolean supportsGeneration() {
}
public abstract T generate(T target) throws IOException;
+
+ @Override
+ public String toString() {
+ return TestUtil.getResource("/").relativize(path).toString();
+ }
}
}
diff --git a/src/test/java/net/fabricmc/mappingio/test/tests/reading/DetectionTest.java b/src/test/java/net/fabricmc/mappingio/test/tests/reading/DetectionTest.java
index 000cb2cb..7033937c 100644
--- a/src/test/java/net/fabricmc/mappingio/test/tests/reading/DetectionTest.java
+++ b/src/test/java/net/fabricmc/mappingio/test/tests/reading/DetectionTest.java
@@ -16,6 +16,7 @@
package net.fabricmc.mappingio.test.tests.reading;
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
@@ -43,7 +44,7 @@ public void run() throws Exception {
if (format == MappingFormat.RECAF_SIMPLE_FILE) {
assertThrows(AssertionFailedError.class, () -> check(dir, format));
} else {
- check(dir, format);
+ assertDoesNotThrow(() -> check(dir, format), "Failed for " + dir + " with " + format);
}
}
}
diff --git a/src/test/java/net/fabricmc/mappingio/test/tests/reading/ValidContentReadTest.java b/src/test/java/net/fabricmc/mappingio/test/tests/reading/ValidContentReadTest.java
index 10eac065..93965d75 100644
--- a/src/test/java/net/fabricmc/mappingio/test/tests/reading/ValidContentReadTest.java
+++ b/src/test/java/net/fabricmc/mappingio/test/tests/reading/ValidContentReadTest.java
@@ -16,6 +16,8 @@
package net.fabricmc.mappingio.test.tests.reading;
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+
import java.nio.file.Files;
import org.jetbrains.annotations.Nullable;
@@ -39,7 +41,7 @@ public class ValidContentReadTest {
public void run() throws Exception {
for (MappingDir dir : TestMappings.values()) {
for (MappingFormat format : MappingFormat.values()) {
- check(dir, format);
+ assertDoesNotThrow(() -> check(dir, format), "Failed for " + dir + " with " + format);
}
}
}
diff --git a/src/test/java/net/fabricmc/mappingio/test/tests/visiting/VisitEndTest.java b/src/test/java/net/fabricmc/mappingio/test/tests/visiting/VisitEndTest.java
index 253af226..05e64cc6 100644
--- a/src/test/java/net/fabricmc/mappingio/test/tests/visiting/VisitEndTest.java
+++ b/src/test/java/net/fabricmc/mappingio/test/tests/visiting/VisitEndTest.java
@@ -16,6 +16,7 @@
package net.fabricmc.mappingio.test.tests.visiting;
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -46,7 +47,7 @@ public class VisitEndTest {
public void run() throws Exception {
for (MappingDir dir : TestMappings.values()) {
for (MappingFormat format : MappingFormat.values()) {
- check(dir, format);
+ assertDoesNotThrow(() -> check(dir, format), "Failed for " + dir + " with " + format);
}
}
}
@@ -129,6 +130,13 @@ public boolean visitContent() throws IOException {
return true;
}
+ @Override
+ public boolean visitPackage(String srcName) throws IOException {
+ check();
+ tree.visitPackage(srcName);
+ return true;
+ }
+
@Override
public boolean visitClass(String srcName) throws IOException {
check();
diff --git a/src/test/java/net/fabricmc/mappingio/test/tests/writing/WriteTest.java b/src/test/java/net/fabricmc/mappingio/test/tests/writing/WriteTest.java
index 6fd5a540..1f03baef 100644
--- a/src/test/java/net/fabricmc/mappingio/test/tests/writing/WriteTest.java
+++ b/src/test/java/net/fabricmc/mappingio/test/tests/writing/WriteTest.java
@@ -16,6 +16,8 @@
package net.fabricmc.mappingio.test.tests.writing;
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+
import java.io.IOException;
import java.nio.file.Path;
@@ -48,7 +50,7 @@ public class WriteTest {
public void run() throws Exception {
for (MappingDir dir : TestMappings.values()) {
for (MappingFormat format : MappingFormat.values()) {
- check(dir, format);
+ assertDoesNotThrow(() -> check(dir, format), "Failed for " + dir + " with " + format);
}
}
}
diff --git a/src/test/java/net/fabricmc/mappingio/test/visitors/NopMappingVisitor.java b/src/test/java/net/fabricmc/mappingio/test/visitors/NopMappingVisitor.java
index e2206f56..60e72c43 100644
--- a/src/test/java/net/fabricmc/mappingio/test/visitors/NopMappingVisitor.java
+++ b/src/test/java/net/fabricmc/mappingio/test/visitors/NopMappingVisitor.java
@@ -43,6 +43,11 @@ public boolean visitContent() throws IOException {
return visitSubVisitors;
}
+ @Override
+ public boolean visitPackage(String srcName) throws IOException {
+ return visitSubVisitors;
+ }
+
@Override
public boolean visitClass(String srcName) throws IOException {
return visitSubVisitors;
diff --git a/src/test/java/net/fabricmc/mappingio/test/visitors/SubsetAssertingVisitor.java b/src/test/java/net/fabricmc/mappingio/test/visitors/SubsetAssertingVisitor.java
index e256e6fc..c76a15df 100644
--- a/src/test/java/net/fabricmc/mappingio/test/visitors/SubsetAssertingVisitor.java
+++ b/src/test/java/net/fabricmc/mappingio/test/visitors/SubsetAssertingVisitor.java
@@ -41,6 +41,7 @@
import net.fabricmc.mappingio.tree.MappingTreeView.MethodArgMappingView;
import net.fabricmc.mappingio.tree.MappingTreeView.MethodMappingView;
import net.fabricmc.mappingio.tree.MappingTreeView.MethodVarMappingView;
+import net.fabricmc.mappingio.tree.MappingTreeView.PackageMappingView;
/**
* A visitor which asserts that the visited mappings are a subset of a superset tree.
@@ -53,6 +54,7 @@ public class SubsetAssertingVisitor implements FlatMappingVisitor {
*/
public SubsetAssertingVisitor(MappingTreeView supTree, @Nullable MappingFormat supFormat, @Nullable MappingFormat subFormat) {
this.supTree = supTree;
+ this.supFormat = supFormat;
this.subFormat = subFormat;
this.supDstNsCount = supTree.getMaxNamespaceId();
this.supFeatures = supFormat == null ? FeatureSetInstantiator.withFullSupport() : supFormat.features();
@@ -103,9 +105,89 @@ public void visitNamespaces(String srcNamespace, List dstNamespaces) thr
}
}
+ @Override
+ public boolean visitPackage(String srcName, @Nullable String[] dstNames) throws IOException {
+ if (!supFeatures.supportsPackages()) return false;
+
+ PackageMappingView supPkg = supTree.getPackage(srcName);
+ boolean supHasDstNames = supFeatures.packages().dstNames() != FeaturePresence.ABSENT;
+ boolean subHasDstNames = subFeatures.packages().dstNames() != FeaturePresence.ABSENT;
+ boolean supHasStructureModification = supFeatures.packages().hasStructureModification();
+
+ if (supPkg == null) { // supTree doesn't have this package, ensure the incoming mappings don't have any data for it
+ if (supHasDstNames && subHasDstNames) {
+ String[] subDstNames = supFeatures.hasNamespaces() || dstNames == null ? dstNames : new String[]{dstNames[subNsIfSupNotNamespaced]};
+
+ if (!isEmpty(subDstNames)) {
+ boolean error = true;
+
+ if (!supHasStructureModification) {
+ int srcNameSlashCount = countOccurrences(srcName, '/');
+
+ for (String subDstName : subDstNames) {
+ if (subDstName != null) {
+ if (countOccurrences(subDstName, '/') == srcNameSlashCount) {
+ error = true;
+ break;
+ } else {
+ // The incoming package has been moved, which supFormat doesn't support, that's why it's missing from supTree
+ error = false;
+ }
+ }
+ }
+ }
+
+ if (error) {
+ throw new AssertionError("Incoming package not contained in supTree: " + srcName);
+ }
+ }
+ }
+
+ return true; // ensure there is no element content
+ }
+
+ Map supDstNamesByNsName = new HashMap<>();
+
+ for (int supNs = 0; supNs < supDstNsCount; supNs++) {
+ supDstNamesByNsName.put(supTree.getNamespaceName(supNs), supPkg.getDstName(supNs));
+ }
+
+ if (supHasDstNames && subHasDstNames && dstNames != null) {
+ for (int subNs = 0; subNs < subDstNamespaces.size(); subNs++) {
+ String supDstName = supDstNamesByNsName.get(subDstNamespaces.get(subNs));
+ if (supDstName == null && !supFeatures.hasNamespaces()) continue;
+
+ String subDstName = dstNames[subNs];
+ if (subDstName == null && (supDstName == null || Objects.equals(supDstName, srcName))) continue; // uncompleted dst name
+
+ assertEquals(supDstName != null ? supDstName : srcName, subDstName, "Incoming package destination name differs from supTree");
+ }
+ }
+
+ return true;
+ }
+
+ @Override
+ public void visitPackageComment(String srcName, @Nullable String[] dstNames, String comment) throws IOException {
+ assert supFeatures.supportsPackages();
+
+ if (supFeatures.elementComments() == ElementCommentSupport.NONE) {
+ return;
+ }
+
+ PackageMappingView supPkg = Objects.requireNonNull(supTree.getPackage(srcName), "Incoming package comment's parent package not contained in supTree: " + srcName);
+
+ assertEquals(supPkg.getComment(), comment, "Incoming package comment not contained in supTree: " + srcName);
+ }
+
@Override
public boolean visitClass(String srcName, @Nullable String[] dstNames) throws IOException {
- if (!supFeatures.supportsClasses()) return true; // sub-elements might still be supported
+ if (!supFeatures.supportsClasses()) {
+ return supFeatures.supportsFields()
+ || supFeatures.supportsMethods()
+ || supFeatures.supportsArgs()
+ || supFeatures.supportsVars();
+ }
ClassMappingView supCls = supTree.getClass(srcName);
boolean supHasDstNames = supFeatures.classes().dstNames() != FeaturePresence.ABSENT;
@@ -143,7 +225,7 @@ public boolean visitClass(String srcName, @Nullable String[] dstNames) throws IO
}
}
- return true;
+ return true; // ensure there is no element content
}
Map supDstNamesByNsName = new HashMap<>();
@@ -187,7 +269,9 @@ public boolean visitClass(String srcName, @Nullable String[] dstNames) throws IO
@Override
public void visitClassComment(String srcName, @Nullable String[] dstNames, String comment) throws IOException {
- if (!supFeatures.supportsClasses() || supFeatures.elementComments() == ElementCommentSupport.NONE) return;
+ if (!supFeatures.supportsClasses() || supFeatures.elementComments() == ElementCommentSupport.NONE) {
+ return;
+ }
ClassMappingView supCls = Objects.requireNonNull(supTree.getClass(srcName), "Incoming class comment's parent class not contained in supTree: " + srcName);
@@ -197,7 +281,7 @@ public void visitClassComment(String srcName, @Nullable String[] dstNames, Strin
@Override
public boolean visitField(String srcClsName, String srcName, @Nullable String srcDesc,
@Nullable String[] dstClsNames, @Nullable String[] dstNames, @Nullable String[] dstDescs) throws IOException {
- if (!supFeatures.supportsFields()) return true;
+ if (!supFeatures.supportsFields()) return false;
String subFldId = srcClsName + "#" + srcName + ":" + srcDesc;
ClassMappingView supCls = Objects.requireNonNull(supTree.getClass(srcClsName), "Incoming field's parent class not contained in supTree: " + subFldId);
@@ -222,7 +306,7 @@ public boolean visitField(String srcClsName, String srcName, @Nullable String sr
boolean missingRequiredSrcDesc = supRequiresSrcDescs && srcDesc == null;
assertTrue(noData || missingRequiredSrcDesc, "Incoming field not contained in supTree: " + subFldId);
- return !missingRequiredSrcDesc;
+ return !missingRequiredSrcDesc; // ensure there is no element content
}
String supFldId = srcClsName + "#" + srcName + ":" + supFld.getSrcDesc();
@@ -269,7 +353,11 @@ public boolean visitField(String srcClsName, String srcName, @Nullable String sr
@Override
public void visitFieldComment(String srcClsName, String srcName, @Nullable String srcDesc,
@Nullable String[] dstClsNames, @Nullable String[] dstNames, @Nullable String[] dstDescs, String comment) throws IOException {
- if (!supFeatures.supportsFields() || supFeatures.elementComments() == ElementCommentSupport.NONE) return;
+ assert supFeatures.supportsFields();
+
+ if (supFeatures.elementComments() == ElementCommentSupport.NONE) {
+ return;
+ }
String subFldId = srcClsName + "#" + srcName + ":" + srcDesc;
ClassMappingView supCls = Objects.requireNonNull(supTree.getClass(srcClsName), "Incoming field comment's parent class not contained in supTree: " + subFldId);
@@ -281,7 +369,9 @@ public void visitFieldComment(String srcClsName, String srcName, @Nullable Strin
@Override
public boolean visitMethod(String srcClsName, String srcName, @Nullable String srcDesc,
@Nullable String[] dstClsNames, @Nullable String[] dstNames, @Nullable String[] dstDescs) throws IOException {
- if (!supFeatures.supportsMethods()) return true;
+ if (!supFeatures.supportsMethods()) {
+ return supFeatures.supportsArgs() || supFeatures.supportsVars();
+ }
String subMthId = srcClsName + "#" + srcName + srcDesc;
ClassMappingView supCls = Objects.requireNonNull(supTree.getClass(srcClsName), "Incoming method's parent class not contained in supTree: " + subMthId);
@@ -306,7 +396,7 @@ public boolean visitMethod(String srcClsName, String srcName, @Nullable String s
boolean missingRequiredSrcDesc = supRequiresSrcDescs && srcDesc == null;
assertTrue(noData || missingRequiredSrcDesc, "Incoming method not contained in supTree: " + subMthId);
- return !missingRequiredSrcDesc;
+ return !missingRequiredSrcDesc; // ensure there is no element content
}
String supMthId = srcClsName + "#" + srcName + supMth.getSrcDesc();
@@ -354,7 +444,9 @@ public boolean visitMethod(String srcClsName, String srcName, @Nullable String s
@Override
public void visitMethodComment(String srcClsName, String srcName, @Nullable String srcDesc,
@Nullable String[] dstClsNames, @Nullable String[] dstNames, @Nullable String[] dstDescs, String comment) throws IOException {
- if (!supFeatures.supportsMethods() || supFeatures.elementComments() == ElementCommentSupport.NONE) return;
+ if (!supFeatures.supportsMethods() || supFeatures.elementComments() == ElementCommentSupport.NONE) {
+ return;
+ }
String subMthId = srcClsName + "#" + srcName + srcDesc;
ClassMappingView supCls = Objects.requireNonNull(supTree.getClass(srcClsName), "Incoming method comment's parent class not contained in supTree: " + subMthId);
@@ -366,7 +458,7 @@ public void visitMethodComment(String srcClsName, String srcName, @Nullable Stri
@Override
public boolean visitMethodArg(String srcClsName, String srcMethodName, @Nullable String srcMethodDesc, int argPosition, int lvIndex, @Nullable String srcName,
@Nullable String[] dstClsNames, @Nullable String[] dstMethodNames, @Nullable String[] dstMethodDescs, @Nullable String[] dstNames) throws IOException {
- if (!supFeatures.supportsArgs()) return true;
+ if (!supFeatures.supportsArgs()) return false;
String subArgId = srcClsName + "#" + srcMethodName + srcMethodDesc + ":" + argPosition + ":" + lvIndex + ":" + srcName;
ClassMappingView supCls = Objects.requireNonNull(supTree.getClass(srcClsName), "Incoming arg's parent class not contained in supTree: " + subArgId);
@@ -389,7 +481,7 @@ public boolean visitMethodArg(String srcClsName, String srcMethodName, @Nullable
assertTrue(isEmpty(subDstNames), "Incoming arg not contained in supTree: " + subArgId);
}
- return true;
+ return true; // ensure there is no element content
}
Map supDstNamesByNsName = new HashMap<>();
@@ -428,7 +520,11 @@ public boolean visitMethodArg(String srcClsName, String srcMethodName, @Nullable
@Override
public void visitMethodArgComment(String srcClsName, String srcMethodName, @Nullable String srcMethodDesc, int argPosition, int lvIndex, @Nullable String srcArgName,
@Nullable String[] dstClsNames, @Nullable String[] dstMethodNames, @Nullable String[] dstMethodDescs, @Nullable String[] dstNames, String comment) throws IOException {
- if (!supFeatures.supportsArgs() || supFeatures.elementComments() == ElementCommentSupport.NONE) return;
+ assert supFeatures.supportsArgs();
+
+ if (supFeatures.elementComments() == ElementCommentSupport.NONE) {
+ return;
+ }
String subArgId = srcClsName + "#" + srcMethodName + srcMethodDesc + ":" + argPosition + ":" + lvIndex + ":" + srcArgName;
@@ -442,7 +538,7 @@ public void visitMethodArgComment(String srcClsName, String srcMethodName, @Null
@Override
public boolean visitMethodVar(String srcClsName, String srcMethodName, @Nullable String srcMethodDesc, int lvtRowIndex, int lvIndex, int startOpIdx, int endOpIdx, @Nullable String srcName,
@Nullable String[] dstClsNames, @Nullable String[] dstMethodNames, @Nullable String[] dstMethodDescs, @Nullable String[] dstNames) throws IOException {
- if (!supFeatures.supportsVars()) return true;
+ if (!supFeatures.supportsVars()) return false;
String subVarId = srcClsName + "#" + srcMethodName + srcMethodDesc + ":" + lvtRowIndex + ":" + lvIndex + ":" + startOpIdx + ":" + endOpIdx + ":" + srcName;
ClassMappingView supCls = Objects.requireNonNull(supTree.getClass(srcClsName), "Incoming var's parent class not contained in supTree: " + subVarId);
@@ -469,7 +565,7 @@ public boolean visitMethodVar(String srcClsName, String srcMethodName, @Nullable
assertTrue(isEmpty(subDstNames), "Incoming var not contained in supTree: " + subVarId);
}
- return true;
+ return true; // ensure there is no element content
}
Map supDstNamesByNsName = new HashMap<>();
@@ -516,7 +612,11 @@ public boolean visitMethodVar(String srcClsName, String srcMethodName, @Nullable
@Override
public void visitMethodVarComment(String srcClsName, String srcMethodName, @Nullable String srcMethodDesc, int lvtRowIndex, int lvIndex, int startOpIdx, int endOpIdx, @Nullable String srcVarName,
@Nullable String[] dstClsNames, @Nullable String[] dstMethodNames, @Nullable String[] dstMethodDescs, @Nullable String[] dstNames, String comment) throws IOException {
- if (!supFeatures.supportsVars() || supFeatures.elementComments() == ElementCommentSupport.NONE) return;
+ assert supFeatures.supportsVars();
+
+ if (supFeatures.elementComments() == ElementCommentSupport.NONE) {
+ return;
+ }
String subVarId = srcClsName + "#" + srcMethodName + srcMethodDesc + ":" + lvtRowIndex + ":" + lvIndex + ":" + startOpIdx + ":" + endOpIdx + ":" + srcVarName;
@@ -537,6 +637,16 @@ private boolean isEmpty(String[] arr) {
return true;
}
+ private int countOccurrences(String str, char c) {
+ int count = 0;
+
+ for (int i = 0; i < str.length(); i++) {
+ if (str.charAt(i) == c) count++;
+ }
+
+ return count;
+ }
+
@Nullable
private String getPackage(String name) {
int lastSlash = name.lastIndexOf('/');
@@ -545,6 +655,7 @@ private String getPackage(String name) {
private final MappingTreeView supTree;
private final int supDstNsCount;
+ private final MappingFormat supFormat;
private final MappingFormat subFormat;
private final FeatureSet supFeatures;
private final FeatureSet subFeatures;
diff --git a/src/test/java/net/fabricmc/mappingio/test/visitors/VisitOrderVerifyingVisitor.java b/src/test/java/net/fabricmc/mappingio/test/visitors/VisitOrderVerifyingVisitor.java
index 905d6f9f..7276a92a 100644
--- a/src/test/java/net/fabricmc/mappingio/test/visitors/VisitOrderVerifyingVisitor.java
+++ b/src/test/java/net/fabricmc/mappingio/test/visitors/VisitOrderVerifyingVisitor.java
@@ -48,6 +48,7 @@ private void init() {
visitedNamespaces = false;
visitedMetadata = false;
visitedContent = false;
+ visitedPackage = false;
visitedClass = false;
visitedField = false;
visitedMethod = false;
@@ -103,6 +104,7 @@ public void visitMetadata(String key, @Nullable String value) throws IOException
assertNamespacesVisited();
visitedMetadata = true;
+ visitedPackage = false;
visitedClass = false;
visitedField = false;
visitedMethod = false;
@@ -120,6 +122,29 @@ public boolean visitContent() throws IOException {
return super.visitContent();
}
+ @Override
+ public boolean visitPackage(String srcName) throws IOException {
+ MappedElementKind elementKind = MappedElementKind.PACKAGE;
+ SrcInfo srcInfo = new SrcInfo().srcName(srcName);
+
+ assertContentVisited();
+ assertLastElementContentVisited();
+ resetLastSrcInfoDownTo(elementKind.level);
+ assertNewSrcInfo(elementKind, srcInfo);
+
+ visitedPackage = true;
+ visitedClass = false;
+ visitedField = false;
+ visitedMethod = false;
+ visitedMethodArg = false;
+ visitedMethodVar = false;
+ lastVisitedElement = elementKind;
+ lastSrcInfo.put(elementKind, srcInfo);
+ resetVisitedElementContentDownTo(elementKind.level);
+
+ return visitedLastElement = super.visitPackage(srcName);
+ }
+
@Override
public boolean visitClass(String srcName) throws IOException {
MappedElementKind elementKind = MappedElementKind.CLASS;
@@ -130,6 +155,7 @@ public boolean visitClass(String srcName) throws IOException {
resetLastSrcInfoDownTo(elementKind.level);
assertNewSrcInfo(elementKind, srcInfo);
+ visitedPackage = false;
visitedClass = true;
visitedField = false;
visitedMethod = false;
@@ -450,6 +476,7 @@ private void assertNewSrcInfo(MappedElementKind kind, SrcInfo srcInfo) {
private boolean visitedNamespaces;
private boolean visitedMetadata;
private boolean visitedContent;
+ private boolean visitedPackage;
private boolean visitedClass;
private boolean visitedField;
private boolean visitedMethod;
diff --git a/src/test/resources/reading/holes/csrg.csrg b/src/test/resources/reading/holes/csrg.csrg
index 0568f73a..e7815365 100644
--- a/src/test/resources/reading/holes/csrg.csrg
+++ b/src/test/resources/reading/holes/csrg.csrg
@@ -1,3 +1,10 @@
+package_1/ package1Ns0Rename/
+package_2/ package2Ns0Rename/
+package_3/ filler_3/package3Ns0Rename/
+package_6/package_7/ filler_7/package6Ns0Rename/package7Ns0Rename/
+package_8/package_9/ package8Ns0Rename/package9Ns0Rename/
+package_10/package_11/ package10Ns0Rename/package11Ns0Rename/
+package_12/package_13/ filler_13/package12Ns0Rename/package13Ns0Rename/
class_3 package_3/class3Ns0Rename
package_6/class_6 package_7/class6Ns0Rename
class_9$class_10 class_9$class10Ns0Rename
diff --git a/src/test/resources/reading/holes/jobf.jobf b/src/test/resources/reading/holes/jobf.jobf
index b5e6978b..24d52d2c 100644
--- a/src/test/resources/reading/holes/jobf.jobf
+++ b/src/test/resources/reading/holes/jobf.jobf
@@ -1,3 +1,7 @@
+p package_1 = package1Ns0Rename
+p package_2 = package2Ns0Rename
+p package_8.package_9 = package8Ns0Rename.package9Ns0Rename
+p package_10.package_11 = package10Ns0Rename.package11Ns0Rename
c class_9$class_10 = class_9$class10Ns0Rename
c class_15$class_16 = class_15$class16Ns0Rename
c package_20.class_20$class_21$class_22 = class_20$class_21$class22Ns0Rename
diff --git a/src/test/resources/reading/holes/migration-map.xml b/src/test/resources/reading/holes/migration-map.xml
index 849e7717..61cf008a 100644
--- a/src/test/resources/reading/holes/migration-map.xml
+++ b/src/test/resources/reading/holes/migration-map.xml
@@ -1,5 +1,12 @@
+
+
+
+
+
+
+
diff --git a/src/test/resources/reading/holes/srg.srg b/src/test/resources/reading/holes/srg.srg
index 348b2d7b..02bf2613 100644
--- a/src/test/resources/reading/holes/srg.srg
+++ b/src/test/resources/reading/holes/srg.srg
@@ -1,3 +1,10 @@
+PK: package_1/ package1Ns0Rename/
+PK: package_2/ package2Ns0Rename/
+PK: package_3/ filler_3/package3Ns0Rename/
+PK: package_6/package_7/ filler_7/package6Ns0Rename/package7Ns0Rename/
+PK: package_8/package_9/ package8Ns0Rename/package9Ns0Rename/
+PK: package_10/package_11/ package10Ns0Rename/package11Ns0Rename/
+PK: package_12/package_13/ filler_13/package12Ns0Rename/package13Ns0Rename/
CL: class_3 package_3/class3Ns0Rename
CL: package_6/class_6 package_7/class6Ns0Rename
CL: class_9$class_10 class_9$class10Ns0Rename
diff --git a/src/test/resources/reading/holes/tsrg.tsrg b/src/test/resources/reading/holes/tsrg.tsrg
index d41d5af1..ff9cb2e6 100644
--- a/src/test/resources/reading/holes/tsrg.tsrg
+++ b/src/test/resources/reading/holes/tsrg.tsrg
@@ -1,3 +1,10 @@
+package_1/ package1Ns0Rename/
+package_2/ package2Ns0Rename/
+package_3/ filler_3/package3Ns0Rename/
+package_6/package_7/ filler_7/package6Ns0Rename/package7Ns0Rename/
+package_8/package_9/ package8Ns0Rename/package9Ns0Rename/
+package_10/package_11/ package10Ns0Rename/package11Ns0Rename/
+package_12/package_13/ filler_13/package12Ns0Rename/package13Ns0Rename/
class_3 package_3/class3Ns0Rename
package_6/class_6 package_7/class6Ns0Rename
class_9$class_10 class_9$class10Ns0Rename
diff --git a/src/test/resources/reading/holes/tsrgV2.tsrg b/src/test/resources/reading/holes/tsrgV2.tsrg
index 1dbfb6e1..5c7e58fe 100644
--- a/src/test/resources/reading/holes/tsrgV2.tsrg
+++ b/src/test/resources/reading/holes/tsrgV2.tsrg
@@ -1,4 +1,14 @@
tsrg2 source target target2
+package_1/ package1Ns0Rename/ package_1/
+package_2/ package2Ns0Rename/ package_2/
+package_3/ filler_3/package3Ns0Rename/ package_3/
+package_4/ package_4/ package4Ns1Rename/
+package_5/ package_5/ package5Ns1Rename/
+package_6/ package_6/ filler_7/package6Ns1Rename/
+package_6/package_7/ filler_7/package6Ns0Rename/package7Ns0Rename/ package_6/package_7/
+package_8/package_9/ package8Ns0Rename/package9Ns0Rename/ package_8/package_9/
+package_10/package_11/ package10Ns0Rename/package11Ns0Rename/ package_10/package_11/
+package_12/package_13/ filler_13/package12Ns0Rename/package13Ns0Rename/ package_12/package_13/
class_3 package_3/class3Ns0Rename class_3
package_4/class_4 package_4/class_4 class4Ns1Rename
package_6/class_6 package_7/class6Ns0Rename package_6/class_6
diff --git a/src/test/resources/reading/holes/xsrg.xsrg b/src/test/resources/reading/holes/xsrg.xsrg
index 6e89784c..f7b08e5e 100644
--- a/src/test/resources/reading/holes/xsrg.xsrg
+++ b/src/test/resources/reading/holes/xsrg.xsrg
@@ -1,3 +1,10 @@
+PK: package_1/ package1Ns0Rename/
+PK: package_2/ package2Ns0Rename/
+PK: package_3/ filler_3/package3Ns0Rename/
+PK: package_6/package_7/ filler_7/package6Ns0Rename/package7Ns0Rename/
+PK: package_8/package_9/ package8Ns0Rename/package9Ns0Rename/
+PK: package_10/package_11/ package10Ns0Rename/package11Ns0Rename/
+PK: package_12/package_13/ filler_13/package12Ns0Rename/package13Ns0Rename/
CL: class_3 package_3/class3Ns0Rename
CL: package_6/class_6 package_7/class6Ns0Rename
CL: class_9$class_10 class_9$class10Ns0Rename
diff --git a/src/test/resources/reading/repeated-elements/csrg.csrg b/src/test/resources/reading/repeated-elements/csrg.csrg
index 0cb26ff5..a19bddb3 100644
--- a/src/test/resources/reading/repeated-elements/csrg.csrg
+++ b/src/test/resources/reading/repeated-elements/csrg.csrg
@@ -1,3 +1,7 @@
+package_1/ package1Ns0Rename0/
+package_1/ package1Ns0Rename/
+package_1/package_2/ package1Ns0Rename/package2Ns0Rename0/
+package_1/package_2/ package1Ns0Rename/package2Ns0Rename/
class_1 class1Ns0Rename0
class_1 class1Ns0Rename
class_1 field_1 field1Ns0Rename0
diff --git a/src/test/resources/reading/repeated-elements/jobf.jobf b/src/test/resources/reading/repeated-elements/jobf.jobf
index 6fe4125a..48bf2342 100644
--- a/src/test/resources/reading/repeated-elements/jobf.jobf
+++ b/src/test/resources/reading/repeated-elements/jobf.jobf
@@ -1,3 +1,7 @@
+p package_1 = package1Ns0Rename0
+p package_1 = package1Ns0Rename
+p package_1.package_2 = package1Ns0Rename.package2Ns0Rename0
+p package_1.package_2 = package1Ns0Rename.package2Ns0Rename
c class_1 = class1Ns0Rename0
c class_1 = class1Ns0Rename
f class_1.field_1:I = field1Ns0Rename0
diff --git a/src/test/resources/reading/repeated-elements/migration-map.xml b/src/test/resources/reading/repeated-elements/migration-map.xml
index 7f1df594..a15e24da 100644
--- a/src/test/resources/reading/repeated-elements/migration-map.xml
+++ b/src/test/resources/reading/repeated-elements/migration-map.xml
@@ -4,6 +4,10 @@
+
+
+
+
diff --git a/src/test/resources/reading/repeated-elements/srg.srg b/src/test/resources/reading/repeated-elements/srg.srg
index 753ad3f2..45f5ec9d 100644
--- a/src/test/resources/reading/repeated-elements/srg.srg
+++ b/src/test/resources/reading/repeated-elements/srg.srg
@@ -1,3 +1,7 @@
+PK: package_1/ package1Ns0Rename0/
+PK: package_1/ package1Ns0Rename/
+PK: package_1/package_2/ package1Ns0Rename/package2Ns0Rename0/
+PK: package_1/package_2/ package1Ns0Rename/package2Ns0Rename/
CL: class_1 class1Ns0Rename0
CL: class_1 class1Ns0Rename1
FD: class_1/field_1 class1Ns0Rename/field1Ns0Rename0
diff --git a/src/test/resources/reading/repeated-elements/tsrg.tsrg b/src/test/resources/reading/repeated-elements/tsrg.tsrg
index cf675052..4c4d66e0 100644
--- a/src/test/resources/reading/repeated-elements/tsrg.tsrg
+++ b/src/test/resources/reading/repeated-elements/tsrg.tsrg
@@ -1,3 +1,7 @@
+package_1/ package1Ns0Rename0/
+package_1/ package1Ns0Rename/
+package_1/package_2/ package1Ns0Rename/package2Ns0Rename0/
+package_1/package_2/ package1Ns0Rename/package2Ns0Rename/
class_1 class1Ns0Rename0
class_1 class1Ns0Rename
field_1 field1Ns0Rename0
diff --git a/src/test/resources/reading/repeated-elements/tsrgV2.tsrg b/src/test/resources/reading/repeated-elements/tsrgV2.tsrg
index 36cc5e1c..f482c46d 100644
--- a/src/test/resources/reading/repeated-elements/tsrgV2.tsrg
+++ b/src/test/resources/reading/repeated-elements/tsrgV2.tsrg
@@ -1,4 +1,8 @@
tsrg2 source target target2
+package_1/ package1Ns0Rename0/ package1Ns1Rename0/
+package_1/ package1Ns0Rename/ package1Ns1Rename/
+package_1/package_2/ package1Ns0Rename/package2Ns0Rename0/ package1Ns1Rename/package2Ns1Rename0/
+package_1/package_2/ package1Ns0Rename/package2Ns0Rename/ package1Ns1Rename/package2Ns1Rename/
class_1 class1Ns0Rename0 class1Ns1Rename0
class_1 class1Ns0Rename class1Ns1Rename
field_1 I field1Ns0Rename0 field1Ns1Rename0
diff --git a/src/test/resources/reading/repeated-elements/xsrg.xsrg b/src/test/resources/reading/repeated-elements/xsrg.xsrg
index 8a82ca9c..9158b034 100644
--- a/src/test/resources/reading/repeated-elements/xsrg.xsrg
+++ b/src/test/resources/reading/repeated-elements/xsrg.xsrg
@@ -1,3 +1,7 @@
+PK: package_1/ package1Ns0Rename0/
+PK: package_1/ package1Ns0Rename/
+PK: package_1/package_2/ package1Ns0Rename/package2Ns0Rename0/
+PK: package_1/package_2/ package1Ns0Rename/package2Ns0Rename/
CL: class_1 class1Ns0Rename0
CL: class_1 class1Ns0Rename
FD: class_1/field_1 I class1Ns0Rename/field1Ns0Rename0 I
diff --git a/src/test/resources/reading/valid/csrg.csrg b/src/test/resources/reading/valid/csrg.csrg
index 2eb1c410..0f9f54f1 100644
--- a/src/test/resources/reading/valid/csrg.csrg
+++ b/src/test/resources/reading/valid/csrg.csrg
@@ -1,3 +1,5 @@
+package_1/ package1Ns0Rename/
+package_1/package_2/ package1Ns0Rename/package2Ns0Rename/
class_1 class1Ns0Rename
class_1 field_1 field1Ns0Rename
class_1 method_1 ()I method1Ns0Rename
diff --git a/src/test/resources/reading/valid/jobf.jobf b/src/test/resources/reading/valid/jobf.jobf
index bab02c3b..97314290 100644
--- a/src/test/resources/reading/valid/jobf.jobf
+++ b/src/test/resources/reading/valid/jobf.jobf
@@ -1,3 +1,5 @@
+p package_1 = package1Ns0Rename
+p package_1.package_2 = package1Ns0Rename.package2Ns0Rename
c class_1 = class1Ns0Rename
f class_1.field_1:I = field1Ns0Rename
m class_1.method_1()I = method1Ns0Rename
diff --git a/src/test/resources/reading/valid/migration-map.xml b/src/test/resources/reading/valid/migration-map.xml
index f330e955..21e0e72f 100644
--- a/src/test/resources/reading/valid/migration-map.xml
+++ b/src/test/resources/reading/valid/migration-map.xml
@@ -4,6 +4,8 @@
+
+
diff --git a/src/test/resources/reading/valid/srg.srg b/src/test/resources/reading/valid/srg.srg
index 95ca6759..d918aa5f 100644
--- a/src/test/resources/reading/valid/srg.srg
+++ b/src/test/resources/reading/valid/srg.srg
@@ -1,3 +1,5 @@
+PK: package_1/ package1Ns0Rename/
+PK: package_1/package_2/ package1Ns0Rename/package2Ns0Rename/
CL: class_1 class1Ns0Rename
FD: class_1/field_1 class1Ns0Rename/field1Ns0Rename
MD: class_1/method_1 ()I class1Ns0Rename/method1Ns0Rename ()I
diff --git a/src/test/resources/reading/valid/tsrg.tsrg b/src/test/resources/reading/valid/tsrg.tsrg
index 6e751643..8b9a74f1 100644
--- a/src/test/resources/reading/valid/tsrg.tsrg
+++ b/src/test/resources/reading/valid/tsrg.tsrg
@@ -1,3 +1,5 @@
+package_1/ package1Ns0Rename/
+package_1/package_2/ package1Ns0Rename/package2Ns0Rename/
class_1 class1Ns0Rename
field_1 field1Ns0Rename
method_1 ()I method1Ns0Rename
diff --git a/src/test/resources/reading/valid/tsrgV2.tsrg b/src/test/resources/reading/valid/tsrgV2.tsrg
index d383ea71..a5e04e8c 100644
--- a/src/test/resources/reading/valid/tsrgV2.tsrg
+++ b/src/test/resources/reading/valid/tsrgV2.tsrg
@@ -1,4 +1,6 @@
tsrg2 source target target2
+package_1/ package1Ns0Rename/ package1Ns1Rename/
+package_1/package_2/ package1Ns0Rename/package2Ns0Rename/ package1Ns1Rename/package2Ns1Rename/
class_1 class1Ns0Rename class1Ns1Rename
field_1 I field1Ns0Rename field1Ns1Rename
method_1 ()I method1Ns0Rename method1Ns1Rename
diff --git a/src/test/resources/reading/valid/xsrg.xsrg b/src/test/resources/reading/valid/xsrg.xsrg
index 0123a1ea..ed4a56b9 100644
--- a/src/test/resources/reading/valid/xsrg.xsrg
+++ b/src/test/resources/reading/valid/xsrg.xsrg
@@ -1,3 +1,5 @@
+PK: package_1/ package1Ns0Rename/
+PK: package_1/package_2/ package1Ns0Rename/package2Ns0Rename/
CL: class_1 class1Ns0Rename
FD: class_1/field_1 I class1Ns0Rename/field1Ns0Rename I
MD: class_1/method_1 ()I class1Ns0Rename/method1Ns0Rename ()I