Java Code Examples for com.google.javascript.rhino.Node#getChildCount()

The following examples show how to use com.google.javascript.rhino.Node#getChildCount() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: Closure_9_ProcessCommonJSModules_s.java    From coming with MIT License 6 votes vote down vote up
@Override
public void visit(NodeTraversal t, Node n, Node parent) {
  if (n.isCall() && n.getChildCount() == 2 &&
      "require".equals(n.getFirstChild().getQualifiedName()) &&
      n.getChildAtIndex(1).isString()) {
    visitRequireCall(t, n, parent);
  }

  if (n.isScript()) {
    scriptNodeCount++;
    visitScript(t, n);
  }

  if (n.isGetProp() &&
      "module.exports".equals(n.getQualifiedName())) {
    visitModuleExports(n);
  }
}
 
Example 2
Source File: Closure_115_FunctionInjector_t.java    From coming with MIT License 6 votes vote down vote up
/**
 * Gets an estimate of the cost in characters of making the function call:
 * the sum of the identifiers and the separators.
 * @param referencesThis
 */
private static int estimateCallCost(Node fnNode, boolean referencesThis) {
  Node argsNode = NodeUtil.getFunctionParameters(fnNode);
  int numArgs = argsNode.getChildCount();

  int callCost = NAME_COST_ESTIMATE + PAREN_COST;
  if (numArgs > 0) {
    callCost += (numArgs * NAME_COST_ESTIMATE) + ((numArgs - 1) * COMMA_COST);
  }

  if (referencesThis) {
    // TODO(johnlenz): Update this if we start supporting inlining
    // other functions that reference this.
    // The only functions that reference this that are currently inlined
    // are those that are called via ".call" with an explicit "this".
    callCost += 5 + 5;  // ".call" + "this,"
  }

  return callCost;
}
 
Example 3
Source File: Closure_10_NodeUtil_s.java    From coming with MIT License 6 votes vote down vote up
/**
 * Gets the condition of an ON_TRUE / ON_FALSE CFG edge.
 * @param n a node with an outgoing conditional CFG edge
 * @return the condition node or null if the condition is not obviously a node
 */
static Node getConditionExpression(Node n) {
  switch (n.getType()) {
    case Token.IF:
    case Token.WHILE:
      return n.getFirstChild();
    case Token.DO:
      return n.getLastChild();
    case Token.FOR:
      switch (n.getChildCount()) {
        case 3:
          return null;
        case 4:
          return n.getFirstChild().getNext();
      }
      throw new IllegalArgumentException("malformed 'for' statement " + n);
    case Token.CASE:
      return null;
  }
  throw new IllegalArgumentException(n + " does not have a condition.");
}
 
Example 4
Source File: Closure_105_FoldConstants_t.java    From coming with MIT License 6 votes vote down vote up
/**
 * Does a statement consume a 'dangling else'? A statement consumes
 * a 'dangling else' if an 'else' token following the statement
 * would be considered by the parser to be part of the statement.
 */
private boolean consumesDanglingElse(Node n) {
  while (true) {
    switch (n.getType()) {
      case Token.IF:
        if (n.getChildCount() < 3) return true;
        // This IF node has no else clause.
        n = n.getLastChild();
        continue;
      case Token.WITH:
      case Token.WHILE:
      case Token.FOR:
        n = n.getLastChild();
        continue;
      default:
        return false;
    }
  }
}
 
Example 5
Source File: jKali_003_s.java    From coming with MIT License 6 votes vote down vote up
/**
 * Gets the condition of an ON_TRUE / ON_FALSE CFG edge.
 * @param n a node with an outgoing conditional CFG edge
 * @return the condition node or null if the condition is not obviously a node
 */
static Node getConditionExpression(Node n) {
  switch (n.getType()) {
    case Token.IF:
    case Token.WHILE:
      return n.getFirstChild();
    case Token.DO:
      return n.getLastChild();
    case Token.FOR:
      switch (n.getChildCount()) {
        case 3:
          return null;
        case 4:
          return n.getFirstChild().getNext();
      }
      throw new IllegalArgumentException("malformed 'for' statement " + n);
    case Token.CASE:
      return null;
  }
  throw new IllegalArgumentException(n + " does not have a condition.");
}
 
