OLD | NEW |
| (Empty) |
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | |
2 // for details. All rights reserved. Use of this source code is governed by a | |
3 // BSD-style license that can be found in the LICENSE file. | |
4 | |
5 package com.google.dart.compiler.backend.js; | |
6 | |
7 import com.google.dart.compiler.backend.js.ast.JsArrayAccess; | |
8 import com.google.dart.compiler.backend.js.ast.JsArrayLiteral; | |
9 import com.google.dart.compiler.backend.js.ast.JsContext; | |
10 import com.google.dart.compiler.backend.js.ast.JsExpression; | |
11 import com.google.dart.compiler.backend.js.ast.JsFunction; | |
12 import com.google.dart.compiler.backend.js.ast.JsInvocation; | |
13 import com.google.dart.compiler.backend.js.ast.JsNameRef; | |
14 import com.google.dart.compiler.backend.js.ast.JsNew; | |
15 import com.google.dart.compiler.backend.js.ast.JsObjectLiteral; | |
16 import com.google.dart.compiler.backend.js.ast.JsVisitable; | |
17 import com.google.dart.compiler.backend.js.ast.JsVisitor; | |
18 | |
19 /** | |
20 * Searches for method invocations in constructor expressions that would not | |
21 * normally be surrounded by parentheses. | |
22 */ | |
23 public class JsConstructExpressionVisitor extends JsVisitor { | |
24 | |
25 public static boolean exec(JsExpression expression) { | |
26 if (JsPrecedenceVisitor.exec(expression) < JsPrecedenceVisitor.PRECEDENCE_NE
W) { | |
27 return true; | |
28 } | |
29 JsConstructExpressionVisitor visitor = new JsConstructExpressionVisitor(); | |
30 visitor.accept(expression); | |
31 return visitor.containsInvocation; | |
32 } | |
33 | |
34 private boolean containsInvocation = false; | |
35 | |
36 private JsConstructExpressionVisitor() { | |
37 } | |
38 | |
39 /** | |
40 * We only look at the array expression since the index has its own scope. | |
41 */ | |
42 @Override | |
43 public boolean visit(JsArrayAccess x, JsContext ctx) { | |
44 accept(x.getArrayExpr()); | |
45 return false; | |
46 } | |
47 | |
48 /** | |
49 * Array literals have their own scoping. | |
50 */ | |
51 @Override | |
52 public boolean visit(JsArrayLiteral x, JsContext ctx) { | |
53 return false; | |
54 } | |
55 | |
56 /** | |
57 * Functions have their own scoping. | |
58 */ | |
59 @Override | |
60 public boolean visit(JsFunction x, JsContext ctx) { | |
61 return false; | |
62 } | |
63 | |
64 @Override | |
65 public boolean visit(JsInvocation x, JsContext ctx) { | |
66 containsInvocation = true; | |
67 return false; | |
68 } | |
69 | |
70 @Override | |
71 public boolean visit(JsNameRef x, JsContext ctx) { | |
72 if (!x.isLeaf()) { | |
73 accept(x.getQualifier()); | |
74 } | |
75 return false; | |
76 } | |
77 | |
78 /** | |
79 * New constructs bind to the nearest set of parentheses. | |
80 */ | |
81 @Override | |
82 public boolean visit(JsNew x, JsContext ctx) { | |
83 return false; | |
84 } | |
85 | |
86 /** | |
87 * Object literals have their own scope. | |
88 */ | |
89 @Override | |
90 public boolean visit(JsObjectLiteral x, JsContext ctx) { | |
91 return false; | |
92 } | |
93 | |
94 /** | |
95 * We only look at nodes that would not normally be surrounded by parentheses. | |
96 */ | |
97 @Override | |
98 protected <T extends JsVisitable> T doAccept(T node) { | |
99 // Assign to Object to prevent 'inconvertible types' compile errors due | |
100 // to http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6548436 | |
101 // reproducible in jdk1.6.0_02. | |
102 Object o = node; | |
103 if (o instanceof JsExpression) { | |
104 JsExpression expression = (JsExpression) o; | |
105 int precedence = JsPrecedenceVisitor.exec(expression); | |
106 // Only visit expressions that won't automatically be surrounded by | |
107 // parentheses | |
108 if (precedence < JsPrecedenceVisitor.PRECEDENCE_NEW) { | |
109 return node; | |
110 } | |
111 } | |
112 return super.doAccept(node); | |
113 } | |
114 } | |
OLD | NEW |