Finds the surrounding ast node of the given expression of any of the given types
@param {!ASTNode} ast
@param {!{start: number, end: number}} expn - contains start and end offsets of expn
@param {!Array.<string>} types
@return {?ASTNode}
161933
function findSurroundASTNode(ast, expn, types) {
        var foundNode = ASTWalker.findNodeAround(ast, expn.start, function (nodeType, node) {
            if (expn.end) {
                return types.includes(nodeType) && node.end >= expn.end;
            } else {
                return types.includes(nodeType);
            }
        });
        return foundNode && _.clone(foundNode.node);
    }
1199632
function isTraceryExpr (node, makeSymbolName) {
  makeSymbolName = makeSymbolName || defaultMakeSymbolName
  return typeof(node) === 'object' && node.type === 'cond'
    && node.test.length === 1 && typeof(node.test[0]) === 'object' && node.test[0].type === 'lookup'
    && node.t.length === 1 && isEvalVar (node.t[0])
    && node.f.length === 1 && isPlainSymExpr (node.f[0])
    && node.test[0].varname.toLowerCase() === node.t[0].args[0].varname.toLowerCase()
    && node.test[0].varname.toLowerCase() === makeSymbolName (node.f[0]).toLowerCase()
}
585025
function parsePostfixExpression() {
        var expr, token, startToken = lookahead;

        expr = inheritCoverGrammar(parseLeftHandSideExpressionAllowCall);

        if (!hasLineTerminator && lookahead.type === Token.Punctuator) {
            if (match('++') || match('--')) {
                // ECMA-262 11.3.1, 11.3.2
                if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) {
                    tolerateError(Messages.StrictLHSPostfix);
                }

                if (!isAssignmentTarget) {
                    tolerateError(Messages.InvalidLHSInAssignment);
                }

                isAssignmentTarget = isBindingElement = false;

                token = lex();
                expr = new WrappingNode(startToken).finishPostfixExpression(token.value, expr);
            }
        }

        return expr;
    }
519087
function findNodeBeforePos(pos) {
    const lut = this.ends;
    assert(is.finitenumber(pos) && pos >= 0);

    let left = 0;
    let right = lut.length - 1;
    while (left < right) {
        const mid = Math.ceil((left + right) / 2);
        assert(mid >= 0 && mid < lut.length);
        if (pos < lut[mid].range[1]) {
            right = mid - 1;
        }
        else {
            left = mid;
        }
    }
    if (left > right) {
        assert(lut[0].range[1] > pos);
        return null;
    }

    const found = left;
    const foundPos = lut[found].range[1];
    if(foundPos > pos) {
        return null;
    }
    if (found <= lut.length - 2) {
        const nextPos = lut[found + 1].range[1];
        assert(nextPos > pos);
    }

    return lut[found];
}
707803
def expressionToAST(ex):
    
    return ASTNode(ex.astType, ex.astKind, ex.value,
                   [expressionToAST(c) for c in ex.children])
187511
function matchesTag(node, exp) {
	return (
		node.nodeType === 1 &&
		(exp.tag === '*' || node.nodeName.toLowerCase() === exp.tag)
	);
}
262772
function(ast, offset) {
			var found = null;
			var dom = ast;
			var missingTagClose = false;
			if (!Array.isArray(ast) && ast.children){
				dom = ast.children;
			}
			 Visitor.visit(dom, {
	            visitNode: function(node) {
					if(node.range[0] <= offset) {
						found = node;
					} else {
					    return Visitor.BREAK;
					}      
	            },
	            endVisitNode: function(node) {
	            	if(found && !missingTagClose && offset >= found.range[1] && offset > node.range[0]) {
	            		found = node;
	            		// If at the boundary of a tag range and there is a missing end tag, return the innermost tag  <a><b></a>
	            		if (offset === found.range[1] && found.endrange && found.openrange && found.endrange[1] === found.openrange[1]){
	            			missingTagClose = true;
	            		}
	            	}
	            }
	        });
	        return found;
		}
