From 0f47403d0220757fed189b76e2071e25b1025cb8 Mon Sep 17 00:00:00 2001 From: Runemoro Date: Wed, 3 Jun 2020 13:39:42 -0400 Subject: Split GUI code to separate module (#242) * Split into modules * Post merge compile fixes Co-authored-by: modmuss50 --- src/main/java/cuchaz/enigma/source/Decompiler.java | 5 - .../cuchaz/enigma/source/DecompilerService.java | 11 - .../java/cuchaz/enigma/source/Decompilers.java | 9 - src/main/java/cuchaz/enigma/source/Source.java | 11 - .../java/cuchaz/enigma/source/SourceIndex.java | 174 --------- .../java/cuchaz/enigma/source/SourceSettings.java | 11 - .../cuchaz/enigma/source/cfr/CfrDecompiler.java | 108 ----- .../java/cuchaz/enigma/source/cfr/CfrSource.java | 38 -- .../cuchaz/enigma/source/cfr/EnigmaDumper.java | 433 --------------------- .../cuchaz/enigma/source/procyon/EntryParser.java | 49 --- .../enigma/source/procyon/ProcyonDecompiler.java | 81 ---- .../enigma/source/procyon/ProcyonSource.java | 49 --- .../procyon/index/SourceIndexClassVisitor.java | 95 ----- .../procyon/index/SourceIndexMethodVisitor.java | 218 ----------- .../source/procyon/index/SourceIndexVisitor.java | 40 -- .../enigma/source/procyon/index/TokenFactory.java | 46 --- .../transformers/AddJavadocsAstTransform.java | 134 ------- .../transformers/DropImportAstTransform.java | 33 -- .../transformers/DropVarModifiersAstTransform.java | 37 -- .../procyon/transformers/InvalidIdentifierFix.java | 29 -- .../source/procyon/transformers/Java8Generics.java | 107 ----- .../ObfuscatedEnumSwitchRewriterTransform.java | 414 -------------------- .../procyon/transformers/RemoveObjectCasts.java | 39 -- .../source/procyon/transformers/VarargsFixer.java | 197 ---------- .../typeloader/CachingClasspathTypeLoader.java | 33 -- .../procyon/typeloader/CachingTypeLoader.java | 38 -- .../typeloader/CompiledSourceTypeLoader.java | 140 ------- .../procyon/typeloader/NoRetryMetadataSystem.java | 38 -- .../procyon/typeloader/SynchronizedTypeLoader.java | 20 - 29 files changed, 2637 deletions(-) delete mode 100644 src/main/java/cuchaz/enigma/source/Decompiler.java delete mode 100644 src/main/java/cuchaz/enigma/source/DecompilerService.java delete mode 100644 src/main/java/cuchaz/enigma/source/Decompilers.java delete mode 100644 src/main/java/cuchaz/enigma/source/Source.java delete mode 100644 src/main/java/cuchaz/enigma/source/SourceIndex.java delete mode 100644 src/main/java/cuchaz/enigma/source/SourceSettings.java delete mode 100644 src/main/java/cuchaz/enigma/source/cfr/CfrDecompiler.java delete mode 100644 src/main/java/cuchaz/enigma/source/cfr/CfrSource.java delete mode 100644 src/main/java/cuchaz/enigma/source/cfr/EnigmaDumper.java delete mode 100644 src/main/java/cuchaz/enigma/source/procyon/EntryParser.java delete mode 100644 src/main/java/cuchaz/enigma/source/procyon/ProcyonDecompiler.java delete mode 100644 src/main/java/cuchaz/enigma/source/procyon/ProcyonSource.java delete mode 100644 src/main/java/cuchaz/enigma/source/procyon/index/SourceIndexClassVisitor.java delete mode 100644 src/main/java/cuchaz/enigma/source/procyon/index/SourceIndexMethodVisitor.java delete mode 100644 src/main/java/cuchaz/enigma/source/procyon/index/SourceIndexVisitor.java delete mode 100644 src/main/java/cuchaz/enigma/source/procyon/index/TokenFactory.java delete mode 100644 src/main/java/cuchaz/enigma/source/procyon/transformers/AddJavadocsAstTransform.java delete mode 100644 src/main/java/cuchaz/enigma/source/procyon/transformers/DropImportAstTransform.java delete mode 100644 src/main/java/cuchaz/enigma/source/procyon/transformers/DropVarModifiersAstTransform.java delete mode 100644 src/main/java/cuchaz/enigma/source/procyon/transformers/InvalidIdentifierFix.java delete mode 100644 src/main/java/cuchaz/enigma/source/procyon/transformers/Java8Generics.java delete mode 100644 src/main/java/cuchaz/enigma/source/procyon/transformers/ObfuscatedEnumSwitchRewriterTransform.java delete mode 100644 src/main/java/cuchaz/enigma/source/procyon/transformers/RemoveObjectCasts.java delete mode 100644 src/main/java/cuchaz/enigma/source/procyon/transformers/VarargsFixer.java delete mode 100644 src/main/java/cuchaz/enigma/source/procyon/typeloader/CachingClasspathTypeLoader.java delete mode 100644 src/main/java/cuchaz/enigma/source/procyon/typeloader/CachingTypeLoader.java delete mode 100644 src/main/java/cuchaz/enigma/source/procyon/typeloader/CompiledSourceTypeLoader.java delete mode 100644 src/main/java/cuchaz/enigma/source/procyon/typeloader/NoRetryMetadataSystem.java delete mode 100644 src/main/java/cuchaz/enigma/source/procyon/typeloader/SynchronizedTypeLoader.java (limited to 'src/main/java/cuchaz/enigma/source') diff --git a/src/main/java/cuchaz/enigma/source/Decompiler.java b/src/main/java/cuchaz/enigma/source/Decompiler.java deleted file mode 100644 index c9666d5..0000000 --- a/src/main/java/cuchaz/enigma/source/Decompiler.java +++ /dev/null @@ -1,5 +0,0 @@ -package cuchaz.enigma.source; - -public interface Decompiler { - Source getSource(String className); -} diff --git a/src/main/java/cuchaz/enigma/source/DecompilerService.java b/src/main/java/cuchaz/enigma/source/DecompilerService.java deleted file mode 100644 index 377ccbc..0000000 --- a/src/main/java/cuchaz/enigma/source/DecompilerService.java +++ /dev/null @@ -1,11 +0,0 @@ -package cuchaz.enigma.source; - -import cuchaz.enigma.ClassProvider; -import cuchaz.enigma.api.service.EnigmaService; -import cuchaz.enigma.api.service.EnigmaServiceType; - -public interface DecompilerService extends EnigmaService { - EnigmaServiceType TYPE = EnigmaServiceType.create("decompiler"); - - Decompiler create(ClassProvider classProvider, SourceSettings settings); -} diff --git a/src/main/java/cuchaz/enigma/source/Decompilers.java b/src/main/java/cuchaz/enigma/source/Decompilers.java deleted file mode 100644 index 7d154a6..0000000 --- a/src/main/java/cuchaz/enigma/source/Decompilers.java +++ /dev/null @@ -1,9 +0,0 @@ -package cuchaz.enigma.source; - -import cuchaz.enigma.source.cfr.CfrDecompiler; -import cuchaz.enigma.source.procyon.ProcyonDecompiler; - -public class Decompilers { - public static final DecompilerService PROCYON = ProcyonDecompiler::new; - public static final DecompilerService CFR = CfrDecompiler::new; -} diff --git a/src/main/java/cuchaz/enigma/source/Source.java b/src/main/java/cuchaz/enigma/source/Source.java deleted file mode 100644 index 43c4de0..0000000 --- a/src/main/java/cuchaz/enigma/source/Source.java +++ /dev/null @@ -1,11 +0,0 @@ -package cuchaz.enigma.source; - -import cuchaz.enigma.translation.mapping.EntryRemapper; - -public interface Source { - String asString(); - - Source addJavadocs(EntryRemapper remapper); - - SourceIndex index(); -} diff --git a/src/main/java/cuchaz/enigma/source/SourceIndex.java b/src/main/java/cuchaz/enigma/source/SourceIndex.java deleted file mode 100644 index 6a335ec..0000000 --- a/src/main/java/cuchaz/enigma/source/SourceIndex.java +++ /dev/null @@ -1,174 +0,0 @@ -package cuchaz.enigma.source; - -import com.google.common.collect.HashMultimap; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import com.google.common.collect.Multimap; -import cuchaz.enigma.analysis.EntryReference; -import cuchaz.enigma.analysis.Token; -import cuchaz.enigma.gui.SourceRemapper; -import cuchaz.enigma.translation.mapping.EntryResolver; -import cuchaz.enigma.translation.mapping.ResolutionStrategy; -import cuchaz.enigma.translation.representation.entry.Entry; - -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.TreeMap; -import java.util.stream.Collectors; - -public class SourceIndex { - private String source; - private List lineOffsets; - private final TreeMap, Entry>> tokenToReference; - private final Multimap, Entry>, Token> referenceToTokens; - private final Map, Token> declarationToToken; - - public SourceIndex() { - tokenToReference = new TreeMap<>(); - referenceToTokens = HashMultimap.create(); - declarationToToken = Maps.newHashMap(); - } - - public SourceIndex(String source) { - this(); - setSource(source); - } - - public void setSource(String source) { - this.source = source; - lineOffsets = Lists.newArrayList(); - lineOffsets.add(0); - - for (int i = 0; i < this.source.length(); i++) { - if (this.source.charAt(i) == '\n') { - lineOffsets.add(i + 1); - } - } - } - - public String getSource() { - return source; - } - - public int getLineNumber(int position) { - int line = 0; - - for (int offset : lineOffsets) { - if (offset > position) { - break; - } - - line++; - } - - return line; - } - - public int getColumnNumber(int position) { - return position - lineOffsets.get(getLineNumber(position) - 1) + 1; - } - - public int getPosition(int line, int column) { - return lineOffsets.get(line - 1) + column - 1; - } - - public Iterable> declarations() { - return declarationToToken.keySet(); - } - - public Iterable declarationTokens() { - return declarationToToken.values(); - } - - public Token getDeclarationToken(Entry entry) { - return declarationToToken.get(entry); - } - - public void addDeclaration(Token token, Entry deobfEntry) { - if (token != null) { - EntryReference, Entry> reference = new EntryReference<>(deobfEntry, token.text); - tokenToReference.put(token, reference); - referenceToTokens.put(reference, token); - declarationToToken.put(deobfEntry, token); - } - } - - public Iterable, Entry>> references() { - return referenceToTokens.keySet(); - } - - public EntryReference, Entry> getReference(Token token) { - if (token == null) { - return null; - } - - return tokenToReference.get(token); - } - - public Iterable referenceTokens() { - return tokenToReference.keySet(); - } - - public Token getReferenceToken(int pos) { - Token token = tokenToReference.floorKey(new Token(pos, pos, null)); - - if (token != null && token.contains(pos)) { - return token; - } - - return null; - } - - public Collection getReferenceTokens(EntryReference, Entry> deobfReference) { - return referenceToTokens.get(deobfReference); - } - - public void addReference(Token token, Entry deobfEntry, Entry deobfContext) { - if (token != null) { - EntryReference, Entry> deobfReference = new EntryReference<>(deobfEntry, token.text, deobfContext); - tokenToReference.put(token, deobfReference); - referenceToTokens.put(deobfReference, token); - } - } - - public void resolveReferences(EntryResolver resolver) { - // resolve all the classes in the source references - for (Token token : Lists.newArrayList(referenceToTokens.values())) { - EntryReference, Entry> reference = tokenToReference.get(token); - EntryReference, Entry> resolvedReference = resolver.resolveFirstReference(reference, ResolutionStrategy.RESOLVE_CLOSEST); - - // replace the reference - tokenToReference.replace(token, resolvedReference); - - Collection tokens = referenceToTokens.removeAll(reference); - referenceToTokens.putAll(resolvedReference, tokens); - } - } - - public SourceIndex remapTo(SourceRemapper.Result result) { - SourceIndex remapped = new SourceIndex(result.getSource()); - - for (Map.Entry, Token> entry : declarationToToken.entrySet()) { - remapped.declarationToToken.put(entry.getKey(), result.getRemappedToken(entry.getValue())); - } - - for (Map.Entry, Entry>, Collection> entry : referenceToTokens.asMap().entrySet()) { - EntryReference, Entry> reference = entry.getKey(); - Collection oldTokens = entry.getValue(); - - Collection newTokens = oldTokens - .stream() - .map(result::getRemappedToken) - .collect(Collectors.toList()); - - remapped.referenceToTokens.putAll(reference, newTokens); - } - - for (Map.Entry, Entry>> entry : tokenToReference.entrySet()) { - remapped.tokenToReference.put(result.getRemappedToken(entry.getKey()), entry.getValue()); - } - - return remapped; - } -} diff --git a/src/main/java/cuchaz/enigma/source/SourceSettings.java b/src/main/java/cuchaz/enigma/source/SourceSettings.java deleted file mode 100644 index f6c68e9..0000000 --- a/src/main/java/cuchaz/enigma/source/SourceSettings.java +++ /dev/null @@ -1,11 +0,0 @@ -package cuchaz.enigma.source; - -public class SourceSettings { - public final boolean removeImports; - public final boolean removeVariableFinal; - - public SourceSettings(boolean removeImports, boolean removeVariableFinal) { - this.removeImports = removeImports; - this.removeVariableFinal = removeVariableFinal; - } -} diff --git a/src/main/java/cuchaz/enigma/source/cfr/CfrDecompiler.java b/src/main/java/cuchaz/enigma/source/cfr/CfrDecompiler.java deleted file mode 100644 index 9e37f16..0000000 --- a/src/main/java/cuchaz/enigma/source/cfr/CfrDecompiler.java +++ /dev/null @@ -1,108 +0,0 @@ -package cuchaz.enigma.source.cfr; - -import com.google.common.io.ByteStreams; -import cuchaz.enigma.ClassProvider; -import cuchaz.enigma.source.Decompiler; -import cuchaz.enigma.source.Source; -import cuchaz.enigma.source.SourceSettings; -import org.benf.cfr.reader.apiunreleased.ClassFileSource2; -import org.benf.cfr.reader.apiunreleased.JarContent; -import org.benf.cfr.reader.bytecode.analysis.parse.utils.Pair; -import org.benf.cfr.reader.entities.ClassFile; -import org.benf.cfr.reader.mapping.MappingFactory; -import org.benf.cfr.reader.mapping.ObfuscationMapping; -import org.benf.cfr.reader.relationship.MemberNameResolver; -import org.benf.cfr.reader.state.DCCommonState; -import org.benf.cfr.reader.state.TypeUsageCollectingDumper; -import org.benf.cfr.reader.util.AnalysisType; -import org.benf.cfr.reader.util.CannotLoadClassException; -import org.benf.cfr.reader.util.collections.ListFactory; -import org.benf.cfr.reader.util.getopt.Options; -import org.benf.cfr.reader.util.getopt.OptionsImpl; -import org.objectweb.asm.ClassWriter; -import org.objectweb.asm.tree.ClassNode; - -import java.io.IOException; -import java.io.InputStream; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; - - -public class CfrDecompiler implements Decompiler { - private final DCCommonState state; - - public CfrDecompiler(ClassProvider classProvider, SourceSettings sourceSettings) { - Map options = new HashMap<>(); - - state = new DCCommonState(OptionsImpl.getFactory().create(options), new ClassFileSource2() { - @Override - public JarContent addJarContent(String s, AnalysisType analysisType) { - return null; - } - - @Override - public void informAnalysisRelativePathDetail(String usePath, String classFilePath) { - - } - - @Override - public Collection addJar(String jarPath) { - return null; - } - - @Override - public String getPossiblyRenamedPath(String path) { - return path; - } - - @Override - public Pair getClassFileContent(String path) { - ClassNode node = classProvider.getClassNode(path.substring(0, path.lastIndexOf('.'))); - - if (node == null) { - try (InputStream classResource = CfrDecompiler.class.getClassLoader().getResourceAsStream(path)) { - if (classResource != null) { - return new Pair<>(ByteStreams.toByteArray(classResource), path); - } - } catch (IOException ignored) {} - - return null; - } - - ClassWriter cw = new ClassWriter(0); - node.accept(cw); - return new Pair<>(cw.toByteArray(), path); - } - }); - } - - @Override - public Source getSource(String className) { - DCCommonState state = this.state; - Options options = state.getOptions(); - - ObfuscationMapping mapping = MappingFactory.get(options, state); - state = new DCCommonState(state, mapping); - ClassFile tree = state.getClassFileMaybePath(className); - - state.configureWith(tree); - - // To make sure we're analysing the cached version - try { - tree = state.getClassFile(tree.getClassType()); - } catch (CannotLoadClassException ignored) {} - - if (options.getOption(OptionsImpl.DECOMPILE_INNER_CLASSES)) { - tree.loadInnerClasses(state); - } - - if (options.getOption(OptionsImpl.RENAME_DUP_MEMBERS)) { - MemberNameResolver.resolveNames(state, ListFactory.newList(state.getClassCache().getLoadedTypes())); - } - - TypeUsageCollectingDumper typeUsageCollector = new TypeUsageCollectingDumper(options, tree); - tree.analyseTop(state, typeUsageCollector); - return new CfrSource(tree, state, typeUsageCollector.getRealTypeUsageInformation()); - } -} diff --git a/src/main/java/cuchaz/enigma/source/cfr/CfrSource.java b/src/main/java/cuchaz/enigma/source/cfr/CfrSource.java deleted file mode 100644 index d4f2da6..0000000 --- a/src/main/java/cuchaz/enigma/source/cfr/CfrSource.java +++ /dev/null @@ -1,38 +0,0 @@ -package cuchaz.enigma.source.cfr; - -import cuchaz.enigma.source.Source; -import cuchaz.enigma.source.SourceIndex; -import cuchaz.enigma.translation.mapping.EntryRemapper; -import org.benf.cfr.reader.entities.ClassFile; -import org.benf.cfr.reader.state.DCCommonState; -import org.benf.cfr.reader.state.TypeUsageInformation; - -public class CfrSource implements Source { - private final ClassFile tree; - private final SourceIndex index; - private final String string; - - public CfrSource(ClassFile tree, DCCommonState state, TypeUsageInformation typeUsages) { - this.tree = tree; - - EnigmaDumper dumper = new EnigmaDumper(typeUsages); - tree.dump(state.getObfuscationMapping().wrap(dumper)); - index = dumper.getIndex(); - string = dumper.getString(); - } - - @Override - public String asString() { - return string; - } - - @Override - public Source addJavadocs(EntryRemapper remapper) { - return this; // TODO - } - - @Override - public SourceIndex index() { - return index; - } -} diff --git a/src/main/java/cuchaz/enigma/source/cfr/EnigmaDumper.java b/src/main/java/cuchaz/enigma/source/cfr/EnigmaDumper.java deleted file mode 100644 index 09e0a9b..0000000 --- a/src/main/java/cuchaz/enigma/source/cfr/EnigmaDumper.java +++ /dev/null @@ -1,433 +0,0 @@ -package cuchaz.enigma.source.cfr; - -import cuchaz.enigma.analysis.Token; -import cuchaz.enigma.source.SourceIndex; -import cuchaz.enigma.translation.representation.MethodDescriptor; -import cuchaz.enigma.translation.representation.TypeDescriptor; -import cuchaz.enigma.translation.representation.entry.*; -import org.benf.cfr.reader.bytecode.analysis.types.*; -import org.benf.cfr.reader.bytecode.analysis.variables.NamedVariable; -import org.benf.cfr.reader.entities.Field; -import org.benf.cfr.reader.entities.Method; -import org.benf.cfr.reader.mapping.NullMapping; -import org.benf.cfr.reader.mapping.ObfuscationMapping; -import org.benf.cfr.reader.state.TypeUsageInformation; -import org.benf.cfr.reader.util.collections.SetFactory; -import org.benf.cfr.reader.util.output.DelegatingDumper; -import org.benf.cfr.reader.util.output.Dumpable; -import org.benf.cfr.reader.util.output.Dumper; -import org.benf.cfr.reader.util.output.TypeContext; - -import java.util.Set; -import java.util.stream.Collectors; - -public class EnigmaDumper implements Dumper { - private int outputCount = 0; - private int indent; - private boolean atStart = true; - private boolean pendingCR = false; - private final StringBuilder sb = new StringBuilder(); - private final TypeUsageInformation typeUsageInformation; - private final Set emitted = SetFactory.newSet(); - private final SourceIndex index = new SourceIndex(); - private int position; - - - public EnigmaDumper(TypeUsageInformation typeUsageInformation) { - this.typeUsageInformation = typeUsageInformation; - } - - private void append(String s) { - sb.append(s); - position += s.length(); - } - - private String getDesc(JavaTypeInstance type) { - if (!type.isUsableType() && type != RawJavaType.VOID) { - throw new IllegalArgumentException(type.toString()); - } - - if (type instanceof JavaGenericBaseInstance) { - return getDesc(type.getDeGenerifiedType()); - } - - if (type instanceof JavaRefTypeInstance) { - return "L" + type.getRawName().replace('.', '/') + ";"; - } - - if (type instanceof JavaArrayTypeInstance) { - return "[" + getDesc(((JavaArrayTypeInstance) type).removeAnArrayIndirection()); - } - - if (type instanceof RawJavaType) { - switch ((RawJavaType) type) { - case BOOLEAN: - return "Z"; - case BYTE: - return "B"; - case CHAR: - return "C"; - case SHORT: - return "S"; - case INT: - return "I"; - case LONG: - return "J"; - case FLOAT: - return "F"; - case DOUBLE: - return "D"; - case VOID: - return "V"; - default: - throw new AssertionError(); - } - } - - throw new AssertionError(); - } - - private MethodEntry getMethodEntry(MethodPrototype method) { - if (method == null || method.getClassType() == null) { - return null; - } - - MethodDescriptor desc = new MethodDescriptor( - method.getArgs().stream().map(type -> new TypeDescriptor(getDesc(type))).collect(Collectors.toList()), - new TypeDescriptor(method.getName().equals("") || method.getName().equals("") ? "V" : getDesc(method.getReturnType())) - ); - - return new MethodEntry(getClassEntry(method.getClassType()), method.getName(), desc); - } - - private LocalVariableEntry getParameterEntry(MethodPrototype method, int parameterIndex, String name) { - int variableIndex = method.isInstanceMethod() ? 1 : 0; - for (int i = 0; i < parameterIndex; i++) { - variableIndex += method.getArgs().get(i).getStackType().getComputationCategory(); - } - - return new LocalVariableEntry(getMethodEntry(method), variableIndex, name, true, null); - } - - private FieldEntry getFieldEntry(JavaTypeInstance owner, String name, JavaTypeInstance type) { - return new FieldEntry(getClassEntry(owner), name, new TypeDescriptor(getDesc(type))); - } - - private ClassEntry getClassEntry(JavaTypeInstance type) { - return new ClassEntry(type.getRawName().replace('.', '/')); - } - - @Override - public Dumper beginBlockComment(boolean inline) { - print("/*").newln(); - return this; - } - - @Override - public Dumper endBlockComment() { - print(" */").newln(); - return this; - } - - @Override - public Dumper label(String s, boolean inline) { - processPendingCR(); - append(s); - append(":"); - return this; - } - - @Override - public Dumper comment(String s) { - append("// "); - append(s); - append("\n"); - return this; - } - - @Override - public void enqueuePendingCarriageReturn() { - pendingCR = true; - } - - @Override - public Dumper removePendingCarriageReturn() { - pendingCR = false; - return this; - } - - private void processPendingCR() { - if (pendingCR) { - append("\n"); - atStart = true; - pendingCR = false; - } - } - - @Override - public Dumper identifier(String s, Object ref, boolean defines) { - return print(s); - } - - @Override - public Dumper methodName(String name, MethodPrototype method, boolean special, boolean defines) { - doIndent(); - Token token = new Token(position, position + name.length(), name); - Entry entry = getMethodEntry(method); - - if (entry != null) { - if (defines) { - index.addDeclaration(token, entry); - } else { - index.addReference(token, entry, null); - } - } - - return identifier(name, null, defines); - } - - @Override - public Dumper parameterName(String name, MethodPrototype method, int index, boolean defines) { - doIndent(); - Token token = new Token(position, position + name.length(), name); - Entry entry = getParameterEntry(method, index, name); - - if (entry != null) { - if (defines) { - this.index.addDeclaration(token, entry); - } else { - this.index.addReference(token, entry, null); - } - } - - return identifier(name, null, defines); - } - - @Override - public Dumper variableName(String name, NamedVariable variable, boolean defines) { - return identifier(name, null, defines); - } - - @Override - public Dumper packageName(JavaRefTypeInstance t) { - String s = t.getPackageName(); - - if (!s.isEmpty()) { - keyword("package ").print(s).endCodeln().newln(); - } - - return this; - } - - @Override - public Dumper fieldName(String name, Field field, JavaTypeInstance owner, boolean hiddenDeclaration, boolean defines) { - doIndent(); - Token token = new Token(position, position + name.length(), name); - Entry entry = field == null ? null : getFieldEntry(owner, name, field.getJavaTypeInstance()); - - if (entry != null) { - if (defines) { - index.addDeclaration(token, entry); - } else { - index.addReference(token, entry, null); - } - } - - identifier(name, null, defines); - return this; - } - - @Override - public Dumper print(String s) { - processPendingCR(); - doIndent(); - append(s); - atStart = s.endsWith("\n"); - outputCount++; - return this; - } - - @Override - public Dumper print(char c) { - return print(String.valueOf(c)); - } - - @Override - public Dumper newln() { - append("\n"); - atStart = true; - outputCount++; - return this; - } - - @Override - public Dumper endCodeln() { - append(";\n"); - atStart = true; - outputCount++; - return this; - } - - @Override - public Dumper keyword(String s) { - print(s); - return this; - } - - @Override - public Dumper operator(String s) { - print(s); - return this; - } - - @Override - public Dumper separator(String s) { - print(s); - return this; - } - - @Override - public Dumper literal(String s, Object o) { - print(s); - return this; - } - - private void doIndent() { - if (!atStart) return; - String indents = " "; - - for (int x = 0; x < indent; ++x) { - append(indents); - } - - atStart = false; - } - - @Override - public void indent(int diff) { - indent += diff; - } - - @Override - public Dumper dump(Dumpable d) { - if (d == null) { - keyword("null"); - return this; - } - - d.dump(this); - return this; - } - - @Override - public TypeUsageInformation getTypeUsageInformation() { - return typeUsageInformation; - } - - @Override - public ObfuscationMapping getObfuscationMapping() { - return NullMapping.INSTANCE; - } - - @Override - public String toString() { - return sb.toString(); - } - - @Override - public void addSummaryError(Method method, String s) {} - - @Override - public void close() { - } - - @Override - public boolean canEmitClass(JavaTypeInstance type) { - return emitted.add(type); - } - - @Override - public int getOutputCount() { - return outputCount; - } - - @Override - public Dumper dump(JavaTypeInstance type) { - return dump(type, TypeContext.None, false); - } - - @Override - public Dumper dump(JavaTypeInstance type, boolean defines) { - return dump(type, TypeContext.None, false); - } - - @Override - public Dumper dump(JavaTypeInstance type, TypeContext context) { - return dump(type, context, false); - } - - private Dumper dump(JavaTypeInstance type, TypeContext context, boolean defines) { - doIndent(); - if (type instanceof JavaRefTypeInstance) { - int start = position; - type.dumpInto(this, typeUsageInformation, TypeContext.None); - int end = position; - Token token = new Token(start, end, sb.toString().substring(start, end)); - - if (defines) { - index.addDeclaration(token, getClassEntry(type)); - } else { - index.addReference(token, getClassEntry(type), null); - } - - return this; - } - - type.dumpInto(this, typeUsageInformation, context); - return this; - } - - @Override - public Dumper withTypeUsageInformation(TypeUsageInformation innerclassTypeUsageInformation) { - return new WithTypeUsageInformationDumper(this, innerclassTypeUsageInformation); - } - - public SourceIndex getIndex() { - index.setSource(getString()); - return index; - } - - public String getString() { - return sb.toString(); - } - - public static class WithTypeUsageInformationDumper extends DelegatingDumper { - private final TypeUsageInformation typeUsageInformation; - - WithTypeUsageInformationDumper(Dumper delegate, TypeUsageInformation typeUsageInformation) { - super(delegate); - this.typeUsageInformation = typeUsageInformation; - } - - @Override - public TypeUsageInformation getTypeUsageInformation() { - return typeUsageInformation; - } - - @Override - public Dumper dump(JavaTypeInstance javaTypeInstance) { - return dump(javaTypeInstance, TypeContext.None); - } - - @Override - public Dumper dump(JavaTypeInstance javaTypeInstance, TypeContext typeContext) { - javaTypeInstance.dumpInto(this, typeUsageInformation, typeContext); - return this; - } - - @Override - public Dumper withTypeUsageInformation(TypeUsageInformation innerclassTypeUsageInformation) { - return new WithTypeUsageInformationDumper(delegate, innerclassTypeUsageInformation); - } - } -} diff --git a/src/main/java/cuchaz/enigma/source/procyon/EntryParser.java b/src/main/java/cuchaz/enigma/source/procyon/EntryParser.java deleted file mode 100644 index 2fae61a..0000000 --- a/src/main/java/cuchaz/enigma/source/procyon/EntryParser.java +++ /dev/null @@ -1,49 +0,0 @@ -package cuchaz.enigma.source.procyon; - -import com.strobel.assembler.metadata.FieldDefinition; -import com.strobel.assembler.metadata.MethodDefinition; -import com.strobel.assembler.metadata.TypeDefinition; -import com.strobel.assembler.metadata.TypeReference; -import cuchaz.enigma.translation.representation.AccessFlags; -import cuchaz.enigma.translation.representation.MethodDescriptor; -import cuchaz.enigma.translation.representation.Signature; -import cuchaz.enigma.translation.representation.TypeDescriptor; -import cuchaz.enigma.translation.representation.entry.ClassDefEntry; -import cuchaz.enigma.translation.representation.entry.ClassEntry; -import cuchaz.enigma.translation.representation.entry.FieldDefEntry; -import cuchaz.enigma.translation.representation.entry.MethodDefEntry; - -public class EntryParser { - public static FieldDefEntry parse(FieldDefinition definition) { - ClassEntry owner = parse(definition.getDeclaringType()); - TypeDescriptor descriptor = new TypeDescriptor(definition.getErasedSignature()); - Signature signature = Signature.createTypedSignature(definition.getSignature()); - AccessFlags access = new AccessFlags(definition.getModifiers()); - return new FieldDefEntry(owner, definition.getName(), descriptor, signature, access, null); - } - - public static ClassDefEntry parse(TypeDefinition def) { - String name = def.getInternalName(); - Signature signature = Signature.createSignature(def.getSignature()); - AccessFlags access = new AccessFlags(def.getModifiers()); - ClassEntry superClass = def.getBaseType() != null ? parse(def.getBaseType()) : null; - ClassEntry[] interfaces = def.getExplicitInterfaces().stream().map(EntryParser::parse).toArray(ClassEntry[]::new); - return new ClassDefEntry(name, signature, access, superClass, interfaces); - } - - public static ClassEntry parse(TypeReference typeReference) { - return new ClassEntry(typeReference.getInternalName()); - } - - public static MethodDefEntry parse(MethodDefinition definition) { - ClassEntry classEntry = parse(definition.getDeclaringType()); - MethodDescriptor descriptor = new MethodDescriptor(definition.getErasedSignature()); - Signature signature = Signature.createSignature(definition.getSignature()); - AccessFlags access = new AccessFlags(definition.getModifiers()); - return new MethodDefEntry(classEntry, definition.getName(), descriptor, signature, access, null); - } - - public static TypeDescriptor parseTypeDescriptor(TypeReference type) { - return new TypeDescriptor(type.getErasedSignature()); - } -} diff --git a/src/main/java/cuchaz/enigma/source/procyon/ProcyonDecompiler.java b/src/main/java/cuchaz/enigma/source/procyon/ProcyonDecompiler.java deleted file mode 100644 index 37bc0c8..0000000 --- a/src/main/java/cuchaz/enigma/source/procyon/ProcyonDecompiler.java +++ /dev/null @@ -1,81 +0,0 @@ -package cuchaz.enigma.source.procyon; - -import com.strobel.assembler.metadata.ITypeLoader; -import com.strobel.assembler.metadata.MetadataSystem; -import com.strobel.assembler.metadata.TypeDefinition; -import com.strobel.assembler.metadata.TypeReference; -import com.strobel.decompiler.DecompilerContext; -import com.strobel.decompiler.DecompilerSettings; -import com.strobel.decompiler.languages.java.BraceStyle; -import com.strobel.decompiler.languages.java.JavaFormattingOptions; -import com.strobel.decompiler.languages.java.ast.AstBuilder; -import com.strobel.decompiler.languages.java.ast.CompilationUnit; -import com.strobel.decompiler.languages.java.ast.InsertParenthesesVisitor; -import cuchaz.enigma.ClassProvider; -import cuchaz.enigma.api.EnigmaPluginContext; -import cuchaz.enigma.source.Source; -import cuchaz.enigma.source.Decompiler; -import cuchaz.enigma.source.SourceSettings; -import cuchaz.enigma.source.procyon.transformers.*; -import cuchaz.enigma.source.procyon.typeloader.CompiledSourceTypeLoader; -import cuchaz.enigma.source.procyon.typeloader.NoRetryMetadataSystem; -import cuchaz.enigma.source.procyon.typeloader.SynchronizedTypeLoader; -import cuchaz.enigma.utils.Utils; - -public class ProcyonDecompiler implements Decompiler { - private final SourceSettings settings; - private final DecompilerSettings decompilerSettings; - private final MetadataSystem metadataSystem; - - public ProcyonDecompiler(ClassProvider classProvider, SourceSettings settings) { - ITypeLoader typeLoader = new SynchronizedTypeLoader(new CompiledSourceTypeLoader(classProvider)); - - metadataSystem = new NoRetryMetadataSystem(typeLoader); - metadataSystem.setEagerMethodLoadingEnabled(true); - - decompilerSettings = DecompilerSettings.javaDefaults(); - decompilerSettings.setMergeVariables(Utils.getSystemPropertyAsBoolean("enigma.mergeVariables", true)); - decompilerSettings.setForceExplicitImports(Utils.getSystemPropertyAsBoolean("enigma.forceExplicitImports", true)); - decompilerSettings.setForceExplicitTypeArguments(Utils.getSystemPropertyAsBoolean("enigma.forceExplicitTypeArguments", true)); - decompilerSettings.setShowDebugLineNumbers(Utils.getSystemPropertyAsBoolean("enigma.showDebugLineNumbers", false)); - decompilerSettings.setShowSyntheticMembers(Utils.getSystemPropertyAsBoolean("enigma.showSyntheticMembers", false)); - decompilerSettings.setTypeLoader(typeLoader); - - JavaFormattingOptions formattingOptions = decompilerSettings.getJavaFormattingOptions(); - formattingOptions.ClassBraceStyle = BraceStyle.EndOfLine; - formattingOptions.InterfaceBraceStyle = BraceStyle.EndOfLine; - formattingOptions.EnumBraceStyle = BraceStyle.EndOfLine; - - this.settings = settings; - } - - @Override - public Source getSource(String className) { - TypeReference type = metadataSystem.lookupType(className); - if (type == null) { - throw new Error(String.format("Unable to find desc: %s", className)); - } - - TypeDefinition resolvedType = type.resolve(); - - DecompilerContext context = new DecompilerContext(); - context.setCurrentType(resolvedType); - context.setSettings(decompilerSettings); - - AstBuilder builder = new AstBuilder(context); - builder.addType(resolvedType); - builder.runTransformations(null); - CompilationUnit source = builder.getCompilationUnit(); - - new ObfuscatedEnumSwitchRewriterTransform(context).run(source); - new VarargsFixer(context).run(source); - new RemoveObjectCasts(context).run(source); - new Java8Generics().run(source); - new InvalidIdentifierFix().run(source); - if (settings.removeImports) DropImportAstTransform.INSTANCE.run(source); - if (settings.removeVariableFinal) DropVarModifiersAstTransform.INSTANCE.run(source); - source.acceptVisitor(new InsertParenthesesVisitor(), null); - - return new ProcyonSource(source, decompilerSettings); - } -} diff --git a/src/main/java/cuchaz/enigma/source/procyon/ProcyonSource.java b/src/main/java/cuchaz/enigma/source/procyon/ProcyonSource.java deleted file mode 100644 index 53c8c70..0000000 --- a/src/main/java/cuchaz/enigma/source/procyon/ProcyonSource.java +++ /dev/null @@ -1,49 +0,0 @@ -package cuchaz.enigma.source.procyon; - -import com.strobel.decompiler.DecompilerSettings; -import com.strobel.decompiler.PlainTextOutput; -import com.strobel.decompiler.languages.java.JavaOutputVisitor; -import com.strobel.decompiler.languages.java.ast.CompilationUnit; -import cuchaz.enigma.source.Source; -import cuchaz.enigma.source.SourceIndex; -import cuchaz.enigma.source.procyon.index.SourceIndexVisitor; -import cuchaz.enigma.source.procyon.transformers.AddJavadocsAstTransform; -import cuchaz.enigma.translation.mapping.EntryRemapper; - -import java.io.StringWriter; - -public class ProcyonSource implements Source { - private final DecompilerSettings settings; - private final CompilationUnit tree; - private String string; - - public ProcyonSource(CompilationUnit tree, DecompilerSettings settings) { - this.settings = settings; - this.tree = tree; - } - - @Override - public SourceIndex index() { - SourceIndex index = new SourceIndex(asString()); - tree.acceptVisitor(new SourceIndexVisitor(), index); - return index; - } - - @Override - public String asString() { - if (string == null) { - StringWriter writer = new StringWriter(); - tree.acceptVisitor(new JavaOutputVisitor(new PlainTextOutput(writer), settings), null); - string = writer.toString(); - } - - return string; - } - - @Override - public Source addJavadocs(EntryRemapper remapper) { - CompilationUnit remappedTree = (CompilationUnit) tree.clone(); - new AddJavadocsAstTransform(remapper).run(remappedTree); - return new ProcyonSource(remappedTree, settings); - } -} diff --git a/src/main/java/cuchaz/enigma/source/procyon/index/SourceIndexClassVisitor.java b/src/main/java/cuchaz/enigma/source/procyon/index/SourceIndexClassVisitor.java deleted file mode 100644 index f6eeb15..0000000 --- a/src/main/java/cuchaz/enigma/source/procyon/index/SourceIndexClassVisitor.java +++ /dev/null @@ -1,95 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.source.procyon.index; - -import com.strobel.assembler.metadata.FieldDefinition; -import com.strobel.assembler.metadata.MethodDefinition; -import com.strobel.assembler.metadata.TypeDefinition; -import com.strobel.assembler.metadata.TypeReference; -import com.strobel.decompiler.languages.TextLocation; -import com.strobel.decompiler.languages.java.ast.*; -import cuchaz.enigma.source.SourceIndex; -import cuchaz.enigma.source.procyon.EntryParser; -import cuchaz.enigma.translation.representation.entry.*; - -public class SourceIndexClassVisitor extends SourceIndexVisitor { - private ClassDefEntry classEntry; - - public SourceIndexClassVisitor(ClassDefEntry classEntry) { - this.classEntry = classEntry; - } - - @Override - public Void visitTypeDeclaration(TypeDeclaration node, SourceIndex index) { - // is this this class, or a subtype? - TypeDefinition def = node.getUserData(Keys.TYPE_DEFINITION); - ClassDefEntry classEntry = EntryParser.parse(def); - if (!classEntry.equals(this.classEntry)) { - // it's a subtype, recurse - index.addDeclaration(TokenFactory.createToken(index, node.getNameToken()), classEntry); - return node.acceptVisitor(new SourceIndexClassVisitor(classEntry), index); - } - - return visitChildren(node, index); - } - - @Override - public Void visitSimpleType(SimpleType node, SourceIndex index) { - TypeReference ref = node.getUserData(Keys.TYPE_REFERENCE); - if (node.getIdentifierToken().getStartLocation() != TextLocation.EMPTY) { - ClassEntry classEntry = new ClassEntry(ref.getInternalName()); - index.addReference(TokenFactory.createToken(index, node.getIdentifierToken()), classEntry, this.classEntry); - } - - return visitChildren(node, index); - } - - @Override - public Void visitMethodDeclaration(MethodDeclaration node, SourceIndex index) { - MethodDefinition def = node.getUserData(Keys.METHOD_DEFINITION); - MethodDefEntry methodEntry = EntryParser.parse(def); - AstNode tokenNode = node.getNameToken(); - if (methodEntry.isConstructor() && methodEntry.getName().equals("")) { - // for static initializers, check elsewhere for the token node - tokenNode = node.getModifiers().firstOrNullObject(); - } - index.addDeclaration(TokenFactory.createToken(index, tokenNode), methodEntry); - return node.acceptVisitor(new SourceIndexMethodVisitor(methodEntry), index); - } - - @Override - public Void visitConstructorDeclaration(ConstructorDeclaration node, SourceIndex index) { - MethodDefinition def = node.getUserData(Keys.METHOD_DEFINITION); - MethodDefEntry methodEntry = EntryParser.parse(def); - index.addDeclaration(TokenFactory.createToken(index, node.getNameToken()), methodEntry); - return node.acceptVisitor(new SourceIndexMethodVisitor(methodEntry), index); - } - - @Override - public Void visitFieldDeclaration(FieldDeclaration node, SourceIndex index) { - FieldDefinition def = node.getUserData(Keys.FIELD_DEFINITION); - FieldDefEntry fieldEntry = EntryParser.parse(def); - assert (node.getVariables().size() == 1); - VariableInitializer variable = node.getVariables().firstOrNullObject(); - index.addDeclaration(TokenFactory.createToken(index, variable.getNameToken()), fieldEntry); - return visitChildren(node, index); - } - - @Override - public Void visitEnumValueDeclaration(EnumValueDeclaration node, SourceIndex index) { - // treat enum declarations as field declarations - FieldDefinition def = node.getUserData(Keys.FIELD_DEFINITION); - FieldDefEntry fieldEntry = EntryParser.parse(def); - index.addDeclaration(TokenFactory.createToken(index, node.getNameToken()), fieldEntry); - return visitChildren(node, index); - } -} diff --git a/src/main/java/cuchaz/enigma/source/procyon/index/SourceIndexMethodVisitor.java b/src/main/java/cuchaz/enigma/source/procyon/index/SourceIndexMethodVisitor.java deleted file mode 100644 index 0e8bc51..0000000 --- a/src/main/java/cuchaz/enigma/source/procyon/index/SourceIndexMethodVisitor.java +++ /dev/null @@ -1,218 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.source.procyon.index; - -import com.google.common.collect.HashMultimap; -import com.google.common.collect.Multimap; -import com.strobel.assembler.metadata.*; -import com.strobel.decompiler.ast.Variable; -import com.strobel.decompiler.languages.TextLocation; -import com.strobel.decompiler.languages.java.ast.*; -import cuchaz.enigma.source.SourceIndex; -import cuchaz.enigma.source.procyon.EntryParser; -import cuchaz.enigma.translation.representation.MethodDescriptor; -import cuchaz.enigma.translation.representation.TypeDescriptor; -import cuchaz.enigma.translation.representation.entry.*; - -import java.lang.Error; -import java.util.HashMap; -import java.util.Map; - -public class SourceIndexMethodVisitor extends SourceIndexVisitor { - private final MethodDefEntry methodEntry; - - private Multimap unmatchedIdentifier = HashMultimap.create(); - private Map> identifierEntryCache = new HashMap<>(); - - public SourceIndexMethodVisitor(MethodDefEntry methodEntry) { - this.methodEntry = methodEntry; - } - - @Override - public Void visitInvocationExpression(InvocationExpression node, SourceIndex index) { - MemberReference ref = node.getUserData(Keys.MEMBER_REFERENCE); - - // get the behavior entry - ClassEntry classEntry = new ClassEntry(ref.getDeclaringType().getInternalName()); - MethodEntry methodEntry = null; - if (ref instanceof MethodReference) { - methodEntry = new MethodEntry(classEntry, ref.getName(), new MethodDescriptor(ref.getErasedSignature())); - } - if (methodEntry != null) { - // get the node for the token - AstNode tokenNode = null; - if (node.getTarget() instanceof MemberReferenceExpression) { - tokenNode = ((MemberReferenceExpression) node.getTarget()).getMemberNameToken(); - } else if (node.getTarget() instanceof SuperReferenceExpression) { - tokenNode = node.getTarget(); - } else if (node.getTarget() instanceof ThisReferenceExpression) { - tokenNode = node.getTarget(); - } - if (tokenNode != null) { - index.addReference(TokenFactory.createToken(index, tokenNode), methodEntry, this.methodEntry); - } - } - - // Check for identifier - node.getArguments().stream().filter(expression -> expression instanceof IdentifierExpression) - .forEach(expression -> this.checkIdentifier((IdentifierExpression) expression, index)); - return visitChildren(node, index); - } - - @Override - public Void visitMemberReferenceExpression(MemberReferenceExpression node, SourceIndex index) { - MemberReference ref = node.getUserData(Keys.MEMBER_REFERENCE); - if (ref instanceof FieldReference) { - // make sure this is actually a field - String erasedSignature = ref.getErasedSignature(); - if (erasedSignature.indexOf('(') >= 0) { - throw new Error("Expected a field here! got " + ref); - } - - ClassEntry classEntry = new ClassEntry(ref.getDeclaringType().getInternalName()); - FieldEntry fieldEntry = new FieldEntry(classEntry, ref.getName(), new TypeDescriptor(erasedSignature)); - index.addReference(TokenFactory.createToken(index, node.getMemberNameToken()), fieldEntry, this.methodEntry); - } - - return visitChildren(node, index); - } - - @Override - public Void visitSimpleType(SimpleType node, SourceIndex index) { - TypeReference ref = node.getUserData(Keys.TYPE_REFERENCE); - if (node.getIdentifierToken().getStartLocation() != TextLocation.EMPTY) { - ClassEntry classEntry = new ClassEntry(ref.getInternalName()); - index.addReference(TokenFactory.createToken(index, node.getIdentifierToken()), classEntry, this.methodEntry); - } - - return visitChildren(node, index); - } - - @Override - public Void visitParameterDeclaration(ParameterDeclaration node, SourceIndex index) { - ParameterDefinition def = node.getUserData(Keys.PARAMETER_DEFINITION); - int parameterIndex = def.getSlot(); - - if (parameterIndex >= 0) { - MethodDefEntry ownerMethod = methodEntry; - if (def.getMethod() instanceof MethodDefinition) { - ownerMethod = EntryParser.parse((MethodDefinition) def.getMethod()); - } - - TypeDescriptor parameterType = EntryParser.parseTypeDescriptor(def.getParameterType()); - LocalVariableDefEntry localVariableEntry = new LocalVariableDefEntry(ownerMethod, parameterIndex, node.getName(), true, parameterType, null); - Identifier identifier = node.getNameToken(); - // cache the argument entry and the identifier - identifierEntryCache.put(identifier.getName(), localVariableEntry); - index.addDeclaration(TokenFactory.createToken(index, identifier), localVariableEntry); - } - - return visitChildren(node, index); - } - - @Override - public Void visitIdentifierExpression(IdentifierExpression node, SourceIndex index) { - MemberReference ref = node.getUserData(Keys.MEMBER_REFERENCE); - if (ref != null) { - ClassEntry classEntry = new ClassEntry(ref.getDeclaringType().getInternalName()); - FieldEntry fieldEntry = new FieldEntry(classEntry, ref.getName(), new TypeDescriptor(ref.getErasedSignature())); - index.addReference(TokenFactory.createToken(index, node.getIdentifierToken()), fieldEntry, this.methodEntry); - } else - this.checkIdentifier(node, index); - return visitChildren(node, index); - } - - private void checkIdentifier(IdentifierExpression node, SourceIndex index) { - if (identifierEntryCache.containsKey(node.getIdentifier())) // If it's in the argument cache, create a token! - index.addDeclaration(TokenFactory.createToken(index, node.getIdentifierToken()), identifierEntryCache.get(node.getIdentifier())); - else - unmatchedIdentifier.put(node.getIdentifier(), node.getIdentifierToken()); // Not matched actually, put it! - } - - private void addDeclarationToUnmatched(String key, SourceIndex index) { - Entry entry = identifierEntryCache.get(key); - - // This cannot happened in theory - if (entry == null) - return; - for (Identifier identifier : unmatchedIdentifier.get(key)) - index.addDeclaration(TokenFactory.createToken(index, identifier), entry); - unmatchedIdentifier.removeAll(key); - } - - @Override - public Void visitObjectCreationExpression(ObjectCreationExpression node, SourceIndex index) { - MemberReference ref = node.getUserData(Keys.MEMBER_REFERENCE); - if (ref != null && node.getType() instanceof SimpleType) { - SimpleType simpleTypeNode = (SimpleType) node.getType(); - ClassEntry classEntry = new ClassEntry(ref.getDeclaringType().getInternalName()); - MethodEntry constructorEntry = new MethodEntry(classEntry, "", new MethodDescriptor(ref.getErasedSignature())); - index.addReference(TokenFactory.createToken(index, simpleTypeNode.getIdentifierToken()), constructorEntry, this.methodEntry); - } - - return visitChildren(node, index); - } - - @Override - public Void visitVariableDeclaration(VariableDeclarationStatement node, SourceIndex index) { - AstNodeCollection variables = node.getVariables(); - - // Single assignation - if (variables.size() == 1) { - VariableInitializer initializer = variables.firstOrNullObject(); - if (initializer != null && node.getType() instanceof SimpleType) { - Identifier identifier = initializer.getNameToken(); - Variable variable = initializer.getUserData(Keys.VARIABLE); - if (variable != null) { - VariableDefinition originalVariable = variable.getOriginalVariable(); - if (originalVariable != null) { - int variableIndex = originalVariable.getSlot(); - if (variableIndex >= 0) { - MethodDefEntry ownerMethod = EntryParser.parse(originalVariable.getDeclaringMethod()); - TypeDescriptor variableType = EntryParser.parseTypeDescriptor(originalVariable.getVariableType()); - LocalVariableDefEntry localVariableEntry = new LocalVariableDefEntry(ownerMethod, variableIndex, initializer.getName(), false, variableType, null); - identifierEntryCache.put(identifier.getName(), localVariableEntry); - addDeclarationToUnmatched(identifier.getName(), index); - index.addDeclaration(TokenFactory.createToken(index, identifier), localVariableEntry); - } - } - } - } - } - return visitChildren(node, index); - } - - @Override - public Void visitMethodGroupExpression(MethodGroupExpression node, SourceIndex index) { - MemberReference ref = node.getUserData(Keys.MEMBER_REFERENCE); - - if (ref instanceof MethodReference) { - // get the behavior entry - ClassEntry classEntry = new ClassEntry(ref.getDeclaringType().getInternalName()); - MethodEntry methodEntry = new MethodEntry(classEntry, ref.getName(), new MethodDescriptor(ref.getErasedSignature())); - - // get the node for the token - AstNode methodNameToken = node.getMethodNameToken(); - AstNode targetToken = node.getTarget(); - - if (methodNameToken != null) { - index.addReference(TokenFactory.createToken(index, methodNameToken), methodEntry, this.methodEntry); - } - - if (targetToken != null && !(targetToken instanceof ThisReferenceExpression)) { - index.addReference(TokenFactory.createToken(index, targetToken), methodEntry.getParent(), this.methodEntry); - } - } - - return visitChildren(node, index); - } -} diff --git a/src/main/java/cuchaz/enigma/source/procyon/index/SourceIndexVisitor.java b/src/main/java/cuchaz/enigma/source/procyon/index/SourceIndexVisitor.java deleted file mode 100644 index dad505f..0000000 --- a/src/main/java/cuchaz/enigma/source/procyon/index/SourceIndexVisitor.java +++ /dev/null @@ -1,40 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.source.procyon.index; - -import com.strobel.assembler.metadata.TypeDefinition; -import com.strobel.decompiler.languages.java.ast.AstNode; -import com.strobel.decompiler.languages.java.ast.DepthFirstAstVisitor; -import com.strobel.decompiler.languages.java.ast.Keys; -import com.strobel.decompiler.languages.java.ast.TypeDeclaration; -import cuchaz.enigma.source.SourceIndex; -import cuchaz.enigma.source.procyon.EntryParser; -import cuchaz.enigma.translation.representation.entry.ClassDefEntry; - -public class SourceIndexVisitor extends DepthFirstAstVisitor { - @Override - public Void visitTypeDeclaration(TypeDeclaration node, SourceIndex index) { - TypeDefinition def = node.getUserData(Keys.TYPE_DEFINITION); - ClassDefEntry classEntry = EntryParser.parse(def); - index.addDeclaration(TokenFactory.createToken(index, node.getNameToken()), classEntry); - - return node.acceptVisitor(new SourceIndexClassVisitor(classEntry), index); - } - - @Override - protected Void visitChildren(AstNode node, SourceIndex index) { - for (final AstNode child : node.getChildren()) { - child.acceptVisitor(this, index); - } - return null; - } -} diff --git a/src/main/java/cuchaz/enigma/source/procyon/index/TokenFactory.java b/src/main/java/cuchaz/enigma/source/procyon/index/TokenFactory.java deleted file mode 100644 index 62e7c10..0000000 --- a/src/main/java/cuchaz/enigma/source/procyon/index/TokenFactory.java +++ /dev/null @@ -1,46 +0,0 @@ -package cuchaz.enigma.source.procyon.index; - -import com.strobel.decompiler.languages.Region; -import com.strobel.decompiler.languages.java.ast.AstNode; -import com.strobel.decompiler.languages.java.ast.ConstructorDeclaration; -import com.strobel.decompiler.languages.java.ast.Identifier; -import com.strobel.decompiler.languages.java.ast.TypeDeclaration; -import cuchaz.enigma.analysis.Token; -import cuchaz.enigma.source.SourceIndex; - -import java.util.regex.Pattern; - -public class TokenFactory { - private static final Pattern ANONYMOUS_INNER = Pattern.compile("\\$\\d+$"); - - public static Token createToken(SourceIndex index, AstNode node) { - String name = node instanceof Identifier ? ((Identifier) node).getName() : ""; - Region region = node.getRegion(); - - if (region.getBeginLine() == 0) { - System.err.println("Got bad region from Procyon for node " + node); - return null; - } - - int start = index.getPosition(region.getBeginLine(), region.getBeginColumn()); - int end = index.getPosition(region.getEndLine(), region.getEndColumn()); - String text = index.getSource().substring(start, end); - Token token = new Token(start, end, text); - - boolean isAnonymousInner = - node instanceof Identifier && - name.indexOf('$') >= 0 && node.getParent() instanceof ConstructorDeclaration && - name.lastIndexOf('$') >= 0 && - !ANONYMOUS_INNER.matcher(name).matches(); - - if (isAnonymousInner) { - TypeDeclaration type = node.getParent().getParent() instanceof TypeDeclaration ? (TypeDeclaration) node.getParent().getParent() : null; - if (type != null) { - name = type.getName(); - token.end = token.start + name.length(); - } - } - - return token; - } -} diff --git a/src/main/java/cuchaz/enigma/source/procyon/transformers/AddJavadocsAstTransform.java b/src/main/java/cuchaz/enigma/source/procyon/transformers/AddJavadocsAstTransform.java deleted file mode 100644 index 70fc8c6..0000000 --- a/src/main/java/cuchaz/enigma/source/procyon/transformers/AddJavadocsAstTransform.java +++ /dev/null @@ -1,134 +0,0 @@ -package cuchaz.enigma.source.procyon.transformers; - -import com.google.common.base.Function; -import com.google.common.base.Strings; -import com.strobel.assembler.metadata.ParameterDefinition; -import com.strobel.decompiler.languages.java.ast.*; -import com.strobel.decompiler.languages.java.ast.transforms.IAstTransform; -import cuchaz.enigma.source.procyon.EntryParser; -import cuchaz.enigma.translation.mapping.EntryMapping; -import cuchaz.enigma.translation.mapping.EntryRemapper; -import cuchaz.enigma.translation.mapping.ResolutionStrategy; -import cuchaz.enigma.translation.representation.entry.*; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Objects; -import java.util.stream.Stream; - -public final class AddJavadocsAstTransform implements IAstTransform { - - private final EntryRemapper remapper; - - public AddJavadocsAstTransform(EntryRemapper remapper) { - this.remapper = remapper; - } - - @Override - public void run(AstNode compilationUnit) { - compilationUnit.acceptVisitor(new Visitor(remapper), null); - } - - static class Visitor extends DepthFirstAstVisitor { - - private final EntryRemapper remapper; - - Visitor(EntryRemapper remapper) { - this.remapper = remapper; - } - - private void addDoc(T node, Function> retriever) { - final Comment[] comments = getComments(node, retriever); - if (comments != null) { - node.insertChildrenBefore(node.getFirstChild(), Roles.COMMENT, comments); - } - } - - private Comment[] getComments(T node, Function> retriever) { - final EntryMapping mapping = remapper.getDeobfMapping(retriever.apply(node)); - final String docs = mapping == null ? null : Strings.emptyToNull(mapping.getJavadoc()); - return docs == null ? null : Stream.of(docs.split("\\R")).map(st -> new Comment(st, - CommentType.Documentation)).toArray(Comment[]::new); - } - - private Comment[] getParameterComments(ParameterDeclaration node, Function> retriever) { - final EntryMapping mapping = remapper.getDeobfMapping(retriever.apply(node)); - final Comment[] ret = getComments(node, retriever); - if (ret != null) { - final String paramPrefix = "@param " + mapping.getTargetName() + " "; - final String indent = Strings.repeat(" ", paramPrefix.length()); - ret[0].setContent(paramPrefix + ret[0].getContent()); - for (int i = 1; i < ret.length; i++) { - ret[i].setContent(indent + ret[i].getContent()); - } - } - return ret; - } - - private void visitMethod(AstNode node) { - final MethodDefEntry methodDefEntry = EntryParser.parse(node.getUserData(Keys.METHOD_DEFINITION)); - final Comment[] baseComments = getComments(node, $ -> methodDefEntry); - List comments = new ArrayList<>(); - if (baseComments != null) - Collections.addAll(comments, baseComments); - - for (ParameterDeclaration dec : node.getChildrenByRole(Roles.PARAMETER)) { - ParameterDefinition def = dec.getUserData(Keys.PARAMETER_DEFINITION); - final Comment[] paramComments = getParameterComments(dec, $ -> new LocalVariableDefEntry(methodDefEntry, def.getSlot(), def.getName(), - true, - EntryParser.parseTypeDescriptor(def.getParameterType()), null)); - if (paramComments != null) - Collections.addAll(comments, paramComments); - } - - if (!comments.isEmpty()) { - if (remapper.getObfResolver().resolveEntry(methodDefEntry, ResolutionStrategy.RESOLVE_ROOT).stream().noneMatch(e -> Objects.equals(e, methodDefEntry))) { - comments.add(0, new Comment("{@inheritDoc}", CommentType.Documentation)); - } - final AstNode oldFirst = node.getFirstChild(); - for (Comment comment : comments) { - node.insertChildBefore(oldFirst, comment, Roles.COMMENT); - } - } - } - - @Override - protected Void visitChildren(AstNode node, Void data) { - for (final AstNode child : node.getChildren()) { - child.acceptVisitor(this, data); - } - return null; - } - - @Override - public Void visitMethodDeclaration(MethodDeclaration node, Void data) { - visitMethod(node); - return super.visitMethodDeclaration(node, data); - } - - @Override - public Void visitConstructorDeclaration(ConstructorDeclaration node, Void data) { - visitMethod(node); - return super.visitConstructorDeclaration(node, data); - } - - @Override - public Void visitFieldDeclaration(FieldDeclaration node, Void data) { - addDoc(node, dec -> EntryParser.parse(dec.getUserData(Keys.FIELD_DEFINITION))); - return super.visitFieldDeclaration(node, data); - } - - @Override - public Void visitTypeDeclaration(TypeDeclaration node, Void data) { - addDoc(node, dec -> EntryParser.parse(dec.getUserData(Keys.TYPE_DEFINITION))); - return super.visitTypeDeclaration(node, data); - } - - @Override - public Void visitEnumValueDeclaration(EnumValueDeclaration node, Void data) { - addDoc(node, dec -> EntryParser.parse(dec.getUserData(Keys.FIELD_DEFINITION))); - return super.visitEnumValueDeclaration(node, data); - } - } -} diff --git a/src/main/java/cuchaz/enigma/source/procyon/transformers/DropImportAstTransform.java b/src/main/java/cuchaz/enigma/source/procyon/transformers/DropImportAstTransform.java deleted file mode 100644 index 39e599d..0000000 --- a/src/main/java/cuchaz/enigma/source/procyon/transformers/DropImportAstTransform.java +++ /dev/null @@ -1,33 +0,0 @@ -package cuchaz.enigma.source.procyon.transformers; - -import com.strobel.decompiler.languages.java.ast.AstNode; -import com.strobel.decompiler.languages.java.ast.DepthFirstAstVisitor; -import com.strobel.decompiler.languages.java.ast.ImportDeclaration; -import com.strobel.decompiler.languages.java.ast.PackageDeclaration; -import com.strobel.decompiler.languages.java.ast.transforms.IAstTransform; - -public final class DropImportAstTransform implements IAstTransform { - public static final DropImportAstTransform INSTANCE = new DropImportAstTransform(); - - private DropImportAstTransform() { - } - - @Override - public void run(AstNode compilationUnit) { - compilationUnit.acceptVisitor(new Visitor(), null); - } - - static class Visitor extends DepthFirstAstVisitor { - @Override - public Void visitPackageDeclaration(PackageDeclaration node, Void data) { - node.remove(); - return null; - } - - @Override - public Void visitImportDeclaration(ImportDeclaration node, Void data) { - node.remove(); - return null; - } - } -} diff --git a/src/main/java/cuchaz/enigma/source/procyon/transformers/DropVarModifiersAstTransform.java b/src/main/java/cuchaz/enigma/source/procyon/transformers/DropVarModifiersAstTransform.java deleted file mode 100644 index b8c087b..0000000 --- a/src/main/java/cuchaz/enigma/source/procyon/transformers/DropVarModifiersAstTransform.java +++ /dev/null @@ -1,37 +0,0 @@ -package cuchaz.enigma.source.procyon.transformers; - -import com.strobel.decompiler.languages.java.ast.*; -import com.strobel.decompiler.languages.java.ast.transforms.IAstTransform; - -import javax.lang.model.element.Modifier; - -public final class DropVarModifiersAstTransform implements IAstTransform { - public static final DropVarModifiersAstTransform INSTANCE = new DropVarModifiersAstTransform(); - - private DropVarModifiersAstTransform() { - } - - @Override - public void run(AstNode compilationUnit) { - compilationUnit.acceptVisitor(new Visitor(), null); - } - - static class Visitor extends DepthFirstAstVisitor { - @Override - public Void visitParameterDeclaration(ParameterDeclaration node, Void data) { - for (JavaModifierToken modifierToken : node.getChildrenByRole(EntityDeclaration.MODIFIER_ROLE)) { - if (modifierToken.getModifier() == Modifier.FINAL) { - modifierToken.remove(); - } - } - - return null; - } - - @Override - public Void visitVariableDeclaration(VariableDeclarationStatement node, Void data) { - node.removeModifier(Modifier.FINAL); - return null; - } - } -} diff --git a/src/main/java/cuchaz/enigma/source/procyon/transformers/InvalidIdentifierFix.java b/src/main/java/cuchaz/enigma/source/procyon/transformers/InvalidIdentifierFix.java deleted file mode 100644 index 34d95fa..0000000 --- a/src/main/java/cuchaz/enigma/source/procyon/transformers/InvalidIdentifierFix.java +++ /dev/null @@ -1,29 +0,0 @@ -package cuchaz.enigma.source.procyon.transformers; - -import com.strobel.decompiler.languages.java.ast.AstNode; -import com.strobel.decompiler.languages.java.ast.DepthFirstAstVisitor; -import com.strobel.decompiler.languages.java.ast.Identifier; -import com.strobel.decompiler.languages.java.ast.transforms.IAstTransform; - -/** - * Created by Thiakil on 13/07/2018. - */ -public class InvalidIdentifierFix implements IAstTransform { - @Override - public void run(AstNode compilationUnit) { - compilationUnit.acceptVisitor(new Visitor(), null); - } - - class Visitor extends DepthFirstAstVisitor{ - @Override - public Void visitIdentifier(Identifier node, Void data) { - super.visitIdentifier(node, data); - if (node.getName().equals("do") || node.getName().equals("if")){ - Identifier newIdentifier = Identifier.create(node.getName() + "_", node.getStartLocation()); - newIdentifier.copyUserDataFrom(node); - node.replaceWith(newIdentifier); - } - return null; - } - } -} diff --git a/src/main/java/cuchaz/enigma/source/procyon/transformers/Java8Generics.java b/src/main/java/cuchaz/enigma/source/procyon/transformers/Java8Generics.java deleted file mode 100644 index 8accfc7..0000000 --- a/src/main/java/cuchaz/enigma/source/procyon/transformers/Java8Generics.java +++ /dev/null @@ -1,107 +0,0 @@ -package cuchaz.enigma.source.procyon.transformers; - -import com.strobel.assembler.metadata.BuiltinTypes; -import com.strobel.assembler.metadata.CommonTypeReferences; -import com.strobel.assembler.metadata.Flags; -import com.strobel.assembler.metadata.IGenericInstance; -import com.strobel.assembler.metadata.IMemberDefinition; -import com.strobel.assembler.metadata.JvmType; -import com.strobel.assembler.metadata.MemberReference; -import com.strobel.assembler.metadata.MethodDefinition; -import com.strobel.assembler.metadata.TypeDefinition; -import com.strobel.assembler.metadata.TypeReference; -import com.strobel.decompiler.languages.java.ast.ArrayCreationExpression; -import com.strobel.decompiler.languages.java.ast.AstNode; -import com.strobel.decompiler.languages.java.ast.AstNodeCollection; -import com.strobel.decompiler.languages.java.ast.AstType; -import com.strobel.decompiler.languages.java.ast.CastExpression; -import com.strobel.decompiler.languages.java.ast.ComposedType; -import com.strobel.decompiler.languages.java.ast.DepthFirstAstVisitor; -import com.strobel.decompiler.languages.java.ast.Expression; -import com.strobel.decompiler.languages.java.ast.Identifier; -import com.strobel.decompiler.languages.java.ast.InvocationExpression; -import com.strobel.decompiler.languages.java.ast.Keys; -import com.strobel.decompiler.languages.java.ast.MemberReferenceExpression; -import com.strobel.decompiler.languages.java.ast.ObjectCreationExpression; -import com.strobel.decompiler.languages.java.ast.Roles; -import com.strobel.decompiler.languages.java.ast.SimpleType; -import com.strobel.decompiler.languages.java.ast.WildcardType; -import com.strobel.decompiler.languages.java.ast.transforms.IAstTransform; - -/** - * Created by Thiakil on 12/07/2018. - */ -public class Java8Generics implements IAstTransform { - - @Override - public void run(AstNode compilationUnit) { - compilationUnit.acceptVisitor(new Visitor(), null); - } - - static class Visitor extends DepthFirstAstVisitor{ - - @Override - public Void visitInvocationExpression(InvocationExpression node, Void data) { - super.visitInvocationExpression(node, data); - if (node.getTarget() instanceof MemberReferenceExpression){ - MemberReferenceExpression referenceExpression = (MemberReferenceExpression) node.getTarget(); - if (referenceExpression.getTypeArguments().stream().map(t->{ - TypeReference tr = t.toTypeReference(); - if (tr.getDeclaringType() != null){//ensure that inner types are resolved so we can get the TypeDefinition below - TypeReference resolved = tr.resolve(); - if (resolved != null) - return resolved; - } - return tr; - }).anyMatch(t -> t.isWildcardType() || (t instanceof TypeDefinition && ((TypeDefinition) t).isAnonymous()))) { - //these are invalid for invocations, let the compiler work it out - referenceExpression.getTypeArguments().clear(); - } else if (referenceExpression.getTypeArguments().stream().allMatch(t->t.toTypeReference().equals(CommonTypeReferences.Object))){ - //all are , thereby redundant and/or bad - referenceExpression.getTypeArguments().clear(); - } - } - return null; - } - - @Override - public Void visitObjectCreationExpression(ObjectCreationExpression node, Void data) { - super.visitObjectCreationExpression(node, data); - AstType type = node.getType(); - if (type instanceof SimpleType && !((SimpleType) type).getTypeArguments().isEmpty()){ - SimpleType simpleType = (SimpleType) type; - AstNodeCollection typeArguments = simpleType.getTypeArguments(); - if (typeArguments.size() == 1 && typeArguments.firstOrNullObject().toTypeReference().equals(CommonTypeReferences.Object)){ - //all are , thereby redundant and/or bad - typeArguments.firstOrNullObject().getChildByRole(Roles.IDENTIFIER).replaceWith(Identifier.create("")); - } - } - return null; - } - - @Override - public Void visitCastExpression(CastExpression node, Void data) { - boolean doReplace = false; - TypeReference typeReference = node.getType().toTypeReference(); - if (typeReference.isArray() && typeReference.getElementType().isGenericType()){ - doReplace = true; - } else if (typeReference.isGenericType()) { - Expression target = node.getExpression(); - if (typeReference instanceof IGenericInstance && ((IGenericInstance)typeReference).getTypeArguments().stream().anyMatch(t->t.isWildcardType())){ - doReplace = true; - } else if (target instanceof InvocationExpression) { - InvocationExpression invocationExpression = (InvocationExpression)target; - if (invocationExpression.getTarget() instanceof MemberReferenceExpression && !((MemberReferenceExpression) invocationExpression.getTarget()).getTypeArguments().isEmpty()) { - ((MemberReferenceExpression) invocationExpression.getTarget()).getTypeArguments().clear(); - doReplace = true; - } - } - } - super.visitCastExpression(node, data); - if (doReplace){ - node.replaceWith(node.getExpression()); - } - return null; - } - } -} diff --git a/src/main/java/cuchaz/enigma/source/procyon/transformers/ObfuscatedEnumSwitchRewriterTransform.java b/src/main/java/cuchaz/enigma/source/procyon/transformers/ObfuscatedEnumSwitchRewriterTransform.java deleted file mode 100644 index 32bb72f..0000000 --- a/src/main/java/cuchaz/enigma/source/procyon/transformers/ObfuscatedEnumSwitchRewriterTransform.java +++ /dev/null @@ -1,414 +0,0 @@ -/* - * Originally: - * EnumSwitchRewriterTransform.java - * - * Copyright (c) 2013 Mike Strobel - * - * This source code is based on Mono.Cecil from Jb Evain, Copyright (c) Jb Evain; - * and ILSpy/ICSharpCode from SharpDevelop, Copyright (c) AlphaSierraPapa. - * - * This source code is subject to terms and conditions of the Apache License, Version 2.0. - * A copy of the license can be found in the License.html file at the root of this distribution. - * By using this source code in any fashion, you are agreeing to be bound by the terms of the - * Apache License, Version 2.0. - * - * You must not remove this notice, or any other, from this software. - */ - -package cuchaz.enigma.source.procyon.transformers; - -import com.strobel.assembler.metadata.BuiltinTypes; -import com.strobel.assembler.metadata.FieldDefinition; -import com.strobel.assembler.metadata.MethodDefinition; -import com.strobel.assembler.metadata.TypeDefinition; -import com.strobel.assembler.metadata.TypeReference; -import com.strobel.core.SafeCloseable; -import com.strobel.core.VerifyArgument; -import com.strobel.decompiler.DecompilerContext; -import com.strobel.decompiler.languages.java.ast.AssignmentExpression; -import com.strobel.decompiler.languages.java.ast.AstBuilder; -import com.strobel.decompiler.languages.java.ast.AstNode; -import com.strobel.decompiler.languages.java.ast.CaseLabel; -import com.strobel.decompiler.languages.java.ast.ContextTrackingVisitor; -import com.strobel.decompiler.languages.java.ast.Expression; -import com.strobel.decompiler.languages.java.ast.IdentifierExpression; -import com.strobel.decompiler.languages.java.ast.IndexerExpression; -import com.strobel.decompiler.languages.java.ast.InvocationExpression; -import com.strobel.decompiler.languages.java.ast.Keys; -import com.strobel.decompiler.languages.java.ast.MemberReferenceExpression; -import com.strobel.decompiler.languages.java.ast.PrimitiveExpression; -import com.strobel.decompiler.languages.java.ast.SwitchSection; -import com.strobel.decompiler.languages.java.ast.SwitchStatement; -import com.strobel.decompiler.languages.java.ast.TypeDeclaration; -import com.strobel.decompiler.languages.java.ast.TypeReferenceExpression; -import com.strobel.decompiler.languages.java.ast.transforms.IAstTransform; - -import java.util.ArrayList; -import java.util.IdentityHashMap; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; - -/** - * Copy of {@link com.strobel.decompiler.languages.java.ast.transforms.EnumSwitchRewriterTransform} modified to: - * - Not rely on a field containing "$SwitchMap$" (Proguard strips it) - * - Ignore classes *with* SwitchMap$ names (so the original can handle it) - * - Ignores inner synthetics that are not package private - */ -@SuppressWarnings("Duplicates") -public class ObfuscatedEnumSwitchRewriterTransform implements IAstTransform { - private final DecompilerContext _context; - - public ObfuscatedEnumSwitchRewriterTransform(final DecompilerContext context) { - _context = VerifyArgument.notNull(context, "context"); - } - - @Override - public void run(final AstNode compilationUnit) { - compilationUnit.acceptVisitor(new Visitor(_context), null); - } - - private final static class Visitor extends ContextTrackingVisitor { - private final static class SwitchMapInfo { - final String enclosingType; - final Map> switches = new LinkedHashMap<>(); - final Map> mappings = new LinkedHashMap<>(); - - TypeDeclaration enclosingTypeDeclaration; - - SwitchMapInfo(final String enclosingType) { - this.enclosingType = enclosingType; - } - } - - private final Map _switchMaps = new LinkedHashMap<>(); - private boolean _isSwitchMapWrapper; - - protected Visitor(final DecompilerContext context) { - super(context); - } - - @Override - public Void visitTypeDeclaration(final TypeDeclaration typeDeclaration, final Void p) { - final boolean oldIsSwitchMapWrapper = _isSwitchMapWrapper; - final TypeDefinition typeDefinition = typeDeclaration.getUserData(Keys.TYPE_DEFINITION); - final boolean isSwitchMapWrapper = isSwitchMapWrapper(typeDefinition); - - if (isSwitchMapWrapper) { - final String internalName = typeDefinition.getInternalName(); - - SwitchMapInfo info = _switchMaps.get(internalName); - - if (info == null) { - _switchMaps.put(internalName, info = new SwitchMapInfo(internalName)); - } - - info.enclosingTypeDeclaration = typeDeclaration; - } - - _isSwitchMapWrapper = isSwitchMapWrapper; - - try { - super.visitTypeDeclaration(typeDeclaration, p); - } - finally { - _isSwitchMapWrapper = oldIsSwitchMapWrapper; - } - - rewrite(); - - return null; - } - - @Override - public Void visitSwitchStatement(final SwitchStatement node, final Void data) { - final Expression test = node.getExpression(); - - if (test instanceof IndexerExpression) { - final IndexerExpression indexer = (IndexerExpression) test; - final Expression array = indexer.getTarget(); - final Expression argument = indexer.getArgument(); - - if (!(array instanceof MemberReferenceExpression)) { - return super.visitSwitchStatement(node, data); - } - - final MemberReferenceExpression arrayAccess = (MemberReferenceExpression) array; - final Expression arrayOwner = arrayAccess.getTarget(); - final String mapName = arrayAccess.getMemberName(); - - if (mapName == null || mapName.startsWith("$SwitchMap$") || !(arrayOwner instanceof TypeReferenceExpression)) { - return super.visitSwitchStatement(node, data); - } - - final TypeReferenceExpression enclosingTypeExpression = (TypeReferenceExpression) arrayOwner; - final TypeReference enclosingType = enclosingTypeExpression.getType().getUserData(Keys.TYPE_REFERENCE); - - if (!isSwitchMapWrapper(enclosingType) || !(argument instanceof InvocationExpression)) { - return super.visitSwitchStatement(node, data); - } - - final InvocationExpression invocation = (InvocationExpression) argument; - final Expression invocationTarget = invocation.getTarget(); - - if (!(invocationTarget instanceof MemberReferenceExpression)) { - return super.visitSwitchStatement(node, data); - } - - final MemberReferenceExpression memberReference = (MemberReferenceExpression) invocationTarget; - - if (!"ordinal".equals(memberReference.getMemberName())) { - return super.visitSwitchStatement(node, data); - } - - final String enclosingTypeName = enclosingType.getInternalName(); - - SwitchMapInfo info = _switchMaps.get(enclosingTypeName); - - if (info == null) { - _switchMaps.put(enclosingTypeName, info = new SwitchMapInfo(enclosingTypeName)); - - final TypeDefinition resolvedType = enclosingType.resolve(); - - if (resolvedType != null) { - AstBuilder astBuilder = context.getUserData(Keys.AST_BUILDER); - - if (astBuilder == null) { - astBuilder = new AstBuilder(context); - } - - try (final SafeCloseable importSuppression = astBuilder.suppressImports()) { - final TypeDeclaration declaration = astBuilder.createType(resolvedType); - - declaration.acceptVisitor(this, data); - } - } - } - - List switches = info.switches.get(mapName); - - if (switches == null) { - info.switches.put(mapName, switches = new ArrayList<>()); - } - - switches.add(node); - } - - return super.visitSwitchStatement(node, data); - } - - @Override - public Void visitAssignmentExpression(final AssignmentExpression node, final Void data) { - final TypeDefinition currentType = context.getCurrentType(); - final MethodDefinition currentMethod = context.getCurrentMethod(); - - if (_isSwitchMapWrapper && - currentType != null && - currentMethod != null && - currentMethod.isTypeInitializer()) { - - final Expression left = node.getLeft(); - final Expression right = node.getRight(); - - if (left instanceof IndexerExpression && - right instanceof PrimitiveExpression) { - - String mapName = null; - - final Expression array = ((IndexerExpression) left).getTarget(); - final Expression argument = ((IndexerExpression) left).getArgument(); - - if (array instanceof MemberReferenceExpression) { - mapName = ((MemberReferenceExpression) array).getMemberName(); - } - else if (array instanceof IdentifierExpression) { - mapName = ((IdentifierExpression) array).getIdentifier(); - } - - if (mapName == null || mapName.startsWith("$SwitchMap$")) { - return super.visitAssignmentExpression(node, data); - } - - if (!(argument instanceof InvocationExpression)) { - return super.visitAssignmentExpression(node, data); - } - - final InvocationExpression invocation = (InvocationExpression) argument; - final Expression invocationTarget = invocation.getTarget(); - - if (!(invocationTarget instanceof MemberReferenceExpression)) { - return super.visitAssignmentExpression(node, data); - } - - final MemberReferenceExpression memberReference = (MemberReferenceExpression) invocationTarget; - final Expression memberTarget = memberReference.getTarget(); - - if (!(memberTarget instanceof MemberReferenceExpression) || !"ordinal".equals(memberReference.getMemberName())) { - return super.visitAssignmentExpression(node, data); - } - - final MemberReferenceExpression outerMemberReference = (MemberReferenceExpression) memberTarget; - final Expression outerMemberTarget = outerMemberReference.getTarget(); - - if (!(outerMemberTarget instanceof TypeReferenceExpression)) { - return super.visitAssignmentExpression(node, data); - } - - final String enclosingType = currentType.getInternalName(); - - SwitchMapInfo info = _switchMaps.get(enclosingType); - - if (info == null) { - _switchMaps.put(enclosingType, info = new SwitchMapInfo(enclosingType)); - - AstBuilder astBuilder = context.getUserData(Keys.AST_BUILDER); - - if (astBuilder == null) { - astBuilder = new AstBuilder(context); - } - - info.enclosingTypeDeclaration = astBuilder.createType(currentType); - } - - final PrimitiveExpression value = (PrimitiveExpression) right; - - assert value.getValue() instanceof Integer; - - Map mapping = info.mappings.get(mapName); - - if (mapping == null) { - info.mappings.put(mapName, mapping = new LinkedHashMap<>()); - } - - final IdentifierExpression enumValue = new IdentifierExpression( Expression.MYSTERY_OFFSET, outerMemberReference.getMemberName()); - - enumValue.putUserData(Keys.MEMBER_REFERENCE, outerMemberReference.getUserData(Keys.MEMBER_REFERENCE)); - - mapping.put(((Number) value.getValue()).intValue(), enumValue); - } - } - - return super.visitAssignmentExpression(node, data); - } - - private void rewrite() { - if (_switchMaps.isEmpty()) { - return; - } - - for (final SwitchMapInfo info : _switchMaps.values()) { - rewrite(info); - } - - // - // Remove switch map type wrappers that are no longer referenced. - // - - outer: - for (final SwitchMapInfo info : _switchMaps.values()) { - for (final String mapName : info.switches.keySet()) { - final List switches = info.switches.get(mapName); - - if (switches != null && !switches.isEmpty()) { - continue outer; - } - } - - final TypeDeclaration enclosingTypeDeclaration = info.enclosingTypeDeclaration; - - if (enclosingTypeDeclaration != null) { - enclosingTypeDeclaration.remove(); - } - } - } - - private void rewrite(final SwitchMapInfo info) { - if (info.switches.isEmpty()) { - return; - } - - for (final String mapName : info.switches.keySet()) { - final List switches = info.switches.get(mapName); - final Map mappings = info.mappings.get(mapName); - - if (switches != null && mappings != null) { - for (int i = 0; i < switches.size(); i++) { - if (rewriteSwitch(switches.get(i), mappings)) { - switches.remove(i--); - } - } - } - } - } - - private boolean rewriteSwitch(final SwitchStatement s, final Map mappings) { - final Map replacements = new IdentityHashMap<>(); - - for (final SwitchSection section : s.getSwitchSections()) { - for (final CaseLabel caseLabel : section.getCaseLabels()) { - final Expression expression = caseLabel.getExpression(); - - if (expression.isNull()) { - continue; - } - - if (expression instanceof PrimitiveExpression) { - final Object value = ((PrimitiveExpression) expression).getValue(); - - if (value instanceof Integer) { - final Expression replacement = mappings.get(value); - - if (replacement != null) { - replacements.put(expression, replacement); - continue; - } - } - } - - // - // If we can't rewrite all cases, we abort. - // - - return false; - } - } - - final IndexerExpression indexer = (IndexerExpression) s.getExpression(); - final InvocationExpression argument = (InvocationExpression) indexer.getArgument(); - final MemberReferenceExpression memberReference = (MemberReferenceExpression) argument.getTarget(); - final Expression newTest = memberReference.getTarget(); - - newTest.remove(); - indexer.replaceWith(newTest); - - for (final Map.Entry entry : replacements.entrySet()) { - entry.getKey().replaceWith(entry.getValue().clone()); - } - - return true; - } - - private static boolean isSwitchMapWrapper(final TypeReference type) { - if (type == null) { - return false; - } - - final TypeDefinition definition = type instanceof TypeDefinition ? (TypeDefinition) type - : type.resolve(); - - if (definition == null || !definition.isSynthetic() || !definition.isInnerClass() || !definition.isPackagePrivate()) { - return false; - } - - for (final FieldDefinition field : definition.getDeclaredFields()) { - if (!field.getName().startsWith("$SwitchMap$") && - BuiltinTypes.Integer.makeArrayType().equals(field.getFieldType())) { - - return true; - } - } - - return false; - } - } -} \ No newline at end of file diff --git a/src/main/java/cuchaz/enigma/source/procyon/transformers/RemoveObjectCasts.java b/src/main/java/cuchaz/enigma/source/procyon/transformers/RemoveObjectCasts.java deleted file mode 100644 index cf0376f..0000000 --- a/src/main/java/cuchaz/enigma/source/procyon/transformers/RemoveObjectCasts.java +++ /dev/null @@ -1,39 +0,0 @@ -package cuchaz.enigma.source.procyon.transformers; - -import com.strobel.assembler.metadata.BuiltinTypes; -import com.strobel.decompiler.DecompilerContext; -import com.strobel.decompiler.languages.java.ast.AstNode; -import com.strobel.decompiler.languages.java.ast.CastExpression; -import com.strobel.decompiler.languages.java.ast.ContextTrackingVisitor; -import com.strobel.decompiler.languages.java.ast.transforms.IAstTransform; - -/** - * Created by Thiakil on 11/07/2018. - */ -public class RemoveObjectCasts implements IAstTransform { - private final DecompilerContext _context; - - public RemoveObjectCasts(DecompilerContext context) { - _context = context; - } - - @Override - public void run(AstNode compilationUnit) { - compilationUnit.acceptVisitor(new Visitor(_context), null); - } - - private final static class Visitor extends ContextTrackingVisitor{ - - protected Visitor(DecompilerContext context) { - super(context); - } - - @Override - public Void visitCastExpression(CastExpression node, Void data) { - if (node.getType().toTypeReference().equals(BuiltinTypes.Object)){ - node.replaceWith(node.getExpression()); - } - return super.visitCastExpression(node, data); - } - } -} diff --git a/src/main/java/cuchaz/enigma/source/procyon/transformers/VarargsFixer.java b/src/main/java/cuchaz/enigma/source/procyon/transformers/VarargsFixer.java deleted file mode 100644 index d3ddaab..0000000 --- a/src/main/java/cuchaz/enigma/source/procyon/transformers/VarargsFixer.java +++ /dev/null @@ -1,197 +0,0 @@ -package cuchaz.enigma.source.procyon.transformers; - -import com.strobel.assembler.metadata.MemberReference; -import com.strobel.assembler.metadata.MetadataFilters; -import com.strobel.assembler.metadata.MetadataHelper; -import com.strobel.assembler.metadata.MethodBinder; -import com.strobel.assembler.metadata.MethodDefinition; -import com.strobel.assembler.metadata.MethodReference; -import com.strobel.assembler.metadata.TypeReference; -import com.strobel.core.StringUtilities; -import com.strobel.core.VerifyArgument; -import com.strobel.decompiler.DecompilerContext; -import com.strobel.decompiler.languages.java.ast.ArrayCreationExpression; -import com.strobel.decompiler.languages.java.ast.ArrayInitializerExpression; -import com.strobel.decompiler.languages.java.ast.AstNode; -import com.strobel.decompiler.languages.java.ast.AstNodeCollection; -import com.strobel.decompiler.languages.java.ast.CastExpression; -import com.strobel.decompiler.languages.java.ast.ContextTrackingVisitor; -import com.strobel.decompiler.languages.java.ast.DepthFirstAstVisitor; -import com.strobel.decompiler.languages.java.ast.Expression; -import com.strobel.decompiler.languages.java.ast.InvocationExpression; -import com.strobel.decompiler.languages.java.ast.JavaResolver; -import com.strobel.decompiler.languages.java.ast.Keys; -import com.strobel.decompiler.languages.java.ast.MemberReferenceExpression; -import com.strobel.decompiler.languages.java.ast.ObjectCreationExpression; -import com.strobel.decompiler.languages.java.ast.transforms.IAstTransform; -import com.strobel.decompiler.semantics.ResolveResult; - -import java.util.ArrayList; -import java.util.List; - -/** - * Created by Thiakil on 12/07/2018. - */ -public class VarargsFixer implements IAstTransform { - private final DecompilerContext _context; - - public VarargsFixer(final DecompilerContext context) { - _context = VerifyArgument.notNull(context, "context"); - } - - @Override - public void run(AstNode compilationUnit) { - compilationUnit.acceptVisitor(new Visitor(_context), null); - } - - class Visitor extends ContextTrackingVisitor { - private final JavaResolver _resolver; - protected Visitor(DecompilerContext context) { - super(context); - _resolver = new JavaResolver(context); - } - - //remove `new Object[0]` on varagrs as the normal tranformer doesnt do them - @Override - public Void visitInvocationExpression(InvocationExpression node, Void data) { - super.visitInvocationExpression(node, data); - MemberReference definition = node.getUserData(Keys.MEMBER_REFERENCE); - if (definition instanceof MethodDefinition && ((MethodDefinition) definition).isVarArgs()){ - AstNodeCollection arguments = node.getArguments(); - Expression lastParam = arguments.lastOrNullObject(); - if (!lastParam.isNull() && lastParam instanceof ArrayCreationExpression){ - ArrayCreationExpression varargArray = (ArrayCreationExpression)lastParam; - if (varargArray.getInitializer().isNull() || varargArray.getInitializer().getElements().isEmpty()){ - lastParam.remove(); - } else { - for (Expression e : varargArray.getInitializer().getElements()){ - arguments.insertBefore(varargArray, e.clone()); - } - varargArray.remove(); - } - } - } - return null; - } - - //applies the vararg transform to object creation - @Override - public Void visitObjectCreationExpression(ObjectCreationExpression node, Void data) { - super.visitObjectCreationExpression(node, data); - final AstNodeCollection arguments = node.getArguments(); - final Expression lastArgument = arguments.lastOrNullObject(); - - Expression arrayArg = lastArgument; - - if (arrayArg instanceof CastExpression) - arrayArg = ((CastExpression) arrayArg).getExpression(); - - if (arrayArg == null || - arrayArg.isNull() || - !(arrayArg instanceof ArrayCreationExpression && - node.getTarget() instanceof MemberReferenceExpression)) { - - return null; - } - - final ArrayCreationExpression newArray = (ArrayCreationExpression) arrayArg; - final MemberReferenceExpression target = (MemberReferenceExpression) node.getTarget(); - - if (!newArray.getAdditionalArraySpecifiers().hasSingleElement()) { - return null; - } - - final MethodReference method = (MethodReference) node.getUserData(Keys.MEMBER_REFERENCE); - - if (method == null) { - return null; - } - - final MethodDefinition resolved = method.resolve(); - - if (resolved == null || !resolved.isVarArgs()) { - return null; - } - - final List candidates; - final Expression invocationTarget = target.getTarget(); - - if (invocationTarget == null || invocationTarget.isNull()) { - candidates = MetadataHelper.findMethods( - context.getCurrentType(), - MetadataFilters.matchName(resolved.getName()) - ); - } - else { - final ResolveResult targetResult = _resolver.apply(invocationTarget); - - if (targetResult == null || targetResult.getType() == null) { - return null; - } - - candidates = MetadataHelper.findMethods( - targetResult.getType(), - MetadataFilters.matchName(resolved.getName()) - ); - } - - final List argTypes = new ArrayList<>(); - - for (final Expression argument : arguments) { - final ResolveResult argResult = _resolver.apply(argument); - - if (argResult == null || argResult.getType() == null) { - return null; - } - - argTypes.add(argResult.getType()); - } - - final MethodBinder.BindResult c1 = MethodBinder.selectMethod(candidates, argTypes); - - if (c1.isFailure() || c1.isAmbiguous()) { - return null; - } - - argTypes.remove(argTypes.size() - 1); - - final ArrayInitializerExpression initializer = newArray.getInitializer(); - final boolean hasElements = !initializer.isNull() && !initializer.getElements().isEmpty(); - - if (hasElements) { - for (final Expression argument : initializer.getElements()) { - final ResolveResult argResult = _resolver.apply(argument); - - if (argResult == null || argResult.getType() == null) { - return null; - } - - argTypes.add(argResult.getType()); - } - } - - final MethodBinder.BindResult c2 = MethodBinder.selectMethod(candidates, argTypes); - - if (c2.isFailure() || - c2.isAmbiguous() || - !StringUtilities.equals(c2.getMethod().getErasedSignature(), c1.getMethod().getErasedSignature())) { - - return null; - } - - lastArgument.remove(); - - if (!hasElements) { - lastArgument.remove(); - return null; - } - - for (final Expression newArg : initializer.getElements()) { - newArg.remove(); - arguments.add(newArg); - } - - return null; - } - } -} diff --git a/src/main/java/cuchaz/enigma/source/procyon/typeloader/CachingClasspathTypeLoader.java b/src/main/java/cuchaz/enigma/source/procyon/typeloader/CachingClasspathTypeLoader.java deleted file mode 100644 index e702956..0000000 --- a/src/main/java/cuchaz/enigma/source/procyon/typeloader/CachingClasspathTypeLoader.java +++ /dev/null @@ -1,33 +0,0 @@ -package cuchaz.enigma.source.procyon.typeloader; - -import com.strobel.assembler.metadata.Buffer; -import com.strobel.assembler.metadata.ClasspathTypeLoader; -import com.strobel.assembler.metadata.ITypeLoader; - -/** - * Caching version of {@link ClasspathTypeLoader} - */ -public class CachingClasspathTypeLoader extends CachingTypeLoader { - private static ITypeLoader extraClassPathLoader = null; - - public static void setExtraClassPathLoader(ITypeLoader loader){ - extraClassPathLoader = loader; - } - - private final ITypeLoader classpathLoader = new ClasspathTypeLoader(); - - @Override - protected byte[] doLoad(String className) { - Buffer parentBuf = new Buffer(); - if (classpathLoader.tryLoadType(className, parentBuf)) { - return parentBuf.array(); - } - if (extraClassPathLoader != null){ - parentBuf.reset(); - if (extraClassPathLoader.tryLoadType(className, parentBuf)){ - return parentBuf.array(); - } - } - return EMPTY_ARRAY;//need to return *something* as null means no store - } -} diff --git a/src/main/java/cuchaz/enigma/source/procyon/typeloader/CachingTypeLoader.java b/src/main/java/cuchaz/enigma/source/procyon/typeloader/CachingTypeLoader.java deleted file mode 100644 index 5be5ddd..0000000 --- a/src/main/java/cuchaz/enigma/source/procyon/typeloader/CachingTypeLoader.java +++ /dev/null @@ -1,38 +0,0 @@ -package cuchaz.enigma.source.procyon.typeloader; - -import com.google.common.collect.Maps; -import com.strobel.assembler.metadata.Buffer; -import com.strobel.assembler.metadata.ITypeLoader; - -import java.util.Map; - -/** - * Common cache functions - */ -public abstract class CachingTypeLoader implements ITypeLoader { - protected static final byte[] EMPTY_ARRAY = {}; - - private final Map cache = Maps.newHashMap(); - - protected abstract byte[] doLoad(String className); - - @Override - public boolean tryLoadType(String className, Buffer out) { - - // check the cache - byte[] data = this.cache.computeIfAbsent(className, this::doLoad); - - if (data == EMPTY_ARRAY) { - return false; - } - - out.reset(data.length); - System.arraycopy(data, 0, out.array(), out.position(), data.length); - out.position(0); - return true; - } - - public void clearCache() { - this.cache.clear(); - } -} diff --git a/src/main/java/cuchaz/enigma/source/procyon/typeloader/CompiledSourceTypeLoader.java b/src/main/java/cuchaz/enigma/source/procyon/typeloader/CompiledSourceTypeLoader.java deleted file mode 100644 index e703d3b..0000000 --- a/src/main/java/cuchaz/enigma/source/procyon/typeloader/CompiledSourceTypeLoader.java +++ /dev/null @@ -1,140 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.source.procyon.typeloader; - -import com.google.common.collect.Lists; -import com.strobel.assembler.metadata.Buffer; -import com.strobel.assembler.metadata.ITypeLoader; -import cuchaz.enigma.ClassProvider; -import cuchaz.enigma.translation.representation.entry.ClassEntry; -import org.objectweb.asm.ClassVisitor; -import org.objectweb.asm.ClassWriter; -import org.objectweb.asm.Opcodes; -import org.objectweb.asm.tree.AbstractInsnNode; -import org.objectweb.asm.tree.ClassNode; -import org.objectweb.asm.tree.MethodInsnNode; -import org.objectweb.asm.tree.MethodNode; - -import java.util.Collection; -import java.util.LinkedList; -import java.util.List; -import java.util.function.Function; - -public class CompiledSourceTypeLoader extends CachingTypeLoader { - //Store one instance as the classpath shouldn't change during load - private static final ITypeLoader CLASSPATH_TYPE_LOADER = new CachingClasspathTypeLoader(); - - private final ClassProvider compiledSource; - private final LinkedList> visitors = new LinkedList<>(); - - public CompiledSourceTypeLoader(ClassProvider compiledSource) { - this.compiledSource = compiledSource; - } - - public void addVisitor(Function visitor) { - this.visitors.addFirst(visitor); - } - - @Override - protected byte[] doLoad(String className) { - byte[] data = loadType(className); - if (data == null) { - return loadClasspath(className); - } - - return data; - } - - private byte[] loadClasspath(String name) { - Buffer parentBuf = new Buffer(); - if (CLASSPATH_TYPE_LOADER.tryLoadType(name, parentBuf)) { - return parentBuf.array(); - } - return EMPTY_ARRAY; - } - - private byte[] loadType(String className) { - ClassEntry entry = new ClassEntry(className); - - // find the class in the jar - ClassNode node = findClassNode(entry); - if (node == null) { - // couldn't find it - return null; - } - - removeRedundantClassCalls(node); - - ClassWriter writer = new ClassWriter(0); - - ClassVisitor visitor = writer; - for (Function visitorFunction : this.visitors) { - visitor = visitorFunction.apply(visitor); - } - - node.accept(visitor); - - // we have a transformed class! - return writer.toByteArray(); - } - - private void removeRedundantClassCalls(ClassNode node) { - // remove .getClass() calls that are seemingly injected - // DUP - // INVOKEVIRTUAL java/lang/Object.getClass ()Ljava/lang/Class; - // POP - for (MethodNode methodNode : node.methods) { - AbstractInsnNode insnNode = methodNode.instructions.getFirst(); - while (insnNode != null) { - if (insnNode instanceof MethodInsnNode && insnNode.getOpcode() == Opcodes.INVOKEVIRTUAL) { - MethodInsnNode methodInsnNode = (MethodInsnNode) insnNode; - if (methodInsnNode.name.equals("getClass") && methodInsnNode.owner.equals("java/lang/Object") && methodInsnNode.desc.equals("()Ljava/lang/Class;")) { - AbstractInsnNode previous = methodInsnNode.getPrevious(); - AbstractInsnNode next = methodInsnNode.getNext(); - if (previous.getOpcode() == Opcodes.DUP && next.getOpcode() == Opcodes.POP) { - insnNode = previous.getPrevious();//reset the iterator so it gets the new next instruction - methodNode.instructions.remove(previous); - methodNode.instructions.remove(methodInsnNode); - methodNode.instructions.remove(next); - } - } - } - insnNode = insnNode.getNext(); - } - } - } - - private ClassNode findClassNode(ClassEntry entry) { - // try to find the class in the jar - for (String className : getClassNamesToTry(entry)) { - ClassNode node = compiledSource.getClassNode(className); - if (node != null) { - return node; - } - } - - // didn't find it ;_; - return null; - } - - private Collection getClassNamesToTry(ClassEntry entry) { - List classNamesToTry = Lists.newArrayList(); - classNamesToTry.add(entry.getFullName()); - - ClassEntry outerClass = entry.getOuterClass(); - if (outerClass != null) { - classNamesToTry.addAll(getClassNamesToTry(outerClass)); - } - - return classNamesToTry; - } -} diff --git a/src/main/java/cuchaz/enigma/source/procyon/typeloader/NoRetryMetadataSystem.java b/src/main/java/cuchaz/enigma/source/procyon/typeloader/NoRetryMetadataSystem.java deleted file mode 100644 index c4732b0..0000000 --- a/src/main/java/cuchaz/enigma/source/procyon/typeloader/NoRetryMetadataSystem.java +++ /dev/null @@ -1,38 +0,0 @@ -package cuchaz.enigma.source.procyon.typeloader; - -import com.strobel.assembler.metadata.ITypeLoader; -import com.strobel.assembler.metadata.MetadataSystem; -import com.strobel.assembler.metadata.TypeDefinition; -import com.strobel.assembler.metadata.TypeReference; - -import java.util.Collections; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; - -public final class NoRetryMetadataSystem extends MetadataSystem { - private final Set failedTypes = Collections.newSetFromMap(new ConcurrentHashMap<>()); - - public NoRetryMetadataSystem(final ITypeLoader typeLoader) { - super(typeLoader); - } - - @Override - protected synchronized TypeDefinition resolveType(final String descriptor, final boolean mightBePrimitive) { - if (failedTypes.contains(descriptor)) { - return null; - } - - final TypeDefinition result = super.resolveType(descriptor, mightBePrimitive); - - if (result == null) { - failedTypes.add(descriptor); - } - - return result; - } - - @Override - public synchronized TypeDefinition resolve(final TypeReference type) { - return super.resolve(type); - } -} diff --git a/src/main/java/cuchaz/enigma/source/procyon/typeloader/SynchronizedTypeLoader.java b/src/main/java/cuchaz/enigma/source/procyon/typeloader/SynchronizedTypeLoader.java deleted file mode 100644 index 86c6ecc..0000000 --- a/src/main/java/cuchaz/enigma/source/procyon/typeloader/SynchronizedTypeLoader.java +++ /dev/null @@ -1,20 +0,0 @@ -package cuchaz.enigma.source.procyon.typeloader; - -import com.strobel.assembler.metadata.Buffer; -import com.strobel.assembler.metadata.ITypeLoader; - -/** - * Typeloader with synchronized tryLoadType method - */ -public class SynchronizedTypeLoader implements ITypeLoader { - private final ITypeLoader delegate; - - public SynchronizedTypeLoader(ITypeLoader delegate) { - this.delegate = delegate; - } - - @Override - public synchronized boolean tryLoadType(String internalName, Buffer buffer) { - return delegate.tryLoadType(internalName, buffer); - } -} -- cgit v1.2.3