[java decompiler] reworks setting/accessing decompiler context

master
Roman Shevchenko 7 years ago
parent fbc3165138
commit 71d8f4d689
  1. 23
      src/org/jetbrains/java/decompiler/main/ClassesProcessor.java
  2. 152
      src/org/jetbrains/java/decompiler/main/DecompilerContext.java
  3. 68
      src/org/jetbrains/java/decompiler/main/Fernflower.java
  4. 5
      src/org/jetbrains/java/decompiler/main/collectors/CounterContainer.java
  5. 7
      src/org/jetbrains/java/decompiler/main/decompiler/BaseDecompiler.java
  6. 6
      src/org/jetbrains/java/decompiler/main/decompiler/ConsoleDecompiler.java
  7. 19
      src/org/jetbrains/java/decompiler/main/rels/ClassWrapper.java
  8. 9
      src/org/jetbrains/java/decompiler/main/rels/MethodProcessorRunnable.java
  9. 2
      src/org/jetbrains/java/decompiler/modules/decompiler/exps/Exprent.java
  10. 7
      src/org/jetbrains/java/decompiler/modules/decompiler/stats/CatchAllStatement.java
  11. 5
      src/org/jetbrains/java/decompiler/modules/decompiler/stats/CatchStatement.java
  12. 5
      src/org/jetbrains/java/decompiler/modules/decompiler/vars/VarDefinitionHelper.java
  13. 5
      src/org/jetbrains/java/decompiler/modules/decompiler/vars/VarProcessor.java
  14. 40
      src/org/jetbrains/java/decompiler/modules/renamer/IdentifierConverter.java
  15. 21
      src/org/jetbrains/java/decompiler/modules/renamer/PoolInterceptor.java
  16. 7
      test/org/jetbrains/java/decompiler/DecompilerTestFixture.java

