Repository: flex-falcon Updated Branches: refs/heads/develop 9c05264f8 -> 47cf23cd6
functions with [JSX] metadata register appropriate dependencies in the graph for their tags Project: http://git-wip-us.apache.org/repos/asf/flex-falcon/repo Commit: http://git-wip-us.apache.org/repos/asf/flex-falcon/commit/58f31971 Tree: http://git-wip-us.apache.org/repos/asf/flex-falcon/tree/58f31971 Diff: http://git-wip-us.apache.org/repos/asf/flex-falcon/diff/58f31971 Branch: refs/heads/develop Commit: 58f31971851e98bfdd5652b5c1626be9bfc9f6c6 Parents: 9c05264 Author: Josh Tynjala <joshtynj...@gmail.com> Authored: Sun Oct 16 17:00:10 2016 -0700 Committer: Josh Tynjala <joshtynj...@gmail.com> Committed: Sun Oct 16 17:00:10 2016 -0700 ---------------------------------------------------------------------- .../internal/codegen/js/jx/LiteralEmitter.java | 42 ++---- .../internal/units/ASCompilationUnit.java | 50 +++++++ .../java/org/apache/flex/utils/JSXUtil.java | 129 +++++++++++++++++++ 3 files changed, 188 insertions(+), 33 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/58f31971/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 176eb35..518c3a5 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,13 +19,11 @@ 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; @@ -34,10 +32,9 @@ 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; +import org.apache.flex.utils.JSXUtil; public class LiteralEmitter extends JSSubEmitter implements ISubEmitter<ILiteralNode> @@ -255,7 +252,7 @@ public class LiteralEmitter extends JSSubEmitter implements { //the close tag of the current element elementName = elementName.substring(1); - elementName = getQualifiedElementName(elementName, node); + elementName = getElementNameToEmit(elementName, node); if (elementStack.size() > 0) { indentPop(); @@ -275,7 +272,7 @@ public class LiteralEmitter extends JSSubEmitter implements indentPush(); writeNewline(ASEmitterTokens.COMMA); } - elementName = getQualifiedElementName(elementName, node); + elementName = getElementNameToEmit(elementName, node); elementStack.push(elementName); write("React.createElement"); write(ASEmitterTokens.PAREN_OPEN); @@ -421,35 +418,14 @@ public class LiteralEmitter extends JSSubEmitter implements write(ASEmitterTokens.SINGLE_QUOTE); } - private String getQualifiedElementName(String elementName, IASNode node) + private String getElementNameToEmit(String elementName, IASNode node) { - String firstChar = elementName.substring(0, 1); - boolean isHTMLTag = firstChar.toLowerCase().equals(firstChar); - if (isHTMLTag) + String qualifiedTypeName = JSXUtil.getQualifiedTypeForElementName(elementName, node); + if (qualifiedTypeName != null) { - return ASEmitterTokens.SINGLE_QUOTE.getToken() + elementName + ASEmitterTokens.SINGLE_QUOTE.getToken(); + return qualifiedTypeName; } - 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; + //it's a basic HTML tag + return ASEmitterTokens.SINGLE_QUOTE.getToken() + elementName + ASEmitterTokens.SINGLE_QUOTE.getToken(); } } http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/58f31971/compiler/src/main/java/org/apache/flex/compiler/internal/units/ASCompilationUnit.java ---------------------------------------------------------------------- diff --git a/compiler/src/main/java/org/apache/flex/compiler/internal/units/ASCompilationUnit.java b/compiler/src/main/java/org/apache/flex/compiler/internal/units/ASCompilationUnit.java index c44e95b..6dc8951 100644 --- a/compiler/src/main/java/org/apache/flex/compiler/internal/units/ASCompilationUnit.java +++ b/compiler/src/main/java/org/apache/flex/compiler/internal/units/ASCompilationUnit.java @@ -29,6 +29,8 @@ import java.util.List; import java.util.Set; import org.apache.flex.compiler.clients.ASC; +import org.apache.flex.compiler.common.DependencyType; +import org.apache.flex.compiler.common.IMetaInfo; import org.apache.flex.compiler.definitions.IDefinition; import org.apache.flex.compiler.filespecs.FileSpecification; import org.apache.flex.compiler.filespecs.IFileSpecification; @@ -41,6 +43,8 @@ import org.apache.flex.compiler.internal.scopes.ASFileScope; import org.apache.flex.compiler.internal.semantics.PostProcessStep; import org.apache.flex.compiler.internal.tree.as.ClassNode; import org.apache.flex.compiler.internal.tree.as.FileNode; +import org.apache.flex.compiler.internal.tree.as.FunctionNode; +import org.apache.flex.compiler.internal.tree.as.XMLLiteralNode; import org.apache.flex.compiler.internal.units.requests.ASFileScopeRequestResult; import org.apache.flex.compiler.internal.units.requests.SWFTagsRequestResult; import org.apache.flex.compiler.problems.ICompilerProblem; @@ -55,6 +59,7 @@ import org.apache.flex.compiler.units.requests.IOutgoingDependenciesRequestResul import org.apache.flex.compiler.units.requests.IRequest; import org.apache.flex.compiler.units.requests.ISWFTagsRequestResult; import org.apache.flex.compiler.units.requests.ISyntaxTreeRequestResult; +import org.apache.flex.utils.JSXUtil; import com.google.common.base.Strings; import com.google.common.collect.ImmutableSet; @@ -466,6 +471,7 @@ public class ASCompilationUnit extends CompilationUnitBase getABCBytesRequest().get(); updateEmbedCompilationUnitDependencies(fn.getEmbedNodes(), problems); + updateJSXDependencies(fn); IOutgoingDependenciesRequestResult result = new IOutgoingDependenciesRequestResult() { @@ -480,6 +486,50 @@ public class ASCompilationUnit extends CompilationUnitBase return result; } + /** + * Iterate through all methods with [JSX] metadata, adding the + * ICompilationUnit dependencies + * + * @throws InterruptedException + */ + private void updateJSXDependencies(IASNode node) throws InterruptedException + { + if (node instanceof FunctionNode) + { + FunctionNode functionNode = (FunctionNode) node; + for (IMetaInfo metaInfo : functionNode.getMetaInfos()) + { + if (metaInfo.getTagName().equals("JSX")) + { + //we need to parse XML in this function's body + functionNode.parseFunctionBody(new ArrayList<ICompilerProblem>()); + } + } + } + if (node instanceof XMLLiteralNode) + { + XMLLiteralNode xmlNode = (XMLLiteralNode) node; + CompilerProject project = getProject(); + ArrayList<String> qualifiedNames = new ArrayList<String>(); + JSXUtil.findQualifiedNamesInXMLLiteral(xmlNode, qualifiedNames); + for (String qualifiedName : qualifiedNames) + { + ICompilationUnit cu = project.resolveQNameToCompilationUnit(qualifiedName); + if (cu != null) + { + project.addDependency(this, cu, DependencyType.EXPRESSION, cu.getQualifiedNames().get(0)); + } + } + } + else + { + for (int i = 0, count = node.getChildCount(); i < count; i++) + { + updateJSXDependencies(node.getChild(i)); + } + } + } + @Override protected void removeAST() { http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/58f31971/compiler/src/main/java/org/apache/flex/utils/JSXUtil.java ---------------------------------------------------------------------- diff --git a/compiler/src/main/java/org/apache/flex/utils/JSXUtil.java b/compiler/src/main/java/org/apache/flex/utils/JSXUtil.java new file mode 100644 index 0000000..0e8940f --- /dev/null +++ b/compiler/src/main/java/org/apache/flex/utils/JSXUtil.java @@ -0,0 +1,129 @@ +/* + * + * 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.utils; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.flex.compiler.common.Multiname; +import org.apache.flex.compiler.internal.tree.as.XMLLiteralNode; +import org.apache.flex.compiler.tree.as.IASNode; +import org.apache.flex.compiler.tree.as.IImportNode; +import org.apache.flex.compiler.tree.as.ILiteralNode; +import org.apache.flex.compiler.tree.as.IScopedNode; + +/** + * Utilities for parsing XML in functions with [JSX] metadata. + */ +public class JSXUtil +{ + public static void findQualifiedNamesInXMLLiteral(XMLLiteralNode node, List<String> qualifiedNames) + { + int childCount = node.getContentsNode().getChildCount(); + for (int i = 0; i < childCount; i++) + { + IASNode child = node.getContentsNode().getChild(i); + if (child instanceof ILiteralNode) + { + ILiteralNode literalChild = (ILiteralNode) child; + if (literalChild.getLiteralType() == ILiteralNode.LiteralType.XML) + { + findQualifiedNamesInXMLLiteralChild(literalChild, qualifiedNames); + } + } + } + } + + private static void findQualifiedNamesInXMLLiteralChild(ILiteralNode node, List<String> qualifiedNames) + { + String value = node.getValue(); + while (true) + { + int index = value.indexOf("<"); + if (index == -1) + { + break; + } + value = value.substring(index + 1); + index = value.indexOf(">"); + int spaceIndex = value.indexOf(" "); + if (spaceIndex == -1) + { + spaceIndex = value.length(); + } + if (index == -1 || index > spaceIndex) + { + index = spaceIndex; + } + String elementName = value.substring(0, index); + if (elementName.endsWith("/")) + { + //strip the / from self-closing tags + elementName = elementName.substring(0, elementName.length() - 1); + } + //ignore end tags + if (!elementName.startsWith("/")) + { + String qualifiedElementName = getQualifiedTypeForElementName(elementName, node); + if (qualifiedElementName != null) + { + qualifiedNames.add(qualifiedElementName); + } + } + value = value.substring(index + 1); + } + } + + /** + * Finds the qualified type name for an <element> in JSX. Returns null if + * the element name is a basic HTML tag. + */ + public static String getQualifiedTypeForElementName(String elementName, IASNode node) + { + String firstChar = elementName.substring(0, 1); + boolean isHTMLTag = firstChar.toLowerCase().equals(firstChar); + if (isHTMLTag) + { + return null; + } + 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; + } +}