Repository: flex-falcon Updated Branches: refs/heads/develop d868ffda1 -> 9d605f29b
handle XML initializers in XML literals Project: http://git-wip-us.apache.org/repos/asf/flex-falcon/repo Commit: http://git-wip-us.apache.org/repos/asf/flex-falcon/commit/9d605f29 Tree: http://git-wip-us.apache.org/repos/asf/flex-falcon/tree/9d605f29 Diff: http://git-wip-us.apache.org/repos/asf/flex-falcon/diff/9d605f29 Branch: refs/heads/develop Commit: 9d605f29bb21ca9a9eb9f5cdbddb1608eb7b65b4 Parents: d868ffd Author: Alex Harui <[email protected]> Authored: Wed Jan 6 12:21:29 2016 -0800 Committer: Alex Harui <[email protected]> Committed: Wed Jan 6 12:21:29 2016 -0800 ---------------------------------------------------------------------- .../js/flexjs/TestFlexJSGlobalClasses.java | 14 +++++++ .../internal/codegen/js/jx/LiteralEmitter.java | 42 +++++++++++++++++--- .../compiler/internal/parsing/as/ASParser.g | 25 +++++++++++- .../internal/parsing/as/BaseASParser.java | 27 +++++++++++++ 4 files changed, 102 insertions(+), 6 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/9d605f29/compiler.jx.tests/src/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSGlobalClasses.java ---------------------------------------------------------------------- diff --git a/compiler.jx.tests/src/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSGlobalClasses.java b/compiler.jx.tests/src/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSGlobalClasses.java index 815d997..35f6823 100644 --- a/compiler.jx.tests/src/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSGlobalClasses.java +++ b/compiler.jx.tests/src/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSGlobalClasses.java @@ -22,6 +22,7 @@ package org.apache.flex.compiler.internal.codegen.js.flexjs; import org.apache.flex.compiler.driver.IBackend; import org.apache.flex.compiler.internal.codegen.js.goog.TestGoogGlobalClasses; import org.apache.flex.compiler.internal.driver.js.flexjs.FlexJSBackend; +import org.apache.flex.compiler.internal.tree.as.VariableNode; import org.apache.flex.compiler.tree.as.IASNode; import org.apache.flex.compiler.tree.as.IBinaryOperatorNode; import org.apache.flex.compiler.tree.as.IForLoopNode; @@ -192,6 +193,19 @@ public class TestFlexJSGlobalClasses extends TestGoogGlobalClasses } @Test + public void testXMLLiteralWithTemplate() + { + VariableNode node = (VariableNode)getNode("private function get tagname():String { return 'name'; };\n" + + "private function get attributename():String { return 'id'; };\n" + + "private function get attributevalue():Number { return 5; };\n" + + "private function get content():String { return 'Fred'; };\n" + + "private function test() { var a:XML = <{tagname} {attributename}={attributevalue}>{content}</{tagname}>;}", + VariableNode.class, WRAP_LEVEL_CLASS); + asBlockWalker.visitVariable(node); + assertOut("var /** @type {XML} */ a = new XML( '<' + this.tagname + ' ' + this.attributename + '=' + this.attributevalue + '>' + this.content + '</' + this.tagname + '>') "); + } + + @Test public void testXMLSingleDot() { IVariableNode node = getVariable("var a:XML = new XML(\"<top attr1='cat'><child attr2='dog'><grandchild attr3='fish'>text</grandchild></child></top>\");var b:XMLList = a.child;"); http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/9d605f29/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/jx/LiteralEmitter.java ---------------------------------------------------------------------- diff --git a/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/jx/LiteralEmitter.java b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/jx/LiteralEmitter.java index 6945772..a4b276c 100644 --- a/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/jx/LiteralEmitter.java +++ b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/jx/LiteralEmitter.java @@ -22,7 +22,11 @@ package org.apache.flex.compiler.internal.codegen.js.jx; import org.apache.flex.compiler.codegen.ISubEmitter; import org.apache.flex.compiler.codegen.js.IJSEmitter; import org.apache.flex.compiler.internal.codegen.js.JSSubEmitter; +import org.apache.flex.compiler.internal.tree.as.IdentifierNode; +import org.apache.flex.compiler.internal.tree.as.LiteralNode; import org.apache.flex.compiler.internal.tree.as.RegExpLiteralNode; +import org.apache.flex.compiler.internal.tree.as.XMLLiteralNode; +import org.apache.flex.compiler.tree.as.IASNode; import org.apache.flex.compiler.tree.as.ILiteralNode; import org.apache.flex.compiler.tree.as.ILiteralNode.LiteralType; @@ -45,12 +49,40 @@ public class LiteralEmitter extends JSSubEmitter implements { if (node.getLiteralType() == LiteralType.XML) { - if (s.contains("'")) - write("\"" + s + "\""); + XMLLiteralNode xmlNode = (XMLLiteralNode)node; + if (xmlNode.getContentsNode().getChildCount() == 1) + { + if (s.contains("'")) + write("\"" + s + "\""); + else + write("'" + s + "'"); + isWritten = true; + } else - write("'" + s + "'"); - - isWritten = true; + { + // probably contains {initializers} + int n = xmlNode.getContentsNode().getChildCount(); + for (int i = 0; i < n; i++) + { + if (i > 0) + write(" + "); + IASNode child = xmlNode.getContentsNode().getChild(i); + if (child instanceof LiteralNode) + { + s = ((LiteralNode)child).getValue(true); + if (s.contains("'")) + write("\"" + s + "\""); + else + write("'" + s + "'"); + isWritten = true; + } + else if (child instanceof IdentifierNode) + { + s = getEmitter().stringifyNode(child); + write(s); + } + } + } } s = s.replaceAll("\n", "__NEWLINE_PLACEHOLDER__"); s = s.replaceAll("\r", "__CR_PLACEHOLDER__"); http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/9d605f29/compiler/src/org/apache/flex/compiler/internal/parsing/as/ASParser.g ---------------------------------------------------------------------- diff --git a/compiler/src/org/apache/flex/compiler/internal/parsing/as/ASParser.g b/compiler/src/org/apache/flex/compiler/internal/parsing/as/ASParser.g index 9b21966..c84a089 100644 --- a/compiler/src/org/apache/flex/compiler/internal/parsing/as/ASParser.g +++ b/compiler/src/org/apache/flex/compiler/internal/parsing/as/ASParser.g @@ -2713,7 +2713,8 @@ xmlTag [BaseLiteralContainerNode n] ) ) xmlWhitespace[n] - ( ( xmlAttribute[n] | xmlContentBlock[n] ) + ( ( { isXMLAttribute() }? xmlAttribute[n] + | xmlContentBlock[n] ) xmlWhitespace[n] )* ( endT:TOKEN_E4X_TAG_END // > @@ -2732,12 +2733,16 @@ xmlTag [BaseLiteralContainerNode n] * name="value" * name='value' * name={value} + * {name}="value" + * {name}='value' + * {name}={value} */ xmlAttribute [BaseLiteralContainerNode n] : ( nT:TOKEN_E4X_NAME { n.appendLiteralToken((ASToken)nT); } | nsT:TOKEN_E4X_XMLNS { n.appendLiteralToken((ASToken)nsT); } + | xmlAttributeBlock[n] ) ( dT:TOKEN_E4X_NAME_DOT { n.appendLiteralToken((ASToken)dT); } @@ -2806,6 +2811,24 @@ xmlContentBlock[BaseLiteralContainerNode n] /** + * Matches a binding expression in an XML literal attribute name. + */ +xmlAttributeBlock[BaseLiteralContainerNode n] +{ + ExpressionNodeBase e = null; +} + : TOKEN_E4X_BINDING_OPEN + e=lhsExpr + { + if(e != null) + n.getContentsNode().addItem(e); + } + TOKEN_E4X_BINDING_CLOSE + ; + exception catch [RecognitionException ex] { handleParsingError(ex); } + + +/** * Matches a left-hand side (of asssignment) expression. */ lhsExpr returns [ExpressionNodeBase n] http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/9d605f29/compiler/src/org/apache/flex/compiler/internal/parsing/as/BaseASParser.java ---------------------------------------------------------------------- diff --git a/compiler/src/org/apache/flex/compiler/internal/parsing/as/BaseASParser.java b/compiler/src/org/apache/flex/compiler/internal/parsing/as/BaseASParser.java index fb57848..83c9084 100644 --- a/compiler/src/org/apache/flex/compiler/internal/parsing/as/BaseASParser.java +++ b/compiler/src/org/apache/flex/compiler/internal/parsing/as/BaseASParser.java @@ -1312,6 +1312,33 @@ abstract class BaseASParser extends LLkParser implements IProblemReporter } /** + * Check if the look-ahead can be matched as a "XMLAttribute". + * + * @return True if the following input is "XMLAttribute". + */ + protected final boolean isXMLAttribute() + { + return LA(1) == TOKEN_E4X_NAME || + LA(1) == TOKEN_E4X_XMLNS || + (LA(1) == TOKEN_E4X_BINDING_OPEN && hasEqualsAfterClose()); + } + + /** + * See if there is an assignment right after the close of the binding expr. + * If there is, then it is an attribute name otherwise no + */ + private final boolean hasEqualsAfterClose() + { + int i = 2; + while (true) + { + if (LA(i) == TOKEN_E4X_BINDING_CLOSE) + return LA(i+1) == TOKEN_E4X_EQUALS; + i++; + } + } + + /** * Stores decorations on the given variable definition. This will set any * collected modifiers, namespace, metadata or comment we've encountered *
