add tinyv1/2 parsers + writers, add mapping merging + flattening, fix bugs #3

Merged
Ecorous merged 4 commits from owlsys/tiny-mappings into main 2024-07-04 14:39:23 -04:00
5 changed files with 89 additions and 56 deletions
Showing only changes of commit e84f01e117 - Show all commits

View file

@ -69,7 +69,20 @@ public record MappingBundle(List<MappingData> data, List<DocumentationData> docu
} }
public MappingData forNamespaces(String src, String dst) { public MappingData forNamespaces(String src, String dst) {
return flatten(src, dst); return flattenInternal(src, dst, false);
}
public MappingData forNamespaces(String src, String dst, boolean allowIncomplete) {
return flattenInternal(src, dst, allowIncomplete);
}
public MappingBundle flatten(String src, String dst) {
return flatten(src, dst, false);
}
public MappingBundle flatten(String src, String dst, boolean allowIncomplete) {
MappingData data = flattenInternal(src, dst, allowIncomplete);
return new MappingBundle(data, get(data.dstNamespace()));
} }
public DocumentationData docsForNamespace(String ns) { public DocumentationData docsForNamespace(String ns) {
@ -78,7 +91,7 @@ public record MappingBundle(List<MappingData> data, List<DocumentationData> docu
if (d.namespace().equals(ns)) { if (d.namespace().equals(ns)) {
result.insert(d); result.insert(d);
} else { } else {
Mapper mappings = new Mapper(forNamespaces(d.namespace(), ns), a -> Collections.emptyList()); Mapper mappings = new Mapper(forNamespaces(d.namespace(), ns, false), a -> Collections.emptyList());
DocumentationData remapped = new DocumentationData(ns); DocumentationData remapped = new DocumentationData(ns);
// TODO is there something we can do about the packages...? (don't think so) // TODO is there something we can do about the packages...? (don't think so)
d.classes().forEach(c -> { d.classes().forEach(c -> {
@ -98,19 +111,29 @@ public record MappingBundle(List<MappingData> data, List<DocumentationData> docu
} }
public MappingBundle flatten() { public MappingBundle flatten() {
MappingData data = flattenData(); return flatten(false);
}
public MappingBundle flatten(boolean allowIncomplete) {
MappingData data = flattenData(allowIncomplete);
return new MappingBundle(data, get(data.dstNamespace())); return new MappingBundle(data, get(data.dstNamespace()));
} }
public MappingData flattenData() { public MappingData flattenData(boolean allowIncomplete) {
Set<String> overlayNs = new HashSet<>();
for (MappingData d : data()) {
if (d.srcNamespace().equals(d.dstNamespace())) {
overlayNs.add(d.srcNamespace());
}
}
List<String> srcNs = srcNamespaces(); List<String> srcNs = srcNamespaces();
List<String> dstNs = dstNamespaces(); List<String> dstNs = dstNamespaces();
List<String> srcNsCandidates = srcNs.stream().filter(s -> !dstNs.contains(s)).toList(); List<String> srcNsCandidates = srcNs.stream().distinct().filter(s -> !dstNs.contains(s) && !overlayNs.contains(s)).toList();
List<String> dstNsCandidates = dstNs.stream().filter(s -> !srcNs.contains(s)).toList(); List<String> dstNsCandidates = dstNs.stream().distinct().filter(s -> !srcNs.contains(s) || overlayNs.contains(s)).toList();
if (srcNsCandidates.size() > 1) { if (srcNsCandidates.size() > 1) {
throw new IllegalStateException("Not a linear graph, cannot flatten! Got possible roots: " + String.join(", ", srcNsCandidates)); throw new IllegalStateException("Not a linear graph, cannot flatten! Got possible roots: " + String.join(", ", srcNsCandidates));
} else if (srcNsCandidates.isEmpty()) { } else if (srcNsCandidates.isEmpty()) {
throw new IllegalStateException("Not a linear graph, cannot flatten! Got no possible roots! SrcNamespaces: " + String.join(", ", srcNs)); throw new IllegalStateException("Not a linear graph, cannot flatten! Got no possible roots! SrcNamespaces: " + String.join(", ", srcNs) + " Overlays: " + String.join(", ", overlayNs));
} }
if (dstNsCandidates.size() > 1) { if (dstNsCandidates.size() > 1) {
throw new IllegalStateException("Not a linear graph, cannot flatten! Got possible ends: " + String.join(", ", dstNsCandidates)); throw new IllegalStateException("Not a linear graph, cannot flatten! Got possible ends: " + String.join(", ", dstNsCandidates));
@ -119,10 +142,10 @@ public record MappingBundle(List<MappingData> data, List<DocumentationData> docu
} }
String srcRoot = srcNsCandidates.getFirst(); String srcRoot = srcNsCandidates.getFirst();
String dstRoot = dstNsCandidates.getFirst(); String dstRoot = dstNsCandidates.getFirst();
return flatten(srcRoot, dstRoot); return flattenInternal(srcRoot, dstRoot, allowIncomplete);
} }
private MappingData flatten(String srcRoot, String dstRoot) { private MappingData flattenInternal(String srcRoot, String dstRoot, boolean allowIncomplete) {
Deque<MappingData> path = computePath(srcRoot, dstRoot).reversed(); Deque<MappingData> path = computePath(srcRoot, dstRoot).reversed();
MappingData result = new MappingData(srcRoot, dstRoot); MappingData result = new MappingData(srcRoot, dstRoot);
@ -140,12 +163,14 @@ public record MappingBundle(List<MappingData> data, List<DocumentationData> docu
String w = res; String w = res;
res = d.classes().get(res); res = d.classes().get(res);
if (res == null) { if (res == null) {
if (!allowIncomplete) {
/* /*
* The mapping set is incomplete at this point. * The mapping set is incomplete at this point.
* We're using the last available value to prevent incompleteness * We're using the last available value to prevent incompleteness
* in the resulting set. * in the resulting set.
*/ */
res = w; res = w;
}
break; break;
} }
} }
@ -167,12 +192,14 @@ public record MappingBundle(List<MappingData> data, List<DocumentationData> docu
owner = mapper.map(owner); owner = mapper.map(owner);
desc = mapper.mapMethodDesc(desc); desc = mapper.mapMethodDesc(desc);
if (res == null) { if (res == null) {
if (!allowIncomplete) {
/* /*
* The mapping set is incomplete at this point. * The mapping set is incomplete at this point.
* We're using the last available value to prevent incompleteness * We're using the last available value to prevent incompleteness
* in the resulting set. * in the resulting set.
*/ */
res = w; res = w;
}
break; break;
} }
} }
@ -194,12 +221,14 @@ public record MappingBundle(List<MappingData> data, List<DocumentationData> docu
owner = mapper.map(owner); owner = mapper.map(owner);
desc = mapper.mapDesc(desc); desc = mapper.mapDesc(desc);
if (res == null) { if (res == null) {
if (!allowIncomplete) {
/* /*
* The mapping set is incomplete at this point. * The mapping set is incomplete at this point.
* We're using the last available value to prevent incompleteness * We're using the last available value to prevent incompleteness
* in the resulting set. * in the resulting set.
*/ */
res = w; res = w;
}
break; break;
} }
} }
@ -234,7 +263,7 @@ public record MappingBundle(List<MappingData> data, List<DocumentationData> docu
Deque<MappingData> path = new ArrayDeque<>(); Deque<MappingData> path = new ArrayDeque<>();
List<MappingData> available = new ArrayList<>(data); List<MappingData> available = new ArrayList<>(data);
for (MappingData d : new ArrayList<>(available)) { for (MappingData d : data) {
if (d.srcNamespace().equals(srcRoot)) { if (d.srcNamespace().equals(srcRoot)) {
path.push(d); path.push(d);
available.remove(d); available.remove(d);
@ -274,6 +303,16 @@ public record MappingBundle(List<MappingData> data, List<DocumentationData> docu
return insert(data).insert(documentation); return insert(data).insert(documentation);
} }
public MappingBundle insert(MappingBundle other) {
return insert(other.data, other.documentation);
}
public MappingBundle insert(List<MappingData> data, List<DocumentationData> documentation) {
data.forEach(this::insert);
documentation.forEach(this::insert);
return this;
}
public DocumentationData get(String namespace) { public DocumentationData get(String namespace) {
DocumentationData result = null; DocumentationData result = null;
for (DocumentationData d : documentation) { for (DocumentationData d : documentation) {
@ -304,4 +343,8 @@ public record MappingBundle(List<MappingData> data, List<DocumentationData> docu
reversed.documentation.addAll(documentation); reversed.documentation.addAll(documentation);
return reversed; return reversed;
} }
public MappingData flattenData() {
return flattenData(false);
}
} }

View file

@ -103,7 +103,7 @@ public class TinyV2Parser {
} }
if (currentF == null && currentM == null) { if (currentF == null && currentM == null) {
throw new IllegalStateException("Field javadoc/Method parameter mapping/javadoc specified before a declaration"); continue;
} }
{ {

View file

@ -115,7 +115,7 @@ public class ParchmentProvider {
javadoc.add("@parameter " + puC.get("name") + " " + doc); javadoc.add("@parameter " + puC.get("name") + " " + doc);
} }
} }
methods.add(new DocumentationData.Method(uc.get("name"), uc.get("descriptor"), javadoc)); methods.add(new DocumentationData.Method(uc.get("name"), uc.get("descriptor"), Objects.requireNonNullElse(javadoc, new ArrayList<>())));
}); });
List<UnmodifiableConfig> fieldsList = Objects.requireNonNullElse(config.get("fields"), Collections.emptyList()); List<UnmodifiableConfig> fieldsList = Objects.requireNonNullElse(config.get("fields"), Collections.emptyList());

View file

@ -17,7 +17,12 @@ public class TinyV1Writer {
* @param writer a writer for the mappings to be written to * @param writer a writer for the mappings to be written to
*/ */
public static void write(MappingBundle bundle, Writer writer) { public static void write(MappingBundle bundle, Writer writer) {
MappingData data = bundle.flattenData(); // we can only have 2 namespaces. MappingData data;
if (bundle.srcNamespaces().size() > 1 || bundle.dstNamespaces().size() > 1) {
data = bundle.flattenData(); // we can only have 2 namespaces.
} else {
data = bundle.data().getFirst();
}
PrintWriter print = new PrintWriter(writer, true); PrintWriter print = new PrintWriter(writer, true);
print.println("v1\t" + data.srcNamespace() + "\t" + data.dstNamespace()); print.println("v1\t" + data.srcNamespace() + "\t" + data.dstNamespace());

View file

@ -14,9 +14,15 @@ public class TinyV2Writer {
public static void write(MappingBundle bundle, Writer writer) { public static void write(MappingBundle bundle, Writer writer) {
Set<String> overlayNs = new HashSet<>();
for (MappingData d : bundle.data()) {
if (d.srcNamespace().equals(d.dstNamespace())) {
overlayNs.add(d.srcNamespace());
}
}
List<String> srcNs = bundle.srcNamespaces(); List<String> srcNs = bundle.srcNamespaces();
List<String> dstNs = bundle.dstNamespaces(); List<String> dstNs = bundle.dstNamespaces();
List<String> srcNamespaces = srcNs.stream().filter(s -> !dstNs.contains(s)).toList(); List<String> srcNamespaces = srcNs.stream().distinct().filter(s -> !dstNs.contains(s) && !overlayNs.contains(s)).toList();
if (srcNamespaces.size() > 1) { if (srcNamespaces.size() > 1) {
throw new IllegalStateException("Mapping Data cannot be reduced to a single source namespace, " + throw new IllegalStateException("Mapping Data cannot be reduced to a single source namespace, " +
"please use .flatten(...) to obtain a mappings set with defined namespaces"); "please use .flatten(...) to obtain a mappings set with defined namespaces");
@ -32,27 +38,6 @@ public class TinyV2Writer {
List<Mapper> reverseMappers = new ArrayList<>(); List<Mapper> reverseMappers = new ArrayList<>();
String src = srcNamespace; String src = srcNamespace;
/*MappingData data = bundle.getWithSrcNamespace(src);
DocumentationData docs = bundle.get(src);
data.classes().forEach((s, s2) -> classes.computeIfAbsent(s, a -> new HashMap<>()).put(0, s2));
data.methods().forEach((member, s) -> methods.computeIfAbsent(member.owner(), a -> new HashMap<>())
.computeIfAbsent(member, a -> new HashMap<>()).put(0, s));
data.fields().forEach((member, s) -> fields.computeIfAbsent(member.owner(), a -> new HashMap<>())
.computeIfAbsent(member, a -> new HashMap<>()).put(0, s));
data.parameters().forEach((member, map) -> {
Map<Integer, Map<Integer, String>> b = parameters.computeIfAbsent(member, a -> new HashMap<>());
map.forEach((i, s) -> {
b.computeIfAbsent(i, a -> new HashMap<>()).put(0, s);
});
});
reverseMappers.addFirst(new Mapper(data.reverse(), s -> Collections.emptyList()));
if (docs != null) {
docs.classes().forEach(c -> {
if (c.javadoc() != null) {
javadocs.put(c.name(), String.join("\n", c.javadoc()));
}
});
}*/
MappingData data = bundle.getWithSrcNamespace(src); MappingData data = bundle.getWithSrcNamespace(src);
DocumentationData docs; DocumentationData docs;
@ -77,7 +62,7 @@ public class TinyV2Writer {
DocumentationData.Class c = docsClasses.get(k); DocumentationData.Class c = docsClasses.get(k);
if (c != null) { if (c != null) {
if (c.javadoc() != null && !c.javadoc().isEmpty()) { if (c.javadoc() != null && !c.javadoc().isEmpty()) {
javadocs.put(root, String.join("\n", c.javadoc())); javadocs.put(root, String.join("\\n", c.javadoc()));
} }
} }
} }
@ -99,7 +84,7 @@ public class TinyV2Writer {
c.getMethod(data.methods().get(key), selfMap.mapMethodDesc(key.descriptor())) c.getMethod(data.methods().get(key), selfMap.mapMethodDesc(key.descriptor()))
.ifPresent(m -> { .ifPresent(m -> {
if (m.javadoc() != null && !m.javadoc().isEmpty()) { if (m.javadoc() != null && !m.javadoc().isEmpty()) {
javadocs.put(rt.owner() + rt.descriptor() + rt.name(), String.join("\n", m.javadoc())); javadocs.put(rt.owner() + rt.descriptor() + rt.name(), String.join("\\n", m.javadoc()));
} }
}); });
} }
@ -122,7 +107,7 @@ public class TinyV2Writer {
c.getField(data.fields().get(member), selfMap.mapDesc(member.descriptor())) c.getField(data.fields().get(member), selfMap.mapDesc(member.descriptor()))
.ifPresent(f -> { .ifPresent(f -> {
if (f.javadoc() != null && !f.javadoc().isEmpty()) { if (f.javadoc() != null && !f.javadoc().isEmpty()) {
javadocs.put(id, String.join("\n", f.javadoc())); javadocs.put(id, String.join("\\n", f.javadoc()));
} }
}); });
} }