diff --git a/spec/tree-sitter-language-mode-spec.js b/spec/tree-sitter-language-mode-spec.js index 0eeeb8b93..fe9ec239b 100644 --- a/spec/tree-sitter-language-mode-spec.js +++ b/spec/tree-sitter-language-mode-spec.js @@ -336,6 +336,20 @@ describe('TreeSitterLanguageMode', () => { #ifndef FOO_H_… #endif `) + + editor.foldAllAtIndentLevel(1) + expect(getDisplayText(editor)).toBe(dedent ` + #ifndef FOO_H_ + #define FOO_H_ + + #ifdef _WIN32… + #elif defined MACOS… + #else… + + #endif + + #endif + `) }) describe('when folding a node that ends with a line break', () => { diff --git a/src/text-editor.js b/src/text-editor.js index e24476b2d..08d07aa71 100644 --- a/src/text-editor.js +++ b/src/text-editor.js @@ -3891,7 +3891,7 @@ class TextEditor { // Extended: Fold all foldable lines at the given indent level. // - // * `level` A {Number}. + // * `level` A {Number} starting at 0. foldAllAtIndentLevel (level) { const languageMode = this.buffer.getLanguageMode() const foldableRanges = ( diff --git a/src/tree-sitter-language-mode.js b/src/tree-sitter-language-mode.js index a76043638..6eec047c3 100644 --- a/src/tree-sitter-language-mode.js +++ b/src/tree-sitter-language-mode.js @@ -138,10 +138,7 @@ class TreeSitterLanguageMode { let stack = [{node: this.document.rootNode, level: 0}] while (stack.length > 0) { const {node, level} = stack.pop() - const startRow = node.startPosition.row - const endRow = node.endPosition.row - let childLevel = level const range = this.getFoldableRangeForNode(node) if (range) { if (goalLevel == null || level === goalLevel) { @@ -155,18 +152,23 @@ class TreeSitterLanguageMode { } if (!updatedExistingRange) result.push(range) } - childLevel++ } + 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 childStartRow = child.startPosition.row - const childEndRow = child.endPosition.row - if (childEndRow > childStartRow) { - if (childStartRow === startRow && childEndRow === endRow) { + 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 if (childLevel <= goalLevel || goalLevel == null) { - stack.push({node: child, level: childLevel}) + } else { + const childLevel = range.containsPoint(childStart) && range.containsPoint(childEnd) + ? level + 1 + : level + if (childLevel <= goalLevel || goalLevel == null) { + stack.push({node: child, level: childLevel}) + } } } }