Add support for custom outlining regions

This commit is contained in:
uniqueiniquity 2017-08-08 09:50:07 -07:00
parent 2b28916e5e
commit 9726ba1198
2 changed files with 73 additions and 0 deletions

View File

@ -2037,6 +2037,10 @@ namespace ts {
end: -1;
}
export interface RegionRange extends TextRange {
name?: string;
}
// represents a top level: { type } expression in a JSDoc comment.
export interface JSDocTypeExpression extends TypeNode {
kind: SyntaxKind.JSDocTypeExpression;

View File

@ -6,6 +6,10 @@ namespace ts.OutliningElementsCollector {
export function collectElements(sourceFile: SourceFile, cancellationToken: CancellationToken): OutliningSpan[] {
const elements: OutliningSpan[] = [];
let depth = 0;
const regions: RegionRange[] = [];
const regionText = "#region";
const regionStart = new RegExp("// #region( .+| *)", "g");
const regionEnd = new RegExp("// #endregion *");
walk(sourceFile);
return elements;
@ -35,6 +39,18 @@ namespace ts.OutliningElementsCollector {
}
}
function addOutliningSpanRegions(regionSpan: RegionRange) {
if (regionSpan) {
const span: OutliningSpan = {
textSpan: createTextSpanFromBounds(regionSpan.pos, regionSpan.end),
hintSpan: createTextSpanFromBounds(regionSpan.pos, regionSpan.end),
bannerText: regionSpan.name,
autoCollapse: false,
};
elements.push(span);
}
}
function addOutliningForLeadingCommentsForNode(n: Node) {
const comments = ts.getLeadingCommentRangesOfNode(n, sourceFile);
@ -89,12 +105,65 @@ namespace ts.OutliningElementsCollector {
return isFunctionBlock(node) && node.parent.kind !== SyntaxKind.ArrowFunction;
}
function isRegionStart(range: CommentRange) {
const comment = sourceFile.text.substring(range.pos, range.end);
const result = comment.match(regionStart);
if (result && result.length > 0) {
const name = result[0].substring(10).trim();
if (name) {
return name;
}
else {
return regionText;
}
}
return "";
}
function isRegionEnd(range: CommentRange) {
const comment = sourceFile.text.substring(range.pos, range.end);
return comment.match(regionEnd);
}
function addRegionsNearNode(n: Node) {
const comments = ts.getLeadingCommentRangesOfNode(n, sourceFile);
if (n.kind !== SyntaxKind.SourceFile && comments) {
for (const currentComment of comments) {
cancellationToken.throwIfCancellationRequested();
if (currentComment.kind === SyntaxKind.SingleLineCommentTrivia) {
const name = isRegionStart(currentComment);
if (name) {
const region: RegionRange = {
pos: currentComment.pos,
end: currentComment.end,
name,
};
regions.push(region);
}
else if (isRegionEnd(currentComment)) {
const region = regions.pop();
if (region) {
region.end = currentComment.end;
addOutliningSpanRegions(region);
}
}
}
}
}
}
function walk(n: Node): void {
cancellationToken.throwIfCancellationRequested();
if (depth > maxDepth) {
return;
}
addRegionsNearNode(n);
if (isDeclaration(n)) {
addOutliningForLeadingCommentsForNode(n);
}