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 81d8866 JSEmitter: emitAssignmentCoercion() now includes special
cases for String coercion with undefined, toString(), and XML methods. Number
coercion detects [ArrayElementType("Number")]. IdentifierNode: moved isXMLish()
to SemanticUtils because it doesn't really apply specifically to identifiers.
BinaryOperatorEmitter: uses the same emitAssignmentCoercion() from JSEmitter as
ReturnEmitter and FunctionCallArgumentsEmitter. Type coercion on assignment is
now in two places inste [...]
81d8866 is described below
commit 81d8866708d67511681882bc51dfbcb052bac9d6
Author: Josh Tynjala <[email protected]>
AuthorDate: Wed Feb 20 11:40:03 2019 -0800
JSEmitter: emitAssignmentCoercion() now includes special cases for String
coercion with undefined, toString(), and XML methods. Number coercion detects
[ArrayElementType("Number")].
IdentifierNode: moved isXMLish() to SemanticUtils because it doesn't really
apply specifically to identifiers.
BinaryOperatorEmitter: uses the same emitAssignmentCoercion() from
JSEmitter as ReturnEmitter and FunctionCallArgumentsEmitter. Type coercion on
assignment is now in two places instead of three.
---
.../compiler/internal/codegen/js/JSEmitter.java | 72 +++++-
.../codegen/js/jx/BinaryOperatorEmitter.java | 280 ++-------------------
.../codegen/js/jx/VarDeclarationEmitter.java | 33 ++-
.../codegen/js/royale/JSRoyaleEmitter.java | 11 +-
.../codegen/js/royale/TestRoyaleExpressions.java | 220 +++++++++++++---
.../codegen/js/royale/TestRoyaleStatements.java | 54 ++++
.../junittestcases5491906995083840238.properties | 55 ++++
.../compiler/internal/semantics/SemanticUtils.java | 114 ++++++++-
.../internal/tree/as/BinaryOperatorPlusNode.java | 5 +-
.../compiler/internal/tree/as/IdentifierNode.java | 22 +-
10 files changed, 532 insertions(+), 334 deletions(-)
diff --git
a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/JSEmitter.java
b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/JSEmitter.java
index c7a4570..178670e 100644
---
a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/JSEmitter.java
+++
b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/JSEmitter.java
@@ -23,14 +23,18 @@ import java.io.FilterWriter;
import java.util.ArrayList;
import java.util.List;
+import org.apache.royale.compiler.codegen.IDocEmitter;
import org.apache.royale.compiler.codegen.IEmitter;
import org.apache.royale.compiler.codegen.ISubEmitter;
import org.apache.royale.compiler.codegen.js.IJSEmitter;
import org.apache.royale.compiler.codegen.js.IMappingEmitter;
import org.apache.royale.compiler.common.ISourceLocation;
import org.apache.royale.compiler.constants.IASLanguageConstants;
+import org.apache.royale.compiler.constants.IMetaAttributeConstants;
import org.apache.royale.compiler.constants.IASLanguageConstants.BuiltinType;
import org.apache.royale.compiler.definitions.IDefinition;
+import org.apache.royale.compiler.definitions.metadata.IMetaTag;
+import org.apache.royale.compiler.definitions.metadata.IMetaTagAttribute;
import org.apache.royale.compiler.internal.codegen.as.ASEmitter;
import org.apache.royale.compiler.internal.codegen.as.ASEmitterTokens;
import org.apache.royale.compiler.internal.codegen.js.jx.BlockCloseEmitter;
@@ -59,6 +63,8 @@ import
org.apache.royale.compiler.internal.codegen.js.jx.TryEmitter;
import org.apache.royale.compiler.internal.codegen.js.jx.UnaryOperatorEmitter;
import org.apache.royale.compiler.internal.codegen.js.jx.WhileLoopEmitter;
import org.apache.royale.compiler.internal.codegen.js.jx.WithEmitter;
+import
org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleDocEmitter;
+import org.apache.royale.compiler.internal.semantics.SemanticUtils;
import org.apache.royale.compiler.internal.tree.as.FunctionNode;
import org.apache.royale.compiler.projects.ICompilerProject;
import org.apache.royale.compiler.tree.as.IASNode;
@@ -528,6 +534,15 @@ public class JSEmitter extends ASEmitter implements
IJSEmitter
{
assignedDef = assignedNode.resolve(project);
assignedTypeDef = assignedNode.resolveType(project);
+ if
(project.getBuiltinType(BuiltinType.ANY_TYPE).equals(assignedTypeDef))
+ {
+ IDefinition resolvedXMLDef =
SemanticUtils.resolveXML(assignedNode, project);
+ if (resolvedXMLDef != null)
+ {
+ assignedDef = resolvedXMLDef;
+ assignedTypeDef =
SemanticUtils.resolveTypeXML(assignedNode, project);
+ }
+ }
}
String coercionStart = null;
String coercionEnd = null;
@@ -580,7 +595,36 @@ public class JSEmitter extends ASEmitter implements
IJSEmitter
&&
!project.getBuiltinType(BuiltinType.INT).equals(assignedTypeDef)
&&
!project.getBuiltinType(BuiltinType.UINT).equals(assignedTypeDef))
{
- coercionStart = "Number(";
+ boolean needsCoercion = true;
+ if (assignedNode instanceof IDynamicAccessNode)
+ {
+ IDynamicAccessNode dynamicAccess = (IDynamicAccessNode)
assignedNode;
+ IDefinition dynamicAccessIndexDef =
dynamicAccess.getRightOperandNode().resolveType(project);
+ if
(project.getBuiltinType(BuiltinType.NUMBER).equals(dynamicAccessIndexDef))
+ {
+ IDefinition leftDef =
dynamicAccess.getLeftOperandNode().resolveType(project);
+ IMetaTag[] metas = leftDef.getAllMetaTags();
+ for (IMetaTag meta : metas)
+ {
+ if
(meta.getTagName().equals(IMetaAttributeConstants.ATTRIBUTE_ARRAYELEMENTTYPE))
+ {
+ IMetaTagAttribute[] attrs =
meta.getAllAttributes();
+ for (IMetaTagAttribute attr : attrs)
+ {
+ String t = attr.getValue();
+ if (t.equals(IASLanguageConstants.Number))
+ {
+ needsCoercion = false;
+ }
+ }
+ }
+ }
+ }
+ }
+ if (needsCoercion)
+ {
+ coercionStart = "Number(";
+ }
}
else if (project.getBuiltinType(BuiltinType.BOOLEAN).equals(definition)
&&
!project.getBuiltinType(BuiltinType.BOOLEAN).equals(assignedTypeDef))
@@ -611,15 +655,35 @@ public class JSEmitter extends ASEmitter implements
IJSEmitter
}
else if (project.getBuiltinType(BuiltinType.STRING).equals(definition)
&&
!project.getBuiltinType(BuiltinType.STRING).equals(assignedTypeDef)
- &&
!project.getBuiltinType(BuiltinType.NULL).equals(assignedTypeDef))
+ &&
!project.getBuiltinType(BuiltinType.NULL).equals(assignedTypeDef)
+ &&
!(project.getBuiltinType(BuiltinType.ANY_TYPE).equals(assignedTypeDef)
+ && SemanticUtils.isToStringFunctionCall(assignedNode,
project)))
{
- coercionStart = "org.apache.royale.utils.Language.string(";
+ if(assignedDef != null &&
assignedDef.getQualifiedName().equals(IASLanguageConstants.UNDEFINED))
+ {
+ //undefined is coerced to null
+ startMapping(assignedNode);
+ write(IASLanguageConstants.NULL);
+ endMapping(assignedNode);
+ return;
+ }
+ boolean emitStringCoercion = true;
+ IDocEmitter docEmitter = getDocEmitter();
+ if (docEmitter instanceof JSRoyaleDocEmitter)
+ {
+ JSRoyaleDocEmitter royaleDocEmitter = (JSRoyaleDocEmitter)
docEmitter;
+ emitStringCoercion = royaleDocEmitter.emitStringConversions;
+ }
+ if (emitStringCoercion)
+ {
+ coercionStart = "org.apache.royale.utils.Language.string(";
+ }
}
if (coercionStart != null)
{
write(coercionStart);
- }
+ }
getWalker().walk(assignedNode);
if (coercionStart != null)
{
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 884168a..1533bf4 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
@@ -21,23 +21,17 @@ 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.constants.IASLanguageConstants.BuiltinType;
import org.apache.royale.compiler.definitions.IDefinition;
import org.apache.royale.compiler.definitions.ITypeDefinition;
-import org.apache.royale.compiler.definitions.metadata.IMetaTag;
-import org.apache.royale.compiler.definitions.metadata.IMetaTagAttribute;
import org.apache.royale.compiler.internal.codegen.as.ASEmitterTokens;
import org.apache.royale.compiler.internal.codegen.js.JSEmitterTokens;
import org.apache.royale.compiler.internal.codegen.js.JSSubEmitter;
-import
org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleDocEmitter;
import org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleEmitter;
import
org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleEmitterTokens;
import org.apache.royale.compiler.internal.codegen.js.goog.JSGoogEmitterTokens;
import org.apache.royale.compiler.internal.definitions.AccessorDefinition;
+import org.apache.royale.compiler.internal.semantics.SemanticUtils;
import org.apache.royale.compiler.internal.tree.as.DynamicAccessNode;
-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.MemberAccessExpressionNode;
import org.apache.royale.compiler.internal.tree.as.UnaryOperatorAtNode;
import org.apache.royale.compiler.tree.ASTNodeID;
@@ -46,7 +40,6 @@ import org.apache.royale.compiler.tree.as.IBinaryOperatorNode;
import org.apache.royale.compiler.tree.as.IClassNode;
import org.apache.royale.compiler.tree.as.IExpressionNode;
import org.apache.royale.compiler.tree.as.IIdentifierNode;
-import org.apache.royale.compiler.tree.as.INumericLiteralNode;
import org.apache.royale.compiler.utils.ASNodeUtils;
public class BinaryOperatorEmitter extends JSSubEmitter implements
@@ -320,7 +313,7 @@ public class BinaryOperatorEmitter extends JSSubEmitter
implements
else if (leftSide.getNodeID() == ASTNodeID.IdentifierID)
{
if ((leftDef != null)
- && IdentifierNode.isXMLish(leftDef,
getWalker().getProject()))
+ && SemanticUtils.isXMLish(leftDef,
getWalker().getProject()))
{
if (node.getNodeID() == ASTNodeID.Op_AddAssignID)
{
@@ -398,233 +391,12 @@ public class BinaryOperatorEmitter extends JSSubEmitter
implements
}
}
-
- boolean leftIsNumber = (leftDef != null &&
(leftDef.getQualifiedName().equals(IASLanguageConstants.Number) ||
-
leftDef.getQualifiedName().equals(IASLanguageConstants._int) ||
-
leftDef.getQualifiedName().equals(IASLanguageConstants.uint)));
- IExpressionNode rNode = node.getRightOperandNode();
- IDefinition rightDef = rNode.resolve(getWalker().getProject());
- IDefinition rightTypeDef =
rNode.resolveType(getWalker().getProject());
- boolean rightIsNumber = (rightTypeDef != null &&
(rightTypeDef.getQualifiedName().equals(IASLanguageConstants.Number) ||
-
rightTypeDef.getQualifiedName().equals(IASLanguageConstants._int) ||
-
rightTypeDef.getQualifiedName().equals(IASLanguageConstants.uint)));
- if (leftIsNumber && !rightIsNumber && (rightTypeDef == null ||
rightTypeDef.getQualifiedName().equals(IASLanguageConstants.ANY_TYPE)))
- {
- if (rNode.getNodeID() == ASTNodeID.FunctionCallID)
- {
- IExpressionNode fnNameNode =
((FunctionCallNode)rNode).getNameNode();
- if (fnNameNode.getNodeID() ==
ASTNodeID.MemberAccessExpressionID)
- {
- MemberAccessExpressionNode mae =
(MemberAccessExpressionNode)fnNameNode;
- IExpressionNode rightNode =
mae.getRightOperandNode();
- rightIsNumber = rightNode.getNodeID() ==
ASTNodeID.IdentifierID &&
-
((IdentifierNode)rightNode).getName().equals("length") &&
- fjs.isXMLList(mae);
- }
- }
- else if (rNode.getNodeID() ==
ASTNodeID.ArrayIndexExpressionID)
- {
- DynamicAccessNode dyn =
(DynamicAccessNode)rNode;
- IDefinition lDef =
dyn.getLeftOperandNode().resolveType(getProject());
- IDefinition rDef =
dyn.getRightOperandNode().resolveType(getProject());
- // numeric indexing?
- if
(rDef.getQualifiedName().equals(IASLanguageConstants.Number))
- {
- IMetaTag[] metas =
lDef.getAllMetaTags();
- for (IMetaTag meta : metas)
- {
- if
(meta.getTagName().equals("ArrayElementType"))
- {
- IMetaTagAttribute[]
attrs = meta.getAllAttributes();
- for (IMetaTagAttribute
attr : attrs)
- {
- String t =
attr.getValue();
- if
(t.equals(IASLanguageConstants.Number))
- rightIsNumber =
true;
- }
- }
- }
- }
- }
- }
- String coercionStart = null;
- String coercionEnd = null;
- String coercedValue = null;
- if (isAssignment)
- {
- if
(getProject().getBuiltinType(BuiltinType.INT).equals(leftDef))
- {
- boolean needsCoercion = false;
- if (rNode instanceof
INumericLiteralNode)
- {
- INumericLiteralNode
numericLiteral = (INumericLiteralNode) rNode;
-
INumericLiteralNode.INumericValue numericValue =
numericLiteral.getNumericValue();
- coercedValue =
Integer.toString(numericValue.toInt32());
- }
- else
if(!getProject().getBuiltinType(BuiltinType.INT).equals(rightTypeDef))
- {
- needsCoercion = true;
- }
- if (needsCoercion)
- {
- coercionStart = "(";
- coercionEnd = ") >> 0";
- }
- }
- else if
(getProject().getBuiltinType(BuiltinType.UINT).equals(leftDef))
- {
- boolean needsCoercion = false;
- if (rNode instanceof
INumericLiteralNode)
- {
- INumericLiteralNode
numericLiteral = (INumericLiteralNode) rNode;
-
INumericLiteralNode.INumericValue numericValue =
numericLiteral.getNumericValue();
- coercedValue =
Long.toString(numericValue.toUint32());
- }
- else
if(!getProject().getBuiltinType(BuiltinType.UINT).equals(rightTypeDef))
- {
- needsCoercion = true;
- }
- if (needsCoercion)
- {
- coercionStart = "(";
- coercionEnd = ") >>> 0";
- }
- }
- else if (leftIsNumber && !rightIsNumber)
- {
- coercionStart = "Number(";
- }
- else if
(getProject().getBuiltinType(BuiltinType.BOOLEAN).equals(leftDef)
- &&
!getProject().getBuiltinType(BuiltinType.BOOLEAN).equals(rightTypeDef))
- {
- boolean needsCoercion = true;
- if
(getProject().getBuiltinType(BuiltinType.NULL).equals(rightTypeDef)
- || (rightDef != null &&
rightDef.getQualifiedName().equals(IASLanguageConstants.UNDEFINED)))
- {
- //null and undefined are
coerced to false
- coercedValue =
IASLanguageConstants.FALSE;
- needsCoercion = false;
- }
- else if (rNode instanceof
INumericLiteralNode)
- {
- INumericLiteralNode
numericLiteral = (INumericLiteralNode) rNode;
-
INumericLiteralNode.INumericValue numericValue =
numericLiteral.getNumericValue();
- //zero is coerced to false, and
everything else is true
- coercedValue =
numericValue.toNumber() == 0.0
- ?
IASLanguageConstants.FALSE
- :
IASLanguageConstants.TRUE;
- needsCoercion =
false;
- }
- if (needsCoercion)
- {
- coercionStart = "!!(";
- }
- }
- else if
(getProject().getBuiltinType(BuiltinType.STRING).equals(leftDef))
- {
- if (rNode.getNodeID() !=
ASTNodeID.LiteralStringID &&
- rNode.getNodeID() !=
ASTNodeID.LiteralNullID)
- {
- if (rightTypeDef == null ||
-
(!(rightTypeDef.getQualifiedName().equals(IASLanguageConstants.String) ||
-
(rightTypeDef.getQualifiedName().equals(IASLanguageConstants.ANY_TYPE)
-
&& rNode.getNodeID() == ASTNodeID.FunctionCallID &&
-
isToString(rNode)) ||
- // if not an
assignment we don't need to coerce numbers
- (!isAssignment
&& rightIsNumber) ||
-
rightTypeDef.getQualifiedName().equals(IASLanguageConstants.Null))))
- {
- JSRoyaleDocEmitter
docEmitter = (JSRoyaleDocEmitter)(getEmitter().getDocEmitter());
- if
(docEmitter.emitStringConversions)
- {
- coercionStart =
"org.apache.royale.utils.Language.string(";
- }
- }
- }
- }
- }
- super_emitBinaryOperator(node, coercionStart, coercionEnd,
coercedValue);
-
- /*
- IExpressionNode leftSide = node.getLeftOperandNode();
-
- IExpressionNode property = null;
- int leftSideChildCount = leftSide.getChildCount();
- if (leftSideChildCount > 0)
- {
- IASNode childNode = leftSide.getChild(leftSideChildCount - 1);
- if (childNode instanceof IExpressionNode)
- property = (IExpressionNode) childNode;
- else
- property = leftSide;
- }
- else
- property = leftSide;
-
- IDefinition def = null;
- if (property instanceof IIdentifierNode)
- def = ((IIdentifierNode) property).resolve(getWalker()
- .getProject());
-
- boolean isSuper = false;
- if (leftSide.getNodeID() == ASTNodeID.MemberAccessExpressionID)
- {
- IASNode cnode = leftSide.getChild(0);
- ASTNodeID cId = cnode.getNodeID();
-
- isSuper = cId == ASTNodeID.SuperID;
- }
-
- String op = node.getOperator().getOperatorText();
- boolean isAssignment = op.contains("=") && !op.contains("==") &&
- !(op.startsWith("<") ||
- op.startsWith(">")
||
-
op.startsWith("!"));
-
- if (def instanceof AccessorDefinition && isAssignment)
- {
- // this will make the set_foo call
- getWalker().walk(leftSide);
- }
- else if (isSuper)
- {
- emitSuperCall(node, "");
- }
- else
- {
- if (ASNodeUtils.hasParenOpen(node))
- write(ASEmitterTokens.PAREN_OPEN);
-
- getWalker().walk(leftSide);
-
- if (node.getNodeID() != ASTNodeID.Op_CommaID)
- write(ASEmitterTokens.SPACE);
-
- writeToken(node.getOperator().getOperatorText());
-
- getWalker().walk(node.getRightOperandNode());
-
- if (ASNodeUtils.hasParenClose(node))
- write(ASEmitterTokens.PAREN_CLOSE);
- }
- */
+
+ super_emitBinaryOperator(node, isAssignment);
}
}
-
- private boolean isToString(IASNode rNode)
- {
- IExpressionNode fnNameNode = ((FunctionCallNode)rNode).getNameNode();
- if (fnNameNode.getNodeID() == ASTNodeID.MemberAccessExpressionID)
- {
- MemberAccessExpressionNode mae =
(MemberAccessExpressionNode)fnNameNode;
- IExpressionNode rightNode = mae.getRightOperandNode();
- return rightNode.getNodeID() == ASTNodeID.IdentifierID &&
-
((IdentifierNode)rightNode).getName().equals("toString");
- }
- return false;
- }
- private void super_emitBinaryOperator(IBinaryOperatorNode node, String
coercionStart, String coercionEnd, String coercedValue)
+ private void super_emitBinaryOperator(IBinaryOperatorNode node, boolean
isAssignment)
{
if (ASNodeUtils.hasParenOpen(node))
write(ASEmitterTokens.PAREN_OPEN);
@@ -691,44 +463,26 @@ public class BinaryOperatorEmitter extends JSSubEmitter
implements
write(ASEmitterTokens.SPACE);
endMapping(node);
- if (coercionStart != null)
- {
- write(coercionStart);
- }
- if (coercedValue != null)
+ if (isAssignment)
{
- startMapping(node.getRightOperandNode());
- write(coercedValue);
- endMapping(node.getRightOperandNode());
+
getEmitter().emitAssignmentCoercion(node.getRightOperandNode(),
node.getLeftOperandNode().resolveType(getProject()));
}
else
{
getWalker().walk(node.getRightOperandNode());
- }
- if (node.getNodeID() == ASTNodeID.Op_InID &&
-
((JSRoyaleEmitter)getEmitter()).isXML(node.getRightOperandNode()))
- {
- write(".elementNames()");
- }
- else if (node.getNodeID() == ASTNodeID.Op_InID &&
-
((JSRoyaleEmitter)getEmitter()).isProxy(node.getRightOperandNode()))
- {
- write(".propertyNames()");
+ if (node.getNodeID() == ASTNodeID.Op_InID &&
+
((JSRoyaleEmitter)getEmitter()).isXML(node.getRightOperandNode()))
+ {
+ write(".elementNames()");
+ }
+ else if (node.getNodeID() == ASTNodeID.Op_InID
&&
+
((JSRoyaleEmitter)getEmitter()).isProxy(node.getRightOperandNode()))
+ {
+ write(".propertyNames()");
+ }
}
}
- if (coercionStart != null)
- {
- if (coercionEnd != null)
- {
- write(coercionEnd);
- }
- else
- {
- write(")");
- }
- }
-
if (ASNodeUtils.hasParenOpen(node))
write(ASEmitterTokens.PAREN_CLOSE);
}
diff --git
a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/VarDeclarationEmitter.java
b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/VarDeclarationEmitter.java
index 64718b1..b2a812e 100644
---
a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/VarDeclarationEmitter.java
+++
b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/jx/VarDeclarationEmitter.java
@@ -29,8 +29,10 @@ import
org.apache.royale.compiler.definitions.metadata.IMetaTag;
import org.apache.royale.compiler.definitions.metadata.IMetaTagAttribute;
import org.apache.royale.compiler.internal.codegen.as.ASEmitterTokens;
import org.apache.royale.compiler.internal.codegen.js.JSSubEmitter;
+import
org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleDocEmitter;
import org.apache.royale.compiler.internal.codegen.js.royale.JSRoyaleEmitter;
import org.apache.royale.compiler.internal.projects.RoyaleJSProject;
+import org.apache.royale.compiler.internal.semantics.SemanticUtils;
import org.apache.royale.compiler.internal.tree.as.ChainedVariableNode;
import org.apache.royale.compiler.internal.tree.as.DynamicAccessNode;
import org.apache.royale.compiler.internal.tree.as.FunctionCallNode;
@@ -97,6 +99,15 @@ public class VarDeclarationEmitter extends JSSubEmitter
implements
{
avdef = avnode.resolve(getProject());
avtypedef = avnode.resolveType(getProject());
+ if
(getProject().getBuiltinType(BuiltinType.ANY_TYPE).equals(avtypedef))
+ {
+ IDefinition resolvedXMLDef = SemanticUtils.resolveXML(avnode,
getProject());
+ if (resolvedXMLDef != null)
+ {
+ avdef = resolvedXMLDef;
+ avtypedef = SemanticUtils.resolveTypeXML(avnode,
getProject());
+ }
+ }
String opcode = avnode.getNodeID().getParaphrase();
if (opcode != "AnonymousFunction")
{
@@ -255,11 +266,25 @@ public class VarDeclarationEmitter extends JSSubEmitter
implements
}
coercionStart = "!!(";
}
- else if
(getProject().getBuiltinType(BuiltinType.STRING).equals(variableDef) &&
-
!getProject().getBuiltinType(BuiltinType.STRING).equals(avtypedef) &&
-
!getProject().getBuiltinType(BuiltinType.NULL).equals(avtypedef))
+ else if
(getProject().getBuiltinType(BuiltinType.STRING).equals(variableDef)
+ &&
!getProject().getBuiltinType(BuiltinType.STRING).equals(avtypedef)
+ &&
!getProject().getBuiltinType(BuiltinType.NULL).equals(avtypedef)
+ &&
!(getProject().getBuiltinType(BuiltinType.ANY_TYPE).equals(avtypedef)
+ && SemanticUtils.isToStringFunctionCall(avnode,
getProject())))
{
- coercionStart = "org.apache.royale.utils.Language.string(";
+ if(avdef != null &&
avdef.getQualifiedName().equals(IASLanguageConstants.UNDEFINED))
+ {
+ //undefined is coerced to null
+ startMapping(avnode);
+ write(IASLanguageConstants.NULL);
+ endMapping(avnode);
+ return;
+ }
+ JSRoyaleDocEmitter docEmitter = (JSRoyaleDocEmitter)
(getEmitter().getDocEmitter());
+ if (docEmitter.emitStringConversions)
+ {
+ coercionStart = "org.apache.royale.utils.Language.string(";
+ }
}
if (coercionStart != null)
{
diff --git
a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/royale/JSRoyaleEmitter.java
b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/royale/JSRoyaleEmitter.java
index 22ecad2..4c987f1 100644
---
a/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/royale/JSRoyaleEmitter.java
+++
b/compiler-jx/src/main/java/org/apache/royale/compiler/internal/codegen/js/royale/JSRoyaleEmitter.java
@@ -76,6 +76,7 @@ import
org.apache.royale.compiler.internal.embedding.EmbedMIMEType;
import org.apache.royale.compiler.internal.projects.CompilerProject;
import org.apache.royale.compiler.internal.projects.RoyaleJSProject;
import org.apache.royale.compiler.internal.projects.RoyaleProject;
+import org.apache.royale.compiler.internal.semantics.SemanticUtils;
import org.apache.royale.compiler.internal.tree.as.*;
import org.apache.royale.compiler.problems.EmbedUnableToReadSourceProblem;
import org.apache.royale.compiler.projects.ICompilerProject;
@@ -1194,7 +1195,7 @@ public class JSRoyaleEmitter extends JSGoogEmitter
implements IJSRoyaleEmitter
IDefinition rightDef =
rightNode.resolveType(getWalker().getProject());
if (rightDef != null)
{
- if (IdentifierNode.isXMLish(rightDef,
getWalker().getProject()))
+ if (SemanticUtils.isXMLish(rightDef,
getWalker().getProject()))
{
return isLeftNodeXMLish(leftNode);
}
@@ -1214,7 +1215,7 @@ public class JSRoyaleEmitter extends JSGoogEmitter
implements IJSRoyaleEmitter
{
IDefinition leftDef =
leftNode.resolveType(getWalker().getProject());
if (leftDef != null)
- return IdentifierNode.isXMLish(leftDef,
getWalker().getProject());
+ return SemanticUtils.isXMLish(leftDef,
getWalker().getProject());
}
else if (leftID == ASTNodeID.MemberAccessExpressionID || leftID
== ASTNodeID.Op_DescendantsID)
{
@@ -1226,7 +1227,7 @@ public class JSRoyaleEmitter extends JSGoogEmitter
implements IJSRoyaleEmitter
IDefinition rightDef =
rightNode.resolveType(getWalker().getProject());
if (rightDef != null)
{
- return
IdentifierNode.isXMLish(rightDef, getWalker().getProject());
+ return SemanticUtils.isXMLish(rightDef,
getWalker().getProject());
}
}
leftNode = maen.getLeftOperandNode();
@@ -1251,7 +1252,7 @@ public class JSRoyaleEmitter extends JSGoogEmitter
implements IJSRoyaleEmitter
leftNode = (IExpressionNode)(leftNode.getChild(0));
IDefinition leftDef =
leftNode.resolveType(getWalker().getProject());
if (leftDef != null)
- return IdentifierNode.isXMLish(leftDef,
getWalker().getProject());
+ return SemanticUtils.isXMLish(leftDef,
getWalker().getProject());
}
else if (leftID == ASTNodeID.E4XFilterID)
@@ -1352,7 +1353,7 @@ public class JSRoyaleEmitter extends JSGoogEmitter
implements IJSRoyaleEmitter
{
return
isXML(((MemberAccessExpressionNode)obj).getLeftOperandNode());
}
- return IdentifierNode.isXMLish(leftDef,
getWalker().getProject());
+ return SemanticUtils.isXMLish(leftDef,
getWalker().getProject());
}
public MemberAccessExpressionNode
getLastMAEInChain(MemberAccessExpressionNode node)
diff --git
a/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleExpressions.java
b/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleExpressions.java
index 05f05ac..5471fb4 100644
---
a/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleExpressions.java
+++
b/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleExpressions.java
@@ -430,6 +430,78 @@ public class TestRoyaleExpressions extends
TestGoogExpressions
}
@Test
+ public void testVisitBinaryOperatorNode_AssignmentStringVarToString()
+ {
+ IBinaryOperatorNode node = getBinaryNode("var var1:String;var
var2:String;var1 = var2");
+ asBlockWalker.visitBinaryOperator(node);
+ assertOut("var1 = var2");
+ }
+
+ @Test
+ public void testVisitBinaryOperatorNode_AssignmentAnyTypeVarToString()
+ {
+ IBinaryOperatorNode node = getBinaryNode("var var1:String;var
var2:*;var1 = var2");
+ asBlockWalker.visitBinaryOperator(node);
+ assertOut("var1 = org.apache.royale.utils.Language.string(var2)");
+ }
+
+ @Test
+ public void
testVisitBinaryOperatorNode_AssignmentAnyTypeVarToStringSuppressed()
+ {
+ IBinaryOperatorNode node = (IBinaryOperatorNode) getNode(
+ "public class B {public var b:String; public var c:Object;
/**\n * @royalenoimplicitstringconversion\n */\npublic function d() { b = c;
}}",
+ IBinaryOperatorNode.class, WRAP_LEVEL_PACKAGE);
+ JSRoyaleDocEmitter docEmitter =
(JSRoyaleDocEmitter)(asBlockWalker.getEmitter().getDocEmitter());
+ IFunctionNode methodNode =
(IFunctionNode)(node.getAncestorOfType(IFunctionNode.class));
+
+ // this adds '/**\n * @royalenoimplicitstringconversion\n * @export\n
*/' to the output but parses
+ // the asdoc so the emitter will suppress the output
+ docEmitter.emitMethodDoc(methodNode, asBlockWalker.getProject());
+ asBlockWalker.visitBinaryOperator(node);
+ assertOut("/**\n * @royalenoimplicitstringconversion\n * @export\n
*/\nthis.b = this.c");
+ }
+
+ @Test
+ public void testVisitBinaryOperatorNode_AssignmentXMLChildToString()
+ {
+ IBinaryOperatorNode node = getBinaryNode("var var1:String;var
var2:XML;var1 = var2.child");
+ asBlockWalker.visitBinaryOperator(node);
+ assertOut("var1 =
org.apache.royale.utils.Language.string(var2.child('child'))");
+ }
+
+ @Test
+ public void testVisitBinaryOperatorNode_AssignmentStringLiteralToString()
+ {
+ IBinaryOperatorNode node = getBinaryNode("var var1:String;var1 =
\"hi\"");
+ asBlockWalker.visitBinaryOperator(node);
+ assertOut("var1 = \"hi\"");
+ }
+
+ @Test
+ public void testVisitBinaryOperatorNode_AssignmentNullToString()
+ {
+ IBinaryOperatorNode node = getBinaryNode("var var1:String;var1 =
null");
+ asBlockWalker.visitBinaryOperator(node);
+ assertOut("var1 = null");
+ }
+
+ @Test
+ public void testVisitBinaryOperatorNode_AssignmentUndefinedToString()
+ {
+ IBinaryOperatorNode node = getBinaryNode("var var1:String;var1 =
undefined");
+ asBlockWalker.visitBinaryOperator(node);
+ assertOut("var1 = null");
+ }
+
+ @Test
+ public void
testVisitBinaryOperatorNode_AssignmentToStringFunctionCallToString()
+ {
+ IBinaryOperatorNode node = getBinaryNode("var var1:String;var
var2:Object;var1 = var2.toString()");
+ asBlockWalker.visitBinaryOperator(node);
+ assertOut("var1 = var2.toString()");
+ }
+
+ @Test
public void testVisitBinaryOperatorNode_setterAssignment()
{
IBinaryOperatorNode node = (IBinaryOperatorNode) getNode(
@@ -898,32 +970,6 @@ public class TestRoyaleExpressions extends
TestGoogExpressions
}
@Test
- public void testVisitBinaryOperatorNode_StringVarAssignmentFromObject()
- {
- IBinaryOperatorNode node = (IBinaryOperatorNode) getNode(
- "public class B {public var b:String; public var c:Object;
public function d() { b = c; }}",
- IBinaryOperatorNode.class, WRAP_LEVEL_PACKAGE);
- asBlockWalker.visitBinaryOperator(node);
- assertOut("this.b = org.apache.royale.utils.Language.string(this.c)");
- }
-
- @Test
- public void
testVisitBinaryOperatorNode_StringVarAssignmentFromObjectSupressed()
- {
- IBinaryOperatorNode node = (IBinaryOperatorNode) getNode(
- "public class B {public var b:String; public var c:Object;
/**\n * @royalenoimplicitstringconversion\n */\npublic function d() { b = c;
}}",
- IBinaryOperatorNode.class, WRAP_LEVEL_PACKAGE);
- JSRoyaleDocEmitter docEmitter =
(JSRoyaleDocEmitter)(asBlockWalker.getEmitter().getDocEmitter());
- IFunctionNode methodNode =
(IFunctionNode)(node.getAncestorOfType(IFunctionNode.class));
-
- // this adds '/**\n * @royalenoimplicitstringconversion\n * @export\n
*/' to the output but parses
- // the asdoc so the emitter will suppress the output
- docEmitter.emitMethodDoc(methodNode, asBlockWalker.getProject());
- asBlockWalker.visitBinaryOperator(node);
- assertOut("/**\n * @royalenoimplicitstringconversion\n * @export\n
*/\nthis.b = this.c");
- }
-
- @Test
public void testVisitBinaryOperatorNode_StringVarCompareWithObject()
{
IBinaryOperatorNode node = (IBinaryOperatorNode) getNode(
@@ -954,16 +1000,6 @@ public class TestRoyaleExpressions extends
TestGoogExpressions
}
@Test
- public void testVisitBinaryOperatorNode_StringAssignFromStarToString()
- {
- IBinaryOperatorNode node = (IBinaryOperatorNode) getNode(
- "public class B {public var b:String; public var c:*; public
function d() { b = c.toString(); }}",
- IBinaryOperatorNode.class, WRAP_LEVEL_PACKAGE);
- asBlockWalker.visitBinaryOperator(node);
- assertOut("this.b = this.c.toString()");
- }
-
- @Test
public void testVisitBinaryOperatorNode_NumberPlusString()
{
IBinaryOperatorNode node = (IBinaryOperatorNode) getNode(
@@ -1716,6 +1752,62 @@ public class TestRoyaleExpressions extends
TestGoogExpressions
}
@Test
+ public void testVisitReturnStringWithLiteral()
+ {
+ IReturnNode node = (IReturnNode) getNode("function():String { return
\"hi\"; }", IReturnNode.class);
+ asBlockWalker.visitReturn(node);
+ assertOut("return \"hi\"");
+ }
+
+ @Test
+ public void testVisitReturnStringWithNull()
+ {
+ IReturnNode node = (IReturnNode) getNode("function():String { return
null; }", IReturnNode.class);
+ asBlockWalker.visitReturn(node);
+ assertOut("return null");
+ }
+
+ @Test
+ public void testVisitReturnStringWithUndefined()
+ {
+ IReturnNode node = (IReturnNode) getNode("function():String { return
undefined; }", IReturnNode.class);
+ asBlockWalker.visitReturn(node);
+ assertOut("return null");
+ }
+
+ @Test
+ public void testVisitReturnStringWithStringVar()
+ {
+ IReturnNode node = (IReturnNode) getNode("function():String { var
a:String; return a; }", IReturnNode.class);
+ asBlockWalker.visitReturn(node);
+ assertOut("return a");
+ }
+
+ @Test
+ public void testVisitReturnStringWithAnyTypeVar()
+ {
+ IReturnNode node = (IReturnNode) getNode("function():String { var a:*;
return a; }", IReturnNode.class);
+ asBlockWalker.visitReturn(node);
+ assertOut("return org.apache.royale.utils.Language.string(a)");
+ }
+
+ @Test
+ public void testVisitReturnStringWithToStringFunctionCall()
+ {
+ IReturnNode node = (IReturnNode) getNode("function():String { var
a:Object; return a.toString(); }", IReturnNode.class);
+ asBlockWalker.visitReturn(node);
+ assertOut("return a.toString()");
+ }
+
+ @Test
+ public void testVisitReturnStringWithXMLChild()
+ {
+ IReturnNode node = (IReturnNode) getNode("function():String { var
a:XML; return a.child; }", IReturnNode.class);
+ asBlockWalker.visitReturn(node);
+ assertOut("return
org.apache.royale.utils.Language.string(a.child('child'))");
+ }
+
+ @Test
public void testVisitFunctionCallWithIntParameterNegative()
{
IFunctionCallNode node = (IFunctionCallNode) getNode("function
a(foo:int):void {}; a(-123)", IFunctionCallNode.class);
@@ -1803,6 +1895,62 @@ public class TestRoyaleExpressions extends
TestGoogExpressions
assertOut("a(false)");
}
+ @Test
+ public void testVisitFunctionCallWithStringParameterLiteral()
+ {
+ IFunctionCallNode node = (IFunctionCallNode) getNode("function
a(foo:String):void {}; a(\"hi\");", IFunctionCallNode.class);
+ asBlockWalker.visitFunctionCall(node);
+ assertOut("a(\"hi\")");
+ }
+
+ @Test
+ public void testVisitFunctionCallWithStringParameterNull()
+ {
+ IFunctionCallNode node = (IFunctionCallNode) getNode("function
a(foo:String):void {}; a(null);", IFunctionCallNode.class);
+ asBlockWalker.visitFunctionCall(node);
+ assertOut("a(null)");
+ }
+
+ @Test
+ public void testVisitFunctionCallWithStringParameterUndefined()
+ {
+ IFunctionCallNode node = (IFunctionCallNode) getNode("function
a(foo:String):void {}; a(undefined);", IFunctionCallNode.class);
+ asBlockWalker.visitFunctionCall(node);
+ assertOut("a(null)");
+ }
+
+ @Test
+ public void testVisitFunctionCallWithStringParameterStringVar()
+ {
+ IFunctionCallNode node = (IFunctionCallNode) getNode("function
a(foo:String):void {}; var b:String; a(b);", IFunctionCallNode.class);
+ asBlockWalker.visitFunctionCall(node);
+ assertOut("a(b)");
+ }
+
+ @Test
+ public void testVisitFunctionCallWithStringParameterAnyTypeVar()
+ {
+ IFunctionCallNode node = (IFunctionCallNode) getNode("function
a(foo:String):void {}; var b:*; a(b);", IFunctionCallNode.class);
+ asBlockWalker.visitFunctionCall(node);
+ assertOut("a(org.apache.royale.utils.Language.string(b))");
+ }
+
+ @Test
+ public void testVisitFunctionCallWithStringParameterToStringFunctionCall()
+ {
+ IFunctionCallNode node = (IFunctionCallNode) getNode("function
a(foo:String):void {}; var b:Object; a(b.toString());",
IFunctionCallNode.class);
+ asBlockWalker.visitFunctionCall(node);
+ assertOut("a(b.toString())");
+ }
+
+ @Test
+ public void testVisitFunctionCallWithStringParameterXMLVarChild()
+ {
+ IFunctionCallNode node = (IFunctionCallNode) getNode("function
a(foo:String):void {}; var b:XML; a(b.child);", IFunctionCallNode.class);
+ asBlockWalker.visitFunctionCall(node);
+
assertOut("a(org.apache.royale.utils.Language.string(b.child('child')))");
+ }
+
protected IBackend createBackend()
{
return new RoyaleBackend();
diff --git
a/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleStatements.java
b/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleStatements.java
index 51de9a0..e316fe4 100644
---
a/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleStatements.java
+++
b/compiler-jx/src/test/java/org/apache/royale/compiler/internal/codegen/js/royale/TestRoyaleStatements.java
@@ -177,6 +177,60 @@ public class TestRoyaleStatements extends
TestGoogStatements
assertOut("var /** @type {number} */ a = 4294967173");
}
+ @Test
+ public void testVarDeclaration_withTypeStringAndAssignedStringLiteral()
+ {
+ IVariableNode node = (IVariableNode) getNode("var a:String = \"hi\";",
+ IVariableNode.class);
+ asBlockWalker.visitVariable(node);
+ assertOut("var /** @type {string} */ a = \"hi\"");
+ }
+
+ @Test
+ public void testVarDeclaration_withTypeStringAndAssignedNull()
+ {
+ IVariableNode node = (IVariableNode) getNode("var a:String = null;",
+ IVariableNode.class);
+ asBlockWalker.visitVariable(node);
+ assertOut("var /** @type {string} */ a = null");
+ }
+
+ @Test
+ public void testVarDeclaration_withTypeStringAndAssignedUndefined()
+ {
+ IVariableNode node = (IVariableNode) getNode("var a:String =
undefined;",
+ IVariableNode.class);
+ asBlockWalker.visitVariable(node);
+ assertOut("var /** @type {string} */ a = null");
+ }
+
+ @Test
+ public void testVarDeclaration_withTypeStringAndAssignedStringVar()
+ {
+ IVariableNode node = (IVariableNode) getNode("function
royaleTest_a():Object { var a:String = b }var b:String;",
+ IVariableNode.class, WRAP_LEVEL_CLASS);
+ asBlockWalker.visitVariable(node);
+ assertOut("var /** @type {string} */ a = this.b");
+ }
+
+ @Test
+ public void testVarDeclaration_withTypeStringAndAssignedAnyTypeVar()
+ {
+ IVariableNode node = (IVariableNode) getNode("function
royaleTest_a():Object { var a:String = b }var b:*;",
+ IVariableNode.class, WRAP_LEVEL_CLASS);
+ asBlockWalker.visitVariable(node);
+ assertOut("var /** @type {string} */ a =
org.apache.royale.utils.Language.string(this.b)");
+ }
+
+ @Test
+ public void
testVarDeclaration_withTypeStringAndAssignedToStringFunctionCall()
+ {
+ IVariableNode node = (IVariableNode) getNode("function
royaleTest_a():Object { var a:String = b.toString(); }var b:Object;",
+ IVariableNode.class, WRAP_LEVEL_CLASS);
+ asBlockWalker.visitVariable(node);
+ assertOut("var /** @type {string} */ a = this.b.toString()");
+ }
+
//----------------------------------
// const declaration
//----------------------------------
diff --git a/compiler-jx/src/test/junittestcases5491906995083840238.properties
b/compiler-jx/src/test/junittestcases5491906995083840238.properties
new file mode 100644
index 0000000..01d88f7
--- /dev/null
+++ b/compiler-jx/src/test/junittestcases5491906995083840238.properties
@@ -0,0 +1,55 @@
+org.apache.royale.compiler.internal.codegen.as.TestAccessorMembers,C:\Users\josht\Development\apache\royale-compiler\compiler-jx\target\junit-results,TEST-org.apache.royale.compiler.internal.codegen.as.TestAccessorMembers
+org.apache.royale.compiler.internal.codegen.as.TestClass,C:\Users\josht\Development\apache\royale-compiler\compiler-jx\target\junit-results,TEST-org.apache.royale.compiler.internal.codegen.as.TestClass
+org.apache.royale.compiler.internal.codegen.as.TestComments,C:\Users\josht\Development\apache\royale-compiler\compiler-jx\target\junit-results,TEST-org.apache.royale.compiler.internal.codegen.as.TestComments
+org.apache.royale.compiler.internal.codegen.as.TestExpressions,C:\Users\josht\Development\apache\royale-compiler\compiler-jx\target\junit-results,TEST-org.apache.royale.compiler.internal.codegen.as.TestExpressions
+org.apache.royale.compiler.internal.codegen.as.TestFieldMembers,C:\Users\josht\Development\apache\royale-compiler\compiler-jx\target\junit-results,TEST-org.apache.royale.compiler.internal.codegen.as.TestFieldMembers
+org.apache.royale.compiler.internal.codegen.as.TestGlobalClasses,C:\Users\josht\Development\apache\royale-compiler\compiler-jx\target\junit-results,TEST-org.apache.royale.compiler.internal.codegen.as.TestGlobalClasses
+org.apache.royale.compiler.internal.codegen.as.TestGlobalConstants,C:\Users\josht\Development\apache\royale-compiler\compiler-jx\target\junit-results,TEST-org.apache.royale.compiler.internal.codegen.as.TestGlobalConstants
+org.apache.royale.compiler.internal.codegen.as.TestGlobalFunctions,C:\Users\josht\Development\apache\royale-compiler\compiler-jx\target\junit-results,TEST-org.apache.royale.compiler.internal.codegen.as.TestGlobalFunctions
+org.apache.royale.compiler.internal.codegen.as.TestInterface,C:\Users\josht\Development\apache\royale-compiler\compiler-jx\target\junit-results,TEST-org.apache.royale.compiler.internal.codegen.as.TestInterface
+org.apache.royale.compiler.internal.codegen.as.TestMethodMembers,C:\Users\josht\Development\apache\royale-compiler\compiler-jx\target\junit-results,TEST-org.apache.royale.compiler.internal.codegen.as.TestMethodMembers
+org.apache.royale.compiler.internal.codegen.as.TestPackage,C:\Users\josht\Development\apache\royale-compiler\compiler-jx\target\junit-results,TEST-org.apache.royale.compiler.internal.codegen.as.TestPackage
+org.apache.royale.compiler.internal.codegen.as.TestParenthesis,C:\Users\josht\Development\apache\royale-compiler\compiler-jx\target\junit-results,TEST-org.apache.royale.compiler.internal.codegen.as.TestParenthesis
+org.apache.royale.compiler.internal.codegen.as.TestStatements,C:\Users\josht\Development\apache\royale-compiler\compiler-jx\target\junit-results,TEST-org.apache.royale.compiler.internal.codegen.as.TestStatements
+org.apache.royale.compiler.internal.codegen.js.amd.TestAMDClassA,C:\Users\josht\Development\apache\royale-compiler\compiler-jx\target\junit-results,TEST-org.apache.royale.compiler.internal.codegen.js.amd.TestAMDClassA
+org.apache.royale.compiler.internal.codegen.js.amd.TestAMDClassB,C:\Users\josht\Development\apache\royale-compiler\compiler-jx\target\junit-results,TEST-org.apache.royale.compiler.internal.codegen.js.amd.TestAMDClassB
+org.apache.royale.compiler.internal.codegen.js.amd.TestAMDEmitter,C:\Users\josht\Development\apache\royale-compiler\compiler-jx\target\junit-results,TEST-org.apache.royale.compiler.internal.codegen.js.amd.TestAMDEmitter
+org.apache.royale.compiler.internal.codegen.js.amd.TestAMDInterfaceI,C:\Users\josht\Development\apache\royale-compiler\compiler-jx\target\junit-results,TEST-org.apache.royale.compiler.internal.codegen.js.amd.TestAMDInterfaceI
+org.apache.royale.compiler.internal.codegen.js.amd.TestAMDInterfaceIOther,C:\Users\josht\Development\apache\royale-compiler\compiler-jx\target\junit-results,TEST-org.apache.royale.compiler.internal.codegen.js.amd.TestAMDInterfaceIOther
+org.apache.royale.compiler.internal.codegen.js.amd.TestAMDInterfaceISub,C:\Users\josht\Development\apache\royale-compiler\compiler-jx\target\junit-results,TEST-org.apache.royale.compiler.internal.codegen.js.amd.TestAMDInterfaceISub
+org.apache.royale.compiler.internal.codegen.js.amd.TestAMDPackage,C:\Users\josht\Development\apache\royale-compiler\compiler-jx\target\junit-results,TEST-org.apache.royale.compiler.internal.codegen.js.amd.TestAMDPackage
+org.apache.royale.compiler.internal.codegen.js.goog.TestGoogAccessorMembers,C:\Users\josht\Development\apache\royale-compiler\compiler-jx\target\junit-results,TEST-org.apache.royale.compiler.internal.codegen.js.goog.TestGoogAccessorMembers
+org.apache.royale.compiler.internal.codegen.js.goog.TestGoogClass,C:\Users\josht\Development\apache\royale-compiler\compiler-jx\target\junit-results,TEST-org.apache.royale.compiler.internal.codegen.js.goog.TestGoogClass
+org.apache.royale.compiler.internal.codegen.js.goog.TestGoogEmitter,C:\Users\josht\Development\apache\royale-compiler\compiler-jx\target\junit-results,TEST-org.apache.royale.compiler.internal.codegen.js.goog.TestGoogEmitter
+org.apache.royale.compiler.internal.codegen.js.goog.TestGoogExpressions,C:\Users\josht\Development\apache\royale-compiler\compiler-jx\target\junit-results,TEST-org.apache.royale.compiler.internal.codegen.js.goog.TestGoogExpressions
+org.apache.royale.compiler.internal.codegen.js.goog.TestGoogFieldMembers,C:\Users\josht\Development\apache\royale-compiler\compiler-jx\target\junit-results,TEST-org.apache.royale.compiler.internal.codegen.js.goog.TestGoogFieldMembers
+org.apache.royale.compiler.internal.codegen.js.goog.TestGoogFile,C:\Users\josht\Development\apache\royale-compiler\compiler-jx\target\junit-results,TEST-org.apache.royale.compiler.internal.codegen.js.goog.TestGoogFile
+org.apache.royale.compiler.internal.codegen.js.goog.TestGoogGlobalClasses,C:\Users\josht\Development\apache\royale-compiler\compiler-jx\target\junit-results,TEST-org.apache.royale.compiler.internal.codegen.js.goog.TestGoogGlobalClasses
+org.apache.royale.compiler.internal.codegen.js.goog.TestGoogGlobalConstants,C:\Users\josht\Development\apache\royale-compiler\compiler-jx\target\junit-results,TEST-org.apache.royale.compiler.internal.codegen.js.goog.TestGoogGlobalConstants
+org.apache.royale.compiler.internal.codegen.js.goog.TestGoogGlobalFunctions,C:\Users\josht\Development\apache\royale-compiler\compiler-jx\target\junit-results,TEST-org.apache.royale.compiler.internal.codegen.js.goog.TestGoogGlobalFunctions
+org.apache.royale.compiler.internal.codegen.js.goog.TestGoogInterface,C:\Users\josht\Development\apache\royale-compiler\compiler-jx\target\junit-results,TEST-org.apache.royale.compiler.internal.codegen.js.goog.TestGoogInterface
+org.apache.royale.compiler.internal.codegen.js.goog.TestGoogMethodMembers,C:\Users\josht\Development\apache\royale-compiler\compiler-jx\target\junit-results,TEST-org.apache.royale.compiler.internal.codegen.js.goog.TestGoogMethodMembers
+org.apache.royale.compiler.internal.codegen.js.goog.TestGoogPackage,C:\Users\josht\Development\apache\royale-compiler\compiler-jx\target\junit-results,TEST-org.apache.royale.compiler.internal.codegen.js.goog.TestGoogPackage
+org.apache.royale.compiler.internal.codegen.js.goog.TestGoogProject,C:\Users\josht\Development\apache\royale-compiler\compiler-jx\target\junit-results,TEST-org.apache.royale.compiler.internal.codegen.js.goog.TestGoogProject
+org.apache.royale.compiler.internal.codegen.js.goog.TestGoogStatements,C:\Users\josht\Development\apache\royale-compiler\compiler-jx\target\junit-results,TEST-org.apache.royale.compiler.internal.codegen.js.goog.TestGoogStatements
+org.apache.royale.compiler.internal.codegen.js.royale.TestDefaultInitializers,C:\Users\josht\Development\apache\royale-compiler\compiler-jx\target\junit-results,TEST-org.apache.royale.compiler.internal.codegen.js.royale.TestDefaultInitializers
+org.apache.royale.compiler.internal.codegen.js.royale.TestDynamicAccessUnknownMembers,C:\Users\josht\Development\apache\royale-compiler\compiler-jx\target\junit-results,TEST-org.apache.royale.compiler.internal.codegen.js.royale.TestDynamicAccessUnknownMembers
+org.apache.royale.compiler.internal.codegen.js.royale.TestRoyaleAccessorMembers,C:\Users\josht\Development\apache\royale-compiler\compiler-jx\target\junit-results,TEST-org.apache.royale.compiler.internal.codegen.js.royale.TestRoyaleAccessorMembers
+org.apache.royale.compiler.internal.codegen.js.royale.TestRoyaleAccessors,C:\Users\josht\Development\apache\royale-compiler\compiler-jx\target\junit-results,TEST-org.apache.royale.compiler.internal.codegen.js.royale.TestRoyaleAccessors
+org.apache.royale.compiler.internal.codegen.js.royale.TestRoyaleEmitter,C:\Users\josht\Development\apache\royale-compiler\compiler-jx\target\junit-results,TEST-org.apache.royale.compiler.internal.codegen.js.royale.TestRoyaleEmitter
+org.apache.royale.compiler.internal.codegen.js.royale.TestRoyaleExpressions,C:\Users\josht\Development\apache\royale-compiler\compiler-jx\target\junit-results,TEST-org.apache.royale.compiler.internal.codegen.js.royale.TestRoyaleExpressions
+org.apache.royale.compiler.internal.codegen.js.royale.TestRoyaleFieldMembers,C:\Users\josht\Development\apache\royale-compiler\compiler-jx\target\junit-results,TEST-org.apache.royale.compiler.internal.codegen.js.royale.TestRoyaleFieldMembers
+org.apache.royale.compiler.internal.codegen.js.royale.TestRoyaleGlobalClasses,C:\Users\josht\Development\apache\royale-compiler\compiler-jx\target\junit-results,TEST-org.apache.royale.compiler.internal.codegen.js.royale.TestRoyaleGlobalClasses
+org.apache.royale.compiler.internal.codegen.js.royale.TestRoyaleGlobalConstants,C:\Users\josht\Development\apache\royale-compiler\compiler-jx\target\junit-results,TEST-org.apache.royale.compiler.internal.codegen.js.royale.TestRoyaleGlobalConstants
+org.apache.royale.compiler.internal.codegen.js.royale.TestRoyaleGlobalFunctions,C:\Users\josht\Development\apache\royale-compiler\compiler-jx\target\junit-results,TEST-org.apache.royale.compiler.internal.codegen.js.royale.TestRoyaleGlobalFunctions
+org.apache.royale.compiler.internal.codegen.js.royale.TestRoyaleInterface,C:\Users\josht\Development\apache\royale-compiler\compiler-jx\target\junit-results,TEST-org.apache.royale.compiler.internal.codegen.js.royale.TestRoyaleInterface
+org.apache.royale.compiler.internal.codegen.js.royale.TestRoyaleJSX,C:\Users\josht\Development\apache\royale-compiler\compiler-jx\target\junit-results,TEST-org.apache.royale.compiler.internal.codegen.js.royale.TestRoyaleJSX
+org.apache.royale.compiler.internal.codegen.js.royale.TestRoyaleMethodMembers,C:\Users\josht\Development\apache\royale-compiler\compiler-jx\target\junit-results,TEST-org.apache.royale.compiler.internal.codegen.js.royale.TestRoyaleMethodMembers
+org.apache.royale.compiler.internal.codegen.js.royale.TestRoyalePackage,C:\Users\josht\Development\apache\royale-compiler\compiler-jx\target\junit-results,TEST-org.apache.royale.compiler.internal.codegen.js.royale.TestRoyalePackage
+org.apache.royale.compiler.internal.codegen.js.royale.TestRoyaleProject,C:\Users\josht\Development\apache\royale-compiler\compiler-jx\target\junit-results,TEST-org.apache.royale.compiler.internal.codegen.js.royale.TestRoyaleProject
+org.apache.royale.compiler.internal.codegen.js.royale.TestRoyaleStatements,C:\Users\josht\Development\apache\royale-compiler\compiler-jx\target\junit-results,TEST-org.apache.royale.compiler.internal.codegen.js.royale.TestRoyaleStatements
+org.apache.royale.compiler.internal.codegen.js.sourcemaps.TestSourceMapExpressions,C:\Users\josht\Development\apache\royale-compiler\compiler-jx\target\junit-results,TEST-org.apache.royale.compiler.internal.codegen.js.sourcemaps.TestSourceMapExpressions
+org.apache.royale.compiler.internal.codegen.js.sourcemaps.TestSourceMapFieldMembers,C:\Users\josht\Development\apache\royale-compiler\compiler-jx\target\junit-results,TEST-org.apache.royale.compiler.internal.codegen.js.sourcemaps.TestSourceMapFieldMembers
+org.apache.royale.compiler.internal.codegen.js.sourcemaps.TestSourceMapGlobalClasses,C:\Users\josht\Development\apache\royale-compiler\compiler-jx\target\junit-results,TEST-org.apache.royale.compiler.internal.codegen.js.sourcemaps.TestSourceMapGlobalClasses
+org.apache.royale.compiler.internal.codegen.js.sourcemaps.TestSourceMapStatements,C:\Users\josht\Development\apache\royale-compiler\compiler-jx\target\junit-results,TEST-org.apache.royale.compiler.internal.codegen.js.sourcemaps.TestSourceMapStatements
+org.apache.royale.compiler.internal.test.TestBase,C:\Users\josht\Development\apache\royale-compiler\compiler-jx\target\junit-results,TEST-org.apache.royale.compiler.internal.test.TestBase
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 ecffb8b..9972ec5 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
@@ -118,12 +118,14 @@ 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.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;
@@ -836,7 +838,7 @@ public class SemanticUtils
if (base != null && base.isDynamicExpression(project))
return true;
// the JS version of XML is not currently dynamic so special case it
here.
- if (base != null && base.getNodeID() == ASTNodeID.IdentifierID &&
IdentifierNode.isXMLish(base.resolveType(project), project))
+ if (base != null && base.getNodeID() == ASTNodeID.IdentifierID &&
isXMLish(base.resolveType(project), project))
return true;
return false;
}
@@ -946,6 +948,116 @@ public class SemanticUtils
}
/**
+ * Resolving the type of an expression on an XMLish object always returns
*,
+ * but this function returns the actual resolved type, if available.
+ *
+ * @param iNode The node you want to resolve
+ * @param project an ICompilerProject for the current project.
+ * @return The type of the underlying expression, or null.
+ */
+ public static IDefinition resolveTypeXML(IExpressionNode iNode,
ICompilerProject project)
+ {
+ IDefinition def = resolveXML(iNode, project);
+ if(def == null)
+ {
+ return null;
+ }
+ if (def instanceof IFunctionDefinition)
+ {
+ IFunctionDefinition functionDef = (IFunctionDefinition) def;
+ return functionDef.resolveReturnType(project);
+ }
+ return null;
+ }
+
+ /**
+ * Resolving an expression on an XMLish object always returns null, but
this
+ * function returns the actual resolved definition, if available.
+ *
+ * @param iNode The node you want to resolve
+ * @param project an ICompilerProject for the current project.
+ * @return The definition of the underlying expression, or null.
+ */
+ public static IDefinition resolveXML(IExpressionNode iNode,
ICompilerProject project)
+ {
+ if (iNode instanceof IFunctionCallNode)
+ {
+ IFunctionCallNode functionCall = (IFunctionCallNode) iNode;
+ IExpressionNode nameNode = functionCall.getNameNode();
+ if (nameNode instanceof IMemberAccessExpressionNode)
+ {
+ IMemberAccessExpressionNode memberAccess =
(IMemberAccessExpressionNode) nameNode;
+ nameNode = memberAccess.getRightOperandNode();
+ }
+ if (nameNode instanceof IdentifierNode)
+ {
+ IdentifierNode rightIdentifier = (IdentifierNode) nameNode;
+ if (rightIdentifier.isMemberRef())
+ {
+ ITypeDefinition baseType = null;
+ ExpressionNodeBase baseExpr =
rightIdentifier.getBaseExpression();
+ if (baseExpr != null)
+ {
+ baseType = baseExpr.resolveType(project);
+ }
+ if(isXMLish(baseType, project))
+ {
+ ASScope asScope = rightIdentifier.getASScope();
+ IDefinition propertyDef =
asScope.getPropertyFromDef(project, baseType, rightIdentifier.getName(), false);
+ if (propertyDef instanceof IFunctionDefinition &&
+ !(propertyDef instanceof IAccessorDefinition))
+ {
+ IFunctionDefinition functionDef =
(IFunctionDefinition) propertyDef;
+ return functionDef;
+ }
+ }
+ }
+ }
+ }
+ 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.
+ *
+ * @param def the {@link IDefinition} to check
+ * @param project the {@link ICompilerProject} in which to look up types
+ * @return true if definition is the built-in XML or XMLList type.
+ */
+ public static boolean isXMLish(IDefinition def, ICompilerProject project)
+ {
+ IDefinition xmlDef =
project.getBuiltinType(IASLanguageConstants.BuiltinType.XML);
+ IDefinition xmlListDef =
project.getBuiltinType(IASLanguageConstants.BuiltinType.XMLLIST);
+ return (xmlDef != null && def == xmlDef) ||
+ (xmlListDef != null && def == xmlListDef);
+ }
+
+ /**
+ * Determines if an expression is a toString() function call.
+ */
+ public static boolean isToStringFunctionCall(IExpressionNode node,
ICompilerProject project)
+ {
+ if(!(node instanceof IFunctionCallNode))
+ {
+ return false;
+ }
+ IFunctionCallNode functionCall = (IFunctionCallNode) node;
+ IExpressionNode nameExpression = functionCall.getNameNode();
+ if (nameExpression instanceof IMemberAccessExpressionNode)
+ {
+ IMemberAccessExpressionNode memberAccess =
(IMemberAccessExpressionNode) nameExpression;
+ IExpressionNode rightNode = memberAccess.getRightOperandNode();
+ if (rightNode instanceof IIdentifierNode)
+ {
+ IIdentifierNode rightIdentifier = (IIdentifierNode) rightNode;
+ return rightIdentifier.getName().equals("toString");
+ }
+ }
+ return false;
+ }
+
+ /**
* Get the type of a node's base expression as a string.
* @param node the node whose base's type is desired.
* @return the type string, or null if none found.
diff --git
a/compiler/src/main/java/org/apache/royale/compiler/internal/tree/as/BinaryOperatorPlusNode.java
b/compiler/src/main/java/org/apache/royale/compiler/internal/tree/as/BinaryOperatorPlusNode.java
index 771b4aa..7f4bcea 100644
---
a/compiler/src/main/java/org/apache/royale/compiler/internal/tree/as/BinaryOperatorPlusNode.java
+++
b/compiler/src/main/java/org/apache/royale/compiler/internal/tree/as/BinaryOperatorPlusNode.java
@@ -21,6 +21,7 @@ package org.apache.royale.compiler.internal.tree.as;
import org.apache.royale.compiler.constants.IASLanguageConstants.BuiltinType;
import org.apache.royale.compiler.definitions.ITypeDefinition;
+import org.apache.royale.compiler.internal.semantics.SemanticUtils;
import org.apache.royale.compiler.parsing.IASToken;
import org.apache.royale.compiler.projects.ICompilerProject;
import org.apache.royale.compiler.tree.ASTNodeID;
@@ -83,8 +84,8 @@ public class BinaryOperatorPlusNode extends
BinaryOperatorNodeBase
// If we're adding two XML-ish (i.e., XML or XMLList) objects,
// then the result is XMLList.
- if (IdentifierNode.isXMLish(leftType, project) &&
- IdentifierNode.isXMLish(rightType, project))
+ if (SemanticUtils.isXMLish(leftType, project) &&
+ SemanticUtils.isXMLish(rightType, project))
{
return project.getBuiltinType(BuiltinType.XMLLIST);
}
diff --git
a/compiler/src/main/java/org/apache/royale/compiler/internal/tree/as/IdentifierNode.java
b/compiler/src/main/java/org/apache/royale/compiler/internal/tree/as/IdentifierNode.java
index 9f38cef..22b0c1b 100644
---
a/compiler/src/main/java/org/apache/royale/compiler/internal/tree/as/IdentifierNode.java
+++
b/compiler/src/main/java/org/apache/royale/compiler/internal/tree/as/IdentifierNode.java
@@ -104,22 +104,6 @@ public class IdentifierNode extends ExpressionNodeBase
implements IIdentifierNod
}
/**
- * Determine if the definition passed in is one of the XML types (XML or
- * XMLList) These classes are unrelated, but behave in similar manners.
- *
- * @param def the {@link IDefinition} to check
- * @param project the {@link ICompilerProject} in which to look up types
- * @return true if definition is the built-in XML or XMLList type.
- */
- public static boolean isXMLish(IDefinition def, ICompilerProject project)
- {
- IDefinition xmlDef =
project.getBuiltinType(IASLanguageConstants.BuiltinType.XML);
- IDefinition xmlListDef =
project.getBuiltinType(IASLanguageConstants.BuiltinType.XMLLIST);
- return (xmlDef != null && def == xmlDef) ||
- (xmlListDef != null && def == xmlListDef);
- }
-
- /**
* Constructor.
*/
public IdentifierNode(String name)
@@ -469,7 +453,7 @@ public class IdentifierNode extends ExpressionNodeBase
implements IIdentifierNod
if (def != null)
{
- if (isXMLish(def.getParent(), project))
+ if (SemanticUtils.isXMLish(def.getParent(), project))
{
// XML and XMLList members should be treated as '*' because
any access could
// resolve to some content inside the XML (i.e. it has a child
tag named 'name').
@@ -903,7 +887,7 @@ public class IdentifierNode extends ExpressionNodeBase
implements IIdentifierNod
// and x is type XML you would get a
can't-convert-Object-to-String
// problem, but there is lots of existing source code that
expects
// this to compile with no cast.
- if (!((RoyaleProject)project).useStrictXML() &&
isXMLish(baseType, project))
+ if (!((RoyaleProject)project).useStrictXML() &&
SemanticUtils.isXMLish(baseType, project))
return null;
if (baseExpr instanceof IdentifierNode)
@@ -1039,7 +1023,7 @@ public class IdentifierNode extends ExpressionNodeBase
implements IIdentifierNod
// Can't early bind to XML/XMLList properties as they may be
hidden by the unknown contents
// of the XML itself, i.e. a child tag named 'parent'
// Matches ASC behavior.
- if (!isXMLish(def.getParent(), project))
+ if (!SemanticUtils.isXMLish(def.getParent(), project))
return true;
}
return false;