getFoldableRangesAtIndentLevel(goalLevel) {
    let result = [];
    let stack = [{ node: this.tree.rootNode, level: 0 }];
    while (stack.length > 0) {
      const { node, level } = stack.pop();

      const range = this.getFoldableRangeForNode(node, this.grammar);
      if (range) {
        if (goalLevel == null || level === goalLevel) {
          let updatedExistingRange = false;
          for (let i = 0, { length } = result; i < length; i++) {
            if (
              result[i].start.row === range.start.row &&
              result[i].end.row === range.end.row
            ) {
              result[i] = range;
              updatedExistingRange = true;
              break;
            }
          }
          if (!updatedExistingRange) result.push(range);
        }
      }

      const parentStartRow = node.startPosition.row;
      const parentEndRow = node.endPosition.row;
      for (
        let children = node.namedChildren, i = 0, { length } = children;
        i < length;
        i++
      ) {
        const child = children[i];
        const { startPosition: childStart, endPosition: childEnd } = child;
        if (childEnd.row > childStart.row) {
          if (
            childStart.row === parentStartRow &&
            childEnd.row === parentEndRow
          ) {
            stack.push({ node: child, level: level });
          } else {
            const childLevel =
              range &&
              range.containsPoint(childStart) &&
              range.containsPoint(childEnd)
                ? level + 1
                : level;
            if (childLevel <= goalLevel || goalLevel == null) {
              stack.push({ node: child, level: childLevel });
            }
          }
        }
      }
    }

    return result.sort((a, b) => a.start.row - b.start.row);
  }
TODO: Make this method generate folds for nested languages (currently,
folds are only generated for the root language layer).