From 076e4393f25bf1ad1ff1bd2853153e2b595dd90b Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Thu, 28 Aug 2014 21:34:14 +0400 Subject: java-decompiler: post-import cleanup (formatting and copyright) --- .../modules/renamer/ClassWrapperNode.java | 78 +- .../modules/renamer/ConverterHelper.java | 256 +++--- .../modules/renamer/IdentifierConverter.java | 875 +++++++++++---------- .../modules/renamer/PoolInterceptor.java | 72 +- 4 files changed, 671 insertions(+), 610 deletions(-) (limited to 'src/org/jetbrains/java/decompiler/modules/renamer') 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 subclasses = new ArrayList(); - - 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 getSubclasses() { - return subclasses; - } - - public ClassWrapperNode getSuperclass() { - return superclass; - } - - public void setSuperclass(ClassWrapperNode superclass) { - this.superclass = superclass; - } + private StructClass classStruct; + + private ClassWrapperNode superclass; + + private List subclasses = new ArrayList(); + + 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 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 setReserved = new HashSet(); - - 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 setNonStandardClassNames = new HashSet(); - - 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 setReserved = new HashSet(); + + 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 setNonStandardClassNames = new HashSet(); + + 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 rootClasses = new ArrayList(); - - private List rootInterfaces = new ArrayList(); - - private HashMap> interfaceNameMaps = new HashMap>(); - - 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 lstClasses = getReversePostOrderListIterative(rootClasses); - - HashMap> classNameMaps = new HashMap>(); - - for(ClassWrapperNode node : lstClasses) { - - StructClass cl = node.getClassStruct(); - HashMap names = new HashMap(); - - // merge informations on super class - if(cl.superClass != null) { - HashMap mapClass = classNameMaps.get(cl.superClass.getString()); - if(mapClass != null) { - names.putAll(mapClass); - } - } - - // merge informations on interfaces - for(String intrName : cl.getInterfaceNames()) { - HashMap 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 processExternalInterface(StructClass cl) { - - HashMap names = new HashMap(); - - for(String intrName : cl.getInterfaceNames()) { - - HashMap 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 lstInterfaces = getReversePostOrderListIterative(rootInterfaces); - - HashMap> interfaceNameMaps = new HashMap>(); - - // rename methods and fields - for(ClassWrapperNode node : lstInterfaces) { - - StructClass cl = node.getClassStruct(); - HashMap names = new HashMap(); - - // merge informations on super interfaces - for(String intrName : cl.getInterfaceNames()) { - HashMap 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 lstAllClasses = new ArrayList(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 names) { - - // all classes are already renamed - String classOldFullName = cl.qualifiedName; - String classNewFullName = interceptor.getName(classOldFullName); - - if(classNewFullName == null) { - classNewFullName = classOldFullName; - } - - // methods - HashSet setMethodNames = new HashSet(); - for(StructMethod md : cl.getMethods()) { - setMethodNames.add(md.getName()); - } - - VBStyleCollection methods = cl.getMethods(); - for(int i=0;i setFieldNames = new HashSet(); - 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 getReversePostOrderListIterative(List roots) { - - List res = new ArrayList(); - - LinkedList stackNode = new LinkedList(); - LinkedList stackIndex = new LinkedList(); - - HashSet setVisited = new HashSet(); - - 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 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 nodes = new HashMap(); - HashMap classes = context.getClasses(); - - List rootClasses = new ArrayList(); - List rootInterfaces = new ArrayList(); - - for(StructClass cl : classes.values()) { - - if(!cl.isOwn()) { - continue; - } - - LinkedList stack = new LinkedList(); - LinkedList stackSubnodes = new LinkedList(); - - 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 rootClasses = new ArrayList(); + + private List rootInterfaces = new ArrayList(); + + private HashMap> interfaceNameMaps = new HashMap>(); + + 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 lstClasses = getReversePostOrderListIterative(rootClasses); + + HashMap> classNameMaps = new HashMap>(); + + for (ClassWrapperNode node : lstClasses) { + + StructClass cl = node.getClassStruct(); + HashMap names = new HashMap(); + + // merge informations on super class + if (cl.superClass != null) { + HashMap mapClass = classNameMaps.get(cl.superClass.getString()); + if (mapClass != null) { + names.putAll(mapClass); + } + } + + // merge informations on interfaces + for (String intrName : cl.getInterfaceNames()) { + HashMap 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 processExternalInterface(StructClass cl) { + + HashMap names = new HashMap(); + + for (String intrName : cl.getInterfaceNames()) { + + HashMap 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 lstInterfaces = getReversePostOrderListIterative(rootInterfaces); + + HashMap> interfaceNameMaps = new HashMap>(); + + // rename methods and fields + for (ClassWrapperNode node : lstInterfaces) { + + StructClass cl = node.getClassStruct(); + HashMap names = new HashMap(); + + // merge informations on super interfaces + for (String intrName : cl.getInterfaceNames()) { + HashMap 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 lstAllClasses = new ArrayList(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 names) { + + // all classes are already renamed + String classOldFullName = cl.qualifiedName; + String classNewFullName = interceptor.getName(classOldFullName); + + if (classNewFullName == null) { + classNewFullName = classOldFullName; + } + + // methods + HashSet setMethodNames = new HashSet(); + for (StructMethod md : cl.getMethods()) { + setMethodNames.add(md.getName()); + } + + VBStyleCollection 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 setFieldNames = new HashSet(); + 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 getReversePostOrderListIterative(List roots) { + + List res = new ArrayList(); + + LinkedList stackNode = new LinkedList(); + LinkedList stackIndex = new LinkedList(); + + HashSet setVisited = new HashSet(); + + 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 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 nodes = new HashMap(); + HashMap classes = context.getClasses(); + + List rootClasses = new ArrayList(); + List rootInterfaces = new ArrayList(); + + for (StructClass cl : classes.values()) { + + if (!cl.isOwn()) { + continue; + } + + LinkedList stack = new LinkedList(); + LinkedList stackSubnodes = new LinkedList(); + + 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 mapOldToNewNames = new HashMap(); - - private HashMap mapNewToOldNames = new HashMap(); - - 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 mapOldToNewNames = new HashMap(); + + private HashMap mapNewToOldNames = new HashMap(); + + 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; + } } -- cgit v1.2.3