This is an automated email from the ASF dual-hosted git repository.
gregdove 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 5519529 Try a bit harder to determine the XMLish-ness of a function
call return type from an XMLish member-access chain. This avoids the wrong
interpretation of things like myXML.name() or myXML.namespace(), but still
works for myXML.attributes(), for example
5519529 is described below
commit 5519529ec94a7ee6f1968198ff176da0bacec463
Author: greg-dove <[email protected]>
AuthorDate: Mon Mar 9 11:57:54 2020 +1300
Try a bit harder to determine the XMLish-ness of a function call return
type from an XMLish member-access chain.
This avoids the wrong interpretation of things like myXML.name() or
myXML.namespace(), but still works for myXML.attributes(), for example
---
.../internal/codegen/js/jx/ForEachEmitter.java | 35 ++++++++++++++++++--
.../internal/codegen/js/utils/EmitterUtils.java | 38 ++++++++++++++++++++++
2 files changed, 71 insertions(+), 2 deletions(-)
diff --git
a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/ForEachEmitter.java
b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/ForEachEmitter.java
index 2902821..d8f1a4c 100644
---
a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/ForEachEmitter.java
+++
b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/ForEachEmitter.java
@@ -22,6 +22,7 @@ package org.apache.royale.compiler.internal.codegen.js.jx;
import org.apache.royale.compiler.codegen.ISubEmitter;
import org.apache.royale.compiler.codegen.js.IJSEmitter;
import org.apache.royale.compiler.constants.IASLanguageConstants;
+import org.apache.royale.compiler.definitions.IDefinition;
import org.apache.royale.compiler.definitions.IFunctionDefinition;
import org.apache.royale.compiler.internal.codegen.as.ASEmitterTokens;
import org.apache.royale.compiler.internal.codegen.js.JSSubEmitter;
@@ -32,6 +33,7 @@ import
org.apache.royale.compiler.internal.tree.as.FunctionCallNode;
import org.apache.royale.compiler.internal.tree.as.IdentifierNode;
import org.apache.royale.compiler.internal.tree.as.LabeledStatementNode;
import org.apache.royale.compiler.internal.tree.as.MemberAccessExpressionNode;
+import org.apache.royale.compiler.scopes.IDefinitionSet;
import org.apache.royale.compiler.tree.ASTNodeID;
import org.apache.royale.compiler.tree.as.*;
@@ -163,14 +165,43 @@ public class ForEachEmitter extends JSSubEmitter
implements
} else if (funcName instanceof IMemberAccessExpressionNode) {
IFunctionDefinition funcDef = (IFunctionDefinition)
((IMemberAccessExpressionNode)
funcName).getRightOperandNode().resolve(getProject());
if (funcDef == null) {
- isXML =
EmitterUtils.isXMLList((IMemberAccessExpressionNode)funcName, getProject()) ||
EmitterUtils.isXML(funcName, getProject());
+ //we need to check the LHS for XMLishness, and then
resolve the method name against the determined XMLish definition (XML or
XMLList),
+ // and then check its return type once we find the public
FunctionDefinition for the method name
+ // (because although it is a member of something XMLish,
it may not return something that is also XMLish, such as a QName, a String, a
uint, or a Namespace etc)
+ IDefinitionSet matchingDefinitions = null;
+ if
(EmitterUtils.isLeftNodeXML(((IMemberAccessExpressionNode)
funcName).getLeftOperandNode(), getProject())) {
+ if (((IMemberAccessExpressionNode)
funcName).getRightOperandNode().getNodeID() == ASTNodeID.IdentifierID) {
+ matchingDefinitions =
getProject().getBuiltinType(IASLanguageConstants.BuiltinType.XML).getContainedScope().getLocalDefinitionSetByName(((IIdentifierNode)((IMemberAccessExpressionNode)
funcName).getRightOperandNode()).getName());
+ }
+ } else if
(EmitterUtils.isLeftNodeXMLList(((IMemberAccessExpressionNode)
funcName).getLeftOperandNode(), getProject())) {
+ if (((IMemberAccessExpressionNode)
funcName).getRightOperandNode().getNodeID() == ASTNodeID.IdentifierID) {
+ matchingDefinitions =
getProject().getBuiltinType(IASLanguageConstants.BuiltinType.XMLLIST).getContainedScope().getLocalDefinitionSetByName(((IIdentifierNode)((IMemberAccessExpressionNode)
funcName).getRightOperandNode()).getName());
+ }
+ }
+ if (matchingDefinitions != null) {
+ for (int i = 0; i< matchingDefinitions.getSize(); i++)
{
+ IDefinition functionDefinition =
matchingDefinitions.getDefinition(i);
+ if (functionDefinition instanceof
IFunctionDefinition) {
+ if (functionDefinition.isPublic()) {
+ isXML =
SemanticUtils.isXMLish((((IFunctionDefinition)
functionDefinition).resolveReturnType(getProject())), getProject());
+ break;
+ }
+ }
+ }
+ }
+
+ //@todo should we emit a warning here if wasXMLish (from
either of the first 2 checks) && !isXML (from the matchingDefinitions check)?
+ // results will not be consistent in this case.
+ // e.g. looping over a QName or Namespace instance
+ // It is probably rare and ill-advised, but it definitely
won't work well in javascript currently for those classes, for example.
+
} else {
isXML =
SemanticUtils.isXMLish(funcDef.resolveReturnType(getProject()), getProject());
}
if (isXML) {
write(".elementNames()");
}
- }
+ } //@todo what about dynamic access node for function call? e.g.
myXML[string_Value_Here]() ... not so easy really, would likely need a runtime
helper/wrapper.
}
endMapping(rnode);
startMapping(node, cnode);
diff --git
a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/utils/EmitterUtils.java
b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/utils/EmitterUtils.java
index 3d35ec3..2e03bf2 100644
---
a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/utils/EmitterUtils.java
+++
b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/utils/EmitterUtils.java
@@ -802,6 +802,44 @@ public class EmitterUtils
return true;
return false;
}
+
+ public static boolean isLeftNodeXMLList(IExpressionNode leftNode,
ICompilerProject project) {
+ boolean isXMLList = false;
+ if (isLeftNodeXMLish(leftNode, project)) {
+ //it is not XMLList if it is a DynamicAccessNode with numeric
index.
+ //this is limited analysis, because ["0"] would also be the same
as [0], but perhaps best we can do without more runtime support
+ if (leftNode instanceof IDynamicAccessNode) { //DynamicAccessNode
+ IExpressionNode dynAccess = ((IDynamicAccessNode)
leftNode).getRightOperandNode();
+ IDefinition accessDef = dynAccess.resolveType(project);
+ if (SemanticUtils.isNumericType(accessDef, project)) {
+ //assume we are XML, not XMLList
+ isXMLList = false;
+ }
+ } else
+ isXMLList = true;
+
+ }
+ return isXMLList;
+ }
+
+ public static boolean isLeftNodeXML(IExpressionNode leftNode,
ICompilerProject project) {
+ boolean isXML = false;
+ if (isLeftNodeXMLish(leftNode, project)) {
+ //it is not XMLList if it is a DynamicAccessNode with numeric
index.
+ //this is limited analysis, because ["0"] would also be the same
as [0], but perhaps best we can do without more runtime support
+ if (leftNode instanceof IDynamicAccessNode) { //DynamicAccessNode
+ IExpressionNode dynAccess = ((IDynamicAccessNode)
leftNode).getRightOperandNode();
+ IDefinition accessDef = dynAccess.resolveType(project);
+ if (SemanticUtils.isNumericType(accessDef, project)) {
+ //assume we are XML, not XMLList
+ isXML = true;
+ }
+ } else
+ isXML = false;
+
+ }
+ return isXML;
+ }
public static boolean isLeftNodeXMLish(IExpressionNode leftNode,
ICompilerProject project)