This is an automated email from the ASF dual-hosted git repository.

joshtynjala pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/royale-compiler.git

commit b3eed13ba5c1e13d6b12bfc41071368d85e35403
Author: Josh Tynjala <[email protected]>
AuthorDate: Mon Nov 20 14:43:27 2023 -0800

    AccessorEmitter: extract some of the branches into separate methods to help 
readability
---
 .../internal/codegen/js/jx/AccessorEmitter.java    | 1338 ++++++++++----------
 1 file changed, 697 insertions(+), 641 deletions(-)

diff --git 
a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/AccessorEmitter.java
 
b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/AccessorEmitter.java
index 2b233fbd7..d84cf8f19 100644
--- 
a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/AccessorEmitter.java
+++ 
b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/AccessorEmitter.java
@@ -79,8 +79,6 @@ public class AccessorEmitter extends JSSubEmitter implements
 
     public void emit(IClassDefinition definition)
     {
-        // TODO (mschmalle) will remove this cast as more things get abstracted
-        JSRoyaleEmitter fjs = (JSRoyaleEmitter) getEmitter();
         RoyaleJSProject project = (RoyaleJSProject)getWalker().getProject();
         boolean emitExports = true;
         if (project != null && project.config != null)
@@ -88,654 +86,19 @@ public class AccessorEmitter extends JSSubEmitter 
implements
 
         if (!getModel().getPropertyMap().isEmpty())
         {
-            String qname = definition.getQualifiedName();
-            Set<String> propertyNames = getModel().getPropertyMap().keySet();
-            for (String propName : propertyNames)
-            {
-                PropertyNodes p = getModel().getPropertyMap().get(propName);
-                IGetterNode getterNode = p.getter;
-                ISetterNode setterNode = p.setter;
-                String baseName = p.name;
-                if (getModel().isExterns)
-                {
-                       IAccessorNode node = (getterNode != null) ? getterNode 
: setterNode;
-                    writeNewline();
-                    writeNewline();
-                    writeNewline();
-                       writeNewline("/**");
-                    if (emitExports)
-                       writeNewline(" * @export");
-                    if (p.type != null)
-                       writeNewline(" * @type {"+ 
JSRoyaleDocEmitter.convertASTypeToJSType(p.type.getBaseName(), 
p.type.getPackageName()) + "}");
-                    writeNewline(" */");
-                    write(getEmitter().formatQualifiedName(qname));
-                    write(ASEmitterTokens.MEMBER_ACCESS);
-                    write(JSEmitterTokens.PROTOTYPE);
-                    if (p.uri != null)
-                    {
-                               INamespaceDecorationNode ns = 
((FunctionNode)node).getActualNamespaceNode();
-                               INamespaceDefinition nsDef = 
(INamespaceDefinition)ns.resolve(project);
-                               
fjs.formatQualifiedName(nsDef.getQualifiedName()); // register with used names
-                               
write(JSRoyaleEmitter.formatNamespacedProperty(p.uri, baseName, true));
-                    }
-                    else
-                    {
-                        write(ASEmitterTokens.MEMBER_ACCESS);
-                       write(baseName);
-                    }
-                    write(ASEmitterTokens.SEMICOLON);
-                }
-                else
-                {
-                    IAccessorNode accessorNode = (getterNode != null) ? 
getterNode : setterNode;
-                    if(!accessorNode.getDefinition().isOverride())
-                    {
-                        // start by writing out the instance accessors as 
regular variables
-                        // because Closure Compiler doesn't properly analyze 
calls to
-                        // defineProperties() alone.
-                        // since there's no analysis, Closure assumes that 
getters/setters
-                        // have no side effects, which results in important 
get/set calls
-                        // being removed as dead code.
-                        // defining the accessors as variables first convinces 
Closure to
-                        // handle them more intelligently while not preventing 
them from
-                        // being real accessors.
-                        // Source: 
https://developers.google.com/closure/compiler/docs/limitations
-                        writeNewline();
-                        writeNewline();
-                        writeNewline();
-                        writeNewline("/**");
-                        if (p.preventRename)
-                            writeNewline(" * @nocollapse");
-                        if (p.resolvedExport && !p.suppressExport)
-                            writeNewline(" * @export");
-                        if (p.type != null)
-                            writeNewline(" * @type {" + 
JSRoyaleDocEmitter.convertASTypeToJSType(p.type.getBaseName(), 
p.type.getPackageName()) + "}"); 
-                        writeNewline(" */");
-                        write(getEmitter().formatQualifiedName(qname));
-                        write(ASEmitterTokens.MEMBER_ACCESS);
-                        write(JSEmitterTokens.PROTOTYPE);
-                        write(ASEmitterTokens.MEMBER_ACCESS);
-                        if (p.uri != null)
-                        {
-                            INamespaceDecorationNode ns = ((FunctionNode) 
accessorNode).getActualNamespaceNode();
-                            INamespaceDefinition nsDef = 
(INamespaceDefinition)ns.resolve(project);
-                            fjs.formatQualifiedName(nsDef.getQualifiedName()); 
// register with used names
-                            
write(JSRoyaleEmitter.formatNamespacedProperty(p.uri, baseName, false));
-                        }
-                        else
-                            write(baseName);
-                        write(ASEmitterTokens.SEMICOLON);
-                    }
-
-                    if (getterNode != null)
-                       {
-                           writeNewline();
-                           writeNewline();
-                           writeNewline();
-                           write(getEmitter().formatQualifiedName(qname));
-                           write(ASEmitterTokens.MEMBER_ACCESS);
-                           write(JSEmitterTokens.PROTOTYPE);
-                           if (p.uri != null)
-                           {
-                                       INamespaceDecorationNode ns = 
((FunctionNode)getterNode).getActualNamespaceNode();
-                                       INamespaceDefinition nsDef = 
(INamespaceDefinition)ns.resolve(project);
-                                       
fjs.formatQualifiedName(nsDef.getQualifiedName()); // register with used names
-                                       
write(JSRoyaleEmitter.formatNamespacedProperty(p.uri, 
fjs.formatGetter(baseName), true));
-                           }
-                           else
-                           {
-                               write(ASEmitterTokens.MEMBER_ACCESS);
-                            write(fjs.formatGetter(baseName));
-                           }
-                           write(ASEmitterTokens.SPACE);
-                           write(ASEmitterTokens.EQUAL);
-                           write(ASEmitterTokens.SPACE);
-                           write(ASEmitterTokens.FUNCTION);
-                           
fjs.emitParameters(getterNode.getParametersContainerNode());
-       
-                           fjs.emitDefinePropertyFunction(getterNode);
-                                               
-                           write(ASEmitterTokens.SEMICOLON);
-                       }
-                       if (setterNode != null)
-                       {
-                                               boolean isClassBindable = 
BindableHelper.isClassCodeGenBindable(definition);
-
-                               boolean isBindable = false;                
-                               IAccessorDefinition setterDef = 
(IAccessorDefinition)setterNode.getDefinition();
-                               IAccessorDefinition getterDef = null;
-                               if (getterNode != null)
-                                       getterDef = 
(IAccessorDefinition)getterNode.getDefinition();
-                               if ((getterDef != null && 
(setterDef.isBindable() || getterDef.isBindable())))
-                               {
-                                                       boolean 
foundExplicitBindableTag = false;
-                                       if (setterDef.isBindable())
-                                       {
-
-                                                               isBindable = 
BindableHelper.isCodeGenBindableMember(setterDef, isClassBindable);
-                                                               
foundExplicitBindableTag = BindableHelper.hasExplicitBindable(setterDef);
-                                       }
-                                       if (getterDef.isBindable())
-                                       {
-
-                                                               isBindable = 
isBindable || BindableHelper.isCodeGenBindableMember(getterDef, 
isClassBindable);
-                                                               
foundExplicitBindableTag = foundExplicitBindableTag || 
BindableHelper.hasExplicitBindable(getterDef);
-
-                                       }
-
-                                                       if (isClassBindable) {
-                                                               //if we 
'foundExplicitBindableTag' such as [Bindable(event='someEvent')], then nothing 
else matters, even another [Bindable] tag is ignored (Flex)
-                                                               isBindable = 
!foundExplicitBindableTag;
-                                                       }
-                               }
-                           writeNewline();
-                           writeNewline();
-                           writeNewline();
-                           write(getEmitter().formatQualifiedName(qname));
-                           write(ASEmitterTokens.MEMBER_ACCESS);
-                           write(JSEmitterTokens.PROTOTYPE);
-                           if (p.uri != null)
-                           {
-                                       INamespaceDecorationNode ns = 
((FunctionNode)setterNode).getActualNamespaceNode();
-                                       INamespaceDefinition nsDef = 
(INamespaceDefinition)ns.resolve(project);
-                                       
fjs.formatQualifiedName(nsDef.getQualifiedName()); // register with used names
-                                       
write(JSRoyaleEmitter.formatNamespacedProperty(p.uri, 
fjs.formatSetter(baseName), true));
-                           }
-                           else
-                           {
-                               write(ASEmitterTokens.MEMBER_ACCESS);
-                               if (isBindable) {
-                                                               
write(JSRoyaleEmitterTokens.BINDABLE_PREFIX);
-                                
write(fjs.formatSetter(fjs.formatPrivateName(definition.getQualifiedName(), 
baseName, true)));
-                                                       } else {
-                                write(fjs.formatSetter(baseName));
-                                                       }
-                           }
-                           write(ASEmitterTokens.SPACE);
-                           write(ASEmitterTokens.EQUAL);
-                           write(ASEmitterTokens.SPACE);
-                           write(ASEmitterTokens.FUNCTION);
-                           
fjs.emitParameters(setterNode.getParametersContainerNode());
-       
-                           fjs.emitDefinePropertyFunction(setterNode);
-                           
-                           write(ASEmitterTokens.SEMICOLON);
-                           
-                           if (isBindable)
-                           {
-                               writeNewline();
-                               writeNewline();
-                               writeNewline();
-                               write(getEmitter().formatQualifiedName(qname));
-                               write(ASEmitterTokens.MEMBER_ACCESS);
-                               write(JSEmitterTokens.PROTOTYPE);
-                               write(ASEmitterTokens.MEMBER_ACCESS);
-                            write(fjs.formatSetter(baseName));
-                               write(ASEmitterTokens.SPACE);
-                               write(ASEmitterTokens.EQUAL);
-                               write(ASEmitterTokens.SPACE);
-                               write(ASEmitterTokens.FUNCTION);
-                               write(ASEmitterTokens.PAREN_OPEN);
-                               write("value");
-                               write(ASEmitterTokens.PAREN_CLOSE);
-                               write(ASEmitterTokens.SPACE);
-                               writeNewline(ASEmitterTokens.BLOCK_OPEN);
-                               write(ASEmitterTokens.VAR);
-                               write(ASEmitterTokens.SPACE);
-                               write("oldValue");
-                               write(ASEmitterTokens.SPACE);
-                               write(ASEmitterTokens.EQUAL);
-                               write(ASEmitterTokens.SPACE);
-                               write(ASEmitterTokens.THIS);
-                               write(ASEmitterTokens.MEMBER_ACCESS);
-                               write(fjs.formatGetter(baseName));
-                               write(ASEmitterTokens.PAREN_OPEN);
-                               write(ASEmitterTokens.PAREN_CLOSE);
-                               writeNewline(ASEmitterTokens.SEMICOLON);
-                               write(ASEmitterTokens.IF);
-                               write(ASEmitterTokens.SPACE);
-                               write(ASEmitterTokens.PAREN_OPEN);
-                               write("oldValue != value");
-                               write(ASEmitterTokens.PAREN_CLOSE);
-                               write(ASEmitterTokens.SPACE);
-                               writeNewline(ASEmitterTokens.BLOCK_OPEN);
-                               write(ASEmitterTokens.THIS);
-                               write(ASEmitterTokens.MEMBER_ACCESS);
-                               write(JSRoyaleEmitterTokens.BINDABLE_PREFIX);
-                            
write(fjs.formatSetter(fjs.formatPrivateName(definition.getQualifiedName(), 
baseName, true)));
-                               write(ASEmitterTokens.PAREN_OPEN);
-                               write("value");
-                               write(ASEmitterTokens.PAREN_CLOSE);
-                               writeNewline(ASEmitterTokens.SEMICOLON);
-                               writeNewline("    
this.dispatchEvent("+fjs.formatQualifiedName(BindableEmitter.VALUECHANGE_EVENT_QNAME)+".createUpdateEvent(");
-                               writeNewline("         this, \"" + 
p.originalName + "\", oldValue, value));");
-                               writeNewline(ASEmitterTokens.BLOCK_CLOSE);
-                               write(ASEmitterTokens.BLOCK_CLOSE);
-                               write(ASEmitterTokens.SEMICOLON);               
         
-                               
-                           }
-                       }
-                }
-            }
+            writeProperties(definition, emitExports);
         }
         if (!getModel().getPropertyMap().isEmpty() && !getModel().isExterns)
         {
-            writeNewline();
-            writeNewline();
-            writeNewline();
-            write(JSGoogEmitterTokens.OBJECT);
-            write(ASEmitterTokens.MEMBER_ACCESS);
-            write(JSEmitterTokens.DEFINE_PROPERTIES);
-            write(ASEmitterTokens.PAREN_OPEN);
-            String qname = definition.getQualifiedName();
-            write(getEmitter().formatQualifiedName(qname));
-            write(ASEmitterTokens.MEMBER_ACCESS);
-            write(JSEmitterTokens.PROTOTYPE);
-            write(ASEmitterTokens.COMMA);
-            write(ASEmitterTokens.SPACE);
-            write("/** @lends {" + getEmitter().formatQualifiedName(qname)
-                    + ".prototype} */ ");
-            writeNewline(ASEmitterTokens.BLOCK_OPEN);
-
-            Set<String> propertyNames = getModel().getPropertyMap().keySet();
-            boolean firstTime = true;
-            for (String propName : propertyNames)
-            {
-                if (firstTime)
-                    firstTime = false;
-                else
-                    writeNewline(ASEmitterTokens.COMMA);
-
-                boolean wroteGetter = false;
-                PropertyNodes p = getModel().getPropertyMap().get(propName);
-                String baseName = p.name;
-                IGetterNode getterNode = p.getter;
-                ISetterNode setterNode = p.setter;
-                writeNewline("/**");
-                if (p.type != null)
-                {
-                       String typeName = p.type.getBaseName();
-                       if (getModel().isInternalClass(typeName))
-                                       typeName = 
getModel().getInternalClasses().get(typeName);
-                                       writeNewline(" * @type {" + 
JSRoyaleDocEmitter.convertASTypeToJSType(typeName, p.type.getPackageName()) + 
"}");
-                }
-                writeNewline(" */");
-                FunctionNode fnNode = getterNode != null ? (FunctionNode) 
getterNode : (FunctionNode) setterNode;
-                if (p.uri != null)
-                {
-                               INamespaceDecorationNode ns = 
fnNode.getActualNamespaceNode();
-                               INamespaceDefinition nsDef = 
(INamespaceDefinition)ns.resolve(project);
-                               
fjs.formatQualifiedName(nsDef.getQualifiedName()); // register with used names 
-                               //String s = nsDef.getURI();
-                               
write(JSRoyaleEmitter.formatNamespacedProperty(p.uri, baseName, false));
-                }
-                else
-                       write(baseName);
-                write(ASEmitterTokens.COLON);
-                write(ASEmitterTokens.SPACE);
-                write(ASEmitterTokens.BLOCK_OPEN);
-                writeNewline();
-                if (getterNode != null)
-                {
-                    write(ASEmitterTokens.GET);
-                    write(ASEmitterTokens.COLON);
-                    write(ASEmitterTokens.SPACE);
-                    write(getEmitter().formatQualifiedName(qname));
-                    write(ASEmitterTokens.MEMBER_ACCESS);
-                    write(JSEmitterTokens.PROTOTYPE);
-                    if (p.uri != null)
-                    {
-                               INamespaceDecorationNode ns = 
((FunctionNode)getterNode).getActualNamespaceNode();
-                               INamespaceDefinition nsDef = 
(INamespaceDefinition)ns.resolve(project);
-                               
fjs.formatQualifiedName(nsDef.getQualifiedName()); // register with used names 
-                               //String s = nsDef.getURI();
-                               
write(JSRoyaleEmitter.formatNamespacedProperty(p.uri, 
fjs.formatGetter(baseName), true));
-                    }
-                    else
-                    {
-                        write(ASEmitterTokens.MEMBER_ACCESS);
-                        write(fjs.formatGetter(baseName));
-                    }
-                    wroteGetter = true;
-                }
-                else if (setterNode != null /* && 
setterNode.getDefinition().isOverride()*/)
-                {
-                       // see if there is a getter on a base class.  If so, we 
have to 
-                       // generate a call to the super from this class because 
-                       // Object.defineProperty doesn't allow overriding just 
the setter.
-                       // If there is no getter defineProp'd the property will 
seen as
-                       // write-only.
-                       IAccessorDefinition other = 
(IAccessorDefinition)SemanticUtils.resolveCorrespondingAccessor(p.setter.getDefinition(),
 getProject());
-                       if (other != null)
-                       {
-                        write(ASEmitterTokens.GET);
-                        write(ASEmitterTokens.COLON);
-                        write(ASEmitterTokens.SPACE);
-                        
-                        
write(getEmitter().formatQualifiedName(other.getParent().getQualifiedName()));
-                        write(ASEmitterTokens.MEMBER_ACCESS);
-                        write(JSEmitterTokens.PROTOTYPE);
-                        if (p.uri != null)
-                        {
-                                       INamespaceDecorationNode ns = 
((FunctionNode)setterNode).getActualNamespaceNode();
-                                       INamespaceDefinition nsDef = 
(INamespaceDefinition)ns.resolve(project);
-                                       
fjs.formatQualifiedName(nsDef.getQualifiedName()); // register with used names 
-                                       //String s = nsDef.getURI();
-                                       
write(JSRoyaleEmitter.formatNamespacedProperty(p.uri, 
fjs.formatGetter(baseName), true));
-                        }
-                        else
-                        {
-                            write(ASEmitterTokens.MEMBER_ACCESS);
-                            write(fjs.formatGetter(baseName));
-                        }
-                        wroteGetter = true;
-                       }
-                }
-                if (setterNode != null)
-                {
-                    if (wroteGetter)
-                        writeNewline(ASEmitterTokens.COMMA);
-
-                    write(ASEmitterTokens.SET);
-                    write(ASEmitterTokens.COLON);
-                    write(ASEmitterTokens.SPACE);
-                    write(getEmitter().formatQualifiedName(qname));
-                    write(ASEmitterTokens.MEMBER_ACCESS);
-                    write(JSEmitterTokens.PROTOTYPE);
-                    if (p.uri != null)
-                    {
-                               INamespaceDecorationNode ns = 
((FunctionNode)setterNode).getActualNamespaceNode();
-                               INamespaceDefinition nsDef = 
(INamespaceDefinition)ns.resolve(project);
-                               
fjs.formatQualifiedName(nsDef.getQualifiedName()); // register with used names 
-                               //String s = nsDef.getURI();
-                               
write(JSRoyaleEmitter.formatNamespacedProperty(p.uri, 
fjs.formatSetter(baseName), true));
-                    }
-                    else
-                    {
-                        write(ASEmitterTokens.MEMBER_ACCESS);
-                        write(fjs.formatSetter(baseName));
-                    }
-                }
-                else if (getterNode != null/* && 
getterNode.getDefinition().isOverride()*/)
-                {
-                       // see if there is a getter on a base class.  If so, we 
have to 
-                       // generate a call to the super from this class because 
-                       // Object.defineProperty doesn't allow overriding just 
the getter.
-                       // If there is no setter defineProp'd the property will 
seen as
-                       // read-only.
-                       IAccessorDefinition other = 
(IAccessorDefinition)SemanticUtils.resolveCorrespondingAccessor(p.getter.getDefinition(),
 getProject());
-                       if (other != null)
-                       {
-                        if (wroteGetter)
-                            writeNewline(ASEmitterTokens.COMMA);
-
-                        write(ASEmitterTokens.SET);
-                        write(ASEmitterTokens.COLON);
-                        write(ASEmitterTokens.SPACE);
-                        
write(getEmitter().formatQualifiedName(other.getParent().getQualifiedName()));
-                        write(ASEmitterTokens.MEMBER_ACCESS);
-                        write(JSEmitterTokens.PROTOTYPE);
-                        if (p.uri != null)
-                        {
-                                       INamespaceDecorationNode ns = 
((FunctionNode)getterNode).getActualNamespaceNode();
-                                       INamespaceDefinition nsDef = 
(INamespaceDefinition)ns.resolve(project);
-                                       
fjs.formatQualifiedName(nsDef.getQualifiedName()); // register with used names 
-                                       //String s = nsDef.getURI();
-                                       
write(JSRoyaleEmitter.formatNamespacedProperty(p.uri, 
fjs.formatSetter(baseName), true));
-                        }
-                        else
-                        {
-                            write(ASEmitterTokens.MEMBER_ACCESS);
-                            write(fjs.formatSetter(baseName));
-                        }
-                       }
-                }
-                write(ASEmitterTokens.BLOCK_CLOSE);
-            }
-            writeNewline(ASEmitterTokens.BLOCK_CLOSE);
-            write(ASEmitterTokens.PAREN_CLOSE);
-            write(ASEmitterTokens.SEMICOLON);
+            writeDefineProperties(definition);
         }
         if (!getModel().getStaticPropertyMap().isEmpty())
         {
-            String qname = definition.getQualifiedName();
-            Set<String> propertyNames = 
getModel().getStaticPropertyMap().keySet();
-            for (String propName : propertyNames)
-            {
-                PropertyNodes p = 
getModel().getStaticPropertyMap().get(propName);
-                IGetterNode getterNode = p.getter;
-                ISetterNode setterNode = p.setter;
-                String baseName = p.name;
-                if (getModel().isExterns)
-                {
-                       IAccessorNode node = (getterNode != null) ? getterNode 
: setterNode;
-                    writeNewline();
-                    writeNewline();
-                    writeNewline();
-                    writeNewline("/**");
-                    if (emitExports)
-                       writeNewline(" * @export");
-                    if (p.type != null)
-                       writeNewline(" * @type {" + 
JSRoyaleDocEmitter.convertASTypeToJSType(p.type.getBaseName(), 
p.type.getPackageName()) + "}");
-                    writeNewline(" */");
-                    write(getEmitter().formatQualifiedName(qname));
-                    if (p.uri != null)
-                    {
-                               INamespaceDecorationNode ns = 
((FunctionNode)node).getActualNamespaceNode();
-                               INamespaceDefinition nsDef = 
(INamespaceDefinition)ns.resolve(project);
-                               
fjs.formatQualifiedName(nsDef.getQualifiedName()); // register with used names 
-                               String s = nsDef.getURI();
-                               
write(JSRoyaleEmitter.formatNamespacedProperty(p.uri, baseName, true));
-                    }
-                    else
-                    {
-                        write(ASEmitterTokens.MEMBER_ACCESS);
-                       write(baseName);
-                    }
-                    write(ASEmitterTokens.SEMICOLON);                  
-                }
-                else
-                {
-                    // start by writing out the static accessors as regular 
variables
-                    // because Closure Compiler doesn't properly analyze calls 
to
-                    // defineProperties() alone.
-                    // since there's no analysis, Closure assumes that 
getters/setters
-                    // have no side effects, which results in important 
get/set calls
-                    // being removed as dead code.
-                    // defining the accessors as variables first convinces 
Closure to
-                    // handle them more intelligently while not preventing 
them from
-                    // being real accessors.
-                    // Source: 
https://developers.google.com/closure/compiler/docs/limitations
-                    writeNewline();
-                    writeNewline();
-                    writeNewline();
-                    writeNewline("/**");
-                    // like instance accessors, we should have if 
(p.preventRename)
-                    // here, but while Closure compiler seems to properly 
handle
-                    // renaming of instance accessors, it fails when we try 
the same
-                    // trick with static accessors, unless there's a 
nocollapse.
-                    // when we allow renaming, we don't want to break anything 
that
-                    // isn't dynamic access, so we always need nocollapse here.
-                    writeNewline(" * @nocollapse");
-                    if (p.resolvedExport && !p.suppressExport)
-                        writeNewline(" * @export");
-                    if (p.type != null)
-                        writeNewline(" * @type {" + 
JSRoyaleDocEmitter.convertASTypeToJSType(p.type.getBaseName(), 
p.type.getPackageName()) + "}"); 
-                    writeNewline(" */");
-                    write(getEmitter().formatQualifiedName(qname));
-                    write(ASEmitterTokens.MEMBER_ACCESS);
-                    if (p.uri != null)
-                    {
-                        IAccessorNode node = (getterNode != null) ? getterNode 
: setterNode;
-                        INamespaceDecorationNode ns = 
((FunctionNode)node).getActualNamespaceNode();
-                        INamespaceDefinition nsDef = 
(INamespaceDefinition)ns.resolve(project);
-                        fjs.formatQualifiedName(nsDef.getQualifiedName()); // 
register with used names
-                        write(JSRoyaleEmitter.formatNamespacedProperty(p.uri, 
baseName, false));
-                    }
-                    else
-                        write(baseName);
-                    write(ASEmitterTokens.SEMICOLON);
-
-                    if (getterNode != null)
-                       {
-                           writeNewline();
-                           writeNewline();
-                           writeNewline();
-                           write(getEmitter().formatQualifiedName(qname));
-                           if (p.uri != null)
-                           {
-                                       INamespaceDecorationNode ns = 
((FunctionNode)getterNode).getActualNamespaceNode();
-                                       INamespaceDefinition nsDef = 
(INamespaceDefinition)ns.resolve(project);
-                                       
fjs.formatQualifiedName(nsDef.getQualifiedName()); // register with used names 
-                                       //String s = nsDef.getURI();
-                                       
write(JSRoyaleEmitter.formatNamespacedProperty(p.uri , 
fjs.formatGetter(baseName), true));
-                           }
-                           else
-                           {
-                               write(ASEmitterTokens.MEMBER_ACCESS);
-                               write(fjs.formatGetter(baseName));
-                           }
-                           write(ASEmitterTokens.SPACE);
-                           write(ASEmitterTokens.EQUAL);
-                           write(ASEmitterTokens.SPACE);
-                           write(ASEmitterTokens.FUNCTION);
-                           
fjs.emitParameters(getterNode.getParametersContainerNode());
-       
-                           fjs.emitDefinePropertyFunction(getterNode);
-                           
-                           write(ASEmitterTokens.SEMICOLON);
-                       }
-                       if (setterNode != null)
-                       {
-                           writeNewline();
-                           writeNewline();
-                           writeNewline();
-                           write(getEmitter().formatQualifiedName(qname));
-                           if (p.uri != null)
-                           {
-                                       INamespaceDecorationNode ns = 
((FunctionNode)setterNode).getActualNamespaceNode();
-                                       INamespaceDefinition nsDef = 
(INamespaceDefinition)ns.resolve(project);
-                                       
fjs.formatQualifiedName(nsDef.getQualifiedName()); // register with used names 
-                                       //String s = nsDef.getURI();
-                                       
write(JSRoyaleEmitter.formatNamespacedProperty(p.uri, 
fjs.formatSetter(baseName), true));
-                           }
-                           else
-                           {
-                               write(ASEmitterTokens.MEMBER_ACCESS);
-                            write(fjs.formatSetter(baseName));
-                           }
-                           write(ASEmitterTokens.SPACE);
-                           write(ASEmitterTokens.EQUAL);
-                           write(ASEmitterTokens.SPACE);
-                           write(ASEmitterTokens.FUNCTION);
-                           
fjs.emitParameters(setterNode.getParametersContainerNode());
-       
-                           fjs.emitDefinePropertyFunction(setterNode);
-                           
-                           write(ASEmitterTokens.SEMICOLON);
-                       }
-                }
-            }
+            writeStaticProperties(definition, emitExports);
         }
         if (!getModel().getStaticPropertyMap().isEmpty() && 
!getModel().isExterns)
         {
-            writeNewline();
-            writeNewline();
-            writeNewline();
-            write(JSGoogEmitterTokens.OBJECT);
-            write(ASEmitterTokens.MEMBER_ACCESS);
-            write(JSEmitterTokens.DEFINE_PROPERTIES);
-            write(ASEmitterTokens.PAREN_OPEN);
-            String qname = definition.getQualifiedName();
-            write(getEmitter().formatQualifiedName(qname));
-            write(ASEmitterTokens.COMMA);
-            write(ASEmitterTokens.SPACE);
-            write("/** @lends {" + getEmitter().formatQualifiedName(qname)
-                    + "} */ ");
-            writeNewline(ASEmitterTokens.BLOCK_OPEN);
-
-            Set<String> propertyNames = getModel().getStaticPropertyMap()
-                    .keySet();
-            boolean firstTime = true;
-            for (String propName : propertyNames)
-            {
-                if (firstTime)
-                    firstTime = false;
-                else
-                    writeNewline(ASEmitterTokens.COMMA);
-
-                PropertyNodes p = getModel().getStaticPropertyMap().get(
-                        propName);
-                IGetterNode getterNode = p.getter;
-                ISetterNode setterNode = p.setter;
-                String baseName = p.name;
-               writeNewline("/**");
-                if (p.type != null)
-                       writeNewline(" * @type {" + 
JSRoyaleDocEmitter.convertASTypeToJSType(p.type.getBaseName(), 
p.type.getPackageName()) + "}");
-                writeNewline(" */");
-                               FunctionNode fnNode = getterNode != null ? 
(FunctionNode) getterNode : (FunctionNode) setterNode;
-                               if (p.uri != null)
-                               {
-                                       INamespaceDecorationNode ns = 
fnNode.getActualNamespaceNode();
-                                       INamespaceDefinition nsDef = 
(INamespaceDefinition)ns.resolve(project);
-                                       
fjs.formatQualifiedName(nsDef.getQualifiedName()); // register with used names
-                                       //String s = nsDef.getURI();
-                                       
write(JSRoyaleEmitter.formatNamespacedProperty(p.uri, baseName, false));
-                               }
-                               else
-                                       write(baseName);
-                write(ASEmitterTokens.COLON);
-                write(ASEmitterTokens.SPACE);
-                write(ASEmitterTokens.BLOCK_OPEN);
-                writeNewline();
-                if (getterNode != null)
-                {
-                    write(ASEmitterTokens.GET);
-                    write(ASEmitterTokens.COLON);
-                    write(ASEmitterTokens.SPACE);
-                    write(getEmitter().formatQualifiedName(qname));
-                    if (p.uri != null)
-                    {
-                               INamespaceDecorationNode ns = 
((FunctionNode)getterNode).getActualNamespaceNode();
-                               INamespaceDefinition nsDef = 
(INamespaceDefinition)ns.resolve(project);
-                               
fjs.formatQualifiedName(nsDef.getQualifiedName()); // register with used names 
-                               //String s = nsDef.getURI();
-                               
write(JSRoyaleEmitter.formatNamespacedProperty(p.uri, 
fjs.formatGetter(baseName), true));
-                    }
-                    else
-                    {
-                        write(ASEmitterTokens.MEMBER_ACCESS);
-                        write(fjs.formatGetter(baseName));
-                    }
-                }
-                if (setterNode != null)
-                {
-                    if (p.getter != null)
-                        writeNewline(ASEmitterTokens.COMMA);
-
-                    write(ASEmitterTokens.SET);
-                    write(ASEmitterTokens.COLON);
-                    write(ASEmitterTokens.SPACE);
-                    write(getEmitter().formatQualifiedName(qname));
-                    if (p.uri != null)
-                    {
-                               INamespaceDecorationNode ns = 
((FunctionNode)setterNode).getActualNamespaceNode();
-                               INamespaceDefinition nsDef = 
(INamespaceDefinition)ns.resolve(project);
-                               
fjs.formatQualifiedName(nsDef.getQualifiedName()); // register with used names 
-                               //String s = nsDef.getURI();
-                               
write(JSRoyaleEmitter.formatNamespacedProperty(p.uri, 
fjs.formatSetter(baseName), true));
-                    }
-                    else
-                    {
-                        write(ASEmitterTokens.MEMBER_ACCESS);
-                        write(fjs.formatSetter(baseName));
-                    }
-                }
-                write(ASEmitterTokens.BLOCK_CLOSE);
-            }
-            writeNewline(ASEmitterTokens.BLOCK_CLOSE);
-            write(ASEmitterTokens.PAREN_CLOSE);
-            write(ASEmitterTokens.SEMICOLON);
+            writeStaticDefinePropreties(definition);
         }
     }
 
@@ -932,4 +295,697 @@ public class AccessorEmitter extends JSSubEmitter 
implements
                        writeNewline();
         }
     }
+
+    private void writeProperties(IClassDefinition definition, boolean 
emitExports)
+    {
+        JSRoyaleEmitter fjs = (JSRoyaleEmitter) getEmitter();
+        String qname = definition.getQualifiedName();
+        Set<String> propertyNames = getModel().getPropertyMap().keySet();
+        for (String propName : propertyNames)
+        {
+            PropertyNodes p = getModel().getPropertyMap().get(propName);
+            IGetterNode getterNode = p.getter;
+            ISetterNode setterNode = p.setter;
+            String baseName = p.name;
+            if (getModel().isExterns)
+            {
+                IAccessorNode node = (getterNode != null) ? getterNode : 
setterNode;
+                writeNewline();
+                writeNewline();
+                writeNewline();
+                writeNewline("/**");
+                if (emitExports)
+                    writeNewline(" * @export");
+                if (p.type != null)
+                    writeNewline(" * @type {"+ 
JSRoyaleDocEmitter.convertASTypeToJSType(p.type.getBaseName(), 
p.type.getPackageName()) + "}");
+                writeNewline(" */");
+                write(getEmitter().formatQualifiedName(qname));
+                write(ASEmitterTokens.MEMBER_ACCESS);
+                write(JSEmitterTokens.PROTOTYPE);
+                if (p.uri != null)
+                {
+                    INamespaceDecorationNode ns = 
((FunctionNode)node).getActualNamespaceNode();
+                    INamespaceDefinition nsDef = 
(INamespaceDefinition)ns.resolve(getWalker().getProject());
+                    fjs.formatQualifiedName(nsDef.getQualifiedName()); // 
register with used names
+                    write(JSRoyaleEmitter.formatNamespacedProperty(p.uri, 
baseName, true));
+                }
+                else
+                {
+                    write(ASEmitterTokens.MEMBER_ACCESS);
+                    write(baseName);
+                }
+                write(ASEmitterTokens.SEMICOLON);
+            }
+            else
+            {
+                IAccessorNode accessorNode = (getterNode != null) ? getterNode 
: setterNode;
+                if(!accessorNode.getDefinition().isOverride())
+                {
+                    // start by writing out the instance accessors as regular 
variables
+                    // because Closure Compiler doesn't properly analyze calls 
to
+                    // defineProperties() alone.
+                    // since there's no analysis, Closure assumes that 
getters/setters
+                    // have no side effects, which results in important 
get/set calls
+                    // being removed as dead code.
+                    // defining the accessors as variables first convinces 
Closure to
+                    // handle them more intelligently while not preventing 
them from
+                    // being real accessors.
+                    // Source: 
https://developers.google.com/closure/compiler/docs/limitations
+                    writeNewline();
+                    writeNewline();
+                    writeNewline();
+                    writeNewline("/**");
+                    if (p.preventRename)
+                        writeNewline(" * @nocollapse");
+                    if (p.resolvedExport && !p.suppressExport)
+                        writeNewline(" * @export");
+                    if (p.type != null)
+                        writeNewline(" * @type {" + 
JSRoyaleDocEmitter.convertASTypeToJSType(p.type.getBaseName(), 
p.type.getPackageName()) + "}"); 
+                    writeNewline(" */");
+                    write(getEmitter().formatQualifiedName(qname));
+                    write(ASEmitterTokens.MEMBER_ACCESS);
+                    write(JSEmitterTokens.PROTOTYPE);
+                    write(ASEmitterTokens.MEMBER_ACCESS);
+                    if (p.uri != null)
+                    {
+                        INamespaceDecorationNode ns = ((FunctionNode) 
accessorNode).getActualNamespaceNode();
+                        INamespaceDefinition nsDef = 
(INamespaceDefinition)ns.resolve(getWalker().getProject());
+                        fjs.formatQualifiedName(nsDef.getQualifiedName()); // 
register with used names
+                        write(JSRoyaleEmitter.formatNamespacedProperty(p.uri, 
baseName, false));
+                    }
+                    else
+                        write(baseName);
+                    write(ASEmitterTokens.SEMICOLON);
+                }
+
+                if (getterNode != null)
+                {
+                    writeGetterNode(p, definition);
+                }
+                if (setterNode != null)
+                {
+                    writeSetterNode(p, definition);
+                }
+            }
+        }
+    }
+    
+    private void writeStaticProperties(IClassDefinition definition, boolean 
emitExports)
+    {
+        JSRoyaleEmitter fjs = (JSRoyaleEmitter) getEmitter();
+        String qname = definition.getQualifiedName();
+        Set<String> propertyNames = getModel().getStaticPropertyMap().keySet();
+        for (String propName : propertyNames)
+        {
+            PropertyNodes p = getModel().getStaticPropertyMap().get(propName);
+            IGetterNode getterNode = p.getter;
+            ISetterNode setterNode = p.setter;
+            String baseName = p.name;
+            if (getModel().isExterns)
+            {
+                IAccessorNode node = (getterNode != null) ? getterNode : 
setterNode;
+                writeNewline();
+                writeNewline();
+                writeNewline();
+                writeNewline("/**");
+                if (emitExports)
+                    writeNewline(" * @export");
+                if (p.type != null)
+                    writeNewline(" * @type {" + 
JSRoyaleDocEmitter.convertASTypeToJSType(p.type.getBaseName(), 
p.type.getPackageName()) + "}");
+                writeNewline(" */");
+                write(getEmitter().formatQualifiedName(qname));
+                if (p.uri != null)
+                {
+                    INamespaceDecorationNode ns = 
((FunctionNode)node).getActualNamespaceNode();
+                    INamespaceDefinition nsDef = 
(INamespaceDefinition)ns.resolve(getWalker().getProject());
+                    fjs.formatQualifiedName(nsDef.getQualifiedName()); // 
register with used names
+                    write(JSRoyaleEmitter.formatNamespacedProperty(p.uri, 
baseName, true));
+                }
+                else
+                {
+                    write(ASEmitterTokens.MEMBER_ACCESS);
+                    write(baseName);
+                }
+                write(ASEmitterTokens.SEMICOLON);                      
+            }
+            else
+            {
+                // start by writing out the static accessors as regular 
variables
+                // because Closure Compiler doesn't properly analyze calls to
+                // defineProperties() alone.
+                // since there's no analysis, Closure assumes that 
getters/setters
+                // have no side effects, which results in important get/set 
calls
+                // being removed as dead code.
+                // defining the accessors as variables first convinces Closure 
to
+                // handle them more intelligently while not preventing them 
from
+                // being real accessors.
+                // Source: 
https://developers.google.com/closure/compiler/docs/limitations
+                writeNewline();
+                writeNewline();
+                writeNewline();
+                writeNewline("/**");
+                // like instance accessors, we should have if (p.preventRename)
+                // here, but while Closure compiler seems to properly handle
+                // renaming of instance accessors, it fails when we try the 
same
+                // trick with static accessors, unless there's a nocollapse.
+                // when we allow renaming, we don't want to break anything that
+                // isn't dynamic access, so we always need nocollapse here.
+                writeNewline(" * @nocollapse");
+                if (p.resolvedExport && !p.suppressExport)
+                    writeNewline(" * @export");
+                if (p.type != null)
+                    writeNewline(" * @type {" + 
JSRoyaleDocEmitter.convertASTypeToJSType(p.type.getBaseName(), 
p.type.getPackageName()) + "}"); 
+                writeNewline(" */");
+                write(getEmitter().formatQualifiedName(qname));
+                write(ASEmitterTokens.MEMBER_ACCESS);
+                if (p.uri != null)
+                {
+                    IAccessorNode node = (getterNode != null) ? getterNode : 
setterNode;
+                    INamespaceDecorationNode ns = 
((FunctionNode)node).getActualNamespaceNode();
+                    INamespaceDefinition nsDef = 
(INamespaceDefinition)ns.resolve(getWalker().getProject());
+                    fjs.formatQualifiedName(nsDef.getQualifiedName()); // 
register with used names
+                    write(JSRoyaleEmitter.formatNamespacedProperty(p.uri, 
baseName, false));
+                }
+                else
+                    write(baseName);
+                write(ASEmitterTokens.SEMICOLON);
+
+                if (getterNode != null)
+                {
+                    writeStaticGetterNode(p, definition);
+                }
+                if (setterNode != null)
+                {
+                    writeStaticSetterNode(p, definition);
+                }
+            }
+        }
+    }
+
+    private void writeDefineProperties(IClassDefinition definition)
+    {
+        JSRoyaleEmitter fjs = (JSRoyaleEmitter) getEmitter();
+        writeNewline();
+        writeNewline();
+        writeNewline();
+        write(JSGoogEmitterTokens.OBJECT);
+        write(ASEmitterTokens.MEMBER_ACCESS);
+        write(JSEmitterTokens.DEFINE_PROPERTIES);
+        write(ASEmitterTokens.PAREN_OPEN);
+        String qname = definition.getQualifiedName();
+        write(getEmitter().formatQualifiedName(qname));
+        write(ASEmitterTokens.MEMBER_ACCESS);
+        write(JSEmitterTokens.PROTOTYPE);
+        write(ASEmitterTokens.COMMA);
+        write(ASEmitterTokens.SPACE);
+        write("/** @lends {" + getEmitter().formatQualifiedName(qname)
+                + ".prototype} */ ");
+        writeNewline(ASEmitterTokens.BLOCK_OPEN);
+
+        Set<String> propertyNames = getModel().getPropertyMap().keySet();
+        boolean firstTime = true;
+        for (String propName : propertyNames)
+        {
+            if (firstTime)
+                firstTime = false;
+            else
+                writeNewline(ASEmitterTokens.COMMA);
+
+            boolean wroteGetter = false;
+            PropertyNodes p = getModel().getPropertyMap().get(propName);
+            String baseName = p.name;
+            IGetterNode getterNode = p.getter;
+            ISetterNode setterNode = p.setter;
+            writeNewline("/**");
+            if (p.type != null)
+            {
+                String typeName = p.type.getBaseName();
+                if (getModel().isInternalClass(typeName))
+                    typeName = getModel().getInternalClasses().get(typeName);
+                writeNewline(" * @type {" + 
JSRoyaleDocEmitter.convertASTypeToJSType(typeName, p.type.getPackageName()) + 
"}");
+            }
+            writeNewline(" */");
+            FunctionNode fnNode = getterNode != null ? (FunctionNode) 
getterNode : (FunctionNode) setterNode;
+            if (p.uri != null)
+            {
+                INamespaceDecorationNode ns = fnNode.getActualNamespaceNode();
+                INamespaceDefinition nsDef = 
(INamespaceDefinition)ns.resolve(getWalker().getProject());
+                fjs.formatQualifiedName(nsDef.getQualifiedName()); // register 
with used names 
+                //String s = nsDef.getURI();
+                write(JSRoyaleEmitter.formatNamespacedProperty(p.uri, 
baseName, false));
+            }
+            else
+                write(baseName);
+            write(ASEmitterTokens.COLON);
+            write(ASEmitterTokens.SPACE);
+            write(ASEmitterTokens.BLOCK_OPEN);
+            writeNewline();
+            if (getterNode != null)
+            {
+                write(ASEmitterTokens.GET);
+                write(ASEmitterTokens.COLON);
+                write(ASEmitterTokens.SPACE);
+                write(getEmitter().formatQualifiedName(qname));
+                write(ASEmitterTokens.MEMBER_ACCESS);
+                write(JSEmitterTokens.PROTOTYPE);
+                if (p.uri != null)
+                {
+                    INamespaceDecorationNode ns = 
((FunctionNode)getterNode).getActualNamespaceNode();
+                    INamespaceDefinition nsDef = 
(INamespaceDefinition)ns.resolve(getWalker().getProject());
+                    fjs.formatQualifiedName(nsDef.getQualifiedName()); // 
register with used names 
+                    //String s = nsDef.getURI();
+                    write(JSRoyaleEmitter.formatNamespacedProperty(p.uri, 
fjs.formatGetter(baseName), true));
+                }
+                else
+                {
+                    write(ASEmitterTokens.MEMBER_ACCESS);
+                    write(fjs.formatGetter(baseName));
+                }
+                wroteGetter = true;
+            }
+            else if (setterNode != null /* && 
setterNode.getDefinition().isOverride()*/)
+            {
+                // see if there is a getter on a base class.  If so, we have 
to 
+                // generate a call to the super from this class because 
+                // Object.defineProperty doesn't allow overriding just the 
setter.
+                // If there is no getter defineProp'd the property will seen as
+                // write-only.
+                IAccessorDefinition other = 
(IAccessorDefinition)SemanticUtils.resolveCorrespondingAccessor(p.setter.getDefinition(),
 getProject());
+                if (other != null)
+                {
+                    write(ASEmitterTokens.GET);
+                    write(ASEmitterTokens.COLON);
+                    write(ASEmitterTokens.SPACE);
+                    
+                    
write(getEmitter().formatQualifiedName(other.getParent().getQualifiedName()));
+                    write(ASEmitterTokens.MEMBER_ACCESS);
+                    write(JSEmitterTokens.PROTOTYPE);
+                    if (p.uri != null)
+                    {
+                        INamespaceDecorationNode ns = 
((FunctionNode)setterNode).getActualNamespaceNode();
+                        INamespaceDefinition nsDef = 
(INamespaceDefinition)ns.resolve(getWalker().getProject());
+                        fjs.formatQualifiedName(nsDef.getQualifiedName()); // 
register with used names 
+                        //String s = nsDef.getURI();
+                        write(JSRoyaleEmitter.formatNamespacedProperty(p.uri, 
fjs.formatGetter(baseName), true));
+                    }
+                    else
+                    {
+                        write(ASEmitterTokens.MEMBER_ACCESS);
+                        write(fjs.formatGetter(baseName));
+                    }
+                    wroteGetter = true;
+                }
+            }
+            if (setterNode != null)
+            {
+                if (wroteGetter)
+                    writeNewline(ASEmitterTokens.COMMA);
+
+                write(ASEmitterTokens.SET);
+                write(ASEmitterTokens.COLON);
+                write(ASEmitterTokens.SPACE);
+                write(getEmitter().formatQualifiedName(qname));
+                write(ASEmitterTokens.MEMBER_ACCESS);
+                write(JSEmitterTokens.PROTOTYPE);
+                if (p.uri != null)
+                {
+                    INamespaceDecorationNode ns = 
((FunctionNode)setterNode).getActualNamespaceNode();
+                    INamespaceDefinition nsDef = 
(INamespaceDefinition)ns.resolve(getWalker().getProject());
+                    fjs.formatQualifiedName(nsDef.getQualifiedName()); // 
register with used names 
+                    //String s = nsDef.getURI();
+                    write(JSRoyaleEmitter.formatNamespacedProperty(p.uri, 
fjs.formatSetter(baseName), true));
+                }
+                else
+                {
+                    write(ASEmitterTokens.MEMBER_ACCESS);
+                    write(fjs.formatSetter(baseName));
+                }
+            }
+            else if (getterNode != null/* && 
getterNode.getDefinition().isOverride()*/)
+            {
+                // see if there is a getter on a base class.  If so, we have 
to 
+                // generate a call to the super from this class because 
+                // Object.defineProperty doesn't allow overriding just the 
getter.
+                // If there is no setter defineProp'd the property will seen as
+                // read-only.
+                IAccessorDefinition other = 
(IAccessorDefinition)SemanticUtils.resolveCorrespondingAccessor(p.getter.getDefinition(),
 getProject());
+                if (other != null)
+                {
+                    if (wroteGetter)
+                        writeNewline(ASEmitterTokens.COMMA);
+
+                    write(ASEmitterTokens.SET);
+                    write(ASEmitterTokens.COLON);
+                    write(ASEmitterTokens.SPACE);
+                    
write(getEmitter().formatQualifiedName(other.getParent().getQualifiedName()));
+                    write(ASEmitterTokens.MEMBER_ACCESS);
+                    write(JSEmitterTokens.PROTOTYPE);
+                    if (p.uri != null)
+                    {
+                        INamespaceDecorationNode ns = 
((FunctionNode)getterNode).getActualNamespaceNode();
+                        INamespaceDefinition nsDef = 
(INamespaceDefinition)ns.resolve(getWalker().getProject());
+                        fjs.formatQualifiedName(nsDef.getQualifiedName()); // 
register with used names 
+                        //String s = nsDef.getURI();
+                        write(JSRoyaleEmitter.formatNamespacedProperty(p.uri, 
fjs.formatSetter(baseName), true));
+                    }
+                    else
+                    {
+                        write(ASEmitterTokens.MEMBER_ACCESS);
+                        write(fjs.formatSetter(baseName));
+                    }
+                }
+            }
+            write(ASEmitterTokens.BLOCK_CLOSE);
+        }
+        writeNewline(ASEmitterTokens.BLOCK_CLOSE);
+        write(ASEmitterTokens.PAREN_CLOSE);
+        write(ASEmitterTokens.SEMICOLON);
+    }
+
+    private void writeStaticDefinePropreties(IClassDefinition definition) {
+        JSRoyaleEmitter fjs = (JSRoyaleEmitter) getEmitter();
+
+        writeNewline();
+        writeNewline();
+        writeNewline();
+        write(JSGoogEmitterTokens.OBJECT);
+        write(ASEmitterTokens.MEMBER_ACCESS);
+        write(JSEmitterTokens.DEFINE_PROPERTIES);
+        write(ASEmitterTokens.PAREN_OPEN);
+        String qname = definition.getQualifiedName();
+        write(getEmitter().formatQualifiedName(qname));
+        write(ASEmitterTokens.COMMA);
+        write(ASEmitterTokens.SPACE);
+        write("/** @lends {" + getEmitter().formatQualifiedName(qname)
+                + "} */ ");
+        writeNewline(ASEmitterTokens.BLOCK_OPEN);
+
+        Set<String> propertyNames = getModel().getStaticPropertyMap()
+                .keySet();
+        boolean firstTime = true;
+        for (String propName : propertyNames)
+        {
+            if (firstTime)
+                firstTime = false;
+            else
+                writeNewline(ASEmitterTokens.COMMA);
+
+            PropertyNodes p = getModel().getStaticPropertyMap().get(
+                    propName);
+            IGetterNode getterNode = p.getter;
+            ISetterNode setterNode = p.setter;
+            String baseName = p.name;
+            writeNewline("/**");
+            if (p.type != null)
+                writeNewline(" * @type {" + 
JSRoyaleDocEmitter.convertASTypeToJSType(p.type.getBaseName(), 
p.type.getPackageName()) + "}");
+            writeNewline(" */");
+            FunctionNode fnNode = getterNode != null ? (FunctionNode) 
getterNode : (FunctionNode) setterNode;
+            if (p.uri != null)
+            {
+                INamespaceDecorationNode ns = fnNode.getActualNamespaceNode();
+                INamespaceDefinition nsDef = 
(INamespaceDefinition)ns.resolve(getWalker().getProject());
+                fjs.formatQualifiedName(nsDef.getQualifiedName()); // register 
with used names
+                //String s = nsDef.getURI();
+                write(JSRoyaleEmitter.formatNamespacedProperty(p.uri, 
baseName, false));
+            }
+            else
+                write(baseName);
+            write(ASEmitterTokens.COLON);
+            write(ASEmitterTokens.SPACE);
+            write(ASEmitterTokens.BLOCK_OPEN);
+            writeNewline();
+            if (getterNode != null)
+            {
+                write(ASEmitterTokens.GET);
+                write(ASEmitterTokens.COLON);
+                write(ASEmitterTokens.SPACE);
+                write(getEmitter().formatQualifiedName(qname));
+                if (p.uri != null)
+                {
+                    INamespaceDecorationNode ns = 
((FunctionNode)getterNode).getActualNamespaceNode();
+                    INamespaceDefinition nsDef = 
(INamespaceDefinition)ns.resolve(getWalker().getProject());
+                    fjs.formatQualifiedName(nsDef.getQualifiedName()); // 
register with used names 
+                    //String s = nsDef.getURI();
+                    write(JSRoyaleEmitter.formatNamespacedProperty(p.uri, 
fjs.formatGetter(baseName), true));
+                }
+                else
+                {
+                    write(ASEmitterTokens.MEMBER_ACCESS);
+                    write(fjs.formatGetter(baseName));
+                }
+            }
+            if (setterNode != null)
+            {
+                if (p.getter != null)
+                    writeNewline(ASEmitterTokens.COMMA);
+
+                write(ASEmitterTokens.SET);
+                write(ASEmitterTokens.COLON);
+                write(ASEmitterTokens.SPACE);
+                write(getEmitter().formatQualifiedName(qname));
+                if (p.uri != null)
+                {
+                    INamespaceDecorationNode ns = 
((FunctionNode)setterNode).getActualNamespaceNode();
+                    INamespaceDefinition nsDef = 
(INamespaceDefinition)ns.resolve(getWalker().getProject());
+                    fjs.formatQualifiedName(nsDef.getQualifiedName()); // 
register with used names 
+                    //String s = nsDef.getURI();
+                    write(JSRoyaleEmitter.formatNamespacedProperty(p.uri, 
fjs.formatSetter(baseName), true));
+                }
+                else
+                {
+                    write(ASEmitterTokens.MEMBER_ACCESS);
+                    write(fjs.formatSetter(baseName));
+                }
+            }
+            write(ASEmitterTokens.BLOCK_CLOSE);
+        }
+        writeNewline(ASEmitterTokens.BLOCK_CLOSE);
+        write(ASEmitterTokens.PAREN_CLOSE);
+        write(ASEmitterTokens.SEMICOLON);
+    }
+
+    private void writeGetterNode(PropertyNodes p, IClassDefinition definition) 
{
+        JSRoyaleEmitter fjs = (JSRoyaleEmitter) getEmitter();
+        String qname = definition.getQualifiedName();
+        String baseName = p.name;
+        IGetterNode getterNode = p.getter;
+        writeNewline();
+        writeNewline();
+        writeNewline();
+        write(getEmitter().formatQualifiedName(qname));
+        write(ASEmitterTokens.MEMBER_ACCESS);
+        write(JSEmitterTokens.PROTOTYPE);
+        if (p.uri != null)
+        {
+            INamespaceDecorationNode ns = 
((FunctionNode)getterNode).getActualNamespaceNode();
+            INamespaceDefinition nsDef = 
(INamespaceDefinition)ns.resolve(getWalker().getProject());
+            fjs.formatQualifiedName(nsDef.getQualifiedName()); // register 
with used names
+            write(JSRoyaleEmitter.formatNamespacedProperty(p.uri, 
fjs.formatGetter(baseName), true));
+        }
+        else
+        {
+            write(ASEmitterTokens.MEMBER_ACCESS);
+            write(fjs.formatGetter(baseName));
+        }
+        write(ASEmitterTokens.SPACE);
+        write(ASEmitterTokens.EQUAL);
+        write(ASEmitterTokens.SPACE);
+        write(ASEmitterTokens.FUNCTION);
+        fjs.emitParameters(getterNode.getParametersContainerNode());
+
+        fjs.emitDefinePropertyFunction(getterNode);
+                            
+        write(ASEmitterTokens.SEMICOLON);
+    }
+
+    private void writeSetterNode(PropertyNodes p, IClassDefinition definition)
+    {
+        JSRoyaleEmitter fjs = (JSRoyaleEmitter) getEmitter();
+        String qname = definition.getQualifiedName();
+        String baseName = p.name;
+        IGetterNode getterNode = p.getter;
+        ISetterNode setterNode = p.setter;
+        boolean isClassBindable = 
BindableHelper.isClassCodeGenBindable(definition);
+
+        boolean isBindable = false;                
+        IAccessorDefinition setterDef = 
(IAccessorDefinition)setterNode.getDefinition();
+        IAccessorDefinition getterDef = null;
+        if (getterNode != null)
+            getterDef = (IAccessorDefinition)getterNode.getDefinition();
+        if ((getterDef != null && (setterDef.isBindable() || 
getterDef.isBindable())))
+        {
+            boolean foundExplicitBindableTag = false;
+            if (setterDef.isBindable())
+            {
+
+                isBindable = BindableHelper.isCodeGenBindableMember(setterDef, 
isClassBindable);
+                foundExplicitBindableTag = 
BindableHelper.hasExplicitBindable(setterDef);
+            }
+            if (getterDef.isBindable())
+            {
+
+                isBindable = isBindable || 
BindableHelper.isCodeGenBindableMember(getterDef, isClassBindable);
+                foundExplicitBindableTag = foundExplicitBindableTag || 
BindableHelper.hasExplicitBindable(getterDef);
+
+            }
+
+            if (isClassBindable) {
+                //if we 'foundExplicitBindableTag' such as 
[Bindable(event='someEvent')], then nothing else matters, even another 
[Bindable] tag is ignored (Flex)
+                isBindable = !foundExplicitBindableTag;
+            }
+        }
+        writeNewline();
+        writeNewline();
+        writeNewline();
+        write(getEmitter().formatQualifiedName(qname));
+        write(ASEmitterTokens.MEMBER_ACCESS);
+        write(JSEmitterTokens.PROTOTYPE);
+        if (p.uri != null)
+        {
+            INamespaceDecorationNode ns = 
((FunctionNode)setterNode).getActualNamespaceNode();
+            INamespaceDefinition nsDef = 
(INamespaceDefinition)ns.resolve(getWalker().getProject());
+            fjs.formatQualifiedName(nsDef.getQualifiedName()); // register 
with used names
+            write(JSRoyaleEmitter.formatNamespacedProperty(p.uri, 
fjs.formatSetter(baseName), true));
+        }
+        else
+        {
+            write(ASEmitterTokens.MEMBER_ACCESS);
+            if (isBindable) {
+                write(JSRoyaleEmitterTokens.BINDABLE_PREFIX);
+                
write(fjs.formatSetter(fjs.formatPrivateName(definition.getQualifiedName(), 
baseName, true)));
+            } else {
+                write(fjs.formatSetter(baseName));
+            }
+        }
+        write(ASEmitterTokens.SPACE);
+        write(ASEmitterTokens.EQUAL);
+        write(ASEmitterTokens.SPACE);
+        write(ASEmitterTokens.FUNCTION);
+        fjs.emitParameters(setterNode.getParametersContainerNode());
+
+        fjs.emitDefinePropertyFunction(setterNode);
+        
+        write(ASEmitterTokens.SEMICOLON);
+        
+        if (isBindable)
+        {
+            writeNewline();
+            writeNewline();
+            writeNewline();
+            write(getEmitter().formatQualifiedName(qname));
+            write(ASEmitterTokens.MEMBER_ACCESS);
+            write(JSEmitterTokens.PROTOTYPE);
+            write(ASEmitterTokens.MEMBER_ACCESS);
+            write(fjs.formatSetter(baseName));
+            write(ASEmitterTokens.SPACE);
+            write(ASEmitterTokens.EQUAL);
+            write(ASEmitterTokens.SPACE);
+            write(ASEmitterTokens.FUNCTION);
+            write(ASEmitterTokens.PAREN_OPEN);
+            write("value");
+            write(ASEmitterTokens.PAREN_CLOSE);
+            write(ASEmitterTokens.SPACE);
+            writeNewline(ASEmitterTokens.BLOCK_OPEN);
+            write(ASEmitterTokens.VAR);
+            write(ASEmitterTokens.SPACE);
+            write("oldValue");
+            write(ASEmitterTokens.SPACE);
+            write(ASEmitterTokens.EQUAL);
+            write(ASEmitterTokens.SPACE);
+            write(ASEmitterTokens.THIS);
+            write(ASEmitterTokens.MEMBER_ACCESS);
+            write(fjs.formatGetter(baseName));
+            write(ASEmitterTokens.PAREN_OPEN);
+            write(ASEmitterTokens.PAREN_CLOSE);
+            writeNewline(ASEmitterTokens.SEMICOLON);
+            write(ASEmitterTokens.IF);
+            write(ASEmitterTokens.SPACE);
+            write(ASEmitterTokens.PAREN_OPEN);
+            write("oldValue != value");
+            write(ASEmitterTokens.PAREN_CLOSE);
+            write(ASEmitterTokens.SPACE);
+            writeNewline(ASEmitterTokens.BLOCK_OPEN);
+            write(ASEmitterTokens.THIS);
+            write(ASEmitterTokens.MEMBER_ACCESS);
+            write(JSRoyaleEmitterTokens.BINDABLE_PREFIX);
+            
write(fjs.formatSetter(fjs.formatPrivateName(definition.getQualifiedName(), 
baseName, true)));
+            write(ASEmitterTokens.PAREN_OPEN);
+            write("value");
+            write(ASEmitterTokens.PAREN_CLOSE);
+            writeNewline(ASEmitterTokens.SEMICOLON);
+            writeNewline("    
this.dispatchEvent("+fjs.formatQualifiedName(BindableEmitter.VALUECHANGE_EVENT_QNAME)+".createUpdateEvent(");
+            writeNewline("         this, \"" + p.originalName + "\", oldValue, 
value));");
+            writeNewline(ASEmitterTokens.BLOCK_CLOSE);
+            write(ASEmitterTokens.BLOCK_CLOSE);
+            write(ASEmitterTokens.SEMICOLON);                           
+        }
+    }
+
+    private void writeStaticGetterNode(PropertyNodes p, IClassDefinition 
definition) {
+        JSRoyaleEmitter fjs = (JSRoyaleEmitter) getEmitter();
+        String qname = definition.getQualifiedName();
+        String baseName = p.name;
+        IGetterNode getterNode = p.getter;
+
+        writeNewline();
+        writeNewline();
+        writeNewline();
+        write(getEmitter().formatQualifiedName(qname));
+        if (p.uri != null)
+        {
+            INamespaceDecorationNode ns = 
((FunctionNode)getterNode).getActualNamespaceNode();
+            INamespaceDefinition nsDef = 
(INamespaceDefinition)ns.resolve(getWalker().getProject());
+            fjs.formatQualifiedName(nsDef.getQualifiedName()); // register 
with used names 
+            //String s = nsDef.getURI();
+            write(JSRoyaleEmitter.formatNamespacedProperty(p.uri , 
fjs.formatGetter(baseName), true));
+        }
+        else
+        {
+            write(ASEmitterTokens.MEMBER_ACCESS);
+            write(fjs.formatGetter(baseName));
+        }
+        write(ASEmitterTokens.SPACE);
+        write(ASEmitterTokens.EQUAL);
+        write(ASEmitterTokens.SPACE);
+        write(ASEmitterTokens.FUNCTION);
+        fjs.emitParameters(getterNode.getParametersContainerNode());
+
+        fjs.emitDefinePropertyFunction(getterNode);
+        
+        write(ASEmitterTokens.SEMICOLON);
+    }
+
+    private void writeStaticSetterNode(PropertyNodes p, IClassDefinition 
definition) {
+        JSRoyaleEmitter fjs = (JSRoyaleEmitter) getEmitter();
+        String qname = definition.getQualifiedName();
+        String baseName = p.name;
+        ISetterNode setterNode = p.setter;
+
+        writeNewline();
+        writeNewline();
+        writeNewline();
+        write(getEmitter().formatQualifiedName(qname));
+        if (p.uri != null)
+        {
+            INamespaceDecorationNode ns = 
((FunctionNode)setterNode).getActualNamespaceNode();
+            INamespaceDefinition nsDef = 
(INamespaceDefinition)ns.resolve(getWalker().getProject());
+            fjs.formatQualifiedName(nsDef.getQualifiedName()); // register 
with used names 
+            //String s = nsDef.getURI();
+            write(JSRoyaleEmitter.formatNamespacedProperty(p.uri, 
fjs.formatSetter(baseName), true));
+        }
+        else
+        {
+            write(ASEmitterTokens.MEMBER_ACCESS);
+            write(fjs.formatSetter(baseName));
+        }
+        write(ASEmitterTokens.SPACE);
+        write(ASEmitterTokens.EQUAL);
+        write(ASEmitterTokens.SPACE);
+        write(ASEmitterTokens.FUNCTION);
+        fjs.emitParameters(setterNode.getParametersContainerNode());
+
+        fjs.emitDefinePropertyFunction(setterNode);
+        
+        write(ASEmitterTokens.SEMICOLON);
+    }
 }

Reply via email to