bracketSelections.js 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  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. var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
  6. function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
  7. return new (P || (P = Promise))(function (resolve, reject) {
  8. function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
  9. function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
  10. function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
  11. step((generator = generator.apply(thisArg, _arguments || [])).next());
  12. });
  13. };
  14. import { LinkedList } from '../../../base/common/linkedList.js';
  15. import { Position } from '../../common/core/position.js';
  16. import { Range } from '../../common/core/range.js';
  17. export class BracketSelectionRangeProvider {
  18. provideSelectionRanges(model, positions) {
  19. return __awaiter(this, void 0, void 0, function* () {
  20. const result = [];
  21. for (const position of positions) {
  22. const bucket = [];
  23. result.push(bucket);
  24. const ranges = new Map();
  25. yield new Promise(resolve => BracketSelectionRangeProvider._bracketsRightYield(resolve, 0, model, position, ranges));
  26. yield new Promise(resolve => BracketSelectionRangeProvider._bracketsLeftYield(resolve, 0, model, position, ranges, bucket));
  27. }
  28. return result;
  29. });
  30. }
  31. static _bracketsRightYield(resolve, round, model, pos, ranges) {
  32. const counts = new Map();
  33. const t1 = Date.now();
  34. while (true) {
  35. if (round >= BracketSelectionRangeProvider._maxRounds) {
  36. resolve();
  37. break;
  38. }
  39. if (!pos) {
  40. resolve();
  41. break;
  42. }
  43. let bracket = model.bracketPairs.findNextBracket(pos);
  44. if (!bracket) {
  45. resolve();
  46. break;
  47. }
  48. let d = Date.now() - t1;
  49. if (d > BracketSelectionRangeProvider._maxDuration) {
  50. setTimeout(() => BracketSelectionRangeProvider._bracketsRightYield(resolve, round + 1, model, pos, ranges));
  51. break;
  52. }
  53. const key = bracket.close[0];
  54. if (bracket.isOpen) {
  55. // wait for closing
  56. let val = counts.has(key) ? counts.get(key) : 0;
  57. counts.set(key, val + 1);
  58. }
  59. else {
  60. // process closing
  61. let val = counts.has(key) ? counts.get(key) : 0;
  62. val -= 1;
  63. counts.set(key, Math.max(0, val));
  64. if (val < 0) {
  65. let list = ranges.get(key);
  66. if (!list) {
  67. list = new LinkedList();
  68. ranges.set(key, list);
  69. }
  70. list.push(bracket.range);
  71. }
  72. }
  73. pos = bracket.range.getEndPosition();
  74. }
  75. }
  76. static _bracketsLeftYield(resolve, round, model, pos, ranges, bucket) {
  77. const counts = new Map();
  78. const t1 = Date.now();
  79. while (true) {
  80. if (round >= BracketSelectionRangeProvider._maxRounds && ranges.size === 0) {
  81. resolve();
  82. break;
  83. }
  84. if (!pos) {
  85. resolve();
  86. break;
  87. }
  88. let bracket = model.bracketPairs.findPrevBracket(pos);
  89. if (!bracket) {
  90. resolve();
  91. break;
  92. }
  93. let d = Date.now() - t1;
  94. if (d > BracketSelectionRangeProvider._maxDuration) {
  95. setTimeout(() => BracketSelectionRangeProvider._bracketsLeftYield(resolve, round + 1, model, pos, ranges, bucket));
  96. break;
  97. }
  98. const key = bracket.close[0];
  99. if (!bracket.isOpen) {
  100. // wait for opening
  101. let val = counts.has(key) ? counts.get(key) : 0;
  102. counts.set(key, val + 1);
  103. }
  104. else {
  105. // opening
  106. let val = counts.has(key) ? counts.get(key) : 0;
  107. val -= 1;
  108. counts.set(key, Math.max(0, val));
  109. if (val < 0) {
  110. let list = ranges.get(key);
  111. if (list) {
  112. let closing = list.shift();
  113. if (list.size === 0) {
  114. ranges.delete(key);
  115. }
  116. const innerBracket = Range.fromPositions(bracket.range.getEndPosition(), closing.getStartPosition());
  117. const outerBracket = Range.fromPositions(bracket.range.getStartPosition(), closing.getEndPosition());
  118. bucket.push({ range: innerBracket });
  119. bucket.push({ range: outerBracket });
  120. BracketSelectionRangeProvider._addBracketLeading(model, outerBracket, bucket);
  121. }
  122. }
  123. }
  124. pos = bracket.range.getStartPosition();
  125. }
  126. }
  127. static _addBracketLeading(model, bracket, bucket) {
  128. if (bracket.startLineNumber === bracket.endLineNumber) {
  129. return;
  130. }
  131. // xxxxxxxx {
  132. //
  133. // }
  134. const startLine = bracket.startLineNumber;
  135. const column = model.getLineFirstNonWhitespaceColumn(startLine);
  136. if (column !== 0 && column !== bracket.startColumn) {
  137. bucket.push({ range: Range.fromPositions(new Position(startLine, column), bracket.getEndPosition()) });
  138. bucket.push({ range: Range.fromPositions(new Position(startLine, 1), bracket.getEndPosition()) });
  139. }
  140. // xxxxxxxx
  141. // {
  142. //
  143. // }
  144. const aboveLine = startLine - 1;
  145. if (aboveLine > 0) {
  146. const column = model.getLineFirstNonWhitespaceColumn(aboveLine);
  147. if (column === bracket.startColumn && column !== model.getLineLastNonWhitespaceColumn(aboveLine)) {
  148. bucket.push({ range: Range.fromPositions(new Position(aboveLine, column), bracket.getEndPosition()) });
  149. bucket.push({ range: Range.fromPositions(new Position(aboveLine, 1), bracket.getEndPosition()) });
  150. }
  151. }
  152. }
  153. }
  154. BracketSelectionRangeProvider._maxDuration = 30;
  155. BracketSelectionRangeProvider._maxRounds = 2;