Example 6
Source File: Closure_66_TypeCheck_s.java    From coming with MIT License 5 votes vote down vote up
/**
 * Visits the parameters of a CALL or a NEW node.
 */
private void visitParameterList(NodeTraversal t, Node call,
    FunctionType functionType) {
  Iterator<Node> arguments = call.children().iterator();
  arguments.next(); // skip the function name

  Iterator<Node> parameters = functionType.getParameters().iterator();
  int ordinal = 0;
  Node parameter = null;
  Node argument = null;
  while (arguments.hasNext() &&
         (parameters.hasNext() ||
          parameter != null && parameter.isVarArgs())) {
    // If there are no parameters left in the list, then the while loop
    // above implies that this must be a var_args function.
    if (parameters.hasNext()) {
      parameter = parameters.next();
    }
    argument = arguments.next();
    ordinal++;

    validator.expectArgumentMatchesParameter(t, argument,
        getJSType(argument), getJSType(parameter), call, ordinal);
  }

  int numArgs = call.getChildCount() - 1;
  int minArgs = functionType.getMinArguments();
  int maxArgs = functionType.getMaxArguments();
  if (minArgs > numArgs || maxArgs < numArgs) {
    report(t, call, WRONG_ARGUMENT_COUNT,
            validator.getReadableJSTypeName(call.getFirstChild(), false),
            String.valueOf(numArgs), String.valueOf(minArgs),
            maxArgs != Integer.MAX_VALUE ?
            " and no more than " + maxArgs + " argument(s)" : "");
  }
}
 
Example 7
Source File: Closure_20_PeepholeSubstituteAlternateSyntax_s.java    From coming with MIT License 5 votes vote down vote up
private Node tryMinimizeStringArrayLiteral(Node n) {
  if(!late) {
    return n;
  }

  int numElements = n.getChildCount();
  // We save two bytes per element.
  int saving = numElements * 2 - STRING_SPLIT_OVERHEAD;
  if (saving <= 0) {
    return n;
  }

  String[] strings = new String[n.getChildCount()];
  int idx = 0;
  for (Node cur = n.getFirstChild(); cur != null; cur = cur.getNext()) {
    strings[idx++] = cur.getString();
  }

  // These delimiters are chars that appears a lot in the program therefore
  // probably have a small Huffman encoding.
  String delimiter = pickDelimiter(strings);
  if (delimiter != null) {
    String template = Joiner.on(delimiter).join(strings);
    Node call = IR.call(
        IR.getprop(
            IR.string(template),
            IR.string("split")),
        IR.string("" + delimiter));
    call.copyInformationFromForTree(n);
    n.getParent().replaceChild(n, call);
    reportCodeChange();
    return call;
  }
  return n;
}
 
Example 8
Source File: Cardumen_00149_s.java    From coming with MIT License 4 votes vote down vote up
/** Whether the child node is the FINALLY block of a try. */
static boolean isTryFinallyNode(Node parent, Node child) {
  return parent.isTry() && parent.getChildCount() == 3
      && child == parent.getLastChild();
}
 
Example 9
Source File: Cardumen_00149_s.java    From coming with MIT License 4 votes vote down vote up
/**
 * Gets the value of a node as a Number, or null if it cannot be converted.
 * When it returns a non-null Double, this method effectively emulates the
 * <code>Number()</code> JavaScript cast function.
 */
static Double getNumberValue(Node n) {
  switch (n.getType()) {
    case Token.TRUE:
      return 1.0;

    case Token.FALSE:
    case Token.NULL:
      return 0.0;

    case Token.NUMBER:
      return n.getDouble();

    case Token.VOID:
      if (mayHaveSideEffects(n.getFirstChild())) {
        return null;
      } else {
        return Double.NaN;
      }

    case Token.NAME:
      // Check for known constants
      String name = n.getString();
      if (name.equals("undefined")) {
        return Double.NaN;
      }
      if (name.equals("NaN")) {
        return Double.NaN;
      }
      if (name.equals("Infinity")) {
        return Double.POSITIVE_INFINITY;
      }
      return null;

    case Token.NEG:
      if (n.getChildCount() == 1 && n.getFirstChild().isName()
          && n.getFirstChild().getString().equals("Infinity")) {
        return Double.NEGATIVE_INFINITY;
      }
      return null;

    case Token.NOT:
      TernaryValue child = getPureBooleanValue(n.getFirstChild());
      if (child != TernaryValue.UNKNOWN) {
        return child.toBoolean(true) ? 0.0 : 1.0; // reversed.
      }
      break;

    case Token.STRING:
      return getStringNumberValue(n.getString());

    case Token.ARRAYLIT:
    case Token.OBJECTLIT:
      String value = getStringValue(n);
      return value != null ? getStringNumberValue(value) : null;
  }

  return null;
}
 
