1 | |
|
2 | |
|
3 | |
|
4 | |
|
5 | |
|
6 | |
|
7 | |
|
8 | |
|
9 | |
|
10 | |
|
11 | |
|
12 | |
|
13 | |
|
14 | |
|
15 | |
|
16 | |
|
17 | |
|
18 | |
|
19 | |
|
20 | |
|
21 | |
|
22 | |
|
23 | |
|
24 | |
|
25 | |
|
26 | |
package com.sun.tools.javafx.comp; |
27 | |
|
28 | |
import com.sun.tools.javac.util.*; |
29 | |
import com.sun.tools.javac.code.*; |
30 | |
import com.sun.tools.javac.code.Symbol.*; |
31 | |
import com.sun.tools.javac.tree.*; |
32 | |
import com.sun.tools.javac.tree.JCTree.*; |
33 | |
|
34 | |
import com.sun.tools.javafx.tree.JavafxTreeMaker; |
35 | |
import com.sun.tools.javafx.comp.JavafxAttr.Sequenceness; |
36 | |
import com.sun.tools.javafx.util.MsgSym; |
37 | |
|
38 | |
|
39 | |
|
40 | |
|
41 | |
|
42 | |
|
43 | |
|
44 | |
|
45 | |
|
46 | |
|
47 | |
public class JavafxAnnotate { |
48 | 12 | protected static final Context.Key<JavafxAnnotate> javafxAnnotateKey = |
49 | |
new Context.Key<JavafxAnnotate>(); |
50 | |
|
51 | |
public static JavafxAnnotate instance(Context context) { |
52 | 1197 | JavafxAnnotate instance = context.get(javafxAnnotateKey); |
53 | 1197 | if (instance == null) |
54 | 399 | instance = new JavafxAnnotate(context); |
55 | 1197 | return instance; |
56 | |
} |
57 | |
|
58 | |
final JavafxAttr attr; |
59 | |
final TreeMaker make; |
60 | |
final Log log; |
61 | |
final Symtab syms; |
62 | |
final Name.Table names; |
63 | |
final JavafxResolve rs; |
64 | |
final Types types; |
65 | |
|
66 | |
final JavafxCheck chk; |
67 | |
|
68 | 399 | protected JavafxAnnotate(Context context) { |
69 | 399 | context.put(javafxAnnotateKey, this); |
70 | 399 | attr = JavafxAttr.instance(context); |
71 | 399 | make = JavafxTreeMaker.instance(context); |
72 | 399 | log = Log.instance(context); |
73 | 399 | syms = Symtab.instance(context); |
74 | 399 | names = Name.Table.instance(context); |
75 | 399 | rs = JavafxResolve.instance(context); |
76 | 399 | types = Types.instance(context); |
77 | |
|
78 | 399 | chk = (JavafxCheck)JavafxCheck.instance(context); |
79 | 399 | } |
80 | |
|
81 | |
|
82 | |
|
83 | |
|
84 | |
|
85 | 399 | private int enterCount = 0; |
86 | |
|
87 | 399 | ListBuffer<Annotator> q = new ListBuffer<Annotator>(); |
88 | |
|
89 | |
public void later(Annotator a) { |
90 | 0 | q.append(a); |
91 | 0 | } |
92 | |
|
93 | |
public void earlier(Annotator a) { |
94 | 0 | q.prepend(a); |
95 | 0 | } |
96 | |
|
97 | |
|
98 | |
public void enterStart() { |
99 | 383 | enterCount++; |
100 | 383 | } |
101 | |
|
102 | |
|
103 | |
public void enterDone() { |
104 | 383 | enterCount--; |
105 | 383 | flush(); |
106 | 383 | } |
107 | |
|
108 | |
public void flush() { |
109 | 1018 | if (enterCount != 0) return; |
110 | 409 | enterCount++; |
111 | |
try { |
112 | 409 | while (q.nonEmpty()) |
113 | 0 | q.next().enterAnnotation(); |
114 | |
} finally { |
115 | 409 | enterCount--; |
116 | 409 | } |
117 | 409 | } |
118 | |
|
119 | |
|
120 | |
|
121 | |
|
122 | |
|
123 | |
|
124 | |
public interface Annotator { |
125 | |
void enterAnnotation(); |
126 | |
String toString(); |
127 | |
} |
128 | |
|
129 | |
|
130 | |
|
131 | |
|
132 | |
|
133 | |
|
134 | |
|
135 | |
|
136 | |
|
137 | |
|
138 | |
Attribute.Compound enterAnnotation(JCAnnotation a, |
139 | |
Type expected, |
140 | |
JavafxEnv<JavafxAttrContext> env) { |
141 | |
|
142 | |
|
143 | |
|
144 | 0 | Type at = (a.annotationType.type != null ? a.annotationType.type |
145 | |
: attr.attribType(a.annotationType, env)); |
146 | 0 | a.type = chk.checkType(a.annotationType.pos(), at, expected, Sequenceness.DISALLOWED); |
147 | 0 | if (a.type.isErroneous()) |
148 | 0 | return new Attribute.Compound(a.type, List.<Pair<MethodSymbol,Attribute>>nil()); |
149 | 0 | if ((a.type.tsym.flags() & Flags.ANNOTATION) == 0) { |
150 | 0 | log.error(a.annotationType.pos(), |
151 | |
MsgSym.MESSAGE_NOT_ANNOTATION_TYPE, a.type.toString()); |
152 | 0 | return new Attribute.Compound(a.type, List.<Pair<MethodSymbol,Attribute>>nil()); |
153 | |
} |
154 | 0 | List<JCExpression> args = a.args; |
155 | 0 | if (args.length() == 1 && args.head.getTag() != JCTree.ASSIGN) { |
156 | |
|
157 | 0 | args.head = make.at(args.head.pos). |
158 | |
Assign(make.Ident(names.value), args.head); |
159 | |
} |
160 | 0 | ListBuffer<Pair<MethodSymbol,Attribute>> buf = |
161 | |
new ListBuffer<Pair<MethodSymbol,Attribute>>(); |
162 | 0 | for (List<JCExpression> tl = args; tl.nonEmpty(); tl = tl.tail) { |
163 | 0 | JCExpression t = tl.head; |
164 | 0 | if (t.getTag() != JCTree.ASSIGN) { |
165 | 0 | log.error(t.pos(), MsgSym.MESSAGE_ANNOTATION_VALUE_MUST_BE_NAME_VALUE); |
166 | 0 | continue; |
167 | |
} |
168 | 0 | JCAssign assign = (JCAssign)t; |
169 | 0 | if (assign.lhs.getTag() != JCTree.IDENT) { |
170 | 0 | log.error(t.pos(), MsgSym.MESSAGE_ANNOTATION_VALUE_MUST_BE_NAME_VALUE); |
171 | 0 | continue; |
172 | |
} |
173 | 0 | JCIdent left = (JCIdent)assign.lhs; |
174 | 0 | Symbol method = rs.resolveQualifiedMethod(left.pos(), |
175 | |
env, |
176 | |
a.type, |
177 | |
left.name, |
178 | |
rs.newMethTemplate(List.<Type>nil(), null)); |
179 | 0 | left.sym = method; |
180 | 0 | left.type = method.type; |
181 | 0 | if (method.owner != a.type.tsym) |
182 | 0 | log.error(left.pos(), MsgSym.MESSAGE_NO_ANNOTATION_MEMBER, left.name, a.type); |
183 | 0 | Type result = method.type.getReturnType(); |
184 | 0 | Attribute value = enterAttributeValue(result, assign.rhs, env); |
185 | 0 | if (!method.type.isErroneous()) |
186 | 0 | buf.append(new Pair<MethodSymbol,Attribute> |
187 | |
((MethodSymbol)method, value)); |
188 | |
} |
189 | 0 | return new Attribute.Compound(a.type, buf.toList()); |
190 | |
} |
191 | |
|
192 | |
Attribute enterAttributeValue(Type expected, |
193 | |
JCExpression tree, |
194 | |
JavafxEnv<JavafxAttrContext> env) { |
195 | 0 | if (expected.isPrimitive() || types.isSameType(expected, syms.stringType)) { |
196 | 0 | Type result = attr.attribExpr(tree, env, expected); |
197 | 0 | if (result.isErroneous()) |
198 | 0 | return new Attribute.Error(expected); |
199 | 0 | if (result.constValue() == null) { |
200 | 0 | log.error(tree.pos(), MsgSym.MESSAGE_ATTRIBUTE_VALUE_MUST_BE_CONSTANT); |
201 | 0 | return new Attribute.Error(expected); |
202 | |
} |
203 | |
|
204 | 0 | return new Attribute.Constant(expected, result.constValue()); |
205 | |
} |
206 | 0 | if (expected.tsym == syms.classType.tsym) { |
207 | 0 | Type result = attr.attribExpr(tree, env, expected); |
208 | 0 | if (result.isErroneous()) |
209 | 0 | return new Attribute.Error(expected); |
210 | 0 | if (TreeInfo.name(tree) != names._class) { |
211 | 0 | log.error(tree.pos(), MsgSym.MESSAGE_ANNOTATION_VALUE_MUST_BE_CLASS_LITERAL); |
212 | 0 | return new Attribute.Error(expected); |
213 | |
} |
214 | 0 | return new Attribute.Class(types, |
215 | |
(((JCFieldAccess) tree).selected).type); |
216 | |
} |
217 | 0 | if ((expected.tsym.flags() & Flags.ANNOTATION) != 0) { |
218 | 0 | if (tree.getTag() != JCTree.ANNOTATION) { |
219 | 0 | log.error(tree.pos(), MsgSym.MESSAGE_ANNOTATION_VALUE_MUST_BE_ANNOTATION); |
220 | 0 | expected = syms.errorType; |
221 | |
} |
222 | 0 | return enterAnnotation((JCAnnotation)tree, expected, env); |
223 | |
} |
224 | 0 | if (expected.tag == TypeTags.ARRAY) { |
225 | 0 | if (tree.getTag() != JCTree.NEWARRAY) { |
226 | 0 | tree = make.at(tree.pos). |
227 | |
NewArray(null, List.<JCExpression>nil(), List.of(tree)); |
228 | |
} |
229 | 0 | JCNewArray na = (JCNewArray)tree; |
230 | 0 | if (na.elemtype != null) { |
231 | 0 | log.error(na.elemtype.pos(), MsgSym.MESSAGE_NEW_NOT_ALLOWED_IN_ANNOTATION); |
232 | 0 | return new Attribute.Error(expected); |
233 | |
} |
234 | 0 | ListBuffer<Attribute> buf = new ListBuffer<Attribute>(); |
235 | 0 | for (List<JCExpression> l = na.elems; l.nonEmpty(); l=l.tail) { |
236 | 0 | buf.append(enterAttributeValue(types.elemtype(expected), |
237 | |
l.head, |
238 | |
env)); |
239 | |
} |
240 | 0 | return new Attribute. |
241 | |
Array(expected, buf.toArray(new Attribute[buf.length()])); |
242 | |
} |
243 | 0 | if (expected.tag == TypeTags.CLASS && |
244 | |
(expected.tsym.flags() & Flags.ENUM) != 0) { |
245 | 0 | attr.attribExpr(tree, env, expected); |
246 | 0 | Symbol sym = TreeInfo.symbol(tree); |
247 | 0 | if (sym == null || |
248 | |
TreeInfo.nonstaticSelect(tree) || |
249 | |
sym.kind != Kinds.VAR || |
250 | |
(sym.flags() & Flags.ENUM) == 0) { |
251 | 0 | log.error(tree.pos(), MsgSym.MESSAGE_ENUM_ANNOTATION_MUST_BE_ENUM_CONSTANT); |
252 | 0 | return new Attribute.Error(expected); |
253 | |
} |
254 | 0 | VarSymbol enumerator = (VarSymbol) sym; |
255 | 0 | return new Attribute.Enum(expected, enumerator); |
256 | |
} |
257 | 0 | if (!expected.isErroneous()) |
258 | 0 | log.error(tree.pos(), MsgSym.MESSAGE_ANNOTATION_VALUE_NOT_ALLOWABLE_TYPE); |
259 | 0 | return new Attribute.Error(attr.attribExpr(tree, env, expected)); |
260 | |
} |
261 | |
} |