Coverage Report - com.sun.tools.javafx.comp.JavafxTypeMorpher
 
Classes in this File Line Coverage Branch Coverage Complexity
JavafxTypeMorpher
98%
62/63
94%
17/18
0
JavafxTypeMorpher$1
N/A
N/A
0
JavafxTypeMorpher$LocationNameSymType
100%
10/10
N/A
0
JavafxTypeMorpher$TypeMorphInfo
97%
33/34
74%
28/38
0
JavafxTypeMorpher$VarMorphInfo
97%
36/37
87%
26/30
0
 
 1  
 /*
 2  
  * Copyright 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 tree accompanied this code.
 10  
  *
 11  
  * This code is distributed in the hope tree 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 tree
 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 java.util.HashMap;
 29  
 import java.util.Map;
 30  
 
 31  
 import com.sun.tools.javac.code.*;
 32  
 import com.sun.tools.javac.code.Type.ClassType;
 33  
 import com.sun.tools.javac.code.Type.MethodType;
 34  
 import com.sun.tools.javac.tree.JCTree.*;
 35  
 import com.sun.tools.javac.util.*;
 36  
 import com.sun.tools.javafx.code.JavafxFlags;
 37  
 import com.sun.tools.javafx.code.JavafxSymtab;
 38  
 import com.sun.tools.javafx.code.JavafxTypes;
 39  
 import com.sun.tools.javafx.code.JavafxVarSymbol;
 40  
 import com.sun.tools.javafx.code.JavafxClassSymbol;
 41  
 import static com.sun.tools.javafx.code.JavafxVarSymbol.*;
 42  
 import static com.sun.tools.javafx.comp.JavafxDefs.locationPackageNameString;
 43  
 import static com.sun.tools.javafx.comp.JavafxDefs.sequencePackageNameString;
 44  
 
 45  
 /**
 46  
  *
 47  
  * @author Robert Field
 48  
  */
 49  38390
 public class JavafxTypeMorpher {
 50  12
     protected static final Context.Key<JavafxTypeMorpher> typeMorpherKey =
 51  
             new Context.Key<JavafxTypeMorpher>();
 52  
 
 53  
     private final JavafxDefs defs;
 54  
     private final Name.Table names;
 55  
     final JavafxClassReader reader;
 56  
     private final JavafxSymtab syms;
 57  
     private final JavafxToJava toJava;  //TODO: this dependency should go away
 58  
     private final JavafxTypes types;
 59  
 
 60  
     public final LocationNameSymType[] bindingNCT;
 61  
     public final LocationNameSymType[] locationNCT;
 62  
     public final LocationNameSymType[] variableNCT;
 63  
     public final LocationNameSymType[] boundComprehensionNCT;
 64  
     public final LocationNameSymType[] constantLocationNCT;
 65  
     public final LocationNameSymType   baseLocation;
 66  
 
 67  
     private final Object[] defaultValueByKind;
 68  
 
 69  10374
     public class LocationNameSymType {
 70  
         public final Name name;
 71  
         public final ClassSymbol sym;
 72  
         public final Type type;
 73  10374
         private LocationNameSymType(Name name) {
 74  10374
             this.name = name;
 75  10374
             sym = reader.jreader.enterClass(name);
 76  10374
             type = sym.type;
 77  10374
         }
 78  
         private LocationNameSymType(String which) {
 79  4389
             this(locationPackageNameString, which);
 80  4389
         }
 81  
         private LocationNameSymType(String pkg, String which) {
 82  6384
             this(Name.fromString(names, pkg + "." + which));
 83  6384
         }
 84  
     }
 85  
 
 86  399
     private Map<Symbol, VarMorphInfo> vmiMap = new HashMap<Symbol, VarMorphInfo>();
 87  
 
 88  
     public class VarMorphInfo extends TypeMorphInfo {
 89  
         private final Symbol sym;
 90  
         private final boolean isMethod;
 91  4205
         private boolean mustMorph = false;
 92  4205
         private boolean haveDeterminedMorphability = false;
 93  4205
         private boolean isBoundTo = false;
 94  4205
         private boolean isAssignedTo = false;
 95  
 
 96  4205
         VarMorphInfo(Symbol sym) {
 97  4205
             super((sym.kind == Kinds.MTH)? ((MethodType)sym.type).getReturnType() : sym.type);
 98  4205
             this.sym = sym;
 99  4205
             this.isMethod = (sym.kind == Kinds.MTH);
 100  4205
         }
 101  
 
 102  
         private void determineMorphability() {
 103  3554
             if (!isMethod) {
 104  3554
                 Symbol owner = getSymbol().owner;
 105  3554
                 if (owner.kind == Kinds.MTH) {
 106  
                     
 107  2557
                    long flag_fields = getSymbol().flags();
 108  
                    
 109  
                    // Variables are morphed if they are accessed within an inner class and have been assigned to
 110  2557
                    if ( (flag_fields & JavafxFlags.INNER_ACCESS) != 0) {
 111  11
                      if ( (flag_fields & JavafxFlags.ASSIGNED_TO) != 0) 
 112  3
                         markMustMorph();
 113  
                    } 
 114  
                    // non-parameter local vars are morphed if they are bound to or sequencea
 115  
                     // (bound functions and their parameters are handled elsewhere)
 116  2557
                    if ((isBoundTo() || isSequence()) && (flag_fields & Flags.PARAMETER) == 0) {
 117  488
                             markMustMorph();
 118  
                    }
 119  2557
                } else if (owner.kind == Kinds.TYP) {
 120  997
                    if (getSymbol() instanceof JavafxVarSymbol) {
 121  510
                        markMustMorph(); // we made it, soassume it is from a JavaFX class
 122  487
                    } else if (sym.flatName() != names._super && sym.flatName() != names._this) {
 123  487
                        if (types.isJFXClass(owner)) {
 124  
                            // this is an attribute: it is owned by a JavaFX class and it isn't 'this' or 'super'
 125  231
                            markMustMorph();
 126  
                        }
 127  
                    }
 128  
                }
 129  
            }
 130  3554
            markDeterminedMorphability();
 131  3554
        }
 132  
 
 133  
        public boolean mustMorph() {
 134  18628
            if (!haveDeterminedMorphability()) {
 135  3554
                determineMorphability();
 136  
            }
 137  18628
            return mustMorph;
 138  
        }
 139  
 
 140  1232
         private void markMustMorph() { mustMorph = true; }
 141  3554
         private void markDeterminedMorphability() { haveDeterminedMorphability = true; }
 142  18628
         private boolean haveDeterminedMorphability() { return haveDeterminedMorphability; }
 143  2557
         public boolean isBoundTo() { return isBoundTo; }
 144  0
         public boolean isAssignedTo() { return isAssignedTo; }
 145  889
         public void markBoundTo() { this.isBoundTo = true; haveDeterminedMorphability = false; }
 146  928
         public void markAssignedTo() { this.isAssignedTo = true; }
 147  
 
 148  
         public Symbol getSymbol() {
 149  20005
             return sym;
 150  
         }
 151  
     }
 152  
 
 153  6
     public class TypeMorphInfo {
 154  
         private Type realType;
 155  
         private final Type morphedVariableType;
 156  
         private final Type morphedLocationType;
 157  
         private int typeKind;
 158  7072
         private Type elementType = null;
 159  
 
 160  7072
         TypeMorphInfo(Type symType) {
 161  7072
             TypeSymbol realTsym = symType.tsym;
 162  
             //check if symbol is already a Location, needed for source class
 163  
             assert 
 164  
                 (realTsym != variableNCT[TYPE_KIND_OBJECT].sym) &&
 165  
                 (realTsym != variableNCT[TYPE_KIND_SEQUENCE].sym) &&
 166  
                 (realTsym != variableNCT[TYPE_KIND_BOOLEAN].sym) &&
 167  
                 (realTsym != variableNCT[TYPE_KIND_DOUBLE].sym) &&
 168  7072
                 (realTsym != variableNCT[TYPE_KIND_INT].sym) : "Locations should have been converted";
 169  
             
 170  7072
             this.realType = symType;
 171  
 
 172  7072
             if (symType.isPrimitive()) {
 173  2935
                 if (realTsym == syms.doubleType.tsym //  || realTsym == syms.floatType.tsym
 174  
                         ) {
 175  597
                     typeKind = TYPE_KIND_DOUBLE;
 176  2338
                 } else if (realTsym == syms.intType.tsym
 177  
                         || realTsym == syms.byteType.tsym
 178  
                         || realTsym == syms.charType.tsym
 179  
                      // || realTsym == syms.longType.tsym //TODO: should this be converted
 180  
                         || realTsym == syms.shortType.tsym) {
 181  1883
                     typeKind = TYPE_KIND_INT;
 182  455
                 } else if (realTsym == syms.booleanType.tsym) {
 183  453
                     typeKind = TYPE_KIND_BOOLEAN;
 184  
                 } else {
 185  
                     //assert false : "should not reach here";
 186  2
                     this.realType = types.boxedClass(realType).type; //TODO: maybe the real type should be kept separate?
 187  2
                     elementType = realType;
 188  2
                     typeKind = TYPE_KIND_OBJECT;
 189  
                 }
 190  
             } else {
 191  4137
                 if (isSequence()) {
 192  1394
                     typeKind = TYPE_KIND_SEQUENCE;
 193  1394
                     elementType = toJava.elementType(symType);
 194  
                 } else {
 195  2743
                     typeKind = TYPE_KIND_OBJECT;
 196  2743
                     elementType = realType;
 197  
                 }
 198  
             }
 199  
 
 200  
             // must be called AFTER typeKind and realType are set in vsym
 201  7072
             this.morphedVariableType = symType == syms.voidType ? symType : generifyIfNeeded(variableType(typeKind), this);
 202  7072
             this.morphedLocationType = symType == syms.voidType ? symType : generifyIfNeeded(locationType(typeKind), this);
 203  7072
         }
 204  
 
 205  
         protected boolean isSequence() {
 206  6445
             return types.isSequence(realType);
 207  
         }
 208  
 
 209  4990
         public Type getRealType() { return realType; }
 210  0
         public Type getRealBoxedType() { return (realType.isPrimitive())? types.boxedClass(realType).type : realType; }
 211  162
         public Type getRealFXType() { return (realType.isPrimitive() && typeKind==TYPE_KIND_OBJECT)? types.boxedClass(realType).type : realType; }
 212  
 
 213  829
         public Type getLocationType() { return morphedLocationType; }
 214  3048
         public Type getVariableType() { return morphedVariableType; }
 215  211
         public Type getConstantLocationType() { return generifyIfNeeded(constantLocationNCT[typeKind].type, this); }
 216  1461
         public Object getDefaultValue() { return defaultValueByKind[typeKind]; }
 217  15663
         public Type getElementType() { return elementType; }
 218  
 
 219  46427
         public int getTypeKind() { return typeKind; }
 220  
     }
 221  
 
 222  
     VarMorphInfo varMorphInfo(Symbol sym) {
 223  33328
         VarMorphInfo vmi = vmiMap.get(sym);
 224  33328
         if (vmi == null) {
 225  4205
             vmi = new VarMorphInfo(sym);
 226  4205
             vmiMap.put(sym, vmi);
 227  
         }
 228  33328
         return vmi;
 229  
     }
 230  
 
 231  
     TypeMorphInfo typeMorphInfo(Type type) {
 232  2867
         return new TypeMorphInfo(type);
 233  
     }
 234  
 
 235  
     public static JavafxTypeMorpher instance(Context context) {
 236  1596
         JavafxTypeMorpher instance = context.get(typeMorpherKey);
 237  1596
         if (instance == null)
 238  399
             instance = new JavafxTypeMorpher(context);
 239  1596
         return instance;
 240  
     }
 241  
 
 242  399
     protected JavafxTypeMorpher(Context context) {
 243  399
         context.put(typeMorpherKey, this);
 244  
 
 245  399
         defs = JavafxDefs.instance(context);
 246  399
         syms = (JavafxSymtab)(JavafxSymtab.instance(context));
 247  399
         types = JavafxTypes.instance(context);
 248  399
         names = Name.Table.instance(context);
 249  399
         reader = JavafxClassReader.instance(context);
 250  399
         toJava = JavafxToJava.instance(context);
 251  
 
 252  399
         variableNCT = new LocationNameSymType[TYPE_KIND_COUNT];
 253  399
         locationNCT = new LocationNameSymType[TYPE_KIND_COUNT];
 254  399
         bindingNCT = new LocationNameSymType[TYPE_KIND_COUNT];  
 255  399
         boundComprehensionNCT = new LocationNameSymType[TYPE_KIND_COUNT];
 256  399
         constantLocationNCT = new LocationNameSymType[TYPE_KIND_COUNT];
 257  
 
 258  2394
         for (int kind = 0; kind < TYPE_KIND_COUNT; ++kind) {
 259  1995
             variableNCT[kind] = new LocationNameSymType(defs.locationVariableName[kind]);
 260  1995
             locationNCT[kind] = new LocationNameSymType(defs.locationInterfaceName[kind]);
 261  1995
             bindingNCT[kind] = new LocationNameSymType(JavafxVarSymbol.getTypePrefix(kind) + "BindingExpression");
 262  1995
             boundComprehensionNCT[kind] = new LocationNameSymType(sequencePackageNameString, JavafxVarSymbol.getTypePrefix(kind) + "BoundComprehension");
 263  1995
             constantLocationNCT[kind] = new LocationNameSymType(JavafxVarSymbol.getTypePrefix(kind) + "Constant");
 264  
         }
 265  
 
 266  399
         baseLocation = new LocationNameSymType("Location");
 267  
 
 268  399
         defaultValueByKind = new Object[TYPE_KIND_COUNT];
 269  399
         defaultValueByKind[TYPE_KIND_OBJECT] = null;
 270  399
         defaultValueByKind[TYPE_KIND_DOUBLE] = 0.0;
 271  399
         defaultValueByKind[TYPE_KIND_BOOLEAN] = 0;
 272  399
         defaultValueByKind[TYPE_KIND_INT] = 0;
 273  399
         defaultValueByKind[TYPE_KIND_SEQUENCE] = null; //TODO: empty sequence
 274  399
     }
 275  
 
 276  
     Type variableType(int typeKind) {
 277  15418
         return variableNCT[typeKind].type;
 278  
     }
 279  
 
 280  
     Type locationType(int typeKind) {
 281  7126
         return locationNCT[typeKind].type;
 282  
     }
 283  
 
 284  
     Type bindingExpressionType(int typeKind) {
 285  153
         return bindingNCT[typeKind].type;
 286  
     }
 287  
 
 288  
     /** Add type parameters.
 289  
      * Returns a bogus hybrid front-end/back-end Type that is only meaningful
 290  
      * as an argument to makeTypeTree.
 291  
      * FIXME when translation creates attributes trees.
 292  
      */
 293  
     Type generifyIfNeeded(Type aLocationType, TypeMorphInfo tmi) {
 294  
         Type newType;
 295  14381
         Type elemType = tmi.getElementType();
 296  14381
         if ((tmi.getTypeKind() == TYPE_KIND_OBJECT ||
 297  
                 tmi.getTypeKind() == TYPE_KIND_SEQUENCE) ) {
 298  8346
             if (elemType == null) {
 299  
                 /* handles library which doesn't have element type */
 300  0
                 elemType = syms.objectType;
 301  
             }
 302  8346
             List<Type> actuals = List.of(elemType);
 303  8346
             Type clazzOuter = variableType(tmi.getTypeKind()).getEnclosingType();
 304  
 
 305  8346
             List<Type> newActuals = List.nil();
 306  8346
             for (Type t : actuals) {
 307  8346
                 if ((t.tsym instanceof ClassSymbol) &&
 308  
                         (t.tsym.flags_field & JavafxFlags.COMPOUND_CLASS) != 0) {
 309  1976
                     String str = t.tsym.name.toString().replace("$", ".");
 310  1976
                     ClassSymbol csym = new JavafxClassSymbol(0, names.fromString(str), t.tsym.owner);
 311  1976
                     csym.flags_field |= JavafxFlags.COMPOUND_CLASS;
 312  1976
                     Type tp = new ClassType(null, null, csym);
 313  1976
                     newActuals = newActuals.append(tp);
 314  1976
                     break;
 315  
                 }
 316  
 
 317  6370
                 newActuals = newActuals.append(t);
 318  
             }
 319  
 
 320  8346
             newType = new ClassType(clazzOuter, newActuals, aLocationType.tsym);
 321  8346
         } else {
 322  6035
             newType = aLocationType;
 323  
         }
 324  14381
         return newType;
 325  
     }
 326  
 }