private void visitComponents(ComprehensionElementVisitor visitor) {
    ASTNode node = getNode().getFirstChildNode();
    while (node != null) {
      IElementType type = node.getElementType();
      ASTNode next = getNextExpression(node);
      if (next == null) break;
      if (type == PyTokenTypes.FOR_KEYWORD) {
        ASTNode next2 = getNextExpression(next);
        if (next2 == null) break;
        final PyAstExpression variable = (PyAstExpression)next.getPsi();
        final PyAstExpression iterated = (PyAstExpression)next2.getPsi();
        final boolean isAsync = Optional
          .ofNullable(node.getTreePrev())
          .map(ASTNode::getTreePrev)
          .map(asyncNode -> asyncNode.getElementType() == PyTokenTypes.ASYNC_KEYWORD)
          .orElse(false);

        visitor.visitForComponent(new PyComprehensionForComponent() {
          @Override
          public PyAstExpression getIteratorVariable() {
            return variable;
          }

          @Override
          public PyAstExpression getIteratedList() {
            return iterated;
          }

          @Override
          public boolean isAsync() {
            return isAsync;
          }
        });
      }
      else if (type == PyTokenTypes.IF_KEYWORD) {
        final PyAstExpression test = (PyAstExpression)next.getPsi();
        visitor.visitIfComponent(new PyComprehensionIfComponent() {
          @Override
          public PyAstExpression getTest() {
            return test;
          }
        });
      }
      node = node.getTreeNext();
    }
  }
private void visitComponents(ComprehensionElementVisitor visitor)