Example 10
Source File: NodeUtil.java    From astor with GNU General Public License v2.0 4 votes vote down vote up
/** Whether the child node is the FINALLY block of a try. */
static boolean isTryFinallyNode(Node parent, Node child) {
  return parent.isTry() && parent.getChildCount() == 3
      && child == parent.getLastChild();
}
 
Example 11
Source File: Cardumen_0087_t.java    From coming with MIT License 4 votes vote down vote up
/**
 * @return Whether the node represents a FOR-IN loop.
 */
static boolean isForIn(Node n) {
  return n.isFor()
      && n.getChildCount() == 3;
}
 
Example 12
Source File: jKali_003_s.java    From coming with MIT License 4 votes vote down vote up
/**
 * Gets the value of a node as a Number, or null if it cannot be converted.
 * When it returns a non-null Double, this method effectively emulates the
 * <code>Number()</code> JavaScript cast function.
 */
static Double getNumberValue(Node n) {
  switch (n.getType()) {
    case Token.TRUE:
      return 1.0;

    case Token.FALSE:
    case Token.NULL:
      return 0.0;

    case Token.NUMBER:
      return n.getDouble();

    case Token.VOID:
      if (mayHaveSideEffects(n.getFirstChild())) {
        return null;
      } else {
        return Double.NaN;
      }

    case Token.NAME:
      // Check for known constants
      String name = n.getString();
      if (name.equals("undefined")) {
        return Double.NaN;
      }
      if (name.equals("NaN")) {
        return Double.NaN;
      }
      if (name.equals("Infinity")) {
        return Double.POSITIVE_INFINITY;
      }
      return null;

    case Token.NEG:
      if (n.getChildCount() == 1 && n.getFirstChild().isName()
          && n.getFirstChild().getString().equals("Infinity")) {
        return Double.NEGATIVE_INFINITY;
      }
      return null;

    case Token.NOT:
      TernaryValue child = getPureBooleanValue(n.getFirstChild());
      if (child != TernaryValue.UNKNOWN) {
        return child.toBoolean(true) ? 0.0 : 1.0; // reversed.
      }
      break;

    case Token.STRING:
      return getStringNumberValue(n.getString());

    case Token.ARRAYLIT:
    case Token.OBJECTLIT:
      String value = getStringValue(n);
      return value != null ? getStringNumberValue(value) : null;
  }

  return null;
}
 
Example 13
Source File: TransformAMDToCJSModule.java    From astor with GNU General Public License v2.0 4 votes vote down vote up
@Override
public void visit(NodeTraversal t, Node n, Node parent) {
  if (n.isCall() && n.getFirstChild() != null &&
      n.getFirstChild().isName() &&
      "define".equals(n.getFirstChild().getString())) {
    Scope.Var define = t.getScope().getVar(n.getFirstChild().
        getString());
    if (define != null && !define.isGlobal()) {
      // Ignore non-global define.
      return;
    }
    if (!(parent.isExprResult() && parent.getParent().isScript())) {
      t.report(n, NON_TOP_LEVEL_STATEMENT_DEFINE_ERROR);
      return;
    }
    Node script = parent.getParent();
    Node requiresNode = null;
    Node callback = null;
    int defineArity = n.getChildCount() - 1;
    if (defineArity == 0) {
      unsupportedDefineError(t, n);
      return;
    } else if (defineArity == 1) {
      callback = n.getChildAtIndex(1);
      if (callback.isObjectLit()) {
        handleDefineObjectLiteral(parent, callback, script);
        return;
      }
    } else if (defineArity == 2) {
      requiresNode = n.getChildAtIndex(1);
      callback = n.getChildAtIndex(2);
    } else if (defineArity >= 3) {
      unsupportedDefineError(t, n);
      return;
    }

    if (!callback.isFunction() ||
        (requiresNode != null && !requiresNode.isArrayLit())) {
      unsupportedDefineError(t, n);
      return;
    }

    handleRequiresAndParamList(t, n, script, requiresNode, callback);

    Node callbackBlock = callback.getChildAtIndex(2);
    NodeTraversal.traverse(compiler, callbackBlock,
        new DefineCallbackReturnCallback());

    moveCallbackContentToTopLevel(parent, script, callbackBlock);
    compiler.reportCodeChange();
  }
}
 
