in src/org/jetbrains/java/decompiler/main/rels/NestedMemberAccess.java [312:445]
private Exprent replaceAccessExprent(ClassNode caller, MethodWrapper methdest, InvocationExprent invexpr) {
ClassNode node = DecompilerContext.getClassProcessor().getMapRootClasses().get(invexpr.getClassName());
MethodWrapper methsource = null;
if (node != null && node.getWrapper() != null) {
methsource = node.getWrapper().getMethodWrapper(invexpr.getName(), invexpr.getStringDescriptor());
}
if (methsource == null || !mapMethodType.containsKey(methsource)) {
return null;
}
// if same method, return
if (node.classStruct.qualifiedName.equals(caller.classStruct.qualifiedName) &&
methsource.methodStruct.getName().equals(methdest.methodStruct.getName()) &&
methsource.methodStruct.getDescriptor().equals(methdest.methodStruct.getDescriptor())) {
// no recursive invocations permitted!
return null;
}
MethodAccess type = mapMethodType.get(methsource);
// // FIXME: impossible case. MethodAccess.NORMAL is not saved in the map
// if(type == MethodAccess.NORMAL) {
// return null;
// }
if (!sameTree(caller, node)) {
return null;
}
DirectGraph graph = methsource.getOrBuildGraph();
Exprent source = graph.first.exprents.get(0);
Exprent retexprent = null;
switch (type) {
case FIELD_GET -> {
ExitExprent exsource = (ExitExprent)source;
if (exsource.getValue().type == Exprent.EXPRENT_VAR) { // qualified this
VarExprent var = (VarExprent)exsource.getValue();
String varname = methsource.varproc.getVarName(new VarVersion(var));
if (!methdest.setOuterVarNames.contains(varname)) {
VarNamesCollector vnc = new VarNamesCollector();
vnc.addName(varname);
methdest.varproc.refreshVarNames(vnc);
methdest.setOuterVarNames.add(varname);
}
int index = methdest.counter.getCounterAndIncrement(CounterContainer.VAR_COUNTER);
VarExprent ret = new VarExprent(index, var.getVarType(), methdest.varproc);
methdest.varproc.setVarName(new VarVersion(index, 0), varname);
retexprent = ret;
}
else { // field
FieldExprent ret = (FieldExprent)exsource.getValue().copy();
if (!ret.isStatic()) {
ret.replaceExprent(ret.getInstance(), invexpr.getParameters().get(0));
}
retexprent = ret;
}
}
case FIELD_SET -> {
AssignmentExprent ret;
if (source.type == Exprent.EXPRENT_EXIT) {
ExitExprent extex = (ExitExprent)source;
ret = (AssignmentExprent)extex.getValue().copy();
}
else {
ret = (AssignmentExprent)source.copy();
}
FieldExprent fexpr = (FieldExprent)ret.getLeft();
if (fexpr.isStatic()) {
ret.replaceExprent(ret.getRight(), invexpr.getParameters().get(0));
}
else {
ret.replaceExprent(ret.getRight(), invexpr.getParameters().get(1));
fexpr.replaceExprent(fexpr.getInstance(), invexpr.getParameters().get(0));
}
// do not use copied bytecodes
ret.getLeft().bytecode = null;
ret.getRight().bytecode = null;
retexprent = ret;
}
case FUNCTION -> retexprent = replaceFunction(invexpr, source);
case METHOD -> {
if (source.type == Exprent.EXPRENT_EXIT) {
source = ((ExitExprent)source).getValue();
}
InvocationExprent invret = (InvocationExprent)source.copy();
int index = 0;
if (!invret.isStatic()) {
invret.replaceExprent(invret.getInstance(), invexpr.getParameters().get(0));
index = 1;
}
for (int i = 0; i < invret.getParameters().size(); i++) {
invret.replaceExprent(invret.getParameters().get(i), invexpr.getParameters().get(i + index));
}
retexprent = invret;
}
}
if (retexprent != null) {
// preserve original bytecodes
retexprent.bytecode = null;
retexprent.addBytecodeOffsets(invexpr.bytecode);
// hide synthetic access method
boolean hide = true;
if (node.type == ClassNode.CLASS_ROOT || (node.access & CodeConstants.ACC_STATIC) != 0) {
StructMethod mt = methsource.methodStruct;
if (!mt.isSynthetic()) {
hide = false;
}
}
if (hide) {
node.getWrapper().getHiddenMembers().add(InterpreterUtil.makeUniqueKey(invexpr.getName(), invexpr.getStringDescriptor()));
}
}
return retexprent;
}