コード例 #1
0
 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;
 }
コード例 #2
0
 public bool IsSafe(JsAstNode node)
 {
     // assume it is unless preven otherwise
     m_isSafe = true;
     node.IfNotNull(n => n.Accept(this));
     return m_isSafe;
 }
コード例 #3
0
 public static void Apply(JsAstNode node)
 {
     if (node != null)
     {
         node.Accept(s_instance);
     }
 }
コード例 #4
0
 public void Append(JsAstNode statement)
 {
     if (statement != null)
     {
         Context.UpdateWith(statement.Context);
         Statements.Append(statement);
     }
 }
コード例 #5
0
 public override bool ReplaceChild(JsAstNode oldNode, JsAstNode newNode)
 {
     if (Operand == oldNode)
     {
         Operand = newNode;
         return true;
     }
     return false;
 }
コード例 #6
0
 public override bool ReplaceChild(JsAstNode oldNode, JsAstNode newNode)
 {
     if (Value == oldNode)
     {
         Value = newNode;
         return true;
     }
     return false;
 }
コード例 #7
0
 public override bool ReplaceChild(JsAstNode oldNode, JsAstNode newNode)
 {
     if (Condition == oldNode)
     {
         Condition = newNode;
         return true;
     }
     return false;
 }
コード例 #8
0
        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;
        }
コード例 #9
0
        public static bool Apply(TextWriter writer, JsAstNode node)
        {
            if (node != null)
            {
                var visitor = new JsonOutputVisitor(writer);
                node.Accept(visitor);
                return visitor.IsValid;
            }

            return false;
        }
コード例 #10
0
        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)));
            }
        }
コード例 #11
0
        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;
        }
コード例 #12
0
        /// <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;
        }
コード例 #13
0
 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;
 }
コード例 #14
0
 /// <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);
         }
     }
 }
コード例 #15
0
 /// <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);
             }
         }
     }
 }
コード例 #16
0
 /// <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);
     }
 }
コード例 #17
0
 /// <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);
 }
コード例 #18
0
        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);
            }
        }
コード例 #19
0
 internal override string GetFunctionGuess(JsAstNode target)
 {
     return Operand2 == target
         ? IsAssign ? Operand1.GetFunctionGuess(this) : Parent.GetFunctionGuess(this)
         : string.Empty;
 }
コード例 #20
0
 public override bool ReplaceChild(JsAstNode oldNode, JsAstNode newNode)
 {
     if (Statement == oldNode)
     {
         Statement = newNode;
         return true;
     }
     return false;
 }
コード例 #21
0
 private void WrapWithLogicalNot(JsAstNode operand)
 {
     operand.Parent.ReplaceChild(
         operand,
         new JsUnaryOperator(operand.Context, m_parser)
             {
                 Operand = operand,
                 OperatorToken = JsToken.LogicalNot
             });
 }
コード例 #22
0
 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);
 }
コード例 #23
0
        /// <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;
        }
コード例 #24
0
 public override bool IsEquivalentTo(JsAstNode otherNode)
 {
     var otherUnary = otherNode as JsUnaryOperator;
     return otherUnary != null
         && OperatorToken == otherUnary.OperatorToken
         && Operand.IsEquivalentTo(otherUnary.Operand);
 }
コード例 #25
0
 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);
         }
     }
 }
コード例 #26
0
 /// <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);
     }
 }
コード例 #27
0
        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;
        }
コード例 #28
0
 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;
 }
コード例 #29
0
        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;
        }
コード例 #30
0
        public override bool ReplaceChild(JsAstNode oldNode, JsAstNode newNode)
        {
            if (Statements == oldNode)
            {
                Statements = ForceToBlock(newNode);
                return true;
            }

            return false;
        }