/* * Copyright 2008 Google Inc. * * Licensed 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 com.google.template.soy.soytree; import com.google.common.collect.ImmutableList; import com.google.template.soy.basetree.CopyState; import com.google.template.soy.basetree.Node; import com.google.template.soy.basetree.ParentNode; import com.google.template.soy.data.SanitizedContent.ContentKind; import com.google.template.soy.exprtree.ExprRootNode; import com.google.template.soy.exprtree.VarDefn; import javax.annotation.Nullable; /** * This class defines the base interface for a node in the parse tree, as well as a number of * subinterfaces that extend the base interface in various aspects. Every concrete node implements * some subset of these interfaces. * * <p>The top level definition is the base node interface. * * <p>Important: Do not use outside of Soy code (treat as superpackage-private). * */ public interface SoyNode extends Node { /** * Enum of specific node kinds (corresponding to specific node types). * * <p>Important: Do not use outside of Soy code (treat as superpackage-private). */ enum Kind { SOY_FILE_SET_NODE, SOY_FILE_NODE, TEMPLATE_BASIC_NODE, TEMPLATE_DELEGATE_NODE, RAW_TEXT_NODE, GOOG_MSG_DEF_NODE, GOOG_MSG_REF_NODE, MSG_FALLBACK_GROUP_NODE, MSG_NODE, MSG_PLURAL_NODE, MSG_PLURAL_CASE_NODE, MSG_PLURAL_DEFAULT_NODE, MSG_SELECT_NODE, MSG_SELECT_CASE_NODE, MSG_SELECT_DEFAULT_NODE, MSG_PLACEHOLDER_NODE, MSG_HTML_TAG_NODE, PRINT_NODE, PRINT_DIRECTIVE_NODE, XID_NODE, CSS_NODE, LET_VALUE_NODE, LET_CONTENT_NODE, IF_NODE, IF_COND_NODE, IF_ELSE_NODE, SWITCH_NODE, SWITCH_CASE_NODE, SWITCH_DEFAULT_NODE, FOREACH_NODE, FOREACH_NONEMPTY_NODE, FOREACH_IFEMPTY_NODE, FOR_NODE, CALL_BASIC_NODE, CALL_DELEGATE_NODE, CALL_PARAM_VALUE_NODE, CALL_PARAM_CONTENT_NODE, // These Node types are created by the com.google.template.soy.html package. RawTextNodes that // appear in an HTML or attribute context are transformed into these node types. In general, // passes that do not output generated code should not need to worry about these types, other // than treating them as generic parent nodes that may contain descendants they are interested // in. INCREMENTAL_HTML_OPEN_TAG, INCREMENTAL_HTML_CLOSE_TAG, INCREMENTAL_HTML_ATTRIBUTE, // TODO(lukes): These nodes are created by the main parser and should eventually subsume the // usecases of the incremental dom nodes defined above (and also MsgHtmlTagNode). But for the // time being we maintain 2 such set of nodes while under development. HTML_OPEN_TAG_NODE, HTML_CLOSE_TAG_NODE, HTML_ATTRIBUTE_NODE, HTML_ATTRIBUTE_VALUE_NODE, LOG_NODE, DEBUGGER_NODE, } /** Returns this node's kind (corresponding to this node's specific type). */ Kind getKind(); /** * Sets this node's id. * * <p>Important: The id should already be set during construction, so this method should only be * used during cloning. * * @param id The new id for this node. */ void setId(int id); /** Returns this node's id. */ int getId(); @Override ParentSoyNode<?> getParent(); /** * {@inheritDoc} * * <p>The copied nodes will have the same ids as the original nodes. If you need to copy a subtree * with new ids assigned to the copied nodes, use {@link SoyTreeUtils#cloneWithNewIds}. */ @Override SoyNode copy(CopyState copyState); // ----------------------------------------------------------------------------------------------- /** A node in a Soy parse tree that may be a parent. */ interface ParentSoyNode<N extends SoyNode> extends SoyNode, ParentNode<N> {} // ----------------------------------------------------------------------------------------------- /** * A node that represents the top of a split-level structure in the parse tree. This indicates * there are special structural requirements on its immediate children (e.g. IfNode may only have * IfCondNode and IfElseNode as children). * * <p>Includes nodes such as SoyFileSetNode, SoyFileNode, IfNode, SwitchNode, ForeachNode, * CallNode, etc. * * <p>During optimization, the immediate children should never be moved, but lower descendants may * be freely moved (either moved within the node's subtree or moved outside of the node's * subtree). */ interface SplitLevelTopNode<N extends SoyNode> extends ParentSoyNode<N> {} // ----------------------------------------------------------------------------------------------- /** * A node that can legally appear as the direct child of some block node (doesn't necessarily have * to be legal as the direct child of a template). To put it another way, a node that can legally * appear as the sibling of a RawTextNode or PrintNode. */ interface StandaloneNode extends SoyNode { @Override ParentSoyNode<StandaloneNode> getParent(); } // ----------------------------------------------------------------------------------------------- /** A node that represents a template block. */ interface BlockNode extends ParentSoyNode<StandaloneNode> {} // ----------------------------------------------------------------------------------------------- /** A node that represents a specific Soy command. */ interface CommandNode extends SoyNode { /** Returns the Soy command name. */ String getCommandName(); /** Returns the command text (may be the empty string). */ String getCommandText(); /** * Builds a Soy tag string that could be the Soy tag for this node. Note that this may not * necessarily be the actual original Soy tag, but a (sort of) canonical equivalent. * @return A Soy tag string that could be the Soy tag for this node. */ String getTagString(); } // ----------------------------------------------------------------------------------------------- /** A node that represents a Soy command that encloses a template block. */ interface BlockCommandNode extends CommandNode, BlockNode {} // ----------------------------------------------------------------------------------------------- /** A node that represents an independent unit of rendering. */ interface RenderUnitNode extends BlockCommandNode { /** * Returns the content kind for strict autoescape, or null if not specified or not applicable. */ @Nullable ContentKind getContentKind(); } // ----------------------------------------------------------------------------------------------- /** A node that represents a specific Soy statement. */ interface StatementNode extends StandaloneNode {} // ----------------------------------------------------------------------------------------------- /** * A node that represents a block of Soy code that is conditionally executed. During optimization, * descendants should generally never be moved outside of the subtree of such a node. We make an * exception for LoopNodes because we don't want to lose the ability to pull invariants out of * loops. * * <p>Includes nodes such as IfCondNode, IfElseNode, SwitchCaseNode, SwitchDefaultNode, * ForeachNonemptyNode, ForeachIfemptyNode, ForNode etc. */ interface ConditionalBlockNode extends BlockNode {} // ----------------------------------------------------------------------------------------------- /** * A node that represents a block of code that is executed in a loop. * * <p>Includes nodes such as ForeachNonemptyNode and ForNode. */ interface LoopNode extends BlockNode {} // ----------------------------------------------------------------------------------------------- /** * A node that adds a new local variable. The scope of the new local variable comprises either the * children of this node or the younger siblings of this node. */ interface LocalVarNode extends SoyNode { /** Returns the name of this node's local variable (without the preceding '$'). */ String getVarName(); /** Returns the variable definition. */ VarDefn getVar(); } // ----------------------------------------------------------------------------------------------- /** A node that adds a new local variable whose scope comprises the children of this code. */ interface LocalVarBlockNode extends LocalVarNode, BlockNode {} // ----------------------------------------------------------------------------------------------- /** * A node that adds a new local variable whose scope comprises the younger siblings of this node. */ interface LocalVarInlineNode extends LocalVarNode, StandaloneNode {} // ----------------------------------------------------------------------------------------------- /** A node that holds some expressions in its fields/properties. */ interface ExprHolderNode extends SoyNode { /** Returns the list of expressions in this node. */ ImmutableList<ExprRootNode> getExprList(); } // ----------------------------------------------------------------------------------------------- /** * A substitution unit is any non-raw-text message part, since it will be replaced when the * message is rendered. Currently, one of MsgPlaceholderNode, MsgSelectNode, MsgPluralNode, or * MsgPluralRemainderNode. */ interface MsgSubstUnitNode extends StandaloneNode { @Override MsgBlockNode getParent(); /** * Returns the base var name for this substitution unit. (For a placeholder, this is the base * placeholder name.) * * <p>Note: This isn't quite correct semantically. It's conceivable that a new type of * substitution unit in the future could have multiple vars. But until that happens, this * simpler model is sufficient. */ String getBaseVarName(); /** * Returns whether this substitution unit should use the same var name as another substitution * unit. (For placeholders, this means the other placeholder is exactly the same as this one, * i.e. it appears twice in the same message.) * @param other The other substitution unit to check against. */ boolean shouldUseSameVarNameAs(MsgSubstUnitNode other); } // ----------------------------------------------------------------------------------------------- /** * A block node that can hold message content. Every direct child of a MsgBlockNode must be either * a RawTextNode or a MsgSubstUnitNode. */ interface MsgBlockNode extends BlockNode {} // ----------------------------------------------------------------------------------------------- /** A node that can be the initial content (i.e. initial child) of a MsgPlaceholderNode. */ interface MsgPlaceholderInitialNode extends StandaloneNode { /** * Gets the user-supplied placeholder name, or null if not supplied or not applicable. Note that * this raw name can be any identifier (not necessarily in upper-underscore format). * @return The user-supplied placeholder name, or null if not supplied or not applicable. */ String getUserSuppliedPhName(); /** * Generates the base placeholder name for this node. * @return The base placeholder name for this node. */ String genBasePhName(); /** * Generates the key object used in comparisons to determine whether two placeholder nodes * should be represented by the same placeholder. * @return The key object for determining whether this node and another node should be * represented by the same placeholder. */ Object genSamenessKey(); } }