Skip to content

Commit 51501e0

Browse files
committed
(GH-1514) Show the last line of folding regions as per default VSCode
Previously the code folding provider would hide the last line of the region, however the default VS Code code folding behaviour is to instead hide from the beginning to end minus one, lines. This commit; * Adds a configuration parameter to show/hide the last line in a region, defaulting to Show the last line * Modifies conversion method for the internal region class to FoldingRange object to show/hide the last line based on the extension settings * Modifies the tests for the default value and adds tests for the show and hide scenarios This code is based on a solution created by; ens-rpitcher <[email protected]>
1 parent 78f2bb3 commit 51501e0

File tree

4 files changed

+68
-21
lines changed

4 files changed

+68
-21
lines changed

package.json

+5
Original file line numberDiff line numberDiff line change
@@ -478,6 +478,11 @@
478478
"default": true,
479479
"description": "Enables syntax based code folding. When disabled, the default indentation based code folding is used."
480480
},
481+
"powershell.codeFolding.showLastLine": {
482+
"type": "boolean",
483+
"default": true,
484+
"description": "Shows the last line of a folded section similar to the default VSCode folding style. When disabled, the entire folded region is hidden."
485+
},
481486
"powershell.codeFormatting.preset": {
482487
"type": "string",
483488
"enum": [

src/features/Folding.ts

+13-3
Original file line numberDiff line numberDiff line change
@@ -157,8 +157,12 @@ class LineNumberRange {
157157
* Creates a vscode.FoldingRange object based on this object
158158
* @returns A Folding Range object for use with the Folding Provider
159159
*/
160-
public toFoldingRange(): vscode.FoldingRange {
161-
return new vscode.FoldingRange(this.startline, this.endline, this.rangeKind);
160+
public toFoldingRange(settings: Settings.ISettings): vscode.FoldingRange {
161+
if (settings.codeFolding && settings.codeFolding.showLastLine) {
162+
return new vscode.FoldingRange(this.startline, this.endline - 1, this.rangeKind);
163+
} else {
164+
return new vscode.FoldingRange(this.startline, this.endline, this.rangeKind);
165+
}
162166
}
163167
}
164168

@@ -252,15 +256,21 @@ export class FoldingProvider implements vscode.FoldingRangeProvider {
252256
return 0;
253257
});
254258

259+
const settings = this.currentSettings();
255260
return foldableRegions
256261
// It's possible to have duplicate or overlapping ranges, that is, regions which have the same starting
257262
// line number as the previous region. Therefore only emit ranges which have a different starting line
258263
// than the previous range.
259264
.filter((item, index, src) => index === 0 || item.startline !== src[index - 1].startline)
260265
// Convert the internal representation into the VSCode expected type
261-
.map((item) => item.toFoldingRange());
266+
.map((item) => item.toFoldingRange(settings));
262267
}
263268

269+
/**
270+
* A helper to return the current extension settings
271+
*/
272+
public currentSettings(): Settings.ISettings { return Settings.load(); }
273+
264274
/**
265275
* Given a start and end textmate scope name, find matching grammar tokens
266276
* and pair them together. Uses a simple stack to take into account nested regions.

src/settings.ts

+2
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ export interface IBugReportingSettings {
3131

3232
export interface ICodeFoldingSettings {
3333
enable?: boolean;
34+
showLastLine?: boolean;
3435
}
3536

3637
export interface ICodeFormattingSettings {
@@ -116,6 +117,7 @@ export function load(): ISettings {
116117

117118
const defaultCodeFoldingSettings: ICodeFoldingSettings = {
118119
enable: true,
120+
showLastLine: false,
119121
};
120122

121123
const defaultCodeFormattingSettings: ICodeFormattingSettings = {

test/features/folding.test.ts

+48-18
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import * as path from "path";
77
import * as vscode from "vscode";
88
import { DocumentSelector } from "vscode-languageclient";
99
import * as folding from "../../src/features/Folding";
10+
import * as Settings from "../../src/settings";
1011
import { MockLogger } from "../test_utils";
1112

1213
const fixturePath = path.join(__dirname, "..", "..", "..", "test", "fixtures");
@@ -22,6 +23,13 @@ function assertFoldingRegions(result, expected): void {
2223
assert.equal(result.length, expected.length);
2324
}
2425

26+
// Wrap the FoldingProvider class with our own custom settings for testing
27+
class CustomSettingFoldingProvider extends folding.FoldingProvider {
28+
public customSettings: Settings.ISettings = Settings.load();
29+
// Overridde the super currentSettings method with our own custom test settings
30+
public currentSettings(): Settings.ISettings { return this.customSettings; }
31+
}
32+
2533
suite("Features", () => {
2634

2735
suite("Folding Provider", async () => {
@@ -38,21 +46,21 @@ suite("Features", () => {
3846

3947
suite("For a single document", async () => {
4048
const expectedFoldingRegions = [
41-
{ start: 0, end: 4, kind: 3 },
42-
{ start: 1, end: 3, kind: 1 },
43-
{ start: 10, end: 15, kind: 1 },
44-
{ start: 16, end: 60, kind: null },
45-
{ start: 17, end: 22, kind: 1 },
46-
{ start: 23, end: 26, kind: null },
47-
{ start: 28, end: 31, kind: null },
48-
{ start: 35, end: 37, kind: 1 },
49-
{ start: 39, end: 49, kind: 3 },
50-
{ start: 41, end: 45, kind: 3 },
51-
{ start: 51, end: 53, kind: null },
52-
{ start: 56, end: 59, kind: null },
53-
{ start: 64, end: 66, kind: 1 },
54-
{ start: 67, end: 72, kind: 3 },
55-
{ start: 68, end: 70, kind: 1 },
49+
{ start: 0, end: 3, kind: 3 },
50+
{ start: 1, end: 2, kind: 1 },
51+
{ start: 10, end: 14, kind: 1 },
52+
{ start: 16, end: 59, kind: null },
53+
{ start: 17, end: 21, kind: 1 },
54+
{ start: 23, end: 25, kind: null },
55+
{ start: 28, end: 30, kind: null },
56+
{ start: 35, end: 36, kind: 1 },
57+
{ start: 39, end: 48, kind: 3 },
58+
{ start: 41, end: 44, kind: 3 },
59+
{ start: 51, end: 52, kind: null },
60+
{ start: 56, end: 58, kind: null },
61+
{ start: 64, end: 65, kind: 1 },
62+
{ start: 67, end: 71, kind: 3 },
63+
{ start: 68, end: 69, kind: 1 },
5664
];
5765

5866
test("Can detect all of the foldable regions in a document with CRLF line endings", async () => {
@@ -83,9 +91,31 @@ suite("Features", () => {
8391
assertFoldingRegions(result, expectedFoldingRegions);
8492
});
8593

94+
suite("Where showLastLine setting is false", async () => {
95+
const customprovider = (new CustomSettingFoldingProvider(psGrammar));
96+
customprovider.customSettings.codeFolding.showLastLine = false;
97+
98+
test("Can detect all foldable regions in a document", async () => {
99+
// Integration test against the test fixture 'folding-lf.ps1' that contains
100+
// all of the different types of folding available
101+
const uri = vscode.Uri.file(path.join(fixturePath, "folding-lf.ps1"));
102+
const document = await vscode.workspace.openTextDocument(uri);
103+
const result = await customprovider.provideFoldingRanges(document, null, null);
104+
105+
// Incrememnt the end line of the expected regions by one as we will
106+
// be hiding the last line
107+
const expectedLastLineRegions = expectedFoldingRegions.map( (item) => {
108+
item.end++;
109+
return item;
110+
});
111+
112+
assertFoldingRegions(result, expectedLastLineRegions);
113+
});
114+
});
115+
86116
test("Can detect all of the foldable regions in a document with mismatched regions", async () => {
87117
const expectedMismatchedFoldingRegions = [
88-
{ start: 2, end: 4, kind: 3 },
118+
{ start: 2, end: 3, kind: 3 },
89119
];
90120

91121
// Integration test against the test fixture 'folding-mismatch.ps1' that contains
@@ -99,8 +129,8 @@ suite("Features", () => {
99129

100130
test("Does not return duplicate or overlapping regions", async () => {
101131
const expectedMismatchedFoldingRegions = [
102-
{ start: 1, end: 2, kind: null },
103-
{ start: 2, end: 4, kind: null },
132+
{ start: 1, end: 1, kind: null },
133+
{ start: 2, end: 3, kind: null },
104134
];
105135

106136
// Integration test against the test fixture 'folding-mismatch.ps1' that contains

0 commit comments

Comments
 (0)