Skip to content

Commit

Permalink
Add heuristic for obfuscated non-simple record getter
Browse files Browse the repository at this point in the history
A simple getter is a getter which contains only "return <field>". The
heuristic for detecting field getters can't detect anything more complex
than that.

This means that non-simple getters for record fields aren't detected,
causing failure later on due to the assumption that a record component
always has a getter.

To fix that, add a simple heuristic to detect getters for record
components, by finding one method that has no parameters and returns the
same type as the record component. It only considers the parameters and
return type (e.g., the method descriptor) as the metadata extraction
works on obfuscated names, and the obf name of the record component may
be different from the obf name of the corresponding getter.

Also add a check to throw an exception when a getter could not be found
for a record component, to easily detect these problems in the future.

Partially addresses #8
  • Loading branch information
sciwhiz12 committed Apr 10, 2024
1 parent 8ed42f3 commit de39f59
Showing 1 changed file with 27 additions and 0 deletions.
27 changes: 27 additions & 0 deletions src/main/java/org/parchmentmc/lodestone/asm/CodeCleaner.java
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,33 @@ private void resolveRecord(MutableClassInfo mutableClassInfo) {
mutableFieldInfo.getGetters()
);
}

if (mutableRecordInfo.getGetters().isEmpty()) {
// If no getters were attached to the fields by the bytecode heuristic, then fallback to a simple
// heuristic: find a single method which has no parameters, and whose return type matches the field type
// (ignoring the method name, since we're dealing with obfuscated names here)
// If there's more than one matching method, bail out: we can't be sure which one is the correct one

String targetDesc = "()" + mutableRecordInfo.getDesc();
MutableMethodInfo foundGetter = null;
int found = 0;
for (MutableMethodInfo methodInfo : mutableClassInfo.getMethods().values()) {
if (targetDesc.equals(methodInfo.getMethod().getDesc())) {
foundGetter = methodInfo;
found++;
}
}

if (found == 1) {
mutableRecordInfo.getGetters().add(foundGetter.getMethod());
// Don't add to the field getters for now, so the field getters are always those determined by the
// bytecode heuristic (See constructor for MutableMethodInfo)
}
}

if (mutableRecordInfo.getGetters().isEmpty()) {
throw new RuntimeException("Failed to find getter for record component " + mutableRecordInfo.getName() + " in class " + mutableClassInfo.getName());
}
}
}

Expand Down

0 comments on commit de39f59

Please sign in to comment.