You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@flex.apache.org by jo...@apache.org on 2016/10/14 18:56:27 UTC
[1/3] git commit: [flex-falcon] [refs/heads/develop] -
LiteralEmitter: when a function has [JSX] metadata,
any XML literals inside are treated as JSX and React calls are emitted instead
Repository: flex-falcon
Updated Branches:
refs/heads/develop 680c335c7 -> 80eb23610
LiteralEmitter: when a function has [JSX] metadata, any XML literals inside are treated as JSX and React calls are emitted instead
Project: http://git-wip-us.apache.org/repos/asf/flex-falcon/repo
Commit: http://git-wip-us.apache.org/repos/asf/flex-falcon/commit/72f0c52a
Tree: http://git-wip-us.apache.org/repos/asf/flex-falcon/tree/72f0c52a
Diff: http://git-wip-us.apache.org/repos/asf/flex-falcon/diff/72f0c52a
Branch: refs/heads/develop
Commit: 72f0c52ad18b454b95ce4dfbf6c0e587742730eb
Parents: 8e79559
Author: Josh Tynjala <jo...@gmail.com>
Authored: Thu Oct 13 14:26:27 2016 -0700
Committer: Josh Tynjala <jo...@gmail.com>
Committed: Fri Oct 14 10:10:16 2016 -0700
----------------------------------------------------------------------
.../js/flexjs/JSFlexJSEmitterTokens.java | 1 +
.../internal/codegen/js/jx/LiteralEmitter.java | 422 ++++++++++++++++---
.../codegen/js/flexjs/TestFlexJSJSX.java | 180 ++++++++
3 files changed, 534 insertions(+), 69 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/72f0c52a/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/flexjs/JSFlexJSEmitterTokens.java
----------------------------------------------------------------------
diff --git a/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/flexjs/JSFlexJSEmitterTokens.java b/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/flexjs/JSFlexJSEmitterTokens.java
index 4431407..4a140e3 100644
--- a/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/flexjs/JSFlexJSEmitterTokens.java
+++ b/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/flexjs/JSFlexJSEmitterTokens.java
@@ -55,6 +55,7 @@ public enum JSFlexJSEmitterTokens implements IEmitterTokens
CLOSURE_FUNCTION_NAME("org.apache.flex.utils.Language.closure"),
SKIP_AS_COERCIONS("skipAsCoercions"),
SKIP_FUNCTION_COERCIONS("skipFunctionCoercions"),
+ JSX("JSX"),
;
private String token;
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/72f0c52a/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/jx/LiteralEmitter.java
----------------------------------------------------------------------
diff --git a/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/jx/LiteralEmitter.java b/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/jx/LiteralEmitter.java
index 1be3b1e..c3e371d 100644
--- a/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/jx/LiteralEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/jx/LiteralEmitter.java
@@ -19,15 +19,25 @@
package org.apache.flex.compiler.internal.codegen.js.jx;
+import java.util.ArrayList;
+import java.util.Stack;
+
import org.apache.flex.compiler.codegen.ISubEmitter;
import org.apache.flex.compiler.codegen.js.IJSEmitter;
+import org.apache.flex.compiler.common.IMetaInfo;
+import org.apache.flex.compiler.common.Multiname;
+import org.apache.flex.compiler.internal.codegen.as.ASEmitterTokens;
import org.apache.flex.compiler.internal.codegen.js.JSSubEmitter;
+import org.apache.flex.compiler.internal.codegen.js.flexjs.JSFlexJSEmitterTokens;
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.IFunctionNode;
+import org.apache.flex.compiler.tree.as.IImportNode;
import org.apache.flex.compiler.tree.as.ILiteralNode;
import org.apache.flex.compiler.tree.as.ILiteralNode.LiteralType;
+import org.apache.flex.compiler.tree.as.IScopedNode;
public class LiteralEmitter extends JSSubEmitter implements
ISubEmitter<ILiteralNode>
@@ -49,60 +59,83 @@ public class LiteralEmitter extends JSSubEmitter implements
{
if (node.getLiteralType() == LiteralType.XML)
{
- newlineReplacement = "\\\\\n";
- XMLLiteralNode xmlNode = (XMLLiteralNode)node;
- if (xmlNode.getContentsNode().getChildCount() == 1)
- {
- if (s.contains("'"))
- s = "\"" + s + "\"";
- else
- s = "'" + s + "'";
- }
- else
- {
- StringBuilder sb = new StringBuilder();
- // probably contains {initializers}
- boolean inAttribute = false;
- int n = xmlNode.getContentsNode().getChildCount();
- for (int i = 0; i < n; i++)
- {
- if (i > 0)
- sb.append(" + ");
- IASNode child = xmlNode.getContentsNode().getChild(i);
- if (child instanceof LiteralNode)
- {
- s = ((LiteralNode)child).getValue(true);
- if (s.contains("'"))
- sb.append("\"" + s + "\"");
- else
- sb.append("'" + s + "'");
- }
- else
- {
- s = getEmitter().stringifyNode(child);
- if (inAttribute)
- {
- sb.append("'\"' + ");
-
- sb.append(s);
-
- sb.append(" + '\"'");
- }
- else
- sb.append(s);
- }
- inAttribute = s.equals("=");
- }
- s = sb.toString();
- }
- char c = s.charAt(0);
- if (c == '"')
+ boolean jsx = false;
+ IFunctionNode functionNode = (IFunctionNode) node
+ .getAncestorOfType(IFunctionNode.class);
+ if (functionNode != null)
{
- s = s.substring(1, s.length() - 1);
- s = s.replace("\"", "\\\"");
- s = "\"" + s + "\"";
+ IMetaInfo[] metaInfos = functionNode.getMetaInfos();
+ for (IMetaInfo metaInfo : metaInfos)
+ {
+ if (metaInfo.getTagName().equals(JSFlexJSEmitterTokens.JSX.getToken()))
+ {
+ jsx = true;
+ break;
+ }
+ }
+ }
+ XMLLiteralNode xmlNode = (XMLLiteralNode) node;
+ if (jsx)
+ {
+ emitJSX(xmlNode);
+ return;
+ }
+ else
+ {
+ newlineReplacement = "\\\\\n";
+ if (xmlNode.getContentsNode().getChildCount() == 1)
+ {
+ if (s.contains("'"))
+ s = "\"" + s + "\"";
+ else
+ s = "'" + s + "'";
+ }
+ else
+ {
+ StringBuilder sb = new StringBuilder();
+ // probably contains {initializers}
+ boolean inAttribute = false;
+ int n = xmlNode.getContentsNode().getChildCount();
+ for (int i = 0; i < n; i++)
+ {
+ if (i > 0)
+ sb.append(" + ");
+ IASNode child = xmlNode.getContentsNode().getChild(i);
+ if (child instanceof LiteralNode)
+ {
+ s = ((LiteralNode) child).getValue(true);
+ if (s.contains("'"))
+ sb.append("\"" + s + "\"");
+ else
+ sb.append("'" + s + "'");
+ }
+ else
+ {
+ s = getEmitter().stringifyNode(child);
+ if (inAttribute)
+ {
+ sb.append("'\"' + ");
+
+ sb.append(s);
+
+ sb.append(" + '\"'");
+ }
+ else
+ sb.append(s);
+ }
+ inAttribute = s.equals("=");
+ }
+ s = sb.toString();
+ }
+ char c = s.charAt(0);
+ if (c == '"')
+ {
+ s = s.substring(1, s.length() - 1);
+ s = s.replace("\"", "\\\"");
+ s = "\"" + s + "\"";
+ }
+ s = "new XML( " + s + ")";
}
- s = "new XML( " + s + ")";
}
s = s.replaceAll("\n", "__NEWLINE_PLACEHOLDER__");
s = s.replaceAll("\r", "__CR_PLACEHOLDER__");
@@ -121,30 +154,281 @@ public class LiteralEmitter extends JSSubEmitter implements
s = s.replaceAll("__NEWLINE_PLACEHOLDER__", newlineReplacement);
if (node.getLiteralType() == LiteralType.STRING)
{
- char c = s.charAt(0);
- if (c == '"')
- {
- s = s.substring(1, s.length() - 1);
- s = s.replace("\"", "\\\"");
- s = "\"" + s + "\"";
- }
- else if (c == '\'')
- {
- s = s.substring(1, s.length() - 1);
- s = s.replace("'", "\\'");
- s = "'" + s + "'";
- }
- s = s.replace("\u2028", "\\u2028");
- s = s.replace("\u2029", "\\u2029");
+ char c = s.charAt(0);
+ if (c == '"')
+ {
+ s = s.substring(1, s.length() - 1);
+ s = s.replace("\"", "\\\"");
+ s = "\"" + s + "\"";
+ }
+ else if (c == '\'')
+ {
+ s = s.substring(1, s.length() - 1);
+ s = s.replace("'", "\\'");
+ s = "'" + s + "'";
+ }
+ s = s.replace("\u2028", "\\u2028");
+ s = s.replace("\u2029", "\\u2029");
}
}
if (!isWritten)
{
- startMapping(node);
+ startMapping(node);
write(s);
- endMapping(node);
+ endMapping(node);
+ }
+ }
+
+ private void emitJSX(XMLLiteralNode node)
+ {
+ int childCount = node.getContentsNode().getChildCount();
+ Stack<String> elementStack = new Stack<String>();
+ String elementName = null;
+ boolean endsWithAttribute = false;
+ for (int i = 0; i < childCount; i++)
+ {
+ IASNode child = node.getContentsNode().getChild(i);
+ if (child instanceof ILiteralNode)
+ {
+ ILiteralNode literalChild = (ILiteralNode) child;
+ if (literalChild.getLiteralType() != LiteralType.XML)
+ {
+ //inside {} syntax. emit normally.
+ getEmitter().getWalker().walk(literalChild);
+ continue;
+ }
+ String value = literalChild.getValue(true);
+ value = value.replaceAll(ASEmitterTokens.NEW_LINE.getToken(), "");
+ value = value.trim();
+ while (value.length() > 0)
+ {
+ int nextTagStartIndex = value.indexOf("<");
+ int nextTagEndIndex = value.indexOf(">");
+ boolean selfClosing = false;
+ boolean startsWithAttribute = false;
+ if (nextTagEndIndex > 0
+ && value.charAt(nextTagEndIndex - 1) == '/')
+ {
+ selfClosing = true;
+ }
+ if (endsWithAttribute)
+ {
+ //we'll fall back into attribute parsing below
+ endsWithAttribute = false;
+ startsWithAttribute = true;
+ elementName = elementStack.peek();
+ }
+ else if (nextTagStartIndex == 0)
+ {
+ //assume that the name ends at the end of the open tag
+ int endNameIndex = nextTagEndIndex;
+ if (endNameIndex == -1)
+ {
+ //literal ends with an attribute that uses {} syntax
+ endNameIndex = value.length() - 1;
+ }
+ int attributeIndex = value.indexOf(" ");
+ if (attributeIndex > 0 && attributeIndex < endNameIndex)
+ {
+ //if there are attributes, the name does not end at
+ //the end of the open tag
+ endNameIndex = attributeIndex;
+ }
+ elementName = value.substring(1, endNameIndex);
+ if (elementName.endsWith("/"))
+ {
+ elementName = elementName.substring(0, elementName.length() - 1);
+ }
+ if (elementName.startsWith("/"))
+ {
+ //the close tag of the current element
+ elementName = elementName.substring(1);
+ elementName = getQualifiedElementName(elementName, node);
+ if (elementStack.size() > 0)
+ {
+ indentPop();
+ }
+ write(ASEmitterTokens.PAREN_CLOSE);
+ String topOfStack = elementStack.pop();
+ assert topOfStack.equals(elementName);
+ value = value.substring(nextTagEndIndex + 1);
+ value = value.trim();
+ continue;
+ }
+ else
+ {
+ //the open tag of a new element
+ if (elementStack.size() > 0)
+ {
+ indentPush();
+ writeNewline(ASEmitterTokens.COMMA);
+ }
+ elementName = getQualifiedElementName(elementName, node);
+ elementStack.push(elementName);
+ write("React.createElement");
+ write(ASEmitterTokens.PAREN_OPEN);
+ write(elementName);
+ value = value.substring(endNameIndex);
+ value = value.trim();
+ //we changed the string, so find it again
+ nextTagEndIndex = value.indexOf(">");
+ }
+ }
+ else
+ {
+ //we're inside an element's open and closing tags
+ String elementText = value.substring(0, nextTagStartIndex);
+ writeToken(ASEmitterTokens.COMMA);
+ emitJSXText(elementText);
+ value = value.substring(nextTagStartIndex);
+ continue;
+ }
+ //parse the tag's attributes
+ if (nextTagEndIndex == -1)
+ {
+ //literal ends with an attribute that uses {} syntax
+ endsWithAttribute = true;
+ nextTagEndIndex = value.length() - 1;
+ }
+ int attributesEndIndex = (selfClosing && nextTagEndIndex > 0) ? nextTagEndIndex - 1 : nextTagEndIndex;
+ String attributes = value.substring(0, attributesEndIndex);
+ emitJSXAttributes(attributes, startsWithAttribute, endsWithAttribute);
+ if (selfClosing)
+ {
+ //end of open tag, including attributes
+ write(ASEmitterTokens.PAREN_CLOSE);
+ if (elementStack.size() > 0)
+ {
+ indentPop();
+ }
+ String topOfStack = elementStack.pop();
+ assert topOfStack.equals(elementName);
+ }
+ value = value.substring(nextTagEndIndex + 1);
+ value = value.trim();
+ }
+ }
+ else
+ {
+ if (!endsWithAttribute)
+ {
+ writeToken(ASEmitterTokens.COMMA);
+ }
+ //not a literal, and inside {} syntax. emit normally.
+ getEmitter().getWalker().walk(child);
+ }
+ }
+ }
+
+ private void emitJSXAttributes(String value, boolean startsWithAttribute, boolean endsWithAttribute)
+ {
+ int attributeCount = 0;
+ while (true)
+ {
+ int charCount = value.length();
+ if (charCount == 0)
+ {
+ break;
+ }
+ int endAttributeNameIndex = value.indexOf("=");
+ if (endAttributeNameIndex == -1)
+ {
+ endAttributeNameIndex = value.length();
+ }
+ String attributeName = value.substring(0, endAttributeNameIndex);
+ writeToken(ASEmitterTokens.COMMA);
+ if (!startsWithAttribute && attributeCount == 0)
+ {
+ writeToken(ASEmitterTokens.BLOCK_OPEN);
+ }
+ if (attributeName.indexOf('-') >= 0)
+ {
+ emitJSXText(attributeName);
+ }
+ else
+ {
+ write(attributeName);
+ }
+ writeToken(ASEmitterTokens.COLON);
+ attributeCount++;
+ if ((endAttributeNameIndex + 1) >= charCount)
+ {
+ //literal ends with an attribute that uses {} syntax
+ break;
+ }
+ int quoteChar = value.charAt(endAttributeNameIndex + 1);
+ int startAttributeValueIndex = endAttributeNameIndex + 2;
+ if (startAttributeValueIndex > charCount)
+ {
+ startAttributeValueIndex = charCount;
+ }
+ int endAttributeValueIndex = value.indexOf(quoteChar, startAttributeValueIndex);
+ if (endAttributeValueIndex == -1 || endAttributeValueIndex > charCount)
+ {
+ endAttributeValueIndex = charCount;
+ }
+ if (endAttributeValueIndex > 0)
+ {
+ String attributeValue = value.substring(startAttributeValueIndex, endAttributeValueIndex);
+ emitJSXText(attributeValue);
+ value = value.substring(endAttributeValueIndex + 1);
+ value = value.trim();
+ }
+ }
+ if (!endsWithAttribute)
+ {
+ if (!startsWithAttribute && attributeCount == 0)
+ {
+ writeToken(ASEmitterTokens.COMMA);
+ write(ASEmitterTokens.NULL);
+ }
+ else
+ {
+ write(ASEmitterTokens.SPACE);
+ write(ASEmitterTokens.BLOCK_CLOSE);
+ }
+ }
+ }
+
+ private void emitJSXText(String elementText)
+ {
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ elementText = elementText.replaceAll("'", "\\\\\'");
+ write(elementText);
+ write(ASEmitterTokens.SINGLE_QUOTE);
+ }
+
+ private String getQualifiedElementName(String elementName, IASNode node)
+ {
+ String firstChar = elementName.substring(0, 1);
+ boolean isHTMLTag = firstChar.toLowerCase().equals(firstChar);
+ if (isHTMLTag)
+ {
+ return ASEmitterTokens.SINGLE_QUOTE.getToken() + elementName + ASEmitterTokens.SINGLE_QUOTE.getToken();
+ }
+ ArrayList<IImportNode> importNodes = new ArrayList<IImportNode>();
+ IScopedNode scopedNode = node.getContainingScope();
+ scopedNode.getAllImportNodes(importNodes);
+ for (IImportNode importNode : importNodes)
+ {
+ if (importNode.isWildcardImport())
+ {
+ continue;
+ }
+ String importName = importNode.getImportName();
+ String importAlias = importNode.getImportAlias();
+ if (importAlias != null && importAlias.equals(elementName))
+ {
+ return importName;
+ }
+ String baseName = Multiname.getBaseNameForQName(importName);
+ if (baseName.equals(elementName))
+ {
+ return importName;
+ }
}
+ return elementName;
}
}
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/72f0c52a/compiler-jx/src/test/java/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSJSX.java
----------------------------------------------------------------------
diff --git a/compiler-jx/src/test/java/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSJSX.java b/compiler-jx/src/test/java/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSJSX.java
new file mode 100644
index 0000000..a3c1c07
--- /dev/null
+++ b/compiler-jx/src/test/java/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSJSX.java
@@ -0,0 +1,180 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.flex.compiler.internal.codegen.js.flexjs;
+
+import org.apache.flex.compiler.driver.IBackend;
+import org.apache.flex.compiler.internal.driver.js.flexjs.FlexJSBackend;
+import org.apache.flex.compiler.internal.test.ASTestBase;
+import org.apache.flex.compiler.tree.as.IFunctionNode;
+
+import org.junit.Test;
+
+public class TestFlexJSJSX extends ASTestBase
+{
+ @Test
+ public void testJSXMetadataWithoutXMLLiterals()
+ {
+ IFunctionNode node = getMethod("[JSX]\nfunction foo() {}");
+ asBlockWalker.visitFunction(node);
+ assertOut("FalconTest_A.prototype.foo = function() {\n}");
+ }
+
+ @Test
+ public void testSimpleSelfClosingHTMLTag()
+ {
+ IFunctionNode node = getMethod("[JSX]\nfunction foo() {return <div/>}");
+ asBlockWalker.visitFunction(node);
+ assertOut("FalconTest_A.prototype.foo = function() {\n return React.createElement('div', null);\n}");
+ }
+
+ @Test
+ public void testSimpleSelfClosingHTMLTagWithTrailingSpace()
+ {
+ IFunctionNode node = getMethod("[JSX]\nfunction foo() {return <div />}");
+ asBlockWalker.visitFunction(node);
+ assertOut("FalconTest_A.prototype.foo = function() {\n return React.createElement('div', null);\n}");
+ }
+
+ @Test
+ public void testSelfClosingHTMLTagWithAttribute()
+ {
+ IFunctionNode node = getMethod("[JSX]\nfunction foo() {return <div id=\"foo\"/>}");
+ asBlockWalker.visitFunction(node);
+ assertOut("FalconTest_A.prototype.foo = function() {\n return React.createElement('div', { id: 'foo' });\n}");
+ }
+
+ @Test
+ public void testSelfClosingHTMLTagWithMultipleAttributes()
+ {
+ IFunctionNode node = getMethod("[JSX]\nfunction foo() {return <div id=\"foo\" className=\"bar\"/>}");
+ asBlockWalker.visitFunction(node);
+ assertOut("FalconTest_A.prototype.foo = function() {\n return React.createElement('div', { id: 'foo', className: 'bar' });\n}");
+ }
+
+ @Test
+ public void testSelfClosingHTMLTagWithSingleQuoteAttribute()
+ {
+ IFunctionNode node = getMethod("[JSX]\nfunction foo() {return <div id=\'foo\'/>}");
+ asBlockWalker.visitFunction(node);
+ assertOut("FalconTest_A.prototype.foo = function() {\n return React.createElement('div', { id: 'foo' });\n}");
+ }
+
+ @Test
+ public void testSelfClosingHTMLTagWithSingleQuoteInAttribute()
+ {
+ IFunctionNode node = getMethod("[JSX]\nfunction foo() {return <div id=\"'\"/>}");
+ asBlockWalker.visitFunction(node);
+ assertOut("FalconTest_A.prototype.foo = function() {\n return React.createElement('div', { id: '\\\'' });\n}");
+ }
+
+ @Test
+ public void testSelfClosingHTMLTagWithDashInAttributeName()
+ {
+ IFunctionNode node = getMethod("[JSX]\nfunction foo() {return <div data-prop=\"foo\"/>}");
+ asBlockWalker.visitFunction(node);
+ assertOut("FalconTest_A.prototype.foo = function() {\n return React.createElement('div', { 'data-prop': 'foo' });\n}");
+ }
+
+ @Test
+ public void testSelfClosingHTMLTagWithSpaceInAttribute()
+ {
+ IFunctionNode node = getMethod("[JSX]\nfunction foo() {return <div className=\"foo bar\"/>}");
+ asBlockWalker.visitFunction(node);
+ assertOut("FalconTest_A.prototype.foo = function() {\n return React.createElement('div', { className: 'foo bar' });\n}");
+ }
+
+ @Test
+ public void testSelfClosingHTMLTagWithSpaceInSingleQuoteAttribute()
+ {
+ IFunctionNode node = getMethod("[JSX]\nfunction foo() {return <div className=\'foo bar\'/>}");
+ asBlockWalker.visitFunction(node);
+ assertOut("FalconTest_A.prototype.foo = function() {\n return React.createElement('div', { className: 'foo bar' });\n}");
+ }
+
+ @Test
+ public void testSelfClosingHTMLTagWithCurlyAttribute()
+ {
+ IFunctionNode node = getMethod("[JSX]\nfunction foo() {return <div id={2}/>}");
+ asBlockWalker.visitFunction(node);
+ assertOut("FalconTest_A.prototype.foo = function() {\n return React.createElement('div', { id: 2 });\n}");
+ }
+
+ @Test
+ public void testSimpleOpenAndCloseHTMLTag()
+ {
+ IFunctionNode node = getMethod("[JSX]\nfunction foo() {return <div></div>}");
+ asBlockWalker.visitFunction(node);
+ assertOut("FalconTest_A.prototype.foo = function() {\n return React.createElement('div', null);\n}");
+ }
+
+ @Test
+ public void testOpenAndCloseHTMLTagWithChildText()
+ {
+ IFunctionNode node = getMethod("[JSX]\nfunction foo() {return <div>Foo</div>}");
+ asBlockWalker.visitFunction(node);
+ assertOut("FalconTest_A.prototype.foo = function() {\n return React.createElement('div', null, 'Foo');\n}");
+ }
+
+ @Test
+ public void testOpenAndCloseHTMLTagWithAttribute()
+ {
+ IFunctionNode node = getMethod("[JSX]\nfunction foo() {return <div id=\"foo\"></div>}");
+ asBlockWalker.visitFunction(node);
+ assertOut("FalconTest_A.prototype.foo = function() {\n return React.createElement('div', { id: 'foo' });\n}");
+ }
+
+ @Test
+ public void testOpenAndCloseHTMLTagWithMultipleAttributes()
+ {
+ IFunctionNode node = getMethod("[JSX]\nfunction foo() {return <div id=\"foo\" className=\"bar\"></div>}");
+ asBlockWalker.visitFunction(node);
+ assertOut("FalconTest_A.prototype.foo = function() {\n return React.createElement('div', { id: 'foo', className: 'bar' });\n}");
+ }
+
+ @Test
+ public void testOpenAndCloseHTMLTagWithAttributeAndChildText()
+ {
+ IFunctionNode node = getMethod("[JSX]\nfunction foo() {return <div id=\"foo\">Foo</div>}");
+ asBlockWalker.visitFunction(node);
+ assertOut("FalconTest_A.prototype.foo = function() {\n return React.createElement('div', { id: 'foo' }, 'Foo');\n}");
+ }
+
+ @Test
+ public void testNestedHTMLTags()
+ {
+ IFunctionNode node = getMethod("[JSX]\nfunction foo() {return <div><button/></div>}");
+ asBlockWalker.visitFunction(node);
+ assertOut("FalconTest_A.prototype.foo = function() {\n return React.createElement('div', null,\n React.createElement('button', null));\n}");
+ }
+
+ @Test
+ public void testImportedClass()
+ {
+ IFunctionNode node = getMethod("[JSX]\nfunction foo() {\n import flash.events.EventDispatcher;\n return <EventDispatcher/>;\n}");
+ asBlockWalker.visitFunction(node);
+ assertOut("FalconTest_A.prototype.foo = function() {\n return React.createElement(flash.events.EventDispatcher, null);\n}");
+ }
+
+ @Override
+ protected IBackend createBackend()
+ {
+ return new FlexJSBackend();
+ }
+}
[2/3] git commit: [flex-falcon] [refs/heads/develop] - compiler-jx:
import statements are not output in JS (they were previously if they appeared
in a function)
Posted by jo...@apache.org.
compiler-jx: import statements are not output in JS (they were previously if they appeared in a function)
Project: http://git-wip-us.apache.org/repos/asf/flex-falcon/repo
Commit: http://git-wip-us.apache.org/repos/asf/flex-falcon/commit/a9650946
Tree: http://git-wip-us.apache.org/repos/asf/flex-falcon/tree/a9650946
Diff: http://git-wip-us.apache.org/repos/asf/flex-falcon/diff/a9650946
Branch: refs/heads/develop
Commit: a96509461b45e143baf52423552a0990a3821824
Parents: 680c335
Author: Josh Tynjala <jo...@gmail.com>
Authored: Fri Oct 14 10:42:26 2016 -0700
Committer: Josh Tynjala <jo...@gmail.com>
Committed: Fri Oct 14 10:42:26 2016 -0700
----------------------------------------------------------------------
.../flex/compiler/internal/codegen/js/JSEmitter.java | 7 +++++++
.../internal/codegen/js/jx/StatementEmitter.java | 6 ++++++
.../codegen/js/flexjs/TestFlexJSStatements.java | 13 +++++++++++++
3 files changed, 26 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/a9650946/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/JSEmitter.java
----------------------------------------------------------------------
diff --git a/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/JSEmitter.java b/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/JSEmitter.java
index 237c430..7824a87 100644
--- a/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/JSEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/JSEmitter.java
@@ -69,6 +69,7 @@ import org.apache.flex.compiler.tree.as.IForLoopNode;
import org.apache.flex.compiler.tree.as.IFunctionNode;
import org.apache.flex.compiler.tree.as.IFunctionObjectNode;
import org.apache.flex.compiler.tree.as.IIfNode;
+import org.apache.flex.compiler.tree.as.IImportNode;
import org.apache.flex.compiler.tree.as.IIterationFlowNode;
import org.apache.flex.compiler.tree.as.ILanguageIdentifierNode;
import org.apache.flex.compiler.tree.as.ILiteralContainerNode;
@@ -340,6 +341,12 @@ public class JSEmitter extends ASEmitter implements IJSEmitter
}
@Override
+ public void emitImport(IImportNode node)
+ {
+ // do nothing
+ }
+
+ @Override
public void emitWhileLoop(IWhileLoopNode node)
{
whileLoopEmitter.emit(node);
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/a9650946/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/jx/StatementEmitter.java
----------------------------------------------------------------------
diff --git a/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/jx/StatementEmitter.java b/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/jx/StatementEmitter.java
index 1f4eb4d..40e933e 100644
--- a/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/jx/StatementEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/jx/StatementEmitter.java
@@ -39,6 +39,12 @@ public class StatementEmitter extends JSSubEmitter implements
{
getWalker().walk(node);
+ if(node.getNodeID() == ASTNodeID.ImportID)
+ {
+ //imports aren't emitted, so don't emit anything here either
+ return;
+ }
+
// XXX (mschmalle) this should be in the after handler?
if (node.getParent().getNodeID() != ASTNodeID.LabledStatementID
&& node.getNodeID() != ASTNodeID.ConfigBlockID
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/a9650946/compiler-jx/src/test/java/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSStatements.java
----------------------------------------------------------------------
diff --git a/compiler-jx/src/test/java/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSStatements.java b/compiler-jx/src/test/java/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSStatements.java
index 733973e..604d0f1 100644
--- a/compiler-jx/src/test/java/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSStatements.java
+++ b/compiler-jx/src/test/java/org/apache/flex/compiler/internal/codegen/js/flexjs/TestFlexJSStatements.java
@@ -27,6 +27,7 @@ import org.apache.flex.compiler.internal.tree.as.LabeledStatementNode;
import org.apache.flex.compiler.tree.as.IFileNode;
import org.apache.flex.compiler.tree.as.IForLoopNode;
import org.apache.flex.compiler.tree.as.IIfNode;
+import org.apache.flex.compiler.tree.as.IImportNode;
import org.apache.flex.compiler.tree.as.ILiteralNode;
import org.apache.flex.compiler.tree.as.ISwitchNode;
import org.apache.flex.compiler.tree.as.ITryNode;
@@ -470,6 +471,18 @@ public class TestFlexJSStatements extends TestGoogStatements
assertOut("with (a)\n b;");
}
+ //----------------------------------
+ // import a.b.C
+ //----------------------------------
+
+ @Test
+ public void testVisitImport()
+ {
+ IImportNode node = (IImportNode) getNode("import flash.events.EventDispatcher;", IImportNode.class);
+ asBlockWalker.visitImport(node);
+ assertOut("");
+ }
+
@Override
@Test
public void testVisit()
[3/3] git commit: [flex-falcon] [refs/heads/develop] - merge develop
Posted by jo...@apache.org.
merge develop
Project: http://git-wip-us.apache.org/repos/asf/flex-falcon/repo
Commit: http://git-wip-us.apache.org/repos/asf/flex-falcon/commit/80eb2361
Tree: http://git-wip-us.apache.org/repos/asf/flex-falcon/tree/80eb2361
Diff: http://git-wip-us.apache.org/repos/asf/flex-falcon/diff/80eb2361
Branch: refs/heads/develop
Commit: 80eb2361059d483a93a087b8c844b14563074a63
Parents: 72f0c52 a965094
Author: Josh Tynjala <jo...@gmail.com>
Authored: Fri Oct 14 10:50:35 2016 -0700
Committer: Josh Tynjala <jo...@gmail.com>
Committed: Fri Oct 14 10:57:09 2016 -0700
----------------------------------------------------------------------
.../apache/flex/compiler/clients/ASDOCJSC.java | 13 --
.../apache/flex/compiler/clients/COMPJSC.java | 2 -
.../compiler/internal/codegen/js/JSEmitter.java | 7 +
.../internal/codegen/js/JSSessionModel.java | 1 -
.../codegen/js/flexjs/JSFlexJSASDocEmitter.java | 63 ------
.../internal/codegen/js/jx/AccessorEmitter.java | 2 -
.../codegen/js/jx/BinaryOperatorEmitter.java | 2 -
.../internal/codegen/js/jx/FieldEmitter.java | 14 --
.../codegen/js/jx/FunctionCallEmitter.java | 30 ++-
.../codegen/js/jx/IdentifierEmitter.java | 4 -
.../internal/codegen/js/jx/LiteralEmitter.java | 8 +-
.../codegen/js/jx/MemberAccessEmitter.java | 3 -
.../codegen/js/jx/StatementEmitter.java | 6 +
.../codegen/js/jx/SuperCallEmitter.java | 2 -
.../mxml/flexjs/MXMLFlexJSASDocEmitter.java | 210 -------------------
.../codegen/mxml/flexjs/MXMLFlexJSEmitter.java | 6 +-
.../driver/js/goog/ASDocConfiguration.java | 2 -
.../driver/mxml/ASDocASSourceFileHandler.java | 1 -
.../mxml/flexjs/MXMLFlexJSASDocBackend.java | 5 -
.../internal/projects/FlexJSProject.java | 1 -
.../js/flexjs/TestFlexJSGlobalClasses.java | 26 +++
.../js/flexjs/TestFlexJSGlobalFunctions.java | 8 +
.../codegen/js/flexjs/TestFlexJSStatements.java | 13 ++
.../flex/compiler/internal/scopes/ASScope.java | 2 -
.../compiler/internal/tree/as/ImportNode.java | 1 -
.../src/test/java/as/ASInheritanceTests.java | 1 -
26 files changed, 91 insertions(+), 342 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/80eb2361/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/jx/LiteralEmitter.java
----------------------------------------------------------------------
diff --cc compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/jx/LiteralEmitter.java
index c3e371d,d3fc55d..47f0c8d
--- a/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/jx/LiteralEmitter.java
+++ b/compiler-jx/src/main/java/org/apache/flex/compiler/internal/codegen/js/jx/LiteralEmitter.java
@@@ -59,83 -49,60 +59,83 @@@ public class LiteralEmitter extends JSS
{
if (node.getLiteralType() == LiteralType.XML)
{
- newlineReplacement = "\\\\\n";
- XMLLiteralNode xmlNode = (XMLLiteralNode)node;
- if (xmlNode.getContentsNode().getChildCount() == 1)
- {
- if (s.contains("'"))
- s = "\"" + s + "\"";
- else
- s = "'" + s + "'";
- }
- else
- {
- StringBuilder sb = new StringBuilder();
- // probably contains {initializers}
- boolean inAttribute = false;
- int n = xmlNode.getContentsNode().getChildCount();
- for (int i = 0; i < n; i++)
- {
- if (i > 0)
- sb.append(" + ");
- IASNode child = xmlNode.getContentsNode().getChild(i);
- if (child instanceof LiteralNode)
- {
- s = ((LiteralNode)child).getValue(true);
- if (s.contains("'"))
- sb.append("\"" + s + "\"");
- else
- sb.append("'" + s + "'");
- }
- else
- {
- s = getEmitter().stringifyNode(child);
- if (inAttribute)
- {
- sb.append("'\"' + ");
-
- sb.append(s);
-
- sb.append(" + '\"'");
- }
- else
- sb.append(s);
- }
- inAttribute = s.endsWith("=");
- }
- s = sb.toString();
- }
- char c = s.charAt(0);
- if (c == '"')
+ boolean jsx = false;
+ IFunctionNode functionNode = (IFunctionNode) node
+ .getAncestorOfType(IFunctionNode.class);
+ if (functionNode != null)
{
- s = s.substring(1, s.length() - 1);
- s = s.replace("\"", "\\\"");
- s = "\"" + s + "\"";
+ IMetaInfo[] metaInfos = functionNode.getMetaInfos();
+ for (IMetaInfo metaInfo : metaInfos)
+ {
+ if (metaInfo.getTagName().equals(JSFlexJSEmitterTokens.JSX.getToken()))
+ {
+ jsx = true;
+ break;
+ }
+ }
+ }
+ XMLLiteralNode xmlNode = (XMLLiteralNode) node;
+ if (jsx)
+ {
+ emitJSX(xmlNode);
+ return;
+ }
+ else
+ {
+ newlineReplacement = "\\\\\n";
+ if (xmlNode.getContentsNode().getChildCount() == 1)
+ {
+ if (s.contains("'"))
+ s = "\"" + s + "\"";
+ else
+ s = "'" + s + "'";
+ }
+ else
+ {
+ StringBuilder sb = new StringBuilder();
+ // probably contains {initializers}
+ boolean inAttribute = false;
+ int n = xmlNode.getContentsNode().getChildCount();
+ for (int i = 0; i < n; i++)
+ {
+ if (i > 0)
+ sb.append(" + ");
+ IASNode child = xmlNode.getContentsNode().getChild(i);
+ if (child instanceof LiteralNode)
+ {
- s = ((LiteralNode) child).getValue(true);
++ s = ((LiteralNode)child).getValue(true);
+ if (s.contains("'"))
+ sb.append("\"" + s + "\"");
+ else
+ sb.append("'" + s + "'");
+ }
+ else
+ {
+ s = getEmitter().stringifyNode(child);
+ if (inAttribute)
+ {
+ sb.append("'\"' + ");
-
++
+ sb.append(s);
-
++
+ sb.append(" + '\"'");
+ }
+ else
+ sb.append(s);
+ }
- inAttribute = s.equals("=");
++ inAttribute = s.endsWith("=");
+ }
+ s = sb.toString();
+ }
+ char c = s.charAt(0);
+ if (c == '"')
+ {
+ s = s.substring(1, s.length() - 1);
+ s = s.replace("\"", "\\\"");
+ s = "\"" + s + "\"";
+ }
+ s = "new XML( " + s + ")";
}
- s = "new XML( " + s + ")";
}
s = s.replaceAll("\n", "__NEWLINE_PLACEHOLDER__");
s = s.replaceAll("\r", "__CR_PLACEHOLDER__");