Skip to content

Commit

Permalink
Ignore synthetic methods when mapping method calls
Browse files Browse the repository at this point in the history
  • Loading branch information
Gaming32 committed Jan 4, 2024
1 parent ade35bf commit 4912c8b
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 4 deletions.
2 changes: 1 addition & 1 deletion src/main/kotlin/com/replaymod/gradle/remap/PsiMapper.kt
Original file line number Diff line number Diff line change
Expand Up @@ -719,7 +719,7 @@ internal class PsiMapper(

override fun visitReferenceElement(reference: PsiJavaCodeReferenceElement) {
if (valid(reference)) {
map(reference, reference.resolve())
map(reference, reference.smartMultiResolve())
}
super.visitReferenceElement(reference)
}
Expand Down
39 changes: 39 additions & 0 deletions src/main/kotlin/com/replaymod/gradle/remap/PsiUtils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,45 @@ private fun findAllSuperMethods(
}
}

fun PsiJavaCodeReferenceElement.smartMultiResolve(): PsiElement? {
val result = multiResolve(false)
if (result.isEmpty()) {
return null
}
if (result.size == 1) {
return result[0].element
}
val methods = result.mapNotNull { it.element as? PsiMethod }
if (methods.size < result.size) {
return null // Only do heuristic search on methods
}
val nonSynthetic = methods.filter {
!it.modifierList.hasModifierProperty("volatile") // ACC_VOLATILE is access 0x40, which is what ACC_BRIDGE is on methods
}
if (nonSynthetic.size == 1) {
return nonSynthetic[0]
}
val heuristicSearch = nonSynthetic.ifEmpty { methods }
var lowestMethodSoFar = heuristicSearch[0]
var lowestReturnSoFar = lowestMethodSoFar.returnType
for (i in 1..heuristicSearch.lastIndex) {
val method = heuristicSearch[i]
val returnType = method.returnType ?: continue
if (lowestReturnSoFar == null) {
lowestMethodSoFar = method
lowestReturnSoFar = returnType
continue
}
if (lowestReturnSoFar.isAssignableFrom(returnType) && lowestReturnSoFar != returnType) {
lowestMethodSoFar = method
lowestReturnSoFar = returnType
continue
}
// In the future, maybe also analyze based on number of supertypes/hierarchy depth?
}
return lowestMethodSoFar
}

internal object PsiUtils {
fun getSignature(method: PsiMethod): MethodSignature = MethodSignature(method.name, getDescriptor(method))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,13 @@ val desynthesizeTransformer = ClasspathTransformer { parent ->
descriptor: String?,
signature: String?,
exceptions: Array<out String>?
) = object : MethodVisitor(api, super.visitMethod(desynthesize(access), name, descriptor, signature, exceptions)) {
override fun visitParameter(name: String?, access: Int) =
super.visitParameter(name, desynthesize(access))
): MethodVisitor {
// Remap synthetic to some other meaningless access. All methods that are already bridge should also already be synthetic.
val newAccess = desynthesize(access) or if ((access and Opcodes.ACC_SYNTHETIC) != 0) Opcodes.ACC_BRIDGE else 0
return object : MethodVisitor(api, super.visitMethod(newAccess, name, descriptor, signature, exceptions)) {
override fun visitParameter(name: String?, access: Int) =
super.visitParameter(name, desynthesize(access))
}
}

override fun visitModule(name: String?, access: Int, version: String?) =
Expand Down

0 comments on commit 4912c8b

Please sign in to comment.