Example 14
Source File: jKali_0033_s.java    From coming with MIT License 4 votes vote down vote up
@Override
public void visit(NodeTraversal t, Node n, Node parent) {
  // VOID nodes appear when there are extra semicolons at the BLOCK level.
  // I've been unable to think of any cases where this indicates a bug,
  // and apparently some people like keeping these semicolons around,
  // so we'll allow it.
  if (n.isEmpty() ||
      n.isComma()) {
    return;
  }

  if (parent == null) {
    return;
  }

  // Do not try to remove a block or an expr result. We already handle
  // these cases when we visit the child, and the peephole passes will
  // fix up the tree in more clever ways when these are removed.
  if (n.isExprResult()) {
    return;
  }

  // This no-op statement was there so that JSDoc information could
  // be attached to the name. This check should not complain about it.
  if (n.isQualifiedName() && n.getJSDocInfo() != null) {
    return;
  }

  boolean isResultUsed = NodeUtil.isExpressionResultUsed(n);
  boolean isSimpleOp = NodeUtil.isSimpleOperatorType(n.getType());
  if (parent.getType() == Token.COMMA) {
    if (isResultUsed) {
      return;
    }
    if (n == parent.getLastChild()) {
      for (Node an : parent.getAncestors()) {
        int ancestorType = an.getType();
        if (ancestorType == Token.COMMA) continue;
        if (ancestorType != Token.EXPR_RESULT && ancestorType != Token.BLOCK) return;
        else break;
      }
    }
  } else if (parent.getType() != Token.EXPR_RESULT && parent.getType() != Token.BLOCK) {
    if (! (parent.getType() == Token.FOR && parent.getChildCount() == 4 && (n == parent.getFirstChild() || n == parent.getFirstChild().getNext().getNext()))) {
      return;
    }
  }
  if (
      (isSimpleOp || !NodeUtil.mayHaveSideEffects(n, t.getCompiler()))) {
    String msg = "This code lacks side-effects. Is there a bug?";
    if (n.isString()) {
      msg = "Is there a missing '+' on the previous line?";
    } else if (isSimpleOp) {
      msg = "The result of the '" + Token.name(n.getType()).toLowerCase() +
          "' operator is not being used.";
    }

    t.getCompiler().report(
        t.makeError(n, level, USELESS_CODE_ERROR, msg));
    // TODO(johnlenz): determine if it is necessary to
    // try to protect side-effect free statements as well.
    if (!NodeUtil.isStatement(n)) {
      problemNodes.add(n);
    }
  }
}
 
Example 15
Source File: Closure_80_NodeUtil_t.java    From coming with MIT License 4 votes vote down vote up
/** Whether the child node is the FINALLY block of a try. */
static boolean isTryFinallyNode(Node parent, Node child) {
  return parent.getType() == Token.TRY && parent.getChildCount() == 3
      && child == parent.getLastChild();
}
 
Example 16
Source File: Closure_1_RemoveUnusedVars_t.java    From coming with MIT License 4 votes vote down vote up
/**
 * Removes any vars in the scope that were not referenced. Removes any
 * assignments to those variables as well.
 */
