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


The following commit(s) were added to refs/heads/develop by this push:
     new 733c41409 MXMLClassReferenceNodeBase: detect MXML 2006 declarations 
and add them to implicit MXMLDeclarationsNodes in the AST (references #243)
733c41409 is described below

commit 733c414091cbf6515e5d3416df1206b041ec06b5
Author: Josh Tynjala <[email protected]>
AuthorDate: Wed Mar 11 09:46:19 2026 -0700

    MXMLClassReferenceNodeBase: detect MXML 2006 declarations and add them to 
implicit MXMLDeclarationsNodes in the AST (references #243)
    
    <fx:Declarations> doesn't exist in MXML 2006. Instead, declarations are 
direct children of the root. This is a little quirky. If the root is an 
mx.core.IContainer, and the child implements mx.core.IUIComponent, then it 
isn't considered a Declaration. Otherwise, for non-container roots, or children 
that aren't UI components, then they are declarations.
    
    I could have added the declarations directly to the root (they were being 
incorrectly including in the default property), but then the SWF and JS 
emitters would also need to detect MXML 2006, and it all got pretty messy. 
Instead, the implicit MXMLDeclarationsNode makes the emitters detect 
declarations the same as MXML 2009.
---
 RELEASE_NOTES.md                                   |   1 +
 .../compiler/internal/projects/RoyaleProject.java  |  17 ++++
 .../projects/RoyaleProjectConfigurator.java        |   1 +
 .../tree/mxml/MXMLClassReferenceNodeBase.java      | 105 ++++++++++++++++-----
 4 files changed, 99 insertions(+), 25 deletions(-)

diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md
index 49a3a1f60..6add25ab6 100644
--- a/RELEASE_NOTES.md
+++ b/RELEASE_NOTES.md
@@ -61,6 +61,7 @@ Apache Royale Compiler 0.9.13
 - compiler: Fixed `as *` incorrectly emitting `*` in JS, which doesn't exist.
 - compiler: Optimized tracking of used qnames by using a set instead of a list.
 - compiler: Tests may be optionally run using Adobe AIR instead of Adobe Flash 
Player.
+- compiler: Fixed top-level children failing to be detected as declarations in 
MXML 2006 namespace.
 - debugger: Added missing isolate ID to SWF load and unload events.
 - debugger: Fixed debugger targeting the current JDK version instead of the 
intended minimum JDK version.
 - debugger: Fixed localized messages appearing as unprocessed tokens.
diff --git 
a/compiler/src/main/java/org/apache/royale/compiler/internal/projects/RoyaleProject.java
 
b/compiler/src/main/java/org/apache/royale/compiler/internal/projects/RoyaleProject.java
index 4dd44aecf..1f83fa685 100644
--- 
a/compiler/src/main/java/org/apache/royale/compiler/internal/projects/RoyaleProject.java
+++ 
b/compiler/src/main/java/org/apache/royale/compiler/internal/projects/RoyaleProject.java
@@ -307,6 +307,13 @@ public class RoyaleProject extends ASProject implements 
IRoyaleProject, ICompile
      * Currently this is "mx.core.IContainer".
      */
     private String containerInterface;
+
+    /**
+     * The fully-qualified name of the runtime interface
+     * for MX UI components.
+     * Currently this is "mx.core.IUIComponent".
+     */
+    private String uiComponentInterface;
     
     /**
      * The fully-qualified name of the runtime interface
@@ -814,6 +821,16 @@ public class RoyaleProject extends ASProject implements 
IRoyaleProject, ICompile
     {
         this.containerInterface = containerInterface;
     }
+    
+    public String getUIComponentInterface()
+    {
+        return uiComponentInterface;
+    }
+    
+    public void setUIComponentInterface(String uiComponentInterface)
+    {
+        this.uiComponentInterface = uiComponentInterface;
+    }
 
     public String getVisualElementContainerInterface()
     {
diff --git 
a/compiler/src/main/java/org/apache/royale/compiler/internal/projects/RoyaleProjectConfigurator.java
 
b/compiler/src/main/java/org/apache/royale/compiler/internal/projects/RoyaleProjectConfigurator.java
index 1bdb4c1e6..dcbc5af9b 100644
--- 
a/compiler/src/main/java/org/apache/royale/compiler/internal/projects/RoyaleProjectConfigurator.java
+++ 
b/compiler/src/main/java/org/apache/royale/compiler/internal/projects/RoyaleProjectConfigurator.java
@@ -163,6 +163,7 @@ public class RoyaleProjectConfigurator extends Configurator
         project.setMXMLObjectInterface(IMXMLTypeConstants.IMXMLObject);
         project.setContainerInterface(IMXMLTypeConstants.IContainer);
         
project.setVisualElementContainerInterface(IMXMLTypeConstants.IVisualElementContainer);
+        project.setUIComponentInterface(IMXMLTypeConstants.IUIComponent);
         project.setResourceBundleClass(IMXMLTypeConstants.ResourceBundle);
         project.setResourceManagerClass(IMXMLTypeConstants.ResourceManager);
         
project.setResourceModuleBaseClass(IMXMLTypeConstants.ResourceModuleBase);
diff --git 
a/compiler/src/main/java/org/apache/royale/compiler/internal/tree/mxml/MXMLClassReferenceNodeBase.java
 
b/compiler/src/main/java/org/apache/royale/compiler/internal/tree/mxml/MXMLClassReferenceNodeBase.java
index 567383dfb..ad39d68fd 100644
--- 
a/compiler/src/main/java/org/apache/royale/compiler/internal/tree/mxml/MXMLClassReferenceNodeBase.java
+++ 
b/compiler/src/main/java/org/apache/royale/compiler/internal/tree/mxml/MXMLClassReferenceNodeBase.java
@@ -57,6 +57,7 @@ import org.apache.royale.compiler.tree.ASTNodeID;
 import org.apache.royale.compiler.tree.as.IASNode;
 import org.apache.royale.compiler.tree.mxml.IMXMLClassReferenceNode;
 import org.apache.royale.compiler.tree.mxml.IMXMLEventSpecifierNode;
+import org.apache.royale.compiler.tree.mxml.IMXMLInstanceNode;
 import org.apache.royale.compiler.tree.mxml.IMXMLNode;
 import org.apache.royale.compiler.tree.mxml.IMXMLPropertySpecifierNode;
 import org.apache.royale.compiler.tree.mxml.IMXMLSpecifierNode;
@@ -113,6 +114,9 @@ abstract class MXMLClassReferenceNodeBase extends 
MXMLNodeBase implements IMXMLC
      */
     private boolean isDeferredInstantiationUIComponent = false;
 
+    private String containerInterface;
+    private String uiComponentInterface;
+
     /**
      * The child nodes of this node. For {@code MXMLInstanceNode} the children
      * will all be property/event/style specifiers. For
@@ -283,9 +287,11 @@ abstract class MXMLClassReferenceNodeBase extends 
MXMLNodeBase implements IMXMLC
 
         // Keep track of whether the class implements mx.core.IContainer,
         // because that affects code generation.
-        String containerInterface = project.getContainerInterface();
+        containerInterface = project.getContainerInterface();
         isContainer = classReference.isInstanceOf(containerInterface, project);
 
+        uiComponentInterface = project.getUIComponentInterface();
+
         // Keep track of whether the class implements 
mx.core.IDeferredInstantiationUIComponent
         // because that affects code generation.
         String deferredInstantiationUIComponentInterface = 
project.getDeferredInstantiationUIComponentInterface();
@@ -489,34 +495,51 @@ abstract class MXMLClassReferenceNodeBase extends 
MXMLNodeBase implements IMXMLC
             {
                 // Handle child tags that are instance tags.
 
-                IVariableDefinition defaultPropertyDefinition = 
getDefaultPropertyDefinition(builder);
-                if (defaultPropertyDefinition != null)
-                {
-                       if (processedDefaultProperty)
-                       {
-                               MXMLDuplicateChildTagProblem problem = new 
MXMLDuplicateChildTagProblem(childTag);
-                        problem.childTag = 
defaultPropertyDefinition.getBaseName();
-                        problem.element = tag.getShortName();
-                        builder.addProblem(problem);
-                        return ;
-                       }
-                       else
-                       {
-                           // Since there is a default property and we haven't 
already processed it,
-                           // assume this child instance tag is part of its 
value.
-                           processDefaultPropertyContentUnit(builder, 
childTag, info);
-                       }
-                }
-                else
+                if (isMXML2006Declaration(childTag, definition, builder))
                 {
                     // This tag is not part of the default property value.
                     processNonDefaultPropertyContentUnit(builder, info, tag);
 
-                    MXMLInstanceNode instanceNode = 
MXMLInstanceNode.createInstanceNode(
-                            builder, definition.getQualifiedName(), this);
-                    instanceNode.setClassReference(project, 
(IClassDefinition)definition); // TODO Move this logic to initializeFromTag().
-                    instanceNode.initializeFromTag(builder, childTag);
-                    info.addChildNode(instanceNode);
+                    // MXML 2006 doesn't have an fx:Declarations tag, but we 
can
+                    // still add a declarations node to the AST to help make
+                    // declarations easier for the emitters to detect. -JT
+                    MXMLDeclarationsNode declarationsNode = new 
MXMLDeclarationsNode(this);
+                    MXMLNodeInfo declarationsInfo = 
declarationsNode.createNodeInfo(builder);
+                    declarationsNode.processChildTag(builder, null, childTag, 
declarationsInfo);
+                    declarationsNode.initializationComplete(builder, null, 
declarationsInfo);
+                    info.addChildNode(declarationsNode);
+                }
+                else
+                {
+                    IVariableDefinition defaultPropertyDefinition = 
getDefaultPropertyDefinition(builder);
+                    if (defaultPropertyDefinition != null)
+                    {
+                        if (processedDefaultProperty)
+                        {
+                            MXMLDuplicateChildTagProblem problem = new 
MXMLDuplicateChildTagProblem(childTag);
+                            problem.childTag = 
defaultPropertyDefinition.getBaseName();
+                            problem.element = tag.getShortName();
+                            builder.addProblem(problem);
+                            return ;
+                        }
+                        else
+                        {
+                            // Since there is a default property and we 
haven't already processed it,
+                            // assume this child instance tag is part of its 
value.
+                            processDefaultPropertyContentUnit(builder, 
childTag, info);
+                        }
+                    }
+                    else
+                    {
+                        // This tag is not part of the default property value.
+                        processNonDefaultPropertyContentUnit(builder, info, 
tag);
+
+                        MXMLInstanceNode instanceNode = 
MXMLInstanceNode.createInstanceNode(
+                                builder, definition.getQualifiedName(), this);
+                        instanceNode.setClassReference(project, 
(IClassDefinition)definition); // TODO Move this logic to initializeFromTag().
+                        instanceNode.initializeFromTag(builder, childTag);
+                        info.addChildNode(instanceNode);   
+                    }
                 }
             }
             else
@@ -852,4 +875,36 @@ abstract class MXMLClassReferenceNodeBase extends 
MXMLNodeBase implements IMXMLC
 
         return true;
     }
+
+    protected boolean isMXML2006Declaration(IMXMLTagData childTag, IDefinition 
definition, MXMLTreeBuilder builder)
+    {
+        if (!MXMLDialect.MXML_2006.equals(builder.getMXMLDialect()))
+        {
+            return false;
+        }
+
+        IMXMLTagData rootTag = builder.getMXMLData().getRootTag();
+        if (rootTag == null || !rootTag.equals(childTag.getParentTag()))
+        {
+            // declarations must be direct children of the root tag
+            return false;
+        }
+
+        IDefinition rootDef = 
builder.getFileScope().resolveTagToDefinition(rootTag);
+        if (rootDef instanceof IClassDefinition
+            && ((IClassDefinition)rootDef).isInstanceOf(containerInterface, 
builder.getProject())
+            && definition instanceof IClassDefinition)
+        {
+            IClassDefinition childClassDef = (IClassDefinition) definition;
+            if (childClassDef != null
+                    && childClassDef.isInstanceOf(uiComponentInterface, 
builder.getProject()))
+            {
+                // this child is added to the display list instead of being
+                // treated as a declaration
+                return false;
+            }
+        }
+
+        return true;
+    }
 }

Reply via email to