| /* |
| * |
| * 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.royale.compiler.internal.codegen.as; |
| |
| import java.io.FilterWriter; |
| import java.io.IOException; |
| import java.util.Collection; |
| import java.util.List; |
| |
| import org.apache.royale.compiler.codegen.IDocEmitter; |
| import org.apache.royale.compiler.codegen.IEmitter; |
| import org.apache.royale.compiler.codegen.IEmitterTokens; |
| import org.apache.royale.compiler.codegen.as.IASEmitter; |
| import org.apache.royale.compiler.common.ASModifier; |
| import org.apache.royale.compiler.common.IImportTarget; |
| import org.apache.royale.compiler.common.ModifiersSet; |
| import org.apache.royale.compiler.constants.IASKeywordConstants; |
| import org.apache.royale.compiler.definitions.IDefinition; |
| import org.apache.royale.compiler.definitions.IFunctionDefinition; |
| import org.apache.royale.compiler.definitions.IPackageDefinition; |
| import org.apache.royale.compiler.definitions.ITypeDefinition; |
| import org.apache.royale.compiler.definitions.IVariableDefinition; |
| import org.apache.royale.compiler.internal.codegen.js.utils.EmitterUtils; |
| import org.apache.royale.compiler.internal.tree.as.ChainedVariableNode; |
| import org.apache.royale.compiler.internal.tree.as.ContainerNode; |
| import org.apache.royale.compiler.internal.tree.as.FunctionNode; |
| import org.apache.royale.compiler.internal.tree.as.LabeledStatementNode; |
| import org.apache.royale.compiler.problems.ICompilerProblem; |
| import org.apache.royale.compiler.tree.ASTNodeID; |
| import org.apache.royale.compiler.tree.as.IASNode; |
| import org.apache.royale.compiler.tree.as.IAccessorNode; |
| import org.apache.royale.compiler.tree.as.IBinaryOperatorNode; |
| import org.apache.royale.compiler.tree.as.ICatchNode; |
| import org.apache.royale.compiler.tree.as.IClassNode; |
| import org.apache.royale.compiler.tree.as.IConditionalNode; |
| import org.apache.royale.compiler.tree.as.IContainerNode; |
| import org.apache.royale.compiler.tree.as.IContainerNode.ContainerType; |
| import org.apache.royale.compiler.tree.as.IDefinitionNode; |
| import org.apache.royale.compiler.tree.as.IDynamicAccessNode; |
| import org.apache.royale.compiler.tree.as.IEmbedNode; |
| import org.apache.royale.compiler.tree.as.IExpressionNode; |
| import org.apache.royale.compiler.tree.as.IForLoopNode; |
| import org.apache.royale.compiler.tree.as.IFunctionCallNode; |
| import org.apache.royale.compiler.tree.as.IFunctionNode; |
| import org.apache.royale.compiler.tree.as.IFunctionObjectNode; |
| import org.apache.royale.compiler.tree.as.IGetterNode; |
| import org.apache.royale.compiler.tree.as.IIdentifierNode; |
| import org.apache.royale.compiler.tree.as.IIfNode; |
| import org.apache.royale.compiler.tree.as.IImportNode; |
| import org.apache.royale.compiler.tree.as.IInterfaceNode; |
| import org.apache.royale.compiler.tree.as.IIterationFlowNode; |
| import org.apache.royale.compiler.tree.as.IKeywordNode; |
| import org.apache.royale.compiler.tree.as.ILanguageIdentifierNode; |
| import org.apache.royale.compiler.tree.as.ILiteralContainerNode; |
| import org.apache.royale.compiler.tree.as.ILiteralNode; |
| import org.apache.royale.compiler.tree.as.IMemberAccessExpressionNode; |
| import org.apache.royale.compiler.tree.as.INamespaceAccessExpressionNode; |
| import org.apache.royale.compiler.tree.as.INamespaceNode; |
| import org.apache.royale.compiler.tree.as.INumericLiteralNode; |
| import org.apache.royale.compiler.tree.as.IObjectLiteralValuePairNode; |
| import org.apache.royale.compiler.tree.as.IOperatorNode; |
| import org.apache.royale.compiler.tree.as.IPackageNode; |
| import org.apache.royale.compiler.tree.as.IParameterNode; |
| import org.apache.royale.compiler.tree.as.IReturnNode; |
| import org.apache.royale.compiler.tree.as.IScopedNode; |
| import org.apache.royale.compiler.tree.as.ISetterNode; |
| import org.apache.royale.compiler.tree.as.IStatementNode; |
| import org.apache.royale.compiler.tree.as.ISwitchNode; |
| import org.apache.royale.compiler.tree.as.ITerminalNode; |
| import org.apache.royale.compiler.tree.as.ITernaryOperatorNode; |
| import org.apache.royale.compiler.tree.as.IThrowNode; |
| import org.apache.royale.compiler.tree.as.ITryNode; |
| import org.apache.royale.compiler.tree.as.ITypeNode; |
| import org.apache.royale.compiler.tree.as.ITypedExpressionNode; |
| import org.apache.royale.compiler.tree.as.IUnaryOperatorNode; |
| import org.apache.royale.compiler.tree.as.IUseNamespaceNode; |
| import org.apache.royale.compiler.tree.as.IVariableExpressionNode; |
| import org.apache.royale.compiler.tree.as.IVariableNode; |
| import org.apache.royale.compiler.tree.as.IWhileLoopNode; |
| import org.apache.royale.compiler.tree.as.IWithNode; |
| import org.apache.royale.compiler.tree.metadata.IMetaTagNode; |
| import org.apache.royale.compiler.utils.ASNodeUtils; |
| import org.apache.royale.compiler.visitor.IBlockWalker; |
| import org.apache.royale.compiler.visitor.as.IASBlockWalker; |
| |
| /** |
| * The base implementation for an ActionScript emitter. |
| * |
| * @author Michael Schmalle |
| */ |
| public class ASEmitter implements IASEmitter, IEmitter |
| { |
| private final FilterWriter out; |
| |
| private IEmitter parentEmitter; |
| |
| public IEmitter getParentEmitter() |
| { |
| return parentEmitter; |
| } |
| |
| public void setParentEmitter(IEmitter value) |
| { |
| parentEmitter = value; |
| } |
| |
| private boolean bufferWrite; |
| |
| protected boolean isBufferWrite() |
| { |
| return bufferWrite; |
| } |
| |
| public void setBufferWrite(boolean value) |
| { |
| bufferWrite = value; |
| } |
| |
| private StringBuilder builder; |
| |
| protected StringBuilder getBuilder() |
| { |
| return builder; |
| } |
| |
| protected void setBuilder(StringBuilder sb) |
| { |
| builder = sb; |
| } |
| |
| protected void flushBuilder() |
| { |
| setBufferWrite(false); |
| write(builder.toString()); |
| builder.setLength(0); |
| } |
| |
| // (mschmalle) think about how this should be implemented, we can add our |
| // own problems to this, they don't just have to be parse problems |
| public List<ICompilerProblem> getProblems() |
| { |
| return walker.getErrors(); |
| } |
| |
| private int currentIndent = 0; |
| |
| protected int getCurrentIndent() |
| { |
| return currentIndent; |
| } |
| |
| protected void writeIndent() |
| { |
| write(ASEmitterTokens.INDENT); |
| } |
| |
| private IASBlockWalker walker; |
| |
| @Override |
| public IBlockWalker getWalker() |
| { |
| return walker; |
| } |
| |
| @Override |
| public void setWalker(IBlockWalker value) |
| { |
| walker = (IASBlockWalker) value; |
| } |
| |
| @Override |
| public IDocEmitter getDocEmitter() |
| { |
| return null; |
| } |
| |
| @Override |
| public void setDocEmitter(IDocEmitter value) |
| { |
| } |
| |
| private int currentLine = 0; |
| |
| protected int getCurrentLine() |
| { |
| return currentLine; |
| } |
| |
| private int currentColumn = 0; |
| |
| protected int getCurrentColumn() |
| { |
| return currentColumn; |
| } |
| |
| public ASEmitter(FilterWriter out) |
| { |
| this.out = out; |
| builder = new StringBuilder(); |
| } |
| |
| @Override |
| public String postProcess(String output) |
| { |
| return output; |
| } |
| |
| @Override |
| public void write(IEmitterTokens value) |
| { |
| write(value.getToken()); |
| } |
| |
| @Override |
| public void write(String value) |
| { |
| try |
| { |
| if (!bufferWrite) |
| { |
| if (parentEmitter != null) |
| { |
| parentEmitter.write(value); |
| } |
| else |
| { |
| int newLineCount = value.length() - value.replace("\n", "").length(); |
| currentLine += newLineCount; |
| if (newLineCount > 0) |
| { |
| currentColumn = value.length() - value.lastIndexOf("\n") - 1; |
| } |
| else |
| { |
| currentColumn += value.length(); |
| } |
| out.write(value); |
| } |
| } |
| else |
| { |
| builder.append(value); |
| } |
| } |
| catch (IOException e) |
| { |
| throw new RuntimeException(e); |
| } |
| } |
| |
| protected String getIndent(int numIndent) |
| { |
| final StringBuilder sb = new StringBuilder(); |
| for (int i = 0; i < numIndent; i++) |
| sb.append(ASEmitterTokens.INDENT.getToken()); |
| return sb.toString(); |
| } |
| |
| @Override |
| public void indentPush() |
| { |
| currentIndent++; |
| } |
| |
| @Override |
| public void indentPop() |
| { |
| currentIndent--; |
| } |
| |
| @Override |
| public void writeNewline() |
| { |
| write(ASEmitterTokens.NEW_LINE); |
| write(getIndent(currentIndent)); |
| } |
| |
| @Override |
| public void writeNewline(IEmitterTokens value) |
| { |
| writeNewline(value.getToken()); |
| } |
| |
| @Override |
| public void writeNewline(String value) |
| { |
| write(value); |
| writeNewline(); |
| } |
| |
| @Override |
| public void writeNewline(IEmitterTokens value, boolean pushIndent) |
| { |
| writeNewline(value.getToken(), pushIndent); |
| } |
| |
| @Override |
| public void writeNewline(String value, boolean pushIndent) |
| { |
| if (pushIndent) |
| indentPush(); |
| else |
| indentPop(); |
| write(value); |
| writeNewline(); |
| } |
| |
| public void writeSymbol(String value) |
| { |
| write(value); |
| } |
| |
| @Override |
| public void writeToken(IEmitterTokens value) |
| { |
| writeToken(value.getToken()); |
| } |
| |
| @Override |
| public void writeToken(String value) |
| { |
| write(value); |
| write(ASEmitterTokens.SPACE); |
| } |
| |
| //-------------------------------------------------------------------------- |
| // IPackageNode |
| //-------------------------------------------------------------------------- |
| |
| @Override |
| public void emitImport(IImportNode node) |
| { |
| IImportTarget target = node.getImportTarget(); |
| writeToken(ASEmitterTokens.IMPORT); |
| write(target.toString()); |
| } |
| |
| @Override |
| public void emitPackageHeader(IPackageDefinition definition) |
| { |
| write(ASEmitterTokens.PACKAGE); |
| |
| IPackageNode node = definition.getNode(); |
| String name = node.getQualifiedName(); |
| if (name != null && !name.equals("")) |
| { |
| write(ASEmitterTokens.SPACE); |
| getWalker().walk(node.getNameExpressionNode()); |
| } |
| |
| write(ASEmitterTokens.SPACE); |
| write(ASEmitterTokens.BLOCK_OPEN); |
| } |
| |
| @Override |
| public void emitPackageHeaderContents(IPackageDefinition definition) |
| { |
| } |
| |
| @Override |
| public void emitPackageContents(IPackageDefinition definition) |
| { |
| IPackageNode node = definition.getNode(); |
| ITypeNode tnode = EmitterUtils.findTypeNode(node); |
| if (tnode != null) |
| { |
| indentPush(); |
| writeNewline(); |
| getWalker().walk(tnode); // IClassNode | IInterfaceNode |
| } |
| } |
| |
| @Override |
| public void emitPackageFooter(IPackageDefinition definition) |
| { |
| indentPop(); |
| writeNewline(); |
| write(ASEmitterTokens.BLOCK_CLOSE); |
| } |
| |
| //-------------------------------------------------------------------------- |
| // |
| //-------------------------------------------------------------------------- |
| |
| @Override |
| public void emitClass(IClassNode node) |
| { |
| writeToken(node.getNamespace()); |
| |
| if (node.hasModifier(ASModifier.FINAL)) |
| { |
| writeToken(ASEmitterTokens.FINAL); |
| } |
| else if (node.hasModifier(ASModifier.DYNAMIC)) |
| { |
| writeToken(ASEmitterTokens.DYNAMIC); |
| } |
| |
| writeToken(ASEmitterTokens.CLASS); |
| getWalker().walk(node.getNameExpressionNode()); |
| write(ASEmitterTokens.SPACE); |
| |
| IExpressionNode bnode = node.getBaseClassExpressionNode(); |
| if (bnode != null) |
| { |
| writeToken(ASEmitterTokens.EXTENDS); |
| getWalker().walk(bnode); |
| write(ASEmitterTokens.SPACE); |
| } |
| |
| IExpressionNode[] inodes = node.getImplementedInterfaceNodes(); |
| final int ilen = inodes.length; |
| if (ilen != 0) |
| { |
| writeToken(ASEmitterTokens.IMPLEMENTS); |
| for (int i = 0; i < ilen; i++) |
| { |
| getWalker().walk(inodes[i]); |
| if (i < ilen - 1) |
| { |
| writeToken(ASEmitterTokens.COMMA); |
| } |
| } |
| write(ASEmitterTokens.SPACE); |
| } |
| |
| write(ASEmitterTokens.BLOCK_OPEN); |
| |
| // fields, methods, namespaces |
| final IDefinitionNode[] members = node.getAllMemberNodes(); |
| if (members.length > 0) |
| { |
| indentPush(); |
| writeNewline(); |
| |
| final int len = members.length; |
| int i = 0; |
| for (IDefinitionNode mnode : members) |
| { |
| getWalker().walk(mnode); |
| if (mnode.getNodeID() == ASTNodeID.VariableID) |
| { |
| write(ASEmitterTokens.SEMICOLON); |
| if (i < len - 1) |
| writeNewline(); |
| } |
| else if (mnode.getNodeID() == ASTNodeID.FunctionID) |
| { |
| if (i < len - 1) |
| writeNewline(); |
| } |
| else if (mnode.getNodeID() == ASTNodeID.GetterID |
| || mnode.getNodeID() == ASTNodeID.SetterID) |
| { |
| if (i < len - 1) |
| writeNewline(); |
| } |
| i++; |
| } |
| |
| indentPop(); |
| } |
| |
| writeNewline(); |
| write(ASEmitterTokens.BLOCK_CLOSE); |
| } |
| |
| @Override |
| public void emitInterface(IInterfaceNode node) |
| { |
| writeToken(node.getNamespace()); |
| |
| writeToken(ASEmitterTokens.INTERFACE); |
| getWalker().walk(node.getNameExpressionNode()); |
| write(ASEmitterTokens.SPACE); |
| |
| IExpressionNode[] inodes = node.getExtendedInterfaceNodes(); |
| final int ilen = inodes.length; |
| if (ilen != 0) |
| { |
| writeToken(ASEmitterTokens.EXTENDS); |
| for (int i = 0; i < ilen; i++) |
| { |
| getWalker().walk(inodes[i]); |
| if (i < ilen - 1) |
| { |
| writeToken(ASEmitterTokens.COMMA); |
| } |
| } |
| write(ASEmitterTokens.SPACE); |
| } |
| |
| write(ASEmitterTokens.BLOCK_OPEN); |
| |
| final IDefinitionNode[] members = node.getAllMemberDefinitionNodes(); |
| if (members.length > 0) |
| { |
| indentPush(); |
| writeNewline(); |
| |
| final int len = members.length; |
| int i = 0; |
| for (IDefinitionNode mnode : members) |
| { |
| getWalker().walk(mnode); |
| write(ASEmitterTokens.SEMICOLON); |
| if (i < len - 1) |
| writeNewline(); |
| i++; |
| } |
| |
| indentPop(); |
| } |
| |
| writeNewline(); |
| write(ASEmitterTokens.BLOCK_CLOSE); |
| } |
| |
| //-------------------------------------------------------------------------- |
| // |
| //-------------------------------------------------------------------------- |
| |
| @Override |
| public void emitVarDeclaration(IVariableNode node) |
| { |
| if (!(node instanceof ChainedVariableNode)) |
| { |
| emitMemberKeyword(node); |
| } |
| |
| emitDeclarationName(node); |
| emitType(node.getVariableTypeNode()); |
| |
| IExpressionNode avnode = node.getAssignedValueNode(); |
| if (avnode != null) |
| { |
| write(ASEmitterTokens.SPACE); |
| writeToken(ASEmitterTokens.EQUAL); |
| emitAssignedValue(avnode); |
| } |
| |
| if (!(node instanceof ChainedVariableNode)) |
| { |
| // check for chained variables |
| int len = node.getChildCount(); |
| for (int i = 0; i < len; i++) |
| { |
| IASNode child = node.getChild(i); |
| if (child instanceof ChainedVariableNode) |
| { |
| writeToken(ASEmitterTokens.COMMA); |
| emitVarDeclaration((IVariableNode) child); |
| } |
| } |
| } |
| |
| // the client such as IASBlockWalker is responsible for the |
| // semi-colon and newline handling |
| } |
| |
| //-------------------------------------------------------------------------- |
| // |
| //-------------------------------------------------------------------------- |
| |
| @Override |
| public void emitFieldDocumentation(IVariableNode node) |
| { |
| } |
| |
| @Override |
| public void emitField(IVariableNode node) |
| { |
| emitFieldDocumentation(node); |
| |
| IVariableDefinition definition = (IVariableDefinition) node |
| .getDefinition(); |
| |
| if (!(node instanceof ChainedVariableNode)) |
| { |
| emitNamespaceIdentifier(node); |
| emitModifiers(definition); |
| emitMemberKeyword(node); |
| } |
| |
| emitMemberName(node); |
| emitType(node.getVariableTypeNode()); |
| |
| IExpressionNode avnode = node.getAssignedValueNode(); |
| if (avnode != null) |
| { |
| write(ASEmitterTokens.SPACE); |
| writeToken(ASEmitterTokens.EQUAL); |
| emitAssignedValue(avnode); |
| } |
| |
| if (!(node instanceof ChainedVariableNode)) |
| { |
| // check for chained variables |
| int len = node.getChildCount(); |
| for (int i = 0; i < len; i++) |
| { |
| IASNode child = node.getChild(i); |
| if (child instanceof ChainedVariableNode) |
| { |
| writeToken(ASEmitterTokens.COMMA); |
| emitField((IVariableNode) child); |
| } |
| } |
| } |
| |
| // the client such as IASBlockWalker is responsible for the |
| // semi-colon and newline handling |
| } |
| |
| //-------------------------------------------------------------------------- |
| // |
| //-------------------------------------------------------------------------- |
| |
| @Override |
| public void emitMethodDocumentation(IFunctionNode node) |
| { |
| } |
| |
| @Override |
| public void emitMethod(IFunctionNode node) |
| { |
| // see below, this is temp, I don't want a bunch of duplicated code |
| // at them moment, subclasses can refine anyways, we are generalizing |
| if (node instanceof IGetterNode) |
| { |
| emitGetAccessorDocumentation((IGetterNode) node); |
| } |
| else if (node instanceof ISetterNode) |
| { |
| emitSetAccessorDocumentation((ISetterNode) node); |
| } |
| else |
| { |
| emitMethodDocumentation(node); |
| } |
| |
| FunctionNode fn = (FunctionNode) node; |
| fn.parseFunctionBody(getProblems()); |
| |
| IFunctionDefinition definition = node.getDefinition(); |
| |
| emitNamespaceIdentifier(node); |
| emitModifiers(definition); |
| emitMemberKeyword(node); |
| |
| // I'm cheating right here, I haven't "seen" the light |
| // on how to properly and efficiently deal with accessors since they are SO alike |
| // I don't want to lump them in with methods because implementations in the |
| // future need to know the difference without loopholes |
| if (node instanceof IAccessorNode) |
| { |
| emitAccessorKeyword(((IAccessorNode) node).getAccessorKeywordNode()); |
| } |
| |
| emitMemberName(node); |
| emitParameters(node.getParametersContainerNode()); |
| emitType(node.getReturnTypeNode()); |
| if (node.getParent().getParent().getNodeID() == ASTNodeID.ClassID) |
| { |
| emitMethodScope(node.getScopedNode()); |
| } |
| |
| // the client such as IASBlockWalker is responsible for the |
| // semi-colon and newline handling |
| } |
| |
| @Override |
| public void emitGetAccessorDocumentation(IGetterNode node) |
| { |
| } |
| |
| @Override |
| public void emitGetAccessor(IGetterNode node) |
| { |
| // just cheat for now, IGetterNode is a IFunctionNode |
| emitMethod(node); |
| } |
| |
| @Override |
| public void emitSetAccessorDocumentation(ISetterNode node) |
| { |
| } |
| |
| @Override |
| public void emitSetAccessor(ISetterNode node) |
| { |
| // just cheat for now, ISetterNode is a IFunctionNode |
| emitMethod(node); |
| } |
| |
| @Override |
| public void emitLocalNamedFunction(IFunctionNode node) |
| { |
| FunctionNode fnode = (FunctionNode) node; |
| write(ASEmitterTokens.FUNCTION); |
| write(ASEmitterTokens.SPACE); |
| write(fnode.getName()); |
| emitParameters(fnode.getParametersContainerNode()); |
| emitType(fnode.getTypeNode()); |
| emitFunctionScope(fnode.getScopedNode()); |
| } |
| |
| @Override |
| public void emitFunctionObject(IFunctionObjectNode node) |
| { |
| FunctionNode fnode = node.getFunctionNode(); |
| write(ASEmitterTokens.FUNCTION); |
| emitParameters(fnode.getParametersContainerNode()); |
| emitType(fnode.getTypeNode()); |
| emitFunctionScope(fnode.getScopedNode()); |
| } |
| |
| //-------------------------------------------------------------------------- |
| // |
| //-------------------------------------------------------------------------- |
| |
| @Override |
| public void emitNamespace(INamespaceNode node) |
| { |
| emitNamespaceIdentifier(node); |
| writeToken(ASEmitterTokens.NAMESPACE); |
| emitMemberName(node); |
| write(ASEmitterTokens.SPACE); |
| writeToken(ASEmitterTokens.EQUAL); |
| getWalker().walk(node.getNamespaceURINode()); |
| } |
| |
| //-------------------------------------------------------------------------- |
| // |
| //-------------------------------------------------------------------------- |
| |
| protected void emitNamespaceIdentifier(IDefinitionNode node) |
| { |
| String namespace = node.getNamespace(); |
| if (namespace != null |
| && !namespace.equals(IASKeywordConstants.INTERNAL)) |
| { |
| writeToken(namespace); |
| } |
| } |
| |
| protected void emitModifiers(IDefinition definition) |
| { |
| ModifiersSet modifierSet = definition.getModifiers(); |
| if (modifierSet.hasModifiers()) |
| { |
| for (ASModifier modifier : modifierSet.getAllModifiers()) |
| { |
| writeToken(modifier.toString()); |
| } |
| } |
| } |
| |
| public void emitMemberKeyword(IDefinitionNode node) |
| { |
| if (node instanceof IFunctionNode) |
| { |
| writeToken(ASEmitterTokens.FUNCTION); |
| } |
| else if (node instanceof IVariableNode) |
| { |
| writeToken(((IVariableNode) node).isConst() ? ASEmitterTokens.CONST |
| : ASEmitterTokens.VAR); |
| } |
| } |
| |
| protected void emitMemberName(IDefinitionNode node) |
| { |
| getWalker().walk(node.getNameExpressionNode()); |
| } |
| |
| public void emitDeclarationName(IDefinitionNode node) |
| { |
| getWalker().walk(node.getNameExpressionNode()); |
| } |
| |
| public void emitParameters(IContainerNode node) |
| { |
| write(ASEmitterTokens.PAREN_OPEN); |
| int len = node.getChildCount(); |
| for (int i = 0; i < len; i++) |
| { |
| IParameterNode parameterNode = (IParameterNode) node.getChild(i); |
| getWalker().walk(parameterNode); //emitParameter |
| if (i < len - 1) |
| { |
| writeToken(ASEmitterTokens.COMMA); |
| } |
| } |
| write(ASEmitterTokens.PAREN_CLOSE); |
| } |
| |
| @Override |
| public void emitParameter(IParameterNode node) |
| { |
| if (node.isRest()) |
| { |
| write(ASEmitterTokens.ELLIPSIS); |
| write(node.getName()); |
| } |
| else |
| { |
| getWalker().walk(node.getNameExpressionNode()); |
| write(ASEmitterTokens.COLON); |
| getWalker().walk(node.getVariableTypeNode()); |
| IExpressionNode anode = node.getAssignedValueNode(); |
| if (anode != null) |
| { |
| write(ASEmitterTokens.SPACE); |
| writeToken(ASEmitterTokens.EQUAL); |
| getWalker().walk(anode); |
| } |
| } |
| } |
| |
| protected void emitType(IExpressionNode node) |
| { |
| // TODO (mschmalle) node.getVariableTypeNode() will return "*" if undefined, what to use? |
| // or node.getReturnTypeNode() |
| if (node != null) |
| { |
| write(ASEmitterTokens.COLON); |
| getWalker().walk(node); |
| } |
| } |
| |
| protected void emitAssignedValue(IExpressionNode node) |
| { |
| if (node == null) |
| { |
| return; |
| } |
| getWalker().walk(node); |
| } |
| |
| @Override |
| public void emitFunctionBlockHeader(IFunctionNode node) |
| { |
| // nothing to do in AS |
| } |
| |
| public void emitMethodScope(IScopedNode node) |
| { |
| write(ASEmitterTokens.SPACE); |
| getWalker().walk(node); |
| } |
| |
| protected void emitAccessorKeyword(IKeywordNode node) |
| { |
| getWalker().walk(node); |
| write(ASEmitterTokens.SPACE); |
| } |
| |
| protected void emitFunctionScope(IScopedNode node) |
| { |
| emitMethodScope(node); |
| } |
| |
| //-------------------------------------------------------------------------- |
| // Statements |
| //-------------------------------------------------------------------------- |
| |
| @Override |
| public void emitStatement(IASNode node) |
| { |
| getWalker().walk(node); |
| // XXX (mschmalle) this should be in the after handler? |
| if (node.getParent().getNodeID() != ASTNodeID.LabledStatementID |
| && node.getNodeID() != ASTNodeID.ConfigBlockID |
| && !(node instanceof IStatementNode)) |
| { |
| write(ASEmitterTokens.SEMICOLON); |
| } |
| |
| if (!isLastStatement(node)) |
| writeNewline(); |
| } |
| |
| @Override |
| public void emitIf(IIfNode node) |
| { |
| IConditionalNode conditional = (IConditionalNode) node.getChild(0); |
| |
| IContainerNode xnode = (IContainerNode) conditional |
| .getStatementContentsNode(); |
| |
| writeToken(ASEmitterTokens.IF); |
| //write(SPACE); |
| write(ASEmitterTokens.PAREN_OPEN); |
| getWalker().walk(conditional.getChild(0)); // conditional expression |
| write(ASEmitterTokens.PAREN_CLOSE); |
| if (!isImplicit(xnode)) |
| write(ASEmitterTokens.SPACE); |
| |
| getWalker().walk(conditional.getChild(1)); // BlockNode |
| IConditionalNode[] nodes = node.getElseIfNodes(); |
| if (nodes.length > 0) |
| { |
| for (int i = 0; i < nodes.length; i++) |
| { |
| IConditionalNode enode = nodes[i]; |
| IContainerNode snode = (IContainerNode) enode |
| .getStatementContentsNode(); |
| |
| final boolean isImplicit = isImplicit(snode); |
| if (isImplicit) |
| writeNewline(); |
| else |
| write(ASEmitterTokens.SPACE); |
| |
| writeToken(ASEmitterTokens.ELSE); |
| writeToken(ASEmitterTokens.IF); |
| write(ASEmitterTokens.PAREN_OPEN); |
| getWalker().walk(enode.getChild(0)); |
| write(ASEmitterTokens.PAREN_CLOSE); |
| if (!isImplicit) |
| write(ASEmitterTokens.SPACE); |
| |
| getWalker().walk(enode.getChild(1)); // ConditionalNode |
| } |
| } |
| |
| ITerminalNode elseNode = node.getElseNode(); |
| if (elseNode != null) |
| { |
| IContainerNode cnode = (IContainerNode) elseNode.getChild(0); |
| // if an implicit if, add a newline with no space |
| final boolean isImplicit = isImplicit(cnode); |
| if (isImplicit) |
| writeNewline(); |
| else |
| write(ASEmitterTokens.SPACE); |
| write(ASEmitterTokens.ELSE); |
| if (!isImplicit) |
| write(ASEmitterTokens.SPACE); |
| |
| getWalker().walk(elseNode); // TerminalNode |
| } |
| } |
| |
| @Override |
| public void emitForEachLoop(IForLoopNode node) |
| { |
| IContainerNode xnode = (IContainerNode) node.getChild(1); |
| writeToken(ASEmitterTokens.FOR); |
| writeToken(ASEmitterTokens.EACH); |
| write(ASEmitterTokens.PAREN_OPEN); |
| |
| IContainerNode cnode = node.getConditionalsContainerNode(); |
| getWalker().walk(cnode.getChild(0)); |
| |
| write(ASEmitterTokens.PAREN_CLOSE); |
| if (!isImplicit(xnode)) |
| write(ASEmitterTokens.SPACE); |
| |
| getWalker().walk(node.getStatementContentsNode()); |
| } |
| |
| @Override |
| public void emitForLoop(IForLoopNode node) |
| { |
| IContainerNode xnode = (IContainerNode) node.getChild(1); |
| |
| writeToken(ASEmitterTokens.FOR); |
| write(ASEmitterTokens.PAREN_OPEN); |
| |
| IContainerNode cnode = node.getConditionalsContainerNode(); |
| final IASNode node0 = cnode.getChild(0); |
| if (node0.getNodeID() == ASTNodeID.Op_InID) |
| { |
| getWalker().walk(cnode.getChild(0)); |
| } |
| else |
| { |
| visitForBody(cnode); |
| } |
| |
| write(ASEmitterTokens.PAREN_CLOSE); |
| if (!isImplicit(xnode)) |
| write(ASEmitterTokens.SPACE); |
| |
| getWalker().walk(node.getStatementContentsNode()); |
| } |
| |
| @Override |
| public void emitSwitch(ISwitchNode node) |
| { |
| writeToken(ASEmitterTokens.SWITCH); |
| write(ASEmitterTokens.PAREN_OPEN); |
| getWalker().walk(node.getChild(0)); |
| writeToken(ASEmitterTokens.PAREN_CLOSE); |
| writeNewline(ASEmitterTokens.BLOCK_OPEN, true); |
| |
| IConditionalNode[] cnodes = ASNodeUtils.getCaseNodes(node); |
| ITerminalNode dnode = ASNodeUtils.getDefaultNode(node); |
| |
| for (int i = 0; i < cnodes.length; i++) |
| { |
| IConditionalNode casen = cnodes[i]; |
| IContainerNode cnode = (IContainerNode) casen.getChild(1); |
| writeToken(ASEmitterTokens.CASE); |
| getWalker().walk(casen.getConditionalExpressionNode()); |
| write(ASEmitterTokens.COLON); |
| if (!isImplicit(cnode)) |
| write(ASEmitterTokens.SPACE); |
| getWalker().walk(casen.getStatementContentsNode()); |
| if (i == cnodes.length - 1 && dnode == null) |
| { |
| indentPop(); |
| writeNewline(); |
| } |
| else |
| writeNewline(); |
| } |
| if (dnode != null) |
| { |
| IContainerNode cnode = (IContainerNode) dnode.getChild(0); |
| write(ASEmitterTokens.DEFAULT); |
| write(ASEmitterTokens.COLON); |
| if (!isImplicit(cnode)) |
| write(ASEmitterTokens.SPACE); |
| getWalker().walk(dnode); |
| indentPop(); |
| writeNewline(); |
| } |
| write(ASEmitterTokens.BLOCK_CLOSE); |
| } |
| |
| @Override |
| public void emitWhileLoop(IWhileLoopNode node) |
| { |
| IContainerNode cnode = (IContainerNode) node.getChild(1); |
| writeToken(ASEmitterTokens.WHILE); |
| write(ASEmitterTokens.PAREN_OPEN); |
| getWalker().walk(node.getConditionalExpressionNode()); |
| write(ASEmitterTokens.PAREN_CLOSE); |
| if (!isImplicit(cnode)) |
| write(ASEmitterTokens.SPACE); |
| getWalker().walk(node.getStatementContentsNode()); |
| } |
| |
| @Override |
| public void emitDoLoop(IWhileLoopNode node) |
| { |
| IContainerNode cnode = (IContainerNode) node.getChild(0); |
| write(ASEmitterTokens.DO); |
| if (!isImplicit(cnode)) |
| write(ASEmitterTokens.SPACE); |
| getWalker().walk(node.getStatementContentsNode()); |
| if (!isImplicit(cnode)) |
| write(ASEmitterTokens.SPACE); |
| else |
| writeNewline(); // TODO (mschmalle) there is something wrong here, block should NL |
| write(ASEmitterTokens.WHILE); |
| write(ASEmitterTokens.SPACE); |
| write(ASEmitterTokens.PAREN_OPEN); |
| getWalker().walk(node.getConditionalExpressionNode()); |
| write(ASEmitterTokens.PAREN_CLOSE); |
| write(ASEmitterTokens.SEMICOLON); |
| } |
| |
| @Override |
| public void emitWith(IWithNode node) |
| { |
| IContainerNode cnode = (IContainerNode) node.getChild(1); |
| writeToken(ASEmitterTokens.WITH); |
| write(ASEmitterTokens.PAREN_OPEN); |
| getWalker().walk(node.getTargetNode()); |
| write(ASEmitterTokens.PAREN_CLOSE); |
| if (!isImplicit(cnode)) |
| write(ASEmitterTokens.SPACE); |
| getWalker().walk(node.getStatementContentsNode()); |
| } |
| |
| @Override |
| public void emitThrow(IThrowNode node) |
| { |
| writeToken(ASEmitterTokens.THROW); |
| getWalker().walk(node.getThrownExpressionNode()); |
| } |
| |
| @Override |
| public void emitTry(ITryNode node) |
| { |
| writeToken(ASEmitterTokens.TRY); |
| getWalker().walk(node.getStatementContentsNode()); |
| for (int i = 0; i < node.getCatchNodeCount(); i++) |
| { |
| getWalker().walk(node.getCatchNode(i)); |
| } |
| ITerminalNode fnode = node.getFinallyNode(); |
| if (fnode != null) |
| { |
| write(ASEmitterTokens.SPACE); |
| writeToken(ASEmitterTokens.FINALLY); |
| getWalker().walk(fnode); |
| } |
| } |
| |
| @Override |
| public void emitCatch(ICatchNode node) |
| { |
| write(ASEmitterTokens.SPACE); |
| writeToken(ASEmitterTokens.CATCH); |
| write(ASEmitterTokens.PAREN_OPEN); |
| getWalker().walk(node.getCatchParameterNode()); |
| writeToken(ASEmitterTokens.PAREN_CLOSE); |
| getWalker().walk(node.getStatementContentsNode()); |
| } |
| |
| @Override |
| public void emitReturn(IReturnNode node) |
| { |
| write(ASEmitterTokens.RETURN); |
| IExpressionNode rnode = node.getReturnValueNode(); |
| if (rnode != null && rnode.getNodeID() != ASTNodeID.NilID) |
| { |
| write(ASEmitterTokens.SPACE); |
| getWalker().walk(rnode); |
| } |
| } |
| |
| //-------------------------------------------------------------------------- |
| // Expressions |
| //-------------------------------------------------------------------------- |
| |
| @Override |
| public void emitFunctionCall(IFunctionCallNode node) |
| { |
| if (node.isNewExpression()) |
| { |
| writeToken(ASEmitterTokens.NEW); |
| } |
| |
| getWalker().walk(node.getNameNode()); |
| |
| emitArguments(node.getArgumentsNode()); |
| } |
| |
| @Override |
| public void emitArguments(IContainerNode node) |
| { |
| write(ASEmitterTokens.PAREN_OPEN); |
| int len = node.getChildCount(); |
| for (int i = 0; i < len; i++) |
| { |
| IExpressionNode argumentNode = (IExpressionNode) node.getChild(i); |
| getWalker().walk(argumentNode); |
| if (i < len - 1) |
| { |
| writeToken(ASEmitterTokens.COMMA); |
| } |
| } |
| write(ASEmitterTokens.PAREN_CLOSE); |
| } |
| |
| //-------------------------------------------------------------------------- |
| // Operators |
| //-------------------------------------------------------------------------- |
| |
| @Override |
| public void emitAsOperator(IBinaryOperatorNode node) |
| { |
| getWalker().walk(node.getLeftOperandNode()); |
| write(ASEmitterTokens.SPACE); |
| writeToken(node.getOperator().getOperatorText()); |
| getWalker().walk(node.getRightOperandNode()); |
| } |
| |
| @Override |
| public void emitIsOperator(IBinaryOperatorNode node) |
| { |
| getWalker().walk(node.getLeftOperandNode()); |
| write(ASEmitterTokens.SPACE); |
| writeToken(node.getOperator().getOperatorText()); |
| getWalker().walk(node.getRightOperandNode()); |
| } |
| |
| @Override |
| public void emitBinaryOperator(IBinaryOperatorNode node) |
| { |
| if (ASNodeUtils.hasParenOpen(node)) |
| write(ASEmitterTokens.PAREN_OPEN); |
| getWalker().walk(node.getLeftOperandNode()); |
| 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); |
| } |
| |
| //-------------------------------------------------------------------------- |
| // Utility |
| //-------------------------------------------------------------------------- |
| |
| protected ITypeNode findTypeNode(IPackageNode node) |
| { |
| IScopedNode scope = node.getScopedNode(); |
| for (int i = 0; i < scope.getChildCount(); i++) |
| { |
| IASNode child = scope.getChild(i); |
| if (child instanceof ITypeNode) |
| return (ITypeNode) child; |
| } |
| return null; |
| } |
| |
| protected ITypeDefinition findType(Collection<IDefinition> definitions) |
| { |
| for (IDefinition definition : definitions) |
| { |
| if (definition instanceof ITypeDefinition) |
| return (ITypeDefinition) definition; |
| } |
| return null; |
| } |
| |
| //-------------------------------------------------------------------------- |
| // Static Utility |
| //-------------------------------------------------------------------------- |
| |
| protected static IFunctionNode getConstructor(IDefinitionNode[] members) |
| { |
| for (IDefinitionNode node : members) |
| { |
| if (node instanceof IFunctionNode) |
| { |
| IFunctionNode fnode = (IFunctionNode) node; |
| if (fnode.isConstructor()) |
| return fnode; |
| } |
| } |
| return null; |
| } |
| |
| protected static boolean isLastStatement(IASNode node) |
| { |
| return getChildIndex(node.getParent(), node) == node.getParent() |
| .getChildCount() - 1; |
| } |
| |
| // this is not fair that we have to do this if (i < len - 1) |
| private static int getChildIndex(IASNode parent, IASNode node) |
| { |
| final int len = parent.getChildCount(); |
| for (int i = 0; i < len; i++) |
| { |
| if (parent.getChild(i) == node) |
| return i; |
| } |
| return -1; |
| } |
| |
| protected static final boolean isImplicit(IContainerNode node) |
| { |
| return EmitterUtils.isImplicit(node); |
| } |
| |
| protected void visitForBody(IContainerNode node) |
| { |
| final IASNode node0 = node.getChild(0); |
| final IASNode node1 = node.getChild(1); |
| final IASNode node2 = node.getChild(2); |
| |
| // initializer |
| if (node0 != null) |
| { |
| getWalker().walk(node0); |
| write(ASEmitterTokens.SEMICOLON); |
| if (node1.getNodeID() != ASTNodeID.NilID) |
| write(ASEmitterTokens.SPACE); |
| } |
| // condition or target |
| if (node1 != null) |
| { |
| getWalker().walk(node1); |
| write(ASEmitterTokens.SEMICOLON); |
| if (node2.getNodeID() != ASTNodeID.NilID) |
| write(ASEmitterTokens.SPACE); |
| } |
| // iterator |
| if (node2 != null) |
| { |
| getWalker().walk(node2); |
| } |
| } |
| |
| @Override |
| public void emitLiteral(ILiteralNode node) |
| { |
| write(node.getValue(true)); |
| } |
| |
| @Override |
| public void emitLiteralContainer(ILiteralContainerNode node) |
| { |
| final ContainerNode cnode = node.getContentsNode(); |
| final ContainerType type = cnode.getContainerType(); |
| String postFix = ""; |
| |
| if (type == ContainerType.BRACES) |
| { |
| write(ASEmitterTokens.BLOCK_OPEN); |
| postFix = ASEmitterTokens.BLOCK_CLOSE.getToken(); |
| } |
| else if (type == ContainerType.BRACKETS) |
| { |
| write(ASEmitterTokens.SQUARE_OPEN); |
| postFix = ASEmitterTokens.SQUARE_CLOSE.getToken(); |
| } |
| else if (type == ContainerType.IMPLICIT) |
| { |
| // nothing to write, move along |
| } |
| else if (type == ContainerType.PARENTHESIS) |
| { |
| write(ASEmitterTokens.PAREN_OPEN); |
| postFix = ASEmitterTokens.PAREN_CLOSE.getToken(); |
| } |
| |
| final int len = cnode.getChildCount(); |
| for (int i = 0; i < len; i++) |
| { |
| IASNode child = cnode.getChild(i); |
| getWalker().walk(child); |
| if (i < len - 1) |
| writeToken(ASEmitterTokens.COMMA); |
| } |
| |
| if (postFix != "") |
| write(postFix); |
| } |
| |
| @Override |
| public void emitIdentifier(IIdentifierNode node) |
| { |
| write(node.getName()); |
| } |
| |
| @Override |
| public void emitNumericLiteral(INumericLiteralNode node) |
| { |
| write(node.getNumericValue().toString()); |
| } |
| |
| @Override |
| public void emitKeyword(IKeywordNode node) |
| { |
| write(node.getNodeID().getParaphrase()); |
| } |
| |
| @Override |
| public void emitIterationFlow(IIterationFlowNode node) |
| { |
| write(node.getKind().toString().toLowerCase()); |
| IIdentifierNode lnode = node.getLabelNode(); |
| if (lnode != null) |
| { |
| write(ASEmitterTokens.SPACE); |
| getWalker().walk(lnode); |
| } |
| } |
| |
| @Override |
| public void emitMemberAccessExpression(IMemberAccessExpressionNode node) |
| { |
| getWalker().walk(node.getLeftOperandNode()); |
| write(node.getOperator().getOperatorText()); |
| getWalker().walk(node.getRightOperandNode()); |
| } |
| |
| @Override |
| public void emitDynamicAccess(IDynamicAccessNode node) |
| { |
| getWalker().walk(node.getLeftOperandNode()); |
| write(ASEmitterTokens.SQUARE_OPEN); |
| getWalker().walk(node.getRightOperandNode()); |
| write(ASEmitterTokens.SQUARE_CLOSE); |
| } |
| |
| @Override |
| public void emitTypedExpression(ITypedExpressionNode node) |
| { |
| getWalker().walk(node.getCollectionNode()); |
| write(ASEmitterTokens.MEMBER_ACCESS); |
| write(ASEmitterTokens.LESS_THAN); |
| getWalker().walk(node.getTypeNode()); |
| write(ASEmitterTokens.GREATER_THAN); |
| } |
| |
| @Override |
| public void emitVariableExpression(IVariableExpressionNode node) |
| { |
| getWalker().walk(node.getTargetVariable()); |
| } |
| |
| @Override |
| public void emitTernaryOperator(ITernaryOperatorNode node) |
| { |
| if (ASNodeUtils.hasParenOpen((IOperatorNode) node)) |
| write(ASEmitterTokens.PAREN_OPEN); |
| getWalker().walk(node.getConditionalNode()); |
| write(ASEmitterTokens.SPACE); |
| writeToken(ASEmitterTokens.TERNARY); |
| getWalker().walk(node.getLeftOperandNode()); |
| write(ASEmitterTokens.SPACE); |
| writeToken(ASEmitterTokens.COLON); |
| getWalker().walk(node.getRightOperandNode()); |
| if (ASNodeUtils.hasParenClose((IOperatorNode) node)) |
| write(ASEmitterTokens.PAREN_CLOSE); |
| } |
| |
| @Override |
| public void emitObjectLiteralValuePair(IObjectLiteralValuePairNode node) |
| { |
| getWalker().walk(node.getNameNode()); |
| write(ASEmitterTokens.COLON); |
| getWalker().walk(node.getValueNode()); |
| } |
| |
| @Override |
| public void emitLabelStatement(LabeledStatementNode node) |
| { |
| writeToken(node.getLabel()); |
| writeToken(ASEmitterTokens.COLON); |
| getWalker().walk(node.getLabeledStatement()); |
| } |
| |
| @Override |
| public void emitNamespaceAccessExpression( |
| INamespaceAccessExpressionNode node) |
| { |
| getWalker().walk(node.getLeftOperandNode()); |
| write(node.getOperator().getOperatorText()); |
| getWalker().walk(node.getRightOperandNode()); |
| } |
| |
| @Override |
| public void emitUnaryOperator(IUnaryOperatorNode node) |
| { |
| if (ASNodeUtils.hasParenOpen(node)) |
| write(ASEmitterTokens.PAREN_OPEN); |
| |
| if (node.getNodeID() == ASTNodeID.Op_PreIncrID |
| || node.getNodeID() == ASTNodeID.Op_PreDecrID |
| || node.getNodeID() == ASTNodeID.Op_BitwiseNotID |
| || node.getNodeID() == ASTNodeID.Op_LogicalNotID |
| || node.getNodeID() == ASTNodeID.Op_SubtractID |
| || node.getNodeID() == ASTNodeID.Op_AddID) |
| { |
| write(node.getOperator().getOperatorText()); |
| IExpressionNode opNode = node.getOperandNode(); |
| getWalker().walk(opNode); |
| } |
| |
| else if (node.getNodeID() == ASTNodeID.Op_PostIncrID |
| || node.getNodeID() == ASTNodeID.Op_PostDecrID) |
| { |
| getWalker().walk(node.getOperandNode()); |
| write(node.getOperator().getOperatorText()); |
| } |
| else if (node.getNodeID() == ASTNodeID.Op_DeleteID |
| || node.getNodeID() == ASTNodeID.Op_VoidID) |
| { |
| writeToken(node.getOperator().getOperatorText()); |
| getWalker().walk(node.getOperandNode()); |
| } |
| else if (node.getNodeID() == ASTNodeID.Op_TypeOfID) |
| { |
| write(node.getOperator().getOperatorText()); |
| write(ASEmitterTokens.PAREN_OPEN); |
| getWalker().walk(node.getOperandNode()); |
| write(ASEmitterTokens.PAREN_CLOSE); |
| } |
| |
| if (ASNodeUtils.hasParenClose(node)) |
| write(ASEmitterTokens.PAREN_CLOSE); |
| } |
| |
| @Override |
| public void emitLanguageIdentifier(ILanguageIdentifierNode node) |
| { |
| if (node.getKind() == ILanguageIdentifierNode.LanguageIdentifierKind.ANY_TYPE) |
| { |
| write(ASEmitterTokens.ANY_TYPE); |
| } |
| else if (node.getKind() == ILanguageIdentifierNode.LanguageIdentifierKind.REST) |
| { |
| write(ASEmitterTokens.ELLIPSIS); |
| } |
| else if (node.getKind() == ILanguageIdentifierNode.LanguageIdentifierKind.SUPER) |
| { |
| write(ASEmitterTokens.SUPER); |
| } |
| else if (node.getKind() == ILanguageIdentifierNode.LanguageIdentifierKind.THIS) |
| { |
| write(ASEmitterTokens.THIS); |
| } |
| else if (node.getKind() == ILanguageIdentifierNode.LanguageIdentifierKind.VOID) |
| { |
| write(ASEmitterTokens.VOID); |
| } |
| } |
| |
| @Override |
| public void emitMetaTag(IMetaTagNode node) |
| { |
| } |
| |
| @Override |
| public void emitEmbed(IEmbedNode node) |
| { |
| } |
| |
| @Override |
| public void emitContainer(IContainerNode node) |
| { |
| } |
| |
| @Override |
| public void emitE4XFilter(IMemberAccessExpressionNode node) |
| { |
| // ToDo (erikdebruin) |
| } |
| |
| @Override |
| public void emitUseNamespace(IUseNamespaceNode node) |
| { |
| // ToDo (erikdebruin) |
| } |
| |
| @Override |
| public void emitBlockOpen(IContainerNode node) |
| { |
| write(ASEmitterTokens.BLOCK_OPEN); |
| } |
| |
| @Override |
| public void emitBlockClose(IContainerNode node) |
| { |
| write(ASEmitterTokens.BLOCK_CLOSE); |
| } |
| |
| @Override |
| public String stringifyNode(IASNode node) |
| { |
| boolean oldBufferWrite = isBufferWrite(); |
| StringBuilder oldBuilder = this.builder; |
| this.builder = new StringBuilder(); |
| setBufferWrite(true); |
| getWalker().walk(node); |
| String result = getBuilder().toString(); |
| getBuilder().setLength(0); |
| this.builder = oldBuilder; |
| setBufferWrite(oldBufferWrite); |
| return result; |
| } |
| } |