boolean isLetDeclaration() { return getParent().isLet(); }
boolean isLetDeclaration() { return getParent().isLet(); }
/** * Is this node a name declaration? * * @param n The node * @return True if {@code n} is VAR, LET or CONST */ public static boolean isNameDeclaration(Node n) { return n.isVar() || n.isLet() || n.isConst(); }
/** * Check that a let declaration is not used with {@defines} */ private void validateDefinesDeclaration(Node n, JSDocInfo info) { if (info != null && info.isDefine() && n.isLet()) { report(n, INVALID_DEFINE_ON_LET); } }
/** * Is this node a name declaration? * * @param n The node * @return True if {@code n} is VAR, LET or CONST */ public static boolean isNameDeclaration(Node n) { return n != null && (n.isVar() || n.isLet() || n.isConst()); }
public static Node forNode(Node init, Node cond, Node incr, Node body) { checkState(init.isVar() || init.isLet() || init.isConst() || mayBeExpressionOrEmpty(init)); checkState(mayBeExpressionOrEmpty(cond)); checkState(mayBeExpressionOrEmpty(incr)); checkState(body.isBlock()); return new Node(Token.FOR, init, cond, incr, body); }
/** * Detect any block-scoped declarations that are younger siblings of the given starting point. * * @param start The start point */ private static boolean hasBlockScopedVarsFollowing(Node start) { for (Node n = start.getNext(); n != null; n = n.getNext()) { if (n.isLet() || n.isConst()) { return true; } } return false; } }
/** * This is similar to NodeUtil.isLValue except that object properties and * array member modification aren't important ("o" in "o.a = 2" is still "o" * after assignment, where in as "o = x", "o" is now "x"). * * This also looks for the redefinition of a name. * function (x) {var x;} * * @param n The NAME node in question. * @param parent The parent of the node. */ private static boolean canNameValueChange(Node n) { return NodeUtil.isLValue(n) && !NodeUtil.getEnclosingStatement(n).isConst() && !NodeUtil.getEnclosingStatement(n).isLet(); }
/** * Determines whether the variable is initialized at the declaration. */ boolean isInitializingDeclaration() { // VAR and LET are the only types of variable declarations that may not initialize // their variables. Catch blocks, named functions, and parameters all do. return (isDeclaration() && !getParent().isVar() && !getParent().isLet()) || nameNode.getFirstChild() != null; }
/** Determines whether the variable is initialized at the declaration. */ public boolean isInitializingDeclaration() { // VAR and LET are the only types of variable declarations that may not initialize // their variables. Catch blocks, named functions, and parameters all do. return (isDeclaration() && !getParent().isVar() && !getParent().isLet()) || nameNode.hasChildren(); }
private void checkShortGoogRequireCall(NodeTraversal t, Node callNode, Node declaration) { if (declaration.isLet()) { t.report(declaration, LET_GOOG_REQUIRE); } if (declaration.getChildCount() != 1) { t.report(declaration, ONE_REQUIRE_PER_DECLARATION); } Node lhs = declaration.getFirstChild(); String shortName = lhs.isName() ? lhs.getString() : null; shortRequiredNamespaces.put(extractFirstArgumentName(callNode), shortName); } }
/** Matches destructing from a variable ie `const {foo, bar: baz} = quux;` */ protected static boolean isVariableDestructuringAssignment(Node statement) { if (!(statement.isConst() || statement.isVar() || statement.isLet())) { return false; } if (!statement.getFirstChild().isDestructuringLhs()) { return false; } Node destructuringAssignment = statement.getFirstChild(); Node rightHandSide = destructuringAssignment.getChildAtIndex(1); return rightHandSide.isName(); }
@Override public void visit(NodeTraversal t, Node n, Node parent) { if (!n.hasChildren() || !NodeUtil.isBlockScopedDeclaration(n.getFirstChild())) { return; } // NOTE: This pass depends on for-of being transpiled away before it runs. checkState(parent == null || !parent.isForOf(), parent); if (n.isLet() || n.isConst()) { letConsts.add(n); } if (NodeUtil.isNameDeclaration(n)) { for (Node nameNode : n.children()) { visitBlockScopedName(t, n, nameNode); } } else { // NOTE: This pass depends on class declarations having been transpiled away checkState(n.isFunction() || n.isCatch(), "Unexpected declaration node: %s", n); visitBlockScopedName(t, n, n.getFirstChild()); } }
/** * Convert all let/const declarations following the start node to var declarations if possible. * * <p>See the unit tests for examples of why this is necessary before moving code into an inner * block, and why this is unsafe to do to declarations inside a loop. * * @param start The start point * @return Whether all block-scoped declarations have been converted. */ private static boolean tryConvertAllBlockScopedFollowing(Node start) { if (NodeUtil.isWithinLoop(start)) { // If in a loop, don't convert anything to a var. Return true only if there are no let/consts. return !hasBlockScopedVarsFollowing(start); } for (Node n = start.getNext(); n != null; n = n.getNext()) { if (n.isLet() || n.isConst()) { n.setToken(Token.VAR); } } return true; }
Node processLabeledStatement(LabelledStatementTree labelTree) { Node statement = transform(labelTree.statement); if (statement.isFunction() || statement.isClass() || statement.isLet() || statement.isConst()) { errorReporter.error( "Lexical declarations are only allowed at top level or inside a block.", sourceName, lineno(labelTree), charno(labelTree)); return statement; // drop the LABEL node so that the resulting AST is valid } return newNode(Token.LABEL, transformLabelName(labelTree.name), statement); }
/** * Matches either `const foo = goog.require()` or `const foo = goog.module.get()` or `const foo = * goog.forwardDeclare()` depending on if statement is in a goog.module or a goog.scope. */ protected static boolean isImportAssignment(Node statement) { if (!(statement.isConst() || statement.isVar() || statement.isLet())) { return false; } Node rightHandSide = statement.getFirstFirstChild(); return rightHandSide != null && rightHandSide.isCall() && (rightHandSide.getFirstChild().matchesQualifiedName("goog.require") || rightHandSide.getFirstChild().matchesQualifiedName("goog.module.get") || rightHandSide.getFirstChild().matchesQualifiedName("goog.forwardDeclare")); }
@Override public void visit(NodeTraversal t, Node n, Node parent) { JSDocInfo bestJSDocInfo = NodeUtil.getBestJSDocInfo(n); if (bestJSDocInfo == null) { return; } // Add visibility for private and protected. if (Visibility.PRIVATE.equals(bestJSDocInfo.getVisibility())) { n.putProp(Node.ACCESS_MODIFIER, Visibility.PRIVATE); } else if (Visibility.PROTECTED.equals(bestJSDocInfo.getVisibility())) { n.putProp(Node.ACCESS_MODIFIER, Visibility.PROTECTED); } // Change variable declarations to constants if (bestJSDocInfo.isConstant() && (n.isVar() || n.isLet())) { n.setToken(Token.CONST); } } }
private void checkShortGoogRequireCall(NodeTraversal t, Node callNode, Node declaration) { if (declaration.isLet() && !callNode.getFirstChild().matchesQualifiedName("goog.forwardDeclare")) { t.report(declaration, LET_GOOG_REQUIRE); } if (!declaration.hasOneChild()) { t.report(declaration, ONE_REQUIRE_PER_DECLARATION); return; } Node lhs = declaration.getFirstChild(); if (lhs.isDestructuringLhs()) { if (!isValidDestructuringImport(lhs)) { t.report(declaration, INVALID_DESTRUCTURING_REQUIRE); } if (callNode.getFirstChild().matchesQualifiedName("goog.forwardDeclare")) { t.report(lhs, INVALID_DESTRUCTURING_FORWARD_DECLARE); } } else { checkState(lhs.isName()); checkShortName(t, lhs, callNode.getLastChild().getString()); } currentModuleInfo.importsByLongRequiredName.put(extractFirstArgumentName(callNode), lhs); for (Node nameNode : NodeUtil.findLhsNodesInNode(declaration)) { String name = nameNode.getString(); if (!currentModuleInfo.shortImportNames.add(name)) { t.report(nameNode, DUPLICATE_NAME_SHORT_REQUIRE, name); } } }
/** * Matches either `const {foo} = goog.require()` or `const {foo} = goog.module.get()` depending on * if statement is in a goog.module or a goog.scope. */ protected static boolean isImportDestructuringAssignment(Node statement) { if (!(statement.isConst() || statement.isVar() || statement.isLet())) { return false; } if (!statement.getFirstChild().isDestructuringLhs()) { return false; } Node destructuringAssignment = statement.getFirstChild(); Node rightHandSide = destructuringAssignment.getChildAtIndex(1); return rightHandSide.isCall() && (rightHandSide.getFirstChild().matchesQualifiedName("goog.require") || rightHandSide.getFirstChild().matchesQualifiedName("goog.module.get")); }
/** * For all VAR node with uninitialized declarations, set * the values to be "undefined". */ private static void fixUninitializedVarDeclarations(Node n, Node containingBlock) { // Inner loop structure must already have logic to initialize its // variables. In particular FOR-IN structures must not be modified. if (NodeUtil.isLoopStructure(n)) { return; } if ((n.isVar() || n.isLet()) && n.hasOneChild()) { Node name = n.getFirstChild(); // It isn't initialized. if (!name.hasChildren()) { Node srcLocation = name; name.addChildToBack(NodeUtil.newUndefinedNode(srcLocation)); containingBlock.addChildToFront(n.detach()); } return; } for (Node c = n.getFirstChild(); c != null; c = c.getNext()) { fixUninitializedVarDeclarations(c, containingBlock); } }