java-decompiler: post-import cleanup (formatting and copyright)

This commit is contained in:
Roman Shevchenko
2014-08-28 21:34:14 +04:00
parent 663631f045
commit 076e4393f2
355 changed files with 38995 additions and 36094 deletions

View File

@@ -1,41 +1,55 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.java.decompiler.modules.renamer;
import org.jetbrains.java.decompiler.struct.StructClass;
import java.util.ArrayList;
import java.util.List;
import org.jetbrains.java.decompiler.struct.StructClass;
public class ClassWrapperNode {
private StructClass classStruct;
private ClassWrapperNode superclass;
private List<ClassWrapperNode> subclasses = new ArrayList<ClassWrapperNode>();
public ClassWrapperNode(StructClass cl) {
this.classStruct = cl;
}
public void addSubclass(ClassWrapperNode node) {
node.setSuperclass(this);
subclasses.add(node);
}
private StructClass classStruct;
public StructClass getClassStruct() {
return classStruct;
}
private ClassWrapperNode superclass;
public List<ClassWrapperNode> getSubclasses() {
return subclasses;
}
private List<ClassWrapperNode> subclasses = new ArrayList<ClassWrapperNode>();
public ClassWrapperNode getSuperclass() {
return superclass;
}
public ClassWrapperNode(StructClass cl) {
this.classStruct = cl;
}
public void setSuperclass(ClassWrapperNode superclass) {
this.superclass = superclass;
}
public void addSubclass(ClassWrapperNode node) {
node.setSuperclass(this);
subclasses.add(node);
}
public StructClass getClassStruct() {
return classStruct;
}
public List<ClassWrapperNode> getSubclasses() {
return subclasses;
}
public ClassWrapperNode getSuperclass() {
return superclass;
}
public void setSuperclass(ClassWrapperNode superclass) {
this.superclass = superclass;
}
}

View File

