Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expose lvt LocalVariable to renaming plugins, add simple renamer that fixes conflicting lvt names #371

Draft
wants to merge 1 commit into
base: develop/1.11.0
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,13 @@

import org.jetbrains.java.decompiler.code.CodeConstants;
import org.jetbrains.java.decompiler.main.DecompilerContext;
import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences;
import org.jetbrains.java.decompiler.main.extern.IVariableNameProvider;
import org.jetbrains.java.decompiler.main.extern.IVariableNamingFactory;
import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor;
import org.jetbrains.java.decompiler.modules.decompiler.vars.VarVersionPair;
import org.jetbrains.java.decompiler.struct.StructMethod;
import org.jetbrains.java.decompiler.struct.gen.MethodDescriptor;
import org.jetbrains.java.decompiler.struct.gen.VarType;
import org.jetbrains.java.decompiler.util.Pair;

public class JADNameProvider implements IVariableNameProvider {
private HashMap<String, Holder> last;
Expand Down Expand Up @@ -103,7 +101,7 @@ public Holder(int t1, boolean skip_zero, List<String> names) {
}

@Override
public Map<VarVersionPair,String> rename(Map<VarVersionPair, Pair<VarType, String>> entries) {
public Map<VarVersionPair,String> renameVariables(Map<VarVersionPair, VariableNamingData> entries) {
int params = 0;
if ((this.method.getAccessFlags() & CodeConstants.ACC_STATIC) != CodeConstants.ACC_STATIC) {
params++;
Expand All @@ -119,7 +117,7 @@ public Map<VarVersionPair,String> rename(Map<VarVersionPair, Pair<VarType, Strin

Map<VarVersionPair, String> result = new LinkedHashMap<>();
for (VarVersionPair ver : keys) {
String type = cleanType(entries.get(ver).b);
String type = cleanType(entries.get(ver).typeName());
if ("this".equals(type)) {
continue;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package org.vineflower.variablerenaming;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.jetbrains.java.decompiler.code.CodeConstants;
import org.jetbrains.java.decompiler.main.DecompilerContext;
import org.jetbrains.java.decompiler.main.extern.IVariableNameProvider;
import org.jetbrains.java.decompiler.main.extern.IVariableNamingFactory;
import org.jetbrains.java.decompiler.modules.decompiler.vars.VarVersionPair;
import org.jetbrains.java.decompiler.struct.StructMethod;
import org.jetbrains.java.decompiler.struct.gen.MethodDescriptor;
import org.jetbrains.java.decompiler.struct.gen.VarType;

public class SimpleNameProvider implements IVariableNameProvider {
private final boolean renameParameters;
private final StructMethod method;
private final Map<String, Integer> usedNames = new HashMap<>();
private final Map<Integer, String> parameters = new HashMap<>();

public SimpleNameProvider(boolean renameParameters, StructMethod method) {
this.renameParameters = renameParameters;
this.method = method;
}

@Override
public Map<VarVersionPair, String> renameVariables(Map<VarVersionPair, VariableNamingData> entries) {
int params = 0;
if ((this.method.getAccessFlags() & CodeConstants.ACC_STATIC) != CodeConstants.ACC_STATIC) {
params++;
}

MethodDescriptor md = MethodDescriptor.parseDescriptor(this.method.getDescriptor());
for (VarType param : md.params) {
params += param.stackSize;
}

List<VarVersionPair> keys = new ArrayList<>(entries.keySet());
Collections.sort(keys, (o1, o2) -> (o1.var != o2.var) ? o1.var - o2.var : o1.version - o2.version);

Map<VarVersionPair, String> result = new LinkedHashMap<>();
for (VarVersionPair ver : keys) {
String origName = entries.get(ver).lvt().getName();
if (origName == null) {
origName = "lv";
}
final String origNameFinal = origName;
if (ver.var >= params) {
this.method.getLocalVariableAttr().getMapNames();
result.put(ver, getNewName(origNameFinal));
} else if (renameParameters) {
result.put(ver, this.parameters.computeIfAbsent(ver.var, k -> getNewName(origNameFinal)));
}
}

return result;
}

private String getNewName(String name) {
int timesUsed = this.usedNames.compute(name, (k, v) -> v == null ? 1 : v + 1);
if (timesUsed == 1) {
return name;
}
return name + (timesUsed - 2);
}

@Override
public String renameParameter(int flags, VarType type, String name, int index) {
if (!this.renameParameters) {
return IVariableNameProvider.super.renameParameter(flags, type, name, index);
}
return this.parameters.computeIfAbsent(index, k -> getNewName(name));
}

@Override
public void addParentContext(IVariableNameProvider renamer) {
if (renamer instanceof SimpleNameProvider s) {
s.usedNames.forEach((k, v) -> this.usedNames.merge(k, v, Integer::sum));
}
}

public static class SimpleNameProviderFactory implements IVariableNamingFactory {

@Override
public IVariableNameProvider createFactory(StructMethod structMethod) {
return new SimpleNameProvider(
DecompilerContext.getOption(VariableRenamingOptions.RENAME_PARAMETERS), structMethod);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import org.jetbrains.java.decompiler.code.CodeConstants;
import org.jetbrains.java.decompiler.main.DecompilerContext;
import org.jetbrains.java.decompiler.main.collectors.ImportCollector;
import org.jetbrains.java.decompiler.main.extern.IVariableNameProvider;
import org.jetbrains.java.decompiler.main.extern.IVariableNamingFactory;
import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor;
Expand All @@ -29,7 +28,7 @@ public TinyNameProvider(boolean renameParameters, StructMethod method) {
}

@Override
public Map<VarVersionPair, String> rename(Map<VarVersionPair, Pair<VarType, String>> entries) {
public Map<VarVersionPair, String> renameVariables(Map<VarVersionPair, VariableNamingData> entries) {
int params = 0;
if ((this.method.getAccessFlags() & CodeConstants.ACC_STATIC) != CodeConstants.ACC_STATIC) {
params++;
Expand All @@ -45,12 +44,12 @@ public Map<VarVersionPair, String> rename(Map<VarVersionPair, Pair<VarType, Stri

Map<VarVersionPair, String> result = new LinkedHashMap<>();
for (VarVersionPair ver : keys) {
String type = cleanType(entries.get(ver).b);
String type = cleanType(entries.get(ver).typeName());

if (ver.var >= params) {
result.put(ver, getNewName(Pair.of(entries.get(ver).a, type)));
result.put(ver, getNewName(Pair.of(entries.get(ver).type(), type)));
} else if (renameParameters) {
result.put(ver, this.parameters.computeIfAbsent(ver.var, k -> getNewName(Pair.of(entries.get(ver).a, type))));
result.put(ver, this.parameters.computeIfAbsent(ver.var, k -> getNewName(Pair.of(entries.get(ver).type(), type))));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,6 @@ public String description() {
static {
Renamers.registerProvider("jad", new JADNameProvider.JADNameProviderFactory());
Renamers.registerProvider("tiny", new TinyNameProvider.TinyNameProviderFactory());
Renamers.registerProvider("fix_clashing_lvt", new SimpleNameProvider.SimpleNameProviderFactory());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@
import org.jetbrains.java.decompiler.main.extern.IVariableNamingFactory;
import org.jetbrains.java.decompiler.modules.decompiler.vars.VarVersionPair;
import org.jetbrains.java.decompiler.struct.StructMethod;
import org.jetbrains.java.decompiler.struct.gen.VarType;
import org.jetbrains.java.decompiler.util.Pair;

public class IdentityRenamerFactory implements IVariableNamingFactory, IVariableNameProvider {
@Override
Expand All @@ -31,7 +29,7 @@ public IVariableNameProvider createFactory(StructMethod method) {
}

@Override
public Map<VarVersionPair, String> rename(Map<VarVersionPair, Pair<VarType, String>> variables) {
public Map<VarVersionPair, String> renameVariables(Map<VarVersionPair, VariableNamingData> variables) {
return null;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,38 @@

import java.util.Map;

import java.util.stream.Collectors;
import org.jetbrains.java.decompiler.code.CodeConstants;
import org.jetbrains.java.decompiler.modules.decompiler.vars.VarVersionPair;
import org.jetbrains.java.decompiler.struct.attr.StructLocalVariableTableAttribute;
import org.jetbrains.java.decompiler.struct.gen.VarType;
import org.jetbrains.java.decompiler.util.Pair;

public interface IVariableNameProvider {
Map<VarVersionPair, String> rename(Map<VarVersionPair, Pair<VarType, String>> variables);
interface VariableNamingData {
VarType type();
String typeName();
StructLocalVariableTableAttribute.LocalVariable lvt();
}

default Map<VarVersionPair, String> renameVariables(Map<VarVersionPair, VariableNamingData> variables) {
return this.rename(variables.entrySet().stream().collect(Collectors.toMap(
Map.Entry::getKey,
e -> Pair.of(e.getValue().type(), e.getValue().typeName())
)));
}

/**
* Renames the variables.
*
* @param variables variables
* @return map of variable pairs to new names
* @deprecated implement {@link #renameVariables(Map)} instead. this method exists for backwards ABI compatibility
*/
@Deprecated
default Map<VarVersionPair, String> rename(Map<VarVersionPair, Pair<VarType, String>> variables) {
throw new UnsupportedOperationException();
}

default String renameAbstractParameter(String name, int index) {
return name;
Expand All @@ -36,5 +61,6 @@ default String renameParameter(int flags, VarType type, String name, int index)

return name;
}

public void addParentContext(IVariableNameProvider renamer);
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import org.jetbrains.java.decompiler.main.DecompilerContext;
import org.jetbrains.java.decompiler.main.collectors.VarNamesCollector;
import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences;
import org.jetbrains.java.decompiler.main.extern.IVariableNameProvider;
import org.jetbrains.java.decompiler.main.rels.MethodWrapper;
import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor;
import org.jetbrains.java.decompiler.modules.decompiler.ValidationHelper;
Expand All @@ -17,6 +18,7 @@
import org.jetbrains.java.decompiler.struct.StructClass;
import org.jetbrains.java.decompiler.struct.StructMethod;
import org.jetbrains.java.decompiler.struct.attr.StructGeneralAttribute;
import org.jetbrains.java.decompiler.struct.attr.StructLocalVariableTableAttribute;
import org.jetbrains.java.decompiler.struct.attr.StructLocalVariableTableAttribute.LocalVariable;
import org.jetbrains.java.decompiler.struct.attr.StructMethodParametersAttribute;
import org.jetbrains.java.decompiler.struct.gen.CodeType;
Expand All @@ -26,7 +28,6 @@
import org.jetbrains.java.decompiler.struct.gen.generics.GenericType;
import org.jetbrains.java.decompiler.util.ArrayHelper;
import org.jetbrains.java.decompiler.util.InterpreterUtil;
import org.jetbrains.java.decompiler.util.Pair;
import org.jetbrains.java.decompiler.util.StatementIterator;

import java.util.*;
Expand Down Expand Up @@ -997,6 +998,12 @@ private VarType getMergedType(VarType fromMin, VarType toMin, VarType fromMax, V
}
}

record VariableNamingDataImpl(
VarType type,
String typeName,
StructLocalVariableTableAttribute.LocalVariable lvt
) implements IVariableNameProvider.VariableNamingData {}

private void propogateLVTs(Statement stat) {
MethodDescriptor md = MethodDescriptor.parseDescriptor(mt.getDescriptor());
Map<VarVersionPair, VarInfo> types = new LinkedHashMap<>();
Expand All @@ -1022,12 +1029,12 @@ private void propogateLVTs(Statement stat) {

findTypes(stat, types);

Map<VarVersionPair, Pair<VarType, String>> typeNames = new LinkedHashMap<>();
Map<VarVersionPair, IVariableNameProvider.VariableNamingData> typeNames = new LinkedHashMap<>();
for (Entry<VarVersionPair, VarInfo> e : types.entrySet()) {
typeNames.put(e.getKey(), Pair.of(e.getValue().getType(), e.getValue().getCast()));
typeNames.put(e.getKey(), new VariableNamingDataImpl(e.getValue().getType(), e.getValue().getCast(), e.getValue().getLVT()));
}

Map<VarVersionPair, String> renames = this.mt.getVariableNamer().rename(typeNames);
Map<VarVersionPair, String> renames = this.mt.getVariableNamer().renameVariables(typeNames);

Set<StructMethod> methods = new HashSet<>();

Expand Down
Loading