Skip to content

Commit

Permalink
Add preliminary .match file reader
Browse files Browse the repository at this point in the history
  • Loading branch information
NebelNidas committed Jun 16, 2023
1 parent c585d9b commit 96cfc5c
Show file tree
Hide file tree
Showing 3 changed files with 156 additions and 1 deletion.
6 changes: 6 additions & 0 deletions src/main/java/net/fabricmc/mappingio/MappingReader.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import net.fabricmc.mappingio.format.MappingFormat;
import net.fabricmc.mappingio.format.enigma.EnigmaDirReader;
import net.fabricmc.mappingio.format.enigma.EnigmaFileReader;
import net.fabricmc.mappingio.format.match.MatchFileReader;
import net.fabricmc.mappingio.format.proguard.ProGuardFileReader;
import net.fabricmc.mappingio.format.srg.SrgFileReader;
import net.fabricmc.mappingio.format.tiny.Tiny1FileReader;
Expand Down Expand Up @@ -72,6 +73,8 @@ public static MappingFormat detectFormat(Reader reader) throws IOException {
case "MD:":
case "FD:":
return MappingFormat.SRG_FILE;
case "Mat":
return MappingFormat.MATCH_FILE;
}

String headerStr = String.valueOf(buffer, 0, pos);
Expand Down Expand Up @@ -197,6 +200,9 @@ public static void read(Reader reader, MappingFormat format, MappingVisitor visi
case PROGUARD_FILE:
ProGuardFileReader.read(reader, visitor);
break;
case MATCH_FILE:
MatchFileReader.read(reader, visitor);
break;
default:
throw new IllegalStateException();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ public enum MappingFormat {
SRG_FILE("SRG file", "srg", false, false, false, false, false),
TSRG_FILE("TSRG file", "tsrg", false, false, false, false, false),
TSRG_2_FILE("TSRG2 file", "tsrg", true, false, false, true, false),
PROGUARD_FILE("ProGuard file", "map", false, true, false, false, false);
PROGUARD_FILE("ProGuard file", "map", false, true, false, false, false),
MATCH_FILE("Match file", "match", false, true, false, true, true);

MappingFormat(String name, String fileExt,
boolean hasNamespaces, boolean hasFieldDescriptors,
Expand Down
148 changes: 148 additions & 0 deletions src/main/java/net/fabricmc/mappingio/format/match/MatchFileReader.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
/*
* Copyright (c) 2021 FabricMC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package net.fabricmc.mappingio.format.match;

import java.io.IOException;
import java.io.Reader;
import java.util.Arrays;

import net.fabricmc.mappingio.MappedElementKind;
import net.fabricmc.mappingio.MappingFlag;
import net.fabricmc.mappingio.MappingVisitor;
import net.fabricmc.mappingio.format.ColumnFileReader;

public class MatchFileReader {
public static void read(Reader reader, MappingVisitor visitor) throws IOException {
read(new ColumnFileReader(reader, '\t'), visitor);
}

private static void read(ColumnFileReader reader, MappingVisitor visitor) throws IOException {
if (!reader.nextCol().startsWith("Matches saved")) {
throw new IOException("invalid/unsupported matches file: incorrect header");
}

if (visitor.getFlags().contains(MappingFlag.NEEDS_MULTIPLE_PASSES)) {
reader.mark();
}

boolean escapeNames = false;

for (;;) {
boolean visitHeader = visitor.visitHeader();

if (visitHeader) {
visitor.visitNamespaces("a", Arrays.asList("b"));
}

if (visitor.visitContent()) {
while (reader.nextLine(0)) {
if (reader.nextCol("c")) { // class: c <name-a> <name-b>
String srcName = reader.nextCol(escapeNames);
if (srcName == null || srcName.isEmpty()) throw new IOException("missing class-name-a in line "+reader.getLineNumber());

if (visitor.visitClass(srcName)) {
readClass(reader, escapeNames, visitor);
}
}
}
}

if (visitor.visitEnd()) break;

reader.reset();
}
}

private static void readClass(ColumnFileReader reader, boolean escapeNames, MappingVisitor visitor) throws IOException {
visitor.visitDstName(MappedElementKind.CLASS, 0, reader.nextCol(escapeNames));
if (!visitor.visitElementContent(MappedElementKind.CLASS)) return;

while (reader.nextLine(1)) {
boolean field = false;
boolean method = false;

if ((field = reader.nextCol("f")) || (method = reader.nextCol("m"))) {
// field: f <name-a;;desc-a> <name-b;;desc->
// method: m <name-a desc-a> <name-b desc-b> (but no spaces between name and desc)

String[] from;
String[] to;

if (field) {
from = reader.nextCol(escapeNames).split(";;");
to = reader.nextCol(escapeNames).split(";;");
} else {
from = toMethodArray(reader.nextCol(escapeNames));
to = toMethodArray(reader.nextCol(escapeNames));
}

if (from.length != 2 || to.length != 2) throw new IOException("invalid member mapping in line "+reader.getLineNumber());

String srcName = from[0];
String srcDesc = from[1];
String dstName = to[0];
String dstDesc = to[1];

if (field && visitor.visitField(srcName, srcDesc)) {
visitor.visitDstName(MappedElementKind.FIELD, 0, dstName);
visitor.visitDstDesc(MappedElementKind.FIELD, 0, dstDesc);
} else if (method && visitor.visitMethod(srcName, srcDesc)) {
visitor.visitDstName(MappedElementKind.METHOD, 0, dstName);
visitor.visitDstDesc(MappedElementKind.METHOD, 0, dstDesc);
readMethodContent(reader, escapeNames, visitor);
}
} else if (reader.nextCol("c")) { // comment: c <comment>
readComment(reader, MappedElementKind.CLASS, visitor);
}
}
}

private static String[] toMethodArray(String nameWithDescriptor) {
int parenPos = nameWithDescriptor.indexOf('(');
return new String[] {
nameWithDescriptor.substring(0, parenPos),
nameWithDescriptor.substring(parenPos)
};
}

private static void readMethodContent(ColumnFileReader reader, boolean escapeNames, MappingVisitor visitor) throws IOException {
if (!visitor.visitElementContent(MappedElementKind.METHOD)) return;

while (reader.nextLine(2)) {
if (reader.nextCol("ma")) {
// method arg: ma <arg-pos-a> <arg-pos-b>

int srcArgPos = reader.nextIntCol();
int dstArgPos = reader.nextIntCol();
if (srcArgPos < 0 || dstArgPos < 0) throw new IOException("missing/invalid method arg position in line "+reader.getLineNumber());

if (visitor.visitMethodArg(srcArgPos, -1, null)) {
// TODO: Implement once per-element metadata is supported
}
} else if (reader.nextCol("c")) { // comment: c <comment>
readComment(reader, MappedElementKind.METHOD, visitor);
}
}
}

private static void readComment(ColumnFileReader reader, MappedElementKind subjectKind, MappingVisitor visitor) throws IOException {
String comment = reader.nextEscapedCol();
if (comment == null) throw new IOException("missing comment in line "+reader.getLineNumber());

visitor.visitComment(subjectKind, comment);
}
}

0 comments on commit 96cfc5c

Please sign in to comment.