Skip to content

Commit

Permalink
Make LineNumberRemapper stop trying to guess line numbers
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
tranquillity-codes committed Dec 18, 2024
1 parent c80333b commit c9438c5
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -106,20 +106,16 @@ public MethodVisitor visitMethod(int access, String name, String descriptor, Str
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);
}
}
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit c9438c5

Please sign in to comment.