933335
function (startToken, endToken, types) {
            var is = true;
            var token = startToken;
            while (token.next && token.next !== endToken) {
                token = token.next;
                if (types.indexOf(token.type) === -1) {
                    is = false;
                    break;
                }
            }
            return is;
        }
529015
function checkASTandNodeArray(ast, nodes) {
  typeCheckObject(ast, 'ast');
  typeCheckArray(nodes, 'nodes');
  nodes.forEach((node, index) => {
    typeCheckObject(node, 'nodes (index: ' + index + ')');
  });
  runValidator(ast, 'ast');
  nodes.forEach((node, index) => {
    runValidator(node, 'nodes (index: ' + index + ')');
  });
}
906140
function find(obj, node, parent) {
  if (!obj) return;
  var result;

  var types = Object.keys(obj);
  for (var i = 0; i < types.length; i++) {
    var type = types[i];

    if (t.is(type, node)) {
      var fn = obj[type];
      result = fn(node, parent);
      if (result != null) break;
    }
  }

  return result;
}
614318
private static void traverseExpression(final ognl.Node node, final Set<String> params) {
		if (node == null) {
			return;
		}
		if (node instanceof ASTProperty) {
			ASTProperty prop = (ASTProperty) node;
			params.add(prop.toString());
		} else {
			int childCount = node.jjtGetNumChildren();
			for (int i = 0; i < childCount; i++) {
				ognl.Node child = node.jjtGetChild(i);
				traverseExpression(child, params);
			}
		}
	}
829562
function _extensionsToAsn1(exts) {
  // create top-level extension container
  var rval = asn1.create(asn1.Class.CONTEXT_SPECIFIC, 3, true, []);

  // create extension sequence (stores a sequence for each extension)
  var seq = asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, []);
  rval.value.push(seq);

  var ext, extseq;
  for(var i = 0; i < exts.length; ++i) {
    ext = exts[i];

    // create a sequence for each extension
    extseq = asn1.create(asn1.Class.UNIVERSAL, asn1.Type.SEQUENCE, true, []);
    seq.value.push(extseq);

    // extnID (OID)
    extseq.value.push(asn1.create(
      asn1.Class.UNIVERSAL, asn1.Type.OID, false,
      asn1.oidToDer(ext.id).getBytes()));

    // critical defaults to false
    if(ext.critical) {
      // critical BOOLEAN DEFAULT FALSE
      extseq.value.push(asn1.create(
        asn1.Class.UNIVERSAL, asn1.Type.BOOLEAN, false,
        String.fromCharCode(0xFF)));
    }

    var value = ext.value;
    if(typeof ext.value !== 'string') {
      // value is asn.1
      value = asn1.toDer(value).getBytes();
    }

    // extnValue (OCTET STRING)
    extseq.value.push(asn1.create(
      asn1.Class.UNIVERSAL, asn1.Type.OCTETSTRING, false, value));
  }

  return rval;
}
140946
function astValue(node) {

  switch (node.type) {

  case 'ExpressionStatement':
    return astValue(node.expression);

  case 'ObjectExpression':
    return node.properties.reduce(
      (obj, prop) => Object.assign(obj, {[prop.key.value]: astValue(prop.value)}),
      {}
    );

  case 'ArrayExpression':
    return node.elements.map(element => astValue(element));

  case 'Literal':
    return node.value;

  default:
    throw new Error(`Unexpected ast node type: ${node.type}`);

  }
}
357018
function match(node, type) {
            let innerStatementNode = node;

            while (innerStatementNode.type === "LabeledStatement") {
                innerStatementNode = innerStatementNode.body;
            }
            if (Array.isArray(type)) {
                return type.some(match.bind(null, innerStatementNode));
            }
            return StatementTypes[type].test(innerStatementNode, sourceCode);
        }
