Make LineNumberRemapper stop trying to guess line numbers (#1235)

Usually the guesses were wrong, so instead let's not generate a
LineNumberTable for lines that lack a mapping in the linemap. This makes
the behavior on decompiler bugs/issues more predictable.
This commit is contained in:
tranquillity-codes
2024-12-23 16:57:57 +01:00
committed by GitHub
parent 2ba633badf
commit 3fce2627d6
2 changed files with 30 additions and 9 deletions

View File

@@ -106,20 +106,16 @@ public record LineNumberRemapper(ClassLineNumbers lineNumbers) {
return new MethodVisitor(api, super.visitMethod(access, name, descriptor, signature, exceptions)) {
@Override
public void visitLineNumber(int line, Label start) {
int tLine = line;
if (tLine <= 0) {
if (line <= 0) {
super.visitLineNumber(line, start);
} else if (tLine >= lineNumbers.maxLine()) {
} else if (line >= lineNumbers.maxLine()) {
super.visitLineNumber(lineNumbers.maxLineDest(), start);
} else {
Integer matchedLine = null;
Integer matchedLine = lineNumbers.lineMap().get(line);
while (tLine <= lineNumbers.maxLine() && ((matchedLine = lineNumbers.lineMap().get(tLine)) == null)) {
tLine++;
if (matchedLine != null) {
super.visitLineNumber(matchedLine, start);
}
super.visitLineNumber(matchedLine != null ? matchedLine : lineNumbers.maxLineDest(), start);
}
}
};

View File

@@ -65,6 +65,31 @@ class LineNumberRemapperTests extends Specification {
readLineNumbers(unpacked) == [37, 39, 40]
}
def "remapLinenumbersExclude"() {
given:
def className = LineNumberSource.class.name.replace('.', '/')
def input = ZipTestUtils.createZipFromBytes([(className + ".class"): getClassBytes(LineNumberSource.class)])
// + 10 to each line number
def entry = new ClassLineNumbers.Entry(className, 30, 40, [
27: 37,
30: 40
])
def lineNumbers = new ClassLineNumbers([(className): entry])
def outputJar = Files.createTempDirectory("loom").resolve("output.jar")
when:
def remapper = new LineNumberRemapper(lineNumbers)
remapper.process(input, outputJar)
def unpacked = ZipUtils.unpack(outputJar, className + ".class")
then:
readLineNumbers(getClassBytes(LineNumberSource.class)) == [27, 29, 30]
readLineNumbers(unpacked) == [37, 40]
}
static byte[] getClassBytes(Class<?> clazz) {
return clazz.classLoader.getResourceAsStream(clazz.name.replace('.', '/') + ".class").withCloseable {
it.bytes