@@ -1,127 +1,143 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.java.decompiler.modules.renamer;
import java.util.HashSet;
import org.jetbrains.java.decompiler.main.extern.IIdentifierRenamer;
import java.util.HashSet;
public class ConverterHelper implements IIdentifierRenamer {
private static HashSet<String> setReserved = new HashSet<String>();
static {
setReserved.add("abstract");
setReserved.add("do");
setReserved.add("if");
setReserved.add("package");
setReserved.add("synchronized");
setReserved.add("boolean");
setReserved.add("double");
setReserved.add("implements");
setReserved.add("private");
setReserved.add("this");
setReserved.add("break");
setReserved.add("else");
setReserved.add("import");
setReserved.add("protected");
setReserved.add("throw");
setReserved.add("byte");
setReserved.add("extends");
setReserved.add("instanceof");
setReserved.add("public");
setReserved.add("throws");
setReserved.add("case");
setReserved.add("false");
setReserved.add("int");
setReserved.add("return");
setReserved.add("transient");
setReserved.add("catch");
setReserved.add("final");
setReserved.add("interface");
setReserved.add("short");
setReserved.add("true");
setReserved.add("char");
setReserved.add("finally");
setReserved.add("long");
setReserved.add("static");
setReserved.add("try");
setReserved.add("class");
setReserved.add("float");
setReserved.add("native");
setReserved.add("strictfp");
setReserved.add("void");
setReserved.add("const");
setReserved.add("for");
setReserved.add("new");
setReserved.add("super");
setReserved.add("volatile");
setReserved.add("continue");
setReserved.add("goto");
setReserved.add("null");
setReserved.add("switch");
setReserved.add("while");
setReserved.add("default");
setReserved.add("assert");
setReserved.add("enum");
}
private int class_counter = 0;
private int field_counter = 0;
private int method_counter = 0;
private HashSet<String> setNonStandardClassNames = new HashSet<String>();
public boolean toBeRenamed(int element_type, String classname, String element, String descriptor) {
String value = (element_type == IIdentifierRenamer.ELEMENT_CLASS)?classname:element;
return value == null || value.length() == 0 || value.length()<=2 || setReserved.contains(value) || Character.isDigit(value.charAt(0));
}
private static HashSet<String> setReserved = new HashSet<String>();
// TODO: consider possible conflicts with not renamed classes, fields and methods!
// We should get all relevant information here.
public String getNextClassname(String fullname, String shortname) {
static {
setReserved.add("abstract");
setReserved.add("do");
setReserved.add("if");
setReserved.add("package");
setReserved.add("synchronized");
setReserved.add("boolean");
setReserved.add("double");
setReserved.add("implements");
setReserved.add("private");
setReserved.add("this");
setReserved.add("break");
setReserved.add("else");
setReserved.add("import");
setReserved.add("protected");
setReserved.add("throw");
setReserved.add("byte");
setReserved.add("extends");
setReserved.add("instanceof");
setReserved.add("public");
setReserved.add("throws");
setReserved.add("case");
setReserved.add("false");
setReserved.add("int");
setReserved.add("return");
setReserved.add("transient");
setReserved.add("catch");
setReserved.add("final");
setReserved.add("interface");
setReserved.add("short");
setReserved.add("true");
setReserved.add("char");
setReserved.add("finally");
setReserved.add("long");
setReserved.add("static");
setReserved.add("try");
setReserved.add("class");
setReserved.add("float");
setReserved.add("native");
setReserved.add("strictfp");
setReserved.add("void");
setReserved.add("const");
setReserved.add("for");
setReserved.add("new");
setReserved.add("super");
setReserved.add("volatile");
setReserved.add("continue");
setReserved.add("goto");
setReserved.add("null");
setReserved.add("switch");
setReserved.add("while");
setReserved.add("default");
setReserved.add("assert");
setReserved.add("enum");
}
if(shortname == null) {
return "class_"+(class_counter++);
}
int index = 0;
while(Character.isDigit(shortname.charAt(index))) {
index++;
}
private int class_counter = 0;
if(index == 0 || index == shortname.length()) {
return "class_"+(class_counter++);
} else {
String name = shortname.substring(index);
if(setNonStandardClassNames.contains(name)) {
return "Inner"+name+"_"+(class_counter++);
} else {
setNonStandardClassNames.add(name);
return "Inner"+name;
}
}
}
public String getNextFieldname(String classname, String field, String descriptor) {
return "field_"+(field_counter++);
}
private int field_counter = 0;
public String getNextMethodname(String classname, String method, String descriptor) {
return "method_"+(method_counter++);
}
// *****************************************************************************
// static methods
// *****************************************************************************
public static String getSimpleClassName(String fullname) {
return fullname.substring(fullname.lastIndexOf('/')+1);
}
private int method_counter = 0;
public static String replaceSimpleClassName(String fullname, String newname) {
return fullname.substring(0, fullname.lastIndexOf('/')+1)+newname;
}
private HashSet<String> setNonStandardClassNames = new HashSet<String>();
public boolean toBeRenamed(int element_type, String classname, String element, String descriptor) {
String value = (element_type == IIdentifierRenamer.ELEMENT_CLASS) ? classname : element;
return value == null || value.length() == 0 || value.length() <= 2 || setReserved.contains(value) || Character.isDigit(value.charAt(0));
}
// TODO: consider possible conflicts with not renamed classes, fields and methods!
// We should get all relevant information here.
public String getNextClassname(String fullname, String shortname) {
if (shortname == null) {
return "class_" + (class_counter++);
}
int index = 0;
while (Character.isDigit(shortname.charAt(index))) {
index++;
}
if (index == 0 || index == shortname.length()) {
return "class_" + (class_counter++);
}
else {
String name = shortname.substring(index);
if (setNonStandardClassNames.contains(name)) {
return "Inner" + name + "_" + (class_counter++);
}
else {
setNonStandardClassNames.add(name);
return "Inner" + name;
}
}
}
public String getNextFieldname(String classname, String field, String descriptor) {
return "field_" + (field_counter++);
}
public String getNextMethodname(String classname, String method, String descriptor) {
return "method_" + (method_counter++);
}
// *****************************************************************************
// static methods
// *****************************************************************************
public static String getSimpleClassName(String fullname) {
return fullname.substring(fullname.lastIndexOf('/') + 1);
}
public static String replaceSimpleClassName(String fullname, String newname) {
return fullname.substring(0, fullname.lastIndexOf('/') + 1) + newname;
}
}

View File

