Skip to content

Commit

Permalink
Fixes for clashing variable renaming (#378)
Browse files Browse the repository at this point in the history
* Add missing inherited name propagation to remapClashingNames

* Add and update test

* commit inner class file

* Update for rebase

* Handle anonymous classes in iterateClashingExprent

* Update tests

* Don't add inherited names

* fix param index for anon classes
  • Loading branch information
jpenilla authored Aug 17, 2024
1 parent 36db2f6 commit 4eb3409
Show file tree
Hide file tree
Showing 7 changed files with 214 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -1628,6 +1628,59 @@ private void iterateClashingExprent(Statement stat, StructMethod mt, Map<Stateme
}
}
}
} else if (!newExprent.isLambda() && newExprent.isAnonymous()) {
ClassNode node = DecompilerContext.getClassProcessor().getMapRootClasses().get(newExprent.getNewType().value);
if (node != null && node.getWrapper() != null) {
for (String mthKey : node.getWrapper().getMethods().getLstKeys()) {
MethodWrapper mw = node.getWrapper().getMethods().getWithKey(mthKey);
StructMethod mt2 = node.getWrapper().getClassStruct().getMethod(mthKey);
if (mt2 != null && mw != null) {
// Propagate current data through to method
VarDefinitionHelper vardef = new VarDefinitionHelper(mw.root, mt2, mw.varproc, false);

// Do lambda parameter rename

// Calculate which varversions are the parameters
// This gnarly logic is needed to ensure that the varversions we're looking at are parameters.
// Notably, lambdas can reference *outer* variables *before* params are listed, this is to handle that case.

MethodDescriptor md = mt2.methodDescriptor();
int start = mt2.hasModifier(CodeConstants.ACC_STATIC) ? 0 : 1;
final int startIdx = start;
for (int i = 0; i < md.params.length; i++) {
if (i >= startIdx) {
VarVersionPair vvp = new VarVersionPair(start, 0);

// Try to perform a rename
String name = mw.varproc.getVarName(vvp);
name = rename(nameMap, name);

// Did we rename? If so, we should add it to the name map and set as clashing
if (!mw.varproc.getVarName(vvp).equals(name)) {
mw.varproc.setClashingName(vvp, name);
nameMap.put(new VarInMethod(vvp, mt2), name);
}
}

start += md.params[i].stackSize;
}

// Iterate clashing names with the lambda's body, with the context of the outer method
vardef.iterateClashingNames(mw.root, mt2, varDefinitions, liveVarDefs, nameMap);

for (Entry<VarVersionPair, String> e : vardef.getClashingNames().entrySet()) {
mw.varproc.setClashingName(e.getKey(), e.getValue());
}

// Pop all the variables we've seen, now that the lambda processing is done
for (Entry<VarInMethod, String> e : new HashSet<>(nameMap.entrySet())) {
if (e.getKey().mt == mt2) {
nameMap.remove(e.getKey());
}
}
}
}
}
}
}

Expand Down
1 change: 1 addition & 0 deletions test/org/jetbrains/java/decompiler/SingleClassesTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,7 @@ private void registerDefault() {
register(JAVA_16_PREVIEW, "PermittedSubClassE", "TestSealedInterfaces");

register(JAVA_8_NODEBUG, "TestDuplicateLocals");
register(CUSTOM, "TestConflictingLvtNamer"); // Generated by compiling, stripping LVT, and then remapping with tiny-remapper

register(JAVA_8, "TestMethodHandles");
register(JAVA_9, "TestVarHandles");
Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
159 changes: 159 additions & 0 deletions testData/results/pkg/TestConflictingLvtNamer.dec
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
package pkg;

import java.util.function.Supplier;

public class TestConflictingLvtNamer {
public static Supplier<Object> method(int i, int j, int k, int l, int m, int n) {
int o = l - i + 1;// 12
int p = m - j + 1;// 13
int q = n - k + 1;// 14
int r = o * p * q;// 15
return () -> new Object() {// 16
private final TestConflictingLvtNamer.Position cursor = new TestConflictingLvtNamer.Position();
private int index;

void innerMethod() {
int ix = this.index % o;// 21
int jx = this.index / o;// 22
int kx = jx % p;// 23
int lx = jx / p;// 24
this.index++;// 25
this.cursor.set(i + ix, j + kx, k + lx);// 26
}// 27
};
}

public static final class Position {
public void set(int i, int j, int k) {
}// 8
}
}

class 'pkg/TestConflictingLvtNamer' {
method 'method (IIIIII)Ljava/util/function/Supplier;' {
0 6
1 6
2 6
3 6
4 6
5 6
6 6
7 7
8 7
9 7
a 7
b 7
c 7
d 7
e 7
f 8
10 8
11 8
12 8
13 8
14 8
15 8
16 8
17 9
18 9
19 9
1a 9
1b 9
1c 9
1d 9
1e 9
1f 9
20 9
2d 10
}

method 'lambda$method$0 (IIIII)Ljava/lang/Object;' {
d 10
}
}

class 'pkg/TestConflictingLvtNamer$1' {
method 'innerMethod ()V' {
0 15
1 15
2 15
3 15
5 15
6 15
7 15
8 15
9 15
a 16
b 16
c 16
d 16
f 16
10 16
11 16
12 16
13 16
14 17
16 17
17 17
18 17
19 17
1a 17
1b 18
1d 18
1e 18
1f 18
20 18
21 18
22 18
23 19
25 19
26 19
27 19
29 19
2d 20
2e 20
2f 20
30 20
32 20
33 20
34 20
35 20
36 20
38 20
39 20
3a 20
3b 20
3c 20
3e 20
3f 20
40 20
41 20
42 20
43 20
44 20
45 20
46 20
47 21
}
}

class 'pkg/TestConflictingLvtNamer$Position' {
method 'set (III)V' {
0 27
}
}

Lines mapping:
8 <-> 28
12 <-> 7
13 <-> 8
14 <-> 9
15 <-> 10
16 <-> 11
21 <-> 16
22 <-> 17
23 <-> 18
24 <-> 19
25 <-> 20
26 <-> 21
27 <-> 22
2 changes: 1 addition & 1 deletion testData/results/pkg/TestThrowException.dec
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ public class TestThrowException {
this.r = new Runnable() {// 12
@Override
public void run() {
int a = 5;// 15
int ax = 5;// 15
}// 16
};
}
Expand Down

0 comments on commit 4eb3409

Please sign in to comment.