Coverage Report - com.sun.tools.javafx.comp.JavafxEnter
 
Classes in this File Line Coverage Branch Coverage Complexity
JavafxEnter
80%
133/167
52%
47/90
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 static com.sun.tools.javac.code.Flags.*;
 29  
 import static com.sun.tools.javac.code.Kinds.*;
 30  
 import com.sun.tools.javac.code.*;
 31  
 import com.sun.tools.javac.code.Type.*;
 32  
 import com.sun.tools.javac.code.Symbol.*;
 33  
 import com.sun.tools.javac.code.Type.ClassType;
 34  
 import com.sun.tools.javac.code.Type.ErrorType;
 35  
 import com.sun.tools.javac.tree.JCTree;
 36  
 import com.sun.tools.javac.tree.JCTree.*;
 37  
 import com.sun.tools.javac.jvm.*;
 38  
 import com.sun.tools.javac.util.*;
 39  
 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
 40  
 
 41  
 import com.sun.tools.javafx.tree.*;
 42  
 import com.sun.tools.javafx.code.*;
 43  
 import com.sun.tools.javafx.util.MsgSym;
 44  
 
 45  
 import java.util.Map;
 46  
 import java.util.HashMap;
 47  
 import javax.tools.JavaFileObject;
 48  
 import javax.tools.JavaFileManager;
 49  
 
 50  
 public class JavafxEnter extends JavafxTreeScanner {
 51  12
     protected static final Context.Key<JavafxEnter> javafxEnterKey =
 52  
         new Context.Key<JavafxEnter>();
 53  
 
 54  
     private final Log log;
 55  
     private final JavafxSymtab syms;
 56  
     private final JavafxCheck chk;
 57  
     private final JavafxTreeMaker make;
 58  
     private final ClassReader reader;
 59  
     private final JavafxAnnotate annotate;
 60  
     private final JavafxMemberEnter memberEnter;
 61  
     private final Lint lint;
 62  
     private final JavaFileManager fileManager;
 63  
     private final JavafxTodo todo;
 64  
     private final JavafxTypes types;
 65  
     private JavafxModuleBuilder javafxModuleBuilder;
 66  
     
 67  
     public static JavafxEnter instance(Context context) {
 68  1197
         JavafxEnter instance = context.get(javafxEnterKey);
 69  1197
         if (instance == null)
 70  399
             instance = new JavafxEnter(context);
 71  1197
         return instance;
 72  
     }
 73  
 
 74  399
     protected JavafxEnter(Context context) {
 75  399
         context.put(javafxEnterKey, this);
 76  
 
 77  399
         log = Log.instance(context);
 78  399
         reader = ClassReader.instance(context);
 79  399
         make = (JavafxTreeMaker)JavafxTreeMaker.instance(context);
 80  399
         syms = (JavafxSymtab)JavafxSymtab.instance(context);
 81  399
         chk = JavafxCheck.instance(context);
 82  399
         memberEnter = JavafxMemberEnter.instance(context);
 83  399
         annotate = JavafxAnnotate.instance(context);
 84  399
         lint = Lint.instance(context);
 85  399
         javafxModuleBuilder = JavafxModuleBuilder.instance(context);
 86  
 
 87  399
         predefClassDef = make.ClassDeclaration(
 88  
             make.Modifiers(PUBLIC),
 89  
             syms.predefClass.name, List.<JCExpression>nil(), null);
 90  399
         predefClassDef.sym = syms.predefClass;
 91  399
         todo = JavafxTodo.instance(context);
 92  399
         fileManager = context.get(JavaFileManager.class);
 93  399
         types = JavafxTypes.instance(context);
 94  399
     }
 95  
 
 96  
     /** A hashtable mapping classes and packages to the environments current
 97  
      *  at the points of their definitions.
 98  
      */
 99  399
     Map<TypeSymbol,JavafxEnv<JavafxAttrContext>> typeEnvs =
 100  
             new HashMap<TypeSymbol,JavafxEnv<JavafxAttrContext>>();
 101  
 
 102  
     /** Visitor method: Scan a single node.
 103  
      */
 104  
     @Override
 105  
     public void scan(JCTree tree) {
 106  57915
         if(tree!=null) tree.accept(this);
 107  57915
     }
 108  
 
 109  
     /** Visitor method: scan a list of nodes.
 110  
      */
 111  
     @Override
 112  
     public void scan(List<? extends JCTree> trees) {
 113  12375
         if (trees != null)
 114  23310
         for (List<? extends JCTree> l = trees; l.nonEmpty(); l = l.tail)
 115  10935
             scan(l.head);
 116  12375
     }
 117  
 
 118  
     /** Accessor for typeEnvs
 119  
      */
 120  
     public JavafxEnv<JavafxAttrContext> getEnv(TypeSymbol sym) {
 121  0
         return typeEnvs.get(sym);
 122  
     }
 123  
     
 124  
     /** The queue of all classes that might still need to be completed;
 125  
      *        saved and initialized by main().
 126  
      */
 127  
 // JavaFX change
 128  
     protected
 129  
 // JavaFX change
 130  
     ListBuffer<ClassSymbol> uncompleted;
 131  
 
 132  
     /** A dummy class to serve as enclClass for toplevel environments.
 133  
      */
 134  
     private JFXClassDeclaration predefClassDef;
 135  
 
 136  
 /* ************************************************************************
 137  
  * environment construction
 138  
  *************************************************************************/
 139  
 
 140  
 
 141  
     /** Create a fresh environment for class bodies.
 142  
      *        This will create a fresh scope for local symbols of a class, referred
 143  
      *        to by the environments info.scope field.
 144  
      *        This scope will contain
 145  
      *          - symbols for this and super
 146  
      *          - symbols for any type parameters
 147  
      *        In addition, it serves as an anchor for scopes of methods and initializers
 148  
      *        which are nested in this scope via Scope.dup().
 149  
      *        This scope should not be confused with the members scope of a class.
 150  
      *
 151  
      *        @param tree        The class definition.
 152  
      *        @param env        The environment current outside of the class definition.
 153  
      */
 154  
     public static JavafxEnv<JavafxAttrContext> classEnv(JFXClassDeclaration tree, JavafxEnv<JavafxAttrContext> env) {
 155  702
         JavafxEnv<JavafxAttrContext> localEnv =
 156  
             env.dup(tree, env.info.dup(new Scope(tree.sym)));
 157  702
         localEnv.enclClass = tree;
 158  702
         localEnv.outer = env;
 159  702
         localEnv.info.isSelfCall = false;
 160  702
         localEnv.info.lint = null; // leave this to be filled in by Attr, 
 161  
                                    // when annotations have been processed
 162  702
         return localEnv;
 163  
     }
 164  
 
 165  
     /** Create a fresh environment for toplevels.
 166  
      *        @param tree        The toplevel tree.
 167  
      */
 168  
     JavafxEnv<JavafxAttrContext> topLevelEnv(JCCompilationUnit tree) {
 169  690
         JavafxEnv<JavafxAttrContext> localEnv = new JavafxEnv<JavafxAttrContext>(tree, new JavafxAttrContext());
 170  690
         localEnv.toplevel = tree;
 171  690
         localEnv.enclClass = predefClassDef;
 172  690
         tree.namedImportScope = new Scope.ImportScope(tree.packge);
 173  690
         tree.starImportScope = new Scope.ImportScope(tree.packge);
 174  690
         localEnv.info.scope = tree.namedImportScope;
 175  690
         localEnv.info.lint = lint;
 176  690
         return localEnv;
 177  
     } 
 178  
 
 179  
     /** The scope in which a member definition in environment env is to be entered
 180  
      *        This is usually the environment's scope, except for class environments,
 181  
      *        where the local scope is for type variables, and the this and super symbol
 182  
      *        only, and members go into the class member scope.
 183  
      */
 184  
     public static Scope enterScope(JavafxEnv<JavafxAttrContext> env) {
 185  5940
         return (env.tree.getTag() == JavafxTag.CLASS_DEF)
 186  
             ? ((JFXClassDeclaration) env.tree).sym.members_field
 187  
             : env.info.scope;
 188  
     }
 189  
 
 190  
 /* ************************************************************************
 191  
  * Visitor methods for phase 1: class enter
 192  
  *************************************************************************/
 193  
 
 194  
     /** Visitor argument: the current environment.
 195  
      */
 196  
     protected JavafxEnv<JavafxAttrContext> env;
 197  
 
 198  
     /** Visitor result: the computed type.
 199  
      */
 200  
 // JavaFX change
 201  
     protected
 202  
 // JavaFX change
 203  
     Type result;
 204  
 
 205  
     /** Visitor method: enter all classes in given tree, catching any
 206  
      *        completion failure exceptions. Return the tree's type.
 207  
      *
 208  
      *        @param tree    The tree to be visited.
 209  
      *        @param env     The environment visitor argument.
 210  
      */
 211  
     Type classEnter(JCTree tree, JavafxEnv<JavafxAttrContext> env) {
 212  3176
         JavafxEnv<JavafxAttrContext> prevEnv = this.env;
 213  
         try {
 214  3176
             this.env = env;
 215  3176
             tree.accept(this);
 216  3176
             return result;
 217  0
         }  catch (CompletionFailure ex) {
 218  0
             return chk.completionError(tree.pos(), ex);
 219  
         } finally {
 220  3176
             this.env = prevEnv;
 221  
         }
 222  
     }
 223  
 
 224  
     /** Visitor method: enter classes of a list of trees, returning a list of types.
 225  
      */
 226  
 // JavaFX change
 227  
     protected
 228  
 // JavaFX change
 229  
     <T extends JCTree> List<Type> classEnter(List<T> trees, JavafxEnv<JavafxAttrContext> env) {
 230  2172
         ListBuffer<Type> ts = new ListBuffer<Type>();
 231  5322
         for (List<T> l = trees; l.nonEmpty(); l = l.tail)
 232  3150
             ts.append(classEnter(l.head, env));
 233  2172
         return ts.toList();
 234  
     }
 235  
 
 236  
     @Override
 237  
     public void visitTopLevel(JCCompilationUnit tree) {
 238  385
         JavaFileObject prev = log.useSource(tree.sourcefile);
 239  385
         boolean addEnv = false;
 240  385
         boolean isPkgInfo = tree.sourcefile.isNameCompatible("package-info",
 241  
                                                              JavaFileObject.Kind.SOURCE);
 242  385
         if (tree.pid != null) {
 243  9
             tree.packge = reader.enterPackage(JavafxTreeInfo.fullName(tree.pid));
 244  9
             if (tree.packageAnnotations.nonEmpty()) {
 245  0
                 if (isPkgInfo) {
 246  0
                     addEnv = true;
 247  
                 } else {
 248  0
                     log.error(tree.packageAnnotations.head.pos(),
 249  
                               MsgSym.MESSAGE_PKG_ANNOTATIONS_SB_IN_PACKAGE_INFO_JAVA);
 250  
                 }
 251  
             }
 252  
         } else {
 253  376
             tree.packge = syms.unnamedPackage;
 254  
         }
 255  385
         tree.packge.complete(); // Find all classes in package.
 256  385
         JavafxEnv<JavafxAttrContext> localEnv = topLevelEnv(tree);
 257  
         
 258  385
         javafxModuleBuilder.preProcessJfxTopLevel(tree);
 259  
 
 260  
         // Save environment of package-info.java file.
 261  385
         if (isPkgInfo) {
 262  0
             JavafxEnv<JavafxAttrContext> env0 = typeEnvs.get(tree.packge);
 263  0
             if (env0 == null) {
 264  0
                 typeEnvs.put(tree.packge, localEnv);
 265  
             } else {
 266  0
                 JCCompilationUnit tree0 = env0.toplevel;
 267  0
                 if (!fileManager.isSameFile(tree.sourcefile, tree0.sourcefile)) {
 268  0
                     log.warning(tree.pid != null ? tree.pid.pos()
 269  
                                                  : null,
 270  
                                 MsgSym.MESSAGE_PKG_INFO_ALREADY_SEEN,
 271  
                                 tree.packge);
 272  0
                     if (addEnv || (tree0.packageAnnotations.isEmpty() &&
 273  
                                    tree.docComments != null &&
 274  
                                    tree.docComments.get(tree) != null)) {
 275  0
                         typeEnvs.put(tree.packge, localEnv);
 276  
                     }
 277  
                 }
 278  
             }
 279  
         }
 280  385
         classEnter(tree.defs, localEnv);
 281  385
         if (addEnv) {
 282  0
             todo.append(localEnv);
 283  
         }
 284  385
         log.useSource(prev);
 285  385
         result = null;
 286  385
     }
 287  
 
 288  
     @Override
 289  
     public void visitClassDeclaration(JFXClassDeclaration tree) {
 290  702
         Symbol owner = env.info.scope.owner;
 291  702
         Scope enclScope = enterScope(env);
 292  
         ClassSymbol c;
 293  702
         if (owner.kind == PCK) {
 294  
             // We are seeing a toplevel class.
 295  385
             PackageSymbol packge = (PackageSymbol) owner;
 296  1171
             for (Symbol q = packge; q != null && q.kind == PCK; q = q.owner)
 297  786
                 q.flags_field |= EXISTS;
 298  385
             c = reader.enterClass(tree.getName(), packge);
 299  385
             packge.members().enterIfAbsent(c);
 300  385
         } else {
 301  317
             if (tree.getName().len != 0 &&
 302  
                     !chk.checkUniqueClassName(tree.pos(), tree.getName(), enclScope)) {
 303  0
                 result = null;
 304  0
                 return;
 305  
             }
 306  317
             if (owner.kind == TYP) {
 307  
                 // We are seeing a member class.
 308  291
                 c = reader.enterClass(tree.getName(), (TypeSymbol) owner);
 309  291
                 if ((owner.flags_field & INTERFACE) != 0) {
 310  0
                     tree.mods.flags |= PUBLIC | STATIC;
 311  
                 }
 312  
             } else {
 313  
                 // We are seeing a local class.
 314  26
                 c = reader.defineClass(tree.getName(), owner);
 315  26
                 c.flatname = chk.localClassName(c);
 316  26
                 if (c.name.len != 0)
 317  26
                     chk.checkTransparentClass(tree.pos(), c, env.info.scope);
 318  
             }
 319  
         }
 320  702
         tree.sym = c;
 321  
 
 322  
         // Enter class into `compiled' table and enclosing scope.
 323  702
         if (chk.compiled.get(c.flatname) != null) {
 324  0
             duplicateClass(tree.pos(), c);
 325  0
             result = new ErrorType(tree.getName(), (TypeSymbol) owner);
 326  0
             tree.sym = (ClassSymbol) result.tsym;
 327  0
             return;
 328  
         }
 329  702
         chk.compiled.put(c.flatname, c);
 330  702
         enclScope.enter(c);
 331  
 
 332  
         // Set up an environment for class block and store in `typeEnvs'
 333  
         // table, to be retrieved later in memberEnter and attribution.
 334  702
         JavafxEnv<JavafxAttrContext> localEnv = classEnv(tree, env);
 335  702
         typeEnvs.put(c, localEnv);
 336  
 
 337  
         // Fill out class fields.
 338  702
         c.completer = memberEnter;
 339  702
         c.flags_field = chk.checkFlags(tree.pos(), tree.mods.flags, c, tree);
 340  702
         c.sourcefile = env.toplevel.sourcefile;
 341  702
         c.members_field = new Scope(c);
 342  
 
 343  702
         ClassType ct = (ClassType) c.type;
 344  702
         if (owner.kind != PCK && (c.flags_field & STATIC) == 0) {
 345  
             // We are seeing a local or inner class.
 346  
             // Set outer_field of this class to closest enclosing class
 347  
             // which contains this class in a non-static context
 348  
             // (its "enclosing instance class"), provided such a class exists.
 349  26
             Symbol owner1 = owner;
 350  
             while ((owner1.kind & (VAR | MTH)) != 0 &&
 351  26
                     (owner1.flags_field & STATIC) == 0) {
 352  0
                 owner1 = owner1.owner;
 353  
             }
 354  26
             if (owner1.kind == TYP) {
 355  26
                 ct.setEnclosingType(owner1.type);
 356  
             }
 357  
         }
 358  
 
 359  
         // Enter type parameters.
 360  702
         ct.typarams_field = classEnter(tree.getEmptyTypeParameters(), localEnv);
 361  
 
 362  
         // Add non-local class to uncompleted, to make sure it will be
 363  
         // completed later.
 364  702
         if (!c.isLocal() && uncompleted != null) uncompleted.append(c);
 365  
         // Recursively enter all member classes.
 366  702
         classEnter(tree.getMembers(), localEnv);
 367  
 
 368  702
         types.addFxClass(c, tree);
 369  702
         result = c.type;
 370  702
     }
 371  
 
 372  
     /** Complain about a duplicate class. */
 373  
     protected void duplicateClass(DiagnosticPosition pos, ClassSymbol c) {
 374  0
         log.error(pos, MsgSym.MESSAGE_DUPLICATE_CLASS, c.fullname);
 375  0
     }
 376  
 
 377  
 /** Class enter visitor method for type parameters.
 378  
      *        Enter a symbol for type parameter in local scope, after checking that it
 379  
      *        is unique.
 380  
      */
 381  
     @Override
 382  
     public void visitTypeParameter(JCTypeParameter tree) {
 383  0
         TypeVar a = (tree.type != null)
 384  
             ? (TypeVar)tree.type
 385  
             : new TypeVar(tree.name, env.info.scope.owner, syms.botType);
 386  0
         tree.type = a;
 387  0
         if (chk.checkUnique(tree.pos(), a.tsym, env.info.scope)) {
 388  0
             env.info.scope.enter(a.tsym);
 389  
         }
 390  0
         result = a;
 391  0
     }
 392  
 
 393  
     /** Default class enter visitor method: do nothing.
 394  
      */
 395  
     @Override
 396  
     public void visitTree(JCTree tree) {
 397  0
         result = null;
 398  0
     }
 399  
     
 400  
     /** Main method: enter all classes in a list of toplevel trees.
 401  
      *        @param trees          The list of trees to be processed.
 402  
      */
 403  
     public void main(List<JCCompilationUnit> trees) {
 404  383
         complete(trees, null);
 405  383
     }
 406  
 
 407  
     /** Main method: enter one class from a list of toplevel trees and
 408  
      *  place the rest on uncompleted for later processing.
 409  
      *  @param trees      The list of trees to be processed.
 410  
      *  @param c          The class symbol to be processed.
 411  
      */
 412  
     public void complete(List<JCCompilationUnit> trees, ClassSymbol c) {
 413  383
         annotate.enterStart();
 414  383
         ListBuffer<ClassSymbol> prevUncompleted = uncompleted;
 415  383
         if (memberEnter.completionEnabled) uncompleted = new ListBuffer<ClassSymbol>();
 416  
 
 417  
         try {
 418  
             // enter all classes, and construct uncompleted list
 419  383
             classEnter(trees, null);
 420  
 
 421  
             // complete all uncompleted classes in memberEnter
 422  383
             if  (memberEnter.completionEnabled) {
 423  1059
                 while (uncompleted.nonEmpty()) {
 424  676
                     ClassSymbol clazz = uncompleted.next();
 425  676
                     if (c == null || c == clazz || prevUncompleted == null)
 426  676
                         clazz.complete();
 427  
                     else
 428  
                         // defer
 429  0
                         prevUncompleted.append(clazz);
 430  676
                 }
 431  
 
 432  
                 // if there remain any unimported toplevels (these must have
 433  
                 // no classes at all), process their import statements as well.
 434  383
                 for (JCCompilationUnit tree : trees) {
 435  385
                     if (tree.starImportScope.elems == null) {
 436  305
                         JavaFileObject prev = log.useSource(tree.sourcefile);
 437  305
                         JavafxEnv<JavafxAttrContext> localEnv = typeEnvs.get(tree.packge);
 438  305
                         if (localEnv == null)
 439  305
                             localEnv = topLevelEnv(tree);
 440  305
                         memberEnter.memberEnter(tree, localEnv);
 441  305
                         log.useSource(prev);
 442  385
                     }
 443  
                 }
 444  
             }
 445  
         } finally {
 446  383
             uncompleted = prevUncompleted;
 447  383
             annotate.enterDone();
 448  383
         }
 449  383
     }
 450  
 
 451  
 }