Fix CRF decompile failing on c0.30 (#1384)

- ClassLineNumbers.readMappings throws a nicer error when the input data is empty.
- GenerateSourcesTask include linemap filename when failed to read.
- CRF decompiler wont write empty linemap data.
- Add test
This commit is contained in:
modmuss
2025-10-05 17:15:49 +01:00
committed by GitHub
parent d611d7f1b3
commit 4eac2e7845
4 changed files with 39 additions and 12 deletions

View File

@@ -98,6 +98,10 @@ public final class LoomCFRDecompiler implements LoomInternalDecompiler {
}
private void writeLineMap(Path output, Map<String, Map<Integer, Integer>> lineMap) {
if (lineMap.isEmpty()) {
return;
}
try (Writer writer = Files.newBufferedWriter(output, StandardCharsets.UTF_8)) {
for (Map.Entry<String, Map<Integer, Integer>> classEntry : lineMap.entrySet()) {
final String name = classEntry.getKey().replace(".", "/");

View File

@@ -28,10 +28,7 @@ import static java.text.MessageFormat.format;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.io.Writer;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
@@ -53,14 +50,6 @@ public record ClassLineNumbers(Map<String, ClassLineNumbers.Entry> lineMap) {
}
}
public static ClassLineNumbers readMappings(Path lineMappingsPath) {
try (BufferedReader reader = Files.newBufferedReader(lineMappingsPath)) {
return readMappings(reader);
} catch (IOException e) {
throw new UncheckedIOException("Exception reading LineMappings file.", e);
}
}
public static ClassLineNumbers readMappings(BufferedReader reader) {
var lineMap = new HashMap<String, ClassLineNumbers.Entry>();
@@ -81,6 +70,7 @@ public record ClassLineNumbers(Map<String, ClassLineNumbers.Entry> lineMap) {
CurrentClass currentClass = null;
Map<Integer, Integer> currentMappings = new HashMap<>();
boolean didRead = false;
try {
while ((line = reader.readLine()) != null) {
@@ -88,6 +78,8 @@ public record ClassLineNumbers(Map<String, ClassLineNumbers.Entry> lineMap) {
continue;
}
didRead = true;
final String[] segments = line.trim().split("\t");
if (line.charAt(0) != '\t') {
@@ -108,7 +100,10 @@ public record ClassLineNumbers(Map<String, ClassLineNumbers.Entry> lineMap) {
throw new RuntimeException(format("Exception reading mapping line @{0}: {1}", lineNumber, line), e);
}
assert currentClass != null;
if (!didRead) {
throw new IllegalArgumentException("Unable to read empty linemap data");
}
currentClass.putEntry(lineMap, currentMappings);
return new ClassLineNumbers(Collections.unmodifiableMap(lineMap));

View File

@@ -631,6 +631,8 @@ public abstract class GenerateSourcesTask extends AbstractLoomTask {
try (BufferedReader reader = Files.newBufferedReader(linemapFile, StandardCharsets.UTF_8)) {
return ClassLineNumbers.readMappings(reader);
} catch (Exception e) {
throw new IOException("Failed to read line number map: " + linemapFile, e);
}
}

View File

@@ -106,4 +106,30 @@ class DecompileTest extends Specification implements GradleProjectTestTrait {
result2.task(":genSourcesWithVineflower").outcome == SUCCESS
result3.task(":genSourcesWithVineflower").outcome == SUCCESS
}
// https://github.com/FabricMC/fabric-loom/issues/1362
@Unroll
def "CFR legacy"() {
setup:
def gradle = gradleProject(project: "minimalBase", version: PRE_RELEASE_GRADLE)
gradle.buildGradle << '''
loom {
noIntermediateMappings()
clientOnlyMinecraftJar()
}
dependencies {
minecraft "com.mojang:minecraft:c0.30_01c"
mappings loom.layered() {
// No names
}
}
'''
when:
def result = gradle.run(task: "genSourcesWithCfr")
then:
result.task(":genSourcesWithCfr").outcome == SUCCESS
}
}