Skip to content

Commit

Permalink
Merge pull request #17954 from uniqueiniquity/regions
Browse files Browse the repository at this point in the history
Add support for custom outlining regions
  • Loading branch information
uniqueiniquity authored Sep 16, 2017
2 parents 088da79 + e5c43cd commit 83f2401
Show file tree
Hide file tree
Showing 4 changed files with 110 additions and 1 deletion.
39 changes: 38 additions & 1 deletion src/services/outliningElementsCollector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,17 @@
namespace ts.OutliningElementsCollector {
const collapseText = "...";
const maxDepth = 20;
const defaultLabel = "#region";
const regionMatch = new RegExp("^\\s*//\\s*#(end)?region(?:\\s+(.*))?$");

export function collectElements(sourceFile: SourceFile, cancellationToken: CancellationToken): OutliningSpan[] {
const elements: OutliningSpan[] = [];
let depth = 0;
const regions: OutliningSpan[] = [];

walk(sourceFile);
return elements;
gatherRegions();
return elements.sort((span1, span2) => span1.textSpan.start - span2.textSpan.start);

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

function gatherRegions(): void {
const lineStarts = sourceFile.getLineStarts();

for (let i = 0; i < lineStarts.length; i++) {
const currentLineStart = lineStarts[i];
const lineEnd = lineStarts[i + 1] - 1 || sourceFile.getEnd();
const comment = sourceFile.text.substring(currentLineStart, lineEnd);
const result = comment.match(regionMatch);

if (result && !isInComment(sourceFile, currentLineStart)) {
if (!result[1]) {
const start = sourceFile.getFullText().indexOf("//", currentLineStart);
const textSpan = createTextSpanFromBounds(start, lineEnd);
const region: OutliningSpan = {
textSpan,
hintSpan: textSpan,
bannerText: result[2] || defaultLabel,
autoCollapse: false
};
regions.push(region);
}
else {
const region = regions.pop();
if (region) {
region.textSpan.length = lineEnd - region.textSpan.start;
region.hintSpan.length = lineEnd - region.textSpan.start;
elements.push(region);
}
}
}
}
}

function walk(n: Node): void {
cancellationToken.throwIfCancellationRequested();
if (depth > maxDepth) {
Expand Down
51 changes: 51 additions & 0 deletions tests/cases/fourslash/getOutliningSpansForRegions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/// <reference path="fourslash.ts"/>

////// region without label
////[|// #region
////
////// #endregion|]
////
////// region without label with trailing spaces
////[|// #region
////
////// #endregion|]
////
////// region with label
////[|// #region label1
////
////// #endregion|]
////
////// region with extra whitespace in all valid locations
//// [|// #region label2 label3
////
//// // #endregion|]
////
////// No space before directive
////[|//#region label4
////
//////#endregion|]
////
////// Nested regions
////[|// #region outer
////
////[|// #region inner
////
////// #endregion inner|]
////
////// #endregion outer|]
////
////// region delimiters not valid when there is preceding text on line
//// test // #region invalid1
////
////test // #endregion
////
////// region delimiters not valid when in multiline comment
/////*
////// #region invalid2
////*/
////
/////*
////// #endregion
////*/

verify.outliningSpansInCurrentFile(test.ranges());
10 changes: 10 additions & 0 deletions tests/cases/fourslash/getOutliningSpansForUnbalancedEndRegion.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/// <reference path="fourslash.ts"/>

////// bottom-heavy region balance
////[|// #region matched
////
////// #endregion matched|]
////
////// #endregion unmatched

verify.outliningSpansInCurrentFile(test.ranges());
11 changes: 11 additions & 0 deletions tests/cases/fourslash/getOutliningSpansForUnbalancedRegion.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/// <reference path="fourslash.ts"/>

////// top-heavy region balance
////// #region unmatched
////
////[|// #region matched
////
////// #endregion matched|]

debugger;
verify.outliningSpansInCurrentFile(test.ranges());

0 comments on commit 83f2401

Please sign in to comment.