Coverage Report - com.sun.tools.javafx.comp.JavafxAnalyzeClass
 
Classes in this File Line Coverage Branch Coverage Complexity
JavafxAnalyzeClass
95%
116/122
84%
76/90
0
JavafxAnalyzeClass$1
N/A
N/A
0
JavafxAnalyzeClass$AttributeInfo
92%
24/26
100%
2/2
0
JavafxAnalyzeClass$TranslatedAttributeInfo
78%
7/9
0%
0/4
0
JavafxAnalyzeClass$TranslatedOverrideAttributeInfo
100%
4/4
N/A
0
 
 1  
 package com.sun.tools.javafx.comp;
 2  
 
 3  
 import com.sun.tools.javac.code.Flags;
 4  
 import com.sun.tools.javac.code.Kinds;
 5  
 import com.sun.tools.javac.code.Scope.Entry;
 6  
 import com.sun.tools.javac.code.Symbol;
 7  
 import com.sun.tools.javac.code.Symbol.ClassSymbol;
 8  
 import com.sun.tools.javac.code.Symbol.MethodSymbol;
 9  
 import com.sun.tools.javac.code.Symbol.VarSymbol;
 10  
 import com.sun.tools.javac.code.Type;
 11  
 import com.sun.tools.javac.code.Type.MethodType;
 12  
 import com.sun.tools.javac.tree.JCTree;
 13  
 import com.sun.tools.javac.tree.JCTree.JCExpression;
 14  
 import com.sun.tools.javac.tree.JCTree.JCStatement;
 15  
 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
 16  
 import com.sun.tools.javac.util.List;
 17  
 import com.sun.tools.javac.util.ListBuffer;
 18  
 import com.sun.tools.javac.util.Log;
 19  
 import com.sun.tools.javac.util.Name;
 20  
 import com.sun.tools.javac.util.Position;
 21  
 
 22  
 import com.sun.tools.javafx.code.JavafxFlags;
 23  
 import com.sun.tools.javafx.code.JavafxTypes;
 24  
 import com.sun.tools.javafx.comp.JavafxTypeMorpher.VarMorphInfo;
 25  
 import com.sun.tools.javafx.tree.*;
 26  
 import com.sun.tools.javafx.util.MsgSym;
 27  
 
 28  
 import static com.sun.tools.javafx.comp.JavafxDefs.*;
 29  
 
 30  
 import java.util.HashMap;
 31  
 import java.util.HashSet;
 32  
 import java.util.Map;
 33  
 import java.util.Set;
 34  
 
 35  6
 class JavafxAnalyzeClass {
 36  
 
 37  
     private final DiagnosticPosition diagPos;
 38  
     private final ClassSymbol currentClassSym;
 39  612
     private final ListBuffer<AttributeInfo> attributeInfos = ListBuffer.lb();
 40  612
     private final Map<String,MethodSymbol> needDispatchMethods = new HashMap<String, MethodSymbol>();
 41  612
     private final Map<String, AttributeInfo> translatedAttributes = new HashMap<String, AttributeInfo>();
 42  612
     private final Map<String, AttributeInfo> visitedSourceAttributes = new HashMap<String, AttributeInfo>();
 43  612
     private final Map<String, AttributeInfo> visitedClassFileAttributes = new HashMap<String, AttributeInfo>();
 44  612
     private final Set<Symbol> addedBaseClasses = new HashSet<Symbol>();
 45  
     private final List<TranslatedAttributeInfo> translatedAttrInfo;
 46  
     private final Log log;
 47  
     private final Name.Table names;
 48  
     private final JavafxTypes types;
 49  
     private final JavafxClassReader reader;
 50  
     private final JavafxTypeMorpher typeMorpher;
 51  
 
 52  2739
     static class AttributeInfo {
 53  
         private final DiagnosticPosition diagPos;
 54  
         private final Symbol sym;
 55  
         private final VarMorphInfo vmi;
 56  
         private final Name name;
 57  
         private final JCStatement initStmt;
 58  
         private final boolean isDirectOwner;
 59  
         private boolean needsCloning;
 60  
         
 61  
         private AttributeInfo(DiagnosticPosition diagPos, Name name, Symbol attrSym, VarMorphInfo vmi,
 62  1099
                 JCStatement initStmt, boolean isDirectOwner) {
 63  1099
             this.diagPos = diagPos;
 64  1099
             this.name = name;
 65  1099
             this.sym = attrSym;
 66  1099
             this.vmi = vmi;
 67  1099
             this.initStmt = initStmt;
 68  1099
             this.isDirectOwner = isDirectOwner;
 69  1099
         }
 70  
 
 71  
         public Symbol getSymbol() {
 72  252
             return sym;
 73  
         }
 74  
 
 75  
         public DiagnosticPosition pos() {
 76  3325
             return diagPos;
 77  
         }
 78  
 
 79  
         public Type getRealType() {
 80  286
             return vmi.getRealType();
 81  
         }
 82  
 
 83  
         public Type getVariableType() {
 84  2568
             return vmi.getVariableType();
 85  
         }
 86  
 
 87  
         public Type getLocationType() {
 88  0
             return vmi.getLocationType();
 89  
         }
 90  
 
 91  
         public Type getElementType() {
 92  70
             return vmi.getElementType();
 93  
         }
 94  
 
 95  
         public Name getName() {
 96  4751
             return name;
 97  
         }
 98  
 
 99  
         public String getNameString() {
 100  4201
             return name.toString();
 101  
         }
 102  
 
 103  
         public long getFlags() {
 104  5229
             return sym.flags();
 105  
         }
 106  
         
 107  
         // possibly confusing.  "needsCloning()" should be used for all known cases
 108  
         //public boolean isInCompoundClass() {
 109  
         //    return (sym.owner.flags() & JavafxFlags.COMPOUND_CLASS) != 0;
 110  
         //}
 111  
         
 112  
         private void setNeedsCloning(boolean needs) {
 113  1640
             needsCloning = needs;
 114  1640
         }
 115  
         
 116  
         public boolean needsCloning() {
 117  2767
             return needsCloning;
 118  
         }
 119  
         
 120  
         public boolean isStatic() {
 121  1644
             return (getFlags() & Flags.STATIC) != 0;
 122  
         }
 123  
 
 124  
         public VarMorphInfo getVMI() {
 125  1091
             return vmi;
 126  
         }
 127  
 
 128  
         public boolean isDirectOwner() {
 129  76
             return isDirectOwner;
 130  
         }
 131  
         
 132  
         public JCStatement getDefaultInitializtionStatement() {
 133  1623
             return initStmt;
 134  
         }
 135  
         
 136  
         public String toString() {
 137  0
             return getNameString();
 138  
         }
 139  
     }
 140  
     
 141  
     /*
 142  
     static class TranslatedAttributeInfo extends AttributeInfo {
 143  
         final JFXVar attribute;
 144  
         final List<JFXAbstractOnChange> onChanges;
 145  
         TranslatedAttributeInfo(JFXVar attribute, VarMorphInfo vmi,
 146  
                 JCStatement initStmt, List<JFXAbstractOnChange> onChanges) {
 147  
             super(attribute.pos(), attribute.sym.name, attribute.sym, vmi, initStmt, true);
 148  
             this.attribute = attribute;
 149  
             this.onChanges = onChanges;
 150  
         }
 151  
         
 152  
         private void setNeedsCloning(boolean needs) {
 153  
             assert needs;
 154  
         }
 155  
         
 156  
         public boolean needsCloning() {
 157  
             return true; // these are from current class, so always need cloning
 158  
         }
 159  
         
 160  
     } */
 161  
     
 162  2
     static class TranslatedAttributeInfo extends AttributeInfo {
 163  
         final JFXVar attribute;
 164  
         private final JFXOnReplace onReplace;
 165  
         TranslatedAttributeInfo(JFXVar attribute, VarMorphInfo vmi,
 166  
                 JCStatement initStmt, JFXOnReplace onReplace) {
 167  563
             super(attribute.pos(), attribute.sym.name, attribute.sym, vmi, initStmt, true);
 168  563
             this.attribute = attribute;
 169  563
             this.onReplace = onReplace;
 170  563
         }
 171  
         
 172  
         private void setNeedsCloning(boolean needs) {
 173  0
             assert needs;
 174  0
         }
 175  
         
 176  
         public boolean needsCloning() {
 177  1999
             return true; // these are from current class, so always need cloning
 178  
         }
 179  
         
 180  563
         JFXOnReplace onReplace() { return onReplace; }
 181  
         
 182  
     }  
 183  
     
 184  
     
 185  
     
 186  
   
 187  
     static class TranslatedOverrideAttributeInfo extends AttributeInfo {
 188  
         private final JFXOnReplace onReplace;
 189  
         TranslatedOverrideAttributeInfo(JFXOverrideAttribute override, 
 190  
                  VarMorphInfo vmi,
 191  
                 JCStatement initStmt, JFXOnReplace onReplace) {
 192  9
             super(override.pos(), override.sym.name, override.sym, vmi, initStmt, true);
 193  9
             this.onReplace = onReplace;
 194  9
         }
 195  
         
 196  9
         JFXOnReplace onReplace() { return onReplace; }
 197  
     }
 198  
      
 199  
     JavafxAnalyzeClass(DiagnosticPosition diagPos,
 200  
             ClassSymbol currentClassSym,
 201  
             List<TranslatedAttributeInfo> translatedAttrInfo,
 202  
             List<TranslatedOverrideAttributeInfo> translatedOverrideAttrInfo,
 203  
             Log log,
 204  
             Name.Table names,
 205  
             JavafxTypes types,
 206  
             JavafxClassReader reader,
 207  612
             JavafxTypeMorpher typeMorpher) {
 208  612
         this.log = log;
 209  612
         this.names = names;
 210  612
         this.types = types;
 211  612
         this.reader = reader;
 212  612
         this.typeMorpher = typeMorpher;
 213  612
         this.diagPos = diagPos;
 214  612
         this.currentClassSym = currentClassSym;
 215  
         
 216  612
         this.translatedAttrInfo = translatedAttrInfo;
 217  612
         for (TranslatedAttributeInfo tai : translatedAttrInfo) {
 218  556
             translatedAttributes.put(tai.getNameString(), tai);
 219  
         }
 220  612
         for (TranslatedOverrideAttributeInfo tai : translatedOverrideAttrInfo) {
 221  9
             translatedAttributes.put(tai.getNameString(), tai);
 222  
         }
 223  
 
 224  
         // do the analysis
 225  612
         process(currentClassSym, true);
 226  612
         types.isCompoundClass(currentClassSym);
 227  612
     }
 228  
 
 229  
     public List<AttributeInfo> instanceAttributeInfos() {
 230  612
         return attributeInfos.toList();
 231  
     }
 232  
 
 233  
     public List<AttributeInfo> staticAttributeInfos() {
 234  612
         ListBuffer<AttributeInfo> ais = ListBuffer.lb();
 235  612
         for (AttributeInfo ai : translatedAttrInfo) {
 236  556
             if (ai.isStatic()) {
 237  75
                 ais.append( ai );
 238  
             }
 239  
         }
 240  612
         return ais.toList();
 241  
     }
 242  
 
 243  
     public List<MethodSymbol> needDispatch() {
 244  612
         ListBuffer<MethodSymbol> meths = ListBuffer.lb();
 245  612
         for (MethodSymbol mSym : needDispatchMethods.values()) {
 246  745
             meths.append( mSym );
 247  
         }
 248  612
         return meths.toList();
 249  
     }
 250  
 
 251  
     private void process(Symbol sym, boolean cloneVisible) {
 252  816
         if (!addedBaseClasses.contains(sym) && types.isJFXClass(sym)) {
 253  781
             ClassSymbol cSym = (ClassSymbol) sym;
 254  781
             addedBaseClasses.add(cSym);
 255  781
             JFXClassDeclaration cDecl = types.getFxClass(cSym);
 256  781
             if (cSym != currentClassSym && (cSym.flags() & (JavafxFlags.COMPOUND_CLASS|Flags.INTERFACE)) == 0) {
 257  
                 // this class is non-compound AND not the current class
 258  
                 // needs to be recursively applied, non-compound in the chain blocks clonability
 259  6
                 cloneVisible = false; 
 260  
             }
 261  
 
 262  
             // get the corresponding AST, null if from class file
 263  781
             if (cDecl == null) {
 264  63
                 for (Type supertype : cSym.getInterfaces()) {
 265  36
                     ClassSymbol iSym = (ClassSymbol) supertype.tsym;
 266  36
                     process(iSym, cloneVisible);
 267  36
                     String iName = iSym.fullname.toString();
 268  36
                     if (iName.endsWith(JavafxDefs.interfaceSuffix)) {
 269  0
                         String sName = iName.substring(0, iName.length() - JavafxDefs.interfaceSuffix.length());
 270  0
                         ClassSymbol sSym = reader.enterClass(names.fromString(sName));
 271  0
                         process(sSym, cloneVisible);
 272  
                     }
 273  36
                 }
 274  63
                 if ((cSym.flags_field & Flags.INTERFACE) == 0 && cSym.members() != null) {
 275  
                     /***
 276  
                     for (Entry e = cSym.members().elems; e != null && e.sym != null; e = e.sibling) {
 277  
                         if (e.sym.kind == Kinds.MTH) {
 278  
                             processMethodFromClassFile((MethodSymbol) e.sym, cSym, cloneVisible);
 279  
                         }
 280  
                     }
 281  
                      * ***/
 282  
                     //TODO: fiz this hack back to the above. for some reason the order of symbols within a scope is inverted
 283  63
                     ListBuffer<MethodSymbol> reversed = ListBuffer.lb();
 284  4910
                     for (Entry e = cSym.members().elems; e != null && e.sym != null; e = e.sibling) {
 285  4847
                         if (e.sym.kind == Kinds.MTH) {
 286  3711
                             reversed.prepend((MethodSymbol) e.sym);
 287  
                         }
 288  
                     }
 289  63
                     for (MethodSymbol meth : reversed) {
 290  3711
                         processMethodFromClassFile(meth, cSym, cloneVisible);
 291  
                     }
 292  
                     
 293  63
                 }
 294  
             } else {
 295  718
                 for (JCExpression supertype : cDecl.getSupertypes()) {
 296  168
                     process(supertype.type.tsym, cloneVisible);
 297  
                 }
 298  718
                 for (JCTree def : cDecl.getMembers()) {
 299  2083
                     if (def.getTag() == JavafxTag.VAR_DEF) {
 300  648
                         processAttributeFromSource((JFXVar) def, cDecl, cloneVisible);
 301  1435
                     } else if (cloneVisible && def.getTag() == JavafxTag.FUNCTION_DEF) {
 302  1105
                         processFunctionFromSource((JFXFunctionDefinition) def);
 303  
                     }
 304  
                 }
 305  
             }
 306  
         }
 307  816
     }
 308  
 
 309  
     private AttributeInfo addAttribute(String attrName, Symbol sym, boolean needsCloning) {
 310  1017
         AttributeInfo attrInfo = translatedAttributes.get(attrName);
 311  1017
         if (attrInfo == null) {
 312  527
             attrInfo = new AttributeInfo(diagPos, 
 313  
                     names.fromString(attrName),
 314  
                     sym, typeMorpher.varMorphInfo(sym), null, sym.owner == currentClassSym);
 315  
         }
 316  1017
         attrInfo.setNeedsCloning(needsCloning || attrInfo.isDirectOwner());
 317  1017
         attributeInfos.append(attrInfo);
 318  1017
         return attrInfo;
 319  
     }
 320  
 
 321  
     private void processMethodFromClassFile(MethodSymbol meth, ClassSymbol cSym, boolean cloneVisible) {
 322  3711
         String methName = meth.name.toString();
 323  3711
         if (methName.startsWith(attributeGetMethodNamePrefix)) {
 324  1091
             String nameSig = methName.substring(attributeGetMethodNamePrefix.length());
 325  1091
             if (visitedSourceAttributes.containsKey(nameSig)) {
 326  0
                 log.error(MsgSym.MESSAGE_JAVAFX_CANNOT_OVERRIDE_DEFAULT_INITIALIZER, nameSig, cSym.className(), visitedSourceAttributes.get(nameSig));
 327  1091
             } else if (visitedClassFileAttributes.containsKey(nameSig)) {
 328  
                 // not an error since they are replicated in class files, but we need to make sure needsCloning is updated
 329  623
                 AttributeInfo attrInfo = visitedClassFileAttributes.get(nameSig);
 330  623
                 attrInfo.setNeedsCloning(cloneVisible && attrInfo.needsCloning());
 331  623
             } else {
 332  468
                 visitedClassFileAttributes.put(nameSig, addAttribute(nameSig, meth, cloneVisible) );
 333  
             }
 334  1091
         } else if (cloneVisible && methName.endsWith(JavafxDefs.implFunctionSuffix)) {
 335  
             // implementation method
 336  267
             methName = methName.substring(0, methName.length() - JavafxDefs.implFunctionSuffix.length());
 337  267
             int cnt = 0;
 338  267
             ListBuffer<VarSymbol> params = ListBuffer.lb();
 339  267
             ListBuffer<Type> paramTypes = ListBuffer.lb();
 340  267
             for (VarSymbol param : meth.getParameters()) {
 341  408
                 cnt++;
 342  408
                 if (cnt > 1) {
 343  141
                     params.append(param);
 344  141
                     paramTypes.append(param.type);
 345  
                 }
 346  
             }
 347  267
             MethodType mtype = new MethodType(paramTypes.toList(), meth.type.getReturnType(), meth.type.getThrownTypes(), meth.type.tsym);
 348  267
             MethodSymbol fixedMeth = new MethodSymbol(meth.flags() & ~Flags.STATIC, names.fromString(methName), mtype, meth.owner);
 349  267
             fixedMeth.params = params.toList();
 350  267
             String nameSig = methodSignature(fixedMeth);
 351  267
             needDispatchMethods.put(nameSig, fixedMeth);  // because we traverse super-to-sub class, last one wins
 352  
         }
 353  3711
     }
 354  
 
 355  
     private void processFunctionFromSource(JFXFunctionDefinition def) {
 356  1105
         MethodSymbol meth = def.sym;
 357  
         // no dispatch methods for abstract or static functions,
 358  
         // and none for methods from non-compound classes (this test is not redundant 
 359  
         // since the current class is allowed through if non-compound
 360  1105
         if ((meth.flags() & (Flags.SYNTHETIC | Flags.ABSTRACT | Flags.STATIC)) == 0  &&
 361  
                 (meth.owner.flags() & JavafxFlags.COMPOUND_CLASS) != 0) {
 362  510
             assert def.pos != Position.NOPOS;
 363  510
             String nameSig = methodSignature(meth);
 364  510
             needDispatchMethods.put(nameSig, meth);  // because we traverse super-to-sub class, last one wins
 365  
         }
 366  1105
     }
 367  
 
 368  
     private void processAttributeFromSource(JFXVar def, JFXClassDeclaration cDecl, boolean cloneVisible) {
 369  648
         VarSymbol var = def.sym;
 370  648
         if (var.owner.kind == Kinds.TYP && (var.flags() & Flags.STATIC) == 0) {
 371  549
             String attrName = var.name.toString();
 372  549
             String className = cDecl.getName().toString();
 373  549
             if (visitedSourceAttributes.containsKey(attrName)) {
 374  0
                 log.error(MsgSym.MESSAGE_JAVAFX_CANNOT_OVERRIDE_DEFAULT_INITIALIZER, attrName, className, visitedSourceAttributes.get(attrName));
 375  549
             } else if (visitedClassFileAttributes.containsKey(attrName)) {
 376  0
                 log.error(MsgSym.MESSAGE_JAVAFX_CANNOT_OVERRIDE_DEFAULT_INITIALIZER, attrName, className, visitedClassFileAttributes.get(attrName));
 377  
             } else {
 378  549
                 visitedSourceAttributes.put(attrName, addAttribute(attrName, var, cloneVisible) );
 379  
             }
 380  
         }
 381  648
     }
 382  
 
 383  
     private String methodSignature(MethodSymbol meth) {
 384  777
         StringBuilder nameSigBld = new StringBuilder();
 385  777
         nameSigBld.append(meth.name.toString());
 386  777
         nameSigBld.append(":");
 387  777
         nameSigBld.append(meth.getReturnType().toString());
 388  777
         nameSigBld.append(":");
 389  777
         for (VarSymbol param : meth.getParameters()) {
 390  659
             nameSigBld.append(param.type.toString());
 391  659
             nameSigBld.append(":");
 392  
         }
 393  777
         return nameSigBld.toString();
 394  
     }
 395  
 }