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.code.*; |
29 | |
import com.sun.tools.javac.jvm.*; |
30 | |
import com.sun.tools.javac.tree.*; |
31 | |
import com.sun.tools.javac.util.*; |
32 | |
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; |
33 | |
import com.sun.tools.javac.code.Symbol.*; |
34 | |
import com.sun.tools.javac.code.Type.*; |
35 | |
import com.sun.tools.javac.tree.JCTree.*; |
36 | |
|
37 | |
import static com.sun.tools.javac.code.Flags.*; |
38 | |
import static com.sun.tools.javac.code.Kinds.*; |
39 | |
import static com.sun.tools.javac.code.TypeTags.*; |
40 | |
|
41 | |
import static com.sun.tools.javac.tree.JCTree.SELECT; |
42 | |
|
43 | |
import com.sun.tools.javafx.tree.*; |
44 | |
import com.sun.tools.javafx.code.JavafxClassSymbol; |
45 | |
import com.sun.tools.javafx.code.JavafxFlags; |
46 | |
import com.sun.tools.javafx.code.JavafxSymtab; |
47 | |
import com.sun.tools.javafx.code.JavafxVarSymbol; |
48 | |
import com.sun.tools.javafx.util.MsgSym; |
49 | |
|
50 | |
import javax.tools.JavaFileObject; |
51 | |
import java.util.Set; |
52 | |
import java.util.HashSet; |
53 | |
|
54 | |
|
55 | |
|
56 | |
|
57 | |
|
58 | |
|
59 | |
|
60 | |
|
61 | |
|
62 | |
|
63 | |
|
64 | |
|
65 | |
|
66 | 12 | public class JavafxMemberEnter extends JavafxTreeScanner implements JavafxVisitor, Completer { |
67 | 12 | protected static final Context.Key<JavafxMemberEnter> javafxMemberEnterKey = |
68 | |
new Context.Key<JavafxMemberEnter>(); |
69 | |
|
70 | |
|
71 | |
protected |
72 | |
final static boolean checkClash = true; |
73 | |
|
74 | |
private final Name.Table names; |
75 | |
private final JavafxEnter enter; |
76 | |
private final Log log; |
77 | |
private final JavafxCheck chk; |
78 | |
private final JavafxAttr attr; |
79 | |
private final JavafxSymtab syms; |
80 | |
private final JavafxTreeMaker make; |
81 | |
private final ClassReader reader; |
82 | |
private final JavafxTodo todo; |
83 | |
private final JavafxAnnotate annotate; |
84 | |
private final Types types; |
85 | |
private final Target target; |
86 | |
|
87 | |
private final boolean skipAnnotations; |
88 | |
private JavafxEnv<JavafxAttrContext> localEnv; |
89 | |
|
90 | |
public static JavafxMemberEnter instance(Context context) { |
91 | 798 | JavafxMemberEnter instance = context.get(javafxMemberEnterKey); |
92 | 798 | if (instance == null) |
93 | 399 | instance = new JavafxMemberEnter(context); |
94 | 798 | return instance; |
95 | |
} |
96 | |
|
97 | 399 | protected JavafxMemberEnter(Context context) { |
98 | |
|
99 | 399 | context.put(javafxMemberEnterKey, this); |
100 | 399 | names = Name.Table.instance(context); |
101 | 399 | enter = JavafxEnter.instance(context); |
102 | 399 | log = Log.instance(context); |
103 | 399 | chk = (JavafxCheck)JavafxCheck.instance(context); |
104 | 399 | attr = JavafxAttr.instance(context); |
105 | 399 | syms = (JavafxSymtab)JavafxSymtab.instance(context); |
106 | 399 | make = (JavafxTreeMaker)JavafxTreeMaker.instance(context); |
107 | 399 | reader = JavafxClassReader.instance(context); |
108 | 399 | todo = JavafxTodo.instance(context); |
109 | 399 | annotate = JavafxAnnotate.instance(context); |
110 | 399 | types = Types.instance(context); |
111 | 399 | target = Target.instance(context); |
112 | |
|
113 | 399 | skipAnnotations = |
114 | |
Options.instance(context).get("skipAnnotations") != null; |
115 | 399 | } |
116 | |
|
117 | |
|
118 | |
|
119 | |
|
120 | |
|
121 | 399 | ListBuffer<JavafxEnv<JavafxAttrContext>> halfcompleted = new ListBuffer<JavafxEnv<JavafxAttrContext>>(); |
122 | |
|
123 | |
|
124 | |
|
125 | |
|
126 | 399 | boolean isFirst = true; |
127 | |
|
128 | |
|
129 | |
|
130 | |
|
131 | |
|
132 | 399 | boolean completionEnabled = true; |
133 | |
|
134 | |
|
135 | |
|
136 | |
|
137 | |
|
138 | |
|
139 | |
|
140 | |
|
141 | |
|
142 | |
|
143 | |
|
144 | |
protected void importAll(int pos, |
145 | |
final TypeSymbol tsym, |
146 | |
JavafxEnv<JavafxAttrContext> env) { |
147 | |
|
148 | 101 | if (tsym.kind == PCK && tsym.members().elems == null && !tsym.exists()) { |
149 | |
|
150 | 0 | if (((PackageSymbol)tsym).fullname.equals(names.java_lang)) { |
151 | 0 | JCDiagnostic msg = JCDiagnostic.fragment(MsgSym.MESSAGE_FATAL_ERR_NO_JAVA_LANG); |
152 | 0 | throw new FatalError(msg); |
153 | |
} else { |
154 | 0 | log.error(pos, MsgSym.MESSAGE_DOES_NOT_EXIST, tsym); |
155 | |
} |
156 | |
} |
157 | 101 | final Scope fromScope = tsym.members(); |
158 | 101 | final Scope toScope = env.toplevel.starImportScope; |
159 | 33884 | for (Scope.Entry e = fromScope.elems; e != null; e = e.sibling) { |
160 | 33783 | if (e.sym.kind == TYP && !toScope.includes(e.sym)) |
161 | 33783 | toScope.enter(e.sym, fromScope); |
162 | |
} |
163 | 101 | } |
164 | |
|
165 | |
|
166 | |
|
167 | |
|
168 | |
|
169 | |
|
170 | |
|
171 | |
private void importStaticAll(int pos, |
172 | |
final TypeSymbol tsym, |
173 | |
JavafxEnv<JavafxAttrContext> env) { |
174 | 0 | final JavaFileObject sourcefile = env.toplevel.sourcefile; |
175 | 0 | final Scope toScope = env.toplevel.starImportScope; |
176 | 0 | final PackageSymbol packge = env.toplevel.packge; |
177 | 0 | final TypeSymbol origin = tsym; |
178 | |
|
179 | |
|
180 | 0 | new Object() { |
181 | 0 | Set<Symbol> processed = new HashSet<Symbol>(); |
182 | |
void importFrom(TypeSymbol tsym) { |
183 | 0 | if (tsym == null || !processed.add(tsym)) |
184 | 0 | return; |
185 | |
|
186 | |
|
187 | 0 | importFrom(types.supertype(tsym.type).tsym); |
188 | 0 | for (Type t : types.interfaces(tsym.type)) |
189 | 0 | importFrom(t.tsym); |
190 | |
|
191 | 0 | final Scope fromScope = tsym.members(); |
192 | 0 | for (Scope.Entry e = fromScope.elems; e != null; e = e.sibling) { |
193 | 0 | Symbol sym = e.sym; |
194 | 0 | if (sym.kind == TYP && |
195 | |
(sym.flags() & STATIC) != 0 && |
196 | |
staticImportAccessible(sym, packge) && |
197 | |
sym.isMemberOf(origin, types) && |
198 | |
!toScope.includes(sym)) |
199 | 0 | toScope.enter(sym, fromScope, origin.members()); |
200 | |
} |
201 | 0 | } |
202 | |
}.importFrom(tsym); |
203 | |
|
204 | |
|
205 | 0 | annotate.earlier(new JavafxAnnotate.Annotator() { |
206 | 0 | Set<Symbol> processed = new HashSet<Symbol>(); |
207 | |
|
208 | |
@Override |
209 | |
public String toString() { |
210 | 0 | return "import static " + tsym + ".*" + " in " + sourcefile; |
211 | |
} |
212 | |
void importFrom(TypeSymbol tsym) { |
213 | 0 | if (tsym == null || !processed.add(tsym)) |
214 | 0 | return; |
215 | |
|
216 | |
|
217 | 0 | importFrom(types.supertype(tsym.type).tsym); |
218 | 0 | for (Type t : types.interfaces(tsym.type)) |
219 | 0 | importFrom(t.tsym); |
220 | |
|
221 | 0 | final Scope fromScope = tsym.members(); |
222 | 0 | for (Scope.Entry e = fromScope.elems; e != null; e = e.sibling) { |
223 | 0 | Symbol sym = e.sym; |
224 | 0 | if (sym.isStatic() && sym.kind != TYP && |
225 | |
staticImportAccessible(sym, packge) && |
226 | |
!toScope.includes(sym) && |
227 | |
sym.isMemberOf(origin, types)) { |
228 | 0 | toScope.enter(sym, fromScope, origin.members()); |
229 | |
} |
230 | |
} |
231 | 0 | } |
232 | |
public void enterAnnotation() { |
233 | 0 | importFrom(tsym); |
234 | 0 | } |
235 | |
}); |
236 | 0 | } |
237 | |
|
238 | |
|
239 | |
boolean staticImportAccessible(Symbol sym, PackageSymbol packge) { |
240 | 0 | int flags = (int)(sym.flags() & AccessFlags); |
241 | 0 | switch (flags) { |
242 | |
default: |
243 | |
case PUBLIC: |
244 | 0 | return true; |
245 | |
case PRIVATE: |
246 | 0 | return false; |
247 | |
case 0: |
248 | |
case PROTECTED: |
249 | 0 | return sym.packge() == packge; |
250 | |
} |
251 | |
} |
252 | |
|
253 | |
|
254 | |
|
255 | |
|
256 | |
|
257 | |
|
258 | |
|
259 | |
|
260 | |
private void importNamedStatic(final DiagnosticPosition pos, |
261 | |
final TypeSymbol tsym, |
262 | |
final Name name, |
263 | |
final JavafxEnv<JavafxAttrContext> env) { |
264 | 0 | if (tsym.kind != TYP) { |
265 | 0 | log.error(pos, MsgSym.MESSAGE_STATIC_IMP_ONLY_CLASSES_AND_INTERFACES); |
266 | 0 | return; |
267 | |
} |
268 | |
|
269 | 0 | final Scope toScope = env.toplevel.namedImportScope; |
270 | 0 | final PackageSymbol packge = env.toplevel.packge; |
271 | 0 | final TypeSymbol origin = tsym; |
272 | |
|
273 | |
|
274 | 0 | new Object() { |
275 | 0 | Set<Symbol> processed = new HashSet<Symbol>(); |
276 | |
void importFrom(TypeSymbol tsym) { |
277 | 0 | if (tsym == null || !processed.add(tsym)) |
278 | 0 | return; |
279 | |
|
280 | |
|
281 | 0 | importFrom(types.supertype(tsym.type).tsym); |
282 | 0 | for (Type t : types.interfaces(tsym.type)) |
283 | 0 | importFrom(t.tsym); |
284 | |
|
285 | 0 | for (Scope.Entry e = tsym.members().lookup(name); |
286 | 0 | e.scope != null; |
287 | 0 | e = e.next()) { |
288 | 0 | Symbol sym = e.sym; |
289 | 0 | if (sym.isStatic() && |
290 | |
sym.kind == TYP && |
291 | |
staticImportAccessible(sym, packge) && |
292 | |
sym.isMemberOf(origin, types) && |
293 | |
chk.checkUniqueStaticImport(pos, sym, toScope)) |
294 | 0 | toScope.enter(sym, sym.owner.members(), origin.members()); |
295 | |
} |
296 | 0 | } |
297 | |
}.importFrom(tsym); |
298 | |
|
299 | |
|
300 | 0 | annotate.earlier(new JavafxAnnotate.Annotator() { |
301 | 0 | Set<Symbol> processed = new HashSet<Symbol>(); |
302 | 0 | boolean found = false; |
303 | |
|
304 | |
@Override |
305 | |
public String toString() { |
306 | 0 | return "import static " + tsym + "." + name; |
307 | |
} |
308 | |
void importFrom(TypeSymbol tsym) { |
309 | 0 | if (tsym == null || !processed.add(tsym)) |
310 | 0 | return; |
311 | |
|
312 | |
|
313 | 0 | importFrom(types.supertype(tsym.type).tsym); |
314 | 0 | for (Type t : types.interfaces(tsym.type)) |
315 | 0 | importFrom(t.tsym); |
316 | |
|
317 | 0 | for (Scope.Entry e = tsym.members().lookup(name); |
318 | 0 | e.scope != null; |
319 | 0 | e = e.next()) { |
320 | 0 | Symbol sym = e.sym; |
321 | 0 | if (sym.isStatic() && |
322 | |
staticImportAccessible(sym, packge) && |
323 | |
sym.isMemberOf(origin, types)) { |
324 | 0 | found = true; |
325 | 0 | if (sym.kind == MTH || |
326 | |
sym.kind != TYP && chk.checkUniqueStaticImport(pos, sym, toScope)) |
327 | 0 | toScope.enter(sym, sym.owner.members(), origin.members()); |
328 | |
} |
329 | |
} |
330 | 0 | } |
331 | |
public void enterAnnotation() { |
332 | 0 | JavaFileObject prev = log.useSource(env.toplevel.sourcefile); |
333 | |
try { |
334 | 0 | importFrom(tsym); |
335 | 0 | if (!found) { |
336 | 0 | log.error(pos, MsgSym.MESSAGE_CANNOT_RESOLVE_LOCATION, |
337 | |
JCDiagnostic.fragment(MsgSym.KINDNAME_STATIC), |
338 | |
name, "", "", JavafxResolve.typeKindName(tsym.type), |
339 | |
tsym.type); |
340 | |
} |
341 | |
} finally { |
342 | 0 | log.useSource(prev); |
343 | 0 | } |
344 | 0 | } |
345 | |
}); |
346 | 0 | } |
347 | |
|
348 | |
|
349 | |
|
350 | |
|
351 | |
|
352 | |
|
353 | |
|
354 | |
void importNamed(DiagnosticPosition pos, Symbol tsym, JavafxEnv<JavafxAttrContext> env) { |
355 | 3327 | if (tsym.kind == TYP && |
356 | |
chk.checkUniqueImport(pos, tsym, env.toplevel.namedImportScope)) |
357 | 3323 | env.toplevel.namedImportScope.enter(tsym, tsym.owner.members()); |
358 | 3327 | } |
359 | |
|
360 | |
|
361 | |
|
362 | |
|
363 | |
|
364 | |
|
365 | |
|
366 | |
protected JavafxEnv<JavafxAttrContext> env; |
367 | |
|
368 | |
|
369 | |
|
370 | |
|
371 | |
void memberEnter(JCTree tree, JavafxEnv<JavafxAttrContext> env) { |
372 | 10369 | JavafxEnv<JavafxAttrContext> prevEnv = this.env; |
373 | |
try { |
374 | 10369 | this.env = env; |
375 | 10369 | tree.accept(this); |
376 | 0 | } catch (CompletionFailure ex) { |
377 | 0 | chk.completionError(tree.pos(), ex); |
378 | |
} finally { |
379 | 10369 | this.env = prevEnv; |
380 | 10369 | } |
381 | 10369 | } |
382 | |
|
383 | |
|
384 | |
|
385 | |
void memberEnter(List<? extends JCTree> trees, JavafxEnv<JavafxAttrContext> env) { |
386 | 12405 | for (List<? extends JCTree> l = trees; l.nonEmpty(); l = l.tail) |
387 | 8206 | memberEnter(l.head, env); |
388 | 4199 | } |
389 | |
|
390 | |
@Override |
391 | |
public void visitTree(JCTree tree) { |
392 | 0 | if (tree instanceof JFXBlockExpression) |
393 | 0 | visitBlockExpression((JFXBlockExpression) tree); |
394 | |
else |
395 | 0 | super.visitTree(tree); |
396 | 0 | } |
397 | |
|
398 | |
@Override |
399 | |
public void visitErroneous(JCErroneous tree) { |
400 | 0 | memberEnter(tree.errs, env); |
401 | 0 | } |
402 | |
|
403 | |
@Override |
404 | |
public void visitTopLevel(JCCompilationUnit tree) { |
405 | 690 | if (tree.starImportScope.elems != null) { |
406 | |
|
407 | 0 | return; |
408 | |
} |
409 | |
|
410 | |
|
411 | |
|
412 | 690 | if (checkClash && tree.pid != null) { |
413 | 14 | Symbol p = tree.packge; |
414 | 40 | while (p.owner != syms.rootPackage) { |
415 | 26 | p.owner.complete(); |
416 | 26 | if (syms.classes.get(p.getQualifiedName()) != null) { |
417 | 0 | log.error(tree.pos, |
418 | |
MsgSym.MESSAGE_PKG_CLASHES_WITH_CLASS_OF_SAME_NAME, |
419 | |
p); |
420 | |
} |
421 | 26 | p = p.owner; |
422 | |
} |
423 | |
} |
424 | |
|
425 | |
|
426 | 690 | annotateLater(tree.packageAnnotations, env, tree.packge); |
427 | |
|
428 | |
|
429 | 690 | importNamed(tree.pos(), syms.javafx_StringType.tsym, env); |
430 | 690 | importNamed(tree.pos(), syms.javafx_IntegerType.tsym, env); |
431 | 690 | importNamed(tree.pos(), syms.javafx_BooleanType.tsym, env); |
432 | 690 | importNamed(tree.pos(), syms.javafx_NumberType.tsym, env); |
433 | |
|
434 | |
|
435 | 690 | memberEnter(tree.defs, env); |
436 | 690 | } |
437 | |
|
438 | |
@Override |
439 | |
public void visitImport(JCImport tree) { |
440 | 668 | JCTree imp = tree.qualid; |
441 | 668 | Name name = TreeInfo.name(imp); |
442 | |
TypeSymbol p; |
443 | |
|
444 | 668 | if (!tree.isStatic()) { |
445 | 668 | if (tree.qualid.getTag() == SELECT) { |
446 | 664 | if (name == names.fromString("Integer")) { |
447 | 0 | log.error(tree.pos, MsgSym.MESSAGE_JAVAFX_CANNOT_IMPORT_INTEGER_PRIMITIVE_TYPE); |
448 | |
} |
449 | 664 | else if (name == names.fromString("Number")) { |
450 | 0 | log.error(tree.pos, MsgSym.MESSAGE_JAVAFX_CANNOT_IMPORT_NUMBER_PRIMITIVE_TYPE); |
451 | |
} |
452 | 664 | else if (name == names.fromString("Boolean")) { |
453 | 0 | log.error(tree.pos, MsgSym.MESSAGE_JAVAFX_CANNOT_IMPORT_BOOLEAN_PRIMITIVE_TYPE); |
454 | |
} |
455 | 664 | else if (name == names.fromString("String")) { |
456 | 0 | log.error(tree.pos, MsgSym.MESSAGE_JAVAFX_CANNOT_IMPORT_STRING_PRIMITIVE_TYPE); |
457 | |
} |
458 | |
} |
459 | |
} |
460 | |
|
461 | |
|
462 | |
|
463 | 668 | JavafxEnv<JavafxAttrContext> localEnv = env.dup(tree); |
464 | |
|
465 | |
|
466 | |
|
467 | |
|
468 | 668 | if (imp instanceof JCFieldAccess) { |
469 | 664 | JCFieldAccess s = (JCFieldAccess) imp; |
470 | 664 | p = attr. |
471 | |
attribTree(s.selected, |
472 | |
localEnv, |
473 | |
tree.staticImport ? TYP : (TYP | PCK), |
474 | |
Type.noType).tsym; |
475 | 664 | if (name == names.asterisk) { |
476 | |
|
477 | 101 | chk.checkCanonical(s.selected); |
478 | 101 | if (tree.staticImport) |
479 | 0 | importStaticAll(tree.pos, p, env); |
480 | |
else |
481 | 101 | importAll(tree.pos, p, env); |
482 | 101 | return; |
483 | |
} else { |
484 | |
|
485 | 563 | if (tree.staticImport) { |
486 | 0 | importNamedStatic(tree.pos(), p, name, localEnv); |
487 | 0 | chk.checkCanonical(s.selected); |
488 | 0 | return; |
489 | |
} |
490 | |
} |
491 | |
} |
492 | 567 | TypeSymbol c = attribImportType(imp, localEnv).tsym; |
493 | 567 | chk.checkCanonical(imp); |
494 | 567 | importNamed(tree.pos(), c, env); |
495 | 567 | } |
496 | |
|
497 | |
|
498 | |
|
499 | |
|
500 | |
|
501 | |
JavafxEnv<JavafxAttrContext> methodEnv(JFXFunctionDefinition tree, JavafxEnv<JavafxAttrContext> env) { |
502 | 1240 | Scope localScope = new Scope(tree.sym); |
503 | 1240 | localScope.next = env.info.scope; |
504 | 1240 | JavafxEnv<JavafxAttrContext> localEnv = |
505 | |
env.dup(tree, env.info.dup(localScope)); |
506 | 1240 | localEnv.outer = env; |
507 | 1240 | localEnv.enclMethod = tree; |
508 | 1240 | if ((tree.mods.flags & STATIC) != 0) localEnv.info.staticLevel++; |
509 | 1240 | return localEnv; |
510 | |
} |
511 | |
|
512 | |
@Override |
513 | |
public void scan(JCTree tree) { |
514 | 4054 | } |
515 | |
|
516 | |
@Override |
517 | |
public void visitVarDef(JCVariableDecl tree) { |
518 | 0 | assert false : "should not be here"; |
519 | 0 | } |
520 | |
|
521 | |
@Override |
522 | |
public void visitVar(JFXVar tree) { |
523 | 3283 | JavafxEnv<JavafxAttrContext> localEnv = env; |
524 | 3283 | if ((tree.mods.flags & STATIC) != 0 || |
525 | |
(env.info.scope.owner.flags() & INTERFACE) != 0) { |
526 | 44 | localEnv = env.dup(tree, env.info.dup()); |
527 | 44 | localEnv.info.staticLevel++; |
528 | |
} |
529 | |
|
530 | 3283 | Scope enclScope = JavafxEnter.enterScope(env); |
531 | 3283 | JavafxVarSymbol v = new JavafxVarSymbol(0, tree.name, null, enclScope.owner); |
532 | 3283 | attr.varSymToTree.put(v, tree); |
533 | 3283 | tree.sym = v; |
534 | 3283 | SymbolCompleter completer = new SymbolCompleter(); |
535 | 3283 | completer.env = env; |
536 | 3283 | completer.tree = tree; |
537 | 3283 | completer.attr = attr; |
538 | 3283 | v.completer = completer; |
539 | |
|
540 | 3283 | v.flags_field = chk.checkFlags(tree.pos(), tree.mods.flags, v, tree); |
541 | 3283 | if (tree.init != null) { |
542 | 1488 | v.flags_field |= HASINIT; |
543 | |
} |
544 | |
|
545 | 3283 | if (chk.checkUnique(tree.pos(), v, enclScope)) { |
546 | 3283 | chk.checkTransparentVar(tree.pos(), v, enclScope); |
547 | 3283 | enclScope.enter(v); |
548 | |
} |
549 | 3283 | annotateLater(tree.mods.annotations, localEnv, v); |
550 | 3283 | v.pos = tree.pos; |
551 | 3283 | } |
552 | |
|
553 | |
@Override |
554 | |
public void visitMethodDef(JCMethodDecl tree) { |
555 | 0 | assert false; |
556 | 0 | } |
557 | |
|
558 | 4397 | static class SymbolCompleter implements Completer { |
559 | |
JavafxEnv<JavafxAttrContext> env; |
560 | |
JCTree tree; |
561 | |
JavafxAttr attr; |
562 | |
|
563 | |
public void complete(Symbol m) throws CompletionFailure { |
564 | 4583 | if (tree instanceof JFXVar) |
565 | 3276 | attr.finishVar((JFXVar) tree, env); |
566 | 1307 | else if (attr.pt != Type.noType) { |
567 | |
|
568 | |
|
569 | |
|
570 | |
|
571 | |
|
572 | |
|
573 | |
|
574 | |
|
575 | 241 | m.completer = this; |
576 | 241 | attr.attribExpr(tree, env); |
577 | |
} |
578 | |
else |
579 | 1066 | attr.finishOperationDefinition((JFXFunctionDefinition) tree, env); |
580 | 4577 | } |
581 | |
} |
582 | |
|
583 | |
@Override |
584 | |
public void visitFunctionDefinition(JFXFunctionDefinition tree) { |
585 | 1114 | Scope enclScope = JavafxEnter.enterScope(env); |
586 | 1114 | MethodSymbol m = new MethodSymbol(0, tree.name, null, enclScope.owner); |
587 | 1114 | m.flags_field = chk.checkFlags(tree.pos(), tree.mods.flags, m, tree); |
588 | 1114 | tree.sym = m; |
589 | 1114 | enclScope.enter(m); |
590 | 1114 | SymbolCompleter completer = new SymbolCompleter(); |
591 | 1114 | completer.env = env; |
592 | 1114 | completer.tree = tree; |
593 | 1114 | completer.attr = attr; |
594 | 1114 | m.completer = completer; |
595 | 1114 | } |
596 | |
|
597 | |
@Override |
598 | |
public void visitReturn(JCReturn tree) { |
599 | 190 | super.visitReturn(tree); |
600 | 190 | if (localEnv != null) { |
601 | 0 | attr.attribStat(tree, localEnv); |
602 | |
} |
603 | 190 | } |
604 | |
|
605 | |
|
606 | |
|
607 | |
@Override |
608 | |
public void visitClassDeclaration(JFXClassDeclaration that) { |
609 | 955 | for (JCExpression superClass : that.getSupertypes()) { |
610 | 119 | Type superType = attr.attribType(superClass, env); |
611 | 119 | if (that.sym != null && that.sym instanceof JavafxClassSymbol) { |
612 | 119 | if (superType != null && superType != Type.noType) { |
613 | 119 | ((JavafxClassSymbol)that.sym).addSuperType(superType); |
614 | |
} |
615 | |
} |
616 | 119 | } |
617 | 955 | } |
618 | |
|
619 | |
|
620 | |
|
621 | |
|
622 | |
|
623 | |
Type attribImportType(JCTree tree, JavafxEnv<JavafxAttrContext> env) { |
624 | 567 | assert completionEnabled; |
625 | |
try { |
626 | |
|
627 | |
|
628 | 567 | completionEnabled = false; |
629 | 567 | return attr.attribType(tree, env); |
630 | |
} finally { |
631 | 567 | completionEnabled = true; |
632 | |
} |
633 | |
} |
634 | |
|
635 | |
|
636 | |
|
637 | |
|
638 | |
|
639 | |
|
640 | |
|
641 | |
protected |
642 | |
|
643 | |
void annotateLater(final List<JCAnnotation> annotations, |
644 | |
final JavafxEnv<JavafxAttrContext> localEnv, |
645 | |
final Symbol s) { |
646 | 4675 | if (annotations.isEmpty()) return; |
647 | 0 | if (s.kind != PCK) s.attributes_field = null; |
648 | 0 | annotate.later(new JavafxAnnotate.Annotator() { |
649 | |
@Override |
650 | |
public String toString() { |
651 | 0 | return "annotate " + annotations + " onto " + s + " in " + s.owner; |
652 | |
} |
653 | |
public void enterAnnotation() { |
654 | 0 | assert s.kind == PCK || s.attributes_field == null; |
655 | 0 | JavaFileObject prev = log.useSource(localEnv.toplevel.sourcefile); |
656 | |
try { |
657 | 0 | if (s.attributes_field != null && |
658 | |
s.attributes_field.nonEmpty() && |
659 | |
annotations.nonEmpty()) |
660 | 0 | log.error(annotations.head.pos, |
661 | |
MsgSym.MESSAGE_ALREADY_ANNOTATED, |
662 | |
JavafxResolve.kindName(s), s); |
663 | 0 | enterAnnotations(annotations, localEnv, s); |
664 | |
} finally { |
665 | 0 | log.useSource(prev); |
666 | 0 | } |
667 | 0 | } |
668 | |
}); |
669 | 0 | } |
670 | |
|
671 | |
|
672 | |
|
673 | |
|
674 | |
|
675 | |
private boolean hasDeprecatedAnnotation(List<JCAnnotation> annotations) { |
676 | 702 | for (List<JCAnnotation> al = annotations; al.nonEmpty(); al = al.tail) { |
677 | 0 | JCAnnotation a = al.head; |
678 | 0 | if (a.annotationType.type == syms.deprecatedType && a.args.isEmpty()) |
679 | 0 | return true; |
680 | |
} |
681 | 702 | return false; |
682 | |
} |
683 | |
|
684 | |
|
685 | |
private void enterAnnotations(List<JCAnnotation> annotations, |
686 | |
JavafxEnv<JavafxAttrContext> env, |
687 | |
Symbol s) { |
688 | 0 | ListBuffer<Attribute.Compound> buf = |
689 | |
new ListBuffer<Attribute.Compound>(); |
690 | 0 | Set<TypeSymbol> annotated = new HashSet<TypeSymbol>(); |
691 | 0 | if (!skipAnnotations) |
692 | 0 | for (List<JCAnnotation> al = annotations; al.nonEmpty(); al = al.tail) { |
693 | 0 | JCAnnotation a = al.head; |
694 | 0 | Attribute.Compound c = annotate.enterAnnotation(a, |
695 | |
syms.annotationType, |
696 | |
env); |
697 | 0 | if (c == null) continue; |
698 | 0 | buf.append(c); |
699 | |
|
700 | 0 | if (!c.type.isErroneous() |
701 | |
&& s.owner.kind != MTH |
702 | |
&& types.isSameType(c.type, syms.deprecatedType)) |
703 | 0 | s.flags_field |= Flags.DEPRECATED; |
704 | 0 | if (!annotated.add(a.type.tsym)) |
705 | 0 | log.error(a.pos, MsgSym.MESSAGE_DUPLICATE_ANNOTATION); |
706 | |
} |
707 | 0 | s.attributes_field = buf.toList(); |
708 | 0 | } |
709 | |
|
710 | |
|
711 | |
protected |
712 | |
|
713 | |
|
714 | |
void annotateDefaultValueLater(final JCExpression defaultValue, |
715 | |
final JavafxEnv<JavafxAttrContext> localEnv, |
716 | |
final MethodSymbol m) { |
717 | 0 | annotate.later(new JavafxAnnotate.Annotator() { |
718 | |
@Override |
719 | |
public String toString() { |
720 | 0 | return "annotate " + m.owner + "." + |
721 | |
m + " default " + defaultValue; |
722 | |
} |
723 | |
public void enterAnnotation() { |
724 | 0 | JavaFileObject prev = log.useSource(localEnv.toplevel.sourcefile); |
725 | |
try { |
726 | 0 | enterDefaultValue(defaultValue, localEnv, m); |
727 | |
} finally { |
728 | 0 | log.useSource(prev); |
729 | 0 | } |
730 | 0 | } |
731 | |
}); |
732 | 0 | } |
733 | |
|
734 | |
|
735 | |
private void enterDefaultValue(final JCExpression defaultValue, |
736 | |
final JavafxEnv<JavafxAttrContext> localEnv, |
737 | |
final MethodSymbol m) { |
738 | 0 | m.defaultValue = annotate.enterAttributeValue(m.type.getReturnType(), |
739 | |
defaultValue, |
740 | |
localEnv); |
741 | 0 | } |
742 | |
|
743 | |
|
744 | |
|
745 | |
|
746 | |
|
747 | |
|
748 | |
|
749 | |
|
750 | |
public void complete(Symbol sym) throws CompletionFailure { |
751 | |
|
752 | 706 | if (!completionEnabled) { |
753 | |
|
754 | 4 | assert (sym.flags() & Flags.COMPOUND) == 0; |
755 | 4 | sym.completer = this; |
756 | 4 | return; |
757 | |
} |
758 | |
|
759 | 702 | ClassSymbol c = (ClassSymbol)sym; |
760 | 702 | ClassType ct = (ClassType)c.type; |
761 | 702 | JavafxEnv<JavafxAttrContext> env = enter.typeEnvs.get(c); |
762 | 702 | JFXClassDeclaration tree = (JFXClassDeclaration)env.tree; |
763 | 702 | boolean wasFirst = isFirst; |
764 | 702 | isFirst = false; |
765 | |
|
766 | 702 | JavaFileObject prev = log.useSource(env.toplevel.sourcefile); |
767 | |
try { |
768 | |
|
769 | 702 | halfcompleted.append(env); |
770 | |
|
771 | |
|
772 | |
|
773 | 702 | if (c.owner.kind == PCK) { |
774 | 385 | memberEnter(env.toplevel, env.enclosing(JCTree.TOPLEVEL)); |
775 | 385 | todo.append(env); |
776 | |
} |
777 | |
|
778 | |
|
779 | 702 | c.flags_field |= UNATTRIBUTED; |
780 | |
|
781 | 702 | if (c.owner.kind == TYP) |
782 | 291 | c.owner.complete(); |
783 | |
|
784 | |
|
785 | 702 | JavafxEnv<JavafxAttrContext> baseEnv = baseEnv(tree, env); |
786 | |
|
787 | 702 | Type supertype = null, solesupertype = null; |
788 | 702 | ListBuffer<Type> interfaces = new ListBuffer<Type>(); |
789 | 702 | Set<Type> interfaceSet = new HashSet<Type>(); |
790 | |
{ |
791 | 702 | ListBuffer<JCExpression> extending = ListBuffer.<JCExpression>lb(); |
792 | 702 | ListBuffer<JCExpression> implementing = ListBuffer.<JCExpression>lb(); |
793 | 702 | boolean compound = (tree.getModifiers().flags & Flags.FINAL) == 0; |
794 | 702 | for (JCExpression stype : tree.getSupertypes()) { |
795 | 158 | Type st = attr.attribType(stype, env); |
796 | |
|
797 | 158 | if (st.isInterface()) { |
798 | 26 | implementing.append(stype); |
799 | |
} else { |
800 | 132 | solesupertype = extending.isEmpty() ? st : null; |
801 | 132 | extending.append(stype); |
802 | 132 | if ((st.tsym.flags_field & JavafxFlags.COMPOUND_CLASS) == 0) { |
803 | 29 | compound = false; |
804 | 29 | supertype = st; |
805 | |
} |
806 | |
else { |
807 | 103 | interfaces.append(st); |
808 | 103 | chk.checkNotRepeated(stype.pos(), types.erasure(st), interfaceSet); |
809 | |
} |
810 | |
} |
811 | 158 | } |
812 | 702 | if (compound) |
813 | 630 | c.flags_field |= JavafxFlags.COMPOUND_CLASS; |
814 | |
|
815 | 702 | tree.setDifferentiatedExtendingImplementing(extending.toList(), implementing.toList()); |
816 | |
} |
817 | |
|
818 | 702 | if (supertype == null) |
819 | 674 | supertype = |
820 | |
((tree.mods.flags & Flags.ENUM) != 0 && !target.compilerBootstrap(c)) |
821 | |
? attr.attribBase(enumBase(tree.pos, c), baseEnv, |
822 | |
true, false, false) |
823 | |
: (c.fullname == names.java_lang_Object) |
824 | |
? Type.noType |
825 | |
: syms.objectType; |
826 | 702 | ct.supertype_field = supertype; |
827 | |
|
828 | |
|
829 | 702 | List<JCExpression> interfaceTrees = tree.getImplementing(); |
830 | 702 | if ((tree.mods.flags & Flags.ENUM) != 0 && target.compilerBootstrap(c)) { |
831 | |
|
832 | 0 | interfaceTrees = |
833 | |
interfaceTrees.prepend(make.Type(new ClassType(syms.comparableType.getEnclosingType(), |
834 | |
List.of(c.type), |
835 | |
syms.comparableType.tsym))); |
836 | |
|
837 | 0 | interfaceTrees = |
838 | |
interfaceTrees.prepend(make.Type(syms.serializableType)); |
839 | |
} |
840 | 702 | for (JCExpression iface : interfaceTrees) { |
841 | 26 | Type i = attr.attribBase(iface, baseEnv, false, true, true); |
842 | 26 | if (i.tag == CLASS) { |
843 | 26 | interfaces.append(i); |
844 | 26 | chk.checkNotRepeated(iface.pos(), types.erasure(i), interfaceSet); |
845 | |
} |
846 | 26 | } |
847 | 702 | if ((c.flags_field & ANNOTATION) != 0) |
848 | 0 | ct.interfaces_field = List.of(syms.annotationType); |
849 | |
else |
850 | 702 | ct.interfaces_field = interfaces.toList(); |
851 | |
|
852 | 702 | if (c.fullname == names.java_lang_Object) { |
853 | 0 | if (tree.getExtending().head != null) { |
854 | 0 | chk.checkNonCyclic(tree.getExtending().head.pos(), |
855 | |
supertype); |
856 | 0 | ct.supertype_field = Type.noType; |
857 | |
} |
858 | 0 | else if (tree.getImplementing().nonEmpty()) { |
859 | 0 | chk.checkNonCyclic(tree.getImplementing().head.pos(), |
860 | |
ct.interfaces_field.head); |
861 | 0 | ct.interfaces_field = List.nil(); |
862 | |
} |
863 | |
} |
864 | |
|
865 | |
|
866 | |
|
867 | |
|
868 | |
|
869 | 702 | attr.attribAnnotationTypes(tree.mods.annotations, baseEnv); |
870 | 702 | if (hasDeprecatedAnnotation(tree.mods.annotations)) |
871 | 0 | c.flags_field |= DEPRECATED; |
872 | 702 | annotateLater(tree.mods.annotations, baseEnv, c); |
873 | |
|
874 | 702 | attr.attribTypeVariables(tree.getEmptyTypeParameters(), baseEnv); |
875 | |
|
876 | 702 | chk.checkNonCyclic(tree.pos(), c.type); |
877 | |
|
878 | |
|
879 | |
|
880 | 702 | if ((c.flags_field & INTERFACE) == 0) { |
881 | 702 | VarSymbol thisSym = |
882 | |
new VarSymbol(FINAL | HASINIT, names._this, c.type, c); |
883 | 702 | thisSym.pos = Position.FIRSTPOS; |
884 | 702 | env.info.scope.enter(thisSym); |
885 | 702 | if (ct.supertype_field.tag == CLASS && solesupertype != null) { |
886 | 98 | VarSymbol superSym = |
887 | |
new VarSymbol(FINAL | HASINIT, names._super, |
888 | |
solesupertype, c); |
889 | 98 | superSym.pos = Position.FIRSTPOS; |
890 | 98 | env.info.scope.enter(superSym); |
891 | |
} |
892 | |
} |
893 | |
|
894 | |
|
895 | |
|
896 | |
|
897 | 702 | if (checkClash && |
898 | |
c.owner.kind == PCK && c.owner != syms.unnamedPackage && |
899 | |
reader.packageExists(c.fullname)) |
900 | |
{ |
901 | 0 | log.error(tree.pos, MsgSym.MESSAGE_CLASH_WITH_PKG_OF_SAME_NAME, c); |
902 | |
} |
903 | |
|
904 | 0 | } catch (CompletionFailure ex) { |
905 | 0 | chk.completionError(tree.pos(), ex); |
906 | |
} finally { |
907 | 702 | log.useSource(prev); |
908 | 702 | } |
909 | |
|
910 | |
|
911 | |
|
912 | 702 | if (wasFirst) { |
913 | |
try { |
914 | 1337 | while (halfcompleted.nonEmpty()) { |
915 | 702 | finish(halfcompleted.next()); |
916 | |
} |
917 | |
} finally { |
918 | 635 | isFirst = true; |
919 | 635 | } |
920 | |
|
921 | |
|
922 | 635 | annotate.flush(); |
923 | |
} |
924 | 702 | } |
925 | |
|
926 | |
private JavafxEnv<JavafxAttrContext> baseEnv(JFXClassDeclaration tree, JavafxEnv<JavafxAttrContext> env) { |
927 | 702 | Scope typaramScope = new Scope(tree.sym); |
928 | 702 | if (tree.getEmptyTypeParameters() != null) |
929 | 702 | for (List<JCTypeParameter> typarams = tree.getEmptyTypeParameters(); |
930 | 702 | typarams.nonEmpty(); |
931 | 0 | typarams = typarams.tail) |
932 | 0 | typaramScope.enter(typarams.head.type.tsym); |
933 | 702 | JavafxEnv<JavafxAttrContext> outer = env.outer; |
934 | 702 | JavafxEnv<JavafxAttrContext> localEnv = outer.dup(tree, outer.info.dup(typaramScope)); |
935 | 702 | localEnv.baseClause = true; |
936 | 702 | localEnv.outer = outer; |
937 | 702 | localEnv.info.isSelfCall = false; |
938 | 702 | return localEnv; |
939 | |
} |
940 | |
|
941 | |
|
942 | |
|
943 | |
|
944 | |
private void finish(JavafxEnv<JavafxAttrContext> env) { |
945 | 702 | JavaFileObject prev = log.useSource(env.toplevel.sourcefile); |
946 | |
try { |
947 | 702 | JFXClassDeclaration tree = (JFXClassDeclaration)env.tree; |
948 | 702 | memberEnter(tree.getMembers(), env); |
949 | |
} finally { |
950 | 702 | log.useSource(prev); |
951 | 702 | } |
952 | 702 | } |
953 | |
|
954 | |
|
955 | |
|
956 | |
|
957 | |
|
958 | |
private JCExpression enumBase(int pos, ClassSymbol c) { |
959 | 0 | JCExpression result = make.at(pos). |
960 | |
TypeApply(make.QualIdent(syms.enumSym), |
961 | |
List.<JCExpression>of(make.Type(c.type))); |
962 | 0 | return result; |
963 | |
} |
964 | |
|
965 | |
|
966 | |
} |