Coverage Report - com.sun.tools.javafx.comp.JavafxMemberEnter
 
Classes in this File Line Coverage Branch Coverage Complexity
JavafxMemberEnter
72%
231/320
53%
100/188
0
JavafxMemberEnter$1
0%
0/13
0%
0/18
0
JavafxMemberEnter$2
0%
0/16
0%
0/18
0
JavafxMemberEnter$3
0%
0/14
0%
0/18
0
JavafxMemberEnter$4
0%
0/25
0%
0/22
0
JavafxMemberEnter$5
0%
0/10
0%
0/12
0
JavafxMemberEnter$6
0%
0/7
N/A
0
JavafxMemberEnter$SymbolCompleter
100%
8/8
100%
4/4
0
 
 1  
 /*
 2  
  * Copyright 1999-2007 Sun Microsystems, Inc.  All Rights Reserved.
 3  
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 4  
  *
 5  
  * This code is free software; you can redistribute it and/or modify it
 6  
  * under the terms of the GNU General Public License version 2 only, as
 7  
  * published by the Free Software Foundation.  Sun designates this
 8  
  * particular file as subject to the "Classpath" exception as provided
 9  
  * by Sun in the LICENSE file that accompanied this code.
 10  
  *
 11  
  * This code is distributed in the hope that it will be useful, but WITHOUT
 12  
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 13  
  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 14  
  * version 2 for more details (a copy is included in the LICENSE file that
 15  
  * accompanied this code).
 16  
  *
 17  
  * You should have received a copy of the GNU General Public License version
 18  
  * 2 along with this work; if not, write to the Free Software Foundation,
 19  
  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 20  
  *
 21  
  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 22  
  * CA 95054 USA or visit www.sun.com if you need additional information or
 23  
  * have any questions.
 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  
  * Add local declaratuions to current environment.
 57  
  * The main entry point is {@code memberEnter}, which is called from
 58  
  * {@link JavafxAttr} when {@code visit}-ing a tree that contains local
 59  
  * declarations.
 60  
  *
 61  
  *  <p><b>This is NOT part of any API supported by Sun Microsystems.  If
 62  
  *  you write code that depends on this, you do so at your own risk.
 63  
  *  This code and its internal interfaces are subject to change or
 64  
  *  deletion without notice.</b>
 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  
 // JavaFX change
 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  
     /** A queue for classes whose members still need to be entered into the
 119  
      *  symbol table.
 120  
      */
 121  399
     ListBuffer<JavafxEnv<JavafxAttrContext>> halfcompleted = new ListBuffer<JavafxEnv<JavafxAttrContext>>();
 122  
 
 123  
     /** Set to true only when the first of a set of classes is
 124  
      *  processed from the halfcompleted queue.
 125  
      */
 126  399
     boolean isFirst = true;
 127  
 
 128  
     /** A flag to disable completion from time to time during member
 129  
      *  enter, as we only need to look up types.  This avoids
 130  
      *  unnecessarily deep recursion.
 131  
      */
 132  399
     boolean completionEnabled = true;
 133  
 
 134  
     /* ---------- Processing import clauses ----------------
 135  
      */
 136  
 
 137  
     /** Import all classes of a class or package on demand.
 138  
      *  @param pos           Position to be used for error reporting.
 139  
      *  @param tsym          The class or package the members of which are imported.
 140  
      *  @param toScope   The (import) scope in which imported classes
 141  
      *               are entered.
 142  
      */
 143  
 // JavaFX change
 144  
     protected void importAll(int pos,
 145  
                            final TypeSymbol tsym,
 146  
                            JavafxEnv<JavafxAttrContext> env) {
 147  
         // Check that packages imported from exist (JLS ???).
 148  101
         if (tsym.kind == PCK && tsym.members().elems == null && !tsym.exists()) {
 149  
             // If we can't find java.lang, exit immediately.
 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  
     /** Import all static members of a class or package on demand.
 166  
      *  @param pos           Position to be used for error reporting.
 167  
      *  @param tsym          The class or package the members of which are imported.
 168  
      *  @param toScope   The (import) scope in which imported classes
 169  
      *               are entered.
 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  
         // enter imported types immediately
 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  
                 // also import inherited names
 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  
         // enter non-types before annotations that might use them
 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  
                 // also import inherited names
 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  
     // is the sym accessible everywhere in packge?
 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  
     /** Import statics types of a given name.  Non-types are handled in Attr.
 254  
      *  @param pos           Position to be used for error reporting.
 255  
      *  @param tsym          The class from which the name is imported.
 256  
      *  @param name          The (simple) name being imported.
 257  
      *  @param env           The environment containing the named import
 258  
      *                  scope to add to.
 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  
         // enter imported types immediately
 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  
                 // also import inherited names
 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  
         // enter non-types before annotations that might use them
 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  
                 // also import inherited names
 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  
     /** Import given class.
 349  
      *  @param pos           Position to be used for error reporting.
 350  
      *  @param tsym          The class to be imported.
 351  
      *  @param env           The environment containing the named import
 352  
      *                  scope to add to.
 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  
  * Visitor methods for member enter
 362  
  *********************************************************************/
 363  
 
 364  
     /** Visitor argument: the current environment
 365  
      */
 366  
     protected JavafxEnv<JavafxAttrContext> env;
 367  
 
 368  
     /** Enter field and method definitions and process import
 369  
      *  clauses, catching any completion failure exceptions.
 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  
     /** Enter members from a list of trees.
 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  
             // we must have already processed this toplevel
 407  0
             return;
 408  
         }
 409  
 
 410  
         // check that no class exists with same fully qualified name as
 411  
         // toplevel package
 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(); // enter all class members of p
 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  
         // process package annotations
 426  690
         annotateLater(tree.packageAnnotations, env, tree.packge);
 427  
 
 428  
         // Import-on-demand the JavaFX types 
 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  
         // Process all import clauses.
 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")) { // TODO: use the constant in the new NameTable when available.
 447  0
                     log.error(tree.pos, MsgSym.MESSAGE_JAVAFX_CANNOT_IMPORT_INTEGER_PRIMITIVE_TYPE);
 448  
                 }
 449  664
                 else if (name == names.fromString("Number")) { // TODO: use the constant in the new NameTable when available.
 450  0
                     log.error(tree.pos, MsgSym.MESSAGE_JAVAFX_CANNOT_IMPORT_NUMBER_PRIMITIVE_TYPE);
 451  
                 }
 452  664
                 else if (name == names.fromString("Boolean")) { // TODO: use the constant in the new NameTable when available.
 453  0
                     log.error(tree.pos, MsgSym.MESSAGE_JAVAFX_CANNOT_IMPORT_BOOLEAN_PRIMITIVE_TYPE);
 454  
                 }
 455  664
                 else if (name == names.fromString("String")) { // TODO: use the constant in the new NameTable when available.
 456  0
                     log.error(tree.pos, MsgSym.MESSAGE_JAVAFX_CANNOT_IMPORT_STRING_PRIMITIVE_TYPE);
 457  
                 }
 458  
             }
 459  
         }
 460  
         
 461  
         // Create a local environment pointing to this tree to disable
 462  
         // effects of other imports in Resolve.findGlobalType
 463  668
         JavafxEnv<JavafxAttrContext> localEnv = env.dup(tree);
 464  
 
 465  
         // Attribute qualifying package or class.
 466  
         // The code structure here is rather ugly, but we'll
 467  
         // fix it when we do implicit-static-import.  FIXME.
 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  
                 // Import on demand.
 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  
                 // Named type import.
 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  
     /** Create a fresh environment for method bodies.
 498  
      *  @param tree     The method definition.
 499  
      *  @param env      The environment current outside of the method definition.
 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  
                 // finishOperationDefinition makes use of the expected type pt.
 568  
                 // This is useful when coming from visitFunctionValue - i.e.
 569  
                 // attributing an anonymous function.  However, using the
 570  
                 // expected type from a random call-site (which can happen if
 571  
                 // we're called via complete) is a bit too flakey.
 572  
                 // (ML can do it, because they unify across all the call-sites.)
 573  
                 // This is a trick to run finishOperationDefinition, but in a
 574  
                 // context where we're cleared the expected type attr.pt.
 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  
 // Javafx modification
 606  
     // Begin JavaFX trees
 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  
  * Type completion
 621  
  *********************************************************************/
 622  
 
 623  
     Type attribImportType(JCTree tree, JavafxEnv<JavafxAttrContext> env) {
 624  567
         assert completionEnabled;
 625  
         try {
 626  
             // To prevent deep recursion, suppress completion of some
 627  
             // types.
 628  567
             completionEnabled = false;
 629  567
             return attr.attribType(tree, env);
 630  
         } finally {
 631  567
             completionEnabled = true;
 632  
         }
 633  
     }
 634  
 
 635  
 /* ********************************************************************
 636  
  * Annotation processing
 637  
  *********************************************************************/
 638  
 
 639  
     /** Queue annotations for later processing. */
 640  
 // JavaFX change
 641  
     protected
 642  
 // JavaFX change
 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; // mark it incomplete for now
 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  
      * Check if a list of annotations contains a reference to
 673  
      * java.lang.Deprecated.
 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  
     /** Enter a set of annotations. */
 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  
             // Note: @Deprecated has no effect on local variables and parameters
 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  
 // Javafx change
 711  
     protected
 712  
 // Javafx change
 713  
     /** Queue processing of an attribute default value. */
 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  
     /** Enter a default value for an attribute method. */
 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  
  * Source completer
 745  
  *********************************************************************/
 746  
 
 747  
     /** Complete entering a class.
 748  
      *  @param sym         The symbol of the class to be completed.
 749  
      */
 750  
     public void complete(Symbol sym) throws CompletionFailure {
 751  
         // Suppress some (recursive) MemberEnter invocations
 752  706
         if (!completionEnabled) {
 753  
             // Re-install same completer for next time around and return.
 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  
             // Save class environment for later member enter (2) processing.
 769  702
             halfcompleted.append(env);
 770  
 
 771  
             // If this is a toplevel-class, make sure any preceding import
 772  
             // clauses have been seen.
 773  702
             if (c.owner.kind == PCK) {
 774  385
                 memberEnter(env.toplevel, env.enclosing(JCTree.TOPLEVEL));
 775  385
                 todo.append(env);
 776  
             }
 777  
 
 778  
             // Mark class as not yet attributed.
 779  702
             c.flags_field |= UNATTRIBUTED;
 780  
 
 781  702
             if (c.owner.kind == TYP)
 782  291
                 c.owner.complete();
 783  
 
 784  
             // create an environment for evaluating the base clauses
 785  702
             JavafxEnv<JavafxAttrContext> baseEnv = baseEnv(tree, env);
 786  
             //TODO: solesupertype implies a bug
 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  
             // Determine interfaces.
 829  702
             List<JCExpression> interfaceTrees = tree.getImplementing();
 830  702
             if ((tree.mods.flags & Flags.ENUM) != 0 && target.compilerBootstrap(c)) {
 831  
                 // add interface Comparable<T>
 832  0
                 interfaceTrees =
 833  
                     interfaceTrees.prepend(make.Type(new ClassType(syms.comparableType.getEnclosingType(),
 834  
                                                                    List.of(c.type),
 835  
                                                                    syms.comparableType.tsym)));
 836  
                 // add interface Serializable
 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  
             // Annotations.
 866  
             // In general, we cannot fully process annotations yet,  but we
 867  
             // can attribute the annotation types and then check to see if the
 868  
             // @Deprecated annotation is present.
 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  
             // If this is a class, enter symbols for this and super into
 879  
             // current scope.
 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  
             // check that no package exists with same fully qualified name,
 895  
             // but admit classes in the unnamed package which have the same
 896  
             // name as a top-level package.
 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  
         // Enter all member fields and methods of a set of half completed
 911  
         // classes in a second phase.
 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  
             // commit pending annotations
 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; // the base clause can't see members of this class
 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  
     /** Enter member fields and methods of a class
 942  
      *  @param env        the environment current for the class block.
 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  
     /** Generate a base clause for an enum type.
 955  
      *  @param pos              The position for trees and diagnostics, if any
 956  
      *  @param c                The class symbol of the enum
 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  
 }