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 2022/01/24 01:34:14 UTC
[royale-compiler] branch develop updated: [JS] Fixes for XMLList addition, for boolean equality checking vs. XML, and for QName inequality checking.
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 5a23c75 [JS] Fixes for XMLList addition, for boolean equality checking vs. XML, and for QName inequality checking.
5a23c75 is described below
commit 5a23c75f66247b3c84b55eb476951c3e5289ac31
Author: greg-dove <gr...@gmail.com>
AuthorDate: Mon Jan 24 14:30:35 2022 +1300
[JS] Fixes for XMLList addition, for boolean equality checking vs. XML, and for QName inequality checking.
---
.../codegen/js/jx/BinaryOperatorEmitter.java | 46 +++++--
.../compiler/internal/semantics/SemanticUtils.java | 139 ++++++++++++++-------
2 files changed, 132 insertions(+), 53 deletions(-)
diff --git a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/BinaryOperatorEmitter.java b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/BinaryOperatorEmitter.java
index bfbdc2b..051f3ff 100644
--- a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/BinaryOperatorEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/BinaryOperatorEmitter.java
@@ -255,15 +255,6 @@ public class BinaryOperatorEmitter extends JSSubEmitter implements
write(ASEmitterTokens.PAREN_CLOSE);
return;
}
- else if (node.getNodeID() == ASTNodeID.Op_EqualID &&
- node.getRightOperandNode().getNodeID() == ASTNodeID.LiteralBooleanID)
- {
- getWalker().walk(xmlNode);
- write(" == '");
- getWalker().walk(node.getRightOperandNode());
- write("'");
- return;
- }
}
else if (isDynamicAccess && ((JSRoyaleEmitter)getEmitter()).isXMLish((IExpressionNode)lnode))
{
@@ -480,12 +471,13 @@ public class BinaryOperatorEmitter extends JSSubEmitter implements
}
}
- if (id == ASTNodeID.Op_EqualID) {
+ if (id == ASTNodeID.Op_EqualID || id ==ASTNodeID.Op_NotEqualID) {
//QName == QName
if (leftDef != null && leftDef.getQualifiedName().equals("QName")) {
IDefinition rightDef = node.getRightOperandNode().resolveType(getProject());
if (rightDef != null && rightDef.getQualifiedName().equals("QName")) {
- //handle non-strict equality a little differently
+ //handle non-strict equality/inequality a little differently
+ if (id == ASTNodeID.Op_NotEqualID) write("!");
write("QName.equality(");
getWalker().walk(node.getLeftOperandNode());
write(",");
@@ -493,6 +485,38 @@ public class BinaryOperatorEmitter extends JSSubEmitter implements
write(")");
return;
}
+ } else if (leftDef != null && getProject().getBuiltinType(BuiltinType.BOOLEAN).equals(leftDef) && SemanticUtils.isXMLish(node.getRightOperandNode(), getProject())) {
+ boolean literalBool = node.getLeftOperandNode().getNodeID() == ASTNodeID.LiteralBooleanID;
+ //note, this only covers boolean ==/!= xmlish, not: xmlish ==/!= boolean
+ if (literalBool) {
+ write("'");
+ }
+ else write("('' + ");
+ getWalker().walk(node.getLeftOperandNode());
+ if (literalBool) {
+ write("'");
+ }
+ else write(")");
+ write(" " + node.getOperator().getOperatorText() + " ");
+
+ getWalker().walk(node.getRightOperandNode());
+ return;
+ } else if ((((leftDef == null || getProject().getBuiltinType(BuiltinType.ANY_TYPE).equals(leftDef)) && SemanticUtils.isXMLish(node.getLeftOperandNode(), getProject())) || SemanticUtils.isXMLish(leftDef, getProject())) && getProject().getBuiltinType(BuiltinType.BOOLEAN).equals(node.getRightOperandNode().resolveType(getProject()))) {
+ boolean literalBool = node.getRightOperandNode().getNodeID() == ASTNodeID.LiteralBooleanID;
+
+ //note, this only covers xmlish ==/!= boolean, not: boolean ==/!= xmlish
+ getWalker().walk(node.getLeftOperandNode());
+ write(" " + node.getOperator().getOperatorText() + " ");
+ if (literalBool) {
+ write("'");
+ }
+ else write("('' + ");
+ getWalker().walk(node.getRightOperandNode());
+ if (literalBool) {
+ write("'");
+ }
+ else write(")");
+ return;
}
}
diff --git a/compiler/src/main/java/org/apache/royale/compiler/internal/semantics/SemanticUtils.java b/compiler/src/main/java/org/apache/royale/compiler/internal/semantics/SemanticUtils.java
index 7973e71..120b934 100644
--- a/compiler/src/main/java/org/apache/royale/compiler/internal/semantics/SemanticUtils.java
+++ b/compiler/src/main/java/org/apache/royale/compiler/internal/semantics/SemanticUtils.java
@@ -33,17 +33,8 @@ import org.apache.royale.compiler.common.DependencyType;
import org.apache.royale.compiler.constants.IASKeywordConstants;
import org.apache.royale.compiler.constants.IASLanguageConstants;
import org.apache.royale.compiler.constants.IASLanguageConstants.BuiltinType;
-import org.apache.royale.compiler.definitions.IAccessorDefinition;
-import org.apache.royale.compiler.definitions.IClassDefinition;
-import org.apache.royale.compiler.definitions.IConstantDefinition;
-import org.apache.royale.compiler.definitions.IDefinition;
-import org.apache.royale.compiler.definitions.IFunctionDefinition;
+import org.apache.royale.compiler.definitions.*;
import org.apache.royale.compiler.definitions.IFunctionDefinition.FunctionClassification;
-import org.apache.royale.compiler.definitions.IInterfaceDefinition;
-import org.apache.royale.compiler.definitions.INamespaceDefinition;
-import org.apache.royale.compiler.definitions.IParameterDefinition;
-import org.apache.royale.compiler.definitions.IScopedDefinition;
-import org.apache.royale.compiler.definitions.ITypeDefinition;
import org.apache.royale.compiler.definitions.metadata.IDeprecationInfo;
import org.apache.royale.compiler.definitions.references.INamespaceReference;
import org.apache.royale.compiler.definitions.references.IReference;
@@ -110,28 +101,10 @@ import org.apache.royale.compiler.problems.ScopedToDefaultNamespaceProblem;
import org.apache.royale.compiler.problems.UnknownSuperclassProblem;
import org.apache.royale.compiler.projects.ICompilerProject;
import org.apache.royale.compiler.scopes.IASScope;
+import org.apache.royale.compiler.scopes.IDefinitionSet;
import org.apache.royale.compiler.tree.ASTNodeID;
-import org.apache.royale.compiler.tree.as.IASNode;
-import org.apache.royale.compiler.tree.as.IClassNode;
-import org.apache.royale.compiler.tree.as.ICommonClassNode;
-import org.apache.royale.compiler.tree.as.IContainerNode;
-import org.apache.royale.compiler.tree.as.IDefinitionNode;
-import org.apache.royale.compiler.tree.as.IExpressionNode;
-import org.apache.royale.compiler.tree.as.IFileNode;
-import org.apache.royale.compiler.tree.as.IFunctionCallNode;
-import org.apache.royale.compiler.tree.as.IFunctionNode;
-import org.apache.royale.compiler.tree.as.IIdentifierNode;
-import org.apache.royale.compiler.tree.as.IImportNode;
-import org.apache.royale.compiler.tree.as.ILanguageIdentifierNode;
+import org.apache.royale.compiler.tree.as.*;
import org.apache.royale.compiler.tree.as.ILanguageIdentifierNode.LanguageIdentifierKind;
-import org.apache.royale.compiler.tree.as.ILiteralNode;
-import org.apache.royale.compiler.tree.as.IMemberAccessExpressionNode;
-import org.apache.royale.compiler.tree.as.INamespaceDecorationNode;
-import org.apache.royale.compiler.tree.as.INumericLiteralNode;
-import org.apache.royale.compiler.tree.as.IParameterNode;
-import org.apache.royale.compiler.tree.as.IScopedNode;
-import org.apache.royale.compiler.tree.as.ITryNode;
-import org.apache.royale.compiler.tree.as.IVariableNode;
import org.apache.royale.compiler.tree.mxml.IMXMLEventSpecifierNode;
/**
@@ -981,13 +954,18 @@ public class SemanticUtils
*/
public static IDefinition resolveXML(IExpressionNode iNode, ICompilerProject project)
{
+ if (iNode.getNodeID().equals(ASTNodeID.E4XFilterID)) {
+ // return XMLList, we can be certain
+ return project.getBuiltinType(IASLanguageConstants.BuiltinType.XMLLIST);
+ }
if (iNode instanceof IFunctionCallNode)
{
IFunctionCallNode functionCall = (IFunctionCallNode) iNode;
IExpressionNode nameNode = functionCall.getNameNode();
+ IMemberAccessExpressionNode memberAccess = null;
if (nameNode instanceof IMemberAccessExpressionNode)
{
- IMemberAccessExpressionNode memberAccess = (IMemberAccessExpressionNode) nameNode;
+ memberAccess = (IMemberAccessExpressionNode) nameNode;
nameNode = memberAccess.getRightOperandNode();
}
if (nameNode instanceof IIdentifierNode)
@@ -1000,46 +978,99 @@ public class SemanticUtils
&& !(resolvedDef instanceof IAccessorDefinition))
{
//method call on XML or XMLList instance
+ resolvedDef = methodXMLishReturnType((IFunctionDefinition)resolvedDef,project);
return resolvedDef;
}
} else {
resolvedDef = functionCall.resolveType(project);
if (resolvedDef != null && isXMLish(resolvedDef, project)) return resolvedDef;
}
+ if (memberAccess !=null) {
+ //try left
+ IDefinition leftDef = resolveXML(memberAccess.getLeftOperandNode(), project);
+ if (leftDef != null) {
+ IClassDefinition xmlish = (IClassDefinition) leftDef;
+ IDefinitionSet funcDefs = xmlish.getContainedScope().getLocalDefinitionSetByName(identifierNode.getName());
+
+ if (funcDefs != null){
+ if (funcDefs.getSize() == 1) {
+ IFunctionDefinition funcDef = (IFunctionDefinition)funcDefs.getDefinition(0);
+ resolvedDef = methodXMLishReturnType(funcDef, project);//.resolveReturnType(project);
+ if (resolvedDef != null) return resolvedDef;
+ } //there should be no competing definitions on XMLish classes
+ }
+ }
+ }
+
}
+
return null;
}
- if (iNode instanceof IIdentifierNode)
+ else if (iNode instanceof IIdentifierNode)
{
IIdentifierNode identifierNode = (IIdentifierNode) iNode;
IDefinition resolvedDef = identifierNode.resolve(project);
- if (resolvedDef != null && isXMLish(resolvedDef.getParent(), project))
- {
- if (resolvedDef.isPrivate() || resolvedDef.isProtected())
- {
- //private/protected member inside the XML or XMLList class
+ if (resolvedDef instanceof IVariableDefinition) {
+ resolvedDef = resolvedDef.resolveType(project);
+ if (resolvedDef != null && isXMLish(resolvedDef, project)) {
return resolvedDef;
}
- } else {
+ }
+ else {
resolvedDef = identifierNode.resolveType(project);
if (resolvedDef != null && isXMLish(resolvedDef, project)) {
return resolvedDef;
}
}
}
- if (iNode instanceof IMemberAccessExpressionNode)
+ else if (iNode instanceof IMemberAccessExpressionNode)
{
IMemberAccessExpressionNode memberAccess = (IMemberAccessExpressionNode) iNode;
IExpressionNode nameNode = memberAccess.getRightOperandNode();
- return resolveXML(nameNode, project);
+ IDefinition resolvedDef = resolveXML(nameNode, project);
+ if (resolvedDef == null) {
+ IDefinition lhs = resolveXML(memberAccess.getLeftOperandNode(), project);
+ if (lhs != null) {
+ if ((nameNode instanceof IUnaryOperatorNode && nameNode.getNodeID().equals(ASTNodeID.Op_AtID)) ||
+ nameNode instanceof IIdentifierNode) {
+ return project.getBuiltinType(BuiltinType.XMLLIST);
+ }
+ }
+ }
+ return resolvedDef;
+ }
+ else if (iNode instanceof IDynamicAccessNode) {
+ IDynamicAccessNode dynAccess = (IDynamicAccessNode) iNode;
+ boolean isNumericAccess = SemanticUtils.isNumericType(dynAccess.getRightOperandNode().resolveType(project), project);
+ IExpressionNode leftSideExpressioNode = dynAccess.getLeftOperandNode();
+ if (!isNumericAccess && leftSideExpressioNode.getNodeID().equals(ASTNodeID.Op_AtID)) {
+ if (dynAccess.getParent() instanceof IMemberAccessExpressionNode) {
+ IMemberAccessExpressionNode mae = (IMemberAccessExpressionNode) (dynAccess.getParent());
+ leftSideExpressioNode = mae.getLeftOperandNode();
+ }
+ }
+ IDefinition lhs = resolveXML(leftSideExpressioNode, project);
+ if (lhs != null) {
+ //if the type is numeric, then assume it is XML, if it is non-numeric, then XMLList
+ return isNumericAccess ? project.getBuiltinType(BuiltinType.XML) : project.getBuiltinType(BuiltinType.XMLLIST);
+ }
+ }
+ else if (iNode instanceof IBinaryOperatorNode) {
+ IBinaryOperatorNode binaryOperatorNode = (IBinaryOperatorNode) iNode;
+ if (binaryOperatorNode.getNodeID().equals(ASTNodeID.Op_AddID)) {
+ //System.out.println("Op_AddID");
+ if (resolveXML(binaryOperatorNode.getLeftOperandNode(),project)!= null && resolveXML(binaryOperatorNode.getRightOperandNode(), project)!=null) {
+ return project.getBuiltinType(BuiltinType.XMLLIST);
+ }
+ }
}
return null;
}
/**
* Determine if the definition passed in is one of the XML types (XML or
- * XMLList) These classes are unrelated, but behave in similar manners.
+ * XMLList) These classes are distinct classes, without shared ancestry or interfaces, but behave in similar manners.
*
* @param iNode the {@link IExpressionNode} to check
* @param project the {@link ICompilerProject} in which to look up types
@@ -1065,6 +1096,30 @@ public class SemanticUtils
return (xmlDef != null && def == xmlDef) ||
(xmlListDef != null && def == xmlListDef);
}
+
+ /**
+ * For an unresolved return type, special case the checking of it.
+ * in XML, parent():* and insertChildAfter are some examples
+ * @param method
+ * @param project
+ * @return
+ */
+ private static IDefinition methodXMLishReturnType(IFunctionDefinition method, ICompilerProject project){
+
+ IDefinition returnType = method.resolveReturnType(project);
+ if (returnType.equals(project.getBuiltinType(BuiltinType.ANY_TYPE)) && project.getBuiltinType(BuiltinType.XML).equals(method.getParent())) {
+ //method names which can be considered to return XML instead of '*'
+ //these are either XML or undefined (as opposed to null)
+ //3 methods that can be considered having XMLish return types : "parent", "insertChildAfter", "insertChildBefore"
+ if (method.getBaseName().matches("parent|insertChildAfter|insertChildBefore")) {
+ return project.getBuiltinType(BuiltinType.XML);
+ }
+ }
+ if (isXMLish(returnType,project)) {
+ return returnType;
+ }
+ return null;
+ }
/**
* Determines if an expression is a toString() function call.
@@ -1347,7 +1402,7 @@ public class SemanticUtils
/**
* Is this function node contained within another function node?
- * @param iNode - the node of interest.
+ * @param functionNode - the node of interest.
* @return true if the function node is a closure
*/
public static boolean isFunctionClosure(IFunctionNode functionNode)