summaryrefslogtreecommitdiffstats
path: root/src/org/jetbrains/java/decompiler/modules/renamer
diff options
context:
space:
mode:
authorRoman Shevchenko <roman.shevchenko@jetbrains.com>2014-08-28 21:34:14 +0400
committerRoman Shevchenko <roman.shevchenko@jetbrains.com>2014-08-28 21:34:19 +0400
commit076e4393f25bf1ad1ff1bd2853153e2b595dd90b (patch)
treef1a17a12ea762525b5efbc0778b0945d906c68c9 /src/org/jetbrains/java/decompiler/modules/renamer
parent663631f0456fcc245dd835889f86541d75161c53 (diff)
downloadfernflower-076e4393f25bf1ad1ff1bd2853153e2b595dd90b.tar
fernflower-076e4393f25bf1ad1ff1bd2853153e2b595dd90b.tar.gz
fernflower-076e4393f25bf1ad1ff1bd2853153e2b595dd90b.tar.lz
fernflower-076e4393f25bf1ad1ff1bd2853153e2b595dd90b.tar.xz
fernflower-076e4393f25bf1ad1ff1bd2853153e2b595dd90b.zip
java-decompiler: post-import cleanup (formatting and copyright)
Diffstat (limited to 'src/org/jetbrains/java/decompiler/modules/renamer')
-rw-r--r--src/org/jetbrains/java/decompiler/modules/renamer/ClassWrapperNode.java78
-rw-r--r--src/org/jetbrains/java/decompiler/modules/renamer/ConverterHelper.java256
-rw-r--r--src/org/jetbrains/java/decompiler/modules/renamer/IdentifierConverter.java875
-rw-r--r--src/org/jetbrains/java/decompiler/modules/renamer/PoolInterceptor.java72
4 files changed, 671 insertions, 610 deletions
diff --git a/src/org/jetbrains/java/decompiler/modules/renamer/ClassWrapperNode.java b/src/org/jetbrains/java/decompiler/modules/renamer/ClassWrapperNode.java
index a3015a8..273579a 100644
--- a/src/org/jetbrains/java/decompiler/modules/renamer/ClassWrapperNode.java
+++ b/src/org/jetbrains/java/decompiler/modules/renamer/ClassWrapperNode.java
@@ -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);
- }
-
- public StructClass getClassStruct() {
- return classStruct;
- }
-
- public List<ClassWrapperNode> getSubclasses() {
- return subclasses;
- }
-
- public ClassWrapperNode getSuperclass() {
- return superclass;
- }
-
- public void setSuperclass(ClassWrapperNode superclass) {
- this.superclass = superclass;
- }
+ 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);
+ }
+
+ public StructClass getClassStruct() {
+ return classStruct;
+ }
+
+ public List<ClassWrapperNode> getSubclasses() {
+ return subclasses;
+ }
+
+ public ClassWrapperNode getSuperclass() {
+ return superclass;
+ }
+ public void setSuperclass(ClassWrapperNode superclass) {
+ this.superclass = superclass;
+ }
}
diff --git a/src/org/jetbrains/java/decompiler/modules/renamer/ConverterHelper.java b/src/org/jetbrains/java/decompiler/modules/renamer/ConverterHelper.java
index d85d51f..f2cb1ec 100644
--- a/src/org/jetbrains/java/decompiler/modules/renamer/ConverterHelper.java
+++ b/src/org/jetbrains/java/decompiler/modules/renamer/ConverterHelper.java
@@ -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));
- }
-
- // 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;
- }
-
+ 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));
+ }
+
+ // 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;
+ }
}
diff --git a/src/org/jetbrains/java/decompiler/modules/renamer/IdentifierConverter.java b/src/org/jetbrains/java/decompiler/modules/renamer/IdentifierConverter.java
index 634dc59..a665de8 100644
--- a/src/org/jetbrains/java/decompiler/modules/renamer/IdentifierConverter.java
+++ b/src/org/jetbrains/java/decompiler/modules/renamer/IdentifierConverter.java
@@ -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 PoolInterceptor interceptor;
-
- private List<ClassWrapperNode> rootClasses = new ArrayList<ClassWrapperNode>();
-
- 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>();
-
- // 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);
-
- 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()) {
-
- 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() {
-
- 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;
- }
-
+ private StructContext context;
+
+ private IIdentifierRenamer helper;
+
+ private PoolInterceptor interceptor;
+
+ private List<ClassWrapperNode> rootClasses = new ArrayList<ClassWrapperNode>();
+
+ 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>();
+
+ // 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);
+
+ 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()) {
+
+ 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() {
+
+ 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;
+ }
}
diff --git a/src/org/jetbrains/java/decompiler/modules/renamer/PoolInterceptor.java b/src/org/jetbrains/java/decompiler/modules/renamer/PoolInterceptor.java
index 73260f4..74e2ed8 100644
--- a/src/org/jetbrains/java/decompiler/modules/renamer/PoolInterceptor.java
+++ b/src/org/jetbrains/java/decompiler/modules/renamer/PoolInterceptor.java
@@ -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>();
-
- public PoolInterceptor(IIdentifierRenamer helper) {
- this.helper = 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;
- }
-
+ private IIdentifierRenamer helper;
+
+ private HashMap<String, String> mapOldToNewNames = new HashMap<String, String>();
+
+ private HashMap<String, String> mapNewToOldNames = new HashMap<String, String>();
+
+ public PoolInterceptor(IIdentifierRenamer helper) {
+ this.helper = 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;
+ }
}