122 lines
5.1 KiB
JavaScript
122 lines
5.1 KiB
JavaScript
/*---------------------------------------------------------------------------------------------
|
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
|
*--------------------------------------------------------------------------------------------*/
|
|
import { createScanner } from 'jsonc-parser';
|
|
import { FoldingRangeKind, Position } from '../jsonLanguageTypes';
|
|
export function getFoldingRanges(document, context) {
|
|
var ranges = [];
|
|
var nestingLevels = [];
|
|
var stack = [];
|
|
var prevStart = -1;
|
|
var scanner = createScanner(document.getText(), false);
|
|
var token = scanner.scan();
|
|
function addRange(range) {
|
|
ranges.push(range);
|
|
nestingLevels.push(stack.length);
|
|
}
|
|
while (token !== 17 /* EOF */) {
|
|
switch (token) {
|
|
case 1 /* OpenBraceToken */:
|
|
case 3 /* OpenBracketToken */: {
|
|
var startLine = document.positionAt(scanner.getTokenOffset()).line;
|
|
var range = { startLine: startLine, endLine: startLine, kind: token === 1 /* OpenBraceToken */ ? 'object' : 'array' };
|
|
stack.push(range);
|
|
break;
|
|
}
|
|
case 2 /* CloseBraceToken */:
|
|
case 4 /* CloseBracketToken */: {
|
|
var kind = token === 2 /* CloseBraceToken */ ? 'object' : 'array';
|
|
if (stack.length > 0 && stack[stack.length - 1].kind === kind) {
|
|
var range = stack.pop();
|
|
var line = document.positionAt(scanner.getTokenOffset()).line;
|
|
if (range && line > range.startLine + 1 && prevStart !== range.startLine) {
|
|
range.endLine = line - 1;
|
|
addRange(range);
|
|
prevStart = range.startLine;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case 13 /* BlockCommentTrivia */: {
|
|
var startLine = document.positionAt(scanner.getTokenOffset()).line;
|
|
var endLine = document.positionAt(scanner.getTokenOffset() + scanner.getTokenLength()).line;
|
|
if (scanner.getTokenError() === 1 /* UnexpectedEndOfComment */ && startLine + 1 < document.lineCount) {
|
|
scanner.setPosition(document.offsetAt(Position.create(startLine + 1, 0)));
|
|
}
|
|
else {
|
|
if (startLine < endLine) {
|
|
addRange({ startLine: startLine, endLine: endLine, kind: FoldingRangeKind.Comment });
|
|
prevStart = startLine;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case 12 /* LineCommentTrivia */: {
|
|
var text = document.getText().substr(scanner.getTokenOffset(), scanner.getTokenLength());
|
|
var m = text.match(/^\/\/\s*#(region\b)|(endregion\b)/);
|
|
if (m) {
|
|
var line = document.positionAt(scanner.getTokenOffset()).line;
|
|
if (m[1]) { // start pattern match
|
|
var range = { startLine: line, endLine: line, kind: FoldingRangeKind.Region };
|
|
stack.push(range);
|
|
}
|
|
else {
|
|
var i = stack.length - 1;
|
|
while (i >= 0 && stack[i].kind !== FoldingRangeKind.Region) {
|
|
i--;
|
|
}
|
|
if (i >= 0) {
|
|
var range = stack[i];
|
|
stack.length = i;
|
|
if (line > range.startLine && prevStart !== range.startLine) {
|
|
range.endLine = line;
|
|
addRange(range);
|
|
prevStart = range.startLine;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
token = scanner.scan();
|
|
}
|
|
var rangeLimit = context && context.rangeLimit;
|
|
if (typeof rangeLimit !== 'number' || ranges.length <= rangeLimit) {
|
|
return ranges;
|
|
}
|
|
if (context && context.onRangeLimitExceeded) {
|
|
context.onRangeLimitExceeded(document.uri);
|
|
}
|
|
var counts = [];
|
|
for (var _i = 0, nestingLevels_1 = nestingLevels; _i < nestingLevels_1.length; _i++) {
|
|
var level = nestingLevels_1[_i];
|
|
if (level < 30) {
|
|
counts[level] = (counts[level] || 0) + 1;
|
|
}
|
|
}
|
|
var entries = 0;
|
|
var maxLevel = 0;
|
|
for (var i = 0; i < counts.length; i++) {
|
|
var n = counts[i];
|
|
if (n) {
|
|
if (n + entries > rangeLimit) {
|
|
maxLevel = i;
|
|
break;
|
|
}
|
|
entries += n;
|
|
}
|
|
}
|
|
var result = [];
|
|
for (var i = 0; i < ranges.length; i++) {
|
|
var level = nestingLevels[i];
|
|
if (typeof level === 'number') {
|
|
if (level < maxLevel || (level === maxLevel && entries++ < rangeLimit)) {
|
|
result.push(ranges[i]);
|
|
}
|
|
}
|
|
}
|
|
return result;
|
|
}
|