jsonFolding.js 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. /*---------------------------------------------------------------------------------------------
  2. * Copyright (c) Microsoft Corporation. All rights reserved.
  3. * Licensed under the MIT License. See License.txt in the project root for license information.
  4. *--------------------------------------------------------------------------------------------*/
  5. import { createScanner } from 'jsonc-parser';
  6. import { FoldingRangeKind, Position } from '../jsonLanguageTypes';
  7. export function getFoldingRanges(document, context) {
  8. var ranges = [];
  9. var nestingLevels = [];
  10. var stack = [];
  11. var prevStart = -1;
  12. var scanner = createScanner(document.getText(), false);
  13. var token = scanner.scan();
  14. function addRange(range) {
  15. ranges.push(range);
  16. nestingLevels.push(stack.length);
  17. }
  18. while (token !== 17 /* EOF */) {
  19. switch (token) {
  20. case 1 /* OpenBraceToken */:
  21. case 3 /* OpenBracketToken */: {
  22. var startLine = document.positionAt(scanner.getTokenOffset()).line;
  23. var range = { startLine: startLine, endLine: startLine, kind: token === 1 /* OpenBraceToken */ ? 'object' : 'array' };
  24. stack.push(range);
  25. break;
  26. }
  27. case 2 /* CloseBraceToken */:
  28. case 4 /* CloseBracketToken */: {
  29. var kind = token === 2 /* CloseBraceToken */ ? 'object' : 'array';
  30. if (stack.length > 0 && stack[stack.length - 1].kind === kind) {
  31. var range = stack.pop();
  32. var line = document.positionAt(scanner.getTokenOffset()).line;
  33. if (range && line > range.startLine + 1 && prevStart !== range.startLine) {
  34. range.endLine = line - 1;
  35. addRange(range);
  36. prevStart = range.startLine;
  37. }
  38. }
  39. break;
  40. }
  41. case 13 /* BlockCommentTrivia */: {
  42. var startLine = document.positionAt(scanner.getTokenOffset()).line;
  43. var endLine = document.positionAt(scanner.getTokenOffset() + scanner.getTokenLength()).line;
  44. if (scanner.getTokenError() === 1 /* UnexpectedEndOfComment */ && startLine + 1 < document.lineCount) {
  45. scanner.setPosition(document.offsetAt(Position.create(startLine + 1, 0)));
  46. }
  47. else {
  48. if (startLine < endLine) {
  49. addRange({ startLine: startLine, endLine: endLine, kind: FoldingRangeKind.Comment });
  50. prevStart = startLine;
  51. }
  52. }
  53. break;
  54. }
  55. case 12 /* LineCommentTrivia */: {
  56. var text = document.getText().substr(scanner.getTokenOffset(), scanner.getTokenLength());
  57. var m = text.match(/^\/\/\s*#(region\b)|(endregion\b)/);
  58. if (m) {
  59. var line = document.positionAt(scanner.getTokenOffset()).line;
  60. if (m[1]) { // start pattern match
  61. var range = { startLine: line, endLine: line, kind: FoldingRangeKind.Region };
  62. stack.push(range);
  63. }
  64. else {
  65. var i = stack.length - 1;
  66. while (i >= 0 && stack[i].kind !== FoldingRangeKind.Region) {
  67. i--;
  68. }
  69. if (i >= 0) {
  70. var range = stack[i];
  71. stack.length = i;
  72. if (line > range.startLine && prevStart !== range.startLine) {
  73. range.endLine = line;
  74. addRange(range);
  75. prevStart = range.startLine;
  76. }
  77. }
  78. }
  79. }
  80. break;
  81. }
  82. }
  83. token = scanner.scan();
  84. }
  85. var rangeLimit = context && context.rangeLimit;
  86. if (typeof rangeLimit !== 'number' || ranges.length <= rangeLimit) {
  87. return ranges;
  88. }
  89. if (context && context.onRangeLimitExceeded) {
  90. context.onRangeLimitExceeded(document.uri);
  91. }
  92. var counts = [];
  93. for (var _i = 0, nestingLevels_1 = nestingLevels; _i < nestingLevels_1.length; _i++) {
  94. var level = nestingLevels_1[_i];
  95. if (level < 30) {
  96. counts[level] = (counts[level] || 0) + 1;
  97. }
  98. }
  99. var entries = 0;
  100. var maxLevel = 0;
  101. for (var i = 0; i < counts.length; i++) {
  102. var n = counts[i];
  103. if (n) {
  104. if (n + entries > rangeLimit) {
  105. maxLevel = i;
  106. break;
  107. }
  108. entries += n;
  109. }
  110. }
  111. var result = [];
  112. for (var i = 0; i < ranges.length; i++) {
  113. var level = nestingLevels[i];
  114. if (typeof level === 'number') {
  115. if (level < maxLevel || (level === maxLevel && entries++ < rangeLimit)) {
  116. result.push(ranges[i]);
  117. }
  118. }
  119. }
  120. return result;
  121. }