Source Code Cross Referenced for GenerateJavaAST.java in  » Ajax » GWT » com » google » gwt » dev » jjs » impl » 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 » Ajax » GWT » com.google.gwt.dev.jjs.impl 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Copyright 2007 Google Inc.
0003:         * 
0004:         * Licensed under the Apache License, Version 2.0 (the "License"); you may not
0005:         * use this file except in compliance with the License. You may obtain a copy of
0006:         * the License at
0007:         * 
0008:         * http://www.apache.org/licenses/LICENSE-2.0
0009:         * 
0010:         * Unless required by applicable law or agreed to in writing, software
0011:         * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
0012:         * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
0013:         * License for the specific language governing permissions and limitations under
0014:         * the License.
0015:         */
0016:        package com.google.gwt.dev.jjs.impl;
0017:
0018:        import com.google.gwt.dev.jjs.HasSourceInfo;
0019:        import com.google.gwt.dev.jjs.InternalCompilerException;
0020:        import com.google.gwt.dev.jjs.SourceInfo;
0021:        import com.google.gwt.dev.jjs.ast.HasEnclosingType;
0022:        import com.google.gwt.dev.jjs.ast.JArrayRef;
0023:        import com.google.gwt.dev.jjs.ast.JArrayType;
0024:        import com.google.gwt.dev.jjs.ast.JAssertStatement;
0025:        import com.google.gwt.dev.jjs.ast.JBinaryOperation;
0026:        import com.google.gwt.dev.jjs.ast.JBinaryOperator;
0027:        import com.google.gwt.dev.jjs.ast.JBlock;
0028:        import com.google.gwt.dev.jjs.ast.JBooleanLiteral;
0029:        import com.google.gwt.dev.jjs.ast.JBreakStatement;
0030:        import com.google.gwt.dev.jjs.ast.JCaseStatement;
0031:        import com.google.gwt.dev.jjs.ast.JCastOperation;
0032:        import com.google.gwt.dev.jjs.ast.JCharLiteral;
0033:        import com.google.gwt.dev.jjs.ast.JClassLiteral;
0034:        import com.google.gwt.dev.jjs.ast.JClassType;
0035:        import com.google.gwt.dev.jjs.ast.JConditional;
0036:        import com.google.gwt.dev.jjs.ast.JContinueStatement;
0037:        import com.google.gwt.dev.jjs.ast.JDoStatement;
0038:        import com.google.gwt.dev.jjs.ast.JDoubleLiteral;
0039:        import com.google.gwt.dev.jjs.ast.JEnumField;
0040:        import com.google.gwt.dev.jjs.ast.JEnumType;
0041:        import com.google.gwt.dev.jjs.ast.JExpression;
0042:        import com.google.gwt.dev.jjs.ast.JExpressionStatement;
0043:        import com.google.gwt.dev.jjs.ast.JField;
0044:        import com.google.gwt.dev.jjs.ast.JFieldRef;
0045:        import com.google.gwt.dev.jjs.ast.JFloatLiteral;
0046:        import com.google.gwt.dev.jjs.ast.JForStatement;
0047:        import com.google.gwt.dev.jjs.ast.JIfStatement;
0048:        import com.google.gwt.dev.jjs.ast.JInstanceOf;
0049:        import com.google.gwt.dev.jjs.ast.JIntLiteral;
0050:        import com.google.gwt.dev.jjs.ast.JInterfaceType;
0051:        import com.google.gwt.dev.jjs.ast.JLabel;
0052:        import com.google.gwt.dev.jjs.ast.JLabeledStatement;
0053:        import com.google.gwt.dev.jjs.ast.JLiteral;
0054:        import com.google.gwt.dev.jjs.ast.JLocal;
0055:        import com.google.gwt.dev.jjs.ast.JLocalDeclarationStatement;
0056:        import com.google.gwt.dev.jjs.ast.JLocalRef;
0057:        import com.google.gwt.dev.jjs.ast.JLongLiteral;
0058:        import com.google.gwt.dev.jjs.ast.JMethod;
0059:        import com.google.gwt.dev.jjs.ast.JMethodBody;
0060:        import com.google.gwt.dev.jjs.ast.JMethodCall;
0061:        import com.google.gwt.dev.jjs.ast.JNewArray;
0062:        import com.google.gwt.dev.jjs.ast.JNewInstance;
0063:        import com.google.gwt.dev.jjs.ast.JNode;
0064:        import com.google.gwt.dev.jjs.ast.JParameter;
0065:        import com.google.gwt.dev.jjs.ast.JParameterRef;
0066:        import com.google.gwt.dev.jjs.ast.JPostfixOperation;
0067:        import com.google.gwt.dev.jjs.ast.JPrefixOperation;
0068:        import com.google.gwt.dev.jjs.ast.JPrimitiveType;
0069:        import com.google.gwt.dev.jjs.ast.JProgram;
0070:        import com.google.gwt.dev.jjs.ast.JReferenceType;
0071:        import com.google.gwt.dev.jjs.ast.JReturnStatement;
0072:        import com.google.gwt.dev.jjs.ast.JStatement;
0073:        import com.google.gwt.dev.jjs.ast.JStringLiteral;
0074:        import com.google.gwt.dev.jjs.ast.JSwitchStatement;
0075:        import com.google.gwt.dev.jjs.ast.JThrowStatement;
0076:        import com.google.gwt.dev.jjs.ast.JTryStatement;
0077:        import com.google.gwt.dev.jjs.ast.JType;
0078:        import com.google.gwt.dev.jjs.ast.JUnaryOperator;
0079:        import com.google.gwt.dev.jjs.ast.JVariable;
0080:        import com.google.gwt.dev.jjs.ast.JVariableRef;
0081:        import com.google.gwt.dev.jjs.ast.JWhileStatement;
0082:        import com.google.gwt.dev.jjs.ast.js.JsniFieldRef;
0083:        import com.google.gwt.dev.jjs.ast.js.JsniMethodBody;
0084:        import com.google.gwt.dev.jjs.ast.js.JsniMethodRef;
0085:        import com.google.gwt.dev.jjs.ast.js.JsonObject;
0086:        import com.google.gwt.dev.js.ast.JsContext;
0087:        import com.google.gwt.dev.js.ast.JsExpression;
0088:        import com.google.gwt.dev.js.ast.JsFunction;
0089:        import com.google.gwt.dev.js.ast.JsModVisitor;
0090:        import com.google.gwt.dev.js.ast.JsNameRef;
0091:        import com.google.gwt.dev.js.ast.JsProgram;
0092:        import com.google.gwt.dev.js.ast.JsSourceInfo;
0093:
0094:        import org.eclipse.jdt.core.compiler.IProblem;
0095:        import org.eclipse.jdt.internal.compiler.CompilationResult;
0096:        import org.eclipse.jdt.internal.compiler.ast.AND_AND_Expression;
0097:        import org.eclipse.jdt.internal.compiler.ast.ASTNode;
0098:        import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
0099:        import org.eclipse.jdt.internal.compiler.ast.AllocationExpression;
0100:        import org.eclipse.jdt.internal.compiler.ast.ArrayAllocationExpression;
0101:        import org.eclipse.jdt.internal.compiler.ast.ArrayInitializer;
0102:        import org.eclipse.jdt.internal.compiler.ast.ArrayReference;
0103:        import org.eclipse.jdt.internal.compiler.ast.AssertStatement;
0104:        import org.eclipse.jdt.internal.compiler.ast.Assignment;
0105:        import org.eclipse.jdt.internal.compiler.ast.BinaryExpression;
0106:        import org.eclipse.jdt.internal.compiler.ast.Block;
0107:        import org.eclipse.jdt.internal.compiler.ast.BreakStatement;
0108:        import org.eclipse.jdt.internal.compiler.ast.CaseStatement;
0109:        import org.eclipse.jdt.internal.compiler.ast.CastExpression;
0110:        import org.eclipse.jdt.internal.compiler.ast.ClassLiteralAccess;
0111:        import org.eclipse.jdt.internal.compiler.ast.CompoundAssignment;
0112:        import org.eclipse.jdt.internal.compiler.ast.ConditionalExpression;
0113:        import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
0114:        import org.eclipse.jdt.internal.compiler.ast.ContinueStatement;
0115:        import org.eclipse.jdt.internal.compiler.ast.DoStatement;
0116:        import org.eclipse.jdt.internal.compiler.ast.EmptyStatement;
0117:        import org.eclipse.jdt.internal.compiler.ast.EqualExpression;
0118:        import org.eclipse.jdt.internal.compiler.ast.ExplicitConstructorCall;
0119:        import org.eclipse.jdt.internal.compiler.ast.Expression;
0120:        import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
0121:        import org.eclipse.jdt.internal.compiler.ast.FieldReference;
0122:        import org.eclipse.jdt.internal.compiler.ast.ForStatement;
0123:        import org.eclipse.jdt.internal.compiler.ast.ForeachStatement;
0124:        import org.eclipse.jdt.internal.compiler.ast.IfStatement;
0125:        import org.eclipse.jdt.internal.compiler.ast.Initializer;
0126:        import org.eclipse.jdt.internal.compiler.ast.InstanceOfExpression;
0127:        import org.eclipse.jdt.internal.compiler.ast.LabeledStatement;
0128:        import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
0129:        import org.eclipse.jdt.internal.compiler.ast.MessageSend;
0130:        import org.eclipse.jdt.internal.compiler.ast.NullLiteral;
0131:        import org.eclipse.jdt.internal.compiler.ast.OR_OR_Expression;
0132:        import org.eclipse.jdt.internal.compiler.ast.PostfixExpression;
0133:        import org.eclipse.jdt.internal.compiler.ast.PrefixExpression;
0134:        import org.eclipse.jdt.internal.compiler.ast.QualifiedAllocationExpression;
0135:        import org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference;
0136:        import org.eclipse.jdt.internal.compiler.ast.QualifiedSuperReference;
0137:        import org.eclipse.jdt.internal.compiler.ast.QualifiedThisReference;
0138:        import org.eclipse.jdt.internal.compiler.ast.ReturnStatement;
0139:        import org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
0140:        import org.eclipse.jdt.internal.compiler.ast.Statement;
0141:        import org.eclipse.jdt.internal.compiler.ast.SuperReference;
0142:        import org.eclipse.jdt.internal.compiler.ast.SwitchStatement;
0143:        import org.eclipse.jdt.internal.compiler.ast.SynchronizedStatement;
0144:        import org.eclipse.jdt.internal.compiler.ast.ThisReference;
0145:        import org.eclipse.jdt.internal.compiler.ast.ThrowStatement;
0146:        import org.eclipse.jdt.internal.compiler.ast.TryStatement;
0147:        import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
0148:        import org.eclipse.jdt.internal.compiler.ast.UnaryExpression;
0149:        import org.eclipse.jdt.internal.compiler.ast.WhileStatement;
0150:        import org.eclipse.jdt.internal.compiler.impl.BooleanConstant;
0151:        import org.eclipse.jdt.internal.compiler.impl.ByteConstant;
0152:        import org.eclipse.jdt.internal.compiler.impl.CharConstant;
0153:        import org.eclipse.jdt.internal.compiler.impl.Constant;
0154:        import org.eclipse.jdt.internal.compiler.impl.DoubleConstant;
0155:        import org.eclipse.jdt.internal.compiler.impl.FloatConstant;
0156:        import org.eclipse.jdt.internal.compiler.impl.IntConstant;
0157:        import org.eclipse.jdt.internal.compiler.impl.LongConstant;
0158:        import org.eclipse.jdt.internal.compiler.impl.ShortConstant;
0159:        import org.eclipse.jdt.internal.compiler.impl.StringConstant;
0160:        import org.eclipse.jdt.internal.compiler.lookup.Binding;
0161:        import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
0162:        import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
0163:        import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
0164:        import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
0165:        import org.eclipse.jdt.internal.compiler.lookup.MethodScope;
0166:        import org.eclipse.jdt.internal.compiler.lookup.NestedTypeBinding;
0167:        import org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding;
0168:        import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
0169:        import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
0170:        import org.eclipse.jdt.internal.compiler.lookup.SyntheticArgumentBinding;
0171:        import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
0172:        import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
0173:        import org.eclipse.jdt.internal.compiler.lookup.VariableBinding;
0174:        import org.eclipse.jdt.internal.compiler.problem.DefaultProblem;
0175:        import org.eclipse.jdt.internal.compiler.problem.ProblemHandler;
0176:        import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
0177:
0178:        import java.lang.reflect.InvocationTargetException;
0179:        import java.lang.reflect.Method;
0180:        import java.util.ArrayList;
0181:        import java.util.Collections;
0182:        import java.util.HashMap;
0183:        import java.util.IdentityHashMap;
0184:        import java.util.Iterator;
0185:        import java.util.LinkedList;
0186:        import java.util.List;
0187:        import java.util.Map;
0188:
0189:        /**
0190:         * This is the big kahuna where most of the nitty gritty of creating our AST
0191:         * happens. BuildTypeMap must have already run so we have valid mappings between
0192:         * JDT nodes and our already-created AST nodes.
0193:         */
0194:        public class GenerateJavaAST {
0195:
0196:            /**
0197:             * Visit the JDT AST and produce our own AST into the passed-in TypeMap's
0198:             * JProgram. By the end of this pass, the produced AST should contain every
0199:             * piece of information we'll ever need about the code. The JDT nodes should
0200:             * never again be referenced after this.
0201:             * 
0202:             * This is implemented as a reflective visitor for JDT's AST. The advantage of
0203:             * doing it reflectively is that if we run into any JDT nodes we can't handle,
0204:             * we'll automatically throw an exception. If we had subclassed
0205:             * {@link org.eclipse.jdt.internal.compiler.ast.ASTNode} we'd have to override
0206:             * every single method and explicitly throw an exception to get the same
0207:             * behavior.
0208:             * 
0209:             * NOTE ON JDT FORCED OPTIMIZATIONS - If JDT statically determines that a
0210:             * section of code in unreachable, it won't fully resolve that section of
0211:             * code. This invalid-state code causes us major problems. As a result, we
0212:             * have to optimize out those dead blocks early and never try to translate
0213:             * them to our AST.
0214:             */
0215:            private static class JavaASTGenerationVisitor {
0216:
0217:                private class JsniRefResolver extends JsModVisitor {
0218:                    private final AbstractMethodDeclaration methodDecl;
0219:                    private final JsniMethodBody nativeMethodBody;
0220:
0221:                    private JsniRefResolver(
0222:                            AbstractMethodDeclaration methodDecl,
0223:                            JsniMethodBody nativeMethodBody) {
0224:                        this .methodDecl = methodDecl;
0225:                        this .nativeMethodBody = nativeMethodBody;
0226:                    }
0227:
0228:                    @Override
0229:                    public void endVisit(JsNameRef x,
0230:                            JsContext<JsExpression> ctx) {
0231:                        String ident = x.getIdent();
0232:                        if (ident.charAt(0) == '@') {
0233:                            processNameRef(x, ctx);
0234:                        }
0235:                    }
0236:
0237:                    private HasEnclosingType parseJsniRef(SourceInfo info,
0238:                            String ident) {
0239:                        String[] parts = ident.substring(1).split("::");
0240:                        assert (parts.length == 2);
0241:                        String className = parts[0];
0242:                        JReferenceType type = program.getFromTypeMap(className);
0243:                        if (type == null) {
0244:                            reportJsniError(info, methodDecl,
0245:                                    "Unresolvable native reference to type '"
0246:                                            + className + "'");
0247:                            return null;
0248:                        }
0249:                        String rhs = parts[1];
0250:                        int parenPos = rhs.indexOf('(');
0251:                        if (parenPos < 0) {
0252:                            // look for a field
0253:                            for (int i = 0; i < type.fields.size(); ++i) {
0254:                                JField field = type.fields.get(i);
0255:                                if (field.getName().equals(rhs)) {
0256:                                    return field;
0257:                                }
0258:                            }
0259:
0260:                            reportJsniError(info, methodDecl,
0261:                                    "Unresolvable native reference to field '"
0262:                                            + rhs + "' in type '" + className
0263:                                            + "'");
0264:                        } else {
0265:                            // look for a method
0266:                            String methodName = rhs.substring(0, parenPos);
0267:                            String almostMatches = null;
0268:                            for (int i = 0; i < type.methods.size(); ++i) {
0269:                                JMethod method = type.methods.get(i);
0270:                                if (method.getName().equals(methodName)) {
0271:                                    String jsniSig = getJsniSig(method);
0272:                                    if (jsniSig.equals(rhs)) {
0273:                                        return method;
0274:                                    } else if (almostMatches == null) {
0275:                                        almostMatches = "'" + jsniSig + "'";
0276:                                    } else {
0277:                                        almostMatches += ", '" + jsniSig + "'";
0278:                                    }
0279:                                }
0280:                            }
0281:
0282:                            if (almostMatches == null) {
0283:                                reportJsniError(info, methodDecl,
0284:                                        "Unresolvable native reference to method '"
0285:                                                + methodName + "' in type '"
0286:                                                + className + "'");
0287:                            } else {
0288:                                reportJsniError(info, methodDecl,
0289:                                        "Unresolvable native reference to method '"
0290:                                                + methodName + "' in type '"
0291:                                                + className
0292:                                                + "' (did you mean "
0293:                                                + almostMatches + "?)");
0294:                            }
0295:                        }
0296:                        return null;
0297:                    }
0298:
0299:                    private void processField(JsNameRef nameRef,
0300:                            SourceInfo info, JField field,
0301:                            JsContext<JsExpression> ctx) {
0302:                        if (field.isStatic() && nameRef.getQualifier() != null) {
0303:                            reportJsniError(info, methodDecl,
0304:                                    "Cannot make a qualified reference to the static field "
0305:                                            + field.getName());
0306:                        } else if (!field.isStatic()
0307:                                && nameRef.getQualifier() == null) {
0308:                            reportJsniError(info, methodDecl,
0309:                                    "Cannot make an unqualified reference to the instance field "
0310:                                            + field.getName());
0311:                        }
0312:
0313:                        /*
0314:                         * We must replace any compile-time constants with the constant value of
0315:                         * the field.
0316:                         */
0317:                        JLiteral initializer = field.constInitializer;
0318:                        if (field.isStatic() && field.isFinal()
0319:                                && initializer != null) {
0320:                            JType type = initializer.getType();
0321:                            if (type instanceof  JPrimitiveType
0322:                                    || type == program.getTypeJavaLangString()) {
0323:                                GenerateJavaScriptLiterals generator = new GenerateJavaScriptLiterals(
0324:                                        jsProgram);
0325:                                generator.accept(initializer);
0326:                                JsExpression result = generator.peek();
0327:                                assert (result != null);
0328:                                ctx.replaceMe(result);
0329:                                return;
0330:                            }
0331:                        }
0332:
0333:                        // Normal: create a jsniRef.
0334:                        JsniFieldRef fieldRef = new JsniFieldRef(program, info,
0335:                                field, currentClass);
0336:                        nativeMethodBody.jsniFieldRefs.add(fieldRef);
0337:                    }
0338:
0339:                    private void processMethod(JsNameRef nameRef,
0340:                            SourceInfo info, JMethod method) {
0341:                        if (method.isStatic() && nameRef.getQualifier() != null) {
0342:                            reportJsniError(info, methodDecl,
0343:                                    "Cannot make a qualified reference to the static method "
0344:                                            + method.getName());
0345:                        } else if (!method.isStatic()
0346:                                && nameRef.getQualifier() == null) {
0347:                            reportJsniError(info, methodDecl,
0348:                                    "Cannot make an unqualified reference to the instance method "
0349:                                            + method.getName());
0350:                        }
0351:
0352:                        JsniMethodRef methodRef = new JsniMethodRef(program,
0353:                                info, method);
0354:                        nativeMethodBody.jsniMethodRefs.add(methodRef);
0355:                    }
0356:
0357:                    private void processNameRef(JsNameRef nameRef,
0358:                            JsContext<JsExpression> ctx) {
0359:                        SourceInfo info = nativeMethodBody.getSourceInfo();
0360:                        // TODO: make this tighter when we have real source info
0361:                        // JSourceInfo info = translateInfo(nameRef.getInfo());
0362:                        String ident = nameRef.getIdent();
0363:                        HasEnclosingType node = program.jsniMap.get(ident);
0364:                        if (node == null) {
0365:                            node = parseJsniRef(info, ident);
0366:                            if (node == null) {
0367:                                return; // already reported error
0368:                            }
0369:                            program.jsniMap.put(ident, node);
0370:                        }
0371:
0372:                        if (node instanceof  JField) {
0373:                            processField(nameRef, info, (JField) node, ctx);
0374:                        } else if (node instanceof  JMethod) {
0375:                            processMethod(nameRef, info, (JMethod) node);
0376:                        } else {
0377:                            throw new InternalCompilerException(
0378:                                    (HasSourceInfo) node,
0379:                                    "JSNI reference to something other than a field or method?",
0380:                                    null);
0381:                        }
0382:                    }
0383:                }
0384:
0385:                private static String getJsniSig(JMethod method) {
0386:                    StringBuffer sb = new StringBuffer();
0387:                    sb.append(method.getName());
0388:                    sb.append("(");
0389:                    for (int i = 0; i < method.getOriginalParamTypes().size(); ++i) {
0390:                        JType type = method.getOriginalParamTypes().get(i);
0391:                        sb.append(type.getJsniSignatureName());
0392:                    }
0393:                    sb.append(")");
0394:                    return sb.toString();
0395:                }
0396:
0397:                private static InternalCompilerException translateException(
0398:                        JNode node, Throwable e) {
0399:                    InternalCompilerException ice;
0400:                    if (e instanceof  InternalCompilerException) {
0401:                        ice = (InternalCompilerException) e;
0402:                        ice.addNode(node);
0403:                    } else {
0404:                        ice = new InternalCompilerException(node,
0405:                                "Error constructing Java AST", e);
0406:                    }
0407:                    return ice;
0408:                }
0409:
0410:                private JReferenceType currentClass;
0411:
0412:                private ClassScope currentClassScope;
0413:
0414:                private String currentFileName;
0415:
0416:                private JMethod currentMethod;
0417:
0418:                private JMethodBody currentMethodBody;
0419:
0420:                private MethodScope currentMethodScope;
0421:
0422:                private int[] currentSeparatorPositions;
0423:
0424:                private final JsProgram jsProgram;
0425:
0426:                private final Map<JMethod, Map<String, JLabel>> labelMap = new IdentityHashMap<JMethod, Map<String, JLabel>>();
0427:
0428:                private final JProgram program;
0429:
0430:                private final TypeMap typeMap;
0431:
0432:                public JavaASTGenerationVisitor(TypeMap typeMap,
0433:                        JProgram program, JsProgram jsProgram) {
0434:                    this .typeMap = typeMap;
0435:                    this .program = program;
0436:                    this .jsProgram = jsProgram;
0437:                }
0438:
0439:                public void processEnumType(JEnumType type) {
0440:                    // Create a JSNI map for string-based lookup.
0441:                    JField mapField = createEnumValueMap(type);
0442:
0443:                    // Generate the synthetic values() and valueOf() methods.
0444:                    for (JMethod method : type.methods) {
0445:                        currentMethod = method;
0446:                        if ("values".equals(method.getName())) {
0447:                            if (method.params.size() != 0) {
0448:                                continue;
0449:                            }
0450:                            currentMethodBody = (JMethodBody) method.getBody();
0451:                            writeEnumValuesMethod(type);
0452:                        } else if ("valueOf".equals(method.getName())) {
0453:                            if (method.params.size() != 1) {
0454:                                continue;
0455:                            }
0456:                            if (method.params.get(0).getType() != program
0457:                                    .getTypeJavaLangString()) {
0458:                                continue;
0459:                            }
0460:                            currentMethodBody = (JMethodBody) method.getBody();
0461:                            writeEnumValueOfMethod(type, mapField);
0462:                        }
0463:                        currentMethodBody = null;
0464:                        currentMethod = null;
0465:                    }
0466:                }
0467:
0468:                /**
0469:                 * We emulate static initializers and instance initializers as methods. As
0470:                 * in other cases, this gives us: simpler AST, easier to optimize, more like
0471:                 * output JavaScript.
0472:                 */
0473:                public void processType(TypeDeclaration x) {
0474:                    if (x.binding.isAnnotationType()) {
0475:                        // Do not process.
0476:                        return;
0477:                    }
0478:                    currentClass = (JReferenceType) typeMap.get(x.binding);
0479:                    try {
0480:                        currentClassScope = x.scope;
0481:                        currentSeparatorPositions = x.compilationResult.lineSeparatorPositions;
0482:                        currentFileName = String
0483:                                .valueOf(x.compilationResult.fileName);
0484:
0485:                        /*
0486:                         * Make clinits chain to super class (JDT doesn't write code to do
0487:                         * this). Call super class $clinit; $clinit is always in position 0.
0488:                         */
0489:                        if (currentClass.extnds != null) {
0490:                            JMethod myClinit = currentClass.methods.get(0);
0491:                            JMethod super Clinit = currentClass.extnds.methods
0492:                                    .get(0);
0493:                            JMethodCall super ClinitCall = new JMethodCall(
0494:                                    program, myClinit.getSourceInfo(), null,
0495:                                    super Clinit);
0496:                            JMethodBody body = (JMethodBody) myClinit.getBody();
0497:                            body.getStatements().add(0,
0498:                                    super ClinitCall.makeStatement());
0499:                        }
0500:
0501:                        if (x.fields != null) {
0502:                            // Process fields
0503:                            for (int i = 0, n = x.fields.length; i < n; ++i) {
0504:                                FieldDeclaration fieldDeclaration = x.fields[i];
0505:                                if (fieldDeclaration.isStatic()) {
0506:                                    // clinit
0507:                                    currentMethod = currentClass.methods.get(0);
0508:                                    currentMethodBody = (JMethodBody) currentMethod
0509:                                            .getBody();
0510:                                    currentMethodScope = x.staticInitializerScope;
0511:                                } else {
0512:                                    // init
0513:                                    currentMethod = currentClass.methods.get(1);
0514:                                    currentMethodBody = (JMethodBody) currentMethod
0515:                                            .getBody();
0516:                                    currentMethodScope = x.initializerScope;
0517:                                }
0518:
0519:                                if (fieldDeclaration instanceof  Initializer) {
0520:                                    assert (currentClass instanceof  JClassType);
0521:                                    processInitializer((Initializer) fieldDeclaration);
0522:                                } else {
0523:                                    processField(fieldDeclaration);
0524:                                }
0525:                            }
0526:                        }
0527:
0528:                        currentMethodScope = null;
0529:                        currentMethod = null;
0530:
0531:                        if (x.methods != null) {
0532:                            // Process methods
0533:                            for (int i = 0, n = x.methods.length; i < n; ++i) {
0534:                                if (x.methods[i].isConstructor()) {
0535:                                    assert (currentClass instanceof  JClassType);
0536:                                    processConstructor((ConstructorDeclaration) x.methods[i]);
0537:                                } else if (x.methods[i].isClinit()) {
0538:                                    // nothing to do
0539:                                } else {
0540:                                    processMethod(x.methods[i]);
0541:                                }
0542:                            }
0543:                        }
0544:
0545:                        // Write the body of the getClass() override.
0546:                        if (currentClass instanceof  JClassType
0547:                                && currentClass != program
0548:                                        .getTypeJavaLangObject()
0549:                                && currentClass != program
0550:                                        .getIndexedType("Array")) {
0551:                            JMethod method = currentClass.methods.get(2);
0552:                            assert ("getClass".equals(method.getName()));
0553:
0554:                            tryFindUpRefs(method);
0555:
0556:                            JMethodBody body = (JMethodBody) method.getBody();
0557:                            JClassLiteral classLit = program
0558:                                    .getLiteralClass(currentClass);
0559:                            body.getStatements().add(
0560:                                    new JReturnStatement(program, null,
0561:                                            classLit));
0562:                        }
0563:
0564:                        if (currentClass instanceof  JEnumType) {
0565:                            processEnumType((JEnumType) currentClass);
0566:                        }
0567:
0568:                        currentClassScope = null;
0569:                        currentClass = null;
0570:                        currentSeparatorPositions = null;
0571:                        currentFileName = null;
0572:                    } catch (Throwable e) {
0573:                        throw translateException(currentClass, e);
0574:                    }
0575:                }
0576:
0577:                /**
0578:                 * This is the guts of the "reflective" part of this visitor. Try to find a
0579:                 * "process" method that exactly matches the run-time type of the argument.
0580:                 */
0581:                protected JNode dispatch(String name, Object child) {
0582:                    if (child == null) {
0583:                        return null;
0584:                    }
0585:
0586:                    try {
0587:                        Method method = getClass().getDeclaredMethod(name,
0588:                                child.getClass());
0589:                        return (JNode) method.invoke(this , child);
0590:                    } catch (Throwable e) {
0591:                        if (e instanceof  InvocationTargetException) {
0592:                            e = ((InvocationTargetException) e)
0593:                                    .getTargetException();
0594:                        }
0595:                        throw translateException(child, e);
0596:                    }
0597:                }
0598:
0599:                /**
0600:                 * Process an Expression type node reflectively; must return a JExpression.
0601:                 */
0602:                protected JExpression dispProcessExpression(Expression x) {
0603:                    /*
0604:                     * Note that we always prefer a JDT-computed constant value to the actual
0605:                     * written expression. (Let's hope JDT is always right.) This means we
0606:                     * don't have to write processExpression methods for the numerous JDT
0607:                     * literal nodes because they ALWAYS have a constant value.
0608:                     */
0609:                    JExpression result = null;
0610:                    if (x != null && x.constant != null
0611:                            && x.constant != Constant.NotAConstant) {
0612:                        result = (JExpression) dispatch("processConstant",
0613:                                x.constant);
0614:                    }
0615:
0616:                    if (result == null) {
0617:                        // The expression was not a constant, so use the general logic.
0618:                        result = (JExpression) dispatch("processExpression", x);
0619:                    }
0620:
0621:                    // Check if we need to box the resulting expression.
0622:                    if (x != null) {
0623:                        if ((x.implicitConversion & TypeIds.BOXING) != 0) {
0624:                            /*
0625:                             * Beware! Passing in "primitiveTypeToBox" seems unnecessary, but it
0626:                             * isn't. You cannot determine the true type to box directly by
0627:                             * calling result.getType() in all cases because sometimes, such as
0628:                             * when the expression is originally a int literal prefixed with a
0629:                             * narrowing cast, the processExpression() calls returns JIntLiterals
0630:                             * even when the actual type should be byte or short. So, unless you
0631:                             * remember what the original expression type was, you'd incorrectly
0632:                             * box a byte as an Integer.
0633:                             */
0634:                            JType primitiveTypeToBox = (JType) typeMap
0635:                                    .get(x.resolvedType);
0636:
0637:                            if (!(primitiveTypeToBox instanceof  JPrimitiveType)) {
0638:                                throw new InternalCompilerException(result,
0639:                                        "Attempt to box a non-primitive type: "
0640:                                                + primitiveTypeToBox.getName(),
0641:                                        null);
0642:                            }
0643:
0644:                            result = box(result,
0645:                                    (JPrimitiveType) primitiveTypeToBox);
0646:                        } else if ((x.implicitConversion & TypeIds.UNBOXING) != 0) {
0647:
0648:                            JType typeToUnbox = (JType) typeMap
0649:                                    .get(x.resolvedType);
0650:                            if (!(typeToUnbox instanceof  JClassType)) {
0651:                                throw new InternalCompilerException(result,
0652:                                        "Attempt to unbox a non-class type: "
0653:                                                + typeToUnbox.getName(), null);
0654:                            }
0655:
0656:                            result = unbox(result, (JClassType) typeToUnbox);
0657:                        }
0658:                    }
0659:                    return result;
0660:                }
0661:
0662:                /**
0663:                 * Process an Statement type node reflectively; must return a JStatement.
0664:                 */
0665:                protected JStatement dispProcessStatement(Statement x) {
0666:                    JStatement stmt;
0667:                    if (x instanceof  Expression) {
0668:                        JExpression expr = dispProcessExpression((Expression) x);
0669:                        if (expr == null) {
0670:                            return null;
0671:                        }
0672:                        stmt = expr.makeStatement();
0673:                    } else {
0674:                        stmt = (JStatement) dispatch("processStatement", x);
0675:                    }
0676:                    return stmt;
0677:                }
0678:
0679:                JBooleanLiteral processConstant(BooleanConstant x) {
0680:                    return program.getLiteralBoolean(x.booleanValue());
0681:                }
0682:
0683:                JIntLiteral processConstant(ByteConstant x) {
0684:                    return program.getLiteralInt(x.byteValue());
0685:                }
0686:
0687:                JCharLiteral processConstant(CharConstant x) {
0688:                    return program.getLiteralChar(x.charValue());
0689:                }
0690:
0691:                JDoubleLiteral processConstant(DoubleConstant x) {
0692:                    return program.getLiteralDouble(x.doubleValue());
0693:                }
0694:
0695:                JFloatLiteral processConstant(FloatConstant x) {
0696:                    return program.getLiteralFloat(x.floatValue());
0697:                }
0698:
0699:                JIntLiteral processConstant(IntConstant x) {
0700:                    return program.getLiteralInt(x.intValue());
0701:                }
0702:
0703:                JLongLiteral processConstant(LongConstant x) {
0704:                    return program.getLiteralLong(x.longValue());
0705:                }
0706:
0707:                JIntLiteral processConstant(ShortConstant x) {
0708:                    return program.getLiteralInt(x.shortValue());
0709:                }
0710:
0711:                JStringLiteral processConstant(StringConstant x) {
0712:                    return program.getLiteralString(x.stringValue()
0713:                            .toCharArray());
0714:                }
0715:
0716:                /**
0717:                 * Weird: we used to have JConstructor (and JConstructorCall) in our AST,
0718:                 * but we got rid of them completely and instead model them as instance
0719:                 * methods whose qualifier is a naked no-argument new operation.
0720:                 * 
0721:                 * There are several reasons we do it this way:
0722:                 * 
0723:                 * 1) When spitting our AST back to Java code (for verification purposes),
0724:                 * we found it was impossible to correctly emulate nested classes as
0725:                 * non-nested classes using traditional constructor syntax. It boiled down
0726:                 * to the fact that you really HAVE to assign your synthetic arguments to
0727:                 * your synthetic fields BEFORE calling your superclass constructor (because
0728:                 * it might call you back polymorphically). And trying to do that in
0729:                 * straight Java is a semantic error, a super call must be the first
0730:                 * statement of your constructor.
0731:                 * 
0732:                 * 2) It's a lot more like how we'll be generating JavaScript eventually.
0733:                 * 
0734:                 * 3) It's a lot easier to optimize; the same optimizations work on our
0735:                 * synthetic fields as work on any user fields. In fact, once we're past AST
0736:                 * generation, we throw away all information about what's synthetic.
0737:                 * 
0738:                 * The order of emulation is: - assign all synthetic fields from synthetic
0739:                 * args - call our super constructor emulation method - call our instance
0740:                 * initializer emulation method - run user code - return this
0741:                 */
0742:                void processConstructor(ConstructorDeclaration x) {
0743:                    JMethod ctor = (JMethod) typeMap.get(x.binding);
0744:                    try {
0745:                        SourceInfo info = ctor.getSourceInfo();
0746:
0747:                        currentMethod = ctor;
0748:                        currentMethodBody = (JMethodBody) ctor.getBody();
0749:                        currentMethodScope = x.scope;
0750:
0751:                        JMethodCall super OrThisCall = null;
0752:                        ExplicitConstructorCall ctorCall = x.constructorCall;
0753:                        if (ctorCall != null) {
0754:                            super OrThisCall = (JMethodCall) dispatch(
0755:                                    "processExpression", ctorCall);
0756:                        }
0757:
0758:                        /*
0759:                         * Determine if we have an explicit this call. The presence of an
0760:                         * explicit this call indicates we can skip certain initialization steps
0761:                         * (as the callee will perform those steps for us). These skippable
0762:                         * steps are 1) assigning synthetic args to fields and 2) running
0763:                         * initializers.
0764:                         */
0765:                        boolean hasExplicitThis = (ctorCall != null)
0766:                                && !ctorCall.isSuperAccess();
0767:
0768:                        JClassType enclosingType = (JClassType) ctor
0769:                                .getEnclosingType();
0770:
0771:                        // Call clinit; $clinit is always in position 0.
0772:                        JMethod clinitMethod = enclosingType.methods.get(0);
0773:                        JMethodCall clinitCall = new JMethodCall(program, info,
0774:                                null, clinitMethod);
0775:                        JMethodBody body = (JMethodBody) ctor.getBody();
0776:                        List<JStatement> statements = body.getStatements();
0777:                        statements.add(clinitCall.makeStatement());
0778:
0779:                        /*
0780:                         * All synthetic fields must be assigned, unless we have an explicit
0781:                         * this constructor call, in which case the callee will assign them for
0782:                         * us.
0783:                         */
0784:                        if (!hasExplicitThis) {
0785:                            ReferenceBinding declaringClass = x.binding.declaringClass;
0786:                            if (declaringClass instanceof  NestedTypeBinding) {
0787:                                Iterator<JParameter> paramIt = getSyntheticsIterator(ctor);
0788:                                NestedTypeBinding nestedBinding = (NestedTypeBinding) declaringClass;
0789:                                if (nestedBinding.enclosingInstances != null) {
0790:                                    for (int i = 0; i < nestedBinding.enclosingInstances.length; ++i) {
0791:                                        SyntheticArgumentBinding arg = nestedBinding.enclosingInstances[i];
0792:                                        JParameter param = paramIt.next();
0793:                                        if (arg.matchingField != null) {
0794:                                            JField field = (JField) typeMap
0795:                                                    .get(arg);
0796:                                            statements
0797:                                                    .add(program
0798:                                                            .createAssignmentStmt(
0799:                                                                    info,
0800:                                                                    createVariableRef(
0801:                                                                            info,
0802:                                                                            field),
0803:                                                                    createVariableRef(
0804:                                                                            info,
0805:                                                                            param)));
0806:                                        }
0807:                                    }
0808:                                }
0809:
0810:                                if (nestedBinding.outerLocalVariables != null) {
0811:                                    for (int i = 0; i < nestedBinding.outerLocalVariables.length; ++i) {
0812:                                        SyntheticArgumentBinding arg = nestedBinding.outerLocalVariables[i];
0813:                                        JParameter param = paramIt.next();
0814:                                        JField field = (JField) typeMap
0815:                                                .get(arg);
0816:                                        statements.add(program
0817:                                                .createAssignmentStmt(info,
0818:                                                        createVariableRef(info,
0819:                                                                field),
0820:                                                        createVariableRef(info,
0821:                                                                param)));
0822:                                    }
0823:                                }
0824:                            }
0825:                        }
0826:
0827:                        // Enums: wire up synthetic name/ordinal params to the super method.
0828:                        if (enclosingType.isEnumOrSubclass() != null) {
0829:                            assert (super OrThisCall != null);
0830:                            JVariableRef enumNameRef = createVariableRef(
0831:                                    super OrThisCall.getSourceInfo(),
0832:                                    ctor.params.get(0));
0833:                            super OrThisCall.getArgs().add(0, enumNameRef);
0834:                            JVariableRef enumOrdinalRef = createVariableRef(
0835:                                    super OrThisCall.getSourceInfo(),
0836:                                    ctor.params.get(1));
0837:                            super OrThisCall.getArgs().add(1, enumOrdinalRef);
0838:                        }
0839:
0840:                        // optional this or super constructor call
0841:                        if (super OrThisCall != null) {
0842:                            statements.add(super OrThisCall.makeStatement());
0843:                        }
0844:
0845:                        JExpression this Ref = createThisRef(info, enclosingType);
0846:
0847:                        /*
0848:                         * Call the synthetic instance initializer method, unless we have an
0849:                         * explicit this constructor call, in which case the callee will.
0850:                         */
0851:                        if (!hasExplicitThis) {
0852:                            // $init is always in position 1 (clinit is in 0)
0853:                            JMethod initMethod = enclosingType.methods.get(1);
0854:                            JMethodCall initCall = new JMethodCall(program,
0855:                                    info, this Ref, initMethod);
0856:                            statements.add(initCall.makeStatement());
0857:                        }
0858:
0859:                        // user code (finally!)
0860:                        if (x.statements != null) {
0861:                            for (int i = 0, n = x.statements.length; i < n; ++i) {
0862:                                Statement origStmt = x.statements[i];
0863:                                JStatement jstmt = dispProcessStatement(origStmt);
0864:                                if (jstmt != null) {
0865:                                    statements.add(jstmt);
0866:                                }
0867:                            }
0868:                        }
0869:
0870:                        currentMethodScope = null;
0871:                        currentMethod = null;
0872:
0873:                        // synthesize a return statement to emulate returning the new object
0874:                        statements.add(new JReturnStatement(program, null,
0875:                                this Ref));
0876:                    } catch (Throwable e) {
0877:                        throw translateException(ctor, e);
0878:                    }
0879:                }
0880:
0881:                JExpression processExpression(AllocationExpression x) {
0882:                    SourceInfo info = makeSourceInfo(x);
0883:                    SourceTypeBinding typeBinding = erasure(x.resolvedType);
0884:                    if (typeBinding.constantPoolName() == null) {
0885:                        /*
0886:                         * Weird case: if JDT determines that this local class is totally
0887:                         * uninstantiable, it won't bother allocating a local name.
0888:                         */
0889:                        return program.getLiteralNull();
0890:                    }
0891:                    JClassType newType = (JClassType) typeMap.get(typeBinding);
0892:                    MethodBinding b = x.binding;
0893:                    JMethod ctor = (JMethod) typeMap.get(b);
0894:                    JMethodCall call;
0895:                    JClassType javaLangString = program.getTypeJavaLangString();
0896:                    if (newType == javaLangString) {
0897:                        /*
0898:                         * MAGIC: java.lang.String is implemented as a JavaScript String
0899:                         * primitive with a modified prototype. This requires funky handling of
0900:                         * constructor calls. We find a method named _String() whose signature
0901:                         * matches the requested constructor
0902:                         */
0903:                        int ctorArgc = ctor.params.size();
0904:                        JMethod targetMethod = null;
0905:                        outer: for (int j = 0; j < javaLangString.methods
0906:                                .size(); ++j) {
0907:                            JMethod method = javaLangString.methods.get(j);
0908:                            if (method.getName().equals("_String")
0909:                                    && method.params.size() == ctorArgc) {
0910:                                for (int i = 0; i < ctorArgc; ++i) {
0911:                                    JParameter mparam = method.params.get(i);
0912:                                    JParameter cparam = ctor.params.get(i);
0913:                                    if (mparam.getType() != cparam.getType()) {
0914:                                        continue outer;
0915:                                    }
0916:                                }
0917:                                targetMethod = method;
0918:                                break;
0919:                            }
0920:                        }
0921:                        if (targetMethod == null) {
0922:                            throw new InternalCompilerException(
0923:                                    "String constructor error; no matching implementation.");
0924:                        }
0925:                        call = new JMethodCall(program, makeSourceInfo(x),
0926:                                null, targetMethod);
0927:                    } else {
0928:                        JNewInstance newInstance = new JNewInstance(program,
0929:                                info, newType);
0930:                        call = new JMethodCall(program, info, newInstance, ctor);
0931:                    }
0932:
0933:                    // Enums: hidden arguments for the name and id.
0934:                    if (x.enumConstant != null) {
0935:                        call.getArgs().add(
0936:                                program.getLiteralString(x.enumConstant.name));
0937:                        call.getArgs().add(
0938:                                program.getLiteralInt(x.enumConstant.binding
0939:                                        .original().id));
0940:                    }
0941:
0942:                    // Plain old regular user arguments
0943:                    addCallArgs(x.arguments, call, b);
0944:
0945:                    // Synthetic args for inner classes
0946:                    ReferenceBinding targetBinding = b.declaringClass;
0947:                    if (targetBinding.isNestedType()
0948:                            && !targetBinding.isStatic()) {
0949:                        NestedTypeBinding nestedBinding = (NestedTypeBinding) erasure(targetBinding);
0950:                        // Synthetic this args for inner classes
0951:                        if (nestedBinding.enclosingInstances != null) {
0952:                            for (int i = 0; i < nestedBinding.enclosingInstances.length; ++i) {
0953:                                SyntheticArgumentBinding arg = nestedBinding.enclosingInstances[i];
0954:                                JClassType syntheticThisType = (JClassType) typeMap
0955:                                        .get(arg.type);
0956:                                call.getArgs().add(
0957:                                        createThisRef(info, syntheticThisType));
0958:                            }
0959:                        }
0960:                        // Synthetic locals for local classes
0961:                        if (nestedBinding.outerLocalVariables != null) {
0962:                            for (int i = 0; i < nestedBinding.outerLocalVariables.length; ++i) {
0963:                                SyntheticArgumentBinding arg = nestedBinding.outerLocalVariables[i];
0964:                                JVariable variable = (JVariable) typeMap
0965:                                        .get(arg.actualOuterLocalVariable);
0966:                                call.getArgs().add(
0967:                                        createVariableRef(info, variable,
0968:                                                arg.actualOuterLocalVariable));
0969:                            }
0970:                        }
0971:                    }
0972:
0973:                    return call;
0974:                }
0975:
0976:                JExpression processExpression(AND_AND_Expression x) {
0977:                    JType type = (JType) typeMap.get(x.resolvedType);
0978:                    SourceInfo info = makeSourceInfo(x);
0979:                    return processBinaryOperation(info, JBinaryOperator.AND,
0980:                            type, x.left, x.right);
0981:                }
0982:
0983:                JExpression processExpression(ArrayAllocationExpression x) {
0984:                    SourceInfo info = makeSourceInfo(x);
0985:                    JArrayType type = (JArrayType) typeMap.get(x.resolvedType);
0986:                    JNewArray newArray = new JNewArray(program, info, type);
0987:
0988:                    if (x.initializer != null) {
0989:                        newArray.initializers = new ArrayList<JExpression>();
0990:                        if (x.initializer.expressions != null) {
0991:                            for (Expression expression : x.initializer.expressions) {
0992:                                newArray.initializers
0993:                                        .add(dispProcessExpression(expression));
0994:                            }
0995:                        }
0996:                    } else {
0997:                        newArray.dims = new ArrayList<JExpression>();
0998:                        for (Expression dimension : x.dimensions) {
0999:                            // can be null if index expression was empty
1000:                            if (dimension == null) {
1001:                                newArray.dims.add(program
1002:                                        .getLiteralAbsentArrayDimension());
1003:                            } else {
1004:                                newArray.dims
1005:                                        .add(dispProcessExpression(dimension));
1006:                            }
1007:                        }
1008:                    }
1009:
1010:                    return newArray;
1011:                }
1012:
1013:                JExpression processExpression(ArrayInitializer x) {
1014:                    SourceInfo info = makeSourceInfo(x);
1015:                    JArrayType type = (JArrayType) typeMap.get(x.resolvedType);
1016:                    JNewArray newArray = new JNewArray(program, info, type);
1017:
1018:                    newArray.initializers = new ArrayList<JExpression>();
1019:                    if (x.expressions != null) {
1020:                        for (Expression expression : x.expressions) {
1021:                            newArray.initializers
1022:                                    .add(dispProcessExpression(expression));
1023:                        }
1024:                    }
1025:
1026:                    return newArray;
1027:                }
1028:
1029:                JExpression processExpression(ArrayReference x) {
1030:                    SourceInfo info = makeSourceInfo(x);
1031:                    JArrayRef arrayRef = new JArrayRef(program, info,
1032:                            dispProcessExpression(x.receiver),
1033:                            dispProcessExpression(x.position));
1034:                    return arrayRef;
1035:                }
1036:
1037:                JExpression processExpression(Assignment x) {
1038:                    JType type = (JType) typeMap.get(x.resolvedType);
1039:                    SourceInfo info = makeSourceInfo(x);
1040:                    return processBinaryOperation(info, JBinaryOperator.ASG,
1041:                            type, x.lhs, x.expression);
1042:                }
1043:
1044:                JExpression processExpression(BinaryExpression x) {
1045:                    JBinaryOperator op;
1046:
1047:                    int binOp = (x.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT;
1048:                    switch (binOp) {
1049:                    case BinaryExpression.LEFT_SHIFT:
1050:                        op = JBinaryOperator.SHL;
1051:                        break;
1052:                    case BinaryExpression.RIGHT_SHIFT:
1053:                        op = JBinaryOperator.SHR;
1054:                        break;
1055:                    case BinaryExpression.UNSIGNED_RIGHT_SHIFT:
1056:                        op = JBinaryOperator.SHRU;
1057:                        break;
1058:                    case BinaryExpression.PLUS:
1059:                        op = JBinaryOperator.ADD;
1060:                        break;
1061:                    case BinaryExpression.MINUS:
1062:                        op = JBinaryOperator.SUB;
1063:                        break;
1064:                    case BinaryExpression.REMAINDER:
1065:                        op = JBinaryOperator.MOD;
1066:                        break;
1067:                    case BinaryExpression.XOR:
1068:                        op = JBinaryOperator.BIT_XOR;
1069:                        break;
1070:                    case BinaryExpression.AND:
1071:                        op = JBinaryOperator.BIT_AND;
1072:                        break;
1073:                    case BinaryExpression.MULTIPLY:
1074:                        op = JBinaryOperator.MUL;
1075:                        break;
1076:                    case BinaryExpression.OR:
1077:                        op = JBinaryOperator.BIT_OR;
1078:                        break;
1079:                    case BinaryExpression.DIVIDE:
1080:                        op = JBinaryOperator.DIV;
1081:                        break;
1082:                    case BinaryExpression.LESS_EQUAL:
1083:                        op = JBinaryOperator.LTE;
1084:                        break;
1085:                    case BinaryExpression.GREATER_EQUAL:
1086:                        op = JBinaryOperator.GTE;
1087:                        break;
1088:                    case BinaryExpression.GREATER:
1089:                        op = JBinaryOperator.GT;
1090:                        break;
1091:                    case BinaryExpression.LESS:
1092:                        op = JBinaryOperator.LT;
1093:                        break;
1094:                    default:
1095:                        throw new InternalCompilerException(
1096:                                "Unexpected operator for BinaryExpression");
1097:                    }
1098:
1099:                    JType type = (JType) typeMap.get(x.resolvedType);
1100:                    SourceInfo info = makeSourceInfo(x);
1101:                    return processBinaryOperation(info, op, type, x.left,
1102:                            x.right);
1103:                }
1104:
1105:                JExpression processExpression(CastExpression x) {
1106:                    SourceInfo info = makeSourceInfo(x);
1107:                    JType type = (JType) typeMap.get(x.resolvedType);
1108:                    JCastOperation cast = new JCastOperation(program, info,
1109:                            type, dispProcessExpression(x.expression));
1110:                    return cast;
1111:                }
1112:
1113:                JExpression processExpression(ClassLiteralAccess x) {
1114:                    JType type = (JType) typeMap.get(x.targetType);
1115:                    return program.getLiteralClass(type);
1116:                }
1117:
1118:                JExpression processExpression(CompoundAssignment x) {
1119:                    JBinaryOperator op;
1120:
1121:                    switch (x.operator) {
1122:                    case CompoundAssignment.PLUS:
1123:                        op = JBinaryOperator.ASG_ADD;
1124:                        break;
1125:                    case CompoundAssignment.MINUS:
1126:                        op = JBinaryOperator.ASG_SUB;
1127:                        break;
1128:                    case CompoundAssignment.MULTIPLY:
1129:                        op = JBinaryOperator.ASG_MUL;
1130:                        break;
1131:                    case CompoundAssignment.DIVIDE:
1132:                        op = JBinaryOperator.ASG_DIV;
1133:                        break;
1134:                    case CompoundAssignment.AND:
1135:                        op = JBinaryOperator.ASG_BIT_AND;
1136:                        break;
1137:                    case CompoundAssignment.OR:
1138:                        op = JBinaryOperator.ASG_BIT_OR;
1139:                        break;
1140:                    case CompoundAssignment.XOR:
1141:                        op = JBinaryOperator.ASG_BIT_XOR;
1142:                        break;
1143:                    case CompoundAssignment.REMAINDER:
1144:                        op = JBinaryOperator.ASG_MOD;
1145:                        break;
1146:                    case CompoundAssignment.LEFT_SHIFT:
1147:                        op = JBinaryOperator.ASG_SHL;
1148:                        break;
1149:                    case CompoundAssignment.RIGHT_SHIFT:
1150:                        op = JBinaryOperator.ASG_SHR;
1151:                        break;
1152:                    case CompoundAssignment.UNSIGNED_RIGHT_SHIFT:
1153:                        op = JBinaryOperator.ASG_SHRU;
1154:                        break;
1155:                    default:
1156:                        throw new InternalCompilerException(
1157:                                "Unexpected operator for CompoundAssignment");
1158:                    }
1159:
1160:                    JType type = (JType) typeMap.get(x.resolvedType);
1161:                    SourceInfo info = makeSourceInfo(x);
1162:                    return processBinaryOperation(info, op, type, x.lhs,
1163:                            x.expression);
1164:                }
1165:
1166:                JExpression processExpression(ConditionalExpression x) {
1167:                    SourceInfo info = makeSourceInfo(x);
1168:                    JType type = (JType) typeMap.get(x.resolvedType);
1169:                    JExpression ifTest = dispProcessExpression(x.condition);
1170:                    JExpression thenExpr = dispProcessExpression(x.valueIfTrue);
1171:                    JExpression elseExpr = dispProcessExpression(x.valueIfFalse);
1172:                    JConditional conditional = new JConditional(program, info,
1173:                            type, ifTest, thenExpr, elseExpr);
1174:                    return conditional;
1175:                }
1176:
1177:                JExpression processExpression(EqualExpression x) {
1178:                    JBinaryOperator op;
1179:                    switch ((x.bits & BinaryExpression.OperatorMASK) >> BinaryExpression.OperatorSHIFT) {
1180:                    case BinaryExpression.EQUAL_EQUAL:
1181:                        op = JBinaryOperator.EQ;
1182:                        break;
1183:                    case BinaryExpression.NOT_EQUAL:
1184:                        op = JBinaryOperator.NEQ;
1185:                        break;
1186:                    default:
1187:                        throw new InternalCompilerException(
1188:                                "Unexpected operator for EqualExpression");
1189:                    }
1190:
1191:                    JType type = (JType) typeMap.get(x.resolvedType);
1192:                    SourceInfo info = makeSourceInfo(x);
1193:                    return processBinaryOperation(info, op, type, x.left,
1194:                            x.right);
1195:                }
1196:
1197:                /**
1198:                 * How we have to treat super calls vs. this calls is so different, they may
1199:                 * as well have been two different JDT nodes.
1200:                 */
1201:                JMethodCall processExpression(ExplicitConstructorCall x) {
1202:                    if (x.isSuperAccess()) {
1203:                        return processSuperConstructorCall(x);
1204:                    } else {
1205:                        return processThisConstructorCall(x);
1206:                    }
1207:                }
1208:
1209:                JExpression processExpression(FieldReference x) {
1210:                    SourceInfo info = makeSourceInfo(x);
1211:                    FieldBinding fieldBinding = x.binding;
1212:                    JField field;
1213:                    if (fieldBinding.declaringClass == null) {
1214:                        // probably array.length
1215:                        field = program.getIndexedField("Array.length");
1216:                        if (!field.getName().equals(
1217:                                String.valueOf(fieldBinding.name))) {
1218:                            throw new InternalCompilerException(
1219:                                    "Error matching fieldBinding.");
1220:                        }
1221:                    } else {
1222:                        field = (JField) typeMap.get(fieldBinding);
1223:                    }
1224:                    JExpression instance = dispProcessExpression(x.receiver);
1225:                    JExpression fieldRef = new JFieldRef(program, info,
1226:                            instance, field, currentClass);
1227:                    return fieldRef;
1228:                }
1229:
1230:                JExpression processExpression(InstanceOfExpression x) {
1231:                    SourceInfo info = makeSourceInfo(x);
1232:                    JExpression expr = dispProcessExpression(x.expression);
1233:                    JReferenceType testType = (JReferenceType) typeMap
1234:                            .get(x.type.resolvedType);
1235:                    return new JInstanceOf(program, info, testType, expr);
1236:                }
1237:
1238:                JExpression processExpression(MessageSend x) {
1239:                    SourceInfo info = makeSourceInfo(x);
1240:                    JType type = (JType) typeMap.get(x.resolvedType);
1241:                    JMethod method = (JMethod) typeMap.get(x.binding);
1242:
1243:                    JExpression qualifier;
1244:                    if (x.receiver instanceof  ThisReference) {
1245:                        if (method.isStatic()) {
1246:                            // don't bother qualifying it, it's a no-op
1247:                            qualifier = null;
1248:                        } else if (x.receiver instanceof  QualifiedThisReference) {
1249:                            // use the supplied qualifier
1250:                            qualifier = dispProcessExpression(x.receiver);
1251:                        } else {
1252:                            /*
1253:                             * In cases where JDT had to synthesize a this ref for us, it could
1254:                             * actually be the wrong type, if the target method is in an enclosing
1255:                             * class. We have to synthesize our own ref of the correct type.
1256:                             */
1257:                            qualifier = createThisRef(info, method
1258:                                    .getEnclosingType());
1259:                        }
1260:                    } else {
1261:                        qualifier = dispProcessExpression(x.receiver);
1262:                    }
1263:
1264:                    JMethodCall call = new JMethodCall(program, info,
1265:                            qualifier, method);
1266:
1267:                    // On a super ref, don't allow polymorphic dispatch. Oddly enough,
1268:                    // QualifiedSuperReference not derived from SuperReference!
1269:                    boolean isSuperRef = x.receiver instanceof  SuperReference
1270:                            || x.receiver instanceof  QualifiedSuperReference;
1271:                    if (isSuperRef) {
1272:                        call.setStaticDispatchOnly();
1273:                    }
1274:
1275:                    // The arguments come first...
1276:                    addCallArgs(x.arguments, call, x.binding);
1277:
1278:                    if (type != method.getType()) {
1279:                        // Must be a generic; insert a cast operation.
1280:                        JReferenceType toType = (JReferenceType) type;
1281:                        return new JCastOperation(program, info, toType, call);
1282:                    } else {
1283:                        return call;
1284:                    }
1285:                }
1286:
1287:                JExpression processExpression(NullLiteral x) {
1288:                    return program.getLiteralNull();
1289:                }
1290:
1291:                JExpression processExpression(OR_OR_Expression x) {
1292:                    JType type = (JType) typeMap.get(x.resolvedType);
1293:                    SourceInfo info = makeSourceInfo(x);
1294:                    return processBinaryOperation(info, JBinaryOperator.OR,
1295:                            type, x.left, x.right);
1296:                }
1297:
1298:                JExpression processExpression(PostfixExpression x) {
1299:                    SourceInfo info = makeSourceInfo(x);
1300:                    JUnaryOperator op;
1301:
1302:                    switch (x.operator) {
1303:                    case PostfixExpression.MINUS:
1304:                        op = JUnaryOperator.DEC;
1305:                        break;
1306:
1307:                    case PostfixExpression.PLUS:
1308:                        op = JUnaryOperator.INC;
1309:                        break;
1310:
1311:                    default:
1312:                        throw new InternalCompilerException(
1313:                                "Unexpected postfix operator");
1314:                    }
1315:
1316:                    JPostfixOperation postOp = new JPostfixOperation(program,
1317:                            info, op, dispProcessExpression(x.lhs));
1318:                    return postOp;
1319:                }
1320:
1321:                JExpression processExpression(PrefixExpression x) {
1322:                    SourceInfo info = makeSourceInfo(x);
1323:                    JUnaryOperator op;
1324:
1325:                    switch (x.operator) {
1326:                    case PrefixExpression.MINUS:
1327:                        op = JUnaryOperator.DEC;
1328:                        break;
1329:
1330:                    case PrefixExpression.PLUS:
1331:                        op = JUnaryOperator.INC;
1332:                        break;
1333:
1334:                    default:
1335:                        throw new InternalCompilerException(
1336:                                "Unexpected prefix operator");
1337:                    }
1338:
1339:                    JPrefixOperation preOp = new JPrefixOperation(program,
1340:                            info, op, dispProcessExpression(x.lhs));
1341:                    return preOp;
1342:                }
1343:
1344:                JExpression processExpression(QualifiedAllocationExpression x) {
1345:                    /*
1346:                     * Weird: sometimes JDT will create a QualifiedAllocationExpression with
1347:                     * no qualifier. I guess this is supposed to let us know that we need to
1348:                     * synthesize a synthetic this arg based on our own current "this"? But
1349:                     * plain old regular AllocationExpression also must be treated as if it
1350:                     * might be be implicitly qualified, so I'm not sure what the point is.
1351:                     * Let's just defer to the AllocationExpression logic if there's no
1352:                     * qualifier.
1353:                     */
1354:                    if (x.enclosingInstance() == null) {
1355:                        return processExpression((AllocationExpression) x);
1356:                    }
1357:
1358:                    SourceInfo info = makeSourceInfo(x);
1359:                    MethodBinding b = x.binding;
1360:                    JMethod ctor = (JMethod) typeMap.get(b);
1361:                    JClassType enclosingType = (JClassType) ctor
1362:                            .getEnclosingType();
1363:                    JNewInstance newInstance = new JNewInstance(program, info,
1364:                            enclosingType);
1365:                    JMethodCall call = new JMethodCall(program, info,
1366:                            newInstance, ctor);
1367:                    JExpression qualifier = dispProcessExpression(x.enclosingInstance);
1368:                    List<JExpression> qualList = new ArrayList<JExpression>();
1369:                    qualList.add(qualifier);
1370:
1371:                    /*
1372:                     * Really weird: Sometimes an allocation expression needs both its
1373:                     * explicit qualifier AND its implicit enclosing class! We add this second
1374:                     * because the explicit qualifier takes precedence.
1375:                     */
1376:                    if (!currentMethod.isStatic()) {
1377:                        JExpression implicitOuter = program.getExprThisRef(
1378:                                info, (JClassType) currentClass);
1379:                        qualList.add(implicitOuter);
1380:                    }
1381:
1382:                    // Plain old regular arguments
1383:                    addCallArgs(x.arguments, call, b);
1384:
1385:                    // Synthetic args for inner classes
1386:                    ReferenceBinding targetBinding = b.declaringClass;
1387:                    if (targetBinding.isNestedType()
1388:                            && !targetBinding.isStatic()) {
1389:                        NestedTypeBinding nestedBinding = (NestedTypeBinding) targetBinding;
1390:                        // Synthetic this args for inner classes
1391:                        if (nestedBinding.enclosingInstances != null) {
1392:                            for (int i = 0; i < nestedBinding.enclosingInstances.length; ++i) {
1393:                                SyntheticArgumentBinding arg = nestedBinding.enclosingInstances[i];
1394:                                JClassType syntheticThisType = (JClassType) typeMap
1395:                                        .get(arg.type);
1396:                                call.getArgs().add(
1397:                                        createThisRef(syntheticThisType,
1398:                                                qualList));
1399:                            }
1400:                        }
1401:                        // Synthetic locals for local classes
1402:                        if (nestedBinding.outerLocalVariables != null) {
1403:                            for (int i = 0; i < nestedBinding.outerLocalVariables.length; ++i) {
1404:                                SyntheticArgumentBinding arg = nestedBinding.outerLocalVariables[i];
1405:                                JVariable variable = (JVariable) typeMap
1406:                                        .get(arg.actualOuterLocalVariable);
1407:                                call.getArgs().add(
1408:                                        createVariableRef(info, variable,
1409:                                                arg.actualOuterLocalVariable));
1410:                            }
1411:                        }
1412:                    }
1413:
1414:                    return call;
1415:                }
1416:
1417:                JExpression processExpression(QualifiedNameReference x) {
1418:                    SourceInfo info = makeSourceInfo(x);
1419:                    Binding binding = x.binding;
1420:                    JNode node = typeMap.get(binding);
1421:                    if (!(node instanceof  JVariable)) {
1422:                        return null;
1423:                    }
1424:                    JVariable variable = (JVariable) node;
1425:
1426:                    JExpression curRef = createVariableRef(info, variable,
1427:                            binding);
1428:
1429:                    /*
1430:                     * Wackiness: JDT represents multiple field access as an array of fields,
1431:                     * each qualified by everything to the left. So each subsequent item in
1432:                     * otherBindings takes the current expression as a qualifier.
1433:                     */
1434:                    if (x.otherBindings != null) {
1435:                        for (FieldBinding fieldBinding : x.otherBindings) {
1436:                            JField field;
1437:                            if (fieldBinding.declaringClass == null) {
1438:                                // probably array.length
1439:                                field = program.getIndexedField("Array.length");
1440:                                if (!field.getName().equals(
1441:                                        String.valueOf(fieldBinding.name))) {
1442:                                    throw new InternalCompilerException(
1443:                                            "Error matching fieldBinding.");
1444:                                }
1445:                            } else {
1446:                                field = (JField) typeMap.get(fieldBinding);
1447:                            }
1448:                            curRef = new JFieldRef(program, info, curRef,
1449:                                    field, currentClass);
1450:                        }
1451:                    }
1452:
1453:                    return curRef;
1454:                }
1455:
1456:                JExpression processExpression(QualifiedSuperReference x) {
1457:                    JClassType refType = (JClassType) typeMap
1458:                            .get(x.resolvedType);
1459:                    JClassType qualType = (JClassType) typeMap
1460:                            .get(x.qualification.resolvedType);
1461:                    assert (refType == qualType.extnds);
1462:                    // Oddly enough, super refs can be modeled as this refs, because whatever
1463:                    // expression they qualify has already been resolved.
1464:                    return processQualifiedThisOrSuperRef(x, qualType);
1465:                }
1466:
1467:                JExpression processExpression(QualifiedThisReference x) {
1468:                    JClassType refType = (JClassType) typeMap
1469:                            .get(x.resolvedType);
1470:                    JClassType qualType = (JClassType) typeMap
1471:                            .get(x.qualification.resolvedType);
1472:                    assert (refType == qualType);
1473:                    return processQualifiedThisOrSuperRef(x, qualType);
1474:                }
1475:
1476:                JExpression processExpression(SingleNameReference x) {
1477:                    SourceInfo info = makeSourceInfo(x);
1478:                    Binding binding = x.binding;
1479:                    Object target = typeMap.get(binding);
1480:                    if (!(target instanceof  JVariable)) {
1481:                        return null;
1482:                    }
1483:                    JVariable variable = (JVariable) target;
1484:
1485:                    /*
1486:                     * Wackiness: if a field happens to have synthetic accessors (only fields
1487:                     * can have them, apparently), this is a ref to a field in an enclosing
1488:                     * instance. CreateThisRef should compute a "this" access of the
1489:                     * appropriate type, unless the field is static.
1490:                     */
1491:                    if (x.syntheticAccessors != null) {
1492:                        JField field = (JField) variable;
1493:                        if (!field.isStatic()) {
1494:                            JExpression instance = createThisRef(info, field
1495:                                    .getEnclosingType());
1496:                            return new JFieldRef(program, info, instance,
1497:                                    field, currentClass);
1498:                        }
1499:                    }
1500:
1501:                    return createVariableRef(info, variable, binding);
1502:                }
1503:
1504:                JExpression processExpression(SuperReference x) {
1505:                    JClassType type = (JClassType) typeMap.get(x.resolvedType);
1506:                    assert (type == currentClass.extnds);
1507:                    SourceInfo info = makeSourceInfo(x);
1508:                    // Oddly enough, super refs can be modeled as a this refs.
1509:                    JExpression super Ref = createThisRef(info, currentClass);
1510:                    return super Ref;
1511:                }
1512:
1513:                JExpression processExpression(ThisReference x) {
1514:                    JClassType type = (JClassType) typeMap.get(x.resolvedType);
1515:                    assert (type == currentClass);
1516:                    SourceInfo info = makeSourceInfo(x);
1517:                    JExpression this Ref = createThisRef(info, currentClass);
1518:                    return this Ref;
1519:                }
1520:
1521:                JExpression processExpression(UnaryExpression x) {
1522:                    SourceInfo info = makeSourceInfo(x);
1523:                    JUnaryOperator op;
1524:                    int operator = ((x.bits & UnaryExpression.OperatorMASK) >> UnaryExpression.OperatorSHIFT);
1525:
1526:                    switch (operator) {
1527:                    case UnaryExpression.MINUS:
1528:                        op = JUnaryOperator.NEG;
1529:                        break;
1530:
1531:                    case UnaryExpression.NOT:
1532:                        op = JUnaryOperator.NOT;
1533:                        break;
1534:
1535:                    case UnaryExpression.PLUS:
1536:                        // Odd case.. a useless + operator; just return the operand
1537:                        return dispProcessExpression(x.expression);
1538:
1539:                    case UnaryExpression.TWIDDLE:
1540:                        op = JUnaryOperator.BIT_NOT;
1541:                        break;
1542:
1543:                    default:
1544:                        throw new InternalCompilerException(
1545:                                "Unexpected operator for unary expression");
1546:                    }
1547:
1548:                    JPrefixOperation preOp = new JPrefixOperation(program,
1549:                            info, op, dispProcessExpression(x.expression));
1550:                    return preOp;
1551:                }
1552:
1553:                List<JExpressionStatement> processExpressionStatements(
1554:                        Statement[] statements) {
1555:                    List<JExpressionStatement> jstatements = new ArrayList<JExpressionStatement>();
1556:                    if (statements != null) {
1557:                        for (int i = 0, n = statements.length; i < n; ++i) {
1558:                            JStatement jstmt = dispProcessStatement(statements[i]);
1559:                            if (jstmt != null) {
1560:                                jstatements.add((JExpressionStatement) jstmt);
1561:                            }
1562:                        }
1563:                    }
1564:                    return jstatements;
1565:                }
1566:
1567:                void processField(FieldDeclaration declaration) {
1568:                    JField field = (JField) typeMap.tryGet(declaration.binding);
1569:                    if (field == null) {
1570:                        /*
1571:                         * When anonymous classes declare constant fields, the field declaration
1572:                         * is not visited by JDT. Just bail since any references to that field
1573:                         * are guaranteed to be replaced with literals.
1574:                         */
1575:                        return;
1576:                    }
1577:                    try {
1578:                        JExpression initializer = null;
1579:                        if (declaration.initialization != null) {
1580:                            initializer = dispProcessExpression(declaration.initialization);
1581:                        }
1582:
1583:                        if (field instanceof  JEnumField) {
1584:                            // An enum field must be initialized!
1585:                            assert (initializer instanceof  JMethodCall);
1586:                        }
1587:
1588:                        if (initializer instanceof  JLiteral) {
1589:                            field.constInitializer = (JLiteral) initializer;
1590:                        } else if (initializer != null) {
1591:                            SourceInfo info = makeSourceInfo(declaration);
1592:                            JStatement assignStmt = program
1593:                                    .createAssignmentStmt(info,
1594:                                            createVariableRef(info, field),
1595:                                            initializer);
1596:
1597:                            // will either be init or clinit
1598:                            currentMethodBody.getStatements().add(assignStmt);
1599:                        }
1600:                    } catch (Throwable e) {
1601:                        throw translateException(field, e);
1602:                    }
1603:                }
1604:
1605:                void processInitializer(Initializer initializer) {
1606:                    JBlock block = (JBlock) dispProcessStatement(initializer.block);
1607:                    try {
1608:                        // will either be init or clinit
1609:                        currentMethodBody.getStatements().add(block);
1610:                    } catch (Throwable e) {
1611:                        throw translateException(initializer, e);
1612:                    }
1613:                }
1614:
1615:                void processMethod(AbstractMethodDeclaration x) {
1616:                    MethodBinding b = x.binding;
1617:                    JMethod method = (JMethod) typeMap.get(b);
1618:                    try {
1619:                        if (b.isImplementing() || b.isOverriding()) {
1620:                            tryFindUpRefs(method, b);
1621:                        }
1622:
1623:                        if (x.isNative()) {
1624:                            processNativeMethod(x, (JsniMethodBody) method
1625:                                    .getBody());
1626:                            return;
1627:                        }
1628:
1629:                        currentMethod = method;
1630:                        currentMethodBody = (JMethodBody) method.getBody();
1631:                        currentMethodScope = x.scope;
1632:
1633:                        if (x.statements != null) {
1634:                            for (int i = 0, n = x.statements.length; i < n; ++i) {
1635:                                Statement origStmt = x.statements[i];
1636:                                JStatement jstmt = dispProcessStatement(origStmt);
1637:                                if (jstmt != null) {
1638:                                    currentMethodBody.getStatements()
1639:                                            .add(jstmt);
1640:                                }
1641:                            }
1642:                        }
1643:                        currentMethodScope = null;
1644:                        currentMethodBody = null;
1645:                        currentMethod = null;
1646:                    } catch (Throwable e) {
1647:                        throw translateException(method, e);
1648:                    }
1649:                }
1650:
1651:                void processNativeMethod(AbstractMethodDeclaration x,
1652:                        JsniMethodBody nativeMethodBody) {
1653:
1654:                    JsFunction func = nativeMethodBody.getFunc();
1655:                    if (func == null) {
1656:                        return;
1657:                    }
1658:
1659:                    // resolve jsni refs
1660:                    new JsniRefResolver(x, nativeMethodBody).accept(func);
1661:                }
1662:
1663:                JStatement processStatement(AssertStatement x) {
1664:                    SourceInfo info = makeSourceInfo(x);
1665:                    JExpression expr = dispProcessExpression(x.assertExpression);
1666:                    JExpression arg = dispProcessExpression(x.exceptionArgument);
1667:                    return new JAssertStatement(program, info, expr, arg);
1668:                }
1669:
1670:                JBlock processStatement(Block x) {
1671:                    if (x == null) {
1672:                        return null;
1673:                    }
1674:
1675:                    SourceInfo info = makeSourceInfo(x);
1676:                    JBlock block = new JBlock(program, info);
1677:                    if (x.statements != null) {
1678:                        for (int i = 0, n = x.statements.length; i < n; ++i) {
1679:                            JStatement jstmt = dispProcessStatement(x.statements[i]);
1680:                            if (jstmt != null) {
1681:                                block.statements.add(jstmt);
1682:                            }
1683:                        }
1684:                    }
1685:                    return block;
1686:                }
1687:
1688:                JStatement processStatement(BreakStatement x) {
1689:                    SourceInfo info = makeSourceInfo(x);
1690:                    return new JBreakStatement(program, info, getOrCreateLabel(
1691:                            info, currentMethod, x.label));
1692:                }
1693:
1694:                JStatement processStatement(CaseStatement x) {
1695:                    SourceInfo info = makeSourceInfo(x);
1696:                    JExpression expression = dispProcessExpression(x.constantExpression);
1697:                    if (x.isEnumConstant) {
1698:                        // TODO: propagate enum information?
1699:                        JFieldRef fieldRef = (JFieldRef) expression;
1700:                        JEnumField field = (JEnumField) fieldRef.getField();
1701:                        return new JCaseStatement(program, info, program
1702:                                .getLiteralInt(field.ordinal()));
1703:                    } else {
1704:                        return new JCaseStatement(program, info,
1705:                                (JLiteral) expression);
1706:                    }
1707:                }
1708:
1709:                JStatement processStatement(ContinueStatement x) {
1710:                    SourceInfo info = makeSourceInfo(x);
1711:                    return new JContinueStatement(program, info,
1712:                            getOrCreateLabel(info, currentMethod, x.label));
1713:                }
1714:
1715:                JStatement processStatement(DoStatement x) {
1716:                    SourceInfo info = makeSourceInfo(x);
1717:                    JExpression loopTest = dispProcessExpression(x.condition);
1718:                    JStatement loopBody = dispProcessStatement(x.action);
1719:                    JDoStatement stmt = new JDoStatement(program, info,
1720:                            loopTest, loopBody);
1721:                    return stmt;
1722:                }
1723:
1724:                JStatement processStatement(EmptyStatement x) {
1725:                    return null;
1726:                }
1727:
1728:                JStatement processStatement(ForeachStatement x) {
1729:                    SourceInfo info = makeSourceInfo(x);
1730:
1731:                    JBlock body;
1732:                    JStatement action = dispProcessStatement(x.action);
1733:                    if (action instanceof  JBlock) {
1734:                        body = (JBlock) action;
1735:                    } else {
1736:                        body = new JBlock(program, info);
1737:                        body.statements.add(action);
1738:                    }
1739:
1740:                    JLocal elementVar = (JLocal) typeMap
1741:                            .get(x.elementVariable.binding);
1742:                    String elementVarName = elementVar.getName();
1743:
1744:                    JLocalDeclarationStatement elementDecl = (JLocalDeclarationStatement) processStatement(x.elementVariable);
1745:                    assert (elementDecl.initializer == null);
1746:
1747:                    JForStatement result;
1748:                    if (x.collection.resolvedType.isArrayType()) {
1749:                        /**
1750:                         * <pre>
1751:                         * for (T[] i$array = collection, int i$index = 0, int i$max = i$array.length;
1752:                         *     i$index < i$max; ++i$index) {
1753:                         *   T elementVar = i$array[i$index];
1754:                         *   // user action
1755:                         * }
1756:                         * </pre>
1757:                         */
1758:                        JLocal arrayVar = createSyntheticLocal(info,
1759:                                elementVarName + "$array", (JType) typeMap
1760:                                        .get(x.collection.resolvedType));
1761:                        JLocal indexVar = createSyntheticLocal(info,
1762:                                elementVarName + "$index", program
1763:                                        .getTypePrimitiveInt());
1764:                        JLocal maxVar = createSyntheticLocal(info,
1765:                                elementVarName + "$max", program
1766:                                        .getTypePrimitiveInt());
1767:
1768:                        List<JStatement> initializers = new ArrayList<JStatement>(
1769:                                3);
1770:                        // T[] i$array = arr
1771:                        initializers.add(createLocalDeclaration(info, arrayVar,
1772:                                dispProcessExpression(x.collection)));
1773:                        // int i$index = 0
1774:                        initializers.add(createLocalDeclaration(info, indexVar,
1775:                                program.getLiteralInt(0)));
1776:                        // int i$max = i$array.length
1777:                        initializers.add(createLocalDeclaration(info, maxVar,
1778:                                new JFieldRef(program, info, createVariableRef(
1779:                                        info, arrayVar), program
1780:                                        .getIndexedField("Array.length"),
1781:                                        currentClass)));
1782:
1783:                        // i$index < i$max
1784:                        JExpression condition = new JBinaryOperation(program,
1785:                                info, program.getTypePrimitiveBoolean(),
1786:                                JBinaryOperator.LT, createVariableRef(info,
1787:                                        indexVar), createVariableRef(info,
1788:                                        maxVar));
1789:
1790:                        // ++i$index
1791:                        List<JExpressionStatement> increments = new ArrayList<JExpressionStatement>(
1792:                                1);
1793:                        increments.add(new JPrefixOperation(program, info,
1794:                                JUnaryOperator.INC, createVariableRef(info,
1795:                                        indexVar)).makeStatement());
1796:
1797:                        // T elementVar = i$array[i$index];
1798:                        elementDecl.initializer = new JArrayRef(program, info,
1799:                                createVariableRef(info, arrayVar),
1800:                                createVariableRef(info, indexVar));
1801:                        body.statements.add(0, elementDecl);
1802:
1803:                        result = new JForStatement(program, info, initializers,
1804:                                condition, increments, body);
1805:                    } else {
1806:                        /**
1807:                         * <pre>
1808:                         * for (Iterator<T> i$iterator = collection.iterator(); i$iterator.hasNext(); ) {
1809:                         *   T elementVar = i$iterator.next();
1810:                         *   // user action
1811:                         * }
1812:                         * </pre>
1813:                         */
1814:                        JLocal iteratorVar = createSyntheticLocal(info,
1815:                                elementVarName + "$iterator", (JType) typeMap
1816:                                        .get(x.collection.resolvedType));
1817:
1818:                        List<JStatement> initializers = new ArrayList<JStatement>(
1819:                                1);
1820:                        // Iterator<T> i$iterator = collection.iterator()
1821:                        initializers
1822:                                .add(createLocalDeclaration(
1823:                                        info,
1824:                                        iteratorVar,
1825:                                        new JMethodCall(
1826:                                                program,
1827:                                                info,
1828:                                                dispProcessExpression(x.collection),
1829:                                                program
1830:                                                        .getIndexedMethod("Iterable.iterator"))));
1831:
1832:                        // i$iterator.hasNext()
1833:                        JExpression condition = new JMethodCall(program, info,
1834:                                createVariableRef(info, iteratorVar), program
1835:                                        .getIndexedMethod("Iterator.hasNext"));
1836:
1837:                        // T elementVar = i$array[i$index];
1838:                        elementDecl.initializer = new JMethodCall(program,
1839:                                info, createVariableRef(info, iteratorVar),
1840:                                program.getIndexedMethod("Iterator.next"));
1841:                        body.statements.add(0, elementDecl);
1842:
1843:                        result = new JForStatement(program, info, initializers,
1844:                                condition, Collections
1845:                                        .<JExpressionStatement> emptyList(),
1846:                                body);
1847:                    }
1848:
1849:                    // May need to box or unbox the assignment.
1850:                    if (x.elementVariableImplicitWidening != -1) {
1851:                        if ((x.elementVariableImplicitWidening & TypeIds.BOXING) != 0) {
1852:                            elementDecl.initializer = box(
1853:                                    elementDecl.initializer,
1854:                                    (JClassType) elementVar.getType());
1855:                        } else if ((x.elementVariableImplicitWidening & TypeIds.UNBOXING) != 0) {
1856:                            elementDecl.initializer = unbox(
1857:                                    elementDecl.initializer,
1858:                                    (JPrimitiveType) elementVar.getType());
1859:                        }
1860:                    }
1861:                    return result;
1862:                }
1863:
1864:                JStatement processStatement(ForStatement x) {
1865:                    SourceInfo info = makeSourceInfo(x);
1866:                    // SEE NOTE ON JDT FORCED OPTIMIZATIONS
1867:                    // If the condition is false, don't process the body
1868:                    boolean removeBody = isOptimizedFalse(x.condition);
1869:
1870:                    List<JStatement> init = processStatements(x.initializations);
1871:                    JExpression expr = dispProcessExpression(x.condition);
1872:                    List<JExpressionStatement> incr = processExpressionStatements(x.increments);
1873:                    JStatement body = removeBody ? null
1874:                            : dispProcessStatement(x.action);
1875:                    return new JForStatement(program, info, init, expr, incr,
1876:                            body);
1877:                }
1878:
1879:                JStatement processStatement(IfStatement x) {
1880:                    // SEE NOTE ON JDT FORCED OPTIMIZATIONS
1881:                    // If the condition is false, don't process the then statement
1882:                    // If the condition is false, don't process the else statement
1883:                    boolean removeThen = isOptimizedFalse(x.condition);
1884:                    boolean removeElse = isOptimizedTrue(x.condition);
1885:
1886:                    SourceInfo info = makeSourceInfo(x);
1887:                    JExpression expr = dispProcessExpression(x.condition);
1888:                    JStatement thenStmt = removeThen ? null
1889:                            : dispProcessStatement(x.thenStatement);
1890:                    JStatement elseStmt = removeElse ? null
1891:                            : dispProcessStatement(x.elseStatement);
1892:                    JIfStatement ifStmt = new JIfStatement(program, info, expr,
1893:                            thenStmt, elseStmt);
1894:                    return ifStmt;
1895:                }
1896:
1897:                JStatement processStatement(LabeledStatement x) {
1898:                    JStatement body = dispProcessStatement(x.statement);
1899:                    if (body == null) {
1900:                        return null;
1901:                    }
1902:                    SourceInfo info = makeSourceInfo(x);
1903:                    return new JLabeledStatement(program, info,
1904:                            getOrCreateLabel(info, currentMethod, x.label),
1905:                            body);
1906:                }
1907:
1908:                JStatement processStatement(LocalDeclaration x) {
1909:                    SourceInfo info = makeSourceInfo(x);
1910:                    JLocal local = (JLocal) typeMap.get(x.binding);
1911:                    JLocalRef localRef = new JLocalRef(program, info, local);
1912:                    JExpression initializer = dispProcessExpression(x.initialization);
1913:                    return new JLocalDeclarationStatement(program, info,
1914:                            localRef, initializer);
1915:                }
1916:
1917:                JStatement processStatement(ReturnStatement x) {
1918:                    SourceInfo info = makeSourceInfo(x);
1919:                    if (currentMethodScope.referenceContext instanceof  ConstructorDeclaration) {
1920:                        /*
1921:                         * Special: constructors are implemented as instance methods that return
1922:                         * their this object, so any embedded return statements have to be fixed
1923:                         * up.
1924:                         */
1925:                        JClassType enclosingType = (JClassType) currentMethod
1926:                                .getEnclosingType();
1927:                        assert (x.expression == null);
1928:                        return new JReturnStatement(program, info,
1929:                                createThisRef(info, enclosingType));
1930:                    } else {
1931:                        return new JReturnStatement(program, info,
1932:                                dispProcessExpression(x.expression));
1933:                    }
1934:                }
1935:
1936:                JStatement processStatement(SwitchStatement x) {
1937:                    SourceInfo info = makeSourceInfo(x);
1938:                    JExpression expression = dispProcessExpression(x.expression);
1939:                    if (expression.getType() instanceof  JClassType) {
1940:                        // Must be an enum; synthesize a call to ordinal().
1941:                        expression = new JMethodCall(program, info, expression,
1942:                                program.getIndexedMethod("Enum.ordinal"));
1943:                    }
1944:                    JBlock block = new JBlock(program, info);
1945:                    block.statements = processStatements(x.statements);
1946:                    return new JSwitchStatement(program, info, expression,
1947:                            block);
1948:                }
1949:
1950:                JStatement processStatement(SynchronizedStatement x) {
1951:                    JBlock block = (JBlock) dispProcessStatement(x.block);
1952:                    JExpression expr = dispProcessExpression(x.expression);
1953:                    block.statements.add(0, expr.makeStatement());
1954:                    return block;
1955:                }
1956:
1957:                JStatement processStatement(ThrowStatement x) {
1958:                    SourceInfo info = makeSourceInfo(x);
1959:                    JExpression toThrow = dispProcessExpression(x.exception);
1960:                    return new JThrowStatement(program, info, toThrow);
1961:                }
1962:
1963:                JStatement processStatement(TryStatement x) {
1964:                    SourceInfo info = makeSourceInfo(x);
1965:                    JBlock tryBlock = (JBlock) dispProcessStatement(x.tryBlock);
1966:                    List<JLocalRef> catchArgs = new ArrayList<JLocalRef>();
1967:                    List<JBlock> catchBlocks = new ArrayList<JBlock>();
1968:                    if (x.catchBlocks != null) {
1969:                        for (int i = 0, c = x.catchArguments.length; i < c; ++i) {
1970:                            JLocal local = (JLocal) typeMap
1971:                                    .get(x.catchArguments[i].binding);
1972:                            catchArgs.add((JLocalRef) createVariableRef(info,
1973:                                    local));
1974:                        }
1975:                        for (int i = 0, c = x.catchBlocks.length; i < c; ++i) {
1976:                            catchBlocks
1977:                                    .add((JBlock) dispProcessStatement(x.catchBlocks[i]));
1978:                        }
1979:                    }
1980:                    JBlock finallyBlock = (JBlock) dispProcessStatement(x.finallyBlock);
1981:                    return new JTryStatement(program, info, tryBlock,
1982:                            catchArgs, catchBlocks, finallyBlock);
1983:                }
1984:
1985:                JStatement processStatement(TypeDeclaration x) {
1986:                    // do nothing -- the local class is treated at the program level
1987:                    return null;
1988:                }
1989:
1990:                JStatement processStatement(WhileStatement x) {
1991:                    // SEE NOTE ON JDT FORCED OPTIMIZATIONS
1992:                    // If the condition is false, don't process the body
1993:                    boolean removeBody = isOptimizedFalse(x.condition);
1994:
1995:                    SourceInfo info = makeSourceInfo(x);
1996:                    JExpression loopTest = dispProcessExpression(x.condition);
1997:                    JStatement loopBody = removeBody ? null
1998:                            : dispProcessStatement(x.action);
1999:                    JWhileStatement stmt = new JWhileStatement(program, info,
2000:                            loopTest, loopBody);
2001:                    return stmt;
2002:                }
2003:
2004:                List<JStatement> processStatements(Statement[] statements) {
2005:                    List<JStatement> jstatements = new ArrayList<JStatement>();
2006:                    if (statements != null) {
2007:                        for (int i = 0, n = statements.length; i < n; ++i) {
2008:                            JStatement jstmt = dispProcessStatement(statements[i]);
2009:                            if (jstmt != null) {
2010:                                jstatements.add(jstmt);
2011:                            }
2012:                        }
2013:                    }
2014:                    return jstatements;
2015:                }
2016:
2017:                JMethodCall processSuperConstructorCall(
2018:                        ExplicitConstructorCall x) {
2019:                    SourceInfo info = makeSourceInfo(x);
2020:                    JMethod ctor = (JMethod) typeMap.get(x.binding);
2021:                    JExpression trueQualifier = createThisRef(info,
2022:                            currentClass);
2023:                    JMethodCall call = new JMethodCall(program, info,
2024:                            trueQualifier, ctor);
2025:
2026:                    addCallArgs(x.arguments, call, x.binding);
2027:
2028:                    // We have to find and pass through any synthetics our supertype needs
2029:                    ReferenceBinding super Class = x.binding.declaringClass;
2030:                    if (super Class instanceof  NestedTypeBinding
2031:                            && !super Class.isStatic()) {
2032:                        NestedTypeBinding myBinding = (NestedTypeBinding) currentClassScope
2033:                                .referenceType().binding;
2034:                        NestedTypeBinding super Binding = (NestedTypeBinding) super Class;
2035:
2036:                        // enclosing types
2037:                        if (super Binding.enclosingInstances != null) {
2038:                            JExpression qualifier = dispProcessExpression(x.qualification);
2039:                            for (int j = 0; j < super Binding.enclosingInstances.length; ++j) {
2040:                                SyntheticArgumentBinding arg = super Binding.enclosingInstances[j];
2041:                                JClassType classType = (JClassType) typeMap
2042:                                        .get(arg.type);
2043:                                if (qualifier == null) {
2044:                                    /*
2045:                                     * Got to be one of my params; it would be illegal to use a this
2046:                                     * ref at this moment-- we would most likely be passing in a
2047:                                     * supertype field that HASN'T BEEN INITIALIZED YET.
2048:                                     * 
2049:                                     * Unfortunately, my params might not work as-is, so we have to
2050:                                     * check each one to see if any will make a suitable this ref.
2051:                                     */
2052:                                    List<JExpression> workList = new ArrayList<JExpression>();
2053:                                    Iterator<JParameter> paramIt = getSyntheticsIterator(currentMethod);
2054:                                    for (int i = 0; i < myBinding.enclosingInstances.length; ++i) {
2055:                                        workList.add(createVariableRef(info,
2056:                                                paramIt.next()));
2057:                                    }
2058:                                    call.getArgs().add(
2059:                                            createThisRef(classType, workList));
2060:                                } else {
2061:                                    call.getArgs()
2062:                                            .add(
2063:                                                    createThisRef(classType,
2064:                                                            qualifier));
2065:                                }
2066:                            }
2067:                        }
2068:
2069:                        // outer locals
2070:                        if (super Binding.outerLocalVariables != null) {
2071:                            for (int j = 0; j < super Binding.outerLocalVariables.length; ++j) {
2072:                                SyntheticArgumentBinding arg = super Binding.outerLocalVariables[j];
2073:                                // Got to be one of my params
2074:                                JType varType = (JType) typeMap.get(arg.type);
2075:                                String varName = String.valueOf(arg.name);
2076:                                JParameter param = null;
2077:                                for (int i = 0; i < currentMethod.params.size(); ++i) {
2078:                                    JParameter paramIt = currentMethod.params
2079:                                            .get(i);
2080:                                    if (varType == paramIt.getType()
2081:                                            && varName
2082:                                                    .equals(paramIt.getName())) {
2083:                                        param = paramIt;
2084:                                    }
2085:                                }
2086:                                if (param == null) {
2087:                                    throw new InternalCompilerException(
2088:                                            "Could not find matching local arg for explicit super ctor call.");
2089:                                }
2090:                                call.getArgs().add(
2091:                                        createVariableRef(info, param));
2092:                            }
2093:                        }
2094:                    }
2095:
2096:                    return call;
2097:                }
2098:
2099:                JMethodCall processThisConstructorCall(ExplicitConstructorCall x) {
2100:                    SourceInfo info = makeSourceInfo(x);
2101:                    JMethod ctor = (JMethod) typeMap.get(x.binding);
2102:                    JExpression trueQualifier = createThisRef(info,
2103:                            currentClass);
2104:                    JMethodCall call = new JMethodCall(program, info,
2105:                            trueQualifier, ctor);
2106:
2107:                    assert (x.qualification == null);
2108:
2109:                    addCallArgs(x.arguments, call, x.binding);
2110:
2111:                    // All synthetics must be passed through to the target ctor
2112:                    ReferenceBinding declaringClass = x.binding.declaringClass;
2113:                    if (declaringClass instanceof  NestedTypeBinding) {
2114:                        Iterator<JParameter> paramIt = getSyntheticsIterator(currentMethod);
2115:                        NestedTypeBinding nestedBinding = (NestedTypeBinding) declaringClass;
2116:                        if (nestedBinding.enclosingInstances != null) {
2117:                            for (int i = 0; i < nestedBinding.enclosingInstances.length; ++i) {
2118:                                call.getArgs()
2119:                                        .add(
2120:                                                createVariableRef(info, paramIt
2121:                                                        .next()));
2122:                            }
2123:                        }
2124:                        if (nestedBinding.outerLocalVariables != null) {
2125:                            for (int i = 0; i < nestedBinding.outerLocalVariables.length; ++i) {
2126:                                call.getArgs()
2127:                                        .add(
2128:                                                createVariableRef(info, paramIt
2129:                                                        .next()));
2130:                            }
2131:                        }
2132:                    }
2133:
2134:                    return call;
2135:                }
2136:
2137:                private void addAllOuterThisRefs(List<? super  JFieldRef> list,
2138:                        JExpression expr, JClassType classType) {
2139:                    if (classType.fields.size() > 0) {
2140:                        JField field = classType.fields.get(0);
2141:                        if (field.getName().startsWith("this$")) {
2142:                            list
2143:                                    .add(new JFieldRef(program, expr
2144:                                            .getSourceInfo(), expr, field,
2145:                                            currentClass));
2146:                        }
2147:                    }
2148:                }
2149:
2150:                private void addAllOuterThisRefsPlusSuperChain(
2151:                        List<? super  JFieldRef> workList, JExpression expr,
2152:                        JClassType classType) {
2153:                    for (; classType != null; classType = classType.extnds) {
2154:                        addAllOuterThisRefs(workList, expr, classType);
2155:                    }
2156:                }
2157:
2158:                private void addCallArgs(Expression[] args, JMethodCall call,
2159:                        MethodBinding binding) {
2160:                    if (args != null) {
2161:                        TypeBinding[] params = binding.parameters;
2162:                        int n = params.length;
2163:
2164:                        if (binding.isVarargs()) {
2165:                            // Do everything but the last arg.
2166:                            --n;
2167:                        }
2168:
2169:                        for (int i = 0; i < n; ++i) {
2170:                            call.getArgs().add(dispProcessExpression(args[i]));
2171:                        }
2172:
2173:                        if (binding.isVarargs()) {
2174:                            // Handle the last arg.
2175:                            JArrayType type = (JArrayType) typeMap
2176:                                    .get(params[n]);
2177:
2178:                            // See if there is only one arg and it's an array of the correct dims.
2179:                            if (args.length == n + 1) {
2180:                                JType lastArgType = (JType) typeMap
2181:                                        .get(args[n].resolvedType);
2182:                                if (lastArgType instanceof  JArrayType) {
2183:                                    JArrayType lastArgArrayType = (JArrayType) lastArgType;
2184:                                    if (lastArgArrayType.getDims() == type
2185:                                            .getDims()) {
2186:                                        // Looks like it's already an array.
2187:                                        call.getArgs().add(
2188:                                                dispProcessExpression(args[n]));
2189:                                        return;
2190:                                    }
2191:                                }
2192:                            }
2193:
2194:                            // Fall through: must synthesize a new array allocation.
2195:                            SourceInfo info = makeSourceInfo(args[n]);
2196:                            JNewArray newArray = new JNewArray(program, info,
2197:                                    type);
2198:                            newArray.initializers = new ArrayList<JExpression>();
2199:                            for (int i = n; i < args.length; ++i) {
2200:                                newArray.initializers
2201:                                        .add(dispProcessExpression(args[i]));
2202:                            }
2203:                            call.getArgs().add(newArray);
2204:                        }
2205:                    }
2206:                }
2207:
2208:                private JExpression box(JExpression toBox,
2209:                        JClassType wrapperType) {
2210:                    JPrimitiveType primitiveType = getPrimitiveTypeForWrapperType(wrapperType);
2211:                    if (primitiveType == null) {
2212:                        throw new InternalCompilerException(toBox,
2213:                                "Failed to find primitive type for wrapper type '"
2214:                                        + wrapperType.getName() + "'", null);
2215:                    }
2216:
2217:                    // Find the correct valueOf() method.
2218:                    JMethod valueOfMethod = null;
2219:                    for (JMethod method : wrapperType.methods) {
2220:                        if ("valueOf".equals(method.getName())) {
2221:                            if (method.params.size() == 1) {
2222:                                JParameter param = method.params.get(0);
2223:                                if (param.getType() == primitiveType) {
2224:                                    // Found it.
2225:                                    valueOfMethod = method;
2226:                                    break;
2227:                                }
2228:                            }
2229:                        }
2230:                    }
2231:
2232:                    if (valueOfMethod == null || !valueOfMethod.isStatic()
2233:                            || valueOfMethod.getType() != wrapperType) {
2234:                        throw new InternalCompilerException(
2235:                                toBox,
2236:                                "Expected to find a method on '"
2237:                                        + wrapperType.getName()
2238:                                        + "' whose signature matches 'public static "
2239:                                        + wrapperType.getName() + " valueOf("
2240:                                        + primitiveType.getName() + ")'", null);
2241:                    }
2242:
2243:                    // Create the boxing call.
2244:                    JMethodCall call = new JMethodCall(program, toBox
2245:                            .getSourceInfo(), null, valueOfMethod);
2246:                    call.getArgs().add(toBox);
2247:                    return call;
2248:                }
2249:
2250:                private JExpression box(JExpression toBox,
2251:                        JPrimitiveType primitiveType) {
2252:                    // Find the wrapper type for this primitive type.
2253:                    String wrapperTypeName = primitiveType.getWrapperTypeName();
2254:                    JClassType wrapperType = (JClassType) program
2255:                            .getFromTypeMap(wrapperTypeName);
2256:                    if (wrapperType == null) {
2257:                        throw new InternalCompilerException(toBox,
2258:                                "Cannot find wrapper type '" + wrapperTypeName
2259:                                        + "' associated with primitive type '"
2260:                                        + primitiveType.getName() + "'", null);
2261:                    }
2262:                    return box(toBox, wrapperType);
2263:                }
2264:
2265:                private JField createEnumValueMap(JEnumType type) {
2266:                    JsonObject map = new JsonObject(program);
2267:                    for (JEnumField field : type.enumList) {
2268:                        // JSON maps require leading underscores to prevent collisions.
2269:                        JStringLiteral key = program.getLiteralString("_"
2270:                                + field.getName());
2271:                        JFieldRef value = new JFieldRef(program, null, null,
2272:                                field, type);
2273:                        map.propInits.add(new JsonObject.JsonPropInit(program,
2274:                                key, value));
2275:                    }
2276:                    JField mapField = program.createField(null, "enum$map"
2277:                            .toCharArray(), type, map.getType(), true, true,
2278:                            true);
2279:
2280:                    // Initialize in clinit.
2281:                    JMethodBody clinitBody = (JMethodBody) type.methods.get(0)
2282:                            .getBody();
2283:                    JExpressionStatement assignment = program
2284:                            .createAssignmentStmt(null, createVariableRef(null,
2285:                                    mapField), map);
2286:                    clinitBody.getStatements().add(assignment);
2287:                    return mapField;
2288:                }
2289:
2290:                private JLocalDeclarationStatement createLocalDeclaration(
2291:                        SourceInfo info, JLocal arrayVar, JExpression value) {
2292:                    return new JLocalDeclarationStatement(program, info,
2293:                            new JLocalRef(program, info, arrayVar), value);
2294:                }
2295:
2296:                /**
2297:                 * Helper to create a qualified "this" ref (really a synthetic this field
2298:                 * access) of the appropriate type. Always use this method instead of
2299:                 * creating a naked JThisRef or you won't get the synthetic accesses right.
2300:                 */
2301:                private JExpression createQualifiedThisRef(SourceInfo info,
2302:                        JClassType targetType) {
2303:                    assert (currentClass instanceof  JClassType);
2304:                    JExpression expr = program.getExprThisRef(info,
2305:                            (JClassType) currentClass);
2306:                    List<JExpression> list = new ArrayList<JExpression>();
2307:                    addAllOuterThisRefsPlusSuperChain(list, expr,
2308:                            (JClassType) currentClass);
2309:                    return createThisRef(targetType, list);
2310:                }
2311:
2312:                private JLocal createSyntheticLocal(SourceInfo info,
2313:                        String name, JType type) {
2314:                    return program.createLocal(info, name.toCharArray(), type,
2315:                            false, currentMethodBody);
2316:                }
2317:
2318:                /**
2319:                 * Helper to create an expression of the target type, possibly by accessing
2320:                 * synthetic this fields on the passed-in expression. This is needed by a
2321:                 * QualifiedAllocationExpression, because the qualifier may not be the
2322:                 * correct type, and we may need use one of its fields.
2323:                 */
2324:                private JExpression createThisRef(JReferenceType qualType,
2325:                        JExpression expr) {
2326:                    List<JExpression> list = new ArrayList<JExpression>();
2327:                    list.add(expr);
2328:                    return createThisRef(qualType, list);
2329:                }
2330:
2331:                /**
2332:                 * Helper to create an expression of the target type, possibly by accessing
2333:                 * synthetic this fields on ANY of several passed-in expressions. Why in the
2334:                 * world would we need to do this? It turns out that when making an
2335:                 * unqualified explicit super constructor call to something that needs a
2336:                 * synthetic outer this arg, the correct value to pass in can be one of
2337:                 * several of the calling constructor's own synthetic ags. The catch is,
2338:                 * it's possible none of the args are exactly the right type-- we have to
2339:                 * make one of them the right type by following each of their synthetic this
2340:                 * refs up an arbitrarily big tree of enclosing classes and
2341:                 * supertypes-with-enclosing-classes until we find something that's the
2342:                 * right type.
2343:                 * 
2344:                 * We have this implemented as a Breadth-First Search to minimize the number
2345:                 * of derefs required, and this seems to be correct. Note that we explicitly
2346:                 * prefer the current expression as one of its supertypes over a synthetic
2347:                 * this ref rooted off the current expression that happens to be the correct
2348:                 * type. We have observed this to be consistent with how Java handles it.
2349:                 */
2350:                private JExpression createThisRef(JReferenceType qualType,
2351:                        List<JExpression> list) {
2352:                    LinkedList<JExpression> workList = new LinkedList<JExpression>();
2353:                    workList.addAll(list);
2354:                    while (!workList.isEmpty()) {
2355:                        JExpression expr = workList.removeFirst();
2356:                        JClassType classType = (JClassType) expr.getType();
2357:                        for (; classType != null; classType = classType.extnds) {
2358:                            // prefer myself or myself-as-supertype over any of my this$ fields
2359:                            // that may have already been added to the work list
2360:                            if (program.typeOracle.canTriviallyCast(classType,
2361:                                    qualType)) {
2362:                                return expr;
2363:                            }
2364:                            addAllOuterThisRefs(workList, expr, classType);
2365:                        }
2366:                    }
2367:
2368:                    throw new InternalCompilerException(
2369:                            "Cannot create a ThisRef of the appropriate type.");
2370:                }
2371:
2372:                /**
2373:                 * Helper to creates this ref (or maybe a synthetic this field access) of
2374:                 * the appropriate type. Always use this method instead of creating a naked
2375:                 * JThisRef or you won't get the synthetic accesses right.
2376:                 */
2377:                private JExpression createThisRef(SourceInfo info,
2378:                        JReferenceType targetType) {
2379:                    assert (currentClass instanceof  JClassType);
2380:                    return createThisRef(targetType, program.getExprThisRef(
2381:                            info, (JClassType) currentClass));
2382:                }
2383:
2384:                /**
2385:                 * Creates an appropriate JVariableRef for the polymorphic type of the
2386:                 * requested JVariable.
2387:                 */
2388:                private JVariableRef createVariableRef(SourceInfo info,
2389:                        JVariable variable) {
2390:                    if (variable instanceof  JLocal) {
2391:                        JLocal local = (JLocal) variable;
2392:                        if (local.getEnclosingMethod() != currentMethod) {
2393:                            throw new InternalCompilerException(
2394:                                    "LocalRef referencing local in a different method.");
2395:                        }
2396:                        return new JLocalRef(program, info, local);
2397:                    } else if (variable instanceof  JParameter) {
2398:                        JParameter parameter = (JParameter) variable;
2399:                        if (parameter.getEnclosingMethod() != currentMethod) {
2400:                            throw new InternalCompilerException(
2401:                                    "ParameterRef referencing param in a different method.");
2402:                        }
2403:                        return new JParameterRef(program, info, parameter);
2404:                    } else if (variable instanceof  JField) {
2405:                        JField field = (JField) variable;
2406:                        JExpression instance = null;
2407:                        if (!field.isStatic()) {
2408:                            JClassType fieldEnclosingType = (JClassType) field
2409:                                    .getEnclosingType();
2410:                            instance = createThisRef(info, fieldEnclosingType);
2411:                            if (!program.typeOracle.canTriviallyCast(
2412:                                    (JClassType) instance.getType(),
2413:                                    fieldEnclosingType)) {
2414:                                throw new InternalCompilerException(
2415:                                        "FieldRef referencing field in a different type.");
2416:                            }
2417:                        }
2418:                        return new JFieldRef(program, info, instance, field,
2419:                                currentClass);
2420:                    }
2421:                    throw new InternalCompilerException(
2422:                            "Unknown JVariable subclass.");
2423:                }
2424:
2425:                /**
2426:                 * Creates an appropriate JVariableRef for the polymorphic type of the
2427:                 * requested JVariable.
2428:                 */
2429:                private JVariableRef createVariableRef(SourceInfo info,
2430:                        JVariable variable, Binding binding) {
2431:                    // Fix up the reference if it's to an outer local/param
2432:                    variable = possiblyReferenceOuterLocal(variable, binding);
2433:                    if (variable == null) {
2434:                        /*
2435:                         * Strange case: in certain circumstances, JDT will fail to provide an
2436:                         * emulation path to an outer local variable. In the case I know of, the
2437:                         * reference is a spurious qualifier to a static method call. Let's just
2438:                         * return null and ditch the expression.
2439:                         */
2440:                        return null;
2441:                    }
2442:                    return createVariableRef(info, variable);
2443:                }
2444:
2445:                private SourceTypeBinding erasure(TypeBinding typeBinding) {
2446:                    if (typeBinding instanceof  ParameterizedTypeBinding) {
2447:                        typeBinding = ((ParameterizedTypeBinding) typeBinding)
2448:                                .erasure();
2449:                    }
2450:                    return (SourceTypeBinding) typeBinding;
2451:                }
2452:
2453:                /**
2454:                 * Get a new label of a particular name, or create a new one if it doesn't
2455:                 * exist already.
2456:                 */
2457:                private JLabel getOrCreateLabel(SourceInfo info,
2458:                        JMethod enclosingMethod, char[] name) {
2459:                    if (name == null) {
2460:                        return null;
2461:                    }
2462:                    String sname = String.valueOf(name);
2463:                    Map<String, JLabel> lblMap = this .labelMap
2464:                            .get(enclosingMethod);
2465:                    if (lblMap == null) {
2466:                        lblMap = new HashMap<String, JLabel>();
2467:                        this .labelMap.put(enclosingMethod, lblMap);
2468:                    }
2469:                    JLabel jlabel = lblMap.get(sname);
2470:                    if (jlabel == null) {
2471:                        jlabel = new JLabel(program, info, sname);
2472:                        lblMap.put(sname, jlabel);
2473:                    }
2474:                    return jlabel;
2475:                }
2476:
2477:                private JPrimitiveType getPrimitiveTypeForWrapperType(
2478:                        JClassType wrapperType) {
2479:                    String wrapperTypeName = wrapperType.getName();
2480:                    if ("java.lang.Integer".equals(wrapperTypeName)) {
2481:                        return program.getTypePrimitiveInt();
2482:                    } else if ("java.lang.Boolean".equals(wrapperTypeName)) {
2483:                        return program.getTypePrimitiveBoolean();
2484:                    } else if ("java.lang.Character".equals(wrapperTypeName)) {
2485:                        return program.getTypePrimitiveChar();
2486:                    } else if ("java.lang.Long".equals(wrapperTypeName)) {
2487:                        return program.getTypePrimitiveLong();
2488:                    } else if ("java.lang.Short".equals(wrapperTypeName)) {
2489:                        return program.getTypePrimitiveShort();
2490:                    } else if ("java.lang.Byte".equals(wrapperTypeName)) {
2491:                        return program.getTypePrimitiveByte();
2492:                    } else if ("java.lang.Double".equals(wrapperTypeName)) {
2493:                        return program.getTypePrimitiveDouble();
2494:                    } else if ("java.lang.Float".equals(wrapperTypeName)) {
2495:                        return program.getTypePrimitiveFloat();
2496:                    } else {
2497:                        return null;
2498:                    }
2499:                }
2500:
2501:                private SourceInfo makeSourceInfo(Statement x) {
2502:                    int startLine = ProblemHandler.searchLineNumber(
2503:                            currentSeparatorPositions, x.sourceStart);
2504:                    return new SourceInfo(x.sourceStart, x.sourceEnd,
2505:                            startLine, currentFileName);
2506:                }
2507:
2508:                /**
2509:                 * Sometimes a variable reference can be to a local or parameter in an an
2510:                 * enclosing method. This is a tricky situation to detect. There's no
2511:                 * obvious way to tell, but the clue we can get from JDT is that the local's
2512:                 * containing method won't be the same as the method we're currently
2513:                 * processing.
2514:                 * 
2515:                 * Once we have this clue, we can use getEmulationPath to compute the
2516:                 * current class's binding for that field.
2517:                 */
2518:                private JVariable possiblyReferenceOuterLocal(
2519:                        JVariable variable, Binding binding) {
2520:
2521:                    if (variable instanceof  JLocal
2522:                            || variable instanceof  JParameter) {
2523:                        LocalVariableBinding localBinding = (LocalVariableBinding) binding;
2524:                        if (localBinding.declaringScope.methodScope() != currentMethodScope) {
2525:                            variable = null;
2526:                            VariableBinding[] vars = currentMethodScope
2527:                                    .getEmulationPath(localBinding);
2528:                            if (vars == null) {
2529:                                return null;
2530:                            }
2531:                            assert (vars.length == 1);
2532:                            VariableBinding varBinding = vars[0];
2533:
2534:                            // See if there's an available parameter
2535:                            if (varBinding instanceof  SyntheticArgumentBinding) {
2536:                                JType type = (JType) typeMap
2537:                                        .get(varBinding.type);
2538:                                String name = String.valueOf(varBinding.name);
2539:                                for (int i = 0; i < currentMethod.params.size(); ++i) {
2540:                                    JParameter param = currentMethod.params
2541:                                            .get(i);
2542:                                    if (type == param.getType()
2543:                                            && name.equals(param.getName())) {
2544:                                        variable = param;
2545:                                        break;
2546:                                    }
2547:                                }
2548:                            }
2549:
2550:                            // just use the field
2551:                            if (variable == null) {
2552:                                variable = (JField) typeMap.get(varBinding);
2553:                            }
2554:
2555:                            // now we have an updated variable that we can create our ref from
2556:                        }
2557:                    }
2558:                    return variable;
2559:                }
2560:
2561:                /**
2562:                 * Helper for creating all JBinaryOperation. Several different JDT nodes can
2563:                 * result in binary operations: AND_AND_Expression, Assignment,
2564:                 * BinaryExpresion, CompoundAssignment, EqualExpression, and
2565:                 * OR_OR_Expression. Hopefully the specific operators that can result in
2566:                 * each different JDT type won't change between releases, because we only
2567:                 * look for the specific operators that we think should match each JDT node,
2568:                 * and throw an error if there's a mismatch.
2569:                 */
2570:                private JExpression processBinaryOperation(SourceInfo info,
2571:                        JBinaryOperator op, JType type, Expression arg1,
2572:                        Expression arg2) {
2573:                    JExpression exprArg1 = dispProcessExpression(arg1);
2574:                    JExpression exprArg2 = dispProcessExpression(arg2);
2575:                    JBinaryOperation binaryOperation = new JBinaryOperation(
2576:                            program, info, type, op, exprArg1, exprArg2);
2577:                    return binaryOperation;
2578:                }
2579:
2580:                private JExpression processQualifiedThisOrSuperRef(
2581:                        QualifiedThisReference x, JClassType qualType) {
2582:                    /*
2583:                     * WEIRD: If a thisref or superref is qualified with the EXACT type of the
2584:                     * innermost type (in other words, a needless qualifier), it must refer to
2585:                     * that innermost type, because a class can never be nested inside of
2586:                     * itself. In this case, we must treat it as if it were not qualified.
2587:                     * 
2588:                     * In all other cases, the qualified thisref or superref cannot possibly
2589:                     * refer to the innermost type (even if the innermost type could be cast
2590:                     * to a compatible type), so we must create a reference to some outer
2591:                     * type.
2592:                     */
2593:                    SourceInfo info = makeSourceInfo(x);
2594:                    if (qualType == currentClass) {
2595:                        return createThisRef(info, qualType);
2596:                    } else {
2597:                        return createQualifiedThisRef(info, qualType);
2598:                    }
2599:                }
2600:
2601:                private InternalCompilerException translateException(
2602:                        Object node, Throwable e) {
2603:                    InternalCompilerException ice;
2604:                    if (e instanceof  InternalCompilerException) {
2605:                        ice = (InternalCompilerException) e;
2606:                    } else {
2607:                        ice = new InternalCompilerException(
2608:                                "Error constructing Java AST", e);
2609:                    }
2610:                    String className = node.getClass().getName();
2611:                    String description = node.toString();
2612:                    SourceInfo sourceInfo = null;
2613:                    if (node instanceof  Statement) {
2614:                        sourceInfo = makeSourceInfo((Statement) node);
2615:                    }
2616:                    ice.addNode(className, description, sourceInfo);
2617:                    return ice;
2618:                }
2619:
2620:                /**
2621:                 * For a given method, try to find all methods that it overrides/implements.
2622:                 * An experimental version that doesn't use JDT. Right now it's only used to
2623:                 * resolve upRefs for Object.getClass(), which is synthetic on everything
2624:                 * other than object.
2625:                 */
2626:                private void tryFindUpRefs(JMethod method) {
2627:                    if (method.getEnclosingType() != null) {
2628:                        tryFindUpRefsRecursive(method, method
2629:                                .getEnclosingType());
2630:                    }
2631:                }
2632:
2633:                /**
2634:                 * For a given method(and method binding), try to find all methods that it
2635:                 * overrides/implements.
2636:                 */
2637:                private void tryFindUpRefs(JMethod method, MethodBinding binding) {
2638:                    tryFindUpRefsRecursive(method, binding,
2639:                            binding.declaringClass);
2640:                }
2641:
2642:                /**
2643:                 * For a given method(and method binding), recursively try to find all
2644:                 * methods that it overrides/implements.
2645:                 */
2646:                private void tryFindUpRefsRecursive(JMethod method,
2647:                        JReferenceType searchThisType) {
2648:
2649:                    // See if this class has any uprefs, unless this class is myself
2650:                    if (method.getEnclosingType() != searchThisType) {
2651:                        outer: for (JMethod upRef : searchThisType.methods) {
2652:                            if (upRef.isStatic()) {
2653:                                continue;
2654:                            }
2655:                            if (!upRef.getName().equals(method.getName())) {
2656:                                continue;
2657:                            }
2658:                            if (upRef.params.size() != method.params.size()) {
2659:                                continue;
2660:                            }
2661:                            for (int i = 0, c = upRef.params.size(); i < c; ++i) {
2662:                                if (upRef.params.get(i).getType() != method.params
2663:                                        .get(i).getType()) {
2664:                                    continue outer;
2665:                                }
2666:                            }
2667:
2668:                            if (!method.overrides.contains(upRef)) {
2669:                                method.overrides.add(upRef);
2670:                                break;
2671:                            }
2672:                        }
2673:                    }
2674:
2675:                    // recurse super class
2676:                    if (searchThisType.extnds != null) {
2677:                        tryFindUpRefsRecursive(method, searchThisType.extnds);
2678:                    }
2679:
2680:                    // recurse super interfaces
2681:                    for (JInterfaceType intf : searchThisType.implments) {
2682:                        tryFindUpRefsRecursive(method, intf);
2683:                    }
2684:                }
2685:
2686:                /**
2687:                 * For a given method(and method binding), recursively try to find all
2688:                 * methods that it overrides/implements.
2689:                 */
2690:                private void tryFindUpRefsRecursive(JMethod method,
2691:                        MethodBinding binding, ReferenceBinding searchThisType) {
2692:
2693:                    // See if this class has any uprefs, unless this class is myself
2694:                    if (binding.declaringClass != searchThisType) {
2695:                        for (MethodBinding tryMethod : searchThisType
2696:                                .getMethods(binding.selector)) {
2697:                            if (binding.areParameterErasuresEqual(tryMethod)) {
2698:                                JMethod upRef = (JMethod) typeMap
2699:                                        .get(tryMethod);
2700:                                if (!method.overrides.contains(upRef)) {
2701:                                    method.overrides.add(upRef);
2702:                                    break;
2703:                                }
2704:                            }
2705:                        }
2706:                    }
2707:
2708:                    // recurse super class
2709:                    if (searchThisType.super class() != null) {
2710:                        tryFindUpRefsRecursive(method, binding, searchThisType
2711:                                .super class());
2712:                    }
2713:
2714:                    // recurse super interfaces
2715:                    if (searchThisType.super Interfaces() != null) {
2716:                        for (int i = 0; i < searchThisType.super Interfaces().length; i++) {
2717:                            ReferenceBinding intf = searchThisType
2718:                                    .super Interfaces()[i];
2719:                            tryFindUpRefsRecursive(method, binding, intf);
2720:                        }
2721:                    }
2722:                }
2723:
2724:                private JExpression unbox(JExpression toUnbox,
2725:                        JClassType wrapperType) {
2726:                    JPrimitiveType primitiveType = getPrimitiveTypeForWrapperType(wrapperType);
2727:                    if (primitiveType == null) {
2728:                        throw new InternalCompilerException(toUnbox,
2729:                                "Attempt to unbox unexpected type '"
2730:                                        + wrapperType.getName() + "'", null);
2731:                    }
2732:
2733:                    String valueMethodName = primitiveType.getName() + "Value";
2734:                    JMethod valueMethod = null;
2735:                    for (Object element : wrapperType.methods) {
2736:                        JMethod method = (JMethod) element;
2737:                        if (method.getName().equals(valueMethodName)) {
2738:                            if (method.params.isEmpty()) {
2739:                                // It's a match!
2740:                                valueMethod = method;
2741:                                break;
2742:                            }
2743:                        }
2744:                    }
2745:
2746:                    if (valueMethod == null) {
2747:                        throw new InternalCompilerException(toUnbox,
2748:                                "Expected to find a method on '"
2749:                                        + wrapperType.getName()
2750:                                        + "' whose signature matches 'public "
2751:                                        + primitiveType.getName() + " "
2752:                                        + valueMethodName + "()'", null);
2753:                    }
2754:
2755:                    JMethodCall unboxCall = new JMethodCall(program, toUnbox
2756:                            .getSourceInfo(), toUnbox, valueMethod);
2757:                    return unboxCall;
2758:                }
2759:
2760:                private JExpression unbox(JExpression toUnbox,
2761:                        JPrimitiveType primitiveType) {
2762:                    String wrapperTypeName = primitiveType.getWrapperTypeName();
2763:                    JClassType wrapperType = (JClassType) program
2764:                            .getFromTypeMap(wrapperTypeName);
2765:                    if (wrapperType == null) {
2766:                        throw new InternalCompilerException(toUnbox,
2767:                                "Cannot find wrapper type '" + wrapperTypeName
2768:                                        + "' associated with primitive type '"
2769:                                        + primitiveType.getName() + "'", null);
2770:                    }
2771:                    return unbox(toUnbox, wrapperType);
2772:                }
2773:
2774:                private void writeEnumValueOfMethod(JEnumType type,
2775:                        JField mapField) {
2776:                    // return Enum.valueOf(map, name);
2777:                    JFieldRef mapRef = new JFieldRef(program, null, null,
2778:                            mapField, type);
2779:                    JVariableRef nameRef = createVariableRef(null,
2780:                            currentMethod.params.get(0));
2781:                    JMethod delegateTo = program
2782:                            .getIndexedMethod("Enum.valueOf");
2783:                    JMethodCall call = new JMethodCall(program, null, null,
2784:                            delegateTo);
2785:                    call.getArgs().add(mapRef);
2786:                    call.getArgs().add(nameRef);
2787:                    currentMethodBody.getStatements().add(
2788:                            new JReturnStatement(program, null, call));
2789:                }
2790:
2791:                private void writeEnumValuesMethod(JEnumType type) {
2792:                    // return new E[]{A,B,C};
2793:                    JNewArray newExpr = new JNewArray(program, null, program
2794:                            .getTypeArray(type, 1));
2795:                    newExpr.initializers = new ArrayList<JExpression>();
2796:                    for (JEnumField field : type.enumList) {
2797:                        JFieldRef fieldRef = new JFieldRef(program, null, null,
2798:                                field, type);
2799:                        newExpr.initializers.add(fieldRef);
2800:                    }
2801:                    currentMethodBody.getStatements().add(
2802:                            new JReturnStatement(program, null, newExpr));
2803:                }
2804:            }
2805:
2806:            /**
2807:             * Combines the information from the JDT type nodes and the type map to create
2808:             * a JProgram structure.
2809:             */
2810:            public static void exec(TypeDeclaration[] types, TypeMap typeMap,
2811:                    JProgram jprogram, JsProgram jsProgram) {
2812:                JavaASTGenerationVisitor v = new JavaASTGenerationVisitor(
2813:                        typeMap, jprogram, jsProgram);
2814:                for (int i = 0; i < types.length; ++i) {
2815:                    v.processType(types[i]);
2816:                }
2817:                Collections
2818:                        .sort(jprogram.getDeclaredTypes(), new HasNameSort());
2819:            }
2820:
2821:            public static void reportJsniError(SourceInfo info,
2822:                    AbstractMethodDeclaration methodDeclaration, String message) {
2823:                CompilationResult compResult = methodDeclaration
2824:                        .compilationResult();
2825:                DefaultProblem problem = new DefaultProblem(info.getFileName()
2826:                        .toCharArray(), message, IProblem.Unclassified, null,
2827:                        ProblemSeverities.Error, info.getStartPos(), info
2828:                                .getEndPos(), info.getStartLine());
2829:                compResult.record(problem, methodDeclaration);
2830:            }
2831:
2832:            public static SourceInfo translateInfo(JsSourceInfo info) {
2833:                // TODO implement this
2834:                return null;
2835:            }
2836:
2837:            /**
2838:             * Gets a JParameter iterator for a constructor method over its synthetic
2839:             * parameters.
2840:             */
2841:            private static Iterator<JParameter> getSyntheticsIterator(
2842:                    JMethod method) {
2843:                Iterator<JParameter> it = method.params.iterator();
2844:                for (int i = 0, c = method.getOriginalParamTypes().size(); i < c; ++i) {
2845:                    it.next();
2846:                }
2847:                return it;
2848:            }
2849:
2850:            /**
2851:             * Returns <code>true</code> if JDT optimized the condition to
2852:             * <code>false</code>.
2853:             */
2854:            private static boolean isOptimizedFalse(Expression condition) {
2855:                if (condition != null) {
2856:                    Constant cst = condition.optimizedBooleanConstant();
2857:                    if (cst != Constant.NotAConstant) {
2858:                        if (cst.booleanValue() == false) {
2859:                            return true;
2860:                        }
2861:                    }
2862:                }
2863:                return false;
2864:            }
2865:
2866:            /**
2867:             * Returns <code>true</code> if JDT optimized the condition to
2868:             * <code>true</code>.
2869:             */
2870:            private static boolean isOptimizedTrue(Expression condition) {
2871:                if (condition != null) {
2872:                    Constant cst = condition.optimizedBooleanConstant();
2873:                    if (cst != Constant.NotAConstant) {
2874:                        if (cst.booleanValue() == true) {
2875:                            return true;
2876:                        }
2877:                    }
2878:                }
2879:                return false;
2880:            }
2881:
2882:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.