Skip to content

Commit 83f2401

Browse files
Merge pull request #17954 from uniqueiniquity/regions
Add support for custom outlining regions
2 parents 088da79 + e5c43cd commit 83f2401

File tree

4 files changed

+110
-1
lines changed

4 files changed

+110
-1
lines changed

src/services/outliningElementsCollector.ts

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,17 @@
22
namespace ts.OutliningElementsCollector {
33
const collapseText = "...";
44
const maxDepth = 20;
5+
const defaultLabel = "#region";
6+
const regionMatch = new RegExp("^\\s*//\\s*#(end)?region(?:\\s+(.*))?$");
57

68
export function collectElements(sourceFile: SourceFile, cancellationToken: CancellationToken): OutliningSpan[] {
79
const elements: OutliningSpan[] = [];
810
let depth = 0;
11+
const regions: OutliningSpan[] = [];
912

1013
walk(sourceFile);
11-
return elements;
14+
gatherRegions();
15+
return elements.sort((span1, span2) => span1.textSpan.start - span2.textSpan.start);
1216

1317
/** If useFullStart is true, then the collapsing span includes leading whitespace, including linebreaks. */
1418
function addOutliningSpan(hintSpanNode: Node, startElement: Node, endElement: Node, autoCollapse: boolean, useFullStart: boolean) {
@@ -89,6 +93,39 @@ namespace ts.OutliningElementsCollector {
8993
return isFunctionBlock(node) && node.parent.kind !== SyntaxKind.ArrowFunction;
9094
}
9195

96+
function gatherRegions(): void {
97+
const lineStarts = sourceFile.getLineStarts();
98+
99+
for (let i = 0; i < lineStarts.length; i++) {
100+
const currentLineStart = lineStarts[i];
101+
const lineEnd = lineStarts[i + 1] - 1 || sourceFile.getEnd();
102+
const comment = sourceFile.text.substring(currentLineStart, lineEnd);
103+
const result = comment.match(regionMatch);
104+
105+
if (result && !isInComment(sourceFile, currentLineStart)) {
106+
if (!result[1]) {
107+
const start = sourceFile.getFullText().indexOf("//", currentLineStart);
108+
const textSpan = createTextSpanFromBounds(start, lineEnd);
109+
const region: OutliningSpan = {
110+
textSpan,
111+
hintSpan: textSpan,
112+
bannerText: result[2] || defaultLabel,
113+
autoCollapse: false
114+
};
115+
regions.push(region);
116+
}
117+
else {
118+
const region = regions.pop();
119+
if (region) {
120+
region.textSpan.length = lineEnd - region.textSpan.start;
121+
region.hintSpan.length = lineEnd - region.textSpan.start;
122+
elements.push(region);
123+
}
124+
}
125+
}
126+
}
127+
}
128+
92129
function walk(n: Node): void {
93130
cancellationToken.throwIfCancellationRequested();
94131
if (depth > maxDepth) {
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/// <reference path="fourslash.ts"/>
2+
3+
////// region without label
4+
////[|// #region
5+
////
6+
////// #endregion|]
7+
////
8+
////// region without label with trailing spaces
9+
////[|// #region
10+
////
11+
////// #endregion|]
12+
////
13+
////// region with label
14+
////[|// #region label1
15+
////
16+
////// #endregion|]
17+
////
18+
////// region with extra whitespace in all valid locations
19+
//// [|// #region label2 label3
20+
////
21+
//// // #endregion|]
22+
////
23+
////// No space before directive
24+
////[|//#region label4
25+
////
26+
//////#endregion|]
27+
////
28+
////// Nested regions
29+
////[|// #region outer
30+
////
31+
////[|// #region inner
32+
////
33+
////// #endregion inner|]
34+
////
35+
////// #endregion outer|]
36+
////
37+
////// region delimiters not valid when there is preceding text on line
38+
//// test // #region invalid1
39+
////
40+
////test // #endregion
41+
////
42+
////// region delimiters not valid when in multiline comment
43+
/////*
44+
////// #region invalid2
45+
////*/
46+
////
47+
/////*
48+
////// #endregion
49+
////*/
50+
51+
verify.outliningSpansInCurrentFile(test.ranges());
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
/// <reference path="fourslash.ts"/>
2+
3+
////// bottom-heavy region balance
4+
////[|// #region matched
5+
////
6+
////// #endregion matched|]
7+
////
8+
////// #endregion unmatched
9+
10+
verify.outliningSpansInCurrentFile(test.ranges());
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/// <reference path="fourslash.ts"/>
2+
3+
////// top-heavy region balance
4+
////// #region unmatched
5+
////
6+
////[|// #region matched
7+
////
8+
////// #endregion matched|]
9+
10+
debugger;
11+
verify.outliningSpansInCurrentFile(test.ranges());

0 commit comments

Comments
 (0)