Source Code Cross Referenced for JsToStringGenerationVisitor.java in  » Ajax » GWT » com » google » gwt » dev » js » 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.js 
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.js;
0017:
0018:        import com.google.gwt.dev.js.ast.HasName;
0019:        import com.google.gwt.dev.js.ast.JsArrayAccess;
0020:        import com.google.gwt.dev.js.ast.JsArrayLiteral;
0021:        import com.google.gwt.dev.js.ast.JsBinaryOperation;
0022:        import com.google.gwt.dev.js.ast.JsBinaryOperator;
0023:        import com.google.gwt.dev.js.ast.JsBlock;
0024:        import com.google.gwt.dev.js.ast.JsBooleanLiteral;
0025:        import com.google.gwt.dev.js.ast.JsBreak;
0026:        import com.google.gwt.dev.js.ast.JsCase;
0027:        import com.google.gwt.dev.js.ast.JsCatch;
0028:        import com.google.gwt.dev.js.ast.JsConditional;
0029:        import com.google.gwt.dev.js.ast.JsContext;
0030:        import com.google.gwt.dev.js.ast.JsContinue;
0031:        import com.google.gwt.dev.js.ast.JsDebugger;
0032:        import com.google.gwt.dev.js.ast.JsDecimalLiteral;
0033:        import com.google.gwt.dev.js.ast.JsDefault;
0034:        import com.google.gwt.dev.js.ast.JsDoWhile;
0035:        import com.google.gwt.dev.js.ast.JsEmpty;
0036:        import com.google.gwt.dev.js.ast.JsExprStmt;
0037:        import com.google.gwt.dev.js.ast.JsExpression;
0038:        import com.google.gwt.dev.js.ast.JsFor;
0039:        import com.google.gwt.dev.js.ast.JsForIn;
0040:        import com.google.gwt.dev.js.ast.JsFunction;
0041:        import com.google.gwt.dev.js.ast.JsIf;
0042:        import com.google.gwt.dev.js.ast.JsIntegralLiteral;
0043:        import com.google.gwt.dev.js.ast.JsInvocation;
0044:        import com.google.gwt.dev.js.ast.JsLabel;
0045:        import com.google.gwt.dev.js.ast.JsName;
0046:        import com.google.gwt.dev.js.ast.JsNameRef;
0047:        import com.google.gwt.dev.js.ast.JsNew;
0048:        import com.google.gwt.dev.js.ast.JsNullLiteral;
0049:        import com.google.gwt.dev.js.ast.JsObjectLiteral;
0050:        import com.google.gwt.dev.js.ast.JsOperator;
0051:        import com.google.gwt.dev.js.ast.JsParameter;
0052:        import com.google.gwt.dev.js.ast.JsPostfixOperation;
0053:        import com.google.gwt.dev.js.ast.JsPrefixOperation;
0054:        import com.google.gwt.dev.js.ast.JsProgram;
0055:        import com.google.gwt.dev.js.ast.JsPropertyInitializer;
0056:        import com.google.gwt.dev.js.ast.JsRegExp;
0057:        import com.google.gwt.dev.js.ast.JsReturn;
0058:        import com.google.gwt.dev.js.ast.JsStatement;
0059:        import com.google.gwt.dev.js.ast.JsStringLiteral;
0060:        import com.google.gwt.dev.js.ast.JsSwitch;
0061:        import com.google.gwt.dev.js.ast.JsSwitchMember;
0062:        import com.google.gwt.dev.js.ast.JsThisRef;
0063:        import com.google.gwt.dev.js.ast.JsThrow;
0064:        import com.google.gwt.dev.js.ast.JsTry;
0065:        import com.google.gwt.dev.js.ast.JsUnaryOperator;
0066:        import com.google.gwt.dev.js.ast.JsVars;
0067:        import com.google.gwt.dev.js.ast.JsVisitor;
0068:        import com.google.gwt.dev.js.ast.JsWhile;
0069:        import com.google.gwt.dev.js.ast.JsVars.JsVar;
0070:        import com.google.gwt.dev.util.TextOutput;
0071:
0072:        import java.util.Iterator;
0073:        import java.util.regex.Pattern;
0074:
0075:        /**
0076:         * Produces text output from a JavaScript AST.
0077:         */
0078:        public class JsToStringGenerationVisitor extends JsVisitor {
0079:
0080:            private static final char[] CHARS_BREAK = "break".toCharArray();
0081:            private static final char[] CHARS_CASE = "case".toCharArray();
0082:            private static final char[] CHARS_CATCH = "catch".toCharArray();
0083:            private static final char[] CHARS_CONTINUE = "continue"
0084:                    .toCharArray();
0085:            private static final char[] CHARS_DEBUGGER = "debugger"
0086:                    .toCharArray();
0087:            private static final char[] CHARS_DEFAULT = "default".toCharArray();
0088:            private static final char[] CHARS_DO = "do".toCharArray();
0089:            private static final char[] CHARS_ELSE = "else".toCharArray();
0090:            private static final char[] CHARS_FALSE = "false".toCharArray();
0091:            private static final char[] CHARS_FINALLY = "finally".toCharArray();
0092:            private static final char[] CHARS_FOR = "for".toCharArray();
0093:            private static final char[] CHARS_FUNCTION = "function"
0094:                    .toCharArray();
0095:            private static final char[] CHARS_IF = "if".toCharArray();
0096:            private static final char[] CHARS_IN = "in".toCharArray();
0097:            private static final char[] CHARS_NEW = "new".toCharArray();
0098:            private static final char[] CHARS_NULL = "null".toCharArray();
0099:            private static final char[] CHARS_RETURN = "return".toCharArray();
0100:            private static final char[] CHARS_SWITCH = "switch".toCharArray();
0101:            private static final char[] CHARS_THIS = "this".toCharArray();
0102:            private static final char[] CHARS_THROW = "throw".toCharArray();
0103:            private static final char[] CHARS_TRUE = "true".toCharArray();
0104:            private static final char[] CHARS_TRY = "try".toCharArray();
0105:            private static final char[] CHARS_VAR = "var".toCharArray();
0106:            private static final char[] CHARS_WHILE = "while".toCharArray();
0107:            private static final char[] HEX_DIGITS = { '0', '1', '2', '3', '4',
0108:                    '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
0109:
0110:            /**
0111:             * How many lines of code to print inside of a JsBlock when printing terse.
0112:             */
0113:            private static final int JSBLOCK_LINES_TO_PRINT = 3;
0114:
0115:            /**
0116:             * A variable name is valid if it contains only letters, numbers, _, $ and
0117:             * does not begin with a number. There are actually other valid variable
0118:             * names, such as ones that contain escaped Unicode characters, but we
0119:             * surround those names with quotes in property initializers to be safe.
0120:             */
0121:            private static final Pattern VALID_NAME_PATTERN = Pattern
0122:                    .compile("[a-zA-Z_$][\\w$]*");
0123:
0124:            protected boolean needSemi = true;
0125:            private final TextOutput p;
0126:
0127:            public JsToStringGenerationVisitor(TextOutput out) {
0128:                this .p = out;
0129:            }
0130:
0131:            @Override
0132:            public boolean visit(JsArrayAccess x, JsContext<JsExpression> ctx) {
0133:                JsExpression arrayExpr = x.getArrayExpr();
0134:                _parenPush(x, arrayExpr, false);
0135:                accept(arrayExpr);
0136:                _parenPop(x, arrayExpr, false);
0137:                _lsquare();
0138:                accept(x.getIndexExpr());
0139:                _rsquare();
0140:                return false;
0141:            }
0142:
0143:            @Override
0144:            public boolean visit(JsArrayLiteral x, JsContext<JsExpression> ctx) {
0145:                _lsquare();
0146:                boolean sep = false;
0147:                for (Object element : x.getExpressions()) {
0148:                    JsExpression arg = (JsExpression) element;
0149:                    sep = _sepCommaOptSpace(sep);
0150:                    _parenPushIfCommaExpr(arg);
0151:                    accept(arg);
0152:                    _parenPopIfCommaExpr(arg);
0153:                }
0154:                _rsquare();
0155:                return false;
0156:            }
0157:
0158:            @Override
0159:            public boolean visit(JsBinaryOperation x,
0160:                    JsContext<JsExpression> ctx) {
0161:                JsBinaryOperator op = x.getOperator();
0162:                JsExpression arg1 = x.getArg1();
0163:                _parenPush(x, arg1, !op.isLeftAssociative());
0164:                accept(arg1);
0165:                if (op.isKeyword()) {
0166:                    _parenPopOrSpace(x, arg1, !op.isLeftAssociative());
0167:                } else {
0168:                    _parenPop(x, arg1, !op.isLeftAssociative());
0169:                    _spaceOpt();
0170:                }
0171:                p.print(op.getSymbol());
0172:                JsExpression arg2 = x.getArg2();
0173:                if (_spaceCalc(op, arg2)) {
0174:                    _parenPushOrSpace(x, arg2, op.isLeftAssociative());
0175:                } else {
0176:                    _spaceOpt();
0177:                    _parenPush(x, arg2, op.isLeftAssociative());
0178:                }
0179:                accept(arg2);
0180:                _parenPop(x, arg2, op.isLeftAssociative());
0181:                return false;
0182:            }
0183:
0184:            @Override
0185:            public boolean visit(JsBlock x, JsContext<JsStatement> ctx) {
0186:                printJsBlockOptionalTruncate(x, true);
0187:                return false;
0188:            }
0189:
0190:            @Override
0191:            public boolean visit(JsBooleanLiteral x, JsContext<JsExpression> ctx) {
0192:                if (x.getValue()) {
0193:                    _true();
0194:                } else {
0195:                    _false();
0196:                }
0197:                return false;
0198:            }
0199:
0200:            @Override
0201:            public boolean visit(JsBreak x, JsContext<JsStatement> ctx) {
0202:                _break();
0203:
0204:                JsNameRef label = x.getLabel();
0205:                if (label != null) {
0206:                    _space();
0207:                    _nameRef(label);
0208:                }
0209:
0210:                return false;
0211:            }
0212:
0213:            @Override
0214:            public boolean visit(JsCase x, JsContext<JsSwitchMember> ctx) {
0215:                _case();
0216:                _space();
0217:                accept(x.getCaseExpr());
0218:                _colon();
0219:                _newlineOpt();
0220:
0221:                indent();
0222:                for (Object element : x.getStmts()) {
0223:                    JsStatement stmt = (JsStatement) element;
0224:                    needSemi = true;
0225:                    accept(stmt);
0226:                    if (needSemi) {
0227:                        _semi();
0228:                    }
0229:                    _newlineOpt();
0230:                }
0231:                outdent();
0232:                needSemi = false;
0233:                return false;
0234:            }
0235:
0236:            @Override
0237:            public boolean visit(JsCatch x, JsContext<JsCatch> ctx) {
0238:                _spaceOpt();
0239:                _catch();
0240:                _spaceOpt();
0241:                _lparen();
0242:                _nameDef(x.getParameter().getName());
0243:
0244:                // Optional catch condition.
0245:                //
0246:                JsExpression catchCond = x.getCondition();
0247:                if (catchCond != null) {
0248:                    _space();
0249:                    _if();
0250:                    _space();
0251:                    accept(catchCond);
0252:                }
0253:
0254:                _rparen();
0255:                _spaceOpt();
0256:                accept(x.getBody());
0257:
0258:                return false;
0259:            }
0260:
0261:            @Override
0262:            public boolean visit(JsConditional x, JsContext<JsExpression> ctx) {
0263:                // right associative
0264:                {
0265:                    JsExpression testExpression = x.getTestExpression();
0266:                    _parenPush(x, testExpression, false);
0267:                    accept(testExpression);
0268:                    _parenPop(x, testExpression, false);
0269:                }
0270:                _questionMark();
0271:                {
0272:                    JsExpression thenExpression = x.getThenExpression();
0273:                    _parenPush(x, thenExpression, false);
0274:                    accept(thenExpression);
0275:                    _parenPop(x, thenExpression, false);
0276:                }
0277:                _colon();
0278:                {
0279:                    JsExpression elseExpression = x.getElseExpression();
0280:                    _parenPush(x, elseExpression, false);
0281:                    accept(elseExpression);
0282:                    _parenPop(x, elseExpression, false);
0283:                }
0284:                return false;
0285:            }
0286:
0287:            @Override
0288:            public boolean visit(JsContinue x, JsContext<JsStatement> ctx) {
0289:                _continue();
0290:
0291:                JsNameRef label = x.getLabel();
0292:                if (label != null) {
0293:                    _space();
0294:                    _nameRef(label);
0295:                }
0296:
0297:                return false;
0298:            }
0299:
0300:            @Override
0301:            public boolean visit(JsDebugger x, JsContext<JsStatement> ctx) {
0302:                _debugger();
0303:                return false;
0304:            }
0305:
0306:            @Override
0307:            public boolean visit(JsDecimalLiteral x, JsContext<JsExpression> ctx) {
0308:                String s = x.getValue();
0309:                // TODO: optimize this to only the cases that need it
0310:                if (s.startsWith("-")) {
0311:                    _space();
0312:                }
0313:                p.print(s);
0314:                return false;
0315:            }
0316:
0317:            @Override
0318:            public boolean visit(JsDefault x, JsContext<JsSwitchMember> ctx) {
0319:                _default();
0320:                _colon();
0321:
0322:                indent();
0323:                for (Object element : x.getStmts()) {
0324:                    JsStatement stmt = (JsStatement) element;
0325:                    needSemi = true;
0326:                    accept(stmt);
0327:                    if (needSemi) {
0328:                        _semi();
0329:                    }
0330:                    _newlineOpt();
0331:                }
0332:                outdent();
0333:                needSemi = false;
0334:                return false;
0335:            }
0336:
0337:            @Override
0338:            public boolean visit(JsDoWhile x, JsContext<JsStatement> ctx) {
0339:                _do();
0340:                _nestedPush(x.getBody(), true);
0341:                accept(x.getBody());
0342:                _nestedPop(x.getBody());
0343:                if (needSemi) {
0344:                    _semi();
0345:                    _newlineOpt();
0346:                } else {
0347:                    _spaceOpt();
0348:                    needSemi = true;
0349:                }
0350:                _while();
0351:                _spaceOpt();
0352:                _lparen();
0353:                accept(x.getCondition());
0354:                _rparen();
0355:                return false;
0356:            }
0357:
0358:            @Override
0359:            public boolean visit(JsEmpty x, JsContext<JsStatement> ctx) {
0360:                return false;
0361:            }
0362:
0363:            @Override
0364:            public boolean visit(JsExprStmt x, JsContext<JsStatement> ctx) {
0365:                boolean surroundWithParentheses = JsFirstExpressionVisitor
0366:                        .exec(x);
0367:                if (surroundWithParentheses) {
0368:                    _lparen();
0369:                }
0370:                JsExpression expr = x.getExpression();
0371:                accept(expr);
0372:                if (surroundWithParentheses) {
0373:                    _rparen();
0374:                }
0375:                return false;
0376:            }
0377:
0378:            @Override
0379:            public boolean visit(JsFor x, JsContext<JsStatement> ctx) {
0380:                _for();
0381:                _spaceOpt();
0382:                _lparen();
0383:
0384:                // The init expressions or var decl.
0385:                //
0386:                if (x.getInitExpr() != null) {
0387:                    accept(x.getInitExpr());
0388:                } else if (x.getInitVars() != null) {
0389:                    accept(x.getInitVars());
0390:                }
0391:
0392:                _semi();
0393:
0394:                // The loop test.
0395:                //
0396:                if (x.getCondition() != null) {
0397:                    _spaceOpt();
0398:                    accept(x.getCondition());
0399:                }
0400:
0401:                _semi();
0402:
0403:                // The incr expression.
0404:                //
0405:                if (x.getIncrExpr() != null) {
0406:                    _spaceOpt();
0407:                    accept(x.getIncrExpr());
0408:                }
0409:
0410:                _rparen();
0411:                _nestedPush(x.getBody(), false);
0412:                accept(x.getBody());
0413:                _nestedPop(x.getBody());
0414:                return false;
0415:            }
0416:
0417:            @Override
0418:            public boolean visit(JsForIn x, JsContext<JsStatement> ctx) {
0419:                _for();
0420:                _spaceOpt();
0421:                _lparen();
0422:
0423:                if (x.getIterVarName() != null) {
0424:                    _var();
0425:                    _space();
0426:                    _nameDef(x.getIterVarName());
0427:
0428:                    if (x.getIterExpr() != null) {
0429:                        _spaceOpt();
0430:                        _assignment();
0431:                        _spaceOpt();
0432:                        accept(x.getIterExpr());
0433:                    }
0434:                } else {
0435:                    // Just a name ref.
0436:                    //
0437:                    accept(x.getIterExpr());
0438:                }
0439:
0440:                _space();
0441:                _in();
0442:                _space();
0443:                accept(x.getObjExpr());
0444:
0445:                _rparen();
0446:                _nestedPush(x.getBody(), false);
0447:                accept(x.getBody());
0448:                _nestedPop(x.getBody());
0449:                return false;
0450:            }
0451:
0452:            // function foo(a, b) {
0453:            // stmts...
0454:            // }
0455:            //
0456:            @Override
0457:            public boolean visit(JsFunction x, JsContext<JsExpression> ctx) {
0458:                _function();
0459:
0460:                // Functions can be anonymous.
0461:                //
0462:                if (x.getName() != null) {
0463:                    _space();
0464:                    _nameOf(x);
0465:                }
0466:
0467:                _lparen();
0468:                boolean sep = false;
0469:                for (Object element : x.getParameters()) {
0470:                    JsParameter param = (JsParameter) element;
0471:                    sep = _sepCommaOptSpace(sep);
0472:                    accept(param);
0473:                }
0474:                _rparen();
0475:
0476:                accept(x.getBody());
0477:                needSemi = true;
0478:                return false;
0479:            }
0480:
0481:            @Override
0482:            public boolean visit(JsIf x, JsContext<JsStatement> ctx) {
0483:                _if();
0484:                _spaceOpt();
0485:                _lparen();
0486:                accept(x.getIfExpr());
0487:                _rparen();
0488:                JsStatement thenStmt = x.getThenStmt();
0489:                _nestedPush(thenStmt, false);
0490:                accept(thenStmt);
0491:                _nestedPop(thenStmt);
0492:                JsStatement elseStmt = x.getElseStmt();
0493:                if (elseStmt != null) {
0494:                    if (needSemi) {
0495:                        _semi();
0496:                        _newlineOpt();
0497:                    } else {
0498:                        _spaceOpt();
0499:                        needSemi = true;
0500:                    }
0501:                    _else();
0502:                    boolean elseIf = elseStmt instanceof  JsIf;
0503:                    if (!elseIf) {
0504:                        _nestedPush(elseStmt, true);
0505:                    } else {
0506:                        _space();
0507:                    }
0508:                    accept(elseStmt);
0509:                    if (!elseIf) {
0510:                        _nestedPop(elseStmt);
0511:                    }
0512:                }
0513:                return false;
0514:            }
0515:
0516:            @Override
0517:            public boolean visit(JsIntegralLiteral x,
0518:                    JsContext<JsExpression> ctx) {
0519:                String s = x.getValue().toString();
0520:                boolean needParens = s.startsWith("-");
0521:                if (needParens) {
0522:                    _lparen();
0523:                }
0524:                p.print(s);
0525:                if (needParens) {
0526:                    _rparen();
0527:                }
0528:                return false;
0529:            }
0530:
0531:            @Override
0532:            public boolean visit(JsInvocation x, JsContext<JsExpression> ctx) {
0533:                accept(x.getQualifier());
0534:
0535:                _lparen();
0536:                boolean sep = false;
0537:                for (Object element : x.getArguments()) {
0538:                    JsExpression arg = (JsExpression) element;
0539:                    sep = _sepCommaOptSpace(sep);
0540:                    _parenPushIfCommaExpr(arg);
0541:                    accept(arg);
0542:                    _parenPopIfCommaExpr(arg);
0543:                }
0544:                _rparen();
0545:                return false;
0546:            }
0547:
0548:            @Override
0549:            public boolean visit(JsLabel x, JsContext<JsStatement> ctx) {
0550:                _nameOf(x);
0551:                _colon();
0552:                _spaceOpt();
0553:                accept(x.getStmt());
0554:                return false;
0555:            }
0556:
0557:            @Override
0558:            public boolean visit(JsNameRef x, JsContext<JsExpression> ctx) {
0559:                JsExpression q = x.getQualifier();
0560:                if (q != null) {
0561:                    _parenPush(x, q, false);
0562:                    accept(q);
0563:                    _parenPop(x, q, false);
0564:                    _dot();
0565:                }
0566:                _nameRef(x);
0567:                return false;
0568:            }
0569:
0570:            @Override
0571:            public boolean visit(JsNew x, JsContext<JsExpression> ctx) {
0572:                _new();
0573:                _space();
0574:
0575:                JsExpression ctorExpr = x.getConstructorExpression();
0576:                boolean needsParens = JsConstructExpressionVisitor
0577:                        .exec(ctorExpr);
0578:                if (needsParens) {
0579:                    _lparen();
0580:                }
0581:                accept(ctorExpr);
0582:                if (needsParens) {
0583:                    _rparen();
0584:                }
0585:
0586:                _lparen();
0587:                boolean sep = false;
0588:                for (Object element : x.getArguments()) {
0589:                    JsExpression arg = (JsExpression) element;
0590:                    sep = _sepCommaOptSpace(sep);
0591:                    _parenPushIfCommaExpr(arg);
0592:                    accept(arg);
0593:                    _parenPopIfCommaExpr(arg);
0594:                }
0595:                _rparen();
0596:
0597:                return false;
0598:            }
0599:
0600:            @Override
0601:            public boolean visit(JsNullLiteral x, JsContext<JsExpression> ctx) {
0602:                _null();
0603:                return false;
0604:            }
0605:
0606:            @Override
0607:            public boolean visit(JsObjectLiteral x, JsContext<JsExpression> ctx) {
0608:                _lbrace();
0609:                boolean sep = false;
0610:                for (Object element : x.getPropertyInitializers()) {
0611:                    sep = _sepCommaOptSpace(sep);
0612:                    JsPropertyInitializer propInit = (JsPropertyInitializer) element;
0613:                    printLabel: {
0614:                        JsExpression labelExpr = propInit.getLabelExpr();
0615:                        // labels can be either string, integral, or decimal literals
0616:                        if (labelExpr instanceof  JsStringLiteral) {
0617:                            String propName = ((JsStringLiteral) labelExpr)
0618:                                    .getValue();
0619:                            if (VALID_NAME_PATTERN.matcher(propName).matches()
0620:                                    && !JsKeywords.isKeyword(propName)) {
0621:                                p.print(propName);
0622:                                break printLabel;
0623:                            }
0624:                        }
0625:                        accept(labelExpr);
0626:                    }
0627:                    _colon();
0628:                    JsExpression valueExpr = propInit.getValueExpr();
0629:                    _parenPushIfCommaExpr(valueExpr);
0630:                    accept(valueExpr);
0631:                    _parenPopIfCommaExpr(valueExpr);
0632:                }
0633:                _rbrace();
0634:                return false;
0635:            }
0636:
0637:            @Override
0638:            public boolean visit(JsParameter x, JsContext<JsParameter> ctx) {
0639:                _nameOf(x);
0640:                return false;
0641:            }
0642:
0643:            @Override
0644:            public boolean visit(JsPostfixOperation x,
0645:                    JsContext<JsExpression> ctx) {
0646:                JsUnaryOperator op = x.getOperator();
0647:                JsExpression arg = x.getArg();
0648:                // unary operators always associate correctly (I think)
0649:                _parenPush(x, arg, false);
0650:                accept(arg);
0651:                _parenPop(x, arg, false);
0652:                p.print(op.getSymbol());
0653:                return false;
0654:            }
0655:
0656:            @Override
0657:            public boolean visit(JsPrefixOperation x,
0658:                    JsContext<JsExpression> ctx) {
0659:                JsUnaryOperator op = x.getOperator();
0660:                p.print(op.getSymbol());
0661:                JsExpression arg = x.getArg();
0662:                if (_spaceCalc(op, arg)) {
0663:                    _space();
0664:                }
0665:                // unary operators always associate correctly (I think)
0666:                _parenPush(x, arg, false);
0667:                accept(arg);
0668:                _parenPop(x, arg, false);
0669:                return false;
0670:            }
0671:
0672:            @Override
0673:            public boolean visit(JsProgram x, JsContext<JsProgram> ctx) {
0674:                p.print("<JsProgram>");
0675:                return false;
0676:            }
0677:
0678:            @Override
0679:            public boolean visit(JsPropertyInitializer x,
0680:                    JsContext<JsPropertyInitializer> ctx) {
0681:                // Since there are separators, we actually print the property init
0682:                // in visit(JsObjectLiteral).
0683:                //
0684:                return false;
0685:            }
0686:
0687:            @Override
0688:            public boolean visit(JsRegExp x, JsContext<JsExpression> ctx) {
0689:                _slash();
0690:                p.print(x.getPattern());
0691:                _slash();
0692:                String flags = x.getFlags();
0693:                if (flags != null) {
0694:                    p.print(flags);
0695:                }
0696:                return false;
0697:            }
0698:
0699:            @Override
0700:            public boolean visit(JsReturn x, JsContext<JsStatement> ctx) {
0701:                _return();
0702:                JsExpression expr = x.getExpr();
0703:                if (expr != null) {
0704:                    _space();
0705:                    accept(expr);
0706:                }
0707:                return false;
0708:            }
0709:
0710:            @Override
0711:            public boolean visit(JsStringLiteral x, JsContext<JsExpression> ctx) {
0712:                printStringLiteral(x.getValue());
0713:                return false;
0714:            }
0715:
0716:            @Override
0717:            public boolean visit(JsSwitch x, JsContext<JsStatement> ctx) {
0718:                _switch();
0719:                _spaceOpt();
0720:                _lparen();
0721:                accept(x.getExpr());
0722:                _rparen();
0723:                _spaceOpt();
0724:                _blockOpen();
0725:                acceptList(x.getCases());
0726:                _blockClose();
0727:                return false;
0728:            }
0729:
0730:            @Override
0731:            public boolean visit(JsThisRef x, JsContext<JsExpression> ctx) {
0732:                _this ();
0733:                return false;
0734:            }
0735:
0736:            @Override
0737:            public boolean visit(JsThrow x, JsContext<JsStatement> ctx) {
0738:                _throw();
0739:                _space();
0740:                accept(x.getExpr());
0741:                return false;
0742:            }
0743:
0744:            @Override
0745:            public boolean visit(JsTry x, JsContext<JsStatement> ctx) {
0746:                _try();
0747:                _spaceOpt();
0748:                accept(x.getTryBlock());
0749:
0750:                acceptList(x.getCatches());
0751:
0752:                JsBlock finallyBlock = x.getFinallyBlock();
0753:                if (finallyBlock != null) {
0754:                    _spaceOpt();
0755:                    _finally();
0756:                    _spaceOpt();
0757:                    accept(finallyBlock);
0758:                }
0759:
0760:                return false;
0761:            }
0762:
0763:            @Override
0764:            public boolean visit(JsVar x, JsContext<JsVar> ctx) {
0765:                _nameOf(x);
0766:                JsExpression initExpr = x.getInitExpr();
0767:                if (initExpr != null) {
0768:                    _spaceOpt();
0769:                    _assignment();
0770:                    _spaceOpt();
0771:                    _parenPushIfCommaExpr(initExpr);
0772:                    accept(initExpr);
0773:                    _parenPopIfCommaExpr(initExpr);
0774:                }
0775:                return false;
0776:            }
0777:
0778:            @Override
0779:            public boolean visit(JsVars x, JsContext<JsStatement> ctx) {
0780:                _var();
0781:                _space();
0782:                boolean sep = false;
0783:                for (JsVar var : x) {
0784:                    sep = _sepCommaOptSpace(sep);
0785:                    accept(var);
0786:                }
0787:                return false;
0788:            }
0789:
0790:            @Override
0791:            public boolean visit(JsWhile x, JsContext<JsStatement> ctx) {
0792:                _while();
0793:                _spaceOpt();
0794:                _lparen();
0795:                accept(x.getCondition());
0796:                _rparen();
0797:                _nestedPush(x.getBody(), false);
0798:                accept(x.getBody());
0799:                _nestedPop(x.getBody());
0800:                return false;
0801:            }
0802:
0803:            // CHECKSTYLE_NAMING_OFF
0804:            protected void _newline() {
0805:                p.newline();
0806:            }
0807:
0808:            protected void _newlineOpt() {
0809:                p.newlineOpt();
0810:            }
0811:
0812:            protected void printJsBlockOptionalTruncate(JsBlock x,
0813:                    boolean truncate) {
0814:                boolean needBraces = !x.isGlobalBlock();
0815:
0816:                if (needBraces) {
0817:                    // Open braces.
0818:                    //
0819:                    _blockOpen();
0820:                }
0821:
0822:                int count = 0;
0823:                for (Iterator<JsStatement> iter = x.getStatements().iterator(); iter
0824:                        .hasNext(); ++count) {
0825:                    if (truncate && count > JSBLOCK_LINES_TO_PRINT) {
0826:                        p.print("[...]");
0827:                        _newlineOpt();
0828:                        break;
0829:                    }
0830:                    JsStatement stmt = iter.next();
0831:                    needSemi = true;
0832:                    accept(stmt);
0833:                    if (needSemi) {
0834:                        /*
0835:                         * Special treatment of function decls: function decls always set
0836:                         * needSemi back to true. But if they are the only item in a statement
0837:                         * (i.e. not part of an assignment operation), just give them a newline
0838:                         * instead of a semi since it makes obfuscated code so much "nicer"
0839:                         * (sic).
0840:                         */
0841:                        if (stmt instanceof  JsExprStmt
0842:                                && ((JsExprStmt) stmt).getExpression() instanceof  JsFunction) {
0843:                            _newline();
0844:                        } else {
0845:                            _semi();
0846:                            _newlineOpt();
0847:                        }
0848:                    }
0849:                }
0850:
0851:                if (needBraces) {
0852:                    // Close braces.
0853:                    //
0854:                    _blockClose();
0855:                }
0856:                needSemi = false;
0857:            }
0858:
0859:            private void _assignment() {
0860:                p.print('=');
0861:            }
0862:
0863:            private void _blockClose() {
0864:                p.indentOut();
0865:                p.print('}');
0866:                _newlineOpt();
0867:            }
0868:
0869:            private void _blockOpen() {
0870:                p.print('{');
0871:                p.indentIn();
0872:                _newlineOpt();
0873:            }
0874:
0875:            private void _break() {
0876:                p.print(CHARS_BREAK);
0877:            }
0878:
0879:            private void _case() {
0880:                p.print(CHARS_CASE);
0881:            }
0882:
0883:            private void _catch() {
0884:                p.print(CHARS_CATCH);
0885:            }
0886:
0887:            private void _colon() {
0888:                p.print(':');
0889:            }
0890:
0891:            private void _continue() {
0892:                p.print(CHARS_CONTINUE);
0893:            }
0894:
0895:            private void _debugger() {
0896:                p.print(CHARS_DEBUGGER);
0897:            }
0898:
0899:            private void _default() {
0900:                p.print(CHARS_DEFAULT);
0901:            }
0902:
0903:            private void _do() {
0904:                p.print(CHARS_DO);
0905:            }
0906:
0907:            private void _dot() {
0908:                p.print('.');
0909:            }
0910:
0911:            private void _else() {
0912:                p.print(CHARS_ELSE);
0913:            }
0914:
0915:            private void _false() {
0916:                p.print(CHARS_FALSE);
0917:            }
0918:
0919:            private void _finally() {
0920:                p.print(CHARS_FINALLY);
0921:            }
0922:
0923:            private void _for() {
0924:                p.print(CHARS_FOR);
0925:            }
0926:
0927:            private void _function() {
0928:                p.print(CHARS_FUNCTION);
0929:            }
0930:
0931:            private void _if() {
0932:                p.print(CHARS_IF);
0933:            }
0934:
0935:            private void _in() {
0936:                p.print(CHARS_IN);
0937:            }
0938:
0939:            private void _lbrace() {
0940:                p.print('{');
0941:            }
0942:
0943:            private void _lparen() {
0944:                p.print('(');
0945:            }
0946:
0947:            private void _lsquare() {
0948:                p.print('[');
0949:            }
0950:
0951:            private void _nameDef(JsName name) {
0952:                p.print(name.getShortIdent());
0953:            }
0954:
0955:            private void _nameOf(HasName hasName) {
0956:                _nameDef(hasName.getName());
0957:            }
0958:
0959:            private void _nameRef(JsNameRef nameRef) {
0960:                p.print(nameRef.getShortIdent());
0961:            }
0962:
0963:            private boolean _nestedPop(JsStatement statement) {
0964:                boolean pop = !(statement instanceof  JsBlock);
0965:                if (pop) {
0966:                    p.indentOut();
0967:                }
0968:                return pop;
0969:            }
0970:
0971:            private boolean _nestedPush(JsStatement statement, boolean needSpace) {
0972:                boolean push = !(statement instanceof  JsBlock);
0973:                if (push) {
0974:                    if (needSpace) {
0975:                        _space();
0976:                    }
0977:                    p.indentIn();
0978:                    _newlineOpt();
0979:                } else {
0980:                    _spaceOpt();
0981:                }
0982:                return push;
0983:            }
0984:
0985:            private void _new() {
0986:                p.print(CHARS_NEW);
0987:            }
0988:
0989:            private void _null() {
0990:                p.print(CHARS_NULL);
0991:            }
0992:
0993:            private boolean _parenCalc(JsExpression parent, JsExpression child,
0994:                    boolean wrongAssoc) {
0995:                int parentPrec = JsPrecedenceVisitor.exec(parent);
0996:                int childPrec = JsPrecedenceVisitor.exec(child);
0997:                return (parentPrec > childPrec || (parentPrec == childPrec && wrongAssoc));
0998:            }
0999:
1000:            private boolean _parenPop(JsExpression parent, JsExpression child,
1001:                    boolean wrongAssoc) {
1002:                boolean doPop = _parenCalc(parent, child, wrongAssoc);
1003:                if (doPop) {
1004:                    _rparen();
1005:                }
1006:                return doPop;
1007:            }
1008:
1009:            private boolean _parenPopIfCommaExpr(JsExpression x) {
1010:                boolean doPop = x instanceof  JsBinaryOperation
1011:                        && ((JsBinaryOperation) x).getOperator() == JsBinaryOperator.COMMA;
1012:                if (doPop) {
1013:                    _rparen();
1014:                }
1015:                return doPop;
1016:            }
1017:
1018:            private boolean _parenPopOrSpace(JsExpression parent,
1019:                    JsExpression child, boolean wrongAssoc) {
1020:                boolean doPop = _parenCalc(parent, child, wrongAssoc);
1021:                if (doPop) {
1022:                    _rparen();
1023:                } else {
1024:                    _space();
1025:                }
1026:                return doPop;
1027:            }
1028:
1029:            private boolean _parenPush(JsExpression parent, JsExpression child,
1030:                    boolean wrongAssoc) {
1031:                boolean doPush = _parenCalc(parent, child, wrongAssoc);
1032:                if (doPush) {
1033:                    _lparen();
1034:                }
1035:                return doPush;
1036:            }
1037:
1038:            private boolean _parenPushIfCommaExpr(JsExpression x) {
1039:                boolean doPush = x instanceof  JsBinaryOperation
1040:                        && ((JsBinaryOperation) x).getOperator() == JsBinaryOperator.COMMA;
1041:                if (doPush) {
1042:                    _lparen();
1043:                }
1044:                return doPush;
1045:            }
1046:
1047:            private boolean _parenPushOrSpace(JsExpression parent,
1048:                    JsExpression child, boolean wrongAssoc) {
1049:                boolean doPush = _parenCalc(parent, child, wrongAssoc);
1050:                if (doPush) {
1051:                    _lparen();
1052:                } else {
1053:                    _space();
1054:                }
1055:                return doPush;
1056:            }
1057:
1058:            private void _questionMark() {
1059:                p.print('?');
1060:            }
1061:
1062:            private void _rbrace() {
1063:                p.print('}');
1064:            }
1065:
1066:            private void _return() {
1067:                p.print(CHARS_RETURN);
1068:            }
1069:
1070:            private void _rparen() {
1071:                p.print(')');
1072:            }
1073:
1074:            private void _rsquare() {
1075:                p.print(']');
1076:            }
1077:
1078:            private void _semi() {
1079:                p.print(';');
1080:            }
1081:
1082:            private boolean _sepCommaOptSpace(boolean sep) {
1083:                if (sep) {
1084:                    p.print(',');
1085:                    _spaceOpt();
1086:                }
1087:                return true;
1088:            }
1089:
1090:            private void _slash() {
1091:                p.print('/');
1092:            }
1093:
1094:            private void _space() {
1095:                p.print(' ');
1096:            }
1097:
1098:            private boolean _spaceCalc(JsOperator op, JsExpression arg) {
1099:                if (op.isKeyword()) {
1100:                    return true;
1101:                }
1102:                if (arg instanceof  JsPrefixOperation) {
1103:                    JsOperator op2 = ((JsPrefixOperation) arg).getOperator();
1104:                    return (op == JsBinaryOperator.SUB || op == JsUnaryOperator.NEG)
1105:                            && (op2 == JsUnaryOperator.DEC || op2 == JsUnaryOperator.NEG)
1106:                            || (op == JsBinaryOperator.ADD && op2 == JsUnaryOperator.INC);
1107:                }
1108:                return false;
1109:            }
1110:
1111:            private void _spaceOpt() {
1112:                p.printOpt(' ');
1113:            }
1114:
1115:            private void _switch() {
1116:                p.print(CHARS_SWITCH);
1117:            }
1118:
1119:            private void _this () {
1120:                p.print(CHARS_THIS);
1121:            }
1122:
1123:            private void _throw() {
1124:                p.print(CHARS_THROW);
1125:            }
1126:
1127:            private void _true() {
1128:                p.print(CHARS_TRUE);
1129:            }
1130:
1131:            private void _try() {
1132:                p.print(CHARS_TRY);
1133:            }
1134:
1135:            private void _var() {
1136:                p.print(CHARS_VAR);
1137:            }
1138:
1139:            private void _while() {
1140:                p.print(CHARS_WHILE);
1141:            }
1142:
1143:            // CHECKSTYLE_NAMING_ON
1144:
1145:            /**
1146:             * Escapes any closing XML tags embedded in <code>str</code>, which could
1147:             * potentially cause a parse failure in a browser, for example, embedding a
1148:             * closing <code>&lt;script&gt;</code> tag.
1149:             * 
1150:             * @param str an unescaped literal; May be null
1151:             */
1152:            private void escapeClosingTags(StringBuffer str) {
1153:                if (str == null) {
1154:                    return;
1155:                }
1156:
1157:                int index = 0;
1158:
1159:                while ((index = str.indexOf("</", index)) != -1) {
1160:                    str.insert(index + 1, '\\');
1161:                }
1162:            }
1163:
1164:            private void indent() {
1165:                p.indentIn();
1166:            }
1167:
1168:            private void outdent() {
1169:                p.indentOut();
1170:            }
1171:
1172:            /**
1173:             * Adapted from
1174:             * {@link com.google.gwt.dev.js.rhino.ScriptRuntime#escapeString(String)}.
1175:             * The difference is that we quote with either &quot; or &apos; depending on
1176:             * which one is used less inside the string.
1177:             */
1178:            private void printStringLiteral(String value) {
1179:
1180:                char[] chars = value.toCharArray();
1181:                final int n = chars.length;
1182:                int quoteCount = 0;
1183:                int aposCount = 0;
1184:                for (int i = 0; i < n; ++i) {
1185:                    switch (chars[i]) {
1186:                    case '"':
1187:                        ++quoteCount;
1188:                        break;
1189:                    case '\'':
1190:                        ++aposCount;
1191:                        break;
1192:                    }
1193:                }
1194:
1195:                StringBuffer result = new StringBuffer(value.length() + 16);
1196:
1197:                char quoteChar = (quoteCount < aposCount) ? '"' : '\'';
1198:                p.print(quoteChar);
1199:
1200:                for (int i = 0; i < n; ++i) {
1201:                    char c = chars[i];
1202:
1203:                    if (' ' <= c && c <= '~' && c != quoteChar && c != '\\') {
1204:                        // an ordinary print character (like C isprint())
1205:                        result.append(c);
1206:                        continue;
1207:                    }
1208:
1209:                    int escape = -1;
1210:                    switch (c) {
1211:                    case 0:
1212:                        escape = '0';
1213:                        break;
1214:                    case '\b':
1215:                        escape = 'b';
1216:                        break;
1217:                    case '\f':
1218:                        escape = 'f';
1219:                        break;
1220:                    case '\n':
1221:                        escape = 'n';
1222:                        break;
1223:                    case '\r':
1224:                        escape = 'r';
1225:                        break;
1226:                    case '\t':
1227:                        escape = 't';
1228:                        break;
1229:                    case '"':
1230:                        escape = '"';
1231:                        break; // only reach here if == quoteChar
1232:                    case '\'':
1233:                        escape = '\'';
1234:                        break; // only reach here if == quoteChar
1235:                    case '\\':
1236:                        escape = '\\';
1237:                        break;
1238:                    }
1239:
1240:                    if (escape >= 0) {
1241:                        // an \escaped sort of character
1242:                        result.append('\\');
1243:                        result.append((char) escape);
1244:                    } else {
1245:                        int hexSize;
1246:                        if (c < 256) {
1247:                            // 2-digit hex
1248:                            result.append("\\x");
1249:                            hexSize = 2;
1250:                        } else {
1251:                            // Unicode.
1252:                            result.append("\\u");
1253:                            hexSize = 4;
1254:                        }
1255:                        // append hexadecimal form of ch left-padded with 0
1256:                        for (int shift = (hexSize - 1) * 4; shift >= 0; shift -= 4) {
1257:                            int digit = 0xf & (c >> shift);
1258:                            result.append(HEX_DIGITS[digit]);
1259:                        }
1260:                    }
1261:                }
1262:                result.append(quoteChar);
1263:                escapeClosingTags(result);
1264:                p.print(result.toString());
1265:            }
1266:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.