Coverage Report - com.sun.tools.javafx.comp.JavafxInitializationBuilder
 
Classes in this File Line Coverage Branch Coverage Complexity
JavafxInitializationBuilder
96%
352/368
78%
190/244
0
JavafxInitializationBuilder$JavafxClassModel
100%
8/8
N/A
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  
 package com.sun.tools.javafx.comp;
 26  
 
 27  
 import com.sun.tools.javac.code.*;
 28  
 import com.sun.tools.javac.code.Scope.Entry;
 29  
 import com.sun.tools.javac.code.Symbol.ClassSymbol;
 30  
 import com.sun.tools.javac.code.Symbol.MethodSymbol;
 31  
 import com.sun.tools.javac.code.Symbol.VarSymbol;
 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.tree.JCTree.*;
 36  
 import com.sun.tools.javac.tree.TreeInfo;
 37  
 import com.sun.tools.javac.util.*;
 38  
 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
 39  
 import com.sun.tools.javafx.code.JavafxFlags;
 40  
 import com.sun.tools.javafx.code.JavafxVarSymbol;
 41  
 import static com.sun.tools.javafx.comp.JavafxDefs.*;
 42  
 import com.sun.tools.javafx.comp.JavafxTypeMorpher.VarMorphInfo;
 43  
 import com.sun.tools.javafx.comp.JavafxAnalyzeClass.AttributeInfo;
 44  
 import com.sun.tools.javafx.comp.JavafxAnalyzeClass.TranslatedAttributeInfo;
 45  
 import com.sun.tools.javafx.comp.JavafxAnalyzeClass.TranslatedOverrideAttributeInfo;
 46  
 import com.sun.tools.javafx.tree.*;
 47  
 
 48  
 /**
 49  
  * Build the representation(s) of a JavaFX class.  Includes class initialization, attribute and function proxies.
 50  
  * With support for multiple inheritent.
 51  
  * 
 52  
  * @author Robert Field
 53  
  * @author Lubo Litchev
 54  
  * @author Per Bothner
 55  
  * @author Zhiqun Chen
 56  
  */
 57  12
 public class JavafxInitializationBuilder extends JavafxTranslationSupport {
 58  12
     protected static final Context.Key<JavafxInitializationBuilder> javafxInitializationBuilderKey =
 59  
         new Context.Key<JavafxInitializationBuilder>();
 60  
 
 61  
     private final JavafxToJava toJava;
 62  
     private final JavafxClassReader reader;
 63  
     
 64  
     private final Name addChangeListenerName;
 65  
     private final Name locationInitializeName;;
 66  
     private final Name[] changeListenerInterfaceName;
 67  
 //    private final Name sequenceReplaceListenerInterfaceName;
 68  
     private final Name sequenceChangeListenerInterfaceName;
 69  
     private static final String initHelperClassName = "com.sun.javafx.runtime.InitHelper";
 70  
     private final Name addTriggersName;
 71  
     final Name userInitName;
 72  
     final Name postInitName;
 73  
     private final Name onChangeArgName1, onChangeArgName2;
 74  
     Name outerAccessorName;
 75  
     Name outerAccessorFieldName;
 76  
     
 77  
     final Type initHelperType;
 78  
     final Type abstractVariableType;
 79  
     
 80  
     public static JavafxInitializationBuilder instance(Context context) {
 81  399
         JavafxInitializationBuilder instance = context.get(javafxInitializationBuilderKey);
 82  399
         if (instance == null)
 83  399
             instance = new JavafxInitializationBuilder(context);
 84  399
         return instance;
 85  
     }
 86  
 
 87  
     protected JavafxInitializationBuilder(Context context) {
 88  399
         super(context);
 89  
         
 90  399
         context.put(javafxInitializationBuilderKey, this);
 91  
 
 92  399
         toJava = JavafxToJava.instance(context);
 93  399
         reader = (JavafxClassReader) JavafxClassReader.instance(context);
 94  
         
 95  399
         addChangeListenerName = names.fromString("addChangeListener");
 96  399
         locationInitializeName = names.fromString("initialize");
 97  399
         changeListenerInterfaceName = new Name[JavafxVarSymbol.TYPE_KIND_COUNT];
 98  2394
         for (int i=0; i< JavafxVarSymbol.TYPE_KIND_COUNT; i++)
 99  1995
             changeListenerInterfaceName[i]
 100  
                     = names.fromString(locationPackageNameString + "." + JavafxVarSymbol.getTypePrefix(i) + "ChangeListener");
 101  
  //       sequenceReplaceListenerInterfaceName = names.fromString(locationPackageName + "SequenceReplaceListener");
 102  399
         sequenceChangeListenerInterfaceName = names.fromString(locationPackageNameString + ".SequenceChangeListener");
 103  399
         addTriggersName = names.fromString("addTriggers$");
 104  399
         userInitName = names.fromString("userInit$");
 105  399
         postInitName = names.fromString("postInit$");
 106  399
         onChangeArgName1 = names.fromString("$oldValue");
 107  399
         onChangeArgName2 = names.fromString("$newValue");
 108  399
         outerAccessorName = names.fromString("accessOuter$");
 109  399
         outerAccessorFieldName = names.fromString("accessOuterField$");
 110  
         
 111  
         {
 112  399
             Name name = Name.fromString(names, initHelperClassName);
 113  399
             ClassSymbol sym = reader.enterClass(name);
 114  399
             initHelperType = sym.type;
 115  
         }
 116  
         {
 117  399
             Name name = Name.fromString(names, locationPackageNameString + ".AbstractVariable");
 118  399
             ClassSymbol sym = reader.enterClass(name);
 119  399
             abstractVariableType = types.erasure( sym.type );
 120  
         }
 121  399
     }
 122  
 
 123  
     /**
 124  
      * Hold the result of analyzing the class.
 125  
      * */
 126  
     static class JavafxClassModel {
 127  
         final Name interfaceName;
 128  
         final List<JCExpression> interfaces;
 129  
         final List<JCTree> iDefinitions;
 130  
         final List<JCTree> additionalClassMembers;
 131  
         final List<JCExpression> additionalImports;
 132  
         final Type superType;
 133  
 
 134  
         JavafxClassModel(
 135  
                 Name interfaceName,
 136  
                 List<JCExpression> interfaces,
 137  
                 List<JCTree> iDefinitions,
 138  
                 List<JCTree> addedClassMembers,
 139  
                 List<JCExpression> additionalImports,
 140  612
                 Type superType) {
 141  612
             this.interfaceName = interfaceName;
 142  612
             this.interfaces = interfaces;
 143  612
             this.iDefinitions = iDefinitions;
 144  612
             this.additionalClassMembers = addedClassMembers;
 145  612
             this.additionalImports = additionalImports;
 146  612
             this.superType = superType;
 147  612
         }
 148  
     }
 149  
 
 150  
     /**
 151  
      * Analyze the class.
 152  
      * 
 153  
      * Determine what methods will be needed to access attributes.
 154  
      * Determine what methods will be needed to proxy to the static implementations of functions.
 155  
      * Determine what other misc fields and methods will be needed.
 156  
      * Create the corresponding interface.
 157  
      * 
 158  
      * Return all this as a JavafxClassModel for use in translation.
 159  
      * */
 160  
    JavafxClassModel createJFXClassModel(JFXClassDeclaration cDecl, 
 161  
            List<TranslatedAttributeInfo> translatedAttrInfo, 
 162  
            List<TranslatedOverrideAttributeInfo> translatedOverrideAttrInfo) {
 163  612
         boolean classOnly = cDecl.generateClassOnly();
 164  612
         DiagnosticPosition diagPos = cDecl.pos();
 165  612
         Type superType = superType(cDecl);
 166  612
         ClassSymbol outerTypeSym = outerTypeSymbol(cDecl); // null unless inner class with outer reference
 167  
 
 168  612
         JavafxAnalyzeClass analysis = new JavafxAnalyzeClass(diagPos,
 169  
                 cDecl.sym, translatedAttrInfo, translatedOverrideAttrInfo,
 170  
                 log, names, types, reader, typeMorpher);
 171  612
         List<AttributeInfo> instanceAttributeInfos = analysis.instanceAttributeInfos();
 172  612
         List<ClassSymbol> javaInterfaces = immediateJavaInterfaceNames(cDecl);
 173  612
         List<ClassSymbol> immediateFxSupertypeNames = immediateJavafxSupertypes(cDecl);
 174  
 
 175  612
         ListBuffer<JCTree> cDefinitions = ListBuffer.lb();  // additional class members needed
 176  612
         cDefinitions.appendList(makeAttributeFields(instanceAttributeInfos));
 177  612
         cDefinitions.appendList(makeAttributeFields(analysis.staticAttributeInfos()));
 178  612
         cDefinitions.appendList(makeClassAttributeGetterMethods(cDecl, instanceAttributeInfos));
 179  612
         cDefinitions.appendList(makeClassAttributeApplyDefaultsMethods(diagPos, cDecl, instanceAttributeInfos));
 180  612
         cDefinitions.append(makeInitStaticAttributesBlock(cDecl, translatedAttrInfo));
 181  612
         cDefinitions.append(makeInitializeMethod(diagPos, instanceAttributeInfos, cDecl));
 182  612
         if (outerTypeSym != null) {
 183  8
             cDefinitions.append(makeClassOuterAccessorField(diagPos, cDecl, outerTypeSym));
 184  8
             cDefinitions.append(makeClassOuterAccessorMethod(diagPos, cDecl, outerTypeSym));
 185  
         }
 186  612
         cDefinitions.append(makeAddTriggersMethod(diagPos, cDecl, immediateFxSupertypeNames, translatedAttrInfo, translatedOverrideAttrInfo));
 187  612
         cDefinitions.appendList(makeClassFunctionProxyMethods(cDecl, analysis.needDispatch()));
 188  612
         if (outerTypeSym == null) {
 189  604
             cDefinitions.append(makeJavaEntryConstructor(diagPos));
 190  
         }
 191  612
         cDefinitions.append(makeFXEntryConstructor(diagPos, outerTypeSym, superType != null && types.isJFXClass(superType.tsym)));
 192  
 
 193  612
         ListBuffer<JCTree> iDefinitions = ListBuffer.lb();
 194  612
         if (!classOnly) {
 195  571
             iDefinitions.appendList(makeInterfaceAttributeGetterMethods(diagPos, translatedAttrInfo));
 196  571
             iDefinitions.appendList(makeInterfaceFunctionMethods(cDecl));
 197  571
             iDefinitions.appendList(makeInterfaceOuterAccessorMembers(cDecl));
 198  
         }
 199  
 
 200  612
         Name interfaceName = classOnly ? null : interfaceName(cDecl);
 201  
 
 202  612
         return new JavafxClassModel(
 203  
                 interfaceName,
 204  
                 makeImplementingInterfaces(diagPos, cDecl, javaInterfaces),
 205  
                 iDefinitions.toList(),
 206  
                 cDefinitions.toList(),
 207  
                 makeAdditionalImports(diagPos, cDecl, javaInterfaces),
 208  
                 superType);
 209  
     }
 210  
    
 211  
     private Type superType(JFXClassDeclaration cDecl) {
 212  
         //TODO: this is in drastic need of cleaning up
 213  612
         Type superType = null;
 214  612
         if (cDecl.type instanceof ClassType &&
 215  
                 (superType = ((ClassType) cDecl.type).supertype_field) != null &&
 216  
                 superType.tsym instanceof ClassSymbol &&
 217  
                 (superType.tsym.flags_field & JavafxFlags.COMPOUND_CLASS) == 0) {
 218  0
         } else if ((cDecl.mods.flags & Flags.FINAL) != 0L && cDecl.getExtending().nonEmpty()) {
 219  0
             Symbol sym1 = TreeInfo.symbol(cDecl.getExtending().head);
 220  0
             if (sym1 != null &&
 221  
                     (sym1.flags_field & JavafxFlags.COMPOUND_CLASS) == 0) {
 222  0
                 superType = cDecl.getExtending().head.type;
 223  
             }
 224  
         }
 225  612
         return superType;
 226  
     }
 227  
    
 228  
     private List<ClassSymbol> immediateJavafxSupertypes(JFXClassDeclaration cDecl) {
 229  612
         ListBuffer<ClassSymbol> javafxClassNamesBuff = ListBuffer.lb();
 230  612
         for (JCExpression stype : cDecl.getSupertypes()) {
 231  120
             Symbol sym = expressionSymbol(stype);
 232  120
             if (types.isJFXClass(sym)) {
 233  93
                 ClassSymbol cSym = (ClassSymbol) sym;
 234  93
                 javafxClassNamesBuff.append(cSym);
 235  
             }
 236  120
         }
 237  612
         return javafxClassNamesBuff.toList();
 238  
     }
 239  
 
 240  
    
 241  
     private List<ClassSymbol> immediateJavaInterfaceNames(JFXClassDeclaration cDecl) {
 242  612
         ListBuffer<ClassSymbol> javaInterfacesBuff = ListBuffer.lb();
 243  612
         for (JCExpression sup : cDecl.getSupertypes()) {
 244  120
             ClassSymbol cSym = (ClassSymbol) expressionSymbol(sup);
 245  120
             if (cSym != null) {
 246  120
                 String className = cSym.fullname.toString();
 247  120
                 boolean isFXInterface = className.endsWith(interfaceSuffix);
 248  
 
 249  120
                 if (!isFXInterface &&
 250  
                         cSym.fullname != names.fromString(fxObjectString) &&
 251  
                         (cSym.flags_field & JavafxFlags.COMPOUND_CLASS) != 0 &&
 252  
                         cSym.type != null) {
 253  87
                     javaInterfacesBuff.append(cSym);
 254  
                 }
 255  
             }
 256  120
         }
 257  612
         return javaInterfacesBuff.toList();
 258  
     }
 259  
 
 260  
     private List<JCTree> makeInterfaceFunctionMethods(JFXClassDeclaration cDecl) {
 261  571
         ListBuffer<JCTree> methods = ListBuffer.lb();
 262  571
         for (JCTree def : cDecl.getMembers()) {
 263  1743
             if (def.getTag() == JavafxTag.FUNCTION_DEF) {
 264  926
                 JFXFunctionDefinition func = (JFXFunctionDefinition) def;
 265  926
                 MethodSymbol sym = func.sym;
 266  926
                 if ((sym.flags() & (Flags.SYNTHETIC | Flags.STATIC)) == 0) {
 267  463
                     appendMethodClones(methods, cDecl, sym, false);
 268  
                 }
 269  1743
             }
 270  
         }
 271  571
         return methods.toList();
 272  
     }
 273  
     
 274  
     /** add proxies which redirect to the static implementation for every concrete method
 275  
      * 
 276  
      * @param cDecl
 277  
      * @param needDispatch
 278  
      * @return
 279  
      */
 280  
     private List<JCTree> makeClassFunctionProxyMethods(JFXClassDeclaration cDecl, List<MethodSymbol> needDispatch) {
 281  612
         ListBuffer<JCTree> methods = ListBuffer.lb();
 282  612
         for (MethodSymbol sym : needDispatch) {
 283  745
             appendMethodClones(methods, cDecl, sym, true);
 284  
         }
 285  612
         return methods.toList();
 286  
     }
 287  
     
 288  
     private void appendMethodClones(ListBuffer<JCTree> methods, JFXClassDeclaration cDecl, MethodSymbol sym, boolean withDispatch) {
 289  
         //TODO: static test is broken
 290  1208
         boolean isBound = (sym.flags() & JavafxFlags.BOUND) != 0;
 291  1208
         JCBlock mthBody = withDispatch ? makeDispatchBody(cDecl, sym, isBound, sym.flags() == Flags.STATIC) : null;
 292  1208
         methods.append(makeMethod(cDecl, sym, mthBody, isBound));
 293  1208
     }
 294  
     
 295  
     private List<JCExpression> makeImplementingInterfaces(DiagnosticPosition diagPos,
 296  
             JFXClassDeclaration cDecl, 
 297  
             List<ClassSymbol> baseInterfaces) {
 298  612
         ListBuffer<JCExpression> implementing = ListBuffer.lb();
 299  612
         implementing.append(makeIdentifier(diagPos, fxObjectString));
 300  626
         for (List<JCExpression> l = cDecl.getImplementing(); l.nonEmpty(); l = l.tail) {
 301  14
             implementing.append(makeTypeTree( null,l.head.type));
 302  
         }
 303  
 
 304  612
         for (ClassSymbol baseClass : baseInterfaces) {
 305  87
                 implementing.append(makeTypeTree( diagPos,baseClass.type, true));
 306  
         }
 307  612
         return implementing.toList();
 308  
     }
 309  
 
 310  
     private List<JCExpression> makeAdditionalImports(DiagnosticPosition diagPos, JFXClassDeclaration cDecl, List<ClassSymbol> baseInterfaces) {
 311  
         // Add import statements for all the base classes and basClass $Intf(s).
 312  
         // There might be references to them when the methods/attributes are rolled up.
 313  612
         ListBuffer<JCExpression> additionalImports = new ListBuffer<JCExpression>();
 314  612
         for (ClassSymbol baseClass : baseInterfaces) {
 315  87
             if (baseClass.type != null && baseClass.type.tsym != null &&
 316  
                     baseClass.type.tsym.packge() != cDecl.sym.packge() &&     // Work around javac bug (CR 6695838)
 317  
                     baseClass.type.tsym.packge() != syms.unnamedPackage) {    // Work around javac bug. the visitImport of Attr 
 318  
                 // is casting to JCFieldAcces, but if you have imported an
 319  
                 // JCIdent only a ClastCastException is thrown.
 320  5
                 additionalImports.append(makeTypeTree( diagPos,baseClass.type, false));
 321  5
                 additionalImports.append(makeTypeTree( diagPos,baseClass.type, true));
 322  
             }
 323  
         }
 324  612
         return additionalImports.toList();
 325  
     }
 326  
    
 327  
     /**
 328  
      * Make a constructor to be called by Java code.
 329  
      * It differs by calling the initialize$ method (that is explicitly called
 330  
      * by FX code).
 331  
      * @param diagPos
 332  
      * @return the constructor
 333  
      */
 334  
     private JCMethodDecl makeJavaEntryConstructor(DiagnosticPosition diagPos) {
 335  
         // call the FX (basic) version of the constructor
 336  604
         JCStatement thisCall = make.at(diagPos).Exec(make.at(diagPos).Apply(null,
 337  
                 make.at(diagPos).Ident(names._this),
 338  
                 List.<JCExpression>of(make.at(diagPos).Literal(TypeTags.BOOLEAN, 0))));
 339  
         // then call the initialize$ method
 340  604
         JCStatement initCall = make.at(diagPos).Exec(make.at(diagPos).Apply(null,
 341  
                 make.at(diagPos).Ident(defs.initializeName),
 342  
                 List.<JCExpression>nil()));
 343  604
         return makeConstructor(diagPos, List.<JCVariableDecl>nil(), List.of(thisCall, initCall));
 344  
     }
 345  
 
 346  
     /**
 347  
      * Make a constructor to be called by JavaFX code.
 348  
      * @param diagPos
 349  
      * @param superIsFX true if there is a super class (in the generated code) and it is a JavaFX class
 350  
      * @return the constructor
 351  
      */
 352  
     private JCMethodDecl makeFXEntryConstructor(DiagnosticPosition diagPos, ClassSymbol outerTypeSym, boolean superIsFX) {    
 353  612
         make.at(diagPos);     
 354  612
         ListBuffer<JCStatement> stmts = ListBuffer.lb();
 355  612
         ListBuffer<JCVariableDecl> params = ListBuffer.lb();
 356  612
         if (outerTypeSym != null) {
 357  
                // add a parameter and a statement to constructor for the outer instance reference
 358  8
                 params.append( make.VarDef(make.Modifiers(0L), outerAccessorFieldName, make.Ident(outerTypeSym), null) );
 359  8
                 JCFieldAccess cSelect = make.Select(make.Ident(names._this), outerAccessorFieldName);
 360  8
                 JCAssign assignStat = make.Assign(cSelect, make.Ident(outerAccessorFieldName));
 361  8
                 stmts.append(make.Exec(assignStat));            
 362  
         }
 363  612
         Name dummyParamName = names.fromString("dummy");
 364  612
         params.append( make.at(diagPos).VarDef(
 365  
                 make.Modifiers(Flags.PARAMETER),
 366  
                 dummyParamName,
 367  
                 makeTypeTree( diagPos,syms.booleanType),
 368  
                 null) );
 369  612
         if (superIsFX) {
 370  
             // call the FX version of the constructor
 371  6
             stmts.append(make.Exec(make.Apply(null,
 372  
                     make.Ident(names._super),
 373  
                     List.<JCExpression>of(make.Ident(dummyParamName)))));
 374  
         }
 375  612
         return makeConstructor(diagPos, params.toList(), stmts.toList());
 376  
     }
 377  
     
 378  
    private JCMethodDecl makeConstructor(DiagnosticPosition diagPos, List<JCVariableDecl> params, List<JCStatement> cStats) {
 379  1216
        return make.MethodDef(make.Modifiers(Flags.PUBLIC), 
 380  
                names.init, 
 381  
                make.TypeIdent(TypeTags.VOID), 
 382  
                List.<JCTypeParameter>nil(), 
 383  
                params,
 384  
                List.<JCExpression>nil(), 
 385  
                make.Block(0L, cStats), 
 386  
                null);
 387  
 
 388  
    }
 389  
     
 390  
     // Add the methods and field for accessing the outer members. Also add a constructor with an extra parameter to handle the instantiation of the classes that access outer members
 391  
     private ClassSymbol outerTypeSymbol(JFXClassDeclaration cdecl) {
 392  612
         if (cdecl.sym != null && toJava.hasOuters.contains(cdecl.sym)) {
 393  8
             Symbol typeOwner = cdecl.sym.owner;
 394  16
             while (typeOwner != null && typeOwner.kind != Kinds.TYP) {
 395  8
                 typeOwner = typeOwner.owner;
 396  
             }
 397  
             
 398  8
             if (typeOwner != null) {
 399  
                 // If FINAL class, it is an anonymous class. There is no interface for it and we need to have the type of the
 400  
                 // type, not it's interface.
 401  8
                 return (typeOwner.flags_field & Flags.FINAL) != 0 ? (ClassSymbol)typeOwner.type.tsym :
 402  
                         reader.jreader.enterClass(names.fromString(typeOwner.type.toString() + interfaceSuffix));
 403  
             }
 404  
         }
 405  604
         return null;
 406  
    }
 407  
     
 408  
     // Make the field for accessing the outer members
 409  
     private JCTree makeClassOuterAccessorField(DiagnosticPosition diagPos, JFXClassDeclaration cdecl, ClassSymbol outerTypeSym) {
 410  
         // Create the field to store the outer instance reference
 411  8
         return make.at(diagPos).VarDef(make.at(diagPos).Modifiers(Flags.PUBLIC), outerAccessorFieldName, make.Ident(outerTypeSym), null);
 412  
     }
 413  
 
 414  
     // Make the method for accessing the outer members
 415  
     private JCTree makeClassOuterAccessorMethod(DiagnosticPosition diagPos, JFXClassDeclaration cdecl, ClassSymbol outerTypeSym) {
 416  8
         make.at(diagPos);
 417  8
         VarSymbol vs = new VarSymbol(Flags.PUBLIC, outerAccessorFieldName, outerTypeSym.type, cdecl.sym);
 418  8
         JCIdent retIdent = make.Ident(vs);
 419  8
         JCStatement retRet = make.Return(retIdent);
 420  8
         List<JCStatement> mStats = List.of(retRet);
 421  8
         return make.MethodDef(make.Modifiers(Flags.PUBLIC), outerAccessorName, make.Ident(outerTypeSym), List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(),
 422  
                 List.<JCExpression>nil(), make.Block(0L, mStats), null);
 423  
     }
 424  
 
 425  
     // methods for accessing the outer members.
 426  
     private List<JCTree> makeInterfaceOuterAccessorMembers(JFXClassDeclaration cdecl) {
 427  571
         ListBuffer<JCTree> members = ListBuffer.lb();
 428  571
         if (cdecl.sym != null && toJava.hasOuters.contains(cdecl.sym)) {
 429  0
             Symbol typeOwner = cdecl.sym.owner;
 430  0
             while (typeOwner != null && typeOwner.kind != Kinds.TYP) {
 431  0
                 typeOwner = typeOwner.owner;
 432  
             }
 433  
 
 434  0
             if (typeOwner != null) {
 435  0
                 ClassSymbol returnSym = typeMorpher.reader.enterClass(names.fromString(typeOwner.type.toString() + interfaceSuffix));
 436  0
                 JCMethodDecl accessorMethod = make.MethodDef(make.Modifiers(Flags.PUBLIC), outerAccessorName, make.Ident(returnSym), List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(),
 437  
                         List.<JCExpression>nil(), null, null);
 438  
 
 439  0
                 accessorMethod.type = new MethodType(List.<Type>nil(), returnSym.type, List.<Type>nil(), returnSym);
 440  0
                 accessorMethod.sym = new MethodSymbol(Flags.PUBLIC, outerAccessorName, returnSym.type, returnSym);
 441  
 
 442  0
                 members.append(accessorMethod);
 443  
             }
 444  
         }
 445  571
         return members.toList();
 446  
     }
 447  
 
 448  
     private List<JCTree> makeInterfaceAttributeGetterMethods(DiagnosticPosition diagPos, List<? extends AttributeInfo> attrInfos) {
 449  571
         ListBuffer<JCTree> getters = ListBuffer.lb();
 450  571
         for (AttributeInfo ai : attrInfos) {
 451  532
             if (!ai.isStatic()) {
 452  461
                 JCModifiers mods = make.Modifiers(Flags.PUBLIC | Flags.ABSTRACT);
 453  461
                 mods = addAccessAnnotationModifiers(diagPos, ai.getFlags(), mods);
 454  461
                 getters.append(make.MethodDef(
 455  
                         mods,
 456  
                         names.fromString(attributeGetMethodNamePrefix + ai.getNameString()),
 457  
                         makeTypeTree( null,ai.getVariableType()),
 458  
                         List.<JCTypeParameter>nil(),
 459  
                         List.<JCVariableDecl>nil(),
 460  
                         List.<JCExpression>nil(),
 461  
                         null, null));
 462  532
             }
 463  
         }
 464  571
         return getters.toList();
 465  
     }
 466  
 
 467  
     private List<JCTree> makeClassAttributeGetterMethods(JFXClassDeclaration cDecl, List<? extends AttributeInfo> attrInfos) {
 468  612
         ListBuffer<JCTree> getters = ListBuffer.lb();
 469  612
         for (AttributeInfo ai : attrInfos) {
 470  1017
             if (ai.needsCloning()) {
 471  1016
                 long flags = ai.getFlags();
 472  1016
                 DiagnosticPosition diagPos = ai.pos();
 473  1016
                 Name attribName = ai.getName();
 474  1016
                 String attribString = ai.getNameString();
 475  1016
                 Name methodName = names.fromString(attributeGetMethodNamePrefix + attribString);
 476  
 
 477  
                 // Add the return statement for the attribute
 478  1016
                 JCExpression value = make.Ident(attribName);
 479  1016
                 JCStatement returnStat = make.at(diagPos).Return(value);
 480  1016
                 JCBlock statBlock = make.at(diagPos).Block(0L, List.of(returnStat));
 481  
 
 482  
                 // Add the method for this class' attributes
 483  1016
                 JCModifiers mods = make.Modifiers(Flags.PUBLIC);
 484  1016
                 mods = addAccessAnnotationModifiers(diagPos, flags, mods);
 485  1016
                 getters.append(make.at(diagPos).MethodDef(
 486  
                         mods,
 487  
                         methodName,
 488  
                         makeTypeTree( null,ai.getVariableType()),
 489  
                         List.<JCTypeParameter>nil(),
 490  
                         List.<JCVariableDecl>nil(),
 491  
                         List.<JCExpression>nil(),
 492  
                         statBlock,
 493  
                         null));
 494  1017
             }
 495  
         }
 496  612
         return getters.toList();
 497  
     }
 498  
         
 499  
     private boolean isAttributeOriginClass(Symbol sym, Name attrName, Name getterName) {
 500  668
         if (types.isJFXClass(sym)) {
 501  665
             ClassSymbol supertypeSym = (ClassSymbol) sym;
 502  58656
             for (Entry e = supertypeSym.members().elems; e != null && e.sym != null; e = e.sibling) { 
 503  58517
                 if ((e.sym.kind == Kinds.MTH && e.sym.name == getterName) ||
 504  
                         (e.sym.kind == Kinds.VAR && e.sym.name == attrName)) {
 505  526
                     return true;
 506  
                 }
 507  
             }
 508  
             // not directly in this class, try in the superclass
 509  139
             for (Type supertype : supertypeSym.getInterfaces()) {
 510  132
                 if (isAttributeOriginClass(supertype.tsym, attrName, getterName) ) {
 511  131
                     return true;
 512  
                 }
 513  
             }
 514  
         }
 515  11
         return false;
 516  
     }
 517  
         
 518  
     /**
 519  
      * Construct the applyDefaults method
 520  
      */
 521  
     private List<JCTree> makeClassAttributeApplyDefaultsMethods(DiagnosticPosition diagPos,
 522  
             JFXClassDeclaration cDecl,
 523  
             List<? extends AttributeInfo> attrInfos) {
 524  612
         ListBuffer<JCTree> methods = ListBuffer.lb();
 525  612
         for (AttributeInfo ai : attrInfos) {
 526  1017
             if (ai.needsCloning()) {
 527  1016
                 String attribString = ai.getNameString();
 528  1016
                 Name methodName = names.fromString(attributeApplyDefaultsMethodNamePrefix +  attribString);
 529  1016
                 ListBuffer<JCStatement> stmts = ListBuffer.lb();
 530  
 
 531  1016
                 if (ai.getDefaultInitializtionStatement() != null) {
 532  
                     // a default exists, either on the direct attribute or on an override
 533  490
                     stmts.append(ai.getDefaultInitializtionStatement());
 534  
                 } else {
 535  
                     // no default, look for the supertype which defines it, and defer to it
 536  526
                     ClassSymbol attrParent = null;
 537  526
                     Name getterName = names.fromString(attributeGetMethodNamePrefix + attribString);
 538  526
                     for (JCExpression supertype : cDecl.getSupertypes()) {
 539  536
                         Symbol sym = supertype.type.tsym;
 540  536
                         if (isAttributeOriginClass(sym, ai.getName(), getterName) ) {
 541  526
                             attrParent = (ClassSymbol) sym;
 542  526
                             break;
 543  
                         }
 544  10
                     }
 545  526
                     assert attrParent != null : "Parent supertype for attribute " + attribString + " not found";
 546  526
                     if (attrParent != null) {
 547  526
                         stmts.append( makeSuperCall(diagPos, attrParent, methodName) );
 548  
                     }
 549  
                 }
 550  1016
                 JCBlock statBlock = make.at(diagPos).Block(0L, stmts.toList());
 551  
 
 552  
                 // Add the method for this class' attributes
 553  1016
                 JCModifiers mods = make.Modifiers(Flags.PUBLIC | (cDecl.generateClassOnly()? 0L : Flags.STATIC) );
 554  1016
                 methods.append(make.at(diagPos).MethodDef(
 555  
                         mods,
 556  
                         methodName,
 557  
                         makeTypeTree( null,syms.voidType),
 558  
                         List.<JCTypeParameter>nil(),
 559  
                         List.<JCVariableDecl>of(makeReceiverParam(cDecl)),
 560  
                         List.<JCExpression>nil(),
 561  
                         statBlock,
 562  
                         null));
 563  1017
             }
 564  
         }
 565  612
         return methods.toList();
 566  
     }
 567  
     
 568  
     private JCStatement makeSuperCall(DiagnosticPosition diagPos, ClassSymbol cSym, Name methodName) {
 569  
         JCExpression receiver;
 570  619
         List<JCExpression> arg = List.<JCExpression>of(make.at(diagPos).Ident(defs.receiverName));
 571  619
         if ((cSym.flags() & JavafxFlags.COMPOUND_CLASS) != 0) {
 572  
             // call to a compound super, use static reference
 573  613
             receiver = makeTypeTree( diagPos,cSym.type, false);
 574  
         } else {
 575  
             // call to a non-compound super, use "super"
 576  6
             receiver = make.at(diagPos).Ident(names._super);
 577  
         }
 578  619
         return callStatement(diagPos, receiver, methodName, arg);
 579  
     }
 580  
 
 581  
     private List<JCStatement> makeAllSuperCalls(DiagnosticPosition diagPos,
 582  
             List<ClassSymbol> javafxClasses, Name methodName) {
 583  612
         ListBuffer<JCStatement> stmts = ListBuffer.lb();
 584  612
         for (ClassSymbol cSym : javafxClasses) {
 585  93
             stmts.append( makeSuperCall(diagPos, cSym, methodName) );
 586  
         }
 587  612
         return stmts.toList();
 588  
     }
 589  
     
 590  
     private JCMethodDecl makeInitializeMethod(DiagnosticPosition diagPos,
 591  
             List<AttributeInfo> attrInfos,
 592  
             JFXClassDeclaration cDecl) {
 593  612
         boolean classIsFinal = (cDecl.getModifiers().flags & Flags.FINAL) != 0;
 594  612
         ListBuffer<JCStatement> stmts = ListBuffer.lb();
 595  
 
 596  
         // Add calls to do the the default value initialization and user init code (validation for example.)
 597  
         
 598  
         // "addTriggers$(this);"
 599  612
        stmts.append( callStatement(
 600  
                diagPos, 
 601  
                null, 
 602  
                addTriggersName, 
 603  
                make.at(diagPos).Ident(names._this)));
 604  
 
 605  
        // "initAttributes$(this);"
 606  612
         stmts.appendList( makeInitAttributesCode(attrInfos, cDecl) );
 607  
         
 608  
         // "userInit$(this);"
 609  612
         stmts.append(callStatement(
 610  
                 diagPos, 
 611  
                 make.Ident(classIsFinal? names._this : cDecl.getName()),
 612  
                 userInitName, 
 613  
                 make.TypeCast(make.Ident(interfaceName(cDecl)), make.Ident(names._this))));
 614  
         
 615  
         // "postInit$(this);"
 616  612
         stmts.append(callStatement(
 617  
                 diagPos,
 618  
                 make.Ident(classIsFinal? names._this : cDecl.getName()),
 619  
                 postInitName,
 620  
                 make.TypeCast(make.Ident(interfaceName(cDecl)), make.Ident(names._this))));
 621  
 
 622  
         // "InitHelper.finish(new[] { attribute, ... });
 623  612
         ListBuffer<JCExpression> attrs = ListBuffer.lb();
 624  612
         for (AttributeInfo ai : attrInfos) {
 625  1017
             if (ai.needsCloning()) {
 626  1016
                 attrs.append(make.at(diagPos).Ident(ai.getName()));
 627  
             }
 628  
         }                
 629  
 
 630  612
         stmts.append( callStatement(diagPos, 
 631  
                 makeTypeTree(diagPos, initHelperType), 
 632  
                 "finish",
 633  
                 make.NewArray(makeTypeTree(diagPos, abstractVariableType), 
 634  
                                 List.<JCExpression>nil(), attrs.toList())));
 635  
 
 636  612
         JCBlock initializeBlock = make.Block(0L, stmts.toList());
 637  612
         return make.MethodDef(
 638  
                 make.Modifiers(Flags.PUBLIC),
 639  
                 defs.initializeName,
 640  
                 makeTypeTree( null,syms.voidType),
 641  
                 List.<JCTypeParameter>nil(), 
 642  
                 List.<JCVariableDecl>nil(), 
 643  
                 List.<JCExpression>nil(), 
 644  
                 initializeBlock, null);
 645  
     }
 646  
     
 647  
     // Add the initialization of this class' attributes
 648  
     private List<JCStatement> makeInitAttributesCode(List<AttributeInfo> attrInfos,
 649  
             JFXClassDeclaration cDecl) {
 650  612
         ListBuffer<JCStatement> stmts = ListBuffer.lb();
 651  612
         for (AttributeInfo ai : attrInfos) {
 652  1017
             if ((ai.getFlags() & Flags.STATIC) == 0) {
 653  1017
                 DiagnosticPosition diagPos = ai.pos();
 654  1017
                 String attribName = ai.getNameString();
 655  1017
                 Name methodName = names.fromString(attributeApplyDefaultsMethodNamePrefix + attribName);
 656  
 
 657  1017
                 List<JCExpression> arg = List.<JCExpression>of(make.at(diagPos).Ident(names._this));
 658  1017
                 JCStatement applyDefaultsCall = callStatement(diagPos, null, methodName, arg);
 659  1017
                 JCExpression needsDefaultCond = callExpression(diagPos,
 660  
                         make.at(diagPos).Ident(ai.getName()),
 661  
                         defs.needDefaultsMethodName);
 662  1017
                 JCStatement protectedCall = make.If(needsDefaultCond, applyDefaultsCall, null);
 663  1017
                 stmts.append( protectedCall );
 664  1017
             }
 665  
         }
 666  612
         return stmts.toList();
 667  
     }
 668  
     
 669  
     /**
 670  
      * Construct the static block for setting defaults
 671  
      * */
 672  
     private JCBlock makeInitStaticAttributesBlock(JFXClassDeclaration cDecl,
 673  
             List<TranslatedAttributeInfo> translatedAttrInfo) {
 674  
         // Add the initialization of this class' attributesa
 675  612
         ListBuffer<JCStatement> stmts = ListBuffer.lb();
 676  612
         for (TranslatedAttributeInfo tai : translatedAttrInfo) {
 677  556
             assert tai.attribute != null && tai.attribute.getTag() == JavafxTag.VAR_DEF && tai.attribute.pos != Position.NOPOS;
 678  556
             if (tai.isStatic()) {
 679  75
                 if (tai.isDirectOwner()) {
 680  75
                     DiagnosticPosition diagPos = tai.pos();
 681  75
                     if (tai.getDefaultInitializtionStatement() != null) {
 682  42
                         stmts.append(tai.getDefaultInitializtionStatement());
 683  
                     }
 684  75
                     stmts.append( callStatement(diagPos, make.at(diagPos).Ident(tai.getName()), locationInitializeName));
 685  
                 }
 686  75
                 JCStatement stat = makeStaticChangeListenerCall(tai);
 687  75
                 if (stat != null) {
 688  0
                     stmts.append(stat);
 689  
                 }
 690  556
             }
 691  
         }
 692  612
         return make.Block(Flags.STATIC, stmts.toList());
 693  
     }
 694  
 
 695  
     /**
 696  
      * Construct the addTriggers method
 697  
      * */
 698  
     private JCMethodDecl makeAddTriggersMethod(DiagnosticPosition diagPos, 
 699  
                                                JFXClassDeclaration cDecl,
 700  
                                                List<ClassSymbol> javafxSupers,
 701  
                                                List<TranslatedAttributeInfo> translatedAttrInfo,
 702  
                                                List<TranslatedOverrideAttributeInfo> translatedTriggerInfo) {
 703  612
         ListBuffer<JCStatement> stmts = ListBuffer.lb();
 704  
 
 705  
         // call the superclasses addTriggers
 706  612
         stmts.appendList( makeAllSuperCalls(diagPos, javafxSupers, addTriggersName) );
 707  
 
 708  
         // add change listeners for triggers on attribute definitions
 709  612
         for (TranslatedAttributeInfo info : translatedAttrInfo) {
 710  556
             JCStatement stat = makeChangeListenerCall(info);
 711  556
             if (stat != null)
 712  113
                 stmts.append(stat);
 713  556
         }
 714  
 
 715  
         // add change listeners for "with" triggers
 716  612
         for (TranslatedOverrideAttributeInfo info : translatedTriggerInfo) {
 717  9
             JCStatement stat = makeChangeListenerCall(info);
 718  9
             if (stat != null)
 719  6
                 stmts.append(stat);
 720  9
         }
 721  
 
 722  612
         return make.at(diagPos).MethodDef(
 723  
                 make.Modifiers(Flags.PUBLIC | (cDecl.generateClassOnly()? 0L : Flags.STATIC) ),
 724  
                 addTriggersName,
 725  
                 makeTypeTree( null,syms.voidType),
 726  
                 List.<JCTypeParameter>nil(),
 727  
                 List.<JCVariableDecl>of( makeReceiverParam(cDecl) ),
 728  
                 List.<JCExpression>nil(),
 729  
                 make.Block(0L, stmts.toList()),
 730  
                 null);
 731  
     }
 732  
 
 733  
     // build a field for each non-static attribute (including inherited).
 734  
     // and for static attributes of this class
 735  
     private List<JCTree> makeAttributeFields(List<? extends AttributeInfo> attrInfos) {
 736  1224
         ListBuffer<JCTree> fields = ListBuffer.lb();
 737  1224
         for (AttributeInfo ai : attrInfos) {
 738  1092
             if (ai.needsCloning()) {
 739  1091
                 DiagnosticPosition diagPos = ai.pos();
 740  1091
                 JCVariableDecl var = make.at(diagPos).VarDef(
 741  
                         make.Modifiers(Flags.PUBLIC | Flags.FINAL | (ai.getFlags() & Flags.STATIC)),
 742  
                         ai.getName(),
 743  
                         makeTypeTree( diagPos,ai.getVariableType()),
 744  
                         makeLocationAttributeVariable(ai.getVMI(), diagPos));
 745  1091
                 fields.append(var);
 746  1092
             }
 747  
         }
 748  1224
         return fields.toList();
 749  
     }
 750  
     
 751  
              
 752  
     /**
 753  
      * Non-destructive creation of "on change" change listener set-up call.
 754  
      */
 755  
     JCStatement makeChangeListenerCall(AttributeInfo info) {
 756  
         
 757  
         //TODO: TranslatedAttributeInfo should be simplified to hold onReplace attribute only
 758  
         //
 759  572
         JFXOnReplace onReplace = null;
 760  
         
 761  572
         if (info instanceof TranslatedAttributeInfo) {
 762  563
             TranslatedAttributeInfo tran_info = (TranslatedAttributeInfo)info;
 763  
        
 764  563
             onReplace = tran_info.onReplace();
 765  563
             if (onReplace == null)
 766  443
                 return null;
 767  120
         } else {
 768  9
             if (info instanceof TranslatedOverrideAttributeInfo) 
 769  9
                 onReplace = ((TranslatedOverrideAttributeInfo)info).onReplace();
 770  
         }
 771  
         
 772  
         
 773  129
         if (onReplace == null) return null;
 774  
         
 775  126
         DiagnosticPosition diagPos = info.pos();
 776  126
         ListBuffer<JCTree> members = ListBuffer.lb();
 777  
 
 778  
         JCExpression changeListener;
 779  126
         List<JCExpression> emptyTypeArgs = List.nil();
 780  126
         int attributeKind = typeMorpher.varMorphInfo(info.getSymbol()).getTypeKind();
 781  
         
 782  126
         if (types.isSequence(info.getRealType())) {
 783  35
             ListBuffer<JCStatement> setUpStmts = ListBuffer.lb();
 784  
 //            changeListener = make.at(diagPos).Identifier(sequenceReplaceListenerInterfaceName);
 785  35
             changeListener = makeIdentifier(diagPos, sequenceChangeListenerInterfaceName);
 786  35
             changeListener = make.TypeApply(changeListener, List.of(makeTypeTree( diagPos,info.getElementType())));
 787  35
             Type seqValType = types.sequenceType(info.getElementType(), false);
 788  35
             List<JCVariableDecl> onChangeArgs = List.of(
 789  
                 makeIndexParam(diagPos, onReplace),
 790  
                 makeParam(diagPos, syms.intType, onReplace.getLastIndex(), "$lastIndex$"),
 791  
                 makeParam(diagPos, info.getRealType(), onReplace.getNewElements(), "$newElements$"),
 792  
                 makeParam(diagPos, seqValType, onReplace.getOldValue(), "$oldValue$"),
 793  
                 makeParam(diagPos, seqValType, null, "$newValue$"));
 794  
    //         members.append(makeChangeListenerMethod(diagPos, onReplace, setUpStmts, "onReplace", onChangeArgs, TypeTags.VOID));
 795  35
             members.append(makeChangeListenerMethod(diagPos, onReplace, setUpStmts, "onChange", onChangeArgs, TypeTags.VOID));
 796  35
         }
 797  
         else {
 798  91
             changeListener = makeIdentifier(diagPos, changeListenerInterfaceName[attributeKind]);
 799  91
             members.append(makeOnReplaceChangeListenerMethod(diagPos, onReplace, info.getRealType()));
 800  
         }
 801  
 
 802  126
         if (attributeKind == JavafxVarSymbol.TYPE_KIND_OBJECT)
 803  34
             changeListener = make.at(diagPos).TypeApply(changeListener,
 804  
                                                         List.<JCExpression>of(makeTypeTree( diagPos,info.getRealType())));
 805  126
         JCNewClass anonymousChangeListener = make.NewClass(
 806  
                 null, 
 807  
                 emptyTypeArgs,
 808  
                 changeListener, 
 809  
                 List.<JCExpression>nil(), 
 810  
                 make.at(diagPos).AnonymousClassDef(make.Modifiers(0L), members.toList()));
 811  
 
 812  
         JCExpression attrRef;
 813  
         // if it is an attribute
 814  126
         if (info.getSymbol().owner.kind == Kinds.TYP) {
 815  119
              attrRef = makeAttributeAccess(diagPos, info.getNameString());
 816  
         } else {
 817  7
              attrRef = makeIdentifier(diagPos, info.getNameString());
 818  
         }
 819  126
         JCFieldAccess tmpSelect = make.at(diagPos).Select(attrRef, addChangeListenerName);
 820  
 
 821  126
         List<JCExpression> args = List.<JCExpression>of(anonymousChangeListener);
 822  126
         return make.at(diagPos).Exec(make.at(diagPos).Apply(emptyTypeArgs, tmpSelect, args));
 823  
     }
 824  
     
 825  
     private JCVariableDecl makeParam(DiagnosticPosition diagPos, Type type, JFXVar var, String nameDefault) {
 826  
         Name name;
 827  175
         if (var != null) {
 828  95
             name = var.getName();
 829  95
             diagPos = var.pos();
 830  
         } else {
 831  80
             name = names.fromString(nameDefault);
 832  
         }
 833  175
         long flags = Flags.PARAMETER|Flags.FINAL;
 834  175
         if (var != null && var.mods != null) {
 835  95
             flags |= var.mods.flags;
 836  
         }
 837  175
         return make.at(diagPos).VarDef(
 838  
                 make.Modifiers(flags),
 839  
                 name,
 840  
                 makeTypeTree(diagPos, type),
 841  
                 null);
 842  
         
 843  
     }
 844  
     
 845  
     private JCVariableDecl makeIndexParam(DiagnosticPosition diagPos, JFXOnReplace onReplace) {
 846  
  //       return makeParam(diagPos, syms.intType, onReplace == null ? null : onReplace.getIndex(), "$index$");
 847  35
         return makeParam(diagPos, syms.intType, onReplace == null ? null : onReplace.getFirstIndex(), "$index$");
 848  
     }
 849  
      
 850  
     
 851  
     /**
 852  
      * construct a change listener method for insertion in a listener anon class.
 853  
      *   void onReplace(...); ...
 854  
      */
 855  
     private JCMethodDecl makeOnReplaceChangeListenerMethod(DiagnosticPosition diagPos,
 856  
                                                            JFXOnReplace onReplace,
 857  
                                                            Type attributeType) {
 858  91
         List<JCVariableDecl> onChangeArgs = List.<JCVariableDecl>nil()
 859  
                 .append(make.VarDef(make.Modifiers(0L), onChangeArgName1, makeTypeTree(diagPos, attributeType), null))
 860  
                 .append(make.VarDef(make.Modifiers(0L), onChangeArgName2, makeTypeTree(diagPos, attributeType), null));
 861  91
         ListBuffer<JCStatement> setUpStmts = ListBuffer.lb();
 862  91
         if (onReplace != null && onReplace.getOldValue() != null) {
 863  
             // Create the variable for the old value, using the specified name
 864  29
             JFXVar oldValue = onReplace.getOldValue();
 865  29
             VarMorphInfo vmi = typeMorpher.varMorphInfo(oldValue.sym);
 866  
 
 867  29
             setUpStmts.append( 
 868  
                     make.at(diagPos).VarDef(
 869  
                         make.Modifiers(0L), 
 870  
                         oldValue.getName(), 
 871  
                         makeTypeTree( diagPos, vmi.getRealType(),types.isJFXClass(vmi.getRealType().tsym)),
 872  
                         makeIdentifier(diagPos, onChangeArgName1)));
 873  
         }
 874  91
         if (onReplace != null && onReplace.getNewElements() != null) {
 875  
             // Create the variable for the new value, using the specified name
 876  7
             JFXVar newValue = onReplace.getNewElements();
 877  7
             VarMorphInfo vmi = typeMorpher.varMorphInfo(newValue.sym);
 878  
 
 879  7
             setUpStmts.append( 
 880  
                     make.at(diagPos).VarDef(
 881  
                         make.Modifiers(0L), 
 882  
                         newValue.getName(), 
 883  
                         makeTypeTree( diagPos, vmi.getRealType(),types.isJFXClass(vmi.getRealType().tsym)),
 884  
                         makeIdentifier(diagPos, onChangeArgName2)));
 885  
         }
 886  91
         return makeChangeListenerMethod(diagPos, onReplace, setUpStmts, "onChange", onChangeArgs, TypeTags.VOID);
 887  
     }
 888  
 
 889  
     /**
 890  
      * construct a change listener method for insertion in a listener anon class.
 891  
      *   boolean onChange();
 892  
      *   void onInsert(...);
 893  
      *   void on Delete(...); ...
 894  
      */
 895  
     private JCMethodDecl makeChangeListenerMethod(
 896  
             DiagnosticPosition diagPos,
 897  
             JFXOnReplace onReplace,
 898  
             ListBuffer<JCStatement> prefixStmts,
 899  
             String methodName,
 900  
             List<JCVariableDecl> args,
 901  
             int returnTypeTag) {
 902  126
         ListBuffer<JCStatement> ocMethStmts = ListBuffer.lb();
 903  126
         ocMethStmts.appendList(prefixStmts);
 904  
         
 905  126
         if (onReplace != null) {
 906  126
             diagPos = onReplace.pos();
 907  126
             ocMethStmts.appendList(onReplace.getBody().getStatements());
 908  
         }
 909  
         
 910  126
         if (returnTypeTag == TypeTags.BOOLEAN) {
 911  0
             ocMethStmts.append(make.at(diagPos).Return(make.at(diagPos).Literal(TypeTags.BOOLEAN, 1)));
 912  
         }
 913  
 
 914  126
         return make.at(diagPos).MethodDef(
 915  
                 make.at(diagPos).Modifiers(Flags.PUBLIC), 
 916  
                 names.fromString(methodName), 
 917  
                 make.at(diagPos).TypeIdent(returnTypeTag), 
 918  
                 List.<JCTypeParameter>nil(), 
 919  
                 args,
 920  
                 List.<JCExpression>nil(), 
 921  
                 make.at(diagPos).Block(0L, ocMethStmts.toList()), 
 922  
                 null);
 923  
     }
 924  
 
 925  
     JCStatement makeStaticChangeListenerCall(TranslatedAttributeInfo info) {
 926  
         // TBD static attribute triggers
 927  75
         return null;
 928  
     }
 929  
 
 930  
     /**
 931  
      * Make a method from a MethodSymbol and an optional method body.
 932  
      * Make a bound version if "isBound" is set.
 933  
      */
 934  
     private JCMethodDecl makeMethod(DiagnosticPosition diagPos, MethodSymbol mth, JCBlock mthBody, boolean isBound) {
 935  
         // build the parameter list
 936  1208
         ListBuffer<JCVariableDecl> params = ListBuffer.lb();
 937  1208
         for (VarSymbol vsym : mth.getParameters()) {
 938  1176
             Type vtype = vsym.asType();
 939  1176
             if (isBound) {
 940  12
                 VarMorphInfo vmi = typeMorpher.varMorphInfo(vsym);
 941  12
                 vtype = vmi.getLocationType();
 942  
             }
 943  1176
             params.append(make.VarDef(
 944  
                     make.Modifiers(0L), 
 945  
                     vsym.name, 
 946  
                     makeTypeTree(diagPos, vtype), 
 947  
                     null // no initial value
 948  
                      // no initial value
 949  
                     ));
 950  1176
         }
 951  
         
 952  
         // make the method
 953  1208
         JCModifiers mods = make.Modifiers(Flags.PUBLIC | (mthBody==null? Flags.ABSTRACT : 0L));
 954  1208
         mods = addAccessAnnotationModifiers(diagPos, mth.flags(), mods);
 955  1208
         return make.at(diagPos).MethodDef(
 956  
                         mods, 
 957  
                         functionName(mth, false, isBound), 
 958  
                         makeReturnTypeTree(diagPos, mth, isBound), 
 959  
                         List.<JCTypeParameter>nil(), 
 960  
                         params.toList(), 
 961  
                         List.<JCExpression>nil(), 
 962  
                         mthBody, 
 963  
                         null);
 964  
     }
 965  
     
 966  
     /**
 967  
      * Make a method body which redirects to the actual implementation in a static method of the defining class.
 968  
      */
 969  
     private JCBlock makeDispatchBody(DiagnosticPosition diagPos, MethodSymbol mth, boolean isBound, boolean isStatic) {
 970  745
         ListBuffer<JCExpression> args = ListBuffer.lb();
 971  745
         if (!isStatic) {
 972  
             // Add the this argument, so the static implementation method is invoked
 973  745
             args.append(make.Ident(names._this));
 974  
         }
 975  745
         for (VarSymbol var : mth.params) {
 976  658
             args.append(make.Ident(var.name));
 977  
         }
 978  745
         JCExpression receiver = makeTypeTree( diagPos,mth.owner.type, false);
 979  745
         JCExpression expr = callExpression(diagPos, receiver, functionName(mth, !isStatic, isBound), args);
 980  745
         JCStatement statement = (mth.getReturnType() == syms.voidType) ? make.Exec(expr) : make.Return(expr);
 981  745
         return make.at(diagPos).Block(0L, List.<JCStatement>of(statement));
 982  
     }
 983  
 
 984  
     protected String getSyntheticPrefix() {
 985  0
         return "ifx$";
 986  
     }
 987  
 }