@@ -1,12 +1,20 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.java.decompiler.modules.renamer;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import org.jetbrains.java.decompiler.code.CodeConstants;
import org.jetbrains.java.decompiler.main.DecompilerContext;
import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences;
@@ -20,428 +28,437 @@ import org.jetbrains.java.decompiler.struct.gen.MethodDescriptor;
import org.jetbrains.java.decompiler.struct.gen.VarType;
import org.jetbrains.java.decompiler.util.VBStyleCollection;
import java.io.IOException;
import java.util.*;
public class IdentifierConverter {
private StructContext context;
private IIdentifierRenamer helper;
private StructContext context;
private PoolInterceptor interceptor;
private List<ClassWrapperNode> rootClasses = new ArrayList<ClassWrapperNode>();
private IIdentifierRenamer helper;
private List<ClassWrapperNode> rootInterfaces = new ArrayList<ClassWrapperNode>();
private HashMap<String, HashMap<String, String>> interfaceNameMaps = new HashMap<String, HashMap<String, String>>();
public void rename(StructContext context) {
try {
this.context = context;
String user_class = (String)DecompilerContext.getProperty(IFernflowerPreferences.USER_RENAMER_CLASS);
if(user_class != null) {
try {
helper = (IIdentifierRenamer)IdentifierConverter.class.getClassLoader().loadClass(user_class).newInstance();
} catch(Exception ex) {
; // ignore errors
}
}
if(helper == null) {
helper = new ConverterHelper();
}
interceptor = new PoolInterceptor(helper);
buildInheritanceTree();
renameAllClasses();
renameInterfaces();
renameClasses();
DecompilerContext.setPoolInterceptor(interceptor);
context.reloadContext();
} catch(IOException ex){
throw new RuntimeException("Renaming failed!");
}
}
private void renameClasses() {
List<ClassWrapperNode> lstClasses = getReversePostOrderListIterative(rootClasses);
HashMap<String, HashMap<String, String>> classNameMaps = new HashMap<String, HashMap<String, String>>();
for(ClassWrapperNode node : lstClasses) {
StructClass cl = node.getClassStruct();
HashMap<String, String> names = new HashMap<String, String>();
private PoolInterceptor interceptor;
// merge informations on super class
if(cl.superClass != null) {
HashMap<String, String> mapClass = classNameMaps.get(cl.superClass.getString());
if(mapClass != null) {
names.putAll(mapClass);
}
}
// merge informations on interfaces
for(String intrName : cl.getInterfaceNames()) {
HashMap<String, String> mapInt = interfaceNameMaps.get(intrName);
if(mapInt != null) {
names.putAll(mapInt);
} else {
StructClass clintr = context.getClass(intrName);
if(clintr!=null) {
names.putAll(processExternalInterface(clintr));
}
}
}
renameClassIdentifiers(cl, names);
private List<ClassWrapperNode> rootClasses = new ArrayList<ClassWrapperNode>();
if(!node.getSubclasses().isEmpty()) {
classNameMaps.put(cl.qualifiedName, names);
}
}
}
private HashMap<String, String> processExternalInterface(StructClass cl) {
HashMap<String, String> names = new HashMap<String, String>();
for(String intrName : cl.getInterfaceNames()) {
private List<ClassWrapperNode> rootInterfaces = new ArrayList<ClassWrapperNode>();
HashMap<String, String> mapInt = interfaceNameMaps.get(intrName);
if(mapInt != null) {
names.putAll(mapInt);
} else {
StructClass clintr = context.getClass(intrName);
if(clintr!=null) {
names.putAll(processExternalInterface(clintr));
}
}
}
renameClassIdentifiers(cl, names);
return names;
}
private void renameInterfaces() {
private HashMap<String, HashMap<String, String>> interfaceNameMaps = new HashMap<String, HashMap<String, String>>();
List<ClassWrapperNode> lstInterfaces = getReversePostOrderListIterative(rootInterfaces);
HashMap<String, HashMap<String, String>> interfaceNameMaps = new HashMap<String, HashMap<String, String>>();
// rename methods and fields
for(ClassWrapperNode node : lstInterfaces) {
StructClass cl = node.getClassStruct();
HashMap<String, String> names = new HashMap<String, String>();
public void rename(StructContext context) {
// merge informations on super interfaces
for(String intrName : cl.getInterfaceNames()) {
HashMap<String, String> mapInt = interfaceNameMaps.get(intrName);
if(mapInt != null) {
names.putAll(mapInt);
}
}
renameClassIdentifiers(cl, names);
try {
this.context = context;
interfaceNameMaps.put(cl.qualifiedName, names);
}
this.interfaceNameMaps = interfaceNameMaps;
}
String user_class = (String)DecompilerContext.getProperty(IFernflowerPreferences.USER_RENAMER_CLASS);
if (user_class != null) {
try {
helper = (IIdentifierRenamer)IdentifierConverter.class.getClassLoader().loadClass(user_class).newInstance();
}
catch (Exception ex) {
; // ignore errors
}
}
private void renameAllClasses() {
if (helper == null) {
helper = new ConverterHelper();
}
// order not important
List<ClassWrapperNode> lstAllClasses = new ArrayList<ClassWrapperNode>(getReversePostOrderListIterative(rootInterfaces));
lstAllClasses.addAll(getReversePostOrderListIterative(rootClasses));
// rename all interfaces and classes
for(ClassWrapperNode node : lstAllClasses) {
renameClass(node.getClassStruct());
}
}
private void renameClass(StructClass cl) {
interceptor = new PoolInterceptor(helper);
if(!cl.isOwn()) {
return;
}
String classOldFullName = cl.qualifiedName;
String classNewFullName = classOldFullName;
buildInheritanceTree();
// TODO: rename packages
String clsimplename = ConverterHelper.getSimpleClassName(classOldFullName);
if(helper.toBeRenamed(IIdentifierRenamer.ELEMENT_CLASS, clsimplename, null, null)) {
do {
classNewFullName = ConverterHelper.replaceSimpleClassName(classOldFullName,
helper.getNextClassname(classOldFullName, ConverterHelper.getSimpleClassName(classOldFullName)));
} while(context.getClasses().containsKey(classNewFullName));
interceptor.addName(classOldFullName, classNewFullName);
}
renameAllClasses();
}
private void renameClassIdentifiers(StructClass cl, HashMap<String, String> names) {
renameInterfaces();
// all classes are already renamed
String classOldFullName = cl.qualifiedName;
String classNewFullName = interceptor.getName(classOldFullName);
renameClasses();
if(classNewFullName == null) {
classNewFullName = classOldFullName;
}
// methods
HashSet<String> setMethodNames = new HashSet<String>();
for(StructMethod md : cl.getMethods()) {
setMethodNames.add(md.getName());
}
VBStyleCollection<StructMethod, String> methods = cl.getMethods();
for(int i=0;i<methods.size();i++) {
StructMethod mt = methods.get(i);
String key = methods.getKey(i);
int access_flags = mt.getAccessFlags();
boolean isPrivate = ((access_flags & CodeConstants.ACC_PRIVATE) != 0);
DecompilerContext.setPoolInterceptor(interceptor);
context.reloadContext();
}
catch (IOException ex) {
throw new RuntimeException("Renaming failed!");
}
}
String name = mt.getName();
if(!cl.isOwn() || (access_flags & CodeConstants.ACC_NATIVE) != 0) {
// external and native methods must not be renamed
if(!isPrivate) {
names.put(key, name);
}
} else if(helper.toBeRenamed(IIdentifierRenamer.ELEMENT_METHOD, classOldFullName, name, mt.getDescriptor())) {
if(isPrivate || !names.containsKey(key)) {
do {
name = helper.getNextMethodname(classOldFullName, name, mt.getDescriptor());
} while(setMethodNames.contains(name));
if(!isPrivate) {
names.put(key, name);
}
} else {
name = names.get(key);
}
private void renameClasses() {
interceptor.addName(classOldFullName+" "+mt.getName()+" "+mt.getDescriptor(),
classNewFullName+" "+name+" "+buildNewDescriptor(false, mt.getDescriptor()));
}
}
// external fields are not being renamed
if(!cl.isOwn()) {
return;
}
// fields
// FIXME: should overloaded fields become the same name?
HashSet<String> setFieldNames = new HashSet<String>();
for(StructField fd : cl.getFields()) {
setFieldNames.add(fd.getName());
}
for(StructField fd : cl.getFields()) {
if(helper.toBeRenamed(IIdentifierRenamer.ELEMENT_FIELD, classOldFullName, fd.getName(), fd.getDescriptor())) {
String newname;
do {
newname = helper.getNextFieldname(classOldFullName, fd.getName(), fd.getDescriptor());
} while(setFieldNames.contains(newname));
List<ClassWrapperNode> lstClasses = getReversePostOrderListIterative(rootClasses);
interceptor.addName(classOldFullName+" "+fd.getName()+" "+fd.getDescriptor(),
classNewFullName+" "+newname+" "+buildNewDescriptor(true, fd.getDescriptor()));
}
}
HashMap<String, HashMap<String, String>> classNameMaps = new HashMap<String, HashMap<String, String>>();
}
private String buildNewDescriptor(boolean isField, String descriptor) {
for (ClassWrapperNode node : lstClasses) {
boolean updated = false;
if(isField) {
FieldDescriptor fd = FieldDescriptor.parseDescriptor(descriptor);
StructClass cl = node.getClassStruct();
HashMap<String, String> names = new HashMap<String, String>();
VarType ftype = fd.type;
if(ftype.type == CodeConstants.TYPE_OBJECT) {
String newclname = interceptor.getName(ftype.value);
if(newclname != null) {
ftype.value = newclname;
updated = true;
}
}
if(updated) {
return fd.getDescriptor();
}
} else {
MethodDescriptor md = MethodDescriptor.parseDescriptor(descriptor);
// params
for(VarType partype : md.params) {
if(partype.type == CodeConstants.TYPE_OBJECT) {
String newclname = interceptor.getName(partype.value);
if(newclname != null) {
partype.value = newclname;
updated = true;
}
}
}
// return value
if(md.ret.type == CodeConstants.TYPE_OBJECT) {
String newclname = interceptor.getName(md.ret.value);
if(newclname!=null) {
md.ret.value = newclname;
updated = true;
}
}
if(updated) {
return md.getDescriptor();
}
}
return descriptor;
}
private List<ClassWrapperNode> getReversePostOrderListIterative(List<ClassWrapperNode> roots) {
List<ClassWrapperNode> res = new ArrayList<ClassWrapperNode>();
LinkedList<ClassWrapperNode> stackNode = new LinkedList<ClassWrapperNode>();
LinkedList<Integer> stackIndex = new LinkedList<Integer>();
HashSet<ClassWrapperNode> setVisited = new HashSet<ClassWrapperNode>();
for(ClassWrapperNode root : roots) {
stackNode.add(root);
stackIndex.add(0);
}
while(!stackNode.isEmpty()) {
ClassWrapperNode node = stackNode.getLast();
int index = stackIndex.removeLast();
// merge informations on super class
if (cl.superClass != null) {
HashMap<String, String> mapClass = classNameMaps.get(cl.superClass.getString());
if (mapClass != null) {
names.putAll(mapClass);
}
}
setVisited.add(node);
List<ClassWrapperNode> lstSubs = node.getSubclasses();
for(; index < lstSubs.size(); index++) {
ClassWrapperNode sub = lstSubs.get(index);
if(!setVisited.contains(sub)) {
stackIndex.add(index+1);
stackNode.add(sub);
stackIndex.add(0);
break;
}
}
// merge informations on interfaces
for (String intrName : cl.getInterfaceNames()) {
HashMap<String, String> mapInt = interfaceNameMaps.get(intrName);
if (mapInt != null) {
names.putAll(mapInt);
}
else {
StructClass clintr = context.getClass(intrName);
if (clintr != null) {
names.putAll(processExternalInterface(clintr));
}
}
}
if(index == lstSubs.size()) {
res.add(0, node);
stackNode.removeLast();
}
}
return res;
}
private void buildInheritanceTree() {
HashMap<String, ClassWrapperNode> nodes = new HashMap<String, ClassWrapperNode>();
HashMap<String, StructClass> classes = context.getClasses();
renameClassIdentifiers(cl, names);
List<ClassWrapperNode> rootClasses = new ArrayList<ClassWrapperNode>();
List<ClassWrapperNode> rootInterfaces = new ArrayList<ClassWrapperNode>();
if (!node.getSubclasses().isEmpty()) {
classNameMaps.put(cl.qualifiedName, names);
}
}
}
for(StructClass cl : classes.values()) {
if(!cl.isOwn()) {
continue;
}
private HashMap<String, String> processExternalInterface(StructClass cl) {
LinkedList<StructClass> stack = new LinkedList<StructClass>();
LinkedList<ClassWrapperNode> stackSubnodes = new LinkedList<ClassWrapperNode>();
stack.add(cl);
stackSubnodes.add(null);
while(!stack.isEmpty()) {
StructClass clstr = stack.removeFirst();
ClassWrapperNode child = stackSubnodes.removeFirst();
ClassWrapperNode node = nodes.get(clstr.qualifiedName);
boolean isNewNode = (node == null);
if(isNewNode) {
nodes.put(clstr.qualifiedName, node = new ClassWrapperNode(clstr));
}
if(child!=null) {
node.addSubclass(child);
}
if(!isNewNode) {
break;
} else {
HashMap<String, String> names = new HashMap<String, String>();
boolean isInterface = ((clstr.access_flags & CodeConstants.ACC_INTERFACE) != 0);
boolean found_parent = false;
if(isInterface) {
for(String intrName : clstr.getInterfaceNames()) {
StructClass clparent = classes.get(intrName);
if(clparent != null) {
stack.add(clparent);
stackSubnodes.add(node);
found_parent = true;
}
}
} else {
if(clstr.superClass != null) { // null iff java/lang/Object
StructClass clparent = classes.get(clstr.superClass.getString());
for (String intrName : cl.getInterfaceNames()) {
if(clparent != null) {
stack.add(clparent);
stackSubnodes.add(node);
found_parent = true;
}
}
}
HashMap<String, String> mapInt = interfaceNameMaps.get(intrName);
if (mapInt != null) {
names.putAll(mapInt);
}
else {
StructClass clintr = context.getClass(intrName);
if (clintr != null) {
names.putAll(processExternalInterface(clintr));
}
}
}
if(!found_parent) { // no super class or interface
(isInterface?rootInterfaces:rootClasses).add(node);
}
}
}
}
this.rootClasses = rootClasses;
this.rootInterfaces = rootInterfaces;
}
renameClassIdentifiers(cl, names);
return names;
}
private void renameInterfaces() {
List<ClassWrapperNode> lstInterfaces = getReversePostOrderListIterative(rootInterfaces);
HashMap<String, HashMap<String, String>> interfaceNameMaps = new HashMap<String, HashMap<String, String>>();
// rename methods and fields
for (ClassWrapperNode node : lstInterfaces) {
StructClass cl = node.getClassStruct();
HashMap<String, String> names = new HashMap<String, String>();
// merge informations on super interfaces
for (String intrName : cl.getInterfaceNames()) {
HashMap<String, String> mapInt = interfaceNameMaps.get(intrName);
if (mapInt != null) {
names.putAll(mapInt);
}
}
renameClassIdentifiers(cl, names);
interfaceNameMaps.put(cl.qualifiedName, names);
}
this.interfaceNameMaps = interfaceNameMaps;
}
private void renameAllClasses() {
// order not important
List<ClassWrapperNode> lstAllClasses = new ArrayList<ClassWrapperNode>(getReversePostOrderListIterative(rootInterfaces));
lstAllClasses.addAll(getReversePostOrderListIterative(rootClasses));
// rename all interfaces and classes
for (ClassWrapperNode node : lstAllClasses) {
renameClass(node.getClassStruct());
}
}
private void renameClass(StructClass cl) {
if (!cl.isOwn()) {
return;
}
String classOldFullName = cl.qualifiedName;
String classNewFullName = classOldFullName;
// TODO: rename packages
String clsimplename = ConverterHelper.getSimpleClassName(classOldFullName);
if (helper.toBeRenamed(IIdentifierRenamer.ELEMENT_CLASS, clsimplename, null, null)) {
do {
classNewFullName = ConverterHelper.replaceSimpleClassName(classOldFullName,
helper.getNextClassname(classOldFullName, ConverterHelper
.getSimpleClassName(classOldFullName)));
}
while (context.getClasses().containsKey(classNewFullName));
interceptor.addName(classOldFullName, classNewFullName);
}
}
private void renameClassIdentifiers(StructClass cl, HashMap<String, String> names) {
// all classes are already renamed
String classOldFullName = cl.qualifiedName;
String classNewFullName = interceptor.getName(classOldFullName);
if (classNewFullName == null) {
classNewFullName = classOldFullName;
}
// methods
HashSet<String> setMethodNames = new HashSet<String>();
for (StructMethod md : cl.getMethods()) {
setMethodNames.add(md.getName());
}
VBStyleCollection<StructMethod, String> methods = cl.getMethods();
for (int i = 0; i < methods.size(); i++) {
StructMethod mt = methods.get(i);
String key = methods.getKey(i);
int access_flags = mt.getAccessFlags();
boolean isPrivate = ((access_flags & CodeConstants.ACC_PRIVATE) != 0);
String name = mt.getName();
if (!cl.isOwn() || (access_flags & CodeConstants.ACC_NATIVE) != 0) {
// external and native methods must not be renamed
if (!isPrivate) {
names.put(key, name);
}
}
else if (helper.toBeRenamed(IIdentifierRenamer.ELEMENT_METHOD, classOldFullName, name, mt.getDescriptor())) {
if (isPrivate || !names.containsKey(key)) {
do {
name = helper.getNextMethodname(classOldFullName, name, mt.getDescriptor());
}
while (setMethodNames.contains(name));
if (!isPrivate) {
names.put(key, name);
}
}
else {
name = names.get(key);
}
interceptor.addName(classOldFullName + " " + mt.getName() + " " + mt.getDescriptor(),
classNewFullName + " " + name + " " + buildNewDescriptor(false, mt.getDescriptor()));
}
}
// external fields are not being renamed
if (!cl.isOwn()) {
return;
}
// fields
// FIXME: should overloaded fields become the same name?
HashSet<String> setFieldNames = new HashSet<String>();
for (StructField fd : cl.getFields()) {
setFieldNames.add(fd.getName());
}
for (StructField fd : cl.getFields()) {
if (helper.toBeRenamed(IIdentifierRenamer.ELEMENT_FIELD, classOldFullName, fd.getName(), fd.getDescriptor())) {
String newname;
do {
newname = helper.getNextFieldname(classOldFullName, fd.getName(), fd.getDescriptor());
}
while (setFieldNames.contains(newname));
interceptor.addName(classOldFullName + " " + fd.getName() + " " + fd.getDescriptor(),
classNewFullName + " " + newname + " " + buildNewDescriptor(true, fd.getDescriptor()));
}
}
}
private String buildNewDescriptor(boolean isField, String descriptor) {
boolean updated = false;
if (isField) {
FieldDescriptor fd = FieldDescriptor.parseDescriptor(descriptor);
VarType ftype = fd.type;
if (ftype.type == CodeConstants.TYPE_OBJECT) {
String newclname = interceptor.getName(ftype.value);
if (newclname != null) {
ftype.value = newclname;
updated = true;
}
}
if (updated) {
return fd.getDescriptor();
}
}
else {
MethodDescriptor md = MethodDescriptor.parseDescriptor(descriptor);
// params
for (VarType partype : md.params) {
if (partype.type == CodeConstants.TYPE_OBJECT) {
String newclname = interceptor.getName(partype.value);
if (newclname != null) {
partype.value = newclname;
updated = true;
}
}
}
// return value
if (md.ret.type == CodeConstants.TYPE_OBJECT) {
String newclname = interceptor.getName(md.ret.value);
if (newclname != null) {
md.ret.value = newclname;
updated = true;
}
}
if (updated) {
return md.getDescriptor();
}
}
return descriptor;
}
private List<ClassWrapperNode> getReversePostOrderListIterative(List<ClassWrapperNode> roots) {
List<ClassWrapperNode> res = new ArrayList<ClassWrapperNode>();
LinkedList<ClassWrapperNode> stackNode = new LinkedList<ClassWrapperNode>();
LinkedList<Integer> stackIndex = new LinkedList<Integer>();
HashSet<ClassWrapperNode> setVisited = new HashSet<ClassWrapperNode>();
for (ClassWrapperNode root : roots) {
stackNode.add(root);
stackIndex.add(0);
}
while (!stackNode.isEmpty()) {
ClassWrapperNode node = stackNode.getLast();
int index = stackIndex.removeLast();
setVisited.add(node);
List<ClassWrapperNode> lstSubs = node.getSubclasses();
for (; index < lstSubs.size(); index++) {
ClassWrapperNode sub = lstSubs.get(index);
if (!setVisited.contains(sub)) {
stackIndex.add(index + 1);
stackNode.add(sub);
stackIndex.add(0);
break;
}
}
if (index == lstSubs.size()) {
res.add(0, node);
stackNode.removeLast();
}
}
return res;
}
private void buildInheritanceTree() {
HashMap<String, ClassWrapperNode> nodes = new HashMap<String, ClassWrapperNode>();
HashMap<String, StructClass> classes = context.getClasses();
List<ClassWrapperNode> rootClasses = new ArrayList<ClassWrapperNode>();
List<ClassWrapperNode> rootInterfaces = new ArrayList<ClassWrapperNode>();
for (StructClass cl : classes.values()) {
if (!cl.isOwn()) {
continue;
}
LinkedList<StructClass> stack = new LinkedList<StructClass>();
LinkedList<ClassWrapperNode> stackSubnodes = new LinkedList<ClassWrapperNode>();
stack.add(cl);
stackSubnodes.add(null);
while (!stack.isEmpty()) {
StructClass clstr = stack.removeFirst();
ClassWrapperNode child = stackSubnodes.removeFirst();
ClassWrapperNode node = nodes.get(clstr.qualifiedName);
boolean isNewNode = (node == null);
if (isNewNode) {
nodes.put(clstr.qualifiedName, node = new ClassWrapperNode(clstr));
}
if (child != null) {
node.addSubclass(child);
}
if (!isNewNode) {
break;
}
else {
boolean isInterface = ((clstr.access_flags & CodeConstants.ACC_INTERFACE) != 0);
boolean found_parent = false;
if (isInterface) {
for (String intrName : clstr.getInterfaceNames()) {
StructClass clparent = classes.get(intrName);
if (clparent != null) {
stack.add(clparent);
stackSubnodes.add(node);
found_parent = true;
}
}
}
else {
if (clstr.superClass != null) { // null iff java/lang/Object
StructClass clparent = classes.get(clstr.superClass.getString());
if (clparent != null) {
stack.add(clparent);
stackSubnodes.add(node);
found_parent = true;
}
}
}
if (!found_parent) { // no super class or interface
(isInterface ? rootInterfaces : rootClasses).add(node);
}
}
}
}
this.rootClasses = rootClasses;
this.rootInterfaces = rootInterfaces;
}
}

