diff options
Diffstat (limited to 'src/org/jetbrains/java/decompiler/modules/renamer/IdentifierConverter.java')
-rw-r--r-- | src/org/jetbrains/java/decompiler/modules/renamer/IdentifierConverter.java | 875 |
1 files changed, 446 insertions, 429 deletions
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; + } } |