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;
+ }
}