View File

@@ -1,36 +1,50 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.java.decompiler.modules.renamer;
import java.util.HashMap;
import org.jetbrains.java.decompiler.main.extern.IIdentifierRenamer;
import java.util.HashMap;
public class PoolInterceptor {
private IIdentifierRenamer helper;
private HashMap<String, String> mapOldToNewNames = new HashMap<String, String>();
private HashMap<String, String> mapNewToOldNames = new HashMap<String, String>();
private IIdentifierRenamer helper;
public PoolInterceptor(IIdentifierRenamer helper) {
this.helper = helper;
}
public void addName(String oldName, String newName) {
mapOldToNewNames.put(oldName, newName);
mapNewToOldNames.put(newName, oldName);
}
private HashMap<String, String> mapOldToNewNames = new HashMap<String, String>();
public String getName(String oldName) {
return mapOldToNewNames.get(oldName);
}
private HashMap<String, String> mapNewToOldNames = new HashMap<String, String>();
public String getOldName(String newName) {
return mapNewToOldNames.get(newName);
}
public PoolInterceptor(IIdentifierRenamer helper) {
this.helper = helper;
}
public IIdentifierRenamer getHelper() {
return helper;
}
public void addName(String oldName, String newName) {
mapOldToNewNames.put(oldName, newName);
mapNewToOldNames.put(newName, oldName);
}
public String getName(String oldName) {
return mapOldToNewNames.get(oldName);
}
public String getOldName(String newName) {
return mapNewToOldNames.get(newName);
}
public IIdentifierRenamer getHelper() {
return helper;
}
}