diff --git a/src/vs/editor/common/model/indentRanges.ts b/src/vs/editor/common/model/indentRanges.ts index 3a7773f592e769234f85c857b9652baff8b3eb67..21a5311146bc46dec29ddfc5f22ff584a1e253e8 100644 --- a/src/vs/editor/common/model/indentRanges.ts +++ b/src/vs/editor/common/model/indentRanges.ts @@ -61,41 +61,47 @@ export function computeRanges(model: ITextModel, offSide: boolean, markers?: Fol // folding pattern match if (m[1]) { // start pattern match // discard all regions until the folding pattern - while (previous.indent >= 0 && !previous.marker) { - previousRegions.pop(); - previous = previousRegions[previousRegions.length - 1]; + let i = previousRegions.length - 1; + while (i > 0 && !previousRegions[i].marker) { + i--; } - if (previous.marker) { + if (i > 0) { + previousRegions.length = i + 1; + previous = previousRegions[i]; + // new folding range from pattern, includes the end line result.push(new IndentRange(line, previous.line, indent, true)); previous.marker = false; previous.indent = indent; previous.line = line; + continue; + } else { + // no end marker found, treat line as a regular line } } else { // end pattern match previousRegions.push({ indent: -2, line, marker: true }); + continue; } - } else { - if (previous.indent > indent) { - // discard all regions with larger indent - do { - previousRegions.pop(); - previous = previousRegions[previousRegions.length - 1]; - } while (previous.indent > indent); + } + if (previous.indent > indent) { + // discard all regions with larger indent + do { + previousRegions.pop(); + previous = previousRegions[previousRegions.length - 1]; + } while (previous.indent > indent); - // new folding range - let endLineNumber = previous.line - 1; - if (endLineNumber - line >= minimumRangeSize) { - result.push(new IndentRange(line, endLineNumber, indent)); - } - } - if (previous.indent === indent) { - previous.line = line; - } else { // previous.indent < indent - // new region with a bigger indent - previousRegions.push({ indent, line, marker: false }); + // new folding range + let endLineNumber = previous.line - 1; + if (endLineNumber - line >= minimumRangeSize) { + result.push(new IndentRange(line, endLineNumber, indent)); } } + if (previous.indent === indent) { + previous.line = line; + } else { // previous.indent < indent + // new region with a bigger indent + previousRegions.push({ indent, line, marker: false }); + } } return result.reverse(); diff --git a/src/vs/editor/test/common/model/indentRanges.test.ts b/src/vs/editor/test/common/model/indentRanges.test.ts index 8d90c5a26352083e7807eaa8132850c571ada36c..6d09f3f1ce202b6f6c9a7c2f91f2cf2c0926e335 100644 --- a/src/vs/editor/test/common/model/indentRanges.test.ts +++ b/src/vs/editor/test/common/model/indentRanges.test.ts @@ -29,125 +29,125 @@ function r(startLineNumber: number, endLineNumber: number, indent: number, marke return { startLineNumber, endLineNumber, indent, marker }; } -// suite('Indentation Folding', () => { +suite('Indentation Folding', () => { -// test('Fold one level', () => { -// let range = [ -// 'A', -// ' A', -// ' A', -// ' A' -// ]; -// assertRanges(range, [r(1, 4, 0)], true); -// assertRanges(range, [r(1, 4, 0)], false); -// }); + test('Fold one level', () => { + let range = [ + 'A', + ' A', + ' A', + ' A' + ]; + assertRanges(range, [r(1, 4, 0)], true); + assertRanges(range, [r(1, 4, 0)], false); + }); -// test('Fold two levels', () => { -// let range = [ -// 'A', -// ' A', -// ' A', -// ' A', -// ' A' -// ]; -// assertRanges(range, [r(1, 5, 0), r(3, 5, 2)], true); -// assertRanges(range, [r(1, 5, 0), r(3, 5, 2)], false); -// }); + test('Fold two levels', () => { + let range = [ + 'A', + ' A', + ' A', + ' A', + ' A' + ]; + assertRanges(range, [r(1, 5, 0), r(3, 5, 2)], true); + assertRanges(range, [r(1, 5, 0), r(3, 5, 2)], false); + }); -// test('Fold three levels', () => { -// let range = [ -// 'A', -// ' A', -// ' A', -// ' A', -// 'A' -// ]; -// assertRanges(range, [r(1, 4, 0), r(2, 4, 2), r(3, 4, 4)], true); -// assertRanges(range, [r(1, 4, 0), r(2, 4, 2), r(3, 4, 4)], false); -// }); + test('Fold three levels', () => { + let range = [ + 'A', + ' A', + ' A', + ' A', + 'A' + ]; + assertRanges(range, [r(1, 4, 0), r(2, 4, 2), r(3, 4, 4)], true); + assertRanges(range, [r(1, 4, 0), r(2, 4, 2), r(3, 4, 4)], false); + }); -// test('Fold decreasing indent', () => { -// let range = [ -// ' A', -// ' A', -// 'A' -// ]; -// assertRanges(range, [], true); -// assertRanges(range, [], false); -// }); + test('Fold decreasing indent', () => { + let range = [ + ' A', + ' A', + 'A' + ]; + assertRanges(range, [], true); + assertRanges(range, [], false); + }); -// test('Fold Java', () => { -// assertRanges([ -// /* 1*/ 'class A {', -// /* 2*/ ' void foo() {', -// /* 3*/ ' console.log();', -// /* 4*/ ' console.log();', -// /* 5*/ ' }', -// /* 6*/ '', -// /* 7*/ ' void bar() {', -// /* 8*/ ' console.log();', -// /* 9*/ ' }', -// /*10*/ '}', -// /*11*/ 'interface B {', -// /*12*/ ' void bar();', -// /*13*/ '}', -// ], [r(1, 9, 0), r(2, 4, 2), r(7, 8, 2), r(11, 12, 0)], false); -// }); + test('Fold Java', () => { + assertRanges([ + /* 1*/ 'class A {', + /* 2*/ ' void foo() {', + /* 3*/ ' console.log();', + /* 4*/ ' console.log();', + /* 5*/ ' }', + /* 6*/ '', + /* 7*/ ' void bar() {', + /* 8*/ ' console.log();', + /* 9*/ ' }', + /*10*/ '}', + /*11*/ 'interface B {', + /*12*/ ' void bar();', + /*13*/ '}', + ], [r(1, 9, 0), r(2, 4, 2), r(7, 8, 2), r(11, 12, 0)], false); + }); -// test('Fold Javadoc', () => { -// assertRanges([ -// /* 1*/ '/**', -// /* 2*/ ' * Comment', -// /* 3*/ ' */', -// /* 4*/ 'class A {', -// /* 5*/ ' void foo() {', -// /* 6*/ ' }', -// /* 7*/ '}', -// ], [r(1, 3, 0), r(4, 6, 0)], false); -// }); -// test('Fold Whitespace Java', () => { -// assertRanges([ -// /* 1*/ 'class A {', -// /* 2*/ '', -// /* 3*/ ' void foo() {', -// /* 4*/ ' ', -// /* 5*/ ' return 0;', -// /* 6*/ ' }', -// /* 7*/ ' ', -// /* 8*/ '}', -// ], [r(1, 7, 0), r(3, 5, 2)], false); -// }); + test('Fold Javadoc', () => { + assertRanges([ + /* 1*/ '/**', + /* 2*/ ' * Comment', + /* 3*/ ' */', + /* 4*/ 'class A {', + /* 5*/ ' void foo() {', + /* 6*/ ' }', + /* 7*/ '}', + ], [r(1, 3, 0), r(4, 6, 0)], false); + }); + test('Fold Whitespace Java', () => { + assertRanges([ + /* 1*/ 'class A {', + /* 2*/ '', + /* 3*/ ' void foo() {', + /* 4*/ ' ', + /* 5*/ ' return 0;', + /* 6*/ ' }', + /* 7*/ ' ', + /* 8*/ '}', + ], [r(1, 7, 0), r(3, 5, 2)], false); + }); -// test('Fold Whitespace Python', () => { -// assertRanges([ -// /* 1*/ 'def a:', -// /* 2*/ ' pass', -// /* 3*/ ' ', -// /* 4*/ ' def b:', -// /* 5*/ ' pass', -// /* 6*/ ' ', -// /* 7*/ ' ', -// /* 8*/ 'def c: # since there was a deintent here' -// ], [r(1, 5, 0), r(4, 5, 2)], true); -// }); + test('Fold Whitespace Python', () => { + assertRanges([ + /* 1*/ 'def a:', + /* 2*/ ' pass', + /* 3*/ ' ', + /* 4*/ ' def b:', + /* 5*/ ' pass', + /* 6*/ ' ', + /* 7*/ ' ', + /* 8*/ 'def c: # since there was a deintent here' + ], [r(1, 5, 0), r(4, 5, 2)], true); + }); -// test('Fold Tabs', () => { -// assertRanges([ -// /* 1*/ 'class A {', -// /* 2*/ '\t\t', -// /* 3*/ '\tvoid foo() {', -// /* 4*/ '\t \t//hello', -// /* 5*/ '\t return 0;', -// /* 6*/ ' \t}', -// /* 7*/ ' ', -// /* 8*/ '}', -// ], [r(1, 7, 0), r(3, 5, 4)], false); -// }); -// }); + test('Fold Tabs', () => { + assertRanges([ + /* 1*/ 'class A {', + /* 2*/ '\t\t', + /* 3*/ '\tvoid foo() {', + /* 4*/ '\t \t//hello', + /* 5*/ '\t return 0;', + /* 6*/ ' \t}', + /* 7*/ ' ', + /* 8*/ '}', + ], [r(1, 7, 0), r(3, 5, 4)], false); + }); +}); let markers: FoldingMarkers = { - start: /^\s*#region/, - end: /^\s*#endregion/ + start: /^\s*#region\b/, + end: /^\s*#endregion\b/ }; suite('Folding with regions', () => { @@ -216,9 +216,9 @@ suite('Folding with regions', () => { /* 2*/ '#region', /* 3*/ ' // comment', /* 4*/ '}', - ], [], false, markers); + ], [r(2, 3, 0)], false, markers); }); - test('Incomplete Regions', () => { + test('Incomplete Regions 2', () => { assertRanges([ /* 1*/ '', /* 2*/ '#region', @@ -291,4 +291,29 @@ suite('Folding with regions', () => { /* 8*/ '', ], [r(1, 7, 0, true), r(3, 5, 0, true)], true, markers); }); + test('Issue 35981', () => { + assertRanges([ + /* 1*/ 'function thisFoldsToEndOfPage() {', + /* 2*/ ' const variable = []', + /* 3*/ ' // #region', + /* 4*/ ' .reduce((a, b) => a,[]);', + /* 5*/ '}', + /* 6*/ '', + /* 7*/ 'function thisFoldsProperly() {', + /* 8*/ ' const foo = "bar"', + /* 9*/ '}', + ], [r(1, 4, 0), r(2, 4, 2), r(7, 8, 0)], false, markers); + }); + test('Misspelled Markers', () => { + assertRanges([ + /* 1*/ '#Region', + /* 2*/ '#endregion', + /* 3*/ '#regionsandmore', + /* 4*/ '#endregion', + /* 5*/ '#region', + /* 6*/ '#end region', + /* 7*/ '#region', + /* 8*/ '#endregionff', + ], [], true, markers); + }); }); \ No newline at end of file