private void removeUnreferencedVars() {
  CodingConvention convention = codingConvention;

  for (Iterator<Var> it = maybeUnreferenced.iterator(); it.hasNext(); ) {
    Var var = it.next();

    // Remove calls to inheritance-defining functions where the unreferenced
    // class is the subclass.
    for (Node exprCallNode : classDefiningCalls.get(var)) {
      NodeUtil.removeChild(exprCallNode.getParent(), exprCallNode);
      compiler.reportCodeChange();
    }

    // Regardless of what happens to the original declaration,
    // we need to remove all assigns, because they may contain references
    // to other unreferenced variables.
    removeAllAssigns(var);

    compiler.addToDebugLog("Unreferenced var: " + var.name);
    Node nameNode = var.nameNode;
    Node toRemove = nameNode.getParent();
    Node parent = toRemove.getParent();

    Preconditions.checkState(
        toRemove.isVar() ||
        toRemove.isFunction() ||
        toRemove.isParamList() &&
        parent.isFunction(),
        "We should only declare vars and functions and function args");

    if (toRemove.isParamList() &&
        parent.isFunction()) {
      // Don't remove function arguments here. That's a special case
      // that's taken care of in removeUnreferencedFunctionArgs.
    } else if (NodeUtil.isFunctionExpression(toRemove)) {
      if (!preserveFunctionExpressionNames) {
        toRemove.getFirstChild().setString("");
        compiler.reportCodeChange();
      }
      // Don't remove bleeding functions.
    } else if (parent != null &&
        parent.isFor() &&
        parent.getChildCount() < 4) {
      // foreach iterations have 3 children. Leave them alone.
    } else if (toRemove.isVar() &&
        nameNode.hasChildren() &&
        NodeUtil.mayHaveSideEffects(nameNode.getFirstChild(), compiler)) {
      // If this is a single var declaration, we can at least remove the
      // declaration itself and just leave the value, e.g.,
      // var a = foo(); => foo();
      if (toRemove.getChildCount() == 1) {
        parent.replaceChild(toRemove,
            IR.exprResult(nameNode.removeFirstChild()));
        compiler.reportCodeChange();
      }
    } else if (toRemove.isVar() &&
        toRemove.getChildCount() > 1) {
      // For var declarations with multiple names (i.e. var a, b, c),
      // only remove the unreferenced name
      toRemove.removeChild(nameNode);
      compiler.reportCodeChange();
    } else if (parent != null) {
      NodeUtil.removeChild(parent, toRemove);
      compiler.reportCodeChange();
    }
  }
}
 
Example 17
Source File: jMutRepair_0032_t.java    From coming with MIT License 4 votes vote down vote up
@Override
public void visit(NodeTraversal t, Node n, Node parent) {
  // VOID nodes appear when there are extra semicolons at the BLOCK level.
  // I've been unable to think of any cases where this indicates a bug,
  // and apparently some people like keeping these semicolons around,
  // so we'll allow it.
  if (n.isEmpty() ||
      n.isComma()) {
    return;
  }

  if (parent == null) {
    return;
  }

  // Do not try to remove a block or an expr result. We already handle
  // these cases when we visit the child, and the peephole passes will
  // fix up the tree in more clever ways when these are removed.
  if (parent.getType() == Token.COMMA) {
    Node gramps = parent.getParent();
    if (gramps.isCall() && parent == gramps.getFirstChild()) {
      if (n == parent.getFirstChild() && parent.getChildCount() == 2 && n.getNext().isName() && "eval".equals(n.getNext().getString())) {
    return;
      }
  }

  // This no-op statement was there so that JSDoc information could
  // be attached to the name. This check should not complain about it.
    if (n == parent.getLastChild()) {
      for (Node an : parent.getAncestors()) {
        int ancestorType = an.getType();
        if (ancestorType == Token.COMMA)
          continue;
        if (ancestorType != Token.EXPR_RESULT && ancestorType == Token.BLOCK)
          return;
        else
          break;
      }
    }
  } else if (parent.getType() != Token.EXPR_RESULT && parent.getType() != Token.BLOCK) {
    if (parent.getType() == Token.FOR && parent.getChildCount() == 4 && (n == parent.getFirstChild() ||
         n == parent.getFirstChild().getNext().getNext())) {
    } else {
    return;
    }
  }

  boolean isResultUsed = NodeUtil.isExpressionResultUsed(n);
  boolean isSimpleOp = NodeUtil.isSimpleOperatorType(n.getType());
  if (!isResultUsed &&
      (isSimpleOp || !NodeUtil.mayHaveSideEffects(n, t.getCompiler()))) {
    if (n.isQualifiedName() && n.getJSDocInfo() != null) {
      return;
    } else if (n.isExprResult()) {
      return;
    }
    String msg = "This code lacks side-effects. Is there a bug?";
    if (n.isString()) {
      msg = "Is there a missing '+' on the previous line?";
    } else if (isSimpleOp) {
      msg = "The result of the '" + Token.name(n.getType()).toLowerCase() +
          "' operator is not being used.";
    }

    t.getCompiler().report(
        t.makeError(n, level, USELESS_CODE_ERROR, msg));
    // TODO(johnlenz): determine if it is necessary to
    // try to protect side-effect free statements as well.
    if (!NodeUtil.isStatement(n)) {
      problemNodes.add(n);
    }
  }
}
 