682281
public function resolveExpressionNodeToType($expr)
    {
        // PARENTHESIZED EXPRESSION
        // Retrieve inner expression from parenthesized expression
        while ($expr instanceof Node\Expression\ParenthesizedExpression) {
            $expr = $expr->expression;
        }

        if ($expr == null || $expr instanceof PhpParser\MissingToken || $expr instanceof PhpParser\SkippedToken) {
            // TODO some members are null or Missing/SkippedToken
            // How do we handle this more generally?
            return new Types\Mixed_;
        }

        // VARIABLE
        //   $this -> Type\this
        //   $myVariable -> type of corresponding assignment expression
        if ($expr instanceof Node\Expression\Variable || $expr instanceof Node\UseVariableName) {
            if ($expr->getName() === 'this') {
                return new Types\Object_(new Fqsen('\\' . $this->getContainingClassFqn($expr)));
            }
            // Find variable definition (parameter or assignment expression)
            $defNode = $this->resolveVariableToNode($expr);
            if ($defNode instanceof Node\Expression\AssignmentExpression || $defNode instanceof Node\UseVariableName) {
                return $this->resolveExpressionNodeToType($defNode);
            }
            if ($defNode instanceof Node\ForeachKey || $defNode instanceof Node\ForeachValue) {
                return $this->getTypeFromNode($defNode);
            }
            if ($defNode instanceof Node\Parameter) {
                return $this->getTypeFromNode($defNode);
            }
        }

        // FUNCTION CALL
        // Function calls are resolved to type corresponding to their FQN
        if ($expr instanceof Node\Expression\CallExpression &&
            !(
                $expr->callableExpression instanceof Node\Expression\ScopedPropertyAccessExpression ||
                $expr->callableExpression instanceof Node\Expression\MemberAccessExpression)
        ) {
            // Find the function definition
            if ($expr->callableExpression instanceof Node\Expression) {
                // Cannot get type for dynamic function call
                return new Types\Mixed_;
            }

            if ($expr->callableExpression instanceof Node\QualifiedName) {
                $fqn = $expr->callableExpression->getResolvedName() ?? $expr->callableExpression->getNamespacedName();
                $fqn .= '()';
                $def = $this->index->getDefinition($fqn, true);
                if ($def !== null) {
                    return $def->type;
                }
            }
        }

        // TRUE / FALSE / NULL
        // Resolve true and false reserved words to Types\Boolean
        if ($expr instanceof Node\ReservedWord) {
            $token = $expr->children->kind;
            if ($token === PhpParser\TokenKind::TrueReservedWord || $token === PhpParser\TokenKind::FalseReservedWord) {
                return new Types\Boolean;
            }

            if ($token === PhpParser\TokenKind::NullReservedWord) {
                return new Types\Null_;
            }
        }

        // CONSTANT FETCH
        // Resolve constants by retrieving corresponding definition type from FQN
        if (ParserHelpers\isConstantFetch($expr)) {
            $fqn = (string)$expr->getNamespacedName();
            $def = $this->index->getDefinition($fqn, true);
            if ($def !== null) {
                return $def->type;
            }
        }

        // MEMBER CALL EXPRESSION/SCOPED PROPERTY CALL EXPRESSION
        //   The type of the member/scoped property call expression is the type of the method, so resolve the
        //   type of the callable expression.
        if ($expr instanceof Node\Expression\CallExpression && (
            $expr->callableExpression instanceof Node\Expression\MemberAccessExpression ||
            $expr->callableExpression instanceof Node\Expression\ScopedPropertyAccessExpression)
        ) {
            return $this->resolveExpressionNodeToType($expr->callableExpression);
        }

        // MEMBER ACCESS EXPRESSION
        if ($expr instanceof Node\Expression\MemberAccessExpression) {
            if ($expr->memberName instanceof Node\Expression) {
                return new Types\Mixed_;
            }
            $var = $expr->dereferencableExpression;

           // Resolve object
            $objType = $this->resolveExpressionNodeToType($var);
            if (!($objType instanceof Types\Compound)) {
                $objType = new Types\Compound([$objType]);
            }
            for ($i = 0; $t = $objType->get($i); $i++) {
                if ($t instanceof Types\This) {
                    $classFqn = self::getContainingClassFqn($expr);
                    if ($classFqn === null) {
                        return new Types\Mixed_;
                    }
                } else if (!($t instanceof Types\Object_) || $t->getFqsen() === null) {
                    return new Types\Mixed_;
                } else {
                    $classFqn = substr((string)$t->getFqsen(), 1);
                }
                $add = '->' . $expr->memberName->getText($expr->getFileContents());
                if ($expr->parent instanceof Node\Expression\CallExpression) {
                    $add .= '()';
                }
                $classDef = $this->index->getDefinition($classFqn);
                if ($classDef !== null) {
                    foreach ($classDef->getAncestorDefinitions($this->index, true) as $fqn => $def) {
                        $def = $this->index->getDefinition($fqn . $add);
                        if ($def !== null) {
                            if ($def->type instanceof Types\This || $def->type instanceof Types\Self_) {
                                return new Types\Object_(new Fqsen('\\' . $classFqn));
                            }
                            return $def->type;
                        }
                    }
                }
            }
        }

        // SCOPED PROPERTY ACCESS EXPRESSION
        if ($expr instanceof Node\Expression\ScopedPropertyAccessExpression) {
            $classType = $this->resolveClassNameToType($expr->scopeResolutionQualifier);
            if (!($classType instanceof Types\Object_) || $classType->getFqsen() === null) {
                return new Types\Mixed_;
            }
            $fqn = substr((string)$classType->getFqsen(), 1) . '::';

            // TODO is there a cleaner way to do this?
            $fqn .= $expr->memberName->getText() ?? $expr->memberName->getText($expr->getFileContents());
            if ($expr->parent instanceof Node\Expression\CallExpression) {
                $fqn .= '()';
            }

            $def = $this->index->getDefinition($fqn);
            if ($def === null) {
                return new Types\Mixed_;
            }
            return $def->type;
        }

        // OBJECT CREATION EXPRESSION
        //   new A() => resolves to the type of the class type designator (A)
        //   TODO: new $this->a => resolves to the string represented by "a"
        if ($expr instanceof Node\Expression\ObjectCreationExpression) {
            return $this->resolveClassNameToType($expr->classTypeDesignator);
        }

        // CLONE EXPRESSION
        //   clone($a) => resolves to the type of $a
        if ($expr instanceof Node\Expression\CloneExpression) {
            return $this->resolveExpressionNodeToType($expr->expression);
        }

        // ASSIGNMENT EXPRESSION
        //   $a = $myExpression => resolves to the type of the right-hand operand
        if ($expr instanceof Node\Expression\AssignmentExpression) {
            return $this->resolveExpressionNodeToType($expr->rightOperand);
        }

        // TERNARY EXPRESSION
        //   $condition ? $ifExpression : $elseExpression => reslves to type of $ifCondition or $elseExpression
        //   $condition ?: $elseExpression => resolves to type of $condition or $elseExpression
        if ($expr instanceof Node\Expression\TernaryExpression) {
            // ?:
            if ($expr->ifExpression === null) {
                return new Types\Compound([
                    $this->resolveExpressionNodeToType($expr->condition), // TODO: why?
                    $this->resolveExpressionNodeToType($expr->elseExpression)
                ]);
            }
            // Ternary is a compound of the two possible values
            return new Types\Compound([
                $this->resolveExpressionNodeToType($expr->ifExpression),
                $this->resolveExpressionNodeToType($expr->elseExpression)
            ]);
        }

        // NULL COALLESCE
        //   $rightOperand ?? $leftOperand => resolves to type of $rightOperand or $leftOperand
        if ($expr instanceof Node\Expression\BinaryExpression && $expr->operator->kind === PhpParser\TokenKind::QuestionQuestionToken) {
            // ?? operator
            return new Types\Compound([
                $this->resolveExpressionNodeToType($expr->leftOperand),
                $this->resolveExpressionNodeToType($expr->rightOperand)
            ]);
        }

        // BOOLEAN EXPRESSIONS: resolve to Types\Boolean
        //   (bool) $expression
        //   !$expression
        //   empty($var)
        //   isset($var)
        //   >, >=, <, <=, &&, ||, AND, OR, XOR, ==, ===, !=, !==
        if (
            ParserHelpers\isBooleanExpression($expr)

            || ($expr instanceof Node\Expression\CastExpression && $expr->castType->kind === PhpParser\TokenKind::BoolCastToken)
            || ($expr instanceof Node\Expression\UnaryOpExpression && $expr->operator->kind === PhpParser\TokenKind::ExclamationToken)
            || $expr instanceof Node\Expression\EmptyIntrinsicExpression
            || $expr instanceof Node\Expression\IssetIntrinsicExpression
        ) {
            return new Types\Boolean;
        }

        // STRING EXPRESSIONS: resolve to Types\String
        //   [concatenation] .=, .
        //   [literals] "hello", \b"hello", \B"hello", 'hello', \b'hello', HEREDOC, NOWDOC
        //   [cast] (string) "hello"
        //
        //   TODO: Magic constants (__CLASS__, __DIR__, __FUNCTION__, __METHOD__, __NAMESPACE__, __TRAIT__, __FILE__)
        if (
            ($expr instanceof Node\Expression\BinaryExpression &&
                ($expr->operator->kind === PhpParser\TokenKind::DotToken || $expr->operator->kind === PhpParser\TokenKind::DotEqualsToken)) ||
            $expr instanceof Node\StringLiteral ||
            ($expr instanceof Node\Expression\CastExpression && $expr->castType->kind === PhpParser\TokenKind::StringCastToken)
        ) {
            return new Types\String_;
        }

        // BINARY EXPRESSIONS:
        // Resolve to Types\Integer if both left and right operands are integer types, otherwise Types\Float
        //   [operator] +, -, *, **
        //   [assignment] *=, **=, -=, +=
        // Resolve to Types\Float
        //   [assignment] /=
        if (
            $expr instanceof Node\Expression\BinaryExpression &&
            ($operator = $expr->operator->kind)
            && ($operator === PhpParser\TokenKind::PlusToken ||
                $operator === PhpParser\TokenKind::AsteriskAsteriskToken ||
                $operator === PhpParser\TokenKind::AsteriskToken ||
                $operator === PhpParser\TokenKind::MinusToken ||

                // Assignment expressions (TODO: consider making this a type of AssignmentExpression rather than kind of BinaryExpression)
                $operator === PhpParser\TokenKind::AsteriskEqualsToken||
                $operator === PhpParser\TokenKind::AsteriskAsteriskEqualsToken ||
                $operator === PhpParser\TokenKind::MinusEqualsToken ||
                $operator === PhpParser\TokenKind::PlusEqualsToken
            )
        ) {
            if (
                $this->resolveExpressionNodeToType($expr->leftOperand) instanceof Types\Integer
                && $this->resolveExpressionNodeToType($expr->rightOperand) instanceof Types\Integer
            ) {
                return new Types\Integer;
            }
            return new Types\Float_;
        } else if (
            $expr instanceof Node\Expression\BinaryExpression &&
            $expr->operator->kind === PhpParser\TokenKind::SlashEqualsToken
        ) {
            return new Types\Float_;
        }

        // INTEGER EXPRESSIONS: resolve to Types\Integer
        //   [literal] 1
        //   [operator] <=>, &, ^, |
        //   TODO: Magic constants (__LINE__)
        if (
            // TODO: consider different Node types of float/int, also better property name (not "children")
            ($expr instanceof Node\NumericLiteral && $expr->children->kind === PhpParser\TokenKind::IntegerLiteralToken) ||
            $expr instanceof Node\Expression\BinaryExpression && (
                ($operator = $expr->operator->kind)
                && ($operator === PhpParser\TokenKind::LessThanEqualsGreaterThanToken ||
                    $operator === PhpParser\TokenKind::AmpersandToken ||
                    $operator === PhpParser\TokenKind::CaretToken ||
                    $operator === PhpParser\TokenKind::BarToken)
            )
        ) {
            return new Types\Integer;
        }

        // FLOAT EXPRESSIONS: resolve to Types\Float
        //   [literal] 1.5
        //   [operator] /
        //   [cast] (double)
        if (
            $expr instanceof Node\NumericLiteral && $expr->children->kind === PhpParser\TokenKind::FloatingLiteralToken ||
            ($expr instanceof Node\Expression\CastExpression && $expr->castType->kind === PhpParser\TokenKind::DoubleCastToken) ||
            ($expr instanceof Node\Expression\BinaryExpression && $expr->operator->kind === PhpParser\TokenKind::SlashToken)
        ) {
            return new Types\Float_;
        }

        // ARRAY CREATION EXPRESSION:
        // Resolve to Types\Array (Types\Compound of value and key types)
        //  [a, b, c]
        //  [1=>"hello", "hi"=>1, 4=>[]]s
        if ($expr instanceof Node\Expression\ArrayCreationExpression) {
            $valueTypes = [];
            $keyTypes = [];
            if ($expr->arrayElements !== null) {
                foreach ($expr->arrayElements->getElements() as $item) {
                    $valueTypes[] = $this->resolveExpressionNodeToType($item->elementValue);
                    $keyTypes[] = $item->elementKey ? $this->resolveExpressionNodeToType($item->elementKey) : new Types\Integer;
                }
            }
            $valueTypes = array_unique($valueTypes);
            $keyTypes = array_unique($keyTypes);
            if (empty($valueTypes)) {
                $valueType = null;
            } else if (count($valueTypes) === 1) {
                $valueType = $valueTypes[0];
            } else {
                $valueType = new Types\Compound($valueTypes);
            }
            if (empty($keyTypes)) {
                $keyType = null;
            } else if (count($keyTypes) === 1) {
                $keyType = $keyTypes[0];
            } else {
                $keyType = new Types\Compound($keyTypes);
            }
            return new Types\Array_($valueType, $keyType);
        }

        // SUBSCRIPT EXPRESSION
        // $myArray[3]
        // $myArray{"hello"}
        if ($expr instanceof Node\Expression\SubscriptExpression) {
            $varType = $this->resolveExpressionNodeToType($expr->postfixExpression);
            if (!($varType instanceof Types\Array_)) {
                return new Types\Mixed_;
            }
            return $varType->getValueType();
        }

        // SCRIPT INCLUSION EXPRESSION
        //   include, require, include_once, require_once
        if ($expr instanceof Node\Expression\ScriptInclusionExpression) {
            // TODO: resolve path to PhpDocument and find return statement
            return new Types\Mixed_;
        }

        if ($expr instanceof Node\QualifiedName) {
            return $this->resolveClassNameToType($expr);
        }

        return new Types\Mixed_;
    }
1112645
function checkTypeParameter(node) {
            // Grammar Checking
            if (node.expression) {
                grammarErrorOnFirstToken(node.expression, ts.Diagnostics.Type_expected);
            }
            checkSourceElement(node.constraint);
            getConstraintOfTypeParameter(getDeclaredTypeOfTypeParameter(getSymbolOfNode(node)));
            if (produceDiagnostics) {
                checkTypeNameIsReserved(node.name, ts.Diagnostics.Type_parameter_name_cannot_be_0);
            }
        }
881373
function checkASTandNode(ast, node) {
  typeCheckObject(ast, 'ast');
  typeCheckObject(node, 'node');
  runValidator(ast, 'ast');
  runValidator(node, 'node');
}