@ -3,7 +3,6 @@ package org.jetbrains.java.decompiler.main;
import org.jetbrains.java.decompiler.code.CodeConstants; import org.jetbrains.java.decompiler.code.CodeConstants;
import org.jetbrains.java.decompiler.main.collectors.BytecodeSourceMapper; import org.jetbrains.java.decompiler.main.collectors.BytecodeSourceMapper;
import org.jetbrains.java.decompiler.main.collectors.CounterContainer;
import org.jetbrains.java.decompiler.main.collectors.ImportCollector; import org.jetbrains.java.decompiler.main.collectors.ImportCollector;
import org.jetbrains.java.decompiler.main.extern.IFernflowerLogger; import org.jetbrains.java.decompiler.main.extern.IFernflowerLogger;
import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences; import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences;
@ -28,6 +27,7 @@ import java.util.Map.Entry;
public class ClassesProcessor { public class ClassesProcessor {
public static final int AVERAGE_CLASS_SIZE = 16 * 1024; public static final int AVERAGE_CLASS_SIZE = 16 * 1024;
private final StructContext context;
private final Map<String, ClassNode> mapRootClasses = new HashMap<>(); private final Map<String, ClassNode> mapRootClasses = new HashMap<>();
private static class Inner { private static class Inner {
@ -41,6 +41,10 @@ public class ClassesProcessor {
} }
public ClassesProcessor(StructContext context) { public ClassesProcessor(StructContext context) {
this.context = context;
}
public void loadClasses(IIdentifierRenamer renamer) {
Map<String, Inner> mapInnerClasses = new HashMap<>(); Map<String, Inner> mapInnerClasses = new HashMap<>();
Map<String, Set<String>> mapNestedClassReferences = new HashMap<>(); Map<String, Set<String>> mapNestedClassReferences = new HashMap<>();
Map<String, Set<String>> mapEnclosingClassReferences = new HashMap<>(); Map<String, Set<String>> mapEnclosingClassReferences = new HashMap<>();
@ -64,12 +68,11 @@ public class ClassesProcessor {
if (savedName != null) { if (savedName != null) {
simpleName = savedName; simpleName = savedName;
} }
else if (simpleName != null && DecompilerContext.getOption(IFernflowerPreferences.RENAME_ENTITIES)) { else if (simpleName != null &&
IIdentifierRenamer renamer = DecompilerContext.getPoolInterceptor().getHelper(); renamer != null &&
if (renamer.toBeRenamed(IIdentifierRenamer.Type.ELEMENT_CLASS, simpleName, null, null)) { renamer.toBeRenamed(IIdentifierRenamer.Type.ELEMENT_CLASS, simpleName, null, null)) {
simpleName = renamer.getNextClassName(innerName, simpleName); simpleName = renamer.getNextClassName(innerName, simpleName);
mapNewSimpleNames.put(innerName, simpleName); mapNewSimpleNames.put(innerName, simpleName);
}
} }
Inner rec = new Inner(); Inner rec = new Inner();
@ -223,9 +226,7 @@ public class ClassesProcessor {
DecompilerContext.getLogger().startReadingClass(cl.qualifiedName); DecompilerContext.getLogger().startReadingClass(cl.qualifiedName);
try { try {
ImportCollector importCollector = new ImportCollector(root); ImportCollector importCollector = new ImportCollector(root);
DecompilerContext.setImportCollector(importCollector); DecompilerContext.startClass(importCollector);
DecompilerContext.setCounterContainer(new CounterContainer());
DecompilerContext.setBytecodeSourceMapper(new BytecodeSourceMapper());
new LambdaProcessor().processClass(root); new LambdaProcessor().processClass(root);
@ -418,4 +419,4 @@ public class ClassesProcessor {
public boolean is_content_method_static; public boolean is_content_method_static;
} }
} }
} }

@ -4,142 +4,142 @@ package org.jetbrains.java.decompiler.main;
import org.jetbrains.java.decompiler.main.collectors.BytecodeSourceMapper; import org.jetbrains.java.decompiler.main.collectors.BytecodeSourceMapper;
import org.jetbrains.java.decompiler.main.collectors.CounterContainer; import org.jetbrains.java.decompiler.main.collectors.CounterContainer;
import org.jetbrains.java.decompiler.main.collectors.ImportCollector; import org.jetbrains.java.decompiler.main.collectors.ImportCollector;
import org.jetbrains.java.decompiler.main.collectors.VarNamesCollector;
import org.jetbrains.java.decompiler.main.extern.IFernflowerLogger; import org.jetbrains.java.decompiler.main.extern.IFernflowerLogger;
import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences; import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences;
import org.jetbrains.java.decompiler.modules.decompiler.vars.VarProcessor;
import org.jetbrains.java.decompiler.modules.renamer.PoolInterceptor; import org.jetbrains.java.decompiler.modules.renamer.PoolInterceptor;
import org.jetbrains.java.decompiler.struct.StructContext; import org.jetbrains.java.decompiler.struct.StructContext;
import java.util.HashMap; import java.util.HashMap;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.Objects;
public class DecompilerContext { public class DecompilerContext {
public static final String CURRENT_CLASS = "CURRENT_CLASS"; public static final String CURRENT_CLASS = "CURRENT_CLASS";
public static final String CURRENT_CLASS_WRAPPER = "CURRENT_CLASS_WRAPPER"; public static final String CURRENT_CLASS_WRAPPER = "CURRENT_CLASS_WRAPPER";
public static final String CURRENT_CLASS_NODE = "CURRENT_CLASS_NODE"; public static final String CURRENT_CLASS_NODE = "CURRENT_CLASS_NODE";
public static final String CURRENT_METHOD_WRAPPER = "CURRENT_METHOD_WRAPPER"; public static final String CURRENT_METHOD_WRAPPER = "CURRENT_METHOD_WRAPPER";
public static final String CURRENT_VAR_PROCESSOR = "CURRENT_VAR_PROCESSOR";
private static final ThreadLocal<DecompilerContext> currentContext = new ThreadLocal<>(); private static volatile DecompilerContext currentContext = null;
private final Map<String, Object> properties; private final Map<String, Object> properties;
private StructContext structContext; private final IFernflowerLogger logger;
private final StructContext structContext;
private final ClassesProcessor classProcessor;
private final PoolInterceptor poolInterceptor;
private ImportCollector importCollector; private ImportCollector importCollector;
private VarNamesCollector varNamescollector; private VarProcessor varProcessor;
private CounterContainer counterContainer; private CounterContainer counterContainer;
private ClassesProcessor classProcessor;
private PoolInterceptor poolInterceptor;
private IFernflowerLogger logger;
private BytecodeSourceMapper bytecodeSourceMapper; private BytecodeSourceMapper bytecodeSourceMapper;
private DecompilerContext(Map<String, Object> properties) { private DecompilerContext(Map<String, Object> properties,
IFernflowerLogger logger,
StructContext structContext,
ClassesProcessor classProcessor,
PoolInterceptor interceptor) {
this.properties = properties; this.properties = properties;
} this.logger = logger;
this.structContext = structContext;
this.classProcessor = classProcessor;
this.poolInterceptor = interceptor;
this.counterContainer = new CounterContainer();
}
// *****************************************************************************
// context setup and update
// *****************************************************************************
public static void initContext(Map<String, Object> customProperties,
IFernflowerLogger logger,
StructContext structContext,
ClassesProcessor classProcessor,
PoolInterceptor interceptor) {
Objects.requireNonNull(logger);
Objects.requireNonNull(structContext);
Objects.requireNonNull(classProcessor);
public static void initContext(Map<String, Object> propertiesCustom) {
Map<String, Object> properties = new HashMap<>(IFernflowerPreferences.DEFAULTS); Map<String, Object> properties = new HashMap<>(IFernflowerPreferences.DEFAULTS);
if (propertiesCustom != null) { if (customProperties != null) {
properties.putAll(propertiesCustom); properties.putAll(customProperties);
} }
currentContext.set(new DecompilerContext(properties));
}
public static DecompilerContext getCurrentContext() { String level = (String)properties.get(IFernflowerPreferences.LOG_LEVEL);
return currentContext.get(); if (level != null) {
} try {
logger.setSeverity(IFernflowerLogger.Severity.valueOf(level.toUpperCase(Locale.US)));
}
catch (IllegalArgumentException ignore) { }
}
public static void setCurrentContext(DecompilerContext context) { currentContext = new DecompilerContext(properties, logger, structContext, classProcessor, interceptor);
currentContext.set(context);
} }
public static Object getProperty(String key) { public static void clearContext() {
return getCurrentContext().properties.get(key); currentContext = null;
} }
public static void setProperty(String key, Object value) { public static void setProperty(String key, Object value) {
getCurrentContext().properties.put(key, value); currentContext.properties.put(key, value);
}
public static boolean getOption(String key) {
return "1".equals(getCurrentContext().properties.get(key));
} }
public static ImportCollector getImportCollector() { public static void startClass(ImportCollector importCollector) {
return getCurrentContext().importCollector; currentContext.importCollector = importCollector;
currentContext.counterContainer = new CounterContainer();
currentContext.bytecodeSourceMapper = new BytecodeSourceMapper();
} }
public static void setImportCollector(ImportCollector importCollector) { public static void startMethod(VarProcessor varProcessor) {
getCurrentContext().importCollector = importCollector; currentContext.varProcessor = varProcessor;
currentContext.counterContainer = new CounterContainer();
} }
public static VarNamesCollector getVarNamesCollector() { // *****************************************************************************
return getCurrentContext().varNamescollector; // context access
} // *****************************************************************************
public static void setVarNamesCollector(VarNamesCollector varNamesCollector) { public static Object getProperty(String key) {
getCurrentContext().varNamescollector = varNamesCollector; return currentContext.properties.get(key);
} }
public static StructContext getStructContext() { public static boolean getOption(String key) {
return getCurrentContext().structContext; return "1".equals(getProperty(key));
} }
public static void setStructContext(StructContext structContext) { public static String getNewLineSeparator() {
getCurrentContext().structContext = structContext; return getOption(IFernflowerPreferences.NEW_LINE_SEPARATOR) ?
IFernflowerPreferences.LINE_SEPARATOR_UNX : IFernflowerPreferences.LINE_SEPARATOR_WIN;
} }
public static CounterContainer getCounterContainer() { public static IFernflowerLogger getLogger() {
return getCurrentContext().counterContainer; return currentContext.logger;
} }
public static void setCounterContainer(CounterContainer counterContainer) { public static StructContext getStructContext() {
getCurrentContext().counterContainer = counterContainer; return currentContext.structContext;
} }
public static ClassesProcessor getClassProcessor() { public static ClassesProcessor getClassProcessor() {
return getCurrentContext().classProcessor; return currentContext.classProcessor;
}
public static void setClassProcessor(ClassesProcessor classProcessor) {
getCurrentContext().classProcessor = classProcessor;
} }
public static PoolInterceptor getPoolInterceptor() { public static PoolInterceptor getPoolInterceptor() {
return getCurrentContext().poolInterceptor; return currentContext.poolInterceptor;
}
public static void setPoolInterceptor(PoolInterceptor poolinterceptor) {
getCurrentContext().poolInterceptor = poolinterceptor;
}
public static BytecodeSourceMapper getBytecodeSourceMapper() {
return getCurrentContext().bytecodeSourceMapper;
} }
public static void setBytecodeSourceMapper(BytecodeSourceMapper bytecodeSourceMapper) { public static ImportCollector getImportCollector() {
getCurrentContext().bytecodeSourceMapper = bytecodeSourceMapper; return currentContext.importCollector;
} }
public static IFernflowerLogger getLogger() { public static VarProcessor getVarProcessor() {
return getCurrentContext().logger; return currentContext.varProcessor;
} }
public static void setLogger(IFernflowerLogger logger) { public static CounterContainer getCounterContainer() {
if (logger != null) { return currentContext.counterContainer;
String level = (String)getProperty(IFernflowerPreferences.LOG_LEVEL);
if (level != null) {
try {
logger.setSeverity(IFernflowerLogger.Severity.valueOf(level.toUpperCase(Locale.US)));
}
catch (IllegalArgumentException ignore) { }
}
}
getCurrentContext().logger = logger;
} }
public static String getNewLineSeparator() { public static BytecodeSourceMapper getBytecodeSourceMapper() {
return getOption(IFernflowerPreferences.NEW_LINE_SEPARATOR) ? return currentContext.bytecodeSourceMapper;
IFernflowerPreferences.LINE_SEPARATOR_UNX : IFernflowerPreferences.LINE_SEPARATOR_WIN;
} }
} }

@ -2,12 +2,10 @@
package org.jetbrains.java.decompiler.main; package org.jetbrains.java.decompiler.main;
import org.jetbrains.java.decompiler.main.ClassesProcessor.ClassNode; import org.jetbrains.java.decompiler.main.ClassesProcessor.ClassNode;
import org.jetbrains.java.decompiler.main.collectors.CounterContainer; import org.jetbrains.java.decompiler.main.extern.*;
import org.jetbrains.java.decompiler.main.extern.IBytecodeProvider; import org.jetbrains.java.decompiler.modules.renamer.ConverterHelper;
import org.jetbrains.java.decompiler.main.extern.IFernflowerLogger;
import org.jetbrains.java.decompiler.main.extern.IResultSaver;
import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences;
import org.jetbrains.java.decompiler.modules.renamer.IdentifierConverter; import org.jetbrains.java.decompiler.modules.renamer.IdentifierConverter;
import org.jetbrains.java.decompiler.modules.renamer.PoolInterceptor;
import org.jetbrains.java.decompiler.struct.IDecompiledData; import org.jetbrains.java.decompiler.struct.IDecompiledData;
import org.jetbrains.java.decompiler.struct.StructClass; import org.jetbrains.java.decompiler.struct.StructClass;
import org.jetbrains.java.decompiler.struct.StructContext; import org.jetbrains.java.decompiler.struct.StructContext;
@ -16,32 +14,50 @@ import org.jetbrains.java.decompiler.struct.lazy.LazyLoader;
import java.util.Map; import java.util.Map;
public class Fernflower implements IDecompiledData { public class Fernflower implements IDecompiledData {
private final StructContext structContext; private final StructContext structContext;
private ClassesProcessor classesProcessor; private final ClassesProcessor classProcessor;
private IIdentifierRenamer helper;
private IdentifierConverter converter;
public Fernflower(IBytecodeProvider provider, IResultSaver saver, Map<String, Object> options, IFernflowerLogger logger) { public Fernflower(IBytecodeProvider provider, IResultSaver saver, Map<String, Object> options, IFernflowerLogger logger) {
structContext = new StructContext(saver, this, new LazyLoader(provider)); structContext = new StructContext(saver, this, new LazyLoader(provider));
DecompilerContext.initContext(options); classProcessor = new ClassesProcessor(structContext);
DecompilerContext.setCounterContainer(new CounterContainer());
DecompilerContext.setLogger(logger); PoolInterceptor interceptor = null;
Object rename = options.get(IFernflowerPreferences.RENAME_ENTITIES);
if ("1".equals(rename) || rename == null && "1".equals(IFernflowerPreferences.DEFAULTS.get(IFernflowerPreferences.RENAME_ENTITIES))) {
helper = loadHelper((String)options.get(IFernflowerPreferences.USER_RENAMER_CLASS));
interceptor = new PoolInterceptor();
converter = new IdentifierConverter(structContext, helper, interceptor);
}
DecompilerContext.initContext(options, logger, structContext, classProcessor, interceptor);
} }
public void decompileContext() { public void decompileContext() {
if (DecompilerContext.getOption(IFernflowerPreferences.RENAME_ENTITIES)) { if (converter != null) {
new IdentifierConverter().rename(structContext); converter.rename();
} }
classesProcessor = new ClassesProcessor(structContext); classProcessor.loadClasses(helper);
DecompilerContext.setClassProcessor(classesProcessor);
DecompilerContext.setStructContext(structContext);
structContext.saveContext(); structContext.saveContext();
} }
private static IIdentifierRenamer loadHelper(String className) {
if (className != null) {
try {
Class<?> renamerClass = Fernflower.class.getClassLoader().loadClass(className);
return (IIdentifierRenamer) renamerClass.getDeclaredConstructor().newInstance();
}
catch (Exception ignored) { }
}
return new ConverterHelper();
}
public void clearContext() { public void clearContext() {
DecompilerContext.setCurrentContext(null); DecompilerContext.clearContext();
} }
public StructContext getStructContext() { public StructContext getStructContext() {
@ -50,18 +66,16 @@ public class Fernflower implements IDecompiledData {
@Override @Override
public String getClassEntryName(StructClass cl, String entryName) { public String getClassEntryName(StructClass cl, String entryName) {
ClassNode node = classesProcessor.getMapRootClasses().get(cl.qualifiedName); ClassNode node = classProcessor.getMapRootClasses().get(cl.qualifiedName);
if (node.type != ClassNode.CLASS_ROOT) { if (node.type != ClassNode.CLASS_ROOT) {
return null; return null;
} }
else if (converter != null) {
String simpleClassName = cl.qualifiedName.substring(cl.qualifiedName.lastIndexOf('/') + 1);
return entryName.substring(0, entryName.lastIndexOf('/') + 1) + simpleClassName + ".java";
}
else { else {
if (DecompilerContext.getOption(IFernflowerPreferences.RENAME_ENTITIES)) { return entryName.substring(0, entryName.lastIndexOf(".class")) + ".java";
String simple_classname = cl.qualifiedName.substring(cl.qualifiedName.lastIndexOf('/') + 1);
return entryName.substring(0, entryName.lastIndexOf('/') + 1) + simple_classname + ".java";
}
else {
return entryName.substring(0, entryName.lastIndexOf(".class")) + ".java";
}
} }
} }
@ -70,7 +84,7 @@ public class Fernflower implements IDecompiledData {
try { try {
TextBuffer buffer = new TextBuffer(ClassesProcessor.AVERAGE_CLASS_SIZE); TextBuffer buffer = new TextBuffer(ClassesProcessor.AVERAGE_CLASS_SIZE);
buffer.append(DecompilerContext.getProperty(IFernflowerPreferences.BANNER).toString()); buffer.append(DecompilerContext.getProperty(IFernflowerPreferences.BANNER).toString());
classesProcessor.writeClass(cl, buffer); classProcessor.writeClass(cl, buffer);
return buffer.toString(); return buffer.toString();
} }
catch (Throwable ex) { catch (Throwable ex) {
@ -78,4 +92,4 @@ public class Fernflower implements IDecompiledData {
return null; return null;
} }
} }
} }

@ -2,9 +2,8 @@
package org.jetbrains.java.decompiler.main.collectors; package org.jetbrains.java.decompiler.main.collectors;
public class CounterContainer { public class CounterContainer {
public static final int STATEMENT_COUNTER = 0; public static final int STATEMENT_COUNTER = 0;
public static final int EXPRENT_COUNTER = 1; public static final int EXPRESSION_COUNTER = 1;
public static final int VAR_COUNTER = 2; public static final int VAR_COUNTER = 2;
private final int[] values = new int[]{1, 1, 1}; private final int[] values = new int[]{1, 1, 1};
@ -20,4 +19,4 @@ public class CounterContainer {
public int getCounterAndIncrement(int counter) { public int getCounterAndIncrement(int counter) {
return values[counter]++; return values[counter]++;
} }
} }

@ -7,18 +7,17 @@ import org.jetbrains.java.decompiler.main.extern.IFernflowerLogger;
import org.jetbrains.java.decompiler.main.extern.IResultSaver; import org.jetbrains.java.decompiler.main.extern.IResultSaver;
import java.io.File; import java.io.File;
import java.io.IOException;
import java.util.Map; import java.util.Map;
@SuppressWarnings("unused")
public class BaseDecompiler { public class BaseDecompiler {
private final Fernflower fernflower; private final Fernflower fernflower;
public BaseDecompiler(IBytecodeProvider provider, IResultSaver saver, Map<String, Object> options, IFernflowerLogger logger) { public BaseDecompiler(IBytecodeProvider provider, IResultSaver saver, Map<String, Object> options, IFernflowerLogger logger) {
fernflower = new Fernflower(provider, saver, options, logger); fernflower = new Fernflower(provider, saver, options, logger);
} }
public void addSpace(File file, boolean isOwn) throws IOException { public void addSpace(File file, boolean isOwn) {
fernflower.getStructContext().addSpace(file, isOwn); fernflower.getStructContext().addSpace(file, isOwn);
} }
@ -30,4 +29,4 @@ public class BaseDecompiler {
fernflower.clearContext(); fernflower.clearContext();
} }
} }
} }

@ -17,7 +17,6 @@ import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream; import java.util.zip.ZipOutputStream;
public class ConsoleDecompiler implements IBytecodeProvider, IResultSaver { public class ConsoleDecompiler implements IBytecodeProvider, IResultSaver {
@SuppressWarnings("UseOfSystemOutOrSystemErr") @SuppressWarnings("UseOfSystemOutOrSystemErr")
public static void main(String[] args) { public static void main(String[] args) {
if (args.length < 2) { if (args.length < 2) {
@ -102,11 +101,6 @@ public class ConsoleDecompiler implements IBytecodeProvider, IResultSaver {
private final Map<String, ZipOutputStream> mapArchiveStreams = new HashMap<>(); private final Map<String, ZipOutputStream> mapArchiveStreams = new HashMap<>();
private final Map<String, Set<String>> mapArchiveEntries = new HashMap<>(); private final Map<String, Set<String>> mapArchiveEntries = new HashMap<>();
@SuppressWarnings("UseOfSystemOutOrSystemErr")
public ConsoleDecompiler(File destination, Map<String, Object> options) {
this(destination, options, new PrintStreamLogger(System.out));
}
protected ConsoleDecompiler(File destination, Map<String, Object> options, IFernflowerLogger logger) { protected ConsoleDecompiler(File destination, Map<String, Object> options, IFernflowerLogger logger) {
root = destination; root = destination;
fernflower = new Fernflower(this, this, options, logger); fernflower = new Fernflower(this, this, options, logger);

@ -25,7 +25,6 @@ import java.util.List;
import java.util.Set; import java.util.Set;
public class ClassWrapper { public class ClassWrapper {
private final StructClass classStruct; private final StructClass classStruct;
private final Set<String> hiddenMembers = new HashSet<>(); private final Set<String> hiddenMembers = new HashSet<>();
private final VBStyleCollection<Exprent, String> staticFieldInitializers = new VBStyleCollection<>(); private final VBStyleCollection<Exprent, String> staticFieldInitializers = new VBStyleCollection<>();
@ -47,15 +46,12 @@ public class ClassWrapper {
for (StructMethod mt : classStruct.getMethods()) { for (StructMethod mt : classStruct.getMethods()) {
DecompilerContext.getLogger().startMethod(mt.getName() + " " + mt.getDescriptor()); DecompilerContext.getLogger().startMethod(mt.getName() + " " + mt.getDescriptor());
VarNamesCollector vc = new VarNamesCollector();
DecompilerContext.setVarNamesCollector(vc);
CounterContainer counter = new CounterContainer();
DecompilerContext.setCounterContainer(counter);
MethodDescriptor md = MethodDescriptor.parseDescriptor(mt.getDescriptor()); MethodDescriptor md = MethodDescriptor.parseDescriptor(mt.getDescriptor());
VarProcessor varProc = new VarProcessor(mt, md); VarProcessor varProc = new VarProcessor(mt, md);
DecompilerContext.setProperty(DecompilerContext.CURRENT_VAR_PROCESSOR, varProc); DecompilerContext.startMethod(varProc);
VarNamesCollector vc = varProc.getVarNamesCollector();
CounterContainer counter = DecompilerContext.getCounterContainer();
RootStatement root = null; RootStatement root = null;
@ -67,7 +63,7 @@ public class ClassWrapper {
root = MethodProcessorRunnable.codeToJava(mt, md, varProc); root = MethodProcessorRunnable.codeToJava(mt, md, varProc);
} }
else { else {
MethodProcessorRunnable mtProc = new MethodProcessorRunnable(mt, md, varProc, DecompilerContext.getCurrentContext()); MethodProcessorRunnable mtProc = new MethodProcessorRunnable(mt, md, varProc);
Thread mtThread = new Thread(mtProc, "Java decompiler"); Thread mtThread = new Thread(mtProc, "Java decompiler");
long stopAt = System.currentTimeMillis() + maxSec * 1000; long stopAt = System.currentTimeMillis() + maxSec * 1000;
@ -128,9 +124,8 @@ public class ClassWrapper {
} }
} }
catch (Throwable ex) { catch (Throwable ex) {
DecompilerContext.getLogger().writeMessage("Method " + mt.getName() + " " + mt.getDescriptor() + " couldn't be decompiled.", String message = "Method " + mt.getName() + " " + mt.getDescriptor() + " couldn't be decompiled.";
IFernflowerLogger.Severity.WARN, DecompilerContext.getLogger().writeMessage(message, IFernflowerLogger.Severity.WARN, ex);
ex);
isError = true; isError = true;
} }

@ -25,23 +25,19 @@ public class MethodProcessorRunnable implements Runnable {
private final StructMethod method; private final StructMethod method;
private final MethodDescriptor methodDescriptor; private final MethodDescriptor methodDescriptor;
private final VarProcessor varProc; private final VarProcessor varProc;
private final DecompilerContext parentContext;
private volatile RootStatement root; private volatile RootStatement root;
private volatile Throwable error; private volatile Throwable error;
private volatile boolean finished = false; private volatile boolean finished = false;
public MethodProcessorRunnable(StructMethod method, MethodDescriptor methodDescriptor, VarProcessor varProc, DecompilerContext parentContext) { public MethodProcessorRunnable(StructMethod method, MethodDescriptor methodDescriptor, VarProcessor varProc) {
this.method = method; this.method = method;
this.methodDescriptor = methodDescriptor; this.methodDescriptor = methodDescriptor;
this.varProc = varProc; this.varProc = varProc;
this.parentContext = parentContext;
} }
@Override @Override
public void run() { public void run() {
DecompilerContext.setCurrentContext(parentContext);
error = null; error = null;
root = null; root = null;
@ -54,9 +50,6 @@ public class MethodProcessorRunnable implements Runnable {
catch (Throwable ex) { catch (Throwable ex) {
error = ex; error = ex;
} }
finally {
DecompilerContext.setCurrentContext(null);
}
finished = true; finished = true;
synchronized (lock) { synchronized (lock) {

@ -45,7 +45,7 @@ public class Exprent implements IMatchable {
public Exprent(int type) { public Exprent(int type) {
this.type = type; this.type = type;
this.id = DecompilerContext.getCounterContainer().getCounterAndIncrement(CounterContainer.EXPRENT_COUNTER); this.id = DecompilerContext.getCounterContainer().getCounterAndIncrement(CounterContainer.EXPRESSION_COUNTER);
} }
public int getPrecedence() { public int getPrecedence() {

@ -10,7 +10,6 @@ import org.jetbrains.java.decompiler.modules.decompiler.DecHelper;
import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor; import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor;
import org.jetbrains.java.decompiler.modules.decompiler.StatEdge; import org.jetbrains.java.decompiler.modules.decompiler.StatEdge;
import org.jetbrains.java.decompiler.modules.decompiler.exps.VarExprent; import org.jetbrains.java.decompiler.modules.decompiler.exps.VarExprent;
import org.jetbrains.java.decompiler.modules.decompiler.vars.VarProcessor;
import org.jetbrains.java.decompiler.struct.gen.VarType; import org.jetbrains.java.decompiler.struct.gen.VarType;
import java.util.ArrayList; import java.util.ArrayList;
@ -56,7 +55,7 @@ public class CatchAllStatement extends Statement {
vars.add(new VarExprent(DecompilerContext.getCounterContainer().getCounterAndIncrement(CounterContainer.VAR_COUNTER), vars.add(new VarExprent(DecompilerContext.getCounterContainer().getCounterAndIncrement(CounterContainer.VAR_COUNTER),
new VarType(CodeConstants.TYPE_OBJECT, 0, "java/lang/Throwable"), new VarType(CodeConstants.TYPE_OBJECT, 0, "java/lang/Throwable"),
(VarProcessor)DecompilerContext.getProperty(DecompilerContext.CURRENT_VAR_PROCESSOR))); DecompilerContext.getVarProcessor()));
} }
@ -165,14 +164,14 @@ public class CatchAllStatement extends Statement {
if (this.monitor != null) { if (this.monitor != null) {
cas.monitor = new VarExprent(DecompilerContext.getCounterContainer().getCounterAndIncrement(CounterContainer.VAR_COUNTER), cas.monitor = new VarExprent(DecompilerContext.getCounterContainer().getCounterAndIncrement(CounterContainer.VAR_COUNTER),
VarType.VARTYPE_INT, VarType.VARTYPE_INT,
(VarProcessor)DecompilerContext.getProperty(DecompilerContext.CURRENT_VAR_PROCESSOR)); DecompilerContext.getVarProcessor());
} }
if (!this.vars.isEmpty()) { if (!this.vars.isEmpty()) {
// FIXME: WTF??? vars?! // FIXME: WTF??? vars?!
vars.add(new VarExprent(DecompilerContext.getCounterContainer().getCounterAndIncrement(CounterContainer.VAR_COUNTER), vars.add(new VarExprent(DecompilerContext.getCounterContainer().getCounterAndIncrement(CounterContainer.VAR_COUNTER),
new VarType(CodeConstants.TYPE_OBJECT, 0, "java/lang/Throwable"), new VarType(CodeConstants.TYPE_OBJECT, 0, "java/lang/Throwable"),
(VarProcessor)DecompilerContext.getProperty(DecompilerContext.CURRENT_VAR_PROCESSOR))); DecompilerContext.getVarProcessor()));
} }
return cas; return cas;

@ -11,7 +11,6 @@ import org.jetbrains.java.decompiler.modules.decompiler.DecHelper;
import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor; import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor;
import org.jetbrains.java.decompiler.modules.decompiler.StatEdge; import org.jetbrains.java.decompiler.modules.decompiler.StatEdge;
import org.jetbrains.java.decompiler.modules.decompiler.exps.VarExprent; import org.jetbrains.java.decompiler.modules.decompiler.exps.VarExprent;
import org.jetbrains.java.decompiler.modules.decompiler.vars.VarProcessor;
import org.jetbrains.java.decompiler.struct.gen.VarType; import org.jetbrains.java.decompiler.struct.gen.VarType;
import java.util.ArrayList; import java.util.ArrayList;
@ -49,7 +48,7 @@ public class CatchStatement extends Statement {
vars.add(new VarExprent(DecompilerContext.getCounterContainer().getCounterAndIncrement(CounterContainer.VAR_COUNTER), vars.add(new VarExprent(DecompilerContext.getCounterContainer().getCounterAndIncrement(CounterContainer.VAR_COUNTER),
new VarType(CodeConstants.TYPE_OBJECT, 0, edge.getExceptions().get(0)), new VarType(CodeConstants.TYPE_OBJECT, 0, edge.getExceptions().get(0)),
// FIXME: for now simply the first type. Should get the first common superclass when possible. // FIXME: for now simply the first type. Should get the first common superclass when possible.
(VarProcessor)DecompilerContext.getProperty(DecompilerContext.CURRENT_VAR_PROCESSOR))); DecompilerContext.getVarProcessor()));
} }
} }
@ -193,7 +192,7 @@ public class CatchStatement extends Statement {
cs.exctstrings.add(new ArrayList<>(exc)); cs.exctstrings.add(new ArrayList<>(exc));
cs.vars.add(new VarExprent(DecompilerContext.getCounterContainer().getCounterAndIncrement(CounterContainer.VAR_COUNTER), cs.vars.add(new VarExprent(DecompilerContext.getCounterContainer().getCounterAndIncrement(CounterContainer.VAR_COUNTER),
new VarType(CodeConstants.TYPE_OBJECT, 0, exc.get(0)), new VarType(CodeConstants.TYPE_OBJECT, 0, exc.get(0)),
(VarProcessor)DecompilerContext.getProperty(DecompilerContext.CURRENT_VAR_PROCESSOR))); DecompilerContext.getVarProcessor()));
} }
return cs; return cs;

@ -37,7 +37,7 @@ public class VarDefinitionHelper {
this.varproc = varproc; this.varproc = varproc;
VarNamesCollector vc = DecompilerContext.getVarNamesCollector(); VarNamesCollector vc = varproc.getVarNamesCollector();
boolean thisvar = !mt.hasModifier(CodeConstants.ACC_STATIC); boolean thisvar = !mt.hasModifier(CodeConstants.ACC_STATIC);
@ -108,8 +108,7 @@ public class VarDefinitionHelper {
public void setVarDefinitions() { public void setVarDefinitions() {
VarNamesCollector vc = varproc.getVarNamesCollector();
VarNamesCollector vc = DecompilerContext.getVarNamesCollector();
for (Entry<Integer, Statement> en : mapVarDefStatements.entrySet()) { for (Entry<Integer, Statement> en : mapVarDefStatements.entrySet()) {
Statement stat = en.getValue(); Statement stat = en.getValue();

@ -13,6 +13,7 @@ import java.util.*;
import java.util.Map.Entry; import java.util.Map.Entry;
public class VarProcessor { public class VarProcessor {
private final VarNamesCollector varNamesCollector = new VarNamesCollector();
private final StructMethod method; private final StructMethod method;
private final MethodDescriptor methodDescriptor; private final MethodDescriptor methodDescriptor;
private Map<VarVersionPair, String> mapVarNames = new HashMap<>(); private Map<VarVersionPair, String> mapVarNames = new HashMap<>();
@ -85,6 +86,10 @@ public class VarProcessor {
} }
} }
public VarNamesCollector getVarNamesCollector() {
return varNamesCollector;
}
public VarType getVarType(VarVersionPair pair) { public VarType getVarType(VarVersionPair pair) {
return varVersions == null ? null : varVersions.getVarType(pair); return varVersions == null ? null : varVersions.getVarType(pair);
} }

@ -2,8 +2,6 @@
package org.jetbrains.java.decompiler.modules.renamer; package org.jetbrains.java.decompiler.modules.renamer;
import org.jetbrains.java.decompiler.code.CodeConstants; 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.IIdentifierRenamer; import org.jetbrains.java.decompiler.main.extern.IIdentifierRenamer;
import org.jetbrains.java.decompiler.struct.StructClass; import org.jetbrains.java.decompiler.struct.StructClass;
import org.jetbrains.java.decompiler.struct.StructContext; import org.jetbrains.java.decompiler.struct.StructContext;
@ -18,41 +16,25 @@ import java.io.IOException;
import java.util.*; import java.util.*;
public class IdentifierConverter implements NewClassNameBuilder { public class IdentifierConverter implements NewClassNameBuilder {
private final StructContext context;
private StructContext context; private final IIdentifierRenamer helper;
private IIdentifierRenamer helper; private final PoolInterceptor interceptor;
private PoolInterceptor interceptor;
private List<ClassWrapperNode> rootClasses = new ArrayList<>(); private List<ClassWrapperNode> rootClasses = new ArrayList<>();
private List<ClassWrapperNode> rootInterfaces = new ArrayList<>(); private List<ClassWrapperNode> rootInterfaces = new ArrayList<>();
private Map<String, Map<String, String>> interfaceNameMaps = new HashMap<>(); private Map<String, Map<String, String>> interfaceNameMaps = new HashMap<>();
public void rename(StructContext context) { public IdentifierConverter(StructContext context, IIdentifierRenamer helper, PoolInterceptor interceptor) {
try { this.context = context;
this.context = context; this.helper = helper;
this.interceptor = interceptor;
String user_class = (String)DecompilerContext.getProperty(IFernflowerPreferences.USER_RENAMER_CLASS); }
if (user_class != null) {
try {
helper = (IIdentifierRenamer)IdentifierConverter.class.getClassLoader().loadClass(user_class).newInstance();
}
catch (Exception ignored) { }
}
if (helper == null) {
helper = new ConverterHelper();
}
interceptor = new PoolInterceptor(helper);
public void rename() {
try {
buildInheritanceTree(); buildInheritanceTree();
renameAllClasses(); renameAllClasses();
renameInterfaces(); renameInterfaces();
renameClasses(); renameClasses();
DecompilerContext.setPoolInterceptor(interceptor);
context.reloadContext(); context.reloadContext();
} }
catch (IOException ex) { catch (IOException ex) {
@ -381,4 +363,4 @@ public class IdentifierConverter implements NewClassNameBuilder {
this.rootClasses = rootClasses; this.rootClasses = rootClasses;
this.rootInterfaces = rootInterfaces; this.rootInterfaces = rootInterfaces;
} }
} }

@ -1,21 +1,12 @@
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. // Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.java.decompiler.modules.renamer; package org.jetbrains.java.decompiler.modules.renamer;
import org.jetbrains.java.decompiler.main.extern.IIdentifierRenamer;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map;
public class PoolInterceptor { public class PoolInterceptor {
private final Map<String, String> mapOldToNewNames = new HashMap<>();
private final IIdentifierRenamer helper; private final Map<String, String> mapNewToOldNames = new HashMap<>();
private final HashMap<String, String> mapOldToNewNames = new HashMap<>();
private final HashMap<String, String> mapNewToOldNames = new HashMap<>();
public PoolInterceptor(IIdentifierRenamer helper) {
this.helper = helper;
}
public void addName(String oldName, String newName) { public void addName(String oldName, String newName) {
mapOldToNewNames.put(oldName, newName); mapOldToNewNames.put(oldName, newName);
@ -29,8 +20,4 @@ public class PoolInterceptor {
public String getOldName(String newName) { public String getOldName(String newName) {
return mapNewToOldNames.get(newName); return mapNewToOldNames.get(newName);
} }
}
public IIdentifierRenamer getHelper() {
return helper;
}
}

@ -2,12 +2,15 @@
package org.jetbrains.java.decompiler; package org.jetbrains.java.decompiler;
import org.jetbrains.java.decompiler.main.decompiler.ConsoleDecompiler; import org.jetbrains.java.decompiler.main.decompiler.ConsoleDecompiler;
import org.jetbrains.java.decompiler.main.decompiler.PrintStreamLogger;
import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences; import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences;
import org.jetbrains.java.decompiler.util.InterpreterUtil; import org.jetbrains.java.decompiler.util.InterpreterUtil;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.*; import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.zip.ZipEntry; import java.util.zip.ZipEntry;
import java.util.zip.ZipFile; import java.util.zip.ZipFile;
@ -115,7 +118,7 @@ public class DecompilerTestFixture {
private final HashMap<String, ZipFile> zipFiles = new HashMap<>(); private final HashMap<String, ZipFile> zipFiles = new HashMap<>();
public TestConsoleDecompiler(File destination, Map<String, Object> options) { public TestConsoleDecompiler(File destination, Map<String, Object> options) {
super(destination, options); super(destination, options, new PrintStreamLogger(System.out));
} }
@Override @Override

Loading…
Cancel
Save