public override bool IsEquivalentTo(JsAstNode otherNode) { var otherRegExp = otherNode as JsRegExpLiteral; return otherRegExp != null && string.CompareOrdinal(Pattern, otherRegExp.Pattern) == 0 && string.CompareOrdinal(PatternSwitches, otherRegExp.PatternSwitches) == 0; }
public bool IsSafe(JsAstNode node) { // assume it is unless preven otherwise m_isSafe = true; node.IfNotNull(n => n.Accept(this)); return m_isSafe; }
public static void Apply(JsAstNode node) { if (node != null) { node.Accept(s_instance); } }
public void Append(JsAstNode statement) { if (statement != null) { Context.UpdateWith(statement.Context); Statements.Append(statement); } }
public override bool ReplaceChild(JsAstNode oldNode, JsAstNode newNode) { if (Operand == oldNode) { Operand = newNode; return true; } return false; }
public override bool ReplaceChild(JsAstNode oldNode, JsAstNode newNode) { if (Value == oldNode) { Value = newNode; return true; } return false; }
public override bool ReplaceChild(JsAstNode oldNode, JsAstNode newNode) { if (Condition == oldNode) { Condition = newNode; return true; } return false; }
public override bool IsEquivalentTo(JsAstNode otherNode) { var otherThis = otherNode as JsThisLiteral; // this really assume we are comparing this operators from the same object scope. // if you compare a this-literal from one function to a this-literal from another, // it will pop positive -- but it won't actually be equivalent! return otherThis != null; }
public static bool Apply(TextWriter writer, JsAstNode node) { if (node != null) { var visitor = new JsonOutputVisitor(writer); node.Accept(visitor); return visitor.IsValid; } return false; }
public static void Apply(TextWriter writer, JsAstNode node, JsSettings settings) { if (node != null) { var outputVisitor = new JsOutputVisitor(writer, settings); node.Accept(outputVisitor); // if there is a symbol map that we are tracking, tell it that we have ended an output run // and pass it offsets to the last line and column positions. settings.IfNotNull(s => s.SymbolsMap.IfNotNull(m => m.EndOutputRun(outputVisitor.m_lineCount, outputVisitor.m_lineLength))); } }
public bool Match(JsAstNode node, string identifiers) { // set the match to false m_isMatch = false; // identifiers cannot be null or blank and must match: IDENT(.IDENT)* // since for JS there has to be at least a global object, the dot must be AFTER the first character. if (node != null && !string.IsNullOrEmpty(identifiers)) { // get all the parts var parts = identifiers.Split('.'); // each part must be a valid JavaScript identifier. Assume everything is valid // unless at least one is invalid -- then forget it var isValid = true; foreach (var part in parts) { if (!JsScanner.IsValidIdentifier(part)) { isValid = false; break; } } // must be valid to continue if (isValid) { // save the parts and start the index on the last one, since we'll be walking backwards m_parts = parts; m_index = parts.Length - 1; node.Accept(this); } } return m_isMatch; }
/// <summary> /// Replace the existing direct child node of the block with a new node. /// </summary> /// <param name="oldNode">existing statement node to replace.</param> /// <param name="newNode">node with which to replace the existing node.</param> /// <returns>true if the replacement was a succeess; false otherwise</returns> public override bool ReplaceChild(JsAstNode oldNode, JsAstNode newNode) { for (int ndx = m_list.Count - 1; ndx >= 0; --ndx) { if (m_list[ndx] == oldNode) { m_list[ndx].IfNotNull(n => n.Parent = (n.Parent == this) ? null : n.Parent); if (newNode == null) { // just remove it m_list.RemoveAt(ndx); } else { JsBlock newBlock = newNode as JsBlock; if (newBlock != null) { // the new "statement" is a block. That means we need to insert all // the statements from the new block at the location of the old item. m_list.RemoveAt(ndx); InsertRange(ndx, newBlock.m_list); } else { // not a block -- slap it in there m_list[ndx] = newNode; newNode.Parent = this; } } return true; } } return false; }
public override bool ReplaceChild(JsAstNode oldNode, JsAstNode newNode) { if (TryBlock == oldNode) { TryBlock = ForceToBlock(newNode); return true; } if (CatchParameter == oldNode) { CatchParameter = newNode as JsParameterDeclaration; return true; } if (CatchBlock == oldNode) { CatchBlock = ForceToBlock(newNode); return true; } if (FinallyBlock == oldNode) { FinallyBlock = ForceToBlock(newNode); return true; } return false; }
/// <summary> /// Insert a new node into the given position index within the block /// </summary> /// <param name="position">zero-based index into which the new node will be inserted</param> /// <param name="item">new node to insert into the block</param> public void Insert(int position, JsAstNode item) { if (item != null) { var block = item as JsBlock; if (block != null) { InsertRange(position, block.Children); } else { item.Parent = this; m_list.Insert(position, item); } } }
/// <summary> /// Insert the given statement node after an existing node in the block. /// </summary> /// <param name="after">exisitng child node of the block</param> /// <param name="item">node to insert after the existing node</param> public void InsertAfter(JsAstNode after, JsAstNode item) { if (item != null) { int index = m_list.IndexOf(after); if (index >= 0) { var block = item as JsBlock; if (block != null) { // don't insert a block into a block -- insert the new block's // children instead (don't want nested blocks) InsertRange(index + 1, block.Children); } else { item.Parent = this; m_list.Insert(index + 1, item); } } } }
/// <summary> /// Append the given statement node to the end of the block /// </summary> /// <param name="element">node to add to the block</param> public void Append(JsAstNode element) { if (element != null) { element.Parent = this; m_list.Add(element); } }
/// <summary> /// Gets the zero-based index of the given syntax tree node within the block, or -1 if the node is not a direct child of the block /// </summary> /// <param name="child">node to find</param> /// <returns>zero-based index of the node in the block, or -1 if the node is not a direct child of the block</returns> public int IndexOf(JsAstNode child) { return m_list.IndexOf(child); }
private static void ReplaceNodeCheckParens(JsAstNode oldNode, JsAstNode newNode) { var grouping = oldNode.Parent as JsGroupingOperator; if (grouping != null) { if (newNode != null) { var targetPrecedence = grouping.Parent.Precedence; var conditional = grouping.Parent as JsConditional; if (conditional != null) { // the conditional is weird in that the different parts need to be // compared against different precedences, not the precedence of the // conditional itself. The condition should be compared to logical-or, // and the true/false expressions against assignment. targetPrecedence = conditional.Condition == grouping ? JsOperatorPrecedence.LogicalOr : JsOperatorPrecedence.Assignment; } if (newNode.Precedence >= targetPrecedence) { // don't need the parens anymore, so replace the grouping operator // with the new node, thereby eliminating the parens grouping.Parent.ReplaceChild(grouping, newNode); } else { // still need the parens; just replace the node with the literal oldNode.Parent.ReplaceChild(oldNode, newNode); } } else { // eliminate the parens grouping.Parent.ReplaceChild(grouping, null); } } else { // just replace the node with the literal oldNode.Parent.ReplaceChild(oldNode, newNode); } }
internal override string GetFunctionGuess(JsAstNode target) { return Operand2 == target ? IsAssign ? Operand1.GetFunctionGuess(this) : Parent.GetFunctionGuess(this) : string.Empty; }
public override bool ReplaceChild(JsAstNode oldNode, JsAstNode newNode) { if (Statement == oldNode) { Statement = newNode; return true; } return false; }
private void WrapWithLogicalNot(JsAstNode operand) { operand.Parent.ReplaceChild( operand, new JsUnaryOperator(operand.Context, m_parser) { Operand = operand, OperatorToken = JsToken.LogicalNot }); }
public override bool IsEquivalentTo(JsAstNode otherNode) { // a binary operator is equivalent to another binary operator if the operator is the same and // both operands are also equivalent var otherBinary = otherNode as JsBinaryOperator; return otherBinary != null && OperatorToken == otherBinary.OperatorToken && Operand1.IsEquivalentTo(otherBinary.Operand1) && Operand2.IsEquivalentTo(otherBinary.Operand2); }
/// <summary> /// Return the first Block node in the tree starting from the given node and working up through the parent nodes. /// </summary> /// <param name="node">initial node</param> /// <returns>first block node in the node tree</returns> private static JsBlock GetParentBlock(JsAstNode node) { while(node != null) { // see if the current node is a block, and if so, return it. var block = node as JsBlock; if (block != null) { return block; } // try the parent node = node.Parent; } // if we get here, we never found a parent block. return null; }
public override bool IsEquivalentTo(JsAstNode otherNode) { var otherUnary = otherNode as JsUnaryOperator; return otherUnary != null && OperatorToken == otherUnary.OperatorToken && Operand.IsEquivalentTo(otherUnary.Operand); }
private void TypicalHandler(JsAstNode node) { if (node != null) { // don't need to recurse -- to logical-not this, we just need to apply // the logical-not operator to it, which will add a character if (m_measure) { // measure ++m_delta; } else { // simple convert WrapWithLogicalNot(node); } } }
/// <summary> /// replace the node with a literal. If the node was wrapped in a grouping operator /// before (parentheses around it), then we can get rid of the parentheses too, since /// we are replacing the node with a single literal entity. /// </summary> /// <param name="node">node to replace</param> /// <param name="newLiteral">literal to replace the node with</param> private static void ReplaceNodeWithLiteral(JsAstNode node, JsConstantWrapper newLiteral) { var grouping = node.Parent as JsGroupingOperator; if (grouping != null) { // because we are replacing the operator with a literal, the parentheses // the grouped this operator are now superfluous. Replace them, too grouping.Parent.ReplaceChild(grouping, newLiteral); } else { // just replace the node with the literal node.Parent.ReplaceChild(node, newLiteral); } }
public override bool ReplaceChild(JsAstNode oldNode, JsAstNode newNode) { if (Body == oldNode) { Body = ForceToBlock(newNode); return true; } else if (ParameterDeclarations == oldNode) { var newList = newNode as JsAstNodeList; if (newNode == null || newList != null) { ParameterDeclarations = newList; return true; } } return false; }
public void SwapOperands() { // swap the operands -- we don't need to go through ReplaceChild or the // property setters because we don't need to change the Parent pointers // or anything like that. JsAstNode temp = m_operand1; m_operand1 = m_operand2; m_operand2 = temp; }
private static bool IsIterativeReference(JsAstNode initializer, IJsNameReference reference) { // we only care about array and regular expressions with the global switch at this point. // if it's not one of those types, then go ahead and assume iterative reference doesn't matter. var regExp = initializer as JsRegExpLiteral; if (initializer is JsArrayLiteral || initializer is JsObjectLiteral || (regExp != null && regExp.PatternSwitches != null && regExp.PatternSwitches.IndexOf("g", StringComparison.OrdinalIgnoreCase) >= 0)) { // get the parent block for the initializer. We'll use this as a stopping point in our loop. var parentBlock = GetParentBlock(initializer); // walk up the parent chain from the reference. If we find a while, a for, or a do-while, // then we know this reference is iteratively called. // stop when the parent is null, the same block containing the initializer, or a function object. // (because a function object will step out of scope, and we know we should be in the same scope) var child = reference as JsAstNode; var parent = child.Parent; while (parent != null && parent != parentBlock && !(parent is JsFunctionObject)) { // while or do-while is iterative -- the condition and the body are both called repeatedly. if (parent is JsWhileNode || parent is JsDoWhile) { return true; } // for-statements call the condition, the incrementer, and the body repeatedly, but not the // initializer. var forNode = parent as JsForNode; if (forNode != null && child != forNode.Initializer) { return true; } // in forin-statements, only the body is repeated, the collection is evaluated only once. var forInStatement = parent as JsForIn; if (forInStatement != null && child == forInStatement.Body) { return true; } // go up child = parent; parent = parent.Parent; } } return false; }
public override bool ReplaceChild(JsAstNode oldNode, JsAstNode newNode) { if (Statements == oldNode) { Statements = ForceToBlock(newNode); return true; } return false; }