@Override public void visit(NodeTraversal t, Node n, Node parent) { if (parent != null && parent.isDestructuringLhs()) { parent = parent.getParent(); } switch (n.getToken()) { case ARRAY_PATTERN: case OBJECT_PATTERN: visitPattern(t, n, parent); if (n == this.patternNestingStack.getLast().pattern) { this.patternNestingStack.removeLast(); } break; default: break; } }
private void processDeclarationWithRhs(NodeTraversal t, Node lhs) { checkArgument( lhs.isQualifiedName() || lhs.isStringKey() || lhs.isDestructuringLhs(), lhs); checkState(NodeUtil.getRValueOfLValue(lhs) != null, lhs); if (!PotentialDeclaration.isConstToBeInferred(lhs)) { return; } processConstWithRhs(t, lhs); }
private void visitForOf(Node node) { Node lhs = node.getFirstChild(); if (lhs.isDestructuringLhs()) { visitDestructuringPatternInEnhancedFor(lhs.getFirstChild()); } }
/** * @param n The node * @return True if {@code n} is a VAR, LET or CONST that contains a * destructuring pattern. */ static boolean isDestructuringDeclaration(Node n) { if (isNameDeclaration(n)) { for (Node c = n.getFirstChild(); c != null; c = c.getNext()) { if (c.isDestructuringLhs()) { return true; } } } return false; }
/** * @param n The node * @return True if {@code n} is a VAR, LET or CONST that contains a * destructuring pattern. */ static boolean isDestructuringDeclaration(Node n) { if (isNameDeclaration(n)) { for (Node c = n.getFirstChild(); c != null; c = c.getNext()) { if (c.isDestructuringLhs()) { return true; } } } return false; }
public static Node declaration(Node lhs, Token type) { checkState(lhs.isName() || lhs.isDestructuringPattern() || lhs.isDestructuringLhs(), lhs); if (lhs.isDestructuringPattern()) { lhs = new Node(Token.DESTRUCTURING_LHS, lhs); } return new Node(type, lhs); }
public static Node declaration(Node lhs, int type) { Preconditions.checkState( lhs.isName() || lhs.isDestructuringPattern() || lhs.isDestructuringLhs(), lhs); if (lhs.isDestructuringPattern()) { lhs = new Node(Token.DESTRUCTURING_LHS, lhs); } return new Node(type, lhs); }
@Override public void visit(NodeTraversal t, Node n, Node parent) { @Nullable Node child = n.getFirstChild(); if (child != null && child.isDestructuringLhs()) { Node potentialImportSpec = child.getFirstChild(); Node potentialModuleName = child.getSecondChild(); if (potentialImportSpec != null && potentialModuleName != null && potentialModuleName.isName()) { destructuringAssignments.put( potentialModuleName.getSourceFileName(), potentialModuleName.getQualifiedName(), potentialImportSpec); } } } }
@Override public void visit(NodeTraversal t, Node n, Node parent) { if (parent != null && parent.isDestructuringLhs()) { parent = parent.getParent(); } switch (n.getType()) { case Token.ARRAY_PATTERN: visitArrayPattern(t, n, parent); break; case Token.OBJECT_PATTERN: visitObjectPattern(t, n, parent); break; } }
private void checkPropertyAccessForDestructuring( NodeTraversal t, Node pattern, JSType objectType, Node stringKey, JSType inferredPropType) { checkArgument(pattern.isDestructuringPattern(), pattern); checkArgument(stringKey.isStringKey(), stringKey); // Get the object node being destructured when it exists. These cases have an actual node `obj`: // const {a} = obj; // ({a} = obj); // while these do not: // for (const {a} of arrayOfObjects) { // const {{a}} = obj; Node objNode = null; Node patternParent = pattern.getParent(); if ((patternParent.isAssign() || patternParent.isDestructuringLhs()) && pattern.getNext() != null) { objNode = pattern.getNext(); } checkPropertyAccess(objectType, t, /* getProp= */ null, inferredPropType, stringKey, objNode); }
private FlowScope traverseDeclarationChild(Node n, FlowScope scope) { if (n.isName()) { return traverseName(n, scope); } checkState(n.isDestructuringLhs(), n); scope = traverse(n.getSecondChild(), scope); return traverseDestructuringPattern( n.getFirstChild(), scope, getJSType(n.getSecondChild()), AssignmentType.DECLARATION); }
private boolean isValidDestructuringImport(Node destructuringLhs) { checkArgument(destructuringLhs.isDestructuringLhs()); Node objectPattern = destructuringLhs.getFirstChild(); if (!objectPattern.isObjectPattern()) { return false; } for (Node stringKey : objectPattern.children()) { if (!stringKey.isStringKey()) { return false; } if (stringKey.hasChildren() && !stringKey.getFirstChild().isName()) { return false; } } return true; }
private static boolean isValidDestructuringImport(Node destructuringLhs) { checkArgument(destructuringLhs.isDestructuringLhs()); Node objectPattern = destructuringLhs.getFirstChild(); if (!objectPattern.isObjectPattern()) { return false; } for (Node stringKey : objectPattern.children()) { if (!stringKey.isStringKey()) { return false; } if (stringKey.hasChildren() && !stringKey.getFirstChild().isName()) { return false; } } return true; } }
private void validateNameDeclarationChild(int type, Node n) { if (n.isName()) { validateLHS(type, n); } else if (n.isDestructuringLhs()) { validateLHS(type, n.getFirstChild()); } else { violation("Invalid child for " + Token.name(type) + " node", n); } }
/** 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(); }
private void validateNameDeclarationChild(Token type, Node n) { if (n.isName()) { // Don't use validateName here since this NAME node may have // a child. validateNonEmptyString(n); validateMaximumChildCount(n, 1); if (n.hasChildren()) { validateExpression(n.getFirstChild()); } } else if (n.isDestructuringLhs()) { validateDestructuringLhs(type, n); } else { violation("Invalid child for " + type + " node", n); } }
@Override protected void processConstWithRhs(NodeTraversal t, Node nameNode) { checkArgument( nameNode.isQualifiedName() || nameNode.isStringKey() || nameNode.isDestructuringLhs(), nameNode); Node jsdocNode = NodeUtil.getBestJSDocInfoNode(nameNode); JSDocInfo originalJsdoc = jsdocNode.getJSDocInfo(); Node rhs = NodeUtil.getRValueOfLValue(nameNode); JSDocInfo newJsdoc = JsdocUtil.getJSDocForRhs(rhs, originalJsdoc); if (newJsdoc == null && ClassUtil.isThisProp(nameNode)) { Var decl = findNameDeclaration(t.getScope(), rhs); newJsdoc = JsdocUtil.getJSDocForName(decl, originalJsdoc); } if (newJsdoc != null) { jsdocNode.setJSDocInfo(newJsdoc); t.reportCodeChange(); } } }
private static final String getNamespace(Node requireStatement) { if (requireStatement.isExprResult()) { // goog.require('a.b.c'); return requireStatement.getFirstChild().getLastChild().getString(); } else if (NodeUtil.isNameDeclaration(requireStatement)) { if (requireStatement.getFirstChild().isName()) { // const x = goog.require('a.b.c'); return requireStatement.getFirstFirstChild().getLastChild().getString(); } else if (requireStatement.getFirstChild().isDestructuringLhs()) { // const {x} = goog.require('a.b.c'); return requireStatement.getFirstChild().getLastChild().getLastChild().getString(); } } throw new IllegalArgumentException("Unexpected node " + requireStatement); }
/** * 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")); }
void check(Node n) { // For most AST nodes, traverse the subtree in postorder because that's how the expressions // are evaluated. if (n == root || !ControlFlowGraph.isEnteringNewCfgNode(n)) { if ((n.isDestructuringLhs() && n.hasTwoChildren()) || (n.isAssign() && n.getFirstChild().isDestructuringPattern()) || n.isDefaultValue()) { // Evaluate the rhs of a destructuring assignment/declaration before the lhs. check(n.getSecondChild()); check(n.getFirstChild()); } else { for (Node c = n.getFirstChild(); c != null; c = c.getNext()) { check(c); } } visit(n, n.getParent()); } }