Skip to content
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
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ jobs:
build:
strategy:
matrix:
java: [11, 17, 19]
java: [17, 21]
runs-on: ubuntu-22.04
container:
image: eclipse-temurin:${{ matrix.java }}
Expand Down
8 changes: 4 additions & 4 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,12 @@ allprojects {
group = 'org.vineflower'

compileJava {
sourceCompatibility = '11'
targetCompatibility = '11'
sourceCompatibility = '17'
targetCompatibility = '17'
}

java.toolchain {
languageVersion = JavaLanguageVersion.of(11)
languageVersion = JavaLanguageVersion.of(17)
}

repositories {
Expand All @@ -56,7 +56,7 @@ allprojects {
group = 'org.vineflower'
archivesBaseName = 'vineflower'

version = '1.10.0'
version = '1.11.0'

def ENV = System.getenv()
version = version + (ENV.GITHUB_ACTIONS ? "" : "+local")
Expand Down
8 changes: 4 additions & 4 deletions plugins/kotlin/testData/results/pkg/TestTailrecFunctions.dec
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,9 @@ class TestTailrecFunctions {
var var12: Long = acc;

while (var10 != 0L) {// 44
if (var10 % (long)2 == 0L) {// 45
if (var10 % 2 == 0L) {// 45
var var21: Long = var8 * var8;
var var23: Long = var10 / (long)2;
var var23: Long = var10 / 2;
var7 = var7;
var8 = var21;
var10 = var23;
Expand Down Expand Up @@ -117,13 +117,13 @@ class TestTailrecFunctions {
break;
}

if (var8 % (long)2 != 0L) {// 51
if (var8 % 2 != 0L) {// 51
var10000 = var6 * var5.fastPow(var6, var8 - 1L);// 52
break;
}

var var15: Long = var6 * var6;
var var17: Long = var8 / (long)2;
var var17: Long = var8 / 2;
var5 = var5;
var6 = var15;
var8 = var17;
Expand Down
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 @@ -13,6 +13,7 @@ protected void registerAll() {
register(JAVA_8, "TestJADNaming");
// TODO: loop part fails
registerRaw(CUSTOM, "TestJadLvtCollision"); // created by placing a class in java8 sources and remapping its param using tinyremapper
register(JAVA_8, "TestJADLocalClasses");
}, IFernflowerPreferences.BYTECODE_SOURCE_MAPPING, "1",
IFernflowerPreferences.DUMP_ORIGINAL_LINES, "1",
IFernflowerPreferences.DUMP_EXCEPTION_ON_ERROR, "0",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package pkg;

public class TestJADLocalClasses {
public void function() {
int i = 0;// 5

class Test {
Test() {
int j = 0;// 8
}// 9
}

}// 11
}

class 'pkg/TestJADLocalClasses' {
method 'function ()V' {
0 4
1 4
2 12
}
}

class 'pkg/TestJADLocalClasses$1Test' {
method '<init> (Lpkg/TestJADLocalClasses;)V' {
9 8
a 8
b 9
}
}

Lines mapping:
5 <-> 5
8 <-> 9
9 <-> 10
11 <-> 13
Not mapped:
7
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package pkg;

public class TestJADLocalClasses {
public void function() {
int a = 0;
class Test {
Test() {
int b = 0;
}
}
}
}
6 changes: 5 additions & 1 deletion src/org/jetbrains/java/decompiler/code/BytecodeVersion.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public boolean hasSwitchExpressions() {
}

public boolean hasSwitchPatternMatch() {
return previewFrom(MAJOR_17);
return previewReleased(MAJOR_17, MAJOR_21);
}

public boolean hasSealedClasses() {
Expand Down Expand Up @@ -112,4 +112,8 @@ public int hashCode() {
public static final int MAJOR_15 = 59;
public static final int MAJOR_16 = 60;
public static final int MAJOR_17 = 61;
public static final int MAJOR_18 = 62;
public static final int MAJOR_19 = 63;
public static final int MAJOR_20 = 64;
public static final int MAJOR_21 = 65;
}
2 changes: 1 addition & 1 deletion src/org/jetbrains/java/decompiler/main/ClassWriter.java
Original file line number Diff line number Diff line change
Expand Up @@ -1208,7 +1208,7 @@ else if (methodWrapper.varproc.getVarFinal(new VarVersionPair(index, 0)) == VarT
String clashingName = methodWrapper.varproc.getClashingName(new VarVersionPair(index, 0));
if (clashingName != null) {
parameterName = clashingName;
} else if (methodParameters != null && i < methodParameters.size()) {
} else if (methodParameters != null && i < methodParameters.size() && methodParameters.get(i).myName != null) {
parameterName = methodParameters.get(i).myName;
} else {
parameterName = methodWrapper.varproc.getVarName(new VarVersionPair(index, 0));
Expand Down
16 changes: 13 additions & 3 deletions src/org/jetbrains/java/decompiler/main/ClassesProcessor.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@
import java.util.*;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class ClassesProcessor implements CodeConstants {
public static final int AVERAGE_CLASS_SIZE = 16 * 1024;
Expand Down Expand Up @@ -94,8 +96,17 @@ public void loadClasses(IIdentifierRenamer renamer) {
boolean bDecompileInner = DecompilerContext.getOption(IFernflowerPreferences.DECOMPILE_INNER);
boolean verifyAnonymousClasses = DecompilerContext.getOption(IFernflowerPreferences.VERIFY_ANONYMOUS_CLASSES);

Matcher excludedMatcher = null;
String excludedRegex = DecompilerContext.getProperty(IFernflowerPreferences.EXCLUDED_CLASSES).toString();
if (!excludedRegex.isEmpty()) {
excludedMatcher = Pattern.compile(excludedRegex).matcher("");
}

// create class nodes
for (StructClass cl : context.getOwnClasses()) {
if (excludedMatcher != null && excludedMatcher.reset(cl.qualifiedName).matches()) {
continue;
}
if (!mapRootClasses.containsKey(cl.qualifiedName)) {
if (bDecompileInner) {
StructInnerClassesAttribute inner = cl.getAttribute(StructGeneralAttribute.ATTRIBUTE_INNER_CLASSES);
Expand Down Expand Up @@ -563,9 +574,8 @@ private static void destroyWrappers(ClassNode node) {
node.classStruct.releaseResources();
node.classStruct.getMethods().forEach(m -> m.clearVariableNamer());

for (ClassNode nd : node.nested) {
destroyWrappers(nd);
}
// Don't destroy inner node wrappers, they may still be needed to process constructor
// invocations etc. from other classes.
}

public Map<String, ClassNode> getMapRootClasses() {
Expand Down
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
Loading