You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@royale.apache.org by gr...@apache.org on 2020/03/08 22:59:45 UTC
[royale-compiler] branch develop updated: 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
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 <gr...@gmail.com>
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)