From ed222cc7d79fe93fb44de210f3dc4d3e229a62e5 Mon Sep 17 00:00:00 2001 From: jochen Date: Mon, 3 May 1999 10:54:24 +0000 Subject: [PATCH] Complete Scope handling git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@739 379699f6-c40d-0410-875b-85095c16579e --- jode/jode/decompiler/TabbedPrintWriter.java | 152 +++++++++++++++++++- 1 file changed, 147 insertions(+), 5 deletions(-) diff --git a/jode/jode/decompiler/TabbedPrintWriter.java b/jode/jode/decompiler/TabbedPrintWriter.java index 34a8dcd..8767e27 100644 --- a/jode/jode/decompiler/TabbedPrintWriter.java +++ b/jode/jode/decompiler/TabbedPrintWriter.java @@ -19,8 +19,11 @@ package jode.decompiler; import java.io.*; +import java.util.Stack; import jode.Decompiler; -import jode.type.Type; +import jode.bytecode.ClassInfo; +import jode.bytecode.InnerClassInfo; +import jode.type.*; public class TabbedPrintWriter { boolean atbol; @@ -29,6 +32,7 @@ public class TabbedPrintWriter { String indentStr = ""; PrintWriter pw; ImportHandler imports; + Stack scopes = new Stack(); public TabbedPrintWriter (OutputStream os, ImportHandler imports) { pw = new PrintWriter(os, true); @@ -114,10 +118,7 @@ public class TabbedPrintWriter { } public void printType(Type type) { - if (imports != null) - print(imports.getTypeString(type)); - else - print(type.toString()); + print(getTypeString(type)); } /** @@ -140,6 +141,147 @@ public class TabbedPrintWriter { } } + public void pushScope(Scope scope) { + scopes.push(scope); + } + + public void popScope() { + scopes.pop(); + } + + /** + * Checks if the name in inScope conflicts with an identifier in a + * higher scope. + */ + public boolean conflicts(String name, Scope inScope, int context) { + int dot = name.indexOf('.'); + if (dot >= 0) + name = name.substring(0, dot); + int count = scopes.size(); + for (int ptr = count; ptr-- > 0; ) { + Scope scope = (Scope) scopes.elementAt(ptr); + if (scope == inScope) + return false; + if (scope.conflicts(name, context)) + return true; + } + return false; + } + + public Scope getScope(Object obj, int scopeType) { + int count = scopes.size(); + for (int ptr = count; ptr-- > 0; ) { + Scope scope = (Scope) scopes.elementAt(ptr); + if (scope.isScopeOf(obj, scopeType)) + return scope; + } + return null; + } + + public String getInnerClassString(ClassInfo info) { + InnerClassInfo[] outers = info.getOuterClasses(); + if (outers == null) + return null; + for (int i=0; i< outers.length; i++) { + if (outers[i].name == null || outers[i].outer == null) + return null; + Scope scope = getScope(ClassInfo.forName(outers[i].outer), + Scope.CLASSSCOPE); + if (scope != null && + !conflicts(outers[i].name, scope, Scope.AMBIGUOUSNAME)) { + StringBuffer sb = new StringBuffer(outers[i].name); + for (int j = i; j-- > 0;) { + sb.append('.').append(outers[j].name); + } + return sb.toString(); + } + } + String name = getClassString + (ClassInfo.forName(outers[outers.length-1].outer)); + StringBuffer sb = new StringBuffer(name); + for (int j = outers.length; j-- > 0;) + sb.append('.').append(outers[j].name); + return sb.toString(); + } + + public String getAnonymousClassString(ClassInfo info) { + InnerClassInfo[] outers = info.getOuterClasses(); + if (outers == null) + return null; + for (int i=0; i< outers.length; i++) { + if (outers[i].name == null) + return "ANONYMOUS CLASS"; + Scope scope = getScope + (ClassInfo.forName(outers[i].outer == null + ? outers[i].inner : outers[i].outer), + outers[i].outer == null + ? Scope.METHODSCOPE : Scope.CLASSSCOPE); + if (scope != null && + !conflicts(outers[i].name, scope, Scope.AMBIGUOUSNAME)) { + StringBuffer sb = new StringBuffer(outers[i].name); + for (int j = i; j-- > 0;) { + sb.append('.').append(outers[j].name); + } + return sb.toString(); + } else if (outers[i].outer == null) { + StringBuffer sb; + if (scope != null) + sb = new StringBuffer("NAME CONFLICT "); + else + sb = new StringBuffer("UNREACHABLE "); + + sb.append(outers[i].name); + for (int j = i; j-- > 0;) { + sb.append('.').append(outers[j].name); + } + return sb.toString(); + } + } + String name = getClassString + (ClassInfo.forName(outers[outers.length-1].outer)); + StringBuffer sb = new StringBuffer(name); + for (int j = outers.length; j-- > 0;) + sb.append('.').append(outers[j].name); + return sb.toString(); + } + + public String getClassString(ClassInfo clazz) { + String name = clazz.getName(); + if (name.indexOf('$') >= 0) { + if ((Decompiler.options & Decompiler.OPTION_INNER) != 0) { + String innerClassName = getInnerClassString(clazz); + if (innerClassName != null) + return innerClassName; + } + if ((Decompiler.options + & Decompiler.OPTION_ANON) != 0) { + String innerClassName = getAnonymousClassString(clazz); + if (innerClassName != null) + return innerClassName; + } + } + if (imports != null) { + String importedName = imports.getClassString(clazz); + if (!conflicts(importedName, null, Scope.AMBIGUOUSNAME)) + return importedName; + } + if (conflicts(name, null, Scope.AMBIGUOUSNAME)) + return "PKGNAMECONFLICT "+ name; + return name; + } + + public String getTypeString(Type type) { + if (type instanceof ArrayType) + return getTypeString(((ArrayType) type).getElementType()) + "[]"; + else if (type instanceof ClassInterfacesType) { + ClassInfo clazz = ((ClassInterfacesType) type).getClassInfo(); + return getClassString(clazz); + } else if (type instanceof NullType) + return "Object"; + else + return type.toString(); + } + /** * Print a opening brace with the current indentation style. * Called at the end of the line of the instance that opens the