Source Code Cross Referenced for InvokeOperator.java in  » Development » jode » jode » expr » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Development » jode » jode.expr 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /* InvokeOperator Copyright (C) 1998-2002 Jochen Hoenicke.
0002:         *
0003:         * This program is free software; you can redistribute it and/or modify
0004:         * it under the terms of the GNU Lesser General Public License as published by
0005:         * the Free Software Foundation; either version 2, or (at your option)
0006:         * any later version.
0007:         *
0008:         * This program is distributed in the hope that it will be useful,
0009:         * but WITHOUT ANY WARRANTY; without even the implied warranty of
0010:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0011:         * GNU General Public License for more details.
0012:         *
0013:         * You should have received a copy of the GNU Lesser General Public License
0014:         * along with this program; see the file COPYING.LESSER.  If not, write to
0015:         * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
0016:         *
0017:         * $Id: InvokeOperator.java.in,v 4.10.2.8 2002/05/28 17:34:06 hoenicke Exp $
0018:         */
0019:
0020:        package jode.expr;
0021:
0022:        import java.lang.reflect.Modifier;
0023:
0024:        import jode.decompiler.MethodAnalyzer;
0025:        import jode.decompiler.MethodAnalyzer;
0026:        import jode.decompiler.ClassAnalyzer;
0027:        import jode.decompiler.TabbedPrintWriter;
0028:        import jode.decompiler.Options;
0029:        import jode.decompiler.OuterValues;
0030:        import jode.decompiler.Scope;
0031:        import jode.GlobalOptions;
0032:        import jode.bytecode.*;
0033:        import jode.jvm.*;
0034:        import jode.type.*;
0035:        import jode.util.SimpleMap;
0036:
0037:        import java.lang.reflect.InvocationTargetException;
0038:        import java.util.Hashtable;
0039:        import java.util.Collections;
0040:        import java.util.Collection;
0041:        import java.util.Map;
0042:        import java.util.Iterator;
0043:        import java.util.Set;
0044:
0045:        public final class InvokeOperator extends Operator implements 
0046:                MatchableOperator {
0047:
0048:            public final static int VIRTUAL = 0;
0049:            public final static int SPECIAL = 1;
0050:            public final static int STATIC = 2;
0051:            public final static int CONSTRUCTOR = 3;
0052:            public final static int ACCESSSPECIAL = 4;
0053:
0054:            /**
0055:             * The methodAnalyzer of the method, that contains this invocation.
0056:             * This is not the method that we should call.
0057:             */
0058:            MethodAnalyzer methodAnalyzer;
0059:            int methodFlag;
0060:            MethodType methodType;
0061:            String methodName;
0062:            Reference ref;
0063:            int skippedArgs;
0064:            Type classType;
0065:            Type[] hints;
0066:
0067:            /**
0068:             * This hashtable contains hints for every library method.  Some
0069:             * library method take or return an int, but it should be a char
0070:             * instead.  We will remember that here to give them the right
0071:             * hint.
0072:             *
0073:             * The key is the string: methodName + "." + methodType, the value
0074:             * is a map: It maps base class types for which this hint applies,
0075:             * to an array of hint types corresponding to the parameters: The
0076:             * first element is the hint type of the return value, the
0077:             * remaining entries are the hint types of the parameters.  All
0078:             * hint types may be null, if that parameter shouldn't be hinted.  
0079:             */
0080:            private final static Hashtable hintTypes = new Hashtable();
0081:
0082:            static {
0083:                /* Fill the hint type hashtable.  For example, the first
0084:                 * parameter of String.indexOf should be hinted as char, even
0085:                 * though the formal parameter is an int.
0086:                 * First hint is hint of return value (even if void)
0087:                 * other hints are that of the parameters in order
0088:                 *
0089:                 * You only have to hint the base class.  Other classes will
0090:                 * inherit the hints.
0091:                 *
0092:                 * We reuse a lot of objects, since they are all unchangeable
0093:                 * this is no problem.  We only hint for chars; it doesn't
0094:                 * make much sense to hint for byte, since its constant
0095:                 * representation is more difficult than an int
0096:                 * representation.  If you have more hints to suggest, please
0097:                 * write contact me. (see GlobalOptions.EMAIL)
0098:                 */
0099:                Type tCharHint = new IntegerType(IntegerType.IT_I,
0100:                        IntegerType.IT_C);
0101:                Type[] hintC = new Type[] { tCharHint };
0102:                Type[] hint0C = new Type[] { null, tCharHint };
0103:                Type[] hint0C0 = new Type[] { null, tCharHint, null };
0104:
0105:                Map hintString0CMap = new SimpleMap(Collections
0106:                        .singleton(new SimpleMap.SimpleEntry(Type.tString,
0107:                                hint0C)));
0108:                Map hintString0C0Map = new SimpleMap(Collections
0109:                        .singleton(new SimpleMap.SimpleEntry(Type.tString,
0110:                                hint0C0)));
0111:                hintTypes.put("indexOf.(I)I", hintString0CMap);
0112:                hintTypes.put("lastIndexOf.(I)I", hintString0CMap);
0113:                hintTypes.put("indexOf.(II)I", hintString0C0Map);
0114:                hintTypes.put("lastIndexOf.(II)I", hintString0C0Map);
0115:                hintTypes.put("write.(I)V", new SimpleMap(Collections
0116:                        .singleton(new SimpleMap.SimpleEntry(Type
0117:                                .tClass("java.io.Writer"), hint0C))));
0118:                hintTypes.put("read.()I", new SimpleMap(Collections
0119:                        .singleton(new SimpleMap.SimpleEntry(Type
0120:                                .tClass("java.io.Reader"), hintC))));
0121:                hintTypes.put("unread.(I)V", new SimpleMap(Collections
0122:                        .singleton(new SimpleMap.SimpleEntry(Type
0123:                                .tClass("java.io.PushbackReader"), hint0C))));
0124:            }
0125:
0126:            public InvokeOperator(MethodAnalyzer methodAnalyzer,
0127:                    int methodFlag, Reference reference) {
0128:                super (Type.tUnknown, 0);
0129:                this .ref = reference;
0130:                this .methodType = Type.tMethod(reference.getType());
0131:                this .methodName = reference.getName();
0132:                this .classType = Type.tType(reference.getClazz());
0133:                this .hints = null;
0134:                Map allHints = (Map) hintTypes.get(methodName + "."
0135:                        + methodType);
0136:                if (allHints != null) {
0137:                    for (Iterator i = allHints.entrySet().iterator(); i
0138:                            .hasNext();) {
0139:                        Map.Entry e = (Map.Entry) i.next();
0140:                        if (classType
0141:                                .isOfType(((Type) e.getKey()).getSubType())) {
0142:                            this .hints = (Type[]) e.getValue();
0143:                            break;
0144:                        }
0145:                    }
0146:                }
0147:                if (hints != null && hints[0] != null)
0148:                    this .type = hints[0];
0149:                else
0150:                    this .type = methodType.getReturnType();
0151:                this .methodAnalyzer = methodAnalyzer;
0152:                this .methodFlag = methodFlag;
0153:                if (methodFlag == STATIC)
0154:                    methodAnalyzer.useType(classType);
0155:                skippedArgs = (methodFlag == STATIC ? 0 : 1);
0156:                initOperands(skippedArgs
0157:                        + methodType.getParameterTypes().length);
0158:                checkAnonymousClasses();
0159:            }
0160:
0161:            public final boolean isStatic() {
0162:                return methodFlag == STATIC;
0163:            }
0164:
0165:            public MethodType getMethodType() {
0166:                return methodType;
0167:            }
0168:
0169:            public String getMethodName() {
0170:                return methodName;
0171:            }
0172:
0173:            private static MethodInfo getMethodInfo(ClassInfo clazz,
0174:                    String name, String type) {
0175:                while (clazz != null) {
0176:                    MethodInfo method = clazz.findMethod(name, type);
0177:                    if (method != null)
0178:                        return method;
0179:                    clazz = clazz.getSuperclass();
0180:                }
0181:                return null;
0182:            }
0183:
0184:            public MethodInfo getMethodInfo() {
0185:                ClassInfo clazz;
0186:                if (ref.getClazz().charAt(0) == '[')
0187:                    clazz = ClassInfo.javaLangObject;
0188:                else
0189:                    clazz = TypeSignature.getClassInfo(ref.getClazz());
0190:                return getMethodInfo(clazz, ref.getName(), ref.getType());
0191:            }
0192:
0193:            public Type getClassType() {
0194:                return classType;
0195:            }
0196:
0197:            public int getPriority() {
0198:                return 950;
0199:            }
0200:
0201:            public void checkAnonymousClasses() {
0202:                if (methodFlag != CONSTRUCTOR
0203:                        || (Options.options & Options.OPTION_ANON) == 0)
0204:                    return;
0205:                InnerClassInfo outer = getOuterClassInfo(getClassInfo());
0206:                if (outer != null
0207:                        && (outer.outer == null || outer.name == null)) {
0208:                    methodAnalyzer.addAnonymousConstructor(this );
0209:                }
0210:            }
0211:
0212:            public void updateSubTypes() {
0213:                int offset = 0;
0214:                if (!isStatic()) {
0215:                    subExpressions[offset++].setType(Type
0216:                            .tSubType(getClassType()));
0217:                }
0218:                Type[] paramTypes = methodType.getParameterTypes();
0219:                for (int i = 0; i < paramTypes.length; i++) {
0220:                    Type pType = (hints != null && hints[i + 1] != null) ? hints[i + 1]
0221:                            : paramTypes[i];
0222:                    subExpressions[offset++].setType(Type.tSubType(pType));
0223:                }
0224:            }
0225:
0226:            public void updateType() {
0227:            }
0228:
0229:            /**
0230:             * Makes a non void expression, in case this is a constructor.
0231:             */
0232:            public void makeNonVoid() {
0233:                if (type != Type.tVoid)
0234:                    throw new jode.AssertError("already non void");
0235:                ClassInfo clazz = getClassInfo();
0236:                InnerClassInfo outer = getOuterClassInfo(clazz);
0237:                if (outer != null && outer.name == null) {
0238:                    /* This is an anonymous class */
0239:                    if (clazz.getInterfaces().length > 0)
0240:                        type = Type.tClass(clazz.getInterfaces()[0]);
0241:                    else
0242:                        type = Type.tClass(clazz.getSuperclass());
0243:                } else
0244:                    type = subExpressions[0].getType();
0245:            }
0246:
0247:            public boolean isConstructor() {
0248:                return methodFlag == CONSTRUCTOR;
0249:            }
0250:
0251:            public ClassInfo getClassInfo() {
0252:                if (classType instanceof  ClassInterfacesType)
0253:                    return ((ClassInterfacesType) classType).getClassInfo();
0254:                return null;
0255:            }
0256:
0257:            /**
0258:             * Checks, whether this is a call of a method from this class.
0259:             */
0260:            public boolean isThis() {
0261:                return getClassInfo() == methodAnalyzer.getClazz();
0262:            }
0263:
0264:            public InnerClassInfo getOuterClassInfo(ClassInfo ci) {
0265:                if (ci != null) {
0266:                    InnerClassInfo[] outers = ci.getOuterClasses();
0267:                    if (outers != null)
0268:                        return outers[0];
0269:                }
0270:                return null;
0271:            }
0272:
0273:            /**
0274:             * Tries to locate the class analyzer for the callee class.  This
0275:             * is mainly useful for inner and anonymous classes.
0276:             *
0277:             * @return The class analyzer, if the callee class is declared
0278:             * inside the same base class as the caller class, null otherwise.
0279:             */
0280:            public ClassAnalyzer getClassAnalyzer() {
0281:                if ((Options.options & (Options.OPTION_ANON | Options.OPTION_INNER)) == 0)
0282:                    return null;
0283:
0284:                ClassInfo callee = getClassInfo();
0285:                if (callee == null)
0286:                    return null;
0287:
0288:                int nested = 0;
0289:                InnerClassInfo[] outers = callee.getOuterClasses();
0290:                if ((Options.options & Options.OPTION_INNER) != 0
0291:                        && outers != null) {
0292:                    /* If the callee class is an inner class we take its
0293:                     * (outermost) parent instead.  This will assure that we
0294:                     * find the callee class with one inner -> outer pass.  
0295:                     */
0296:                    nested = outers.length;
0297:                    if (outers[nested - 1].outer == null
0298:                            || outers[nested - 1].name == null)
0299:                        nested--;
0300:
0301:                    if (nested > 0)
0302:                        callee = ClassInfo.forName(outers[nested - 1].outer);
0303:                }
0304:
0305:                /* First check if it is an inner class */
0306:                ClassAnalyzer ana = methodAnalyzer.getClassAnalyzer(callee);
0307:
0308:                if (ana == null) {
0309:                    /* Now we iterate the caller analyzer queue to find the class
0310:                     * analyzer for callee
0311:                     */
0312:                    ana = methodAnalyzer.getClassAnalyzer();
0313:                    while (callee != ana.getClazz()) {
0314:                        if (ana.getParent() == null)
0315:                            return null;
0316:                        if (ana.getParent() instanceof  MethodAnalyzer
0317:                                && (Options.options & Options.OPTION_ANON) != 0)
0318:                            ana = ((MethodAnalyzer) ana.getParent())
0319:                                    .getClassAnalyzer();
0320:                        else if (ana.getParent() instanceof  ClassAnalyzer
0321:                                && (Options.options & Options.OPTION_INNER) != 0)
0322:                            ana = (ClassAnalyzer) ana.getParent();
0323:                        else
0324:                            throw new jode.AssertError("Unknown parent: " + ana
0325:                                    + ": " + ana.getParent());
0326:                    }
0327:                }
0328:
0329:                /* Now get the ClassAnalyzer of the real callee */
0330:                while (nested > 0) {
0331:                    nested--;
0332:                    ana = ana.getInnerClassAnalyzer(outers[nested].name);
0333:                    if (ana == null)
0334:                        return null;
0335:                }
0336:                return ana;
0337:            }
0338:
0339:            /**
0340:             * Checks, whether this is a call of a method from this class or an
0341:             * outer instance.
0342:             */
0343:            public boolean isOuter() {
0344:                if (classType instanceof  ClassInterfacesType) {
0345:                    ClassInfo clazz = ((ClassInterfacesType) classType)
0346:                            .getClassInfo();
0347:                    ClassAnalyzer ana = methodAnalyzer.getClassAnalyzer();
0348:                    while (true) {
0349:                        if (clazz == ana.getClazz())
0350:                            return true;
0351:                        if (ana.getParent() == null)
0352:                            break;
0353:                        if (ana.getParent() instanceof  MethodAnalyzer
0354:                                && (Options.options & Options.OPTION_ANON) != 0)
0355:                            ana = ((MethodAnalyzer) ana.getParent())
0356:                                    .getClassAnalyzer();
0357:                        else if (ana.getParent() instanceof  ClassAnalyzer
0358:                                && (Options.options & Options.OPTION_INNER) != 0)
0359:                            ana = (ClassAnalyzer) ana.getParent();
0360:                        else
0361:                            throw new jode.AssertError("Unknown parent: " + ana
0362:                                    + ": " + ana.getParent());
0363:                    }
0364:                }
0365:                return false;
0366:            }
0367:
0368:            /**
0369:             * Tries to locate the method analyzer for the callee.  This
0370:             * is mainly useful for inner and anonymous classes.
0371:             *
0372:             * @return The method analyzer, if the callee is declared
0373:             * inside the same base class as the caller class, null otherwise.
0374:             */
0375:            public MethodAnalyzer getMethodAnalyzer() {
0376:                ClassAnalyzer ana = getClassAnalyzer();
0377:                if (ana == null)
0378:                    return null;
0379:                return ana.getMethod(methodName, methodType);
0380:            }
0381:
0382:            /**
0383:             * Checks, whether this is a call of a method from the super class.
0384:             * @XXX check, if its the first super class that implements the method.
0385:             */
0386:            public boolean isSuperOrThis() {
0387:                ClassInfo clazz = getClassInfo();
0388:                if (clazz != null) {
0389:                    return clazz.super ClassOf(methodAnalyzer.getClazz());
0390:                }
0391:                return false;
0392:            }
0393:
0394:            public boolean isConstant() {
0395:                if ((Options.options & Options.OPTION_ANON) == 0)
0396:                    return super .isConstant();
0397:
0398:                ClassInfo clazz = getClassInfo();
0399:                InnerClassInfo outer = getOuterClassInfo(clazz);
0400:                ClassAnalyzer clazzAna = methodAnalyzer.getClassAnalyzer(clazz);
0401:                if (clazzAna != null && outer != null && outer.outer == null
0402:                        && outer.name != null
0403:                        && clazzAna.getParent() == methodAnalyzer) {
0404:                    /* This is a named method scope class, it needs
0405:                     * declaration.  And therefore can't be moved into
0406:                     * a field initializer. */
0407:                    return false;
0408:                }
0409:                return super .isConstant();
0410:            }
0411:
0412:            /**
0413:             * Checks if the value of the operator can be changed by this expression.
0414:             */
0415:            public boolean matches(Operator loadop) {
0416:                return (loadop instanceof  InvokeOperator || loadop instanceof  GetFieldOperator);
0417:            }
0418:
0419:            /**
0420:             * Checks if the method is the magic class$ method.
0421:             * @return true if this is the magic class$ method, false otherwise.
0422:             */
0423:            public boolean isGetClass() {
0424:                MethodAnalyzer mana = getMethodAnalyzer();
0425:                if (mana == null)
0426:                    return false;
0427:                SyntheticAnalyzer synth = getMethodAnalyzer().getSynthetic();
0428:                return (synth != null && synth.getKind() == SyntheticAnalyzer.GETCLASS);
0429:            }
0430:
0431:            class Environment extends SimpleRuntimeEnvironment {
0432:
0433:                Interpreter interpreter;
0434:                String classSig;
0435:
0436:                public Environment(String interpretedClassSig) {
0437:                    classSig = interpretedClassSig.intern();
0438:                }
0439:
0440:                public Object invokeMethod(Reference ref, boolean isVirtual,
0441:                        Object cls, Object[] params)
0442:                        throws InterpreterException, InvocationTargetException {
0443:                    if (cls == null && ref.getClazz().equals(classSig)) {
0444:                        String clazzName = ref.getClazz();
0445:                        clazzName = clazzName.substring(1,
0446:                                ref.getClazz().length() - 1).replace('/', '.');
0447:                        BytecodeInfo info = ClassInfo.forName(clazzName)
0448:                                .findMethod(ref.getName(), ref.getType())
0449:                                .getBytecode();
0450:                        if (info != null)
0451:                            return interpreter.interpretMethod(info, null,
0452:                                    params);
0453:                        throw new InterpreterException(
0454:                                "Can't interpret static native method: " + ref);
0455:                    } else
0456:                        return super .invokeMethod(ref, isVirtual, cls, params);
0457:                }
0458:            }
0459:
0460:            public ConstOperator deobfuscateString(ConstOperator op) {
0461:                ClassAnalyzer clazz = methodAnalyzer.getClassAnalyzer();
0462:                MethodAnalyzer ma = clazz.getMethod(methodName, methodType);
0463:                if (ma == null)
0464:                    return null;
0465:                Environment env = new Environment("L"
0466:                        + methodAnalyzer.getClazz().getName().replace('.', '/')
0467:                        + ";");
0468:                Interpreter interpreter = new Interpreter(env);
0469:                env.interpreter = interpreter;
0470:
0471:                String result;
0472:                try {
0473:                    result = (String) interpreter.interpretMethod(ma
0474:                            .getBytecodeInfo(), null, new Object[] { op
0475:                            .getValue() });
0476:                } catch (InterpreterException ex) {
0477:                    if ((GlobalOptions.debuggingFlags & GlobalOptions.DEBUG_INTERPRT) != 0) {
0478:                        GlobalOptions.err
0479:                                .println("Warning: Can't interpret method "
0480:                                        + methodName);
0481:                        ex.printStackTrace(GlobalOptions.err);
0482:                    }
0483:                    return null;
0484:                } catch (InvocationTargetException ex) {
0485:                    if ((GlobalOptions.debuggingFlags & GlobalOptions.DEBUG_INTERPRT) != 0) {
0486:                        GlobalOptions.err
0487:                                .println("Warning: Interpreted method throws"
0488:                                        + " an uncaught exception: ");
0489:                        ex.getTargetException().printStackTrace(
0490:                                GlobalOptions.err);
0491:                    }
0492:                    return null;
0493:                }
0494:                return new ConstOperator(result);
0495:            }
0496:
0497:            public Expression simplifyStringBuffer() {
0498:                if (getClassType().equals(Type.tStringBuffer)) {
0499:                    if (isConstructor()
0500:                            && subExpressions[0] instanceof  NewOperator) {
0501:                        if (methodType.getParameterTypes().length == 0)
0502:                            return EMPTYSTRING;
0503:                        if (methodType.getParameterTypes().length == 1
0504:                                && methodType.getParameterTypes()[0]
0505:                                        .equals(Type.tString))
0506:                            return subExpressions[1].simplifyString();
0507:                    }
0508:
0509:                    if (!isStatic() && getMethodName().equals("append")
0510:                            && getMethodType().getParameterTypes().length == 1) {
0511:
0512:                        Expression firstOp = subExpressions[0]
0513:                                .simplifyStringBuffer();
0514:                        if (firstOp == null)
0515:                            return null;
0516:
0517:                        subExpressions[1] = subExpressions[1].simplifyString();
0518:
0519:                        if (firstOp == EMPTYSTRING
0520:                                && subExpressions[1].getType().isOfType(
0521:                                        Type.tString))
0522:                            return subExpressions[1];
0523:
0524:                        if (firstOp instanceof  StringAddOperator
0525:                                && (((Operator) firstOp).getSubExpressions()[0] == EMPTYSTRING))
0526:                            firstOp = ((Operator) firstOp).getSubExpressions()[1];
0527:
0528:                        Expression secondOp = subExpressions[1];
0529:                        Type[] paramTypes = new Type[] { Type.tStringBuffer,
0530:                                secondOp.getType().getCanonic() };
0531:                        if (needsCast(1, paramTypes)) {
0532:                            Type castType = methodType.getParameterTypes()[0];
0533:                            Operator castOp = new ConvertOperator(castType,
0534:                                    castType);
0535:                            castOp.addOperand(secondOp);
0536:                            secondOp = castOp;
0537:                        }
0538:                        Operator result = new StringAddOperator();
0539:                        result.addOperand(secondOp);
0540:                        result.addOperand(firstOp);
0541:                        return result;
0542:                    }
0543:                }
0544:                return null;
0545:            }
0546:
0547:            public Expression simplifyString() {
0548:                if (getMethodName().equals("toString") && !isStatic()
0549:                        && getClassType().equals(Type.tStringBuffer)
0550:                        && subExpressions.length == 1) {
0551:                    Expression simple = subExpressions[0]
0552:                            .simplifyStringBuffer();
0553:                    if (simple != null)
0554:                        return simple;
0555:                } else if (getMethodName().equals("valueOf") && isStatic()
0556:                        && getClassType().equals(Type.tString)
0557:                        && subExpressions.length == 1) {
0558:
0559:                    if (subExpressions[0].getType().isOfType(Type.tString))
0560:                        return subExpressions[0];
0561:
0562:                    Operator op = new StringAddOperator();
0563:                    op.addOperand(subExpressions[0]);
0564:                    op.addOperand(EMPTYSTRING);
0565:                }
0566:                /* The pizza way (pizza is the compiler of kaffe) */
0567:                else if (getMethodName().equals("concat") && !isStatic()
0568:                        && getClassType().equals(Type.tString)) {
0569:
0570:                    Expression result = new StringAddOperator();
0571:                    Expression right = subExpressions[1].simplify();
0572:                    if (right instanceof  StringAddOperator) {
0573:                        Operator op = (Operator) right;
0574:                        if (op.subExpressions != null
0575:                                && op.subExpressions[0] == EMPTYSTRING)
0576:                            right = op.subExpressions[1];
0577:                    }
0578:                    result.addOperand(right);
0579:                    result.addOperand(subExpressions[0].simplify());
0580:                } else if ((Options.options & Options.OPTION_DECRYPT) != 0
0581:                        && isThis()
0582:                        && isStatic()
0583:                        && methodType.getParameterTypes().length == 1
0584:                        && methodType.getParameterTypes()[0]
0585:                                .equals(Type.tString)
0586:                        && methodType.getReturnType().equals(Type.tString)) {
0587:
0588:                    Expression expr = subExpressions[0].simplifyString();
0589:                    if (expr instanceof  ConstOperator) {
0590:                        expr = deobfuscateString((ConstOperator) expr);
0591:                        if (expr != null)
0592:                            return expr;
0593:                    }
0594:                }
0595:                return this ;
0596:            }
0597:
0598:            public Expression simplifyAccess() {
0599:                if (getMethodAnalyzer() != null) {
0600:                    SyntheticAnalyzer synth = getMethodAnalyzer()
0601:                            .getSynthetic();
0602:                    if (synth != null) {
0603:                        int unifyParam = synth.getUnifyParam();
0604:                        Expression op = null;
0605:                        switch (synth.getKind()) {
0606:                        case SyntheticAnalyzer.ACCESSGETFIELD:
0607:                            op = new GetFieldOperator(methodAnalyzer, false,
0608:                                    synth.getReference());
0609:                            break;
0610:                        case SyntheticAnalyzer.ACCESSGETSTATIC:
0611:                            op = new GetFieldOperator(methodAnalyzer, true,
0612:                                    synth.getReference());
0613:                            break;
0614:                        case SyntheticAnalyzer.ACCESSPUTFIELD:
0615:                        case SyntheticAnalyzer.ACCESSDUPPUTFIELD:
0616:                            op = new StoreInstruction(
0617:                                    new PutFieldOperator(methodAnalyzer, false,
0618:                                            synth.getReference()));
0619:                            if (synth.getKind() == synth.ACCESSDUPPUTFIELD)
0620:                                ((StoreInstruction) op).makeNonVoid();
0621:                            break;
0622:                        case SyntheticAnalyzer.ACCESSPUTSTATIC:
0623:                        case SyntheticAnalyzer.ACCESSDUPPUTSTATIC:
0624:                            op = new StoreInstruction(new PutFieldOperator(
0625:                                    methodAnalyzer, true, synth.getReference()));
0626:                            if (synth.getKind() == synth.ACCESSDUPPUTSTATIC)
0627:                                ((StoreInstruction) op).makeNonVoid();
0628:                            break;
0629:                        case SyntheticAnalyzer.ACCESSMETHOD:
0630:                            op = new InvokeOperator(methodAnalyzer,
0631:                                    ACCESSSPECIAL, synth.getReference());
0632:                            break;
0633:                        case SyntheticAnalyzer.ACCESSSTATICMETHOD:
0634:                            op = new InvokeOperator(methodAnalyzer, STATIC,
0635:                                    synth.getReference());
0636:                            break;
0637:                        case SyntheticAnalyzer.ACCESSCONSTRUCTOR:
0638:                            if (subExpressions[unifyParam] instanceof  ConstOperator
0639:                                    && ((ConstOperator) subExpressions[unifyParam])
0640:                                            .getValue() == null) {
0641:                                op = new InvokeOperator(methodAnalyzer,
0642:                                        CONSTRUCTOR, synth.getReference());
0643:                            }
0644:                            break;
0645:                        }
0646:
0647:                        if (op != null) {
0648:                            if (subExpressions != null) {
0649:                                for (int i = subExpressions.length; i-- > 0;) {
0650:                                    if (i == unifyParam
0651:                                            && synth.getKind() == SyntheticAnalyzer.ACCESSCONSTRUCTOR)
0652:                                        // skip the null param.
0653:                                        continue;
0654:                                    op = op.addOperand(subExpressions[i]);
0655:                                    if (subExpressions[i].getFreeOperandCount() > 0)
0656:                                        break;
0657:                                }
0658:                            }
0659:                            return op;
0660:                        }
0661:                    }
0662:                }
0663:                return null;
0664:            }
0665:
0666:            public boolean needsCast(int param, Type[] paramTypes) {
0667:                Type realClassType;
0668:                if (methodFlag == STATIC)
0669:                    realClassType = classType;
0670:                else if (param == 0) {
0671:                    if (paramTypes[0] instanceof  NullType)
0672:                        return true;
0673:                    if (!(paramTypes[0] instanceof  ClassInterfacesType && classType instanceof  ClassInterfacesType))
0674:                        return false;
0675:
0676:                    ClassInfo clazz = ((ClassInterfacesType) classType)
0677:                            .getClassInfo();
0678:                    ClassInfo parClazz = ((ClassInterfacesType) paramTypes[0])
0679:                            .getClassInfo();
0680:                    MethodInfo method = getMethodInfo();
0681:                    if (method == null)
0682:                        /* This is a NoSuchMethodError */
0683:                        return false;
0684:                    if (Modifier.isPrivate(method.getModifiers()))
0685:                        return parClazz != clazz;
0686:                    else if ((method.getModifiers() & (Modifier.PROTECTED | Modifier.PUBLIC)) == 0) {
0687:                        /* Method is protected.  We need a cast if parClazz is in
0688:                         * other package than clazz.
0689:                         */
0690:                        int lastDot = clazz.getName().lastIndexOf('.');
0691:                        if (lastDot != parClazz.getName().lastIndexOf('.')
0692:                                || !(parClazz.getName().startsWith(clazz
0693:                                        .getName().substring(0, lastDot + 1))))
0694:                            return true;
0695:                    }
0696:                    return false;
0697:                } else {
0698:                    realClassType = paramTypes[0];
0699:                }
0700:
0701:                if (!(realClassType instanceof  ClassInterfacesType)) {
0702:                    /* Arrays don't have overloaded methods, all okay */
0703:                    return false;
0704:                }
0705:                ClassInfo clazz = ((ClassInterfacesType) realClassType)
0706:                        .getClassInfo();
0707:                int offset = skippedArgs;
0708:
0709:                Type[] myParamTypes = methodType.getParameterTypes();
0710:                if (myParamTypes[param - offset].equals(paramTypes[param])) {
0711:                    /* Type at param is okay. */
0712:                    return false;
0713:                }
0714:                /* Now check if there is a conflicting method in this class or
0715:                 * a superclass.  */
0716:                while (clazz != null) {
0717:                    MethodInfo[] methods = clazz.getMethods();
0718:                    next_method: for (int i = 0; i < methods.length; i++) {
0719:                        if (!methods[i].getName().equals(methodName))
0720:                            /* method name doesn't match*/
0721:                            continue next_method;
0722:
0723:                        Type[] otherParamTypes = Type.tMethod(
0724:                                methods[i].getType()).getParameterTypes();
0725:                        if (otherParamTypes.length != myParamTypes.length) {
0726:                            /* parameter count doesn't match*/
0727:                            continue next_method;
0728:                        }
0729:
0730:                        if (myParamTypes[param - offset].isOfType(Type
0731:                                .tSubType(otherParamTypes[param - offset]))) {
0732:                            /* cast to myParamTypes cannot resolve any conflicts. */
0733:                            continue next_method;
0734:                        }
0735:                        for (int p = offset; p < paramTypes.length; p++) {
0736:                            if (!paramTypes[p].isOfType(Type
0737:                                    .tSubType(otherParamTypes[p - offset]))) {
0738:                                /* No conflict here */
0739:                                continue next_method;
0740:                            }
0741:                        }
0742:                        /* There is a conflict that can be resolved by a cast. */
0743:                        return true;
0744:                    }
0745:                    clazz = clazz.getSuperclass();
0746:                }
0747:                return false;
0748:            }
0749:
0750:            public Expression simplify() {
0751:                Expression expr = simplifyAccess();
0752:                if (expr != null)
0753:                    return expr.simplify();
0754:                expr = simplifyString();
0755:                if (expr != this )
0756:                    return expr.simplify();
0757:                return super .simplify();
0758:            }
0759:
0760:            /**
0761:             * We add the named method scoped classes to the declarables, and
0762:             * only fillDeclarables on the parameters we will print.
0763:             */
0764:            public void fillDeclarables(Collection used) {
0765:                ClassInfo clazz = getClassInfo();
0766:                InnerClassInfo outer = getOuterClassInfo(clazz);
0767:                ClassAnalyzer clazzAna = methodAnalyzer.getClassAnalyzer(clazz);
0768:
0769:                if ((Options.options & Options.OPTION_ANON) != 0
0770:                        && outer != null && outer.outer == null
0771:                        && outer.name != null && clazzAna != null
0772:                        && clazzAna.getParent() == methodAnalyzer) {
0773:
0774:                    /* This is a named method scope class, declare it.
0775:                     * But first declare all method scoped classes,
0776:                     * that are used inside; order does matter.
0777:                     */
0778:                    clazzAna.fillDeclarables(used);
0779:                    used.add(clazzAna);
0780:                }
0781:
0782:                if (!isConstructor() || isStatic()) {
0783:                    super .fillDeclarables(used);
0784:                    return;
0785:                }
0786:                int arg = 1;
0787:                int length = subExpressions.length;
0788:                boolean jikesAnonymousInner = false;
0789:                boolean implicitOuterClass = false;
0790:
0791:                if ((Options.options & Options.OPTION_ANON) != 0
0792:                        && clazzAna != null && outer != null
0793:                        && (outer.outer == null || outer.name == null)) {
0794:
0795:                    OuterValues ov = clazzAna.getOuterValues();
0796:                    arg += ov.getCount();
0797:                    jikesAnonymousInner = ov.isJikesAnonymousInner();
0798:                    implicitOuterClass = ov.isImplicitOuterClass();
0799:
0800:                    for (int i = 1; i < arg; i++) {
0801:                        Expression expr = subExpressions[i];
0802:                        if (expr instanceof  CheckNullOperator) {
0803:                            CheckNullOperator cno = (CheckNullOperator) expr;
0804:                            expr = cno.subExpressions[0];
0805:                        }
0806:                        expr.fillDeclarables(used);
0807:                    }
0808:
0809:                    if (outer.name == null) {
0810:                        /* This is an anonymous class */
0811:                        ClassInfo super Clazz = clazz.getSuperclass();
0812:                        ClassInfo[] interfaces = clazz.getInterfaces();
0813:                        if (interfaces.length == 1
0814:                                && (super Clazz == null || super Clazz == ClassInfo.javaLangObject)) {
0815:                            clazz = interfaces[0];
0816:                        } else {
0817:                            clazz = (super Clazz != null ? super Clazz
0818:                                    : ClassInfo.javaLangObject);
0819:                        }
0820:                        outer = getOuterClassInfo(clazz);
0821:
0822:                    }
0823:                }
0824:
0825:                if ((Options.options & Options.OPTION_INNER) != 0
0826:                        && outer != null && outer.outer != null
0827:                        && outer.name != null
0828:                        && !Modifier.isStatic(outer.modifiers)
0829:                        && !implicitOuterClass && arg < length) {
0830:
0831:                    Expression outerExpr = jikesAnonymousInner ? subExpressions[--length]
0832:                            : subExpressions[arg++];
0833:                    if (outerExpr instanceof  CheckNullOperator) {
0834:                        CheckNullOperator cno = (CheckNullOperator) outerExpr;
0835:                        outerExpr = cno.subExpressions[0];
0836:                    }
0837:                    outerExpr.fillDeclarables(used);
0838:                }
0839:                for (int i = arg; i < length; i++)
0840:                    subExpressions[i].fillDeclarables(used);
0841:            }
0842:
0843:            /**
0844:             * We add the named method scoped classes to the declarables, and
0845:             * only fillDeclarables on the parameters we will print.
0846:             */
0847:            public void makeDeclaration(Set done) {
0848:                super .makeDeclaration(done);
0849:
0850:                if (isConstructor() && !isStatic()
0851:                        && (Options.options & Options.OPTION_ANON) != 0) {
0852:                    ClassInfo clazz = getClassInfo();
0853:                    InnerClassInfo outer = getOuterClassInfo(clazz);
0854:                    ClassAnalyzer clazzAna = methodAnalyzer
0855:                            .getClassAnalyzer(clazz);
0856:                    if (clazzAna != null && outer != null && outer.name == null) {
0857:
0858:                        /* call makeDeclaration on the anonymous class, since
0859:                         * _we_ will declare the anonymous class.  */
0860:                        clazzAna.makeDeclaration(done);
0861:                    }
0862:                }
0863:            }
0864:
0865:            public int getBreakPenalty() {
0866:                return 5;
0867:            }
0868:
0869:            /* Invokes never equals: they may return different values even if
0870:             * they have the same parameters.
0871:             */
0872:            public void dumpExpression(TabbedPrintWriter writer)
0873:                    throws java.io.IOException {
0874:                int arg = 1;
0875:                int length = subExpressions.length;
0876:
0877:                boolean anonymousNew = false;
0878:                ClassInfo clazz = getClassInfo();
0879:                ClassAnalyzer clazzAna = null;
0880:
0881:                Type[] paramTypes = new Type[subExpressions.length];
0882:                for (int i = 0; i < subExpressions.length; i++)
0883:                    paramTypes[i] = subExpressions[i].getType().getCanonic();
0884:
0885:                writer.startOp(writer.NO_PAREN, 0);
0886:                switch (methodFlag) {
0887:                case CONSTRUCTOR: {
0888:
0889:                    boolean qualifiedNew = false;
0890:                    boolean jikesAnonymousInner = false;
0891:                    boolean implicitOuterClass = false;
0892:
0893:                    /* Check if this is an anonymous constructor. In this case
0894:                     * clazz and outer will be changed to point to the
0895:                     * super class and anonymousNew will be set. 
0896:                     */
0897:                    InnerClassInfo outer = getOuterClassInfo(clazz);
0898:                    if (outer != null && outer.name == null
0899:                            && (Options.options & Options.OPTION_ANON) != 0)
0900:                        anonymousNew = true;
0901:                    clazzAna = methodAnalyzer.getClassAnalyzer(clazz);
0902:                    if ((~Options.options & (Options.OPTION_ANON | Options.OPTION_CONTRAFO)) == 0
0903:                            && clazzAna != null
0904:                            && outer != null
0905:                            && (outer.outer == null || outer.name == null)) {
0906:
0907:                        /* This is a method scoped class, skip the outerValues */
0908:                        OuterValues ov = clazzAna.getOuterValues();
0909:                        arg += ov.getCount();
0910:                        jikesAnonymousInner = ov.isJikesAnonymousInner();
0911:                        implicitOuterClass = ov.isImplicitOuterClass();
0912:
0913:                        if (outer.name == null) {
0914:                            /* This is an anonymous class */
0915:                            ClassInfo super Clazz = clazz.getSuperclass();
0916:                            ClassInfo[] interfaces = clazz.getInterfaces();
0917:                            if (interfaces.length == 1
0918:                                    && (super Clazz == null || super Clazz == ClassInfo.javaLangObject)) {
0919:                                clazz = interfaces[0];
0920:                            } else {
0921:                                if (interfaces.length > 0) {
0922:                                    writer
0923:                                            .print("too many supers in ANONYMOUS ");
0924:                                }
0925:                                clazz = (super Clazz != null ? super Clazz
0926:                                        : ClassInfo.javaLangObject);
0927:                            }
0928:                            outer = getOuterClassInfo(clazz);
0929:                            if (jikesAnonymousInner && outer != null
0930:                                    && outer.outer == null
0931:                                    && outer.name != null) {
0932:                                Expression this Expr = subExpressions[--length];
0933:                                if (this Expr instanceof  CheckNullOperator) {
0934:                                    CheckNullOperator cno = (CheckNullOperator) this Expr;
0935:                                    this Expr = cno.subExpressions[0];
0936:                                }
0937:                                if (!(this Expr instanceof  ThisOperator)
0938:                                        || (((ThisOperator) this Expr)
0939:                                                .getClassInfo() != methodAnalyzer
0940:                                                .getClazz()))
0941:                                    writer.print("ILLEGAL ANON CONSTR");
0942:                            }
0943:                        }
0944:                    }
0945:
0946:                    /* Check if this is an inner class.  It will dump the outer
0947:                     * class expression, except if its default.
0948:                     */
0949:                    if (outer != null
0950:                            && outer.outer != null
0951:                            && outer.name != null
0952:                            && !Modifier.isStatic(outer.modifiers)
0953:                            && (~Options.options & (Options.OPTION_INNER | Options.OPTION_CONTRAFO)) == 0) {
0954:
0955:                        if (implicitOuterClass) {
0956:                            /* Outer class is "this" and is not given
0957:                             * explicitly. No need to print something.
0958:                             */
0959:                        } else if (arg < length) {
0960:                            Expression outerExpr = jikesAnonymousInner ? subExpressions[--length]
0961:                                    : subExpressions[arg++];
0962:                            if (outerExpr instanceof  CheckNullOperator) {
0963:                                CheckNullOperator cno = (CheckNullOperator) outerExpr;
0964:                                outerExpr = cno.subExpressions[0];
0965:                            } else {
0966:                                /* We used to complain about MISSING CHECKNULL
0967:                                 * here except for ThisOperators.  But javac
0968:                                 * v8 doesn't seem to create CHECKNULL ops.
0969:                                 */
0970:                            }
0971:
0972:                            if (outerExpr instanceof  ThisOperator) {
0973:                                Scope scope = writer.getScope(
0974:                                        ((ThisOperator) outerExpr)
0975:                                                .getClassInfo(),
0976:                                        Scope.CLASSSCOPE);
0977:                                if (writer.conflicts(outer.name, scope,
0978:                                        Scope.CLASSNAME)) {
0979:                                    qualifiedNew = true;
0980:                                    outerExpr.dumpExpression(writer, 950);
0981:                                    writer.breakOp();
0982:                                    writer.print(".");
0983:                                }
0984:                            } else {
0985:                                qualifiedNew = true;
0986:                                if (outerExpr.getType().getCanonic() instanceof  NullType) {
0987:                                    writer.print("(");
0988:                                    writer.startOp(writer.EXPL_PAREN, 1);
0989:                                    writer.print("(");
0990:                                    writer.printType(Type.tClass(ClassInfo
0991:                                            .forName(outer.outer)));
0992:                                    writer.print(") ");
0993:                                    writer.breakOp();
0994:                                    outerExpr.dumpExpression(writer, 700);
0995:                                    writer.endOp();
0996:                                    writer.print(")");
0997:                                } else
0998:                                    outerExpr.dumpExpression(writer, 950);
0999:                                writer.breakOp();
1000:                                writer.print(".");
1001:                            }
1002:                        } else
1003:                            writer.print("MISSING OUTEREXPR ");
1004:                    }
1005:
1006:                    if (subExpressions[0] instanceof  NewOperator
1007:                            && paramTypes[0].equals(classType)) {
1008:                        writer.print("new ");
1009:                        if (qualifiedNew)
1010:                            writer.print(outer.name);
1011:                        else
1012:                            writer.printType(Type.tClass(clazz));
1013:                        break;
1014:                    }
1015:
1016:                    if (subExpressions[0] instanceof  ThisOperator
1017:                            && (((ThisOperator) subExpressions[0])
1018:                                    .getClassInfo() == methodAnalyzer
1019:                                    .getClazz())) {
1020:                        if (isThis())
1021:                            writer.print("this");
1022:                        else
1023:                            writer.print("super");
1024:                        break;
1025:                    }
1026:
1027:                    writer.print("(");
1028:                    writer.startOp(writer.EXPL_PAREN, 0);
1029:                    writer.print("(UNCONSTRUCTED)");
1030:                    writer.breakOp();
1031:                    subExpressions[0].dumpExpression(writer, 700);
1032:                    writer.endOp();
1033:                    writer.print(")");
1034:                    writer.breakOp();
1035:                    writer.print(".");
1036:                    writer.printType(Type.tClass(clazz));
1037:                    break;
1038:                }
1039:                case SPECIAL:
1040:                    if (isSuperOrThis()
1041:                            && subExpressions[0] instanceof  ThisOperator
1042:                            && (((ThisOperator) subExpressions[0])
1043:                                    .getClassInfo() == methodAnalyzer
1044:                                    .getClazz())) {
1045:                        if (!isThis()) {
1046:                            /* We don't have to check if this is the real super
1047:                             * class, as long as ACC_SUPER is set.
1048:                             */
1049:                            writer.print("super");
1050:                            ClassInfo super Clazz = getClassInfo()
1051:                                    .getSuperclass();
1052:                            paramTypes[0] = super Clazz == null ? Type.tObject
1053:                                    : Type.tClass(super Clazz);
1054:                            writer.breakOp();
1055:                            writer.print(".");
1056:                        } else {
1057:                            /* XXX check if this is a private method. */
1058:                        }
1059:                    } else if (isThis()) {
1060:                        /* XXX check if this is a private method. */
1061:                        if (needsCast(0, paramTypes)) {
1062:                            writer.print("(");
1063:                            writer.startOp(writer.EXPL_PAREN, 1);
1064:                            writer.print("(");
1065:                            writer.printType(classType);
1066:                            writer.print(") ");
1067:                            writer.breakOp();
1068:                            subExpressions[0].dumpExpression(writer, 700);
1069:                            writer.endOp();
1070:                            writer.print(")");
1071:                            paramTypes[0] = classType;
1072:                        } else
1073:                            subExpressions[0].dumpExpression(writer, 950);
1074:                        writer.breakOp();
1075:                        writer.print(".");
1076:                    } else {
1077:                        writer.print("(");
1078:                        writer.startOp(writer.EXPL_PAREN, 0);
1079:                        writer.print("(NON VIRTUAL ");
1080:                        writer.printType(classType);
1081:                        writer.print(") ");
1082:                        writer.breakOp();
1083:                        subExpressions[0].dumpExpression(writer, 700);
1084:                        writer.endOp();
1085:                        writer.print(")");
1086:                        writer.breakOp();
1087:                        writer.print(".");
1088:                    }
1089:                    writer.print(methodName);
1090:                    break;
1091:
1092:                case ACCESSSPECIAL:
1093:                    /* Calling a private method in another class. (This is
1094:                     * allowed for inner classes.)
1095:                     */
1096:                    if (paramTypes[0].equals(classType))
1097:                        subExpressions[0].dumpExpression(writer, 950);
1098:                    else {
1099:                        writer.print("(");
1100:                        writer.startOp(writer.EXPL_PAREN, 0);
1101:                        writer.print("(");
1102:                        writer.printType(classType);
1103:                        writer.print(") ");
1104:                        writer.breakOp();
1105:                        paramTypes[0] = classType;
1106:                        subExpressions[0].dumpExpression(writer, 700);
1107:                        writer.endOp();
1108:                        writer.print(")");
1109:                    }
1110:                    writer.breakOp();
1111:                    writer.print(".");
1112:                    writer.print(methodName);
1113:                    break;
1114:
1115:                case STATIC: {
1116:                    arg = 0;
1117:                    Scope scope = writer.getScope(getClassInfo(),
1118:                            Scope.CLASSSCOPE);
1119:                    if (scope == null
1120:                            || writer.conflicts(methodName, scope,
1121:                                    Scope.METHODNAME)) {
1122:                        writer.printType(classType);
1123:                        writer.breakOp();
1124:                        writer.print(".");
1125:                    }
1126:                    writer.print(methodName);
1127:                    break;
1128:                }
1129:
1130:                case VIRTUAL:
1131:                    if (subExpressions[0] instanceof  ThisOperator) {
1132:                        ThisOperator this Op = (ThisOperator) subExpressions[0];
1133:                        Scope scope = writer.getScope(this Op.getClassInfo(),
1134:                                Scope.CLASSSCOPE);
1135:                        if (writer.conflicts(methodName, scope,
1136:                                Scope.METHODNAME)
1137:                                || (/* This method is inherited from the parent of
1138:                                 * an outer class, or it is inherited from the
1139:                                 * parent of this class and there is a conflicting
1140:                                 * method in some outer class.
1141:                                 */
1142:                                getMethodAnalyzer() == null && (!isThis() || writer
1143:                                        .conflicts(methodName, null,
1144:                                                Scope.NOSUPERMETHODNAME)))) {
1145:                            this Op.dumpExpression(writer, 950);
1146:                            writer.breakOp();
1147:                            writer.print(".");
1148:                        }
1149:                    } else {
1150:                        if (needsCast(0, paramTypes)) {
1151:                            writer.print("(");
1152:                            writer.startOp(writer.EXPL_PAREN, 1);
1153:                            writer.print("(");
1154:                            writer.printType(classType);
1155:                            writer.print(") ");
1156:                            writer.breakOp();
1157:                            subExpressions[0].dumpExpression(writer, 700);
1158:                            writer.endOp();
1159:                            writer.print(")");
1160:                            paramTypes[0] = classType;
1161:                        } else
1162:                            subExpressions[0].dumpExpression(writer, 950);
1163:                        writer.breakOp();
1164:                        writer.print(".");
1165:                    }
1166:                    writer.print(methodName);
1167:                }
1168:
1169:                writer.endOp();
1170:                writer.breakOp();
1171:                if ((Options.outputStyle & Options.GNU_SPACING) != 0)
1172:                    writer.print(" ");
1173:                writer.print("(");
1174:                writer.startOp(writer.EXPL_PAREN, 0);
1175:                boolean first = true;
1176:                int offset = skippedArgs;
1177:                while (arg < length) {
1178:                    if (!first) {
1179:                        writer.print(", ");
1180:                        writer.breakOp();
1181:                    } else
1182:                        first = false;
1183:                    int priority = 0;
1184:                    if (needsCast(arg, paramTypes)) {
1185:                        Type castType = methodType.getParameterTypes()[arg
1186:                                - offset];
1187:                        writer.startOp(writer.IMPL_PAREN, 1);
1188:                        writer.print("(");
1189:                        writer.printType(castType);
1190:                        writer.print(") ");
1191:                        writer.breakOp();
1192:                        paramTypes[arg] = castType;
1193:                        priority = 700;
1194:                    }
1195:                    subExpressions[arg++].dumpExpression(writer, priority);
1196:                    if (priority == 700)
1197:                        writer.endOp();
1198:                }
1199:                writer.endOp();
1200:                writer.print(")");
1201:
1202:                if (anonymousNew) {
1203:                    /* If this was an anonymous constructor call, we must now
1204:                     * dump the source code of the anonymous class.  
1205:                     */
1206:                    Object state = writer.saveOps();
1207:                    writer.openBraceClass();
1208:                    writer.tab();
1209:                    clazzAna.dumpBlock(writer);
1210:                    writer.untab();
1211:                    writer.closeBraceClass();
1212:                    writer.restoreOps(state);
1213:                }
1214:            }
1215:
1216:            public boolean opEquals(Operator o) {
1217:                if (o instanceof  InvokeOperator) {
1218:                    InvokeOperator i = (InvokeOperator) o;
1219:                    return classType.equals(i.classType)
1220:                            && methodName.equals(i.methodName)
1221:                            && methodType.equals(i.methodType)
1222:                            && methodFlag == i.methodFlag;
1223:                }
1224:                return false;
1225:            }
1226:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.