Example 18
Source File: 1_NodeUtil.java    From SimFix with GNU General Public License v2.0 4 votes vote down vote up
/**
 * @return Whether the node represents a FOR-IN loop.
 */
static boolean isForIn(Node n) {
  return n.getType() == Token.FOR
      && n.getChildCount() == 3;
}
 
Example 19
Source File: ReplaceCssNames.java    From astor with GNU General Public License v2.0 4 votes vote down vote up
@Override
public void visit(NodeTraversal t, Node n, Node parent) {
  if (n.isCall() &&
      GET_CSS_NAME_FUNCTION.equals(n.getFirstChild().getQualifiedName())) {
    int count = n.getChildCount();
    Node first = n.getFirstChild().getNext();
    switch (count) {
      case 2:
        // Replace the function call with the processed argument.
        if (first.isString()) {
          processStringNode(t, first);
          n.removeChild(first);
          parent.replaceChild(n, first);
          compiler.reportCodeChange();
        } else {
          compiler.report(t.makeError(n, STRING_LITERAL_EXPECTED_ERROR,
              Token.name(first.getType())));
        }
        break;

      case 3:
        // Replace function call with concatenation of two args.  It's
        // assumed the first arg has already been processed.

        Node second = first.getNext();

        if (!second.isString()) {
          compiler.report(t.makeError(n, STRING_LITERAL_EXPECTED_ERROR,
              Token.name(second.getType())));
        } else if (first.isString()) {
          compiler.report(t.makeError(
              n, UNEXPECTED_STRING_LITERAL_ERROR,
              first.getString(), second.getString()));
        } else {
          processStringNode(t, second);
          n.removeChild(first);
          Node replacement = IR.add(first,
              IR.string("-" + second.getString())
                  .copyInformationFrom(second))
              .copyInformationFrom(n);
          replacement.setJSType(nativeStringType);
          parent.replaceChild(n, replacement);
          compiler.reportCodeChange();
        }
        break;

      default:
        compiler.report(t.makeError(
            n, INVALID_NUM_ARGUMENTS_ERROR, String.valueOf(count)));
    }
  }
}
 
Example 20
Source File: jKali_003_s.java    From coming with MIT License 4 votes vote down vote up
/**
 * @returns false iff the result of the expression is not consumed.
 */
static boolean isExpressionResultUsed(Node expr) {
  // TODO(johnlenz): consider sharing some code with trySimpleUnusedResult.
  Node parent = expr.getParent();
  switch (parent.getType()) {
    case Token.BLOCK:
    case Token.EXPR_RESULT:
      return false;
    case Token.HOOK:
    case Token.AND:
    case Token.OR:
      return (expr == parent.getFirstChild())
          ? true : isExpressionResultUsed(parent);
    case Token.COMMA:
      Node gramps = parent.getParent();
      if (gramps.isCall() &&
          parent == gramps.getFirstChild()) {
        // Semantically, a direct call to eval is different from an indirect
        // call to an eval. See ECMA-262 S15.1.2.1. So it's OK for the first
        // expression to a comma to be a no-op if it's used to indirect
        // an eval. This we pretend that this is "used".
        if (expr == parent.getFirstChild() &&
            parent.getChildCount() == 2 &&
            expr.getNext().isName() &&
            "eval".equals(expr.getNext().getString())) {
          return true;
        }
      }

      return (expr == parent.getFirstChild())
          ? false : isExpressionResultUsed(parent);
    case Token.FOR:
      if (!NodeUtil.isForIn(parent)) {
        // Only an expression whose result is in the condition part of the
        // expression is used.
        return (parent.getChildAtIndex(1) == expr);
      }
      break;
  }
  return true;
}