Added FlexJS JS emitter and backend In order to be able to handle FlexJS specific JS output, a new emitter and supporting files are added.
Signed-off-by: Erik de Bruin <[email protected]> Project: http://git-wip-us.apache.org/repos/asf/flex-falcon/repo Commit: http://git-wip-us.apache.org/repos/asf/flex-falcon/commit/38ca8a6c Tree: http://git-wip-us.apache.org/repos/asf/flex-falcon/tree/38ca8a6c Diff: http://git-wip-us.apache.org/repos/asf/flex-falcon/diff/38ca8a6c Branch: refs/heads/develop Commit: 38ca8a6c0bea2f01d209ca5d5c5dbab1472b84e3 Parents: 43e9b3c Author: Erik de Bruin <[email protected]> Authored: Wed Mar 27 16:26:55 2013 +0100 Committer: Erik de Bruin <[email protected]> Committed: Wed Mar 27 16:29:59 2013 +0100 ---------------------------------------------------------------------- .../codegen/js/flexjs/IJSFlexJSEmitter.java | 30 ++ .../codegen/js/flexjs/JSFlexJSEmitter.java | 368 +++++++++++++++ .../internal/driver/js/flexjs/FlexJSBackend.java | 42 ++ 3 files changed, 440 insertions(+), 0 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/38ca8a6c/compiler.jx/src/org/apache/flex/compiler/codegen/js/flexjs/IJSFlexJSEmitter.java ---------------------------------------------------------------------- diff --git a/compiler.jx/src/org/apache/flex/compiler/codegen/js/flexjs/IJSFlexJSEmitter.java b/compiler.jx/src/org/apache/flex/compiler/codegen/js/flexjs/IJSFlexJSEmitter.java new file mode 100644 index 0000000..038c5ce --- /dev/null +++ b/compiler.jx/src/org/apache/flex/compiler/codegen/js/flexjs/IJSFlexJSEmitter.java @@ -0,0 +1,30 @@ +/* + * + * 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.codegen.js.flexjs; + +import org.apache.flex.compiler.codegen.js.goog.IJSGoogEmitter; + +/** + * @author Erik de Bruin + */ +public interface IJSFlexJSEmitter extends IJSGoogEmitter +{ + +} http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/38ca8a6c/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/flexjs/JSFlexJSEmitter.java ---------------------------------------------------------------------- diff --git a/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/flexjs/JSFlexJSEmitter.java b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/flexjs/JSFlexJSEmitter.java new file mode 100644 index 0000000..dd4d137 --- /dev/null +++ b/compiler.jx/src/org/apache/flex/compiler/internal/codegen/js/flexjs/JSFlexJSEmitter.java @@ -0,0 +1,368 @@ +/* + * + * 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 java.io.FilterWriter; + +import org.apache.flex.compiler.codegen.js.flexjs.IJSFlexJSEmitter; +import org.apache.flex.compiler.common.ASModifier; +import org.apache.flex.compiler.constants.IASLanguageConstants; +import org.apache.flex.compiler.definitions.IDefinition; +import org.apache.flex.compiler.definitions.IFunctionDefinition; +import org.apache.flex.compiler.definitions.ITypeDefinition; +import org.apache.flex.compiler.internal.codegen.as.ASEmitterTokens; +import org.apache.flex.compiler.internal.codegen.js.JSEmitterTokens; +import org.apache.flex.compiler.internal.codegen.js.goog.JSGoogEmitter; +import org.apache.flex.compiler.internal.codegen.js.goog.JSGoogEmitterTokens; +import org.apache.flex.compiler.internal.definitions.AccessorDefinition; +import org.apache.flex.compiler.internal.tree.as.BinaryOperatorAssignmentNode; +import org.apache.flex.compiler.internal.tree.as.FunctionCallNode; +import org.apache.flex.compiler.internal.tree.as.FunctionNode; +import org.apache.flex.compiler.projects.ICompilerProject; +import org.apache.flex.compiler.tree.ASTNodeID; +import org.apache.flex.compiler.tree.as.IASNode; +import org.apache.flex.compiler.tree.as.IAccessorNode; +import org.apache.flex.compiler.tree.as.IBinaryOperatorNode; +import org.apache.flex.compiler.tree.as.IClassNode; +import org.apache.flex.compiler.tree.as.IDefinitionNode; +import org.apache.flex.compiler.tree.as.IExpressionNode; +import org.apache.flex.compiler.tree.as.IFunctionCallNode; +import org.apache.flex.compiler.tree.as.IFunctionNode; +import org.apache.flex.compiler.tree.as.IGetterNode; +import org.apache.flex.compiler.tree.as.IIdentifierNode; +import org.apache.flex.compiler.tree.as.IMemberAccessExpressionNode; +import org.apache.flex.compiler.tree.as.ISetterNode; +import org.apache.flex.compiler.utils.ASNodeUtils; + +/** + * Concrete implementation of the 'goog' JavaScript production. + * + * @author Michael Schmalle + * @author Erik de Bruin + */ +public class JSFlexJSEmitter extends JSGoogEmitter implements IJSFlexJSEmitter +{ + + public JSFlexJSEmitter(FilterWriter out) + { + super(out); + } + + @Override + protected void emitAccessors(IAccessorNode node) + { + if (node.getNodeID() == ASTNodeID.GetterID) + { + emitGetAccessor((IGetterNode) node); + } + else if (node.getNodeID() == ASTNodeID.SetterID) + { + emitSetAccessor((ISetterNode) node); + } + } + + @Override + public void emitIdentifier(IIdentifierNode node) + { + ICompilerProject project = getWalker().getProject(); + + IClassNode cnode = (IClassNode) node + .getAncestorOfType(IClassNode.class); + + IDefinition def = ((IIdentifierNode) node).resolve(project); + + ITypeDefinition type = ((IIdentifierNode) node).resolveType(project); + + IASNode pnode = node.getParent(); + ASTNodeID inode = pnode.getNodeID(); + + boolean writeSelf = false; + if (cnode != null) + { + IDefinitionNode[] members = cnode.getAllMemberNodes(); + for (IDefinitionNode mnode : members) + { + if ((type != null && type.getQualifiedName().equalsIgnoreCase( + IASLanguageConstants.Function)) + || (def != null && def.getQualifiedName() + .equalsIgnoreCase(mnode.getQualifiedName()))) + { + if (!(pnode instanceof FunctionNode) + && inode != ASTNodeID.MemberAccessExpressionID) + { + writeSelf = true; + break; + } + else if (inode == ASTNodeID.MemberAccessExpressionID + && !def.isStatic()) + { + String tname = type.getQualifiedName(); + writeSelf = !tname.equalsIgnoreCase(cnode + .getQualifiedName()) + && !tname.equals(IASLanguageConstants.Function); + break; + } + } + } + } + + // XXX (erikdebruin) I desperately needed a way to bypass the addition + // of the 'self' prefix when running the tests... Or + // I'd have to put the prefix in ~150 asserts! + boolean isRunningInTestMode = cnode != null + && cnode.getQualifiedName().equalsIgnoreCase("A"); + + if (writeSelf && !isRunningInTestMode) + { + write(JSGoogEmitterTokens.SELF); + write(ASEmitterTokens.MEMBER_ACCESS); + } + else + { + String pname = (type != null) ? type.getPackageName() : ""; + if (cnode != null + && pname != "" + && !pname.equalsIgnoreCase(cnode.getPackageName()) + && inode != ASTNodeID.ArgumentID + && inode != ASTNodeID.VariableID + && inode != ASTNodeID.TypedExpressionID) + { + write(pname); + write(ASEmitterTokens.MEMBER_ACCESS); + } + } + + if (def instanceof AccessorDefinition) + { + IASNode anode = node + .getAncestorOfType(BinaryOperatorAssignmentNode.class); + + boolean isLeftSide = anode != null + && (pnode.equals(anode.getChild(0)) || node.equals(anode + .getChild(0))); + + write((anode != null && isLeftSide) ? "set_" : "get_"); + write(node.getName()); + write(ASEmitterTokens.PAREN_OPEN); + + IExpressionNode rightSide = null; + + if (anode != null) + { + if (isLeftSide) + { + rightSide = ((BinaryOperatorAssignmentNode) anode) + .getRightOperandNode(); + + getWalker().walk(rightSide); + } + else + { + rightSide = ((IBinaryOperatorNode) pnode) + .getRightOperandNode(); + } + } + + write(ASEmitterTokens.PAREN_CLOSE); + + if (anode != null + && !isLeftSide && pnode instanceof IBinaryOperatorNode + && !(pnode instanceof IMemberAccessExpressionNode)) + { + rightSide = ((IBinaryOperatorNode) pnode).getRightOperandNode(); + + if (rightSide != null) + { + write(ASEmitterTokens.SPACE); + + writeToken(((IBinaryOperatorNode) pnode).getOperator() + .getOperatorText()); + + getWalker().walk(rightSide); + } + } + } + else + { + write(node.getName()); + } + } + + @Override + protected void emitSuperCall(IASNode node, String type) + { + IFunctionNode fnode = (node instanceof IFunctionNode) ? (IFunctionNode) node + : null; + IFunctionCallNode fcnode = (node instanceof IFunctionCallNode) ? (FunctionCallNode) node + : null; + + if (type == CONSTRUCTOR_EMPTY) + { + indentPush(); + writeNewline(); + indentPop(); + } + else if (type == SUPER_FUNCTION_CALL) + { + if (fnode == null) + fnode = (IFunctionNode) fcnode + .getAncestorOfType(IFunctionNode.class); + } + + write(JSGoogEmitterTokens.GOOG_BASE); + write(ASEmitterTokens.PAREN_OPEN); + write(ASEmitterTokens.THIS); + + if (fnode != null && !fnode.isConstructor()) + { + writeToken(ASEmitterTokens.COMMA); + write(ASEmitterTokens.SINGLE_QUOTE); + if (fnode.getNodeID() == ASTNodeID.GetterID) + write("get_"); + else if (fnode.getNodeID() == ASTNodeID.SetterID) + write("set_"); + + write(fnode.getName()); + write(ASEmitterTokens.SINGLE_QUOTE); + } + + IASNode[] anodes = null; + boolean writeArguments = false; + if (fcnode != null) + { + anodes = fcnode.getArgumentNodes(); + + writeArguments = anodes.length > 0; + } + else if (fnode.isConstructor()) + { + anodes = fnode.getParameterNodes(); + + writeArguments = (anodes != null && anodes.length > 0); + } + + if (writeArguments) + { + int len = anodes.length; + for (int i = 0; i < len; i++) + { + writeToken(ASEmitterTokens.COMMA); + + getWalker().walk(anodes[i]); + } + } + + write(ASEmitterTokens.PAREN_CLOSE); + + if (type == CONSTRUCTOR_FULL) + { + write(ASEmitterTokens.SEMICOLON); + writeNewline(); + } + else if (type == CONSTRUCTOR_EMPTY) + { + write(ASEmitterTokens.SEMICOLON); + } + } + + @Override + public void emitBinaryOperator(IBinaryOperatorNode node) + { + ASTNodeID id = node.getNodeID(); + if (id == ASTNodeID.Op_IsID + || id == ASTNodeID.Op_AsID || id == ASTNodeID.Op_InID + || id == ASTNodeID.Op_LogicalAndAssignID + || id == ASTNodeID.Op_LogicalOrAssignID) + { + super.emitBinaryOperator(node); + } + else + { + IExpressionNode leftSide = node.getLeftOperandNode(); + + IExpressionNode property = null; + int leftSideChildCount = leftSide.getChildCount(); + if (leftSideChildCount > 0) + property = (IExpressionNode) leftSide + .getChild(leftSideChildCount - 1); + else + property = leftSide; + + IDefinition def = null; + if (property instanceof IIdentifierNode) + def = ((IIdentifierNode) property).resolve(getWalker() + .getProject()); + + if (def instanceof AccessorDefinition) + { + getWalker().walk(leftSide); + } + 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); + } + } + } + + @Override + protected void emitObjectDefineProperty(IAccessorNode node) + { + /* + Class.prototype.get_property = function() + { + // body; + }; + */ + + FunctionNode fn = (FunctionNode) node; + fn.parseFunctionBody(problems); + + IFunctionDefinition definition = node.getDefinition(); + ITypeDefinition type = (ITypeDefinition) definition.getParent(); + write(type.getQualifiedName()); + if (!node.hasModifier(ASModifier.STATIC)) + { + write(ASEmitterTokens.MEMBER_ACCESS); + write(JSEmitterTokens.PROTOTYPE); + } + + write(ASEmitterTokens.MEMBER_ACCESS); + write((node instanceof IGetterNode) ? "get_" : "set_"); + writeToken(node.getName()); + writeToken(ASEmitterTokens.EQUAL); + write(ASEmitterTokens.FUNCTION); + emitParamters(node.getParameterNodes()); + //writeNewline(); + emitMethodScope(node.getScopedNode()); + } +} http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/38ca8a6c/compiler.jx/src/org/apache/flex/compiler/internal/driver/js/flexjs/FlexJSBackend.java ---------------------------------------------------------------------- diff --git a/compiler.jx/src/org/apache/flex/compiler/internal/driver/js/flexjs/FlexJSBackend.java b/compiler.jx/src/org/apache/flex/compiler/internal/driver/js/flexjs/FlexJSBackend.java new file mode 100644 index 0000000..9a7d92e --- /dev/null +++ b/compiler.jx/src/org/apache/flex/compiler/internal/driver/js/flexjs/FlexJSBackend.java @@ -0,0 +1,42 @@ +/* + * + * 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.driver.js.flexjs; + +import java.io.FilterWriter; + +import org.apache.flex.compiler.codegen.js.IJSEmitter; +import org.apache.flex.compiler.internal.codegen.js.flexjs.JSFlexJSEmitter; +import org.apache.flex.compiler.internal.driver.js.goog.GoogBackend; + +/** + * @author Erik de Bruin + */ +public class FlexJSBackend extends GoogBackend +{ + + @Override + public IJSEmitter createEmitter(FilterWriter out) + { + IJSEmitter emitter = new JSFlexJSEmitter(out); + emitter.setDocEmitter(createDocEmitter(emitter)); + return emitter; + } + +}
