From 4eac2e7845244725c1110a986e2d6bf42a8176f2 Mon Sep 17 00:00:00 2001 From: modmuss Date: Sun, 5 Oct 2025 17:15:49 +0100 Subject: [PATCH] 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 --- .../decompilers/cfr/LoomCFRDecompiler.java | 4 +++ .../loom/decompilers/ClassLineNumbers.java | 19 +++++--------- .../loom/task/GenerateSourcesTask.java | 2 ++ .../test/integration/DecompileTest.groovy | 26 +++++++++++++++++++ 4 files changed, 39 insertions(+), 12 deletions(-) diff --git a/src/decompilers/cfr/net/fabricmc/loom/decompilers/cfr/LoomCFRDecompiler.java b/src/decompilers/cfr/net/fabricmc/loom/decompilers/cfr/LoomCFRDecompiler.java index 72f7b2e5..0f9510cc 100644 --- a/src/decompilers/cfr/net/fabricmc/loom/decompilers/cfr/LoomCFRDecompiler.java +++ b/src/decompilers/cfr/net/fabricmc/loom/decompilers/cfr/LoomCFRDecompiler.java @@ -98,6 +98,10 @@ public final class LoomCFRDecompiler implements LoomInternalDecompiler { } private void writeLineMap(Path output, Map> lineMap) { + if (lineMap.isEmpty()) { + return; + } + try (Writer writer = Files.newBufferedWriter(output, StandardCharsets.UTF_8)) { for (Map.Entry> classEntry : lineMap.entrySet()) { final String name = classEntry.getKey().replace(".", "/"); diff --git a/src/main/java/net/fabricmc/loom/decompilers/ClassLineNumbers.java b/src/main/java/net/fabricmc/loom/decompilers/ClassLineNumbers.java index 120972fa..64928cad 100644 --- a/src/main/java/net/fabricmc/loom/decompilers/ClassLineNumbers.java +++ b/src/main/java/net/fabricmc/loom/decompilers/ClassLineNumbers.java @@ -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 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(); @@ -81,6 +70,7 @@ public record ClassLineNumbers(Map lineMap) { CurrentClass currentClass = null; Map currentMappings = new HashMap<>(); + boolean didRead = false; try { while ((line = reader.readLine()) != null) { @@ -88,6 +78,8 @@ public record ClassLineNumbers(Map lineMap) { continue; } + didRead = true; + final String[] segments = line.trim().split("\t"); if (line.charAt(0) != '\t') { @@ -108,7 +100,10 @@ public record ClassLineNumbers(Map 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)); diff --git a/src/main/java/net/fabricmc/loom/task/GenerateSourcesTask.java b/src/main/java/net/fabricmc/loom/task/GenerateSourcesTask.java index 9ff3ed2f..1fc99793 100644 --- a/src/main/java/net/fabricmc/loom/task/GenerateSourcesTask.java +++ b/src/main/java/net/fabricmc/loom/task/GenerateSourcesTask.java @@ -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); } } diff --git a/src/test/groovy/net/fabricmc/loom/test/integration/DecompileTest.groovy b/src/test/groovy/net/fabricmc/loom/test/integration/DecompileTest.groovy index 120d9e73..57b2d32f 100644 --- a/src/test/groovy/net/fabricmc/loom/test/integration/DecompileTest.groovy +++ b/src/test/groovy/net/fabricmc/loom/test/integration/DecompileTest.groovy @@ -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 + } }